--- /dev/null
+From c22ca5c1c175a73972fc0d5d3829041004ad95cb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 27 Apr 2025 15:41:51 -0400
+Subject: __legitimize_mnt(): check for MNT_SYNC_UMOUNT should be under
+ mount_lock
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+[ Upstream commit 250cf3693060a5f803c5f1ddc082bb06b16112a9 ]
+
+... or we risk stealing final mntput from sync umount - raising mnt_count
+after umount(2) has verified that victim is not busy, but before it
+has set MNT_SYNC_UMOUNT; in that case __legitimize_mnt() doesn't see
+that it's safe to quietly undo mnt_count increment and leaves dropping
+the reference to caller, where it'll be a full-blown mntput().
+
+Check under mount_lock is needed; leaving the current one done before
+taking that makes no sense - it's nowhere near common enough to bother
+with.
+
+Reviewed-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/namespace.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/fs/namespace.c b/fs/namespace.c
+index c3c1e8c644f2e..c1ac585e41e36 100644
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -750,12 +750,8 @@ int __legitimize_mnt(struct vfsmount *bastard, unsigned seq)
+ smp_mb(); // see mntput_no_expire() and do_umount()
+ if (likely(!read_seqretry(&mount_lock, seq)))
+ return 0;
+- if (bastard->mnt_flags & MNT_SYNC_UMOUNT) {
+- mnt_add_count(mnt, -1);
+- return 1;
+- }
+ lock_mount_hash();
+- if (unlikely(bastard->mnt_flags & MNT_DOOMED)) {
++ if (unlikely(bastard->mnt_flags & (MNT_SYNC_UMOUNT | MNT_DOOMED))) {
+ mnt_add_count(mnt, -1);
+ unlock_mount_hash();
+ return 1;
+--
+2.39.5
+
--- /dev/null
+From a8af08d06f15bbb170b2cec6c095584dfd414da7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Jan 2025 10:09:41 -0700
+Subject: accel/qaic: Mask out SR-IOV PCI resources
+
+From: Youssef Samir <quic_yabdulra@quicinc.com>
+
+[ Upstream commit 8685520474bfc0fe4be83c3cbfe3fb3e1ca1514a ]
+
+During the initialization of the qaic device, pci_select_bars() is
+used to fetch a bitmask of the BARs exposed by the device. On devices
+that have Virtual Functions capabilities, the bitmask includes SR-IOV
+BARs.
+
+Use a mask to filter out SR-IOV BARs if they exist.
+
+Signed-off-by: Youssef Samir <quic_yabdulra@quicinc.com>
+Reviewed-by: Jeffrey Hugo <quic_jhugo@quicinc.com>
+Signed-off-by: Jeffrey Hugo <quic_jhugo@quicinc.com>
+Reviewed-by: Lizhi Hou <lizhi.hou@amd.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250117170943.2643280-6-quic_jhugo@quicinc.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/accel/qaic/qaic_drv.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/accel/qaic/qaic_drv.c b/drivers/accel/qaic/qaic_drv.c
+index f139c564eadf9..10e711c96a670 100644
+--- a/drivers/accel/qaic/qaic_drv.c
++++ b/drivers/accel/qaic/qaic_drv.c
+@@ -432,7 +432,7 @@ static int init_pci(struct qaic_device *qdev, struct pci_dev *pdev)
+ int bars;
+ int ret;
+
+- bars = pci_select_bars(pdev, IORESOURCE_MEM);
++ bars = pci_select_bars(pdev, IORESOURCE_MEM) & 0x3f;
+
+ /* make sure the device has the expected BARs */
+ if (bars != (BIT(0) | BIT(2) | BIT(4))) {
+--
+2.39.5
+
--- /dev/null
+From 1faf97e59e93674e451ac5f07225be41a50453ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Feb 2025 14:34:08 +0800
+Subject: ACPI: HED: Always initialize before evged
+
+From: Xiaofei Tan <tanxiaofei@huawei.com>
+
+[ Upstream commit cccf6ee090c8c133072d5d5b52ae25f3bc907a16 ]
+
+When the HED driver is built-in, it initializes after evged because they
+both are at the same initcall level, so the initialization ordering
+depends on the Makefile order. However, this prevents RAS records
+coming in between the evged driver initialization and the HED driver
+initialization from being handled.
+
+If the number of such RAS records is above the APEI HEST error source
+number, the HEST resources may be exhausted, and that may affect
+subsequent RAS error reporting.
+
+To fix this issue, change the initcall level of HED to subsys_initcall
+and prevent the driver from being built as a module by changing ACPI_HED
+in Kconfig from "tristate" to "bool".
+
+Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
+Link: https://patch.msgid.link/20250212063408.927666-1-tanxiaofei@huawei.com
+[ rjw: Changelog edits ]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/Kconfig | 2 +-
+ drivers/acpi/hed.c | 7 ++++++-
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
+index d67f63d93b2ab..89fa569d63702 100644
+--- a/drivers/acpi/Kconfig
++++ b/drivers/acpi/Kconfig
+@@ -443,7 +443,7 @@ config ACPI_SBS
+ the modules will be called sbs and sbshc.
+
+ config ACPI_HED
+- tristate "Hardware Error Device"
++ bool "Hardware Error Device"
+ help
+ This driver supports the Hardware Error Device (PNP0C33),
+ which is used to report some hardware errors notified via
+diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c
+index 7652515a6be1e..3499f86c411e3 100644
+--- a/drivers/acpi/hed.c
++++ b/drivers/acpi/hed.c
+@@ -80,7 +80,12 @@ static struct acpi_driver acpi_hed_driver = {
+ .remove = acpi_hed_remove,
+ },
+ };
+-module_acpi_driver(acpi_hed_driver);
++
++static int __init acpi_hed_driver_init(void)
++{
++ return acpi_bus_register_driver(&acpi_hed_driver);
++}
++subsys_initcall(acpi_hed_driver_init);
+
+ MODULE_AUTHOR("Huang Ying");
+ MODULE_DESCRIPTION("ACPI Hardware Error Device Driver");
+--
+2.39.5
+
--- /dev/null
+From 0c9eaa40708f780c7ecd4058b50ba6a4faa16a99 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Mar 2025 10:55:07 +0000
+Subject: ACPI: PNP: Add Intel OC Watchdog IDs to non-PNP device list
+
+From: Diogo Ivo <diogo.ivo@siemens.com>
+
+[ Upstream commit f06777cf2bbc21dd8c71d6e3906934e56b4e18e4 ]
+
+Intel Over-Clocking Watchdogs are described in ACPI tables by both the
+generic PNP0C02 _CID and their ACPI _HID. The presence of the _CID then
+causes the PNP scan handler to attach to the watchdog, preventing the
+actual watchdog driver from binding. Address this by adding the ACPI
+_HIDs to the list of non-PNP devices, so that the PNP scan handler is
+bypassed.
+
+Note that these watchdogs can be described by multiple _HIDs for what
+seems to be identical hardware. This commit is not a complete list of
+all the possible watchdog ACPI _HIDs.
+
+Signed-off-by: Diogo Ivo <diogo.ivo@siemens.com>
+Link: https://patch.msgid.link/20250317-ivo-intel_oc_wdt-v3-2-32c396f4eefd@siemens.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/acpi_pnp.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c
+index 01abf26764b00..3f5a1840f5733 100644
+--- a/drivers/acpi/acpi_pnp.c
++++ b/drivers/acpi/acpi_pnp.c
+@@ -355,8 +355,10 @@ static bool acpi_pnp_match(const char *idstr, const struct acpi_device_id **matc
+ * device represented by it.
+ */
+ static const struct acpi_device_id acpi_nonpnp_device_ids[] = {
++ {"INT3F0D"},
+ {"INTC1080"},
+ {"INTC1081"},
++ {"INTC1099"},
+ {""},
+ };
+
+--
+2.39.5
+
--- /dev/null
+From ef8e3ec3ff413e4b736341071bdd811cc594a536 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 27 Apr 2025 10:10:34 +0200
+Subject: ALSA: hda/realtek: Add quirk for HP Spectre x360 15-df1xxx
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit be0c40da888840fe91b45474cb70779e6cbaf7ca ]
+
+HP Spectre x360 15-df1xxx with SSID 13c:863e requires similar
+workarounds that were applied to another HP Spectre x360 models;
+it has a mute LED only, no micmute LEDs, and needs the speaker GPIO
+seup.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=220054
+Link: https://patch.msgid.link/20250427081035.11567-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/hda/patch_realtek.c | 42 +++++++++++++++++++++++++++++++++++
+ 1 file changed, 42 insertions(+)
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 0b243adac8cf4..015c66b9003a4 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -6965,6 +6965,41 @@ static void alc285_fixup_hp_spectre_x360_eb1(struct hda_codec *codec,
+ }
+ }
+
++/* GPIO1 = amplifier on/off */
++static void alc285_fixup_hp_spectre_x360_df1(struct hda_codec *codec,
++ const struct hda_fixup *fix,
++ int action)
++{
++ struct alc_spec *spec = codec->spec;
++ static const hda_nid_t conn[] = { 0x02 };
++ static const struct hda_pintbl pincfgs[] = {
++ { 0x14, 0x90170110 }, /* front/high speakers */
++ { 0x17, 0x90170130 }, /* back/bass speakers */
++ { }
++ };
++
++ // enable mute led
++ alc285_fixup_hp_mute_led_coefbit(codec, fix, action);
++
++ switch (action) {
++ case HDA_FIXUP_ACT_PRE_PROBE:
++ /* needed for amp of back speakers */
++ spec->gpio_mask |= 0x01;
++ spec->gpio_dir |= 0x01;
++ snd_hda_apply_pincfgs(codec, pincfgs);
++ /* share DAC to have unified volume control */
++ snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn), conn);
++ snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
++ break;
++ case HDA_FIXUP_ACT_INIT:
++ /* need to toggle GPIO to enable the amp of back speakers */
++ alc_update_gpio_data(codec, 0x01, true);
++ msleep(100);
++ alc_update_gpio_data(codec, 0x01, false);
++ break;
++ }
++}
++
+ static void alc285_fixup_hp_spectre_x360(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+ {
+@@ -7730,6 +7765,7 @@ enum {
+ ALC280_FIXUP_HP_9480M,
+ ALC245_FIXUP_HP_X360_AMP,
+ ALC285_FIXUP_HP_SPECTRE_X360_EB1,
++ ALC285_FIXUP_HP_SPECTRE_X360_DF1,
+ ALC285_FIXUP_HP_ENVY_X360,
+ ALC288_FIXUP_DELL_HEADSET_MODE,
+ ALC288_FIXUP_DELL1_MIC_NO_PRESENCE,
+@@ -9798,6 +9834,10 @@ static const struct hda_fixup alc269_fixups[] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc285_fixup_hp_spectre_x360_eb1
+ },
++ [ALC285_FIXUP_HP_SPECTRE_X360_DF1] = {
++ .type = HDA_FIXUP_FUNC,
++ .v.func = alc285_fixup_hp_spectre_x360_df1
++ },
+ [ALC285_FIXUP_HP_ENVY_X360] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc285_fixup_hp_envy_x360,
+@@ -10515,6 +10555,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x103c, 0x86c1, "HP Laptop 15-da3001TU", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
+ SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO),
+ SND_PCI_QUIRK(0x103c, 0x86e7, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
++ SND_PCI_QUIRK(0x103c, 0x863e, "HP Spectre x360 15-df1xxx", ALC285_FIXUP_HP_SPECTRE_X360_DF1),
+ SND_PCI_QUIRK(0x103c, 0x86e8, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
+ SND_PCI_QUIRK(0x103c, 0x86f9, "HP Spectre x360 13-aw0xxx", ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED),
+ SND_PCI_QUIRK(0x103c, 0x8716, "HP Elite Dragonfly G2 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
+@@ -11404,6 +11445,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
+ {.id = ALC295_FIXUP_HP_OMEN, .name = "alc295-hp-omen"},
+ {.id = ALC285_FIXUP_HP_SPECTRE_X360, .name = "alc285-hp-spectre-x360"},
+ {.id = ALC285_FIXUP_HP_SPECTRE_X360_EB1, .name = "alc285-hp-spectre-x360-eb1"},
++ {.id = ALC285_FIXUP_HP_SPECTRE_X360_DF1, .name = "alc285-hp-spectre-x360-df1"},
+ {.id = ALC285_FIXUP_HP_ENVY_X360, .name = "alc285-hp-envy-x360"},
+ {.id = ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP, .name = "alc287-ideapad-bass-spk-amp"},
+ {.id = ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN, .name = "alc287-yoga9-bass-spk-pin"},
+--
+2.39.5
+
--- /dev/null
+From 6435ab9070e4d022a7da74a1481d193e6fea3c05 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 16 Feb 2025 22:31:03 +0100
+Subject: ALSA: hda/realtek: Enable PC beep passthrough for HP EliteBook 855 G7
+
+From: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
+
+[ Upstream commit aa85822c611aef7cd4dc17d27121d43e21bb82f0 ]
+
+PC speaker works well on this platform in BIOS and in Linux until sound
+card drivers are loaded. Then it stops working.
+
+There seems to be a beep generator node at 0x1a in this CODEC
+(ALC269_TYPE_ALC215) but it seems to be only connected to capture mixers
+at nodes 0x22 and 0x23.
+If I unmute the mixer input for 0x1a at node 0x23 and start recording
+from its "ALC285 Analog" capture device I can clearly hear beeps in that
+recording.
+
+So the beep generator is indeed working properly, however I wasn't able to
+figure out any way to connect it to speakers.
+
+However, the bits in the "Passthrough Control" register (0x36) seems to
+work at least partially: by zeroing "B" and "h" and setting "S" I can at
+least make the PIT PC speaker output appear either in this laptop speakers
+or headphones (depending on whether they are connected or not).
+
+There are some caveats, however:
+* If the CODEC gets runtime-suspended the beeps stop so it needs HDA beep
+device for keeping it awake during beeping.
+
+* If the beep generator node is generating any beep the PC beep passthrough
+seems to be temporarily inhibited, so the HDA beep device has to be
+prevented from using the actual beep generator node - but the beep device
+is still necessary due to the previous point.
+
+* In contrast with other platforms here beep amplification has to be
+disabled otherwise the beeps output are WAY louder than they were on pure
+BIOS setup.
+
+Unless someone (from Realtek probably) knows how to make the beep generator
+node output appear in speakers / headphones using PC beep passthrough seems
+to be the only way to make PC speaker beeping actually work on this
+platform.
+
+Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
+Acked-by: kailang@realtek.com
+Link: https://patch.msgid.link/7461f695b4daed80f2fc4b1463ead47f04f9ad05.1739741254.git.mail@maciej.szmigiero.name
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/sound/hda_codec.h | 1 +
+ sound/pci/hda/hda_beep.c | 15 +++++++++------
+ sound/pci/hda/patch_realtek.c | 34 +++++++++++++++++++++++++++++++++-
+ 3 files changed, 43 insertions(+), 7 deletions(-)
+
+diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h
+index 575e55aa08ca9..c1fe6290d04dc 100644
+--- a/include/sound/hda_codec.h
++++ b/include/sound/hda_codec.h
+@@ -195,6 +195,7 @@ struct hda_codec {
+ /* beep device */
+ struct hda_beep *beep;
+ unsigned int beep_mode;
++ bool beep_just_power_on;
+
+ /* widget capabilities cache */
+ u32 *wcaps;
+diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
+index e51d475725576..13a7d92e8d8d0 100644
+--- a/sound/pci/hda/hda_beep.c
++++ b/sound/pci/hda/hda_beep.c
+@@ -31,8 +31,9 @@ static void generate_tone(struct hda_beep *beep, int tone)
+ beep->power_hook(beep, true);
+ beep->playing = 1;
+ }
+- snd_hda_codec_write(codec, beep->nid, 0,
+- AC_VERB_SET_BEEP_CONTROL, tone);
++ if (!codec->beep_just_power_on)
++ snd_hda_codec_write(codec, beep->nid, 0,
++ AC_VERB_SET_BEEP_CONTROL, tone);
+ if (!tone && beep->playing) {
+ beep->playing = 0;
+ if (beep->power_hook)
+@@ -212,10 +213,12 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
+ struct hda_beep *beep;
+ int err;
+
+- if (!snd_hda_get_bool_hint(codec, "beep"))
+- return 0; /* disabled explicitly by hints */
+- if (codec->beep_mode == HDA_BEEP_MODE_OFF)
+- return 0; /* disabled by module option */
++ if (!codec->beep_just_power_on) {
++ if (!snd_hda_get_bool_hint(codec, "beep"))
++ return 0; /* disabled explicitly by hints */
++ if (codec->beep_mode == HDA_BEEP_MODE_OFF)
++ return 0; /* disabled by module option */
++ }
+
+ beep = kzalloc(sizeof(*beep), GFP_KERNEL);
+ if (beep == NULL)
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index db72c5fce9d18..0b243adac8cf4 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -28,6 +28,7 @@
+ #include <sound/hda_codec.h>
+ #include "hda_local.h"
+ #include "hda_auto_parser.h"
++#include "hda_beep.h"
+ #include "hda_jack.h"
+ #include "hda_generic.h"
+ #include "hda_component.h"
+@@ -7036,6 +7037,30 @@ static void alc285_fixup_hp_envy_x360(struct hda_codec *codec,
+ }
+ }
+
++static void alc285_fixup_hp_beep(struct hda_codec *codec,
++ const struct hda_fixup *fix, int action)
++{
++ if (action == HDA_FIXUP_ACT_PRE_PROBE) {
++ codec->beep_just_power_on = true;
++ } else if (action == HDA_FIXUP_ACT_INIT) {
++#ifdef CONFIG_SND_HDA_INPUT_BEEP
++ /*
++ * Just enable loopback to internal speaker and headphone jack.
++ * Disable amplification to get about the same beep volume as
++ * was on pure BIOS setup before loading the driver.
++ */
++ alc_update_coef_idx(codec, 0x36, 0x7070, BIT(13));
++
++ snd_hda_enable_beep_device(codec, 1);
++
++#if !IS_ENABLED(CONFIG_INPUT_PCSPKR)
++ dev_warn_once(hda_codec_dev(codec),
++ "enable CONFIG_INPUT_PCSPKR to get PC beeps\n");
++#endif
++#endif
++ }
++}
++
+ /* for hda_fixup_thinkpad_acpi() */
+ #include "thinkpad_helper.c"
+
+@@ -7806,6 +7831,7 @@ enum {
+ ALC285_FIXUP_HP_GPIO_LED,
+ ALC285_FIXUP_HP_MUTE_LED,
+ ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED,
++ ALC285_FIXUP_HP_BEEP_MICMUTE_LED,
+ ALC236_FIXUP_HP_MUTE_LED_COEFBIT2,
+ ALC236_FIXUP_HP_GPIO_LED,
+ ALC236_FIXUP_HP_MUTE_LED,
+@@ -9395,6 +9421,12 @@ static const struct hda_fixup alc269_fixups[] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc285_fixup_hp_spectre_x360_mute_led,
+ },
++ [ALC285_FIXUP_HP_BEEP_MICMUTE_LED] = {
++ .type = HDA_FIXUP_FUNC,
++ .v.func = alc285_fixup_hp_beep,
++ .chained = true,
++ .chain_id = ALC285_FIXUP_HP_MUTE_LED,
++ },
+ [ALC236_FIXUP_HP_MUTE_LED_COEFBIT2] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc236_fixup_hp_mute_led_coefbit2,
+@@ -10493,7 +10525,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x103c, 0x8730, "HP ProBook 445 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
+ SND_PCI_QUIRK(0x103c, 0x8735, "HP ProBook 435 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
+ SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_AMP_INIT),
+- SND_PCI_QUIRK(0x103c, 0x8760, "HP", ALC285_FIXUP_HP_MUTE_LED),
++ SND_PCI_QUIRK(0x103c, 0x8760, "HP EliteBook 8{4,5}5 G7", ALC285_FIXUP_HP_BEEP_MICMUTE_LED),
+ SND_PCI_QUIRK(0x103c, 0x876e, "HP ENVY x360 Convertible 13-ay0xxx", ALC245_FIXUP_HP_X360_MUTE_LEDS),
+ SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED),
+ SND_PCI_QUIRK(0x103c, 0x877d, "HP", ALC236_FIXUP_HP_MUTE_LED),
+--
+2.39.5
+
--- /dev/null
+From 260eab4705084b13600806b3b93c6cbf5cca9bd8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Mar 2025 09:42:42 +0100
+Subject: ALSA: seq: Improve data consistency at polling
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit e3cd33ab17c33bd8f1a9df66ec83a15dd8f7afbb ]
+
+snd_seq_poll() calls snd_seq_write_pool_allocated() that reads out a
+field in client->pool object, while it can be updated concurrently via
+ioctls, as reported by syzbot. The data race itself is harmless, as
+it's merely a poll() call, and the state is volatile. OTOH, the read
+out of poll object info from the caller side is fragile, and we can
+leave it better in snd_seq_pool_poll_wait() alone.
+
+A similar pattern is seen in snd_seq_kernel_client_write_poll(), too,
+which is called from the OSS sequencer.
+
+This patch drops the pool checks from the caller side and add the
+pool->lock in snd_seq_pool_poll_wait() for better data consistency.
+
+Reported-by: syzbot+2d373c9936c00d7e120c@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/67c88903.050a0220.15b4b9.0028.GAE@google.com
+Link: https://patch.msgid.link/20250307084246.29271-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/core/seq/seq_clientmgr.c | 5 +----
+ sound/core/seq/seq_memory.c | 1 +
+ 2 files changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
+index b74de9c0969fc..9e59a97f47472 100644
+--- a/sound/core/seq/seq_clientmgr.c
++++ b/sound/core/seq/seq_clientmgr.c
+@@ -1164,8 +1164,7 @@ static __poll_t snd_seq_poll(struct file *file, poll_table * wait)
+ if (snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_OUTPUT) {
+
+ /* check if data is available in the pool */
+- if (!snd_seq_write_pool_allocated(client) ||
+- snd_seq_pool_poll_wait(client->pool, file, wait))
++ if (snd_seq_pool_poll_wait(client->pool, file, wait))
+ mask |= EPOLLOUT | EPOLLWRNORM;
+ }
+
+@@ -2583,8 +2582,6 @@ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table
+ if (client == NULL)
+ return -ENXIO;
+
+- if (! snd_seq_write_pool_allocated(client))
+- return 1;
+ if (snd_seq_pool_poll_wait(client->pool, file, wait))
+ return 1;
+ return 0;
+diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
+index 20155e3e87c6a..ccde0ca3d2082 100644
+--- a/sound/core/seq/seq_memory.c
++++ b/sound/core/seq/seq_memory.c
+@@ -427,6 +427,7 @@ int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file,
+ poll_table *wait)
+ {
+ poll_wait(file, &pool->output_sleep, wait);
++ guard(spinlock_irq)(&pool->lock);
+ return snd_seq_output_ok(pool);
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 4bd27235f91f96a1c21431a83445448d2b46e806 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 29 Apr 2025 20:36:15 +0200
+Subject: ALSA: usb-audio: Fix duplicated name in MIDI substream names
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 0759e77a6d9bd34a874da73721ce4a7dc6665023 ]
+
+The MIDI substream name string is constructed from the combination of
+the card shortname (which is taken from USB iProduct) and the USB
+iJack. The problem is that some devices put the product name to the
+iJack field, too. For example, aplaymidi -l output on the Lanchkey MK
+49 are like:
+
+ % aplaymidi -l
+ Port Client name Port name
+ 44:0 Launchkey MK4 49 Launchkey MK4 49 Launchkey MK4
+ 44:1 Launchkey MK4 49 Launchkey MK4 49 Launchkey MK4
+
+where the actual iJack name can't be seen because it's truncated due
+to the doubly words.
+
+For resolving those situations, this patch compares the iJack string
+with the card shortname, and drops if both start with the same words.
+Then the result becomes like:
+
+ % aplaymidi -l
+ Port Client name Port name
+ 40:0 Launchkey MK4 49 Launchkey MK4 49 MIDI In
+ 40:1 Launchkey MK4 49 Launchkey MK4 49 DAW In
+
+A caveat is that there are some pre-defined names for certain
+devices in the driver code, and this workaround shouldn't be applied
+to them. Similarly, when the iJack isn't specified, we should skip
+this check, too. The patch added those checks in addition to the
+string comparison.
+
+Suggested-by: Paul Davis <paul@linuxaudiosystems.com>
+Tested-by: Paul Davis <paul@linuxaudiosystems.com>
+Link: https://lore.kernel.org/CAFa_cKmEDQWcJatbYWi6A58Zg4Ma9_6Nr3k5LhqwyxC-P_kXtw@mail.gmail.com
+Link: https://patch.msgid.link/20250429183626.20773-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/midi.c | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/sound/usb/midi.c b/sound/usb/midi.c
+index 826ac870f2469..a792ada18863a 100644
+--- a/sound/usb/midi.c
++++ b/sound/usb/midi.c
+@@ -1885,10 +1885,18 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi,
+ }
+
+ port_info = find_port_info(umidi, number);
+- name_format = port_info ? port_info->name :
+- (jack_name != default_jack_name ? "%s %s" : "%s %s %d");
+- snprintf(substream->name, sizeof(substream->name),
+- name_format, umidi->card->shortname, jack_name, number + 1);
++ if (port_info || jack_name == default_jack_name ||
++ strncmp(umidi->card->shortname, jack_name, strlen(umidi->card->shortname)) != 0) {
++ name_format = port_info ? port_info->name :
++ (jack_name != default_jack_name ? "%s %s" : "%s %s %d");
++ snprintf(substream->name, sizeof(substream->name),
++ name_format, umidi->card->shortname, jack_name, number + 1);
++ } else {
++ /* The manufacturer included the iProduct name in the jack
++ * name, do not use both
++ */
++ strscpy(substream->name, jack_name);
++ }
+
+ *rsubstream = substream;
+ }
+--
+2.39.5
+
--- /dev/null
+From b3a17a4ab9167f6a5521c013be9e8020c59219e7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jan 2025 18:46:20 +0530
+Subject: arch/powerpc/perf: Check the instruction type before creating sample
+ with perf_mem_data_src
+
+From: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
+
+[ Upstream commit 2ffb26afa64261139e608bf087a0c1fe24d76d4d ]
+
+perf mem report aborts as below sometimes (during some corner
+case) in powerpc:
+
+ # ./perf mem report 1>out
+ *** stack smashing detected ***: terminated
+ Aborted (core dumped)
+
+The backtrace is as below:
+ __pthread_kill_implementation ()
+ raise ()
+ abort ()
+ __libc_message
+ __fortify_fail
+ __stack_chk_fail
+ hist_entry.lvl_snprintf
+ __sort__hpp_entry
+ __hist_entry__snprintf
+ hists.fprintf
+ cmd_report
+ cmd_mem
+
+Snippet of code which triggers the issue
+from tools/perf/util/sort.c
+
+ static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf,
+ size_t size, unsigned int width)
+ {
+ char out[64];
+
+ perf_mem__lvl_scnprintf(out, sizeof(out), he->mem_info);
+ return repsep_snprintf(bf, size, "%-*s", width, out);
+ }
+
+The value of "out" is filled from perf_mem_data_src value.
+Debugging this further showed that for some corner cases, the
+value of "data_src" was pointing to wrong value. This resulted
+in bigger size of string and causing stack check fail.
+
+The perf mem data source values are captured in the sample via
+isa207_get_mem_data_src function. The initial check is to fetch
+the type of sampled instruction. If the type of instruction is
+not valid (not a load/store instruction), the function returns.
+
+Since 'commit e16fd7f2cb1a ("perf: Use sample_flags for data_src")',
+data_src field is not initialized by the perf_sample_data_init()
+function. If the PMU driver doesn't set the data_src value to zero if
+type is not valid, this will result in uninitailised value for data_src.
+The uninitailised value of data_src resulted in stack check fail
+followed by abort for "perf mem report".
+
+When requesting for data source information in the sample, the
+instruction type is expected to be load or store instruction.
+In ISA v3.0, due to hardware limitation, there are corner cases
+where the instruction type other than load or store is observed.
+In ISA v3.0 and before values "0" and "7" are considered reserved.
+In ISA v3.1, value "7" has been used to indicate "larx/stcx".
+Drop the sample if instruction type has reserved values for this
+field with a ISA version check. Initialize data_src to zero in
+isa207_get_mem_data_src if the instruction type is not load/store.
+
+Reported-by: Disha Goel <disgoel@linux.vnet.ibm.com>
+Signed-off-by: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
+Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
+Link: https://patch.msgid.link/20250121131621.39054-1-atrajeev@linux.vnet.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/perf/core-book3s.c | 20 ++++++++++++++++++++
+ arch/powerpc/perf/isa207-common.c | 4 +++-
+ 2 files changed, 23 insertions(+), 1 deletion(-)
+
+diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
+index 42867469752d7..33d726bb99e3d 100644
+--- a/arch/powerpc/perf/core-book3s.c
++++ b/arch/powerpc/perf/core-book3s.c
+@@ -2222,6 +2222,10 @@ static struct pmu power_pmu = {
+ #define PERF_SAMPLE_ADDR_TYPE (PERF_SAMPLE_ADDR | \
+ PERF_SAMPLE_PHYS_ADDR | \
+ PERF_SAMPLE_DATA_PAGE_SIZE)
++
++#define SIER_TYPE_SHIFT 15
++#define SIER_TYPE_MASK (0x7ull << SIER_TYPE_SHIFT)
++
+ /*
+ * A counter has overflowed; update its count and record
+ * things if requested. Note that interrupts are hard-disabled
+@@ -2290,6 +2294,22 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
+ is_kernel_addr(mfspr(SPRN_SIAR)))
+ record = 0;
+
++ /*
++ * SIER[46-48] presents instruction type of the sampled instruction.
++ * In ISA v3.0 and before values "0" and "7" are considered reserved.
++ * In ISA v3.1, value "7" has been used to indicate "larx/stcx".
++ * Drop the sample if "type" has reserved values for this field with a
++ * ISA version check.
++ */
++ if (event->attr.sample_type & PERF_SAMPLE_DATA_SRC &&
++ ppmu->get_mem_data_src) {
++ val = (regs->dar & SIER_TYPE_MASK) >> SIER_TYPE_SHIFT;
++ if (val == 0 || (val == 7 && !cpu_has_feature(CPU_FTR_ARCH_31))) {
++ record = 0;
++ atomic64_inc(&event->lost_samples);
++ }
++ }
++
+ /*
+ * Finally record data if requested.
+ */
+diff --git a/arch/powerpc/perf/isa207-common.c b/arch/powerpc/perf/isa207-common.c
+index 56301b2bc8ae8..031a2b63c171d 100644
+--- a/arch/powerpc/perf/isa207-common.c
++++ b/arch/powerpc/perf/isa207-common.c
+@@ -321,8 +321,10 @@ void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags,
+
+ sier = mfspr(SPRN_SIER);
+ val = (sier & ISA207_SIER_TYPE_MASK) >> ISA207_SIER_TYPE_SHIFT;
+- if (val != 1 && val != 2 && !(val == 7 && cpu_has_feature(CPU_FTR_ARCH_31)))
++ if (val != 1 && val != 2 && !(val == 7 && cpu_has_feature(CPU_FTR_ARCH_31))) {
++ dsrc->val = 0;
+ return;
++ }
+
+ idx = (sier & ISA207_SIER_LDST_MASK) >> ISA207_SIER_LDST_SHIFT;
+ sub_idx = (sier & ISA207_SIER_DATA_SRC_MASK) >> ISA207_SIER_DATA_SRC_SHIFT;
+--
+2.39.5
+
--- /dev/null
+From 4c69a51859aa9e61c92c6ad43bc67ea9b1b0f7ce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Feb 2025 08:51:56 -0700
+Subject: ARM: at91: pm: fix at91_suspend_finish for ZQ calibration
+
+From: Li Bin <bin.li@microchip.com>
+
+[ Upstream commit bc4722c3598d0e2c2dbf9609a3d3198993093e2b ]
+
+For sama7g5 and sama7d65 backup mode, we encountered a "ZQ calibrate error"
+during recalibrating the impedance in BootStrap.
+We found that the impedance value saved in at91_suspend_finish() before
+the DDR entered self-refresh mode did not match the resistor values. The
+ZDATA field in the DDR3PHY_ZQ0CR0 register uses a modified gray code to
+select the different impedance setting.
+But these gray code are incorrect, a workaournd from design team fixed the
+bug in the calibration logic. The ZDATA contains four independent impedance
+elements, but the algorithm combined the four elements into one. The elements
+were fixed using properly shifted offsets.
+
+Signed-off-by: Li Bin <bin.li@microchip.com>
+[nicolas.ferre@microchip.com: fix indentation and combine 2 patches]
+Signed-off-by: Nicolas Ferre <nicolas.ferre@microchip.com>
+Tested-by: Ryan Wanner <Ryan.Wanner@microchip.com>
+Tested-by: Durai Manickam KR <durai.manickamkr@microchip.com>
+Tested-by: Andrei Simion <andrei.simion@microchip.com>
+Signed-off-by: Ryan Wanner <Ryan.Wanner@microchip.com>
+Link: https://lore.kernel.org/r/28b33f9bcd0ca60ceba032969fe054d38f2b9577.1740671156.git.Ryan.Wanner@microchip.com
+Signed-off-by: Claudiu Beznea <claudiu.beznea@tuxon.dev>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/mach-at91/pm.c | 21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
+index 05a1547642b60..6c3e6aa22606f 100644
+--- a/arch/arm/mach-at91/pm.c
++++ b/arch/arm/mach-at91/pm.c
+@@ -545,11 +545,12 @@ extern u32 at91_pm_suspend_in_sram_sz;
+
+ static int at91_suspend_finish(unsigned long val)
+ {
+- unsigned char modified_gray_code[] = {
+- 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05, 0x0c, 0x0d,
+- 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09, 0x18, 0x19, 0x1a, 0x1b,
+- 0x1e, 0x1f, 0x1c, 0x1d, 0x14, 0x15, 0x16, 0x17, 0x12, 0x13,
+- 0x10, 0x11,
++ /* SYNOPSYS workaround to fix a bug in the calibration logic */
++ unsigned char modified_fix_code[] = {
++ 0x00, 0x01, 0x01, 0x06, 0x07, 0x0c, 0x06, 0x07, 0x0b, 0x18,
++ 0x0a, 0x0b, 0x0c, 0x0d, 0x0d, 0x0a, 0x13, 0x13, 0x12, 0x13,
++ 0x14, 0x15, 0x15, 0x12, 0x18, 0x19, 0x19, 0x1e, 0x1f, 0x14,
++ 0x1e, 0x1f,
+ };
+ unsigned int tmp, index;
+ int i;
+@@ -560,25 +561,25 @@ static int at91_suspend_finish(unsigned long val)
+ * restore the ZQ0SR0 with the value saved here. But the
+ * calibration is buggy and restoring some values from ZQ0SR0
+ * is forbidden and risky thus we need to provide processed
+- * values for these (modified gray code values).
++ * values for these.
+ */
+ tmp = readl(soc_pm.data.ramc_phy + DDR3PHY_ZQ0SR0);
+
+ /* Store pull-down output impedance select. */
+ index = (tmp >> DDR3PHY_ZQ0SR0_PDO_OFF) & 0x1f;
+- soc_pm.bu->ddr_phy_calibration[0] = modified_gray_code[index];
++ soc_pm.bu->ddr_phy_calibration[0] = modified_fix_code[index] << DDR3PHY_ZQ0SR0_PDO_OFF;
+
+ /* Store pull-up output impedance select. */
+ index = (tmp >> DDR3PHY_ZQ0SR0_PUO_OFF) & 0x1f;
+- soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index];
++ soc_pm.bu->ddr_phy_calibration[0] |= modified_fix_code[index] << DDR3PHY_ZQ0SR0_PUO_OFF;
+
+ /* Store pull-down on-die termination impedance select. */
+ index = (tmp >> DDR3PHY_ZQ0SR0_PDODT_OFF) & 0x1f;
+- soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index];
++ soc_pm.bu->ddr_phy_calibration[0] |= modified_fix_code[index] << DDR3PHY_ZQ0SR0_PDODT_OFF;
+
+ /* Store pull-up on-die termination impedance select. */
+ index = (tmp >> DDR3PHY_ZQ0SRO_PUODT_OFF) & 0x1f;
+- soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index];
++ soc_pm.bu->ddr_phy_calibration[0] |= modified_fix_code[index] << DDR3PHY_ZQ0SRO_PUODT_OFF;
+
+ /*
+ * The 1st 8 words of memory might get corrupted in the process
+--
+2.39.5
+
--- /dev/null
+From 2fc89d1462df3b2daa4ce20ac5e55ae95369ac92 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Feb 2025 12:56:11 +0200
+Subject: ARM: tegra: Switch DSI-B clock parent to PLLD on Tegra114
+
+From: Svyatoslav Ryhel <clamor95@gmail.com>
+
+[ Upstream commit 2b3db788f2f614b875b257cdb079adadedc060f3 ]
+
+PLLD is usually used as parent clock for internal video devices, like
+DSI for example, while PLLD2 is used as parent for HDMI.
+
+Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
+Link: https://lore.kernel.org/r/20250226105615.61087-3-clamor95@gmail.com
+Signed-off-by: Thierry Reding <treding@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/nvidia/tegra114.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/nvidia/tegra114.dtsi b/arch/arm/boot/dts/nvidia/tegra114.dtsi
+index 86f14e2fd29f3..6c057b5069514 100644
+--- a/arch/arm/boot/dts/nvidia/tegra114.dtsi
++++ b/arch/arm/boot/dts/nvidia/tegra114.dtsi
+@@ -139,7 +139,7 @@ dsib: dsi@54400000 {
+ reg = <0x54400000 0x00040000>;
+ clocks = <&tegra_car TEGRA114_CLK_DSIB>,
+ <&tegra_car TEGRA114_CLK_DSIBLP>,
+- <&tegra_car TEGRA114_CLK_PLL_D2_OUT0>;
++ <&tegra_car TEGRA114_CLK_PLL_D_OUT0>;
+ clock-names = "dsi", "lp", "parent";
+ resets = <&tegra_car 82>;
+ reset-names = "dsi";
+--
+2.39.5
+
--- /dev/null
+From 7a2769eacdd8c7bd50ab0d7a48c45328c31589f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Mar 2025 22:19:00 +0800
+Subject: arm64: Add support for HIP09 Spectre-BHB mitigation
+
+From: Jinqian Yang <yangjinqian1@huawei.com>
+
+[ Upstream commit e18c09b204e81702ea63b9f1a81ab003b72e3174 ]
+
+The HIP09 processor is vulnerable to the Spectre-BHB (Branch History
+Buffer) attack, which can be exploited to leak information through
+branch prediction side channels. This commit adds the MIDR of HIP09
+to the list for software mitigation.
+
+Signed-off-by: Jinqian Yang <yangjinqian1@huawei.com>
+Link: https://lore.kernel.org/r/20250325141900.2057314-1-yangjinqian1@huawei.com
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/cputype.h | 2 ++
+ arch/arm64/kernel/proton-pack.c | 1 +
+ 2 files changed, 3 insertions(+)
+
+diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
+index 8a6b7feca3e42..d92a0203e5a93 100644
+--- a/arch/arm64/include/asm/cputype.h
++++ b/arch/arm64/include/asm/cputype.h
+@@ -132,6 +132,7 @@
+ #define FUJITSU_CPU_PART_A64FX 0x001
+
+ #define HISI_CPU_PART_TSV110 0xD01
++#define HISI_CPU_PART_HIP09 0xD02
+
+ #define APPLE_CPU_PART_M1_ICESTORM 0x022
+ #define APPLE_CPU_PART_M1_FIRESTORM 0x023
+@@ -208,6 +209,7 @@
+ #define MIDR_NVIDIA_CARMEL MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_CARMEL)
+ #define MIDR_FUJITSU_A64FX MIDR_CPU_MODEL(ARM_CPU_IMP_FUJITSU, FUJITSU_CPU_PART_A64FX)
+ #define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110)
++#define MIDR_HISI_HIP09 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_HIP09)
+ #define MIDR_APPLE_M1_ICESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM)
+ #define MIDR_APPLE_M1_FIRESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM)
+ #define MIDR_APPLE_M1_ICESTORM_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_PRO)
+diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c
+index 8ef3335ecff72..31eaf15d2079a 100644
+--- a/arch/arm64/kernel/proton-pack.c
++++ b/arch/arm64/kernel/proton-pack.c
+@@ -904,6 +904,7 @@ static u8 spectre_bhb_loop_affected(void)
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_A77),
+ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1),
+ MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_GOLD),
++ MIDR_ALL_VERSIONS(MIDR_HISI_HIP09),
+ {},
+ };
+ static const struct midr_range spectre_bhb_k11_list[] = {
+--
+2.39.5
+
--- /dev/null
+From fc7e77a74eb958d274881dd11c0189cf3a3eb447 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Feb 2025 10:12:26 +0530
+Subject: arm64/mm: Check pmd_table() in pmd_trans_huge()
+
+From: Ryan Roberts <ryan.roberts@arm.com>
+
+[ Upstream commit d1770e909898c108e8c7d30ca039053e8818a9c9 ]
+
+Check for pmd_table() in pmd_trans_huge() rather then just checking for the
+PMD_TABLE_BIT. But ensure all present-invalid entries are handled correctly
+by always setting PTE_VALID before checking with pmd_table().
+
+Cc: Will Deacon <will@kernel.org>
+Cc: Ard Biesheuvel <ardb@kernel.org>
+Cc: Ryan Roberts <ryan.roberts@arm.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: linux-arm-kernel@lists.infradead.org
+Cc: linux-kernel@vger.kernel.org
+Signed-off-by: Ryan Roberts <ryan.roberts@arm.com>
+Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
+Link: https://lore.kernel.org/r/20250221044227.1145393-8-anshuman.khandual@arm.com
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/pgtable.h | 24 ++++++++++++------------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
+index c329ea061dc98..8ee56ae999c16 100644
+--- a/arch/arm64/include/asm/pgtable.h
++++ b/arch/arm64/include/asm/pgtable.h
+@@ -554,18 +554,6 @@ static inline int pmd_protnone(pmd_t pmd)
+ #endif
+
+ #define pmd_present(pmd) pte_present(pmd_pte(pmd))
+-
+-/*
+- * THP definitions.
+- */
+-
+-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+-static inline int pmd_trans_huge(pmd_t pmd)
+-{
+- return pmd_val(pmd) && pmd_present(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT);
+-}
+-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+-
+ #define pmd_dirty(pmd) pte_dirty(pmd_pte(pmd))
+ #define pmd_young(pmd) pte_young(pmd_pte(pmd))
+ #define pmd_valid(pmd) pte_valid(pmd_pte(pmd))
+@@ -725,6 +713,18 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+ #define pmd_leaf_size(pmd) (pmd_cont(pmd) ? CONT_PMD_SIZE : PMD_SIZE)
+ #define pte_leaf_size(pte) (pte_cont(pte) ? CONT_PTE_SIZE : PAGE_SIZE)
+
++#ifdef CONFIG_TRANSPARENT_HUGEPAGE
++static inline int pmd_trans_huge(pmd_t pmd)
++{
++ /*
++ * If pmd is present-invalid, pmd_table() won't detect it
++ * as a table, so force the valid bit for the comparison.
++ */
++ return pmd_val(pmd) && pmd_present(pmd) &&
++ !pmd_table(__pmd(pmd_val(pmd) | PTE_VALID));
++}
++#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
++
+ #if defined(CONFIG_ARM64_64K_PAGES) || CONFIG_PGTABLE_LEVELS < 3
+ static inline bool pud_sect(pud_t pud) { return false; }
+ static inline bool pud_table(pud_t pud) { return true; }
+--
+2.39.5
+
--- /dev/null
+From 0507249884273f23d95e9ca3a5a9f5e8f1b2cbbb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Feb 2025 10:12:25 +0530
+Subject: arm64/mm: Check PUD_TYPE_TABLE in pud_bad()
+
+From: Ryan Roberts <ryan.roberts@arm.com>
+
+[ Upstream commit bfb1d2b9021c21891427acc86eb848ccedeb274e ]
+
+pud_bad() is currently defined in terms of pud_table(). Although for some
+configs, pud_table() is hard-coded to true i.e. when using 64K base pages
+or when page table levels are less than 3.
+
+pud_bad() is intended to check that the pud is configured correctly. Hence
+let's open-code the same check that the full version of pud_table() uses
+into pud_bad(). Then it always performs the check regardless of the config.
+
+Cc: Will Deacon <will@kernel.org>
+Cc: Ard Biesheuvel <ardb@kernel.org>
+Cc: Ryan Roberts <ryan.roberts@arm.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: linux-arm-kernel@lists.infradead.org
+Cc: linux-kernel@vger.kernel.org
+Signed-off-by: Ryan Roberts <ryan.roberts@arm.com>
+Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
+Link: https://lore.kernel.org/r/20250221044227.1145393-7-anshuman.khandual@arm.com
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/pgtable.h | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
+index 8ee56ae999c16..5ba8376735cb0 100644
+--- a/arch/arm64/include/asm/pgtable.h
++++ b/arch/arm64/include/asm/pgtable.h
+@@ -806,7 +806,8 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)
+ pr_err("%s:%d: bad pmd %016llx.\n", __FILE__, __LINE__, pmd_val(e))
+
+ #define pud_none(pud) (!pud_val(pud))
+-#define pud_bad(pud) (!pud_table(pud))
++#define pud_bad(pud) ((pud_val(pud) & PUD_TYPE_MASK) != \
++ PUD_TYPE_TABLE)
+ #define pud_present(pud) pte_present(pud_pte(pud))
+ #ifndef __PAGETABLE_PMD_FOLDED
+ #define pud_leaf(pud) (pud_present(pud) && !pud_table(pud))
+--
+2.39.5
+
--- /dev/null
+From c7cda983106f40802ca3cd60d0ee7e0bf0a69eea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 12:17:36 +0000
+Subject: arm64: tegra: p2597: Fix gpio for vdd-1v8-dis regulator
+
+From: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
+
+[ Upstream commit f34621f31e3be81456c903287f7e4c0609829e29 ]
+
+According to the board schematics the enable pin of this regulator is
+connected to gpio line #9 of the first instance of the TCA9539
+GPIO expander, so adjust it.
+
+Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
+Link: https://lore.kernel.org/r/20250224-diogo-gpio_exp-v1-1-80fb84ac48c6@tecnico.ulisboa.pt
+Signed-off-by: Thierry Reding <treding@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
+index 63b94a04308e8..38d49d612c0c1 100644
+--- a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
++++ b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
+@@ -1686,7 +1686,7 @@ vdd_1v8_dis: regulator-vdd-1v8-dis {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+- gpio = <&exp1 14 GPIO_ACTIVE_HIGH>;
++ gpio = <&exp1 9 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ vin-supply = <&vdd_1v8>;
+ };
+--
+2.39.5
+
--- /dev/null
+From 3a8e671f5871b0940679a8f893f8f0ff3a3ab8f1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jan 2025 15:19:03 +0000
+Subject: arm64: tegra: Resize aperture for the IGX PCIe C5 slot
+
+From: Jon Hunter <jonathanh@nvidia.com>
+
+[ Upstream commit 6d4bfe6d86af1ef52bdb4592c9afb2037f24f2c4 ]
+
+Some discrete graphics cards such as the NVIDIA RTX A6000 support
+resizable BARs. When connecting an A6000 card to the NVIDIA IGX Orin
+platform, resizing the BAR1 aperture to 8GB fails because the current
+device-tree configuration for the PCIe C5 slot cannot support this.
+Fix this by updating the device-tree 'reg' and 'ranges' properties for
+the PCIe C5 slot to support this.
+
+Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
+Link: https://lore.kernel.org/r/20250116151903.476047-1-jonathanh@nvidia.com
+Signed-off-by: Thierry Reding <treding@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts b/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts
+index 36e8880537460..9ce55b4d2de89 100644
+--- a/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts
++++ b/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts
+@@ -302,6 +302,16 @@ pcie@14160000 {
+ };
+
+ pcie@141a0000 {
++ reg = <0x00 0x141a0000 0x0 0x00020000 /* appl registers (128K) */
++ 0x00 0x3a000000 0x0 0x00040000 /* configuration space (256K) */
++ 0x00 0x3a040000 0x0 0x00040000 /* iATU_DMA reg space (256K) */
++ 0x00 0x3a080000 0x0 0x00040000 /* DBI reg space (256K) */
++ 0x2e 0x20000000 0x0 0x10000000>; /* ECAM (256MB) */
++
++ ranges = <0x81000000 0x00 0x3a100000 0x00 0x3a100000 0x0 0x00100000 /* downstream I/O (1MB) */
++ 0x82000000 0x00 0x40000000 0x2e 0x30000000 0x0 0x08000000 /* non-prefetchable memory (128MB) */
++ 0xc3000000 0x28 0x00000000 0x28 0x00000000 0x6 0x20000000>; /* prefetchable memory (25088MB) */
++
+ status = "okay";
+ vddio-pex-ctl-supply = <&vdd_1v8_ls>;
+ phys = <&p2u_nvhs_0>, <&p2u_nvhs_1>, <&p2u_nvhs_2>,
+--
+2.39.5
+
--- /dev/null
+From d90570c5e5adc969fe2c1af5ce5e789eeb4cec37 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Nov 2024 01:57:12 -0800
+Subject: arm64: zynqmp: add clock-output-names property in clock nodes
+
+From: Naman Trivedi <naman.trivedimanojbhai@amd.com>
+
+[ Upstream commit 385a59e7f7fb3438466a0712cc14672c708bbd57 ]
+
+Add clock-output-names property to clock nodes, so that the resulting
+clock name do not change when clock node name is changed.
+Also, replace underscores with hyphens in the clock node names as per
+dt-schema rule.
+
+Signed-off-by: Naman Trivedi <naman.trivedimanojbhai@amd.com>
+Acked-by: Senthil Nathan Thangaraj <senthilnathan.thangaraj@amd.com>
+Link: https://lore.kernel.org/r/20241122095712.1166883-1-naman.trivedimanojbhai@amd.com
+Signed-off-by: Michal Simek <michal.simek@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi | 15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi
+index 60d1b1acf9a03..385fed8a852af 100644
+--- a/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi
++++ b/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi
+@@ -10,39 +10,44 @@
+
+ #include <dt-bindings/clock/xlnx-zynqmp-clk.h>
+ / {
+- pss_ref_clk: pss_ref_clk {
++ pss_ref_clk: pss-ref-clk {
+ bootph-all;
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <33333333>;
++ clock-output-names = "pss_ref_clk";
+ };
+
+- video_clk: video_clk {
++ video_clk: video-clk {
+ bootph-all;
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <27000000>;
++ clock-output-names = "video_clk";
+ };
+
+- pss_alt_ref_clk: pss_alt_ref_clk {
++ pss_alt_ref_clk: pss-alt-ref-clk {
+ bootph-all;
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
++ clock-output-names = "pss_alt_ref_clk";
+ };
+
+- gt_crx_ref_clk: gt_crx_ref_clk {
++ gt_crx_ref_clk: gt-crx-ref-clk {
+ bootph-all;
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <108000000>;
++ clock-output-names = "gt_crx_ref_clk";
+ };
+
+- aux_ref_clk: aux_ref_clk {
++ aux_ref_clk: aux-ref-clk {
+ bootph-all;
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <27000000>;
++ clock-output-names = "aux_ref_clk";
+ };
+ };
+
+--
+2.39.5
+
--- /dev/null
+From fc49f17c05ddc55ae2c395be6d215a5ec3ed3b1c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Feb 2025 15:10:43 +0100
+Subject: ASoC: codecs: pcm3168a: Allow for 24-bit in provider mode
+
+From: Cezary Rojewski <cezary.rojewski@intel.com>
+
+[ Upstream commit 7d92a38d67e5d937b64b20aa4fd14451ee1772f3 ]
+
+As per codec device specification, 24-bit is allowed in provider mode.
+Update the code to reflect that.
+
+Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
+Link: https://patch.msgid.link/20250203141051.2361323-4-cezary.rojewski@intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/pcm3168a.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c
+index fac0617ab95b6..6cbb8d0535b02 100644
+--- a/sound/soc/codecs/pcm3168a.c
++++ b/sound/soc/codecs/pcm3168a.c
+@@ -493,9 +493,9 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
+ }
+ break;
+ case 24:
+- if (provider_mode || (format == SND_SOC_DAIFMT_DSP_A) ||
+- (format == SND_SOC_DAIFMT_DSP_B)) {
+- dev_err(component->dev, "24-bit slots not supported in provider mode, or consumer mode using DSP\n");
++ if (!provider_mode && ((format == SND_SOC_DAIFMT_DSP_A) ||
++ (format == SND_SOC_DAIFMT_DSP_B))) {
++ dev_err(component->dev, "24-bit slots not supported in consumer mode using DSP\n");
+ return -EINVAL;
+ }
+ break;
+--
+2.39.5
+
--- /dev/null
+From dc0e41cd12e735a8903a7d0170ca5e37f61825b0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Mar 2025 20:24:59 +0100
+Subject: ASoC: codecs: wsa883x: Correct VI sense channel mask
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit ed3b274abc4008efffebf1997968a3f2720a86d3 ]
+
+VI sense port on WSA883x speaker takes only one channel, so use 0x1 as
+channel mask. This fixes garbage being recorded by the speaker when
+testing the VI sense feedback path.
+
+Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://patch.msgid.link/20250312-asoc-wsa88xx-visense-v1-1-9ca705881122@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/wsa883x.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c
+index 47da5674d7c92..e31b7fb104e6c 100644
+--- a/sound/soc/codecs/wsa883x.c
++++ b/sound/soc/codecs/wsa883x.c
+@@ -529,7 +529,7 @@ static const struct sdw_port_config wsa883x_pconfig[WSA883X_MAX_SWR_PORTS] = {
+ },
+ [WSA883X_PORT_VISENSE] = {
+ .num = WSA883X_PORT_VISENSE + 1,
+- .ch_mask = 0x3,
++ .ch_mask = 0x1,
+ },
+ };
+
+--
+2.39.5
+
--- /dev/null
+From 9447f57eaa9ef4ded554c7327267906ad3e9f056 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Mar 2025 20:25:00 +0100
+Subject: ASoC: codecs: wsa884x: Correct VI sense channel mask
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 060fac202eb8e5c83961f0e0bf6dad8ab6e46643 ]
+
+VI sense port on WSA883x speaker takes only one channel, so use 0x1 as
+channel mask. This fixes garbage being recorded by the speaker when
+testing the VI sense feedback path.
+
+Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://patch.msgid.link/20250312-asoc-wsa88xx-visense-v1-2-9ca705881122@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/wsa884x.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/soc/codecs/wsa884x.c b/sound/soc/codecs/wsa884x.c
+index 560a2c04b6955..18b0ee8f15a55 100644
+--- a/sound/soc/codecs/wsa884x.c
++++ b/sound/soc/codecs/wsa884x.c
+@@ -891,7 +891,7 @@ static const struct sdw_port_config wsa884x_pconfig[WSA884X_MAX_SWR_PORTS] = {
+ },
+ [WSA884X_PORT_VISENSE] = {
+ .num = WSA884X_PORT_VISENSE + 1,
+- .ch_mask = 0x3,
++ .ch_mask = 0x1,
+ },
+ [WSA884X_PORT_CPS] = {
+ .num = WSA884X_PORT_CPS + 1,
+--
+2.39.5
+
--- /dev/null
+From 9ecf254ba8c3a8ad5348ab5e115553b08177bb86 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Apr 2025 10:09:44 +0100
+Subject: ASoC: cs42l43: Disable headphone clamps during type detection
+
+From: Charles Keepax <ckeepax@opensource.cirrus.com>
+
+[ Upstream commit 70ad2e6bd180f94be030aef56e59693e36d945f3 ]
+
+The headphone clamps cause fairly loud pops during type detect
+because they sink current from the detection process itself. Disable
+the clamps whilst the type detect runs, to improve the detection
+pop performance.
+
+Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
+Link: https://patch.msgid.link/20250423090944.1504538-1-ckeepax@opensource.cirrus.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/cs42l43-jack.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/sound/soc/codecs/cs42l43-jack.c b/sound/soc/codecs/cs42l43-jack.c
+index 73d764fc85392..984a7f470a31f 100644
+--- a/sound/soc/codecs/cs42l43-jack.c
++++ b/sound/soc/codecs/cs42l43-jack.c
+@@ -654,6 +654,10 @@ static int cs42l43_run_type_detect(struct cs42l43_codec *priv)
+
+ reinit_completion(&priv->type_detect);
+
++ regmap_update_bits(cs42l43->regmap, CS42L43_STEREO_MIC_CLAMP_CTRL,
++ CS42L43_SMIC_HPAMP_CLAMP_DIS_FRC_VAL_MASK,
++ CS42L43_SMIC_HPAMP_CLAMP_DIS_FRC_VAL_MASK);
++
+ cs42l43_start_hs_bias(priv, true);
+ regmap_update_bits(cs42l43->regmap, CS42L43_HS2,
+ CS42L43_HSDET_MODE_MASK, 0x3 << CS42L43_HSDET_MODE_SHIFT);
+@@ -665,6 +669,9 @@ static int cs42l43_run_type_detect(struct cs42l43_codec *priv)
+ CS42L43_HSDET_MODE_MASK, 0x2 << CS42L43_HSDET_MODE_SHIFT);
+ cs42l43_stop_hs_bias(priv);
+
++ regmap_update_bits(cs42l43->regmap, CS42L43_STEREO_MIC_CLAMP_CTRL,
++ CS42L43_SMIC_HPAMP_CLAMP_DIS_FRC_VAL_MASK, 0);
++
+ if (!time_left)
+ return -ETIMEDOUT;
+
+--
+2.39.5
+
--- /dev/null
+From 1908224ced1af712a80ca55c2b666f1c34cfabdc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 6 Apr 2025 16:08:54 -0500
+Subject: ASoC: imx-card: Adjust over allocation of memory in
+ imx_card_parse_of()
+
+From: Chenyuan Yang <chenyuan0y@gmail.com>
+
+[ Upstream commit a9a69c3b38c89d7992fb53db4abb19104b531d32 ]
+
+Incorrect types are used as sizeof() arguments in devm_kcalloc().
+It should be sizeof(dai_link_data) for link_data instead of
+sizeof(snd_soc_dai_link).
+
+This is found by our static analysis tool.
+
+Signed-off-by: Chenyuan Yang <chenyuan0y@gmail.com>
+Link: https://patch.msgid.link/20250406210854.149316-1-chenyuan0y@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/fsl/imx-card.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c
+index 93dbe40008c00..e5ae435171d68 100644
+--- a/sound/soc/fsl/imx-card.c
++++ b/sound/soc/fsl/imx-card.c
+@@ -516,7 +516,7 @@ static int imx_card_parse_of(struct imx_card_data *data)
+ if (!card->dai_link)
+ return -ENOMEM;
+
+- data->link_data = devm_kcalloc(dev, num_links, sizeof(*link), GFP_KERNEL);
++ data->link_data = devm_kcalloc(dev, num_links, sizeof(*link_data), GFP_KERNEL);
+ if (!data->link_data)
+ return -ENOMEM;
+
+--
+2.39.5
+
--- /dev/null
+From cea49373e2c1b797cb91f8f11a08c44849d13c02 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 20 Apr 2025 10:56:59 +0200
+Subject: ASoC: Intel: bytcr_rt5640: Add DMI quirk for Acer Aspire SW3-013
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit a549b927ea3f5e50b1394209b64e6e17e31d4db8 ]
+
+Acer Aspire SW3-013 requires the very same quirk as other Acer Aspire
+model for making it working.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=220011
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/20250420085716.12095-1-tiwai@suse.de
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/boards/bytcr_rt5640.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
+index 1148e9498d8e8..b6434b4731261 100644
+--- a/sound/soc/intel/boards/bytcr_rt5640.c
++++ b/sound/soc/intel/boards/bytcr_rt5640.c
+@@ -576,6 +576,19 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
+ BYT_RT5640_SSP0_AIF2 |
+ BYT_RT5640_MCLK_EN),
+ },
++ { /* Acer Aspire SW3-013 */
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW3-013"),
++ },
++ .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
++ BYT_RT5640_JD_SRC_JD2_IN4N |
++ BYT_RT5640_OVCD_TH_2000UA |
++ BYT_RT5640_OVCD_SF_0P75 |
++ BYT_RT5640_DIFF_MIC |
++ BYT_RT5640_SSP0_AIF1 |
++ BYT_RT5640_MCLK_EN),
++ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+--
+2.39.5
+
--- /dev/null
+From 545bd30f3ec0c41474fdbc779a1d970463ce935d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Apr 2025 11:31:19 +0100
+Subject: ASoC: intel/sdw_utils: Add volume limit to cs42l43 speakers
+
+From: Stefan Binding <sbinding@opensource.cirrus.com>
+
+[ Upstream commit 02b44a2b2bdcee03cbb92484d31e9ca1b91b2a38 ]
+
+The volume control for cs42l43 speakers has a maximum gain of +31.5 dB.
+However, for many use cases, this can cause distorted audio, depending
+various factors, such as other signal-processing elements in the chain,
+for example if the audio passes through a gain control before reaching
+the codec or the signal path has been tuned for a particular maximum
+gain in the codec.
+
+In the case of systems which use the soc_sdw_cs42l43 driver, audio will
+likely be distorted in all cases above 0 dB, therefore add a volume
+limit of 128, which is 0 dB maximum volume inside this driver.
+
+Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com>
+Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
+Link: https://patch.msgid.link/20250430103134.24579-2-sbinding@opensource.cirrus.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/sdw_utils/soc_sdw_cs42l43.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/sound/soc/sdw_utils/soc_sdw_cs42l43.c b/sound/soc/sdw_utils/soc_sdw_cs42l43.c
+index adb1c008e871d..2dc7787234c36 100644
+--- a/sound/soc/sdw_utils/soc_sdw_cs42l43.c
++++ b/sound/soc/sdw_utils/soc_sdw_cs42l43.c
+@@ -20,6 +20,8 @@
+ #include <sound/soc-dapm.h>
+ #include <sound/soc_sdw_utils.h>
+
++#define CS42L43_SPK_VOLUME_0DB 128 /* 0dB Max */
++
+ static const struct snd_soc_dapm_route cs42l43_hs_map[] = {
+ { "Headphone", NULL, "cs42l43 AMP3_OUT" },
+ { "Headphone", NULL, "cs42l43 AMP4_OUT" },
+@@ -117,6 +119,14 @@ int asoc_sdw_cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_so
+ return -ENOMEM;
+ }
+
++ ret = snd_soc_limit_volume(card, "cs42l43 Speaker Digital Volume",
++ CS42L43_SPK_VOLUME_0DB);
++ if (ret)
++ dev_err(card->dev, "cs42l43 speaker volume limit failed: %d\n", ret);
++ else
++ dev_info(card->dev, "Setting CS42L43 Speaker volume limit to %d\n",
++ CS42L43_SPK_VOLUME_0DB);
++
+ ret = snd_soc_dapm_add_routes(&card->dapm, cs42l43_spk_map,
+ ARRAY_SIZE(cs42l43_spk_map));
+ if (ret)
+--
+2.39.5
+
--- /dev/null
+From dfbd159f75be911bf4266d61a579c5843ab2d35b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Mar 2025 16:52:17 -0300
+Subject: ASoC: mediatek: mt6359: Add stub for mt6359_accdet_enable_jack_detect
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+
+[ Upstream commit 0116a7d84b32537a10d9bea1fd1bfc06577ef527 ]
+
+Add a stub for mt6359_accdet_enable_jack_detect() to prevent linker
+failures in the machine sound drivers calling it when
+CONFIG_SND_SOC_MT6359_ACCDET is not enabled.
+
+Suggested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+Link: https://patch.msgid.link/20250306-mt8188-accdet-v3-3-7828e835ff4b@collabora.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/mt6359-accdet.h | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h
+index c234f2f4276a1..78ada3a5bfae5 100644
+--- a/sound/soc/codecs/mt6359-accdet.h
++++ b/sound/soc/codecs/mt6359-accdet.h
+@@ -123,6 +123,15 @@ struct mt6359_accdet {
+ struct workqueue_struct *jd_workqueue;
+ };
+
++#if IS_ENABLED(CONFIG_SND_SOC_MT6359_ACCDET)
+ int mt6359_accdet_enable_jack_detect(struct snd_soc_component *component,
+ struct snd_soc_jack *jack);
++#else
++static inline int
++mt6359_accdet_enable_jack_detect(struct snd_soc_component *component,
++ struct snd_soc_jack *jack)
++{
++ return -EOPNOTSUPP;
++}
++#endif
+ #endif
+--
+2.39.5
+
--- /dev/null
+From 8dd2aac1de497c380d8b16f3a007e3e4d2ed8537 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 11:33:48 -0300
+Subject: ASoC: mediatek: mt8188: Add reference for dmic clocks
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+
+[ Upstream commit bf1800073f4d55f08191b034c86b95881e99b6fd ]
+
+Add the names for the dmic clocks, aud_afe_dmic* and aud_dmic_hires*, so
+they can be acquired and enabled by the platform driver.
+
+Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://patch.msgid.link/20250225-genio700-dmic-v2-2-3076f5b50ef7@collabora.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/mediatek/mt8188/mt8188-afe-clk.c | 8 ++++++++
+ sound/soc/mediatek/mt8188/mt8188-afe-clk.h | 8 ++++++++
+ 2 files changed, 16 insertions(+)
+
+diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-clk.c b/sound/soc/mediatek/mt8188/mt8188-afe-clk.c
+index e69c1bb2cb239..7f411b8577823 100644
+--- a/sound/soc/mediatek/mt8188/mt8188-afe-clk.c
++++ b/sound/soc/mediatek/mt8188/mt8188-afe-clk.c
+@@ -58,7 +58,15 @@ static const char *aud_clks[MT8188_CLK_NUM] = {
+ [MT8188_CLK_AUD_ADC] = "aud_adc",
+ [MT8188_CLK_AUD_DAC_HIRES] = "aud_dac_hires",
+ [MT8188_CLK_AUD_A1SYS_HP] = "aud_a1sys_hp",
++ [MT8188_CLK_AUD_AFE_DMIC1] = "aud_afe_dmic1",
++ [MT8188_CLK_AUD_AFE_DMIC2] = "aud_afe_dmic2",
++ [MT8188_CLK_AUD_AFE_DMIC3] = "aud_afe_dmic3",
++ [MT8188_CLK_AUD_AFE_DMIC4] = "aud_afe_dmic4",
+ [MT8188_CLK_AUD_ADC_HIRES] = "aud_adc_hires",
++ [MT8188_CLK_AUD_DMIC_HIRES1] = "aud_dmic_hires1",
++ [MT8188_CLK_AUD_DMIC_HIRES2] = "aud_dmic_hires2",
++ [MT8188_CLK_AUD_DMIC_HIRES3] = "aud_dmic_hires3",
++ [MT8188_CLK_AUD_DMIC_HIRES4] = "aud_dmic_hires4",
+ [MT8188_CLK_AUD_I2SIN] = "aud_i2sin",
+ [MT8188_CLK_AUD_TDM_IN] = "aud_tdm_in",
+ [MT8188_CLK_AUD_I2S_OUT] = "aud_i2s_out",
+diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-clk.h b/sound/soc/mediatek/mt8188/mt8188-afe-clk.h
+index ec53c171c170a..c6c78d684f3ee 100644
+--- a/sound/soc/mediatek/mt8188/mt8188-afe-clk.h
++++ b/sound/soc/mediatek/mt8188/mt8188-afe-clk.h
+@@ -54,7 +54,15 @@ enum {
+ MT8188_CLK_AUD_ADC,
+ MT8188_CLK_AUD_DAC_HIRES,
+ MT8188_CLK_AUD_A1SYS_HP,
++ MT8188_CLK_AUD_AFE_DMIC1,
++ MT8188_CLK_AUD_AFE_DMIC2,
++ MT8188_CLK_AUD_AFE_DMIC3,
++ MT8188_CLK_AUD_AFE_DMIC4,
+ MT8188_CLK_AUD_ADC_HIRES,
++ MT8188_CLK_AUD_DMIC_HIRES1,
++ MT8188_CLK_AUD_DMIC_HIRES2,
++ MT8188_CLK_AUD_DMIC_HIRES3,
++ MT8188_CLK_AUD_DMIC_HIRES4,
+ MT8188_CLK_AUD_I2SIN,
+ MT8188_CLK_AUD_TDM_IN,
+ MT8188_CLK_AUD_I2S_OUT,
+--
+2.39.5
+
--- /dev/null
+From 414f6e788e644e52a36dbaea25b80d381143edec Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 11:33:49 -0300
+Subject: ASoC: mediatek: mt8188: Treat DMIC_GAINx_CUR as non-volatile
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+
+[ Upstream commit 7d87bde21c73731ddaf15e572020f80999c38ee3 ]
+
+The DMIC_GAINx_CUR registers contain the current (as in present) gain of
+each DMIC. During capture, this gain will ramp up until a target value
+is reached, and therefore the register is volatile since it is updated
+automatically by hardware.
+
+However, after capture the register's value returns to the value that
+was written to it. So reading these registers returns the current gain,
+and writing configures the initial gain for every capture.
+
+>From an audio configuration perspective, reading the instantaneous gain
+is not really useful. Instead, reading back the initial gain that was
+configured is the desired behavior. For that reason, consider the
+DMIC_GAINx_CUR registers as non-volatile, so the regmap's cache can be
+used to retrieve the values, rather than requiring pm runtime resuming
+the device.
+
+Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://patch.msgid.link/20250225-genio700-dmic-v2-3-3076f5b50ef7@collabora.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/mediatek/mt8188/mt8188-afe-pcm.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c
+index 73e5c63aeec87..d36520c6272dd 100644
+--- a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c
++++ b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c
+@@ -2855,10 +2855,6 @@ static bool mt8188_is_volatile_reg(struct device *dev, unsigned int reg)
+ case AFE_DMIC3_SRC_DEBUG_MON0:
+ case AFE_DMIC3_UL_SRC_MON0:
+ case AFE_DMIC3_UL_SRC_MON1:
+- case DMIC_GAIN1_CUR:
+- case DMIC_GAIN2_CUR:
+- case DMIC_GAIN3_CUR:
+- case DMIC_GAIN4_CUR:
+ case ETDM_IN1_MONITOR:
+ case ETDM_IN2_MONITOR:
+ case ETDM_OUT1_MONITOR:
+--
+2.39.5
+
--- /dev/null
+From b9766667f3f9fb66325479fe929ea0d2c0f2cce4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Feb 2025 00:57:22 +0000
+Subject: ASoC: ops: Enforce platform maximum on initial value
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Martin Povišer <povik+lin@cutebit.org>
+
+[ Upstream commit 783db6851c1821d8b983ffb12b99c279ff64f2ee ]
+
+Lower the volume if it is violating the platform maximum at its initial
+value (i.e. at the time of the 'snd_soc_limit_volume' call).
+
+Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
+[Cherry picked from the Asahi kernel with fixups -- broonie]
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Link: https://patch.msgid.link/20250208-asoc-volume-limit-v1-1-b98fcf4cdbad@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/soc-ops.c | 29 ++++++++++++++++++++++++++++-
+ 1 file changed, 28 insertions(+), 1 deletion(-)
+
+diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
+index b0e4e4168f38d..fb11003d56cf6 100644
+--- a/sound/soc/soc-ops.c
++++ b/sound/soc/soc-ops.c
+@@ -639,6 +639,33 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
+ }
+ EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
+
++static int snd_soc_clip_to_platform_max(struct snd_kcontrol *kctl)
++{
++ struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value;
++ struct snd_ctl_elem_value uctl;
++ int ret;
++
++ if (!mc->platform_max)
++ return 0;
++
++ ret = kctl->get(kctl, &uctl);
++ if (ret < 0)
++ return ret;
++
++ if (uctl.value.integer.value[0] > mc->platform_max)
++ uctl.value.integer.value[0] = mc->platform_max;
++
++ if (snd_soc_volsw_is_stereo(mc) &&
++ uctl.value.integer.value[1] > mc->platform_max)
++ uctl.value.integer.value[1] = mc->platform_max;
++
++ ret = kctl->put(kctl, &uctl);
++ if (ret < 0)
++ return ret;
++
++ return 0;
++}
++
+ /**
+ * snd_soc_limit_volume - Set new limit to an existing volume control.
+ *
+@@ -663,7 +690,7 @@ int snd_soc_limit_volume(struct snd_soc_card *card,
+ struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value;
+ if (max <= mc->max - mc->min) {
+ mc->platform_max = max;
+- ret = 0;
++ ret = snd_soc_clip_to_platform_max(kctl);
+ }
+ }
+ return ret;
+--
+2.39.5
+
--- /dev/null
+From 053604cc8f35a1b81f73b9dddbc2dd222b822759 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Mar 2025 14:31:52 +0100
+Subject: ASoC: pcm6240: Drop bogus code handling IRQ as GPIO
+
+From: Linus Walleij <linus.walleij@linaro.org>
+
+[ Upstream commit 17fdf318f5fbe5c27353ae917c0c5a2899d9c259 ]
+
+The current code for the IRQ in pcm6240 makes no sense:
+it looks up an IRQ with of_irq_get(), treat it as a GPIO
+by issuing gpio_request(), gpio_direction_input()
+and gpio_to_irq() on it.
+
+This is just wrong, if the device tree assigns the IRQ
+from a GPIO number this is just incorrect: it is clearly
+stated that GPIO providers and IRQ providers are
+orthogonal.
+
+It is possible to look up an IRQ to a corresponding GPIO
+line but this is taking an IRQ and pretending it's a
+GPIO, which is just semantically wrong.
+
+Drop the offending code and treat the IRQ that we get
+from the device tree as any other IRQ, see for example
+other codec drivers.
+
+The DT bindings for this codec does not have any in-tree
+DTS files, which may explain why things are weird.
+
+As a bonus, this moves the driver away from the legacy
+<linux/gpio.h> include.
+
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Link: https://patch.msgid.link/20250312-pcm-codecs-v1-3-41ffc4f8fc5c@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/pcm6240.c | 28 +++++++---------------------
+ sound/soc/codecs/pcm6240.h | 7 +------
+ 2 files changed, 8 insertions(+), 27 deletions(-)
+
+diff --git a/sound/soc/codecs/pcm6240.c b/sound/soc/codecs/pcm6240.c
+index 5d99877f88397..e59bb77edf091 100644
+--- a/sound/soc/codecs/pcm6240.c
++++ b/sound/soc/codecs/pcm6240.c
+@@ -14,7 +14,7 @@
+
+ #include <linux/unaligned.h>
+ #include <linux/firmware.h>
+-#include <linux/gpio.h>
++#include <linux/gpio/consumer.h>
+ #include <linux/i2c.h>
+ #include <linux/module.h>
+ #include <linux/of_irq.h>
+@@ -2035,10 +2035,8 @@ static const struct regmap_config pcmdevice_i2c_regmap = {
+
+ static void pcmdevice_remove(struct pcmdevice_priv *pcm_dev)
+ {
+- if (gpio_is_valid(pcm_dev->irq_info.gpio)) {
+- gpio_free(pcm_dev->irq_info.gpio);
+- free_irq(pcm_dev->irq_info.nmb, pcm_dev);
+- }
++ if (pcm_dev->irq)
++ free_irq(pcm_dev->irq, pcm_dev);
+ mutex_destroy(&pcm_dev->codec_lock);
+ }
+
+@@ -2110,7 +2108,7 @@ static int pcmdevice_i2c_probe(struct i2c_client *i2c)
+ ndev = 1;
+ dev_addrs[0] = i2c->addr;
+ }
+- pcm_dev->irq_info.gpio = of_irq_get(np, 0);
++ pcm_dev->irq = of_irq_get(np, 0);
+
+ for (i = 0; i < ndev; i++)
+ pcm_dev->addr[i] = dev_addrs[i];
+@@ -2133,22 +2131,10 @@ static int pcmdevice_i2c_probe(struct i2c_client *i2c)
+
+ if (pcm_dev->chip_id == PCM1690)
+ goto skip_interrupt;
+- if (gpio_is_valid(pcm_dev->irq_info.gpio)) {
+- dev_dbg(pcm_dev->dev, "irq-gpio = %d", pcm_dev->irq_info.gpio);
+-
+- ret = gpio_request(pcm_dev->irq_info.gpio, "PCMDEV-IRQ");
+- if (!ret) {
+- int gpio = pcm_dev->irq_info.gpio;
+-
+- gpio_direction_input(gpio);
+- pcm_dev->irq_info.nmb = gpio_to_irq(gpio);
+-
+- } else
+- dev_err(pcm_dev->dev, "%s: GPIO %d request error\n",
+- __func__, pcm_dev->irq_info.gpio);
++ if (pcm_dev->irq) {
++ dev_dbg(pcm_dev->dev, "irq = %d", pcm_dev->irq);
+ } else
+- dev_err(pcm_dev->dev, "Looking up irq-gpio failed %d\n",
+- pcm_dev->irq_info.gpio);
++ dev_err(pcm_dev->dev, "No irq provided\n");
+
+ skip_interrupt:
+ ret = devm_snd_soc_register_component(&i2c->dev,
+diff --git a/sound/soc/codecs/pcm6240.h b/sound/soc/codecs/pcm6240.h
+index 1e125bb972860..2d8f9e798139a 100644
+--- a/sound/soc/codecs/pcm6240.h
++++ b/sound/soc/codecs/pcm6240.h
+@@ -208,11 +208,6 @@ struct pcmdevice_regbin {
+ struct pcmdevice_config_info **cfg_info;
+ };
+
+-struct pcmdevice_irqinfo {
+- int gpio;
+- int nmb;
+-};
+-
+ struct pcmdevice_priv {
+ struct snd_soc_component *component;
+ struct i2c_client *client;
+@@ -221,7 +216,7 @@ struct pcmdevice_priv {
+ struct gpio_desc *hw_rst;
+ struct regmap *regmap;
+ struct pcmdevice_regbin regbin;
+- struct pcmdevice_irqinfo irq_info;
++ int irq;
+ unsigned int addr[PCMDEVICE_MAX_I2C_DEVICES];
+ unsigned int chip_id;
+ int cur_conf;
+--
+2.39.5
+
--- /dev/null
+From 5c4d49fd293c279538afc5566ca3613f22bbea05 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Feb 2025 16:14:30 +0000
+Subject: ASoC: qcom: sm8250: explicitly set format in
+ sm8250_be_hw_params_fixup()
+
+From: Alexey Klimov <alexey.klimov@linaro.org>
+
+[ Upstream commit 89be3c15a58b2ccf31e969223c8ac93ca8932d81 ]
+
+Setting format to s16le is required for compressed playback on compatible
+soundcards.
+
+Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Signed-off-by: Alexey Klimov <alexey.klimov@linaro.org>
+Link: https://patch.msgid.link/20250228161430.373961-1-alexey.klimov@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/qcom/sm8250.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c
+index 19adadedc88a2..1001fd3213803 100644
+--- a/sound/soc/qcom/sm8250.c
++++ b/sound/soc/qcom/sm8250.c
+@@ -7,6 +7,7 @@
+ #include <sound/soc.h>
+ #include <sound/soc-dapm.h>
+ #include <sound/pcm.h>
++#include <sound/pcm_params.h>
+ #include <linux/soundwire/sdw.h>
+ #include <sound/jack.h>
+ #include <linux/input-event-codes.h>
+@@ -39,9 +40,11 @@ static int sm8250_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
++ struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+
+ rate->min = rate->max = 48000;
+ channels->min = channels->max = 2;
++ snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
+
+ return 0;
+ }
+--
+2.39.5
+
--- /dev/null
+From 27db8278dbbd806e2fd9d3452985dde34964f400 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Jan 2025 15:44:07 +0000
+Subject: ASoC: rt722-sdca: Add some missing readable registers
+
+From: Charles Keepax <ckeepax@opensource.cirrus.com>
+
+[ Upstream commit f9a5c4b6afc79073491acdab7f1e943ee3a19fbb ]
+
+Add a few missing registers from the readable register callback.
+
+Suggested-by: Shuming Fan <shumingf@realtek.com>
+Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
+Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
+Link: https://patch.msgid.link/20250107154408.814455-6-ckeepax@opensource.cirrus.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/rt722-sdca-sdw.c | 49 +++++++++++++++++++++++++++++--
+ 1 file changed, 46 insertions(+), 3 deletions(-)
+
+diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c
+index 5449d6b5cf3d1..bf83f4bc94fc1 100644
+--- a/sound/soc/codecs/rt722-sdca-sdw.c
++++ b/sound/soc/codecs/rt722-sdca-sdw.c
+@@ -28,9 +28,50 @@ static bool rt722_sdca_readable_register(struct device *dev, unsigned int reg)
+ 0):
+ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_GE49, RT722_SDCA_CTL_DETECTED_MODE,
+ 0):
+- case SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, RT722_SDCA_CTL_HIDTX_CURRENT_OWNER,
+- 0) ... SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01,
+- RT722_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0):
++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_XU03, RT722_SDCA_CTL_SELECTED_MODE,
++ 0):
++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05,
++ RT722_SDCA_CTL_FU_MUTE, CH_L) ...
++ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05,
++ RT722_SDCA_CTL_FU_MUTE, CH_R):
++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_XU0D,
++ RT722_SDCA_CTL_SELECTED_MODE, 0):
++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F,
++ RT722_SDCA_CTL_FU_MUTE, CH_L) ...
++ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F,
++ RT722_SDCA_CTL_FU_MUTE, CH_R):
++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PDE40,
++ RT722_SDCA_CTL_REQ_POWER_STATE, 0):
++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PDE12,
++ RT722_SDCA_CTL_REQ_POWER_STATE, 0):
++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_CS01,
++ RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0):
++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_CS11,
++ RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0):
++ case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E,
++ RT722_SDCA_CTL_FU_MUTE, CH_01) ...
++ SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E,
++ RT722_SDCA_CTL_FU_MUTE, CH_04):
++ case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_IT26,
++ RT722_SDCA_CTL_VENDOR_DEF, 0):
++ case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_PDE2A,
++ RT722_SDCA_CTL_REQ_POWER_STATE, 0):
++ case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_CS1F,
++ RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0):
++ case SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01,
++ RT722_SDCA_CTL_HIDTX_CURRENT_OWNER, 0) ...
++ SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01,
++ RT722_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0):
++ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06,
++ RT722_SDCA_CTL_FU_MUTE, CH_L) ...
++ SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06,
++ RT722_SDCA_CTL_FU_MUTE, CH_R):
++ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_OT23,
++ RT722_SDCA_CTL_VENDOR_DEF, CH_08):
++ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_PDE23,
++ RT722_SDCA_CTL_REQ_POWER_STATE, 0):
++ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_CS31,
++ RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0):
+ case RT722_BUF_ADDR_HID1 ... RT722_BUF_ADDR_HID2:
+ return true;
+ default:
+@@ -74,6 +115,7 @@ static bool rt722_sdca_mbq_readable_register(struct device *dev, unsigned int re
+ case 0x5600000 ... 0x5600007:
+ case 0x5700000 ... 0x5700004:
+ case 0x5800000 ... 0x5800004:
++ case 0x5810000:
+ case 0x5b00003:
+ case 0x5c00011:
+ case 0x5d00006:
+@@ -81,6 +123,7 @@ static bool rt722_sdca_mbq_readable_register(struct device *dev, unsigned int re
+ case 0x5f00030:
+ case 0x6100000 ... 0x6100051:
+ case 0x6100055 ... 0x6100057:
++ case 0x6100060:
+ case 0x6100062:
+ case 0x6100064 ... 0x6100065:
+ case 0x6100067:
+--
+2.39.5
+
--- /dev/null
+From 04ecee4e14acd7ecfb35a5efbb9f88c19a4cd841 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Feb 2025 02:24:38 +0000
+Subject: ASoC: soc-dai: check return value at snd_soc_dai_set_tdm_slot()
+
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+
+[ Upstream commit 7f1186a8d738661b941b298fd6d1d5725ed71428 ]
+
+snd_soc_dai_set_tdm_slot() calls .xlate_tdm_slot_mask() or
+snd_soc_xlate_tdm_slot_mask(), but didn't check its return value.
+Let's check it.
+
+This patch might break existing driver. In such case, let's makes
+each func to void instead of int.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Link: https://patch.msgid.link/87o6z7yk61.wl-kuninori.morimoto.gx@renesas.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/soc-dai.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c
+index 4e08892d24c62..de09d21add453 100644
+--- a/sound/soc/soc-dai.c
++++ b/sound/soc/soc-dai.c
+@@ -275,10 +275,11 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
+
+ if (dai->driver->ops &&
+ dai->driver->ops->xlate_tdm_slot_mask)
+- dai->driver->ops->xlate_tdm_slot_mask(slots,
+- &tx_mask, &rx_mask);
++ ret = dai->driver->ops->xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask);
+ else
+- snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask);
++ ret = snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask);
++ if (ret)
++ goto err;
+
+ for_each_pcm_streams(stream)
+ snd_soc_dai_tdm_mask_set(dai, stream, *tdm_mask[stream]);
+@@ -287,6 +288,7 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
+ dai->driver->ops->set_tdm_slot)
+ ret = dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask,
+ slots, slot_width);
++err:
+ return soc_dai_ret(dai, ret);
+ }
+ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
+--
+2.39.5
+
--- /dev/null
+From 120e7700de4352fba94199762f5b5fe25f4779f1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Feb 2025 11:02:25 +1300
+Subject: ASoC: sun4i-codec: support hp-det-gpios property
+
+From: Ryan Walklin <ryan@testtoast.com>
+
+[ Upstream commit a149377c033afe6557c50892ebbfc0e8b7e2e253 ]
+
+Add support for GPIO headphone detection with the hp-det-gpios
+property. In order for this to properly disable the path upon
+removal of headphones, the output must be labelled Headphone which
+is a common sink in the driver.
+
+Describe a headphone jack and detection GPIO in the driver, check for
+a corresponding device tree node, and enable jack detection in a new
+machine init function if described.
+
+Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
+Signed-off-by: Ryan Walklin <ryan@testtoast.com>
+
+--
+Changelog v1..v2:
+- Separate DAPM changes into separate patch and add rationale.
+
+Tested-by: Philippe Simons <simons.philippe@gmail.com>
+Link: https://patch.msgid.link/20250214220247.10810-4-ryan@testtoast.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/sunxi/sun4i-codec.c | 53 +++++++++++++++++++++++++++++++++++
+ 1 file changed, 53 insertions(+)
+
+diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
+index 330bc0c09f56b..93dd88fb805dd 100644
+--- a/sound/soc/sunxi/sun4i-codec.c
++++ b/sound/soc/sunxi/sun4i-codec.c
+@@ -21,6 +21,7 @@
+ #include <linux/gpio/consumer.h>
+
+ #include <sound/core.h>
++#include <sound/jack.h>
+ #include <sound/pcm.h>
+ #include <sound/pcm_params.h>
+ #include <sound/soc.h>
+@@ -235,6 +236,7 @@ struct sun4i_codec {
+ struct clk *clk_module;
+ struct reset_control *rst;
+ struct gpio_desc *gpio_pa;
++ struct gpio_desc *gpio_hp;
+
+ /* ADC_FIFOC register is at different offset on different SoCs */
+ struct regmap_field *reg_adc_fifoc;
+@@ -1263,6 +1265,49 @@ static struct snd_soc_dai_driver dummy_cpu_dai = {
+ .ops = &dummy_dai_ops,
+ };
+
++static struct snd_soc_jack sun4i_headphone_jack;
++
++static struct snd_soc_jack_pin sun4i_headphone_jack_pins[] = {
++ { .pin = "Headphone", .mask = SND_JACK_HEADPHONE },
++};
++
++static struct snd_soc_jack_gpio sun4i_headphone_jack_gpio = {
++ .name = "hp-det",
++ .report = SND_JACK_HEADPHONE,
++ .debounce_time = 150,
++};
++
++static int sun4i_codec_machine_init(struct snd_soc_pcm_runtime *rtd)
++{
++ struct snd_soc_card *card = rtd->card;
++ struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card);
++ int ret;
++
++ if (scodec->gpio_hp) {
++ ret = snd_soc_card_jack_new_pins(card, "Headphone Jack",
++ SND_JACK_HEADPHONE,
++ &sun4i_headphone_jack,
++ sun4i_headphone_jack_pins,
++ ARRAY_SIZE(sun4i_headphone_jack_pins));
++ if (ret) {
++ dev_err(rtd->dev,
++ "Headphone jack creation failed: %d\n", ret);
++ return ret;
++ }
++
++ sun4i_headphone_jack_gpio.desc = scodec->gpio_hp;
++ ret = snd_soc_jack_add_gpios(&sun4i_headphone_jack, 1,
++ &sun4i_headphone_jack_gpio);
++
++ if (ret) {
++ dev_err(rtd->dev, "Headphone GPIO not added: %d\n", ret);
++ return ret;
++ }
++ }
++
++ return 0;
++}
++
+ static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev,
+ int *num_links)
+ {
+@@ -1288,6 +1333,7 @@ static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev,
+ link->codecs->name = dev_name(dev);
+ link->platforms->name = dev_name(dev);
+ link->dai_fmt = SND_SOC_DAIFMT_I2S;
++ link->init = sun4i_codec_machine_init;
+
+ *num_links = 1;
+
+@@ -1728,6 +1774,13 @@ static int sun4i_codec_probe(struct platform_device *pdev)
+ return ret;
+ }
+
++ scodec->gpio_hp = devm_gpiod_get_optional(&pdev->dev, "hp-det", GPIOD_IN);
++ if (IS_ERR(scodec->gpio_hp)) {
++ ret = PTR_ERR(scodec->gpio_hp);
++ dev_err_probe(&pdev->dev, ret, "Failed to get hp-det gpio\n");
++ return ret;
++ }
++
+ /* reg_field setup */
+ scodec->reg_adc_fifoc = devm_regmap_field_alloc(&pdev->dev,
+ scodec->regmap,
+--
+2.39.5
+
--- /dev/null
+From 2bb4f14b7a2536b8fa4b8e9874d097c2396d5e7a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Feb 2025 01:03:27 +0000
+Subject: ASoC: tas2764: Add reg defaults for TAS2764_INT_CLK_CFG
+
+From: Hector Martin <marcan@marcan.st>
+
+[ Upstream commit d64c4c3d1c578f98d70db1c5e2535b47adce9d07 ]
+
+Signed-off-by: Hector Martin <marcan@marcan.st>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Link: https://patch.msgid.link/20250208-asoc-tas2764-v1-4-dbab892a69b5@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/tas2764.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c
+index 58315eab492a1..bc0a73fc7ab41 100644
+--- a/sound/soc/codecs/tas2764.c
++++ b/sound/soc/codecs/tas2764.c
+@@ -634,6 +634,7 @@ static const struct reg_default tas2764_reg_defaults[] = {
+ { TAS2764_TDM_CFG2, 0x0a },
+ { TAS2764_TDM_CFG3, 0x10 },
+ { TAS2764_TDM_CFG5, 0x42 },
++ { TAS2764_INT_CLK_CFG, 0x19 },
+ };
+
+ static const struct regmap_range_cfg tas2764_regmap_ranges[] = {
+--
+2.39.5
+
--- /dev/null
+From 7d8f30b329b7c16aa9c9cc587556193499216d3d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Feb 2025 01:03:26 +0000
+Subject: ASoC: tas2764: Mark SW_RESET as volatile
+
+From: Hector Martin <marcan@marcan.st>
+
+[ Upstream commit f37f1748564ac51d32f7588bd7bfc99913ccab8e ]
+
+Since the bit is self-clearing.
+
+Signed-off-by: Hector Martin <marcan@marcan.st>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Link: https://patch.msgid.link/20250208-asoc-tas2764-v1-3-dbab892a69b5@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/tas2764.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c
+index bc0a73fc7ab41..31f94c8cf2844 100644
+--- a/sound/soc/codecs/tas2764.c
++++ b/sound/soc/codecs/tas2764.c
+@@ -652,6 +652,7 @@ static const struct regmap_range_cfg tas2764_regmap_ranges[] = {
+ static bool tas2764_volatile_register(struct device *dev, unsigned int reg)
+ {
+ switch (reg) {
++ case TAS2764_SW_RST:
+ case TAS2764_INT_LTCH0 ... TAS2764_INT_LTCH4:
+ case TAS2764_INT_CLK_CFG:
+ return true;
+--
+2.39.5
+
--- /dev/null
+From aa61e1a3eba50eecb637475e9a88a6e98fb05114 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Feb 2025 01:03:24 +0000
+Subject: ASoC: tas2764: Power up/down amp on mute ops
+
+From: Hector Martin <marcan@marcan.st>
+
+[ Upstream commit 1c3b5f37409682184669457a5bdf761268eafbe5 ]
+
+The ASoC convention is that clocks are removed after codec mute, and
+power up/down is more about top level power management. For these chips,
+the "mute" state still expects a TDM clock, and yanking the clock in
+this state will trigger clock errors. So, do the full
+shutdown<->mute<->active transition on the mute operation, so the amp is
+in software shutdown by the time the clocks are removed.
+
+This fixes TDM clock errors when streams are stopped.
+
+Signed-off-by: Hector Martin <marcan@marcan.st>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Link: https://patch.msgid.link/20250208-asoc-tas2764-v1-1-dbab892a69b5@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/tas2764.c | 51 ++++++++++++++++----------------------
+ 1 file changed, 21 insertions(+), 30 deletions(-)
+
+diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c
+index 31f94c8cf2844..39a7d39536fe6 100644
+--- a/sound/soc/codecs/tas2764.c
++++ b/sound/soc/codecs/tas2764.c
+@@ -180,33 +180,6 @@ static SOC_ENUM_SINGLE_DECL(
+ static const struct snd_kcontrol_new tas2764_asi1_mux =
+ SOC_DAPM_ENUM("ASI1 Source", tas2764_ASI1_src_enum);
+
+-static int tas2764_dac_event(struct snd_soc_dapm_widget *w,
+- struct snd_kcontrol *kcontrol, int event)
+-{
+- struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+- struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
+- int ret;
+-
+- switch (event) {
+- case SND_SOC_DAPM_POST_PMU:
+- tas2764->dac_powered = true;
+- ret = tas2764_update_pwr_ctrl(tas2764);
+- break;
+- case SND_SOC_DAPM_PRE_PMD:
+- tas2764->dac_powered = false;
+- ret = tas2764_update_pwr_ctrl(tas2764);
+- break;
+- default:
+- dev_err(tas2764->dev, "Unsupported event\n");
+- return -EINVAL;
+- }
+-
+- if (ret < 0)
+- return ret;
+-
+- return 0;
+-}
+-
+ static const struct snd_kcontrol_new isense_switch =
+ SOC_DAPM_SINGLE("Switch", TAS2764_PWR_CTRL, TAS2764_ISENSE_POWER_EN, 1, 1);
+ static const struct snd_kcontrol_new vsense_switch =
+@@ -219,8 +192,7 @@ static const struct snd_soc_dapm_widget tas2764_dapm_widgets[] = {
+ 1, &isense_switch),
+ SND_SOC_DAPM_SWITCH("VSENSE", TAS2764_PWR_CTRL, TAS2764_VSENSE_POWER_EN,
+ 1, &vsense_switch),
+- SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2764_dac_event,
+- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
++ SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_OUTPUT("OUT"),
+ SND_SOC_DAPM_SIGGEN("VMON"),
+ SND_SOC_DAPM_SIGGEN("IMON")
+@@ -241,9 +213,28 @@ static int tas2764_mute(struct snd_soc_dai *dai, int mute, int direction)
+ {
+ struct tas2764_priv *tas2764 =
+ snd_soc_component_get_drvdata(dai->component);
++ int ret;
++
++ if (!mute) {
++ tas2764->dac_powered = true;
++ ret = tas2764_update_pwr_ctrl(tas2764);
++ if (ret)
++ return ret;
++ }
+
+ tas2764->unmuted = !mute;
+- return tas2764_update_pwr_ctrl(tas2764);
++ ret = tas2764_update_pwr_ctrl(tas2764);
++ if (ret)
++ return ret;
++
++ if (mute) {
++ tas2764->dac_powered = false;
++ ret = tas2764_update_pwr_ctrl(tas2764);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
+ }
+
+ static int tas2764_set_bitwidth(struct tas2764_priv *tas2764, int bitwidth)
+--
+2.39.5
+
--- /dev/null
+From fb4e36494e0ad2aea2888f66f15e50c0798338ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 19:27:38 +0200
+Subject: auxdisplay: charlcd: Partially revert "Move hwidth and bwidth to
+ struct hd44780_common"
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 09965a142078080fe7807bab0f6f1890cb5987a4 ]
+
+Commit 2545c1c948a6 ("auxdisplay: Move hwidth and bwidth to struct
+hd44780_common") makes charlcd_alloc() argument-less effectively dropping
+the single allocation for the struct charlcd_priv object along with
+the driver specific one. Restore that behaviour here.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/auxdisplay/charlcd.c | 5 +++--
+ drivers/auxdisplay/charlcd.h | 5 +++--
+ drivers/auxdisplay/hd44780.c | 2 +-
+ drivers/auxdisplay/lcd2s.c | 2 +-
+ drivers/auxdisplay/panel.c | 2 +-
+ 5 files changed, 9 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
+index 19b619376d48b..09020bb8ad15f 100644
+--- a/drivers/auxdisplay/charlcd.c
++++ b/drivers/auxdisplay/charlcd.c
+@@ -595,18 +595,19 @@ static int charlcd_init(struct charlcd *lcd)
+ return 0;
+ }
+
+-struct charlcd *charlcd_alloc(void)
++struct charlcd *charlcd_alloc(unsigned int drvdata_size)
+ {
+ struct charlcd_priv *priv;
+ struct charlcd *lcd;
+
+- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++ priv = kzalloc(sizeof(*priv) + drvdata_size, GFP_KERNEL);
+ if (!priv)
+ return NULL;
+
+ priv->esc_seq.len = -1;
+
+ lcd = &priv->lcd;
++ lcd->drvdata = priv->drvdata;
+
+ return lcd;
+ }
+diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
+index 4d4287209d04c..d10b89740bcae 100644
+--- a/drivers/auxdisplay/charlcd.h
++++ b/drivers/auxdisplay/charlcd.h
+@@ -51,7 +51,7 @@ struct charlcd {
+ unsigned long y;
+ } addr;
+
+- void *drvdata;
++ void *drvdata; /* Set by charlcd_alloc() */
+ };
+
+ /**
+@@ -95,7 +95,8 @@ struct charlcd_ops {
+ };
+
+ void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on);
+-struct charlcd *charlcd_alloc(void);
++
++struct charlcd *charlcd_alloc(unsigned int drvdata_size);
+ void charlcd_free(struct charlcd *lcd);
+
+ int charlcd_register(struct charlcd *lcd);
+diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
+index 41807ce363399..9428f951c9bf2 100644
+--- a/drivers/auxdisplay/hd44780.c
++++ b/drivers/auxdisplay/hd44780.c
+@@ -226,7 +226,7 @@ static int hd44780_probe(struct platform_device *pdev)
+ if (!hdc)
+ return -ENOMEM;
+
+- lcd = charlcd_alloc();
++ lcd = charlcd_alloc(0);
+ if (!lcd)
+ goto fail1;
+
+diff --git a/drivers/auxdisplay/lcd2s.c b/drivers/auxdisplay/lcd2s.c
+index 6422be0dfe20e..0ecf6a9469f24 100644
+--- a/drivers/auxdisplay/lcd2s.c
++++ b/drivers/auxdisplay/lcd2s.c
+@@ -307,7 +307,7 @@ static int lcd2s_i2c_probe(struct i2c_client *i2c)
+ if (err < 0)
+ return err;
+
+- lcd = charlcd_alloc();
++ lcd = charlcd_alloc(0);
+ if (!lcd)
+ return -ENOMEM;
+
+diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
+index 6dc8798d01f98..4da142692d55f 100644
+--- a/drivers/auxdisplay/panel.c
++++ b/drivers/auxdisplay/panel.c
+@@ -835,7 +835,7 @@ static void lcd_init(void)
+ if (!hdc)
+ return;
+
+- charlcd = charlcd_alloc();
++ charlcd = charlcd_alloc(0);
+ if (!charlcd) {
+ kfree(hdc);
+ return;
+--
+2.39.5
+
--- /dev/null
+From c8c407a7308fc6c6717eec28820f262285aba85a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Mar 2025 12:05:56 -0400
+Subject: badblocks: Fix a nonsense WARN_ON() which checks whether a u64
+ variable < 0
+
+From: Coly Li <colyli@kernel.org>
+
+[ Upstream commit 7e76336e14de9a2b67af96012ddd46c5676cf340 ]
+
+In _badblocks_check(), there are lines of code like this,
+1246 sectors -= len;
+[snipped]
+1251 WARN_ON(sectors < 0);
+
+The WARN_ON() at line 1257 doesn't make sense because sectors is
+unsigned long long type and never to be <0.
+
+Fix it by checking directly checking whether sectors is less than len.
+
+Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
+Signed-off-by: Coly Li <colyli@kernel.org>
+Reviewed-by: Yu Kuai <yukuai3@huawei.com>
+Link: https://lore.kernel.org/r/20250309160556.42854-1-colyli@kernel.org
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/badblocks.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/block/badblocks.c b/block/badblocks.c
+index db4ec8b9b2a8c..a9709771a1015 100644
+--- a/block/badblocks.c
++++ b/block/badblocks.c
+@@ -1349,14 +1349,15 @@ static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors,
+ len = sectors;
+
+ update_sectors:
++ /* This situation should never happen */
++ WARN_ON(sectors < len);
++
+ s += len;
+ sectors -= len;
+
+ if (sectors > 0)
+ goto re_check;
+
+- WARN_ON(sectors < 0);
+-
+ if (unacked_badblocks > 0)
+ rv = -1;
+ else if (acked_badblocks > 0)
+--
+2.39.5
+
--- /dev/null
+From 173bba6daab32921822b3008c05d6fa0b3d2af98 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Mar 2025 10:29:24 +0800
+Subject: blk-cgroup: improve policy registration error handling
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Chen Linxuan <chenlinxuan@uniontech.com>
+
+[ Upstream commit e1a0202c6bfda24002a3ae2115154fa90104c649 ]
+
+This patch improve the returned error code of blkcg_policy_register().
+
+1. Move the validation check for cpd/pd_alloc_fn and cpd/pd_free_fn
+ function pairs to the start of blkcg_policy_register(). This ensures
+ we immediately return -EINVAL if the function pairs are not correctly
+ provided, rather than returning -ENOSPC after locking and unlocking
+ mutexes unnecessarily.
+
+ Those locks should not contention any problems, as error of policy
+ registration is a super cold path.
+
+2. Return -ENOMEM when cpd_alloc_fn() failed.
+
+Co-authored-by: Wen Tao <wentao@uniontech.com>
+Signed-off-by: Wen Tao <wentao@uniontech.com>
+Signed-off-by: Chen Linxuan <chenlinxuan@uniontech.com>
+Reviewed-by: Michal Koutný <mkoutny@suse.com>
+Acked-by: Tejun Heo <tj@kernel.org>
+Reviewed-by: Yu Kuai <yukuai3@huawei.com>
+Link: https://lore.kernel.org/r/3E333A73B6B6DFC0+20250317022924.150907-1-chenlinxuan@uniontech.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-cgroup.c | 22 ++++++++++++----------
+ 1 file changed, 12 insertions(+), 10 deletions(-)
+
+diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
+index f1cf7f2909f3a..643d6bf66522e 100644
+--- a/block/blk-cgroup.c
++++ b/block/blk-cgroup.c
+@@ -1725,27 +1725,27 @@ int blkcg_policy_register(struct blkcg_policy *pol)
+ struct blkcg *blkcg;
+ int i, ret;
+
++ /*
++ * Make sure cpd/pd_alloc_fn and cpd/pd_free_fn in pairs, and policy
++ * without pd_alloc_fn/pd_free_fn can't be activated.
++ */
++ if ((!pol->cpd_alloc_fn ^ !pol->cpd_free_fn) ||
++ (!pol->pd_alloc_fn ^ !pol->pd_free_fn))
++ return -EINVAL;
++
+ mutex_lock(&blkcg_pol_register_mutex);
+ mutex_lock(&blkcg_pol_mutex);
+
+ /* find an empty slot */
+- ret = -ENOSPC;
+ for (i = 0; i < BLKCG_MAX_POLS; i++)
+ if (!blkcg_policy[i])
+ break;
+ if (i >= BLKCG_MAX_POLS) {
+ pr_warn("blkcg_policy_register: BLKCG_MAX_POLS too small\n");
++ ret = -ENOSPC;
+ goto err_unlock;
+ }
+
+- /*
+- * Make sure cpd/pd_alloc_fn and cpd/pd_free_fn in pairs, and policy
+- * without pd_alloc_fn/pd_free_fn can't be activated.
+- */
+- if ((!pol->cpd_alloc_fn ^ !pol->cpd_free_fn) ||
+- (!pol->pd_alloc_fn ^ !pol->pd_free_fn))
+- goto err_unlock;
+-
+ /* register @pol */
+ pol->plid = i;
+ blkcg_policy[pol->plid] = pol;
+@@ -1756,8 +1756,10 @@ int blkcg_policy_register(struct blkcg_policy *pol)
+ struct blkcg_policy_data *cpd;
+
+ cpd = pol->cpd_alloc_fn(GFP_KERNEL);
+- if (!cpd)
++ if (!cpd) {
++ ret = -ENOMEM;
+ goto err_free_cpds;
++ }
+
+ blkcg->cpd[pol->plid] = cpd;
+ cpd->blkcg = blkcg;
+--
+2.39.5
+
--- /dev/null
+From 543a90e8dc5fd35e43385ae51cc454ce73ff8a9f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Mar 2025 12:31:20 +0800
+Subject: blk-throttle: don't take carryover for prioritized processing of
+ metadata
+
+From: Ming Lei <ming.lei@redhat.com>
+
+[ Upstream commit a9fc8868b350cbf4ff730a4ea9651319cc669516 ]
+
+Commit 29390bb5661d ("blk-throttle: support prioritized processing of metadata")
+takes bytes/ios carryover for prioritized processing of metadata. Turns out
+we can support it by charging it directly without trimming slice, and the
+result is same with carryover.
+
+Cc: Tejun Heo <tj@kernel.org>
+Cc: Josef Bacik <josef@toxicpanda.com>
+Cc: Yu Kuai <yukuai3@huawei.com>
+Signed-off-by: Ming Lei <ming.lei@redhat.com>
+Acked-by: Tejun Heo <tj@kernel.org>
+Link: https://lore.kernel.org/r/20250305043123.3938491-3-ming.lei@redhat.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-throttle.c | 15 +++++----------
+ 1 file changed, 5 insertions(+), 10 deletions(-)
+
+diff --git a/block/blk-throttle.c b/block/blk-throttle.c
+index 2c4192e12efab..6b82fcbd7e774 100644
+--- a/block/blk-throttle.c
++++ b/block/blk-throttle.c
+@@ -1593,13 +1593,6 @@ static bool tg_within_limit(struct throtl_grp *tg, struct bio *bio, bool rw)
+ return tg_may_dispatch(tg, bio, NULL);
+ }
+
+-static void tg_dispatch_in_debt(struct throtl_grp *tg, struct bio *bio, bool rw)
+-{
+- if (!bio_flagged(bio, BIO_BPS_THROTTLED))
+- tg->carryover_bytes[rw] -= throtl_bio_data_size(bio);
+- tg->carryover_ios[rw]--;
+-}
+-
+ bool __blk_throtl_bio(struct bio *bio)
+ {
+ struct request_queue *q = bdev_get_queue(bio->bi_bdev);
+@@ -1636,10 +1629,12 @@ bool __blk_throtl_bio(struct bio *bio)
+ /*
+ * IOs which may cause priority inversions are
+ * dispatched directly, even if they're over limit.
+- * Debts are handled by carryover_bytes/ios while
+- * calculating wait time.
++ *
++ * Charge and dispatch directly, and our throttle
++ * control algorithm is adaptive, and extra IO bytes
++ * will be throttled for paying the debt
+ */
+- tg_dispatch_in_debt(tg, bio, rw);
++ throtl_charge_bio(tg, bio);
+ } else {
+ /* if above limits, break to queue */
+ break;
+--
+2.39.5
+
--- /dev/null
+From 4acfc83afbfd346d4560f66161db62f07c6675ca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Apr 2025 12:53:42 -0700
+Subject: block: fix race between set_blocksize and read paths
+
+From: Darrick J. Wong <djwong@kernel.org>
+
+[ Upstream commit c0e473a0d226479e8e925d5ba93f751d8df628e9 ]
+
+With the new large sector size support, it's now the case that
+set_blocksize can change i_blksize and the folio order in a manner that
+conflicts with a concurrent reader and causes a kernel crash.
+
+Specifically, let's say that udev-worker calls libblkid to detect the
+labels on a block device. The read call can create an order-0 folio to
+read the first 4096 bytes from the disk. But then udev is preempted.
+
+Next, someone tries to mount an 8k-sectorsize filesystem from the same
+block device. The filesystem calls set_blksize, which sets i_blksize to
+8192 and the minimum folio order to 1.
+
+Now udev resumes, still holding the order-0 folio it allocated. It then
+tries to schedule a read bio and do_mpage_readahead tries to create
+bufferheads for the folio. Unfortunately, blocks_per_folio == 0 because
+the page size is 4096 but the blocksize is 8192 so no bufferheads are
+attached and the bh walk never sets bdev. We then submit the bio with a
+NULL block device and crash.
+
+Therefore, truncate the page cache after flushing but before updating
+i_blksize. However, that's not enough -- we also need to lock out file
+IO and page faults during the update. Take both the i_rwsem and the
+invalidate_lock in exclusive mode for invalidations, and in shared mode
+for read/write operations.
+
+I don't know if this is the correct fix, but xfs/259 found it.
+
+Signed-off-by: Darrick J. Wong <djwong@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
+Tested-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
+Link: https://lore.kernel.org/r/174543795699.4139148.2086129139322431423.stgit@frogsfrogsfrogs
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/bdev.c | 17 +++++++++++++++++
+ block/blk-zoned.c | 5 ++++-
+ block/fops.c | 16 ++++++++++++++++
+ block/ioctl.c | 6 ++++++
+ 4 files changed, 43 insertions(+), 1 deletion(-)
+
+diff --git a/block/bdev.c b/block/bdev.c
+index 738e3c8457e7f..e7daca6565ea6 100644
+--- a/block/bdev.c
++++ b/block/bdev.c
+@@ -168,9 +168,26 @@ int set_blocksize(struct file *file, int size)
+
+ /* Don't change the size if it is same as current */
+ if (inode->i_blkbits != blksize_bits(size)) {
++ /*
++ * Flush and truncate the pagecache before we reconfigure the
++ * mapping geometry because folio sizes are variable now. If a
++ * reader has already allocated a folio whose size is smaller
++ * than the new min_order but invokes readahead after the new
++ * min_order becomes visible, readahead will think there are
++ * "zero" blocks per folio and crash. Take the inode and
++ * invalidation locks to avoid racing with
++ * read/write/fallocate.
++ */
++ inode_lock(inode);
++ filemap_invalidate_lock(inode->i_mapping);
++
+ sync_blockdev(bdev);
++ kill_bdev(bdev);
++
+ inode->i_blkbits = blksize_bits(size);
+ kill_bdev(bdev);
++ filemap_invalidate_unlock(inode->i_mapping);
++ inode_unlock(inode);
+ }
+ return 0;
+ }
+diff --git a/block/blk-zoned.c b/block/blk-zoned.c
+index c11db5be25324..414118435240a 100644
+--- a/block/blk-zoned.c
++++ b/block/blk-zoned.c
+@@ -347,6 +347,7 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode,
+ op = REQ_OP_ZONE_RESET;
+
+ /* Invalidate the page cache, including dirty pages. */
++ inode_lock(bdev->bd_mapping->host);
+ filemap_invalidate_lock(bdev->bd_mapping);
+ ret = blkdev_truncate_zone_range(bdev, mode, &zrange);
+ if (ret)
+@@ -368,8 +369,10 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode,
+ ret = blkdev_zone_mgmt(bdev, op, zrange.sector, zrange.nr_sectors);
+
+ fail:
+- if (cmd == BLKRESETZONE)
++ if (cmd == BLKRESETZONE) {
+ filemap_invalidate_unlock(bdev->bd_mapping);
++ inode_unlock(bdev->bd_mapping->host);
++ }
+
+ return ret;
+ }
+diff --git a/block/fops.c b/block/fops.c
+index 43983be5a2b3b..d4b1d942f2700 100644
+--- a/block/fops.c
++++ b/block/fops.c
+@@ -721,7 +721,14 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
+ ret = direct_write_fallback(iocb, from, ret,
+ blkdev_buffered_write(iocb, from));
+ } else {
++ /*
++ * Take i_rwsem and invalidate_lock to avoid racing with
++ * set_blocksize changing i_blkbits/folio order and punching
++ * out the pagecache.
++ */
++ inode_lock_shared(bd_inode);
+ ret = blkdev_buffered_write(iocb, from);
++ inode_unlock_shared(bd_inode);
+ }
+
+ if (ret > 0)
+@@ -732,6 +739,7 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
+
+ static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
+ {
++ struct inode *bd_inode = bdev_file_inode(iocb->ki_filp);
+ struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host);
+ loff_t size = bdev_nr_bytes(bdev);
+ loff_t pos = iocb->ki_pos;
+@@ -768,7 +776,13 @@ static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
+ goto reexpand;
+ }
+
++ /*
++ * Take i_rwsem and invalidate_lock to avoid racing with set_blocksize
++ * changing i_blkbits/folio order and punching out the pagecache.
++ */
++ inode_lock_shared(bd_inode);
+ ret = filemap_read(iocb, to, ret);
++ inode_unlock_shared(bd_inode);
+
+ reexpand:
+ if (unlikely(shorted))
+@@ -811,6 +825,7 @@ static long blkdev_fallocate(struct file *file, int mode, loff_t start,
+ if ((start | len) & (bdev_logical_block_size(bdev) - 1))
+ return -EINVAL;
+
++ inode_lock(inode);
+ filemap_invalidate_lock(inode->i_mapping);
+
+ /*
+@@ -843,6 +858,7 @@ static long blkdev_fallocate(struct file *file, int mode, loff_t start,
+
+ fail:
+ filemap_invalidate_unlock(inode->i_mapping);
++ inode_unlock(inode);
+ return error;
+ }
+
+diff --git a/block/ioctl.c b/block/ioctl.c
+index 6554b728bae6a..919066b4bb49c 100644
+--- a/block/ioctl.c
++++ b/block/ioctl.c
+@@ -141,6 +141,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,
+ if (err)
+ return err;
+
++ inode_lock(bdev->bd_mapping->host);
+ filemap_invalidate_lock(bdev->bd_mapping);
+ err = truncate_bdev_range(bdev, mode, start, start + len - 1);
+ if (err)
+@@ -173,6 +174,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,
+ blk_finish_plug(&plug);
+ fail:
+ filemap_invalidate_unlock(bdev->bd_mapping);
++ inode_unlock(bdev->bd_mapping->host);
+ return err;
+ }
+
+@@ -198,12 +200,14 @@ static int blk_ioctl_secure_erase(struct block_device *bdev, blk_mode_t mode,
+ end > bdev_nr_bytes(bdev))
+ return -EINVAL;
+
++ inode_lock(bdev->bd_mapping->host);
+ filemap_invalidate_lock(bdev->bd_mapping);
+ err = truncate_bdev_range(bdev, mode, start, end - 1);
+ if (!err)
+ err = blkdev_issue_secure_erase(bdev, start >> 9, len >> 9,
+ GFP_KERNEL);
+ filemap_invalidate_unlock(bdev->bd_mapping);
++ inode_unlock(bdev->bd_mapping->host);
+ return err;
+ }
+
+@@ -235,6 +239,7 @@ static int blk_ioctl_zeroout(struct block_device *bdev, blk_mode_t mode,
+ return -EINVAL;
+
+ /* Invalidate the page cache, including dirty pages */
++ inode_lock(bdev->bd_mapping->host);
+ filemap_invalidate_lock(bdev->bd_mapping);
+ err = truncate_bdev_range(bdev, mode, start, end);
+ if (err)
+@@ -245,6 +250,7 @@ static int blk_ioctl_zeroout(struct block_device *bdev, blk_mode_t mode,
+
+ fail:
+ filemap_invalidate_unlock(bdev->bd_mapping);
++ inode_unlock(bdev->bd_mapping->host);
+ return err;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 887f043325f7a555fabed1e9ea0d6f15c458176e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 07:44:31 -0800
+Subject: block: mark bounce buffering as incompatible with integrity
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 5fd0268a8806d35dcaf89139bfcda92be51b2b2f ]
+
+None of the few drivers still using the legacy block layer bounce
+buffering support integrity metadata. Explicitly mark the features as
+incompatible and stop creating the slab and mempool for integrity
+buffers for the bounce bio_set.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Anuj Gupta <anuj20.g@samsung.com>
+Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
+Reviewed-by: Hannes Reinecke <hare@suse.de>
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Link: https://lore.kernel.org/r/20250225154449.422989-2-hch@lst.de
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-settings.c | 5 +++++
+ block/bounce.c | 2 --
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/block/blk-settings.c b/block/blk-settings.c
+index 1e63e3dd54402..7858c92b44834 100644
+--- a/block/blk-settings.c
++++ b/block/blk-settings.c
+@@ -124,6 +124,11 @@ static int blk_validate_integrity_limits(struct queue_limits *lim)
+ return 0;
+ }
+
++ if (lim->features & BLK_FEAT_BOUNCE_HIGH) {
++ pr_warn("no bounce buffer support for integrity metadata\n");
++ return -EINVAL;
++ }
++
+ if (!IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY)) {
+ pr_warn("integrity support disabled.\n");
+ return -EINVAL;
+diff --git a/block/bounce.c b/block/bounce.c
+index 0d898cd5ec497..09a9616cf2094 100644
+--- a/block/bounce.c
++++ b/block/bounce.c
+@@ -41,8 +41,6 @@ static void init_bounce_bioset(void)
+
+ ret = bioset_init(&bounce_bio_set, BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS);
+ BUG_ON(ret);
+- if (bioset_integrity_create(&bounce_bio_set, BIO_POOL_SIZE))
+- BUG_ON(1);
+
+ ret = bioset_init(&bounce_bio_split, BIO_POOL_SIZE, 0, 0);
+ BUG_ON(ret);
+--
+2.39.5
+
--- /dev/null
+From ed32721492581310d5488c1acfd9446b5ebf4fe5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 May 2025 13:27:30 +0200
+Subject: block: only update request sector if needed
+
+From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+
+[ Upstream commit db492e24f9b05547ba12b4783f09c9d943cf42fe ]
+
+In case of a ZONE APPEND write, regardless of native ZONE APPEND or the
+emulation layer in the zone write plugging code, the sector the data got
+written to by the device needs to be updated in the bio.
+
+At the moment, this is done for every native ZONE APPEND write and every
+request that is flagged with 'BIO_ZONE_WRITE_PLUGGING'. But thus
+superfluously updates the sector for regular writes to a zoned block
+device.
+
+Check if a bio is a native ZONE APPEND write or if the bio is flagged as
+'BIO_EMULATES_ZONE_APPEND', meaning the block layer's zone write plugging
+code handles the ZONE APPEND and translates it into a regular write and
+back. Only if one of these two criterion is met, update the sector in the
+bio upon completion.
+
+Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://lore.kernel.org/r/dea089581cb6b777c1cd1500b38ac0b61df4b2d1.1746530748.git.jth@kernel.org
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk.h | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/block/blk.h b/block/blk.h
+index 1426f9c281973..e91012247ff29 100644
+--- a/block/blk.h
++++ b/block/blk.h
+@@ -482,7 +482,8 @@ static inline void blk_zone_update_request_bio(struct request *rq,
+ * the original BIO sector so that blk_zone_write_plug_bio_endio() can
+ * lookup the zone write plug.
+ */
+- if (req_op(rq) == REQ_OP_ZONE_APPEND || bio_zone_write_plugging(bio))
++ if (req_op(rq) == REQ_OP_ZONE_APPEND ||
++ bio_flagged(bio, BIO_EMULATES_ZONE_APPEND))
+ bio->bi_iter.bi_sector = rq->__sector;
+ }
+ void blk_zone_write_plug_bio_endio(struct bio *bio);
+--
+2.39.5
+
--- /dev/null
+From 0922694798881d86948270f468bd2c32e2eac5d7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Mar 2025 18:25:22 -0700
+Subject: Bluetooth: btmtksdio: Prevent enabling interrupts after IRQ handler
+ removal
+
+From: Sean Wang <sean.wang@mediatek.com>
+
+[ Upstream commit 6ac4233afb9a389a7629b7f812395d1d1eca5a83 ]
+
+Ensure interrupts are not re-enabled when the IRQ handler has already been
+removed. This prevents unexpected IRQ handler execution due to stale or
+unhandled interrupts.
+
+Modify btmtksdio_txrx_work to check if bdev->func->irq_handler exists
+before calling sdio_writel to enable interrupts.
+
+Co-developed-by: Pedro Tsai <pedro.tsai@mediatek.com>
+Signed-off-by: Pedro Tsai <pedro.tsai@mediatek.com>
+Co-developed-by: Felix Freimann <felix.freimann@mediatek.com>
+Signed-off-by: Felix Freimann <felix.freimann@mediatek.com>
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btmtksdio.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
+index 11d33cd7b08fc..d4ea1ff07b3e7 100644
+--- a/drivers/bluetooth/btmtksdio.c
++++ b/drivers/bluetooth/btmtksdio.c
+@@ -610,7 +610,8 @@ static void btmtksdio_txrx_work(struct work_struct *work)
+ } while (int_status || time_is_before_jiffies(txrx_timeout));
+
+ /* Enable interrupt */
+- sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL);
++ if (bdev->func->irq_handler)
++ sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL);
+
+ sdio_release_host(bdev->func);
+
+--
+2.39.5
+
--- /dev/null
+From f49055f2f9fc27104bb2b52f58c3c857013e59cc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Mar 2025 03:23:00 -0300
+Subject: Bluetooth: Disable SCO support if READ_VOICE_SETTING is
+ unsupported/broken
+
+From: Pedro Nishiyama <nishiyama.pedro@gmail.com>
+
+[ Upstream commit 14d17c78a4b1660c443bae9d38c814edea506f62 ]
+
+A SCO connection without the proper voice_setting can cause
+the controller to lock up.
+
+Signed-off-by: Pedro Nishiyama <nishiyama.pedro@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/hci_event.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
+index bc5b42fce2b80..8894633403519 100644
+--- a/net/bluetooth/hci_event.c
++++ b/net/bluetooth/hci_event.c
+@@ -932,6 +932,9 @@ static u8 hci_cc_read_buffer_size(struct hci_dev *hdev, void *data,
+ hdev->sco_pkts = 8;
+ }
+
++ if (!read_voice_setting_capable(hdev))
++ hdev->sco_pkts = 0;
++
+ hdev->acl_cnt = hdev->acl_pkts;
+ hdev->sco_cnt = hdev->sco_pkts;
+
+--
+2.39.5
+
--- /dev/null
+From e84b1d73967907862eb93a7fa124a30d6ab12d6f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Mar 2025 11:31:26 -0700
+Subject: bnxt_en: Query FW parameters when the CAPS_CHANGE bit is set
+
+From: shantiprasad shettar <shantiprasad.shettar@broadcom.com>
+
+[ Upstream commit a6c81e32aeacbfd530d576fa401edd506ec966ef ]
+
+Newer FW can set the CAPS_CHANGE flag during ifup if some capabilities
+or configurations have changed. For example, the CoS queue
+configurations may have changed. Support this new flag by treating it
+almost like FW reset. The driver will essentially rediscover all
+features and capabilities, reconfigure all backing store context memory,
+reset everything to default, and reserve all resources.
+
+Reviewed-by: Somnath Kotur <somnath.kotur@broadcom.com>
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: shantiprasad shettar <shantiprasad.shettar@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20250310183129.3154117-5-michael.chan@broadcom.com
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 12b61a6fcda42..2bb1fce350dbb 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -11783,6 +11783,7 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up)
+ struct hwrm_func_drv_if_change_input *req;
+ bool fw_reset = !bp->irq_tbl;
+ bool resc_reinit = false;
++ bool caps_change = false;
+ int rc, retry = 0;
+ u32 flags = 0;
+
+@@ -11838,8 +11839,11 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up)
+ set_bit(BNXT_STATE_ABORT_ERR, &bp->state);
+ return -ENODEV;
+ }
+- if (resc_reinit || fw_reset) {
+- if (fw_reset) {
++ if (flags & FUNC_DRV_IF_CHANGE_RESP_FLAGS_CAPS_CHANGE)
++ caps_change = true;
++
++ if (resc_reinit || fw_reset || caps_change) {
++ if (fw_reset || caps_change) {
+ set_bit(BNXT_STATE_FW_RESET_DET, &bp->state);
+ if (!test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
+ bnxt_ulp_irq_stop(bp);
+--
+2.39.5
+
--- /dev/null
+From a78fe7703a7fc7380a9324b62183215c6e2fed43 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 03:39:14 +0000
+Subject: bonding: report duplicate MAC address in all situations
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Hangbin Liu <liuhangbin@gmail.com>
+
+[ Upstream commit 28d68d396a1cd21591e8c6d74afbde33a7ea107e ]
+
+Normally, a bond uses the MAC address of the first added slave as the bond’s
+MAC address. And the bond will set active slave’s MAC address to bond’s
+address if fail_over_mac is set to none (0) or follow (2).
+
+When the first slave is removed, the bond will still use the removed slave’s
+MAC address, which can lead to a duplicate MAC address and potentially cause
+issues with the switch. To avoid confusion, let's warn the user in all
+situations, including when fail_over_mac is set to 2 or not in active-backup
+mode.
+
+Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
+Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
+Link: https://patch.msgid.link/20250225033914.18617-1-liuhangbin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_main.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 4d73abae503d1..4d2e30f4ee250 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -2542,7 +2542,7 @@ static int __bond_release_one(struct net_device *bond_dev,
+
+ RCU_INIT_POINTER(bond->current_arp_slave, NULL);
+
+- if (!all && (!bond->params.fail_over_mac ||
++ if (!all && (bond->params.fail_over_mac != BOND_FOM_ACTIVE ||
+ BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP)) {
+ if (ether_addr_equal_64bits(bond_dev->dev_addr, slave->perm_hwaddr) &&
+ bond_has_slaves(bond))
+--
+2.39.5
+
--- /dev/null
+From 5bc9d4c7eb5541ed4b893acc8e799a7a9ee6df28 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Mar 2025 07:44:09 -0500
+Subject: book3s64/radix: Fix compile errors when
+ CONFIG_ARCH_WANT_OPTIMIZE_DAX_VMEMMAP=n
+
+From: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+
+[ Upstream commit 29bdc1f1c1df80868fb35bc69d1f073183adc6de ]
+
+Fix compile errors when CONFIG_ARCH_WANT_OPTIMIZE_DAX_VMEMMAP=n
+
+Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Signed-off-by: Donet Tom <donettom@linux.ibm.com>
+Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
+Link: https://patch.msgid.link/8231763344223c193e3452eab0ae8ea966aff466.1741609795.git.donettom@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/mm/book3s64/radix_pgtable.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c
+index 04189689c127e..0d807bf2328d8 100644
+--- a/arch/powerpc/mm/book3s64/radix_pgtable.c
++++ b/arch/powerpc/mm/book3s64/radix_pgtable.c
+@@ -988,7 +988,7 @@ int __meminit radix__vmemmap_create_mapping(unsigned long start,
+ return 0;
+ }
+
+-
++#ifdef CONFIG_ARCH_WANT_OPTIMIZE_DAX_VMEMMAP
+ bool vmemmap_can_optimize(struct vmem_altmap *altmap, struct dev_pagemap *pgmap)
+ {
+ if (radix_enabled())
+@@ -996,6 +996,7 @@ bool vmemmap_can_optimize(struct vmem_altmap *altmap, struct dev_pagemap *pgmap)
+
+ return false;
+ }
++#endif
+
+ int __meminit vmemmap_check_pmd(pmd_t *pmdp, int node,
+ unsigned long addr, unsigned long next)
+--
+2.39.5
+
--- /dev/null
+From c1c2811e9b79c9c8bd90fb733384f88ac68c336e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 15:01:16 -0800
+Subject: bpf: Allow pre-ordering for bpf cgroup progs
+
+From: Yonghong Song <yonghong.song@linux.dev>
+
+[ Upstream commit 4b82b181a26cff8bf7adc3a85a88d121d92edeaf ]
+
+Currently for bpf progs in a cgroup hierarchy, the effective prog array
+is computed from bottom cgroup to upper cgroups (post-ordering). For
+example, the following cgroup hierarchy
+ root cgroup: p1, p2
+ subcgroup: p3, p4
+have BPF_F_ALLOW_MULTI for both cgroup levels.
+The effective cgroup array ordering looks like
+ p3 p4 p1 p2
+and at run time, progs will execute based on that order.
+
+But in some cases, it is desirable to have root prog executes earlier than
+children progs (pre-ordering). For example,
+ - prog p1 intends to collect original pkt dest addresses.
+ - prog p3 will modify original pkt dest addresses to a proxy address for
+ security reason.
+The end result is that prog p1 gets proxy address which is not what it
+wants. Putting p1 to every child cgroup is not desirable either as it
+will duplicate itself in many child cgroups. And this is exactly a use case
+we are encountering in Meta.
+
+To fix this issue, let us introduce a flag BPF_F_PREORDER. If the flag
+is specified at attachment time, the prog has higher priority and the
+ordering with that flag will be from top to bottom (pre-ordering).
+For example, in the above example,
+ root cgroup: p1, p2
+ subcgroup: p3, p4
+Let us say p2 and p4 are marked with BPF_F_PREORDER. The final
+effective array ordering will be
+ p2 p4 p3 p1
+
+Suggested-by: Andrii Nakryiko <andrii@kernel.org>
+Acked-by: Andrii Nakryiko <andrii@kernel.org>
+Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
+Link: https://lore.kernel.org/r/20250224230116.283071-1-yonghong.song@linux.dev
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/bpf-cgroup.h | 1 +
+ include/uapi/linux/bpf.h | 1 +
+ kernel/bpf/cgroup.c | 33 +++++++++++++++++++++++++--------
+ kernel/bpf/syscall.c | 3 ++-
+ tools/include/uapi/linux/bpf.h | 1 +
+ 5 files changed, 30 insertions(+), 9 deletions(-)
+
+diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
+index ce91d9b2acb9f..7e029c82ae45f 100644
+--- a/include/linux/bpf-cgroup.h
++++ b/include/linux/bpf-cgroup.h
+@@ -111,6 +111,7 @@ struct bpf_prog_list {
+ struct bpf_prog *prog;
+ struct bpf_cgroup_link *link;
+ struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE];
++ u32 flags;
+ };
+
+ int cgroup_bpf_inherit(struct cgroup *cgrp);
+diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
+index 4a939c90dc2e4..552fd633f8200 100644
+--- a/include/uapi/linux/bpf.h
++++ b/include/uapi/linux/bpf.h
+@@ -1206,6 +1206,7 @@ enum bpf_perf_event_type {
+ #define BPF_F_BEFORE (1U << 3)
+ #define BPF_F_AFTER (1U << 4)
+ #define BPF_F_ID (1U << 5)
++#define BPF_F_PREORDER (1U << 6)
+ #define BPF_F_LINK BPF_F_LINK /* 1 << 13 */
+
+ /* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the
+diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
+index 025d7e2214aeb..c0d606c40195d 100644
+--- a/kernel/bpf/cgroup.c
++++ b/kernel/bpf/cgroup.c
+@@ -369,7 +369,7 @@ static struct bpf_prog *prog_list_prog(struct bpf_prog_list *pl)
+ /* count number of elements in the list.
+ * it's slow but the list cannot be long
+ */
+-static u32 prog_list_length(struct hlist_head *head)
++static u32 prog_list_length(struct hlist_head *head, int *preorder_cnt)
+ {
+ struct bpf_prog_list *pl;
+ u32 cnt = 0;
+@@ -377,6 +377,8 @@ static u32 prog_list_length(struct hlist_head *head)
+ hlist_for_each_entry(pl, head, node) {
+ if (!prog_list_prog(pl))
+ continue;
++ if (preorder_cnt && (pl->flags & BPF_F_PREORDER))
++ (*preorder_cnt)++;
+ cnt++;
+ }
+ return cnt;
+@@ -400,7 +402,7 @@ static bool hierarchy_allows_attach(struct cgroup *cgrp,
+
+ if (flags & BPF_F_ALLOW_MULTI)
+ return true;
+- cnt = prog_list_length(&p->bpf.progs[atype]);
++ cnt = prog_list_length(&p->bpf.progs[atype], NULL);
+ WARN_ON_ONCE(cnt > 1);
+ if (cnt == 1)
+ return !!(flags & BPF_F_ALLOW_OVERRIDE);
+@@ -423,12 +425,12 @@ static int compute_effective_progs(struct cgroup *cgrp,
+ struct bpf_prog_array *progs;
+ struct bpf_prog_list *pl;
+ struct cgroup *p = cgrp;
+- int cnt = 0;
++ int i, j, cnt = 0, preorder_cnt = 0, fstart, bstart, init_bstart;
+
+ /* count number of effective programs by walking parents */
+ do {
+ if (cnt == 0 || (p->bpf.flags[atype] & BPF_F_ALLOW_MULTI))
+- cnt += prog_list_length(&p->bpf.progs[atype]);
++ cnt += prog_list_length(&p->bpf.progs[atype], &preorder_cnt);
+ p = cgroup_parent(p);
+ } while (p);
+
+@@ -439,20 +441,34 @@ static int compute_effective_progs(struct cgroup *cgrp,
+ /* populate the array with effective progs */
+ cnt = 0;
+ p = cgrp;
++ fstart = preorder_cnt;
++ bstart = preorder_cnt - 1;
+ do {
+ if (cnt > 0 && !(p->bpf.flags[atype] & BPF_F_ALLOW_MULTI))
+ continue;
+
++ init_bstart = bstart;
+ hlist_for_each_entry(pl, &p->bpf.progs[atype], node) {
+ if (!prog_list_prog(pl))
+ continue;
+
+- item = &progs->items[cnt];
++ if (pl->flags & BPF_F_PREORDER) {
++ item = &progs->items[bstart];
++ bstart--;
++ } else {
++ item = &progs->items[fstart];
++ fstart++;
++ }
+ item->prog = prog_list_prog(pl);
+ bpf_cgroup_storages_assign(item->cgroup_storage,
+ pl->storage);
+ cnt++;
+ }
++
++ /* reverse pre-ordering progs at this cgroup level */
++ for (i = bstart + 1, j = init_bstart; i < j; i++, j--)
++ swap(progs->items[i], progs->items[j]);
++
+ } while ((p = cgroup_parent(p)));
+
+ *array = progs;
+@@ -663,7 +679,7 @@ static int __cgroup_bpf_attach(struct cgroup *cgrp,
+ */
+ return -EPERM;
+
+- if (prog_list_length(progs) >= BPF_CGROUP_MAX_PROGS)
++ if (prog_list_length(progs, NULL) >= BPF_CGROUP_MAX_PROGS)
+ return -E2BIG;
+
+ pl = find_attach_entry(progs, prog, link, replace_prog,
+@@ -698,6 +714,7 @@ static int __cgroup_bpf_attach(struct cgroup *cgrp,
+
+ pl->prog = prog;
+ pl->link = link;
++ pl->flags = flags;
+ bpf_cgroup_storages_assign(pl->storage, storage);
+ cgrp->bpf.flags[atype] = saved_flags;
+
+@@ -1073,7 +1090,7 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
+ lockdep_is_held(&cgroup_mutex));
+ total_cnt += bpf_prog_array_length(effective);
+ } else {
+- total_cnt += prog_list_length(&cgrp->bpf.progs[atype]);
++ total_cnt += prog_list_length(&cgrp->bpf.progs[atype], NULL);
+ }
+ }
+
+@@ -1105,7 +1122,7 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
+ u32 id;
+
+ progs = &cgrp->bpf.progs[atype];
+- cnt = min_t(int, prog_list_length(progs), total_cnt);
++ cnt = min_t(int, prog_list_length(progs, NULL), total_cnt);
+ i = 0;
+ hlist_for_each_entry(pl, progs, node) {
+ prog = prog_list_prog(pl);
+diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
+index fc048d3c0e69f..ab74a226e3d6d 100644
+--- a/kernel/bpf/syscall.c
++++ b/kernel/bpf/syscall.c
+@@ -4042,7 +4042,8 @@ static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
+ #define BPF_F_ATTACH_MASK_BASE \
+ (BPF_F_ALLOW_OVERRIDE | \
+ BPF_F_ALLOW_MULTI | \
+- BPF_F_REPLACE)
++ BPF_F_REPLACE | \
++ BPF_F_PREORDER)
+
+ #define BPF_F_ATTACH_MASK_MPROG \
+ (BPF_F_REPLACE | \
+diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
+index 4a939c90dc2e4..552fd633f8200 100644
+--- a/tools/include/uapi/linux/bpf.h
++++ b/tools/include/uapi/linux/bpf.h
+@@ -1206,6 +1206,7 @@ enum bpf_perf_event_type {
+ #define BPF_F_BEFORE (1U << 3)
+ #define BPF_F_AFTER (1U << 4)
+ #define BPF_F_ID (1U << 5)
++#define BPF_F_PREORDER (1U << 6)
+ #define BPF_F_LINK BPF_F_LINK /* 1 << 13 */
+
+ /* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the
+--
+2.39.5
+
--- /dev/null
+From 29fae98d26e9221a3b8ae8fa40dc70157e945c60 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Feb 2025 03:03:52 -0800
+Subject: bpf: copy_verifier_state() should copy 'loop_entry' field
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+[ Upstream commit bbbc02b7445ebfda13e4847f4f1413c6480a85a9 ]
+
+The bpf_verifier_state.loop_entry state should be copied by
+copy_verifier_state(). Otherwise, .loop_entry values from unrelated
+states would poison env->cur_state.
+
+Additionally, env->stack should not contain any states with
+.loop_entry != NULL. The states in env->stack are yet to be verified,
+while .loop_entry is set for states that reached an equivalent state.
+This means that env->cur_state->loop_entry should always be NULL after
+pop_stack().
+
+See the selftest in the next commit for an example of the program that
+is not safe yet is accepted by verifier w/o this fix.
+
+This change has some verification performance impact for selftests:
+
+File Program Insns (A) Insns (B) Insns (DIFF) States (A) States (B) States (DIFF)
+---------------------------------- ---------------------------- --------- --------- -------------- ---------- ---------- -------------
+arena_htab.bpf.o arena_htab_llvm 717 426 -291 (-40.59%) 57 37 -20 (-35.09%)
+arena_htab_asm.bpf.o arena_htab_asm 597 445 -152 (-25.46%) 47 37 -10 (-21.28%)
+arena_list.bpf.o arena_list_del 309 279 -30 (-9.71%) 23 14 -9 (-39.13%)
+iters.bpf.o iter_subprog_check_stacksafe 155 141 -14 (-9.03%) 15 14 -1 (-6.67%)
+iters.bpf.o iter_subprog_iters 1094 1003 -91 (-8.32%) 88 83 -5 (-5.68%)
+iters.bpf.o loop_state_deps2 479 725 +246 (+51.36%) 46 63 +17 (+36.96%)
+kmem_cache_iter.bpf.o open_coded_iter 63 59 -4 (-6.35%) 7 6 -1 (-14.29%)
+verifier_bits_iter.bpf.o max_words 92 84 -8 (-8.70%) 8 7 -1 (-12.50%)
+verifier_iterating_callbacks.bpf.o cond_break2 113 107 -6 (-5.31%) 12 12 +0 (+0.00%)
+
+And significant negative impact for sched_ext:
+
+File Program Insns (A) Insns (B) Insns (DIFF) States (A) States (B) States (DIFF)
+----------------- ---------------------- --------- --------- -------------------- ---------- ---------- ------------------
+bpf.bpf.o lavd_init 7039 14723 +7684 (+109.16%) 490 1139 +649 (+132.45%)
+bpf.bpf.o layered_dispatch 11485 10548 -937 (-8.16%) 848 762 -86 (-10.14%)
+bpf.bpf.o layered_dump 7422 1000001 +992579 (+13373.47%) 681 31178 +30497 (+4478.27%)
+bpf.bpf.o layered_enqueue 16854 71127 +54273 (+322.02%) 1611 6450 +4839 (+300.37%)
+bpf.bpf.o p2dq_dispatch 665 791 +126 (+18.95%) 68 78 +10 (+14.71%)
+bpf.bpf.o p2dq_init 2343 2980 +637 (+27.19%) 201 237 +36 (+17.91%)
+bpf.bpf.o refresh_layer_cpumasks 16487 674760 +658273 (+3992.68%) 1770 65370 +63600 (+3593.22%)
+bpf.bpf.o rusty_select_cpu 1937 40872 +38935 (+2010.07%) 177 3210 +3033 (+1713.56%)
+scx_central.bpf.o central_dispatch 636 2687 +2051 (+322.48%) 63 227 +164 (+260.32%)
+scx_nest.bpf.o nest_init 636 815 +179 (+28.14%) 60 73 +13 (+21.67%)
+scx_qmap.bpf.o qmap_dispatch 2393 3580 +1187 (+49.60%) 196 253 +57 (+29.08%)
+scx_qmap.bpf.o qmap_dump 233 318 +85 (+36.48%) 22 30 +8 (+36.36%)
+scx_qmap.bpf.o qmap_init 16367 17436 +1069 (+6.53%) 603 669 +66 (+10.95%)
+
+Note 'layered_dump' program, which now hits 1M instructions limit.
+This impact would be mitigated in the next patch.
+
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Link: https://lore.kernel.org/r/20250215110411.3236773-2-eddyz87@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 592ee3b47635b..1437108f9d7af 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -1447,6 +1447,7 @@ static int copy_verifier_state(struct bpf_verifier_state *dst_state,
+ dst_state->callback_unroll_depth = src->callback_unroll_depth;
+ dst_state->used_as_loop_entry = src->used_as_loop_entry;
+ dst_state->may_goto_depth = src->may_goto_depth;
++ dst_state->loop_entry = src->loop_entry;
+ for (i = 0; i <= src->curframe; i++) {
+ dst = dst_state->frame[i];
+ if (!dst) {
+@@ -18720,6 +18721,8 @@ static int do_check(struct bpf_verifier_env *env)
+ return err;
+ break;
+ } else {
++ if (WARN_ON_ONCE(env->cur_state->loop_entry))
++ env->cur_state->loop_entry = NULL;
+ do_print_state = true;
+ continue;
+ }
+--
+2.39.5
+
--- /dev/null
+From f6cee4edac9e2662c79efcdca2f38890bf20bedd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Feb 2025 03:03:54 -0800
+Subject: bpf: don't do clean_live_states when state->loop_entry->branches > 0
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+[ Upstream commit 9e63fdb0cbdf3268c86638a8274f4d5549a82820 ]
+
+verifier.c:is_state_visited() uses RANGE_WITHIN states comparison rules
+for cached states that have loop_entry with non-zero branches count
+(meaning that loop_entry's verification is not yet done).
+
+The RANGE_WITHIN rules in regsafe()/stacksafe() require register and
+stack objects types to be identical in current and old states.
+
+verifier.c:clean_live_states() replaces registers and stack spills
+with NOT_INIT/STACK_INVALID marks, if these registers/stack spills are
+not read in any child state. This means that clean_live_states() works
+against loop convergence logic under some conditions. See selftest in
+the next patch for a specific example.
+
+Mitigate this by prohibiting clean_verifier_state() when
+state->loop_entry->branches > 0.
+
+This undoes negative verification performance impact of the
+copy_verifier_state() fix from the previous patch.
+Below is comparison between master and current patch.
+
+selftests:
+
+File Program Insns (A) Insns (B) Insns (DIFF) States (A) States (B) States (DIFF)
+---------------------------------- ---------------------------- --------- --------- --------------- ---------- ---------- --------------
+arena_htab.bpf.o arena_htab_llvm 717 423 -294 (-41.00%) 57 37 -20 (-35.09%)
+arena_htab_asm.bpf.o arena_htab_asm 597 445 -152 (-25.46%) 47 37 -10 (-21.28%)
+arena_list.bpf.o arena_list_add 1493 1822 +329 (+22.04%) 30 37 +7 (+23.33%)
+arena_list.bpf.o arena_list_del 309 261 -48 (-15.53%) 23 15 -8 (-34.78%)
+iters.bpf.o checkpoint_states_deletion 18125 22154 +4029 (+22.23%) 818 918 +100 (+12.22%)
+iters.bpf.o iter_nested_deeply_iters 593 367 -226 (-38.11%) 67 43 -24 (-35.82%)
+iters.bpf.o iter_nested_iters 813 772 -41 (-5.04%) 79 72 -7 (-8.86%)
+iters.bpf.o iter_subprog_check_stacksafe 155 135 -20 (-12.90%) 15 14 -1 (-6.67%)
+iters.bpf.o iter_subprog_iters 1094 808 -286 (-26.14%) 88 68 -20 (-22.73%)
+iters.bpf.o loop_state_deps2 479 356 -123 (-25.68%) 46 35 -11 (-23.91%)
+iters.bpf.o triple_continue 35 31 -4 (-11.43%) 3 3 +0 (+0.00%)
+kmem_cache_iter.bpf.o open_coded_iter 63 59 -4 (-6.35%) 7 6 -1 (-14.29%)
+mptcp_subflow.bpf.o _getsockopt_subflow 501 446 -55 (-10.98%) 25 23 -2 (-8.00%)
+pyperf600_iter.bpf.o on_event 12339 6379 -5960 (-48.30%) 441 286 -155 (-35.15%)
+verifier_bits_iter.bpf.o max_words 92 84 -8 (-8.70%) 8 7 -1 (-12.50%)
+verifier_iterating_callbacks.bpf.o cond_break2 113 192 +79 (+69.91%) 12 21 +9 (+75.00%)
+
+sched_ext:
+
+File Program Insns (A) Insns (B) Insns (DIFF) States (A) States (B) States (DIFF)
+----------------- ---------------------- --------- --------- ----------------- ---------- ---------- ----------------
+bpf.bpf.o layered_dispatch 11485 9039 -2446 (-21.30%) 848 662 -186 (-21.93%)
+bpf.bpf.o layered_dump 7422 5022 -2400 (-32.34%) 681 298 -383 (-56.24%)
+bpf.bpf.o layered_enqueue 16854 13753 -3101 (-18.40%) 1611 1308 -303 (-18.81%)
+bpf.bpf.o layered_init 1000001 5549 -994452 (-99.45%) 84672 523 -84149 (-99.38%)
+bpf.bpf.o layered_runnable 3149 1899 -1250 (-39.70%) 288 151 -137 (-47.57%)
+bpf.bpf.o p2dq_init 2343 1936 -407 (-17.37%) 201 170 -31 (-15.42%)
+bpf.bpf.o refresh_layer_cpumasks 16487 1285 -15202 (-92.21%) 1770 120 -1650 (-93.22%)
+bpf.bpf.o rusty_select_cpu 1937 1386 -551 (-28.45%) 177 125 -52 (-29.38%)
+scx_central.bpf.o central_dispatch 636 600 -36 (-5.66%) 63 59 -4 (-6.35%)
+scx_central.bpf.o central_init 913 632 -281 (-30.78%) 48 39 -9 (-18.75%)
+scx_nest.bpf.o nest_init 636 601 -35 (-5.50%) 60 58 -2 (-3.33%)
+scx_pair.bpf.o pair_dispatch 1000001 1914 -998087 (-99.81%) 58169 142 -58027 (-99.76%)
+scx_qmap.bpf.o qmap_dispatch 2393 2187 -206 (-8.61%) 196 174 -22 (-11.22%)
+scx_qmap.bpf.o qmap_init 16367 22777 +6410 (+39.16%) 603 768 +165 (+27.36%)
+
+'layered_init' and 'pair_dispatch' hit 1M on master, but are verified
+ok with this patch.
+
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Link: https://lore.kernel.org/r/20250215110411.3236773-4-eddyz87@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 294fbafbeba75..592ee3b47635b 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -17282,12 +17282,16 @@ static void clean_verifier_state(struct bpf_verifier_env *env,
+ static void clean_live_states(struct bpf_verifier_env *env, int insn,
+ struct bpf_verifier_state *cur)
+ {
++ struct bpf_verifier_state *loop_entry;
+ struct bpf_verifier_state_list *sl;
+
+ sl = *explored_state(env, insn);
+ while (sl) {
+ if (sl->state.branches)
+ goto next;
++ loop_entry = get_loop_entry(&sl->state);
++ if (loop_entry && loop_entry->branches)
++ goto next;
+ if (sl->state.insn_idx != insn ||
+ !same_callsites(&sl->state, cur))
+ goto next;
+--
+2.39.5
+
--- /dev/null
+From 40448c81395b1cf6bbeae0638d9ea3882c6a4889 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Apr 2025 11:32:51 -0400
+Subject: bpf: fix possible endless loop in BPF map iteration
+
+From: Brandon Kammerdiener <brandon.kammerdiener@intel.com>
+
+[ Upstream commit 75673fda0c557ae26078177dd14d4857afbf128d ]
+
+The _safe variant used here gets the next element before running the callback,
+avoiding the endless loop condition.
+
+Signed-off-by: Brandon Kammerdiener <brandon.kammerdiener@intel.com>
+Link: https://lore.kernel.org/r/20250424153246.141677-2-brandon.kammerdiener@intel.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Acked-by: Hou Tao <houtao1@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/hashtab.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
+index bb3ba8ebaf3d2..570e2f7231443 100644
+--- a/kernel/bpf/hashtab.c
++++ b/kernel/bpf/hashtab.c
+@@ -2223,7 +2223,7 @@ static long bpf_for_each_hash_elem(struct bpf_map *map, bpf_callback_t callback_
+ b = &htab->buckets[i];
+ rcu_read_lock();
+ head = &b->head;
+- hlist_nulls_for_each_entry_rcu(elem, n, head, hash_node) {
++ hlist_nulls_for_each_entry_safe(elem, n, head, hash_node) {
+ key = elem->key;
+ if (is_percpu) {
+ /* current cpu value for percpu map */
+--
+2.39.5
+
--- /dev/null
+From 27d32b043247672b9ee03864ffd7cdc7ef959691 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 15:29:31 +0800
+Subject: bpf: Prevent unsafe access to the sock fields in the BPF timestamping
+ callback
+
+From: Jason Xing <kerneljasonxing@gmail.com>
+
+[ Upstream commit fd93eaffb3f977b23bc0a48d4c8616e654fcf133 ]
+
+The subsequent patch will implement BPF TX timestamping. It will
+call the sockops BPF program without holding the sock lock.
+
+This breaks the current assumption that all sock ops programs will
+hold the sock lock. The sock's fields of the uapi's bpf_sock_ops
+requires this assumption.
+
+To address this, a new "u8 is_locked_tcp_sock;" field is added. This
+patch sets it in the current sock_ops callbacks. The "is_fullsock"
+test is then replaced by the "is_locked_tcp_sock" test during
+sock_ops_convert_ctx_access().
+
+The new TX timestamping callbacks added in the subsequent patch will
+not have this set. This will prevent unsafe access from the new
+timestamping callbacks.
+
+Potentially, we could allow read-only access. However, this would
+require identifying which callback is read-safe-only and also requires
+additional BPF instruction rewrites in the covert_ctx. Since the BPF
+program can always read everything from a socket (e.g., by using
+bpf_core_cast), this patch keeps it simple and disables all read
+and write access to any socket fields through the bpf_sock_ops
+UAPI from the new TX timestamping callback.
+
+Moreover, note that some of the fields in bpf_sock_ops are specific
+to tcp_sock, and sock_ops currently only supports tcp_sock. In
+the future, UDP timestamping will be added, which will also break
+this assumption. The same idea used in this patch will be reused.
+Considering that the current sock_ops only supports tcp_sock, the
+variable is named is_locked_"tcp"_sock.
+
+Signed-off-by: Jason Xing <kerneljasonxing@gmail.com>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Link: https://patch.msgid.link/20250220072940.99994-4-kerneljasonxing@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/filter.h | 1 +
+ include/net/tcp.h | 1 +
+ net/core/filter.c | 8 ++++----
+ net/ipv4/tcp_input.c | 2 ++
+ net/ipv4/tcp_output.c | 2 ++
+ 5 files changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/include/linux/filter.h b/include/linux/filter.h
+index 5118caf8aa1c7..2b1029aeb36ae 100644
+--- a/include/linux/filter.h
++++ b/include/linux/filter.h
+@@ -1506,6 +1506,7 @@ struct bpf_sock_ops_kern {
+ void *skb_data_end;
+ u8 op;
+ u8 is_fullsock;
++ u8 is_locked_tcp_sock;
+ u8 remaining_opt_len;
+ u64 temp; /* temp and everything after is not
+ * initialized to 0 before calling
+diff --git a/include/net/tcp.h b/include/net/tcp.h
+index 3255a199ef60d..c4820759ee0c3 100644
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -2667,6 +2667,7 @@ static inline int tcp_call_bpf(struct sock *sk, int op, u32 nargs, u32 *args)
+ memset(&sock_ops, 0, offsetof(struct bpf_sock_ops_kern, temp));
+ if (sk_fullsock(sk)) {
+ sock_ops.is_fullsock = 1;
++ sock_ops.is_locked_tcp_sock = 1;
+ sock_owned_by_me(sk);
+ }
+
+diff --git a/net/core/filter.c b/net/core/filter.c
+index 99b23fd2f509c..b5de0a192258c 100644
+--- a/net/core/filter.c
++++ b/net/core/filter.c
+@@ -10379,10 +10379,10 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
+ } \
+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \
+ struct bpf_sock_ops_kern, \
+- is_fullsock), \
++ is_locked_tcp_sock), \
+ fullsock_reg, si->src_reg, \
+ offsetof(struct bpf_sock_ops_kern, \
+- is_fullsock)); \
++ is_locked_tcp_sock)); \
+ *insn++ = BPF_JMP_IMM(BPF_JEQ, fullsock_reg, 0, jmp); \
+ if (si->dst_reg == si->src_reg) \
+ *insn++ = BPF_LDX_MEM(BPF_DW, reg, si->src_reg, \
+@@ -10467,10 +10467,10 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
+ temp)); \
+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \
+ struct bpf_sock_ops_kern, \
+- is_fullsock), \
++ is_locked_tcp_sock), \
+ reg, si->dst_reg, \
+ offsetof(struct bpf_sock_ops_kern, \
+- is_fullsock)); \
++ is_locked_tcp_sock)); \
+ *insn++ = BPF_JMP_IMM(BPF_JEQ, reg, 0, 2); \
+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \
+ struct bpf_sock_ops_kern, sk),\
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index d29219e067b7f..f5690085a2ac5 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -169,6 +169,7 @@ static void bpf_skops_parse_hdr(struct sock *sk, struct sk_buff *skb)
+ memset(&sock_ops, 0, offsetof(struct bpf_sock_ops_kern, temp));
+ sock_ops.op = BPF_SOCK_OPS_PARSE_HDR_OPT_CB;
+ sock_ops.is_fullsock = 1;
++ sock_ops.is_locked_tcp_sock = 1;
+ sock_ops.sk = sk;
+ bpf_skops_init_skb(&sock_ops, skb, tcp_hdrlen(skb));
+
+@@ -185,6 +186,7 @@ static void bpf_skops_established(struct sock *sk, int bpf_op,
+ memset(&sock_ops, 0, offsetof(struct bpf_sock_ops_kern, temp));
+ sock_ops.op = bpf_op;
+ sock_ops.is_fullsock = 1;
++ sock_ops.is_locked_tcp_sock = 1;
+ sock_ops.sk = sk;
+ /* sk with TCP_REPAIR_ON does not have skb in tcp_finish_connect */
+ if (skb)
+diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
+index 6d5387811c32a..ca1e52036d4d2 100644
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -525,6 +525,7 @@ static void bpf_skops_hdr_opt_len(struct sock *sk, struct sk_buff *skb,
+ sock_owned_by_me(sk);
+
+ sock_ops.is_fullsock = 1;
++ sock_ops.is_locked_tcp_sock = 1;
+ sock_ops.sk = sk;
+ }
+
+@@ -570,6 +571,7 @@ static void bpf_skops_write_hdr_opt(struct sock *sk, struct sk_buff *skb,
+ sock_owned_by_me(sk);
+
+ sock_ops.is_fullsock = 1;
++ sock_ops.is_locked_tcp_sock = 1;
+ sock_ops.sk = sk;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From e31c9a8c1df23609a36d4a45fb2a02ebc4887c0a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Mar 2025 17:40:37 +0000
+Subject: bpf: Return prog btf_id without capable check
+
+From: Mykyta Yatsenko <yatsenko@meta.com>
+
+[ Upstream commit 07651ccda9ff10a8ca427670cdd06ce2c8e4269c ]
+
+Return prog's btf_id from bpf_prog_get_info_by_fd regardless of capable
+check. This patch enables scenario, when freplace program, running
+from user namespace, requires to query target prog's btf.
+
+Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Acked-by: Yonghong Song <yonghong.song@linux.dev>
+Link: https://lore.kernel.org/bpf/20250317174039.161275-3-mykyta.yatsenko5@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/syscall.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
+index 977c084577565..fc048d3c0e69f 100644
+--- a/kernel/bpf/syscall.c
++++ b/kernel/bpf/syscall.c
+@@ -4606,6 +4606,8 @@ static int bpf_prog_get_info_by_fd(struct file *file,
+ info.recursion_misses = stats.misses;
+
+ info.verified_insns = prog->aux->verified_insns;
++ if (prog->aux->btf)
++ info.btf_id = btf_obj_id(prog->aux->btf);
+
+ if (!bpf_capable()) {
+ info.jited_prog_len = 0;
+@@ -4752,8 +4754,6 @@ static int bpf_prog_get_info_by_fd(struct file *file,
+ }
+ }
+
+- if (prog->aux->btf)
+- info.btf_id = btf_obj_id(prog->aux->btf);
+ info.attach_btf_id = prog->aux->attach_btf_id;
+ if (attach_btf)
+ info.attach_btf_obj_id = btf_obj_id(attach_btf);
+--
+2.39.5
+
--- /dev/null
+From 6465a7ba98f98917e1ccb49e17de662ee9faf316 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 15:35:44 -0800
+Subject: bpf: Search and add kfuncs in struct_ops prologue and epilogue
+
+From: Amery Hung <amery.hung@bytedance.com>
+
+[ Upstream commit d519594ee2445d7cd1ad51f4db4cee58f8213400 ]
+
+Currently, add_kfunc_call() is only invoked once before the main
+verification loop. Therefore, the verifier could not find the
+bpf_kfunc_btf_tab of a new kfunc call which is not seen in user defined
+struct_ops operators but introduced in gen_prologue or gen_epilogue
+during do_misc_fixup(). Fix this by searching kfuncs in the patching
+instruction buffer and add them to prog->aux->kfunc_tab.
+
+Signed-off-by: Amery Hung <amery.hung@bytedance.com>
+Acked-by: Eduard Zingerman <eddyz87@gmail.com>
+Acked-by: Martin KaFai Lau <martin.lau@kernel.org>
+Link: https://lore.kernel.org/r/20250225233545.285481-1-ameryhung@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 25 ++++++++++++++++++++++++-
+ 1 file changed, 24 insertions(+), 1 deletion(-)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 8656208aa4bbb..294fbafbeba75 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -2987,6 +2987,21 @@ bpf_jit_find_kfunc_model(const struct bpf_prog *prog,
+ return res ? &res->func_model : NULL;
+ }
+
++static int add_kfunc_in_insns(struct bpf_verifier_env *env,
++ struct bpf_insn *insn, int cnt)
++{
++ int i, ret;
++
++ for (i = 0; i < cnt; i++, insn++) {
++ if (bpf_pseudo_kfunc_call(insn)) {
++ ret = add_kfunc_call(env, insn->imm, insn->off);
++ if (ret < 0)
++ return ret;
++ }
++ }
++ return 0;
++}
++
+ static int add_subprog_and_kfunc(struct bpf_verifier_env *env)
+ {
+ struct bpf_subprog_info *subprog = env->subprog_info;
+@@ -19768,7 +19783,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
+ {
+ struct bpf_subprog_info *subprogs = env->subprog_info;
+ const struct bpf_verifier_ops *ops = env->ops;
+- int i, cnt, size, ctx_field_size, delta = 0, epilogue_cnt = 0;
++ int i, cnt, size, ctx_field_size, ret, delta = 0, epilogue_cnt = 0;
+ const int insn_cnt = env->prog->len;
+ struct bpf_insn *epilogue_buf = env->epilogue_buf;
+ struct bpf_insn *insn_buf = env->insn_buf;
+@@ -19797,6 +19812,10 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
+ return -ENOMEM;
+ env->prog = new_prog;
+ delta += cnt - 1;
++
++ ret = add_kfunc_in_insns(env, epilogue_buf, epilogue_cnt - 1);
++ if (ret < 0)
++ return ret;
+ }
+ }
+
+@@ -19817,6 +19836,10 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
+
+ env->prog = new_prog;
+ delta += cnt - 1;
++
++ ret = add_kfunc_in_insns(env, insn_buf, cnt - 1);
++ if (ret < 0)
++ return ret;
+ }
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 463b4752c68492c1fe4fa43590caa5c70157801e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jan 2025 14:27:19 -0800
+Subject: bpf: Use kallsyms to find the function name of a struct_ops's stub
+ function
+
+From: Martin KaFai Lau <martin.lau@kernel.org>
+
+[ Upstream commit 12fdd29d5d71d2987a1aec434b704d850a4d7fcb ]
+
+In commit 1611603537a4 ("bpf: Create argument information for nullable arguments."),
+it introduced a "__nullable" tagging at the argument name of a
+stub function. Some background on the commit:
+it requires to tag the stub function instead of directly tagging
+the "ops" of a struct. This is because the btf func_proto of the "ops"
+does not have the argument name and the "__nullable" is tagged at
+the argument name.
+
+To find the stub function of a "ops", it currently relies on a naming
+convention on the stub function "st_ops__ops_name".
+e.g. tcp_congestion_ops__ssthresh. However, the new kernel
+sub system implementing bpf_struct_ops have missed this and
+have been surprised that the "__nullable" and the to-be-landed
+"__ref" tagging was not effective.
+
+One option would be to give a warning whenever the stub function does
+not follow the naming convention, regardless if it requires arg tagging
+or not.
+
+Instead, this patch uses the kallsyms_lookup approach and removes
+the requirement on the naming convention. The st_ops->cfi_stubs has
+all the stub function kernel addresses. kallsyms_lookup() is used to
+lookup the function name. With the function name, BTF can be used to
+find the BTF func_proto. The existing "__nullable" arg name searching
+logic will then fall through.
+
+One notable change is,
+if it failed in kallsyms_lookup or it failed in looking up the stub
+function name from the BTF, the bpf_struct_ops registration will fail.
+This is different from the previous behavior that it silently ignored
+the "st_ops__ops_name" function not found error.
+
+The "tcp_congestion_ops", "sched_ext_ops", and "hid_bpf_ops" can still be
+registered successfully after this patch. There is struct_ops_maybe_null
+selftest to cover the "__nullable" tagging.
+
+Other minor changes:
+1. Removed the "%s__%s" format from the pr_warn because the naming
+ convention is removed.
+2. The existing bpf_struct_ops_supported() is also moved earlier
+ because prepare_arg_info needs to use it to decide if the
+ stub function is NULL before calling the prepare_arg_info.
+
+Cc: Tejun Heo <tj@kernel.org>
+Cc: Benjamin Tissoires <bentiss@kernel.org>
+Cc: Yonghong Song <yonghong.song@linux.dev>
+Cc: Amery Hung <ameryhung@gmail.com>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Reviewed-by: Amery Hung <ameryhung@gmail.com>
+Link: https://lore.kernel.org/r/20250127222719.2544255-1-martin.lau@linux.dev
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/bpf_struct_ops.c | 98 +++++++++++++++++--------------------
+ 1 file changed, 44 insertions(+), 54 deletions(-)
+
+diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c
+index b70d0eef8a284..477947456371a 100644
+--- a/kernel/bpf/bpf_struct_ops.c
++++ b/kernel/bpf/bpf_struct_ops.c
+@@ -147,39 +147,6 @@ void bpf_struct_ops_image_free(void *image)
+ }
+
+ #define MAYBE_NULL_SUFFIX "__nullable"
+-#define MAX_STUB_NAME 128
+-
+-/* Return the type info of a stub function, if it exists.
+- *
+- * The name of a stub function is made up of the name of the struct_ops and
+- * the name of the function pointer member, separated by "__". For example,
+- * if the struct_ops type is named "foo_ops" and the function pointer
+- * member is named "bar", the stub function name would be "foo_ops__bar".
+- */
+-static const struct btf_type *
+-find_stub_func_proto(const struct btf *btf, const char *st_op_name,
+- const char *member_name)
+-{
+- char stub_func_name[MAX_STUB_NAME];
+- const struct btf_type *func_type;
+- s32 btf_id;
+- int cp;
+-
+- cp = snprintf(stub_func_name, MAX_STUB_NAME, "%s__%s",
+- st_op_name, member_name);
+- if (cp >= MAX_STUB_NAME) {
+- pr_warn("Stub function name too long\n");
+- return NULL;
+- }
+- btf_id = btf_find_by_name_kind(btf, stub_func_name, BTF_KIND_FUNC);
+- if (btf_id < 0)
+- return NULL;
+- func_type = btf_type_by_id(btf, btf_id);
+- if (!func_type)
+- return NULL;
+-
+- return btf_type_by_id(btf, func_type->type); /* FUNC_PROTO */
+-}
+
+ /* Prepare argument info for every nullable argument of a member of a
+ * struct_ops type.
+@@ -204,27 +171,42 @@ find_stub_func_proto(const struct btf *btf, const char *st_op_name,
+ static int prepare_arg_info(struct btf *btf,
+ const char *st_ops_name,
+ const char *member_name,
+- const struct btf_type *func_proto,
++ const struct btf_type *func_proto, void *stub_func_addr,
+ struct bpf_struct_ops_arg_info *arg_info)
+ {
+ const struct btf_type *stub_func_proto, *pointed_type;
+ const struct btf_param *stub_args, *args;
+ struct bpf_ctx_arg_aux *info, *info_buf;
+ u32 nargs, arg_no, info_cnt = 0;
++ char ksym[KSYM_SYMBOL_LEN];
++ const char *stub_fname;
++ s32 stub_func_id;
+ u32 arg_btf_id;
+ int offset;
+
+- stub_func_proto = find_stub_func_proto(btf, st_ops_name, member_name);
+- if (!stub_func_proto)
+- return 0;
++ stub_fname = kallsyms_lookup((unsigned long)stub_func_addr, NULL, NULL, NULL, ksym);
++ if (!stub_fname) {
++ pr_warn("Cannot find the stub function name for the %s in struct %s\n",
++ member_name, st_ops_name);
++ return -ENOENT;
++ }
++
++ stub_func_id = btf_find_by_name_kind(btf, stub_fname, BTF_KIND_FUNC);
++ if (stub_func_id < 0) {
++ pr_warn("Cannot find the stub function %s in btf\n", stub_fname);
++ return -ENOENT;
++ }
++
++ stub_func_proto = btf_type_by_id(btf, stub_func_id);
++ stub_func_proto = btf_type_by_id(btf, stub_func_proto->type);
+
+ /* Check if the number of arguments of the stub function is the same
+ * as the number of arguments of the function pointer.
+ */
+ nargs = btf_type_vlen(func_proto);
+ if (nargs != btf_type_vlen(stub_func_proto)) {
+- pr_warn("the number of arguments of the stub function %s__%s does not match the number of arguments of the member %s of struct %s\n",
+- st_ops_name, member_name, member_name, st_ops_name);
++ pr_warn("the number of arguments of the stub function %s does not match the number of arguments of the member %s of struct %s\n",
++ stub_fname, member_name, st_ops_name);
+ return -EINVAL;
+ }
+
+@@ -254,21 +236,21 @@ static int prepare_arg_info(struct btf *btf,
+ &arg_btf_id);
+ if (!pointed_type ||
+ !btf_type_is_struct(pointed_type)) {
+- pr_warn("stub function %s__%s has %s tagging to an unsupported type\n",
+- st_ops_name, member_name, MAYBE_NULL_SUFFIX);
++ pr_warn("stub function %s has %s tagging to an unsupported type\n",
++ stub_fname, MAYBE_NULL_SUFFIX);
+ goto err_out;
+ }
+
+ offset = btf_ctx_arg_offset(btf, func_proto, arg_no);
+ if (offset < 0) {
+- pr_warn("stub function %s__%s has an invalid trampoline ctx offset for arg#%u\n",
+- st_ops_name, member_name, arg_no);
++ pr_warn("stub function %s has an invalid trampoline ctx offset for arg#%u\n",
++ stub_fname, arg_no);
+ goto err_out;
+ }
+
+ if (args[arg_no].type != stub_args[arg_no].type) {
+- pr_warn("arg#%u type in stub function %s__%s does not match with its original func_proto\n",
+- arg_no, st_ops_name, member_name);
++ pr_warn("arg#%u type in stub function %s does not match with its original func_proto\n",
++ arg_no, stub_fname);
+ goto err_out;
+ }
+
+@@ -325,6 +307,13 @@ static bool is_module_member(const struct btf *btf, u32 id)
+ return !strcmp(btf_name_by_offset(btf, t->name_off), "module");
+ }
+
++int bpf_struct_ops_supported(const struct bpf_struct_ops *st_ops, u32 moff)
++{
++ void *func_ptr = *(void **)(st_ops->cfi_stubs + moff);
++
++ return func_ptr ? 0 : -ENOTSUPP;
++}
++
+ int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc,
+ struct btf *btf,
+ struct bpf_verifier_log *log)
+@@ -388,7 +377,10 @@ int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc,
+
+ for_each_member(i, t, member) {
+ const struct btf_type *func_proto;
++ void **stub_func_addr;
++ u32 moff;
+
++ moff = __btf_member_bit_offset(t, member) / 8;
+ mname = btf_name_by_offset(btf, member->name_off);
+ if (!*mname) {
+ pr_warn("anon member in struct %s is not supported\n",
+@@ -414,7 +406,11 @@ int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc,
+ func_proto = btf_type_resolve_func_ptr(btf,
+ member->type,
+ NULL);
+- if (!func_proto)
++
++ /* The member is not a function pointer or
++ * the function pointer is not supported.
++ */
++ if (!func_proto || bpf_struct_ops_supported(st_ops, moff))
+ continue;
+
+ if (btf_distill_func_proto(log, btf,
+@@ -426,8 +422,9 @@ int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc,
+ goto errout;
+ }
+
++ stub_func_addr = *(void **)(st_ops->cfi_stubs + moff);
+ err = prepare_arg_info(btf, st_ops->name, mname,
+- func_proto,
++ func_proto, stub_func_addr,
+ arg_info + i);
+ if (err)
+ goto errout;
+@@ -1153,13 +1150,6 @@ void bpf_struct_ops_put(const void *kdata)
+ bpf_map_put(&st_map->map);
+ }
+
+-int bpf_struct_ops_supported(const struct bpf_struct_ops *st_ops, u32 moff)
+-{
+- void *func_ptr = *(void **)(st_ops->cfi_stubs + moff);
+-
+- return func_ptr ? 0 : -ENOTSUPP;
+-}
+-
+ static bool bpf_struct_ops_valid_to_reg(struct bpf_map *map)
+ {
+ struct bpf_struct_ops_map *st_map = (struct bpf_struct_ops_map *)map;
+--
+2.39.5
+
--- /dev/null
+From bf359f58d92cde41cb5fad7b8d15deee90f7d087 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jan 2025 08:18:57 +0100
+Subject: bpftool: Fix readlink usage in get_fd_type
+
+From: Viktor Malik <vmalik@redhat.com>
+
+[ Upstream commit 0053f7d39d491b6138d7c526876d13885cbb65f1 ]
+
+The `readlink(path, buf, sizeof(buf))` call reads at most sizeof(buf)
+bytes and *does not* append null-terminator to buf. With respect to
+that, fix two pieces in get_fd_type:
+
+1. Change the truncation check to contain sizeof(buf) rather than
+ sizeof(path).
+2. Append null-terminator to buf.
+
+Reported by Coverity.
+
+Signed-off-by: Viktor Malik <vmalik@redhat.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Reviewed-by: Quentin Monnet <qmo@kernel.org>
+Link: https://lore.kernel.org/bpf/20250129071857.75182-1-vmalik@redhat.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/bpf/bpftool/common.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
+index 9b75639434b81..0a764426d9358 100644
+--- a/tools/bpf/bpftool/common.c
++++ b/tools/bpf/bpftool/common.c
+@@ -461,10 +461,11 @@ int get_fd_type(int fd)
+ p_err("can't read link type: %s", strerror(errno));
+ return -1;
+ }
+- if (n == sizeof(path)) {
++ if (n == sizeof(buf)) {
+ p_err("can't read link type: path too long!");
+ return -1;
+ }
++ buf[n] = '\0';
+
+ if (strstr(buf, "bpf-map"))
+ return BPF_OBJ_MAP;
+--
+2.39.5
+
--- /dev/null
+From 73708fd72e7d6928deac67f6deabf69ae3cda28c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Feb 2025 18:37:15 +0100
+Subject: bridge: mdb: Allow replace of a host-joined group
+
+From: Petr Machata <petrm@nvidia.com>
+
+[ Upstream commit d9e9f6d7b7d0c520bb87f19d2cbc57aeeb2091d5 ]
+
+Attempts to replace an MDB group membership of the host itself are
+currently bounced:
+
+ # ip link add name br up type bridge vlan_filtering 1
+ # bridge mdb replace dev br port br grp 239.0.0.1 vid 2
+ # bridge mdb replace dev br port br grp 239.0.0.1 vid 2
+ Error: bridge: Group is already joined by host.
+
+A similar operation done on a member port would succeed. Ignore the check
+for replacement of host group memberships as well.
+
+The bit of code that this enables is br_multicast_host_join(), which, for
+already-joined groups only refreshes the MC group expiration timer, which
+is desirable; and a userspace notification, also desirable.
+
+Change a selftest that exercises this code path from expecting a rejection
+to expecting a pass. The rest of MDB selftests pass without modification.
+
+Signed-off-by: Petr Machata <petrm@nvidia.com>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Acked-by: Nikolay Aleksandrov <razor@blackwall.org>
+Link: https://patch.msgid.link/e5c5188b9787ae806609e7ca3aa2a0a501b9b5c4.1738685648.git.petrm@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bridge/br_mdb.c | 2 +-
+ tools/testing/selftests/net/forwarding/bridge_mdb.sh | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
+index 1a52a0bca086d..7e1ad229e1330 100644
+--- a/net/bridge/br_mdb.c
++++ b/net/bridge/br_mdb.c
+@@ -1040,7 +1040,7 @@ static int br_mdb_add_group(const struct br_mdb_config *cfg,
+
+ /* host join */
+ if (!port) {
+- if (mp->host_joined) {
++ if (mp->host_joined && !(cfg->nlflags & NLM_F_REPLACE)) {
+ NL_SET_ERR_MSG_MOD(extack, "Group is already joined by host");
+ return -EEXIST;
+ }
+diff --git a/tools/testing/selftests/net/forwarding/bridge_mdb.sh b/tools/testing/selftests/net/forwarding/bridge_mdb.sh
+index d9d587454d207..8c1597ebc2d38 100755
+--- a/tools/testing/selftests/net/forwarding/bridge_mdb.sh
++++ b/tools/testing/selftests/net/forwarding/bridge_mdb.sh
+@@ -149,7 +149,7 @@ cfg_test_host_common()
+ check_err $? "Failed to add $name host entry"
+
+ bridge mdb replace dev br0 port br0 grp $grp $state vid 10 &> /dev/null
+- check_fail $? "Managed to replace $name host entry"
++ check_err $? "Failed to replace $name host entry"
+
+ bridge mdb del dev br0 port br0 grp $grp $state vid 10
+ bridge mdb get dev br0 grp $grp vid 10 &> /dev/null
+--
+2.39.5
+
--- /dev/null
+From 97a62c61168c4d1674ec9acc99df3a1423e0b140 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Mar 2025 10:58:46 +0000
+Subject: btrfs: avoid linker error in btrfs_find_create_tree_block()
+
+From: Mark Harmstone <maharmstone@fb.com>
+
+[ Upstream commit 7ef3cbf17d2734ca66c4ed8573be45f4e461e7ee ]
+
+The inline function btrfs_is_testing() is hardcoded to return 0 if
+CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set. Currently we're relying on
+the compiler optimizing out the call to alloc_test_extent_buffer() in
+btrfs_find_create_tree_block(), as it's not been defined (it's behind an
+ #ifdef).
+
+Add a stub version of alloc_test_extent_buffer() to avoid linker errors
+on non-standard optimization levels. This problem was seen on GCC 14
+with -O0 and is helps to see symbols that would be otherwise optimized
+out.
+
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Mark Harmstone <maharmstone@fb.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/extent_io.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
+index e263d4b0546fa..d322cf82783f9 100644
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -2826,10 +2826,10 @@ struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info,
+ return eb;
+ }
+
+-#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
+ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info,
+ u64 start)
+ {
++#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
+ struct extent_buffer *eb, *exists = NULL;
+ int ret;
+
+@@ -2865,8 +2865,11 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info,
+ free_eb:
+ btrfs_release_extent_buffer(eb);
+ return exists;
+-}
++#else
++ /* Stub to avoid linker error when compiled with optimizations turned off. */
++ return NULL;
+ #endif
++}
+
+ static struct extent_buffer *grab_extent_buffer(
+ struct btrfs_fs_info *fs_info, struct page *page)
+--
+2.39.5
+
--- /dev/null
+From 0d0ac8504404233c364e3e313dcda34faa10c3c1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 29 Apr 2025 15:17:50 +0930
+Subject: btrfs: avoid NULL pointer dereference if no valid csum tree
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit f95d186255b319c48a365d47b69bd997fecb674e ]
+
+[BUG]
+When trying read-only scrub on a btrfs with rescue=idatacsums mount
+option, it will crash with the following call trace:
+
+ BUG: kernel NULL pointer dereference, address: 0000000000000208
+ #PF: supervisor read access in kernel mode
+ #PF: error_code(0x0000) - not-present page
+ CPU: 1 UID: 0 PID: 835 Comm: btrfs Tainted: G O 6.15.0-rc3-custom+ #236 PREEMPT(full)
+ Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS unknown 02/02/2022
+ RIP: 0010:btrfs_lookup_csums_bitmap+0x49/0x480 [btrfs]
+ Call Trace:
+ <TASK>
+ scrub_find_fill_first_stripe+0x35b/0x3d0 [btrfs]
+ scrub_simple_mirror+0x175/0x290 [btrfs]
+ scrub_stripe+0x5f7/0x6f0 [btrfs]
+ scrub_chunk+0x9a/0x150 [btrfs]
+ scrub_enumerate_chunks+0x333/0x660 [btrfs]
+ btrfs_scrub_dev+0x23e/0x600 [btrfs]
+ btrfs_ioctl+0x1dcf/0x2f80 [btrfs]
+ __x64_sys_ioctl+0x97/0xc0
+ do_syscall_64+0x4f/0x120
+ entry_SYSCALL_64_after_hwframe+0x76/0x7e
+
+[CAUSE]
+Mount option "rescue=idatacsums" will completely skip loading the csum
+tree, so that any data read will not find any data csum thus we will
+ignore data checksum verification.
+
+Normally call sites utilizing csum tree will check the fs state flag
+NO_DATA_CSUMS bit, but unfortunately scrub does not check that bit at all.
+
+This results in scrub to call btrfs_search_slot() on a NULL pointer
+and triggered above crash.
+
+[FIX]
+Check both extent and csum tree root before doing any tree search.
+
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/scrub.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
+index c73a41b1ad560..d8fcc3eb85c88 100644
+--- a/fs/btrfs/scrub.c
++++ b/fs/btrfs/scrub.c
+@@ -1541,8 +1541,8 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
+ u64 extent_gen;
+ int ret;
+
+- if (unlikely(!extent_root)) {
+- btrfs_err(fs_info, "no valid extent root for scrub");
++ if (unlikely(!extent_root || !csum_root)) {
++ btrfs_err(fs_info, "no valid extent or csum root for scrub");
+ return -EUCLEAN;
+ }
+ memset(stripe->sectors, 0, sizeof(struct scrub_sector_verification) *
+--
+2.39.5
+
--- /dev/null
+From 7be1753bfce931f2dc1a2bd449fad094f29ba9b7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Apr 2025 23:23:29 -0700
+Subject: btrfs: compression: adjust cb->compressed_folios allocation type
+
+From: Kees Cook <kees@kernel.org>
+
+[ Upstream commit 6f9a8ab796c6528d22de3c504c81fce7dde63d8a ]
+
+In preparation for making the kmalloc() family of allocators type aware,
+we need to make sure that the returned type from the allocation matches
+the type of the variable being assigned. (Before, the allocator would
+always return "void *", which can be implicitly cast to any pointer type.)
+
+The assigned type is "struct folio **" but the returned type will be
+"struct page **". These are the same allocation size (pointer size), but
+the types don't match. Adjust the allocation type to match the assignment.
+
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Kees Cook <kees@kernel.org>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/compression.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
+index 40332ab62f101..65d883da86c60 100644
+--- a/fs/btrfs/compression.c
++++ b/fs/btrfs/compression.c
+@@ -606,7 +606,7 @@ void btrfs_submit_compressed_read(struct btrfs_bio *bbio)
+ free_extent_map(em);
+
+ cb->nr_folios = DIV_ROUND_UP(compressed_len, PAGE_SIZE);
+- cb->compressed_folios = kcalloc(cb->nr_folios, sizeof(struct page *), GFP_NOFS);
++ cb->compressed_folios = kcalloc(cb->nr_folios, sizeof(struct folio *), GFP_NOFS);
+ if (!cb->compressed_folios) {
+ ret = BLK_STS_RESOURCE;
+ goto out_free_bio;
+--
+2.39.5
+
--- /dev/null
+From a6767dfe1e61038111aa5ec4f3b85e00f91afd79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Apr 2025 09:25:06 -0400
+Subject: btrfs: correct the order of prelim_ref arguments in btrfs__prelim_ref
+
+From: Goldwyn Rodrigues <rgoldwyn@suse.de>
+
+[ Upstream commit bc7e0975093567f51be8e1bdf4aa5900a3cf0b1e ]
+
+btrfs_prelim_ref() calls the old and new reference variables in the
+incorrect order. This causes a NULL pointer dereference because oldref
+is passed as NULL to trace_btrfs_prelim_ref_insert().
+
+Note, trace_btrfs_prelim_ref_insert() is being called with newref as
+oldref (and oldref as NULL) on purpose in order to print out
+the values of newref.
+
+To reproduce:
+echo 1 > /sys/kernel/debug/tracing/events/btrfs/btrfs_prelim_ref_insert/enable
+
+Perform some writeback operations.
+
+Backtrace:
+BUG: kernel NULL pointer dereference, address: 0000000000000018
+ #PF: supervisor read access in kernel mode
+ #PF: error_code(0x0000) - not-present page
+ PGD 115949067 P4D 115949067 PUD 11594a067 PMD 0
+ Oops: Oops: 0000 [#1] SMP NOPTI
+ CPU: 1 UID: 0 PID: 1188 Comm: fsstress Not tainted 6.15.0-rc2-tester+ #47 PREEMPT(voluntary) 7ca2cef72d5e9c600f0c7718adb6462de8149622
+ Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-2-gc13ff2cd-prebuilt.qemu.org 04/01/2014
+ RIP: 0010:trace_event_raw_event_btrfs__prelim_ref+0x72/0x130
+ Code: e8 43 81 9f ff 48 85 c0 74 78 4d 85 e4 0f 84 8f 00 00 00 49 8b 94 24 c0 06 00 00 48 8b 0a 48 89 48 08 48 8b 52 08 48 89 50 10 <49> 8b 55 18 48 89 50 18 49 8b 55 20 48 89 50 20 41 0f b6 55 28 88
+ RSP: 0018:ffffce44820077a0 EFLAGS: 00010286
+ RAX: ffff8c6b403f9014 RBX: ffff8c6b55825730 RCX: 304994edf9cf506b
+ RDX: d8b11eb7f0fdb699 RSI: ffff8c6b403f9010 RDI: ffff8c6b403f9010
+ RBP: 0000000000000001 R08: 0000000000000001 R09: 0000000000000010
+ R10: 00000000ffffffff R11: 0000000000000000 R12: ffff8c6b4e8fb000
+ R13: 0000000000000000 R14: ffffce44820077a8 R15: ffff8c6b4abd1540
+ FS: 00007f4dc6813740(0000) GS:ffff8c6c1d378000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 0000000000000018 CR3: 000000010eb42000 CR4: 0000000000750ef0
+ PKRU: 55555554
+ Call Trace:
+ <TASK>
+ prelim_ref_insert+0x1c1/0x270
+ find_parent_nodes+0x12a6/0x1ee0
+ ? __entry_text_end+0x101f06/0x101f09
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ btrfs_is_data_extent_shared+0x167/0x640
+ ? fiemap_process_hole+0xd0/0x2c0
+ extent_fiemap+0xa5c/0xbc0
+ ? __entry_text_end+0x101f05/0x101f09
+ btrfs_fiemap+0x7e/0xd0
+ do_vfs_ioctl+0x425/0x9d0
+ __x64_sys_ioctl+0x75/0xc0
+
+Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/trace/events/btrfs.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h
+index af6b3827fb1d0..3b16b0cc1b7a6 100644
+--- a/include/trace/events/btrfs.h
++++ b/include/trace/events/btrfs.h
+@@ -1924,7 +1924,7 @@ DECLARE_EVENT_CLASS(btrfs__prelim_ref,
+ TP_PROTO(const struct btrfs_fs_info *fs_info,
+ const struct prelim_ref *oldref,
+ const struct prelim_ref *newref, u64 tree_size),
+- TP_ARGS(fs_info, newref, oldref, tree_size),
++ TP_ARGS(fs_info, oldref, newref, tree_size),
+
+ TP_STRUCT__entry_btrfs(
+ __field( u64, root_id )
+--
+2.39.5
+
--- /dev/null
+From 499fb5133b1bfeff06af13546a29821a4696157b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Mar 2025 14:25:38 +0000
+Subject: btrfs: fix non-empty delayed iputs list on unmount due to async
+ workers
+
+From: Filipe Manana <fdmanana@suse.com>
+
+[ Upstream commit cda76788f8b0f7de3171100e3164ec1ce702292e ]
+
+At close_ctree() after we have ran delayed iputs either explicitly through
+calling btrfs_run_delayed_iputs() or later during the call to
+btrfs_commit_super() or btrfs_error_commit_super(), we assert that the
+delayed iputs list is empty.
+
+We have (another) race where this assertion might fail because we have
+queued an async write into the fs_info->workers workqueue. Here's how it
+happens:
+
+1) We are submitting a data bio for an inode that is not the data
+ relocation inode, so we call btrfs_wq_submit_bio();
+
+2) btrfs_wq_submit_bio() submits a work for the fs_info->workers queue
+ that will run run_one_async_done();
+
+3) We enter close_ctree(), flush several work queues except
+ fs_info->workers, explicitly run delayed iputs with a call to
+ btrfs_run_delayed_iputs() and then again shortly after by calling
+ btrfs_commit_super() or btrfs_error_commit_super(), which also run
+ delayed iputs;
+
+4) run_one_async_done() is executed in the work queue, and because there
+ was an IO error (bio->bi_status is not 0) it calls btrfs_bio_end_io(),
+ which drops the final reference on the associated ordered extent by
+ calling btrfs_put_ordered_extent() - and that adds a delayed iput for
+ the inode;
+
+5) At close_ctree() we find that after stopping the cleaner and
+ transaction kthreads the delayed iputs list is not empty, failing the
+ following assertion:
+
+ ASSERT(list_empty(&fs_info->delayed_iputs));
+
+Fix this by flushing the fs_info->workers workqueue before running delayed
+iputs at close_ctree().
+
+David reported this when running generic/648, which exercises IO error
+paths by using the DM error table.
+
+Reported-by: David Sterba <dsterba@suse.com>
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/disk-io.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
+index e0e740e4d7c75..147c50ef912ac 100644
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -4282,6 +4282,19 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
+ */
+ btrfs_flush_workqueue(fs_info->delalloc_workers);
+
++ /*
++ * We can have ordered extents getting their last reference dropped from
++ * the fs_info->workers queue because for async writes for data bios we
++ * queue a work for that queue, at btrfs_wq_submit_bio(), that runs
++ * run_one_async_done() which calls btrfs_bio_end_io() in case the bio
++ * has an error, and that later function can do the final
++ * btrfs_put_ordered_extent() on the ordered extent attached to the bio,
++ * which adds a delayed iput for the inode. So we must flush the queue
++ * so that we don't have delayed iputs after committing the current
++ * transaction below and stopping the cleaner and transaction kthreads.
++ */
++ btrfs_flush_workqueue(fs_info->workers);
++
+ /*
+ * When finishing a compressed write bio we schedule a work queue item
+ * to finish an ordered extent - btrfs_finish_compressed_write_work()
+--
+2.39.5
+
--- /dev/null
+From d60927365deef5521d5a7f98a2f5854ea7c8cf78 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Feb 2025 16:12:15 +0000
+Subject: btrfs: get zone unusable bytes while holding lock at
+ btrfs_reclaim_bgs_work()
+
+From: Filipe Manana <fdmanana@suse.com>
+
+[ Upstream commit 1283b8c125a83bf7a7dbe90c33d3472b6d7bf612 ]
+
+At btrfs_reclaim_bgs_work(), we are grabbing a block group's zone unusable
+bytes while not under the protection of the block group's spinlock, so
+this can trigger race reports from KCSAN (or similar tools) since that
+field is typically updated while holding the lock, such as at
+__btrfs_add_free_space_zoned() for example.
+
+Fix this by grabbing the zone unusable bytes while we are still in the
+critical section holding the block group's spinlock, which is right above
+where we are currently grabbing it.
+
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/block-group.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
+index 4423d8b716a58..aa8656c8b7e7e 100644
+--- a/fs/btrfs/block-group.c
++++ b/fs/btrfs/block-group.c
+@@ -1891,6 +1891,17 @@ void btrfs_reclaim_bgs_work(struct work_struct *work)
+ up_write(&space_info->groups_sem);
+ goto next;
+ }
++
++ /*
++ * Cache the zone_unusable value before turning the block group
++ * to read only. As soon as the block group is read only it's
++ * zone_unusable value gets moved to the block group's read-only
++ * bytes and isn't available for calculations anymore. We also
++ * cache it before unlocking the block group, to prevent races
++ * (reports from KCSAN and such tools) with tasks updating it.
++ */
++ zone_unusable = bg->zone_unusable;
++
+ spin_unlock(&bg->lock);
+ spin_unlock(&space_info->lock);
+
+@@ -1907,13 +1918,6 @@ void btrfs_reclaim_bgs_work(struct work_struct *work)
+ goto next;
+ }
+
+- /*
+- * Cache the zone_unusable value before turning the block group
+- * to read only. As soon as the blog group is read only it's
+- * zone_unusable value gets moved to the block group's read-only
+- * bytes and isn't available for calculations anymore.
+- */
+- zone_unusable = bg->zone_unusable;
+ ret = inc_block_group_ro(bg, 0);
+ up_write(&space_info->groups_sem);
+ if (ret < 0)
+--
+2.39.5
+
--- /dev/null
+From 0285d6e40261e744f594dbd7b413300383a5adc9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Apr 2025 12:47:50 -0700
+Subject: btrfs: handle empty eb->folios in num_extent_folios()
+
+From: Boris Burkov <boris@bur.io>
+
+[ Upstream commit d6fe0c69b3aa5c985380b794bdf8e6e9b1811e60 ]
+
+num_extent_folios() unconditionally calls folio_order() on
+eb->folios[0]. If that is NULL this will be a segfault. It is reasonable
+for it to return 0 as the number of folios in the eb when the first
+entry is NULL, so do that instead.
+
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Boris Burkov <boris@bur.io>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/extent_io.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
+index 8a36117ed4532..fcb60837d7dc6 100644
+--- a/fs/btrfs/extent_io.h
++++ b/fs/btrfs/extent_io.h
+@@ -293,6 +293,8 @@ static inline int num_extent_pages(const struct extent_buffer *eb)
+ */
+ static inline int num_extent_folios(const struct extent_buffer *eb)
+ {
++ if (!eb->folios[0])
++ return 0;
+ if (folio_order(eb->folios[0]))
+ return 1;
+ return num_extent_pages(eb);
+--
+2.39.5
+
--- /dev/null
+From 15609bda6a77bad1b2a9dc3b711d3f8851bde40d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Mar 2025 15:01:05 -0800
+Subject: btrfs: make btrfs_discard_workfn() block_group ref explicit
+
+From: Boris Burkov <boris@bur.io>
+
+[ Upstream commit 895c6721d310c036dcfebb5ab845822229fa35eb ]
+
+Currently, the async discard machinery owns a ref to the block_group
+when the block_group is queued on a discard list. However, to handle
+races with discard cancellation and the discard workfn, we have a
+specific logic to detect that the block_group is *currently* running in
+the workfn, to protect the workfn's usage amidst cancellation.
+
+As far as I can tell, this doesn't have any overt bugs (though
+finish_discard_pass() and remove_from_discard_list() racing can have a
+surprising outcome for the caller of remove_from_discard_list() in that
+it is again added at the end).
+
+But it is needlessly complicated to rely on locking and the nullity of
+discard_ctl->block_group. Simplify this significantly by just taking a
+refcount while we are in the workfn and unconditionally drop it in both
+the remove and workfn paths, regardless of if they race.
+
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Boris Burkov <boris@bur.io>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/discard.c | 34 ++++++++++++++++------------------
+ 1 file changed, 16 insertions(+), 18 deletions(-)
+
+diff --git a/fs/btrfs/discard.c b/fs/btrfs/discard.c
+index e9cdc1759dada..de23c4b3515e5 100644
+--- a/fs/btrfs/discard.c
++++ b/fs/btrfs/discard.c
+@@ -168,13 +168,7 @@ static bool remove_from_discard_list(struct btrfs_discard_ctl *discard_ctl,
+ block_group->discard_eligible_time = 0;
+ queued = !list_empty(&block_group->discard_list);
+ list_del_init(&block_group->discard_list);
+- /*
+- * If the block group is currently running in the discard workfn, we
+- * don't want to deref it, since it's still being used by the workfn.
+- * The workfn will notice this case and deref the block group when it is
+- * finished.
+- */
+- if (queued && !running)
++ if (queued)
+ btrfs_put_block_group(block_group);
+
+ spin_unlock(&discard_ctl->lock);
+@@ -273,9 +267,10 @@ static struct btrfs_block_group *peek_discard_list(
+ block_group->discard_cursor = block_group->start;
+ block_group->discard_state = BTRFS_DISCARD_EXTENTS;
+ }
+- discard_ctl->block_group = block_group;
+ }
+ if (block_group) {
++ btrfs_get_block_group(block_group);
++ discard_ctl->block_group = block_group;
+ *discard_state = block_group->discard_state;
+ *discard_index = block_group->discard_index;
+ }
+@@ -506,9 +501,20 @@ static void btrfs_discard_workfn(struct work_struct *work)
+
+ block_group = peek_discard_list(discard_ctl, &discard_state,
+ &discard_index, now);
+- if (!block_group || !btrfs_run_discard_work(discard_ctl))
++ if (!block_group)
+ return;
++ if (!btrfs_run_discard_work(discard_ctl)) {
++ spin_lock(&discard_ctl->lock);
++ btrfs_put_block_group(block_group);
++ discard_ctl->block_group = NULL;
++ spin_unlock(&discard_ctl->lock);
++ return;
++ }
+ if (now < block_group->discard_eligible_time) {
++ spin_lock(&discard_ctl->lock);
++ btrfs_put_block_group(block_group);
++ discard_ctl->block_group = NULL;
++ spin_unlock(&discard_ctl->lock);
+ btrfs_discard_schedule_work(discard_ctl, false);
+ return;
+ }
+@@ -560,15 +566,7 @@ static void btrfs_discard_workfn(struct work_struct *work)
+ spin_lock(&discard_ctl->lock);
+ discard_ctl->prev_discard = trimmed;
+ discard_ctl->prev_discard_time = now;
+- /*
+- * If the block group was removed from the discard list while it was
+- * running in this workfn, then we didn't deref it, since this function
+- * still owned that reference. But we set the discard_ctl->block_group
+- * back to NULL, so we can use that condition to know that now we need
+- * to deref the block_group.
+- */
+- if (discard_ctl->block_group == NULL)
+- btrfs_put_block_group(block_group);
++ btrfs_put_block_group(block_group);
+ discard_ctl->block_group = NULL;
+ __btrfs_discard_schedule_work(discard_ctl, now, false);
+ spin_unlock(&discard_ctl->lock);
+--
+2.39.5
+
--- /dev/null
+From 98504dd74a2688ff63dba6bf1d9f8abc7f0b322e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Nov 2024 19:15:34 +1030
+Subject: btrfs: prevent inline data extents read from touching blocks beyond
+ its range
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit 1a5b5668d711d3d1ef447446beab920826decec3 ]
+
+Currently reading an inline data extent will zero out the remaining
+range in the page.
+
+This is not yet causing problems even for block size < page size
+(subpage) cases because:
+
+1) An inline data extent always starts at file offset 0
+ Meaning at page read, we always read the inline extent first, before
+ any other blocks in the page. Then later blocks are properly read out
+ and re-fill the zeroed out ranges.
+
+2) Currently btrfs will read out the whole page if a buffered write is
+ not page aligned
+ So a page is either fully uptodate at buffered write time (covers the
+ whole page), or we will read out the whole page first.
+ Meaning there is nothing to lose for such an inline extent read.
+
+But it's still not ideal:
+
+- We're zeroing out the page twice
+ Once done by read_inline_extent()/uncompress_inline(), once done by
+ btrfs_do_readpage() for ranges beyond i_size.
+
+- We're touching blocks that don't belong to the inline extent
+ In the incoming patches, we can have a partial uptodate folio, of
+ which some dirty blocks can exist while the page is not fully uptodate:
+
+ The page size is 16K and block size is 4K:
+
+ 0 4K 8K 12K 16K
+ | | |/////////| |
+
+ And range [8K, 12K) is dirtied by a buffered write, the remaining
+ blocks are not uptodate.
+
+ If range [0, 4K) contains an inline data extent, and we try to read
+ the whole page, the current behavior will overwrite range [8K, 12K)
+ with zero and cause data loss.
+
+So to make the behavior more consistent and in preparation for future
+changes, limit the inline data extents read to only zero out the range
+inside the first block, not the whole page.
+
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/inode.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index 0da2611fb9c85..ee8c18d298758 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -6825,6 +6825,7 @@ static noinline int uncompress_inline(struct btrfs_path *path,
+ {
+ int ret;
+ struct extent_buffer *leaf = path->nodes[0];
++ const u32 blocksize = leaf->fs_info->sectorsize;
+ char *tmp;
+ size_t max_size;
+ unsigned long inline_size;
+@@ -6841,7 +6842,7 @@ static noinline int uncompress_inline(struct btrfs_path *path,
+
+ read_extent_buffer(leaf, tmp, ptr, inline_size);
+
+- max_size = min_t(unsigned long, PAGE_SIZE, max_size);
++ max_size = min_t(unsigned long, blocksize, max_size);
+ ret = btrfs_decompress(compress_type, tmp, folio, 0, inline_size,
+ max_size);
+
+@@ -6853,8 +6854,8 @@ static noinline int uncompress_inline(struct btrfs_path *path,
+ * cover that region here.
+ */
+
+- if (max_size < PAGE_SIZE)
+- folio_zero_range(folio, max_size, PAGE_SIZE - max_size);
++ if (max_size < blocksize)
++ folio_zero_range(folio, max_size, blocksize - max_size);
+ kfree(tmp);
+ return ret;
+ }
+@@ -6862,6 +6863,7 @@ static noinline int uncompress_inline(struct btrfs_path *path,
+ static int read_inline_extent(struct btrfs_inode *inode, struct btrfs_path *path,
+ struct folio *folio)
+ {
++ const u32 blocksize = path->nodes[0]->fs_info->sectorsize;
+ struct btrfs_file_extent_item *fi;
+ void *kaddr;
+ size_t copy_size;
+@@ -6876,14 +6878,14 @@ static int read_inline_extent(struct btrfs_inode *inode, struct btrfs_path *path
+ if (btrfs_file_extent_compression(path->nodes[0], fi) != BTRFS_COMPRESS_NONE)
+ return uncompress_inline(path, folio, fi);
+
+- copy_size = min_t(u64, PAGE_SIZE,
++ copy_size = min_t(u64, blocksize,
+ btrfs_file_extent_ram_bytes(path->nodes[0], fi));
+ kaddr = kmap_local_folio(folio, 0);
+ read_extent_buffer(path->nodes[0], kaddr,
+ btrfs_file_extent_inline_start(fi), copy_size);
+ kunmap_local(kaddr);
+- if (copy_size < PAGE_SIZE)
+- folio_zero_range(folio, copy_size, PAGE_SIZE - copy_size);
++ if (copy_size < blocksize)
++ folio_zero_range(folio, copy_size, blocksize - copy_size);
+ return 0;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From a5afc96d757771c992eb3af4629a562ec52ba1dc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 14:30:44 +1030
+Subject: btrfs: properly limit inline data extent according to block size
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit 23019d3e6617a8ec99a8d2f5947aa3dd8a74a1b8 ]
+
+Btrfs utilizes inline data extent for the following cases:
+
+- Regular small files
+- Symlinks
+
+And "btrfs check" detects any file extents that are too large as an
+error.
+
+It's not a problem for 4K block size, but for the incoming smaller
+block sizes (2K), it can cause problems due to bad limits:
+
+- Non-compressed inline data extents
+ We do not allow a non-compressed inline data extent to be as large as
+ block size.
+
+- Symlinks
+ Currently the only real limit on symlinks are 4K, which can be larger
+ than 2K block size.
+
+These will result btrfs-check to report too large file extents.
+
+Fix it by adding proper size checks for the above cases.
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/inode.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index 9ce1270addb04..0da2611fb9c85 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -623,6 +623,10 @@ static bool can_cow_file_range_inline(struct btrfs_inode *inode,
+ if (size > fs_info->sectorsize)
+ return false;
+
++ /* We do not allow a non-compressed extent to be as large as block size. */
++ if (data_len >= fs_info->sectorsize)
++ return false;
++
+ /* We cannot exceed the maximum inline data size. */
+ if (data_len > BTRFS_MAX_INLINE_DATA_SIZE(fs_info))
+ return false;
+@@ -8691,7 +8695,12 @@ static int btrfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
+ struct extent_buffer *leaf;
+
+ name_len = strlen(symname);
+- if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(fs_info))
++ /*
++ * Symlinks utilize uncompressed inline extent data, which should not
++ * reach block size.
++ */
++ if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(fs_info) ||
++ name_len >= fs_info->sectorsize)
+ return -ENAMETOOLONG;
+
+ inode = new_inode(dir->i_sb);
+--
+2.39.5
+
--- /dev/null
+From 71eb805f31af11f3055df78c5b20531f2aeb6f73 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Mar 2025 14:36:10 +1030
+Subject: btrfs: run btrfs_error_commit_super() early
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit df94a342efb451deb0e32b495d1d6cd4bb3a1648 ]
+
+[BUG]
+Even after all the error fixes related the
+"ASSERT(list_empty(&fs_info->delayed_iputs));" in close_ctree(), I can
+still hit it reliably with my experimental 2K block size.
+
+[CAUSE]
+In my case, all the error is triggered after the fs is already in error
+status.
+
+I find the following call trace to be the cause of race:
+
+ Main thread | endio_write_workers
+---------------------------------------------+---------------------------
+close_ctree() |
+|- btrfs_error_commit_super() |
+| |- btrfs_cleanup_transaction() |
+| | |- btrfs_destroy_all_ordered_extents() |
+| | |- btrfs_wait_ordered_roots() |
+| |- btrfs_run_delayed_iputs() |
+| | btrfs_finish_ordered_io()
+| | |- btrfs_put_ordered_extent()
+| | |- btrfs_add_delayed_iput()
+|- ASSERT(list_empty(delayed_iputs)) |
+ !!! Triggered !!!
+
+The root cause is that, btrfs_wait_ordered_roots() only wait for
+ordered extents to finish their IOs, not to wait for them to finish and
+removed.
+
+[FIX]
+Since btrfs_error_commit_super() will flush and wait for all ordered
+extents, it should be executed early, before we start flushing the
+workqueues.
+
+And since btrfs_error_commit_super() now runs early, there is no need to
+run btrfs_run_delayed_iputs() inside it, so just remove the
+btrfs_run_delayed_iputs() call from btrfs_error_commit_super().
+
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/disk-io.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
+index 19e5f8eaae772..e0e740e4d7c75 100644
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -4254,6 +4254,14 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
+ /* clear out the rbtree of defraggable inodes */
+ btrfs_cleanup_defrag_inodes(fs_info);
+
++ /*
++ * Handle the error fs first, as it will flush and wait for all ordered
++ * extents. This will generate delayed iputs, thus we want to handle
++ * it first.
++ */
++ if (unlikely(BTRFS_FS_ERROR(fs_info)))
++ btrfs_error_commit_super(fs_info);
++
+ /*
+ * Wait for any fixup workers to complete.
+ * If we don't wait for them here and they are still running by the time
+@@ -4343,9 +4351,6 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
+ btrfs_err(fs_info, "commit super ret %d", ret);
+ }
+
+- if (BTRFS_FS_ERROR(fs_info))
+- btrfs_error_commit_super(fs_info);
+-
+ kthread_stop(fs_info->transaction_kthread);
+ kthread_stop(fs_info->cleaner_kthread);
+
+@@ -4468,10 +4473,6 @@ static void btrfs_error_commit_super(struct btrfs_fs_info *fs_info)
+ /* cleanup FS via transaction */
+ btrfs_cleanup_transaction(fs_info);
+
+- mutex_lock(&fs_info->cleaner_mutex);
+- btrfs_run_delayed_iputs(fs_info);
+- mutex_unlock(&fs_info->cleaner_mutex);
+-
+ down_write(&fs_info->cleanup_work_sem);
+ up_write(&fs_info->cleanup_work_sem);
+ }
+--
+2.39.5
+
--- /dev/null
+From 5fe70cc5c2e4fd256ad700a1e3a66e23e1964295 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Feb 2025 13:09:25 +0000
+Subject: btrfs: send: return -ENAMETOOLONG when attempting a path that is too
+ long
+
+From: Filipe Manana <fdmanana@suse.com>
+
+[ Upstream commit a77749b3e21813566cea050bbb3414ae74562eba ]
+
+When attempting to build a too long path we are currently returning
+-ENOMEM, which is very odd and misleading. So update fs_path_ensure_buf()
+to return -ENAMETOOLONG instead. Also, while at it, move the WARN_ON()
+into the if statement's expression, as it makes it clear what is being
+tested and also has the effect of adding 'unlikely' to the statement,
+which allows the compiler to generate better code as this condition is
+never expected to happen.
+
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/send.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
+index b1015f383f75e..c843b4aefb8ac 100644
+--- a/fs/btrfs/send.c
++++ b/fs/btrfs/send.c
+@@ -487,10 +487,8 @@ static int fs_path_ensure_buf(struct fs_path *p, int len)
+ if (p->buf_len >= len)
+ return 0;
+
+- if (len > PATH_MAX) {
+- WARN_ON(1);
+- return -ENOMEM;
+- }
++ if (WARN_ON(len > PATH_MAX))
++ return -ENAMETOOLONG;
+
+ path_len = p->end - p->start;
+ old_buf_len = p->buf_len;
+--
+2.39.5
+
--- /dev/null
+From 784d3a559cba3422f75db61667062152c4f14697 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Feb 2025 15:05:00 +0100
+Subject: btrfs: zoned: exit btrfs_can_activate_zone if
+ BTRFS_FS_NEED_ZONE_FINISH is set
+
+From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+
+[ Upstream commit 26b38e28162ef4ceb1e0482299820fbbd7dbcd92 ]
+
+If BTRFS_FS_NEED_ZONE_FINISH is already set for the whole filesystem, exit
+early in btrfs_can_activate_zone(). There's no need to check if
+BTRFS_FS_NEED_ZONE_FINISH needs to be set if it is already set.
+
+Reviewed-by: Naohiro Aota <naohiro.aota@wdc.com>
+Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/zoned.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
+index 2603c9d60fd21..d1167aeb07354 100644
+--- a/fs/btrfs/zoned.c
++++ b/fs/btrfs/zoned.c
+@@ -2326,6 +2326,9 @@ bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices, u64 flags)
+ if (!btrfs_is_zoned(fs_info))
+ return true;
+
++ if (test_bit(BTRFS_FS_NEED_ZONE_FINISH, &fs_info->flags))
++ return false;
++
+ /* Check if there is a device with active zones left */
+ mutex_lock(&fs_info->chunk_mutex);
+ spin_lock(&fs_info->zone_active_bgs_lock);
+--
+2.39.5
+
--- /dev/null
+From 16833ca50849a92a655900498d280237f83d199a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Feb 2025 21:23:14 +0100
+Subject: can: c_can: Use of_property_present() to test existence of DT
+ property
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit ab1bc2290fd8311d49b87c29f1eb123fcb581bee ]
+
+of_property_read_bool() should be used only on boolean properties.
+
+Cc: Rob Herring <robh@kernel.org>
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
+Link: https://patch.msgid.link/20250212-syscon-phandle-args-can-v2-3-ac9a1253396b@linaro.org
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/c_can/c_can_platform.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
+index 399844809bbea..bb6071a758f36 100644
+--- a/drivers/net/can/c_can/c_can_platform.c
++++ b/drivers/net/can/c_can/c_can_platform.c
+@@ -324,7 +324,7 @@ static int c_can_plat_probe(struct platform_device *pdev)
+ /* Check if we need custom RAMINIT via syscon. Mostly for TI
+ * platforms. Only supported with DT boot.
+ */
+- if (np && of_property_read_bool(np, "syscon-raminit")) {
++ if (np && of_property_present(np, "syscon-raminit")) {
+ u32 id;
+ struct c_can_raminit *raminit = &priv->raminit_sys;
+
+--
+2.39.5
+
--- /dev/null
+From e30f4f1ba5422c601eb0c9772b611ee2e7c47305 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Apr 2025 07:30:00 +0000
+Subject: cgroup: Fix compilation issue due to cgroup_mutex not being exported
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: gaoxu <gaoxu2@honor.com>
+
+[ Upstream commit 87c259a7a359e73e6c52c68fcbec79988999b4e6 ]
+
+When adding folio_memcg function call in the zram module for
+Android16-6.12, the following error occurs during compilation:
+ERROR: modpost: "cgroup_mutex" [../soc-repo/zram.ko] undefined!
+
+This error is caused by the indirect call to lockdep_is_held(&cgroup_mutex)
+within folio_memcg. The export setting for cgroup_mutex is controlled by
+the CONFIG_PROVE_RCU macro. If CONFIG_LOCKDEP is enabled while
+CONFIG_PROVE_RCU is not, this compilation error will occur.
+
+To resolve this issue, add a parallel macro CONFIG_LOCKDEP control to
+ensure cgroup_mutex is properly exported when needed.
+
+Signed-off-by: gao xu <gaoxu2@honor.com>
+Acked-by: Michal Koutný <mkoutny@suse.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/cgroup/cgroup.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
+index e63d6f3b00470..62933468aaf46 100644
+--- a/kernel/cgroup/cgroup.c
++++ b/kernel/cgroup/cgroup.c
+@@ -90,7 +90,7 @@
+ DEFINE_MUTEX(cgroup_mutex);
+ DEFINE_SPINLOCK(css_set_lock);
+
+-#ifdef CONFIG_PROVE_RCU
++#if (defined CONFIG_PROVE_RCU || defined CONFIG_LOCKDEP)
+ EXPORT_SYMBOL_GPL(cgroup_mutex);
+ EXPORT_SYMBOL_GPL(css_set_lock);
+ #endif
+--
+2.39.5
+
--- /dev/null
+From 161ad2c6209c7993a7ad833ef24bb548cdab5dc2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Mar 2025 00:13:30 -0700
+Subject: cgroup/rstat: avoid disabling irqs for O(num_cpu)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 0efc297a3c4974dbd609ee36fc6345720b6ca735 ]
+
+cgroup_rstat_flush_locked() grabs the irq safe cgroup_rstat_lock while
+iterating all possible cpus. It only drops the lock if there is
+scheduler or spin lock contention. If neither, then interrupts can be
+disabled for a long time. On large machines this can disable interrupts
+for a long enough time to drop network packets. On 400+ CPU machines
+I've seen interrupt disabled for over 40 msec.
+
+Prevent rstat from disabling interrupts while processing all possible
+cpus. Instead drop and reacquire cgroup_rstat_lock for each cpu. This
+approach was previously discussed in
+https://lore.kernel.org/lkml/ZBz%2FV5a7%2F6PZeM7S@slm.duckdns.org/,
+though this was in the context of an non-irq rstat spin lock.
+
+Benchmark this change with:
+1) a single stat_reader process with 400 threads, each reading a test
+ memcg's memory.stat repeatedly for 10 seconds.
+2) 400 memory hog processes running in the test memcg and repeatedly
+ charging memory until oom killed. Then they repeat charging and oom
+ killing.
+
+v6.14-rc6 with CONFIG_IRQSOFF_TRACER with stat_reader and hogs, finds
+interrupts are disabled by rstat for 45341 usec:
+ # => started at: _raw_spin_lock_irq
+ # => ended at: cgroup_rstat_flush
+ #
+ #
+ # _------=> CPU#
+ # / _-----=> irqs-off/BH-disabled
+ # | / _----=> need-resched
+ # || / _---=> hardirq/softirq
+ # ||| / _--=> preempt-depth
+ # |||| / _-=> migrate-disable
+ # ||||| / delay
+ # cmd pid |||||| time | caller
+ # \ / |||||| \ | /
+ stat_rea-96532 52d.... 0us*: _raw_spin_lock_irq
+ stat_rea-96532 52d.... 45342us : cgroup_rstat_flush
+ stat_rea-96532 52d.... 45342us : tracer_hardirqs_on <-cgroup_rstat_flush
+ stat_rea-96532 52d.... 45343us : <stack trace>
+ => memcg1_stat_format
+ => memory_stat_format
+ => memory_stat_show
+ => seq_read_iter
+ => vfs_read
+ => ksys_read
+ => do_syscall_64
+ => entry_SYSCALL_64_after_hwframe
+
+With this patch the CONFIG_IRQSOFF_TRACER doesn't find rstat to be the
+longest holder. The longest irqs-off holder has irqs disabled for
+4142 usec, a huge reduction from previous 45341 usec rstat finding.
+
+Running stat_reader memory.stat reader for 10 seconds:
+- without memory hogs: 9.84M accesses => 12.7M accesses
+- with memory hogs: 9.46M accesses => 11.1M accesses
+The throughput of memory.stat access improves.
+
+The mode of memory.stat access latency after grouping by of 2 buckets:
+- without memory hogs: 64 usec => 16 usec
+- with memory hogs: 64 usec => 8 usec
+The memory.stat latency improves.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: Greg Thelen <gthelen@google.com>
+Tested-by: Greg Thelen <gthelen@google.com>
+Acked-by: Michal Koutný <mkoutny@suse.com>
+Reviewed-by: Yosry Ahmed <yosry.ahmed@linux.dev>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/cgroup/rstat.c | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+diff --git a/kernel/cgroup/rstat.c b/kernel/cgroup/rstat.c
+index 3e01781aeb7bd..c4ce2f5a9745f 100644
+--- a/kernel/cgroup/rstat.c
++++ b/kernel/cgroup/rstat.c
+@@ -323,13 +323,11 @@ static void cgroup_rstat_flush_locked(struct cgroup *cgrp)
+ rcu_read_unlock();
+ }
+
+- /* play nice and yield if necessary */
+- if (need_resched() || spin_needbreak(&cgroup_rstat_lock)) {
+- __cgroup_rstat_unlock(cgrp, cpu);
+- if (!cond_resched())
+- cpu_relax();
+- __cgroup_rstat_lock(cgrp, cpu);
+- }
++ /* play nice and avoid disabling interrupts for a long time */
++ __cgroup_rstat_unlock(cgrp, cpu);
++ if (!cond_resched())
++ cpu_relax();
++ __cgroup_rstat_lock(cgrp, cpu);
+ }
+ }
+
+--
+2.39.5
+
--- /dev/null
+From f6ed3cfb612385aaa39ac1433c059d824063ef2e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Dec 2024 20:44:23 +0100
+Subject: cifs: Add fallback for SMB2 CREATE without FILE_READ_ATTRIBUTES
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit e255612b5ed9f179abe8196df7c2ba09dd227900 ]
+
+Some operations, like WRITE, does not require FILE_READ_ATTRIBUTES access.
+
+So when FILE_READ_ATTRIBUTES is not explicitly requested for
+smb2_open_file() then first try to do SMB2 CREATE with FILE_READ_ATTRIBUTES
+access (like it was before) and then fallback to SMB2 CREATE without
+FILE_READ_ATTRIBUTES access (less common case).
+
+This change allows to complete WRITE operation to a file when it does not
+grant FILE_READ_ATTRIBUTES permission and its parent directory does not
+grant READ_DATA permission (parent directory READ_DATA is implicit grant of
+child FILE_READ_ATTRIBUTES permission).
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/smb2file.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c
+index e836bc2193ddd..b313c128ffbab 100644
+--- a/fs/smb/client/smb2file.c
++++ b/fs/smb/client/smb2file.c
+@@ -107,16 +107,25 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32
+ int err_buftype = CIFS_NO_BUFFER;
+ struct cifs_fid *fid = oparms->fid;
+ struct network_resiliency_req nr_ioctl_req;
++ bool retry_without_read_attributes = false;
+
+ smb2_path = cifs_convert_path_to_utf16(oparms->path, oparms->cifs_sb);
+ if (smb2_path == NULL)
+ return -ENOMEM;
+
+- oparms->desired_access |= FILE_READ_ATTRIBUTES;
++ if (!(oparms->desired_access & FILE_READ_ATTRIBUTES)) {
++ oparms->desired_access |= FILE_READ_ATTRIBUTES;
++ retry_without_read_attributes = true;
++ }
+ smb2_oplock = SMB2_OPLOCK_LEVEL_BATCH;
+
+ rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov,
+ &err_buftype);
++ if (rc == -EACCES && retry_without_read_attributes) {
++ oparms->desired_access &= ~FILE_READ_ATTRIBUTES;
++ rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov,
++ &err_buftype);
++ }
+ if (rc && data) {
+ struct smb2_hdr *hdr = err_iov.iov_base;
+
+--
+2.39.5
+
--- /dev/null
+From 8fcbf5b2c6acceb99a41813e54be5d9739ee9028 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Feb 2025 17:52:19 +0900
+Subject: cifs: add validation check for the fields in smb_aces
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+[ Upstream commit eeb827f2922eb07ffbf7d53569cc95b38272646f ]
+
+cifs.ko is missing validation check when accessing smb_aces.
+This patch add validation check for the fields in smb_aces.
+
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/cifsacl.c | 17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/fs/smb/client/cifsacl.c b/fs/smb/client/cifsacl.c
+index e36f0e2d7d21e..9a73478e00688 100644
+--- a/fs/smb/client/cifsacl.c
++++ b/fs/smb/client/cifsacl.c
+@@ -811,7 +811,23 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
+ return;
+
+ for (i = 0; i < num_aces; ++i) {
++ if (end_of_acl - acl_base < acl_size)
++ break;
++
+ ppace[i] = (struct smb_ace *) (acl_base + acl_size);
++ acl_base = (char *)ppace[i];
++ acl_size = offsetof(struct smb_ace, sid) +
++ offsetof(struct smb_sid, sub_auth);
++
++ if (end_of_acl - acl_base < acl_size ||
++ ppace[i]->sid.num_subauth == 0 ||
++ ppace[i]->sid.num_subauth > SID_MAX_SUB_AUTHORITIES ||
++ (end_of_acl - acl_base <
++ acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth) ||
++ (le16_to_cpu(ppace[i]->size) <
++ acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth))
++ break;
++
+ #ifdef CONFIG_CIFS_DEBUG2
+ dump_ace(ppace[i], end_of_acl);
+ #endif
+@@ -855,7 +871,6 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
+ (void *)ppace[i],
+ sizeof(struct smb_ace)); */
+
+- acl_base = (char *)ppace[i];
+ acl_size = le16_to_cpu(ppace[i]->size);
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 611b159a9999bc5cebfe7b8616dd5cd3c6d3a7be Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 30 Dec 2024 20:34:18 +0100
+Subject: cifs: Fix and improve cifs_query_path_info() and
+ cifs_query_file_info()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit 1041c117a2c33cdffc4f695ac4b469e9124d24d5 ]
+
+When CAP_NT_SMBS was not negotiated then do not issue CIFSSMBQPathInfo()
+and CIFSSMBQFileInfo() commands. CIFSSMBQPathInfo() is not supported by
+non-NT Win9x SMB server and CIFSSMBQFileInfo() returns from Win9x SMB
+server bogus data in Attributes field (for example lot of files are marked
+as reparse points, even Win9x does not support them and read-only bit is
+not marked for read-only files). Correct information is returned by
+CIFSFindFirst() or SMBQueryInformation() command.
+
+So as a fallback in cifs_query_path_info() function use CIFSFindFirst()
+with SMB_FIND_FILE_FULL_DIRECTORY_INFO level which is supported by both NT
+and non-NT servers and as a last option use SMBQueryInformation() as it was
+before.
+
+And in function cifs_query_file_info() immediately returns -EOPNOTSUPP when
+not communicating with NT server. Client then revalidate inode entry by the
+cifs_query_path_info() call, which is working fine. So fstat() syscall on
+already opened file will receive correct information.
+
+Note that both fallback functions in non-UNICODE mode expands wildcards.
+Therefore those fallback functions cannot be used on paths which contain
+SMB wildcard characters (* ? " > <).
+
+CIFSFindFirst() returns all 4 time attributes as opposite of
+SMBQueryInformation() which returns only one.
+
+With this change it is possible to query all 4 times attributes from Win9x
+server and at the same time, client minimize sending of unsupported
+commands to server.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/smb1ops.c | 103 ++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 95 insertions(+), 8 deletions(-)
+
+diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
+index 71fe5aa52630d..088fd84188b95 100644
+--- a/fs/smb/client/smb1ops.c
++++ b/fs/smb/client/smb1ops.c
+@@ -541,24 +541,104 @@ static int cifs_query_path_info(const unsigned int xid,
+ const char *full_path,
+ struct cifs_open_info_data *data)
+ {
+- int rc;
++ int rc = -EOPNOTSUPP;
+ FILE_ALL_INFO fi = {};
++ struct cifs_search_info search_info = {};
++ bool non_unicode_wildcard = false;
+
+ data->reparse_point = false;
+ data->adjust_tz = false;
+
+- /* could do find first instead but this returns more info */
+- rc = CIFSSMBQPathInfo(xid, tcon, full_path, &fi, 0 /* not legacy */, cifs_sb->local_nls,
+- cifs_remap(cifs_sb));
+ /*
+- * BB optimize code so we do not make the above call when server claims
+- * no NT SMB support and the above call failed at least once - set flag
+- * in tcon or mount.
++ * First try CIFSSMBQPathInfo() function which returns more info
++ * (NumberOfLinks) than CIFSFindFirst() fallback function.
++ * Some servers like Win9x do not support SMB_QUERY_FILE_ALL_INFO over
++ * TRANS2_QUERY_PATH_INFORMATION, but supports it with filehandle over
++ * TRANS2_QUERY_FILE_INFORMATION (function CIFSSMBQFileInfo(). But SMB
++ * Open command on non-NT servers works only for files, does not work
++ * for directories. And moreover Win9x SMB server returns bogus data in
++ * SMB_QUERY_FILE_ALL_INFO Attributes field. So for non-NT servers,
++ * do not even use CIFSSMBQPathInfo() or CIFSSMBQFileInfo() function.
++ */
++ if (tcon->ses->capabilities & CAP_NT_SMBS)
++ rc = CIFSSMBQPathInfo(xid, tcon, full_path, &fi, 0 /* not legacy */,
++ cifs_sb->local_nls, cifs_remap(cifs_sb));
++
++ /*
++ * Non-UNICODE variant of fallback functions below expands wildcards,
++ * so they cannot be used for querying paths with wildcard characters.
+ */
+- if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
++ if (rc && !(tcon->ses->capabilities & CAP_UNICODE) && strpbrk(full_path, "*?\"><"))
++ non_unicode_wildcard = true;
++
++ /*
++ * Then fallback to CIFSFindFirst() which works also with non-NT servers
++ * but does not does not provide NumberOfLinks.
++ */
++ if ((rc == -EOPNOTSUPP || rc == -EINVAL) &&
++ !non_unicode_wildcard) {
++ if (!(tcon->ses->capabilities & tcon->ses->server->vals->cap_nt_find))
++ search_info.info_level = SMB_FIND_FILE_INFO_STANDARD;
++ else
++ search_info.info_level = SMB_FIND_FILE_FULL_DIRECTORY_INFO;
++ rc = CIFSFindFirst(xid, tcon, full_path, cifs_sb, NULL,
++ CIFS_SEARCH_CLOSE_ALWAYS | CIFS_SEARCH_CLOSE_AT_END,
++ &search_info, false);
++ if (rc == 0) {
++ if (!(tcon->ses->capabilities & tcon->ses->server->vals->cap_nt_find)) {
++ FIND_FILE_STANDARD_INFO *di;
++ int offset = tcon->ses->server->timeAdj;
++
++ di = (FIND_FILE_STANDARD_INFO *)search_info.srch_entries_start;
++ fi.CreationTime = cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm(
++ di->CreationDate, di->CreationTime, offset)));
++ fi.LastAccessTime = cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm(
++ di->LastAccessDate, di->LastAccessTime, offset)));
++ fi.LastWriteTime = cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm(
++ di->LastWriteDate, di->LastWriteTime, offset)));
++ fi.ChangeTime = fi.LastWriteTime;
++ fi.Attributes = cpu_to_le32(le16_to_cpu(di->Attributes));
++ fi.AllocationSize = cpu_to_le64(le32_to_cpu(di->AllocationSize));
++ fi.EndOfFile = cpu_to_le64(le32_to_cpu(di->DataSize));
++ } else {
++ FILE_FULL_DIRECTORY_INFO *di;
++
++ di = (FILE_FULL_DIRECTORY_INFO *)search_info.srch_entries_start;
++ fi.CreationTime = di->CreationTime;
++ fi.LastAccessTime = di->LastAccessTime;
++ fi.LastWriteTime = di->LastWriteTime;
++ fi.ChangeTime = di->ChangeTime;
++ fi.Attributes = di->ExtFileAttributes;
++ fi.AllocationSize = di->AllocationSize;
++ fi.EndOfFile = di->EndOfFile;
++ fi.EASize = di->EaSize;
++ }
++ fi.NumberOfLinks = cpu_to_le32(1);
++ fi.DeletePending = 0;
++ fi.Directory = !!(le32_to_cpu(fi.Attributes) & ATTR_DIRECTORY);
++ cifs_buf_release(search_info.ntwrk_buf_start);
++ } else if (!full_path[0]) {
++ /*
++ * CIFSFindFirst() does not work on root path if the
++ * root path was exported on the server from the top
++ * level path (drive letter).
++ */
++ rc = -EOPNOTSUPP;
++ }
++ }
++
++ /*
++ * If everything failed then fallback to the legacy SMB command
++ * SMB_COM_QUERY_INFORMATION which works with all servers, but
++ * provide just few information.
++ */
++ if ((rc == -EOPNOTSUPP || rc == -EINVAL) && !non_unicode_wildcard) {
+ rc = SMBQueryInformation(xid, tcon, full_path, &fi, cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+ data->adjust_tz = true;
++ } else if ((rc == -EOPNOTSUPP || rc == -EINVAL) && non_unicode_wildcard) {
++ /* Path with non-UNICODE wildcard character cannot exist. */
++ rc = -ENOENT;
+ }
+
+ if (!rc) {
+@@ -655,6 +735,13 @@ static int cifs_query_file_info(const unsigned int xid, struct cifs_tcon *tcon,
+ int rc;
+ FILE_ALL_INFO fi = {};
+
++ /*
++ * CIFSSMBQFileInfo() for non-NT servers returns bogus data in
++ * Attributes fields. So do not use this command for non-NT servers.
++ */
++ if (!(tcon->ses->capabilities & CAP_NT_SMBS))
++ return -EOPNOTSUPP;
++
+ if (cfile->symlink_target) {
+ data->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
+ if (!data->symlink_target)
+--
+2.39.5
+
--- /dev/null
+From 7923eac171fea5177740f19ab35a606d732a97ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 30 Dec 2024 21:32:39 +0100
+Subject: cifs: Fix changing times and read-only attr over SMB1
+ smb_set_file_info() function
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit f122121796f91168d0894c2710b8dd71330a34f8 ]
+
+Function CIFSSMBSetPathInfo() is not supported by non-NT servers and
+returns error. Fallback code via open filehandle and CIFSSMBSetFileInfo()
+does not work neither because CIFS_open() works also only on NT server.
+
+Therefore currently the whole smb_set_file_info() function as a SMB1
+callback for the ->set_file_info() does not work with older non-NT SMB
+servers, like Win9x and others.
+
+This change implements fallback code in smb_set_file_info() which will
+works with any server and allows to change time values and also to set or
+clear read-only attributes.
+
+To make existing fallback code via CIFSSMBSetFileInfo() working with also
+non-NT servers, it is needed to change open function from CIFS_open()
+(which is NT specific) to cifs_open_file() which works with any server
+(this is just a open wrapper function which choose the correct open
+function supported by the server).
+
+CIFSSMBSetFileInfo() is working also on non-NT servers, but zero time
+values are not treated specially. So first it is needed to fill all time
+values if some of them are missing, via cifs_query_path_info() call.
+
+There is another issue, opening file in write-mode (needed for changing
+attributes) is not possible when the file has read-only attribute set.
+The only option how to clear read-only attribute is via SMB_COM_SETATTR
+command. And opening directory is not possible neither and here the
+SMB_COM_SETATTR command is the only option how to change attributes.
+And CIFSSMBSetFileInfo() does not honor setting read-only attribute, so
+for setting is also needed to use SMB_COM_SETATTR command.
+
+Existing code in cifs_query_path_info() is already using SMB_COM_GETATTR as
+a fallback code path (function SMBQueryInformation()), so introduce a new
+function SMBSetInformation which will implement SMB_COM_SETATTR command.
+
+My testing showed that Windows XP SMB1 client is also using SMB_COM_SETATTR
+command for setting or clearing read-only attribute against non-NT server.
+So this can prove that this is the correct way how to do it.
+
+With this change it is possible set all 4 time values and all attributes,
+including clearing and setting read-only bit on non-NT SMB servers.
+Tested against Win98 SMB1 server.
+
+This change fixes "touch" command which was failing when called on existing
+file. And fixes also "chmod +w" and "chmod -w" commands which were also
+failing (as they are changing read-only attribute).
+
+Note that this change depends on following change
+"cifs: Improve cifs_query_path_info() and cifs_query_file_info()"
+as it require to query all 4 time attribute values.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/cifspdu.h | 5 +-
+ fs/smb/client/cifsproto.h | 4 ++
+ fs/smb/client/cifssmb.c | 57 +++++++++++++++++++
+ fs/smb/client/smb1ops.c | 112 +++++++++++++++++++++++++++++++++++---
+ 4 files changed, 166 insertions(+), 12 deletions(-)
+
+diff --git a/fs/smb/client/cifspdu.h b/fs/smb/client/cifspdu.h
+index ee78bb6741d62..28f8ca470770d 100644
+--- a/fs/smb/client/cifspdu.h
++++ b/fs/smb/client/cifspdu.h
+@@ -1226,10 +1226,9 @@ typedef struct smb_com_query_information_rsp {
+ typedef struct smb_com_setattr_req {
+ struct smb_hdr hdr; /* wct = 8 */
+ __le16 attr;
+- __le16 time_low;
+- __le16 time_high;
++ __le32 last_write_time;
+ __le16 reserved[5]; /* must be zero */
+- __u16 ByteCount;
++ __le16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII */
+ unsigned char fileName[];
+ } __attribute__((packed)) SETATTR_REQ;
+diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
+index 306386e5c171f..6e938b17875f5 100644
+--- a/fs/smb/client/cifsproto.h
++++ b/fs/smb/client/cifsproto.h
+@@ -396,6 +396,10 @@ extern int CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon);
+ extern int CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ struct kstatfs *FSData);
+
++extern int SMBSetInformation(const unsigned int xid, struct cifs_tcon *tcon,
++ const char *fileName, __le32 attributes, __le64 write_time,
++ const struct nls_table *nls_codepage,
++ struct cifs_sb_info *cifs_sb);
+ extern int CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *fileName, const FILE_BASIC_INFO *data,
+ const struct nls_table *nls_codepage,
+diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c
+index e2a14e25da87c..8667f403a0ab6 100644
+--- a/fs/smb/client/cifssmb.c
++++ b/fs/smb/client/cifssmb.c
+@@ -5199,6 +5199,63 @@ CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
+ return rc;
+ }
+
++int
++SMBSetInformation(const unsigned int xid, struct cifs_tcon *tcon,
++ const char *fileName, __le32 attributes, __le64 write_time,
++ const struct nls_table *nls_codepage,
++ struct cifs_sb_info *cifs_sb)
++{
++ SETATTR_REQ *pSMB;
++ SETATTR_RSP *pSMBr;
++ struct timespec64 ts;
++ int bytes_returned;
++ int name_len;
++ int rc;
++
++ cifs_dbg(FYI, "In %s path %s\n", __func__, fileName);
++
++retry:
++ rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len =
++ cifsConvertToUTF16((__le16 *) pSMB->fileName,
++ fileName, PATH_MAX, nls_codepage,
++ cifs_remap(cifs_sb));
++ name_len++; /* trailing null */
++ name_len *= 2;
++ } else {
++ name_len = copy_path_name(pSMB->fileName, fileName);
++ }
++ /* Only few attributes can be set by this command, others are not accepted by Win9x. */
++ pSMB->attr = cpu_to_le16(le32_to_cpu(attributes) &
++ (ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE));
++ /* Zero write time value (in both NT and SETATTR formats) means to not change it. */
++ if (le64_to_cpu(write_time) != 0) {
++ ts = cifs_NTtimeToUnix(write_time);
++ pSMB->last_write_time = cpu_to_le32(ts.tv_sec);
++ }
++ pSMB->BufferFormat = 0x04;
++ name_len++; /* account for buffer type byte */
++ inc_rfc1001_len(pSMB, (__u16)name_len);
++ pSMB->ByteCount = cpu_to_le16(name_len);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc)
++ cifs_dbg(FYI, "Send error in %s = %d\n", __func__, rc);
++
++ cifs_buf_release(pSMB);
++
++ if (rc == -EAGAIN)
++ goto retry;
++
++ return rc;
++}
++
+ /* Some legacy servers such as NT4 require that the file times be set on
+ an open handle, rather than by pathname - this is awkward due to
+ potential access conflicts on the open, but it is unavoidable for these
+diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
+index 088fd84188b95..0385a514f59e9 100644
+--- a/fs/smb/client/smb1ops.c
++++ b/fs/smb/client/smb1ops.c
+@@ -912,6 +912,9 @@ smb_set_file_info(struct inode *inode, const char *full_path,
+ struct cifs_fid fid;
+ struct cifs_open_parms oparms;
+ struct cifsFileInfo *open_file;
++ FILE_BASIC_INFO new_buf;
++ struct cifs_open_info_data query_data;
++ __le64 write_time = buf->LastWriteTime;
+ struct cifsInodeInfo *cinode = CIFS_I(inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct tcon_link *tlink = NULL;
+@@ -919,20 +922,58 @@ smb_set_file_info(struct inode *inode, const char *full_path,
+
+ /* if the file is already open for write, just use that fileid */
+ open_file = find_writable_file(cinode, FIND_WR_FSUID_ONLY);
++
+ if (open_file) {
+ fid.netfid = open_file->fid.netfid;
+ netpid = open_file->pid;
+ tcon = tlink_tcon(open_file->tlink);
+- goto set_via_filehandle;
++ } else {
++ tlink = cifs_sb_tlink(cifs_sb);
++ if (IS_ERR(tlink)) {
++ rc = PTR_ERR(tlink);
++ tlink = NULL;
++ goto out;
++ }
++ tcon = tlink_tcon(tlink);
+ }
+
+- tlink = cifs_sb_tlink(cifs_sb);
+- if (IS_ERR(tlink)) {
+- rc = PTR_ERR(tlink);
+- tlink = NULL;
+- goto out;
++ /*
++ * Non-NT servers interprets zero time value in SMB_SET_FILE_BASIC_INFO
++ * over TRANS2_SET_FILE_INFORMATION as a valid time value. NT servers
++ * interprets zero time value as do not change existing value on server.
++ * API of ->set_file_info() callback expects that zero time value has
++ * the NT meaning - do not change. Therefore if server is non-NT and
++ * some time values in "buf" are zero, then fetch missing time values.
++ */
++ if (!(tcon->ses->capabilities & CAP_NT_SMBS) &&
++ (!buf->CreationTime || !buf->LastAccessTime ||
++ !buf->LastWriteTime || !buf->ChangeTime)) {
++ rc = cifs_query_path_info(xid, tcon, cifs_sb, full_path, &query_data);
++ if (rc) {
++ if (open_file) {
++ cifsFileInfo_put(open_file);
++ open_file = NULL;
++ }
++ goto out;
++ }
++ /*
++ * Original write_time from buf->LastWriteTime is preserved
++ * as SMBSetInformation() interprets zero as do not change.
++ */
++ new_buf = *buf;
++ buf = &new_buf;
++ if (!buf->CreationTime)
++ buf->CreationTime = query_data.fi.CreationTime;
++ if (!buf->LastAccessTime)
++ buf->LastAccessTime = query_data.fi.LastAccessTime;
++ if (!buf->LastWriteTime)
++ buf->LastWriteTime = query_data.fi.LastWriteTime;
++ if (!buf->ChangeTime)
++ buf->ChangeTime = query_data.fi.ChangeTime;
+ }
+- tcon = tlink_tcon(tlink);
++
++ if (open_file)
++ goto set_via_filehandle;
+
+ rc = CIFSSMBSetPathInfo(xid, tcon, full_path, buf, cifs_sb->local_nls,
+ cifs_sb);
+@@ -953,8 +994,45 @@ smb_set_file_info(struct inode *inode, const char *full_path,
+ .fid = &fid,
+ };
+
+- cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n");
+- rc = CIFS_open(xid, &oparms, &oplock, NULL);
++ if (S_ISDIR(inode->i_mode) && !(tcon->ses->capabilities & CAP_NT_SMBS)) {
++ /* Opening directory path is not possible on non-NT servers. */
++ rc = -EOPNOTSUPP;
++ } else {
++ /*
++ * Use cifs_open_file() instead of CIFS_open() as the
++ * cifs_open_file() selects the correct function which
++ * works also on non-NT servers.
++ */
++ rc = cifs_open_file(xid, &oparms, &oplock, NULL);
++ /*
++ * Opening path for writing on non-NT servers is not
++ * possible when the read-only attribute is already set.
++ * Non-NT server in this case returns -EACCES. For those
++ * servers the only possible way how to clear the read-only
++ * bit is via SMB_COM_SETATTR command.
++ */
++ if (rc == -EACCES &&
++ (cinode->cifsAttrs & ATTR_READONLY) &&
++ le32_to_cpu(buf->Attributes) != 0 && /* 0 = do not change attrs */
++ !(le32_to_cpu(buf->Attributes) & ATTR_READONLY) &&
++ !(tcon->ses->capabilities & CAP_NT_SMBS))
++ rc = -EOPNOTSUPP;
++ }
++
++ /* Fallback to SMB_COM_SETATTR command when absolutelty needed. */
++ if (rc == -EOPNOTSUPP) {
++ cifs_dbg(FYI, "calling SetInformation since SetPathInfo for attrs/times not supported by this server\n");
++ rc = SMBSetInformation(xid, tcon, full_path,
++ buf->Attributes != 0 ? buf->Attributes : cpu_to_le32(cinode->cifsAttrs),
++ write_time,
++ cifs_sb->local_nls, cifs_sb);
++ if (rc == 0)
++ cinode->cifsAttrs = le32_to_cpu(buf->Attributes);
++ else
++ rc = -EACCES;
++ goto out;
++ }
++
+ if (rc != 0) {
+ if (rc == -EIO)
+ rc = -EINVAL;
+@@ -962,6 +1040,7 @@ smb_set_file_info(struct inode *inode, const char *full_path,
+ }
+
+ netpid = current->tgid;
++ cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for attrs/times not supported by this server\n");
+
+ set_via_filehandle:
+ rc = CIFSSMBSetFileInfo(xid, tcon, buf, fid.netfid, netpid);
+@@ -972,6 +1051,21 @@ smb_set_file_info(struct inode *inode, const char *full_path,
+ CIFSSMBClose(xid, tcon, fid.netfid);
+ else
+ cifsFileInfo_put(open_file);
++
++ /*
++ * Setting the read-only bit is not honered on non-NT servers when done
++ * via open-semantics. So for setting it, use SMB_COM_SETATTR command.
++ * This command works only after the file is closed, so use it only when
++ * operation was called without the filehandle.
++ */
++ if (open_file == NULL &&
++ !(tcon->ses->capabilities & CAP_NT_SMBS) &&
++ le32_to_cpu(buf->Attributes) & ATTR_READONLY) {
++ SMBSetInformation(xid, tcon, full_path,
++ buf->Attributes,
++ 0 /* do not change write time */,
++ cifs_sb->local_nls, cifs_sb);
++ }
+ out:
+ if (tlink != NULL)
+ cifs_put_tlink(tlink);
+--
+2.39.5
+
--- /dev/null
+From eee4f7efec7521a621fe6881ba170ab06dc68dae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Oct 2024 22:46:20 +0100
+Subject: cifs: Fix establishing NetBIOS session for SMB2+ connection
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit 781802aa5a5950f99899f13ff9d760f5db81d36d ]
+
+Function ip_rfc1001_connect() which establish NetBIOS session for SMB
+connections, currently uses smb_send() function for sending NetBIOS Session
+Request packet. This function expects that the passed buffer is SMB packet
+and for SMB2+ connections it mangles packet header, which breaks prepared
+NetBIOS Session Request packet. Result is that this function send garbage
+packet for SMB2+ connection, which SMB2+ server cannot parse. That function
+is not mangling packets for SMB1 connections, so it somehow works for SMB1.
+
+Fix this problem and instead of smb_send(), use smb_send_kvec() function
+which does not mangle prepared packet, this function send them as is. Just
+API of this function takes struct msghdr (kvec) instead of packet buffer.
+
+[MS-SMB2] specification allows SMB2 protocol to use NetBIOS as a transport
+protocol. NetBIOS can be used over TCP via port 139. So this is a valid
+configuration, just not so common. And even recent Windows versions (e.g.
+Windows Server 2022) still supports this configuration: SMB over TCP port
+139, including for modern SMB2 and SMB3 dialects.
+
+This change fixes SMB2 and SMB3 connections over TCP port 139 which
+requires establishing of NetBIOS session. Tested that this change fixes
+establishing of SMB2 and SMB3 connections with Windows Server 2022.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/cifsproto.h | 3 +++
+ fs/smb/client/connect.c | 20 +++++++++++++++-----
+ fs/smb/client/transport.c | 2 +-
+ 3 files changed, 19 insertions(+), 6 deletions(-)
+
+diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
+index 90b7b30abfbd8..306386e5c171f 100644
+--- a/fs/smb/client/cifsproto.h
++++ b/fs/smb/client/cifsproto.h
+@@ -31,6 +31,9 @@ extern void cifs_small_buf_release(void *);
+ extern void free_rsp_buf(int, void *);
+ extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *,
+ unsigned int /* length */);
++extern int smb_send_kvec(struct TCP_Server_Info *server,
++ struct msghdr *msg,
++ size_t *sent);
+ extern unsigned int _get_xid(void);
+ extern void _free_xid(unsigned int);
+ #define get_xid() \
+diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
+index 3b4c2e59f1799..8260d0e07a628 100644
+--- a/fs/smb/client/connect.c
++++ b/fs/smb/client/connect.c
+@@ -3063,8 +3063,10 @@ ip_rfc1001_connect(struct TCP_Server_Info *server)
+ * sessinit is sent but no second negprot
+ */
+ struct rfc1002_session_packet req = {};
+- struct smb_hdr *smb_buf = (struct smb_hdr *)&req;
++ struct msghdr msg = {};
++ struct kvec iov = {};
+ unsigned int len;
++ size_t sent;
+
+ req.trailer.session_req.called_len = sizeof(req.trailer.session_req.called_name);
+
+@@ -3093,10 +3095,18 @@ ip_rfc1001_connect(struct TCP_Server_Info *server)
+ * As per rfc1002, @len must be the number of bytes that follows the
+ * length field of a rfc1002 session request payload.
+ */
+- len = sizeof(req) - offsetof(struct rfc1002_session_packet, trailer.session_req);
++ len = sizeof(req.trailer.session_req);
++ req.type = RFC1002_SESSION_REQUEST;
++ req.flags = 0;
++ req.length = cpu_to_be16(len);
++ len += offsetof(typeof(req), trailer.session_req);
++ iov.iov_base = &req;
++ iov.iov_len = len;
++ iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, &iov, 1, len);
++ rc = smb_send_kvec(server, &msg, &sent);
++ if (rc < 0 || len != sent)
++ return (rc == -EINTR || rc == -EAGAIN) ? rc : -ECONNABORTED;
+
+- smb_buf->smb_buf_length = cpu_to_be32((RFC1002_SESSION_REQUEST << 24) | len);
+- rc = smb_send(server, smb_buf, len);
+ /*
+ * RFC1001 layer in at least one server requires very short break before
+ * negprot presumably because not expecting negprot to follow so fast.
+@@ -3105,7 +3115,7 @@ ip_rfc1001_connect(struct TCP_Server_Info *server)
+ */
+ usleep_range(1000, 2000);
+
+- return rc;
++ return 0;
+ }
+
+ static int
+diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c
+index 91812150186c0..9f13a705f7f67 100644
+--- a/fs/smb/client/transport.c
++++ b/fs/smb/client/transport.c
+@@ -179,7 +179,7 @@ delete_mid(struct mid_q_entry *mid)
+ * Our basic "send data to server" function. Should be called with srv_mutex
+ * held. The caller is responsible for handling the results.
+ */
+-static int
++int
+ smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
+ size_t *sent)
+ {
+--
+2.39.5
+
--- /dev/null
+From 4e838f880244f9950a80e812b734fda99d50d0a6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 2 Nov 2024 20:06:50 +0100
+Subject: cifs: Fix negotiate retry functionality
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit e94e882a6d69525c07589222cf3a6ff57ad12b5b ]
+
+SMB negotiate retry functionality in cifs_negotiate() is currently broken
+and does not work when doing socket reconnect. Caller of this function,
+which is cifs_negotiate_protocol() requires that tcpStatus after successful
+execution of negotiate callback stay in CifsInNegotiate. But if the
+CIFSSMBNegotiate() called from cifs_negotiate() fails due to connection
+issues then tcpStatus is changed as so repeated CIFSSMBNegotiate() call
+does not help.
+
+Fix this problem by moving retrying code from negotiate callback (which is
+either cifs_negotiate() or smb2_negotiate()) to cifs_negotiate_protocol()
+which is caller of those callbacks. This allows to properly handle and
+implement correct transistions between tcpStatus states as function
+cifs_negotiate_protocol() already handles it.
+
+With this change, cifs_negotiate_protocol() now handles also -EAGAIN error
+set by the RFC1002_NEGATIVE_SESSION_RESPONSE processing after reconnecting
+with NetBIOS session.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/connect.c | 10 ++++++++++
+ fs/smb/client/smb1ops.c | 7 -------
+ fs/smb/client/smb2ops.c | 3 ---
+ 3 files changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
+index 112057c7ca11c..3b4c2e59f1799 100644
+--- a/fs/smb/client/connect.c
++++ b/fs/smb/client/connect.c
+@@ -3957,11 +3957,13 @@ int
+ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses,
+ struct TCP_Server_Info *server)
+ {
++ bool in_retry = false;
+ int rc = 0;
+
+ if (!server->ops->need_neg || !server->ops->negotiate)
+ return -ENOSYS;
+
++retry:
+ /* only send once per connect */
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus != CifsGood &&
+@@ -3981,6 +3983,14 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses,
+ spin_unlock(&server->srv_lock);
+
+ rc = server->ops->negotiate(xid, ses, server);
++ if (rc == -EAGAIN) {
++ /* Allow one retry attempt */
++ if (!in_retry) {
++ in_retry = true;
++ goto retry;
++ }
++ rc = -EHOSTDOWN;
++ }
+ if (rc == 0) {
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus == CifsInNegotiate)
+diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
+index 55cceb8229323..a2dbebd13720b 100644
+--- a/fs/smb/client/smb1ops.c
++++ b/fs/smb/client/smb1ops.c
+@@ -426,13 +426,6 @@ cifs_negotiate(const unsigned int xid,
+ {
+ int rc;
+ rc = CIFSSMBNegotiate(xid, ses, server);
+- if (rc == -EAGAIN) {
+- /* retry only once on 1st time connection */
+- set_credits(server, 1);
+- rc = CIFSSMBNegotiate(xid, ses, server);
+- if (rc == -EAGAIN)
+- rc = -EHOSTDOWN;
+- }
+ return rc;
+ }
+
+diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
+index 590b70d71694b..ff50cdfde5fe4 100644
+--- a/fs/smb/client/smb2ops.c
++++ b/fs/smb/client/smb2ops.c
+@@ -464,9 +464,6 @@ smb2_negotiate(const unsigned int xid,
+ server->CurrentMid = 0;
+ spin_unlock(&server->mid_lock);
+ rc = SMB2_negotiate(xid, ses, server);
+- /* BB we probably don't need to retry with modern servers */
+- if (rc == -EAGAIN)
+- rc = -EHOSTDOWN;
+ return rc;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 13951eafb0ad0347dae67980975303d378ffa916 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 28 Dec 2024 21:09:54 +0100
+Subject: cifs: Fix querying and creating MF symlinks over SMB1
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit 4236ac9fe5b8b42756070d4abfb76fed718e87c2 ]
+
+Old SMB1 servers without CAP_NT_SMBS do not support CIFS_open() function
+and instead SMBLegacyOpen() needs to be used. This logic is already handled
+in cifs_open_file() function, which is server->ops->open callback function.
+
+So for querying and creating MF symlinks use open callback function instead
+of CIFS_open() function directly.
+
+This change fixes querying and creating new MF symlinks on Windows 98.
+Currently cifs_query_mf_symlink() is not able to detect MF symlink and
+cifs_create_mf_symlink() is failing with EIO error.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/link.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/fs/smb/client/link.c b/fs/smb/client/link.c
+index 47ddeb7fa1116..aa45ef6ae99a6 100644
+--- a/fs/smb/client/link.c
++++ b/fs/smb/client/link.c
+@@ -257,7 +257,7 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_open_parms oparms;
+ struct cifs_io_parms io_parms = {0};
+ int buf_type = CIFS_NO_BUFFER;
+- FILE_ALL_INFO file_info;
++ struct cifs_open_info_data query_data;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+@@ -269,11 +269,11 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+ .fid = &fid,
+ };
+
+- rc = CIFS_open(xid, &oparms, &oplock, &file_info);
++ rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &query_data);
+ if (rc)
+ return rc;
+
+- if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
++ if (query_data.fi.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
+ rc = -ENOENT;
+ /* it's not a symlink */
+ goto out;
+@@ -312,7 +312,7 @@ cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+ .fid = &fid,
+ };
+
+- rc = CIFS_open(xid, &oparms, &oplock, NULL);
++ rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
+ if (rc)
+ return rc;
+
+--
+2.39.5
+
--- /dev/null
+From 3dff2b7f775df9e1455ecedf9e157d5be467c0e0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 27 Oct 2024 12:10:52 +0100
+Subject: cifs: Set default Netbios RFC1001 server name to hostname in UNC
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit be786e509c1af9b2dcf25c3d601f05c8c251f482 ]
+
+Windows SMB servers (including SMB2+) which are working over RFC1001
+require that Netbios server name specified in RFC1001 Session Request
+packet is same as the UNC host name. Netbios server name can be already
+specified manually via -o servern= option.
+
+With this change the RFC1001 server name is set automatically by extracting
+the hostname from the mount source.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/fs_context.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
+index b015a4f997cb6..8b70d92f48458 100644
+--- a/fs/smb/client/fs_context.c
++++ b/fs/smb/client/fs_context.c
+@@ -1058,6 +1058,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
+ int i, opt;
+ bool is_smb3 = !strcmp(fc->fs_type->name, "smb3");
+ bool skip_parsing = false;
++ char *hostname;
+
+ cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key);
+
+@@ -1390,6 +1391,16 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
+ cifs_errorf(fc, "OOM when copying UNC string\n");
+ goto cifs_parse_mount_err;
+ }
++ hostname = extract_hostname(ctx->UNC);
++ if (IS_ERR(hostname)) {
++ cifs_errorf(fc, "Cannot extract hostname from UNC string\n");
++ goto cifs_parse_mount_err;
++ }
++ /* last byte, type, is 0x20 for servr type */
++ memset(ctx->target_rfc1001_name, 0x20, RFC1001_NAME_LEN_WITH_NULL);
++ for (i = 0; i < RFC1001_NAME_LEN && hostname[i] != 0; i++)
++ ctx->target_rfc1001_name[i] = toupper(hostname[i]);
++ kfree(hostname);
+ break;
+ case Opt_user:
+ kfree(ctx->username);
+--
+2.39.5
+
--- /dev/null
+From 460b4aa62f0bc3c05696cb82799426e53bdd6af2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Feb 2025 19:26:46 +0100
+Subject: clk: imx8mp: inform CCF of maximum frequency of clocks
+
+From: Ahmad Fatoum <a.fatoum@pengutronix.de>
+
+[ Upstream commit 06a61b5cb6a8638fa8823cd09b17233b29696fa2 ]
+
+The IMX8MPCEC datasheet lists maximum frequencies allowed for different
+modules. Some of these limits are universal, but some depend on
+whether the SoC is operating in nominal or in overdrive mode.
+
+The imx8mp.dtsi currently assumes overdrive mode and configures some
+clocks in accordance with this. Boards wishing to make use of nominal
+mode will need to override some of the clock rates manually.
+
+As operating the clocks outside of their allowed range can lead to
+difficult to debug issues, it makes sense to register the maximum rates
+allowed in the driver, so the CCF can take them into account.
+
+Reviewed-by: Peng Fan <peng.fan@nxp.com>
+Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
+Link: https://lore.kernel.org/r/20250218-imx8m-clk-v4-6-b7697dc2dcd0@pengutronix.de
+Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/imx/clk-imx8mp.c | 151 +++++++++++++++++++++++++++++++++++
+ 1 file changed, 151 insertions(+)
+
+diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
+index fb18f507f1213..fe6dac70f1a15 100644
+--- a/drivers/clk/imx/clk-imx8mp.c
++++ b/drivers/clk/imx/clk-imx8mp.c
+@@ -8,6 +8,7 @@
+ #include <linux/err.h>
+ #include <linux/io.h>
+ #include <linux/module.h>
++#include <linux/units.h>
+ #include <linux/of_address.h>
+ #include <linux/platform_device.h>
+ #include <linux/slab.h>
+@@ -406,11 +407,151 @@ static const char * const imx8mp_clkout_sels[] = {"audio_pll1_out", "audio_pll2_
+ static struct clk_hw **hws;
+ static struct clk_hw_onecell_data *clk_hw_data;
+
++struct imx8mp_clock_constraints {
++ unsigned int clkid;
++ u32 maxrate;
++};
++
++/*
++ * Below tables are taken from IMX8MPCEC Rev. 2.1, 07/2023
++ * Table 13. Maximum frequency of modules.
++ * Probable typos fixed are marked with a comment.
++ */
++static const struct imx8mp_clock_constraints imx8mp_clock_common_constraints[] = {
++ { IMX8MP_CLK_A53_DIV, 1000 * HZ_PER_MHZ },
++ { IMX8MP_CLK_ENET_AXI, 266666667 }, /* Datasheet claims 266MHz */
++ { IMX8MP_CLK_NAND_USDHC_BUS, 266666667 }, /* Datasheet claims 266MHz */
++ { IMX8MP_CLK_MEDIA_APB, 200 * HZ_PER_MHZ },
++ { IMX8MP_CLK_HDMI_APB, 133333333 }, /* Datasheet claims 133MHz */
++ { IMX8MP_CLK_ML_AXI, 800 * HZ_PER_MHZ },
++ { IMX8MP_CLK_AHB, 133333333 },
++ { IMX8MP_CLK_IPG_ROOT, 66666667 },
++ { IMX8MP_CLK_AUDIO_AHB, 400 * HZ_PER_MHZ },
++ { IMX8MP_CLK_MEDIA_DISP2_PIX, 170 * HZ_PER_MHZ },
++ { IMX8MP_CLK_DRAM_ALT, 666666667 },
++ { IMX8MP_CLK_DRAM_APB, 200 * HZ_PER_MHZ },
++ { IMX8MP_CLK_CAN1, 80 * HZ_PER_MHZ },
++ { IMX8MP_CLK_CAN2, 80 * HZ_PER_MHZ },
++ { IMX8MP_CLK_PCIE_AUX, 10 * HZ_PER_MHZ },
++ { IMX8MP_CLK_I2C5, 66666667 }, /* Datasheet claims 66MHz */
++ { IMX8MP_CLK_I2C6, 66666667 }, /* Datasheet claims 66MHz */
++ { IMX8MP_CLK_SAI1, 66666667 }, /* Datasheet claims 66MHz */
++ { IMX8MP_CLK_SAI2, 66666667 }, /* Datasheet claims 66MHz */
++ { IMX8MP_CLK_SAI3, 66666667 }, /* Datasheet claims 66MHz */
++ { IMX8MP_CLK_SAI5, 66666667 }, /* Datasheet claims 66MHz */
++ { IMX8MP_CLK_SAI6, 66666667 }, /* Datasheet claims 66MHz */
++ { IMX8MP_CLK_ENET_QOS, 125 * HZ_PER_MHZ },
++ { IMX8MP_CLK_ENET_QOS_TIMER, 200 * HZ_PER_MHZ },
++ { IMX8MP_CLK_ENET_REF, 125 * HZ_PER_MHZ },
++ { IMX8MP_CLK_ENET_TIMER, 125 * HZ_PER_MHZ },
++ { IMX8MP_CLK_ENET_PHY_REF, 125 * HZ_PER_MHZ },
++ { IMX8MP_CLK_NAND, 500 * HZ_PER_MHZ },
++ { IMX8MP_CLK_QSPI, 400 * HZ_PER_MHZ },
++ { IMX8MP_CLK_USDHC1, 400 * HZ_PER_MHZ },
++ { IMX8MP_CLK_USDHC2, 400 * HZ_PER_MHZ },
++ { IMX8MP_CLK_I2C1, 66666667 }, /* Datasheet claims 66MHz */
++ { IMX8MP_CLK_I2C2, 66666667 }, /* Datasheet claims 66MHz */
++ { IMX8MP_CLK_I2C3, 66666667 }, /* Datasheet claims 66MHz */
++ { IMX8MP_CLK_I2C4, 66666667 }, /* Datasheet claims 66MHz */
++ { IMX8MP_CLK_UART1, 80 * HZ_PER_MHZ },
++ { IMX8MP_CLK_UART2, 80 * HZ_PER_MHZ },
++ { IMX8MP_CLK_UART3, 80 * HZ_PER_MHZ },
++ { IMX8MP_CLK_UART4, 80 * HZ_PER_MHZ },
++ { IMX8MP_CLK_ECSPI1, 80 * HZ_PER_MHZ },
++ { IMX8MP_CLK_ECSPI2, 80 * HZ_PER_MHZ },
++ { IMX8MP_CLK_PWM1, 66666667 }, /* Datasheet claims 66MHz */
++ { IMX8MP_CLK_PWM2, 66666667 }, /* Datasheet claims 66MHz */
++ { IMX8MP_CLK_PWM3, 66666667 }, /* Datasheet claims 66MHz */
++ { IMX8MP_CLK_PWM4, 66666667 }, /* Datasheet claims 66MHz */
++ { IMX8MP_CLK_GPT1, 100 * HZ_PER_MHZ },
++ { IMX8MP_CLK_GPT2, 100 * HZ_PER_MHZ },
++ { IMX8MP_CLK_GPT3, 100 * HZ_PER_MHZ },
++ { IMX8MP_CLK_GPT4, 100 * HZ_PER_MHZ },
++ { IMX8MP_CLK_GPT5, 100 * HZ_PER_MHZ },
++ { IMX8MP_CLK_GPT6, 100 * HZ_PER_MHZ },
++ { IMX8MP_CLK_WDOG, 66666667 }, /* Datasheet claims 66MHz */
++ { IMX8MP_CLK_IPP_DO_CLKO1, 200 * HZ_PER_MHZ },
++ { IMX8MP_CLK_IPP_DO_CLKO2, 200 * HZ_PER_MHZ },
++ { IMX8MP_CLK_HDMI_REF_266M, 266 * HZ_PER_MHZ },
++ { IMX8MP_CLK_USDHC3, 400 * HZ_PER_MHZ },
++ { IMX8MP_CLK_MEDIA_MIPI_PHY1_REF, 300 * HZ_PER_MHZ },
++ { IMX8MP_CLK_MEDIA_DISP1_PIX, 250 * HZ_PER_MHZ },
++ { IMX8MP_CLK_MEDIA_CAM2_PIX, 277 * HZ_PER_MHZ },
++ { IMX8MP_CLK_MEDIA_LDB, 595 * HZ_PER_MHZ },
++ { IMX8MP_CLK_MEDIA_MIPI_TEST_BYTE, 200 * HZ_PER_MHZ },
++ { IMX8MP_CLK_ECSPI3, 80 * HZ_PER_MHZ },
++ { IMX8MP_CLK_PDM, 200 * HZ_PER_MHZ },
++ { IMX8MP_CLK_SAI7, 66666667 }, /* Datasheet claims 66MHz */
++ { IMX8MP_CLK_MAIN_AXI, 400 * HZ_PER_MHZ },
++ { /* Sentinel */ }
++};
++
++static const struct imx8mp_clock_constraints imx8mp_clock_nominal_constraints[] = {
++ { IMX8MP_CLK_M7_CORE, 600 * HZ_PER_MHZ },
++ { IMX8MP_CLK_ML_CORE, 800 * HZ_PER_MHZ },
++ { IMX8MP_CLK_GPU3D_CORE, 800 * HZ_PER_MHZ },
++ { IMX8MP_CLK_GPU3D_SHADER_CORE, 800 * HZ_PER_MHZ },
++ { IMX8MP_CLK_GPU2D_CORE, 800 * HZ_PER_MHZ },
++ { IMX8MP_CLK_AUDIO_AXI_SRC, 600 * HZ_PER_MHZ },
++ { IMX8MP_CLK_HSIO_AXI, 400 * HZ_PER_MHZ },
++ { IMX8MP_CLK_MEDIA_ISP, 400 * HZ_PER_MHZ },
++ { IMX8MP_CLK_VPU_BUS, 600 * HZ_PER_MHZ },
++ { IMX8MP_CLK_MEDIA_AXI, 400 * HZ_PER_MHZ },
++ { IMX8MP_CLK_HDMI_AXI, 400 * HZ_PER_MHZ },
++ { IMX8MP_CLK_GPU_AXI, 600 * HZ_PER_MHZ },
++ { IMX8MP_CLK_GPU_AHB, 300 * HZ_PER_MHZ },
++ { IMX8MP_CLK_NOC, 800 * HZ_PER_MHZ },
++ { IMX8MP_CLK_NOC_IO, 600 * HZ_PER_MHZ },
++ { IMX8MP_CLK_ML_AHB, 300 * HZ_PER_MHZ },
++ { IMX8MP_CLK_VPU_G1, 600 * HZ_PER_MHZ },
++ { IMX8MP_CLK_VPU_G2, 500 * HZ_PER_MHZ },
++ { IMX8MP_CLK_MEDIA_CAM1_PIX, 400 * HZ_PER_MHZ },
++ { IMX8MP_CLK_VPU_VC8000E, 400 * HZ_PER_MHZ }, /* Datasheet claims 500MHz */
++ { IMX8MP_CLK_DRAM_CORE, 800 * HZ_PER_MHZ },
++ { IMX8MP_CLK_GIC, 400 * HZ_PER_MHZ },
++ { /* Sentinel */ }
++};
++
++static const struct imx8mp_clock_constraints imx8mp_clock_overdrive_constraints[] = {
++ { IMX8MP_CLK_M7_CORE, 800 * HZ_PER_MHZ},
++ { IMX8MP_CLK_ML_CORE, 1000 * HZ_PER_MHZ },
++ { IMX8MP_CLK_GPU3D_CORE, 1000 * HZ_PER_MHZ },
++ { IMX8MP_CLK_GPU3D_SHADER_CORE, 1000 * HZ_PER_MHZ },
++ { IMX8MP_CLK_GPU2D_CORE, 1000 * HZ_PER_MHZ },
++ { IMX8MP_CLK_AUDIO_AXI_SRC, 800 * HZ_PER_MHZ },
++ { IMX8MP_CLK_HSIO_AXI, 500 * HZ_PER_MHZ },
++ { IMX8MP_CLK_MEDIA_ISP, 500 * HZ_PER_MHZ },
++ { IMX8MP_CLK_VPU_BUS, 800 * HZ_PER_MHZ },
++ { IMX8MP_CLK_MEDIA_AXI, 500 * HZ_PER_MHZ },
++ { IMX8MP_CLK_HDMI_AXI, 500 * HZ_PER_MHZ },
++ { IMX8MP_CLK_GPU_AXI, 800 * HZ_PER_MHZ },
++ { IMX8MP_CLK_GPU_AHB, 400 * HZ_PER_MHZ },
++ { IMX8MP_CLK_NOC, 1000 * HZ_PER_MHZ },
++ { IMX8MP_CLK_NOC_IO, 800 * HZ_PER_MHZ },
++ { IMX8MP_CLK_ML_AHB, 400 * HZ_PER_MHZ },
++ { IMX8MP_CLK_VPU_G1, 800 * HZ_PER_MHZ },
++ { IMX8MP_CLK_VPU_G2, 700 * HZ_PER_MHZ },
++ { IMX8MP_CLK_MEDIA_CAM1_PIX, 500 * HZ_PER_MHZ },
++ { IMX8MP_CLK_VPU_VC8000E, 500 * HZ_PER_MHZ }, /* Datasheet claims 400MHz */
++ { IMX8MP_CLK_DRAM_CORE, 1000 * HZ_PER_MHZ },
++ { IMX8MP_CLK_GIC, 500 * HZ_PER_MHZ },
++ { /* Sentinel */ }
++};
++
++static void imx8mp_clocks_apply_constraints(const struct imx8mp_clock_constraints constraints[])
++{
++ const struct imx8mp_clock_constraints *constr;
++
++ for (constr = constraints; constr->clkid; constr++)
++ clk_hw_set_rate_range(hws[constr->clkid], 0, constr->maxrate);
++}
++
+ static int imx8mp_clocks_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+ struct device_node *np;
+ void __iomem *anatop_base, *ccm_base;
++ const char *opmode;
+ int err;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx8mp-anatop");
+@@ -715,6 +856,16 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
+
+ imx_check_clk_hws(hws, IMX8MP_CLK_END);
+
++ imx8mp_clocks_apply_constraints(imx8mp_clock_common_constraints);
++
++ err = of_property_read_string(np, "fsl,operating-mode", &opmode);
++ if (!err) {
++ if (!strcmp(opmode, "nominal"))
++ imx8mp_clocks_apply_constraints(imx8mp_clock_nominal_constraints);
++ else if (!strcmp(opmode, "overdrive"))
++ imx8mp_clocks_apply_constraints(imx8mp_clock_overdrive_constraints);
++ }
++
+ err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
+ if (err < 0) {
+ dev_err(dev, "failed to register hws for i.MX8MP\n");
+--
+2.39.5
+
--- /dev/null
+From ab401264679aeb93d2e204610fc09d3562810f92 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jan 2025 22:26:12 +0000
+Subject: clk: qcom: camcc-sm8250: Use clk_rcg2_shared_ops for some RCGs
+
+From: Jordan Crouse <jorcrous@amazon.com>
+
+[ Upstream commit 52b10b591f83dc6d9a1d6c2dc89433470a787ecd ]
+
+Update some RCGs on the sm8250 camera clock controller to use
+clk_rcg2_shared_ops. The shared_ops ensure the RCGs get parked
+to the XO during clock disable to prevent the clocks from locking up
+when the GDSC is enabled. These mirror similar fixes for other controllers
+such as commit e5c359f70e4b ("clk: qcom: camcc: Update the clock ops for
+the SC7180").
+
+Signed-off-by: Jordan Crouse <jorcrous@amazon.com>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Link: https://lore.kernel.org/r/20250122222612.32351-1-jorcrous@amazon.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/qcom/camcc-sm8250.c | 56 ++++++++++++++++-----------------
+ 1 file changed, 28 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/clk/qcom/camcc-sm8250.c b/drivers/clk/qcom/camcc-sm8250.c
+index 34d2f17520dcc..450ddbebd35f2 100644
+--- a/drivers/clk/qcom/camcc-sm8250.c
++++ b/drivers/clk/qcom/camcc-sm8250.c
+@@ -411,7 +411,7 @@ static struct clk_rcg2 cam_cc_bps_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -433,7 +433,7 @@ static struct clk_rcg2 cam_cc_camnoc_axi_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -454,7 +454,7 @@ static struct clk_rcg2 cam_cc_cci_0_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -469,7 +469,7 @@ static struct clk_rcg2 cam_cc_cci_1_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -490,7 +490,7 @@ static struct clk_rcg2 cam_cc_cphy_rx_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -511,7 +511,7 @@ static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -526,7 +526,7 @@ static struct clk_rcg2 cam_cc_csi1phytimer_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -556,7 +556,7 @@ static struct clk_rcg2 cam_cc_csi3phytimer_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -571,7 +571,7 @@ static struct clk_rcg2 cam_cc_csi4phytimer_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -586,7 +586,7 @@ static struct clk_rcg2 cam_cc_csi5phytimer_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -611,7 +611,7 @@ static struct clk_rcg2 cam_cc_fast_ahb_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -634,7 +634,7 @@ static struct clk_rcg2 cam_cc_fd_core_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -649,7 +649,7 @@ static struct clk_rcg2 cam_cc_icp_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -673,7 +673,7 @@ static struct clk_rcg2 cam_cc_ife_0_clk_src = {
+ .parent_data = cam_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -710,7 +710,7 @@ static struct clk_rcg2 cam_cc_ife_0_csid_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -734,7 +734,7 @@ static struct clk_rcg2 cam_cc_ife_1_clk_src = {
+ .parent_data = cam_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -749,7 +749,7 @@ static struct clk_rcg2 cam_cc_ife_1_csid_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -771,7 +771,7 @@ static struct clk_rcg2 cam_cc_ife_lite_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -786,7 +786,7 @@ static struct clk_rcg2 cam_cc_ife_lite_csid_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -810,7 +810,7 @@ static struct clk_rcg2 cam_cc_ipe_0_clk_src = {
+ .parent_data = cam_cc_parent_data_4,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_4),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -825,7 +825,7 @@ static struct clk_rcg2 cam_cc_jpeg_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -847,7 +847,7 @@ static struct clk_rcg2 cam_cc_mclk0_clk_src = {
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -862,7 +862,7 @@ static struct clk_rcg2 cam_cc_mclk1_clk_src = {
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -877,7 +877,7 @@ static struct clk_rcg2 cam_cc_mclk2_clk_src = {
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -892,7 +892,7 @@ static struct clk_rcg2 cam_cc_mclk3_clk_src = {
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -907,7 +907,7 @@ static struct clk_rcg2 cam_cc_mclk4_clk_src = {
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -922,7 +922,7 @@ static struct clk_rcg2 cam_cc_mclk5_clk_src = {
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+@@ -993,7 +993,7 @@ static struct clk_rcg2 cam_cc_slow_ahb_clk_src = {
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_rcg2_shared_ops,
+ },
+ };
+
+--
+2.39.5
+
--- /dev/null
+From 63911ae224540d45a35cbd4cb970ca5c9fbfc05d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Feb 2025 21:01:35 +0100
+Subject: clk: qcom: clk-alpha-pll: Do not use random stack value for recalc
+ rate
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 7a243e1b814a02ab40793026ef64223155d86395 ]
+
+If regmap_read() fails, random stack value was used in calculating new
+frequency in recalc_rate() callbacks. Such failure is really not
+expected as these are all MMIO reads, however code should be here
+correct and bail out. This also avoids possible warning on
+uninitialized value.
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/20250212-b4-clk-qcom-clean-v3-1-499f37444f5d@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/qcom/clk-alpha-pll.c | 52 ++++++++++++++++++++++----------
+ 1 file changed, 36 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
+index 10e276dabff93..e76ecc4663511 100644
+--- a/drivers/clk/qcom/clk-alpha-pll.c
++++ b/drivers/clk/qcom/clk-alpha-pll.c
+@@ -670,14 +670,19 @@ clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ u32 alpha_width = pll_alpha_width(pll);
+
+- regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l);
++ if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l))
++ return 0;
++
++ if (regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl))
++ return 0;
+
+- regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl);
+ if (ctl & PLL_ALPHA_EN) {
+- regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &low);
++ if (regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &low))
++ return 0;
+ if (alpha_width > 32) {
+- regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll),
+- &high);
++ if (regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll),
++ &high))
++ return 0;
+ a = (u64)high << 32 | low;
+ } else {
+ a = low & GENMASK(alpha_width - 1, 0);
+@@ -903,8 +908,11 @@ alpha_pll_huayra_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ u32 l, alpha = 0, ctl, alpha_m, alpha_n;
+
+- regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l);
+- regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl);
++ if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l))
++ return 0;
++
++ if (regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl))
++ return 0;
+
+ if (ctl & PLL_ALPHA_EN) {
+ regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &alpha);
+@@ -1098,8 +1106,11 @@ clk_trion_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ u32 l, frac, alpha_width = pll_alpha_width(pll);
+
+- regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l);
+- regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &frac);
++ if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l))
++ return 0;
++
++ if (regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &frac))
++ return 0;
+
+ return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width);
+ }
+@@ -1157,7 +1168,8 @@ clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+ struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
+ u32 ctl;
+
+- regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl);
++ if (regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl))
++ return 0;
+
+ ctl >>= PLL_POST_DIV_SHIFT;
+ ctl &= PLL_POST_DIV_MASK(pll);
+@@ -1373,8 +1385,11 @@ static unsigned long alpha_pll_fabia_recalc_rate(struct clk_hw *hw,
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ u32 l, frac, alpha_width = pll_alpha_width(pll);
+
+- regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l);
+- regmap_read(pll->clkr.regmap, PLL_FRAC(pll), &frac);
++ if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l))
++ return 0;
++
++ if (regmap_read(pll->clkr.regmap, PLL_FRAC(pll), &frac))
++ return 0;
+
+ return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width);
+ }
+@@ -1524,7 +1539,8 @@ clk_trion_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+ struct regmap *regmap = pll->clkr.regmap;
+ u32 i, div = 1, val;
+
+- regmap_read(regmap, PLL_USER_CTL(pll), &val);
++ if (regmap_read(regmap, PLL_USER_CTL(pll), &val))
++ return 0;
+
+ val >>= pll->post_div_shift;
+ val &= PLL_POST_DIV_MASK(pll);
+@@ -2451,9 +2467,12 @@ static unsigned long alpha_pll_lucid_evo_recalc_rate(struct clk_hw *hw,
+ struct regmap *regmap = pll->clkr.regmap;
+ u32 l, frac;
+
+- regmap_read(regmap, PLL_L_VAL(pll), &l);
++ if (regmap_read(regmap, PLL_L_VAL(pll), &l))
++ return 0;
+ l &= LUCID_EVO_PLL_L_VAL_MASK;
+- regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac);
++
++ if (regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac))
++ return 0;
+
+ return alpha_pll_calc_rate(parent_rate, l, frac, pll_alpha_width(pll));
+ }
+@@ -2528,7 +2547,8 @@ static unsigned long clk_rivian_evo_pll_recalc_rate(struct clk_hw *hw,
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ u32 l;
+
+- regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l);
++ if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l))
++ return 0;
+
+ return parent_rate * l;
+ }
+--
+2.39.5
+
--- /dev/null
+From 68af772ab3b3da91fd6e00deade6f7fa9959e6ce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Oct 2024 00:34:12 +0800
+Subject: clk: qcom: ipq5018: allow it to be bulid on arm32
+
+From: Karl Chan <exxxxkc@getgoogleoff.me>
+
+[ Upstream commit 5d02941c83997b58e8fc15390290c7c6975acaff ]
+
+There are some ipq5018 based device's firmware only can able to boot
+arm32 but the clock driver dont allow it to be compiled on arm32.
+Therefore allow GCC for IPQ5018 to be selected when building ARM32
+kernel
+
+Signed-off-by: Karl Chan <exxxxkc@getgoogleoff.me>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20241007163414.32458-4-exxxxkc@getgoogleoff.me
+[bjorn: Updated commit message, per Dmitry's suggestion]
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/qcom/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
+index 16145f74bbc85..fd605bccf48dc 100644
+--- a/drivers/clk/qcom/Kconfig
++++ b/drivers/clk/qcom/Kconfig
+@@ -199,7 +199,7 @@ config IPQ_GCC_4019
+
+ config IPQ_GCC_5018
+ tristate "IPQ5018 Global Clock Controller"
+- depends on ARM64 || COMPILE_TEST
++ depends on ARM || ARM64 || COMPILE_TEST
+ help
+ Support for global clock controller on ipq5018 devices.
+ Say Y if you want to use peripheral devices such as UART, SPI,
+--
+2.39.5
+
--- /dev/null
+From 185ea39663e9ff1dbde38840167fb9609c99656e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Feb 2025 15:04:55 +0530
+Subject: clk: qcom: lpassaudiocc-sc7280: Add support for LPASS resets for
+ QCM6490
+
+From: Taniya Das <quic_tdas@quicinc.com>
+
+[ Upstream commit cdbbc480f4146cb659af97f4020601fde5fb65a7 ]
+
+On the QCM6490 boards, the LPASS firmware controls the complete clock
+controller functionalities and associated power domains. However, only
+the LPASS resets required to be controlled by the high level OS. Thus,
+add support for the resets in the clock driver to enable the Audio SW
+driver to assert/deassert the audio resets as needed.
+
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Taniya Das <quic_tdas@quicinc.com>
+Link: https://lore.kernel.org/r/20250221-lpass_qcm6490_resets-v5-2-6be0c0949a83@quicinc.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/qcom/lpassaudiocc-sc7280.c | 23 +++++++++++++++++++----
+ 1 file changed, 19 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/clk/qcom/lpassaudiocc-sc7280.c b/drivers/clk/qcom/lpassaudiocc-sc7280.c
+index 45e7264770866..22169da08a51a 100644
+--- a/drivers/clk/qcom/lpassaudiocc-sc7280.c
++++ b/drivers/clk/qcom/lpassaudiocc-sc7280.c
+@@ -1,6 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ /*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
++ * Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ #include <linux/clk-provider.h>
+@@ -713,14 +714,24 @@ static const struct qcom_reset_map lpass_audio_cc_sc7280_resets[] = {
+ [LPASS_AUDIO_SWR_WSA_CGCR] = { 0xb0, 1 },
+ };
+
++static const struct regmap_config lpass_audio_cc_sc7280_reset_regmap_config = {
++ .name = "lpassaudio_cc_reset",
++ .reg_bits = 32,
++ .reg_stride = 4,
++ .val_bits = 32,
++ .fast_io = true,
++ .max_register = 0xc8,
++};
++
+ static const struct qcom_cc_desc lpass_audio_cc_reset_sc7280_desc = {
+- .config = &lpass_audio_cc_sc7280_regmap_config,
++ .config = &lpass_audio_cc_sc7280_reset_regmap_config,
+ .resets = lpass_audio_cc_sc7280_resets,
+ .num_resets = ARRAY_SIZE(lpass_audio_cc_sc7280_resets),
+ };
+
+ static const struct of_device_id lpass_audio_cc_sc7280_match_table[] = {
+- { .compatible = "qcom,sc7280-lpassaudiocc" },
++ { .compatible = "qcom,qcm6490-lpassaudiocc", .data = &lpass_audio_cc_reset_sc7280_desc },
++ { .compatible = "qcom,sc7280-lpassaudiocc", .data = &lpass_audio_cc_sc7280_desc },
+ { }
+ };
+ MODULE_DEVICE_TABLE(of, lpass_audio_cc_sc7280_match_table);
+@@ -752,13 +763,17 @@ static int lpass_audio_cc_sc7280_probe(struct platform_device *pdev)
+ struct regmap *regmap;
+ int ret;
+
++ desc = device_get_match_data(&pdev->dev);
++
++ if (of_device_is_compatible(pdev->dev.of_node, "qcom,qcm6490-lpassaudiocc"))
++ return qcom_cc_probe_by_index(pdev, 1, desc);
++
+ ret = lpass_audio_setup_runtime_pm(pdev);
+ if (ret)
+ return ret;
+
+ lpass_audio_cc_sc7280_regmap_config.name = "lpassaudio_cc";
+ lpass_audio_cc_sc7280_regmap_config.max_register = 0x2f000;
+- desc = &lpass_audio_cc_sc7280_desc;
+
+ regmap = qcom_cc_map(pdev, desc);
+ if (IS_ERR(regmap)) {
+@@ -772,7 +787,7 @@ static int lpass_audio_cc_sc7280_probe(struct platform_device *pdev)
+ regmap_write(regmap, 0x4, 0x3b);
+ regmap_write(regmap, 0x8, 0xff05);
+
+- ret = qcom_cc_really_probe(&pdev->dev, &lpass_audio_cc_sc7280_desc, regmap);
++ ret = qcom_cc_really_probe(&pdev->dev, desc, regmap);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register LPASS AUDIO CC clocks\n");
+ goto exit;
+--
+2.39.5
+
--- /dev/null
+From 599677263c4691a9779e12dcf80ba3537d09db04 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Dec 2024 21:02:01 +0000
+Subject: clk: renesas: rzg2l-cpg: Refactor Runtime PM clock validation
+
+From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+
+[ Upstream commit f6f73b891bf6beff069fcacc7b4a796e1009bf26 ]
+
+Refactor rzg2l_cpg_attach_dev to delegate clock validation for Runtime PM
+to the updated rzg2l_cpg_is_pm_clk function. Ensure validation of clocks
+associated with the power domain while excluding external and core clocks.
+Prevent incorrect Runtime PM management for clocks outside the domain's
+scope.
+
+Update rzg2l_cpg_is_pm_clk to operate on a per-power-domain basis. Verify
+clkspec.np against the domain's device node, check argument validity, and
+validate clock type (CPG_MOD). Use the no_pm_mod_clks array to exclude
+specific clocks from PM management.
+
+Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lore.kernel.org/20241216210201.239855-1-prabhakar.mahadev-lad.rj@bp.renesas.com
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/renesas/rzg2l-cpg.c | 102 +++++++++++++++++---------------
+ 1 file changed, 54 insertions(+), 48 deletions(-)
+
+diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
+index 229f4540b219e..97d42328fa81a 100644
+--- a/drivers/clk/renesas/rzg2l-cpg.c
++++ b/drivers/clk/renesas/rzg2l-cpg.c
+@@ -1549,28 +1549,6 @@ static int rzg2l_cpg_reset_controller_register(struct rzg2l_cpg_priv *priv)
+ return devm_reset_controller_register(priv->dev, &priv->rcdev);
+ }
+
+-static bool rzg2l_cpg_is_pm_clk(struct rzg2l_cpg_priv *priv,
+- const struct of_phandle_args *clkspec)
+-{
+- const struct rzg2l_cpg_info *info = priv->info;
+- unsigned int id;
+- unsigned int i;
+-
+- if (clkspec->args_count != 2)
+- return false;
+-
+- if (clkspec->args[0] != CPG_MOD)
+- return false;
+-
+- id = clkspec->args[1] + info->num_total_core_clks;
+- for (i = 0; i < info->num_no_pm_mod_clks; i++) {
+- if (info->no_pm_mod_clks[i] == id)
+- return false;
+- }
+-
+- return true;
+-}
+-
+ /**
+ * struct rzg2l_cpg_pm_domains - RZ/G2L PM domains data structure
+ * @onecell_data: cell data
+@@ -1595,45 +1573,73 @@ struct rzg2l_cpg_pd {
+ u16 id;
+ };
+
++static bool rzg2l_cpg_is_pm_clk(struct rzg2l_cpg_pd *pd,
++ const struct of_phandle_args *clkspec)
++{
++ if (clkspec->np != pd->genpd.dev.of_node || clkspec->args_count != 2)
++ return false;
++
++ switch (clkspec->args[0]) {
++ case CPG_MOD: {
++ struct rzg2l_cpg_priv *priv = pd->priv;
++ const struct rzg2l_cpg_info *info = priv->info;
++ unsigned int id = clkspec->args[1];
++
++ if (id >= priv->num_mod_clks)
++ return false;
++
++ id += info->num_total_core_clks;
++
++ for (unsigned int i = 0; i < info->num_no_pm_mod_clks; i++) {
++ if (info->no_pm_mod_clks[i] == id)
++ return false;
++ }
++
++ return true;
++ }
++
++ case CPG_CORE:
++ default:
++ return false;
++ }
++}
++
+ static int rzg2l_cpg_attach_dev(struct generic_pm_domain *domain, struct device *dev)
+ {
+ struct rzg2l_cpg_pd *pd = container_of(domain, struct rzg2l_cpg_pd, genpd);
+- struct rzg2l_cpg_priv *priv = pd->priv;
+ struct device_node *np = dev->of_node;
+ struct of_phandle_args clkspec;
+ bool once = true;
+ struct clk *clk;
++ unsigned int i;
+ int error;
+- int i = 0;
+-
+- while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
+- &clkspec)) {
+- if (rzg2l_cpg_is_pm_clk(priv, &clkspec)) {
+- if (once) {
+- once = false;
+- error = pm_clk_create(dev);
+- if (error) {
+- of_node_put(clkspec.np);
+- goto err;
+- }
+- }
+- clk = of_clk_get_from_provider(&clkspec);
++
++ for (i = 0; !of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, &clkspec); i++) {
++ if (!rzg2l_cpg_is_pm_clk(pd, &clkspec)) {
+ of_node_put(clkspec.np);
+- if (IS_ERR(clk)) {
+- error = PTR_ERR(clk);
+- goto fail_destroy;
+- }
++ continue;
++ }
+
+- error = pm_clk_add_clk(dev, clk);
++ if (once) {
++ once = false;
++ error = pm_clk_create(dev);
+ if (error) {
+- dev_err(dev, "pm_clk_add_clk failed %d\n",
+- error);
+- goto fail_put;
++ of_node_put(clkspec.np);
++ goto err;
+ }
+- } else {
+- of_node_put(clkspec.np);
+ }
+- i++;
++ clk = of_clk_get_from_provider(&clkspec);
++ of_node_put(clkspec.np);
++ if (IS_ERR(clk)) {
++ error = PTR_ERR(clk);
++ goto fail_destroy;
++ }
++
++ error = pm_clk_add_clk(dev, clk);
++ if (error) {
++ dev_err(dev, "pm_clk_add_clk failed %d\n", error);
++ goto fail_put;
++ }
+ }
+
+ return 0;
+--
+2.39.5
+
--- /dev/null
+From 08b7457832b7c2f04a30d5b6b2e8b9f1c34e4833 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Feb 2025 19:41:35 +0800
+Subject: clocksource/drivers/timer-riscv: Stop stimecmp when cpu hotplug
+
+From: Nick Hu <nick.hu@sifive.com>
+
+[ Upstream commit 70c93b026ed07078e933583591aa9ca6701cd9da ]
+
+Stop the timer when the cpu is going to be offline otherwise the
+timer interrupt may be pending while performing power-down.
+
+Suggested-by: Anup Patel <anup@brainfault.org>
+Link: https://lore.kernel.org/lkml/20240829033904.477200-3-nick.hu@sifive.com/T/#u
+Signed-off-by: Nick Hu <nick.hu@sifive.com>
+Reviewed-by: Anup Patel <anup@brainfault.org>
+Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20250219114135.27764-3-nick.hu@sifive.com
+Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clocksource/timer-riscv.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c
+index 48ce50c5f5e68..4d7cf338824a3 100644
+--- a/drivers/clocksource/timer-riscv.c
++++ b/drivers/clocksource/timer-riscv.c
+@@ -126,7 +126,13 @@ static int riscv_timer_starting_cpu(unsigned int cpu)
+
+ static int riscv_timer_dying_cpu(unsigned int cpu)
+ {
++ /*
++ * Stop the timer when the cpu is going to be offline otherwise
++ * the timer interrupt may be pending while performing power-down.
++ */
++ riscv_clock_event_stop();
+ disable_percpu_irq(riscv_clock_event_irq);
++
+ return 0;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 3e810787a32f05b346f19fa872661c028e0efd47 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jan 2025 13:32:47 +0100
+Subject: clocksource: mips-gic-timer: Enable counter when CPUs start
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Paul Burton <paulburton@kernel.org>
+
+[ Upstream commit 3128b0a2e0cf6e07aa78e5f8cf7dd9cd59dc8174 ]
+
+In multi-cluster MIPS I6500 systems there is a GIC in each cluster,
+each with its own counter. When a cluster powers up the counter will
+be stopped, with the COUNTSTOP bit set in the GIC_CONFIG register.
+
+In single cluster systems, it has been fine to clear COUNTSTOP once
+in gic_clocksource_of_init() to start the counter. In multi-cluster
+systems, this will only have started the counter in the boot cluster,
+and any CPUs in other clusters will find their counter stopped which
+will break the GIC clock_event_device.
+
+Resolve this by having CPUs clear the COUNTSTOP bit when they come
+online, using the existing gic_starting_cpu() CPU hotplug callback. This
+will allow CPUs in secondary clusters to ensure that the cluster's GIC
+counter is running as expected.
+
+Signed-off-by: Paul Burton <paulburton@kernel.org>
+Signed-off-by: Chao-ying Fu <cfu@wavecomp.com>
+Signed-off-by: Dragan Mladjenovic <dragan.mladjenovic@syrmia.com>
+Signed-off-by: Aleksandar Rikalo <arikalo@gmail.com>
+Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
+Tested-by: Serge Semin <fancer.lancer@gmail.com>
+Tested-by: Gregory CLEMENT <gregory.clement@bootlin.com>
+Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clocksource/mips-gic-timer.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c
+index 110347707ff98..8592910710d17 100644
+--- a/drivers/clocksource/mips-gic-timer.c
++++ b/drivers/clocksource/mips-gic-timer.c
+@@ -115,6 +115,9 @@ static void gic_update_frequency(void *data)
+
+ static int gic_starting_cpu(unsigned int cpu)
+ {
++ /* Ensure the GIC counter is running */
++ clear_gic_config(GIC_CONFIG_COUNTSTOP);
++
+ gic_clockevent_cpu_init(cpu, this_cpu_ptr(&gic_clockevent_device));
+ return 0;
+ }
+@@ -252,9 +255,6 @@ static int __init gic_clocksource_of_init(struct device_node *node)
+ pr_warn("Unable to register clock notifier\n");
+ }
+
+- /* And finally start the counter */
+- clear_gic_config(GIC_CONFIG_COUNTSTOP);
+-
+ /*
+ * It's safe to use the MIPS GIC timer as a sched clock source only if
+ * its ticks are stable, which is true on either the platforms with
+--
+2.39.5
+
--- /dev/null
+From b8731d9a99796cc6b1e961781908173c6dda3956 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Mar 2025 12:11:06 +0000
+Subject: coresight-etb10: change etb_drvdata spinlock's type to raw_spinlock_t
+
+From: Yeoreum Yun <yeoreum.yun@arm.com>
+
+[ Upstream commit 6b80c0abe475ed1017c5e862636049aa1cc17a1a ]
+
+In coresight-etb10 drivers, etb_drvdata->spinlock can be held
+during __schedule() by perf_event_task_sched_out()/in().
+
+Since etb_drvdata->spinlock type is spinlock_t and
+perf_event_task_sched_out()/in() is called after acquiring rq_lock,
+which is raw_spinlock_t (an unsleepable lock),
+this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.
+
+To address this, change type etb_drvdata->spinlock in coresight-etb10 drivers,
+which can be called by perf_event_task_sched_out()/in(),
+from spinlock_t to raw_spinlock_t.
+
+Reviewed-by: James Clark <james.clark@linaro.org>
+Reviewed-by: Mike Leach <mike.leach@linaro.org>
+Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
+Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
+Link: https://lore.kernel.org/r/20250306121110.1647948-6-yeoreum.yun@arm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwtracing/coresight/coresight-etb10.c | 26 +++++++++----------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
+index aea9ac9c4bd06..7948597d483d2 100644
+--- a/drivers/hwtracing/coresight/coresight-etb10.c
++++ b/drivers/hwtracing/coresight/coresight-etb10.c
+@@ -84,7 +84,7 @@ struct etb_drvdata {
+ struct clk *atclk;
+ struct coresight_device *csdev;
+ struct miscdevice miscdev;
+- spinlock_t spinlock;
++ raw_spinlock_t spinlock;
+ local_t reading;
+ pid_t pid;
+ u8 *buf;
+@@ -145,7 +145,7 @@ static int etb_enable_sysfs(struct coresight_device *csdev)
+ unsigned long flags;
+ struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+- spin_lock_irqsave(&drvdata->spinlock, flags);
++ raw_spin_lock_irqsave(&drvdata->spinlock, flags);
+
+ /* Don't messup with perf sessions. */
+ if (coresight_get_mode(csdev) == CS_MODE_PERF) {
+@@ -163,7 +163,7 @@ static int etb_enable_sysfs(struct coresight_device *csdev)
+
+ csdev->refcnt++;
+ out:
+- spin_unlock_irqrestore(&drvdata->spinlock, flags);
++ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ return ret;
+ }
+
+@@ -176,7 +176,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data)
+ struct perf_output_handle *handle = data;
+ struct cs_buffers *buf = etm_perf_sink_config(handle);
+
+- spin_lock_irqsave(&drvdata->spinlock, flags);
++ raw_spin_lock_irqsave(&drvdata->spinlock, flags);
+
+ /* No need to continue if the component is already in used by sysFS. */
+ if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
+@@ -219,7 +219,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data)
+ }
+
+ out:
+- spin_unlock_irqrestore(&drvdata->spinlock, flags);
++ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ return ret;
+ }
+
+@@ -352,11 +352,11 @@ static int etb_disable(struct coresight_device *csdev)
+ struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+ unsigned long flags;
+
+- spin_lock_irqsave(&drvdata->spinlock, flags);
++ raw_spin_lock_irqsave(&drvdata->spinlock, flags);
+
+ csdev->refcnt--;
+ if (csdev->refcnt) {
+- spin_unlock_irqrestore(&drvdata->spinlock, flags);
++ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ return -EBUSY;
+ }
+
+@@ -366,7 +366,7 @@ static int etb_disable(struct coresight_device *csdev)
+ /* Dissociate from monitored process. */
+ drvdata->pid = -1;
+ coresight_set_mode(csdev, CS_MODE_DISABLED);
+- spin_unlock_irqrestore(&drvdata->spinlock, flags);
++ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_dbg(&csdev->dev, "ETB disabled\n");
+ return 0;
+@@ -443,7 +443,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev,
+
+ capacity = drvdata->buffer_depth * ETB_FRAME_SIZE_WORDS;
+
+- spin_lock_irqsave(&drvdata->spinlock, flags);
++ raw_spin_lock_irqsave(&drvdata->spinlock, flags);
+
+ /* Don't do anything if another tracer is using this sink */
+ if (csdev->refcnt != 1)
+@@ -566,7 +566,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev,
+ __etb_enable_hw(drvdata);
+ CS_LOCK(drvdata->base);
+ out:
+- spin_unlock_irqrestore(&drvdata->spinlock, flags);
++ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ return to_read;
+ }
+@@ -587,13 +587,13 @@ static void etb_dump(struct etb_drvdata *drvdata)
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&drvdata->spinlock, flags);
++ raw_spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
+ __etb_disable_hw(drvdata);
+ etb_dump_hw(drvdata);
+ __etb_enable_hw(drvdata);
+ }
+- spin_unlock_irqrestore(&drvdata->spinlock, flags);
++ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_dbg(&drvdata->csdev->dev, "ETB dumped\n");
+ }
+@@ -746,7 +746,7 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
+ drvdata->base = base;
+ desc.access = CSDEV_ACCESS_IOMEM(base);
+
+- spin_lock_init(&drvdata->spinlock);
++ raw_spin_lock_init(&drvdata->spinlock);
+
+ drvdata->buffer_depth = etb_get_buffer_depth(drvdata);
+
+--
+2.39.5
+
--- /dev/null
+From e742b76ecbee16cc608f588c0503c2ea1ec89168 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 5 Apr 2025 00:42:19 +0800
+Subject: cpufreq: Add SM8650 to cpufreq-dt-platdev blocklist
+
+From: Pengyu Luo <mitltlatltl@gmail.com>
+
+[ Upstream commit fc5414a4774e14e51a93499a6adfdc45f2de82e0 ]
+
+SM8650 have already been supported by qcom-cpufreq-hw driver, but
+never been added to cpufreq-dt-platdev. This makes noise
+
+[ 0.388525] cpufreq-dt cpufreq-dt: failed register driver: -17
+[ 0.388537] cpufreq-dt cpufreq-dt: probe with driver cpufreq-dt failed with error -17
+
+So adding it to the cpufreq-dt-platdev driver's blocklist to fix it.
+
+Signed-off-by: Pengyu Luo <mitltlatltl@gmail.com>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/cpufreq-dt-platdev.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
+index 78ad3221fe077..67bac12d4d55b 100644
+--- a/drivers/cpufreq/cpufreq-dt-platdev.c
++++ b/drivers/cpufreq/cpufreq-dt-platdev.c
+@@ -172,6 +172,7 @@ static const struct of_device_id blocklist[] __initconst = {
+ { .compatible = "qcom,sm8350", },
+ { .compatible = "qcom,sm8450", },
+ { .compatible = "qcom,sm8550", },
++ { .compatible = "qcom,sm8650", },
+
+ { .compatible = "st,stih407", },
+ { .compatible = "st,stih410", },
+--
+2.39.5
+
--- /dev/null
+From dbe8208444bfe92eb9a22e73c2ef5cd3c498e475 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jan 2025 08:52:52 +0000
+Subject: cpufreq: amd-pstate: Remove unnecessary driver_lock in set_boost
+
+From: Dhananjay Ugwekar <dhananjay.ugwekar@amd.com>
+
+[ Upstream commit db1cafc77aaaf871509da06f4a864e9af6d6791f ]
+
+set_boost is a per-policy function call, hence a driver wide lock is
+unnecessary. Also this mutex_acquire can collide with the mutex_acquire
+from the mode-switch path in status_store(), which can lead to a
+deadlock. So, remove it.
+
+Signed-off-by: Dhananjay Ugwekar <dhananjay.ugwekar@amd.com>
+Acked-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/amd-pstate.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
+index 9db5354fdb027..7a16d19322286 100644
+--- a/drivers/cpufreq/amd-pstate.c
++++ b/drivers/cpufreq/amd-pstate.c
+@@ -696,7 +696,6 @@ static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state)
+ pr_err("Boost mode is not supported by this processor or SBIOS\n");
+ return -EOPNOTSUPP;
+ }
+- guard(mutex)(&amd_pstate_driver_lock);
+
+ ret = amd_pstate_cpu_boost_update(policy, state);
+ WRITE_ONCE(cpudata->boost_state, !ret ? state : false);
+--
+2.39.5
+
--- /dev/null
+From 575d7d2172f0d5f41a67f408a0ceba00c7e2f36e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Mar 2025 00:28:48 -0500
+Subject: cpufreq: tegra186: Share policy per cluster
+
+From: Aaron Kling <luceoscutum@gmail.com>
+
+[ Upstream commit be4ae8c19492cd6d5de61ccb34ffb3f5ede5eec8 ]
+
+This functionally brings tegra186 in line with tegra210 and tegra194,
+sharing a cpufreq policy between all cores in a cluster.
+
+Reviewed-by: Sumit Gupta <sumitg@nvidia.com>
+Acked-by: Thierry Reding <treding@nvidia.com>
+Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/tegra186-cpufreq.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/cpufreq/tegra186-cpufreq.c b/drivers/cpufreq/tegra186-cpufreq.c
+index 7b8fcfa55038b..4e5b6f9a56d1b 100644
+--- a/drivers/cpufreq/tegra186-cpufreq.c
++++ b/drivers/cpufreq/tegra186-cpufreq.c
+@@ -73,11 +73,18 @@ static int tegra186_cpufreq_init(struct cpufreq_policy *policy)
+ {
+ struct tegra186_cpufreq_data *data = cpufreq_get_driver_data();
+ unsigned int cluster = data->cpus[policy->cpu].bpmp_cluster_id;
++ u32 cpu;
+
+ policy->freq_table = data->clusters[cluster].table;
+ policy->cpuinfo.transition_latency = 300 * 1000;
+ policy->driver_data = NULL;
+
++ /* set same policy for all cpus in a cluster */
++ for (cpu = 0; cpu < ARRAY_SIZE(tegra186_cpus); cpu++) {
++ if (data->cpus[cpu].bpmp_cluster_id == cluster)
++ cpumask_set_cpu(cpu, policy->cpus);
++ }
++
+ return 0;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 405e733cf7655cff74103b4739837eac674851e6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Feb 2025 15:29:05 +0100
+Subject: cpuidle: menu: Avoid discarding useful information
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+[ Upstream commit 85975daeaa4d6ec560bfcd354fc9c08ad7f38888 ]
+
+When giving up on making a high-confidence prediction,
+get_typical_interval() always returns UINT_MAX which means that the
+next idle interval prediction will be based entirely on the time till
+the next timer. However, the information represented by the most
+recent intervals may not be completely useless in those cases.
+
+Namely, the largest recent idle interval is an upper bound on the
+recently observed idle duration, so it is reasonable to assume that
+the next idle duration is unlikely to exceed it. Moreover, this is
+still true after eliminating the suspected outliers if the sample
+set still under consideration is at least as large as 50% of the
+maximum sample set size.
+
+Accordingly, make get_typical_interval() return the current maximum
+recent interval value in that case instead of UINT_MAX.
+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Reported-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+Tested-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+Reviewed-by: Christian Loehle <christian.loehle@arm.com>
+Tested-by: Christian Loehle <christian.loehle@arm.com>
+Tested-by: Aboorva Devarajan <aboorvad@linux.ibm.com>
+Link: https://patch.msgid.link/7770672.EvYhyI6sBW@rjwysocki.net
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpuidle/governors/menu.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
+index f3c9d49f0f2a5..97ffadc7e57a6 100644
+--- a/drivers/cpuidle/governors/menu.c
++++ b/drivers/cpuidle/governors/menu.c
+@@ -239,8 +239,19 @@ static unsigned int get_typical_interval(struct menu_device *data)
+ * This can deal with workloads that have long pauses interspersed
+ * with sporadic activity with a bunch of short pauses.
+ */
+- if ((divisor * 4) <= INTERVALS * 3)
++ if (divisor * 4 <= INTERVALS * 3) {
++ /*
++ * If there are sufficiently many data points still under
++ * consideration after the outliers have been eliminated,
++ * returning without a prediction would be a mistake because it
++ * is likely that the next interval will not exceed the current
++ * maximum, so return the latter in that case.
++ */
++ if (divisor >= INTERVALS / 2)
++ return max;
++
+ return UINT_MAX;
++ }
+
+ thresh = max - 1;
+ goto again;
+--
+2.39.5
+
--- /dev/null
+From 98efe9de78192eb674ac4a843f18ade97c3da2a9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 16 Feb 2025 11:07:24 +0800
+Subject: crypto: ahash - Set default reqsize from ahash_alg
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+[ Upstream commit 9e01aaa1033d6e40f8d7cf4f20931a61ce9e3f04 ]
+
+Add a reqsize field to struct ahash_alg and use it to set the
+default reqsize so that algorithms with a static reqsize are
+not forced to create an init_tfm function.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ crypto/ahash.c | 4 ++++
+ include/crypto/hash.h | 3 +++
+ 2 files changed, 7 insertions(+)
+
+diff --git a/crypto/ahash.c b/crypto/ahash.c
+index bcd9de009a91b..fe19bf7f15eb9 100644
+--- a/crypto/ahash.c
++++ b/crypto/ahash.c
+@@ -473,6 +473,7 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm)
+ struct ahash_alg *alg = crypto_ahash_alg(hash);
+
+ crypto_ahash_set_statesize(hash, alg->halg.statesize);
++ crypto_ahash_set_reqsize(hash, alg->reqsize);
+
+ if (tfm->__crt_alg->cra_type == &crypto_shash_type)
+ return crypto_init_ahash_using_shash(tfm);
+@@ -638,6 +639,9 @@ static int ahash_prepare_alg(struct ahash_alg *alg)
+ if (alg->halg.statesize == 0)
+ return -EINVAL;
+
++ if (alg->reqsize && alg->reqsize < alg->halg.statesize)
++ return -EINVAL;
++
+ err = hash_prepare_alg(&alg->halg);
+ if (err)
+ return err;
+diff --git a/include/crypto/hash.h b/include/crypto/hash.h
+index 2d5ea9f9ff43e..6692253f0b5be 100644
+--- a/include/crypto/hash.h
++++ b/include/crypto/hash.h
+@@ -132,6 +132,7 @@ struct ahash_request {
+ * This is a counterpart to @init_tfm, used to remove
+ * various changes set in @init_tfm.
+ * @clone_tfm: Copy transform into new object, may allocate memory.
++ * @reqsize: Size of the request context.
+ * @halg: see struct hash_alg_common
+ */
+ struct ahash_alg {
+@@ -148,6 +149,8 @@ struct ahash_alg {
+ void (*exit_tfm)(struct crypto_ahash *tfm);
+ int (*clone_tfm)(struct crypto_ahash *dst, struct crypto_ahash *src);
+
++ unsigned int reqsize;
++
+ struct hash_alg_common halg;
+ };
+
+--
+2.39.5
+
--- /dev/null
+From 5fe28927b005259e709fded1b922503362d7d641 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Feb 2025 17:04:46 +0800
+Subject: crypto: lzo - Fix compression buffer overrun
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+[ Upstream commit cc47f07234f72cbd8e2c973cdbf2a6730660a463 ]
+
+Unlike the decompression code, the compression code in LZO never
+checked for output overruns. It instead assumes that the caller
+always provides enough buffer space, disregarding the buffer length
+provided by the caller.
+
+Add a safe compression interface that checks for the end of buffer
+before each write. Use the safe interface in crypto/lzo.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ crypto/lzo-rle.c | 2 +-
+ crypto/lzo.c | 2 +-
+ include/linux/lzo.h | 8 +++
+ lib/lzo/Makefile | 2 +-
+ lib/lzo/lzo1x_compress.c | 102 +++++++++++++++++++++++++---------
+ lib/lzo/lzo1x_compress_safe.c | 18 ++++++
+ 6 files changed, 106 insertions(+), 28 deletions(-)
+ create mode 100644 lib/lzo/lzo1x_compress_safe.c
+
+diff --git a/crypto/lzo-rle.c b/crypto/lzo-rle.c
+index 0631d975bfac1..0abc2d87f0420 100644
+--- a/crypto/lzo-rle.c
++++ b/crypto/lzo-rle.c
+@@ -55,7 +55,7 @@ static int __lzorle_compress(const u8 *src, unsigned int slen,
+ size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
+ int err;
+
+- err = lzorle1x_1_compress(src, slen, dst, &tmp_len, ctx);
++ err = lzorle1x_1_compress_safe(src, slen, dst, &tmp_len, ctx);
+
+ if (err != LZO_E_OK)
+ return -EINVAL;
+diff --git a/crypto/lzo.c b/crypto/lzo.c
+index ebda132dd22bf..8338851c7406a 100644
+--- a/crypto/lzo.c
++++ b/crypto/lzo.c
+@@ -55,7 +55,7 @@ static int __lzo_compress(const u8 *src, unsigned int slen,
+ size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
+ int err;
+
+- err = lzo1x_1_compress(src, slen, dst, &tmp_len, ctx);
++ err = lzo1x_1_compress_safe(src, slen, dst, &tmp_len, ctx);
+
+ if (err != LZO_E_OK)
+ return -EINVAL;
+diff --git a/include/linux/lzo.h b/include/linux/lzo.h
+index e95c7d1092b28..4d30e3624acd2 100644
+--- a/include/linux/lzo.h
++++ b/include/linux/lzo.h
+@@ -24,10 +24,18 @@
+ int lzo1x_1_compress(const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len, void *wrkmem);
+
++/* Same as above but does not write more than dst_len to dst. */
++int lzo1x_1_compress_safe(const unsigned char *src, size_t src_len,
++ unsigned char *dst, size_t *dst_len, void *wrkmem);
++
+ /* This requires 'wrkmem' of size LZO1X_1_MEM_COMPRESS */
+ int lzorle1x_1_compress(const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len, void *wrkmem);
+
++/* Same as above but does not write more than dst_len to dst. */
++int lzorle1x_1_compress_safe(const unsigned char *src, size_t src_len,
++ unsigned char *dst, size_t *dst_len, void *wrkmem);
++
+ /* safe decompression with overrun testing */
+ int lzo1x_decompress_safe(const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len);
+diff --git a/lib/lzo/Makefile b/lib/lzo/Makefile
+index 2f58fafbbdddc..fc7b2b7ef4b20 100644
+--- a/lib/lzo/Makefile
++++ b/lib/lzo/Makefile
+@@ -1,5 +1,5 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+-lzo_compress-objs := lzo1x_compress.o
++lzo_compress-objs := lzo1x_compress.o lzo1x_compress_safe.o
+ lzo_decompress-objs := lzo1x_decompress_safe.o
+
+ obj-$(CONFIG_LZO_COMPRESS) += lzo_compress.o
+diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c
+index 47d6d43ea9578..7b10ca86a8930 100644
+--- a/lib/lzo/lzo1x_compress.c
++++ b/lib/lzo/lzo1x_compress.c
+@@ -18,11 +18,22 @@
+ #include <linux/lzo.h>
+ #include "lzodefs.h"
+
+-static noinline size_t
+-lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
+- unsigned char *out, size_t *out_len,
+- size_t ti, void *wrkmem, signed char *state_offset,
+- const unsigned char bitstream_version)
++#undef LZO_UNSAFE
++
++#ifndef LZO_SAFE
++#define LZO_UNSAFE 1
++#define LZO_SAFE(name) name
++#define HAVE_OP(x) 1
++#endif
++
++#define NEED_OP(x) if (!HAVE_OP(x)) goto output_overrun
++
++static noinline int
++LZO_SAFE(lzo1x_1_do_compress)(const unsigned char *in, size_t in_len,
++ unsigned char **out, unsigned char *op_end,
++ size_t *tp, void *wrkmem,
++ signed char *state_offset,
++ const unsigned char bitstream_version)
+ {
+ const unsigned char *ip;
+ unsigned char *op;
+@@ -30,8 +41,9 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
+ const unsigned char * const ip_end = in + in_len - 20;
+ const unsigned char *ii;
+ lzo_dict_t * const dict = (lzo_dict_t *) wrkmem;
++ size_t ti = *tp;
+
+- op = out;
++ op = *out;
+ ip = in;
+ ii = ip;
+ ip += ti < 4 ? 4 - ti : 0;
+@@ -116,25 +128,32 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
+ if (t != 0) {
+ if (t <= 3) {
+ op[*state_offset] |= t;
++ NEED_OP(4);
+ COPY4(op, ii);
+ op += t;
+ } else if (t <= 16) {
++ NEED_OP(17);
+ *op++ = (t - 3);
+ COPY8(op, ii);
+ COPY8(op + 8, ii + 8);
+ op += t;
+ } else {
+ if (t <= 18) {
++ NEED_OP(1);
+ *op++ = (t - 3);
+ } else {
+ size_t tt = t - 18;
++ NEED_OP(1);
+ *op++ = 0;
+ while (unlikely(tt > 255)) {
+ tt -= 255;
++ NEED_OP(1);
+ *op++ = 0;
+ }
++ NEED_OP(1);
+ *op++ = tt;
+ }
++ NEED_OP(t);
+ do {
+ COPY8(op, ii);
+ COPY8(op + 8, ii + 8);
+@@ -151,6 +170,7 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
+ if (unlikely(run_length)) {
+ ip += run_length;
+ run_length -= MIN_ZERO_RUN_LENGTH;
++ NEED_OP(4);
+ put_unaligned_le32((run_length << 21) | 0xfffc18
+ | (run_length & 0x7), op);
+ op += 4;
+@@ -243,10 +263,12 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
+ ip += m_len;
+ if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) {
+ m_off -= 1;
++ NEED_OP(2);
+ *op++ = (((m_len - 1) << 5) | ((m_off & 7) << 2));
+ *op++ = (m_off >> 3);
+ } else if (m_off <= M3_MAX_OFFSET) {
+ m_off -= 1;
++ NEED_OP(1);
+ if (m_len <= M3_MAX_LEN)
+ *op++ = (M3_MARKER | (m_len - 2));
+ else {
+@@ -254,14 +276,18 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
+ *op++ = M3_MARKER | 0;
+ while (unlikely(m_len > 255)) {
+ m_len -= 255;
++ NEED_OP(1);
+ *op++ = 0;
+ }
++ NEED_OP(1);
+ *op++ = (m_len);
+ }
++ NEED_OP(2);
+ *op++ = (m_off << 2);
+ *op++ = (m_off >> 6);
+ } else {
+ m_off -= 0x4000;
++ NEED_OP(1);
+ if (m_len <= M4_MAX_LEN)
+ *op++ = (M4_MARKER | ((m_off >> 11) & 8)
+ | (m_len - 2));
+@@ -282,11 +308,14 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
+ m_len -= M4_MAX_LEN;
+ *op++ = (M4_MARKER | ((m_off >> 11) & 8));
+ while (unlikely(m_len > 255)) {
++ NEED_OP(1);
+ m_len -= 255;
+ *op++ = 0;
+ }
++ NEED_OP(1);
+ *op++ = (m_len);
+ }
++ NEED_OP(2);
+ *op++ = (m_off << 2);
+ *op++ = (m_off >> 6);
+ }
+@@ -295,14 +324,20 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
+ ii = ip;
+ goto next;
+ }
+- *out_len = op - out;
+- return in_end - (ii - ti);
++ *out = op;
++ *tp = in_end - (ii - ti);
++ return LZO_E_OK;
++
++output_overrun:
++ return LZO_E_OUTPUT_OVERRUN;
+ }
+
+-static int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
+- unsigned char *out, size_t *out_len,
+- void *wrkmem, const unsigned char bitstream_version)
++static int LZO_SAFE(lzogeneric1x_1_compress)(
++ const unsigned char *in, size_t in_len,
++ unsigned char *out, size_t *out_len,
++ void *wrkmem, const unsigned char bitstream_version)
+ {
++ unsigned char * const op_end = out + *out_len;
+ const unsigned char *ip = in;
+ unsigned char *op = out;
+ unsigned char *data_start;
+@@ -326,14 +361,18 @@ static int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
+ while (l > 20) {
+ size_t ll = min_t(size_t, l, m4_max_offset + 1);
+ uintptr_t ll_end = (uintptr_t) ip + ll;
++ int err;
++
+ if ((ll_end + ((t + ll) >> 5)) <= ll_end)
+ break;
+ BUILD_BUG_ON(D_SIZE * sizeof(lzo_dict_t) > LZO1X_1_MEM_COMPRESS);
+ memset(wrkmem, 0, D_SIZE * sizeof(lzo_dict_t));
+- t = lzo1x_1_do_compress(ip, ll, op, out_len, t, wrkmem,
+- &state_offset, bitstream_version);
++ err = LZO_SAFE(lzo1x_1_do_compress)(
++ ip, ll, &op, op_end, &t, wrkmem,
++ &state_offset, bitstream_version);
++ if (err != LZO_E_OK)
++ return err;
+ ip += ll;
+- op += *out_len;
+ l -= ll;
+ }
+ t += l;
+@@ -342,20 +381,26 @@ static int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
+ const unsigned char *ii = in + in_len - t;
+
+ if (op == data_start && t <= 238) {
++ NEED_OP(1);
+ *op++ = (17 + t);
+ } else if (t <= 3) {
+ op[state_offset] |= t;
+ } else if (t <= 18) {
++ NEED_OP(1);
+ *op++ = (t - 3);
+ } else {
+ size_t tt = t - 18;
++ NEED_OP(1);
+ *op++ = 0;
+ while (tt > 255) {
+ tt -= 255;
++ NEED_OP(1);
+ *op++ = 0;
+ }
++ NEED_OP(1);
+ *op++ = tt;
+ }
++ NEED_OP(t);
+ if (t >= 16) do {
+ COPY8(op, ii);
+ COPY8(op + 8, ii + 8);
+@@ -368,31 +413,38 @@ static int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
+ } while (--t > 0);
+ }
+
++ NEED_OP(3);
+ *op++ = M4_MARKER | 1;
+ *op++ = 0;
+ *op++ = 0;
+
+ *out_len = op - out;
+ return LZO_E_OK;
++
++output_overrun:
++ return LZO_E_OUTPUT_OVERRUN;
+ }
+
+-int lzo1x_1_compress(const unsigned char *in, size_t in_len,
+- unsigned char *out, size_t *out_len,
+- void *wrkmem)
++int LZO_SAFE(lzo1x_1_compress)(const unsigned char *in, size_t in_len,
++ unsigned char *out, size_t *out_len,
++ void *wrkmem)
+ {
+- return lzogeneric1x_1_compress(in, in_len, out, out_len, wrkmem, 0);
++ return LZO_SAFE(lzogeneric1x_1_compress)(
++ in, in_len, out, out_len, wrkmem, 0);
+ }
+
+-int lzorle1x_1_compress(const unsigned char *in, size_t in_len,
+- unsigned char *out, size_t *out_len,
+- void *wrkmem)
++int LZO_SAFE(lzorle1x_1_compress)(const unsigned char *in, size_t in_len,
++ unsigned char *out, size_t *out_len,
++ void *wrkmem)
+ {
+- return lzogeneric1x_1_compress(in, in_len, out, out_len,
+- wrkmem, LZO_VERSION);
++ return LZO_SAFE(lzogeneric1x_1_compress)(
++ in, in_len, out, out_len, wrkmem, LZO_VERSION);
+ }
+
+-EXPORT_SYMBOL_GPL(lzo1x_1_compress);
+-EXPORT_SYMBOL_GPL(lzorle1x_1_compress);
++EXPORT_SYMBOL_GPL(LZO_SAFE(lzo1x_1_compress));
++EXPORT_SYMBOL_GPL(LZO_SAFE(lzorle1x_1_compress));
+
++#ifndef LZO_UNSAFE
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("LZO1X-1 Compressor");
++#endif
+diff --git a/lib/lzo/lzo1x_compress_safe.c b/lib/lzo/lzo1x_compress_safe.c
+new file mode 100644
+index 0000000000000..371c9f8494928
+--- /dev/null
++++ b/lib/lzo/lzo1x_compress_safe.c
+@@ -0,0 +1,18 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * LZO1X Compressor from LZO
++ *
++ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
++ *
++ * The full LZO package can be found at:
++ * http://www.oberhumer.com/opensource/lzo/
++ *
++ * Changed for Linux kernel use by:
++ * Nitin Gupta <nitingupta910@gmail.com>
++ * Richard Purdie <rpurdie@openedhand.com>
++ */
++
++#define LZO_SAFE(name) name##_safe
++#define HAVE_OP(x) ((size_t)(op_end - op) >= (size_t)(x))
++
++#include "lzo1x_compress.c"
+--
+2.39.5
+
--- /dev/null
+From cc9bc41542af3f0046bb04685ff19d3beb376b0a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 08:42:25 +0100
+Subject: crypto: mxs-dcp - Only set OTP_KEY bit for OTP key
+
+From: Sven Schwermer <sven@svenschwermer.de>
+
+[ Upstream commit caa9dbb76ff52ec848a57245062aaeaa07740adc ]
+
+While MXS_DCP_CONTROL0_OTP_KEY is set, the CRYPTO_KEY (DCP_PAES_KEY_OTP)
+is used even if the UNIQUE_KEY (DCP_PAES_KEY_UNIQUE) is selected. This
+is not clearly documented, but this implementation is consistent with
+NXP's downstream kernel fork and optee_os.
+
+Signed-off-by: Sven Schwermer <sven@svenschwermer.de>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/mxs-dcp.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c
+index 77a6301f37f0a..29c0c69d5905d 100644
+--- a/drivers/crypto/mxs-dcp.c
++++ b/drivers/crypto/mxs-dcp.c
+@@ -265,12 +265,12 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx,
+ MXS_DCP_CONTROL0_INTERRUPT |
+ MXS_DCP_CONTROL0_ENABLE_CIPHER;
+
+- if (key_referenced)
+- /* Set OTP key bit to select the key via KEY_SELECT. */
+- desc->control0 |= MXS_DCP_CONTROL0_OTP_KEY;
+- else
++ if (!key_referenced)
+ /* Payload contains the key. */
+ desc->control0 |= MXS_DCP_CONTROL0_PAYLOAD_KEY;
++ else if (actx->key[0] == DCP_PAES_KEY_OTP)
++ /* Set OTP key bit to select the key via KEY_SELECT. */
++ desc->control0 |= MXS_DCP_CONTROL0_OTP_KEY;
+
+ if (rctx->enc)
+ desc->control0 |= MXS_DCP_CONTROL0_CIPHER_ENCRYPT;
+--
+2.39.5
+
--- /dev/null
+From 33582ad9031c30e18bc0937d31400f2c65bb8ee6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Mar 2025 13:27:05 +0530
+Subject: crypto: octeontx2 - suppress auth failure screaming due to negative
+ tests
+
+From: Shashank Gupta <shashankg@marvell.com>
+
+[ Upstream commit 64b7871522a4cba99d092e1c849d6f9092868aaa ]
+
+This patch addresses an issue where authentication failures were being
+erroneously reported due to negative test failures in the "ccm(aes)"
+selftest.
+pr_debug suppress unnecessary screaming of these tests.
+
+Signed-off-by: Shashank Gupta <shashankg@marvell.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/marvell/octeontx2/otx2_cptvf_reqmgr.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf_reqmgr.c b/drivers/crypto/marvell/octeontx2/otx2_cptvf_reqmgr.c
+index 5387c68f3c9df..4262441070372 100644
+--- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_reqmgr.c
++++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_reqmgr.c
+@@ -264,9 +264,10 @@ static int cpt_process_ccode(struct otx2_cptlfs_info *lfs,
+ break;
+ }
+
+- dev_err(&pdev->dev,
+- "Request failed with software error code 0x%x\n",
+- cpt_status->s.uc_compcode);
++ pr_debug("Request failed with software error code 0x%x: algo = %s driver = %s\n",
++ cpt_status->s.uc_compcode,
++ info->req->areq->tfm->__crt_alg->cra_name,
++ info->req->areq->tfm->__crt_alg->cra_driver_name);
+ otx2_cpt_dump_sg_list(pdev, info->req);
+ break;
+ }
+--
+2.39.5
+
--- /dev/null
+From 32b9c5acf8b2d1d9d1125c23da88ca3d71e7df42 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Feb 2025 08:57:51 +0800
+Subject: crypto: skcipher - Zap type in crypto_alloc_sync_skcipher
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+[ Upstream commit ee509efc74ddbc59bb5d6fd6e050f9ef25f74bff ]
+
+The type needs to be zeroed as otherwise the user could use it to
+allocate an asynchronous sync skcipher.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ crypto/skcipher.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/crypto/skcipher.c b/crypto/skcipher.c
+index ceed7f33a67ba..fd3273b519dc0 100644
+--- a/crypto/skcipher.c
++++ b/crypto/skcipher.c
+@@ -844,6 +844,7 @@ struct crypto_sync_skcipher *crypto_alloc_sync_skcipher(
+
+ /* Only sync algorithms allowed. */
+ mask |= CRYPTO_ALG_ASYNC | CRYPTO_ALG_SKCIPHER_REQSIZE_LARGE;
++ type &= ~(CRYPTO_ALG_ASYNC | CRYPTO_ALG_SKCIPHER_REQSIZE_LARGE);
+
+ tfm = crypto_alloc_tfm(alg_name, &crypto_skcipher_type, type, mask);
+
+--
+2.39.5
+
--- /dev/null
+From cfba0beb16b95e847ca9d7d1d4331394b91d371f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Mar 2025 15:36:21 +0800
+Subject: dlm: make tcp still work in multi-link env
+
+From: Heming Zhao <heming.zhao@suse.com>
+
+[ Upstream commit 03d2b62208a336a3bb984b9465ef6d89a046ea22 ]
+
+This patch bypasses multi-link errors in TCP mode, allowing dlm
+to operate on the first tcp link.
+
+Signed-off-by: Heming Zhao <heming.zhao@suse.com>
+Signed-off-by: David Teigland <teigland@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/dlm/lowcomms.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
+index f2d88a3581695..10461451185e8 100644
+--- a/fs/dlm/lowcomms.c
++++ b/fs/dlm/lowcomms.c
+@@ -1826,8 +1826,8 @@ static int dlm_tcp_listen_validate(void)
+ {
+ /* We don't support multi-homed hosts */
+ if (dlm_local_count > 1) {
+- log_print("TCP protocol can't handle multi-homed hosts, try SCTP");
+- return -EINVAL;
++ log_print("Detect multi-homed hosts but use only the first IP address.");
++ log_print("Try SCTP, if you want to enable multi-link.");
+ }
+
+ return 0;
+--
+2.39.5
+
--- /dev/null
+From 6b4ef8c7424978499bebcc34cf1fa592999ee43b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Mar 2025 16:41:50 +0800
+Subject: dm cache: prevent BUG_ON by blocking retries on failed device resumes
+
+From: Ming-Hung Tsai <mtsai@redhat.com>
+
+[ Upstream commit 5da692e2262b8f81993baa9592f57d12c2703dea ]
+
+A cache device failing to resume due to mapping errors should not be
+retried, as the failure leaves a partially initialized policy object.
+Repeating the resume operation risks triggering BUG_ON when reloading
+cache mappings into the incomplete policy object.
+
+Reproduce steps:
+
+1. create a cache metadata consisting of 512 or more cache blocks,
+ with some mappings stored in the first array block of the mapping
+ array. Here we use cache_restore v1.0 to build the metadata.
+
+cat <<EOF >> cmeta.xml
+<superblock uuid="" block_size="128" nr_cache_blocks="512" \
+policy="smq" hint_width="4">
+ <mappings>
+ <mapping cache_block="0" origin_block="0" dirty="false"/>
+ </mappings>
+</superblock>
+EOF
+dmsetup create cmeta --table "0 8192 linear /dev/sdc 0"
+cache_restore -i cmeta.xml -o /dev/mapper/cmeta --metadata-version=2
+dmsetup remove cmeta
+
+2. wipe the second array block of the mapping array to simulate
+ data degradations.
+
+mapping_root=$(dd if=/dev/sdc bs=1c count=8 skip=192 \
+2>/dev/null | hexdump -e '1/8 "%u\n"')
+ablock=$(dd if=/dev/sdc bs=1c count=8 skip=$((4096*mapping_root+2056)) \
+2>/dev/null | hexdump -e '1/8 "%u\n"')
+dd if=/dev/zero of=/dev/sdc bs=4k count=1 seek=$ablock
+
+3. try bringing up the cache device. The resume is expected to fail
+ due to the broken array block.
+
+dmsetup create cmeta --table "0 8192 linear /dev/sdc 0"
+dmsetup create cdata --table "0 65536 linear /dev/sdc 8192"
+dmsetup create corig --table "0 524288 linear /dev/sdc 262144"
+dmsetup create cache --notable
+dmsetup load cache --table "0 524288 cache /dev/mapper/cmeta \
+/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"
+dmsetup resume cache
+
+4. try resuming the cache again. An unexpected BUG_ON is triggered
+ while loading cache mappings.
+
+dmsetup resume cache
+
+Kernel logs:
+
+(snip)
+------------[ cut here ]------------
+kernel BUG at drivers/md/dm-cache-policy-smq.c:752!
+Oops: invalid opcode: 0000 [#1] PREEMPT SMP KASAN NOPTI
+CPU: 0 UID: 0 PID: 332 Comm: dmsetup Not tainted 6.13.4 #3
+RIP: 0010:smq_load_mapping+0x3e5/0x570
+
+Fix by disallowing resume operations for devices that failed the
+initial attempt.
+
+Signed-off-by: Ming-Hung Tsai <mtsai@redhat.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-cache-target.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
+index 849eb6333e980..6aa4095dc5876 100644
+--- a/drivers/md/dm-cache-target.c
++++ b/drivers/md/dm-cache-target.c
+@@ -2899,6 +2899,27 @@ static dm_cblock_t get_cache_dev_size(struct cache *cache)
+ return to_cblock(size);
+ }
+
++static bool can_resume(struct cache *cache)
++{
++ /*
++ * Disallow retrying the resume operation for devices that failed the
++ * first resume attempt, as the failure leaves the policy object partially
++ * initialized. Retrying could trigger BUG_ON when loading cache mappings
++ * into the incomplete policy object.
++ */
++ if (cache->sized && !cache->loaded_mappings) {
++ if (get_cache_mode(cache) != CM_WRITE)
++ DMERR("%s: unable to resume a failed-loaded cache, please check metadata.",
++ cache_device_name(cache));
++ else
++ DMERR("%s: unable to resume cache due to missing proper cache table reload",
++ cache_device_name(cache));
++ return false;
++ }
++
++ return true;
++}
++
+ static bool can_resize(struct cache *cache, dm_cblock_t new_size)
+ {
+ if (from_cblock(new_size) > from_cblock(cache->cache_size)) {
+@@ -2947,6 +2968,9 @@ static int cache_preresume(struct dm_target *ti)
+ struct cache *cache = ti->private;
+ dm_cblock_t csize = get_cache_dev_size(cache);
+
++ if (!can_resume(cache))
++ return -EINVAL;
++
+ /*
+ * Check to see if the cache has resized.
+ */
+--
+2.39.5
+
--- /dev/null
+From 1ec4b4bf74ddb75fb02a09ab8e7a8bc1864c7107 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 19:20:14 +0800
+Subject: dm: fix unconditional IO throttle caused by REQ_PREFLUSH
+
+From: Jinliang Zheng <alexjlzheng@gmail.com>
+
+[ Upstream commit 88f7f56d16f568f19e1a695af34a7f4a6ce537a6 ]
+
+When a bio with REQ_PREFLUSH is submitted to dm, __send_empty_flush()
+generates a flush_bio with REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC,
+which causes the flush_bio to be throttled by wbt_wait().
+
+An example from v5.4, similar problem also exists in upstream:
+
+ crash> bt 2091206
+ PID: 2091206 TASK: ffff2050df92a300 CPU: 109 COMMAND: "kworker/u260:0"
+ #0 [ffff800084a2f7f0] __switch_to at ffff80004008aeb8
+ #1 [ffff800084a2f820] __schedule at ffff800040bfa0c4
+ #2 [ffff800084a2f880] schedule at ffff800040bfa4b4
+ #3 [ffff800084a2f8a0] io_schedule at ffff800040bfa9c4
+ #4 [ffff800084a2f8c0] rq_qos_wait at ffff8000405925bc
+ #5 [ffff800084a2f940] wbt_wait at ffff8000405bb3a0
+ #6 [ffff800084a2f9a0] __rq_qos_throttle at ffff800040592254
+ #7 [ffff800084a2f9c0] blk_mq_make_request at ffff80004057cf38
+ #8 [ffff800084a2fa60] generic_make_request at ffff800040570138
+ #9 [ffff800084a2fae0] submit_bio at ffff8000405703b4
+ #10 [ffff800084a2fb50] xlog_write_iclog at ffff800001280834 [xfs]
+ #11 [ffff800084a2fbb0] xlog_sync at ffff800001280c3c [xfs]
+ #12 [ffff800084a2fbf0] xlog_state_release_iclog at ffff800001280df4 [xfs]
+ #13 [ffff800084a2fc10] xlog_write at ffff80000128203c [xfs]
+ #14 [ffff800084a2fcd0] xlog_cil_push at ffff8000012846dc [xfs]
+ #15 [ffff800084a2fda0] xlog_cil_push_work at ffff800001284a2c [xfs]
+ #16 [ffff800084a2fdb0] process_one_work at ffff800040111d08
+ #17 [ffff800084a2fe00] worker_thread at ffff8000401121cc
+ #18 [ffff800084a2fe70] kthread at ffff800040118de4
+
+After commit 2def2845cc33 ("xfs: don't allow log IO to be throttled"),
+the metadata submitted by xlog_write_iclog() should not be throttled.
+But due to the existence of the dm layer, throttling flush_bio indirectly
+causes the metadata bio to be throttled.
+
+Fix this by conditionally adding REQ_IDLE to flush_bio.bi_opf, which makes
+wbt_should_throttle() return false to avoid wbt_wait().
+
+Signed-off-by: Jinliang Zheng <alexjlzheng@tencent.com>
+Reviewed-by: Tianxiang Peng <txpeng@tencent.com>
+Reviewed-by: Hao Peng <flyingpeng@tencent.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/md/dm.c b/drivers/md/dm.c
+index 19230404d8c2b..d29125ee9e72a 100644
+--- a/drivers/md/dm.c
++++ b/drivers/md/dm.c
+@@ -1541,14 +1541,18 @@ static void __send_empty_flush(struct clone_info *ci)
+ {
+ struct dm_table *t = ci->map;
+ struct bio flush_bio;
++ blk_opf_t opf = REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC;
++
++ if ((ci->io->orig_bio->bi_opf & (REQ_IDLE | REQ_SYNC)) ==
++ (REQ_IDLE | REQ_SYNC))
++ opf |= REQ_IDLE;
+
+ /*
+ * Use an on-stack bio for this, it's safe since we don't
+ * need to reference it after submit. It's just used as
+ * the basis for the clone(s).
+ */
+- bio_init(&flush_bio, ci->io->md->disk->part0, NULL, 0,
+- REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC);
++ bio_init(&flush_bio, ci->io->md->disk->part0, NULL, 0, opf);
+
+ ci->bio = &flush_bio;
+ ci->sector_count = 0;
+--
+2.39.5
+
--- /dev/null
+From 63838f2c630800f60d77ad2167e4994dc5d4ba42 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Mar 2025 13:51:32 +0100
+Subject: dm: restrict dm device size to 2^63-512 bytes
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+[ Upstream commit 45fc728515c14f53f6205789de5bfd72a95af3b8 ]
+
+The devices with size >= 2^63 bytes can't be used reliably by userspace
+because the type off_t is a signed 64-bit integer.
+
+Therefore, we limit the maximum size of a device mapper device to
+2^63-512 bytes.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-table.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
+index 3dc5bc3d29d64..883f01e78324f 100644
+--- a/drivers/md/dm-table.c
++++ b/drivers/md/dm-table.c
+@@ -698,6 +698,10 @@ int dm_table_add_target(struct dm_table *t, const char *type,
+ DMERR("%s: zero-length target", dm_device_name(t->md));
+ return -EINVAL;
+ }
++ if (start + len < start || start + len > LLONG_MAX >> SECTOR_SHIFT) {
++ DMERR("%s: too large device", dm_device_name(t->md));
++ return -EINVAL;
++ }
+
+ ti->type = dm_get_target_type(type);
+ if (!ti->type) {
+--
+2.39.5
+
--- /dev/null
+From 26b0854dfa27b44eccd2d19e1db372be63432dc1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jan 2025 18:27:12 -0500
+Subject: dm vdo indexer: prevent unterminated string warning
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Chung Chung <cchung@redhat.com>
+
+[ Upstream commit f4e99b846c90163d350c69d6581ac38dd5818eb8 ]
+
+Fix array initialization that triggers a warning:
+
+error: initializer-string for array of ‘unsigned char’ is too long
+ [-Werror=unterminated-string-initialization]
+
+Signed-off-by: Chung Chung <cchung@redhat.com>
+Signed-off-by: Matthew Sakai <msakai@redhat.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-vdo/indexer/index-layout.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/md/dm-vdo/indexer/index-layout.c b/drivers/md/dm-vdo/indexer/index-layout.c
+index 627adc24af3b7..053b7845d1f34 100644
+--- a/drivers/md/dm-vdo/indexer/index-layout.c
++++ b/drivers/md/dm-vdo/indexer/index-layout.c
+@@ -54,7 +54,6 @@
+ * Each save also has a unique nonce.
+ */
+
+-#define MAGIC_SIZE 32
+ #define NONCE_INFO_SIZE 32
+ #define MAX_SAVES 2
+
+@@ -98,9 +97,11 @@ enum region_type {
+ #define SUPER_VERSION_CURRENT 3
+ #define SUPER_VERSION_MAXIMUM 7
+
+-static const u8 LAYOUT_MAGIC[MAGIC_SIZE] = "*ALBIREO*SINGLE*FILE*LAYOUT*001*";
++static const u8 LAYOUT_MAGIC[] = "*ALBIREO*SINGLE*FILE*LAYOUT*001*";
+ static const u64 REGION_MAGIC = 0x416c6252676e3031; /* 'AlbRgn01' */
+
++#define MAGIC_SIZE (sizeof(LAYOUT_MAGIC) - 1)
++
+ struct region_header {
+ u64 magic;
+ u64 region_blocks;
+--
+2.39.5
+
--- /dev/null
+From 35a4eda668c9bbe8d4ab8887a89ce676ee8d5a62 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jan 2025 18:26:05 -0500
+Subject: dm vdo: use a short static string for thread name prefix
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Matthew Sakai <msakai@redhat.com>
+
+[ Upstream commit 3280c9313c9adce01550cc9f00edfb1dc7c744da ]
+
+Also remove MODULE_NAME and a BUG_ON check, both unneeded.
+
+This fixes a warning about string truncation in snprintf that
+will never happen in practice:
+
+drivers/md/dm-vdo/vdo.c: In function ‘vdo_make’:
+drivers/md/dm-vdo/vdo.c:564:5: error: ‘%s’ directive output may be truncated writing up to 55 bytes into a region of size 16 [-Werror=format-truncation=]
+ "%s%u", MODULE_NAME, instance);
+ ^~
+drivers/md/dm-vdo/vdo.c:563:2: note: ‘snprintf’ output between 2 and 66 bytes into a destination of size 16
+ snprintf(vdo->thread_name_prefix, sizeof(vdo->thread_name_prefix),
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ "%s%u", MODULE_NAME, instance);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Reported-by: John Garry <john.g.garry@oracle.com>
+Reviewed-by: John Garry <john.g.garry@oracle.com>
+Signed-off-by: Matthew Sakai <msakai@redhat.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-vdo/vdo.c | 11 +----------
+ 1 file changed, 1 insertion(+), 10 deletions(-)
+
+diff --git a/drivers/md/dm-vdo/vdo.c b/drivers/md/dm-vdo/vdo.c
+index fff847767755a..b897f88250d2a 100644
+--- a/drivers/md/dm-vdo/vdo.c
++++ b/drivers/md/dm-vdo/vdo.c
+@@ -31,9 +31,7 @@
+
+ #include <linux/completion.h>
+ #include <linux/device-mapper.h>
+-#include <linux/kernel.h>
+ #include <linux/lz4.h>
+-#include <linux/module.h>
+ #include <linux/mutex.h>
+ #include <linux/spinlock.h>
+ #include <linux/types.h>
+@@ -142,12 +140,6 @@ static void finish_vdo_request_queue(void *ptr)
+ vdo_unregister_allocating_thread();
+ }
+
+-#ifdef MODULE
+-#define MODULE_NAME THIS_MODULE->name
+-#else
+-#define MODULE_NAME "dm-vdo"
+-#endif /* MODULE */
+-
+ static const struct vdo_work_queue_type default_queue_type = {
+ .start = start_vdo_request_queue,
+ .finish = finish_vdo_request_queue,
+@@ -559,8 +551,7 @@ int vdo_make(unsigned int instance, struct device_config *config, char **reason,
+ *vdo_ptr = vdo;
+
+ snprintf(vdo->thread_name_prefix, sizeof(vdo->thread_name_prefix),
+- "%s%u", MODULE_NAME, instance);
+- BUG_ON(vdo->thread_name_prefix[0] == '\0');
++ "vdo%u", instance);
+ result = vdo_allocate(vdo->thread_config.thread_count,
+ struct vdo_thread, __func__, &vdo->threads);
+ if (result != VDO_SUCCESS) {
+--
+2.39.5
+
--- /dev/null
+From ac663217ac4eeab508db348a67511d45ccd9846f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jan 2025 21:18:05 -0500
+Subject: dm vdo vio-pool: allow variable-sized metadata vios
+
+From: Ken Raeburn <raeburn@redhat.com>
+
+[ Upstream commit f979da512553a41a657f2c1198277e84d66f8ce3 ]
+
+With larger-sized metadata vio pools, vdo will sometimes need to
+issue I/O with a smaller size than the allocated size. Since
+vio_reset_bio is where the bvec array and I/O size are initialized,
+this reset interface must now specify what I/O size to use.
+
+Signed-off-by: Ken Raeburn <raeburn@redhat.com>
+Signed-off-by: Matthew Sakai <msakai@redhat.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-vdo/io-submitter.c | 6 ++++--
+ drivers/md/dm-vdo/io-submitter.h | 18 +++++++++++++---
+ drivers/md/dm-vdo/types.h | 3 +++
+ drivers/md/dm-vdo/vio.c | 36 +++++++++++++++++++-------------
+ drivers/md/dm-vdo/vio.h | 2 ++
+ 5 files changed, 46 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/md/dm-vdo/io-submitter.c b/drivers/md/dm-vdo/io-submitter.c
+index ab62abe18827b..a664be89c15d7 100644
+--- a/drivers/md/dm-vdo/io-submitter.c
++++ b/drivers/md/dm-vdo/io-submitter.c
+@@ -327,6 +327,7 @@ void vdo_submit_data_vio(struct data_vio *data_vio)
+ * @error_handler: the handler for submission or I/O errors (may be NULL)
+ * @operation: the type of I/O to perform
+ * @data: the buffer to read or write (may be NULL)
++ * @size: the I/O amount in bytes
+ *
+ * The vio is enqueued on a vdo bio queue so that bio submission (which may block) does not block
+ * other vdo threads.
+@@ -338,7 +339,7 @@ void vdo_submit_data_vio(struct data_vio *data_vio)
+ */
+ void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical,
+ bio_end_io_t callback, vdo_action_fn error_handler,
+- blk_opf_t operation, char *data)
++ blk_opf_t operation, char *data, int size)
+ {
+ int result;
+ struct vdo_completion *completion = &vio->completion;
+@@ -349,7 +350,8 @@ void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical,
+
+ vdo_reset_completion(completion);
+ completion->error_handler = error_handler;
+- result = vio_reset_bio(vio, data, callback, operation | REQ_META, physical);
++ result = vio_reset_bio_with_size(vio, data, size, callback, operation | REQ_META,
++ physical);
+ if (result != VDO_SUCCESS) {
+ continue_vio(vio, result);
+ return;
+diff --git a/drivers/md/dm-vdo/io-submitter.h b/drivers/md/dm-vdo/io-submitter.h
+index 80748699496f2..3088f11055fdd 100644
+--- a/drivers/md/dm-vdo/io-submitter.h
++++ b/drivers/md/dm-vdo/io-submitter.h
+@@ -8,6 +8,7 @@
+
+ #include <linux/bio.h>
+
++#include "constants.h"
+ #include "types.h"
+
+ struct io_submitter;
+@@ -26,14 +27,25 @@ void vdo_submit_data_vio(struct data_vio *data_vio);
+
+ void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical,
+ bio_end_io_t callback, vdo_action_fn error_handler,
+- blk_opf_t operation, char *data);
++ blk_opf_t operation, char *data, int size);
+
+ static inline void vdo_submit_metadata_vio(struct vio *vio, physical_block_number_t physical,
+ bio_end_io_t callback, vdo_action_fn error_handler,
+ blk_opf_t operation)
+ {
+ __submit_metadata_vio(vio, physical, callback, error_handler,
+- operation, vio->data);
++ operation, vio->data, vio->block_count * VDO_BLOCK_SIZE);
++}
++
++static inline void vdo_submit_metadata_vio_with_size(struct vio *vio,
++ physical_block_number_t physical,
++ bio_end_io_t callback,
++ vdo_action_fn error_handler,
++ blk_opf_t operation,
++ int size)
++{
++ __submit_metadata_vio(vio, physical, callback, error_handler,
++ operation, vio->data, size);
+ }
+
+ static inline void vdo_submit_flush_vio(struct vio *vio, bio_end_io_t callback,
+@@ -41,7 +53,7 @@ static inline void vdo_submit_flush_vio(struct vio *vio, bio_end_io_t callback,
+ {
+ /* FIXME: Can we just use REQ_OP_FLUSH? */
+ __submit_metadata_vio(vio, 0, callback, error_handler,
+- REQ_OP_WRITE | REQ_PREFLUSH, NULL);
++ REQ_OP_WRITE | REQ_PREFLUSH, NULL, 0);
+ }
+
+ #endif /* VDO_IO_SUBMITTER_H */
+diff --git a/drivers/md/dm-vdo/types.h b/drivers/md/dm-vdo/types.h
+index dbe892b10f265..cdf36e7d77021 100644
+--- a/drivers/md/dm-vdo/types.h
++++ b/drivers/md/dm-vdo/types.h
+@@ -376,6 +376,9 @@ struct vio {
+ /* The size of this vio in blocks */
+ unsigned int block_count;
+
++ /* The amount of data to be read or written, in bytes */
++ unsigned int io_size;
++
+ /* The data being read or written. */
+ char *data;
+
+diff --git a/drivers/md/dm-vdo/vio.c b/drivers/md/dm-vdo/vio.c
+index b291578f726f5..7c417c1af4516 100644
+--- a/drivers/md/dm-vdo/vio.c
++++ b/drivers/md/dm-vdo/vio.c
+@@ -188,14 +188,23 @@ void vdo_set_bio_properties(struct bio *bio, struct vio *vio, bio_end_io_t callb
+
+ /*
+ * Prepares the bio to perform IO with the specified buffer. May only be used on a VDO-allocated
+- * bio, as it assumes the bio wraps a 4k buffer that is 4k aligned, but there does not have to be a
+- * vio associated with the bio.
++ * bio, as it assumes the bio wraps a 4k-multiple buffer that is 4k aligned, but there does not
++ * have to be a vio associated with the bio.
+ */
+ int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback,
+ blk_opf_t bi_opf, physical_block_number_t pbn)
+ {
+- int bvec_count, offset, len, i;
++ return vio_reset_bio_with_size(vio, data, vio->block_count * VDO_BLOCK_SIZE,
++ callback, bi_opf, pbn);
++}
++
++int vio_reset_bio_with_size(struct vio *vio, char *data, int size, bio_end_io_t callback,
++ blk_opf_t bi_opf, physical_block_number_t pbn)
++{
++ int bvec_count, offset, i;
+ struct bio *bio = vio->bio;
++ int vio_size = vio->block_count * VDO_BLOCK_SIZE;
++ int remaining;
+
+ bio_reset(bio, bio->bi_bdev, bi_opf);
+ vdo_set_bio_properties(bio, vio, callback, bi_opf, pbn);
+@@ -204,22 +213,21 @@ int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback,
+
+ bio->bi_io_vec = bio->bi_inline_vecs;
+ bio->bi_max_vecs = vio->block_count + 1;
+- len = VDO_BLOCK_SIZE * vio->block_count;
++ if (VDO_ASSERT(size <= vio_size, "specified size %d is not greater than allocated %d",
++ size, vio_size) != VDO_SUCCESS)
++ size = vio_size;
++ vio->io_size = size;
+ offset = offset_in_page(data);
+- bvec_count = DIV_ROUND_UP(offset + len, PAGE_SIZE);
++ bvec_count = DIV_ROUND_UP(offset + size, PAGE_SIZE);
++ remaining = size;
+
+- /*
+- * If we knew that data was always on one page, or contiguous pages, we wouldn't need the
+- * loop. But if we're using vmalloc, it's not impossible that the data is in different
+- * pages that can't be merged in bio_add_page...
+- */
+- for (i = 0; (i < bvec_count) && (len > 0); i++) {
++ for (i = 0; (i < bvec_count) && (remaining > 0); i++) {
+ struct page *page;
+ int bytes_added;
+ int bytes = PAGE_SIZE - offset;
+
+- if (bytes > len)
+- bytes = len;
++ if (bytes > remaining)
++ bytes = remaining;
+
+ page = is_vmalloc_addr(data) ? vmalloc_to_page(data) : virt_to_page(data);
+ bytes_added = bio_add_page(bio, page, bytes, offset);
+@@ -231,7 +239,7 @@ int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback,
+ }
+
+ data += bytes;
+- len -= bytes;
++ remaining -= bytes;
+ offset = 0;
+ }
+
+diff --git a/drivers/md/dm-vdo/vio.h b/drivers/md/dm-vdo/vio.h
+index 3490e9f59b04a..74e8fd7c8c029 100644
+--- a/drivers/md/dm-vdo/vio.h
++++ b/drivers/md/dm-vdo/vio.h
+@@ -123,6 +123,8 @@ void vdo_set_bio_properties(struct bio *bio, struct vio *vio, bio_end_io_t callb
+
+ int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback,
+ blk_opf_t bi_opf, physical_block_number_t pbn);
++int vio_reset_bio_with_size(struct vio *vio, char *data, int size, bio_end_io_t callback,
++ blk_opf_t bi_opf, physical_block_number_t pbn);
+
+ void update_vio_error_stats(struct vio *vio, const char *format, ...)
+ __printf(2, 3);
+--
+2.39.5
+
--- /dev/null
+From ce99cfd11c6f65658876d9cdaa5fa897d301669e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Apr 2025 09:56:59 +0200
+Subject: dma-mapping: avoid potential unused data compilation warning
+
+From: Marek Szyprowski <m.szyprowski@samsung.com>
+
+[ Upstream commit c9b19ea63036fc537a69265acea1b18dabd1cbd3 ]
+
+When CONFIG_NEED_DMA_MAP_STATE is not defined, dma-mapping clients might
+report unused data compilation warnings for dma_unmap_*() calls
+arguments. Redefine macros for those calls to let compiler to notice that
+it is okay when the provided arguments are not used.
+
+Reported-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Suggested-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Tested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://lore.kernel.org/r/20250415075659.428549-1-m.szyprowski@samsung.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/dma-mapping.h | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
+index 1524da363734a..22b9099927fad 100644
+--- a/include/linux/dma-mapping.h
++++ b/include/linux/dma-mapping.h
+@@ -633,10 +633,14 @@ static inline int dma_mmap_wc(struct device *dev,
+ #else
+ #define DEFINE_DMA_UNMAP_ADDR(ADDR_NAME)
+ #define DEFINE_DMA_UNMAP_LEN(LEN_NAME)
+-#define dma_unmap_addr(PTR, ADDR_NAME) (0)
+-#define dma_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0)
+-#define dma_unmap_len(PTR, LEN_NAME) (0)
+-#define dma_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
++#define dma_unmap_addr(PTR, ADDR_NAME) \
++ ({ typeof(PTR) __p __maybe_unused = PTR; 0; })
++#define dma_unmap_addr_set(PTR, ADDR_NAME, VAL) \
++ do { typeof(PTR) __p __maybe_unused = PTR; } while (0)
++#define dma_unmap_len(PTR, LEN_NAME) \
++ ({ typeof(PTR) __p __maybe_unused = PTR; 0; })
++#define dma_unmap_len_set(PTR, LEN_NAME, VAL) \
++ do { typeof(PTR) __p __maybe_unused = PTR; } while (0)
+ #endif
+
+ #endif /* _LINUX_DMA_MAPPING_H */
+--
+2.39.5
+
--- /dev/null
+From 14a4bcd5edb19a2180a15e62dd54be3dc3cf9c8e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Apr 2025 21:40:34 +1000
+Subject: dma-mapping: Fix warning reported for missing prototype
+
+From: Balbir Singh <balbirs@nvidia.com>
+
+[ Upstream commit cae5572ec9261f752af834cdaaf5a0ba0afcf256 ]
+
+lkp reported a warning about missing prototype for a recent patch.
+
+The kernel-doc style comments are out of sync, move them to the right
+function.
+
+Cc: Marek Szyprowski <m.szyprowski@samsung.com>
+Cc: Christoph Hellwig <hch@lst.de>
+
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202504190615.g9fANxHw-lkp@intel.com/
+
+Signed-off-by: Balbir Singh <balbirs@nvidia.com>
+[mszyprow: reformatted subject]
+Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Link: https://lore.kernel.org/r/20250422114034.3535515-1-balbirs@nvidia.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/dma/mapping.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
+index f7366083b4d00..74d453ec750a1 100644
+--- a/kernel/dma/mapping.c
++++ b/kernel/dma/mapping.c
+@@ -897,14 +897,6 @@ int dma_set_coherent_mask(struct device *dev, u64 mask)
+ }
+ EXPORT_SYMBOL(dma_set_coherent_mask);
+
+-/**
+- * dma_addressing_limited - return if the device is addressing limited
+- * @dev: device to check
+- *
+- * Return %true if the devices DMA mask is too small to address all memory in
+- * the system, else %false. Lack of addressing bits is the prime reason for
+- * bounce buffering, but might not be the only one.
+- */
+ static bool __dma_addressing_limited(struct device *dev)
+ {
+ const struct dma_map_ops *ops = get_dma_ops(dev);
+@@ -918,6 +910,14 @@ static bool __dma_addressing_limited(struct device *dev)
+ return !dma_direct_all_ram_mapped(dev);
+ }
+
++/**
++ * dma_addressing_limited - return if the device is addressing limited
++ * @dev: device to check
++ *
++ * Return %true if the devices DMA mask is too small to address all memory in
++ * the system, else %false. Lack of addressing bits is the prime reason for
++ * bounce buffering, but might not be the only one.
++ */
+ bool dma_addressing_limited(struct device *dev)
+ {
+ if (!__dma_addressing_limited(dev))
+--
+2.39.5
+
--- /dev/null
+From 6320d70e8750f51317c26dd7dcbf1dc3dbd1d9fc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Apr 2025 21:37:52 +1000
+Subject: dma/mapping.c: dev_dbg support for dma_addressing_limited
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Balbir Singh <balbirs@nvidia.com>
+
+[ Upstream commit 2042c352e21d19eaf5f9e22fb6afce72293ef28c ]
+
+In the debug and resolution of an issue involving forced use of bounce
+buffers, 7170130e4c72 ("x86/mm/init: Handle the special case of device
+private pages in add_pages(), to not increase max_pfn and trigger
+dma_addressing_limited() bounce buffers"). It would have been easier
+to debug the issue if dma_addressing_limited() had debug information
+about the device not being able to address all of memory and thus forcing
+all accesses through a bounce buffer. Please see[2]
+
+Implement dev_dbg to debug the potential use of bounce buffers
+when we hit the condition. When swiotlb is used,
+dma_addressing_limited() is used to determine the size of maximum dma
+buffer size in dma_direct_max_mapping_size(). The debug prints could be
+triggered in that check as well (when enabled).
+
+Link: https://lore.kernel.org/lkml/20250401000752.249348-1-balbirs@nvidia.com/ [1]
+Link: https://lore.kernel.org/lkml/20250310112206.4168-1-spasswolf@web.de/ [2]
+
+Cc: Marek Szyprowski <m.szyprowski@samsung.com>
+Cc: Robin Murphy <robin.murphy@arm.com>
+Cc: "Christian König" <christian.koenig@amd.com>
+Cc: Ingo Molnar <mingo@kernel.org>
+Cc: Kees Cook <kees@kernel.org>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Andy Lutomirski <luto@kernel.org>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Cc: Bert Karwatzki <spasswolf@web.de>
+Cc: Christoph Hellwig <hch@infradead.org>
+
+Signed-off-by: Balbir Singh <balbirs@nvidia.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Link: https://lore.kernel.org/r/20250414113752.3298276-1-balbirs@nvidia.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/dma/mapping.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
+index 864a1121bf086..f7366083b4d00 100644
+--- a/kernel/dma/mapping.c
++++ b/kernel/dma/mapping.c
+@@ -905,7 +905,7 @@ EXPORT_SYMBOL(dma_set_coherent_mask);
+ * the system, else %false. Lack of addressing bits is the prime reason for
+ * bounce buffering, but might not be the only one.
+ */
+-bool dma_addressing_limited(struct device *dev)
++static bool __dma_addressing_limited(struct device *dev)
+ {
+ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+@@ -917,6 +917,15 @@ bool dma_addressing_limited(struct device *dev)
+ return false;
+ return !dma_direct_all_ram_mapped(dev);
+ }
++
++bool dma_addressing_limited(struct device *dev)
++{
++ if (!__dma_addressing_limited(dev))
++ return false;
++
++ dev_dbg(dev, "device is DMA addressing limited\n");
++ return true;
++}
+ EXPORT_SYMBOL_GPL(dma_addressing_limited);
+
+ size_t dma_max_mapping_size(struct device *dev)
+--
+2.39.5
+
--- /dev/null
+From 88e379a687f56f3f051b7b0ccc61583144761644 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Feb 2025 15:02:10 +0000
+Subject: dpll: Add an assertion to check freq_supported_num
+
+From: Jiasheng Jiang <jiashengjiangcool@gmail.com>
+
+[ Upstream commit 39e912a959c19338855b768eaaee2917d7841f71 ]
+
+Since the driver is broken in the case that src->freq_supported is not
+NULL but src->freq_supported_num is 0, add an assertion for it.
+
+Signed-off-by: Jiasheng Jiang <jiashengjiangcool@gmail.com>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
+Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
+Link: https://patch.msgid.link/20250228150210.34404-1-jiashengjiangcool@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dpll/dpll_core.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
+index 1877201d1aa9f..20bdc52f63a50 100644
+--- a/drivers/dpll/dpll_core.c
++++ b/drivers/dpll/dpll_core.c
+@@ -443,8 +443,11 @@ static void dpll_pin_prop_free(struct dpll_pin_properties *prop)
+ static int dpll_pin_prop_dup(const struct dpll_pin_properties *src,
+ struct dpll_pin_properties *dst)
+ {
++ if (WARN_ON(src->freq_supported && !src->freq_supported_num))
++ return -EINVAL;
++
+ memcpy(dst, src, sizeof(*dst));
+- if (src->freq_supported && src->freq_supported_num) {
++ if (src->freq_supported) {
+ size_t freq_size = src->freq_supported_num *
+ sizeof(*src->freq_supported);
+ dst->freq_supported = kmemdup(src->freq_supported,
+--
+2.39.5
+
--- /dev/null
+From 130f8cb61ed4cdff36578a7b2dacaca00d65d024 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Mar 2025 16:57:51 +0800
+Subject: dql: Fix dql->limit value when reset.
+
+From: Jing Su <jingsusu@didiglobal.com>
+
+[ Upstream commit 3a17f23f7c36bac3a3584aaf97d3e3e0b2790396 ]
+
+Executing dql_reset after setting a non-zero value for limit_min can
+lead to an unreasonable situation where dql->limit is less than
+dql->limit_min.
+
+For instance, after setting
+/sys/class/net/eth*/queues/tx-0/byte_queue_limits/limit_min,
+an ifconfig down/up operation might cause the ethernet driver to call
+netdev_tx_reset_queue, which in turn invokes dql_reset.
+
+In this case, dql->limit is reset to 0 while dql->limit_min remains
+non-zero value, which is unexpected. The limit should always be
+greater than or equal to limit_min.
+
+Signed-off-by: Jing Su <jingsusu@didiglobal.com>
+Link: https://patch.msgid.link/Z9qHD1s/NEuQBdgH@pilot-ThinkCentre-M930t-N000
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ lib/dynamic_queue_limits.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/dynamic_queue_limits.c b/lib/dynamic_queue_limits.c
+index e49deddd3de9f..7d1dfbb99b397 100644
+--- a/lib/dynamic_queue_limits.c
++++ b/lib/dynamic_queue_limits.c
+@@ -190,7 +190,7 @@ EXPORT_SYMBOL(dql_completed);
+ void dql_reset(struct dql *dql)
+ {
+ /* Reset all dynamic values */
+- dql->limit = 0;
++ dql->limit = dql->min_limit;
+ dql->num_queued = 0;
+ dql->num_completed = 0;
+ dql->last_obj_cnt = 0;
+--
+2.39.5
+
--- /dev/null
+From d08c0e9f3594b4b54686440002e51986a7db1bca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Dec 2024 16:43:14 -0800
+Subject: drm: Add valid clones check
+
+From: Jessica Zhang <quic_jesszhan@quicinc.com>
+
+[ Upstream commit 41b4b11da02157c7474caf41d56baae0e941d01a ]
+
+Check that all encoders attached to a given CRTC are valid
+possible_clones of each other.
+
+Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
+Reviewed-by: Maxime Ripard <mripard@kernel.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20241216-concurrent-wb-v4-3-fe220297a7f0@quicinc.com
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_atomic_helper.c | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
+index 32902f77f00dd..40e4e1b6c9110 100644
+--- a/drivers/gpu/drm/drm_atomic_helper.c
++++ b/drivers/gpu/drm/drm_atomic_helper.c
+@@ -574,6 +574,30 @@ mode_valid(struct drm_atomic_state *state)
+ return 0;
+ }
+
++static int drm_atomic_check_valid_clones(struct drm_atomic_state *state,
++ struct drm_crtc *crtc)
++{
++ struct drm_encoder *drm_enc;
++ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
++ crtc);
++
++ drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) {
++ if (!drm_enc->possible_clones) {
++ DRM_DEBUG("enc%d possible_clones is 0\n", drm_enc->base.id);
++ continue;
++ }
++
++ if ((crtc_state->encoder_mask & drm_enc->possible_clones) !=
++ crtc_state->encoder_mask) {
++ DRM_DEBUG("crtc%d failed valid clone check for mask 0x%x\n",
++ crtc->base.id, crtc_state->encoder_mask);
++ return -EINVAL;
++ }
++ }
++
++ return 0;
++}
++
+ /**
+ * drm_atomic_helper_check_modeset - validate state object for modeset changes
+ * @dev: DRM device
+@@ -745,6 +769,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
+ ret = drm_atomic_add_affected_planes(state, crtc);
+ if (ret != 0)
+ return ret;
++
++ ret = drm_atomic_check_valid_clones(state, crtc);
++ if (ret != 0)
++ return ret;
+ }
+
+ /*
+--
+2.39.5
+
--- /dev/null
+From 86c790ff507728161ab46200dec60f28319c1217 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Feb 2025 13:46:53 -0500
+Subject: drm/amd/display: Add support for disconnected eDP streams
+
+From: Harry VanZyllDeJong <hvanzyll@amd.com>
+
+[ Upstream commit 6571bef25fe48c642f7a69ccf7c3198b317c136a ]
+
+[Why]
+eDP may not be connected to the GPU on driver start causing
+fail enumeration.
+
+[How]
+Move the virtual signal type check before the eDP connector
+signal check.
+
+Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
+Signed-off-by: Harry VanZyllDeJong <hvanzyll@amd.com>
+Signed-off-by: Roman Li <roman.li@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../drm/amd/display/dc/link/protocols/link_dp_capability.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
+index 23e650e39910e..d9a1e1a599674 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
+@@ -945,6 +945,9 @@ bool link_decide_link_settings(struct dc_stream_state *stream,
+ * TODO: add MST specific link training routine
+ */
+ decide_mst_link_settings(link, link_setting);
++ } else if (stream->signal == SIGNAL_TYPE_VIRTUAL) {
++ link_setting->lane_count = LANE_COUNT_FOUR;
++ link_setting->link_rate = LINK_RATE_HIGH3;
+ } else if (link->connector_signal == SIGNAL_TYPE_EDP) {
+ /* enable edp link optimization for DSC eDP case */
+ if (stream->timing.flags.DSC) {
+@@ -967,9 +970,6 @@ bool link_decide_link_settings(struct dc_stream_state *stream,
+ } else {
+ edp_decide_link_settings(link, link_setting, req_bw);
+ }
+- } else if (stream->signal == SIGNAL_TYPE_VIRTUAL) {
+- link_setting->lane_count = LANE_COUNT_FOUR;
+- link_setting->link_rate = LINK_RATE_HIGH3;
+ } else {
+ decide_dp_link_settings(link, link_setting, req_bw);
+ }
+--
+2.39.5
+
--- /dev/null
+From 1fb20f39e04b7295a80f8a1687b077c5a90ce3be Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Feb 2025 20:09:14 +0800
+Subject: drm/amd/display: calculate the remain segments for all pipes
+
+From: Zhikai Zhai <zhikai.zhai@amd.com>
+
+[ Upstream commit d3069feecdb5542604d29b59acfd1fd213bad95b ]
+
+[WHY]
+In some cases the remain de-tile buffer segments will be greater
+than zero if we don't add the non-top pipe to calculate, at
+this time the override de-tile buffer size will be valid and used.
+But it makes the de-tile buffer segments used finally for all of pipes
+exceed the maximum.
+
+[HOW]
+Add the non-top pipe to calculate the remain de-tile buffer segments.
+Don't set override size to use the average according to pipe count
+if the value exceed the maximum.
+
+Reviewed-by: Charlene Liu <charlene.liu@amd.com>
+Signed-off-by: Zhikai Zhai <zhikai.zhai@amd.com>
+Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../dc/resource/dcn315/dcn315_resource.c | 42 +++++++++----------
+ 1 file changed, 20 insertions(+), 22 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
+index f2ce687c0e03c..9cb72805b8d1a 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
+@@ -1699,7 +1699,7 @@ static int dcn315_populate_dml_pipes_from_context(
+ pipes[pipe_cnt].dout.dsc_input_bpc = 0;
+ DC_FP_START();
+ dcn31_zero_pipe_dcc_fraction(pipes, pipe_cnt);
+- if (pixel_rate_crb && !pipe->top_pipe && !pipe->prev_odm_pipe) {
++ if (pixel_rate_crb) {
+ int bpp = source_format_to_bpp(pipes[pipe_cnt].pipe.src.source_format);
+ /* Ceil to crb segment size */
+ int approx_det_segs_required_for_pstate = dcn_get_approx_det_segs_required_for_pstate(
+@@ -1756,28 +1756,26 @@ static int dcn315_populate_dml_pipes_from_context(
+ continue;
+ }
+
+- if (!pipe->top_pipe && !pipe->prev_odm_pipe) {
+- bool split_required = pipe->stream->timing.pix_clk_100hz >= dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc)
+- || (pipe->plane_state && pipe->plane_state->src_rect.width > 5120);
+-
+- if (remaining_det_segs > MIN_RESERVED_DET_SEGS && crb_pipes != 0)
+- pipes[pipe_cnt].pipe.src.det_size_override += (remaining_det_segs - MIN_RESERVED_DET_SEGS) / crb_pipes +
+- (crb_idx < (remaining_det_segs - MIN_RESERVED_DET_SEGS) % crb_pipes ? 1 : 0);
+- if (pipes[pipe_cnt].pipe.src.det_size_override > 2 * DCN3_15_MAX_DET_SEGS) {
+- /* Clamp to 2 pipe split max det segments */
+- remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override - 2 * (DCN3_15_MAX_DET_SEGS);
+- pipes[pipe_cnt].pipe.src.det_size_override = 2 * DCN3_15_MAX_DET_SEGS;
+- }
+- if (pipes[pipe_cnt].pipe.src.det_size_override > DCN3_15_MAX_DET_SEGS || split_required) {
+- /* If we are splitting we must have an even number of segments */
+- remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override % 2;
+- pipes[pipe_cnt].pipe.src.det_size_override -= pipes[pipe_cnt].pipe.src.det_size_override % 2;
+- }
+- /* Convert segments into size for DML use */
+- pipes[pipe_cnt].pipe.src.det_size_override *= DCN3_15_CRB_SEGMENT_SIZE_KB;
+-
+- crb_idx++;
++ bool split_required = pipe->stream->timing.pix_clk_100hz >= dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc)
++ || (pipe->plane_state && pipe->plane_state->src_rect.width > 5120);
++
++ if (remaining_det_segs > MIN_RESERVED_DET_SEGS && crb_pipes != 0)
++ pipes[pipe_cnt].pipe.src.det_size_override += (remaining_det_segs - MIN_RESERVED_DET_SEGS) / crb_pipes +
++ (crb_idx < (remaining_det_segs - MIN_RESERVED_DET_SEGS) % crb_pipes ? 1 : 0);
++ if (pipes[pipe_cnt].pipe.src.det_size_override > 2 * DCN3_15_MAX_DET_SEGS) {
++ /* Clamp to 2 pipe split max det segments */
++ remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override - 2 * (DCN3_15_MAX_DET_SEGS);
++ pipes[pipe_cnt].pipe.src.det_size_override = 2 * DCN3_15_MAX_DET_SEGS;
++ }
++ if (pipes[pipe_cnt].pipe.src.det_size_override > DCN3_15_MAX_DET_SEGS || split_required) {
++ /* If we are splitting we must have an even number of segments */
++ remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override % 2;
++ pipes[pipe_cnt].pipe.src.det_size_override -= pipes[pipe_cnt].pipe.src.det_size_override % 2;
+ }
++ /* Convert segments into size for DML use */
++ pipes[pipe_cnt].pipe.src.det_size_override *= DCN3_15_CRB_SEGMENT_SIZE_KB;
++
++ crb_idx++;
+ pipe_cnt++;
+ }
+ }
+--
+2.39.5
+
--- /dev/null
+From 8cb706f2b39883f31b872b30211e6606e6764ae2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Apr 2025 10:24:29 -0400
+Subject: drm/amd/display: Call FP Protect Before Mode Programming/Mode Support
+
+From: Austin Zheng <Austin.Zheng@amd.com>
+
+[ Upstream commit eba692ca3abca258b3214a6e4126afefad1822f0 ]
+
+[Why]
+Memory allocation occurs within dml21_validate() for adding phantom planes.
+May cause kernel to be tainted due to usage of FP Start.
+
+[How]
+Move FP start from dml21_validate to before mode programming/mode support.
+Calculations requiring floating point are all done within mode programming
+or mode support.
+
+Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
+Signed-off-by: Austin Zheng <Austin.Zheng@amd.com>
+Signed-off-by: Ray Wu <ray.wu@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit fe3250f10819b411808ab9ae1d824c5fc9b59170)
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c
+index e3e4f40bd4123..dcbe327209d5d 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c
++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c
+@@ -221,7 +221,9 @@ static bool dml21_mode_check_and_programming(const struct dc *in_dc, struct dc_s
+ if (!result)
+ return false;
+
++ DC_FP_START();
+ result = dml2_build_mode_programming(mode_programming);
++ DC_FP_END();
+ if (!result)
+ return false;
+
+@@ -271,7 +273,9 @@ static bool dml21_check_mode_support(const struct dc *in_dc, struct dc_state *co
+ mode_support->dml2_instance = dml_init->dml2_instance;
+ dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx);
+ dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params.programming = dml_ctx->v21.mode_programming.programming;
++ DC_FP_START();
+ is_supported = dml2_check_mode_supported(mode_support);
++ DC_FP_END();
+ if (!is_supported)
+ return false;
+
+@@ -282,16 +286,12 @@ bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml
+ {
+ bool out = false;
+
+- DC_FP_START();
+-
+ /* Use dml_validate_only for fast_validate path */
+ if (fast_validate)
+ out = dml21_check_mode_support(in_dc, context, dml_ctx);
+ else
+ out = dml21_mode_check_and_programming(in_dc, context, dml_ctx);
+
+- DC_FP_END();
+-
+ return out;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 1cc31c01ebca4f0e1a47275f332d2fffbda3125e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Sep 2024 16:56:20 -0400
+Subject: drm/amd/display: Configure DTBCLK_P with OPTC only for dcn401
+
+From: Dillon Varone <dillon.varone@amd.com>
+
+[ Upstream commit 3c6c8d1a1e3f033f1abf84d6d54c268c35b0fcdd ]
+
+[WHY]
+DTBCLK_P is used to generate virtual pixel clock, and to drive the HPO
+stream encoder clock. Programming the required clock when
+enabling/disabling both components can cause issues.
+For example, if HPO is being disabled and clock source is changed to
+REFCLK, virtual pixel rate will then be wrong, causing issues in CRTC.
+
+[HOW]
+Only program the DTBCLK_P when programming CRTC, as its expected it will
+be enabled prior to HPO, and disabled after HPO in all valid cases.
+
+Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
+Signed-off-by: Dillon Varone <dillon.varone@amd.com>
+Signed-off-by: Fangzhi Zuo <jerry.zuo@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 874697e12793 ("drm/amd/display: Defer BW-optimization-blocked DRR adjustments")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../amd/display/dc/dccg/dcn401/dcn401_dccg.c | 3 -
+ .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 135 +++++++++++++++++-
+ .../amd/display/dc/hwss/dcn401/dcn401_hwseq.h | 7 +
+ .../amd/display/dc/hwss/dcn401/dcn401_init.c | 4 +-
+ 4 files changed, 142 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c
+index 0b889004509ad..62402c7be0a5e 100644
+--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c
++++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c
+@@ -580,9 +580,6 @@ static void dccg401_set_dpstreamclk(
+ int otg_inst,
+ int dp_hpo_inst)
+ {
+- /* set the dtbclk_p source */
+- dccg401_set_dtbclk_p_src(dccg, src, otg_inst);
+-
+ /* enabled to select one of the DTBCLKs for pipe */
+ if (src == REFCLK)
+ dccg401_disable_dpstreamclk(dccg, dp_hpo_inst);
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+index 62f1e597787e6..b6b333a2461f8 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+@@ -844,6 +844,13 @@ enum dc_status dcn401_enable_stream_timing(
+ odm_slice_width, last_odm_slice_width);
+ }
+
++ /* set DTBCLK_P */
++ if (dc->res_pool->dccg->funcs->set_dtbclk_p_src) {
++ if (dc_is_dp_signal(stream->signal) || dc_is_virtual_signal(stream->signal)) {
++ dc->res_pool->dccg->funcs->set_dtbclk_p_src(dc->res_pool->dccg, DPREFCLK, pipe_ctx->stream_res.tg->inst);
++ }
++ }
++
+ /* HW program guide assume display already disable
+ * by unplug sequence. OTG assume stop.
+ */
+@@ -1007,8 +1014,6 @@ void dcn401_enable_stream(struct pipe_ctx *pipe_ctx)
+ dccg->funcs->enable_symclk32_se(dccg, dp_hpo_inst, phyd32clk);
+ }
+ } else {
+- /* need to set DTBCLK_P source to DPREFCLK for DP8B10B */
+- dccg->funcs->set_dtbclk_p_src(dccg, DPREFCLK, tg->inst);
+ dccg->funcs->enable_symclk_se(dccg, stream_enc->stream_enc_inst,
+ link_enc->transmitter - TRANSMITTER_UNIPHY_A);
+ }
+@@ -1773,3 +1778,129 @@ void dcn401_program_outstanding_updates(struct dc *dc,
+ if (hubbub->funcs->program_compbuf_segments)
+ hubbub->funcs->program_compbuf_segments(hubbub, context->bw_ctx.bw.dcn.arb_regs.compbuf_size, true);
+ }
++
++void dcn401_reset_back_end_for_pipe(
++ struct dc *dc,
++ struct pipe_ctx *pipe_ctx,
++ struct dc_state *context)
++{
++ int i;
++ struct dc_link *link = pipe_ctx->stream->link;
++ const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
++
++ DC_LOGGER_INIT(dc->ctx->logger);
++ if (pipe_ctx->stream_res.stream_enc == NULL) {
++ pipe_ctx->stream = NULL;
++ return;
++ }
++
++ /* DPMS may already disable or */
++ /* dpms_off status is incorrect due to fastboot
++ * feature. When system resume from S4 with second
++ * screen only, the dpms_off would be true but
++ * VBIOS lit up eDP, so check link status too.
++ */
++ if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
++ dc->link_srv->set_dpms_off(pipe_ctx);
++ else if (pipe_ctx->stream_res.audio)
++ dc->hwss.disable_audio_stream(pipe_ctx);
++
++ /* free acquired resources */
++ if (pipe_ctx->stream_res.audio) {
++ /*disable az_endpoint*/
++ pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
++
++ /*free audio*/
++ if (dc->caps.dynamic_audio == true) {
++ /*we have to dynamic arbitrate the audio endpoints*/
++ /*we free the resource, need reset is_audio_acquired*/
++ update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
++ pipe_ctx->stream_res.audio, false);
++ pipe_ctx->stream_res.audio = NULL;
++ }
++ }
++
++ /* by upper caller loop, parent pipe: pipe0, will be reset last.
++ * back end share by all pipes and will be disable only when disable
++ * parent pipe.
++ */
++ if (pipe_ctx->top_pipe == NULL) {
++
++ dc->hwss.set_abm_immediate_disable(pipe_ctx);
++
++ pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
++
++ pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
++ if (pipe_ctx->stream_res.tg->funcs->set_odm_bypass)
++ pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
++ pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
++
++ if (pipe_ctx->stream_res.tg->funcs->set_drr)
++ pipe_ctx->stream_res.tg->funcs->set_drr(
++ pipe_ctx->stream_res.tg, NULL);
++ /* TODO - convert symclk_ref_cnts for otg to a bit map to solve
++ * the case where the same symclk is shared across multiple otg
++ * instances
++ */
++ if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
++ link->phy_state.symclk_ref_cnts.otg = 0;
++ if (link->phy_state.symclk_state == SYMCLK_ON_TX_OFF) {
++ link_hwss->disable_link_output(link,
++ &pipe_ctx->link_res, pipe_ctx->stream->signal);
++ link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF;
++ }
++
++ /* reset DTBCLK_P */
++ if (dc->res_pool->dccg->funcs->set_dtbclk_p_src)
++ dc->res_pool->dccg->funcs->set_dtbclk_p_src(dc->res_pool->dccg, REFCLK, pipe_ctx->stream_res.tg->inst);
++ }
++
++ for (i = 0; i < dc->res_pool->pipe_count; i++)
++ if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx)
++ break;
++
++ if (i == dc->res_pool->pipe_count)
++ return;
++
++/*
++ * In case of a dangling plane, setting this to NULL unconditionally
++ * causes failures during reset hw ctx where, if stream is NULL,
++ * it is expected that the pipe_ctx pointers to pipes and plane are NULL.
++ */
++ pipe_ctx->stream = NULL;
++ DC_LOG_DEBUG("Reset back end for pipe %d, tg:%d\n",
++ pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst);
++}
++
++void dcn401_reset_hw_ctx_wrap(
++ struct dc *dc,
++ struct dc_state *context)
++{
++ int i;
++ struct dce_hwseq *hws = dc->hwseq;
++
++ /* Reset Back End*/
++ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
++ struct pipe_ctx *pipe_ctx_old =
++ &dc->current_state->res_ctx.pipe_ctx[i];
++ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
++
++ if (!pipe_ctx_old->stream)
++ continue;
++
++ if (pipe_ctx_old->top_pipe || pipe_ctx_old->prev_odm_pipe)
++ continue;
++
++ if (!pipe_ctx->stream ||
++ pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
++ struct clock_source *old_clk = pipe_ctx_old->clock_source;
++
++ if (hws->funcs.reset_back_end_for_pipe)
++ hws->funcs.reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state);
++ if (hws->funcs.enable_stream_gating)
++ hws->funcs.enable_stream_gating(dc, pipe_ctx_old);
++ if (old_clk)
++ old_clk->funcs->cs_power_down(old_clk);
++ }
++ }
++}
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
+index a27e62081685d..6256429c8a4f6 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
+@@ -84,4 +84,11 @@ void adjust_hotspot_between_slices_for_2x_magnify(uint32_t cursor_width, struct
+ void dcn401_wait_for_det_buffer_update(struct dc *dc, struct dc_state *context, struct pipe_ctx *otg_master);
+ void dcn401_interdependent_update_lock(struct dc *dc, struct dc_state *context, bool lock);
+ void dcn401_program_outstanding_updates(struct dc *dc, struct dc_state *context);
++void dcn401_reset_back_end_for_pipe(
++ struct dc *dc,
++ struct pipe_ctx *pipe_ctx,
++ struct dc_state *context);
++void dcn401_reset_hw_ctx_wrap(
++ struct dc *dc,
++ struct dc_state *context);
+ #endif /* __DC_HWSS_DCN401_H__ */
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
+index a2ca07235c83d..d6f36b8e1a261 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
+@@ -111,7 +111,7 @@ static const struct hwseq_private_funcs dcn401_private_funcs = {
+ .power_down = dce110_power_down,
+ .enable_display_power_gating = dcn10_dummy_display_power_gating,
+ .blank_pixel_data = dcn20_blank_pixel_data,
+- .reset_hw_ctx_wrap = dcn20_reset_hw_ctx_wrap,
++ .reset_hw_ctx_wrap = dcn401_reset_hw_ctx_wrap,
+ .enable_stream_timing = dcn401_enable_stream_timing,
+ .edp_backlight_control = dce110_edp_backlight_control,
+ .setup_vupdate_interrupt = dcn20_setup_vupdate_interrupt,
+@@ -136,7 +136,7 @@ static const struct hwseq_private_funcs dcn401_private_funcs = {
+ .update_mall_sel = dcn32_update_mall_sel,
+ .calculate_dccg_k1_k2_values = NULL,
+ .apply_single_controller_ctx_to_hw = dce110_apply_single_controller_ctx_to_hw,
+- .reset_back_end_for_pipe = dcn20_reset_back_end_for_pipe,
++ .reset_back_end_for_pipe = dcn401_reset_back_end_for_pipe,
+ .populate_mcm_luts = NULL,
+ };
+
+--
+2.39.5
+
--- /dev/null
+From c0a4bd92d11ff331af2a8eacfd9791a794fd19bc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Feb 2025 10:35:23 +0800
+Subject: drm/amd/display: Correct timing_adjust_pending flag setting.
+
+From: Zhongwei Zhang <Zhongwei.Zhang@amd.com>
+
+[ Upstream commit 34935701b7ed1a1ef449310ba041f10964b23cf4 ]
+
+[Why&How]
+stream->adjust will be overwritten by update->crtc_timing_adjust.
+We should set update->crtc_timing_adjust->timing_adjust_pending
+and then overwrite stream->adjust.
+Reset update->crtc_timing_adjust->timing_adjust_pending after
+the assignment.
+
+Reviewed-by: Charlene Liu <charlene.liu@amd.com>
+Signed-off-by: Zhongwei Zhang <Zhongwei.Zhang@amd.com>
+Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 874697e12793 ("drm/amd/display: Defer BW-optimization-blocked DRR adjustments")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
+index 3392746f1d420..a76e6fc3fef78 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
+@@ -2979,8 +2979,9 @@ static void copy_stream_update_to_stream(struct dc *dc,
+ if (update->crtc_timing_adjust) {
+ if (stream->adjust.v_total_min != update->crtc_timing_adjust->v_total_min ||
+ stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max)
+- stream->adjust.timing_adjust_pending = true;
++ update->crtc_timing_adjust->timing_adjust_pending = true;
+ stream->adjust = *update->crtc_timing_adjust;
++ update->crtc_timing_adjust->timing_adjust_pending = false;
+ }
+
+ if (update->dpms_off)
+--
+2.39.5
+
--- /dev/null
+From 09311399ac2354796639e4ea2e411018ec43a3d1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Apr 2025 02:54:26 -0400
+Subject: drm/amd/display: Defer BW-optimization-blocked DRR adjustments
+
+From: John Olender <john.olender@gmail.com>
+
+[ Upstream commit 874697e127931bf50a37ce9d96ee80f3a08a0c38 ]
+
+[Why & How]
+Instead of dropping DRR updates, defer them. This fixes issues where
+monitor continues to see incorrect refresh rate after VRR was turned off
+by userspace.
+
+Fixes: 32953485c558 ("drm/amd/display: Do not update DRR while BW optimizations pending")
+Link: https://gitlab.freedesktop.org/drm/amd/-/issues/3546
+Reviewed-by: Sun peng Li <sunpeng.li@amd.com>
+Signed-off-by: John Olender <john.olender@gmail.com>
+Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Ray Wu <ray.wu@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 53761b7ecd83e6fbb9f2206f8c980a6aa308c844)
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 10 +++++++---
+ 2 files changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index ff33760aa4fae..17c03b89abb31 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -365,6 +365,8 @@ get_crtc_by_otg_inst(struct amdgpu_device *adev,
+ static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
+ struct dm_crtc_state *new_state)
+ {
++ if (new_state->stream->adjust.timing_adjust_pending)
++ return true;
+ if (new_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED)
+ return true;
+ else if (amdgpu_dm_crtc_vrr_active(old_state) != amdgpu_dm_crtc_vrr_active(new_state))
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
+index a76e6fc3fef78..dd4b131fac6cb 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
+@@ -438,9 +438,12 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
+ * Don't adjust DRR while there's bandwidth optimizations pending to
+ * avoid conflicting with firmware updates.
+ */
+- if (dc->ctx->dce_version > DCE_VERSION_MAX)
+- if (dc->optimized_required || dc->wm_optimized_required)
++ if (dc->ctx->dce_version > DCE_VERSION_MAX) {
++ if (dc->optimized_required || dc->wm_optimized_required) {
++ stream->adjust.timing_adjust_pending = true;
+ return false;
++ }
++ }
+
+ dc_exit_ips_for_hw_access(dc);
+
+@@ -2978,7 +2981,8 @@ static void copy_stream_update_to_stream(struct dc *dc,
+
+ if (update->crtc_timing_adjust) {
+ if (stream->adjust.v_total_min != update->crtc_timing_adjust->v_total_min ||
+- stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max)
++ stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max ||
++ stream->adjust.timing_adjust_pending)
+ update->crtc_timing_adjust->timing_adjust_pending = true;
+ stream->adjust = *update->crtc_timing_adjust;
+ update->crtc_timing_adjust->timing_adjust_pending = false;
+--
+2.39.5
+
--- /dev/null
+From 54b8024e2aae7697c22674ae228d5dbeb103a8a0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Dec 2024 09:25:18 -0500
+Subject: drm/amd/display/dm: drop hw_support check in amdgpu_dm_i2c_xfer()
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+[ Upstream commit 33da70bd1e115d7d73f45fb1c09f5ecc448f3f13 ]
+
+DC supports SW i2c as well. Drop the check.
+
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 1e5984e71bfd7..09ef87c69230e 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -8288,7 +8288,7 @@ static int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap,
+ int i;
+ int result = -EIO;
+
+- if (!ddc_service->ddc_pin || !ddc_service->ddc_pin->hw_info.hw_supported)
++ if (!ddc_service->ddc_pin)
+ return result;
+
+ cmd.payloads = kcalloc(num, sizeof(struct i2c_payload), GFP_KERNEL);
+--
+2.39.5
+
--- /dev/null
+From 8f58bef6e9924af020e341fe2e2811e6bbac1ada Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 16:18:34 +0800
+Subject: drm/amd/display: Do not enable replay when vtotal update is pending.
+
+From: Danny Wang <danny.wang@amd.com>
+
+[ Upstream commit bd00b29b5f236dce677089319176dee5872b5a7a ]
+
+[Why&How]
+Vtotal is not applied to HW when handling vsync interrupt.
+Make sure vtotal is aligned before enable replay.
+
+Reviewed-by: Anthony Koo <anthony.koo@amd.com>
+Reviewed-by: Robin Chen <robin.chen@amd.com>
+Signed-off-by: Danny Wang <danny.wang@amd.com>
+Signed-off-by: Zhongwei Zhang <Zhongwei.Zhang@amd.com>
+Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 874697e12793 ("drm/amd/display: Defer BW-optimization-blocked DRR adjustments")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 9 +++++++--
+ .../gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 15 +++++++++++++++
+ drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 1 +
+ .../drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 7 ++-----
+ .../drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 7 ++-----
+ .../drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 8 ++------
+ .../drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c | 4 +---
+ .../drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 3 +--
+ .../drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 10 +++-------
+ .../gpu/drm/amd/display/dc/hwss/hw_sequencer.h | 6 ++++++
+ 10 files changed, 40 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
+index 216b525bd75e7..3392746f1d420 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
+@@ -452,6 +452,7 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
+
+ if (dc->caps.max_v_total != 0 &&
+ (adjust->v_total_max > dc->caps.max_v_total || adjust->v_total_min > dc->caps.max_v_total)) {
++ stream->adjust.timing_adjust_pending = false;
+ if (adjust->allow_otg_v_count_halt)
+ return set_long_vtotal(dc, stream, adjust);
+ else
+@@ -465,7 +466,7 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
+ dc->hwss.set_drr(&pipe,
+ 1,
+ *adjust);
+-
++ stream->adjust.timing_adjust_pending = false;
+ return true;
+ }
+ }
+@@ -2975,8 +2976,12 @@ static void copy_stream_update_to_stream(struct dc *dc,
+ if (update->vrr_active_fixed)
+ stream->vrr_active_fixed = *update->vrr_active_fixed;
+
+- if (update->crtc_timing_adjust)
++ if (update->crtc_timing_adjust) {
++ if (stream->adjust.v_total_min != update->crtc_timing_adjust->v_total_min ||
++ stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max)
++ stream->adjust.timing_adjust_pending = true;
+ stream->adjust = *update->crtc_timing_adjust;
++ }
+
+ if (update->dpms_off)
+ stream->dpms_off = *update->dpms_off;
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+index bb766c2a74176..fdcba960e1e6f 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+@@ -554,6 +554,21 @@ void set_p_state_switch_method(
+ }
+ }
+
++void set_drr_and_clear_adjust_pending(
++ struct pipe_ctx *pipe_ctx,
++ struct dc_stream_state *stream,
++ struct drr_params *params)
++{
++ /* params can be null.*/
++ if (pipe_ctx && pipe_ctx->stream_res.tg &&
++ pipe_ctx->stream_res.tg->funcs->set_drr)
++ pipe_ctx->stream_res.tg->funcs->set_drr(
++ pipe_ctx->stream_res.tg, params);
++
++ if (stream)
++ stream->adjust.timing_adjust_pending = false;
++}
++
+ void get_fams2_visual_confirm_color(
+ struct dc *dc,
+ struct dc_state *context,
+diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+index c10567ec1c819..0ded4bc7825b0 100644
+--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
++++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+@@ -1000,6 +1000,7 @@ struct dc_crtc_timing_adjust {
+ uint32_t v_total_mid;
+ uint32_t v_total_mid_frame_num;
+ uint32_t allow_otg_v_count_halt;
++ uint8_t timing_adjust_pending;
+ };
+
+
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+index 4fbed0298adfa..1e76524d116dc 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+@@ -1653,9 +1653,7 @@ enum dc_status dce110_apply_single_controller_ctx_to_hw(
+
+ params.vertical_total_min = stream->adjust.v_total_min;
+ params.vertical_total_max = stream->adjust.v_total_max;
+- if (pipe_ctx->stream_res.tg->funcs->set_drr)
+- pipe_ctx->stream_res.tg->funcs->set_drr(
+- pipe_ctx->stream_res.tg, ¶ms);
++ set_drr_and_clear_adjust_pending(pipe_ctx, stream, ¶ms);
+
+ // DRR should set trigger event to monitor surface update event
+ if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0)
+@@ -2103,8 +2101,7 @@ static void set_drr(struct pipe_ctx **pipe_ctx,
+ struct timing_generator *tg = pipe_ctx[i]->stream_res.tg;
+
+ if ((tg != NULL) && tg->funcs) {
+- if (tg->funcs->set_drr)
+- tg->funcs->set_drr(tg, ¶ms);
++ set_drr_and_clear_adjust_pending(pipe_ctx[i], pipe_ctx[i]->stream, ¶ms);
+ if (adjust.v_total_max != 0 && adjust.v_total_min != 0)
+ if (tg->funcs->set_static_screen_control)
+ tg->funcs->set_static_screen_control(
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+index d725af14af371..00be0b26689d3 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+@@ -1112,9 +1112,7 @@ static void dcn10_reset_back_end_for_pipe(
+ pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
+
+ pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
+- if (pipe_ctx->stream_res.tg->funcs->set_drr)
+- pipe_ctx->stream_res.tg->funcs->set_drr(
+- pipe_ctx->stream_res.tg, NULL);
++ set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL);
+ if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
+ pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0;
+ }
+@@ -3217,8 +3215,7 @@ void dcn10_set_drr(struct pipe_ctx **pipe_ctx,
+ struct timing_generator *tg = pipe_ctx[i]->stream_res.tg;
+
+ if ((tg != NULL) && tg->funcs) {
+- if (tg->funcs->set_drr)
+- tg->funcs->set_drr(tg, ¶ms);
++ set_drr_and_clear_adjust_pending(pipe_ctx[i], pipe_ctx[i]->stream, ¶ms);
+ if (adjust.v_total_max != 0 && adjust.v_total_min != 0)
+ if (tg->funcs->set_static_screen_control)
+ tg->funcs->set_static_screen_control(
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+index f5f1ccd8303cf..9c5cdb3b80b5d 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+@@ -952,9 +952,7 @@ enum dc_status dcn20_enable_stream_timing(
+ params.vertical_total_max = stream->adjust.v_total_max;
+ params.vertical_total_mid = stream->adjust.v_total_mid;
+ params.vertical_total_mid_frame_num = stream->adjust.v_total_mid_frame_num;
+- if (pipe_ctx->stream_res.tg->funcs->set_drr)
+- pipe_ctx->stream_res.tg->funcs->set_drr(
+- pipe_ctx->stream_res.tg, ¶ms);
++ set_drr_and_clear_adjust_pending(pipe_ctx, stream, ¶ms);
+
+ // DRR should set trigger event to monitor surface update event
+ if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0)
+@@ -2822,9 +2820,7 @@ void dcn20_reset_back_end_for_pipe(
+ pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
+ pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
+
+- if (pipe_ctx->stream_res.tg->funcs->set_drr)
+- pipe_ctx->stream_res.tg->funcs->set_drr(
+- pipe_ctx->stream_res.tg, NULL);
++ set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL);
+ /* TODO - convert symclk_ref_cnts for otg to a bit map to solve
+ * the case where the same symclk is shared across multiple otg
+ * instances
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
+index 3d4b31bd99469..9aa925a0b3b43 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
+@@ -528,9 +528,7 @@ static void dcn31_reset_back_end_for_pipe(
+ if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
+ pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0;
+
+- if (pipe_ctx->stream_res.tg->funcs->set_drr)
+- pipe_ctx->stream_res.tg->funcs->set_drr(
+- pipe_ctx->stream_res.tg, NULL);
++ set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL);
+
+ link = pipe_ctx->stream->link;
+ /* DPMS may already disable or */
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+index 38755ca771401..ca446e08f6a27 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+@@ -1452,8 +1452,7 @@ void dcn35_set_drr(struct pipe_ctx **pipe_ctx,
+ num_frames = 2 * (frame_rate % 60);
+ }
+ }
+- if (tg->funcs->set_drr)
+- tg->funcs->set_drr(tg, ¶ms);
++ set_drr_and_clear_adjust_pending(pipe_ctx[i], pipe_ctx[i]->stream, ¶ms);
+ if (adjust.v_total_max != 0 && adjust.v_total_min != 0)
+ if (tg->funcs->set_static_screen_control)
+ tg->funcs->set_static_screen_control(
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+index b6b333a2461f8..3279f347660cb 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+@@ -902,10 +902,7 @@ enum dc_status dcn401_enable_stream_timing(
+ }
+
+ hws->funcs.wait_for_blank_complete(pipe_ctx->stream_res.opp);
+-
+- if (pipe_ctx->stream_res.tg->funcs->set_drr)
+- pipe_ctx->stream_res.tg->funcs->set_drr(
+- pipe_ctx->stream_res.tg, ¶ms);
++ set_drr_and_clear_adjust_pending(pipe_ctx, stream, ¶ms);
+
+ /* Event triggers and num frames initialized for DRR, but can be
+ * later updated for PSR use. Note DRR trigger events are generated
+@@ -1835,9 +1832,8 @@ void dcn401_reset_back_end_for_pipe(
+ pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
+ pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
+
+- if (pipe_ctx->stream_res.tg->funcs->set_drr)
+- pipe_ctx->stream_res.tg->funcs->set_drr(
+- pipe_ctx->stream_res.tg, NULL);
++ set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL);
++
+ /* TODO - convert symclk_ref_cnts for otg to a bit map to solve
+ * the case where the same symclk is shared across multiple otg
+ * instances
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+index ac92056256233..9ae6259f2db17 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
++++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+@@ -46,6 +46,7 @@ struct dce_hwseq;
+ struct link_resource;
+ struct dc_dmub_cmd;
+ struct pg_block_update;
++struct drr_params;
+
+ struct subvp_pipe_control_lock_fast_params {
+ struct dc *dc;
+@@ -509,6 +510,11 @@ void set_p_state_switch_method(
+ struct dc_state *context,
+ struct pipe_ctx *pipe_ctx);
+
++void set_drr_and_clear_adjust_pending(
++ struct pipe_ctx *pipe_ctx,
++ struct dc_stream_state *stream,
++ struct drr_params *params);
++
+ void hwss_execute_sequence(struct dc *dc,
+ struct block_sequence block_sequence[],
+ int num_steps);
+--
+2.39.5
+
--- /dev/null
+From 021441d93ac1b3f654e2d9e8d34bc11b28a7276d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jan 2025 11:57:49 -0500
+Subject: drm/amd/display: Don't treat wb connector as physical in
+ create_validate_stream_for_sink
+
+From: Harry Wentland <harry.wentland@amd.com>
+
+[ Upstream commit cbf4890c6f28fb1ad733e14613fbd33c2004bced ]
+
+Don't try to operate on a drm_wb_connector as an amdgpu_dm_connector.
+While dereferencing aconnector->base will "work" it's wrong and
+might lead to unknown bad things. Just... don't.
+
+Reviewed-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Roman Li <roman.li@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 26 ++++++++++++-------
+ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 +-
+ .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 6 ++---
+ 3 files changed, 20 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index c0ff501687f5b..1e5984e71bfd7 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -7399,12 +7399,12 @@ static enum dc_status dm_validate_stream_and_context(struct dc *dc,
+ }
+
+ struct dc_stream_state *
+-create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
++create_validate_stream_for_sink(struct drm_connector *connector,
+ const struct drm_display_mode *drm_mode,
+ const struct dm_connector_state *dm_state,
+ const struct dc_stream_state *old_stream)
+ {
+- struct drm_connector *connector = &aconnector->base;
++ struct amdgpu_dm_connector *aconnector = NULL;
+ struct amdgpu_device *adev = drm_to_adev(connector->dev);
+ struct dc_stream_state *stream;
+ const struct drm_connector_state *drm_state = dm_state ? &dm_state->base : NULL;
+@@ -7415,8 +7415,12 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
+ if (!dm_state)
+ return NULL;
+
+- if (aconnector->dc_link->connector_signal == SIGNAL_TYPE_HDMI_TYPE_A ||
+- aconnector->dc_link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER)
++ if (connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK)
++ aconnector = to_amdgpu_dm_connector(connector);
++
++ if (aconnector &&
++ (aconnector->dc_link->connector_signal == SIGNAL_TYPE_HDMI_TYPE_A ||
++ aconnector->dc_link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER))
+ bpc_limit = 8;
+
+ do {
+@@ -7428,10 +7432,11 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
+ break;
+ }
+
+- if (aconnector->base.connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
++ dc_result = dc_validate_stream(adev->dm.dc, stream);
++
++ if (!aconnector) /* writeback connector */
+ return stream;
+
+- dc_result = dc_validate_stream(adev->dm.dc, stream);
+ if (dc_result == DC_OK && stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
+ dc_result = dm_dp_mst_is_port_support_mode(aconnector, stream);
+
+@@ -7461,7 +7466,7 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
+ __func__, __LINE__);
+
+ aconnector->force_yuv420_output = true;
+- stream = create_validate_stream_for_sink(aconnector, drm_mode,
++ stream = create_validate_stream_for_sink(connector, drm_mode,
+ dm_state, old_stream);
+ aconnector->force_yuv420_output = false;
+ }
+@@ -7476,6 +7481,9 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec
+ struct dc_sink *dc_sink;
+ /* TODO: Unhardcode stream count */
+ struct dc_stream_state *stream;
++ /* we always have an amdgpu_dm_connector here since we got
++ * here via the amdgpu_dm_connector_helper_funcs
++ */
+ struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+
+ if ((mode->flags & DRM_MODE_FLAG_INTERLACE) ||
+@@ -7500,7 +7508,7 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec
+
+ drm_mode_set_crtcinfo(mode, 0);
+
+- stream = create_validate_stream_for_sink(aconnector, mode,
++ stream = create_validate_stream_for_sink(connector, mode,
+ to_dm_connector_state(connector->state),
+ NULL);
+ if (stream) {
+@@ -10520,7 +10528,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
+ if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
+ goto skip_modeset;
+
+- new_stream = create_validate_stream_for_sink(aconnector,
++ new_stream = create_validate_stream_for_sink(connector,
+ &new_crtc_state->mode,
+ dm_new_conn_state,
+ dm_old_crtc_state->stream);
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+index 20ad72d1b0d9b..9603352ee0949 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+@@ -987,7 +987,7 @@ int amdgpu_dm_process_dmub_set_config_sync(struct dc_context *ctx, unsigned int
+ struct set_config_cmd_payload *payload, enum set_config_status *operation_result);
+
+ struct dc_stream_state *
+- create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
++ create_validate_stream_for_sink(struct drm_connector *connector,
+ const struct drm_display_mode *drm_mode,
+ const struct dm_connector_state *dm_state,
+ const struct dc_stream_state *old_stream);
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+index fca0c31e14d8f..92158009cfa73 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+@@ -1646,7 +1646,6 @@ int pre_validate_dsc(struct drm_atomic_state *state,
+
+ if (ind >= 0) {
+ struct drm_connector *connector;
+- struct amdgpu_dm_connector *aconnector;
+ struct drm_connector_state *drm_new_conn_state;
+ struct dm_connector_state *dm_new_conn_state;
+ struct dm_crtc_state *dm_old_crtc_state;
+@@ -1654,15 +1653,14 @@ int pre_validate_dsc(struct drm_atomic_state *state,
+ connector =
+ amdgpu_dm_find_first_crtc_matching_connector(state,
+ state->crtcs[ind].ptr);
+- aconnector = to_amdgpu_dm_connector(connector);
+ drm_new_conn_state =
+ drm_atomic_get_new_connector_state(state,
+- &aconnector->base);
++ connector);
+ dm_new_conn_state = to_dm_connector_state(drm_new_conn_state);
+ dm_old_crtc_state = to_dm_crtc_state(state->crtcs[ind].old_state);
+
+ local_dc_state->streams[i] =
+- create_validate_stream_for_sink(aconnector,
++ create_validate_stream_for_sink(connector,
+ &state->crtcs[ind].new_state->mode,
+ dm_new_conn_state,
+ dm_old_crtc_state->stream);
+--
+2.39.5
+
--- /dev/null
+From 001631e85bc15f56f0d25f3d3b1a0d3d99178cb6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jan 2025 13:14:54 -0500
+Subject: drm/amd/display: Don't try AUX transactions on disconnected link
+
+From: Ilya Bakoulin <Ilya.Bakoulin@amd.com>
+
+[ Upstream commit e8bffa52e0253cfd689813a620e64521256bc712 ]
+
+[Why]
+Setting link DPMS off in response to HPD disconnect creates AUX
+transactions on a link that is supposed to be disconnected. This can
+cause issues in some cases when the sink re-asserts HPD and expects
+source to re-enable the link.
+
+[How]
+Avoid AUX transactions on disconnected link.
+
+Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
+Signed-off-by: Ilya Bakoulin <Ilya.Bakoulin@amd.com>
+Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c
+index bafa52a0165a0..17c57cf98ec5c 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c
++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c
+@@ -75,7 +75,8 @@ void dp_disable_link_phy(struct dc_link *link,
+ struct dc *dc = link->ctx->dc;
+
+ if (!link->wa_flags.dp_keep_receiver_powered &&
+- !link->skip_implict_edp_power_control)
++ !link->skip_implict_edp_power_control &&
++ link->type != dc_connection_none)
+ dpcd_write_rx_power_ctrl(link, false);
+
+ dc->hwss.disable_link_output(link, link_res, signal);
+@@ -163,8 +164,9 @@ enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource
+ } else {
+ if (link->fec_state == dc_link_fec_ready) {
+ fec_config = 0;
+- core_link_write_dpcd(link, DP_FEC_CONFIGURATION,
+- &fec_config, sizeof(fec_config));
++ if (link->type != dc_connection_none)
++ core_link_write_dpcd(link, DP_FEC_CONFIGURATION,
++ &fec_config, sizeof(fec_config));
+
+ link_enc->funcs->fec_set_ready(link_enc, false);
+ link->fec_state = dc_link_fec_not_ready;
+--
+2.39.5
+
--- /dev/null
+From e252ec8952db15bb116a014b62f6051d86113c76 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Apr 2025 15:04:08 -0400
+Subject: drm/amd/display: Enable urgent latency adjustment on DCN35
+
+From: Nicholas Susanto <nsusanto@amd.com>
+
+[ Upstream commit 756c85e4d0ddc497b4ad5b1f41ad54e838e06188 ]
+
+[Why]
+
+Urgent latency adjustment was disabled on DCN35 due to issues with P0
+enablement on some platforms. Without urgent latency, underflows occur
+when doing certain high timing configurations. After testing, we found
+that reenabling urgent latency didn't reintroduce p0 support on multiple
+platforms.
+
+[How]
+
+renable urgent latency on DCN35 and setting it to 3000 Mhz.
+
+This reverts commit 3412860cc4c0c484f53f91b371483e6e4440c3e5.
+
+Reviewed-by: Charlene Liu <charlene.liu@amd.com>
+Signed-off-by: Nicholas Susanto <nsusanto@amd.com>
+Signed-off-by: Zaeem Mohamed <zaeem.mohamed@amd.com>
+Tested-by: Mark Broadworth <mark.broadworth@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit cd74ce1f0cddffb3f36d0995d0f61e89f0010738)
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c
+index 47d785204f29c..beed7adbbd43e 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c
+@@ -195,9 +195,9 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = {
+ .dcn_downspread_percent = 0.5,
+ .gpuvm_min_page_size_bytes = 4096,
+ .hostvm_min_page_size_bytes = 4096,
+- .do_urgent_latency_adjustment = 0,
++ .do_urgent_latency_adjustment = 1,
+ .urgent_latency_adjustment_fabric_clock_component_us = 0,
+- .urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
++ .urgent_latency_adjustment_fabric_clock_reference_mhz = 3000,
+ };
+
+ void dcn35_build_wm_range_table_fpu(struct clk_mgr *clk_mgr)
+--
+2.39.5
+
--- /dev/null
+From 6380d5d2da2c068ff5164972dd2595a7ca68f78a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Feb 2025 09:56:53 -0500
+Subject: drm/amd/display: Ensure DMCUB idle before reset on DCN31/DCN35
+
+From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+
+[ Upstream commit c707ea82c79dbd1d295ec94cc6529a5248c77757 ]
+
+[Why]
+If we soft reset before halt finishes and there are outstanding
+memory transactions then the memory interface may produce unexpected
+results, such as out of order transactions when the firmware next runs.
+
+These can manifest as random or unexpected load/store violations.
+
+[How]
+Increase the timeout before soft reset to ensure the DMCUB has quiesced.
+This is effectively 1s maximum based on experimentation.
+
+Use the enable bit check on DCN31 like we're doing on DCN35 and reorder
+the reset writes to follow the HW programming guide.
+
+Ensure we're reading SCRATCH7 instead of SCRATCH8 for the HALT code.
+No current versions of DMCUB firmware use the SCRATCH8 boot bit to
+dynamically switch where the HALT code goes to maintain backwards
+compatibility with PSP.
+
+Reviewed-by: Dillon Varone <dillon.varone@amd.com>
+Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Signed-off-by: Wayne Lin <wayne.lin@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dmub/src/dmub_dcn31.c | 17 +++++++++++------
+ .../gpu/drm/amd/display/dmub/src/dmub_dcn35.c | 4 ++--
+ 2 files changed, 13 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
+index d9f31b191c693..1a68b5782cac6 100644
+--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
+@@ -83,8 +83,8 @@ static inline void dmub_dcn31_translate_addr(const union dmub_addr *addr_in,
+ void dmub_dcn31_reset(struct dmub_srv *dmub)
+ {
+ union dmub_gpint_data_register cmd;
+- const uint32_t timeout = 100;
+- uint32_t in_reset, scratch, i, pwait_mode;
++ const uint32_t timeout = 100000;
++ uint32_t in_reset, is_enabled, scratch, i, pwait_mode;
+
+ REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset);
+
+@@ -108,7 +108,7 @@ void dmub_dcn31_reset(struct dmub_srv *dmub)
+ }
+
+ for (i = 0; i < timeout; ++i) {
+- scratch = dmub->hw_funcs.get_gpint_response(dmub);
++ scratch = REG_READ(DMCUB_SCRATCH7);
+ if (scratch == DMUB_GPINT__STOP_FW_RESPONSE)
+ break;
+
+@@ -125,9 +125,14 @@ void dmub_dcn31_reset(struct dmub_srv *dmub)
+ /* Force reset in case we timed out, DMCUB is likely hung. */
+ }
+
+- REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1);
+- REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0);
+- REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1);
++ REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enabled);
++
++ if (is_enabled) {
++ REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1);
++ REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1);
++ REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0);
++ }
++
+ REG_WRITE(DMCUB_INBOX1_RPTR, 0);
+ REG_WRITE(DMCUB_INBOX1_WPTR, 0);
+ REG_WRITE(DMCUB_OUTBOX1_RPTR, 0);
+diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c
+index 2ccad79053c58..4581eb4794518 100644
+--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c
++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c
+@@ -88,7 +88,7 @@ static inline void dmub_dcn35_translate_addr(const union dmub_addr *addr_in,
+ void dmub_dcn35_reset(struct dmub_srv *dmub)
+ {
+ union dmub_gpint_data_register cmd;
+- const uint32_t timeout = 100;
++ const uint32_t timeout = 100000;
+ uint32_t in_reset, is_enabled, scratch, i, pwait_mode;
+
+ REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset);
+@@ -113,7 +113,7 @@ void dmub_dcn35_reset(struct dmub_srv *dmub)
+ }
+
+ for (i = 0; i < timeout; ++i) {
+- scratch = dmub->hw_funcs.get_gpint_response(dmub);
++ scratch = REG_READ(DMCUB_SCRATCH7);
+ if (scratch == DMUB_GPINT__STOP_FW_RESPONSE)
+ break;
+
+--
+2.39.5
+
--- /dev/null
+From 187c79514ca83f0139155e897b05df594022d0ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jan 2025 14:46:27 -0500
+Subject: drm/amd/display: Fix BT2020 YCbCr limited/full range input
+
+From: Ilya Bakoulin <Ilya.Bakoulin@amd.com>
+
+[ Upstream commit 07bc2dcbcf403d47d6f305ef7f0d3d489491c5fb ]
+
+[Why]
+BT2020 YCbCr input is not handled properly when full range
+quantization is used and limited range is not supported at all.
+
+[How]
+- Add enums for BT2020 YCbCr limited/full range
+- Add limited range CSC matrix
+
+Reviewed-by: Krunoslav Kovac <krunoslav.kovac@amd.com>
+Signed-off-by: Ilya Bakoulin <Ilya.Bakoulin@amd.com>
+Signed-off-by: Roman Li <roman.li@amd.com>
+Tested-by: Robert Mader <robert.mader@collabora.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 2 +-
+ drivers/gpu/drm/amd/display/dc/basics/dc_common.c | 3 ++-
+ drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 5 +++--
+ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 ++--
+ drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 4 +++-
+ drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 3 ++-
+ .../gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c | 3 ++-
+ .../amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c | 3 ++-
+ .../amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c | 3 ++-
+ drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h | 6 +++++-
+ .../gpu/drm/amd/display/modules/info_packet/info_packet.c | 4 ++--
+ 12 files changed, 29 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 17c03b89abb31..c0ff501687f5b 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -5552,9 +5552,9 @@ fill_plane_color_attributes(const struct drm_plane_state *plane_state,
+
+ case DRM_COLOR_YCBCR_BT2020:
+ if (full_range)
+- *color_space = COLOR_SPACE_2020_YCBCR;
++ *color_space = COLOR_SPACE_2020_YCBCR_FULL;
+ else
+- return -EINVAL;
++ *color_space = COLOR_SPACE_2020_YCBCR_LIMITED;
+ break;
+
+ default:
+@@ -6050,7 +6050,7 @@ get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing,
+ if (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB)
+ color_space = COLOR_SPACE_2020_RGB_FULLRANGE;
+ else
+- color_space = COLOR_SPACE_2020_YCBCR;
++ color_space = COLOR_SPACE_2020_YCBCR_LIMITED;
+ break;
+ case DRM_MODE_COLORIMETRY_DEFAULT: // ITU601
+ default:
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+index 98e88903d07d5..15d94d2a0e2fb 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+@@ -1145,7 +1145,7 @@ static int amdgpu_current_colorspace_show(struct seq_file *m, void *data)
+ case COLOR_SPACE_2020_RGB_FULLRANGE:
+ seq_puts(m, "BT2020_RGB");
+ break;
+- case COLOR_SPACE_2020_YCBCR:
++ case COLOR_SPACE_2020_YCBCR_LIMITED:
+ seq_puts(m, "BT2020_YCC");
+ break;
+ default:
+diff --git a/drivers/gpu/drm/amd/display/dc/basics/dc_common.c b/drivers/gpu/drm/amd/display/dc/basics/dc_common.c
+index b2fc4f8e64825..a51c2701da247 100644
+--- a/drivers/gpu/drm/amd/display/dc/basics/dc_common.c
++++ b/drivers/gpu/drm/amd/display/dc/basics/dc_common.c
+@@ -40,7 +40,8 @@ bool is_rgb_cspace(enum dc_color_space output_color_space)
+ case COLOR_SPACE_YCBCR709:
+ case COLOR_SPACE_YCBCR601_LIMITED:
+ case COLOR_SPACE_YCBCR709_LIMITED:
+- case COLOR_SPACE_2020_YCBCR:
++ case COLOR_SPACE_2020_YCBCR_LIMITED:
++ case COLOR_SPACE_2020_YCBCR_FULL:
+ return false;
+ default:
+ /* Add a case to switch */
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+index d2342a91e7e71..d62b00314682f 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+@@ -176,7 +176,7 @@ static bool is_ycbcr2020_type(
+ {
+ bool ret = false;
+
+- if (color_space == COLOR_SPACE_2020_YCBCR)
++ if (color_space == COLOR_SPACE_2020_YCBCR_LIMITED || color_space == COLOR_SPACE_2020_YCBCR_FULL)
+ ret = true;
+ return ret;
+ }
+@@ -247,7 +247,8 @@ void color_space_to_black_color(
+ case COLOR_SPACE_YCBCR709_BLACK:
+ case COLOR_SPACE_YCBCR601_LIMITED:
+ case COLOR_SPACE_YCBCR709_LIMITED:
+- case COLOR_SPACE_2020_YCBCR:
++ case COLOR_SPACE_2020_YCBCR_LIMITED:
++ case COLOR_SPACE_2020_YCBCR_FULL:
+ *black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_CV];
+ break;
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+index bfcbbea377298..6dbf139c51f72 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -4215,7 +4215,7 @@ static void set_avi_info_frame(
+ break;
+ case COLOR_SPACE_2020_RGB_FULLRANGE:
+ case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
+- case COLOR_SPACE_2020_YCBCR:
++ case COLOR_SPACE_2020_YCBCR_LIMITED:
+ hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR;
+ hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED;
+ break;
+@@ -4229,7 +4229,7 @@ static void set_avi_info_frame(
+ break;
+ }
+
+- if (pixel_encoding && color_space == COLOR_SPACE_2020_YCBCR &&
++ if (pixel_encoding && color_space == COLOR_SPACE_2020_YCBCR_LIMITED &&
+ stream->out_transfer_func.tf == TRANSFER_FUNCTION_GAMMA22) {
+ hdmi_info.bits.EC0_EC2 = 0;
+ hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709;
+diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+index 0ded4bc7825b0..6fd94c5f6da52 100644
+--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
++++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+@@ -641,7 +641,8 @@ enum dc_color_space {
+ COLOR_SPACE_YCBCR709_LIMITED,
+ COLOR_SPACE_2020_RGB_FULLRANGE,
+ COLOR_SPACE_2020_RGB_LIMITEDRANGE,
+- COLOR_SPACE_2020_YCBCR,
++ COLOR_SPACE_2020_YCBCR_LIMITED,
++ COLOR_SPACE_2020_YCBCR_FULL,
+ COLOR_SPACE_ADOBERGB,
+ COLOR_SPACE_DCIP3,
+ COLOR_SPACE_DISPLAYNATIVE,
+@@ -649,6 +650,7 @@ enum dc_color_space {
+ COLOR_SPACE_APPCTRL,
+ COLOR_SPACE_CUSTOMPOINTS,
+ COLOR_SPACE_YCBCR709_BLACK,
++ COLOR_SPACE_2020_YCBCR = COLOR_SPACE_2020_YCBCR_LIMITED,
+ };
+
+ enum dc_dither_option {
+diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
+index 5c2825bc9a876..654b919465f08 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
++++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
+@@ -420,7 +420,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
+ dynamic_range_rgb = 1; /*limited range*/
+ break;
+ case COLOR_SPACE_2020_RGB_FULLRANGE:
+- case COLOR_SPACE_2020_YCBCR:
++ case COLOR_SPACE_2020_YCBCR_LIMITED:
+ case COLOR_SPACE_XR_RGB:
+ case COLOR_SPACE_MSREF_SCRGB:
+ case COLOR_SPACE_ADOBERGB:
+@@ -432,6 +432,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
+ case COLOR_SPACE_APPCTRL:
+ case COLOR_SPACE_CUSTOMPOINTS:
+ case COLOR_SPACE_UNKNOWN:
++ default:
+ /* do nothing */
+ break;
+ }
+diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c
+index f496e952ceecb..f8f1e98f646e6 100644
+--- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c
++++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c
+@@ -393,7 +393,7 @@ void enc1_stream_encoder_dp_set_stream_attribute(
+ break;
+ case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
+ case COLOR_SPACE_2020_RGB_FULLRANGE:
+- case COLOR_SPACE_2020_YCBCR:
++ case COLOR_SPACE_2020_YCBCR_LIMITED:
+ case COLOR_SPACE_XR_RGB:
+ case COLOR_SPACE_MSREF_SCRGB:
+ case COLOR_SPACE_ADOBERGB:
+@@ -406,6 +406,7 @@ void enc1_stream_encoder_dp_set_stream_attribute(
+ case COLOR_SPACE_CUSTOMPOINTS:
+ case COLOR_SPACE_UNKNOWN:
+ case COLOR_SPACE_YCBCR709_BLACK:
++ default:
+ /* do nothing */
+ break;
+ }
+diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c
+index 0a27e0942a123..0008816cf1553 100644
+--- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c
++++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c
+@@ -634,7 +634,7 @@ void enc401_stream_encoder_dp_set_stream_attribute(
+ break;
+ case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
+ case COLOR_SPACE_2020_RGB_FULLRANGE:
+- case COLOR_SPACE_2020_YCBCR:
++ case COLOR_SPACE_2020_YCBCR_LIMITED:
+ case COLOR_SPACE_XR_RGB:
+ case COLOR_SPACE_MSREF_SCRGB:
+ case COLOR_SPACE_ADOBERGB:
+@@ -647,6 +647,7 @@ void enc401_stream_encoder_dp_set_stream_attribute(
+ case COLOR_SPACE_CUSTOMPOINTS:
+ case COLOR_SPACE_UNKNOWN:
+ case COLOR_SPACE_YCBCR709_BLACK:
++ default:
+ /* do nothing */
+ break;
+ }
+diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c
+index 678db949cfe3c..759b453385c46 100644
+--- a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c
++++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c
+@@ -323,7 +323,7 @@ static void dcn31_hpo_dp_stream_enc_set_stream_attribute(
+ break;
+ case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
+ case COLOR_SPACE_2020_RGB_FULLRANGE:
+- case COLOR_SPACE_2020_YCBCR:
++ case COLOR_SPACE_2020_YCBCR_LIMITED:
+ case COLOR_SPACE_XR_RGB:
+ case COLOR_SPACE_MSREF_SCRGB:
+ case COLOR_SPACE_ADOBERGB:
+@@ -336,6 +336,7 @@ static void dcn31_hpo_dp_stream_enc_set_stream_attribute(
+ case COLOR_SPACE_CUSTOMPOINTS:
+ case COLOR_SPACE_UNKNOWN:
+ case COLOR_SPACE_YCBCR709_BLACK:
++ default:
+ /* do nothing */
+ break;
+ }
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
+index 0150f2581ee4c..0c5675d1c5936 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
+@@ -119,10 +119,14 @@ static const struct dpp_input_csc_matrix __maybe_unused dpp_input_csc_matrix[] =
+ { 0x39a6, 0x2568, 0, 0xe0d6,
+ 0xeedd, 0x2568, 0xf925, 0x9a8,
+ 0, 0x2568, 0x43ee, 0xdbb2 } },
+- { COLOR_SPACE_2020_YCBCR,
++ { COLOR_SPACE_2020_YCBCR_FULL,
+ { 0x2F30, 0x2000, 0, 0xE869,
+ 0xEDB7, 0x2000, 0xFABC, 0xBC6,
+ 0, 0x2000, 0x3C34, 0xE1E6 } },
++ { COLOR_SPACE_2020_YCBCR_LIMITED,
++ { 0x35B9, 0x2543, 0, 0xE2B2,
++ 0xEB2F, 0x2543, 0xFA01, 0x0B1F,
++ 0, 0x2543, 0x4489, 0xDB42 } },
+ { COLOR_SPACE_2020_RGB_LIMITEDRANGE,
+ { 0x35E0, 0x255F, 0, 0xE2B3,
+ 0xEB20, 0x255F, 0xF9FD, 0xB1E,
+diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
+index a344e2e49b0ea..b3d55cac35694 100644
+--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
++++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
+@@ -383,10 +383,10 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
+ colorimetryFormat = ColorimetryYCC_DP_ITU709;
+ else if (cs == COLOR_SPACE_ADOBERGB)
+ colorimetryFormat = ColorimetryYCC_DP_AdobeYCC;
+- else if (cs == COLOR_SPACE_2020_YCBCR)
++ else if (cs == COLOR_SPACE_2020_YCBCR_LIMITED)
+ colorimetryFormat = ColorimetryYCC_DP_ITU2020YCbCr;
+
+- if (cs == COLOR_SPACE_2020_YCBCR && tf == TRANSFER_FUNC_GAMMA_22)
++ if (cs == COLOR_SPACE_2020_YCBCR_LIMITED && tf == TRANSFER_FUNC_GAMMA_22)
+ colorimetryFormat = ColorimetryYCC_DP_ITU709;
+ break;
+
+--
+2.39.5
+
--- /dev/null
+From c5190603c503fb09eae49e8105dffc4a9f461cfe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 12:37:10 -0500
+Subject: drm/amd/display: fix dcn4x init failed
+
+From: Charlene Liu <Charlene.Liu@amd.com>
+
+[ Upstream commit 23ef388a84c72b0614a6c10f866ffeac7e807719 ]
+
+[why]
+failed due to cmdtable not created.
+switch atombios cmdtable as default.
+
+Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
+Signed-off-by: Charlene Liu <Charlene.Liu@amd.com>
+Signed-off-by: Zaeem Mohamed <zaeem.mohamed@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/bios/command_table2.c | 9 ---------
+ .../gpu/drm/amd/display/dc/bios/command_table_helper2.c | 3 +--
+ 2 files changed, 1 insertion(+), 11 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
+index 7d18f372ce7ab..6bc59b7ef007b 100644
+--- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
++++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
+@@ -101,7 +101,6 @@ static void init_dig_encoder_control(struct bios_parser *bp)
+ bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v1_5;
+ break;
+ default:
+- dm_output_to_console("Don't have dig_encoder_control for v%d\n", version);
+ bp->cmd_tbl.dig_encoder_control = encoder_control_fallback;
+ break;
+ }
+@@ -238,7 +237,6 @@ static void init_transmitter_control(struct bios_parser *bp)
+ bp->cmd_tbl.transmitter_control = transmitter_control_v1_7;
+ break;
+ default:
+- dm_output_to_console("Don't have transmitter_control for v%d\n", crev);
+ bp->cmd_tbl.transmitter_control = transmitter_control_fallback;
+ break;
+ }
+@@ -408,8 +406,6 @@ static void init_set_pixel_clock(struct bios_parser *bp)
+ bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7;
+ break;
+ default:
+- dm_output_to_console("Don't have set_pixel_clock for v%d\n",
+- BIOS_CMD_TABLE_PARA_REVISION(setpixelclock));
+ bp->cmd_tbl.set_pixel_clock = set_pixel_clock_fallback;
+ break;
+ }
+@@ -554,7 +550,6 @@ static void init_set_crtc_timing(struct bios_parser *bp)
+ set_crtc_using_dtd_timing_v3;
+ break;
+ default:
+- dm_output_to_console("Don't have set_crtc_timing for v%d\n", dtd_version);
+ bp->cmd_tbl.set_crtc_timing = NULL;
+ break;
+ }
+@@ -671,8 +666,6 @@ static void init_enable_crtc(struct bios_parser *bp)
+ bp->cmd_tbl.enable_crtc = enable_crtc_v1;
+ break;
+ default:
+- dm_output_to_console("Don't have enable_crtc for v%d\n",
+- BIOS_CMD_TABLE_PARA_REVISION(enablecrtc));
+ bp->cmd_tbl.enable_crtc = NULL;
+ break;
+ }
+@@ -864,8 +857,6 @@ static void init_set_dce_clock(struct bios_parser *bp)
+ bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1;
+ break;
+ default:
+- dm_output_to_console("Don't have set_dce_clock for v%d\n",
+- BIOS_CMD_TABLE_PARA_REVISION(setdceclock));
+ bp->cmd_tbl.set_dce_clock = NULL;
+ break;
+ }
+diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c
+index 73458e2951034..df8139bda142b 100644
+--- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c
++++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c
+@@ -87,8 +87,7 @@ bool dal_bios_parser_init_cmd_tbl_helper2(
+ return true;
+
+ default:
+- /* Unsupported DCE */
+- BREAK_TO_DEBUGGER();
++ *h = dal_cmd_tbl_helper_dce112_get_table2();
+ return false;
+ }
+ }
+--
+2.39.5
+
--- /dev/null
+From 40cd1c2b3ed3e0ab8fc5c4410f2b4bd31a54ed51 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 13:10:41 -0500
+Subject: drm/amd/display: Fix DMUB reset sequence for DCN401
+
+From: Dillon Varone <Dillon.Varone@amd.com>
+
+[ Upstream commit 0dfcc2bf269010a6e093793034c048049a40ee93 ]
+
+[WHY]
+It should no longer use DMCUB_SOFT_RESET as it can result
+in the memory request path becoming desynchronized.
+
+[HOW]
+To ensure robustness in the reset sequence:
+1) Extend timeout on the "halt" command sent via gpint, and check for
+controller to enter "wait" as a stronger guarantee that there are no
+requests to memory still in flight.
+2) Remove usage of DMCUB_SOFT_RESET
+3) Rely on PSP to reset the controller safely
+
+Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Signed-off-by: Dillon Varone <Dillon.Varone@amd.com>
+Signed-off-by: Wayne Lin <wayne.lin@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../drm/amd/display/dmub/src/dmub_dcn401.c | 47 ++++++++++++-------
+ .../drm/amd/display/dmub/src/dmub_dcn401.h | 3 +-
+ 2 files changed, 32 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c
+index 39a8cb6d7523c..e1c4fe1c6e3ee 100644
+--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c
++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c
+@@ -63,8 +63,10 @@ static inline void dmub_dcn401_translate_addr(const union dmub_addr *addr_in,
+ void dmub_dcn401_reset(struct dmub_srv *dmub)
+ {
+ union dmub_gpint_data_register cmd;
+- const uint32_t timeout = 30;
+- uint32_t in_reset, scratch, i;
++ const uint32_t timeout_us = 1 * 1000 * 1000; //1s
++ const uint32_t poll_delay_us = 1; //1us
++ uint32_t i = 0;
++ uint32_t in_reset, scratch, pwait_mode;
+
+ REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset);
+
+@@ -75,32 +77,35 @@ void dmub_dcn401_reset(struct dmub_srv *dmub)
+
+ dmub->hw_funcs.set_gpint(dmub, cmd);
+
+- /**
+- * Timeout covers both the ACK and the wait
+- * for remaining work to finish.
+- *
+- * This is mostly bound by the PHY disable sequence.
+- * Each register check will be greater than 1us, so
+- * don't bother using udelay.
+- */
+-
+- for (i = 0; i < timeout; ++i) {
++ for (i = 0; i < timeout_us; i++) {
+ if (dmub->hw_funcs.is_gpint_acked(dmub, cmd))
+ break;
++
++ udelay(poll_delay_us);
+ }
+
+- for (i = 0; i < timeout; ++i) {
++ for (; i < timeout_us; i++) {
+ scratch = dmub->hw_funcs.get_gpint_response(dmub);
+ if (scratch == DMUB_GPINT__STOP_FW_RESPONSE)
+ break;
++
++ udelay(poll_delay_us);
+ }
+
+- /* Force reset in case we timed out, DMCUB is likely hung. */
++ for (; i < timeout_us; i++) {
++ REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &pwait_mode);
++ if (pwait_mode & (1 << 0))
++ break;
++
++ udelay(poll_delay_us);
++ }
++ }
++
++ if (i >= timeout_us) {
++ /* timeout should never occur */
++ BREAK_TO_DEBUGGER();
+ }
+
+- REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1);
+- REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0);
+- REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1);
+ REG_WRITE(DMCUB_INBOX1_RPTR, 0);
+ REG_WRITE(DMCUB_INBOX1_WPTR, 0);
+ REG_WRITE(DMCUB_OUTBOX1_RPTR, 0);
+@@ -131,7 +136,10 @@ void dmub_dcn401_backdoor_load(struct dmub_srv *dmub,
+
+ dmub_dcn401_get_fb_base_offset(dmub, &fb_base, &fb_offset);
+
++ /* reset and disable DMCUB and MMHUBBUB DMUIF */
+ REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1);
++ REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1);
++ REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0);
+
+ dmub_dcn401_translate_addr(&cw0->offset, fb_base, fb_offset, &offset);
+
+@@ -151,6 +159,7 @@ void dmub_dcn401_backdoor_load(struct dmub_srv *dmub,
+ DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top,
+ DMCUB_REGION3_CW1_ENABLE, 1);
+
++ /* release DMCUB reset only to prevent premature execution */
+ REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID,
+ 0x20);
+ }
+@@ -161,7 +170,10 @@ void dmub_dcn401_backdoor_load_zfb_mode(struct dmub_srv *dmub,
+ {
+ union dmub_addr offset;
+
++ /* reset and disable DMCUB and MMHUBBUB DMUIF */
+ REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1);
++ REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1);
++ REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0);
+
+ offset = cw0->offset;
+
+@@ -181,6 +193,7 @@ void dmub_dcn401_backdoor_load_zfb_mode(struct dmub_srv *dmub,
+ DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top,
+ DMCUB_REGION3_CW1_ENABLE, 1);
+
++ /* release DMCUB reset only to prevent premature execution */
+ REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID,
+ 0x20);
+ }
+diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h
+index 4c8843b796950..31f95b27e227d 100644
+--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h
++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h
+@@ -169,7 +169,8 @@ struct dmub_srv;
+ DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_EN) \
+ DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_ACK) \
+ DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_STAT) \
+- DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_EN)
++ DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_EN) \
++ DMUB_SF(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS)
+
+ struct dmub_srv_dcn401_reg_offset {
+ #define DMUB_SR(reg) uint32_t reg;
+--
+2.39.5
+
--- /dev/null
+From 181accd35377db6c36ff135e3ee27b4af6574106 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Feb 2025 15:45:43 +0800
+Subject: drm/amd/display: Fix incorrect DPCD configs while Replay/PSR switch
+
+From: Leon Huang <Leon.Huang1@amd.com>
+
+[ Upstream commit 0d9cabc8f591ea1cd97c071b853b75b155c13259 ]
+
+[Why]
+When switching between PSR/Replay,
+the DPCD config of previous mode is not cleared,
+resulting in unexpected behavior in TCON.
+
+[How]
+Initialize the DPCD in setup function
+
+Reviewed-by: Robin Chen <robin.chen@amd.com>
+Signed-off-by: Leon Huang <Leon.Huang1@amd.com>
+Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../link/protocols/link_edp_panel_control.c | 25 ++++++++++++++++---
+ 1 file changed, 22 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
+index 3aa05a2be6c09..fa642f4b88c2d 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
+@@ -674,6 +674,18 @@ bool edp_setup_psr(struct dc_link *link,
+ if (!link)
+ return false;
+
++ //Clear PSR cfg
++ memset(&psr_configuration, 0, sizeof(psr_configuration));
++ dm_helpers_dp_write_dpcd(
++ link->ctx,
++ link,
++ DP_PSR_EN_CFG,
++ &psr_configuration.raw,
++ sizeof(psr_configuration.raw));
++
++ if (link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED)
++ return false;
++
+ dc = link->ctx->dc;
+ dmcu = dc->res_pool->dmcu;
+ psr = dc->res_pool->psr;
+@@ -684,9 +696,6 @@ bool edp_setup_psr(struct dc_link *link,
+ if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
+ return false;
+
+-
+- memset(&psr_configuration, 0, sizeof(psr_configuration));
+-
+ psr_configuration.bits.ENABLE = 1;
+ psr_configuration.bits.CRC_VERIFICATION = 1;
+ psr_configuration.bits.FRAME_CAPTURE_INDICATION =
+@@ -950,6 +959,16 @@ bool edp_setup_replay(struct dc_link *link, const struct dc_stream_state *stream
+ if (!link)
+ return false;
+
++ //Clear Replay config
++ dm_helpers_dp_write_dpcd(link->ctx, link,
++ DP_SINK_PR_ENABLE_AND_CONFIGURATION,
++ (uint8_t *)&(replay_config.raw), sizeof(uint8_t));
++
++ if (!(link->replay_settings.config.replay_supported))
++ return false;
++
++ link->replay_settings.config.replay_error_status.raw = 0;
++
+ dc = link->ctx->dc;
+
+ replay = dc->res_pool->replay;
+--
+2.39.5
+
--- /dev/null
+From 501cf1278e67c98263b57ef90e7eebab30749276 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Dec 2024 17:19:09 -0500
+Subject: drm/amd/display: Fix mismatch type comparison
+
+From: Assadian, Navid <navid.assadian@amd.com>
+
+[ Upstream commit 26873260d394b1e33cdd720154aedf0af95327f9 ]
+
+The mismatch type comparison/assignment may cause data loss. Since the
+values are always non-negative, it is safe to use unsigned variables to
+resolve the mismatch.
+
+Signed-off-by: Navid Assadian <navid.assadian@amd.com>
+Reviewed-by: Joshua Aberback <joshua.aberback@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/spl/dc_spl.c | 4 ++--
+ drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
+index 014e8a296f0c7..54c7d6aecf51c 100644
+--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
++++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
+@@ -875,8 +875,8 @@ static bool spl_get_optimal_number_of_taps(
+ bool *enable_isharp)
+ {
+ int num_part_y, num_part_c;
+- int max_taps_y, max_taps_c;
+- int min_taps_y, min_taps_c;
++ unsigned int max_taps_y, max_taps_c;
++ unsigned int min_taps_y, min_taps_c;
+ enum lb_memory_config lb_config;
+ bool skip_easf = false;
+
+diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h
+index 2a74ff5fdfdbc..a2c28949ec47f 100644
+--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h
++++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h
+@@ -479,7 +479,7 @@ struct spl_sharpness_range {
+ };
+ struct adaptive_sharpness {
+ bool enable;
+- int sharpness_level;
++ unsigned int sharpness_level;
+ struct spl_sharpness_range sharpness_range;
+ };
+ enum linear_light_scaling { // convert it in translation logic
+--
+2.39.5
+
--- /dev/null
+From 3033a249f554f7c71b57f1b6a6cc5ad1782a9613 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Feb 2025 17:06:42 -0500
+Subject: drm/amd/display: Fix p-state type when p-state is unsupported
+
+From: Dillon Varone <Dillon.Varone@amd.com>
+
+[ Upstream commit a025f424af0407b7561bd5e6217295dde3abbc2e ]
+
+[WHY&HOW]
+P-state type would remain on previously used when unsupported which
+causes confusion in logging and visual confirm, so set back to zero
+when unsupported.
+
+Reviewed-by: Aric Cyr <aric.cyr@amd.com>
+Signed-off-by: Dillon Varone <Dillon.Varone@amd.com>
+Signed-off-by: Wayne Lin <wayne.lin@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+index fdcba960e1e6f..d2342a91e7e71 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+@@ -508,6 +508,7 @@ void set_p_state_switch_method(
+ if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !vba)
+ return;
+
++ pipe_ctx->p_state_type = P_STATE_UNKNOWN;
+ if (vba->DRAMClockChangeSupport[vba->VoltageLevel][vba->maxMpcComb] !=
+ dm_dram_clock_change_unsupported) {
+ /* MCLK switching is supported */
+--
+2.39.5
+
--- /dev/null
+From 34261fb5e830f054fd80915145ff9d2184dd35f2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Mar 2025 23:15:56 +0800
+Subject: drm/amd/display: Guard against setting dispclk low for dcn31x
+
+From: Jing Zhou <Jing.Zhou@amd.com>
+
+[ Upstream commit 9c2f4ae64bb6f6d83a54d88b9ee0f369cdbb9fa8 ]
+
+[WHY]
+We should never apply a minimum dispclk value while in
+prepare_bandwidth or while displays are active. This is
+always an optimizaiton for when all displays are disabled.
+
+[HOW]
+Defer dispclk optimization until safe_to_lower = true
+and display_count reaches 0.
+
+Since 0 has a special value in this logic (ie. no dispclk
+required) we also need adjust the logic that clamps it for
+the actual request to PMFW.
+
+Reviewed-by: Charlene Liu <charlene.liu@amd.com>
+Reviewed-by: Chris Park <chris.park@amd.com>
+Reviewed-by: Eric Yang <eric.yang@amd.com>
+Signed-off-by: Jing Zhou <Jing.Zhou@amd.com>
+Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../dc/clk_mgr/dcn315/dcn315_clk_mgr.c | 20 +++++++++++--------
+ .../dc/clk_mgr/dcn316/dcn316_clk_mgr.c | 13 +++++++++---
+ 2 files changed, 22 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
+index a0fb4481d2f1b..827b24b3442ad 100644
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
+@@ -130,7 +130,7 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+ struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
+ struct dc *dc = clk_mgr_base->ctx->dc;
+- int display_count;
++ int display_count = 0;
+ bool update_dppclk = false;
+ bool update_dispclk = false;
+ bool dpp_clock_lowered = false;
+@@ -204,15 +204,19 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
+ update_dppclk = true;
+ }
+
+- if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) {
+- /* No need to apply the w/a if we haven't taken over from bios yet */
+- if (clk_mgr_base->clks.dispclk_khz)
+- dcn315_disable_otg_wa(clk_mgr_base, context, true);
++ if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) &&
++ (new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) {
++ int requested_dispclk_khz = new_clocks->dispclk_khz;
+
++ dcn315_disable_otg_wa(clk_mgr_base, context, true);
++
++ /* Clamp the requested clock to PMFW based on their limit. */
++ if (dc->debug.min_disp_clk_khz > 0 && requested_dispclk_khz < dc->debug.min_disp_clk_khz)
++ requested_dispclk_khz = dc->debug.min_disp_clk_khz;
++
++ dcn315_smu_set_dispclk(clk_mgr, requested_dispclk_khz);
+ clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
+- dcn315_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz);
+- if (clk_mgr_base->clks.dispclk_khz)
+- dcn315_disable_otg_wa(clk_mgr_base, context, false);
++ dcn315_disable_otg_wa(clk_mgr_base, context, false);
+
+ update_dispclk = true;
+ }
+diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
+index c3e50c3aaa609..37c39756fece4 100644
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
+@@ -140,7 +140,7 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base,
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+ struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
+ struct dc *dc = clk_mgr_base->ctx->dc;
+- int display_count;
++ int display_count = 0;
+ bool update_dppclk = false;
+ bool update_dispclk = false;
+ bool dpp_clock_lowered = false;
+@@ -211,11 +211,18 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base,
+ update_dppclk = true;
+ }
+
+- if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) {
++ if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) &&
++ (new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) {
++ int requested_dispclk_khz = new_clocks->dispclk_khz;
++
+ dcn316_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true);
+
++ /* Clamp the requested clock to PMFW based on their limit. */
++ if (dc->debug.min_disp_clk_khz > 0 && requested_dispclk_khz < dc->debug.min_disp_clk_khz)
++ requested_dispclk_khz = dc->debug.min_disp_clk_khz;
++
++ dcn316_smu_set_dispclk(clk_mgr, requested_dispclk_khz);
+ clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
+- dcn316_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz);
+ dcn316_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false);
+
+ update_dispclk = true;
+--
+2.39.5
+
--- /dev/null
+From 928eb8f16832eda40469059ff0b711b7ecd2dd35 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Feb 2025 09:49:58 -0500
+Subject: drm/amd/display: Guard against setting dispclk low when active
+
+From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+
+[ Upstream commit 72d7a7fa1f2404fd31c84a8f808b1b37021a3a9e ]
+
+[Why]
+We should never apply a minimum dispclk value while in prepare_bandwidth
+or while displays are active. This is always an optimization for when
+all displays are disabled.
+
+[How]
+Defer dispclk optimization until safe_to_lower = true and display_count
+reaches 0.
+
+Since 0 has a special value in this logic (ie. no dispclk required)
+we also need adjust the logic that clamps it for the actual request
+to PMFW.
+
+Reviewed-by: Gabe Teeger <gabe.teeger@amd.com>
+Reviewed-by: Leo Chen <leo.chen@amd.com>
+Reviewed-by: Syed Hassan <syed.hassan@amd.com>
+Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Signed-off-by: Roman Li <roman.li@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
+index 7d0d8852ce8d2..a4ac601a30c35 100644
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
+@@ -452,14 +452,19 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
+ update_dppclk = true;
+ }
+
+- if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) {
++ if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) &&
++ (new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) {
++ int requested_dispclk_khz = new_clocks->dispclk_khz;
++
+ dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true);
+
+- if (dc->debug.min_disp_clk_khz > 0 && new_clocks->dispclk_khz < dc->debug.min_disp_clk_khz)
+- new_clocks->dispclk_khz = dc->debug.min_disp_clk_khz;
++ /* Clamp the requested clock to PMFW based on their limit. */
++ if (dc->debug.min_disp_clk_khz > 0 && requested_dispclk_khz < dc->debug.min_disp_clk_khz)
++ requested_dispclk_khz = dc->debug.min_disp_clk_khz;
+
++ dcn35_smu_set_dispclk(clk_mgr, requested_dispclk_khz);
+ clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
+- dcn35_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz);
++
+ dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false);
+
+ update_dispclk = true;
+--
+2.39.5
+
--- /dev/null
+From 7206c0077c86668a379e918a6b6bafa4fbcedd49 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Feb 2025 15:17:56 -0500
+Subject: drm/amd/display: handle max_downscale_src_width fail check
+
+From: Yihan Zhu <Yihan.Zhu@amd.com>
+
+[ Upstream commit 02a940da2ccc0cc0299811379580852b405a0ea2 ]
+
+[WHY]
+If max_downscale_src_width check fails, we exit early from TAP calculation and left a NULL
+value to the scaling data structure to cause the zero divide in the DML validation.
+
+[HOW]
+Call set default TAP calculation before early exit in get_optimal_number_of_taps due to
+max downscale limit exceed.
+
+Reviewed-by: Samson Tam <samson.tam@amd.com>
+Signed-off-by: Yihan Zhu <Yihan.Zhu@amd.com>
+Signed-off-by: Zaeem Mohamed <zaeem.mohamed@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c
+index 40acebd13e46d..abf439e743f23 100644
+--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c
++++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c
+@@ -425,11 +425,6 @@ bool dpp3_get_optimal_number_of_taps(
+ int min_taps_y, min_taps_c;
+ enum lb_memory_config lb_config;
+
+- if (scl_data->viewport.width > scl_data->h_active &&
+- dpp->ctx->dc->debug.max_downscale_src_width != 0 &&
+- scl_data->viewport.width > dpp->ctx->dc->debug.max_downscale_src_width)
+- return false;
+-
+ /*
+ * Set default taps if none are provided
+ * From programming guide: taps = min{ ceil(2*H_RATIO,1), 8} for downscaling
+@@ -467,6 +462,12 @@ bool dpp3_get_optimal_number_of_taps(
+ else
+ scl_data->taps.h_taps_c = in_taps->h_taps_c;
+
++ // Avoid null data in the scl data with this early return, proceed non-adaptive calcualtion first
++ if (scl_data->viewport.width > scl_data->h_active &&
++ dpp->ctx->dc->debug.max_downscale_src_width != 0 &&
++ scl_data->viewport.width > dpp->ctx->dc->debug.max_downscale_src_width)
++ return false;
++
+ /*Ensure we can support the requested number of vtaps*/
+ min_taps_y = dc_fixpt_ceil(scl_data->ratios.vert);
+ min_taps_c = dc_fixpt_ceil(scl_data->ratios.vert_c);
+--
+2.39.5
+
--- /dev/null
+From b65629bc0e05e7b7a05478630792959a8818d0e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Jan 2025 12:03:23 -0500
+Subject: drm/amd/display: Increase block_sequence array size
+
+From: Joshua Aberback <joshua.aberback@amd.com>
+
+[ Upstream commit 3a7810c212bcf2f722671dadf4b23ff70a7d23ee ]
+
+[Why]
+It's possible to generate more than 50 steps in hwss_build_fast_sequence,
+for example with a 6-pipe asic where all pipes are in one MPC chain. This
+overflows the block_sequence buffer and corrupts block_sequence_steps,
+causing a crash.
+
+[How]
+Expand block_sequence to 100 items. A naive upper bound on the possible
+number of steps for a 6-pipe asic, ignoring the potential for steps to be
+mutually exclusive, is 91 with current code, therefore 100 is sufficient.
+
+Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
+Signed-off-by: Joshua Aberback <joshua.aberback@amd.com>
+Signed-off-by: Wayne Lin <wayne.lin@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+index e1e3142cdc00a..62fb2009b3028 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+@@ -621,7 +621,7 @@ struct dc_state {
+ */
+ struct bw_context bw_ctx;
+
+- struct block_sequence block_sequence[50];
++ struct block_sequence block_sequence[100];
+ unsigned int block_sequence_steps;
+ struct dc_dmub_cmd dc_dmub_cmd[10];
+ unsigned int dmub_cmd_count;
+--
+2.39.5
+
--- /dev/null
+From 888a339141c2d29b196be0c915377c8fbd5d9eda Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jan 2025 14:22:31 +0800
+Subject: drm/amd/display: Initial psr_version with correct setting
+
+From: Tom Chung <chiahsuan.chung@amd.com>
+
+[ Upstream commit d8c782cac5007e68e7484d420168f12d3490def6 ]
+
+[Why & How]
+The initial setting for psr_version is not correct while
+create a virtual link.
+
+The default psr_version should be DC_PSR_VERSION_UNSUPPORTED.
+
+Reviewed-by: Roman Li <roman.li@amd.com>
+Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Zaeem Mohamed <zaeem.mohamed@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
+index fa7db10104c45..a99d3e2256f19 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
+@@ -276,6 +276,7 @@ static bool create_links(
+ link->link_id.type = OBJECT_TYPE_CONNECTOR;
+ link->link_id.id = CONNECTOR_ID_VIRTUAL;
+ link->link_id.enum_id = ENUM_ID_1;
++ link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
+ link->link_enc = kzalloc(sizeof(*link->link_enc), GFP_KERNEL);
+
+ if (!link->link_enc) {
+--
+2.39.5
+
--- /dev/null
+From c062cc4df989af99959a3b0320de505f37616546 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 14:52:30 +0800
+Subject: drm/amd/display: not abort link train when bw is low
+
+From: Peichen Huang <PeiChen.Huang@amd.com>
+
+[ Upstream commit 8a21da2842bb22b2b80e5902d0438030d729bfd3 ]
+
+[WHY]
+DP tunneling should not abort link train even bandwidth become
+too low after downgrade. Otherwise, it would fail compliance test.
+
+[HOW}
+Do link train with downgrade settings even bandwidth is not enough
+
+Reviewed-by: Cruise Hung <cruise.hung@amd.com>
+Reviewed-by: Meenakshikumar Somasundaram <meenakshikumar.somasundaram@amd.com>
+Signed-off-by: Peichen Huang <PeiChen.Huang@amd.com>
+Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/link/protocols/link_dp_training.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
+index 27b881f947e8b..9385a32a471b8 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
+@@ -1769,13 +1769,10 @@ bool perform_link_training_with_retries(
+ is_link_bw_min = ((cur_link_settings.link_rate <= LINK_RATE_LOW) &&
+ (cur_link_settings.lane_count <= LANE_COUNT_ONE));
+
+- if (is_link_bw_low) {
++ if (is_link_bw_low)
+ DC_LOG_WARNING(
+ "%s: Link(%d) bandwidth too low after fallback req_bw(%d) > link_bw(%d)\n",
+ __func__, link->link_index, req_bw, link_bw);
+-
+- return false;
+- }
+ }
+
+ msleep(delay_between_attempts);
+--
+2.39.5
+
--- /dev/null
+From fe97b59ef5da22df05f39275380bf461927b8502 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jan 2025 11:57:54 -0500
+Subject: drm/amd/display: pass calculated dram_speed_mts to dml2
+
+From: Charlene Liu <Charlene.Liu@amd.com>
+
+[ Upstream commit b40d022ec06ade9f6c809091dc188422a0f0946d ]
+
+[why]
+currently dml2 is using a hard coded 16 to convert memclk to dram_speed_mts.
+for apu, this depends on wck_ratio.
+
+change to pass the already calculated dram_speed_mts from fpu to dml2.
+
+v2: use existing calculation of dram_speed_mts for now to avoid regression
+
+Signed-off-by: Charlene Liu <Charlene.Liu@amd.com>
+Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Reviewed-by: Roman Li <Roman.Li@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c | 2 ++
+ drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c | 1 +
+ drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h | 1 +
+ 3 files changed, 4 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c
+index beed7adbbd43e..c90dee4e9116a 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c
+@@ -367,6 +367,8 @@ void dcn35_update_bw_bounding_box_fpu(struct dc *dc,
+ clock_limits[i].socclk_mhz;
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].memclk_mhz =
+ clk_table->entries[i].memclk_mhz * clk_table->entries[i].wck_ratio;
++
++ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dram_speed_mts = clock_limits[i].dram_speed_mts;
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz =
+ clock_limits[i].dtbclk_mhz;
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dcfclk_levels =
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c
+index a201dbb743d79..79d921adc2153 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c
+@@ -401,6 +401,7 @@ void dcn351_update_bw_bounding_box_fpu(struct dc *dc,
+ clock_limits[i].socclk_mhz;
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].memclk_mhz =
+ clk_table->entries[i].memclk_mhz * clk_table->entries[i].wck_ratio;
++ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dram_speed_mts = clock_limits[i].dram_speed_mts;
+ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz =
+ clock_limits[i].dtbclk_mhz;
+ dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dcfclk_levels =
+diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
+index 0f944fcfd5a5b..785226945699d 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
+@@ -159,6 +159,7 @@ struct dml2_clks_table_entry {
+ unsigned int dtbclk_mhz;
+ unsigned int dispclk_mhz;
+ unsigned int dppclk_mhz;
++ unsigned int dram_speed_mts; /*which is based on wck_ratio*/
+ };
+
+ struct dml2_clks_num_entries {
+--
+2.39.5
+
--- /dev/null
+From d5a1591af12e46b77ff24b958c61cb87afb14bf0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Jan 2025 15:25:41 -0500
+Subject: drm/amd/display: Populate register address for dentist for dcn401
+
+From: Dillon Varone <dillon.varone@amd.com>
+
+[ Upstream commit 5f0d1ef6f16e150ee46cc00b8d233d9d271fe39e ]
+
+[WHY&HOW]
+Address was not previously populated which can result in incorrect
+clock frequencies being read on boot.
+
+Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
+Signed-off-by: Dillon Varone <dillon.varone@amd.com>
+Signed-off-by: Wayne Lin <wayne.lin@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c | 2 ++
+ drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h | 1 +
+ 2 files changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
+index 8cfc5f4359374..313e52997596a 100644
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
+@@ -24,6 +24,8 @@
+
+ #include "dml/dcn401/dcn401_fpu.h"
+
++#define DCN_BASE__INST0_SEG1 0x000000C0
++
+ #define mmCLK01_CLK0_CLK_PLL_REQ 0x16E37
+ #define mmCLK01_CLK0_CLK0_DFS_CNTL 0x16E69
+ #define mmCLK01_CLK0_CLK1_DFS_CNTL 0x16E6C
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
+index 7a1ca1e98059b..221645c023b50 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
+@@ -221,6 +221,7 @@ enum dentist_divider_range {
+ CLK_SF(CLK0_CLK_PLL_REQ, FbMult_frac, mask_sh)
+
+ #define CLK_REG_LIST_DCN401() \
++ SR(DENTIST_DISPCLK_CNTL), \
+ CLK_SR_DCN401(CLK0_CLK_PLL_REQ, CLK01, 0), \
+ CLK_SR_DCN401(CLK0_CLK0_DFS_CNTL, CLK01, 0), \
+ CLK_SR_DCN401(CLK0_CLK1_DFS_CNTL, CLK01, 0), \
+--
+2.39.5
+
--- /dev/null
+From e0c52d80cec35d3168fb0d94c185c01c8d8456cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Feb 2025 14:34:02 -0500
+Subject: drm/amd/display: Read LTTPR ALPM caps during link cap retrieval
+
+From: George Shen <george.shen@amd.com>
+
+[ Upstream commit de84d580126eb2214937df755cfec5ef0901479e ]
+
+[Why]
+The latest DP spec requires the DP TX to read DPCD F0000h through F0009h
+when detecting LTTPR capabilities for the first time.
+
+[How]
+Update LTTPR cap retrieval to read up to F0009h (two more bytes than the
+previous F0007h), and store the LTTPR ALPM capabilities.
+
+Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
+Signed-off-by: George Shen <george.shen@amd.com>
+Signed-off-by: Roman Li <roman.li@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 12 ++++++++++++
+ .../display/dc/link/protocols/link_dp_capability.c | 6 +++++-
+ 2 files changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
+index 41bd95e9177a4..223c3d55544b2 100644
+--- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
++++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
+@@ -959,6 +959,14 @@ union dp_128b_132b_supported_lttpr_link_rates {
+ uint8_t raw;
+ };
+
++union dp_alpm_lttpr_cap {
++ struct {
++ uint8_t AUX_LESS_ALPM_SUPPORTED :1;
++ uint8_t RESERVED :7;
++ } bits;
++ uint8_t raw;
++};
++
+ union dp_sink_video_fallback_formats {
+ struct {
+ uint8_t dp_1024x768_60Hz_24bpp_support :1;
+@@ -1103,6 +1111,7 @@ struct dc_lttpr_caps {
+ uint8_t max_ext_timeout;
+ union dp_main_link_channel_coding_lttpr_cap main_link_channel_coding;
+ union dp_128b_132b_supported_lttpr_link_rates supported_128b_132b_rates;
++ union dp_alpm_lttpr_cap alpm;
+ uint8_t aux_rd_interval[MAX_REPEATER_CNT - 1];
+ };
+
+@@ -1352,6 +1361,9 @@ struct dp_trace {
+ #ifndef DPCD_MAX_UNCOMPRESSED_PIXEL_RATE_CAP
+ #define DPCD_MAX_UNCOMPRESSED_PIXEL_RATE_CAP 0x221c
+ #endif
++#ifndef DP_LTTPR_ALPM_CAPABILITIES
++#define DP_LTTPR_ALPM_CAPABILITIES 0xF0009
++#endif
+ #ifndef DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE
+ #define DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE 0x50
+ #endif
+diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
+index d9a1e1a599674..842636c7922b4 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
+@@ -1495,7 +1495,7 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link)
+
+ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link)
+ {
+- uint8_t lttpr_dpcd_data[8] = {0};
++ uint8_t lttpr_dpcd_data[10] = {0};
+ enum dc_status status;
+ bool is_lttpr_present;
+
+@@ -1545,6 +1545,10 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link)
+ lttpr_dpcd_data[DP_PHY_REPEATER_128B132B_RATES -
+ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
+
++ link->dpcd_caps.lttpr_caps.alpm.raw =
++ lttpr_dpcd_data[DP_LTTPR_ALPM_CAPABILITIES -
++ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
++
+ /* If this chip cap is set, at least one retimer must exist in the chain
+ * Override count to 1 if we receive a known bad count (0 or an invalid value) */
+ if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
+--
+2.39.5
+
--- /dev/null
+From 14397f8734aa1734754f3c05af60ca791e7a8a27 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Mar 2025 13:53:16 -0500
+Subject: drm/amd/display: remove minimum Dispclk and apply oem panel timing.
+
+From: Charlene Liu <Charlene.Liu@amd.com>
+
+[ Upstream commit 756e58e83e89d372b94269c0cde61fe55da76947 ]
+
+[why & how]
+1. apply oem panel timing (not only on OLED)
+2. remove MIN_DPP_DISP_CLK request in driver.
+
+This fix will apply for dcn31x but not
+sync with DML's output.
+
+Reviewed-by: Ovidiu Bunea <ovidiu.bunea@amd.com>
+Signed-off-by: Charlene Liu <Charlene.Liu@amd.com>
+Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c | 2 --
+ drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c | 2 --
+ drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 3 ++-
+ 3 files changed, 2 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
+index 827b24b3442ad..e4d22f74f9869 100644
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
+@@ -194,8 +194,6 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
+ // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow.
+ if (new_clocks->dppclk_khz < MIN_DPP_DISP_CLK)
+ new_clocks->dppclk_khz = MIN_DPP_DISP_CLK;
+- if (new_clocks->dispclk_khz < MIN_DPP_DISP_CLK)
+- new_clocks->dispclk_khz = MIN_DPP_DISP_CLK;
+
+ if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) {
+ if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz)
+diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
+index 37c39756fece4..49efea0c8fcff 100644
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
+@@ -201,8 +201,6 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base,
+ // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow.
+ if (new_clocks->dppclk_khz < 100000)
+ new_clocks->dppclk_khz = 100000;
+- if (new_clocks->dispclk_khz < 100000)
+- new_clocks->dispclk_khz = 100000;
+
+ if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) {
+ if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz)
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+index 1e76524d116dc..59457ca24e1dc 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+@@ -1064,7 +1064,8 @@ void dce110_edp_backlight_control(
+ DC_LOG_DC("edp_receiver_ready_T9 skipped\n");
+ }
+
+- if (!enable && link->dpcd_sink_ext_caps.bits.oled) {
++ if (!enable) {
++ /*follow oem panel config's requirement*/
+ pre_T11_delay += link->panel_config.pps.extra_pre_t11_ms;
+ msleep(pre_T11_delay);
+ }
+--
+2.39.5
+
--- /dev/null
+From d6cb0f813d45cf66b2c926284b0418af7d7a54cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jan 2025 16:39:52 -0500
+Subject: drm/amd/display: Request HW cursor on DCN3.2 with SubVP
+
+From: Aric Cyr <Aric.Cyr@amd.com>
+
+[ Upstream commit b74f46f3ce1e5f6336645f1e9ff47c56d5dfdef1 ]
+
+[why]
+When SubVP is active the HW cursor size is limited to 64x64, and
+anything larger will force composition which is bad for gaming on
+DCN3.2 if the game uses a larger cursor.
+
+[how]
+If HW cursor is requested, typically by a fullscreen game, do not
+enable SubVP so that up to 256x256 cursor sizes are available for
+DCN3.2.
+
+Reviewed-by: Aric Cyr <aric.cyr@amd.com>
+Signed-off-by: Aric Cyr <Aric.Cyr@amd.com>
+Signed-off-by: Wayne Lin <wayne.lin@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 3 ++-
+ drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 1 +
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
+index dd4b131fac6cb..fa7db10104c45 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
+@@ -4744,7 +4744,8 @@ static bool full_update_required(struct dc *dc,
+ stream_update->lut3d_func ||
+ stream_update->pending_test_pattern ||
+ stream_update->crtc_timing_adjust ||
+- stream_update->scaler_sharpener_update))
++ stream_update->scaler_sharpener_update ||
++ stream_update->hw_cursor_req))
+ return true;
+
+ if (stream) {
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+index 6f490d8d7038c..56dda686e2992 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+@@ -626,6 +626,7 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc,
+ * - Not TMZ surface
+ */
+ if (pipe->plane_state && !pipe->top_pipe && !pipe->prev_odm_pipe && !dcn32_is_center_timing(pipe) &&
++ !pipe->stream->hw_cursor_req &&
+ !(pipe->stream->timing.pix_clk_100hz / 10000 > DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ) &&
+ (!dcn32_is_psr_capable(pipe) || (context->stream_count == 1 && dc->caps.dmub_caps.subvp_psr)) &&
+ dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_NONE &&
+--
+2.39.5
+
--- /dev/null
+From d053aa9690d0fde790630c2d40ad2261e4b0fd27 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Feb 2025 22:00:13 -0500
+Subject: drm/amd/display: Skip checking FRL_MODE bit for PCON BW determination
+
+From: George Shen <george.shen@amd.com>
+
+[ Upstream commit 0584bbcf0c53c133081100e4f4c9fe41e598d045 ]
+
+[Why/How]
+Certain PCON will clear the FRL_MODE bit despite supporting the link BW
+indicated in the other bits.
+
+Thus, skip checking the FRL_MODE bit when interpreting the
+hdmi_encoded_link_bw struct.
+
+Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
+Signed-off-by: George Shen <george.shen@amd.com>
+Signed-off-by: Wayne Lin <wayne.lin@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../dc/link/protocols/link_dp_capability.c | 30 +++++++++----------
+ 1 file changed, 15 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
+index 885e749cdc6e9..23e650e39910e 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
+@@ -250,21 +250,21 @@ static uint32_t intersect_frl_link_bw_support(
+ {
+ uint32_t supported_bw_in_kbps = max_supported_frl_bw_in_kbps;
+
+- // HDMI_ENCODED_LINK_BW bits are only valid if HDMI Link Configuration bit is 1 (FRL mode)
+- if (hdmi_encoded_link_bw.bits.FRL_MODE) {
+- if (hdmi_encoded_link_bw.bits.BW_48Gbps)
+- supported_bw_in_kbps = 48000000;
+- else if (hdmi_encoded_link_bw.bits.BW_40Gbps)
+- supported_bw_in_kbps = 40000000;
+- else if (hdmi_encoded_link_bw.bits.BW_32Gbps)
+- supported_bw_in_kbps = 32000000;
+- else if (hdmi_encoded_link_bw.bits.BW_24Gbps)
+- supported_bw_in_kbps = 24000000;
+- else if (hdmi_encoded_link_bw.bits.BW_18Gbps)
+- supported_bw_in_kbps = 18000000;
+- else if (hdmi_encoded_link_bw.bits.BW_9Gbps)
+- supported_bw_in_kbps = 9000000;
+- }
++ /* Skip checking FRL_MODE bit, as certain PCON will clear
++ * it despite supporting the link BW indicated in the other bits.
++ */
++ if (hdmi_encoded_link_bw.bits.BW_48Gbps)
++ supported_bw_in_kbps = 48000000;
++ else if (hdmi_encoded_link_bw.bits.BW_40Gbps)
++ supported_bw_in_kbps = 40000000;
++ else if (hdmi_encoded_link_bw.bits.BW_32Gbps)
++ supported_bw_in_kbps = 32000000;
++ else if (hdmi_encoded_link_bw.bits.BW_24Gbps)
++ supported_bw_in_kbps = 24000000;
++ else if (hdmi_encoded_link_bw.bits.BW_18Gbps)
++ supported_bw_in_kbps = 18000000;
++ else if (hdmi_encoded_link_bw.bits.BW_9Gbps)
++ supported_bw_in_kbps = 9000000;
+
+ return supported_bw_in_kbps;
+ }
+--
+2.39.5
+
--- /dev/null
+From 7ccb1033c4f5df1a03a0b35ccaef018fcfdfd1c3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Jan 2025 11:21:46 +0800
+Subject: drm/amd/display: Support multiple options during psr entry.
+
+From: Martin Tsai <Martin.Tsai@amd.com>
+
+[ Upstream commit 3a5fa55455db6a11248a25f24570c365f9246144 ]
+
+[WHY]
+Some panels may not handle idle pattern properly during PSR entry.
+
+[HOW]
+Add a condition to allow multiple options on power down
+sequence during PSR1 entry.
+
+Reviewed-by: Anthony Koo <anthony.koo@amd.com>
+Signed-off-by: Martin Tsai <Martin.Tsai@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dc_types.h | 7 +++++++
+ drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 4 ++++
+ drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 6 ++++++
+ 3 files changed, 17 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
+index c8bdbbba44ef9..1aca9e96c474f 100644
+--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
++++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
+@@ -1009,6 +1009,13 @@ struct psr_settings {
+ unsigned int psr_sdp_transmit_line_num_deadline;
+ uint8_t force_ffu_mode;
+ unsigned int psr_power_opt;
++
++ /**
++ * Some panels cannot handle idle pattern during PSR entry.
++ * To power down phy before disable stream to avoid sending
++ * idle pattern.
++ */
++ uint8_t power_down_phy_before_disable_stream;
+ };
+
+ enum replay_coasting_vtotal_type {
+diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
+index cae18f8c1c9a0..8821153d0ac3b 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
++++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
+@@ -419,6 +419,10 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
+ copy_settings_data->relock_delay_frame_cnt = 0;
+ if (link->dpcd_caps.sink_dev_id == DP_BRANCH_DEVICE_ID_001CF8)
+ copy_settings_data->relock_delay_frame_cnt = 2;
++
++ copy_settings_data->power_down_phy_before_disable_stream =
++ link->psr_settings.power_down_phy_before_disable_stream;
++
+ copy_settings_data->dsc_slice_height = psr_context->dsc_slice_height;
+
+ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+index 7835100b37c41..d743368303682 100644
+--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
++++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+@@ -2869,6 +2869,12 @@ struct dmub_cmd_psr_copy_settings_data {
+ * Some panels request main link off before xth vertical line
+ */
+ uint16_t poweroff_before_vertical_line;
++ /**
++ * Some panels cannot handle idle pattern during PSR entry.
++ * To power down phy before disable stream to avoid sending
++ * idle pattern.
++ */
++ uint8_t power_down_phy_before_disable_stream;
+ };
+
+ /**
+--
+2.39.5
+
--- /dev/null
+From be24d5f7426a5d098b7197db5243c9a62413fb3f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Jan 2025 11:35:46 -0500
+Subject: drm/amd/display: Update CR AUX RD interval interpretation
+
+From: George Shen <george.shen@amd.com>
+
+[ Upstream commit 6a7fde433231c18164c117592d3e18ced648ad58 ]
+
+[Why]
+DP spec updated to have the CR AUX RD interval match the EQ AUX RD
+interval interpretation of DPCD 0000Eh/0220Eh for 8b/10b non-LTTPR mode
+and LTTPR transparent mode cases.
+
+[How]
+Update interpretation of DPCD 0000Eh/0220Eh for CR AUX RD interval
+during 8b/10b link training.
+
+Reviewed-by: Michael Strauss <michael.strauss@amd.com>
+Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
+Signed-off-by: George Shen <george.shen@amd.com>
+Signed-off-by: Zaeem Mohamed <zaeem.mohamed@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../display/dc/link/protocols/link_dp_training_8b_10b.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c
+index 3bdce32a85e3c..ae95ec48e5721 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c
++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c
+@@ -36,7 +36,8 @@
+ link->ctx->logger
+
+ static int32_t get_cr_training_aux_rd_interval(struct dc_link *link,
+- const struct dc_link_settings *link_settings)
++ const struct dc_link_settings *link_settings,
++ enum lttpr_mode lttpr_mode)
+ {
+ union training_aux_rd_interval training_rd_interval;
+ uint32_t wait_in_micro_secs = 100;
+@@ -49,6 +50,8 @@ static int32_t get_cr_training_aux_rd_interval(struct dc_link *link,
+ DP_TRAINING_AUX_RD_INTERVAL,
+ (uint8_t *)&training_rd_interval,
+ sizeof(training_rd_interval));
++ if (lttpr_mode != LTTPR_MODE_NON_TRANSPARENT)
++ wait_in_micro_secs = 400;
+ if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL)
+ wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
+ }
+@@ -110,7 +113,6 @@ void decide_8b_10b_training_settings(
+ */
+ lt_settings->link_settings.link_spread = link->dp_ss_off ?
+ LINK_SPREAD_DISABLED : LINK_SPREAD_05_DOWNSPREAD_30KHZ;
+- lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting);
+ lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting);
+ lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting);
+ lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting);
+@@ -119,6 +121,7 @@ void decide_8b_10b_training_settings(
+ lt_settings->disallow_per_lane_settings = true;
+ lt_settings->always_match_dpcd_with_hw_lane_settings = true;
+ lt_settings->lttpr_mode = dp_decide_8b_10b_lttpr_mode(link);
++ lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting, lt_settings->lttpr_mode);
+ dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 967add8d3b7996e7c4e07faad51710bc5901cbc5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Jan 2025 17:49:36 -0500
+Subject: drm/amd/display: Use Nominal vBlank If Provided Instead Of Capping It
+
+From: Austin Zheng <Austin.Zheng@amd.com>
+
+[ Upstream commit 41df56b1fc24cc36fffb10e437385b3a49fbb5e2 ]
+
+[Why/How]
+vBlank used to determine the max vStartup is based on the smallest between
+the vblank provided by the timing and vblank in ip_caps.
+Extra vblank time is not considered if the vblank provided by the timing ends
+up being higher than what's defined by the ip_caps
+
+Use 1 less than the vblank size in case the timing is interlaced
+so vstartup will always be less than vblank_nom.
+
+Reviewed-by: Dillon Varone <dillon.varone@amd.com>
+Signed-off-by: Austin Zheng <Austin.Zheng@amd.com>
+Signed-off-by: Wayne Lin <wayne.lin@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
+index e2a3764d9d181..0090b7bc232bf 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
+@@ -3630,13 +3630,12 @@ static unsigned int CalculateMaxVStartup(
+ double line_time_us = (double)timing->h_total / ((double)timing->pixel_clock_khz / 1000);
+ unsigned int vblank_actual = timing->v_total - timing->v_active;
+ unsigned int vblank_nom_default_in_line = (unsigned int)math_floor2((double)vblank_nom_default_us / line_time_us, 1.0);
+- unsigned int vblank_nom_input = (unsigned int)math_min2(timing->vblank_nom, vblank_nom_default_in_line);
+- unsigned int vblank_avail = (vblank_nom_input == 0) ? vblank_nom_default_in_line : vblank_nom_input;
++ unsigned int vblank_avail = (timing->vblank_nom == 0) ? vblank_nom_default_in_line : (unsigned int)timing->vblank_nom;
+
+ vblank_size = (unsigned int)math_min2(vblank_actual, vblank_avail);
+
+ if (timing->interlaced && !ptoi_supported)
+- max_vstartup_lines = (unsigned int)(math_floor2(vblank_size / 2.0, 1.0));
++ max_vstartup_lines = (unsigned int)(math_floor2((vblank_size - 1) / 2.0, 1.0));
+ else
+ max_vstartup_lines = vblank_size - (unsigned int)math_max2(1.0, math_ceil2(write_back_delay_us / line_time_us, 1.0));
+ #ifdef __DML_VBA_DEBUG__
+--
+2.39.5
+
--- /dev/null
+From a1575df5c6909dbd6fdfaa1dd8f589170534a6a5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Feb 2025 17:43:01 +0530
+Subject: drm/amd/pm: Fetch current power limit from PMFW
+
+From: Lijo Lazar <lijo.lazar@amd.com>
+
+[ Upstream commit b2a9e562dfa156bd53e62ce571f3f8f65d243f14 ]
+
+On SMU v13.0.12, always query the firmware to get the current power
+limit as it could be updated through other means also.
+
+Signed-off-by: Lijo Lazar <lijo.lazar@amd.com>
+Reviewed-by: Asad Kamal <asad.kamal@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+index 99d2d3092ea54..3fd8da5dc761e 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+@@ -2772,6 +2772,7 @@ int smu_get_power_limit(void *handle,
+ switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
+ case IP_VERSION(13, 0, 2):
+ case IP_VERSION(13, 0, 6):
++ case IP_VERSION(13, 0, 12):
+ case IP_VERSION(13, 0, 14):
+ case IP_VERSION(11, 0, 7):
+ case IP_VERSION(11, 0, 11):
+--
+2.39.5
+
--- /dev/null
+From b4e1e9652588887c4b4f0b92bbf3181915972488 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Dec 2024 19:16:37 +0800
+Subject: drm/amd/pm: Skip P2S load for SMU v13.0.12
+
+From: Asad Kamal <asad.kamal@amd.com>
+
+[ Upstream commit 1fb85819d629676f1d53f40c3fffa25a33a881e4 ]
+
+Skip P2S table load for SMU v13.0.12
+
+Signed-off-by: Asad Kamal <asad.kamal@amd.com>
+Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
+index 55ed6247eb61f..9ac694c4f1f7a 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
+@@ -275,8 +275,9 @@ static int smu_v13_0_6_init_microcode(struct smu_context *smu)
+ int var = (adev->pdev->device & 0xF);
+ char ucode_prefix[15];
+
+- /* No need to load P2S tables in IOV mode */
+- if (amdgpu_sriov_vf(adev))
++ /* No need to load P2S tables in IOV mode or for smu v13.0.12 */
++ if (amdgpu_sriov_vf(adev) ||
++ (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 12)))
+ return 0;
+
+ if (!(adev->flags & AMD_IS_APU)) {
+--
+2.39.5
+
--- /dev/null
+From 9085aa9327820cfd0b6a3786e922296cf0c5fa03 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Mar 2025 20:52:38 -0400
+Subject: drm/amdgpu: adjust drm_firmware_drivers_only() handling
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+[ Upstream commit e00e5c223878a60e391e5422d173c3382d378f87 ]
+
+Move to probe so we can check the PCI device type and
+only apply the drm_firmware_drivers_only() check for
+PCI DISPLAY classes. Also add a module parameter to
+override the nomodeset kernel parameter as a workaround
+for platforms that have this hardcoded on their kernel
+command lines.
+
+Reviewed-by: Kent Russell <kent.russell@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+index 1b479bd851354..93c3de2d27d3a 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+@@ -172,6 +172,7 @@ uint amdgpu_sdma_phase_quantum = 32;
+ char *amdgpu_disable_cu;
+ char *amdgpu_virtual_display;
+ bool enforce_isolation;
++int amdgpu_modeset = -1;
+
+ /* Specifies the default granularity for SVM, used in buffer
+ * migration and restoration of backing memory when handling
+@@ -1037,6 +1038,13 @@ module_param_named(user_partt_mode, amdgpu_user_partt_mode, uint, 0444);
+ module_param(enforce_isolation, bool, 0444);
+ MODULE_PARM_DESC(enforce_isolation, "enforce process isolation between graphics and compute . enforce_isolation = on");
+
++/**
++ * DOC: modeset (int)
++ * Override nomodeset (1 = override, -1 = auto). The default is -1 (auto).
++ */
++MODULE_PARM_DESC(modeset, "Override nomodeset (1 = enable, -1 = auto)");
++module_param_named(modeset, amdgpu_modeset, int, 0444);
++
+ /**
+ * DOC: seamless (int)
+ * Seamless boot will keep the image on the screen during the boot process.
+@@ -2248,6 +2256,12 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
+ int ret, retry = 0, i;
+ bool supports_atomic = false;
+
++ if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA ||
++ (pdev->class >> 8) == PCI_CLASS_DISPLAY_OTHER) {
++ if (drm_firmware_drivers_only() && amdgpu_modeset == -1)
++ return -EINVAL;
++ }
++
+ /* skip devices which are owned by radeon */
+ for (i = 0; i < ARRAY_SIZE(amdgpu_unsupported_pciidlist); i++) {
+ if (amdgpu_unsupported_pciidlist[i] == pdev->device)
+--
+2.39.5
+
--- /dev/null
+From 90d1ed349a360345076dcb6880f58ce297cac5fd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Apr 2025 00:19:13 -0400
+Subject: drm/amdgpu: Allow P2P access through XGMI
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Felix Kuehling <felix.kuehling@amd.com>
+
+[ Upstream commit a92741e72f91b904c1d8c3d409ed8dbe9c1f2b26 ]
+
+If peer memory is accessible through XGMI, allow leaving it in VRAM
+rather than forcing its migration to GTT on DMABuf attachment.
+
+Signed-off-by: Felix Kuehling <felix.kuehling@amd.com>
+Tested-by: Hao (Claire) Zhou <hao.zhou@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 372c8d72c3680fdea3fbb2d6b089f76b4a6d596a)
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 30 ++++++++++++++++++++-
+ 1 file changed, 29 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+index 2f90fff1b9ddc..e63a32c214475 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+@@ -42,6 +42,29 @@
+ #include <linux/dma-fence-array.h>
+ #include <linux/pci-p2pdma.h>
+
++static const struct dma_buf_attach_ops amdgpu_dma_buf_attach_ops;
++
++/**
++ * dma_buf_attach_adev - Helper to get adev of an attachment
++ *
++ * @attach: attachment
++ *
++ * Returns:
++ * A struct amdgpu_device * if the attaching device is an amdgpu device or
++ * partition, NULL otherwise.
++ */
++static struct amdgpu_device *dma_buf_attach_adev(struct dma_buf_attachment *attach)
++{
++ if (attach->importer_ops == &amdgpu_dma_buf_attach_ops) {
++ struct drm_gem_object *obj = attach->importer_priv;
++ struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
++
++ return amdgpu_ttm_adev(bo->tbo.bdev);
++ }
++
++ return NULL;
++}
++
+ /**
+ * amdgpu_dma_buf_attach - &dma_buf_ops.attach implementation
+ *
+@@ -53,11 +76,13 @@
+ static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
+ struct dma_buf_attachment *attach)
+ {
++ struct amdgpu_device *attach_adev = dma_buf_attach_adev(attach);
+ struct drm_gem_object *obj = dmabuf->priv;
+ struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
+
+- if (pci_p2pdma_distance(adev->pdev, attach->dev, false) < 0)
++ if (!amdgpu_dmabuf_is_xgmi_accessible(attach_adev, bo) &&
++ pci_p2pdma_distance(adev->pdev, attach->dev, false) < 0)
+ attach->peer2peer = false;
+
+ return 0;
+@@ -456,6 +481,9 @@ bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev,
+ struct drm_gem_object *obj = &bo->tbo.base;
+ struct drm_gem_object *gobj;
+
++ if (!adev)
++ return false;
++
+ if (obj->import_attach) {
+ struct dma_buf *dma_buf = obj->import_attach->dmabuf;
+
+--
+2.39.5
+
--- /dev/null
+From 0dd177485a88232fbee4f7852267030716e167d0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Feb 2025 10:39:27 +0800
+Subject: drm/amdgpu/discovery: check ip_discovery fw file available
+
+From: Flora Cui <flora.cui@amd.com>
+
+[ Upstream commit 017fbb6690c2245b1b4ef39b66c79d2990fe63dd ]
+
+Signed-off-by: Flora Cui <flora.cui@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 31 ++++++++++---------
+ 1 file changed, 16 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+index ca8091fd3a24f..018240a2ab96a 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+@@ -111,8 +111,7 @@
+ #include "amdgpu_isp.h"
+ #endif
+
+-#define FIRMWARE_IP_DISCOVERY "amdgpu/ip_discovery.bin"
+-MODULE_FIRMWARE(FIRMWARE_IP_DISCOVERY);
++MODULE_FIRMWARE("amdgpu/ip_discovery.bin");
+
+ #define mmIP_DISCOVERY_VERSION 0x16A00
+ #define mmRCC_CONFIG_MEMSIZE 0xde3
+@@ -295,21 +294,13 @@ static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev,
+ return ret;
+ }
+
+-static int amdgpu_discovery_read_binary_from_file(struct amdgpu_device *adev, uint8_t *binary)
++static int amdgpu_discovery_read_binary_from_file(struct amdgpu_device *adev,
++ uint8_t *binary,
++ const char *fw_name)
+ {
+ const struct firmware *fw;
+- const char *fw_name;
+ int r;
+
+- switch (amdgpu_discovery) {
+- case 2:
+- fw_name = FIRMWARE_IP_DISCOVERY;
+- break;
+- default:
+- dev_warn(adev->dev, "amdgpu_discovery is not set properly\n");
+- return -EINVAL;
+- }
+-
+ r = request_firmware(&fw, fw_name, adev->dev);
+ if (r) {
+ dev_err(adev->dev, "can't load firmware \"%s\"\n",
+@@ -402,10 +393,19 @@ static int amdgpu_discovery_verify_npsinfo(struct amdgpu_device *adev,
+ return 0;
+ }
+
++static const char *amdgpu_discovery_get_fw_name(struct amdgpu_device *adev)
++{
++ if (amdgpu_discovery == 2)
++ return "amdgpu/ip_discovery.bin";
++
++ return NULL;
++}
++
+ static int amdgpu_discovery_init(struct amdgpu_device *adev)
+ {
+ struct table_info *info;
+ struct binary_header *bhdr;
++ const char *fw_name;
+ uint16_t offset;
+ uint16_t size;
+ uint16_t checksum;
+@@ -417,9 +417,10 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
+ return -ENOMEM;
+
+ /* Read from file if it is the preferred option */
+- if (amdgpu_discovery == 2) {
++ fw_name = amdgpu_discovery_get_fw_name(adev);
++ if (fw_name != NULL) {
+ dev_info(adev->dev, "use ip discovery information from file");
+- r = amdgpu_discovery_read_binary_from_file(adev, adev->mman.discovery_bin);
++ r = amdgpu_discovery_read_binary_from_file(adev, adev->mman.discovery_bin, fw_name);
+
+ if (r) {
+ dev_err(adev->dev, "failed to read ip discovery binary from file\n");
+--
+2.39.5
+
--- /dev/null
+From 46551ff428662e5b910fb7528f97fe1bc637fb6a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 18:38:28 -0500
+Subject: drm/amdgpu: Do not program AGP BAR regs under SRIOV in gfxhub_v1_0.c
+
+From: Victor Lu <victorchengchi.lu@amd.com>
+
+[ Upstream commit 057fef20b8401110a7bc1c2fe9d804a8a0bf0d24 ]
+
+SRIOV VF does not have write access to AGP BAR regs.
+Skip the writes to avoid a dmesg warning.
+
+Signed-off-by: Victor Lu <victorchengchi.lu@amd.com>
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c
+index 0e3ddea7b8e0f..a7bfc9f41d0e3 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c
+@@ -92,12 +92,12 @@ static void gfxhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev)
+ {
+ uint64_t value;
+
+- /* Program the AGP BAR */
+- WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BASE, 0);
+- WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BOT, adev->gmc.agp_start >> 24);
+- WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_TOP, adev->gmc.agp_end >> 24);
+-
+ if (!amdgpu_sriov_vf(adev) || adev->asic_type <= CHIP_VEGA10) {
++ /* Program the AGP BAR */
++ WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BASE, 0);
++ WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BOT, adev->gmc.agp_start >> 24);
++ WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_TOP, adev->gmc.agp_end >> 24);
++
+ /* Program the system aperture low logical page number. */
+ WREG32_SOC15_RLC(GC, 0, mmMC_VM_SYSTEM_APERTURE_LOW_ADDR,
+ min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);
+--
+2.39.5
+
--- /dev/null
+From 23b64bba5d08a57a61b3bded0e0536afd8d3fdc5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Nov 2024 15:58:39 +0800
+Subject: drm/amdgpu: enlarge the VBIOS binary size limit
+
+From: Shiwu Zhang <shiwu.zhang@amd.com>
+
+[ Upstream commit 667b96134c9e206aebe40985650bf478935cbe04 ]
+
+Some chips have a larger VBIOS file so raise the size limit to support
+the flashing tool.
+
+Signed-off-by: Shiwu Zhang <shiwu.zhang@amd.com>
+Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+index 31a376f2742a2..48e30e5f83389 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+@@ -44,7 +44,7 @@
+ #include "amdgpu_securedisplay.h"
+ #include "amdgpu_atomfirmware.h"
+
+-#define AMD_VBIOS_FILE_MAX_SIZE_B (1024*1024*3)
++#define AMD_VBIOS_FILE_MAX_SIZE_B (1024*1024*16)
+
+ static int psp_load_smu_fw(struct psp_context *psp);
+ static int psp_rap_terminate(struct psp_context *psp);
+--
+2.39.5
+
--- /dev/null
+From c39e82136173f72caa0ef67bf71ba67aa5f8dc8b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Mar 2025 15:10:22 +0800
+Subject: drm/amdgpu: Fix missing drain retry fault the last entry
+
+From: Emily Deng <Emily.Deng@amd.com>
+
+[ Upstream commit fe2fa3be3d59ba67d6de54a0064441ec233cb50c ]
+
+While the entry get in svm_range_unmap_from_cpu is the last entry, and
+the entry is page fault, it also need to be dropped. So for equal case,
+it also need to be dropped.
+
+v2:
+Only modify the svm_range_restore_pages.
+
+Signed-off-by: Emily Deng <Emily.Deng@amd.com>
+Reviewed-by: Xiaogang Chen<xiaogang.chen@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h | 3 +++
+ drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 2 +-
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
+index 508f02eb0cf8f..7de10208e8dde 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
+@@ -78,6 +78,9 @@ struct amdgpu_ih_ring {
+ #define amdgpu_ih_ts_after(t1, t2) \
+ (((int64_t)((t2) << 16) - (int64_t)((t1) << 16)) > 0LL)
+
++#define amdgpu_ih_ts_after_or_equal(t1, t2) \
++ (((int64_t)((t2) << 16) - (int64_t)((t1) << 16)) >= 0LL)
++
+ /* provided by the ih block */
+ struct amdgpu_ih_funcs {
+ /* ring read/write ptr handling, called from interrupt context */
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+index b50283864dcd2..f00d41be7fca2 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+@@ -3014,7 +3014,7 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
+
+ /* check if this page fault time stamp is before svms->checkpoint_ts */
+ if (svms->checkpoint_ts[gpuidx] != 0) {
+- if (amdgpu_ih_ts_after(ts, svms->checkpoint_ts[gpuidx])) {
++ if (amdgpu_ih_ts_after_or_equal(ts, svms->checkpoint_ts[gpuidx])) {
+ pr_debug("draining retry fault, drop fault 0x%llx\n", addr);
+ r = -EAGAIN;
+ goto out_unlock_svms;
+--
+2.39.5
+
--- /dev/null
+From ab97d73375289196975ff9d7c7af9c59152151ec Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Feb 2025 15:55:33 -0500
+Subject: drm/amdgpu/gfx11: don't read registers in mqd init
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+[ Upstream commit e27b36ea6ba5f29e91fcfb375ea29503708fcf43 ]
+
+Just use the default values. There's not need to
+get the value from hardware and it could cause problems
+if we do that at runtime and gfxoff is active.
+
+Reviewed-by: Mukul Joshi <mukul.joshi@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 47 ++++++++++++++++++--------
+ 1 file changed, 32 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+index 0357fea8ae1df..1f06b22dbe7c6 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+@@ -63,6 +63,23 @@
+ #define regPC_CONFIG_CNTL_1 0x194d
+ #define regPC_CONFIG_CNTL_1_BASE_IDX 1
+
++#define regCP_GFX_MQD_CONTROL_DEFAULT 0x00000100
++#define regCP_GFX_HQD_VMID_DEFAULT 0x00000000
++#define regCP_GFX_HQD_QUEUE_PRIORITY_DEFAULT 0x00000000
++#define regCP_GFX_HQD_QUANTUM_DEFAULT 0x00000a01
++#define regCP_GFX_HQD_CNTL_DEFAULT 0x00a00000
++#define regCP_RB_DOORBELL_CONTROL_DEFAULT 0x00000000
++#define regCP_GFX_HQD_RPTR_DEFAULT 0x00000000
++
++#define regCP_HQD_EOP_CONTROL_DEFAULT 0x00000006
++#define regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT 0x00000000
++#define regCP_MQD_CONTROL_DEFAULT 0x00000100
++#define regCP_HQD_PQ_CONTROL_DEFAULT 0x00308509
++#define regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT 0x00000000
++#define regCP_HQD_PQ_RPTR_DEFAULT 0x00000000
++#define regCP_HQD_PERSISTENT_STATE_DEFAULT 0x0be05501
++#define regCP_HQD_IB_CONTROL_DEFAULT 0x00300000
++
+ MODULE_FIRMWARE("amdgpu/gc_11_0_0_pfp.bin");
+ MODULE_FIRMWARE("amdgpu/gc_11_0_0_me.bin");
+ MODULE_FIRMWARE("amdgpu/gc_11_0_0_mec.bin");
+@@ -3896,7 +3913,7 @@ static void gfx_v11_0_gfx_mqd_set_priority(struct amdgpu_device *adev,
+ if (prop->hqd_pipe_priority == AMDGPU_GFX_PIPE_PRIO_HIGH)
+ priority = 1;
+
+- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_QUEUE_PRIORITY);
++ tmp = regCP_GFX_HQD_QUEUE_PRIORITY_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_QUEUE_PRIORITY, PRIORITY_LEVEL, priority);
+ mqd->cp_gfx_hqd_queue_priority = tmp;
+ }
+@@ -3918,14 +3935,14 @@ static int gfx_v11_0_gfx_mqd_init(struct amdgpu_device *adev, void *m,
+ mqd->cp_mqd_base_addr_hi = upper_32_bits(prop->mqd_gpu_addr);
+
+ /* set up mqd control */
+- tmp = RREG32_SOC15(GC, 0, regCP_GFX_MQD_CONTROL);
++ tmp = regCP_GFX_MQD_CONTROL_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_GFX_MQD_CONTROL, VMID, 0);
+ tmp = REG_SET_FIELD(tmp, CP_GFX_MQD_CONTROL, PRIV_STATE, 1);
+ tmp = REG_SET_FIELD(tmp, CP_GFX_MQD_CONTROL, CACHE_POLICY, 0);
+ mqd->cp_gfx_mqd_control = tmp;
+
+ /* set up gfx_hqd_vimd with 0x0 to indicate the ring buffer's vmid */
+- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_VMID);
++ tmp = regCP_GFX_HQD_VMID_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_VMID, VMID, 0);
+ mqd->cp_gfx_hqd_vmid = 0;
+
+@@ -3933,7 +3950,7 @@ static int gfx_v11_0_gfx_mqd_init(struct amdgpu_device *adev, void *m,
+ gfx_v11_0_gfx_mqd_set_priority(adev, mqd, prop);
+
+ /* set up time quantum */
+- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_QUANTUM);
++ tmp = regCP_GFX_HQD_QUANTUM_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_QUANTUM, QUANTUM_EN, 1);
+ mqd->cp_gfx_hqd_quantum = tmp;
+
+@@ -3955,7 +3972,7 @@ static int gfx_v11_0_gfx_mqd_init(struct amdgpu_device *adev, void *m,
+
+ /* set up the gfx_hqd_control, similar as CP_RB0_CNTL */
+ rb_bufsz = order_base_2(prop->queue_size / 4) - 1;
+- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_CNTL);
++ tmp = regCP_GFX_HQD_CNTL_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, RB_BUFSZ, rb_bufsz);
+ tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, RB_BLKSZ, rb_bufsz - 2);
+ #ifdef __BIG_ENDIAN
+@@ -3964,7 +3981,7 @@ static int gfx_v11_0_gfx_mqd_init(struct amdgpu_device *adev, void *m,
+ mqd->cp_gfx_hqd_cntl = tmp;
+
+ /* set up cp_doorbell_control */
+- tmp = RREG32_SOC15(GC, 0, regCP_RB_DOORBELL_CONTROL);
++ tmp = regCP_RB_DOORBELL_CONTROL_DEFAULT;
+ if (prop->use_doorbell) {
+ tmp = REG_SET_FIELD(tmp, CP_RB_DOORBELL_CONTROL,
+ DOORBELL_OFFSET, prop->doorbell_index);
+@@ -3976,7 +3993,7 @@ static int gfx_v11_0_gfx_mqd_init(struct amdgpu_device *adev, void *m,
+ mqd->cp_rb_doorbell_control = tmp;
+
+ /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
+- mqd->cp_gfx_hqd_rptr = RREG32_SOC15(GC, 0, regCP_GFX_HQD_RPTR);
++ mqd->cp_gfx_hqd_rptr = regCP_GFX_HQD_RPTR_DEFAULT;
+
+ /* active the queue */
+ mqd->cp_gfx_hqd_active = 1;
+@@ -4062,14 +4079,14 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
+ mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr);
+
+ /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
+- tmp = RREG32_SOC15(GC, 0, regCP_HQD_EOP_CONTROL);
++ tmp = regCP_HQD_EOP_CONTROL_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE,
+ (order_base_2(GFX11_MEC_HPD_SIZE / 4) - 1));
+
+ mqd->cp_hqd_eop_control = tmp;
+
+ /* enable doorbell? */
+- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL);
++ tmp = regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT;
+
+ if (prop->use_doorbell) {
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+@@ -4098,7 +4115,7 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
+ mqd->cp_mqd_base_addr_hi = upper_32_bits(prop->mqd_gpu_addr);
+
+ /* set MQD vmid to 0 */
+- tmp = RREG32_SOC15(GC, 0, regCP_MQD_CONTROL);
++ tmp = regCP_MQD_CONTROL_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_MQD_CONTROL, VMID, 0);
+ mqd->cp_mqd_control = tmp;
+
+@@ -4108,7 +4125,7 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
+ mqd->cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr);
+
+ /* set up the HQD, this is similar to CP_RB0_CNTL */
+- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PQ_CONTROL);
++ tmp = regCP_HQD_PQ_CONTROL_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, QUEUE_SIZE,
+ (order_base_2(prop->queue_size / 4) - 1));
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE,
+@@ -4134,7 +4151,7 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
+ tmp = 0;
+ /* enable the doorbell if requested */
+ if (prop->use_doorbell) {
+- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL);
++ tmp = regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+ DOORBELL_OFFSET, prop->doorbell_index);
+
+@@ -4149,17 +4166,17 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
+ mqd->cp_hqd_pq_doorbell_control = tmp;
+
+ /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
+- mqd->cp_hqd_pq_rptr = RREG32_SOC15(GC, 0, regCP_HQD_PQ_RPTR);
++ mqd->cp_hqd_pq_rptr = regCP_HQD_PQ_RPTR_DEFAULT;
+
+ /* set the vmid for the queue */
+ mqd->cp_hqd_vmid = 0;
+
+- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PERSISTENT_STATE);
++ tmp = regCP_HQD_PERSISTENT_STATE_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x55);
+ mqd->cp_hqd_persistent_state = tmp;
+
+ /* set MIN_IB_AVAIL_SIZE */
+- tmp = RREG32_SOC15(GC, 0, regCP_HQD_IB_CONTROL);
++ tmp = regCP_HQD_IB_CONTROL_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_HQD_IB_CONTROL, MIN_IB_AVAIL_SIZE, 3);
+ mqd->cp_hqd_ib_control = tmp;
+
+--
+2.39.5
+
--- /dev/null
+From bc1b6e91b1c039f7204b4d31561b769162c6f288 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Feb 2025 16:08:03 -0500
+Subject: drm/amdgpu/gfx12: don't read registers in mqd init
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+[ Upstream commit fc3c139cf0432b79fd08e23100a559ee51cd0be4 ]
+
+Just use the default values. There's not need to
+get the value from hardware and it could cause problems
+if we do that at runtime and gfxoff is active.
+
+Reviewed-by: Mukul Joshi <mukul.joshi@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 48 ++++++++++++++++++--------
+ 1 file changed, 33 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+index 241619ee10e4b..adcfcf594286f 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+@@ -52,6 +52,24 @@
+
+ #define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L
+
++#define regCP_GFX_MQD_CONTROL_DEFAULT 0x00000100
++#define regCP_GFX_HQD_VMID_DEFAULT 0x00000000
++#define regCP_GFX_HQD_QUEUE_PRIORITY_DEFAULT 0x00000000
++#define regCP_GFX_HQD_QUANTUM_DEFAULT 0x00000a01
++#define regCP_GFX_HQD_CNTL_DEFAULT 0x00f00000
++#define regCP_RB_DOORBELL_CONTROL_DEFAULT 0x00000000
++#define regCP_GFX_HQD_RPTR_DEFAULT 0x00000000
++
++#define regCP_HQD_EOP_CONTROL_DEFAULT 0x00000006
++#define regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT 0x00000000
++#define regCP_MQD_CONTROL_DEFAULT 0x00000100
++#define regCP_HQD_PQ_CONTROL_DEFAULT 0x00308509
++#define regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT 0x00000000
++#define regCP_HQD_PQ_RPTR_DEFAULT 0x00000000
++#define regCP_HQD_PERSISTENT_STATE_DEFAULT 0x0be05501
++#define regCP_HQD_IB_CONTROL_DEFAULT 0x00300000
++
++
+ MODULE_FIRMWARE("amdgpu/gc_12_0_0_pfp.bin");
+ MODULE_FIRMWARE("amdgpu/gc_12_0_0_me.bin");
+ MODULE_FIRMWARE("amdgpu/gc_12_0_0_mec.bin");
+@@ -2851,25 +2869,25 @@ static int gfx_v12_0_gfx_mqd_init(struct amdgpu_device *adev, void *m,
+ mqd->cp_mqd_base_addr_hi = upper_32_bits(prop->mqd_gpu_addr);
+
+ /* set up mqd control */
+- tmp = RREG32_SOC15(GC, 0, regCP_GFX_MQD_CONTROL);
++ tmp = regCP_GFX_MQD_CONTROL_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_GFX_MQD_CONTROL, VMID, 0);
+ tmp = REG_SET_FIELD(tmp, CP_GFX_MQD_CONTROL, PRIV_STATE, 1);
+ tmp = REG_SET_FIELD(tmp, CP_GFX_MQD_CONTROL, CACHE_POLICY, 0);
+ mqd->cp_gfx_mqd_control = tmp;
+
+ /* set up gfx_hqd_vimd with 0x0 to indicate the ring buffer's vmid */
+- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_VMID);
++ tmp = regCP_GFX_HQD_VMID_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_VMID, VMID, 0);
+ mqd->cp_gfx_hqd_vmid = 0;
+
+ /* set up default queue priority level
+ * 0x0 = low priority, 0x1 = high priority */
+- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_QUEUE_PRIORITY);
++ tmp = regCP_GFX_HQD_QUEUE_PRIORITY_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_QUEUE_PRIORITY, PRIORITY_LEVEL, 0);
+ mqd->cp_gfx_hqd_queue_priority = tmp;
+
+ /* set up time quantum */
+- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_QUANTUM);
++ tmp = regCP_GFX_HQD_QUANTUM_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_QUANTUM, QUANTUM_EN, 1);
+ mqd->cp_gfx_hqd_quantum = tmp;
+
+@@ -2891,7 +2909,7 @@ static int gfx_v12_0_gfx_mqd_init(struct amdgpu_device *adev, void *m,
+
+ /* set up the gfx_hqd_control, similar as CP_RB0_CNTL */
+ rb_bufsz = order_base_2(prop->queue_size / 4) - 1;
+- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_CNTL);
++ tmp = regCP_GFX_HQD_CNTL_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, RB_BUFSZ, rb_bufsz);
+ tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, RB_BLKSZ, rb_bufsz - 2);
+ #ifdef __BIG_ENDIAN
+@@ -2900,7 +2918,7 @@ static int gfx_v12_0_gfx_mqd_init(struct amdgpu_device *adev, void *m,
+ mqd->cp_gfx_hqd_cntl = tmp;
+
+ /* set up cp_doorbell_control */
+- tmp = RREG32_SOC15(GC, 0, regCP_RB_DOORBELL_CONTROL);
++ tmp = regCP_RB_DOORBELL_CONTROL_DEFAULT;
+ if (prop->use_doorbell) {
+ tmp = REG_SET_FIELD(tmp, CP_RB_DOORBELL_CONTROL,
+ DOORBELL_OFFSET, prop->doorbell_index);
+@@ -2912,7 +2930,7 @@ static int gfx_v12_0_gfx_mqd_init(struct amdgpu_device *adev, void *m,
+ mqd->cp_rb_doorbell_control = tmp;
+
+ /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
+- mqd->cp_gfx_hqd_rptr = RREG32_SOC15(GC, 0, regCP_GFX_HQD_RPTR);
++ mqd->cp_gfx_hqd_rptr = regCP_GFX_HQD_RPTR_DEFAULT;
+
+ /* active the queue */
+ mqd->cp_gfx_hqd_active = 1;
+@@ -3007,14 +3025,14 @@ static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
+ mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr);
+
+ /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
+- tmp = RREG32_SOC15(GC, 0, regCP_HQD_EOP_CONTROL);
++ tmp = regCP_HQD_EOP_CONTROL_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE,
+ (order_base_2(GFX12_MEC_HPD_SIZE / 4) - 1));
+
+ mqd->cp_hqd_eop_control = tmp;
+
+ /* enable doorbell? */
+- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL);
++ tmp = regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT;
+
+ if (prop->use_doorbell) {
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+@@ -3043,7 +3061,7 @@ static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
+ mqd->cp_mqd_base_addr_hi = upper_32_bits(prop->mqd_gpu_addr);
+
+ /* set MQD vmid to 0 */
+- tmp = RREG32_SOC15(GC, 0, regCP_MQD_CONTROL);
++ tmp = regCP_MQD_CONTROL_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_MQD_CONTROL, VMID, 0);
+ mqd->cp_mqd_control = tmp;
+
+@@ -3053,7 +3071,7 @@ static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
+ mqd->cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr);
+
+ /* set up the HQD, this is similar to CP_RB0_CNTL */
+- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PQ_CONTROL);
++ tmp = regCP_HQD_PQ_CONTROL_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, QUEUE_SIZE,
+ (order_base_2(prop->queue_size / 4) - 1));
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE,
+@@ -3078,7 +3096,7 @@ static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
+ tmp = 0;
+ /* enable the doorbell if requested */
+ if (prop->use_doorbell) {
+- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL);
++ tmp = regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+ DOORBELL_OFFSET, prop->doorbell_index);
+
+@@ -3093,17 +3111,17 @@ static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
+ mqd->cp_hqd_pq_doorbell_control = tmp;
+
+ /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
+- mqd->cp_hqd_pq_rptr = RREG32_SOC15(GC, 0, regCP_HQD_PQ_RPTR);
++ mqd->cp_hqd_pq_rptr = regCP_HQD_PQ_RPTR_DEFAULT;
+
+ /* set the vmid for the queue */
+ mqd->cp_hqd_vmid = 0;
+
+- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PERSISTENT_STATE);
++ tmp = regCP_HQD_PERSISTENT_STATE_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x55);
+ mqd->cp_hqd_persistent_state = tmp;
+
+ /* set MIN_IB_AVAIL_SIZE */
+- tmp = RREG32_SOC15(GC, 0, regCP_HQD_IB_CONTROL);
++ tmp = regCP_HQD_IB_CONTROL_DEFAULT;
+ tmp = REG_SET_FIELD(tmp, CP_HQD_IB_CONTROL, MIN_IB_AVAIL_SIZE, 3);
+ mqd->cp_hqd_ib_control = tmp;
+
+--
+2.39.5
+
--- /dev/null
+From 054fe174f049544d13d659da22274b9ec636d524 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Feb 2025 09:39:24 -0500
+Subject: drm/amdgpu/mes11: fix set_hw_resources_1 calculation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+[ Upstream commit 1350dd3691b5f757a948e5b9895d62c422baeb90 ]
+
+It's GPU page size not CPU page size. In most cases they
+are the same, but not always. This can lead to overallocation
+on systems with larger pages.
+
+Cc: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Cc: Christian König <christian.koenig@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+index 7a773fcd7752c..49113df8baefd 100644
+--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+@@ -690,7 +690,7 @@ static int mes_v11_0_set_hw_resources(struct amdgpu_mes *mes)
+
+ static int mes_v11_0_set_hw_resources_1(struct amdgpu_mes *mes)
+ {
+- int size = 128 * PAGE_SIZE;
++ int size = 128 * AMDGPU_GPU_PAGE_SIZE;
+ int ret = 0;
+ struct amdgpu_device *adev = mes->adev;
+ union MESAPI_SET_HW_RESOURCES_1 mes_set_hw_res_pkt;
+--
+2.39.5
+
--- /dev/null
+From c602050350944d1d50d35a41fa5c934b29d81286 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Mar 2025 10:27:55 +0800
+Subject: drm/amdgpu: release xcp_mgr on exit
+
+From: Flora Cui <flora.cui@amd.com>
+
+[ Upstream commit b5aaa82e2b12feaaa6958f7fa0917ddcc03c24ee ]
+
+Free on driver cleanup.
+
+Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
+Signed-off-by: Flora Cui <flora.cui@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+index 081c0e45779fc..ca0411c9500e7 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -4677,6 +4677,9 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
+ kfree(adev->fru_info);
+ adev->fru_info = NULL;
+
++ kfree(adev->xcp_mgr);
++ adev->xcp_mgr = NULL;
++
+ px = amdgpu_device_supports_px(adev_to_drm(adev));
+
+ if (px || (!dev_is_removable(&adev->pdev->dev) &&
+--
+2.39.5
+
--- /dev/null
+From 2857551c382f998f422dd88599e853aa6460a338 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jan 2025 16:28:49 +0100
+Subject: drm/amdgpu: remove all KFD fences from the BO on release
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Christian König <christian.koenig@amd.com>
+
+[ Upstream commit cb0de06d1b0afb2d0c600ad748069f5ce27730ec ]
+
+Remove all KFD BOs from the private dma_resv object.
+
+This prevents the KFD from being evict unecessarily when an exported BO
+is released.
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: James Zhu <James.Zhu@amd.com>
+Reviewed-by: Felix Kuehling <felix.kuehling@amd.com>
+Reviewed-and-tested-by: James Zhu <James.Zhu@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 5 +-
+ .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 52 ++++++++-----------
+ drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 38 ++++++++------
+ 3 files changed, 47 insertions(+), 48 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+index f9d1194484423..581fe1a48f376 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+@@ -192,7 +192,7 @@ int kfd_debugfs_kfd_mem_limits(struct seq_file *m, void *data);
+ #if IS_ENABLED(CONFIG_HSA_AMD)
+ bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm);
+ struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f);
+-int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo);
++void amdgpu_amdkfd_remove_all_eviction_fences(struct amdgpu_bo *bo);
+ int amdgpu_amdkfd_evict_userptr(struct mmu_interval_notifier *mni,
+ unsigned long cur_seq, struct kgd_mem *mem);
+ int amdgpu_amdkfd_bo_validate_and_fence(struct amdgpu_bo *bo,
+@@ -212,9 +212,8 @@ struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f)
+ }
+
+ static inline
+-int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo)
++void amdgpu_amdkfd_remove_all_eviction_fences(struct amdgpu_bo *bo)
+ {
+- return 0;
+ }
+
+ static inline
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+index fa572ba7f9fc1..1465b3adacb0a 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+@@ -370,40 +370,32 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo,
+ return 0;
+ }
+
+-int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo)
++/**
++ * amdgpu_amdkfd_remove_all_eviction_fences - Remove all eviction fences
++ * @bo: the BO where to remove the evictions fences from.
++ *
++ * This functions should only be used on release when all references to the BO
++ * are already dropped. We remove the eviction fence from the private copy of
++ * the dma_resv object here since that is what is used during release to
++ * determine of the BO is idle or not.
++ */
++void amdgpu_amdkfd_remove_all_eviction_fences(struct amdgpu_bo *bo)
+ {
+- struct amdgpu_bo *root = bo;
+- struct amdgpu_vm_bo_base *vm_bo;
+- struct amdgpu_vm *vm;
+- struct amdkfd_process_info *info;
+- struct amdgpu_amdkfd_fence *ef;
+- int ret;
+-
+- /* we can always get vm_bo from root PD bo.*/
+- while (root->parent)
+- root = root->parent;
++ struct dma_resv *resv = &bo->tbo.base._resv;
++ struct dma_fence *fence, *stub;
++ struct dma_resv_iter cursor;
+
+- vm_bo = root->vm_bo;
+- if (!vm_bo)
+- return 0;
++ dma_resv_assert_held(resv);
+
+- vm = vm_bo->vm;
+- if (!vm)
+- return 0;
+-
+- info = vm->process_info;
+- if (!info || !info->eviction_fence)
+- return 0;
+-
+- ef = container_of(dma_fence_get(&info->eviction_fence->base),
+- struct amdgpu_amdkfd_fence, base);
+-
+- BUG_ON(!dma_resv_trylock(bo->tbo.base.resv));
+- ret = amdgpu_amdkfd_remove_eviction_fence(bo, ef);
+- dma_resv_unlock(bo->tbo.base.resv);
++ stub = dma_fence_get_stub();
++ dma_resv_for_each_fence(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP, fence) {
++ if (!to_amdgpu_amdkfd_fence(fence))
++ continue;
+
+- dma_fence_put(&ef->base);
+- return ret;
++ dma_resv_replace_fences(resv, fence->context, stub,
++ DMA_RESV_USAGE_BOOKKEEP);
++ }
++ dma_fence_put(stub);
+ }
+
+ static int amdgpu_amdkfd_bo_validate(struct amdgpu_bo *bo, uint32_t domain,
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+index 4c4bdc4f51b29..fc588ef598c09 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+@@ -1246,28 +1246,36 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo)
+ if (abo->kfd_bo)
+ amdgpu_amdkfd_release_notify(abo);
+
+- /* We only remove the fence if the resv has individualized. */
+- WARN_ON_ONCE(bo->type == ttm_bo_type_kernel
+- && bo->base.resv != &bo->base._resv);
+- if (bo->base.resv == &bo->base._resv)
+- amdgpu_amdkfd_remove_fence_on_pt_pd_bos(abo);
++ /*
++ * We lock the private dma_resv object here and since the BO is about to
++ * be released nobody else should have a pointer to it.
++ * So when this locking here fails something is wrong with the reference
++ * counting.
++ */
++ if (WARN_ON_ONCE(!dma_resv_trylock(&bo->base._resv)))
++ return;
++
++ amdgpu_amdkfd_remove_all_eviction_fences(abo);
+
+ if (!bo->resource || bo->resource->mem_type != TTM_PL_VRAM ||
+ !(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE) ||
+ adev->in_suspend || drm_dev_is_unplugged(adev_to_drm(adev)))
+- return;
++ goto out;
+
+- if (WARN_ON_ONCE(!dma_resv_trylock(bo->base.resv)))
+- return;
++ r = dma_resv_reserve_fences(&bo->base._resv, 1);
++ if (r)
++ goto out;
+
+- r = amdgpu_fill_buffer(abo, 0, bo->base.resv, &fence, true);
+- if (!WARN_ON(r)) {
+- amdgpu_vram_mgr_set_cleared(bo->resource);
+- amdgpu_bo_fence(abo, fence, false);
+- dma_fence_put(fence);
+- }
++ r = amdgpu_fill_buffer(abo, 0, &bo->base._resv, &fence, true);
++ if (WARN_ON(r))
++ goto out;
++
++ amdgpu_vram_mgr_set_cleared(bo->resource);
++ dma_resv_add_fence(&bo->base._resv, fence, DMA_RESV_USAGE_KERNEL);
++ dma_fence_put(fence);
+
+- dma_resv_unlock(bo->base.resv);
++out:
++ dma_resv_unlock(&bo->base._resv);
+ }
+
+ /**
+--
+2.39.5
+
--- /dev/null
+From f1a9ee5a1dc5ba4691bcbe1facbccf3646a2d4b0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Feb 2025 14:28:49 +0800
+Subject: drm/amdgpu: reset psp->cmd to NULL after releasing the buffer
+
+From: Jiang Liu <gerry@linux.alibaba.com>
+
+[ Upstream commit e92f3f94cad24154fd3baae30c6dfb918492278d ]
+
+Reset psp->cmd to NULL after releasing the buffer in function psp_sw_fini().
+
+Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
+Signed-off-by: Jiang Liu <gerry@linux.alibaba.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+index d70855d7c61c1..31a376f2742a2 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+@@ -531,7 +531,6 @@ static int psp_sw_fini(void *handle)
+ {
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct psp_context *psp = &adev->psp;
+- struct psp_gfx_cmd_resp *cmd = psp->cmd;
+
+ psp_memory_training_fini(psp);
+
+@@ -541,8 +540,8 @@ static int psp_sw_fini(void *handle)
+ amdgpu_ucode_release(&psp->cap_fw);
+ amdgpu_ucode_release(&psp->toc_fw);
+
+- kfree(cmd);
+- cmd = NULL;
++ kfree(psp->cmd);
++ psp->cmd = NULL;
+
+ psp_free_shared_bufs(psp);
+
+--
+2.39.5
+
--- /dev/null
+From 6beea77658fda7e59e462ff26b55334d375b1d9c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Feb 2025 17:57:47 -0500
+Subject: drm/amdgpu: Set snoop bit for SDMA for MI series
+
+From: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
+
+[ Upstream commit 3394b1f76d3f8adf695ceed350a5dae49003eb37 ]
+
+SDMA writes has to probe invalidate RW lines. Set snoop bit in mmhub for
+this to happen.
+
+v2: Missed a few mmhub_v9_4. Added now.
+v3: Calculate hub offset once since it doesn't change inside the loop
+ Modified function names based on review comments.
+
+Signed-off-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
+Reviewed-by: Philip Yang <Philip.Yang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c | 25 ++++++++++
+ drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c | 27 +++++++++++
+ drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c | 31 ++++++++++++
+ .../asic_reg/mmhub/mmhub_9_4_1_offset.h | 32 +++++++++++++
+ .../asic_reg/mmhub/mmhub_9_4_1_sh_mask.h | 48 +++++++++++++++++++
+ 5 files changed, 163 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c
+index 9689e2b5d4e51..2adee2b94c37d 100644
+--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c
++++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c
+@@ -172,6 +172,30 @@ static void mmhub_v1_7_init_tlb_regs(struct amdgpu_device *adev)
+ WREG32_SOC15(MMHUB, 0, regMC_VM_MX_L1_TLB_CNTL, tmp);
+ }
+
++/* Set snoop bit for SDMA so that SDMA writes probe-invalidates RW lines */
++static void mmhub_v1_7_init_snoop_override_regs(struct amdgpu_device *adev)
++{
++ uint32_t tmp;
++ int i;
++ uint32_t distance = regDAGB1_WRCLI_GPU_SNOOP_OVERRIDE -
++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE;
++
++ for (i = 0; i < 5; i++) { /* DAGB instances */
++ tmp = RREG32_SOC15_OFFSET(MMHUB, 0,
++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE, i * distance);
++ tmp |= (1 << 15); /* SDMA client is BIT15 */
++ WREG32_SOC15_OFFSET(MMHUB, 0,
++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE, i * distance, tmp);
++
++ tmp = RREG32_SOC15_OFFSET(MMHUB, 0,
++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE, i * distance);
++ tmp |= (1 << 15);
++ WREG32_SOC15_OFFSET(MMHUB, 0,
++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE, i * distance, tmp);
++ }
++
++}
++
+ static void mmhub_v1_7_init_cache_regs(struct amdgpu_device *adev)
+ {
+ uint32_t tmp;
+@@ -337,6 +361,7 @@ static int mmhub_v1_7_gart_enable(struct amdgpu_device *adev)
+ mmhub_v1_7_init_system_aperture_regs(adev);
+ mmhub_v1_7_init_tlb_regs(adev);
+ mmhub_v1_7_init_cache_regs(adev);
++ mmhub_v1_7_init_snoop_override_regs(adev);
+
+ mmhub_v1_7_enable_system_domain(adev);
+ mmhub_v1_7_disable_identity_aperture(adev);
+diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c
+index b01bb759d0f4f..2276c644a6974 100644
+--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c
++++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c
+@@ -214,6 +214,32 @@ static void mmhub_v1_8_init_tlb_regs(struct amdgpu_device *adev)
+ }
+ }
+
++/* Set snoop bit for SDMA so that SDMA writes probe-invalidates RW lines */
++static void mmhub_v1_8_init_snoop_override_regs(struct amdgpu_device *adev)
++{
++ uint32_t tmp, inst_mask;
++ int i, j;
++ uint32_t distance = regDAGB1_WRCLI_GPU_SNOOP_OVERRIDE -
++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE;
++
++ inst_mask = adev->aid_mask;
++ for_each_inst(i, inst_mask) {
++ for (j = 0; j < 5; j++) { /* DAGB instances */
++ tmp = RREG32_SOC15_OFFSET(MMHUB, i,
++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE, j * distance);
++ tmp |= (1 << 15); /* SDMA client is BIT15 */
++ WREG32_SOC15_OFFSET(MMHUB, i,
++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE, j * distance, tmp);
++
++ tmp = RREG32_SOC15_OFFSET(MMHUB, i,
++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE, j * distance);
++ tmp |= (1 << 15);
++ WREG32_SOC15_OFFSET(MMHUB, i,
++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE, j * distance, tmp);
++ }
++ }
++}
++
+ static void mmhub_v1_8_init_cache_regs(struct amdgpu_device *adev)
+ {
+ uint32_t tmp, inst_mask;
+@@ -419,6 +445,7 @@ static int mmhub_v1_8_gart_enable(struct amdgpu_device *adev)
+ mmhub_v1_8_init_system_aperture_regs(adev);
+ mmhub_v1_8_init_tlb_regs(adev);
+ mmhub_v1_8_init_cache_regs(adev);
++ mmhub_v1_8_init_snoop_override_regs(adev);
+
+ mmhub_v1_8_enable_system_domain(adev);
+ mmhub_v1_8_disable_identity_aperture(adev);
+diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
+index ff1b58e446892..fe0710b55c3ac 100644
+--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
++++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
+@@ -198,6 +198,36 @@ static void mmhub_v9_4_init_tlb_regs(struct amdgpu_device *adev, int hubid)
+ hubid * MMHUB_INSTANCE_REGISTER_OFFSET, tmp);
+ }
+
++/* Set snoop bit for SDMA so that SDMA writes probe-invalidates RW lines */
++static void mmhub_v9_4_init_snoop_override_regs(struct amdgpu_device *adev, int hubid)
++{
++ uint32_t tmp;
++ int i;
++ uint32_t distance = mmDAGB1_WRCLI_GPU_SNOOP_OVERRIDE -
++ mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE;
++ uint32_t huboffset = hubid * MMHUB_INSTANCE_REGISTER_OFFSET;
++
++ for (i = 0; i < 5 - (2 * hubid); i++) {
++ /* DAGB instances 0 to 4 are in hub0 and 5 to 7 are in hub1 */
++ tmp = RREG32_SOC15_OFFSET(MMHUB, 0,
++ mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE,
++ huboffset + i * distance);
++ tmp |= (1 << 15); /* SDMA client is BIT15 */
++ WREG32_SOC15_OFFSET(MMHUB, 0,
++ mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE,
++ huboffset + i * distance, tmp);
++
++ tmp = RREG32_SOC15_OFFSET(MMHUB, 0,
++ mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE,
++ huboffset + i * distance);
++ tmp |= (1 << 15);
++ WREG32_SOC15_OFFSET(MMHUB, 0,
++ mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE,
++ huboffset + i * distance, tmp);
++ }
++
++}
++
+ static void mmhub_v9_4_init_cache_regs(struct amdgpu_device *adev, int hubid)
+ {
+ uint32_t tmp;
+@@ -392,6 +422,7 @@ static int mmhub_v9_4_gart_enable(struct amdgpu_device *adev)
+ if (!amdgpu_sriov_vf(adev))
+ mmhub_v9_4_init_cache_regs(adev, i);
+
++ mmhub_v9_4_init_snoop_override_regs(adev, i);
+ mmhub_v9_4_enable_system_domain(adev, i);
+ if (!amdgpu_sriov_vf(adev))
+ mmhub_v9_4_disable_identity_aperture(adev, i);
+diff --git a/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_offset.h b/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_offset.h
+index c488d4a50cf46..b2252deabc17a 100644
+--- a/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_offset.h
++++ b/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_offset.h
+@@ -203,6 +203,10 @@
+ #define mmDAGB0_WR_DATA_CREDIT_BASE_IDX 1
+ #define mmDAGB0_WR_MISC_CREDIT 0x0058
+ #define mmDAGB0_WR_MISC_CREDIT_BASE_IDX 1
++#define mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE 0x005b
++#define mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1
++#define mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x005c
++#define mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1
+ #define mmDAGB0_WRCLI_ASK_PENDING 0x005d
+ #define mmDAGB0_WRCLI_ASK_PENDING_BASE_IDX 1
+ #define mmDAGB0_WRCLI_GO_PENDING 0x005e
+@@ -455,6 +459,10 @@
+ #define mmDAGB1_WR_DATA_CREDIT_BASE_IDX 1
+ #define mmDAGB1_WR_MISC_CREDIT 0x00d8
+ #define mmDAGB1_WR_MISC_CREDIT_BASE_IDX 1
++#define mmDAGB1_WRCLI_GPU_SNOOP_OVERRIDE 0x00db
++#define mmDAGB1_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1
++#define mmDAGB1_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x00dc
++#define mmDAGB1_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1
+ #define mmDAGB1_WRCLI_ASK_PENDING 0x00dd
+ #define mmDAGB1_WRCLI_ASK_PENDING_BASE_IDX 1
+ #define mmDAGB1_WRCLI_GO_PENDING 0x00de
+@@ -707,6 +715,10 @@
+ #define mmDAGB2_WR_DATA_CREDIT_BASE_IDX 1
+ #define mmDAGB2_WR_MISC_CREDIT 0x0158
+ #define mmDAGB2_WR_MISC_CREDIT_BASE_IDX 1
++#define mmDAGB2_WRCLI_GPU_SNOOP_OVERRIDE 0x015b
++#define mmDAGB2_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1
++#define mmDAGB2_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x015c
++#define mmDAGB2_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1
+ #define mmDAGB2_WRCLI_ASK_PENDING 0x015d
+ #define mmDAGB2_WRCLI_ASK_PENDING_BASE_IDX 1
+ #define mmDAGB2_WRCLI_GO_PENDING 0x015e
+@@ -959,6 +971,10 @@
+ #define mmDAGB3_WR_DATA_CREDIT_BASE_IDX 1
+ #define mmDAGB3_WR_MISC_CREDIT 0x01d8
+ #define mmDAGB3_WR_MISC_CREDIT_BASE_IDX 1
++#define mmDAGB3_WRCLI_GPU_SNOOP_OVERRIDE 0x01db
++#define mmDAGB3_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1
++#define mmDAGB3_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x01dc
++#define mmDAGB3_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1
+ #define mmDAGB3_WRCLI_ASK_PENDING 0x01dd
+ #define mmDAGB3_WRCLI_ASK_PENDING_BASE_IDX 1
+ #define mmDAGB3_WRCLI_GO_PENDING 0x01de
+@@ -1211,6 +1227,10 @@
+ #define mmDAGB4_WR_DATA_CREDIT_BASE_IDX 1
+ #define mmDAGB4_WR_MISC_CREDIT 0x0258
+ #define mmDAGB4_WR_MISC_CREDIT_BASE_IDX 1
++#define mmDAGB4_WRCLI_GPU_SNOOP_OVERRIDE 0x025b
++#define mmDAGB4_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1
++#define mmDAGB4_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x025c
++#define mmDAGB4_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1
+ #define mmDAGB4_WRCLI_ASK_PENDING 0x025d
+ #define mmDAGB4_WRCLI_ASK_PENDING_BASE_IDX 1
+ #define mmDAGB4_WRCLI_GO_PENDING 0x025e
+@@ -4793,6 +4813,10 @@
+ #define mmDAGB5_WR_DATA_CREDIT_BASE_IDX 1
+ #define mmDAGB5_WR_MISC_CREDIT 0x3058
+ #define mmDAGB5_WR_MISC_CREDIT_BASE_IDX 1
++#define mmDAGB5_WRCLI_GPU_SNOOP_OVERRIDE 0x305b
++#define mmDAGB5_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1
++#define mmDAGB5_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x305c
++#define mmDAGB5_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1
+ #define mmDAGB5_WRCLI_ASK_PENDING 0x305d
+ #define mmDAGB5_WRCLI_ASK_PENDING_BASE_IDX 1
+ #define mmDAGB5_WRCLI_GO_PENDING 0x305e
+@@ -5045,6 +5069,10 @@
+ #define mmDAGB6_WR_DATA_CREDIT_BASE_IDX 1
+ #define mmDAGB6_WR_MISC_CREDIT 0x30d8
+ #define mmDAGB6_WR_MISC_CREDIT_BASE_IDX 1
++#define mmDAGB6_WRCLI_GPU_SNOOP_OVERRIDE 0x30db
++#define mmDAGB6_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1
++#define mmDAGB6_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x30dc
++#define mmDAGB6_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1
+ #define mmDAGB6_WRCLI_ASK_PENDING 0x30dd
+ #define mmDAGB6_WRCLI_ASK_PENDING_BASE_IDX 1
+ #define mmDAGB6_WRCLI_GO_PENDING 0x30de
+@@ -5297,6 +5325,10 @@
+ #define mmDAGB7_WR_DATA_CREDIT_BASE_IDX 1
+ #define mmDAGB7_WR_MISC_CREDIT 0x3158
+ #define mmDAGB7_WR_MISC_CREDIT_BASE_IDX 1
++#define mmDAGB7_WRCLI_GPU_SNOOP_OVERRIDE 0x315b
++#define mmDAGB7_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1
++#define mmDAGB7_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x315c
++#define mmDAGB7_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1
+ #define mmDAGB7_WRCLI_ASK_PENDING 0x315d
+ #define mmDAGB7_WRCLI_ASK_PENDING_BASE_IDX 1
+ #define mmDAGB7_WRCLI_GO_PENDING 0x315e
+diff --git a/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_sh_mask.h
+index 2969fbf282b7d..5069d2fd467f2 100644
+--- a/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_sh_mask.h
++++ b/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_sh_mask.h
+@@ -1532,6 +1532,12 @@
+ //DAGB0_WRCLI_DBUS_GO_PENDING
+ #define DAGB0_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0
+ #define DAGB0_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL
++//DAGB0_WRCLI_GPU_SNOOP_OVERRIDE
++#define DAGB0_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0
++#define DAGB0_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL
++//DAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE
++#define DAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0
++#define DAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL
+ //DAGB0_DAGB_DLY
+ #define DAGB0_DAGB_DLY__DLY__SHIFT 0x0
+ #define DAGB0_DAGB_DLY__CLI__SHIFT 0x8
+@@ -3207,6 +3213,12 @@
+ //DAGB1_WRCLI_DBUS_GO_PENDING
+ #define DAGB1_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0
+ #define DAGB1_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL
++//DAGB1_WRCLI_GPU_SNOOP_OVERRIDE
++#define DAGB1_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0
++#define DAGB1_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL
++//DAGB1_WRCLI_GPU_SNOOP_OVERRIDE_VALUE
++#define DAGB1_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0
++#define DAGB1_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL
+ //DAGB1_DAGB_DLY
+ #define DAGB1_DAGB_DLY__DLY__SHIFT 0x0
+ #define DAGB1_DAGB_DLY__CLI__SHIFT 0x8
+@@ -4882,6 +4894,12 @@
+ //DAGB2_WRCLI_DBUS_GO_PENDING
+ #define DAGB2_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0
+ #define DAGB2_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL
++//DAGB2_WRCLI_GPU_SNOOP_OVERRIDE
++#define DAGB2_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0
++#define DAGB2_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL
++//DAGB2_WRCLI_GPU_SNOOP_OVERRIDE_VALUE
++#define DAGB2_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0
++#define DAGB2_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL
+ //DAGB2_DAGB_DLY
+ #define DAGB2_DAGB_DLY__DLY__SHIFT 0x0
+ #define DAGB2_DAGB_DLY__CLI__SHIFT 0x8
+@@ -6557,6 +6575,12 @@
+ //DAGB3_WRCLI_DBUS_GO_PENDING
+ #define DAGB3_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0
+ #define DAGB3_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL
++//DAGB3_WRCLI_GPU_SNOOP_OVERRIDE
++#define DAGB3_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0
++#define DAGB3_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL
++//DAGB3_WRCLI_GPU_SNOOP_OVERRIDE_VALUE
++#define DAGB3_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0
++#define DAGB3_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL
+ //DAGB3_DAGB_DLY
+ #define DAGB3_DAGB_DLY__DLY__SHIFT 0x0
+ #define DAGB3_DAGB_DLY__CLI__SHIFT 0x8
+@@ -8232,6 +8256,12 @@
+ //DAGB4_WRCLI_DBUS_GO_PENDING
+ #define DAGB4_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0
+ #define DAGB4_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL
++//DAGB4_WRCLI_GPU_SNOOP_OVERRIDE
++#define DAGB4_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0
++#define DAGB4_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL
++//DAGB4_WRCLI_GPU_SNOOP_OVERRIDE_VALUE
++#define DAGB4_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0
++#define DAGB4_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL
+ //DAGB4_DAGB_DLY
+ #define DAGB4_DAGB_DLY__DLY__SHIFT 0x0
+ #define DAGB4_DAGB_DLY__CLI__SHIFT 0x8
+@@ -28737,6 +28767,12 @@
+ //DAGB5_WRCLI_DBUS_GO_PENDING
+ #define DAGB5_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0
+ #define DAGB5_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL
++//DAGB5_WRCLI_GPU_SNOOP_OVERRIDE
++#define DAGB5_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0
++#define DAGB5_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL
++//DAGB5_WRCLI_GPU_SNOOP_OVERRIDE_VALUE
++#define DAGB5_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0
++#define DAGB5_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL
+ //DAGB5_DAGB_DLY
+ #define DAGB5_DAGB_DLY__DLY__SHIFT 0x0
+ #define DAGB5_DAGB_DLY__CLI__SHIFT 0x8
+@@ -30412,6 +30448,12 @@
+ //DAGB6_WRCLI_DBUS_GO_PENDING
+ #define DAGB6_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0
+ #define DAGB6_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL
++//DAGB6_WRCLI_GPU_SNOOP_OVERRIDE
++#define DAGB6_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0
++#define DAGB6_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL
++//DAGB6_WRCLI_GPU_SNOOP_OVERRIDE_VALUE
++#define DAGB6_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0
++#define DAGB6_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL
+ //DAGB6_DAGB_DLY
+ #define DAGB6_DAGB_DLY__DLY__SHIFT 0x0
+ #define DAGB6_DAGB_DLY__CLI__SHIFT 0x8
+@@ -32087,6 +32129,12 @@
+ //DAGB7_WRCLI_DBUS_GO_PENDING
+ #define DAGB7_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0
+ #define DAGB7_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL
++//DAGB7_WRCLI_GPU_SNOOP_OVERRIDE
++#define DAGB7_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0
++#define DAGB7_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL
++//DAGB7_WRCLI_GPU_SNOOP_OVERRIDE_VALUE
++#define DAGB7_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0
++#define DAGB7_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL
+ //DAGB7_DAGB_DLY
+ #define DAGB7_DAGB_DLY__DLY__SHIFT 0x0
+ #define DAGB7_DAGB_DLY__CLI__SHIFT 0x8
+--
+2.39.5
+
--- /dev/null
+From d40d4dbac2a94d07a1b9d91f2b810f36428b8bab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Mar 2025 09:32:13 -0400
+Subject: drm/amdgpu: Skip pcie_replay_count sysfs creation for VF
+
+From: Victor Skvortsov <victor.skvortsov@amd.com>
+
+[ Upstream commit 9c05636ca72a2dbf41bf0900380f438a0de47319 ]
+
+VFs cannot read the NAK_COUNTER register. This information is only
+available through PMFW metrics.
+
+Signed-off-by: Victor Skvortsov <victor.skvortsov@amd.com>
+Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 27 ++++++++++++++++------
+ 1 file changed, 20 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+index cb102ee71d04c..081c0e45779fc 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -170,6 +170,24 @@ static ssize_t amdgpu_device_get_pcie_replay_count(struct device *dev,
+ static DEVICE_ATTR(pcie_replay_count, 0444,
+ amdgpu_device_get_pcie_replay_count, NULL);
+
++static int amdgpu_device_attr_sysfs_init(struct amdgpu_device *adev)
++{
++ int ret = 0;
++
++ if (!amdgpu_sriov_vf(adev))
++ ret = sysfs_create_file(&adev->dev->kobj,
++ &dev_attr_pcie_replay_count.attr);
++
++ return ret;
++}
++
++static void amdgpu_device_attr_sysfs_fini(struct amdgpu_device *adev)
++{
++ if (!amdgpu_sriov_vf(adev))
++ sysfs_remove_file(&adev->dev->kobj,
++ &dev_attr_pcie_replay_count.attr);
++}
++
+ static ssize_t amdgpu_sysfs_reg_state_get(struct file *f, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t ppos, size_t count)
+@@ -4030,11 +4048,6 @@ static bool amdgpu_device_check_iommu_remap(struct amdgpu_device *adev)
+ }
+ #endif
+
+-static const struct attribute *amdgpu_dev_attributes[] = {
+- &dev_attr_pcie_replay_count.attr,
+- NULL
+-};
+-
+ static void amdgpu_device_set_mcbp(struct amdgpu_device *adev)
+ {
+ if (amdgpu_mcbp == 1)
+@@ -4477,7 +4490,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
+ } else
+ adev->ucode_sysfs_en = true;
+
+- r = sysfs_create_files(&adev->dev->kobj, amdgpu_dev_attributes);
++ r = amdgpu_device_attr_sysfs_init(adev);
+ if (r)
+ dev_err(adev->dev, "Could not create amdgpu device attr\n");
+
+@@ -4614,7 +4627,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
+ amdgpu_pm_sysfs_fini(adev);
+ if (adev->ucode_sysfs_en)
+ amdgpu_ucode_sysfs_fini(adev);
+- sysfs_remove_files(&adev->dev->kobj, amdgpu_dev_attributes);
++ amdgpu_device_attr_sysfs_fini(adev);
+ amdgpu_fru_sysfs_fini(adev);
+
+ amdgpu_reg_state_sysfs_fini(adev);
+--
+2.39.5
+
--- /dev/null
+From 01275c0742f97bff40fdb4fb6a2baf48ad2c9c42 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Feb 2025 13:44:32 +0100
+Subject: drm/amdgpu: Update SRIOV video codec caps
+
+From: David Rosca <david.rosca@amd.com>
+
+[ Upstream commit 19478f2011f8b53dee401c91423c4e0b73753e4f ]
+
+There have been multiple fixes to the video caps that are missing for
+SRIOV. Update the SRIOV caps with correct values.
+
+Signed-off-by: David Rosca <david.rosca@amd.com>
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Reviewed-by: Ruijing Dong <ruijing.dong@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/nv.c | 16 ++++++++--------
+ drivers/gpu/drm/amd/amdgpu/soc21.c | 10 ++--------
+ 2 files changed, 10 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c
+index 4f94a119d6275..ab0eecbab4125 100644
+--- a/drivers/gpu/drm/amd/amdgpu/nv.c
++++ b/drivers/gpu/drm/amd/amdgpu/nv.c
+@@ -141,23 +141,23 @@ static struct amdgpu_video_codec_info sriov_sc_video_codecs_encode_array[] = {
+ };
+
+ static struct amdgpu_video_codec_info sriov_sc_video_codecs_decode_array_vcn0[] = {
+- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)},
+- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)},
++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 1920, 1088, 3)},
++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 1920, 1088, 5)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
+- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)},
++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 1920, 1088, 4)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)},
+- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)},
++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)},
+ };
+
+ static struct amdgpu_video_codec_info sriov_sc_video_codecs_decode_array_vcn1[] = {
+- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)},
+- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)},
++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 1920, 1088, 3)},
++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 1920, 1088, 5)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
+- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)},
++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 1920, 1088, 4)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)},
+- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)},
++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)},
+ };
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c
+index bba35880badb9..04a1b2a46368f 100644
+--- a/drivers/gpu/drm/amd/amdgpu/soc21.c
++++ b/drivers/gpu/drm/amd/amdgpu/soc21.c
+@@ -117,23 +117,17 @@ static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_encode_vcn1 = {
+ };
+
+ static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_decode_array_vcn0[] = {
+- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)},
+- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
+- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)},
+- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)},
++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)},
+ };
+
+ static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_decode_array_vcn1[] = {
+- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)},
+- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
+- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)},
+- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)},
++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)},
+ };
+
+--
+2.39.5
+
--- /dev/null
+From 92ed2eb8a872c0269c393352f229c13cd1d9223a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 1 Jan 2025 14:23:31 +0530
+Subject: drm/amdgpu: Use active umc info from discovery
+
+From: Lijo Lazar <lijo.lazar@amd.com>
+
+[ Upstream commit f7a594e40517fa2ab25d5ca10e7b6a158f529fb5 ]
+
+There could be configs where some UMC instances are harvested. This
+information is obtained through discovery data and populated in
+umc.active_mask. Avoid reassigning this as AID mask, instead use the
+mask directly while iterating through umc instances. This is to avoid
+accesses to harvested UMC instances.
+
+v2: fix warning (Alex)
+
+Signed-off-by: Lijo Lazar <lijo.lazar@amd.com>
+Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c | 42 +++++++++++++++++++++++++
+ drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 1 -
+ 2 files changed, 42 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
+index bb7b9b2eaac1a..8da0bddab3d23 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
+@@ -383,6 +383,45 @@ int amdgpu_umc_fill_error_record(struct ras_err_data *err_data,
+ return 0;
+ }
+
++static int amdgpu_umc_loop_all_aid(struct amdgpu_device *adev, umc_func func,
++ void *data)
++{
++ uint32_t umc_node_inst;
++ uint32_t node_inst;
++ uint32_t umc_inst;
++ uint32_t ch_inst;
++ int ret;
++
++ /*
++ * This loop is done based on the following -
++ * umc.active mask = mask of active umc instances across all nodes
++ * umc.umc_inst_num = maximum number of umc instancess per node
++ * umc.node_inst_num = maximum number of node instances
++ * Channel instances are not assumed to be harvested.
++ */
++ dev_dbg(adev->dev, "active umcs :%lx umc_inst per node: %d",
++ adev->umc.active_mask, adev->umc.umc_inst_num);
++ for_each_set_bit(umc_node_inst, &(adev->umc.active_mask),
++ adev->umc.node_inst_num * adev->umc.umc_inst_num) {
++ node_inst = umc_node_inst / adev->umc.umc_inst_num;
++ umc_inst = umc_node_inst % adev->umc.umc_inst_num;
++ LOOP_UMC_CH_INST(ch_inst) {
++ dev_dbg(adev->dev,
++ "node_inst :%d umc_inst: %d ch_inst: %d",
++ node_inst, umc_inst, ch_inst);
++ ret = func(adev, node_inst, umc_inst, ch_inst, data);
++ if (ret) {
++ dev_err(adev->dev,
++ "Node %d umc %d ch %d func returns %d\n",
++ node_inst, umc_inst, ch_inst, ret);
++ return ret;
++ }
++ }
++ }
++
++ return 0;
++}
++
+ int amdgpu_umc_loop_channels(struct amdgpu_device *adev,
+ umc_func func, void *data)
+ {
+@@ -391,6 +430,9 @@ int amdgpu_umc_loop_channels(struct amdgpu_device *adev,
+ uint32_t ch_inst = 0;
+ int ret = 0;
+
++ if (adev->aid_mask)
++ return amdgpu_umc_loop_all_aid(adev, func, data);
++
+ if (adev->umc.node_inst_num) {
+ LOOP_UMC_EACH_NODE_INST_AND_CH(node_inst, umc_inst, ch_inst) {
+ ret = func(adev, node_inst, umc_inst, ch_inst, data);
+diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+index 9a212413c6d3a..78c527b56f7c5 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+@@ -1461,7 +1461,6 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev)
+ adev->umc.umc_inst_num = UMC_V12_0_UMC_INSTANCE_NUM;
+ adev->umc.node_inst_num /= UMC_V12_0_UMC_INSTANCE_NUM;
+ adev->umc.channel_offs = UMC_V12_0_PER_CHANNEL_OFFSET;
+- adev->umc.active_mask = adev->aid_mask;
+ adev->umc.retire_unit = UMC_V12_0_BAD_PAGE_NUM_PER_CHANNEL;
+ if (!adev->gmc.xgmi.connected_to_cpu && !adev->gmc.is_app_apu)
+ adev->umc.ras = &umc_v12_0_ras;
+--
+2.39.5
+
--- /dev/null
+From 613f39e5acbe96ac1b1061d81df5aeac9f88efa8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jan 2025 15:48:26 -0500
+Subject: drm/amdkfd: fix missing L2 cache info in topology
+
+From: Eric Huang <jinhuieric.huang@amd.com>
+
+[ Upstream commit 5ffd56822a7159917306d99f18fd15dfd7288f20 ]
+
+In some ASICs L2 cache info may miss in kfd topology,
+because the first bitmap may be empty, that means
+the first cu may be inactive, so to find the first
+active cu will solve the issue.
+
+v2: Only find the first active cu in the first xcc
+
+Signed-off-by: Eric Huang <jinhuieric.huang@amd.com>
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Acked-by: Lijo Lazar <lijo.lazar@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 19 +++++++++++++++++--
+ 1 file changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+index bcb5cdc4a9d81..82da568604b6e 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+@@ -1683,17 +1683,32 @@ static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext,
+ int cache_type, unsigned int cu_processor_id,
+ struct kfd_node *knode)
+ {
+- unsigned int cu_sibling_map_mask;
++ unsigned int cu_sibling_map_mask = 0;
+ int first_active_cu;
+ int i, j, k, xcc, start, end;
+ int num_xcc = NUM_XCC(knode->xcc_mask);
+ struct kfd_cache_properties *pcache = NULL;
+ enum amdgpu_memory_partition mode;
+ struct amdgpu_device *adev = knode->adev;
++ bool found = false;
+
+ start = ffs(knode->xcc_mask) - 1;
+ end = start + num_xcc;
+- cu_sibling_map_mask = cu_info->bitmap[start][0][0];
++
++ /* To find the bitmap in the first active cu in the first
++ * xcc, it is based on the assumption that evrey xcc must
++ * have at least one active cu.
++ */
++ for (i = 0; i < gfx_info->max_shader_engines && !found; i++) {
++ for (j = 0; j < gfx_info->max_sh_per_se && !found; j++) {
++ if (cu_info->bitmap[start][i % 4][j % 4]) {
++ cu_sibling_map_mask =
++ cu_info->bitmap[start][i % 4][j % 4];
++ found = true;
++ }
++ }
++ }
++
+ cu_sibling_map_mask &=
+ ((1 << pcache_info[cache_type].num_cu_shared) - 1);
+ first_active_cu = ffs(cu_sibling_map_mask);
+--
+2.39.5
+
--- /dev/null
+From 7baa1cf47da76cbe2e06daf65d172356bb0d05b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 20:08:29 -0500
+Subject: drm/amdkfd: KFD release_work possible circular locking
+
+From: Philip Yang <Philip.Yang@amd.com>
+
+[ Upstream commit 1b9366c601039d60546794c63fbb83ce8e53b978 ]
+
+If waiting for gpu reset done in KFD release_work, thers is WARNING:
+possible circular locking dependency detected
+
+ #2 kfd_create_process
+ kfd_process_mutex
+ flush kfd release work
+
+ #1 kfd release work
+ wait for amdgpu reset work
+
+ #0 amdgpu_device_gpu_reset
+ kgd2kfd_pre_reset
+ kfd_process_mutex
+
+ Possible unsafe locking scenario:
+
+ CPU0 CPU1
+ ---- ----
+ lock((work_completion)(&p->release_work));
+ lock((wq_completion)kfd_process_wq);
+ lock((work_completion)(&p->release_work));
+ lock((wq_completion)amdgpu-reset-dev);
+
+To fix this, KFD create process move flush release work outside
+kfd_process_mutex.
+
+Signed-off-by: Philip Yang <Philip.Yang@amd.com>
+Reviewed-by: Felix Kuehling <felix.kuehling@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdkfd/kfd_process.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+index 0ec8b457494bd..45923da7709fd 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+@@ -842,6 +842,14 @@ struct kfd_process *kfd_create_process(struct task_struct *thread)
+ return ERR_PTR(-EINVAL);
+ }
+
++ /* If the process just called exec(3), it is possible that the
++ * cleanup of the kfd_process (following the release of the mm
++ * of the old process image) is still in the cleanup work queue.
++ * Make sure to drain any job before trying to recreate any
++ * resource for this process.
++ */
++ flush_workqueue(kfd_process_wq);
++
+ /*
+ * take kfd processes mutex before starting of process creation
+ * so there won't be a case where two threads of the same process
+@@ -860,14 +868,6 @@ struct kfd_process *kfd_create_process(struct task_struct *thread)
+ if (process) {
+ pr_debug("Process already found\n");
+ } else {
+- /* If the process just called exec(3), it is possible that the
+- * cleanup of the kfd_process (following the release of the mm
+- * of the old process image) is still in the cleanup work queue.
+- * Make sure to drain any job before trying to recreate any
+- * resource for this process.
+- */
+- flush_workqueue(kfd_process_wq);
+-
+ process = create_process(thread);
+ if (IS_ERR(process))
+ goto out;
+--
+2.39.5
+
--- /dev/null
+From aa8caf2889b62a645fc3e0a9673496de184aa337 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Jan 2025 14:07:24 -0500
+Subject: drm/amdkfd: Set per-process flags only once cik/vi
+
+From: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
+
+[ Upstream commit 289e68503a4533b014f8447e2af28ad44c92c221 ]
+
+Set per-process static sh_mem config only once during process
+initialization. Move all static changes from update_qpd() which is
+called each time a queue is created to set_cache_memory_policy() which
+is called once during process initialization.
+
+set_cache_memory_policy() is currently defined only for cik and vi
+family. So this commit only focuses on these two. A separate commit will
+address other asics.
+
+Signed-off-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
+Reviewed-by: Amber Lin <Amber.Lin@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../drm/amd/amdkfd/kfd_device_queue_manager.c | 39 +---------
+ .../amd/amdkfd/kfd_device_queue_manager_cik.c | 69 ++++++++++++------
+ .../amd/amdkfd/kfd_device_queue_manager_vi.c | 71 ++++++++++++-------
+ 3 files changed, 94 insertions(+), 85 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+index 951b87e7e3f68..6a58dd8d2130c 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+@@ -2453,14 +2453,6 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm,
+ return retval;
+ }
+
+-/*
+- * Low bits must be 0000/FFFF as required by HW, high bits must be 0 to
+- * stay in user mode.
+- */
+-#define APE1_FIXED_BITS_MASK 0xFFFF80000000FFFFULL
+-/* APE1 limit is inclusive and 64K aligned. */
+-#define APE1_LIMIT_ALIGNMENT 0xFFFF
+-
+ static bool set_cache_memory_policy(struct device_queue_manager *dqm,
+ struct qcm_process_device *qpd,
+ enum cache_policy default_policy,
+@@ -2475,34 +2467,6 @@ static bool set_cache_memory_policy(struct device_queue_manager *dqm,
+
+ dqm_lock(dqm);
+
+- if (alternate_aperture_size == 0) {
+- /* base > limit disables APE1 */
+- qpd->sh_mem_ape1_base = 1;
+- qpd->sh_mem_ape1_limit = 0;
+- } else {
+- /*
+- * In FSA64, APE1_Base[63:0] = { 16{SH_MEM_APE1_BASE[31]},
+- * SH_MEM_APE1_BASE[31:0], 0x0000 }
+- * APE1_Limit[63:0] = { 16{SH_MEM_APE1_LIMIT[31]},
+- * SH_MEM_APE1_LIMIT[31:0], 0xFFFF }
+- * Verify that the base and size parameters can be
+- * represented in this format and convert them.
+- * Additionally restrict APE1 to user-mode addresses.
+- */
+-
+- uint64_t base = (uintptr_t)alternate_aperture_base;
+- uint64_t limit = base + alternate_aperture_size - 1;
+-
+- if (limit <= base || (base & APE1_FIXED_BITS_MASK) != 0 ||
+- (limit & APE1_FIXED_BITS_MASK) != APE1_LIMIT_ALIGNMENT) {
+- retval = false;
+- goto out;
+- }
+-
+- qpd->sh_mem_ape1_base = base >> 16;
+- qpd->sh_mem_ape1_limit = limit >> 16;
+- }
+-
+ retval = dqm->asic_ops.set_cache_memory_policy(
+ dqm,
+ qpd,
+@@ -2511,6 +2475,9 @@ static bool set_cache_memory_policy(struct device_queue_manager *dqm,
+ alternate_aperture_base,
+ alternate_aperture_size);
+
++ if (retval)
++ goto out;
++
+ if ((dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) && (qpd->vmid != 0))
+ program_sh_mem_settings(dqm, qpd);
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c
+index d4d95c7f2e5d4..32bedef912b3b 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c
+@@ -27,6 +27,14 @@
+ #include "oss/oss_2_4_sh_mask.h"
+ #include "gca/gfx_7_2_sh_mask.h"
+
++/*
++ * Low bits must be 0000/FFFF as required by HW, high bits must be 0 to
++ * stay in user mode.
++ */
++#define APE1_FIXED_BITS_MASK 0xFFFF80000000FFFFULL
++/* APE1 limit is inclusive and 64K aligned. */
++#define APE1_LIMIT_ALIGNMENT 0xFFFF
++
+ static bool set_cache_memory_policy_cik(struct device_queue_manager *dqm,
+ struct qcm_process_device *qpd,
+ enum cache_policy default_policy,
+@@ -84,6 +92,36 @@ static bool set_cache_memory_policy_cik(struct device_queue_manager *dqm,
+ {
+ uint32_t default_mtype;
+ uint32_t ape1_mtype;
++ unsigned int temp;
++ bool retval = true;
++
++ if (alternate_aperture_size == 0) {
++ /* base > limit disables APE1 */
++ qpd->sh_mem_ape1_base = 1;
++ qpd->sh_mem_ape1_limit = 0;
++ } else {
++ /*
++ * In FSA64, APE1_Base[63:0] = { 16{SH_MEM_APE1_BASE[31]},
++ * SH_MEM_APE1_BASE[31:0], 0x0000 }
++ * APE1_Limit[63:0] = { 16{SH_MEM_APE1_LIMIT[31]},
++ * SH_MEM_APE1_LIMIT[31:0], 0xFFFF }
++ * Verify that the base and size parameters can be
++ * represented in this format and convert them.
++ * Additionally restrict APE1 to user-mode addresses.
++ */
++
++ uint64_t base = (uintptr_t)alternate_aperture_base;
++ uint64_t limit = base + alternate_aperture_size - 1;
++
++ if (limit <= base || (base & APE1_FIXED_BITS_MASK) != 0 ||
++ (limit & APE1_FIXED_BITS_MASK) != APE1_LIMIT_ALIGNMENT) {
++ retval = false;
++ goto out;
++ }
++
++ qpd->sh_mem_ape1_base = base >> 16;
++ qpd->sh_mem_ape1_limit = limit >> 16;
++ }
+
+ default_mtype = (default_policy == cache_policy_coherent) ?
+ MTYPE_NONCACHED :
+@@ -97,37 +135,22 @@ static bool set_cache_memory_policy_cik(struct device_queue_manager *dqm,
+ | ALIGNMENT_MODE(SH_MEM_ALIGNMENT_MODE_UNALIGNED)
+ | DEFAULT_MTYPE(default_mtype)
+ | APE1_MTYPE(ape1_mtype);
+-
+- return true;
+-}
+-
+-static int update_qpd_cik(struct device_queue_manager *dqm,
+- struct qcm_process_device *qpd)
+-{
+- struct kfd_process_device *pdd;
+- unsigned int temp;
+-
+- pdd = qpd_to_pdd(qpd);
+-
+- /* check if sh_mem_config register already configured */
+- if (qpd->sh_mem_config == 0) {
+- qpd->sh_mem_config =
+- ALIGNMENT_MODE(SH_MEM_ALIGNMENT_MODE_UNALIGNED) |
+- DEFAULT_MTYPE(MTYPE_NONCACHED) |
+- APE1_MTYPE(MTYPE_NONCACHED);
+- qpd->sh_mem_ape1_limit = 0;
+- qpd->sh_mem_ape1_base = 0;
+- }
+-
+ /* On dGPU we're always in GPUVM64 addressing mode with 64-bit
+ * aperture addresses.
+ */
+- temp = get_sh_mem_bases_nybble_64(pdd);
++ temp = get_sh_mem_bases_nybble_64(qpd_to_pdd(qpd));
+ qpd->sh_mem_bases = compute_sh_mem_bases_64bit(temp);
+
+ pr_debug("is32bit process: %d sh_mem_bases nybble: 0x%X and register 0x%X\n",
+ qpd->pqm->process->is_32bit_user_mode, temp, qpd->sh_mem_bases);
+
++out:
++ return retval;
++}
++
++static int update_qpd_cik(struct device_queue_manager *dqm,
++ struct qcm_process_device *qpd)
++{
+ return 0;
+ }
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c
+index b291ee0fab943..320518f418903 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c
+@@ -27,6 +27,14 @@
+ #include "gca/gfx_8_0_sh_mask.h"
+ #include "oss/oss_3_0_sh_mask.h"
+
++/*
++ * Low bits must be 0000/FFFF as required by HW, high bits must be 0 to
++ * stay in user mode.
++ */
++#define APE1_FIXED_BITS_MASK 0xFFFF80000000FFFFULL
++/* APE1 limit is inclusive and 64K aligned. */
++#define APE1_LIMIT_ALIGNMENT 0xFFFF
++
+ static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm,
+ struct qcm_process_device *qpd,
+ enum cache_policy default_policy,
+@@ -85,6 +93,36 @@ static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm,
+ {
+ uint32_t default_mtype;
+ uint32_t ape1_mtype;
++ unsigned int temp;
++ bool retval = true;
++
++ if (alternate_aperture_size == 0) {
++ /* base > limit disables APE1 */
++ qpd->sh_mem_ape1_base = 1;
++ qpd->sh_mem_ape1_limit = 0;
++ } else {
++ /*
++ * In FSA64, APE1_Base[63:0] = { 16{SH_MEM_APE1_BASE[31]},
++ * SH_MEM_APE1_BASE[31:0], 0x0000 }
++ * APE1_Limit[63:0] = { 16{SH_MEM_APE1_LIMIT[31]},
++ * SH_MEM_APE1_LIMIT[31:0], 0xFFFF }
++ * Verify that the base and size parameters can be
++ * represented in this format and convert them.
++ * Additionally restrict APE1 to user-mode addresses.
++ */
++
++ uint64_t base = (uintptr_t)alternate_aperture_base;
++ uint64_t limit = base + alternate_aperture_size - 1;
++
++ if (limit <= base || (base & APE1_FIXED_BITS_MASK) != 0 ||
++ (limit & APE1_FIXED_BITS_MASK) != APE1_LIMIT_ALIGNMENT) {
++ retval = false;
++ goto out;
++ }
++
++ qpd->sh_mem_ape1_base = base >> 16;
++ qpd->sh_mem_ape1_limit = limit >> 16;
++ }
+
+ default_mtype = (default_policy == cache_policy_coherent) ?
+ MTYPE_UC :
+@@ -100,40 +138,21 @@ static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm,
+ default_mtype << SH_MEM_CONFIG__DEFAULT_MTYPE__SHIFT |
+ ape1_mtype << SH_MEM_CONFIG__APE1_MTYPE__SHIFT;
+
+- return true;
+-}
+-
+-static int update_qpd_vi(struct device_queue_manager *dqm,
+- struct qcm_process_device *qpd)
+-{
+- struct kfd_process_device *pdd;
+- unsigned int temp;
+-
+- pdd = qpd_to_pdd(qpd);
+-
+- /* check if sh_mem_config register already configured */
+- if (qpd->sh_mem_config == 0) {
+- qpd->sh_mem_config =
+- SH_MEM_ALIGNMENT_MODE_UNALIGNED <<
+- SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT |
+- MTYPE_UC <<
+- SH_MEM_CONFIG__DEFAULT_MTYPE__SHIFT |
+- MTYPE_UC <<
+- SH_MEM_CONFIG__APE1_MTYPE__SHIFT;
+-
+- qpd->sh_mem_ape1_limit = 0;
+- qpd->sh_mem_ape1_base = 0;
+- }
+-
+ /* On dGPU we're always in GPUVM64 addressing mode with 64-bit
+ * aperture addresses.
+ */
+- temp = get_sh_mem_bases_nybble_64(pdd);
++ temp = get_sh_mem_bases_nybble_64(qpd_to_pdd(qpd));
+ qpd->sh_mem_bases = compute_sh_mem_bases_64bit(temp);
+
+ pr_debug("sh_mem_bases nybble: 0x%X and register 0x%X\n",
+ temp, qpd->sh_mem_bases);
++out:
++ return retval;
++}
+
++static int update_qpd_vi(struct device_queue_manager *dqm,
++ struct qcm_process_device *qpd)
++{
+ return 0;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 1fe58243c1becd36c0f05ae5b132d215f37061a9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Jan 2025 14:13:35 -0500
+Subject: drm/amdkfd: Set per-process flags only once for gfx9/10/11/12
+
+From: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
+
+[ Upstream commit 61972cd93af70738a6ad7f93e17cc7f68a01e182 ]
+
+Define set_cache_memory_policy() for these asics and move all static
+changes from update_qpd() which is called each time a queue is created
+to set_cache_memory_policy() which is called once during process
+initialization
+
+Signed-off-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
+Reviewed-by: Amber Lin <Amber.Lin@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../amd/amdkfd/kfd_device_queue_manager_v10.c | 41 +++++++++++--------
+ .../amd/amdkfd/kfd_device_queue_manager_v11.c | 41 +++++++++++--------
+ .../amd/amdkfd/kfd_device_queue_manager_v12.c | 41 +++++++++++--------
+ .../amd/amdkfd/kfd_device_queue_manager_v9.c | 36 +++++++++++++++-
+ 4 files changed, 107 insertions(+), 52 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c
+index 245a90dfc2f6b..b5f5f141353b5 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c
+@@ -31,10 +31,17 @@ static int update_qpd_v10(struct device_queue_manager *dqm,
+ struct qcm_process_device *qpd);
+ static void init_sdma_vm_v10(struct device_queue_manager *dqm, struct queue *q,
+ struct qcm_process_device *qpd);
++static bool set_cache_memory_policy_v10(struct device_queue_manager *dqm,
++ struct qcm_process_device *qpd,
++ enum cache_policy default_policy,
++ enum cache_policy alternate_policy,
++ void __user *alternate_aperture_base,
++ uint64_t alternate_aperture_size);
+
+ void device_queue_manager_init_v10(
+ struct device_queue_manager_asic_ops *asic_ops)
+ {
++ asic_ops->set_cache_memory_policy = set_cache_memory_policy_v10;
+ asic_ops->update_qpd = update_qpd_v10;
+ asic_ops->init_sdma_vm = init_sdma_vm_v10;
+ asic_ops->mqd_manager_init = mqd_manager_init_v10;
+@@ -49,27 +56,27 @@ static uint32_t compute_sh_mem_bases_64bit(struct kfd_process_device *pdd)
+ private_base;
+ }
+
+-static int update_qpd_v10(struct device_queue_manager *dqm,
+- struct qcm_process_device *qpd)
++static bool set_cache_memory_policy_v10(struct device_queue_manager *dqm,
++ struct qcm_process_device *qpd,
++ enum cache_policy default_policy,
++ enum cache_policy alternate_policy,
++ void __user *alternate_aperture_base,
++ uint64_t alternate_aperture_size)
+ {
+- struct kfd_process_device *pdd;
+-
+- pdd = qpd_to_pdd(qpd);
+-
+- /* check if sh_mem_config register already configured */
+- if (qpd->sh_mem_config == 0) {
+- qpd->sh_mem_config =
+- (SH_MEM_ALIGNMENT_MODE_UNALIGNED <<
+- SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) |
+- (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT);
+- qpd->sh_mem_ape1_limit = 0;
+- qpd->sh_mem_ape1_base = 0;
+- }
+-
+- qpd->sh_mem_bases = compute_sh_mem_bases_64bit(pdd);
++ qpd->sh_mem_config = (SH_MEM_ALIGNMENT_MODE_UNALIGNED <<
++ SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) |
++ (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT);
++ qpd->sh_mem_ape1_limit = 0;
++ qpd->sh_mem_ape1_base = 0;
++ qpd->sh_mem_bases = compute_sh_mem_bases_64bit(qpd_to_pdd(qpd));
+
+ pr_debug("sh_mem_bases 0x%X\n", qpd->sh_mem_bases);
++ return true;
++}
+
++static int update_qpd_v10(struct device_queue_manager *dqm,
++ struct qcm_process_device *qpd)
++{
+ return 0;
+ }
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c
+index 2e129da7acb43..f436878d0d621 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c
+@@ -30,10 +30,17 @@ static int update_qpd_v11(struct device_queue_manager *dqm,
+ struct qcm_process_device *qpd);
+ static void init_sdma_vm_v11(struct device_queue_manager *dqm, struct queue *q,
+ struct qcm_process_device *qpd);
++static bool set_cache_memory_policy_v11(struct device_queue_manager *dqm,
++ struct qcm_process_device *qpd,
++ enum cache_policy default_policy,
++ enum cache_policy alternate_policy,
++ void __user *alternate_aperture_base,
++ uint64_t alternate_aperture_size);
+
+ void device_queue_manager_init_v11(
+ struct device_queue_manager_asic_ops *asic_ops)
+ {
++ asic_ops->set_cache_memory_policy = set_cache_memory_policy_v11;
+ asic_ops->update_qpd = update_qpd_v11;
+ asic_ops->init_sdma_vm = init_sdma_vm_v11;
+ asic_ops->mqd_manager_init = mqd_manager_init_v11;
+@@ -48,28 +55,28 @@ static uint32_t compute_sh_mem_bases_64bit(struct kfd_process_device *pdd)
+ private_base;
+ }
+
+-static int update_qpd_v11(struct device_queue_manager *dqm,
+- struct qcm_process_device *qpd)
++static bool set_cache_memory_policy_v11(struct device_queue_manager *dqm,
++ struct qcm_process_device *qpd,
++ enum cache_policy default_policy,
++ enum cache_policy alternate_policy,
++ void __user *alternate_aperture_base,
++ uint64_t alternate_aperture_size)
+ {
+- struct kfd_process_device *pdd;
+-
+- pdd = qpd_to_pdd(qpd);
+-
+- /* check if sh_mem_config register already configured */
+- if (qpd->sh_mem_config == 0) {
+- qpd->sh_mem_config =
+- (SH_MEM_ALIGNMENT_MODE_UNALIGNED <<
+- SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) |
+- (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT);
+-
+- qpd->sh_mem_ape1_limit = 0;
+- qpd->sh_mem_ape1_base = 0;
+- }
++ qpd->sh_mem_config = (SH_MEM_ALIGNMENT_MODE_UNALIGNED <<
++ SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) |
++ (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT);
+
+- qpd->sh_mem_bases = compute_sh_mem_bases_64bit(pdd);
++ qpd->sh_mem_ape1_limit = 0;
++ qpd->sh_mem_ape1_base = 0;
++ qpd->sh_mem_bases = compute_sh_mem_bases_64bit(qpd_to_pdd(qpd));
+
+ pr_debug("sh_mem_bases 0x%X\n", qpd->sh_mem_bases);
++ return true;
++}
+
++static int update_qpd_v11(struct device_queue_manager *dqm,
++ struct qcm_process_device *qpd)
++{
+ return 0;
+ }
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c
+index 4f3295b29dfb1..62ca1c8fcbaf9 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c
+@@ -30,10 +30,17 @@ static int update_qpd_v12(struct device_queue_manager *dqm,
+ struct qcm_process_device *qpd);
+ static void init_sdma_vm_v12(struct device_queue_manager *dqm, struct queue *q,
+ struct qcm_process_device *qpd);
++static bool set_cache_memory_policy_v12(struct device_queue_manager *dqm,
++ struct qcm_process_device *qpd,
++ enum cache_policy default_policy,
++ enum cache_policy alternate_policy,
++ void __user *alternate_aperture_base,
++ uint64_t alternate_aperture_size);
+
+ void device_queue_manager_init_v12(
+ struct device_queue_manager_asic_ops *asic_ops)
+ {
++ asic_ops->set_cache_memory_policy = set_cache_memory_policy_v12;
+ asic_ops->update_qpd = update_qpd_v12;
+ asic_ops->init_sdma_vm = init_sdma_vm_v12;
+ asic_ops->mqd_manager_init = mqd_manager_init_v12;
+@@ -48,28 +55,28 @@ static uint32_t compute_sh_mem_bases_64bit(struct kfd_process_device *pdd)
+ private_base;
+ }
+
+-static int update_qpd_v12(struct device_queue_manager *dqm,
+- struct qcm_process_device *qpd)
++static bool set_cache_memory_policy_v12(struct device_queue_manager *dqm,
++ struct qcm_process_device *qpd,
++ enum cache_policy default_policy,
++ enum cache_policy alternate_policy,
++ void __user *alternate_aperture_base,
++ uint64_t alternate_aperture_size)
+ {
+- struct kfd_process_device *pdd;
+-
+- pdd = qpd_to_pdd(qpd);
+-
+- /* check if sh_mem_config register already configured */
+- if (qpd->sh_mem_config == 0) {
+- qpd->sh_mem_config =
+- (SH_MEM_ALIGNMENT_MODE_UNALIGNED <<
+- SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) |
+- (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT);
+-
+- qpd->sh_mem_ape1_limit = 0;
+- qpd->sh_mem_ape1_base = 0;
+- }
++ qpd->sh_mem_config = (SH_MEM_ALIGNMENT_MODE_UNALIGNED <<
++ SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) |
++ (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT);
+
+- qpd->sh_mem_bases = compute_sh_mem_bases_64bit(pdd);
++ qpd->sh_mem_ape1_limit = 0;
++ qpd->sh_mem_ape1_base = 0;
++ qpd->sh_mem_bases = compute_sh_mem_bases_64bit(qpd_to_pdd(qpd));
+
+ pr_debug("sh_mem_bases 0x%X\n", qpd->sh_mem_bases);
++ return true;
++}
+
++static int update_qpd_v12(struct device_queue_manager *dqm,
++ struct qcm_process_device *qpd)
++{
+ return 0;
+ }
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c
+index 210bcc048f4c5..3264509408bc8 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c
+@@ -30,10 +30,17 @@ static int update_qpd_v9(struct device_queue_manager *dqm,
+ struct qcm_process_device *qpd);
+ static void init_sdma_vm_v9(struct device_queue_manager *dqm, struct queue *q,
+ struct qcm_process_device *qpd);
++static bool set_cache_memory_policy_v9(struct device_queue_manager *dqm,
++ struct qcm_process_device *qpd,
++ enum cache_policy default_policy,
++ enum cache_policy alternate_policy,
++ void __user *alternate_aperture_base,
++ uint64_t alternate_aperture_size);
+
+ void device_queue_manager_init_v9(
+ struct device_queue_manager_asic_ops *asic_ops)
+ {
++ asic_ops->set_cache_memory_policy = set_cache_memory_policy_v9;
+ asic_ops->update_qpd = update_qpd_v9;
+ asic_ops->init_sdma_vm = init_sdma_vm_v9;
+ asic_ops->mqd_manager_init = mqd_manager_init_v9;
+@@ -48,10 +55,37 @@ static uint32_t compute_sh_mem_bases_64bit(struct kfd_process_device *pdd)
+ private_base;
+ }
+
++static bool set_cache_memory_policy_v9(struct device_queue_manager *dqm,
++ struct qcm_process_device *qpd,
++ enum cache_policy default_policy,
++ enum cache_policy alternate_policy,
++ void __user *alternate_aperture_base,
++ uint64_t alternate_aperture_size)
++{
++ qpd->sh_mem_config = SH_MEM_ALIGNMENT_MODE_UNALIGNED <<
++ SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT;
++
++ if (dqm->dev->kfd->noretry)
++ qpd->sh_mem_config |= 1 << SH_MEM_CONFIG__RETRY_DISABLE__SHIFT;
++
++ if (KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 4, 3) ||
++ KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 4, 4) ||
++ KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 5, 0))
++ qpd->sh_mem_config |= (1 << SH_MEM_CONFIG__F8_MODE__SHIFT);
++
++ qpd->sh_mem_ape1_limit = 0;
++ qpd->sh_mem_ape1_base = 0;
++ qpd->sh_mem_bases = compute_sh_mem_bases_64bit(qpd_to_pdd(qpd));
++
++ pr_debug("sh_mem_bases 0x%X sh_mem_config 0x%X\n", qpd->sh_mem_bases,
++ qpd->sh_mem_config);
++ return true;
++}
++
+ static int update_qpd_v9(struct device_queue_manager *dqm,
+ struct qcm_process_device *qpd)
+ {
+- struct kfd_process_device *pdd;
++ struct kfd_process_device *pdd = qpd_to_pdd(qpd);
+
+ pdd = qpd_to_pdd(qpd);
+
+--
+2.39.5
+
--- /dev/null
+From 48028dc3efcb6679b30408c2065dacfdf4f97af4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Mar 2025 11:08:21 -0400
+Subject: drm/amdkfd: set precise mem ops caps to disabled for gfx 11 and 12
+
+From: Jonathan Kim <jonathan.kim@amd.com>
+
+[ Upstream commit f82d27dcff939d3cbecbc60e1b71e2518c37e81d ]
+
+Clause instructions with precise memory enabled currently hang the
+shader so set capabilities flag to disabled since it's unsafe to use
+for debugging.
+
+Signed-off-by: Jonathan Kim <jonathan.kim@amd.com>
+Tested-by: Lancelot Six <lancelot.six@amd.com>
+Reviewed-by: Harish Kasiviswanathan <harish.kasiviswanathan@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+index 3871591c9aec9..bcb5cdc4a9d81 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+@@ -2002,10 +2002,6 @@ static void kfd_topology_set_capabilities(struct kfd_topology_device *dev)
+ dev->node_props.debug_prop |= HSA_DBG_WATCH_ADDR_MASK_LO_BIT_GFX10 |
+ HSA_DBG_WATCH_ADDR_MASK_HI_BIT;
+
+- if (KFD_GC_VERSION(dev->gpu) >= IP_VERSION(11, 0, 0))
+- dev->node_props.capability |=
+- HSA_CAP_TRAP_DEBUG_PRECISE_MEMORY_OPERATIONS_SUPPORTED;
+-
+ if (KFD_GC_VERSION(dev->gpu) >= IP_VERSION(12, 0, 0))
+ dev->node_props.capability |=
+ HSA_CAP_TRAP_DEBUG_PRECISE_ALU_OPERATIONS_SUPPORTED;
+--
+2.39.5
+
--- /dev/null
+From f76e569b97b0992d4a0cdddf5d38bab265130fb0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jan 2025 10:21:08 +0100
+Subject: drm/ast: Find VBIOS mode from regular display size
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit c81202906b5cd56db403e95db3d29c9dfc8c74c1 ]
+
+The ast driver looks up supplied display modes from an internal list of
+display modes supported by the VBIOS.
+
+Do not use the crtc_-prefixed display values from struct drm_display_mode
+for looking up the VBIOS mode. The fields contain raw values that the
+driver programs to hardware. They are affected by display settings like
+double-scan or interlace.
+
+Instead use the regular vdisplay and hdisplay fields for lookup. As the
+programmed values can now differ from the values used for lookup, set
+struct drm_display_mode.crtc_vdisplay and .crtc_hdisplay from the VBIOS
+mode.
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-9-tzimmermann@suse.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/ast/ast_mode.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
+index ed496fb32bf34..24ed1cd3caf17 100644
+--- a/drivers/gpu/drm/ast/ast_mode.c
++++ b/drivers/gpu/drm/ast/ast_mode.c
+@@ -131,7 +131,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format,
+ return false;
+ }
+
+- switch (mode->crtc_hdisplay) {
++ switch (mode->hdisplay) {
+ case 640:
+ vbios_mode->enh_table = &res_640x480[refresh_rate_index];
+ break;
+@@ -145,7 +145,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format,
+ vbios_mode->enh_table = &res_1152x864[refresh_rate_index];
+ break;
+ case 1280:
+- if (mode->crtc_vdisplay == 800)
++ if (mode->vdisplay == 800)
+ vbios_mode->enh_table = &res_1280x800[refresh_rate_index];
+ else
+ vbios_mode->enh_table = &res_1280x1024[refresh_rate_index];
+@@ -157,7 +157,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format,
+ vbios_mode->enh_table = &res_1440x900[refresh_rate_index];
+ break;
+ case 1600:
+- if (mode->crtc_vdisplay == 900)
++ if (mode->vdisplay == 900)
+ vbios_mode->enh_table = &res_1600x900[refresh_rate_index];
+ else
+ vbios_mode->enh_table = &res_1600x1200[refresh_rate_index];
+@@ -166,7 +166,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format,
+ vbios_mode->enh_table = &res_1680x1050[refresh_rate_index];
+ break;
+ case 1920:
+- if (mode->crtc_vdisplay == 1080)
++ if (mode->vdisplay == 1080)
+ vbios_mode->enh_table = &res_1920x1080[refresh_rate_index];
+ else
+ vbios_mode->enh_table = &res_1920x1200[refresh_rate_index];
+@@ -210,6 +210,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format,
+ hborder = (vbios_mode->enh_table->flags & HBorder) ? 8 : 0;
+ vborder = (vbios_mode->enh_table->flags & VBorder) ? 8 : 0;
+
++ adjusted_mode->crtc_hdisplay = vbios_mode->enh_table->hde;
+ adjusted_mode->crtc_htotal = vbios_mode->enh_table->ht;
+ adjusted_mode->crtc_hblank_start = vbios_mode->enh_table->hde + hborder;
+ adjusted_mode->crtc_hblank_end = vbios_mode->enh_table->ht - hborder;
+@@ -219,6 +220,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format,
+ vbios_mode->enh_table->hfp +
+ vbios_mode->enh_table->hsync);
+
++ adjusted_mode->crtc_vdisplay = vbios_mode->enh_table->vde;
+ adjusted_mode->crtc_vtotal = vbios_mode->enh_table->vt;
+ adjusted_mode->crtc_vblank_start = vbios_mode->enh_table->vde + vborder;
+ adjusted_mode->crtc_vblank_end = vbios_mode->enh_table->vt - vborder;
+--
+2.39.5
+
--- /dev/null
+From 1fdc960d1ed86da405fa14056741124b79509d5f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Jan 2025 18:24:16 +0100
+Subject: drm/atomic: clarify the rules around drm_atomic_state->allow_modeset
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Simona Vetter <simona.vetter@ffwll.ch>
+
+[ Upstream commit c5e3306a424b52e38ad2c28c7f3399fcd03e383d ]
+
+msm is automagically upgrading normal commits to full modesets, and
+that's a big no-no:
+
+- for one this results in full on->off->on transitions on all these
+ crtc, at least if you're using the usual helpers. Which seems to be
+ the case, and is breaking uapi
+
+- further even if the ctm change itself would not result in flicker,
+ this can hide modesets for other reasons. Which again breaks the
+ uapi
+
+v2: I forgot the case of adding unrelated crtc state. Add that case
+and link to the existing kerneldoc explainers. This has come up in an
+irc discussion with Manasi and Ville about intel's bigjoiner mode.
+Also cc everyone involved in the msm irc discussion, more people
+joined after I sent out v1.
+
+v3: Wording polish from Pekka and Thomas
+
+Acked-by: Pekka Paalanen <pekka.paalanen@collabora.com>
+Acked-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Cc: Maxime Ripard <mripard@kernel.org>
+Cc: Thomas Zimmermann <tzimmermann@suse.de>
+Cc: David Airlie <airlied@gmail.com>
+Cc: Daniel Vetter <daniel@ffwll.ch>
+Cc: Pekka Paalanen <pekka.paalanen@collabora.com>
+Cc: Rob Clark <robdclark@gmail.com>
+Cc: Simon Ser <contact@emersion.fr>
+Cc: Manasi Navare <navaremanasi@google.com>
+Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Cc: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Simona Vetter <simona.vetter@intel.com>
+Signed-off-by: Simona Vetter <simona.vetter@ffwll.ch>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250108172417.160831-1-simona.vetter@ffwll.ch
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/drm/drm_atomic.h | 23 +++++++++++++++++++++--
+ 1 file changed, 21 insertions(+), 2 deletions(-)
+
+diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
+index 31ca88deb10d2..1ded9a8d4e84d 100644
+--- a/include/drm/drm_atomic.h
++++ b/include/drm/drm_atomic.h
+@@ -376,8 +376,27 @@ struct drm_atomic_state {
+ *
+ * Allow full modeset. This is used by the ATOMIC IOCTL handler to
+ * implement the DRM_MODE_ATOMIC_ALLOW_MODESET flag. Drivers should
+- * never consult this flag, instead looking at the output of
+- * drm_atomic_crtc_needs_modeset().
++ * generally not consult this flag, but instead look at the output of
++ * drm_atomic_crtc_needs_modeset(). The detailed rules are:
++ *
++ * - Drivers must not consult @allow_modeset in the atomic commit path.
++ * Use drm_atomic_crtc_needs_modeset() instead.
++ *
++ * - Drivers must consult @allow_modeset before adding unrelated struct
++ * drm_crtc_state to this commit by calling
++ * drm_atomic_get_crtc_state(). See also the warning in the
++ * documentation for that function.
++ *
++ * - Drivers must never change this flag, it is under the exclusive
++ * control of userspace.
++ *
++ * - Drivers may consult @allow_modeset in the atomic check path, if
++ * they have the choice between an optimal hardware configuration
++ * which requires a modeset, and a less optimal configuration which
++ * can be committed without a modeset. An example would be suboptimal
++ * scanout FIFO allocation resulting in increased idle power
++ * consumption. This allows userspace to avoid flickering and delays
++ * for the normal composition loop at reasonable cost.
+ */
+ bool allow_modeset : 1;
+ /**
+--
+2.39.5
+
--- /dev/null
+From c86bd60f50af36d637dd6f6ce97c0d6c552cd4b4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Jan 2025 18:03:54 +0100
+Subject: drm: bridge: adv7511: fill stream capabilities
+
+From: Olivier Moysan <olivier.moysan@foss.st.com>
+
+[ Upstream commit c852646f12d4cd5b4f19eeec2976c5d98c0382f8 ]
+
+Set no_i2s_capture and no_spdif_capture flags in hdmi_codec_pdata structure
+to report that the ADV7511 HDMI bridge does not support i2s or spdif audio
+capture.
+
+Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250108170356.413063-2-olivier.moysan@foss.st.com
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/adv7511/adv7511_audio.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
+index 8f786592143b6..24e1e11acf697 100644
+--- a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
+@@ -244,7 +244,9 @@ static const struct hdmi_codec_pdata codec_data = {
+ .ops = &adv7511_codec_ops,
+ .max_i2s_channels = 2,
+ .i2s = 1,
++ .no_i2s_capture = 1,
+ .spdif = 1,
++ .no_spdif_capture = 1,
+ };
+
+ int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511)
+--
+2.39.5
+
--- /dev/null
+From d26c1182a9f8e5e54dab4211889be515be055f89 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 26 Dec 2024 12:31:15 +0530
+Subject: drm/buddy: fix issue that force_merge cannot free all roots
+
+From: Lin.Cao <lincao12@amd.com>
+
+[ Upstream commit 467dce3817bd2b62ccd6fcfd7aae76f242ac907e ]
+
+If buddy manager have more than one roots and each root have sub-block
+need to be free. When drm_buddy_fini called, the first loop of
+force_merge will merge and free all of the sub block of first root,
+which offset is 0x0 and size is biggest(more than have of the mm size).
+In subsequent force_merge rounds, if we use 0 as start and use remaining
+mm size as end, the block of other roots will be skipped in
+__force_merge function. It will cause the other roots can not be freed.
+
+Solution: use roots' offset as the start could fix this issue.
+
+Signed-off-by: Lin.Cao <lincao12@amd.com>
+Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com>
+Reviewed-by: Matthew Auld <matthew.auld@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20241226070116.309290-1-Arunpravin.PaneerSelvam@amd.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_buddy.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c
+index 103c185bb1c8a..ca42e6081d27c 100644
+--- a/drivers/gpu/drm/drm_buddy.c
++++ b/drivers/gpu/drm/drm_buddy.c
+@@ -324,7 +324,7 @@ EXPORT_SYMBOL(drm_buddy_init);
+ */
+ void drm_buddy_fini(struct drm_buddy *mm)
+ {
+- u64 root_size, size;
++ u64 root_size, size, start;
+ unsigned int order;
+ int i;
+
+@@ -332,7 +332,8 @@ void drm_buddy_fini(struct drm_buddy *mm)
+
+ for (i = 0; i < mm->n_roots; ++i) {
+ order = ilog2(size) - ilog2(mm->chunk_size);
+- __force_merge(mm, 0, size, order);
++ start = drm_buddy_block_offset(mm->roots[i]);
++ __force_merge(mm, start, start + size, order);
+
+ WARN_ON(!drm_buddy_block_is_free(mm->roots[i]));
+ drm_block_free(mm, mm->roots[i]);
+--
+2.39.5
+
--- /dev/null
+From 7df9350fe8c3338fee827a28b35418cbb55e3b8a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Feb 2025 18:03:04 +0100
+Subject: drm/gem: Test for imported GEM buffers with helper
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit b57aa47d39e94dc47403a745e2024664e544078c ]
+
+Add drm_gem_is_imported() that tests if a GEM object's buffer has
+been imported. Update the GEM code accordingly.
+
+GEM code usually tests for imports if import_attach has been set
+in struct drm_gem_object. But attaching a dma-buf on import requires
+a DMA-capable importer device, which is not the case for many serial
+busses like USB or I2C. The new helper tests if a GEM object's dma-buf
+has been created from the GEM object.
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: Anusha Srivatsa <asrivats@redhat.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250226172457.217725-2-tzimmermann@suse.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_gem.c | 4 ++--
+ include/drm/drm_gem.h | 14 ++++++++++++++
+ 2 files changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
+index 149b8e25da5bb..426d0867882df 100644
+--- a/drivers/gpu/drm/drm_gem.c
++++ b/drivers/gpu/drm/drm_gem.c
+@@ -322,7 +322,7 @@ int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
+ return -ENOENT;
+
+ /* Don't allow imported objects to be mapped */
+- if (obj->import_attach) {
++ if (drm_gem_is_imported(obj)) {
+ ret = -EINVAL;
+ goto out;
+ }
+@@ -1152,7 +1152,7 @@ void drm_gem_print_info(struct drm_printer *p, unsigned int indent,
+ drm_vma_node_start(&obj->vma_node));
+ drm_printf_indent(p, indent, "size=%zu\n", obj->size);
+ drm_printf_indent(p, indent, "imported=%s\n",
+- str_yes_no(obj->import_attach));
++ str_yes_no(drm_gem_is_imported(obj)));
+
+ if (obj->funcs->print_info)
+ obj->funcs->print_info(p, indent, obj);
+diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
+index d8b86df2ec0da..70c0f8c83629d 100644
+--- a/include/drm/drm_gem.h
++++ b/include/drm/drm_gem.h
+@@ -35,6 +35,7 @@
+ */
+
+ #include <linux/kref.h>
++#include <linux/dma-buf.h>
+ #include <linux/dma-resv.h>
+ #include <linux/list.h>
+ #include <linux/mutex.h>
+@@ -570,6 +571,19 @@ static inline bool drm_gem_object_is_shared_for_memory_stats(struct drm_gem_obje
+ return (obj->handle_count > 1) || obj->dma_buf;
+ }
+
++/**
++ * drm_gem_is_imported() - Tests if GEM object's buffer has been imported
++ * @obj: the GEM object
++ *
++ * Returns:
++ * True if the GEM object's buffer has been imported, false otherwise
++ */
++static inline bool drm_gem_is_imported(const struct drm_gem_object *obj)
++{
++ /* The dma-buf's priv field points to the original GEM object. */
++ return obj->dma_buf && (obj->dma_buf->priv != obj);
++}
++
+ #ifdef CONFIG_LOCKDEP
+ /**
+ * drm_gem_gpuva_set_lock() - Set the lock protecting accesses to the gpuva list.
+--
+2.39.5
+
--- /dev/null
+From 07d712d32f771e1511bc804275be08cdba94eb47 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 16:47:58 +0100
+Subject: drm/mediatek: mtk_dpi: Add checks for reg_h_fre_con existence
+
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+[ Upstream commit 8c9da7cd0bbcc90ab444454fecf535320456a312 ]
+
+In preparation for adding support for newer DPI instances which
+do support direct-pin but do not have any H_FRE_CON register,
+like the one found in MT8195 and MT8188, add a branch to check
+if the reg_h_fre_con variable was declared in the mtk_dpi_conf
+structure for the probed SoC DPI version.
+
+As a note, this is useful specifically only for cases in which
+the support_direct_pin variable is true, so mt8195-dpintf is
+not affected by any issue.
+
+Reviewed-by: CK Hu <ck.hu@mediatek.com>
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://patchwork.kernel.org/project/dri-devel/patch/20250217154836.108895-6-angelogioacchino.delregno@collabora.com/
+Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/mediatek/mtk_dpi.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
+index 9c11d3158324c..20a50180d4d49 100644
+--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
++++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
+@@ -410,12 +410,13 @@ static void mtk_dpi_config_swap_input(struct mtk_dpi *dpi, bool enable)
+
+ static void mtk_dpi_config_2n_h_fre(struct mtk_dpi *dpi)
+ {
+- mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, H_FRE_2N, H_FRE_2N);
++ if (dpi->conf->reg_h_fre_con)
++ mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, H_FRE_2N, H_FRE_2N);
+ }
+
+ static void mtk_dpi_config_disable_edge(struct mtk_dpi *dpi)
+ {
+- if (dpi->conf->edge_sel_en)
++ if (dpi->conf->edge_sel_en && dpi->conf->reg_h_fre_con)
+ mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, 0, EDGE_SEL_EN);
+ }
+
+--
+2.39.5
+
--- /dev/null
+From c5baf9fd2d65f57362c25a57799f36f7c4b73b74 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jan 2025 10:29:50 -0800
+Subject: drm/nouveau: fix the broken marco GSP_MSG_MAX_SIZE
+
+From: Zhi Wang <zhiw@nvidia.com>
+
+[ Upstream commit bbae6680cfe38b033250b483722e60ccd865976f ]
+
+The macro GSP_MSG_MAX_SIZE refers to another macro that doesn't exist.
+It represents the max GSP message element size.
+
+Fix the broken marco so it can be used to replace some magic numbers in
+the code.
+
+Signed-off-by: Zhi Wang <zhiw@nvidia.com>
+Signed-off-by: Danilo Krummrich <dakr@kernel.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250124182958.2040494-8-zhiw@nvidia.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
+index 9c83bab0a5309..fc84ca214f247 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
+@@ -58,7 +58,7 @@
+ #include <linux/parser.h>
+
+ #define GSP_MSG_MIN_SIZE GSP_PAGE_SIZE
+-#define GSP_MSG_MAX_SIZE GSP_PAGE_MIN_SIZE * 16
++#define GSP_MSG_MAX_SIZE (GSP_MSG_MIN_SIZE * 16)
+
+ struct r535_gsp_msg {
+ u8 auth_tag_buffer[16];
+--
+2.39.5
+
--- /dev/null
+From dc7114cb5a5a024022d466dcd59580627f04719b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 Jan 2025 14:28:53 -0800
+Subject: drm/panel-edp: Add Starry 116KHD024006
+
+From: Douglas Anderson <dianders@chromium.org>
+
+[ Upstream commit 749b5b279e5636cdcef51e15d67b77162cca6caa ]
+
+We have a few reports of sc7180-trogdor-pompom devices that have a
+panel in them that IDs as STA 0x0004 and has the following raw EDID:
+
+ 00 ff ff ff ff ff ff 00 4e 81 04 00 00 00 00 00
+ 10 20 01 04 a5 1a 0e 78 0a dc dd 96 5b 5b 91 28
+ 1f 52 54 00 00 00 01 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 8e 1c 56 a0 50 00 1e 30 28 20
+ 55 00 00 90 10 00 00 18 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fe
+ 00 31 31 36 4b 48 44 30 32 34 30 30 36 0a 00 e6
+
+We've been unable to locate a datasheet for this panel and our partner
+has not been responsive, but all Starry eDP datasheets that we can
+find agree on the same timing (delay_100_500_e200) so it should be
+safe to use that here instead of the super conservative timings. We'll
+still go a little extra conservative and allow `hpd_absent` of 200
+instead of 100 because that won't add any real-world delay in most
+cases.
+
+We'll associate the string from the EDID ("116KHD024006") with this
+panel. Given that the ID is the suspicious value of 0x0004 it seems
+likely that Starry doesn't always update their IDs but the string will
+still work to differentiate if we ever need to in the future.
+
+Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
+Signed-off-by: Douglas Anderson <dianders@chromium.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250109142853.1.Ibcc3009933fd19507cc9c713ad0c99c7a9e4fe17@changeid
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/panel/panel-edp.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c
+index 767e47a2b0c14..663af985d1b38 100644
+--- a/drivers/gpu/drm/panel/panel-edp.c
++++ b/drivers/gpu/drm/panel/panel-edp.c
+@@ -1983,6 +1983,7 @@ static const struct edp_panel_entry edp_panels[] = {
+ EDP_PANEL_ENTRY('S', 'H', 'P', 0x153a, &delay_200_500_e50, "LQ140T1JH01"),
+ EDP_PANEL_ENTRY('S', 'H', 'P', 0x154c, &delay_200_500_p2e100, "LQ116M1JW10"),
+
++ EDP_PANEL_ENTRY('S', 'T', 'A', 0x0004, &delay_200_500_e200, "116KHD024006"),
+ EDP_PANEL_ENTRY('S', 'T', 'A', 0x0100, &delay_100_500_e200, "2081116HHD028001-51D"),
+
+ { /* sentinal */ }
+--
+2.39.5
+
--- /dev/null
+From 45cdcfb087bbe8e3246d4568cb3f83a40931a5a3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Mar 2025 11:44:17 +0800
+Subject: drm/rockchip: vop2: Add uv swap for cluster window
+
+From: Andy Yan <andy.yan@rock-chips.com>
+
+[ Upstream commit e7aae9f6d762139f8d2b86db03793ae0ab3dd802 ]
+
+The Cluster windows of upcoming VOP on rk3576 also support
+linear YUV support, we need to set uv swap bit for it.
+
+As the VOP2_WIN_UV_SWA register defined on rk3568/rk3588 is
+0xffffffff, so this register will not be touched on these
+two platforms.
+
+Signed-off-by: Andy Yan <andy.yan@rock-chips.com>
+Tested-by: Michael Riesch <michael.riesch@wolfvision.net> # on RK3568
+Tested-by: Detlev Casanova <detlev.casanova@collabora.com>
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250303034436.192400-4-andyshrk@163.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+index 5880d87fe6b3a..2aab2a0956788 100644
+--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+@@ -1432,10 +1432,8 @@ static void vop2_plane_atomic_update(struct drm_plane *plane,
+
+ rb_swap = vop2_win_rb_swap(fb->format->format);
+ vop2_win_write(win, VOP2_WIN_RB_SWAP, rb_swap);
+- if (!vop2_cluster_window(win)) {
+- uv_swap = vop2_win_uv_swap(fb->format->format);
+- vop2_win_write(win, VOP2_WIN_UV_SWAP, uv_swap);
+- }
++ uv_swap = vop2_win_uv_swap(fb->format->format);
++ vop2_win_write(win, VOP2_WIN_UV_SWAP, uv_swap);
+
+ if (fb->format->is_yuv) {
+ vop2_win_write(win, VOP2_WIN_UV_VIR, DIV_ROUND_UP(fb->pitches[1], 4));
+--
+2.39.5
+
--- /dev/null
+From 5d95e19f07a4207466eb8fd3252d63dbb48bf377 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Feb 2025 14:40:06 +0200
+Subject: drm/rockchip: vop2: Improve display modes handling on RK3588 HDMI0
+
+From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
+
+[ Upstream commit 2c1268e7aad0819f38e56134bbc2095fd95fde1b ]
+
+The RK3588 specific implementation is currently quite limited in terms
+of handling the full range of display modes supported by the connected
+screens, e.g. 2560x1440@75Hz, 2048x1152@60Hz, 1024x768@60Hz are just a
+few of them.
+
+Additionally, it doesn't cope well with non-integer refresh rates like
+59.94, 29.97, 23.98, etc.
+
+Make use of HDMI0 PHY PLL as a more accurate DCLK source to handle
+all display modes up to 4K@60Hz.
+
+Tested-by: FUKAUMI Naoki <naoki@radxa.com>
+Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250204-vop2-hdmi0-disp-modes-v3-3-d71c6a196e58@collabora.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 34 ++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+
+diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+index 2aab2a0956788..5d7df4c3b08c4 100644
+--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+@@ -157,6 +157,7 @@ struct vop2_video_port {
+ struct drm_crtc crtc;
+ struct vop2 *vop2;
+ struct clk *dclk;
++ struct clk *dclk_src;
+ unsigned int id;
+ const struct vop2_video_port_data *data;
+
+@@ -211,6 +212,7 @@ struct vop2 {
+ struct clk *hclk;
+ struct clk *aclk;
+ struct clk *pclk;
++ struct clk *pll_hdmiphy0;
+
+ /* optional internal rgb encoder */
+ struct rockchip_rgb *rgb;
+@@ -219,6 +221,8 @@ struct vop2 {
+ struct vop2_win win[];
+ };
+
++#define VOP2_MAX_DCLK_RATE 600000000
++
+ #define vop2_output_if_is_hdmi(x) ((x) == ROCKCHIP_VOP2_EP_HDMI0 || \
+ (x) == ROCKCHIP_VOP2_EP_HDMI1)
+
+@@ -1051,6 +1055,9 @@ static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
+
+ vop2_crtc_disable_irq(vp, VP_INT_DSP_HOLD_VALID);
+
++ if (vp->dclk_src)
++ clk_set_parent(vp->dclk, vp->dclk_src);
++
+ clk_disable_unprepare(vp->dclk);
+
+ vop2->enable_count--;
+@@ -2071,6 +2078,27 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc,
+
+ vop2_vp_write(vp, RK3568_VP_MIPI_CTRL, 0);
+
++ /*
++ * Switch to HDMI PHY PLL as DCLK source for display modes up
++ * to 4K@60Hz, if available, otherwise keep using the system CRU.
++ */
++ if (vop2->pll_hdmiphy0 && clock <= VOP2_MAX_DCLK_RATE) {
++ drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) {
++ struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
++
++ if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI0) {
++ if (!vp->dclk_src)
++ vp->dclk_src = clk_get_parent(vp->dclk);
++
++ ret = clk_set_parent(vp->dclk, vop2->pll_hdmiphy0);
++ if (ret < 0)
++ drm_warn(vop2->drm,
++ "Could not switch to HDMI0 PHY PLL: %d\n", ret);
++ break;
++ }
++ }
++ }
++
+ clk_set_rate(vp->dclk, clock);
+
+ vop2_post_config(crtc);
+@@ -3242,6 +3270,12 @@ static int vop2_bind(struct device *dev, struct device *master, void *data)
+ return PTR_ERR(vop2->pclk);
+ }
+
++ vop2->pll_hdmiphy0 = devm_clk_get_optional(vop2->dev, "pll_hdmiphy0");
++ if (IS_ERR(vop2->pll_hdmiphy0)) {
++ drm_err(vop2->drm, "failed to get pll_hdmiphy0\n");
++ return PTR_ERR(vop2->pll_hdmiphy0);
++ }
++
+ vop2->irq = platform_get_irq(pdev, 0);
+ if (vop2->irq < 0) {
+ drm_err(vop2->drm, "cannot find irq for vop2\n");
+--
+2.39.5
+
--- /dev/null
+From 78a6a9639f1cc6e50a745e5ee68efa1270fd4e46 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 13:50:46 +0100
+Subject: drm/v3d: Add clock handling
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Stefan Wahren <wahrenst@gmx.net>
+
+[ Upstream commit 4dd40b5f9c3d89b67af0dbe059cf4a51aac6bf06 ]
+
+Since the initial commit 57692c94dcbe ("drm/v3d: Introduce a new DRM driver
+for Broadcom V3D V3.x+") the struct v3d_dev reserved a pointer for
+an optional V3D clock. But there wasn't any code, which fetched it.
+So add the missing clock handling before accessing any V3D registers.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+Reviewed-by: Maíra Canal <mcanal@igalia.com>
+Signed-off-by: Maíra Canal <mcanal@igalia.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250201125046.33030-1-wahrenst@gmx.net
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/v3d/v3d_drv.c | 25 ++++++++++++++++++++-----
+ 1 file changed, 20 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c
+index d7ff1f5fa481f..7c17108da7d2d 100644
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -286,11 +286,21 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
+ if (ret)
+ return ret;
+
++ v3d->clk = devm_clk_get_optional(dev, NULL);
++ if (IS_ERR(v3d->clk))
++ return dev_err_probe(dev, PTR_ERR(v3d->clk), "Failed to get V3D clock\n");
++
++ ret = clk_prepare_enable(v3d->clk);
++ if (ret) {
++ dev_err(&pdev->dev, "Couldn't enable the V3D clock\n");
++ return ret;
++ }
++
+ mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO);
+ mask = DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH));
+ ret = dma_set_mask_and_coherent(dev, mask);
+ if (ret)
+- return ret;
++ goto clk_disable;
+
+ v3d->va_width = 30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_VA_WIDTH);
+
+@@ -310,28 +320,29 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
+ ret = PTR_ERR(v3d->reset);
+
+ if (ret == -EPROBE_DEFER)
+- return ret;
++ goto clk_disable;
+
+ v3d->reset = NULL;
+ ret = map_regs(v3d, &v3d->bridge_regs, "bridge");
+ if (ret) {
+ dev_err(dev,
+ "Failed to get reset control or bridge regs\n");
+- return ret;
++ goto clk_disable;
+ }
+ }
+
+ if (v3d->ver < 41) {
+ ret = map_regs(v3d, &v3d->gca_regs, "gca");
+ if (ret)
+- return ret;
++ goto clk_disable;
+ }
+
+ v3d->mmu_scratch = dma_alloc_wc(dev, 4096, &v3d->mmu_scratch_paddr,
+ GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO);
+ if (!v3d->mmu_scratch) {
+ dev_err(dev, "Failed to allocate MMU scratch page\n");
+- return -ENOMEM;
++ ret = -ENOMEM;
++ goto clk_disable;
+ }
+
+ ret = v3d_gem_init(drm);
+@@ -360,6 +371,8 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
+ v3d_gem_destroy(drm);
+ dma_free:
+ dma_free_wc(dev, 4096, v3d->mmu_scratch, v3d->mmu_scratch_paddr);
++clk_disable:
++ clk_disable_unprepare(v3d->clk);
+ return ret;
+ }
+
+@@ -377,6 +390,8 @@ static void v3d_platform_drm_remove(struct platform_device *pdev)
+
+ dma_free_wc(v3d->drm.dev, 4096, v3d->mmu_scratch,
+ v3d->mmu_scratch_paddr);
++
++ clk_disable_unprepare(v3d->clk);
+ }
+
+ static struct platform_driver v3d_platform_driver = {
+--
+2.39.5
+
--- /dev/null
+From b7870dbafbf39915dd942704700f6a88f4a90d32 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 23:03:22 +0000
+Subject: drm/xe/debugfs: Add missing xe_pm_runtime_put in wedge_mode_set
+
+From: Shuicheng Lin <shuicheng.lin@intel.com>
+
+[ Upstream commit b31e668d3111b100d16fd7db8db335328ce8c6d5 ]
+
+xe_pm_runtime_put is missed in the failure path.
+
+Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Shuicheng Lin <shuicheng.lin@intel.com>
+Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250213230322.1180621-1-shuicheng.lin@intel.com
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_debugfs.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c
+index 051a37e477f4c..278ce1c37b395 100644
+--- a/drivers/gpu/drm/xe/xe_debugfs.c
++++ b/drivers/gpu/drm/xe/xe_debugfs.c
+@@ -156,6 +156,7 @@ static ssize_t wedged_mode_set(struct file *f, const char __user *ubuf,
+ ret = xe_guc_ads_scheduler_policy_toggle_reset(>->uc.guc.ads);
+ if (ret) {
+ xe_gt_err(gt, "Failed to update GuC ADS scheduler policy. GuC may still cause engine reset even with wedged_mode=2\n");
++ xe_pm_runtime_put(xe);
+ return -EIO;
+ }
+ }
+--
+2.39.5
+
--- /dev/null
+From ab7e96abd815d7e340e80fc664ba083efd440bd5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Feb 2025 06:36:15 +0800
+Subject: drm/xe/debugfs: fixed the return value of wedged_mode_set
+
+From: Xin Wang <x.wang@intel.com>
+
+[ Upstream commit 6884d2051011f4db9e2f0b85709c79a8ced13bd6 ]
+
+It is generally expected that the write() function should return a
+positive value indicating the number of bytes written or a negative
+error code if an error occurs. Returning 0 is unusual and can lead
+to unexpected behavior.
+
+When the user program writes the same value to wedged_mode twice in
+a row, a lockup will occur, because the value expected to be
+returned by the write() function inside the program should be equal
+to the actual written value instead of 0.
+
+To reproduce the issue:
+echo 1 > /sys/kernel/debug/dri/0/wedged_mode
+echo 1 > /sys/kernel/debug/dri/0/wedged_mode <- lockup here
+
+Signed-off-by: Xin Wang <x.wang@intel.com>
+Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Cc: Fei Yang <fei.yang@intel.com>
+Cc: Shuicheng Lin <shuicheng.lin@intel.com>
+Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250213223615.2327367-1-x.wang@intel.com
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_debugfs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c
+index fe4319eb13fdf..051a37e477f4c 100644
+--- a/drivers/gpu/drm/xe/xe_debugfs.c
++++ b/drivers/gpu/drm/xe/xe_debugfs.c
+@@ -147,7 +147,7 @@ static ssize_t wedged_mode_set(struct file *f, const char __user *ubuf,
+ return -EINVAL;
+
+ if (xe->wedged.mode == wedged_mode)
+- return 0;
++ return size;
+
+ xe->wedged.mode = wedged_mode;
+
+--
+2.39.5
+
--- /dev/null
+From 165f697b004adee0fb19c978e1aa51285033a814 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Dec 2024 09:31:11 +0100
+Subject: drm/xe: Do not attempt to bootstrap VF in execlists mode
+
+From: Maarten Lankhorst <dev@lankhorst.se>
+
+[ Upstream commit f3b59457808f61d88178b0afa67cbd017d7ce79e ]
+
+It was mentioned in a review that there is a possibility of choosing
+to load the module with VF in execlists mode.
+
+Of course this doesn't work, just bomb out as hard as possible.
+
+Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20241210083111.230484-12-dev@lankhorst.se
+Signed-off-by: Maarten Lankhorst <dev@lankhorst.se>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
+index 7ddbfeaf494ac..29badbd829ab6 100644
+--- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
++++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
+@@ -235,6 +235,9 @@ int xe_gt_sriov_vf_bootstrap(struct xe_gt *gt)
+ {
+ int err;
+
++ if (!xe_device_uc_enabled(gt_to_xe(gt)))
++ return -ENODEV;
++
+ err = vf_reset_guc_state(gt);
+ if (unlikely(err))
+ return err;
+--
+2.39.5
+
--- /dev/null
+From fb59012fe3561c58691dbc7d176a79dbfa4c1151 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 11:29:00 -0800
+Subject: drm/xe: Fix xe_tile_init_noalloc() error propagation
+
+From: Lucas De Marchi <lucas.demarchi@intel.com>
+
+[ Upstream commit 0bcf41171c64234e79eb3552d00f0aad8a47e8d3 ]
+
+Propagate the error to the caller so initialization properly stops if
+sysfs creation fails.
+
+Reviewed-by: Francois Dugast <francois.dugast@intel.com>
+Reviewed-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250213192909.996148-4-lucas.demarchi@intel.com
+Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_tile.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_tile.c b/drivers/gpu/drm/xe/xe_tile.c
+index dda5268507d8e..349beddf9b383 100644
+--- a/drivers/gpu/drm/xe/xe_tile.c
++++ b/drivers/gpu/drm/xe/xe_tile.c
+@@ -173,9 +173,7 @@ int xe_tile_init_noalloc(struct xe_tile *tile)
+
+ xe_wa_apply_tile_workarounds(tile);
+
+- err = xe_tile_sysfs_init(tile);
+-
+- return 0;
++ return xe_tile_sysfs_init(tile);
+ }
+
+ void xe_tile_migrate_wait(struct xe_tile *tile)
+--
+2.39.5
+
--- /dev/null
+From acd17cb06774cbae2e84c2c9397c14dc62a621c3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Dec 2024 09:31:03 +0100
+Subject: drm/xe: Move suballocator init to after display init
+
+From: Maarten Lankhorst <dev@lankhorst.se>
+
+[ Upstream commit 380b0cdaa76bc8f5c16db16eaf48751e792ff041 ]
+
+No allocations should be done before we have had a chance to preserve
+the display fb.
+
+Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20241210083111.230484-4-dev@lankhorst.se
+Signed-off-by: Maarten Lankhorst <dev@lankhorst.se>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_device.c | 6 ++++++
+ drivers/gpu/drm/xe/xe_tile.c | 12 ++++++++----
+ drivers/gpu/drm/xe/xe_tile.h | 1 +
+ 3 files changed, 15 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
+index 5c37bed3c948f..23e02372a49db 100644
+--- a/drivers/gpu/drm/xe/xe_device.c
++++ b/drivers/gpu/drm/xe/xe_device.c
+@@ -708,6 +708,12 @@ int xe_device_probe(struct xe_device *xe)
+ if (err)
+ goto err;
+
++ for_each_tile(tile, xe, id) {
++ err = xe_tile_init(tile);
++ if (err)
++ goto err;
++ }
++
+ for_each_gt(gt, xe, id) {
+ last_gt = id;
+
+diff --git a/drivers/gpu/drm/xe/xe_tile.c b/drivers/gpu/drm/xe/xe_tile.c
+index 349beddf9b383..36c87d7c72fbc 100644
+--- a/drivers/gpu/drm/xe/xe_tile.c
++++ b/drivers/gpu/drm/xe/xe_tile.c
+@@ -167,15 +167,19 @@ int xe_tile_init_noalloc(struct xe_tile *tile)
+ if (err)
+ return err;
+
+- tile->mem.kernel_bb_pool = xe_sa_bo_manager_init(tile, SZ_1M, 16);
+- if (IS_ERR(tile->mem.kernel_bb_pool))
+- return PTR_ERR(tile->mem.kernel_bb_pool);
+-
+ xe_wa_apply_tile_workarounds(tile);
+
+ return xe_tile_sysfs_init(tile);
+ }
+
++int xe_tile_init(struct xe_tile *tile)
++{
++ tile->mem.kernel_bb_pool = xe_sa_bo_manager_init(tile, SZ_1M, 16);
++ if (IS_ERR(tile->mem.kernel_bb_pool))
++ return PTR_ERR(tile->mem.kernel_bb_pool);
++
++ return 0;
++}
+ void xe_tile_migrate_wait(struct xe_tile *tile)
+ {
+ xe_migrate_wait(tile->migrate);
+diff --git a/drivers/gpu/drm/xe/xe_tile.h b/drivers/gpu/drm/xe/xe_tile.h
+index 1c9e42ade6b05..eb939316d55b0 100644
+--- a/drivers/gpu/drm/xe/xe_tile.h
++++ b/drivers/gpu/drm/xe/xe_tile.h
+@@ -12,6 +12,7 @@ struct xe_tile;
+
+ int xe_tile_init_early(struct xe_tile *tile, struct xe_device *xe, u8 id);
+ int xe_tile_init_noalloc(struct xe_tile *tile);
++int xe_tile_init(struct xe_tile *tile);
+
+ void xe_tile_migrate_wait(struct xe_tile *tile);
+
+--
+2.39.5
+
--- /dev/null
+From 10a56087e0e9b09cab3bdb77c29571dc36d4547b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Mar 2025 17:26:36 -0800
+Subject: drm/xe: Nuke VM's mapping upon close
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Matthew Brost <matthew.brost@intel.com>
+
+[ Upstream commit 074e40d9c2a84939fe28d7121d3469db50f34a3d ]
+
+Clear root PT entry and invalidate entire VM's address space when
+closing the VM. Will prevent the GPU from accessing any of the VM's
+memory after closing.
+
+v2:
+ - s/vma/vm in kernel doc (CI)
+ - Don't nuke migration VM as this occur at driver unload (CI)
+v3:
+ - Rebase and pull into SVM series (Thomas)
+ - Wait for pending binds (Thomas)
+v5:
+ - Remove xe_gt_tlb_invalidation_fence_fini in error case (Matt Auld)
+ - Drop local migration bool (Thomas)
+v7:
+ - Add drm_dev_enter/exit protecting invalidation (CI, Matt Auld)
+
+Signed-off-by: Matthew Brost <matthew.brost@intel.com>
+Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250306012657.3505757-12-matthew.brost@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c | 22 ++++++++++++++
+ drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h | 2 ++
+ drivers/gpu/drm/xe/xe_pt.c | 14 +++++++++
+ drivers/gpu/drm/xe/xe_pt.h | 3 ++
+ drivers/gpu/drm/xe/xe_vm.c | 32 +++++++++++++++++++++
+ 5 files changed, 73 insertions(+)
+
+diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
+index 98a450271f5ce..3155825fa46ad 100644
+--- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
++++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
+@@ -406,6 +406,28 @@ int xe_gt_tlb_invalidation_range(struct xe_gt *gt,
+ return send_tlb_invalidation(>->uc.guc, fence, action, len);
+ }
+
++/**
++ * xe_gt_tlb_invalidation_vm - Issue a TLB invalidation on this GT for a VM
++ * @gt: graphics tile
++ * @vm: VM to invalidate
++ *
++ * Invalidate entire VM's address space
++ */
++void xe_gt_tlb_invalidation_vm(struct xe_gt *gt, struct xe_vm *vm)
++{
++ struct xe_gt_tlb_invalidation_fence fence;
++ u64 range = 1ull << vm->xe->info.va_bits;
++ int ret;
++
++ xe_gt_tlb_invalidation_fence_init(gt, &fence, true);
++
++ ret = xe_gt_tlb_invalidation_range(gt, &fence, 0, range, vm->usm.asid);
++ if (ret < 0)
++ return;
++
++ xe_gt_tlb_invalidation_fence_wait(&fence);
++}
++
+ /**
+ * xe_gt_tlb_invalidation_vma - Issue a TLB invalidation on this GT for a VMA
+ * @gt: graphics tile
+diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
+index 672acfcdf0d70..abe9b03d543e6 100644
+--- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
++++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
+@@ -12,6 +12,7 @@
+
+ struct xe_gt;
+ struct xe_guc;
++struct xe_vm;
+ struct xe_vma;
+
+ int xe_gt_tlb_invalidation_init_early(struct xe_gt *gt);
+@@ -21,6 +22,7 @@ int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt);
+ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
+ struct xe_gt_tlb_invalidation_fence *fence,
+ struct xe_vma *vma);
++void xe_gt_tlb_invalidation_vm(struct xe_gt *gt, struct xe_vm *vm);
+ int xe_gt_tlb_invalidation_range(struct xe_gt *gt,
+ struct xe_gt_tlb_invalidation_fence *fence,
+ u64 start, u64 end, u32 asid);
+diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
+index 230cf47fb9c5e..fb94ff55c7361 100644
+--- a/drivers/gpu/drm/xe/xe_pt.c
++++ b/drivers/gpu/drm/xe/xe_pt.c
+@@ -217,6 +217,20 @@ void xe_pt_destroy(struct xe_pt *pt, u32 flags, struct llist_head *deferred)
+ xe_pt_free(pt);
+ }
+
++/**
++ * xe_pt_clear() - Clear a page-table.
++ * @xe: xe device.
++ * @pt: The page-table.
++ *
++ * Clears page-table by setting to zero.
++ */
++void xe_pt_clear(struct xe_device *xe, struct xe_pt *pt)
++{
++ struct iosys_map *map = &pt->bo->vmap;
++
++ xe_map_memset(xe, map, 0, 0, SZ_4K);
++}
++
+ /**
+ * DOC: Pagetable building
+ *
+diff --git a/drivers/gpu/drm/xe/xe_pt.h b/drivers/gpu/drm/xe/xe_pt.h
+index 9ab386431cadd..8e43912ae8e94 100644
+--- a/drivers/gpu/drm/xe/xe_pt.h
++++ b/drivers/gpu/drm/xe/xe_pt.h
+@@ -13,6 +13,7 @@ struct dma_fence;
+ struct xe_bo;
+ struct xe_device;
+ struct xe_exec_queue;
++struct xe_svm_range;
+ struct xe_sync_entry;
+ struct xe_tile;
+ struct xe_vm;
+@@ -35,6 +36,8 @@ void xe_pt_populate_empty(struct xe_tile *tile, struct xe_vm *vm,
+
+ void xe_pt_destroy(struct xe_pt *pt, u32 flags, struct llist_head *deferred);
+
++void xe_pt_clear(struct xe_device *xe, struct xe_pt *pt);
++
+ int xe_pt_update_ops_prepare(struct xe_tile *tile, struct xe_vma_ops *vops);
+ struct dma_fence *xe_pt_update_ops_run(struct xe_tile *tile,
+ struct xe_vma_ops *vops);
+diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
+index 872de052d670f..de257a032225f 100644
+--- a/drivers/gpu/drm/xe/xe_vm.c
++++ b/drivers/gpu/drm/xe/xe_vm.c
+@@ -8,6 +8,7 @@
+ #include <linux/dma-fence-array.h>
+ #include <linux/nospec.h>
+
++#include <drm/drm_drv.h>
+ #include <drm/drm_exec.h>
+ #include <drm/drm_print.h>
+ #include <drm/ttm/ttm_execbuf_util.h>
+@@ -1581,9 +1582,40 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
+
+ static void xe_vm_close(struct xe_vm *vm)
+ {
++ struct xe_device *xe = vm->xe;
++ bool bound;
++ int idx;
++
++ bound = drm_dev_enter(&xe->drm, &idx);
++
+ down_write(&vm->lock);
++
+ vm->size = 0;
++
++ if (!((vm->flags & XE_VM_FLAG_MIGRATION))) {
++ struct xe_tile *tile;
++ struct xe_gt *gt;
++ u8 id;
++
++ /* Wait for pending binds */
++ dma_resv_wait_timeout(xe_vm_resv(vm),
++ DMA_RESV_USAGE_BOOKKEEP,
++ false, MAX_SCHEDULE_TIMEOUT);
++
++ if (bound) {
++ for_each_tile(tile, xe, id)
++ if (vm->pt_root[id])
++ xe_pt_clear(xe, vm->pt_root[id]);
++
++ for_each_gt(gt, xe, id)
++ xe_gt_tlb_invalidation_vm(gt, vm);
++ }
++ }
++
+ up_write(&vm->lock);
++
++ if (bound)
++ drm_dev_exit(idx);
+ }
+
+ void xe_vm_close_and_put(struct xe_vm *vm)
+--
+2.39.5
+
--- /dev/null
+From 00a740e47856d1144802612c0e54444f034601e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Feb 2025 17:02:55 -0800
+Subject: drm/xe/oa: Ensure that polled read returns latest data
+
+From: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
+
+[ Upstream commit 98c9d27ab30aa9c6451d3a34e6e297171f273e51 ]
+
+In polled mode, user calls poll() for read data to be available before
+performing a read(). In the duration between these 2 calls, there may be
+new data available in the OA buffer. To ensure user reads all available
+data, check for latest data in the OA buffer in polled read.
+
+Signed-off-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
+Reviewed-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250212010255.1423343-1-umesh.nerlige.ramappa@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_oa.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c
+index 448766033690c..d306ed0a04434 100644
+--- a/drivers/gpu/drm/xe/xe_oa.c
++++ b/drivers/gpu/drm/xe/xe_oa.c
+@@ -535,6 +535,7 @@ static ssize_t xe_oa_read(struct file *file, char __user *buf,
+ mutex_unlock(&stream->stream_lock);
+ } while (!offset && !ret);
+ } else {
++ xe_oa_buffer_check_unlocked(stream);
+ mutex_lock(&stream->stream_lock);
+ ret = __xe_oa_read(stream, buf, count, &offset);
+ mutex_unlock(&stream->stream_lock);
+--
+2.39.5
+
--- /dev/null
+From 3867bffca01d5688d355a7fdbdc3abff028ec0f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 15:58:06 +0530
+Subject: drm/xe/pf: Create a link between PF and VF devices
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Satyanarayana K V P <satyanarayana.k.v.p@intel.com>
+
+[ Upstream commit 8c0aff7d92e2be25717669eb65a81a89740a24f2 ]
+
+When both PF and VF devices are enabled on the host, they
+resume simultaneously during system resume.
+
+However, the PF must finish provisioning the VF before any
+VFs can successfully resume.
+
+Establish a parent-child device link between the PF and VF
+devices to ensure the correct order of resumption.
+
+V4 -> V5:
+- Added missing break in the error condition.
+V3 -> V4:
+- Made xe_pci_pf_get_vf_dev() as a static function and updated
+ input parameter types.
+- Updated xe_sriov_warn() to xe_sriov_abort() when VF device
+ cannot be found.
+V2 -> V3:
+- Added function documentation for xe_pci_pf_get_vf_dev().
+- Added assertion if not called from PF.
+V1 -> V2:
+- Added a helper function to get VF pci_dev.
+- Updated xe_sriov_notice() to xe_sriov_warn() if vf pci_dev
+ is not found.
+
+Signed-off-by: Satyanarayana K V P <satyanarayana.k.v.p@intel.com>
+Cc: Michał Wajdeczko <michal.wajdeczko@intel.com>
+Cc: Michał Winiarski <michal.winiarski@intel.com>
+Cc: Piotr Piórkowski <piotr.piorkowski@intel.com>
+Reviewed-by: Piotr Piorkowski <piotr.piorkowski@intel.com>
+Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250224102807.11065-2-satyanarayana.k.v.p@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_pci_sriov.c | 51 +++++++++++++++++++++++++++++++
+ 1 file changed, 51 insertions(+)
+
+diff --git a/drivers/gpu/drm/xe/xe_pci_sriov.c b/drivers/gpu/drm/xe/xe_pci_sriov.c
+index aaceee748287e..09ee8a06fe2ed 100644
+--- a/drivers/gpu/drm/xe/xe_pci_sriov.c
++++ b/drivers/gpu/drm/xe/xe_pci_sriov.c
+@@ -62,6 +62,55 @@ static void pf_reset_vfs(struct xe_device *xe, unsigned int num_vfs)
+ xe_gt_sriov_pf_control_trigger_flr(gt, n);
+ }
+
++static struct pci_dev *xe_pci_pf_get_vf_dev(struct xe_device *xe, unsigned int vf_id)
++{
++ struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
++
++ xe_assert(xe, IS_SRIOV_PF(xe));
++
++ /* caller must use pci_dev_put() */
++ return pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus),
++ pdev->bus->number,
++ pci_iov_virtfn_devfn(pdev, vf_id));
++}
++
++static void pf_link_vfs(struct xe_device *xe, int num_vfs)
++{
++ struct pci_dev *pdev_pf = to_pci_dev(xe->drm.dev);
++ struct device_link *link;
++ struct pci_dev *pdev_vf;
++ unsigned int n;
++
++ /*
++ * When both PF and VF devices are enabled on the host, during system
++ * resume they are resuming in parallel.
++ *
++ * But PF has to complete the provision of VF first to allow any VFs to
++ * successfully resume.
++ *
++ * Create a parent-child device link between PF and VF devices that will
++ * enforce correct resume order.
++ */
++ for (n = 1; n <= num_vfs; n++) {
++ pdev_vf = xe_pci_pf_get_vf_dev(xe, n - 1);
++
++ /* unlikely, something weird is happening, abort */
++ if (!pdev_vf) {
++ xe_sriov_err(xe, "Cannot find VF%u device, aborting link%s creation!\n",
++ n, str_plural(num_vfs));
++ break;
++ }
++
++ link = device_link_add(&pdev_vf->dev, &pdev_pf->dev,
++ DL_FLAG_AUTOREMOVE_CONSUMER);
++ /* unlikely and harmless, continue with other VFs */
++ if (!link)
++ xe_sriov_notice(xe, "Failed linking VF%u\n", n);
++
++ pci_dev_put(pdev_vf);
++ }
++}
++
+ static int pf_enable_vfs(struct xe_device *xe, int num_vfs)
+ {
+ struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
+@@ -92,6 +141,8 @@ static int pf_enable_vfs(struct xe_device *xe, int num_vfs)
+ if (err < 0)
+ goto failed;
+
++ pf_link_vfs(xe, num_vfs);
++
+ xe_sriov_info(xe, "Enabled %u of %u VF%s\n",
+ num_vfs, total_vfs, str_plural(total_vfs));
+ return num_vfs;
+--
+2.39.5
+
--- /dev/null
+From 7f110a9fb626ffb2db99ea1be7decb372b4c172e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jan 2025 20:59:47 +0100
+Subject: drm/xe/pf: Reset GuC VF config when unprovisioning critical resource
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Michal Wajdeczko <michal.wajdeczko@intel.com>
+
+[ Upstream commit 33f17e2cbd930a2a00eb007d9b241b6db010a880 ]
+
+GuC firmware counts received VF configuration KLVs and may start
+validation of the complete VF config even if some resources where
+unprovisioned in the meantime, leading to unexpected errors like:
+
+ $ echo 1 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/contexts_quota
+ $ echo 0 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/contexts_quota
+ $ echo 1 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/doorbells_quota
+ $ echo 0 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/doorbells_quota
+ $ echo 1 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/ggtt_quota
+ tee: '/sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/ggtt_quota': Input/output error
+
+To mitigate this problem trigger explicit VF config reset after
+unprovisioning any of the critical resources (GGTT, context or
+doorbell IDs) that GuC is monitoring.
+
+Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
+Reviewed-by: Michał Winiarski <michal.winiarski@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250129195947.764-3-michal.wajdeczko@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 37 +++++++++++++++++++---
+ 1 file changed, 33 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
+index c9ed996b9cb0c..786f0dba41437 100644
+--- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
++++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
+@@ -323,6 +323,26 @@ static int pf_push_full_vf_config(struct xe_gt *gt, unsigned int vfid)
+ return err;
+ }
+
++static int pf_push_vf_cfg(struct xe_gt *gt, unsigned int vfid, bool reset)
++{
++ int err = 0;
++
++ xe_gt_assert(gt, vfid);
++ lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt));
++
++ if (reset)
++ err = pf_send_vf_cfg_reset(gt, vfid);
++ if (!err)
++ err = pf_push_full_vf_config(gt, vfid);
++
++ return err;
++}
++
++static int pf_refresh_vf_cfg(struct xe_gt *gt, unsigned int vfid)
++{
++ return pf_push_vf_cfg(gt, vfid, true);
++}
++
+ static u64 pf_get_ggtt_alignment(struct xe_gt *gt)
+ {
+ struct xe_device *xe = gt_to_xe(gt);
+@@ -419,6 +439,10 @@ static int pf_provision_vf_ggtt(struct xe_gt *gt, unsigned int vfid, u64 size)
+ return err;
+
+ pf_release_vf_config_ggtt(gt, config);
++
++ err = pf_refresh_vf_cfg(gt, vfid);
++ if (unlikely(err))
++ return err;
+ }
+ xe_gt_assert(gt, !xe_ggtt_node_allocated(config->ggtt_region));
+
+@@ -744,6 +768,10 @@ static int pf_provision_vf_ctxs(struct xe_gt *gt, unsigned int vfid, u32 num_ctx
+ return ret;
+
+ pf_release_config_ctxs(gt, config);
++
++ ret = pf_refresh_vf_cfg(gt, vfid);
++ if (unlikely(ret))
++ return ret;
+ }
+
+ if (!num_ctxs)
+@@ -1041,6 +1069,10 @@ static int pf_provision_vf_dbs(struct xe_gt *gt, unsigned int vfid, u32 num_dbs)
+ return ret;
+
+ pf_release_config_dbs(gt, config);
++
++ ret = pf_refresh_vf_cfg(gt, vfid);
++ if (unlikely(ret))
++ return ret;
+ }
+
+ if (!num_dbs)
+@@ -2003,10 +2035,7 @@ int xe_gt_sriov_pf_config_push(struct xe_gt *gt, unsigned int vfid, bool refresh
+ xe_gt_assert(gt, vfid);
+
+ mutex_lock(xe_gt_sriov_pf_master_mutex(gt));
+- if (refresh)
+- err = pf_send_vf_cfg_reset(gt, vfid);
+- if (!err)
+- err = pf_push_full_vf_config(gt, vfid);
++ err = pf_push_vf_cfg(gt, vfid, refresh);
+ mutex_unlock(xe_gt_sriov_pf_master_mutex(gt));
+
+ if (unlikely(err)) {
+--
+2.39.5
+
--- /dev/null
+From 777504a7d8edce1c8426c06caff06fe874446ee6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Jan 2025 16:01:37 -0500
+Subject: drm/xe: Reject BO eviction if BO is bound to current VM
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Oak Zeng <oak.zeng@intel.com>
+
+[ Upstream commit 0af944f0e3082ff517958b1cea76fb9b8cb379dd ]
+
+This is a follow up fix for
+https://patchwork.freedesktop.org/patch/msgid/20241203021929.1919730-1-oak.zeng@intel.com
+The overall goal is to fail vm_bind when there is memory pressure. See more
+details in the commit message of above patch. Abbove patch fixes the issue
+when user pass in a vm_id parameter during gem_create. If user doesn't pass
+in a vm_id during gem_create, above patch doesn't help.
+
+This patch further reject BO eviction (which could be triggered by bo validation)
+if BO is bound to the current VM. vm_bind could fail due to the eviction failure.
+The BO to VM reverse mapping structure is used to determine whether BO is bound
+to VM.
+
+v2:
+Move vm_bo definition from function scope to if(evict) clause (Thomas)
+Further constraint the condition by adding ctx->resv (Thomas)
+Add a short comment describe the change.
+
+Suggested-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Signed-off-by: Oak Zeng <oak.zeng@intel.com>
+Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250110210137.3181576-1-oak.zeng@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_bo.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
+index 35a8242a9f541..8acc4640f0a28 100644
+--- a/drivers/gpu/drm/xe/xe_bo.c
++++ b/drivers/gpu/drm/xe/xe_bo.c
+@@ -702,6 +702,21 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict,
+ goto out;
+ }
+
++ /* Reject BO eviction if BO is bound to current VM. */
++ if (evict && ctx->resv) {
++ struct drm_gpuvm_bo *vm_bo;
++
++ drm_gem_for_each_gpuvm_bo(vm_bo, &bo->ttm.base) {
++ struct xe_vm *vm = gpuvm_to_vm(vm_bo->vm);
++
++ if (xe_vm_resv(vm) == ctx->resv &&
++ xe_vm_in_preempt_fence_mode(vm)) {
++ ret = -EBUSY;
++ goto out;
++ }
++ }
++ }
++
+ /*
+ * Failed multi-hop where the old_mem is still marked as
+ * TTM_PL_FLAG_TEMPORARY, should just be a dummy move.
+--
+2.39.5
+
--- /dev/null
+From b438bed4acfc7cb612d891ce88c0c5ec4f824019 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jan 2025 16:37:13 +0100
+Subject: drm/xe/relay: Don't use GFP_KERNEL for new transactions
+
+From: Michal Wajdeczko <michal.wajdeczko@intel.com>
+
+[ Upstream commit 78d5d1e20d1de9422f013338a0f2311448588ba7 ]
+
+VFs use a relay transaction during the resume/reset flow and use
+of the GFP_KERNEL flag may conflict with the reclaim:
+
+ -> #0 (fs_reclaim){+.+.}-{0:0}:
+ [ ] __lock_acquire+0x1874/0x2bc0
+ [ ] lock_acquire+0xd2/0x310
+ [ ] fs_reclaim_acquire+0xc5/0x100
+ [ ] mempool_alloc_noprof+0x5c/0x1b0
+ [ ] __relay_get_transaction+0xdc/0xa10 [xe]
+ [ ] relay_send_to+0x251/0xe50 [xe]
+ [ ] xe_guc_relay_send_to_pf+0x79/0x3a0 [xe]
+ [ ] xe_gt_sriov_vf_connect+0x90/0x4d0 [xe]
+ [ ] xe_uc_init_hw+0x157/0x3b0 [xe]
+ [ ] do_gt_restart+0x1ae/0x650 [xe]
+ [ ] xe_gt_resume+0xb6/0x120 [xe]
+ [ ] xe_pm_runtime_resume+0x15b/0x370 [xe]
+ [ ] xe_pci_runtime_resume+0x73/0x90 [xe]
+ [ ] pci_pm_runtime_resume+0xa0/0x100
+ [ ] __rpm_callback+0x4d/0x170
+ [ ] rpm_callback+0x64/0x70
+ [ ] rpm_resume+0x594/0x790
+ [ ] __pm_runtime_resume+0x4e/0x90
+ [ ] xe_pm_runtime_get_ioctl+0x9c/0x160 [xe]
+
+Since we have a preallocated pool of relay transactions, which
+should cover all our normal relay use cases, we may use the
+GFP_NOWAIT flag when allocating new outgoing transactions.
+
+Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
+Tested-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
+Reviewed-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250131153713.808-1-michal.wajdeczko@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_guc_relay.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_guc_relay.c b/drivers/gpu/drm/xe/xe_guc_relay.c
+index ade6162dc2598..0e5b43e1518ea 100644
+--- a/drivers/gpu/drm/xe/xe_guc_relay.c
++++ b/drivers/gpu/drm/xe/xe_guc_relay.c
+@@ -224,7 +224,7 @@ __relay_get_transaction(struct xe_guc_relay *relay, bool incoming, u32 remote, u
+ * with CTB lock held which is marked as used in the reclaim path.
+ * Btw, that's one of the reason why we use mempool here!
+ */
+- txn = mempool_alloc(&relay->pool, incoming ? GFP_ATOMIC : GFP_KERNEL);
++ txn = mempool_alloc(&relay->pool, incoming ? GFP_ATOMIC : GFP_NOWAIT);
+ if (!txn)
+ return ERR_PTR(-ENOMEM);
+
+--
+2.39.5
+
--- /dev/null
+From 430fef42b4cdb18231d51f97e842f05e9cb8c6cf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Mar 2025 17:26:26 -0800
+Subject: drm/xe: Retry BO allocation
+
+From: Matthew Brost <matthew.brost@intel.com>
+
+[ Upstream commit 1d724a2f1b2c3f0cba4975784a808482e0631adf ]
+
+TTM doesn't support fair eviction via WW locking, this mitigated in by
+using retry loops in exec and preempt rebind worker. Extend this retry
+loop to BO allocation. Once TTM supports fair eviction this patch can be
+reverted.
+
+v4:
+ - Keep line break (Stuart)
+
+Signed-off-by: Matthew Brost <matthew.brost@intel.com>
+Reviewed-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
+Reviewed-by: Stuart Summers <stuart.summers@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250306012657.3505757-2-matthew.brost@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_bo.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
+index 84e327b569252..35a8242a9f541 100644
+--- a/drivers/gpu/drm/xe/xe_bo.c
++++ b/drivers/gpu/drm/xe/xe_bo.c
+@@ -1975,6 +1975,7 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data,
+ struct xe_file *xef = to_xe_file(file);
+ struct drm_xe_gem_create *args = data;
+ struct xe_vm *vm = NULL;
++ ktime_t end = 0;
+ struct xe_bo *bo;
+ unsigned int bo_flags;
+ u32 handle;
+@@ -2047,6 +2048,10 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data,
+ vm = xe_vm_lookup(xef, args->vm_id);
+ if (XE_IOCTL_DBG(xe, !vm))
+ return -ENOENT;
++ }
++
++retry:
++ if (vm) {
+ err = xe_vm_lock(vm, true);
+ if (err)
+ goto out_vm;
+@@ -2060,6 +2065,8 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data,
+
+ if (IS_ERR(bo)) {
+ err = PTR_ERR(bo);
++ if (xe_vm_validate_should_retry(NULL, err, &end))
++ goto retry;
+ goto out_vm;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 57aaf1ddc383ba5ba1bdac8afe52efe3c8e4e770 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Dec 2024 20:41:54 +0100
+Subject: drm/xe/sa: Always call drm_suballoc_manager_fini()
+
+From: Michal Wajdeczko <michal.wajdeczko@intel.com>
+
+[ Upstream commit 9cd3f4efc870463f17f6c29114c61fb6bfcaa291 ]
+
+After successful call to drm_suballoc_manager_init() we should
+make sure to call drm_suballoc_manager_fini() as it may include
+some cleanup code even if we didn't start using it for real.
+
+As we can abort init() early due to kvzalloc() failure, we should
+either explicitly call drm_suballoc_manager_fini() or, even better,
+postpone drm_suballoc_manager_init() once we finish all other
+preparation steps, so we can rely on fini() that will do cleanup.
+
+Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
+Cc: Matthew Brost <matthew.brost@intel.com>
+Reviewed-by: Matthew Brost <matthew.brost@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20241220194205.995-2-michal.wajdeczko@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_sa.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_sa.c b/drivers/gpu/drm/xe/xe_sa.c
+index fe2cb2a96f788..1d42547590067 100644
+--- a/drivers/gpu/drm/xe/xe_sa.c
++++ b/drivers/gpu/drm/xe/xe_sa.c
+@@ -57,8 +57,6 @@ struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32
+ }
+ sa_manager->bo = bo;
+ sa_manager->is_iomem = bo->vmap.is_iomem;
+-
+- drm_suballoc_manager_init(&sa_manager->base, managed_size, align);
+ sa_manager->gpu_addr = xe_bo_ggtt_addr(bo);
+
+ if (bo->vmap.is_iomem) {
+@@ -72,6 +70,7 @@ struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32
+ memset(sa_manager->cpu_ptr, 0, bo->ttm.base.size);
+ }
+
++ drm_suballoc_manager_init(&sa_manager->base, managed_size, align);
+ ret = drmm_add_action_or_reset(&xe->drm, xe_sa_bo_manager_fini,
+ sa_manager);
+ if (ret)
+--
+2.39.5
+
--- /dev/null
+From 69413931fc792b46883e86fa9d3b9022cacbfddc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 11:29:01 -0800
+Subject: drm/xe: Stop ignoring errors from xe_ttm_stolen_mgr_init()
+
+From: Lucas De Marchi <lucas.demarchi@intel.com>
+
+[ Upstream commit ff57025c358603555f1e0ae0d50282a460433594 ]
+
+Make sure to differentiate normal behavior, e.g. there's no stolen, from
+allocation errors or failure to initialize lower layers.
+
+Reviewed-by: Francois Dugast <francois.dugast@intel.com>
+Reviewed-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250213192909.996148-5-lucas.demarchi@intel.com
+Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_device.c | 4 +++-
+ drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c | 17 +++++++++--------
+ drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h | 2 +-
+ 3 files changed, 13 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
+index bb85208cf1a94..5c37bed3c948f 100644
+--- a/drivers/gpu/drm/xe/xe_device.c
++++ b/drivers/gpu/drm/xe/xe_device.c
+@@ -694,7 +694,9 @@ int xe_device_probe(struct xe_device *xe)
+ }
+
+ /* Allocate and map stolen after potential VRAM resize */
+- xe_ttm_stolen_mgr_init(xe);
++ err = xe_ttm_stolen_mgr_init(xe);
++ if (err)
++ return err;
+
+ /*
+ * Now that GT is initialized (TTM in particular),
+diff --git a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c
+index f7113cf6109d5..ef84fa757b26f 100644
+--- a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c
++++ b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c
+@@ -201,17 +201,16 @@ static u64 detect_stolen(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr)
+ #endif
+ }
+
+-void xe_ttm_stolen_mgr_init(struct xe_device *xe)
++int xe_ttm_stolen_mgr_init(struct xe_device *xe)
+ {
+- struct xe_ttm_stolen_mgr *mgr = drmm_kzalloc(&xe->drm, sizeof(*mgr), GFP_KERNEL);
+ struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
++ struct xe_ttm_stolen_mgr *mgr;
+ u64 stolen_size, io_size;
+ int err;
+
+- if (!mgr) {
+- drm_dbg_kms(&xe->drm, "Stolen mgr init failed\n");
+- return;
+- }
++ mgr = drmm_kzalloc(&xe->drm, sizeof(*mgr), GFP_KERNEL);
++ if (!mgr)
++ return -ENOMEM;
+
+ if (IS_SRIOV_VF(xe))
+ stolen_size = 0;
+@@ -224,7 +223,7 @@ void xe_ttm_stolen_mgr_init(struct xe_device *xe)
+
+ if (!stolen_size) {
+ drm_dbg_kms(&xe->drm, "No stolen memory support\n");
+- return;
++ return 0;
+ }
+
+ /*
+@@ -240,7 +239,7 @@ void xe_ttm_stolen_mgr_init(struct xe_device *xe)
+ io_size, PAGE_SIZE);
+ if (err) {
+ drm_dbg_kms(&xe->drm, "Stolen mgr init failed: %i\n", err);
+- return;
++ return err;
+ }
+
+ drm_dbg_kms(&xe->drm, "Initialized stolen memory support with %llu bytes\n",
+@@ -248,6 +247,8 @@ void xe_ttm_stolen_mgr_init(struct xe_device *xe)
+
+ if (io_size)
+ mgr->mapping = devm_ioremap_wc(&pdev->dev, mgr->io_base, io_size);
++
++ return 0;
+ }
+
+ u64 xe_ttm_stolen_io_offset(struct xe_bo *bo, u32 offset)
+diff --git a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h
+index 1777245ff8101..8e877d1e839bd 100644
+--- a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h
++++ b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h
+@@ -12,7 +12,7 @@ struct ttm_resource;
+ struct xe_bo;
+ struct xe_device;
+
+-void xe_ttm_stolen_mgr_init(struct xe_device *xe);
++int xe_ttm_stolen_mgr_init(struct xe_device *xe);
+ int xe_ttm_stolen_io_mem_reserve(struct xe_device *xe, struct ttm_resource *mem);
+ bool xe_ttm_stolen_cpu_access_needs_ggtt(struct xe_device *xe);
+ u64 xe_ttm_stolen_io_offset(struct xe_bo *bo, u32 offset);
+--
+2.39.5
+
--- /dev/null
+From 681cead80b289ad55402949c2d1d9b1495bd9df1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 15:58:07 +0530
+Subject: drm/xe/vf: Retry sending MMIO request to GUC on timeout error
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Satyanarayana K V P <satyanarayana.k.v.p@intel.com>
+
+[ Upstream commit ba757a65d2a28d46a8ccf50538f4f05036983f1b ]
+
+Add support to allow retrying the sending of MMIO requests
+from the VF to the GUC in the event of an error. During the
+suspend/resume process, VFs begin resuming only after the PF has
+resumed. Although the PF resumes, the GUC reset and provisioning
+occur later in a separate worker process.
+
+When there are a large number of VFs, some may attempt to resume
+before the PF has completed its provisioning. Therefore, if a
+MMIO request from a VF fails during this period, we will retry
+sending the request up to GUC_RESET_VF_STATE_RETRY_MAX times,
+which is set to a maximum of 10 attempts.
+
+Signed-off-by: Satyanarayana K V P <satyanarayana.k.v.p@intel.com>
+Cc: Michał Wajdeczko <michal.wajdeczko@intel.com>
+Cc: Michał Winiarski <michal.winiarski@intel.com>
+Cc: Piotr Piórkowski <piotr.piorkowski@intel.com>
+Reviewed-by: Piotr Piorkowski <piotr.piorkowski@intel.com>
+Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250224102807.11065-3-satyanarayana.k.v.p@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
+index f982d6f9f218d..7ddbfeaf494ac 100644
+--- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
++++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
+@@ -46,12 +46,19 @@ static int guc_action_vf_reset(struct xe_guc *guc)
+ return ret > 0 ? -EPROTO : ret;
+ }
+
++#define GUC_RESET_VF_STATE_RETRY_MAX 10
+ static int vf_reset_guc_state(struct xe_gt *gt)
+ {
++ unsigned int retry = GUC_RESET_VF_STATE_RETRY_MAX;
+ struct xe_guc *guc = >->uc.guc;
+ int err;
+
+- err = guc_action_vf_reset(guc);
++ do {
++ err = guc_action_vf_reset(guc);
++ if (!err || err != -ETIMEDOUT)
++ break;
++ } while (--retry);
++
+ if (unlikely(err))
+ xe_gt_sriov_err(gt, "Failed to reset GuC state (%pe)\n", ERR_PTR(err));
+ return err;
+--
+2.39.5
+
--- /dev/null
+From 2d319cfa1595f9ffe38e1cd5ffab65dbba5a190b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 07:23:13 +0100
+Subject: drm/xe: xe_gen_wa_oob: replace program_invocation_short_name
+
+From: Daniel Gomez <da.gomez@samsung.com>
+
+[ Upstream commit 89eb42b5539f6ae6a0cabcb39e5b6fcc83c106a1 ]
+
+program_invocation_short_name may not be available in other systems.
+Instead, replace it with the argv[0] to pass the executable name.
+
+Fixes build error when program_invocation_short_name is not available:
+
+drivers/gpu/drm/xe/xe_gen_wa_oob.c:34:3: error: use of
+undeclared identifier 'program_invocation_short_name' 34 |
+program_invocation_short_name); | ^ 1 error
+generated.
+
+Suggested-by: Masahiro Yamada <masahiroy@kernel.org>
+Signed-off-by: Daniel Gomez <da.gomez@samsung.com>
+Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250224-macos-build-support-xe-v3-1-d2c9ed3a27cc@samsung.com
+Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_gen_wa_oob.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_gen_wa_oob.c b/drivers/gpu/drm/xe/xe_gen_wa_oob.c
+index 904cf47925aa1..ed9183599e31c 100644
+--- a/drivers/gpu/drm/xe/xe_gen_wa_oob.c
++++ b/drivers/gpu/drm/xe/xe_gen_wa_oob.c
+@@ -28,10 +28,10 @@
+ "\n" \
+ "#endif\n"
+
+-static void print_usage(FILE *f)
++static void print_usage(FILE *f, const char *progname)
+ {
+ fprintf(f, "usage: %s <input-rule-file> <generated-c-source-file> <generated-c-header-file>\n",
+- program_invocation_short_name);
++ progname);
+ }
+
+ static void print_parse_error(const char *err_msg, const char *line,
+@@ -144,7 +144,7 @@ int main(int argc, const char *argv[])
+
+ if (argc < 3) {
+ fprintf(stderr, "ERROR: wrong arguments\n");
+- print_usage(stderr);
++ print_usage(stderr, argv[0]);
+ return 1;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 5677d466ab4cfe1cb52fa66053eb9f11ac530827 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jan 2025 07:50:26 +0100
+Subject: EDAC/ie31200: work around false positive build warning
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit c29dfd661fe2f8d1b48c7f00590929c04b25bf40 ]
+
+gcc-14 produces a bogus warning in some configurations:
+
+drivers/edac/ie31200_edac.c: In function 'ie31200_probe1.isra':
+drivers/edac/ie31200_edac.c:412:26: error: 'dimm_info' is used uninitialized [-Werror=uninitialized]
+ 412 | struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL];
+ | ^~~~~~~~~
+drivers/edac/ie31200_edac.c:412:26: note: 'dimm_info' declared here
+ 412 | struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL];
+ | ^~~~~~~~~
+
+I don't see any way the unintialized access could really happen here,
+but I can see why the compiler gets confused by the two loops.
+
+Instead, rework the two nested loops to only read the addr_decode
+registers and then keep only one instance of the dimm info structure.
+
+[Tony: Qiuxu pointed out that the "populate DIMM info" comment was left
+behind in the refactor and suggested moving it. I deleted the comment
+as unnecessry in front os a call to populate_dimm_info(). That seems
+pretty self-describing.]
+
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Acked-by: Jason Baron <jbaron@akamai.com>
+Signed-off-by: Tony Luck <tony.luck@intel.com>
+Link: https://lore.kernel.org/all/20250122065031.1321015-1-arnd@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/edac/ie31200_edac.c | 28 +++++++++++++---------------
+ 1 file changed, 13 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c
+index 56be8ef40f376..e3635fba63b49 100644
+--- a/drivers/edac/ie31200_edac.c
++++ b/drivers/edac/ie31200_edac.c
+@@ -405,10 +405,9 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx)
+ int i, j, ret;
+ struct mem_ctl_info *mci = NULL;
+ struct edac_mc_layer layers[2];
+- struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL];
+ void __iomem *window;
+ struct ie31200_priv *priv;
+- u32 addr_decode, mad_offset;
++ u32 addr_decode[IE31200_CHANNELS], mad_offset;
+
+ /*
+ * Kaby Lake, Coffee Lake seem to work like Skylake. Please re-visit
+@@ -466,19 +465,10 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx)
+ mad_offset = IE31200_MAD_DIMM_0_OFFSET;
+ }
+
+- /* populate DIMM info */
+ for (i = 0; i < IE31200_CHANNELS; i++) {
+- addr_decode = readl(window + mad_offset +
++ addr_decode[i] = readl(window + mad_offset +
+ (i * 4));
+- edac_dbg(0, "addr_decode: 0x%x\n", addr_decode);
+- for (j = 0; j < IE31200_DIMMS_PER_CHANNEL; j++) {
+- populate_dimm_info(&dimm_info[i][j], addr_decode, j,
+- skl);
+- edac_dbg(0, "size: 0x%x, rank: %d, width: %d\n",
+- dimm_info[i][j].size,
+- dimm_info[i][j].dual_rank,
+- dimm_info[i][j].x16_width);
+- }
++ edac_dbg(0, "addr_decode: 0x%x\n", addr_decode[i]);
+ }
+
+ /*
+@@ -489,14 +479,22 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx)
+ */
+ for (i = 0; i < IE31200_DIMMS_PER_CHANNEL; i++) {
+ for (j = 0; j < IE31200_CHANNELS; j++) {
++ struct dimm_data dimm_info;
+ struct dimm_info *dimm;
+ unsigned long nr_pages;
+
+- nr_pages = IE31200_PAGES(dimm_info[j][i].size, skl);
++ populate_dimm_info(&dimm_info, addr_decode[j], i,
++ skl);
++ edac_dbg(0, "size: 0x%x, rank: %d, width: %d\n",
++ dimm_info.size,
++ dimm_info.dual_rank,
++ dimm_info.x16_width);
++
++ nr_pages = IE31200_PAGES(dimm_info.size, skl);
+ if (nr_pages == 0)
+ continue;
+
+- if (dimm_info[j][i].dual_rank) {
++ if (dimm_info.dual_rank) {
+ nr_pages = nr_pages / 2;
+ dimm = edac_get_dimm(mci, (i * 2) + 1, j, 0);
+ dimm->nr_pages = nr_pages;
+--
+2.39.5
+
--- /dev/null
+From e031aa5dd5350af76ecd6ef4ecd1abc4c8e6aa27 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Feb 2025 16:09:59 -0600
+Subject: eeprom: ee1004: Check chip before probing
+
+From: Eddie James <eajames@linux.ibm.com>
+
+[ Upstream commit d9406677428e9234ea62bb2d2f5e996d1b777760 ]
+
+Like other eeprom drivers, check if the device is really there and
+functional before probing.
+
+Signed-off-by: Eddie James <eajames@linux.ibm.com>
+Link: https://lore.kernel.org/r/20250218220959.721698-1-eajames@linux.ibm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/misc/eeprom/ee1004.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/misc/eeprom/ee1004.c b/drivers/misc/eeprom/ee1004.c
+index 89224d4af4a20..e13f9fdd9d7b1 100644
+--- a/drivers/misc/eeprom/ee1004.c
++++ b/drivers/misc/eeprom/ee1004.c
+@@ -304,6 +304,10 @@ static int ee1004_probe(struct i2c_client *client)
+ I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_READ_BYTE_DATA))
+ return -EPFNOSUPPORT;
+
++ err = i2c_smbus_read_byte(client);
++ if (err < 0)
++ return -ENODEV;
++
+ mutex_lock(&ee1004_bus_lock);
+
+ err = ee1004_init_bus_data(client);
+--
+2.39.5
+
--- /dev/null
+From 91290d9af1cb9e8f671aee4d0be57c40826a5f40 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Mar 2025 13:48:40 +0800
+Subject: erofs: initialize decompression early
+
+From: Gao Xiang <hsiangkao@linux.alibaba.com>
+
+[ Upstream commit fe1e57d44d7f106df9048e815e4862cf63921220 ]
+
+ - Rename erofs_init_managed_cache() to z_erofs_init_super();
+ - Move the initialization of managed_pslots into z_erofs_init_super() too;
+ - Move z_erofs_init_super() and packed inode preparation upwards, before
+ the root inode initialization.
+
+Therefore, the root directory can also be compressible.
+
+Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
+Acked-by: Chao Yu <chao@kernel.org>
+Link: https://lore.kernel.org/r/20250317054840.3483000-1-hsiangkao@linux.alibaba.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/erofs/internal.h | 4 ++--
+ fs/erofs/super.c | 46 ++++++++++++++++++++++-----------------------
+ fs/erofs/zdata.c | 4 ++--
+ 3 files changed, 26 insertions(+), 28 deletions(-)
+
+diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
+index edbabb3256c9a..2c11e8f3048e9 100644
+--- a/fs/erofs/internal.h
++++ b/fs/erofs/internal.h
+@@ -453,6 +453,7 @@ int __init erofs_init_shrinker(void);
+ void erofs_exit_shrinker(void);
+ int __init z_erofs_init_subsystem(void);
+ void z_erofs_exit_subsystem(void);
++int z_erofs_init_super(struct super_block *sb);
+ unsigned long z_erofs_shrink_scan(struct erofs_sb_info *sbi,
+ unsigned long nr_shrink);
+ int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map,
+@@ -462,7 +463,6 @@ void z_erofs_put_gbuf(void *ptr);
+ int z_erofs_gbuf_growsize(unsigned int nrpages);
+ int __init z_erofs_gbuf_init(void);
+ void z_erofs_gbuf_exit(void);
+-int erofs_init_managed_cache(struct super_block *sb);
+ int z_erofs_parse_cfgs(struct super_block *sb, struct erofs_super_block *dsb);
+ #else
+ static inline void erofs_shrinker_register(struct super_block *sb) {}
+@@ -471,7 +471,7 @@ static inline int erofs_init_shrinker(void) { return 0; }
+ static inline void erofs_exit_shrinker(void) {}
+ static inline int z_erofs_init_subsystem(void) { return 0; }
+ static inline void z_erofs_exit_subsystem(void) {}
+-static inline int erofs_init_managed_cache(struct super_block *sb) { return 0; }
++static inline int z_erofs_init_super(struct super_block *sb) { return 0; }
+ #endif /* !CONFIG_EROFS_FS_ZIP */
+
+ #ifdef CONFIG_EROFS_FS_BACKED_BY_FILE
+diff --git a/fs/erofs/super.c b/fs/erofs/super.c
+index 5b279977c9d5d..3421448fef0e3 100644
+--- a/fs/erofs/super.c
++++ b/fs/erofs/super.c
+@@ -664,9 +664,16 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
+ else
+ sb->s_flags &= ~SB_POSIXACL;
+
+-#ifdef CONFIG_EROFS_FS_ZIP
+- xa_init(&sbi->managed_pslots);
+-#endif
++ err = z_erofs_init_super(sb);
++ if (err)
++ return err;
++
++ if (erofs_sb_has_fragments(sbi) && sbi->packed_nid) {
++ inode = erofs_iget(sb, sbi->packed_nid);
++ if (IS_ERR(inode))
++ return PTR_ERR(inode);
++ sbi->packed_inode = inode;
++ }
+
+ inode = erofs_iget(sb, sbi->root_nid);
+ if (IS_ERR(inode))
+@@ -678,24 +685,11 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
+ iput(inode);
+ return -EINVAL;
+ }
+-
+ sb->s_root = d_make_root(inode);
+ if (!sb->s_root)
+ return -ENOMEM;
+
+ erofs_shrinker_register(sb);
+- if (erofs_sb_has_fragments(sbi) && sbi->packed_nid) {
+- sbi->packed_inode = erofs_iget(sb, sbi->packed_nid);
+- if (IS_ERR(sbi->packed_inode)) {
+- err = PTR_ERR(sbi->packed_inode);
+- sbi->packed_inode = NULL;
+- return err;
+- }
+- }
+- err = erofs_init_managed_cache(sb);
+- if (err)
+- return err;
+-
+ err = erofs_xattr_prefixes_init(sb);
+ if (err)
+ return err;
+@@ -831,6 +825,16 @@ static int erofs_init_fs_context(struct fs_context *fc)
+ return 0;
+ }
+
++static void erofs_drop_internal_inodes(struct erofs_sb_info *sbi)
++{
++ iput(sbi->packed_inode);
++ sbi->packed_inode = NULL;
++#ifdef CONFIG_EROFS_FS_ZIP
++ iput(sbi->managed_cache);
++ sbi->managed_cache = NULL;
++#endif
++}
++
+ static void erofs_kill_sb(struct super_block *sb)
+ {
+ struct erofs_sb_info *sbi = EROFS_SB(sb);
+@@ -840,6 +844,7 @@ static void erofs_kill_sb(struct super_block *sb)
+ kill_anon_super(sb);
+ else
+ kill_block_super(sb);
++ erofs_drop_internal_inodes(sbi);
+ fs_put_dax(sbi->dif0.dax_dev, NULL);
+ erofs_fscache_unregister_fs(sb);
+ erofs_sb_free(sbi);
+@@ -850,17 +855,10 @@ static void erofs_put_super(struct super_block *sb)
+ {
+ struct erofs_sb_info *const sbi = EROFS_SB(sb);
+
+- DBG_BUGON(!sbi);
+-
+ erofs_unregister_sysfs(sb);
+ erofs_shrinker_unregister(sb);
+ erofs_xattr_prefixes_cleanup(sb);
+-#ifdef CONFIG_EROFS_FS_ZIP
+- iput(sbi->managed_cache);
+- sbi->managed_cache = NULL;
+-#endif
+- iput(sbi->packed_inode);
+- sbi->packed_inode = NULL;
++ erofs_drop_internal_inodes(sbi);
+ erofs_free_dev_context(sbi->devs);
+ sbi->devs = NULL;
+ erofs_fscache_unregister_fs(sb);
+diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c
+index e5e94afc5af88..74521d7dbee1d 100644
+--- a/fs/erofs/zdata.c
++++ b/fs/erofs/zdata.c
+@@ -663,18 +663,18 @@ static const struct address_space_operations z_erofs_cache_aops = {
+ .invalidate_folio = z_erofs_cache_invalidate_folio,
+ };
+
+-int erofs_init_managed_cache(struct super_block *sb)
++int z_erofs_init_super(struct super_block *sb)
+ {
+ struct inode *const inode = new_inode(sb);
+
+ if (!inode)
+ return -ENOMEM;
+-
+ set_nlink(inode, 1);
+ inode->i_size = OFFSET_MAX;
+ inode->i_mapping->a_ops = &z_erofs_cache_aops;
+ mapping_set_gfp_mask(inode->i_mapping, GFP_KERNEL);
+ EROFS_SB(sb)->managed_cache = inode;
++ xa_init(&EROFS_SB(sb)->managed_pslots);
+ return 0;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From c61af6b822c62369fa867f46e3876d640374bf31 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Feb 2025 17:00:38 -0800
+Subject: eth: fbnic: set IFF_UNICAST_FLT to avoid enabling promiscuous mode
+ when adding unicast addrs
+
+From: Alexander Duyck <alexanderduyck@meta.com>
+
+[ Upstream commit 09717c28b76c30b1dc8c261c855ffb2406abab2e ]
+
+I realized when we were adding unicast addresses we were enabling
+promiscuous mode. I did a bit of digging and realized we had overlooked
+setting the driver private flag to indicate we supported unicast filtering.
+
+Example below shows the table with 00deadbeef01 as the main NIC address,
+and 5 additional addresses in the 00deadbeefX0 format.
+
+ # cat $dbgfs/mac_addr
+ Idx S TCAM Bitmap Addr/Mask
+ ----------------------------------
+ 00 0 00000000,00000000 000000000000
+ 000000000000
+ 01 0 00000000,00000000 000000000000
+ 000000000000
+ 02 0 00000000,00000000 000000000000
+ 000000000000
+ ...
+ 24 0 00000000,00000000 000000000000
+ 000000000000
+ 25 1 00100000,00000000 00deadbeef50
+ 000000000000
+ 26 1 00100000,00000000 00deadbeef40
+ 000000000000
+ 27 1 00100000,00000000 00deadbeef30
+ 000000000000
+ 28 1 00100000,00000000 00deadbeef20
+ 000000000000
+ 29 1 00100000,00000000 00deadbeef10
+ 000000000000
+ 30 1 00100000,00000000 00deadbeef01
+ 000000000000
+ 31 0 00000000,00000000 000000000000
+ 000000000000
+
+Before rule 31 would be active. With this change it correctly sticks
+to just the unicast filters.
+
+Signed-off-by: Alexander Duyck <alexanderduyck@meta.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20250204010038.1404268-2-kuba@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/meta/fbnic/fbnic_netdev.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c
+index a400616a24d41..79e94632533c8 100644
+--- a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c
++++ b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c
+@@ -544,6 +544,8 @@ struct net_device *fbnic_netdev_alloc(struct fbnic_dev *fbd)
+ fbnic_rss_key_fill(fbn->rss_key);
+ fbnic_rss_init_en_mask(fbn);
+
++ netdev->priv_flags |= IFF_UNICAST_FLT;
++
+ netdev->features |=
+ NETIF_F_RXHASH |
+ NETIF_F_SG |
+--
+2.39.5
+
--- /dev/null
+From 391a9ea87bb03951eb75a89ae178b2b682c77175 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Feb 2025 17:06:33 -0800
+Subject: eth: mlx4: don't try to complete XDP frames in netpoll
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 8fdeafd66edaf420ea0063a1f13442fe3470fe70 ]
+
+mlx4 doesn't support ndo_xdp_xmit / XDP_REDIRECT and wasn't
+using page pool until now, so it could run XDP completions
+in netpoll (NAPI budget == 0) just fine. Page pool has calling
+context requirements, make sure we don't try to call it from
+what is potentially HW IRQ context.
+
+Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20250213010635.1354034-3-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx4/en_tx.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+index 1ddb11cb25f91..6e077d202827a 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+@@ -450,6 +450,8 @@ int mlx4_en_process_tx_cq(struct net_device *dev,
+
+ if (unlikely(!priv->port_up))
+ return 0;
++ if (unlikely(!napi_budget) && cq->type == TX_XDP)
++ return 0;
+
+ netdev_txq_bql_complete_prefetchw(ring->tx_queue);
+
+--
+2.39.5
+
--- /dev/null
+From aad2ce8dfaf5a7075448dcae7de6baeae6260a0d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Mar 2025 00:01:16 +0900
+Subject: exfat: call bh_read in get_block only when necessary
+
+From: Sungjong Seo <sj1557.seo@samsung.com>
+
+[ Upstream commit c73e680d1f84059e1b1ea82a537f6ccc1c563eb4 ]
+
+With commit 11a347fb6cef ("exfat: change to get file size from DataLength"),
+exfat_get_block() can now handle valid_size. However, most partial
+unwritten blocks that could be mapped with other blocks are being
+inefficiently processed separately as individual blocks.
+
+Except for partial unwritten blocks that require independent processing,
+let's handle them simply as before.
+
+Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
+Reviewed-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/exfat/inode.c | 159 +++++++++++++++++++++++------------------------
+ 1 file changed, 77 insertions(+), 82 deletions(-)
+
+diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c
+index 3801516ac5071..cc4dcb7a32b57 100644
+--- a/fs/exfat/inode.c
++++ b/fs/exfat/inode.c
+@@ -274,9 +274,11 @@ static int exfat_get_block(struct inode *inode, sector_t iblock,
+ sector_t last_block;
+ sector_t phys = 0;
+ sector_t valid_blks;
++ loff_t i_size;
+
+ mutex_lock(&sbi->s_lock);
+- last_block = EXFAT_B_TO_BLK_ROUND_UP(i_size_read(inode), sb);
++ i_size = i_size_read(inode);
++ last_block = EXFAT_B_TO_BLK_ROUND_UP(i_size, sb);
+ if (iblock >= last_block && !create)
+ goto done;
+
+@@ -305,102 +307,95 @@ static int exfat_get_block(struct inode *inode, sector_t iblock,
+ if (buffer_delay(bh_result))
+ clear_buffer_delay(bh_result);
+
+- if (create) {
++ /*
++ * In most cases, we just need to set bh_result to mapped, unmapped
++ * or new status as follows:
++ * 1. i_size == valid_size
++ * 2. write case (create == 1)
++ * 3. direct_read (!bh_result->b_folio)
++ * -> the unwritten part will be zeroed in exfat_direct_IO()
++ *
++ * Otherwise, in the case of buffered read, it is necessary to take
++ * care the last nested block if valid_size is not equal to i_size.
++ */
++ if (i_size == ei->valid_size || create || !bh_result->b_folio)
+ valid_blks = EXFAT_B_TO_BLK_ROUND_UP(ei->valid_size, sb);
++ else
++ valid_blks = EXFAT_B_TO_BLK(ei->valid_size, sb);
+
+- if (iblock + max_blocks < valid_blks) {
+- /* The range has been written, map it */
+- goto done;
+- } else if (iblock < valid_blks) {
+- /*
+- * The range has been partially written,
+- * map the written part.
+- */
+- max_blocks = valid_blks - iblock;
+- goto done;
+- }
++ /* The range has been fully written, map it */
++ if (iblock + max_blocks < valid_blks)
++ goto done;
+
+- /* The area has not been written, map and mark as new. */
+- set_buffer_new(bh_result);
++ /* The range has been partially written, map the written part */
++ if (iblock < valid_blks) {
++ max_blocks = valid_blks - iblock;
++ goto done;
++ }
+
++ /* The area has not been written, map and mark as new for create case */
++ if (create) {
++ set_buffer_new(bh_result);
+ ei->valid_size = EXFAT_BLK_TO_B(iblock + max_blocks, sb);
+ mark_inode_dirty(inode);
+- } else {
+- valid_blks = EXFAT_B_TO_BLK(ei->valid_size, sb);
++ goto done;
++ }
+
+- if (iblock + max_blocks < valid_blks) {
+- /* The range has been written, map it */
+- goto done;
+- } else if (iblock < valid_blks) {
+- /*
+- * The area has been partially written,
+- * map the written part.
+- */
+- max_blocks = valid_blks - iblock;
++ /*
++ * The area has just one block partially written.
++ * In that case, we should read and fill the unwritten part of
++ * a block with zero.
++ */
++ if (bh_result->b_folio && iblock == valid_blks &&
++ (ei->valid_size & (sb->s_blocksize - 1))) {
++ loff_t size, pos;
++ void *addr;
++
++ max_blocks = 1;
++
++ /*
++ * No buffer_head is allocated.
++ * (1) bmap: It's enough to set blocknr without I/O.
++ * (2) read: The unwritten part should be filled with zero.
++ * If a folio does not have any buffers,
++ * let's returns -EAGAIN to fallback to
++ * block_read_full_folio() for per-bh IO.
++ */
++ if (!folio_buffers(bh_result->b_folio)) {
++ err = -EAGAIN;
+ goto done;
+- } else if (iblock == valid_blks &&
+- (ei->valid_size & (sb->s_blocksize - 1))) {
+- /*
+- * The block has been partially written,
+- * zero the unwritten part and map the block.
+- */
+- loff_t size, pos;
+- void *addr;
+-
+- max_blocks = 1;
+-
+- /*
+- * For direct read, the unwritten part will be zeroed in
+- * exfat_direct_IO()
+- */
+- if (!bh_result->b_folio)
+- goto done;
+-
+- /*
+- * No buffer_head is allocated.
+- * (1) bmap: It's enough to fill bh_result without I/O.
+- * (2) read: The unwritten part should be filled with 0
+- * If a folio does not have any buffers,
+- * let's returns -EAGAIN to fallback to
+- * per-bh IO like block_read_full_folio().
+- */
+- if (!folio_buffers(bh_result->b_folio)) {
+- err = -EAGAIN;
+- goto done;
+- }
++ }
+
+- pos = EXFAT_BLK_TO_B(iblock, sb);
+- size = ei->valid_size - pos;
+- addr = folio_address(bh_result->b_folio) +
+- offset_in_folio(bh_result->b_folio, pos);
++ pos = EXFAT_BLK_TO_B(iblock, sb);
++ size = ei->valid_size - pos;
++ addr = folio_address(bh_result->b_folio) +
++ offset_in_folio(bh_result->b_folio, pos);
+
+- /* Check if bh->b_data points to proper addr in folio */
+- if (bh_result->b_data != addr) {
+- exfat_fs_error_ratelimit(sb,
++ /* Check if bh->b_data points to proper addr in folio */
++ if (bh_result->b_data != addr) {
++ exfat_fs_error_ratelimit(sb,
+ "b_data(%p) != folio_addr(%p)",
+ bh_result->b_data, addr);
+- err = -EINVAL;
+- goto done;
+- }
+-
+- /* Read a block */
+- err = bh_read(bh_result, 0);
+- if (err < 0)
+- goto done;
++ err = -EINVAL;
++ goto done;
++ }
+
+- /* Zero unwritten part of a block */
+- memset(bh_result->b_data + size, 0,
+- bh_result->b_size - size);
++ /* Read a block */
++ err = bh_read(bh_result, 0);
++ if (err < 0)
++ goto done;
+
+- err = 0;
+- } else {
+- /*
+- * The range has not been written, clear the mapped flag
+- * to only zero the cache and do not read from disk.
+- */
+- clear_buffer_mapped(bh_result);
+- }
++ /* Zero unwritten part of a block */
++ memset(bh_result->b_data + size, 0, bh_result->b_size - size);
++ err = 0;
++ goto done;
+ }
++
++ /*
++ * The area has not been written, clear mapped for read/bmap cases.
++ * If so, it will be filled with zero without reading from disk.
++ */
++ clear_buffer_mapped(bh_result);
+ done:
+ bh_result->b_size = EXFAT_BLK_TO_B(max_blocks, sb);
+ if (err < 0)
+--
+2.39.5
+
--- /dev/null
+From 9591f9ea1e2a52280934f3c69e9687a87b93e360 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Mar 2025 18:19:41 +0100
+Subject: exit: fix the usage of delay_group_leader->exit_code in
+ do_notify_parent() and pidfs_exit()
+
+From: Oleg Nesterov <oleg@redhat.com>
+
+[ Upstream commit 9133607de37a4887c6f89ed937176a0a0c1ebb17 ]
+
+Consider a process with a group leader L and a sub-thread T.
+L does sys_exit(1), then T does sys_exit_group(2).
+
+In this case wait_task_zombie(L) will notice SIGNAL_GROUP_EXIT and use
+L->signal->group_exit_code, this is correct.
+
+But, before that, do_notify_parent(L) called by release_task(T) will use
+L->exit_code != L->signal->group_exit_code, and this is not consistent.
+We don't really care, I think that nobody relies on the info which comes
+with SIGCHLD, if nothing else SIGCHLD < SIGRTMIN can be queued only once.
+
+But pidfs_exit() is more problematic, I think pidfs_exit_info->exit_code
+should report ->group_exit_code in this case, just like wait_task_zombie().
+
+TODO: with this change we can hopefully cleanup (or may be even kill) the
+similar SIGNAL_GROUP_EXIT checks, at least in wait_task_zombie().
+
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Link: https://lore.kernel.org/r/20250324171941.GA13114@redhat.com
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/exit.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/kernel/exit.c b/kernel/exit.c
+index 619f0014c33be..9d888f26bf784 100644
+--- a/kernel/exit.c
++++ b/kernel/exit.c
+@@ -266,6 +266,9 @@ void release_task(struct task_struct *p)
+ leader = p->group_leader;
+ if (leader != p && thread_group_empty(leader)
+ && leader->exit_state == EXIT_ZOMBIE) {
++ /* for pidfs_exit() and do_notify_parent() */
++ if (leader->signal->flags & SIGNAL_GROUP_EXIT)
++ leader->exit_code = leader->signal->group_exit_code;
+ /*
+ * If we were the last child thread and the leader has
+ * exited already, and the leader's parent ignores SIGCHLD,
+--
+2.39.5
+
--- /dev/null
+From c232ea8a5725fa5baef85b1d628cc6514eeeb5a5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jan 2025 19:05:26 +0800
+Subject: ext4: do not convert the unwritten extents if data writeback fails
+
+From: Baokun Li <libaokun1@huawei.com>
+
+[ Upstream commit e856f93e0fb249955f7d5efb18fe20500a9ccc6d ]
+
+When dioread_nolock is turned on (the default), it will convert unwritten
+extents to written at ext4_end_io_end(), even if the data writeback fails.
+
+It leads to the possibility that stale data may be exposed when the
+physical block corresponding to the file data is read-only (i.e., writes
+return -EIO, but reads are normal).
+
+Therefore a new ext4_io_end->flags EXT4_IO_END_FAILED is added, which
+indicates that some bio write-back failed in the current ext4_io_end.
+When this flag is set, the unwritten to written conversion is no longer
+performed. Users can read the data normally until the caches are dropped,
+after that, the failed extents can only be read to all 0.
+
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
+Link: https://patch.msgid.link/20250122110533.4116662-3-libaokun@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/ext4.h | 3 ++-
+ fs/ext4/page-io.c | 16 ++++++++++++++--
+ 2 files changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index bbffb76d9a904..75df7eeee50d8 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -278,7 +278,8 @@ struct ext4_system_blocks {
+ /*
+ * Flags for ext4_io_end->flags
+ */
+-#define EXT4_IO_END_UNWRITTEN 0x0001
++#define EXT4_IO_END_UNWRITTEN 0x0001
++#define EXT4_IO_END_FAILED 0x0002
+
+ struct ext4_io_end_vec {
+ struct list_head list; /* list of io_end_vec */
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index b7b9261fec3b5..cb023922c93c8 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -181,14 +181,25 @@ static int ext4_end_io_end(ext4_io_end_t *io_end)
+ "list->prev 0x%p\n",
+ io_end, inode->i_ino, io_end->list.next, io_end->list.prev);
+
+- io_end->handle = NULL; /* Following call will use up the handle */
+- ret = ext4_convert_unwritten_io_end_vec(handle, io_end);
++ /*
++ * Do not convert the unwritten extents if data writeback fails,
++ * or stale data may be exposed.
++ */
++ io_end->handle = NULL; /* Following call will use up the handle */
++ if (unlikely(io_end->flag & EXT4_IO_END_FAILED)) {
++ ret = -EIO;
++ if (handle)
++ jbd2_journal_free_reserved(handle);
++ } else {
++ ret = ext4_convert_unwritten_io_end_vec(handle, io_end);
++ }
+ if (ret < 0 && !ext4_forced_shutdown(inode->i_sb)) {
+ ext4_msg(inode->i_sb, KERN_EMERG,
+ "failed to convert unwritten extents to written "
+ "extents -- potential data loss! "
+ "(inode %lu, error %d)", inode->i_ino, ret);
+ }
++
+ ext4_clear_io_unwritten_flag(io_end);
+ ext4_release_io_end(io_end);
+ return ret;
+@@ -344,6 +355,7 @@ static void ext4_end_bio(struct bio *bio)
+ bio->bi_status, inode->i_ino,
+ (unsigned long long)
+ bi_sector >> (inode->i_blkbits - 9));
++ io_end->flag |= EXT4_IO_END_FAILED;
+ mapping_set_error(inode->i_mapping,
+ blk_status_to_errno(bio->bi_status));
+ }
+--
+2.39.5
+
--- /dev/null
+From ef006c48e325e2d6d8bd1f8e55816c93414dc416 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Dec 2024 09:16:30 +0800
+Subject: ext4: don't write back data before punch hole in nojournal mode
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+[ Upstream commit 43d0105e2c7523cc6b14cad65e2044e829c0a07a ]
+
+There is no need to write back all data before punching a hole in
+non-journaled mode since it will be dropped soon after removing space.
+Therefore, the call to filemap_write_and_wait_range() can be eliminated.
+Besides, similar to ext4_zero_range(), we must address the case of
+partially punched folios when block size < page size. It is essential to
+remove writable userspace mappings to ensure that the folio can be
+faulted again during subsequent mmap write access.
+
+In journaled mode, we need to write dirty pages out before discarding
+page cache in case of crash before committing the freeing data
+transaction, which could expose old, stale data, even if synchronization
+has been performed.
+
+Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
+Link: https://patch.msgid.link/20241220011637.1157197-4-yi.zhang@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/inode.c | 18 +++++-------------
+ 1 file changed, 5 insertions(+), 13 deletions(-)
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 487d9aec56c9d..819be57bb4ecf 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3933,17 +3933,6 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
+
+ trace_ext4_punch_hole(inode, offset, length, 0);
+
+- /*
+- * Write out all dirty pages to avoid race conditions
+- * Then release them.
+- */
+- if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
+- ret = filemap_write_and_wait_range(mapping, offset,
+- offset + length - 1);
+- if (ret)
+- return ret;
+- }
+-
+ inode_lock(inode);
+
+ /* No need to punch hole beyond i_size */
+@@ -4005,8 +3994,11 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
+ ret = ext4_update_disksize_before_punch(inode, offset, length);
+ if (ret)
+ goto out_dio;
+- truncate_pagecache_range(inode, first_block_offset,
+- last_block_offset);
++
++ ret = ext4_truncate_page_cache_block_range(inode,
++ first_block_offset, last_block_offset + 1);
++ if (ret)
++ goto out_dio;
+ }
+
+ if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
+--
+2.39.5
+
--- /dev/null
+From 4d20b4edd11e4d0e2a3bbd96f8e21f1be3f9c1cb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Mar 2025 11:10:11 -0600
+Subject: ext4: on a remount, only log the ro or r/w state when it has changed
+
+From: Nicolas Bretz <bretznic@gmail.com>
+
+[ Upstream commit d7b0befd09320e3356a75cb96541c030515e7f5f ]
+
+A user complained that a message such as:
+
+EXT4-fs (nvme0n1p3): re-mounted UUID ro. Quota mode: none.
+
+implied that the file system was previously mounted read/write and was
+now remounted read-only, when it could have been some other mount
+state that had changed by the "mount -o remount" operation. Fix this
+by only logging "ro"or "r/w" when it has changed.
+
+https://bugzilla.kernel.org/show_bug.cgi?id=219132
+
+Signed-off-by: Nicolas Bretz <bretznic@gmail.com>
+Link: https://patch.msgid.link/20250319171011.8372-1-bretznic@gmail.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/super.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 4291ab3c20be6..473909c4a3784 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -6744,6 +6744,7 @@ static int ext4_reconfigure(struct fs_context *fc)
+ {
+ struct super_block *sb = fc->root->d_sb;
+ int ret;
++ bool old_ro = sb_rdonly(sb);
+
+ fc->s_fs_info = EXT4_SB(sb);
+
+@@ -6755,9 +6756,9 @@ static int ext4_reconfigure(struct fs_context *fc)
+ if (ret < 0)
+ return ret;
+
+- ext4_msg(sb, KERN_INFO, "re-mounted %pU %s. Quota mode: %s.",
+- &sb->s_uuid, sb_rdonly(sb) ? "ro" : "r/w",
+- ext4_quota_mode(sb));
++ ext4_msg(sb, KERN_INFO, "re-mounted %pU%s.",
++ &sb->s_uuid,
++ (old_ro != sb_rdonly(sb)) ? (sb_rdonly(sb) ? " ro" : " r/w") : "");
+
+ return 0;
+ }
+--
+2.39.5
+
--- /dev/null
+From 14c7c899263192c282693be8b855db07c55c6607 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jan 2025 19:05:27 +0800
+Subject: ext4: reject the 'data_err=abort' option in nojournal mode
+
+From: Baokun Li <libaokun1@huawei.com>
+
+[ Upstream commit 26343ca0df715097065b02a6cddb4a029d5b9327 ]
+
+data_err=abort aborts the journal on I/O errors. However, this option is
+meaningless if journal is disabled, so it is rejected in nojournal mode
+to reduce unnecessary checks. Also, this option is ignored upon remount.
+
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20250122110533.4116662-4-libaokun@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/super.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 473909c4a3784..99117d1e1bdd5 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2787,6 +2787,13 @@ static int ext4_check_opt_consistency(struct fs_context *fc,
+ }
+
+ if (is_remount) {
++ if (!sbi->s_journal &&
++ ctx_test_mount_opt(ctx, EXT4_MOUNT_DATA_ERR_ABORT)) {
++ ext4_msg(NULL, KERN_WARNING,
++ "Remounting fs w/o journal so ignoring data_err option");
++ ctx_clear_mount_opt(ctx, EXT4_MOUNT_DATA_ERR_ABORT);
++ }
++
+ if (ctx_test_mount_opt(ctx, EXT4_MOUNT_DAX_ALWAYS) &&
+ (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)) {
+ ext4_msg(NULL, KERN_ERR, "can't mount with "
+@@ -5396,6 +5403,11 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ "data=, fs mounted w/o journal");
+ goto failed_mount3a;
+ }
++ if (test_opt(sb, DATA_ERR_ABORT)) {
++ ext4_msg(sb, KERN_ERR,
++ "can't mount with data_err=abort, fs mounted w/o journal");
++ goto failed_mount3a;
++ }
+ sbi->s_def_mount_opt &= ~EXT4_MOUNT_JOURNAL_CHECKSUM;
+ clear_opt(sb, JOURNAL_CHECKSUM);
+ clear_opt(sb, DATA_FLAGS);
+--
+2.39.5
+
--- /dev/null
+From 93d42835eccd4978b8138f758f57a3d23b13f394 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Dec 2024 09:16:28 +0800
+Subject: ext4: remove writable userspace mappings before truncating page cache
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+[ Upstream commit 17207d0bb209e8b40f27d7f3f96e82a78af0bf2c ]
+
+When zeroing a range of folios on the filesystem which block size is
+less than the page size, the file's mapped blocks within one page will
+be marked as unwritten, we should remove writable userspace mappings to
+ensure that ext4_page_mkwrite() can be called during subsequent write
+access to these partial folios. Otherwise, data written by subsequent
+mmap writes may not be saved to disk.
+
+ $mkfs.ext4 -b 1024 /dev/vdb
+ $mount /dev/vdb /mnt
+ $xfs_io -t -f -c "pwrite -S 0x58 0 4096" -c "mmap -rw 0 4096" \
+ -c "mwrite -S 0x5a 2048 2048" -c "fzero 2048 2048" \
+ -c "mwrite -S 0x59 2048 2048" -c "close" /mnt/foo
+
+ $od -Ax -t x1z /mnt/foo
+ 000000 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58
+ *
+ 000800 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59
+ *
+ 001000
+
+ $umount /mnt && mount /dev/vdb /mnt
+ $od -Ax -t x1z /mnt/foo
+ 000000 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58
+ *
+ 000800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ *
+ 001000
+
+Fix this by introducing ext4_truncate_page_cache_block_range() to remove
+writable userspace mappings when truncating a partial folio range.
+Additionally, move the journal data mode-specific handlers and
+truncate_pagecache_range() into this function, allowing it to serve as a
+common helper that correctly manages the page cache in preparation for
+block range manipulations.
+
+Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
+Link: https://patch.msgid.link/20241220011637.1157197-2-yi.zhang@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/ext4.h | 2 ++
+ fs/ext4/extents.c | 19 ++++----------
+ fs/ext4/inode.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 70 insertions(+), 14 deletions(-)
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 75df7eeee50d8..c2e6989a568c2 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -3013,6 +3013,8 @@ extern int ext4_inode_attach_jinode(struct inode *inode);
+ extern int ext4_can_truncate(struct inode *inode);
+ extern int ext4_truncate(struct inode *);
+ extern int ext4_break_layouts(struct inode *);
++extern int ext4_truncate_page_cache_block_range(struct inode *inode,
++ loff_t start, loff_t end);
+ extern int ext4_punch_hole(struct file *file, loff_t offset, loff_t length);
+ extern void ext4_set_inode_flags(struct inode *, bool init);
+ extern int ext4_alloc_da_blocks(struct inode *inode);
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 60909af2d4a53..ba3419958a832 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -4667,22 +4667,13 @@ static long ext4_zero_range(struct file *file, loff_t offset,
+ goto out_mutex;
+ }
+
+- /*
+- * For journalled data we need to write (and checkpoint) pages
+- * before discarding page cache to avoid inconsitent data on
+- * disk in case of crash before zeroing trans is committed.
+- */
+- if (ext4_should_journal_data(inode)) {
+- ret = filemap_write_and_wait_range(mapping, start,
+- end - 1);
+- if (ret) {
+- filemap_invalidate_unlock(mapping);
+- goto out_mutex;
+- }
++ /* Now release the pages and zero block aligned part of pages */
++ ret = ext4_truncate_page_cache_block_range(inode, start, end);
++ if (ret) {
++ filemap_invalidate_unlock(mapping);
++ goto out_mutex;
+ }
+
+- /* Now release the pages and zero block aligned part of pages */
+- truncate_pagecache_range(inode, start, end - 1);
+ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
+
+ ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 819be57bb4ecf..38fe9a213d09b 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -31,6 +31,7 @@
+ #include <linux/writeback.h>
+ #include <linux/pagevec.h>
+ #include <linux/mpage.h>
++#include <linux/rmap.h>
+ #include <linux/namei.h>
+ #include <linux/uio.h>
+ #include <linux/bio.h>
+@@ -3879,6 +3880,68 @@ int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset,
+ return ret;
+ }
+
++static inline void ext4_truncate_folio(struct inode *inode,
++ loff_t start, loff_t end)
++{
++ unsigned long blocksize = i_blocksize(inode);
++ struct folio *folio;
++
++ /* Nothing to be done if no complete block needs to be truncated. */
++ if (round_up(start, blocksize) >= round_down(end, blocksize))
++ return;
++
++ folio = filemap_lock_folio(inode->i_mapping, start >> PAGE_SHIFT);
++ if (IS_ERR(folio))
++ return;
++
++ if (folio_mkclean(folio))
++ folio_mark_dirty(folio);
++ folio_unlock(folio);
++ folio_put(folio);
++}
++
++int ext4_truncate_page_cache_block_range(struct inode *inode,
++ loff_t start, loff_t end)
++{
++ unsigned long blocksize = i_blocksize(inode);
++ int ret;
++
++ /*
++ * For journalled data we need to write (and checkpoint) pages
++ * before discarding page cache to avoid inconsitent data on disk
++ * in case of crash before freeing or unwritten converting trans
++ * is committed.
++ */
++ if (ext4_should_journal_data(inode)) {
++ ret = filemap_write_and_wait_range(inode->i_mapping, start,
++ end - 1);
++ if (ret)
++ return ret;
++ goto truncate_pagecache;
++ }
++
++ /*
++ * If the block size is less than the page size, the file's mapped
++ * blocks within one page could be freed or converted to unwritten.
++ * So it's necessary to remove writable userspace mappings, and then
++ * ext4_page_mkwrite() can be called during subsequent write access
++ * to these partial folios.
++ */
++ if (!IS_ALIGNED(start | end, PAGE_SIZE) &&
++ blocksize < PAGE_SIZE && start < inode->i_size) {
++ loff_t page_boundary = round_up(start, PAGE_SIZE);
++
++ ext4_truncate_folio(inode, start, min(page_boundary, end));
++ if (end > page_boundary)
++ ext4_truncate_folio(inode,
++ round_down(end, PAGE_SIZE), end);
++ }
++
++truncate_pagecache:
++ truncate_pagecache_range(inode, start, end - 1);
++ return 0;
++}
++
+ static void ext4_wait_dax_page(struct inode *inode)
+ {
+ filemap_invalidate_unlock(inode->i_mapping);
+--
+2.39.5
+
--- /dev/null
+From 15c17152b7f486b575660779fed33906f56d097b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 2 Mar 2025 17:06:39 +0100
+Subject: ext4: reorder capability check last
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Christian Göttsche <cgzones@googlemail.com>
+
+[ Upstream commit 1b419c889c0767a5b66d0a6c566cae491f1cb0f7 ]
+
+capable() calls refer to enabled LSMs whether to permit or deny the
+request. This is relevant in connection with SELinux, where a
+capability check results in a policy decision and by default a denial
+message on insufficient permission is issued.
+It can lead to three undesired cases:
+ 1. A denial message is generated, even in case the operation was an
+ unprivileged one and thus the syscall succeeded, creating noise.
+ 2. To avoid the noise from 1. the policy writer adds a rule to ignore
+ those denial messages, hiding future syscalls, where the task
+ performs an actual privileged operation, leading to hidden limited
+ functionality of that task.
+ 3. To avoid the noise from 1. the policy writer adds a rule to permit
+ the task the requested capability, while it does not need it,
+ violating the principle of least privilege.
+
+Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
+Reviewed-by: Serge Hallyn <serge@hallyn.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20250302160657.127253-2-cgoettsche@seltendoof.de
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/balloc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 8042ad8738089..c48fd36b2d74c 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -649,8 +649,8 @@ static int ext4_has_free_clusters(struct ext4_sb_info *sbi,
+ /* Hm, nope. Are (enough) root reserved clusters available? */
+ if (uid_eq(sbi->s_resuid, current_fsuid()) ||
+ (!gid_eq(sbi->s_resgid, GLOBAL_ROOT_GID) && in_group_p(sbi->s_resgid)) ||
+- capable(CAP_SYS_RESOURCE) ||
+- (flags & EXT4_MB_USE_ROOT_BLOCKS)) {
++ (flags & EXT4_MB_USE_ROOT_BLOCKS) ||
++ capable(CAP_SYS_RESOURCE)) {
+
+ if (free_clusters >= (nclusters + dirty_clusters +
+ resv_clusters))
+--
+2.39.5
+
--- /dev/null
+From 0aee74b380502a70551552e1a423ea85d1b2bdfb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Mar 2025 11:12:17 -0600
+Subject: f2fs: defer readonly check vs norecovery
+
+From: Eric Sandeen <sandeen@redhat.com>
+
+[ Upstream commit 9cca49875997a1a7e92800a828a62bacb0f577b9 ]
+
+Defer the readonly-vs-norecovery check until after option parsing is done
+so that option parsing does not require an active superblock for the test.
+Add a helpful message, while we're at it.
+
+(I think could be moved back into parsing after we switch to the new mount
+API if desired, as the fs context will have RO state available.)
+
+Signed-off-by: Eric Sandeen <sandeen@redhat.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/super.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
+index 573cc4725e2e8..280debf2df4f6 100644
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -728,10 +728,8 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
+ set_opt(sbi, DISABLE_ROLL_FORWARD);
+ break;
+ case Opt_norecovery:
+- /* this option mounts f2fs with ro */
++ /* requires ro mount, checked in f2fs_default_check */
+ set_opt(sbi, NORECOVERY);
+- if (!f2fs_readonly(sb))
+- return -EINVAL;
+ break;
+ case Opt_discard:
+ if (!f2fs_hw_support_discard(sbi)) {
+@@ -1406,6 +1404,12 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
+ f2fs_err(sbi, "Allow to mount readonly mode only");
+ return -EROFS;
+ }
++
++ if (test_opt(sbi, NORECOVERY) && !f2fs_readonly(sbi->sb)) {
++ f2fs_err(sbi, "norecovery requires readonly mount");
++ return -EINVAL;
++ }
++
+ return 0;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From ab71a104aa2ef9c1c70827e66076064a25f955d7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jan 2025 05:06:07 +0000
+Subject: f2fs: introduce f2fs_base_attr for global sysfs entries
+
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+
+[ Upstream commit 21925ede449e038ed6f9efdfe0e79f15bddc34bc ]
+
+In /sys/fs/f2fs/features, there's no f2fs_sb_info, so let's avoid to get
+the pointer.
+
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/sysfs.c | 74 ++++++++++++++++++++++++++++++++++---------------
+ 1 file changed, 52 insertions(+), 22 deletions(-)
+
+diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
+index d9a44f03e558b..7df638f901a1f 100644
+--- a/fs/f2fs/sysfs.c
++++ b/fs/f2fs/sysfs.c
+@@ -61,6 +61,12 @@ struct f2fs_attr {
+ int id;
+ };
+
++struct f2fs_base_attr {
++ struct attribute attr;
++ ssize_t (*show)(struct f2fs_base_attr *a, char *buf);
++ ssize_t (*store)(struct f2fs_base_attr *a, const char *buf, size_t len);
++};
++
+ static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
+ struct f2fs_sb_info *sbi, char *buf);
+
+@@ -864,6 +870,25 @@ static void f2fs_sb_release(struct kobject *kobj)
+ complete(&sbi->s_kobj_unregister);
+ }
+
++static ssize_t f2fs_base_attr_show(struct kobject *kobj,
++ struct attribute *attr, char *buf)
++{
++ struct f2fs_base_attr *a = container_of(attr,
++ struct f2fs_base_attr, attr);
++
++ return a->show ? a->show(a, buf) : 0;
++}
++
++static ssize_t f2fs_base_attr_store(struct kobject *kobj,
++ struct attribute *attr,
++ const char *buf, size_t len)
++{
++ struct f2fs_base_attr *a = container_of(attr,
++ struct f2fs_base_attr, attr);
++
++ return a->store ? a->store(a, buf, len) : 0;
++}
++
+ /*
+ * Note that there are three feature list entries:
+ * 1) /sys/fs/f2fs/features
+@@ -882,14 +907,13 @@ static void f2fs_sb_release(struct kobject *kobj)
+ * please add new on-disk feature in this list only.
+ * - ref. F2FS_SB_FEATURE_RO_ATTR()
+ */
+-static ssize_t f2fs_feature_show(struct f2fs_attr *a,
+- struct f2fs_sb_info *sbi, char *buf)
++static ssize_t f2fs_feature_show(struct f2fs_base_attr *a, char *buf)
+ {
+ return sysfs_emit(buf, "supported\n");
+ }
+
+ #define F2FS_FEATURE_RO_ATTR(_name) \
+-static struct f2fs_attr f2fs_attr_##_name = { \
++static struct f2fs_base_attr f2fs_base_attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = 0444 }, \
+ .show = f2fs_feature_show, \
+ }
+@@ -1258,37 +1282,38 @@ static struct attribute *f2fs_attrs[] = {
+ };
+ ATTRIBUTE_GROUPS(f2fs);
+
++#define BASE_ATTR_LIST(name) (&f2fs_base_attr_##name.attr)
+ static struct attribute *f2fs_feat_attrs[] = {
+ #ifdef CONFIG_FS_ENCRYPTION
+- ATTR_LIST(encryption),
+- ATTR_LIST(test_dummy_encryption_v2),
++ BASE_ATTR_LIST(encryption),
++ BASE_ATTR_LIST(test_dummy_encryption_v2),
+ #if IS_ENABLED(CONFIG_UNICODE)
+- ATTR_LIST(encrypted_casefold),
++ BASE_ATTR_LIST(encrypted_casefold),
+ #endif
+ #endif /* CONFIG_FS_ENCRYPTION */
+ #ifdef CONFIG_BLK_DEV_ZONED
+- ATTR_LIST(block_zoned),
++ BASE_ATTR_LIST(block_zoned),
+ #endif
+- ATTR_LIST(atomic_write),
+- ATTR_LIST(extra_attr),
+- ATTR_LIST(project_quota),
+- ATTR_LIST(inode_checksum),
+- ATTR_LIST(flexible_inline_xattr),
+- ATTR_LIST(quota_ino),
+- ATTR_LIST(inode_crtime),
+- ATTR_LIST(lost_found),
++ BASE_ATTR_LIST(atomic_write),
++ BASE_ATTR_LIST(extra_attr),
++ BASE_ATTR_LIST(project_quota),
++ BASE_ATTR_LIST(inode_checksum),
++ BASE_ATTR_LIST(flexible_inline_xattr),
++ BASE_ATTR_LIST(quota_ino),
++ BASE_ATTR_LIST(inode_crtime),
++ BASE_ATTR_LIST(lost_found),
+ #ifdef CONFIG_FS_VERITY
+- ATTR_LIST(verity),
++ BASE_ATTR_LIST(verity),
+ #endif
+- ATTR_LIST(sb_checksum),
++ BASE_ATTR_LIST(sb_checksum),
+ #if IS_ENABLED(CONFIG_UNICODE)
+- ATTR_LIST(casefold),
++ BASE_ATTR_LIST(casefold),
+ #endif
+- ATTR_LIST(readonly),
++ BASE_ATTR_LIST(readonly),
+ #ifdef CONFIG_F2FS_FS_COMPRESSION
+- ATTR_LIST(compression),
++ BASE_ATTR_LIST(compression),
+ #endif
+- ATTR_LIST(pin_file),
++ BASE_ATTR_LIST(pin_file),
+ NULL,
+ };
+ ATTRIBUTE_GROUPS(f2fs_feat);
+@@ -1362,9 +1387,14 @@ static struct kset f2fs_kset = {
+ .kobj = {.ktype = &f2fs_ktype},
+ };
+
++static const struct sysfs_ops f2fs_feat_attr_ops = {
++ .show = f2fs_base_attr_show,
++ .store = f2fs_base_attr_store,
++};
++
+ static const struct kobj_type f2fs_feat_ktype = {
+ .default_groups = f2fs_feat_groups,
+- .sysfs_ops = &f2fs_attr_ops,
++ .sysfs_ops = &f2fs_feat_attr_ops,
+ };
+
+ static struct kobject f2fs_feat = {
+--
+2.39.5
+
--- /dev/null
+From 07ead22454beffa529280a887534e7e1f1041855 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 2 Feb 2025 21:33:46 +0100
+Subject: fbcon: Use correct erase colour for clearing in fbcon
+
+From: Zsolt Kajtar <soci@c64.rulez.org>
+
+[ Upstream commit 892c788d73fe4a94337ed092cb998c49fa8ecaf4 ]
+
+The erase colour calculation for fbcon clearing should use get_color instead
+of attr_col_ec, like everything else. The latter is similar but is not correct.
+For example it's missing the depth dependent remapping and doesn't care about
+blanking.
+
+The problem can be reproduced by setting up the background colour to grey
+(vt.color=0x70) and having an fbcon console set to 2bpp (4 shades of gray).
+Now the background attribute should be 1 (dark gray) on the console.
+
+If the screen is scrolled when pressing enter in a shell prompt at the bottom
+line then the new line is cleared using colour 7 instead of 1. That's not
+something fillrect likes (at 2bbp it expect 0-3) so the result is interesting.
+
+This patch switches to get_color with vc_video_erase_char to determine the
+erase colour from attr_col_ec. That makes the latter function redundant as
+no other users were left.
+
+Use correct erase colour for clearing in fbcon
+
+Signed-off-by: Zsolt Kajtar <soci@c64.rulez.org>
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/fbdev/core/bitblit.c | 5 ++--
+ drivers/video/fbdev/core/fbcon.c | 10 +++++---
+ drivers/video/fbdev/core/fbcon.h | 38 +---------------------------
+ drivers/video/fbdev/core/fbcon_ccw.c | 5 ++--
+ drivers/video/fbdev/core/fbcon_cw.c | 5 ++--
+ drivers/video/fbdev/core/fbcon_ud.c | 5 ++--
+ drivers/video/fbdev/core/tileblit.c | 8 +++---
+ 7 files changed, 18 insertions(+), 58 deletions(-)
+
+diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c
+index 3ff1b2a8659e8..f9475c14f7339 100644
+--- a/drivers/video/fbdev/core/bitblit.c
++++ b/drivers/video/fbdev/core/bitblit.c
+@@ -59,12 +59,11 @@ static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy,
+ }
+
+ static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy,
+- int sx, int height, int width)
++ int sx, int height, int width, int fg, int bg)
+ {
+- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
+ struct fb_fillrect region;
+
+- region.color = attr_bgcol_ec(bgshift, vc, info);
++ region.color = bg;
+ region.dx = sx * vc->vc_font.width;
+ region.dy = sy * vc->vc_font.height;
+ region.width = width * vc->vc_font.width;
+diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
+index e8b4e8c119b5c..07d127110ca4c 100644
+--- a/drivers/video/fbdev/core/fbcon.c
++++ b/drivers/video/fbdev/core/fbcon.c
+@@ -1258,7 +1258,7 @@ static void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
+ {
+ struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+ struct fbcon_ops *ops = info->fbcon_par;
+-
++ int fg, bg;
+ struct fbcon_display *p = &fb_display[vc->vc_num];
+ u_int y_break;
+
+@@ -1279,16 +1279,18 @@ static void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
+ fbcon_clear_margins(vc, 0);
+ }
+
++ fg = get_color(vc, info, vc->vc_video_erase_char, 1);
++ bg = get_color(vc, info, vc->vc_video_erase_char, 0);
+ /* Split blits that cross physical y_wrap boundary */
+
+ y_break = p->vrows - p->yscroll;
+ if (sy < y_break && sy + height - 1 >= y_break) {
+ u_int b = y_break - sy;
+- ops->clear(vc, info, real_y(p, sy), sx, b, width);
++ ops->clear(vc, info, real_y(p, sy), sx, b, width, fg, bg);
+ ops->clear(vc, info, real_y(p, sy + b), sx, height - b,
+- width);
++ width, fg, bg);
+ } else
+- ops->clear(vc, info, real_y(p, sy), sx, height, width);
++ ops->clear(vc, info, real_y(p, sy), sx, height, width, fg, bg);
+ }
+
+ static void fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
+diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
+index df70ea5ec5b37..4d97e6d8a16a2 100644
+--- a/drivers/video/fbdev/core/fbcon.h
++++ b/drivers/video/fbdev/core/fbcon.h
+@@ -55,7 +55,7 @@ struct fbcon_ops {
+ void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy,
+ int sx, int dy, int dx, int height, int width);
+ void (*clear)(struct vc_data *vc, struct fb_info *info, int sy,
+- int sx, int height, int width);
++ int sx, int height, int width, int fb, int bg);
+ void (*putcs)(struct vc_data *vc, struct fb_info *info,
+ const unsigned short *s, int count, int yy, int xx,
+ int fg, int bg);
+@@ -116,42 +116,6 @@ static inline int mono_col(const struct fb_info *info)
+ return (~(0xfff << max_len)) & 0xff;
+ }
+
+-static inline int attr_col_ec(int shift, struct vc_data *vc,
+- struct fb_info *info, int is_fg)
+-{
+- int is_mono01;
+- int col;
+- int fg;
+- int bg;
+-
+- if (!vc)
+- return 0;
+-
+- if (vc->vc_can_do_color)
+- return is_fg ? attr_fgcol(shift,vc->vc_video_erase_char)
+- : attr_bgcol(shift,vc->vc_video_erase_char);
+-
+- if (!info)
+- return 0;
+-
+- col = mono_col(info);
+- is_mono01 = info->fix.visual == FB_VISUAL_MONO01;
+-
+- if (attr_reverse(vc->vc_video_erase_char)) {
+- fg = is_mono01 ? col : 0;
+- bg = is_mono01 ? 0 : col;
+- }
+- else {
+- fg = is_mono01 ? 0 : col;
+- bg = is_mono01 ? col : 0;
+- }
+-
+- return is_fg ? fg : bg;
+-}
+-
+-#define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0)
+-#define attr_fgcol_ec(fgshift, vc, info) attr_col_ec(fgshift, vc, info, 1)
+-
+ /*
+ * Scroll Method
+ */
+diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c
+index f9b794ff7d396..89ef4ba7e8672 100644
+--- a/drivers/video/fbdev/core/fbcon_ccw.c
++++ b/drivers/video/fbdev/core/fbcon_ccw.c
+@@ -78,14 +78,13 @@ static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy,
+ }
+
+ static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy,
+- int sx, int height, int width)
++ int sx, int height, int width, int fg, int bg)
+ {
+ struct fbcon_ops *ops = info->fbcon_par;
+ struct fb_fillrect region;
+- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
+ u32 vyres = GETVYRES(ops->p, info);
+
+- region.color = attr_bgcol_ec(bgshift,vc,info);
++ region.color = bg;
+ region.dx = sy * vc->vc_font.height;
+ region.dy = vyres - ((sx + width) * vc->vc_font.width);
+ region.height = width * vc->vc_font.width;
+diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c
+index 903f6fc174e14..b9dac7940fb77 100644
+--- a/drivers/video/fbdev/core/fbcon_cw.c
++++ b/drivers/video/fbdev/core/fbcon_cw.c
+@@ -63,14 +63,13 @@ static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy,
+ }
+
+ static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy,
+- int sx, int height, int width)
++ int sx, int height, int width, int fg, int bg)
+ {
+ struct fbcon_ops *ops = info->fbcon_par;
+ struct fb_fillrect region;
+- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
+ u32 vxres = GETVXRES(ops->p, info);
+
+- region.color = attr_bgcol_ec(bgshift,vc,info);
++ region.color = bg;
+ region.dx = vxres - ((sy + height) * vc->vc_font.height);
+ region.dy = sx * vc->vc_font.width;
+ region.height = width * vc->vc_font.width;
+diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c
+index 594331936fd3c..0af7913a2abdc 100644
+--- a/drivers/video/fbdev/core/fbcon_ud.c
++++ b/drivers/video/fbdev/core/fbcon_ud.c
+@@ -64,15 +64,14 @@ static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy,
+ }
+
+ static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy,
+- int sx, int height, int width)
++ int sx, int height, int width, int fg, int bg)
+ {
+ struct fbcon_ops *ops = info->fbcon_par;
+ struct fb_fillrect region;
+- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
+ u32 vyres = GETVYRES(ops->p, info);
+ u32 vxres = GETVXRES(ops->p, info);
+
+- region.color = attr_bgcol_ec(bgshift,vc,info);
++ region.color = bg;
+ region.dy = vyres - ((sy + height) * vc->vc_font.height);
+ region.dx = vxres - ((sx + width) * vc->vc_font.width);
+ region.width = width * vc->vc_font.width;
+diff --git a/drivers/video/fbdev/core/tileblit.c b/drivers/video/fbdev/core/tileblit.c
+index eff7ec4da1671..45b0828fad1cf 100644
+--- a/drivers/video/fbdev/core/tileblit.c
++++ b/drivers/video/fbdev/core/tileblit.c
+@@ -32,16 +32,14 @@ static void tile_bmove(struct vc_data *vc, struct fb_info *info, int sy,
+ }
+
+ static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy,
+- int sx, int height, int width)
++ int sx, int height, int width, int fg, int bg)
+ {
+ struct fb_tilerect rect;
+- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
+- int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
+
+ rect.index = vc->vc_video_erase_char &
+ ((vc->vc_hi_font_mask) ? 0x1ff : 0xff);
+- rect.fg = attr_fgcol_ec(fgshift, vc, info);
+- rect.bg = attr_bgcol_ec(bgshift, vc, info);
++ rect.fg = fg;
++ rect.bg = bg;
+ rect.sx = sx;
+ rect.sy = sy;
+ rect.width = width;
+--
+2.39.5
+
--- /dev/null
+From ecc387801b878053ebc8e8fb123b99c602ace104 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 09:18:09 +0100
+Subject: fbdev: core: tileblit: Implement missing margin clearing for tileblit
+
+From: Zsolt Kajtar <soci@c64.rulez.org>
+
+[ Upstream commit 76d3ca89981354e1f85a3e0ad9ac4217d351cc72 ]
+
+I was wondering why there's garbage at the bottom of the screen when
+tile blitting is used with an odd mode like 1080, 600 or 200. Sure there's
+only space for half a tile but the same area is clean when the buffer
+is bitmap.
+
+Then later I found that it's supposed to be cleaned but that's not
+implemented. So I took what's in bitblit and adapted it for tileblit.
+
+This implementation was tested for both the horizontal and vertical case,
+and now does the same as what's done for bitmap buffers.
+
+If anyone is interested to reproduce the problem then I could bet that'd
+be on a S3 or Ark. Just set up a mode with an odd line count and make
+sure that the virtual size covers the complete tile at the bottom. E.g.
+for 600 lines that's 608 virtual lines for a 16 tall tile. Then the
+bottom area should be cleaned.
+
+For the right side it's more difficult as there the drivers won't let an
+odd size happen, unless the code is modified. But once it reports back a
+few pixel columns short then fbcon won't use the last column. With the
+patch that column is now clean.
+
+Btw. the virtual size should be rounded up by the driver for both axes
+(not only the horizontal) so that it's dividable by the tile size.
+That's a driver bug but correcting it is not in scope for this patch.
+
+Implement missing margin clearing for tileblit
+
+Signed-off-by: Zsolt Kajtar <soci@c64.rulez.org>
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/fbdev/core/tileblit.c | 37 ++++++++++++++++++++++++++++-
+ 1 file changed, 36 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/video/fbdev/core/tileblit.c b/drivers/video/fbdev/core/tileblit.c
+index 45b0828fad1cf..d342b90c42b7f 100644
+--- a/drivers/video/fbdev/core/tileblit.c
++++ b/drivers/video/fbdev/core/tileblit.c
+@@ -74,7 +74,42 @@ static void tile_putcs(struct vc_data *vc, struct fb_info *info,
+ static void tile_clear_margins(struct vc_data *vc, struct fb_info *info,
+ int color, int bottom_only)
+ {
+- return;
++ unsigned int cw = vc->vc_font.width;
++ unsigned int ch = vc->vc_font.height;
++ unsigned int rw = info->var.xres - (vc->vc_cols*cw);
++ unsigned int bh = info->var.yres - (vc->vc_rows*ch);
++ unsigned int rs = info->var.xres - rw;
++ unsigned int bs = info->var.yres - bh;
++ unsigned int vwt = info->var.xres_virtual / cw;
++ unsigned int vht = info->var.yres_virtual / ch;
++ struct fb_tilerect rect;
++
++ rect.index = vc->vc_video_erase_char &
++ ((vc->vc_hi_font_mask) ? 0x1ff : 0xff);
++ rect.fg = color;
++ rect.bg = color;
++
++ if ((int) rw > 0 && !bottom_only) {
++ rect.sx = (info->var.xoffset + rs + cw - 1) / cw;
++ rect.sy = 0;
++ rect.width = (rw + cw - 1) / cw;
++ rect.height = vht;
++ if (rect.width + rect.sx > vwt)
++ rect.width = vwt - rect.sx;
++ if (rect.sx < vwt)
++ info->tileops->fb_tilefill(info, &rect);
++ }
++
++ if ((int) bh > 0) {
++ rect.sx = info->var.xoffset / cw;
++ rect.sy = (info->var.yoffset + bs) / ch;
++ rect.width = rs / cw;
++ rect.height = (bh + ch - 1) / ch;
++ if (rect.height + rect.sy > vht)
++ rect.height = vht - rect.sy;
++ if (rect.sy < vht)
++ info->tileops->fb_tilefill(info, &rect);
++ }
+ }
+
+ static void tile_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
+--
+2.39.5
+
--- /dev/null
+From 6749ee14d893b0592e1a841db3f1aed4c3e08578 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Mar 2025 09:54:31 +0800
+Subject: fbdev: fsl-diu-fb: add missing device_remove_file()
+
+From: Shixiong Ou <oushixiong@kylinos.cn>
+
+[ Upstream commit 86d16cd12efa547ed43d16ba7a782c1251c80ea8 ]
+
+Call device_remove_file() when driver remove.
+
+Signed-off-by: Shixiong Ou <oushixiong@kylinos.cn>
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/fbdev/fsl-diu-fb.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/video/fbdev/fsl-diu-fb.c b/drivers/video/fbdev/fsl-diu-fb.c
+index 5ac8201c35337..b71d15794ce8b 100644
+--- a/drivers/video/fbdev/fsl-diu-fb.c
++++ b/drivers/video/fbdev/fsl-diu-fb.c
+@@ -1827,6 +1827,7 @@ static void fsl_diu_remove(struct platform_device *pdev)
+ int i;
+
+ data = dev_get_drvdata(&pdev->dev);
++ device_remove_file(&pdev->dev, &data->dev_attr);
+ disable_lcdc(&data->fsl_diu_info[0]);
+
+ free_irq(data->irq, data->diu_reg);
+--
+2.39.5
+
--- /dev/null
+From a11600ad993853581882e32c9dd1348884a77e8d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 15:38:48 +0000
+Subject: firmware: arm_ffa: Handle the presence of host partition in the
+ partition info
+
+From: Sudeep Holla <sudeep.holla@arm.com>
+
+[ Upstream commit 2f622a8b0722d332a2a149794a3add47bc9bdcf3 ]
+
+Currently it is assumed that the firmware doesn't present the host
+partition in the list of partitions presented as part of the response
+to PARTITION_INFO_GET from the firmware. However, there are few
+platforms that prefer to present the same in the list of partitions.
+It is not manadatory but not restricted as well.
+
+So handle the same by making sure to check the presence of the host
+VM ID in the XArray partition information maintained/managed in the
+driver before attempting to add it.
+
+Tested-by: Viresh Kumar <viresh.kumar@linaro.org>
+Message-Id: <20250217-ffa_updates-v3-7-bd1d9de615e7@arm.com>
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/arm_ffa/driver.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
+index 8dc8654f9f4b2..47751b2c057ae 100644
+--- a/drivers/firmware/arm_ffa/driver.c
++++ b/drivers/firmware/arm_ffa/driver.c
+@@ -1449,6 +1449,10 @@ static int ffa_setup_partitions(void)
+
+ kfree(pbuf);
+
++ /* Check if the host is already added as part of partition info */
++ if (xa_load(&drv_info->partition_info, drv_info->vm_id))
++ return 0;
++
+ /* Allocate for the host */
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+--
+2.39.5
+
--- /dev/null
+From da31d1f852ce38d71086637e0c973e8c67ff1dfe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 15:38:53 +0000
+Subject: firmware: arm_ffa: Reject higher major version as incompatible
+
+From: Sudeep Holla <sudeep.holla@arm.com>
+
+[ Upstream commit efff6a7f16b34fd902f342b58bd8bafc2d6f2fd1 ]
+
+When the firmware compatibility was handled previously in the commit
+8e3f9da608f1 ("firmware: arm_ffa: Handle compatibility with different firmware versions"),
+we only addressed firmware versions that have higher minor versions
+compared to the driver version which is should be considered compatible
+unless the firmware returns NOT_SUPPORTED.
+
+However, if the firmware reports higher major version than the driver
+supported, we need to reject it. If the firmware can work in a compatible
+mode with the driver requested version, it must return the same major
+version as requested.
+
+Tested-by: Viresh Kumar <viresh.kumar@linaro.org>
+Message-Id: <20250217-ffa_updates-v3-12-bd1d9de615e7@arm.com>
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/arm_ffa/driver.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
+index dce448687e28e..8dc8654f9f4b2 100644
+--- a/drivers/firmware/arm_ffa/driver.c
++++ b/drivers/firmware/arm_ffa/driver.c
+@@ -150,6 +150,14 @@ static int ffa_version_check(u32 *version)
+ return -EOPNOTSUPP;
+ }
+
++ if (FFA_MAJOR_VERSION(ver.a0) > FFA_MAJOR_VERSION(FFA_DRIVER_VERSION)) {
++ pr_err("Incompatible v%d.%d! Latest supported v%d.%d\n",
++ FFA_MAJOR_VERSION(ver.a0), FFA_MINOR_VERSION(ver.a0),
++ FFA_MAJOR_VERSION(FFA_DRIVER_VERSION),
++ FFA_MINOR_VERSION(FFA_DRIVER_VERSION));
++ return -EINVAL;
++ }
++
+ if (ver.a0 < FFA_MIN_VERSION) {
+ pr_err("Incompatible v%d.%d! Earliest supported v%d.%d\n",
+ FFA_MAJOR_VERSION(ver.a0), FFA_MINOR_VERSION(ver.a0),
+--
+2.39.5
+
--- /dev/null
+From b536915bdab48de69b3258b4540c70821c9090ab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Jan 2025 15:35:52 +0530
+Subject: firmware: arm_ffa: Set dma_mask for ffa devices
+
+From: Viresh Kumar <viresh.kumar@linaro.org>
+
+[ Upstream commit cc0aac7ca17e0ea3ca84b552fc79f3e86fd07f53 ]
+
+Set dma_mask for FFA devices, otherwise DMA allocation using the device pointer
+lead to following warning:
+
+WARNING: CPU: 1 PID: 1 at kernel/dma/mapping.c:597 dma_alloc_attrs+0xe0/0x124
+
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Message-Id: <e3dd8042ac680bd74b6580c25df855d092079c18.1737107520.git.viresh.kumar@linaro.org>
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/arm_ffa/bus.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c
+index dfda5ffc14db7..dea3eb741d95d 100644
+--- a/drivers/firmware/arm_ffa/bus.c
++++ b/drivers/firmware/arm_ffa/bus.c
+@@ -212,6 +212,7 @@ ffa_device_register(const struct ffa_partition_info *part_info,
+ dev = &ffa_dev->dev;
+ dev->bus = &ffa_bus_type;
+ dev->release = ffa_release_device;
++ dev->dma_mask = &dev->coherent_dma_mask;
+ dev_set_name(&ffa_dev->dev, "arm-ffa-%d", id);
+
+ ffa_dev->id = id;
+--
+2.39.5
+
--- /dev/null
+From b9939b7dc777b1f332dfeeacfa1c9db255313d0d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jan 2025 14:18:20 +0000
+Subject: firmware: arm_scmi: Relax duplicate name constraint across protocol
+ ids
+
+From: Sudeep Holla <sudeep.holla@arm.com>
+
+[ Upstream commit 21ee965267bcbdd733be0f35344fa0f0226d7861 ]
+
+Currently in scmi_protocol_device_request(), no duplicate scmi device
+name is allowed across any protocol. However scmi_dev_match_id() first
+matches the protocol id and then the name. So, there is no strict
+requirement to keep this scmi device name unique across all the protocols.
+
+Relax the constraint on the duplicate name across the protocols and
+inhibit only within the same protocol id.
+
+Message-Id: <20250131141822.514342-1-sudeep.holla@arm.com>
+Reviewed-by: Dhruva Gole <d-gole@ti.com>
+Reviewed-by: Peng Fan <peng.fan@nxp.com>
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/arm_scmi/bus.c | 19 ++++++-------------
+ 1 file changed, 6 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
+index 782c9bec8361c..73a6ab4a224d7 100644
+--- a/drivers/firmware/arm_scmi/bus.c
++++ b/drivers/firmware/arm_scmi/bus.c
+@@ -42,7 +42,7 @@ static atomic_t scmi_syspower_registered = ATOMIC_INIT(0);
+ * This helper let an SCMI driver request specific devices identified by the
+ * @id_table to be created for each active SCMI instance.
+ *
+- * The requested device name MUST NOT be already existent for any protocol;
++ * The requested device name MUST NOT be already existent for this protocol;
+ * at first the freshly requested @id_table is annotated in the IDR table
+ * @scmi_requested_devices and then the requested device is advertised to any
+ * registered party via the @scmi_requested_devices_nh notification chain.
+@@ -52,7 +52,6 @@ static atomic_t scmi_syspower_registered = ATOMIC_INIT(0);
+ static int scmi_protocol_device_request(const struct scmi_device_id *id_table)
+ {
+ int ret = 0;
+- unsigned int id = 0;
+ struct list_head *head, *phead = NULL;
+ struct scmi_requested_dev *rdev;
+
+@@ -67,19 +66,13 @@ static int scmi_protocol_device_request(const struct scmi_device_id *id_table)
+ }
+
+ /*
+- * Search for the matching protocol rdev list and then search
+- * of any existent equally named device...fails if any duplicate found.
++ * Find the matching protocol rdev list and then search of any
++ * existent equally named device...fails if any duplicate found.
+ */
+ mutex_lock(&scmi_requested_devices_mtx);
+- idr_for_each_entry(&scmi_requested_devices, head, id) {
+- if (!phead) {
+- /* A list found registered in the IDR is never empty */
+- rdev = list_first_entry(head, struct scmi_requested_dev,
+- node);
+- if (rdev->id_table->protocol_id ==
+- id_table->protocol_id)
+- phead = head;
+- }
++ phead = idr_find(&scmi_requested_devices, id_table->protocol_id);
++ if (phead) {
++ head = phead;
+ list_for_each_entry(rdev, head, node) {
+ if (!strcmp(rdev->id_table->name, id_table->name)) {
+ pr_err("Ignoring duplicate request [%d] %s\n",
+--
+2.39.5
+
--- /dev/null
+From 71f0c94fdb48e169ef3edf9bbf7db548eb57fb46 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Feb 2025 11:19:51 +0530
+Subject: firmware: xilinx: Dont send linux address to get fpga config get
+ status
+
+From: Siva Durga Prasad Paladugu <siva.durga.prasad.paladugu@amd.com>
+
+[ Upstream commit 5abc174016052caff1bcf4cedb159bd388411e98 ]
+
+Fpga get config status just returns status through ret_payload and there
+is no need to allocate local buf and send its address through SMC args.
+Moreover, the address that is being passed till now is linux virtual
+address and is incorrect.
+Corresponding modification has been done in the firmware to avoid using the
+address sent by linux.
+
+Signed-off-by: Siva Durga Prasad Paladugu <siva.durga.prasad.paladugu@amd.com>
+Signed-off-by: Nava kishore Manne <nava.kishore.manne@amd.com>
+Link: https://lore.kernel.org/r/20250207054951.1650534-1-nava.kishore.manne@amd.com
+Signed-off-by: Michal Simek <michal.simek@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/xilinx/zynqmp.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
+index add8acf66a9c7..5578158f13750 100644
+--- a/drivers/firmware/xilinx/zynqmp.c
++++ b/drivers/firmware/xilinx/zynqmp.c
+@@ -1012,17 +1012,13 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status);
+ int zynqmp_pm_fpga_get_config_status(u32 *value)
+ {
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+- u32 buf, lower_addr, upper_addr;
+ int ret;
+
+ if (!value)
+ return -EINVAL;
+
+- lower_addr = lower_32_bits((u64)&buf);
+- upper_addr = upper_32_bits((u64)&buf);
+-
+ ret = zynqmp_pm_invoke_fn(PM_FPGA_READ, ret_payload, 4,
+- XILINX_ZYNQMP_PM_FPGA_CONFIG_STAT_OFFSET, lower_addr, upper_addr,
++ XILINX_ZYNQMP_PM_FPGA_CONFIG_STAT_OFFSET, 0, 0,
+ XILINX_ZYNQMP_PM_FPGA_READ_CONFIG_REG);
+
+ *value = ret_payload[1];
+--
+2.39.5
+
--- /dev/null
+From 409ab908b8af98312cd98c923eefa1c947a65209 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 06:12:49 +0800
+Subject: fpga: altera-cvp: Increase credit timeout
+
+From: Kuhanh Murugasen Krishnan <kuhanh.murugasen.krishnan@intel.com>
+
+[ Upstream commit 0f05886a40fdc55016ba4d9ae0a9c41f8312f15b ]
+
+Increase the timeout for SDM (Secure device manager) data credits from
+20ms to 40ms. Internal stress tests running at 500 loops failed with the
+current timeout of 20ms. At the start of a FPGA configuration, the CVP
+host driver reads the transmit credits from SDM. It then sends bitstream
+FPGA data to SDM based on the total credits. Each credit allows the
+CVP host driver to send 4kBytes of data. There are situations whereby,
+the SDM did not respond in time during testing.
+
+Signed-off-by: Ang Tien Sung <tien.sung.ang@intel.com>
+Signed-off-by: Kuhanh Murugasen Krishnan <kuhanh.murugasen.krishnan@intel.com>
+Acked-by: Xu Yilun <yilun.xu@intel.com>
+Link: https://lore.kernel.org/r/20250212221249.2715929-1-tien.sung.ang@intel.com
+Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/fpga/altera-cvp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c
+index 6b09144324453..5af0bd33890c0 100644
+--- a/drivers/fpga/altera-cvp.c
++++ b/drivers/fpga/altera-cvp.c
+@@ -52,7 +52,7 @@
+ /* V2 Defines */
+ #define VSE_CVP_TX_CREDITS 0x49 /* 8bit */
+
+-#define V2_CREDIT_TIMEOUT_US 20000
++#define V2_CREDIT_TIMEOUT_US 40000
+ #define V2_CHECK_CREDIT_US 10
+ #define V2_POLL_TIMEOUT_US 1000000
+ #define V2_USER_TIMEOUT_US 500000
+--
+2.39.5
+
--- /dev/null
+From c61a716ed7cc0ed687c3c71ef8713d2b20afe03b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Apr 2025 18:59:16 -0700
+Subject: fs/buffer: introduce sleeping flavors for pagecache lookups
+
+From: Davidlohr Bueso <dave@stgolabs.net>
+
+[ Upstream commit 2814a7d3d2ff5d2cdd22936f641f758fdb971fa0 ]
+
+Add __find_get_block_nonatomic() and sb_find_get_block_nonatomic()
+calls for which users will be converted where safe. These versions
+will take the folio lock instead of the mapping's private_lock.
+
+Reviewed-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
+Link: https://kdevops.org/ext4/v6.15-rc2.html # [0]
+Link: https://lore.kernel.org/all/aAAEvcrmREWa1SKF@bombadil.infradead.org/ # [1]
+Link: https://lore.kernel.org/20250418015921.132400-3-dave@stgolabs.net
+Tested-by: kdevops@lists.linux.dev
+Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/buffer.c | 9 +++++++++
+ include/linux/buffer_head.h | 8 ++++++++
+ 2 files changed, 17 insertions(+)
+
+diff --git a/fs/buffer.c b/fs/buffer.c
+index ba464c2002061..b04705eb6cc57 100644
+--- a/fs/buffer.c
++++ b/fs/buffer.c
+@@ -1420,6 +1420,15 @@ __find_get_block(struct block_device *bdev, sector_t block, unsigned size)
+ }
+ EXPORT_SYMBOL(__find_get_block);
+
++/* same as __find_get_block() but allows sleeping contexts */
++struct buffer_head *
++__find_get_block_nonatomic(struct block_device *bdev, sector_t block,
++ unsigned size)
++{
++ return find_get_block_common(bdev, block, size, false);
++}
++EXPORT_SYMBOL(__find_get_block_nonatomic);
++
+ /**
+ * bdev_getblk - Get a buffer_head in a block device's buffer cache.
+ * @bdev: The block device.
+diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
+index 932139c5d46f5..ffcd76d977703 100644
+--- a/include/linux/buffer_head.h
++++ b/include/linux/buffer_head.h
+@@ -223,6 +223,8 @@ void __wait_on_buffer(struct buffer_head *);
+ wait_queue_head_t *bh_waitq_head(struct buffer_head *bh);
+ struct buffer_head *__find_get_block(struct block_device *bdev, sector_t block,
+ unsigned size);
++struct buffer_head *__find_get_block_nonatomic(struct block_device *bdev,
++ sector_t block, unsigned size);
+ struct buffer_head *bdev_getblk(struct block_device *bdev, sector_t block,
+ unsigned size, gfp_t gfp);
+ void __brelse(struct buffer_head *);
+@@ -398,6 +400,12 @@ sb_find_get_block(struct super_block *sb, sector_t block)
+ return __find_get_block(sb->s_bdev, block, sb->s_blocksize);
+ }
+
++static inline struct buffer_head *
++sb_find_get_block_nonatomic(struct super_block *sb, sector_t block)
++{
++ return __find_get_block_nonatomic(sb->s_bdev, block, sb->s_blocksize);
++}
++
+ static inline void
+ map_bh(struct buffer_head *bh, struct super_block *sb, sector_t block)
+ {
+--
+2.39.5
+
--- /dev/null
+From 2897cbf60f8a57ab14753a4569399f1e95aab3c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Apr 2025 18:59:15 -0700
+Subject: fs/buffer: split locking for pagecache lookups
+
+From: Davidlohr Bueso <dave@stgolabs.net>
+
+[ Upstream commit 7ffe3de53a885dbb5836541c2178bd07d1bad7df ]
+
+Callers of __find_get_block() may or may not allow for blocking
+semantics, and is currently assumed that it will not. Layout
+two paths based on this. The the private_lock scheme will
+continued to be used for atomic contexts. Otherwise take the
+folio lock instead, which protects the buffers, such as
+vs migration and try_to_free_buffers().
+
+Per the "hack idea", the latter can alleviate contention on
+the private_lock for bdev mappings. For reasons of determinism
+and avoid making bugs hard to reproduce, the trylocking is not
+attempted.
+
+No change in semantics. All lookup users still take the spinlock.
+
+Reviewed-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
+Link: https://kdevops.org/ext4/v6.15-rc2.html # [0]
+Link: https://lore.kernel.org/all/aAAEvcrmREWa1SKF@bombadil.infradead.org/ # [1]
+Link: https://lore.kernel.org/20250418015921.132400-2-dave@stgolabs.net
+Tested-by: kdevops@lists.linux.dev
+Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/buffer.c | 41 +++++++++++++++++++++++++----------------
+ 1 file changed, 25 insertions(+), 16 deletions(-)
+
+diff --git a/fs/buffer.c b/fs/buffer.c
+index 32bd0f4c42236..ba464c2002061 100644
+--- a/fs/buffer.c
++++ b/fs/buffer.c
+@@ -176,18 +176,8 @@ void end_buffer_write_sync(struct buffer_head *bh, int uptodate)
+ }
+ EXPORT_SYMBOL(end_buffer_write_sync);
+
+-/*
+- * Various filesystems appear to want __find_get_block to be non-blocking.
+- * But it's the page lock which protects the buffers. To get around this,
+- * we get exclusion from try_to_free_buffers with the blockdev mapping's
+- * i_private_lock.
+- *
+- * Hack idea: for the blockdev mapping, i_private_lock contention
+- * may be quite high. This code could TryLock the page, and if that
+- * succeeds, there is no need to take i_private_lock.
+- */
+ static struct buffer_head *
+-__find_get_block_slow(struct block_device *bdev, sector_t block)
++__find_get_block_slow(struct block_device *bdev, sector_t block, bool atomic)
+ {
+ struct address_space *bd_mapping = bdev->bd_mapping;
+ const int blkbits = bd_mapping->host->i_blkbits;
+@@ -204,7 +194,16 @@ __find_get_block_slow(struct block_device *bdev, sector_t block)
+ if (IS_ERR(folio))
+ goto out;
+
+- spin_lock(&bd_mapping->i_private_lock);
++ /*
++ * Folio lock protects the buffers. Callers that cannot block
++ * will fallback to serializing vs try_to_free_buffers() via
++ * the i_private_lock.
++ */
++ if (atomic)
++ spin_lock(&bd_mapping->i_private_lock);
++ else
++ folio_lock(folio);
++
+ head = folio_buffers(folio);
+ if (!head)
+ goto out_unlock;
+@@ -236,7 +235,10 @@ __find_get_block_slow(struct block_device *bdev, sector_t block)
+ 1 << blkbits);
+ }
+ out_unlock:
+- spin_unlock(&bd_mapping->i_private_lock);
++ if (atomic)
++ spin_unlock(&bd_mapping->i_private_lock);
++ else
++ folio_unlock(folio);
+ folio_put(folio);
+ out:
+ return ret;
+@@ -1394,14 +1396,15 @@ lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size)
+ * it in the LRU and mark it as accessed. If it is not present then return
+ * NULL
+ */
+-struct buffer_head *
+-__find_get_block(struct block_device *bdev, sector_t block, unsigned size)
++static struct buffer_head *
++find_get_block_common(struct block_device *bdev, sector_t block,
++ unsigned size, bool atomic)
+ {
+ struct buffer_head *bh = lookup_bh_lru(bdev, block, size);
+
+ if (bh == NULL) {
+ /* __find_get_block_slow will mark the page accessed */
+- bh = __find_get_block_slow(bdev, block);
++ bh = __find_get_block_slow(bdev, block, atomic);
+ if (bh)
+ bh_lru_install(bh);
+ } else
+@@ -1409,6 +1412,12 @@ __find_get_block(struct block_device *bdev, sector_t block, unsigned size)
+
+ return bh;
+ }
++
++struct buffer_head *
++__find_get_block(struct block_device *bdev, sector_t block, unsigned size)
++{
++ return find_get_block_common(bdev, block, size, true);
++}
+ EXPORT_SYMBOL(__find_get_block);
+
+ /**
+--
+2.39.5
+
--- /dev/null
+From 41a1c35203be1f9fb4e851c0ec7caafdfc89c249 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Apr 2025 18:59:17 -0700
+Subject: fs/buffer: use sleeping version of __find_get_block()
+
+From: Davidlohr Bueso <dave@stgolabs.net>
+
+[ Upstream commit 5b67d43976828dea2394eae2556b369bb7a61f64 ]
+
+Convert to the new nonatomic flavor to benefit from potential performance
+benefits and adapt in the future vs migration such that semantics
+are kept.
+
+Convert write_boundary_block() which already takes the buffer
+lock as well as bdev_getblk() depending on the respective gpf flags.
+There are no changes in semantics.
+
+Suggested-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
+Link: https://kdevops.org/ext4/v6.15-rc2.html # [0]
+Link: https://lore.kernel.org/all/aAAEvcrmREWa1SKF@bombadil.infradead.org/ # [1]
+Link: https://lore.kernel.org/20250418015921.132400-4-dave@stgolabs.net
+Tested-by: kdevops@lists.linux.dev # [0] [1]
+Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/buffer.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/fs/buffer.c b/fs/buffer.c
+index b04705eb6cc57..e9e84512a027a 100644
+--- a/fs/buffer.c
++++ b/fs/buffer.c
+@@ -658,7 +658,9 @@ EXPORT_SYMBOL(generic_buffers_fsync);
+ void write_boundary_block(struct block_device *bdev,
+ sector_t bblock, unsigned blocksize)
+ {
+- struct buffer_head *bh = __find_get_block(bdev, bblock + 1, blocksize);
++ struct buffer_head *bh;
++
++ bh = __find_get_block_nonatomic(bdev, bblock + 1, blocksize);
+ if (bh) {
+ if (buffer_dirty(bh))
+ write_dirty_buffer(bh, 0);
+@@ -1446,7 +1448,12 @@ EXPORT_SYMBOL(__find_get_block_nonatomic);
+ struct buffer_head *bdev_getblk(struct block_device *bdev, sector_t block,
+ unsigned size, gfp_t gfp)
+ {
+- struct buffer_head *bh = __find_get_block(bdev, block, size);
++ struct buffer_head *bh;
++
++ if (gfpflags_allow_blocking(gfp))
++ bh = __find_get_block_nonatomic(bdev, block, size);
++ else
++ bh = __find_get_block(bdev, block, size);
+
+ might_alloc(gfp);
+ if (bh)
+--
+2.39.5
+
--- /dev/null
+From b17ced97330cd7979a120e24cba921f869d4d861 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Apr 2025 18:59:20 -0700
+Subject: fs/ext4: use sleeping version of sb_find_get_block()
+
+From: Davidlohr Bueso <dave@stgolabs.net>
+
+[ Upstream commit 6e8f57fd09c9fb569d10b2ccc3878155b702591a ]
+
+Enable ext4_free_blocks() to use it, which has a cond_resched to begin
+with. Convert to the new nonatomic flavor to benefit from potential
+performance benefits and adapt in the future vs migration such that
+semantics are kept.
+
+Suggested-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
+Link: https://kdevops.org/ext4/v6.15-rc2.html # [0]
+Link: https://lore.kernel.org/all/aAAEvcrmREWa1SKF@bombadil.infradead.org/ # [1]
+Link: https://lore.kernel.org/20250418015921.132400-7-dave@stgolabs.net
+Tested-by: kdevops@lists.linux.dev
+Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/mballoc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 92f49d7eb3c00..109cf88e7caac 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -6644,7 +6644,8 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ for (i = 0; i < count; i++) {
+ cond_resched();
+ if (is_metadata)
+- bh = sb_find_get_block(inode->i_sb, block + i);
++ bh = sb_find_get_block_nonatomic(inode->i_sb,
++ block + i);
+ ext4_forget(handle, is_metadata, inode, bh, block + i);
+ }
+ }
+--
+2.39.5
+
--- /dev/null
+From 0cb2501c96be84c28109a6be7e5a95117dc61b7f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Apr 2025 18:59:19 -0700
+Subject: fs/jbd2: use sleeping version of __find_get_block()
+
+From: Davidlohr Bueso <dave@stgolabs.net>
+
+[ Upstream commit f76d4c28a46a9260d85e00dafc8f46d369365d33 ]
+
+Convert to the new nonatomic flavor to benefit from potential
+performance benefits and adapt in the future vs migration such
+that semantics are kept.
+
+- jbd2_journal_revoke(): can sleep (has might_sleep() in the beginning)
+
+- jbd2_journal_cancel_revoke(): only used from do_get_write_access() and
+ do_get_create_access() which do sleep. So can sleep.
+
+- jbd2_clear_buffer_revoked_flags() - only called from journal commit code
+ which sleeps. So can sleep.
+
+Suggested-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
+Link: https://kdevops.org/ext4/v6.15-rc2.html # [0]
+Link: https://lore.kernel.org/all/aAAEvcrmREWa1SKF@bombadil.infradead.org/ # [1]
+Link: https://lore.kernel.org/20250418015921.132400-6-dave@stgolabs.net
+Tested-by: kdevops@lists.linux.dev
+Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jbd2/revoke.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
+index ce63d5fde9c3a..f68fc8c255f00 100644
+--- a/fs/jbd2/revoke.c
++++ b/fs/jbd2/revoke.c
+@@ -345,7 +345,8 @@ int jbd2_journal_revoke(handle_t *handle, unsigned long long blocknr,
+ bh = bh_in;
+
+ if (!bh) {
+- bh = __find_get_block(bdev, blocknr, journal->j_blocksize);
++ bh = __find_get_block_nonatomic(bdev, blocknr,
++ journal->j_blocksize);
+ if (bh)
+ BUFFER_TRACE(bh, "found on hash");
+ }
+@@ -355,7 +356,8 @@ int jbd2_journal_revoke(handle_t *handle, unsigned long long blocknr,
+
+ /* If there is a different buffer_head lying around in
+ * memory anywhere... */
+- bh2 = __find_get_block(bdev, blocknr, journal->j_blocksize);
++ bh2 = __find_get_block_nonatomic(bdev, blocknr,
++ journal->j_blocksize);
+ if (bh2) {
+ /* ... and it has RevokeValid status... */
+ if (bh2 != bh && buffer_revokevalid(bh2))
+@@ -466,7 +468,8 @@ int jbd2_journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
+ * state machine will get very upset later on. */
+ if (need_cancel) {
+ struct buffer_head *bh2;
+- bh2 = __find_get_block(bh->b_bdev, bh->b_blocknr, bh->b_size);
++ bh2 = __find_get_block_nonatomic(bh->b_bdev, bh->b_blocknr,
++ bh->b_size);
+ if (bh2) {
+ if (bh2 != bh)
+ clear_buffer_revoked(bh2);
+@@ -495,9 +498,9 @@ void jbd2_clear_buffer_revoked_flags(journal_t *journal)
+ struct jbd2_revoke_record_s *record;
+ struct buffer_head *bh;
+ record = (struct jbd2_revoke_record_s *)list_entry;
+- bh = __find_get_block(journal->j_fs_dev,
+- record->blocknr,
+- journal->j_blocksize);
++ bh = __find_get_block_nonatomic(journal->j_fs_dev,
++ record->blocknr,
++ journal->j_blocksize);
+ if (bh) {
+ clear_buffer_revoked(bh);
+ __brelse(bh);
+--
+2.39.5
+
--- /dev/null
+From f2345d09fc1cbee743f0fae7e636e69045e8ec0b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Feb 2025 14:38:18 -0800
+Subject: fs/mpage: avoid negative shift for large blocksize
+
+From: Hannes Reinecke <hare@kernel.org>
+
+[ Upstream commit 86c60efd7c0ede43bd677f2eee1d84200528df1e ]
+
+For large blocksizes the number of block bits is larger than PAGE_SHIFT,
+so calculate the sector number from the byte offset instead. This is
+required to enable large folios with buffer-heads.
+
+Reviewed-by: "Matthew Wilcox (Oracle)" <willy@infradead.org>
+Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
+Signed-off-by: Hannes Reinecke <hare@kernel.org>
+Link: https://lore.kernel.org/r/20250221223823.1680616-4-mcgrof@kernel.org
+Reviewed-by: Hannes Reinecke <hare@suse.de>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/mpage.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/fs/mpage.c b/fs/mpage.c
+index 82aecf3727437..a3c82206977f6 100644
+--- a/fs/mpage.c
++++ b/fs/mpage.c
+@@ -181,7 +181,7 @@ static struct bio *do_mpage_readpage(struct mpage_readpage_args *args)
+ if (folio_buffers(folio))
+ goto confused;
+
+- block_in_file = (sector_t)folio->index << (PAGE_SHIFT - blkbits);
++ block_in_file = folio_pos(folio) >> blkbits;
+ last_block = block_in_file + args->nr_pages * blocks_per_page;
+ last_block_in_file = (i_size_read(inode) + blocksize - 1) >> blkbits;
+ if (last_block > last_block_in_file)
+@@ -527,7 +527,7 @@ static int __mpage_writepage(struct folio *folio, struct writeback_control *wbc,
+ * The page has no buffers: map it to disk
+ */
+ BUG_ON(!folio_test_uptodate(folio));
+- block_in_file = (sector_t)folio->index << (PAGE_SHIFT - blkbits);
++ block_in_file = folio_pos(folio) >> blkbits;
+ /*
+ * Whole page beyond EOF? Skip allocating blocks to avoid leaking
+ * space.
+--
+2.39.5
+
--- /dev/null
+From 845bc2817038b7a0cbb65812d850b945519c7130 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Apr 2025 18:59:18 -0700
+Subject: fs/ocfs2: use sleeping version of __find_get_block()
+
+From: Davidlohr Bueso <dave@stgolabs.net>
+
+[ Upstream commit a0b5ff07491010789fcb012bc8f9dad9d26f9a8b ]
+
+This is a path that allows for blocking as it does IO. Convert
+to the new nonatomic flavor to benefit from potential performance
+benefits and adapt in the future vs migration such that semantics
+are kept.
+
+Suggested-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
+Link: https://kdevops.org/ext4/v6.15-rc2.html # [0]
+Link: https://lore.kernel.org/all/aAAEvcrmREWa1SKF@bombadil.infradead.org/ # [1]
+Link: https://lore.kernel.org/20250418015921.132400-5-dave@stgolabs.net
+Tested-by: kdevops@lists.linux.dev
+Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ocfs2/journal.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
+index 2ebee1dced1b2..c2a73bfb16aa4 100644
+--- a/fs/ocfs2/journal.c
++++ b/fs/ocfs2/journal.c
+@@ -1271,7 +1271,7 @@ static int ocfs2_force_read_journal(struct inode *inode)
+ }
+
+ for (i = 0; i < p_blocks; i++, p_blkno++) {
+- bh = __find_get_block(osb->sb->s_bdev, p_blkno,
++ bh = __find_get_block_nonatomic(osb->sb->s_bdev, p_blkno,
+ osb->sb->s_blocksize);
+ /* block not cached. */
+ if (!bh)
+--
+2.39.5
+
--- /dev/null
+From 2f25ea731c746fdd66008d7ee567fe7aacf6c834 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Feb 2025 09:17:53 +0800
+Subject: fuse: Return EPERM rather than ENOSYS from link()
+
+From: Matt Johnston <matt@codeconstruct.com.au>
+
+[ Upstream commit 8344213571b2ac8caf013cfd3b37bc3467c3a893 ]
+
+link() is documented to return EPERM when a filesystem doesn't support
+the operation, return that instead.
+
+Link: https://github.com/libfuse/libfuse/issues/925
+Signed-off-by: Matt Johnston <matt@codeconstruct.com.au>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/fuse/dir.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
+index a1e86ec07c38b..ff543dc09130e 100644
+--- a/fs/fuse/dir.c
++++ b/fs/fuse/dir.c
+@@ -1133,6 +1133,8 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
+ else if (err == -EINTR)
+ fuse_invalidate_attr(inode);
+
++ if (err == -ENOSYS)
++ err = -EPERM;
+ return err;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 37e79f542e8dd33af973a1ae4fc93090f05654e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Feb 2025 17:31:36 -0800
+Subject: genirq/msi: Store the IOMMU IOVA directly in msi_desc instead of
+ iommu_cookie
+
+From: Jason Gunthorpe <jgg@nvidia.com>
+
+[ Upstream commit 1f7df3a691740a7736bbc99dc4ed536120eb4746 ]
+
+The IOMMU translation for MSI message addresses has been a 2-step process,
+separated in time:
+
+ 1) iommu_dma_prepare_msi(): A cookie pointer containing the IOVA address
+ is stored in the MSI descriptor when an MSI interrupt is allocated.
+
+ 2) iommu_dma_compose_msi_msg(): this cookie pointer is used to compute a
+ translated message address.
+
+This has an inherent lifetime problem for the pointer stored in the cookie
+that must remain valid between the two steps. However, there is no locking
+at the irq layer that helps protect the lifetime. Today, this works under
+the assumption that the iommu domain is not changed while MSI interrupts
+being programmed. This is true for normal DMA API users within the kernel,
+as the iommu domain is attached before the driver is probed and cannot be
+changed while a driver is attached.
+
+Classic VFIO type1 also prevented changing the iommu domain while VFIO was
+running as it does not support changing the "container" after starting up.
+
+However, iommufd has improved this so that the iommu domain can be changed
+during VFIO operation. This potentially allows userspace to directly race
+VFIO_DEVICE_ATTACH_IOMMUFD_PT (which calls iommu_attach_group()) and
+VFIO_DEVICE_SET_IRQS (which calls into iommu_dma_compose_msi_msg()).
+
+This potentially causes both the cookie pointer and the unlocked call to
+iommu_get_domain_for_dev() on the MSI translation path to become UAFs.
+
+Fix the MSI cookie UAF by removing the cookie pointer. The translated IOVA
+address is already known during iommu_dma_prepare_msi() and cannot change.
+Thus, it can simply be stored as an integer in the MSI descriptor.
+
+The other UAF related to iommu_get_domain_for_dev() will be addressed in
+patch "iommu: Make iommu_dma_prepare_msi() into a generic operation" by
+using the IOMMU group mutex.
+
+Link: https://patch.msgid.link/r/a4f2cd76b9dc1833ee6c1cf325cba57def22231c.1740014950.git.nicolinc@nvidia.com
+Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
+Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/dma-iommu.c | 28 +++++++++++++---------------
+ include/linux/msi.h | 33 ++++++++++++---------------------
+ 2 files changed, 25 insertions(+), 36 deletions(-)
+
+diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
+index 2a9fa0c8cc00f..0f0caf59023c7 100644
+--- a/drivers/iommu/dma-iommu.c
++++ b/drivers/iommu/dma-iommu.c
+@@ -1815,7 +1815,7 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
+ static DEFINE_MUTEX(msi_prepare_lock); /* see below */
+
+ if (!domain || !domain->iova_cookie) {
+- desc->iommu_cookie = NULL;
++ msi_desc_set_iommu_msi_iova(desc, 0, 0);
+ return 0;
+ }
+
+@@ -1827,11 +1827,12 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
+ mutex_lock(&msi_prepare_lock);
+ msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain);
+ mutex_unlock(&msi_prepare_lock);
+-
+- msi_desc_set_iommu_cookie(desc, msi_page);
+-
+ if (!msi_page)
+ return -ENOMEM;
++
++ msi_desc_set_iommu_msi_iova(
++ desc, msi_page->iova,
++ ilog2(cookie_msi_granule(domain->iova_cookie)));
+ return 0;
+ }
+
+@@ -1842,18 +1843,15 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
+ */
+ void iommu_dma_compose_msi_msg(struct msi_desc *desc, struct msi_msg *msg)
+ {
+- struct device *dev = msi_desc_to_dev(desc);
+- const struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
+- const struct iommu_dma_msi_page *msi_page;
++#ifdef CONFIG_IRQ_MSI_IOMMU
++ if (desc->iommu_msi_shift) {
++ u64 msi_iova = desc->iommu_msi_iova << desc->iommu_msi_shift;
+
+- msi_page = msi_desc_get_iommu_cookie(desc);
+-
+- if (!domain || !domain->iova_cookie || WARN_ON(!msi_page))
+- return;
+-
+- msg->address_hi = upper_32_bits(msi_page->iova);
+- msg->address_lo &= cookie_msi_granule(domain->iova_cookie) - 1;
+- msg->address_lo += lower_32_bits(msi_page->iova);
++ msg->address_hi = upper_32_bits(msi_iova);
++ msg->address_lo = lower_32_bits(msi_iova) |
++ (msg->address_lo & ((1 << desc->iommu_msi_shift) - 1));
++ }
++#endif
+ }
+
+ static int iommu_dma_init(void)
+diff --git a/include/linux/msi.h b/include/linux/msi.h
+index 59a421fc42bf0..63d0e51f7a801 100644
+--- a/include/linux/msi.h
++++ b/include/linux/msi.h
+@@ -165,6 +165,10 @@ struct msi_desc_data {
+ * @dev: Pointer to the device which uses this descriptor
+ * @msg: The last set MSI message cached for reuse
+ * @affinity: Optional pointer to a cpu affinity mask for this descriptor
++ * @iommu_msi_iova: Optional shifted IOVA from the IOMMU to override the msi_addr.
++ * Only used if iommu_msi_shift != 0
++ * @iommu_msi_shift: Indicates how many bits of the original address should be
++ * preserved when using iommu_msi_iova.
+ * @sysfs_attr: Pointer to sysfs device attribute
+ *
+ * @write_msi_msg: Callback that may be called when the MSI message
+@@ -183,7 +187,8 @@ struct msi_desc {
+ struct msi_msg msg;
+ struct irq_affinity_desc *affinity;
+ #ifdef CONFIG_IRQ_MSI_IOMMU
+- const void *iommu_cookie;
++ u64 iommu_msi_iova : 58;
++ u64 iommu_msi_shift : 6;
+ #endif
+ #ifdef CONFIG_SYSFS
+ struct device_attribute *sysfs_attrs;
+@@ -284,28 +289,14 @@ struct msi_desc *msi_next_desc(struct device *dev, unsigned int domid,
+
+ #define msi_desc_to_dev(desc) ((desc)->dev)
+
+-#ifdef CONFIG_IRQ_MSI_IOMMU
+-static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
+-{
+- return desc->iommu_cookie;
+-}
+-
+-static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc,
+- const void *iommu_cookie)
+-{
+- desc->iommu_cookie = iommu_cookie;
+-}
+-#else
+-static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
++static inline void msi_desc_set_iommu_msi_iova(struct msi_desc *desc, u64 msi_iova,
++ unsigned int msi_shift)
+ {
+- return NULL;
+-}
+-
+-static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc,
+- const void *iommu_cookie)
+-{
+-}
++#ifdef CONFIG_IRQ_MSI_IOMMU
++ desc->iommu_msi_iova = msi_iova >> msi_shift;
++ desc->iommu_msi_shift = msi_shift;
+ #endif
++}
+
+ int msi_domain_insert_msi_desc(struct device *dev, unsigned int domid,
+ struct msi_desc *init_desc);
+--
+2.39.5
+
--- /dev/null
+From 08d60b86830ca8e02e4daeca23e247005835b516 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Feb 2025 14:58:39 +0100
+Subject: gfs2: Check for empty queue in run_queue
+
+From: Andreas Gruenbacher <agruenba@redhat.com>
+
+[ Upstream commit d838605fea6eabae3746a276fd448f6719eb3926 ]
+
+In run_queue(), check if the queue of pending requests is empty instead
+of blindly assuming that it won't be.
+
+Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/gfs2/glock.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
+index a51fe42732c4c..4f1eca99786b6 100644
+--- a/fs/gfs2/glock.c
++++ b/fs/gfs2/glock.c
+@@ -843,12 +843,13 @@ static void run_queue(struct gfs2_glock *gl, const int nonblock)
+ __releases(&gl->gl_lockref.lock)
+ __acquires(&gl->gl_lockref.lock)
+ {
+- struct gfs2_holder *gh = NULL;
++ struct gfs2_holder *gh;
+
+ if (test_bit(GLF_LOCK, &gl->gl_flags))
+ return;
+ set_bit(GLF_LOCK, &gl->gl_flags);
+
++ /* While a demote is in progress, the GLF_LOCK flag must be set. */
+ GLOCK_BUG_ON(gl, test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags));
+
+ if (test_bit(GLF_DEMOTE, &gl->gl_flags) &&
+@@ -860,18 +861,22 @@ __acquires(&gl->gl_lockref.lock)
+ set_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags);
+ GLOCK_BUG_ON(gl, gl->gl_demote_state == LM_ST_EXCLUSIVE);
+ gl->gl_target = gl->gl_demote_state;
++ do_xmote(gl, NULL, gl->gl_target);
++ return;
+ } else {
+ if (test_bit(GLF_DEMOTE, &gl->gl_flags))
+ gfs2_demote_wake(gl);
+ if (do_promote(gl))
+ goto out_unlock;
+ gh = find_first_waiter(gl);
++ if (!gh)
++ goto out_unlock;
+ gl->gl_target = gh->gh_state;
+ if (!(gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)))
+ do_error(gl, 0); /* Fail queued try locks */
++ do_xmote(gl, gh, gl->gl_target);
++ return;
+ }
+- do_xmote(gl, gh, gl->gl_target);
+- return;
+
+ out_sched:
+ clear_bit(GLF_LOCK, &gl->gl_flags);
+--
+2.39.5
+
--- /dev/null
+From be4d0ffcf0986018a2be0ade52de6305f326142b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Nov 2024 10:35:18 +0800
+Subject: HID: usbkbd: Fix the bit shift number for LED_KANA
+
+From: junan <junan76@163.com>
+
+[ Upstream commit d73a4bfa2881a6859b384b75a414c33d4898b055 ]
+
+Since "LED_KANA" was defined as "0x04", the shift number should be "4".
+
+Signed-off-by: junan <junan76@163.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/usbkbd.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
+index c439ed2f16dbc..af6bc76dbf649 100644
+--- a/drivers/hid/usbhid/usbkbd.c
++++ b/drivers/hid/usbhid/usbkbd.c
+@@ -160,7 +160,7 @@ static int usb_kbd_event(struct input_dev *dev, unsigned int type,
+ return -1;
+
+ spin_lock_irqsave(&kbd->leds_lock, flags);
+- kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) |
++ kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 4) | (!!test_bit(LED_COMPOSE, dev->led) << 3) |
+ (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) |
+ (!!test_bit(LED_NUML, dev->led));
+
+--
+2.39.5
+
--- /dev/null
+From 9c25489ab1f01dfe329d2edabf7d8b1f9c401c0b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Feb 2025 15:43:33 +0200
+Subject: hrtimers: Replace hrtimer_clock_to_base_table with switch-case
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 4441b976dfeff0d3579e8da3c0283300c618a553 ]
+
+Clang and GCC complain about overlapped initialisers in the
+hrtimer_clock_to_base_table definition. With `make W=1` and CONFIG_WERROR=y
+(which is default nowadays) this breaks the build:
+
+ CC kernel/time/hrtimer.o
+kernel/time/hrtimer.c:124:21: error: initializer overrides prior initialization of this subobject [-Werror,-Winitializer-overrides]
+ 124 | [CLOCK_REALTIME] = HRTIMER_BASE_REALTIME,
+
+kernel/time/hrtimer.c:122:27: note: previous initialization is here
+ 122 | [0 ... MAX_CLOCKS - 1] = HRTIMER_MAX_CLOCK_BASES,
+
+(and similar for CLOCK_MONOTONIC, CLOCK_BOOTTIME, and CLOCK_TAI).
+
+hrtimer_clockid_to_base(), which uses the table, is only used in
+__hrtimer_init(), which is not a hotpath.
+
+Therefore replace the table lookup with a switch case in
+hrtimer_clockid_to_base() to avoid this warning.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/all/20250214134424.3367619-1-andriy.shevchenko@linux.intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/time/hrtimer.c | 29 ++++++++++++-----------------
+ 1 file changed, 12 insertions(+), 17 deletions(-)
+
+diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
+index db9c06bb23116..06fbc226341fd 100644
+--- a/kernel/time/hrtimer.c
++++ b/kernel/time/hrtimer.c
+@@ -117,16 +117,6 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
+ .csd = CSD_INIT(retrigger_next_event, NULL)
+ };
+
+-static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = {
+- /* Make sure we catch unsupported clockids */
+- [0 ... MAX_CLOCKS - 1] = HRTIMER_MAX_CLOCK_BASES,
+-
+- [CLOCK_REALTIME] = HRTIMER_BASE_REALTIME,
+- [CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC,
+- [CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME,
+- [CLOCK_TAI] = HRTIMER_BASE_TAI,
+-};
+-
+ static inline bool hrtimer_base_is_online(struct hrtimer_cpu_base *base)
+ {
+ if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
+@@ -1597,14 +1587,19 @@ u64 hrtimer_next_event_without(const struct hrtimer *exclude)
+
+ static inline int hrtimer_clockid_to_base(clockid_t clock_id)
+ {
+- if (likely(clock_id < MAX_CLOCKS)) {
+- int base = hrtimer_clock_to_base_table[clock_id];
+-
+- if (likely(base != HRTIMER_MAX_CLOCK_BASES))
+- return base;
++ switch (clock_id) {
++ case CLOCK_REALTIME:
++ return HRTIMER_BASE_REALTIME;
++ case CLOCK_MONOTONIC:
++ return HRTIMER_BASE_MONOTONIC;
++ case CLOCK_BOOTTIME:
++ return HRTIMER_BASE_BOOTTIME;
++ case CLOCK_TAI:
++ return HRTIMER_BASE_TAI;
++ default:
++ WARN(1, "Invalid clockid %d. Using MONOTONIC\n", clock_id);
++ return HRTIMER_BASE_MONOTONIC;
+ }
+- WARN(1, "Invalid clockid %d. Using MONOTONIC\n", clock_id);
+- return HRTIMER_BASE_MONOTONIC;
+ }
+
+ static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
+--
+2.39.5
+
--- /dev/null
+From 601b179356f5a05163f06dcb8a4f02cad62c3542 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Mar 2025 00:52:50 -0500
+Subject: hwmon: (dell-smm) Increment the number of fans
+
+From: Kurt Borja <kuurtb@gmail.com>
+
+[ Upstream commit dbcfcb239b3b452ef8782842c36fb17dd1b9092f ]
+
+Some Alienware laptops that support the SMM interface, may have up to 4
+fans.
+
+Tested on an Alienware x15 r1.
+
+Signed-off-by: Kurt Borja <kuurtb@gmail.com>
+Link: https://lore.kernel.org/r/20250304055249.51940-2-kuurtb@gmail.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/hwmon/dell-smm-hwmon.rst | 14 +++++++-------
+ drivers/hwmon/dell-smm-hwmon.c | 5 ++++-
+ 2 files changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/Documentation/hwmon/dell-smm-hwmon.rst b/Documentation/hwmon/dell-smm-hwmon.rst
+index 74905675d71f9..5a4edb6565cf9 100644
+--- a/Documentation/hwmon/dell-smm-hwmon.rst
++++ b/Documentation/hwmon/dell-smm-hwmon.rst
+@@ -32,12 +32,12 @@ Temperature sensors and fans can be queried and set via the standard
+ =============================== ======= =======================================
+ Name Perm Description
+ =============================== ======= =======================================
+-fan[1-3]_input RO Fan speed in RPM.
+-fan[1-3]_label RO Fan label.
+-fan[1-3]_min RO Minimal Fan speed in RPM
+-fan[1-3]_max RO Maximal Fan speed in RPM
+-fan[1-3]_target RO Expected Fan speed in RPM
+-pwm[1-3] RW Control the fan PWM duty-cycle.
++fan[1-4]_input RO Fan speed in RPM.
++fan[1-4]_label RO Fan label.
++fan[1-4]_min RO Minimal Fan speed in RPM
++fan[1-4]_max RO Maximal Fan speed in RPM
++fan[1-4]_target RO Expected Fan speed in RPM
++pwm[1-4] RW Control the fan PWM duty-cycle.
+ pwm1_enable WO Enable or disable automatic BIOS fan
+ control (not supported on all laptops,
+ see below for details).
+@@ -93,7 +93,7 @@ Again, when you find new codes, we'd be happy to have your patches!
+ ---------------------------
+
+ The driver also exports the fans as thermal cooling devices with
+-``type`` set to ``dell-smm-fan[1-3]``. This allows for easy fan control
++``type`` set to ``dell-smm-fan[1-4]``. This allows for easy fan control
+ using one of the thermal governors.
+
+ Module parameters
+diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c
+index f5bdf842040e6..b043fbd15c9da 100644
+--- a/drivers/hwmon/dell-smm-hwmon.c
++++ b/drivers/hwmon/dell-smm-hwmon.c
+@@ -73,7 +73,7 @@
+ #define DELL_SMM_LEGACY_EXECUTE 0x1
+
+ #define DELL_SMM_NO_TEMP 10
+-#define DELL_SMM_NO_FANS 3
++#define DELL_SMM_NO_FANS 4
+
+ struct smm_regs {
+ unsigned int eax;
+@@ -1074,11 +1074,14 @@ static const struct hwmon_channel_info * const dell_smm_info[] = {
+ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX |
+ HWMON_F_TARGET,
+ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX |
++ HWMON_F_TARGET,
++ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX |
+ HWMON_F_TARGET
+ ),
+ HWMON_CHANNEL_INFO(pwm,
+ HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
+ HWMON_PWM_INPUT,
++ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT
+ ),
+ NULL
+--
+2.39.5
+
--- /dev/null
+From 29c668f3098b2a168ad21f779a8d6e543e3ea992 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Feb 2025 15:59:30 +0100
+Subject: hwmon: (gpio-fan) Add missing mutex locks
+
+From: Alexander Stein <alexander.stein@ew.tq-group.com>
+
+[ Upstream commit 9fee7d19bab635f89223cc40dfd2c8797fdc4988 ]
+
+set_fan_speed() is expected to be called with fan_data->lock being locked.
+Add locking for proper synchronization.
+
+Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
+Link: https://lore.kernel.org/r/20250210145934.761280-3-alexander.stein@ew.tq-group.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/gpio-fan.c | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
+index d92c536be9af7..b779240328d59 100644
+--- a/drivers/hwmon/gpio-fan.c
++++ b/drivers/hwmon/gpio-fan.c
+@@ -393,7 +393,12 @@ static int gpio_fan_set_cur_state(struct thermal_cooling_device *cdev,
+ if (state >= fan_data->num_speed)
+ return -EINVAL;
+
++ mutex_lock(&fan_data->lock);
++
+ set_fan_speed(fan_data, state);
++
++ mutex_unlock(&fan_data->lock);
++
+ return 0;
+ }
+
+@@ -489,7 +494,11 @@ MODULE_DEVICE_TABLE(of, of_gpio_fan_match);
+
+ static void gpio_fan_stop(void *data)
+ {
++ struct gpio_fan_data *fan_data = data;
++
++ mutex_lock(&fan_data->lock);
+ set_fan_speed(data, 0);
++ mutex_unlock(&fan_data->lock);
+ }
+
+ static int gpio_fan_probe(struct platform_device *pdev)
+@@ -562,7 +571,9 @@ static int gpio_fan_suspend(struct device *dev)
+
+ if (fan_data->gpios) {
+ fan_data->resume_speed = fan_data->speed_index;
++ mutex_lock(&fan_data->lock);
+ set_fan_speed(fan_data, 0);
++ mutex_unlock(&fan_data->lock);
+ }
+
+ return 0;
+@@ -572,8 +583,11 @@ static int gpio_fan_resume(struct device *dev)
+ {
+ struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+
+- if (fan_data->gpios)
++ if (fan_data->gpios) {
++ mutex_lock(&fan_data->lock);
+ set_fan_speed(fan_data, fan_data->resume_speed);
++ mutex_unlock(&fan_data->lock);
++ }
+
+ return 0;
+ }
+--
+2.39.5
+
--- /dev/null
+From 4e1a420da098cd76abb9069ea29326bf4caa86c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Feb 2025 09:54:08 +0000
+Subject: hwmon: (xgene-hwmon) use appropriate type for the latency value
+
+From: Andrey Vatoropin <a.vatoropin@crpt.ru>
+
+[ Upstream commit 8df0f002827e18632dcd986f7546c1abf1953a6f ]
+
+The expression PCC_NUM_RETRIES * pcc_chan->latency is currently being
+evaluated using 32-bit arithmetic.
+
+Since a value of type 'u64' is used to store the eventual result,
+and this result is later sent to the function usecs_to_jiffies with
+input parameter unsigned int, the current data type is too wide to
+store the value of ctx->usecs_lat.
+
+Change the data type of "usecs_lat" to a more suitable (narrower) type.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Signed-off-by: Andrey Vatoropin <a.vatoropin@crpt.ru>
+Link: https://lore.kernel.org/r/20250204095400.95013-1-a.vatoropin@crpt.ru
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/xgene-hwmon.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c
+index 92d82faf237fc..4e05077e4256d 100644
+--- a/drivers/hwmon/xgene-hwmon.c
++++ b/drivers/hwmon/xgene-hwmon.c
+@@ -105,7 +105,7 @@ struct xgene_hwmon_dev {
+
+ phys_addr_t comm_base_addr;
+ void *pcc_comm_addr;
+- u64 usecs_lat;
++ unsigned int usecs_lat;
+ };
+
+ /*
+--
+2.39.5
+
--- /dev/null
+From 1d289341a1cf75e1e45d218acdf4c1470b87bd66 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Mar 2025 22:06:04 -0400
+Subject: hypfs_create_cpu_files(): add missing check for hypfs_mkdir() failure
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+[ Upstream commit 00cdfdcfa0806202aea56b02cedbf87ef1e75df8 ]
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/hypfs/hypfs_diag_fs.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/s390/hypfs/hypfs_diag_fs.c b/arch/s390/hypfs/hypfs_diag_fs.c
+index 00a6d370a2803..280266a74f378 100644
+--- a/arch/s390/hypfs/hypfs_diag_fs.c
++++ b/arch/s390/hypfs/hypfs_diag_fs.c
+@@ -208,6 +208,8 @@ static int hypfs_create_cpu_files(struct dentry *cpus_dir, void *cpu_info)
+ snprintf(buffer, TMP_SIZE, "%d", cpu_info__cpu_addr(diag204_get_info_type(),
+ cpu_info));
+ cpu_dir = hypfs_mkdir(cpus_dir, buffer);
++ if (IS_ERR(cpu_dir))
++ return PTR_ERR(cpu_dir);
+ rc = hypfs_create_u64(cpu_dir, "mgmtime",
+ cpu_info__acc_time(diag204_get_info_type(), cpu_info) -
+ cpu_info__lp_time(diag204_get_info_type(), cpu_info));
+--
+2.39.5
+
--- /dev/null
+From 344270d1f1ed57614870e894fdb52741908982f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 May 2025 19:56:41 +0200
+Subject: i2c: designware: Fix an error handling path in i2c_dw_pci_probe()
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit 1cfe51ef07ca3286581d612debfb0430eeccbb65 ]
+
+If navi_amd_register_client() fails, the previous i2c_dw_probe() call
+should be undone by a corresponding i2c_del_adapter() call, as already done
+in the remove function.
+
+Fixes: 17631e8ca2d3 ("i2c: designware: Add driver support for AMD NAVI GPU")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Cc: <stable@vger.kernel.org> # v5.13+
+Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
+Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
+Link: https://lore.kernel.org/r/fcd9651835a32979df8802b2db9504c523a8ebbb.1747158983.git.christophe.jaillet@wanadoo.fr
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i2c/busses/i2c-designware-pcidrv.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
+index 433cb285d3b20..5ea6d40373e7e 100644
+--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
++++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
+@@ -278,9 +278,11 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
+
+ if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) {
+ dev->slave = i2c_new_ccgx_ucsi(&dev->adapter, dev->irq, &dgpu_node);
+- if (IS_ERR(dev->slave))
++ if (IS_ERR(dev->slave)) {
++ i2c_del_adapter(&dev->adapter);
+ return dev_err_probe(device, PTR_ERR(dev->slave),
+ "register UCSI failed\n");
++ }
+ }
+
+ pm_runtime_set_autosuspend_delay(device, 1000);
+--
+2.39.5
+
--- /dev/null
+From 980be9efe6686b1310c6d5b07aa86c83f04a720c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Sep 2024 15:44:19 +0300
+Subject: i2c: designware: Use temporary variable for struct device
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit d2f94dccab8319063dd1fbc1738b4a280c2e4009 ]
+
+Use temporary variable for struct device to make code neater.
+
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+Reviewed-by: Andi Shyti <andi.shyti@kernel.org>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
+Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
+Stable-dep-of: 1cfe51ef07ca ("i2c: designware: Fix an error handling path in i2c_dw_pci_probe()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i2c/busses/i2c-designware-pcidrv.c | 29 ++++++-------
+ drivers/i2c/busses/i2c-designware-platdrv.c | 48 ++++++++++-----------
+ 2 files changed, 37 insertions(+), 40 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
+index 7b2c5d71a7fce..433cb285d3b20 100644
+--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
++++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
+@@ -207,6 +207,7 @@ static const struct software_node dgpu_node = {
+ static int i2c_dw_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+ {
++ struct device *device = &pdev->dev;
+ struct dw_i2c_dev *dev;
+ struct i2c_adapter *adap;
+ int r;
+@@ -214,25 +215,22 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
+ struct dw_scl_sda_cfg *cfg;
+
+ if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers))
+- return dev_err_probe(&pdev->dev, -EINVAL,
+- "Invalid driver data %ld\n",
++ return dev_err_probe(device, -EINVAL, "Invalid driver data %ld\n",
+ id->driver_data);
+
+ controller = &dw_pci_controllers[id->driver_data];
+
+ r = pcim_enable_device(pdev);
+ if (r)
+- return dev_err_probe(&pdev->dev, r,
+- "Failed to enable I2C PCI device\n");
++ return dev_err_probe(device, r, "Failed to enable I2C PCI device\n");
+
+ pci_set_master(pdev);
+
+ r = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev));
+ if (r)
+- return dev_err_probe(&pdev->dev, r,
+- "I/O memory remapping failed\n");
++ return dev_err_probe(device, r, "I/O memory remapping failed\n");
+
+- dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
++ dev = devm_kzalloc(device, sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+@@ -242,7 +240,7 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
+
+ dev->get_clk_rate_khz = controller->get_clk_rate_khz;
+ dev->base = pcim_iomap_table(pdev)[0];
+- dev->dev = &pdev->dev;
++ dev->dev = device;
+ dev->irq = pci_irq_vector(pdev, 0);
+ dev->flags |= controller->flags;
+
+@@ -281,14 +279,14 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
+ if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) {
+ dev->slave = i2c_new_ccgx_ucsi(&dev->adapter, dev->irq, &dgpu_node);
+ if (IS_ERR(dev->slave))
+- return dev_err_probe(dev->dev, PTR_ERR(dev->slave),
++ return dev_err_probe(device, PTR_ERR(dev->slave),
+ "register UCSI failed\n");
+ }
+
+- pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
+- pm_runtime_use_autosuspend(&pdev->dev);
+- pm_runtime_put_autosuspend(&pdev->dev);
+- pm_runtime_allow(&pdev->dev);
++ pm_runtime_set_autosuspend_delay(device, 1000);
++ pm_runtime_use_autosuspend(device);
++ pm_runtime_put_autosuspend(device);
++ pm_runtime_allow(device);
+
+ return 0;
+ }
+@@ -296,11 +294,12 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
+ static void i2c_dw_pci_remove(struct pci_dev *pdev)
+ {
+ struct dw_i2c_dev *dev = pci_get_drvdata(pdev);
++ struct device *device = &pdev->dev;
+
+ i2c_dw_disable(dev);
+
+- pm_runtime_forbid(&pdev->dev);
+- pm_runtime_get_noresume(&pdev->dev);
++ pm_runtime_forbid(device);
++ pm_runtime_get_noresume(device);
+
+ i2c_del_adapter(&dev->adapter);
+ }
+diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
+index 2d0c7348e4917..a3e86930bf418 100644
+--- a/drivers/i2c/busses/i2c-designware-platdrv.c
++++ b/drivers/i2c/busses/i2c-designware-platdrv.c
+@@ -205,6 +205,7 @@ static void i2c_dw_remove_lock_support(struct dw_i2c_dev *dev)
+
+ static int dw_i2c_plat_probe(struct platform_device *pdev)
+ {
++ struct device *device = &pdev->dev;
+ struct i2c_adapter *adap;
+ struct dw_i2c_dev *dev;
+ int irq, ret;
+@@ -213,15 +214,15 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
+ if (irq < 0)
+ return irq;
+
+- dev = devm_kzalloc(&pdev->dev, sizeof(struct dw_i2c_dev), GFP_KERNEL);
++ dev = devm_kzalloc(device, sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+- dev->flags = (uintptr_t)device_get_match_data(&pdev->dev);
+- if (device_property_present(&pdev->dev, "wx,i2c-snps-model"))
++ dev->flags = (uintptr_t)device_get_match_data(device);
++ if (device_property_present(device, "wx,i2c-snps-model"))
+ dev->flags = MODEL_WANGXUN_SP | ACCESS_POLLING;
+
+- dev->dev = &pdev->dev;
++ dev->dev = device;
+ dev->irq = irq;
+ platform_set_drvdata(pdev, dev);
+
+@@ -229,7 +230,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
+ if (ret)
+ return ret;
+
+- dev->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
++ dev->rst = devm_reset_control_get_optional_exclusive(device, NULL);
+ if (IS_ERR(dev->rst))
+ return PTR_ERR(dev->rst);
+
+@@ -246,13 +247,13 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
+ i2c_dw_configure(dev);
+
+ /* Optional interface clock */
+- dev->pclk = devm_clk_get_optional(&pdev->dev, "pclk");
++ dev->pclk = devm_clk_get_optional(device, "pclk");
+ if (IS_ERR(dev->pclk)) {
+ ret = PTR_ERR(dev->pclk);
+ goto exit_reset;
+ }
+
+- dev->clk = devm_clk_get_optional(&pdev->dev, NULL);
++ dev->clk = devm_clk_get_optional(device, NULL);
+ if (IS_ERR(dev->clk)) {
+ ret = PTR_ERR(dev->clk);
+ goto exit_reset;
+@@ -280,28 +281,24 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
+ I2C_CLASS_HWMON : I2C_CLASS_DEPRECATED;
+ adap->nr = -1;
+
+- if (dev->flags & ACCESS_NO_IRQ_SUSPEND) {
+- dev_pm_set_driver_flags(&pdev->dev,
+- DPM_FLAG_SMART_PREPARE);
+- } else {
+- dev_pm_set_driver_flags(&pdev->dev,
+- DPM_FLAG_SMART_PREPARE |
+- DPM_FLAG_SMART_SUSPEND);
+- }
++ if (dev->flags & ACCESS_NO_IRQ_SUSPEND)
++ dev_pm_set_driver_flags(device, DPM_FLAG_SMART_PREPARE);
++ else
++ dev_pm_set_driver_flags(device, DPM_FLAG_SMART_PREPARE | DPM_FLAG_SMART_SUSPEND);
+
+- device_enable_async_suspend(&pdev->dev);
++ device_enable_async_suspend(device);
+
+ /* The code below assumes runtime PM to be disabled. */
+- WARN_ON(pm_runtime_enabled(&pdev->dev));
++ WARN_ON(pm_runtime_enabled(device));
+
+- pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
+- pm_runtime_use_autosuspend(&pdev->dev);
+- pm_runtime_set_active(&pdev->dev);
++ pm_runtime_set_autosuspend_delay(device, 1000);
++ pm_runtime_use_autosuspend(device);
++ pm_runtime_set_active(device);
+
+ if (dev->shared_with_punit)
+- pm_runtime_get_noresume(&pdev->dev);
++ pm_runtime_get_noresume(device);
+
+- pm_runtime_enable(&pdev->dev);
++ pm_runtime_enable(device);
+
+ ret = i2c_dw_probe(dev);
+ if (ret)
+@@ -319,15 +316,16 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
+ static void dw_i2c_plat_remove(struct platform_device *pdev)
+ {
+ struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
++ struct device *device = &pdev->dev;
+
+- pm_runtime_get_sync(&pdev->dev);
++ pm_runtime_get_sync(device);
+
+ i2c_del_adapter(&dev->adapter);
+
+ i2c_dw_disable(dev);
+
+- pm_runtime_dont_use_autosuspend(&pdev->dev);
+- pm_runtime_put_sync(&pdev->dev);
++ pm_runtime_dont_use_autosuspend(device);
++ pm_runtime_put_sync(device);
+ dw_i2c_plat_pm_cleanup(dev);
+
+ i2c_dw_remove_lock_support(dev);
+--
+2.39.5
+
--- /dev/null
+From a4b2d247e183c0496bb024c5e264587c8a3d1b15 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Feb 2025 20:28:03 +0300
+Subject: i2c: pxa: fix call balance of i2c->clk handling routines
+
+From: Vitalii Mordan <mordan@ispras.ru>
+
+[ Upstream commit be7113d2e2a6f20cbee99c98d261a1fd6fd7b549 ]
+
+If the clock i2c->clk was not enabled in i2c_pxa_probe(), it should not be
+disabled in any path.
+
+Found by Linux Verification Center (linuxtesting.org) with Klever.
+
+Signed-off-by: Vitalii Mordan <mordan@ispras.ru>
+Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
+Link: https://lore.kernel.org/r/20250212172803.1422136-1-mordan@ispras.ru
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i2c/busses/i2c-pxa.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
+index 4d76e71cdd4be..afc1a8171f59e 100644
+--- a/drivers/i2c/busses/i2c-pxa.c
++++ b/drivers/i2c/busses/i2c-pxa.c
+@@ -1503,7 +1503,10 @@ static int i2c_pxa_probe(struct platform_device *dev)
+ i2c->adap.name);
+ }
+
+- clk_prepare_enable(i2c->clk);
++ ret = clk_prepare_enable(i2c->clk);
++ if (ret)
++ return dev_err_probe(&dev->dev, ret,
++ "failed to enable clock\n");
+
+ if (i2c->use_pio) {
+ i2c->adap.algo = &i2c_pxa_pio_algorithm;
+--
+2.39.5
+
--- /dev/null
+From d0cc26edaddd09ee9814c7f4ce5aefa5aad10095 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Nov 2023 10:48:37 +0100
+Subject: i2c: qup: Vote for interconnect bandwidth to DRAM
+
+From: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
+
+[ Upstream commit d4f35233a6345f62637463ef6e0708f44ffaa583 ]
+
+When the I2C QUP controller is used together with a DMA engine it needs
+to vote for the interconnect path to the DRAM. Otherwise it may be
+unable to access the memory quickly enough.
+
+The requested peak bandwidth is dependent on the I2C core clock.
+
+To avoid sending votes too often the bandwidth is always requested when
+a DMA transfer starts, but dropped only on runtime suspend. Runtime
+suspend should only happen if no transfer is active. After resumption we
+can defer the next vote until the first DMA transfer actually happens.
+
+The implementation is largely identical to the one introduced for
+spi-qup in commit ecdaa9473019 ("spi: qup: Vote for interconnect
+bandwidth to DRAM") since both drivers represent the same hardware
+block.
+
+Signed-off-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
+Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
+Link: https://lore.kernel.org/r/20231128-i2c-qup-dvfs-v1-3-59a0e3039111@kernkonzept.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i2c/busses/i2c-qup.c | 36 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+
+diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
+index d480162a4d394..eb97abcb4cd33 100644
+--- a/drivers/i2c/busses/i2c-qup.c
++++ b/drivers/i2c/busses/i2c-qup.c
+@@ -14,6 +14,7 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/err.h>
+ #include <linux/i2c.h>
++#include <linux/interconnect.h>
+ #include <linux/interrupt.h>
+ #include <linux/io.h>
+ #include <linux/module.h>
+@@ -150,6 +151,8 @@
+ /* TAG length for DATA READ in RX FIFO */
+ #define READ_RX_TAGS_LEN 2
+
++#define QUP_BUS_WIDTH 8
++
+ static unsigned int scl_freq;
+ module_param_named(scl_freq, scl_freq, uint, 0444);
+ MODULE_PARM_DESC(scl_freq, "SCL frequency override");
+@@ -227,6 +230,7 @@ struct qup_i2c_dev {
+ int irq;
+ struct clk *clk;
+ struct clk *pclk;
++ struct icc_path *icc_path;
+ struct i2c_adapter adap;
+
+ int clk_ctl;
+@@ -255,6 +259,10 @@ struct qup_i2c_dev {
+ /* To configure when bus is in run state */
+ u32 config_run;
+
++ /* bandwidth votes */
++ u32 src_clk_freq;
++ u32 cur_bw_clk_freq;
++
+ /* dma parameters */
+ bool is_dma;
+ /* To check if the current transfer is using DMA */
+@@ -453,6 +461,23 @@ static int qup_i2c_bus_active(struct qup_i2c_dev *qup, int len)
+ return ret;
+ }
+
++static int qup_i2c_vote_bw(struct qup_i2c_dev *qup, u32 clk_freq)
++{
++ u32 needed_peak_bw;
++ int ret;
++
++ if (qup->cur_bw_clk_freq == clk_freq)
++ return 0;
++
++ needed_peak_bw = Bps_to_icc(clk_freq * QUP_BUS_WIDTH);
++ ret = icc_set_bw(qup->icc_path, 0, needed_peak_bw);
++ if (ret)
++ return ret;
++
++ qup->cur_bw_clk_freq = clk_freq;
++ return 0;
++}
++
+ static void qup_i2c_write_tx_fifo_v1(struct qup_i2c_dev *qup)
+ {
+ struct qup_i2c_block *blk = &qup->blk;
+@@ -838,6 +863,10 @@ static int qup_i2c_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
+ int ret = 0;
+ int idx = 0;
+
++ ret = qup_i2c_vote_bw(qup, qup->src_clk_freq);
++ if (ret)
++ return ret;
++
+ enable_irq(qup->irq);
+ ret = qup_i2c_req_dma(qup);
+
+@@ -1643,6 +1672,7 @@ static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup)
+ config = readl(qup->base + QUP_CONFIG);
+ config |= QUP_CLOCK_AUTO_GATE;
+ writel(config, qup->base + QUP_CONFIG);
++ qup_i2c_vote_bw(qup, 0);
+ clk_disable_unprepare(qup->pclk);
+ }
+
+@@ -1743,6 +1773,11 @@ static int qup_i2c_probe(struct platform_device *pdev)
+ goto fail_dma;
+ }
+ qup->is_dma = true;
++
++ qup->icc_path = devm_of_icc_get(&pdev->dev, NULL);
++ if (IS_ERR(qup->icc_path))
++ return dev_err_probe(&pdev->dev, PTR_ERR(qup->icc_path),
++ "failed to get interconnect path\n");
+ }
+
+ nodma:
+@@ -1791,6 +1826,7 @@ static int qup_i2c_probe(struct platform_device *pdev)
+ qup_i2c_enable_clocks(qup);
+ src_clk_freq = clk_get_rate(qup->clk);
+ }
++ qup->src_clk_freq = src_clk_freq;
+
+ /*
+ * Bootloaders might leave a pending interrupt on certain QUP's,
+--
+2.39.5
+
--- /dev/null
+From 33e496dc56a478c35961feca37f8186487c14c63 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Mar 2025 13:36:06 +0800
+Subject: i3c: master: svc: Fix missing STOP for master request
+
+From: Stanley Chu <yschu@nuvoton.com>
+
+[ Upstream commit 0430bf9bc1ac068c8b8c540eb93e5751872efc51 ]
+
+The controller driver nacked the master request but didn't emit a
+STOP to end the transaction. The driver shall refuse the unsupported
+requests and return the controller state to IDLE by emitting a STOP.
+
+Signed-off-by: Stanley Chu <yschu@nuvoton.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20250318053606.3087121-4-yschu@nuvoton.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master/svc-i3c-master.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
+index 7911814ad82ac..6ffe022dbb5b4 100644
+--- a/drivers/i3c/master/svc-i3c-master.c
++++ b/drivers/i3c/master/svc-i3c-master.c
+@@ -511,6 +511,7 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
+ queue_work(master->base.wq, &master->hj_work);
+ break;
+ case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST:
++ svc_i3c_master_emit_stop(master);
+ default:
+ break;
+ }
+--
+2.39.5
+
--- /dev/null
+From bd6843098dd9387bfb4ac0751947f5fab62f06a7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jan 2025 11:22:50 -0500
+Subject: i3c: master: svc: Flush FIFO before sending Dynamic Address
+ Assignment(DAA)
+
+From: Frank Li <Frank.Li@nxp.com>
+
+[ Upstream commit a892ee4cf22a50e1d6988d0464a9a421f3e5db2f ]
+
+Ensure the FIFO is empty before issuing the DAA command to prevent
+incorrect command data from being sent. Align with other data transfers,
+such as svc_i3c_master_start_xfer_locked(), which flushes the FIFO before
+sending a command.
+
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://lore.kernel.org/r/20250129162250.3629189-1-Frank.Li@nxp.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master/svc-i3c-master.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
+index 6ffe022dbb5b4..62913feae45dd 100644
+--- a/drivers/i3c/master/svc-i3c-master.c
++++ b/drivers/i3c/master/svc-i3c-master.c
+@@ -860,6 +860,8 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
+ u32 reg;
+ int ret, i;
+
++ svc_i3c_master_flush_fifo(master);
++
+ while (true) {
+ /* SVC_I3C_MCTRL_REQUEST_PROC_DAA have two mode, ENTER DAA or PROCESS DAA.
+ *
+--
+2.39.5
+
--- /dev/null
+From 32e4baee8897e12275fa0d89993399642eb23617 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 07:58:09 +0100
+Subject: ice: count combined queues using Rx/Tx count
+
+From: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
+
+[ Upstream commit c3a392bdd31adc474f1009ee85c13fdd01fe800d ]
+
+Previous implementation assumes that there is 1:1 matching between
+vectors and queues. It isn't always true.
+
+Get minimum value from Rx/Tx queues to determine combined queues number.
+
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com>
+Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_ethtool.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c
+index 7d1feeb317be3..2a2acbeb57221 100644
+--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c
++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c
+@@ -3817,8 +3817,7 @@ static u32 ice_get_combined_cnt(struct ice_vsi *vsi)
+ ice_for_each_q_vector(vsi, q_idx) {
+ struct ice_q_vector *q_vector = vsi->q_vectors[q_idx];
+
+- if (q_vector->rx.rx_ring && q_vector->tx.tx_ring)
+- combined++;
++ combined += min(q_vector->num_ring_tx, q_vector->num_ring_rx);
+ }
+
+ return combined;
+--
+2.39.5
+
--- /dev/null
+From 3b3bdec990892ad9e6640a641a7c93f50784d881 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 07:58:17 +0100
+Subject: ice: init flow director before RDMA
+
+From: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
+
+[ Upstream commit d67627e7b53203ca150e54723abbed81a0716286 ]
+
+Flow director needs only one MSI-X. Load it before RDMA to save MSI-X
+for it.
+
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com>
+Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_main.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
+index ca707dfcb286e..63d2105fce933 100644
+--- a/drivers/net/ethernet/intel/ice/ice_main.c
++++ b/drivers/net/ethernet/intel/ice/ice_main.c
+@@ -5175,11 +5175,12 @@ int ice_load(struct ice_pf *pf)
+
+ ice_napi_add(vsi);
+
++ ice_init_features(pf);
++
+ err = ice_init_rdma(pf);
+ if (err)
+ goto err_init_rdma;
+
+- ice_init_features(pf);
+ ice_service_task_restart(pf);
+
+ clear_bit(ICE_DOWN, pf->state);
+@@ -5187,6 +5188,7 @@ int ice_load(struct ice_pf *pf)
+ return 0;
+
+ err_init_rdma:
++ ice_deinit_features(pf);
+ ice_tc_indir_block_unregister(vsi);
+ err_tc_indir_block_register:
+ ice_unregister_netdev(vsi);
+@@ -5210,8 +5212,8 @@ void ice_unload(struct ice_pf *pf)
+
+ devl_assert_locked(priv_to_devlink(pf));
+
+- ice_deinit_features(pf);
+ ice_deinit_rdma(pf);
++ ice_deinit_features(pf);
+ ice_tc_indir_block_unregister(vsi);
+ ice_unregister_netdev(vsi);
+ ice_devlink_destroy_pf_port(pf);
+--
+2.39.5
+
--- /dev/null
+From 0bff30fa0536333140573016852755dc1abbc2d4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 07:58:14 +0100
+Subject: ice: treat dyn_allowed only as suggestion
+
+From: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
+
+[ Upstream commit a8c2d3932c1106af2764cc6869b29bcf3cb5bc47 ]
+
+It can be needed to have some MSI-X allocated as static and rest as
+dynamic. For example on PF VSI. We want to always have minimum one MSI-X
+on it, because of that it is allocated as a static one, rest can be
+dynamic if it is supported.
+
+Change the ice_get_irq_res() to allow using static entries if they are
+free even if caller wants dynamic one.
+
+Adjust limit values to the new approach. Min and max in limit means the
+values that are valid, so decrease max and num_static by one.
+
+Set vsi::irq_dyn_alloc if dynamic allocation is supported.
+
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com>
+Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_irq.c | 25 ++++++++++++------------
+ drivers/net/ethernet/intel/ice/ice_lib.c | 2 ++
+ 2 files changed, 15 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_irq.c b/drivers/net/ethernet/intel/ice/ice_irq.c
+index ad82ff7d19957..09f9c7ba52795 100644
+--- a/drivers/net/ethernet/intel/ice/ice_irq.c
++++ b/drivers/net/ethernet/intel/ice/ice_irq.c
+@@ -45,7 +45,7 @@ static void ice_free_irq_res(struct ice_pf *pf, u16 index)
+ /**
+ * ice_get_irq_res - get an interrupt resource
+ * @pf: board private structure
+- * @dyn_only: force entry to be dynamically allocated
++ * @dyn_allowed: allow entry to be dynamically allocated
+ *
+ * Allocate new irq entry in the free slot of the tracker. Since xarray
+ * is used, always allocate new entry at the lowest possible index. Set
+@@ -53,11 +53,12 @@ static void ice_free_irq_res(struct ice_pf *pf, u16 index)
+ *
+ * Returns allocated irq entry or NULL on failure.
+ */
+-static struct ice_irq_entry *ice_get_irq_res(struct ice_pf *pf, bool dyn_only)
++static struct ice_irq_entry *ice_get_irq_res(struct ice_pf *pf,
++ bool dyn_allowed)
+ {
+- struct xa_limit limit = { .max = pf->irq_tracker.num_entries,
++ struct xa_limit limit = { .max = pf->irq_tracker.num_entries - 1,
+ .min = 0 };
+- unsigned int num_static = pf->irq_tracker.num_static;
++ unsigned int num_static = pf->irq_tracker.num_static - 1;
+ struct ice_irq_entry *entry;
+ unsigned int index;
+ int ret;
+@@ -66,9 +67,9 @@ static struct ice_irq_entry *ice_get_irq_res(struct ice_pf *pf, bool dyn_only)
+ if (!entry)
+ return NULL;
+
+- /* skip preallocated entries if the caller says so */
+- if (dyn_only)
+- limit.min = num_static;
++ /* only already allocated if the caller says so */
++ if (!dyn_allowed)
++ limit.max = num_static;
+
+ ret = xa_alloc(&pf->irq_tracker.entries, &index, entry, limit,
+ GFP_KERNEL);
+@@ -78,7 +79,7 @@ static struct ice_irq_entry *ice_get_irq_res(struct ice_pf *pf, bool dyn_only)
+ entry = NULL;
+ } else {
+ entry->index = index;
+- entry->dynamic = index >= num_static;
++ entry->dynamic = index > num_static;
+ }
+
+ return entry;
+@@ -272,7 +273,7 @@ int ice_init_interrupt_scheme(struct ice_pf *pf)
+ /**
+ * ice_alloc_irq - Allocate new interrupt vector
+ * @pf: board private structure
+- * @dyn_only: force dynamic allocation of the interrupt
++ * @dyn_allowed: allow dynamic allocation of the interrupt
+ *
+ * Allocate new interrupt vector for a given owner id.
+ * return struct msi_map with interrupt details and track
+@@ -285,20 +286,20 @@ int ice_init_interrupt_scheme(struct ice_pf *pf)
+ * interrupt will be allocated with pci_msix_alloc_irq_at.
+ *
+ * Some callers may only support dynamically allocated interrupts.
+- * This is indicated with dyn_only flag.
++ * This is indicated with dyn_allowed flag.
+ *
+ * On failure, return map with negative .index. The caller
+ * is expected to check returned map index.
+ *
+ */
+-struct msi_map ice_alloc_irq(struct ice_pf *pf, bool dyn_only)
++struct msi_map ice_alloc_irq(struct ice_pf *pf, bool dyn_allowed)
+ {
+ int sriov_base_vector = pf->sriov_base_vector;
+ struct msi_map map = { .index = -ENOENT };
+ struct device *dev = ice_pf_to_dev(pf);
+ struct ice_irq_entry *entry;
+
+- entry = ice_get_irq_res(pf, dyn_only);
++ entry = ice_get_irq_res(pf, dyn_allowed);
+ if (!entry)
+ return map;
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
+index 121a5ad5c8e10..8961eebe67aa2 100644
+--- a/drivers/net/ethernet/intel/ice/ice_lib.c
++++ b/drivers/net/ethernet/intel/ice/ice_lib.c
+@@ -567,6 +567,8 @@ ice_vsi_alloc_def(struct ice_vsi *vsi, struct ice_channel *ch)
+ return -ENOMEM;
+ }
+
++ vsi->irq_dyn_alloc = pci_msix_can_alloc_dyn(vsi->back->pdev);
++
+ switch (vsi->type) {
+ case ICE_VSI_PF:
+ case ICE_VSI_SF:
+--
+2.39.5
+
--- /dev/null
+From 88d8c797cfb1d1bfcd59c4387f16fd75d3221099 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Mar 2025 12:55:34 +0200
+Subject: ieee802154: ca8210: Use proper setters and getters for bitwise types
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 169b2262205836a5d1213ff44dca2962276bece1 ]
+
+Sparse complains that the driver doesn't respect the bitwise types:
+
+drivers/net/ieee802154/ca8210.c:1796:27: warning: incorrect type in assignment (different base types)
+drivers/net/ieee802154/ca8210.c:1796:27: expected restricted __le16 [addressable] [assigned] [usertype] pan_id
+drivers/net/ieee802154/ca8210.c:1796:27: got unsigned short [usertype]
+drivers/net/ieee802154/ca8210.c:1801:25: warning: incorrect type in assignment (different base types)
+drivers/net/ieee802154/ca8210.c:1801:25: expected restricted __le16 [addressable] [assigned] [usertype] pan_id
+drivers/net/ieee802154/ca8210.c:1801:25: got unsigned short [usertype]
+drivers/net/ieee802154/ca8210.c:1928:28: warning: incorrect type in argument 3 (different base types)
+drivers/net/ieee802154/ca8210.c:1928:28: expected unsigned short [usertype] dst_pan_id
+drivers/net/ieee802154/ca8210.c:1928:28: got restricted __le16 [addressable] [usertype] pan_id
+
+Use proper setters and getters for bitwise types.
+
+Note, in accordance with [1] the protocol is little endian.
+
+Link: https://www.cascoda.com/wp-content/uploads/2018/11/CA-8210_datasheet_0418.pdf [1]
+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://lore.kernel.org/20250305105656.2133487-2-andriy.shevchenko@linux.intel.com
+Signed-off-by: Stefan Schmidt <stefan@datenfreihafen.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ieee802154/ca8210.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c
+index 753215ebc67c7..a036910f60828 100644
+--- a/drivers/net/ieee802154/ca8210.c
++++ b/drivers/net/ieee802154/ca8210.c
+@@ -1446,8 +1446,7 @@ static u8 mcps_data_request(
+ command.pdata.data_req.src_addr_mode = src_addr_mode;
+ command.pdata.data_req.dst.mode = dst_address_mode;
+ if (dst_address_mode != MAC_MODE_NO_ADDR) {
+- command.pdata.data_req.dst.pan_id[0] = LS_BYTE(dst_pan_id);
+- command.pdata.data_req.dst.pan_id[1] = MS_BYTE(dst_pan_id);
++ put_unaligned_le16(dst_pan_id, command.pdata.data_req.dst.pan_id);
+ if (dst_address_mode == MAC_MODE_SHORT_ADDR) {
+ command.pdata.data_req.dst.address[0] = LS_BYTE(
+ dst_addr->short_address
+@@ -1795,12 +1794,12 @@ static int ca8210_skb_rx(
+ }
+ hdr.source.mode = data_ind[0];
+ dev_dbg(&priv->spi->dev, "srcAddrMode: %#03x\n", hdr.source.mode);
+- hdr.source.pan_id = *(u16 *)&data_ind[1];
++ hdr.source.pan_id = cpu_to_le16(get_unaligned_le16(&data_ind[1]));
+ dev_dbg(&priv->spi->dev, "srcPanId: %#06x\n", hdr.source.pan_id);
+ memcpy(&hdr.source.extended_addr, &data_ind[3], 8);
+ hdr.dest.mode = data_ind[11];
+ dev_dbg(&priv->spi->dev, "dstAddrMode: %#03x\n", hdr.dest.mode);
+- hdr.dest.pan_id = *(u16 *)&data_ind[12];
++ hdr.dest.pan_id = cpu_to_le16(get_unaligned_le16(&data_ind[12]));
+ dev_dbg(&priv->spi->dev, "dstPanId: %#06x\n", hdr.dest.pan_id);
+ memcpy(&hdr.dest.extended_addr, &data_ind[14], 8);
+
+@@ -1927,7 +1926,7 @@ static int ca8210_skb_tx(
+ status = mcps_data_request(
+ header.source.mode,
+ header.dest.mode,
+- header.dest.pan_id,
++ le16_to_cpu(header.dest.pan_id),
+ (union macaddr *)&header.dest.extended_addr,
+ skb->len - mac_len,
+ &skb->data[mac_len],
+--
+2.39.5
+
--- /dev/null
+From 080c265ca08391f072576bfca58f2bff5980ae98 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Feb 2025 14:09:07 -0600
+Subject: iio: adc: ad7944: don't use storagebits for sizing
+
+From: David Lechner <dlechner@baylibre.com>
+
+[ Upstream commit 503d20ed8cf7c7b40ec0bd94f53c490c1d91c31b ]
+
+Replace use of storagebits with realbits for determining the number of
+bytes needed for SPI transfers.
+
+When adding SPI offload support, storagebits will always be 32 rather
+than 16 for 16-bit 16-bit chips so we can no longer rely on storagebits
+being the correct size expected by the SPI framework (it always uses
+4 bytes for > 16-bit xfers and 2 bytes for > 8-bit xfers). Instead,
+derive the correct size from realbits since it will always be correct
+even when SPI offloading is used.
+
+Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Reviewed-vy: Nuno Sa <nuno.sa@analog.com>
+Signed-off-by: David Lechner <dlechner@baylibre.com>
+Link: https://patch.msgid.link/20250207-dlech-mainline-spi-engine-offload-2-v8-10-e48a489be48c@baylibre.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/ad7944.c | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/iio/adc/ad7944.c b/drivers/iio/adc/ad7944.c
+index 0f36138a71445..58a25792cec37 100644
+--- a/drivers/iio/adc/ad7944.c
++++ b/drivers/iio/adc/ad7944.c
+@@ -98,6 +98,9 @@ struct ad7944_chip_info {
+ const struct iio_chan_spec channels[2];
+ };
+
++/* get number of bytes for SPI xfer */
++#define AD7944_SPI_BYTES(scan_type) ((scan_type).realbits > 16 ? 4 : 2)
++
+ /*
+ * AD7944_DEFINE_CHIP_INFO - Define a chip info structure for a specific chip
+ * @_name: The name of the chip
+@@ -164,7 +167,7 @@ static int ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc *
+
+ /* Then we can read the data during the acquisition phase */
+ xfers[2].rx_buf = &adc->sample.raw;
+- xfers[2].len = BITS_TO_BYTES(chan->scan_type.storagebits);
++ xfers[2].len = AD7944_SPI_BYTES(chan->scan_type);
+ xfers[2].bits_per_word = chan->scan_type.realbits;
+
+ spi_message_init_with_transfers(&adc->msg, xfers, 3);
+@@ -193,7 +196,7 @@ static int ad7944_4wire_mode_init_msg(struct device *dev, struct ad7944_adc *adc
+ xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS;
+
+ xfers[1].rx_buf = &adc->sample.raw;
+- xfers[1].len = BITS_TO_BYTES(chan->scan_type.storagebits);
++ xfers[1].len = AD7944_SPI_BYTES(chan->scan_type);
+ xfers[1].bits_per_word = chan->scan_type.realbits;
+
+ spi_message_init_with_transfers(&adc->msg, xfers, 2);
+@@ -228,7 +231,7 @@ static int ad7944_chain_mode_init_msg(struct device *dev, struct ad7944_adc *adc
+ xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS;
+
+ xfers[1].rx_buf = adc->chain_mode_buf;
+- xfers[1].len = BITS_TO_BYTES(chan->scan_type.storagebits) * n_chain_dev;
++ xfers[1].len = AD7944_SPI_BYTES(chan->scan_type) * n_chain_dev;
+ xfers[1].bits_per_word = chan->scan_type.realbits;
+
+ spi_message_init_with_transfers(&adc->msg, xfers, 2);
+@@ -274,12 +277,12 @@ static int ad7944_single_conversion(struct ad7944_adc *adc,
+ return ret;
+
+ if (adc->spi_mode == AD7944_SPI_MODE_CHAIN) {
+- if (chan->scan_type.storagebits > 16)
++ if (chan->scan_type.realbits > 16)
+ *val = ((u32 *)adc->chain_mode_buf)[chan->scan_index];
+ else
+ *val = ((u16 *)adc->chain_mode_buf)[chan->scan_index];
+ } else {
+- if (chan->scan_type.storagebits > 16)
++ if (chan->scan_type.realbits > 16)
+ *val = adc->sample.raw.u32;
+ else
+ *val = adc->sample.raw.u16;
+@@ -409,8 +412,7 @@ static int ad7944_chain_mode_alloc(struct device *dev,
+ /* 1 word for each voltage channel + aligned u64 for timestamp */
+
+ chain_mode_buf_size = ALIGN(n_chain_dev *
+- BITS_TO_BYTES(chan[0].scan_type.storagebits), sizeof(u64))
+- + sizeof(u64);
++ AD7944_SPI_BYTES(chan[0].scan_type), sizeof(u64)) + sizeof(u64);
+ buf = devm_kzalloc(dev, chain_mode_buf_size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+--
+2.39.5
+
--- /dev/null
+From b06d09c6ca135751a3feda0d7e3131db20583566 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Mar 2025 11:09:11 -0500
+Subject: ima: process_measurement() needlessly takes inode_lock() on MAY_READ
+
+From: Frederick Lawler <fred@cloudflare.com>
+
+[ Upstream commit 30d68cb0c37ebe2dc63aa1d46a28b9163e61caa2 ]
+
+On IMA policy update, if a measure rule exists in the policy,
+IMA_MEASURE is set for ima_policy_flags which makes the violation_check
+variable always true. Coupled with a no-action on MAY_READ for a
+FILE_CHECK call, we're always taking the inode_lock().
+
+This becomes a performance problem for extremely heavy read-only workloads.
+Therefore, prevent this only in the case there's no action to be taken.
+
+Signed-off-by: Frederick Lawler <fred@cloudflare.com>
+Acked-by: Roberto Sassu <roberto.sassu@huawei.com>
+Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ security/integrity/ima/ima_main.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
+index a9aab10bebcaa..2f3f267e72167 100644
+--- a/security/integrity/ima/ima_main.c
++++ b/security/integrity/ima/ima_main.c
+@@ -245,7 +245,9 @@ static int process_measurement(struct file *file, const struct cred *cred,
+ &allowed_algos);
+ violation_check = ((func == FILE_CHECK || func == MMAP_CHECK ||
+ func == MMAP_CHECK_REQPROT) &&
+- (ima_policy_flag & IMA_MEASURE));
++ (ima_policy_flag & IMA_MEASURE) &&
++ ((action & IMA_MEASURE) ||
++ (file->f_mode & FMODE_WRITE)));
+ if (!action && !violation_check)
+ return 0;
+
+--
+2.39.5
+
--- /dev/null
+From cac19d703186f4d2e0b6f35bff3eafd1a669d0df Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 31 Mar 2025 13:56:08 +0100
+Subject: intel_th: avoid using deprecated page->mapping, index fields
+
+From: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
+
+[ Upstream commit 8e553520596bbd5ce832e26e9d721e6a0c797b8b ]
+
+The struct page->mapping, index fields are deprecated and soon to be only
+available as part of a folio.
+
+It is likely the intel_th code which sets page->mapping, index is was
+implemented out of concern that some aspect of the page fault logic may
+encounter unexpected problems should they not.
+
+However, the appropriate interface for inserting kernel-allocated memory is
+vm_insert_page() in a VM_MIXEDMAP. By using the helper function
+vmf_insert_mixed() we can do this with minimal churn in the existing fault
+handler.
+
+By doing so, we bypass the remainder of the faulting logic. The pages are
+still pinned so there is no possibility of anything unexpected being done
+with the pages once established.
+
+It would also be reasonable to pre-map everything on fault, however to
+minimise churn we retain the fault handler.
+
+We also eliminate all code which clears page->mapping on teardown as this
+has now become unnecessary.
+
+The MSU code relies on faulting to function correctly, so is by definition
+dependent on CONFIG_MMU. We avoid spurious reports about compilation
+failure for unsupported platforms by making this requirement explicit in
+Kconfig as part of this change too.
+
+Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
+Acked-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Link: https://lore.kernel.org/r/20250331125608.60300-1-lorenzo.stoakes@oracle.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwtracing/intel_th/Kconfig | 1 +
+ drivers/hwtracing/intel_th/msu.c | 31 +++++++-----------------------
+ 2 files changed, 8 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/hwtracing/intel_th/Kconfig b/drivers/hwtracing/intel_th/Kconfig
+index 4b6359326ede9..4f7d2b6d79e29 100644
+--- a/drivers/hwtracing/intel_th/Kconfig
++++ b/drivers/hwtracing/intel_th/Kconfig
+@@ -60,6 +60,7 @@ config INTEL_TH_STH
+
+ config INTEL_TH_MSU
+ tristate "Intel(R) Trace Hub Memory Storage Unit"
++ depends on MMU
+ help
+ Memory Storage Unit (MSU) trace output device enables
+ storing STP traces to system memory. It supports single
+diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c
+index 66123d684ac9e..93b65a9731d72 100644
+--- a/drivers/hwtracing/intel_th/msu.c
++++ b/drivers/hwtracing/intel_th/msu.c
+@@ -19,6 +19,7 @@
+ #include <linux/io.h>
+ #include <linux/workqueue.h>
+ #include <linux/dma-mapping.h>
++#include <linux/pfn_t.h>
+
+ #ifdef CONFIG_X86
+ #include <asm/set_memory.h>
+@@ -967,7 +968,6 @@ static void msc_buffer_contig_free(struct msc *msc)
+ for (off = 0; off < msc->nr_pages << PAGE_SHIFT; off += PAGE_SIZE) {
+ struct page *page = virt_to_page(msc->base + off);
+
+- page->mapping = NULL;
+ __free_page(page);
+ }
+
+@@ -1149,9 +1149,6 @@ static void __msc_buffer_win_free(struct msc *msc, struct msc_window *win)
+ int i;
+
+ for_each_sg(win->sgt->sgl, sg, win->nr_segs, i) {
+- struct page *page = msc_sg_page(sg);
+-
+- page->mapping = NULL;
+ dma_free_coherent(msc_dev(win->msc)->parent->parent, PAGE_SIZE,
+ sg_virt(sg), sg_dma_address(sg));
+ }
+@@ -1592,22 +1589,10 @@ static void msc_mmap_close(struct vm_area_struct *vma)
+ {
+ struct msc_iter *iter = vma->vm_file->private_data;
+ struct msc *msc = iter->msc;
+- unsigned long pg;
+
+ if (!atomic_dec_and_mutex_lock(&msc->mmap_count, &msc->buf_mutex))
+ return;
+
+- /* drop page _refcounts */
+- for (pg = 0; pg < msc->nr_pages; pg++) {
+- struct page *page = msc_buffer_get_page(msc, pg);
+-
+- if (WARN_ON_ONCE(!page))
+- continue;
+-
+- if (page->mapping)
+- page->mapping = NULL;
+- }
+-
+ /* last mapping -- drop user_count */
+ atomic_dec(&msc->user_count);
+ mutex_unlock(&msc->buf_mutex);
+@@ -1617,16 +1602,14 @@ static vm_fault_t msc_mmap_fault(struct vm_fault *vmf)
+ {
+ struct msc_iter *iter = vmf->vma->vm_file->private_data;
+ struct msc *msc = iter->msc;
++ struct page *page;
+
+- vmf->page = msc_buffer_get_page(msc, vmf->pgoff);
+- if (!vmf->page)
++ page = msc_buffer_get_page(msc, vmf->pgoff);
++ if (!page)
+ return VM_FAULT_SIGBUS;
+
+- get_page(vmf->page);
+- vmf->page->mapping = vmf->vma->vm_file->f_mapping;
+- vmf->page->index = vmf->pgoff;
+-
+- return 0;
++ get_page(page);
++ return vmf_insert_mixed(vmf->vma, vmf->address, page_to_pfn_t(page));
+ }
+
+ static const struct vm_operations_struct msc_mmap_ops = {
+@@ -1667,7 +1650,7 @@ static int intel_th_msc_mmap(struct file *file, struct vm_area_struct *vma)
+ atomic_dec(&msc->user_count);
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+- vm_flags_set(vma, VM_DONTEXPAND | VM_DONTCOPY);
++ vm_flags_set(vma, VM_DONTEXPAND | VM_DONTCOPY | VM_MIXEDMAP);
+ vma->vm_ops = &msc_mmap_ops;
+ return ret;
+ }
+--
+2.39.5
+
--- /dev/null
+From 5b4b7f9d492b3a3267af896852bd735cba2440d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Apr 2025 12:28:39 +0100
+Subject: io_uring: don't duplicate flushing in io_req_post_cqe
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+[ Upstream commit 5e16f1a68d28965c12b6fa227a306fef8a680f84 ]
+
+io_req_post_cqe() sets submit_state.cq_flush so that
+*flush_completions() can take care of batch commiting CQEs. Don't commit
+it twice by using __io_cq_unlock_post().
+
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Link: https://lore.kernel.org/r/41c416660c509cee676b6cad96081274bcb459f3.1745493861.git.asml.silence@gmail.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ io_uring/io_uring.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
+index 8ef0603c07f11..985c87ea09a90 100644
+--- a/io_uring/io_uring.c
++++ b/io_uring/io_uring.c
+@@ -874,10 +874,15 @@ bool io_req_post_cqe(struct io_kiocb *req, s32 res, u32 cflags)
+ lockdep_assert(!io_wq_current_is_worker());
+ lockdep_assert_held(&ctx->uring_lock);
+
+- __io_cq_lock(ctx);
+- posted = io_fill_cqe_aux(ctx, req->cqe.user_data, res, cflags);
++ if (!ctx->lockless_cq) {
++ spin_lock(&ctx->completion_lock);
++ posted = io_fill_cqe_aux(ctx, req->cqe.user_data, res, cflags);
++ spin_unlock(&ctx->completion_lock);
++ } else {
++ posted = io_fill_cqe_aux(ctx, req->cqe.user_data, res, cflags);
++ }
++
+ ctx->submit_state.cq_flush = true;
+- __io_cq_unlock_post(ctx);
+ return posted;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From a4f2a220136145e6d285703465b26447f1dc4235 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Apr 2025 07:17:17 -0600
+Subject: io_uring/fdinfo: annotate racy sq/cq head/tail reads
+
+From: Jens Axboe <axboe@kernel.dk>
+
+[ Upstream commit f024d3a8ded0d8d2129ae123d7a5305c29ca44ce ]
+
+syzbot complains about the cached sq head read, and it's totally right.
+But we don't need to care, it's just reading fdinfo, and reading the
+CQ or SQ tail/head entries are known racy in that they are just a view
+into that very instant and may of course be outdated by the time they
+are reported.
+
+Annotate both the SQ head and CQ tail read with data_race() to avoid
+this syzbot complaint.
+
+Link: https://lore.kernel.org/io-uring/6811f6dc.050a0220.39e3a1.0d0e.GAE@google.com/
+Reported-by: syzbot+3e77fd302e99f5af9394@syzkaller.appspotmail.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ io_uring/fdinfo.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/io_uring/fdinfo.c b/io_uring/fdinfo.c
+index 6b1247664b355..ecdbe473a49f7 100644
+--- a/io_uring/fdinfo.c
++++ b/io_uring/fdinfo.c
+@@ -83,11 +83,11 @@ __cold void io_uring_show_fdinfo(struct seq_file *m, struct file *file)
+ seq_printf(m, "SqMask:\t0x%x\n", sq_mask);
+ seq_printf(m, "SqHead:\t%u\n", sq_head);
+ seq_printf(m, "SqTail:\t%u\n", sq_tail);
+- seq_printf(m, "CachedSqHead:\t%u\n", ctx->cached_sq_head);
++ seq_printf(m, "CachedSqHead:\t%u\n", data_race(ctx->cached_sq_head));
+ seq_printf(m, "CqMask:\t0x%x\n", cq_mask);
+ seq_printf(m, "CqHead:\t%u\n", cq_head);
+ seq_printf(m, "CqTail:\t%u\n", cq_tail);
+- seq_printf(m, "CachedCqTail:\t%u\n", ctx->cached_cq_tail);
++ seq_printf(m, "CachedCqTail:\t%u\n", data_race(ctx->cached_cq_tail));
+ seq_printf(m, "SQEs:\t%u\n", sq_tail - sq_head);
+ sq_entries = min(sq_tail - sq_head, ctx->sq_entries);
+ for (i = 0; i < sq_entries; i++) {
+--
+2.39.5
+
--- /dev/null
+From 666701a2c1b6774fd20220e1f5cc5b81529f7bc0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Mar 2025 23:11:50 +0000
+Subject: io_uring/msg: initialise msg request opcode
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+[ Upstream commit 9cc0bbdaba2a66ad90bc6ce45163b7745baffe98 ]
+
+It's risky to have msg request opcode set to garbage, so at least
+initialise it to nop. Later we might want to add a user inaccessible
+opcode for such cases.
+
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Link: https://lore.kernel.org/r/9afe650fcb348414a4529d89f52eb8969ba06efd.1743190078.git.asml.silence@gmail.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ io_uring/msg_ring.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/io_uring/msg_ring.c b/io_uring/msg_ring.c
+index 7fd9badcfaf81..35b1b585e9cbe 100644
+--- a/io_uring/msg_ring.c
++++ b/io_uring/msg_ring.c
+@@ -94,6 +94,7 @@ static int io_msg_remote_post(struct io_ring_ctx *ctx, struct io_kiocb *req,
+ kmem_cache_free(req_cachep, req);
+ return -EOWNERDEAD;
+ }
++ req->opcode = IORING_OP_NOP;
+ req->cqe.user_data = user_data;
+ io_req_set_res(req, res, cflags);
+ percpu_ref_get(&ctx->refs);
+--
+2.39.5
+
--- /dev/null
+From 4b04cce2a9c3856638252801d1f2360903718a35 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Feb 2025 16:23:16 +0000
+Subject: iommu/amd/pgtbl_v2: Improve error handling
+
+From: Vasant Hegde <vasant.hegde@amd.com>
+
+[ Upstream commit 36a1cfd497435ba5e37572fe9463bb62a7b1b984 ]
+
+Return -ENOMEM if v2_alloc_pte() fails to allocate memory.
+
+Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
+Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
+Link: https://lore.kernel.org/r/20250227162320.5805-4-vasant.hegde@amd.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/amd/io_pgtable_v2.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/iommu/amd/io_pgtable_v2.c b/drivers/iommu/amd/io_pgtable_v2.c
+index c616de2c5926e..a56a273963059 100644
+--- a/drivers/iommu/amd/io_pgtable_v2.c
++++ b/drivers/iommu/amd/io_pgtable_v2.c
+@@ -254,7 +254,7 @@ static int iommu_v2_map_pages(struct io_pgtable_ops *ops, unsigned long iova,
+ pte = v2_alloc_pte(cfg->amd.nid, pgtable->pgd,
+ iova, map_size, gfp, &updated);
+ if (!pte) {
+- ret = -EINVAL;
++ ret = -ENOMEM;
+ goto out;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 73525cebeb5f7fd3ffdf6567abaf794632c593de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Feb 2025 15:46:32 +0000
+Subject: iommu: Keep dev->iommu state consistent
+
+From: Robin Murphy <robin.murphy@arm.com>
+
+[ Upstream commit 3832862eb9c4dfa0e80b2522bfaedbc8a43de97d ]
+
+At the moment, if of_iommu_configure() allocates dev->iommu itself via
+iommu_fwspec_init(), then suffers a DT parsing failure, it cleans up the
+fwspec but leaves the empty dev_iommu hanging around. So far this is
+benign (if a tiny bit wasteful), but we'd like to be able to reason
+about dev->iommu having a consistent and unambiguous lifecycle. Thus
+make sure that the of_iommu cleanup undoes precisely whatever it did.
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
+Link: https://lore.kernel.org/r/d219663a3f23001f23d520a883ac622d70b4e642.1740753261.git.robin.murphy@arm.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/iommu-priv.h | 2 ++
+ drivers/iommu/iommu.c | 2 +-
+ drivers/iommu/of_iommu.c | 6 +++++-
+ 3 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/iommu/iommu-priv.h b/drivers/iommu/iommu-priv.h
+index de5b54eaa8bf1..a5913c0b02a0a 100644
+--- a/drivers/iommu/iommu-priv.h
++++ b/drivers/iommu/iommu-priv.h
+@@ -17,6 +17,8 @@ static inline const struct iommu_ops *dev_iommu_ops(struct device *dev)
+ return dev->iommu->iommu_dev->ops;
+ }
+
++void dev_iommu_free(struct device *dev);
++
+ const struct iommu_ops *iommu_ops_from_fwnode(const struct fwnode_handle *fwnode);
+
+ static inline const struct iommu_ops *iommu_fwspec_ops(struct iommu_fwspec *fwspec)
+diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
+index cac3dce111689..879009adef407 100644
+--- a/drivers/iommu/iommu.c
++++ b/drivers/iommu/iommu.c
+@@ -347,7 +347,7 @@ static struct dev_iommu *dev_iommu_get(struct device *dev)
+ return param;
+ }
+
+-static void dev_iommu_free(struct device *dev)
++void dev_iommu_free(struct device *dev)
+ {
+ struct dev_iommu *param = dev->iommu;
+
+diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
+index e7a6a1611d193..e3fcab925a547 100644
+--- a/drivers/iommu/of_iommu.c
++++ b/drivers/iommu/of_iommu.c
+@@ -118,6 +118,7 @@ static void of_pci_check_device_ats(struct device *dev, struct device_node *np)
+ int of_iommu_configure(struct device *dev, struct device_node *master_np,
+ const u32 *id)
+ {
++ bool dev_iommu_present;
+ int err;
+
+ if (!master_np)
+@@ -129,6 +130,7 @@ int of_iommu_configure(struct device *dev, struct device_node *master_np,
+ mutex_unlock(&iommu_probe_device_lock);
+ return 0;
+ }
++ dev_iommu_present = dev->iommu;
+
+ /*
+ * We don't currently walk up the tree looking for a parent IOMMU.
+@@ -149,8 +151,10 @@ int of_iommu_configure(struct device *dev, struct device_node *master_np,
+ err = of_iommu_configure_device(master_np, dev, id);
+ }
+
+- if (err)
++ if (err && dev_iommu_present)
+ iommu_fwspec_free(dev);
++ else if (err && dev->iommu)
++ dev_iommu_free(dev);
+ mutex_unlock(&iommu_probe_device_lock);
+
+ if (!err && dev->bus)
+--
+2.39.5
+
--- /dev/null
+From 45bad9afb01cf09b1301a08c8e036758f4560543 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Mar 2025 10:47:47 +0800
+Subject: iommu/vt-d: Move scalable mode ATS enablement to probe path
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+[ Upstream commit 5518f239aff1baf772c5748da3add7243c5fb5df ]
+
+Device ATS is currently enabled when a domain is attached to the device
+and disabled when the domain is detached. This creates a limitation:
+when the IOMMU is operating in scalable mode and IOPF is enabled, the
+device's domain cannot be changed.
+
+The previous code enables ATS when a domain is set to a device's RID and
+disables it during RID domain switch. So, if a PASID is set with a
+domain requiring PRI, ATS should remain enabled until the domain is
+removed. During the PASID domain's lifecycle, if the RID's domain
+changes, PRI will be disrupted because it depends on ATS, which is
+disabled when the blocking domain is set for the device's RID.
+
+Remove this limitation by moving ATS enablement to the device probe path.
+
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Tested-by: Zhangfei Gao <zhangfei.gao@linaro.org>
+Link: https://lore.kernel.org/r/20250228092631.3425464-5-baolu.lu@linux.intel.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/iommu.c | 51 ++++++++++++++++++++-----------------
+ 1 file changed, 27 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
+index 157542c07aaaf..737f33cddc43f 100644
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -1284,32 +1284,28 @@ static bool dev_needs_extra_dtlb_flush(struct pci_dev *pdev)
+ return true;
+ }
+
+-static void iommu_enable_pci_caps(struct device_domain_info *info)
++static void iommu_enable_pci_ats(struct device_domain_info *info)
+ {
+ struct pci_dev *pdev;
+
+- if (!dev_is_pci(info->dev))
++ if (!info->ats_supported)
+ return;
+
+ pdev = to_pci_dev(info->dev);
+- if (info->ats_supported && pci_ats_page_aligned(pdev) &&
+- !pci_enable_ats(pdev, VTD_PAGE_SHIFT))
++ if (!pci_ats_page_aligned(pdev))
++ return;
++
++ if (!pci_enable_ats(pdev, VTD_PAGE_SHIFT))
+ info->ats_enabled = 1;
+ }
+
+-static void iommu_disable_pci_caps(struct device_domain_info *info)
++static void iommu_disable_pci_ats(struct device_domain_info *info)
+ {
+- struct pci_dev *pdev;
+-
+- if (!dev_is_pci(info->dev))
++ if (!info->ats_enabled)
+ return;
+
+- pdev = to_pci_dev(info->dev);
+-
+- if (info->ats_enabled) {
+- pci_disable_ats(pdev);
+- info->ats_enabled = 0;
+- }
++ pci_disable_ats(to_pci_dev(info->dev));
++ info->ats_enabled = 0;
+ }
+
+ static void intel_flush_iotlb_all(struct iommu_domain *domain)
+@@ -1722,12 +1718,19 @@ domain_context_mapping(struct dmar_domain *domain, struct device *dev)
+ struct device_domain_info *info = dev_iommu_priv_get(dev);
+ struct intel_iommu *iommu = info->iommu;
+ u8 bus = info->bus, devfn = info->devfn;
++ int ret;
+
+ if (!dev_is_pci(dev))
+ return domain_context_mapping_one(domain, iommu, bus, devfn);
+
+- return pci_for_each_dma_alias(to_pci_dev(dev),
+- domain_context_mapping_cb, domain);
++ ret = pci_for_each_dma_alias(to_pci_dev(dev),
++ domain_context_mapping_cb, domain);
++ if (ret)
++ return ret;
++
++ iommu_enable_pci_ats(info);
++
++ return 0;
+ }
+
+ /* Return largest possible superpage level for a given mapping */
+@@ -1987,8 +1990,6 @@ static int dmar_domain_attach_device(struct dmar_domain *domain,
+ if (ret)
+ goto out_block_translation;
+
+- iommu_enable_pci_caps(info);
+-
+ ret = cache_tag_assign_domain(domain, dev, IOMMU_NO_PASID);
+ if (ret)
+ goto out_block_translation;
+@@ -3368,6 +3369,7 @@ static void domain_context_clear(struct device_domain_info *info)
+
+ pci_for_each_dma_alias(to_pci_dev(info->dev),
+ &domain_context_clear_one_cb, info);
++ iommu_disable_pci_ats(info);
+ }
+
+ /*
+@@ -3384,7 +3386,6 @@ void device_block_translation(struct device *dev)
+ if (info->domain)
+ cache_tag_unassign_domain(info->domain, dev, IOMMU_NO_PASID);
+
+- iommu_disable_pci_caps(info);
+ if (!dev_is_real_dma_subdevice(dev)) {
+ if (sm_supported(iommu))
+ intel_pasid_tear_down_entry(iommu, dev,
+@@ -3964,6 +3965,9 @@ static struct iommu_device *intel_iommu_probe_device(struct device *dev)
+ !pci_enable_pasid(pdev, info->pasid_supported & ~1))
+ info->pasid_enabled = 1;
+
++ if (sm_supported(iommu))
++ iommu_enable_pci_ats(info);
++
+ return &iommu->iommu;
+ free_table:
+ intel_pasid_free_table(dev);
+@@ -3980,6 +3984,8 @@ static void intel_iommu_release_device(struct device *dev)
+ struct device_domain_info *info = dev_iommu_priv_get(dev);
+ struct intel_iommu *iommu = info->iommu;
+
++ iommu_disable_pci_ats(info);
++
+ if (info->pasid_enabled) {
+ pci_disable_pasid(to_pci_dev(dev));
+ info->pasid_enabled = 0;
+@@ -4581,13 +4587,10 @@ static int identity_domain_attach_dev(struct iommu_domain *domain, struct device
+ if (dev_is_real_dma_subdevice(dev))
+ return 0;
+
+- if (sm_supported(iommu)) {
++ if (sm_supported(iommu))
+ ret = intel_pasid_setup_pass_through(iommu, dev, IOMMU_NO_PASID);
+- if (!ret)
+- iommu_enable_pci_caps(info);
+- } else {
++ else
+ ret = device_setup_pass_through(dev);
+- }
+
+ return ret;
+ }
+--
+2.39.5
+
--- /dev/null
+From c3dd9ce314ac02f6a3e638d6a00723ef18760c73 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Feb 2025 02:40:12 -0800
+Subject: iommufd: Disallow allocating nested parent domain with fault ID
+
+From: Yi Liu <yi.l.liu@intel.com>
+
+[ Upstream commit 1062d81086156e42878d701b816d2f368b53a77c ]
+
+Allocating a domain with a fault ID indicates that the domain is faultable.
+However, there is a gap for the nested parent domain to support PRI. Some
+hardware lacks the capability to distinguish whether PRI occurs at stage 1
+or stage 2. This limitation may require software-based page table walking
+to resolve. Since no in-tree IOMMU driver currently supports this
+functionality, it is disallowed. For more details, refer to the related
+discussion at [1].
+
+[1] https://lore.kernel.org/linux-iommu/bd1655c6-8b2f-4cfa-adb1-badc00d01811@intel.com/
+
+Link: https://patch.msgid.link/r/20250226104012.82079-1-yi.l.liu@intel.com
+Suggested-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Yi Liu <yi.l.liu@intel.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/iommufd/hw_pagetable.c | 3 +++
+ tools/testing/selftests/iommu/iommufd.c | 4 ++++
+ 2 files changed, 7 insertions(+)
+
+diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c
+index d06bf6e6c19fd..2454627a8b61b 100644
+--- a/drivers/iommu/iommufd/hw_pagetable.c
++++ b/drivers/iommu/iommufd/hw_pagetable.c
+@@ -122,6 +122,9 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
+ if ((flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING) &&
+ !device_iommu_capable(idev->dev, IOMMU_CAP_DIRTY_TRACKING))
+ return ERR_PTR(-EOPNOTSUPP);
++ if ((flags & IOMMU_HWPT_FAULT_ID_VALID) &&
++ (flags & IOMMU_HWPT_ALLOC_NEST_PARENT))
++ return ERR_PTR(-EOPNOTSUPP);
+
+ hwpt_paging = __iommufd_object_alloc(
+ ictx, hwpt_paging, IOMMUFD_OBJ_HWPT_PAGING, common.obj);
+diff --git a/tools/testing/selftests/iommu/iommufd.c b/tools/testing/selftests/iommu/iommufd.c
+index 4927b9add5add..06f252733660a 100644
+--- a/tools/testing/selftests/iommu/iommufd.c
++++ b/tools/testing/selftests/iommu/iommufd.c
+@@ -289,6 +289,10 @@ TEST_F(iommufd_ioas, alloc_hwpt_nested)
+ &test_hwpt_id);
+ test_err_hwpt_alloc(EINVAL, self->device_id, self->device_id, 0,
+ &test_hwpt_id);
++ test_err_hwpt_alloc(EOPNOTSUPP, self->device_id, self->ioas_id,
++ IOMMU_HWPT_ALLOC_NEST_PARENT |
++ IOMMU_HWPT_FAULT_ID_VALID,
++ &test_hwpt_id);
+
+ test_cmd_hwpt_alloc(self->device_id, self->ioas_id,
+ IOMMU_HWPT_ALLOC_NEST_PARENT,
+--
+2.39.5
+
--- /dev/null
+From e60f7337211d074862bef142bb68c72fd510a4c4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Mar 2025 11:01:42 -0700
+Subject: iommufd: Extend IOMMU_GET_HW_INFO to report PASID capability
+
+From: Yi Liu <yi.l.liu@intel.com>
+
+[ Upstream commit 803f97298e7de9242eb677a1351dcafbbcc9117e ]
+
+PASID usage requires PASID support in both device and IOMMU. Since the
+iommu drivers always enable the PASID capability for the device if it
+is supported, this extends the IOMMU_GET_HW_INFO to report the PASID
+capability to userspace. Also, enhances the selftest accordingly.
+
+Link: https://patch.msgid.link/r/20250321180143.8468-5-yi.l.liu@intel.com
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
+Tested-by: Zhangfei Gao <zhangfei.gao@linaro.org> #aarch64 platform
+Tested-by: Nicolin Chen <nicolinc@nvidia.com>
+Signed-off-by: Yi Liu <yi.l.liu@intel.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/iommufd/device.c | 34 +++++++++++++++++++++++++++++++++-
+ drivers/pci/ats.c | 33 +++++++++++++++++++++++++++++++++
+ include/linux/pci-ats.h | 3 +++
+ include/uapi/linux/iommufd.h | 14 +++++++++++++-
+ 4 files changed, 82 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c
+index 3fd8920e79ffb..74480ae6bfc0b 100644
+--- a/drivers/iommu/iommufd/device.c
++++ b/drivers/iommu/iommufd/device.c
+@@ -3,6 +3,7 @@
+ */
+ #include <linux/iommu.h>
+ #include <linux/iommufd.h>
++#include <linux/pci-ats.h>
+ #include <linux/slab.h>
+ #include <uapi/linux/iommufd.h>
+
+@@ -1304,7 +1305,8 @@ int iommufd_get_hw_info(struct iommufd_ucmd *ucmd)
+ void *data;
+ int rc;
+
+- if (cmd->flags || cmd->__reserved)
++ if (cmd->flags || cmd->__reserved[0] || cmd->__reserved[1] ||
++ cmd->__reserved[2])
+ return -EOPNOTSUPP;
+
+ idev = iommufd_get_device(ucmd, cmd->dev_id);
+@@ -1361,6 +1363,36 @@ int iommufd_get_hw_info(struct iommufd_ucmd *ucmd)
+ if (device_iommu_capable(idev->dev, IOMMU_CAP_DIRTY_TRACKING))
+ cmd->out_capabilities |= IOMMU_HW_CAP_DIRTY_TRACKING;
+
++ cmd->out_max_pasid_log2 = 0;
++ /*
++ * Currently, all iommu drivers enable PASID in the probe_device()
++ * op if iommu and device supports it. So the max_pasids stored in
++ * dev->iommu indicates both PASID support and enable status. A
++ * non-zero dev->iommu->max_pasids means PASID is supported and
++ * enabled. The iommufd only reports PASID capability to userspace
++ * if it's enabled.
++ */
++ if (idev->dev->iommu->max_pasids) {
++ cmd->out_max_pasid_log2 = ilog2(idev->dev->iommu->max_pasids);
++
++ if (dev_is_pci(idev->dev)) {
++ struct pci_dev *pdev = to_pci_dev(idev->dev);
++ int ctrl;
++
++ ctrl = pci_pasid_status(pdev);
++
++ WARN_ON_ONCE(ctrl < 0 ||
++ !(ctrl & PCI_PASID_CTRL_ENABLE));
++
++ if (ctrl & PCI_PASID_CTRL_EXEC)
++ cmd->out_capabilities |=
++ IOMMU_HW_CAP_PCI_PASID_EXEC;
++ if (ctrl & PCI_PASID_CTRL_PRIV)
++ cmd->out_capabilities |=
++ IOMMU_HW_CAP_PCI_PASID_PRIV;
++ }
++ }
++
+ rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
+ out_free:
+ kfree(data);
+diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c
+index 6afff1f1b1430..c331b108e71de 100644
+--- a/drivers/pci/ats.c
++++ b/drivers/pci/ats.c
+@@ -538,4 +538,37 @@ int pci_max_pasids(struct pci_dev *pdev)
+ return (1 << FIELD_GET(PCI_PASID_CAP_WIDTH, supported));
+ }
+ EXPORT_SYMBOL_GPL(pci_max_pasids);
++
++/**
++ * pci_pasid_status - Check the PASID status
++ * @pdev: PCI device structure
++ *
++ * Returns a negative value when no PASID capability is present.
++ * Otherwise the value of the control register is returned.
++ * Status reported are:
++ *
++ * PCI_PASID_CTRL_ENABLE - PASID enabled
++ * PCI_PASID_CTRL_EXEC - Execute permission enabled
++ * PCI_PASID_CTRL_PRIV - Privileged mode enabled
++ */
++int pci_pasid_status(struct pci_dev *pdev)
++{
++ int pasid;
++ u16 ctrl;
++
++ if (pdev->is_virtfn)
++ pdev = pci_physfn(pdev);
++
++ pasid = pdev->pasid_cap;
++ if (!pasid)
++ return -EINVAL;
++
++ pci_read_config_word(pdev, pasid + PCI_PASID_CTRL, &ctrl);
++
++ ctrl &= PCI_PASID_CTRL_ENABLE | PCI_PASID_CTRL_EXEC |
++ PCI_PASID_CTRL_PRIV;
++
++ return ctrl;
++}
++EXPORT_SYMBOL_GPL(pci_pasid_status);
+ #endif /* CONFIG_PCI_PASID */
+diff --git a/include/linux/pci-ats.h b/include/linux/pci-ats.h
+index 0e8b74e63767a..75c6c86cf09dc 100644
+--- a/include/linux/pci-ats.h
++++ b/include/linux/pci-ats.h
+@@ -42,6 +42,7 @@ int pci_enable_pasid(struct pci_dev *pdev, int features);
+ void pci_disable_pasid(struct pci_dev *pdev);
+ int pci_pasid_features(struct pci_dev *pdev);
+ int pci_max_pasids(struct pci_dev *pdev);
++int pci_pasid_status(struct pci_dev *pdev);
+ #else /* CONFIG_PCI_PASID */
+ static inline int pci_enable_pasid(struct pci_dev *pdev, int features)
+ { return -EINVAL; }
+@@ -50,6 +51,8 @@ static inline int pci_pasid_features(struct pci_dev *pdev)
+ { return -EINVAL; }
+ static inline int pci_max_pasids(struct pci_dev *pdev)
+ { return -EINVAL; }
++static inline int pci_pasid_status(struct pci_dev *pdev)
++{ return -EINVAL; }
+ #endif /* CONFIG_PCI_PASID */
+
+ #endif /* LINUX_PCI_ATS_H */
+diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
+index 8c4470742dcd9..41048271a0667 100644
+--- a/include/uapi/linux/iommufd.h
++++ b/include/uapi/linux/iommufd.h
+@@ -504,9 +504,17 @@ enum iommu_hw_info_type {
+ * IOMMU_HWPT_GET_DIRTY_BITMAP
+ * IOMMU_HWPT_SET_DIRTY_TRACKING
+ *
++ * @IOMMU_HW_CAP_PCI_PASID_EXEC: Execute Permission Supported, user ignores it
++ * when the struct
++ * iommu_hw_info::out_max_pasid_log2 is zero.
++ * @IOMMU_HW_CAP_PCI_PASID_PRIV: Privileged Mode Supported, user ignores it
++ * when the struct
++ * iommu_hw_info::out_max_pasid_log2 is zero.
+ */
+ enum iommufd_hw_capabilities {
+ IOMMU_HW_CAP_DIRTY_TRACKING = 1 << 0,
++ IOMMU_HW_CAP_PCI_PASID_EXEC = 1 << 1,
++ IOMMU_HW_CAP_PCI_PASID_PRIV = 1 << 2,
+ };
+
+ /**
+@@ -522,6 +530,9 @@ enum iommufd_hw_capabilities {
+ * iommu_hw_info_type.
+ * @out_capabilities: Output the generic iommu capability info type as defined
+ * in the enum iommu_hw_capabilities.
++ * @out_max_pasid_log2: Output the width of PASIDs. 0 means no PASID support.
++ * PCI devices turn to out_capabilities to check if the
++ * specific capabilities is supported or not.
+ * @__reserved: Must be 0
+ *
+ * Query an iommu type specific hardware information data from an iommu behind
+@@ -545,7 +556,8 @@ struct iommu_hw_info {
+ __u32 data_len;
+ __aligned_u64 data_uptr;
+ __u32 out_data_type;
+- __u32 __reserved;
++ __u8 out_max_pasid_log2;
++ __u8 __reserved[3];
+ __aligned_u64 out_capabilities;
+ };
+ #define IOMMU_GET_HW_INFO _IO(IOMMUFD_TYPE, IOMMUFD_CMD_GET_HW_INFO)
+--
+2.39.5
+
--- /dev/null
+From fa5086f407ec81ade83be1d9942fae8dd5211a25 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Feb 2025 16:24:58 +0900
+Subject: ip: fib_rules: Fetch net from fib_rule in fib[46]_rule_configure().
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit 5a1ccffd30a08f5a2428cd5fbb3ab03e8eb6c66d ]
+
+The following patch will not set skb->sk from VRF path.
+
+Let's fetch net from fib_rule->fr_net instead of sock_net(skb->sk)
+in fib[46]_rule_configure().
+
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Tested-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20250207072502.87775-5-kuniyu@amazon.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/fib_rules.c | 4 ++--
+ net/ipv6/fib6_rules.c | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
+index b07292d50ee76..4563e5303c1a8 100644
+--- a/net/ipv4/fib_rules.c
++++ b/net/ipv4/fib_rules.c
+@@ -245,9 +245,9 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
+ struct nlattr **tb,
+ struct netlink_ext_ack *extack)
+ {
+- struct net *net = sock_net(skb->sk);
++ struct fib4_rule *rule4 = (struct fib4_rule *)rule;
++ struct net *net = rule->fr_net;
+ int err = -EINVAL;
+- struct fib4_rule *rule4 = (struct fib4_rule *) rule;
+
+ if (!inet_validate_dscp(frh->tos)) {
+ NL_SET_ERR_MSG(extack,
+diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
+index 04a9ed5e8310f..29185c9ebd020 100644
+--- a/net/ipv6/fib6_rules.c
++++ b/net/ipv6/fib6_rules.c
+@@ -365,9 +365,9 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
+ struct nlattr **tb,
+ struct netlink_ext_ack *extack)
+ {
++ struct fib6_rule *rule6 = (struct fib6_rule *)rule;
++ struct net *net = rule->fr_net;
+ int err = -EINVAL;
+- struct net *net = sock_net(skb->sk);
+- struct fib6_rule *rule6 = (struct fib6_rule *) rule;
+
+ if (!inet_validate_dscp(frh->tos)) {
+ NL_SET_ERR_MSG(extack,
+--
+2.39.5
+
--- /dev/null
+From a020d6a95d8ea59a06788bf69a89048fd5d7b2fe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Feb 2025 20:23:27 -0800
+Subject: ipv4: fib: Move fib_valid_key_len() to rtm_to_fib_config().
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit 254ba7e6032d3fc738050d500b0c1d8197af90ca ]
+
+fib_valid_key_len() is called in the beginning of fib_table_insert()
+or fib_table_delete() to check if the prefix length is valid.
+
+fib_table_insert() and fib_table_delete() are called from 3 paths
+
+ - ip_rt_ioctl()
+ - inet_rtm_newroute() / inet_rtm_delroute()
+ - fib_magic()
+
+In the first ioctl() path, rtentry_to_fib_config() checks the prefix
+length with bad_mask(). Also, fib_magic() always passes the correct
+prefix: 32 or ifa->ifa_prefixlen, which is already validated.
+
+Let's move fib_valid_key_len() to the rtnetlink path, rtm_to_fib_config().
+
+While at it, 2 direct returns in rtm_to_fib_config() are changed to
+goto to match other places in the same function
+
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Link: https://patch.msgid.link/20250228042328.96624-12-kuniyu@amazon.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/fib_frontend.c | 18 ++++++++++++++++--
+ net/ipv4/fib_trie.c | 22 ----------------------
+ 2 files changed, 16 insertions(+), 24 deletions(-)
+
+diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
+index 793e6781399a4..5b7c41333d6fc 100644
+--- a/net/ipv4/fib_frontend.c
++++ b/net/ipv4/fib_frontend.c
+@@ -829,19 +829,33 @@ static int rtm_to_fib_config(struct net *net, struct sk_buff *skb,
+ }
+ }
+
++ if (cfg->fc_dst_len > 32) {
++ NL_SET_ERR_MSG(extack, "Invalid prefix length");
++ err = -EINVAL;
++ goto errout;
++ }
++
++ if (cfg->fc_dst_len < 32 && (ntohl(cfg->fc_dst) << cfg->fc_dst_len)) {
++ NL_SET_ERR_MSG(extack, "Invalid prefix for given prefix length");
++ err = -EINVAL;
++ goto errout;
++ }
++
+ if (cfg->fc_nh_id) {
+ if (cfg->fc_oif || cfg->fc_gw_family ||
+ cfg->fc_encap || cfg->fc_mp) {
+ NL_SET_ERR_MSG(extack,
+ "Nexthop specification and nexthop id are mutually exclusive");
+- return -EINVAL;
++ err = -EINVAL;
++ goto errout;
+ }
+ }
+
+ if (has_gw && has_via) {
+ NL_SET_ERR_MSG(extack,
+ "Nexthop configuration can not contain both GATEWAY and VIA");
+- return -EINVAL;
++ err = -EINVAL;
++ goto errout;
+ }
+
+ if (!cfg->fc_table)
+diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
+index 09e31757e96c7..cc86031d2050f 100644
+--- a/net/ipv4/fib_trie.c
++++ b/net/ipv4/fib_trie.c
+@@ -1193,22 +1193,6 @@ static int fib_insert_alias(struct trie *t, struct key_vector *tp,
+ return 0;
+ }
+
+-static bool fib_valid_key_len(u32 key, u8 plen, struct netlink_ext_ack *extack)
+-{
+- if (plen > KEYLENGTH) {
+- NL_SET_ERR_MSG(extack, "Invalid prefix length");
+- return false;
+- }
+-
+- if ((plen < KEYLENGTH) && (key << plen)) {
+- NL_SET_ERR_MSG(extack,
+- "Invalid prefix for given prefix length");
+- return false;
+- }
+-
+- return true;
+-}
+-
+ static void fib_remove_alias(struct trie *t, struct key_vector *tp,
+ struct key_vector *l, struct fib_alias *old);
+
+@@ -1229,9 +1213,6 @@ int fib_table_insert(struct net *net, struct fib_table *tb,
+
+ key = ntohl(cfg->fc_dst);
+
+- if (!fib_valid_key_len(key, plen, extack))
+- return -EINVAL;
+-
+ pr_debug("Insert table=%u %08x/%d\n", tb->tb_id, key, plen);
+
+ fi = fib_create_info(cfg, extack);
+@@ -1723,9 +1704,6 @@ int fib_table_delete(struct net *net, struct fib_table *tb,
+
+ key = ntohl(cfg->fc_dst);
+
+- if (!fib_valid_key_len(key, plen, extack))
+- return -EINVAL;
+-
+ l = fib_find_node(t, &tp, key);
+ if (!l)
+ return -ESRCH;
+--
+2.39.5
+
--- /dev/null
+From 34bd9b0c2ee1ea50981dba6a185f953f57b25cc5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Feb 2025 22:36:54 +0100
+Subject: ipv4: ip_gre: Fix set but not used warning in ipgre_err() if
+ IPv4-only
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Geert Uytterhoeven <geert@linux-m68k.org>
+
+[ Upstream commit 50f37fc2a39c4a8cc4813629b4cf239b71c6097d ]
+
+if CONFIG_NET_IPGRE is enabled, but CONFIG_IPV6 is disabled:
+
+ net/ipv4/ip_gre.c: In function ‘ipgre_err’:
+ net/ipv4/ip_gre.c:144:22: error: variable ‘data_len’ set but not used [-Werror=unused-but-set-variable]
+ 144 | unsigned int data_len = 0;
+ | ^~~~~~~~
+
+Fix this by moving all data_len processing inside the IPV6-only section
+that uses its result.
+
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202501121007.2GofXmh5-lkp@intel.com/
+Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/d09113cfe2bfaca02f3dddf832fb5f48dd20958b.1738704881.git.geert@linux-m68k.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_gre.c | 16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
+index f1f31ebfc7934..9667f27740258 100644
+--- a/net/ipv4/ip_gre.c
++++ b/net/ipv4/ip_gre.c
+@@ -141,7 +141,6 @@ static int ipgre_err(struct sk_buff *skb, u32 info,
+ const struct iphdr *iph;
+ const int type = icmp_hdr(skb)->type;
+ const int code = icmp_hdr(skb)->code;
+- unsigned int data_len = 0;
+ struct ip_tunnel *t;
+
+ if (tpi->proto == htons(ETH_P_TEB))
+@@ -182,7 +181,6 @@ static int ipgre_err(struct sk_buff *skb, u32 info,
+ case ICMP_TIME_EXCEEDED:
+ if (code != ICMP_EXC_TTL)
+ return 0;
+- data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
+ break;
+
+ case ICMP_REDIRECT:
+@@ -190,10 +188,16 @@ static int ipgre_err(struct sk_buff *skb, u32 info,
+ }
+
+ #if IS_ENABLED(CONFIG_IPV6)
+- if (tpi->proto == htons(ETH_P_IPV6) &&
+- !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len,
+- type, data_len))
+- return 0;
++ if (tpi->proto == htons(ETH_P_IPV6)) {
++ unsigned int data_len = 0;
++
++ if (type == ICMP_TIME_EXCEEDED)
++ data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
++
++ if (!ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len,
++ type, data_len))
++ return 0;
++ }
+ #endif
+
+ if (t->parms.iph.daddr == 0 ||
+--
+2.39.5
+
--- /dev/null
+From adfc6beaee5df86875b1f94d7d7adad71e98f147 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Mar 2025 22:34:09 -0500
+Subject: ipv6: save dontfrag in cork
+
+From: Willem de Bruijn <willemb@google.com>
+
+[ Upstream commit a18dfa9925b9ef6107ea3aa5814ca3c704d34a8a ]
+
+When spanning datagram construction over multiple send calls using
+MSG_MORE, per datagram settings are configured on the first send.
+
+That is when ip(6)_setup_cork stores these settings for subsequent use
+in __ip(6)_append_data and others.
+
+The only flag that escaped this was dontfrag. As a result, a datagram
+could be constructed with df=0 on the first sendmsg, but df=1 on a
+next. Which is what cmsg_ip.sh does in an upcoming MSG_MORE test in
+the "diff" scenario.
+
+Changing datagram conditions in the middle of constructing an skb
+makes this already complex code path even more convoluted. It is here
+unintentional. Bring this flag in line with expected sockopt/cmsg
+behavior.
+
+And stop passing ipc6 to __ip6_append_data, to avoid such issues
+in the future. This is already the case for __ip_append_data.
+
+inet6_cork had a 6 byte hole, so the 1B flag has no impact.
+
+Signed-off-by: Willem de Bruijn <willemb@google.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20250307033620.411611-3-willemdebruijn.kernel@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/ipv6.h | 1 +
+ net/ipv6/ip6_output.c | 9 +++++----
+ 2 files changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
+index a6e2aadbb91bd..5aeeed22f35bf 100644
+--- a/include/linux/ipv6.h
++++ b/include/linux/ipv6.h
+@@ -207,6 +207,7 @@ struct inet6_cork {
+ struct ipv6_txoptions *opt;
+ u8 hop_limit;
+ u8 tclass;
++ u8 dontfrag:1;
+ };
+
+ /* struct ipv6_pinfo - ipv6 private area */
+diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
+index 434ddf263b88a..89a61e040e6a1 100644
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -1386,6 +1386,7 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork,
+ }
+ v6_cork->hop_limit = ipc6->hlimit;
+ v6_cork->tclass = ipc6->tclass;
++ v6_cork->dontfrag = ipc6->dontfrag;
+ if (rt->dst.flags & DST_XFRM_TUNNEL)
+ mtu = READ_ONCE(np->pmtudisc) >= IPV6_PMTUDISC_PROBE ?
+ READ_ONCE(rt->dst.dev->mtu) : dst_mtu(&rt->dst);
+@@ -1417,7 +1418,7 @@ static int __ip6_append_data(struct sock *sk,
+ int getfrag(void *from, char *to, int offset,
+ int len, int odd, struct sk_buff *skb),
+ void *from, size_t length, int transhdrlen,
+- unsigned int flags, struct ipcm6_cookie *ipc6)
++ unsigned int flags)
+ {
+ struct sk_buff *skb, *skb_prev = NULL;
+ struct inet_cork *cork = &cork_full->base;
+@@ -1471,7 +1472,7 @@ static int __ip6_append_data(struct sock *sk,
+ if (headersize + transhdrlen > mtu)
+ goto emsgsize;
+
+- if (cork->length + length > mtu - headersize && ipc6->dontfrag &&
++ if (cork->length + length > mtu - headersize && v6_cork->dontfrag &&
+ (sk->sk_protocol == IPPROTO_UDP ||
+ sk->sk_protocol == IPPROTO_ICMPV6 ||
+ sk->sk_protocol == IPPROTO_RAW)) {
+@@ -1843,7 +1844,7 @@ int ip6_append_data(struct sock *sk,
+
+ return __ip6_append_data(sk, &sk->sk_write_queue, &inet->cork,
+ &np->cork, sk_page_frag(sk), getfrag,
+- from, length, transhdrlen, flags, ipc6);
++ from, length, transhdrlen, flags);
+ }
+ EXPORT_SYMBOL_GPL(ip6_append_data);
+
+@@ -2048,7 +2049,7 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
+ err = __ip6_append_data(sk, &queue, cork, &v6_cork,
+ ¤t->task_frag, getfrag, from,
+ length + exthdrlen, transhdrlen + exthdrlen,
+- flags, ipc6);
++ flags);
+ if (err) {
+ __ip6_flush_pending_frames(sk, &queue, cork, &v6_cork);
+ return ERR_PTR(err);
+--
+2.39.5
+
--- /dev/null
+From 83e6d88a21b3da2fa401429a1daf92ba772e81a5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jan 2025 11:16:37 +0200
+Subject: irqchip/riscv-aplic: Add support for hart indexes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
+
+[ Upstream commit b93afe8a3ac53ae52296d65acfaa9c5f582a48cc ]
+
+RISC-V APLIC specification defines "hart index" in:
+
+ https://github.com/riscv/riscv-aia
+
+Within a given interrupt domain, each of the domain’s harts has a unique
+index number in the range 0 to 2^14 − 1 (= 16,383). The index number a
+domain associates with a hart may or may not have any relationship to the
+unique hart identifier (“hart ID”) that the RISC-V Privileged Architecture
+assigns to the hart. Two different interrupt domains may employ entirely
+different index numbers for the same set of harts.
+
+Further, this document says in "4.5 Memory-mapped control region for an
+interrupt domain":
+
+The array of IDC structures may include some for potential hart index
+numbers that are not actual hart index numbers in the domain. For example,
+the first IDC structure is always for hart index 0, but 0 is not
+necessarily a valid index number for any hart in the domain.
+
+Support arbitrary hart indices specified in an optional APLIC property
+"riscv,hart-indexes" which is specified as an array of u32 elements, one
+per interrupt target. If this property is not specified, fallback to use
+logical hart indices within the domain.
+
+Signed-off-by: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Anup Patel <anup@brainfault.org>
+Link: https://lore.kernel.org/all/20250129091637.1667279-3-vladimir.kondratiev@mobileye.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/irqchip/irq-riscv-aplic-direct.c | 24 +++++++++++++++++++++---
+ 1 file changed, 21 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/irqchip/irq-riscv-aplic-direct.c b/drivers/irqchip/irq-riscv-aplic-direct.c
+index 7cd6b646774b9..205ad61d15e49 100644
+--- a/drivers/irqchip/irq-riscv-aplic-direct.c
++++ b/drivers/irqchip/irq-riscv-aplic-direct.c
+@@ -31,7 +31,7 @@ struct aplic_direct {
+ };
+
+ struct aplic_idc {
+- unsigned int hart_index;
++ u32 hart_index;
+ void __iomem *regs;
+ struct aplic_direct *direct;
+ };
+@@ -219,6 +219,20 @@ static int aplic_direct_parse_parent_hwirq(struct device *dev, u32 index,
+ return 0;
+ }
+
++static int aplic_direct_get_hart_index(struct device *dev, u32 logical_index,
++ u32 *hart_index)
++{
++ const char *prop_hart_index = "riscv,hart-indexes";
++ struct device_node *np = to_of_node(dev->fwnode);
++
++ if (!np || !of_property_present(np, prop_hart_index)) {
++ *hart_index = logical_index;
++ return 0;
++ }
++
++ return of_property_read_u32_index(np, prop_hart_index, logical_index, hart_index);
++}
++
+ int aplic_direct_setup(struct device *dev, void __iomem *regs)
+ {
+ int i, j, rc, cpu, current_cpu, setup_count = 0;
+@@ -265,8 +279,12 @@ int aplic_direct_setup(struct device *dev, void __iomem *regs)
+ cpumask_set_cpu(cpu, &direct->lmask);
+
+ idc = per_cpu_ptr(&aplic_idcs, cpu);
+- idc->hart_index = i;
+- idc->regs = priv->regs + APLIC_IDC_BASE + i * APLIC_IDC_SIZE;
++ rc = aplic_direct_get_hart_index(dev, i, &idc->hart_index);
++ if (rc) {
++ dev_warn(dev, "hart index not found for IDC%d\n", i);
++ continue;
++ }
++ idc->regs = priv->regs + APLIC_IDC_BASE + idc->hart_index * APLIC_IDC_SIZE;
+ idc->direct = direct;
+
+ aplic_idc_set_delivery(idc, true);
+--
+2.39.5
+
--- /dev/null
+From 4b533771d0285f90bfdcfc1330f59275033c083c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 14:26:53 +0530
+Subject: irqchip/riscv-imsic: Separate next and previous pointers in IMSIC
+ vector
+
+From: Anup Patel <apatel@ventanamicro.com>
+
+[ Upstream commit 0f67911e821c67ecfccc365a2103ce276a9a56fe ]
+
+Currently, there is only one "move" pointer in struct imsic_vector so
+during vector movement the old vector points to the new vector and new
+vector points to itself.
+
+To support forced cleanup of the old vector, add separate "move_next" and
+"move_prev" pointers to struct imsic_vector, where during vector movement
+the "move_next" pointer of the old vector points to the new vector and the
+"move_prev" pointer of the new vector points to the old vector.
+
+Both "move_next" and "move_prev" pointers are cleared separately by
+__imsic_local_sync() with a restriction that "move_prev" on the new
+CPU is cleared only after the old CPU has cleared "move_next".
+
+Signed-off-by: Anup Patel <apatel@ventanamicro.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/all/20250217085657.789309-8-apatel@ventanamicro.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/irqchip/irq-riscv-imsic-early.c | 8 ++-
+ drivers/irqchip/irq-riscv-imsic-state.c | 96 +++++++++++++++++--------
+ drivers/irqchip/irq-riscv-imsic-state.h | 7 +-
+ 3 files changed, 78 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/irqchip/irq-riscv-imsic-early.c b/drivers/irqchip/irq-riscv-imsic-early.c
+index c5c2e6929a2f5..b5def6268936e 100644
+--- a/drivers/irqchip/irq-riscv-imsic-early.c
++++ b/drivers/irqchip/irq-riscv-imsic-early.c
+@@ -77,6 +77,12 @@ static void imsic_handle_irq(struct irq_desc *desc)
+ struct imsic_vector *vec;
+ unsigned long local_id;
+
++ /*
++ * Process pending local synchronization instead of waiting
++ * for per-CPU local timer to expire.
++ */
++ imsic_local_sync_all(false);
++
+ chained_irq_enter(chip, desc);
+
+ while ((local_id = csr_swap(CSR_TOPEI, 0))) {
+@@ -120,7 +126,7 @@ static int imsic_starting_cpu(unsigned int cpu)
+ * Interrupts identities might have been enabled/disabled while
+ * this CPU was not running so sync-up local enable/disable state.
+ */
+- imsic_local_sync_all();
++ imsic_local_sync_all(true);
+
+ /* Enable local interrupt delivery */
+ imsic_local_delivery(true);
+diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
+index b97e6cd89ed74..1aeba76d72795 100644
+--- a/drivers/irqchip/irq-riscv-imsic-state.c
++++ b/drivers/irqchip/irq-riscv-imsic-state.c
+@@ -124,10 +124,11 @@ void __imsic_eix_update(unsigned long base_id, unsigned long num_id, bool pend,
+ }
+ }
+
+-static void __imsic_local_sync(struct imsic_local_priv *lpriv)
++static bool __imsic_local_sync(struct imsic_local_priv *lpriv)
+ {
+ struct imsic_local_config *mlocal;
+ struct imsic_vector *vec, *mvec;
++ bool ret = true;
+ int i;
+
+ lockdep_assert_held(&lpriv->lock);
+@@ -143,35 +144,75 @@ static void __imsic_local_sync(struct imsic_local_priv *lpriv)
+ __imsic_id_clear_enable(i);
+
+ /*
+- * If the ID was being moved to a new ID on some other CPU
+- * then we can get a MSI during the movement so check the
+- * ID pending bit and re-trigger the new ID on other CPU
+- * using MMIO write.
++ * Clear the previous vector pointer of the new vector only
++ * after the movement is complete on the old CPU.
+ */
+- mvec = READ_ONCE(vec->move);
+- WRITE_ONCE(vec->move, NULL);
+- if (mvec && mvec != vec) {
++ mvec = READ_ONCE(vec->move_prev);
++ if (mvec) {
++ /*
++ * If the old vector has not been updated then
++ * try again in the next sync-up call.
++ */
++ if (READ_ONCE(mvec->move_next)) {
++ ret = false;
++ continue;
++ }
++
++ WRITE_ONCE(vec->move_prev, NULL);
++ }
++
++ /*
++ * If a vector was being moved to a new vector on some other
++ * CPU then we can get a MSI during the movement so check the
++ * ID pending bit and re-trigger the new ID on other CPU using
++ * MMIO write.
++ */
++ mvec = READ_ONCE(vec->move_next);
++ if (mvec) {
+ if (__imsic_id_read_clear_pending(i)) {
+ mlocal = per_cpu_ptr(imsic->global.local, mvec->cpu);
+ writel_relaxed(mvec->local_id, mlocal->msi_va);
+ }
+
++ WRITE_ONCE(vec->move_next, NULL);
+ imsic_vector_free(&lpriv->vectors[i]);
+ }
+
+ skip:
+ bitmap_clear(lpriv->dirty_bitmap, i, 1);
+ }
++
++ return ret;
+ }
+
+-void imsic_local_sync_all(void)
++#ifdef CONFIG_SMP
++static void __imsic_local_timer_start(struct imsic_local_priv *lpriv)
++{
++ lockdep_assert_held(&lpriv->lock);
++
++ if (!timer_pending(&lpriv->timer)) {
++ lpriv->timer.expires = jiffies + 1;
++ add_timer_on(&lpriv->timer, smp_processor_id());
++ }
++}
++#else
++static inline void __imsic_local_timer_start(struct imsic_local_priv *lpriv)
++{
++}
++#endif
++
++void imsic_local_sync_all(bool force_all)
+ {
+ struct imsic_local_priv *lpriv = this_cpu_ptr(imsic->lpriv);
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&lpriv->lock, flags);
+- bitmap_fill(lpriv->dirty_bitmap, imsic->global.nr_ids + 1);
+- __imsic_local_sync(lpriv);
++
++ if (force_all)
++ bitmap_fill(lpriv->dirty_bitmap, imsic->global.nr_ids + 1);
++ if (!__imsic_local_sync(lpriv))
++ __imsic_local_timer_start(lpriv);
++
+ raw_spin_unlock_irqrestore(&lpriv->lock, flags);
+ }
+
+@@ -190,12 +231,7 @@ void imsic_local_delivery(bool enable)
+ #ifdef CONFIG_SMP
+ static void imsic_local_timer_callback(struct timer_list *timer)
+ {
+- struct imsic_local_priv *lpriv = this_cpu_ptr(imsic->lpriv);
+- unsigned long flags;
+-
+- raw_spin_lock_irqsave(&lpriv->lock, flags);
+- __imsic_local_sync(lpriv);
+- raw_spin_unlock_irqrestore(&lpriv->lock, flags);
++ imsic_local_sync_all(false);
+ }
+
+ static void __imsic_remote_sync(struct imsic_local_priv *lpriv, unsigned int cpu)
+@@ -216,14 +252,11 @@ static void __imsic_remote_sync(struct imsic_local_priv *lpriv, unsigned int cpu
+ */
+ if (cpu_online(cpu)) {
+ if (cpu == smp_processor_id()) {
+- __imsic_local_sync(lpriv);
+- return;
++ if (__imsic_local_sync(lpriv))
++ return;
+ }
+
+- if (!timer_pending(&lpriv->timer)) {
+- lpriv->timer.expires = jiffies + 1;
+- add_timer_on(&lpriv->timer, cpu);
+- }
++ __imsic_local_timer_start(lpriv);
+ }
+ }
+ #else
+@@ -278,8 +311,9 @@ void imsic_vector_unmask(struct imsic_vector *vec)
+ raw_spin_unlock(&lpriv->lock);
+ }
+
+-static bool imsic_vector_move_update(struct imsic_local_priv *lpriv, struct imsic_vector *vec,
+- bool new_enable, struct imsic_vector *new_move)
++static bool imsic_vector_move_update(struct imsic_local_priv *lpriv,
++ struct imsic_vector *vec, bool is_old_vec,
++ bool new_enable, struct imsic_vector *move_vec)
+ {
+ unsigned long flags;
+ bool enabled;
+@@ -289,7 +323,10 @@ static bool imsic_vector_move_update(struct imsic_local_priv *lpriv, struct imsi
+ /* Update enable and move details */
+ enabled = READ_ONCE(vec->enable);
+ WRITE_ONCE(vec->enable, new_enable);
+- WRITE_ONCE(vec->move, new_move);
++ if (is_old_vec)
++ WRITE_ONCE(vec->move_next, move_vec);
++ else
++ WRITE_ONCE(vec->move_prev, move_vec);
+
+ /* Mark the vector as dirty and synchronize */
+ bitmap_set(lpriv->dirty_bitmap, vec->local_id, 1);
+@@ -322,8 +359,8 @@ void imsic_vector_move(struct imsic_vector *old_vec, struct imsic_vector *new_ve
+ * interrupt on the old vector while device was being moved
+ * to the new vector.
+ */
+- enabled = imsic_vector_move_update(old_lpriv, old_vec, false, new_vec);
+- imsic_vector_move_update(new_lpriv, new_vec, enabled, new_vec);
++ enabled = imsic_vector_move_update(old_lpriv, old_vec, true, false, new_vec);
++ imsic_vector_move_update(new_lpriv, new_vec, false, enabled, old_vec);
+ }
+
+ #ifdef CONFIG_GENERIC_IRQ_DEBUGFS
+@@ -386,7 +423,8 @@ struct imsic_vector *imsic_vector_alloc(unsigned int hwirq, const struct cpumask
+ vec = &lpriv->vectors[local_id];
+ vec->hwirq = hwirq;
+ vec->enable = false;
+- vec->move = NULL;
++ vec->move_next = NULL;
++ vec->move_prev = NULL;
+
+ return vec;
+ }
+diff --git a/drivers/irqchip/irq-riscv-imsic-state.h b/drivers/irqchip/irq-riscv-imsic-state.h
+index 391e442808275..f02842b84ed58 100644
+--- a/drivers/irqchip/irq-riscv-imsic-state.h
++++ b/drivers/irqchip/irq-riscv-imsic-state.h
+@@ -23,7 +23,8 @@ struct imsic_vector {
+ unsigned int hwirq;
+ /* Details accessed using local lock held */
+ bool enable;
+- struct imsic_vector *move;
++ struct imsic_vector *move_next;
++ struct imsic_vector *move_prev;
+ };
+
+ struct imsic_local_priv {
+@@ -74,7 +75,7 @@ static inline void __imsic_id_clear_enable(unsigned long id)
+ __imsic_eix_update(id, 1, false, false);
+ }
+
+-void imsic_local_sync_all(void);
++void imsic_local_sync_all(bool force_all);
+ void imsic_local_delivery(bool enable);
+
+ void imsic_vector_mask(struct imsic_vector *vec);
+@@ -87,7 +88,7 @@ static inline bool imsic_vector_isenabled(struct imsic_vector *vec)
+
+ static inline struct imsic_vector *imsic_vector_get_move(struct imsic_vector *vec)
+ {
+- return READ_ONCE(vec->move);
++ return READ_ONCE(vec->move_prev);
+ }
+
+ void imsic_vector_move(struct imsic_vector *old_vec, struct imsic_vector *new_vec);
+--
+2.39.5
+
--- /dev/null
+From dde029165a50ddad5ef1c1bfec3c9482376c5534 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 14:26:47 +0530
+Subject: irqchip/riscv-imsic: Set irq_set_affinity() for IMSIC base
+
+From: Andrew Jones <ajones@ventanamicro.com>
+
+[ Upstream commit 999f458c1771354371ba367dd84f55f9a62a4233 ]
+
+The IMSIC driver assigns the IMSIC domain specific imsic_irq_set_affinity()
+callback to the per device leaf MSI domain. That's a layering violation as
+it is called with the leaf domain data and not with the IMSIC domain
+data. This prevents moving the IMSIC driver to the common MSI library which
+uses the generic msi_domain_set_affinity() callback for device MSI domains.
+
+Instead of using imsic_irq_set_affinity() for leaf MSI domains, use
+imsic_irq_set_affinity() for the non-leaf IMSIC base domain and use
+irq_chip_set_affinity_parent() for leaf MSI domains.
+
+[ tglx: Massaged change log ]
+
+Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
+Signed-off-by: Anup Patel <apatel@ventanamicro.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/all/20250217085657.789309-2-apatel@ventanamicro.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/irqchip/irq-riscv-imsic-platform.c | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/irqchip/irq-riscv-imsic-platform.c b/drivers/irqchip/irq-riscv-imsic-platform.c
+index c708780e8760f..5d7c30ad8855b 100644
+--- a/drivers/irqchip/irq-riscv-imsic-platform.c
++++ b/drivers/irqchip/irq-riscv-imsic-platform.c
+@@ -96,9 +96,8 @@ static int imsic_irq_set_affinity(struct irq_data *d, const struct cpumask *mask
+ bool force)
+ {
+ struct imsic_vector *old_vec, *new_vec;
+- struct irq_data *pd = d->parent_data;
+
+- old_vec = irq_data_get_irq_chip_data(pd);
++ old_vec = irq_data_get_irq_chip_data(d);
+ if (WARN_ON(!old_vec))
+ return -ENOENT;
+
+@@ -116,13 +115,13 @@ static int imsic_irq_set_affinity(struct irq_data *d, const struct cpumask *mask
+ return -ENOSPC;
+
+ /* Point device to the new vector */
+- imsic_msi_update_msg(d, new_vec);
++ imsic_msi_update_msg(irq_get_irq_data(d->irq), new_vec);
+
+ /* Update irq descriptors with the new vector */
+- pd->chip_data = new_vec;
++ d->chip_data = new_vec;
+
+- /* Update effective affinity of parent irq data */
+- irq_data_update_effective_affinity(pd, cpumask_of(new_vec->cpu));
++ /* Update effective affinity */
++ irq_data_update_effective_affinity(d, cpumask_of(new_vec->cpu));
+
+ /* Move state of the old vector to the new vector */
+ imsic_vector_move(old_vec, new_vec);
+@@ -135,6 +134,9 @@ static struct irq_chip imsic_irq_base_chip = {
+ .name = "IMSIC",
+ .irq_mask = imsic_irq_mask,
+ .irq_unmask = imsic_irq_unmask,
++#ifdef CONFIG_SMP
++ .irq_set_affinity = imsic_irq_set_affinity,
++#endif
+ .irq_retrigger = imsic_irq_retrigger,
+ .irq_compose_msi_msg = imsic_irq_compose_msg,
+ .flags = IRQCHIP_SKIP_SET_WAKE |
+@@ -245,7 +247,7 @@ static bool imsic_init_dev_msi_info(struct device *dev,
+ if (WARN_ON_ONCE(domain != real_parent))
+ return false;
+ #ifdef CONFIG_SMP
+- info->chip->irq_set_affinity = imsic_irq_set_affinity;
++ info->chip->irq_set_affinity = irq_chip_set_affinity_parent;
+ #endif
+ break;
+ default:
+--
+2.39.5
+
--- /dev/null
+From b7176936f7aef8dbc4a8fbd424af2624ccbcdb9d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Feb 2025 10:46:59 +0100
+Subject: jbd2: do not try to recover wiped journal
+
+From: Jan Kara <jack@suse.cz>
+
+[ Upstream commit a662f3c03b754e1f97a2781fa242e95bdb139798 ]
+
+If a journal is wiped, we will set journal->j_tail to 0. However if
+'write' argument is not set (as it happens for read-only device or for
+ocfs2), the on-disk superblock is not updated accordingly and thus
+jbd2_journal_recover() cat try to recover the wiped journal. Fix the
+check in jbd2_journal_recover() to use journal->j_tail for checking
+empty journal instead.
+
+Signed-off-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
+Link: https://patch.msgid.link/20250206094657.20865-4-jack@suse.cz
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jbd2/recovery.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
+index 667f67342c522..f85f401526c54 100644
+--- a/fs/jbd2/recovery.c
++++ b/fs/jbd2/recovery.c
+@@ -287,19 +287,20 @@ static int fc_do_one_pass(journal_t *journal,
+ int jbd2_journal_recover(journal_t *journal)
+ {
+ int err, err2;
+- journal_superblock_t * sb;
+-
+ struct recovery_info info;
+
+ memset(&info, 0, sizeof(info));
+- sb = journal->j_superblock;
+
+ /*
+ * The journal superblock's s_start field (the current log head)
+ * is always zero if, and only if, the journal was cleanly
+- * unmounted.
++ * unmounted. We use its in-memory version j_tail here because
++ * jbd2_journal_wipe() could have updated it without updating journal
++ * superblock.
+ */
+- if (!sb->s_start) {
++ if (!journal->j_tail) {
++ journal_superblock_t *sb = journal->j_superblock;
++
+ jbd2_debug(1, "No recovery required, last transaction %d, head block %u\n",
+ be32_to_cpu(sb->s_sequence), be32_to_cpu(sb->s_head));
+ journal->j_transaction_sequence = be32_to_cpu(sb->s_sequence) + 1;
+--
+2.39.5
+
--- /dev/null
+From 25631aaa96f36bd745fd3d639eec91ed5ffea5e7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Mar 2025 17:21:37 -0500
+Subject: kbuild: fix argument parsing in scripts/config
+
+From: Seyediman Seyedarab <imandevel@gmail.com>
+
+[ Upstream commit f757f6011c92b5a01db742c39149bed9e526478f ]
+
+The script previously assumed --file was always the first argument,
+which caused issues when it appeared later. This patch updates the
+parsing logic to scan all arguments to find --file, sets the config
+file correctly, and resets the argument list with the remaining
+commands.
+
+It also fixes --refresh to respect --file by passing KCONFIG_CONFIG=$FN
+to make oldconfig.
+
+Signed-off-by: Seyediman Seyedarab <imandevel@gmail.com>
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ scripts/config | 26 ++++++++++++++++----------
+ 1 file changed, 16 insertions(+), 10 deletions(-)
+
+diff --git a/scripts/config b/scripts/config
+index ff88e2faefd35..ea475c07de283 100755
+--- a/scripts/config
++++ b/scripts/config
+@@ -32,6 +32,7 @@ commands:
+ Disable option directly after other option
+ --module-after|-M beforeopt option
+ Turn option into module directly after other option
++ --refresh Refresh the config using old settings
+
+ commands can be repeated multiple times
+
+@@ -124,16 +125,22 @@ undef_var() {
+ txt_delete "^# $name is not set" "$FN"
+ }
+
+-if [ "$1" = "--file" ]; then
+- FN="$2"
+- if [ "$FN" = "" ] ; then
+- usage
++FN=.config
++CMDS=()
++while [[ $# -gt 0 ]]; do
++ if [ "$1" = "--file" ]; then
++ if [ "$2" = "" ]; then
++ usage
++ fi
++ FN="$2"
++ shift 2
++ else
++ CMDS+=("$1")
++ shift
+ fi
+- shift 2
+-else
+- FN=.config
+-fi
++done
+
++set -- "${CMDS[@]}"
+ if [ "$1" = "" ] ; then
+ usage
+ fi
+@@ -217,9 +224,8 @@ while [ "$1" != "" ] ; do
+ set_var "${CONFIG_}$B" "${CONFIG_}$B=m" "${CONFIG_}$A"
+ ;;
+
+- # undocumented because it ignores --file (fixme)
+ --refresh)
+- yes "" | make oldconfig
++ yes "" | make oldconfig KCONFIG_CONFIG=$FN
+ ;;
+
+ *)
+--
+2.39.5
+
--- /dev/null
+From a8fc1a1142c59f43b58ab3e6f411924ce68af4b8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Feb 2025 03:41:55 +0900
+Subject: kconfig: do not clear SYMBOL_VALID when reading
+ include/config/auto.conf
+
+From: Masahiro Yamada <masahiroy@kernel.org>
+
+[ Upstream commit 226ac19c217f24f0927d0a73cf9ee613971a188d ]
+
+When conf_read_simple() is called with S_DEF_AUTO, it is meant to read
+previous symbol values from include/config/auto.conf to determine which
+include/config/* files should be touched.
+
+This process should not modify the current symbol status in any way.
+However, conf_touch_deps() currently invalidates all symbol values and
+recalculates them, which is totally unneeded.
+
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ scripts/kconfig/confdata.c | 19 ++++++++++++-------
+ 1 file changed, 12 insertions(+), 7 deletions(-)
+
+diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
+index 3b55e7a4131d9..ac95661a1c9dd 100644
+--- a/scripts/kconfig/confdata.c
++++ b/scripts/kconfig/confdata.c
+@@ -385,7 +385,7 @@ int conf_read_simple(const char *name, int def)
+
+ def_flags = SYMBOL_DEF << def;
+ for_all_symbols(sym) {
+- sym->flags &= ~(def_flags|SYMBOL_VALID);
++ sym->flags &= ~def_flags;
+ switch (sym->type) {
+ case S_INT:
+ case S_HEX:
+@@ -398,7 +398,11 @@ int conf_read_simple(const char *name, int def)
+ }
+ }
+
+- expr_invalidate_all();
++ if (def == S_DEF_USER) {
++ for_all_symbols(sym)
++ sym->flags &= ~SYMBOL_VALID;
++ expr_invalidate_all();
++ }
+
+ while (getline_stripped(&line, &line_asize, in) != -1) {
+ struct menu *choice;
+@@ -464,6 +468,9 @@ int conf_read_simple(const char *name, int def)
+ if (conf_set_sym_val(sym, def, def_flags, val))
+ continue;
+
++ if (def != S_DEF_USER)
++ continue;
++
+ /*
+ * If this is a choice member, give it the highest priority.
+ * If conflicting CONFIG options are given from an input file,
+@@ -967,10 +974,8 @@ static int conf_touch_deps(void)
+ depfile_path[depfile_prefix_len] = 0;
+
+ conf_read_simple(name, S_DEF_AUTO);
+- sym_calc_value(modules_sym);
+
+ for_all_symbols(sym) {
+- sym_calc_value(sym);
+ if (sym_is_choice(sym))
+ continue;
+ if (sym->flags & SYMBOL_WRITE) {
+@@ -1084,12 +1089,12 @@ int conf_write_autoconf(int overwrite)
+ if (ret)
+ return -1;
+
+- if (conf_touch_deps())
+- return 1;
+-
+ for_all_symbols(sym)
+ sym_calc_value(sym);
+
++ if (conf_touch_deps())
++ return 1;
++
+ ret = __conf_write_autoconf(conf_get_autoheader_name(),
+ print_symbol_for_c,
+ &comment_style_c);
+--
+2.39.5
+
--- /dev/null
+From 341195dbe36798d3b5b86782e37251806b23f516 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Mar 2025 14:28:37 +0000
+Subject: kconfig: merge_config: use an empty file as initfile
+
+From: Daniel Gomez <da.gomez@samsung.com>
+
+[ Upstream commit a26fe287eed112b4e21e854f173c8918a6a8596d ]
+
+The scripts/kconfig/merge_config.sh script requires an existing
+$INITFILE (or the $1 argument) as a base file for merging Kconfig
+fragments. However, an empty $INITFILE can serve as an initial starting
+point, later referenced by the KCONFIG_ALLCONFIG Makefile variable
+if -m is not used. This variable can point to any configuration file
+containing preset config symbols (the merged output) as stated in
+Documentation/kbuild/kconfig.rst. When -m is used $INITFILE will
+contain just the merge output requiring the user to run make (i.e.
+KCONFIG_ALLCONFIG=<$INITFILE> make <allnoconfig/alldefconfig> or make
+olddefconfig).
+
+Instead of failing when `$INITFILE` is missing, create an empty file and
+use it as the starting point for merges.
+
+Signed-off-by: Daniel Gomez <da.gomez@samsung.com>
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ scripts/kconfig/merge_config.sh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh
+index 0b7952471c18f..79c09b378be81 100755
+--- a/scripts/kconfig/merge_config.sh
++++ b/scripts/kconfig/merge_config.sh
+@@ -112,8 +112,8 @@ INITFILE=$1
+ shift;
+
+ if [ ! -r "$INITFILE" ]; then
+- echo "The base file '$INITFILE' does not exist. Exit." >&2
+- exit 1
++ echo "The base file '$INITFILE' does not exist. Creating one..." >&2
++ touch "$INITFILE"
+ fi
+
+ MERGE_LIST=$*
+--
+2.39.5
+
--- /dev/null
+From 47f4808a74c1abb8ff4a358d4a3fa28e5aec9039 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 15:50:19 +0100
+Subject: kernfs: Acquire kernfs_rwsem in kernfs_get_parent_dentry().
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+[ Upstream commit 122ab92dee80582c39740609a627198dd5b6b595 ]
+
+kernfs_get_parent_dentry() passes kernfs_node::parent to
+kernfs_get_inode().
+
+Acquire kernfs_root::kernfs_rwsem to ensure kernfs_node::parent isn't
+replaced during the operation.
+
+Acked-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20250213145023.2820193-3-bigeasy@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/kernfs/mount.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
+index 0f6379ae258d1..4a0ff08d589ca 100644
+--- a/fs/kernfs/mount.c
++++ b/fs/kernfs/mount.c
+@@ -145,7 +145,9 @@ static struct dentry *kernfs_fh_to_parent(struct super_block *sb,
+ static struct dentry *kernfs_get_parent_dentry(struct dentry *child)
+ {
+ struct kernfs_node *kn = kernfs_dentry_node(child);
++ struct kernfs_root *root = kernfs_root(kn);
+
++ guard(rwsem_read)(&root->kernfs_rwsem);
+ return d_obtain_alias(kernfs_get_inode(child->d_sb, kn->parent));
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 9bb7d9f7370173a25f5494ebd70085a8a54e33bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 15:50:20 +0100
+Subject: kernfs: Acquire kernfs_rwsem in kernfs_node_dentry().
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+[ Upstream commit 5b2fabf7fe8f745ff214ff003e6067b64f172271 ]
+
+kernfs_node_dentry() passes kernfs_node::name to
+lookup_positive_unlocked().
+
+Acquire kernfs_root::kernfs_rwsem to ensure the node is not renamed
+during the operation.
+
+Acked-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20250213145023.2820193-4-bigeasy@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/kernfs/mount.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
+index 1358c21837f1a..0f6379ae258d1 100644
+--- a/fs/kernfs/mount.c
++++ b/fs/kernfs/mount.c
+@@ -207,6 +207,7 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn,
+ {
+ struct dentry *dentry;
+ struct kernfs_node *knparent;
++ struct kernfs_root *root;
+
+ BUG_ON(sb->s_op != &kernfs_sops);
+
+@@ -216,6 +217,9 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn,
+ if (!kn->parent)
+ return dentry;
+
++ root = kernfs_root(kn);
++ guard(rwsem_read)(&root->kernfs_rwsem);
++
+ knparent = find_next_ancestor(kn, NULL);
+ if (WARN_ON(!knparent)) {
+ dput(dentry);
+--
+2.39.5
+
--- /dev/null
+From 079fbf2ff1f0e3107a47874c3cb8ee013bf89409 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 15:50:18 +0100
+Subject: kernfs: Acquire kernfs_rwsem in kernfs_notify_workfn().
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+[ Upstream commit 400188ae361a9d9a72a47a6cedaf2d2efcc84aa8 ]
+
+kernfs_notify_workfn() dereferences kernfs_node::name and passes it
+later to fsnotify(). If the node is renamed then the previously observed
+name pointer becomes invalid.
+
+Acquire kernfs_root::kernfs_rwsem to block renames of the node.
+
+Acked-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20250213145023.2820193-2-bigeasy@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/kernfs/file.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
+index 8502ef68459b9..165d8e37976ba 100644
+--- a/fs/kernfs/file.c
++++ b/fs/kernfs/file.c
+@@ -911,6 +911,7 @@ static void kernfs_notify_workfn(struct work_struct *work)
+ /* kick fsnotify */
+
+ down_read(&root->kernfs_supers_rwsem);
++ down_read(&root->kernfs_rwsem);
+ list_for_each_entry(info, &kernfs_root(kn)->supers, node) {
+ struct kernfs_node *parent;
+ struct inode *p_inode = NULL;
+@@ -947,6 +948,7 @@ static void kernfs_notify_workfn(struct work_struct *work)
+ iput(inode);
+ }
+
++ up_read(&root->kernfs_rwsem);
+ up_read(&root->kernfs_supers_rwsem);
+ kernfs_put(kn);
+ goto repeat;
+--
+2.39.5
+
--- /dev/null
+From 6247ef751c277b43adbe8b0e75696f1e59cf2921 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 15:50:21 +0100
+Subject: kernfs: Don't re-lock kernfs_root::kernfs_rwsem in
+ kernfs_fop_readdir().
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+[ Upstream commit 9aab10a0249eab4ec77c6a5e4f66442610c12a09 ]
+
+The readdir operation iterates over all entries and invokes dir_emit()
+for every entry passing kernfs_node::name as argument.
+Since the name argument can change, and become invalid, the
+kernfs_root::kernfs_rwsem lock should not be dropped to prevent renames
+during the operation.
+
+The lock drop around dir_emit() has been initially introduced in commit
+ 1e5289c97bba2 ("sysfs: Cache the last sysfs_dirent to improve readdir scalability v2")
+
+to avoid holding a global lock during a page fault. The lock drop is
+wrong since the support of renames and not a big burden since the lock
+is no longer global.
+
+Don't re-acquire kernfs_root::kernfs_rwsem while copying the name to the
+userpace buffer.
+
+Acked-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20250213145023.2820193-5-bigeasy@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/kernfs/dir.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
+index 458519e416fe7..5a1fea414996e 100644
+--- a/fs/kernfs/dir.c
++++ b/fs/kernfs/dir.c
+@@ -1868,10 +1868,10 @@ static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx)
+ file->private_data = pos;
+ kernfs_get(pos);
+
+- up_read(&root->kernfs_rwsem);
+- if (!dir_emit(ctx, name, len, ino, type))
++ if (!dir_emit(ctx, name, len, ino, type)) {
++ up_read(&root->kernfs_rwsem);
+ return 0;
+- down_read(&root->kernfs_rwsem);
++ }
+ }
+ up_read(&root->kernfs_rwsem);
+ file->private_data = NULL;
+--
+2.39.5
+
--- /dev/null
+From 10d6731fc902f64ab2457c34c7d2cd1503e9cc34 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 15:50:22 +0100
+Subject: kernfs: Use RCU to access kernfs_node::parent.
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+[ Upstream commit 633488947ef66b194377411322dc9e12aab79b65 ]
+
+kernfs_rename_lock is used to obtain stable kernfs_node::{name|parent}
+pointer. This is a preparation to access kernfs_node::parent under RCU
+and ensure that the pointer remains stable under the RCU lifetime
+guarantees.
+
+For a complete path, as it is done in kernfs_path_from_node(), the
+kernfs_rename_lock is still required in order to obtain a stable parent
+relationship while computing the relevant node depth. This must not
+change while the nodes are inspected in order to build the path.
+If the kernfs user never moves the nodes (changes the parent) then the
+kernfs_rename_lock is not required and the RCU guarantees are
+sufficient. This "restriction" can be set with
+KERNFS_ROOT_INVARIANT_PARENT. Otherwise the lock is required.
+
+Rename kernfs_node::parent to kernfs_node::__parent to denote the RCU
+access and use RCU accessor while accessing the node.
+Make cgroup use KERNFS_ROOT_INVARIANT_PARENT since the parent here can
+not change.
+
+Acked-by: Tejun Heo <tj@kernel.org>
+Cc: Yonghong Song <yonghong.song@linux.dev>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20250213145023.2820193-6-bigeasy@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/cpu/resctrl/rdtgroup.c | 65 +++++++++----
+ fs/kernfs/dir.c | 96 ++++++++++++-------
+ fs/kernfs/kernfs-internal.h | 32 ++++++-
+ fs/kernfs/mount.c | 10 +-
+ fs/kernfs/symlink.c | 23 ++---
+ fs/sysfs/file.c | 24 +++--
+ include/linux/kernfs.h | 10 +-
+ kernel/cgroup/cgroup-v1.c | 2 +-
+ kernel/cgroup/cgroup.c | 24 ++++-
+ .../selftests/bpf/progs/profiler.inc.h | 2 +-
+ 10 files changed, 195 insertions(+), 93 deletions(-)
+
+diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+index 2d48db66fca85..d4d7ccf1253b8 100644
+--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c
++++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+@@ -948,10 +948,20 @@ static int rdt_last_cmd_status_show(struct kernfs_open_file *of,
+ return 0;
+ }
+
++static void *rdt_kn_parent_priv(struct kernfs_node *kn)
++{
++ /*
++ * The parent pointer is only valid within RCU section since it can be
++ * replaced.
++ */
++ guard(rcu)();
++ return rcu_dereference(kn->__parent)->priv;
++}
++
+ static int rdt_num_closids_show(struct kernfs_open_file *of,
+ struct seq_file *seq, void *v)
+ {
+- struct resctrl_schema *s = of->kn->parent->priv;
++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
+
+ seq_printf(seq, "%u\n", s->num_closid);
+ return 0;
+@@ -960,7 +970,7 @@ static int rdt_num_closids_show(struct kernfs_open_file *of,
+ static int rdt_default_ctrl_show(struct kernfs_open_file *of,
+ struct seq_file *seq, void *v)
+ {
+- struct resctrl_schema *s = of->kn->parent->priv;
++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
+ struct rdt_resource *r = s->res;
+
+ seq_printf(seq, "%x\n", r->default_ctrl);
+@@ -970,7 +980,7 @@ static int rdt_default_ctrl_show(struct kernfs_open_file *of,
+ static int rdt_min_cbm_bits_show(struct kernfs_open_file *of,
+ struct seq_file *seq, void *v)
+ {
+- struct resctrl_schema *s = of->kn->parent->priv;
++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
+ struct rdt_resource *r = s->res;
+
+ seq_printf(seq, "%u\n", r->cache.min_cbm_bits);
+@@ -980,7 +990,7 @@ static int rdt_min_cbm_bits_show(struct kernfs_open_file *of,
+ static int rdt_shareable_bits_show(struct kernfs_open_file *of,
+ struct seq_file *seq, void *v)
+ {
+- struct resctrl_schema *s = of->kn->parent->priv;
++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
+ struct rdt_resource *r = s->res;
+
+ seq_printf(seq, "%x\n", r->cache.shareable_bits);
+@@ -1004,7 +1014,7 @@ static int rdt_shareable_bits_show(struct kernfs_open_file *of,
+ static int rdt_bit_usage_show(struct kernfs_open_file *of,
+ struct seq_file *seq, void *v)
+ {
+- struct resctrl_schema *s = of->kn->parent->priv;
++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
+ /*
+ * Use unsigned long even though only 32 bits are used to ensure
+ * test_bit() is used safely.
+@@ -1086,7 +1096,7 @@ static int rdt_bit_usage_show(struct kernfs_open_file *of,
+ static int rdt_min_bw_show(struct kernfs_open_file *of,
+ struct seq_file *seq, void *v)
+ {
+- struct resctrl_schema *s = of->kn->parent->priv;
++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
+ struct rdt_resource *r = s->res;
+
+ seq_printf(seq, "%u\n", r->membw.min_bw);
+@@ -1096,7 +1106,7 @@ static int rdt_min_bw_show(struct kernfs_open_file *of,
+ static int rdt_num_rmids_show(struct kernfs_open_file *of,
+ struct seq_file *seq, void *v)
+ {
+- struct rdt_resource *r = of->kn->parent->priv;
++ struct rdt_resource *r = rdt_kn_parent_priv(of->kn);
+
+ seq_printf(seq, "%d\n", r->num_rmid);
+
+@@ -1106,7 +1116,7 @@ static int rdt_num_rmids_show(struct kernfs_open_file *of,
+ static int rdt_mon_features_show(struct kernfs_open_file *of,
+ struct seq_file *seq, void *v)
+ {
+- struct rdt_resource *r = of->kn->parent->priv;
++ struct rdt_resource *r = rdt_kn_parent_priv(of->kn);
+ struct mon_evt *mevt;
+
+ list_for_each_entry(mevt, &r->evt_list, list) {
+@@ -1121,7 +1131,7 @@ static int rdt_mon_features_show(struct kernfs_open_file *of,
+ static int rdt_bw_gran_show(struct kernfs_open_file *of,
+ struct seq_file *seq, void *v)
+ {
+- struct resctrl_schema *s = of->kn->parent->priv;
++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
+ struct rdt_resource *r = s->res;
+
+ seq_printf(seq, "%u\n", r->membw.bw_gran);
+@@ -1131,7 +1141,7 @@ static int rdt_bw_gran_show(struct kernfs_open_file *of,
+ static int rdt_delay_linear_show(struct kernfs_open_file *of,
+ struct seq_file *seq, void *v)
+ {
+- struct resctrl_schema *s = of->kn->parent->priv;
++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
+ struct rdt_resource *r = s->res;
+
+ seq_printf(seq, "%u\n", r->membw.delay_linear);
+@@ -1149,7 +1159,7 @@ static int max_threshold_occ_show(struct kernfs_open_file *of,
+ static int rdt_thread_throttle_mode_show(struct kernfs_open_file *of,
+ struct seq_file *seq, void *v)
+ {
+- struct resctrl_schema *s = of->kn->parent->priv;
++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
+ struct rdt_resource *r = s->res;
+
+ if (r->membw.throttle_mode == THREAD_THROTTLE_PER_THREAD)
+@@ -1214,7 +1224,7 @@ static enum resctrl_conf_type resctrl_peer_type(enum resctrl_conf_type my_type)
+ static int rdt_has_sparse_bitmasks_show(struct kernfs_open_file *of,
+ struct seq_file *seq, void *v)
+ {
+- struct resctrl_schema *s = of->kn->parent->priv;
++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
+ struct rdt_resource *r = s->res;
+
+ seq_printf(seq, "%u\n", r->cache.arch_has_sparse_bitmasks);
+@@ -1626,7 +1636,7 @@ static int mbm_config_show(struct seq_file *s, struct rdt_resource *r, u32 evtid
+ static int mbm_total_bytes_config_show(struct kernfs_open_file *of,
+ struct seq_file *seq, void *v)
+ {
+- struct rdt_resource *r = of->kn->parent->priv;
++ struct rdt_resource *r = rdt_kn_parent_priv(of->kn);
+
+ mbm_config_show(seq, r, QOS_L3_MBM_TOTAL_EVENT_ID);
+
+@@ -1636,7 +1646,7 @@ static int mbm_total_bytes_config_show(struct kernfs_open_file *of,
+ static int mbm_local_bytes_config_show(struct kernfs_open_file *of,
+ struct seq_file *seq, void *v)
+ {
+- struct rdt_resource *r = of->kn->parent->priv;
++ struct rdt_resource *r = rdt_kn_parent_priv(of->kn);
+
+ mbm_config_show(seq, r, QOS_L3_MBM_LOCAL_EVENT_ID);
+
+@@ -1742,7 +1752,7 @@ static ssize_t mbm_total_bytes_config_write(struct kernfs_open_file *of,
+ char *buf, size_t nbytes,
+ loff_t off)
+ {
+- struct rdt_resource *r = of->kn->parent->priv;
++ struct rdt_resource *r = rdt_kn_parent_priv(of->kn);
+ int ret;
+
+ /* Valid input requires a trailing newline */
+@@ -1768,7 +1778,7 @@ static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of,
+ char *buf, size_t nbytes,
+ loff_t off)
+ {
+- struct rdt_resource *r = of->kn->parent->priv;
++ struct rdt_resource *r = rdt_kn_parent_priv(of->kn);
+ int ret;
+
+ /* Valid input requires a trailing newline */
+@@ -2430,12 +2440,13 @@ static struct rdtgroup *kernfs_to_rdtgroup(struct kernfs_node *kn)
+ * resource. "info" and its subdirectories don't
+ * have rdtgroup structures, so return NULL here.
+ */
+- if (kn == kn_info || kn->parent == kn_info)
++ if (kn == kn_info ||
++ rcu_access_pointer(kn->__parent) == kn_info)
+ return NULL;
+ else
+ return kn->priv;
+ } else {
+- return kn->parent->priv;
++ return rdt_kn_parent_priv(kn);
+ }
+ }
+
+@@ -3759,9 +3770,18 @@ static int rdtgroup_rmdir_ctrl(struct rdtgroup *rdtgrp, cpumask_var_t tmpmask)
+ return 0;
+ }
+
++static struct kernfs_node *rdt_kn_parent(struct kernfs_node *kn)
++{
++ /*
++ * Valid within the RCU section it was obtained or while rdtgroup_mutex
++ * is held.
++ */
++ return rcu_dereference_check(kn->__parent, lockdep_is_held(&rdtgroup_mutex));
++}
++
+ static int rdtgroup_rmdir(struct kernfs_node *kn)
+ {
+- struct kernfs_node *parent_kn = kn->parent;
++ struct kernfs_node *parent_kn;
+ struct rdtgroup *rdtgrp;
+ cpumask_var_t tmpmask;
+ int ret = 0;
+@@ -3774,6 +3794,7 @@ static int rdtgroup_rmdir(struct kernfs_node *kn)
+ ret = -EPERM;
+ goto out;
+ }
++ parent_kn = rdt_kn_parent(kn);
+
+ /*
+ * If the rdtgroup is a ctrl_mon group and parent directory
+@@ -3842,6 +3863,7 @@ static void mongrp_reparent(struct rdtgroup *rdtgrp,
+ static int rdtgroup_rename(struct kernfs_node *kn,
+ struct kernfs_node *new_parent, const char *new_name)
+ {
++ struct kernfs_node *kn_parent;
+ struct rdtgroup *new_prdtgrp;
+ struct rdtgroup *rdtgrp;
+ cpumask_var_t tmpmask;
+@@ -3876,8 +3898,9 @@ static int rdtgroup_rename(struct kernfs_node *kn,
+ goto out;
+ }
+
+- if (rdtgrp->type != RDTMON_GROUP || !kn->parent ||
+- !is_mon_groups(kn->parent, kn->name)) {
++ kn_parent = rdt_kn_parent(kn);
++ if (rdtgrp->type != RDTMON_GROUP || !kn_parent ||
++ !is_mon_groups(kn_parent, kn->name)) {
+ rdt_last_cmd_puts("Source must be a MON group\n");
+ ret = -EPERM;
+ goto out;
+diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
+index 5a1fea414996e..d2306641b569c 100644
+--- a/fs/kernfs/dir.c
++++ b/fs/kernfs/dir.c
+@@ -17,7 +17,7 @@
+
+ #include "kernfs-internal.h"
+
+-static DEFINE_RWLOCK(kernfs_rename_lock); /* kn->parent and ->name */
++DEFINE_RWLOCK(kernfs_rename_lock); /* kn->parent and ->name */
+ /*
+ * Don't use rename_lock to piggy back on pr_cont_buf. We don't want to
+ * call pr_cont() while holding rename_lock. Because sometimes pr_cont()
+@@ -56,7 +56,7 @@ static int kernfs_name_locked(struct kernfs_node *kn, char *buf, size_t buflen)
+ if (!kn)
+ return strscpy(buf, "(null)", buflen);
+
+- return strscpy(buf, kn->parent ? kn->name : "/", buflen);
++ return strscpy(buf, rcu_access_pointer(kn->__parent) ? kn->name : "/", buflen);
+ }
+
+ /* kernfs_node_depth - compute depth from @from to @to */
+@@ -64,9 +64,9 @@ static size_t kernfs_depth(struct kernfs_node *from, struct kernfs_node *to)
+ {
+ size_t depth = 0;
+
+- while (to->parent && to != from) {
++ while (rcu_dereference(to->__parent) && to != from) {
+ depth++;
+- to = to->parent;
++ to = rcu_dereference(to->__parent);
+ }
+ return depth;
+ }
+@@ -84,18 +84,18 @@ static struct kernfs_node *kernfs_common_ancestor(struct kernfs_node *a,
+ db = kernfs_depth(rb->kn, b);
+
+ while (da > db) {
+- a = a->parent;
++ a = rcu_dereference(a->__parent);
+ da--;
+ }
+ while (db > da) {
+- b = b->parent;
++ b = rcu_dereference(b->__parent);
+ db--;
+ }
+
+ /* worst case b and a will be the same at root */
+ while (b != a) {
+- b = b->parent;
+- a = a->parent;
++ b = rcu_dereference(b->__parent);
++ a = rcu_dereference(a->__parent);
+ }
+
+ return a;
+@@ -168,8 +168,9 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
+
+ /* Calculate how many bytes we need for the rest */
+ for (i = depth_to - 1; i >= 0; i--) {
++
+ for (kn = kn_to, j = 0; j < i; j++)
+- kn = kn->parent;
++ kn = rcu_dereference(kn->__parent);
+
+ len += scnprintf(buf + len, buflen - len, "/%s", kn->name);
+ }
+@@ -226,6 +227,7 @@ int kernfs_path_from_node(struct kernfs_node *to, struct kernfs_node *from,
+ unsigned long flags;
+ int ret;
+
++ guard(rcu)();
+ read_lock_irqsave(&kernfs_rename_lock, flags);
+ ret = kernfs_path_from_node_locked(to, from, buf, buflen);
+ read_unlock_irqrestore(&kernfs_rename_lock, flags);
+@@ -295,7 +297,7 @@ struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn)
+ unsigned long flags;
+
+ read_lock_irqsave(&kernfs_rename_lock, flags);
+- parent = kn->parent;
++ parent = kernfs_parent(kn);
+ kernfs_get(parent);
+ read_unlock_irqrestore(&kernfs_rename_lock, flags);
+
+@@ -360,8 +362,12 @@ static int kernfs_sd_compare(const struct kernfs_node *left,
+ */
+ static int kernfs_link_sibling(struct kernfs_node *kn)
+ {
+- struct rb_node **node = &kn->parent->dir.children.rb_node;
+ struct rb_node *parent = NULL;
++ struct kernfs_node *kn_parent;
++ struct rb_node **node;
++
++ kn_parent = kernfs_parent(kn);
++ node = &kn_parent->dir.children.rb_node;
+
+ while (*node) {
+ struct kernfs_node *pos;
+@@ -380,13 +386,13 @@ static int kernfs_link_sibling(struct kernfs_node *kn)
+
+ /* add new node and rebalance the tree */
+ rb_link_node(&kn->rb, parent, node);
+- rb_insert_color(&kn->rb, &kn->parent->dir.children);
++ rb_insert_color(&kn->rb, &kn_parent->dir.children);
+
+ /* successfully added, account subdir number */
+ down_write(&kernfs_root(kn)->kernfs_iattr_rwsem);
+ if (kernfs_type(kn) == KERNFS_DIR)
+- kn->parent->dir.subdirs++;
+- kernfs_inc_rev(kn->parent);
++ kn_parent->dir.subdirs++;
++ kernfs_inc_rev(kn_parent);
+ up_write(&kernfs_root(kn)->kernfs_iattr_rwsem);
+
+ return 0;
+@@ -407,16 +413,19 @@ static int kernfs_link_sibling(struct kernfs_node *kn)
+ */
+ static bool kernfs_unlink_sibling(struct kernfs_node *kn)
+ {
++ struct kernfs_node *kn_parent;
++
+ if (RB_EMPTY_NODE(&kn->rb))
+ return false;
+
++ kn_parent = kernfs_parent(kn);
+ down_write(&kernfs_root(kn)->kernfs_iattr_rwsem);
+ if (kernfs_type(kn) == KERNFS_DIR)
+- kn->parent->dir.subdirs--;
+- kernfs_inc_rev(kn->parent);
++ kn_parent->dir.subdirs--;
++ kernfs_inc_rev(kn_parent);
+ up_write(&kernfs_root(kn)->kernfs_iattr_rwsem);
+
+- rb_erase(&kn->rb, &kn->parent->dir.children);
++ rb_erase(&kn->rb, &kn_parent->dir.children);
+ RB_CLEAR_NODE(&kn->rb);
+ return true;
+ }
+@@ -562,7 +571,7 @@ void kernfs_put(struct kernfs_node *kn)
+ * Moving/renaming is always done while holding reference.
+ * kn->parent won't change beneath us.
+ */
+- parent = kn->parent;
++ parent = kernfs_parent(kn);
+
+ WARN_ONCE(atomic_read(&kn->active) != KN_DEACTIVATED_BIAS,
+ "kernfs_put: %s/%s: released with incorrect active_ref %d\n",
+@@ -701,7 +710,7 @@ struct kernfs_node *kernfs_new_node(struct kernfs_node *parent,
+ name, mode, uid, gid, flags);
+ if (kn) {
+ kernfs_get(parent);
+- kn->parent = parent;
++ rcu_assign_pointer(kn->__parent, parent);
+ }
+ return kn;
+ }
+@@ -769,13 +778,14 @@ struct kernfs_node *kernfs_find_and_get_node_by_id(struct kernfs_root *root,
+ */
+ int kernfs_add_one(struct kernfs_node *kn)
+ {
+- struct kernfs_node *parent = kn->parent;
+- struct kernfs_root *root = kernfs_root(parent);
++ struct kernfs_root *root = kernfs_root(kn);
+ struct kernfs_iattrs *ps_iattr;
++ struct kernfs_node *parent;
+ bool has_ns;
+ int ret;
+
+ down_write(&root->kernfs_rwsem);
++ parent = kernfs_parent(kn);
+
+ ret = -EINVAL;
+ has_ns = kernfs_ns_enabled(parent);
+@@ -949,6 +959,11 @@ struct kernfs_node *kernfs_walk_and_get_ns(struct kernfs_node *parent,
+ return kn;
+ }
+
++unsigned int kernfs_root_flags(struct kernfs_node *kn)
++{
++ return kernfs_root(kn)->flags;
++}
++
+ /**
+ * kernfs_create_root - create a new kernfs hierarchy
+ * @scops: optional syscall operations for the hierarchy
+@@ -1111,7 +1126,7 @@ struct kernfs_node *kernfs_create_empty_dir(struct kernfs_node *parent,
+
+ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
+ {
+- struct kernfs_node *kn;
++ struct kernfs_node *kn, *parent;
+ struct kernfs_root *root;
+
+ if (flags & LOOKUP_RCU)
+@@ -1162,8 +1177,9 @@ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
+ if (!kernfs_active(kn))
+ goto out_bad;
+
++ parent = kernfs_parent(kn);
+ /* The kernfs node has been moved? */
+- if (kernfs_dentry_node(dentry->d_parent) != kn->parent)
++ if (kernfs_dentry_node(dentry->d_parent) != parent)
+ goto out_bad;
+
+ /* The kernfs node has been renamed */
+@@ -1171,7 +1187,7 @@ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
+ goto out_bad;
+
+ /* The kernfs node has been moved to a different namespace */
+- if (kn->parent && kernfs_ns_enabled(kn->parent) &&
++ if (parent && kernfs_ns_enabled(parent) &&
+ kernfs_info(dentry->d_sb)->ns != kn->ns)
+ goto out_bad;
+
+@@ -1364,7 +1380,7 @@ static struct kernfs_node *kernfs_next_descendant_post(struct kernfs_node *pos,
+ return kernfs_leftmost_descendant(rb_to_kn(rbn));
+
+ /* no sibling left, visit parent */
+- return pos->parent;
++ return kernfs_parent(pos);
+ }
+
+ static void kernfs_activate_one(struct kernfs_node *kn)
+@@ -1376,7 +1392,7 @@ static void kernfs_activate_one(struct kernfs_node *kn)
+ if (kernfs_active(kn) || (kn->flags & (KERNFS_HIDDEN | KERNFS_REMOVING)))
+ return;
+
+- WARN_ON_ONCE(kn->parent && RB_EMPTY_NODE(&kn->rb));
++ WARN_ON_ONCE(rcu_access_pointer(kn->__parent) && RB_EMPTY_NODE(&kn->rb));
+ WARN_ON_ONCE(atomic_read(&kn->active) != KN_DEACTIVATED_BIAS);
+
+ atomic_sub(KN_DEACTIVATED_BIAS, &kn->active);
+@@ -1446,7 +1462,7 @@ void kernfs_show(struct kernfs_node *kn, bool show)
+
+ static void __kernfs_remove(struct kernfs_node *kn)
+ {
+- struct kernfs_node *pos;
++ struct kernfs_node *pos, *parent;
+
+ /* Short-circuit if non-root @kn has already finished removal. */
+ if (!kn)
+@@ -1458,7 +1474,7 @@ static void __kernfs_remove(struct kernfs_node *kn)
+ * This is for kernfs_remove_self() which plays with active ref
+ * after removal.
+ */
+- if (kn->parent && RB_EMPTY_NODE(&kn->rb))
++ if (kernfs_parent(kn) && RB_EMPTY_NODE(&kn->rb))
+ return;
+
+ pr_debug("kernfs %s: removing\n", kn->name);
+@@ -1484,14 +1500,14 @@ static void __kernfs_remove(struct kernfs_node *kn)
+ kernfs_get(pos);
+
+ kernfs_drain(pos);
+-
++ parent = kernfs_parent(pos);
+ /*
+ * kernfs_unlink_sibling() succeeds once per node. Use it
+ * to decide who's responsible for cleanups.
+ */
+- if (!pos->parent || kernfs_unlink_sibling(pos)) {
++ if (!parent || kernfs_unlink_sibling(pos)) {
+ struct kernfs_iattrs *ps_iattr =
+- pos->parent ? pos->parent->iattr : NULL;
++ parent ? parent->iattr : NULL;
+
+ /* update timestamps on the parent */
+ down_write(&kernfs_root(kn)->kernfs_iattr_rwsem);
+@@ -1721,7 +1737,7 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
+ int error;
+
+ /* can't move or rename root */
+- if (!kn->parent)
++ if (!rcu_access_pointer(kn->__parent))
+ return -EINVAL;
+
+ root = kernfs_root(kn);
+@@ -1732,8 +1748,15 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
+ (new_parent->flags & KERNFS_EMPTY_DIR))
+ goto out;
+
++ old_parent = kernfs_parent(kn);
++ if (root->flags & KERNFS_ROOT_INVARIANT_PARENT) {
++ error = -EINVAL;
++ if (WARN_ON_ONCE(old_parent != new_parent))
++ goto out;
++ }
++
+ error = 0;
+- if ((kn->parent == new_parent) && (kn->ns == new_ns) &&
++ if ((old_parent == new_parent) && (kn->ns == new_ns) &&
+ (strcmp(kn->name, new_name) == 0))
+ goto out; /* nothing to rename */
+
+@@ -1760,8 +1783,8 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
+ /* rename_lock protects ->parent and ->name accessors */
+ write_lock_irq(&kernfs_rename_lock);
+
+- old_parent = kn->parent;
+- kn->parent = new_parent;
++ old_parent = kernfs_parent(kn);
++ rcu_assign_pointer(kn->__parent, new_parent);
+
+ kn->ns = new_ns;
+ if (new_name) {
+@@ -1794,7 +1817,8 @@ static struct kernfs_node *kernfs_dir_pos(const void *ns,
+ {
+ if (pos) {
+ int valid = kernfs_active(pos) &&
+- pos->parent == parent && hash == pos->hash;
++ rcu_access_pointer(pos->__parent) == parent &&
++ hash == pos->hash;
+ kernfs_put(pos);
+ if (!valid)
+ pos = NULL;
+diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h
+index b42ee6547cdc1..c43bee18b79f7 100644
+--- a/fs/kernfs/kernfs-internal.h
++++ b/fs/kernfs/kernfs-internal.h
+@@ -19,6 +19,8 @@
+ #include <linux/kernfs.h>
+ #include <linux/fs_context.h>
+
++extern rwlock_t kernfs_rename_lock;
++
+ struct kernfs_iattrs {
+ kuid_t ia_uid;
+ kgid_t ia_gid;
+@@ -64,11 +66,14 @@ struct kernfs_root {
+ *
+ * Return: the kernfs_root @kn belongs to.
+ */
+-static inline struct kernfs_root *kernfs_root(struct kernfs_node *kn)
++static inline struct kernfs_root *kernfs_root(const struct kernfs_node *kn)
+ {
++ const struct kernfs_node *knp;
+ /* if parent exists, it's always a dir; otherwise, @sd is a dir */
+- if (kn->parent)
+- kn = kn->parent;
++ guard(rcu)();
++ knp = rcu_dereference(kn->__parent);
++ if (knp)
++ kn = knp;
+ return kn->dir.root;
+ }
+
+@@ -97,6 +102,27 @@ struct kernfs_super_info {
+ };
+ #define kernfs_info(SB) ((struct kernfs_super_info *)(SB->s_fs_info))
+
++static inline bool kernfs_root_is_locked(const struct kernfs_node *kn)
++{
++ return lockdep_is_held(&kernfs_root(kn)->kernfs_rwsem);
++}
++
++static inline struct kernfs_node *kernfs_parent(const struct kernfs_node *kn)
++{
++ /*
++ * The kernfs_node::__parent remains valid within a RCU section. The kn
++ * can be reparented (and renamed) which changes the entry. This can be
++ * avoided by locking kernfs_root::kernfs_rwsem or kernfs_rename_lock.
++ * Both locks can be used to obtain a reference on __parent. Once the
++ * reference count reaches 0 then the node is about to be freed
++ * and can not be renamed (or become a different parent) anymore.
++ */
++ return rcu_dereference_check(kn->__parent,
++ kernfs_root_is_locked(kn) ||
++ lockdep_is_held(&kernfs_rename_lock) ||
++ !atomic_read(&kn->count));
++}
++
+ static inline struct kernfs_node *kernfs_dentry_node(struct dentry *dentry)
+ {
+ if (d_really_is_negative(dentry))
+diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
+index 4a0ff08d589ca..2252b16e6ef0b 100644
+--- a/fs/kernfs/mount.c
++++ b/fs/kernfs/mount.c
+@@ -148,7 +148,7 @@ static struct dentry *kernfs_get_parent_dentry(struct dentry *child)
+ struct kernfs_root *root = kernfs_root(kn);
+
+ guard(rwsem_read)(&root->kernfs_rwsem);
+- return d_obtain_alias(kernfs_get_inode(child->d_sb, kn->parent));
++ return d_obtain_alias(kernfs_get_inode(child->d_sb, kernfs_parent(kn)));
+ }
+
+ static const struct export_operations kernfs_export_ops = {
+@@ -188,10 +188,10 @@ static struct kernfs_node *find_next_ancestor(struct kernfs_node *child,
+ return NULL;
+ }
+
+- while (child->parent != parent) {
+- if (!child->parent)
++ while (kernfs_parent(child) != parent) {
++ child = kernfs_parent(child);
++ if (!child)
+ return NULL;
+- child = child->parent;
+ }
+
+ return child;
+@@ -216,7 +216,7 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn,
+ dentry = dget(sb->s_root);
+
+ /* Check if this is the root kernfs_node */
+- if (!kn->parent)
++ if (!rcu_access_pointer(kn->__parent))
+ return dentry;
+
+ root = kernfs_root(kn);
+diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c
+index 45371a70caa71..05c62ca93c53d 100644
+--- a/fs/kernfs/symlink.c
++++ b/fs/kernfs/symlink.c
+@@ -62,10 +62,10 @@ static int kernfs_get_target_path(struct kernfs_node *parent,
+
+ /* go up to the root, stop at the base */
+ base = parent;
+- while (base->parent) {
+- kn = target->parent;
+- while (kn->parent && base != kn)
+- kn = kn->parent;
++ while (kernfs_parent(base)) {
++ kn = kernfs_parent(target);
++ while (kernfs_parent(kn) && base != kn)
++ kn = kernfs_parent(kn);
+
+ if (base == kn)
+ break;
+@@ -75,14 +75,14 @@ static int kernfs_get_target_path(struct kernfs_node *parent,
+
+ strcpy(s, "../");
+ s += 3;
+- base = base->parent;
++ base = kernfs_parent(base);
+ }
+
+ /* determine end of target string for reverse fillup */
+ kn = target;
+- while (kn->parent && kn != base) {
++ while (kernfs_parent(kn) && kn != base) {
+ len += strlen(kn->name) + 1;
+- kn = kn->parent;
++ kn = kernfs_parent(kn);
+ }
+
+ /* check limits */
+@@ -94,7 +94,7 @@ static int kernfs_get_target_path(struct kernfs_node *parent,
+
+ /* reverse fillup of target string from target to base */
+ kn = target;
+- while (kn->parent && kn != base) {
++ while (kernfs_parent(kn) && kn != base) {
+ int slen = strlen(kn->name);
+
+ len -= slen;
+@@ -102,7 +102,7 @@ static int kernfs_get_target_path(struct kernfs_node *parent,
+ if (len)
+ s[--len] = '/';
+
+- kn = kn->parent;
++ kn = kernfs_parent(kn);
+ }
+
+ return 0;
+@@ -111,12 +111,13 @@ static int kernfs_get_target_path(struct kernfs_node *parent,
+ static int kernfs_getlink(struct inode *inode, char *path)
+ {
+ struct kernfs_node *kn = inode->i_private;
+- struct kernfs_node *parent = kn->parent;
++ struct kernfs_node *parent;
+ struct kernfs_node *target = kn->symlink.target_kn;
+- struct kernfs_root *root = kernfs_root(parent);
++ struct kernfs_root *root = kernfs_root(kn);
+ int error;
+
+ down_read(&root->kernfs_rwsem);
++ parent = kernfs_parent(kn);
+ error = kernfs_get_target_path(parent, target, path);
+ up_read(&root->kernfs_rwsem);
+
+diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
+index d1995e2d6c943..3671a3fd60198 100644
+--- a/fs/sysfs/file.c
++++ b/fs/sysfs/file.c
+@@ -19,13 +19,19 @@
+
+ #include "sysfs.h"
+
++static struct kobject *sysfs_file_kobj(struct kernfs_node *kn)
++{
++ guard(rcu)();
++ return rcu_dereference(kn->__parent)->priv;
++}
++
+ /*
+ * Determine ktype->sysfs_ops for the given kernfs_node. This function
+ * must be called while holding an active reference.
+ */
+ static const struct sysfs_ops *sysfs_file_ops(struct kernfs_node *kn)
+ {
+- struct kobject *kobj = kn->parent->priv;
++ struct kobject *kobj = sysfs_file_kobj(kn);
+
+ if (kn->flags & KERNFS_LOCKDEP)
+ lockdep_assert_held(kn);
+@@ -40,7 +46,7 @@ static const struct sysfs_ops *sysfs_file_ops(struct kernfs_node *kn)
+ static int sysfs_kf_seq_show(struct seq_file *sf, void *v)
+ {
+ struct kernfs_open_file *of = sf->private;
+- struct kobject *kobj = of->kn->parent->priv;
++ struct kobject *kobj = sysfs_file_kobj(of->kn);
+ const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
+ ssize_t count;
+ char *buf;
+@@ -78,7 +84,7 @@ static ssize_t sysfs_kf_bin_read(struct kernfs_open_file *of, char *buf,
+ size_t count, loff_t pos)
+ {
+ struct bin_attribute *battr = of->kn->priv;
+- struct kobject *kobj = of->kn->parent->priv;
++ struct kobject *kobj = sysfs_file_kobj(of->kn);
+ loff_t size = file_inode(of->file)->i_size;
+
+ if (!count)
+@@ -102,7 +108,7 @@ static ssize_t sysfs_kf_read(struct kernfs_open_file *of, char *buf,
+ size_t count, loff_t pos)
+ {
+ const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
+- struct kobject *kobj = of->kn->parent->priv;
++ struct kobject *kobj = sysfs_file_kobj(of->kn);
+ ssize_t len;
+
+ /*
+@@ -128,7 +134,7 @@ static ssize_t sysfs_kf_write(struct kernfs_open_file *of, char *buf,
+ size_t count, loff_t pos)
+ {
+ const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
+- struct kobject *kobj = of->kn->parent->priv;
++ struct kobject *kobj = sysfs_file_kobj(of->kn);
+
+ if (!count)
+ return 0;
+@@ -141,7 +147,7 @@ static ssize_t sysfs_kf_bin_write(struct kernfs_open_file *of, char *buf,
+ size_t count, loff_t pos)
+ {
+ struct bin_attribute *battr = of->kn->priv;
+- struct kobject *kobj = of->kn->parent->priv;
++ struct kobject *kobj = sysfs_file_kobj(of->kn);
+ loff_t size = file_inode(of->file)->i_size;
+
+ if (size) {
+@@ -162,7 +168,7 @@ static int sysfs_kf_bin_mmap(struct kernfs_open_file *of,
+ struct vm_area_struct *vma)
+ {
+ struct bin_attribute *battr = of->kn->priv;
+- struct kobject *kobj = of->kn->parent->priv;
++ struct kobject *kobj = sysfs_file_kobj(of->kn);
+
+ return battr->mmap(of->file, kobj, battr, vma);
+ }
+@@ -171,7 +177,7 @@ static loff_t sysfs_kf_bin_llseek(struct kernfs_open_file *of, loff_t offset,
+ int whence)
+ {
+ struct bin_attribute *battr = of->kn->priv;
+- struct kobject *kobj = of->kn->parent->priv;
++ struct kobject *kobj = sysfs_file_kobj(of->kn);
+
+ if (battr->llseek)
+ return battr->llseek(of->file, kobj, battr, offset, whence);
+@@ -482,7 +488,7 @@ EXPORT_SYMBOL_GPL(sysfs_break_active_protection);
+ */
+ void sysfs_unbreak_active_protection(struct kernfs_node *kn)
+ {
+- struct kobject *kobj = kn->parent->priv;
++ struct kobject *kobj = sysfs_file_kobj(kn);
+
+ kernfs_unbreak_active_protection(kn);
+ kernfs_put(kn);
+diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
+index 87c79d076d6d7..5dda9a268e44c 100644
+--- a/include/linux/kernfs.h
++++ b/include/linux/kernfs.h
+@@ -147,6 +147,11 @@ enum kernfs_root_flag {
+ * Support user xattrs to be written to nodes rooted at this root.
+ */
+ KERNFS_ROOT_SUPPORT_USER_XATTR = 0x0008,
++
++ /*
++ * Renames must not change the parent node.
++ */
++ KERNFS_ROOT_INVARIANT_PARENT = 0x0010,
+ };
+
+ /* type-specific structures for kernfs_node union members */
+@@ -199,8 +204,8 @@ struct kernfs_node {
+ * never moved to a different parent, it is safe to access the
+ * parent directly.
+ */
+- struct kernfs_node *parent;
+ const char *name;
++ struct kernfs_node __rcu *__parent;
+
+ struct rb_node rb;
+
+@@ -416,6 +421,7 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn,
+ struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops,
+ unsigned int flags, void *priv);
+ void kernfs_destroy_root(struct kernfs_root *root);
++unsigned int kernfs_root_flags(struct kernfs_node *kn);
+
+ struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent,
+ const char *name, umode_t mode,
+@@ -514,6 +520,8 @@ kernfs_create_root(struct kernfs_syscall_ops *scops, unsigned int flags,
+ { return ERR_PTR(-ENOSYS); }
+
+ static inline void kernfs_destroy_root(struct kernfs_root *root) { }
++static inline unsigned int kernfs_root_flags(struct kernfs_node *kn)
++{ return 0; }
+
+ static inline struct kernfs_node *
+ kernfs_create_dir_ns(struct kernfs_node *parent, const char *name,
+diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c
+index e28d5f0d20ed0..c9752eb607ec9 100644
+--- a/kernel/cgroup/cgroup-v1.c
++++ b/kernel/cgroup/cgroup-v1.c
+@@ -844,7 +844,7 @@ static int cgroup1_rename(struct kernfs_node *kn, struct kernfs_node *new_parent
+
+ if (kernfs_type(kn) != KERNFS_DIR)
+ return -ENOTDIR;
+- if (kn->parent != new_parent)
++ if (rcu_access_pointer(kn->__parent) != new_parent)
+ return -EIO;
+
+ /*
+diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
+index 62933468aaf46..6f3d942482350 100644
+--- a/kernel/cgroup/cgroup.c
++++ b/kernel/cgroup/cgroup.c
+@@ -633,9 +633,22 @@ int cgroup_task_count(const struct cgroup *cgrp)
+ return count;
+ }
+
++static struct cgroup *kn_priv(struct kernfs_node *kn)
++{
++ struct kernfs_node *parent;
++ /*
++ * The parent can not be replaced due to KERNFS_ROOT_INVARIANT_PARENT.
++ * Therefore it is always safe to dereference this pointer outside of a
++ * RCU section.
++ */
++ parent = rcu_dereference_check(kn->__parent,
++ kernfs_root_flags(kn) & KERNFS_ROOT_INVARIANT_PARENT);
++ return parent->priv;
++}
++
+ struct cgroup_subsys_state *of_css(struct kernfs_open_file *of)
+ {
+- struct cgroup *cgrp = of->kn->parent->priv;
++ struct cgroup *cgrp = kn_priv(of->kn);
+ struct cftype *cft = of_cft(of);
+
+ /*
+@@ -1612,7 +1625,7 @@ void cgroup_kn_unlock(struct kernfs_node *kn)
+ if (kernfs_type(kn) == KERNFS_DIR)
+ cgrp = kn->priv;
+ else
+- cgrp = kn->parent->priv;
++ cgrp = kn_priv(kn);
+
+ cgroup_unlock();
+
+@@ -1644,7 +1657,7 @@ struct cgroup *cgroup_kn_lock_live(struct kernfs_node *kn, bool drain_offline)
+ if (kernfs_type(kn) == KERNFS_DIR)
+ cgrp = kn->priv;
+ else
+- cgrp = kn->parent->priv;
++ cgrp = kn_priv(kn);
+
+ /*
+ * We're gonna grab cgroup_mutex which nests outside kernfs
+@@ -2118,7 +2131,8 @@ int cgroup_setup_root(struct cgroup_root *root, u16 ss_mask)
+ root->kf_root = kernfs_create_root(kf_sops,
+ KERNFS_ROOT_CREATE_DEACTIVATED |
+ KERNFS_ROOT_SUPPORT_EXPORTOP |
+- KERNFS_ROOT_SUPPORT_USER_XATTR,
++ KERNFS_ROOT_SUPPORT_USER_XATTR |
++ KERNFS_ROOT_INVARIANT_PARENT,
+ root_cgrp);
+ if (IS_ERR(root->kf_root)) {
+ ret = PTR_ERR(root->kf_root);
+@@ -4144,7 +4158,7 @@ static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf,
+ size_t nbytes, loff_t off)
+ {
+ struct cgroup_file_ctx *ctx = of->priv;
+- struct cgroup *cgrp = of->kn->parent->priv;
++ struct cgroup *cgrp = kn_priv(of->kn);
+ struct cftype *cft = of_cft(of);
+ struct cgroup_subsys_state *css;
+ int ret;
+diff --git a/tools/testing/selftests/bpf/progs/profiler.inc.h b/tools/testing/selftests/bpf/progs/profiler.inc.h
+index 8bd1ebd7d6afd..813143b4985dc 100644
+--- a/tools/testing/selftests/bpf/progs/profiler.inc.h
++++ b/tools/testing/selftests/bpf/progs/profiler.inc.h
+@@ -223,7 +223,7 @@ static INLINE void* read_full_cgroup_path(struct kernfs_node* cgroup_node,
+ if (bpf_cmp_likely(filepart_length, <=, MAX_PATH)) {
+ payload += filepart_length;
+ }
+- cgroup_node = BPF_CORE_READ(cgroup_node, parent);
++ cgroup_node = BPF_CORE_READ(cgroup_node, __parent);
+ }
+ return payload;
+ }
+--
+2.39.5
+
--- /dev/null
+From f5152796a339a5be91d89654f9329b7c03f4f73f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jan 2025 11:01:42 +0000
+Subject: kunit: tool: Use qboot on QEMU x86_64
+
+From: Brendan Jackman <jackmanb@google.com>
+
+[ Upstream commit 08fafac4c9f289a9d9a22d838921e4b3eb22c664 ]
+
+As noted in [0], SeaBIOS (QEMU default) makes a mess of the terminal,
+qboot does not.
+
+It turns out this is actually useful with kunit.py, since the user is
+exposed to this issue if they set --raw_output=all.
+
+qboot is also faster than SeaBIOS, but it's is marginal for this
+usecase.
+
+[0] https://lore.kernel.org/all/CA+i-1C0wYb-gZ8Mwh3WSVpbk-LF-Uo+njVbASJPe1WXDURoV7A@mail.gmail.com/
+
+Both SeaBIOS and qboot are x86-specific.
+
+Link: https://lore.kernel.org/r/20250124-kunit-qboot-v1-1-815e4d4c6f7c@google.com
+Signed-off-by: Brendan Jackman <jackmanb@google.com>
+Reviewed-by: David Gow <davidgow@google.com>
+Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/kunit/qemu_configs/x86_64.py | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/tools/testing/kunit/qemu_configs/x86_64.py b/tools/testing/kunit/qemu_configs/x86_64.py
+index dc79490768630..4a6bf4e048f5b 100644
+--- a/tools/testing/kunit/qemu_configs/x86_64.py
++++ b/tools/testing/kunit/qemu_configs/x86_64.py
+@@ -7,4 +7,6 @@ CONFIG_SERIAL_8250_CONSOLE=y''',
+ qemu_arch='x86_64',
+ kernel_path='arch/x86/boot/bzImage',
+ kernel_command_line='console=ttyS0',
+- extra_qemu_params=[])
++ # qboot is faster than SeaBIOS and doesn't mess up
++ # the terminal.
++ extra_qemu_params=['-bios', 'qboot.rom'])
+--
+2.39.5
+
--- /dev/null
+From 9786e6d583ffe70d1d274bc486363a17b2520dbc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 23 Feb 2025 20:14:59 +0800
+Subject: leds: pwm-multicolor: Add check for fwnode_property_read_u32
+
+From: Yuanjun Gong <ruc_gongyuanjun@163.com>
+
+[ Upstream commit 6d91124e7edc109f114b1afe6d00d85d0d0ac174 ]
+
+Add a check to the return value of fwnode_property_read_u32()
+in case it fails.
+
+Signed-off-by: Yuanjun Gong <ruc_gongyuanjun@163.com>
+Link: https://lore.kernel.org/r/20250223121459.2889484-1-ruc_gongyuanjun@163.com
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/leds/rgb/leds-pwm-multicolor.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/leds/rgb/leds-pwm-multicolor.c b/drivers/leds/rgb/leds-pwm-multicolor.c
+index e1a81e0109e8a..c0aa34b1d0e2d 100644
+--- a/drivers/leds/rgb/leds-pwm-multicolor.c
++++ b/drivers/leds/rgb/leds-pwm-multicolor.c
+@@ -135,8 +135,11 @@ static int led_pwm_mc_probe(struct platform_device *pdev)
+
+ /* init the multicolor's LED class device */
+ cdev = &priv->mc_cdev.led_cdev;
+- fwnode_property_read_u32(mcnode, "max-brightness",
++ ret = fwnode_property_read_u32(mcnode, "max-brightness",
+ &cdev->max_brightness);
++ if (ret)
++ goto release_mcnode;
++
+ cdev->flags = LED_CORE_SUSPENDRESUME;
+ cdev->brightness_set_blocking = led_pwm_mc_set;
+
+--
+2.39.5
+
--- /dev/null
+From f79f727c1ab20bda817c4012ce14c64974bb1c68 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Jan 2025 12:36:53 +0100
+Subject: leds: trigger: netdev: Configure LED blink interval for HW offload
+
+From: Marek Vasut <marex@denx.de>
+
+[ Upstream commit c629c972b310af41e9e072febb6dae9a299edde6 ]
+
+In case a PHY LED implements .blink_set callback to set LED blink
+interval, call it even if .hw_control is already set, as that LED
+blink interval likely controls the blink rate of that HW offloaded
+LED. For PHY LEDs, that can be their activity blinking interval.
+
+The software blinking is not affected by this change.
+
+With this change, the LED interval setting looks something like this:
+$ echo netdev > /sys/class/leds/led:green:lan/trigger
+$ echo 1 > /sys/class/leds/led:green:lan/brightness
+$ echo 250 > /sys/class/leds/led:green:lan/interval
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Link: https://lore.kernel.org/r/20250120113740.91807-1-marex@denx.de
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/leds/trigger/ledtrig-netdev.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c
+index 4b0863db901a9..356a55ced2c28 100644
+--- a/drivers/leds/trigger/ledtrig-netdev.c
++++ b/drivers/leds/trigger/ledtrig-netdev.c
+@@ -68,6 +68,7 @@ struct led_netdev_data {
+ unsigned int last_activity;
+
+ unsigned long mode;
++ unsigned long blink_delay;
+ int link_speed;
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(supported_link_modes);
+ u8 duplex;
+@@ -86,6 +87,10 @@ static void set_baseline_state(struct led_netdev_data *trigger_data)
+ /* Already validated, hw control is possible with the requested mode */
+ if (trigger_data->hw_control) {
+ led_cdev->hw_control_set(led_cdev, trigger_data->mode);
++ if (led_cdev->blink_set) {
++ led_cdev->blink_set(led_cdev, &trigger_data->blink_delay,
++ &trigger_data->blink_delay);
++ }
+
+ return;
+ }
+@@ -454,10 +459,11 @@ static ssize_t interval_store(struct device *dev,
+ size_t size)
+ {
+ struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
++ struct led_classdev *led_cdev = trigger_data->led_cdev;
+ unsigned long value;
+ int ret;
+
+- if (trigger_data->hw_control)
++ if (trigger_data->hw_control && !led_cdev->blink_set)
+ return -EINVAL;
+
+ ret = kstrtoul(buf, 0, &value);
+@@ -466,9 +472,13 @@ static ssize_t interval_store(struct device *dev,
+
+ /* impose some basic bounds on the timer interval */
+ if (value >= 5 && value <= 10000) {
+- cancel_delayed_work_sync(&trigger_data->work);
++ if (trigger_data->hw_control) {
++ trigger_data->blink_delay = value;
++ } else {
++ cancel_delayed_work_sync(&trigger_data->work);
+
+- atomic_set(&trigger_data->interval, msecs_to_jiffies(value));
++ atomic_set(&trigger_data->interval, msecs_to_jiffies(value));
++ }
+ set_baseline_state(trigger_data); /* resets timer */
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 12c1088c278a74c6a17b523e4cd9d975f7a0ac59 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Feb 2025 17:48:08 -0800
+Subject: libbpf: fix LDX/STX/ST CO-RE relocation size adjustment logic
+
+From: Andrii Nakryiko <andrii@kernel.org>
+
+[ Upstream commit 06096d19ee3897a7e70922580159607fe315da7a ]
+
+Libbpf has a somewhat obscure feature of automatically adjusting the
+"size" of LDX/STX/ST instruction (memory store and load instructions),
+based on originally recorded access size (u8, u16, u32, or u64) and the
+actual size of the field on target kernel. This is meant to facilitate
+using BPF CO-RE on 32-bit architectures (pointers are always 64-bit in
+BPF, but host kernel's BTF will have it as 32-bit type), as well as
+generally supporting safe type changes (unsigned integer type changes
+can be transparently "relocated").
+
+One issue that surfaced only now, 5 years after this logic was
+implemented, is how this all works when dealing with fields that are
+arrays. This isn't all that easy and straightforward to hit (see
+selftests that reproduce this condition), but one of sched_ext BPF
+programs did hit it with innocent looking loop.
+
+Long story short, libbpf used to calculate entire array size, instead of
+making sure to only calculate array's element size. But it's the element
+that is loaded by LDX/STX/ST instructions (1, 2, 4, or 8 bytes), so
+that's what libbpf should check. This patch adjusts the logic for
+arrays and fixed the issue.
+
+Reported-by: Emil Tsalapatis <emil@etsalapatis.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Acked-by: Eduard Zingerman <eddyz87@gmail.com>
+Link: https://lore.kernel.org/r/20250207014809.1573841-1-andrii@kernel.org
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/lib/bpf/relo_core.c | 24 ++++++++++++++++++++----
+ 1 file changed, 20 insertions(+), 4 deletions(-)
+
+diff --git a/tools/lib/bpf/relo_core.c b/tools/lib/bpf/relo_core.c
+index 63a4d5ad12d1a..26cde1b27174b 100644
+--- a/tools/lib/bpf/relo_core.c
++++ b/tools/lib/bpf/relo_core.c
+@@ -683,7 +683,7 @@ static int bpf_core_calc_field_relo(const char *prog_name,
+ {
+ const struct bpf_core_accessor *acc;
+ const struct btf_type *t;
+- __u32 byte_off, byte_sz, bit_off, bit_sz, field_type_id;
++ __u32 byte_off, byte_sz, bit_off, bit_sz, field_type_id, elem_id;
+ const struct btf_member *m;
+ const struct btf_type *mt;
+ bool bitfield;
+@@ -706,8 +706,14 @@ static int bpf_core_calc_field_relo(const char *prog_name,
+ if (!acc->name) {
+ if (relo->kind == BPF_CORE_FIELD_BYTE_OFFSET) {
+ *val = spec->bit_offset / 8;
+- /* remember field size for load/store mem size */
+- sz = btf__resolve_size(spec->btf, acc->type_id);
++ /* remember field size for load/store mem size;
++ * note, for arrays we care about individual element
++ * sizes, not the overall array size
++ */
++ t = skip_mods_and_typedefs(spec->btf, acc->type_id, &elem_id);
++ while (btf_is_array(t))
++ t = skip_mods_and_typedefs(spec->btf, btf_array(t)->type, &elem_id);
++ sz = btf__resolve_size(spec->btf, elem_id);
+ if (sz < 0)
+ return -EINVAL;
+ *field_sz = sz;
+@@ -767,7 +773,17 @@ static int bpf_core_calc_field_relo(const char *prog_name,
+ case BPF_CORE_FIELD_BYTE_OFFSET:
+ *val = byte_off;
+ if (!bitfield) {
+- *field_sz = byte_sz;
++ /* remember field size for load/store mem size;
++ * note, for arrays we care about individual element
++ * sizes, not the overall array size
++ */
++ t = skip_mods_and_typedefs(spec->btf, field_type_id, &elem_id);
++ while (btf_is_array(t))
++ t = skip_mods_and_typedefs(spec->btf, btf_array(t)->type, &elem_id);
++ sz = btf__resolve_size(spec->btf, elem_id);
++ if (sz < 0)
++ return -EINVAL;
++ *field_sz = sz;
+ *type_id = field_type_id;
+ }
+ break;
+--
+2.39.5
+
--- /dev/null
+From b9119a807ee2bd305525d9fdf3ae64becd443626 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Feb 2025 02:31:11 +0530
+Subject: libbpf: Fix out-of-bound read
+
+From: Nandakumar Edamana <nandakumar@nandakumar.co.in>
+
+[ Upstream commit 236d3910117e9f97ebf75e511d8bcc950f1a4e5f ]
+
+In `set_kcfg_value_str`, an untrusted string is accessed with the assumption
+that it will be at least two characters long due to the presence of checks for
+opening and closing quotes. But the check for the closing quote
+(value[len - 1] != '"') misses the fact that it could be checking the opening
+quote itself in case of an invalid input that consists of just the opening
+quote.
+
+This commit adds an explicit check to make sure the string is at least two
+characters long.
+
+Signed-off-by: Nandakumar Edamana <nandakumar@nandakumar.co.in>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Link: https://lore.kernel.org/bpf/20250221210110.3182084-1-nandakumar@nandakumar.co.in
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/lib/bpf/libbpf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
+index 5b45f76059296..a6bbae1e4c6b9 100644
+--- a/tools/lib/bpf/libbpf.c
++++ b/tools/lib/bpf/libbpf.c
+@@ -2074,7 +2074,7 @@ static int set_kcfg_value_str(struct extern_desc *ext, char *ext_val,
+ }
+
+ len = strlen(value);
+- if (value[len - 1] != '"') {
++ if (len < 2 || value[len - 1] != '"') {
+ pr_warn("extern (kcfg) '%s': invalid string config '%s'\n",
+ ext->name, value);
+ return -EINVAL;
+--
+2.39.5
+
--- /dev/null
+From da78c30fd182b84458551ef74f482bcd478a17b4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Mar 2025 17:40:38 +0000
+Subject: libbpf: Pass BPF token from find_prog_btf_id to BPF_BTF_GET_FD_BY_ID
+
+From: Mykyta Yatsenko <yatsenko@meta.com>
+
+[ Upstream commit 974ef9f0d23edc1a802691c585b84514b414a96d ]
+
+Pass BPF token from bpf_program__set_attach_target to
+BPF_BTF_GET_FD_BY_ID bpf command.
+When freplace program attaches to target program, it needs to look up
+for BTF of the target, this may require BPF token, if, for example,
+running from user namespace.
+
+Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Acked-by: Yonghong Song <yonghong.song@linux.dev>
+Link: https://lore.kernel.org/bpf/20250317174039.161275-4-mykyta.yatsenko5@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/lib/bpf/bpf.c | 3 ++-
+ tools/lib/bpf/bpf.h | 3 ++-
+ tools/lib/bpf/btf.c | 15 +++++++++++++--
+ tools/lib/bpf/libbpf.c | 10 +++++-----
+ tools/lib/bpf/libbpf_internal.h | 1 +
+ 5 files changed, 23 insertions(+), 9 deletions(-)
+
+diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
+index 2a4c71501a17d..72470acce67b7 100644
+--- a/tools/lib/bpf/bpf.c
++++ b/tools/lib/bpf/bpf.c
+@@ -1095,7 +1095,7 @@ int bpf_map_get_fd_by_id(__u32 id)
+ int bpf_btf_get_fd_by_id_opts(__u32 id,
+ const struct bpf_get_fd_by_id_opts *opts)
+ {
+- const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
++ const size_t attr_sz = offsetofend(union bpf_attr, fd_by_id_token_fd);
+ union bpf_attr attr;
+ int fd;
+
+@@ -1105,6 +1105,7 @@ int bpf_btf_get_fd_by_id_opts(__u32 id,
+ memset(&attr, 0, attr_sz);
+ attr.btf_id = id;
+ attr.open_flags = OPTS_GET(opts, open_flags, 0);
++ attr.fd_by_id_token_fd = OPTS_GET(opts, token_fd, 0);
+
+ fd = sys_bpf_fd(BPF_BTF_GET_FD_BY_ID, &attr, attr_sz);
+ return libbpf_err_errno(fd);
+diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
+index a4a7b1ad1b631..b93d00968cba1 100644
+--- a/tools/lib/bpf/bpf.h
++++ b/tools/lib/bpf/bpf.h
+@@ -484,9 +484,10 @@ LIBBPF_API int bpf_link_get_next_id(__u32 start_id, __u32 *next_id);
+ struct bpf_get_fd_by_id_opts {
+ size_t sz; /* size of this struct for forward/backward compatibility */
+ __u32 open_flags; /* permissions requested for the operation on fd */
++ __u32 token_fd;
+ size_t :0;
+ };
+-#define bpf_get_fd_by_id_opts__last_field open_flags
++#define bpf_get_fd_by_id_opts__last_field token_fd
+
+ LIBBPF_API int bpf_prog_get_fd_by_id(__u32 id);
+ LIBBPF_API int bpf_prog_get_fd_by_id_opts(__u32 id,
+diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
+index 27e7bfae953bd..3a7e0ba9f5923 100644
+--- a/tools/lib/bpf/btf.c
++++ b/tools/lib/bpf/btf.c
+@@ -1618,12 +1618,18 @@ struct btf *btf_get_from_fd(int btf_fd, struct btf *base_btf)
+ return btf;
+ }
+
+-struct btf *btf__load_from_kernel_by_id_split(__u32 id, struct btf *base_btf)
++struct btf *btf_load_from_kernel(__u32 id, struct btf *base_btf, int token_fd)
+ {
+ struct btf *btf;
+ int btf_fd;
++ LIBBPF_OPTS(bpf_get_fd_by_id_opts, opts);
++
++ if (token_fd) {
++ opts.open_flags |= BPF_F_TOKEN_FD;
++ opts.token_fd = token_fd;
++ }
+
+- btf_fd = bpf_btf_get_fd_by_id(id);
++ btf_fd = bpf_btf_get_fd_by_id_opts(id, &opts);
+ if (btf_fd < 0)
+ return libbpf_err_ptr(-errno);
+
+@@ -1633,6 +1639,11 @@ struct btf *btf__load_from_kernel_by_id_split(__u32 id, struct btf *base_btf)
+ return libbpf_ptr(btf);
+ }
+
++struct btf *btf__load_from_kernel_by_id_split(__u32 id, struct btf *base_btf)
++{
++ return btf_load_from_kernel(id, base_btf, 0);
++}
++
+ struct btf *btf__load_from_kernel_by_id(__u32 id)
+ {
+ return btf__load_from_kernel_by_id_split(id, NULL);
+diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
+index 5ff643e60d09c..5b45f76059296 100644
+--- a/tools/lib/bpf/libbpf.c
++++ b/tools/lib/bpf/libbpf.c
+@@ -9936,7 +9936,7 @@ int libbpf_find_vmlinux_btf_id(const char *name,
+ return libbpf_err(err);
+ }
+
+-static int libbpf_find_prog_btf_id(const char *name, __u32 attach_prog_fd)
++static int libbpf_find_prog_btf_id(const char *name, __u32 attach_prog_fd, int token_fd)
+ {
+ struct bpf_prog_info info;
+ __u32 info_len = sizeof(info);
+@@ -9956,7 +9956,7 @@ static int libbpf_find_prog_btf_id(const char *name, __u32 attach_prog_fd)
+ pr_warn("The target program doesn't have BTF\n");
+ goto out;
+ }
+- btf = btf__load_from_kernel_by_id(info.btf_id);
++ btf = btf_load_from_kernel(info.btf_id, NULL, token_fd);
+ err = libbpf_get_error(btf);
+ if (err) {
+ pr_warn("Failed to get BTF %d of the program: %d\n", info.btf_id, err);
+@@ -10039,7 +10039,7 @@ static int libbpf_find_attach_btf_id(struct bpf_program *prog, const char *attac
+ pr_warn("prog '%s': attach program FD is not set\n", prog->name);
+ return -EINVAL;
+ }
+- err = libbpf_find_prog_btf_id(attach_name, attach_prog_fd);
++ err = libbpf_find_prog_btf_id(attach_name, attach_prog_fd, prog->obj->token_fd);
+ if (err < 0) {
+ pr_warn("prog '%s': failed to find BPF program (FD %d) BTF ID for '%s': %d\n",
+ prog->name, attach_prog_fd, attach_name, err);
+@@ -12804,7 +12804,7 @@ struct bpf_link *bpf_program__attach_freplace(const struct bpf_program *prog,
+ if (target_fd) {
+ LIBBPF_OPTS(bpf_link_create_opts, target_opts);
+
+- btf_id = libbpf_find_prog_btf_id(attach_func_name, target_fd);
++ btf_id = libbpf_find_prog_btf_id(attach_func_name, target_fd, prog->obj->token_fd);
+ if (btf_id < 0)
+ return libbpf_err_ptr(btf_id);
+
+@@ -13629,7 +13629,7 @@ int bpf_program__set_attach_target(struct bpf_program *prog,
+
+ if (attach_prog_fd) {
+ btf_id = libbpf_find_prog_btf_id(attach_func_name,
+- attach_prog_fd);
++ attach_prog_fd, prog->obj->token_fd);
+ if (btf_id < 0)
+ return libbpf_err(btf_id);
+ } else {
+diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h
+index 408df59e07719..bd7adb8594d40 100644
+--- a/tools/lib/bpf/libbpf_internal.h
++++ b/tools/lib/bpf/libbpf_internal.h
+@@ -408,6 +408,7 @@ int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
+ int btf_load_into_kernel(struct btf *btf,
+ char *log_buf, size_t log_sz, __u32 log_level,
+ int token_fd);
++struct btf *btf_load_from_kernel(__u32 id, struct btf *base_btf, int token_fd);
+
+ struct btf *btf_get_from_fd(int btf_fd, struct btf *base_btf);
+ void btf_get_kernel_prefix_kind(enum bpf_attach_type attach_type,
+--
+2.39.5
+
--- /dev/null
+From b589caebbffea6213b76013900f70bc3e805730c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Mar 2025 12:22:22 +0100
+Subject: libnvdimm/labels: Fix divide error in nd_label_data_init()
+
+From: Robert Richter <rrichter@amd.com>
+
+[ Upstream commit ef1d3455bbc1922f94a91ed58d3d7db440652959 ]
+
+If a faulty CXL memory device returns a broken zero LSA size in its
+memory device information (Identify Memory Device (Opcode 4000h), CXL
+spec. 3.1, 8.2.9.9.1.1), a divide error occurs in the libnvdimm
+driver:
+
+ Oops: divide error: 0000 [#1] PREEMPT SMP NOPTI
+ RIP: 0010:nd_label_data_init+0x10e/0x800 [libnvdimm]
+
+Code and flow:
+
+1) CXL Command 4000h returns LSA size = 0
+2) config_size is assigned to zero LSA size (CXL pmem driver):
+
+drivers/cxl/pmem.c: .config_size = mds->lsa_size,
+
+3) max_xfer is set to zero (nvdimm driver):
+
+drivers/nvdimm/label.c: max_xfer = min_t(size_t, ndd->nsarea.max_xfer, config_size);
+
+4) A subsequent DIV_ROUND_UP() causes a division by zero:
+
+drivers/nvdimm/label.c: /* Make our initial read size a multiple of max_xfer size */
+drivers/nvdimm/label.c: read_size = min(DIV_ROUND_UP(read_size, max_xfer) * max_xfer,
+drivers/nvdimm/label.c- config_size);
+
+Fix this by checking the config size parameter by extending an
+existing check.
+
+Signed-off-by: Robert Richter <rrichter@amd.com>
+Reviewed-by: Pankaj Gupta <pankaj.gupta@amd.com>
+Reviewed-by: Ira Weiny <ira.weiny@intel.com>
+Link: https://patch.msgid.link/20250320112223.608320-1-rrichter@amd.com
+Signed-off-by: Ira Weiny <ira.weiny@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvdimm/label.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
+index 082253a3a9560..04f4a049599a1 100644
+--- a/drivers/nvdimm/label.c
++++ b/drivers/nvdimm/label.c
+@@ -442,7 +442,8 @@ int nd_label_data_init(struct nvdimm_drvdata *ndd)
+ if (ndd->data)
+ return 0;
+
+- if (ndd->nsarea.status || ndd->nsarea.max_xfer == 0) {
++ if (ndd->nsarea.status || ndd->nsarea.max_xfer == 0 ||
++ ndd->nsarea.config_size == 0) {
+ dev_dbg(ndd->dev, "failed to init config data area: (%u:%u)\n",
+ ndd->nsarea.max_xfer, ndd->nsarea.config_size);
+ return -ENXIO;
+--
+2.39.5
+
--- /dev/null
+From c4da04f1b6a92ed457d0468d578cfbec40ad563c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Mar 2025 07:33:22 -0700
+Subject: lockdep: Fix wait context check on softirq for PREEMPT_RT
+
+From: Ryo Takakura <ryotkkr98@gmail.com>
+
+[ Upstream commit 61c39d8c83e2077f33e0a2c8980a76a7f323f0ce ]
+
+Since:
+
+ 0c1d7a2c2d32 ("lockdep: Remove softirq accounting on PREEMPT_RT.")
+
+the wait context test for mutex usage within "in softirq context" fails
+as it references @softirq_context:
+
+ | wait context tests |
+ --------------------------------------------------------------------------
+ | rcu | raw | spin |mutex |
+ --------------------------------------------------------------------------
+ in hardirq context: ok | ok | ok | ok |
+ in hardirq context (not threaded): ok | ok | ok | ok |
+ in softirq context: ok | ok | ok |FAILED|
+
+As a fix, add lockdep map for BH disabled section. This fixes the
+issue by letting us catch cases when local_bh_disable() gets called
+with preemption disabled where local_lock doesn't get acquired.
+In the case of "in softirq context" selftest, local_bh_disable() was
+being called with preemption disable as it's early in the boot.
+
+[ boqun: Move the lockdep annotations into __local_bh_*() to avoid false
+ positives because of unpaired local_bh_disable() reported by
+ Borislav Petkov and Peter Zijlstra, and make bh_lock_map
+ only exist for PREEMPT_RT. ]
+
+[ mingo: Restored authorship and improved the bh_lock_map definition. ]
+
+Signed-off-by: Ryo Takakura <ryotkkr98@gmail.com>
+Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Link: https://lore.kernel.org/r/20250321143322.79651-1-boqun.feng@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/softirq.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/kernel/softirq.c b/kernel/softirq.c
+index 8c4524ce65faf..00ff176350413 100644
+--- a/kernel/softirq.c
++++ b/kernel/softirq.c
+@@ -126,6 +126,18 @@ static DEFINE_PER_CPU(struct softirq_ctrl, softirq_ctrl) = {
+ .lock = INIT_LOCAL_LOCK(softirq_ctrl.lock),
+ };
+
++#ifdef CONFIG_DEBUG_LOCK_ALLOC
++static struct lock_class_key bh_lock_key;
++struct lockdep_map bh_lock_map = {
++ .name = "local_bh",
++ .key = &bh_lock_key,
++ .wait_type_outer = LD_WAIT_FREE,
++ .wait_type_inner = LD_WAIT_CONFIG, /* PREEMPT_RT makes BH preemptible. */
++ .lock_type = LD_LOCK_PERCPU,
++};
++EXPORT_SYMBOL_GPL(bh_lock_map);
++#endif
++
+ /**
+ * local_bh_blocked() - Check for idle whether BH processing is blocked
+ *
+@@ -148,6 +160,8 @@ void __local_bh_disable_ip(unsigned long ip, unsigned int cnt)
+
+ WARN_ON_ONCE(in_hardirq());
+
++ lock_map_acquire_read(&bh_lock_map);
++
+ /* First entry of a task into a BH disabled section? */
+ if (!current->softirq_disable_cnt) {
+ if (preemptible()) {
+@@ -211,6 +225,8 @@ void __local_bh_enable_ip(unsigned long ip, unsigned int cnt)
+ WARN_ON_ONCE(in_hardirq());
+ lockdep_assert_irqs_enabled();
+
++ lock_map_release(&bh_lock_map);
++
+ local_irq_save(flags);
+ curcnt = __this_cpu_read(softirq_ctrl.cnt);
+
+@@ -261,6 +277,8 @@ static inline void ksoftirqd_run_begin(void)
+ /* Counterpart to ksoftirqd_run_begin() */
+ static inline void ksoftirqd_run_end(void)
+ {
++ /* pairs with the lock_map_acquire_read() in ksoftirqd_run_begin() */
++ lock_map_release(&bh_lock_map);
+ __local_bh_enable(SOFTIRQ_OFFSET, true);
+ WARN_ON_ONCE(in_interrupt());
+ local_irq_enable();
+--
+2.39.5
+
--- /dev/null
+From ef90256884af79b879dab890a6cdaf0026a4f557 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jan 2025 13:00:40 +0100
+Subject: loop: check in LO_FLAGS_DIRECT_IO in loop_default_blocksize
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit f6f9e32fe1e454ae8ac0190b2c2bd6074914beec ]
+
+We can't go below the minimum direct I/O size no matter if direct I/O is
+enabled by passing in an O_DIRECT file descriptor or due to the explicit
+flag. Now that LO_FLAGS_DIRECT_IO is set earlier after assigning a
+backing file, loop_default_blocksize can check it instead of the
+O_DIRECT flag to handle both conditions.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
+Link: https://lore.kernel.org/r/20250131120120.1315125-4-hch@lst.de
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/block/loop.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/block/loop.c b/drivers/block/loop.c
+index 6bd44ec2c9b1a..fa9c77b8f4d23 100644
+--- a/drivers/block/loop.c
++++ b/drivers/block/loop.c
+@@ -916,7 +916,7 @@ static unsigned int loop_default_blocksize(struct loop_device *lo,
+ struct block_device *backing_bdev)
+ {
+ /* In case of direct I/O, match underlying block size */
+- if ((lo->lo_backing_file->f_flags & O_DIRECT) && backing_bdev)
++ if ((lo->lo_flags & LO_FLAGS_DIRECT_IO) && backing_bdev)
+ return bdev_logical_block_size(backing_bdev);
+ return SECTOR_SIZE;
+ }
+--
+2.39.5
+
--- /dev/null
+From 447e64f82bd12d1345910b87b861dd3e3be4a34c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Mar 2025 15:28:51 +0000
+Subject: mailbox: pcc: Use acpi_os_ioremap() instead of ioremap()
+
+From: Sudeep Holla <sudeep.holla@arm.com>
+
+[ Upstream commit d181acea5b864e91f38f5771b8961215ce5017ae ]
+
+The Platform Communication Channel (PCC) mailbox driver currently uses
+ioremap() to map channel shared memory regions. However it is preferred
+to use acpi_os_ioremap(), which is mapping function specific to EFI/ACPI
+defined memory regions. It ensures that the correct memory attributes
+are applied when mapping ACPI-provided regions.
+
+While at it, also add checks for handling any errors with the mapping.
+
+Acked-by: Huisong Li <lihuisong@huawei.com>
+Tested-by: Huisong Li <lihuisong@huawei.com>
+Tested-by: Adam Young <admiyo@os.amperecomputing.com>
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mailbox/pcc.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
+index f8215a8f656a4..49254d99a8ad6 100644
+--- a/drivers/mailbox/pcc.c
++++ b/drivers/mailbox/pcc.c
+@@ -419,8 +419,12 @@ int pcc_mbox_ioremap(struct mbox_chan *chan)
+ return -1;
+ pchan_info = chan->con_priv;
+ pcc_mbox_chan = &pchan_info->chan;
+- pcc_mbox_chan->shmem = ioremap(pcc_mbox_chan->shmem_base_addr,
+- pcc_mbox_chan->shmem_size);
++
++ pcc_mbox_chan->shmem = acpi_os_ioremap(pcc_mbox_chan->shmem_base_addr,
++ pcc_mbox_chan->shmem_size);
++ if (!pcc_mbox_chan->shmem)
++ return -ENXIO;
++
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(pcc_mbox_ioremap);
+--
+2.39.5
+
--- /dev/null
+From d9bd5d918832283161732ff824ad0e2b5250812c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 08:27:13 +0000
+Subject: mailbox: use error ret code of of_parse_phandle_with_args()
+
+From: Tudor Ambarus <tudor.ambarus@linaro.org>
+
+[ Upstream commit 24fdd5074b205cfb0ef4cd0751a2d03031455929 ]
+
+In case of error, of_parse_phandle_with_args() returns -EINVAL when the
+passed index is negative, or -ENOENT when the index is for an empty
+phandle. The mailbox core overwrote the error return code with a less
+precise -ENODEV. Use the error returned code from
+of_parse_phandle_with_args().
+
+Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
+Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mailbox/mailbox.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c
+index d3d26a2c98956..cb174e788a96c 100644
+--- a/drivers/mailbox/mailbox.c
++++ b/drivers/mailbox/mailbox.c
+@@ -415,11 +415,12 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
+
+ mutex_lock(&con_mutex);
+
+- if (of_parse_phandle_with_args(dev->of_node, "mboxes",
+- "#mbox-cells", index, &spec)) {
++ ret = of_parse_phandle_with_args(dev->of_node, "mboxes", "#mbox-cells",
++ index, &spec);
++ if (ret) {
+ dev_dbg(dev, "%s: can't parse \"mboxes\" property\n", __func__);
+ mutex_unlock(&con_mutex);
+- return ERR_PTR(-ENODEV);
++ return ERR_PTR(ret);
+ }
+
+ chan = ERR_PTR(-EPROBE_DEFER);
+--
+2.39.5
+
--- /dev/null
+From 055b660be507baec9d3ca5ceeb5cdcd5e89e2896 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Mar 2025 16:10:08 +0800
+Subject: mctp: Fix incorrect tx flow invalidation condition in mctp-i2c
+
+From: Daniel Hsu <d486250@gmail.com>
+
+[ Upstream commit 70facbf978ac90c6da17a3de2a8dd111b06f1bac ]
+
+Previously, the condition for invalidating the tx flow in
+mctp_i2c_invalidate_tx_flow() checked if `rc` was nonzero.
+However, this could incorrectly trigger the invalidation
+even when `rc > 0` was returned as a success status.
+
+This patch updates the condition to explicitly check for `rc < 0`,
+ensuring that only error cases trigger the invalidation.
+
+Signed-off-by: Daniel Hsu <Daniel-Hsu@quantatw.com>
+Reviewed-by: Jeremy Kerr <jk@codeconstruct.com.au>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/mctp/mctp-i2c.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/mctp/mctp-i2c.c b/drivers/net/mctp/mctp-i2c.c
+index 6622de48fc9e7..503a9174321c6 100644
+--- a/drivers/net/mctp/mctp-i2c.c
++++ b/drivers/net/mctp/mctp-i2c.c
+@@ -538,7 +538,7 @@ static void mctp_i2c_xmit(struct mctp_i2c_dev *midev, struct sk_buff *skb)
+ rc = __i2c_transfer(midev->adapter, &msg, 1);
+
+ /* on tx errors, the flow can no longer be considered valid */
+- if (rc)
++ if (rc < 0)
+ mctp_i2c_invalidate_tx_flow(midev, skb);
+
+ break;
+--
+2.39.5
+
--- /dev/null
+From f08f30b2a35f77403ae41590970047194b01e620 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Feb 2025 00:09:07 +0100
+Subject: media: adv7180: Disable test-pattern control on adv7180
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+
+[ Upstream commit a980bc5f56b0292336e408f657f79e574e8067c0 ]
+
+The register that enables selecting a test-pattern to be outputted in
+free-run mode (FREE_RUN_PAT_SEL[2:0]) is only available on adv7280 based
+devices, not the adv7180 based ones.
+
+Add a flag to mark devices that are capable of generating test-patterns,
+and those that are not. And only register the control on supported
+devices.
+
+Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/i2c/adv7180.c | 34 ++++++++++++++++++++++------------
+ 1 file changed, 22 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
+index 819ff9f7c90fe..2a20a4fad796c 100644
+--- a/drivers/media/i2c/adv7180.c
++++ b/drivers/media/i2c/adv7180.c
+@@ -195,6 +195,7 @@ struct adv7180_state;
+ #define ADV7180_FLAG_V2 BIT(1)
+ #define ADV7180_FLAG_MIPI_CSI2 BIT(2)
+ #define ADV7180_FLAG_I2P BIT(3)
++#define ADV7180_FLAG_TEST_PATTERN BIT(4)
+
+ struct adv7180_chip_info {
+ unsigned int flags;
+@@ -682,11 +683,15 @@ static int adv7180_init_controls(struct adv7180_state *state)
+ ADV7180_HUE_MAX, 1, ADV7180_HUE_DEF);
+ v4l2_ctrl_new_custom(&state->ctrl_hdl, &adv7180_ctrl_fast_switch, NULL);
+
+- v4l2_ctrl_new_std_menu_items(&state->ctrl_hdl, &adv7180_ctrl_ops,
+- V4L2_CID_TEST_PATTERN,
+- ARRAY_SIZE(test_pattern_menu) - 1,
+- 0, ARRAY_SIZE(test_pattern_menu) - 1,
+- test_pattern_menu);
++ if (state->chip_info->flags & ADV7180_FLAG_TEST_PATTERN) {
++ v4l2_ctrl_new_std_menu_items(&state->ctrl_hdl,
++ &adv7180_ctrl_ops,
++ V4L2_CID_TEST_PATTERN,
++ ARRAY_SIZE(test_pattern_menu) - 1,
++ 0,
++ ARRAY_SIZE(test_pattern_menu) - 1,
++ test_pattern_menu);
++ }
+
+ state->sd.ctrl_handler = &state->ctrl_hdl;
+ if (state->ctrl_hdl.error) {
+@@ -1221,7 +1226,7 @@ static const struct adv7180_chip_info adv7182_info = {
+ };
+
+ static const struct adv7180_chip_info adv7280_info = {
+- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P,
++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P | ADV7180_FLAG_TEST_PATTERN,
+ .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
+ BIT(ADV7182_INPUT_CVBS_AIN2) |
+ BIT(ADV7182_INPUT_CVBS_AIN3) |
+@@ -1235,7 +1240,8 @@ static const struct adv7180_chip_info adv7280_info = {
+ };
+
+ static const struct adv7180_chip_info adv7280_m_info = {
+- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P,
++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P |
++ ADV7180_FLAG_TEST_PATTERN,
+ .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
+ BIT(ADV7182_INPUT_CVBS_AIN2) |
+ BIT(ADV7182_INPUT_CVBS_AIN3) |
+@@ -1256,7 +1262,8 @@ static const struct adv7180_chip_info adv7280_m_info = {
+ };
+
+ static const struct adv7180_chip_info adv7281_info = {
+- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2,
++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 |
++ ADV7180_FLAG_TEST_PATTERN,
+ .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
+ BIT(ADV7182_INPUT_CVBS_AIN2) |
+ BIT(ADV7182_INPUT_CVBS_AIN7) |
+@@ -1271,7 +1278,8 @@ static const struct adv7180_chip_info adv7281_info = {
+ };
+
+ static const struct adv7180_chip_info adv7281_m_info = {
+- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2,
++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 |
++ ADV7180_FLAG_TEST_PATTERN,
+ .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
+ BIT(ADV7182_INPUT_CVBS_AIN2) |
+ BIT(ADV7182_INPUT_CVBS_AIN3) |
+@@ -1291,7 +1299,8 @@ static const struct adv7180_chip_info adv7281_m_info = {
+ };
+
+ static const struct adv7180_chip_info adv7281_ma_info = {
+- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2,
++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 |
++ ADV7180_FLAG_TEST_PATTERN,
+ .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
+ BIT(ADV7182_INPUT_CVBS_AIN2) |
+ BIT(ADV7182_INPUT_CVBS_AIN3) |
+@@ -1316,7 +1325,7 @@ static const struct adv7180_chip_info adv7281_ma_info = {
+ };
+
+ static const struct adv7180_chip_info adv7282_info = {
+- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P,
++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P | ADV7180_FLAG_TEST_PATTERN,
+ .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
+ BIT(ADV7182_INPUT_CVBS_AIN2) |
+ BIT(ADV7182_INPUT_CVBS_AIN7) |
+@@ -1331,7 +1340,8 @@ static const struct adv7180_chip_info adv7282_info = {
+ };
+
+ static const struct adv7180_chip_info adv7282_m_info = {
+- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P,
++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P |
++ ADV7180_FLAG_TEST_PATTERN,
+ .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
+ BIT(ADV7182_INPUT_CVBS_AIN2) |
+ BIT(ADV7182_INPUT_CVBS_AIN3) |
+--
+2.39.5
+
--- /dev/null
+From 9770160e0708362fff8d01e944e026917e3077b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Oct 2024 15:50:15 +0200
+Subject: media: c8sectpfe: Call of_node_put(i2c_bus) only once in
+ c8sectpfe_probe()
+
+From: Markus Elfring <elfring@users.sourceforge.net>
+
+[ Upstream commit b773530a34df0687020520015057075f8b7b4ac4 ]
+
+An of_node_put(i2c_bus) call was immediately used after a pointer check
+for an of_find_i2c_adapter_by_node() call in this function implementation.
+Thus call such a function only once instead directly before the check.
+
+This issue was transformed by using the Coccinelle software.
+
+Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c
+index 67d3d6e50d2e2..ed3a107965cc9 100644
+--- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c
++++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c
+@@ -797,13 +797,12 @@ static int c8sectpfe_probe(struct platform_device *pdev)
+ }
+ tsin->i2c_adapter =
+ of_find_i2c_adapter_by_node(i2c_bus);
++ of_node_put(i2c_bus);
+ if (!tsin->i2c_adapter) {
+ dev_err(&pdev->dev, "No i2c adapter found\n");
+- of_node_put(i2c_bus);
+ ret = -ENODEV;
+ goto err_node_put;
+ }
+- of_node_put(i2c_bus);
+
+ /* Acquire reset GPIO and activate it */
+ tsin->rst_gpio = devm_fwnode_gpiod_get(dev,
+--
+2.39.5
+
--- /dev/null
+From b833aafb62c4bb7c72bef6bdebe2758e72cf5f85 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 14:13:24 +0100
+Subject: media: cx231xx: set device_caps for 417
+
+From: Hans Verkuil <hverkuil@xs4all.nl>
+
+[ Upstream commit a79efc44b51432490538a55b9753a721f7d3ea42 ]
+
+The video_device for the MPEG encoder did not set device_caps.
+
+Add this, otherwise the video device can't be registered (you get a
+WARN_ON instead).
+
+Not seen before since currently 417 support is disabled, but I found
+this while experimenting with it.
+
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/cx231xx/cx231xx-417.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c
+index abb967c8bd352..6cb130eb32d58 100644
+--- a/drivers/media/usb/cx231xx/cx231xx-417.c
++++ b/drivers/media/usb/cx231xx/cx231xx-417.c
+@@ -1722,6 +1722,8 @@ static void cx231xx_video_dev_init(
+ vfd->lock = &dev->lock;
+ vfd->release = video_device_release_empty;
+ vfd->ctrl_handler = &dev->mpeg_ctrl_handler.hdl;
++ vfd->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
++ V4L2_CAP_VIDEO_CAPTURE;
+ video_set_drvdata(vfd, dev);
+ if (dev->tuner_type == TUNER_ABSENT) {
+ v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY);
+--
+2.39.5
+
--- /dev/null
+From 6df4d594e67986c11cb60e2ebe51ed447b68253e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Feb 2025 12:34:36 +0530
+Subject: media: i2c: imx219: Correct the minimum vblanking value
+
+From: David Plowman <david.plowman@raspberrypi.com>
+
+[ Upstream commit e3b82d49bf676f3c873e642038765eac32ab6d39 ]
+
+The datasheet for this sensor documents the minimum vblanking as being
+32 lines. It does fix some problems with occasional black lines at the
+bottom of images (tested on Raspberry Pi).
+
+Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
+Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
+Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/i2c/imx219.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c
+index 906aa314b7f84..eaa1496c71bb2 100644
+--- a/drivers/media/i2c/imx219.c
++++ b/drivers/media/i2c/imx219.c
+@@ -74,7 +74,7 @@
+ #define IMX219_REG_VTS CCI_REG16(0x0160)
+ #define IMX219_VTS_MAX 0xffff
+
+-#define IMX219_VBLANK_MIN 4
++#define IMX219_VBLANK_MIN 32
+
+ /* HBLANK control - read only */
+ #define IMX219_PPL_DEFAULT 3448
+--
+2.39.5
+
--- /dev/null
+From 8a3fcaaab84400909e46a900179a06d9388cdbda Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Feb 2025 18:17:31 +0900
+Subject: media: imx335: Set vblank immediately
+
+From: Paul Elder <paul.elder@ideasonboard.com>
+
+[ Upstream commit c0aa40f45fef80b4182704d1bc089cbf8ae8bed0 ]
+
+When the vblank v4l2 control is set, it does not get written to the
+hardware unless exposure is also changed. Change the behavior such that
+the vblank is written immediately when the control is set, as setting
+the vblank without changing the exposure is a valid use case (such as
+for changing the frame rate).
+
+Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
+Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/i2c/imx335.c | 21 +++++++++++++++------
+ 1 file changed, 15 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c
+index fcfd1d851bd4a..0beb80b8c4581 100644
+--- a/drivers/media/i2c/imx335.c
++++ b/drivers/media/i2c/imx335.c
+@@ -559,12 +559,14 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl)
+ imx335->vblank,
+ imx335->vblank + imx335->cur_mode->height);
+
+- return __v4l2_ctrl_modify_range(imx335->exp_ctrl,
+- IMX335_EXPOSURE_MIN,
+- imx335->vblank +
+- imx335->cur_mode->height -
+- IMX335_EXPOSURE_OFFSET,
+- 1, IMX335_EXPOSURE_DEFAULT);
++ ret = __v4l2_ctrl_modify_range(imx335->exp_ctrl,
++ IMX335_EXPOSURE_MIN,
++ imx335->vblank +
++ imx335->cur_mode->height -
++ IMX335_EXPOSURE_OFFSET,
++ 1, IMX335_EXPOSURE_DEFAULT);
++ if (ret)
++ return ret;
+ }
+
+ /*
+@@ -575,6 +577,13 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl)
+ return 0;
+
+ switch (ctrl->id) {
++ case V4L2_CID_VBLANK:
++ exposure = imx335->exp_ctrl->val;
++ analog_gain = imx335->again_ctrl->val;
++
++ ret = imx335_update_exp_gain(imx335, exposure, analog_gain);
++
++ break;
+ case V4L2_CID_EXPOSURE:
+ exposure = ctrl->val;
+ analog_gain = imx335->again_ctrl->val;
+--
+2.39.5
+
--- /dev/null
+From 73ac4ff467a0c1afd8af098e2c8ce86ca34f7662 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jan 2025 10:01:27 +0530
+Subject: media: qcom: camss: Add default case in vfe_src_pad_code
+
+From: Depeng Shao <quic_depengs@quicinc.com>
+
+[ Upstream commit 2f4204bb00b32eca3391a468d3b37e87feb96fa9 ]
+
+Add a default case in vfe_src_pad_code to get rid of a compile
+warning if a new hw enum is added.
+
+Signed-off-by: Depeng Shao <quic_depengs@quicinc.com>
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/qcom/camss/camss-vfe.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c
+index 83c5a36d071fc..8f6b0eccefb48 100644
+--- a/drivers/media/platform/qcom/camss/camss-vfe.c
++++ b/drivers/media/platform/qcom/camss/camss-vfe.c
+@@ -398,6 +398,10 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code,
+ return sink_code;
+ }
+ break;
++ default:
++ WARN(1, "Unsupported HW version: %x\n",
++ vfe->camss->res->version);
++ break;
+ }
+ return 0;
+ }
+--
+2.39.5
+
--- /dev/null
+From 99aac56eccccccd8650abeb71c9c369aaab78439 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jan 2025 10:01:28 +0530
+Subject: media: qcom: camss: csid: Only add TPG v4l2 ctrl if TPG hardware is
+ available
+
+From: Depeng Shao <quic_depengs@quicinc.com>
+
+[ Upstream commit 2f1361f862a68063f37362f1beb400e78e289581 ]
+
+There is no CSID TPG on some SoCs, so the v4l2 ctrl in CSID driver
+shouldn't be registered. Checking the supported TPG modes to indicate
+if the TPG hardware exists or not and only registering v4l2 ctrl for
+CSID only when the TPG hardware is present.
+
+Signed-off-by: Depeng Shao <quic_depengs@quicinc.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../media/platform/qcom/camss/camss-csid.c | 60 +++++++++++--------
+ 1 file changed, 35 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c
+index 858db5d4ca75c..e51f2ed3f0315 100644
+--- a/drivers/media/platform/qcom/camss/camss-csid.c
++++ b/drivers/media/platform/qcom/camss/camss-csid.c
+@@ -683,11 +683,13 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable)
+ int ret;
+
+ if (enable) {
+- ret = v4l2_ctrl_handler_setup(&csid->ctrls);
+- if (ret < 0) {
+- dev_err(csid->camss->dev,
+- "could not sync v4l2 controls: %d\n", ret);
+- return ret;
++ if (csid->testgen.nmodes != CSID_PAYLOAD_MODE_DISABLED) {
++ ret = v4l2_ctrl_handler_setup(&csid->ctrls);
++ if (ret < 0) {
++ dev_err(csid->camss->dev,
++ "could not sync v4l2 controls: %d\n", ret);
++ return ret;
++ }
+ }
+
+ if (!csid->testgen.enabled &&
+@@ -761,7 +763,8 @@ static void csid_try_format(struct csid_device *csid,
+ break;
+
+ case MSM_CSID_PAD_SRC:
+- if (csid->testgen_mode->cur.val == 0) {
++ if (csid->testgen.nmodes == CSID_PAYLOAD_MODE_DISABLED ||
++ csid->testgen_mode->cur.val == 0) {
+ /* Test generator is disabled, */
+ /* keep pad formats in sync */
+ u32 code = fmt->code;
+@@ -811,7 +814,8 @@ static int csid_enum_mbus_code(struct v4l2_subdev *sd,
+
+ code->code = csid->res->formats->formats[code->index].code;
+ } else {
+- if (csid->testgen_mode->cur.val == 0) {
++ if (csid->testgen.nmodes == CSID_PAYLOAD_MODE_DISABLED ||
++ csid->testgen_mode->cur.val == 0) {
+ struct v4l2_mbus_framefmt *sink_fmt;
+
+ sink_fmt = __csid_get_format(csid, sd_state,
+@@ -1190,7 +1194,8 @@ static int csid_link_setup(struct media_entity *entity,
+
+ /* If test generator is enabled */
+ /* do not allow a link from CSIPHY to CSID */
+- if (csid->testgen_mode->cur.val != 0)
++ if (csid->testgen.nmodes != CSID_PAYLOAD_MODE_DISABLED &&
++ csid->testgen_mode->cur.val != 0)
+ return -EBUSY;
+
+ sd = media_entity_to_v4l2_subdev(remote->entity);
+@@ -1283,24 +1288,27 @@ int msm_csid_register_entity(struct csid_device *csid,
+ MSM_CSID_NAME, csid->id);
+ v4l2_set_subdevdata(sd, csid);
+
+- ret = v4l2_ctrl_handler_init(&csid->ctrls, 1);
+- if (ret < 0) {
+- dev_err(dev, "Failed to init ctrl handler: %d\n", ret);
+- return ret;
+- }
++ if (csid->testgen.nmodes != CSID_PAYLOAD_MODE_DISABLED) {
++ ret = v4l2_ctrl_handler_init(&csid->ctrls, 1);
++ if (ret < 0) {
++ dev_err(dev, "Failed to init ctrl handler: %d\n", ret);
++ return ret;
++ }
+
+- csid->testgen_mode = v4l2_ctrl_new_std_menu_items(&csid->ctrls,
+- &csid_ctrl_ops, V4L2_CID_TEST_PATTERN,
+- csid->testgen.nmodes, 0, 0,
+- csid->testgen.modes);
++ csid->testgen_mode =
++ v4l2_ctrl_new_std_menu_items(&csid->ctrls,
++ &csid_ctrl_ops, V4L2_CID_TEST_PATTERN,
++ csid->testgen.nmodes, 0, 0,
++ csid->testgen.modes);
+
+- if (csid->ctrls.error) {
+- dev_err(dev, "Failed to init ctrl: %d\n", csid->ctrls.error);
+- ret = csid->ctrls.error;
+- goto free_ctrl;
+- }
++ if (csid->ctrls.error) {
++ dev_err(dev, "Failed to init ctrl: %d\n", csid->ctrls.error);
++ ret = csid->ctrls.error;
++ goto free_ctrl;
++ }
+
+- csid->subdev.ctrl_handler = &csid->ctrls;
++ csid->subdev.ctrl_handler = &csid->ctrls;
++ }
+
+ ret = csid_init_formats(sd, NULL);
+ if (ret < 0) {
+@@ -1331,7 +1339,8 @@ int msm_csid_register_entity(struct csid_device *csid,
+ media_cleanup:
+ media_entity_cleanup(&sd->entity);
+ free_ctrl:
+- v4l2_ctrl_handler_free(&csid->ctrls);
++ if (csid->testgen.nmodes != CSID_PAYLOAD_MODE_DISABLED)
++ v4l2_ctrl_handler_free(&csid->ctrls);
+
+ return ret;
+ }
+@@ -1344,7 +1353,8 @@ void msm_csid_unregister_entity(struct csid_device *csid)
+ {
+ v4l2_device_unregister_subdev(&csid->subdev);
+ media_entity_cleanup(&csid->subdev.entity);
+- v4l2_ctrl_handler_free(&csid->ctrls);
++ if (csid->testgen.nmodes != CSID_PAYLOAD_MODE_DISABLED)
++ v4l2_ctrl_handler_free(&csid->ctrls);
+ }
+
+ inline bool csid_is_lite(struct csid_device *csid)
+--
+2.39.5
+
--- /dev/null
+From f6498b7806e50e1ae786d97501c98dfde3aa242a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Jan 2025 17:07:01 +0100
+Subject: media: tc358746: improve calculation of the D-PHY timing registers
+
+From: Matthias Fend <matthias.fend@emfend.at>
+
+[ Upstream commit 78d7265e2e1ce349e7f3c6a085f2b66d7b73f4ca ]
+
+When calculating D-PHY registers, using data rates that are not multiples
+of 16 can lead to precision loss in division operations. This can result in
+register values that produce timing violations against the MIPI standard.
+
+An example:
+cfg->hs_clk_rate = 294MHz
+hf_clk = 18
+
+If the desired value in cfg->init is 100us, which is the minimum allowed
+value, then the LINEINITCNT register is calculated as 1799. But since the
+actual clock is 18.375MHz instead of 18MHz, this setting results in a time
+that is shorter than 100us and thus violates the standard. The correct
+value for LINEINITCNT would be 1837.
+
+Improve the precision of calculations by using Hz instead of MHz as unit.
+
+Signed-off-by: Matthias Fend <matthias.fend@emfend.at>
+Reviewed-by: Marco Felsch <m.felsch@pengutronix.de>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/i2c/tc358746.c | 19 +++++++------------
+ 1 file changed, 7 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/media/i2c/tc358746.c b/drivers/media/i2c/tc358746.c
+index 389582420ba78..048a1a381b333 100644
+--- a/drivers/media/i2c/tc358746.c
++++ b/drivers/media/i2c/tc358746.c
+@@ -460,24 +460,20 @@ static int tc358746_apply_misc_config(struct tc358746 *tc358746)
+ return err;
+ }
+
+-/* Use MHz as base so the div needs no u64 */
+-static u32 tc358746_cfg_to_cnt(unsigned int cfg_val,
+- unsigned int clk_mhz,
+- unsigned int time_base)
++static u32 tc358746_cfg_to_cnt(unsigned long cfg_val, unsigned long clk_hz,
++ unsigned long long time_base)
+ {
+- return DIV_ROUND_UP(cfg_val * clk_mhz, time_base);
++ return div64_u64((u64)cfg_val * clk_hz + time_base - 1, time_base);
+ }
+
+-static u32 tc358746_ps_to_cnt(unsigned int cfg_val,
+- unsigned int clk_mhz)
++static u32 tc358746_ps_to_cnt(unsigned long cfg_val, unsigned long clk_hz)
+ {
+- return tc358746_cfg_to_cnt(cfg_val, clk_mhz, USEC_PER_SEC);
++ return tc358746_cfg_to_cnt(cfg_val, clk_hz, PSEC_PER_SEC);
+ }
+
+-static u32 tc358746_us_to_cnt(unsigned int cfg_val,
+- unsigned int clk_mhz)
++static u32 tc358746_us_to_cnt(unsigned long cfg_val, unsigned long clk_hz)
+ {
+- return tc358746_cfg_to_cnt(cfg_val, clk_mhz, 1);
++ return tc358746_cfg_to_cnt(cfg_val, clk_hz, USEC_PER_SEC);
+ }
+
+ static int tc358746_apply_dphy_config(struct tc358746 *tc358746)
+@@ -492,7 +488,6 @@ static int tc358746_apply_dphy_config(struct tc358746 *tc358746)
+
+ /* The hs_byte_clk is also called SYSCLK in the excel sheet */
+ hs_byte_clk = cfg->hs_clk_rate / 8;
+- hs_byte_clk /= HZ_PER_MHZ;
+ hf_clk = hs_byte_clk / 2;
+
+ val = tc358746_us_to_cnt(cfg->init, hf_clk) - 1;
+--
+2.39.5
+
--- /dev/null
+From 57c7200ed48395cfd92e3c688fa4c6c7a3a8a638 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Dec 2024 16:00:16 +0100
+Subject: media: test-drivers: vivid: don't call schedule in loop
+
+From: Hans Verkuil <hverkuil@xs4all.nl>
+
+[ Upstream commit e4740118b752005cbed339aec9a1d1c43620e0b9 ]
+
+Artem reported that the CPU load was 100% when capturing from
+vivid at low resolution with ffmpeg.
+
+This was caused by:
+
+while (time_is_after_jiffies(cur_jiffies + wait_jiffies) &&
+ !kthread_should_stop())
+ schedule();
+
+If there are no other processes running that can be scheduled,
+then this is basically a busy-loop.
+
+Change it to wait_event_interruptible_timeout() which doesn't
+have that problem.
+
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Reported-by: Artem S. Tashkinov <aros@gmx.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219570
+Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/test-drivers/vivid/vivid-kthread-cap.c | 11 ++++++++---
+ drivers/media/test-drivers/vivid/vivid-kthread-out.c | 11 ++++++++---
+ .../media/test-drivers/vivid/vivid-kthread-touch.c | 11 ++++++++---
+ drivers/media/test-drivers/vivid/vivid-sdr-cap.c | 11 ++++++++---
+ 4 files changed, 32 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/media/test-drivers/vivid/vivid-kthread-cap.c b/drivers/media/test-drivers/vivid/vivid-kthread-cap.c
+index 669bd96da4c79..273e8ed8c2a90 100644
+--- a/drivers/media/test-drivers/vivid/vivid-kthread-cap.c
++++ b/drivers/media/test-drivers/vivid/vivid-kthread-cap.c
+@@ -789,9 +789,14 @@ static int vivid_thread_vid_cap(void *data)
+ next_jiffies_since_start = jiffies_since_start;
+
+ wait_jiffies = next_jiffies_since_start - jiffies_since_start;
+- while (time_is_after_jiffies(cur_jiffies + wait_jiffies) &&
+- !kthread_should_stop())
+- schedule();
++ if (!time_is_after_jiffies(cur_jiffies + wait_jiffies))
++ continue;
++
++ wait_queue_head_t wait;
++
++ init_waitqueue_head(&wait);
++ wait_event_interruptible_timeout(wait, kthread_should_stop(),
++ cur_jiffies + wait_jiffies - jiffies);
+ }
+ dprintk(dev, 1, "Video Capture Thread End\n");
+ return 0;
+diff --git a/drivers/media/test-drivers/vivid/vivid-kthread-out.c b/drivers/media/test-drivers/vivid/vivid-kthread-out.c
+index fac6208b51da8..015a7b166a1e6 100644
+--- a/drivers/media/test-drivers/vivid/vivid-kthread-out.c
++++ b/drivers/media/test-drivers/vivid/vivid-kthread-out.c
+@@ -235,9 +235,14 @@ static int vivid_thread_vid_out(void *data)
+ next_jiffies_since_start = jiffies_since_start;
+
+ wait_jiffies = next_jiffies_since_start - jiffies_since_start;
+- while (time_is_after_jiffies(cur_jiffies + wait_jiffies) &&
+- !kthread_should_stop())
+- schedule();
++ if (!time_is_after_jiffies(cur_jiffies + wait_jiffies))
++ continue;
++
++ wait_queue_head_t wait;
++
++ init_waitqueue_head(&wait);
++ wait_event_interruptible_timeout(wait, kthread_should_stop(),
++ cur_jiffies + wait_jiffies - jiffies);
+ }
+ dprintk(dev, 1, "Video Output Thread End\n");
+ return 0;
+diff --git a/drivers/media/test-drivers/vivid/vivid-kthread-touch.c b/drivers/media/test-drivers/vivid/vivid-kthread-touch.c
+index fa711ee36a3fb..c862689786b69 100644
+--- a/drivers/media/test-drivers/vivid/vivid-kthread-touch.c
++++ b/drivers/media/test-drivers/vivid/vivid-kthread-touch.c
+@@ -135,9 +135,14 @@ static int vivid_thread_touch_cap(void *data)
+ next_jiffies_since_start = jiffies_since_start;
+
+ wait_jiffies = next_jiffies_since_start - jiffies_since_start;
+- while (time_is_after_jiffies(cur_jiffies + wait_jiffies) &&
+- !kthread_should_stop())
+- schedule();
++ if (!time_is_after_jiffies(cur_jiffies + wait_jiffies))
++ continue;
++
++ wait_queue_head_t wait;
++
++ init_waitqueue_head(&wait);
++ wait_event_interruptible_timeout(wait, kthread_should_stop(),
++ cur_jiffies + wait_jiffies - jiffies);
+ }
+ dprintk(dev, 1, "Touch Capture Thread End\n");
+ return 0;
+diff --git a/drivers/media/test-drivers/vivid/vivid-sdr-cap.c b/drivers/media/test-drivers/vivid/vivid-sdr-cap.c
+index 38cda33dffb2a..97cfc58b70571 100644
+--- a/drivers/media/test-drivers/vivid/vivid-sdr-cap.c
++++ b/drivers/media/test-drivers/vivid/vivid-sdr-cap.c
+@@ -206,9 +206,14 @@ static int vivid_thread_sdr_cap(void *data)
+ next_jiffies_since_start = jiffies_since_start;
+
+ wait_jiffies = next_jiffies_since_start - jiffies_since_start;
+- while (time_is_after_jiffies(cur_jiffies + wait_jiffies) &&
+- !kthread_should_stop())
+- schedule();
++ if (!time_is_after_jiffies(cur_jiffies + wait_jiffies))
++ continue;
++
++ wait_queue_head_t wait;
++
++ init_waitqueue_head(&wait);
++ wait_event_interruptible_timeout(wait, kthread_should_stop(),
++ cur_jiffies + wait_jiffies - jiffies);
+ }
+ dprintk(dev, 1, "SDR Capture Thread End\n");
+ return 0;
+--
+2.39.5
+
--- /dev/null
+From 985a81d3a04e7d324421ea5ebb7b25cff8dc1685 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Feb 2025 11:55:51 +0000
+Subject: media: uvcvideo: Add sanity check to uvc_ioctl_xu_ctrl_map
+
+From: Ricardo Ribalda <ribalda@chromium.org>
+
+[ Upstream commit 990262fdfce24d6055df9711424343d94d829e6a ]
+
+Do not process unknown data types.
+
+Tested-by: Yunke Cao <yunkec@google.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Link: https://lore.kernel.org/r/20250203-uvc-roi-v17-15-5900a9fed613@chromium.org
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/uvc/uvc_v4l2.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
+index 7bcd706281daf..cb7d9fb589fca 100644
+--- a/drivers/media/usb/uvc/uvc_v4l2.c
++++ b/drivers/media/usb/uvc/uvc_v4l2.c
+@@ -106,6 +106,12 @@ static int uvc_ioctl_xu_ctrl_map(struct uvc_video_chain *chain,
+ struct uvc_control_mapping *map;
+ int ret;
+
++ if (xmap->data_type > UVC_CTRL_DATA_TYPE_BITMASK) {
++ uvc_dbg(chain->dev, CONTROL,
++ "Unsupported UVC data type %u\n", xmap->data_type);
++ return -EINVAL;
++ }
++
+ map = kzalloc(sizeof(*map), GFP_KERNEL);
+ if (map == NULL)
+ return -ENOMEM;
+--
+2.39.5
+
--- /dev/null
+From ba2a6e3f7382143a3c8b2839438f74a4046478eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Feb 2025 11:55:40 +0000
+Subject: media: uvcvideo: Handle uvc menu translation inside uvc_get_le_value
+
+From: Ricardo Ribalda <ribalda@chromium.org>
+
+[ Upstream commit 9109a0b4cb10fd681e9c6e9a4497a6fec5b91c39 ]
+
+map->get() gets a value from an uvc_control in "UVC format" and converts
+it to a value that can be consumed by v4l2.
+
+Instead of using a special get function for V4L2_CTRL_TYPE_MENU, we
+were converting from uvc_get_le_value in two different places.
+
+Move the conversion to uvc_get_le_value().
+
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Tested-by: Yunke Cao <yunkec@google.com>
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Link: https://lore.kernel.org/r/20250203-uvc-roi-v17-4-5900a9fed613@chromium.org
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/uvc/uvc_ctrl.c | 77 +++++++++++++-------------------
+ 1 file changed, 32 insertions(+), 45 deletions(-)
+
+diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
+index 4837d8df9c038..58d1bc80253e8 100644
+--- a/drivers/media/usb/uvc/uvc_ctrl.c
++++ b/drivers/media/usb/uvc/uvc_ctrl.c
+@@ -862,6 +862,25 @@ static inline void uvc_clear_bit(u8 *data, int bit)
+ data[bit >> 3] &= ~(1 << (bit & 7));
+ }
+
++static s32 uvc_menu_to_v4l2_menu(struct uvc_control_mapping *mapping, s32 val)
++{
++ unsigned int i;
++
++ for (i = 0; BIT(i) <= mapping->menu_mask; ++i) {
++ u32 menu_value;
++
++ if (!test_bit(i, &mapping->menu_mask))
++ continue;
++
++ menu_value = uvc_mapping_get_menu_value(mapping, i);
++
++ if (menu_value == val)
++ return i;
++ }
++
++ return val;
++}
++
+ /*
+ * Extract the bit string specified by mapping->offset and mapping->size
+ * from the little-endian data stored at 'data' and return the result as
+@@ -896,6 +915,16 @@ static s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
+ if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED)
+ value |= -(value & (1 << (mapping->size - 1)));
+
++ /* If it is a menu, convert from uvc to v4l2. */
++ if (mapping->v4l2_type != V4L2_CTRL_TYPE_MENU)
++ return value;
++
++ switch (query) {
++ case UVC_GET_CUR:
++ case UVC_GET_DEF:
++ return uvc_menu_to_v4l2_menu(mapping, value);
++ }
++
+ return value;
+ }
+
+@@ -1060,32 +1089,6 @@ static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain,
+ return 0;
+ }
+
+-static s32 __uvc_ctrl_get_value(struct uvc_control_mapping *mapping,
+- const u8 *data)
+-{
+- s32 value = mapping->get(mapping, UVC_GET_CUR, data);
+-
+- if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
+- unsigned int i;
+-
+- for (i = 0; BIT(i) <= mapping->menu_mask; ++i) {
+- u32 menu_value;
+-
+- if (!test_bit(i, &mapping->menu_mask))
+- continue;
+-
+- menu_value = uvc_mapping_get_menu_value(mapping, i);
+-
+- if (menu_value == value) {
+- value = i;
+- break;
+- }
+- }
+- }
+-
+- return value;
+-}
+-
+ static int __uvc_ctrl_load_cur(struct uvc_video_chain *chain,
+ struct uvc_control *ctrl)
+ {
+@@ -1136,8 +1139,8 @@ static int __uvc_ctrl_get(struct uvc_video_chain *chain,
+ if (ret < 0)
+ return ret;
+
+- *value = __uvc_ctrl_get_value(mapping,
+- uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
++ *value = mapping->get(mapping, UVC_GET_CUR,
++ uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
+
+ return 0;
+ }
+@@ -1287,7 +1290,6 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
+ {
+ struct uvc_control_mapping *master_map = NULL;
+ struct uvc_control *master_ctrl = NULL;
+- unsigned int i;
+
+ memset(v4l2_ctrl, 0, sizeof(*v4l2_ctrl));
+ v4l2_ctrl->id = mapping->id;
+@@ -1330,21 +1332,6 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
+ v4l2_ctrl->minimum = ffs(mapping->menu_mask) - 1;
+ v4l2_ctrl->maximum = fls(mapping->menu_mask) - 1;
+ v4l2_ctrl->step = 1;
+-
+- for (i = 0; BIT(i) <= mapping->menu_mask; ++i) {
+- u32 menu_value;
+-
+- if (!test_bit(i, &mapping->menu_mask))
+- continue;
+-
+- menu_value = uvc_mapping_get_menu_value(mapping, i);
+-
+- if (menu_value == v4l2_ctrl->default_value) {
+- v4l2_ctrl->default_value = i;
+- break;
+- }
+- }
+-
+ return 0;
+
+ case V4L2_CTRL_TYPE_BOOLEAN:
+@@ -1627,7 +1614,7 @@ void uvc_ctrl_status_event(struct uvc_video_chain *chain,
+ uvc_ctrl_set_handle(handle, ctrl, NULL);
+
+ list_for_each_entry(mapping, &ctrl->info.mappings, list) {
+- s32 value = __uvc_ctrl_get_value(mapping, data);
++ s32 value = mapping->get(mapping, UVC_GET_CUR, data);
+
+ /*
+ * handle may be NULL here if the device sends auto-update
+--
+2.39.5
+
--- /dev/null
+From ad7def4200d9e66885c8bcbb4ff83bdbbd6dc6d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Dec 2024 10:48:49 +0200
+Subject: media: v4l: Memset argument to 0 before calling get_mbus_config pad
+ op
+
+From: Sakari Ailus <sakari.ailus@linux.intel.com>
+
+[ Upstream commit 91d6a99acfa5ce9f95ede775074b80f7193bd717 ]
+
+Memset the config argument to get_mbus_config V4L2 sub-device pad
+operation to zero before calling the operation. This ensures the callers
+don't need to bother with it nor the implementations need to set all
+fields that may not be relevant to them.
+
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/v4l2-core/v4l2-subdev.c | 2 ++
+ include/media/v4l2-subdev.h | 4 +++-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
+index 3a4ba08810d24..1193852bad599 100644
+--- a/drivers/media/v4l2-core/v4l2-subdev.c
++++ b/drivers/media/v4l2-core/v4l2-subdev.c
+@@ -439,6 +439,8 @@ static int call_enum_dv_timings(struct v4l2_subdev *sd,
+ static int call_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
+ struct v4l2_mbus_config *config)
+ {
++ memset(config, 0, sizeof(*config));
++
+ return check_pad(sd, pad) ? :
+ sd->ops->pad->get_mbus_config(sd, pad, config);
+ }
+diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
+index 8daa0929865cf..43343f1586d13 100644
+--- a/include/media/v4l2-subdev.h
++++ b/include/media/v4l2-subdev.h
+@@ -821,7 +821,9 @@ struct v4l2_subdev_state {
+ * possible configuration from the remote end, likely calling
+ * this operation as close as possible to stream on time. The
+ * operation shall fail if the pad index it has been called on
+- * is not valid or in case of unrecoverable failures.
++ * is not valid or in case of unrecoverable failures. The
++ * config argument has been memset to 0 just before calling
++ * the op.
+ *
+ * @set_routing: Enable or disable data connection routes described in the
+ * subdevice routing table. Subdevs that implement this operation
+--
+2.39.5
+
--- /dev/null
+From 7344e327ada73f2c74c910e3688b95cbeee3c348 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Mar 2025 15:12:03 +0100
+Subject: mei: vsc: Use struct vsc_tp_packet as vsc-tp tx_buf and rx_buf type
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit f88c0c72ffb014e5eba676ee337c4eb3b1d6a119 ]
+
+vsc_tp.tx_buf and vsc_tp.rx_buf point to a struct vsc_tp_packet, use
+the correct type instead of "void *" and use sizeof(*ptr) when allocating
+memory for these buffers.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Alexander Usyskin <alexander.usyskin@intel.com>
+Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Link: https://lore.kernel.org/r/20250318141203.94342-3-hdegoede@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/misc/mei/vsc-tp.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/misc/mei/vsc-tp.c b/drivers/misc/mei/vsc-tp.c
+index eb51fbe8d92fb..ad7c7f1573191 100644
+--- a/drivers/misc/mei/vsc-tp.c
++++ b/drivers/misc/mei/vsc-tp.c
+@@ -71,8 +71,8 @@ struct vsc_tp {
+ u32 seq;
+
+ /* command buffer */
+- void *tx_buf;
+- void *rx_buf;
++ struct vsc_tp_packet *tx_buf;
++ struct vsc_tp_packet *rx_buf;
+
+ atomic_t assert_cnt;
+ wait_queue_head_t xfer_wait;
+@@ -164,7 +164,7 @@ static int vsc_tp_xfer_helper(struct vsc_tp *tp, struct vsc_tp_packet *pkt,
+ {
+ int ret, offset = 0, cpy_len, src_len, dst_len = sizeof(struct vsc_tp_packet_hdr);
+ int next_xfer_len = VSC_TP_PACKET_SIZE(pkt) + VSC_TP_XFER_TIMEOUT_BYTES;
+- u8 *src, *crc_src, *rx_buf = tp->rx_buf;
++ u8 *src, *crc_src, *rx_buf = (u8 *)tp->rx_buf;
+ int count_down = VSC_TP_MAX_XFER_COUNT;
+ u32 recv_crc = 0, crc = ~0;
+ struct vsc_tp_packet_hdr ack;
+@@ -324,7 +324,7 @@ int vsc_tp_rom_xfer(struct vsc_tp *tp, const void *obuf, void *ibuf, size_t len)
+ guard(mutex)(&tp->mutex);
+
+ /* rom xfer is big endian */
+- cpu_to_be32_array(tp->tx_buf, obuf, words);
++ cpu_to_be32_array((u32 *)tp->tx_buf, obuf, words);
+
+ ret = read_poll_timeout(gpiod_get_value_cansleep, ret,
+ !ret, VSC_TP_ROM_XFER_POLL_DELAY_US,
+@@ -340,7 +340,7 @@ int vsc_tp_rom_xfer(struct vsc_tp *tp, const void *obuf, void *ibuf, size_t len)
+ return ret;
+
+ if (ibuf)
+- be32_to_cpu_array(ibuf, tp->rx_buf, words);
++ be32_to_cpu_array(ibuf, (u32 *)tp->rx_buf, words);
+
+ return ret;
+ }
+@@ -496,11 +496,11 @@ static int vsc_tp_probe(struct spi_device *spi)
+ if (!tp)
+ return -ENOMEM;
+
+- tp->tx_buf = devm_kzalloc(dev, VSC_TP_MAX_XFER_SIZE, GFP_KERNEL);
++ tp->tx_buf = devm_kzalloc(dev, sizeof(*tp->tx_buf), GFP_KERNEL);
+ if (!tp->tx_buf)
+ return -ENOMEM;
+
+- tp->rx_buf = devm_kzalloc(dev, VSC_TP_MAX_XFER_SIZE, GFP_KERNEL);
++ tp->rx_buf = devm_kzalloc(dev, sizeof(*tp->rx_buf), GFP_KERNEL);
+ if (!tp->rx_buf)
+ return -ENOMEM;
+
+--
+2.39.5
+
--- /dev/null
+From eb326e717c2073c7dd5fc984e9dc6679eb024743 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Feb 2025 09:58:32 -0600
+Subject: mfd: axp20x: AXP717: Add AXP717_TS_PIN_CFG to writeable regs
+
+From: Chris Morgan <macromorgan@hotmail.com>
+
+[ Upstream commit bfad07fe298bfba0c7ddab87c5b5325970203a1e ]
+
+Add AXP717_TS_PIN_CFG (register 0x50) to the table of writeable
+registers so that the temperature sensor can be configured by the
+battery driver.
+
+Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
+Link: https://lore.kernel.org/r/20250204155835.161973-3-macroalpha82@gmail.com
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mfd/axp20x.c | 1 +
+ include/linux/mfd/axp20x.h | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
+index 4051551757f2d..3780929039710 100644
+--- a/drivers/mfd/axp20x.c
++++ b/drivers/mfd/axp20x.c
+@@ -214,6 +214,7 @@ static const struct regmap_range axp717_writeable_ranges[] = {
+ regmap_reg_range(AXP717_VSYS_V_POWEROFF, AXP717_VSYS_V_POWEROFF),
+ regmap_reg_range(AXP717_IRQ0_EN, AXP717_IRQ4_EN),
+ regmap_reg_range(AXP717_IRQ0_STATE, AXP717_IRQ4_STATE),
++ regmap_reg_range(AXP717_TS_PIN_CFG, AXP717_TS_PIN_CFG),
+ regmap_reg_range(AXP717_ICC_CHG_SET, AXP717_CV_CHG_SET),
+ regmap_reg_range(AXP717_DCDC_OUTPUT_CONTROL, AXP717_CPUSLDO_CONTROL),
+ regmap_reg_range(AXP717_ADC_CH_EN_CONTROL, AXP717_ADC_CH_EN_CONTROL),
+diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
+index f4dfc1871a95b..d1c21ad6440d1 100644
+--- a/include/linux/mfd/axp20x.h
++++ b/include/linux/mfd/axp20x.h
+@@ -135,6 +135,7 @@ enum axp20x_variants {
+ #define AXP717_IRQ2_STATE 0x4a
+ #define AXP717_IRQ3_STATE 0x4b
+ #define AXP717_IRQ4_STATE 0x4c
++#define AXP717_TS_PIN_CFG 0x50
+ #define AXP717_ICC_CHG_SET 0x62
+ #define AXP717_ITERM_CHG_SET 0x63
+ #define AXP717_CV_CHG_SET 0x64
+--
+2.39.5
+
--- /dev/null
+From 063cc2f1f9e40e18b041d8c527b23ef24540a1ab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Feb 2025 11:37:23 -0600
+Subject: mfd: tps65219: Remove TPS65219_REG_TI_DEV_ID check
+
+From: Shree Ramamoorthy <s-ramamoorthy@ti.com>
+
+[ Upstream commit 76b58d5111fdcffce615beb71520bc7a6f1742c9 ]
+
+The chipid macro/variable and regmap_read function call is not needed
+because the TPS65219_REG_TI_DEV_ID register value is not a consistent value
+across TPS65219 PMIC config versions. Reading from the DEV_ID register
+without a consistent value to compare it to isn't useful. There isn't a
+way to verify the match data ID is the same ID read from the DEV_ID device
+register. 0xF0 isn't a DEV_ID value consistent across TPS65219 NVM
+configurations.
+
+For TPS65215, there is a consistent value in bits 5-0 of the DEV_ID
+register. However, there are other error checks in place within probe()
+that apply to both PMICs rather than keeping this isolated check for one
+PMIC.
+
+Signed-off-by: Shree Ramamoorthy <s-ramamoorthy@ti.com>
+Link: https://lore.kernel.org/r/20250206173725.386720-4-s-ramamoorthy@ti.com
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mfd/tps65219.c | 7 -------
+ 1 file changed, 7 deletions(-)
+
+diff --git a/drivers/mfd/tps65219.c b/drivers/mfd/tps65219.c
+index 57ff5cb294a66..d3b77abec786e 100644
+--- a/drivers/mfd/tps65219.c
++++ b/drivers/mfd/tps65219.c
+@@ -228,7 +228,6 @@ static const struct regmap_irq_chip tps65219_irq_chip = {
+ static int tps65219_probe(struct i2c_client *client)
+ {
+ struct tps65219 *tps;
+- unsigned int chipid;
+ bool pwr_button;
+ int ret;
+
+@@ -253,12 +252,6 @@ static int tps65219_probe(struct i2c_client *client)
+ if (ret)
+ return ret;
+
+- ret = regmap_read(tps->regmap, TPS65219_REG_TI_DEV_ID, &chipid);
+- if (ret) {
+- dev_err(tps->dev, "Failed to read device ID: %d\n", ret);
+- return ret;
+- }
+-
+ ret = devm_mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO,
+ tps65219_cells, ARRAY_SIZE(tps65219_cells),
+ NULL, 0, regmap_irq_get_domain(tps->irq_data));
+--
+2.39.5
+
--- /dev/null
+From ffa0cd408bd7ce1b2902fd51fe50b692e5e76ac2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jan 2025 13:32:48 +0100
+Subject: MIPS: pm-cps: Use per-CPU variables as per-CPU, not per-core
+
+From: Paul Burton <paulburton@kernel.org>
+
+[ Upstream commit 00a134fc2bb4a5f8fada58cf7ff4259149691d64 ]
+
+The pm-cps code has up until now used per-CPU variables indexed by core,
+rather than CPU number, in order to share data amongst sibling CPUs (ie.
+VPs/threads in a core). This works fine for single cluster systems, but
+with multi-cluster systems a core number is no longer unique in the
+system, leading to sharing between CPUs that are not actually siblings.
+
+Avoid this issue by using per-CPU variables as they are more generally
+used - ie. access them using CPU numbers rather than core numbers.
+Sharing between siblings is then accomplished by:
+ - Assigning the same pointer to entries for each sibling CPU for the
+ nc_asm_enter & ready_count variables, which allow this by virtue of
+ being per-CPU pointers.
+
+ - Indexing by the first CPU set in a CPUs cpu_sibling_map in the case
+ of pm_barrier, for which we can't use the previous approach because
+ the per-CPU variable is not a pointer.
+
+Signed-off-by: Paul Burton <paulburton@kernel.org>
+Signed-off-by: Dragan Mladjenovic <dragan.mladjenovic@syrmia.com>
+Signed-off-by: Aleksandar Rikalo <arikalo@gmail.com>
+Tested-by: Serge Semin <fancer.lancer@gmail.com>
+Tested-by: Gregory CLEMENT <gregory.clement@bootlin.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/kernel/pm-cps.c | 30 +++++++++++++++++-------------
+ 1 file changed, 17 insertions(+), 13 deletions(-)
+
+diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c
+index d09ca77e624d7..9369a8dc385e2 100644
+--- a/arch/mips/kernel/pm-cps.c
++++ b/arch/mips/kernel/pm-cps.c
+@@ -57,10 +57,7 @@ static DEFINE_PER_CPU_ALIGNED(u32*, ready_count);
+ /* Indicates online CPUs coupled with the current CPU */
+ static DEFINE_PER_CPU_ALIGNED(cpumask_t, online_coupled);
+
+-/*
+- * Used to synchronize entry to deep idle states. Actually per-core rather
+- * than per-CPU.
+- */
++/* Used to synchronize entry to deep idle states */
+ static DEFINE_PER_CPU_ALIGNED(atomic_t, pm_barrier);
+
+ /* Saved CPU state across the CPS_PM_POWER_GATED state */
+@@ -112,9 +109,10 @@ int cps_pm_enter_state(enum cps_pm_state state)
+ cps_nc_entry_fn entry;
+ struct core_boot_config *core_cfg;
+ struct vpe_boot_config *vpe_cfg;
++ atomic_t *barrier;
+
+ /* Check that there is an entry function for this state */
+- entry = per_cpu(nc_asm_enter, core)[state];
++ entry = per_cpu(nc_asm_enter, cpu)[state];
+ if (!entry)
+ return -EINVAL;
+
+@@ -150,7 +148,7 @@ int cps_pm_enter_state(enum cps_pm_state state)
+ smp_mb__after_atomic();
+
+ /* Create a non-coherent mapping of the core ready_count */
+- core_ready_count = per_cpu(ready_count, core);
++ core_ready_count = per_cpu(ready_count, cpu);
+ nc_addr = kmap_noncoherent(virt_to_page(core_ready_count),
+ (unsigned long)core_ready_count);
+ nc_addr += ((unsigned long)core_ready_count & ~PAGE_MASK);
+@@ -158,7 +156,8 @@ int cps_pm_enter_state(enum cps_pm_state state)
+
+ /* Ensure ready_count is zero-initialised before the assembly runs */
+ WRITE_ONCE(*nc_core_ready_count, 0);
+- coupled_barrier(&per_cpu(pm_barrier, core), online);
++ barrier = &per_cpu(pm_barrier, cpumask_first(&cpu_sibling_map[cpu]));
++ coupled_barrier(barrier, online);
+
+ /* Run the generated entry code */
+ left = entry(online, nc_core_ready_count);
+@@ -629,12 +628,14 @@ static void *cps_gen_entry_code(unsigned cpu, enum cps_pm_state state)
+
+ static int cps_pm_online_cpu(unsigned int cpu)
+ {
+- enum cps_pm_state state;
+- unsigned core = cpu_core(&cpu_data[cpu]);
++ unsigned int sibling, core;
+ void *entry_fn, *core_rc;
++ enum cps_pm_state state;
++
++ core = cpu_core(&cpu_data[cpu]);
+
+ for (state = CPS_PM_NC_WAIT; state < CPS_PM_STATE_COUNT; state++) {
+- if (per_cpu(nc_asm_enter, core)[state])
++ if (per_cpu(nc_asm_enter, cpu)[state])
+ continue;
+ if (!test_bit(state, state_support))
+ continue;
+@@ -646,16 +647,19 @@ static int cps_pm_online_cpu(unsigned int cpu)
+ clear_bit(state, state_support);
+ }
+
+- per_cpu(nc_asm_enter, core)[state] = entry_fn;
++ for_each_cpu(sibling, &cpu_sibling_map[cpu])
++ per_cpu(nc_asm_enter, sibling)[state] = entry_fn;
+ }
+
+- if (!per_cpu(ready_count, core)) {
++ if (!per_cpu(ready_count, cpu)) {
+ core_rc = kmalloc(sizeof(u32), GFP_KERNEL);
+ if (!core_rc) {
+ pr_err("Failed allocate core %u ready_count\n", core);
+ return -ENOMEM;
+ }
+- per_cpu(ready_count, core) = core_rc;
++
++ for_each_cpu(sibling, &cpu_sibling_map[cpu])
++ per_cpu(ready_count, sibling) = core_rc;
+ }
+
+ return 0;
+--
+2.39.5
+
--- /dev/null
+From 5fa8e0fd560852226d63f065e876509f485161ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 Jun 2020 10:54:35 +0800
+Subject: MIPS: Use arch specific syscall name match function
+
+From: Bibo Mao <maobibo@loongson.cn>
+
+[ Upstream commit 756276ce78d5624dc814f9d99f7d16c8fd51076e ]
+
+On MIPS system, most of the syscall function name begin with prefix
+sys_. Some syscalls are special such as clone/fork, function name of
+these begin with __sys_. Since scratch registers need be saved in
+stack when these system calls happens.
+
+With ftrace system call method, system call functions are declared with
+SYSCALL_DEFINEx, metadata of the system call symbol name begins with
+sys_. Here mips specific function arch_syscall_match_sym_name is used to
+compare function name between sys_call_table[] and metadata of syscall
+symbol.
+
+Signed-off-by: Bibo Mao <maobibo@loongson.cn>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/include/asm/ftrace.h | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h
+index dc025888f6d28..b41fc10446688 100644
+--- a/arch/mips/include/asm/ftrace.h
++++ b/arch/mips/include/asm/ftrace.h
+@@ -91,4 +91,20 @@ void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra,
+
+ #endif /* __ASSEMBLY__ */
+ #endif /* CONFIG_FUNCTION_TRACER */
++
++#ifdef CONFIG_FTRACE_SYSCALLS
++#ifndef __ASSEMBLY__
++/*
++ * Some syscall entry functions on mips start with "__sys_" (fork and clone,
++ * for instance). We should also match the sys_ variant with those.
++ */
++#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
++static inline bool arch_syscall_match_sym_name(const char *sym,
++ const char *name)
++{
++ return !strcmp(sym, name) ||
++ (!strncmp(sym, "__sys_", 6) && !strcmp(sym + 6, name + 4));
++}
++#endif /* __ASSEMBLY__ */
++#endif /* CONFIG_FTRACE_SYSCALLS */
+ #endif /* _ASM_MIPS_FTRACE_H */
+--
+2.39.5
+
--- /dev/null
+From da9a781a08da1733c44b7de6c9f0a88461d62e48 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jan 2025 13:01:48 +0100
+Subject: misc: pci_endpoint_test: Give disabled BARs a distinct error code
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Niklas Cassel <cassel@kernel.org>
+
+[ Upstream commit 7e80bbef1d697dbce7a39cfad0df770880fe3f29 ]
+
+The current code returns -ENOMEM if test->bar[barno] is NULL.
+
+There can be two reasons why test->bar[barno] is NULL:
+
+ 1) The pci_ioremap_bar() call in pci_endpoint_test_probe() failed.
+ 2) The BAR was skipped, because it is disabled by the endpoint.
+
+Many PCI endpoint controller drivers will disable all BARs in their
+init function. A disabled BAR will have a size of 0.
+
+A PCI endpoint function driver will be able to enable any BAR that
+is not marked as BAR_RESERVED (which means that the BAR should not
+be touched by the EPF driver).
+
+Thus, perform check if the size is 0, before checking if
+test->bar[barno] is NULL, such that we can return different errors.
+
+This will allow the selftests to return SKIP instead of FAIL for
+disabled BARs.
+
+Signed-off-by: Niklas Cassel <cassel@kernel.org>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Link: https://lore.kernel.org/r/20250123120147.3603409-3-cassel@kernel.org
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+[kwilczynski: commit log]
+Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/misc/pci_endpoint_test.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
+index e22afb420d099..f05256b7c2084 100644
+--- a/drivers/misc/pci_endpoint_test.c
++++ b/drivers/misc/pci_endpoint_test.c
+@@ -287,11 +287,13 @@ static bool pci_endpoint_test_bar(struct pci_endpoint_test *test,
+ void *read_buf __free(kfree) = NULL;
+ struct pci_dev *pdev = test->pdev;
+
++ bar_size = pci_resource_len(pdev, barno);
++ if (!bar_size)
++ return -ENODATA;
++
+ if (!test->bar[barno])
+ return false;
+
+- bar_size = pci_resource_len(pdev, barno);
+-
+ if (barno == test->test_reg_bar)
+ bar_size = 0x4;
+
+--
+2.39.5
+
--- /dev/null
+From 4ba191f7bd2ced6905583a047f57c2e38f05f2f7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Feb 2025 00:17:49 +0530
+Subject: mmc: dw_mmc: add exynos7870 DW MMC support
+
+From: Kaustabh Chakraborty <kauschluss@disroot.org>
+
+[ Upstream commit 7cbe799ac10fd8be85af5e0615c4337f81e575f3 ]
+
+Add support for Exynos7870 DW MMC controllers, for both SMU and non-SMU
+variants. These controllers require a quirk to access 64-bit FIFO in 32-bit
+accesses (DW_MMC_QUIRK_FIFO64_32).
+
+Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
+Link: https://lore.kernel.org/r/20250219-exynos7870-mmc-v2-3-b4255a3e39ed@disroot.org
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/dw_mmc-exynos.c | 41 +++++++++++++++++++++++++++++++-
+ 1 file changed, 40 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
+index 6dc057718d2cb..89682f10e69f3 100644
+--- a/drivers/mmc/host/dw_mmc-exynos.c
++++ b/drivers/mmc/host/dw_mmc-exynos.c
+@@ -27,6 +27,8 @@ enum dw_mci_exynos_type {
+ DW_MCI_TYPE_EXYNOS5420_SMU,
+ DW_MCI_TYPE_EXYNOS7,
+ DW_MCI_TYPE_EXYNOS7_SMU,
++ DW_MCI_TYPE_EXYNOS7870,
++ DW_MCI_TYPE_EXYNOS7870_SMU,
+ DW_MCI_TYPE_ARTPEC8,
+ };
+
+@@ -69,6 +71,12 @@ static struct dw_mci_exynos_compatible {
+ }, {
+ .compatible = "samsung,exynos7-dw-mshc-smu",
+ .ctrl_type = DW_MCI_TYPE_EXYNOS7_SMU,
++ }, {
++ .compatible = "samsung,exynos7870-dw-mshc",
++ .ctrl_type = DW_MCI_TYPE_EXYNOS7870,
++ }, {
++ .compatible = "samsung,exynos7870-dw-mshc-smu",
++ .ctrl_type = DW_MCI_TYPE_EXYNOS7870_SMU,
+ }, {
+ .compatible = "axis,artpec8-dw-mshc",
+ .ctrl_type = DW_MCI_TYPE_ARTPEC8,
+@@ -85,6 +93,8 @@ static inline u8 dw_mci_exynos_get_ciu_div(struct dw_mci *host)
+ return EXYNOS4210_FIXED_CIU_CLK_DIV;
+ else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
+ priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
+ return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL64)) + 1;
+ else
+@@ -100,7 +110,8 @@ static void dw_mci_exynos_config_smu(struct dw_mci *host)
+ * set for non-ecryption mode at this time.
+ */
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420_SMU ||
+- priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU) {
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU) {
+ mci_writel(host, MPSBEGIN0, 0);
+ mci_writel(host, MPSEND0, SDMMC_ENDING_SEC_NR_MAX);
+ mci_writel(host, MPSCTRL0, SDMMC_MPSCTRL_SECURE_WRITE_BIT |
+@@ -126,6 +137,12 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host)
+ DQS_CTRL_GET_RD_DELAY(priv->saved_strobe_ctrl);
+ }
+
++ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU) {
++ /* Quirk needed for certain Exynos SoCs */
++ host->quirks |= DW_MMC_QUIRK_FIFO64_32;
++ }
++
+ if (priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) {
+ /* Quirk needed for the ARTPEC-8 SoC */
+ host->quirks |= DW_MMC_QUIRK_EXTENDED_TMOUT;
+@@ -143,6 +160,8 @@ static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing)
+
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
+ priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
+ clksel = mci_readl(host, CLKSEL64);
+ else
+@@ -152,6 +171,8 @@ static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing)
+
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
+ priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
+ mci_writel(host, CLKSEL64, clksel);
+ else
+@@ -222,6 +243,8 @@ static int dw_mci_exynos_resume_noirq(struct device *dev)
+
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
+ priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
+ clksel = mci_readl(host, CLKSEL64);
+ else
+@@ -230,6 +253,8 @@ static int dw_mci_exynos_resume_noirq(struct device *dev)
+ if (clksel & SDMMC_CLKSEL_WAKEUP_INT) {
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
+ priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
+ mci_writel(host, CLKSEL64, clksel);
+ else
+@@ -409,6 +434,8 @@ static inline u8 dw_mci_exynos_get_clksmpl(struct dw_mci *host)
+
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
+ priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
+ return SDMMC_CLKSEL_CCLK_SAMPLE(mci_readl(host, CLKSEL64));
+ else
+@@ -422,6 +449,8 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample)
+
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
+ priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
+ clksel = mci_readl(host, CLKSEL64);
+ else
+@@ -429,6 +458,8 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample)
+ clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample);
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
+ priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
+ mci_writel(host, CLKSEL64, clksel);
+ else
+@@ -443,6 +474,8 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host)
+
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
+ priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
+ clksel = mci_readl(host, CLKSEL64);
+ else
+@@ -453,6 +486,8 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host)
+
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
+ priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
+ mci_writel(host, CLKSEL64, clksel);
+ else
+@@ -632,6 +667,10 @@ static const struct of_device_id dw_mci_exynos_match[] = {
+ .data = &exynos_drv_data, },
+ { .compatible = "samsung,exynos7-dw-mshc-smu",
+ .data = &exynos_drv_data, },
++ { .compatible = "samsung,exynos7870-dw-mshc",
++ .data = &exynos_drv_data, },
++ { .compatible = "samsung,exynos7870-dw-mshc-smu",
++ .data = &exynos_drv_data, },
+ { .compatible = "axis,artpec8-dw-mshc",
+ .data = &artpec_drv_data, },
+ {},
+--
+2.39.5
+
--- /dev/null
+From 3a44ce978a711e0c3739e5821d6337150f7ff582 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Mar 2025 14:50:21 -0500
+Subject: mmc: host: Wait for Vdd to settle on card power off
+
+From: Erick Shepherd <erick.shepherd@ni.com>
+
+[ Upstream commit 31e75ed964582257f59156ce6a42860e1ae4cc39 ]
+
+The SD spec version 6.0 section 6.4.1.5 requires that Vdd must be
+lowered to less than 0.5V for a minimum of 1 ms when powering off a
+card. Increase wait to 15 ms so that voltage has time to drain down
+to 0.5V and cards can power off correctly. Issues with voltage drain
+time were only observed on Apollo Lake and Bay Trail host controllers
+so this fix is limited to those devices.
+
+Signed-off-by: Erick Shepherd <erick.shepherd@ni.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Link: https://lore.kernel.org/r/20250314195021.1588090-1-erick.shepherd@ni.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/sdhci-pci-core.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
+index 2e2e15e2d8fb8..b0b1d403f3527 100644
+--- a/drivers/mmc/host/sdhci-pci-core.c
++++ b/drivers/mmc/host/sdhci-pci-core.c
+@@ -609,8 +609,12 @@ static void sdhci_intel_set_power(struct sdhci_host *host, unsigned char mode,
+
+ sdhci_set_power(host, mode, vdd);
+
+- if (mode == MMC_POWER_OFF)
++ if (mode == MMC_POWER_OFF) {
++ if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_APL_SD ||
++ slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BYT_SD)
++ usleep_range(15000, 17500);
+ return;
++ }
+
+ /*
+ * Bus power might not enable after D3 -> D0 transition due to the
+--
+2.39.5
+
--- /dev/null
+From c997762379c4efdf58c48725bbd4f06ade02af5e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Feb 2025 15:46:45 -0600
+Subject: mmc: sdhci: Disable SD card clock before changing parameters
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Erick Shepherd <erick.shepherd@ni.com>
+
+[ Upstream commit fb3bbc46c94f261b6156ee863c1b06c84cf157dc ]
+
+Per the SD Host Controller Simplified Specification v4.20 §3.2.3, change
+the SD card clock parameters only after first disabling the external card
+clock. Doing this fixes a spurious clock pulse on Baytrail and Apollo Lake
+SD controllers which otherwise breaks voltage switching with a specific
+Swissbit SD card.
+
+Signed-off-by: Kyle Roeschley <kyle.roeschley@ni.com>
+Signed-off-by: Brad Mouring <brad.mouring@ni.com>
+Signed-off-by: Erick Shepherd <erick.shepherd@ni.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Link: https://lore.kernel.org/r/20250211214645.469279-1-erick.shepherd@ni.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/sdhci.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
+index 4b91c9e966357..8ae76300d157d 100644
+--- a/drivers/mmc/host/sdhci.c
++++ b/drivers/mmc/host/sdhci.c
+@@ -2035,10 +2035,15 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
+
+ host->mmc->actual_clock = 0;
+
+- sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
++ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
++ if (clk & SDHCI_CLOCK_CARD_EN)
++ sdhci_writew(host, clk & ~SDHCI_CLOCK_CARD_EN,
++ SDHCI_CLOCK_CONTROL);
+
+- if (clock == 0)
++ if (clock == 0) {
++ sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+ return;
++ }
+
+ clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
+ sdhci_enable_clk(host, clk);
+--
+2.39.5
+
--- /dev/null
+From 3149c6263cfdabbbf7c919051f261ca1a9ac0d8a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Feb 2025 14:59:20 +0100
+Subject: mptcp: pm: userspace: flags: clearer msg if no remote addr
+
+From: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+
+[ Upstream commit 58b21309f97b08b6b9814d1ee1419249eba9ef08 ]
+
+Since its introduction in commit 892f396c8e68 ("mptcp: netlink: issue
+MP_PRIO signals from userspace PMs"), it was mandatory to specify the
+remote address, because of the 'if (rem->addr.family == AF_UNSPEC)'
+check done later one.
+
+In theory, this attribute can be optional, but it sounds better to be
+precise to avoid sending the MP_PRIO on the wrong subflow, e.g. if there
+are multiple subflows attached to the same local ID. This can be relaxed
+later on if there is a need to act on multiple subflows with one
+command.
+
+For the moment, the check to see if attr_rem is NULL can be removed,
+because mptcp_pm_parse_entry() will do this check as well, no need to do
+that differently here.
+
+Reviewed-by: Geliang Tang <geliang@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mptcp/pm_userspace.c | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c
+index e35178f5205fa..bb76295d04c56 100644
+--- a/net/mptcp/pm_userspace.c
++++ b/net/mptcp/pm_userspace.c
+@@ -589,11 +589,9 @@ int mptcp_userspace_pm_set_flags(struct sk_buff *skb, struct genl_info *info)
+ if (ret < 0)
+ goto set_flags_err;
+
+- if (attr_rem) {
+- ret = mptcp_pm_parse_entry(attr_rem, info, false, &rem);
+- if (ret < 0)
+- goto set_flags_err;
+- }
++ ret = mptcp_pm_parse_entry(attr_rem, info, false, &rem);
++ if (ret < 0)
++ goto set_flags_err;
+
+ if (loc.addr.family == AF_UNSPEC ||
+ rem.addr.family == AF_UNSPEC) {
+--
+2.39.5
+
--- /dev/null
+From be3e420965eb62cb41a4f2c74d957600571e3c25 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Apr 2025 15:00:04 +0300
+Subject: net: enetc: refactor bulk flipping of RX buffers to separate function
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit 1d587faa5be7e9785b682cc5f58ba8f4100c13ea ]
+
+This small snippet of code ensures that we do something with the array
+of RX software buffer descriptor elements after passing the skb to the
+stack. In this case, we see if the other half of the page is reusable,
+and if so, we "turn around" the buffers, making them directly usable by
+enetc_refill_rx_ring() without going to enetc_new_page().
+
+We will need to perform this kind of buffer flipping from a new code
+path, i.e. from XDP_PASS. Currently, enetc_build_skb() does it there
+buffer by buffer, but in a subsequent change we will stop using
+enetc_build_skb() for XDP_PASS.
+
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Wei Fang <wei.fang@nxp.com>
+Link: https://patch.msgid.link/20250417120005.3288549-3-vladimir.oltean@nxp.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/enetc/enetc.c | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
+index f662a5d54986c..d8272b7a55fcb 100644
+--- a/drivers/net/ethernet/freescale/enetc/enetc.c
++++ b/drivers/net/ethernet/freescale/enetc/enetc.c
+@@ -1572,6 +1572,16 @@ static void enetc_xdp_drop(struct enetc_bdr *rx_ring, int rx_ring_first,
+ }
+ }
+
++static void enetc_bulk_flip_buff(struct enetc_bdr *rx_ring, int rx_ring_first,
++ int rx_ring_last)
++{
++ while (rx_ring_first != rx_ring_last) {
++ enetc_flip_rx_buff(rx_ring,
++ &rx_ring->rx_swbd[rx_ring_first]);
++ enetc_bdr_idx_inc(rx_ring, &rx_ring_first);
++ }
++}
++
+ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
+ struct napi_struct *napi, int work_limit,
+ struct bpf_prog *prog)
+@@ -1687,11 +1697,7 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
+ enetc_xdp_drop(rx_ring, orig_i, i);
+ rx_ring->stats.xdp_redirect_failures++;
+ } else {
+- while (orig_i != i) {
+- enetc_flip_rx_buff(rx_ring,
+- &rx_ring->rx_swbd[orig_i]);
+- enetc_bdr_idx_inc(rx_ring, &orig_i);
+- }
++ enetc_bulk_flip_buff(rx_ring, orig_i, i);
+ xdp_redirect_frm_cnt++;
+ rx_ring->stats.xdp_redirect++;
+ }
+--
+2.39.5
+
--- /dev/null
+From fade2d707dfc24460f66f19d795454e0302423e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 21:15:09 +0100
+Subject: net: ethernet: mtk_ppe_offload: Allow QinQ, double ETH_P_8021Q only
+
+From: Eric Woudstra <ericwouds@gmail.com>
+
+[ Upstream commit 7fe0353606d77a32c4c7f2814833dd1c043ebdd2 ]
+
+mtk_foe_entry_set_vlan() in mtk_ppe.c already supports double vlan
+tagging, but mtk_flow_offload_replace() in mtk_ppe_offload.c only allows
+for 1 vlan tag, optionally in combination with pppoe and dsa tags.
+
+However, mtk_foe_entry_set_vlan() only allows for setting the vlan id.
+The protocol cannot be set, it is always ETH_P_8021Q, for inner and outer
+tag. This patch adds QinQ support to mtk_flow_offload_replace(), only in
+the case that both inner and outer tags are ETH_P_8021Q.
+
+Only PPPoE-in-Q (as before) and Q-in-Q are allowed. A combination
+of PPPoE and Q-in-Q is not allowed.
+
+Signed-off-by: Eric Woudstra <ericwouds@gmail.com>
+Link: https://patch.msgid.link/20250225201509.20843-1-ericwouds@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/mediatek/mtk_ppe_offload.c | 22 +++++++++----------
+ 1 file changed, 11 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+index f20bb390df3ad..c855fb799ce14 100644
+--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+@@ -34,8 +34,10 @@ struct mtk_flow_data {
+ u16 vlan_in;
+
+ struct {
+- u16 id;
+- __be16 proto;
++ struct {
++ u16 id;
++ __be16 proto;
++ } vlans[2];
+ u8 num;
+ } vlan;
+ struct {
+@@ -349,18 +351,19 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f,
+ case FLOW_ACTION_CSUM:
+ break;
+ case FLOW_ACTION_VLAN_PUSH:
+- if (data.vlan.num == 1 ||
++ if (data.vlan.num + data.pppoe.num == 2 ||
+ act->vlan.proto != htons(ETH_P_8021Q))
+ return -EOPNOTSUPP;
+
+- data.vlan.id = act->vlan.vid;
+- data.vlan.proto = act->vlan.proto;
++ data.vlan.vlans[data.vlan.num].id = act->vlan.vid;
++ data.vlan.vlans[data.vlan.num].proto = act->vlan.proto;
+ data.vlan.num++;
+ break;
+ case FLOW_ACTION_VLAN_POP:
+ break;
+ case FLOW_ACTION_PPPOE_PUSH:
+- if (data.pppoe.num == 1)
++ if (data.pppoe.num == 1 ||
++ data.vlan.num == 2)
+ return -EOPNOTSUPP;
+
+ data.pppoe.sid = act->pppoe.sid;
+@@ -450,12 +453,9 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f,
+ if (offload_type == MTK_PPE_PKT_TYPE_BRIDGE)
+ foe.bridge.vlan = data.vlan_in;
+
+- if (data.vlan.num == 1) {
+- if (data.vlan.proto != htons(ETH_P_8021Q))
+- return -EOPNOTSUPP;
++ for (i = 0; i < data.vlan.num; i++)
++ mtk_foe_entry_set_vlan(eth, &foe, data.vlan.vlans[i].id);
+
+- mtk_foe_entry_set_vlan(eth, &foe, data.vlan.id);
+- }
+ if (data.pppoe.num == 1)
+ mtk_foe_entry_set_pppoe(eth, &foe, data.pppoe.sid);
+
+--
+2.39.5
+
--- /dev/null
+From 7e65dea44969911128d1d0d921dd2cb075621b6c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Mar 2025 08:46:57 +0100
+Subject: net: ethernet: ti: cpsw_new: populate netdev of_node
+
+From: Alexander Sverdlin <alexander.sverdlin@siemens.com>
+
+[ Upstream commit 7ff1c88fc89688c27f773ba956f65f0c11367269 ]
+
+So that of_find_net_device_by_node() can find CPSW ports and other DSA
+switches can be stacked downstream. Tested in conjunction with KSZ8873.
+
+Reviewed-by: Siddharth Vadapalli <s-vadapalli@ti.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Alexander Sverdlin <alexander.sverdlin@siemens.com>
+Link: https://patch.msgid.link/20250303074703.1758297-1-alexander.sverdlin@siemens.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ti/cpsw_new.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c
+index 557cc71b9dd22..0eee1a0527b5c 100644
+--- a/drivers/net/ethernet/ti/cpsw_new.c
++++ b/drivers/net/ethernet/ti/cpsw_new.c
+@@ -1417,6 +1417,7 @@ static int cpsw_create_ports(struct cpsw_common *cpsw)
+ ndev->netdev_ops = &cpsw_netdev_ops;
+ ndev->ethtool_ops = &cpsw_ethtool_ops;
+ SET_NETDEV_DEV(ndev, dev);
++ ndev->dev.of_node = slave_data->slave_node;
+
+ if (!napi_ndev) {
+ /* CPSW Host port CPDMA interface is shared between
+--
+2.39.5
+
--- /dev/null
+From 78153538a016587abd0c3ceded6e4b8895dbadcc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Feb 2025 15:53:28 -0800
+Subject: net: ethtool: prevent flow steering to RSS contexts which don't exist
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit de7f7582dff292832fbdeaeff34e6b2ee6f9f95f ]
+
+Since commit 42dc431f5d0e ("ethtool: rss: prevent rss ctx deletion
+when in use") we prevent removal of RSS contexts pointed to by
+existing flow rules. Core should also prevent creation of rules
+which point to RSS context which don't exist in the first place.
+
+Reviewed-by: Joe Damato <jdamato@fastly.com>
+Link: https://patch.msgid.link/20250206235334.1425329-2-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/ioctl.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
+index 8b9692c35e706..6ed01cec97a8e 100644
+--- a/net/ethtool/ioctl.c
++++ b/net/ethtool/ioctl.c
+@@ -993,10 +993,14 @@ static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev,
+ return rc;
+
+ /* Nonzero ring with RSS only makes sense if NIC adds them together */
+- if (cmd == ETHTOOL_SRXCLSRLINS && info.fs.flow_type & FLOW_RSS &&
+- !ops->cap_rss_rxnfc_adds &&
+- ethtool_get_flow_spec_ring(info.fs.ring_cookie))
+- return -EINVAL;
++ if (cmd == ETHTOOL_SRXCLSRLINS && info.fs.flow_type & FLOW_RSS) {
++ if (!ops->cap_rss_rxnfc_adds &&
++ ethtool_get_flow_spec_ring(info.fs.ring_cookie))
++ return -EINVAL;
++
++ if (!xa_load(&dev->ethtool->rss_ctx, info.rss_context))
++ return -EINVAL;
++ }
+
+ if (cmd == ETHTOOL_SRXFH && ops->get_rxfh) {
+ struct ethtool_rxfh_param rxfh = {};
+--
+2.39.5
+
--- /dev/null
+From 3d4ca7653f3bab9afc8e9164589edc8258072546 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Feb 2025 13:12:55 +0100
+Subject: net: fec: Refactor MAC reset to function
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Csókás, Bence <csokas.bence@prolan.hu>
+
+[ Upstream commit 67800d296191d0a9bde0a7776f99ca1ddfa0fc26 ]
+
+The core is reset both in `fec_restart()` (called on link-up) and
+`fec_stop()` (going to sleep, driver remove etc.). These two functions
+had their separate implementations, which was at first only a register
+write and a `udelay()` (and the accompanying block comment). However,
+since then we got soft-reset (MAC disable) and Wake-on-LAN support, which
+meant that these implementations diverged, often causing bugs.
+
+For instance, as of now, `fec_stop()` does not check for
+`FEC_QUIRK_NO_HARD_RESET`, meaning the MII/RMII mode is cleared on eg.
+a PM power-down event; and `fec_restart()` missed the refactor renaming
+the "magic" constant `1` to `FEC_ECR_RESET`.
+
+To harmonize current implementations, and eliminate this source of
+potential future bugs, refactor implementation to a common function.
+
+Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Csókás, Bence <csokas.bence@prolan.hu>
+Link: https://patch.msgid.link/20250207121255.161146-2-csokas.bence@prolan.hu
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/fec_main.c | 52 +++++++++++------------
+ 1 file changed, 25 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
+index 04906897615d8..479ced24096b8 100644
+--- a/drivers/net/ethernet/freescale/fec_main.c
++++ b/drivers/net/ethernet/freescale/fec_main.c
+@@ -1098,6 +1098,29 @@ static void fec_enet_enable_ring(struct net_device *ndev)
+ }
+ }
+
++/* Whack a reset. We should wait for this.
++ * For i.MX6SX SOC, enet use AXI bus, we use disable MAC
++ * instead of reset MAC itself.
++ */
++static void fec_ctrl_reset(struct fec_enet_private *fep, bool allow_wol)
++{
++ u32 val;
++
++ if (!allow_wol || !(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) {
++ if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES ||
++ ((fep->quirks & FEC_QUIRK_NO_HARD_RESET) && fep->link)) {
++ writel(0, fep->hwp + FEC_ECNTRL);
++ } else {
++ writel(FEC_ECR_RESET, fep->hwp + FEC_ECNTRL);
++ udelay(10);
++ }
++ } else {
++ val = readl(fep->hwp + FEC_ECNTRL);
++ val |= (FEC_ECR_MAGICEN | FEC_ECR_SLEEP);
++ writel(val, fep->hwp + FEC_ECNTRL);
++ }
++}
++
+ /*
+ * This function is called to start or restart the FEC during a link
+ * change, transmit timeout, or to reconfigure the FEC. The network
+@@ -1114,17 +1137,7 @@ fec_restart(struct net_device *ndev)
+ if (fep->bufdesc_ex)
+ fec_ptp_save_state(fep);
+
+- /* Whack a reset. We should wait for this.
+- * For i.MX6SX SOC, enet use AXI bus, we use disable MAC
+- * instead of reset MAC itself.
+- */
+- if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES ||
+- ((fep->quirks & FEC_QUIRK_NO_HARD_RESET) && fep->link)) {
+- writel(0, fep->hwp + FEC_ECNTRL);
+- } else {
+- writel(1, fep->hwp + FEC_ECNTRL);
+- udelay(10);
+- }
++ fec_ctrl_reset(fep, false);
+
+ /*
+ * enet-mac reset will reset mac address registers too,
+@@ -1378,22 +1391,7 @@ fec_stop(struct net_device *ndev)
+ if (fep->bufdesc_ex)
+ fec_ptp_save_state(fep);
+
+- /* Whack a reset. We should wait for this.
+- * For i.MX6SX SOC, enet use AXI bus, we use disable MAC
+- * instead of reset MAC itself.
+- */
+- if (!(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) {
+- if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES) {
+- writel(0, fep->hwp + FEC_ECNTRL);
+- } else {
+- writel(FEC_ECR_RESET, fep->hwp + FEC_ECNTRL);
+- udelay(10);
+- }
+- } else {
+- val = readl(fep->hwp + FEC_ECNTRL);
+- val |= (FEC_ECR_MAGICEN | FEC_ECR_SLEEP);
+- writel(val, fep->hwp + FEC_ECNTRL);
+- }
++ fec_ctrl_reset(fep, true);
+ writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
+ writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+
+--
+2.39.5
+
--- /dev/null
+From 21b19293a9a774de47c621d858564246d6eab678 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Feb 2025 14:48:25 +0000
+Subject: net: flush_backlog() small changes
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit cbe08724c18078564abefbf6591078a7c98e5e0f ]
+
+Add READ_ONCE() around reads of skb->dev->reg_state, because
+this field can be changed from other threads/cpus.
+
+Instead of calling dev_kfree_skb_irq() and kfree_skb()
+while interrupts are masked and locks held,
+use a temporary list and use __skb_queue_purge_reason()
+
+Use SKB_DROP_REASON_DEV_READY drop reason to better
+describe why these skbs are dropped.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
+Link: https://patch.msgid.link/20250204144825.316785-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/dev.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 7b7b36c43c82c..2ba2160dd093a 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -6034,16 +6034,18 @@ static DEFINE_PER_CPU(struct work_struct, flush_works);
+ static void flush_backlog(struct work_struct *work)
+ {
+ struct sk_buff *skb, *tmp;
++ struct sk_buff_head list;
+ struct softnet_data *sd;
+
++ __skb_queue_head_init(&list);
+ local_bh_disable();
+ sd = this_cpu_ptr(&softnet_data);
+
+ backlog_lock_irq_disable(sd);
+ skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) {
+- if (skb->dev->reg_state == NETREG_UNREGISTERING) {
++ if (READ_ONCE(skb->dev->reg_state) == NETREG_UNREGISTERING) {
+ __skb_unlink(skb, &sd->input_pkt_queue);
+- dev_kfree_skb_irq(skb);
++ __skb_queue_tail(&list, skb);
+ rps_input_queue_head_incr(sd);
+ }
+ }
+@@ -6051,14 +6053,16 @@ static void flush_backlog(struct work_struct *work)
+
+ local_lock_nested_bh(&softnet_data.process_queue_bh_lock);
+ skb_queue_walk_safe(&sd->process_queue, skb, tmp) {
+- if (skb->dev->reg_state == NETREG_UNREGISTERING) {
++ if (READ_ONCE(skb->dev->reg_state) == NETREG_UNREGISTERING) {
+ __skb_unlink(skb, &sd->process_queue);
+- kfree_skb(skb);
++ __skb_queue_tail(&list, skb);
+ rps_input_queue_head_incr(sd);
+ }
+ }
+ local_unlock_nested_bh(&softnet_data.process_queue_bh_lock);
+ local_bh_enable();
++
++ __skb_queue_purge_reason(&list, SKB_DROP_REASON_DEV_READY);
+ }
+
+ static bool flush_required(int cpu)
+--
+2.39.5
+
--- /dev/null
+From 55d9c52cd28c646d1ceb9d4cba3cdd7df0e8b2d7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Mar 2025 18:16:59 +0200
+Subject: net: hsr: Fix PRP duplicate detection
+
+From: Jaakko Karrenpalo <jkarrenpalo@gmail.com>
+
+[ Upstream commit 05fd00e5e7b1ac60d264f72423fba38cc382b447 ]
+
+Add PRP specific function for handling duplicate
+packets. This is needed because of potential
+L2 802.1p prioritization done by network switches.
+
+The L2 prioritization can re-order the PRP packets
+from a node causing the existing implementation to
+discard the frame(s) that have been received 'late'
+because the sequence number is before the previous
+received packet. This can happen if the node is
+sending multiple frames back-to-back with different
+priority.
+
+Signed-off-by: Jaakko Karrenpalo <jkarrenpalo@gmail.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20250307161700.1045-1-jkarrenpalo@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/hsr/hsr_device.c | 2 +
+ net/hsr/hsr_forward.c | 4 +-
+ net/hsr/hsr_framereg.c | 95 ++++++++++++++++++++++++++++++++++++++++--
+ net/hsr/hsr_framereg.h | 8 +++-
+ net/hsr/hsr_main.h | 2 +
+ 5 files changed, 104 insertions(+), 7 deletions(-)
+
+diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
+index 44048d7538ddc..9d0754b3642fd 100644
+--- a/net/hsr/hsr_device.c
++++ b/net/hsr/hsr_device.c
+@@ -543,6 +543,7 @@ static struct hsr_proto_ops hsr_ops = {
+ .drop_frame = hsr_drop_frame,
+ .fill_frame_info = hsr_fill_frame_info,
+ .invalid_dan_ingress_frame = hsr_invalid_dan_ingress_frame,
++ .register_frame_out = hsr_register_frame_out,
+ };
+
+ static struct hsr_proto_ops prp_ops = {
+@@ -553,6 +554,7 @@ static struct hsr_proto_ops prp_ops = {
+ .fill_frame_info = prp_fill_frame_info,
+ .handle_san_frame = prp_handle_san_frame,
+ .update_san_info = prp_update_san_info,
++ .register_frame_out = prp_register_frame_out,
+ };
+
+ void hsr_dev_setup(struct net_device *dev)
+diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c
+index c0217476eb17f..ace4e355d1647 100644
+--- a/net/hsr/hsr_forward.c
++++ b/net/hsr/hsr_forward.c
+@@ -524,8 +524,8 @@ static void hsr_forward_do(struct hsr_frame_info *frame)
+ * Also for SAN, this shouldn't be done.
+ */
+ if (!frame->is_from_san &&
+- hsr_register_frame_out(port, frame->node_src,
+- frame->sequence_nr))
++ hsr->proto_ops->register_frame_out &&
++ hsr->proto_ops->register_frame_out(port, frame))
+ continue;
+
+ if (frame->is_supervision && port->type == HSR_PT_MASTER &&
+diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c
+index 73bc6f659812f..85991fab7db58 100644
+--- a/net/hsr/hsr_framereg.c
++++ b/net/hsr/hsr_framereg.c
+@@ -35,6 +35,7 @@ static bool seq_nr_after(u16 a, u16 b)
+
+ #define seq_nr_before(a, b) seq_nr_after((b), (a))
+ #define seq_nr_before_or_eq(a, b) (!seq_nr_after((a), (b)))
++#define PRP_DROP_WINDOW_LEN 32768
+
+ bool hsr_addr_is_redbox(struct hsr_priv *hsr, unsigned char *addr)
+ {
+@@ -176,8 +177,11 @@ static struct hsr_node *hsr_add_node(struct hsr_priv *hsr,
+ new_node->time_in[i] = now;
+ new_node->time_out[i] = now;
+ }
+- for (i = 0; i < HSR_PT_PORTS; i++)
++ for (i = 0; i < HSR_PT_PORTS; i++) {
+ new_node->seq_out[i] = seq_out;
++ new_node->seq_expected[i] = seq_out + 1;
++ new_node->seq_start[i] = seq_out + 1;
++ }
+
+ if (san && hsr->proto_ops->handle_san_frame)
+ hsr->proto_ops->handle_san_frame(san, rx_port, new_node);
+@@ -482,9 +486,11 @@ void hsr_register_frame_in(struct hsr_node *node, struct hsr_port *port,
+ * 0 otherwise, or
+ * negative error code on error
+ */
+-int hsr_register_frame_out(struct hsr_port *port, struct hsr_node *node,
+- u16 sequence_nr)
++int hsr_register_frame_out(struct hsr_port *port, struct hsr_frame_info *frame)
+ {
++ struct hsr_node *node = frame->node_src;
++ u16 sequence_nr = frame->sequence_nr;
++
+ spin_lock_bh(&node->seq_out_lock);
+ if (seq_nr_before_or_eq(sequence_nr, node->seq_out[port->type]) &&
+ time_is_after_jiffies(node->time_out[port->type] +
+@@ -499,6 +505,89 @@ int hsr_register_frame_out(struct hsr_port *port, struct hsr_node *node,
+ return 0;
+ }
+
++/* Adaptation of the PRP duplicate discard algorithm described in wireshark
++ * wiki (https://wiki.wireshark.org/PRP)
++ *
++ * A drop window is maintained for both LANs with start sequence set to the
++ * first sequence accepted on the LAN that has not been seen on the other LAN,
++ * and expected sequence set to the latest received sequence number plus one.
++ *
++ * When a frame is received on either LAN it is compared against the received
++ * frames on the other LAN. If it is outside the drop window of the other LAN
++ * the frame is accepted and the drop window is updated.
++ * The drop window for the other LAN is reset.
++ *
++ * 'port' is the outgoing interface
++ * 'frame' is the frame to be sent
++ *
++ * Return:
++ * 1 if frame can be shown to have been sent recently on this interface,
++ * 0 otherwise
++ */
++int prp_register_frame_out(struct hsr_port *port, struct hsr_frame_info *frame)
++{
++ enum hsr_port_type other_port;
++ enum hsr_port_type rcv_port;
++ struct hsr_node *node;
++ u16 sequence_diff;
++ u16 sequence_exp;
++ u16 sequence_nr;
++
++ /* out-going frames are always in order
++ * and can be checked the same way as for HSR
++ */
++ if (frame->port_rcv->type == HSR_PT_MASTER)
++ return hsr_register_frame_out(port, frame);
++
++ /* for PRP we should only forward frames from the slave ports
++ * to the master port
++ */
++ if (port->type != HSR_PT_MASTER)
++ return 1;
++
++ node = frame->node_src;
++ sequence_nr = frame->sequence_nr;
++ sequence_exp = sequence_nr + 1;
++ rcv_port = frame->port_rcv->type;
++ other_port = rcv_port == HSR_PT_SLAVE_A ? HSR_PT_SLAVE_B :
++ HSR_PT_SLAVE_A;
++
++ spin_lock_bh(&node->seq_out_lock);
++ if (time_is_before_jiffies(node->time_out[port->type] +
++ msecs_to_jiffies(HSR_ENTRY_FORGET_TIME)) ||
++ (node->seq_start[rcv_port] == node->seq_expected[rcv_port] &&
++ node->seq_start[other_port] == node->seq_expected[other_port])) {
++ /* the node hasn't been sending for a while
++ * or both drop windows are empty, forward the frame
++ */
++ node->seq_start[rcv_port] = sequence_nr;
++ } else if (seq_nr_before(sequence_nr, node->seq_expected[other_port]) &&
++ seq_nr_before_or_eq(node->seq_start[other_port], sequence_nr)) {
++ /* drop the frame, update the drop window for the other port
++ * and reset our drop window
++ */
++ node->seq_start[other_port] = sequence_exp;
++ node->seq_expected[rcv_port] = sequence_exp;
++ node->seq_start[rcv_port] = node->seq_expected[rcv_port];
++ spin_unlock_bh(&node->seq_out_lock);
++ return 1;
++ }
++
++ /* update the drop window for the port where this frame was received
++ * and clear the drop window for the other port
++ */
++ node->seq_start[other_port] = node->seq_expected[other_port];
++ node->seq_expected[rcv_port] = sequence_exp;
++ sequence_diff = sequence_exp - node->seq_start[rcv_port];
++ if (sequence_diff > PRP_DROP_WINDOW_LEN)
++ node->seq_start[rcv_port] = sequence_exp - PRP_DROP_WINDOW_LEN;
++
++ node->time_out[port->type] = jiffies;
++ node->seq_out[port->type] = sequence_nr;
++ spin_unlock_bh(&node->seq_out_lock);
++ return 0;
++}
++
+ static struct hsr_port *get_late_port(struct hsr_priv *hsr,
+ struct hsr_node *node)
+ {
+diff --git a/net/hsr/hsr_framereg.h b/net/hsr/hsr_framereg.h
+index 993fa950d8144..b04948659d84d 100644
+--- a/net/hsr/hsr_framereg.h
++++ b/net/hsr/hsr_framereg.h
+@@ -44,8 +44,7 @@ void hsr_addr_subst_dest(struct hsr_node *node_src, struct sk_buff *skb,
+
+ void hsr_register_frame_in(struct hsr_node *node, struct hsr_port *port,
+ u16 sequence_nr);
+-int hsr_register_frame_out(struct hsr_port *port, struct hsr_node *node,
+- u16 sequence_nr);
++int hsr_register_frame_out(struct hsr_port *port, struct hsr_frame_info *frame);
+
+ void hsr_prune_nodes(struct timer_list *t);
+ void hsr_prune_proxy_nodes(struct timer_list *t);
+@@ -73,6 +72,8 @@ void prp_update_san_info(struct hsr_node *node, bool is_sup);
+ bool hsr_is_node_in_db(struct list_head *node_db,
+ const unsigned char addr[ETH_ALEN]);
+
++int prp_register_frame_out(struct hsr_port *port, struct hsr_frame_info *frame);
++
+ struct hsr_node {
+ struct list_head mac_list;
+ /* Protect R/W access to seq_out */
+@@ -89,6 +90,9 @@ struct hsr_node {
+ bool san_b;
+ u16 seq_out[HSR_PT_PORTS];
+ bool removed;
++ /* PRP specific duplicate handling */
++ u16 seq_expected[HSR_PT_PORTS];
++ u16 seq_start[HSR_PT_PORTS];
+ struct rcu_head rcu_head;
+ };
+
+diff --git a/net/hsr/hsr_main.h b/net/hsr/hsr_main.h
+index fcfeb79bb0401..e26244456f639 100644
+--- a/net/hsr/hsr_main.h
++++ b/net/hsr/hsr_main.h
+@@ -183,6 +183,8 @@ struct hsr_proto_ops {
+ struct hsr_frame_info *frame);
+ bool (*invalid_dan_ingress_frame)(__be16 protocol);
+ void (*update_san_info)(struct hsr_node *node, bool is_sup);
++ int (*register_frame_out)(struct hsr_port *port,
++ struct hsr_frame_info *frame);
+ };
+
+ struct hsr_self_node {
+--
+2.39.5
+
--- /dev/null
+From 9b2cd75ebd74be49d505e115806c531620c885b2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Feb 2025 20:50:33 +0800
+Subject: net: ipv6: Init tunnel link-netns before registering dev
+
+From: Xiao Liang <shaw.leon@gmail.com>
+
+[ Upstream commit db014522f35606031d8ac58b4aed6b1ed84f03d1 ]
+
+Currently some IPv6 tunnel drivers set tnl->net to dev_net(dev) in
+ndo_init(), which is called in register_netdevice(). However, it lacks
+the context of link-netns when we enable cross-net tunnels at device
+registration time.
+
+Let's move the init of tunnel link-netns before register_netdevice().
+
+ip6_gre has already initialized netns, so just remove the redundant
+assignment.
+
+Signed-off-by: Xiao Liang <shaw.leon@gmail.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Link: https://patch.msgid.link/20250219125039.18024-8-shaw.leon@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/ip6_gre.c | 2 --
+ net/ipv6/ip6_tunnel.c | 3 ++-
+ net/ipv6/ip6_vti.c | 3 ++-
+ net/ipv6/sit.c | 8 +++++---
+ 4 files changed, 9 insertions(+), 7 deletions(-)
+
+diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
+index 235808cfec705..68e9a41eed491 100644
+--- a/net/ipv6/ip6_gre.c
++++ b/net/ipv6/ip6_gre.c
+@@ -1498,7 +1498,6 @@ static int ip6gre_tunnel_init_common(struct net_device *dev)
+ tunnel = netdev_priv(dev);
+
+ tunnel->dev = dev;
+- tunnel->net = dev_net(dev);
+ strcpy(tunnel->parms.name, dev->name);
+
+ ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL);
+@@ -1882,7 +1881,6 @@ static int ip6erspan_tap_init(struct net_device *dev)
+ tunnel = netdev_priv(dev);
+
+ tunnel->dev = dev;
+- tunnel->net = dev_net(dev);
+ strcpy(tunnel->parms.name, dev->name);
+
+ ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL);
+diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
+index 48fd53b989726..5350c9bb2319b 100644
+--- a/net/ipv6/ip6_tunnel.c
++++ b/net/ipv6/ip6_tunnel.c
+@@ -1878,7 +1878,6 @@ ip6_tnl_dev_init_gen(struct net_device *dev)
+ int t_hlen;
+
+ t->dev = dev;
+- t->net = dev_net(dev);
+
+ ret = dst_cache_init(&t->dst_cache, GFP_KERNEL);
+ if (ret)
+@@ -1940,6 +1939,7 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev)
+ struct net *net = dev_net(dev);
+ struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+
++ t->net = net;
+ t->parms.proto = IPPROTO_IPV6;
+
+ rcu_assign_pointer(ip6n->tnls_wc[0], t);
+@@ -2013,6 +2013,7 @@ static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev,
+ int err;
+
+ nt = netdev_priv(dev);
++ nt->net = net;
+
+ if (ip_tunnel_netlink_encap_parms(data, &ipencap)) {
+ err = ip6_tnl_encap_setup(nt, &ipencap);
+diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
+index 590737c275379..0123504691443 100644
+--- a/net/ipv6/ip6_vti.c
++++ b/net/ipv6/ip6_vti.c
+@@ -925,7 +925,6 @@ static inline int vti6_dev_init_gen(struct net_device *dev)
+ struct ip6_tnl *t = netdev_priv(dev);
+
+ t->dev = dev;
+- t->net = dev_net(dev);
+ netdev_hold(dev, &t->dev_tracker, GFP_KERNEL);
+ netdev_lockdep_set_classes(dev);
+ return 0;
+@@ -958,6 +957,7 @@ static int __net_init vti6_fb_tnl_dev_init(struct net_device *dev)
+ struct net *net = dev_net(dev);
+ struct vti6_net *ip6n = net_generic(net, vti6_net_id);
+
++ t->net = net;
+ t->parms.proto = IPPROTO_IPV6;
+
+ rcu_assign_pointer(ip6n->tnls_wc[0], t);
+@@ -1008,6 +1008,7 @@ static int vti6_newlink(struct net *src_net, struct net_device *dev,
+ vti6_netlink_parms(data, &nt->parms);
+
+ nt->parms.proto = IPPROTO_IPV6;
++ nt->net = net;
+
+ if (vti6_locate(net, &nt->parms, 0))
+ return -EEXIST;
+diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
+index 39bd8951bfca1..3c15a0ae228e2 100644
+--- a/net/ipv6/sit.c
++++ b/net/ipv6/sit.c
+@@ -269,6 +269,7 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net,
+
+ nt = netdev_priv(dev);
+
++ nt->net = net;
+ nt->parms = *parms;
+ if (ipip6_tunnel_create(dev) < 0)
+ goto failed_free;
+@@ -1449,7 +1450,6 @@ static int ipip6_tunnel_init(struct net_device *dev)
+ int err;
+
+ tunnel->dev = dev;
+- tunnel->net = dev_net(dev);
+ strcpy(tunnel->parms.name, dev->name);
+
+ ipip6_tunnel_bind_dev(dev);
+@@ -1563,6 +1563,7 @@ static int ipip6_newlink(struct net *src_net, struct net_device *dev,
+ int err;
+
+ nt = netdev_priv(dev);
++ nt->net = net;
+
+ if (ip_tunnel_netlink_encap_parms(data, &ipencap)) {
+ err = ip_tunnel_encap_setup(nt, &ipencap);
+@@ -1858,6 +1859,9 @@ static int __net_init sit_init_net(struct net *net)
+ */
+ sitn->fb_tunnel_dev->netns_local = true;
+
++ t = netdev_priv(sitn->fb_tunnel_dev);
++ t->net = net;
++
+ err = register_netdev(sitn->fb_tunnel_dev);
+ if (err)
+ goto err_reg_dev;
+@@ -1865,8 +1869,6 @@ static int __net_init sit_init_net(struct net *net)
+ ipip6_tunnel_clone_6rd(sitn->fb_tunnel_dev, sitn);
+ ipip6_fb_tunnel_init(sitn->fb_tunnel_dev);
+
+- t = netdev_priv(sitn->fb_tunnel_dev);
+-
+ strcpy(t->parms.name, sitn->fb_tunnel_dev->name);
+ return 0;
+
+--
+2.39.5
+
--- /dev/null
+From 9ac65064550c9696d1de7b2405e84a13c6a56f95 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Jan 2025 09:27:14 -0800
+Subject: net/mana: fix warning in the writer of client oob
+
+From: Konstantin Taranov <kotaranov@microsoft.com>
+
+[ Upstream commit 5ec7e1c86c441c46a374577bccd9488abea30037 ]
+
+Do not warn on missing pad_data when oob is in sgl.
+
+Signed-off-by: Konstantin Taranov <kotaranov@microsoft.com>
+Link: https://patch.msgid.link/1737394039-28772-9-git-send-email-kotaranov@linux.microsoft.com
+Reviewed-by: Shiraz Saleem <shirazsaleem@microsoft.com>
+Reviewed-by: Long Li <longli@microsoft.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microsoft/mana/gdma_main.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+index 36802e0a8b570..9bac4083d8a09 100644
+--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
++++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+@@ -1044,7 +1044,7 @@ static u32 mana_gd_write_client_oob(const struct gdma_wqe_request *wqe_req,
+ header->inline_oob_size_div4 = client_oob_size / sizeof(u32);
+
+ if (oob_in_sgl) {
+- WARN_ON_ONCE(!pad_data || wqe_req->num_sge < 2);
++ WARN_ON_ONCE(wqe_req->num_sge < 2);
+
+ header->client_oob_in_sgl = 1;
+
+--
+2.39.5
+
--- /dev/null
+From f98e9fb5d0bc3c09de54d00fb6436119e8486eb2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Feb 2025 09:45:05 -0800
+Subject: net/mlx4_core: Avoid impossible mlx4_db_alloc() order value
+
+From: Kees Cook <kees@kernel.org>
+
+[ Upstream commit 4a6f18f28627e121bd1f74b5fcc9f945d6dbeb1e ]
+
+GCC can see that the value range for "order" is capped, but this leads
+it to consider that it might be negative, leading to a false positive
+warning (with GCC 15 with -Warray-bounds -fdiagnostics-details):
+
+../drivers/net/ethernet/mellanox/mlx4/alloc.c:691:47: error: array subscript -1 is below array bounds of 'long unsigned int *[2]' [-Werror=array-bounds=]
+ 691 | i = find_first_bit(pgdir->bits[o], MLX4_DB_PER_PAGE >> o);
+ | ~~~~~~~~~~~^~~
+ 'mlx4_alloc_db_from_pgdir': events 1-2
+ 691 | i = find_first_bit(pgdir->bits[o], MLX4_DB_PER_PAGE >> o); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | | | | | (2) out of array bounds here
+ | (1) when the condition is evaluated to true In file included from ../drivers/net/ethernet/mellanox/mlx4/mlx4.h:53,
+ from ../drivers/net/ethernet/mellanox/mlx4/alloc.c:42:
+../include/linux/mlx4/device.h:664:33: note: while referencing 'bits'
+ 664 | unsigned long *bits[2];
+ | ^~~~
+
+Switch the argument to unsigned int, which removes the compiler needing
+to consider negative values.
+
+Signed-off-by: Kees Cook <kees@kernel.org>
+Link: https://patch.msgid.link/20250210174504.work.075-kees@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx4/alloc.c | 6 +++---
+ include/linux/mlx4/device.h | 2 +-
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx4/alloc.c b/drivers/net/ethernet/mellanox/mlx4/alloc.c
+index b330020dc0d67..f2bded847e61d 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/alloc.c
++++ b/drivers/net/ethernet/mellanox/mlx4/alloc.c
+@@ -682,9 +682,9 @@ static struct mlx4_db_pgdir *mlx4_alloc_db_pgdir(struct device *dma_device)
+ }
+
+ static int mlx4_alloc_db_from_pgdir(struct mlx4_db_pgdir *pgdir,
+- struct mlx4_db *db, int order)
++ struct mlx4_db *db, unsigned int order)
+ {
+- int o;
++ unsigned int o;
+ int i;
+
+ for (o = order; o <= 1; ++o) {
+@@ -712,7 +712,7 @@ static int mlx4_alloc_db_from_pgdir(struct mlx4_db_pgdir *pgdir,
+ return 0;
+ }
+
+-int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, int order)
++int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, unsigned int order)
+ {
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_db_pgdir *pgdir;
+diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
+index 27f42f713c891..86f0f2a25a3d6 100644
+--- a/include/linux/mlx4/device.h
++++ b/include/linux/mlx4/device.h
+@@ -1135,7 +1135,7 @@ int mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
+ int mlx4_buf_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
+ struct mlx4_buf *buf);
+
+-int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, int order);
++int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, unsigned int order);
+ void mlx4_db_free(struct mlx4_dev *dev, struct mlx4_db *db);
+
+ int mlx4_alloc_hwq_res(struct mlx4_dev *dev, struct mlx4_hwq_resources *wqres,
+--
+2.39.5
+
--- /dev/null
+From 5403ddd741aece4b2579b633e7d9509d23ec2103 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 11:46:38 +0200
+Subject: net/mlx5: Apply rate-limiting to high temperature warning
+
+From: Shahar Shitrit <shshitrit@nvidia.com>
+
+[ Upstream commit 9dd3d5d258aceb37bdf09c8b91fa448f58ea81f0 ]
+
+Wrap the high temperature warning in a temperature event with
+a call to net_ratelimit() to prevent flooding the kernel log
+with repeated warning messages when temperature exceeds the
+threshold multiple times within a short duration.
+
+Signed-off-by: Shahar Shitrit <shshitrit@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Reviewed-by: Mateusz Polchlopek <mateusz.polchlopek@intel.com>
+Link: https://patch.msgid.link/20250213094641.226501-2-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/events.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/events.c b/drivers/net/ethernet/mellanox/mlx5/core/events.c
+index cd8d107f7d9e3..fc6e56305cbbc 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/events.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/events.c
+@@ -169,9 +169,10 @@ static int temp_warn(struct notifier_block *nb, unsigned long type, void *data)
+ value_lsb &= 0x1;
+ value_msb = be64_to_cpu(eqe->data.temp_warning.sensor_warning_msb);
+
+- mlx5_core_warn(events->dev,
+- "High temperature on sensors with bit set %llx %llx",
+- value_msb, value_lsb);
++ if (net_ratelimit())
++ mlx5_core_warn(events->dev,
++ "High temperature on sensors with bit set %llx %llx",
++ value_msb, value_lsb);
+
+ return NOTIFY_OK;
+ }
+--
+2.39.5
+
--- /dev/null
+From 00a9da08d9ea4958ef9b9b73f8731132c415a515 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Feb 2025 14:25:40 +0200
+Subject: net/mlx5: Avoid report two health errors on same syndrome
+
+From: Moshe Shemesh <moshe@nvidia.com>
+
+[ Upstream commit b5d7b2f04ebcff740f44ef4d295b3401aeb029f4 ]
+
+In case health counter has not increased for few polling intervals, miss
+counter will reach max misses threshold and health report will be
+triggered for FW health reporter. In case syndrome found on same health
+poll another health report will be triggered.
+
+Avoid two health reports on same syndrome by marking this syndrome as
+already known.
+
+Signed-off-by: Moshe Shemesh <moshe@nvidia.com>
+Reviewed-by: Shahar Shitrit <shshitrit@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/health.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c
+index a6329ca2d9bff..52c8035547be5 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/health.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c
+@@ -799,6 +799,7 @@ static void poll_health(struct timer_list *t)
+ health->prev = count;
+ if (health->miss_counter == MAX_MISSES) {
+ mlx5_core_err(dev, "device's health compromised - reached miss count\n");
++ health->synd = ioread8(&h->synd);
+ print_health_info(dev);
+ queue_work(health->wq, &health->report_work);
+ }
+--
+2.39.5
+
--- /dev/null
+From 6b02bb6d380941391c44ed8c3c4e3d7adb5d83d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Feb 2025 10:58:08 +0200
+Subject: net/mlx5: Change POOL_NEXT_SIZE define value and make it global
+
+From: Patrisious Haddad <phaddad@nvidia.com>
+
+[ Upstream commit 80df31f384b4146a62a01b3d4beb376cc7b9a89e ]
+
+Change POOL_NEXT_SIZE define value from 0 to BIT(30), since this define
+is used to request the available maximum sized flow table, and zero doesn't
+make sense for it, whereas some places in the driver use zero explicitly
+expecting the smallest table size possible but instead due to this
+define they end up allocating the biggest table size unawarely.
+
+In addition move the definition to "include/linux/mlx5/fs.h" to expose the
+define to IB driver as well, while appropriately renaming it.
+
+Signed-off-by: Patrisious Haddad <phaddad@nvidia.com>
+Reviewed-by: Maor Gottlieb <maorg@nvidia.com>
+Reviewed-by: Mark Bloch <mbloch@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20250219085808.349923-3-tariqt@nvidia.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c | 2 +-
+ drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c | 6 ++++--
+ drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h | 2 --
+ drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c | 3 ++-
+ include/linux/mlx5/fs.h | 2 ++
+ 5 files changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c
+index 8587cd572da53..bdb825aa87268 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c
+@@ -96,7 +96,7 @@ static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw)
+ if (!flow_group_in)
+ return -ENOMEM;
+
+- ft_attr.max_fte = POOL_NEXT_SIZE;
++ ft_attr.max_fte = MLX5_FS_MAX_POOL_SIZE;
+ ft_attr.prio = LEGACY_FDB_PRIO;
+ fdb = mlx5_create_flow_table(root_ns, &ft_attr);
+ if (IS_ERR(fdb)) {
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c
+index c14590acc7726..f6abfd00d7e68 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c
+@@ -50,10 +50,12 @@ mlx5_ft_pool_get_avail_sz(struct mlx5_core_dev *dev, enum fs_flow_table_type tab
+ int i, found_i = -1;
+
+ for (i = ARRAY_SIZE(FT_POOLS) - 1; i >= 0; i--) {
+- if (dev->priv.ft_pool->ft_left[i] && FT_POOLS[i] >= desired_size &&
++ if (dev->priv.ft_pool->ft_left[i] &&
++ (FT_POOLS[i] >= desired_size ||
++ desired_size == MLX5_FS_MAX_POOL_SIZE) &&
+ FT_POOLS[i] <= max_ft_size) {
+ found_i = i;
+- if (desired_size != POOL_NEXT_SIZE)
++ if (desired_size != MLX5_FS_MAX_POOL_SIZE)
+ break;
+ }
+ }
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h
+index 25f4274b372b5..173e312db7204 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h
+@@ -7,8 +7,6 @@
+ #include <linux/mlx5/driver.h>
+ #include "fs_core.h"
+
+-#define POOL_NEXT_SIZE 0
+-
+ int mlx5_ft_pool_init(struct mlx5_core_dev *dev);
+ void mlx5_ft_pool_destroy(struct mlx5_core_dev *dev);
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c
+index 711d14dea2485..d313cb7f0ed88 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c
+@@ -161,7 +161,8 @@ mlx5_chains_create_table(struct mlx5_fs_chains *chains,
+ ft_attr.flags |= (MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT |
+ MLX5_FLOW_TABLE_TUNNEL_EN_DECAP);
+
+- sz = (chain == mlx5_chains_get_nf_ft_chain(chains)) ? FT_TBL_SZ : POOL_NEXT_SIZE;
++ sz = (chain == mlx5_chains_get_nf_ft_chain(chains)) ?
++ FT_TBL_SZ : MLX5_FS_MAX_POOL_SIZE;
+ ft_attr.max_fte = sz;
+
+ /* We use chains_default_ft(chains) as the table's next_ft till
+diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h
+index b744e554f014d..db5c9ddef1702 100644
+--- a/include/linux/mlx5/fs.h
++++ b/include/linux/mlx5/fs.h
+@@ -40,6 +40,8 @@
+
+ #define MLX5_SET_CFG(p, f, v) MLX5_SET(create_flow_group_in, p, f, v)
+
++#define MLX5_FS_MAX_POOL_SIZE BIT(30)
++
+ enum mlx5_flow_destination_type {
+ MLX5_FLOW_DESTINATION_TYPE_NONE,
+ MLX5_FLOW_DESTINATION_TYPE_VPORT,
+--
+2.39.5
+
--- /dev/null
+From dc278d6865aec60c5a0e1b55cd416b271ca75133 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Feb 2025 12:17:15 +0200
+Subject: net/mlx5: Extend Ethtool loopback selftest to support non-linear SKB
+
+From: Alexei Lazar <alazar@nvidia.com>
+
+[ Upstream commit 95b9606b15bb3ce1198d28d2393dd0e1f0a5f3e9 ]
+
+Current loopback test validation ignores non-linear SKB case in
+the SKB access, which can lead to failures in scenarios such as
+when HW GRO is enabled.
+Linearize the SKB so both cases will be handled.
+
+Signed-off-by: Alexei Lazar <alazar@nvidia.com>
+Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20250209101716.112774-15-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
+index 1d60465cc2ca4..2f7a543feca62 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
+@@ -166,6 +166,9 @@ mlx5e_test_loopback_validate(struct sk_buff *skb,
+ struct udphdr *udph;
+ struct iphdr *iph;
+
++ if (skb_linearize(skb))
++ goto out;
++
+ /* We are only going to peek, no need to clone the SKB */
+ if (MLX5E_TEST_PKT_SIZE - ETH_HLEN > skb_headlen(skb))
+ goto out;
+--
+2.39.5
+
--- /dev/null
+From 9b5cada437957fbe15fea50301c7271d1abdd431 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 11:46:40 +0200
+Subject: net/mlx5: Modify LSB bitmask in temperature event to include only the
+ first bit
+
+From: Shahar Shitrit <shshitrit@nvidia.com>
+
+[ Upstream commit 633f16d7e07c129a36b882c05379e01ce5bdb542 ]
+
+In the sensor_count field of the MTEWE register, bits 1-62 are
+supported only for unmanaged switches, not for NICs, and bit 63
+is reserved for internal use.
+
+To prevent confusing output that may include set bits that are
+not relevant to NIC sensors, we update the bitmask to retain only
+the first bit, which corresponds to the sensor ASIC.
+
+Signed-off-by: Shahar Shitrit <shshitrit@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Reviewed-by: Mateusz Polchlopek <mateusz.polchlopek@intel.com>
+Link: https://patch.msgid.link/20250213094641.226501-4-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/events.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/events.c b/drivers/net/ethernet/mellanox/mlx5/core/events.c
+index d91ea53eb394d..cd8d107f7d9e3 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/events.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/events.c
+@@ -163,6 +163,10 @@ static int temp_warn(struct notifier_block *nb, unsigned long type, void *data)
+ u64 value_msb;
+
+ value_lsb = be64_to_cpu(eqe->data.temp_warning.sensor_warning_lsb);
++ /* bit 1-63 are not supported for NICs,
++ * hence read only bit 0 (asic) from lsb.
++ */
++ value_lsb &= 0x1;
+ value_msb = be64_to_cpu(eqe->data.temp_warning.sensor_warning_msb);
+
+ mlx5_core_warn(events->dev,
+--
+2.39.5
+
--- /dev/null
+From 7484380154dc81c8d7c8d33ae3de16ac308b66fb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Feb 2025 12:17:16 +0200
+Subject: net/mlx5: XDP, Enable TX side XDP multi-buffer support
+
+From: Alexei Lazar <alazar@nvidia.com>
+
+[ Upstream commit 1a9304859b3a4119579524c293b902a8927180f3 ]
+
+In XDP scenarios, fragmented packets can occur if the MTU is larger
+than the page size, even when the packet size fits within the linear
+part.
+If XDP multi-buffer support is disabled, the fragmented part won't be
+handled in the TX flow, leading to packet drops.
+
+Since XDP multi-buffer support is always available, this commit removes
+the conditional check for enabling it.
+This ensures that XDP multi-buffer support is always enabled,
+regardless of the `is_xdp_mb` parameter, and guarantees the handling of
+fragmented packets in such scenarios.
+
+Signed-off-by: Alexei Lazar <alazar@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20250209101716.112774-16-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en.h | 1 -
+ .../ethernet/mellanox/mlx5/core/en/params.c | 1 -
+ .../ethernet/mellanox/mlx5/core/en/params.h | 1 -
+ .../mellanox/mlx5/core/en/reporter_tx.c | 1 -
+ .../net/ethernet/mellanox/mlx5/core/en/xdp.c | 49 ++++++++-----------
+ .../net/ethernet/mellanox/mlx5/core/en_main.c | 29 -----------
+ 6 files changed, 21 insertions(+), 61 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
+index 57b7298a0e793..d6266f6a96d6e 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
+@@ -385,7 +385,6 @@ enum {
+ MLX5E_SQ_STATE_VLAN_NEED_L2_INLINE,
+ MLX5E_SQ_STATE_PENDING_XSK_TX,
+ MLX5E_SQ_STATE_PENDING_TLS_RX_RESYNC,
+- MLX5E_SQ_STATE_XDP_MULTIBUF,
+ MLX5E_NUM_SQ_STATES, /* Must be kept last */
+ };
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c
+index 31eb99f09c63c..8c4d710e85675 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c
+@@ -1242,7 +1242,6 @@ void mlx5e_build_xdpsq_param(struct mlx5_core_dev *mdev,
+ mlx5e_build_sq_param_common(mdev, param);
+ MLX5_SET(wq, wq, log_wq_sz, params->log_sq_size);
+ param->is_mpw = MLX5E_GET_PFLAG(params, MLX5E_PFLAG_XDP_TX_MPWQE);
+- param->is_xdp_mb = !mlx5e_rx_is_linear_skb(mdev, params, xsk);
+ mlx5e_build_tx_cq_param(mdev, params, ¶m->cqp);
+ }
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.h b/drivers/net/ethernet/mellanox/mlx5/core/en/params.h
+index 3f8986f9d8629..bd5877acc5b1e 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.h
+@@ -33,7 +33,6 @@ struct mlx5e_sq_param {
+ struct mlx5_wq_param wq;
+ bool is_mpw;
+ bool is_tls;
+- bool is_xdp_mb;
+ u16 stop_room;
+ };
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
+index c8adf309ecad0..dbd9482359e1e 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
+@@ -16,7 +16,6 @@ static const char * const sq_sw_state_type_name[] = {
+ [MLX5E_SQ_STATE_VLAN_NEED_L2_INLINE] = "vlan_need_l2_inline",
+ [MLX5E_SQ_STATE_PENDING_XSK_TX] = "pending_xsk_tx",
+ [MLX5E_SQ_STATE_PENDING_TLS_RX_RESYNC] = "pending_tls_rx_resync",
+- [MLX5E_SQ_STATE_XDP_MULTIBUF] = "xdp_multibuf",
+ };
+
+ static int mlx5e_wait_for_sq_flush(struct mlx5e_txqsq *sq)
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
+index 4610621a340e5..08ab0999f7b31 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
+@@ -546,6 +546,7 @@ mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd,
+ bool inline_ok;
+ bool linear;
+ u16 pi;
++ int i;
+
+ struct mlx5e_xdpsq_stats *stats = sq->stats;
+
+@@ -612,41 +613,33 @@ mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd,
+
+ cseg->opmod_idx_opcode = cpu_to_be32((sq->pc << 8) | MLX5_OPCODE_SEND);
+
+- if (test_bit(MLX5E_SQ_STATE_XDP_MULTIBUF, &sq->state)) {
+- int i;
+-
+- memset(&cseg->trailer, 0, sizeof(cseg->trailer));
+- memset(eseg, 0, sizeof(*eseg) - sizeof(eseg->trailer));
+-
+- eseg->inline_hdr.sz = cpu_to_be16(inline_hdr_sz);
++ memset(&cseg->trailer, 0, sizeof(cseg->trailer));
++ memset(eseg, 0, sizeof(*eseg) - sizeof(eseg->trailer));
+
+- for (i = 0; i < num_frags; i++) {
+- skb_frag_t *frag = &xdptxdf->sinfo->frags[i];
+- dma_addr_t addr;
++ eseg->inline_hdr.sz = cpu_to_be16(inline_hdr_sz);
+
+- addr = xdptxdf->dma_arr ? xdptxdf->dma_arr[i] :
+- page_pool_get_dma_addr(skb_frag_page(frag)) +
+- skb_frag_off(frag);
++ for (i = 0; i < num_frags; i++) {
++ skb_frag_t *frag = &xdptxdf->sinfo->frags[i];
++ dma_addr_t addr;
+
+- dseg->addr = cpu_to_be64(addr);
+- dseg->byte_count = cpu_to_be32(skb_frag_size(frag));
+- dseg->lkey = sq->mkey_be;
+- dseg++;
+- }
++ addr = xdptxdf->dma_arr ? xdptxdf->dma_arr[i] :
++ page_pool_get_dma_addr(skb_frag_page(frag)) +
++ skb_frag_off(frag);
+
+- cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt);
++ dseg->addr = cpu_to_be64(addr);
++ dseg->byte_count = cpu_to_be32(skb_frag_size(frag));
++ dseg->lkey = sq->mkey_be;
++ dseg++;
++ }
+
+- sq->db.wqe_info[pi] = (struct mlx5e_xdp_wqe_info) {
+- .num_wqebbs = num_wqebbs,
+- .num_pkts = 1,
+- };
++ cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt);
+
+- sq->pc += num_wqebbs;
+- } else {
+- cseg->fm_ce_se = 0;
++ sq->db.wqe_info[pi] = (struct mlx5e_xdp_wqe_info) {
++ .num_wqebbs = num_wqebbs,
++ .num_pkts = 1,
++ };
+
+- sq->pc++;
+- }
++ sq->pc += num_wqebbs;
+
+ xsk_tx_metadata_request(meta, &mlx5e_xsk_tx_metadata_ops, eseg);
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+index 3e9ad3cb8121d..38055537b12ac 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+@@ -2030,41 +2030,12 @@ int mlx5e_open_xdpsq(struct mlx5e_channel *c, struct mlx5e_params *params,
+ csp.min_inline_mode = sq->min_inline_mode;
+ set_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
+
+- if (param->is_xdp_mb)
+- set_bit(MLX5E_SQ_STATE_XDP_MULTIBUF, &sq->state);
+-
+ err = mlx5e_create_sq_rdy(c->mdev, param, &csp, 0, &sq->sqn);
+ if (err)
+ goto err_free_xdpsq;
+
+ mlx5e_set_xmit_fp(sq, param->is_mpw);
+
+- if (!param->is_mpw && !test_bit(MLX5E_SQ_STATE_XDP_MULTIBUF, &sq->state)) {
+- unsigned int ds_cnt = MLX5E_TX_WQE_EMPTY_DS_COUNT + 1;
+- unsigned int inline_hdr_sz = 0;
+- int i;
+-
+- if (sq->min_inline_mode != MLX5_INLINE_MODE_NONE) {
+- inline_hdr_sz = MLX5E_XDP_MIN_INLINE;
+- ds_cnt++;
+- }
+-
+- /* Pre initialize fixed WQE fields */
+- for (i = 0; i < mlx5_wq_cyc_get_size(&sq->wq); i++) {
+- struct mlx5e_tx_wqe *wqe = mlx5_wq_cyc_get_wqe(&sq->wq, i);
+- struct mlx5_wqe_ctrl_seg *cseg = &wqe->ctrl;
+- struct mlx5_wqe_eth_seg *eseg = &wqe->eth;
+-
+- sq->db.wqe_info[i] = (struct mlx5e_xdp_wqe_info) {
+- .num_wqebbs = 1,
+- .num_pkts = 1,
+- };
+-
+- cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt);
+- eseg->inline_hdr.sz = cpu_to_be16(inline_hdr_sz);
+- }
+- }
+-
+ return 0;
+
+ err_free_xdpsq:
+--
+2.39.5
+
--- /dev/null
+From 3fb87b8e74c817b226104597aed2dfa3b6bb66dc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 23:39:53 +0200
+Subject: net/mlx5e: Add correct match to check IPSec syndromes for switchdev
+ mode
+
+From: Jianbo Liu <jianbol@nvidia.com>
+
+[ Upstream commit 85e4a808af2545fefaf18c8fe50071b06fcbdabc ]
+
+In commit dddb49b63d86 ("net/mlx5e: Add IPsec and ASO syndromes check
+in HW"), IPSec and ASO syndromes checks after decryption for the
+specified ASO object were added. But they are correct only for eswith
+in legacy mode. For switchdev mode, metadata register c1 is used to
+save the mapped id (not ASO object id). So, need to change the match
+accordingly for the check rules in status table.
+
+Signed-off-by: Jianbo Liu <jianbol@nvidia.com>
+Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
+Reviewed-by: Patrisious Haddad <phaddad@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20250220213959.504304-4-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../mellanox/mlx5/core/en_accel/ipsec_fs.c | 28 ++++++++++++++-----
+ .../mellanox/mlx5/core/esw/ipsec_fs.c | 13 +++++++++
+ .../mellanox/mlx5/core/esw/ipsec_fs.h | 5 ++++
+ include/linux/mlx5/eswitch.h | 2 ++
+ 4 files changed, 41 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
+index 57861d34d46f8..59b9653f573c8 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
+@@ -165,6 +165,25 @@ static void ipsec_rx_status_pass_destroy(struct mlx5e_ipsec *ipsec,
+ #endif
+ }
+
++static void ipsec_rx_rule_add_match_obj(struct mlx5e_ipsec_sa_entry *sa_entry,
++ struct mlx5e_ipsec_rx *rx,
++ struct mlx5_flow_spec *spec)
++{
++ struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
++
++ if (rx == ipsec->rx_esw) {
++ mlx5_esw_ipsec_rx_rule_add_match_obj(sa_entry, spec);
++ } else {
++ MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
++ misc_parameters_2.metadata_reg_c_2);
++ MLX5_SET(fte_match_param, spec->match_value,
++ misc_parameters_2.metadata_reg_c_2,
++ sa_entry->ipsec_obj_id | BIT(31));
++
++ spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2;
++ }
++}
++
+ static int rx_add_rule_drop_auth_trailer(struct mlx5e_ipsec_sa_entry *sa_entry,
+ struct mlx5e_ipsec_rx *rx)
+ {
+@@ -200,11 +219,8 @@ static int rx_add_rule_drop_auth_trailer(struct mlx5e_ipsec_sa_entry *sa_entry,
+
+ MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.ipsec_syndrome);
+ MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.ipsec_syndrome, 1);
+- MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_2);
+- MLX5_SET(fte_match_param, spec->match_value,
+- misc_parameters_2.metadata_reg_c_2,
+- sa_entry->ipsec_obj_id | BIT(31));
+ spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
++ ipsec_rx_rule_add_match_obj(sa_entry, rx, spec);
+ rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
+ if (IS_ERR(rule)) {
+ err = PTR_ERR(rule);
+@@ -281,10 +297,8 @@ static int rx_add_rule_drop_replay(struct mlx5e_ipsec_sa_entry *sa_entry, struct
+
+ MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_4);
+ MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_4, 1);
+- MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_2);
+- MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_2,
+- sa_entry->ipsec_obj_id | BIT(31));
+ spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
++ ipsec_rx_rule_add_match_obj(sa_entry, rx, spec);
+ rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
+ if (IS_ERR(rule)) {
+ err = PTR_ERR(rule);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c
+index ed977ae75fab8..4bba2884c1c05 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c
+@@ -85,6 +85,19 @@ int mlx5_esw_ipsec_rx_setup_modify_header(struct mlx5e_ipsec_sa_entry *sa_entry,
+ return err;
+ }
+
++void mlx5_esw_ipsec_rx_rule_add_match_obj(struct mlx5e_ipsec_sa_entry *sa_entry,
++ struct mlx5_flow_spec *spec)
++{
++ MLX5_SET(fte_match_param, spec->match_criteria,
++ misc_parameters_2.metadata_reg_c_1,
++ ESW_IPSEC_RX_MAPPED_ID_MATCH_MASK);
++ MLX5_SET(fte_match_param, spec->match_value,
++ misc_parameters_2.metadata_reg_c_1,
++ sa_entry->rx_mapped_id << ESW_ZONE_ID_BITS);
++
++ spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2;
++}
++
+ void mlx5_esw_ipsec_rx_id_mapping_remove(struct mlx5e_ipsec_sa_entry *sa_entry)
+ {
+ struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h
+index ac9c65b89166e..514c15258b1d1 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h
+@@ -20,6 +20,8 @@ int mlx5_esw_ipsec_rx_ipsec_obj_id_search(struct mlx5e_priv *priv, u32 id,
+ void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec,
+ struct mlx5e_ipsec_tx_create_attr *attr);
+ void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev);
++void mlx5_esw_ipsec_rx_rule_add_match_obj(struct mlx5e_ipsec_sa_entry *sa_entry,
++ struct mlx5_flow_spec *spec);
+ #else
+ static inline void mlx5_esw_ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec,
+ struct mlx5e_ipsec_rx_create_attr *attr) {}
+@@ -48,5 +50,8 @@ static inline void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec,
+ struct mlx5e_ipsec_tx_create_attr *attr) {}
+
+ static inline void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev) {}
++static inline void
++mlx5_esw_ipsec_rx_rule_add_match_obj(struct mlx5e_ipsec_sa_entry *sa_entry,
++ struct mlx5_flow_spec *spec) {}
+ #endif /* CONFIG_MLX5_ESWITCH */
+ #endif /* __MLX5_ESW_IPSEC_FS_H__ */
+diff --git a/include/linux/mlx5/eswitch.h b/include/linux/mlx5/eswitch.h
+index df73a2ccc9af3..67256e776566c 100644
+--- a/include/linux/mlx5/eswitch.h
++++ b/include/linux/mlx5/eswitch.h
+@@ -147,6 +147,8 @@ u32 mlx5_eswitch_get_vport_metadata_for_set(struct mlx5_eswitch *esw,
+
+ /* reuse tun_opts for the mapped ipsec obj id when tun_id is 0 (invalid) */
+ #define ESW_IPSEC_RX_MAPPED_ID_MASK GENMASK(ESW_TUN_OPTS_BITS - 1, 0)
++#define ESW_IPSEC_RX_MAPPED_ID_MATCH_MASK \
++ GENMASK(31 - ESW_RESERVED_BITS, ESW_ZONE_ID_BITS)
+
+ u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev);
+ u16 mlx5_eswitch_get_total_vports(const struct mlx5_core_dev *dev);
+--
+2.39.5
+
--- /dev/null
+From 21ff6801089234902e04aec82e7db8486946fd43 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Feb 2025 23:35:16 +0200
+Subject: net/mlx5e: Avoid WARN_ON when configuring MQPRIO with HTB offload
+ enabled
+
+From: Carolina Jubran <cjubran@nvidia.com>
+
+[ Upstream commit 689805dcc474c2accb5cffbbcea1c06ee4a54570 ]
+
+When attempting to enable MQPRIO while HTB offload is already
+configured, the driver currently returns `-EINVAL` and triggers a
+`WARN_ON`, leading to an unnecessary call trace.
+
+Update the code to handle this case more gracefully by returning
+`-EOPNOTSUPP` instead, while also providing a helpful user message.
+
+Signed-off-by: Carolina Jubran <cjubran@nvidia.com>
+Reviewed-by: Yael Chemla <ychemla@nvidia.com>
+Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+index 38055537b12ac..4a2f58a9d7066 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+@@ -3759,8 +3759,11 @@ static int mlx5e_setup_tc_mqprio(struct mlx5e_priv *priv,
+ /* MQPRIO is another toplevel qdisc that can't be attached
+ * simultaneously with the offloaded HTB.
+ */
+- if (WARN_ON(mlx5e_selq_is_htb_enabled(&priv->selq)))
+- return -EINVAL;
++ if (mlx5e_selq_is_htb_enabled(&priv->selq)) {
++ NL_SET_ERR_MSG_MOD(mqprio->extack,
++ "MQPRIO cannot be configured when HTB offload is enabled.");
++ return -EOPNOTSUPP;
++ }
+
+ switch (mqprio->mode) {
+ case TC_MQPRIO_MODE_DCB:
+--
+2.39.5
+
--- /dev/null
+From 8aebbc2114a6d387d7473933ac92c5fddb616566 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Feb 2025 12:17:08 +0200
+Subject: net/mlx5e: reduce rep rxq depth to 256 for ECPF
+
+From: William Tu <witu@nvidia.com>
+
+[ Upstream commit b9cc8f9d700867aaa77aedddfea85e53d5e5d584 ]
+
+By experiments, a single queue representor netdev consumes kernel
+memory around 2.8MB, and 1.8MB out of the 2.8MB is due to page
+pool for the RXQ. Scaling to a thousand representors consumes 2.8GB,
+which becomes a memory pressure issue for embedded devices such as
+BlueField-2 16GB / BlueField-3 32GB memory.
+
+Since representor netdevs mostly handles miss traffic, and ideally,
+most of the traffic will be offloaded, reduce the default non-uplink
+rep netdev's RXQ default depth from 1024 to 256 if mdev is ecpf eswitch
+manager. This saves around 1MB of memory per regular RQ,
+(1024 - 256) * 2KB, allocated from page pool.
+
+With rxq depth of 256, the netlink page pool tool reports
+$./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml \
+ --dump page-pool-get
+ {'id': 277,
+ 'ifindex': 9,
+ 'inflight': 128,
+ 'inflight-mem': 786432,
+ 'napi-id': 775}]
+
+This is due to mtu 1500 + headroom consumes half pages, so 256 rxq
+entries consumes around 128 pages (thus create a page pool with
+size 128), shown above at inflight.
+
+Note that each netdev has multiple types of RQs, including
+Regular RQ, XSK, PTP, Drop, Trap RQ. Since non-uplink representor
+only supports regular rq, this patch only changes the regular RQ's
+default depth.
+
+Signed-off-by: William Tu <witu@nvidia.com>
+Reviewed-by: Bodong Wang <bodong@nvidia.com>
+Reviewed-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
+Link: https://patch.msgid.link/20250209101716.112774-8-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+index fd1f460b7be65..18ec392d17404 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+@@ -65,6 +65,7 @@
+ #define MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE \
+ max(0x7, MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)
+ #define MLX5E_REP_PARAMS_DEF_NUM_CHANNELS 1
++#define MLX5E_REP_PARAMS_DEF_LOG_RQ_SIZE 0x8
+
+ static const char mlx5e_rep_driver_name[] = "mlx5e_rep";
+
+@@ -854,6 +855,8 @@ static void mlx5e_build_rep_params(struct net_device *netdev)
+
+ /* RQ */
+ mlx5e_build_rq_params(mdev, params);
++ if (!mlx5e_is_uplink_rep(priv) && mlx5_core_is_ecpf(mdev))
++ params->log_rq_mtu_frames = MLX5E_REP_PARAMS_DEF_LOG_RQ_SIZE;
+
+ /* If netdev is already registered (e.g. move from nic profile to uplink,
+ * RTNL lock must be held before triggering netdev notifiers.
+--
+2.39.5
+
--- /dev/null
+From 1c71ab780360893fa0cfda1f9550a630e3c691a7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Feb 2025 12:17:07 +0200
+Subject: net/mlx5e: reduce the max log mpwrq sz for ECPF and reps
+
+From: William Tu <witu@nvidia.com>
+
+[ Upstream commit e1d68ea58c7e9ebacd9ad7a99b25a3578fa62182 ]
+
+For the ECPF and representors, reduce the max MPWRQ size from 256KB (18)
+to 128KB (17). This prepares the later patch for saving representor
+memory.
+
+With Striding RQ, there is a minimum of 4 MPWQEs. So with 128KB of max
+MPWRQ size, the minimal memory is 4 * 128KB = 512KB. When creating page
+pool, consider 1500 mtu, the minimal page pool size will be 512KB/4KB =
+128 pages = 256 rx ring entries (2 entries per page).
+
+Before this patch, setting RX ringsize (ethtool -G rx) to 256 causes
+driver to allocate page pool size more than it needs due to max MPWRQ
+is 256KB (18). Ex: 4 * 256KB = 1MB, 1MB/4KB = 256 pages, but actually
+128 pages is good enough. Reducing the max MPWRQ to 128KB fixes the
+limitation.
+
+Signed-off-by: William Tu <witu@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
+Link: https://patch.msgid.link/20250209101716.112774-7-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en.h | 2 --
+ .../net/ethernet/mellanox/mlx5/core/en/params.c | 15 +++++++++++----
+ 2 files changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
+index d6266f6a96d6e..e048a667e0758 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
+@@ -94,8 +94,6 @@ struct page_pool;
+ #define MLX5_MPWRQ_DEF_LOG_STRIDE_SZ(mdev) \
+ MLX5_MPWRQ_LOG_STRIDE_SZ(mdev, order_base_2(MLX5E_RX_MAX_HEAD))
+
+-#define MLX5_MPWRQ_MAX_LOG_WQE_SZ 18
+-
+ /* Keep in sync with mlx5e_mpwrq_log_wqe_sz.
+ * These are theoretical maximums, which can be further restricted by
+ * capabilities. These values are used for static resource allocations and
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c
+index 8c4d710e85675..58ec5e44aa7ad 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c
+@@ -10,6 +10,9 @@
+ #include <net/page_pool/types.h>
+ #include <net/xdp_sock_drv.h>
+
++#define MLX5_MPWRQ_MAX_LOG_WQE_SZ 18
++#define MLX5_REP_MPWRQ_MAX_LOG_WQE_SZ 17
++
+ static u8 mlx5e_mpwrq_min_page_shift(struct mlx5_core_dev *mdev)
+ {
+ u8 min_page_shift = MLX5_CAP_GEN_2(mdev, log_min_mkey_entity_size);
+@@ -103,18 +106,22 @@ u8 mlx5e_mpwrq_log_wqe_sz(struct mlx5_core_dev *mdev, u8 page_shift,
+ enum mlx5e_mpwrq_umr_mode umr_mode)
+ {
+ u8 umr_entry_size = mlx5e_mpwrq_umr_entry_size(umr_mode);
+- u8 max_pages_per_wqe, max_log_mpwqe_size;
++ u8 max_pages_per_wqe, max_log_wqe_size_calc;
++ u8 max_log_wqe_size_cap;
+ u16 max_wqe_size;
+
+ /* Keep in sync with MLX5_MPWRQ_MAX_PAGES_PER_WQE. */
+ max_wqe_size = mlx5e_get_max_sq_aligned_wqebbs(mdev) * MLX5_SEND_WQE_BB;
+ max_pages_per_wqe = ALIGN_DOWN(max_wqe_size - sizeof(struct mlx5e_umr_wqe),
+ MLX5_UMR_FLEX_ALIGNMENT) / umr_entry_size;
+- max_log_mpwqe_size = ilog2(max_pages_per_wqe) + page_shift;
++ max_log_wqe_size_calc = ilog2(max_pages_per_wqe) + page_shift;
++
++ WARN_ON_ONCE(max_log_wqe_size_calc < MLX5E_ORDER2_MAX_PACKET_MTU);
+
+- WARN_ON_ONCE(max_log_mpwqe_size < MLX5E_ORDER2_MAX_PACKET_MTU);
++ max_log_wqe_size_cap = mlx5_core_is_ecpf(mdev) ?
++ MLX5_REP_MPWRQ_MAX_LOG_WQE_SZ : MLX5_MPWRQ_MAX_LOG_WQE_SZ;
+
+- return min_t(u8, max_log_mpwqe_size, MLX5_MPWRQ_MAX_LOG_WQE_SZ);
++ return min_t(u8, max_log_wqe_size_calc, max_log_wqe_size_cap);
+ }
+
+ u8 mlx5e_mpwrq_pages_per_wqe(struct mlx5_core_dev *mdev, u8 page_shift,
+--
+2.39.5
+
--- /dev/null
+From 8eecccf10491a733371f6876b16f705aebe68231 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Feb 2025 12:17:09 +0200
+Subject: net/mlx5e: set the tx_queue_len for pfifo_fast
+
+From: William Tu <witu@nvidia.com>
+
+[ Upstream commit a38cc5706fb9f7dc4ee3a443f61de13ce1e410ed ]
+
+By default, the mq netdev creates a pfifo_fast qdisc. On a
+system with 16 core, the pfifo_fast with 3 bands consumes
+16 * 3 * 8 (size of pointer) * 1024 (default tx queue len)
+= 393KB. The patch sets the tx qlen to representor default
+value, 128 (1<<MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE), which
+consumes 16 * 3 * 8 * 128 = 49KB, saving 344KB for each
+representor at ECPF.
+
+Signed-off-by: William Tu <witu@nvidia.com>
+Reviewed-by: Daniel Jurgens <danielj@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
+Link: https://patch.msgid.link/20250209101716.112774-9-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+index 0657d10765357..fd1f460b7be65 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+@@ -885,6 +885,8 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev,
+ netdev->ethtool_ops = &mlx5e_rep_ethtool_ops;
+
+ netdev->watchdog_timeo = 15 * HZ;
++ if (mlx5_core_is_ecpf(mdev))
++ netdev->tx_queue_len = 1 << MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE;
+
+ #if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
+ netdev->hw_features |= NETIF_F_HW_TC;
+--
+2.39.5
+
--- /dev/null
+From ce6df84395d0a10d697df996cb9ac977d5133331 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Feb 2025 14:56:37 -0800
+Subject: net: page_pool: avoid false positive warning if NAPI was never added
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit c1e00bc4be06cacee6307cedb9b55bbaddb5044d ]
+
+We expect NAPI to be in disabled state when page pool is torn down.
+But it is also legal if the NAPI is completely uninitialized.
+
+Reviewed-by: Mina Almasry <almasrymina@google.com>
+Link: https://patch.msgid.link/20250206225638.1387810-4-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/dev.h | 12 ++++++++++++
+ net/core/page_pool.c | 7 ++-----
+ 2 files changed, 14 insertions(+), 5 deletions(-)
+
+diff --git a/net/core/dev.h b/net/core/dev.h
+index 2e3bb7669984a..764e0097ccf22 100644
+--- a/net/core/dev.h
++++ b/net/core/dev.h
+@@ -148,6 +148,18 @@ void xdp_do_check_flushed(struct napi_struct *napi);
+ static inline void xdp_do_check_flushed(struct napi_struct *napi) { }
+ #endif
+
++/* Best effort check that NAPI is not idle (can't be scheduled to run) */
++static inline void napi_assert_will_not_race(const struct napi_struct *napi)
++{
++ /* uninitialized instance, can't race */
++ if (!napi->poll_list.next)
++ return;
++
++ /* SCHED bit is set on disabled instances */
++ WARN_ON(!test_bit(NAPI_STATE_SCHED, &napi->state));
++ WARN_ON(READ_ONCE(napi->list_owner) != -1);
++}
++
+ void kick_defer_list_purge(struct softnet_data *sd, unsigned int cpu);
+
+ #define XMIT_RECURSION_LIMIT 8
+diff --git a/net/core/page_pool.c b/net/core/page_pool.c
+index 7b20f6fcb82c0..c8ce069605c42 100644
+--- a/net/core/page_pool.c
++++ b/net/core/page_pool.c
+@@ -25,6 +25,7 @@
+
+ #include <trace/events/page_pool.h>
+
++#include "dev.h"
+ #include "mp_dmabuf_devmem.h"
+ #include "netmem_priv.h"
+ #include "page_pool_priv.h"
+@@ -1108,11 +1109,7 @@ void page_pool_disable_direct_recycling(struct page_pool *pool)
+ if (!pool->p.napi)
+ return;
+
+- /* To avoid races with recycling and additional barriers make sure
+- * pool and NAPI are unlinked when NAPI is disabled.
+- */
+- WARN_ON(!test_bit(NAPI_STATE_SCHED, &pool->p.napi->state));
+- WARN_ON(READ_ONCE(pool->p.napi->list_owner) != -1);
++ napi_assert_will_not_race(pool->p.napi);
+
+ WRITE_ONCE(pool->p.napi, NULL);
+ }
+--
+2.39.5
+
--- /dev/null
+From dec8859b4c827bea5c5bd1431ecddd2ce7d5f9db Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Feb 2025 17:43:19 +0200
+Subject: net: phy: nxp-c45-tja11xx: add match_phy_device to TJA1103/TJA1104
+
+From: Andrei Botila <andrei.botila@oss.nxp.com>
+
+[ Upstream commit a06a868a0cd96bc51401cdea897313a3f6ad01a0 ]
+
+Add .match_phy_device for the existing TJAs to differentiate between
+TJA1103 and TJA1104.
+TJA1103 and TJA1104 share the same PHY_ID but TJA1104 has MACsec
+capabilities while TJA1103 doesn't.
+
+Signed-off-by: Andrei Botila <andrei.botila@oss.nxp.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20250228154320.2979000-2-andrei.botila@oss.nxp.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/phy/nxp-c45-tja11xx.c | 54 +++++++++++++++++++++++++++++--
+ 1 file changed, 52 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
+index 9788b820c6be7..99a5eee77bec1 100644
+--- a/drivers/net/phy/nxp-c45-tja11xx.c
++++ b/drivers/net/phy/nxp-c45-tja11xx.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /* NXP C45 PHY driver
+- * Copyright 2021-2023 NXP
++ * Copyright 2021-2025 NXP
+ * Author: Radu Pirea <radu-nicolae.pirea@oss.nxp.com>
+ */
+
+@@ -18,6 +18,8 @@
+
+ #include "nxp-c45-tja11xx.h"
+
++#define PHY_ID_MASK GENMASK(31, 4)
++/* Same id: TJA1103, TJA1104 */
+ #define PHY_ID_TJA_1103 0x001BB010
+ #define PHY_ID_TJA_1120 0x001BB031
+
+@@ -1930,6 +1932,30 @@ static void tja1120_nmi_handler(struct phy_device *phydev,
+ }
+ }
+
++static int nxp_c45_macsec_ability(struct phy_device *phydev)
++{
++ bool macsec_ability;
++ int phy_abilities;
++
++ phy_abilities = phy_read_mmd(phydev, MDIO_MMD_VEND1,
++ VEND1_PORT_ABILITIES);
++ macsec_ability = !!(phy_abilities & MACSEC_ABILITY);
++
++ return macsec_ability;
++}
++
++static int tja1103_match_phy_device(struct phy_device *phydev)
++{
++ return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) &&
++ !nxp_c45_macsec_ability(phydev);
++}
++
++static int tja1104_match_phy_device(struct phy_device *phydev)
++{
++ return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) &&
++ nxp_c45_macsec_ability(phydev);
++}
++
+ static const struct nxp_c45_regmap tja1120_regmap = {
+ .vend1_ptp_clk_period = 0x1020,
+ .vend1_event_msg_filt = 0x9010,
+@@ -2000,7 +2026,6 @@ static const struct nxp_c45_phy_data tja1120_phy_data = {
+
+ static struct phy_driver nxp_c45_driver[] = {
+ {
+- PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103),
+ .name = "NXP C45 TJA1103",
+ .get_features = nxp_c45_get_features,
+ .driver_data = &tja1103_phy_data,
+@@ -2022,6 +2047,31 @@ static struct phy_driver nxp_c45_driver[] = {
+ .get_sqi = nxp_c45_get_sqi,
+ .get_sqi_max = nxp_c45_get_sqi_max,
+ .remove = nxp_c45_remove,
++ .match_phy_device = tja1103_match_phy_device,
++ },
++ {
++ .name = "NXP C45 TJA1104",
++ .get_features = nxp_c45_get_features,
++ .driver_data = &tja1103_phy_data,
++ .probe = nxp_c45_probe,
++ .soft_reset = nxp_c45_soft_reset,
++ .config_aneg = genphy_c45_config_aneg,
++ .config_init = nxp_c45_config_init,
++ .config_intr = tja1103_config_intr,
++ .handle_interrupt = nxp_c45_handle_interrupt,
++ .read_status = genphy_c45_read_status,
++ .suspend = genphy_c45_pma_suspend,
++ .resume = genphy_c45_pma_resume,
++ .get_sset_count = nxp_c45_get_sset_count,
++ .get_strings = nxp_c45_get_strings,
++ .get_stats = nxp_c45_get_stats,
++ .cable_test_start = nxp_c45_cable_test_start,
++ .cable_test_get_status = nxp_c45_cable_test_get_status,
++ .set_loopback = genphy_c45_loopback,
++ .get_sqi = nxp_c45_get_sqi,
++ .get_sqi_max = nxp_c45_get_sqi_max,
++ .remove = nxp_c45_remove,
++ .match_phy_device = tja1104_match_phy_device,
+ },
+ {
+ PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120),
+--
+2.39.5
+
--- /dev/null
+From ecab843997900d659195333e7e718f6b53932d92 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Feb 2025 20:15:17 +0800
+Subject: net: phylink: use pl->link_interface in phylink_expects_phy()
+
+From: Choong Yong Liang <yong.liang.choong@linux.intel.com>
+
+[ Upstream commit b63263555eaafbf9ab1a82f2020bbee872d83759 ]
+
+The phylink_expects_phy() function allows MAC drivers to check if they are
+expecting a PHY to attach. The checking condition in phylink_expects_phy()
+aims to achieve the same result as the checking condition in
+phylink_attach_phy().
+
+However, the checking condition in phylink_expects_phy() uses
+pl->link_config.interface, while phylink_attach_phy() uses
+pl->link_interface.
+
+Initially, both pl->link_interface and pl->link_config.interface are set
+to SGMII, and pl->cfg_link_an_mode is set to MLO_AN_INBAND.
+
+When the interface switches from SGMII to 2500BASE-X,
+pl->link_config.interface is updated by phylink_major_config().
+At this point, pl->cfg_link_an_mode remains MLO_AN_INBAND, and
+pl->link_config.interface is set to 2500BASE-X.
+Subsequently, when the STMMAC interface is taken down
+administratively and brought back up, it is blocked by
+phylink_expects_phy().
+
+Since phylink_expects_phy() and phylink_attach_phy() aim to achieve the
+same result, phylink_expects_phy() should check pl->link_interface,
+which never changes, instead of pl->link_config.interface, which is
+updated by phylink_major_config().
+
+Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Choong Yong Liang <yong.liang.choong@linux.intel.com>
+Link: https://patch.msgid.link/20250227121522.1802832-2-yong.liang.choong@linux.intel.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/phy/phylink.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
+index 3e9957b6aa148..b78dfcbec936c 100644
+--- a/drivers/net/phy/phylink.c
++++ b/drivers/net/phy/phylink.c
+@@ -1811,7 +1811,7 @@ bool phylink_expects_phy(struct phylink *pl)
+ {
+ if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
+ (pl->cfg_link_an_mode == MLO_AN_INBAND &&
+- phy_interface_mode_is_8023z(pl->link_config.interface)))
++ phy_interface_mode_is_8023z(pl->link_interface)))
+ return false;
+ return true;
+ }
+--
+2.39.5
+
--- /dev/null
+From bff7e807bc71e3e6bd8fb1c231554924719a6e95 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Feb 2025 09:45:27 +0100
+Subject: net: pktgen: fix access outside of user given buffer in
+ pktgen_thread_write()
+
+From: Peter Seiderer <ps.report@gmx.net>
+
+[ Upstream commit 425e64440ad0a2f03bdaf04be0ae53dededbaa77 ]
+
+Honour the user given buffer size for the strn_len() calls (otherwise
+strn_len() will access memory outside of the user given buffer).
+
+Signed-off-by: Peter Seiderer <ps.report@gmx.net>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20250219084527.20488-8-ps.report@gmx.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/pktgen.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/net/core/pktgen.c b/net/core/pktgen.c
+index 4d87da56c56a0..762ede0278990 100644
+--- a/net/core/pktgen.c
++++ b/net/core/pktgen.c
+@@ -1898,8 +1898,8 @@ static ssize_t pktgen_thread_write(struct file *file,
+ i = len;
+
+ /* Read variable name */
+-
+- len = strn_len(&user_buffer[i], sizeof(name) - 1);
++ max = min(sizeof(name) - 1, count - i);
++ len = strn_len(&user_buffer[i], max);
+ if (len < 0)
+ return len;
+
+@@ -1929,7 +1929,8 @@ static ssize_t pktgen_thread_write(struct file *file,
+ if (!strcmp(name, "add_device")) {
+ char f[32];
+ memset(f, 0, 32);
+- len = strn_len(&user_buffer[i], sizeof(f) - 1);
++ max = min(sizeof(f) - 1, count - i);
++ len = strn_len(&user_buffer[i], max);
+ if (len < 0) {
+ ret = len;
+ goto out;
+--
+2.39.5
+
--- /dev/null
+From d66e2bef4ea37fce0cceec71a3ddbd050211a693 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Feb 2025 14:56:00 +0100
+Subject: net: pktgen: fix mpls maximum labels list parsing
+
+From: Peter Seiderer <ps.report@gmx.net>
+
+[ Upstream commit 2b15a0693f70d1e8119743ee89edbfb1271b3ea8 ]
+
+Fix mpls maximum labels list parsing up to MAX_MPLS_LABELS entries (instead
+of up to MAX_MPLS_LABELS - 1).
+
+Addresses the following:
+
+ $ echo "mpls 00000f00,00000f01,00000f02,00000f03,00000f04,00000f05,00000f06,00000f07,00000f08,00000f09,00000f0a,00000f0b,00000f0c,00000f0d,00000f0e,00000f0f" > /proc/net/pktgen/lo\@0
+ -bash: echo: write error: Argument list too long
+
+Signed-off-by: Peter Seiderer <ps.report@gmx.net>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/pktgen.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/net/core/pktgen.c b/net/core/pktgen.c
+index b6db4910359bb..4d87da56c56a0 100644
+--- a/net/core/pktgen.c
++++ b/net/core/pktgen.c
+@@ -898,6 +898,10 @@ static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev)
+ pkt_dev->nr_labels = 0;
+ do {
+ __u32 tmp;
++
++ if (n >= MAX_MPLS_LABELS)
++ return -E2BIG;
++
+ len = hex32_arg(&buffer[i], 8, &tmp);
+ if (len <= 0)
+ return len;
+@@ -909,8 +913,6 @@ static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev)
+ return -EFAULT;
+ i++;
+ n++;
+- if (n >= MAX_MPLS_LABELS)
+- return -E2BIG;
+ } while (c == ',');
+
+ pkt_dev->nr_labels = n;
+--
+2.39.5
+
--- /dev/null
+From 9b501e74411c8dbd50e4945a6036437da12b0095 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Mar 2025 20:43:04 +0800
+Subject: net/smc: use the correct ndev to find pnetid by pnetid table
+
+From: Guangguan Wang <guangguan.wang@linux.alibaba.com>
+
+[ Upstream commit bfc6c67ec2d64d0ca4e5cc3e1ac84298a10b8d62 ]
+
+When using smc_pnet in SMC, it will only search the pnetid in the
+base_ndev of the netdev hierarchy(both HW PNETID and User-defined
+sw pnetid). This may not work for some scenarios when using SMC in
+container on cloud environment.
+In container, there have choices of different container network,
+such as directly using host network, virtual network IPVLAN, veth,
+etc. Different choices of container network have different netdev
+hierarchy. Examples of netdev hierarchy show below. (eth0 and eth1
+in host below is the netdev directly related to the physical device).
+ _______________________________
+ | _________________ |
+ | |POD | |
+ | | | |
+ | | eth0_________ | |
+ | |____| |__| |
+ | | | |
+ | | | |
+ | eth1|base_ndev| eth0_______ |
+ | | | | RDMA ||
+ | host |_________| |_______||
+ ---------------------------------
+ netdev hierarchy if directly using host network
+ ________________________________
+ | _________________ |
+ | |POD __________ | |
+ | | |upper_ndev| | |
+ | |eth0|__________| | |
+ | |_______|_________| |
+ | |lower netdev |
+ | __|______ |
+ | eth1| | eth0_______ |
+ | |base_ndev| | RDMA ||
+ | host |_________| |_______||
+ ---------------------------------
+ netdev hierarchy if using IPVLAN
+ _______________________________
+ | _____________________ |
+ | |POD _________ | |
+ | | |base_ndev|| |
+ | |eth0(veth)|_________|| |
+ | |____________|________| |
+ | |pairs |
+ | _______|_ |
+ | | | eth0_______ |
+ | veth|base_ndev| | RDMA ||
+ | |_________| |_______||
+ | _________ |
+ | eth1|base_ndev| |
+ | host |_________| |
+ ---------------------------------
+ netdev hierarchy if using veth
+Due to some reasons, the eth1 in host is not RDMA attached netdevice,
+pnetid is needed to map the eth1(in host) with RDMA device so that POD
+can do SMC-R. Because the eth1(in host) is managed by CNI plugin(such
+as Terway, network management plugin in container environment), and in
+cloud environment the eth(in host) can dynamically be inserted by CNI
+when POD create and dynamically be removed by CNI when POD destroy and
+no POD related to the eth(in host) anymore. It is hard to config the
+pnetid to the eth1(in host). But it is easy to config the pnetid to the
+netdevice which can be seen in POD. When do SMC-R, both the container
+directly using host network and the container using veth network can
+successfully match the RDMA device, because the configured pnetid netdev
+is a base_ndev. But the container using IPVLAN can not successfully
+match the RDMA device and 0x03030000 fallback happens, because the
+configured pnetid netdev is not a base_ndev. Additionally, if config
+pnetid to the eth1(in host) also can not work for matching RDMA device
+when using veth network and doing SMC-R in POD.
+
+To resolve the problems list above, this patch extends to search user
+-defined sw pnetid in the clc handshake ndev when no pnetid can be found
+in the base_ndev, and the base_ndev take precedence over ndev for backward
+compatibility. This patch also can unify the pnetid setup of different
+network choices list above in container(Config user-defined sw pnetid in
+the netdevice can be seen in POD).
+
+Signed-off-by: Guangguan Wang <guangguan.wang@linux.alibaba.com>
+Reviewed-by: Wenjia Zhang <wenjia@linux.ibm.com>
+Reviewed-by: Halil Pasic <pasic@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/smc_pnet.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c
+index 716808f374a8d..b391c2ef463f2 100644
+--- a/net/smc/smc_pnet.c
++++ b/net/smc/smc_pnet.c
+@@ -1079,14 +1079,16 @@ static void smc_pnet_find_roce_by_pnetid(struct net_device *ndev,
+ struct smc_init_info *ini)
+ {
+ u8 ndev_pnetid[SMC_MAX_PNETID_LEN];
++ struct net_device *base_ndev;
+ struct net *net;
+
+- ndev = pnet_find_base_ndev(ndev);
++ base_ndev = pnet_find_base_ndev(ndev);
+ net = dev_net(ndev);
+- if (smc_pnetid_by_dev_port(ndev->dev.parent, ndev->dev_port,
++ if (smc_pnetid_by_dev_port(base_ndev->dev.parent, base_ndev->dev_port,
+ ndev_pnetid) &&
++ smc_pnet_find_ndev_pnetid_by_table(base_ndev, ndev_pnetid) &&
+ smc_pnet_find_ndev_pnetid_by_table(ndev, ndev_pnetid)) {
+- smc_pnet_find_rdma_dev(ndev, ini);
++ smc_pnet_find_rdma_dev(base_ndev, ini);
+ return; /* pnetid could not be determined */
+ }
+ _smc_pnet_find_roce_by_pnetid(ndev_pnetid, ini, NULL, net);
+--
+2.39.5
+
--- /dev/null
+From 73a4fa816f73ef6d610beceb63385cdc2537373b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Feb 2025 21:43:28 +0800
+Subject: net: stmmac: dwmac-loongson: Set correct {tx,rx}_fifo_size
+
+From: Huacai Chen <chenhuacai@loongson.cn>
+
+[ Upstream commit 8dbf0c7556454b52af91bae305ca71500c31495c ]
+
+Now for dwmac-loongson {tx,rx}_fifo_size are uninitialised, which means
+zero. This means dwmac-loongson doesn't support changing MTU because in
+stmmac_change_mtu() it requires the fifo size be no less than MTU. Thus,
+set the correct tx_fifo_size and rx_fifo_size for it (16KB multiplied by
+queue counts).
+
+Here {tx,rx}_fifo_size is initialised with the initial value (also the
+maximum value) of {tx,rx}_queues_to_use. So it will keep as 16KB if we
+don't change the queue count, and will be larger than 16KB if we change
+(decrease) the queue count. However stmmac_change_mtu() still work well
+with current logic (MTU cannot be larger than 16KB for stmmac).
+
+Note: the Fixes tag picked here is the oldest commit and key commit of
+the dwmac-loongson series "stmmac: Add Loongson platform support".
+
+Acked-by: Yanteng Si <si.yanteng@linux.dev>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Chong Qiao <qiaochong@loongson.cn>
+Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
+Link: https://patch.msgid.link/20250210134328.2755328-1-chenhuacai@loongson.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+index ab7c2750c1042..702ea5a00b56d 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+@@ -590,6 +590,9 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
+ if (ret)
+ goto err_disable_device;
+
++ plat->tx_fifo_size = SZ_16K * plat->tx_queues_to_use;
++ plat->rx_fifo_size = SZ_16K * plat->rx_queues_to_use;
++
+ if (dev_of_node(&pdev->dev))
+ ret = loongson_dwmac_dt_config(pdev, plat, &res);
+ else
+--
+2.39.5
+
--- /dev/null
+From 33e91f950c3e04bef5db3e4dbf7bd7087446297b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Mar 2025 21:37:14 +0000
+Subject: net: stmmac: dwmac-rk: Validate GRF and peripheral GRF during probe
+
+From: Jonas Karlman <jonas@kwiboo.se>
+
+[ Upstream commit 247e84f66a3d1946193d739fec5dc3d69833fd00 ]
+
+All Rockchip GMAC variants typically write to GRF regs to control e.g.
+interface mode, speed and MAC rx/tx delay. Newer SoCs such as RK3576 and
+RK3588 use a mix of GRF and peripheral GRF regs. These syscon regmaps is
+located with help of a rockchip,grf and rockchip,php-grf phandle.
+
+However, validating the rockchip,grf and rockchip,php-grf syscon regmap
+is deferred until e.g. interface mode or speed is configured, inside the
+individual SoC specific operations.
+
+Change to validate the rockchip,grf and rockchip,php-grf syscon regmap
+at probe time to simplify all SoC specific operations.
+
+This should not introduce any backward compatibility issues as all
+GMAC nodes have been added together with a rockchip,grf phandle (and
+rockchip,php-grf where required) in their initial commit.
+
+Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20250308213720.2517944-3-jonas@kwiboo.se
+Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/stmicro/stmmac/dwmac-rk.c | 21 +++++++++++++++++--
+ 1 file changed, 19 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+index 50073bdade46e..8f90eae937741 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+@@ -33,6 +33,7 @@ struct rk_gmac_ops {
+ void (*set_clock_selection)(struct rk_priv_data *bsp_priv, bool input,
+ bool enable);
+ void (*integrated_phy_powerup)(struct rk_priv_data *bsp_priv);
++ bool php_grf_required;
+ bool regs_valid;
+ u32 regs[];
+ };
+@@ -1263,6 +1264,7 @@ static const struct rk_gmac_ops rk3576_ops = {
+ .set_rgmii_speed = rk3576_set_gmac_speed,
+ .set_rmii_speed = rk3576_set_gmac_speed,
+ .set_clock_selection = rk3576_set_clock_selection,
++ .php_grf_required = true,
+ .regs_valid = true,
+ .regs = {
+ 0x2a220000, /* gmac0 */
+@@ -1410,6 +1412,7 @@ static const struct rk_gmac_ops rk3588_ops = {
+ .set_rgmii_speed = rk3588_set_gmac_speed,
+ .set_rmii_speed = rk3588_set_gmac_speed,
+ .set_clock_selection = rk3588_set_clock_selection,
++ .php_grf_required = true,
+ .regs_valid = true,
+ .regs = {
+ 0xfe1b0000, /* gmac0 */
+@@ -1830,8 +1833,22 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
+
+ bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "rockchip,grf");
+- bsp_priv->php_grf = syscon_regmap_lookup_by_phandle(dev->of_node,
+- "rockchip,php-grf");
++ if (IS_ERR(bsp_priv->grf)) {
++ dev_err_probe(dev, PTR_ERR(bsp_priv->grf),
++ "failed to lookup rockchip,grf\n");
++ return ERR_CAST(bsp_priv->grf);
++ }
++
++ if (ops->php_grf_required) {
++ bsp_priv->php_grf =
++ syscon_regmap_lookup_by_phandle(dev->of_node,
++ "rockchip,php-grf");
++ if (IS_ERR(bsp_priv->php_grf)) {
++ dev_err_probe(dev, PTR_ERR(bsp_priv->php_grf),
++ "failed to lookup rockchip,php-grf\n");
++ return ERR_CAST(bsp_priv->php_grf);
++ }
++ }
+
+ if (plat->phy_node) {
+ bsp_priv->integrated_phy = of_property_read_bool(plat->phy_node,
+--
+2.39.5
+
--- /dev/null
+From a494fe540dc05a9864ab3c626cba6fd8a3313216 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Mar 2025 11:45:58 +0100
+Subject: net: tn40xx: add pci-id of the aqr105-based Tehuti TN4010 cards
+
+From: Hans-Frieder Vogt <hfdevel@gmx.net>
+
+[ Upstream commit 53377b5c2952097527b01ce2f1d9a9332f042f70 ]
+
+Add the PCI-ID of the AQR105-based Tehuti TN4010 cards to allow loading
+of the tn40xx driver on these cards. Here, I chose the detailed definition
+with the subvendor ID similar to the QT2025 cards with the PCI-ID
+TEHUTI:0x4022, because there is a card with an AQ2104 hiding amongst the
+AQR105 cards, and they all come with the same PCI-ID (TEHUTI:0x4025). But
+the AQ2104 is currently not supported.
+
+Signed-off-by: Hans-Frieder Vogt <hfdevel@gmx.net>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20250322-tn9510-v3a-v7-7-672a9a3d8628@gmx.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/tehuti/tn40.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/net/ethernet/tehuti/tn40.c b/drivers/net/ethernet/tehuti/tn40.c
+index 259bdac24cf21..a6965258441c4 100644
+--- a/drivers/net/ethernet/tehuti/tn40.c
++++ b/drivers/net/ethernet/tehuti/tn40.c
+@@ -1832,6 +1832,10 @@ static const struct pci_device_id tn40_id_table[] = {
+ PCI_VENDOR_ID_ASUSTEK, 0x8709) },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_TEHUTI, 0x4022,
+ PCI_VENDOR_ID_EDIMAX, 0x8103) },
++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_TEHUTI, PCI_DEVICE_ID_TEHUTI_TN9510,
++ PCI_VENDOR_ID_TEHUTI, 0x3015) },
++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_TEHUTI, PCI_DEVICE_ID_TEHUTI_TN9510,
++ PCI_VENDOR_ID_EDIMAX, 0x8102) },
+ { }
+ };
+
+--
+2.39.5
+
--- /dev/null
+From 0a89babea10188330a8255dfffe0c56eb01d6e60 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Mar 2025 11:45:56 +0100
+Subject: net: tn40xx: create swnode for mdio and aqr105 phy and add to mdiobus
+
+From: Hans-Frieder Vogt <hfdevel@gmx.net>
+
+[ Upstream commit 25b6a6d29d4082f6ac231c056ac321a996eb55c9 ]
+
+In case of an AQR105-based device, create a software node for the mdio
+function, with a child node for the Aquantia AQR105 PHY, providing a
+firmware-name (and a bit more, which may be used for future checks) to
+allow the PHY to load a MAC specific firmware from the file system.
+
+The name of the PHY software node follows the naming convention suggested
+in the patch for the mdiobus_scan function (in the same patch series).
+
+Signed-off-by: Hans-Frieder Vogt <hfdevel@gmx.net>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20250322-tn9510-v3a-v7-5-672a9a3d8628@gmx.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/tehuti/tn40.c | 5 +-
+ drivers/net/ethernet/tehuti/tn40.h | 33 ++++++++++
+ drivers/net/ethernet/tehuti/tn40_mdio.c | 82 ++++++++++++++++++++++++-
+ 3 files changed, 117 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/tehuti/tn40.c b/drivers/net/ethernet/tehuti/tn40.c
+index a6965258441c4..558b791a97edd 100644
+--- a/drivers/net/ethernet/tehuti/tn40.c
++++ b/drivers/net/ethernet/tehuti/tn40.c
+@@ -1778,7 +1778,7 @@ static int tn40_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ ret = tn40_phy_register(priv);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to set up PHY.\n");
+- goto err_free_irq;
++ goto err_cleanup_swnodes;
+ }
+
+ ret = tn40_priv_init(priv);
+@@ -1795,6 +1795,8 @@ static int tn40_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ return 0;
+ err_unregister_phydev:
+ tn40_phy_unregister(priv);
++err_cleanup_swnodes:
++ tn40_swnodes_cleanup(priv);
+ err_free_irq:
+ pci_free_irq_vectors(pdev);
+ err_unset_drvdata:
+@@ -1816,6 +1818,7 @@ static void tn40_remove(struct pci_dev *pdev)
+ unregister_netdev(ndev);
+
+ tn40_phy_unregister(priv);
++ tn40_swnodes_cleanup(priv);
+ pci_free_irq_vectors(priv->pdev);
+ pci_set_drvdata(pdev, NULL);
+ iounmap(priv->regs);
+diff --git a/drivers/net/ethernet/tehuti/tn40.h b/drivers/net/ethernet/tehuti/tn40.h
+index 490781fe51205..25da8686d4691 100644
+--- a/drivers/net/ethernet/tehuti/tn40.h
++++ b/drivers/net/ethernet/tehuti/tn40.h
+@@ -4,10 +4,13 @@
+ #ifndef _TN40_H_
+ #define _TN40_H_
+
++#include <linux/property.h>
+ #include "tn40_regs.h"
+
+ #define TN40_DRV_NAME "tn40xx"
+
++#define PCI_DEVICE_ID_TEHUTI_TN9510 0x4025
++
+ #define TN40_MDIO_SPEED_1MHZ (1)
+ #define TN40_MDIO_SPEED_6MHZ (6)
+
+@@ -102,10 +105,39 @@ struct tn40_txdb {
+ int size; /* Number of elements in the db */
+ };
+
++#define NODE_PROP(_NAME, _PROP) ( \
++ (const struct software_node) { \
++ .name = _NAME, \
++ .properties = _PROP, \
++ })
++
++#define NODE_PAR_PROP(_NAME, _PAR, _PROP) ( \
++ (const struct software_node) { \
++ .name = _NAME, \
++ .parent = _PAR, \
++ .properties = _PROP, \
++ })
++
++enum tn40_swnodes {
++ SWNODE_MDIO,
++ SWNODE_PHY,
++ SWNODE_MAX
++};
++
++struct tn40_nodes {
++ char phy_name[32];
++ char mdio_name[32];
++ struct property_entry phy_props[3];
++ struct software_node swnodes[SWNODE_MAX];
++ const struct software_node *group[SWNODE_MAX + 1];
++};
++
+ struct tn40_priv {
+ struct net_device *ndev;
+ struct pci_dev *pdev;
+
++ struct tn40_nodes nodes;
++
+ struct napi_struct napi;
+ /* RX FIFOs: 1 for data (full) descs, and 2 for free descs */
+ struct tn40_rxd_fifo rxd_fifo0;
+@@ -225,6 +257,7 @@ static inline void tn40_write_reg(struct tn40_priv *priv, u32 reg, u32 val)
+
+ int tn40_set_link_speed(struct tn40_priv *priv, u32 speed);
+
++void tn40_swnodes_cleanup(struct tn40_priv *priv);
+ int tn40_mdiobus_init(struct tn40_priv *priv);
+
+ int tn40_phy_register(struct tn40_priv *priv);
+diff --git a/drivers/net/ethernet/tehuti/tn40_mdio.c b/drivers/net/ethernet/tehuti/tn40_mdio.c
+index af18615d64a8a..5bb0cbc87d064 100644
+--- a/drivers/net/ethernet/tehuti/tn40_mdio.c
++++ b/drivers/net/ethernet/tehuti/tn40_mdio.c
+@@ -14,6 +14,8 @@
+ (FIELD_PREP(TN40_MDIO_PRTAD_MASK, (port))))
+ #define TN40_MDIO_CMD_READ BIT(15)
+
++#define AQR105_FIRMWARE "tehuti/aqr105-tn40xx.cld"
++
+ static void tn40_mdio_set_speed(struct tn40_priv *priv, u32 speed)
+ {
+ void __iomem *regs = priv->regs;
+@@ -111,6 +113,56 @@ static int tn40_mdio_write_c45(struct mii_bus *mii_bus, int addr, int devnum,
+ return tn40_mdio_write(mii_bus->priv, addr, devnum, regnum, val);
+ }
+
++/* registers an mdio node and an aqr105 PHY at address 1
++ * tn40_mdio-%id {
++ * ethernet-phy@1 {
++ * compatible = "ethernet-phy-id03a1.b4a3";
++ * reg = <1>;
++ * firmware-name = AQR105_FIRMWARE;
++ * };
++ * };
++ */
++static int tn40_swnodes_register(struct tn40_priv *priv)
++{
++ struct tn40_nodes *nodes = &priv->nodes;
++ struct pci_dev *pdev = priv->pdev;
++ struct software_node *swnodes;
++ u32 id;
++
++ id = pci_dev_id(pdev);
++
++ snprintf(nodes->phy_name, sizeof(nodes->phy_name), "ethernet-phy@1");
++ snprintf(nodes->mdio_name, sizeof(nodes->mdio_name), "tn40_mdio-%x",
++ id);
++
++ swnodes = nodes->swnodes;
++
++ swnodes[SWNODE_MDIO] = NODE_PROP(nodes->mdio_name, NULL);
++
++ nodes->phy_props[0] = PROPERTY_ENTRY_STRING("compatible",
++ "ethernet-phy-id03a1.b4a3");
++ nodes->phy_props[1] = PROPERTY_ENTRY_U32("reg", 1);
++ nodes->phy_props[2] = PROPERTY_ENTRY_STRING("firmware-name",
++ AQR105_FIRMWARE);
++ swnodes[SWNODE_PHY] = NODE_PAR_PROP(nodes->phy_name,
++ &swnodes[SWNODE_MDIO],
++ nodes->phy_props);
++
++ nodes->group[SWNODE_PHY] = &swnodes[SWNODE_PHY];
++ nodes->group[SWNODE_MDIO] = &swnodes[SWNODE_MDIO];
++ return software_node_register_node_group(nodes->group);
++}
++
++void tn40_swnodes_cleanup(struct tn40_priv *priv)
++{
++ /* cleanup of swnodes is only needed for AQR105-based cards */
++ if (priv->pdev->device == PCI_DEVICE_ID_TEHUTI_TN9510) {
++ fwnode_handle_put(dev_fwnode(&priv->mdio->dev));
++ device_remove_software_node(&priv->mdio->dev);
++ software_node_unregister_node_group(priv->nodes.group);
++ }
++}
++
+ int tn40_mdiobus_init(struct tn40_priv *priv)
+ {
+ struct pci_dev *pdev = priv->pdev;
+@@ -129,14 +181,40 @@ int tn40_mdiobus_init(struct tn40_priv *priv)
+
+ bus->read_c45 = tn40_mdio_read_c45;
+ bus->write_c45 = tn40_mdio_write_c45;
++ priv->mdio = bus;
++
++ /* provide swnodes for AQR105-based cards only */
++ if (pdev->device == PCI_DEVICE_ID_TEHUTI_TN9510) {
++ ret = tn40_swnodes_register(priv);
++ if (ret) {
++ pr_err("swnodes failed\n");
++ return ret;
++ }
++
++ ret = device_add_software_node(&bus->dev,
++ priv->nodes.group[SWNODE_MDIO]);
++ if (ret) {
++ dev_err(&pdev->dev,
++ "device_add_software_node failed: %d\n", ret);
++ goto err_swnodes_unregister;
++ }
++ }
+
+ ret = devm_mdiobus_register(&pdev->dev, bus);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register mdiobus %d %u %u\n",
+ ret, bus->state, MDIOBUS_UNREGISTERED);
+- return ret;
++ goto err_swnodes_cleanup;
+ }
+ tn40_mdio_set_speed(priv, TN40_MDIO_SPEED_6MHZ);
+- priv->mdio = bus;
+ return 0;
++
++err_swnodes_unregister:
++ software_node_unregister_node_group(priv->nodes.group);
++ return ret;
++err_swnodes_cleanup:
++ tn40_swnodes_cleanup(priv);
++ return ret;
+ }
++
++MODULE_FIRMWARE(AQR105_FIRMWARE);
+--
+2.39.5
+
--- /dev/null
+From 65498a41bb5038b13107f46a883d66d0b2a3702d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 17:33:33 +0100
+Subject: net: xgene-v2: remove incorrect ACPI_PTR annotation
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit 01358e8fe922f716c05d7864ac2213b2440026e7 ]
+
+Building with W=1 shows a warning about xge_acpi_match being unused when
+CONFIG_ACPI is disabled:
+
+drivers/net/ethernet/apm/xgene-v2/main.c:723:36: error: unused variable 'xge_acpi_match' [-Werror,-Wunused-const-variable]
+
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Link: https://patch.msgid.link/20250225163341.4168238-2-arnd@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/apm/xgene-v2/main.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c b/drivers/net/ethernet/apm/xgene-v2/main.c
+index 9e90c23814910..68335935cea77 100644
+--- a/drivers/net/ethernet/apm/xgene-v2/main.c
++++ b/drivers/net/ethernet/apm/xgene-v2/main.c
+@@ -9,8 +9,6 @@
+
+ #include "main.h"
+
+-static const struct acpi_device_id xge_acpi_match[];
+-
+ static int xge_get_resources(struct xge_pdata *pdata)
+ {
+ struct platform_device *pdev;
+@@ -731,7 +729,7 @@ MODULE_DEVICE_TABLE(acpi, xge_acpi_match);
+ static struct platform_driver xge_driver = {
+ .driver = {
+ .name = "xgene-enet-v2",
+- .acpi_match_table = ACPI_PTR(xge_acpi_match),
++ .acpi_match_table = xge_acpi_match,
+ },
+ .probe = xge_probe,
+ .remove_new = xge_remove,
+--
+2.39.5
+
--- /dev/null
+From 0c5014e4005aae48d6225bd73f0c6f083ccfcf4f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jan 2025 18:06:30 +0100
+Subject: netfilter: conntrack: Bound nf_conntrack sysctl writes
+
+From: Nicolas Bouchinet <nicolas.bouchinet@ssi.gouv.fr>
+
+[ Upstream commit 8b6861390ffee6b8ed78b9395e3776c16fec6579 ]
+
+nf_conntrack_max and nf_conntrack_expect_max sysctls were authorized to
+be written any negative value, which would then be stored in the
+unsigned int variables nf_conntrack_max and nf_ct_expect_max variables.
+
+While the do_proc_dointvec_conv function is supposed to limit writing
+handled by proc_dointvec proc_handler to INT_MAX. Such a negative value
+being written in an unsigned int leads to a very high value, exceeding
+this limit.
+
+Moreover, the nf_conntrack_expect_max sysctl documentation specifies the
+minimum value is 1.
+
+The proc_handlers have thus been updated to proc_dointvec_minmax in
+order to specify the following write bounds :
+
+* Bound nf_conntrack_max sysctl writings between SYSCTL_ZERO
+ and SYSCTL_INT_MAX.
+
+* Bound nf_conntrack_expect_max sysctl writings between SYSCTL_ONE
+ and SYSCTL_INT_MAX as defined in the sysctl documentation.
+
+With this patch applied, sysctl writes outside the defined in the bound
+will thus lead to a write error :
+
+```
+sysctl -w net.netfilter.nf_conntrack_expect_max=-1
+sysctl: setting key "net.netfilter.nf_conntrack_expect_max": Invalid argument
+```
+
+Signed-off-by: Nicolas Bouchinet <nicolas.bouchinet@ssi.gouv.fr>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_conntrack_standalone.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
+index 7d4f0fa8b609d..3ea60ff7a6a49 100644
+--- a/net/netfilter/nf_conntrack_standalone.c
++++ b/net/netfilter/nf_conntrack_standalone.c
+@@ -619,7 +619,9 @@ static struct ctl_table nf_ct_sysctl_table[] = {
+ .data = &nf_conntrack_max,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+- .proc_handler = proc_dointvec,
++ .proc_handler = proc_dointvec_minmax,
++ .extra1 = SYSCTL_ZERO,
++ .extra2 = SYSCTL_INT_MAX,
+ },
+ [NF_SYSCTL_CT_COUNT] = {
+ .procname = "nf_conntrack_count",
+@@ -655,7 +657,9 @@ static struct ctl_table nf_ct_sysctl_table[] = {
+ .data = &nf_ct_expect_max,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+- .proc_handler = proc_dointvec,
++ .proc_handler = proc_dointvec_minmax,
++ .extra1 = SYSCTL_ONE,
++ .extra2 = SYSCTL_INT_MAX,
+ },
+ [NF_SYSCTL_CT_ACCT] = {
+ .procname = "nf_conntrack_acct",
+@@ -948,7 +952,9 @@ static struct ctl_table nf_ct_netfilter_table[] = {
+ .data = &nf_conntrack_max,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+- .proc_handler = proc_dointvec,
++ .proc_handler = proc_dointvec_minmax,
++ .extra1 = SYSCTL_ZERO,
++ .extra2 = SYSCTL_INT_MAX,
+ },
+ };
+
+--
+2.39.5
+
--- /dev/null
+From b6612f215bae8602e540e2575fb365b2b6e167b4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Mar 2025 13:19:18 -0400
+Subject: NFS: Don't allow waiting for exiting tasks
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+[ Upstream commit 8d3ca331026a7f9700d3747eed59a67b8f828cdc ]
+
+Once a task calls exit_signals() it can no longer be signalled. So do
+not allow it to do killable waits.
+
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/inode.c | 2 ++
+ fs/nfs/internal.h | 5 +++++
+ fs/nfs/nfs3proc.c | 2 +-
+ fs/nfs/nfs4proc.c | 9 +++++++--
+ 4 files changed, 15 insertions(+), 3 deletions(-)
+
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index 596f351701372..330273cf94531 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -74,6 +74,8 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr)
+
+ int nfs_wait_bit_killable(struct wait_bit_key *key, int mode)
+ {
++ if (unlikely(nfs_current_task_exiting()))
++ return -EINTR;
+ schedule();
+ if (signal_pending_state(mode, current))
+ return -ERESTARTSYS;
+diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
+index 8b568a514fd1c..1be4be3d4a2b6 100644
+--- a/fs/nfs/internal.h
++++ b/fs/nfs/internal.h
+@@ -901,6 +901,11 @@ static inline u32 nfs_stateid_hash(const nfs4_stateid *stateid)
+ NFS4_STATEID_OTHER_SIZE);
+ }
+
++static inline bool nfs_current_task_exiting(void)
++{
++ return (current->flags & PF_EXITING) != 0;
++}
++
+ static inline bool nfs_error_is_fatal(int err)
+ {
+ switch (err) {
+diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
+index 1566163c6d85b..88b0fb343ae04 100644
+--- a/fs/nfs/nfs3proc.c
++++ b/fs/nfs/nfs3proc.c
+@@ -39,7 +39,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
+ __set_current_state(TASK_KILLABLE|TASK_FREEZABLE_UNSAFE);
+ schedule_timeout(NFS_JUKEBOX_RETRY_TIME);
+ res = -ERESTARTSYS;
+- } while (!fatal_signal_pending(current));
++ } while (!fatal_signal_pending(current) && !nfs_current_task_exiting());
+ return res;
+ }
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index ca01f79c82e4a..11f2b5cb3b06b 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -434,6 +434,8 @@ static int nfs4_delay_killable(long *timeout)
+ {
+ might_sleep();
+
++ if (unlikely(nfs_current_task_exiting()))
++ return -EINTR;
+ __set_current_state(TASK_KILLABLE|TASK_FREEZABLE_UNSAFE);
+ schedule_timeout(nfs4_update_delay(timeout));
+ if (!__fatal_signal_pending(current))
+@@ -445,6 +447,8 @@ static int nfs4_delay_interruptible(long *timeout)
+ {
+ might_sleep();
+
++ if (unlikely(nfs_current_task_exiting()))
++ return -EINTR;
+ __set_current_state(TASK_INTERRUPTIBLE|TASK_FREEZABLE_UNSAFE);
+ schedule_timeout(nfs4_update_delay(timeout));
+ if (!signal_pending(current))
+@@ -1765,7 +1769,8 @@ static void nfs_set_open_stateid_locked(struct nfs4_state *state,
+ rcu_read_unlock();
+ trace_nfs4_open_stateid_update_wait(state->inode, stateid, 0);
+
+- if (!fatal_signal_pending(current)) {
++ if (!fatal_signal_pending(current) &&
++ !nfs_current_task_exiting()) {
+ if (schedule_timeout(5*HZ) == 0)
+ status = -EAGAIN;
+ else
+@@ -3569,7 +3574,7 @@ static bool nfs4_refresh_open_old_stateid(nfs4_stateid *dst,
+ write_sequnlock(&state->seqlock);
+ trace_nfs4_close_stateid_update_wait(state->inode, dst, 0);
+
+- if (fatal_signal_pending(current))
++ if (fatal_signal_pending(current) || nfs_current_task_exiting())
+ status = -EINTR;
+ else
+ if (schedule_timeout(5*HZ) != 0)
+--
+2.39.5
+
--- /dev/null
+From 52edd4862750fe1b16575e21605fa2819f2e066e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Mar 2025 19:20:53 -0400
+Subject: NFSv4: Check for delegation validity in
+ nfs_start_delegation_return_locked()
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+[ Upstream commit 9e8f324bd44c1fe026b582b75213de4eccfa1163 ]
+
+Check that the delegation is still attached after taking the spin lock
+in nfs_start_delegation_return_locked().
+
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/delegation.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
+index 325ba0663a6de..8bdbc4dca89ca 100644
+--- a/fs/nfs/delegation.c
++++ b/fs/nfs/delegation.c
+@@ -307,7 +307,8 @@ nfs_start_delegation_return_locked(struct nfs_inode *nfsi)
+ if (delegation == NULL)
+ goto out;
+ spin_lock(&delegation->lock);
+- if (!test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) {
++ if (delegation->inode &&
++ !test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) {
+ clear_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags);
+ /* Refcount matched in nfs_end_delegation_return() */
+ ret = nfs_get_delegation(delegation);
+--
+2.39.5
+
--- /dev/null
+From bb59afa435f57c5539c799619b62012a6c99cd69 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Mar 2025 20:35:33 -0400
+Subject: NFSv4: Treat ENETUNREACH errors as fatal for state recovery
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+[ Upstream commit 0af5fb5ed3d2fd9e110c6112271f022b744a849a ]
+
+If a containerised process is killed and causes an ENETUNREACH or
+ENETDOWN error to be propagated to the state manager, then mark the
+nfs_client as being dead so that we don't loop in functions that are
+expecting recovery to succeed.
+
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: Benjamin Coddington <bcodding@redhat.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/nfs4state.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
+index dafd61186557f..397a86011878f 100644
+--- a/fs/nfs/nfs4state.c
++++ b/fs/nfs/nfs4state.c
+@@ -2740,7 +2740,15 @@ static void nfs4_state_manager(struct nfs_client *clp)
+ pr_warn_ratelimited("NFS: state manager%s%s failed on NFSv4 server %s"
+ " with error %d\n", section_sep, section,
+ clp->cl_hostname, -status);
+- ssleep(1);
++ switch (status) {
++ case -ENETDOWN:
++ case -ENETUNREACH:
++ nfs_mark_client_ready(clp, -EIO);
++ break;
++ default:
++ ssleep(1);
++ break;
++ }
+ out_drain:
+ memalloc_nofs_restore(memflags);
+ nfs4_end_drain_session(clp);
+--
+2.39.5
+
--- /dev/null
+From 507ae214217d2abf9346d8e9f5360bd0eb9635c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Feb 2025 14:39:13 -0800
+Subject: nvme: map uring_cmd data even if address is 0
+
+From: Xinyu Zhang <xizhang@purestorage.com>
+
+[ Upstream commit 99fde895ff56ac2241e7b7b4566731d72f2fdaa7 ]
+
+When using kernel registered bvec fixed buffers, the "address" is
+actually the offset into the bvec rather than userspace address.
+Therefore it can be 0.
+
+We can skip checking whether the address is NULL before mapping
+uring_cmd data. Bad userspace address will be handled properly later when
+the user buffer is imported.
+
+With this patch, we will be able to use the kernel registered bvec fixed
+buffers in io_uring NVMe passthru with ublk zero-copy support.
+
+Reviewed-by: Caleb Sander Mateos <csander@purestorage.com>
+Reviewed-by: Jens Axboe <axboe@kernel.dk>
+Reviewed-by: Ming Lei <ming.lei@redhat.com>
+Signed-off-by: Xinyu Zhang <xizhang@purestorage.com>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Link: https://lore.kernel.org/r/20250227223916.143006-4-kbusch@meta.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/ioctl.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
+index a1b3c538a4bd2..d128e6cf6f1b0 100644
+--- a/drivers/nvme/host/ioctl.c
++++ b/drivers/nvme/host/ioctl.c
+@@ -515,7 +515,7 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
+ return PTR_ERR(req);
+ req->timeout = d.timeout_ms ? msecs_to_jiffies(d.timeout_ms) : 0;
+
+- if (d.addr && d.data_len) {
++ if (d.data_len) {
+ ret = nvme_map_user_request(req, d.addr,
+ d.data_len, nvme_to_user_ptr(d.metadata),
+ d.metadata_len, 0, ioucmd, vec);
+--
+2.39.5
+
--- /dev/null
+From a7cfc4b882c8747a783139b17c7c4c40b0d22386 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Apr 2025 20:17:25 +0800
+Subject: nvme-pci: add quirks for device 126f:1001
+
+From: Wentao Guan <guanwentao@uniontech.com>
+
+[ Upstream commit 5b960f92ac3e5b4d7f60a506a6b6735eead1da01 ]
+
+This commit adds NVME_QUIRK_NO_DEEPEST_PS and NVME_QUIRK_BOGUS_NID for
+device [126f:1001].
+
+It is similar to commit e89086c43f05 ("drivers/nvme: Add quirks for
+device 126f:2262")
+
+Diff is according the dmesg, use NVME_QUIRK_IGNORE_DEV_SUBNQN.
+
+dmesg | grep -i nvme0:
+ nvme nvme0: pci function 0000:01:00.0
+ nvme nvme0: missing or invalid SUBNQN field.
+ nvme nvme0: 12/0/0 default/read/poll queues
+
+Link:https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e89086c43f0500bc7c4ce225495b73b8ce234c1f
+Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
+Signed-off-by: WangYuli <wangyuli@uniontech.com>
+Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/pci.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index 265b3608ae26e..f2c06bb96c8d2 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -3587,6 +3587,9 @@ static const struct pci_device_id nvme_id_table[] = {
+ .driver_data = NVME_QUIRK_BOGUS_NID, },
+ { PCI_DEVICE(0x1217, 0x8760), /* O2 Micro 64GB Steam Deck */
+ .driver_data = NVME_QUIRK_DMAPOOL_ALIGN_512, },
++ { PCI_DEVICE(0x126f, 0x1001), /* Silicon Motion generic */
++ .driver_data = NVME_QUIRK_NO_DEEPEST_PS |
++ NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+ { PCI_DEVICE(0x126f, 0x2262), /* Silicon Motion generic */
+ .driver_data = NVME_QUIRK_NO_DEEPEST_PS |
+ NVME_QUIRK_BOGUS_NID, },
+--
+2.39.5
+
--- /dev/null
+From ca623d56a62ec6607d8358b00ad2b1c6f1629d06 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Apr 2025 10:40:10 +0800
+Subject: nvme-pci: add quirks for WDC Blue SN550 15b7:5009
+
+From: Wentao Guan <guanwentao@uniontech.com>
+
+[ Upstream commit ab35ad950d439ec3409509835d229b3d93d3c7f9 ]
+
+Add two quirks for the WDC Blue SN550 (PCI ID 15b7:5009) based on user
+reports and hardware analysis:
+
+ - NVME_QUIRK_NO_DEEPEST_PS:
+ liaozw talked to me the problem and solved with
+ nvme_core.default_ps_max_latency_us=0, so add the quirk.
+ I also found some reports in the following link.
+
+ - NVME_QUIRK_BROKEN_MSI:
+ after get the lspci from Jack Rio.
+ I think that the disk also have NVME_QUIRK_BROKEN_MSI.
+ described in commit d5887dc6b6c0 ("nvme-pci: Add quirk for broken MSIs")
+ as sean said in link which match the MSI 1/32 and MSI-X 17.
+
+Log:
+lspci -nn | grep -i memory
+03:00.0 Non-Volatile memory controller [0108]: Sandisk Corp SanDisk Ultra 3D / WD PC SN530, IX SN530, Blue SN550 NVMe SSD (DRAM-less) [15b7:5009] (rev 01)
+lspci -v -d 15b7:5009
+03:00.0 Non-Volatile memory controller: Sandisk Corp SanDisk Ultra 3D / WD PC SN530, IX SN530, Blue SN550 NVMe SSD (DRAM-less) (rev 01) (prog-if 02 [NVM Express])
+ Subsystem: Sandisk Corp WD Blue SN550 NVMe SSD
+ Flags: bus master, fast devsel, latency 0, IRQ 35, IOMMU group 10
+ Memory at fe800000 (64-bit, non-prefetchable) [size=16K]
+ Memory at fe804000 (64-bit, non-prefetchable) [size=256]
+ Capabilities: [80] Power Management version 3
+ Capabilities: [90] MSI: Enable- Count=1/32 Maskable- 64bit+
+ Capabilities: [b0] MSI-X: Enable+ Count=17 Masked-
+ Capabilities: [c0] Express Endpoint, MSI 00
+ Capabilities: [100] Advanced Error Reporting
+ Capabilities: [150] Device Serial Number 00-00-00-00-00-00-00-00
+ Capabilities: [1b8] Latency Tolerance Reporting
+ Capabilities: [300] Secondary PCI Express
+ Capabilities: [900] L1 PM Substates
+ Kernel driver in use: nvme
+dmesg | grep nvme
+[ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-6.12.20-amd64-desktop-rolling root=UUID= ro splash quiet nvme_core.default_ps_max_latency_us=0 DEEPIN_GFXMODE=
+[ 0.059301] Kernel command line: BOOT_IMAGE=/vmlinuz-6.12.20-amd64-desktop-rolling root=UUID= ro splash quiet nvme_core.default_ps_max_latency_us=0 DEEPIN_GFXMODE=
+[ 0.542430] nvme nvme0: pci function 0000:03:00.0
+[ 0.560426] nvme nvme0: allocated 32 MiB host memory buffer.
+[ 0.562491] nvme nvme0: 16/0/0 default/read/poll queues
+[ 0.567764] nvme0n1: p1 p2 p3 p4 p5 p6 p7 p8 p9
+[ 6.388726] EXT4-fs (nvme0n1p7): mounted filesystem ro with ordered data mode. Quota mode: none.
+[ 6.893421] EXT4-fs (nvme0n1p7): re-mounted r/w. Quota mode: none.
+[ 7.125419] Adding 16777212k swap on /dev/nvme0n1p8. Priority:-2 extents:1 across:16777212k SS
+[ 7.157588] EXT4-fs (nvme0n1p6): mounted filesystem r/w with ordered data mode. Quota mode: none.
+[ 7.165021] EXT4-fs (nvme0n1p9): mounted filesystem r/w with ordered data mode. Quota mode: none.
+[ 8.036932] nvme nvme0: using unchecked data buffer
+[ 8.096023] block nvme0n1: No UUID available providing old NGUID
+
+Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d5887dc6b6c054d0da3cd053afc15b7be1f45ff6
+Link: https://lore.kernel.org/all/20240422162822.3539156-1-sean.anderson@linux.dev/
+Reported-by: liaozw <hedgehog-002@163.com>
+Closes: https://bbs.deepin.org.cn/post/286300
+Reported-by: rugk <rugk+github@posteo.de>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=208123
+Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/pci.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index f2c06bb96c8d2..cd8a10f6accff 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -3613,6 +3613,9 @@ static const struct pci_device_id nvme_id_table[] = {
+ NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+ { PCI_DEVICE(0x15b7, 0x5008), /* Sandisk SN530 */
+ .driver_data = NVME_QUIRK_BROKEN_MSI },
++ { PCI_DEVICE(0x15b7, 0x5009), /* Sandisk SN550 */
++ .driver_data = NVME_QUIRK_BROKEN_MSI |
++ NVME_QUIRK_NO_DEEPEST_PS },
+ { PCI_DEVICE(0x1987, 0x5012), /* Phison E12 */
+ .driver_data = NVME_QUIRK_BOGUS_NID, },
+ { PCI_DEVICE(0x1987, 0x5016), /* Phison E16 */
+--
+2.39.5
+
--- /dev/null
+From a3f1d24e0fc73ca4bc699723dcaa656db1b12190 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Apr 2025 12:22:46 +0100
+Subject: nvmem: core: fix bit offsets of more than one byte
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit 7a06ef75107799675ea6e4d73b9df37e18e352a8 ]
+
+If the NVMEM specifies a stride to access data, reading particular cell
+might require bit offset that is bigger than one byte. Rework NVMEM core
+code to support bit offsets of more than 8 bits.
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20250411112251.68002-9-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvmem/core.c | 24 +++++++++++++++++-------
+ 1 file changed, 17 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
+index d00a3b015635c..8af2a569c23aa 100644
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -824,7 +824,9 @@ static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_nod
+ if (addr && len == (2 * sizeof(u32))) {
+ info.bit_offset = be32_to_cpup(addr++);
+ info.nbits = be32_to_cpup(addr);
+- if (info.bit_offset >= BITS_PER_BYTE || info.nbits < 1) {
++ if (info.bit_offset >= BITS_PER_BYTE * info.bytes ||
++ info.nbits < 1 ||
++ info.bit_offset + info.nbits > BITS_PER_BYTE * info.bytes) {
+ dev_err(dev, "nvmem: invalid bits on %pOF\n", child);
+ of_node_put(child);
+ return -EINVAL;
+@@ -1617,21 +1619,29 @@ EXPORT_SYMBOL_GPL(nvmem_cell_put);
+ static void nvmem_shift_read_buffer_in_place(struct nvmem_cell_entry *cell, void *buf)
+ {
+ u8 *p, *b;
+- int i, extra, bit_offset = cell->bit_offset;
++ int i, extra, bytes_offset;
++ int bit_offset = cell->bit_offset;
+
+ p = b = buf;
+- if (bit_offset) {
++
++ bytes_offset = bit_offset / BITS_PER_BYTE;
++ b += bytes_offset;
++ bit_offset %= BITS_PER_BYTE;
++
++ if (bit_offset % BITS_PER_BYTE) {
+ /* First shift */
+- *b++ >>= bit_offset;
++ *p = *b++ >> bit_offset;
+
+ /* setup rest of the bytes if any */
+ for (i = 1; i < cell->bytes; i++) {
+ /* Get bits from next byte and shift them towards msb */
+- *p |= *b << (BITS_PER_BYTE - bit_offset);
++ *p++ |= *b << (BITS_PER_BYTE - bit_offset);
+
+- p = b;
+- *b++ >>= bit_offset;
++ *p = *b++ >> bit_offset;
+ }
++ } else if (p != b) {
++ memmove(p, b, cell->bytes - bytes_offset);
++ p += cell->bytes - 1;
+ } else {
+ /* point to the msb */
+ p += cell->bytes - 1;
+--
+2.39.5
+
--- /dev/null
+From 28a7b109d67c2871d7a96136e86ce99b58900231 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Apr 2025 12:22:48 +0100
+Subject: nvmem: core: update raw_len if the bit reading is required
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit 6786484223d5705bf7f919c1e5055d478ebeec32 ]
+
+If NVMEM cell uses bit offset or specifies bit truncation, update
+raw_len manually (following the cell->bytes update), ensuring that the
+NVMEM access is still word-aligned.
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20250411112251.68002-11-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvmem/core.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
+index 3671d156c7c33..d1869e6de3844 100644
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -581,9 +581,11 @@ static int nvmem_cell_info_to_nvmem_cell_entry_nodup(struct nvmem_device *nvmem,
+ cell->nbits = info->nbits;
+ cell->np = info->np;
+
+- if (cell->nbits)
++ if (cell->nbits) {
+ cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
+ BITS_PER_BYTE);
++ cell->raw_len = ALIGN(cell->bytes, nvmem->word_size);
++ }
+
+ if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
+ dev_err(&nvmem->dev,
+--
+2.39.5
+
--- /dev/null
+From 5af84817c963c39301177eb04b735c42a2e8b54e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Apr 2025 12:22:47 +0100
+Subject: nvmem: core: verify cell's raw_len
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit 13bcd440f2ff38cd7e42a179c223d4b833158b33 ]
+
+Check that the NVMEM cell's raw_len is a aligned to word_size. Otherwise
+Otherwise drivers might face incomplete read while accessing the last
+part of the NVMEM cell.
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20250411112251.68002-10-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvmem/core.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
+index 8af2a569c23aa..3671d156c7c33 100644
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -592,6 +592,18 @@ static int nvmem_cell_info_to_nvmem_cell_entry_nodup(struct nvmem_device *nvmem,
+ return -EINVAL;
+ }
+
++ if (!IS_ALIGNED(cell->raw_len, nvmem->word_size)) {
++ dev_err(&nvmem->dev,
++ "cell %s raw len %zd unaligned to nvmem word size %d\n",
++ cell->name ?: "<unknown>", cell->raw_len,
++ nvmem->word_size);
++
++ if (info->raw_len)
++ return -EINVAL;
++
++ cell->raw_len = ALIGN(cell->raw_len, nvmem->word_size);
++ }
++
+ return 0;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From c7837806df09de0bf933a7f4994b0f0fade1db89 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Apr 2025 12:22:49 +0100
+Subject: nvmem: qfprom: switch to 4-byte aligned reads
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit 3566a737db87a9bf360c2fd36433c5149f805f2e ]
+
+All platforms since Snapdragon 8 Gen1 (SM8450) require using 4-byte
+reads to access QFPROM data. While older platforms were more than happy
+with 1-byte reads, change the qfprom driver to use 4-byte reads for all
+the platforms. Specify stride and word size of 4 bytes. To retain
+compatibility with the existing DT and to simplify porting data from
+vendor kernels, use fixup_dt_cell_info in order to bump alignment
+requirements.
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20250411112251.68002-12-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvmem/qfprom.c | 26 ++++++++++++++++++++------
+ 1 file changed, 20 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
+index 116a39e804c70..a872c640b8c5a 100644
+--- a/drivers/nvmem/qfprom.c
++++ b/drivers/nvmem/qfprom.c
+@@ -321,19 +321,32 @@ static int qfprom_reg_read(void *context,
+ unsigned int reg, void *_val, size_t bytes)
+ {
+ struct qfprom_priv *priv = context;
+- u8 *val = _val;
+- int i = 0, words = bytes;
++ u32 *val = _val;
+ void __iomem *base = priv->qfpcorrected;
++ int words = DIV_ROUND_UP(bytes, sizeof(u32));
++ int i;
+
+ if (read_raw_data && priv->qfpraw)
+ base = priv->qfpraw;
+
+- while (words--)
+- *val++ = readb(base + reg + i++);
++ for (i = 0; i < words; i++)
++ *val++ = readl(base + reg + i * sizeof(u32));
+
+ return 0;
+ }
+
++/* Align reads to word boundary */
++static void qfprom_fixup_dt_cell_info(struct nvmem_device *nvmem,
++ struct nvmem_cell_info *cell)
++{
++ unsigned int byte_offset = cell->offset % sizeof(u32);
++
++ cell->bit_offset += byte_offset * BITS_PER_BYTE;
++ cell->offset -= byte_offset;
++ if (byte_offset && !cell->nbits)
++ cell->nbits = cell->bytes * BITS_PER_BYTE;
++}
++
+ static void qfprom_runtime_disable(void *data)
+ {
+ pm_runtime_disable(data);
+@@ -358,10 +371,11 @@ static int qfprom_probe(struct platform_device *pdev)
+ struct nvmem_config econfig = {
+ .name = "qfprom",
+ .add_legacy_fixed_of_cells = true,
+- .stride = 1,
+- .word_size = 1,
++ .stride = 4,
++ .word_size = 4,
+ .id = NVMEM_DEVID_AUTO,
+ .reg_read = qfprom_reg_read,
++ .fixup_dt_cell_info = qfprom_fixup_dt_cell_info,
+ };
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+--
+2.39.5
+
--- /dev/null
+From a6797dddc00e97cb3718370730babe169e6d4e5c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Apr 2025 12:22:42 +0100
+Subject: nvmem: rockchip-otp: add rk3576 variant data
+
+From: Heiko Stuebner <heiko@sntech.de>
+
+[ Upstream commit 50d75a13a9ce880a5ef07a4ccc63ba561cc2e69a ]
+
+The variant works very similar to the rk3588, just with a different
+read-offset and size.
+
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Tested-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20250411112251.68002-5-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvmem/rockchip-otp.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c
+index 3edfbfc2d7220..d88f12c532426 100644
+--- a/drivers/nvmem/rockchip-otp.c
++++ b/drivers/nvmem/rockchip-otp.c
+@@ -274,6 +274,14 @@ static const struct rockchip_data px30_data = {
+ .reg_read = px30_otp_read,
+ };
+
++static const struct rockchip_data rk3576_data = {
++ .size = 0x100,
++ .read_offset = 0x700,
++ .clks = px30_otp_clocks,
++ .num_clks = ARRAY_SIZE(px30_otp_clocks),
++ .reg_read = rk3588_otp_read,
++};
++
+ static const char * const rk3588_otp_clocks[] = {
+ "otp", "apb_pclk", "phy", "arb",
+ };
+@@ -295,6 +303,10 @@ static const struct of_device_id rockchip_otp_match[] = {
+ .compatible = "rockchip,rk3308-otp",
+ .data = &px30_data,
+ },
++ {
++ .compatible = "rockchip,rk3576-otp",
++ .data = &rk3576_data,
++ },
+ {
+ .compatible = "rockchip,rk3588-otp",
+ .data = &rk3588_data,
+--
+2.39.5
+
--- /dev/null
+From c0a5f0d237538ec3ea246f3b1cb2936911f2666c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Apr 2025 12:22:39 +0100
+Subject: nvmem: rockchip-otp: Move read-offset into variant-data
+
+From: Heiko Stuebner <heiko@sntech.de>
+
+[ Upstream commit 6907e8093b3070d877ee607e5ceede60cfd08bde ]
+
+The RK3588 has an offset into the OTP area where the readable area begins
+and automatically adds this to the start address.
+Other variants are very much similar to rk3588, just with a different
+offset, so move that value into variant-data.
+
+To match the size in bytes, store this value also in bytes and not in
+number of blocks.
+
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Tested-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20250411112251.68002-2-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvmem/rockchip-otp.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c
+index ebc3f0b24166b..3edfbfc2d7220 100644
+--- a/drivers/nvmem/rockchip-otp.c
++++ b/drivers/nvmem/rockchip-otp.c
+@@ -59,7 +59,6 @@
+ #define RK3588_OTPC_AUTO_EN 0x08
+ #define RK3588_OTPC_INT_ST 0x84
+ #define RK3588_OTPC_DOUT0 0x20
+-#define RK3588_NO_SECURE_OFFSET 0x300
+ #define RK3588_NBYTES 4
+ #define RK3588_BURST_NUM 1
+ #define RK3588_BURST_SHIFT 8
+@@ -69,6 +68,7 @@
+
+ struct rockchip_data {
+ int size;
++ int read_offset;
+ const char * const *clks;
+ int num_clks;
+ nvmem_reg_read_t reg_read;
+@@ -196,7 +196,7 @@ static int rk3588_otp_read(void *context, unsigned int offset,
+ addr_start = round_down(offset, RK3588_NBYTES) / RK3588_NBYTES;
+ addr_end = round_up(offset + bytes, RK3588_NBYTES) / RK3588_NBYTES;
+ addr_len = addr_end - addr_start;
+- addr_start += RK3588_NO_SECURE_OFFSET;
++ addr_start += otp->data->read_offset / RK3588_NBYTES;
+
+ buf = kzalloc(array_size(addr_len, RK3588_NBYTES), GFP_KERNEL);
+ if (!buf)
+@@ -280,6 +280,7 @@ static const char * const rk3588_otp_clocks[] = {
+
+ static const struct rockchip_data rk3588_data = {
+ .size = 0x400,
++ .read_offset = 0xc00,
+ .clks = rk3588_otp_clocks,
+ .num_clks = ARRAY_SIZE(rk3588_otp_clocks),
+ .reg_read = rk3588_otp_read,
+--
+2.39.5
+
--- /dev/null
+From 8ebbbdb53ca3a45ae211002a067662e6d79f226b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Apr 2025 16:06:21 +1000
+Subject: nvmet-tcp: don't restore null sk_state_change
+
+From: Alistair Francis <alistair.francis@wdc.com>
+
+[ Upstream commit 46d22b47df2741996af277a2838b95f130436c13 ]
+
+queue->state_change is set as part of nvmet_tcp_set_queue_sock(), but if
+the TCP connection isn't established when nvmet_tcp_set_queue_sock() is
+called then queue->state_change isn't set and sock->sk->sk_state_change
+isn't replaced.
+
+As such we don't need to restore sock->sk->sk_state_change if
+queue->state_change is NULL.
+
+This avoids NULL pointer dereferences such as this:
+
+[ 286.462026][ C0] BUG: kernel NULL pointer dereference, address: 0000000000000000
+[ 286.462814][ C0] #PF: supervisor instruction fetch in kernel mode
+[ 286.463796][ C0] #PF: error_code(0x0010) - not-present page
+[ 286.464392][ C0] PGD 8000000140620067 P4D 8000000140620067 PUD 114201067 PMD 0
+[ 286.465086][ C0] Oops: Oops: 0010 [#1] SMP KASAN PTI
+[ 286.465559][ C0] CPU: 0 UID: 0 PID: 1628 Comm: nvme Not tainted 6.15.0-rc2+ #11 PREEMPT(voluntary)
+[ 286.466393][ C0] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-3.fc41 04/01/2014
+[ 286.467147][ C0] RIP: 0010:0x0
+[ 286.467420][ C0] Code: Unable to access opcode bytes at 0xffffffffffffffd6.
+[ 286.467977][ C0] RSP: 0018:ffff8883ae008580 EFLAGS: 00010246
+[ 286.468425][ C0] RAX: 0000000000000000 RBX: ffff88813fd34100 RCX: ffffffffa386cc43
+[ 286.469019][ C0] RDX: 1ffff11027fa68b6 RSI: 0000000000000008 RDI: ffff88813fd34100
+[ 286.469545][ C0] RBP: ffff88813fd34160 R08: 0000000000000000 R09: ffffed1027fa682c
+[ 286.470072][ C0] R10: ffff88813fd34167 R11: 0000000000000000 R12: ffff88813fd344c3
+[ 286.470585][ C0] R13: ffff88813fd34112 R14: ffff88813fd34aec R15: ffff888132cdd268
+[ 286.471070][ C0] FS: 00007fe3c04c7d80(0000) GS:ffff88840743f000(0000) knlGS:0000000000000000
+[ 286.471644][ C0] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 286.472543][ C0] CR2: ffffffffffffffd6 CR3: 000000012daca000 CR4: 00000000000006f0
+[ 286.473500][ C0] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[ 286.474467][ C0] DR3: 0000000000000000 DR6: 00000000ffff07f0 DR7: 0000000000000400
+[ 286.475453][ C0] Call Trace:
+[ 286.476102][ C0] <IRQ>
+[ 286.476719][ C0] tcp_fin+0x2bb/0x440
+[ 286.477429][ C0] tcp_data_queue+0x190f/0x4e60
+[ 286.478174][ C0] ? __build_skb_around+0x234/0x330
+[ 286.478940][ C0] ? rcu_is_watching+0x11/0xb0
+[ 286.479659][ C0] ? __pfx_tcp_data_queue+0x10/0x10
+[ 286.480431][ C0] ? tcp_try_undo_loss+0x640/0x6c0
+[ 286.481196][ C0] ? seqcount_lockdep_reader_access.constprop.0+0x82/0x90
+[ 286.482046][ C0] ? kvm_clock_get_cycles+0x14/0x30
+[ 286.482769][ C0] ? ktime_get+0x66/0x150
+[ 286.483433][ C0] ? rcu_is_watching+0x11/0xb0
+[ 286.484146][ C0] tcp_rcv_established+0x6e4/0x2050
+[ 286.484857][ C0] ? rcu_is_watching+0x11/0xb0
+[ 286.485523][ C0] ? ipv4_dst_check+0x160/0x2b0
+[ 286.486203][ C0] ? __pfx_tcp_rcv_established+0x10/0x10
+[ 286.486917][ C0] ? lock_release+0x217/0x2c0
+[ 286.487595][ C0] tcp_v4_do_rcv+0x4d6/0x9b0
+[ 286.488279][ C0] tcp_v4_rcv+0x2af8/0x3e30
+[ 286.488904][ C0] ? raw_local_deliver+0x51b/0xad0
+[ 286.489551][ C0] ? rcu_is_watching+0x11/0xb0
+[ 286.490198][ C0] ? __pfx_tcp_v4_rcv+0x10/0x10
+[ 286.490813][ C0] ? __pfx_raw_local_deliver+0x10/0x10
+[ 286.491487][ C0] ? __pfx_nf_confirm+0x10/0x10 [nf_conntrack]
+[ 286.492275][ C0] ? rcu_is_watching+0x11/0xb0
+[ 286.492900][ C0] ip_protocol_deliver_rcu+0x8f/0x370
+[ 286.493579][ C0] ip_local_deliver_finish+0x297/0x420
+[ 286.494268][ C0] ip_local_deliver+0x168/0x430
+[ 286.494867][ C0] ? __pfx_ip_local_deliver+0x10/0x10
+[ 286.495498][ C0] ? __pfx_ip_local_deliver_finish+0x10/0x10
+[ 286.496204][ C0] ? ip_rcv_finish_core+0x19a/0x1f20
+[ 286.496806][ C0] ? lock_release+0x217/0x2c0
+[ 286.497414][ C0] ip_rcv+0x455/0x6e0
+[ 286.497945][ C0] ? __pfx_ip_rcv+0x10/0x10
+[ 286.498550][ C0] ? rcu_is_watching+0x11/0xb0
+[ 286.499137][ C0] ? __pfx_ip_rcv_finish+0x10/0x10
+[ 286.499763][ C0] ? lock_release+0x217/0x2c0
+[ 286.500327][ C0] ? dl_scaled_delta_exec+0xd1/0x2c0
+[ 286.500922][ C0] ? __pfx_ip_rcv+0x10/0x10
+[ 286.501480][ C0] __netif_receive_skb_one_core+0x166/0x1b0
+[ 286.502173][ C0] ? __pfx___netif_receive_skb_one_core+0x10/0x10
+[ 286.502903][ C0] ? lock_acquire+0x2b2/0x310
+[ 286.503487][ C0] ? process_backlog+0x372/0x1350
+[ 286.504087][ C0] ? lock_release+0x217/0x2c0
+[ 286.504642][ C0] process_backlog+0x3b9/0x1350
+[ 286.505214][ C0] ? process_backlog+0x372/0x1350
+[ 286.505779][ C0] __napi_poll.constprop.0+0xa6/0x490
+[ 286.506363][ C0] net_rx_action+0x92e/0xe10
+[ 286.506889][ C0] ? __pfx_net_rx_action+0x10/0x10
+[ 286.507437][ C0] ? timerqueue_add+0x1f0/0x320
+[ 286.507977][ C0] ? sched_clock_cpu+0x68/0x540
+[ 286.508492][ C0] ? lock_acquire+0x2b2/0x310
+[ 286.509043][ C0] ? kvm_sched_clock_read+0xd/0x20
+[ 286.509607][ C0] ? handle_softirqs+0x1aa/0x7d0
+[ 286.510187][ C0] handle_softirqs+0x1f2/0x7d0
+[ 286.510754][ C0] ? __pfx_handle_softirqs+0x10/0x10
+[ 286.511348][ C0] ? irqtime_account_irq+0x181/0x290
+[ 286.511937][ C0] ? __dev_queue_xmit+0x85d/0x3450
+[ 286.512510][ C0] do_softirq.part.0+0x89/0xc0
+[ 286.513100][ C0] </IRQ>
+[ 286.513548][ C0] <TASK>
+[ 286.513953][ C0] __local_bh_enable_ip+0x112/0x140
+[ 286.514522][ C0] ? __dev_queue_xmit+0x85d/0x3450
+[ 286.515072][ C0] __dev_queue_xmit+0x872/0x3450
+[ 286.515619][ C0] ? nft_do_chain+0xe16/0x15b0 [nf_tables]
+[ 286.516252][ C0] ? __pfx___dev_queue_xmit+0x10/0x10
+[ 286.516817][ C0] ? selinux_ip_postroute+0x43c/0xc50
+[ 286.517433][ C0] ? __pfx_selinux_ip_postroute+0x10/0x10
+[ 286.518061][ C0] ? rcu_is_watching+0x11/0xb0
+[ 286.518606][ C0] ? ip_output+0x164/0x4a0
+[ 286.519149][ C0] ? rcu_is_watching+0x11/0xb0
+[ 286.519671][ C0] ? ip_finish_output2+0x17d5/0x1fb0
+[ 286.520258][ C0] ip_finish_output2+0xb4b/0x1fb0
+[ 286.520787][ C0] ? __pfx_ip_finish_output2+0x10/0x10
+[ 286.521355][ C0] ? __ip_finish_output+0x15d/0x750
+[ 286.521890][ C0] ip_output+0x164/0x4a0
+[ 286.522372][ C0] ? __pfx_ip_output+0x10/0x10
+[ 286.522872][ C0] ? rcu_is_watching+0x11/0xb0
+[ 286.523402][ C0] ? _raw_spin_unlock_irqrestore+0x4c/0x60
+[ 286.524031][ C0] ? __pfx_ip_finish_output+0x10/0x10
+[ 286.524605][ C0] ? __ip_queue_xmit+0x999/0x2260
+[ 286.525200][ C0] ? rcu_is_watching+0x11/0xb0
+[ 286.525744][ C0] ? ipv4_dst_check+0x16a/0x2b0
+[ 286.526279][ C0] ? lock_release+0x217/0x2c0
+[ 286.526793][ C0] __ip_queue_xmit+0x1883/0x2260
+[ 286.527324][ C0] ? __skb_clone+0x54c/0x730
+[ 286.527827][ C0] __tcp_transmit_skb+0x209b/0x37a0
+[ 286.528374][ C0] ? __pfx___tcp_transmit_skb+0x10/0x10
+[ 286.528952][ C0] ? rcu_is_watching+0x11/0xb0
+[ 286.529472][ C0] ? seqcount_lockdep_reader_access.constprop.0+0x82/0x90
+[ 286.530152][ C0] ? trace_hardirqs_on+0x12/0x120
+[ 286.530691][ C0] tcp_write_xmit+0xb81/0x88b0
+[ 286.531224][ C0] ? mod_memcg_state+0x4d/0x60
+[ 286.531736][ C0] ? rcu_is_watching+0x11/0xb0
+[ 286.532253][ C0] __tcp_push_pending_frames+0x90/0x320
+[ 286.532826][ C0] tcp_send_fin+0x141/0xb50
+[ 286.533352][ C0] ? __pfx_tcp_send_fin+0x10/0x10
+[ 286.533908][ C0] ? __local_bh_enable_ip+0xab/0x140
+[ 286.534495][ C0] inet_shutdown+0x243/0x320
+[ 286.535077][ C0] nvme_tcp_alloc_queue+0xb3b/0x2590 [nvme_tcp]
+[ 286.535709][ C0] ? do_raw_spin_lock+0x129/0x260
+[ 286.536314][ C0] ? __pfx_nvme_tcp_alloc_queue+0x10/0x10 [nvme_tcp]
+[ 286.536996][ C0] ? do_raw_spin_unlock+0x54/0x1e0
+[ 286.537550][ C0] ? _raw_spin_unlock+0x29/0x50
+[ 286.538127][ C0] ? do_raw_spin_lock+0x129/0x260
+[ 286.538664][ C0] ? __pfx_do_raw_spin_lock+0x10/0x10
+[ 286.539249][ C0] ? nvme_tcp_alloc_admin_queue+0xd5/0x340 [nvme_tcp]
+[ 286.539892][ C0] ? __wake_up+0x40/0x60
+[ 286.540392][ C0] nvme_tcp_alloc_admin_queue+0xd5/0x340 [nvme_tcp]
+[ 286.541047][ C0] ? rcu_is_watching+0x11/0xb0
+[ 286.541589][ C0] nvme_tcp_setup_ctrl+0x8b/0x7a0 [nvme_tcp]
+[ 286.542254][ C0] ? _raw_spin_unlock_irqrestore+0x4c/0x60
+[ 286.542887][ C0] ? __pfx_nvme_tcp_setup_ctrl+0x10/0x10 [nvme_tcp]
+[ 286.543568][ C0] ? trace_hardirqs_on+0x12/0x120
+[ 286.544166][ C0] ? _raw_spin_unlock_irqrestore+0x35/0x60
+[ 286.544792][ C0] ? nvme_change_ctrl_state+0x196/0x2e0 [nvme_core]
+[ 286.545477][ C0] nvme_tcp_create_ctrl+0x839/0xb90 [nvme_tcp]
+[ 286.546126][ C0] nvmf_dev_write+0x3db/0x7e0 [nvme_fabrics]
+[ 286.546775][ C0] ? rw_verify_area+0x69/0x520
+[ 286.547334][ C0] vfs_write+0x218/0xe90
+[ 286.547854][ C0] ? do_syscall_64+0x9f/0x190
+[ 286.548408][ C0] ? trace_hardirqs_on_prepare+0xdb/0x120
+[ 286.549037][ C0] ? syscall_exit_to_user_mode+0x93/0x280
+[ 286.549659][ C0] ? __pfx_vfs_write+0x10/0x10
+[ 286.550259][ C0] ? do_syscall_64+0x9f/0x190
+[ 286.550840][ C0] ? syscall_exit_to_user_mode+0x8e/0x280
+[ 286.551516][ C0] ? trace_hardirqs_on_prepare+0xdb/0x120
+[ 286.552180][ C0] ? syscall_exit_to_user_mode+0x93/0x280
+[ 286.552834][ C0] ? ksys_read+0xf5/0x1c0
+[ 286.553386][ C0] ? __pfx_ksys_read+0x10/0x10
+[ 286.553964][ C0] ksys_write+0xf5/0x1c0
+[ 286.554499][ C0] ? __pfx_ksys_write+0x10/0x10
+[ 286.555072][ C0] ? trace_hardirqs_on_prepare+0xdb/0x120
+[ 286.555698][ C0] ? syscall_exit_to_user_mode+0x93/0x280
+[ 286.556319][ C0] ? do_syscall_64+0x54/0x190
+[ 286.556866][ C0] do_syscall_64+0x93/0x190
+[ 286.557420][ C0] ? rcu_read_unlock+0x17/0x60
+[ 286.557986][ C0] ? rcu_is_watching+0x11/0xb0
+[ 286.558526][ C0] ? lock_release+0x217/0x2c0
+[ 286.559087][ C0] ? rcu_is_watching+0x11/0xb0
+[ 286.559659][ C0] ? count_memcg_events.constprop.0+0x4a/0x60
+[ 286.560476][ C0] ? exc_page_fault+0x7a/0x110
+[ 286.561064][ C0] ? rcu_is_watching+0x11/0xb0
+[ 286.561647][ C0] ? lock_release+0x217/0x2c0
+[ 286.562257][ C0] ? do_user_addr_fault+0x171/0xa00
+[ 286.562839][ C0] ? do_user_addr_fault+0x4a2/0xa00
+[ 286.563453][ C0] ? irqentry_exit_to_user_mode+0x84/0x270
+[ 286.564112][ C0] ? rcu_is_watching+0x11/0xb0
+[ 286.564677][ C0] ? irqentry_exit_to_user_mode+0x84/0x270
+[ 286.565317][ C0] ? trace_hardirqs_on_prepare+0xdb/0x120
+[ 286.565922][ C0] entry_SYSCALL_64_after_hwframe+0x76/0x7e
+[ 286.566542][ C0] RIP: 0033:0x7fe3c05e6504
+[ 286.567102][ C0] Code: c7 00 16 00 00 00 b8 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 80 3d c5 8b 10 00 00 74 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 55 48 89 e5 48 83 ec 20 48 89
+[ 286.568931][ C0] RSP: 002b:00007fff76444f58 EFLAGS: 00000202 ORIG_RAX: 0000000000000001
+[ 286.569807][ C0] RAX: ffffffffffffffda RBX: 000000003b40d930 RCX: 00007fe3c05e6504
+[ 286.570621][ C0] RDX: 00000000000000cf RSI: 000000003b40d930 RDI: 0000000000000003
+[ 286.571443][ C0] RBP: 0000000000000003 R08: 00000000000000cf R09: 000000003b40d930
+[ 286.572246][ C0] R10: 0000000000000000 R11: 0000000000000202 R12: 000000003b40cd60
+[ 286.573069][ C0] R13: 00000000000000cf R14: 00007fe3c07417f8 R15: 00007fe3c073502e
+[ 286.573886][ C0] </TASK>
+
+Closes: https://lore.kernel.org/linux-nvme/5hdonndzoqa265oq3bj6iarwtfk5dewxxjtbjvn5uqnwclpwt6@a2n6w3taxxex/
+Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
+Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
+Tested-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/target/tcp.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
+index 4f9cac8a5abe0..259ad77c03c50 100644
+--- a/drivers/nvme/target/tcp.c
++++ b/drivers/nvme/target/tcp.c
+@@ -1560,6 +1560,9 @@ static void nvmet_tcp_restore_socket_callbacks(struct nvmet_tcp_queue *queue)
+ {
+ struct socket *sock = queue->sock;
+
++ if (!queue->state_change)
++ return;
++
+ write_lock_bh(&sock->sk->sk_callback_lock);
+ sock->sk->sk_data_ready = queue->data_ready;
+ sock->sk->sk_state_change = queue->state_change;
+--
+2.39.5
+
--- /dev/null
+From 62db3a5bf283982e2ecab1e2712f103975f005b4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Mar 2025 12:29:00 -0700
+Subject: objtool: Fix error handling inconsistencies in check()
+
+From: Josh Poimboeuf <jpoimboe@kernel.org>
+
+[ Upstream commit b745962cb97569aad026806bb0740663cf813147 ]
+
+Make sure all fatal errors are funneled through the 'out' label with a
+negative ret.
+
+Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Brendan Jackman <jackmanb@google.com>
+Link: https://lore.kernel.org/r/0f49d6a27a080b4012e84e6df1e23097f44cc082.1741975349.git.jpoimboe@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/objtool/check.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/tools/objtool/check.c b/tools/objtool/check.c
+index 0757b98b0a445..4fce0074076f3 100644
+--- a/tools/objtool/check.c
++++ b/tools/objtool/check.c
+@@ -4758,8 +4758,10 @@ int check(struct objtool_file *file)
+ init_cfi_state(&force_undefined_cfi);
+ force_undefined_cfi.force_undefined = true;
+
+- if (!cfi_hash_alloc(1UL << (file->elf->symbol_bits - 3)))
++ if (!cfi_hash_alloc(1UL << (file->elf->symbol_bits - 3))) {
++ ret = -1;
+ goto out;
++ }
+
+ cfi_hash_add(&init_cfi);
+ cfi_hash_add(&func_cfi);
+@@ -4776,7 +4778,7 @@ int check(struct objtool_file *file)
+ if (opts.retpoline) {
+ ret = validate_retpoline(file);
+ if (ret < 0)
+- return ret;
++ goto out;
+ warnings += ret;
+ }
+
+@@ -4812,7 +4814,7 @@ int check(struct objtool_file *file)
+ */
+ ret = validate_unrets(file);
+ if (ret < 0)
+- return ret;
++ goto out;
+ warnings += ret;
+ }
+
+@@ -4875,7 +4877,7 @@ int check(struct objtool_file *file)
+ if (opts.prefix) {
+ ret = add_prefix_symbols(file);
+ if (ret < 0)
+- return ret;
++ goto out;
+ warnings += ret;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From cf78c17cdc92d09fc97409f43d53a6b2809cbc6b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Mar 2025 14:55:58 -0700
+Subject: objtool: Properly disable uaccess validation
+
+From: Josh Poimboeuf <jpoimboe@kernel.org>
+
+[ Upstream commit e1a9dda74dbffbc3fa2069ff418a1876dc99fb14 ]
+
+If opts.uaccess isn't set, the uaccess validation is disabled, but only
+partially: it doesn't read the uaccess_safe_builtin list but still tries
+to do the validation. Disable it completely to prevent false warnings.
+
+Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Link: https://lore.kernel.org/r/0e95581c1d2107fb5f59418edf2b26bba38b0cbb.1742852846.git.jpoimboe@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/objtool/check.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/tools/objtool/check.c b/tools/objtool/check.c
+index bea6461ac340d..0757b98b0a445 100644
+--- a/tools/objtool/check.c
++++ b/tools/objtool/check.c
+@@ -3353,7 +3353,7 @@ static int handle_insn_ops(struct instruction *insn,
+ if (update_cfi_state(insn, next_insn, &state->cfi, op))
+ return 1;
+
+- if (!insn->alt_group)
++ if (!opts.uaccess || !insn->alt_group)
+ continue;
+
+ if (op->dest.type == OP_DEST_PUSHF) {
+@@ -3820,6 +3820,9 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
+ return 0;
+
+ case INSN_STAC:
++ if (!opts.uaccess)
++ break;
++
+ if (state.uaccess) {
+ WARN_INSN(insn, "recursive UACCESS enable");
+ return 1;
+@@ -3829,6 +3832,9 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
+ break;
+
+ case INSN_CLAC:
++ if (!opts.uaccess)
++ break;
++
+ if (!state.uaccess && func) {
+ WARN_INSN(insn, "redundant UACCESS disable");
+ return 1;
+@@ -4304,7 +4310,8 @@ static int validate_symbol(struct objtool_file *file, struct section *sec,
+ if (!insn || insn->ignore || insn->visited)
+ return 0;
+
+- state->uaccess = sym->uaccess_safe;
++ if (opts.uaccess)
++ state->uaccess = sym->uaccess_safe;
+
+ ret = validate_branch(file, insn_func(insn), insn, *state);
+ if (ret)
+--
+2.39.5
+
--- /dev/null
+From 44b588a89f8a92a2c49793ee8d606c309f83bfd8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 09:26:03 +0530
+Subject: Octeontx2-af: RPM: Register driver with PCI subsys IDs
+
+From: Hariprasad Kelam <hkelam@marvell.com>
+
+[ Upstream commit fc9167192f29485be5621e2e9c8208b717b65753 ]
+
+Although the PCI device ID and Vendor ID for the RPM (MAC) block
+have remained the same across Octeon CN10K and the next-generation
+CN20K silicon, Hardware architecture has changed (NIX mapped RPMs
+and RFOE Mapped RPMs).
+
+Add PCI Subsystem IDs to the device table to ensure that this driver
+can be probed from NIX mapped RPM devices only.
+
+Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
+Link: https://patch.msgid.link/20250224035603.1220913-1-hkelam@marvell.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/octeontx2/af/cgx.c | 14 ++++++++++++--
+ drivers/net/ethernet/marvell/octeontx2/af/rvu.h | 2 ++
+ 2 files changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+index e43c4608d3ba3..971993586fb49 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+@@ -66,8 +66,18 @@ static int cgx_fwi_link_change(struct cgx *cgx, int lmac_id, bool en);
+ /* Supported devices */
+ static const struct pci_device_id cgx_id_table[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_CGX) },
+- { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_RPM) },
+- { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10KB_RPM) },
++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_RPM,
++ PCI_ANY_ID, PCI_SUBSYS_DEVID_CN10K_A) },
++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_RPM,
++ PCI_ANY_ID, PCI_SUBSYS_DEVID_CNF10K_A) },
++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_RPM,
++ PCI_ANY_ID, PCI_SUBSYS_DEVID_CNF10K_B) },
++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10KB_RPM,
++ PCI_ANY_ID, PCI_SUBSYS_DEVID_CN10K_B) },
++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10KB_RPM,
++ PCI_ANY_ID, PCI_SUBSYS_DEVID_CN20KA) },
++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10KB_RPM,
++ PCI_ANY_ID, PCI_SUBSYS_DEVID_CNF20KA) },
+ { 0, } /* end of table */
+ };
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+index 8555edbb1c8f9..f94bf04788e98 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+@@ -30,6 +30,8 @@
+ #define PCI_SUBSYS_DEVID_CNF10K_A 0xBA00
+ #define PCI_SUBSYS_DEVID_CNF10K_B 0xBC00
+ #define PCI_SUBSYS_DEVID_CN10K_B 0xBD00
++#define PCI_SUBSYS_DEVID_CN20KA 0xC220
++#define PCI_SUBSYS_DEVID_CNF20KA 0xC320
+
+ /* PCI BAR nos */
+ #define PCI_AF_REG_BAR_NUM 0
+--
+2.39.5
+
--- /dev/null
+From 43c8bf678e68b19bbd1285e0b84ce2af21803805 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Mar 2025 20:47:25 +0000
+Subject: orangefs: Do not truncate file size
+
+From: Matthew Wilcox (Oracle) <willy@infradead.org>
+
+[ Upstream commit 062e8093592fb866b8e016641a8b27feb6ac509d ]
+
+'len' is used to store the result of i_size_read(), so making 'len'
+a size_t results in truncation to 4GiB on 32-bit systems.
+
+Signed-off-by: "Matthew Wilcox (Oracle)" <willy@infradead.org>
+Link: https://lore.kernel.org/r/20250305204734.1475264-2-willy@infradead.org
+Tested-by: Mike Marshall <hubcap@omnibond.com>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/orangefs/inode.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
+index aae6d2b8767df..63d7c1ca0dfd3 100644
+--- a/fs/orangefs/inode.c
++++ b/fs/orangefs/inode.c
+@@ -23,9 +23,9 @@ static int orangefs_writepage_locked(struct page *page,
+ struct orangefs_write_range *wr = NULL;
+ struct iov_iter iter;
+ struct bio_vec bv;
+- size_t len, wlen;
++ size_t wlen;
+ ssize_t ret;
+- loff_t off;
++ loff_t len, off;
+
+ set_page_writeback(page);
+
+@@ -91,8 +91,7 @@ static int orangefs_writepages_work(struct orangefs_writepages *ow,
+ struct orangefs_write_range *wrp, wr;
+ struct iov_iter iter;
+ ssize_t ret;
+- size_t len;
+- loff_t off;
++ loff_t len, off;
+ int i;
+
+ len = i_size_read(inode);
+--
+2.39.5
+
--- /dev/null
+From e579727b2972dd7e328a0df00b34f88eb92045b1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 10:35:56 +0200
+Subject: PCI: brcmstb: Add a softdep to MIP MSI-X driver
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Stanimir Varbanov <svarbanov@suse.de>
+
+[ Upstream commit 2294059118c550464dd8906286324d90c33b152b ]
+
+Then the brcmstb PCIe driver and MIP MSI-X interrupt controller
+drivers are built as modules there could be a race in probing.
+
+To avoid this, add a softdep to MIP driver to guarantee that
+MIP driver will be load first.
+
+Signed-off-by: Stanimir Varbanov <svarbanov@suse.de>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Tested-by: Ivan T. Ivanov <iivanov@suse.de>
+Link: https://lore.kernel.org/r/20250224083559.47645-5-svarbanov@suse.de
+[kwilczynski: commit log]
+Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/pcie-brcmstb.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
+index 32ffb0c14c3ca..81f085cebf627 100644
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -1947,3 +1947,4 @@ module_platform_driver(brcm_pcie_driver);
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Broadcom STB PCIe RC driver");
+ MODULE_AUTHOR("Broadcom");
++MODULE_SOFTDEP("pre: irq_bcm2712_mip");
+--
+2.39.5
+
--- /dev/null
+From 5455770e0f68048d58d0db6a21328c9c360e9c80 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 10:35:58 +0200
+Subject: PCI: brcmstb: Expand inbound window size up to 64GB
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Stanimir Varbanov <svarbanov@suse.de>
+
+[ Upstream commit 25a98c727015638baffcfa236e3f37b70cedcf87 ]
+
+The BCM2712 memory map can support up to 64GB of system memory, thus
+expand the inbound window size in calculation helper function.
+
+The change is safe for the currently supported SoCs that have smaller
+inbound window sizes.
+
+Signed-off-by: Stanimir Varbanov <svarbanov@suse.de>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Reviewed-by: Jim Quinlan <james.quinlan@broadcom.com>
+Tested-by: Ivan T. Ivanov <iivanov@suse.de>
+Link: https://lore.kernel.org/r/20250224083559.47645-7-svarbanov@suse.de
+[kwilczynski: commit log]
+Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/pcie-brcmstb.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
+index 792d24cea5747..32ffb0c14c3ca 100644
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -309,8 +309,8 @@ static int brcm_pcie_encode_ibar_size(u64 size)
+ if (log2_in >= 12 && log2_in <= 15)
+ /* Covers 4KB to 32KB (inclusive) */
+ return (log2_in - 12) + 0x1c;
+- else if (log2_in >= 16 && log2_in <= 35)
+- /* Covers 64KB to 32GB, (inclusive) */
++ else if (log2_in >= 16 && log2_in <= 36)
++ /* Covers 64KB to 64GB, (inclusive) */
+ return log2_in - 15;
+ /* Something is awry so disable */
+ return 0;
+--
+2.39.5
+
--- /dev/null
+From cd2bcab75a91aa66f98922149e4e58c2845b46de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Mar 2025 15:15:46 -0500
+Subject: PCI: dwc: ep: Ensure proper iteration over outbound map windows
+
+From: Frank Li <Frank.Li@nxp.com>
+
+[ Upstream commit f3e1dccba0a0833fc9a05fb838ebeb6ea4ca0e1a ]
+
+Most systems' PCIe outbound map windows have non-zero physical addresses,
+but the possibility of encountering zero increased after following commit
+("PCI: dwc: Use parent_bus_offset").
+
+'ep->outbound_addr[n]', representing 'parent_bus_address', might be 0 on
+some hardware, which trims high address bits through bus fabric before
+sending to the PCIe controller.
+
+Replace the iteration logic with 'for_each_set_bit()' to ensure only
+allocated map windows are iterated when determining the ATU index from a
+given address.
+
+Link: https://lore.kernel.org/r/20250315201548.858189-12-helgaas@kernel.org
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/dwc/pcie-designware-ep.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
+index dea19250598a6..9e7e94f32b436 100644
+--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
++++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
+@@ -280,7 +280,7 @@ static int dw_pcie_find_index(struct dw_pcie_ep *ep, phys_addr_t addr,
+ u32 index;
+ struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+
+- for (index = 0; index < pci->num_ob_windows; index++) {
++ for_each_set_bit(index, ep->ob_window_map, pci->num_ob_windows) {
+ if (ep->outbound_addr[index] != addr)
+ continue;
+ *atu_index = index;
+--
+2.39.5
+
--- /dev/null
+From dbf5654ac17d8d4fa6f95f59065f95b1809a30d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Mar 2025 15:15:36 -0500
+Subject: PCI: dwc: Use resource start as ioremap() input in
+ dw_pcie_pme_turn_off()
+
+From: Frank Li <Frank.Li@nxp.com>
+
+[ Upstream commit 8f4a489b370e6612700aa16b9e4373b2d85d7503 ]
+
+The msg_res region translates writes into PCIe Message TLPs. Previously we
+mapped this region using atu.cpu_addr, the input address programmed into
+the ATU.
+
+"cpu_addr" is a misnomer because when a bus fabric translates addresses
+between the CPU and the ATU, the ATU input address is different from the
+CPU address. A future patch will rename "cpu_addr" and correct the value
+to be the ATU input address instead of the CPU physical address.
+
+Map the msg_res region before writing to it using the msg_res resource
+start, a CPU physical address.
+
+Link: https://lore.kernel.org/r/20250315201548.858189-2-helgaas@kernel.org
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/dwc/pcie-designware-host.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
+index 120e2aca5164a..d428457d9c432 100644
+--- a/drivers/pci/controller/dwc/pcie-designware-host.c
++++ b/drivers/pci/controller/dwc/pcie-designware-host.c
+@@ -902,7 +902,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci)
+ if (ret)
+ return ret;
+
+- mem = ioremap(atu.cpu_addr, pci->region_align);
++ mem = ioremap(pci->pp.msg_res->start, pci->region_align);
+ if (!mem)
+ return -ENOMEM;
+
+--
+2.39.5
+
--- /dev/null
+From 93f381c5e867e370af8a6a71ea11a0b5167ebd83 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jan 2025 13:30:43 +0100
+Subject: PCI: endpoint: pci-epf-test: Fix double free that causes kernel to
+ oops
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Christian Bruel <christian.bruel@foss.st.com>
+
+[ Upstream commit 934e9d137d937706004c325fa1474f9e3f1ba10a ]
+
+Fix a kernel oops found while testing the stm32_pcie Endpoint driver
+with handling of PERST# deassertion:
+
+During EP initialization, pci_epf_test_alloc_space() allocates all BARs,
+which are further freed if epc_set_bar() fails (for instance, due to no
+free inbound window).
+
+However, when pci_epc_set_bar() fails, the error path:
+
+ pci_epc_set_bar() ->
+ pci_epf_free_space()
+
+does not clear the previous assignment to epf_test->reg[bar].
+
+Then, if the host reboots, the PERST# deassertion restarts the BAR
+allocation sequence with the same allocation failure (no free inbound
+window), creating a double free situation since epf_test->reg[bar] was
+deallocated and is still non-NULL.
+
+Thus, make sure that pci_epf_alloc_space() and pci_epf_free_space()
+invocations are symmetric, and as such, set epf_test->reg[bar] to NULL
+when memory is freed.
+
+Reviewed-by: Niklas Cassel <cassel@kernel.org>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Christian Bruel <christian.bruel@foss.st.com>
+Link: https://lore.kernel.org/r/20250124123043.96112-1-christian.bruel@foss.st.com
+[kwilczynski: commit log]
+Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/endpoint/functions/pci-epf-test.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
+index 14b4c68ab4e1a..21aa3709e2577 100644
+--- a/drivers/pci/endpoint/functions/pci-epf-test.c
++++ b/drivers/pci/endpoint/functions/pci-epf-test.c
+@@ -703,6 +703,7 @@ static int pci_epf_test_set_bar(struct pci_epf *epf)
+ if (ret) {
+ pci_epf_free_space(epf, epf_test->reg[bar], bar,
+ PRIMARY_INTERFACE);
++ epf_test->reg[bar] = NULL;
+ dev_err(dev, "Failed to set BAR%d\n", bar);
+ if (bar == test_reg_bar)
+ return ret;
+@@ -878,6 +879,7 @@ static void pci_epf_test_free_space(struct pci_epf *epf)
+
+ pci_epf_free_space(epf, epf_test->reg[bar], bar,
+ PRIMARY_INTERFACE);
++ epf_test->reg[bar] = NULL;
+ }
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 5c8798c18a788a2161e5a208ecfd5e54b49d7716 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 5 Dec 2024 12:24:20 +0530
+Subject: PCI: epf-mhi: Update device ID for SA8775P
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mrinmay Sarkar <quic_msarkar@quicinc.com>
+
+[ Upstream commit 4f13dd9e2b1d2b317bb36704f8a7bd1d3017f7a2 ]
+
+Update device ID for the Qcom SA8775P SoC.
+
+Signed-off-by: Mrinmay Sarkar <quic_msarkar@quicinc.com>
+Link: https://lore.kernel.org/r/20241205065422.2515086-3-quic_msarkar@quicinc.com
+[kwilczynski: commit log]
+Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/endpoint/functions/pci-epf-mhi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/pci/endpoint/functions/pci-epf-mhi.c b/drivers/pci/endpoint/functions/pci-epf-mhi.c
+index 54286a40bdfbf..6643a88c7a0ce 100644
+--- a/drivers/pci/endpoint/functions/pci-epf-mhi.c
++++ b/drivers/pci/endpoint/functions/pci-epf-mhi.c
+@@ -125,7 +125,7 @@ static const struct pci_epf_mhi_ep_info sm8450_info = {
+
+ static struct pci_epf_header sa8775p_header = {
+ .vendorid = PCI_VENDOR_ID_QCOM,
+- .deviceid = 0x0306, /* FIXME: Update deviceid for sa8775p EP */
++ .deviceid = 0x0116,
+ .baseclass_code = PCI_CLASS_OTHERS,
+ .interrupt_pin = PCI_INTERRUPT_INTA,
+ };
+--
+2.39.5
+
--- /dev/null
+From f0f40375eb2c907b130a1783551b68bfff23d0d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Dec 2024 19:56:12 +0200
+Subject: PCI: Fix old_size lower bound in calculate_iosize() too
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+
+[ Upstream commit ff61f380de5652e723168341480cc7adf1dd6213 ]
+
+Commit 903534fa7d30 ("PCI: Fix resource double counting on remove &
+rescan") fixed double counting of mem resources because of old_size being
+applied too early.
+
+Fix a similar counting bug on the io resource side.
+
+Link: https://lore.kernel.org/r/20241216175632.4175-6-ilpo.jarvinen@linux.intel.com
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Tested-by: Xiaochun Lee <lixc17@lenovo.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/setup-bus.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
+index f16c7ce3bf3fc..1eceabef9e84d 100644
+--- a/drivers/pci/setup-bus.c
++++ b/drivers/pci/setup-bus.c
+@@ -814,11 +814,9 @@ static resource_size_t calculate_iosize(resource_size_t size,
+ size = (size & 0xff) + ((size & ~0xffUL) << 2);
+ #endif
+ size = size + size1;
+- if (size < old_size)
+- size = old_size;
+
+- size = ALIGN(max(size, add_size) + children_add_size, align);
+- return size;
++ size = max(size, add_size) + children_add_size;
++ return ALIGN(max(size, old_size), align);
+ }
+
+ static resource_size_t calculate_memsize(resource_size_t size,
+--
+2.39.5
+
--- /dev/null
+From e0dc536d3a0df78e2bf0618e85b4001dd7f8df2d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Feb 2025 10:20:56 +0100
+Subject: PCI: vmd: Disable MSI remapping bypass under Xen
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Roger Pau Monne <roger.pau@citrix.com>
+
+[ Upstream commit 6c4d5aadf5df31ea0ac025980670eee9beaf466b ]
+
+MSI remapping bypass (directly configuring MSI entries for devices on the
+VMD bus) won't work under Xen, as Xen is not aware of devices in such bus,
+and hence cannot configure the entries using the pIRQ interface in the PV
+case, and in the PVH case traps won't be setup for MSI entries for such
+devices.
+
+Until Xen is aware of devices in the VMD bus prevent the
+VMD_FEAT_CAN_BYPASS_MSI_REMAP capability from being used when running as
+any kind of Xen guest.
+
+The MSI remapping bypass is an optional feature of VMD bridges, and hence
+when running under Xen it will be masked and devices will be forced to
+redirect its interrupts from the VMD bridge. That mode of operation must
+always be supported by VMD bridges and works when Xen is not aware of
+devices behind the VMD bridge.
+
+Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
+Acked-by: Bjorn Helgaas <bhelgaas@google.com>
+Message-ID: <20250219092059.90850-3-roger.pau@citrix.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/vmd.c | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c
+index 94ceec50a2b94..8df064b62a2ff 100644
+--- a/drivers/pci/controller/vmd.c
++++ b/drivers/pci/controller/vmd.c
+@@ -17,6 +17,8 @@
+ #include <linux/rculist.h>
+ #include <linux/rcupdate.h>
+
++#include <xen/xen.h>
++
+ #include <asm/irqdomain.h>
+
+ #define VMD_CFGBAR 0
+@@ -970,6 +972,24 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ struct vmd_dev *vmd;
+ int err;
+
++ if (xen_domain()) {
++ /*
++ * Xen doesn't have knowledge about devices in the VMD bus
++ * because the config space of devices behind the VMD bridge is
++ * not known to Xen, and hence Xen cannot discover or configure
++ * them in any way.
++ *
++ * Bypass of MSI remapping won't work in that case as direct
++ * write by Linux to the MSI entries won't result in functional
++ * interrupts, as Xen is the entity that manages the host
++ * interrupt controller and must configure interrupts. However
++ * multiplexing of interrupts by the VMD bridge will work under
++ * Xen, so force the usage of that mode which must always be
++ * supported by VMD bridges.
++ */
++ features &= ~VMD_FEAT_CAN_BYPASS_MSI_REMAP;
++ }
++
+ if (resource_size(&dev->resource[VMD_CFGBAR]) < (1 << 20))
+ return -ENOMEM;
+
+--
+2.39.5
+
--- /dev/null
+From 5dccbd9f2fc70e58ee1012a1293741451d409eb8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jan 2025 05:44:32 +0000
+Subject: perf/amd/ibs: Fix ->config to sample period calculation for OP PMU
+
+From: Ravi Bangoria <ravi.bangoria@amd.com>
+
+[ Upstream commit 598bdf4fefff5af4ce6d26d16f7b2a20808fc4cb ]
+
+Instead of using standard perf_event_attr->freq=0 and ->sample_period
+fields, IBS event in 'sample period mode' can also be opened by setting
+period value directly in perf_event_attr->config in a MaxCnt bit-field
+format.
+
+IBS OP MaxCnt bits are defined as:
+
+ (high bits) IbsOpCtl[26:20] = IbsOpMaxCnt[26:20]
+ (low bits) IbsOpCtl[15:0] = IbsOpMaxCnt[19:4]
+
+Perf event sample period can be derived from MaxCnt bits as:
+
+ sample_period = (high bits) | ((low_bits) << 4);
+
+However, current code just masks MaxCnt bits and shifts all of them,
+including high bits, which is incorrect. Fix it.
+
+Signed-off-by: Ravi Bangoria <ravi.bangoria@amd.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Acked-by: Namhyung Kim <namhyung@kernel.org>
+Link: https://lkml.kernel.org/r/20250115054438.1021-4-ravi.bangoria@amd.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/amd/ibs.c | 17 +++++++++++++----
+ 1 file changed, 13 insertions(+), 4 deletions(-)
+
+diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c
+index 8f3b5764e139d..d34ee6f04f18f 100644
+--- a/arch/x86/events/amd/ibs.c
++++ b/arch/x86/events/amd/ibs.c
+@@ -272,7 +272,7 @@ static int perf_ibs_init(struct perf_event *event)
+ {
+ struct hw_perf_event *hwc = &event->hw;
+ struct perf_ibs *perf_ibs;
+- u64 max_cnt, config;
++ u64 config;
+ int ret;
+
+ perf_ibs = get_ibs_pmu(event->attr.type);
+@@ -309,10 +309,19 @@ static int perf_ibs_init(struct perf_event *event)
+ if (!hwc->sample_period)
+ hwc->sample_period = 0x10;
+ } else {
+- max_cnt = config & perf_ibs->cnt_mask;
++ u64 period = 0;
++
++ if (perf_ibs == &perf_ibs_op) {
++ period = (config & IBS_OP_MAX_CNT) << 4;
++ if (ibs_caps & IBS_CAPS_OPCNTEXT)
++ period |= config & IBS_OP_MAX_CNT_EXT_MASK;
++ } else {
++ period = (config & IBS_FETCH_MAX_CNT) << 4;
++ }
++
+ config &= ~perf_ibs->cnt_mask;
+- event->attr.sample_period = max_cnt << 4;
+- hwc->sample_period = event->attr.sample_period;
++ event->attr.sample_period = period;
++ hwc->sample_period = period;
+ }
+
+ if (!hwc->sample_period)
+--
+2.39.5
+
--- /dev/null
+From 47edcb211109882dfb221fdca11da6ca4d04e8a2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jan 2025 05:44:33 +0000
+Subject: perf/amd/ibs: Fix perf_ibs_op.cnt_mask for CurCnt
+
+From: Ravi Bangoria <ravi.bangoria@amd.com>
+
+[ Upstream commit 46dcf85566170d4528b842bf83ffc350d71771fa ]
+
+IBS Op uses two counters: MaxCnt and CurCnt. MaxCnt is programmed with
+the desired sample period. IBS hw generates sample when CurCnt reaches
+to MaxCnt. The size of these counter used to be 20 bits but later they
+were extended to 27 bits. The 7 bit extension is indicated by CPUID
+Fn8000_001B_EAX[6 / OpCntExt].
+
+perf_ibs->cnt_mask variable contains bit masks for MaxCnt and CurCnt.
+But IBS driver does not set upper 7 bits of CurCnt in cnt_mask even
+when OpCntExt CPUID bit is set. Fix this.
+
+IBS driver uses cnt_mask[CurCnt] bits only while disabling an event.
+Fortunately, CurCnt bits are not read from MSR while re-enabling the
+event, instead MaxCnt is programmed with desired period and CurCnt is
+set to 0. Hence, we did not see any issues so far.
+
+Signed-off-by: Ravi Bangoria <ravi.bangoria@amd.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Acked-by: Namhyung Kim <namhyung@kernel.org>
+Link: https://lkml.kernel.org/r/20250115054438.1021-5-ravi.bangoria@amd.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/amd/ibs.c | 3 ++-
+ arch/x86/include/asm/perf_event.h | 1 +
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c
+index c3a2f6f57770a..8f3b5764e139d 100644
+--- a/arch/x86/events/amd/ibs.c
++++ b/arch/x86/events/amd/ibs.c
+@@ -1222,7 +1222,8 @@ static __init int perf_ibs_op_init(void)
+ if (ibs_caps & IBS_CAPS_OPCNTEXT) {
+ perf_ibs_op.max_period |= IBS_OP_MAX_CNT_EXT_MASK;
+ perf_ibs_op.config_mask |= IBS_OP_MAX_CNT_EXT_MASK;
+- perf_ibs_op.cnt_mask |= IBS_OP_MAX_CNT_EXT_MASK;
++ perf_ibs_op.cnt_mask |= (IBS_OP_MAX_CNT_EXT_MASK |
++ IBS_OP_CUR_CNT_EXT_MASK);
+ }
+
+ if (ibs_caps & IBS_CAPS_ZEN4)
+diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
+index 7505bb5d260ab..aa351c4a20eee 100644
+--- a/arch/x86/include/asm/perf_event.h
++++ b/arch/x86/include/asm/perf_event.h
+@@ -520,6 +520,7 @@ struct pebs_xmm {
+ */
+ #define IBS_OP_CUR_CNT (0xFFF80ULL<<32)
+ #define IBS_OP_CUR_CNT_RAND (0x0007FULL<<32)
++#define IBS_OP_CUR_CNT_EXT_MASK (0x7FULL<<52)
+ #define IBS_OP_CNT_CTL (1ULL<<19)
+ #define IBS_OP_VAL (1ULL<<18)
+ #define IBS_OP_ENABLE (1ULL<<17)
+--
+2.39.5
+
--- /dev/null
+From 878851b069dd494ada0d926f70f8a2591b15f2ee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Feb 2025 14:39:56 -0600
+Subject: perf: arm_pmuv3: Call kvm_vcpu_pmu_resync_el0() before enabling
+ counters
+
+From: Rob Herring (Arm) <robh@kernel.org>
+
+[ Upstream commit 04bd15c4cbc3f7bd2399d1baab958c5e738dbfc9 ]
+
+Counting events related to setup of the PMU is not desired, but
+kvm_vcpu_pmu_resync_el0() is called just after the PMU counters have
+been enabled. Move the call to before enabling the counters.
+
+Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
+Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
+Tested-by: James Clark <james.clark@linaro.org>
+Link: https://lore.kernel.org/r/20250218-arm-brbe-v19-v20-1-4e9922fc2e8e@kernel.org
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/perf/arm_pmuv3.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c
+index 0afe02f879b45..d9b56f0f90942 100644
+--- a/drivers/perf/arm_pmuv3.c
++++ b/drivers/perf/arm_pmuv3.c
+@@ -816,10 +816,10 @@ static void armv8pmu_start(struct arm_pmu *cpu_pmu)
+ else
+ armv8pmu_disable_user_access();
+
++ kvm_vcpu_pmu_resync_el0();
++
+ /* Enable all counters */
+ armv8pmu_pmcr_write(armv8pmu_pmcr_read() | ARMV8_PMU_PMCR_E);
+-
+- kvm_vcpu_pmu_resync_el0();
+ }
+
+ static void armv8pmu_stop(struct arm_pmu *cpu_pmu)
+--
+2.39.5
+
--- /dev/null
+From 05f2e06606f07903a60482c4611d98e11e65f549 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jan 2025 07:23:02 -0800
+Subject: perf: Avoid the read if the count is already updated
+
+From: Peter Zijlstra (Intel) <peterz@infradead.org>
+
+[ Upstream commit 8ce939a0fa194939cc1f92dbd8bc1a7806e7d40a ]
+
+The event may have been updated in the PMU-specific implementation,
+e.g., Intel PEBS counters snapshotting. The common code should not
+read and overwrite the value.
+
+The PERF_SAMPLE_READ in the data->sample_type can be used to detect
+whether the PMU-specific value is available. If yes, avoid the
+pmu->read() in the common code. Add a new flag, skip_read, to track the
+case.
+
+Factor out a perf_pmu_read() to clean up the code.
+
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lkml.kernel.org/r/20250121152303.3128733-3-kan.liang@linux.intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/perf_event.h | 8 +++++++-
+ kernel/events/core.c | 33 ++++++++++++++++-----------------
+ kernel/events/ring_buffer.c | 1 +
+ 3 files changed, 24 insertions(+), 18 deletions(-)
+
+diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
+index 0997077bcc52a..ce64b4b937f06 100644
+--- a/include/linux/perf_event.h
++++ b/include/linux/perf_event.h
+@@ -1063,7 +1063,13 @@ struct perf_output_handle {
+ struct perf_buffer *rb;
+ unsigned long wakeup;
+ unsigned long size;
+- u64 aux_flags;
++ union {
++ u64 flags; /* perf_output*() */
++ u64 aux_flags; /* perf_aux_output*() */
++ struct {
++ u64 skip_read : 1;
++ };
++ };
+ union {
+ void *addr;
+ unsigned long head;
+diff --git a/kernel/events/core.c b/kernel/events/core.c
+index 19dde12f23b83..285a4548450bd 100644
+--- a/kernel/events/core.c
++++ b/kernel/events/core.c
+@@ -1195,6 +1195,12 @@ static void perf_assert_pmu_disabled(struct pmu *pmu)
+ WARN_ON_ONCE(*this_cpu_ptr(pmu->pmu_disable_count) == 0);
+ }
+
++static inline void perf_pmu_read(struct perf_event *event)
++{
++ if (event->state == PERF_EVENT_STATE_ACTIVE)
++ event->pmu->read(event);
++}
++
+ static void get_ctx(struct perf_event_context *ctx)
+ {
+ refcount_inc(&ctx->refcount);
+@@ -3482,8 +3488,7 @@ static void __perf_event_sync_stat(struct perf_event *event,
+ * we know the event must be on the current CPU, therefore we
+ * don't need to use it.
+ */
+- if (event->state == PERF_EVENT_STATE_ACTIVE)
+- event->pmu->read(event);
++ perf_pmu_read(event);
+
+ perf_event_update_time(event);
+
+@@ -4634,15 +4639,8 @@ static void __perf_event_read(void *info)
+
+ pmu->read(event);
+
+- for_each_sibling_event(sub, event) {
+- if (sub->state == PERF_EVENT_STATE_ACTIVE) {
+- /*
+- * Use sibling's PMU rather than @event's since
+- * sibling could be on different (eg: software) PMU.
+- */
+- sub->pmu->read(sub);
+- }
+- }
++ for_each_sibling_event(sub, event)
++ perf_pmu_read(sub);
+
+ data->ret = pmu->commit_txn(pmu);
+
+@@ -7408,9 +7406,8 @@ static void perf_output_read_group(struct perf_output_handle *handle,
+ if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
+ values[n++] = running;
+
+- if ((leader != event) &&
+- (leader->state == PERF_EVENT_STATE_ACTIVE))
+- leader->pmu->read(leader);
++ if ((leader != event) && !handle->skip_read)
++ perf_pmu_read(leader);
+
+ values[n++] = perf_event_count(leader, self);
+ if (read_format & PERF_FORMAT_ID)
+@@ -7423,9 +7420,8 @@ static void perf_output_read_group(struct perf_output_handle *handle,
+ for_each_sibling_event(sub, leader) {
+ n = 0;
+
+- if ((sub != event) &&
+- (sub->state == PERF_EVENT_STATE_ACTIVE))
+- sub->pmu->read(sub);
++ if ((sub != event) && !handle->skip_read)
++ perf_pmu_read(sub);
+
+ values[n++] = perf_event_count(sub, self);
+ if (read_format & PERF_FORMAT_ID)
+@@ -7484,6 +7480,9 @@ void perf_output_sample(struct perf_output_handle *handle,
+ {
+ u64 sample_type = data->type;
+
++ if (data->sample_flags & PERF_SAMPLE_READ)
++ handle->skip_read = 1;
++
+ perf_output_put(handle, *header);
+
+ if (sample_type & PERF_SAMPLE_IDENTIFIER)
+diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
+index bbfa22c0a1597..6ecbbc57cdfde 100644
+--- a/kernel/events/ring_buffer.c
++++ b/kernel/events/ring_buffer.c
+@@ -185,6 +185,7 @@ __perf_output_begin(struct perf_output_handle *handle,
+
+ handle->rb = rb;
+ handle->event = event;
++ handle->flags = 0;
+
+ have_lost = local_read(&rb->lost);
+ if (unlikely(have_lost)) {
+--
+2.39.5
+
--- /dev/null
+From 0945f764fdef893577edeea18ced9c3fc22f2d12 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Feb 2025 11:21:28 +0100
+Subject: perf/core: Clean up perf_try_init_event()
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit da02f54e81db2f7bf6af9d1d0cfc5b41ec6d0dcb ]
+
+Make sure that perf_try_init_event() doesn't leave event->pmu nor
+event->destroy set on failure.
+
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Acked-by: Ravi Bangoria <ravi.bangoria@amd.com>
+Link: https://lore.kernel.org/r/20250205102449.110145835@infradead.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/events/core.c | 65 ++++++++++++++++++++++++++------------------
+ 1 file changed, 38 insertions(+), 27 deletions(-)
+
+diff --git a/kernel/events/core.c b/kernel/events/core.c
+index edafe9fc4bdd0..19dde12f23b83 100644
+--- a/kernel/events/core.c
++++ b/kernel/events/core.c
+@@ -11978,40 +11978,51 @@ static int perf_try_init_event(struct pmu *pmu, struct perf_event *event)
+ if (ctx)
+ perf_event_ctx_unlock(event->group_leader, ctx);
+
+- if (!ret) {
+- if (!(pmu->capabilities & PERF_PMU_CAP_EXTENDED_REGS) &&
+- has_extended_regs(event))
+- ret = -EOPNOTSUPP;
++ if (ret)
++ goto err_pmu;
+
+- if (pmu->capabilities & PERF_PMU_CAP_NO_EXCLUDE &&
+- event_has_any_exclude_flag(event))
+- ret = -EINVAL;
++ if (!(pmu->capabilities & PERF_PMU_CAP_EXTENDED_REGS) &&
++ has_extended_regs(event)) {
++ ret = -EOPNOTSUPP;
++ goto err_destroy;
++ }
+
+- if (pmu->scope != PERF_PMU_SCOPE_NONE && event->cpu >= 0) {
+- const struct cpumask *cpumask = perf_scope_cpu_topology_cpumask(pmu->scope, event->cpu);
+- struct cpumask *pmu_cpumask = perf_scope_cpumask(pmu->scope);
+- int cpu;
+-
+- if (pmu_cpumask && cpumask) {
+- cpu = cpumask_any_and(pmu_cpumask, cpumask);
+- if (cpu >= nr_cpu_ids)
+- ret = -ENODEV;
+- else
+- event->event_caps |= PERF_EV_CAP_READ_SCOPE;
+- } else {
+- ret = -ENODEV;
+- }
+- }
++ if (pmu->capabilities & PERF_PMU_CAP_NO_EXCLUDE &&
++ event_has_any_exclude_flag(event)) {
++ ret = -EINVAL;
++ goto err_destroy;
++ }
+
+- if (ret && event->destroy)
+- event->destroy(event);
++ if (pmu->scope != PERF_PMU_SCOPE_NONE && event->cpu >= 0) {
++ const struct cpumask *cpumask;
++ struct cpumask *pmu_cpumask;
++ int cpu;
++
++ cpumask = perf_scope_cpu_topology_cpumask(pmu->scope, event->cpu);
++ pmu_cpumask = perf_scope_cpumask(pmu->scope);
++
++ ret = -ENODEV;
++ if (!pmu_cpumask || !cpumask)
++ goto err_destroy;
++
++ cpu = cpumask_any_and(pmu_cpumask, cpumask);
++ if (cpu >= nr_cpu_ids)
++ goto err_destroy;
++
++ event->event_caps |= PERF_EV_CAP_READ_SCOPE;
+ }
+
+- if (ret) {
+- event->pmu = NULL;
+- module_put(pmu->module);
++ return 0;
++
++err_destroy:
++ if (event->destroy) {
++ event->destroy(event);
++ event->destroy = NULL;
+ }
+
++err_pmu:
++ event->pmu = NULL;
++ module_put(pmu->module);
+ return ret;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 123d326f14b72218826317c14d1c2d68b40d62b8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Mar 2025 14:54:51 +0530
+Subject: perf/hw_breakpoint: Return EOPNOTSUPP for unsupported breakpoint type
+
+From: Saket Kumar Bhaskar <skb99@linux.ibm.com>
+
+[ Upstream commit 061c991697062f3bf87b72ed553d1d33a0e370dd ]
+
+Currently, __reserve_bp_slot() returns -ENOSPC for unsupported
+breakpoint types on the architecture. For example, powerpc
+does not support hardware instruction breakpoints. This causes
+the perf_skip BPF selftest to fail, as neither ENOENT nor
+EOPNOTSUPP is returned by perf_event_open for unsupported
+breakpoint types. As a result, the test that should be skipped
+for this arch is not correctly identified.
+
+To resolve this, hw_breakpoint_event_init() should exit early by
+checking for unsupported breakpoint types using
+hw_breakpoint_slots_cached() and return the appropriate error
+(-EOPNOTSUPP).
+
+Signed-off-by: Saket Kumar Bhaskar <skb99@linux.ibm.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Cc: Marco Elver <elver@google.com>
+Cc: Dmitry Vyukov <dvyukov@google.com>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Frederic Weisbecker <fweisbec@gmail.com>
+Link: https://lore.kernel.org/r/20250303092451.1862862-1-skb99@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/events/hw_breakpoint.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c
+index 6c2cb4e4f48da..8f3f624419aa9 100644
+--- a/kernel/events/hw_breakpoint.c
++++ b/kernel/events/hw_breakpoint.c
+@@ -950,9 +950,10 @@ static int hw_breakpoint_event_init(struct perf_event *bp)
+ return -ENOENT;
+
+ /*
+- * no branch sampling for breakpoint events
++ * Check if breakpoint type is supported before proceeding.
++ * Also, no branch sampling for breakpoint events.
+ */
+- if (has_branch_stack(bp))
++ if (!hw_breakpoint_slots_cached(find_slot_idx(bp->attr.bp_type)) || has_branch_stack(bp))
+ return -EOPNOTSUPP;
+
+ err = register_perf_hw_breakpoint(bp);
+--
+2.39.5
+
--- /dev/null
+From 926f6fb20c83803820bda8c789ad688a8e65a430 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Feb 2025 14:31:45 +0200
+Subject: phy: core: don't require set_mode() callback for phy_get_mode() to
+ work
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit d58c04e305afbaa9dda7969151f06c4efe2c98b0 ]
+
+As reported by Damon Ding, the phy_get_mode() call doesn't work as
+expected unless the PHY driver has a .set_mode() call. This prompts PHY
+drivers to have empty stubs for .set_mode() for the sake of being able
+to get the mode.
+
+Make .set_mode() callback truly optional and update PHY's mode even if
+it there is none.
+
+Cc: Damon Ding <damon.ding@rock-chips.com>
+Link: https://lore.kernel.org/r/96f8310f-93f1-4bcb-8637-137e1159ff83@rock-chips.com
+Tested-by: Damon Ding <damon.ding@rock-chips.com>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20250209-phy-fix-set-moe-v2-1-76e248503856@linaro.org
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/phy/phy-core.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
+index 413f76e2d1744..e0a6a272f5714 100644
+--- a/drivers/phy/phy-core.c
++++ b/drivers/phy/phy-core.c
+@@ -405,13 +405,14 @@ EXPORT_SYMBOL_GPL(phy_power_off);
+
+ int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode)
+ {
+- int ret;
++ int ret = 0;
+
+- if (!phy || !phy->ops->set_mode)
++ if (!phy)
+ return 0;
+
+ mutex_lock(&phy->mutex);
+- ret = phy->ops->set_mode(phy, mode, submode);
++ if (phy->ops->set_mode)
++ ret = phy->ops->set_mode(phy, mode, submode);
+ if (!ret)
+ phy->attrs.mode = mode;
+ mutex_unlock(&phy->mutex);
+--
+2.39.5
+
--- /dev/null
+From 93bfabab446db73c84e53f4d071635ac85c86bf5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Dec 2024 16:31:04 +0000
+Subject: phy: exynos5-usbdrd: fix EDS distribution tuning (gs101)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: André Draszik <andre.draszik@linaro.org>
+
+[ Upstream commit 21860f340ba76ee042e5431ff92537f89bc11476 ]
+
+This code's intention is to configure lane0 and lane2 tunings, but for
+lane2 there is a typo and it ends up tuning something else.
+
+Fix the typo, as it doesn't appear to make sense to apply different
+tunings for lane0 vs lane2.
+
+The same typo appears to exist in the bootloader, hence we restore the
+original value in the typo'd registers as well. This can be removed
+once / if the bootloader is updated.
+
+Note that this is incorrect in the downstream driver as well - the
+values had been copied from there.
+
+Reviewed-by: Peter Griffin <peter.griffin@linaro.org>
+Tested-by: Peter Griffin <peter.griffin@linaro.org>
+Signed-off-by: André Draszik <andre.draszik@linaro.org>
+Tested-by: Will McVicker <willmcvicker@google.com>
+Link: https://lore.kernel.org/r/20241206-gs101-phy-lanes-orientation-phy-v4-4-f5961268b149@linaro.org
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/phy/samsung/phy-exynos5-usbdrd.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c
+index 46b8f6987c62c..28d02ae60cc14 100644
+--- a/drivers/phy/samsung/phy-exynos5-usbdrd.c
++++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c
+@@ -1513,8 +1513,11 @@ static const struct exynos5_usbdrd_phy_tuning gs101_tunes_pipe3_preinit[] = {
+ PHY_TUNING_ENTRY_PMA(0x09e0, -1, 0x00),
+ PHY_TUNING_ENTRY_PMA(0x09e4, -1, 0x36),
+ PHY_TUNING_ENTRY_PMA(0x1e7c, -1, 0x06),
+- PHY_TUNING_ENTRY_PMA(0x1e90, -1, 0x00),
+- PHY_TUNING_ENTRY_PMA(0x1e94, -1, 0x36),
++ PHY_TUNING_ENTRY_PMA(0x19e0, -1, 0x00),
++ PHY_TUNING_ENTRY_PMA(0x19e4, -1, 0x36),
++ /* fix bootloader bug */
++ PHY_TUNING_ENTRY_PMA(0x1e90, -1, 0x02),
++ PHY_TUNING_ENTRY_PMA(0x1e94, -1, 0x0b),
+ /* improve LVCC */
+ PHY_TUNING_ENTRY_PMA(0x08f0, -1, 0x30),
+ PHY_TUNING_ENTRY_PMA(0x18f0, -1, 0x30),
+--
+2.39.5
+
--- /dev/null
+From 12686d8faf1a16931ae3f023e950fd5f4c4a0fd9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Feb 2025 18:51:54 +0800
+Subject: phy: phy-rockchip-samsung-hdptx: Swap the definitions of LCPLL_REF
+ and ROPLL_REF
+
+From: Damon Ding <damon.ding@rock-chips.com>
+
+[ Upstream commit 2947c8065e9efdd3b6434d2817dc8896234a3fc0 ]
+
+According to the datasheet, setting the dig_clk_sel bit of CMN_REG(0097)
+to 1'b1 selects LCPLL as the reference clock, while setting it to 1'b0
+selects the ROPLL.
+
+Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20250205105157.580060-2-damon.ding@rock-chips.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+index be6f1ca9095aa..dc6e01dff5c74 100644
+--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
++++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+@@ -94,8 +94,8 @@
+ #define LCPLL_ALONE_MODE BIT(1)
+ /* CMN_REG(0097) */
+ #define DIG_CLK_SEL BIT(1)
+-#define ROPLL_REF BIT(1)
+-#define LCPLL_REF 0
++#define LCPLL_REF BIT(1)
++#define ROPLL_REF 0
+ /* CMN_REG(0099) */
+ #define CMN_ROPLL_ALONE_MODE BIT(2)
+ #define ROPLL_ALONE_MODE BIT(2)
+--
+2.39.5
+
--- /dev/null
+From f7a07c8345d8f879e5501160b9eaa3f73f0e216c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 May 2025 15:50:31 +0300
+Subject: phy: renesas: rcar-gen3-usb2: Assert PLL reset on PHY power off
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit 9ce71e85b29eb63e48e294479742e670513f03a0 ]
+
+Assert PLL reset on PHY power off. This saves power.
+
+Fixes: f3b5a8d9b50d ("phy: rcar-gen3-usb2: Add R-Car Gen3 USB2 PHY driver")
+Cc: stable@vger.kernel.org
+Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Tested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Link: https://lore.kernel.org/r/20250507125032.565017-5-claudiu.beznea.uj@bp.renesas.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/phy/renesas/phy-rcar-gen3-usb2.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+index 188e903445aeb..b45aee8f59644 100644
+--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
++++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+@@ -540,9 +540,17 @@ static int rcar_gen3_phy_usb2_power_off(struct phy *p)
+ struct rcar_gen3_chan *channel = rphy->ch;
+ int ret = 0;
+
+- scoped_guard(spinlock_irqsave, &channel->lock)
++ scoped_guard(spinlock_irqsave, &channel->lock) {
+ rphy->powered = false;
+
++ if (rcar_gen3_are_all_rphys_power_off(channel)) {
++ u32 val = readl(channel->base + USB2_USBCTR);
++
++ val |= USB2_USBCTR_PLL_RST;
++ writel(val, channel->base + USB2_USBCTR);
++ }
++ }
++
+ if (channel->vbus)
+ ret = regulator_disable(channel->vbus);
+
+--
+2.39.5
+
--- /dev/null
+From 099423f96e7fe0f986f912b30dfe75783879fb0a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 May 2025 15:50:30 +0300
+Subject: phy: renesas: rcar-gen3-usb2: Lock around hardware registers and
+ driver data
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit 55a387ebb9219cbe4edfa8ba9996ccb0e7ad4932 ]
+
+The phy-rcar-gen3-usb2 driver exposes four individual PHYs that are
+requested and configured by PHY users. The struct phy_ops APIs access the
+same set of registers to configure all PHYs. Additionally, PHY settings can
+be modified through sysfs or an IRQ handler. While some struct phy_ops APIs
+are protected by a driver-wide mutex, others rely on individual
+PHY-specific mutexes.
+
+This approach can lead to various issues, including:
+1/ the IRQ handler may interrupt PHY settings in progress, racing with
+ hardware configuration protected by a mutex lock
+2/ due to msleep(20) in rcar_gen3_init_otg(), while a configuration thread
+ suspends to wait for the delay, another thread may try to configure
+ another PHY (with phy_init() + phy_power_on()); re-running the
+ phy_init() goes to the exact same configuration code, re-running the
+ same hardware configuration on the same set of registers (and bits)
+ which might impact the result of the msleep for the 1st configuring
+ thread
+3/ sysfs can configure the hardware (though role_store()) and it can
+ still race with the phy_init()/phy_power_on() APIs calling into the
+ drivers struct phy_ops
+
+To address these issues, add a spinlock to protect hardware register access
+and driver private data structures (e.g., calls to
+rcar_gen3_is_any_rphy_initialized()). Checking driver-specific data remains
+necessary as all PHY instances share common settings. With this change,
+the existing mutex protection is removed and the cleanup.h helpers are
+used.
+
+While at it, to keep the code simpler, do not skip
+regulator_enable()/regulator_disable() APIs in
+rcar_gen3_phy_usb2_power_on()/rcar_gen3_phy_usb2_power_off() as the
+regulators enable/disable operations are reference counted anyway.
+
+Fixes: f3b5a8d9b50d ("phy: rcar-gen3-usb2: Add R-Car Gen3 USB2 PHY driver")
+Cc: stable@vger.kernel.org
+Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Tested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Link: https://lore.kernel.org/r/20250507125032.565017-4-claudiu.beznea.uj@bp.renesas.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Stable-dep-of: 9ce71e85b29e ("phy: renesas: rcar-gen3-usb2: Assert PLL reset on PHY power off")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/phy/renesas/phy-rcar-gen3-usb2.c | 49 +++++++++++++-----------
+ 1 file changed, 26 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+index 4cd1b6e677482..188e903445aeb 100644
+--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
++++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+@@ -9,6 +9,7 @@
+ * Copyright (C) 2014 Cogent Embedded, Inc.
+ */
+
++#include <linux/cleanup.h>
+ #include <linux/extcon-provider.h>
+ #include <linux/interrupt.h>
+ #include <linux/io.h>
+@@ -118,7 +119,7 @@ struct rcar_gen3_chan {
+ struct regulator *vbus;
+ struct reset_control *rstc;
+ struct work_struct work;
+- struct mutex lock; /* protects rphys[...].powered */
++ spinlock_t lock; /* protects access to hardware and driver data structure. */
+ enum usb_dr_mode dr_mode;
+ u32 obint_enable_bits;
+ bool extcon_host;
+@@ -348,6 +349,8 @@ static ssize_t role_store(struct device *dev, struct device_attribute *attr,
+ bool is_b_device;
+ enum phy_mode cur_mode, new_mode;
+
++ guard(spinlock_irqsave)(&ch->lock);
++
+ if (!ch->is_otg_channel || !rcar_gen3_is_any_otg_rphy_initialized(ch))
+ return -EIO;
+
+@@ -415,7 +418,7 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
+ val = readl(usb2_base + USB2_ADPCTRL);
+ writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL);
+ }
+- msleep(20);
++ mdelay(20);
+
+ writel(0xffffffff, usb2_base + USB2_OBINTSTA);
+ writel(ch->obint_enable_bits, usb2_base + USB2_OBINTEN);
+@@ -436,12 +439,14 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch)
+ if (pm_runtime_suspended(dev))
+ goto rpm_put;
+
+- status = readl(usb2_base + USB2_OBINTSTA);
+- if (status & ch->obint_enable_bits) {
+- dev_vdbg(dev, "%s: %08x\n", __func__, status);
+- writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA);
+- rcar_gen3_device_recognition(ch);
+- ret = IRQ_HANDLED;
++ scoped_guard(spinlock, &ch->lock) {
++ status = readl(usb2_base + USB2_OBINTSTA);
++ if (status & ch->obint_enable_bits) {
++ dev_vdbg(dev, "%s: %08x\n", __func__, status);
++ writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA);
++ rcar_gen3_device_recognition(ch);
++ ret = IRQ_HANDLED;
++ }
+ }
+
+ rpm_put:
+@@ -456,6 +461,8 @@ static int rcar_gen3_phy_usb2_init(struct phy *p)
+ void __iomem *usb2_base = channel->base;
+ u32 val;
+
++ guard(spinlock_irqsave)(&channel->lock);
++
+ /* Initialize USB2 part */
+ val = readl(usb2_base + USB2_INT_ENABLE);
+ val |= USB2_INT_ENABLE_UCOM_INTEN | rphy->int_enable_bits;
+@@ -482,6 +489,8 @@ static int rcar_gen3_phy_usb2_exit(struct phy *p)
+ void __iomem *usb2_base = channel->base;
+ u32 val;
+
++ guard(spinlock_irqsave)(&channel->lock);
++
+ rphy->initialized = false;
+
+ val = readl(usb2_base + USB2_INT_ENABLE);
+@@ -501,16 +510,17 @@ static int rcar_gen3_phy_usb2_power_on(struct phy *p)
+ u32 val;
+ int ret = 0;
+
+- mutex_lock(&channel->lock);
+- if (!rcar_gen3_are_all_rphys_power_off(channel))
+- goto out;
+-
+ if (channel->vbus) {
+ ret = regulator_enable(channel->vbus);
+ if (ret)
+- goto out;
++ return ret;
+ }
+
++ guard(spinlock_irqsave)(&channel->lock);
++
++ if (!rcar_gen3_are_all_rphys_power_off(channel))
++ goto out;
++
+ val = readl(usb2_base + USB2_USBCTR);
+ val |= USB2_USBCTR_PLL_RST;
+ writel(val, usb2_base + USB2_USBCTR);
+@@ -520,7 +530,6 @@ static int rcar_gen3_phy_usb2_power_on(struct phy *p)
+ out:
+ /* The powered flag should be set for any other phys anyway */
+ rphy->powered = true;
+- mutex_unlock(&channel->lock);
+
+ return 0;
+ }
+@@ -531,18 +540,12 @@ static int rcar_gen3_phy_usb2_power_off(struct phy *p)
+ struct rcar_gen3_chan *channel = rphy->ch;
+ int ret = 0;
+
+- mutex_lock(&channel->lock);
+- rphy->powered = false;
+-
+- if (!rcar_gen3_are_all_rphys_power_off(channel))
+- goto out;
++ scoped_guard(spinlock_irqsave, &channel->lock)
++ rphy->powered = false;
+
+ if (channel->vbus)
+ ret = regulator_disable(channel->vbus);
+
+-out:
+- mutex_unlock(&channel->lock);
+-
+ return ret;
+ }
+
+@@ -753,7 +756,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
+ if (phy_data->no_adp_ctrl)
+ channel->obint_enable_bits = USB2_OBINT_IDCHG_EN;
+
+- mutex_init(&channel->lock);
++ spin_lock_init(&channel->lock);
+ for (i = 0; i < NUM_OF_PHYS; i++) {
+ channel->rphys[i].phy = devm_phy_create(dev, NULL,
+ phy_data->phy_usb2_ops);
+--
+2.39.5
+
--- /dev/null
+From 1cfbe64823cd782cc08318490f59f3a92c7834db Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 May 2025 15:50:29 +0300
+Subject: phy: renesas: rcar-gen3-usb2: Move IRQ request in probe
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit de76809f60cc938d3580bbbd5b04b7d12af6ce3a ]
+
+Commit 08b0ad375ca6 ("phy: renesas: rcar-gen3-usb2: move IRQ registration
+to init") moved the IRQ request operation from probe to
+struct phy_ops::phy_init API to avoid triggering interrupts (which lead to
+register accesses) while the PHY clocks (enabled through runtime PM APIs)
+are not active. If this happens, it results in a synchronous abort.
+
+One way to reproduce this issue is by enabling CONFIG_DEBUG_SHIRQ, which
+calls free_irq() on driver removal.
+
+Move the IRQ request and free operations back to probe, and take the
+runtime PM state into account in IRQ handler. This commit is preparatory
+for the subsequent fixes in this series.
+
+Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Tested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Link: https://lore.kernel.org/r/20250507125032.565017-3-claudiu.beznea.uj@bp.renesas.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Stable-dep-of: 9ce71e85b29e ("phy: renesas: rcar-gen3-usb2: Assert PLL reset on PHY power off")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/phy/renesas/phy-rcar-gen3-usb2.c | 46 +++++++++++++-----------
+ 1 file changed, 26 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+index 513fd35dcaa95..4cd1b6e677482 100644
+--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
++++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+@@ -120,7 +120,6 @@ struct rcar_gen3_chan {
+ struct work_struct work;
+ struct mutex lock; /* protects rphys[...].powered */
+ enum usb_dr_mode dr_mode;
+- int irq;
+ u32 obint_enable_bits;
+ bool extcon_host;
+ bool is_otg_channel;
+@@ -428,16 +427,25 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch)
+ {
+ struct rcar_gen3_chan *ch = _ch;
+ void __iomem *usb2_base = ch->base;
+- u32 status = readl(usb2_base + USB2_OBINTSTA);
++ struct device *dev = ch->dev;
+ irqreturn_t ret = IRQ_NONE;
++ u32 status;
+
++ pm_runtime_get_noresume(dev);
++
++ if (pm_runtime_suspended(dev))
++ goto rpm_put;
++
++ status = readl(usb2_base + USB2_OBINTSTA);
+ if (status & ch->obint_enable_bits) {
+- dev_vdbg(ch->dev, "%s: %08x\n", __func__, status);
++ dev_vdbg(dev, "%s: %08x\n", __func__, status);
+ writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA);
+ rcar_gen3_device_recognition(ch);
+ ret = IRQ_HANDLED;
+ }
+
++rpm_put:
++ pm_runtime_put_noidle(dev);
+ return ret;
+ }
+
+@@ -447,17 +455,6 @@ static int rcar_gen3_phy_usb2_init(struct phy *p)
+ struct rcar_gen3_chan *channel = rphy->ch;
+ void __iomem *usb2_base = channel->base;
+ u32 val;
+- int ret;
+-
+- if (!rcar_gen3_is_any_rphy_initialized(channel) && channel->irq >= 0) {
+- INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work);
+- ret = request_irq(channel->irq, rcar_gen3_phy_usb2_irq,
+- IRQF_SHARED, dev_name(channel->dev), channel);
+- if (ret < 0) {
+- dev_err(channel->dev, "No irq handler (%d)\n", channel->irq);
+- return ret;
+- }
+- }
+
+ /* Initialize USB2 part */
+ val = readl(usb2_base + USB2_INT_ENABLE);
+@@ -493,9 +490,6 @@ static int rcar_gen3_phy_usb2_exit(struct phy *p)
+ val &= ~USB2_INT_ENABLE_UCOM_INTEN;
+ writel(val, usb2_base + USB2_INT_ENABLE);
+
+- if (channel->irq >= 0 && !rcar_gen3_is_any_rphy_initialized(channel))
+- free_irq(channel->irq, channel);
+-
+ return 0;
+ }
+
+@@ -701,7 +695,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
+ struct device *dev = &pdev->dev;
+ struct rcar_gen3_chan *channel;
+ struct phy_provider *provider;
+- int ret = 0, i;
++ int ret = 0, i, irq;
+
+ if (!dev->of_node) {
+ dev_err(dev, "This driver needs device tree\n");
+@@ -717,8 +711,6 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
+ return PTR_ERR(channel->base);
+
+ channel->obint_enable_bits = USB2_OBINT_BITS;
+- /* get irq number here and request_irq for OTG in phy_init */
+- channel->irq = platform_get_irq_optional(pdev, 0);
+ channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node);
+ if (channel->dr_mode != USB_DR_MODE_UNKNOWN) {
+ channel->is_otg_channel = true;
+@@ -787,6 +779,20 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
+ channel->vbus = NULL;
+ }
+
++ irq = platform_get_irq_optional(pdev, 0);
++ if (irq < 0 && irq != -ENXIO) {
++ ret = irq;
++ goto error;
++ } else if (irq > 0) {
++ INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work);
++ ret = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq,
++ IRQF_SHARED, dev_name(dev), channel);
++ if (ret < 0) {
++ dev_err(dev, "Failed to request irq (%d)\n", irq);
++ goto error;
++ }
++ }
++
+ provider = devm_of_phy_provider_register(dev, rcar_gen3_phy_usb2_xlate);
+ if (IS_ERR(provider)) {
+ dev_err(dev, "Failed to register PHY provider\n");
+--
+2.39.5
+
--- /dev/null
+From d1d5f1410e92cfe5970889b29c1f4a2bdd9bc7ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Mar 2025 16:00:07 +0800
+Subject: phy: rockchip: usbdp: Only verify link rates/lanes/voltage when the
+ corresponding set flags are set
+
+From: Andy Yan <andy.yan@rock-chips.com>
+
+[ Upstream commit 969a38be437b68dc9e12e3c3f08911c9f9c8be73 ]
+
+According documentation of phy_configure_opts_dp, at the configure
+stage, link rates should only be verify/configure when set_rate
+flag is set, the same applies to lanes and voltage.
+
+So do it as the documentation says.
+Because voltage setting depends on the lanes, link rates set
+previously, so record the link rates and lanes at it's verify stage.
+
+Signed-off-by: Andy Yan <andy.yan@rock-chips.com>
+Link: https://lore.kernel.org/r/20250312080041.524546-1-andyshrk@163.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/phy/rockchip/phy-rockchip-usbdp.c | 87 ++++++++++++++---------
+ 1 file changed, 53 insertions(+), 34 deletions(-)
+
+diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
+index f5c6d264d89ed..d2021f7941e3e 100644
+--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
++++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
+@@ -187,6 +187,8 @@ struct rk_udphy {
+ u32 dp_aux_din_sel;
+ bool dp_sink_hpd_sel;
+ bool dp_sink_hpd_cfg;
++ unsigned int link_rate;
++ unsigned int lanes;
+ u8 bw;
+ int id;
+
+@@ -1102,15 +1104,19 @@ static int rk_udphy_dp_phy_power_off(struct phy *phy)
+ return 0;
+ }
+
+-static int rk_udphy_dp_phy_verify_link_rate(unsigned int link_rate)
++/*
++ * Verify link rate
++ */
++static int rk_udphy_dp_phy_verify_link_rate(struct rk_udphy *udphy,
++ struct phy_configure_opts_dp *dp)
+ {
+- switch (link_rate) {
++ switch (dp->link_rate) {
+ case 1620:
+ case 2700:
+ case 5400:
+ case 8100:
++ udphy->link_rate = dp->link_rate;
+ break;
+-
+ default:
+ return -EINVAL;
+ }
+@@ -1118,45 +1124,44 @@ static int rk_udphy_dp_phy_verify_link_rate(unsigned int link_rate)
+ return 0;
+ }
+
+-static int rk_udphy_dp_phy_verify_config(struct rk_udphy *udphy,
+- struct phy_configure_opts_dp *dp)
++static int rk_udphy_dp_phy_verify_lanes(struct rk_udphy *udphy,
++ struct phy_configure_opts_dp *dp)
+ {
+- int i, ret;
+-
+- /* If changing link rate was required, verify it's supported. */
+- ret = rk_udphy_dp_phy_verify_link_rate(dp->link_rate);
+- if (ret)
+- return ret;
+-
+- /* Verify lane count. */
+ switch (dp->lanes) {
+ case 1:
+ case 2:
+ case 4:
+ /* valid lane count. */
++ udphy->lanes = dp->lanes;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+- /*
+- * If changing voltages is required, check swing and pre-emphasis
+- * levels, per-lane.
+- */
+- if (dp->set_voltages) {
+- /* Lane count verified previously. */
+- for (i = 0; i < dp->lanes; i++) {
+- if (dp->voltage[i] > 3 || dp->pre[i] > 3)
+- return -EINVAL;
++ return 0;
++}
+
+- /*
+- * Sum of voltage swing and pre-emphasis levels cannot
+- * exceed 3.
+- */
+- if (dp->voltage[i] + dp->pre[i] > 3)
+- return -EINVAL;
+- }
++/*
++ * If changing voltages is required, check swing and pre-emphasis
++ * levels, per-lane.
++ */
++static int rk_udphy_dp_phy_verify_voltages(struct rk_udphy *udphy,
++ struct phy_configure_opts_dp *dp)
++{
++ int i;
++
++ /* Lane count verified previously. */
++ for (i = 0; i < udphy->lanes; i++) {
++ if (dp->voltage[i] > 3 || dp->pre[i] > 3)
++ return -EINVAL;
++
++ /*
++ * Sum of voltage swing and pre-emphasis levels cannot
++ * exceed 3.
++ */
++ if (dp->voltage[i] + dp->pre[i] > 3)
++ return -EINVAL;
+ }
+
+ return 0;
+@@ -1196,9 +1201,23 @@ static int rk_udphy_dp_phy_configure(struct phy *phy,
+ u32 i, val, lane;
+ int ret;
+
+- ret = rk_udphy_dp_phy_verify_config(udphy, dp);
+- if (ret)
+- return ret;
++ if (dp->set_rate) {
++ ret = rk_udphy_dp_phy_verify_link_rate(udphy, dp);
++ if (ret)
++ return ret;
++ }
++
++ if (dp->set_lanes) {
++ ret = rk_udphy_dp_phy_verify_lanes(udphy, dp);
++ if (ret)
++ return ret;
++ }
++
++ if (dp->set_voltages) {
++ ret = rk_udphy_dp_phy_verify_voltages(udphy, dp);
++ if (ret)
++ return ret;
++ }
+
+ if (dp->set_rate) {
+ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET,
+@@ -1243,9 +1262,9 @@ static int rk_udphy_dp_phy_configure(struct phy *phy,
+ }
+
+ if (dp->set_voltages) {
+- for (i = 0; i < dp->lanes; i++) {
++ for (i = 0; i < udphy->lanes; i++) {
+ lane = udphy->dp_lane_sel[i];
+- switch (dp->link_rate) {
++ switch (udphy->link_rate) {
+ case 1620:
+ case 2700:
+ regmap_update_bits(udphy->pma_regmap,
+--
+2.39.5
+
--- /dev/null
+From 19f4b04c738203169f7d4ae792891d1766eca3ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Mar 2025 14:24:08 +0100
+Subject: pidfs: improve multi-threaded exec and premature thread-group leader
+ exit polling
+
+From: Christian Brauner <brauner@kernel.org>
+
+[ Upstream commit 0fb482728ba1ee2130eaa461bf551f014447997c ]
+
+This is another attempt trying to make pidfd polling for multi-threaded
+exec and premature thread-group leader exit consistent.
+
+A quick recap of these two cases:
+
+(1) During a multi-threaded exec by a subthread, i.e., non-thread-group
+ leader thread, all other threads in the thread-group including the
+ thread-group leader are killed and the struct pid of the
+ thread-group leader will be taken over by the subthread that called
+ exec. IOW, two tasks change their TIDs.
+
+(2) A premature thread-group leader exit means that the thread-group
+ leader exited before all of the other subthreads in the thread-group
+ have exited.
+
+Both cases lead to inconsistencies for pidfd polling with PIDFD_THREAD.
+Any caller that holds a PIDFD_THREAD pidfd to the current thread-group
+leader may or may not see an exit notification on the file descriptor
+depending on when poll is performed. If the poll is performed before the
+exec of the subthread has concluded an exit notification is generated
+for the old thread-group leader. If the poll is performed after the exec
+of the subthread has concluded no exit notification is generated for the
+old thread-group leader.
+
+The correct behavior would be to simply not generate an exit
+notification on the struct pid of a subhthread exec because the struct
+pid is taken over by the subthread and thus remains alive.
+
+But this is difficult to handle because a thread-group may exit
+prematurely as mentioned in (2). In that case an exit notification is
+reliably generated but the subthreads may continue to run for an
+indeterminate amount of time and thus also may exec at some point.
+
+So far there was no way to distinguish between (1) and (2) internally.
+This tiny series tries to address this problem by discarding
+PIDFD_THREAD notification on premature thread-group leader exit.
+
+If that works correctly then no exit notifications are generated for a
+PIDFD_THREAD pidfd for a thread-group leader until all subthreads have
+been reaped. If a subthread should exec aftewards no exit notification
+will be generated until that task exits or it creates subthreads and
+repeates the cycle.
+
+Co-Developed-by: Oleg Nesterov <oleg@redhat.com>
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Link: https://lore.kernel.org/r/20250320-work-pidfs-thread_group-v4-1-da678ce805bf@kernel.org
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/pidfs.c | 9 +++++----
+ kernel/exit.c | 6 +++---
+ kernel/signal.c | 3 +--
+ 3 files changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/fs/pidfs.c b/fs/pidfs.c
+index 80675b6bf8845..52b7e4f767327 100644
+--- a/fs/pidfs.c
++++ b/fs/pidfs.c
+@@ -95,20 +95,21 @@ static void pidfd_show_fdinfo(struct seq_file *m, struct file *f)
+ static __poll_t pidfd_poll(struct file *file, struct poll_table_struct *pts)
+ {
+ struct pid *pid = pidfd_pid(file);
+- bool thread = file->f_flags & PIDFD_THREAD;
+ struct task_struct *task;
+ __poll_t poll_flags = 0;
+
+ poll_wait(file, &pid->wait_pidfd, pts);
+ /*
+- * Depending on PIDFD_THREAD, inform pollers when the thread
+- * or the whole thread-group exits.
++ * Don't wake waiters if the thread-group leader exited
++ * prematurely. They either get notified when the last subthread
++ * exits or not at all if one of the remaining subthreads execs
++ * and assumes the struct pid of the old thread-group leader.
+ */
+ guard(rcu)();
+ task = pid_task(pid, PIDTYPE_PID);
+ if (!task)
+ poll_flags = EPOLLIN | EPOLLRDNORM | EPOLLHUP;
+- else if (task->exit_state && (thread || thread_group_empty(task)))
++ else if (task->exit_state && !delay_group_leader(task))
+ poll_flags = EPOLLIN | EPOLLRDNORM;
+
+ return poll_flags;
+diff --git a/kernel/exit.c b/kernel/exit.c
+index 9d888f26bf784..c94d23ccd1520 100644
+--- a/kernel/exit.c
++++ b/kernel/exit.c
+@@ -745,10 +745,10 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
+
+ tsk->exit_state = EXIT_ZOMBIE;
+ /*
+- * sub-thread or delay_group_leader(), wake up the
+- * PIDFD_THREAD waiters.
++ * Ignore thread-group leaders that exited before all
++ * subthreads did.
+ */
+- if (!thread_group_empty(tsk))
++ if (!delay_group_leader(tsk))
+ do_notify_pidfd(tsk);
+
+ if (unlikely(tsk->ptrace)) {
+diff --git a/kernel/signal.c b/kernel/signal.c
+index 2ae45e6eb6bb8..468b589c39e69 100644
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -2063,8 +2063,7 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
+ WARN_ON_ONCE(!tsk->ptrace &&
+ (tsk->group_leader != tsk || !thread_group_empty(tsk)));
+ /*
+- * tsk is a group leader and has no threads, wake up the
+- * non-PIDFD_THREAD waiters.
++ * Notify for thread-group leaders without subthreads.
+ */
+ if (thread_group_empty(tsk))
+ do_notify_pidfd(tsk);
+--
+2.39.5
+
--- /dev/null
+From 1dd1a477ca53cf55649b1a987001f57e2f07f0c7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Mar 2025 21:54:47 +0100
+Subject: pinctrl: bcm281xx: Use "unsigned int" instead of bare "unsigned"
+
+From: Artur Weber <aweber.kernel@gmail.com>
+
+[ Upstream commit 07b5a2a13f4704c5eae3be7277ec54ffdba45f72 ]
+
+Replace uses of bare "unsigned" with "unsigned int" to fix checkpatch
+warnings. No functional change.
+
+Signed-off-by: Artur Weber <aweber.kernel@gmail.com>
+Link: https://lore.kernel.org/20250303-bcm21664-pinctrl-v3-2-5f8b80e4ab51@gmail.com
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/bcm/pinctrl-bcm281xx.c | 44 +++++++++++++-------------
+ 1 file changed, 22 insertions(+), 22 deletions(-)
+
+diff --git a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
+index cf6efa9c0364a..a039b490cdb8e 100644
+--- a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
++++ b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
+@@ -72,7 +72,7 @@ static enum bcm281xx_pin_type hdmi_pin = BCM281XX_PIN_TYPE_HDMI;
+ struct bcm281xx_pin_function {
+ const char *name;
+ const char * const *groups;
+- const unsigned ngroups;
++ const unsigned int ngroups;
+ };
+
+ /*
+@@ -84,10 +84,10 @@ struct bcm281xx_pinctrl_data {
+
+ /* List of all pins */
+ const struct pinctrl_pin_desc *pins;
+- const unsigned npins;
++ const unsigned int npins;
+
+ const struct bcm281xx_pin_function *functions;
+- const unsigned nfunctions;
++ const unsigned int nfunctions;
+
+ struct regmap *regmap;
+ };
+@@ -941,7 +941,7 @@ static struct bcm281xx_pinctrl_data bcm281xx_pinctrl = {
+ };
+
+ static inline enum bcm281xx_pin_type pin_type_get(struct pinctrl_dev *pctldev,
+- unsigned pin)
++ unsigned int pin)
+ {
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+@@ -985,7 +985,7 @@ static int bcm281xx_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+ }
+
+ static const char *bcm281xx_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+- unsigned group)
++ unsigned int group)
+ {
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+@@ -993,9 +993,9 @@ static const char *bcm281xx_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ }
+
+ static int bcm281xx_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+- unsigned group,
++ unsigned int group,
+ const unsigned **pins,
+- unsigned *num_pins)
++ unsigned int *num_pins)
+ {
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+@@ -1007,7 +1007,7 @@ static int bcm281xx_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+
+ static void bcm281xx_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s,
+- unsigned offset)
++ unsigned int offset)
+ {
+ seq_printf(s, " %s", dev_name(pctldev->dev));
+ }
+@@ -1029,7 +1029,7 @@ static int bcm281xx_pinctrl_get_fcns_count(struct pinctrl_dev *pctldev)
+ }
+
+ static const char *bcm281xx_pinctrl_get_fcn_name(struct pinctrl_dev *pctldev,
+- unsigned function)
++ unsigned int function)
+ {
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+@@ -1037,9 +1037,9 @@ static const char *bcm281xx_pinctrl_get_fcn_name(struct pinctrl_dev *pctldev,
+ }
+
+ static int bcm281xx_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev,
+- unsigned function,
++ unsigned int function,
+ const char * const **groups,
+- unsigned * const num_groups)
++ unsigned int * const num_groups)
+ {
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+@@ -1050,8 +1050,8 @@ static int bcm281xx_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev,
+ }
+
+ static int bcm281xx_pinmux_set(struct pinctrl_dev *pctldev,
+- unsigned function,
+- unsigned group)
++ unsigned int function,
++ unsigned int group)
+ {
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm281xx_pin_function *f = &pdata->functions[function];
+@@ -1082,7 +1082,7 @@ static const struct pinmux_ops bcm281xx_pinctrl_pinmux_ops = {
+ };
+
+ static int bcm281xx_pinctrl_pin_config_get(struct pinctrl_dev *pctldev,
+- unsigned pin,
++ unsigned int pin,
+ unsigned long *config)
+ {
+ return -ENOTSUPP;
+@@ -1091,9 +1091,9 @@ static int bcm281xx_pinctrl_pin_config_get(struct pinctrl_dev *pctldev,
+
+ /* Goes through the configs and update register val/mask */
+ static int bcm281xx_std_pin_update(struct pinctrl_dev *pctldev,
+- unsigned pin,
++ unsigned int pin,
+ unsigned long *configs,
+- unsigned num_configs,
++ unsigned int num_configs,
+ u32 *val,
+ u32 *mask)
+ {
+@@ -1207,9 +1207,9 @@ static const u16 bcm281xx_pullup_map[] = {
+
+ /* Goes through the configs and update register val/mask */
+ static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev,
+- unsigned pin,
++ unsigned int pin,
+ unsigned long *configs,
+- unsigned num_configs,
++ unsigned int num_configs,
+ u32 *val,
+ u32 *mask)
+ {
+@@ -1277,9 +1277,9 @@ static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev,
+
+ /* Goes through the configs and update register val/mask */
+ static int bcm281xx_hdmi_pin_update(struct pinctrl_dev *pctldev,
+- unsigned pin,
++ unsigned int pin,
+ unsigned long *configs,
+- unsigned num_configs,
++ unsigned int num_configs,
+ u32 *val,
+ u32 *mask)
+ {
+@@ -1321,9 +1321,9 @@ static int bcm281xx_hdmi_pin_update(struct pinctrl_dev *pctldev,
+ }
+
+ static int bcm281xx_pinctrl_pin_config_set(struct pinctrl_dev *pctldev,
+- unsigned pin,
++ unsigned int pin,
+ unsigned long *configs,
+- unsigned num_configs)
++ unsigned int num_configs)
+ {
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+ enum bcm281xx_pin_type pin_type;
+--
+2.39.5
+
--- /dev/null
+From ece469a82c226eb09718e9738b2b1375ff0bc23f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jan 2025 18:00:09 +0100
+Subject: pinctrl: devicetree: do not goto err when probing hogs in
+ pinctrl_dt_to_map
+
+From: Valentin Caron <valentin.caron@foss.st.com>
+
+[ Upstream commit c98868e816209e568c9d72023ba0bc1e4d96e611 ]
+
+Cross case in pinctrl framework make impossible to an hogged pin and
+another, not hogged, used within the same device-tree node. For example
+with this simplified device-tree :
+
+ &pinctrl {
+ pinctrl_pin_1: pinctrl-pin-1 {
+ pins = "dummy-pinctrl-pin";
+ };
+ };
+
+ &rtc {
+ pinctrl-names = "default"
+ pinctrl-0 = <&pinctrl_pin_1 &rtc_pin_1>
+
+ rtc_pin_1: rtc-pin-1 {
+ pins = "dummy-rtc-pin";
+ };
+ };
+
+"pinctrl_pin_1" configuration is never set. This produces this path in
+the code:
+
+ really_probe()
+ pinctrl_bind_pins()
+ | devm_pinctrl_get()
+ | pinctrl_get()
+ | create_pinctrl()
+ | pinctrl_dt_to_map()
+ | // Hog pin create an abort for all pins of the node
+ | ret = dt_to_map_one_config()
+ | | /* Do not defer probing of hogs (circular loop) */
+ | | if (np_pctldev == p->dev->of_node)
+ | | return -ENODEV;
+ | if (ret)
+ | goto err
+ |
+ call_driver_probe()
+ stm32_rtc_probe()
+ pinctrl_enable()
+ pinctrl_claim_hogs()
+ create_pinctrl()
+ for_each_maps(maps_node, i, map)
+ // Not hog pin is skipped
+ if (pctldev && strcmp(dev_name(pctldev->dev),
+ map->ctrl_dev_name))
+ continue;
+
+At the first call of create_pinctrl() the hogged pin produces an abort to
+avoid a defer of hogged pins. All other pin configurations are trashed.
+
+At the second call, create_pinctrl is now called with pctldev parameter to
+get hogs, but in this context only hogs are set. And other pins are
+skipped.
+
+To handle this, do not produce an abort in the first call of
+create_pinctrl(). Classic pin configuration will be set in
+pinctrl_bind_pins() context. And the hogged pin configuration will be set
+in pinctrl_claim_hogs() context.
+
+Signed-off-by: Valentin Caron <valentin.caron@foss.st.com>
+Link: https://lore.kernel.org/20250116170009.2075544-1-valentin.caron@foss.st.com
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/devicetree.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
+index 6a94ecd6a8dea..0b7f74beb6a6a 100644
+--- a/drivers/pinctrl/devicetree.c
++++ b/drivers/pinctrl/devicetree.c
+@@ -143,10 +143,14 @@ static int dt_to_map_one_config(struct pinctrl *p,
+ pctldev = get_pinctrl_dev_from_of_node(np_pctldev);
+ if (pctldev)
+ break;
+- /* Do not defer probing of hogs (circular loop) */
++ /*
++ * Do not defer probing of hogs (circular loop)
++ *
++ * Return 1 to let the caller catch the case.
++ */
+ if (np_pctldev == p->dev->of_node) {
+ of_node_put(np_pctldev);
+- return -ENODEV;
++ return 1;
+ }
+ }
+ of_node_put(np_pctldev);
+@@ -265,6 +269,8 @@ int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev)
+ ret = dt_to_map_one_config(p, pctldev, statename,
+ np_config);
+ of_node_put(np_config);
++ if (ret == 1)
++ continue;
+ if (ret < 0)
+ goto err;
+ }
+--
+2.39.5
+
--- /dev/null
+From e1d0d02dfcd535b2aa550e789a4b1edf170a66bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 29 Mar 2025 20:01:32 +0100
+Subject: pinctrl: meson: define the pull up/down resistor value as 60 kOhm
+
+From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+
+[ Upstream commit e56088a13708757da68ad035269d69b93ac8c389 ]
+
+The public datasheets of the following Amlogic SoCs describe a typical
+resistor value for the built-in pull up/down resistor:
+- Meson8/8b/8m2: not documented
+- GXBB (S905): 60 kOhm
+- GXL (S905X): 60 kOhm
+- GXM (S912): 60 kOhm
+- G12B (S922X): 60 kOhm
+- SM1 (S905D3): 60 kOhm
+
+The public G12B and SM1 datasheets additionally state min and max
+values:
+- min value: 50 kOhm for both, pull-up and pull-down
+- max value for the pull-up: 70 kOhm
+- max value for the pull-down: 130 kOhm
+
+Use 60 kOhm in the pinctrl-meson driver as well so it's shown in the
+debugfs output. It may not be accurate for Meson8/8b/8m2 but in reality
+60 kOhm is closer to the actual value than 1 Ohm.
+
+Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
+Link: https://lore.kernel.org/20250329190132.855196-1-martin.blumenstingl@googlemail.com
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/meson/pinctrl-meson.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
+index 253a0cc57e396..e5a32a0532eee 100644
+--- a/drivers/pinctrl/meson/pinctrl-meson.c
++++ b/drivers/pinctrl/meson/pinctrl-meson.c
+@@ -487,7 +487,7 @@ static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin,
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_BIAS_PULL_UP:
+ if (meson_pinconf_get_pull(pc, pin) == param)
+- arg = 1;
++ arg = 60000;
+ else
+ return -EINVAL;
+ break;
+--
+2.39.5
+
--- /dev/null
+From 97275c2ed34285ae55d6467f27d8f3597fc0067c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Feb 2025 12:01:16 +0200
+Subject: pinctrl: renesas: rzg2l: Add suspend/resume support for pull up/down
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit b2bd65fbb617353e3c46ba5206b3b030fa0f260c ]
+
+The Renesas RZ/G3S supports a power-saving mode where power to most of
+the SoC components is lost, including the PIN controller. Save and
+restore the pull-up/pull-down register contents to ensure the
+functionality is preserved after a suspend/resume cycle.
+
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lore.kernel.org/20250205100116.2032765-1-claudiu.beznea.uj@bp.renesas.com
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/renesas/pinctrl-rzg2l.c | 19 ++++++++++++++++++-
+ 1 file changed, 18 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
+index d90685cfe2e1a..bde58f5a743cb 100644
+--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c
++++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
+@@ -311,6 +311,7 @@ struct rzg2l_pinctrl_pin_settings {
+ * @pmc: PMC registers cache
+ * @pfc: PFC registers cache
+ * @iolh: IOLH registers cache
++ * @pupd: PUPD registers cache
+ * @ien: IEN registers cache
+ * @sd_ch: SD_CH registers cache
+ * @eth_poc: ET_POC registers cache
+@@ -324,6 +325,7 @@ struct rzg2l_pinctrl_reg_cache {
+ u32 *pfc;
+ u32 *iolh[2];
+ u32 *ien[2];
++ u32 *pupd[2];
+ u8 sd_ch[2];
+ u8 eth_poc[2];
+ u8 eth_mode;
+@@ -2539,6 +2541,11 @@ static int rzg2l_pinctrl_reg_cache_alloc(struct rzg2l_pinctrl *pctrl)
+ if (!cache->ien[i])
+ return -ENOMEM;
+
++ cache->pupd[i] = devm_kcalloc(pctrl->dev, nports, sizeof(*cache->pupd[i]),
++ GFP_KERNEL);
++ if (!cache->pupd[i])
++ return -ENOMEM;
++
+ /* Allocate dedicated cache. */
+ dedicated_cache->iolh[i] = devm_kcalloc(pctrl->dev, n_dedicated_pins,
+ sizeof(*dedicated_cache->iolh[i]),
+@@ -2779,7 +2786,7 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen
+ struct rzg2l_pinctrl_reg_cache *cache = pctrl->cache;
+
+ for (u32 port = 0; port < nports; port++) {
+- bool has_iolh, has_ien;
++ bool has_iolh, has_ien, has_pupd;
+ u32 off, caps;
+ u8 pincnt;
+ u64 cfg;
+@@ -2791,6 +2798,7 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen
+ caps = FIELD_GET(PIN_CFG_MASK, cfg);
+ has_iolh = !!(caps & (PIN_CFG_IOLH_A | PIN_CFG_IOLH_B | PIN_CFG_IOLH_C));
+ has_ien = !!(caps & PIN_CFG_IEN);
++ has_pupd = !!(caps & PIN_CFG_PUPD);
+
+ if (suspend)
+ RZG2L_PCTRL_REG_ACCESS32(suspend, pctrl->base + PFC(off), cache->pfc[port]);
+@@ -2809,6 +2817,15 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen
+ }
+ }
+
++ if (has_pupd) {
++ RZG2L_PCTRL_REG_ACCESS32(suspend, pctrl->base + PUPD(off),
++ cache->pupd[0][port]);
++ if (pincnt >= 4) {
++ RZG2L_PCTRL_REG_ACCESS32(suspend, pctrl->base + PUPD(off),
++ cache->pupd[1][port]);
++ }
++ }
++
+ RZG2L_PCTRL_REG_ACCESS16(suspend, pctrl->base + PM(off), cache->pm[port]);
+ RZG2L_PCTRL_REG_ACCESS8(suspend, pctrl->base + P(off), cache->p[port]);
+
+--
+2.39.5
+
--- /dev/null
+From d43a1dd0704dbaaae59881429a3f00217c347197 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Feb 2025 13:17:49 +0800
+Subject: pinctrl: sophgo: avoid to modify untouched bit when setting cv1800
+ pinconf
+
+From: Inochi Amaoto <inochiama@gmail.com>
+
+[ Upstream commit ef1a5121ae3da02372fcb66d9632ed3d47ad5637 ]
+
+When setting pinconf configuration for cv1800 SoC, the driver just writes
+the value. It may zero some bits of the pinconf register and cause some
+unexpected error. Add a mask to avoid this.
+
+Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
+Link: https://lore.kernel.org/20250211051801.470800-2-inochiama@gmail.com
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/sophgo/pinctrl-cv18xx.c | 33 +++++++++++++++++--------
+ 1 file changed, 23 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/pinctrl/sophgo/pinctrl-cv18xx.c b/drivers/pinctrl/sophgo/pinctrl-cv18xx.c
+index 57f2674e75d68..84b4850771ce2 100644
+--- a/drivers/pinctrl/sophgo/pinctrl-cv18xx.c
++++ b/drivers/pinctrl/sophgo/pinctrl-cv18xx.c
+@@ -574,10 +574,10 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
+ struct cv1800_pin *pin,
+ unsigned long *configs,
+ unsigned int num_configs,
+- u32 *value)
++ u32 *value, u32 *mask)
+ {
+ int i;
+- u32 v = 0;
++ u32 v = 0, m = 0;
+ enum cv1800_pin_io_type type;
+ int ret;
+
+@@ -596,10 +596,12 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ v &= ~PIN_IO_PULLDOWN;
+ v |= FIELD_PREP(PIN_IO_PULLDOWN, arg);
++ m |= PIN_IO_PULLDOWN;
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ v &= ~PIN_IO_PULLUP;
+ v |= FIELD_PREP(PIN_IO_PULLUP, arg);
++ m |= PIN_IO_PULLUP;
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH_UA:
+ ret = cv1800_pinctrl_oc2reg(pctrl, pin, arg);
+@@ -607,6 +609,7 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
+ return ret;
+ v &= ~PIN_IO_DRIVE;
+ v |= FIELD_PREP(PIN_IO_DRIVE, ret);
++ m |= PIN_IO_DRIVE;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_UV:
+ ret = cv1800_pinctrl_schmitt2reg(pctrl, pin, arg);
+@@ -614,6 +617,7 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
+ return ret;
+ v &= ~PIN_IO_SCHMITT;
+ v |= FIELD_PREP(PIN_IO_SCHMITT, ret);
++ m |= PIN_IO_SCHMITT;
+ break;
+ case PIN_CONFIG_POWER_SOURCE:
+ /* Ignore power source as it is always fixed */
+@@ -621,10 +625,12 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
+ case PIN_CONFIG_SLEW_RATE:
+ v &= ~PIN_IO_OUT_FAST_SLEW;
+ v |= FIELD_PREP(PIN_IO_OUT_FAST_SLEW, arg);
++ m |= PIN_IO_OUT_FAST_SLEW;
+ break;
+ case PIN_CONFIG_BIAS_BUS_HOLD:
+ v &= ~PIN_IO_BUS_HOLD;
+ v |= FIELD_PREP(PIN_IO_BUS_HOLD, arg);
++ m |= PIN_IO_BUS_HOLD;
+ break;
+ default:
+ return -ENOTSUPP;
+@@ -632,17 +638,19 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
+ }
+
+ *value = v;
++ *mask = m;
+
+ return 0;
+ }
+
+ static int cv1800_pin_set_config(struct cv1800_pinctrl *pctrl,
+ unsigned int pin_id,
+- u32 value)
++ u32 value, u32 mask)
+ {
+ struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id);
+ unsigned long flags;
+ void __iomem *addr;
++ u32 reg;
+
+ if (!pin)
+ return -EINVAL;
+@@ -650,7 +658,10 @@ static int cv1800_pin_set_config(struct cv1800_pinctrl *pctrl,
+ addr = cv1800_pinctrl_get_component_addr(pctrl, &pin->conf);
+
+ raw_spin_lock_irqsave(&pctrl->lock, flags);
+- writel(value, addr);
++ reg = readl(addr);
++ reg &= ~mask;
++ reg |= value;
++ writel(reg, addr);
+ raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+
+ return 0;
+@@ -662,16 +673,17 @@ static int cv1800_pconf_set(struct pinctrl_dev *pctldev,
+ {
+ struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id);
+- u32 value;
++ u32 value, mask;
+
+ if (!pin)
+ return -ENODEV;
+
+ if (cv1800_pinconf_compute_config(pctrl, pin,
+- configs, num_configs, &value))
++ configs, num_configs,
++ &value, &mask))
+ return -ENOTSUPP;
+
+- return cv1800_pin_set_config(pctrl, pin_id, value);
++ return cv1800_pin_set_config(pctrl, pin_id, value, mask);
+ }
+
+ static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev,
+@@ -682,7 +694,7 @@ static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev,
+ struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ const struct group_desc *group;
+ const struct cv1800_pin_mux_config *pinmuxs;
+- u32 value;
++ u32 value, mask;
+ int i;
+
+ group = pinctrl_generic_get_group(pctldev, gsel);
+@@ -692,11 +704,12 @@ static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev,
+ pinmuxs = group->data;
+
+ if (cv1800_pinconf_compute_config(pctrl, pinmuxs[0].pin,
+- configs, num_configs, &value))
++ configs, num_configs,
++ &value, &mask))
+ return -ENOTSUPP;
+
+ for (i = 0; i < group->grp.npins; i++)
+- cv1800_pin_set_config(pctrl, group->grp.pins[i], value);
++ cv1800_pin_set_config(pctrl, group->grp.pins[i], value, mask);
+
+ return 0;
+ }
+--
+2.39.5
+
--- /dev/null
+From f83ff5ff7d6c27fc4bcf3359bf3ea69abe6a9ae5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Mar 2025 16:19:39 +0530
+Subject: pinctrl-tegra: Restore SFSEL bit when freeing pins
+
+From: Prathamesh Shete <pshete@nvidia.com>
+
+[ Upstream commit c12bfa0fee65940b10ff5187349f76c6f6b1df9c ]
+
+Each pin can be configured as a Special Function IO (SFIO) or GPIO,
+where the SFIO enables the pin to operate in alternative modes such as
+I2C, SPI, etc.
+
+The current implementation sets all the pins back to SFIO mode
+even if they were initially in GPIO mode. This can cause glitches
+on the pins when pinctrl_gpio_free() is called.
+
+Avoid these undesired glitches by storing the pin's SFIO/GPIO
+state on GPIO request and restoring it on GPIO free.
+
+Signed-off-by: Prathamesh Shete <pshete@nvidia.com>
+Link: https://lore.kernel.org/20250305104939.15168-2-pshete@nvidia.com
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/tegra/pinctrl-tegra.c | 59 +++++++++++++++++++++++----
+ drivers/pinctrl/tegra/pinctrl-tegra.h | 6 +++
+ 2 files changed, 57 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c
+index 3b046450bd3ff..27823e4207347 100644
+--- a/drivers/pinctrl/tegra/pinctrl-tegra.c
++++ b/drivers/pinctrl/tegra/pinctrl-tegra.c
+@@ -278,8 +278,8 @@ static int tegra_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ return 0;
+ }
+
+-static const struct tegra_pingroup *tegra_pinctrl_get_group(struct pinctrl_dev *pctldev,
+- unsigned int offset)
++static int tegra_pinctrl_get_group_index(struct pinctrl_dev *pctldev,
++ unsigned int offset)
+ {
+ struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+ unsigned int group, num_pins, j;
+@@ -292,12 +292,35 @@ static const struct tegra_pingroup *tegra_pinctrl_get_group(struct pinctrl_dev *
+ continue;
+ for (j = 0; j < num_pins; j++) {
+ if (offset == pins[j])
+- return &pmx->soc->groups[group];
++ return group;
+ }
+ }
+
+- dev_err(pctldev->dev, "Pingroup not found for pin %u\n", offset);
+- return NULL;
++ return -EINVAL;
++}
++
++static const struct tegra_pingroup *tegra_pinctrl_get_group(struct pinctrl_dev *pctldev,
++ unsigned int offset,
++ int group_index)
++{
++ struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
++
++ if (group_index < 0 || group_index > pmx->soc->ngroups)
++ return NULL;
++
++ return &pmx->soc->groups[group_index];
++}
++
++static struct tegra_pingroup_config *tegra_pinctrl_get_group_config(struct pinctrl_dev *pctldev,
++ unsigned int offset,
++ int group_index)
++{
++ struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
++
++ if (group_index < 0)
++ return NULL;
++
++ return &pmx->pingroup_configs[group_index];
+ }
+
+ static int tegra_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev,
+@@ -306,12 +329,15 @@ static int tegra_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev,
+ {
+ struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+ const struct tegra_pingroup *group;
++ struct tegra_pingroup_config *config;
++ int group_index;
+ u32 value;
+
+ if (!pmx->soc->sfsel_in_mux)
+ return 0;
+
+- group = tegra_pinctrl_get_group(pctldev, offset);
++ group_index = tegra_pinctrl_get_group_index(pctldev, offset);
++ group = tegra_pinctrl_get_group(pctldev, offset, group_index);
+
+ if (!group)
+ return -EINVAL;
+@@ -319,7 +345,11 @@ static int tegra_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev,
+ if (group->mux_reg < 0 || group->sfsel_bit < 0)
+ return -EINVAL;
+
++ config = tegra_pinctrl_get_group_config(pctldev, offset, group_index);
++ if (!config)
++ return -EINVAL;
+ value = pmx_readl(pmx, group->mux_bank, group->mux_reg);
++ config->is_sfsel = (value & BIT(group->sfsel_bit)) != 0;
+ value &= ~BIT(group->sfsel_bit);
+ pmx_writel(pmx, value, group->mux_bank, group->mux_reg);
+
+@@ -332,12 +362,15 @@ static void tegra_pinctrl_gpio_disable_free(struct pinctrl_dev *pctldev,
+ {
+ struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+ const struct tegra_pingroup *group;
++ struct tegra_pingroup_config *config;
++ int group_index;
+ u32 value;
+
+ if (!pmx->soc->sfsel_in_mux)
+ return;
+
+- group = tegra_pinctrl_get_group(pctldev, offset);
++ group_index = tegra_pinctrl_get_group_index(pctldev, offset);
++ group = tegra_pinctrl_get_group(pctldev, offset, group_index);
+
+ if (!group)
+ return;
+@@ -345,8 +378,12 @@ static void tegra_pinctrl_gpio_disable_free(struct pinctrl_dev *pctldev,
+ if (group->mux_reg < 0 || group->sfsel_bit < 0)
+ return;
+
++ config = tegra_pinctrl_get_group_config(pctldev, offset, group_index);
++ if (!config)
++ return;
+ value = pmx_readl(pmx, group->mux_bank, group->mux_reg);
+- value |= BIT(group->sfsel_bit);
++ if (config->is_sfsel)
++ value |= BIT(group->sfsel_bit);
+ pmx_writel(pmx, value, group->mux_bank, group->mux_reg);
+ }
+
+@@ -791,6 +828,12 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
+ pmx->dev = &pdev->dev;
+ pmx->soc = soc_data;
+
++ pmx->pingroup_configs = devm_kcalloc(&pdev->dev,
++ pmx->soc->ngroups, sizeof(*pmx->pingroup_configs),
++ GFP_KERNEL);
++ if (!pmx->pingroup_configs)
++ return -ENOMEM;
++
+ /*
+ * Each mux group will appear in 4 functions' list of groups.
+ * This over-allocates slightly, since not all groups are mux groups.
+diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.h b/drivers/pinctrl/tegra/pinctrl-tegra.h
+index b3289bdf727d8..b97136685f7a8 100644
+--- a/drivers/pinctrl/tegra/pinctrl-tegra.h
++++ b/drivers/pinctrl/tegra/pinctrl-tegra.h
+@@ -8,6 +8,10 @@
+ #ifndef __PINMUX_TEGRA_H__
+ #define __PINMUX_TEGRA_H__
+
++struct tegra_pingroup_config {
++ bool is_sfsel;
++};
++
+ struct tegra_pmx {
+ struct device *dev;
+ struct pinctrl_dev *pctl;
+@@ -21,6 +25,8 @@ struct tegra_pmx {
+ int nbanks;
+ void __iomem **regs;
+ u32 *backup_regs;
++ /* Array of size soc->ngroups */
++ struct tegra_pingroup_config *pingroup_configs;
+ };
+
+ enum tegra_pinconf_param {
+--
+2.39.5
+
--- /dev/null
+From eb252db794cdfab455f76fca78117ce390be075e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Apr 2025 20:06:08 +0600
+Subject: platform/x86: asus-wmi: Disable OOBE state after resume from
+ hibernation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pavel Nikulin <pavel@noa-labs.com>
+
+[ Upstream commit 77bdac73754e4c0c564c1ca80fe3d9c93b0e715a ]
+
+ASUS firmware resets OOBE state during S4 suspend, so the keyboard
+blinks during resume from hibernation. This patch disables OOBE state
+after resume from hibernation.
+
+Signed-off-by: Pavel Nikulin <pavel@noa-labs.com>
+Link: https://lore.kernel.org/r/20250418140706.1691-1-pavel@noa-labs.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/asus-wmi.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
+index a1cff9ff35a92..9d79c5ea8b495 100644
+--- a/drivers/platform/x86/asus-wmi.c
++++ b/drivers/platform/x86/asus-wmi.c
+@@ -304,6 +304,7 @@ struct asus_wmi {
+
+ u32 kbd_rgb_dev;
+ bool kbd_rgb_state_available;
++ bool oobe_state_available;
+
+ u8 throttle_thermal_policy_mode;
+ u32 throttle_thermal_policy_dev;
+@@ -1826,7 +1827,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
+ goto error;
+ }
+
+- if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_OOBE)) {
++ if (asus->oobe_state_available) {
+ /*
+ * Disable OOBE state, so that e.g. the keyboard backlight
+ * works.
+@@ -4741,6 +4742,7 @@ static int asus_wmi_add(struct platform_device *pdev)
+ asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU);
+ asus->dgpu_disable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU);
+ asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE);
++ asus->oobe_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_OOBE);
+ asus->ally_mcu_usb_switch = acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE)
+ && dmi_check_system(asus_ally_mcu_quirk);
+
+@@ -4994,6 +4996,13 @@ static int asus_hotk_restore(struct device *device)
+ }
+ if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
+ kbd_led_update(asus);
++ if (asus->oobe_state_available) {
++ /*
++ * Disable OOBE state, so that e.g. the keyboard backlight
++ * works.
++ */
++ asus_wmi_set_devstate(ASUS_WMI_DEVID_OOBE, 1, NULL);
++ }
+
+ if (asus_wmi_has_fnlock_key(asus))
+ asus_wmi_fnlock_update(asus);
+--
+2.39.5
+
--- /dev/null
+From 33245ee3fc8993631eb03cd2460209242da51704 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Apr 2025 09:07:38 +0200
+Subject: platform/x86: ideapad-laptop: add support for some new buttons
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Gašper Nemgar <gasper.nemgar@gmail.com>
+
+[ Upstream commit 02c6e43397c39edd0c172859bf8c851b46be09a8 ]
+
+Add entries to unsupported WMI codes in ideapad_keymap[] and one
+check for WMI code 0x13d to trigger platform_profile_cycle().
+
+Signed-off-by: Gašper Nemgar <gasper.nemgar@gmail.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20250418070738.7171-1-gasper.nemgar@gmail.com
+[ij: joined nested if ()s & major tweaks to changelog]
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/ideapad-laptop.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
+index c908f52ed717b..bdb4cbee42058 100644
+--- a/drivers/platform/x86/ideapad-laptop.c
++++ b/drivers/platform/x86/ideapad-laptop.c
+@@ -1297,6 +1297,16 @@ static const struct key_entry ideapad_keymap[] = {
+ /* Specific to some newer models */
+ { KE_KEY, 0x3e | IDEAPAD_WMI_KEY, { KEY_MICMUTE } },
+ { KE_KEY, 0x3f | IDEAPAD_WMI_KEY, { KEY_RFKILL } },
++ /* Star- (User Assignable Key) */
++ { KE_KEY, 0x44 | IDEAPAD_WMI_KEY, { KEY_PROG1 } },
++ /* Eye */
++ { KE_KEY, 0x45 | IDEAPAD_WMI_KEY, { KEY_PROG3 } },
++ /* Performance toggle also Fn+Q, handled inside ideapad_wmi_notify() */
++ { KE_KEY, 0x3d | IDEAPAD_WMI_KEY, { KEY_PROG4 } },
++ /* shift + prtsc */
++ { KE_KEY, 0x2d | IDEAPAD_WMI_KEY, { KEY_CUT } },
++ { KE_KEY, 0x29 | IDEAPAD_WMI_KEY, { KEY_TOUCHPAD_TOGGLE } },
++ { KE_KEY, 0x2a | IDEAPAD_WMI_KEY, { KEY_ROOT_MENU } },
+
+ { KE_END },
+ };
+@@ -2083,6 +2093,12 @@ static void ideapad_wmi_notify(struct wmi_device *wdev, union acpi_object *data)
+ dev_dbg(&wdev->dev, "WMI fn-key event: 0x%llx\n",
+ data->integer.value);
+
++ /* performance button triggered by 0x3d */
++ if (data->integer.value == 0x3d && priv->dytc) {
++ platform_profile_cycle();
++ break;
++ }
++
+ /* 0x02 FnLock, 0x03 Esc */
+ if (data->integer.value == 0x02 || data->integer.value == 0x03)
+ ideapad_fn_lock_led_notify(priv, data->integer.value == 0x02);
+--
+2.39.5
+
--- /dev/null
+From 8a3e7ef184be24d0af94eeb22161c4ff4f4f8b7a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Apr 2025 09:43:32 +0530
+Subject: platform/x86/intel: hid: Add Pantherlake support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Saranya Gopal <saranya.gopal@intel.com>
+
+[ Upstream commit 12df9ec3e1955aed6a0c839f2375cd8e5d5150cf ]
+
+Add Pantherlake ACPI device ID to the Intel HID driver.
+
+While there, clean up the device ID table to remove the ", 0" parts.
+
+Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Saranya Gopal <saranya.gopal@intel.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://lore.kernel.org/r/20250421041332.830136-1-saranya.gopal@intel.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/intel/hid.c | 21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/platform/x86/intel/hid.c b/drivers/platform/x86/intel/hid.c
+index 9a609358956f3..59392f1a0d8ad 100644
+--- a/drivers/platform/x86/intel/hid.c
++++ b/drivers/platform/x86/intel/hid.c
+@@ -44,16 +44,17 @@ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Alex Hung");
+
+ static const struct acpi_device_id intel_hid_ids[] = {
+- {"INT33D5", 0},
+- {"INTC1051", 0},
+- {"INTC1054", 0},
+- {"INTC1070", 0},
+- {"INTC1076", 0},
+- {"INTC1077", 0},
+- {"INTC1078", 0},
+- {"INTC107B", 0},
+- {"INTC10CB", 0},
+- {"", 0},
++ { "INT33D5" },
++ { "INTC1051" },
++ { "INTC1054" },
++ { "INTC1070" },
++ { "INTC1076" },
++ { "INTC1077" },
++ { "INTC1078" },
++ { "INTC107B" },
++ { "INTC10CB" },
++ { "INTC10CC" },
++ { }
+ };
+ MODULE_DEVICE_TABLE(acpi, intel_hid_ids);
+
+--
+2.39.5
+
--- /dev/null
+From de711920f8d279953913570b5a7956c633dcc3ac Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Feb 2025 20:18:32 +0100
+Subject: pmdomain: imx: gpcv2: use proper helper for property detection
+
+From: Ahmad Fatoum <a.fatoum@pengutronix.de>
+
+[ Upstream commit 6568cb40e73163fa25e2779f7234b169b2e1a32e ]
+
+Starting with commit c141ecc3cecd7 ("of: Warn when of_property_read_bool()
+is used on non-boolean properties"), probing the gpcv2 device on i.MX8M
+SoCs leads to warnings when LOCKDEP is enabled.
+
+Fix this by checking property presence with of_property_present as
+intended.
+
+Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
+Link: https://lore.kernel.org/r/20250218-gpcv2-of-property-present-v1-1-3bb1a9789654@pengutronix.de
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pmdomain/imx/gpcv2.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/pmdomain/imx/gpcv2.c b/drivers/pmdomain/imx/gpcv2.c
+index e03c2cb39a693..0dbf1893abfa3 100644
+--- a/drivers/pmdomain/imx/gpcv2.c
++++ b/drivers/pmdomain/imx/gpcv2.c
+@@ -1361,7 +1361,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
+ }
+
+ if (IS_ENABLED(CONFIG_LOCKDEP) &&
+- of_property_read_bool(domain->dev->of_node, "power-domains"))
++ of_property_present(domain->dev->of_node, "power-domains"))
+ lockdep_set_subclass(&domain->genpd.mlock, 1);
+
+ ret = of_genpd_add_provider_simple(domain->dev->of_node,
+--
+2.39.5
+
--- /dev/null
+From df0905a10288d4ab80af6bb88942ad8b8269df3f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Mar 2025 12:45:01 -0400
+Subject: pNFS/flexfiles: Report ENETDOWN as a connection error
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+[ Upstream commit aa42add73ce9b9e3714723d385c254b75814e335 ]
+
+If the client should see an ENETDOWN when trying to connect to the data
+server, it might still be able to talk to the metadata server through
+another NIC. If so, report the error.
+
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Tested-by: Jeff Layton <jlayton@kernel.org>
+Acked-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/flexfilelayout/flexfilelayout.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
+index a1cfe4cc60c4b..8f7ea4076653d 100644
+--- a/fs/nfs/flexfilelayout/flexfilelayout.c
++++ b/fs/nfs/flexfilelayout/flexfilelayout.c
+@@ -1263,6 +1263,7 @@ static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg,
+ case -ECONNRESET:
+ case -EHOSTDOWN:
+ case -EHOSTUNREACH:
++ case -ENETDOWN:
+ case -ENETUNREACH:
+ case -EADDRINUSE:
+ case -ENOBUFS:
+--
+2.39.5
+
--- /dev/null
+From b306e9779eeecc72b2e7d41f7cca776c1d481e49 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Mar 2025 15:24:33 -0700
+Subject: PNP: Expand length of fixup id string
+
+From: Kees Cook <kees@kernel.org>
+
+[ Upstream commit 425b1c97b07f2290700f708edabef32861e2b2db ]
+
+GCC 15's -Wunterminated-string-initialization saw that "id" was not
+including the required trailing NUL character. Instead of marking "id"
+with __nonstring[1], expand the length of the string as it is used in
+(debugging) format strings that expect a properly formed C string.
+
+Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117178 [1]
+Signed-off-by: Kees Cook <kees@kernel.org>
+Link: https://patch.msgid.link/20250310222432.work.826-kees@kernel.org
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/pnp.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/linux/pnp.h b/include/linux/pnp.h
+index b7a7158aaf65e..23fe3eaf242d6 100644
+--- a/include/linux/pnp.h
++++ b/include/linux/pnp.h
+@@ -290,7 +290,7 @@ static inline void pnp_set_drvdata(struct pnp_dev *pdev, void *data)
+ }
+
+ struct pnp_fixup {
+- char id[7];
++ char id[8];
+ void (*quirk_function) (struct pnp_dev *dev); /* fixup function */
+ };
+
+--
+2.39.5
+
--- /dev/null
+From 7760142a7869d24acaea7597a1d3d84016e8aa5a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Mar 2025 17:48:17 +0100
+Subject: posix-timers: Add cond_resched() to posix_timer_add() search loop
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 5f2909c6cd13564a07ae692a95457f52295c4f22 ]
+
+With a large number of POSIX timers the search for a valid ID might cause a
+soft lockup on PREEMPT_NONE/VOLUNTARY kernels.
+
+Add cond_resched() to the loop to prevent that.
+
+[ tglx: Split out from Eric's series ]
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
+Link: https://lore.kernel.org/all/20250214135911.2037402-2-edumazet@google.com
+Link: https://lore.kernel.org/all/20250308155623.635612865@linutronix.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/time/posix-timers.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
+index 4576aaed13b23..896ff735034ce 100644
+--- a/kernel/time/posix-timers.c
++++ b/kernel/time/posix-timers.c
+@@ -118,6 +118,7 @@ static int posix_timer_add(struct k_itimer *timer)
+ return id;
+ }
+ spin_unlock(&hash_lock);
++ cond_resched();
+ }
+ /* POSIX return code when no timer ID could be allocated */
+ return -EAGAIN;
+--
+2.39.5
+
--- /dev/null
+From ef135dc8e5d557aa788c7b6aabfd11ca4a890569 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Mar 2025 17:48:10 +0100
+Subject: posix-timers: Ensure that timer initialization is fully visible
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit 2389c6efd3ad8edb3bcce0019b4edcc7d9c7de19 ]
+
+Frederic pointed out that the memory operations to initialize the timer are
+not guaranteed to be visible, when __lock_timer() observes timer::it_signal
+valid under timer::it_lock:
+
+ T0 T1
+ --------- -----------
+ do_timer_create()
+ // A
+ new_timer->.... = ....
+ spin_lock(current->sighand)
+ // B
+ WRITE_ONCE(new_timer->it_signal, current->signal)
+ spin_unlock(current->sighand)
+ sys_timer_*()
+ t = __lock_timer()
+ spin_lock(&timr->it_lock)
+ // observes B
+ if (timr->it_signal == current->signal)
+ return timr;
+ if (!t)
+ return;
+ // Is not guaranteed to observe A
+
+Protect the write of timer::it_signal, which makes the timer valid, with
+timer::it_lock as well. This guarantees that T1 must observe the
+initialization A completely, when it observes the valid signal pointer
+under timer::it_lock. sighand::siglock must still be taken to protect the
+signal::posix_timers list.
+
+Reported-by: Frederic Weisbecker <frederic@kernel.org>
+Suggested-by: Frederic Weisbecker <frederic@kernel.org>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
+Link: https://lore.kernel.org/all/20250308155623.507944489@linutronix.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/time/posix-timers.c | 21 ++++++++++++++-------
+ 1 file changed, 14 insertions(+), 7 deletions(-)
+
+diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
+index 896ff735034ce..c5d9bfbb082b8 100644
+--- a/kernel/time/posix-timers.c
++++ b/kernel/time/posix-timers.c
+@@ -514,14 +514,21 @@ static int do_timer_create(clockid_t which_clock, struct sigevent *event,
+ if (error)
+ goto out;
+
+- spin_lock_irq(¤t->sighand->siglock);
+- /* This makes the timer valid in the hash table */
+- WRITE_ONCE(new_timer->it_signal, current->signal);
+- hlist_add_head(&new_timer->list, ¤t->signal->posix_timers);
+- spin_unlock_irq(¤t->sighand->siglock);
+ /*
+- * After unlocking sighand::siglock @new_timer is subject to
+- * concurrent removal and cannot be touched anymore
++ * timer::it_lock ensures that __lock_timer() observes a fully
++ * initialized timer when it observes a valid timer::it_signal.
++ *
++ * sighand::siglock is required to protect signal::posix_timers.
++ */
++ scoped_guard (spinlock_irq, &new_timer->it_lock) {
++ guard(spinlock)(¤t->sighand->siglock);
++ /* This makes the timer valid in the hash table */
++ WRITE_ONCE(new_timer->it_signal, current->signal);
++ hlist_add_head(&new_timer->list, ¤t->signal->posix_timers);
++ }
++ /*
++ * After unlocking @new_timer is subject to concurrent removal and
++ * cannot be touched anymore
+ */
+ return 0;
+ out:
+--
+2.39.5
+
--- /dev/null
+From 00c8f743eb2db24c473dae02c43de82786b19bc1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Feb 2025 09:58:33 -0600
+Subject: power: supply: axp20x_battery: Update temp sensor for AXP717 from
+ device tree
+
+From: Chris Morgan <macromorgan@hotmail.com>
+
+[ Upstream commit bbcfe510ecd47f2db4c8653c7dfa9dc7a55b1583 ]
+
+Allow a boolean property of "x-powers,no-thermistor" to specify devices
+where the ts pin is not connected to anything. This works around an
+issue found with some devices where the efuse is not programmed
+correctly from the factory or when the register gets set erroneously.
+
+Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
+Tested-by: Philippe Simons <simons.philippe@gmail.com>
+Link: https://lore.kernel.org/r/20250204155835.161973-4-macroalpha82@gmail.com
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/power/supply/axp20x_battery.c | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c
+index 57eba1ddb17ba..88fbae613e8bc 100644
+--- a/drivers/power/supply/axp20x_battery.c
++++ b/drivers/power/supply/axp20x_battery.c
+@@ -89,6 +89,8 @@
+ #define AXP717_BAT_CC_MIN_UA 0
+ #define AXP717_BAT_CC_MAX_UA 3008000
+
++#define AXP717_TS_PIN_DISABLE BIT(4)
++
+ struct axp20x_batt_ps;
+
+ struct axp_data {
+@@ -117,6 +119,7 @@ struct axp20x_batt_ps {
+ /* Maximum constant charge current */
+ unsigned int max_ccc;
+ const struct axp_data *data;
++ bool ts_disable;
+ };
+
+ static int axp20x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
+@@ -983,6 +986,24 @@ static void axp717_set_battery_info(struct platform_device *pdev,
+ int ccc = info->constant_charge_current_max_ua;
+ int val;
+
++ axp_batt->ts_disable = (device_property_read_bool(axp_batt->dev,
++ "x-powers,no-thermistor"));
++
++ /*
++ * Under rare conditions an incorrectly programmed efuse for
++ * the temp sensor on the PMIC may trigger a fault condition.
++ * Allow users to hard-code if the ts pin is not used to work
++ * around this problem. Note that this requires the battery
++ * be correctly defined in the device tree with a monitored
++ * battery node.
++ */
++ if (axp_batt->ts_disable) {
++ regmap_update_bits(axp_batt->regmap,
++ AXP717_TS_PIN_CFG,
++ AXP717_TS_PIN_DISABLE,
++ AXP717_TS_PIN_DISABLE);
++ }
++
+ if (vmin > 0 && axp717_set_voltage_min_design(axp_batt, vmin))
+ dev_err(&pdev->dev,
+ "couldn't set voltage_min_design\n");
+--
+2.39.5
+
--- /dev/null
+From e54e285a44668071c93d922e9dc2eec7829d44f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jan 2025 18:19:09 +0100
+Subject: powerpc/prom_init: Fixup missing #size-cells on PowerBook6,7
+
+From: Andreas Schwab <schwab@linux-m68k.org>
+
+[ Upstream commit 7e67ef889c9ab7246547db73d524459f47403a77 ]
+
+Similar to the PowerMac3,1, the PowerBook6,7 is missing the #size-cells
+property on the i2s node.
+
+Depends-on: commit 045b14ca5c36 ("of: WARN on deprecated #address-cells/#size-cells handling")
+Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
+Acked-by: Rob Herring (Arm) <robh@kernel.org>
+[maddy: added "commit" work in depends-on to avoid checkpatch error]
+Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
+Link: https://patch.msgid.link/875xmizl6a.fsf@igel.home
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/kernel/prom_init.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
+index 935568d68196d..b1dc4cb9f78e6 100644
+--- a/arch/powerpc/kernel/prom_init.c
++++ b/arch/powerpc/kernel/prom_init.c
+@@ -2982,11 +2982,11 @@ static void __init fixup_device_tree_pmac(void)
+ char type[8];
+ phandle node;
+
+- // Some pmacs are missing #size-cells on escc nodes
++ // Some pmacs are missing #size-cells on escc or i2s nodes
+ for (node = 0; prom_next_node(&node); ) {
+ type[0] = '\0';
+ prom_getprop(node, "device_type", type, sizeof(type));
+- if (prom_strcmp(type, "escc"))
++ if (prom_strcmp(type, "escc") && prom_strcmp(type, "i2s"))
+ continue;
+
+ if (prom_getproplen(node, "#size-cells") != PROM_ERROR)
+--
+2.39.5
+
--- /dev/null
+From 349c1e84757a8583b89979238e659144a25afc71 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Jan 2025 10:48:14 -0600
+Subject: powerpc/pseries/iommu: create DDW for devices with DMA mask less than
+ 64-bits
+
+From: Gaurav Batra <gbatra@linux.ibm.com>
+
+[ Upstream commit 67dfc11982f7e3c37f0977e74671da2391b29181 ]
+
+Starting with PAPR level 2.13, platform supports placing PHB in limited
+address mode. Devices that support DMA masks less that 64-bit but greater
+than 32-bits are placed in limited address mode. In this mode, the
+starting DMA address returned by the DDW is 4GB.
+
+When the device driver calls dma_supported, with mask less then 64-bit, the
+PowerPC IOMMU driver places PHB in the Limited Addressing Mode before
+creating DDW.
+
+Signed-off-by: Gaurav Batra <gbatra@linux.ibm.com>
+Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
+Link: https://patch.msgid.link/20250108164814.73250-1-gbatra@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/platforms/pseries/iommu.c | 110 +++++++++++++++++++++----
+ 1 file changed, 94 insertions(+), 16 deletions(-)
+
+diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
+index 8f32340960e21..d6ebc19fb99c5 100644
+--- a/arch/powerpc/platforms/pseries/iommu.c
++++ b/arch/powerpc/platforms/pseries/iommu.c
+@@ -52,7 +52,8 @@ enum {
+ enum {
+ DDW_EXT_SIZE = 0,
+ DDW_EXT_RESET_DMA_WIN = 1,
+- DDW_EXT_QUERY_OUT_SIZE = 2
++ DDW_EXT_QUERY_OUT_SIZE = 2,
++ DDW_EXT_LIMITED_ADDR_MODE = 3
+ };
+
+ static struct iommu_table *iommu_pseries_alloc_table(int node)
+@@ -1327,6 +1328,54 @@ static void reset_dma_window(struct pci_dev *dev, struct device_node *par_dn)
+ ret);
+ }
+
++/*
++ * Platforms support placing PHB in limited address mode starting with LoPAR
++ * level 2.13 implement. In this mode, the DMA address returned by DDW is over
++ * 4GB but, less than 64-bits. This benefits IO adapters that don't support
++ * 64-bits for DMA addresses.
++ */
++static int limited_dma_window(struct pci_dev *dev, struct device_node *par_dn)
++{
++ int ret;
++ u32 cfg_addr, reset_dma_win, las_supported;
++ u64 buid;
++ struct device_node *dn;
++ struct pci_dn *pdn;
++
++ ret = ddw_read_ext(par_dn, DDW_EXT_RESET_DMA_WIN, &reset_dma_win);
++ if (ret)
++ goto out;
++
++ ret = ddw_read_ext(par_dn, DDW_EXT_LIMITED_ADDR_MODE, &las_supported);
++
++ /* Limited Address Space extension available on the platform but DDW in
++ * limited addressing mode not supported
++ */
++ if (!ret && !las_supported)
++ ret = -EPROTO;
++
++ if (ret) {
++ dev_info(&dev->dev, "Limited Address Space for DDW not Supported, err: %d", ret);
++ goto out;
++ }
++
++ dn = pci_device_to_OF_node(dev);
++ pdn = PCI_DN(dn);
++ buid = pdn->phb->buid;
++ cfg_addr = (pdn->busno << 16) | (pdn->devfn << 8);
++
++ ret = rtas_call(reset_dma_win, 4, 1, NULL, cfg_addr, BUID_HI(buid),
++ BUID_LO(buid), 1);
++ if (ret)
++ dev_info(&dev->dev,
++ "ibm,reset-pe-dma-windows(%x) for Limited Addr Support: %x %x %x returned %d ",
++ reset_dma_win, cfg_addr, BUID_HI(buid), BUID_LO(buid),
++ ret);
++
++out:
++ return ret;
++}
++
+ /* Return largest page shift based on "IO Page Sizes" output of ibm,query-pe-dma-window. */
+ static int iommu_get_page_shift(u32 query_page_size)
+ {
+@@ -1394,7 +1443,7 @@ static struct property *ddw_property_create(const char *propname, u32 liobn, u64
+ *
+ * returns true if can map all pages (direct mapping), false otherwise..
+ */
+-static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
++static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn, u64 dma_mask)
+ {
+ int len = 0, ret;
+ int max_ram_len = order_base_2(ddw_memory_hotplug_max());
+@@ -1413,6 +1462,9 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
+ bool pmem_present;
+ struct pci_dn *pci = PCI_DN(pdn);
+ struct property *default_win = NULL;
++ bool limited_addr_req = false, limited_addr_enabled = false;
++ int dev_max_ddw;
++ int ddw_sz;
+
+ dn = of_find_node_by_type(NULL, "ibm,pmemory");
+ pmem_present = dn != NULL;
+@@ -1439,7 +1491,6 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
+ * the ibm,ddw-applicable property holds the tokens for:
+ * ibm,query-pe-dma-window
+ * ibm,create-pe-dma-window
+- * ibm,remove-pe-dma-window
+ * for the given node in that order.
+ * the property is actually in the parent, not the PE
+ */
+@@ -1459,6 +1510,20 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
+ if (ret != 0)
+ goto out_failed;
+
++ /* DMA Limited Addressing required? This is when the driver has
++ * requested to create DDW but supports mask which is less than 64-bits
++ */
++ limited_addr_req = (dma_mask != DMA_BIT_MASK(64));
++
++ /* place the PHB in Limited Addressing mode */
++ if (limited_addr_req) {
++ if (limited_dma_window(dev, pdn))
++ goto out_failed;
++
++ /* PHB is in Limited address mode */
++ limited_addr_enabled = true;
++ }
++
+ /*
+ * If there is no window available, remove the default DMA window,
+ * if it's present. This will make all the resources available to the
+@@ -1505,6 +1570,15 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
+ goto out_failed;
+ }
+
++ /* Maximum DMA window size that the device can address (in log2) */
++ dev_max_ddw = fls64(dma_mask);
++
++ /* If the device DMA mask is less than 64-bits, make sure the DMA window
++ * size is not bigger than what the device can access
++ */
++ ddw_sz = min(order_base_2(query.largest_available_block << page_shift),
++ dev_max_ddw);
++
+ /*
+ * The "ibm,pmemory" can appear anywhere in the address space.
+ * Assuming it is still backed by page structs, try MAX_PHYSMEM_BITS
+@@ -1513,23 +1587,21 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
+ */
+ len = max_ram_len;
+ if (pmem_present) {
+- if (query.largest_available_block >=
+- (1ULL << (MAX_PHYSMEM_BITS - page_shift)))
++ if (ddw_sz >= MAX_PHYSMEM_BITS)
+ len = MAX_PHYSMEM_BITS;
+ else
+ dev_info(&dev->dev, "Skipping ibm,pmemory");
+ }
+
+ /* check if the available block * number of ptes will map everything */
+- if (query.largest_available_block < (1ULL << (len - page_shift))) {
++ if (ddw_sz < len) {
+ dev_dbg(&dev->dev,
+ "can't map partition max 0x%llx with %llu %llu-sized pages\n",
+ 1ULL << len,
+ query.largest_available_block,
+ 1ULL << page_shift);
+
+- len = order_base_2(query.largest_available_block << page_shift);
+-
++ len = ddw_sz;
+ dynamic_mapping = true;
+ } else {
+ direct_mapping = !default_win_removed ||
+@@ -1543,8 +1615,9 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
+ */
+ if (default_win_removed && pmem_present && !direct_mapping) {
+ /* DDW is big enough to be split */
+- if ((query.largest_available_block << page_shift) >=
+- MIN_DDW_VPMEM_DMA_WINDOW + (1ULL << max_ram_len)) {
++ if ((1ULL << ddw_sz) >=
++ MIN_DDW_VPMEM_DMA_WINDOW + (1ULL << max_ram_len)) {
++
+ direct_mapping = true;
+
+ /* offset of the Dynamic part of DDW */
+@@ -1555,8 +1628,7 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
+ dynamic_mapping = true;
+
+ /* create max size DDW possible */
+- len = order_base_2(query.largest_available_block
+- << page_shift);
++ len = ddw_sz;
+ }
+ }
+
+@@ -1685,7 +1757,7 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
+ __remove_dma_window(pdn, ddw_avail, create.liobn);
+
+ out_failed:
+- if (default_win_removed)
++ if (default_win_removed || limited_addr_enabled)
+ reset_dma_window(dev, pdn);
+
+ fpdn = kzalloc(sizeof(*fpdn), GFP_KERNEL);
+@@ -1704,6 +1776,9 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
+ dev->dev.bus_dma_limit = dev->dev.archdata.dma_offset +
+ (1ULL << max_ram_len);
+
++ dev_info(&dev->dev, "lsa_required: %x, lsa_enabled: %x, direct mapping: %x\n",
++ limited_addr_req, limited_addr_enabled, direct_mapping);
++
+ return direct_mapping;
+ }
+
+@@ -1829,8 +1904,11 @@ static bool iommu_bypass_supported_pSeriesLP(struct pci_dev *pdev, u64 dma_mask)
+ {
+ struct device_node *dn = pci_device_to_OF_node(pdev), *pdn;
+
+- /* only attempt to use a new window if 64-bit DMA is requested */
+- if (dma_mask < DMA_BIT_MASK(64))
++ /* For DDW, DMA mask should be more than 32-bits. For mask more then
++ * 32-bits but less then 64-bits, DMA addressing is supported in
++ * Limited Addressing mode.
++ */
++ if (dma_mask <= DMA_BIT_MASK(32))
+ return false;
+
+ dev_dbg(&pdev->dev, "node is %pOF\n", dn);
+@@ -1843,7 +1921,7 @@ static bool iommu_bypass_supported_pSeriesLP(struct pci_dev *pdev, u64 dma_mask)
+ */
+ pdn = pci_dma_find(dn, NULL);
+ if (pdn && PCI_DN(pdn))
+- return enable_ddw(pdev, pdn);
++ return enable_ddw(pdev, pdn, dma_mask);
+
+ return false;
+ }
+--
+2.39.5
+
--- /dev/null
+From d60e0ef2ac366cf7d6b9ca2bba9adf40a871b739 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jan 2025 12:38:54 -0600
+Subject: powerpc/pseries/iommu: memory notifier incorrectly adds TCEs for
+ pmemory
+
+From: Gaurav Batra <gbatra@linux.ibm.com>
+
+[ Upstream commit 6aa989ab2bd0d37540c812b4270006ff794662e7 ]
+
+iommu_mem_notifier() is invoked when RAM is dynamically added/removed. This
+notifier call is responsible to add/remove TCEs from the Dynamic DMA Window
+(DDW) when TCEs are pre-mapped. TCEs are pre-mapped only for RAM and not
+for persistent memory (pmemory). For DMA buffers in pmemory, TCEs are
+dynamically mapped when the device driver instructs to do so.
+
+The issue is 'daxctl' command is capable of adding pmemory as "System RAM"
+after LPAR boot. The command to do so is -
+
+daxctl reconfigure-device --mode=system-ram dax0.0 --force
+
+This will dynamically add pmemory range to LPAR RAM eventually invoking
+iommu_mem_notifier(). The address range of pmemory is way beyond the Max
+RAM that the LPAR can have. Which means, this range is beyond the DDW
+created for the device, at device initialization time.
+
+As a result when TCEs are pre-mapped for the pmemory range, by
+iommu_mem_notifier(), PHYP HCALL returns H_PARAMETER. This failed the
+command, daxctl, to add pmemory as RAM.
+
+The solution is to not pre-map TCEs for pmemory.
+
+Signed-off-by: Gaurav Batra <gbatra@linux.ibm.com>
+Tested-by: Donet Tom <donettom@linux.ibm.com>
+Reviewed-by: Donet Tom <donettom@linux.ibm.com>
+Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
+Link: https://patch.msgid.link/20250130183854.92258-1-gbatra@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/include/asm/mmzone.h | 1 +
+ arch/powerpc/mm/numa.c | 2 +-
+ arch/powerpc/platforms/pseries/iommu.c | 29 ++++++++++++++------------
+ 3 files changed, 18 insertions(+), 14 deletions(-)
+
+diff --git a/arch/powerpc/include/asm/mmzone.h b/arch/powerpc/include/asm/mmzone.h
+index d99863cd6cde4..049152f8d597a 100644
+--- a/arch/powerpc/include/asm/mmzone.h
++++ b/arch/powerpc/include/asm/mmzone.h
+@@ -29,6 +29,7 @@ extern cpumask_var_t node_to_cpumask_map[];
+ #ifdef CONFIG_MEMORY_HOTPLUG
+ extern unsigned long max_pfn;
+ u64 memory_hotplug_max(void);
++u64 hot_add_drconf_memory_max(void);
+ #else
+ #define memory_hotplug_max() memblock_end_of_DRAM()
+ #endif
+diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
+index 3c1da08304d03..603a0f652ba61 100644
+--- a/arch/powerpc/mm/numa.c
++++ b/arch/powerpc/mm/numa.c
+@@ -1336,7 +1336,7 @@ int hot_add_scn_to_nid(unsigned long scn_addr)
+ return nid;
+ }
+
+-static u64 hot_add_drconf_memory_max(void)
++u64 hot_add_drconf_memory_max(void)
+ {
+ struct device_node *memory = NULL;
+ struct device_node *dn = NULL;
+diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
+index ae6f7a235d8b2..8f32340960e21 100644
+--- a/arch/powerpc/platforms/pseries/iommu.c
++++ b/arch/powerpc/platforms/pseries/iommu.c
+@@ -1284,17 +1284,13 @@ static LIST_HEAD(failed_ddw_pdn_list);
+
+ static phys_addr_t ddw_memory_hotplug_max(void)
+ {
+- resource_size_t max_addr = memory_hotplug_max();
+- struct device_node *memory;
++ resource_size_t max_addr;
+
+- for_each_node_by_type(memory, "memory") {
+- struct resource res;
+-
+- if (of_address_to_resource(memory, 0, &res))
+- continue;
+-
+- max_addr = max_t(resource_size_t, max_addr, res.end + 1);
+- }
++#if defined(CONFIG_NUMA) && defined(CONFIG_MEMORY_HOTPLUG)
++ max_addr = hot_add_drconf_memory_max();
++#else
++ max_addr = memblock_end_of_DRAM();
++#endif
+
+ return max_addr;
+ }
+@@ -1600,7 +1596,7 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
+
+ if (direct_mapping) {
+ /* DDW maps the whole partition, so enable direct DMA mapping */
+- ret = walk_system_ram_range(0, memblock_end_of_DRAM() >> PAGE_SHIFT,
++ ret = walk_system_ram_range(0, ddw_memory_hotplug_max() >> PAGE_SHIFT,
+ win64->value, tce_setrange_multi_pSeriesLP_walk);
+ if (ret) {
+ dev_info(&dev->dev, "failed to map DMA window for %pOF: %d\n",
+@@ -2349,11 +2345,17 @@ static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
+ struct memory_notify *arg = data;
+ int ret = 0;
+
++ /* This notifier can get called when onlining persistent memory as well.
++ * TCEs are not pre-mapped for persistent memory. Persistent memory will
++ * always be above ddw_memory_hotplug_max()
++ */
++
+ switch (action) {
+ case MEM_GOING_ONLINE:
+ spin_lock(&dma_win_list_lock);
+ list_for_each_entry(window, &dma_win_list, list) {
+- if (window->direct) {
++ if (window->direct && (arg->start_pfn << PAGE_SHIFT) <
++ ddw_memory_hotplug_max()) {
+ ret |= tce_setrange_multi_pSeriesLP(arg->start_pfn,
+ arg->nr_pages, window->prop);
+ }
+@@ -2365,7 +2367,8 @@ static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
+ case MEM_OFFLINE:
+ spin_lock(&dma_win_list_lock);
+ list_for_each_entry(window, &dma_win_list, list) {
+- if (window->direct) {
++ if (window->direct && (arg->start_pfn << PAGE_SHIFT) <
++ ddw_memory_hotplug_max()) {
+ ret |= tce_clearrange_multi_pSeriesLP(arg->start_pfn,
+ arg->nr_pages, window->prop);
+ }
+--
+2.39.5
+
--- /dev/null
+From bf4408e68c8ff4421cb0b82b29f48ca4f1cb0fcc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Feb 2025 16:59:05 -0300
+Subject: printk: Check CON_SUSPEND when unblanking a console
+
+From: Marcos Paulo de Souza <mpdesouza@suse.com>
+
+[ Upstream commit 72c96a2dacc0fb056d13a5f02b0845c4c910fe54 ]
+
+The commit 9e70a5e109a4 ("printk: Add per-console suspended state")
+introduced the CON_SUSPENDED flag for consoles. The suspended consoles
+will stop receiving messages, so don't unblank suspended consoles
+because it won't be showing anything either way.
+
+Signed-off-by: Marcos Paulo de Souza <mpdesouza@suse.com>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Reviewed-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20250226-printk-renaming-v1-5-0b878577f2e6@suse.com
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/printk/printk.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
+index 881a26e18c658..3a91b739e8f30 100644
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -3310,7 +3310,12 @@ void console_unblank(void)
+ */
+ cookie = console_srcu_read_lock();
+ for_each_console_srcu(c) {
+- if ((console_srcu_read_flags(c) & CON_ENABLED) && c->unblank) {
++ short flags = console_srcu_read_flags(c);
++
++ if (flags & CON_SUSPENDED)
++ continue;
++
++ if ((flags & CON_ENABLED) && c->unblank) {
+ found_unblank = true;
+ break;
+ }
+@@ -3347,7 +3352,12 @@ void console_unblank(void)
+
+ cookie = console_srcu_read_lock();
+ for_each_console_srcu(c) {
+- if ((console_srcu_read_flags(c) & CON_ENABLED) && c->unblank)
++ short flags = console_srcu_read_flags(c);
++
++ if (flags & CON_SUSPENDED)
++ continue;
++
++ if ((flags & CON_ENABLED) && c->unblank)
+ c->unblank();
+ }
+ console_srcu_read_unlock(cookie);
+--
+2.39.5
+
--- /dev/null
+From c90e28881334dcbe3d369c4a4941b0ce39f0ce31 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Feb 2025 11:16:59 -0800
+Subject: pstore: Change kmsg_bytes storage size to u32
+
+From: Kees Cook <kees@kernel.org>
+
+[ Upstream commit 5674609535bafa834ab014d90d9bbe8e89223a0b ]
+
+The types around kmsg_bytes were inconsistent. The global was unsigned
+long, the argument to pstore_set_kmsg_bytes() was int, and the filesystem
+option was u32. Given other internal limits, there's not much sense
+in making a single pstore record larger than INT_MAX and it can't be
+negative, so use u32 everywhere. Additionally, use READ/WRITE_ONCE and a
+local variable in pstore_dump() to avoid kmsg_bytes changing during a
+dump.
+
+Link: https://lore.kernel.org/r/20250206191655.work.798-kees@kernel.org
+Signed-off-by: Kees Cook <kees@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/pstore/inode.c | 2 +-
+ fs/pstore/internal.h | 4 ++--
+ fs/pstore/platform.c | 11 ++++++-----
+ 3 files changed, 9 insertions(+), 8 deletions(-)
+
+diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
+index 56815799ce798..9de6b280c4f41 100644
+--- a/fs/pstore/inode.c
++++ b/fs/pstore/inode.c
+@@ -265,7 +265,7 @@ static void parse_options(char *options)
+ static int pstore_show_options(struct seq_file *m, struct dentry *root)
+ {
+ if (kmsg_bytes != CONFIG_PSTORE_DEFAULT_KMSG_BYTES)
+- seq_printf(m, ",kmsg_bytes=%lu", kmsg_bytes);
++ seq_printf(m, ",kmsg_bytes=%u", kmsg_bytes);
+ return 0;
+ }
+
+diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h
+index 801d6c0b170c3..a0fc511969100 100644
+--- a/fs/pstore/internal.h
++++ b/fs/pstore/internal.h
+@@ -6,7 +6,7 @@
+ #include <linux/time.h>
+ #include <linux/pstore.h>
+
+-extern unsigned long kmsg_bytes;
++extern unsigned int kmsg_bytes;
+
+ #ifdef CONFIG_PSTORE_FTRACE
+ extern void pstore_register_ftrace(void);
+@@ -35,7 +35,7 @@ static inline void pstore_unregister_pmsg(void) {}
+
+ extern struct pstore_info *psinfo;
+
+-extern void pstore_set_kmsg_bytes(int);
++extern void pstore_set_kmsg_bytes(unsigned int bytes);
+ extern void pstore_get_records(int);
+ extern void pstore_get_backend_records(struct pstore_info *psi,
+ struct dentry *root, int quiet);
+diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
+index f56b066ab80ce..557cf9d40177f 100644
+--- a/fs/pstore/platform.c
++++ b/fs/pstore/platform.c
+@@ -92,8 +92,8 @@ module_param(compress, charp, 0444);
+ MODULE_PARM_DESC(compress, "compression to use");
+
+ /* How much of the kernel log to snapshot */
+-unsigned long kmsg_bytes = CONFIG_PSTORE_DEFAULT_KMSG_BYTES;
+-module_param(kmsg_bytes, ulong, 0444);
++unsigned int kmsg_bytes = CONFIG_PSTORE_DEFAULT_KMSG_BYTES;
++module_param(kmsg_bytes, uint, 0444);
+ MODULE_PARM_DESC(kmsg_bytes, "amount of kernel log to snapshot (in bytes)");
+
+ static void *compress_workspace;
+@@ -107,9 +107,9 @@ static void *compress_workspace;
+ static char *big_oops_buf;
+ static size_t max_compressed_size;
+
+-void pstore_set_kmsg_bytes(int bytes)
++void pstore_set_kmsg_bytes(unsigned int bytes)
+ {
+- kmsg_bytes = bytes;
++ WRITE_ONCE(kmsg_bytes, bytes);
+ }
+
+ /* Tag each group of saved records with a sequence number */
+@@ -278,6 +278,7 @@ static void pstore_dump(struct kmsg_dumper *dumper,
+ struct kmsg_dump_detail *detail)
+ {
+ struct kmsg_dump_iter iter;
++ unsigned int remaining = READ_ONCE(kmsg_bytes);
+ unsigned long total = 0;
+ const char *why;
+ unsigned int part = 1;
+@@ -300,7 +301,7 @@ static void pstore_dump(struct kmsg_dumper *dumper,
+ kmsg_dump_rewind(&iter);
+
+ oopscount++;
+- while (total < kmsg_bytes) {
++ while (total < remaining) {
+ char *dst;
+ size_t dst_size;
+ int header_size;
+--
+2.39.5
+
--- /dev/null
+From 8f4b77a6ac92b2645ad3192d37038d77a6e94658 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Feb 2025 23:40:33 +0100
+Subject: r8152: add vendor/device ID pair for Dell Alienware AW1022z
+
+From: Aleksander Jan Bajkowski <olek2@wp.pl>
+
+[ Upstream commit 848b09d53d923b4caee5491f57a5c5b22d81febc ]
+
+The Dell AW1022z is an RTL8156B based 2.5G Ethernet controller.
+
+Add the vendor and product ID values to the driver. This makes Ethernet
+work with the adapter.
+
+Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl>
+Link: https://patch.msgid.link/20250206224033.980115-1-olek2@wp.pl
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/r8152.c | 1 +
+ include/linux/usb/r8152.h | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
+index 96fa3857d8e25..2cab046749a92 100644
+--- a/drivers/net/usb/r8152.c
++++ b/drivers/net/usb/r8152.c
+@@ -10085,6 +10085,7 @@ static const struct usb_device_id rtl8152_table[] = {
+ { USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff) },
+ { USB_DEVICE(VENDOR_ID_TPLINK, 0x0601) },
+ { USB_DEVICE(VENDOR_ID_DLINK, 0xb301) },
++ { USB_DEVICE(VENDOR_ID_DELL, 0xb097) },
+ { USB_DEVICE(VENDOR_ID_ASUS, 0x1976) },
+ {}
+ };
+diff --git a/include/linux/usb/r8152.h b/include/linux/usb/r8152.h
+index 33a4c146dc19c..2ca60828f28bb 100644
+--- a/include/linux/usb/r8152.h
++++ b/include/linux/usb/r8152.h
+@@ -30,6 +30,7 @@
+ #define VENDOR_ID_NVIDIA 0x0955
+ #define VENDOR_ID_TPLINK 0x2357
+ #define VENDOR_ID_DLINK 0x2001
++#define VENDOR_ID_DELL 0x413c
+ #define VENDOR_ID_ASUS 0x0b05
+
+ #if IS_REACHABLE(CONFIG_USB_RTL8152)
+--
+2.39.5
+
--- /dev/null
+From 1e859877d0e392e3a2a97926da6a00c0fb2bf999 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Mar 2025 16:37:21 +0800
+Subject: r8169: disable RTL8126 ZRX-DC timeout
+
+From: ChunHao Lin <hau@realtek.com>
+
+[ Upstream commit b48688ea3c9ac8d5d910c6e91fb7f80d846581f0 ]
+
+Disable it due to it dose not meet ZRX-DC specification. If it is enabled,
+device will exit L1 substate every 100ms. Disable it for saving more power
+in L1 substate.
+
+Signed-off-by: ChunHao Lin <hau@realtek.com>
+Reviewed-by: Heiner Kallweit <hkallweit1@gmail.com>
+Link: https://patch.msgid.link/20250318083721.4127-3-hau@realtek.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 27 +++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
+index 5ed2818bac257..3420b6cf8189f 100644
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -2850,6 +2850,32 @@ static u32 rtl_csi_read(struct rtl8169_private *tp, int addr)
+ RTL_R32(tp, CSIDR) : ~0;
+ }
+
++static void rtl_disable_zrxdc_timeout(struct rtl8169_private *tp)
++{
++ struct pci_dev *pdev = tp->pci_dev;
++ u32 csi;
++ int rc;
++ u8 val;
++
++#define RTL_GEN3_RELATED_OFF 0x0890
++#define RTL_GEN3_ZRXDC_NONCOMPL 0x1
++ if (pdev->cfg_size > RTL_GEN3_RELATED_OFF) {
++ rc = pci_read_config_byte(pdev, RTL_GEN3_RELATED_OFF, &val);
++ if (rc == PCIBIOS_SUCCESSFUL) {
++ val &= ~RTL_GEN3_ZRXDC_NONCOMPL;
++ rc = pci_write_config_byte(pdev, RTL_GEN3_RELATED_OFF,
++ val);
++ if (rc == PCIBIOS_SUCCESSFUL)
++ return;
++ }
++ }
++
++ netdev_notice_once(tp->dev,
++ "No native access to PCI extended config space, falling back to CSI\n");
++ csi = rtl_csi_read(tp, RTL_GEN3_RELATED_OFF);
++ rtl_csi_write(tp, RTL_GEN3_RELATED_OFF, csi & ~RTL_GEN3_ZRXDC_NONCOMPL);
++}
++
+ static void rtl_set_aspm_entry_latency(struct rtl8169_private *tp, u8 val)
+ {
+ struct pci_dev *pdev = tp->pci_dev;
+@@ -3816,6 +3842,7 @@ static void rtl_hw_start_8125b(struct rtl8169_private *tp)
+
+ static void rtl_hw_start_8126a(struct rtl8169_private *tp)
+ {
++ rtl_disable_zrxdc_timeout(tp);
+ rtl_set_def_aspm_entry_latency(tp);
+ rtl_hw_start_8125_common(tp);
+ }
+--
+2.39.5
+
--- /dev/null
+From 69a307f5fa0eeec6920ba25a4120a4a554443434 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Feb 2025 07:58:17 +0100
+Subject: r8169: don't scan PHY addresses > 0
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+[ Upstream commit faac69a4ae5abb49e62c79c66b51bb905c9aa5ec ]
+
+The PHY address is a dummy, because r8169 PHY access registers
+don't support a PHY address. Therefore scan address 0 only.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/830637dd-4016-4a68-92b3-618fcac6589d@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
+index 3420b6cf8189f..85bb5121cd245 100644
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -5258,6 +5258,7 @@ static int r8169_mdio_register(struct rtl8169_private *tp)
+ new_bus->priv = tp;
+ new_bus->parent = &pdev->dev;
+ new_bus->irq[0] = PHY_MAC_INTERRUPT;
++ new_bus->phy_mask = GENMASK(31, 1);
+ snprintf(new_bus->id, MII_BUS_ID_SIZE, "r8169-%x-%x",
+ pci_domain_nr(pdev->bus), pci_dev_id(pdev));
+
+--
+2.39.5
+
--- /dev/null
+From 810f6648011b4f7f7b952821e9ad2663a5a1bdea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 Dec 2024 14:15:07 -0800
+Subject: rcu: Fix get_state_synchronize_rcu_full() GP-start detection
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Paul E. McKenney <paulmck@kernel.org>
+
+[ Upstream commit 85aad7cc417877054c65bd490dc037b087ef21b4 ]
+
+The get_state_synchronize_rcu_full() and poll_state_synchronize_rcu_full()
+functions use the root rcu_node structure's ->gp_seq field to detect
+the beginnings and ends of grace periods, respectively. This choice is
+necessary for the poll_state_synchronize_rcu_full() function because
+(give or take counter wrap), the following sequence is guaranteed not
+to trigger:
+
+ get_state_synchronize_rcu_full(&rgos);
+ synchronize_rcu();
+ WARN_ON_ONCE(!poll_state_synchronize_rcu_full(&rgos));
+
+The RCU callbacks that awaken synchronize_rcu() instances are
+guaranteed not to be invoked before the root rcu_node structure's
+->gp_seq field is updated to indicate the end of the grace period.
+However, these callbacks might start being invoked immediately
+thereafter, in particular, before rcu_state.gp_seq has been updated.
+Therefore, poll_state_synchronize_rcu_full() must refer to the
+root rcu_node structure's ->gp_seq field. Because this field is
+updated under this structure's ->lock, any code following a call to
+poll_state_synchronize_rcu_full() will be fully ordered after the
+full grace-period computation, as is required by RCU's memory-ordering
+semantics.
+
+By symmetry, the get_state_synchronize_rcu_full() function should also
+use this same root rcu_node structure's ->gp_seq field. But it turns out
+that symmetry is profoundly (though extremely infrequently) destructive
+in this case. To see this, consider the following sequence of events:
+
+1. CPU 0 starts a new grace period, and updates rcu_state.gp_seq
+ accordingly.
+
+2. As its first step of grace-period initialization, CPU 0 examines
+ the current CPU hotplug state and decides that it need not wait
+ for CPU 1, which is currently offline.
+
+3. CPU 1 comes online, and updates its state. But this does not
+ affect the current grace period, but rather the one after that.
+ After all, CPU 1 was offline when the current grace period
+ started, so all pre-existing RCU readers on CPU 1 must have
+ completed or been preempted before it last went offline.
+ The current grace period therefore has nothing it needs to wait
+ for on CPU 1.
+
+4. CPU 1 switches to an rcutorture kthread which is running
+ rcutorture's rcu_torture_reader() function, which starts a new
+ RCU reader.
+
+5. CPU 2 is running rcutorture's rcu_torture_writer() function
+ and collects a new polled grace-period "cookie" using
+ get_state_synchronize_rcu_full(). Because the newly started
+ grace period has not completed initialization, the root rcu_node
+ structure's ->gp_seq field has not yet been updated to indicate
+ that this new grace period has already started.
+
+ This cookie is therefore set up for the end of the current grace
+ period (rather than the end of the following grace period).
+
+6. CPU 0 finishes grace-period initialization.
+
+7. If CPU 1’s rcutorture reader is preempted, it will be added to
+ the ->blkd_tasks list, but because CPU 1’s ->qsmask bit is not
+ set in CPU 1's leaf rcu_node structure, the ->gp_tasks pointer
+ will not be updated. Thus, this grace period will not wait on
+ it. Which is only fair, given that the CPU did not come online
+ until after the grace period officially started.
+
+8. CPUs 0 and 2 then detect the new grace period and then report
+ a quiescent state to the RCU core.
+
+9. Because CPU 1 was offline at the start of the current grace
+ period, CPUs 0 and 2 are the only CPUs that this grace period
+ needs to wait on. So the grace period ends and post-grace-period
+ cleanup starts. In particular, the root rcu_node structure's
+ ->gp_seq field is updated to indicate that this grace period
+ has now ended.
+
+10. CPU 2 continues running rcu_torture_writer() and sees that,
+ from the viewpoint of the root rcu_node structure consulted by
+ the poll_state_synchronize_rcu_full() function, the grace period
+ has ended. It therefore updates state accordingly.
+
+11. CPU 1 is still running the same RCU reader, which notices this
+ update and thus complains about the too-short grace period.
+
+The fix is for the get_state_synchronize_rcu_full() function to use
+rcu_state.gp_seq instead of the root rcu_node structure's ->gp_seq field.
+With this change in place, if step 5's cookie indicates that the grace
+period has not yet started, then any prior code executed by CPU 2 must
+have happened before CPU 1 came online. This will in turn prevent CPU
+1's code in steps 3 and 11 from spanning CPU 2's grace-period wait,
+thus preventing CPU 1 from being subjected to a too-short grace period.
+
+This commit therefore makes this change. Note that there is no change to
+the poll_state_synchronize_rcu_full() function, which as noted above,
+must continue to use the root rcu_node structure's ->gp_seq field.
+This is of course an asymmetry between these two functions, but is an
+asymmetry that is absolutely required for correct operation. It is a
+common human tendency to greatly value symmetry, and sometimes symmetry
+is a wonderful thing. Other times, symmetry results in poor performance.
+But in this case, symmetry is just plain wrong.
+
+Nevertheless, the asymmetry does require an additional adjustment.
+It is possible for get_state_synchronize_rcu_full() to see a given
+grace period as having started, but for an immediately following
+poll_state_synchronize_rcu_full() to see it as having not yet started.
+Given the current rcu_seq_done_exact() implementation, this will
+result in a false-positive indication that the grace period is done
+from poll_state_synchronize_rcu_full(). This is dealt with by making
+rcu_seq_done_exact() reach back three grace periods rather than just
+two of them.
+
+However, simply changing get_state_synchronize_rcu_full() function to
+use rcu_state.gp_seq instead of the root rcu_node structure's ->gp_seq
+field results in a theoretical bug in kernels booted with
+rcutree.rcu_normal_wake_from_gp=1 due to the following sequence of
+events:
+
+o The rcu_gp_init() function invokes rcu_seq_start() to officially
+ start a new grace period.
+
+o A new RCU reader begins, referencing X from some RCU-protected
+ list. The new grace period is not obligated to wait for this
+ reader.
+
+o An updater removes X, then calls synchronize_rcu(), which queues
+ a wait element.
+
+o The grace period ends, awakening the updater, which frees X
+ while the reader is still referencing it.
+
+The reason that this is theoretical is that although the grace period
+has officially started, none of the CPUs are officially aware of this,
+and thus will have to assume that the RCU reader pre-dated the start of
+the grace period. Detailed explanation can be found at [2] and [3].
+
+Except for kernels built with CONFIG_PROVE_RCU=y, which use the polled
+grace-period APIs, which can and do complain bitterly when this sequence
+of events occurs. Not only that, there might be some future RCU
+grace-period mechanism that pulls this sequence of events from theory
+into practice. This commit therefore also pulls the call to
+rcu_sr_normal_gp_init() to precede that to rcu_seq_start().
+
+Although this fixes commit 91a967fd6934 ("rcu: Add full-sized polling
+for get_completed*() and poll_state*()"), it is not clear that it is
+worth backporting this commit. First, it took me many weeks to convince
+rcutorture to reproduce this more frequently than once per year.
+Second, this cannot be reproduced at all without frequent CPU-hotplug
+operations, as in waiting all of 50 milliseconds from the end of the
+previous operation until starting the next one. Third, the TREE03.boot
+settings cause multi-millisecond delays during RCU grace-period
+initialization, which greatly increase the probability of the above
+sequence of events. (Don't do this in production workloads!) Fourth,
+the TREE03 rcutorture scenario was modified to use four-CPU guest OSes,
+to have a single-rcu_node combining tree, no testing of RCU priority
+boosting, and no random preemption, and these modifications were
+necessary to reproduce this issue in a reasonable timeframe. Fifth,
+extremely heavy use of get_state_synchronize_rcu_full() and/or
+poll_state_synchronize_rcu_full() is required to reproduce this, and as
+of v6.12, only kfree_rcu() uses it, and even then not particularly
+heavily.
+
+[boqun: Apply the fix [1], and add the comment before the moved
+rcu_sr_normal_gp_init(). Additional links are added for explanation.]
+
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
+Reviewed-by: Joel Fernandes (Google) <joel@joelfernandes.org>
+Tested-by: Uladzislau Rezki (Sony) <urezki@gmail.com>
+Link: https://lore.kernel.org/rcu/d90bd6d9-d15c-4b9b-8a69-95336e74e8f4@paulmck-laptop/ [1]
+Link: https://lore.kernel.org/rcu/20250303001507.GA3994772@joelnvbox/ [2]
+Link: https://lore.kernel.org/rcu/Z8bcUsZ9IpRi1QoP@pc636/ [3]
+Reviewed-by: Joel Fernandes <joelagnelf@nvidia.com>
+Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/rcu/rcu.h | 2 +-
+ kernel/rcu/tree.c | 15 +++++++++++----
+ 2 files changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h
+index feb3ac1dc5d59..f87c9d6d36fcb 100644
+--- a/kernel/rcu/rcu.h
++++ b/kernel/rcu/rcu.h
+@@ -162,7 +162,7 @@ static inline bool rcu_seq_done_exact(unsigned long *sp, unsigned long s)
+ {
+ unsigned long cur_s = READ_ONCE(*sp);
+
+- return ULONG_CMP_GE(cur_s, s) || ULONG_CMP_LT(cur_s, s - (2 * RCU_SEQ_STATE_MASK + 1));
++ return ULONG_CMP_GE(cur_s, s) || ULONG_CMP_LT(cur_s, s - (3 * RCU_SEQ_STATE_MASK + 1));
+ }
+
+ /*
+diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
+index 8e52c1dd06284..4ed8632195217 100644
+--- a/kernel/rcu/tree.c
++++ b/kernel/rcu/tree.c
+@@ -1822,10 +1822,14 @@ static noinline_for_stack bool rcu_gp_init(void)
+
+ /* Advance to a new grace period and initialize state. */
+ record_gp_stall_check_time();
++ /*
++ * A new wait segment must be started before gp_seq advanced, so
++ * that previous gp waiters won't observe the new gp_seq.
++ */
++ start_new_poll = rcu_sr_normal_gp_init();
+ /* Record GP times before starting GP, hence rcu_seq_start(). */
+ rcu_seq_start(&rcu_state.gp_seq);
+ ASSERT_EXCLUSIVE_WRITER(rcu_state.gp_seq);
+- start_new_poll = rcu_sr_normal_gp_init();
+ trace_rcu_grace_period(rcu_state.name, rcu_state.gp_seq, TPS("start"));
+ rcu_poll_gp_seq_start(&rcu_state.gp_seq_polled_snap);
+ raw_spin_unlock_irq_rcu_node(rnp);
+@@ -4183,14 +4187,17 @@ EXPORT_SYMBOL_GPL(get_state_synchronize_rcu);
+ */
+ void get_state_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp)
+ {
+- struct rcu_node *rnp = rcu_get_root();
+-
+ /*
+ * Any prior manipulation of RCU-protected data must happen
+ * before the loads from ->gp_seq and ->expedited_sequence.
+ */
+ smp_mb(); /* ^^^ */
+- rgosp->rgos_norm = rcu_seq_snap(&rnp->gp_seq);
++
++ // Yes, rcu_state.gp_seq, not rnp_root->gp_seq, the latter's use
++ // in poll_state_synchronize_rcu_full() notwithstanding. Use of
++ // the latter here would result in too-short grace periods due to
++ // interactions with newly onlined CPUs.
++ rgosp->rgos_norm = rcu_seq_snap(&rcu_state.gp_seq);
+ rgosp->rgos_exp = rcu_seq_snap(&rcu_state.expedited_sequence);
+ }
+ EXPORT_SYMBOL_GPL(get_state_synchronize_rcu_full);
+--
+2.39.5
+
--- /dev/null
+From 90137af73c9fb4c5d1ca5e75907c66f9a645827e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 Dec 2024 20:06:52 -0800
+Subject: rcu: fix header guard for rcu_all_qs()
+
+From: Ankur Arora <ankur.a.arora@oracle.com>
+
+[ Upstream commit ad6b5b73ff565e88aca7a7d1286788d80c97ba71 ]
+
+rcu_all_qs() is defined for !CONFIG_PREEMPT_RCU but the declaration
+is conditioned on CONFIG_PREEMPTION.
+
+With CONFIG_PREEMPT_LAZY, CONFIG_PREEMPTION=y does not imply
+CONFIG_PREEMPT_RCU=y.
+
+Decouple the two.
+
+Cc: Paul E. McKenney <paulmck@kernel.org>
+Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
+Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Ankur Arora <ankur.a.arora@oracle.com>
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/rcutree.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
+index 90a684f94776e..ae8b5cb475a36 100644
+--- a/include/linux/rcutree.h
++++ b/include/linux/rcutree.h
+@@ -104,7 +104,7 @@ extern int rcu_scheduler_active;
+ void rcu_end_inkernel_boot(void);
+ bool rcu_inkernel_boot_has_ended(void);
+ bool rcu_is_watching(void);
+-#ifndef CONFIG_PREEMPTION
++#ifndef CONFIG_PREEMPT_RCU
+ void rcu_all_qs(void);
+ #endif
+
+--
+2.39.5
+
--- /dev/null
+From 883a1da2dd727a10e12dd8756d383ce4cd97b91f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 Dec 2024 20:06:56 -0800
+Subject: rcu: handle quiescent states for PREEMPT_RCU=n, PREEMPT_COUNT=y
+
+From: Ankur Arora <ankur.a.arora@oracle.com>
+
+[ Upstream commit 83b28cfe796464ebbde1cf7916c126da6d572685 ]
+
+With PREEMPT_RCU=n, cond_resched() provides urgently needed quiescent
+states for read-side critical sections via rcu_all_qs().
+One reason why this was needed: lacking preempt-count, the tick
+handler has no way of knowing whether it is executing in a
+read-side critical section or not.
+
+With (PREEMPT_LAZY=y, PREEMPT_DYNAMIC=n), we get (PREEMPT_COUNT=y,
+PREEMPT_RCU=n). In this configuration cond_resched() is a stub and
+does not provide quiescent states via rcu_all_qs().
+(PREEMPT_RCU=y provides this information via rcu_read_unlock() and
+its nesting counter.)
+
+So, use the availability of preempt_count() to report quiescent states
+in rcu_flavor_sched_clock_irq().
+
+Suggested-by: Paul E. McKenney <paulmck@kernel.org>
+Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Ankur Arora <ankur.a.arora@oracle.com>
+Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/rcu/tree_plugin.h | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
+index 1c7cbd145d5e3..75ba4d5788c0f 100644
+--- a/kernel/rcu/tree_plugin.h
++++ b/kernel/rcu/tree_plugin.h
+@@ -974,13 +974,16 @@ static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp)
+ */
+ static void rcu_flavor_sched_clock_irq(int user)
+ {
+- if (user || rcu_is_cpu_rrupt_from_idle()) {
++ if (user || rcu_is_cpu_rrupt_from_idle() ||
++ (IS_ENABLED(CONFIG_PREEMPT_COUNT) &&
++ (preempt_count() == HARDIRQ_OFFSET))) {
+
+ /*
+ * Get here if this CPU took its interrupt from user
+- * mode or from the idle loop, and if this is not a
+- * nested interrupt. In this case, the CPU is in
+- * a quiescent state, so note it.
++ * mode, from the idle loop without this being a nested
++ * interrupt, or while not holding the task preempt count
++ * (with PREEMPT_COUNT=y). In this case, the CPU is in a
++ * quiescent state, so note it.
+ *
+ * No memory barrier is required here because rcu_qs()
+ * references only CPU-local variables that other CPUs
+--
+2.39.5
+
--- /dev/null
+From 0245be6a50e054178f24b7fc6eb991a59758db8c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 Dec 2024 20:06:55 -0800
+Subject: rcu: handle unstable rdp in rcu_read_unlock_strict()
+
+From: Ankur Arora <ankur.a.arora@oracle.com>
+
+[ Upstream commit fcf0e25ad4c8d14d2faab4d9a17040f31efce205 ]
+
+rcu_read_unlock_strict() can be called with preemption enabled
+which can make for an unstable rdp and a racy norm value.
+
+Fix this by dropping the preempt-count in __rcu_read_unlock()
+after the call to rcu_read_unlock_strict(), adjusting the
+preempt-count check appropriately.
+
+Suggested-by: Frederic Weisbecker <frederic@kernel.org>
+Signed-off-by: Ankur Arora <ankur.a.arora@oracle.com>
+Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/rcupdate.h | 2 +-
+ kernel/rcu/tree_plugin.h | 11 ++++++++++-
+ 2 files changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
+index bd69ddc102fbc..0844ab3288519 100644
+--- a/include/linux/rcupdate.h
++++ b/include/linux/rcupdate.h
+@@ -95,9 +95,9 @@ static inline void __rcu_read_lock(void)
+
+ static inline void __rcu_read_unlock(void)
+ {
+- preempt_enable();
+ if (IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD))
+ rcu_read_unlock_strict();
++ preempt_enable();
+ }
+
+ static inline int rcu_preempt_depth(void)
+diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
+index 75ba4d5788c0f..304e3405e6ec7 100644
+--- a/kernel/rcu/tree_plugin.h
++++ b/kernel/rcu/tree_plugin.h
+@@ -832,8 +832,17 @@ void rcu_read_unlock_strict(void)
+ {
+ struct rcu_data *rdp;
+
+- if (irqs_disabled() || preempt_count() || !rcu_state.gp_kthread)
++ if (irqs_disabled() || in_atomic_preempt_off() || !rcu_state.gp_kthread)
+ return;
++
++ /*
++ * rcu_report_qs_rdp() can only be invoked with a stable rdp and
++ * from the local CPU.
++ *
++ * The in_atomic_preempt_off() check ensures that we come here holding
++ * the last preempt_count (which will get dropped once we return to
++ * __rcu_read_unlock().
++ */
+ rdp = this_cpu_ptr(&rcu_data);
+ rdp->cpu_no_qs.b.norm = false;
+ rcu_report_qs_rdp(rdp);
+--
+2.39.5
+
--- /dev/null
+From 5d73f58630925bb001cff677390e4817646f2277 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 14:16:23 +0000
+Subject: RDMA/core: Fix best page size finding when it can cross SG entries
+
+From: Michael Margolin <mrgolin@amazon.com>
+
+[ Upstream commit 486055f5e09df959ad4e3aa4ee75b5c91ddeec2e ]
+
+A single scatter-gather entry is limited by a 32 bits "length" field
+that is practically 4GB - PAGE_SIZE. This means that even when the
+memory is physically contiguous, we might need more than one entry to
+represent it. Additionally when using dmabuf, the sg_table might be
+originated outside the subsystem and optimized for other needs.
+
+For instance an SGT of 16GB GPU continuous memory might look like this:
+(a real life example)
+
+dma_address 34401400000, length fffff000
+dma_address 345013ff000, length fffff000
+dma_address 346013fe000, length fffff000
+dma_address 347013fd000, length fffff000
+dma_address 348013fc000, length 4000
+
+Since ib_umem_find_best_pgsz works within SG entries, in the above case
+we will result with the worst possible 4KB page size.
+
+Fix this by taking into consideration only the alignment of addresses of
+real discontinuity points rather than treating SG entries as such, and
+adjust the page iterator to correctly handle cross SG entry pages.
+
+There is currently an assumption that drivers do not ask for pages
+bigger than maximal DMA size supported by their devices.
+
+Reviewed-by: Firas Jahjah <firasj@amazon.com>
+Reviewed-by: Yonatan Nachum <ynachum@amazon.com>
+Signed-off-by: Michael Margolin <mrgolin@amazon.com>
+Link: https://patch.msgid.link/20250217141623.12428-1-mrgolin@amazon.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/core/umem.c | 36 ++++++++++++++++++++++++---------
+ drivers/infiniband/core/verbs.c | 11 +++++-----
+ 2 files changed, 32 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
+index 07c571c7b6999..c5b6863947605 100644
+--- a/drivers/infiniband/core/umem.c
++++ b/drivers/infiniband/core/umem.c
+@@ -80,9 +80,12 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,
+ unsigned long pgsz_bitmap,
+ unsigned long virt)
+ {
+- struct scatterlist *sg;
++ unsigned long curr_len = 0;
++ dma_addr_t curr_base = ~0;
+ unsigned long va, pgoff;
++ struct scatterlist *sg;
+ dma_addr_t mask;
++ dma_addr_t end;
+ int i;
+
+ umem->iova = va = virt;
+@@ -107,17 +110,30 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,
+ pgoff = umem->address & ~PAGE_MASK;
+
+ for_each_sgtable_dma_sg(&umem->sgt_append.sgt, sg, i) {
+- /* Walk SGL and reduce max page size if VA/PA bits differ
+- * for any address.
++ /* If the current entry is physically contiguous with the previous
++ * one, no need to take its start addresses into consideration.
+ */
+- mask |= (sg_dma_address(sg) + pgoff) ^ va;
++ if (check_add_overflow(curr_base, curr_len, &end) ||
++ end != sg_dma_address(sg)) {
++
++ curr_base = sg_dma_address(sg);
++ curr_len = 0;
++
++ /* Reduce max page size if VA/PA bits differ */
++ mask |= (curr_base + pgoff) ^ va;
++
++ /* The alignment of any VA matching a discontinuity point
++ * in the physical memory sets the maximum possible page
++ * size as this must be a starting point of a new page that
++ * needs to be aligned.
++ */
++ if (i != 0)
++ mask |= va;
++ }
++
++ curr_len += sg_dma_len(sg);
+ va += sg_dma_len(sg) - pgoff;
+- /* Except for the last entry, the ending iova alignment sets
+- * the maximum possible page size as the low bits of the iova
+- * must be zero when starting the next chunk.
+- */
+- if (i != (umem->sgt_append.sgt.nents - 1))
+- mask |= va;
++
+ pgoff = 0;
+ }
+
+diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
+index 473ee0831307c..dc40001072a5e 100644
+--- a/drivers/infiniband/core/verbs.c
++++ b/drivers/infiniband/core/verbs.c
+@@ -3109,22 +3109,23 @@ EXPORT_SYMBOL(__rdma_block_iter_start);
+ bool __rdma_block_iter_next(struct ib_block_iter *biter)
+ {
+ unsigned int block_offset;
+- unsigned int sg_delta;
++ unsigned int delta;
+
+ if (!biter->__sg_nents || !biter->__sg)
+ return false;
+
+ biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance;
+ block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1);
+- sg_delta = BIT_ULL(biter->__pg_bit) - block_offset;
++ delta = BIT_ULL(biter->__pg_bit) - block_offset;
+
+- if (sg_dma_len(biter->__sg) - biter->__sg_advance > sg_delta) {
+- biter->__sg_advance += sg_delta;
+- } else {
++ while (biter->__sg_nents && biter->__sg &&
++ sg_dma_len(biter->__sg) - biter->__sg_advance <= delta) {
++ delta -= sg_dma_len(biter->__sg) - biter->__sg_advance;
+ biter->__sg_advance = 0;
+ biter->__sg = sg_next(biter->__sg);
+ biter->__sg_nents--;
+ }
++ biter->__sg_advance += delta;
+
+ return true;
+ }
+--
+2.39.5
+
--- /dev/null
+From 98910dac3d7637cba7c3c001616363ad06ea2713 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Feb 2025 15:54:13 +0200
+Subject: RDMA/uverbs: Propagate errors from rdma_lookup_get_uobject()
+
+From: Maher Sanalla <msanalla@nvidia.com>
+
+[ Upstream commit 81f8f7454ad9e0bf95efdec6542afdc9a6ab1e24 ]
+
+Currently, the IB uverbs API calls uobj_get_uobj_read(), which in turn
+uses the rdma_lookup_get_uobject() helper to retrieve user objects.
+In case of failure, uobj_get_uobj_read() returns NULL, overriding the
+error code from rdma_lookup_get_uobject(). The IB uverbs API then
+translates this NULL to -EINVAL, masking the actual error and
+complicating debugging. For example, applications calling ibv_modify_qp
+that fails with EBUSY when retrieving the QP uobject will see the
+overridden error code EINVAL instead, masking the actual error.
+
+Furthermore, based on rdma-core commit:
+"2a22f1ced5f3 ("Merge pull request #1568 from jakemoroni/master")"
+Kernel's IB uverbs return values are either ignored and passed on as is
+to application or overridden with other errnos in a few cases.
+
+Thus, to improve error reporting and debuggability, propagate the
+original error from rdma_lookup_get_uobject() instead of replacing it
+with EINVAL.
+
+Signed-off-by: Maher Sanalla <msanalla@nvidia.com>
+Link: https://patch.msgid.link/64f9d3711b183984e939962c2f83383904f97dfb.1740577869.git.leon@kernel.org
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/core/uverbs_cmd.c | 144 ++++++++++++++-------------
+ include/rdma/uverbs_std_types.h | 2 +-
+ 2 files changed, 77 insertions(+), 69 deletions(-)
+
+diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
+index edef79daed3fa..535bb99ed9f5f 100644
+--- a/drivers/infiniband/core/uverbs_cmd.c
++++ b/drivers/infiniband/core/uverbs_cmd.c
+@@ -718,8 +718,8 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs)
+ goto err_free;
+
+ pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs);
+- if (!pd) {
+- ret = -EINVAL;
++ if (IS_ERR(pd)) {
++ ret = PTR_ERR(pd);
+ goto err_free;
+ }
+
+@@ -809,8 +809,8 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs)
+ if (cmd.flags & IB_MR_REREG_PD) {
+ new_pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle,
+ attrs);
+- if (!new_pd) {
+- ret = -EINVAL;
++ if (IS_ERR(new_pd)) {
++ ret = PTR_ERR(new_pd);
+ goto put_uobjs;
+ }
+ } else {
+@@ -919,8 +919,8 @@ static int ib_uverbs_alloc_mw(struct uverbs_attr_bundle *attrs)
+ return PTR_ERR(uobj);
+
+ pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs);
+- if (!pd) {
+- ret = -EINVAL;
++ if (IS_ERR(pd)) {
++ ret = PTR_ERR(pd);
+ goto err_free;
+ }
+
+@@ -1127,8 +1127,8 @@ static int ib_uverbs_resize_cq(struct uverbs_attr_bundle *attrs)
+ return ret;
+
+ cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
+- if (!cq)
+- return -EINVAL;
++ if (IS_ERR(cq))
++ return PTR_ERR(cq);
+
+ ret = cq->device->ops.resize_cq(cq, cmd.cqe, &attrs->driver_udata);
+ if (ret)
+@@ -1189,8 +1189,8 @@ static int ib_uverbs_poll_cq(struct uverbs_attr_bundle *attrs)
+ return ret;
+
+ cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
+- if (!cq)
+- return -EINVAL;
++ if (IS_ERR(cq))
++ return PTR_ERR(cq);
+
+ /* we copy a struct ib_uverbs_poll_cq_resp to user space */
+ header_ptr = attrs->ucore.outbuf;
+@@ -1238,8 +1238,8 @@ static int ib_uverbs_req_notify_cq(struct uverbs_attr_bundle *attrs)
+ return ret;
+
+ cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
+- if (!cq)
+- return -EINVAL;
++ if (IS_ERR(cq))
++ return PTR_ERR(cq);
+
+ ib_req_notify_cq(cq, cmd.solicited_only ?
+ IB_CQ_SOLICITED : IB_CQ_NEXT_COMP);
+@@ -1321,8 +1321,8 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
+ ind_tbl = uobj_get_obj_read(rwq_ind_table,
+ UVERBS_OBJECT_RWQ_IND_TBL,
+ cmd->rwq_ind_tbl_handle, attrs);
+- if (!ind_tbl) {
+- ret = -EINVAL;
++ if (IS_ERR(ind_tbl)) {
++ ret = PTR_ERR(ind_tbl);
+ goto err_put;
+ }
+
+@@ -1360,8 +1360,10 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
+ if (cmd->is_srq) {
+ srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ,
+ cmd->srq_handle, attrs);
+- if (!srq || srq->srq_type == IB_SRQT_XRC) {
+- ret = -EINVAL;
++ if (IS_ERR(srq) ||
++ srq->srq_type == IB_SRQT_XRC) {
++ ret = IS_ERR(srq) ? PTR_ERR(srq) :
++ -EINVAL;
+ goto err_put;
+ }
+ }
+@@ -1371,23 +1373,29 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
+ rcq = uobj_get_obj_read(
+ cq, UVERBS_OBJECT_CQ,
+ cmd->recv_cq_handle, attrs);
+- if (!rcq) {
+- ret = -EINVAL;
++ if (IS_ERR(rcq)) {
++ ret = PTR_ERR(rcq);
+ goto err_put;
+ }
+ }
+ }
+ }
+
+- if (has_sq)
++ if (has_sq) {
+ scq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ,
+ cmd->send_cq_handle, attrs);
++ if (IS_ERR(scq)) {
++ ret = PTR_ERR(scq);
++ goto err_put;
++ }
++ }
++
+ if (!ind_tbl && cmd->qp_type != IB_QPT_XRC_INI)
+ rcq = rcq ?: scq;
+ pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd->pd_handle,
+ attrs);
+- if (!pd || (!scq && has_sq)) {
+- ret = -EINVAL;
++ if (IS_ERR(pd)) {
++ ret = PTR_ERR(pd);
+ goto err_put;
+ }
+
+@@ -1482,18 +1490,18 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
+ err_put:
+ if (!IS_ERR(xrcd_uobj))
+ uobj_put_read(xrcd_uobj);
+- if (pd)
++ if (!IS_ERR_OR_NULL(pd))
+ uobj_put_obj_read(pd);
+- if (scq)
++ if (!IS_ERR_OR_NULL(scq))
+ rdma_lookup_put_uobject(&scq->uobject->uevent.uobject,
+ UVERBS_LOOKUP_READ);
+- if (rcq && rcq != scq)
++ if (!IS_ERR_OR_NULL(rcq) && rcq != scq)
+ rdma_lookup_put_uobject(&rcq->uobject->uevent.uobject,
+ UVERBS_LOOKUP_READ);
+- if (srq)
++ if (!IS_ERR_OR_NULL(srq))
+ rdma_lookup_put_uobject(&srq->uobject->uevent.uobject,
+ UVERBS_LOOKUP_READ);
+- if (ind_tbl)
++ if (!IS_ERR_OR_NULL(ind_tbl))
+ uobj_put_obj_read(ind_tbl);
+
+ uobj_alloc_abort(&obj->uevent.uobject, attrs);
+@@ -1655,8 +1663,8 @@ static int ib_uverbs_query_qp(struct uverbs_attr_bundle *attrs)
+ }
+
+ qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
+- if (!qp) {
+- ret = -EINVAL;
++ if (IS_ERR(qp)) {
++ ret = PTR_ERR(qp);
+ goto out;
+ }
+
+@@ -1761,8 +1769,8 @@ static int modify_qp(struct uverbs_attr_bundle *attrs,
+
+ qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd->base.qp_handle,
+ attrs);
+- if (!qp) {
+- ret = -EINVAL;
++ if (IS_ERR(qp)) {
++ ret = PTR_ERR(qp);
+ goto out;
+ }
+
+@@ -2028,8 +2036,8 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs)
+ return -ENOMEM;
+
+ qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
+- if (!qp) {
+- ret = -EINVAL;
++ if (IS_ERR(qp)) {
++ ret = PTR_ERR(qp);
+ goto out;
+ }
+
+@@ -2066,9 +2074,9 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs)
+
+ ud->ah = uobj_get_obj_read(ah, UVERBS_OBJECT_AH,
+ user_wr->wr.ud.ah, attrs);
+- if (!ud->ah) {
++ if (IS_ERR(ud->ah)) {
++ ret = PTR_ERR(ud->ah);
+ kfree(ud);
+- ret = -EINVAL;
+ goto out_put;
+ }
+ ud->remote_qpn = user_wr->wr.ud.remote_qpn;
+@@ -2305,8 +2313,8 @@ static int ib_uverbs_post_recv(struct uverbs_attr_bundle *attrs)
+ return PTR_ERR(wr);
+
+ qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
+- if (!qp) {
+- ret = -EINVAL;
++ if (IS_ERR(qp)) {
++ ret = PTR_ERR(qp);
+ goto out;
+ }
+
+@@ -2356,8 +2364,8 @@ static int ib_uverbs_post_srq_recv(struct uverbs_attr_bundle *attrs)
+ return PTR_ERR(wr);
+
+ srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs);
+- if (!srq) {
+- ret = -EINVAL;
++ if (IS_ERR(srq)) {
++ ret = PTR_ERR(srq);
+ goto out;
+ }
+
+@@ -2413,8 +2421,8 @@ static int ib_uverbs_create_ah(struct uverbs_attr_bundle *attrs)
+ }
+
+ pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs);
+- if (!pd) {
+- ret = -EINVAL;
++ if (IS_ERR(pd)) {
++ ret = PTR_ERR(pd);
+ goto err;
+ }
+
+@@ -2483,8 +2491,8 @@ static int ib_uverbs_attach_mcast(struct uverbs_attr_bundle *attrs)
+ return ret;
+
+ qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
+- if (!qp)
+- return -EINVAL;
++ if (IS_ERR(qp))
++ return PTR_ERR(qp);
+
+ obj = qp->uobject;
+
+@@ -2533,8 +2541,8 @@ static int ib_uverbs_detach_mcast(struct uverbs_attr_bundle *attrs)
+ return ret;
+
+ qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
+- if (!qp)
+- return -EINVAL;
++ if (IS_ERR(qp))
++ return PTR_ERR(qp);
+
+ obj = qp->uobject;
+ mutex_lock(&obj->mcast_lock);
+@@ -2668,8 +2676,8 @@ static int kern_spec_to_ib_spec_action(struct uverbs_attr_bundle *attrs,
+ UVERBS_OBJECT_FLOW_ACTION,
+ kern_spec->action.handle,
+ attrs);
+- if (!ib_spec->action.act)
+- return -EINVAL;
++ if (IS_ERR(ib_spec->action.act))
++ return PTR_ERR(ib_spec->action.act);
+ ib_spec->action.size =
+ sizeof(struct ib_flow_spec_action_handle);
+ flow_resources_add(uflow_res,
+@@ -2686,8 +2694,8 @@ static int kern_spec_to_ib_spec_action(struct uverbs_attr_bundle *attrs,
+ UVERBS_OBJECT_COUNTERS,
+ kern_spec->flow_count.handle,
+ attrs);
+- if (!ib_spec->flow_count.counters)
+- return -EINVAL;
++ if (IS_ERR(ib_spec->flow_count.counters))
++ return PTR_ERR(ib_spec->flow_count.counters);
+ ib_spec->flow_count.size =
+ sizeof(struct ib_flow_spec_action_count);
+ flow_resources_add(uflow_res,
+@@ -2905,14 +2913,14 @@ static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs)
+ return PTR_ERR(obj);
+
+ pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs);
+- if (!pd) {
+- err = -EINVAL;
++ if (IS_ERR(pd)) {
++ err = PTR_ERR(pd);
+ goto err_uobj;
+ }
+
+ cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
+- if (!cq) {
+- err = -EINVAL;
++ if (IS_ERR(cq)) {
++ err = PTR_ERR(cq);
+ goto err_put_pd;
+ }
+
+@@ -3013,8 +3021,8 @@ static int ib_uverbs_ex_modify_wq(struct uverbs_attr_bundle *attrs)
+ return -EINVAL;
+
+ wq = uobj_get_obj_read(wq, UVERBS_OBJECT_WQ, cmd.wq_handle, attrs);
+- if (!wq)
+- return -EINVAL;
++ if (IS_ERR(wq))
++ return PTR_ERR(wq);
+
+ if (cmd.attr_mask & IB_WQ_FLAGS) {
+ wq_attr.flags = cmd.flags;
+@@ -3097,8 +3105,8 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs)
+ num_read_wqs++) {
+ wq = uobj_get_obj_read(wq, UVERBS_OBJECT_WQ,
+ wqs_handles[num_read_wqs], attrs);
+- if (!wq) {
+- err = -EINVAL;
++ if (IS_ERR(wq)) {
++ err = PTR_ERR(wq);
+ goto put_wqs;
+ }
+
+@@ -3253,8 +3261,8 @@ static int ib_uverbs_ex_create_flow(struct uverbs_attr_bundle *attrs)
+ }
+
+ qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
+- if (!qp) {
+- err = -EINVAL;
++ if (IS_ERR(qp)) {
++ err = PTR_ERR(qp);
+ goto err_uobj;
+ }
+
+@@ -3400,15 +3408,15 @@ static int __uverbs_create_xsrq(struct uverbs_attr_bundle *attrs,
+ if (ib_srq_has_cq(cmd->srq_type)) {
+ attr.ext.cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ,
+ cmd->cq_handle, attrs);
+- if (!attr.ext.cq) {
+- ret = -EINVAL;
++ if (IS_ERR(attr.ext.cq)) {
++ ret = PTR_ERR(attr.ext.cq);
+ goto err_put_xrcd;
+ }
+ }
+
+ pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd->pd_handle, attrs);
+- if (!pd) {
+- ret = -EINVAL;
++ if (IS_ERR(pd)) {
++ ret = PTR_ERR(pd);
+ goto err_put_cq;
+ }
+
+@@ -3515,8 +3523,8 @@ static int ib_uverbs_modify_srq(struct uverbs_attr_bundle *attrs)
+ return ret;
+
+ srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs);
+- if (!srq)
+- return -EINVAL;
++ if (IS_ERR(srq))
++ return PTR_ERR(srq);
+
+ attr.max_wr = cmd.max_wr;
+ attr.srq_limit = cmd.srq_limit;
+@@ -3543,8 +3551,8 @@ static int ib_uverbs_query_srq(struct uverbs_attr_bundle *attrs)
+ return ret;
+
+ srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs);
+- if (!srq)
+- return -EINVAL;
++ if (IS_ERR(srq))
++ return PTR_ERR(srq);
+
+ ret = ib_query_srq(srq, &attr);
+
+@@ -3669,8 +3677,8 @@ static int ib_uverbs_ex_modify_cq(struct uverbs_attr_bundle *attrs)
+ return -EOPNOTSUPP;
+
+ cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
+- if (!cq)
+- return -EINVAL;
++ if (IS_ERR(cq))
++ return PTR_ERR(cq);
+
+ ret = rdma_set_cq_moderation(cq, cmd.attr.cq_count, cmd.attr.cq_period);
+
+diff --git a/include/rdma/uverbs_std_types.h b/include/rdma/uverbs_std_types.h
+index fe05121169589..555ea3d142a46 100644
+--- a/include/rdma/uverbs_std_types.h
++++ b/include/rdma/uverbs_std_types.h
+@@ -34,7 +34,7 @@
+ static inline void *_uobj_get_obj_read(struct ib_uobject *uobj)
+ {
+ if (IS_ERR(uobj))
+- return NULL;
++ return ERR_CAST(uobj);
+ return uobj->object;
+ }
+ #define uobj_get_obj_read(_object, _type, _id, _attrs) \
+--
+2.39.5
+
--- /dev/null
+From ad33376242fedac840a21f3199e78d870993e949 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jan 2025 17:31:43 +0000
+Subject: regulator: ad5398: Add device tree support
+
+From: Isaac Scott <isaac.scott@ideasonboard.com>
+
+[ Upstream commit 5a6a461079decea452fdcae955bccecf92e07e97 ]
+
+Previously, the ad5398 driver used only platform_data, which is
+deprecated in favour of device tree. This caused the AD5398 to fail to
+probe as it could not load its init_data. If the AD5398 has a device
+tree node, pull the init_data from there using
+of_get_regulator_init_data.
+
+Signed-off-by: Isaac Scott <isaac.scott@ideasonboard.com>
+Acked-by: Michael Hennerich <michael.hennerich@analog.com>
+Link: https://patch.msgid.link/20250128173143.959600-4-isaac.scott@ideasonboard.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/regulator/ad5398.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c
+index 40f7dba42b5ad..404cbe32711e7 100644
+--- a/drivers/regulator/ad5398.c
++++ b/drivers/regulator/ad5398.c
+@@ -14,6 +14,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/regulator/driver.h>
+ #include <linux/regulator/machine.h>
++#include <linux/regulator/of_regulator.h>
+
+ #define AD5398_CURRENT_EN_MASK 0x8000
+
+@@ -221,15 +222,20 @@ static int ad5398_probe(struct i2c_client *client)
+ const struct ad5398_current_data_format *df =
+ (struct ad5398_current_data_format *)id->driver_data;
+
+- if (!init_data)
+- return -EINVAL;
+-
+ chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ config.dev = &client->dev;
++ if (client->dev.of_node)
++ init_data = of_get_regulator_init_data(&client->dev,
++ client->dev.of_node,
++ &ad5398_reg);
++ if (!init_data)
++ return -EINVAL;
++
+ config.init_data = init_data;
++ config.of_node = client->dev.of_node;
+ config.driver_data = chip;
+
+ chip->client = client;
+--
+2.39.5
+
--- /dev/null
+From 35475f3e1e2054f9549f75e0325e1512f5c4c2f0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Feb 2025 20:56:48 +0100
+Subject: remoteproc: qcom_wcnss: Handle platforms with only single power
+ domain
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Matti Lehtimäki <matti.lehtimaki@gmail.com>
+
+[ Upstream commit 65991ea8a6d1e68effdc01d95ebe39f1653f7b71 ]
+
+Both MSM8974 and MSM8226 have only CX as power domain with MX & PX being
+handled as regulators. Handle this case by reodering pd_names to have CX
+first, and handling that the driver core will already attach a single
+power domain internally.
+
+Signed-off-by: Matti Lehtimäki <matti.lehtimaki@gmail.com>
+[luca: minor changes]
+Signed-off-by: Luca Weiss <luca@lucaweiss.eu>
+Link: https://lore.kernel.org/r/20250206-wcnss-singlepd-v2-2-9a53ee953dee@lucaweiss.eu
+[bjorn: Added missing braces to else after multi-statement if]
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/remoteproc/qcom_wcnss.c | 33 ++++++++++++++++++++++++++-------
+ 1 file changed, 26 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
+index a7bb9da27029d..735d373a9f636 100644
+--- a/drivers/remoteproc/qcom_wcnss.c
++++ b/drivers/remoteproc/qcom_wcnss.c
+@@ -117,10 +117,10 @@ static const struct wcnss_data pronto_v1_data = {
+ .pmu_offset = 0x1004,
+ .spare_offset = 0x1088,
+
+- .pd_names = { "mx", "cx" },
++ .pd_names = { "cx", "mx" },
+ .vregs = (struct wcnss_vreg_info[]) {
+- { "vddmx", 950000, 1150000, 0 },
+ { "vddcx", .super_turbo = true},
++ { "vddmx", 950000, 1150000, 0 },
+ { "vddpx", 1800000, 1800000, 0 },
+ },
+ .num_pd_vregs = 2,
+@@ -131,10 +131,10 @@ static const struct wcnss_data pronto_v2_data = {
+ .pmu_offset = 0x1004,
+ .spare_offset = 0x1088,
+
+- .pd_names = { "mx", "cx" },
++ .pd_names = { "cx", "mx" },
+ .vregs = (struct wcnss_vreg_info[]) {
+- { "vddmx", 1287500, 1287500, 0 },
+ { "vddcx", .super_turbo = true },
++ { "vddmx", 1287500, 1287500, 0 },
+ { "vddpx", 1800000, 1800000, 0 },
+ },
+ .num_pd_vregs = 2,
+@@ -397,8 +397,17 @@ static irqreturn_t wcnss_stop_ack_interrupt(int irq, void *dev)
+ static int wcnss_init_pds(struct qcom_wcnss *wcnss,
+ const char * const pd_names[WCNSS_MAX_PDS])
+ {
++ struct device *dev = wcnss->dev;
+ int i, ret;
+
++ /* Handle single power domain */
++ if (dev->pm_domain) {
++ wcnss->pds[0] = dev;
++ wcnss->num_pds = 1;
++ pm_runtime_enable(dev);
++ return 0;
++ }
++
+ for (i = 0; i < WCNSS_MAX_PDS; i++) {
+ if (!pd_names[i])
+ break;
+@@ -418,8 +427,15 @@ static int wcnss_init_pds(struct qcom_wcnss *wcnss,
+
+ static void wcnss_release_pds(struct qcom_wcnss *wcnss)
+ {
++ struct device *dev = wcnss->dev;
+ int i;
+
++ /* Handle single power domain */
++ if (wcnss->num_pds == 1 && dev->pm_domain) {
++ pm_runtime_disable(dev);
++ return;
++ }
++
+ for (i = 0; i < wcnss->num_pds; i++)
+ dev_pm_domain_detach(wcnss->pds[i], false);
+ }
+@@ -437,10 +453,13 @@ static int wcnss_init_regulators(struct qcom_wcnss *wcnss,
+ * the regulators for the power domains. For old device trees we need to
+ * reserve extra space to manage them through the regulator interface.
+ */
+- if (wcnss->num_pds)
+- info += num_pd_vregs;
+- else
++ if (wcnss->num_pds) {
++ info += wcnss->num_pds;
++ /* Handle single power domain case */
++ num_vregs += num_pd_vregs - wcnss->num_pds;
++ } else {
+ num_vregs += num_pd_vregs;
++ }
+
+ bulk = devm_kcalloc(wcnss->dev,
+ num_vregs, sizeof(struct regulator_bulk_data),
+--
+2.39.5
+
--- /dev/null
+From 63197dda759fda30c933234215efa3b7083c1b98 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jan 2025 13:29:51 +0800
+Subject: Revert "drm/amd/display: Exit idle optimizations before attempt to
+ access PHY"
+
+From: Brandon Syu <Brandon.Syu@amd.com>
+
+[ Upstream commit be704e5ef4bd66dee9bb3f876964327e3a247d31 ]
+
+This reverts commit de612738e9771bd66aeb20044486c457c512f684.
+
+Reason to revert: screen flashes or gray screen appeared half of the
+screen after resume from S4/S5.
+
+Reviewed-by: Charlene Liu <charlene.liu@amd.com>
+Signed-off-by: Brandon Syu <Brandon.Syu@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+index 59457ca24e1dc..ccdc9d4101863 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+@@ -1888,7 +1888,6 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
+ bool can_apply_edp_fast_boot = false;
+ bool can_apply_seamless_boot = false;
+ bool keep_edp_vdd_on = false;
+- struct dc_bios *dcb = dc->ctx->dc_bios;
+ DC_LOGGER_INIT();
+
+
+@@ -1965,8 +1964,6 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
+ hws->funcs.edp_backlight_control(edp_link_with_sink, false);
+ }
+ /*resume from S3, no vbios posting, no need to power down again*/
+- if (dcb && dcb->funcs && !dcb->funcs->is_accelerated_mode(dcb))
+- clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr);
+
+ power_down_all_hw_blocks(dc);
+
+@@ -1979,8 +1976,6 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
+ disable_vga_and_power_gate_all_controllers(dc);
+ if (edp_link_with_sink && !keep_edp_vdd_on)
+ dc->hwss.edp_power_control(edp_link_with_sink, false);
+- if (dcb && dcb->funcs && !dcb->funcs->is_accelerated_mode(dcb))
+- clk_mgr_optimize_pwr_state(dc, dc->clk_mgr);
+ }
+ bios_set_scratch_acc_mode_change(dc->ctx->dc_bios, 1);
+ }
+--
+2.39.5
+
--- /dev/null
+From fc95fbbd339c2642e2d89f01b63122815d171c71 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jan 2025 11:46:52 -0500
+Subject: Revert "drm/amd/display: Request HW cursor on DCN3.2 with SubVP"
+
+From: Leo Zeng <Leo.Zeng@amd.com>
+
+[ Upstream commit 8ae6dfc0b61b170cf13832d4cfe2a0c744e621a7 ]
+
+This reverts commit 13437c91606c9232c747475e202fe3827cd53264.
+
+Reason to revert: idle power regression found in testing.
+
+Reviewed-by: Dillon Varone <dillon.varone@amd.com>
+Signed-off-by: Leo Zeng <Leo.Zeng@amd.com>
+Signed-off-by: Roman Li <roman.li@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+index 56dda686e2992..6f490d8d7038c 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+@@ -626,7 +626,6 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc,
+ * - Not TMZ surface
+ */
+ if (pipe->plane_state && !pipe->top_pipe && !pipe->prev_odm_pipe && !dcn32_is_center_timing(pipe) &&
+- !pipe->stream->hw_cursor_req &&
+ !(pipe->stream->timing.pix_clk_100hz / 10000 > DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ) &&
+ (!dcn32_is_psr_capable(pipe) || (context->stream_count == 1 && dc->caps.dmub_caps.subvp_psr)) &&
+ dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_NONE &&
+--
+2.39.5
+
--- /dev/null
+From 00aad305a360310aefb97a5346b709aec43790fb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 26 Oct 2024 10:13:54 -0700
+Subject: riscv: Allow NOMMU kernels to access all of RAM
+
+From: Samuel Holland <samuel.holland@sifive.com>
+
+[ Upstream commit 2c0391b29b27f315c1b4c29ffde66f50b29fab99 ]
+
+NOMMU kernels currently cannot access memory below the kernel link
+address. Remove this restriction by setting PAGE_OFFSET to the actual
+start of RAM, as determined from the devicetree. The kernel link address
+must be a constant, so keep using CONFIG_PAGE_OFFSET for that purpose.
+
+Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
+Reviewed-by: Jesse Taube <mr.bossman075@gmail.com>
+Link: https://lore.kernel.org/r/20241026171441.3047904-3-samuel.holland@sifive.com
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/include/asm/page.h | 12 ++++--------
+ arch/riscv/include/asm/pgtable.h | 2 +-
+ 2 files changed, 5 insertions(+), 9 deletions(-)
+
+diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h
+index febf820d50583..e8beadc2bffda 100644
+--- a/arch/riscv/include/asm/page.h
++++ b/arch/riscv/include/asm/page.h
+@@ -26,12 +26,9 @@
+ * When not using MMU this corresponds to the first free page in
+ * physical memory (aligned on a page boundary).
+ */
+-#ifdef CONFIG_64BIT
+ #ifdef CONFIG_MMU
++#ifdef CONFIG_64BIT
+ #define PAGE_OFFSET kernel_map.page_offset
+-#else
+-#define PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL)
+-#endif
+ /*
+ * By default, CONFIG_PAGE_OFFSET value corresponds to SV57 address space so
+ * define the PAGE_OFFSET value for SV48 and SV39.
+@@ -41,6 +38,9 @@
+ #else
+ #define PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL)
+ #endif /* CONFIG_64BIT */
++#else
++#define PAGE_OFFSET ((unsigned long)phys_ram_base)
++#endif /* CONFIG_MMU */
+
+ #ifndef __ASSEMBLY__
+
+@@ -97,11 +97,7 @@ typedef struct page *pgtable_t;
+ #define MIN_MEMBLOCK_ADDR 0
+ #endif
+
+-#ifdef CONFIG_MMU
+ #define ARCH_PFN_OFFSET (PFN_DOWN((unsigned long)phys_ram_base))
+-#else
+-#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT)
+-#endif /* CONFIG_MMU */
+
+ struct kernel_mapping {
+ unsigned long page_offset;
+diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
+index c0866ada5bbc4..479550cdb440f 100644
+--- a/arch/riscv/include/asm/pgtable.h
++++ b/arch/riscv/include/asm/pgtable.h
+@@ -12,7 +12,7 @@
+ #include <asm/pgtable-bits.h>
+
+ #ifndef CONFIG_MMU
+-#define KERNEL_LINK_ADDR PAGE_OFFSET
++#define KERNEL_LINK_ADDR _AC(CONFIG_PAGE_OFFSET, UL)
+ #define KERN_VIRT_SIZE (UL(-1))
+ #else
+
+--
+2.39.5
+
--- /dev/null
+From fb21ddcf8fce2edf49b918928760bcd9c2388b90 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jan 2025 15:24:24 +0100
+Subject: riscv: Call secondary mmu notifier when flushing the tlb
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alexandre Ghiti <alexghiti@rivosinc.com>
+
+[ Upstream commit d9be2b9b60497a82aeceec3a98d8b37fdd2960f2 ]
+
+This is required to allow the IOMMU driver to correctly flush its own
+TLB.
+
+Reviewed-by: Clément Léger <cleger@rivosinc.com>
+Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
+Link: https://lore.kernel.org/r/20250113142424.30487-1-alexghiti@rivosinc.com
+Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/mm/tlbflush.c | 37 ++++++++++++++++++++++---------------
+ 1 file changed, 22 insertions(+), 15 deletions(-)
+
+diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c
+index 9b6e86ce38674..bb77607c87aa2 100644
+--- a/arch/riscv/mm/tlbflush.c
++++ b/arch/riscv/mm/tlbflush.c
+@@ -4,6 +4,7 @@
+ #include <linux/smp.h>
+ #include <linux/sched.h>
+ #include <linux/hugetlb.h>
++#include <linux/mmu_notifier.h>
+ #include <asm/sbi.h>
+ #include <asm/mmu_context.h>
+
+@@ -78,10 +79,17 @@ static void __ipi_flush_tlb_range_asid(void *info)
+ local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid);
+ }
+
+-static void __flush_tlb_range(const struct cpumask *cmask, unsigned long asid,
++static inline unsigned long get_mm_asid(struct mm_struct *mm)
++{
++ return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID;
++}
++
++static void __flush_tlb_range(struct mm_struct *mm,
++ const struct cpumask *cmask,
+ unsigned long start, unsigned long size,
+ unsigned long stride)
+ {
++ unsigned long asid = get_mm_asid(mm);
+ unsigned int cpu;
+
+ if (cpumask_empty(cmask))
+@@ -105,30 +113,26 @@ static void __flush_tlb_range(const struct cpumask *cmask, unsigned long asid,
+ }
+
+ put_cpu();
+-}
+
+-static inline unsigned long get_mm_asid(struct mm_struct *mm)
+-{
+- return cntx2asid(atomic_long_read(&mm->context.id));
++ if (mm)
++ mmu_notifier_arch_invalidate_secondary_tlbs(mm, start, start + size);
+ }
+
+ void flush_tlb_mm(struct mm_struct *mm)
+ {
+- __flush_tlb_range(mm_cpumask(mm), get_mm_asid(mm),
+- 0, FLUSH_TLB_MAX_SIZE, PAGE_SIZE);
++ __flush_tlb_range(mm, mm_cpumask(mm), 0, FLUSH_TLB_MAX_SIZE, PAGE_SIZE);
+ }
+
+ void flush_tlb_mm_range(struct mm_struct *mm,
+ unsigned long start, unsigned long end,
+ unsigned int page_size)
+ {
+- __flush_tlb_range(mm_cpumask(mm), get_mm_asid(mm),
+- start, end - start, page_size);
++ __flush_tlb_range(mm, mm_cpumask(mm), start, end - start, page_size);
+ }
+
+ void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
+ {
+- __flush_tlb_range(mm_cpumask(vma->vm_mm), get_mm_asid(vma->vm_mm),
++ __flush_tlb_range(vma->vm_mm, mm_cpumask(vma->vm_mm),
+ addr, PAGE_SIZE, PAGE_SIZE);
+ }
+
+@@ -161,13 +165,13 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ }
+ }
+
+- __flush_tlb_range(mm_cpumask(vma->vm_mm), get_mm_asid(vma->vm_mm),
++ __flush_tlb_range(vma->vm_mm, mm_cpumask(vma->vm_mm),
+ start, end - start, stride_size);
+ }
+
+ void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+ {
+- __flush_tlb_range(cpu_online_mask, FLUSH_TLB_NO_ASID,
++ __flush_tlb_range(NULL, cpu_online_mask,
+ start, end - start, PAGE_SIZE);
+ }
+
+@@ -175,7 +179,7 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+ void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+ {
+- __flush_tlb_range(mm_cpumask(vma->vm_mm), get_mm_asid(vma->vm_mm),
++ __flush_tlb_range(vma->vm_mm, mm_cpumask(vma->vm_mm),
+ start, end - start, PMD_SIZE);
+ }
+ #endif
+@@ -189,7 +193,10 @@ void arch_tlbbatch_add_pending(struct arch_tlbflush_unmap_batch *batch,
+ struct mm_struct *mm,
+ unsigned long uaddr)
+ {
++ unsigned long start = uaddr & PAGE_MASK;
++
+ cpumask_or(&batch->cpumask, &batch->cpumask, mm_cpumask(mm));
++ mmu_notifier_arch_invalidate_secondary_tlbs(mm, start, start + PAGE_SIZE);
+ }
+
+ void arch_flush_tlb_batched_pending(struct mm_struct *mm)
+@@ -199,7 +206,7 @@ void arch_flush_tlb_batched_pending(struct mm_struct *mm)
+
+ void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
+ {
+- __flush_tlb_range(&batch->cpumask, FLUSH_TLB_NO_ASID, 0,
+- FLUSH_TLB_MAX_SIZE, PAGE_SIZE);
++ __flush_tlb_range(NULL, &batch->cpumask,
++ 0, FLUSH_TLB_MAX_SIZE, PAGE_SIZE);
+ cpumask_clear(&batch->cpumask);
+ }
+--
+2.39.5
+
--- /dev/null
+From a65354c0edcdd519e212f4b5047616c7aae2791d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Mar 2025 23:37:44 +0100
+Subject: rtc: ds1307: stop disabling alarms on probe
+
+From: Alexandre Belloni <alexandre.belloni@bootlin.com>
+
+[ Upstream commit dcec12617ee61beed928e889607bf37e145bf86b ]
+
+It is a bad practice to disable alarms on probe or remove as this will
+prevent alarms across reboots.
+
+Link: https://lore.kernel.org/r/20250303223744.1135672-1-alexandre.belloni@bootlin.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/rtc/rtc-ds1307.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
+index 872e0b679be48..5efbe69bf5ca8 100644
+--- a/drivers/rtc/rtc-ds1307.c
++++ b/drivers/rtc/rtc-ds1307.c
+@@ -1807,10 +1807,8 @@ static int ds1307_probe(struct i2c_client *client)
+ * For some variants, be sure alarms can trigger when we're
+ * running on Vbackup (BBSQI/BBSQW)
+ */
+- if (want_irq || ds1307_can_wakeup_device) {
++ if (want_irq || ds1307_can_wakeup_device)
+ regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit;
+- regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE);
+- }
+
+ regmap_write(ds1307->regmap, DS1337_REG_CONTROL,
+ regs[0]);
+--
+2.39.5
+
--- /dev/null
+From bdec44a3625517fe7175f382dd3c013d58e92118 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Mar 2025 22:42:41 +0100
+Subject: rtc: rv3032: fix EERD location
+
+From: Alexandre Belloni <alexandre.belloni@bootlin.com>
+
+[ Upstream commit b0f9cb4a0706b0356e84d67e48500b77b343debe ]
+
+EERD is bit 2 in CTRL1
+
+Link: https://lore.kernel.org/r/20250306214243.1167692-1-alexandre.belloni@bootlin.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/rtc/rtc-rv3032.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/rtc/rtc-rv3032.c b/drivers/rtc/rtc-rv3032.c
+index 35b2e36b426a0..cb01038a2e27f 100644
+--- a/drivers/rtc/rtc-rv3032.c
++++ b/drivers/rtc/rtc-rv3032.c
+@@ -69,7 +69,7 @@
+ #define RV3032_CLKOUT2_FD_MSK GENMASK(6, 5)
+ #define RV3032_CLKOUT2_OS BIT(7)
+
+-#define RV3032_CTRL1_EERD BIT(3)
++#define RV3032_CTRL1_EERD BIT(2)
+ #define RV3032_CTRL1_WADA BIT(5)
+
+ #define RV3032_CTRL2_STOP BIT(0)
+--
+2.39.5
+
--- /dev/null
+From d9110c8dd7fea7d5ccbd5669a82ca2ffed90d2ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Mar 2025 12:42:59 +0100
+Subject: s390/tlb: Use mm_has_pgste() instead of mm_alloc_pgste()
+
+From: Heiko Carstens <hca@linux.ibm.com>
+
+[ Upstream commit 9291ea091b29bb3e37c4b3416c7c1e49e472c7d5 ]
+
+An mm has pgstes only after s390_enable_sie() has been called, while
+mm_alloc_pgste() may be always true (e.g. via sysctl setting).
+
+Limit the calls to gmap_unlink() in pte_free_tlb() to those cases
+where there might be something to unlink.
+
+Reviewed-by: Alexander Gordeev <agordeev@linux.ibm.com>
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/include/asm/tlb.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h
+index e95b2c8081eb8..793afe236df07 100644
+--- a/arch/s390/include/asm/tlb.h
++++ b/arch/s390/include/asm/tlb.h
+@@ -85,7 +85,7 @@ static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
+ tlb->mm->context.flush_mm = 1;
+ tlb->freed_tables = 1;
+ tlb->cleared_pmds = 1;
+- if (mm_alloc_pgste(tlb->mm))
++ if (mm_has_pgste(tlb->mm))
+ gmap_unlink(tlb->mm, (unsigned long *)pte, address);
+ tlb_remove_ptdesc(tlb, pte);
+ }
+--
+2.39.5
+
--- /dev/null
+From f84ec31ee430bfdc1b1b922f26c52b3f252f98ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Mar 2025 06:32:57 -0400
+Subject: s390/vfio-ap: Fix no AP queue sharing allowed message written to
+ kernel log
+
+From: Anthony Krowiak <akrowiak@linux.ibm.com>
+
+[ Upstream commit d33d729afcc8ad2148d99f9bc499b33fd0c0d73b ]
+
+An erroneous message is written to the kernel log when either of the
+following actions are taken by a user:
+
+1. Assign an adapter or domain to a vfio_ap mediated device via its sysfs
+ assign_adapter or assign_domain attributes that would result in one or
+ more AP queues being assigned that are already assigned to a different
+ mediated device. Sharing of queues between mdevs is not allowed.
+
+2. Reserve an adapter or domain for the host device driver via the AP bus
+ driver's sysfs apmask or aqmask attribute that would result in providing
+ host access to an AP queue that is in use by a vfio_ap mediated device.
+ Reserving a queue for a host driver that is in use by an mdev is not
+ allowed.
+
+In both cases, the assignment will return an error; however, a message like
+the following is written to the kernel log:
+
+vfio_ap_mdev e1839397-51a0-4e3c-91e0-c3b9c3d3047d: Userspace may not
+re-assign queue 00.0028 already assigned to \
+e1839397-51a0-4e3c-91e0-c3b9c3d3047d
+
+Notice the mdev reporting the error is the same as the mdev identified
+in the message as the one to which the queue is being assigned.
+It is perfectly okay to assign a queue to an mdev to which it is
+already assigned; the assignment is simply ignored by the vfio_ap device
+driver.
+
+This patch logs more descriptive and accurate messages for both 1 and 2
+above to the kernel log:
+
+Example for 1:
+vfio_ap_mdev 0fe903a0-a323-44db-9daf-134c68627d61: Userspace may not assign
+queue 00.0033 to mdev: already assigned to \
+62177883-f1bb-47f0-914d-32a22e3a8804
+
+Example for 2:
+vfio_ap_mdev 62177883-f1bb-47f0-914d-32a22e3a8804: Can not reserve queue
+00.0033 for host driver: in use by mdev
+
+Signed-off-by: Anthony Krowiak <akrowiak@linux.ibm.com>
+Link: https://lore.kernel.org/r/20250311103304.1539188-1-akrowiak@linux.ibm.com
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/s390/crypto/vfio_ap_ops.c | 72 ++++++++++++++++++++-----------
+ 1 file changed, 46 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
+index 9f76f2d7b66e5..3bac163057d89 100644
+--- a/drivers/s390/crypto/vfio_ap_ops.c
++++ b/drivers/s390/crypto/vfio_ap_ops.c
+@@ -851,48 +851,66 @@ static void vfio_ap_mdev_remove(struct mdev_device *mdev)
+ vfio_put_device(&matrix_mdev->vdev);
+ }
+
+-#define MDEV_SHARING_ERR "Userspace may not re-assign queue %02lx.%04lx " \
+- "already assigned to %s"
++#define MDEV_SHARING_ERR "Userspace may not assign queue %02lx.%04lx to mdev: already assigned to %s"
+
+-static void vfio_ap_mdev_log_sharing_err(struct ap_matrix_mdev *matrix_mdev,
+- unsigned long *apm,
+- unsigned long *aqm)
++#define MDEV_IN_USE_ERR "Can not reserve queue %02lx.%04lx for host driver: in use by mdev"
++
++static void vfio_ap_mdev_log_sharing_err(struct ap_matrix_mdev *assignee,
++ struct ap_matrix_mdev *assigned_to,
++ unsigned long *apm, unsigned long *aqm)
+ {
+ unsigned long apid, apqi;
+- const struct device *dev = mdev_dev(matrix_mdev->mdev);
+- const char *mdev_name = dev_name(dev);
+
+- for_each_set_bit_inv(apid, apm, AP_DEVICES)
++ for_each_set_bit_inv(apid, apm, AP_DEVICES) {
++ for_each_set_bit_inv(apqi, aqm, AP_DOMAINS) {
++ dev_warn(mdev_dev(assignee->mdev), MDEV_SHARING_ERR,
++ apid, apqi, dev_name(mdev_dev(assigned_to->mdev)));
++ }
++ }
++}
++
++static void vfio_ap_mdev_log_in_use_err(struct ap_matrix_mdev *assignee,
++ unsigned long *apm, unsigned long *aqm)
++{
++ unsigned long apid, apqi;
++
++ for_each_set_bit_inv(apid, apm, AP_DEVICES) {
+ for_each_set_bit_inv(apqi, aqm, AP_DOMAINS)
+- dev_warn(dev, MDEV_SHARING_ERR, apid, apqi, mdev_name);
++ dev_warn(mdev_dev(assignee->mdev), MDEV_IN_USE_ERR, apid, apqi);
++ }
+ }
+
+ /**
+ * vfio_ap_mdev_verify_no_sharing - verify APQNs are not shared by matrix mdevs
+ *
++ * @assignee: the matrix mdev to which @mdev_apm and @mdev_aqm are being
++ * assigned; or, NULL if this function was called by the AP bus
++ * driver in_use callback to verify none of the APQNs being reserved
++ * for the host device driver are in use by a vfio_ap mediated device
+ * @mdev_apm: mask indicating the APIDs of the APQNs to be verified
+ * @mdev_aqm: mask indicating the APQIs of the APQNs to be verified
+ *
+- * Verifies that each APQN derived from the Cartesian product of a bitmap of
+- * AP adapter IDs and AP queue indexes is not configured for any matrix
+- * mediated device. AP queue sharing is not allowed.
++ * Verifies that each APQN derived from the Cartesian product of APIDs
++ * represented by the bits set in @mdev_apm and the APQIs of the bits set in
++ * @mdev_aqm is not assigned to a mediated device other than the mdev to which
++ * the APQN is being assigned (@assignee). AP queue sharing is not allowed.
+ *
+ * Return: 0 if the APQNs are not shared; otherwise return -EADDRINUSE.
+ */
+-static int vfio_ap_mdev_verify_no_sharing(unsigned long *mdev_apm,
++static int vfio_ap_mdev_verify_no_sharing(struct ap_matrix_mdev *assignee,
++ unsigned long *mdev_apm,
+ unsigned long *mdev_aqm)
+ {
+- struct ap_matrix_mdev *matrix_mdev;
++ struct ap_matrix_mdev *assigned_to;
+ DECLARE_BITMAP(apm, AP_DEVICES);
+ DECLARE_BITMAP(aqm, AP_DOMAINS);
+
+- list_for_each_entry(matrix_mdev, &matrix_dev->mdev_list, node) {
++ list_for_each_entry(assigned_to, &matrix_dev->mdev_list, node) {
+ /*
+- * If the input apm and aqm are fields of the matrix_mdev
+- * object, then move on to the next matrix_mdev.
++ * If the mdev to which the mdev_apm and mdev_aqm is being
++ * assigned is the same as the mdev being verified
+ */
+- if (mdev_apm == matrix_mdev->matrix.apm &&
+- mdev_aqm == matrix_mdev->matrix.aqm)
++ if (assignee == assigned_to)
+ continue;
+
+ memset(apm, 0, sizeof(apm));
+@@ -902,15 +920,16 @@ static int vfio_ap_mdev_verify_no_sharing(unsigned long *mdev_apm,
+ * We work on full longs, as we can only exclude the leftover
+ * bits in non-inverse order. The leftover is all zeros.
+ */
+- if (!bitmap_and(apm, mdev_apm, matrix_mdev->matrix.apm,
+- AP_DEVICES))
++ if (!bitmap_and(apm, mdev_apm, assigned_to->matrix.apm, AP_DEVICES))
+ continue;
+
+- if (!bitmap_and(aqm, mdev_aqm, matrix_mdev->matrix.aqm,
+- AP_DOMAINS))
++ if (!bitmap_and(aqm, mdev_aqm, assigned_to->matrix.aqm, AP_DOMAINS))
+ continue;
+
+- vfio_ap_mdev_log_sharing_err(matrix_mdev, apm, aqm);
++ if (assignee)
++ vfio_ap_mdev_log_sharing_err(assignee, assigned_to, apm, aqm);
++ else
++ vfio_ap_mdev_log_in_use_err(assigned_to, apm, aqm);
+
+ return -EADDRINUSE;
+ }
+@@ -939,7 +958,8 @@ static int vfio_ap_mdev_validate_masks(struct ap_matrix_mdev *matrix_mdev)
+ matrix_mdev->matrix.aqm))
+ return -EADDRNOTAVAIL;
+
+- return vfio_ap_mdev_verify_no_sharing(matrix_mdev->matrix.apm,
++ return vfio_ap_mdev_verify_no_sharing(matrix_mdev,
++ matrix_mdev->matrix.apm,
+ matrix_mdev->matrix.aqm);
+ }
+
+@@ -2467,7 +2487,7 @@ int vfio_ap_mdev_resource_in_use(unsigned long *apm, unsigned long *aqm)
+
+ mutex_lock(&matrix_dev->guests_lock);
+ mutex_lock(&matrix_dev->mdevs_lock);
+- ret = vfio_ap_mdev_verify_no_sharing(apm, aqm);
++ ret = vfio_ap_mdev_verify_no_sharing(NULL, apm, aqm);
+ mutex_unlock(&matrix_dev->mdevs_lock);
+ mutex_unlock(&matrix_dev->guests_lock);
+
+--
+2.39.5
+
--- /dev/null
+From 3a50b5dcfdaa2bb97cd46645738da5d4ff17f3e8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Apr 2025 17:50:42 +0800
+Subject: samples/bpf: Fix compilation failure for samples/bpf on LoongArch
+ Fedora
+
+From: Haoran Jiang <jianghaoran@kylinos.cn>
+
+[ Upstream commit 548762f05d19c5542db7590bcdfb9be1fb928376 ]
+
+When building the latest samples/bpf on LoongArch Fedora
+
+ make M=samples/bpf
+
+There are compilation errors as follows:
+
+In file included from ./linux/samples/bpf/sockex2_kern.c:2:
+In file included from ./include/uapi/linux/in.h:25:
+In file included from ./include/linux/socket.h:8:
+In file included from ./include/linux/uio.h:9:
+In file included from ./include/linux/thread_info.h:60:
+In file included from ./arch/loongarch/include/asm/thread_info.h:15:
+In file included from ./arch/loongarch/include/asm/processor.h:13:
+In file included from ./arch/loongarch/include/asm/cpu-info.h:11:
+./arch/loongarch/include/asm/loongarch.h:13:10: fatal error: 'larchintrin.h' file not found
+ ^~~~~~~~~~~~~~~
+1 error generated.
+
+larchintrin.h is included in /usr/lib64/clang/14.0.6/include,
+and the header file location is specified at compile time.
+
+Test on LoongArch Fedora:
+https://github.com/fedora-remix-loongarch/releases-info
+
+Signed-off-by: Haoran Jiang <jianghaoran@kylinos.cn>
+Signed-off-by: zhangxi <zhangxi@kylinos.cn>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Link: https://lore.kernel.org/bpf/20250425095042.838824-1-jianghaoran@kylinos.cn
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ samples/bpf/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
+index 7afe040cf43b3..f06f88b26183c 100644
+--- a/samples/bpf/Makefile
++++ b/samples/bpf/Makefile
+@@ -400,7 +400,7 @@ $(obj)/%.o: $(src)/%.c
+ @echo " CLANG-bpf " $@
+ $(Q)$(CLANG) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(BPF_EXTRA_CFLAGS) \
+ -I$(obj) -I$(srctree)/tools/testing/selftests/bpf/ \
+- -I$(LIBBPF_INCLUDE) \
++ -I$(LIBBPF_INCLUDE) $(CLANG_SYS_INCLUDES) \
+ -D__KERNEL__ -D__BPF_TRACING__ -Wno-unused-value -Wno-pointer-sign \
+ -D__TARGET_ARCH_$(SRCARCH) -Wno-compare-distinct-pointer-types \
+ -Wno-gnu-variable-sized-type-not-at-end \
+--
+2.39.5
+
--- /dev/null
+From c6c8e11a91749b5edb18e82a61ccf9e715fc0fff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Feb 2025 15:53:23 +0800
+Subject: sched: Reduce the default slice to avoid tasks getting an extra tick
+
+From: zihan zhou <15645113830zzh@gmail.com>
+
+[ Upstream commit 2ae891b826958b60919ea21c727f77bcd6ffcc2c ]
+
+The old default value for slice is 0.75 msec * (1 + ilog(ncpus)) which
+means that we have a default slice of:
+
+ 0.75 for 1 cpu
+ 1.50 up to 3 cpus
+ 2.25 up to 7 cpus
+ 3.00 for 8 cpus and above.
+
+For HZ=250 and HZ=100, because of the tick accuracy, the runtime of
+tasks is far higher than their slice.
+
+For HZ=1000 with 8 cpus or more, the accuracy of tick is already
+satisfactory, but there is still an issue that tasks will get an extra
+tick because the tick often arrives a little faster than expected. In
+this case, the task can only wait until the next tick to consider that it
+has reached its deadline, and will run 1ms longer.
+
+vruntime + sysctl_sched_base_slice = deadline
+ |-----------|-----------|-----------|-----------|
+ 1ms 1ms 1ms 1ms
+ ^ ^ ^ ^
+ tick1 tick2 tick3 tick4(nearly 4ms)
+
+There are two reasons for tick error: clockevent precision and the
+CONFIG_IRQ_TIME_ACCOUNTING/CONFIG_PARAVIRT_TIME_ACCOUNTING. with
+CONFIG_IRQ_TIME_ACCOUNTING every tick will be less than 1ms, but even
+without it, because of clockevent precision, tick still often less than
+1ms.
+
+In order to make scheduling more precise, we changed 0.75 to 0.70,
+Using 0.70 instead of 0.75 should not change much for other configs
+and would fix this issue:
+
+ 0.70 for 1 cpu
+ 1.40 up to 3 cpus
+ 2.10 up to 7 cpus
+ 2.8 for 8 cpus and above.
+
+This does not guarantee that tasks can run the slice time accurately
+every time, but occasionally running an extra tick has little impact.
+
+Signed-off-by: zihan zhou <15645113830zzh@gmail.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Vincent Guittot <vincent.guittot@linaro.org>
+Link: https://lkml.kernel.org/r/20250208075322.13139-1-15645113830zzh@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sched/fair.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index 990d0828bf2a9..443f6a9ef3f8f 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -71,10 +71,10 @@ unsigned int sysctl_sched_tunable_scaling = SCHED_TUNABLESCALING_LOG;
+ /*
+ * Minimal preemption granularity for CPU-bound tasks:
+ *
+- * (default: 0.75 msec * (1 + ilog(ncpus)), units: nanoseconds)
++ * (default: 0.70 msec * (1 + ilog(ncpus)), units: nanoseconds)
+ */
+-unsigned int sysctl_sched_base_slice = 750000ULL;
+-static unsigned int normalized_sysctl_sched_base_slice = 750000ULL;
++unsigned int sysctl_sched_base_slice = 700000ULL;
++static unsigned int normalized_sysctl_sched_base_slice = 700000ULL;
+
+ const_debug unsigned int sysctl_sched_migration_cost = 500000UL;
+
+--
+2.39.5
+
--- /dev/null
+From 2510a5a2ce613b9850a2f347d5c1476194e9c6be Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 10:58:19 +0100
+Subject: scsi: logging: Fix scsi_logging_level bounds
+
+From: Nicolas Bouchinet <nicolas.bouchinet@ssi.gouv.fr>
+
+[ Upstream commit 2cef5b4472c602e6c5a119aca869d9d4050586f3 ]
+
+Bound scsi_logging_level sysctl writings between SYSCTL_ZERO and
+SYSCTL_INT_MAX.
+
+The proc_handler has thus been updated to proc_dointvec_minmax.
+
+Signed-off-by: Nicolas Bouchinet <nicolas.bouchinet@ssi.gouv.fr>
+Link: https://lore.kernel.org/r/20250224095826.16458-5-nicolas.bouchinet@clip-os.org
+Reviewed-by: Joel Granados <joel.granados@kernel.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_sysctl.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/scsi_sysctl.c b/drivers/scsi/scsi_sysctl.c
+index 093774d775346..daa160459c9b3 100644
+--- a/drivers/scsi/scsi_sysctl.c
++++ b/drivers/scsi/scsi_sysctl.c
+@@ -17,7 +17,9 @@ static struct ctl_table scsi_table[] = {
+ .data = &scsi_logging_level,
+ .maxlen = sizeof(scsi_logging_level),
+ .mode = 0644,
+- .proc_handler = proc_dointvec },
++ .proc_handler = proc_dointvec_minmax,
++ .extra1 = SYSCTL_ZERO,
++ .extra2 = SYSCTL_INT_MAX },
+ };
+
+ static struct ctl_table_header *scsi_table_header;
+--
+2.39.5
+
--- /dev/null
+From 8db278501e479338ed214b7c1c2ae7a4e9b1c1ab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jan 2025 16:05:20 -0800
+Subject: scsi: lpfc: Free phba irq in lpfc_sli4_enable_msi() when
+ pci_irq_vector() fails
+
+From: Justin Tee <justin.tee@broadcom.com>
+
+[ Upstream commit f0842902b383982d1f72c490996aa8fc29a7aa0d ]
+
+Fix smatch warning regarding missed calls to free_irq(). Free the phba IRQ
+in the failed pci_irq_vector cases.
+
+lpfc_init.c: lpfc_sli4_enable_msi() warn: 'phba->pcidev->irq' from
+ request_irq() not released.
+
+Signed-off-by: Justin Tee <justin.tee@broadcom.com>
+Link: https://lore.kernel.org/r/20250131000524.163662-3-justintee8345@gmail.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/lpfc/lpfc_init.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
+index a3658ef1141b2..50c761991191f 100644
+--- a/drivers/scsi/lpfc/lpfc_init.c
++++ b/drivers/scsi/lpfc/lpfc_init.c
+@@ -13190,6 +13190,7 @@ lpfc_sli4_enable_msi(struct lpfc_hba *phba)
+ eqhdl = lpfc_get_eq_hdl(0);
+ rc = pci_irq_vector(phba->pcidev, 0);
+ if (rc < 0) {
++ free_irq(phba->pcidev->irq, phba);
+ pci_free_irq_vectors(phba->pcidev);
+ lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
+ "0496 MSI pci_irq_vec failed (%d)\n", rc);
+@@ -13270,6 +13271,7 @@ lpfc_sli4_enable_intr(struct lpfc_hba *phba, uint32_t cfg_mode)
+ eqhdl = lpfc_get_eq_hdl(0);
+ retval = pci_irq_vector(phba->pcidev, 0);
+ if (retval < 0) {
++ free_irq(phba->pcidev->irq, phba);
+ lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
+ "0502 INTR pci_irq_vec failed (%d)\n",
+ retval);
+--
+2.39.5
+
--- /dev/null
+From 16c14b77e82d6adabc90e640de870875cb2f1963 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jan 2025 16:05:22 -0800
+Subject: scsi: lpfc: Handle duplicate D_IDs in ndlp search-by D_ID routine
+
+From: Justin Tee <justin.tee@broadcom.com>
+
+[ Upstream commit 56c3d809b7b450379162d0b8a70bbe71ab8db706 ]
+
+After a port swap between separate fabrics, there may be multiple nodes in
+the vport's fc_nodes list with the same fabric well known address.
+Duplication is temporary and eventually resolves itself after dev_loss_tmo
+expires, but nameserver queries may still occur before dev_loss_tmo. This
+possibly results in returning stale fabric ndlp objects. Fix by adding an
+nlp_state check to ensure the ndlp search routine returns the correct newer
+allocated ndlp fabric object.
+
+Signed-off-by: Justin Tee <justin.tee@broadcom.com>
+Link: https://lore.kernel.org/r/20250131000524.163662-5-justintee8345@gmail.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/lpfc/lpfc_hbadisc.c | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
+index 6e8d8a96c54fb..31dcabebc9b6d 100644
+--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
+@@ -5622,6 +5622,7 @@ static struct lpfc_nodelist *
+ __lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did)
+ {
+ struct lpfc_nodelist *ndlp;
++ struct lpfc_nodelist *np = NULL;
+ uint32_t data1;
+
+ list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
+@@ -5636,14 +5637,20 @@ __lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did)
+ ndlp, ndlp->nlp_DID,
+ ndlp->nlp_flag, data1, ndlp->nlp_rpi,
+ ndlp->active_rrqs_xri_bitmap);
+- return ndlp;
++
++ /* Check for new or potentially stale node */
++ if (ndlp->nlp_state != NLP_STE_UNUSED_NODE)
++ return ndlp;
++ np = ndlp;
+ }
+ }
+
+- /* FIND node did <did> NOT FOUND */
+- lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE,
+- "0932 FIND node did x%x NOT FOUND.\n", did);
+- return NULL;
++ if (!np)
++ /* FIND node did <did> NOT FOUND */
++ lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE,
++ "0932 FIND node did x%x NOT FOUND.\n", did);
++
++ return np;
+ }
+
+ struct lpfc_nodelist *
+--
+2.39.5
+
--- /dev/null
+From b057f204657f9f7b43bde5bf0c277b3bb9bc5b42 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jan 2025 16:05:21 -0800
+Subject: scsi: lpfc: Ignore ndlp rport mismatch in dev_loss_tmo callbk
+
+From: Justin Tee <justin.tee@broadcom.com>
+
+[ Upstream commit 23ed62897746f49f195d819ce6edeb1db27d1b72 ]
+
+With repeated port swaps between separate fabrics, there can be multiple
+registrations for fabric well known address 0xfffffe. This can cause ndlp
+reference confusion due to the usage of a single ndlp ptr that stores the
+rport object in fc_rport struct private storage during transport
+registration. Subsequent registrations update the ndlp->rport field with
+the newer rport, so when transport layer triggers dev_loss_tmo for the
+earlier registered rport the ndlp->rport private storage is referencing the
+newer rport instead of the older rport in dev_loss_tmo callbk.
+
+Because the older ndlp->rport object is already cleaned up elsewhere in
+driver code during the time of fabric swap, check that the rport provided
+in dev_loss_tmo callbk actually matches the rport stored in the LLDD's
+ndlp->rport field. Otherwise, skip dev_loss_tmo work on a stale rport.
+
+Signed-off-by: Justin Tee <justin.tee@broadcom.com>
+Link: https://lore.kernel.org/r/20250131000524.163662-4-justintee8345@gmail.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/lpfc/lpfc_hbadisc.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
+index 31dcabebc9b6d..f2e4237ff3d99 100644
+--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
+@@ -227,10 +227,16 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
+ if (ndlp->nlp_state == NLP_STE_MAPPED_NODE)
+ return;
+
+- /* check for recovered fabric node */
+- if (ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
+- ndlp->nlp_DID == Fabric_DID)
++ /* Ignore callback for a mismatched (stale) rport */
++ if (ndlp->rport != rport) {
++ lpfc_vlog_msg(vport, KERN_WARNING, LOG_NODE,
++ "6788 fc rport mismatch: d_id x%06x ndlp x%px "
++ "fc rport x%px node rport x%px state x%x "
++ "refcnt %u\n",
++ ndlp->nlp_DID, ndlp, rport, ndlp->rport,
++ ndlp->nlp_state, kref_read(&ndlp->kref));
+ return;
++ }
+
+ if (rport->port_name != wwn_to_u64(ndlp->nlp_portname.u.wwn))
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+--
+2.39.5
+
--- /dev/null
+From e8bc974d29d18d51b864ac416a9fcc8362a0f0b8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Apr 2025 15:45:46 +0530
+Subject: scsi: mpi3mr: Add level check to control event logging
+
+From: Ranjan Kumar <ranjan.kumar@broadcom.com>
+
+[ Upstream commit b0b7ee3b574a72283399b9232f6190be07f220c0 ]
+
+Ensure event logs are only generated when the debug logging level
+MPI3_DEBUG_EVENT is enabled. This prevents unnecessary logging.
+
+Signed-off-by: Ranjan Kumar <ranjan.kumar@broadcom.com>
+Link: https://lore.kernel.org/r/20250415101546.204018-1-ranjan.kumar@broadcom.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/mpi3mr/mpi3mr_fw.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c
+index c0a372868e1d7..f6d3db3fd0d8e 100644
+--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c
++++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c
+@@ -174,6 +174,9 @@ static void mpi3mr_print_event_data(struct mpi3mr_ioc *mrioc,
+ char *desc = NULL;
+ u16 event;
+
++ if (!(mrioc->logging_level & MPI3_DEBUG_EVENT))
++ return;
++
+ event = event_reply->event;
+
+ switch (event) {
+--
+2.39.5
+
--- /dev/null
+From 8aaf91b811af447aef12a06fa44833199aef5cf4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 19:55:26 +0530
+Subject: scsi: mpi3mr: Update timestamp only for supervisor IOCs
+
+From: Ranjan Kumar <ranjan.kumar@broadcom.com>
+
+[ Upstream commit 83a9d30d29f275571f6e8f879f04b2379be7eb6c ]
+
+The driver issues the time stamp update command periodically. Even if the
+command fails with supervisor only IOC Status.
+
+Instead check the Non-Supervisor capability bit reported by IOC as part of
+IOC Facts.
+
+Co-developed-by: Sumit Saxena <sumit.saxena@broadcom.com>
+Signed-off-by: Sumit Saxena <sumit.saxena@broadcom.com>
+Signed-off-by: Ranjan Kumar <ranjan.kumar@broadcom.com>
+Link: https://lore.kernel.org/r/20250220142528.20837-3-ranjan.kumar@broadcom.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/mpi3mr/mpi3mr_fw.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c
+index f6d3db3fd0d8e..604f37e5c0c35 100644
+--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c
++++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c
+@@ -2747,7 +2747,10 @@ static void mpi3mr_watchdog_work(struct work_struct *work)
+ return;
+ }
+
+- if (mrioc->ts_update_counter++ >= mrioc->ts_update_interval) {
++ if (!(mrioc->facts.ioc_capabilities &
++ MPI3_IOCFACTS_CAPABILITY_NON_SUPERVISOR_IOC) &&
++ (mrioc->ts_update_counter++ >= mrioc->ts_update_interval)) {
++
+ mrioc->ts_update_counter = 0;
+ mpi3mr_sync_timestamp(mrioc);
+ }
+--
+2.39.5
+
--- /dev/null
+From 761e19929da3beaaeabe0919bbf1fbfcc4b77462 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Feb 2025 17:26:55 -0800
+Subject: scsi: mpt3sas: Send a diag reset if target reset fails
+
+From: Shivasharan S <shivasharan.srikanteshwara@broadcom.com>
+
+[ Upstream commit 5612d6d51ed2634a033c95de2edec7449409cbb9 ]
+
+When an IOCTL times out and driver issues a target reset, if firmware
+fails the task management elevate the recovery by issuing a diag reset to
+controller.
+
+Signed-off-by: Shivasharan S <shivasharan.srikanteshwara@broadcom.com>
+Link: https://lore.kernel.org/r/1739410016-27503-5-git-send-email-shivasharan.srikanteshwara@broadcom.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/mpt3sas/mpt3sas_ctl.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
+index 87784c96249a7..47faa27bc3559 100644
+--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
++++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
+@@ -679,6 +679,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
+ size_t data_in_sz = 0;
+ long ret;
+ u16 device_handle = MPT3SAS_INVALID_DEVICE_HANDLE;
++ int tm_ret;
+
+ issue_reset = 0;
+
+@@ -1120,18 +1121,25 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
+ if (pcie_device && (!ioc->tm_custom_handling) &&
+ (!(mpt3sas_scsih_is_pcie_scsi_device(
+ pcie_device->device_info))))
+- mpt3sas_scsih_issue_locked_tm(ioc,
++ tm_ret = mpt3sas_scsih_issue_locked_tm(ioc,
+ le16_to_cpu(mpi_request->FunctionDependent1),
+ 0, 0, 0,
+ MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
+ 0, pcie_device->reset_timeout,
+ MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE);
+ else
+- mpt3sas_scsih_issue_locked_tm(ioc,
++ tm_ret = mpt3sas_scsih_issue_locked_tm(ioc,
+ le16_to_cpu(mpi_request->FunctionDependent1),
+ 0, 0, 0,
+ MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
+ 0, 30, MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET);
++
++ if (tm_ret != SUCCESS) {
++ ioc_info(ioc,
++ "target reset failed, issue hard reset: handle (0x%04x)\n",
++ le16_to_cpu(mpi_request->FunctionDependent1));
++ mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
++ }
+ } else
+ mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
+ }
+--
+2.39.5
+
--- /dev/null
+From c02cabed8ef2e147b1df5477bf87ae559ddc3bbe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 11:26:30 +0200
+Subject: scsi: scsi_debug: First fixes for tapes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
+
+[ Upstream commit f69da85d5d5cc5b7dfb963a6c6c1ac0dd9002341 ]
+
+Patch includes the following:
+
+ - Enable MODE SENSE/SELECT without actual page (to read/write only the
+ Block Descriptor)
+
+ - Store the density code and block size in the Block Descriptor (only
+ short version for tapes)
+
+ - Fix REWIND not to use the wrong page filling function
+
+Signed-off-by: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
+Link: https://lore.kernel.org/r/20250213092636.2510-2-Kai.Makisara@kolumbus.fi
+Reviewed-by: John Meneghini <jmeneghi@redhat.com>
+Tested-by: John Meneghini <jmeneghi@redhat.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_debug.c | 55 ++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 49 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
+index 680ba180a6725..89a2aaccdcfce 100644
+--- a/drivers/scsi/scsi_debug.c
++++ b/drivers/scsi/scsi_debug.c
+@@ -173,6 +173,10 @@ static const char *sdebug_version_date = "20210520";
+ #define DEF_ZBC_MAX_OPEN_ZONES 8
+ #define DEF_ZBC_NR_CONV_ZONES 1
+
++/* Default parameters for tape drives */
++#define TAPE_DEF_DENSITY 0x0
++#define TAPE_DEF_BLKSIZE 0
++
+ #define SDEBUG_LUN_0_VAL 0
+
+ /* bit mask values for sdebug_opts */
+@@ -363,6 +367,10 @@ struct sdebug_dev_info {
+ ktime_t create_ts; /* time since bootup that this device was created */
+ struct sdeb_zone_state *zstate;
+
++ /* For tapes */
++ unsigned int tape_blksize;
++ unsigned int tape_density;
++
+ struct dentry *debugfs_entry;
+ struct spinlock list_lock;
+ struct list_head inject_err_list;
+@@ -773,7 +781,7 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEM_P1 + 1] = {
+ /* 20 */
+ {0, 0x1e, 0, 0, NULL, NULL, /* ALLOW REMOVAL */
+ {6, 0, 0, 0, 0x3, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+- {0, 0x1, 0, 0, resp_start_stop, NULL, /* REWIND ?? */
++ {0, 0x1, 0, 0, NULL, NULL, /* REWIND ?? */
+ {6, 0x1, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ATA_PT */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+@@ -2742,7 +2750,7 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
+ unsigned char *ap;
+ unsigned char *arr __free(kfree);
+ unsigned char *cmd = scp->cmnd;
+- bool dbd, llbaa, msense_6, is_disk, is_zbc;
++ bool dbd, llbaa, msense_6, is_disk, is_zbc, is_tape;
+
+ arr = kzalloc(SDEBUG_MAX_MSENSE_SZ, GFP_ATOMIC);
+ if (!arr)
+@@ -2755,7 +2763,8 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
+ llbaa = msense_6 ? false : !!(cmd[1] & 0x10);
+ is_disk = (sdebug_ptype == TYPE_DISK);
+ is_zbc = devip->zoned;
+- if ((is_disk || is_zbc) && !dbd)
++ is_tape = (sdebug_ptype == TYPE_TAPE);
++ if ((is_disk || is_zbc || is_tape) && !dbd)
+ bd_len = llbaa ? 16 : 8;
+ else
+ bd_len = 0;
+@@ -2793,15 +2802,25 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
+ put_unaligned_be32(0xffffffff, ap + 0);
+ else
+ put_unaligned_be32(sdebug_capacity, ap + 0);
+- put_unaligned_be16(sdebug_sector_size, ap + 6);
++ if (is_tape) {
++ ap[0] = devip->tape_density;
++ put_unaligned_be16(devip->tape_blksize, ap + 6);
++ } else
++ put_unaligned_be16(sdebug_sector_size, ap + 6);
+ offset += bd_len;
+ ap = arr + offset;
+ } else if (16 == bd_len) {
++ if (is_tape) {
++ mk_sense_invalid_fld(scp, SDEB_IN_DATA, 1, 4);
++ return check_condition_result;
++ }
+ put_unaligned_be64((u64)sdebug_capacity, ap + 0);
+ put_unaligned_be32(sdebug_sector_size, ap + 12);
+ offset += bd_len;
+ ap = arr + offset;
+ }
++ if (cmd[2] == 0)
++ goto only_bd; /* Only block descriptor requested */
+
+ /*
+ * N.B. If len>0 before resp_*_pg() call, then form of that call should be:
+@@ -2902,6 +2921,7 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
+ default:
+ goto bad_pcode;
+ }
++only_bd:
+ if (msense_6)
+ arr[0] = offset - 1;
+ else
+@@ -2945,8 +2965,27 @@ static int resp_mode_select(struct scsi_cmnd *scp,
+ __func__, param_len, res);
+ md_len = mselect6 ? (arr[0] + 1) : (get_unaligned_be16(arr + 0) + 2);
+ bd_len = mselect6 ? arr[3] : get_unaligned_be16(arr + 6);
+- off = bd_len + (mselect6 ? 4 : 8);
+- if (md_len > 2 || off >= res) {
++ off = (mselect6 ? 4 : 8);
++ if (sdebug_ptype == TYPE_TAPE) {
++ int blksize;
++
++ if (bd_len != 8) {
++ mk_sense_invalid_fld(scp, SDEB_IN_DATA,
++ mselect6 ? 3 : 6, -1);
++ return check_condition_result;
++ }
++ blksize = get_unaligned_be16(arr + off + 6);
++ if ((blksize % 4) != 0) {
++ mk_sense_invalid_fld(scp, SDEB_IN_DATA, off + 6, -1);
++ return check_condition_result;
++ }
++ devip->tape_density = arr[off];
++ devip->tape_blksize = blksize;
++ }
++ off += bd_len;
++ if (off >= res)
++ return 0; /* No page written, just descriptors */
++ if (md_len > 2) {
+ mk_sense_invalid_fld(scp, SDEB_IN_DATA, 0, -1);
+ return check_condition_result;
+ }
+@@ -5835,6 +5874,10 @@ static struct sdebug_dev_info *sdebug_device_create(
+ } else {
+ devip->zoned = false;
+ }
++ if (sdebug_ptype == TYPE_TAPE) {
++ devip->tape_density = TAPE_DEF_DENSITY;
++ devip->tape_blksize = TAPE_DEF_BLKSIZE;
++ }
+ devip->create_ts = ktime_get_boottime();
+ atomic_set(&devip->stopped, (sdeb_tur_ms_to_ready > 0 ? 2 : 0));
+ spin_lock_init(&devip->list_lock);
+--
+2.39.5
+
--- /dev/null
+From 54bd97ac8749bc55e6de8579a2b6c730039a72a7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Mar 2025 13:25:15 +0200
+Subject: scsi: st: ERASE does not change tape location
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
+
+[ Upstream commit ad77cebf97bd42c93ab4e3bffd09f2b905c1959a ]
+
+The SCSI ERASE command erases from the current position onwards. Don't
+clear the position variables.
+
+Signed-off-by: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
+Link: https://lore.kernel.org/r/20250311112516.5548-3-Kai.Makisara@kolumbus.fi
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/st.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
+index 1c0951168f646..1cfd7e71dcdde 100644
+--- a/drivers/scsi/st.c
++++ b/drivers/scsi/st.c
+@@ -2894,7 +2894,6 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
+ timeout = STp->long_timeout * 8;
+
+ DEBC_printk(STp, "Erasing tape.\n");
+- fileno = blkno = at_sm = 0;
+ break;
+ case MTSETBLK: /* Set block length */
+ case MTSETDENSITY: /* Set tape density */
+--
+2.39.5
+
--- /dev/null
+From 21524a84f4c1f7c83d171c7dec7fb4e36e067527 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Jan 2025 21:49:22 +0200
+Subject: scsi: st: Restore some drive settings after reset
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
+
+[ Upstream commit 7081dc75df79696d8322d01821c28e53416c932c ]
+
+Some of the allowed operations put the tape into a known position to
+continue operation assuming only the tape position has changed. But reset
+sets partition, density and block size to drive default values. These
+should be restored to the values before reset.
+
+Normally the current block size and density are stored by the drive. If
+the settings have been changed, the changed values have to be saved by the
+driver across reset.
+
+Signed-off-by: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
+Link: https://lore.kernel.org/r/20250120194925.44432-2-Kai.Makisara@kolumbus.fi
+Reviewed-by: John Meneghini <jmeneghi@redhat.com>
+Tested-by: John Meneghini <jmeneghi@redhat.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/st.c | 24 +++++++++++++++++++++---
+ drivers/scsi/st.h | 2 ++
+ 2 files changed, 23 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
+index 1cfd7e71dcdde..3e982c166baf9 100644
+--- a/drivers/scsi/st.c
++++ b/drivers/scsi/st.c
+@@ -952,7 +952,6 @@ static void reset_state(struct scsi_tape *STp)
+ STp->partition = find_partition(STp);
+ if (STp->partition < 0)
+ STp->partition = 0;
+- STp->new_partition = STp->partition;
+ }
+ }
+ \f
+@@ -2926,14 +2925,17 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
+ if (cmd_in == MTSETDENSITY) {
+ (STp->buffer)->b_data[4] = arg;
+ STp->density_changed = 1; /* At least we tried ;-) */
++ STp->changed_density = arg;
+ } else if (cmd_in == SET_DENS_AND_BLK)
+ (STp->buffer)->b_data[4] = arg >> 24;
+ else
+ (STp->buffer)->b_data[4] = STp->density;
+ if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) {
+ ltmp = arg & MT_ST_BLKSIZE_MASK;
+- if (cmd_in == MTSETBLK)
++ if (cmd_in == MTSETBLK) {
+ STp->blksize_changed = 1; /* At least we tried ;-) */
++ STp->changed_blksize = arg;
++ }
+ } else
+ ltmp = STp->block_size;
+ (STp->buffer)->b_data[9] = (ltmp >> 16);
+@@ -3634,9 +3636,25 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
+ retval = (-EIO);
+ goto out;
+ }
+- reset_state(STp);
++ reset_state(STp); /* Clears pos_unknown */
+ /* remove this when the midlevel properly clears was_reset */
+ STp->device->was_reset = 0;
++
++ /* Fix the device settings after reset, ignore errors */
++ if (mtc.mt_op == MTREW || mtc.mt_op == MTSEEK ||
++ mtc.mt_op == MTEOM) {
++ if (STp->can_partitions) {
++ /* STp->new_partition contains the
++ * latest partition set
++ */
++ STp->partition = 0;
++ switch_partition(STp);
++ }
++ if (STp->density_changed)
++ st_int_ioctl(STp, MTSETDENSITY, STp->changed_density);
++ if (STp->blksize_changed)
++ st_int_ioctl(STp, MTSETBLK, STp->changed_blksize);
++ }
+ }
+
+ if (mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
+diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
+index 1aaaf5369a40f..6d31b894ee84c 100644
+--- a/drivers/scsi/st.h
++++ b/drivers/scsi/st.h
+@@ -165,6 +165,7 @@ struct scsi_tape {
+ unsigned char compression_changed;
+ unsigned char drv_buffer;
+ unsigned char density;
++ unsigned char changed_density;
+ unsigned char door_locked;
+ unsigned char autorew_dev; /* auto-rewind device */
+ unsigned char rew_at_close; /* rewind necessary at close */
+@@ -172,6 +173,7 @@ struct scsi_tape {
+ unsigned char cleaning_req; /* cleaning requested? */
+ unsigned char first_tur; /* first TEST UNIT READY */
+ int block_size;
++ int changed_blksize;
+ int min_block;
+ int max_block;
+ int recover_count; /* From tape opening */
+--
+2.39.5
+
--- /dev/null
+From 2ffff5e7aa5c4dfb313c626af8976c38cd59af4e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Mar 2025 13:25:16 +0200
+Subject: scsi: st: Tighten the page format heuristics with MODE SELECT
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
+
+[ Upstream commit 8db816c6f176321e42254badd5c1a8df8bfcfdb4 ]
+
+In the days when SCSI-2 was emerging, some drives did claim SCSI-2 but did
+not correctly implement it. The st driver first tries MODE SELECT with the
+page format bit set to set the block descriptor. If not successful, the
+non-page format is tried.
+
+The test only tests the sense code and this triggers also from illegal
+parameter in the parameter list. The test is limited to "old" devices and
+made more strict to remove false alarms.
+
+Signed-off-by: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
+Link: https://lore.kernel.org/r/20250311112516.5548-4-Kai.Makisara@kolumbus.fi
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/st.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
+index a17441635ff3a..1c0951168f646 100644
+--- a/drivers/scsi/st.c
++++ b/drivers/scsi/st.c
+@@ -3081,7 +3081,9 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
+ cmd_in == MTSETDRVBUFFER ||
+ cmd_in == SET_DENS_AND_BLK) {
+ if (cmdstatp->sense_hdr.sense_key == ILLEGAL_REQUEST &&
+- !(STp->use_pf & PF_TESTED)) {
++ cmdstatp->sense_hdr.asc == 0x24 &&
++ (STp->device)->scsi_level <= SCSI_2 &&
++ !(STp->use_pf & PF_TESTED)) {
+ /* Try the other possible state of Page Format if not
+ already tried */
+ STp->use_pf = (STp->use_pf ^ USE_PF) | PF_TESTED;
+--
+2.39.5
+
--- /dev/null
+From 165678224cfa95213e0460f42305f423e6e28c5c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Dec 2024 13:17:57 +0300
+Subject: scsi: target: iscsi: Fix timeout on deleted connection
+
+From: Dmitry Bogdanov <d.bogdanov@yadro.com>
+
+[ Upstream commit 7f533cc5ee4c4436cee51dc58e81dfd9c3384418 ]
+
+NOPIN response timer may expire on a deleted connection and crash with
+such logs:
+
+Did not receive response to NOPIN on CID: 0, failing connection for I_T Nexus (null),i,0x00023d000125,iqn.2017-01.com.iscsi.target,t,0x3d
+
+BUG: Kernel NULL pointer dereference on read at 0x00000000
+NIP strlcpy+0x8/0xb0
+LR iscsit_fill_cxn_timeout_err_stats+0x5c/0xc0 [iscsi_target_mod]
+Call Trace:
+ iscsit_handle_nopin_response_timeout+0xfc/0x120 [iscsi_target_mod]
+ call_timer_fn+0x58/0x1f0
+ run_timer_softirq+0x740/0x860
+ __do_softirq+0x16c/0x420
+ irq_exit+0x188/0x1c0
+ timer_interrupt+0x184/0x410
+
+That is because nopin response timer may be re-started on nopin timer
+expiration.
+
+Stop nopin timer before stopping the nopin response timer to be sure
+that no one of them will be re-started.
+
+Signed-off-by: Dmitry Bogdanov <d.bogdanov@yadro.com>
+Link: https://lore.kernel.org/r/20241224101757.32300-1-d.bogdanov@yadro.com
+Reviewed-by: Maurizio Lombardi <mlombard@redhat.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/target/iscsi/iscsi_target.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
+index 6002283cbebab..68bbdf3ee101d 100644
+--- a/drivers/target/iscsi/iscsi_target.c
++++ b/drivers/target/iscsi/iscsi_target.c
+@@ -4317,8 +4317,8 @@ int iscsit_close_connection(
+ spin_unlock(&iscsit_global->ts_bitmap_lock);
+
+ iscsit_stop_timers_for_cmds(conn);
+- iscsit_stop_nopin_response_timer(conn);
+ iscsit_stop_nopin_timer(conn);
++ iscsit_stop_nopin_response_timer(conn);
+
+ if (conn->conn_transport->iscsit_wait_conn)
+ conn->conn_transport->iscsit_wait_conn(conn);
+--
+2.39.5
+
--- /dev/null
+From b0856a7850b388e46c689b55020a050fb725b3b4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jan 2025 16:55:42 +0800
+Subject: scsi: target: spc: Fix loop traversal in spc_rsoc_get_descr()
+
+From: Chaohai Chen <wdhh66@163.com>
+
+[ Upstream commit 04ad06e41d1c74cc323b20a7bd023c47bd0e0c38 ]
+
+Stop traversing after finding the appropriate descriptor.
+
+Signed-off-by: Chaohai Chen <wdhh66@163.com>
+Link: https://lore.kernel.org/r/20250124085542.109088-1-wdhh66@163.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/target/target_core_spc.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
+index 61c065702350e..701dcbd7b63cf 100644
+--- a/drivers/target/target_core_spc.c
++++ b/drivers/target/target_core_spc.c
+@@ -2151,8 +2151,10 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode)
+ if (descr->serv_action_valid)
+ return TCM_INVALID_CDB_FIELD;
+
+- if (!descr->enabled || descr->enabled(descr, cmd))
++ if (!descr->enabled || descr->enabled(descr, cmd)) {
+ *opcode = descr;
++ return TCM_NO_SENSE;
++ }
+ break;
+ case 0x2:
+ /*
+@@ -2166,8 +2168,10 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode)
+ if (descr->serv_action_valid &&
+ descr->service_action == requested_sa) {
+ if (!descr->enabled || descr->enabled(descr,
+- cmd))
++ cmd)) {
+ *opcode = descr;
++ return TCM_NO_SENSE;
++ }
+ } else if (!descr->serv_action_valid)
+ return TCM_INVALID_CDB_FIELD;
+ break;
+@@ -2180,13 +2184,15 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode)
+ */
+ if (descr->service_action == requested_sa)
+ if (!descr->enabled || descr->enabled(descr,
+- cmd))
++ cmd)) {
+ *opcode = descr;
++ return TCM_NO_SENSE;
++ }
+ break;
+ }
+ }
+
+- return 0;
++ return TCM_NO_SENSE;
+ }
+
+ static sense_reason_t
+--
+2.39.5
+
--- /dev/null
+From c6e5e6e58a0e3cecae3ac5ddf9a0cbcd935ed6b1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Apr 2025 17:46:30 +0530
+Subject: scsi: ufs: Introduce quirk to extend PA_HIBERN8TIME for UFS devices
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Manish Pandey <quic_mapa@quicinc.com>
+
+[ Upstream commit 569330a34a31a52c904239439984a59972c11d28 ]
+
+Samsung UFS devices require additional time in hibern8 mode before
+exiting, beyond the negotiated handshaking phase between the host and
+device. Introduce a quirk to increase the PA_HIBERN8TIME parameter by
+100 µs, a value derived from experiments, to ensure a proper hibernation
+process.
+
+Signed-off-by: Manish Pandey <quic_mapa@quicinc.com>
+Link: https://lore.kernel.org/r/20250411121630.21330-3-quic_mapa@quicinc.com
+Reviewed-by: Bean Huo <beanhuo@micron.com>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ufs/core/ufshcd.c | 29 +++++++++++++++++++++++++++++
+ include/ufs/ufs_quirks.h | 6 ++++++
+ 2 files changed, 35 insertions(+)
+
+diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
+index a9b032d2f4a8d..247e425428c88 100644
+--- a/drivers/ufs/core/ufshcd.c
++++ b/drivers/ufs/core/ufshcd.c
+@@ -278,6 +278,7 @@ static const struct ufs_dev_quirk ufs_fixups[] = {
+ .model = UFS_ANY_MODEL,
+ .quirk = UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM |
+ UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE |
++ UFS_DEVICE_QUIRK_PA_HIBER8TIME |
+ UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS },
+ { .wmanufacturerid = UFS_VENDOR_SKHYNIX,
+ .model = UFS_ANY_MODEL,
+@@ -8459,6 +8460,31 @@ static int ufshcd_quirk_tune_host_pa_tactivate(struct ufs_hba *hba)
+ return ret;
+ }
+
++/**
++ * ufshcd_quirk_override_pa_h8time - Ensures proper adjustment of PA_HIBERN8TIME.
++ * @hba: per-adapter instance
++ *
++ * Some UFS devices require specific adjustments to the PA_HIBERN8TIME parameter
++ * to ensure proper hibernation timing. This function retrieves the current
++ * PA_HIBERN8TIME value and increments it by 100us.
++ */
++static void ufshcd_quirk_override_pa_h8time(struct ufs_hba *hba)
++{
++ u32 pa_h8time;
++ int ret;
++
++ ret = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_HIBERN8TIME), &pa_h8time);
++ if (ret) {
++ dev_err(hba->dev, "Failed to get PA_HIBERN8TIME: %d\n", ret);
++ return;
++ }
++
++ /* Increment by 1 to increase hibernation time by 100 µs */
++ ret = ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HIBERN8TIME), pa_h8time + 1);
++ if (ret)
++ dev_err(hba->dev, "Failed updating PA_HIBERN8TIME: %d\n", ret);
++}
++
+ static void ufshcd_tune_unipro_params(struct ufs_hba *hba)
+ {
+ ufshcd_vops_apply_dev_quirks(hba);
+@@ -8469,6 +8495,9 @@ static void ufshcd_tune_unipro_params(struct ufs_hba *hba)
+
+ if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE)
+ ufshcd_quirk_tune_host_pa_tactivate(hba);
++
++ if (hba->dev_quirks & UFS_DEVICE_QUIRK_PA_HIBER8TIME)
++ ufshcd_quirk_override_pa_h8time(hba);
+ }
+
+ static void ufshcd_clear_dbg_ufs_stats(struct ufs_hba *hba)
+diff --git a/include/ufs/ufs_quirks.h b/include/ufs/ufs_quirks.h
+index 41ff44dfa1db3..f52de5ed1b3b6 100644
+--- a/include/ufs/ufs_quirks.h
++++ b/include/ufs/ufs_quirks.h
+@@ -107,4 +107,10 @@ struct ufs_dev_quirk {
+ */
+ #define UFS_DEVICE_QUIRK_DELAY_AFTER_LPM (1 << 11)
+
++/*
++ * Some ufs devices may need more time to be in hibern8 before exiting.
++ * Enable this quirk to give it an additional 100us.
++ */
++#define UFS_DEVICE_QUIRK_PA_HIBER8TIME (1 << 12)
++
+ #endif /* UFS_QUIRKS_H_ */
+--
+2.39.5
+
--- /dev/null
+From fd6c40f66a754e4c86049b00fb8c7357fce7a715 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Apr 2025 10:02:46 -0700
+Subject: selftests/bpf: Mitigate sockmap_ktls disconnect_after_delete failure
+
+From: Ihor Solodrai <ihor.solodrai@linux.dev>
+
+[ Upstream commit f2858f308131a09e33afb766cd70119b5b900569 ]
+
+"sockmap_ktls disconnect_after_delete" test has been failing on BPF CI
+after recent merges from netdev:
+* https://github.com/kernel-patches/bpf/actions/runs/14458537639
+* https://github.com/kernel-patches/bpf/actions/runs/14457178732
+
+It happens because disconnect has been disabled for TLS [1], and it
+renders the test case invalid.
+
+Removing all the test code creates a conflict between bpf and
+bpf-next, so for now only remove the offending assert [2].
+
+The test will be removed later on bpf-next.
+
+[1] https://lore.kernel.org/netdev/20250404180334.3224206-1-kuba@kernel.org/
+[2] https://lore.kernel.org/bpf/cfc371285323e1a3f3b006bfcf74e6cf7ad65258@linux.dev/
+
+Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Link: https://lore.kernel.org/bpf/20250416170246.2438524-1-ihor.solodrai@linux.dev
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c b/tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c
+index 2d0796314862a..0a99fd404f6dc 100644
+--- a/tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c
++++ b/tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c
+@@ -68,7 +68,6 @@ static void test_sockmap_ktls_disconnect_after_delete(int family, int map)
+ goto close_cli;
+
+ err = disconnect(cli);
+- ASSERT_OK(err, "disconnect");
+
+ close_cli:
+ close(cli);
+--
+2.39.5
+
--- /dev/null
+From 37f2a19e8ba4337a58badabef1f67f369e14a6d1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Feb 2025 11:27:23 -0800
+Subject: selftests/net: have `gro.sh -t` return a correct exit code
+
+From: Kevin Krakauer <krakauer@google.com>
+
+[ Upstream commit 784e6abd99f24024a8998b5916795f0bec9d2fd9 ]
+
+Modify gro.sh to return a useful exit code when the -t flag is used. It
+formerly returned 0 no matter what.
+
+Tested: Ran `gro.sh -t large` and verified that test failures return 1.
+Signed-off-by: Kevin Krakauer <krakauer@google.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20250226192725.621969-2-krakauer@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/net/gro.sh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/tools/testing/selftests/net/gro.sh b/tools/testing/selftests/net/gro.sh
+index 02c21ff4ca81f..aabd6e5480b8e 100755
+--- a/tools/testing/selftests/net/gro.sh
++++ b/tools/testing/selftests/net/gro.sh
+@@ -100,5 +100,6 @@ trap cleanup EXIT
+ if [[ "${test}" == "all" ]]; then
+ run_all_tests
+ else
+- run_test "${proto}" "${test}"
++ exit_code=$(run_test "${proto}" "${test}")
++ exit $exit_code
+ fi;
+--
+2.39.5
+
--- /dev/null
+From 3248841827441e81c96226bc07369ba5cee44d5a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 07:21:53 +0100
+Subject: serial: mctrl_gpio: split disable_ms into sync and no_sync APIs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alexis Lothoré <alexis.lothore@bootlin.com>
+
+[ Upstream commit 1bd2aad57da95f7f2d2bb52f7ad15c0f4993a685 ]
+
+The following splat has been observed on a SAMA5D27 platform using
+atmel_serial:
+
+BUG: sleeping function called from invalid context at kernel/irq/manage.c:738
+in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 27, name: kworker/u5:0
+preempt_count: 1, expected: 0
+INFO: lockdep is turned off.
+irq event stamp: 0
+hardirqs last enabled at (0): [<00000000>] 0x0
+hardirqs last disabled at (0): [<c01588f0>] copy_process+0x1c4c/0x7bec
+softirqs last enabled at (0): [<c0158944>] copy_process+0x1ca0/0x7bec
+softirqs last disabled at (0): [<00000000>] 0x0
+CPU: 0 UID: 0 PID: 27 Comm: kworker/u5:0 Not tainted 6.13.0-rc7+ #74
+Hardware name: Atmel SAMA5
+Workqueue: hci0 hci_power_on [bluetooth]
+Call trace:
+ unwind_backtrace from show_stack+0x18/0x1c
+ show_stack from dump_stack_lvl+0x44/0x70
+ dump_stack_lvl from __might_resched+0x38c/0x598
+ __might_resched from disable_irq+0x1c/0x48
+ disable_irq from mctrl_gpio_disable_ms+0x74/0xc0
+ mctrl_gpio_disable_ms from atmel_disable_ms.part.0+0x80/0x1f4
+ atmel_disable_ms.part.0 from atmel_set_termios+0x764/0x11e8
+ atmel_set_termios from uart_change_line_settings+0x15c/0x994
+ uart_change_line_settings from uart_set_termios+0x2b0/0x668
+ uart_set_termios from tty_set_termios+0x600/0x8ec
+ tty_set_termios from ttyport_set_flow_control+0x188/0x1e0
+ ttyport_set_flow_control from wilc_setup+0xd0/0x524 [hci_wilc]
+ wilc_setup [hci_wilc] from hci_dev_open_sync+0x330/0x203c [bluetooth]
+ hci_dev_open_sync [bluetooth] from hci_dev_do_open+0x40/0xb0 [bluetooth]
+ hci_dev_do_open [bluetooth] from hci_power_on+0x12c/0x664 [bluetooth]
+ hci_power_on [bluetooth] from process_one_work+0x998/0x1a38
+ process_one_work from worker_thread+0x6e0/0xfb4
+ worker_thread from kthread+0x3d4/0x484
+ kthread from ret_from_fork+0x14/0x28
+
+This warning is emitted when trying to toggle, at the highest level,
+some flow control (with serdev_device_set_flow_control) in a device
+driver. At the lowest level, the atmel_serial driver is using
+serial_mctrl_gpio lib to enable/disable the corresponding IRQs
+accordingly. The warning emitted by CONFIG_DEBUG_ATOMIC_SLEEP is due to
+disable_irq (called in mctrl_gpio_disable_ms) being possibly called in
+some atomic context (some tty drivers perform modem lines configuration
+in regions protected by port lock).
+
+Split mctrl_gpio_disable_ms into two differents APIs, a non-blocking one
+and a blocking one. Replace mctrl_gpio_disable_ms calls with the
+relevant version depending on whether the call is protected by some port
+lock.
+
+Suggested-by: Jiri Slaby <jirislaby@kernel.org>
+Signed-off-by: Alexis Lothoré <alexis.lothore@bootlin.com>
+Acked-by: Richard Genoud <richard.genoud@bootlin.com>
+Link: https://lore.kernel.org/r/20250217-atomic_sleep_mctrl_serial_gpio-v3-1-59324b313eef@bootlin.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/driver-api/serial/driver.rst | 2 +-
+ drivers/tty/serial/8250/8250_port.c | 2 +-
+ drivers/tty/serial/atmel_serial.c | 2 +-
+ drivers/tty/serial/imx.c | 2 +-
+ drivers/tty/serial/serial_mctrl_gpio.c | 34 +++++++++++++++++-----
+ drivers/tty/serial/serial_mctrl_gpio.h | 17 +++++++++--
+ drivers/tty/serial/sh-sci.c | 2 +-
+ drivers/tty/serial/stm32-usart.c | 2 +-
+ 8 files changed, 47 insertions(+), 16 deletions(-)
+
+diff --git a/Documentation/driver-api/serial/driver.rst b/Documentation/driver-api/serial/driver.rst
+index 84b43061c11be..60434f2b02863 100644
+--- a/Documentation/driver-api/serial/driver.rst
++++ b/Documentation/driver-api/serial/driver.rst
+@@ -103,4 +103,4 @@ Some helpers are provided in order to set/get modem control lines via GPIO.
+ .. kernel-doc:: drivers/tty/serial/serial_mctrl_gpio.c
+ :identifiers: mctrl_gpio_init mctrl_gpio_free mctrl_gpio_to_gpiod
+ mctrl_gpio_set mctrl_gpio_get mctrl_gpio_enable_ms
+- mctrl_gpio_disable_ms
++ mctrl_gpio_disable_ms_sync mctrl_gpio_disable_ms_no_sync
+diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
+index c1376727642a7..0519679929652 100644
+--- a/drivers/tty/serial/8250/8250_port.c
++++ b/drivers/tty/serial/8250/8250_port.c
+@@ -1657,7 +1657,7 @@ static void serial8250_disable_ms(struct uart_port *port)
+ if (up->bugs & UART_BUG_NOMSR)
+ return;
+
+- mctrl_gpio_disable_ms(up->gpios);
++ mctrl_gpio_disable_ms_no_sync(up->gpios);
+
+ up->ier &= ~UART_IER_MSI;
+ serial_port_out(port, UART_IER, up->ier);
+diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
+index 09b246c9e389e..8bd39586a49f7 100644
+--- a/drivers/tty/serial/atmel_serial.c
++++ b/drivers/tty/serial/atmel_serial.c
+@@ -700,7 +700,7 @@ static void atmel_disable_ms(struct uart_port *port)
+
+ atmel_port->ms_irq_enabled = false;
+
+- mctrl_gpio_disable_ms(atmel_port->gpios);
++ mctrl_gpio_disable_ms_no_sync(atmel_port->gpios);
+
+ if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS))
+ idr |= ATMEL_US_CTSIC;
+diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
+index 90974d338f3c0..8e3b15534bc72 100644
+--- a/drivers/tty/serial/imx.c
++++ b/drivers/tty/serial/imx.c
+@@ -1596,7 +1596,7 @@ static void imx_uart_shutdown(struct uart_port *port)
+ imx_uart_dma_exit(sport);
+ }
+
+- mctrl_gpio_disable_ms(sport->gpios);
++ mctrl_gpio_disable_ms_sync(sport->gpios);
+
+ uart_port_lock_irqsave(&sport->port, &flags);
+ ucr2 = imx_uart_readl(sport, UCR2);
+diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c
+index 8855688a5b6c0..ca55bcc0b6111 100644
+--- a/drivers/tty/serial/serial_mctrl_gpio.c
++++ b/drivers/tty/serial/serial_mctrl_gpio.c
+@@ -322,11 +322,7 @@ void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios)
+ }
+ EXPORT_SYMBOL_GPL(mctrl_gpio_enable_ms);
+
+-/**
+- * mctrl_gpio_disable_ms - disable irqs and handling of changes to the ms lines
+- * @gpios: gpios to disable
+- */
+-void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios)
++static void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios, bool sync)
+ {
+ enum mctrl_gpio_idx i;
+
+@@ -342,10 +338,34 @@ void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios)
+ if (!gpios->irq[i])
+ continue;
+
+- disable_irq(gpios->irq[i]);
++ if (sync)
++ disable_irq(gpios->irq[i]);
++ else
++ disable_irq_nosync(gpios->irq[i]);
+ }
+ }
+-EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms);
++
++/**
++ * mctrl_gpio_disable_ms_sync - disable irqs and handling of changes to the ms
++ * lines, and wait for any pending IRQ to be processed
++ * @gpios: gpios to disable
++ */
++void mctrl_gpio_disable_ms_sync(struct mctrl_gpios *gpios)
++{
++ mctrl_gpio_disable_ms(gpios, true);
++}
++EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms_sync);
++
++/**
++ * mctrl_gpio_disable_ms_no_sync - disable irqs and handling of changes to the
++ * ms lines, and return immediately
++ * @gpios: gpios to disable
++ */
++void mctrl_gpio_disable_ms_no_sync(struct mctrl_gpios *gpios)
++{
++ mctrl_gpio_disable_ms(gpios, false);
++}
++EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms_no_sync);
+
+ void mctrl_gpio_enable_irq_wake(struct mctrl_gpios *gpios)
+ {
+diff --git a/drivers/tty/serial/serial_mctrl_gpio.h b/drivers/tty/serial/serial_mctrl_gpio.h
+index fc76910fb105a..79e97838ebe56 100644
+--- a/drivers/tty/serial/serial_mctrl_gpio.h
++++ b/drivers/tty/serial/serial_mctrl_gpio.h
+@@ -87,9 +87,16 @@ void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios);
+ void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios);
+
+ /*
+- * Disable gpio interrupts to report status line changes.
++ * Disable gpio interrupts to report status line changes, and block until
++ * any corresponding IRQ is processed
+ */
+-void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios);
++void mctrl_gpio_disable_ms_sync(struct mctrl_gpios *gpios);
++
++/*
++ * Disable gpio interrupts to report status line changes, and return
++ * immediately
++ */
++void mctrl_gpio_disable_ms_no_sync(struct mctrl_gpios *gpios);
+
+ /*
+ * Enable gpio wakeup interrupts to enable wake up source.
+@@ -148,7 +155,11 @@ static inline void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios)
+ {
+ }
+
+-static inline void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios)
++static inline void mctrl_gpio_disable_ms_sync(struct mctrl_gpios *gpios)
++{
++}
++
++static inline void mctrl_gpio_disable_ms_no_sync(struct mctrl_gpios *gpios)
+ {
+ }
+
+diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
+index f43059e1b5c28..80efe3b0ed0c3 100644
+--- a/drivers/tty/serial/sh-sci.c
++++ b/drivers/tty/serial/sh-sci.c
+@@ -2297,7 +2297,7 @@ static void sci_shutdown(struct uart_port *port)
+ dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
+
+ s->autorts = false;
+- mctrl_gpio_disable_ms(to_sci_port(port)->gpios);
++ mctrl_gpio_disable_ms_sync(to_sci_port(port)->gpios);
+
+ uart_port_lock_irqsave(port, &flags);
+ sci_stop_rx(port);
+diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
+index 9b9981352b1e1..e685cace5c854 100644
+--- a/drivers/tty/serial/stm32-usart.c
++++ b/drivers/tty/serial/stm32-usart.c
+@@ -944,7 +944,7 @@ static void stm32_usart_enable_ms(struct uart_port *port)
+
+ static void stm32_usart_disable_ms(struct uart_port *port)
+ {
+- mctrl_gpio_disable_ms(to_stm32_port(port)->gpios);
++ mctrl_gpio_disable_ms_sync(to_stm32_port(port)->gpios);
+ }
+
+ /* Transmit stop */
+--
+2.39.5
+
--- /dev/null
+From 9469f6e0b2edebbb7ee4448e03e2fb802c628f12 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Feb 2025 13:33:13 +0200
+Subject: serial: sh-sci: Update the suspend/resume support
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit 22a6984c5b5df8eab864d7f3e8b94d5a554d31ab ]
+
+The Renesas RZ/G3S supports a power saving mode where power to most of the
+SoC components is turned off. When returning from this power saving mode,
+SoC components need to be re-configured.
+
+The SCIFs on the Renesas RZ/G3S need to be re-configured as well when
+returning from this power saving mode. The sh-sci code already configures
+the SCIF clocks, power domain and registers by calling uart_resume_port()
+in sci_resume(). On suspend path the SCIF UART ports are suspended
+accordingly (by calling uart_suspend_port() in sci_suspend()). The only
+missing setting is the reset signal. For this assert/de-assert the reset
+signal on driver suspend/resume.
+
+In case the no_console_suspend is specified by the user, the registers need
+to be saved on suspend path and restore on resume path. To do this the
+sci_console_save()/sci_console_restore() functions were added. There is no
+need to cache/restore the status or FIFO registers. Only the control
+registers. The registers that will be saved/restored on suspend/resume are
+specified by the struct sci_suspend_regs data structure.
+
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lore.kernel.org/r/20250207113313.545432-1-claudiu.beznea.uj@bp.renesas.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/sh-sci.c | 71 +++++++++++++++++++++++++++++++++++--
+ 1 file changed, 69 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
+index 80efe3b0ed0c3..779074b1c2be4 100644
+--- a/drivers/tty/serial/sh-sci.c
++++ b/drivers/tty/serial/sh-sci.c
+@@ -104,6 +104,15 @@ struct plat_sci_reg {
+ u8 offset, size;
+ };
+
++struct sci_suspend_regs {
++ u16 scsmr;
++ u16 scscr;
++ u16 scfcr;
++ u16 scsptr;
++ u8 scbrr;
++ u8 semr;
++};
++
+ struct sci_port_params {
+ const struct plat_sci_reg regs[SCIx_NR_REGS];
+ unsigned int fifosize;
+@@ -134,6 +143,8 @@ struct sci_port {
+ struct dma_chan *chan_tx;
+ struct dma_chan *chan_rx;
+
++ struct reset_control *rstc;
++
+ #ifdef CONFIG_SERIAL_SH_SCI_DMA
+ struct dma_chan *chan_tx_saved;
+ struct dma_chan *chan_rx_saved;
+@@ -153,6 +164,7 @@ struct sci_port {
+ int rx_trigger;
+ struct timer_list rx_fifo_timer;
+ int rx_fifo_timeout;
++ struct sci_suspend_regs suspend_regs;
+ u16 hscif_tot;
+
+ bool has_rtscts;
+@@ -3384,6 +3396,7 @@ static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev,
+ }
+
+ sp = &sci_ports[id];
++ sp->rstc = rstc;
+ *dev_id = id;
+
+ p->type = SCI_OF_TYPE(data);
+@@ -3532,13 +3545,57 @@ static int sci_probe(struct platform_device *dev)
+ return 0;
+ }
+
++static void sci_console_save(struct sci_port *s)
++{
++ struct sci_suspend_regs *regs = &s->suspend_regs;
++ struct uart_port *port = &s->port;
++
++ if (sci_getreg(port, SCSMR)->size)
++ regs->scsmr = sci_serial_in(port, SCSMR);
++ if (sci_getreg(port, SCSCR)->size)
++ regs->scscr = sci_serial_in(port, SCSCR);
++ if (sci_getreg(port, SCFCR)->size)
++ regs->scfcr = sci_serial_in(port, SCFCR);
++ if (sci_getreg(port, SCSPTR)->size)
++ regs->scsptr = sci_serial_in(port, SCSPTR);
++ if (sci_getreg(port, SCBRR)->size)
++ regs->scbrr = sci_serial_in(port, SCBRR);
++ if (sci_getreg(port, SEMR)->size)
++ regs->semr = sci_serial_in(port, SEMR);
++}
++
++static void sci_console_restore(struct sci_port *s)
++{
++ struct sci_suspend_regs *regs = &s->suspend_regs;
++ struct uart_port *port = &s->port;
++
++ if (sci_getreg(port, SCSMR)->size)
++ sci_serial_out(port, SCSMR, regs->scsmr);
++ if (sci_getreg(port, SCSCR)->size)
++ sci_serial_out(port, SCSCR, regs->scscr);
++ if (sci_getreg(port, SCFCR)->size)
++ sci_serial_out(port, SCFCR, regs->scfcr);
++ if (sci_getreg(port, SCSPTR)->size)
++ sci_serial_out(port, SCSPTR, regs->scsptr);
++ if (sci_getreg(port, SCBRR)->size)
++ sci_serial_out(port, SCBRR, regs->scbrr);
++ if (sci_getreg(port, SEMR)->size)
++ sci_serial_out(port, SEMR, regs->semr);
++}
++
+ static __maybe_unused int sci_suspend(struct device *dev)
+ {
+ struct sci_port *sport = dev_get_drvdata(dev);
+
+- if (sport)
++ if (sport) {
+ uart_suspend_port(&sci_uart_driver, &sport->port);
+
++ if (!console_suspend_enabled && uart_console(&sport->port))
++ sci_console_save(sport);
++ else
++ return reset_control_assert(sport->rstc);
++ }
++
+ return 0;
+ }
+
+@@ -3546,8 +3603,18 @@ static __maybe_unused int sci_resume(struct device *dev)
+ {
+ struct sci_port *sport = dev_get_drvdata(dev);
+
+- if (sport)
++ if (sport) {
++ if (!console_suspend_enabled && uart_console(&sport->port)) {
++ sci_console_restore(sport);
++ } else {
++ int ret = reset_control_deassert(sport->rstc);
++
++ if (ret)
++ return ret;
++ }
++
+ uart_resume_port(&sci_uart_driver, &sport->port);
++ }
+
+ return 0;
+ }
+--
+2.39.5
+
--- /dev/null
+drm-amd-display-configure-dtbclk_p-with-optc-only-fo.patch
+drm-amd-display-do-not-enable-replay-when-vtotal-upd.patch
+drm-amd-display-correct-timing_adjust_pending-flag-s.patch
+drm-amd-display-defer-bw-optimization-blocked-drr-ad.patch
+i2c-designware-use-temporary-variable-for-struct-dev.patch
+i2c-designware-fix-an-error-handling-path-in-i2c_dw_.patch
+phy-renesas-rcar-gen3-usb2-move-irq-request-in-probe.patch
+phy-renesas-rcar-gen3-usb2-lock-around-hardware-regi.patch
+phy-renesas-rcar-gen3-usb2-assert-pll-reset-on-phy-p.patch
+cpufreq-add-sm8650-to-cpufreq-dt-platdev-blocklist.patch
+nvmem-rockchip-otp-move-read-offset-into-variant-dat.patch
+nvmem-rockchip-otp-add-rk3576-variant-data.patch
+nvmem-core-fix-bit-offsets-of-more-than-one-byte.patch
+nvmem-core-verify-cell-s-raw_len.patch
+nvmem-core-update-raw_len-if-the-bit-reading-is-requ.patch
+nvmem-qfprom-switch-to-4-byte-aligned-reads.patch
+scsi-target-iscsi-fix-timeout-on-deleted-connection.patch
+scsi-ufs-introduce-quirk-to-extend-pa_hibern8time-fo.patch
+virtio_ring-fix-data-race-by-tagging-event_triggered.patch
+dma-mapping.c-dev_dbg-support-for-dma_addressing_lim.patch
+intel_th-avoid-using-deprecated-page-mapping-index-f.patch
+mei-vsc-use-struct-vsc_tp_packet-as-vsc-tp-tx_buf-an.patch
+dma-mapping-avoid-potential-unused-data-compilation-.patch
+cgroup-fix-compilation-issue-due-to-cgroup_mutex-not.patch
+vhost_task-fix-vhost_task_create-documentation.patch
+vhost-scsi-protect-vq-log_used-with-vq-mutex.patch
+scsi-mpi3mr-add-level-check-to-control-event-logging.patch
+net-enetc-refactor-bulk-flipping-of-rx-buffers-to-se.patch
+dma-mapping-fix-warning-reported-for-missing-prototy.patch
+ima-process_measurement-needlessly-takes-inode_lock-.patch
+fs-buffer-split-locking-for-pagecache-lookups.patch
+fs-buffer-introduce-sleeping-flavors-for-pagecache-l.patch
+fs-buffer-use-sleeping-version-of-__find_get_block.patch
+fs-ocfs2-use-sleeping-version-of-__find_get_block.patch
+fs-jbd2-use-sleeping-version-of-__find_get_block.patch
+fs-ext4-use-sleeping-version-of-sb_find_get_block.patch
+drm-amd-display-enable-urgent-latency-adjustment-on-.patch
+drm-amdgpu-allow-p2p-access-through-xgmi.patch
+selftests-bpf-mitigate-sockmap_ktls-disconnect_after.patch
+block-fix-race-between-set_blocksize-and-read-paths.patch
+io_uring-don-t-duplicate-flushing-in-io_req_post_cqe.patch
+bpf-fix-possible-endless-loop-in-bpf-map-iteration.patch
+samples-bpf-fix-compilation-failure-for-samples-bpf-.patch
+kconfig-merge_config-use-an-empty-file-as-initfile.patch
+x86-fred-fix-system-hang-during-s4-resume-with-fred-.patch
+s390-vfio-ap-fix-no-ap-queue-sharing-allowed-message.patch
+cifs-add-fallback-for-smb2-create-without-file_read_.patch
+cifs-fix-querying-and-creating-mf-symlinks-over-smb1.patch
+cifs-fix-negotiate-retry-functionality.patch
+smb-client-store-original-io-parameters-and-prevent-.patch
+fuse-return-eperm-rather-than-enosys-from-link.patch
+exfat-call-bh_read-in-get_block-only-when-necessary.patch
+io_uring-msg-initialise-msg-request-opcode.patch
+nfsv4-check-for-delegation-validity-in-nfs_start_del.patch
+nfs-don-t-allow-waiting-for-exiting-tasks.patch
+sunrpc-don-t-allow-waiting-for-exiting-tasks.patch
+arm64-add-support-for-hip09-spectre-bhb-mitigation.patch
+iommufd-extend-iommu_get_hw_info-to-report-pasid-cap.patch
+tracing-mark-binary-printing-functions-with-__printf.patch
+acpi-pnp-add-intel-oc-watchdog-ids-to-non-pnp-device.patch
+tpm-convert-warn-to-dbg-in-tpm2_start_auth_session.patch
+mailbox-pcc-use-acpi_os_ioremap-instead-of-ioremap.patch
+mailbox-use-error-ret-code-of-of_parse_phandle_with_.patch
+riscv-allow-nommu-kernels-to-access-all-of-ram.patch
+fbdev-fsl-diu-fb-add-missing-device_remove_file.patch
+fbcon-use-correct-erase-colour-for-clearing-in-fbcon.patch
+fbdev-core-tileblit-implement-missing-margin-clearin.patch
+cifs-set-default-netbios-rfc1001-server-name-to-host.patch
+cifs-add-validation-check-for-the-fields-in-smb_aces.patch
+cifs-fix-establishing-netbios-session-for-smb2-conne.patch
+nfsv4-treat-enetunreach-errors-as-fatal-for-state-re.patch
+sunrpc-rpc_clnt_set_transport-must-not-change-the-au.patch
+sunrpc-rpcbind-should-never-reset-the-port-to-the-va.patch
+spi-rockchip-fix-register-out-of-bounds-access.patch
+asoc-codecs-wsa884x-correct-vi-sense-channel-mask.patch
+asoc-codecs-wsa883x-correct-vi-sense-channel-mask.patch
+mctp-fix-incorrect-tx-flow-invalidation-condition-in.patch
+net-tn40xx-add-pci-id-of-the-aqr105-based-tehuti-tn4.patch
+net-tn40xx-create-swnode-for-mdio-and-aqr105-phy-and.patch
+thermal-drivers-mediatek-lvts-start-sensor-interrupt.patch
+thermal-drivers-qoriq-power-down-tmu-on-system-suspe.patch
+bluetooth-btmtksdio-prevent-enabling-interrupts-afte.patch
+bluetooth-disable-sco-support-if-read_voice_setting-.patch
+exit-fix-the-usage-of-delay_group_leader-exit_code-i.patch
+dql-fix-dql-limit-value-when-reset.patch
+lockdep-fix-wait-context-check-on-softirq-for-preemp.patch
+objtool-properly-disable-uaccess-validation.patch
+pci-dwc-ep-ensure-proper-iteration-over-outbound-map.patch
+r8169-disable-rtl8126-zrx-dc-timeout.patch
+tools-build-don-t-pass-test-log-files-to-linker.patch
+pnfs-flexfiles-report-enetdown-as-a-connection-error.patch
+drm-amdgpu-discovery-check-ip_discovery-fw-file-avai.patch
+drm-amdkfd-set-precise-mem-ops-caps-to-disabled-for-.patch
+pci-vmd-disable-msi-remapping-bypass-under-xen.patch
+xen-pci-do-not-register-devices-with-segments-0x1000.patch
+ext4-on-a-remount-only-log-the-ro-or-r-w-state-when-.patch
+libnvdimm-labels-fix-divide-error-in-nd_label_data_i.patch
+pidfs-improve-multi-threaded-exec-and-premature-thre.patch
+staging-vchiq_arm-create-keep-alive-thread-during-pr.patch
+mmc-host-wait-for-vdd-to-settle-on-card-power-off.patch
+drm-amdgpu-skip-pcie_replay_count-sysfs-creation-for.patch
+cgroup-rstat-avoid-disabling-irqs-for-o-num_cpu.patch
+wifi-mt76-only-mark-tx-status-failed-frames-as-acked.patch
+wifi-mt76-mt7996-fix-ser-reset-trigger-on-wed-reset.patch
+wifi-mt76-mt7996-revise-txs-size.patch
+wifi-mt76-mt7925-load-the-appropriate-clc-data-based.patch
+wifi-mt76-mt7925-fix-fails-to-enter-low-power-mode-i.patch
+x86-headers-replace-__assembly__-with-__assembler__-.patch
+x86-stackprotector-64-only-export-__ref_stack_chk_gu.patch
+x86-smpboot-fix-init-delay-assignment-for-extended-i.patch
+x86-microcode-update-the-intel-processor-flag-scan-c.patch
+x86-mm-check-return-value-from-memblock_phys_alloc_r.patch
+i2c-qup-vote-for-interconnect-bandwidth-to-dram.patch
+i2c-pxa-fix-call-balance-of-i2c-clk-handling-routine.patch
+btrfs-make-btrfs_discard_workfn-block_group-ref-expl.patch
+btrfs-avoid-linker-error-in-btrfs_find_create_tree_b.patch
+btrfs-run-btrfs_error_commit_super-early.patch
+btrfs-fix-non-empty-delayed-iputs-list-on-unmount-du.patch
+btrfs-properly-limit-inline-data-extent-according-to.patch
+btrfs-prevent-inline-data-extents-read-from-touching.patch
+btrfs-get-zone-unusable-bytes-while-holding-lock-at-.patch
+btrfs-send-return-enametoolong-when-attempting-a-pat.patch
+btrfs-zoned-exit-btrfs_can_activate_zone-if-btrfs_fs.patch
+blk-cgroup-improve-policy-registration-error-handlin.patch
+drm-amdgpu-release-xcp_mgr-on-exit.patch
+drm-amd-display-guard-against-setting-dispclk-low-fo.patch
+drm-amdgpu-adjust-drm_firmware_drivers_only-handling.patch
+i3c-master-svc-fix-missing-stop-for-master-request.patch
+s390-tlb-use-mm_has_pgste-instead-of-mm_alloc_pgste.patch
+dlm-make-tcp-still-work-in-multi-link-env.patch
+clocksource-drivers-timer-riscv-stop-stimecmp-when-c.patch
+um-store-full-csgsfs-and-ss-register-from-mcontext.patch
+um-update-min_low_pfn-to-match-changes-in-uml_reserv.patch
+wifi-mwifiex-fix-ht40-bandwidth-issue.patch
+bnxt_en-query-fw-parameters-when-the-caps_change-bit.patch
+riscv-call-secondary-mmu-notifier-when-flushing-the-.patch
+ext4-reorder-capability-check-last.patch
+hypfs_create_cpu_files-add-missing-check-for-hypfs_m.patch
+scsi-st-tighten-the-page-format-heuristics-with-mode.patch
+scsi-st-erase-does-not-change-tape-location.patch
+vfio-pci-handle-intx-irq_notconnected.patch
+libbpf-pass-bpf-token-from-find_prog_btf_id-to-bpf_b.patch
+bpf-return-prog-btf_id-without-capable-check.patch
+pci-dwc-use-resource-start-as-ioremap-input-in-dw_pc.patch
+jbd2-do-not-try-to-recover-wiped-journal.patch
+tcp-reorganize-tcp_in_ack_event-and-tcp_count_delive.patch
+rtc-rv3032-fix-eerd-location.patch
+objtool-fix-error-handling-inconsistencies-in-check.patch
+thunderbolt-do-not-add-non-active-nvm-if-nvm-upgrade.patch
+erofs-initialize-decompression-early.patch
+spi-spi-mux-fix-coverity-issue-unchecked-return-valu.patch
+asoc-pcm6240-drop-bogus-code-handling-irq-as-gpio.patch
+asoc-mediatek-mt6359-add-stub-for-mt6359_accdet_enab.patch
+bpf-allow-pre-ordering-for-bpf-cgroup-progs.patch
+kbuild-fix-argument-parsing-in-scripts-config.patch
+kconfig-do-not-clear-symbol_valid-when-reading-inclu.patch
+crypto-octeontx2-suppress-auth-failure-screaming-due.patch
+dm-restrict-dm-device-size-to-2-63-512-bytes.patch
+net-smc-use-the-correct-ndev-to-find-pnetid-by-pneti.patch
+xen-add-support-for-xenserver-6.1-platform-device.patch
+pinctrl-tegra-restore-sfsel-bit-when-freeing-pins.patch
+mfd-tps65219-remove-tps65219_reg_ti_dev_id-check.patch
+drm-amdgpu-gfx12-don-t-read-registers-in-mqd-init.patch
+drm-amdgpu-gfx11-don-t-read-registers-in-mqd-init.patch
+drm-amdgpu-update-sriov-video-codec-caps.patch
+asoc-sun4i-codec-support-hp-det-gpios-property.patch
+clk-qcom-lpassaudiocc-sc7280-add-support-for-lpass-r.patch
+f2fs-defer-readonly-check-vs-norecovery.patch
+ext4-reject-the-data_err-abort-option-in-nojournal-m.patch
+ext4-do-not-convert-the-unwritten-extents-if-data-wr.patch
+rdma-uverbs-propagate-errors-from-rdma_lookup_get_uo.patch
+posix-timers-add-cond_resched-to-posix_timer_add-sea.patch
+posix-timers-ensure-that-timer-initialization-is-ful.patch
+net-stmmac-dwmac-rk-validate-grf-and-peripheral-grf-.patch
+net-hsr-fix-prp-duplicate-detection.patch
+timer_list-don-t-use-pk-through-printk.patch
+wifi-rtw89-set-force-he-tb-mode-when-connecting-to-1.patch
+netfilter-conntrack-bound-nf_conntrack-sysctl-writes.patch
+pnp-expand-length-of-fixup-id-string.patch
+phy-rockchip-usbdp-only-verify-link-rates-lanes-volt.patch
+arm64-mm-check-pmd_table-in-pmd_trans_huge.patch
+arm64-mm-check-pud_type_table-in-pud_bad.patch
+mmc-dw_mmc-add-exynos7870-dw-mmc-support.patch
+mmc-sdhci-disable-sd-card-clock-before-changing-para.patch
+usb-xhci-don-t-change-the-status-of-stalled-tds-on-f.patch
+wifi-iwlwifi-mvm-fix-setting-the-tk-when-associated.patch
+hwmon-dell-smm-increment-the-number-of-fans.patch
+iommu-keep-dev-iommu-state-consistent.patch
+printk-check-con_suspend-when-unblanking-a-console.patch
+wifi-iwlwifi-don-t-warn-when-if-there-is-a-fw-error.patch
+wifi-iwlwifi-w-a-fw-smps-mode-selection.patch
+wifi-iwlwifi-fix-debug-actions-order.patch
+wifi-iwlwifi-mark-br-device-not-integrated.patch
+wifi-iwlwifi-fix-the-eckv-uefi-variable-name.patch
+wifi-mac80211-fix-warning-on-disconnect-during-faile.patch
+wifi-mac80211_hwsim-fix-mld-address-translation.patch
+wifi-cfg80211-allow-ir-in-20-mhz-configurations.patch
+ipv6-save-dontfrag-in-cork.patch
+drm-amd-display-remove-minimum-dispclk-and-apply-oem.patch
+drm-amd-display-calculate-the-remain-segments-for-al.patch
+drm-amd-display-not-abort-link-train-when-bw-is-low.patch
+drm-amd-display-fix-incorrect-dpcd-configs-while-rep.patch
+gfs2-check-for-empty-queue-in-run_queue.patch
+auxdisplay-charlcd-partially-revert-move-hwidth-and-.patch
+asoc-qcom-sm8250-explicitly-set-format-in-sm8250_be_.patch
+badblocks-fix-a-nonsense-warn_on-which-checks-whethe.patch
+coresight-etb10-change-etb_drvdata-spinlock-s-type-t.patch
+iommu-vt-d-move-scalable-mode-ats-enablement-to-prob.patch
+iommu-amd-pgtbl_v2-improve-error-handling.patch
+cpufreq-tegra186-share-policy-per-cluster.patch
+watchdog-aspeed-update-bootstatus-handling.patch
+pci-endpoint-pci-epf-test-fix-double-free-that-cause.patch
+misc-pci_endpoint_test-give-disabled-bars-a-distinct.patch
+crypto-lzo-fix-compression-buffer-overrun.patch
+crypto-mxs-dcp-only-set-otp_key-bit-for-otp-key.patch
+drm-amdkfd-set-per-process-flags-only-once-for-gfx9-.patch
+drm-amdkfd-set-per-process-flags-only-once-cik-vi.patch
+drm-amdgpu-fix-missing-drain-retry-fault-the-last-en.patch
+arm64-tegra-p2597-fix-gpio-for-vdd-1v8-dis-regulator.patch
+arm64-tegra-resize-aperture-for-the-igx-pcie-c5-slot.patch
+powerpc-prom_init-fixup-missing-size-cells-on-powerb.patch
+alsa-seq-improve-data-consistency-at-polling.patch
+tcp-bring-back-numa-dispersion-in-inet_ehash_locks_a.patch
+rtc-ds1307-stop-disabling-alarms-on-probe.patch
+ieee802154-ca8210-use-proper-setters-and-getters-for.patch
+drm-xe-nuke-vm-s-mapping-upon-close.patch
+drm-xe-retry-bo-allocation.patch
+soc-samsung-include-linux-array_size.h-where-needed.patch
+arm-tegra-switch-dsi-b-clock-parent-to-plld-on-tegra.patch
+media-c8sectpfe-call-of_node_put-i2c_bus-only-once-i.patch
+usb-xhci-set-page-size-to-the-xhci-supported-size.patch
+dm-cache-prevent-bug_on-by-blocking-retries-on-faile.patch
+soc-mediatek-mtk-mutex-add-dpi1-sof-eof-to-mt8188-mu.patch
+orangefs-do-not-truncate-file-size.patch
+drm-gem-test-for-imported-gem-buffers-with-helper.patch
+net-phylink-use-pl-link_interface-in-phylink_expects.patch
+blk-throttle-don-t-take-carryover-for-prioritized-pr.patch
+remoteproc-qcom_wcnss-handle-platforms-with-only-sin.patch
+drm-amdgpu-do-not-program-agp-bar-regs-under-sriov-i.patch
+drm-amd-display-ensure-dmcub-idle-before-reset-on-dc.patch
+drm-amd-display-skip-checking-frl_mode-bit-for-pcon-.patch
+drm-amd-display-fix-dmub-reset-sequence-for-dcn401.patch
+drm-amd-display-fix-p-state-type-when-p-state-is-uns.patch
+drm-amd-display-request-hw-cursor-on-dcn3.2-with-sub.patch
+perf-core-clean-up-perf_try_init_event.patch
+media-cx231xx-set-device_caps-for-417.patch
+pinctrl-bcm281xx-use-unsigned-int-instead-of-bare-un.patch
+rcu-fix-get_state_synchronize_rcu_full-gp-start-dete.patch
+net-ethernet-ti-cpsw_new-populate-netdev-of_node.patch
+net-phy-nxp-c45-tja11xx-add-match_phy_device-to-tja1.patch
+dpll-add-an-assertion-to-check-freq_supported_num.patch
+ublk-enforce-ublks_max-only-for-unprivileged-devices.patch
+iommufd-disallow-allocating-nested-parent-domain-wit.patch
+media-imx335-set-vblank-immediately.patch
+net-pktgen-fix-mpls-maximum-labels-list-parsing.patch
+perf-hw_breakpoint-return-eopnotsupp-for-unsupported.patch
+alsa-hda-realtek-enable-pc-beep-passthrough-for-hp-e.patch
+scsi-logging-fix-scsi_logging_level-bounds.patch
+ipv4-fib-move-fib_valid_key_len-to-rtm_to_fib_config.patch
+drm-rockchip-vop2-add-uv-swap-for-cluster-window.patch
+block-mark-bounce-buffering-as-incompatible-with-int.patch
+ublk-complete-command-synchronously-on-error.patch
+media-uvcvideo-add-sanity-check-to-uvc_ioctl_xu_ctrl.patch
+media-uvcvideo-handle-uvc-menu-translation-inside-uv.patch
+clk-imx8mp-inform-ccf-of-maximum-frequency-of-clocks.patch
+x86-bugs-make-spectre-user-default-depend-on-mitigat.patch
+hwmon-gpio-fan-add-missing-mutex-locks.patch
+arm-at91-pm-fix-at91_suspend_finish-for-zq-calibrati.patch
+drm-mediatek-mtk_dpi-add-checks-for-reg_h_fre_con-ex.patch
+fpga-altera-cvp-increase-credit-timeout.patch
+perf-arm_pmuv3-call-kvm_vcpu_pmu_resync_el0-before-e.patch
+soc-apple-rtkit-use-high-prio-work-queue.patch
+soc-apple-rtkit-implement-oslog-buffers-properly.patch
+wifi-ath12k-report-proper-tx-completion-status-to-ma.patch
+pci-brcmstb-expand-inbound-window-size-up-to-64gb.patch
+pci-brcmstb-add-a-softdep-to-mip-msi-x-driver.patch
+nvme-map-uring_cmd-data-even-if-address-is-0.patch
+firmware-arm_ffa-set-dma_mask-for-ffa-devices.patch
+drm-xe-vf-retry-sending-mmio-request-to-guc-on-timeo.patch
+drm-xe-pf-create-a-link-between-pf-and-vf-devices.patch
+net-mlx5-avoid-report-two-health-errors-on-same-synd.patch
+selftests-net-have-gro.sh-t-return-a-correct-exit-co.patch
+pinctrl-sophgo-avoid-to-modify-untouched-bit-when-se.patch
+drm-amdkfd-kfd-release_work-possible-circular-lockin.patch
+drm-xe-xe_gen_wa_oob-replace-program_invocation_shor.patch
+leds-pwm-multicolor-add-check-for-fwnode_property_re.patch
+net-ethernet-mtk_ppe_offload-allow-qinq-double-eth_p.patch
+net-xgene-v2-remove-incorrect-acpi_ptr-annotation.patch
+bonding-report-duplicate-mac-address-in-all-situatio.patch
+wifi-ath12k-improve-bss-discovery-with-hidden-ssid-i.patch
+soc-ti-k3-socinfo-do-not-use-syscon-helper-to-build-.patch
+bpf-search-and-add-kfuncs-in-struct_ops-prologue-and.patch
+octeontx2-af-rpm-register-driver-with-pci-subsys-ids.patch
+x86-build-fix-broken-copy-command-in-genimage.sh-whe.patch
+drm-amd-display-handle-max_downscale_src_width-fail-.patch
+drm-amd-display-fix-dcn4x-init-failed.patch
+drm-amd-display-fix-mismatch-type-comparison.patch
+asoc-mediatek-mt8188-treat-dmic_gainx_cur-as-non-vol.patch
+asoc-mediatek-mt8188-add-reference-for-dmic-clocks.patch
+x86-nmi-add-an-emergency-handler-in-nmi_desc-use-it-.patch
+vhost-scsi-return-queue-full-for-page-alloc-failures.patch
+vdpa-mlx5-fix-mlx5_vdpa_get_config-endianness-on-big.patch
+cpuidle-menu-avoid-discarding-useful-information.patch
+media-adv7180-disable-test-pattern-control-on-adv718.patch
+media-tc358746-improve-calculation-of-the-d-phy-timi.patch
+net-mlx5e-add-correct-match-to-check-ipsec-syndromes.patch
+scsi-mpi3mr-update-timestamp-only-for-supervisor-ioc.patch
+loop-check-in-lo_flags_direct_io-in-loop_default_blo.patch
+libbpf-fix-out-of-bound-read.patch
+dm-fix-unconditional-io-throttle-caused-by-req_prefl.patch
+fs-mpage-avoid-negative-shift-for-large-blocksize.patch
+scsi-scsi_debug-first-fixes-for-tapes.patch
+net-mlx5-change-pool_next_size-define-value-and-make.patch
+x86-kaslr-reduce-kaslr-entropy-on-most-x86-systems.patch
+crypto-ahash-set-default-reqsize-from-ahash_alg.patch
+crypto-skcipher-zap-type-in-crypto_alloc_sync_skciph.patch
+net-ipv6-init-tunnel-link-netns-before-registering-d.patch
+drm-xe-oa-ensure-that-polled-read-returns-latest-dat.patch
+mips-use-arch-specific-syscall-name-match-function.patch
+drm-amdgpu-remove-all-kfd-fences-from-the-bo-on-rele.patch
+x86-locking-use-alt_output_sp-for-percpu_-try_-cmpxc.patch
+genirq-msi-store-the-iommu-iova-directly-in-msi_desc.patch
+mips-pm-cps-use-per-cpu-variables-as-per-cpu-not-per.patch
+clocksource-mips-gic-timer-enable-counter-when-cpus-.patch
+pci-epf-mhi-update-device-id-for-sa8775p.patch
+scsi-mpt3sas-send-a-diag-reset-if-target-reset-fails.patch
+wifi-rtw88-fix-rtw_init_vht_cap-for-rtl8814au.patch
+wifi-rtw88-fix-rtw_init_ht_cap-for-rtl8814au.patch
+wifi-rtw88-fix-rtw_desc_to_mcsrate-to-handle-mcs16-3.patch
+wifi-rtw89-fw-propagate-error-code-from-rtw89_h2c_tx.patch
+wifi-rtw89-fw-get-sb_sel_ver-via-get_unaligned_le32.patch
+wifi-rtw89-fw-add-blacklist-to-avoid-obsolete-secure.patch
+wifi-rtw89-8922a-fix-incorrect-sta-id-in-eht-mu-ppdu.patch
+net-pktgen-fix-access-outside-of-user-given-buffer-i.patch
+power-supply-axp20x_battery-update-temp-sensor-for-a.patch
+edac-ie31200-work-around-false-positive-build-warnin.patch
+bpf-prevent-unsafe-access-to-the-sock-fields-in-the-.patch
+i3c-master-svc-flush-fifo-before-sending-dynamic-add.patch
+mfd-axp20x-axp717-add-axp717_ts_pin_cfg-to-writeable.patch
+eeprom-ee1004-check-chip-before-probing.patch
+irqchip-riscv-imsic-separate-next-and-previous-point.patch
+drm-amd-pm-fetch-current-power-limit-from-pmfw.patch
+drm-amd-display-add-support-for-disconnected-edp-str.patch
+drm-amd-display-guard-against-setting-dispclk-low-wh.patch
+drm-amd-display-fix-bt2020-ycbcr-limited-full-range-.patch
+drm-amd-display-read-lttpr-alpm-caps-during-link-cap.patch
+revert-drm-amd-display-request-hw-cursor-on-dcn3.2-w.patch
+drm-amd-display-don-t-treat-wb-connector-as-physical.patch
+serial-mctrl_gpio-split-disable_ms-into-sync-and-no_.patch
+rdma-core-fix-best-page-size-finding-when-it-can-cro.patch
+pmdomain-imx-gpcv2-use-proper-helper-for-property-de.patch
+can-c_can-use-of_property_present-to-test-existence-.patch
+bpf-don-t-do-clean_live_states-when-state-loop_entry.patch
+bpf-copy_verifier_state-should-copy-loop_entry-field.patch
+eth-mlx4-don-t-try-to-complete-xdp-frames-in-netpoll.patch
+pci-fix-old_size-lower-bound-in-calculate_iosize-too.patch
+acpi-hed-always-initialize-before-evged.patch
+vxlan-join-leave-mc-group-after-remote-changes.patch
+x86-relocs-handle-r_x86_64_rex_gotpcrelx-relocations.patch
+x86-boot-disable-stack-protector-for-early-boot-code.patch
+hrtimers-replace-hrtimer_clock_to_base_table-with-sw.patch
+irqchip-riscv-imsic-set-irq_set_affinity-for-imsic-b.patch
+media-test-drivers-vivid-don-t-call-schedule-in-loop.patch
+net-mlx5-modify-lsb-bitmask-in-temperature-event-to-.patch
+net-mlx5-apply-rate-limiting-to-high-temperature-war.patch
+firmware-arm_ffa-reject-higher-major-version-as-inco.patch
+firmware-arm_ffa-handle-the-presence-of-host-partiti.patch
+firmware-xilinx-dont-send-linux-address-to-get-fpga-.patch
+asoc-ops-enforce-platform-maximum-on-initial-value.patch
+asoc-tas2764-add-reg-defaults-for-tas2764_int_clk_cf.patch
+asoc-tas2764-mark-sw_reset-as-volatile.patch
+asoc-tas2764-power-up-down-amp-on-mute-ops.patch
+asoc-soc-dai-check-return-value-at-snd_soc_dai_set_t.patch
+pinctrl-devicetree-do-not-goto-err-when-probing-hogs.patch
+smack-recognize-ipv4-cipso-w-o-categories.patch
+smack-revert-smackfs-added-check-catlen.patch
+kunit-tool-use-qboot-on-qemu-x86_64.patch
+kernfs-don-t-re-lock-kernfs_root-kernfs_rwsem-in-ker.patch
+kernfs-acquire-kernfs_rwsem-in-kernfs_node_dentry.patch
+kernfs-acquire-kernfs_rwsem-in-kernfs_get_parent_den.patch
+kernfs-acquire-kernfs_rwsem-in-kernfs_notify_workfn.patch
+media-i2c-imx219-correct-the-minimum-vblanking-value.patch
+media-v4l-memset-argument-to-0-before-calling-get_mb.patch
+libbpf-fix-ldx-stx-st-co-re-relocation-size-adjustme.patch
+net-mlx4_core-avoid-impossible-mlx4_db_alloc-order-v.patch
+drm-xe-stop-ignoring-errors-from-xe_ttm_stolen_mgr_i.patch
+drm-xe-fix-xe_tile_init_noalloc-error-propagation.patch
+clk-qcom-ipq5018-allow-it-to-be-bulid-on-arm32.patch
+clk-qcom-clk-alpha-pll-do-not-use-random-stack-value.patch
+drm-xe-debugfs-fixed-the-return-value-of-wedged_mode.patch
+drm-xe-debugfs-add-missing-xe_pm_runtime_put-in-wedg.patch
+x86-ibt-handle-fineibt-in-handle_cfi_failure.patch
+x86-traps-cleanup-and-robustify-decode_bug.patch
+sched-reduce-the-default-slice-to-avoid-tasks-gettin.patch
+serial-sh-sci-update-the-suspend-resume-support.patch
+pinctrl-renesas-rzg2l-add-suspend-resume-support-for.patch
+phy-phy-rockchip-samsung-hdptx-swap-the-definitions-.patch
+phy-core-don-t-require-set_mode-callback-for-phy_get.patch
+phy-exynos5-usbdrd-fix-eds-distribution-tuning-gs101.patch
+soundwire-amd-change-the-soundwire-wake-enable-disab.patch
+soundwire-cadence_master-set-frame-shape-and-divider.patch
+net-stmmac-dwmac-loongson-set-correct-tx-rx-_fifo_si.patch
+drm-amdgpu-mes11-fix-set_hw_resources_1-calculation.patch
+drm-amdkfd-fix-missing-l2-cache-info-in-topology.patch
+drm-amdgpu-set-snoop-bit-for-sdma-for-mi-series.patch
+drm-amd-display-pass-calculated-dram_speed_mts-to-dm.patch
+drm-amd-display-don-t-try-aux-transactions-on-discon.patch
+drm-amdgpu-reset-psp-cmd-to-null-after-releasing-the.patch
+drm-amd-pm-skip-p2s-load-for-smu-v13.0.12.patch
+drm-amd-display-support-multiple-options-during-psr-.patch
+revert-drm-amd-display-exit-idle-optimizations-befor.patch
+drm-amd-display-update-cr-aux-rd-interval-interpreta.patch
+drm-amd-display-initial-psr_version-with-correct-set.patch
+drm-amd-display-increase-block_sequence-array-size.patch
+drm-amd-display-use-nominal-vblank-if-provided-inste.patch
+drm-amd-display-populate-register-address-for-dentis.patch
+drm-amdgpu-use-active-umc-info-from-discovery.patch
+drm-amdgpu-enlarge-the-vbios-binary-size-limit.patch
+drm-amd-display-dm-drop-hw_support-check-in-amdgpu_d.patch
+scsi-target-spc-fix-loop-traversal-in-spc_rsoc_get_d.patch
+net-mlx5-xdp-enable-tx-side-xdp-multi-buffer-support.patch
+net-mlx5-extend-ethtool-loopback-selftest-to-support.patch
+net-mlx5e-set-the-tx_queue_len-for-pfifo_fast.patch
+net-mlx5e-reduce-rep-rxq-depth-to-256-for-ecpf.patch
+net-mlx5e-reduce-the-max-log-mpwrq-sz-for-ecpf-and-r.patch
+drm-v3d-add-clock-handling.patch
+xfrm-prevent-high-seq-input-in-non-esn-mode.patch
+wifi-ath12k-fix-the-ampdu-id-fetch-in-the-hal_rx_mpd.patch
+mptcp-pm-userspace-flags-clearer-msg-if-no-remote-ad.patch
+wifi-iwlwifi-use-correct-imr-dump-variable.patch
+wifi-iwlwifi-don-t-warn-during-reprobe.patch
+wifi-mac80211-don-t-unconditionally-call-drv_mgd_com.patch
+wifi-mac80211-remove-misplaced-drv_mgd_complete_tx-c.patch
+wifi-mac80211-set-ieee80211_prep_tx_info-link_id-upo.patch
+net-fec-refactor-mac-reset-to-function.patch
+powerpc-pseries-iommu-memory-notifier-incorrectly-ad.patch
+powerpc-pseries-iommu-create-ddw-for-devices-with-dm.patch
+arch-powerpc-perf-check-the-instruction-type-before-.patch
+ip-fib_rules-fetch-net-from-fib_rule-in-fib-46-_rule.patch
+r8152-add-vendor-device-id-pair-for-dell-alienware-a.patch
+iio-adc-ad7944-don-t-use-storagebits-for-sizing.patch
+pstore-change-kmsg_bytes-storage-size-to-u32.patch
+leds-trigger-netdev-configure-led-blink-interval-for.patch
+net-ethtool-prevent-flow-steering-to-rss-contexts-wh.patch
+ext4-don-t-write-back-data-before-punch-hole-in-nojo.patch
+ext4-remove-writable-userspace-mappings-before-trunc.patch
+wifi-rtw88-fix-download_firmware_validate-for-rtl881.patch
+wifi-rtw88-fix-__rtw_download_firmware-for-rtl8814au.patch
+wifi-rtw89-coex-assign-value-over-than-0-to-avoid-fi.patch
+wifi-rtw89-fw-validate-multi-firmware-header-before-.patch
+wifi-rtw89-fw-validate-multi-firmware-header-before-.patch-29952
+wifi-rtw89-call-power_on-ahead-before-selecting-firm.patch
+clk-qcom-camcc-sm8250-use-clk_rcg2_shared_ops-for-so.patch
+net-page_pool-avoid-false-positive-warning-if-napi-w.patch
+tools-power-turbostat-clustered-uncore-mhz-counters-.patch
+hwmon-xgene-hwmon-use-appropriate-type-for-the-laten.patch
+f2fs-introduce-f2fs_base_attr-for-global-sysfs-entri.patch
+media-qcom-camss-csid-only-add-tpg-v4l2-ctrl-if-tpg-.patch
+media-qcom-camss-add-default-case-in-vfe_src_pad_cod.patch
+drm-rockchip-vop2-improve-display-modes-handling-on-.patch
+eth-fbnic-set-iff_unicast_flt-to-avoid-enabling-prom.patch
+tools-ynl-gen-don-t-output-external-constants.patch
+net-mlx5e-avoid-warn_on-when-configuring-mqprio-with.patch
+cpufreq-amd-pstate-remove-unnecessary-driver_lock-in.patch
+vxlan-annotate-fdb-data-races.patch
+ipv4-ip_gre-fix-set-but-not-used-warning-in-ipgre_er.patch
+r8169-don-t-scan-phy-addresses-0.patch
+net-flush_backlog-small-changes.patch
+bridge-mdb-allow-replace-of-a-host-joined-group.patch
+ice-init-flow-director-before-rdma.patch
+ice-treat-dyn_allowed-only-as-suggestion.patch
+rcu-handle-quiescent-states-for-preempt_rcu-n-preemp.patch
+rcu-handle-unstable-rdp-in-rcu_read_unlock_strict.patch
+rcu-fix-header-guard-for-rcu_all_qs.patch
+perf-avoid-the-read-if-the-count-is-already-updated.patch
+ice-count-combined-queues-using-rx-tx-count.patch
+drm-xe-relay-don-t-use-gfp_kernel-for-new-transactio.patch
+net-mana-fix-warning-in-the-writer-of-client-oob.patch
+scsi-lpfc-handle-duplicate-d_ids-in-ndlp-search-by-d.patch
+scsi-lpfc-ignore-ndlp-rport-mismatch-in-dev_loss_tmo.patch
+scsi-lpfc-free-phba-irq-in-lpfc_sli4_enable_msi-when.patch
+scsi-st-restore-some-drive-settings-after-reset.patch
+wifi-ath12k-avoid-napi_sync-before-napi_enable.patch
+hid-usbkbd-fix-the-bit-shift-number-for-led_kana.patch
+arm64-zynqmp-add-clock-output-names-property-in-cloc.patch
+asoc-codecs-pcm3168a-allow-for-24-bit-in-provider-mo.patch
+asoc-rt722-sdca-add-some-missing-readable-registers.patch
+irqchip-riscv-aplic-add-support-for-hart-indexes.patch
+dm-vdo-vio-pool-allow-variable-sized-metadata-vios.patch
+dm-vdo-indexer-prevent-unterminated-string-warning.patch
+dm-vdo-use-a-short-static-string-for-thread-name-pre.patch
+drm-ast-find-vbios-mode-from-regular-display-size.patch
+bpf-use-kallsyms-to-find-the-function-name-of-a-stru.patch
+bpftool-fix-readlink-usage-in-get_fd_type.patch
+firmware-arm_scmi-relax-duplicate-name-constraint-ac.patch
+perf-amd-ibs-fix-perf_ibs_op.cnt_mask-for-curcnt.patch
+perf-amd-ibs-fix-config-to-sample-period-calculation.patch
+clk-renesas-rzg2l-cpg-refactor-runtime-pm-clock-vali.patch
+wifi-rtl8xxxu-retry-firmware-download-on-error.patch
+wifi-rtw88-don-t-use-static-local-variable-in-rtw882.patch
+wifi-rtw89-add-wiphy_lock-to-work-that-isn-t-held-wi.patch
+spi-zynqmp-gqspi-always-acknowledge-interrupts.patch
+regulator-ad5398-add-device-tree-support.patch
+wifi-ath12k-fix-ath12k_hal_tx_cmd_ext_desc_setup-inf.patch
+accel-qaic-mask-out-sr-iov-pci-resources.patch
+drm-xe-pf-reset-guc-vf-config-when-unprovisioning-cr.patch
+wifi-ath9k-return-by-of_get_mac_address.patch
+wifi-ath12k-fetch-regdb.bin-file-from-board-2.bin.patch
+wifi-ath12k-fix-end-offset-bit-definition-in-monitor.patch
+drm-bridge-adv7511-fill-stream-capabilities.patch
+drm-nouveau-fix-the-broken-marco-gsp_msg_max_size.patch
+wifi-ath11k-use-dma_alloc_noncoherent-for-rx_tid-buf.patch
+drm-xe-move-suballocator-init-to-after-display-init.patch
+drm-xe-do-not-attempt-to-bootstrap-vf-in-execlists-m.patch
+wifi-rtw89-coex-separated-wi-fi-connecting-event-fro.patch
+drm-xe-sa-always-call-drm_suballoc_manager_fini.patch
+drm-xe-reject-bo-eviction-if-bo-is-bound-to-current-.patch
+drm-atomic-clarify-the-rules-around-drm_atomic_state.patch
+drm-buddy-fix-issue-that-force_merge-cannot-free-all.patch
+drm-panel-edp-add-starry-116khd024006.patch
+drm-add-valid-clones-check.patch
+kernfs-use-rcu-to-access-kernfs_node-parent.patch
+asoc-imx-card-adjust-over-allocation-of-memory-in-im.patch
+book3s64-radix-fix-compile-errors-when-config_arch_w.patch
+pinctrl-meson-define-the-pull-up-down-resistor-value.patch
+smb-server-smb2pdu-check-return-value-of-xa_store.patch
+platform-x86-intel-hid-add-pantherlake-support.patch
+platform-x86-asus-wmi-disable-oobe-state-after-resum.patch
+platform-x86-ideapad-laptop-add-support-for-some-new.patch
+asoc-cs42l43-disable-headphone-clamps-during-type-de.patch
+asoc-intel-bytcr_rt5640-add-dmi-quirk-for-acer-aspir.patch
+alsa-hda-realtek-add-quirk-for-hp-spectre-x360-15-df.patch
+nvme-pci-add-quirks-for-device-126f-1001.patch
+nvme-pci-add-quirks-for-wdc-blue-sn550-15b7-5009.patch
+alsa-usb-audio-fix-duplicated-name-in-midi-substream.patch
+nvmet-tcp-don-t-restore-null-sk_state_change.patch
+io_uring-fdinfo-annotate-racy-sq-cq-head-tail-reads.patch
+cifs-fix-and-improve-cifs_query_path_info-and-cifs_q.patch
+cifs-fix-changing-times-and-read-only-attr-over-smb1.patch
+asoc-intel-sdw_utils-add-volume-limit-to-cs42l43-spe.patch
+btrfs-compression-adjust-cb-compressed_folios-alloca.patch
+btrfs-correct-the-order-of-prelim_ref-arguments-in-b.patch
+btrfs-handle-empty-eb-folios-in-num_extent_folios.patch
+btrfs-avoid-null-pointer-dereference-if-no-valid-csu.patch
+tools-ynl-gen-validate-0-len-strings-from-kernel.patch
+block-only-update-request-sector-if-needed.patch
+wifi-iwlwifi-add-support-for-killer-on-mtl.patch
+x86-kconfig-make-cfi_auto_default-depend-on-rust-or-.patch
+xenbus-allow-pvh-dom0-a-non-local-xenstore.patch
+drm-amd-display-call-fp-protect-before-mode-programm.patch
+__legitimize_mnt-check-for-mnt_sync_umount-should-be.patch
--- /dev/null
+From 2bd85938b32bef7a73efbcf328c3cce3e375c8aa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Jan 2025 02:40:34 +0300
+Subject: smack: recognize ipv4 CIPSO w/o categories
+
+From: Konstantin Andreev <andreev@swemel.ru>
+
+[ Upstream commit a158a937d864d0034fea14913c1f09c6d5f574b8 ]
+
+If SMACK label has CIPSO representation w/o categories, e.g.:
+
+| # cat /smack/cipso2
+| foo 10
+| @ 250/2
+| ...
+
+then SMACK does not recognize such CIPSO in input ipv4 packets
+and substitues '*' label instead. Audit records may look like
+
+| lsm=SMACK fn=smack_socket_sock_rcv_skb action=denied
+| subject="*" object="_" requested=w pid=0 comm="swapper/1" ...
+
+This happens in two steps:
+
+1) security/smack/smackfs.c`smk_set_cipso
+ does not clear NETLBL_SECATTR_MLS_CAT
+ from (struct smack_known *)skp->smk_netlabel.flags
+ on assigning CIPSO w/o categories:
+
+| rcu_assign_pointer(skp->smk_netlabel.attr.mls.cat, ncats.attr.mls.cat);
+| skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl;
+
+2) security/smack/smack_lsm.c`smack_from_secattr
+ can not match skp->smk_netlabel with input packet's
+ struct netlbl_lsm_secattr *sap
+ because sap->flags have not NETLBL_SECATTR_MLS_CAT (what is correct)
+ but skp->smk_netlabel.flags have (what is incorrect):
+
+| if ((sap->flags & NETLBL_SECATTR_MLS_CAT) == 0) {
+| if ((skp->smk_netlabel.flags &
+| NETLBL_SECATTR_MLS_CAT) == 0)
+| found = 1;
+| break;
+| }
+
+This commit sets/clears NETLBL_SECATTR_MLS_CAT in
+skp->smk_netlabel.flags according to the presense of CIPSO categories.
+The update of smk_netlabel is not atomic, so input packets processing
+still may be incorrect during short time while update proceeds.
+
+Signed-off-by: Konstantin Andreev <andreev@swemel.ru>
+Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ security/smack/smackfs.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
+index 5dd1e164f9b13..d27e8b916bfb9 100644
+--- a/security/smack/smackfs.c
++++ b/security/smack/smackfs.c
+@@ -933,6 +933,10 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
+ if (rc >= 0) {
+ old_cat = skp->smk_netlabel.attr.mls.cat;
+ rcu_assign_pointer(skp->smk_netlabel.attr.mls.cat, ncats.attr.mls.cat);
++ if (ncats.attr.mls.cat)
++ skp->smk_netlabel.flags |= NETLBL_SECATTR_MLS_CAT;
++ else
++ skp->smk_netlabel.flags &= ~(u32)NETLBL_SECATTR_MLS_CAT;
+ skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl;
+ synchronize_rcu();
+ netlbl_catmap_free(old_cat);
+--
+2.39.5
+
--- /dev/null
+From e5d25204ff1278a24a92f68a8a9c6bd5854f5b32 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Jan 2025 02:40:33 +0300
+Subject: smack: Revert "smackfs: Added check catlen"
+
+From: Konstantin Andreev <andreev@swemel.ru>
+
+[ Upstream commit c7fb50cecff9cad19fdac5b37337eae4e42b94c7 ]
+
+This reverts commit ccfd889acb06eab10b98deb4b5eef0ec74157ea0
+
+The indicated commit
+* does not describe the problem that change tries to solve
+* has programming issues
+* introduces a bug: forever clears NETLBL_SECATTR_MLS_CAT
+ in (struct smack_known *)skp->smk_netlabel.flags
+
+Reverting the commit to reapproach original problem
+
+Signed-off-by: Konstantin Andreev <andreev@swemel.ru>
+Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ security/smack/smackfs.c | 17 +++--------------
+ 1 file changed, 3 insertions(+), 14 deletions(-)
+
+diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
+index d27e8b916bfb9..1e35c9f807b2b 100644
+--- a/security/smack/smackfs.c
++++ b/security/smack/smackfs.c
+@@ -830,7 +830,7 @@ static int smk_open_cipso(struct inode *inode, struct file *file)
+ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos, int format)
+ {
+- struct netlbl_lsm_catmap *old_cat, *new_cat = NULL;
++ struct netlbl_lsm_catmap *old_cat;
+ struct smack_known *skp;
+ struct netlbl_lsm_secattr ncats;
+ char mapcatset[SMK_CIPSOLEN];
+@@ -917,19 +917,8 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
+
+ smack_catset_bit(cat, mapcatset);
+ }
+- ncats.flags = 0;
+- if (catlen == 0) {
+- ncats.attr.mls.cat = NULL;
+- ncats.attr.mls.lvl = maplevel;
+- new_cat = netlbl_catmap_alloc(GFP_ATOMIC);
+- if (new_cat)
+- new_cat->next = ncats.attr.mls.cat;
+- ncats.attr.mls.cat = new_cat;
+- skp->smk_netlabel.flags &= ~(1U << 3);
+- rc = 0;
+- } else {
+- rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN);
+- }
++
++ rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN);
+ if (rc >= 0) {
+ old_cat = skp->smk_netlabel.attr.mls.cat;
+ rcu_assign_pointer(skp->smk_netlabel.attr.mls.cat, ncats.attr.mls.cat);
+--
+2.39.5
+
--- /dev/null
+From aa05216e99d038bf68e41d070c56f24b2e835d6e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 31 Mar 2025 21:33:14 +0800
+Subject: smb: client: Store original IO parameters and prevent zero IO sizes
+
+From: Wang Zhaolong <wangzhaolong1@huawei.com>
+
+[ Upstream commit 287906b20035a04a234d1a3c64f760a5678387be ]
+
+During mount option processing and negotiation with the server, the
+original user-specified rsize/wsize values were being modified directly.
+This makes it impossible to recover these values after a connection
+reset, leading to potential degraded performance after reconnection.
+
+The other problem is that When negotiating read and write sizes, there are
+cases where the negotiated values might calculate to zero, especially
+during reconnection when server->max_read or server->max_write might be
+reset. In general, these values come from the negotiation response.
+According to MS-SMB2 specification, these values should be at least 65536
+bytes.
+
+This patch improves IO parameter handling:
+
+1. Adds vol_rsize and vol_wsize fields to store the original user-specified
+ values separately from the negotiated values
+2. Uses got_rsize/got_wsize flags to determine if values were
+ user-specified rather than checking for non-zero values, which is more
+ reliable
+3. Adds a prevent_zero_iosize() helper function to ensure IO sizes are
+ never negotiated down to zero, which could happen in edge cases like
+ when server->max_read/write is zero
+
+The changes make the CIFS client more resilient to unusual server
+responses and reconnection scenarios, preventing potential failures
+when IO sizes are calculated to be zero.
+
+Signed-off-by: Wang Zhaolong <wangzhaolong1@huawei.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/fs_context.c | 2 ++
+ fs/smb/client/fs_context.h | 3 +++
+ fs/smb/client/smb1ops.c | 6 +++---
+ fs/smb/client/smb2ops.c | 27 +++++++++++++++++++--------
+ fs/smb/common/smb2pdu.h | 3 +++
+ 5 files changed, 30 insertions(+), 11 deletions(-)
+
+diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
+index 69cca4f17dbaa..b015a4f997cb6 100644
+--- a/fs/smb/client/fs_context.c
++++ b/fs/smb/client/fs_context.c
+@@ -1267,6 +1267,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
+ case Opt_rsize:
+ ctx->rsize = result.uint_32;
+ ctx->got_rsize = true;
++ ctx->vol_rsize = ctx->rsize;
+ break;
+ case Opt_wsize:
+ ctx->wsize = result.uint_32;
+@@ -1282,6 +1283,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
+ ctx->wsize, PAGE_SIZE);
+ }
+ }
++ ctx->vol_wsize = ctx->wsize;
+ break;
+ case Opt_acregmax:
+ if (result.uint_32 > CIFS_MAX_ACTIMEO / HZ) {
+diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h
+index ac6baa774ad3a..c7e00025518f7 100644
+--- a/fs/smb/client/fs_context.h
++++ b/fs/smb/client/fs_context.h
+@@ -263,6 +263,9 @@ struct smb3_fs_context {
+ bool use_client_guid:1;
+ /* reuse existing guid for multichannel */
+ u8 client_guid[SMB2_CLIENT_GUID_SIZE];
++ /* User-specified original r/wsize value */
++ unsigned int vol_rsize;
++ unsigned int vol_wsize;
+ unsigned int bsize;
+ unsigned int rasize;
+ unsigned int rsize;
+diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
+index a2dbebd13720b..71fe5aa52630d 100644
+--- a/fs/smb/client/smb1ops.c
++++ b/fs/smb/client/smb1ops.c
+@@ -437,8 +437,8 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
+ unsigned int wsize;
+
+ /* start with specified wsize, or default */
+- if (ctx->wsize)
+- wsize = ctx->wsize;
++ if (ctx->got_wsize)
++ wsize = ctx->vol_wsize;
+ else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
+ wsize = CIFS_DEFAULT_IOSIZE;
+ else
+@@ -490,7 +490,7 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
+ else
+ defsize = server->maxBuf - sizeof(READ_RSP);
+
+- rsize = ctx->rsize ? ctx->rsize : defsize;
++ rsize = ctx->got_rsize ? ctx->vol_rsize : defsize;
+
+ /*
+ * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to
+diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
+index ff50cdfde5fe4..74bcc51ccd32f 100644
+--- a/fs/smb/client/smb2ops.c
++++ b/fs/smb/client/smb2ops.c
+@@ -467,6 +467,17 @@ smb2_negotiate(const unsigned int xid,
+ return rc;
+ }
+
++static inline unsigned int
++prevent_zero_iosize(unsigned int size, const char *type)
++{
++ if (size == 0) {
++ cifs_dbg(VFS, "SMB: Zero %ssize calculated, using minimum value %u\n",
++ type, CIFS_MIN_DEFAULT_IOSIZE);
++ return CIFS_MIN_DEFAULT_IOSIZE;
++ }
++ return size;
++}
++
+ static unsigned int
+ smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
+ {
+@@ -474,12 +485,12 @@ smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
+ unsigned int wsize;
+
+ /* start with specified wsize, or default */
+- wsize = ctx->wsize ? ctx->wsize : CIFS_DEFAULT_IOSIZE;
++ wsize = ctx->got_wsize ? ctx->vol_wsize : CIFS_DEFAULT_IOSIZE;
+ wsize = min_t(unsigned int, wsize, server->max_write);
+ if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
+ wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE);
+
+- return wsize;
++ return prevent_zero_iosize(wsize, "w");
+ }
+
+ static unsigned int
+@@ -489,7 +500,7 @@ smb3_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
+ unsigned int wsize;
+
+ /* start with specified wsize, or default */
+- wsize = ctx->wsize ? ctx->wsize : SMB3_DEFAULT_IOSIZE;
++ wsize = ctx->got_wsize ? ctx->vol_wsize : SMB3_DEFAULT_IOSIZE;
+ wsize = min_t(unsigned int, wsize, server->max_write);
+ #ifdef CONFIG_CIFS_SMB_DIRECT
+ if (server->rdma) {
+@@ -511,7 +522,7 @@ smb3_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
+ if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
+ wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE);
+
+- return wsize;
++ return prevent_zero_iosize(wsize, "w");
+ }
+
+ static unsigned int
+@@ -521,13 +532,13 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
+ unsigned int rsize;
+
+ /* start with specified rsize, or default */
+- rsize = ctx->rsize ? ctx->rsize : CIFS_DEFAULT_IOSIZE;
++ rsize = ctx->got_rsize ? ctx->vol_rsize : CIFS_DEFAULT_IOSIZE;
+ rsize = min_t(unsigned int, rsize, server->max_read);
+
+ if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
+ rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE);
+
+- return rsize;
++ return prevent_zero_iosize(rsize, "r");
+ }
+
+ static unsigned int
+@@ -537,7 +548,7 @@ smb3_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
+ unsigned int rsize;
+
+ /* start with specified rsize, or default */
+- rsize = ctx->rsize ? ctx->rsize : SMB3_DEFAULT_IOSIZE;
++ rsize = ctx->got_rsize ? ctx->vol_rsize : SMB3_DEFAULT_IOSIZE;
+ rsize = min_t(unsigned int, rsize, server->max_read);
+ #ifdef CONFIG_CIFS_SMB_DIRECT
+ if (server->rdma) {
+@@ -560,7 +571,7 @@ smb3_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
+ if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
+ rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE);
+
+- return rsize;
++ return prevent_zero_iosize(rsize, "r");
+ }
+
+ /*
+diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h
+index 9f272cc8f5660..0a4ca286f4169 100644
+--- a/fs/smb/common/smb2pdu.h
++++ b/fs/smb/common/smb2pdu.h
+@@ -95,6 +95,9 @@
+ */
+ #define SMB3_DEFAULT_IOSIZE (4 * 1024 * 1024)
+
++/* According to MS-SMB2 specification The minimum recommended value is 65536.*/
++#define CIFS_MIN_DEFAULT_IOSIZE (65536)
++
+ /*
+ * SMB2 Header Definition
+ *
+--
+2.39.5
+
--- /dev/null
+From d0632d61a123846a420317c981d207a673188115 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Apr 2025 20:26:25 +0100
+Subject: smb: server: smb2pdu: check return value of xa_store()
+
+From: Salah Triki <salah.triki@gmail.com>
+
+[ Upstream commit af5226abb40cae959f424f7ca614787a1c87ce48 ]
+
+xa_store() may fail so check its return value and return error code if
+error occurred.
+
+Signed-off-by: Salah Triki <salah.triki@gmail.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/server/smb2pdu.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
+index f0760d786502f..08d9a7cfba8cd 100644
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -1448,7 +1448,7 @@ static int ntlm_authenticate(struct ksmbd_work *work,
+ {
+ struct ksmbd_conn *conn = work->conn;
+ struct ksmbd_session *sess = work->sess;
+- struct channel *chann = NULL;
++ struct channel *chann = NULL, *old;
+ struct ksmbd_user *user;
+ u64 prev_id;
+ int sz, rc;
+@@ -1560,7 +1560,12 @@ static int ntlm_authenticate(struct ksmbd_work *work,
+ return -ENOMEM;
+
+ chann->conn = conn;
+- xa_store(&sess->ksmbd_chann_list, (long)conn, chann, KSMBD_DEFAULT_GFP);
++ old = xa_store(&sess->ksmbd_chann_list, (long)conn, chann,
++ KSMBD_DEFAULT_GFP);
++ if (xa_is_err(old)) {
++ kfree(chann);
++ return xa_err(old);
++ }
+ }
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 5139f7cff4f7444a914fb671bc076374d4bd2328 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Feb 2025 19:00:04 +0000
+Subject: soc: apple: rtkit: Implement OSLog buffers properly
+
+From: Hector Martin <marcan@marcan.st>
+
+[ Upstream commit a06398687065e0c334dc5fc4d2778b5b87292e43 ]
+
+Apparently nobody can figure out where the old logic came from, but it
+seems like it has never been actually used on any supported firmware to
+this day. OSLog buffers were apparently never requested.
+
+But starting with 13.3, we actually need this implemented properly for
+MTP (and later AOP) to work, so let's actually do that.
+
+Signed-off-by: Hector Martin <marcan@marcan.st>
+Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
+Link: https://lore.kernel.org/r/20250226-apple-soc-misc-v2-2-c3ec37f9021b@svenpeter.dev
+Signed-off-by: Sven Peter <sven@svenpeter.dev>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/apple/rtkit-internal.h | 1 +
+ drivers/soc/apple/rtkit.c | 56 ++++++++++++++++++------------
+ 2 files changed, 35 insertions(+), 22 deletions(-)
+
+diff --git a/drivers/soc/apple/rtkit-internal.h b/drivers/soc/apple/rtkit-internal.h
+index 27c9fa745fd52..b8d5244678f01 100644
+--- a/drivers/soc/apple/rtkit-internal.h
++++ b/drivers/soc/apple/rtkit-internal.h
+@@ -44,6 +44,7 @@ struct apple_rtkit {
+
+ struct apple_rtkit_shmem ioreport_buffer;
+ struct apple_rtkit_shmem crashlog_buffer;
++ struct apple_rtkit_shmem oslog_buffer;
+
+ struct apple_rtkit_shmem syslog_buffer;
+ char *syslog_msg_buffer;
+diff --git a/drivers/soc/apple/rtkit.c b/drivers/soc/apple/rtkit.c
+index 00d59a81db88b..45ccbe2cbcd63 100644
+--- a/drivers/soc/apple/rtkit.c
++++ b/drivers/soc/apple/rtkit.c
+@@ -66,8 +66,9 @@ enum {
+ #define APPLE_RTKIT_SYSLOG_MSG_SIZE GENMASK_ULL(31, 24)
+
+ #define APPLE_RTKIT_OSLOG_TYPE GENMASK_ULL(63, 56)
+-#define APPLE_RTKIT_OSLOG_INIT 1
+-#define APPLE_RTKIT_OSLOG_ACK 3
++#define APPLE_RTKIT_OSLOG_BUFFER_REQUEST 1
++#define APPLE_RTKIT_OSLOG_SIZE GENMASK_ULL(55, 36)
++#define APPLE_RTKIT_OSLOG_IOVA GENMASK_ULL(35, 0)
+
+ #define APPLE_RTKIT_MIN_SUPPORTED_VERSION 11
+ #define APPLE_RTKIT_MAX_SUPPORTED_VERSION 12
+@@ -251,15 +252,21 @@ static int apple_rtkit_common_rx_get_buffer(struct apple_rtkit *rtk,
+ struct apple_rtkit_shmem *buffer,
+ u8 ep, u64 msg)
+ {
+- size_t n_4kpages = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_SIZE, msg);
+ u64 reply;
+ int err;
+
++ /* The different size vs. IOVA shifts look odd but are indeed correct this way */
++ if (ep == APPLE_RTKIT_EP_OSLOG) {
++ buffer->size = FIELD_GET(APPLE_RTKIT_OSLOG_SIZE, msg);
++ buffer->iova = FIELD_GET(APPLE_RTKIT_OSLOG_IOVA, msg) << 12;
++ } else {
++ buffer->size = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_SIZE, msg) << 12;
++ buffer->iova = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_IOVA, msg);
++ }
++
+ buffer->buffer = NULL;
+ buffer->iomem = NULL;
+ buffer->is_mapped = false;
+- buffer->iova = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_IOVA, msg);
+- buffer->size = n_4kpages << 12;
+
+ dev_dbg(rtk->dev, "RTKit: buffer request for 0x%zx bytes at %pad\n",
+ buffer->size, &buffer->iova);
+@@ -284,11 +291,21 @@ static int apple_rtkit_common_rx_get_buffer(struct apple_rtkit *rtk,
+ }
+
+ if (!buffer->is_mapped) {
+- reply = FIELD_PREP(APPLE_RTKIT_SYSLOG_TYPE,
+- APPLE_RTKIT_BUFFER_REQUEST);
+- reply |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_SIZE, n_4kpages);
+- reply |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_IOVA,
+- buffer->iova);
++ /* oslog uses different fields and needs a shifted IOVA instead of size */
++ if (ep == APPLE_RTKIT_EP_OSLOG) {
++ reply = FIELD_PREP(APPLE_RTKIT_OSLOG_TYPE,
++ APPLE_RTKIT_OSLOG_BUFFER_REQUEST);
++ reply |= FIELD_PREP(APPLE_RTKIT_OSLOG_SIZE, buffer->size);
++ reply |= FIELD_PREP(APPLE_RTKIT_OSLOG_IOVA,
++ buffer->iova >> 12);
++ } else {
++ reply = FIELD_PREP(APPLE_RTKIT_SYSLOG_TYPE,
++ APPLE_RTKIT_BUFFER_REQUEST);
++ reply |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_SIZE,
++ buffer->size >> 12);
++ reply |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_IOVA,
++ buffer->iova);
++ }
+ apple_rtkit_send_message(rtk, ep, reply, NULL, false);
+ }
+
+@@ -482,25 +499,18 @@ static void apple_rtkit_syslog_rx(struct apple_rtkit *rtk, u64 msg)
+ }
+ }
+
+-static void apple_rtkit_oslog_rx_init(struct apple_rtkit *rtk, u64 msg)
+-{
+- u64 ack;
+-
+- dev_dbg(rtk->dev, "RTKit: oslog init: msg: 0x%llx\n", msg);
+- ack = FIELD_PREP(APPLE_RTKIT_OSLOG_TYPE, APPLE_RTKIT_OSLOG_ACK);
+- apple_rtkit_send_message(rtk, APPLE_RTKIT_EP_OSLOG, ack, NULL, false);
+-}
+-
+ static void apple_rtkit_oslog_rx(struct apple_rtkit *rtk, u64 msg)
+ {
+ u8 type = FIELD_GET(APPLE_RTKIT_OSLOG_TYPE, msg);
+
+ switch (type) {
+- case APPLE_RTKIT_OSLOG_INIT:
+- apple_rtkit_oslog_rx_init(rtk, msg);
++ case APPLE_RTKIT_OSLOG_BUFFER_REQUEST:
++ apple_rtkit_common_rx_get_buffer(rtk, &rtk->oslog_buffer,
++ APPLE_RTKIT_EP_OSLOG, msg);
+ break;
+ default:
+- dev_warn(rtk->dev, "RTKit: Unknown oslog message: %llx\n", msg);
++ dev_warn(rtk->dev, "RTKit: Unknown oslog message: %llx\n",
++ msg);
+ }
+ }
+
+@@ -710,6 +720,7 @@ int apple_rtkit_reinit(struct apple_rtkit *rtk)
+
+ apple_rtkit_free_buffer(rtk, &rtk->ioreport_buffer);
+ apple_rtkit_free_buffer(rtk, &rtk->crashlog_buffer);
++ apple_rtkit_free_buffer(rtk, &rtk->oslog_buffer);
+ apple_rtkit_free_buffer(rtk, &rtk->syslog_buffer);
+
+ kfree(rtk->syslog_msg_buffer);
+@@ -890,6 +901,7 @@ void apple_rtkit_free(struct apple_rtkit *rtk)
+
+ apple_rtkit_free_buffer(rtk, &rtk->ioreport_buffer);
+ apple_rtkit_free_buffer(rtk, &rtk->crashlog_buffer);
++ apple_rtkit_free_buffer(rtk, &rtk->oslog_buffer);
+ apple_rtkit_free_buffer(rtk, &rtk->syslog_buffer);
+
+ kfree(rtk->syslog_msg_buffer);
+--
+2.39.5
+
--- /dev/null
+From 06f4bb55662aac15f78ebfe199ac47a671881708 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Feb 2025 19:00:05 +0000
+Subject: soc: apple: rtkit: Use high prio work queue
+
+From: Janne Grunau <j@jannau.net>
+
+[ Upstream commit 22af2fac88fa5dbc310bfe7d0b66d4de3ac47305 ]
+
+rtkit messages as communication with the DCP firmware for framebuffer
+swaps or input events are time critical so use WQ_HIGHPRI to prevent
+user space CPU load to increase latency.
+With kwin_wayland 6's explicit sync mode user space load was able to
+delay the IOMFB rtkit communication enough to miss vsync for surface
+swaps. Minimal test scenario is constantly resizing a glxgears
+Xwayland window.
+
+Signed-off-by: Janne Grunau <j@jannau.net>
+Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
+Link: https://lore.kernel.org/r/20250226-apple-soc-misc-v2-3-c3ec37f9021b@svenpeter.dev
+Signed-off-by: Sven Peter <sven@svenpeter.dev>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/apple/rtkit.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/apple/rtkit.c b/drivers/soc/apple/rtkit.c
+index e6d940292c9fb..00d59a81db88b 100644
+--- a/drivers/soc/apple/rtkit.c
++++ b/drivers/soc/apple/rtkit.c
+@@ -667,7 +667,7 @@ struct apple_rtkit *apple_rtkit_init(struct device *dev, void *cookie,
+ rtk->mbox->rx = apple_rtkit_rx;
+ rtk->mbox->cookie = rtk;
+
+- rtk->wq = alloc_ordered_workqueue("rtkit-%s", WQ_MEM_RECLAIM,
++ rtk->wq = alloc_ordered_workqueue("rtkit-%s", WQ_HIGHPRI | WQ_MEM_RECLAIM,
+ dev_name(rtk->dev));
+ if (!rtk->wq) {
+ ret = -ENOMEM;
+--
+2.39.5
+
--- /dev/null
+From 24b4b52aa2a2e39a57c9c9e12f1b455cd5dd14f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Feb 2025 11:00:05 +0100
+Subject: soc: mediatek: mtk-mutex: Add DPI1 SOF/EOF to MT8188 mutex tables
+
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+[ Upstream commit 694e0b7c1747603243da874de9cbbf8cb806ca44 ]
+
+MT8188 uses DPI1 to output to the HDMI controller: add the
+Start of Frame and End of Frame configuration for the DPI1
+IP to the tables to unblock generation and sending of these
+signals to the GCE.
+
+Link: https://lore.kernel.org/r/20250212100012.33001-2-angelogioacchino.delregno@collabora.com
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/mediatek/mtk-mutex.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
+index 5250c1d702eb9..aaa965d4b050a 100644
+--- a/drivers/soc/mediatek/mtk-mutex.c
++++ b/drivers/soc/mediatek/mtk-mutex.c
+@@ -155,6 +155,7 @@
+ #define MT8188_MUTEX_MOD_DISP1_VPP_MERGE3 23
+ #define MT8188_MUTEX_MOD_DISP1_VPP_MERGE4 24
+ #define MT8188_MUTEX_MOD_DISP1_DISP_MIXER 30
++#define MT8188_MUTEX_MOD_DISP1_DPI1 38
+ #define MT8188_MUTEX_MOD_DISP1_DP_INTF1 39
+
+ #define MT8195_MUTEX_MOD_DISP_OVL0 0
+@@ -289,6 +290,7 @@
+ #define MT8188_MUTEX_SOF_DSI0 1
+ #define MT8188_MUTEX_SOF_DP_INTF0 3
+ #define MT8188_MUTEX_SOF_DP_INTF1 4
++#define MT8188_MUTEX_SOF_DPI1 5
+ #define MT8195_MUTEX_SOF_DSI0 1
+ #define MT8195_MUTEX_SOF_DSI1 2
+ #define MT8195_MUTEX_SOF_DP_INTF0 3
+@@ -301,6 +303,7 @@
+ #define MT8188_MUTEX_EOF_DSI0 (MT8188_MUTEX_SOF_DSI0 << 7)
+ #define MT8188_MUTEX_EOF_DP_INTF0 (MT8188_MUTEX_SOF_DP_INTF0 << 7)
+ #define MT8188_MUTEX_EOF_DP_INTF1 (MT8188_MUTEX_SOF_DP_INTF1 << 7)
++#define MT8188_MUTEX_EOF_DPI1 (MT8188_MUTEX_SOF_DPI1 << 7)
+ #define MT8195_MUTEX_EOF_DSI0 (MT8195_MUTEX_SOF_DSI0 << 7)
+ #define MT8195_MUTEX_EOF_DSI1 (MT8195_MUTEX_SOF_DSI1 << 7)
+ #define MT8195_MUTEX_EOF_DP_INTF0 (MT8195_MUTEX_SOF_DP_INTF0 << 7)
+@@ -472,6 +475,7 @@ static const u8 mt8188_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+ [DDP_COMPONENT_PWM0] = MT8188_MUTEX_MOD2_DISP_PWM0,
+ [DDP_COMPONENT_DP_INTF0] = MT8188_MUTEX_MOD_DISP_DP_INTF0,
+ [DDP_COMPONENT_DP_INTF1] = MT8188_MUTEX_MOD_DISP1_DP_INTF1,
++ [DDP_COMPONENT_DPI1] = MT8188_MUTEX_MOD_DISP1_DPI1,
+ [DDP_COMPONENT_ETHDR_MIXER] = MT8188_MUTEX_MOD_DISP1_DISP_MIXER,
+ [DDP_COMPONENT_MDP_RDMA0] = MT8188_MUTEX_MOD_DISP1_MDP_RDMA0,
+ [DDP_COMPONENT_MDP_RDMA1] = MT8188_MUTEX_MOD_DISP1_MDP_RDMA1,
+@@ -686,6 +690,8 @@ static const u16 mt8188_mutex_sof[DDP_MUTEX_SOF_MAX] = {
+ [MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
+ [MUTEX_SOF_DSI0] =
+ MT8188_MUTEX_SOF_DSI0 | MT8188_MUTEX_EOF_DSI0,
++ [MUTEX_SOF_DPI1] =
++ MT8188_MUTEX_SOF_DPI1 | MT8188_MUTEX_EOF_DPI1,
+ [MUTEX_SOF_DP_INTF0] =
+ MT8188_MUTEX_SOF_DP_INTF0 | MT8188_MUTEX_EOF_DP_INTF0,
+ [MUTEX_SOF_DP_INTF1] =
+--
+2.39.5
+
--- /dev/null
+From 3d24971a7f3821813f5d462943422e3cf8279ed8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Mar 2025 22:14:02 +0100
+Subject: soc: samsung: include linux/array_size.h where needed
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit 4c57930f68d90e0d52c396d058cfa9ed8447a6c4 ]
+
+This does not necessarily get included through asm/io.h:
+
+drivers/soc/samsung/exynos3250-pmu.c:120:18: error: use of undeclared identifier 'ARRAY_SIZE'
+ 120 | for (i = 0; i < ARRAY_SIZE(exynos3250_list_feed); i++) {
+ | ^
+drivers/soc/samsung/exynos5250-pmu.c:162:18: error: use of undeclared identifier 'ARRAY_SIZE'
+ 162 | for (i = 0; i < ARRAY_SIZE(exynos5_list_both_cnt_feed); i++) {
+ | ^
+
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Link: https://lore.kernel.org/r/20250305211446.43772-1-arnd@kernel.org
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/samsung/exynos-asv.c | 1 +
+ drivers/soc/samsung/exynos-chipid.c | 1 +
+ drivers/soc/samsung/exynos-pmu.c | 1 +
+ drivers/soc/samsung/exynos-usi.c | 1 +
+ drivers/soc/samsung/exynos3250-pmu.c | 1 +
+ drivers/soc/samsung/exynos5250-pmu.c | 1 +
+ drivers/soc/samsung/exynos5420-pmu.c | 1 +
+ 7 files changed, 7 insertions(+)
+
+diff --git a/drivers/soc/samsung/exynos-asv.c b/drivers/soc/samsung/exynos-asv.c
+index 97006cc3b9461..8e681f5195264 100644
+--- a/drivers/soc/samsung/exynos-asv.c
++++ b/drivers/soc/samsung/exynos-asv.c
+@@ -9,6 +9,7 @@
+ * Samsung Exynos SoC Adaptive Supply Voltage support
+ */
+
++#include <linux/array_size.h>
+ #include <linux/cpu.h>
+ #include <linux/device.h>
+ #include <linux/energy_model.h>
+diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c
+index bba8d86ae1bb0..dedfe6d0fb3f3 100644
+--- a/drivers/soc/samsung/exynos-chipid.c
++++ b/drivers/soc/samsung/exynos-chipid.c
+@@ -12,6 +12,7 @@
+ * Samsung Exynos SoC Adaptive Supply Voltage and Chip ID support
+ */
+
++#include <linux/array_size.h>
+ #include <linux/device.h>
+ #include <linux/errno.h>
+ #include <linux/mfd/syscon.h>
+diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c
+index dd5256e5aae1a..c40313886a012 100644
+--- a/drivers/soc/samsung/exynos-pmu.c
++++ b/drivers/soc/samsung/exynos-pmu.c
+@@ -5,6 +5,7 @@
+ //
+ // Exynos - CPU PMU(Power Management Unit) support
+
++#include <linux/array_size.h>
+ #include <linux/arm-smccc.h>
+ #include <linux/of.h>
+ #include <linux/of_address.h>
+diff --git a/drivers/soc/samsung/exynos-usi.c b/drivers/soc/samsung/exynos-usi.c
+index 114352695ac2b..5a93a68dba87f 100644
+--- a/drivers/soc/samsung/exynos-usi.c
++++ b/drivers/soc/samsung/exynos-usi.c
+@@ -6,6 +6,7 @@
+ * Samsung Exynos USI driver (Universal Serial Interface).
+ */
+
++#include <linux/array_size.h>
+ #include <linux/clk.h>
+ #include <linux/mfd/syscon.h>
+ #include <linux/module.h>
+diff --git a/drivers/soc/samsung/exynos3250-pmu.c b/drivers/soc/samsung/exynos3250-pmu.c
+index 30f230ed1769c..4bad12a995422 100644
+--- a/drivers/soc/samsung/exynos3250-pmu.c
++++ b/drivers/soc/samsung/exynos3250-pmu.c
+@@ -5,6 +5,7 @@
+ //
+ // Exynos3250 - CPU PMU (Power Management Unit) support
+
++#include <linux/array_size.h>
+ #include <linux/soc/samsung/exynos-regs-pmu.h>
+ #include <linux/soc/samsung/exynos-pmu.h>
+
+diff --git a/drivers/soc/samsung/exynos5250-pmu.c b/drivers/soc/samsung/exynos5250-pmu.c
+index 7a2d50be6b4ac..2ae5c3e1b07a3 100644
+--- a/drivers/soc/samsung/exynos5250-pmu.c
++++ b/drivers/soc/samsung/exynos5250-pmu.c
+@@ -5,6 +5,7 @@
+ //
+ // Exynos5250 - CPU PMU (Power Management Unit) support
+
++#include <linux/array_size.h>
+ #include <linux/soc/samsung/exynos-regs-pmu.h>
+ #include <linux/soc/samsung/exynos-pmu.h>
+
+diff --git a/drivers/soc/samsung/exynos5420-pmu.c b/drivers/soc/samsung/exynos5420-pmu.c
+index 6fedcd78cb451..58a2209795f78 100644
+--- a/drivers/soc/samsung/exynos5420-pmu.c
++++ b/drivers/soc/samsung/exynos5420-pmu.c
+@@ -5,6 +5,7 @@
+ //
+ // Exynos5420 - CPU PMU (Power Management Unit) support
+
++#include <linux/array_size.h>
+ #include <linux/pm.h>
+ #include <linux/soc/samsung/exynos-regs-pmu.h>
+ #include <linux/soc/samsung/exynos-pmu.h>
+--
+2.39.5
+
--- /dev/null
+From 1c8b298976d56424d8f8ed0cb2d2b21f9136240c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jan 2025 12:17:26 -0600
+Subject: soc: ti: k3-socinfo: Do not use syscon helper to build regmap
+
+From: Andrew Davis <afd@ti.com>
+
+[ Upstream commit a5caf03188e44388e8c618dcbe5fffad1a249385 ]
+
+The syscon helper device_node_to_regmap() is used to fetch a regmap
+registered to a device node. It also currently creates this regmap
+if the node did not already have a regmap associated with it. This
+should only be used on "syscon" nodes. This driver is not such a
+device and instead uses device_node_to_regmap() on its own node as
+a hacky way to create a regmap for itself.
+
+This will not work going forward and so we should create our regmap
+the normal way by defining our regmap_config, fetching our memory
+resource, then using the normal regmap_init_mmio() function.
+
+Signed-off-by: Andrew Davis <afd@ti.com>
+Link: https://lore.kernel.org/r/20250123181726.597144-1-afd@ti.com
+Signed-off-by: Nishanth Menon <nm@ti.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/ti/k3-socinfo.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/soc/ti/k3-socinfo.c b/drivers/soc/ti/k3-socinfo.c
+index 4fb0f0a248288..704039eb3c078 100644
+--- a/drivers/soc/ti/k3-socinfo.c
++++ b/drivers/soc/ti/k3-socinfo.c
+@@ -105,6 +105,12 @@ k3_chipinfo_variant_to_sr(unsigned int partno, unsigned int variant,
+ return -ENODEV;
+ }
+
++static const struct regmap_config k3_chipinfo_regmap_cfg = {
++ .reg_bits = 32,
++ .val_bits = 32,
++ .reg_stride = 4,
++};
++
+ static int k3_chipinfo_probe(struct platform_device *pdev)
+ {
+ struct device_node *node = pdev->dev.of_node;
+@@ -112,13 +118,18 @@ static int k3_chipinfo_probe(struct platform_device *pdev)
+ struct device *dev = &pdev->dev;
+ struct soc_device *soc_dev;
+ struct regmap *regmap;
++ void __iomem *base;
+ u32 partno_id;
+ u32 variant;
+ u32 jtag_id;
+ u32 mfg;
+ int ret;
+
+- regmap = device_node_to_regmap(node);
++ base = devm_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(base))
++ return PTR_ERR(base);
++
++ regmap = regmap_init_mmio(dev, base, &k3_chipinfo_regmap_cfg);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+--
+2.39.5
+
--- /dev/null
+From 1e61312314a45c69ece240ab1d0b4e472fe3b9e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Feb 2025 12:28:36 +0530
+Subject: soundwire: amd: change the soundwire wake enable/disable sequence
+
+From: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
+
+[ Upstream commit dcc48a73eae7f791b1a6856ea1bcc4079282c88d ]
+
+During runtime suspend scenario, SoundWire wake should be enabled and
+during system level suspend scenario SoundWire wake should be disabled.
+
+Implement the SoundWire wake enable/disable sequence as per design flow
+for SoundWire poweroff mode.
+
+Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
+Link: https://lore.kernel.org/r/20250207065841.4718-2-Vijendar.Mukunda@amd.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soundwire/amd_manager.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/soundwire/amd_manager.c b/drivers/soundwire/amd_manager.c
+index 0d01849c35861..e3d5e6c1d582c 100644
+--- a/drivers/soundwire/amd_manager.c
++++ b/drivers/soundwire/amd_manager.c
+@@ -1110,6 +1110,7 @@ static int __maybe_unused amd_suspend(struct device *dev)
+ amd_sdw_wake_enable(amd_manager, false);
+ return amd_sdw_clock_stop(amd_manager);
+ } else if (amd_manager->power_mode_mask & AMD_SDW_POWER_OFF_MODE) {
++ amd_sdw_wake_enable(amd_manager, false);
+ /*
+ * As per hardware programming sequence on AMD platforms,
+ * clock stop should be invoked first before powering-off
+@@ -1137,6 +1138,7 @@ static int __maybe_unused amd_suspend_runtime(struct device *dev)
+ amd_sdw_wake_enable(amd_manager, true);
+ return amd_sdw_clock_stop(amd_manager);
+ } else if (amd_manager->power_mode_mask & AMD_SDW_POWER_OFF_MODE) {
++ amd_sdw_wake_enable(amd_manager, true);
+ ret = amd_sdw_clock_stop(amd_manager);
+ if (ret)
+ return ret;
+--
+2.39.5
+
--- /dev/null
+From 1a489af338c6d57bfa7bb5ed5628da4ac89654d5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Feb 2025 15:42:31 +0800
+Subject: soundwire: cadence_master: set frame shape and divider based on
+ actual clk freq
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Bard Liao <yung-chuan.liao@linux.intel.com>
+
+[ Upstream commit e738d77f78b3ac085dfb51be414e93464abba7ec ]
+
+Frame shape and curr_dr_freq could be updated by sdw_compute_bus_params().
+Peripherals will set curr_dr_freq as their frequency. Managers
+should do the same. Then update frame shape according to the actual
+bus frequency.
+
+Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
+Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
+Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
+Link: https://lore.kernel.org/r/20250205074232.87537-2-yung-chuan.liao@linux.intel.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soundwire/cadence_master.c | 22 +++++++++++++++++++---
+ 1 file changed, 19 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c
+index 05652e983539b..6f2b5ec5c87c6 100644
+--- a/drivers/soundwire/cadence_master.c
++++ b/drivers/soundwire/cadence_master.c
+@@ -1341,7 +1341,7 @@ static u32 cdns_set_initial_frame_shape(int n_rows, int n_cols)
+ return val;
+ }
+
+-static void cdns_init_clock_ctrl(struct sdw_cdns *cdns)
++static int cdns_init_clock_ctrl(struct sdw_cdns *cdns)
+ {
+ struct sdw_bus *bus = &cdns->bus;
+ struct sdw_master_prop *prop = &bus->prop;
+@@ -1355,14 +1355,25 @@ static void cdns_init_clock_ctrl(struct sdw_cdns *cdns)
+ prop->default_row,
+ prop->default_col);
+
++ if (!prop->default_frame_rate || !prop->default_row) {
++ dev_err(cdns->dev, "Default frame_rate %d or row %d is invalid\n",
++ prop->default_frame_rate, prop->default_row);
++ return -EINVAL;
++ }
++
+ /* Set clock divider */
+- divider = (prop->mclk_freq / prop->max_clk_freq) - 1;
++ divider = (prop->mclk_freq * SDW_DOUBLE_RATE_FACTOR /
++ bus->params.curr_dr_freq) - 1;
+
+ cdns_updatel(cdns, CDNS_MCP_CLK_CTRL0,
+ CDNS_MCP_CLK_MCLKD_MASK, divider);
+ cdns_updatel(cdns, CDNS_MCP_CLK_CTRL1,
+ CDNS_MCP_CLK_MCLKD_MASK, divider);
+
++ /* Set frame shape base on the actual bus frequency. */
++ prop->default_col = bus->params.curr_dr_freq /
++ prop->default_frame_rate / prop->default_row;
++
+ /*
+ * Frame shape changes after initialization have to be done
+ * with the bank switch mechanism
+@@ -1375,6 +1386,8 @@ static void cdns_init_clock_ctrl(struct sdw_cdns *cdns)
+ ssp_interval = prop->default_frame_rate / SDW_CADENCE_GSYNC_HZ;
+ cdns_writel(cdns, CDNS_MCP_SSP_CTRL0, ssp_interval);
+ cdns_writel(cdns, CDNS_MCP_SSP_CTRL1, ssp_interval);
++
++ return 0;
+ }
+
+ /**
+@@ -1383,9 +1396,12 @@ static void cdns_init_clock_ctrl(struct sdw_cdns *cdns)
+ */
+ int sdw_cdns_init(struct sdw_cdns *cdns)
+ {
++ int ret;
+ u32 val;
+
+- cdns_init_clock_ctrl(cdns);
++ ret = cdns_init_clock_ctrl(cdns);
++ if (ret)
++ return ret;
+
+ sdw_cdns_check_self_clearing_bits(cdns, __func__, false, 0);
+
+--
+2.39.5
+
--- /dev/null
+From a45f064a93e437c9911c653c95eb2960958cc3e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Mar 2025 13:57:53 +0100
+Subject: spi-rockchip: Fix register out of bounds access
+
+From: Luis de Arquer <luis.dearquer@inertim.com>
+
+[ Upstream commit 7a874e8b54ea21094f7fd2d428b164394c6cb316 ]
+
+Do not write native chip select stuff for GPIO chip selects.
+GPIOs can be numbered much higher than native CS.
+Also, it makes no sense.
+
+Signed-off-by: Luis de Arquer <luis.dearquer@inertim.com>
+Link: https://patch.msgid.link/365ccddfba110549202b3520f4401a6a936e82a8.camel@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-rockchip.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
+index 40a64a598a749..5008489d6fac8 100644
+--- a/drivers/spi/spi-rockchip.c
++++ b/drivers/spi/spi-rockchip.c
+@@ -547,7 +547,7 @@ static int rockchip_spi_config(struct rockchip_spi *rs,
+ cr0 |= (spi->mode & 0x3U) << CR0_SCPH_OFFSET;
+ if (spi->mode & SPI_LSB_FIRST)
+ cr0 |= CR0_FBM_LSB << CR0_FBM_OFFSET;
+- if (spi->mode & SPI_CS_HIGH)
++ if ((spi->mode & SPI_CS_HIGH) && !(spi_get_csgpiod(spi, 0)))
+ cr0 |= BIT(spi_get_chipselect(spi, 0)) << CR0_SOI_OFFSET;
+
+ if (xfer->rx_buf && xfer->tx_buf)
+--
+2.39.5
+
--- /dev/null
+From 58654f04f132cc05806837505578503aa9380244 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Mar 2025 23:46:06 -0600
+Subject: spi: spi-mux: Fix coverity issue, unchecked return value
+
+From: Sergio Perez Gonzalez <sperezglz@gmail.com>
+
+[ Upstream commit 5a5fc308418aca275a898d638bc38c093d101855 ]
+
+The return value of spi_setup() is not captured within
+spi_mux_select() and it is assumed to be always success.
+
+CID: 1638374
+
+Signed-off-by: Sergio Perez Gonzalez <sperezglz@gmail.com>
+Link: https://patch.msgid.link/20250316054651.13242-1-sperezglz@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-mux.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/drivers/spi/spi-mux.c b/drivers/spi/spi-mux.c
+index c02c4204442f5..0eb35c4e3987e 100644
+--- a/drivers/spi/spi-mux.c
++++ b/drivers/spi/spi-mux.c
+@@ -68,9 +68,7 @@ static int spi_mux_select(struct spi_device *spi)
+
+ priv->current_cs = spi_get_chipselect(spi, 0);
+
+- spi_setup(priv->spi);
+-
+- return 0;
++ return spi_setup(priv->spi);
+ }
+
+ static int spi_mux_setup(struct spi_device *spi)
+--
+2.39.5
+
--- /dev/null
+From 11edf8708c24cf58a15aeea06c43c610d6a00130 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jan 2025 17:41:30 -0500
+Subject: spi: zynqmp-gqspi: Always acknowledge interrupts
+
+From: Sean Anderson <sean.anderson@linux.dev>
+
+[ Upstream commit 89785306453ce6d949e783f6936821a0b7649ee2 ]
+
+RXEMPTY can cause an IRQ, even though we may not do anything about it
+(such as if we are waiting for more received data). We must still handle
+these IRQs because we can tell they were caused by the device.
+
+Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
+Link: https://patch.msgid.link/20250116224130.2684544-6-sean.anderson@linux.dev
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-zynqmp-gqspi.c | 20 ++++++++------------
+ 1 file changed, 8 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
+index b9df39e06e7cd..4b091b4d4ff37 100644
+--- a/drivers/spi/spi-zynqmp-gqspi.c
++++ b/drivers/spi/spi-zynqmp-gqspi.c
+@@ -799,7 +799,6 @@ static void zynqmp_process_dma_irq(struct zynqmp_qspi *xqspi)
+ static irqreturn_t zynqmp_qspi_irq(int irq, void *dev_id)
+ {
+ struct zynqmp_qspi *xqspi = (struct zynqmp_qspi *)dev_id;
+- irqreturn_t ret = IRQ_NONE;
+ u32 status, mask, dma_status = 0;
+
+ status = zynqmp_gqspi_read(xqspi, GQSPI_ISR_OFST);
+@@ -814,27 +813,24 @@ static irqreturn_t zynqmp_qspi_irq(int irq, void *dev_id)
+ dma_status);
+ }
+
+- if (mask & GQSPI_ISR_TXNOT_FULL_MASK) {
++ if (!mask && !dma_status)
++ return IRQ_NONE;
++
++ if (mask & GQSPI_ISR_TXNOT_FULL_MASK)
+ zynqmp_qspi_filltxfifo(xqspi, GQSPI_TX_FIFO_FILL);
+- ret = IRQ_HANDLED;
+- }
+
+- if (dma_status & GQSPI_QSPIDMA_DST_I_STS_DONE_MASK) {
++ if (dma_status & GQSPI_QSPIDMA_DST_I_STS_DONE_MASK)
+ zynqmp_process_dma_irq(xqspi);
+- ret = IRQ_HANDLED;
+- } else if (!(mask & GQSPI_IER_RXEMPTY_MASK) &&
+- (mask & GQSPI_IER_GENFIFOEMPTY_MASK)) {
++ else if (!(mask & GQSPI_IER_RXEMPTY_MASK) &&
++ (mask & GQSPI_IER_GENFIFOEMPTY_MASK))
+ zynqmp_qspi_readrxfifo(xqspi, GQSPI_RX_FIFO_FILL);
+- ret = IRQ_HANDLED;
+- }
+
+ if (xqspi->bytes_to_receive == 0 && xqspi->bytes_to_transfer == 0 &&
+ ((status & GQSPI_IRQ_MASK) == GQSPI_IRQ_MASK)) {
+ zynqmp_gqspi_write(xqspi, GQSPI_IDR_OFST, GQSPI_ISR_IDR_MASK);
+ complete(&xqspi->data_completion);
+- ret = IRQ_HANDLED;
+ }
+- return ret;
++ return IRQ_HANDLED;
+ }
+
+ /**
+--
+2.39.5
+
--- /dev/null
+From 5b21673a24281f10e600e1e7f0f9f174b4592e1e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Mar 2025 13:50:13 +0100
+Subject: staging: vchiq_arm: Create keep-alive thread during probe
+
+From: Stefan Wahren <wahrenst@gmx.net>
+
+[ Upstream commit 86bc8821700665ad3962f3ef0d93667f59cf7031 ]
+
+Creating the keep-alive thread in vchiq_platform_init_state have
+the following advantages:
+- abort driver probe if kthread_create fails (more consistent behavior)
+- make resource release process easier
+
+Since vchiq_keepalive_thread_func is defined below
+vchiq_platform_init_state, the latter must be moved.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+Link: https://lore.kernel.org/r/20250309125014.37166-5-wahrenst@gmx.net
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../interface/vchiq_arm/vchiq_arm.c | 69 +++++++++----------
+ 1 file changed, 34 insertions(+), 35 deletions(-)
+
+diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+index 97787002080a1..1a9432646b70a 100644
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -588,29 +588,6 @@ static int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state
+ return 0;
+ }
+
+-int
+-vchiq_platform_init_state(struct vchiq_state *state)
+-{
+- struct vchiq_arm_state *platform_state;
+-
+- platform_state = devm_kzalloc(state->dev, sizeof(*platform_state), GFP_KERNEL);
+- if (!platform_state)
+- return -ENOMEM;
+-
+- rwlock_init(&platform_state->susp_res_lock);
+-
+- init_completion(&platform_state->ka_evt);
+- atomic_set(&platform_state->ka_use_count, 0);
+- atomic_set(&platform_state->ka_use_ack_count, 0);
+- atomic_set(&platform_state->ka_release_count, 0);
+-
+- platform_state->state = state;
+-
+- state->platform_state = (struct opaque_platform_state *)platform_state;
+-
+- return 0;
+-}
+-
+ static struct vchiq_arm_state *vchiq_platform_get_arm_state(struct vchiq_state *state)
+ {
+ return (struct vchiq_arm_state *)state->platform_state;
+@@ -1358,6 +1335,39 @@ vchiq_keepalive_thread_func(void *v)
+ return 0;
+ }
+
++int
++vchiq_platform_init_state(struct vchiq_state *state)
++{
++ struct vchiq_arm_state *platform_state;
++ char threadname[16];
++
++ platform_state = devm_kzalloc(state->dev, sizeof(*platform_state), GFP_KERNEL);
++ if (!platform_state)
++ return -ENOMEM;
++
++ snprintf(threadname, sizeof(threadname), "vchiq-keep/%d",
++ state->id);
++ platform_state->ka_thread = kthread_create(&vchiq_keepalive_thread_func,
++ (void *)state, threadname);
++ if (IS_ERR(platform_state->ka_thread)) {
++ dev_err(state->dev, "couldn't create thread %s\n", threadname);
++ return PTR_ERR(platform_state->ka_thread);
++ }
++
++ rwlock_init(&platform_state->susp_res_lock);
++
++ init_completion(&platform_state->ka_evt);
++ atomic_set(&platform_state->ka_use_count, 0);
++ atomic_set(&platform_state->ka_use_ack_count, 0);
++ atomic_set(&platform_state->ka_release_count, 0);
++
++ platform_state->state = state;
++
++ state->platform_state = (struct opaque_platform_state *)platform_state;
++
++ return 0;
++}
++
+ int
+ vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service,
+ enum USE_TYPE_E use_type)
+@@ -1678,7 +1688,6 @@ void vchiq_platform_conn_state_changed(struct vchiq_state *state,
+ enum vchiq_connstate newstate)
+ {
+ struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state);
+- char threadname[16];
+
+ dev_dbg(state->dev, "suspend: %d: %s->%s\n",
+ state->id, get_conn_state_name(oldstate), get_conn_state_name(newstate));
+@@ -1693,17 +1702,7 @@ void vchiq_platform_conn_state_changed(struct vchiq_state *state,
+
+ arm_state->first_connect = 1;
+ write_unlock_bh(&arm_state->susp_res_lock);
+- snprintf(threadname, sizeof(threadname), "vchiq-keep/%d",
+- state->id);
+- arm_state->ka_thread = kthread_create(&vchiq_keepalive_thread_func,
+- (void *)state,
+- threadname);
+- if (IS_ERR(arm_state->ka_thread)) {
+- dev_err(state->dev, "suspend: Couldn't create thread %s\n",
+- threadname);
+- } else {
+- wake_up_process(arm_state->ka_thread);
+- }
++ wake_up_process(arm_state->ka_thread);
+ }
+
+ static const struct of_device_id vchiq_of_match[] = {
+--
+2.39.5
+
--- /dev/null
+From 50353376b010a007e52d9814b140a21bbce5d94f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Mar 2025 12:52:52 -0400
+Subject: SUNRPC: Don't allow waiting for exiting tasks
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+[ Upstream commit 14e41b16e8cb677bb440dca2edba8b041646c742 ]
+
+Once a task calls exit_signals() it can no longer be signalled. So do
+not allow it to do killable waits.
+
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sunrpc/sched.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
+index 9b45fbdc90cab..73bc39281ef5f 100644
+--- a/net/sunrpc/sched.c
++++ b/net/sunrpc/sched.c
+@@ -276,6 +276,8 @@ EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue);
+
+ static int rpc_wait_bit_killable(struct wait_bit_key *key, int mode)
+ {
++ if (unlikely(current->flags & PF_EXITING))
++ return -EINTR;
+ schedule();
+ if (signal_pending_state(mode, current))
+ return -ERESTARTSYS;
+--
+2.39.5
+
--- /dev/null
+From c9b4ac22c6d9576b608626c8f37f068180e60bc2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Mar 2025 19:35:01 -0400
+Subject: SUNRPC: rpc_clnt_set_transport() must not change the autobind setting
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+[ Upstream commit bf9be373b830a3e48117da5d89bb6145a575f880 ]
+
+The autobind setting was supposed to be determined in rpc_create(),
+since commit c2866763b402 ("SUNRPC: use sockaddr + size when creating
+remote transport endpoints").
+
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: Benjamin Coddington <bcodding@redhat.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sunrpc/clnt.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
+index 0090162ee8c35..17a4de75bfaf6 100644
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -270,9 +270,6 @@ static struct rpc_xprt *rpc_clnt_set_transport(struct rpc_clnt *clnt,
+ old = rcu_dereference_protected(clnt->cl_xprt,
+ lockdep_is_held(&clnt->cl_lock));
+
+- if (!xprt_bound(xprt))
+- clnt->cl_autobind = 1;
+-
+ clnt->cl_timeout = timeout;
+ rcu_assign_pointer(clnt->cl_xprt, xprt);
+ spin_unlock(&clnt->cl_lock);
+--
+2.39.5
+
--- /dev/null
+From baf4a5bd49614d0fc00e3ff7651ad3d6a9829dae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Mar 2025 19:05:48 -0400
+Subject: SUNRPC: rpcbind should never reset the port to the value '0'
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+[ Upstream commit 214c13e380ad7636631279f426387f9c4e3c14d9 ]
+
+If we already had a valid port number for the RPC service, then we
+should not allow the rpcbind client to set it to the invalid value '0'.
+
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: Benjamin Coddington <bcodding@redhat.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sunrpc/rpcb_clnt.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
+index 102c3818bc54d..53bcca365fb1c 100644
+--- a/net/sunrpc/rpcb_clnt.c
++++ b/net/sunrpc/rpcb_clnt.c
+@@ -820,9 +820,10 @@ static void rpcb_getport_done(struct rpc_task *child, void *data)
+ }
+
+ trace_rpcb_setport(child, map->r_status, map->r_port);
+- xprt->ops->set_port(xprt, map->r_port);
+- if (map->r_port)
++ if (map->r_port) {
++ xprt->ops->set_port(xprt, map->r_port);
+ xprt_set_bound(xprt);
++ }
+ }
+
+ /*
+--
+2.39.5
+
--- /dev/null
+From 7812a0785a9d6a095954bcf58bd7f7fd1c7e6243 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Mar 2025 13:05:50 +0000
+Subject: tcp: bring back NUMA dispersion in inet_ehash_locks_alloc()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit f8ece40786c9342249aa0a1b55e148ee23b2a746 ]
+
+We have platforms with 6 NUMA nodes and 480 cpus.
+
+inet_ehash_locks_alloc() currently allocates a single 64KB page
+to hold all ehash spinlocks. This adds more pressure on a single node.
+
+Change inet_ehash_locks_alloc() to use vmalloc() to spread
+the spinlocks on all online nodes, driven by NUMA policies.
+
+At boot time, NUMA policy is interleave=all, meaning that
+tcp_hashinfo.ehash_locks gets hash dispersion on all nodes.
+
+Tested:
+
+lack5:~# grep inet_ehash_locks_alloc /proc/vmallocinfo
+0x00000000d9aec4d1-0x00000000a828b652 69632 inet_ehash_locks_alloc+0x90/0x100 pages=16 vmalloc N0=2 N1=3 N2=3 N3=3 N4=3 N5=2
+
+lack5:~# echo 8192 >/proc/sys/net/ipv4/tcp_child_ehash_entries
+lack5:~# numactl --interleave=all unshare -n bash -c "grep inet_ehash_locks_alloc /proc/vmallocinfo"
+0x000000004e99d30c-0x00000000763f3279 36864 inet_ehash_locks_alloc+0x90/0x100 pages=8 vmalloc N0=1 N1=2 N2=2 N3=1 N4=1 N5=1
+0x00000000d9aec4d1-0x00000000a828b652 69632 inet_ehash_locks_alloc+0x90/0x100 pages=16 vmalloc N0=2 N1=3 N2=3 N3=3 N4=3 N5=2
+
+lack5:~# numactl --interleave=0,5 unshare -n bash -c "grep inet_ehash_locks_alloc /proc/vmallocinfo"
+0x00000000fd73a33e-0x0000000004b9a177 36864 inet_ehash_locks_alloc+0x90/0x100 pages=8 vmalloc N0=4 N5=4
+0x00000000d9aec4d1-0x00000000a828b652 69632 inet_ehash_locks_alloc+0x90/0x100 pages=16 vmalloc N0=2 N1=3 N2=3 N3=3 N4=3 N5=2
+
+lack5:~# echo 1024 >/proc/sys/net/ipv4/tcp_child_ehash_entries
+lack5:~# numactl --interleave=all unshare -n bash -c "grep inet_ehash_locks_alloc /proc/vmallocinfo"
+0x00000000db07d7a2-0x00000000ad697d29 8192 inet_ehash_locks_alloc+0x90/0x100 pages=1 vmalloc N2=1
+0x00000000d9aec4d1-0x00000000a828b652 69632 inet_ehash_locks_alloc+0x90/0x100 pages=16 vmalloc N0=2 N1=3 N2=3 N3=3 N4=3 N5=2
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Tested-by: Jason Xing <kerneljasonxing@gmail.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Link: https://patch.msgid.link/20250305130550.1865988-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/inet_hashtables.c | 37 ++++++++++++++++++++++++++-----------
+ 1 file changed, 26 insertions(+), 11 deletions(-)
+
+diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
+index 9bfcfd016e182..2b4a588247639 100644
+--- a/net/ipv4/inet_hashtables.c
++++ b/net/ipv4/inet_hashtables.c
+@@ -1230,22 +1230,37 @@ int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo)
+ {
+ unsigned int locksz = sizeof(spinlock_t);
+ unsigned int i, nblocks = 1;
++ spinlock_t *ptr = NULL;
+
+- if (locksz != 0) {
+- /* allocate 2 cache lines or at least one spinlock per cpu */
+- nblocks = max(2U * L1_CACHE_BYTES / locksz, 1U);
+- nblocks = roundup_pow_of_two(nblocks * num_possible_cpus());
++ if (locksz == 0)
++ goto set_mask;
+
+- /* no more locks than number of hash buckets */
+- nblocks = min(nblocks, hashinfo->ehash_mask + 1);
++ /* Allocate 2 cache lines or at least one spinlock per cpu. */
++ nblocks = max(2U * L1_CACHE_BYTES / locksz, 1U) * num_possible_cpus();
+
+- hashinfo->ehash_locks = kvmalloc_array(nblocks, locksz, GFP_KERNEL);
+- if (!hashinfo->ehash_locks)
+- return -ENOMEM;
++ /* At least one page per NUMA node. */
++ nblocks = max(nblocks, num_online_nodes() * PAGE_SIZE / locksz);
++
++ nblocks = roundup_pow_of_two(nblocks);
++
++ /* No more locks than number of hash buckets. */
++ nblocks = min(nblocks, hashinfo->ehash_mask + 1);
+
+- for (i = 0; i < nblocks; i++)
+- spin_lock_init(&hashinfo->ehash_locks[i]);
++ if (num_online_nodes() > 1) {
++ /* Use vmalloc() to allow NUMA policy to spread pages
++ * on all available nodes if desired.
++ */
++ ptr = vmalloc_array(nblocks, locksz);
++ }
++ if (!ptr) {
++ ptr = kvmalloc_array(nblocks, locksz, GFP_KERNEL);
++ if (!ptr)
++ return -ENOMEM;
+ }
++ for (i = 0; i < nblocks; i++)
++ spin_lock_init(&ptr[i]);
++ hashinfo->ehash_locks = ptr;
++set_mask:
+ hashinfo->ehash_locks_mask = nblocks - 1;
+ return 0;
+ }
+--
+2.39.5
+
--- /dev/null
+From e35d1f83d28daf393cb845b5155afdd3e933371b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Mar 2025 23:38:41 +0100
+Subject: tcp: reorganize tcp_in_ack_event() and tcp_count_delivered()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ilpo Järvinen <ij@kernel.org>
+
+[ Upstream commit 149dfb31615e22271d2525f078c95ea49bc4db24 ]
+
+- Move tcp_count_delivered() earlier and split tcp_count_delivered_ce()
+ out of it
+- Move tcp_in_ack_event() later
+- While at it, remove the inline from tcp_in_ack_event() and let
+ the compiler to decide
+
+Accurate ECN's heuristics does not know if there is going
+to be ACE field based CE counter increase or not until after
+rtx queue has been processed. Only then the number of ACKed
+bytes/pkts is available. As CE or not affects presence of
+FLAG_ECE, that information for tcp_in_ack_event is not yet
+available in the old location of the call to tcp_in_ack_event().
+
+Signed-off-by: Ilpo Järvinen <ij@kernel.org>
+Signed-off-by: Chia-Yu Chang <chia-yu.chang@nokia-bell-labs.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_input.c | 56 +++++++++++++++++++++++++-------------------
+ 1 file changed, 32 insertions(+), 24 deletions(-)
+
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index d93a5a89c5692..d29219e067b7f 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -419,6 +419,20 @@ static bool tcp_ecn_rcv_ecn_echo(const struct tcp_sock *tp, const struct tcphdr
+ return false;
+ }
+
++static void tcp_count_delivered_ce(struct tcp_sock *tp, u32 ecn_count)
++{
++ tp->delivered_ce += ecn_count;
++}
++
++/* Updates the delivered and delivered_ce counts */
++static void tcp_count_delivered(struct tcp_sock *tp, u32 delivered,
++ bool ece_ack)
++{
++ tp->delivered += delivered;
++ if (ece_ack)
++ tcp_count_delivered_ce(tp, delivered);
++}
++
+ /* Buffer size and advertised window tuning.
+ *
+ * 1. Tuning sk->sk_sndbuf, when connection enters established state.
+@@ -1154,15 +1168,6 @@ void tcp_mark_skb_lost(struct sock *sk, struct sk_buff *skb)
+ }
+ }
+
+-/* Updates the delivered and delivered_ce counts */
+-static void tcp_count_delivered(struct tcp_sock *tp, u32 delivered,
+- bool ece_ack)
+-{
+- tp->delivered += delivered;
+- if (ece_ack)
+- tp->delivered_ce += delivered;
+-}
+-
+ /* This procedure tags the retransmission queue when SACKs arrive.
+ *
+ * We have three tag bits: SACKED(S), RETRANS(R) and LOST(L).
+@@ -3862,12 +3867,23 @@ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag)
+ }
+ }
+
+-static inline void tcp_in_ack_event(struct sock *sk, u32 flags)
++static void tcp_in_ack_event(struct sock *sk, int flag)
+ {
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+
+- if (icsk->icsk_ca_ops->in_ack_event)
+- icsk->icsk_ca_ops->in_ack_event(sk, flags);
++ if (icsk->icsk_ca_ops->in_ack_event) {
++ u32 ack_ev_flags = 0;
++
++ if (flag & FLAG_WIN_UPDATE)
++ ack_ev_flags |= CA_ACK_WIN_UPDATE;
++ if (flag & FLAG_SLOWPATH) {
++ ack_ev_flags |= CA_ACK_SLOWPATH;
++ if (flag & FLAG_ECE)
++ ack_ev_flags |= CA_ACK_ECE;
++ }
++
++ icsk->icsk_ca_ops->in_ack_event(sk, ack_ev_flags);
++ }
+ }
+
+ /* Congestion control has updated the cwnd already. So if we're in
+@@ -3984,12 +4000,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
+ tcp_snd_una_update(tp, ack);
+ flag |= FLAG_WIN_UPDATE;
+
+- tcp_in_ack_event(sk, CA_ACK_WIN_UPDATE);
+-
+ NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPHPACKS);
+ } else {
+- u32 ack_ev_flags = CA_ACK_SLOWPATH;
+-
+ if (ack_seq != TCP_SKB_CB(skb)->end_seq)
+ flag |= FLAG_DATA;
+ else
+@@ -4001,19 +4013,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
+ flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una,
+ &sack_state);
+
+- if (tcp_ecn_rcv_ecn_echo(tp, tcp_hdr(skb))) {
++ if (tcp_ecn_rcv_ecn_echo(tp, tcp_hdr(skb)))
+ flag |= FLAG_ECE;
+- ack_ev_flags |= CA_ACK_ECE;
+- }
+
+ if (sack_state.sack_delivered)
+ tcp_count_delivered(tp, sack_state.sack_delivered,
+ flag & FLAG_ECE);
+-
+- if (flag & FLAG_WIN_UPDATE)
+- ack_ev_flags |= CA_ACK_WIN_UPDATE;
+-
+- tcp_in_ack_event(sk, ack_ev_flags);
+ }
+
+ /* This is a deviation from RFC3168 since it states that:
+@@ -4040,6 +4045,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
+
+ tcp_rack_update_reo_wnd(sk, &rs);
+
++ tcp_in_ack_event(sk, flag);
++
+ if (tp->tlp_high_seq)
+ tcp_process_tlp_ack(sk, ack, flag);
+
+@@ -4071,6 +4078,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
+ return 1;
+
+ no_queue:
++ tcp_in_ack_event(sk, flag);
+ /* If data was DSACKed, see if we can undo a cwnd reduction. */
+ if (flag & FLAG_DSACKING_ACK) {
+ tcp_fastretrans_alert(sk, prior_snd_una, num_dupack, &flag,
+--
+2.39.5
+
--- /dev/null
+From ff6ab28aa5823fce285bb200fef171a7a3da44f0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jan 2025 10:27:15 -0300
+Subject: thermal/drivers/mediatek/lvts: Start sensor interrupts disabled
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+
+[ Upstream commit 2738fb3ec6838a10d2c4ce65cefdb3b90b11bd61 ]
+
+Interrupts are enabled per sensor in lvts_update_irq_mask() as needed,
+there's no point in enabling all of them during initialization. Change
+the MONINT register initial value so all sensor interrupts start
+disabled.
+
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+Link: https://lore.kernel.org/r/20250113-mt8192-lvts-filtered-suspend-fix-v2-4-07a25200c7c6@collabora.com
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c
+index 4b3225377e8f8..3295b27ab70d2 100644
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -65,7 +65,6 @@
+ #define LVTS_HW_FILTER 0x0
+ #define LVTS_TSSEL_CONF 0x13121110
+ #define LVTS_CALSCALE_CONF 0x300
+-#define LVTS_MONINT_CONF 0x0300318C
+
+ #define LVTS_MONINT_OFFSET_SENSOR0 0xC
+ #define LVTS_MONINT_OFFSET_SENSOR1 0x180
+@@ -929,7 +928,7 @@ static int lvts_irq_init(struct lvts_ctrl *lvts_ctrl)
+ * The LVTS_MONINT register layout is the same as the LVTS_MONINTSTS
+ * register, except we set the bits to enable the interrupt.
+ */
+- writel(LVTS_MONINT_CONF, LVTS_MONINT(lvts_ctrl->base));
++ writel(0, LVTS_MONINT(lvts_ctrl->base));
+
+ return 0;
+ }
+--
+2.39.5
+
--- /dev/null
+From 3b497a1154a7eef219f027e3569798f86f74b07e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Dec 2024 11:48:59 -0500
+Subject: thermal/drivers/qoriq: Power down TMU on system suspend
+
+From: Alice Guo <alice.guo@nxp.com>
+
+[ Upstream commit 229f3feb4b0442835b27d519679168bea2de96c2 ]
+
+Enable power-down of TMU (Thermal Management Unit) for TMU version 2 during
+system suspend to save power. Save approximately 4.3mW on VDD_ANA_1P8 on
+i.MX93 platforms.
+
+Signed-off-by: Alice Guo <alice.guo@nxp.com>
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20241209164859.3758906-2-Frank.Li@nxp.com
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/thermal/qoriq_thermal.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
+index 52e26be8c53df..aed2729f63d06 100644
+--- a/drivers/thermal/qoriq_thermal.c
++++ b/drivers/thermal/qoriq_thermal.c
+@@ -18,6 +18,7 @@
+ #define SITES_MAX 16
+ #define TMR_DISABLE 0x0
+ #define TMR_ME 0x80000000
++#define TMR_CMD BIT(29)
+ #define TMR_ALPF 0x0c000000
+ #define TMR_ALPF_V2 0x03000000
+ #define TMTMIR_DEFAULT 0x0000000f
+@@ -356,6 +357,12 @@ static int qoriq_tmu_suspend(struct device *dev)
+ if (ret)
+ return ret;
+
++ if (data->ver > TMU_VER1) {
++ ret = regmap_set_bits(data->regmap, REGS_TMR, TMR_CMD);
++ if (ret)
++ return ret;
++ }
++
+ clk_disable_unprepare(data->clk);
+
+ return 0;
+@@ -370,6 +377,12 @@ static int qoriq_tmu_resume(struct device *dev)
+ if (ret)
+ return ret;
+
++ if (data->ver > TMU_VER1) {
++ ret = regmap_clear_bits(data->regmap, REGS_TMR, TMR_CMD);
++ if (ret)
++ return ret;
++ }
++
+ /* Enable monitoring */
+ return regmap_update_bits(data->regmap, REGS_TMR, TMR_ME, TMR_ME);
+ }
+--
+2.39.5
+
--- /dev/null
+From 54f69643af741ade857c12d5fa5163c50c3eb9d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Mar 2025 14:56:20 +0200
+Subject: thunderbolt: Do not add non-active NVM if NVM upgrade is disabled for
+ retimer
+
+From: Mika Westerberg <mika.westerberg@linux.intel.com>
+
+[ Upstream commit ad79c278e478ca8c1a3bf8e7a0afba8f862a48a1 ]
+
+This is only used to write a new NVM in order to upgrade the retimer
+firmware. It does not make sense to expose it if upgrade is disabled.
+This also makes it consistent with the router NVM upgrade.
+
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/thunderbolt/retimer.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/thunderbolt/retimer.c b/drivers/thunderbolt/retimer.c
+index eeb64433ebbca..3488be7620674 100644
+--- a/drivers/thunderbolt/retimer.c
++++ b/drivers/thunderbolt/retimer.c
+@@ -93,9 +93,11 @@ static int tb_retimer_nvm_add(struct tb_retimer *rt)
+ if (ret)
+ goto err_nvm;
+
+- ret = tb_nvm_add_non_active(nvm, nvm_write);
+- if (ret)
+- goto err_nvm;
++ if (!rt->no_nvm_upgrade) {
++ ret = tb_nvm_add_non_active(nvm, nvm_write);
++ if (ret)
++ goto err_nvm;
++ }
+
+ rt->nvm = nvm;
+ dev_dbg(&rt->dev, "NVM version %x.%x\n", nvm->major, nvm->minor);
+--
+2.39.5
+
--- /dev/null
+From 514b7f59baa5cf2e6fd99a584d87335175b667ee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Mar 2025 10:54:47 +0100
+Subject: timer_list: Don't use %pK through printk()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
+
+[ Upstream commit a52067c24ccf6ee4c85acffa0f155e9714f9adce ]
+
+This reverts commit f590308536db ("timer debug: Hide kernel addresses via
+%pK in /proc/timer_list")
+
+The timer list helper SEQ_printf() uses either the real seq_printf() for
+procfs output or vprintk() to print to the kernel log, when invoked from
+SysRq-q. It uses %pK for printing pointers.
+
+In the past %pK was prefered over %p as it would not leak raw pointer
+values into the kernel log. Since commit ad67b74d2469 ("printk: hash
+addresses printed with %p") the regular %p has been improved to avoid this
+issue.
+
+Furthermore, restricted pointers ("%pK") were never meant to be used
+through printk(). They can still unintentionally leak raw pointers or
+acquire sleeping looks in atomic contexts.
+
+Switch to the regular pointer formatting which is safer, easier to reason
+about and sufficient here.
+
+Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/lkml/20250113171731-dc10e3c1-da64-4af0-b767-7c7070468023@linutronix.de/
+Link: https://lore.kernel.org/all/20250311-restricted-pointers-timer-v1-1-6626b91e54ab@linutronix.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/time/timer_list.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
+index 1c311c46da507..cfbb46cc4e761 100644
+--- a/kernel/time/timer_list.c
++++ b/kernel/time/timer_list.c
+@@ -46,7 +46,7 @@ static void
+ print_timer(struct seq_file *m, struct hrtimer *taddr, struct hrtimer *timer,
+ int idx, u64 now)
+ {
+- SEQ_printf(m, " #%d: <%pK>, %ps", idx, taddr, timer->function);
++ SEQ_printf(m, " #%d: <%p>, %ps", idx, taddr, timer->function);
+ SEQ_printf(m, ", S:%02x", timer->state);
+ SEQ_printf(m, "\n");
+ SEQ_printf(m, " # expires at %Lu-%Lu nsecs [in %Ld to %Ld nsecs]\n",
+@@ -98,7 +98,7 @@ print_active_timers(struct seq_file *m, struct hrtimer_clock_base *base,
+ static void
+ print_base(struct seq_file *m, struct hrtimer_clock_base *base, u64 now)
+ {
+- SEQ_printf(m, " .base: %pK\n", base);
++ SEQ_printf(m, " .base: %p\n", base);
+ SEQ_printf(m, " .index: %d\n", base->index);
+
+ SEQ_printf(m, " .resolution: %u nsecs\n", hrtimer_resolution);
+--
+2.39.5
+
--- /dev/null
+From 3712bd8ca7875cac673cee41d82ded18f237de70 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Mar 2025 14:36:23 -0700
+Subject: tools/build: Don't pass test log files to linker
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit 935e7cb5bb80106ff4f2fe39640f430134ef8cd8 ]
+
+Separate test log files from object files. Depend on test log output
+but don't pass to the linker.
+
+Reviewed-by: James Clark <james.clark@linaro.org>
+Signed-off-by: Ian Rogers <irogers@google.com>
+Link: https://lore.kernel.org/r/20250311213628.569562-2-irogers@google.com
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/build/Makefile.build | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build
+index 5fb3fb3d97e0f..ffe988867703b 100644
+--- a/tools/build/Makefile.build
++++ b/tools/build/Makefile.build
+@@ -149,6 +149,10 @@ objprefix := $(subst ./,,$(OUTPUT)$(dir)/)
+ obj-y := $(addprefix $(objprefix),$(obj-y))
+ subdir-obj-y := $(addprefix $(objprefix),$(subdir-obj-y))
+
++# Separate out test log files from real build objects.
++test-y := $(filter %_log, $(obj-y))
++obj-y := $(filter-out %_log, $(obj-y))
++
+ # Final '$(obj)-in.o' object
+ in-target := $(objprefix)$(obj)-in.o
+
+@@ -159,7 +163,7 @@ $(subdir-y):
+
+ $(sort $(subdir-obj-y)): $(subdir-y) ;
+
+-$(in-target): $(obj-y) FORCE
++$(in-target): $(obj-y) $(test-y) FORCE
+ $(call rule_mkdir)
+ $(call if_changed,$(host)ld_multi)
+
+--
+2.39.5
+
--- /dev/null
+From 91d4186f306387a8fd94543622c190fd2f2a764d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Feb 2025 21:46:24 -0600
+Subject: tools/power turbostat: Clustered Uncore MHz counters should honor
+ show/hide options
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Len Brown <len.brown@intel.com>
+
+[ Upstream commit 1c7c7388e6c31f46b26a884d80b45efbad8237b2 ]
+
+The clustered uncore frequency counters, UMHz*.*
+should honor the --show and --hide options.
+
+All non-specified counters should be implicityly hidden.
+But when --show was used, UMHz*.* showed up anyway:
+
+$ sudo turbostat -q -S --show Busy%
+Busy% UMHz0.0 UMHz1.0 UMHz2.0 UMHz3.0 UMHz4.0
+
+Indeed, there was no string that can be used to explicitly
+show or hide clustered uncore counters.
+
+Even through they are dynamically probed and added,
+group the clustered UMHz*.* counters with the legacy
+built-in-counter "UncMHz" for show/hide.
+
+turbostat --show Busy%
+ does not show UMHz*.*.
+turbostat --show UncMHz
+ shows either UncMHz or UMHz*.*, if present
+turbostat --hide UncMHz
+ hides either UncMHz or UMHz*.*, if present
+
+Reported-by: Artem Bityutskiy <artem.bityutskiy@intel.com>
+Signed-off-by: Len Brown <len.brown@intel.com>
+Tested-by: Artem Bityutskiy <artem.bityutskiy@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/power/x86/turbostat/turbostat.8 | 1 +
+ tools/power/x86/turbostat/turbostat.c | 13 ++++++++++++-
+ 2 files changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
+index a3cf1d17163ae..e4b00e13302b3 100644
+--- a/tools/power/x86/turbostat/turbostat.8
++++ b/tools/power/x86/turbostat/turbostat.8
+@@ -199,6 +199,7 @@ The system configuration dump (if --quiet is not used) is followed by statistics
+ \fBUncMHz\fP per-package uncore MHz, instantaneous sample.
+ .PP
+ \fBUMHz1.0\fP per-package uncore MHz for domain=1 and fabric_cluster=0, instantaneous sample. System summary is the average of all packages.
++For the "--show" and "--hide" options, use "UncMHz" to operate on all UMHz*.* as a group.
+ .SH TOO MUCH INFORMATION EXAMPLE
+ By default, turbostat dumps all possible information -- a system configuration header, followed by columns for all counters.
+ This is ideal for remote debugging, use the "--out" option to save everything to a text file, and get that file to the expert helping you debug.
+diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
+index 77ef60980ee58..12424bf08551d 100644
+--- a/tools/power/x86/turbostat/turbostat.c
++++ b/tools/power/x86/turbostat/turbostat.c
+@@ -6445,7 +6445,18 @@ static void probe_intel_uncore_frequency_cluster(void)
+ sprintf(path, "%s/current_freq_khz", path_base);
+ sprintf(name_buf, "UMHz%d.%d", domain_id, cluster_id);
+
+- add_counter(0, path, name_buf, 0, SCOPE_PACKAGE, COUNTER_K2M, FORMAT_AVERAGE, 0, package_id);
++ /*
++ * Once add_couter() is called, that counter is always read
++ * and reported -- So it is effectively (enabled & present).
++ * Only call add_counter() here if legacy BIC_UNCORE_MHZ (UncMHz)
++ * is (enabled). Since we are in this routine, we
++ * know we will not probe and set (present) the legacy counter.
++ *
++ * This allows "--show/--hide UncMHz" to be effective for
++ * the clustered MHz counters, as a group.
++ */
++ if BIC_IS_ENABLED(BIC_UNCORE_MHZ)
++ add_counter(0, path, name_buf, 0, SCOPE_PACKAGE, COUNTER_K2M, FORMAT_AVERAGE, 0, package_id);
+
+ if (quiet)
+ continue;
+--
+2.39.5
+
--- /dev/null
+From c381b451a7733406d1e47277910d3d0715d28a2c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Feb 2025 13:55:09 -0800
+Subject: tools: ynl-gen: don't output external constants
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 7e8b24e24ac46038e48c9a042e7d9b31855cbca5 ]
+
+A definition with a "header" property is an "external" definition
+for C code, as in it is defined already in another C header file.
+Other languages will need the exact value but C codegen should
+not recreate it. So don't output those definitions in the uAPI
+header.
+
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Link: https://patch.msgid.link/20250203215510.1288728-1-kuba@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/net/ynl/ynl-gen-c.py | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/tools/net/ynl/ynl-gen-c.py b/tools/net/ynl/ynl-gen-c.py
+index 463f1394ab971..c78f1c1bca75c 100755
+--- a/tools/net/ynl/ynl-gen-c.py
++++ b/tools/net/ynl/ynl-gen-c.py
+@@ -2417,6 +2417,9 @@ def render_uapi(family, cw):
+
+ defines = []
+ for const in family['definitions']:
++ if const.get('header'):
++ continue
++
+ if const['type'] != 'const':
+ cw.writes_defines(defines)
+ defines = []
+--
+2.39.5
+
--- /dev/null
+From 50ec4baff1f0eea8bb79251ac85ca1dad64edb5a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 May 2025 21:30:50 -0700
+Subject: tools: ynl-gen: validate 0 len strings from kernel
+
+From: David Wei <dw@davidwei.uk>
+
+[ Upstream commit 4720f9707c783f642332dee3d56dccaefa850e42 ]
+
+Strings from the kernel are guaranteed to be null terminated and
+ynl_attr_validate() checks for this. But it doesn't check if the string
+has a len of 0, which would cause problems when trying to access
+data[len - 1]. Fix this by checking that len is positive.
+
+Signed-off-by: David Wei <dw@davidwei.uk>
+Link: https://patch.msgid.link/20250503043050.861238-1-dw@davidwei.uk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/net/ynl/lib/ynl.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/net/ynl/lib/ynl.c b/tools/net/ynl/lib/ynl.c
+index ce32cb35007d6..c4da34048ef85 100644
+--- a/tools/net/ynl/lib/ynl.c
++++ b/tools/net/ynl/lib/ynl.c
+@@ -364,7 +364,7 @@ int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr)
+ "Invalid attribute (binary %s)", policy->name);
+ return -1;
+ case YNL_PT_NUL_STR:
+- if ((!policy->len || len <= policy->len) && !data[len - 1])
++ if (len && (!policy->len || len <= policy->len) && !data[len - 1])
+ break;
+ yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
+ "Invalid attribute (string %s)", policy->name);
+--
+2.39.5
+
--- /dev/null
+From eb609d9be74156706a2103b1427c3472014666cf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Mar 2025 10:56:44 +0000
+Subject: tpm: Convert warn to dbg in tpm2_start_auth_session()
+
+From: Jonathan McDowell <noodles@meta.com>
+
+[ Upstream commit 6359691b4fbcaf3ed86f53043a1f7c6cc54c09be ]
+
+TPM2 sessions have been flushed lazily since commit df745e25098dc ("tpm:
+Lazily flush the auth session"). If /dev/tpm{rm}0 is not accessed
+in-between two in-kernel calls, it is possible that a TPM2 session is
+re-started before the previous one has been completed.
+
+This causes a spurios warning in a legit run-time condition, which is also
+correctly addressed with a fast return path:
+
+[ 2.944047] tpm tpm0: auth session is active
+
+Address the issue by changing dev_warn_once() call to a dev_dbg_once()
+call.
+
+[jarkko: Rewrote the commit message, and instead of dropping converted
+ to a debug message.]
+Signed-off-by: Jonathan McDowell <noodles@meta.com>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/char/tpm/tpm2-sessions.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c
+index ecea089157301..cf0b831540447 100644
+--- a/drivers/char/tpm/tpm2-sessions.c
++++ b/drivers/char/tpm/tpm2-sessions.c
+@@ -974,7 +974,7 @@ int tpm2_start_auth_session(struct tpm_chip *chip)
+ int rc;
+
+ if (chip->auth) {
+- dev_warn_once(&chip->dev, "auth session is active\n");
++ dev_dbg_once(&chip->dev, "auth session is active\n");
+ return 0;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From b2426af09e43844befcdb556dbdf5625bd0cb972 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Mar 2025 16:40:49 +0200
+Subject: tracing: Mark binary printing functions with __printf() attribute
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 196a062641fe68d9bfe0ad36b6cd7628c99ad22c ]
+
+Binary printing functions are using printf() type of format, and compiler
+is not happy about them as is:
+
+kernel/trace/trace.c:3292:9: error: function ‘trace_vbprintk’ might be a candidate for ‘gnu_printf’ format attribute [-Werror=suggest-attribute=format]
+kernel/trace/trace_seq.c:182:9: error: function ‘trace_seq_bprintf’ might be a candidate for ‘gnu_printf’ format attribute [-Werror=suggest-attribute=format]
+
+Fix the compilation errors by adding __printf() attribute.
+
+While at it, move existing __printf() attributes from the implementations
+to the declarations. IT also fixes incorrect attribute parameters that are
+used for trace_array_printk().
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Reviewed-by: Kees Cook <kees@kernel.org>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Link: https://lore.kernel.org/r/20250321144822.324050-4-andriy.shevchenko@linux.intel.com
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/trace.h | 4 ++--
+ include/linux/trace_seq.h | 8 ++++----
+ kernel/trace/trace.c | 11 +++--------
+ kernel/trace/trace.h | 16 +++++++++-------
+ 4 files changed, 18 insertions(+), 21 deletions(-)
+
+diff --git a/include/linux/trace.h b/include/linux/trace.h
+index fdcd76b7be83d..7eaad857dee04 100644
+--- a/include/linux/trace.h
++++ b/include/linux/trace.h
+@@ -72,8 +72,8 @@ static inline int unregister_ftrace_export(struct trace_export *export)
+ static inline void trace_printk_init_buffers(void)
+ {
+ }
+-static inline int trace_array_printk(struct trace_array *tr, unsigned long ip,
+- const char *fmt, ...)
++static inline __printf(3, 4)
++int trace_array_printk(struct trace_array *tr, unsigned long ip, const char *fmt, ...)
+ {
+ return 0;
+ }
+diff --git a/include/linux/trace_seq.h b/include/linux/trace_seq.h
+index 1ef95c0287f05..a93ed5ac32265 100644
+--- a/include/linux/trace_seq.h
++++ b/include/linux/trace_seq.h
+@@ -88,8 +88,8 @@ extern __printf(2, 3)
+ void trace_seq_printf(struct trace_seq *s, const char *fmt, ...);
+ extern __printf(2, 0)
+ void trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args);
+-extern void
+-trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary);
++extern __printf(2, 0)
++void trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary);
+ extern int trace_print_seq(struct seq_file *m, struct trace_seq *s);
+ extern int trace_seq_to_user(struct trace_seq *s, char __user *ubuf,
+ int cnt);
+@@ -113,8 +113,8 @@ static inline __printf(2, 3)
+ void trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
+ {
+ }
+-static inline void
+-trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
++static inline __printf(2, 0)
++void trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
+ {
+ }
+
+diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
+index 06104c2c66ab2..e773b0adcfc0a 100644
+--- a/kernel/trace/trace.c
++++ b/kernel/trace/trace.c
+@@ -3343,10 +3343,9 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
+ }
+ EXPORT_SYMBOL_GPL(trace_vbprintk);
+
+-__printf(3, 0)
+-static int
+-__trace_array_vprintk(struct trace_buffer *buffer,
+- unsigned long ip, const char *fmt, va_list args)
++static __printf(3, 0)
++int __trace_array_vprintk(struct trace_buffer *buffer,
++ unsigned long ip, const char *fmt, va_list args)
+ {
+ struct trace_event_call *call = &event_print;
+ struct ring_buffer_event *event;
+@@ -3399,7 +3398,6 @@ __trace_array_vprintk(struct trace_buffer *buffer,
+ return len;
+ }
+
+-__printf(3, 0)
+ int trace_array_vprintk(struct trace_array *tr,
+ unsigned long ip, const char *fmt, va_list args)
+ {
+@@ -3429,7 +3427,6 @@ int trace_array_vprintk(struct trace_array *tr,
+ * Note, trace_array_init_printk() must be called on @tr before this
+ * can be used.
+ */
+-__printf(3, 0)
+ int trace_array_printk(struct trace_array *tr,
+ unsigned long ip, const char *fmt, ...)
+ {
+@@ -3474,7 +3471,6 @@ int trace_array_init_printk(struct trace_array *tr)
+ }
+ EXPORT_SYMBOL_GPL(trace_array_init_printk);
+
+-__printf(3, 4)
+ int trace_array_printk_buf(struct trace_buffer *buffer,
+ unsigned long ip, const char *fmt, ...)
+ {
+@@ -3490,7 +3486,6 @@ int trace_array_printk_buf(struct trace_buffer *buffer,
+ return ret;
+ }
+
+-__printf(2, 0)
+ int trace_vprintk(unsigned long ip, const char *fmt, va_list args)
+ {
+ return trace_array_vprintk(printk_trace, ip, fmt, args);
+diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
+index 04ea327198ba8..82da3ac140242 100644
+--- a/kernel/trace/trace.h
++++ b/kernel/trace/trace.h
+@@ -818,13 +818,15 @@ static inline void __init disable_tracing_selftest(const char *reason)
+
+ extern void *head_page(struct trace_array_cpu *data);
+ extern unsigned long long ns2usecs(u64 nsec);
+-extern int
+-trace_vbprintk(unsigned long ip, const char *fmt, va_list args);
+-extern int
+-trace_vprintk(unsigned long ip, const char *fmt, va_list args);
+-extern int
+-trace_array_vprintk(struct trace_array *tr,
+- unsigned long ip, const char *fmt, va_list args);
++
++__printf(2, 0)
++int trace_vbprintk(unsigned long ip, const char *fmt, va_list args);
++__printf(2, 0)
++int trace_vprintk(unsigned long ip, const char *fmt, va_list args);
++__printf(3, 0)
++int trace_array_vprintk(struct trace_array *tr,
++ unsigned long ip, const char *fmt, va_list args);
++__printf(3, 4)
+ int trace_array_printk_buf(struct trace_buffer *buffer,
+ unsigned long ip, const char *fmt, ...);
+ void trace_printk_seq(struct trace_seq *s);
+--
+2.39.5
+
--- /dev/null
+From 6f4adf23886b0c4d6e1c1efd71db82131fceae1a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 14:24:55 -0700
+Subject: ublk: complete command synchronously on error
+
+From: Caleb Sander Mateos <csander@purestorage.com>
+
+[ Upstream commit 603f9be21c1894e462416e3324962d6c9c2b95f8 ]
+
+In case of an error, ublk's ->uring_cmd() functions currently return
+-EIOCBQUEUED and immediately call io_uring_cmd_done(). -EIOCBQUEUED and
+io_uring_cmd_done() are intended for asynchronous completions. For
+synchronous completions, the ->uring_cmd() function can just return the
+negative return code directly. This skips io_uring_cmd_del_cancelable(),
+and deferring the completion to task work. So return the error code
+directly from __ublk_ch_uring_cmd() and ublk_ctrl_uring_cmd().
+
+Update ublk_ch_uring_cmd_cb(), which currently ignores the return value
+from __ublk_ch_uring_cmd(), to call io_uring_cmd_done() for synchronous
+completions.
+
+Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
+Reviewed-by: Ming Lei <ming.lei@redhat.com>
+Reviewed-by: Keith Busch <kbusch@kernel.org>
+Link: https://lore.kernel.org/r/20250225212456.2902549-1-csander@purestorage.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/block/ublk_drv.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
+index 5ec5d580ef506..a01a547c562f3 100644
+--- a/drivers/block/ublk_drv.c
++++ b/drivers/block/ublk_drv.c
+@@ -1881,10 +1881,9 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
+ return -EIOCBQUEUED;
+
+ out:
+- io_uring_cmd_done(cmd, ret, 0, issue_flags);
+ pr_devel("%s: complete: cmd op %d, tag %d ret %x io_flags %x\n",
+ __func__, cmd_op, tag, ret, io->flags);
+- return -EIOCBQUEUED;
++ return ret;
+ }
+
+ static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub,
+@@ -1940,7 +1939,10 @@ static inline int ublk_ch_uring_cmd_local(struct io_uring_cmd *cmd,
+ static void ublk_ch_uring_cmd_cb(struct io_uring_cmd *cmd,
+ unsigned int issue_flags)
+ {
+- ublk_ch_uring_cmd_local(cmd, issue_flags);
++ int ret = ublk_ch_uring_cmd_local(cmd, issue_flags);
++
++ if (ret != -EIOCBQUEUED)
++ io_uring_cmd_done(cmd, ret, 0, issue_flags);
+ }
+
+ static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
+@@ -3065,10 +3067,9 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
+ if (ub)
+ ublk_put_device(ub);
+ out:
+- io_uring_cmd_done(cmd, ret, 0, issue_flags);
+ pr_devel("%s: cmd done ret %d cmd_op %x, dev id %d qid %d\n",
+ __func__, ret, cmd->cmd_op, header->dev_id, header->queue_id);
+- return -EIOCBQUEUED;
++ return ret;
+ }
+
+ static const struct file_operations ublk_ctl_fops = {
+--
+2.39.5
+
--- /dev/null
+From a90c67cc873985c8bf1e5228bfb9f429f21041a1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Feb 2025 21:31:48 -0700
+Subject: ublk: enforce ublks_max only for unprivileged devices
+
+From: Uday Shankar <ushankar@purestorage.com>
+
+[ Upstream commit 80bdfbb3545b6f16680a72c825063d08a6b44c7a ]
+
+Commit 403ebc877832 ("ublk_drv: add module parameter of ublks_max for
+limiting max allowed ublk dev"), claimed ublks_max was added to prevent
+a DoS situation with an untrusted user creating too many ublk devices.
+If that's the case, ublks_max should only restrict the number of
+unprivileged ublk devices in the system. Enforce the limit only for
+unprivileged ublk devices, and rename variables accordingly. Leave the
+external-facing parameter name unchanged, since changing it may break
+systems which use it (but still update its documentation to reflect its
+new meaning).
+
+As a result of this change, in a system where there are only normal
+(non-unprivileged) devices, the maximum number of such devices is
+increased to 1 << MINORBITS, or 1048576. That ought to be enough for
+anyone, right?
+
+Signed-off-by: Uday Shankar <ushankar@purestorage.com>
+Reviewed-by: Ming Lei <ming.lei@redhat.com>
+Link: https://lore.kernel.org/r/20250228-ublks_max-v1-1-04b7379190c0@purestorage.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/block/ublk_drv.c | 42 ++++++++++++++++++++++++++--------------
+ 1 file changed, 27 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
+index 38b9e485e520d..5ec5d580ef506 100644
+--- a/drivers/block/ublk_drv.c
++++ b/drivers/block/ublk_drv.c
+@@ -484,15 +484,17 @@ static wait_queue_head_t ublk_idr_wq; /* wait until one idr is freed */
+
+ static DEFINE_MUTEX(ublk_ctl_mutex);
+
++
++#define UBLK_MAX_UBLKS UBLK_MINORS
++
+ /*
+- * Max ublk devices allowed to add
++ * Max unprivileged ublk devices allowed to add
+ *
+ * It can be extended to one per-user limit in future or even controlled
+ * by cgroup.
+ */
+-#define UBLK_MAX_UBLKS UBLK_MINORS
+-static unsigned int ublks_max = 64;
+-static unsigned int ublks_added; /* protected by ublk_ctl_mutex */
++static unsigned int unprivileged_ublks_max = 64;
++static unsigned int unprivileged_ublks_added; /* protected by ublk_ctl_mutex */
+
+ static struct miscdevice ublk_misc;
+
+@@ -2203,7 +2205,8 @@ static int ublk_add_chdev(struct ublk_device *ub)
+ if (ret)
+ goto fail;
+
+- ublks_added++;
++ if (ub->dev_info.flags & UBLK_F_UNPRIVILEGED_DEV)
++ unprivileged_ublks_added++;
+ return 0;
+ fail:
+ put_device(dev);
+@@ -2241,12 +2244,17 @@ static int ublk_add_tag_set(struct ublk_device *ub)
+
+ static void ublk_remove(struct ublk_device *ub)
+ {
++ bool unprivileged;
++
+ ublk_stop_dev(ub);
+ cancel_work_sync(&ub->stop_work);
+ cancel_work_sync(&ub->quiesce_work);
+ cdev_device_del(&ub->cdev, &ub->cdev_dev);
++ unprivileged = ub->dev_info.flags & UBLK_F_UNPRIVILEGED_DEV;
+ ublk_put_device(ub);
+- ublks_added--;
++
++ if (unprivileged)
++ unprivileged_ublks_added--;
+ }
+
+ static struct ublk_device *ublk_get_device_from_id(int idx)
+@@ -2495,7 +2503,8 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd)
+ return ret;
+
+ ret = -EACCES;
+- if (ublks_added >= ublks_max)
++ if ((info.flags & UBLK_F_UNPRIVILEGED_DEV) &&
++ unprivileged_ublks_added >= unprivileged_ublks_max)
+ goto out_unlock;
+
+ ret = -ENOMEM;
+@@ -3123,23 +3132,26 @@ static void __exit ublk_exit(void)
+ module_init(ublk_init);
+ module_exit(ublk_exit);
+
+-static int ublk_set_max_ublks(const char *buf, const struct kernel_param *kp)
++static int ublk_set_max_unprivileged_ublks(const char *buf,
++ const struct kernel_param *kp)
+ {
+ return param_set_uint_minmax(buf, kp, 0, UBLK_MAX_UBLKS);
+ }
+
+-static int ublk_get_max_ublks(char *buf, const struct kernel_param *kp)
++static int ublk_get_max_unprivileged_ublks(char *buf,
++ const struct kernel_param *kp)
+ {
+- return sysfs_emit(buf, "%u\n", ublks_max);
++ return sysfs_emit(buf, "%u\n", unprivileged_ublks_max);
+ }
+
+-static const struct kernel_param_ops ublk_max_ublks_ops = {
+- .set = ublk_set_max_ublks,
+- .get = ublk_get_max_ublks,
++static const struct kernel_param_ops ublk_max_unprivileged_ublks_ops = {
++ .set = ublk_set_max_unprivileged_ublks,
++ .get = ublk_get_max_unprivileged_ublks,
+ };
+
+-module_param_cb(ublks_max, &ublk_max_ublks_ops, &ublks_max, 0644);
+-MODULE_PARM_DESC(ublks_max, "max number of ublk devices allowed to add(default: 64)");
++module_param_cb(ublks_max, &ublk_max_unprivileged_ublks_ops,
++ &unprivileged_ublks_max, 0644);
++MODULE_PARM_DESC(ublks_max, "max number of unprivileged ublk devices allowed to add(default: 64)");
+
+ MODULE_AUTHOR("Ming Lei <ming.lei@redhat.com>");
+ MODULE_DESCRIPTION("Userspace block device");
+--
+2.39.5
+
--- /dev/null
+From ad85e4dca18fdd467c10fdfdf1e08cd0e1e2a351 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 19:18:19 +0100
+Subject: um: Store full CSGSFS and SS register from mcontext
+
+From: Benjamin Berg <benjamin@sipsolutions.net>
+
+[ Upstream commit cef721e0d53d2b64f2ba177c63a0dfdd7c0daf17 ]
+
+Doing this allows using registers as retrieved from an mcontext to be
+pushed to a process using PTRACE_SETREGS.
+
+It is not entirely clear to me why CSGSFS was masked. Doing so creates
+issues when using the mcontext as process state in seccomp and simply
+copying the register appears to work perfectly fine for ptrace.
+
+Signed-off-by: Benjamin Berg <benjamin@sipsolutions.net>
+Link: https://patch.msgid.link/20250224181827.647129-2-benjamin@sipsolutions.net
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/um/os-Linux/mcontext.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/arch/x86/um/os-Linux/mcontext.c b/arch/x86/um/os-Linux/mcontext.c
+index e80ab7d281177..1b0d95328b2c7 100644
+--- a/arch/x86/um/os-Linux/mcontext.c
++++ b/arch/x86/um/os-Linux/mcontext.c
+@@ -27,7 +27,6 @@ void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc)
+ COPY(RIP);
+ COPY2(EFLAGS, EFL);
+ COPY2(CS, CSGSFS);
+- regs->gp[CS / sizeof(unsigned long)] &= 0xffff;
+- regs->gp[CS / sizeof(unsigned long)] |= 3;
++ regs->gp[SS / sizeof(unsigned long)] = mc->gregs[REG_CSGSFS] >> 48;
+ #endif
+ }
+--
+2.39.5
+
--- /dev/null
+From 7ad9baf4ee5f0774501256ce0dfb785fe206e4de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Feb 2025 12:18:55 +0800
+Subject: um: Update min_low_pfn to match changes in uml_reserved
+
+From: Tiwei Bie <tiwei.btw@antgroup.com>
+
+[ Upstream commit e82cf3051e6193f61e03898f8dba035199064d36 ]
+
+When uml_reserved is updated, min_low_pfn must also be updated
+accordingly. Otherwise, min_low_pfn will not accurately reflect
+the lowest available PFN.
+
+Signed-off-by: Tiwei Bie <tiwei.btw@antgroup.com>
+Link: https://patch.msgid.link/20250221041855.1156109-1-tiwei.btw@antgroup.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/um/kernel/mem.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
+index a5b4fe2ad9315..6ca9ea4a230bc 100644
+--- a/arch/um/kernel/mem.c
++++ b/arch/um/kernel/mem.c
+@@ -70,6 +70,7 @@ void __init mem_init(void)
+ map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
+ memblock_free((void *)brk_end, uml_reserved - brk_end);
+ uml_reserved = brk_end;
++ min_low_pfn = PFN_UP(__pa(uml_reserved));
+
+ /* this will put all low memory onto the freelists */
+ memblock_free_all();
+--
+2.39.5
+
--- /dev/null
+From ab919c30185c3182a9727af4cee5bcf4c3f41418 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Mar 2025 17:45:50 +0200
+Subject: usb: xhci: Don't change the status of stalled TDs on failed Stop EP
+
+From: Michal Pecio <michal.pecio@gmail.com>
+
+[ Upstream commit dfc88357b6b6356dadea06b2c0bc8041f5e11720 ]
+
+When the device stalls an endpoint, current TD is assigned -EPIPE
+status and Reset Endpoint is queued. If a Stop Endpoint is pending
+at the time, it will run before Reset Endpoint and fail due to the
+stall. Its handler will change TD's status to -EPROTO before Reset
+Endpoint handler runs and initiates giveback.
+
+Check if the stall has already been handled and don't try to do it
+again. Since xhci_handle_halted_endpoint() performs this check too,
+not overwriting td->status is the only difference.
+
+I haven't seen this case yet, but I have seen a related one where
+the xHC has already executed Reset Endpoint, EP Context state is
+now Stopped and EP_HALTED is set. If the xHC took a bit longer to
+execute Reset Endpoint, said case would become this one.
+
+Signed-off-by: Michal Pecio <michal.pecio@gmail.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20250311154551.4035726-3-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-ring.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index 3e70e4f6bf083..fbc8419a54730 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1156,7 +1156,14 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
+ */
+ switch (GET_EP_CTX_STATE(ep_ctx)) {
+ case EP_STATE_HALTED:
+- xhci_dbg(xhci, "Stop ep completion raced with stall, reset ep\n");
++ xhci_dbg(xhci, "Stop ep completion raced with stall\n");
++ /*
++ * If the halt happened before Stop Endpoint failed, its transfer event
++ * should have already been handled and Reset Endpoint should be pending.
++ */
++ if (ep->ep_state & EP_HALTED)
++ goto reset_done;
++
+ if (ep->ep_state & EP_HAS_STREAMS) {
+ reset_type = EP_SOFT_RESET;
+ } else {
+@@ -1167,8 +1174,11 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
+ }
+ /* reset ep, reset handler cleans up cancelled tds */
+ err = xhci_handle_halted_endpoint(xhci, ep, td, reset_type);
++ xhci_dbg(xhci, "Stop ep completion resetting ep, status %d\n", err);
+ if (err)
+ break;
++reset_done:
++ /* Reset EP handler will clean up cancelled TDs */
+ ep->ep_state &= ~EP_STOP_CMD_PENDING;
+ return;
+ case EP_STATE_STOPPED:
+--
+2.39.5
+
--- /dev/null
+From 001fdaaa34664b82d493cf4e28c9232c7b534576 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Mar 2025 16:49:48 +0200
+Subject: usb: xhci: set page size to the xHCI-supported size
+
+From: Niklas Neronin <niklas.neronin@linux.intel.com>
+
+[ Upstream commit 68c1f1671650b49bbd26e6a65ddcf33f2565efa3 ]
+
+The current xHCI driver does not validate whether a page size of 4096
+bytes is supported. Address the issue by setting the page size to the
+value supported by the xHCI controller, as read from the Page Size
+register. In the event of an unexpected value; default to a 4K page size.
+
+Additionally, this commit removes unnecessary debug messages and instead
+prints the supported and used page size once.
+
+The xHCI controller supports page sizes of (2^{(n+12)}) bytes, where 'n'
+is the Page Size Bit. Only one page size is supported, with a maximum
+page size of 128 KB.
+
+Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20250306144954.3507700-10-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-mem.c | 34 ++++++++++++++++++----------------
+ drivers/usb/host/xhci.h | 8 ++++----
+ 2 files changed, 22 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
+index 8c26275696df9..f9c51e0f2e37c 100644
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -1959,7 +1959,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
+ xhci->interrupters = NULL;
+
+ xhci->page_size = 0;
+- xhci->page_shift = 0;
+ xhci->usb2_rhub.bus_state.bus_suspended = 0;
+ xhci->usb3_rhub.bus_state.bus_suspended = 0;
+ }
+@@ -2378,6 +2377,22 @@ xhci_create_secondary_interrupter(struct usb_hcd *hcd, unsigned int segs,
+ }
+ EXPORT_SYMBOL_GPL(xhci_create_secondary_interrupter);
+
++static void xhci_hcd_page_size(struct xhci_hcd *xhci)
++{
++ u32 page_size;
++
++ page_size = readl(&xhci->op_regs->page_size) & XHCI_PAGE_SIZE_MASK;
++ if (!is_power_of_2(page_size)) {
++ xhci_warn(xhci, "Invalid page size register = 0x%x\n", page_size);
++ /* Fallback to 4K page size, since that's common */
++ page_size = 1;
++ }
++
++ xhci->page_size = page_size << 12;
++ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "HCD page size set to %iK",
++ xhci->page_size >> 10);
++}
++
+ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
+ {
+ struct xhci_interrupter *ir;
+@@ -2385,7 +2400,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
+ dma_addr_t dma;
+ unsigned int val, val2;
+ u64 val_64;
+- u32 page_size, temp;
++ u32 temp;
+ int i;
+
+ INIT_LIST_HEAD(&xhci->cmd_list);
+@@ -2394,20 +2409,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
+ INIT_DELAYED_WORK(&xhci->cmd_timer, xhci_handle_command_timeout);
+ init_completion(&xhci->cmd_ring_stop_completion);
+
+- page_size = readl(&xhci->op_regs->page_size);
+- xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+- "Supported page size register = 0x%x", page_size);
+- val = ffs(page_size) - 1;
+- if (val < 16)
+- xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+- "Supported page size of %iK", (1 << (val + 12)) / 1024);
+- else
+- xhci_warn(xhci, "WARN: no supported page size\n");
+- /* Use 4K pages, since that's common and the minimum the HC supports */
+- xhci->page_shift = 12;
+- xhci->page_size = 1 << xhci->page_shift;
+- xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+- "HCD page size set to %iK", xhci->page_size / 1024);
++ xhci_hcd_page_size(xhci);
+
+ /*
+ * Program the Number of Device Slots Enabled field in the CONFIG
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index 2a954efa53e80..c4d5b90ef90a8 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -211,6 +211,9 @@ struct xhci_op_regs {
+ #define CONFIG_CIE (1 << 9)
+ /* bits 10:31 - reserved and should be preserved */
+
++/* bits 15:0 - HCD page shift bit */
++#define XHCI_PAGE_SIZE_MASK 0xffff
++
+ /**
+ * struct xhci_intr_reg - Interrupt Register Set
+ * @irq_pending: IMAN - Interrupt Management Register. Used to enable
+@@ -1503,10 +1506,7 @@ struct xhci_hcd {
+ u16 max_interrupters;
+ /* imod_interval in ns (I * 250ns) */
+ u32 imod_interval;
+- /* 4KB min, 128MB max */
+- int page_size;
+- /* Valid values are 12 to 20, inclusive */
+- int page_shift;
++ u32 page_size;
+ /* MSI-X/MSI vectors */
+ int nvecs;
+ /* optional clocks */
+--
+2.39.5
+
--- /dev/null
+From ac813a8ecf94773fabcdf582b4365b15787a48b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Feb 2025 11:31:27 -0600
+Subject: vdpa/mlx5: Fix mlx5_vdpa_get_config() endianness on big-endian
+ machines
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Konstantin Shkolnyy <kshk@linux.ibm.com>
+
+[ Upstream commit 439252e167ac45a5d46f573aac1da7d8f3e051ad ]
+
+mlx5_vdpa_dev_add() doesn’t initialize mvdev->actual_features. It’s
+initialized later by mlx5_vdpa_set_driver_features(). However,
+mlx5_vdpa_get_config() depends on the VIRTIO_F_VERSION_1 flag in
+actual_features, to return data with correct endianness. When it’s called
+before mlx5_vdpa_set_driver_features(), the data are incorrectly returned
+as big-endian on big-endian machines, while QEMU then interprets them as
+little-endian.
+
+The fix is to initialize this VIRTIO_F_VERSION_1 as early as possible,
+especially considering that mlx5_vdpa_dev_add() insists on this flag to
+always be set anyway.
+
+Signed-off-by: Konstantin Shkolnyy <kshk@linux.ibm.com>
+Message-Id: <20250204173127.166673-1-kshk@linux.ibm.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vdpa/mlx5/net/mlx5_vnet.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c
+index 5f581e71e2010..76aedac37a788 100644
+--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c
++++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
+@@ -3884,6 +3884,9 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name,
+ ndev->mvdev.max_vqs = max_vqs;
+ mvdev = &ndev->mvdev;
+ mvdev->mdev = mdev;
++ /* cpu_to_mlx5vdpa16() below depends on this flag */
++ mvdev->actual_features =
++ (device_features & BIT_ULL(VIRTIO_F_VERSION_1));
+
+ ndev->vqs = kcalloc(max_vqs, sizeof(*ndev->vqs), GFP_KERNEL);
+ ndev->event_cbs = kcalloc(max_vqs + 1, sizeof(*ndev->event_cbs), GFP_KERNEL);
+--
+2.39.5
+
--- /dev/null
+From 599f1568fe8d98f804e5b3cc4b210385085d1b54 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Mar 2025 17:06:21 -0600
+Subject: vfio/pci: Handle INTx IRQ_NOTCONNECTED
+
+From: Alex Williamson <alex.williamson@redhat.com>
+
+[ Upstream commit 860be250fc32de9cb24154bf21b4e36f40925707 ]
+
+Some systems report INTx as not routed by setting pdev->irq to
+IRQ_NOTCONNECTED, resulting in a -ENOTCONN error when trying to
+setup eventfd signaling. Include this in the set of conditions
+for which the PIN register is virtualized to zero.
+
+Additionally consolidate vfio_pci_get_irq_count() to use this
+virtualized value in reporting INTx support via ioctl and sanity
+checking ioctl paths since pdev->irq is re-used when the device
+is in MSI mode.
+
+The combination of these results in both the config space of the
+device and the ioctl interface behaving as if the device does not
+support INTx.
+
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Link: https://lore.kernel.org/r/20250311230623.1264283-1-alex.williamson@redhat.com
+Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vfio/pci/vfio_pci_config.c | 3 ++-
+ drivers/vfio/pci/vfio_pci_core.c | 10 +---------
+ drivers/vfio/pci/vfio_pci_intrs.c | 2 +-
+ 3 files changed, 4 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
+index ea2745c1ac5e6..8ea38e7421df4 100644
+--- a/drivers/vfio/pci/vfio_pci_config.c
++++ b/drivers/vfio/pci/vfio_pci_config.c
+@@ -1813,7 +1813,8 @@ int vfio_config_init(struct vfio_pci_core_device *vdev)
+ cpu_to_le16(PCI_COMMAND_MEMORY);
+ }
+
+- if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx)
++ if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx ||
++ vdev->pdev->irq == IRQ_NOTCONNECTED)
+ vconfig[PCI_INTERRUPT_PIN] = 0;
+
+ ret = vfio_cap_init(vdev);
+diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
+index c9eaba2276365..087c273a547fa 100644
+--- a/drivers/vfio/pci/vfio_pci_core.c
++++ b/drivers/vfio/pci/vfio_pci_core.c
+@@ -727,15 +727,7 @@ EXPORT_SYMBOL_GPL(vfio_pci_core_finish_enable);
+ static int vfio_pci_get_irq_count(struct vfio_pci_core_device *vdev, int irq_type)
+ {
+ if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) {
+- u8 pin;
+-
+- if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) ||
+- vdev->nointx || vdev->pdev->is_virtfn)
+- return 0;
+-
+- pci_read_config_byte(vdev->pdev, PCI_INTERRUPT_PIN, &pin);
+-
+- return pin ? 1 : 0;
++ return vdev->vconfig[PCI_INTERRUPT_PIN] ? 1 : 0;
+ } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) {
+ u8 pos;
+ u16 flags;
+diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
+index 8382c58343356..565966351dfad 100644
+--- a/drivers/vfio/pci/vfio_pci_intrs.c
++++ b/drivers/vfio/pci/vfio_pci_intrs.c
+@@ -259,7 +259,7 @@ static int vfio_intx_enable(struct vfio_pci_core_device *vdev,
+ if (!is_irq_none(vdev))
+ return -EINVAL;
+
+- if (!pdev->irq)
++ if (!pdev->irq || pdev->irq == IRQ_NOTCONNECTED)
+ return -ENODEV;
+
+ name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-intx(%s)", pci_name(pdev));
+--
+2.39.5
+
--- /dev/null
+From be3a28326ee30cad49baa936163f7c49fb3f6ad8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Apr 2025 23:29:46 -0700
+Subject: vhost-scsi: protect vq->log_used with vq->mutex
+
+From: Dongli Zhang <dongli.zhang@oracle.com>
+
+[ Upstream commit f591cf9fce724e5075cc67488c43c6e39e8cbe27 ]
+
+The vhost-scsi completion path may access vq->log_base when vq->log_used is
+already set to false.
+
+ vhost-thread QEMU-thread
+
+vhost_scsi_complete_cmd_work()
+-> vhost_add_used()
+ -> vhost_add_used_n()
+ if (unlikely(vq->log_used))
+ QEMU disables vq->log_used
+ via VHOST_SET_VRING_ADDR.
+ mutex_lock(&vq->mutex);
+ vq->log_used = false now!
+ mutex_unlock(&vq->mutex);
+
+ QEMU gfree(vq->log_base)
+ log_used()
+ -> log_write(vq->log_base)
+
+Assuming the VMM is QEMU. The vq->log_base is from QEMU userpace and can be
+reclaimed via gfree(). As a result, this causes invalid memory writes to
+QEMU userspace.
+
+The control queue path has the same issue.
+
+Signed-off-by: Dongli Zhang <dongli.zhang@oracle.com>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Reviewed-by: Mike Christie <michael.christie@oracle.com>
+Message-Id: <20250403063028.16045-2-dongli.zhang@oracle.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vhost/scsi.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
+index 35a03306d1345..ecad2f53b7635 100644
+--- a/drivers/vhost/scsi.c
++++ b/drivers/vhost/scsi.c
+@@ -571,6 +571,9 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
+ int ret;
+
+ llnode = llist_del_all(&svq->completion_list);
++
++ mutex_lock(&svq->vq.mutex);
++
+ llist_for_each_entry_safe(cmd, t, llnode, tvc_completion_list) {
+ se_cmd = &cmd->tvc_se_cmd;
+
+@@ -604,6 +607,8 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
+ vhost_scsi_release_cmd_res(se_cmd);
+ }
+
++ mutex_unlock(&svq->vq.mutex);
++
+ if (signal)
+ vhost_signal(&svq->vs->dev, &svq->vq);
+ }
+@@ -1346,8 +1351,11 @@ static void vhost_scsi_tmf_resp_work(struct vhost_work *work)
+ else
+ resp_code = VIRTIO_SCSI_S_FUNCTION_REJECTED;
+
++ mutex_lock(&tmf->svq->vq.mutex);
+ vhost_scsi_send_tmf_resp(tmf->vhost, &tmf->svq->vq, tmf->in_iovs,
+ tmf->vq_desc, &tmf->resp_iov, resp_code);
++ mutex_unlock(&tmf->svq->vq.mutex);
++
+ vhost_scsi_release_tmf_res(tmf);
+ }
+
+--
+2.39.5
+
--- /dev/null
+From ce67bfc522b2d6ba2c694ae607336d34a4173ecb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 13:15:11 -0600
+Subject: vhost-scsi: Return queue full for page alloc failures during copy
+
+From: Mike Christie <michael.christie@oracle.com>
+
+[ Upstream commit 891b99eab0f89dbe08d216f4ab71acbeaf7a3102 ]
+
+This has us return queue full if we can't allocate a page during the
+copy operation so the initiator can retry.
+
+Signed-off-by: Mike Christie <michael.christie@oracle.com>
+Message-Id: <20241203191705.19431-5-michael.christie@oracle.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vhost/scsi.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
+index ecad2f53b7635..38d243d914d00 100644
+--- a/drivers/vhost/scsi.c
++++ b/drivers/vhost/scsi.c
+@@ -762,7 +762,7 @@ vhost_scsi_copy_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter,
+ size_t len = iov_iter_count(iter);
+ unsigned int nbytes = 0;
+ struct page *page;
+- int i;
++ int i, ret;
+
+ if (cmd->tvc_data_direction == DMA_FROM_DEVICE) {
+ cmd->saved_iter_addr = dup_iter(&cmd->saved_iter, iter,
+@@ -775,6 +775,7 @@ vhost_scsi_copy_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter,
+ page = alloc_page(GFP_KERNEL);
+ if (!page) {
+ i--;
++ ret = -ENOMEM;
+ goto err;
+ }
+
+@@ -782,8 +783,10 @@ vhost_scsi_copy_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter,
+ sg_set_page(&sg[i], page, nbytes, 0);
+
+ if (cmd->tvc_data_direction == DMA_TO_DEVICE &&
+- copy_page_from_iter(page, 0, nbytes, iter) != nbytes)
++ copy_page_from_iter(page, 0, nbytes, iter) != nbytes) {
++ ret = -EFAULT;
+ goto err;
++ }
+
+ len -= nbytes;
+ }
+@@ -798,7 +801,7 @@ vhost_scsi_copy_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter,
+ for (; i >= 0; i--)
+ __free_page(sg_page(&sg[i]));
+ kfree(cmd->saved_iter_addr);
+- return -ENOMEM;
++ return ret;
+ }
+
+ static int
+@@ -1282,9 +1285,9 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
+ " %d\n", cmd, exp_data_len, prot_bytes, data_direction);
+
+ if (data_direction != DMA_NONE) {
+- if (unlikely(vhost_scsi_mapal(cmd, prot_bytes,
+- &prot_iter, exp_data_len,
+- &data_iter))) {
++ ret = vhost_scsi_mapal(cmd, prot_bytes, &prot_iter,
++ exp_data_len, &data_iter);
++ if (unlikely(ret)) {
+ vq_err(vq, "Failed to map iov to sgl\n");
+ vhost_scsi_release_cmd_res(&cmd->tvc_se_cmd);
+ goto err;
+--
+2.39.5
+
--- /dev/null
+From f378c9e3e4ef85e66bb0aac8ccafad71c0fb5e72 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Mar 2025 13:44:35 +0100
+Subject: vhost_task: fix vhost_task_create() documentation
+
+From: Stefano Garzarella <sgarzare@redhat.com>
+
+[ Upstream commit fec0abf52609c20279243699d08b660c142ce0aa ]
+
+Commit cb380909ae3b ("vhost: return task creation error instead of NULL")
+changed the return value of vhost_task_create(), but did not update the
+documentation.
+
+Reflect the change in the documentation: on an error, vhost_task_create()
+returns an ERR_PTR() and no longer NULL.
+
+Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
+Message-Id: <20250327124435.142831-1-sgarzare@redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/vhost_task.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/vhost_task.c b/kernel/vhost_task.c
+index 2ef2e1b800916..2f844c279a3e0 100644
+--- a/kernel/vhost_task.c
++++ b/kernel/vhost_task.c
+@@ -111,7 +111,7 @@ EXPORT_SYMBOL_GPL(vhost_task_stop);
+ * @arg: data to be passed to fn and handled_kill
+ * @name: the thread's name
+ *
+- * This returns a specialized task for use by the vhost layer or NULL on
++ * This returns a specialized task for use by the vhost layer or ERR_PTR() on
+ * failure. The returned task is inactive, and the caller must fire it up
+ * through vhost_task_start().
+ */
+--
+2.39.5
+
--- /dev/null
+From edcd4e5d7c5772a609bede9e26e49dbf70acddee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Mar 2025 21:04:12 +0800
+Subject: virtio_ring: Fix data race by tagging event_triggered as racy for
+ KCSAN
+
+From: Zhongqiu Han <quic_zhonhan@quicinc.com>
+
+[ Upstream commit 2e2f925fe737576df2373931c95e1a2b66efdfef ]
+
+syzbot reports a data-race when accessing the event_triggered, here is the
+simplified stack when the issue occurred:
+
+==================================================================
+BUG: KCSAN: data-race in virtqueue_disable_cb / virtqueue_enable_cb_delayed
+
+write to 0xffff8881025bc452 of 1 bytes by task 3288 on cpu 0:
+ virtqueue_enable_cb_delayed+0x42/0x3c0 drivers/virtio/virtio_ring.c:2653
+ start_xmit+0x230/0x1310 drivers/net/virtio_net.c:3264
+ __netdev_start_xmit include/linux/netdevice.h:5151 [inline]
+ netdev_start_xmit include/linux/netdevice.h:5160 [inline]
+ xmit_one net/core/dev.c:3800 [inline]
+
+read to 0xffff8881025bc452 of 1 bytes by interrupt on cpu 1:
+ virtqueue_disable_cb_split drivers/virtio/virtio_ring.c:880 [inline]
+ virtqueue_disable_cb+0x92/0x180 drivers/virtio/virtio_ring.c:2566
+ skb_xmit_done+0x5f/0x140 drivers/net/virtio_net.c:777
+ vring_interrupt+0x161/0x190 drivers/virtio/virtio_ring.c:2715
+ __handle_irq_event_percpu+0x95/0x490 kernel/irq/handle.c:158
+ handle_irq_event_percpu kernel/irq/handle.c:193 [inline]
+
+value changed: 0x01 -> 0x00
+==================================================================
+
+When the data race occurs, the function virtqueue_enable_cb_delayed() sets
+event_triggered to false, and virtqueue_disable_cb_split/packed() reads it
+as false due to the race condition. Since event_triggered is an unreliable
+hint used for optimization, this should only cause the driver temporarily
+suggest that the device not send an interrupt notification when the event
+index is used.
+
+Fix this KCSAN reported data-race issue by explicitly tagging the access as
+data_racy.
+
+Reported-by: syzbot+efe683d57990864b8c8e@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/all/67c7761a.050a0220.15b4b9.0018.GAE@google.com/
+Signed-off-by: Zhongqiu Han <quic_zhonhan@quicinc.com>
+Message-Id: <20250312130412.3516307-1-quic_zhonhan@quicinc.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/virtio/virtio_ring.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
+index 1f8a322eb00be..147926c8bae09 100644
+--- a/drivers/virtio/virtio_ring.c
++++ b/drivers/virtio/virtio_ring.c
+@@ -2530,7 +2530,7 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *_vq)
+ struct vring_virtqueue *vq = to_vvq(_vq);
+
+ if (vq->event_triggered)
+- vq->event_triggered = false;
++ data_race(vq->event_triggered = false);
+
+ return vq->packed_ring ? virtqueue_enable_cb_delayed_packed(_vq) :
+ virtqueue_enable_cb_delayed_split(_vq);
+--
+2.39.5
+
--- /dev/null
+From ace72a73123362e6535f029b324eb26418ac15b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Feb 2025 16:55:42 +0200
+Subject: vxlan: Annotate FDB data races
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit f6205f8215f12a96518ac9469ff76294ae7bd612 ]
+
+The 'used' and 'updated' fields in the FDB entry structure can be
+accessed concurrently by multiple threads, leading to reports such as
+[1]. Can be reproduced using [2].
+
+Suppress these reports by annotating these accesses using
+READ_ONCE() / WRITE_ONCE().
+
+[1]
+BUG: KCSAN: data-race in vxlan_xmit / vxlan_xmit
+
+write to 0xffff942604d263a8 of 8 bytes by task 286 on cpu 0:
+ vxlan_xmit+0xb29/0x2380
+ dev_hard_start_xmit+0x84/0x2f0
+ __dev_queue_xmit+0x45a/0x1650
+ packet_xmit+0x100/0x150
+ packet_sendmsg+0x2114/0x2ac0
+ __sys_sendto+0x318/0x330
+ __x64_sys_sendto+0x76/0x90
+ x64_sys_call+0x14e8/0x1c00
+ do_syscall_64+0x9e/0x1a0
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+read to 0xffff942604d263a8 of 8 bytes by task 287 on cpu 2:
+ vxlan_xmit+0xadf/0x2380
+ dev_hard_start_xmit+0x84/0x2f0
+ __dev_queue_xmit+0x45a/0x1650
+ packet_xmit+0x100/0x150
+ packet_sendmsg+0x2114/0x2ac0
+ __sys_sendto+0x318/0x330
+ __x64_sys_sendto+0x76/0x90
+ x64_sys_call+0x14e8/0x1c00
+ do_syscall_64+0x9e/0x1a0
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+value changed: 0x00000000fffbac6e -> 0x00000000fffbac6f
+
+Reported by Kernel Concurrency Sanitizer on:
+CPU: 2 UID: 0 PID: 287 Comm: mausezahn Not tainted 6.13.0-rc7-01544-gb4b270f11a02 #5
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-3.fc41 04/01/2014
+
+[2]
+ #!/bin/bash
+
+ set +H
+ echo whitelist > /sys/kernel/debug/kcsan
+ echo !vxlan_xmit > /sys/kernel/debug/kcsan
+
+ ip link add name vx0 up type vxlan id 10010 dstport 4789 local 192.0.2.1
+ bridge fdb add 00:11:22:33:44:55 dev vx0 self static dst 198.51.100.1
+ taskset -c 0 mausezahn vx0 -a own -b 00:11:22:33:44:55 -c 0 -q &
+ taskset -c 2 mausezahn vx0 -a own -b 00:11:22:33:44:55 -c 0 -q &
+
+Reviewed-by: Petr Machata <petrm@nvidia.com>
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
+Link: https://patch.msgid.link/20250204145549.1216254-2-idosch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_core.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
+index 01f66760e1328..474faccf75fd9 100644
+--- a/drivers/net/vxlan/vxlan_core.c
++++ b/drivers/net/vxlan/vxlan_core.c
+@@ -227,9 +227,9 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
+ be32_to_cpu(fdb->vni)))
+ goto nla_put_failure;
+
+- ci.ndm_used = jiffies_to_clock_t(now - fdb->used);
++ ci.ndm_used = jiffies_to_clock_t(now - READ_ONCE(fdb->used));
+ ci.ndm_confirmed = 0;
+- ci.ndm_updated = jiffies_to_clock_t(now - fdb->updated);
++ ci.ndm_updated = jiffies_to_clock_t(now - READ_ONCE(fdb->updated));
+ ci.ndm_refcnt = 0;
+
+ if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
+@@ -434,8 +434,8 @@ static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan,
+ struct vxlan_fdb *f;
+
+ f = __vxlan_find_mac(vxlan, mac, vni);
+- if (f && f->used != jiffies)
+- f->used = jiffies;
++ if (f && READ_ONCE(f->used) != jiffies)
++ WRITE_ONCE(f->used, jiffies);
+
+ return f;
+ }
+@@ -1009,12 +1009,12 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan,
+ !(f->flags & NTF_VXLAN_ADDED_BY_USER)) {
+ if (f->state != state) {
+ f->state = state;
+- f->updated = jiffies;
++ WRITE_ONCE(f->updated, jiffies);
+ notify = 1;
+ }
+ if (f->flags != fdb_flags) {
+ f->flags = fdb_flags;
+- f->updated = jiffies;
++ WRITE_ONCE(f->updated, jiffies);
+ notify = 1;
+ }
+ }
+@@ -1048,7 +1048,7 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan,
+ }
+
+ if (ndm_flags & NTF_USE)
+- f->used = jiffies;
++ WRITE_ONCE(f->used, jiffies);
+
+ if (notify) {
+ if (rd == NULL)
+@@ -1477,7 +1477,7 @@ static bool vxlan_snoop(struct net_device *dev,
+ src_mac, &rdst->remote_ip.sa, &src_ip->sa);
+
+ rdst->remote_ip = *src_ip;
+- f->updated = jiffies;
++ WRITE_ONCE(f->updated, jiffies);
+ vxlan_fdb_notify(vxlan, f, rdst, RTM_NEWNEIGH, true, NULL);
+ } else {
+ u32 hash_index = fdb_head_index(vxlan, src_mac, vni);
+@@ -2825,7 +2825,7 @@ static void vxlan_cleanup(struct timer_list *t)
+ if (f->flags & NTF_EXT_LEARNED)
+ continue;
+
+- timeout = f->used + vxlan->cfg.age_interval * HZ;
++ timeout = READ_ONCE(f->used) + vxlan->cfg.age_interval * HZ;
+ if (time_before_eq(timeout, jiffies)) {
+ netdev_dbg(vxlan->dev,
+ "garbage collect %pM\n",
+--
+2.39.5
+
--- /dev/null
+From 576644915f40ebe078ae5b0775a49d23fda53177 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Feb 2025 17:18:21 +0100
+Subject: vxlan: Join / leave MC group after remote changes
+
+From: Petr Machata <petrm@nvidia.com>
+
+[ Upstream commit d42d543368343c0449a4e433b5f02e063a86209c ]
+
+When a vxlan netdevice is brought up, if its default remote is a multicast
+address, the device joins the indicated group.
+
+Therefore when the multicast remote address changes, the device should
+leave the current group and subscribe to the new one. Similarly when the
+interface used for endpoint communication is changed in a situation when
+multicast remote is configured. This is currently not done.
+
+Both vxlan_igmp_join() and vxlan_igmp_leave() can however fail. So it is
+possible that with such fix, the netdevice will end up in an inconsistent
+situation where the old group is not joined anymore, but joining the new
+group fails. Should we join the new group first, and leave the old one
+second, we might end up in the opposite situation, where both groups are
+joined. Undoing any of this during rollback is going to be similarly
+problematic.
+
+One solution would be to just forbid the change when the netdevice is up.
+However in vnifilter mode, changing the group address is allowed, and these
+problems are simply ignored (see vxlan_vni_update_group()):
+
+ # ip link add name br up type bridge vlan_filtering 1
+ # ip link add vx1 up master br type vxlan external vnifilter local 192.0.2.1 dev lo dstport 4789
+ # bridge vni add dev vx1 vni 200 group 224.0.0.1
+ # tcpdump -i lo &
+ # bridge vni add dev vx1 vni 200 group 224.0.0.2
+ 18:55:46.523438 IP 0.0.0.0 > 224.0.0.22: igmp v3 report, 1 group record(s)
+ 18:55:46.943447 IP 0.0.0.0 > 224.0.0.22: igmp v3 report, 1 group record(s)
+ # bridge vni
+ dev vni group/remote
+ vx1 200 224.0.0.2
+
+Having two different modes of operation for conceptually the same interface
+is silly, so in this patch, just do what the vnifilter code does and deal
+with the errors by crossing fingers real hard.
+
+The vnifilter code leaves old before joining new, and in case of join /
+leave failures does not roll back the configuration changes that have
+already been applied, but bails out of joining if it could not leave. Do
+the same here: leave before join, apply changes unconditionally and do not
+attempt to join if we couldn't leave.
+
+Signed-off-by: Petr Machata <petrm@nvidia.com>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_core.c | 18 ++++++++++++++++--
+ 1 file changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
+index 5e7cdd1b806fb..01f66760e1328 100644
+--- a/drivers/net/vxlan/vxlan_core.c
++++ b/drivers/net/vxlan/vxlan_core.c
+@@ -4340,6 +4340,7 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
+ struct netlink_ext_ack *extack)
+ {
+ struct vxlan_dev *vxlan = netdev_priv(dev);
++ bool rem_ip_changed, change_igmp;
+ struct net_device *lowerdev;
+ struct vxlan_config conf;
+ struct vxlan_rdst *dst;
+@@ -4363,8 +4364,13 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
+ if (err)
+ return err;
+
++ rem_ip_changed = !vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip);
++ change_igmp = vxlan->dev->flags & IFF_UP &&
++ (rem_ip_changed ||
++ dst->remote_ifindex != conf.remote_ifindex);
++
+ /* handle default dst entry */
+- if (!vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip)) {
++ if (rem_ip_changed) {
+ u32 hash_index = fdb_head_index(vxlan, all_zeros_mac, conf.vni);
+
+ spin_lock_bh(&vxlan->hash_lock[hash_index]);
+@@ -4408,6 +4414,9 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
+ }
+ }
+
++ if (change_igmp && vxlan_addr_multicast(&dst->remote_ip))
++ err = vxlan_multicast_leave(vxlan);
++
+ if (conf.age_interval != vxlan->cfg.age_interval)
+ mod_timer(&vxlan->age_timer, jiffies);
+
+@@ -4415,7 +4424,12 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
+ if (lowerdev && lowerdev != dst->remote_dev)
+ dst->remote_dev = lowerdev;
+ vxlan_config_apply(dev, &conf, lowerdev, vxlan->net, true);
+- return 0;
++
++ if (!err && change_igmp &&
++ vxlan_addr_multicast(&dst->remote_ip))
++ err = vxlan_multicast_join(vxlan);
++
++ return err;
+ }
+
+ static void vxlan_dellink(struct net_device *dev, struct list_head *head)
+--
+2.39.5
+
--- /dev/null
+From 1fd8fea7a5d3a95b6a0a26adc71bd656c455f453 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jan 2025 17:37:37 +0800
+Subject: watchdog: aspeed: Update bootstatus handling
+
+From: Chin-Ting Kuo <chin-ting_kuo@aspeedtech.com>
+
+[ Upstream commit 5c03f9f4d36292150c14ebd90788c4d3273ed9dc ]
+
+The boot status in the watchdog device struct is updated during
+controller probe stage. Application layer can get the boot status
+through the command, cat /sys/class/watchdog/watchdogX/bootstatus.
+The bootstatus can be,
+WDIOF_CARDRESET => System is reset due to WDT timeout occurs.
+Others => Other reset events, e.g., power on reset.
+
+On ASPEED platforms, boot status is recorded in the SCU registers.
+- AST2400: Only a bit is used to represent system reset triggered by
+ any WDT controller.
+- AST2500/AST2600: System reset triggered by different WDT controllers
+ can be distinguished by different SCU bits.
+
+Besides, on AST2400 and AST2500, since alternating boot event is
+also triggered by using WDT timeout mechanism, it is classified
+as WDIOF_CARDRESET.
+
+Signed-off-by: Chin-Ting Kuo <chin-ting_kuo@aspeedtech.com>
+Reviewed-by: Andrew Jeffery <andrew@codeconstruct.com.au>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Link: https://lore.kernel.org/r/20250113093737.845097-2-chin-ting_kuo@aspeedtech.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/watchdog/aspeed_wdt.c | 81 ++++++++++++++++++++++++++++++++++-
+ 1 file changed, 79 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c
+index b4773a6aaf8cc..369635b38ca0e 100644
+--- a/drivers/watchdog/aspeed_wdt.c
++++ b/drivers/watchdog/aspeed_wdt.c
+@@ -11,21 +11,30 @@
+ #include <linux/io.h>
+ #include <linux/kernel.h>
+ #include <linux/kstrtox.h>
++#include <linux/mfd/syscon.h>
+ #include <linux/module.h>
+ #include <linux/of.h>
+ #include <linux/of_irq.h>
+ #include <linux/platform_device.h>
++#include <linux/regmap.h>
+ #include <linux/watchdog.h>
+
+ static bool nowayout = WATCHDOG_NOWAYOUT;
+ module_param(nowayout, bool, 0);
+ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
++struct aspeed_wdt_scu {
++ const char *compatible;
++ u32 reset_status_reg;
++ u32 wdt_reset_mask;
++ u32 wdt_reset_mask_shift;
++};
+
+ struct aspeed_wdt_config {
+ u32 ext_pulse_width_mask;
+ u32 irq_shift;
+ u32 irq_mask;
++ struct aspeed_wdt_scu scu;
+ };
+
+ struct aspeed_wdt {
+@@ -39,18 +48,36 @@ static const struct aspeed_wdt_config ast2400_config = {
+ .ext_pulse_width_mask = 0xff,
+ .irq_shift = 0,
+ .irq_mask = 0,
++ .scu = {
++ .compatible = "aspeed,ast2400-scu",
++ .reset_status_reg = 0x3c,
++ .wdt_reset_mask = 0x1,
++ .wdt_reset_mask_shift = 1,
++ },
+ };
+
+ static const struct aspeed_wdt_config ast2500_config = {
+ .ext_pulse_width_mask = 0xfffff,
+ .irq_shift = 12,
+ .irq_mask = GENMASK(31, 12),
++ .scu = {
++ .compatible = "aspeed,ast2500-scu",
++ .reset_status_reg = 0x3c,
++ .wdt_reset_mask = 0x1,
++ .wdt_reset_mask_shift = 2,
++ },
+ };
+
+ static const struct aspeed_wdt_config ast2600_config = {
+ .ext_pulse_width_mask = 0xfffff,
+ .irq_shift = 0,
+ .irq_mask = GENMASK(31, 10),
++ .scu = {
++ .compatible = "aspeed,ast2600-scu",
++ .reset_status_reg = 0x74,
++ .wdt_reset_mask = 0xf,
++ .wdt_reset_mask_shift = 16,
++ },
+ };
+
+ static const struct of_device_id aspeed_wdt_of_table[] = {
+@@ -213,6 +240,56 @@ static int aspeed_wdt_restart(struct watchdog_device *wdd,
+ return 0;
+ }
+
++static void aspeed_wdt_update_bootstatus(struct platform_device *pdev,
++ struct aspeed_wdt *wdt)
++{
++ const struct resource *res;
++ struct aspeed_wdt_scu scu = wdt->cfg->scu;
++ struct regmap *scu_base;
++ u32 reset_mask_width;
++ u32 reset_mask_shift;
++ u32 idx = 0;
++ u32 status;
++ int ret;
++
++ if (!of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt")) {
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ idx = ((intptr_t)wdt->base & 0x00000fff) / resource_size(res);
++ }
++
++ scu_base = syscon_regmap_lookup_by_compatible(scu.compatible);
++ if (IS_ERR(scu_base)) {
++ wdt->wdd.bootstatus = WDIOS_UNKNOWN;
++ return;
++ }
++
++ ret = regmap_read(scu_base, scu.reset_status_reg, &status);
++ if (ret) {
++ wdt->wdd.bootstatus = WDIOS_UNKNOWN;
++ return;
++ }
++
++ reset_mask_width = hweight32(scu.wdt_reset_mask);
++ reset_mask_shift = scu.wdt_reset_mask_shift +
++ reset_mask_width * idx;
++
++ if (status & (scu.wdt_reset_mask << reset_mask_shift))
++ wdt->wdd.bootstatus = WDIOF_CARDRESET;
++
++ /* clear wdt reset event flag */
++ if (of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt") ||
++ of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2500-wdt")) {
++ ret = regmap_read(scu_base, scu.reset_status_reg, &status);
++ if (!ret) {
++ status &= ~(scu.wdt_reset_mask << reset_mask_shift);
++ regmap_write(scu_base, scu.reset_status_reg, status);
++ }
++ } else {
++ regmap_write(scu_base, scu.reset_status_reg,
++ scu.wdt_reset_mask << reset_mask_shift);
++ }
++}
++
+ /* access_cs0 shows if cs0 is accessible, hence the reverted bit */
+ static ssize_t access_cs0_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+@@ -458,10 +535,10 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
+ writel(duration - 1, wdt->base + WDT_RESET_WIDTH);
+ }
+
++ aspeed_wdt_update_bootstatus(pdev, wdt);
++
+ status = readl(wdt->base + WDT_TIMEOUT_STATUS);
+ if (status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY) {
+- wdt->wdd.bootstatus = WDIOF_CARDRESET;
+-
+ if (of_device_is_compatible(np, "aspeed,ast2400-wdt") ||
+ of_device_is_compatible(np, "aspeed,ast2500-wdt"))
+ wdt->wdd.groups = bswitch_groups;
+--
+2.39.5
+
--- /dev/null
+From c5775b6da8875b32f425f425ba1b13d3fe475d6c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 19 Jan 2025 22:12:19 +0530
+Subject: wifi: ath11k: Use dma_alloc_noncoherent for rx_tid buffer allocation
+
+From: P Praneesh <quic_ppranees@quicinc.com>
+
+[ Upstream commit eeadc6baf8b3dcd32787cc84f0473dc2a2850370 ]
+
+Currently, the driver allocates cacheable DMA buffers for the rx_tid
+structure using kzalloc() and dma_map_single(). These buffers are
+long-lived and can persist for the lifetime of the peer, which is not
+advisable. Instead of using kzalloc() and dma_map_single() for allocating
+cacheable DMA buffers, utilize the dma_alloc_noncoherent() helper for the
+allocation of long-lived cacheable DMA buffers, such as the peer's rx_tid.
+Since dma_alloc_noncoherent() returns unaligned physical and virtual
+addresses, align them internally before use within the driver. This
+ensures proper allocation of non-coherent memory through the kernel
+helper.
+
+Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1
+Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3
+
+Signed-off-by: P Praneesh <quic_ppranees@quicinc.com>
+Tested-by: Tim Harvey <tharvey@gateworks.com>
+Link: https://patch.msgid.link/20250119164219.647059-3-quic_ppranees@quicinc.com
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath11k/dp.h | 6 +-
+ drivers/net/wireless/ath/ath11k/dp_rx.c | 117 +++++++++++-------------
+ 2 files changed, 58 insertions(+), 65 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h
+index 65d2bc0687c88..eaf902c25e192 100644
+--- a/drivers/net/wireless/ath/ath11k/dp.h
++++ b/drivers/net/wireless/ath/ath11k/dp.h
+@@ -1,7 +1,7 @@
+ /* SPDX-License-Identifier: BSD-3-Clause-Clear */
+ /*
+ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2021-2023, 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ #ifndef ATH11K_DP_H
+@@ -20,7 +20,6 @@ struct ath11k_ext_irq_grp;
+
+ struct dp_rx_tid {
+ u8 tid;
+- u32 *vaddr;
+ dma_addr_t paddr;
+ u32 size;
+ u32 ba_win_sz;
+@@ -37,6 +36,9 @@ struct dp_rx_tid {
+ /* Timer info related to fragments */
+ struct timer_list frag_timer;
+ struct ath11k_base *ab;
++ u32 *vaddr_unaligned;
++ dma_addr_t paddr_unaligned;
++ u32 unaligned_size;
+ };
+
+ #define DP_REO_DESC_FREE_THRESHOLD 64
+diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
+index 40b52d12b4323..bfb8e7b1a300c 100644
+--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: BSD-3-Clause-Clear
+ /*
+ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ #include <linux/ieee80211.h>
+@@ -675,11 +675,11 @@ void ath11k_dp_reo_cmd_list_cleanup(struct ath11k_base *ab)
+ list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) {
+ list_del(&cmd->list);
+ rx_tid = &cmd->data;
+- if (rx_tid->vaddr) {
+- dma_unmap_single(ab->dev, rx_tid->paddr,
+- rx_tid->size, DMA_BIDIRECTIONAL);
+- kfree(rx_tid->vaddr);
+- rx_tid->vaddr = NULL;
++ if (rx_tid->vaddr_unaligned) {
++ dma_free_noncoherent(ab->dev, rx_tid->unaligned_size,
++ rx_tid->vaddr_unaligned,
++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
++ rx_tid->vaddr_unaligned = NULL;
+ }
+ kfree(cmd);
+ }
+@@ -689,11 +689,11 @@ void ath11k_dp_reo_cmd_list_cleanup(struct ath11k_base *ab)
+ list_del(&cmd_cache->list);
+ dp->reo_cmd_cache_flush_count--;
+ rx_tid = &cmd_cache->data;
+- if (rx_tid->vaddr) {
+- dma_unmap_single(ab->dev, rx_tid->paddr,
+- rx_tid->size, DMA_BIDIRECTIONAL);
+- kfree(rx_tid->vaddr);
+- rx_tid->vaddr = NULL;
++ if (rx_tid->vaddr_unaligned) {
++ dma_free_noncoherent(ab->dev, rx_tid->unaligned_size,
++ rx_tid->vaddr_unaligned,
++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
++ rx_tid->vaddr_unaligned = NULL;
+ }
+ kfree(cmd_cache);
+ }
+@@ -708,11 +708,11 @@ static void ath11k_dp_reo_cmd_free(struct ath11k_dp *dp, void *ctx,
+ if (status != HAL_REO_CMD_SUCCESS)
+ ath11k_warn(dp->ab, "failed to flush rx tid hw desc, tid %d status %d\n",
+ rx_tid->tid, status);
+- if (rx_tid->vaddr) {
+- dma_unmap_single(dp->ab->dev, rx_tid->paddr, rx_tid->size,
+- DMA_BIDIRECTIONAL);
+- kfree(rx_tid->vaddr);
+- rx_tid->vaddr = NULL;
++ if (rx_tid->vaddr_unaligned) {
++ dma_free_noncoherent(dp->ab->dev, rx_tid->unaligned_size,
++ rx_tid->vaddr_unaligned,
++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
++ rx_tid->vaddr_unaligned = NULL;
+ }
+ }
+
+@@ -749,10 +749,10 @@ static void ath11k_dp_reo_cache_flush(struct ath11k_base *ab,
+ if (ret) {
+ ath11k_err(ab, "failed to send HAL_REO_CMD_FLUSH_CACHE cmd, tid %d (%d)\n",
+ rx_tid->tid, ret);
+- dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size,
+- DMA_BIDIRECTIONAL);
+- kfree(rx_tid->vaddr);
+- rx_tid->vaddr = NULL;
++ dma_free_noncoherent(ab->dev, rx_tid->unaligned_size,
++ rx_tid->vaddr_unaligned,
++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
++ rx_tid->vaddr_unaligned = NULL;
+ }
+ }
+
+@@ -802,10 +802,10 @@ static void ath11k_dp_rx_tid_del_func(struct ath11k_dp *dp, void *ctx,
+
+ return;
+ free_desc:
+- dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size,
+- DMA_BIDIRECTIONAL);
+- kfree(rx_tid->vaddr);
+- rx_tid->vaddr = NULL;
++ dma_free_noncoherent(ab->dev, rx_tid->unaligned_size,
++ rx_tid->vaddr_unaligned,
++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
++ rx_tid->vaddr_unaligned = NULL;
+ }
+
+ void ath11k_peer_rx_tid_delete(struct ath11k *ar,
+@@ -831,14 +831,16 @@ void ath11k_peer_rx_tid_delete(struct ath11k *ar,
+ if (ret != -ESHUTDOWN)
+ ath11k_err(ar->ab, "failed to send HAL_REO_CMD_UPDATE_RX_QUEUE cmd, tid %d (%d)\n",
+ tid, ret);
+- dma_unmap_single(ar->ab->dev, rx_tid->paddr, rx_tid->size,
+- DMA_BIDIRECTIONAL);
+- kfree(rx_tid->vaddr);
+- rx_tid->vaddr = NULL;
++ dma_free_noncoherent(ar->ab->dev, rx_tid->unaligned_size,
++ rx_tid->vaddr_unaligned,
++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
++ rx_tid->vaddr_unaligned = NULL;
+ }
+
+ rx_tid->paddr = 0;
++ rx_tid->paddr_unaligned = 0;
+ rx_tid->size = 0;
++ rx_tid->unaligned_size = 0;
+ }
+
+ static int ath11k_dp_rx_link_desc_return(struct ath11k_base *ab,
+@@ -982,10 +984,9 @@ static void ath11k_dp_rx_tid_mem_free(struct ath11k_base *ab,
+ if (!rx_tid->active)
+ goto unlock_exit;
+
+- dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size,
+- DMA_BIDIRECTIONAL);
+- kfree(rx_tid->vaddr);
+- rx_tid->vaddr = NULL;
++ dma_free_noncoherent(ab->dev, rx_tid->unaligned_size, rx_tid->vaddr_unaligned,
++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
++ rx_tid->vaddr_unaligned = NULL;
+
+ rx_tid->active = false;
+
+@@ -1000,9 +1001,8 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id,
+ struct ath11k_base *ab = ar->ab;
+ struct ath11k_peer *peer;
+ struct dp_rx_tid *rx_tid;
+- u32 hw_desc_sz;
+- u32 *addr_aligned;
+- void *vaddr;
++ u32 hw_desc_sz, *vaddr;
++ void *vaddr_unaligned;
+ dma_addr_t paddr;
+ int ret;
+
+@@ -1050,49 +1050,40 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id,
+ else
+ hw_desc_sz = ath11k_hal_reo_qdesc_size(DP_BA_WIN_SZ_MAX, tid);
+
+- vaddr = kzalloc(hw_desc_sz + HAL_LINK_DESC_ALIGN - 1, GFP_ATOMIC);
+- if (!vaddr) {
++ rx_tid->unaligned_size = hw_desc_sz + HAL_LINK_DESC_ALIGN - 1;
++ vaddr_unaligned = dma_alloc_noncoherent(ab->dev, rx_tid->unaligned_size, &paddr,
++ DMA_BIDIRECTIONAL, GFP_ATOMIC);
++ if (!vaddr_unaligned) {
+ spin_unlock_bh(&ab->base_lock);
+ return -ENOMEM;
+ }
+
+- addr_aligned = PTR_ALIGN(vaddr, HAL_LINK_DESC_ALIGN);
+-
+- ath11k_hal_reo_qdesc_setup(addr_aligned, tid, ba_win_sz,
+- ssn, pn_type);
+-
+- paddr = dma_map_single(ab->dev, addr_aligned, hw_desc_sz,
+- DMA_BIDIRECTIONAL);
+-
+- ret = dma_mapping_error(ab->dev, paddr);
+- if (ret) {
+- spin_unlock_bh(&ab->base_lock);
+- ath11k_warn(ab, "failed to setup dma map for peer %pM rx tid %d: %d\n",
+- peer_mac, tid, ret);
+- goto err_mem_free;
+- }
+-
+- rx_tid->vaddr = vaddr;
+- rx_tid->paddr = paddr;
++ rx_tid->vaddr_unaligned = vaddr_unaligned;
++ vaddr = PTR_ALIGN(vaddr_unaligned, HAL_LINK_DESC_ALIGN);
++ rx_tid->paddr_unaligned = paddr;
++ rx_tid->paddr = rx_tid->paddr_unaligned + ((unsigned long)vaddr -
++ (unsigned long)rx_tid->vaddr_unaligned);
++ ath11k_hal_reo_qdesc_setup(vaddr, tid, ba_win_sz, ssn, pn_type);
+ rx_tid->size = hw_desc_sz;
+ rx_tid->active = true;
+
++ /* After dma_alloc_noncoherent, vaddr is being modified for reo qdesc setup.
++ * Since these changes are not reflected in the device, driver now needs to
++ * explicitly call dma_sync_single_for_device.
++ */
++ dma_sync_single_for_device(ab->dev, rx_tid->paddr,
++ rx_tid->size,
++ DMA_TO_DEVICE);
+ spin_unlock_bh(&ab->base_lock);
+
+- ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac,
+- paddr, tid, 1, ba_win_sz);
++ ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac, rx_tid->paddr,
++ tid, 1, ba_win_sz);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to setup rx reorder queue for peer %pM tid %d: %d\n",
+ peer_mac, tid, ret);
+ ath11k_dp_rx_tid_mem_free(ab, peer_mac, vdev_id, tid);
+ }
+
+- return ret;
+-
+-err_mem_free:
+- kfree(rx_tid->vaddr);
+- rx_tid->vaddr = NULL;
+-
+ return ret;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 0db630222afc021fdafd49c6a4c2b09ba19098c1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jan 2025 14:30:58 +0530
+Subject: wifi: ath12k: Avoid napi_sync() before napi_enable()
+
+From: Avula Sri Charan <quic_asrichar@quicinc.com>
+
+[ Upstream commit 268c73d470a5790a492a2fc2ded084b909d144f3 ]
+
+In case of MHI error a reset work will be queued which will try
+napi_disable() after napi_synchronize().
+
+As the napi will be only enabled after qmi_firmware_ready event,
+trying napi_synchronize() before napi_enable() will result in
+indefinite sleep in case of a firmware crash in QMI init sequence.
+
+To avoid this, introduce napi_enabled flag to check if napi is enabled
+or not before calling napi_synchronize().
+
+Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
+
+Signed-off-by: Avula Sri Charan <quic_asrichar@quicinc.com>
+Signed-off-by: Tamizh Chelvam Raja <quic_tamizhr@quicinc.com>
+Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>
+Link: https://patch.msgid.link/20250124090058.3194299-1-quic_tamizhr@quicinc.com
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/core.h | 1 +
+ drivers/net/wireless/ath/ath12k/pci.c | 13 ++++++++++---
+ 2 files changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
+index 7f2e9a9b40977..3faf3430effb9 100644
+--- a/drivers/net/wireless/ath/ath12k/core.h
++++ b/drivers/net/wireless/ath/ath12k/core.h
+@@ -148,6 +148,7 @@ struct ath12k_ext_irq_grp {
+ u32 num_irq;
+ u32 grp_id;
+ u64 timestamp;
++ bool napi_enabled;
+ struct napi_struct napi;
+ struct net_device *napi_ndev;
+ };
+diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
+index 2ff866e1d7d5b..45d537066345a 100644
+--- a/drivers/net/wireless/ath/ath12k/pci.c
++++ b/drivers/net/wireless/ath/ath12k/pci.c
+@@ -481,8 +481,11 @@ static void __ath12k_pci_ext_irq_disable(struct ath12k_base *ab)
+
+ ath12k_pci_ext_grp_disable(irq_grp);
+
+- napi_synchronize(&irq_grp->napi);
+- napi_disable(&irq_grp->napi);
++ if (irq_grp->napi_enabled) {
++ napi_synchronize(&irq_grp->napi);
++ napi_disable(&irq_grp->napi);
++ irq_grp->napi_enabled = false;
++ }
+ }
+ }
+
+@@ -1112,7 +1115,11 @@ void ath12k_pci_ext_irq_enable(struct ath12k_base *ab)
+ for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) {
+ struct ath12k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
+
+- napi_enable(&irq_grp->napi);
++ if (!irq_grp->napi_enabled) {
++ napi_enable(&irq_grp->napi);
++ irq_grp->napi_enabled = true;
++ }
++
+ ath12k_pci_ext_grp_enable(irq_grp);
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 7327c41d9f405f876a8ae1a9ec53b1f67665bbbf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jan 2025 08:58:35 +0530
+Subject: wifi: ath12k: Fetch regdb.bin file from board-2.bin
+
+From: Aaradhana Sahu <quic_aarasahu@quicinc.com>
+
+[ Upstream commit 24f587572acf7509127dbdfcbf1b681ef84eeba0 ]
+
+Currently, ath12k_core_fetch_regdb() finds regdb.bin file through
+board id's but in board-2.bin file regdb.bin file is present with
+default board id because of which regdb.bin is not fetched.
+
+Add support to fetch regdb.bin file from board-2.bin through
+default board id.
+
+Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
+
+Signed-off-by: Aaradhana Sahu <quic_aarasahu@quicinc.com>
+Reviewed-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
+Link: https://patch.msgid.link/20250116032835.118397-1-quic_aarasahu@quicinc.com
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/core.c | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
+index 51252e8bc1ae9..8bb8ee98188bf 100644
+--- a/drivers/net/wireless/ath/ath12k/core.c
++++ b/drivers/net/wireless/ath/ath12k/core.c
+@@ -161,7 +161,7 @@ EXPORT_SYMBOL(ath12k_core_resume);
+
+ static int __ath12k_core_create_board_name(struct ath12k_base *ab, char *name,
+ size_t name_len, bool with_variant,
+- bool bus_type_mode)
++ bool bus_type_mode, bool with_default)
+ {
+ /* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */
+ char variant[9 + ATH12K_QMI_BDF_EXT_STR_LENGTH] = { 0 };
+@@ -192,7 +192,9 @@ static int __ath12k_core_create_board_name(struct ath12k_base *ab, char *name,
+ "bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s",
+ ath12k_bus_str(ab->hif.bus),
+ ab->qmi.target.chip_id,
+- ab->qmi.target.board_id, variant);
++ with_default ?
++ ATH12K_BOARD_ID_DEFAULT : ab->qmi.target.board_id,
++ variant);
+ break;
+ }
+
+@@ -204,19 +206,19 @@ static int __ath12k_core_create_board_name(struct ath12k_base *ab, char *name,
+ static int ath12k_core_create_board_name(struct ath12k_base *ab, char *name,
+ size_t name_len)
+ {
+- return __ath12k_core_create_board_name(ab, name, name_len, true, false);
++ return __ath12k_core_create_board_name(ab, name, name_len, true, false, false);
+ }
+
+ static int ath12k_core_create_fallback_board_name(struct ath12k_base *ab, char *name,
+ size_t name_len)
+ {
+- return __ath12k_core_create_board_name(ab, name, name_len, false, false);
++ return __ath12k_core_create_board_name(ab, name, name_len, false, false, true);
+ }
+
+ static int ath12k_core_create_bus_type_board_name(struct ath12k_base *ab, char *name,
+ size_t name_len)
+ {
+- return __ath12k_core_create_board_name(ab, name, name_len, false, true);
++ return __ath12k_core_create_board_name(ab, name, name_len, false, true, true);
+ }
+
+ const struct firmware *ath12k_core_firmware_request(struct ath12k_base *ab,
+--
+2.39.5
+
--- /dev/null
+From a2a13e99dbfc02ee55759b46fc77241c38dcea12 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jan 2025 08:13:06 +0100
+Subject: wifi: ath12k: fix ath12k_hal_tx_cmd_ext_desc_setup() info1 override
+
+From: Nicolas Escande <nico.escande@gmail.com>
+
+[ Upstream commit df11edfba49e5fb69f4c9e7cb76082b89c417f78 ]
+
+Since inception there is an obvious typo laying around in
+ath12k_hal_tx_cmd_ext_desc_setup(). Instead of initializing + adding
+flags to tcl_ext_cmd->info1, we initialize + override. This will be needed
+in the future to make broadcast frames work with ethernet encapsulation.
+
+Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1
+
+Signed-off-by: Nicolas Escande <nico.escande@gmail.com>
+Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
+Link: https://patch.msgid.link/20250127071306.1454699-1-nico.escande@gmail.com
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/dp_tx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c
+index ad21fbfbcbe22..201ffdb8c44ae 100644
+--- a/drivers/net/wireless/ath/ath12k/dp_tx.c
++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c
+@@ -117,7 +117,7 @@ static void ath12k_hal_tx_cmd_ext_desc_setup(struct ath12k_base *ab,
+ le32_encode_bits(ti->data_len,
+ HAL_TX_MSDU_EXT_INFO1_BUF_LEN);
+
+- tcl_ext_cmd->info1 = le32_encode_bits(1, HAL_TX_MSDU_EXT_INFO1_EXTN_OVERRIDE) |
++ tcl_ext_cmd->info1 |= le32_encode_bits(1, HAL_TX_MSDU_EXT_INFO1_EXTN_OVERRIDE) |
+ le32_encode_bits(ti->encap_type,
+ HAL_TX_MSDU_EXT_INFO1_ENCAP_TYPE) |
+ le32_encode_bits(ti->encrypt_type,
+--
+2.39.5
+
--- /dev/null
+From ec7a31fe4936ecd990c1d5ab7926c8f2ca6808b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 23 Dec 2024 11:31:25 +0530
+Subject: wifi: ath12k: Fix end offset bit definition in monitor ring
+ descriptor
+
+From: P Praneesh <quic_ppranees@quicinc.com>
+
+[ Upstream commit 6788a666000d600bd8f2e9f991cad9cc805e7f01 ]
+
+End offset for the monitor destination ring descriptor is defined as
+16 bits, while the firmware definition specifies only 12 bits.
+The remaining bits (bit 12 to bit 15) are reserved and may contain
+junk values, leading to invalid information retrieval. Fix this issue
+by updating the correct genmask values.
+
+Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
+Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
+
+Signed-off-by: P Praneesh <quic_ppranees@quicinc.com>
+Link: https://patch.msgid.link/20241223060132.3506372-8-quic_ppranees@quicinc.com
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/hal_desc.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/ath/ath12k/hal_desc.h b/drivers/net/wireless/ath/ath12k/hal_desc.h
+index 739f73370015e..4f745cfd7d8e7 100644
+--- a/drivers/net/wireless/ath/ath12k/hal_desc.h
++++ b/drivers/net/wireless/ath/ath12k/hal_desc.h
+@@ -2966,7 +2966,7 @@ struct hal_mon_buf_ring {
+
+ #define HAL_MON_DEST_COOKIE_BUF_ID GENMASK(17, 0)
+
+-#define HAL_MON_DEST_INFO0_END_OFFSET GENMASK(15, 0)
++#define HAL_MON_DEST_INFO0_END_OFFSET GENMASK(11, 0)
+ #define HAL_MON_DEST_INFO0_FLUSH_DETECTED BIT(16)
+ #define HAL_MON_DEST_INFO0_END_OF_PPDU BIT(17)
+ #define HAL_MON_DEST_INFO0_INITIATOR BIT(18)
+--
+2.39.5
+
--- /dev/null
+From 62123b542e883bdac9400984f3a770aa36f5f470 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Feb 2025 07:08:51 +0530
+Subject: wifi: ath12k: fix the ampdu id fetch in the HAL_RX_MPDU_START TLV
+
+From: P Praneesh <quic_ppranees@quicinc.com>
+
+[ Upstream commit dff4f278ee1ef12d822b7ed2a1048d27037209bb ]
+
+Currently, ampdu id is update with peer id mask which is incorrect.
+Therefore, update the ampdu id with PPDU id mask value. Also move
+the ampdu_id field inside the user stats since it is a user id based
+statistics.
+
+Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
+Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
+
+Signed-off-by: P Praneesh <quic_ppranees@quicinc.com>
+Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
+Signed-off-by: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
+Link: https://patch.msgid.link/20250206013854.174765-7-quic_periyasa@quicinc.com
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/dp_mon.c | 16 ++++++++++------
+ drivers/net/wireless/ath/ath12k/hal_rx.h | 3 ++-
+ 2 files changed, 12 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c
+index 4c98b9de1e584..6a88745369447 100644
+--- a/drivers/net/wireless/ath/ath12k/dp_mon.c
++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: BSD-3-Clause-Clear
+ /*
+ * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
+- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ #include "dp_mon.h"
+@@ -666,6 +666,11 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k_base *ab,
+ if (userid < HAL_MAX_UL_MU_USERS) {
+ struct hal_rx_user_status *rxuser_stats =
+ &ppdu_info->userstats[userid];
++
++ if (ppdu_info->num_mpdu_fcs_ok > 1 ||
++ ppdu_info->num_mpdu_fcs_err > 1)
++ ppdu_info->userstats[userid].ampdu_present = true;
++
+ ppdu_info->num_users += 1;
+
+ ath12k_dp_mon_rx_handle_ofdma_info(tlv_data, rxuser_stats);
+@@ -783,8 +788,8 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k_base *ab,
+ if (userid < HAL_MAX_UL_MU_USERS) {
+ info[0] = __le32_to_cpu(mpdu_start->info0);
+ ppdu_info->userid = userid;
+- ppdu_info->ampdu_id[userid] =
+- u32_get_bits(info[0], HAL_RX_MPDU_START_INFO1_PEERID);
++ ppdu_info->userstats[userid].ampdu_id =
++ u32_get_bits(info[0], HAL_RX_MPDU_START_INFO0_PPDU_ID);
+ }
+
+ mon_mpdu = kzalloc(sizeof(*mon_mpdu), GFP_ATOMIC);
+@@ -1020,15 +1025,14 @@ static void ath12k_dp_mon_update_radiotap(struct ath12k *ar,
+ {
+ struct ieee80211_supported_band *sband;
+ u8 *ptr = NULL;
+- u16 ampdu_id = ppduinfo->ampdu_id[ppduinfo->userid];
+
+ rxs->flag |= RX_FLAG_MACTIME_START;
+ rxs->signal = ppduinfo->rssi_comb + ATH12K_DEFAULT_NOISE_FLOOR;
+ rxs->nss = ppduinfo->nss + 1;
+
+- if (ampdu_id) {
++ if (ppduinfo->userstats[ppduinfo->userid].ampdu_present) {
+ rxs->flag |= RX_FLAG_AMPDU_DETAILS;
+- rxs->ampdu_reference = ampdu_id;
++ rxs->ampdu_reference = ppduinfo->userstats[ppduinfo->userid].ampdu_id;
+ }
+
+ if (ppduinfo->he_mu_flags) {
+diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.h b/drivers/net/wireless/ath/ath12k/hal_rx.h
+index 095216eabc01d..8c37cbc01b1c5 100644
+--- a/drivers/net/wireless/ath/ath12k/hal_rx.h
++++ b/drivers/net/wireless/ath/ath12k/hal_rx.h
+@@ -143,6 +143,8 @@ struct hal_rx_user_status {
+ u32 mpdu_fcs_ok_bitmap[HAL_RX_NUM_WORDS_PER_PPDU_BITMAP];
+ u32 mpdu_ok_byte_count;
+ u32 mpdu_err_byte_count;
++ bool ampdu_present;
++ u16 ampdu_id;
+ };
+
+ #define HAL_MAX_UL_MU_USERS 37
+@@ -226,7 +228,6 @@ struct hal_rx_mon_ppdu_info {
+ u8 addr4[ETH_ALEN];
+ struct hal_rx_user_status userstats[HAL_MAX_UL_MU_USERS];
+ u8 userid;
+- u16 ampdu_id[HAL_MAX_UL_MU_USERS];
+ bool first_msdu_in_mpdu;
+ bool is_ampdu;
+ u8 medium_prot_type;
+--
+2.39.5
+
--- /dev/null
+From cd206b0d520cd9666e1dff08e991e52fe7f8d50b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Feb 2025 11:30:05 +0530
+Subject: wifi: ath12k: Improve BSS discovery with hidden SSID in 6 GHz band
+
+From: Ramasamy Kaliappan <quic_rkaliapp@quicinc.com>
+
+[ Upstream commit 27d38bdfd416f4db70e09c3bef3b030c86fd235a ]
+
+Currently, sometimes, the station is unable to identify the configured
+AP SSID in its scan results when the AP is not broadcasting its name
+publicly and has a hidden SSID.
+
+Currently, channel dwell time for an ath12k station is 30 ms. Sometimes,
+station can send broadcast probe request to AP close to the end of dwell
+time. In some of these cases, before AP sends a response to the received
+probe request, the dwell time on the station side would come to an end.
+So, the station will move to scan next channel and will not be able to
+acknowledge the unicast probe response.
+
+Resolve this issue by increasing station's channel dwell time to 70 ms,
+so that the it remains on the same channel for a longer period. This
+would increase the station's chance of receiving probe response from the
+AP. The station will then send a response acknowledgment back to the AP,
+thus leading to successful scan and BSS discovery.
+
+With an increased dwell time, scan would take longer than it takes now.
+But, this fix is an improvement for hidden SSID scan issue.
+
+Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1
+
+Signed-off-by: Ramasamy Kaliappan <quic_rkaliapp@quicinc.com>
+Signed-off-by: Roopni Devanathan <quic_rdevanat@quicinc.com>
+Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
+Link: https://patch.msgid.link/20250207060005.153835-1-quic_rdevanat@quicinc.com
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/wmi.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
+index a6ba97949440e..30836a09d5506 100644
+--- a/drivers/net/wireless/ath/ath12k/wmi.c
++++ b/drivers/net/wireless/ath/ath12k/wmi.c
+@@ -2206,8 +2206,8 @@ void ath12k_wmi_start_scan_init(struct ath12k *ar,
+ arg->dwell_time_active = 50;
+ arg->dwell_time_active_2g = 0;
+ arg->dwell_time_passive = 150;
+- arg->dwell_time_active_6g = 40;
+- arg->dwell_time_passive_6g = 30;
++ arg->dwell_time_active_6g = 70;
++ arg->dwell_time_passive_6g = 70;
+ arg->min_rest_time = 50;
+ arg->max_rest_time = 500;
+ arg->repeat_probe_time = 0;
+--
+2.39.5
+
--- /dev/null
+From 46288aa0baf9d3af3af68052d6aedb482e8a8de6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Nov 2024 23:04:32 +0530
+Subject: wifi: ath12k: Report proper tx completion status to mac80211
+
+From: Vinith Kumar R <quic_vinithku@quicinc.com>
+
+[ Upstream commit d2d9c9b8de725e1006d3aa3d18678a732f5d3584 ]
+
+Currently Tx completion for few exception packets are received from
+firmware and the tx status updated to mac80211. The tx status values of
+HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP and HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL
+are considered as tx failure and reported as tx failure to mac80211.
+But these failure status is due to internal firmware tx drop and these
+packets were not tried to transmit in the air.
+In case of mesh this invalid tx status report might trigger mpath broken
+issue due to increase in mpath fail average.
+So do not report these tx status as tx failure instead free the skb
+by calling ieee80211_free_txskb(), and that will be accounted as dropped
+frame.
+
+Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
+
+Signed-off-by: Vinith Kumar R <quic_vinithku@quicinc.com>
+Signed-off-by: Tamizh Chelvam Raja <quic_tamizhr@quicinc.com>
+Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
+Link: https://patch.msgid.link/20241122173432.2064858-1-quic_tamizhr@quicinc.com
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/dp_tx.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c
+index 44406e0b4a342..ad21fbfbcbe22 100644
+--- a/drivers/net/wireless/ath/ath12k/dp_tx.c
++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c
+@@ -557,13 +557,13 @@ ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab,
+
+ switch (wbm_status) {
+ case HAL_WBM_REL_HTT_TX_COMP_STATUS_OK:
+- case HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP:
+- case HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL:
+ ts.acked = (wbm_status == HAL_WBM_REL_HTT_TX_COMP_STATUS_OK);
+ ts.ack_rssi = le32_get_bits(status_desc->info2,
+ HTT_TX_WBM_COMP_INFO2_ACK_RSSI);
+ ath12k_dp_tx_htt_tx_complete_buf(ab, msdu, tx_ring, &ts);
+ break;
++ case HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP:
++ case HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL:
+ case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ:
+ case HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT:
+ ath12k_dp_tx_free_txbuf(ab, msdu, mac_id, tx_ring);
+--
+2.39.5
+
--- /dev/null
+From a30438390010dd0ab87e7c85c31e822be1b6d436 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Nov 2024 14:23:26 -0800
+Subject: wifi: ath9k: return by of_get_mac_address
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Rosen Penev <rosenp@gmail.com>
+
+[ Upstream commit dfffb317519f88534bb82797f055f0a2fd867e7b ]
+
+When using nvmem, ath9k could potentially be loaded before nvmem, which
+loads after mtd. This is an issue if DT contains an nvmem mac address.
+
+If nvmem is not ready in time for ath9k, -EPROBE_DEFER is returned. Pass
+it to _probe so that ath9k can properly grab a potentially present MAC
+address.
+
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
+Link: https://patch.msgid.link/20241105222326.194417-1-rosenp@gmail.com
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath9k/init.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
+index 7fad7e75af6a3..619bebd389bd2 100644
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -691,7 +691,9 @@ static int ath9k_of_init(struct ath_softc *sc)
+ ah->ah_flags |= AH_NO_EEP_SWAP;
+ }
+
+- of_get_mac_address(np, common->macaddr);
++ ret = of_get_mac_address(np, common->macaddr);
++ if (ret == -EPROBE_DEFER)
++ return ret;
+
+ return 0;
+ }
+--
+2.39.5
+
--- /dev/null
+From 263cd9340690db374ac3e9d77582da09e8158bad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Mar 2025 23:03:30 +0200
+Subject: wifi: cfg80211: allow IR in 20 MHz configurations
+
+From: Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
+
+[ Upstream commit cf4bd1608882792d4742e27a819493312904a680 ]
+
+Some regulatory bodies doesn't allow IR (initiate radioation) on a
+specific subband, but allows it for channels with a bandwidth of 20 MHz.
+Add a channel flag that indicates that, and consider it in
+cfg80211_reg_check_beaconing.
+
+While on it, fix the kernel doc of enum nl80211_reg_rule_flags and
+change it to use BIT().
+
+Signed-off-by: Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
+Co-developed-by: Somashekhar Puttagangaiah <somashekhar.puttagangaiah@intel.com>
+Signed-off-by: Somashekhar Puttagangaiah <somashekhar.puttagangaiah@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20250308225541.d3ab352a73ff.I8a8f79e1c9eb74936929463960ee2a324712fe51@changeid
+[fix typo]
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/cfg80211.h | 3 +++
+ include/uapi/linux/nl80211.h | 52 ++++++++++++++++++++----------------
+ net/wireless/chan.c | 8 +++++-
+ net/wireless/nl80211.c | 4 +++
+ net/wireless/reg.c | 4 ++-
+ 5 files changed, 46 insertions(+), 25 deletions(-)
+
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index 941dc62f3027c..8a712ca73f2b0 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -127,6 +127,8 @@ struct wiphy;
+ * even if it is otherwise disabled.
+ * @IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP: Allow using this channel for AP operation
+ * with very low power (VLP), even if otherwise set to NO_IR.
++ * @IEEE80211_CHAN_ALLOW_20MHZ_ACTIVITY: Allow activity on a 20 MHz channel,
++ * even if otherwise set to NO_IR.
+ */
+ enum ieee80211_channel_flags {
+ IEEE80211_CHAN_DISABLED = BIT(0),
+@@ -155,6 +157,7 @@ enum ieee80211_channel_flags {
+ IEEE80211_CHAN_NO_6GHZ_AFC_CLIENT = BIT(23),
+ IEEE80211_CHAN_CAN_MONITOR = BIT(24),
+ IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP = BIT(25),
++ IEEE80211_CHAN_ALLOW_20MHZ_ACTIVITY = BIT(26),
+ };
+
+ #define IEEE80211_CHAN_NO_HT40 \
+diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
+index f97f5adc8d518..c2d7faf8d87fa 100644
+--- a/include/uapi/linux/nl80211.h
++++ b/include/uapi/linux/nl80211.h
+@@ -4294,6 +4294,8 @@ enum nl80211_wmm_rule {
+ * otherwise completely disabled.
+ * @NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP: This channel can be used for a
+ * very low power (VLP) AP, despite being NO_IR.
++ * @NL80211_FREQUENCY_ATTR_ALLOW_20MHZ_ACTIVITY: This channel can be active in
++ * 20 MHz bandwidth, despite being NO_IR.
+ * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
+ * currently defined
+ * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
+@@ -4338,6 +4340,7 @@ enum nl80211_frequency_attr {
+ NL80211_FREQUENCY_ATTR_NO_6GHZ_AFC_CLIENT,
+ NL80211_FREQUENCY_ATTR_CAN_MONITOR,
+ NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP,
++ NL80211_FREQUENCY_ATTR_ALLOW_20MHZ_ACTIVITY,
+
+ /* keep last */
+ __NL80211_FREQUENCY_ATTR_AFTER_LAST,
+@@ -4549,31 +4552,34 @@ enum nl80211_sched_scan_match_attr {
+ * @NL80211_RRF_NO_6GHZ_AFC_CLIENT: Client connection to AFC AP not allowed
+ * @NL80211_RRF_ALLOW_6GHZ_VLP_AP: Very low power (VLP) AP can be permitted
+ * despite NO_IR configuration.
++ * @NL80211_RRF_ALLOW_20MHZ_ACTIVITY: Allow activity in 20 MHz bandwidth,
++ * despite NO_IR configuration.
+ */
+ enum nl80211_reg_rule_flags {
+- NL80211_RRF_NO_OFDM = 1<<0,
+- NL80211_RRF_NO_CCK = 1<<1,
+- NL80211_RRF_NO_INDOOR = 1<<2,
+- NL80211_RRF_NO_OUTDOOR = 1<<3,
+- NL80211_RRF_DFS = 1<<4,
+- NL80211_RRF_PTP_ONLY = 1<<5,
+- NL80211_RRF_PTMP_ONLY = 1<<6,
+- NL80211_RRF_NO_IR = 1<<7,
+- __NL80211_RRF_NO_IBSS = 1<<8,
+- NL80211_RRF_AUTO_BW = 1<<11,
+- NL80211_RRF_IR_CONCURRENT = 1<<12,
+- NL80211_RRF_NO_HT40MINUS = 1<<13,
+- NL80211_RRF_NO_HT40PLUS = 1<<14,
+- NL80211_RRF_NO_80MHZ = 1<<15,
+- NL80211_RRF_NO_160MHZ = 1<<16,
+- NL80211_RRF_NO_HE = 1<<17,
+- NL80211_RRF_NO_320MHZ = 1<<18,
+- NL80211_RRF_NO_EHT = 1<<19,
+- NL80211_RRF_PSD = 1<<20,
+- NL80211_RRF_DFS_CONCURRENT = 1<<21,
+- NL80211_RRF_NO_6GHZ_VLP_CLIENT = 1<<22,
+- NL80211_RRF_NO_6GHZ_AFC_CLIENT = 1<<23,
+- NL80211_RRF_ALLOW_6GHZ_VLP_AP = 1<<24,
++ NL80211_RRF_NO_OFDM = 1 << 0,
++ NL80211_RRF_NO_CCK = 1 << 1,
++ NL80211_RRF_NO_INDOOR = 1 << 2,
++ NL80211_RRF_NO_OUTDOOR = 1 << 3,
++ NL80211_RRF_DFS = 1 << 4,
++ NL80211_RRF_PTP_ONLY = 1 << 5,
++ NL80211_RRF_PTMP_ONLY = 1 << 6,
++ NL80211_RRF_NO_IR = 1 << 7,
++ __NL80211_RRF_NO_IBSS = 1 << 8,
++ NL80211_RRF_AUTO_BW = 1 << 11,
++ NL80211_RRF_IR_CONCURRENT = 1 << 12,
++ NL80211_RRF_NO_HT40MINUS = 1 << 13,
++ NL80211_RRF_NO_HT40PLUS = 1 << 14,
++ NL80211_RRF_NO_80MHZ = 1 << 15,
++ NL80211_RRF_NO_160MHZ = 1 << 16,
++ NL80211_RRF_NO_HE = 1 << 17,
++ NL80211_RRF_NO_320MHZ = 1 << 18,
++ NL80211_RRF_NO_EHT = 1 << 19,
++ NL80211_RRF_PSD = 1 << 20,
++ NL80211_RRF_DFS_CONCURRENT = 1 << 21,
++ NL80211_RRF_NO_6GHZ_VLP_CLIENT = 1 << 22,
++ NL80211_RRF_NO_6GHZ_AFC_CLIENT = 1 << 23,
++ NL80211_RRF_ALLOW_6GHZ_VLP_AP = 1 << 24,
++ NL80211_RRF_ALLOW_20MHZ_ACTIVITY = 1 << 25,
+ };
+
+ #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR
+diff --git a/net/wireless/chan.c b/net/wireless/chan.c
+index e579d7e1425fe..c4f3fefeb3544 100644
+--- a/net/wireless/chan.c
++++ b/net/wireless/chan.c
+@@ -6,7 +6,7 @@
+ *
+ * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2013-2014 Intel Mobile Communications GmbH
+- * Copyright 2018-2024 Intel Corporation
++ * Copyright 2018-2025 Intel Corporation
+ */
+
+ #include <linux/export.h>
+@@ -1621,6 +1621,12 @@ bool cfg80211_reg_check_beaconing(struct wiphy *wiphy,
+ if (cfg->reg_power == IEEE80211_REG_VLP_AP)
+ permitting_flags |= IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP;
+
++ if ((cfg->iftype == NL80211_IFTYPE_P2P_GO ||
++ cfg->iftype == NL80211_IFTYPE_AP) &&
++ (chandef->width == NL80211_CHAN_WIDTH_20_NOHT ||
++ chandef->width == NL80211_CHAN_WIDTH_20))
++ permitting_flags |= IEEE80211_CHAN_ALLOW_20MHZ_ACTIVITY;
++
+ return _cfg80211_reg_can_beacon(wiphy, chandef, cfg->iftype,
+ check_no_ir ? IEEE80211_CHAN_NO_IR : 0,
+ permitting_flags);
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index ecfceddce00fc..c778ffa1c8efd 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -1213,6 +1213,10 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
+ if ((chan->flags & IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP) &&
+ nla_put_flag(msg, NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP))
+ goto nla_put_failure;
++ if ((chan->flags & IEEE80211_CHAN_ALLOW_20MHZ_ACTIVITY) &&
++ nla_put_flag(msg,
++ NL80211_FREQUENCY_ATTR_ALLOW_20MHZ_ACTIVITY))
++ goto nla_put_failure;
+ }
+
+ if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
+diff --git a/net/wireless/reg.c b/net/wireless/reg.c
+index 2b626078739c5..f6846eb0f4b84 100644
+--- a/net/wireless/reg.c
++++ b/net/wireless/reg.c
+@@ -5,7 +5,7 @@
+ * Copyright 2008-2011 Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
+ * Copyright 2013-2014 Intel Mobile Communications GmbH
+ * Copyright 2017 Intel Deutschland GmbH
+- * Copyright (C) 2018 - 2024 Intel Corporation
++ * Copyright (C) 2018 - 2025 Intel Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+@@ -1603,6 +1603,8 @@ static u32 map_regdom_flags(u32 rd_flags)
+ channel_flags |= IEEE80211_CHAN_PSD;
+ if (rd_flags & NL80211_RRF_ALLOW_6GHZ_VLP_AP)
+ channel_flags |= IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP;
++ if (rd_flags & NL80211_RRF_ALLOW_20MHZ_ACTIVITY)
++ channel_flags |= IEEE80211_CHAN_ALLOW_20MHZ_ACTIVITY;
+ return channel_flags;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From f4404227bb6fda77c8bf5f1c00a9e61950b63860 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 May 2025 21:42:59 +0200
+Subject: wifi: iwlwifi: add support for Killer on MTL
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit ebedf8b7f05b9c886d68d63025db8d1b12343157 ]
+
+For now, we need another entry for these devices, this
+will be changed completely for 6.16.
+
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219926
+Link: https://patch.msgid.link/20250506214258.2efbdc9e9a82.I31915ec252bd1c74bd53b89a0e214e42a74b6f2e@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+index 9141ea57abfce..68989d183e82a 100644
+--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
++++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+@@ -587,6 +587,8 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = {
+ IWL_DEV_INFO(0x7A70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
+ IWL_DEV_INFO(0x7AF0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
+ IWL_DEV_INFO(0x7AF0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
++ IWL_DEV_INFO(0x7F70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
++ IWL_DEV_INFO(0x7F70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
+
+ IWL_DEV_INFO(0x271C, 0x0214, iwl9260_2ac_cfg, iwl9260_1_name),
+ IWL_DEV_INFO(0x7E40, 0x1691, iwl_cfg_ma, iwl_ax411_killer_1690s_name),
+--
+2.39.5
+
--- /dev/null
+From 04c5406d0f267c7c7ccfb44943ee0ba2e75ae2d7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Feb 2025 14:55:35 +0200
+Subject: wifi: iwlwifi: don't warn during reprobe
+
+From: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+
+[ Upstream commit 696cca64308dc641d0bbe4aa2c09dd9752aa288d ]
+
+During reprobe, the sw state is being destroyd, and so is the
+connection. When the peer STA is being removed, the opmode sends a
+command to flush the TXQs of the STA and uses iwl_trans_wait_txq_empty.
+
+This one warns if the FW is not alive, but it really shouldn't if
+there is a FW error - and return silently instead, just like we do when
+sending a hcmd.
+
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Reviewed-by: Johannes Berg <johannes.berg@intel.com>
+Link: https://patch.msgid.link/20250205145347.76425b10e5a0.I3bf0de2eb090a8b94c4e36d93dd91df61fadb808@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
+index 311b167ea09ed..510e04b721da6 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
+@@ -454,6 +454,9 @@ IWL_EXPORT_SYMBOL(iwl_trans_txq_enable_cfg);
+
+ int iwl_trans_wait_txq_empty(struct iwl_trans *trans, int queue)
+ {
++ if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
++ return -EIO;
++
+ if (WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
+ "bad state = %d\n", trans->state))
+ return -EIO;
+--
+2.39.5
+
--- /dev/null
+From b4a393cdb9b31edbcb7d20a903946115e81425d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Mar 2025 23:19:23 +0200
+Subject: wifi: iwlwifi: don't warn when if there is a FW error
+
+From: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+
+[ Upstream commit c7f50d0433a016d43681592836a3d484817bfb34 ]
+
+iwl_trans_reclaim is warning if it is called when the FW is not alive.
+But if it is called when there is a pending restart, i.e. after a FW
+error, there is no need to warn, instead - return silently.
+
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20250308231427.ba3d90b22c25.I9332506af1997faefcf0bdb51d98d5e874051722@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
+index 3b3dcaf33c9d9..311b167ea09ed 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
+@@ -2,7 +2,7 @@
+ /*
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016-2017 Intel Deutschland GmbH
+- * Copyright (C) 2019-2021, 2023-2024 Intel Corporation
++ * Copyright (C) 2019-2021, 2023-2025 Intel Corporation
+ */
+ #include <linux/kernel.h>
+ #include <linux/bsearch.h>
+@@ -419,6 +419,9 @@ IWL_EXPORT_SYMBOL(iwl_trans_tx);
+ void iwl_trans_reclaim(struct iwl_trans *trans, int queue, int ssn,
+ struct sk_buff_head *skbs, bool is_flush)
+ {
++ if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
++ return;
++
+ if (WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
+ "bad state = %d\n", trans->state))
+ return;
+--
+2.39.5
+
--- /dev/null
+From de98ee79802a1c0d86c278d71fddaf6c717e1e76 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Mar 2025 23:19:18 +0200
+Subject: wifi: iwlwifi: fix debug actions order
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit eb29b4ffafb20281624dcd2cbb768d6f30edf600 ]
+
+The order of actions taken for debug was implemented incorrectly.
+Now we implemented the dump split and do the FW reset only in the
+middle of the dump (rather than the FW killing itself on error.)
+As a result, some of the actions taken when applying the config
+will now crash the device, so we need to fix the order.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20250308231427.6de7fa8e63ed.I40632c48e2a67a8aca05def572a934b88ce7934b@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
+index 08d990ba8a794..ce787326aa69d 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+ /*
+- * Copyright (C) 2018-2024 Intel Corporation
++ * Copyright (C) 2018-2025 Intel Corporation
+ */
+ #include <linux/firmware.h>
+ #include "iwl-drv.h"
+@@ -1372,15 +1372,15 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,
+ switch (tp_id) {
+ case IWL_FW_INI_TIME_POINT_EARLY:
+ iwl_dbg_tlv_init_cfg(fwrt);
+- iwl_dbg_tlv_apply_config(fwrt, conf_list);
+ iwl_dbg_tlv_update_drams(fwrt);
+ iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL);
++ iwl_dbg_tlv_apply_config(fwrt, conf_list);
+ break;
+ case IWL_FW_INI_TIME_POINT_AFTER_ALIVE:
+ iwl_dbg_tlv_apply_buffers(fwrt);
+ iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list);
+- iwl_dbg_tlv_apply_config(fwrt, conf_list);
+ iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL);
++ iwl_dbg_tlv_apply_config(fwrt, conf_list);
+ break;
+ case IWL_FW_INI_TIME_POINT_PERIODIC:
+ iwl_dbg_tlv_set_periodic_trigs(fwrt);
+@@ -1390,14 +1390,14 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,
+ case IWL_FW_INI_TIME_POINT_MISSED_BEACONS:
+ case IWL_FW_INI_TIME_POINT_FW_DHC_NOTIFICATION:
+ iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list);
+- iwl_dbg_tlv_apply_config(fwrt, conf_list);
+ iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data,
+ iwl_dbg_tlv_check_fw_pkt);
++ iwl_dbg_tlv_apply_config(fwrt, conf_list);
+ break;
+ default:
+ iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list);
+- iwl_dbg_tlv_apply_config(fwrt, conf_list);
+ iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL);
++ iwl_dbg_tlv_apply_config(fwrt, conf_list);
+ break;
+ }
+ }
+--
+2.39.5
+
--- /dev/null
+From 85e3526640f174b7554272093170c854948aee9a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Mar 2025 23:19:13 +0200
+Subject: wifi: iwlwifi: fix the ECKV UEFI variable name
+
+From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+
+[ Upstream commit 3ea2970b0578011ab8402ad0cff39712255f63df ]
+
+This UEFI variable name was badly named. Fix its name and also use the
+right GUID to find it: we need to use the BT_WIFI (a.k.a. Common) GUID.
+
+Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20250308231426.78c998d0fa71.I2bc9d72c1dc2c4d7028f0265634a940c2fadbbb5@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 8 +++++---
+ drivers/net/wireless/intel/iwlwifi/fw/uefi.h | 4 ++--
+ 2 files changed, 7 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
+index 834f7c9bb9e92..86d6286a15378 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
++++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+ /*
+- * Copyright(c) 2021-2024 Intel Corporation
++ * Copyright(c) 2021-2025 Intel Corporation
+ */
+
+ #include "iwl-drv.h"
+@@ -673,8 +673,10 @@ int iwl_uefi_get_eckv(struct iwl_fw_runtime *fwrt, u32 *extl_clk)
+ struct uefi_cnv_var_eckv *data;
+ int ret = 0;
+
+- data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_ECKV_NAME,
+- "ECKV", sizeof(*data), NULL);
++ data = iwl_uefi_get_verified_variable_guid(fwrt->trans,
++ &IWL_EFI_WIFI_BT_GUID,
++ IWL_UEFI_ECKV_NAME,
++ "ECKV", sizeof(*data), NULL);
+ if (IS_ERR(data))
+ return -EINVAL;
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
+index e525d449e656e..c931f5cedb0b9 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
++++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
+@@ -1,6 +1,6 @@
+ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+ /*
+- * Copyright(c) 2021-2024 Intel Corporation
++ * Copyright(c) 2021-2025 Intel Corporation
+ */
+ #ifndef __iwl_fw_uefi__
+ #define __iwl_fw_uefi__
+@@ -19,7 +19,7 @@
+ #define IWL_UEFI_WTAS_NAME L"UefiCnvWlanWTAS"
+ #define IWL_UEFI_SPLC_NAME L"UefiCnvWlanSPLC"
+ #define IWL_UEFI_WRDD_NAME L"UefiCnvWlanWRDD"
+-#define IWL_UEFI_ECKV_NAME L"UefiCnvWlanECKV"
++#define IWL_UEFI_ECKV_NAME L"UefiCnvCommonECKV"
+ #define IWL_UEFI_DSM_NAME L"UefiCnvWlanGeneralCfg"
+ #define IWL_UEFI_WBEM_NAME L"UefiCnvWlanWBEM"
+ #define IWL_UEFI_PUNCTURING_NAME L"UefiCnvWlanPuncturing"
+--
+2.39.5
+
--- /dev/null
+From b29136ef1788984b2d67b4ec5b25bd10dc4aa365 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Mar 2025 23:19:17 +0200
+Subject: wifi: iwlwifi: mark Br device not integrated
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 5f0ab2f35a43773a0dfe1297129a8dbff906b932 ]
+
+This is a discrete device, don't mark it as integrated.
+This also means we cannot set the LTR delay.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20250308231427.9bb69393fcc9.I197129383e5441c8139cbb0e810ae0b71198a37c@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c
+index ab7c0f8d54f42..d3542af0f625e 100644
+--- a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c
++++ b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c
+@@ -148,11 +148,9 @@ const struct iwl_cfg_trans_params iwl_br_trans_cfg = {
+ .mq_rx_supported = true,
+ .rf_id = true,
+ .gen2 = true,
+- .integrated = true,
+ .umac_prph_offset = 0x300000,
+ .xtal_latency = 12000,
+ .low_latency_xtal = true,
+- .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
+ };
+
+ const char iwl_br_name[] = "Intel(R) TBD Br device";
+--
+2.39.5
+
--- /dev/null
+From f73792049f3bd73551e6bda556189b40c3ed8ad5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Mar 2025 23:19:25 +0200
+Subject: wifi: iwlwifi: mvm: fix setting the TK when associated
+
+From: Avraham Stern <avraham.stern@intel.com>
+
+[ Upstream commit 3ad61970ac9e164be1b09b46c01aa942e8966132 ]
+
+When running secured ranging and the initiator is associated with
+the responder, the TK was not set in the range request command.
+Fix it.
+
+Signed-off-by: Avraham Stern <avraham.stern@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20250308231427.603dc31579d9.Icd19d797e56483c08dd22c55b96fee481c4d2f3d@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
+index 55245f913286b..2ed7a0d77ef83 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
+@@ -773,7 +773,11 @@ iwl_mvm_ftm_set_secured_ranging(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+
+ target.bssid = bssid;
+ target.cipher = cipher;
++ target.tk = NULL;
+ ieee80211_iter_keys(mvm->hw, vif, iter, &target);
++
++ if (!WARN_ON(!target.tk))
++ memcpy(tk, target.tk, TK_11AZ_LEN);
+ } else {
+ memcpy(tk, entry->tk, sizeof(entry->tk));
+ }
+--
+2.39.5
+
--- /dev/null
+From b64bde75433883a703f5672c1e2a25c5856205a6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Feb 2025 14:55:46 +0200
+Subject: wifi: iwlwifi: use correct IMR dump variable
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 21e4d29ac0def546d57bacebe4a51cbed1209b03 ]
+
+We shouldn't dump the reg_data here which dumps the last
+entry again, it should use the imr_reg_data.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20250205145347.3313b18667d1.Iaa9ab66b1d397912a573525e060d39ea01b29d19@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+index 6594216f873c4..cd284767ff4ba 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
++++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+ /*
+- * Copyright (C) 2005-2014, 2018-2024 Intel Corporation
++ * Copyright (C) 2005-2014, 2018-2025 Intel Corporation
+ * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2015-2017 Intel Deutschland GmbH
+ */
+@@ -2691,7 +2691,7 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
+ }
+ /* collect DRAM_IMR region in the last */
+ if (imr_reg_data.reg_tlv)
+- size += iwl_dump_ini_mem(fwrt, list, ®_data,
++ size += iwl_dump_ini_mem(fwrt, list, &imr_reg_data,
+ &iwl_dump_ini_region_ops[IWL_FW_INI_REGION_DRAM_IMR]);
+
+ if (size) {
+--
+2.39.5
+
--- /dev/null
+From 415ab8ad60eef1e2014f36b9d80787ef999cf205 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Mar 2025 23:19:19 +0200
+Subject: wifi: iwlwifi: w/a FW SMPS mode selection
+
+From: Daniel Gabay <daniel.gabay@intel.com>
+
+[ Upstream commit b2e709805ce955f80803b7cab3421813c79e1df4 ]
+
+The FW is now responsible of determining the SMPS mode.
+If the user disabled power save in a certain vif, we send the vif-level
+power command to clear out the POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK bit
+for that vif.
+But erroneously, the FW checks DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK in
+the device-level command to determine the SMPS mode.
+
+To W/A this, send also the device-level command when the power save of a
+vif changes, and disable power save if there is any vif that has power
+save disabled.
+
+Signed-off-by: Daniel Gabay <daniel.gabay@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20250308231427.7bf205efa027.I2c793ff1fc2a6779a95faaee1ded348100fd97f1@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 15 +++++++++++++++
+ .../net/wireless/intel/iwlwifi/mvm/mld-mac80211.c | 3 ++-
+ drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 3 +++
+ 3 files changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+index d37d83d246354..3fd257f770baa 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+@@ -4096,6 +4096,20 @@ iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm,
+ return 0;
+ }
+
++void iwl_mvm_smps_workaround(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
++ bool update)
++{
++ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
++
++ if (!iwl_mvm_has_rlc_offload(mvm))
++ return;
++
++ mvmvif->ps_disabled = !vif->cfg.ps;
++
++ if (update)
++ iwl_mvm_power_update_mac(mvm);
++}
++
+ /* Common part for MLD and non-MLD modes */
+ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+@@ -4188,6 +4202,7 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
+ new_state == IEEE80211_STA_AUTHORIZED) {
+ ret = iwl_mvm_sta_state_assoc_to_authorized(mvm, vif, sta,
+ callbacks);
++ iwl_mvm_smps_workaround(mvm, vif, true);
+ } else if (old_state == IEEE80211_STA_AUTHORIZED &&
+ new_state == IEEE80211_STA_ASSOC) {
+ ret = iwl_mvm_sta_state_authorized_to_assoc(mvm, vif, sta,
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+index e252f0dcea205..04da02bdd9536 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+ /*
+- * Copyright (C) 2022-2024 Intel Corporation
++ * Copyright (C) 2022-2025 Intel Corporation
+ */
+ #include "mvm.h"
+
+@@ -961,6 +961,7 @@ static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm,
+ }
+
+ if (changes & BSS_CHANGED_PS) {
++ iwl_mvm_smps_workaround(mvm, vif, false);
+ ret = iwl_mvm_power_update_mac(mvm);
+ if (ret)
+ IWL_ERR(mvm, "failed to update power mode\n");
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+index ef07cff203b0d..7d86d273092ac 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+@@ -3042,4 +3042,7 @@ iwl_mvm_send_ap_tx_power_constraint_cmd(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf,
+ bool is_ap);
++
++void iwl_mvm_smps_workaround(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
++ bool update);
+ #endif /* __IWL_MVM_H__ */
+--
+2.39.5
+
--- /dev/null
+From 303c99cdbf3706bf368a5cb9b88d2f6601e2f458 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Feb 2025 11:39:22 +0200
+Subject: wifi: mac80211: don't unconditionally call drv_mgd_complete_tx()
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 1798271b3604b902d45033ec569f2bf77e94ecc2 ]
+
+We might not have called drv_mgd_prepare_tx(), so only call
+drv_mgd_complete_tx() under the same conditions.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20250205110958.e091fc39a351.Ie6a3cdca070612a0aa4b3c6914ab9ed602d1f456@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mac80211/mlme.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index 3a279ded46c2f..6a29877fd7b37 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -3589,7 +3589,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
+ if (tx)
+ ieee80211_flush_queues(local, sdata, false);
+
+- drv_mgd_complete_tx(sdata->local, sdata, &info);
++ if (tx || frame_buf)
++ drv_mgd_complete_tx(sdata->local, sdata, &info);
+
+ /* clear AP addr only after building the needed mgmt frames */
+ eth_zero_addr(sdata->deflink.u.mgd.bssid);
+--
+2.39.5
+
--- /dev/null
+From 872af8c3bb160ae8868c9f00bd6527238a70920e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Mar 2025 23:03:36 +0200
+Subject: wifi: mac80211: fix warning on disconnect during failed ML reconf
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 0e104aa3676d020f6c442cd7fbaeb72adaaab6fc ]
+
+If multi-link reconfiguration fails, we can disconnect with a local link
+already allocated but the BSS entry not assigned yet, which leads to a
+warning in cfg80211. Add a check to avoid the warning.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Reviewed-by: Ilan Peer <ilan.peer@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20250308225541.699bd9cbabe5.I599d5ff69092a65e916e2acd25137ae9df8debe8@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mac80211/mlme.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index cc8c5d18b130d..3a279ded46c2f 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -4033,7 +4033,7 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
+ struct ieee80211_link_data *link;
+
+ link = sdata_dereference(sdata->link[link_id], sdata);
+- if (!link)
++ if (!link || !link->conf->bss)
+ continue;
+ cfg80211_unlink_bss(local->hw.wiphy, link->conf->bss);
+ link->conf->bss = NULL;
+--
+2.39.5
+
--- /dev/null
+From 0127ccf9df0401050b89f3ada28a07c83d57b0f5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Feb 2025 11:39:21 +0200
+Subject: wifi: mac80211: remove misplaced drv_mgd_complete_tx() call
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit f4995cdc4d02d0abc8e9fcccad5c71ce676c1e3f ]
+
+In the original commit 15fae3410f1d ("mac80211: notify driver on
+mgd TX completion") I evidently made a mistake and placed the
+call in the "associated" if, rather than the "assoc_data". Later
+I noticed the missing call and placed it in commit c042600c17d8
+("wifi: mac80211: adding missing drv_mgd_complete_tx() call"),
+but didn't remove the wrong one. Remove it now.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20250205110958.6ed954179bbf.Id8ef8835b7e6da3bf913c76f77d201017dc8a3c9@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mac80211/mlme.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index 6a29877fd7b37..6a23a24f7d794 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -9220,7 +9220,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
+ ieee80211_report_disconnect(sdata, frame_buf,
+ sizeof(frame_buf), true,
+ req->reason_code, false);
+- drv_mgd_complete_tx(sdata->local, sdata, &info);
+ return 0;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 33bbbf8d2263ec1031555b3a90fc768b3d5db6ef Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Feb 2025 11:39:20 +0200
+Subject: wifi: mac80211: set ieee80211_prep_tx_info::link_id upon Auth Rx
+
+From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+
+[ Upstream commit 8c60179b64434894eac1ffab7396bac131bc8b6e ]
+
+This will be used by the low level driver.
+Note that link_id will be 0 in case of a non-MLO authentication.
+Also fix a call-site of mgd_prepare_tx() where the link_id was not
+populated.
+
+Update the documentation to reflect the current state
+ieee80211_prep_tx_info::link_id is also available in mgd_complete_tx().
+
+Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20250205110958.6a590f189ce5.I1fc5c0da26b143f5b07191eb592f01f7083d55ae@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/mac80211.h | 4 ++--
+ net/mac80211/driver-ops.h | 3 ++-
+ net/mac80211/mlme.c | 4 +++-
+ 3 files changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/include/net/mac80211.h b/include/net/mac80211.h
+index 3b964f8834e71..fee854892bec5 100644
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -7,7 +7,7 @@
+ * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2013-2014 Intel Mobile Communications GmbH
+ * Copyright (C) 2015 - 2017 Intel Deutschland GmbH
+- * Copyright (C) 2018 - 2024 Intel Corporation
++ * Copyright (C) 2018 - 2025 Intel Corporation
+ */
+
+ #ifndef MAC80211_H
+@@ -3803,7 +3803,7 @@ enum ieee80211_reconfig_type {
+ * @was_assoc: set if this call is due to deauth/disassoc
+ * while just having been associated
+ * @link_id: the link id on which the frame will be TX'ed.
+- * Only used with the mgd_prepare_tx() method.
++ * 0 for a non-MLO connection.
+ */
+ struct ieee80211_prep_tx_info {
+ u16 duration;
+diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
+index a06644084d15d..d1c10f5f95160 100644
+--- a/net/mac80211/driver-ops.h
++++ b/net/mac80211/driver-ops.h
+@@ -2,7 +2,7 @@
+ /*
+ * Portions of this file
+ * Copyright(c) 2016 Intel Deutschland GmbH
+-* Copyright (C) 2018-2019, 2021-2024 Intel Corporation
++* Copyright (C) 2018-2019, 2021-2025 Intel Corporation
+ */
+
+ #ifndef __MAC80211_DRIVER_OPS
+@@ -955,6 +955,7 @@ static inline void drv_mgd_complete_tx(struct ieee80211_local *local,
+ return;
+ WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION);
+
++ info->link_id = info->link_id < 0 ? 0 : info->link_id;
+ trace_drv_mgd_complete_tx(local, sdata, info->duration,
+ info->subtype, info->success);
+ if (local->ops->mgd_complete_tx)
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index 6a23a24f7d794..8fa9b9dd46118 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -8,7 +8,7 @@
+ * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2013-2014 Intel Mobile Communications GmbH
+ * Copyright (C) 2015 - 2017 Intel Deutschland GmbH
+- * Copyright (C) 2018 - 2024 Intel Corporation
++ * Copyright (C) 2018 - 2025 Intel Corporation
+ */
+
+ #include <linux/delay.h>
+@@ -4307,6 +4307,8 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
+ auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
+ status_code = le16_to_cpu(mgmt->u.auth.status_code);
+
++ info.link_id = ifmgd->auth_data->link_id;
++
+ if (auth_alg != ifmgd->auth_data->algorithm ||
+ (auth_alg != WLAN_AUTH_SAE &&
+ auth_transaction != ifmgd->auth_data->expected_transaction) ||
+--
+2.39.5
+
--- /dev/null
+From 8287a113fc177ddd7152d15521c08a76568573f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Mar 2025 23:03:34 +0200
+Subject: wifi: mac80211_hwsim: Fix MLD address translation
+
+From: Ilan Peer <ilan.peer@intel.com>
+
+[ Upstream commit 65bff0be9b154621b617fc2e4bd89f1e18e97cdb ]
+
+Do address translations only between shared links. It is
+possible that while an non-AP MLD station and an AP MLD
+station have shared links, the frame is intended to be sent
+on a link which is not shared (for example when sending a
+probe response).
+
+Signed-off-by: Ilan Peer <ilan.peer@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20250308225541.1aa461270bb6.Ic21592e1b1634653f02b80628cb2152f6e9de367@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/virtual/mac80211_hwsim.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
+index 3f424f14de4ec..4a2b7c9921bc6 100644
+--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
++++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
+@@ -4,7 +4,7 @@
+ * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2011, Javier Lopez <jlopex@gmail.com>
+ * Copyright (c) 2016 - 2017 Intel Deutschland GmbH
+- * Copyright (C) 2018 - 2024 Intel Corporation
++ * Copyright (C) 2018 - 2025 Intel Corporation
+ */
+
+ /*
+@@ -1983,11 +1983,13 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
+ return;
+ }
+
+- if (sta && sta->mlo) {
+- if (WARN_ON(!link_sta)) {
+- ieee80211_free_txskb(hw, skb);
+- return;
+- }
++ /* Do address translations only between shared links. It is
++ * possible that while an non-AP MLD station and an AP MLD
++ * station have shared links, the frame is intended to be sent
++ * on a link which is not shared (for example when sending a
++ * probe response).
++ */
++ if (sta && sta->mlo && link_sta) {
+ /* address translation to link addresses on TX */
+ ether_addr_copy(hdr->addr1, link_sta->addr);
+ ether_addr_copy(hdr->addr2, bss_conf->addr);
+--
+2.39.5
+
--- /dev/null
+From 8df495c55c5c87d036ac835a65a0b4a4649e72f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Jan 2025 13:06:22 +0800
+Subject: wifi: mt76: mt7925: fix fails to enter low power mode in suspend
+ state
+
+From: Quan Zhou <quan.zhou@mediatek.com>
+
+[ Upstream commit 2d5630b0c9466ac6549495828aa7dce7424a272a ]
+
+The mt7925 sometimes fails to enter low power mode during suspend.
+This is caused by the chip firmware sending an additional ACK event
+to the host after processing the suspend command. Due to timing issues,
+this event may not reach the host, causing the chip to get stuck.
+To resolve this, the ACK flag in the suspend command is removed,
+as it is not needed in the MT7925 architecture. This prevents the
+firmware from sending the additional ACK event, ensuring the device
+can reliably enter low power mode during suspend.
+
+Signed-off-by: Quan Zhou <quan.zhou@mediatek.com>
+Link: https://patch.msgid.link/d056938144a3a0336c3a4e3cec6f271899f32bf7.1736775666.git.quan.zhou@mediatek.com
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+index 5b14bf434df36..2396e1795fe17 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+@@ -3287,6 +3287,9 @@ int mt7925_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb,
+ else
+ uni_txd->option = MCU_CMD_UNI_EXT_ACK;
+
++ if (cmd == MCU_UNI_CMD(HIF_CTRL))
++ uni_txd->option &= ~MCU_CMD_ACK;
++
+ goto exit;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 935cee0c3f574cda215ee2b2a39ae1cafab3c842 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Mar 2025 19:36:44 +0800
+Subject: wifi: mt76: mt7925: load the appropriate CLC data based on hardware
+ type
+
+From: Ming Yen Hsieh <mingyen.hsieh@mediatek.com>
+
+[ Upstream commit f2027ef3f733d3f0bb7f27fa3343784058f946ab ]
+
+Read the EEPROM to determine the hardware type and uses this to load the
+correct CLC data.
+
+Signed-off-by: Ming Yen Hsieh <mingyen.hsieh@mediatek.com>
+Link: https://patch.msgid.link/20250304113649.867387-1-mingyen.hsieh@mediatek.com
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/wireless/mediatek/mt76/mt7925/mcu.c | 61 ++++++++++++++++++-
+ .../wireless/mediatek/mt76/mt7925/mt7925.h | 3 +
+ 2 files changed, 63 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+index 8476f9caa98db..5b14bf434df36 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+@@ -616,6 +616,54 @@ int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev,
+ return ret;
+ }
+
++static int mt7925_mcu_read_eeprom(struct mt792x_dev *dev, u32 offset, u8 *val)
++{
++ struct {
++ u8 rsv[4];
++
++ __le16 tag;
++ __le16 len;
++
++ __le32 addr;
++ __le32 valid;
++ u8 data[MT7925_EEPROM_BLOCK_SIZE];
++ } __packed req = {
++ .tag = cpu_to_le16(1),
++ .len = cpu_to_le16(sizeof(req) - 4),
++ .addr = cpu_to_le32(round_down(offset,
++ MT7925_EEPROM_BLOCK_SIZE)),
++ };
++ struct evt {
++ u8 rsv[4];
++
++ __le16 tag;
++ __le16 len;
++
++ __le32 ver;
++ __le32 addr;
++ __le32 valid;
++ __le32 size;
++ __le32 magic_num;
++ __le32 type;
++ __le32 rsv1[4];
++ u8 data[32];
++ } __packed *res;
++ struct sk_buff *skb;
++ int ret;
++
++ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WM_UNI_CMD_QUERY(EFUSE_CTRL),
++ &req, sizeof(req), true, &skb);
++ if (ret)
++ return ret;
++
++ res = (struct evt *)skb->data;
++ *val = res->data[offset % MT7925_EEPROM_BLOCK_SIZE];
++
++ dev_kfree_skb(skb);
++
++ return 0;
++}
++
+ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name)
+ {
+ const struct mt76_connac2_fw_trailer *hdr;
+@@ -624,13 +672,20 @@ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name)
+ struct mt76_dev *mdev = &dev->mt76;
+ struct mt792x_phy *phy = &dev->phy;
+ const struct firmware *fw;
++ u8 *clc_base = NULL, hw_encap = 0;
+ int ret, i, len, offset = 0;
+- u8 *clc_base = NULL;
+
+ if (mt7925_disable_clc ||
+ mt76_is_usb(&dev->mt76))
+ return 0;
+
++ if (mt76_is_mmio(&dev->mt76)) {
++ ret = mt7925_mcu_read_eeprom(dev, MT_EE_HW_TYPE, &hw_encap);
++ if (ret)
++ return ret;
++ hw_encap = u8_get_bits(hw_encap, MT_EE_HW_TYPE_ENCAP);
++ }
++
+ ret = request_firmware(&fw, fw_name, mdev->dev);
+ if (ret)
+ return ret;
+@@ -675,6 +730,10 @@ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name)
+ if (phy->clc[clc->idx])
+ continue;
+
++ /* header content sanity */
++ if (u8_get_bits(clc->type, MT_EE_HW_TYPE_ENCAP) != hw_encap)
++ continue;
++
+ phy->clc[clc->idx] = devm_kmemdup(mdev->dev, clc,
+ le32_to_cpu(clc->len),
+ GFP_KERNEL);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
+index df3c705d1cb3f..4ad779329b8f0 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
+@@ -147,9 +147,12 @@ enum mt7925_eeprom_field {
+ MT_EE_CHIP_ID = 0x000,
+ MT_EE_VERSION = 0x002,
+ MT_EE_MAC_ADDR = 0x004,
++ MT_EE_HW_TYPE = 0xa71,
+ __MT_EE_MAX = 0x9ff
+ };
+
++#define MT_EE_HW_TYPE_ENCAP GENMASK(1, 0)
++
+ enum {
+ TXPWR_USER,
+ TXPWR_EEPROM,
+--
+2.39.5
+
--- /dev/null
+From f5739daa13bed5b6dcd9afde0e3ad0740a867199 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Mar 2025 11:36:39 +0100
+Subject: wifi: mt76: mt7996: fix SER reset trigger on WED reset
+
+From: Rex Lu <rex.lu@mediatek.com>
+
+[ Upstream commit 8d38abdf6c182225c5c0a81451fa51b7b36a635d ]
+
+The firmware needs a specific trigger when WED is being reset due to an
+ethernet reset condition. This helps prevent further L1 SER failure.
+
+Signed-off-by: Rex Lu <rex.lu@mediatek.com>
+Link: https://patch.msgid.link/20250311103646.43346-2-nbd@nbd.name
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mediatek/mt76/mt7996/mcu.h | 3 ++-
+ drivers/net/wireless/mediatek/mt76/mt7996/mmio.c | 2 +-
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
+index 43468bcaffc6d..a75e1c9435bb0 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
+@@ -908,7 +908,8 @@ enum {
+ UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE,
+ UNI_CMD_SER_SET_RECOVER_L3_BF,
+ UNI_CMD_SER_SET_RECOVER_L4_MDP,
+- UNI_CMD_SER_SET_RECOVER_FULL,
++ UNI_CMD_SER_SET_RECOVER_FROM_ETH,
++ UNI_CMD_SER_SET_RECOVER_FULL = 8,
+ UNI_CMD_SER_SET_SYSTEM_ASSERT,
+ /* action */
+ UNI_CMD_SER_ENABLE = 1,
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
+index 442f72450352b..b6209ed1cfe01 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
+@@ -281,7 +281,7 @@ static int mt7996_mmio_wed_reset(struct mtk_wed_device *wed)
+ if (test_and_set_bit(MT76_STATE_WED_RESET, &mphy->state))
+ return -EBUSY;
+
+- ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_L1,
++ ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_FROM_ETH,
+ mphy->band_idx);
+ if (ret)
+ goto out;
+--
+2.39.5
+
--- /dev/null
+From 239f14fec56d69f165ef222dbc999d09dbb62afc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Mar 2025 11:36:38 +0100
+Subject: wifi: mt76: mt7996: revise TXS size
+
+From: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+
+[ Upstream commit 593c829b4326f7b3b15a69e97c9044ecbad3c319 ]
+
+Size of MPDU/PPDU TXS is 12 DWs.
+In mt7996/mt7992, last 4 DWs are reserved, so TXS size was mistakenly
+considered to be 8 DWs. However, in mt7990, 9th DW of TXS starts to be used.
+
+Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+Link: https://patch.msgid.link/20250311103646.43346-1-nbd@nbd.name
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h | 3 +++
+ drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 4 ++--
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
+index db0c29e65185c..487ad716f872a 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
+@@ -314,6 +314,9 @@ enum tx_frag_idx {
+ #define MT_TXFREE_INFO_COUNT GENMASK(27, 24)
+ #define MT_TXFREE_INFO_STAT GENMASK(29, 28)
+
++#define MT_TXS_HDR_SIZE 4 /* Unit: DW */
++#define MT_TXS_SIZE 12 /* Unit: DW */
++
+ #define MT_TXS0_BW GENMASK(31, 29)
+ #define MT_TXS0_TID GENMASK(28, 26)
+ #define MT_TXS0_AMPDU BIT(25)
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+index f590902fdeea3..ef2d7eaaaffdd 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+@@ -1399,7 +1399,7 @@ bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len)
+ mt7996_mac_tx_free(dev, data, len);
+ return false;
+ case PKT_TYPE_TXS:
+- for (rxd += 4; rxd + 8 <= end; rxd += 8)
++ for (rxd += MT_TXS_HDR_SIZE; rxd + MT_TXS_SIZE <= end; rxd += MT_TXS_SIZE)
+ mt7996_mac_add_txs(dev, rxd);
+ return false;
+ case PKT_TYPE_RX_FW_MONITOR:
+@@ -1442,7 +1442,7 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ mt7996_mcu_rx_event(dev, skb);
+ break;
+ case PKT_TYPE_TXS:
+- for (rxd += 4; rxd + 8 <= end; rxd += 8)
++ for (rxd += MT_TXS_HDR_SIZE; rxd + MT_TXS_SIZE <= end; rxd += MT_TXS_SIZE)
+ mt7996_mac_add_txs(dev, rxd);
+ dev_kfree_skb(skb);
+ break;
+--
+2.39.5
+
--- /dev/null
+From 962bf712b773ea798eea81856d6c318f6aa694d4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Mar 2025 11:36:43 +0100
+Subject: wifi: mt76: only mark tx-status-failed frames as ACKed on mt76x0/2
+
+From: Felix Fietkau <nbd@nbd.name>
+
+[ Upstream commit 0c5a89ceddc1728a40cb3313948401dd70e3c649 ]
+
+The interrupt status polling is unreliable, which can cause status events
+to get lost. On all newer chips, txs-timeout is an indication that the
+packet was either never sent, or never acked.
+Fixes issues with inactivity polling.
+
+Link: https://patch.msgid.link/20250311103646.43346-6-nbd@nbd.name
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
+ drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 3 ++-
+ drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 3 ++-
+ drivers/net/wireless/mediatek/mt76/mt76x2/pci.c | 3 ++-
+ drivers/net/wireless/mediatek/mt76/mt76x2/usb.c | 3 ++-
+ drivers/net/wireless/mediatek/mt76/tx.c | 3 ++-
+ 6 files changed, 11 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
+index e2e9b5ece74e2..a6ac8e5512eba 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76.h
++++ b/drivers/net/wireless/mediatek/mt76/mt76.h
+@@ -489,6 +489,7 @@ struct mt76_hw_cap {
+ #define MT_DRV_RX_DMA_HDR BIT(3)
+ #define MT_DRV_HW_MGMT_TXQ BIT(4)
+ #define MT_DRV_AMSDU_OFFLOAD BIT(5)
++#define MT_DRV_IGNORE_TXS_FAILED BIT(6)
+
+ struct mt76_driver_ops {
+ u32 drv_flags;
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
+index 1eb955f3ca130..911e162a45980 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
++++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
+@@ -156,7 +156,8 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ static const struct mt76_driver_ops drv_ops = {
+ .txwi_size = sizeof(struct mt76x02_txwi),
+ .drv_flags = MT_DRV_TX_ALIGNED4_SKBS |
+- MT_DRV_SW_RX_AIRTIME,
++ MT_DRV_SW_RX_AIRTIME |
++ MT_DRV_IGNORE_TXS_FAILED,
+ .survey_flags = SURVEY_INFO_TIME_TX,
+ .update_survey = mt76x02_update_channel,
+ .set_channel = mt76x0_set_channel,
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+index b031c500b7415..90e5666c0857d 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
++++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+@@ -214,7 +214,8 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
+ const struct usb_device_id *id)
+ {
+ static const struct mt76_driver_ops drv_ops = {
+- .drv_flags = MT_DRV_SW_RX_AIRTIME,
++ .drv_flags = MT_DRV_SW_RX_AIRTIME |
++ MT_DRV_IGNORE_TXS_FAILED,
+ .survey_flags = SURVEY_INFO_TIME_TX,
+ .update_survey = mt76x02_update_channel,
+ .set_channel = mt76x0_set_channel,
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
+index 67c9d1caa0bd6..55f076231bdc5 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
++++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
+@@ -22,7 +22,8 @@ mt76x2e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ static const struct mt76_driver_ops drv_ops = {
+ .txwi_size = sizeof(struct mt76x02_txwi),
+ .drv_flags = MT_DRV_TX_ALIGNED4_SKBS |
+- MT_DRV_SW_RX_AIRTIME,
++ MT_DRV_SW_RX_AIRTIME |
++ MT_DRV_IGNORE_TXS_FAILED,
+ .survey_flags = SURVEY_INFO_TIME_TX,
+ .update_survey = mt76x02_update_channel,
+ .set_channel = mt76x2e_set_channel,
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
+index a4f4d12f904e7..84ef80ab4afbf 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
++++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
+@@ -30,7 +30,8 @@ static int mt76x2u_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+ {
+ static const struct mt76_driver_ops drv_ops = {
+- .drv_flags = MT_DRV_SW_RX_AIRTIME,
++ .drv_flags = MT_DRV_SW_RX_AIRTIME |
++ MT_DRV_IGNORE_TXS_FAILED,
+ .survey_flags = SURVEY_INFO_TIME_TX,
+ .update_survey = mt76x02_update_channel,
+ .set_channel = mt76x2u_set_channel,
+diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
+index ce193e625666b..065a1e4537457 100644
+--- a/drivers/net/wireless/mediatek/mt76/tx.c
++++ b/drivers/net/wireless/mediatek/mt76/tx.c
+@@ -100,7 +100,8 @@ __mt76_tx_status_skb_done(struct mt76_dev *dev, struct sk_buff *skb, u8 flags,
+ return;
+
+ /* Tx status can be unreliable. if it fails, mark the frame as ACKed */
+- if (flags & MT_TX_CB_TXS_FAILED) {
++ if (flags & MT_TX_CB_TXS_FAILED &&
++ (dev->drv->drv_flags & MT_DRV_IGNORE_TXS_FAILED)) {
+ info->status.rates[0].count = 0;
+ info->status.rates[0].idx = -1;
+ info->flags |= IEEE80211_TX_STAT_ACK;
+--
+2.39.5
+
--- /dev/null
+From e42e2920e39e672fad3280c951852f30f7fe2a4a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Mar 2025 17:42:38 +0800
+Subject: wifi: mwifiex: Fix HT40 bandwidth issue.
+
+From: Jeff Chen <jeff.chen_1@nxp.com>
+
+[ Upstream commit 4fcfcbe457349267fe048524078e8970807c1a5b ]
+
+This patch addresses an issue where, despite the AP supporting 40MHz
+bandwidth, the connection was limited to 20MHz. Without this fix,
+even if the access point supports 40MHz, the bandwidth after
+connection remains at 20MHz. This issue is not a regression.
+
+Signed-off-by: Jeff Chen <jeff.chen_1@nxp.com>
+Reviewed-by: Francesco Dolcini <francesco.dolcini@toradex.com>
+Link: https://patch.msgid.link/20250314094238.2097341-1-jeff.chen_1@nxp.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/marvell/mwifiex/11n.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/marvell/mwifiex/11n.c b/drivers/net/wireless/marvell/mwifiex/11n.c
+index 66f0f5377ac18..738bafc3749b0 100644
+--- a/drivers/net/wireless/marvell/mwifiex/11n.c
++++ b/drivers/net/wireless/marvell/mwifiex/11n.c
+@@ -403,12 +403,14 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
+
+ if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 &&
+ bss_desc->bcn_ht_oper->ht_param &
+- IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)
++ IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) {
++ chan_list->chan_scan_param[0].radio_type |=
++ CHAN_BW_40MHZ << 2;
+ SET_SECONDARYCHAN(chan_list->chan_scan_param[0].
+ radio_type,
+ (bss_desc->bcn_ht_oper->ht_param &
+ IEEE80211_HT_PARAM_CHA_SEC_OFFSET));
+-
++ }
+ *buffer += struct_size(chan_list, chan_scan_param, 1);
+ ret_len += struct_size(chan_list, chan_scan_param, 1);
+ }
+--
+2.39.5
+
--- /dev/null
+From 87aff57c1de042e4912fa33a22e4bc24ad209208 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jan 2025 20:48:28 +0100
+Subject: wifi: rtl8xxxu: retry firmware download on error
+
+From: Soeren Moch <smoch@web.de>
+
+[ Upstream commit 3d3e28feca7ac8c6cf2a390dbbe1f97e3feb7f36 ]
+
+Occasionally there is an EPROTO error during firmware download.
+This error is converted to EAGAIN in the download function.
+But nobody tries again and so device probe fails.
+
+Implement download retry to fix this.
+
+This error was observed (and fix tested) on a tbs2910 board [1]
+with an embedded RTL8188EU (0bda:8179) device behind a USB hub.
+
+[1] arch/arm/boot/dts/nxp/imx/imx6q-tbs2910.dts
+
+Signed-off-by: Soeren Moch <smoch@web.de>
+Acked-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20250127194828.599379-1-smoch@web.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtl8xxxu/core.c | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c b/drivers/net/wireless/realtek/rtl8xxxu/core.c
+index 4ce0c05c51291..569856ca677f6 100644
+--- a/drivers/net/wireless/realtek/rtl8xxxu/core.c
++++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c
+@@ -860,9 +860,10 @@ rtl8xxxu_writeN(struct rtl8xxxu_priv *priv, u16 addr, u8 *buf, u16 len)
+ return len;
+
+ write_error:
+- dev_info(&udev->dev,
+- "%s: Failed to write block at addr: %04x size: %04x\n",
+- __func__, addr, blocksize);
++ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_WRITE)
++ dev_info(&udev->dev,
++ "%s: Failed to write block at addr: %04x size: %04x\n",
++ __func__, addr, blocksize);
+ return -EAGAIN;
+ }
+
+@@ -4064,8 +4065,14 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
+ */
+ rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, fops->trxff_boundary);
+
+- ret = rtl8xxxu_download_firmware(priv);
+- dev_dbg(dev, "%s: download_firmware %i\n", __func__, ret);
++ for (int retry = 5; retry >= 0 ; retry--) {
++ ret = rtl8xxxu_download_firmware(priv);
++ dev_dbg(dev, "%s: download_firmware %i\n", __func__, ret);
++ if (ret != -EAGAIN)
++ break;
++ if (retry)
++ dev_dbg(dev, "%s: retry firmware download\n", __func__);
++ }
+ if (ret)
+ goto exit;
+ ret = rtl8xxxu_start_firmware(priv);
+--
+2.39.5
+
--- /dev/null
+From dbea83d64eb1e19b0f78e8fdb3f5286cd114540b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 26 Jan 2025 16:03:11 +0200
+Subject: wifi: rtw88: Don't use static local variable in
+ rtw8822b_set_tx_power_index_by_rate
+
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+
+[ Upstream commit 00451eb3bec763f708e7e58326468c1e575e5a66 ]
+
+Some users want to plug two identical USB devices at the same time.
+This static variable could theoretically cause them to use incorrect
+TX power values.
+
+Move the variable to the caller and pass a pointer to it to
+rtw8822b_set_tx_power_index_by_rate().
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Acked-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/8a60f581-0ab5-4d98-a97d-dd83b605008f@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw88/rtw8822b.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+index 6edb17aea90e0..4a6c0a9266a09 100644
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+@@ -976,11 +976,11 @@ static void rtw8822b_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc,
+ }
+
+ static void
+-rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs)
++rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path,
++ u8 rs, u32 *phy_pwr_idx)
+ {
+ struct rtw_hal *hal = &rtwdev->hal;
+ static const u32 offset_txagc[2] = {0x1d00, 0x1d80};
+- static u32 phy_pwr_idx;
+ u8 rate, rate_idx, pwr_index, shift;
+ int j;
+
+@@ -988,12 +988,12 @@ rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs)
+ rate = rtw_rate_section[rs][j];
+ pwr_index = hal->tx_pwr_tbl[path][rate];
+ shift = rate & 0x3;
+- phy_pwr_idx |= ((u32)pwr_index << (shift * 8));
++ *phy_pwr_idx |= ((u32)pwr_index << (shift * 8));
+ if (shift == 0x3) {
+ rate_idx = rate & 0xfc;
+ rtw_write32(rtwdev, offset_txagc[path] + rate_idx,
+- phy_pwr_idx);
+- phy_pwr_idx = 0;
++ *phy_pwr_idx);
++ *phy_pwr_idx = 0;
+ }
+ }
+ }
+@@ -1001,11 +1001,13 @@ rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs)
+ static void rtw8822b_set_tx_power_index(struct rtw_dev *rtwdev)
+ {
+ struct rtw_hal *hal = &rtwdev->hal;
++ u32 phy_pwr_idx = 0;
+ int rs, path;
+
+ for (path = 0; path < hal->rf_path_num; path++) {
+ for (rs = 0; rs < RTW_RATE_SECTION_MAX; rs++)
+- rtw8822b_set_tx_power_index_by_rate(rtwdev, path, rs);
++ rtw8822b_set_tx_power_index_by_rate(rtwdev, path, rs,
++ &phy_pwr_idx);
+ }
+ }
+
+--
+2.39.5
+
--- /dev/null
+From bfc1a42749f85aa868587f7652ab81a4bd3fd6e6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Feb 2025 20:36:56 +0200
+Subject: wifi: rtw88: Fix __rtw_download_firmware() for RTL8814AU
+
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+
+[ Upstream commit 8425f5c8f04dbcf11ade78f984a494fc0b90e7a0 ]
+
+Don't call ltecoex_read_reg() and ltecoex_reg_write() when the
+ltecoex_addr member of struct rtw_chip_info is NULL. The RTL8814AU
+doesn't have this feature.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Acked-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/55b5641f-094e-4f94-9f79-ac053733f2cf@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw88/mac.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c
+index 564f5988ee82a..d1c4f5cdcb21d 100644
+--- a/drivers/net/wireless/realtek/rtw88/mac.c
++++ b/drivers/net/wireless/realtek/rtw88/mac.c
+@@ -783,7 +783,8 @@ static int __rtw_download_firmware(struct rtw_dev *rtwdev,
+ if (!check_firmware_size(data, size))
+ return -EINVAL;
+
+- if (!ltecoex_read_reg(rtwdev, 0x38, <ecoex_bckp))
++ if (rtwdev->chip->ltecoex_addr &&
++ !ltecoex_read_reg(rtwdev, 0x38, <ecoex_bckp))
+ return -EBUSY;
+
+ wlan_cpu_enable(rtwdev, false);
+@@ -801,7 +802,8 @@ static int __rtw_download_firmware(struct rtw_dev *rtwdev,
+
+ wlan_cpu_enable(rtwdev, true);
+
+- if (!ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp)) {
++ if (rtwdev->chip->ltecoex_addr &&
++ !ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp)) {
+ ret = -EBUSY;
+ goto dlfw_fail;
+ }
+--
+2.39.5
+
--- /dev/null
+From 7779fd53b5467d3f3960d8445dcfeab9f8d4866c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Feb 2025 20:37:36 +0200
+Subject: wifi: rtw88: Fix download_firmware_validate() for RTL8814AU
+
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+
+[ Upstream commit 9e8243025cc06abc975c876dffda052073207ab3 ]
+
+After the firmware is uploaded, download_firmware_validate() checks some
+bits in REG_MCUFW_CTRL to see if everything went okay. The
+RTL8814AU power on sequence sets bits 13 and 12 to 2, which this
+function does not expect, so it thinks the firmware upload failed.
+
+Make download_firmware_validate() ignore bits 13 and 12.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Acked-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/049d2887-22fc-47b7-9e59-62627cb525f8@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw88/reg.h | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h
+index 4d9b8668e8b04..2708ee2f12a47 100644
+--- a/drivers/net/wireless/realtek/rtw88/reg.h
++++ b/drivers/net/wireless/realtek/rtw88/reg.h
+@@ -109,6 +109,7 @@
+ #define BIT_SHIFT_ROM_PGE 16
+ #define BIT_FW_INIT_RDY BIT(15)
+ #define BIT_FW_DW_RDY BIT(14)
++#define BIT_CPU_CLK_SEL (BIT(12) | BIT(13))
+ #define BIT_RPWM_TOGGLE BIT(7)
+ #define BIT_RAM_DL_SEL BIT(7) /* legacy only */
+ #define BIT_DMEM_CHKSUM_OK BIT(6)
+@@ -126,7 +127,7 @@
+ BIT_CHECK_SUM_OK)
+ #define FW_READY_LEGACY (BIT_MCUFWDL_RDY | BIT_FWDL_CHK_RPT | \
+ BIT_WINTINI_RDY | BIT_RAM_DL_SEL)
+-#define FW_READY_MASK 0xffff
++#define FW_READY_MASK (0xffff & ~BIT_CPU_CLK_SEL)
+
+ #define REG_MCU_TST_CFG 0x84
+ #define VAL_FW_TRIGGER 0x1
+--
+2.39.5
+
--- /dev/null
+From b0dcddcb87a0765155e6475003b5d0ded3c3ed1a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Feb 2025 01:29:52 +0200
+Subject: wifi: rtw88: Fix rtw_desc_to_mcsrate() to handle MCS16-31
+
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+
+[ Upstream commit 86d04f8f991a0509e318fe886d5a1cf795736c7d ]
+
+This function translates the rate number reported by the hardware into
+something mac80211 can understand. It was ignoring the 3SS and 4SS HT
+rates. Translate them too.
+
+Also set *nss to 0 for the HT rates, just to make sure it's
+initialised.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Acked-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/d0a5a86b-4869-47f6-a5a7-01c0f987cc7f@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw88/util.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw88/util.c b/drivers/net/wireless/realtek/rtw88/util.c
+index e222d3c01a77e..66819f6944055 100644
+--- a/drivers/net/wireless/realtek/rtw88/util.c
++++ b/drivers/net/wireless/realtek/rtw88/util.c
+@@ -101,7 +101,8 @@ void rtw_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss)
+ *nss = 4;
+ *mcs = rate - DESC_RATEVHT4SS_MCS0;
+ } else if (rate >= DESC_RATEMCS0 &&
+- rate <= DESC_RATEMCS15) {
++ rate <= DESC_RATEMCS31) {
++ *nss = 0;
+ *mcs = rate - DESC_RATEMCS0;
+ }
+ }
+--
+2.39.5
+
--- /dev/null
+From ba0a5b0fd6d0f573129ee9080bc6f14ced6c97b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Feb 2025 01:30:22 +0200
+Subject: wifi: rtw88: Fix rtw_init_ht_cap() for RTL8814AU
+
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+
+[ Upstream commit c7eea1ba05ca5b0dbf77a27cf2e1e6e2fb3c0043 ]
+
+Set the RX mask and the highest RX rate according to the number of
+spatial streams the chip can receive. For RTL8814AU that is 3.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Acked-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/4e786f50-ed1c-4387-8b28-e6ff00e35e81@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw88/main.c | 17 ++++++-----------
+ 1 file changed, 6 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
+index 2c81e4cae039e..a808af2f085ec 100644
+--- a/drivers/net/wireless/realtek/rtw88/main.c
++++ b/drivers/net/wireless/realtek/rtw88/main.c
+@@ -1543,6 +1543,7 @@ static void rtw_init_ht_cap(struct rtw_dev *rtwdev,
+ {
+ const struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
++ int i;
+
+ ht_cap->ht_supported = true;
+ ht_cap->cap = 0;
+@@ -1562,17 +1563,11 @@ static void rtw_init_ht_cap(struct rtw_dev *rtwdev,
+ ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+ ht_cap->ampdu_density = chip->ampdu_density;
+ ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+- if (efuse->hw_cap.nss > 1) {
+- ht_cap->mcs.rx_mask[0] = 0xFF;
+- ht_cap->mcs.rx_mask[1] = 0xFF;
+- ht_cap->mcs.rx_mask[4] = 0x01;
+- ht_cap->mcs.rx_highest = cpu_to_le16(300);
+- } else {
+- ht_cap->mcs.rx_mask[0] = 0xFF;
+- ht_cap->mcs.rx_mask[1] = 0x00;
+- ht_cap->mcs.rx_mask[4] = 0x01;
+- ht_cap->mcs.rx_highest = cpu_to_le16(150);
+- }
++
++ for (i = 0; i < efuse->hw_cap.nss; i++)
++ ht_cap->mcs.rx_mask[i] = 0xFF;
++ ht_cap->mcs.rx_mask[4] = 0x01;
++ ht_cap->mcs.rx_highest = cpu_to_le16(150 * efuse->hw_cap.nss);
+ }
+
+ static void rtw_init_vht_cap(struct rtw_dev *rtwdev,
+--
+2.39.5
+
--- /dev/null
+From 070dc0a1d1c328bd0ea95468e0d7f52a6ea5ab01 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Feb 2025 01:30:48 +0200
+Subject: wifi: rtw88: Fix rtw_init_vht_cap() for RTL8814AU
+
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+
+[ Upstream commit 6be7544d19fcfcb729495e793bc6181f85bb8949 ]
+
+Set the MCS maps and the highest rates according to the number of
+spatial streams the chip has. For RTL8814AU that is 3.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Acked-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/e86aa009-b5bf-4b3a-8112-ea5e3cd49465@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw88/main.c | 23 +++++++++--------------
+ 1 file changed, 9 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
+index bbdef38c7e341..2c81e4cae039e 100644
+--- a/drivers/net/wireless/realtek/rtw88/main.c
++++ b/drivers/net/wireless/realtek/rtw88/main.c
+@@ -1579,8 +1579,9 @@ static void rtw_init_vht_cap(struct rtw_dev *rtwdev,
+ struct ieee80211_sta_vht_cap *vht_cap)
+ {
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+- u16 mcs_map;
++ u16 mcs_map = 0;
+ __le16 highest;
++ int i;
+
+ if (efuse->hw_cap.ptcl != EFUSE_HW_CAP_IGNORE &&
+ efuse->hw_cap.ptcl != EFUSE_HW_CAP_PTCL_VHT)
+@@ -1603,21 +1604,15 @@ static void rtw_init_vht_cap(struct rtw_dev *rtwdev,
+ if (rtw_chip_has_rx_ldpc(rtwdev))
+ vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC;
+
+- mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 |
+- IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 |
+- IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 |
+- IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 |
+- IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 |
+- IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 |
+- IEEE80211_VHT_MCS_NOT_SUPPORTED << 14;
+- if (efuse->hw_cap.nss > 1) {
+- highest = cpu_to_le16(780);
+- mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << 2;
+- } else {
+- highest = cpu_to_le16(390);
+- mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << 2;
++ for (i = 0; i < 8; i++) {
++ if (i < efuse->hw_cap.nss)
++ mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2);
++ else
++ mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);
+ }
+
++ highest = cpu_to_le16(390 * efuse->hw_cap.nss);
++
+ vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
+ vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
+ vht_cap->vht_mcs.rx_highest = highest;
+--
+2.39.5
+
--- /dev/null
+From ef48e063634ebdfa97aa5e0565d7b737f7739141 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 14:12:35 +0800
+Subject: wifi: rtw89: 8922a: fix incorrect STA-ID in EHT MU PPDU
+
+From: Kuan-Chung Chen <damon.chen@realtek.com>
+
+[ Upstream commit bdce0574243b43b3bb2064f609c0c326df44c4c6 ]
+
+EHT MU PPDU contains user field of EHT-SIG field with STA-ID that
+must match AID subfield in the Associate Response. Add a necessary
+setting to prevent these from being inconsistent.
+
+Signed-off-by: Kuan-Chung Chen <damon.chen@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20250217061235.32031-1-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/fw.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
+index 93d760b8b5e35..9346fe082040c 100644
+--- a/drivers/net/wireless/realtek/rtw89/fw.c
++++ b/drivers/net/wireless/realtek/rtw89/fw.c
+@@ -3128,9 +3128,10 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev,
+ CCTLINFO_G7_W5_NOMINAL_PKT_PADDING3 |
+ CCTLINFO_G7_W5_NOMINAL_PKT_PADDING4);
+
+- h2c->w6 = le32_encode_bits(vif->type == NL80211_IFTYPE_STATION ? 1 : 0,
++ h2c->w6 = le32_encode_bits(vif->cfg.aid, CCTLINFO_G7_W6_AID12_PAID) |
++ le32_encode_bits(vif->type == NL80211_IFTYPE_STATION ? 1 : 0,
+ CCTLINFO_G7_W6_ULDL);
+- h2c->m6 = cpu_to_le32(CCTLINFO_G7_W6_ULDL);
++ h2c->m6 = cpu_to_le32(CCTLINFO_G7_W6_AID12_PAID | CCTLINFO_G7_W6_ULDL);
+
+ if (rtwsta_link) {
+ h2c->w8 = le32_encode_bits(link_sta->he_cap.has_he,
+--
+2.39.5
+
--- /dev/null
+From ad733f6142e71a25be0ed71b8f295eed572595fc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jan 2025 14:03:01 +0800
+Subject: wifi: rtw89: add wiphy_lock() to work that isn't held wiphy_lock()
+ yet
+
+From: Ping-Ke Shih <pkshih@realtek.com>
+
+[ Upstream commit ebfc9199df05d37b67f4d1b7ee997193f3d2e7c8 ]
+
+To ensure where are protected by driver mutex can also be protected by
+wiphy_lock(), so afterward we can remove driver mutex safely.
+
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20250122060310.31976-2-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/regd.c | 2 ++
+ drivers/net/wireless/realtek/rtw89/ser.c | 4 ++++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c
+index bb064a086970b..e8df68818da01 100644
+--- a/drivers/net/wireless/realtek/rtw89/regd.c
++++ b/drivers/net/wireless/realtek/rtw89/regd.c
+@@ -695,6 +695,7 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct rtw89_dev *rtwdev = hw->priv;
+
++ wiphy_lock(wiphy);
+ mutex_lock(&rtwdev->mutex);
+ rtw89_leave_ps_mode(rtwdev);
+
+@@ -712,6 +713,7 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request
+
+ exit:
+ mutex_unlock(&rtwdev->mutex);
++ wiphy_unlock(wiphy);
+ }
+
+ /* Maximum Transmit Power field (@raw) can be EIRP or PSD.
+diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c
+index 7b203bb7f151a..02c2ac12f197a 100644
+--- a/drivers/net/wireless/realtek/rtw89/ser.c
++++ b/drivers/net/wireless/realtek/rtw89/ser.c
+@@ -156,9 +156,11 @@ static void ser_state_run(struct rtw89_ser *ser, u8 evt)
+ rtw89_debug(rtwdev, RTW89_DBG_SER, "ser: %s receive %s\n",
+ ser_st_name(ser), ser_ev_name(ser, evt));
+
++ wiphy_lock(rtwdev->hw->wiphy);
+ mutex_lock(&rtwdev->mutex);
+ rtw89_leave_lps(rtwdev);
+ mutex_unlock(&rtwdev->mutex);
++ wiphy_unlock(rtwdev->hw->wiphy);
+
+ ser->st_tbl[ser->state].st_func(ser, evt);
+ }
+@@ -707,9 +709,11 @@ static void ser_l2_reset_st_hdl(struct rtw89_ser *ser, u8 evt)
+
+ switch (evt) {
+ case SER_EV_STATE_IN:
++ wiphy_lock(rtwdev->hw->wiphy);
+ mutex_lock(&rtwdev->mutex);
+ ser_l2_reset_st_pre_hdl(ser);
+ mutex_unlock(&rtwdev->mutex);
++ wiphy_unlock(rtwdev->hw->wiphy);
+
+ ieee80211_restart_hw(rtwdev->hw);
+ ser_set_alarm(ser, SER_RECFG_TIMEOUT, SER_EV_L2_RECFG_TIMEOUT);
+--
+2.39.5
+
--- /dev/null
+From f57ee9a8468718e730f68ea164e05b6e20f53a80 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Feb 2025 15:29:08 +0800
+Subject: wifi: rtw89: call power_on ahead before selecting firmware
+
+From: Ping-Ke Shih <pkshih@realtek.com>
+
+[ Upstream commit d078f5857a00c06fa0ddee26d3cb722e938e1688 ]
+
+Driver selects firmware by hardware version, which normally can be read
+from registers before selecting firmware. However, certain chips such as
+RTL8851B, it needs to read hardware version from efuse while doing
+power_on, but do power_on after selecting firmware in current flow.
+
+To resolve this flow problem, move power_on out from
+rtw89_mac_partial_init(), and call rtw89_mac_pwr_on() separately at
+proper places to have expected flow.
+
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20250203072911.47313-2-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/core.c | 23 +++++++++++-------
+ drivers/net/wireless/realtek/rtw89/mac.c | 29 ++++++++++++++++-------
+ drivers/net/wireless/realtek/rtw89/mac.h | 1 +
+ 3 files changed, 36 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
+index f82a26be6fa82..83b22bd0ce81a 100644
+--- a/drivers/net/wireless/realtek/rtw89/core.c
++++ b/drivers/net/wireless/realtek/rtw89/core.c
+@@ -4862,8 +4862,6 @@ static int rtw89_chip_efuse_info_setup(struct rtw89_dev *rtwdev)
+
+ rtw89_hci_mac_pre_deinit(rtwdev);
+
+- rtw89_mac_pwr_off(rtwdev);
+-
+ return 0;
+ }
+
+@@ -4944,36 +4942,45 @@ int rtw89_chip_info_setup(struct rtw89_dev *rtwdev)
+
+ rtw89_read_chip_ver(rtwdev);
+
++ ret = rtw89_mac_pwr_on(rtwdev);
++ if (ret) {
++ rtw89_err(rtwdev, "failed to power on\n");
++ return ret;
++ }
++
+ ret = rtw89_wait_firmware_completion(rtwdev);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to wait firmware completion\n");
+- return ret;
++ goto out;
+ }
+
+ ret = rtw89_fw_recognize(rtwdev);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to recognize firmware\n");
+- return ret;
++ goto out;
+ }
+
+ ret = rtw89_chip_efuse_info_setup(rtwdev);
+ if (ret)
+- return ret;
++ goto out;
+
+ ret = rtw89_fw_recognize_elements(rtwdev);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to recognize firmware elements\n");
+- return ret;
++ goto out;
+ }
+
+ ret = rtw89_chip_board_info_setup(rtwdev);
+ if (ret)
+- return ret;
++ goto out;
+
+ rtw89_core_setup_rfe_parms(rtwdev);
+ rtwdev->ps_mode = rtw89_update_ps_mode(rtwdev);
+
+- return 0;
++out:
++ rtw89_mac_pwr_off(rtwdev);
++
++ return ret;
+ }
+ EXPORT_SYMBOL(rtw89_chip_info_setup);
+
+diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
+index 04e254bd6b17f..9b09d4b7dea59 100644
+--- a/drivers/net/wireless/realtek/rtw89/mac.c
++++ b/drivers/net/wireless/realtek/rtw89/mac.c
+@@ -1491,6 +1491,21 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
+ #undef PWR_ACT
+ }
+
++int rtw89_mac_pwr_on(struct rtw89_dev *rtwdev)
++{
++ int ret;
++
++ ret = rtw89_mac_power_switch(rtwdev, true);
++ if (ret) {
++ rtw89_mac_power_switch(rtwdev, false);
++ ret = rtw89_mac_power_switch(rtwdev, true);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++}
++
+ void rtw89_mac_pwr_off(struct rtw89_dev *rtwdev)
+ {
+ rtw89_mac_power_switch(rtwdev, false);
+@@ -3918,14 +3933,6 @@ int rtw89_mac_partial_init(struct rtw89_dev *rtwdev, bool include_bb)
+ {
+ int ret;
+
+- ret = rtw89_mac_power_switch(rtwdev, true);
+- if (ret) {
+- rtw89_mac_power_switch(rtwdev, false);
+- ret = rtw89_mac_power_switch(rtwdev, true);
+- if (ret)
+- return ret;
+- }
+-
+ rtw89_mac_ctrl_hci_dma_trx(rtwdev, true);
+
+ if (include_bb) {
+@@ -3958,6 +3965,10 @@ int rtw89_mac_init(struct rtw89_dev *rtwdev)
+ bool include_bb = !!chip->bbmcu_nr;
+ int ret;
+
++ ret = rtw89_mac_pwr_on(rtwdev);
++ if (ret)
++ return ret;
++
+ ret = rtw89_mac_partial_init(rtwdev, include_bb);
+ if (ret)
+ goto fail;
+@@ -3989,7 +4000,7 @@ int rtw89_mac_init(struct rtw89_dev *rtwdev)
+
+ return ret;
+ fail:
+- rtw89_mac_power_switch(rtwdev, false);
++ rtw89_mac_pwr_off(rtwdev);
+
+ return ret;
+ }
+diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
+index 5ba1133b79d64..7974849f41e25 100644
+--- a/drivers/net/wireless/realtek/rtw89/mac.h
++++ b/drivers/net/wireless/realtek/rtw89/mac.h
+@@ -1120,6 +1120,7 @@ rtw89_write32_port_set(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_l
+ rtw89_write32_set(rtwdev, reg, bit);
+ }
+
++int rtw89_mac_pwr_on(struct rtw89_dev *rtwdev);
+ void rtw89_mac_pwr_off(struct rtw89_dev *rtwdev);
+ int rtw89_mac_partial_init(struct rtw89_dev *rtwdev, bool include_bb);
+ int rtw89_mac_init(struct rtw89_dev *rtwdev);
+--
+2.39.5
+
--- /dev/null
+From 647e580fd18c847d064104754558146f4bedc356 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Feb 2025 09:32:31 +0800
+Subject: wifi: rtw89: coex: Assign value over than 0 to avoid firmware timer
+ hang
+
+From: Ching-Te Ku <ku920601@realtek.com>
+
+[ Upstream commit 2e4c4717b3f6f019c71af984564b6e4d0ae8d0bd ]
+
+If the slot duration is 0, the firmware timer will trigger timer hang at
+the timer initializing state in a low rate due to hardware algorithm.
+
+Signed-off-by: Ching-Te Ku <ku920601@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20250205013233.10945-2-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/coex.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c
+index 8d54d71fcf539..5f878f086f7cf 100644
+--- a/drivers/net/wireless/realtek/rtw89/coex.c
++++ b/drivers/net/wireless/realtek/rtw89/coex.c
+@@ -89,10 +89,10 @@ static const struct rtw89_btc_fbtc_slot s_def[] = {
+ [CXST_B4] = __DEF_FBTC_SLOT(50, 0xe5555555, SLOT_MIX),
+ [CXST_LK] = __DEF_FBTC_SLOT(20, 0xea5a5a5a, SLOT_ISO),
+ [CXST_BLK] = __DEF_FBTC_SLOT(500, 0x55555555, SLOT_MIX),
+- [CXST_E2G] = __DEF_FBTC_SLOT(0, 0xea5a5a5a, SLOT_MIX),
+- [CXST_E5G] = __DEF_FBTC_SLOT(0, 0xffffffff, SLOT_ISO),
++ [CXST_E2G] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_MIX),
++ [CXST_E5G] = __DEF_FBTC_SLOT(5, 0xffffffff, SLOT_ISO),
+ [CXST_EBT] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX),
+- [CXST_ENULL] = __DEF_FBTC_SLOT(0, 0xaaaaaaaa, SLOT_ISO),
++ [CXST_ENULL] = __DEF_FBTC_SLOT(5, 0xaaaaaaaa, SLOT_ISO),
+ [CXST_WLK] = __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX),
+ [CXST_W1FDD] = __DEF_FBTC_SLOT(50, 0xffffffff, SLOT_ISO),
+ [CXST_B1FDD] = __DEF_FBTC_SLOT(50, 0xffffdfff, SLOT_ISO),
+--
+2.39.5
+
--- /dev/null
+From b659357ef7cdec0b54e38908abe7f9cc9de384b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Jan 2025 09:54:15 +0800
+Subject: wifi: rtw89: coex: Separated Wi-Fi connecting event from Wi-Fi scan
+ event
+
+From: Ching-Te Ku <ku920601@realtek.com>
+
+[ Upstream commit 4a57346652154bb339c48b41166df9154cff33f5 ]
+
+Wi-Fi connecting process don't need to assign to firmware slot control,
+if assign firmware slot control for Wi-Fi connecting event, firmware will
+not toggle slots because driver don't tell the slot schedule to firmware.
+Wi-Fi connecting event end should also cancel the 4way handshake status.
+
+Signed-off-by: Ching-Te Ku <ku920601@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20250110015416.10704-3-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/coex.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c
+index 5f878f086f7cf..6cdbf02f405ae 100644
+--- a/drivers/net/wireless/realtek/rtw89/coex.c
++++ b/drivers/net/wireless/realtek/rtw89/coex.c
+@@ -5356,7 +5356,8 @@ static void _action_wl_scan(struct rtw89_dev *rtwdev)
+ struct rtw89_btc_wl_info *wl = &btc->cx.wl;
+ struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
+
+- if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
++ if (btc->cx.state_map != BTC_WLINKING &&
++ RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
+ _action_wl_25g_mcc(rtwdev);
+ rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n");
+ } else if (rtwdev->dbcc_en) {
+@@ -7178,6 +7179,8 @@ void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx)
+ _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
+ }
+
++ btc->dm.tdma_instant_excute = 1;
++
+ _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH);
+ }
+
+@@ -7630,7 +7633,8 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev,
+ else
+ wl->status.map.connecting = 0;
+
+- if (state == BTC_ROLE_MSTS_STA_DIS_CONN)
++ if (state == BTC_ROLE_MSTS_STA_DIS_CONN ||
++ state == BTC_ROLE_MSTS_STA_CONN_END)
+ wl->status.map._4way = false;
+
+ _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO);
+--
+2.39.5
+
--- /dev/null
+From 3d93caea03a632f84e2b5394e9301b5982583273 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 14:43:04 +0800
+Subject: wifi: rtw89: fw: add blacklist to avoid obsolete secure firmware
+
+From: Ping-Ke Shih <pkshih@realtek.com>
+
+[ Upstream commit f11d042b3a2e92ab1aa10e0da8e290bcdcf31d39 ]
+
+To ensure secure chip only runs expected secure firmware, stop using
+obsolete firmware in blacklist which weakness or flaw was found.
+
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20250217064308.43559-2-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/core.h | 2 +
+ drivers/net/wireless/realtek/rtw89/fw.c | 52 ++++++++++++++++++-
+ drivers/net/wireless/realtek/rtw89/fw.h | 12 +++++
+ drivers/net/wireless/realtek/rtw89/rtw8851b.c | 1 +
+ drivers/net/wireless/realtek/rtw89/rtw8852a.c | 1 +
+ drivers/net/wireless/realtek/rtw89/rtw8852b.c | 1 +
+ .../net/wireless/realtek/rtw89/rtw8852bt.c | 1 +
+ drivers/net/wireless/realtek/rtw89/rtw8852c.c | 1 +
+ drivers/net/wireless/realtek/rtw89/rtw8922a.c | 1 +
+ 9 files changed, 71 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
+index ff3048d2489f1..4f64ea392e6c9 100644
+--- a/drivers/net/wireless/realtek/rtw89/core.h
++++ b/drivers/net/wireless/realtek/rtw89/core.h
+@@ -17,6 +17,7 @@ struct rtw89_dev;
+ struct rtw89_pci_info;
+ struct rtw89_mac_gen_def;
+ struct rtw89_phy_gen_def;
++struct rtw89_fw_blacklist;
+ struct rtw89_efuse_block_cfg;
+ struct rtw89_h2c_rf_tssi;
+ struct rtw89_fw_txpwr_track_cfg;
+@@ -4232,6 +4233,7 @@ struct rtw89_chip_info {
+ bool try_ce_fw;
+ u8 bbmcu_nr;
+ u32 needed_fw_elms;
++ const struct rtw89_fw_blacklist *fw_blacklist;
+ u32 fifo_size;
+ bool small_fifo_size;
+ u32 dle_scc_rsvd_size;
+diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
+index f0e87af68d8cb..93d760b8b5e35 100644
+--- a/drivers/net/wireless/realtek/rtw89/fw.c
++++ b/drivers/net/wireless/realtek/rtw89/fw.c
+@@ -38,6 +38,16 @@ struct rtw89_arp_rsp {
+
+ static const u8 mss_signature[] = {0x4D, 0x53, 0x53, 0x4B, 0x50, 0x4F, 0x4F, 0x4C};
+
++const struct rtw89_fw_blacklist rtw89_fw_blacklist_default = {
++ .ver = 0x00,
++ .list = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++ },
++};
++EXPORT_SYMBOL(rtw89_fw_blacklist_default);
++
+ union rtw89_fw_element_arg {
+ size_t offset;
+ enum rtw89_rf_path rf_path;
+@@ -315,6 +325,46 @@ static int __parse_formatted_mssc(struct rtw89_dev *rtwdev,
+ return 0;
+ }
+
++static int __check_secure_blacklist(struct rtw89_dev *rtwdev,
++ struct rtw89_fw_bin_info *info,
++ struct rtw89_fw_hdr_section_info *section_info,
++ const void *content)
++{
++ const struct rtw89_fw_blacklist *chip_blacklist = rtwdev->chip->fw_blacklist;
++ const union rtw89_fw_section_mssc_content *section_content = content;
++ struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
++ u8 byte_idx;
++ u8 bit_mask;
++
++ if (!sec->secure_boot)
++ return 0;
++
++ if (!info->secure_section_exist || section_info->ignore)
++ return 0;
++
++ if (!chip_blacklist) {
++ rtw89_err(rtwdev, "chip no blacklist for secure firmware\n");
++ return -ENOENT;
++ }
++
++ byte_idx = section_content->blacklist.bit_in_chip_list >> 3;
++ bit_mask = BIT(section_content->blacklist.bit_in_chip_list & 0x7);
++
++ if (section_content->blacklist.ver > chip_blacklist->ver) {
++ rtw89_err(rtwdev, "chip blacklist out of date (%u, %u)\n",
++ section_content->blacklist.ver, chip_blacklist->ver);
++ return -EINVAL;
++ }
++
++ if (chip_blacklist->list[byte_idx] & bit_mask) {
++ rtw89_err(rtwdev, "firmware %u in chip blacklist\n",
++ section_content->blacklist.ver);
++ return -EPERM;
++ }
++
++ return 0;
++}
++
+ static int __parse_security_section(struct rtw89_dev *rtwdev,
+ struct rtw89_fw_bin_info *info,
+ struct rtw89_fw_hdr_section_info *section_info,
+@@ -340,7 +390,7 @@ static int __parse_security_section(struct rtw89_dev *rtwdev,
+ info->secure_section_exist = true;
+ }
+
+- return 0;
++ return __check_secure_blacklist(rtwdev, info, section_info, content);
+ }
+
+ static int rtw89_fw_hdr_parser_v1(struct rtw89_dev *rtwdev, const u8 *fw, u32 len,
+diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
+index ccbbc43f33fee..502ece540b9dc 100644
+--- a/drivers/net/wireless/realtek/rtw89/fw.h
++++ b/drivers/net/wireless/realtek/rtw89/fw.h
+@@ -639,6 +639,11 @@ struct rtw89_fw_mss_pool_hdr {
+ } __packed;
+
+ union rtw89_fw_section_mssc_content {
++ struct {
++ u8 pad[0x20];
++ u8 bit_in_chip_list;
++ u8 ver;
++ } __packed blacklist;
+ struct {
+ u8 pad[58];
+ __le32 v;
+@@ -649,6 +654,13 @@ union rtw89_fw_section_mssc_content {
+ } __packed key_sign_len;
+ } __packed;
+
++struct rtw89_fw_blacklist {
++ u8 ver;
++ u8 list[32];
++};
++
++extern const struct rtw89_fw_blacklist rtw89_fw_blacklist_default;
++
+ static inline void SET_CTRL_INFO_MACID(void *table, u32 val)
+ {
+ le32p_replace_bits((__le32 *)(table) + 0, val, GENMASK(6, 0));
+diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
+index f9766bf30e71d..0d2a1e712b345 100644
+--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c
++++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
+@@ -2443,6 +2443,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
+ .try_ce_fw = true,
+ .bbmcu_nr = 0,
+ .needed_fw_elms = 0,
++ .fw_blacklist = NULL,
+ .fifo_size = 196608,
+ .small_fifo_size = true,
+ .dle_scc_rsvd_size = 98304,
+diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+index 42d369d2e916a..5f08207936c68 100644
+--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
++++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+@@ -2159,6 +2159,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
+ .try_ce_fw = false,
+ .bbmcu_nr = 0,
+ .needed_fw_elms = 0,
++ .fw_blacklist = NULL,
+ .fifo_size = 458752,
+ .small_fifo_size = false,
+ .dle_scc_rsvd_size = 0,
+diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+index 364aa21cbd446..0e03d97ba1cf6 100644
+--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c
++++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+@@ -797,6 +797,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
+ .try_ce_fw = true,
+ .bbmcu_nr = 0,
+ .needed_fw_elms = 0,
++ .fw_blacklist = &rtw89_fw_blacklist_default,
+ .fifo_size = 196608,
+ .small_fifo_size = true,
+ .dle_scc_rsvd_size = 98304,
+diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
+index dab7e71ec6a14..1dd3e51bab9f3 100644
+--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
++++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
+@@ -731,6 +731,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = {
+ .try_ce_fw = true,
+ .bbmcu_nr = 0,
+ .needed_fw_elms = RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS_NO_6GHZ,
++ .fw_blacklist = &rtw89_fw_blacklist_default,
+ .fifo_size = 458752,
+ .small_fifo_size = true,
+ .dle_scc_rsvd_size = 98304,
+diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+index dbe77abb2c488..5e2592cf1a9fa 100644
+--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
++++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+@@ -2936,6 +2936,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
+ .try_ce_fw = false,
+ .bbmcu_nr = 0,
+ .needed_fw_elms = 0,
++ .fw_blacklist = &rtw89_fw_blacklist_default,
+ .fifo_size = 458752,
+ .small_fifo_size = false,
+ .dle_scc_rsvd_size = 0,
+diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
+index ef7747adbcc2b..64a41f24b2adb 100644
+--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c
++++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
+@@ -2632,6 +2632,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
+ .try_ce_fw = false,
+ .bbmcu_nr = 1,
+ .needed_fw_elms = RTW89_BE_GEN_DEF_NEEDED_FW_ELEMENTS,
++ .fw_blacklist = &rtw89_fw_blacklist_default,
+ .fifo_size = 589824,
+ .small_fifo_size = false,
+ .dle_scc_rsvd_size = 0,
+--
+2.39.5
+
--- /dev/null
+From 0f8ea39a1b5a1a8bc50560df87c71682528282bc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 14:43:05 +0800
+Subject: wifi: rtw89: fw: get sb_sel_ver via get_unaligned_le32()
+
+From: Ping-Ke Shih <pkshih@realtek.com>
+
+[ Upstream commit 2f9da853f4d848d23bade4c22931ea0f5a011674 ]
+
+The sb_sel_ver is selection version for secure boot recorded in firmware
+binary data, and its size is 4 and offset is 58 (not natural alignment).
+Use get_unaligned_le32() to get this value safely. Find this by reviewing.
+
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20250217064308.43559-3-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/fw.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
+index 9d26502a2885a..f0e87af68d8cb 100644
+--- a/drivers/net/wireless/realtek/rtw89/fw.c
++++ b/drivers/net/wireless/realtek/rtw89/fw.c
+@@ -285,7 +285,7 @@ static int __parse_formatted_mssc(struct rtw89_dev *rtwdev,
+ if (!sec->secure_boot)
+ goto out;
+
+- sb_sel_ver = le32_to_cpu(section_content->sb_sel_ver.v);
++ sb_sel_ver = get_unaligned_le32(§ion_content->sb_sel_ver.v);
+ if (sb_sel_ver && sb_sel_ver != sec->sb_sel_mgn)
+ goto ignore;
+
+--
+2.39.5
+
--- /dev/null
+From 28a308fb5776f08234564ef8276bd78f5be8bac0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 14:43:06 +0800
+Subject: wifi: rtw89: fw: propagate error code from rtw89_h2c_tx()
+
+From: Ping-Ke Shih <pkshih@realtek.com>
+
+[ Upstream commit 56e1acaa0f80620b8e2c3410db35b4b975782b0a ]
+
+The error code should be propagated to callers during downloading firmware
+header and body. Remove unnecessary assignment of -1.
+
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20250217064308.43559-4-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/fw.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
+index 620e076d1b597..9d26502a2885a 100644
+--- a/drivers/net/wireless/realtek/rtw89/fw.c
++++ b/drivers/net/wireless/realtek/rtw89/fw.c
+@@ -1234,7 +1234,6 @@ static int __rtw89_fw_download_hdr(struct rtw89_dev *rtwdev,
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+- ret = -1;
+ goto fail;
+ }
+
+@@ -1311,7 +1310,6 @@ static int __rtw89_fw_download_main(struct rtw89_dev *rtwdev,
+ ret = rtw89_h2c_tx(rtwdev, skb, true);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+- ret = -1;
+ goto fail;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From ba8d64cbf590ba3149c39062f4c474e98909de0b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Feb 2025 15:29:11 +0800
+Subject: wifi: rtw89: fw: validate multi-firmware header before getting its
+ size
+
+From: Ping-Ke Shih <pkshih@realtek.com>
+
+[ Upstream commit 2b8bdc5237014cc61784b3676cbaca5325959f3d ]
+
+To access firmware elements appended after multi-firmware, add its size
+as offset to get start address of firmware elements.
+
+ +-----+-------+------+---------+--------------+ --
+ | sig | fw_nr | rsvd | version | reserved | \
+ +---------------------------------------------+ |
+ fw 0 | cv | type | mp | rsvd | shift | size | rsvd | |
+ +---------------------------------------------+ |
+ fw 1 | cv | type | mp | rsvd | shift | size | rsvd | |
+ +---------------------------------------------+ |
+ fw N-1 | ... | |
+ +=============================================+ | mfw size
+ | fw 0 content | |
+ +=============================================+ |
+ | fw 1 content | |
+ +=============================================+ |
+ | ... | |
+ +=============================================+ |
+ | fw N -1 content | |
+ +=============================================+ --/
+ | fw element TLV X |
+ +=============================================+
+ | fw element TLV Y |
+ +=============================================+
+ | fw element TLV Z |
+ +=============================================+
+
+To avoid Coverity warning when getting mfw size, validate it header ahead.
+
+Addresses-Coverity-ID: 1544385 ("Untrusted array index read")
+
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20250203072911.47313-5-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/fw.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
+index 9346fe082040c..520dc0bc01956 100644
+--- a/drivers/net/wireless/realtek/rtw89/fw.c
++++ b/drivers/net/wireless/realtek/rtw89/fw.c
+@@ -563,12 +563,17 @@ static u32 rtw89_mfw_get_size(struct rtw89_dev *rtwdev)
+ (const struct rtw89_mfw_hdr *)firmware->data;
+ const struct rtw89_mfw_info *mfw_info;
+ u32 size;
++ int ret;
+
+ if (mfw_hdr->sig != RTW89_MFW_SIG) {
+ rtw89_warn(rtwdev, "not mfw format\n");
+ return 0;
+ }
+
++ ret = rtw89_mfw_validate_hdr(rtwdev, firmware, mfw_hdr);
++ if (ret)
++ return ret;
++
+ mfw_info = &mfw_hdr->info[mfw_hdr->fw_nr - 1];
+ size = le32_to_cpu(mfw_info->shift) + le32_to_cpu(mfw_info->size);
+
+--
+2.39.5
+
--- /dev/null
+From eda9fd28c0a4e8468aa88da2fd777943a114da57 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Feb 2025 15:29:10 +0800
+Subject: wifi: rtw89: fw: validate multi-firmware header before accessing
+
+From: Ping-Ke Shih <pkshih@realtek.com>
+
+[ Upstream commit 1f0efffd597893404aea5c3d4f1bdaa1c61d4434 ]
+
+A firmeware file contains multi-firmware with a header to represent
+contents. The mfw_hdr->fw_nr is to define number of firmware in file.
+
+ +-----+-------+------+---------+--------------+
+ | sig | fw_nr | rsvd | version | reserved |
+ +---------------------------------------------+ --
+ fw 0 | cv | type | mp | rsvd | shift | size | rsvd | \
+ +---------------------------------------------+ |
+ fw 1 | cv | type | mp | rsvd | shift | size | rsvd | | mfw_hdr->fw_nr
+ +---------------------------------------------+ |
+ fw N-1 | ... | /
+ +=============================================+ --
+ | fw 0 content |
+ | (pointed by fw0 shift/size) |
+ +=============================================+
+
+To avoid Coverity warning, validate header is in range of firmware size,
+and also validate the range of actual firmware content is in range.
+
+Addresses-Coverity-ID: 1494046 ("Untrusted loop bound")
+
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20250203072911.47313-4-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/fw.c | 35 +++++++++++++++++++++++++
+ 1 file changed, 35 insertions(+)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
+index 520dc0bc01956..e5c90050e7115 100644
+--- a/drivers/net/wireless/realtek/rtw89/fw.c
++++ b/drivers/net/wireless/realtek/rtw89/fw.c
+@@ -501,6 +501,30 @@ static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev,
+ }
+ }
+
++static int rtw89_mfw_validate_hdr(struct rtw89_dev *rtwdev,
++ const struct firmware *firmware,
++ const struct rtw89_mfw_hdr *mfw_hdr)
++{
++ const void *mfw = firmware->data;
++ u32 mfw_len = firmware->size;
++ u8 fw_nr = mfw_hdr->fw_nr;
++ const void *ptr;
++
++ if (fw_nr == 0) {
++ rtw89_err(rtwdev, "mfw header has no fw entry\n");
++ return -ENOENT;
++ }
++
++ ptr = &mfw_hdr->info[fw_nr];
++
++ if (ptr > mfw + mfw_len) {
++ rtw89_err(rtwdev, "mfw header out of address\n");
++ return -EFAULT;
++ }
++
++ return 0;
++}
++
+ static
+ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
+ struct rtw89_fw_suit *fw_suit, bool nowarn)
+@@ -511,6 +535,7 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
+ u32 mfw_len = firmware->size;
+ const struct rtw89_mfw_hdr *mfw_hdr = (const struct rtw89_mfw_hdr *)mfw;
+ const struct rtw89_mfw_info *mfw_info = NULL, *tmp;
++ int ret;
+ int i;
+
+ if (mfw_hdr->sig != RTW89_MFW_SIG) {
+@@ -523,6 +548,10 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
+ return 0;
+ }
+
++ ret = rtw89_mfw_validate_hdr(rtwdev, firmware, mfw_hdr);
++ if (ret)
++ return ret;
++
+ for (i = 0; i < mfw_hdr->fw_nr; i++) {
+ tmp = &mfw_hdr->info[i];
+ if (tmp->type != type)
+@@ -552,6 +581,12 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
+ found:
+ fw_suit->data = mfw + le32_to_cpu(mfw_info->shift);
+ fw_suit->size = le32_to_cpu(mfw_info->size);
++
++ if (fw_suit->data + fw_suit->size > mfw + mfw_len) {
++ rtw89_err(rtwdev, "fw_suit %d out of address\n", type);
++ return -EFAULT;
++ }
++
+ return 0;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 85b661ca54f2051fc431eaea0a8e1b8743b0569b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Mar 2025 10:11:44 +0800
+Subject: wifi: rtw89: set force HE TB mode when connecting to 11ax AP
+
+From: Dian-Syuan Yang <dian_syuan0116@realtek.com>
+
+[ Upstream commit a9b56f219a0fa550f92e65ac58443a7892380e09 ]
+
+Some of 11ax AP set the UL HE-SIG-A2 reserved subfield to all 0s, which
+will cause the 11be chip to recognize trigger frame as EHT. We propose
+a method to bypass the "UL HE-SIG-A2 reserved subfield" and always uses
+HE TB in response to the AP's trigger frame.
+
+Signed-off-by: Dian-Syuan Yang <dian_syuan0116@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20250306021144.12854-6-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/mac.c | 26 +++++++++++++++++++
+ drivers/net/wireless/realtek/rtw89/mac.h | 2 ++
+ drivers/net/wireless/realtek/rtw89/mac80211.c | 1 +
+ drivers/net/wireless/realtek/rtw89/reg.h | 4 +++
+ 4 files changed, 33 insertions(+)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
+index 4574aa62839b0..04e254bd6b17f 100644
+--- a/drivers/net/wireless/realtek/rtw89/mac.c
++++ b/drivers/net/wireless/realtek/rtw89/mac.c
+@@ -4745,6 +4745,32 @@ void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev,
+ rtw89_write32_set(rtwdev, reg, mac->narrow_bw_ru_dis.mask);
+ }
+
++void rtw89_mac_set_he_tb(struct rtw89_dev *rtwdev,
++ struct rtw89_vif_link *rtwvif_link)
++{
++ struct ieee80211_bss_conf *bss_conf;
++ bool set;
++ u32 reg;
++
++ if (rtwdev->chip->chip_gen != RTW89_CHIP_BE)
++ return;
++
++ rcu_read_lock();
++
++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
++ set = bss_conf->he_support && !bss_conf->eht_support;
++
++ rcu_read_unlock();
++
++ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_CLIENT_OM_CTRL,
++ rtwvif_link->mac_idx);
++
++ if (set)
++ rtw89_write32_set(rtwdev, reg, B_BE_TRIG_DIS_EHTTB);
++ else
++ rtw89_write32_clr(rtwdev, reg, B_BE_TRIG_DIS_EHTTB);
++}
++
+ void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
+ {
+ rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif_link);
+diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
+index 0c269961a5731..5ba1133b79d64 100644
+--- a/drivers/net/wireless/realtek/rtw89/mac.h
++++ b/drivers/net/wireless/realtek/rtw89/mac.h
+@@ -1160,6 +1160,8 @@ void rtw89_mac_port_cfg_rx_sync(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link, bool en);
+ void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link);
++void rtw89_mac_set_he_tb(struct rtw89_dev *rtwdev,
++ struct rtw89_vif_link *rtwvif_link);
+ void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link);
+ void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en);
+ int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif);
+diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
+index 8351a70d325d4..3a1a2b243adf0 100644
+--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
++++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
+@@ -669,6 +669,7 @@ static void __rtw89_ops_bss_link_assoc(struct rtw89_dev *rtwdev,
+ rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, rtwvif_link);
+ rtw89_mac_port_update(rtwdev, rtwvif_link);
+ rtw89_mac_set_he_obss_narrow_bw_ru(rtwdev, rtwvif_link);
++ rtw89_mac_set_he_tb(rtwdev, rtwvif_link);
+ }
+
+ static void __rtw89_ops_bss_assoc(struct rtw89_dev *rtwdev,
+diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
+index 69678eab23093..9fbcc7fee290f 100644
+--- a/drivers/net/wireless/realtek/rtw89/reg.h
++++ b/drivers/net/wireless/realtek/rtw89/reg.h
+@@ -7093,6 +7093,10 @@
+ #define B_BE_MACLBK_RDY_NUM_MASK GENMASK(7, 3)
+ #define B_BE_MACLBK_EN BIT(0)
+
++#define R_BE_CLIENT_OM_CTRL 0x11040
++#define R_BE_CLIENT_OM_CTRL_C1 0x15040
++#define B_BE_TRIG_DIS_EHTTB BIT(24)
++
+ #define R_BE_WMAC_NAV_CTL 0x11080
+ #define R_BE_WMAC_NAV_CTL_C1 0x15080
+ #define B_BE_WMAC_NAV_UPPER_EN BIT(26)
+--
+2.39.5
+
--- /dev/null
+From f3a1f548fbc2cab8c4d91ecfea486ba5fca42986 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jan 2025 14:07:35 -0500
+Subject: x86/boot: Disable stack protector for early boot code
+
+From: Brian Gerst <brgerst@gmail.com>
+
+[ Upstream commit a9a76b38aaf577887103e3ebb41d70e6aa5a4b19 ]
+
+On 64-bit, this will prevent crashes when the canary access is changed
+from %gs:40 to %gs:__stack_chk_guard(%rip). RIP-relative addresses from
+the identity-mapped early boot code will target the wrong address with
+zero-based percpu. KASLR could then shift that address to an unmapped
+page causing a crash on boot.
+
+This early boot code runs well before user-space is active and does not
+need stack protector enabled.
+
+Signed-off-by: Brian Gerst <brgerst@gmail.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Link: https://lore.kernel.org/r/20250123190747.745588-4-brgerst@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/Makefile | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
+index f7918980667a3..f42c0903ef86d 100644
+--- a/arch/x86/kernel/Makefile
++++ b/arch/x86/kernel/Makefile
+@@ -44,6 +44,8 @@ KCOV_INSTRUMENT_unwind_orc.o := n
+ KCOV_INSTRUMENT_unwind_frame.o := n
+ KCOV_INSTRUMENT_unwind_guess.o := n
+
++CFLAGS_head32.o := -fno-stack-protector
++CFLAGS_head64.o := -fno-stack-protector
+ CFLAGS_irq.o := -I $(src)/../include/asm/trace
+
+ obj-y += head_$(BITS).o
+--
+2.39.5
+
--- /dev/null
+From 487e0bbdeea67b065f371a2ad345896a6e3cc543 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 31 Oct 2024 04:06:17 -0700
+Subject: x86/bugs: Make spectre user default depend on MITIGATION_SPECTRE_V2
+
+From: Breno Leitao <leitao@debian.org>
+
+[ Upstream commit 98fdaeb296f51ef08e727a7cc72e5b5c864c4f4d ]
+
+Change the default value of spectre v2 in user mode to respect the
+CONFIG_MITIGATION_SPECTRE_V2 config option.
+
+Currently, user mode spectre v2 is set to auto
+(SPECTRE_V2_USER_CMD_AUTO) by default, even if
+CONFIG_MITIGATION_SPECTRE_V2 is disabled.
+
+Set the spectre_v2 value to auto (SPECTRE_V2_USER_CMD_AUTO) if the
+Spectre v2 config (CONFIG_MITIGATION_SPECTRE_V2) is enabled, otherwise
+set the value to none (SPECTRE_V2_USER_CMD_NONE).
+
+Important to say the command line argument "spectre_v2_user" overwrites
+the default value in both cases.
+
+When CONFIG_MITIGATION_SPECTRE_V2 is not set, users have the flexibility
+to opt-in for specific mitigations independently. In this scenario,
+setting spectre_v2= will not enable spectre_v2_user=, and command line
+options spectre_v2_user and spectre_v2 are independent when
+CONFIG_MITIGATION_SPECTRE_V2=n.
+
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Reviewed-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+Acked-by: Josh Poimboeuf <jpoimboe@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: David Kaplan <David.Kaplan@amd.com>
+Link: https://lore.kernel.org/r/20241031-x86_bugs_last_v2-v2-2-b7ff1dab840e@debian.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/admin-guide/kernel-parameters.txt | 2 ++
+ arch/x86/kernel/cpu/bugs.c | 10 +++++++---
+ 2 files changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
+index e691f75c97e7b..b5cb361485541 100644
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -6261,6 +6261,8 @@
+
+ Selecting 'on' will also enable the mitigation
+ against user space to user space task attacks.
++ Selecting specific mitigation does not force enable
++ user mitigations.
+
+ Selecting 'off' will disable both the kernel and
+ the user space protections.
+diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
+index c683abd640fde..0e9ab0b9a4942 100644
+--- a/arch/x86/kernel/cpu/bugs.c
++++ b/arch/x86/kernel/cpu/bugs.c
+@@ -1442,9 +1442,13 @@ static __ro_after_init enum spectre_v2_mitigation_cmd spectre_v2_cmd;
+ static enum spectre_v2_user_cmd __init
+ spectre_v2_parse_user_cmdline(void)
+ {
++ enum spectre_v2_user_cmd mode;
+ char arg[20];
+ int ret, i;
+
++ mode = IS_ENABLED(CONFIG_MITIGATION_SPECTRE_V2) ?
++ SPECTRE_V2_USER_CMD_AUTO : SPECTRE_V2_USER_CMD_NONE;
++
+ switch (spectre_v2_cmd) {
+ case SPECTRE_V2_CMD_NONE:
+ return SPECTRE_V2_USER_CMD_NONE;
+@@ -1457,7 +1461,7 @@ spectre_v2_parse_user_cmdline(void)
+ ret = cmdline_find_option(boot_command_line, "spectre_v2_user",
+ arg, sizeof(arg));
+ if (ret < 0)
+- return SPECTRE_V2_USER_CMD_AUTO;
++ return mode;
+
+ for (i = 0; i < ARRAY_SIZE(v2_user_options); i++) {
+ if (match_option(arg, ret, v2_user_options[i].option)) {
+@@ -1467,8 +1471,8 @@ spectre_v2_parse_user_cmdline(void)
+ }
+ }
+
+- pr_err("Unknown user space protection option (%s). Switching to AUTO select\n", arg);
+- return SPECTRE_V2_USER_CMD_AUTO;
++ pr_err("Unknown user space protection option (%s). Switching to default\n", arg);
++ return mode;
+ }
+
+ static inline bool spectre_v2_in_ibrs_mode(enum spectre_v2_mitigation mode)
+--
+2.39.5
+
--- /dev/null
+From 6bbf7ec9011b48f5d232a02fcb8acd541ff1ce90 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Jan 2025 12:05:00 +0000
+Subject: x86/build: Fix broken copy command in genimage.sh when making
+ isoimage
+
+From: Nir Lichtman <nir@lichtman.org>
+
+[ Upstream commit e451630226bd09dc730eedb4e32cab1cc7155ae8 ]
+
+Problem: Currently when running the "make isoimage" command there is an
+error related to wrong parameters passed to the cp command:
+
+ "cp: missing destination file operand after 'arch/x86/boot/isoimage/'"
+
+This is caused because FDINITRDS is an empty array.
+
+Solution: Check if FDINITRDS is empty before executing the "cp" command,
+similar to how it is done in the case of hdimage.
+
+Signed-off-by: Nir Lichtman <nir@lichtman.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Cc: "H. Peter Anvin" <hpa@zytor.com>
+Cc: Ard Biesheuvel <ardb@kernel.org>
+Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
+Cc: Michal Marek <michal.lkml@markovi.net>
+Link: https://lore.kernel.org/r/20250110120500.GA923218@lichtman.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/boot/genimage.sh | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/arch/x86/boot/genimage.sh b/arch/x86/boot/genimage.sh
+index c9299aeb7333e..3882ead513f74 100644
+--- a/arch/x86/boot/genimage.sh
++++ b/arch/x86/boot/genimage.sh
+@@ -22,6 +22,7 @@
+ # This script requires:
+ # bash
+ # syslinux
++# genisoimage
+ # mtools (for fdimage* and hdimage)
+ # edk2/OVMF (for hdimage)
+ #
+@@ -251,7 +252,9 @@ geniso() {
+ cp "$isolinux" "$ldlinux" "$tmp_dir"
+ cp "$FBZIMAGE" "$tmp_dir"/linux
+ echo default linux "$KCMDLINE" > "$tmp_dir"/isolinux.cfg
+- cp "${FDINITRDS[@]}" "$tmp_dir"/
++ if [ ${#FDINITRDS[@]} -gt 0 ]; then
++ cp "${FDINITRDS[@]}" "$tmp_dir"/
++ fi
+ genisoimage -J -r -appid 'LINUX_BOOT' -input-charset=utf-8 \
+ -quiet -o "$FIMAGE" -b isolinux.bin \
+ -c boot.cat -no-emul-boot -boot-load-size 4 \
+--
+2.39.5
+
--- /dev/null
+From 8f6ba1b65ddb93088b3239769134a597e220b480 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Apr 2025 00:57:27 -0700
+Subject: x86/fred: Fix system hang during S4 resume with FRED enabled
+
+From: Xin Li (Intel) <xin@zytor.com>
+
+[ Upstream commit e5f1e8af9c9e151ecd665f6d2e36fb25fec3b110 ]
+
+Upon a wakeup from S4, the restore kernel starts and initializes the
+FRED MSRs as needed from its perspective. It then loads a hibernation
+image, including the image kernel, and attempts to load image pages
+directly into their original page frames used before hibernation unless
+those frames are currently in use. Once all pages are moved to their
+original locations, it jumps to a "trampoline" page in the image kernel.
+
+At this point, the image kernel takes control, but the FRED MSRs still
+contain values set by the restore kernel, which may differ from those
+set by the image kernel before hibernation. Therefore, the image kernel
+must ensure the FRED MSRs have the same values as before hibernation.
+Since these values depend only on the location of the kernel text and
+data, they can be recomputed from scratch.
+
+Reported-by: Xi Pardee <xi.pardee@intel.com>
+Reported-by: Todd Brandt <todd.e.brandt@intel.com>
+Tested-by: Todd Brandt <todd.e.brandt@intel.com>
+Suggested-by: H. Peter Anvin (Intel) <hpa@zytor.com>
+Signed-off-by: Xin Li (Intel) <xin@zytor.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
+Cc: Andy Lutomirski <luto@kernel.org>
+Cc: Brian Gerst <brgerst@gmail.com>
+Cc: Juergen Gross <jgross@suse.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Link: https://lore.kernel.org/r/20250401075728.3626147-1-xin@zytor.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/power/cpu.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
+index 63230ff8cf4f0..08e76a5ca1553 100644
+--- a/arch/x86/power/cpu.c
++++ b/arch/x86/power/cpu.c
+@@ -27,6 +27,7 @@
+ #include <asm/mmu_context.h>
+ #include <asm/cpu_device_id.h>
+ #include <asm/microcode.h>
++#include <asm/fred.h>
+
+ #ifdef CONFIG_X86_32
+ __visible unsigned long saved_context_ebx;
+@@ -231,6 +232,19 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
+ */
+ #ifdef CONFIG_X86_64
+ wrmsrl(MSR_GS_BASE, ctxt->kernelmode_gs_base);
++
++ /*
++ * Reinitialize FRED to ensure the FRED MSRs contain the same values
++ * as before hibernation.
++ *
++ * Note, the setup of FRED RSPs requires access to percpu data
++ * structures. Therefore, FRED reinitialization can only occur after
++ * the percpu access pointer (i.e., MSR_GS_BASE) is restored.
++ */
++ if (ctxt->cr4 & X86_CR4_FRED) {
++ cpu_init_fred_exceptions();
++ cpu_init_fred_rsps();
++ }
+ #else
+ loadsegment(fs, __KERNEL_PERCPU);
+ #endif
+--
+2.39.5
+
--- /dev/null
+From 771a8e570e4b02aaba0b4df0ac7e6e2ceec01630 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Mar 2025 11:42:56 +0100
+Subject: x86/headers: Replace __ASSEMBLY__ with __ASSEMBLER__ in UAPI headers
+
+From: Thomas Huth <thuth@redhat.com>
+
+[ Upstream commit 8a141be3233af7d4f7014ebc44d5452d46b2b1be ]
+
+__ASSEMBLY__ is only defined by the Makefile of the kernel, so
+this is not really useful for UAPI headers (unless the userspace
+Makefile defines it, too). Let's switch to __ASSEMBLER__ which
+gets set automatically by the compiler when compiling assembly
+code.
+
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Cc: "H. Peter Anvin" <hpa@zytor.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: Brian Gerst <brgerst@gmail.com>
+Link: https://lore.kernel.org/r/20250310104256.123527-1-thuth@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/uapi/asm/bootparam.h | 4 ++--
+ arch/x86/include/uapi/asm/e820.h | 4 ++--
+ arch/x86/include/uapi/asm/ldt.h | 4 ++--
+ arch/x86/include/uapi/asm/msr.h | 4 ++--
+ arch/x86/include/uapi/asm/ptrace-abi.h | 6 +++---
+ arch/x86/include/uapi/asm/ptrace.h | 4 ++--
+ arch/x86/include/uapi/asm/setup_data.h | 4 ++--
+ arch/x86/include/uapi/asm/signal.h | 8 ++++----
+ 8 files changed, 19 insertions(+), 19 deletions(-)
+
+diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
+index 9b82eebd7add5..dafbf581c515d 100644
+--- a/arch/x86/include/uapi/asm/bootparam.h
++++ b/arch/x86/include/uapi/asm/bootparam.h
+@@ -26,7 +26,7 @@
+ #define XLF_5LEVEL_ENABLED (1<<6)
+ #define XLF_MEM_ENCRYPTION (1<<7)
+
+-#ifndef __ASSEMBLY__
++#ifndef __ASSEMBLER__
+
+ #include <linux/types.h>
+ #include <linux/screen_info.h>
+@@ -210,6 +210,6 @@ enum x86_hardware_subarch {
+ X86_NR_SUBARCHS,
+ };
+
+-#endif /* __ASSEMBLY__ */
++#endif /* __ASSEMBLER__ */
+
+ #endif /* _ASM_X86_BOOTPARAM_H */
+diff --git a/arch/x86/include/uapi/asm/e820.h b/arch/x86/include/uapi/asm/e820.h
+index 2f491efe3a126..55bc668671560 100644
+--- a/arch/x86/include/uapi/asm/e820.h
++++ b/arch/x86/include/uapi/asm/e820.h
+@@ -54,7 +54,7 @@
+ */
+ #define E820_RESERVED_KERN 128
+
+-#ifndef __ASSEMBLY__
++#ifndef __ASSEMBLER__
+ #include <linux/types.h>
+ struct e820entry {
+ __u64 addr; /* start of memory segment */
+@@ -76,7 +76,7 @@ struct e820map {
+ #define BIOS_ROM_BASE 0xffe00000
+ #define BIOS_ROM_END 0xffffffff
+
+-#endif /* __ASSEMBLY__ */
++#endif /* __ASSEMBLER__ */
+
+
+ #endif /* _UAPI_ASM_X86_E820_H */
+diff --git a/arch/x86/include/uapi/asm/ldt.h b/arch/x86/include/uapi/asm/ldt.h
+index d62ac5db093b4..a82c039d8e6a7 100644
+--- a/arch/x86/include/uapi/asm/ldt.h
++++ b/arch/x86/include/uapi/asm/ldt.h
+@@ -12,7 +12,7 @@
+ /* The size of each LDT entry. */
+ #define LDT_ENTRY_SIZE 8
+
+-#ifndef __ASSEMBLY__
++#ifndef __ASSEMBLER__
+ /*
+ * Note on 64bit base and limit is ignored and you cannot set DS/ES/CS
+ * not to the default values if you still want to do syscalls. This
+@@ -44,5 +44,5 @@ struct user_desc {
+ #define MODIFY_LDT_CONTENTS_STACK 1
+ #define MODIFY_LDT_CONTENTS_CODE 2
+
+-#endif /* !__ASSEMBLY__ */
++#endif /* !__ASSEMBLER__ */
+ #endif /* _ASM_X86_LDT_H */
+diff --git a/arch/x86/include/uapi/asm/msr.h b/arch/x86/include/uapi/asm/msr.h
+index e7516b402a00f..4b8917ca28fe7 100644
+--- a/arch/x86/include/uapi/asm/msr.h
++++ b/arch/x86/include/uapi/asm/msr.h
+@@ -2,7 +2,7 @@
+ #ifndef _UAPI_ASM_X86_MSR_H
+ #define _UAPI_ASM_X86_MSR_H
+
+-#ifndef __ASSEMBLY__
++#ifndef __ASSEMBLER__
+
+ #include <linux/types.h>
+ #include <linux/ioctl.h>
+@@ -10,5 +10,5 @@
+ #define X86_IOC_RDMSR_REGS _IOWR('c', 0xA0, __u32[8])
+ #define X86_IOC_WRMSR_REGS _IOWR('c', 0xA1, __u32[8])
+
+-#endif /* __ASSEMBLY__ */
++#endif /* __ASSEMBLER__ */
+ #endif /* _UAPI_ASM_X86_MSR_H */
+diff --git a/arch/x86/include/uapi/asm/ptrace-abi.h b/arch/x86/include/uapi/asm/ptrace-abi.h
+index 16074b9c93bb5..5823584dea132 100644
+--- a/arch/x86/include/uapi/asm/ptrace-abi.h
++++ b/arch/x86/include/uapi/asm/ptrace-abi.h
+@@ -25,7 +25,7 @@
+
+ #else /* __i386__ */
+
+-#if defined(__ASSEMBLY__) || defined(__FRAME_OFFSETS)
++#if defined(__ASSEMBLER__) || defined(__FRAME_OFFSETS)
+ /*
+ * C ABI says these regs are callee-preserved. They aren't saved on kernel entry
+ * unless syscall needs a complete, fully filled "struct pt_regs".
+@@ -57,7 +57,7 @@
+ #define EFLAGS 144
+ #define RSP 152
+ #define SS 160
+-#endif /* __ASSEMBLY__ */
++#endif /* __ASSEMBLER__ */
+
+ /* top of stack page */
+ #define FRAME_SIZE 168
+@@ -87,7 +87,7 @@
+
+ #define PTRACE_SINGLEBLOCK 33 /* resume execution until next branch */
+
+-#ifndef __ASSEMBLY__
++#ifndef __ASSEMBLER__
+ #include <linux/types.h>
+ #endif
+
+diff --git a/arch/x86/include/uapi/asm/ptrace.h b/arch/x86/include/uapi/asm/ptrace.h
+index 85165c0edafc8..e0b5b4f6226b1 100644
+--- a/arch/x86/include/uapi/asm/ptrace.h
++++ b/arch/x86/include/uapi/asm/ptrace.h
+@@ -7,7 +7,7 @@
+ #include <asm/processor-flags.h>
+
+
+-#ifndef __ASSEMBLY__
++#ifndef __ASSEMBLER__
+
+ #ifdef __i386__
+ /* this struct defines the way the registers are stored on the
+@@ -81,6 +81,6 @@ struct pt_regs {
+
+
+
+-#endif /* !__ASSEMBLY__ */
++#endif /* !__ASSEMBLER__ */
+
+ #endif /* _UAPI_ASM_X86_PTRACE_H */
+diff --git a/arch/x86/include/uapi/asm/setup_data.h b/arch/x86/include/uapi/asm/setup_data.h
+index b111b0c185449..50c45ead4e7c9 100644
+--- a/arch/x86/include/uapi/asm/setup_data.h
++++ b/arch/x86/include/uapi/asm/setup_data.h
+@@ -18,7 +18,7 @@
+ #define SETUP_INDIRECT (1<<31)
+ #define SETUP_TYPE_MAX (SETUP_ENUM_MAX | SETUP_INDIRECT)
+
+-#ifndef __ASSEMBLY__
++#ifndef __ASSEMBLER__
+
+ #include <linux/types.h>
+
+@@ -78,6 +78,6 @@ struct ima_setup_data {
+ __u64 size;
+ } __attribute__((packed));
+
+-#endif /* __ASSEMBLY__ */
++#endif /* __ASSEMBLER__ */
+
+ #endif /* _UAPI_ASM_X86_SETUP_DATA_H */
+diff --git a/arch/x86/include/uapi/asm/signal.h b/arch/x86/include/uapi/asm/signal.h
+index f777346450ec3..1067efabf18b5 100644
+--- a/arch/x86/include/uapi/asm/signal.h
++++ b/arch/x86/include/uapi/asm/signal.h
+@@ -2,7 +2,7 @@
+ #ifndef _UAPI_ASM_X86_SIGNAL_H
+ #define _UAPI_ASM_X86_SIGNAL_H
+
+-#ifndef __ASSEMBLY__
++#ifndef __ASSEMBLER__
+ #include <linux/types.h>
+ #include <linux/compiler.h>
+
+@@ -16,7 +16,7 @@ struct siginfo;
+ typedef unsigned long sigset_t;
+
+ #endif /* __KERNEL__ */
+-#endif /* __ASSEMBLY__ */
++#endif /* __ASSEMBLER__ */
+
+
+ #define SIGHUP 1
+@@ -68,7 +68,7 @@ typedef unsigned long sigset_t;
+
+ #include <asm-generic/signal-defs.h>
+
+-#ifndef __ASSEMBLY__
++#ifndef __ASSEMBLER__
+
+
+ # ifndef __KERNEL__
+@@ -106,6 +106,6 @@ typedef struct sigaltstack {
+ __kernel_size_t ss_size;
+ } stack_t;
+
+-#endif /* __ASSEMBLY__ */
++#endif /* __ASSEMBLER__ */
+
+ #endif /* _UAPI_ASM_X86_SIGNAL_H */
+--
+2.39.5
+
--- /dev/null
+From 8812d91b07c8ff7a1ab61015c54621ac22dcf9d0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 12:45:47 +0100
+Subject: x86/ibt: Handle FineIBT in handle_cfi_failure()
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit 882b86fd4e0d49bf91148dbadcdbece19ded40e6 ]
+
+Sami reminded me that FineIBT failure does not hook into the regular
+CFI failure case, and as such CFI_PERMISSIVE does not work.
+
+Reported-by: Sami Tolvanen <samitolvanen@google.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Sami Tolvanen <samitolvanen@google.com>
+Link: https://lkml.kernel.org/r/20250214092619.GB21726@noisy.programming.kicks-ass.net
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/cfi.h | 11 +++++++++++
+ arch/x86/kernel/alternative.c | 30 ++++++++++++++++++++++++++++++
+ arch/x86/kernel/cfi.c | 22 ++++++++++++++++++----
+ 3 files changed, 59 insertions(+), 4 deletions(-)
+
+diff --git a/arch/x86/include/asm/cfi.h b/arch/x86/include/asm/cfi.h
+index 31d19c815f992..7dd5ab239c87b 100644
+--- a/arch/x86/include/asm/cfi.h
++++ b/arch/x86/include/asm/cfi.h
+@@ -126,6 +126,17 @@ static inline int cfi_get_offset(void)
+
+ extern u32 cfi_get_func_hash(void *func);
+
++#ifdef CONFIG_FINEIBT
++extern bool decode_fineibt_insn(struct pt_regs *regs, unsigned long *target, u32 *type);
++#else
++static inline bool
++decode_fineibt_insn(struct pt_regs *regs, unsigned long *target, u32 *type)
++{
++ return false;
++}
++
++#endif
++
+ #else
+ static inline enum bug_trap_type handle_cfi_failure(struct pt_regs *regs)
+ {
+diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
+index 66e77bd7d5116..6ab96bc764cfa 100644
+--- a/arch/x86/kernel/alternative.c
++++ b/arch/x86/kernel/alternative.c
+@@ -1254,6 +1254,7 @@ asm( ".pushsection .rodata \n"
+ " endbr64 \n"
+ " subl $0x12345678, %r10d \n"
+ " je fineibt_preamble_end \n"
++ "fineibt_preamble_ud2: \n"
+ " ud2 \n"
+ " nop \n"
+ "fineibt_preamble_end: \n"
+@@ -1261,9 +1262,11 @@ asm( ".pushsection .rodata \n"
+ );
+
+ extern u8 fineibt_preamble_start[];
++extern u8 fineibt_preamble_ud2[];
+ extern u8 fineibt_preamble_end[];
+
+ #define fineibt_preamble_size (fineibt_preamble_end - fineibt_preamble_start)
++#define fineibt_preamble_ud2 (fineibt_preamble_ud2 - fineibt_preamble_start)
+ #define fineibt_preamble_hash 7
+
+ asm( ".pushsection .rodata \n"
+@@ -1568,6 +1571,33 @@ static void poison_cfi(void *addr)
+ }
+ }
+
++/*
++ * regs->ip points to a UD2 instruction, return true and fill out target and
++ * type when this UD2 is from a FineIBT preamble.
++ *
++ * We check the preamble by checking for the ENDBR instruction relative to the
++ * UD2 instruction.
++ */
++bool decode_fineibt_insn(struct pt_regs *regs, unsigned long *target, u32 *type)
++{
++ unsigned long addr = regs->ip - fineibt_preamble_ud2;
++ u32 endbr, hash;
++
++ __get_kernel_nofault(&endbr, addr, u32, Efault);
++ if (endbr != gen_endbr())
++ return false;
++
++ *target = addr + fineibt_preamble_size;
++
++ __get_kernel_nofault(&hash, addr + fineibt_preamble_hash, u32, Efault);
++ *type = (u32)regs->r10 + hash;
++
++ return true;
++
++Efault:
++ return false;
++}
++
+ #else
+
+ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
+diff --git a/arch/x86/kernel/cfi.c b/arch/x86/kernel/cfi.c
+index e6bf78fac1462..f6905bef0af84 100644
+--- a/arch/x86/kernel/cfi.c
++++ b/arch/x86/kernel/cfi.c
+@@ -70,11 +70,25 @@ enum bug_trap_type handle_cfi_failure(struct pt_regs *regs)
+ unsigned long target;
+ u32 type;
+
+- if (!is_cfi_trap(regs->ip))
+- return BUG_TRAP_TYPE_NONE;
++ switch (cfi_mode) {
++ case CFI_KCFI:
++ if (!is_cfi_trap(regs->ip))
++ return BUG_TRAP_TYPE_NONE;
++
++ if (!decode_cfi_insn(regs, &target, &type))
++ return report_cfi_failure_noaddr(regs, regs->ip);
++
++ break;
+
+- if (!decode_cfi_insn(regs, &target, &type))
+- return report_cfi_failure_noaddr(regs, regs->ip);
++ case CFI_FINEIBT:
++ if (!decode_fineibt_insn(regs, &target, &type))
++ return BUG_TRAP_TYPE_NONE;
++
++ break;
++
++ default:
++ return BUG_TRAP_TYPE_NONE;
++ }
+
+ return report_cfi_failure(regs, regs->ip, &target, type);
+ }
+--
+2.39.5
+
--- /dev/null
+From 1cc42ab326bc21dd8eb3cf9852cda10c55363242 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Feb 2025 10:42:34 +1100
+Subject: x86/kaslr: Reduce KASLR entropy on most x86 systems
+
+From: Balbir Singh <balbirs@nvidia.com>
+
+[ Upstream commit 7ffb791423c7c518269a9aad35039ef824a40adb ]
+
+When CONFIG_PCI_P2PDMA=y (which is basically enabled on all
+large x86 distros), it maps the PFN's via a ZONE_DEVICE
+mapping using devm_memremap_pages(). The mapped virtual
+address range corresponds to the pci_resource_start()
+of the BAR address and size corresponding to the BAR length.
+
+When KASLR is enabled, the direct map range of the kernel is
+reduced to the size of physical memory plus additional padding.
+If the BAR address is beyond this limit, PCI peer to peer DMA
+mappings fail.
+
+Fix this by not shrinking the size of the direct map when
+CONFIG_PCI_P2PDMA=y.
+
+This reduces the total available entropy, but it's better than
+the current work around of having to disable KASLR completely.
+
+[ mingo: Clarified the changelog to point out the broad impact ... ]
+
+Signed-off-by: Balbir Singh <balbirs@nvidia.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Reviewed-by: Kees Cook <kees@kernel.org>
+Acked-by: Bjorn Helgaas <bhelgaas@google.com> # drivers/pci/Kconfig
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Andy Lutomirski <luto@kernel.org>
+Link: https://lore.kernel.org/lkml/20250206023201.1481957-1-balbirs@nvidia.com/
+Link: https://lore.kernel.org/r/20250206234234.1912585-1-balbirs@nvidia.com
+--
+ arch/x86/mm/kaslr.c | 10 ++++++++--
+ drivers/pci/Kconfig | 6 ++++++
+ 2 files changed, 14 insertions(+), 2 deletions(-)
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/mm/kaslr.c | 10 ++++++++--
+ drivers/pci/Kconfig | 6 ++++++
+ 2 files changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/mm/kaslr.c b/arch/x86/mm/kaslr.c
+index 230f1dee4f095..e0b0ec0f82457 100644
+--- a/arch/x86/mm/kaslr.c
++++ b/arch/x86/mm/kaslr.c
+@@ -109,8 +109,14 @@ void __init kernel_randomize_memory(void)
+ memory_tb = DIV_ROUND_UP(max_pfn << PAGE_SHIFT, 1UL << TB_SHIFT) +
+ CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING;
+
+- /* Adapt physical memory region size based on available memory */
+- if (memory_tb < kaslr_regions[0].size_tb)
++ /*
++ * Adapt physical memory region size based on available memory,
++ * except when CONFIG_PCI_P2PDMA is enabled. P2PDMA exposes the
++ * device BAR space assuming the direct map space is large enough
++ * for creating a ZONE_DEVICE mapping in the direct map corresponding
++ * to the physical BAR address.
++ */
++ if (!IS_ENABLED(CONFIG_PCI_P2PDMA) && (memory_tb < kaslr_regions[0].size_tb))
+ kaslr_regions[0].size_tb = memory_tb;
+
+ /*
+diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
+index 0d94e4a967d81..7cef00d9d7ab6 100644
+--- a/drivers/pci/Kconfig
++++ b/drivers/pci/Kconfig
+@@ -194,6 +194,12 @@ config PCI_P2PDMA
+ P2P DMA transactions must be between devices behind the same root
+ port.
+
++ Enabling this option will reduce the entropy of x86 KASLR memory
++ regions. For example - on a 46 bit system, the entropy goes down
++ from 16 bits to 15 bits. The actual reduction in entropy depends
++ on the physical address bits, on processor features, kernel config
++ (5 level page table) and physical memory present on the system.
++
+ If unsure, say N.
+
+ config PCI_LABEL
+--
+2.39.5
+
--- /dev/null
+From 811a1f29f30a4525ac8021ee7c6bf8f991c08c45 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 10 Apr 2025 11:54:20 +0000
+Subject: x86/Kconfig: make CFI_AUTO_DEFAULT depend on !RUST or Rust >= 1.88
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Paweł Anikiel <panikiel@google.com>
+
+[ Upstream commit 5595c31c370957aabe739ac3996aedba8267603f ]
+
+Calling core::fmt::write() from rust code while FineIBT is enabled
+results in a kernel panic:
+
+[ 4614.199779] kernel BUG at arch/x86/kernel/cet.c:132!
+[ 4614.205343] Oops: invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
+[ 4614.211781] CPU: 2 UID: 0 PID: 6057 Comm: dmabuf_dump Tainted: G U O 6.12.17-android16-0-g6ab38c534a43 #1 9da040f27673ec3945e23b998a0f8bd64c846599
+[ 4614.227832] Tainted: [U]=USER, [O]=OOT_MODULE
+[ 4614.241247] RIP: 0010:do_kernel_cp_fault+0xea/0xf0
+...
+[ 4614.398144] RIP: 0010:_RNvXs5_NtNtNtCs3o2tGsuHyou_4core3fmt3num3impyNtB9_7Display3fmt+0x0/0x20
+[ 4614.407792] Code: 48 f7 df 48 0f 48 f9 48 89 f2 89 c6 5d e9 18 fd ff ff 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 41 81 ea 14 61 af 2c 74 03 0f 0b 90 <66> 0f 1f 00 55 48 89 e5 48 89 f2 48 8b 3f be 01 00 00 00 5d e9 e7
+[ 4614.428775] RSP: 0018:ffffb95acfa4ba68 EFLAGS: 00010246
+[ 4614.434609] RAX: 0000000000000000 RBX: 0000000000000010 RCX: 0000000000000000
+[ 4614.442587] RDX: 0000000000000007 RSI: ffffb95acfa4ba70 RDI: ffffb95acfa4bc88
+[ 4614.450557] RBP: ffffb95acfa4bae0 R08: ffff0a00ffffff05 R09: 0000000000000070
+[ 4614.458527] R10: 0000000000000000 R11: ffffffffab67eaf0 R12: ffffb95acfa4bcc8
+[ 4614.466493] R13: ffffffffac5d50f0 R14: 0000000000000000 R15: 0000000000000000
+[ 4614.474473] ? __cfi__RNvXs5_NtNtNtCs3o2tGsuHyou_4core3fmt3num3impyNtB9_7Display3fmt+0x10/0x10
+[ 4614.484118] ? _RNvNtCs3o2tGsuHyou_4core3fmt5write+0x1d2/0x250
+
+This happens because core::fmt::write() calls
+core::fmt::rt::Argument::fmt(), which currently has CFI disabled:
+
+library/core/src/fmt/rt.rs:
+171 // FIXME: Transmuting formatter in new and indirectly branching to/calling
+172 // it here is an explicit CFI violation.
+173 #[allow(inline_no_sanitize)]
+174 #[no_sanitize(cfi, kcfi)]
+175 #[inline]
+176 pub(super) unsafe fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+
+This causes a Control Protection exception, because FineIBT has sealed
+off the original function's endbr64.
+
+This makes rust currently incompatible with FineIBT. Add a Kconfig
+dependency that prevents FineIBT from getting turned on by default
+if rust is enabled.
+
+[ Rust 1.88.0 (scheduled for 2025-06-26) should have this fixed [1],
+ and thus we relaxed the condition with Rust >= 1.88.
+
+ When `objtool` lands checking for this with e.g. [2], the plan is
+ to ideally run that in upstream Rust's CI to prevent regressions
+ early [3], since we do not control `core`'s source code.
+
+ Alice tested the Rust PR backported to an older compiler.
+
+ Peter would like that Rust provides a stable `core` which can be
+ pulled into the kernel: "Relying on that much out of tree code is
+ 'unfortunate'".
+
+ - Miguel ]
+
+Signed-off-by: Paweł Anikiel <panikiel@google.com>
+Reviewed-by: Alice Ryhl <aliceryhl@google.com>
+Acked-by: Peter Zijlstra <peterz@infradead.org>
+Link: https://github.com/rust-lang/rust/pull/139632 [1]
+Link: https://lore.kernel.org/rust-for-linux/20250410154556.GB9003@noisy.programming.kicks-ass.net/ [2]
+Link: https://github.com/rust-lang/rust/pull/139632#issuecomment-2801950873 [3]
+Link: https://lore.kernel.org/r/20250410115420.366349-1-panikiel@google.com
+Link: https://lore.kernel.org/r/att0-CANiq72kjDM0cKALVy4POEzhfdT4nO7tqz0Pm7xM+3=_0+L1t=A@mail.gmail.com
+[ Reduced splat. - Miguel ]
+Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index 7b3622ba4c3c8..15425c9bdc2bc 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -2420,6 +2420,7 @@ config STRICT_SIGALTSTACK_SIZE
+ config CFI_AUTO_DEFAULT
+ bool "Attempt to use FineIBT by default at boot time"
+ depends on FINEIBT
++ depends on !RUST || RUSTC_VERSION >= 108800
+ default y
+ help
+ Attempt to use FineIBT by default at boot time. If enabled,
+--
+2.39.5
+
--- /dev/null
+From b4f78e42808b7c786170fbd01e1839d4a2910e04 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Feb 2025 16:07:46 +0100
+Subject: x86/locking: Use ALT_OUTPUT_SP() for
+ percpu_{,try_}cmpxchg{64,128}_op()
+
+From: Uros Bizjak <ubizjak@gmail.com>
+
+[ Upstream commit 4087e16b033140cf2ce509ec23503bddec818a16 ]
+
+percpu_{,try_}cmpxchg{64,128}() macros use CALL instruction inside
+asm statement in one of their alternatives. Use ALT_OUTPUT_SP()
+macro to add required dependence on %esp register.
+
+ALT_OUTPUT_SP() implements the above dependence by adding
+ASM_CALL_CONSTRAINT to its arguments. This constraint should be used
+for any inline asm which has a CALL instruction, otherwise the
+compiler may schedule the asm before the frame pointer gets set up
+by the containing function, causing objtool to print a "call without
+frame pointer save/setup" warning.
+
+Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Link: https://lore.kernel.org/r/20250214150929.5780-1-ubizjak@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/percpu.h | 28 ++++++++++++++--------------
+ 1 file changed, 14 insertions(+), 14 deletions(-)
+
+diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
+index c55a79d5feaeb..2d9c250b3c8d8 100644
+--- a/arch/x86/include/asm/percpu.h
++++ b/arch/x86/include/asm/percpu.h
+@@ -349,9 +349,9 @@ do { \
+ \
+ asm qual (ALTERNATIVE("call this_cpu_cmpxchg8b_emu", \
+ "cmpxchg8b " __percpu_arg([var]), X86_FEATURE_CX8) \
+- : [var] "+m" (__my_cpu_var(_var)), \
+- "+a" (old__.low), \
+- "+d" (old__.high) \
++ : ALT_OUTPUT_SP([var] "+m" (__my_cpu_var(_var)), \
++ "+a" (old__.low), \
++ "+d" (old__.high)) \
+ : "b" (new__.low), \
+ "c" (new__.high), \
+ "S" (&(_var)) \
+@@ -380,10 +380,10 @@ do { \
+ asm qual (ALTERNATIVE("call this_cpu_cmpxchg8b_emu", \
+ "cmpxchg8b " __percpu_arg([var]), X86_FEATURE_CX8) \
+ CC_SET(z) \
+- : CC_OUT(z) (success), \
+- [var] "+m" (__my_cpu_var(_var)), \
+- "+a" (old__.low), \
+- "+d" (old__.high) \
++ : ALT_OUTPUT_SP(CC_OUT(z) (success), \
++ [var] "+m" (__my_cpu_var(_var)), \
++ "+a" (old__.low), \
++ "+d" (old__.high)) \
+ : "b" (new__.low), \
+ "c" (new__.high), \
+ "S" (&(_var)) \
+@@ -420,9 +420,9 @@ do { \
+ \
+ asm qual (ALTERNATIVE("call this_cpu_cmpxchg16b_emu", \
+ "cmpxchg16b " __percpu_arg([var]), X86_FEATURE_CX16) \
+- : [var] "+m" (__my_cpu_var(_var)), \
+- "+a" (old__.low), \
+- "+d" (old__.high) \
++ : ALT_OUTPUT_SP([var] "+m" (__my_cpu_var(_var)), \
++ "+a" (old__.low), \
++ "+d" (old__.high)) \
+ : "b" (new__.low), \
+ "c" (new__.high), \
+ "S" (&(_var)) \
+@@ -451,10 +451,10 @@ do { \
+ asm qual (ALTERNATIVE("call this_cpu_cmpxchg16b_emu", \
+ "cmpxchg16b " __percpu_arg([var]), X86_FEATURE_CX16) \
+ CC_SET(z) \
+- : CC_OUT(z) (success), \
+- [var] "+m" (__my_cpu_var(_var)), \
+- "+a" (old__.low), \
+- "+d" (old__.high) \
++ : ALT_OUTPUT_SP(CC_OUT(z) (success), \
++ [var] "+m" (__my_cpu_var(_var)), \
++ "+a" (old__.low), \
++ "+d" (old__.high)) \
+ : "b" (new__.low), \
+ "c" (new__.high), \
+ "S" (&(_var)) \
+--
+2.39.5
+
--- /dev/null
+From 543bab893a1f6fe4ffe3eef38e9046b572918e75 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Feb 2025 18:41:21 +0000
+Subject: x86/microcode: Update the Intel processor flag scan check
+
+From: Sohil Mehta <sohil.mehta@intel.com>
+
+[ Upstream commit 7e6b0a2e4152f4046af95eeb46f8b4f9b2a7398d ]
+
+The Family model check to read the processor flag MSR is misleading and
+potentially incorrect. It doesn't consider Family while comparing the
+model number. The original check did have a Family number but it got
+lost/moved during refactoring.
+
+intel_collect_cpu_info() is called through multiple paths such as early
+initialization, CPU hotplug as well as IFS image load. Some of these
+flows would be error prone due to the ambiguous check.
+
+Correct the processor flag scan check to use a Family number and update
+it to a VFM based one to make it more readable.
+
+Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
+Link: https://lore.kernel.org/r/20250219184133.816753-4-sohil.mehta@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/intel-family.h | 1 +
+ arch/x86/kernel/cpu/microcode/intel.c | 2 +-
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h
+index 62d8b9448dc5c..c6198fbcc1d77 100644
+--- a/arch/x86/include/asm/intel-family.h
++++ b/arch/x86/include/asm/intel-family.h
+@@ -46,6 +46,7 @@
+ #define INTEL_ANY IFM(X86_FAMILY_ANY, X86_MODEL_ANY)
+
+ #define INTEL_PENTIUM_PRO IFM(6, 0x01)
++#define INTEL_PENTIUM_III_DESCHUTES IFM(6, 0x05)
+
+ #define INTEL_CORE_YONAH IFM(6, 0x0E)
+
+diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
+index df5650eb3f088..362cc71bbc866 100644
+--- a/arch/x86/kernel/cpu/microcode/intel.c
++++ b/arch/x86/kernel/cpu/microcode/intel.c
+@@ -74,7 +74,7 @@ void intel_collect_cpu_info(struct cpu_signature *sig)
+ sig->pf = 0;
+ sig->rev = intel_get_microcode_revision();
+
+- if (x86_model(sig->sig) >= 5 || x86_family(sig->sig) > 6) {
++ if (IFM(x86_family(sig->sig), x86_model(sig->sig)) >= INTEL_PENTIUM_III_DESCHUTES) {
+ unsigned int val[2];
+
+ /* get processor flags from MSR 0x17 */
+--
+2.39.5
+
--- /dev/null
+From f1962511b535336d75cab7fdc37659726230bc63 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Nov 2024 20:36:59 +0300
+Subject: x86/mm: Check return value from memblock_phys_alloc_range()
+
+From: Philip Redkin <me@rarity.fan>
+
+[ Upstream commit 631ca8909fd5c62b9fda9edda93924311a78a9c4 ]
+
+At least with CONFIG_PHYSICAL_START=0x100000, if there is < 4 MiB of
+contiguous free memory available at this point, the kernel will crash
+and burn because memblock_phys_alloc_range() returns 0 on failure,
+which leads memblock_phys_free() to throw the first 4 MiB of physical
+memory to the wolves.
+
+At a minimum it should fail gracefully with a meaningful diagnostic,
+but in fact everything seems to work fine without the weird reserve
+allocation.
+
+Signed-off-by: Philip Redkin <me@rarity.fan>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Cc: Dave Hansen <dave.hansen@linux.intel.com>
+Cc: Rik van Riel <riel@surriel.com>
+Cc: "H. Peter Anvin" <hpa@zytor.com>
+Link: https://lore.kernel.org/r/94b3e98f-96a7-3560-1f76-349eb95ccf7f@rarity.fan
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/mm/init.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
+index 101725c149c42..9cbc1e6057d3c 100644
+--- a/arch/x86/mm/init.c
++++ b/arch/x86/mm/init.c
+@@ -645,8 +645,13 @@ static void __init memory_map_top_down(unsigned long map_start,
+ */
+ addr = memblock_phys_alloc_range(PMD_SIZE, PMD_SIZE, map_start,
+ map_end);
+- memblock_phys_free(addr, PMD_SIZE);
+- real_end = addr + PMD_SIZE;
++ if (!addr) {
++ pr_warn("Failed to release memory for alloc_low_pages()");
++ real_end = max(map_start, ALIGN_DOWN(map_end, PMD_SIZE));
++ } else {
++ memblock_phys_free(addr, PMD_SIZE);
++ real_end = addr + PMD_SIZE;
++ }
+
+ /* step_size need to be small so pgt_buf from BRK could cover it */
+ step_size = PMD_SIZE;
+--
+2.39.5
+
--- /dev/null
+From c14d1a0208b7516b242bd94f0e7ae6a36f071b13 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Feb 2025 14:18:44 -0500
+Subject: x86/nmi: Add an emergency handler in nmi_desc & use it in
+ nmi_shootdown_cpus()
+
+From: Waiman Long <longman@redhat.com>
+
+[ Upstream commit fe37c699ae3eed6e02ee55fbf5cb9ceb7fcfd76c ]
+
+Depending on the type of panics, it was found that the
+__register_nmi_handler() function can be called in NMI context from
+nmi_shootdown_cpus() leading to a lockdep splat:
+
+ WARNING: inconsistent lock state
+ inconsistent {INITIAL USE} -> {IN-NMI} usage.
+
+ lock(&nmi_desc[0].lock);
+ <Interrupt>
+ lock(&nmi_desc[0].lock);
+
+ Call Trace:
+ _raw_spin_lock_irqsave
+ __register_nmi_handler
+ nmi_shootdown_cpus
+ kdump_nmi_shootdown_cpus
+ native_machine_crash_shutdown
+ __crash_kexec
+
+In this particular case, the following panic message was printed before:
+
+ Kernel panic - not syncing: Fatal hardware error!
+
+This message seemed to be given out from __ghes_panic() running in
+NMI context.
+
+The __register_nmi_handler() function which takes the nmi_desc lock
+with irq disabled shouldn't be called from NMI context as this can
+lead to deadlock.
+
+The nmi_shootdown_cpus() function can only be invoked once. After the
+first invocation, all other CPUs should be stuck in the newly added
+crash_nmi_callback() and cannot respond to a second NMI.
+
+Fix it by adding a new emergency NMI handler to the nmi_desc
+structure and provide a new set_emergency_nmi_handler() helper to set
+crash_nmi_callback() in any context. The new emergency handler will
+preempt other handlers in the linked list. That will eliminate the need
+to take any lock and serve the panic in NMI use case.
+
+Signed-off-by: Waiman Long <longman@redhat.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Acked-by: Rik van Riel <riel@surriel.com>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/r/20250206191844.131700-1-longman@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/nmi.h | 2 ++
+ arch/x86/kernel/nmi.c | 42 ++++++++++++++++++++++++++++++++++++++
+ arch/x86/kernel/reboot.c | 10 +++------
+ 3 files changed, 47 insertions(+), 7 deletions(-)
+
+diff --git a/arch/x86/include/asm/nmi.h b/arch/x86/include/asm/nmi.h
+index 41a0ebb699ec6..f677382093f36 100644
+--- a/arch/x86/include/asm/nmi.h
++++ b/arch/x86/include/asm/nmi.h
+@@ -56,6 +56,8 @@ int __register_nmi_handler(unsigned int, struct nmiaction *);
+
+ void unregister_nmi_handler(unsigned int, const char *);
+
++void set_emergency_nmi_handler(unsigned int type, nmi_handler_t handler);
++
+ void stop_nmi(void);
+ void restart_nmi(void);
+ void local_touch_nmi(void);
+diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
+index ed163c8c8604e..9a95d00f14233 100644
+--- a/arch/x86/kernel/nmi.c
++++ b/arch/x86/kernel/nmi.c
+@@ -40,8 +40,12 @@
+ #define CREATE_TRACE_POINTS
+ #include <trace/events/nmi.h>
+
++/*
++ * An emergency handler can be set in any context including NMI
++ */
+ struct nmi_desc {
+ raw_spinlock_t lock;
++ nmi_handler_t emerg_handler;
+ struct list_head head;
+ };
+
+@@ -132,9 +136,22 @@ static void nmi_check_duration(struct nmiaction *action, u64 duration)
+ static int nmi_handle(unsigned int type, struct pt_regs *regs)
+ {
+ struct nmi_desc *desc = nmi_to_desc(type);
++ nmi_handler_t ehandler;
+ struct nmiaction *a;
+ int handled=0;
+
++ /*
++ * Call the emergency handler, if set
++ *
++ * In the case of crash_nmi_callback() emergency handler, it will
++ * return in the case of the crashing CPU to enable it to complete
++ * other necessary crashing actions ASAP. Other handlers in the
++ * linked list won't need to be run.
++ */
++ ehandler = desc->emerg_handler;
++ if (ehandler)
++ return ehandler(type, regs);
++
+ rcu_read_lock();
+
+ /*
+@@ -224,6 +241,31 @@ void unregister_nmi_handler(unsigned int type, const char *name)
+ }
+ EXPORT_SYMBOL_GPL(unregister_nmi_handler);
+
++/**
++ * set_emergency_nmi_handler - Set emergency handler
++ * @type: NMI type
++ * @handler: the emergency handler to be stored
++ *
++ * Set an emergency NMI handler which, if set, will preempt all the other
++ * handlers in the linked list. If a NULL handler is passed in, it will clear
++ * it. It is expected that concurrent calls to this function will not happen
++ * or the system is screwed beyond repair.
++ */
++void set_emergency_nmi_handler(unsigned int type, nmi_handler_t handler)
++{
++ struct nmi_desc *desc = nmi_to_desc(type);
++
++ if (WARN_ON_ONCE(desc->emerg_handler == handler))
++ return;
++ desc->emerg_handler = handler;
++
++ /*
++ * Ensure the emergency handler is visible to other CPUs before
++ * function return
++ */
++ smp_wmb();
++}
++
+ static void
+ pci_serr_error(unsigned char reason, struct pt_regs *regs)
+ {
+diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
+index dc1dd3f3e67fc..9aaac1f9f45b5 100644
+--- a/arch/x86/kernel/reboot.c
++++ b/arch/x86/kernel/reboot.c
+@@ -926,15 +926,11 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback)
+ shootdown_callback = callback;
+
+ atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+- /* Would it be better to replace the trap vector here? */
+- if (register_nmi_handler(NMI_LOCAL, crash_nmi_callback,
+- NMI_FLAG_FIRST, "crash"))
+- return; /* Return what? */
++
+ /*
+- * Ensure the new callback function is set before sending
+- * out the NMI
++ * Set emergency handler to preempt other handlers.
+ */
+- wmb();
++ set_emergency_nmi_handler(NMI_LOCAL, crash_nmi_callback);
+
+ apic_send_IPI_allbutself(NMI_VECTOR);
+
+--
+2.39.5
+
--- /dev/null
+From e2c328b432149ff61d399af825c934869c86116e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jan 2025 14:07:37 -0500
+Subject: x86/relocs: Handle R_X86_64_REX_GOTPCRELX relocations
+
+From: Brian Gerst <brgerst@gmail.com>
+
+[ Upstream commit cb7927fda002ca49ae62e2782c1692acc7b80c67 ]
+
+Clang may produce R_X86_64_REX_GOTPCRELX relocations when redefining the
+stack protector location. Treat them as another type of PC-relative
+relocation.
+
+Signed-off-by: Brian Gerst <brgerst@gmail.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Link: https://lore.kernel.org/r/20250123190747.745588-6-brgerst@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/tools/relocs.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
+index c101bed619400..7f390e3374a76 100644
+--- a/arch/x86/tools/relocs.c
++++ b/arch/x86/tools/relocs.c
+@@ -32,6 +32,11 @@ static struct relocs relocs32;
+ static struct relocs relocs32neg;
+ static struct relocs relocs64;
+ # define FMT PRIu64
++
++#ifndef R_X86_64_REX_GOTPCRELX
++# define R_X86_64_REX_GOTPCRELX 42
++#endif
++
+ #else
+ # define FMT PRIu32
+ #endif
+@@ -227,6 +232,7 @@ static const char *rel_type(unsigned type)
+ REL_TYPE(R_X86_64_PC16),
+ REL_TYPE(R_X86_64_8),
+ REL_TYPE(R_X86_64_PC8),
++ REL_TYPE(R_X86_64_REX_GOTPCRELX),
+ #else
+ REL_TYPE(R_386_NONE),
+ REL_TYPE(R_386_32),
+@@ -861,6 +867,7 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym,
+
+ case R_X86_64_PC32:
+ case R_X86_64_PLT32:
++ case R_X86_64_REX_GOTPCRELX:
+ /*
+ * PC relative relocations don't need to be adjusted unless
+ * referencing a percpu symbol.
+--
+2.39.5
+
--- /dev/null
+From de9f5b7bb79edee808c7d356acfcdfc67f2345f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Feb 2025 18:41:28 +0000
+Subject: x86/smpboot: Fix INIT delay assignment for extended Intel Families
+
+From: Sohil Mehta <sohil.mehta@intel.com>
+
+[ Upstream commit 7a2ad752746bfb13e89a83984ecc52a48bae4969 ]
+
+Some old crusty CPUs need an extra delay that slows down booting. See
+the comment above 'init_udelay' for details. Newer CPUs don't need the
+delay.
+
+Right now, for Intel, Family 6 and only Family 6 skips the delay. That
+leaves out both the Family 15 (Pentium 4s) and brand new Family 18/19
+models.
+
+The omission of Family 15 (Pentium 4s) seems like an oversight and 18/19
+do not need the delay.
+
+Skip the delay on all Intel processors Family 6 and beyond.
+
+Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Link: https://lore.kernel.org/r/20250219184133.816753-11-sohil.mehta@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/smpboot.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
+index f1fac08fdef28..2c451de702c87 100644
+--- a/arch/x86/kernel/smpboot.c
++++ b/arch/x86/kernel/smpboot.c
+@@ -681,9 +681,9 @@ static void __init smp_quirk_init_udelay(void)
+ return;
+
+ /* if modern processor, use no delay */
+- if (((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 6)) ||
+- ((boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) && (boot_cpu_data.x86 >= 0x18)) ||
+- ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && (boot_cpu_data.x86 >= 0xF))) {
++ if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && boot_cpu_data.x86_vfm >= INTEL_PENTIUM_PRO) ||
++ (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON && boot_cpu_data.x86 >= 0x18) ||
++ (boot_cpu_data.x86_vendor == X86_VENDOR_AMD && boot_cpu_data.x86 >= 0xF)) {
+ init_udelay = 0;
+ return;
+ }
+--
+2.39.5
+
--- /dev/null
+From b6982925e93b8b7bd20a3795cfbf87a6e0332ff8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Mar 2025 12:48:49 +0100
+Subject: x86/stackprotector/64: Only export __ref_stack_chk_guard on
+ CONFIG_SMP
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ingo Molnar <mingo@kernel.org>
+
+[ Upstream commit 91d5451d97ce35cbd510277fa3b7abf9caa4e34d ]
+
+The __ref_stack_chk_guard symbol doesn't exist on UP:
+
+ <stdin>:4:15: error: ‘__ref_stack_chk_guard’ undeclared here (not in a function)
+
+Fix the #ifdef around the entry.S export.
+
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Cc: Brian Gerst <brgerst@gmail.com>
+Cc: Ard Biesheuvel <ardb@kernel.org>
+Cc: Uros Bizjak <ubizjak@gmail.com>
+Link: https://lore.kernel.org/r/20250123190747.745588-8-brgerst@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/entry/entry.S | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/entry/entry.S b/arch/x86/entry/entry.S
+index 58e3124ee2b42..5b96249734ada 100644
+--- a/arch/x86/entry/entry.S
++++ b/arch/x86/entry/entry.S
+@@ -63,7 +63,7 @@ THUNK warn_thunk_thunk, __warn_thunk
+ * entirely in the C code, and use an alias emitted by the linker script
+ * instead.
+ */
+-#ifdef CONFIG_STACKPROTECTOR
++#if defined(CONFIG_STACKPROTECTOR) && defined(CONFIG_SMP)
+ EXPORT_SYMBOL(__ref_stack_chk_guard);
+ #endif
+ #endif
+--
+2.39.5
+
--- /dev/null
+From 91f62dbac4e2e0740df12c32a5153eee89ac4b3c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Feb 2025 13:15:36 +0100
+Subject: x86/traps: Cleanup and robustify decode_bug()
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit c20ad96c9a8f0aeaf4e4057730a22de2657ad0c2 ]
+
+Notably, don't attempt to decode an immediate when MOD == 3.
+
+Additionally have it return the instruction length, such that WARN
+like bugs can more reliably skip to the correct instruction.
+
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Sami Tolvanen <samitolvanen@google.com>
+Link: https://lore.kernel.org/r/20250207122546.721120726@infradead.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/bug.h | 5 ++-
+ arch/x86/include/asm/ibt.h | 4 +-
+ arch/x86/kernel/traps.c | 82 ++++++++++++++++++++++++++++----------
+ 3 files changed, 65 insertions(+), 26 deletions(-)
+
+diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h
+index 806649c7f23dc..9a0f29be1a9ea 100644
+--- a/arch/x86/include/asm/bug.h
++++ b/arch/x86/include/asm/bug.h
+@@ -22,8 +22,9 @@
+ #define SECOND_BYTE_OPCODE_UD2 0x0b
+
+ #define BUG_NONE 0xffff
+-#define BUG_UD1 0xfffe
+-#define BUG_UD2 0xfffd
++#define BUG_UD2 0xfffe
++#define BUG_UD1 0xfffd
++#define BUG_UD1_UBSAN 0xfffc
+
+ #ifdef CONFIG_GENERIC_BUG
+
+diff --git a/arch/x86/include/asm/ibt.h b/arch/x86/include/asm/ibt.h
+index 1e59581d500ca..b778ae6e67ee8 100644
+--- a/arch/x86/include/asm/ibt.h
++++ b/arch/x86/include/asm/ibt.h
+@@ -41,7 +41,7 @@
+ _ASM_PTR fname "\n\t" \
+ ".popsection\n\t"
+
+-static inline __attribute_const__ u32 gen_endbr(void)
++static __always_inline __attribute_const__ u32 gen_endbr(void)
+ {
+ u32 endbr;
+
+@@ -56,7 +56,7 @@ static inline __attribute_const__ u32 gen_endbr(void)
+ return endbr;
+ }
+
+-static inline __attribute_const__ u32 gen_endbr_poison(void)
++static __always_inline __attribute_const__ u32 gen_endbr_poison(void)
+ {
+ /*
+ * 4 byte NOP that isn't NOP4 (in fact it is OSP NOP3), such that it
+diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
+index 5e3e036e6e537..b18fc7539b8d7 100644
+--- a/arch/x86/kernel/traps.c
++++ b/arch/x86/kernel/traps.c
+@@ -94,10 +94,17 @@ __always_inline int is_valid_bugaddr(unsigned long addr)
+
+ /*
+ * Check for UD1 or UD2, accounting for Address Size Override Prefixes.
+- * If it's a UD1, get the ModRM byte to pass along to UBSan.
++ * If it's a UD1, further decode to determine its use:
++ *
++ * UBSan{0}: 67 0f b9 00 ud1 (%eax),%eax
++ * UBSan{10}: 67 0f b9 40 10 ud1 0x10(%eax),%eax
++ * static_call: 0f b9 cc ud1 %esp,%ecx
++ *
++ * Notably UBSAN uses EAX, static_call uses ECX.
+ */
+-__always_inline int decode_bug(unsigned long addr, u32 *imm)
++__always_inline int decode_bug(unsigned long addr, s32 *imm, int *len)
+ {
++ unsigned long start = addr;
+ u8 v;
+
+ if (addr < TASK_SIZE_MAX)
+@@ -110,24 +117,42 @@ __always_inline int decode_bug(unsigned long addr, u32 *imm)
+ return BUG_NONE;
+
+ v = *(u8 *)(addr++);
+- if (v == SECOND_BYTE_OPCODE_UD2)
++ if (v == SECOND_BYTE_OPCODE_UD2) {
++ *len = addr - start;
+ return BUG_UD2;
++ }
+
+- if (!IS_ENABLED(CONFIG_UBSAN_TRAP) || v != SECOND_BYTE_OPCODE_UD1)
++ if (v != SECOND_BYTE_OPCODE_UD1)
+ return BUG_NONE;
+
+- /* Retrieve the immediate (type value) for the UBSAN UD1 */
+- v = *(u8 *)(addr++);
+- if (X86_MODRM_RM(v) == 4)
+- addr++;
+-
+ *imm = 0;
+- if (X86_MODRM_MOD(v) == 1)
+- *imm = *(u8 *)addr;
+- else if (X86_MODRM_MOD(v) == 2)
+- *imm = *(u32 *)addr;
+- else
+- WARN_ONCE(1, "Unexpected MODRM_MOD: %u\n", X86_MODRM_MOD(v));
++ v = *(u8 *)(addr++); /* ModRM */
++
++ if (X86_MODRM_MOD(v) != 3 && X86_MODRM_RM(v) == 4)
++ addr++; /* SIB */
++
++ /* Decode immediate, if present */
++ switch (X86_MODRM_MOD(v)) {
++ case 0: if (X86_MODRM_RM(v) == 5)
++ addr += 4; /* RIP + disp32 */
++ break;
++
++ case 1: *imm = *(s8 *)addr;
++ addr += 1;
++ break;
++
++ case 2: *imm = *(s32 *)addr;
++ addr += 4;
++ break;
++
++ case 3: break;
++ }
++
++ /* record instruction length */
++ *len = addr - start;
++
++ if (X86_MODRM_REG(v) == 0) /* EAX */
++ return BUG_UD1_UBSAN;
+
+ return BUG_UD1;
+ }
+@@ -258,10 +283,10 @@ static inline void handle_invalid_op(struct pt_regs *regs)
+ static noinstr bool handle_bug(struct pt_regs *regs)
+ {
+ bool handled = false;
+- int ud_type;
+- u32 imm;
++ int ud_type, ud_len;
++ s32 ud_imm;
+
+- ud_type = decode_bug(regs->ip, &imm);
++ ud_type = decode_bug(regs->ip, &ud_imm, &ud_len);
+ if (ud_type == BUG_NONE)
+ return handled;
+
+@@ -281,15 +306,28 @@ static noinstr bool handle_bug(struct pt_regs *regs)
+ */
+ if (regs->flags & X86_EFLAGS_IF)
+ raw_local_irq_enable();
+- if (ud_type == BUG_UD2) {
++
++ switch (ud_type) {
++ case BUG_UD2:
+ if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN ||
+ handle_cfi_failure(regs) == BUG_TRAP_TYPE_WARN) {
+- regs->ip += LEN_UD2;
++ regs->ip += ud_len;
+ handled = true;
+ }
+- } else if (IS_ENABLED(CONFIG_UBSAN_TRAP)) {
+- pr_crit("%s at %pS\n", report_ubsan_failure(regs, imm), (void *)regs->ip);
++ break;
++
++ case BUG_UD1_UBSAN:
++ if (IS_ENABLED(CONFIG_UBSAN_TRAP)) {
++ pr_crit("%s at %pS\n",
++ report_ubsan_failure(regs, ud_imm),
++ (void *)regs->ip);
++ }
++ break;
++
++ default:
++ break;
+ }
++
+ if (regs->flags & X86_EFLAGS_IF)
+ raw_local_irq_disable();
+ instrumentation_end();
+--
+2.39.5
+
--- /dev/null
+From c9d3c4c2a685de13e844502936fcb45566e99e0f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Feb 2025 14:50:15 +0000
+Subject: xen: Add support for XenServer 6.1 platform device
+
+From: Frediano Ziglio <frediano.ziglio@cloud.com>
+
+[ Upstream commit 2356f15caefc0cc63d9cc5122641754f76ef9b25 ]
+
+On XenServer on Windows machine a platform device with ID 2 instead of
+1 is used.
+
+This device is mainly identical to device 1 but due to some Windows
+update behaviour it was decided to use a device with a different ID.
+
+This causes compatibility issues with Linux which expects, if Xen
+is detected, to find a Xen platform device (5853:0001) otherwise code
+will crash due to some missing initialization (specifically grant
+tables). Specifically from dmesg
+
+ RIP: 0010:gnttab_expand+0x29/0x210
+ Code: 90 0f 1f 44 00 00 55 31 d2 48 89 e5 41 57 41 56 41 55 41 89 fd
+ 41 54 53 48 83 ec 10 48 8b 05 7e 9a 49 02 44 8b 35 a7 9a 49 02
+ <8b> 48 04 8d 44 39 ff f7 f1 45 8d 24 06 89 c3 e8 43 fe ff ff
+ 44 39
+ RSP: 0000:ffffba34c01fbc88 EFLAGS: 00010086
+ ...
+
+The device 2 is presented by Xapi adding device specification to
+Qemu command line.
+
+Signed-off-by: Frediano Ziglio <frediano.ziglio@cloud.com>
+Acked-by: Juergen Gross <jgross@suse.com>
+Message-ID: <20250227145016.25350-1-frediano.ziglio@cloud.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/xen/platform-pci.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c
+index 544d3f9010b92..1db82da56db62 100644
+--- a/drivers/xen/platform-pci.c
++++ b/drivers/xen/platform-pci.c
+@@ -26,6 +26,8 @@
+
+ #define DRV_NAME "xen-platform-pci"
+
++#define PCI_DEVICE_ID_XEN_PLATFORM_XS61 0x0002
++
+ static unsigned long platform_mmio;
+ static unsigned long platform_mmio_alloc;
+ static unsigned long platform_mmiolen;
+@@ -174,6 +176,8 @@ static int platform_pci_probe(struct pci_dev *pdev,
+ static const struct pci_device_id platform_pci_tbl[] = {
+ {PCI_VENDOR_ID_XEN, PCI_DEVICE_ID_XEN_PLATFORM,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
++ {PCI_VENDOR_ID_XEN, PCI_DEVICE_ID_XEN_PLATFORM_XS61,
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0,}
+ };
+
+--
+2.39.5
+
--- /dev/null
+From e3fc61275ab72609e718e8a2a5e405d743550821 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Feb 2025 10:20:55 +0100
+Subject: xen/pci: Do not register devices with segments >= 0x10000
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Roger Pau Monne <roger.pau@citrix.com>
+
+[ Upstream commit 5ccf1b8ae76ddf348e02a0d1564ff9baf8b6c415 ]
+
+The current hypercall interface for doing PCI device operations always uses
+a segment field that has a 16 bit width. However on Linux there are buses
+like VMD that hook up devices into the PCI hierarchy at segment >= 0x10000,
+after the maximum possible segment enumerated in ACPI.
+
+Attempting to register or manage those devices with Xen would result in
+errors at best, or overlaps with existing devices living on the truncated
+equivalent segment values. Note also that the VMD segment numbers are
+arbitrarily assigned by the OS, and hence there would need to be some
+negotiation between Xen and the OS to agree on how to enumerate VMD
+segments and devices behind them.
+
+Skip notifying Xen about those devices. Given how VMD bridges can
+multiplex interrupts on behalf of devices behind them there's no need for
+Xen to be aware of such devices for them to be usable by Linux.
+
+Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
+Acked-by: Juergen Gross <jgross@suse.com>
+Message-ID: <20250219092059.90850-2-roger.pau@citrix.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/xen/pci.c | 32 ++++++++++++++++++++++++++++++++
+ 1 file changed, 32 insertions(+)
+
+diff --git a/drivers/xen/pci.c b/drivers/xen/pci.c
+index 416f231809cb6..bfe07adb3e3a6 100644
+--- a/drivers/xen/pci.c
++++ b/drivers/xen/pci.c
+@@ -43,6 +43,18 @@ static int xen_add_device(struct device *dev)
+ pci_mcfg_reserved = true;
+ }
+ #endif
++
++ if (pci_domain_nr(pci_dev->bus) >> 16) {
++ /*
++ * The hypercall interface is limited to 16bit PCI segment
++ * values, do not attempt to register devices with Xen in
++ * segments greater or equal than 0x10000.
++ */
++ dev_info(dev,
++ "not registering with Xen: invalid PCI segment\n");
++ return 0;
++ }
++
+ if (pci_seg_supported) {
+ DEFINE_RAW_FLEX(struct physdev_pci_device_add, add, optarr, 1);
+
+@@ -149,6 +161,16 @@ static int xen_remove_device(struct device *dev)
+ int r;
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+
++ if (pci_domain_nr(pci_dev->bus) >> 16) {
++ /*
++ * The hypercall interface is limited to 16bit PCI segment
++ * values.
++ */
++ dev_info(dev,
++ "not unregistering with Xen: invalid PCI segment\n");
++ return 0;
++ }
++
+ if (pci_seg_supported) {
+ struct physdev_pci_device device = {
+ .seg = pci_domain_nr(pci_dev->bus),
+@@ -182,6 +204,16 @@ int xen_reset_device(const struct pci_dev *dev)
+ .flags = PCI_DEVICE_RESET_FLR,
+ };
+
++ if (pci_domain_nr(dev->bus) >> 16) {
++ /*
++ * The hypercall interface is limited to 16bit PCI segment
++ * values.
++ */
++ dev_info(&dev->dev,
++ "unable to notify Xen of device reset: invalid PCI segment\n");
++ return 0;
++ }
++
+ return HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_reset, &device);
+ }
+ EXPORT_SYMBOL_GPL(xen_reset_device);
+--
+2.39.5
+
--- /dev/null
+From 7da0c765a6ef62d454e03efd8c4c306468bbd179 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 May 2025 16:44:56 -0400
+Subject: xenbus: Allow PVH dom0 a non-local xenstore
+
+From: Jason Andryuk <jason.andryuk@amd.com>
+
+[ Upstream commit 90989869baae47ee2aa3bcb6f6eb9fbbe4287958 ]
+
+Make xenbus_init() allow a non-local xenstore for a PVH dom0 - it is
+currently forced to XS_LOCAL. With Hyperlaunch booting dom0 and a
+xenstore stubdom, dom0 can be handled as a regular XS_HVM following the
+late init path.
+
+Ideally we'd drop the use of xen_initial_domain() and just check for the
+event channel instead. However, ARM has a xen,enhanced no-xenstore
+mode, where the event channel and PFN would both be 0. Retain the
+xen_initial_domain() check, and use that for an additional check when
+the event channel is 0.
+
+Check the full 64bit HVM_PARAM_STORE_EVTCHN value to catch the off
+chance that high bits are set for the 32bit event channel.
+
+Signed-off-by: Jason Andryuk <jason.andryuk@amd.com>
+Change-Id: I5506da42e4c6b8e85079fefb2f193c8de17c7437
+Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Message-ID: <20250506204456.5220-1-jason.andryuk@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/xen/xenbus/xenbus_probe.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
+index 6d32ffb011365..86fe6e7790566 100644
+--- a/drivers/xen/xenbus/xenbus_probe.c
++++ b/drivers/xen/xenbus/xenbus_probe.c
+@@ -966,9 +966,15 @@ static int __init xenbus_init(void)
+ if (xen_pv_domain())
+ xen_store_domain_type = XS_PV;
+ if (xen_hvm_domain())
++ {
+ xen_store_domain_type = XS_HVM;
+- if (xen_hvm_domain() && xen_initial_domain())
+- xen_store_domain_type = XS_LOCAL;
++ err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
++ if (err)
++ goto out_error;
++ xen_store_evtchn = (int)v;
++ if (!v && xen_initial_domain())
++ xen_store_domain_type = XS_LOCAL;
++ }
+ if (xen_pv_domain() && !xen_start_info->store_evtchn)
+ xen_store_domain_type = XS_LOCAL;
+ if (xen_pv_domain() && xen_start_info->store_evtchn)
+@@ -987,10 +993,6 @@ static int __init xenbus_init(void)
+ xen_store_interface = gfn_to_virt(xen_store_gfn);
+ break;
+ case XS_HVM:
+- err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
+- if (err)
+- goto out_error;
+- xen_store_evtchn = (int)v;
+ err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v);
+ if (err)
+ goto out_error;
+--
+2.39.5
+
--- /dev/null
+From 495948964d304b2179bfc1a06c7da9295e2cd900 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Feb 2025 20:27:49 +0200
+Subject: xfrm: prevent high SEQ input in non-ESN mode
+
+From: Leon Romanovsky <leonro@nvidia.com>
+
+[ Upstream commit e3aa43a50a6455831e3c32dabc7ece38d9cd9d05 ]
+
+In non-ESN mode, the SEQ numbers are limited to 32 bits and seq_hi/oseq_hi
+are not used. So make sure that user gets proper error message, in case
+such assignment occurred.
+
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xfrm/xfrm_user.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
+index 87013623773a2..da2a1c00ca8a6 100644
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -178,6 +178,12 @@ static inline int verify_replay(struct xfrm_usersa_info *p,
+ "Replay seq and seq_hi should be 0 for output SA");
+ return -EINVAL;
+ }
++ if (rs->oseq_hi && !(p->flags & XFRM_STATE_ESN)) {
++ NL_SET_ERR_MSG(
++ extack,
++ "Replay oseq_hi should be 0 in non-ESN mode for output SA");
++ return -EINVAL;
++ }
+ if (rs->bmp_len) {
+ NL_SET_ERR_MSG(extack, "Replay bmp_len should 0 for output SA");
+ return -EINVAL;
+@@ -190,6 +196,12 @@ static inline int verify_replay(struct xfrm_usersa_info *p,
+ "Replay oseq and oseq_hi should be 0 for input SA");
+ return -EINVAL;
+ }
++ if (rs->seq_hi && !(p->flags & XFRM_STATE_ESN)) {
++ NL_SET_ERR_MSG(
++ extack,
++ "Replay seq_hi should be 0 in non-ESN mode for input SA");
++ return -EINVAL;
++ }
+ }
+
+ return 0;
+--
+2.39.5
+