--- /dev/null
+From 446a2ff568e093da486b759cbd322a286446f929 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Mar 2025 10:20:30 +0100
+Subject: ahci: add PCI ID for Marvell 88SE9215 SATA Controller
+
+From: Daniel Kral <d.kral@proxmox.com>
+
+[ Upstream commit 885251dc35767b1c992f6909532ca366c830814a ]
+
+Add support for Marvell Technology Group Ltd. 88SE9215 SATA 6 Gb/s
+controller, which is e.g. used in the DAWICONTROL DC-614e RAID bus
+controller and was not automatically recognized before.
+
+Tested with a DAWICONTROL DC-614e RAID bus controller.
+
+Signed-off-by: Daniel Kral <d.kral@proxmox.com>
+Link: https://lore.kernel.org/r/20250304092030.37108-1-d.kral@proxmox.com
+Signed-off-by: Niklas Cassel <cassel@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/ahci.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
+index 45f63b09828a1..14dd1b432ac34 100644
+--- a/drivers/ata/ahci.c
++++ b/drivers/ata/ahci.c
+@@ -589,6 +589,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
+ .driver_data = board_ahci_yes_fbs },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
+ .driver_data = board_ahci_yes_fbs },
++ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9215),
++ .driver_data = board_ahci_yes_fbs },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230),
+ .driver_data = board_ahci_yes_fbs },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9235),
+--
+2.39.5
+
--- /dev/null
+From 0e0e01ed0b81e96670a2147b211e175defc5776c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Mar 2025 18:43:14 +0800
+Subject: ahci: Marvell 88SE9215 controllers prefer DMA for ATAPI
+
+From: Huacai Chen <chenhuacai@loongson.cn>
+
+[ Upstream commit 0507c777f5d8f9e34b137d28ee263599a7b81242 ]
+
+We use CD/DVD drives under Marvell 88SE9215 SATA controller on many
+Loongson-based machines. We found its PIO doesn't work well, and on the
+opposite its DMA seems work very well.
+
+We don't know the detail of the 88SE9215 SATA controller, but we have
+tested different CD/DVD drives and they all have problems under 88SE9215
+(but they all work well under an Intel SATA controller). So, we consider
+this problem is bound to 88SE9215 SATA controller rather than bound to
+CD/DVD drives.
+
+As a solution, we define a new dedicated AHCI board id which is named
+board_ahci_yes_fbs_atapi_dma for 88SE9215, and for this id we set the
+AHCI_HFLAG_ATAPI_DMA_QUIRK and ATA_QUIRK_ATAPI_MOD16_DMA flags on the
+SATA controller in order to prefer ATAPI DMA.
+
+Reported-by: Yuli Wang <wangyuli@uniontech.com>
+Tested-by: Jie Fan <fanjie@uniontech.com>
+Tested-by: Erpeng Xu <xuerpeng@uniontech.com>
+Tested-by: Yuli Wang <wangyuli@uniontech.com>
+Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
+Link: https://lore.kernel.org/r/20250318104314.2160526-1-chenhuacai@loongson.cn
+Signed-off-by: Niklas Cassel <cassel@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/ahci.c | 11 ++++++++++-
+ drivers/ata/ahci.h | 1 +
+ drivers/ata/libahci.c | 4 ++++
+ 3 files changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
+index 14dd1b432ac34..650122deb480d 100644
+--- a/drivers/ata/ahci.c
++++ b/drivers/ata/ahci.c
+@@ -63,6 +63,7 @@ enum board_ids {
+ board_ahci_pcs_quirk_no_devslp,
+ board_ahci_pcs_quirk_no_sntf,
+ board_ahci_yes_fbs,
++ board_ahci_yes_fbs_atapi_dma,
+
+ /* board IDs for specific chipsets in alphabetical order */
+ board_ahci_al,
+@@ -188,6 +189,14 @@ static const struct ata_port_info ahci_port_info[] = {
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_ops,
+ },
++ [board_ahci_yes_fbs_atapi_dma] = {
++ AHCI_HFLAGS (AHCI_HFLAG_YES_FBS |
++ AHCI_HFLAG_ATAPI_DMA_QUIRK),
++ .flags = AHCI_FLAG_COMMON,
++ .pio_mask = ATA_PIO4,
++ .udma_mask = ATA_UDMA6,
++ .port_ops = &ahci_ops,
++ },
+ /* by chipsets */
+ [board_ahci_al] = {
+ AHCI_HFLAGS (AHCI_HFLAG_NO_PMP | AHCI_HFLAG_NO_MSI),
+@@ -590,7 +599,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
+ .driver_data = board_ahci_yes_fbs },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9215),
+- .driver_data = board_ahci_yes_fbs },
++ .driver_data = board_ahci_yes_fbs_atapi_dma },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230),
+ .driver_data = board_ahci_yes_fbs },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9235),
+diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
+index 8f40f75ba08cf..10a5fe02f0a45 100644
+--- a/drivers/ata/ahci.h
++++ b/drivers/ata/ahci.h
+@@ -246,6 +246,7 @@ enum {
+ AHCI_HFLAG_NO_SXS = BIT(26), /* SXS not supported */
+ AHCI_HFLAG_43BIT_ONLY = BIT(27), /* 43bit DMA addr limit */
+ AHCI_HFLAG_INTEL_PCS_QUIRK = BIT(28), /* apply Intel PCS quirk */
++ AHCI_HFLAG_ATAPI_DMA_QUIRK = BIT(29), /* force ATAPI to use DMA */
+
+ /* ap->flags bits */
+
+diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
+index fdfa7b2662180..a28ffe1e59691 100644
+--- a/drivers/ata/libahci.c
++++ b/drivers/ata/libahci.c
+@@ -1321,6 +1321,10 @@ static void ahci_dev_config(struct ata_device *dev)
+ {
+ struct ahci_host_priv *hpriv = dev->link->ap->host->private_data;
+
++ if ((dev->class == ATA_DEV_ATAPI) &&
++ (hpriv->flags & AHCI_HFLAG_ATAPI_DMA_QUIRK))
++ dev->quirks |= ATA_QUIRK_ATAPI_MOD16_DMA;
++
+ if (hpriv->flags & AHCI_HFLAG_SECT255) {
+ dev->max_sectors = 255;
+ ata_dev_info(dev,
+--
+2.39.5
+
--- /dev/null
+From 43c31fbcf63d8844ee2b91a2e222aff951dc0fda Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Feb 2025 23:46:02 +0200
+Subject: ALSA: hda: intel: Add Lenovo IdeaPad Z570 to probe denylist
+
+From: Maxim Mikityanskiy <maxtram95@gmail.com>
+
+[ Upstream commit becc794c5e46f4dfca59f2385f78d83fc9e84700 ]
+
+Lenovo IdeaPad Z570 with NVIDIA GeForce Ge 540M doesn't have sound on
+the discrete GPU. The HDA controller in DGPU is disabled by BIOS, but
+then reenabled by quirk_nvidia_hda(). The probe fails and ends up with
+the "GPU sound probed, but not operational" error.
+
+Add this laptop to DMI-based denylist to prevent probe early. DMI is
+used, because the audio device has zero subsystem IDs, and this entry
+would be too much, blocking all 540M chips:
+ PCI_DEVICE_SUB(0x10de, 0x0bea, 0x0000, 0x0000)
+Also, this laptop comes in a variety of modifications with different
+NVIDIA GPUs, so the DMI check will cover them all.
+
+Signed-off-by: Maxim Mikityanskiy <maxtram95@gmail.com>
+Link: https://patch.msgid.link/20250208214602.39607-3-maxtram95@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/hda/hda_intel.c | 29 +++++++++++++++++++++++++++++
+ 1 file changed, 29 insertions(+)
+
+diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
+index b511563bbb6ba..25b1984898ab2 100644
+--- a/sound/pci/hda/hda_intel.c
++++ b/sound/pci/hda/hda_intel.c
+@@ -37,6 +37,7 @@
+ #include <linux/completion.h>
+ #include <linux/acpi.h>
+ #include <linux/pgtable.h>
++#include <linux/dmi.h>
+
+ #ifdef CONFIG_X86
+ /* for snoop control */
+@@ -2084,6 +2085,27 @@ static const struct pci_device_id driver_denylist[] = {
+ {}
+ };
+
++static struct pci_device_id driver_denylist_ideapad_z570[] = {
++ { PCI_DEVICE_SUB(0x10de, 0x0bea, 0x0000, 0x0000) }, /* NVIDIA GF108 HDA */
++ {}
++};
++
++/* DMI-based denylist, to be used when:
++ * - PCI subsystem IDs are zero, impossible to distinguish from valid sound cards.
++ * - Different modifications of the same laptop use different GPU models.
++ */
++static const struct dmi_system_id driver_denylist_dmi[] = {
++ {
++ /* No HDA in NVIDIA DGPU. BIOS disables it, but quirk_nvidia_hda() reenables. */
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++ DMI_MATCH(DMI_PRODUCT_VERSION, "Ideapad Z570"),
++ },
++ .driver_data = &driver_denylist_ideapad_z570,
++ },
++ {}
++};
++
+ static const struct hda_controller_ops pci_hda_ops = {
+ .disable_msi_reset_irq = disable_msi_reset_irq,
+ .position_check = azx_position_check,
+@@ -2094,6 +2116,7 @@ static DECLARE_BITMAP(probed_devs, SNDRV_CARDS);
+ static int azx_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+ {
++ const struct dmi_system_id *dmi;
+ struct snd_card *card;
+ struct hda_intel *hda;
+ struct azx *chip;
+@@ -2106,6 +2129,12 @@ static int azx_probe(struct pci_dev *pci,
+ return -ENODEV;
+ }
+
++ dmi = dmi_first_match(driver_denylist_dmi);
++ if (dmi && pci_match_id(dmi->driver_data, pci)) {
++ dev_info(&pci->dev, "Skipping the device on the DMI denylist\n");
++ return -ENODEV;
++ }
++
+ dev = find_first_zero_bit(probed_devs, SNDRV_CARDS);
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+--
+2.39.5
+
--- /dev/null
+From 2d157e9209a5f8d10222a2fc5f59c9e8fda73b3c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Feb 2025 23:46:01 +0200
+Subject: ALSA: hda: intel: Fix Optimus when GPU has no sound
+
+From: Maxim Mikityanskiy <maxtram95@gmail.com>
+
+[ Upstream commit 2b360ba9a4936486380bc30d1eabceb40a714d98 ]
+
+quirk_nvidia_hda() forcefully enables HDA controller on all NVIDIA GPUs,
+because some buggy BIOSes leave it disabled. However, some dual-GPU
+laptops do not have a functional HDA controller in DGPU, and BIOS
+disables it on purpose. After quirk_nvidia_hda() reenables this dummy
+HDA controller, attempting to probe it fails at azx_first_init(), which
+is too late to cancel the probe, as it happens in azx_probe_continue().
+
+The sna_hda_intel driver calls azx_free() and stops the chip, however,
+it stays probed, and from the runtime PM point of view, the device
+remains active (it was set as active by the PCI subsystem on probe). It
+prevents vga_switcheroo from turning off the DGPU, because
+pci_create_device_link() syncs power management for video and audio
+devices.
+
+Affected devices should be added to driver_denylist to prevent them from
+probing early. This patch helps identify such devices by printing a
+warning, and also forces the device to the suspended state to allow
+vga_switcheroo turn off DGPU.
+
+Signed-off-by: Maxim Mikityanskiy <maxtram95@gmail.com>
+Link: https://patch.msgid.link/20250208214602.39607-2-maxtram95@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/hda/hda_intel.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
+index cb9925948175f..b511563bbb6ba 100644
+--- a/sound/pci/hda/hda_intel.c
++++ b/sound/pci/hda/hda_intel.c
+@@ -1360,8 +1360,21 @@ static void azx_free(struct azx *chip)
+ if (use_vga_switcheroo(hda)) {
+ if (chip->disabled && hda->probe_continued)
+ snd_hda_unlock_devices(&chip->bus);
+- if (hda->vga_switcheroo_registered)
++ if (hda->vga_switcheroo_registered) {
+ vga_switcheroo_unregister_client(chip->pci);
++
++ /* Some GPUs don't have sound, and azx_first_init fails,
++ * leaving the device probed but non-functional. As long
++ * as it's probed, the PCI subsystem keeps its runtime
++ * PM status as active. Force it to suspended (as we
++ * actually stop the chip) to allow GPU to suspend via
++ * vga_switcheroo, and print a warning.
++ */
++ dev_warn(&pci->dev, "GPU sound probed, but not operational: please add a quirk to driver_denylist\n");
++ pm_runtime_disable(&pci->dev);
++ pm_runtime_set_suspended(&pci->dev);
++ pm_runtime_enable(&pci->dev);
++ }
+ }
+
+ if (bus->chip_init) {
+--
+2.39.5
+
--- /dev/null
+From e56e4f1c1f9ab161e79668c451892b5b3780605e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Mar 2025 23:16:17 +0100
+Subject: ALSA: usb-audio: Fix CME quirk for UF series keyboards
+
+From: Ricard Wanderlof <ricard2013@butoba.net>
+
+[ Upstream commit c2820405ba55a38932aa2177f026b70064296663 ]
+
+Fix quirk for CME master keyboards so it not only handles
+sysex but also song position pointer, MIDI timing clock, start
+and stop messages, and active sensing. All of these can be
+output by the CME UF series master keyboards.
+
+Tested with a CME UF6 in a desktop Linux environment as
+well as on the Zynthian Raspberry Pi based platform.
+
+Signed-off-by: Ricard Wanderlof <ricard2013@butoba.net>
+Link: https://patch.msgid.link/20250313-cme-fix-v1-1-d404889e4de8@butoba.net
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/midi.c | 80 ++++++++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 74 insertions(+), 6 deletions(-)
+
+diff --git a/sound/usb/midi.c b/sound/usb/midi.c
+index 779d97d31f170..826ac870f2469 100644
+--- a/sound/usb/midi.c
++++ b/sound/usb/midi.c
+@@ -489,16 +489,84 @@ static void ch345_broken_sysex_input(struct snd_usb_midi_in_endpoint *ep,
+
+ /*
+ * CME protocol: like the standard protocol, but SysEx commands are sent as a
+- * single USB packet preceded by a 0x0F byte.
++ * single USB packet preceded by a 0x0F byte, as are system realtime
++ * messages and MIDI Active Sensing.
++ * Also, multiple messages can be sent in the same packet.
+ */
+ static void snd_usbmidi_cme_input(struct snd_usb_midi_in_endpoint *ep,
+ uint8_t *buffer, int buffer_length)
+ {
+- if (buffer_length < 2 || (buffer[0] & 0x0f) != 0x0f)
+- snd_usbmidi_standard_input(ep, buffer, buffer_length);
+- else
+- snd_usbmidi_input_data(ep, buffer[0] >> 4,
+- &buffer[1], buffer_length - 1);
++ int remaining = buffer_length;
++
++ /*
++ * CME send sysex, song position pointer, system realtime
++ * and active sensing using CIN 0x0f, which in the standard
++ * is only intended for single byte unparsed data.
++ * So we need to interpret these here before sending them on.
++ * By default, we assume single byte data, which is true
++ * for system realtime (midi clock, start, stop and continue)
++ * and active sensing, and handle the other (known) cases
++ * separately.
++ * In contrast to the standard, CME does not split sysex
++ * into multiple 4-byte packets, but lumps everything together
++ * into one. In addition, CME can string multiple messages
++ * together in the same packet; pressing the Record button
++ * on an UF6 sends a sysex message directly followed
++ * by a song position pointer in the same packet.
++ * For it to have any reasonable meaning, a sysex message
++ * needs to be at least 3 bytes in length (0xf0, id, 0xf7),
++ * corresponding to a packet size of 4 bytes, and the ones sent
++ * by CME devices are 6 or 7 bytes, making the packet fragments
++ * 7 or 8 bytes long (six or seven bytes plus preceding CN+CIN byte).
++ * For the other types, the packet size is always 4 bytes,
++ * as per the standard, with the data size being 3 for SPP
++ * and 1 for the others.
++ * Thus all packet fragments are at least 4 bytes long, so we can
++ * skip anything that is shorter; this also conveniantly skips
++ * packets with size 0, which CME devices continuously send when
++ * they have nothing better to do.
++ * Another quirk is that sometimes multiple messages are sent
++ * in the same packet. This has been observed for midi clock
++ * and active sensing i.e. 0x0f 0xf8 0x00 0x00 0x0f 0xfe 0x00 0x00,
++ * but also multiple note ons/offs, and control change together
++ * with MIDI clock. Similarly, some sysex messages are followed by
++ * the song position pointer in the same packet, and occasionally
++ * additionally by a midi clock or active sensing.
++ * We handle this by looping over all data and parsing it along the way.
++ */
++ while (remaining >= 4) {
++ int source_length = 4; /* default */
++
++ if ((buffer[0] & 0x0f) == 0x0f) {
++ int data_length = 1; /* default */
++
++ if (buffer[1] == 0xf0) {
++ /* Sysex: Find EOX and send on whole message. */
++ /* To kick off the search, skip the first
++ * two bytes (CN+CIN and SYSEX (0xf0).
++ */
++ uint8_t *tmp_buf = buffer + 2;
++ int tmp_length = remaining - 2;
++
++ while (tmp_length > 1 && *tmp_buf != 0xf7) {
++ tmp_buf++;
++ tmp_length--;
++ }
++ data_length = tmp_buf - buffer;
++ source_length = data_length + 1;
++ } else if (buffer[1] == 0xf2) {
++ /* Three byte song position pointer */
++ data_length = 3;
++ }
++ snd_usbmidi_input_data(ep, buffer[0] >> 4,
++ &buffer[1], data_length);
++ } else {
++ /* normal channel events */
++ snd_usbmidi_standard_input(ep, buffer, source_length);
++ }
++ buffer += source_length;
++ remaining -= source_length;
++ }
+ }
+
+ /*
+--
+2.39.5
+
--- /dev/null
+From c3d43f4b8b4197b3d080f69ddb1928ab5e947f11 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Dec 2024 13:11:09 -0800
+Subject: arm64: cputype: Add QCOM_CPU_PART_KRYO_3XX_GOLD
+
+From: Douglas Anderson <dianders@chromium.org>
+
+[ Upstream commit 401c3333bb2396aa52e4121887a6f6a6e2f040bc ]
+
+Add a definition for the Qualcomm Kryo 300-series Gold cores.
+
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Douglas Anderson <dianders@chromium.org>
+Acked-by: Trilok Soni <quic_tsoni@quicinc.com>
+Link: https://lore.kernel.org/r/20241219131107.v3.1.I18e0288742871393228249a768e5d56ea65d93dc@changeid
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/cputype.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
+index 488f8e7513495..c8058f91a5bd3 100644
+--- a/arch/arm64/include/asm/cputype.h
++++ b/arch/arm64/include/asm/cputype.h
+@@ -119,6 +119,7 @@
+ #define QCOM_CPU_PART_KRYO 0x200
+ #define QCOM_CPU_PART_KRYO_2XX_GOLD 0x800
+ #define QCOM_CPU_PART_KRYO_2XX_SILVER 0x801
++#define QCOM_CPU_PART_KRYO_3XX_GOLD 0x802
+ #define QCOM_CPU_PART_KRYO_3XX_SILVER 0x803
+ #define QCOM_CPU_PART_KRYO_4XX_GOLD 0x804
+ #define QCOM_CPU_PART_KRYO_4XX_SILVER 0x805
+@@ -195,6 +196,7 @@
+ #define MIDR_QCOM_KRYO MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO)
+ #define MIDR_QCOM_KRYO_2XX_GOLD MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_2XX_GOLD)
+ #define MIDR_QCOM_KRYO_2XX_SILVER MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_2XX_SILVER)
++#define MIDR_QCOM_KRYO_3XX_GOLD MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_3XX_GOLD)
+ #define MIDR_QCOM_KRYO_3XX_SILVER MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_3XX_SILVER)
+ #define MIDR_QCOM_KRYO_4XX_GOLD MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_4XX_GOLD)
+ #define MIDR_QCOM_KRYO_4XX_SILVER MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_4XX_SILVER)
+--
+2.39.5
+
--- /dev/null
+From 2819239df000651b10b882b9e7824b0a2ba588d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Mar 2025 19:16:17 +0800
+Subject: ASoC: amd: Add DMI quirk for ACP6X mic support
+
+From: keenplify <keenplify@gmail.com>
+
+[ Upstream commit 309b367eafc8e162603cd29189da6db770411fea ]
+
+Some AMD laptops with ACP6X do not expose the DMIC properly on Linux.
+Adding a DMI quirk enables mic functionality.
+
+Similar to Bugzilla #218402, this issue affects multiple users.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=219853
+Signed-off-by: keenplify <keenplify@gmail.com>
+Link: https://patch.msgid.link/20250315111617.12194-1-keenplify@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/amd/yc/acp6x-mach.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
+index a7637056972aa..bd3808f98ec9e 100644
+--- a/sound/soc/amd/yc/acp6x-mach.c
++++ b/sound/soc/amd/yc/acp6x-mach.c
+@@ -584,6 +584,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
+ DMI_MATCH(DMI_PRODUCT_VERSION, "pang13"),
+ }
+ },
++ {
++ .driver_data = &acp6x_card,
++ .matches = {
++ DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."),
++ DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 15 C7UCX"),
++ }
++ },
+ {}
+ };
+
+--
+2.39.5
+
--- /dev/null
+From 47af861c765b09e8bd0456ff68ea379b7998d388 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Feb 2025 11:57:56 +0530
+Subject: ASoC: amd: ps: use macro for ACP6.3 pci revision id
+
+From: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
+
+[ Upstream commit 4b36a47e2d989b98953dbfb1e97da0f0169f5086 ]
+
+Use macro for ACP6.3 PCI revision id instead of hard coded value.
+
+Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
+Link: https://patch.msgid.link/20250207062819.1527184-3-Vijendar.Mukunda@amd.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/amd/ps/acp63.h | 1 +
+ sound/soc/amd/ps/pci-ps.c | 2 +-
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h
+index 39208305dd6c3..f9759c9342cf3 100644
+--- a/sound/soc/amd/ps/acp63.h
++++ b/sound/soc/amd/ps/acp63.h
+@@ -11,6 +11,7 @@
+ #define ACP_DEVICE_ID 0x15E2
+ #define ACP63_REG_START 0x1240000
+ #define ACP63_REG_END 0x125C000
++#define ACP63_PCI_REV 0x63
+
+ #define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001
+ #define ACP_PGFSM_CNTL_POWER_ON_MASK 1
+diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c
+index 5c4a0be7a7889..aec3150ecf581 100644
+--- a/sound/soc/amd/ps/pci-ps.c
++++ b/sound/soc/amd/ps/pci-ps.c
+@@ -559,7 +559,7 @@ static int snd_acp63_probe(struct pci_dev *pci,
+
+ /* Pink Sardine device check */
+ switch (pci->revision) {
+- case 0x63:
++ case ACP63_PCI_REV:
+ break;
+ default:
+ dev_dbg(&pci->dev, "acp63 pci device not found\n");
+--
+2.39.5
+
--- /dev/null
+From b28ce9b49d2d784ca232454cf8270caa40ee162d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Mar 2025 17:55:03 +0530
+Subject: ASoC: amd: yc: update quirk data for new Lenovo model
+
+From: Syed Saba kareem <syed.sabakareem@amd.com>
+
+[ Upstream commit 5a4dd520ef8a94ecf81ac77b90d6a03e91c100a9 ]
+
+Update Quirk data for new Lenovo model 83J2 for YC platform.
+
+Signed-off-by: Syed Saba kareem <syed.sabakareem@amd.com>
+Link: https://patch.msgid.link/20250321122507.190193-1-syed.sabakareem@amd.com
+Reported-by: Reiner <Reiner.Proels@gmail.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219887
+Tested-by: Reiner <Reiner.Proels@gmail.com>
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/amd/yc/acp6x-mach.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
+index bd3808f98ec9e..e632f16c91025 100644
+--- a/sound/soc/amd/yc/acp6x-mach.c
++++ b/sound/soc/amd/yc/acp6x-mach.c
+@@ -339,6 +339,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "83Q3"),
+ }
+ },
++ {
++ .driver_data = &acp6x_card,
++ .matches = {
++ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "83J2"),
++ }
++ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+--
+2.39.5
+
--- /dev/null
+From 06dac7db65cd40a8c9eff2d86a99d7aeb9a41564 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Feb 2025 18:05:08 +0800
+Subject: ASoC: fsl_audmix: register card device depends on 'dais' property
+
+From: Shengjiu Wang <shengjiu.wang@nxp.com>
+
+[ Upstream commit 294a60e5e9830045c161181286d44ce669f88833 ]
+
+In order to make the audmix device linked by audio graph card, make
+'dais' property to be optional.
+
+If 'dais' property exists, then register the imx-audmix card driver.
+otherwise, it should be linked by audio graph card.
+
+Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
+Link: https://patch.msgid.link/20250226100508.2352568-5-shengjiu.wang@nxp.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/fsl/fsl_audmix.c | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c
+index 3cd9a66b70a15..7981d598ba139 100644
+--- a/sound/soc/fsl/fsl_audmix.c
++++ b/sound/soc/fsl/fsl_audmix.c
+@@ -488,11 +488,17 @@ static int fsl_audmix_probe(struct platform_device *pdev)
+ goto err_disable_pm;
+ }
+
+- priv->pdev = platform_device_register_data(dev, "imx-audmix", 0, NULL, 0);
+- if (IS_ERR(priv->pdev)) {
+- ret = PTR_ERR(priv->pdev);
+- dev_err(dev, "failed to register platform: %d\n", ret);
+- goto err_disable_pm;
++ /*
++ * If dais property exist, then register the imx-audmix card driver.
++ * otherwise, it should be linked by audio graph card.
++ */
++ if (of_find_property(pdev->dev.of_node, "dais", NULL)) {
++ priv->pdev = platform_device_register_data(dev, "imx-audmix", 0, NULL, 0);
++ if (IS_ERR(priv->pdev)) {
++ ret = PTR_ERR(priv->pdev);
++ dev_err(dev, "failed to register platform: %d\n", ret);
++ goto err_disable_pm;
++ }
+ }
+
+ return 0;
+--
+2.39.5
+
--- /dev/null
+From 0c7f2dd9bc17413231660a860dad5f7ee37e127a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Jan 2025 09:43:43 +0800
+Subject: ASoC: SOF: topology: Use krealloc_array() to replace krealloc()
+
+From: Zhang Heng <zhangheng@kylinos.cn>
+
+[ Upstream commit a05143a8f713d9ae6abc41141dac52c66fca8b06 ]
+
+Use krealloc_array() to replace krealloc() with multiplication.
+krealloc_array() has multiply overflow check, which will be safer.
+
+Signed-off-by: Zhang Heng <zhangheng@kylinos.cn>
+Link: https://patch.msgid.link/20250117014343.451503-1-zhangheng@kylinos.cn
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/sof/topology.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
+index b3fca5fd87d68..37ca15cc5728c 100644
+--- a/sound/soc/sof/topology.c
++++ b/sound/soc/sof/topology.c
+@@ -1269,8 +1269,8 @@ static int sof_widget_parse_tokens(struct snd_soc_component *scomp, struct snd_s
+ struct snd_sof_tuple *new_tuples;
+
+ num_tuples += token_list[object_token_list[i]].count * (num_sets - 1);
+- new_tuples = krealloc(swidget->tuples,
+- sizeof(*new_tuples) * num_tuples, GFP_KERNEL);
++ new_tuples = krealloc_array(swidget->tuples,
++ num_tuples, sizeof(*new_tuples), GFP_KERNEL);
+ if (!new_tuples) {
+ ret = -ENOMEM;
+ goto err;
+--
+2.39.5
+
--- /dev/null
+From 52da0d3f5cd99d73192480ef67d8b9b1ece9b7b8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jan 2025 14:35:46 +0100
+Subject: ata: libata-core: Add 'external' to the libata.force kernel parameter
+
+From: Niklas Cassel <cassel@kernel.org>
+
+[ Upstream commit deca423213cb33feda15e261e7b5b992077a6a08 ]
+
+Commit ae1f3db006b7 ("ata: ahci: do not enable LPM on external ports")
+changed so that LPM is not enabled on external ports (hotplug-capable or
+eSATA ports).
+
+This is because hotplug and LPM are mutually exclusive, see 7.3.1 Hot Plug
+Removal Detection and Power Management Interaction in AHCI 1.3.1.
+
+This does require that firmware has set the appropate bits (HPCP or ESP)
+in PxCMD (which is a per port register in the AHCI controller).
+
+If the firmware has failed to mark a port as hotplug-capable or eSATA in
+PxCMD, then there is currently not much a user can do.
+
+If LPM is enabled on the port, hotplug insertions and removals will not be
+detected on that port.
+
+In order to allow a user to fix up broken firmware, add 'external' to the
+libata.force kernel parameter.
+
+libata.force can be specified either on the kernel command line, or as a
+kernel module parameter.
+
+For more information, see Documentation/admin-guide/kernel-parameters.txt.
+
+Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
+Link: https://lore.kernel.org/r/20250130133544.219297-4-cassel@kernel.org
+Signed-off-by: Niklas Cassel <cassel@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../admin-guide/kernel-parameters.txt | 2 +
+ drivers/ata/libata-core.c | 38 +++++++++++++++++++
+ 2 files changed, 40 insertions(+)
+
+diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
+index d401577b5a6ac..607a8937f1754 100644
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -3028,6 +3028,8 @@
+ * max_sec_lba48: Set or clear transfer size limit to
+ 65535 sectors.
+
++ * external: Mark port as external (hotplug-capable).
++
+ * [no]lpm: Enable or disable link power management.
+
+ * [no]setxfer: Indicate if transfer speed mode setting
+diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
+index d956735e2a764..0cb97181d10a9 100644
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -88,6 +88,7 @@ struct ata_force_param {
+ unsigned int xfer_mask;
+ unsigned int quirk_on;
+ unsigned int quirk_off;
++ unsigned int pflags_on;
+ u16 lflags_on;
+ u16 lflags_off;
+ };
+@@ -331,6 +332,35 @@ void ata_force_cbl(struct ata_port *ap)
+ }
+ }
+
++/**
++ * ata_force_pflags - force port flags according to libata.force
++ * @ap: ATA port of interest
++ *
++ * Force port flags according to libata.force and whine about it.
++ *
++ * LOCKING:
++ * EH context.
++ */
++static void ata_force_pflags(struct ata_port *ap)
++{
++ int i;
++
++ for (i = ata_force_tbl_size - 1; i >= 0; i--) {
++ const struct ata_force_ent *fe = &ata_force_tbl[i];
++
++ if (fe->port != -1 && fe->port != ap->print_id)
++ continue;
++
++ /* let pflags stack */
++ if (fe->param.pflags_on) {
++ ap->pflags |= fe->param.pflags_on;
++ ata_port_notice(ap,
++ "FORCE: port flag 0x%x forced -> 0x%x\n",
++ fe->param.pflags_on, ap->pflags);
++ }
++ }
++}
++
+ /**
+ * ata_force_link_limits - force link limits according to libata.force
+ * @link: ATA link of interest
+@@ -486,6 +516,7 @@ static void ata_force_quirks(struct ata_device *dev)
+ }
+ }
+ #else
++static inline void ata_force_pflags(struct ata_port *ap) { }
+ static inline void ata_force_link_limits(struct ata_link *link) { }
+ static inline void ata_force_xfermask(struct ata_device *dev) { }
+ static inline void ata_force_quirks(struct ata_device *dev) { }
+@@ -5460,6 +5491,8 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
+ #endif
+ ata_sff_port_init(ap);
+
++ ata_force_pflags(ap);
++
+ return ap;
+ }
+ EXPORT_SYMBOL_GPL(ata_port_alloc);
+@@ -6272,6 +6305,9 @@ EXPORT_SYMBOL_GPL(ata_platform_remove_one);
+ { "no" #name, .lflags_on = (flags) }, \
+ { #name, .lflags_off = (flags) }
+
++#define force_pflag_on(name, flags) \
++ { #name, .pflags_on = (flags) }
++
+ #define force_quirk_on(name, flag) \
+ { #name, .quirk_on = (flag) }
+
+@@ -6331,6 +6367,8 @@ static const struct ata_force_param force_tbl[] __initconst = {
+ force_lflag_on(rstonce, ATA_LFLAG_RST_ONCE),
+ force_lflag_onoff(dbdelay, ATA_LFLAG_NO_DEBOUNCE_DELAY),
+
++ force_pflag_on(external, ATA_PFLAG_EXTERNAL),
++
+ force_quirk_onoff(ncq, ATA_QUIRK_NONCQ),
+ force_quirk_onoff(ncqtrim, ATA_QUIRK_NO_NCQ_TRIM),
+ force_quirk_onoff(ncqati, ATA_QUIRK_NO_NCQ_ON_ATI),
+--
+2.39.5
+
--- /dev/null
+From dcf106aa7259f1a376f85540ca0042dfc80e9947 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Feb 2025 02:54:23 +0100
+Subject: ata: libata-eh: Do not use ATAPI DMA for a device limited to PIO mode
+
+From: Niklas Cassel <cassel@kernel.org>
+
+[ Upstream commit 91ec84f8eaddbc93d7c62e363d68aeb7b89879c7 ]
+
+atapi_eh_request_sense() currently uses ATAPI DMA if the SATA controller
+has ATA_FLAG_PIO_DMA (PIO cmds via DMA) set.
+
+However, ATA_FLAG_PIO_DMA is a flag that can be set by a low-level driver
+on a port at initialization time, before any devices are scanned.
+
+If a controller detects a connected device that only supports PIO, we set
+the flag ATA_DFLAG_PIO.
+
+Modify atapi_eh_request_sense() to not use ATAPI DMA if the connected
+device only supports PIO.
+
+Reported-by: Philip Pemberton <lists@philpem.me.uk>
+Closes: https://lore.kernel.org/linux-ide/c6722ee8-5e21-4169-af59-cbbae9edc02f@philpem.me.uk/
+Tested-by: Philip Pemberton <lists@philpem.me.uk>
+Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
+Link: https://lore.kernel.org/r/20250221015422.20687-2-cassel@kernel.org
+Signed-off-by: Niklas Cassel <cassel@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/libata-eh.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
+index 3b303d4ae37a0..16cd676eae1f9 100644
+--- a/drivers/ata/libata-eh.c
++++ b/drivers/ata/libata-eh.c
+@@ -1542,8 +1542,15 @@ unsigned int atapi_eh_request_sense(struct ata_device *dev,
+ tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+ tf.command = ATA_CMD_PACKET;
+
+- /* is it pointless to prefer PIO for "safety reasons"? */
+- if (ap->flags & ATA_FLAG_PIO_DMA) {
++ /*
++ * Do not use DMA if the connected device only supports PIO, even if the
++ * port prefers PIO commands via DMA.
++ *
++ * Ideally, we should call atapi_check_dma() to check if it is safe for
++ * the LLD to use DMA for REQUEST_SENSE, but we don't have a qc.
++ * Since we can't check the command, perhaps we should only use pio?
++ */
++ if ((ap->flags & ATA_FLAG_PIO_DMA) && !(dev->flags & ATA_DFLAG_PIO)) {
+ tf.protocol = ATAPI_PROT_DMA;
+ tf.feature |= ATAPI_PKT_DMA;
+ } else {
+--
+2.39.5
+
--- /dev/null
+From c24b9b2b48b3a3034eecb12f58e6b8b3a817903a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Mar 2025 03:22:59 -0300
+Subject: Bluetooth: Add quirk for broken READ_PAGE_SCAN_TYPE
+
+From: Pedro Nishiyama <nishiyama.pedro@gmail.com>
+
+[ Upstream commit 127881334eaad639e0a19a399ee8c91d6c9dc982 ]
+
+Some fake controllers cannot be initialized because they return a smaller
+report than expected for READ_PAGE_SCAN_TYPE.
+
+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>
+---
+ include/net/bluetooth/hci.h | 8 ++++++++
+ net/bluetooth/hci_sync.c | 3 ++-
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
+index fa6f92915968f..71d2432876406 100644
+--- a/include/net/bluetooth/hci.h
++++ b/include/net/bluetooth/hci.h
+@@ -361,6 +361,14 @@ enum {
+ * This quirk must be set before hci_register_dev is called.
+ */
+ HCI_QUIRK_BROKEN_READ_VOICE_SETTING,
++
++ /* When this quirk is set, the HCI_OP_READ_PAGE_SCAN_TYPE command is
++ * skipped. This is required for a subset of the CSR controller clones
++ * which erroneously claim to support it.
++ *
++ * This quirk must be set before hci_register_dev is called.
++ */
++ HCI_QUIRK_BROKEN_READ_PAGE_SCAN_TYPE,
+ };
+
+ /* HCI device flags */
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index bb455e96a715a..cb4d47ae129e8 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -4156,7 +4156,8 @@ static int hci_read_page_scan_type_sync(struct hci_dev *hdev)
+ * support the Read Page Scan Type command. Check support for
+ * this command in the bit mask of supported commands.
+ */
+- if (!(hdev->commands[13] & 0x01))
++ if (!(hdev->commands[13] & 0x01) ||
++ test_bit(HCI_QUIRK_BROKEN_READ_PAGE_SCAN_TYPE, &hdev->quirks))
+ return 0;
+
+ return __hci_cmd_sync_status(hdev, HCI_OP_READ_PAGE_SCAN_TYPE,
+--
+2.39.5
+
--- /dev/null
+From 02e673bd1806c4237a811969330635cc7e360160 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Mar 2025 03:22:58 -0300
+Subject: Bluetooth: Add quirk for broken READ_VOICE_SETTING
+
+From: Pedro Nishiyama <nishiyama.pedro@gmail.com>
+
+[ Upstream commit ff26b2dd6568392f60fa67a4e58279938025c3af ]
+
+Some fake controllers cannot be initialized because they return a smaller
+report than expected for READ_VOICE_SETTING.
+
+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>
+---
+ include/net/bluetooth/hci.h | 8 ++++++++
+ include/net/bluetooth/hci_core.h | 4 ++++
+ net/bluetooth/hci_sync.c | 3 +++
+ 3 files changed, 15 insertions(+)
+
+diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
+index dd10e02bfc746..fa6f92915968f 100644
+--- a/include/net/bluetooth/hci.h
++++ b/include/net/bluetooth/hci.h
+@@ -353,6 +353,14 @@ enum {
+ * during the hdev->setup vendor callback.
+ */
+ HCI_QUIRK_FIXUP_LE_EXT_ADV_REPORT_PHY,
++
++ /* When this quirk is set, the HCI_OP_READ_VOICE_SETTING command is
++ * skipped. This is required for a subset of the CSR controller clones
++ * which erroneously claim to support it.
++ *
++ * This quirk must be set before hci_register_dev is called.
++ */
++ HCI_QUIRK_BROKEN_READ_VOICE_SETTING,
+ };
+
+ /* HCI device flags */
+diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
+index c95f7e6ba2551..4245910ffc4a2 100644
+--- a/include/net/bluetooth/hci_core.h
++++ b/include/net/bluetooth/hci_core.h
+@@ -1921,6 +1921,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
+ ((dev)->commands[20] & 0x10 && \
+ !test_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks))
+
++#define read_voice_setting_capable(dev) \
++ ((dev)->commands[9] & 0x04 && \
++ !test_bit(HCI_QUIRK_BROKEN_READ_VOICE_SETTING, &(dev)->quirks))
++
+ /* Use enhanced synchronous connection if command is supported and its quirk
+ * has not been set.
+ */
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index 7b2b04d6b8563..bb455e96a715a 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -3720,6 +3720,9 @@ static int hci_read_local_name_sync(struct hci_dev *hdev)
+ /* Read Voice Setting */
+ static int hci_read_voice_setting_sync(struct hci_dev *hdev)
+ {
++ if (!read_voice_setting_capable(hdev))
++ return 0;
++
+ return __hci_cmd_sync_status(hdev, HCI_OP_READ_VOICE_SETTING,
+ 0, NULL, HCI_CMD_TIMEOUT);
+ }
+--
+2.39.5
+
--- /dev/null
+From 437cd6ee79dca4239c1b47f69d0a7eb5ca3ba926 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jan 2025 17:07:09 +0530
+Subject: Bluetooth: btintel_pcie: Add device id of Whale Peak
+
+From: Kiran K <kiran.k@intel.com>
+
+[ Upstream commit 6b8c05e52d66e4fe4ab1df4c6e15f339ecd9aa51 ]
+
+Add device of Whale Peak.
+
+Output of sudo lspci -v -s 00:14.7:
+
+00:14.7 Bluetooth: Intel Corporation Device e476
+ Subsystem: Intel Corporation Device 0011
+ Flags: bus master, fast devsel, latency 0, IRQ 16, IOMMU group 11
+ Memory at 11011c30000 (64-bit, non-prefetchable) [size=16K]
+ Capabilities: [c8] Power Management version 3
+ Capabilities: [d0] MSI: Enable- Count=1/1 Maskable- 64bit+
+ Capabilities: [40] Express Root Complex Integrated Endpoint, MSI 00
+ Capabilities: [80] MSI-X: Enable+ Count=32 Masked-
+ Capabilities: [100] Latency Tolerance Reporting
+ Kernel driver in use: btintel_pcie
+ Kernel modules: btintel_pcie
+
+Signed-off-by: Kiran K <kiran.k@intel.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btintel_pcie.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
+index 53f6b4f76bccd..ab465e13c1f60 100644
+--- a/drivers/bluetooth/btintel_pcie.c
++++ b/drivers/bluetooth/btintel_pcie.c
+@@ -36,6 +36,7 @@
+ /* Intel Bluetooth PCIe device id table */
+ static const struct pci_device_id btintel_pcie_table[] = {
+ { BTINTEL_PCI_DEVICE(0xA876, PCI_ANY_ID) },
++ { BTINTEL_PCI_DEVICE(0xE476, PCI_ANY_ID) },
+ { 0 }
+ };
+ MODULE_DEVICE_TABLE(pci, btintel_pcie_table);
+--
+2.39.5
+
--- /dev/null
+From 6a45026436fa7fb6285c5f48badc73ecc122bef4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 10:01:28 +0800
+Subject: Bluetooth: btusb: Add 2 HWIDs for MT7922
+
+From: Jiande Lu <jiande.lu@mediatek.com>
+
+[ Upstream commit a88643b7e48506777e175e80c902c727ddd90851 ]
+
+Add below HWIDs for MediaTek MT7922 USB Bluetooth chip.
+VID 0x0489, PID 0xe152
+VID 0x0489, PID 0xe153
+
+Patch has been tested successfully and controller is recognized
+device pair successfully.
+
+MT7922 module bring up message as below.
+Bluetooth: Core ver 2.22
+Bluetooth: HCI device and connection manager initialized
+Bluetooth: HCI socket layer initialized
+Bluetooth: L2CAP socket layer initialized
+Bluetooth: SCO socket layer initialized
+Bluetooth: hci0: HW/SW Version: 0x008a008a, Build Time: 20241106163512
+Bluetooth: hci0: Device setup in 2284925 usecs
+Bluetooth: hci0: HCI Enhanced Setup Synchronous Connection command is advertised, but not supported.
+Bluetooth: hci0: AOSP extensions version v1.00
+Bluetooth: BNEP (Ethernet Emulation) ver 1.3
+Bluetooth: BNEP filters: protocol multicast
+Bluetooth: BNEP socket layer initialized
+Bluetooth: MGMT ver 1.22
+Bluetooth: RFCOMM TTY layer initialized
+Bluetooth: RFCOMM socket layer initialized
+Bluetooth: RFCOMM ver 1.11
+
+Signed-off-by: Jiande Lu <jiande.lu@mediatek.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btusb.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
+index 3a0b9dc98707f..151054a718522 100644
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -626,6 +626,10 @@ static const struct usb_device_id quirks_table[] = {
+ BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x0489, 0xe102), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH },
++ { USB_DEVICE(0x0489, 0xe152), .driver_info = BTUSB_MEDIATEK |
++ BTUSB_WIDEBAND_SPEECH },
++ { USB_DEVICE(0x0489, 0xe153), .driver_info = BTUSB_MEDIATEK |
++ BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x04ca, 0x3804), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x04ca, 0x38e4), .driver_info = BTUSB_MEDIATEK |
+--
+2.39.5
+
--- /dev/null
+From 2f4ca7d592055446cf11e8f8bc79c6223c79cb44 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 16:59:45 +0530
+Subject: Bluetooth: hci_qca: use the power sequencer for wcn6750
+
+From: Janaki Ramaiah Thota <quic_janathot@quicinc.com>
+
+[ Upstream commit 852cfdc7a5a5af54358325c1e0f490cc178d9664 ]
+
+Older boards are having entry "enable-gpios" in dts, we can safely assume
+latest boards which are supporting PMU node enrty will support power
+sequencer.
+
+Signed-off-by: Janaki Ramaiah Thota <quic_janathot@quicinc.com>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/hci_qca.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
+index 37fddf6055beb..1837622ea625a 100644
+--- a/drivers/bluetooth/hci_qca.c
++++ b/drivers/bluetooth/hci_qca.c
+@@ -2353,6 +2353,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)
+ switch (qcadev->btsoc_type) {
+ case QCA_WCN6855:
+ case QCA_WCN7850:
++ case QCA_WCN6750:
+ if (!device_property_present(&serdev->dev, "enable-gpios")) {
+ /*
+ * Backward compatibility with old DT sources. If the
+@@ -2372,7 +2373,6 @@ static int qca_serdev_probe(struct serdev_device *serdev)
+ case QCA_WCN3990:
+ case QCA_WCN3991:
+ case QCA_WCN3998:
+- case QCA_WCN6750:
+ qcadev->bt_power->dev = &serdev->dev;
+ err = qca_init_regulators(qcadev->bt_power, data->vregs,
+ data->num_vregs);
+--
+2.39.5
+
--- /dev/null
+From b4b44e51b64dbfe7209c3694168138ad35acd880 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jan 2025 21:43:26 +0300
+Subject: Bluetooth: hci_uart: fix race during initialization
+
+From: Arseniy Krasnov <avkrasnov@salutedevices.com>
+
+[ Upstream commit 366ceff495f902182d42b6f41525c2474caf3f9a ]
+
+'hci_register_dev()' calls power up function, which is executed by
+kworker - 'hci_power_on()'. This function does access to bluetooth chip
+using callbacks from 'hci_ldisc.c', for example 'hci_uart_send_frame()'.
+Now 'hci_uart_send_frame()' checks 'HCI_UART_PROTO_READY' bit set, and
+if not - it fails. Problem is that 'HCI_UART_PROTO_READY' is set after
+'hci_register_dev()', and there is tiny chance that 'hci_power_on()' will
+be executed before setting this bit. In that case HCI init logic fails.
+
+Patch moves setting of 'HCI_UART_PROTO_READY' before calling function
+'hci_uart_register_dev()'.
+
+Signed-off-by: Arseniy Krasnov <avkrasnov@salutedevices.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/hci_ldisc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
+index 395d66e32a2ea..2651e2e33f2a1 100644
+--- a/drivers/bluetooth/hci_ldisc.c
++++ b/drivers/bluetooth/hci_ldisc.c
+@@ -707,12 +707,13 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
+
+ hu->proto = p;
+
++ set_bit(HCI_UART_PROTO_READY, &hu->flags);
++
+ err = hci_uart_register_dev(hu);
+ if (err) {
+ return err;
+ }
+
+- set_bit(HCI_UART_PROTO_READY, &hu->flags);
+ return 0;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From f573e88d0297bb36cee82e13a4601bc52c98fd58 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Feb 2025 22:41:16 +0200
+Subject: Bluetooth: qca: simplify WCN399x NVM loading
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit 1cc41b5092e3aa511454ec882c525af311bee631 ]
+
+The WCN399x code has two separate cases for loading the NVM data. In
+preparation to adding support for WCN3950, which also requires similar
+quirk, split the "variant" to be specified explicitly and merge two
+snprintfs into a single one.
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btqca.c | 13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
+index 04d02c746ec0f..dd2c0485b9848 100644
+--- a/drivers/bluetooth/btqca.c
++++ b/drivers/bluetooth/btqca.c
+@@ -785,6 +785,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
+ const char *firmware_name)
+ {
+ struct qca_fw_config config = {};
++ const char *variant = "";
+ int err;
+ u8 rom_ver = 0;
+ u32 soc_ver;
+@@ -879,13 +880,11 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
+ case QCA_WCN3990:
+ case QCA_WCN3991:
+ case QCA_WCN3998:
+- if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID) {
+- snprintf(config.fwname, sizeof(config.fwname),
+- "qca/crnv%02xu.bin", rom_ver);
+- } else {
+- snprintf(config.fwname, sizeof(config.fwname),
+- "qca/crnv%02x.bin", rom_ver);
+- }
++ if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID)
++ variant = "u";
++
++ snprintf(config.fwname, sizeof(config.fwname),
++ "qca/crnv%02x%s.bin", rom_ver, variant);
+ break;
+ case QCA_WCN3988:
+ snprintf(config.fwname, sizeof(config.fwname),
+--
+2.39.5
+
--- /dev/null
+From b8ee837427ae336c2c242b826ea0b02078b06a25 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Mar 2025 15:16:57 -0800
+Subject: btrfs: harden block_group::bg_list against list_del() races
+
+From: Boris Burkov <boris@bur.io>
+
+[ Upstream commit 7511e29cf1355b2c47d0effb39e463119913e2f6 ]
+
+As far as I can tell, these calls of list_del_init() on bg_list cannot
+run concurrently with btrfs_mark_bg_unused() or btrfs_mark_bg_to_reclaim(),
+as they are in transaction error paths and situations where the block
+group is readonly.
+
+However, if there is any chance at all of racing with mark_bg_unused(),
+or a different future user of bg_list, better to be safe than sorry.
+
+Otherwise we risk the following interleaving (bg_list refcount in parens)
+
+T1 (some random op) T2 (btrfs_mark_bg_unused)
+ !list_empty(&bg->bg_list); (1)
+list_del_init(&bg->bg_list); (1)
+ list_move_tail (1)
+btrfs_put_block_group (0)
+ btrfs_delete_unused_bgs
+ bg = list_first_entry
+ list_del_init(&bg->bg_list);
+ btrfs_put_block_group(bg); (-1)
+
+Ultimately, this results in a broken ref count that hits zero one deref
+early and the real final deref underflows the refcount, resulting in a WARNING.
+
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Reviewed-by: Filipe Manana <fdmanana@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-tree.c | 8 ++++++++
+ fs/btrfs/transaction.c | 12 ++++++++++++
+ 2 files changed, 20 insertions(+)
+
+diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
+index f3e93ba7ec97f..4ceffbef32987 100644
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -2897,7 +2897,15 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans)
+ block_group->length,
+ &trimmed);
+
++ /*
++ * Not strictly necessary to lock, as the block_group should be
++ * read-only from btrfs_delete_unused_bgs().
++ */
++ ASSERT(block_group->ro);
++ spin_lock(&fs_info->unused_bgs_lock);
+ list_del_init(&block_group->bg_list);
++ spin_unlock(&fs_info->unused_bgs_lock);
++
+ btrfs_unfreeze_block_group(block_group);
+ btrfs_put_block_group(block_group);
+
+diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
+index 82dd9ee89fbc5..24806e19c7c41 100644
+--- a/fs/btrfs/transaction.c
++++ b/fs/btrfs/transaction.c
+@@ -161,7 +161,13 @@ void btrfs_put_transaction(struct btrfs_transaction *transaction)
+ cache = list_first_entry(&transaction->deleted_bgs,
+ struct btrfs_block_group,
+ bg_list);
++ /*
++ * Not strictly necessary to lock, as no other task will be using a
++ * block_group on the deleted_bgs list during a transaction abort.
++ */
++ spin_lock(&transaction->fs_info->unused_bgs_lock);
+ list_del_init(&cache->bg_list);
++ spin_unlock(&transaction->fs_info->unused_bgs_lock);
+ btrfs_unfreeze_block_group(cache);
+ btrfs_put_block_group(cache);
+ }
+@@ -2099,7 +2105,13 @@ static void btrfs_cleanup_pending_block_groups(struct btrfs_trans_handle *trans)
+
+ list_for_each_entry_safe(block_group, tmp, &trans->new_bgs, bg_list) {
+ btrfs_dec_delayed_refs_rsv_bg_inserts(fs_info);
++ /*
++ * Not strictly necessary to lock, as no other task will be using a
++ * block_group on the new_bgs list during a transaction abort.
++ */
++ spin_lock(&fs_info->unused_bgs_lock);
+ list_del_init(&block_group->bg_list);
++ spin_unlock(&fs_info->unused_bgs_lock);
+ }
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 5fc07c7451dd0bec22059d06887601bbd06e5b21 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jan 2025 14:07:04 +0200
+Subject: can: flexcan: add NXP S32G2/S32G3 SoC support
+
+From: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
+
+[ Upstream commit 8503a4b1a24d32e95f3a233062e8f1dc0b2052bd ]
+
+Add device type data for S32G2/S32G3 SoC.
+
+FlexCAN module from S32G2/S32G3 is similar with i.MX SoCs, but interrupt
+management is different.
+
+On S32G2/S32G3 SoC, there are separate interrupts for state change, bus
+errors, Mailboxes 0-7 and Mailboxes 8-127 respectively.
+In order to handle this FlexCAN hardware particularity, first reuse the
+'FLEXCAN_QUIRK_NR_IRQ_3' quirk provided by mcf5441x's irq handling
+support. Secondly, use the newly introduced
+'FLEXCAN_QUIRK_SECONDARY_MB_IRQ' quirk which handles the case where two
+separate mailbox ranges are controlled by independent hardware interrupt
+lines.
+
+Signed-off-by: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
+Link: https://patch.msgid.link/20250113120704.522307-4-ciprianmarian.costea@oss.nxp.com
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/flexcan/flexcan-core.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
+index 1a94586cbd11e..fca290afb5329 100644
+--- a/drivers/net/can/flexcan/flexcan-core.c
++++ b/drivers/net/can/flexcan/flexcan-core.c
+@@ -386,6 +386,16 @@ static const struct flexcan_devtype_data fsl_lx2160a_r1_devtype_data = {
+ FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR,
+ };
+
++static const struct flexcan_devtype_data nxp_s32g2_devtype_data = {
++ .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
++ FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_BROKEN_PERR_STATE |
++ FLEXCAN_QUIRK_USE_RX_MAILBOX | FLEXCAN_QUIRK_SUPPORT_FD |
++ FLEXCAN_QUIRK_SUPPORT_ECC | FLEXCAN_QUIRK_NR_IRQ_3 |
++ FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
++ FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR |
++ FLEXCAN_QUIRK_SECONDARY_MB_IRQ,
++};
++
+ static const struct can_bittiming_const flexcan_bittiming_const = {
+ .name = DRV_NAME,
+ .tseg1_min = 4,
+@@ -2055,6 +2065,7 @@ static const struct of_device_id flexcan_of_match[] = {
+ { .compatible = "fsl,vf610-flexcan", .data = &fsl_vf610_devtype_data, },
+ { .compatible = "fsl,ls1021ar2-flexcan", .data = &fsl_ls1021a_r2_devtype_data, },
+ { .compatible = "fsl,lx2160ar1-flexcan", .data = &fsl_lx2160a_r1_devtype_data, },
++ { .compatible = "nxp,s32g2-flexcan", .data = &nxp_s32g2_devtype_data, },
+ { /* sentinel */ },
+ };
+ MODULE_DEVICE_TABLE(of, flexcan_of_match);
+--
+2.39.5
+
--- /dev/null
+From 1851ec669011dedadaa53d6acb115b6df0f2305b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jan 2025 14:07:03 +0200
+Subject: can: flexcan: Add quirk to handle separate interrupt lines for
+ mailboxes
+
+From: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
+
+[ Upstream commit 8c652cf030a769fbfc73cfc280ed3f1656343c35 ]
+
+Introduce 'FLEXCAN_QUIRK_SECONDARY_MB_IRQ' quirk to handle a FlexCAN
+hardware module integration particularity where two ranges of mailboxes
+are controlled by separate hardware interrupt lines.
+The same 'flexcan_irq' handler is used for both separate mailbox interrupt
+lines, with no other changes.
+
+Signed-off-by: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
+Reviewed-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
+Link: https://patch.msgid.link/20250113120704.522307-3-ciprianmarian.costea@oss.nxp.com
+[mkl: flexcan_open(): change order and free irq_secondary_mb first]
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/flexcan/flexcan-core.c | 24 +++++++++++++++++++++++-
+ drivers/net/can/flexcan/flexcan.h | 5 +++++
+ 2 files changed, 28 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
+index b080740bcb104..1a94586cbd11e 100644
+--- a/drivers/net/can/flexcan/flexcan-core.c
++++ b/drivers/net/can/flexcan/flexcan-core.c
+@@ -1762,14 +1762,25 @@ static int flexcan_open(struct net_device *dev)
+ goto out_free_irq_boff;
+ }
+
++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SECONDARY_MB_IRQ) {
++ err = request_irq(priv->irq_secondary_mb,
++ flexcan_irq, IRQF_SHARED, dev->name, dev);
++ if (err)
++ goto out_free_irq_err;
++ }
++
+ flexcan_chip_interrupts_enable(dev);
+
+ netif_start_queue(dev);
+
+ return 0;
+
++ out_free_irq_err:
++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3)
++ free_irq(priv->irq_err, dev);
+ out_free_irq_boff:
+- free_irq(priv->irq_boff, dev);
++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3)
++ free_irq(priv->irq_boff, dev);
+ out_free_irq:
+ free_irq(dev->irq, dev);
+ out_can_rx_offload_disable:
+@@ -1794,6 +1805,9 @@ static int flexcan_close(struct net_device *dev)
+ netif_stop_queue(dev);
+ flexcan_chip_interrupts_disable(dev);
+
++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SECONDARY_MB_IRQ)
++ free_irq(priv->irq_secondary_mb, dev);
++
+ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
+ free_irq(priv->irq_err, dev);
+ free_irq(priv->irq_boff, dev);
+@@ -2187,6 +2201,14 @@ static int flexcan_probe(struct platform_device *pdev)
+ }
+ }
+
++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SECONDARY_MB_IRQ) {
++ priv->irq_secondary_mb = platform_get_irq_byname(pdev, "mb-1");
++ if (priv->irq_secondary_mb < 0) {
++ err = priv->irq_secondary_mb;
++ goto failed_platform_get_irq;
++ }
++ }
++
+ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SUPPORT_FD) {
+ priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD |
+ CAN_CTRLMODE_FD_NON_ISO;
+diff --git a/drivers/net/can/flexcan/flexcan.h b/drivers/net/can/flexcan/flexcan.h
+index 4933d8c7439e6..2cf886618c962 100644
+--- a/drivers/net/can/flexcan/flexcan.h
++++ b/drivers/net/can/flexcan/flexcan.h
+@@ -70,6 +70,10 @@
+ #define FLEXCAN_QUIRK_SUPPORT_RX_FIFO BIT(16)
+ /* Setup stop mode with ATF SCMI protocol to support wakeup */
+ #define FLEXCAN_QUIRK_SETUP_STOP_MODE_SCMI BIT(17)
++/* Device has two separate interrupt lines for two mailbox ranges, which
++ * both need to have an interrupt handler registered.
++ */
++#define FLEXCAN_QUIRK_SECONDARY_MB_IRQ BIT(18)
+
+ struct flexcan_devtype_data {
+ u32 quirks; /* quirks needed for different IP cores */
+@@ -107,6 +111,7 @@ struct flexcan_priv {
+
+ int irq_boff;
+ int irq_err;
++ int irq_secondary_mb;
+
+ /* IPC handle when setup stop mode by System Controller firmware(scfw) */
+ struct imx_sc_ipc *sc_ipc_handle;
+--
+2.39.5
+
--- /dev/null
+From 1dbe8fa5a4a36810669d002883a2df37d30a7504 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Mar 2025 11:17:35 +0100
+Subject: cdc_ether|r8152: ThinkPad Hybrid USB-C/A Dock quirk
+
+From: Philipp Hahn <phahn-oss@avm.de>
+
+[ Upstream commit a07f23ad9baf716cbf7746e452c92960536ceae6 ]
+
+Lenovo ThinkPad Hybrid USB-C with USB-A Dock (17ef:a359) is affected by
+the same problem as the Lenovo Powered USB-C Travel Hub (17ef:721e):
+Both are based on the Realtek RTL8153B chip used to use the cdc_ether
+driver. However, using this driver, with the system suspended the device
+constantly sends pause-frames as soon as the receive buffer fills up.
+This causes issues with other devices, where some Ethernet switches stop
+forwarding packets altogether.
+
+Using the Realtek driver (r8152) fixes this issue. Pause frames are no
+longer sent while the host system is suspended.
+
+Cc: Leon Schuermann <leon@is.currently.online>
+Cc: Jakub Kicinski <kuba@kernel.org>
+Cc: Oliver Neukum <oliver@neukum.org> (maintainer:USB CDC ETHERNET DRIVER)
+Cc: netdev@vger.kernel.org (open list:NETWORKING DRIVERS)
+Link: https://git.kernel.org/netdev/net/c/cb82a54904a9
+Link: https://git.kernel.org/netdev/net/c/2284bbd0cf39
+Link: https://www.lenovo.com/de/de/p/accessories-and-software/docking/docking-usb-docks/40af0135eu
+Signed-off-by: Philipp Hahn <phahn-oss@avm.de>
+Reviewed-by: Kory Maincent <kory.maincent@bootlin.com>
+Link: https://patch.msgid.link/484336aad52d14ccf061b535bc19ef6396ef5120.1741601523.git.p.hahn@avm.de
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/cdc_ether.c | 7 +++++++
+ drivers/net/usb/r8152.c | 6 ++++++
+ drivers/net/usb/r8153_ecm.c | 6 ++++++
+ 3 files changed, 19 insertions(+)
+
+diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
+index a6469235d904e..a032c1ded4063 100644
+--- a/drivers/net/usb/cdc_ether.c
++++ b/drivers/net/usb/cdc_ether.c
+@@ -783,6 +783,13 @@ static const struct usb_device_id products[] = {
+ .driver_info = 0,
+ },
+
++/* Lenovo ThinkPad Hybrid USB-C with USB-A Dock (40af0135eu, based on Realtek RTL8153) */
++{
++ USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0xa359, USB_CLASS_COMM,
++ USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
++ .driver_info = 0,
++},
++
+ /* Aquantia AQtion USB to 5GbE Controller (based on AQC111U) */
+ {
+ USB_DEVICE_AND_INTERFACE_INFO(AQUANTIA_VENDOR_ID, 0xc101,
+diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
+index 468c739740463..96fa3857d8e25 100644
+--- a/drivers/net/usb/r8152.c
++++ b/drivers/net/usb/r8152.c
+@@ -785,6 +785,7 @@ enum rtl8152_flags {
+ #define DEVICE_ID_THINKPAD_USB_C_DONGLE 0x720c
+ #define DEVICE_ID_THINKPAD_USB_C_DOCK_GEN2 0xa387
+ #define DEVICE_ID_THINKPAD_USB_C_DOCK_GEN3 0x3062
++#define DEVICE_ID_THINKPAD_HYBRID_USB_C_DOCK 0xa359
+
+ struct tally_counter {
+ __le64 tx_packets;
+@@ -9787,6 +9788,7 @@ static bool rtl8152_supports_lenovo_macpassthru(struct usb_device *udev)
+ case DEVICE_ID_THINKPAD_USB_C_DOCK_GEN2:
+ case DEVICE_ID_THINKPAD_USB_C_DOCK_GEN3:
+ case DEVICE_ID_THINKPAD_USB_C_DONGLE:
++ case DEVICE_ID_THINKPAD_HYBRID_USB_C_DOCK:
+ return 1;
+ }
+ } else if (vendor_id == VENDOR_ID_REALTEK && parent_vendor_id == VENDOR_ID_LENOVO) {
+@@ -10064,6 +10066,8 @@ static const struct usb_device_id rtl8152_table[] = {
+ { USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0927) },
+ { USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0c5e) },
+ { USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101) },
++
++ /* Lenovo */
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x304f) },
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x3054) },
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x3062) },
+@@ -10074,7 +10078,9 @@ static const struct usb_device_id rtl8152_table[] = {
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x720c) },
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x7214) },
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x721e) },
++ { USB_DEVICE(VENDOR_ID_LENOVO, 0xa359) },
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0xa387) },
++
+ { USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041) },
+ { USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff) },
+ { USB_DEVICE(VENDOR_ID_TPLINK, 0x0601) },
+diff --git a/drivers/net/usb/r8153_ecm.c b/drivers/net/usb/r8153_ecm.c
+index 20b2df8d74ae1..8d860dacdf49b 100644
+--- a/drivers/net/usb/r8153_ecm.c
++++ b/drivers/net/usb/r8153_ecm.c
+@@ -135,6 +135,12 @@ static const struct usb_device_id products[] = {
+ USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long)&r8153_info,
+ },
++/* Lenovo ThinkPad Hybrid USB-C with USB-A Dock (40af0135eu, based on Realtek RTL8153) */
++{
++ USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID_LENOVO, 0xa359, USB_CLASS_COMM,
++ USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
++ .driver_info = (unsigned long)&r8153_info,
++},
+
+ { }, /* END */
+ };
+--
+2.39.5
+
--- /dev/null
+From e9f2bb1ec1307b9706143d213cefcea5669b87a1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Feb 2025 16:10:41 -0800
+Subject: drivers: base: devres: Allow to release group on device release
+
+From: Lucas De Marchi <lucas.demarchi@intel.com>
+
+[ Upstream commit 8e1ddfada4530939a8cb64ee9251aef780474274 ]
+
+When releasing a device, if the release action causes a group to be
+released, a warning is emitted because it can't find the group. This
+happens because devres_release_all() moves the entire list to a todo
+list and also move the group markers. Considering r* normal resource
+nodes and g1 a group resource node:
+
+ g1 -----------.
+ v v
+ r1 -> r2 -> g1[0] -> r3-> g[1] -> r4
+
+After devres_release_all(), dev->devres_head becomes empty and the todo
+list it iterates on becomes:
+
+ g1
+ v
+ r1 -> r2 -> r3-> r4 -> g1[0]
+
+When a call to component_del() is made and takes down the aggregate
+device, a warning like this happen:
+
+ RIP: 0010:devres_release_group+0x362/0x530
+ ...
+ Call Trace:
+ <TASK>
+ component_unbind+0x156/0x380
+ component_unbind_all+0x1d0/0x270
+ mei_component_master_unbind+0x28/0x80 [mei_hdcp]
+ take_down_aggregate_device+0xc1/0x160
+ component_del+0x1c6/0x3e0
+ intel_hdcp_component_fini+0xf1/0x170 [xe]
+ xe_display_fini+0x1e/0x40 [xe]
+
+Because the devres group corresponding to the hdcp component cannot be
+found. Just ignore this corner case: if the dev->devres_head is empty
+and the caller is trying to remove a group, it's likely in the process
+of device cleanup so just ignore it instead of warning.
+
+Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250222001051.3012936-2-lucas.demarchi@intel.com
+Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/devres.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/base/devres.c b/drivers/base/devres.c
+index 2152eec0c1352..68224f2f83fff 100644
+--- a/drivers/base/devres.c
++++ b/drivers/base/devres.c
+@@ -687,6 +687,13 @@ int devres_release_group(struct device *dev, void *id)
+ spin_unlock_irqrestore(&dev->devres_lock, flags);
+
+ release_nodes(dev, &todo);
++ } else if (list_empty(&dev->devres_head)) {
++ /*
++ * dev is probably dying via devres_release_all(): groups
++ * have already been removed and are on the process of
++ * being released - don't touch and don't warn.
++ */
++ spin_unlock_irqrestore(&dev->devres_lock, flags);
+ } else {
+ WARN_ON(1);
+ spin_unlock_irqrestore(&dev->devres_lock, flags);
+--
+2.39.5
+
--- /dev/null
+From 865e1829a754b36c22b1928a49e148735a32ed43 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Dec 2024 13:18:42 -0800
+Subject: drm: allow encoder mode_set even when connectors change for crtc
+
+From: Abhinav Kumar <quic_abhinavk@quicinc.com>
+
+[ Upstream commit 7e182cb4f5567f53417b762ec0d679f0b6f0039d ]
+
+In certain use-cases, a CRTC could switch between two encoders
+and because the mode being programmed on the CRTC remains
+the same during this switch, the CRTC's mode_changed remains false.
+In such cases, the encoder's mode_set also gets skipped.
+
+Skipping mode_set on the encoder for such cases could cause an issue
+because even though the same CRTC mode was being used, the encoder
+type could have changed like the CRTC could have switched from a
+real time encoder to a writeback encoder OR vice-versa.
+
+Allow encoder's mode_set to happen even when connectors changed on a
+CRTC and not just when the mode changed.
+
+Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
+Reviewed-by: Maxime Ripard <mripard@kernel.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20241211-abhinavk-modeset-fix-v3-1-0de4bf3e7c32@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 | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
+index 5186d2114a503..32902f77f00dd 100644
+--- a/drivers/gpu/drm/drm_atomic_helper.c
++++ b/drivers/gpu/drm/drm_atomic_helper.c
+@@ -1376,7 +1376,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
+ mode = &new_crtc_state->mode;
+ adjusted_mode = &new_crtc_state->adjusted_mode;
+
+- if (!new_crtc_state->mode_changed)
++ if (!new_crtc_state->mode_changed && !new_crtc_state->connectors_changed)
+ continue;
+
+ drm_dbg_atomic(dev, "modeset on [ENCODER:%d:%s]\n",
+--
+2.39.5
+
--- /dev/null
+From a54cdae70ecfacd661c8a10fd25b43296f940ce0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 11:52:32 -0500
+Subject: drm/amd/display: stop DML2 from removing pipes based on planes
+
+From: Mike Katsnelson <mike.katsnelson@amd.com>
+
+[ Upstream commit 8adeff83a3b07fa6d0958ed51e1b38ba7469e448 ]
+
+[Why]
+Transitioning from low to high resolutions at high refresh rates caused grey corruption.
+During the transition state, there is a period where plane size is based on low resultion
+state and ODM slices are based on high resoultion state, causing the entire plane to be
+contained in one ODM slice. DML2 would turn off the pipe for the ODM slice with no plane,
+causing an underflow since the pixel rate for the higher resolution cannot be supported on
+one pipe. This change stops DML2 from turning off pipes that are mapped to an ODM slice
+with no plane. This is possible to do without negative consequences because pipes can now
+take the minimum viewport and draw with zero recout size, removing the need to have the
+pipe turned off.
+
+[How]
+In map_pipes_from_plane(), remove "check" that skips ODM slices that are not covered by
+the plane. This prevents the pipes for those ODM slices from being freed.
+
+Reviewed-by: Ovidiu Bunea <ovidiu.bunea@amd.com>
+Signed-off-by: Mike Katsnelson <mike.katsnelson@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/dml2/dml2_dc_resource_mgmt.c | 26 -------------------
+ 1 file changed, 26 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
+index 1ed21c1b86a5b..a966abd407881 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
+@@ -532,26 +532,6 @@ static void calculate_odm_slices(const struct dc_stream_state *stream, unsigned
+ odm_slice_end_x[odm_factor - 1] = stream->src.width - 1;
+ }
+
+-static bool is_plane_in_odm_slice(const struct dc_plane_state *plane, unsigned int slice_index, unsigned int *odm_slice_end_x, unsigned int num_slices)
+-{
+- unsigned int slice_start_x, slice_end_x;
+-
+- if (slice_index == 0)
+- slice_start_x = 0;
+- else
+- slice_start_x = odm_slice_end_x[slice_index - 1] + 1;
+-
+- slice_end_x = odm_slice_end_x[slice_index];
+-
+- if (plane->clip_rect.x + plane->clip_rect.width < slice_start_x)
+- return false;
+-
+- if (plane->clip_rect.x > slice_end_x)
+- return false;
+-
+- return true;
+-}
+-
+ static void add_odm_slice_to_odm_tree(struct dml2_context *ctx,
+ struct dc_state *state,
+ struct dc_pipe_mapping_scratch *scratch,
+@@ -791,12 +771,6 @@ static void map_pipes_for_plane(struct dml2_context *ctx, struct dc_state *state
+ sort_pipes_for_splitting(&scratch->pipe_pool);
+
+ for (odm_slice_index = 0; odm_slice_index < scratch->odm_info.odm_factor; odm_slice_index++) {
+- // We build the tree for one ODM slice at a time.
+- // Each ODM slice shares a common OPP
+- if (!is_plane_in_odm_slice(plane, odm_slice_index, scratch->odm_info.odm_slice_end_x, scratch->odm_info.odm_factor)) {
+- continue;
+- }
+-
+ // Now we have a list of all pipes to be used for this plane/stream, now setup the tree.
+ scratch->odm_info.next_higher_pipe_for_odm_slice[odm_slice_index] = add_plane_to_blend_tree(ctx, state,
+ plane,
+--
+2.39.5
+
--- /dev/null
+From c04e5d6289fa7a77053513c6a550b6d6c6dcd706 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 Jan 2025 16:11:48 +0800
+Subject: drm/amd/display: Update Cursor request mode to the beginning prefetch
+ always
+
+From: Zhikai Zhai <zhikai.zhai@amd.com>
+
+[ Upstream commit 4a4077b4b63a8404efd6d37fc2926f03fb25bace ]
+
+[Why]
+The double buffer cursor registers is updated by the cursor
+vupdate event. There is a gap between vupdate and cursor data
+fetch if cursor fetch data reletive to cursor position.
+Cursor corruption will happen if we update the cursor surface
+in this gap.
+
+[How]
+Modify the cursor request mode to the beginning prefetch always
+and avoid wraparound calculation issues.
+
+Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Signed-off-by: Zhikai Zhai <zhikai.zhai@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>
+---
+ .../amd/display/dc/hubp/dcn31/dcn31_hubp.c | 2 +-
+ .../amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 22 ++++++++-----------
+ 2 files changed, 10 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn31/dcn31_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn31/dcn31_hubp.c
+index a65a0ddee6467..c671908ba7d06 100644
+--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn31/dcn31_hubp.c
++++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn31/dcn31_hubp.c
+@@ -44,7 +44,7 @@ void hubp31_set_unbounded_requesting(struct hubp *hubp, bool enable)
+ struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+ REG_UPDATE(DCHUBP_CNTL, HUBP_UNBOUNDED_REQ_MODE, enable);
+- REG_UPDATE(CURSOR_CONTROL, CURSOR_REQ_MODE, enable);
++ REG_UPDATE(CURSOR_CONTROL, CURSOR_REQ_MODE, 1);
+ }
+
+ void hubp31_soft_reset(struct hubp *hubp, bool reset)
+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 fd0530251c6e5..d725af14af371 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
+@@ -1992,20 +1992,11 @@ static void delay_cursor_until_vupdate(struct dc *dc, struct pipe_ctx *pipe_ctx)
+ dc->hwss.get_position(&pipe_ctx, 1, &position);
+ vpos = position.vertical_count;
+
+- /* Avoid wraparound calculation issues */
+- vupdate_start += stream->timing.v_total;
+- vupdate_end += stream->timing.v_total;
+- vpos += stream->timing.v_total;
+-
+ if (vpos <= vupdate_start) {
+ /* VPOS is in VACTIVE or back porch. */
+ lines_to_vupdate = vupdate_start - vpos;
+- } else if (vpos > vupdate_end) {
+- /* VPOS is in the front porch. */
+- return;
+ } else {
+- /* VPOS is in VUPDATE. */
+- lines_to_vupdate = 0;
++ lines_to_vupdate = stream->timing.v_total - vpos + vupdate_start;
+ }
+
+ /* Calculate time until VUPDATE in microseconds. */
+@@ -2013,13 +2004,18 @@ static void delay_cursor_until_vupdate(struct dc *dc, struct pipe_ctx *pipe_ctx)
+ stream->timing.h_total * 10000u / stream->timing.pix_clk_100hz;
+ us_to_vupdate = lines_to_vupdate * us_per_line;
+
++ /* Stall out until the cursor update completes. */
++ if (vupdate_end < vupdate_start)
++ vupdate_end += stream->timing.v_total;
++
++ /* Position is in the range of vupdate start and end*/
++ if (lines_to_vupdate > stream->timing.v_total - vupdate_end + vupdate_start)
++ us_to_vupdate = 0;
++
+ /* 70 us is a conservative estimate of cursor update time*/
+ if (us_to_vupdate > 70)
+ return;
+
+- /* Stall out until the cursor update completes. */
+- if (vupdate_end < vupdate_start)
+- vupdate_end += stream->timing.v_total;
+ us_vupdate = (vupdate_end - vupdate_start + 1) * us_per_line;
+ udelay(us_to_vupdate + us_vupdate);
+ }
+--
+2.39.5
+
--- /dev/null
+From 7ce797354b5fa5de46bc9465bc1c820c338591a7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Mar 2025 08:40:01 +0800
+Subject: drm/amdgpu: Fix the race condition for draining retry fault
+
+From: Emily Deng <Emily.Deng@amd.com>
+
+[ Upstream commit f844732e3ad9c4b78df7436232949b8d2096d1a6 ]
+
+Issue:
+In the scenario where svm_range_restore_pages is called, but
+svm->checkpoint_ts has not been set and the retry fault has not been
+drained, svm_range_unmap_from_cpu is triggered and calls svm_range_free.
+Meanwhile, svm_range_restore_pages continues execution and reaches
+svm_range_from_addr. This results in a "failed to find prange..." error,
+ causing the page recovery to fail.
+
+How to fix:
+Move the timestamp check code under the protection of svm->lock.
+
+v2:
+Make sure all right locks are released before go out.
+
+v3:
+Directly goto out_unlock_svms, and return -EAGAIN.
+
+v4:
+Refine code.
+
+Signed-off-by: Emily Deng <Emily.Deng@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_svm.c | 31 +++++++++++++++-------------
+ 1 file changed, 17 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+index 8c61dee5ca0db..b50283864dcd2 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+@@ -2992,19 +2992,6 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
+ goto out;
+ }
+
+- /* 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])) {
+- pr_debug("draining retry fault, drop fault 0x%llx\n", addr);
+- r = 0;
+- goto out;
+- } else
+- /* ts is after svms->checkpoint_ts now, reset svms->checkpoint_ts
+- * to zero to avoid following ts wrap around give wrong comparing
+- */
+- svms->checkpoint_ts[gpuidx] = 0;
+- }
+-
+ if (!p->xnack_enabled) {
+ pr_debug("XNACK not enabled for pasid 0x%x\n", pasid);
+ r = -EFAULT;
+@@ -3024,6 +3011,21 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
+ mmap_read_lock(mm);
+ retry_write_locked:
+ mutex_lock(&svms->lock);
++
++ /* 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])) {
++ pr_debug("draining retry fault, drop fault 0x%llx\n", addr);
++ r = -EAGAIN;
++ goto out_unlock_svms;
++ } else {
++ /* ts is after svms->checkpoint_ts now, reset svms->checkpoint_ts
++ * to zero to avoid following ts wrap around give wrong comparing
++ */
++ svms->checkpoint_ts[gpuidx] = 0;
++ }
++ }
++
+ prange = svm_range_from_addr(svms, addr, NULL);
+ if (!prange) {
+ pr_debug("failed to find prange svms 0x%p address [0x%llx]\n",
+@@ -3148,7 +3150,8 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
+ mutex_unlock(&svms->lock);
+ mmap_read_unlock(mm);
+
+- svm_range_count_fault(node, p, gpuidx);
++ if (r != -EAGAIN)
++ svm_range_count_fault(node, p, gpuidx);
+
+ mmput(mm);
+ out:
+--
+2.39.5
+
--- /dev/null
+From 6b06a19dd5915080b2d4c1c9a61c0cadbe4146bc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Jan 2025 13:51:39 +0100
+Subject: drm/amdgpu: grab an additional reference on the gang fence v2
+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 0d9a95099dcb05b5f4719c830d15bf4fdcad0dc2 ]
+
+We keep the gang submission fence around in adev, make sure that it
+stays alive.
+
+v2: fix memory leak on retry
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+Acked-by: Srinivasan Shanmugam <srinivasan.shanmugam@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 | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+index 96845541b2d25..31d4df9688981 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -6575,18 +6575,26 @@ struct dma_fence *amdgpu_device_switch_gang(struct amdgpu_device *adev,
+ {
+ struct dma_fence *old = NULL;
+
++ dma_fence_get(gang);
+ do {
+ dma_fence_put(old);
+ old = amdgpu_device_get_gang(adev);
+ if (old == gang)
+ break;
+
+- if (!dma_fence_is_signaled(old))
++ if (!dma_fence_is_signaled(old)) {
++ dma_fence_put(gang);
+ return old;
++ }
+
+ } while (cmpxchg((struct dma_fence __force **)&adev->gang_submit,
+ old, gang) != old);
+
++ /*
++ * Drop it once for the exchanged reference in adev and once for the
++ * thread local reference acquired in amdgpu_device_get_gang().
++ */
++ dma_fence_put(old);
+ dma_fence_put(old);
+ return NULL;
+ }
+--
+2.39.5
+
--- /dev/null
+From 9292f91c5273f14238676050cea3280e5b569b8b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Mar 2025 15:51:48 +0800
+Subject: drm/amdgpu: handle amdgpu_cgs_create_device() errors in
+ amd_powerplay_create()
+
+From: Wentao Liang <vulab@iscas.ac.cn>
+
+[ Upstream commit 1435e895d4fc967d64e9f5bf81e992ac32f5ac76 ]
+
+Add error handling to propagate amdgpu_cgs_create_device() failures
+to the caller. When amdgpu_cgs_create_device() fails, release hwmgr
+and return -ENOMEM to prevent null pointer dereference.
+
+[v1]->[v2]: Change error code from -EINVAL to -ENOMEM. Free hwmgr.
+
+Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
+index a71c6117d7e54..0115d26b5af92 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
+@@ -51,6 +51,11 @@ static int amd_powerplay_create(struct amdgpu_device *adev)
+ hwmgr->adev = adev;
+ hwmgr->not_vf = !amdgpu_sriov_vf(adev);
+ hwmgr->device = amdgpu_cgs_create_device(adev);
++ if (!hwmgr->device) {
++ kfree(hwmgr);
++ return -ENOMEM;
++ }
++
+ mutex_init(&hwmgr->msg_lock);
+ hwmgr->chip_family = adev->family;
+ hwmgr->chip_id = adev->asic_type;
+--
+2.39.5
+
--- /dev/null
+From 4c59c63922221588619d280e5a369564c2879868 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Jan 2025 09:53:13 -0500
+Subject: drm/amdgpu: Unlocked unmap only clear page table leaves
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Philip Yang <Philip.Yang@amd.com>
+
+[ Upstream commit 23b645231eeffdaf44021debac881d2f26824150 ]
+
+SVM migration unmap pages from GPU and then update mapping to GPU to
+recover page fault. Currently unmap clears the PDE entry for range
+length >= huge page and free PTB bo, update mapping to alloc new PT bo.
+There is race bug that the freed entry bo maybe still on the pt_free
+list, reused when updating mapping and then freed, leave invalid PDE
+entry and cause GPU page fault.
+
+By setting the update to clear only one PDE entry or clear PTB, to
+avoid unmap to free PTE bo. This fixes the race bug and improve the
+unmap and map to GPU performance. Update mapping to huge page will
+still free the PTB bo.
+
+With this change, the vm->pt_freed list and work is not needed. Add
+WARN_ON(unlocked) in amdgpu_vm_pt_free_dfs to catch if unmap to free the
+PTB.
+
+Signed-off-by: Philip Yang <Philip.Yang@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/amdgpu_vm.c | 4 ---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 4 ---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c | 43 +++++++----------------
+ 3 files changed, 13 insertions(+), 38 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+index 73e02141a6e21..37d53578825b3 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+@@ -2434,8 +2434,6 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+ spin_lock_init(&vm->status_lock);
+ INIT_LIST_HEAD(&vm->freed);
+ INIT_LIST_HEAD(&vm->done);
+- INIT_LIST_HEAD(&vm->pt_freed);
+- INIT_WORK(&vm->pt_free_work, amdgpu_vm_pt_free_work);
+ INIT_KFIFO(vm->faults);
+
+ r = amdgpu_vm_init_entities(adev, vm);
+@@ -2607,8 +2605,6 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
+
+ amdgpu_amdkfd_gpuvm_destroy_cb(adev, vm);
+
+- flush_work(&vm->pt_free_work);
+-
+ root = amdgpu_bo_ref(vm->root.bo);
+ amdgpu_bo_reserve(root, true);
+ amdgpu_vm_put_task_info(vm->task_info);
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+index 52dd7cdfdc814..ee893527a4f1d 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+@@ -360,10 +360,6 @@ struct amdgpu_vm {
+ /* BOs which are invalidated, has been updated in the PTs */
+ struct list_head done;
+
+- /* PT BOs scheduled to free and fill with zero if vm_resv is not hold */
+- struct list_head pt_freed;
+- struct work_struct pt_free_work;
+-
+ /* contains the page directory */
+ struct amdgpu_vm_bo_base root;
+ struct dma_fence *last_update;
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
+index f78a0434a48fa..54ae0e9bc6d77 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
+@@ -546,27 +546,6 @@ static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base *entry)
+ amdgpu_bo_unref(&entry->bo);
+ }
+
+-void amdgpu_vm_pt_free_work(struct work_struct *work)
+-{
+- struct amdgpu_vm_bo_base *entry, *next;
+- struct amdgpu_vm *vm;
+- LIST_HEAD(pt_freed);
+-
+- vm = container_of(work, struct amdgpu_vm, pt_free_work);
+-
+- spin_lock(&vm->status_lock);
+- list_splice_init(&vm->pt_freed, &pt_freed);
+- spin_unlock(&vm->status_lock);
+-
+- /* flush_work in amdgpu_vm_fini ensure vm->root.bo is valid. */
+- amdgpu_bo_reserve(vm->root.bo, true);
+-
+- list_for_each_entry_safe(entry, next, &pt_freed, vm_status)
+- amdgpu_vm_pt_free(entry);
+-
+- amdgpu_bo_unreserve(vm->root.bo);
+-}
+-
+ /**
+ * amdgpu_vm_pt_free_list - free PD/PT levels
+ *
+@@ -579,19 +558,15 @@ void amdgpu_vm_pt_free_list(struct amdgpu_device *adev,
+ struct amdgpu_vm_update_params *params)
+ {
+ struct amdgpu_vm_bo_base *entry, *next;
+- struct amdgpu_vm *vm = params->vm;
+ bool unlocked = params->unlocked;
+
+ if (list_empty(¶ms->tlb_flush_waitlist))
+ return;
+
+- if (unlocked) {
+- spin_lock(&vm->status_lock);
+- list_splice_init(¶ms->tlb_flush_waitlist, &vm->pt_freed);
+- spin_unlock(&vm->status_lock);
+- schedule_work(&vm->pt_free_work);
+- return;
+- }
++ /*
++ * unlocked unmap clear page table leaves, warning to free the page entry.
++ */
++ WARN_ON(unlocked);
+
+ list_for_each_entry_safe(entry, next, ¶ms->tlb_flush_waitlist, vm_status)
+ amdgpu_vm_pt_free(entry);
+@@ -899,7 +874,15 @@ int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params *params,
+ incr = (uint64_t)AMDGPU_GPU_PAGE_SIZE << shift;
+ mask = amdgpu_vm_pt_entries_mask(adev, cursor.level);
+ pe_start = ((cursor.pfn >> shift) & mask) * 8;
+- entry_end = ((uint64_t)mask + 1) << shift;
++
++ if (cursor.level < AMDGPU_VM_PTB && params->unlocked)
++ /*
++ * MMU notifier callback unlocked unmap huge page, leave is PDE entry,
++ * only clear one entry. Next entry search again for PDE or PTE leave.
++ */
++ entry_end = 1ULL << shift;
++ else
++ entry_end = ((uint64_t)mask + 1) << shift;
+ entry_end += cursor.pfn & ~(entry_end - 1);
+ entry_end = min(entry_end, end);
+
+--
+2.39.5
+
--- /dev/null
+From 59c184dc2fd7b13eb72939958f540c4bcdd5ccce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 18:08:02 -0500
+Subject: drm/amdkfd: clamp queue size to minimum
+
+From: David Yat Sin <David.YatSin@amd.com>
+
+[ Upstream commit e90711946b53590371ecce32e8fcc381a99d6333 ]
+
+If queue size is less than minimum, clamp it to minimum to prevent
+underflow when writing queue mqd.
+
+Signed-off-by: David Yat Sin <David.YatSin@amd.com>
+Reviewed-by: Jay Cornwall <jay.cornwall@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_chardev.c | 10 ++++++++++
+ include/uapi/linux/kfd_ioctl.h | 2 ++
+ 2 files changed, 12 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+index 3e6b4736a7fea..67b5f3d7ff8e9 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+@@ -212,6 +212,11 @@ static int set_queue_properties_from_user(struct queue_properties *q_properties,
+ return -EINVAL;
+ }
+
++ if (args->ring_size < KFD_MIN_QUEUE_RING_SIZE) {
++ args->ring_size = KFD_MIN_QUEUE_RING_SIZE;
++ pr_debug("Size lower. clamped to KFD_MIN_QUEUE_RING_SIZE");
++ }
++
+ if (!access_ok((const void __user *) args->read_pointer_address,
+ sizeof(uint32_t))) {
+ pr_err("Can't access read pointer\n");
+@@ -461,6 +466,11 @@ static int kfd_ioctl_update_queue(struct file *filp, struct kfd_process *p,
+ return -EINVAL;
+ }
+
++ if (args->ring_size < KFD_MIN_QUEUE_RING_SIZE) {
++ args->ring_size = KFD_MIN_QUEUE_RING_SIZE;
++ pr_debug("Size lower. clamped to KFD_MIN_QUEUE_RING_SIZE");
++ }
++
+ properties.queue_address = args->ring_base_address;
+ properties.queue_size = args->ring_size;
+ properties.queue_percent = args->queue_percentage & 0xFF;
+diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h
+index 717307d6b5b74..3e1c11d9d9808 100644
+--- a/include/uapi/linux/kfd_ioctl.h
++++ b/include/uapi/linux/kfd_ioctl.h
+@@ -62,6 +62,8 @@ struct kfd_ioctl_get_version_args {
+ #define KFD_MAX_QUEUE_PERCENTAGE 100
+ #define KFD_MAX_QUEUE_PRIORITY 15
+
++#define KFD_MIN_QUEUE_RING_SIZE 1024
++
+ struct kfd_ioctl_create_queue_args {
+ __u64 ring_base_address; /* to KFD */
+ __u64 write_pointer_address; /* from KFD */
+--
+2.39.5
+
--- /dev/null
+From 5932bd5d31ce23ea50ff13695ad4fcff44a6947e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Feb 2025 09:42:31 -0500
+Subject: drm/amdkfd: debugfs hang_hws skip GPU with MES
+
+From: Philip Yang <Philip.Yang@amd.com>
+
+[ Upstream commit fe9d0061c413f8fb8c529b18b592b04170850ded ]
+
+debugfs hang_hws is used by GPU reset test with HWS, for MES this crash
+the kernel with NULL pointer access because dqm->packet_mgr is not setup
+for MES path.
+
+Skip GPU with MES for now, MES hang_hws debugfs interface will be
+supported later.
+
+Signed-off-by: Philip Yang <Philip.Yang@amd.com>
+Reviewed-by: Kent Russell <kent.russell@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_device.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+index d350c7ce35b3d..9186ef0bd2a32 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+@@ -1493,6 +1493,11 @@ int kfd_debugfs_hang_hws(struct kfd_node *dev)
+ return -EINVAL;
+ }
+
++ if (dev->kfd->shared_resources.enable_mes) {
++ dev_err(dev->adev->dev, "Inducing MES hang is not supported\n");
++ return -EINVAL;
++ }
++
+ return dqm_debugfs_hang_hws(dev->dqm);
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 324556ee23a933a51c260d9c46021f5e562c0eff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Feb 2025 17:50:13 -0500
+Subject: drm/amdkfd: Fix mode1 reset crash issue
+
+From: Philip Yang <Philip.Yang@amd.com>
+
+[ Upstream commit f0b4440cdc1807bb6ec3dce0d6de81170803569b ]
+
+If HW scheduler hangs and mode1 reset is used to recover GPU, KFD signal
+user space to abort the processes. After process abort exit, user queues
+still use the GPU to access system memory before h/w is reset while KFD
+cleanup worker free system memory and free VRAM.
+
+There is use-after-free race bug that KFD allocate and reuse the freed
+system memory, and user queue write to the same system memory to corrupt
+the data structure and cause driver crash.
+
+To fix this race, KFD cleanup worker terminate user queues, then flush
+reset_domain wq to wait for any GPU ongoing reset complete, and then
+free outstanding BOs.
+
+Signed-off-by: Philip Yang <Philip.Yang@amd.com>
+Reviewed-by: Lijo Lazar <lijo.lazar@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 | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+index 264bd764f6f27..0ec8b457494bd 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+@@ -35,6 +35,7 @@
+ #include <linux/pm_runtime.h>
+ #include "amdgpu_amdkfd.h"
+ #include "amdgpu.h"
++#include "amdgpu_reset.h"
+
+ struct mm_struct;
+
+@@ -1140,6 +1141,17 @@ static void kfd_process_remove_sysfs(struct kfd_process *p)
+ p->kobj = NULL;
+ }
+
++/*
++ * If any GPU is ongoing reset, wait for reset complete.
++ */
++static void kfd_process_wait_gpu_reset_complete(struct kfd_process *p)
++{
++ int i;
++
++ for (i = 0; i < p->n_pdds; i++)
++ flush_workqueue(p->pdds[i]->dev->adev->reset_domain->wq);
++}
++
+ /* No process locking is needed in this function, because the process
+ * is not findable any more. We must assume that no other thread is
+ * using it any more, otherwise we couldn't safely free the process
+@@ -1154,6 +1166,11 @@ static void kfd_process_wq_release(struct work_struct *work)
+ kfd_process_dequeue_from_all_devices(p);
+ pqm_uninit(&p->pqm);
+
++ /*
++ * If GPU in reset, user queues may still running, wait for reset complete.
++ */
++ kfd_process_wait_gpu_reset_complete(p);
++
+ /* Signal the eviction fence after user mode queues are
+ * destroyed. This allows any BOs to be freed without
+ * triggering pointless evictions or waiting for fences.
+--
+2.39.5
+
--- /dev/null
+From 762b6a12b51aa5521af3da306ecf5003aa667801 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 16:02:13 -0500
+Subject: drm/amdkfd: Fix pqm_destroy_queue race with GPU reset
+
+From: Philip Yang <Philip.Yang@amd.com>
+
+[ Upstream commit 7919b4cad5545ed93778f11881ceee72e4dbed66 ]
+
+If GPU in reset, destroy_queue return -EIO, pqm_destroy_queue should
+delete the queue from process_queue_list and free the resource.
+
+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_queue_manager.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+index ac777244ee0a1..4078a81761871 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+@@ -546,7 +546,7 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid)
+ pr_err("Pasid 0x%x destroy queue %d failed, ret %d\n",
+ pqm->process->pasid,
+ pqn->q->properties.queue_id, retval);
+- if (retval != -ETIME)
++ if (retval != -ETIME && retval != -EIO)
+ goto err_destroy_queue;
+ }
+ kfd_procfs_del_queue(pqn->q);
+--
+2.39.5
+
--- /dev/null
+From a6835a808a75f77e74270e2660b0f55e187a06f6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Feb 2025 13:57:44 +0100
+Subject: drm/bridge: panel: forbid initializing a panel with unknown connector
+ type
+
+From: Luca Ceresoli <luca.ceresoli@bootlin.com>
+
+[ Upstream commit b296955b3a740ecc8b3b08e34fd64f1ceabb8fb4 ]
+
+Having an DRM_MODE_CONNECTOR_Unknown connector type is considered bad, and
+drm_panel_bridge_add_typed() and derivatives are deprecated for this.
+
+drm_panel_init() won't prevent initializing a panel with a
+DRM_MODE_CONNECTOR_Unknown connector type. Luckily there are no in-tree
+users doing it, so take this as an opportinuty to document a valid
+connector type must be passed.
+
+Returning an error if this rule is violated is not possible because
+drm_panel_init() is a void function. Add at least a warning to make any
+violations noticeable, especially to non-upstream drivers.
+
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
+Signed-off-by: Robert Foss <rfoss@kernel.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250214-drm-assorted-cleanups-v7-5-88ca5827d7af@bootlin.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_panel.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c
+index 19ab0a794add3..fd8fa2e0ef6fa 100644
+--- a/drivers/gpu/drm/drm_panel.c
++++ b/drivers/gpu/drm/drm_panel.c
+@@ -49,7 +49,7 @@ static LIST_HEAD(panel_list);
+ * @dev: parent device of the panel
+ * @funcs: panel operations
+ * @connector_type: the connector type (DRM_MODE_CONNECTOR_*) corresponding to
+- * the panel interface
++ * the panel interface (must NOT be DRM_MODE_CONNECTOR_Unknown)
+ *
+ * Initialize the panel structure for subsequent registration with
+ * drm_panel_add().
+@@ -57,6 +57,9 @@ static LIST_HEAD(panel_list);
+ void drm_panel_init(struct drm_panel *panel, struct device *dev,
+ const struct drm_panel_funcs *funcs, int connector_type)
+ {
++ if (connector_type == DRM_MODE_CONNECTOR_Unknown)
++ DRM_WARN("%s: %s: a valid connector type is required!\n", __func__, dev_name(dev));
++
+ INIT_LIST_HEAD(&panel->list);
+ INIT_LIST_HEAD(&panel->followers);
+ mutex_init(&panel->follower_lock);
+--
+2.39.5
+
--- /dev/null
+From 5a90cc507275fbddb493064535e0be88c3fc3504 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Feb 2025 13:57:40 +0100
+Subject: drm/debugfs: fix printk format for bridge index
+
+From: Luca Ceresoli <luca.ceresoli@bootlin.com>
+
+[ Upstream commit 72443c730b7a7b5670a921ea928e17b9b99bd934 ]
+
+idx is an unsigned int, use %u for printk-style strings.
+
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
+Signed-off-by: Robert Foss <rfoss@kernel.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250214-drm-assorted-cleanups-v7-1-88ca5827d7af@bootlin.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_debugfs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
+index 9d3e6dd68810e..98a37dc3324e4 100644
+--- a/drivers/gpu/drm/drm_debugfs.c
++++ b/drivers/gpu/drm/drm_debugfs.c
+@@ -743,7 +743,7 @@ static int bridges_show(struct seq_file *m, void *data)
+ unsigned int idx = 0;
+
+ drm_for_each_bridge_in_chain(encoder, bridge) {
+- drm_printf(&p, "bridge[%d]: %ps\n", idx++, bridge->funcs);
++ drm_printf(&p, "bridge[%u]: %ps\n", idx++, bridge->funcs);
+ drm_printf(&p, "\ttype: [%d] %s\n",
+ bridge->type,
+ drm_get_connector_type_name(bridge->type));
+--
+2.39.5
+
--- /dev/null
+From 677dca6e1b616ac7e7da0f0ac0b22f0e85239087 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 16:48:02 +0100
+Subject: drm/mediatek: mtk_dpi: Explicitly manage TVD clock in power on/off
+
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+[ Upstream commit 473c33f5ce651365468503c76f33158aaa1c7dd2 ]
+
+In preparation for adding support for MT8195's HDMI reserved
+DPI, add calls to clk_prepare_enable() / clk_disable_unprepare()
+for the TVD clock: in this particular case, the aforementioned
+clock is not (and cannot be) parented to neither pixel or engine
+clocks hence it won't get enabled automatically by the clock
+framework.
+
+Please note that on all of the currently supported MediaTek
+platforms, the TVD clock is always a parent of either pixel or
+engine clocks, and this means that the common clock framework
+is already enabling this clock before the children.
+On such platforms, this commit will only increase the refcount
+of the TVD clock without any functional change.
+
+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-10-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 | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
+index 21ec6c775521f..9c11d3158324c 100644
+--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
++++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
+@@ -471,6 +471,7 @@ static void mtk_dpi_power_off(struct mtk_dpi *dpi)
+
+ mtk_dpi_disable(dpi);
+ clk_disable_unprepare(dpi->pixel_clk);
++ clk_disable_unprepare(dpi->tvd_clk);
+ clk_disable_unprepare(dpi->engine_clk);
+ }
+
+@@ -487,6 +488,12 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi)
+ goto err_refcount;
+ }
+
++ ret = clk_prepare_enable(dpi->tvd_clk);
++ if (ret) {
++ dev_err(dpi->dev, "Failed to enable tvd pll: %d\n", ret);
++ goto err_engine;
++ }
++
+ ret = clk_prepare_enable(dpi->pixel_clk);
+ if (ret) {
+ dev_err(dpi->dev, "Failed to enable pixel clock: %d\n", ret);
+@@ -496,6 +503,8 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi)
+ return 0;
+
+ err_pixel:
++ clk_disable_unprepare(dpi->tvd_clk);
++err_engine:
+ clk_disable_unprepare(dpi->engine_clk);
+ err_refcount:
+ dpi->refcount--;
+--
+2.39.5
+
--- /dev/null
+From 404c6e81990f87e69525a118bf19dfe162139876 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 16:47:59 +0100
+Subject: drm/mediatek: mtk_dpi: Move the input_2p_en bit to platform data
+
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+[ Upstream commit c90876a695dd83e76680b88b40067275a5982811 ]
+
+In preparation for adding support for MT8195's HDMI reserved DPI
+instance, move the input_2p_en bit for DP_INTF to platform data.
+
+While at it, remove the input_2pixel member from platform data as
+having this bit implies that the 2pixel feature must be enabled.
+
+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-7-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 | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
+index a08d206549543..21ec6c775521f 100644
+--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
++++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
+@@ -127,14 +127,14 @@ struct mtk_dpi_yc_limit {
+ * @is_ck_de_pol: Support CK/DE polarity.
+ * @swap_input_support: Support input swap function.
+ * @support_direct_pin: IP supports direct connection to dpi panels.
+- * @input_2pixel: Input pixel of dp_intf is 2 pixel per round, so enable this
+- * config to enable this feature.
+ * @dimension_mask: Mask used for HWIDTH, HPORCH, VSYNC_WIDTH and VSYNC_PORCH
+ * (no shift).
+ * @hvsize_mask: Mask of HSIZE and VSIZE mask (no shift).
+ * @channel_swap_shift: Shift value of channel swap.
+ * @yuv422_en_bit: Enable bit of yuv422.
+ * @csc_enable_bit: Enable bit of CSC.
++ * @input_2p_en_bit: Enable bit for input two pixel per round feature.
++ * If present, implies that the feature must be enabled.
+ * @pixels_per_iter: Quantity of transferred pixels per iteration.
+ * @edge_cfg_in_mmsys: If the edge configuration for DPI's output needs to be set in MMSYS.
+ */
+@@ -148,12 +148,12 @@ struct mtk_dpi_conf {
+ bool is_ck_de_pol;
+ bool swap_input_support;
+ bool support_direct_pin;
+- bool input_2pixel;
+ u32 dimension_mask;
+ u32 hvsize_mask;
+ u32 channel_swap_shift;
+ u32 yuv422_en_bit;
+ u32 csc_enable_bit;
++ u32 input_2p_en_bit;
+ u32 pixels_per_iter;
+ bool edge_cfg_in_mmsys;
+ };
+@@ -610,9 +610,9 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
+ mtk_dpi_dual_edge(dpi);
+ mtk_dpi_config_disable_edge(dpi);
+ }
+- if (dpi->conf->input_2pixel) {
+- mtk_dpi_mask(dpi, DPI_CON, DPINTF_INPUT_2P_EN,
+- DPINTF_INPUT_2P_EN);
++ if (dpi->conf->input_2p_en_bit) {
++ mtk_dpi_mask(dpi, DPI_CON, dpi->conf->input_2p_en_bit,
++ dpi->conf->input_2p_en_bit);
+ }
+ mtk_dpi_sw_reset(dpi, false);
+
+@@ -992,12 +992,12 @@ static const struct mtk_dpi_conf mt8195_dpintf_conf = {
+ .output_fmts = mt8195_output_fmts,
+ .num_output_fmts = ARRAY_SIZE(mt8195_output_fmts),
+ .pixels_per_iter = 4,
+- .input_2pixel = true,
+ .dimension_mask = DPINTF_HPW_MASK,
+ .hvsize_mask = DPINTF_HSIZE_MASK,
+ .channel_swap_shift = DPINTF_CH_SWAP,
+ .yuv422_en_bit = DPINTF_YUV422_EN,
+ .csc_enable_bit = DPINTF_CSC_ENABLE,
++ .input_2p_en_bit = DPINTF_INPUT_2P_EN,
+ };
+
+ static int mtk_dpi_probe(struct platform_device *pdev)
+--
+2.39.5
+
--- /dev/null
+From fa9a5e8e52f7841ab43d80edb42e9baa5f996d2b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 22:24:52 +0000
+Subject: drm: panel-orientation-quirks: Add new quirk for GPD Win 2
+
+From: Andrew Wyatt <fewtarius@steamfork.org>
+
+[ Upstream commit a860eb9c6ba6cdbf32e3e01a606556e5a90a2931 ]
+
+Some GPD Win 2 units shipped with the correct DMI strings.
+
+Add a DMI match to correctly rotate the panel on these units.
+
+Signed-off-by: Andrew Wyatt <fewtarius@steamfork.org>
+Signed-off-by: John Edwards <uejji@uejji.net>
+Tested-by: Paco Avelar <pacoavelar@hotmail.com>
+Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250213222455.93533-5-uejji@uejji.net
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c
+index b57078cfdd80f..384a8dcf454fb 100644
+--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
++++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
+@@ -339,6 +339,12 @@ static const struct dmi_system_id orientation_data[] = {
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
+ },
+ .driver_data = (void *)&gpd_win2,
++ }, { /* GPD Win 2 (correct DMI strings) */
++ .matches = {
++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "WIN2")
++ },
++ .driver_data = (void *)&lcd720x1280_rightside_up,
+ }, { /* GPD Win 3 */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
+--
+2.39.5
+
--- /dev/null
+From e2109888834e2fd9f559cc9c8a25359acbfcfe47 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 22:24:51 +0000
+Subject: drm: panel-orientation-quirks: Add quirk for AYA NEO Slide
+
+From: Andrew Wyatt <fewtarius@steamfork.org>
+
+[ Upstream commit 132c89ef8872e602cfb909377815111d121fe8d7 ]
+
+The AYANEO Slide uses a 1080x1920 portrait LCD panel. This is the same
+panel used on the AYANEO Air Plus, but the DMI data is too different to
+match both with one entry.
+
+Add a DMI match to correctly rotate the panel on the AYANEO Slide.
+
+This also covers the Antec Core HS, which is a rebranded AYANEO Slide with
+the exact same hardware and DMI strings.
+
+Signed-off-by: Andrew Wyatt <fewtarius@steamfork.org>
+Signed-off-by: John Edwards <uejji@uejji.net>
+Tested-by: John Edwards <uejji@uejji.net>
+Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250213222455.93533-4-uejji@uejji.net
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c
+index b5f6ae0459459..b57078cfdd80f 100644
+--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
++++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
+@@ -244,6 +244,12 @@ static const struct dmi_system_id orientation_data[] = {
+ DMI_MATCH(DMI_BOARD_NAME, "KUN"),
+ },
+ .driver_data = (void *)&lcd1600x2560_rightside_up,
++ }, { /* AYA NEO SLIDE */
++ .matches = {
++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "SLIDE"),
++ },
++ .driver_data = (void *)&lcd1080x1920_leftside_up,
+ }, { /* AYN Loki Max */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ayn"),
+--
+2.39.5
+
--- /dev/null
+From 8f1674af570f37759000e508dcee2e0732350e78 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 22:24:53 +0000
+Subject: drm: panel-orientation-quirks: Add quirk for OneXPlayer Mini (Intel)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Andrew Wyatt <fewtarius@steamfork.org>
+
+[ Upstream commit b24dcc183583fc360ae0f0899e286a68f46abbd0 ]
+
+The Intel model of the OneXPlayer Mini uses a 1200x1920 portrait LCD panel.
+The DMI strings are the same as the OneXPlayer, which already has a DMI
+quirk, but the panel is different.
+
+Add a DMI match to correctly rotate this panel.
+
+Signed-off-by: Andrew Wyatt <fewtarius@steamfork.org>
+Co-developed-by: John Edwards <uejji@uejji.net>
+Signed-off-by: John Edwards <uejji@uejji.net>
+Tested-by: João Pedro Kurtz <joexkurtz@gmail.com>
+Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250213222455.93533-6-uejji@uejji.net
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_panel_orientation_quirks.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c
+index 384a8dcf454fb..c554ad8f246b6 100644
+--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
++++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
+@@ -129,6 +129,12 @@ static const struct drm_dmi_panel_orientation_data lcd1080x1920_rightside_up = {
+ .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
+ };
+
++static const struct drm_dmi_panel_orientation_data lcd1200x1920_leftside_up = {
++ .width = 1200,
++ .height = 1920,
++ .orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP,
++};
++
+ static const struct drm_dmi_panel_orientation_data lcd1200x1920_rightside_up = {
+ .width = 1200,
+ .height = 1920,
+@@ -473,6 +479,12 @@ static const struct dmi_system_id orientation_data[] = {
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ONE XPLAYER"),
+ },
+ .driver_data = (void *)&lcd1600x2560_leftside_up,
++ }, { /* OneXPlayer Mini (Intel) */
++ .matches = {
++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ONE-NETBOOK TECHNOLOGY CO., LTD."),
++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ONE XPLAYER"),
++ },
++ .driver_data = (void *)&lcd1200x1920_leftside_up,
+ }, { /* OrangePi Neo */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "OrangePi"),
+--
+2.39.5
+
--- /dev/null
+From 7384d0bbea7059e5f2dadd6484d3a0c509c5a761 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 22:24:50 +0000
+Subject: drm: panel-orientation-quirks: Add quirks for AYA NEO Flip DS and KB
+
+From: Andrew Wyatt <fewtarius@steamfork.org>
+
+[ Upstream commit 529741c331da1fbf54f86c6ec3a4558b9b0b16dc ]
+
+The AYA NEO Flip DS and KB both use a 1080x1920 portrait LCD panel. The
+Flip DS additionally uses a 640x960 portrait LCD panel as a second display.
+
+Add DMI matches to correctly rotate these panels.
+
+Signed-off-by: Andrew Wyatt <fewtarius@steamfork.org>
+Co-developed-by: John Edwards <uejji@uejji.net>
+Signed-off-by: John Edwards <uejji@uejji.net>
+Tested-by: Paco Avelar <pacoavelar@hotmail.com>
+Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250213222455.93533-3-uejji@uejji.net
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_panel_orientation_quirks.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c
+index f9c975338fc9e..b5f6ae0459459 100644
+--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
++++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
+@@ -93,6 +93,12 @@ static const struct drm_dmi_panel_orientation_data onegx1_pro = {
+ .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
+ };
+
++static const struct drm_dmi_panel_orientation_data lcd640x960_leftside_up = {
++ .width = 640,
++ .height = 960,
++ .orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP,
++};
++
+ static const struct drm_dmi_panel_orientation_data lcd720x1280_rightside_up = {
+ .width = 720,
+ .height = 1280,
+@@ -202,6 +208,18 @@ static const struct dmi_system_id orientation_data[] = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "AIR"),
+ },
+ .driver_data = (void *)&lcd1080x1920_leftside_up,
++ }, { /* AYA NEO Flip DS Bottom Screen */
++ .matches = {
++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"),
++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "FLIP DS"),
++ },
++ .driver_data = (void *)&lcd640x960_leftside_up,
++ }, { /* AYA NEO Flip KB/DS Top Screen */
++ .matches = {
++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "FLIP"),
++ },
++ .driver_data = (void *)&lcd1080x1920_leftside_up,
+ }, { /* AYA NEO Founder */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYA NEO"),
+--
+2.39.5
+
--- /dev/null
+From be556156328a68b77cdcdc21a420c650301fb0cc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 22:24:49 +0000
+Subject: drm: panel-orientation-quirks: Add support for AYANEO 2S
+
+From: Andrew Wyatt <fewtarius@steamfork.org>
+
+[ Upstream commit eb8f1e3e8ee10cff591d4a47437dfd34d850d454 ]
+
+AYANEO 2S uses the same panel and orientation as the AYANEO 2.
+
+Update the AYANEO 2 DMI match to also match AYANEO 2S.
+
+Signed-off-by: Andrew Wyatt <fewtarius@steamfork.org>
+Signed-off-by: John Edwards <uejji@uejji.net>
+Tested-by: John Edwards <uejji@uejji.net>
+Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250213222455.93533-2-uejji@uejji.net
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_panel_orientation_quirks.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c
+index 4a73821b81f6f..f9c975338fc9e 100644
+--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
++++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
+@@ -184,10 +184,10 @@ static const struct dmi_system_id orientation_data[] = {
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T103HAF"),
+ },
+ .driver_data = (void *)&lcd800x1280_rightside_up,
+- }, { /* AYA NEO AYANEO 2 */
++ }, { /* AYA NEO AYANEO 2/2S */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"),
+- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "AYANEO 2"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "AYANEO 2"),
+ },
+ .driver_data = (void *)&lcd1200x1920_rightside_up,
+ }, { /* AYA NEO 2021 */
+--
+2.39.5
+
--- /dev/null
+From 767538acd765679cc31b4ec272967f8b2c4c80af Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jan 2025 21:50:15 +0530
+Subject: drm/xe/bmg: Add new PCI IDs
+
+From: Shekhar Chauhan <shekhar.chauhan@intel.com>
+
+[ Upstream commit fa8ffaae1b15236b8afb0fbbc04117ff7c900a83 ]
+
+Add 3 new PCI IDs for BMG.
+
+v2: Fix typo -> Replace '.' with ','
+
+Signed-off-by: Shekhar Chauhan <shekhar.chauhan@intel.com>
+Reviewed-by: Clint Taylor <Clinton.A.Taylor@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250128162015.3288675-1-shekhar.chauhan@intel.com
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/drm/intel/i915_pciids.h | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/include/drm/intel/i915_pciids.h b/include/drm/intel/i915_pciids.h
+index f35534522d333..dacea289acaf5 100644
+--- a/include/drm/intel/i915_pciids.h
++++ b/include/drm/intel/i915_pciids.h
+@@ -809,6 +809,9 @@
+ MACRO__(0xE20B, ## __VA_ARGS__), \
+ MACRO__(0xE20C, ## __VA_ARGS__), \
+ MACRO__(0xE20D, ## __VA_ARGS__), \
+- MACRO__(0xE212, ## __VA_ARGS__)
++ MACRO__(0xE210, ## __VA_ARGS__), \
++ MACRO__(0xE212, ## __VA_ARGS__), \
++ MACRO__(0xE215, ## __VA_ARGS__), \
++ MACRO__(0xE216, ## __VA_ARGS__)
+
+ #endif /* _I915_PCIIDS_H */
+--
+2.39.5
+
--- /dev/null
+From 2f06c862cd7408fb284db40496049909dc36d216 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jan 2025 19:25:02 +0100
+Subject: drm/xe/vf: Don't try to trigger a full GT reset if VF
+
+From: Michal Wajdeczko <michal.wajdeczko@intel.com>
+
+[ Upstream commit 459777724d306315070d24608fcd89aea85516d6 ]
+
+VFs don't have access to the GDRST(0x941c) register that driver
+uses to reset a GT. Attempt to trigger a reset using debugfs:
+
+ $ cat /sys/kernel/debug/dri/0000:00:02.1/gt0/force_reset
+
+or due to a hang condition detected by the driver leads to:
+
+ [ ] xe 0000:00:02.1: [drm] GT0: trying reset from force_reset [xe]
+ [ ] xe 0000:00:02.1: [drm] GT0: reset queued
+ [ ] xe 0000:00:02.1: [drm] GT0: reset started
+ [ ] ------------[ cut here ]------------
+ [ ] xe 0000:00:02.1: [drm] GT0: VF is trying to write 0x1 to an inaccessible register 0x941c+0x0
+ [ ] WARNING: CPU: 3 PID: 3069 at drivers/gpu/drm/xe/xe_gt_sriov_vf.c:996 xe_gt_sriov_vf_write32+0xc6/0x580 [xe]
+ [ ] RIP: 0010:xe_gt_sriov_vf_write32+0xc6/0x580 [xe]
+ [ ] Call Trace:
+ [ ] <TASK>
+ [ ] ? show_regs+0x6c/0x80
+ [ ] ? __warn+0x93/0x1c0
+ [ ] ? xe_gt_sriov_vf_write32+0xc6/0x580 [xe]
+ [ ] ? report_bug+0x182/0x1b0
+ [ ] ? handle_bug+0x6e/0xb0
+ [ ] ? exc_invalid_op+0x18/0x80
+ [ ] ? asm_exc_invalid_op+0x1b/0x20
+ [ ] ? xe_gt_sriov_vf_write32+0xc6/0x580 [xe]
+ [ ] ? xe_gt_sriov_vf_write32+0xc6/0x580 [xe]
+ [ ] ? xe_gt_tlb_invalidation_reset+0xef/0x110 [xe]
+ [ ] ? __mutex_unlock_slowpath+0x41/0x2e0
+ [ ] xe_mmio_write32+0x64/0x150 [xe]
+ [ ] do_gt_reset+0x2f/0xa0 [xe]
+ [ ] gt_reset_worker+0x14e/0x1e0 [xe]
+ [ ] process_one_work+0x21c/0x740
+ [ ] worker_thread+0x1db/0x3c0
+
+Fix that by sending H2G VF_RESET(0x5507) action instead.
+
+Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/4078
+Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
+Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250131182502.852-1-michal.wajdeczko@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_gt.c | 4 ++++
+ drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 16 ++++++++++++++++
+ drivers/gpu/drm/xe/xe_gt_sriov_vf.h | 1 +
+ 3 files changed, 21 insertions(+)
+
+diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
+index 98fe8573e054e..17ba15132a984 100644
+--- a/drivers/gpu/drm/xe/xe_gt.c
++++ b/drivers/gpu/drm/xe/xe_gt.c
+@@ -32,6 +32,7 @@
+ #include "xe_gt_pagefault.h"
+ #include "xe_gt_printk.h"
+ #include "xe_gt_sriov_pf.h"
++#include "xe_gt_sriov_vf.h"
+ #include "xe_gt_sysfs.h"
+ #include "xe_gt_tlb_invalidation.h"
+ #include "xe_gt_topology.h"
+@@ -647,6 +648,9 @@ static int do_gt_reset(struct xe_gt *gt)
+ {
+ int err;
+
++ if (IS_SRIOV_VF(gt_to_xe(gt)))
++ return xe_gt_sriov_vf_reset(gt);
++
+ xe_gsc_wa_14015076503(gt, true);
+
+ xe_mmio_write32(gt, GDRST, GRDOM_FULL);
+diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
+index 4ebc82e607af6..f982d6f9f218d 100644
+--- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
++++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
+@@ -57,6 +57,22 @@ static int vf_reset_guc_state(struct xe_gt *gt)
+ return err;
+ }
+
++/**
++ * xe_gt_sriov_vf_reset - Reset GuC VF internal state.
++ * @gt: the &xe_gt
++ *
++ * It requires functional `GuC MMIO based communication`_.
++ *
++ * Return: 0 on success or a negative error code on failure.
++ */
++int xe_gt_sriov_vf_reset(struct xe_gt *gt)
++{
++ if (!xe_device_uc_enabled(gt_to_xe(gt)))
++ return -ENODEV;
++
++ return vf_reset_guc_state(gt);
++}
++
+ static int guc_action_match_version(struct xe_guc *guc,
+ u32 wanted_branch, u32 wanted_major, u32 wanted_minor,
+ u32 *branch, u32 *major, u32 *minor, u32 *patch)
+diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h
+index e541ce57bec24..576ff5e795a8b 100644
+--- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h
++++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h
+@@ -12,6 +12,7 @@ struct drm_printer;
+ struct xe_gt;
+ struct xe_reg;
+
++int xe_gt_sriov_vf_reset(struct xe_gt *gt);
+ int xe_gt_sriov_vf_bootstrap(struct xe_gt *gt);
+ int xe_gt_sriov_vf_query_config(struct xe_gt *gt);
+ int xe_gt_sriov_vf_connect(struct xe_gt *gt);
+--
+2.39.5
+
--- /dev/null
+From b2ac498399d6d7cc25df177c632fd6fee598f979 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Feb 2025 10:13:01 +0000
+Subject: drm/xe/xelp: Move Wa_16011163337 from tunings to workarounds
+
+From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
+
+[ Upstream commit d9b5d83c5a4d720af6ddbefe2825c78f0325a3fd ]
+
+Workaround database specifies 16011163337 as a workaround so lets move it
+there.
+
+Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
+Cc: Lucas De Marchi <lucas.demarchi@intel.com>
+Cc: Matt Roper <matthew.d.roper@intel.com>
+Cc: Gustavo Sousa <gustavo.sousa@intel.com>
+Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250227101304.46660-3-tvrtko.ursulin@igalia.com
+Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_tuning.c | 8 --------
+ drivers/gpu/drm/xe/xe_wa.c | 7 +++++++
+ 2 files changed, 7 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_tuning.c b/drivers/gpu/drm/xe/xe_tuning.c
+index 0d5e04158917b..1fb12da21c9e4 100644
+--- a/drivers/gpu/drm/xe/xe_tuning.c
++++ b/drivers/gpu/drm/xe/xe_tuning.c
+@@ -97,14 +97,6 @@ static const struct xe_rtp_entry_sr engine_tunings[] = {
+ };
+
+ static const struct xe_rtp_entry_sr lrc_tunings[] = {
+- { XE_RTP_NAME("Tuning: ganged timer, also known as 16011163337"),
+- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, 1210), ENGINE_CLASS(RENDER)),
+- /* read verification is ignored due to 1608008084. */
+- XE_RTP_ACTIONS(FIELD_SET_NO_READ_MASK(FF_MODE2,
+- FF_MODE2_GS_TIMER_MASK,
+- FF_MODE2_GS_TIMER_224))
+- },
+-
+ /* DG2 */
+
+ { XE_RTP_NAME("Tuning: L3 cache"),
+diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c
+index 37e592b2bf062..0a1905f8d380a 100644
+--- a/drivers/gpu/drm/xe/xe_wa.c
++++ b/drivers/gpu/drm/xe/xe_wa.c
+@@ -606,6 +606,13 @@ static const struct xe_rtp_entry_sr engine_was[] = {
+ };
+
+ static const struct xe_rtp_entry_sr lrc_was[] = {
++ { XE_RTP_NAME("16011163337"),
++ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, 1210), ENGINE_CLASS(RENDER)),
++ /* read verification is ignored due to 1608008084. */
++ XE_RTP_ACTIONS(FIELD_SET_NO_READ_MASK(FF_MODE2,
++ FF_MODE2_GS_TIMER_MASK,
++ FF_MODE2_GS_TIMER_224))
++ },
+ { XE_RTP_NAME("1409342910, 14010698770, 14010443199, 1408979724, 1409178076, 1409207793, 1409217633, 1409252684, 1409347922, 1409142259"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, 1210)),
+ XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN3,
+--
+2.39.5
+
--- /dev/null
+From 3c96aa08d839d141a7a29fc4c874259410829a79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jan 2025 13:57:50 +0530
+Subject: ext4: ignore xattrs past end
+
+From: Bhupesh <bhupesh@igalia.com>
+
+[ Upstream commit c8e008b60492cf6fd31ef127aea6d02fd3d314cd ]
+
+Once inside 'ext4_xattr_inode_dec_ref_all' we should
+ignore xattrs entries past the 'end' entry.
+
+This fixes the following KASAN reported issue:
+
+==================================================================
+BUG: KASAN: slab-use-after-free in ext4_xattr_inode_dec_ref_all+0xb8c/0xe90
+Read of size 4 at addr ffff888012c120c4 by task repro/2065
+
+CPU: 1 UID: 0 PID: 2065 Comm: repro Not tainted 6.13.0-rc2+ #11
+Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x1fd/0x300
+ ? tcp_gro_dev_warn+0x260/0x260
+ ? _printk+0xc0/0x100
+ ? read_lock_is_recursive+0x10/0x10
+ ? irq_work_queue+0x72/0xf0
+ ? __virt_addr_valid+0x17b/0x4b0
+ print_address_description+0x78/0x390
+ print_report+0x107/0x1f0
+ ? __virt_addr_valid+0x17b/0x4b0
+ ? __virt_addr_valid+0x3ff/0x4b0
+ ? __phys_addr+0xb5/0x160
+ ? ext4_xattr_inode_dec_ref_all+0xb8c/0xe90
+ kasan_report+0xcc/0x100
+ ? ext4_xattr_inode_dec_ref_all+0xb8c/0xe90
+ ext4_xattr_inode_dec_ref_all+0xb8c/0xe90
+ ? ext4_xattr_delete_inode+0xd30/0xd30
+ ? __ext4_journal_ensure_credits+0x5f0/0x5f0
+ ? __ext4_journal_ensure_credits+0x2b/0x5f0
+ ? inode_update_timestamps+0x410/0x410
+ ext4_xattr_delete_inode+0xb64/0xd30
+ ? ext4_truncate+0xb70/0xdc0
+ ? ext4_expand_extra_isize_ea+0x1d20/0x1d20
+ ? __ext4_mark_inode_dirty+0x670/0x670
+ ? ext4_journal_check_start+0x16f/0x240
+ ? ext4_inode_is_fast_symlink+0x2f2/0x3a0
+ ext4_evict_inode+0xc8c/0xff0
+ ? ext4_inode_is_fast_symlink+0x3a0/0x3a0
+ ? do_raw_spin_unlock+0x53/0x8a0
+ ? ext4_inode_is_fast_symlink+0x3a0/0x3a0
+ evict+0x4ac/0x950
+ ? proc_nr_inodes+0x310/0x310
+ ? trace_ext4_drop_inode+0xa2/0x220
+ ? _raw_spin_unlock+0x1a/0x30
+ ? iput+0x4cb/0x7e0
+ do_unlinkat+0x495/0x7c0
+ ? try_break_deleg+0x120/0x120
+ ? 0xffffffff81000000
+ ? __check_object_size+0x15a/0x210
+ ? strncpy_from_user+0x13e/0x250
+ ? getname_flags+0x1dc/0x530
+ __x64_sys_unlinkat+0xc8/0xf0
+ do_syscall_64+0x65/0x110
+ entry_SYSCALL_64_after_hwframe+0x67/0x6f
+RIP: 0033:0x434ffd
+Code: 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 8
+RSP: 002b:00007ffc50fa7b28 EFLAGS: 00000246 ORIG_RAX: 0000000000000107
+RAX: ffffffffffffffda RBX: 00007ffc50fa7e18 RCX: 0000000000434ffd
+RDX: 0000000000000000 RSI: 0000000020000240 RDI: 0000000000000005
+RBP: 00007ffc50fa7be0 R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001
+R13: 00007ffc50fa7e08 R14: 00000000004bbf30 R15: 0000000000000001
+ </TASK>
+
+The buggy address belongs to the object at ffff888012c12000
+ which belongs to the cache filp of size 360
+The buggy address is located 196 bytes inside of
+ freed 360-byte region [ffff888012c12000, ffff888012c12168)
+
+The buggy address belongs to the physical page:
+page: refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x12c12
+head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
+flags: 0x40(head|node=0|zone=0)
+page_type: f5(slab)
+raw: 0000000000000040 ffff888000ad7640 ffffea0000497a00 dead000000000004
+raw: 0000000000000000 0000000000100010 00000001f5000000 0000000000000000
+head: 0000000000000040 ffff888000ad7640 ffffea0000497a00 dead000000000004
+head: 0000000000000000 0000000000100010 00000001f5000000 0000000000000000
+head: 0000000000000001 ffffea00004b0481 ffffffffffffffff 0000000000000000
+head: 0000000000000002 0000000000000000 00000000ffffffff 0000000000000000
+page dumped because: kasan: bad access detected
+
+Memory state around the buggy address:
+ ffff888012c11f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ ffff888012c12000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+> ffff888012c12080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+ ^
+ ffff888012c12100: fb fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc
+ ffff888012c12180: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+==================================================================
+
+Reported-by: syzbot+b244bda78289b00204ed@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=b244bda78289b00204ed
+Suggested-by: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
+Signed-off-by: Bhupesh <bhupesh@igalia.com>
+Link: https://patch.msgid.link/20250128082751.124948-2-bhupesh@igalia.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/xattr.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 7647e9f6e1903..6ff94cdf1515c 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -1176,15 +1176,24 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
+ {
+ struct inode *ea_inode;
+ struct ext4_xattr_entry *entry;
++ struct ext4_iloc iloc;
+ bool dirty = false;
+ unsigned int ea_ino;
+ int err;
+ int credits;
++ void *end;
++
++ if (block_csum)
++ end = (void *)bh->b_data + bh->b_size;
++ else {
++ ext4_get_inode_loc(parent, &iloc);
++ end = (void *)ext4_raw_inode(&iloc) + EXT4_SB(parent->i_sb)->s_inode_size;
++ }
+
+ /* One credit for dec ref on ea_inode, one for orphan list addition, */
+ credits = 2 + extra_credits;
+
+- for (entry = first; !IS_LAST_ENTRY(entry);
++ for (entry = first; (void *)entry < end && !IS_LAST_ENTRY(entry);
+ entry = EXT4_XATTR_NEXT(entry)) {
+ if (!entry->e_value_inum)
+ continue;
+--
+2.39.5
+
--- /dev/null
+From de9d69d47a465f843588e7b443adf0560787acaf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Nov 2024 18:08:55 +0530
+Subject: ext4: protect ext4_release_dquot against freezing
+
+From: Ojaswin Mujoo <ojaswin@linux.ibm.com>
+
+[ Upstream commit 530fea29ef82e169cd7fe048c2b7baaeb85a0028 ]
+
+Protect ext4_release_dquot against freezing so that we
+don't try to start a transaction when FS is frozen, leading
+to warnings.
+
+Further, avoid taking the freeze protection if a transaction
+is already running so that we don't need end up in a deadlock
+as described in
+
+ 46e294efc355 ext4: fix deadlock with fs freezing and EA inodes
+
+Suggested-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
+Reviewed-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20241121123855.645335-3-ojaswin@linux.ibm.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/super.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index d3795c6c0a9d8..4291ab3c20be6 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -6906,12 +6906,25 @@ static int ext4_release_dquot(struct dquot *dquot)
+ {
+ int ret, err;
+ handle_t *handle;
++ bool freeze_protected = false;
++
++ /*
++ * Trying to sb_start_intwrite() in a running transaction
++ * can result in a deadlock. Further, running transactions
++ * are already protected from freezing.
++ */
++ if (!ext4_journal_current_handle()) {
++ sb_start_intwrite(dquot->dq_sb);
++ freeze_protected = true;
++ }
+
+ handle = ext4_journal_start(dquot_to_inode(dquot), EXT4_HT_QUOTA,
+ EXT4_QUOTA_DEL_BLOCKS(dquot->dq_sb));
+ if (IS_ERR(handle)) {
+ /* Release dquot anyway to avoid endless cycle in dqput() */
+ dquot_release(dquot);
++ if (freeze_protected)
++ sb_end_intwrite(dquot->dq_sb);
+ return PTR_ERR(handle);
+ }
+ ret = dquot_release(dquot);
+@@ -6922,6 +6935,10 @@ static int ext4_release_dquot(struct dquot *dquot)
+ err = ext4_journal_stop(handle);
+ if (!ret)
+ ret = err;
++
++ if (freeze_protected)
++ sb_end_intwrite(dquot->dq_sb);
++
+ return ret;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From e74d9b205422d92fcacb3ab6fe0a2fcec01f38f0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Feb 2025 15:36:32 +0800
+Subject: f2fs: don't retry IO for corrupted data scenario
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 1534747d3170646ddeb9ea5f7caaac90359707cf ]
+
+F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942]
+F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942]
+F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942]
+F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942]
+F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942]
+F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942]
+F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942]
+F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942]
+F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942]
+F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942]
+
+If node block is loaded successfully, but its content is inconsistent, it
+doesn't need to retry IO.
+
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/inode.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
+index 10780e37fc7b6..6135eee771cc9 100644
+--- a/fs/f2fs/inode.c
++++ b/fs/f2fs/inode.c
+@@ -751,8 +751,12 @@ void f2fs_update_inode_page(struct inode *inode)
+ if (err == -ENOENT)
+ return;
+
++ if (err == -EFSCORRUPTED)
++ goto stop_checkpoint;
++
+ if (err == -ENOMEM || ++count <= DEFAULT_RETRY_IO_COUNT)
+ goto retry;
++stop_checkpoint:
+ f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_UPDATE_INODE);
+ return;
+ }
+--
+2.39.5
+
--- /dev/null
+From 61805a483a1f6e1098fa917fb53b410861d9183d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Mar 2025 11:47:38 +0800
+Subject: f2fs: fix to avoid out-of-bounds access in
+ f2fs_truncate_inode_blocks()
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit e6494977bd4a83862118a05f57a8df40256951c0 ]
+
+syzbot reports an UBSAN issue as below:
+
+------------[ cut here ]------------
+UBSAN: array-index-out-of-bounds in fs/f2fs/node.h:381:10
+index 18446744073709550692 is out of range for type '__le32[5]' (aka 'unsigned int[5]')
+CPU: 0 UID: 0 PID: 5318 Comm: syz.0.0 Not tainted 6.14.0-rc3-syzkaller-00060-g6537cfb395f3 #0
+Call Trace:
+ <TASK>
+ __dump_stack lib/dump_stack.c:94 [inline]
+ dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120
+ ubsan_epilogue lib/ubsan.c:231 [inline]
+ __ubsan_handle_out_of_bounds+0x121/0x150 lib/ubsan.c:429
+ get_nid fs/f2fs/node.h:381 [inline]
+ f2fs_truncate_inode_blocks+0xa5e/0xf60 fs/f2fs/node.c:1181
+ f2fs_do_truncate_blocks+0x782/0x1030 fs/f2fs/file.c:808
+ f2fs_truncate_blocks+0x10d/0x300 fs/f2fs/file.c:836
+ f2fs_truncate+0x417/0x720 fs/f2fs/file.c:886
+ f2fs_file_write_iter+0x1bdb/0x2550 fs/f2fs/file.c:5093
+ aio_write+0x56b/0x7c0 fs/aio.c:1633
+ io_submit_one+0x8a7/0x18a0 fs/aio.c:2052
+ __do_sys_io_submit fs/aio.c:2111 [inline]
+ __se_sys_io_submit+0x171/0x2e0 fs/aio.c:2081
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7f238798cde9
+
+index 18446744073709550692 (decimal, unsigned long long)
+= 0xfffffffffffffc64 (hexadecimal, unsigned long long)
+= -924 (decimal, long long)
+
+In f2fs_truncate_inode_blocks(), UBSAN detects that get_nid() tries to
+access .i_nid[-924], it means both offset[0] and level should zero.
+
+The possible case should be in f2fs_do_truncate_blocks(), we try to
+truncate inode size to zero, however, dn.ofs_in_node is zero and
+dn.node_page is not an inode page, so it fails to truncate inode page,
+and then pass zeroed free_from to f2fs_truncate_inode_blocks(), result
+in this issue.
+
+ if (dn.ofs_in_node || IS_INODE(dn.node_page)) {
+ f2fs_truncate_data_blocks_range(&dn, count);
+ free_from += count;
+ }
+
+I guess the reason why dn.node_page is not an inode page could be: there
+are multiple nat entries share the same node block address, once the node
+block address was reused, f2fs_get_node_page() may load a non-inode block.
+
+Let's add a sanity check for such condition to avoid out-of-bounds access
+issue.
+
+Reported-by: syzbot+6653f10281a1badc749e@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/all/66fdcdf3.050a0220.40bef.0025.GAE@google.com
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/node.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
+index 4d7b9fd6ef31a..9fc07737d8661 100644
+--- a/fs/f2fs/node.c
++++ b/fs/f2fs/node.c
+@@ -1134,7 +1134,14 @@ int f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from)
+ trace_f2fs_truncate_inode_blocks_enter(inode, from);
+
+ level = get_node_path(inode, from, offset, noffset);
+- if (level < 0) {
++ if (level <= 0) {
++ if (!level) {
++ level = -EFSCORRUPTED;
++ f2fs_err(sbi, "%s: inode ino=%lx has corrupted node block, from:%lu addrs:%u",
++ __func__, inode->i_ino,
++ from, ADDRS_PER_INODE(inode));
++ set_sbi_flag(sbi, SBI_NEED_FSCK);
++ }
+ trace_f2fs_truncate_inode_blocks_exit(inode, level);
+ return level;
+ }
+--
+2.39.5
+
--- /dev/null
+From 78c8f6aabedc845b96c822ba9538136a73b2caf8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Mar 2025 21:19:52 +0000
+Subject: fbdev: omapfb: Add 'plane' value check
+
+From: Leonid Arapov <arapovl839@gmail.com>
+
+[ Upstream commit 3e411827f31db7f938a30a3c7a7599839401ec30 ]
+
+Function dispc_ovl_setup is not intended to work with the value OMAP_DSS_WB
+of the enum parameter plane.
+
+The value of this parameter is initialized in dss_init_overlays and in the
+current state of the code it cannot take this value so it's not a real
+problem.
+
+For the purposes of defensive coding it wouldn't be superfluous to check
+the parameter value, because some functions down the call stack process
+this value correctly and some not.
+
+For example, in dispc_ovl_setup_global_alpha it may lead to buffer
+overflow.
+
+Add check for this value.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE static
+analysis tool.
+
+Signed-off-by: Leonid Arapov <arapovl839@gmail.com>
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/fbdev/omap2/omapfb/dss/dispc.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dispc.c b/drivers/video/fbdev/omap2/omapfb/dss/dispc.c
+index 5832485ab998c..c29b6236952b3 100644
+--- a/drivers/video/fbdev/omap2/omapfb/dss/dispc.c
++++ b/drivers/video/fbdev/omap2/omapfb/dss/dispc.c
+@@ -2749,9 +2749,13 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
+ bool mem_to_mem)
+ {
+ int r;
+- enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
++ enum omap_overlay_caps caps;
+ enum omap_channel channel;
+
++ if (plane == OMAP_DSS_WB)
++ return -EINVAL;
++
++ caps = dss_feat_get_overlay_caps(plane);
+ channel = dispc_ovl_get_channel_out(plane);
+
+ DSSDBG("dispc_ovl_setup %d, pa %pad, pa_uv %pad, sw %d, %d,%d, %dx%d ->"
+--
+2.39.5
+
--- /dev/null
+From 13bde86cf665585db86ced80b3d0d2a7eb1f88f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 10:33:28 -0800
+Subject: Flush console log from kernel_power_off()
+
+From: Paul E. McKenney <paulmck@kernel.org>
+
+[ Upstream commit 6ea9a1781c70a8be1fcdc49134fc1bf4baba8bca ]
+
+Kernels built with CONFIG_PREEMPT_RT=y can lose significant console output
+and shutdown time, which hides shutdown-time RCU issues from rcutorture.
+Therefore, make pr_flush() public and invoke it after then last print
+in kernel_power_off().
+
+[ paulmck: Apply John Ogness feedback. ]
+[ paulmck: Appy Sebastian Andrzej Siewior feedback. ]
+[ paulmck: Apply kernel test robot feedback. ]
+
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Reviewed-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
+Link: https://lore.kernel.org/r/5f743488-dc2a-4f19-bdda-cf50b9314832@paulmck-laptop
+Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/printk.h | 6 ++++++
+ kernel/printk/printk.c | 4 +---
+ kernel/reboot.c | 1 +
+ 3 files changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/include/linux/printk.h b/include/linux/printk.h
+index eca9bb2ee637b..0cb647ecd77f5 100644
+--- a/include/linux/printk.h
++++ b/include/linux/printk.h
+@@ -204,6 +204,7 @@ void printk_legacy_allow_panic_sync(void);
+ extern bool nbcon_device_try_acquire(struct console *con);
+ extern void nbcon_device_release(struct console *con);
+ void nbcon_atomic_flush_unsafe(void);
++bool pr_flush(int timeout_ms, bool reset_on_progress);
+ #else
+ static inline __printf(1, 0)
+ int vprintk(const char *s, va_list args)
+@@ -304,6 +305,11 @@ static inline void nbcon_atomic_flush_unsafe(void)
+ {
+ }
+
++static inline bool pr_flush(int timeout_ms, bool reset_on_progress)
++{
++ return true;
++}
++
+ #endif
+
+ bool this_cpu_in_panic(void);
+diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
+index 3b75f6e8410b9..881a26e18c658 100644
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2436,7 +2436,6 @@ asmlinkage __visible int _printk(const char *fmt, ...)
+ }
+ EXPORT_SYMBOL(_printk);
+
+-static bool pr_flush(int timeout_ms, bool reset_on_progress);
+ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress);
+
+ #else /* CONFIG_PRINTK */
+@@ -2449,7 +2448,6 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
+
+ static u64 syslog_seq;
+
+-static bool pr_flush(int timeout_ms, bool reset_on_progress) { return true; }
+ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress) { return true; }
+
+ #endif /* CONFIG_PRINTK */
+@@ -4436,7 +4434,7 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
+ * Context: Process context. May sleep while acquiring console lock.
+ * Return: true if all usable printers are caught up.
+ */
+-static bool pr_flush(int timeout_ms, bool reset_on_progress)
++bool pr_flush(int timeout_ms, bool reset_on_progress)
+ {
+ return __pr_flush(NULL, timeout_ms, reset_on_progress);
+ }
+diff --git a/kernel/reboot.c b/kernel/reboot.c
+index f05dbde2c93fe..d6ee090eda943 100644
+--- a/kernel/reboot.c
++++ b/kernel/reboot.c
+@@ -697,6 +697,7 @@ void kernel_power_off(void)
+ migrate_to_reboot_cpu();
+ syscore_shutdown();
+ pr_emerg("Power down\n");
++ pr_flush(1000, true);
+ kmsg_dump(KMSG_DUMP_SHUTDOWN);
+ machine_power_off();
+ }
+--
+2.39.5
+
--- /dev/null
+From ccdd0ba96337c19794dad47c1bb6d249edbda7b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Mar 2025 14:57:25 +0100
+Subject: fs: consistently deref the files table with rcu_dereference_raw()
+
+From: Mateusz Guzik <mjguzik@gmail.com>
+
+[ Upstream commit f381640e1bd4f2de7ccafbfe8703d33c3718aad9 ]
+
+... except when the table is known to be only used by one thread.
+
+A file pointer can get installed at any moment despite the ->file_lock
+being held since the following:
+8a81252b774b53e6 ("fs/file.c: don't acquire files->file_lock in fd_install()")
+
+Accesses subject to such a race can in principle suffer load tearing.
+
+While here redo the comment in dup_fd -- it only covered a race against
+files showing up, still assuming fd_install() takes the lock.
+
+Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
+Link: https://lore.kernel.org/r/20250313135725.1320914-1-mjguzik@gmail.com
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/file.c | 26 +++++++++++++++++---------
+ 1 file changed, 17 insertions(+), 9 deletions(-)
+
+diff --git a/fs/file.c b/fs/file.c
+index 4cb952541dd03..b6fb6d18ac3b9 100644
+--- a/fs/file.c
++++ b/fs/file.c
+@@ -367,17 +367,25 @@ struct files_struct *dup_fd(struct files_struct *oldf, struct fd_range *punch_ho
+ old_fds = old_fdt->fd;
+ new_fds = new_fdt->fd;
+
++ /*
++ * We may be racing against fd allocation from other threads using this
++ * files_struct, despite holding ->file_lock.
++ *
++ * alloc_fd() might have already claimed a slot, while fd_install()
++ * did not populate it yet. Note the latter operates locklessly, so
++ * the file can show up as we are walking the array below.
++ *
++ * At the same time we know no files will disappear as all other
++ * operations take the lock.
++ *
++ * Instead of trying to placate userspace racing with itself, we
++ * ref the file if we see it and mark the fd slot as unused otherwise.
++ */
+ for (i = open_files; i != 0; i--) {
+- struct file *f = *old_fds++;
++ struct file *f = rcu_dereference_raw(*old_fds++);
+ if (f) {
+ get_file(f);
+ } else {
+- /*
+- * The fd may be claimed in the fd bitmap but not yet
+- * instantiated in the files array if a sibling thread
+- * is partway through open(). So make sure that this
+- * fd is available to the new process.
+- */
+ __clear_open_fd(open_files - i, new_fdt);
+ }
+ rcu_assign_pointer(*new_fds++, f);
+@@ -637,7 +645,7 @@ struct file *file_close_fd_locked(struct files_struct *files, unsigned fd)
+ return NULL;
+
+ fd = array_index_nospec(fd, fdt->max_fds);
+- file = fdt->fd[fd];
++ file = rcu_dereference_raw(fdt->fd[fd]);
+ if (file) {
+ rcu_assign_pointer(fdt->fd[fd], NULL);
+ __put_unused_fd(files, fd);
+@@ -1219,7 +1227,7 @@ __releases(&files->file_lock)
+ */
+ fdt = files_fdtable(files);
+ fd = array_index_nospec(fd, fdt->max_fds);
+- tofree = fdt->fd[fd];
++ tofree = rcu_dereference_raw(fdt->fd[fd]);
+ if (!tofree && fd_is_open(fd, fdt))
+ goto Ebusy;
+ get_file(file);
+--
+2.39.5
+
--- /dev/null
+From 0792d19a43ce035537f7e3370bf9b443c8600863 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 12:43:49 +0300
+Subject: fs/jfs: cast inactags to s64 to prevent potential overflow
+
+From: Rand Deeb <rand.sec96@gmail.com>
+
+[ Upstream commit 70ca3246ad201b53a9f09380b3f29d8bac320383 ]
+
+The expression "inactags << bmp->db_agl2size" in the function
+dbFinalizeBmap() is computed using int operands. Although the
+values (inactags and db_agl2size) are derived from filesystem
+parameters and are usually small, there is a theoretical risk that
+the shift could overflow a 32-bit int if extreme values occur.
+
+According to the C standard, shifting a signed 32-bit int can lead
+to undefined behavior if the result exceeds its range. In our
+case, an overflow could miscalculate free blocks, potentially
+leading to erroneous filesystem accounting.
+
+To ensure the arithmetic is performed in 64-bit space, we cast
+"inactags" to s64 before shifting. This defensive fix prevents any
+risk of overflow and complies with kernel coding best practices.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Signed-off-by: Rand Deeb <rand.sec96@gmail.com>
+Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jfs/jfs_dmap.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
+index f9009e4f9ffd8..f89f07c9580ea 100644
+--- a/fs/jfs/jfs_dmap.c
++++ b/fs/jfs/jfs_dmap.c
+@@ -3666,8 +3666,8 @@ void dbFinalizeBmap(struct inode *ipbmap)
+ * system size is not a multiple of the group size).
+ */
+ inactfree = (inactags && ag_rem) ?
+- ((inactags - 1) << bmp->db_agl2size) + ag_rem
+- : inactags << bmp->db_agl2size;
++ (((s64)inactags - 1) << bmp->db_agl2size) + ag_rem
++ : ((s64)inactags << bmp->db_agl2size);
+
+ /* determine how many free blocks are in the active
+ * allocation groups plus the average number of free blocks
+--
+2.39.5
+
--- /dev/null
+From 2b403980a6d405e42f1eafd266a43eae2072fea6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 12:52:31 +0300
+Subject: fs/jfs: Prevent integer overflow in AG size calculation
+
+From: Rand Deeb <rand.sec96@gmail.com>
+
+[ Upstream commit 7fcbf789629cdb9fbf4e2172ce31136cfed11e5e ]
+
+The JFS filesystem calculates allocation group (AG) size using 1 <<
+l2agsize in dbExtendFS(). When l2agsize exceeds 31 (possible with >2TB
+aggregates on 32-bit systems), this 32-bit shift operation causes undefined
+behavior and improper AG sizing.
+
+On 32-bit architectures:
+- Left-shifting 1 by 32+ bits results in 0 due to integer overflow
+- This creates invalid AG sizes (0 or garbage values) in
+sbi->bmap->db_agsize
+- Subsequent block allocations would reference invalid AG structures
+- Could lead to:
+ - Filesystem corruption during extend operations
+ - Kernel crashes due to invalid memory accesses
+ - Security vulnerabilities via malformed on-disk structures
+
+Fix by casting to s64 before shifting:
+bmp->db_agsize = (s64)1 << l2agsize;
+
+This ensures 64-bit arithmetic even on 32-bit architectures. The cast
+matches the data type of db_agsize (s64) and follows similar patterns in
+JFS block calculation code.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Signed-off-by: Rand Deeb <rand.sec96@gmail.com>
+Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jfs/jfs_dmap.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
+index f89f07c9580ea..9ac1fc2ed05bc 100644
+--- a/fs/jfs/jfs_dmap.c
++++ b/fs/jfs/jfs_dmap.c
+@@ -3403,7 +3403,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks)
+ oldl2agsize = bmp->db_agl2size;
+
+ bmp->db_agl2size = l2agsize;
+- bmp->db_agsize = 1 << l2agsize;
++ bmp->db_agsize = (s64)1 << l2agsize;
+
+ /* compute new number of AG */
+ agno = bmp->db_numag;
+--
+2.39.5
+
--- /dev/null
+From 059325f54306b96ac82dea42a614d32095c799ce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:38:54 +0100
+Subject: HID: Add hid-universal-pidff driver and supported device ids
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit f06bf8d94fffbb544b1cb5402c92e0a075f0d420 ]
+
+Extend pidff compatibility, usable button range, manage pidff quirks and
+set improved fuzz/flat default for high precision devices. Possibility
+of fixing device descriptors in the future if such needs arises.
+
+As many of PID devices are quite similar and not dependent on
+custom drivers, this one can handle all of PID devices which
+need special care.
+
+Numerous sim racing/sim flight bases report a lot of buttons
+in excess of 100. Moza Racing exposes 128 of them and thus
+the need to extend the available range.
+
+All the included devices were tested and confirmed working
+with the help of the sim racing community.
+
+Changes in v6:
+- Support "split" devices with a separate "input device" for buttons
+- Fixed comment styling
+
+Co-developed-by: Makarenko Oleg <oleg@makarenk.ooo>
+Signed-off-by: Makarenko Oleg <oleg@makarenk.ooo>
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Reviewed-by: Michał Kopeć <michal@nozomi.space>
+Reviewed-by: Paul Dino Jones <paul@spacefreak18.xyz>
+Tested-by: Cristóferson Bueno <cbueno81@gmail.com>
+Tested-by: Pablo Cisneros <patchkez@protonmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/Kconfig | 14 +++
+ drivers/hid/Makefile | 1 +
+ drivers/hid/hid-ids.h | 31 +++++
+ drivers/hid/hid-universal-pidff.c | 192 ++++++++++++++++++++++++++++++
+ 4 files changed, 238 insertions(+)
+ create mode 100644 drivers/hid/hid-universal-pidff.c
+
+diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
+index 4500d7653b05e..95a4ede270991 100644
+--- a/drivers/hid/Kconfig
++++ b/drivers/hid/Kconfig
+@@ -1205,6 +1205,20 @@ config HID_U2FZERO
+ allow setting the brightness to anything but 1, which will
+ trigger a single blink and immediately reset back to 0.
+
++config HID_UNIVERSAL_PIDFF
++ tristate "universal-pidff: extended USB PID driver compatibility and usage"
++ depends on USB_HID
++ depends on HID_PID
++ help
++ Extended PID support for selected devices.
++
++ Contains report fixups, extended usable button range and
++ pidff quirk management to extend compatibility with slightly
++ non-compliant USB PID devices and better fuzz/flat values for
++ high precision direct drive devices.
++
++ Supports Moza Racing, Cammus, VRS, FFBeast and more.
++
+ config HID_WACOM
+ tristate "Wacom Intuos/Graphire tablet support (USB)"
+ depends on USB_HID
+diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
+index f2900ee2ef858..27ee02bf6f26d 100644
+--- a/drivers/hid/Makefile
++++ b/drivers/hid/Makefile
+@@ -139,6 +139,7 @@ hid-uclogic-objs := hid-uclogic-core.o \
+ hid-uclogic-params.o
+ obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o
+ obj-$(CONFIG_HID_UDRAW_PS3) += hid-udraw-ps3.o
++obj-$(CONFIG_HID_UNIVERSAL_PIDFF) += hid-universal-pidff.o
+ obj-$(CONFIG_HID_LED) += hid-led.o
+ obj-$(CONFIG_HID_XIAOMI) += hid-xiaomi.o
+ obj-$(CONFIG_HID_XINMO) += hid-xinmo.o
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index c6ae7c4268b84..08be87b3cc990 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -262,6 +262,10 @@
+ #define USB_DEVICE_ID_BTC_EMPREX_REMOTE 0x5578
+ #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2 0x5577
+
++#define USB_VENDOR_ID_CAMMUS 0x3416
++#define USB_DEVICE_ID_CAMMUS_C5 0x0301
++#define USB_DEVICE_ID_CAMMUS_C12 0x0302
++
+ #define USB_VENDOR_ID_CANDO 0x2087
+ #define USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH 0x0703
+ #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01
+@@ -453,6 +457,11 @@
+ #define USB_VENDOR_ID_EVISION 0x320f
+ #define USB_DEVICE_ID_EVISION_ICL01 0x5041
+
++#define USB_VENDOR_ID_FFBEAST 0x045b
++#define USB_DEVICE_ID_FFBEAST_JOYSTICK 0x58f9
++#define USB_DEVICE_ID_FFBEAST_RUDDER 0x5968
++#define USB_DEVICE_ID_FFBEAST_WHEEL 0x59d7
++
+ #define USB_VENDOR_ID_FLATFROG 0x25b5
+ #define USB_DEVICE_ID_MULTITOUCH_3200 0x0002
+
+@@ -813,6 +822,13 @@
+ #define I2C_DEVICE_ID_LG_8001 0x8001
+ #define I2C_DEVICE_ID_LG_7010 0x7010
+
++#define USB_VENDOR_ID_LITE_STAR 0x11ff
++#define USB_DEVICE_ID_PXN_V10 0x3245
++#define USB_DEVICE_ID_PXN_V12 0x1212
++#define USB_DEVICE_ID_PXN_V12_LITE 0x1112
++#define USB_DEVICE_ID_PXN_V12_LITE_2 0x1211
++#define USB_DEVICE_LITE_STAR_GT987_FF 0x2141
++
+ #define USB_VENDOR_ID_LOGITECH 0x046d
+ #define USB_DEVICE_ID_LOGITECH_Z_10_SPK 0x0a07
+ #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
+@@ -960,6 +976,18 @@
+ #define USB_VENDOR_ID_MONTEREY 0x0566
+ #define USB_DEVICE_ID_GENIUS_KB29E 0x3004
+
++#define USB_VENDOR_ID_MOZA 0x346e
++#define USB_DEVICE_ID_MOZA_R3 0x0005
++#define USB_DEVICE_ID_MOZA_R3_2 0x0015
++#define USB_DEVICE_ID_MOZA_R5 0x0004
++#define USB_DEVICE_ID_MOZA_R5_2 0x0014
++#define USB_DEVICE_ID_MOZA_R9 0x0002
++#define USB_DEVICE_ID_MOZA_R9_2 0x0012
++#define USB_DEVICE_ID_MOZA_R12 0x0006
++#define USB_DEVICE_ID_MOZA_R12_2 0x0016
++#define USB_DEVICE_ID_MOZA_R16_R21 0x0000
++#define USB_DEVICE_ID_MOZA_R16_R21_2 0x0010
++
+ #define USB_VENDOR_ID_MSI 0x1770
+ #define USB_DEVICE_ID_MSI_GT683R_LED_PANEL 0xff00
+
+@@ -1371,6 +1399,9 @@
+ #define USB_DEVICE_ID_VELLEMAN_K8061_FIRST 0x8061
+ #define USB_DEVICE_ID_VELLEMAN_K8061_LAST 0x8068
+
++#define USB_VENDOR_ID_VRS 0x0483
++#define USB_DEVICE_ID_VRS_DFP 0xa355
++
+ #define USB_VENDOR_ID_VTL 0x0306
+ #define USB_DEVICE_ID_VTL_MULTITOUCH_FF3F 0xff3f
+
+diff --git a/drivers/hid/hid-universal-pidff.c b/drivers/hid/hid-universal-pidff.c
+new file mode 100644
+index 0000000000000..55aad2e4ac1b8
+--- /dev/null
++++ b/drivers/hid/hid-universal-pidff.c
+@@ -0,0 +1,192 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * HID UNIVERSAL PIDFF
++ * hid-pidff wrapper for PID-enabled devices
++ * Handles device reports, quirks and extends usable button range
++ *
++ * Copyright (c) 2024, 2025 Makarenko Oleg
++ * Copyright (c) 2024, 2025 Tomasz Pakuła
++ */
++
++#include <linux/device.h>
++#include <linux/hid.h>
++#include <linux/module.h>
++#include <linux/input-event-codes.h>
++#include "hid-ids.h"
++
++#define JOY_RANGE (BTN_DEAD - BTN_JOYSTICK + 1)
++
++/*
++ * Map buttons manually to extend the default joystick button limit
++ */
++static int universal_pidff_input_mapping(struct hid_device *hdev,
++ struct hid_input *hi, struct hid_field *field, struct hid_usage *usage,
++ unsigned long **bit, int *max)
++{
++ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
++ return 0;
++
++ if (field->application != HID_GD_JOYSTICK)
++ return 0;
++
++ int button = ((usage->hid - 1) & HID_USAGE);
++ int code = button + BTN_JOYSTICK;
++
++ /* Detect the end of JOYSTICK buttons range */
++ if (code > BTN_DEAD)
++ code = button + KEY_NEXT_FAVORITE - JOY_RANGE;
++
++ /*
++ * Map overflowing buttons to KEY_RESERVED to not ignore
++ * them and let them still trigger MSC_SCAN
++ */
++ if (code > KEY_MAX)
++ code = KEY_RESERVED;
++
++ hid_map_usage(hi, usage, bit, max, EV_KEY, code);
++ hid_dbg(hdev, "Button %d: usage %d", button, code);
++ return 1;
++}
++
++/*
++ * Check if the device is PID and initialize it
++ * Add quirks after initialisation
++ */
++static int universal_pidff_probe(struct hid_device *hdev,
++ const struct hid_device_id *id)
++{
++ int i, error;
++ error = hid_parse(hdev);
++ if (error) {
++ hid_err(hdev, "HID parse failed\n");
++ goto err;
++ }
++
++ error = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
++ if (error) {
++ hid_err(hdev, "HID hw start failed\n");
++ goto err;
++ }
++
++ /* Check if device contains PID usage page */
++ error = 1;
++ for (i = 0; i < hdev->collection_size; i++)
++ if ((hdev->collection[i].usage & HID_USAGE_PAGE) == HID_UP_PID) {
++ error = 0;
++ hid_dbg(hdev, "PID usage page found\n");
++ break;
++ }
++
++ /*
++ * Do not fail as this might be the second "device"
++ * just for additional buttons/axes. Exit cleanly if force
++ * feedback usage page wasn't found (included devices were
++ * tested and confirmed to be USB PID after all).
++ */
++ if (error) {
++ hid_dbg(hdev, "PID usage page not found in the descriptor\n");
++ return 0;
++ }
++
++ /* Check if HID_PID support is enabled */
++ int (*init_function)(struct hid_device *, __u32);
++ init_function = hid_pidff_init_with_quirks;
++
++ if (!init_function) {
++ hid_warn(hdev, "HID_PID support not enabled!\n");
++ return 0;
++ }
++
++ error = init_function(hdev, id->driver_data);
++ if (error) {
++ hid_warn(hdev, "Error initialising force feedback\n");
++ goto err;
++ }
++
++ hid_info(hdev, "Universal pidff driver loaded sucesfully!");
++
++ return 0;
++err:
++ return error;
++}
++
++static int universal_pidff_input_configured(struct hid_device *hdev,
++ struct hid_input *hidinput)
++{
++ int axis;
++ struct input_dev *input = hidinput->input;
++
++ if (!input->absinfo)
++ return 0;
++
++ /* Decrease fuzz and deadzone on available axes */
++ for (axis = ABS_X; axis <= ABS_BRAKE; axis++) {
++ if (!test_bit(axis, input->absbit))
++ continue;
++
++ input_set_abs_params(input, axis,
++ input->absinfo[axis].minimum,
++ input->absinfo[axis].maximum,
++ axis == ABS_X ? 0 : 8, 0);
++ }
++
++ /* Remove fuzz and deadzone from the second joystick axis */
++ if (hdev->vendor == USB_VENDOR_ID_FFBEAST &&
++ hdev->product == USB_DEVICE_ID_FFBEAST_JOYSTICK)
++ input_set_abs_params(input, ABS_Y,
++ input->absinfo[ABS_Y].minimum,
++ input->absinfo[ABS_Y].maximum, 0, 0);
++
++ return 0;
++}
++
++static const struct hid_device_id universal_pidff_devices[] = {
++ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R3),
++ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
++ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R3_2),
++ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
++ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R5),
++ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
++ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R5_2),
++ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
++ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R9),
++ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
++ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R9_2),
++ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
++ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R12),
++ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
++ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R12_2),
++ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
++ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R16_R21),
++ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
++ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R16_R21_2),
++ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
++ { HID_USB_DEVICE(USB_VENDOR_ID_CAMMUS, USB_DEVICE_ID_CAMMUS_C5) },
++ { HID_USB_DEVICE(USB_VENDOR_ID_CAMMUS, USB_DEVICE_ID_CAMMUS_C12) },
++ { HID_USB_DEVICE(USB_VENDOR_ID_VRS, USB_DEVICE_ID_VRS_DFP),
++ .driver_data = HID_PIDFF_QUIRK_PERMISSIVE_CONTROL },
++ { HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_JOYSTICK), },
++ { HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_RUDDER), },
++ { HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_WHEEL) },
++ { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V10) },
++ { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12) },
++ { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE) },
++ { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE_2) },
++ { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_LITE_STAR_GT987_FF) },
++ { }
++};
++MODULE_DEVICE_TABLE(hid, universal_pidff_devices);
++
++static struct hid_driver universal_pidff = {
++ .name = "hid-universal-pidff",
++ .id_table = universal_pidff_devices,
++ .input_mapping = universal_pidff_input_mapping,
++ .probe = universal_pidff_probe,
++ .input_configured = universal_pidff_input_configured
++};
++module_hid_driver(universal_pidff);
++
++MODULE_DESCRIPTION("Universal driver for USB PID Force Feedback devices");
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Makarenko Oleg <oleg@makarenk.ooo>");
++MODULE_AUTHOR("Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>");
+--
+2.39.5
+
--- /dev/null
+From ba7d1e50ee005a4648f78fbc942e9d7b140068c1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:38:52 +0100
+Subject: HID: pidff: Add FIX_WHEEL_DIRECTION quirk
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit 3051bf5ec773b803c474ea556b57d678a8885be3 ]
+
+Most steering wheels simply ignore DIRECTION field, but some try to be
+compliant with the PID standard and use it in force calculations. Games
+often ignore setting this field properly and/or there can be issues with
+dinput8 -> wine -> SDL -> Linux API translation, and this value can be
+incorrect. This can lead to partial/complete loss of Force Feedback or
+even unexpected force reversal.
+
+Sadly, this quirk can't be detected automatically without sending out
+effects that would move an axis.
+
+This fixes FFB on Moza Racing devices and others where effect direction
+is not simply ignored.
+
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Reviewed-by: Michał Kopeć <michal@nozomi.space>
+Reviewed-by: Paul Dino Jones <paul@spacefreak18.xyz>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 12 +++++++++---
+ include/linux/hid.h | 1 +
+ 2 files changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index b8c2ba0a930c2..a37cf852a2836 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -137,6 +137,9 @@ static const u8 pidff_block_load_status[] = { 0x8c, 0x8d };
+ #define PID_EFFECT_STOP 1
+ static const u8 pidff_effect_operation_status[] = { 0x79, 0x7b };
+
++/* Polar direction 90 degrees (North) */
++#define PIDFF_FIXED_WHEEL_DIRECTION 0x4000
++
+ struct pidff_usage {
+ struct hid_field *field;
+ s32 *value;
+@@ -328,9 +331,12 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
+ pidff->set_effect[PID_GAIN].value[0] =
+ pidff->set_effect[PID_GAIN].field->logical_maximum;
+ pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
+- pidff->effect_direction->value[0] =
+- pidff_rescale(effect->direction, 0xffff,
+- pidff->effect_direction);
++
++ /* Use fixed direction if needed */
++ pidff->effect_direction->value[0] = pidff_rescale(
++ pidff->quirks & HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION ?
++ PIDFF_FIXED_WHEEL_DIRECTION : effect->direction,
++ 0xffff, pidff->effect_direction);
+
+ /* Omit setting delay field if it's missing */
+ if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_DELAY))
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index 818e07744c408..c2927e3854a6e 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -1233,6 +1233,7 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks);
+ #define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0)
+ #define HID_PIDFF_QUIRK_MISSING_PBO BIT(1)
+ #define HID_PIDFF_QUIRK_PERMISSIVE_CONTROL BIT(2)
++#define HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION BIT(3)
+
+ #define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__)
+
+--
+2.39.5
+
--- /dev/null
+From a7f5dddc37eac23cedc29b9b3bb1dee9a5a5481d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:38:51 +0100
+Subject: HID: pidff: Add hid_pidff_init_with_quirks and export as GPL symbol
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit 36de0164bbaff1484288e84ac5df5cff00580263 ]
+
+This lays out a way to provide an initial set of quirks to enable before
+device initialization takes place. GPL symbol export needed for the
+possibility of building HID drivers which use this function as modules.
+
+Adding a wrapper function to ensure compatibility with the old behavior
+of hid_pidff_init.
+
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Reviewed-by: Michał Kopeć <michal@nozomi.space>
+Reviewed-by: Paul Dino Jones <paul@spacefreak18.xyz>
+Tested-by: Paul Dino Jones <paul@spacefreak18.xyz>
+Tested-by: Cristóferson Bueno <cbueno81@gmail.com>
+Tested-by: Pablo Cisneros <patchkez@protonmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 15 ++++++++++++++-
+ include/linux/hid.h | 2 ++
+ 2 files changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index 5a57ba0d7026a..b8c2ba0a930c2 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -1268,8 +1268,9 @@ static int pidff_check_autocenter(struct pidff_device *pidff,
+
+ /*
+ * Check if the device is PID and initialize it
++ * Set initial quirks
+ */
+-int hid_pidff_init(struct hid_device *hid)
++int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks)
+ {
+ struct pidff_device *pidff;
+ struct hid_input *hidinput = list_entry(hid->inputs.next,
+@@ -1291,6 +1292,7 @@ int hid_pidff_init(struct hid_device *hid)
+ return -ENOMEM;
+
+ pidff->hid = hid;
++ pidff->quirks = initial_quirks;
+
+ hid_device_io_start(hid);
+
+@@ -1369,3 +1371,14 @@ int hid_pidff_init(struct hid_device *hid)
+ kfree(pidff);
+ return error;
+ }
++EXPORT_SYMBOL_GPL(hid_pidff_init_with_quirks);
++
++/*
++ * Check if the device is PID and initialize it
++ * Wrapper made to keep the compatibility with old
++ * init function
++ */
++int hid_pidff_init(struct hid_device *hid)
++{
++ return hid_pidff_init_with_quirks(hid, 0);
++}
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index cd3fedce48109..818e07744c408 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -1223,8 +1223,10 @@ void hid_quirks_exit(__u16 bus);
+
+ #ifdef CONFIG_HID_PID
+ int hid_pidff_init(struct hid_device *hid);
++int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks);
+ #else
+ #define hid_pidff_init NULL
++#define hid_pidff_init_with_quirks NULL
+ #endif
+
+ /* HID PIDFF quirks */
+--
+2.39.5
+
--- /dev/null
+From 37af9080d03a44283d97d43edcc8eb9a0c63e771 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:38:48 +0100
+Subject: HID: pidff: Add MISSING_DELAY quirk and its detection
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit 2d5c7ce5bf4cc27db41632f357f682d0ee4518e7 ]
+
+A lot of devices do not include this field, and it's seldom used in force
+feedback implementations. I tested about three dozen applications and
+none of them make use of the delay.
+
+This fixes initialization of a lot of PID wheels like Cammus, VRS, FFBeast
+
+This change has no effect on fully compliant devices
+
+Co-developed-by: Makarenko Oleg <oleg@makarenk.ooo>
+Signed-off-by: Makarenko Oleg <oleg@makarenk.ooo>
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Reviewed-by: Michał Kopeć <michal@nozomi.space>
+Reviewed-by: Paul Dino Jones <paul@spacefreak18.xyz>
+Tested-by: Paul Dino Jones <paul@spacefreak18.xyz>
+Tested-by: Cristóferson Bueno <cbueno81@gmail.com>
+Tested-by: Pablo Cisneros <patchkez@protonmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 33 ++++++++++++++++++++++++++++-----
+ include/linux/hid.h | 3 +++
+ 2 files changed, 31 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index a01c1b2ab2f4c..929f5967e7cb1 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -185,6 +185,8 @@ struct pidff_device {
+ int operation_id[sizeof(pidff_effect_operation_status)];
+
+ int pid_id[PID_EFFECTS_MAX];
++
++ u32 quirks;
+ };
+
+ /*
+@@ -329,7 +331,10 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
+ pidff->effect_direction->value[0] =
+ pidff_rescale(effect->direction, 0xffff,
+ pidff->effect_direction);
+- pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay;
++
++ /* Omit setting delay field if it's missing */
++ if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_DELAY))
++ pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay;
+
+ hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
+ HID_REQ_SET_REPORT);
+@@ -748,7 +753,10 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
+ pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0;
+ pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
+ pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
+- pidff->set_effect[PID_START_DELAY].value[0] = 0;
++
++ /* Omit setting delay field if it's missing */
++ if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_DELAY))
++ pidff->set_effect[PID_START_DELAY].value[0] = 0;
+
+ hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
+ HID_REQ_SET_REPORT);
+@@ -771,6 +779,7 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
+ struct hid_report *report, int count, int strict)
+ {
+ int i, j, k, found;
++ int return_value = 0;
+
+ for (k = 0; k < count; k++) {
+ found = 0;
+@@ -795,12 +804,17 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
+ if (found)
+ break;
+ }
+- if (!found && strict) {
++ if (!found && table[k] == pidff_set_effect[PID_START_DELAY]) {
++ pr_debug("Delay field not found, but that's OK\n");
++ pr_debug("Setting MISSING_DELAY quirk\n");
++ return_value |= HID_PIDFF_QUIRK_MISSING_DELAY;
++ }
++ else if (!found && strict) {
+ pr_debug("failed to locate %d\n", k);
+ return -1;
+ }
+ }
+- return 0;
++ return return_value;
+ }
+
+ /*
+@@ -1075,11 +1089,19 @@ static int pidff_find_effects(struct pidff_device *pidff,
+ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
+ {
+ int envelope_ok = 0;
++ int status = 0;
+
+- if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) {
++ /* Save info about the device not having the DELAY ffb field. */
++ status = PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1);
++ if (status == -1) {
+ hid_err(pidff->hid, "unknown set_effect report layout\n");
+ return -ENODEV;
+ }
++ pidff->quirks |= status;
++
++ if (status & HID_PIDFF_QUIRK_MISSING_DELAY)
++ hid_dbg(pidff->hid, "Adding MISSING_DELAY quirk\n");
++
+
+ PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0);
+ if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) {
+@@ -1323,6 +1345,7 @@ int hid_pidff_init(struct hid_device *hid)
+ ff->playback = pidff_playback;
+
+ hid_info(dev, "Force feedback for USB HID PID devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
++ hid_dbg(dev, "Active quirks mask: 0x%x\n", pidff->quirks);
+
+ hid_device_io_stop(hid);
+
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index dd33423012538..42e4111f43e76 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -1227,6 +1227,9 @@ int hid_pidff_init(struct hid_device *hid);
+ #define hid_pidff_init NULL
+ #endif
+
++/* HID PIDFF quirks */
++#define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0)
++
+ #define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__)
+
+ #define hid_err(hid, fmt, ...) \
+--
+2.39.5
+
--- /dev/null
+From 98277acb5ab00249bc8478aa773a9a75bbec19bd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:38:49 +0100
+Subject: HID: pidff: Add MISSING_PBO quirk and its detection
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit fc7c154e9bb3c2b98875cfc565406f4787e3b7a4 ]
+
+Some devices with only one axis are missing PARAMETER_BLOCK_OFFSET field
+for conditional effects. They can only have one axis, so we're limiting
+the max_axis when setting the report for those effects.
+
+Automatic detection ensures compatibility even if such device won't be
+explicitly defined in the kernel.
+
+Fixes initialization of VRS DirectForce PRO and possibly other devices.
+
+Changes in v6:
+- Fixed NULL pointer dereference. When PBO is missing, make sure not
+ to set it anyway
+
+Co-developed-by: Makarenko Oleg <oleg@makarenk.ooo>
+Signed-off-by: Makarenko Oleg <oleg@makarenk.ooo>
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Reviewed-by: Michał Kopeć <michal@nozomi.space>
+Reviewed-by: Paul Dino Jones <paul@spacefreak18.xyz>
+Tested-by: Paul Dino Jones <paul@spacefreak18.xyz>
+Tested-by: Cristóferson Bueno <cbueno81@gmail.com>
+Tested-by: Pablo Cisneros <patchkez@protonmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 47 +++++++++++++++++++++-------------
+ include/linux/hid.h | 1 +
+ 2 files changed, 30 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index 929f5967e7cb1..503b22feacdbb 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -391,13 +391,19 @@ static int pidff_needs_set_periodic(struct ff_effect *effect,
+ static void pidff_set_condition_report(struct pidff_device *pidff,
+ struct ff_effect *effect)
+ {
+- int i;
++ int i, max_axis;
++
++ /* Devices missing Parameter Block Offset can only have one axis */
++ max_axis = pidff->quirks & HID_PIDFF_QUIRK_MISSING_PBO ? 1 : 2;
+
+ pidff->set_condition[PID_EFFECT_BLOCK_INDEX].value[0] =
+ pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
+
+- for (i = 0; i < 2; i++) {
+- pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i;
++ for (i = 0; i < max_axis; i++) {
++ /* Omit Parameter Block Offset if missing */
++ if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_PBO))
++ pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i;
++
+ pidff_set_signed(&pidff->set_condition[PID_CP_OFFSET],
+ effect->u.condition[i].center);
+ pidff_set_signed(&pidff->set_condition[PID_POS_COEFFICIENT],
+@@ -809,6 +815,11 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
+ pr_debug("Setting MISSING_DELAY quirk\n");
+ return_value |= HID_PIDFF_QUIRK_MISSING_DELAY;
+ }
++ else if (!found && table[k] == pidff_set_condition[PID_PARAM_BLOCK_OFFSET]) {
++ pr_debug("PBO field not found, but that's OK\n");
++ pr_debug("Setting MISSING_PBO quirk\n");
++ return_value |= HID_PIDFF_QUIRK_MISSING_PBO;
++ }
+ else if (!found && strict) {
+ pr_debug("failed to locate %d\n", k);
+ return -1;
+@@ -1088,7 +1099,6 @@ static int pidff_find_effects(struct pidff_device *pidff,
+ */
+ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
+ {
+- int envelope_ok = 0;
+ int status = 0;
+
+ /* Save info about the device not having the DELAY ffb field. */
+@@ -1119,13 +1129,10 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
+ return -ENODEV;
+ }
+
+- if (!PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1))
+- envelope_ok = 1;
+-
+ if (pidff_find_special_fields(pidff) || pidff_find_effects(pidff, dev))
+ return -ENODEV;
+
+- if (!envelope_ok) {
++ if (PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1)) {
+ if (test_and_clear_bit(FF_CONSTANT, dev->ffbit))
+ hid_warn(pidff->hid,
+ "has constant effect but no envelope\n");
+@@ -1150,16 +1157,20 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
+ clear_bit(FF_RAMP, dev->ffbit);
+ }
+
+- if ((test_bit(FF_SPRING, dev->ffbit) ||
+- test_bit(FF_DAMPER, dev->ffbit) ||
+- test_bit(FF_FRICTION, dev->ffbit) ||
+- test_bit(FF_INERTIA, dev->ffbit)) &&
+- PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) {
+- hid_warn(pidff->hid, "unknown condition effect layout\n");
+- clear_bit(FF_SPRING, dev->ffbit);
+- clear_bit(FF_DAMPER, dev->ffbit);
+- clear_bit(FF_FRICTION, dev->ffbit);
+- clear_bit(FF_INERTIA, dev->ffbit);
++ if (test_bit(FF_SPRING, dev->ffbit) ||
++ test_bit(FF_DAMPER, dev->ffbit) ||
++ test_bit(FF_FRICTION, dev->ffbit) ||
++ test_bit(FF_INERTIA, dev->ffbit)) {
++ status = PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1);
++
++ if (status < 0) {
++ hid_warn(pidff->hid, "unknown condition effect layout\n");
++ clear_bit(FF_SPRING, dev->ffbit);
++ clear_bit(FF_DAMPER, dev->ffbit);
++ clear_bit(FF_FRICTION, dev->ffbit);
++ clear_bit(FF_INERTIA, dev->ffbit);
++ }
++ pidff->quirks |= status;
+ }
+
+ if (test_bit(FF_PERIODIC, dev->ffbit) &&
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index 42e4111f43e76..088c6688c3f98 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -1229,6 +1229,7 @@ int hid_pidff_init(struct hid_device *hid);
+
+ /* HID PIDFF quirks */
+ #define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0)
++#define HID_PIDFF_QUIRK_MISSING_PBO BIT(1)
+
+ #define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__)
+
+--
+2.39.5
+
--- /dev/null
+From 0596ae311963d67adc42e490fe852ab6cb3eb149 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:38:56 +0100
+Subject: HID: pidff: Add PERIODIC_SINE_ONLY quirk
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit abdbf8764f4962af2a910abb3a213ecf304a73d3 ]
+
+Some devices only support SINE periodic effect although they advertise
+support for all PERIODIC effect in their HID descriptor. Some just do
+nothing when trying to play such an effect (upload goes fine), some express
+undefined behavior like turning to one side.
+
+This quirk forces all the periodic effects to be uploaded as SINE. This is
+acceptable as all these effects are similar in nature and are mostly used as
+rumble. SINE is the most popular with others seldom used (especially SAW_UP
+and SAW_DOWN).
+
+Fixes periodic effects for PXN and LITE STAR wheels
+
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Reviewed-by: Michał Kopeć <michal@nozomi.space>
+Reviewed-by: Paul Dino Jones <paul@spacefreak18.xyz>
+Tested-by: Cristóferson Bueno <cbueno81@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-universal-pidff.c | 15 ++++++++++-----
+ drivers/hid/usbhid/hid-pidff.c | 3 +++
+ include/linux/hid.h | 1 +
+ 3 files changed, 14 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/hid/hid-universal-pidff.c b/drivers/hid/hid-universal-pidff.c
+index 55aad2e4ac1b8..7ef5ab9146b1c 100644
+--- a/drivers/hid/hid-universal-pidff.c
++++ b/drivers/hid/hid-universal-pidff.c
+@@ -168,11 +168,16 @@ static const struct hid_device_id universal_pidff_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_JOYSTICK), },
+ { HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_RUDDER), },
+ { HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_WHEEL) },
+- { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V10) },
+- { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12) },
+- { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE) },
+- { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE_2) },
+- { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_LITE_STAR_GT987_FF) },
++ { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V10),
++ .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
++ { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12),
++ .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
++ { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE),
++ .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
++ { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE_2),
++ .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
++ { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_LITE_STAR_GT987_FF),
++ .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
+ { }
+ };
+ MODULE_DEVICE_TABLE(hid, universal_pidff_devices);
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index a37cf852a2836..4c94d8cbac43a 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -637,6 +637,9 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
+ return -EINVAL;
+ }
+
++ if (pidff->quirks & HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY)
++ type_id = PID_SINE;
++
+ error = pidff_request_effect_upload(pidff,
+ pidff->type_id[type_id]);
+ if (error)
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index c2927e3854a6e..495b5b3b2cb80 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -1234,6 +1234,7 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks);
+ #define HID_PIDFF_QUIRK_MISSING_PBO BIT(1)
+ #define HID_PIDFF_QUIRK_PERMISSIVE_CONTROL BIT(2)
+ #define HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION BIT(3)
++#define HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY BIT(4)
+
+ #define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__)
+
+--
+2.39.5
+
--- /dev/null
+From 562819f87731f45deac5588a5ea7658baccb8446 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:38:50 +0100
+Subject: HID: pidff: Add PERMISSIVE_CONTROL quirk
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit a4119108d2530747e61c7cbf52e2affd089cb1f6 ]
+
+With this quirk, a PID device isn't required to have a strict
+logical_minimum of 1 for the the PID_DEVICE_CONTROL usage page.
+
+Some devices come with weird values in their device descriptors and
+this quirk enables their initialization even if the logical minimum
+of the DEVICE_CONTROL page is not 1.
+
+Fixes initialization of VRS Direct Force Pro
+
+Changes in v6:
+- Change quirk name to better reflect it's intention
+
+Co-developed-by: Makarenko Oleg <oleg@makarenk.ooo>
+Signed-off-by: Makarenko Oleg <oleg@makarenk.ooo>
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Reviewed-by: Michał Kopeć <michal@nozomi.space>
+Reviewed-by: Paul Dino Jones <paul@spacefreak18.xyz>
+Tested-by: Paul Dino Jones <paul@spacefreak18.xyz>
+Tested-by: Cristóferson Bueno <cbueno81@gmail.com>
+Tested-by: Pablo Cisneros <patchkez@protonmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 3 ++-
+ include/linux/hid.h | 5 +++--
+ 2 files changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index 503b22feacdbb..5a57ba0d7026a 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -969,7 +969,8 @@ static int pidff_find_special_fields(struct pidff_device *pidff)
+ 0x57, 0);
+ pidff->device_control =
+ pidff_find_special_field(pidff->reports[PID_DEVICE_CONTROL],
+- 0x96, 1);
++ 0x96, !(pidff->quirks & HID_PIDFF_QUIRK_PERMISSIVE_CONTROL));
++
+ pidff->block_load_status =
+ pidff_find_special_field(pidff->reports[PID_BLOCK_LOAD],
+ 0x8b, 1);
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index 088c6688c3f98..cd3fedce48109 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -1228,8 +1228,9 @@ int hid_pidff_init(struct hid_device *hid);
+ #endif
+
+ /* HID PIDFF quirks */
+-#define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0)
+-#define HID_PIDFF_QUIRK_MISSING_PBO BIT(1)
++#define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0)
++#define HID_PIDFF_QUIRK_MISSING_PBO BIT(1)
++#define HID_PIDFF_QUIRK_PERMISSIVE_CONTROL BIT(2)
+
+ #define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__)
+
+--
+2.39.5
+
--- /dev/null
+From f64b0c08ca959d5ead2df0591f868ab2ba075417 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:38:45 +0100
+Subject: HID: pidff: Convert infinite length from Linux API to PID standard
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit 37e0591fe44dce39d1ebc7a82d5b6e4dba1582eb ]
+
+Software uses 0 as de-facto infinite lenght on Linux FF apis (SDL),
+Linux doesn't actually define anythi as of now, while USB PID defines
+NULL (0xffff). Most PID devices do not expect a 0-length effect and
+can't interpret it as infinite. This change fixes Force Feedback for
+most PID compliant devices.
+
+As most games depend on updating the values of already playing infinite
+effects, this is crucial to ensure they will actually work.
+
+Previously, users had to rely on third-party software to do this conversion
+and make their PID devices usable.
+
+Co-developed-by: Makarenko Oleg <oleg@makarenk.ooo>
+Signed-off-by: Makarenko Oleg <oleg@makarenk.ooo>
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Reviewed-by: Michał Kopeć <michal@nozomi.space>
+Reviewed-by: Paul Dino Jones <paul@spacefreak18.xyz>
+Tested-by: Paul Dino Jones <paul@spacefreak18.xyz>
+Tested-by: Cristóferson Bueno <cbueno81@gmail.com>
+Tested-by: Pablo Cisneros <patchkez@protonmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index 3b4ee21cd8111..5fe4422bb5bad 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -21,6 +21,7 @@
+ #include "usbhid.h"
+
+ #define PID_EFFECTS_MAX 64
++#define PID_INFINITE 0xffff
+
+ /* Report usage table used to put reports into an array */
+
+@@ -301,7 +302,12 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
+ pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
+ pidff->set_effect_type->value[0] =
+ pidff->create_new_effect_type->value[0];
+- pidff->set_effect[PID_DURATION].value[0] = effect->replay.length;
++
++ /* Convert infinite length from Linux API (0)
++ to PID standard (NULL) if needed */
++ pidff->set_effect[PID_DURATION].value[0] =
++ effect->replay.length == 0 ? PID_INFINITE : effect->replay.length;
++
+ pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = effect->trigger.button;
+ pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] =
+ effect->trigger.interval;
+--
+2.39.5
+
--- /dev/null
+From 36988e05f517c006b47716ad597f9b14f46ac8a3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:38:46 +0100
+Subject: HID: pidff: Do not send effect envelope if it's empty
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit 8876fc1884f5b39550c8387ff3176396c988541d ]
+
+Envelope struct is always initialized, but the envelope itself is
+optional as described in USB PID Device class definition 1.0.
+
+5.1.1.1 Type Specific Block Offsets
+...
+4) Effects that do not use Condition Blocks use 1 Parameter Block and
+an *optional* Envelope Block.
+
+Sending out "empty" envelope breaks force feedback on some devices with
+games that use SINE effect + offset to emulate constant force effect, as
+well as generally breaking Constant/Periodic effects. One of the affected
+brands is Moza Racing.
+
+This change prevents the envelope from being sent if it contains all
+0 values while keeping the old behavior of only sending it, if it differs
+from the old one.
+
+Changes in v6:
+- Simplify the checks to make them clearer
+- Fix possible null pointer dereference while calling
+ pidff_needs_set_envelope
+
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Reviewed-by: Michał Kopeć <michal@nozomi.space>
+Reviewed-by: Paul Dino Jones <paul@spacefreak18.xyz>
+Tested-by: Paul Dino Jones <paul@spacefreak18.xyz>
+Tested-by: Cristóferson Bueno <cbueno81@gmail.com>
+Tested-by: Pablo Cisneros <patchkez@protonmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 42 +++++++++++++++++++---------------
+ 1 file changed, 24 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index 5fe4422bb5bad..a01c1b2ab2f4c 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -262,10 +262,22 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
+ static int pidff_needs_set_envelope(struct ff_envelope *envelope,
+ struct ff_envelope *old)
+ {
+- return envelope->attack_level != old->attack_level ||
+- envelope->fade_level != old->fade_level ||
++ bool needs_new_envelope;
++ needs_new_envelope = envelope->attack_level != 0 ||
++ envelope->fade_level != 0 ||
++ envelope->attack_length != 0 ||
++ envelope->fade_length != 0;
++
++ if (!needs_new_envelope)
++ return false;
++
++ if (!old)
++ return needs_new_envelope;
++
++ return envelope->attack_level != old->attack_level ||
++ envelope->fade_level != old->fade_level ||
+ envelope->attack_length != old->attack_length ||
+- envelope->fade_length != old->fade_length;
++ envelope->fade_length != old->fade_length;
+ }
+
+ /*
+@@ -580,11 +592,9 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
+ pidff_set_effect_report(pidff, effect);
+ if (!old || pidff_needs_set_constant(effect, old))
+ pidff_set_constant_force_report(pidff, effect);
+- if (!old ||
+- pidff_needs_set_envelope(&effect->u.constant.envelope,
+- &old->u.constant.envelope))
+- pidff_set_envelope_report(pidff,
+- &effect->u.constant.envelope);
++ if (pidff_needs_set_envelope(&effect->u.constant.envelope,
++ old ? &old->u.constant.envelope : NULL))
++ pidff_set_envelope_report(pidff, &effect->u.constant.envelope);
+ break;
+
+ case FF_PERIODIC:
+@@ -619,11 +629,9 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
+ pidff_set_effect_report(pidff, effect);
+ if (!old || pidff_needs_set_periodic(effect, old))
+ pidff_set_periodic_report(pidff, effect);
+- if (!old ||
+- pidff_needs_set_envelope(&effect->u.periodic.envelope,
+- &old->u.periodic.envelope))
+- pidff_set_envelope_report(pidff,
+- &effect->u.periodic.envelope);
++ if (pidff_needs_set_envelope(&effect->u.periodic.envelope,
++ old ? &old->u.periodic.envelope : NULL))
++ pidff_set_envelope_report(pidff, &effect->u.periodic.envelope);
+ break;
+
+ case FF_RAMP:
+@@ -637,11 +645,9 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
+ pidff_set_effect_report(pidff, effect);
+ if (!old || pidff_needs_set_ramp(effect, old))
+ pidff_set_ramp_force_report(pidff, effect);
+- if (!old ||
+- pidff_needs_set_envelope(&effect->u.ramp.envelope,
+- &old->u.ramp.envelope))
+- pidff_set_envelope_report(pidff,
+- &effect->u.ramp.envelope);
++ if (pidff_needs_set_envelope(&effect->u.ramp.envelope,
++ old ? &old->u.ramp.envelope : NULL))
++ pidff_set_envelope_report(pidff, &effect->u.ramp.envelope);
+ break;
+
+ case FF_SPRING:
+--
+2.39.5
+
--- /dev/null
+From 30b4f0226035818a797b50fd4de7c1d41224e316 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:39:02 +0100
+Subject: HID: pidff: Fix null pointer dereference in pidff_find_fields
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <forest10pl@gmail.com>
+
+[ Upstream commit 22a05462c3d0eee15154faf8d13c49e6295270a5 ]
+
+This function triggered a null pointer dereference if used to search for
+a report that isn't implemented on the device. This happened both for
+optional and required reports alike.
+
+The same logic was applied to pidff_find_special_field and although
+pidff_init_fields should return an error earlier if one of the required
+reports is missing, future modifications could change this logic and
+resurface this possible null pointer dereference again.
+
+LKML bug report:
+https://lore.kernel.org/all/CAL-gK7f5=R0nrrQdPtaZZr1fd-cdAMbDMuZ_NLA8vM0SX+nGSw@mail.gmail.com
+
+Reported-by: Nolan Nicholson <nolananicholson@gmail.com>
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Reviewed-by: Michał Kopeć <michal@nozomi.space>
+Reviewed-by: Paul Dino Jones <paul@spacefreak18.xyz>
+Tested-by: Paul Dino Jones <paul@spacefreak18.xyz>
+Tested-by: Cristóferson Bueno <cbueno81@gmail.com>
+Tested-by: Pablo Cisneros <patchkez@protonmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index 4c94d8cbac43a..25dbed076f530 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -793,6 +793,11 @@ static void pidff_set_autocenter(struct input_dev *dev, u16 magnitude)
+ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
+ struct hid_report *report, int count, int strict)
+ {
++ if (!report) {
++ pr_debug("pidff_find_fields, null report\n");
++ return -1;
++ }
++
+ int i, j, k, found;
+ int return_value = 0;
+
+@@ -917,6 +922,11 @@ static int pidff_reports_ok(struct pidff_device *pidff)
+ static struct hid_field *pidff_find_special_field(struct hid_report *report,
+ int usage, int enforce_min)
+ {
++ if (!report) {
++ pr_debug("pidff_find_special_field, null report\n");
++ return NULL;
++ }
++
+ int i;
+
+ for (i = 0; i < report->maxfield; i++) {
+--
+2.39.5
+
--- /dev/null
+From 824505fafffb3d31a615305559d5f11295333964 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 19:24:19 +0800
+Subject: jfs: add sanity check for agwidth in dbMount
+
+From: Edward Adam Davis <eadavis@qq.com>
+
+[ Upstream commit ddf2846f22e8575d6b4b6a66f2100f168b8cd73d ]
+
+The width in dmapctl of the AG is zero, it trigger a divide error when
+calculating the control page level in dbAllocAG.
+
+To avoid this issue, add a check for agwidth in dbAllocAG.
+
+Reported-and-tested-by: syzbot+7c808908291a569281a9@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=7c808908291a569281a9
+Signed-off-by: Edward Adam Davis <eadavis@qq.com>
+Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jfs/jfs_dmap.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
+index 9ac1fc2ed05bc..0e1019382cf51 100644
+--- a/fs/jfs/jfs_dmap.c
++++ b/fs/jfs/jfs_dmap.c
+@@ -204,6 +204,10 @@ int dbMount(struct inode *ipbmap)
+ bmp->db_aglevel = le32_to_cpu(dbmp_le->dn_aglevel);
+ bmp->db_agheight = le32_to_cpu(dbmp_le->dn_agheight);
+ bmp->db_agwidth = le32_to_cpu(dbmp_le->dn_agwidth);
++ if (!bmp->db_agwidth) {
++ err = -EINVAL;
++ goto err_release_metapage;
++ }
+ bmp->db_agstart = le32_to_cpu(dbmp_le->dn_agstart);
+ bmp->db_agl2size = le32_to_cpu(dbmp_le->dn_agl2size);
+ if (bmp->db_agl2size > L2MAXL2SIZE - L2MAXAG ||
+--
+2.39.5
+
--- /dev/null
+From 7cbe1f7aa6e2c999bb131edde8b5b2cf836a6bb1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Feb 2025 22:02:11 +0800
+Subject: jfs: Fix uninit-value access of imap allocated in the diMount()
+ function
+
+From: Zhongqiu Han <quic_zhonhan@quicinc.com>
+
+[ Upstream commit 9629d7d66c621671d9a47afe27ca9336bfc8a9ea ]
+
+syzbot reports that hex_dump_to_buffer is using uninit-value:
+
+=====================================================
+BUG: KMSAN: uninit-value in hex_dump_to_buffer+0x888/0x1100 lib/hexdump.c:171
+hex_dump_to_buffer+0x888/0x1100 lib/hexdump.c:171
+print_hex_dump+0x13d/0x3e0 lib/hexdump.c:276
+diFree+0x5ba/0x4350 fs/jfs/jfs_imap.c:876
+jfs_evict_inode+0x510/0x550 fs/jfs/inode.c:156
+evict+0x723/0xd10 fs/inode.c:796
+iput_final fs/inode.c:1946 [inline]
+iput+0x97b/0xdb0 fs/inode.c:1972
+txUpdateMap+0xf3e/0x1150 fs/jfs/jfs_txnmgr.c:2367
+txLazyCommit fs/jfs/jfs_txnmgr.c:2664 [inline]
+jfs_lazycommit+0x627/0x11d0 fs/jfs/jfs_txnmgr.c:2733
+kthread+0x6b9/0xef0 kernel/kthread.c:464
+ret_from_fork+0x6d/0x90 arch/x86/kernel/process.c:148
+ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
+
+Uninit was created at:
+slab_post_alloc_hook mm/slub.c:4121 [inline]
+slab_alloc_node mm/slub.c:4164 [inline]
+__kmalloc_cache_noprof+0x8e3/0xdf0 mm/slub.c:4320
+kmalloc_noprof include/linux/slab.h:901 [inline]
+diMount+0x61/0x7f0 fs/jfs/jfs_imap.c:105
+jfs_mount+0xa8e/0x11d0 fs/jfs/jfs_mount.c:176
+jfs_fill_super+0xa47/0x17c0 fs/jfs/super.c:523
+get_tree_bdev_flags+0x6ec/0x910 fs/super.c:1636
+get_tree_bdev+0x37/0x50 fs/super.c:1659
+jfs_get_tree+0x34/0x40 fs/jfs/super.c:635
+vfs_get_tree+0xb1/0x5a0 fs/super.c:1814
+do_new_mount+0x71f/0x15e0 fs/namespace.c:3560
+path_mount+0x742/0x1f10 fs/namespace.c:3887
+do_mount fs/namespace.c:3900 [inline]
+__do_sys_mount fs/namespace.c:4111 [inline]
+__se_sys_mount+0x71f/0x800 fs/namespace.c:4088
+__x64_sys_mount+0xe4/0x150 fs/namespace.c:4088
+x64_sys_call+0x39bf/0x3c30 arch/x86/include/generated/asm/syscalls_64.h:166
+do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+do_syscall_64+0xcd/0x1e0 arch/x86/entry/common.c:83
+entry_SYSCALL_64_after_hwframe+0x77/0x7f
+=====================================================
+
+The reason is that imap is not properly initialized after memory
+allocation. It will cause the snprintf() function to write uninitialized
+data into linebuf within hex_dump_to_buffer().
+
+Fix this by using kzalloc instead of kmalloc to clear its content at the
+beginning in diMount().
+
+Signed-off-by: Zhongqiu Han <quic_zhonhan@quicinc.com>
+Reported-by: syzbot+df6cdcb35904203d2b6d@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/lkml/67b5d07e.050a0220.14d86d.00e6.GAE@google.com/
+Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jfs/jfs_imap.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
+index a360b24ed320c..cf16655cd26ba 100644
+--- a/fs/jfs/jfs_imap.c
++++ b/fs/jfs/jfs_imap.c
+@@ -102,7 +102,7 @@ int diMount(struct inode *ipimap)
+ * allocate/initialize the in-memory inode map control structure
+ */
+ /* allocate the in-memory inode map control structure. */
+- imap = kmalloc(sizeof(struct inomap), GFP_KERNEL);
++ imap = kzalloc(sizeof(struct inomap), GFP_KERNEL);
+ if (imap == NULL)
+ return -ENOMEM;
+
+--
+2.39.5
+
--- /dev/null
+From 6427cb1eb7628b6fe2435e1dba4316e70775da42 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 19:13:21 +0800
+Subject: jfs: Prevent copying of nlink with value 0 from disk inode
+
+From: Edward Adam Davis <eadavis@qq.com>
+
+[ Upstream commit b61e69bb1c049cf507e3c654fa3dc1568231bd07 ]
+
+syzbot report a deadlock in diFree. [1]
+
+When calling "ioctl$LOOP_SET_STATUS64", the offset value passed in is 4,
+which does not match the mounted loop device, causing the mapping of the
+mounted loop device to be invalidated.
+
+When creating the directory and creating the inode of iag in diReadSpecial(),
+read the page of fixed disk inode (AIT) in raw mode in read_metapage(), the
+metapage data it returns is corrupted, which causes the nlink value of 0 to be
+assigned to the iag inode when executing copy_from_dinode(), which ultimately
+causes a deadlock when entering diFree().
+
+To avoid this, first check the nlink value of dinode before setting iag inode.
+
+[1]
+WARNING: possible recursive locking detected
+6.12.0-rc7-syzkaller-00212-g4a5df3796467 #0 Not tainted
+--------------------------------------------
+syz-executor301/5309 is trying to acquire lock:
+ffff888044548920 (&(imap->im_aglock[index])){+.+.}-{3:3}, at: diFree+0x37c/0x2fb0 fs/jfs/jfs_imap.c:889
+
+but task is already holding lock:
+ffff888044548920 (&(imap->im_aglock[index])){+.+.}-{3:3}, at: diAlloc+0x1b6/0x1630
+
+other info that might help us debug this:
+ Possible unsafe locking scenario:
+
+ CPU0
+ ----
+ lock(&(imap->im_aglock[index]));
+ lock(&(imap->im_aglock[index]));
+
+ *** DEADLOCK ***
+
+ May be due to missing lock nesting notation
+
+5 locks held by syz-executor301/5309:
+ #0: ffff8880422a4420 (sb_writers#9){.+.+}-{0:0}, at: mnt_want_write+0x3f/0x90 fs/namespace.c:515
+ #1: ffff88804755b390 (&type->i_mutex_dir_key#6/1){+.+.}-{3:3}, at: inode_lock_nested include/linux/fs.h:850 [inline]
+ #1: ffff88804755b390 (&type->i_mutex_dir_key#6/1){+.+.}-{3:3}, at: filename_create+0x260/0x540 fs/namei.c:4026
+ #2: ffff888044548920 (&(imap->im_aglock[index])){+.+.}-{3:3}, at: diAlloc+0x1b6/0x1630
+ #3: ffff888044548890 (&imap->im_freelock){+.+.}-{3:3}, at: diNewIAG fs/jfs/jfs_imap.c:2460 [inline]
+ #3: ffff888044548890 (&imap->im_freelock){+.+.}-{3:3}, at: diAllocExt fs/jfs/jfs_imap.c:1905 [inline]
+ #3: ffff888044548890 (&imap->im_freelock){+.+.}-{3:3}, at: diAllocAG+0x4b7/0x1e50 fs/jfs/jfs_imap.c:1669
+ #4: ffff88804755a618 (&jfs_ip->rdwrlock/1){++++}-{3:3}, at: diNewIAG fs/jfs/jfs_imap.c:2477 [inline]
+ #4: ffff88804755a618 (&jfs_ip->rdwrlock/1){++++}-{3:3}, at: diAllocExt fs/jfs/jfs_imap.c:1905 [inline]
+ #4: ffff88804755a618 (&jfs_ip->rdwrlock/1){++++}-{3:3}, at: diAllocAG+0x869/0x1e50 fs/jfs/jfs_imap.c:1669
+
+stack backtrace:
+CPU: 0 UID: 0 PID: 5309 Comm: syz-executor301 Not tainted 6.12.0-rc7-syzkaller-00212-g4a5df3796467 #0
+Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
+Call Trace:
+ <TASK>
+ __dump_stack lib/dump_stack.c:94 [inline]
+ dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120
+ print_deadlock_bug+0x483/0x620 kernel/locking/lockdep.c:3037
+ check_deadlock kernel/locking/lockdep.c:3089 [inline]
+ validate_chain+0x15e2/0x5920 kernel/locking/lockdep.c:3891
+ __lock_acquire+0x1384/0x2050 kernel/locking/lockdep.c:5202
+ lock_acquire+0x1ed/0x550 kernel/locking/lockdep.c:5825
+ __mutex_lock_common kernel/locking/mutex.c:608 [inline]
+ __mutex_lock+0x136/0xd70 kernel/locking/mutex.c:752
+ diFree+0x37c/0x2fb0 fs/jfs/jfs_imap.c:889
+ jfs_evict_inode+0x32d/0x440 fs/jfs/inode.c:156
+ evict+0x4e8/0x9b0 fs/inode.c:725
+ diFreeSpecial fs/jfs/jfs_imap.c:552 [inline]
+ duplicateIXtree+0x3c6/0x550 fs/jfs/jfs_imap.c:3022
+ diNewIAG fs/jfs/jfs_imap.c:2597 [inline]
+ diAllocExt fs/jfs/jfs_imap.c:1905 [inline]
+ diAllocAG+0x17dc/0x1e50 fs/jfs/jfs_imap.c:1669
+ diAlloc+0x1d2/0x1630 fs/jfs/jfs_imap.c:1590
+ ialloc+0x8f/0x900 fs/jfs/jfs_inode.c:56
+ jfs_mkdir+0x1c5/0xba0 fs/jfs/namei.c:225
+ vfs_mkdir+0x2f9/0x4f0 fs/namei.c:4257
+ do_mkdirat+0x264/0x3a0 fs/namei.c:4280
+ __do_sys_mkdirat fs/namei.c:4295 [inline]
+ __se_sys_mkdirat fs/namei.c:4293 [inline]
+ __x64_sys_mkdirat+0x87/0xa0 fs/namei.c:4293
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Reported-by: syzbot+355da3b3a74881008e8f@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=355da3b3a74881008e8f
+Signed-off-by: Edward Adam Davis <eadavis@qq.com>
+Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jfs/jfs_imap.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
+index cf16655cd26ba..8ddc14c56501a 100644
+--- a/fs/jfs/jfs_imap.c
++++ b/fs/jfs/jfs_imap.c
+@@ -456,7 +456,7 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
+ dp += inum % 8; /* 8 inodes per 4K page */
+
+ /* copy on-disk inode to in-memory inode */
+- if ((copy_from_dinode(dp, ip)) != 0) {
++ if ((copy_from_dinode(dp, ip) != 0) || (ip->i_nlink == 0)) {
+ /* handle bad return by returning NULL for ip */
+ set_nlink(ip, 1); /* Don't want iput() deleting it */
+ iput(ip);
+--
+2.39.5
+
--- /dev/null
+From 257e8617cf828a69c28cde7df3de9e4ccffcf045 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Mar 2025 04:38:54 +0000
+Subject: ktest: Fix Test Failures Due to Missing LOG_FILE Directories
+
+From: Ayush Jain <Ayush.jain3@amd.com>
+
+[ Upstream commit 5a1bed232781d356f842576daacc260f0d0c8d2e ]
+
+Handle missing parent directories for LOG_FILE path to prevent test
+failures. If the parent directories don't exist, create them to ensure
+the tests proceed successfully.
+
+Cc: <warthog9@eaglescrag.net>
+Link: https://lore.kernel.org/20250307043854.2518539-1-Ayush.jain3@amd.com
+Signed-off-by: Ayush Jain <Ayush.jain3@amd.com>
+Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/ktest/ktest.pl | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
+index c76ad0be54e2e..7e524601e01ad 100755
+--- a/tools/testing/ktest/ktest.pl
++++ b/tools/testing/ktest/ktest.pl
+@@ -4303,6 +4303,14 @@ if (defined($opt{"LOG_FILE"})) {
+ if ($opt{"CLEAR_LOG"}) {
+ unlink $opt{"LOG_FILE"};
+ }
++
++ if (! -e $opt{"LOG_FILE"} && $opt{"LOG_FILE"} =~ m,^(.*/),) {
++ my $dir = $1;
++ if (! -d $dir) {
++ mkpath($dir) or die "Failed to create directories '$dir': $!";
++ print "\nThe log directory $dir did not exist, so it was created.\n";
++ }
++ }
+ open(LOG, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
+ LOG->autoflush(1);
+ }
+--
+2.39.5
+
--- /dev/null
+From 5147fceea4d6a483efa7e0c66d230fef85e55a2c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Feb 2025 15:52:51 +0530
+Subject: media: s5p-mfc: Corrected NV12M/NV21M plane-sizes
+
+From: Aakarsh Jain <aakarsh.jain@samsung.com>
+
+[ Upstream commit 7d0d0b2342bebc47a46499cdf21257ed1e58c4aa ]
+
+There is a possibility of getting page fault if the overall
+buffer size is not aligned to 256bytes. Since MFC does read
+operation only and it won't corrupt the data values even if
+it reads the extra bytes.
+Corrected luma and chroma plane sizes for V4L2_PIX_FMT_NV12M
+and V4L2_PIX_FMT_NV21M pixel format.
+
+Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Aakarsh Jain <aakarsh.jain@samsung.com>
+Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c
+index 73f7af674c01b..0c636090d723d 100644
+--- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c
++++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c
+@@ -549,8 +549,9 @@ static void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx)
+ case V4L2_PIX_FMT_NV21M:
+ ctx->stride[0] = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN_V6);
+ ctx->stride[1] = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN_V6);
+- ctx->luma_size = ctx->stride[0] * ALIGN(ctx->img_height, 16);
+- ctx->chroma_size = ctx->stride[0] * ALIGN(ctx->img_height / 2, 16);
++ ctx->luma_size = ALIGN(ctx->stride[0] * ALIGN(ctx->img_height, 16), 256);
++ ctx->chroma_size = ALIGN(ctx->stride[0] * ALIGN(ctx->img_height / 2, 16),
++ 256);
+ break;
+ case V4L2_PIX_FMT_YUV420M:
+ case V4L2_PIX_FMT_YVU420M:
+--
+2.39.5
+
--- /dev/null
+From a0b531b4606ffaa45d4cc5ae612c2bf38d425a97 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Dec 2024 10:48:14 +0000
+Subject: media: uvcvideo: Add quirk for Actions UVC05
+
+From: Ricardo Ribalda <ribalda@chromium.org>
+
+[ Upstream commit 8c54e58f94ed3ff28643aefd2c0c2c98313ee770 ]
+
+Actions UVC05 is a HDMI to USB dongle that implements the UVC protocol.
+
+When the device suspends, its firmware seems to enter a weird mode when it
+does not produce more frames.
+
+Add the device to the quirk list to disable autosuspend.
+
+Bus 001 Device 007: ID 1de1:f105 Actions Microelectronics Co. Display
+ capture-UVC05
+Device Descriptor:
+ bLength 18
+ bDescriptorType 1
+ bcdUSB 2.00
+ bDeviceClass 239 Miscellaneous Device
+ bDeviceSubClass 2 [unknown]
+ bDeviceProtocol 1 Interface Association
+ bMaxPacketSize0 64
+ idVendor 0x1de1 Actions Microelectronics Co.
+ idProduct 0xf105 Display capture-UVC05
+ bcdDevice 4.09
+ iManufacturer 1 Actions Micro
+ iProduct 2 Display capture-UVC05
+ iSerial 3 -1005308387
+ bNumConfigurations 1
+
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Link: https://lore.kernel.org/r/20241210-uvc-hdmi-suspend-v1-1-01f5dec023ea@chromium.org
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/uvc/uvc_driver.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
+index 4d8e00b425f44..a0d683d266471 100644
+--- a/drivers/media/usb/uvc/uvc_driver.c
++++ b/drivers/media/usb/uvc/uvc_driver.c
+@@ -3039,6 +3039,15 @@ static const struct usb_device_id uvc_ids[] = {
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX
+ | UVC_QUIRK_IGNORE_SELECTOR_UNIT) },
++ /* Actions Microelectronics Co. Display capture-UVC05 */
++ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
++ | USB_DEVICE_ID_MATCH_INT_INFO,
++ .idVendor = 0x1de1,
++ .idProduct = 0xf105,
++ .bInterfaceClass = USB_CLASS_VIDEO,
++ .bInterfaceSubClass = 1,
++ .bInterfaceProtocol = 0,
++ .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_DISABLE_AUTOSUSPEND) },
+ /* NXP Semiconductors IR VIDEO */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+--
+2.39.5
+
--- /dev/null
+From fab63606e8ead8a4d5bc0d057148a958bcd650e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Feb 2025 00:17:48 +0530
+Subject: mmc: dw_mmc: add a quirk for accessing 64-bit FIFOs in two halves
+
+From: Kaustabh Chakraborty <kauschluss@disroot.org>
+
+[ Upstream commit 57c0902f8bec51add5a1eb908d8b876592725d81 ]
+
+In certain DW MMC implementations (such as in some Exynos7870
+controllers), 64-bit read/write is not allowed from a 64-bit FIFO.
+Add a quirk which facilitates accessing the 64-bit FIFO registers in two
+32-bit halves.
+
+Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
+Link: https://lore.kernel.org/r/20250219-exynos7870-mmc-v2-2-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.c | 94 ++++++++++++++++++++++++++++++++++++++-
+ drivers/mmc/host/dw_mmc.h | 27 +++++++++++
+ 2 files changed, 119 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
+index e9f6e4e622901..55158540c28cf 100644
+--- a/drivers/mmc/host/dw_mmc.c
++++ b/drivers/mmc/host/dw_mmc.c
+@@ -2579,6 +2579,91 @@ static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt)
+ }
+ }
+
++static void dw_mci_push_data64_32(struct dw_mci *host, void *buf, int cnt)
++{
++ struct mmc_data *data = host->data;
++ int init_cnt = cnt;
++
++ /* try and push anything in the part_buf */
++ if (unlikely(host->part_buf_count)) {
++ int len = dw_mci_push_part_bytes(host, buf, cnt);
++
++ buf += len;
++ cnt -= len;
++
++ if (host->part_buf_count == 8) {
++ mci_fifo_l_writeq(host->fifo_reg, host->part_buf);
++ host->part_buf_count = 0;
++ }
++ }
++#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
++ if (unlikely((unsigned long)buf & 0x7)) {
++ while (cnt >= 8) {
++ u64 aligned_buf[16];
++ int len = min(cnt & -8, (int)sizeof(aligned_buf));
++ int items = len >> 3;
++ int i;
++ /* memcpy from input buffer into aligned buffer */
++ memcpy(aligned_buf, buf, len);
++ buf += len;
++ cnt -= len;
++ /* push data from aligned buffer into fifo */
++ for (i = 0; i < items; ++i)
++ mci_fifo_l_writeq(host->fifo_reg, aligned_buf[i]);
++ }
++ } else
++#endif
++ {
++ u64 *pdata = buf;
++
++ for (; cnt >= 8; cnt -= 8)
++ mci_fifo_l_writeq(host->fifo_reg, *pdata++);
++ buf = pdata;
++ }
++ /* put anything remaining in the part_buf */
++ if (cnt) {
++ dw_mci_set_part_bytes(host, buf, cnt);
++ /* Push data if we have reached the expected data length */
++ if ((data->bytes_xfered + init_cnt) ==
++ (data->blksz * data->blocks))
++ mci_fifo_l_writeq(host->fifo_reg, host->part_buf);
++ }
++}
++
++static void dw_mci_pull_data64_32(struct dw_mci *host, void *buf, int cnt)
++{
++#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
++ if (unlikely((unsigned long)buf & 0x7)) {
++ while (cnt >= 8) {
++ /* pull data from fifo into aligned buffer */
++ u64 aligned_buf[16];
++ int len = min(cnt & -8, (int)sizeof(aligned_buf));
++ int items = len >> 3;
++ int i;
++
++ for (i = 0; i < items; ++i)
++ aligned_buf[i] = mci_fifo_l_readq(host->fifo_reg);
++
++ /* memcpy from aligned buffer into output buffer */
++ memcpy(buf, aligned_buf, len);
++ buf += len;
++ cnt -= len;
++ }
++ } else
++#endif
++ {
++ u64 *pdata = buf;
++
++ for (; cnt >= 8; cnt -= 8)
++ *pdata++ = mci_fifo_l_readq(host->fifo_reg);
++ buf = pdata;
++ }
++ if (cnt) {
++ host->part_buf = mci_fifo_l_readq(host->fifo_reg);
++ dw_mci_pull_final_bytes(host, buf, cnt);
++ }
++}
++
+ static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt)
+ {
+ int len;
+@@ -3379,8 +3464,13 @@ int dw_mci_probe(struct dw_mci *host)
+ width = 16;
+ host->data_shift = 1;
+ } else if (i == 2) {
+- host->push_data = dw_mci_push_data64;
+- host->pull_data = dw_mci_pull_data64;
++ if ((host->quirks & DW_MMC_QUIRK_FIFO64_32)) {
++ host->push_data = dw_mci_push_data64_32;
++ host->pull_data = dw_mci_pull_data64_32;
++ } else {
++ host->push_data = dw_mci_push_data64;
++ host->pull_data = dw_mci_pull_data64;
++ }
+ width = 64;
+ host->data_shift = 3;
+ } else {
+diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
+index 6447b916990dc..5463392dc8110 100644
+--- a/drivers/mmc/host/dw_mmc.h
++++ b/drivers/mmc/host/dw_mmc.h
+@@ -281,6 +281,8 @@ struct dw_mci_board {
+
+ /* Support for longer data read timeout */
+ #define DW_MMC_QUIRK_EXTENDED_TMOUT BIT(0)
++/* Force 32-bit access to the FIFO */
++#define DW_MMC_QUIRK_FIFO64_32 BIT(1)
+
+ #define DW_MMC_240A 0x240a
+ #define DW_MMC_280A 0x280a
+@@ -472,6 +474,31 @@ struct dw_mci_board {
+ #define mci_fifo_writel(__value, __reg) __raw_writel(__reg, __value)
+ #define mci_fifo_writeq(__value, __reg) __raw_writeq(__reg, __value)
+
++/*
++ * Some dw_mmc devices have 64-bit FIFOs, but expect them to be
++ * accessed using two 32-bit accesses. If such controller is used
++ * with a 64-bit kernel, this has to be done explicitly.
++ */
++static inline u64 mci_fifo_l_readq(void __iomem *addr)
++{
++ u64 ans;
++ u32 proxy[2];
++
++ proxy[0] = mci_fifo_readl(addr);
++ proxy[1] = mci_fifo_readl(addr + 4);
++ memcpy(&ans, proxy, 8);
++ return ans;
++}
++
++static inline void mci_fifo_l_writeq(void __iomem *addr, u64 value)
++{
++ u32 proxy[2];
++
++ memcpy(proxy, &value, 8);
++ mci_fifo_writel(addr, proxy[0]);
++ mci_fifo_writel(addr + 4, proxy[1]);
++}
++
+ /* Register access macros */
+ #define mci_readl(dev, reg) \
+ readl_relaxed((dev)->regs + SDMMC_##reg)
+--
+2.39.5
+
--- /dev/null
+From 2fe9916fa276f87e68fba3640693004a9eac7bd6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Feb 2025 13:56:12 -0800
+Subject: net: page_pool: don't cast mp param to devmem
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+[ Upstream commit 8d522566ae9cb3f0609ddb2a6ce3f4f39988043c ]
+
+page_pool_check_memory_provider() is a generic path and shouldn't assume
+anything about the actual type of the memory provider argument. It's
+fine while devmem is the only provider, but cast away the devmem
+specific binding types to avoid confusion.
+
+Reviewed-by: Jakub Kicinski <kuba@kernel.org>
+Reviewed-by: Mina Almasry <almasrymina@google.com>
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Signed-off-by: David Wei <dw@davidwei.uk>
+Link: https://patch.msgid.link/20250204215622.695511-2-dw@davidwei.uk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/page_pool_user.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/core/page_pool_user.c b/net/core/page_pool_user.c
+index 48335766c1bfd..8d31c71bea1a3 100644
+--- a/net/core/page_pool_user.c
++++ b/net/core/page_pool_user.c
+@@ -353,7 +353,7 @@ void page_pool_unlist(struct page_pool *pool)
+ int page_pool_check_memory_provider(struct net_device *dev,
+ struct netdev_rx_queue *rxq)
+ {
+- struct net_devmem_dmabuf_binding *binding = rxq->mp_params.mp_priv;
++ void *binding = rxq->mp_params.mp_priv;
+ struct page_pool *pool;
+ struct hlist_node *n;
+
+--
+2.39.5
+
--- /dev/null
+From 252a0da24335765147bf36bfb4e698cec8dfdd47 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Feb 2025 18:59:40 +0100
+Subject: net: sfp: add quirk for 2.5G OEM BX SFP
+
+From: Birger Koblitz <mail@birger-koblitz.de>
+
+[ Upstream commit a85035561025063125f81090e4f2bd65da368c83 ]
+
+The OEM SFP-2.5G-BX10-D/U SFP module pair is meant to operate with
+2500Base-X. However, in their EEPROM they incorrectly specify:
+Transceiver codes : 0x00 0x12 0x00 0x00 0x12 0x00 0x01 0x05 0x00
+BR, Nominal : 2500MBd
+
+Use sfp_quirk_2500basex for this module to allow 2500Base-X mode anyway.
+Tested on BananaPi R3.
+
+Signed-off-by: Birger Koblitz <mail@birger-koblitz.de>
+Reviewed-by: Daniel Golle <daniel@makrotopia.org>
+Link: https://patch.msgid.link/20250218-b4-lkmsub-v1-1-1e51dcabed90@birger-koblitz.de
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/phy/sfp.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
+index dcec92625cf65..9a5de80acd2f7 100644
+--- a/drivers/net/phy/sfp.c
++++ b/drivers/net/phy/sfp.c
+@@ -515,6 +515,8 @@ static const struct sfp_quirk sfp_quirks[] = {
+
+ SFP_QUIRK_F("OEM", "SFP-10G-T", sfp_fixup_rollball_cc),
+ SFP_QUIRK_M("OEM", "SFP-2.5G-T", sfp_quirk_oem_2_5g),
++ SFP_QUIRK_M("OEM", "SFP-2.5G-BX10-D", sfp_quirk_2500basex),
++ SFP_QUIRK_M("OEM", "SFP-2.5G-BX10-U", sfp_quirk_2500basex),
+ SFP_QUIRK_F("OEM", "RTSFP-10", sfp_fixup_rollball_cc),
+ SFP_QUIRK_F("OEM", "RTSFP-10G", sfp_fixup_rollball_cc),
+ SFP_QUIRK_F("Turris", "RTSFP-2.5G", sfp_fixup_rollball),
+--
+2.39.5
+
--- /dev/null
+From 9376e8defc37214cad97ebd6cf60a9af4a68d677 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Feb 2025 08:10:58 +0100
+Subject: net: sfp: add quirk for FS SFP-10GM-T copper SFP+ module
+
+From: Martin Schiller <ms@dev.tdt.de>
+
+[ Upstream commit 05ec5c085eb7ae044d49e04a3cff194a0b2a3251 ]
+
+Add quirk for a copper SFP that identifies itself as "FS" "SFP-10GM-T".
+It uses RollBall protocol to talk to the PHY and needs 4 sec wait before
+probing the PHY.
+
+Signed-off-by: Martin Schiller <ms@dev.tdt.de>
+Link: https://patch.msgid.link/20250227071058.1520027-1-ms@dev.tdt.de
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/phy/sfp.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
+index 9a5de80acd2f7..7b33993f7001e 100644
+--- a/drivers/net/phy/sfp.c
++++ b/drivers/net/phy/sfp.c
+@@ -385,7 +385,7 @@ static void sfp_fixup_rollball(struct sfp *sfp)
+ sfp->phy_t_retry = msecs_to_jiffies(1000);
+ }
+
+-static void sfp_fixup_fs_2_5gt(struct sfp *sfp)
++static void sfp_fixup_rollball_wait4s(struct sfp *sfp)
+ {
+ sfp_fixup_rollball(sfp);
+
+@@ -399,7 +399,7 @@ static void sfp_fixup_fs_2_5gt(struct sfp *sfp)
+ static void sfp_fixup_fs_10gt(struct sfp *sfp)
+ {
+ sfp_fixup_10gbaset_30m(sfp);
+- sfp_fixup_fs_2_5gt(sfp);
++ sfp_fixup_rollball_wait4s(sfp);
+ }
+
+ static void sfp_fixup_halny_gsfp(struct sfp *sfp)
+@@ -479,9 +479,10 @@ static const struct sfp_quirk sfp_quirks[] = {
+ // PHY.
+ SFP_QUIRK_F("FS", "SFP-10G-T", sfp_fixup_fs_10gt),
+
+- // Fiberstore SFP-2.5G-T uses Rollball protocol to talk to the PHY and
+- // needs 4 sec wait before probing the PHY.
+- SFP_QUIRK_F("FS", "SFP-2.5G-T", sfp_fixup_fs_2_5gt),
++ // Fiberstore SFP-2.5G-T and SFP-10GM-T uses Rollball protocol to talk
++ // to the PHY and needs 4 sec wait before probing the PHY.
++ SFP_QUIRK_F("FS", "SFP-2.5G-T", sfp_fixup_rollball_wait4s),
++ SFP_QUIRK_F("FS", "SFP-10GM-T", sfp_fixup_rollball_wait4s),
+
+ // Fiberstore GPON-ONU-34-20BI can operate at 2500base-X, but report 1.2GBd
+ // NRZ in their EEPROM
+--
+2.39.5
+
--- /dev/null
+From 6a699c7677482e07ccc68ec432fe5098a419e9f3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Feb 2025 16:09:51 +0100
+Subject: net: usb: asix_devices: add FiberGecko DeviceID
+
+From: Max Schulze <max.schulze@online.de>
+
+[ Upstream commit 4079918ae720e842ed7dff65fedeb9980b374995 ]
+
+The FiberGecko is a small USB module that connects a 100 Mbit/s SFP
+
+Signed-off-by: Max Schulze <max.schulze@online.de>
+Tested-by: Max Schulze <max.schulze@online.de>
+Suggested-by: David Hollis <dhollis@davehollis.com>
+Reported-by: Sven Kreiensen <s.kreiensen@lyconsys.com>
+Link: https://patch.msgid.link/20250212150957.43900-2-max.schulze@online.de
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/asix_devices.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
+index 57d6e5abc30e8..da24941a6e444 100644
+--- a/drivers/net/usb/asix_devices.c
++++ b/drivers/net/usb/asix_devices.c
+@@ -1421,6 +1421,19 @@ static const struct driver_info hg20f9_info = {
+ .data = FLAG_EEPROM_MAC,
+ };
+
++static const struct driver_info lyconsys_fibergecko100_info = {
++ .description = "LyconSys FiberGecko 100 USB 2.0 to SFP Adapter",
++ .bind = ax88178_bind,
++ .status = asix_status,
++ .link_reset = ax88178_link_reset,
++ .reset = ax88178_link_reset,
++ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
++ FLAG_MULTI_PACKET,
++ .rx_fixup = asix_rx_fixup_common,
++ .tx_fixup = asix_tx_fixup,
++ .data = 0x20061201,
++};
++
+ static const struct usb_device_id products [] = {
+ {
+ // Linksys USB200M
+@@ -1578,6 +1591,10 @@ static const struct usb_device_id products [] = {
+ // Linux Automation GmbH USB 10Base-T1L
+ USB_DEVICE(0x33f7, 0x0004),
+ .driver_info = (unsigned long) &lxausb_t1l_info,
++}, {
++ /* LyconSys FiberGecko 100 */
++ USB_DEVICE(0x1d2a, 0x0801),
++ .driver_info = (unsigned long) &lyconsys_fibergecko100_info,
+ },
+ { }, // END
+ };
+--
+2.39.5
+
--- /dev/null
+From 388579e2eaab88699e9c173ed4f0423657ed4140 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Mar 2025 03:06:57 -0700
+Subject: net: vlan: don't propagate flags on open
+
+From: Stanislav Fomichev <sdf@fomichev.me>
+
+[ Upstream commit 27b918007d96402aba10ed52a6af8015230f1793 ]
+
+With the device instance lock, there is now a possibility of a deadlock:
+
+[ 1.211455] ============================================
+[ 1.211571] WARNING: possible recursive locking detected
+[ 1.211687] 6.14.0-rc5-01215-g032756b4ca7a-dirty #5 Not tainted
+[ 1.211823] --------------------------------------------
+[ 1.211936] ip/184 is trying to acquire lock:
+[ 1.212032] ffff8881024a4c30 (&dev->lock){+.+.}-{4:4}, at: dev_set_allmulti+0x4e/0xb0
+[ 1.212207]
+[ 1.212207] but task is already holding lock:
+[ 1.212332] ffff8881024a4c30 (&dev->lock){+.+.}-{4:4}, at: dev_open+0x50/0xb0
+[ 1.212487]
+[ 1.212487] other info that might help us debug this:
+[ 1.212626] Possible unsafe locking scenario:
+[ 1.212626]
+[ 1.212751] CPU0
+[ 1.212815] ----
+[ 1.212871] lock(&dev->lock);
+[ 1.212944] lock(&dev->lock);
+[ 1.213016]
+[ 1.213016] *** DEADLOCK ***
+[ 1.213016]
+[ 1.213143] May be due to missing lock nesting notation
+[ 1.213143]
+[ 1.213294] 3 locks held by ip/184:
+[ 1.213371] #0: ffffffff838b53e0 (rtnl_mutex){+.+.}-{4:4}, at: rtnl_nets_lock+0x1b/0xa0
+[ 1.213543] #1: ffffffff84e5fc70 (&net->rtnl_mutex){+.+.}-{4:4}, at: rtnl_nets_lock+0x37/0xa0
+[ 1.213727] #2: ffff8881024a4c30 (&dev->lock){+.+.}-{4:4}, at: dev_open+0x50/0xb0
+[ 1.213895]
+[ 1.213895] stack backtrace:
+[ 1.213991] CPU: 0 UID: 0 PID: 184 Comm: ip Not tainted 6.14.0-rc5-01215-g032756b4ca7a-dirty #5
+[ 1.213993] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.16.3-1-1 04/01/2014
+[ 1.213994] Call Trace:
+[ 1.213995] <TASK>
+[ 1.213996] dump_stack_lvl+0x8e/0xd0
+[ 1.214000] print_deadlock_bug+0x28b/0x2a0
+[ 1.214020] lock_acquire+0xea/0x2a0
+[ 1.214027] __mutex_lock+0xbf/0xd40
+[ 1.214038] dev_set_allmulti+0x4e/0xb0 # real_dev->flags & IFF_ALLMULTI
+[ 1.214040] vlan_dev_open+0xa5/0x170 # ndo_open on vlandev
+[ 1.214042] __dev_open+0x145/0x270
+[ 1.214046] __dev_change_flags+0xb0/0x1e0
+[ 1.214051] netif_change_flags+0x22/0x60 # IFF_UP vlandev
+[ 1.214053] dev_change_flags+0x61/0xb0 # for each device in group from dev->vlan_info
+[ 1.214055] vlan_device_event+0x766/0x7c0 # on netdevsim0
+[ 1.214058] notifier_call_chain+0x78/0x120
+[ 1.214062] netif_open+0x6d/0x90
+[ 1.214064] dev_open+0x5b/0xb0 # locks netdevsim0
+[ 1.214066] bond_enslave+0x64c/0x1230
+[ 1.214075] do_set_master+0x175/0x1e0 # on netdevsim0
+[ 1.214077] do_setlink+0x516/0x13b0
+[ 1.214094] rtnl_newlink+0xaba/0xb80
+[ 1.214132] rtnetlink_rcv_msg+0x440/0x490
+[ 1.214144] netlink_rcv_skb+0xeb/0x120
+[ 1.214150] netlink_unicast+0x1f9/0x320
+[ 1.214153] netlink_sendmsg+0x346/0x3f0
+[ 1.214157] __sock_sendmsg+0x86/0xb0
+[ 1.214160] ____sys_sendmsg+0x1c8/0x220
+[ 1.214164] ___sys_sendmsg+0x28f/0x2d0
+[ 1.214179] __x64_sys_sendmsg+0xef/0x140
+[ 1.214184] do_syscall_64+0xec/0x1d0
+[ 1.214190] entry_SYSCALL_64_after_hwframe+0x77/0x7f
+[ 1.214191] RIP: 0033:0x7f2d1b4a7e56
+
+Device setup:
+
+ netdevsim0 (down)
+ ^ ^
+ bond netdevsim1.100@netdevsim1 allmulticast=on (down)
+
+When we enslave the lower device (netdevsim0) which has a vlan, we
+propagate vlan's allmuti/promisc flags during ndo_open. This causes
+(re)locking on of the real_dev.
+
+Propagate allmulti/promisc on flags change, not on the open. There
+is a slight semantics change that vlans that are down now propagate
+the flags, but this seems unlikely to result in the real issues.
+
+Reproducer:
+
+ echo 0 1 > /sys/bus/netdevsim/new_device
+
+ dev_path=$(ls -d /sys/bus/netdevsim/devices/netdevsim0/net/*)
+ dev=$(echo $dev_path | rev | cut -d/ -f1 | rev)
+
+ ip link set dev $dev name netdevsim0
+ ip link set dev netdevsim0 up
+
+ ip link add link netdevsim0 name netdevsim0.100 type vlan id 100
+ ip link set dev netdevsim0.100 allmulticast on down
+ ip link add name bond1 type bond mode 802.3ad
+ ip link set dev netdevsim0 down
+ ip link set dev netdevsim0 master bond1
+ ip link set dev bond1 up
+ ip link show
+
+Reported-by: syzbot+b0c03d76056ef6cd12a6@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/Z9CfXjLMKn6VLG5d@mini-arch/T/#m15ba130f53227c883e79fb969687d69d670337a0
+Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20250313100657.2287455-1-sdf@fomichev.me
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/8021q/vlan_dev.c | 31 ++++---------------------------
+ 1 file changed, 4 insertions(+), 27 deletions(-)
+
+diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
+index 458040e8a0e0b..9184cf7eb1286 100644
+--- a/net/8021q/vlan_dev.c
++++ b/net/8021q/vlan_dev.c
+@@ -273,17 +273,6 @@ static int vlan_dev_open(struct net_device *dev)
+ goto out;
+ }
+
+- if (dev->flags & IFF_ALLMULTI) {
+- err = dev_set_allmulti(real_dev, 1);
+- if (err < 0)
+- goto del_unicast;
+- }
+- if (dev->flags & IFF_PROMISC) {
+- err = dev_set_promiscuity(real_dev, 1);
+- if (err < 0)
+- goto clear_allmulti;
+- }
+-
+ ether_addr_copy(vlan->real_dev_addr, real_dev->dev_addr);
+
+ if (vlan->flags & VLAN_FLAG_GVRP)
+@@ -297,12 +286,6 @@ static int vlan_dev_open(struct net_device *dev)
+ netif_carrier_on(dev);
+ return 0;
+
+-clear_allmulti:
+- if (dev->flags & IFF_ALLMULTI)
+- dev_set_allmulti(real_dev, -1);
+-del_unicast:
+- if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr))
+- dev_uc_del(real_dev, dev->dev_addr);
+ out:
+ netif_carrier_off(dev);
+ return err;
+@@ -315,10 +298,6 @@ static int vlan_dev_stop(struct net_device *dev)
+
+ dev_mc_unsync(real_dev, dev);
+ dev_uc_unsync(real_dev, dev);
+- if (dev->flags & IFF_ALLMULTI)
+- dev_set_allmulti(real_dev, -1);
+- if (dev->flags & IFF_PROMISC)
+- dev_set_promiscuity(real_dev, -1);
+
+ if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr))
+ dev_uc_del(real_dev, dev->dev_addr);
+@@ -490,12 +469,10 @@ static void vlan_dev_change_rx_flags(struct net_device *dev, int change)
+ {
+ struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
+
+- if (dev->flags & IFF_UP) {
+- if (change & IFF_ALLMULTI)
+- dev_set_allmulti(real_dev, dev->flags & IFF_ALLMULTI ? 1 : -1);
+- if (change & IFF_PROMISC)
+- dev_set_promiscuity(real_dev, dev->flags & IFF_PROMISC ? 1 : -1);
+- }
++ if (change & IFF_ALLMULTI)
++ dev_set_allmulti(real_dev, dev->flags & IFF_ALLMULTI ? 1 : -1);
++ if (change & IFF_PROMISC)
++ dev_set_promiscuity(real_dev, dev->flags & IFF_PROMISC ? 1 : -1);
+ }
+
+ static void vlan_dev_set_rx_mode(struct net_device *vlan_dev)
+--
+2.39.5
+
--- /dev/null
+From cdb1a5c4dbe743d5038a73a885ff68009e597c77 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Feb 2025 14:42:50 +0800
+Subject: page_pool: avoid infinite loop to schedule delayed worker
+
+From: Jason Xing <kerneljasonxing@gmail.com>
+
+[ Upstream commit 43130d02baa137033c25297aaae95fd0edc41654 ]
+
+We noticed the kworker in page_pool_release_retry() was waken
+up repeatedly and infinitely in production because of the
+buggy driver causing the inflight less than 0 and warning
+us in page_pool_inflight()[1].
+
+Since the inflight value goes negative, it means we should
+not expect the whole page_pool to get back to work normally.
+
+This patch mitigates the adverse effect by not rescheduling
+the kworker when detecting the inflight negative in
+page_pool_release_retry().
+
+[1]
+[Mon Feb 10 20:36:11 2025] ------------[ cut here ]------------
+[Mon Feb 10 20:36:11 2025] Negative(-51446) inflight packet-pages
+...
+[Mon Feb 10 20:36:11 2025] Call Trace:
+[Mon Feb 10 20:36:11 2025] page_pool_release_retry+0x23/0x70
+[Mon Feb 10 20:36:11 2025] process_one_work+0x1b1/0x370
+[Mon Feb 10 20:36:11 2025] worker_thread+0x37/0x3a0
+[Mon Feb 10 20:36:11 2025] kthread+0x11a/0x140
+[Mon Feb 10 20:36:11 2025] ? process_one_work+0x370/0x370
+[Mon Feb 10 20:36:11 2025] ? __kthread_cancel_work+0x40/0x40
+[Mon Feb 10 20:36:11 2025] ret_from_fork+0x35/0x40
+[Mon Feb 10 20:36:11 2025] ---[ end trace ebffe800f33e7e34 ]---
+Note: before this patch, the above calltrace would flood the
+dmesg due to repeated reschedule of release_dw kworker.
+
+Signed-off-by: Jason Xing <kerneljasonxing@gmail.com>
+Reviewed-by: Mina Almasry <almasrymina@google.com>
+Link: https://patch.msgid.link/20250214064250.85987-1-kerneljasonxing@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/page_pool.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/net/core/page_pool.c b/net/core/page_pool.c
+index a813d30d21353..7b20f6fcb82c0 100644
+--- a/net/core/page_pool.c
++++ b/net/core/page_pool.c
+@@ -1066,7 +1066,13 @@ static void page_pool_release_retry(struct work_struct *wq)
+ int inflight;
+
+ inflight = page_pool_release(pool);
+- if (!inflight)
++ /* In rare cases, a driver bug may cause inflight to go negative.
++ * Don't reschedule release if inflight is 0 or negative.
++ * - If 0, the page_pool has been destroyed
++ * - if negative, we will never recover
++ * in both cases no reschedule is necessary.
++ */
++ if (inflight <= 0)
+ return;
+
+ /* Periodic warning for page pools the user can't see */
+--
+2.39.5
+
--- /dev/null
+From 22a7fbc9e76d502224b2982e288ad6cd22579ad6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Feb 2025 10:21:21 +0100
+Subject: PCI: Add Rockchip Vendor ID
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Shawn Lin <shawn.lin@rock-chips.com>
+
+[ Upstream commit 20bbb083bbc9d3f8db390f2e35e168f1b23dae8a ]
+
+Move PCI_VENDOR_ID_ROCKCHIP from pci_endpoint_test.c to pci_ids.h and
+reuse it in pcie-rockchip-host.c.
+
+Link: https://lore.kernel.org/r/20250218092120.2322784-2-cassel@kernel.org
+Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
+Signed-off-by: Niklas Cassel <cassel@kernel.org>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/misc/pci_endpoint_test.c | 1 -
+ drivers/pci/controller/pcie-rockchip-host.c | 2 +-
+ drivers/pci/controller/pcie-rockchip.h | 1 -
+ include/linux/pci_ids.h | 2 ++
+ 4 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
+index 3aaaf47fa4ee2..b5c8422fd2f04 100644
+--- a/drivers/misc/pci_endpoint_test.c
++++ b/drivers/misc/pci_endpoint_test.c
+@@ -85,7 +85,6 @@
+ #define PCI_DEVICE_ID_RENESAS_R8A774E1 0x0025
+ #define PCI_DEVICE_ID_RENESAS_R8A779F0 0x0031
+
+-#define PCI_VENDOR_ID_ROCKCHIP 0x1d87
+ #define PCI_DEVICE_ID_ROCKCHIP_RK3588 0x3588
+
+ static DEFINE_IDA(pci_endpoint_test_ida);
+diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c
+index cbec711148253..481dcc476c556 100644
+--- a/drivers/pci/controller/pcie-rockchip-host.c
++++ b/drivers/pci/controller/pcie-rockchip-host.c
+@@ -367,7 +367,7 @@ static int rockchip_pcie_host_init_port(struct rockchip_pcie *rockchip)
+ }
+ }
+
+- rockchip_pcie_write(rockchip, ROCKCHIP_VENDOR_ID,
++ rockchip_pcie_write(rockchip, PCI_VENDOR_ID_ROCKCHIP,
+ PCIE_CORE_CONFIG_VENDOR);
+ rockchip_pcie_write(rockchip,
+ PCI_CLASS_BRIDGE_PCI_NORMAL << 8,
+diff --git a/drivers/pci/controller/pcie-rockchip.h b/drivers/pci/controller/pcie-rockchip.h
+index 15ee949f2485e..688f51d9bde63 100644
+--- a/drivers/pci/controller/pcie-rockchip.h
++++ b/drivers/pci/controller/pcie-rockchip.h
+@@ -188,7 +188,6 @@
+ #define AXI_WRAPPER_NOR_MSG 0xc
+
+ #define PCIE_RC_SEND_PME_OFF 0x11960
+-#define ROCKCHIP_VENDOR_ID 0x1d87
+ #define PCIE_LINK_IS_L2(x) \
+ (((x) & PCIE_CLIENT_DEBUG_LTSSM_MASK) == PCIE_CLIENT_DEBUG_LTSSM_L2)
+ #define PCIE_LINK_UP(x) \
+diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
+index c9dc15355f1ba..c395b3c5c05cf 100644
+--- a/include/linux/pci_ids.h
++++ b/include/linux/pci_ids.h
+@@ -2605,6 +2605,8 @@
+
+ #define PCI_VENDOR_ID_ZHAOXIN 0x1d17
+
++#define PCI_VENDOR_ID_ROCKCHIP 0x1d87
++
+ #define PCI_VENDOR_ID_HYGON 0x1d94
+
+ #define PCI_VENDOR_ID_META 0x1d9b
+--
+2.39.5
+
--- /dev/null
+From c8d5893c6152279ef33a51865d6b890272aff783 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Mar 2025 09:06:35 +0100
+Subject: PCI: Check BAR index for validity
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Philipp Stanner <phasta@kernel.org>
+
+[ Upstream commit b1a7f99967fc0c052db8e65b449c7b32b1e9177f ]
+
+Many functions in PCI use accessor macros such as pci_resource_len(),
+which take a BAR index. That index, however, is never checked for
+validity, potentially resulting in undefined behavior by overflowing the
+array pci_dev.resource in the macro pci_resource_n().
+
+Since many users of those macros directly assign the accessed value to
+an unsigned integer, the macros cannot be changed easily anymore to
+return -EINVAL for invalid indexes. Consequently, the problem has to be
+mitigated in higher layers.
+
+Add pci_bar_index_valid(). Use it where appropriate.
+
+Link: https://lore.kernel.org/r/20250312080634.13731-4-phasta@kernel.org
+Closes: https://lore.kernel.org/all/adb53b1f-29e1-3d14-0e61-351fd2d3ff0d@linux.intel.com/
+Reported-by: Bingbu Cao <bingbu.cao@linux.intel.com>
+Signed-off-by: Philipp Stanner <phasta@kernel.org>
+[kwilczynski: correct if-statement condition the pci_bar_index_is_valid()
+helper function uses, tidy up code comments]
+Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
+[bhelgaas: fix typo]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/devres.c | 16 ++++++++++++++--
+ drivers/pci/iomap.c | 29 +++++++++++++++++++++--------
+ drivers/pci/pci.c | 6 ++++++
+ drivers/pci/pci.h | 16 ++++++++++++++++
+ 4 files changed, 57 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/pci/devres.c b/drivers/pci/devres.c
+index 643f85849ef64..cd39479de7c72 100644
+--- a/drivers/pci/devres.c
++++ b/drivers/pci/devres.c
+@@ -577,7 +577,7 @@ static int pcim_add_mapping_to_legacy_table(struct pci_dev *pdev,
+ {
+ void __iomem **legacy_iomap_table;
+
+- if (bar >= PCI_STD_NUM_BARS)
++ if (!pci_bar_index_is_valid(bar))
+ return -EINVAL;
+
+ legacy_iomap_table = (void __iomem **)pcim_iomap_table(pdev);
+@@ -622,7 +622,7 @@ static void pcim_remove_bar_from_legacy_table(struct pci_dev *pdev, int bar)
+ {
+ void __iomem **legacy_iomap_table;
+
+- if (bar >= PCI_STD_NUM_BARS)
++ if (!pci_bar_index_is_valid(bar))
+ return;
+
+ legacy_iomap_table = (void __iomem **)pcim_iomap_table(pdev);
+@@ -655,6 +655,9 @@ void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
+ void __iomem *mapping;
+ struct pcim_addr_devres *res;
+
++ if (!pci_bar_index_is_valid(bar))
++ return NULL;
++
+ res = pcim_addr_devres_alloc(pdev);
+ if (!res)
+ return NULL;
+@@ -722,6 +725,9 @@ void __iomem *pcim_iomap_region(struct pci_dev *pdev, int bar,
+ int ret;
+ struct pcim_addr_devres *res;
+
++ if (!pci_bar_index_is_valid(bar))
++ return IOMEM_ERR_PTR(-EINVAL);
++
+ res = pcim_addr_devres_alloc(pdev);
+ if (!res)
+ return IOMEM_ERR_PTR(-ENOMEM);
+@@ -822,6 +828,9 @@ static int _pcim_request_region(struct pci_dev *pdev, int bar, const char *name,
+ int ret;
+ struct pcim_addr_devres *res;
+
++ if (!pci_bar_index_is_valid(bar))
++ return -EINVAL;
++
+ res = pcim_addr_devres_alloc(pdev);
+ if (!res)
+ return -ENOMEM;
+@@ -1043,6 +1052,9 @@ void __iomem *pcim_iomap_range(struct pci_dev *pdev, int bar,
+ void __iomem *mapping;
+ struct pcim_addr_devres *res;
+
++ if (!pci_bar_index_is_valid(bar))
++ return IOMEM_ERR_PTR(-EINVAL);
++
+ res = pcim_addr_devres_alloc(pdev);
+ if (!res)
+ return IOMEM_ERR_PTR(-ENOMEM);
+diff --git a/drivers/pci/iomap.c b/drivers/pci/iomap.c
+index 9fb7cacc15cde..fe706ed946dfd 100644
+--- a/drivers/pci/iomap.c
++++ b/drivers/pci/iomap.c
+@@ -9,6 +9,8 @@
+
+ #include <linux/export.h>
+
++#include "pci.h" /* for pci_bar_index_is_valid() */
++
+ /**
+ * pci_iomap_range - create a virtual mapping cookie for a PCI BAR
+ * @dev: PCI device that owns the BAR
+@@ -33,12 +35,19 @@ void __iomem *pci_iomap_range(struct pci_dev *dev,
+ unsigned long offset,
+ unsigned long maxlen)
+ {
+- resource_size_t start = pci_resource_start(dev, bar);
+- resource_size_t len = pci_resource_len(dev, bar);
+- unsigned long flags = pci_resource_flags(dev, bar);
++ resource_size_t start, len;
++ unsigned long flags;
++
++ if (!pci_bar_index_is_valid(bar))
++ return NULL;
++
++ start = pci_resource_start(dev, bar);
++ len = pci_resource_len(dev, bar);
++ flags = pci_resource_flags(dev, bar);
+
+ if (len <= offset || !start)
+ return NULL;
++
+ len -= offset;
+ start += offset;
+ if (maxlen && len > maxlen)
+@@ -77,16 +86,20 @@ void __iomem *pci_iomap_wc_range(struct pci_dev *dev,
+ unsigned long offset,
+ unsigned long maxlen)
+ {
+- resource_size_t start = pci_resource_start(dev, bar);
+- resource_size_t len = pci_resource_len(dev, bar);
+- unsigned long flags = pci_resource_flags(dev, bar);
++ resource_size_t start, len;
++ unsigned long flags;
+
+-
+- if (flags & IORESOURCE_IO)
++ if (!pci_bar_index_is_valid(bar))
+ return NULL;
+
++ start = pci_resource_start(dev, bar);
++ len = pci_resource_len(dev, bar);
++ flags = pci_resource_flags(dev, bar);
++
+ if (len <= offset || !start)
+ return NULL;
++ if (flags & IORESOURCE_IO)
++ return NULL;
+
+ len -= offset;
+ start += offset;
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index 169aa8fd74a11..be61fa93d3971 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -3922,6 +3922,9 @@ EXPORT_SYMBOL(pci_enable_atomic_ops_to_root);
+ */
+ void pci_release_region(struct pci_dev *pdev, int bar)
+ {
++ if (!pci_bar_index_is_valid(bar))
++ return;
++
+ /*
+ * This is done for backwards compatibility, because the old PCI devres
+ * API had a mode in which the function became managed if it had been
+@@ -3967,6 +3970,9 @@ EXPORT_SYMBOL(pci_release_region);
+ static int __pci_request_region(struct pci_dev *pdev, int bar,
+ const char *res_name, int exclusive)
+ {
++ if (!pci_bar_index_is_valid(bar))
++ return -EINVAL;
++
+ if (pci_is_managed(pdev)) {
+ if (exclusive == IORESOURCE_EXCLUSIVE)
+ return pcim_request_region_exclusive(pdev, bar, res_name);
+diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
+index 1cdc2c9547a7e..65df6d2ac0032 100644
+--- a/drivers/pci/pci.h
++++ b/drivers/pci/pci.h
+@@ -165,6 +165,22 @@ static inline void pci_wakeup_event(struct pci_dev *dev)
+ pm_wakeup_event(&dev->dev, 100);
+ }
+
++/**
++ * pci_bar_index_is_valid - Check whether a BAR index is within valid range
++ * @bar: BAR index
++ *
++ * Protects against overflowing &struct pci_dev.resource array.
++ *
++ * Return: true for valid index, false otherwise.
++ */
++static inline bool pci_bar_index_is_valid(int bar)
++{
++ if (bar >= 0 && bar < PCI_NUM_RESOURCES)
++ return true;
++
++ return false;
++}
++
+ static inline bool pci_has_subordinate(struct pci_dev *pci_dev)
+ {
+ return !!(pci_dev->subordinate);
+--
+2.39.5
+
--- /dev/null
+From 8967d762738ac22f18b8c0dc5060d338d4a046bc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Mar 2025 15:02:17 -0600
+Subject: PCI: Enable Configuration RRS SV early
+
+From: Bjorn Helgaas <bhelgaas@google.com>
+
+[ Upstream commit 3f8c4959fc18e477801386a625e726c59f52a2c4 ]
+
+Following a reset, a Function may respond to Config Requests with Request
+Retry Status (RRS) Completion Status to indicate that it is temporarily
+unable to process the Request, but will be able to process the Request in
+the future (PCIe r6.0, sec 2.3.1).
+
+If the Configuration RRS Software Visibility feature is enabled and a Root
+Complex receives RRS for a config read of the Vendor ID, the Root Complex
+completes the Request to the host by returning PCI_VENDOR_ID_PCI_SIG,
+0x0001 (sec 2.3.2).
+
+The Config RRS SV feature applies only to Root Ports and is not directly
+related to pci_scan_bridge_extend(). Move the RRS SV enable to
+set_pcie_port_type() where we handle other PCIe-specific configuration.
+
+Link: https://lore.kernel.org/r/20250303210217.199504-1-helgaas@kernel.org
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/probe.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
+index 0e757b23a09f0..80dcfb72ea121 100644
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -1327,8 +1327,6 @@ static int pci_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev,
+ pci_write_config_word(dev, PCI_BRIDGE_CONTROL,
+ bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT);
+
+- pci_enable_rrs_sv(dev);
+-
+ if ((secondary || subordinate) && !pcibios_assign_all_busses() &&
+ !is_cardbus && !broken) {
+ unsigned int cmax, buses;
+@@ -1569,6 +1567,11 @@ void set_pcie_port_type(struct pci_dev *pdev)
+ pdev->pcie_cap = pos;
+ pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16);
+ pdev->pcie_flags_reg = reg16;
++
++ type = pci_pcie_type(pdev);
++ if (type == PCI_EXP_TYPE_ROOT_PORT)
++ pci_enable_rrs_sv(pdev);
++
+ pci_read_config_dword(pdev, pos + PCI_EXP_DEVCAP, &pdev->devcap);
+ pdev->pcie_mpss = FIELD_GET(PCI_EXP_DEVCAP_PAYLOAD, pdev->devcap);
+
+@@ -1585,7 +1588,6 @@ void set_pcie_port_type(struct pci_dev *pdev)
+ * correctly so detect impossible configurations here and correct
+ * the port type accordingly.
+ */
+- type = pci_pcie_type(pdev);
+ if (type == PCI_EXP_TYPE_DOWNSTREAM) {
+ /*
+ * If pdev claims to be downstream port but the parent
+--
+2.39.5
+
--- /dev/null
+From 6d42c1e0704ae0a84c16ef906e8676c1ea227c0e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Feb 2025 09:08:30 +0100
+Subject: PCI: vmd: Make vmd_dev::cfg_lock a raw_spinlock_t type
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ryo Takakura <ryotkkr98@gmail.com>
+
+[ Upstream commit 18056a48669a040bef491e63b25896561ee14d90 ]
+
+The access to the PCI config space via pci_ops::read and pci_ops::write is
+a low-level hardware access. The functions can be accessed with disabled
+interrupts even on PREEMPT_RT. The pci_lock is a raw_spinlock_t for this
+purpose.
+
+A spinlock_t becomes a sleeping lock on PREEMPT_RT, so it cannot be
+acquired with disabled interrupts. The vmd_dev::cfg_lock is accessed in
+the same context as the pci_lock.
+
+Make vmd_dev::cfg_lock a raw_spinlock_t type so it can be used with
+interrupts disabled.
+
+This was reported as:
+
+ BUG: sleeping function called from invalid context at kernel/locking/spinlock_rt.c:48
+ Call Trace:
+ rt_spin_lock+0x4e/0x130
+ vmd_pci_read+0x8d/0x100 [vmd]
+ pci_user_read_config_byte+0x6f/0xe0
+ pci_read_config+0xfe/0x290
+ sysfs_kf_bin_read+0x68/0x90
+
+Signed-off-by: Ryo Takakura <ryotkkr98@gmail.com>
+Tested-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
+Acked-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
+[bigeasy: reword commit message]
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Tested-off-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
+Link: https://lore.kernel.org/r/20250218080830.ufw3IgyX@linutronix.de
+[kwilczynski: commit log]
+Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
+[bhelgaas: add back report info from
+https://lore.kernel.org/lkml/20241218115951.83062-1-ryotkkr98@gmail.com/]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/vmd.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c
+index 9d9596947350f..94ceec50a2b94 100644
+--- a/drivers/pci/controller/vmd.c
++++ b/drivers/pci/controller/vmd.c
+@@ -125,7 +125,7 @@ struct vmd_irq_list {
+ struct vmd_dev {
+ struct pci_dev *dev;
+
+- spinlock_t cfg_lock;
++ raw_spinlock_t cfg_lock;
+ void __iomem *cfgbar;
+
+ int msix_count;
+@@ -391,7 +391,7 @@ static int vmd_pci_read(struct pci_bus *bus, unsigned int devfn, int reg,
+ if (!addr)
+ return -EFAULT;
+
+- spin_lock_irqsave(&vmd->cfg_lock, flags);
++ raw_spin_lock_irqsave(&vmd->cfg_lock, flags);
+ switch (len) {
+ case 1:
+ *value = readb(addr);
+@@ -406,7 +406,7 @@ static int vmd_pci_read(struct pci_bus *bus, unsigned int devfn, int reg,
+ ret = -EINVAL;
+ break;
+ }
+- spin_unlock_irqrestore(&vmd->cfg_lock, flags);
++ raw_spin_unlock_irqrestore(&vmd->cfg_lock, flags);
+ return ret;
+ }
+
+@@ -426,7 +426,7 @@ static int vmd_pci_write(struct pci_bus *bus, unsigned int devfn, int reg,
+ if (!addr)
+ return -EFAULT;
+
+- spin_lock_irqsave(&vmd->cfg_lock, flags);
++ raw_spin_lock_irqsave(&vmd->cfg_lock, flags);
+ switch (len) {
+ case 1:
+ writeb(value, addr);
+@@ -444,7 +444,7 @@ static int vmd_pci_write(struct pci_bus *bus, unsigned int devfn, int reg,
+ ret = -EINVAL;
+ break;
+ }
+- spin_unlock_irqrestore(&vmd->cfg_lock, flags);
++ raw_spin_unlock_irqrestore(&vmd->cfg_lock, flags);
+ return ret;
+ }
+
+@@ -1009,7 +1009,7 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ if (features & VMD_FEAT_OFFSET_FIRST_VECTOR)
+ vmd->first_vec = 1;
+
+- spin_lock_init(&vmd->cfg_lock);
++ raw_spin_lock_init(&vmd->cfg_lock);
+ pci_set_drvdata(dev, vmd);
+ err = vmd_enable_domain(vmd, features);
+ if (err)
+--
+2.39.5
+
--- /dev/null
+From a87cd007f8f1cc5fdb15d9f92d0d728655cdb8f7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Feb 2025 14:39:57 -0600
+Subject: perf: arm_pmu: Don't disable counter in armpmu_add()
+
+From: Mark Rutland <mark.rutland@arm.com>
+
+[ Upstream commit dcca27bc1eccb9abc2552aab950b18a9742fb8e7 ]
+
+Currently armpmu_add() tries to handle a newly-allocated counter having
+a stale associated event, but this should not be possible, and if this
+were to happen the current mitigation is insufficient and potentially
+expensive. It would be better to warn if we encounter the impossible
+case.
+
+Calls to pmu::add() and pmu::del() are serialized by the core perf code,
+and armpmu_del() clears the relevant slot in pmu_hw_events::events[]
+before clearing the bit in pmu_hw_events::used_mask such that the
+counter can be reallocated. Thus when armpmu_add() allocates a counter
+index from pmu_hw_events::used_mask, it should not be possible to observe
+a stale even in pmu_hw_events::events[] unless either
+pmu_hw_events::used_mask or pmu_hw_events::events[] have been corrupted.
+
+If this were to happen, we'd end up with two events with the same
+event->hw.idx, which would clash with each other during reprogramming,
+deletion, etc, and produce bogus results. Add a WARN_ON_ONCE() for this
+case so that we can detect if this ever occurs in practice.
+
+That possiblity aside, there's no need to call arm_pmu::disable(event)
+for the new event. The PMU reset code initialises the counter in a
+disabled state, and armpmu_del() will disable the counter before it can
+be reused. Remove the redundant disable.
+
+Signed-off-by: Mark Rutland <mark.rutland@arm.com>
+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-2-4e9922fc2e8e@kernel.org
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/perf/arm_pmu.c | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
+index 398cce3d76fc4..2f33e69a8caf2 100644
+--- a/drivers/perf/arm_pmu.c
++++ b/drivers/perf/arm_pmu.c
+@@ -342,12 +342,10 @@ armpmu_add(struct perf_event *event, int flags)
+ if (idx < 0)
+ return idx;
+
+- /*
+- * If there is an event in the counter we are going to use then make
+- * sure it is disabled.
+- */
++ /* The newly-allocated counter should be empty */
++ WARN_ON_ONCE(hw_events->events[idx]);
++
+ event->hw.idx = idx;
+- armpmu->disable(event);
+ hw_events->events[idx] = event;
+
+ hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+--
+2.39.5
+
--- /dev/null
+From ecca5b755c0db67a25fa8f52f7437f0ad8eb038f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 20:17:15 +0800
+Subject: perf/dwc_pcie: fix some unreleased resources
+
+From: Yunhui Cui <cuiyunhui@bytedance.com>
+
+[ Upstream commit 6eb1e8ef586ac4a3dcdc20248f9cb45e4ceb141f ]
+
+Release leaked resources, such as plat_dev and dev_info.
+
+Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com>
+Reviewed-by: Shuai Xue <xueshuai@linux.alibaba.com>
+Link: https://lore.kernel.org/r/20250220121716.50324-2-cuiyunhui@bytedance.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/perf/dwc_pcie_pmu.c | 33 ++++++++++++++++++++++-----------
+ 1 file changed, 22 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/perf/dwc_pcie_pmu.c b/drivers/perf/dwc_pcie_pmu.c
+index 4ca50f9b6dfed..7dbda36884c8d 100644
+--- a/drivers/perf/dwc_pcie_pmu.c
++++ b/drivers/perf/dwc_pcie_pmu.c
+@@ -567,8 +567,10 @@ static int dwc_pcie_register_dev(struct pci_dev *pdev)
+ return PTR_ERR(plat_dev);
+
+ dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
+- if (!dev_info)
++ if (!dev_info) {
++ platform_device_unregister(plat_dev);
+ return -ENOMEM;
++ }
+
+ /* Cache platform device to handle pci device hotplug */
+ dev_info->plat_dev = plat_dev;
+@@ -724,6 +726,15 @@ static struct platform_driver dwc_pcie_pmu_driver = {
+ .driver = {.name = "dwc_pcie_pmu",},
+ };
+
++static void dwc_pcie_cleanup_devices(void)
++{
++ struct dwc_pcie_dev_info *dev_info, *tmp;
++
++ list_for_each_entry_safe(dev_info, tmp, &dwc_pcie_dev_info_head, dev_node) {
++ dwc_pcie_unregister_dev(dev_info);
++ }
++}
++
+ static int __init dwc_pcie_pmu_init(void)
+ {
+ struct pci_dev *pdev = NULL;
+@@ -736,7 +747,7 @@ static int __init dwc_pcie_pmu_init(void)
+ ret = dwc_pcie_register_dev(pdev);
+ if (ret) {
+ pci_dev_put(pdev);
+- return ret;
++ goto err_cleanup;
+ }
+ }
+
+@@ -745,35 +756,35 @@ static int __init dwc_pcie_pmu_init(void)
+ dwc_pcie_pmu_online_cpu,
+ dwc_pcie_pmu_offline_cpu);
+ if (ret < 0)
+- return ret;
++ goto err_cleanup;
+
+ dwc_pcie_pmu_hp_state = ret;
+
+ ret = platform_driver_register(&dwc_pcie_pmu_driver);
+ if (ret)
+- goto platform_driver_register_err;
++ goto err_remove_cpuhp;
+
+ ret = bus_register_notifier(&pci_bus_type, &dwc_pcie_pmu_nb);
+ if (ret)
+- goto platform_driver_register_err;
++ goto err_unregister_driver;
+ notify = true;
+
+ return 0;
+
+-platform_driver_register_err:
++err_unregister_driver:
++ platform_driver_unregister(&dwc_pcie_pmu_driver);
++err_remove_cpuhp:
+ cpuhp_remove_multi_state(dwc_pcie_pmu_hp_state);
+-
++err_cleanup:
++ dwc_pcie_cleanup_devices();
+ return ret;
+ }
+
+ static void __exit dwc_pcie_pmu_exit(void)
+ {
+- struct dwc_pcie_dev_info *dev_info, *tmp;
+-
+ if (notify)
+ bus_unregister_notifier(&pci_bus_type, &dwc_pcie_pmu_nb);
+- list_for_each_entry_safe(dev_info, tmp, &dwc_pcie_dev_info_head, dev_node)
+- dwc_pcie_unregister_dev(dev_info);
++ dwc_pcie_cleanup_devices();
+ platform_driver_unregister(&dwc_pcie_pmu_driver);
+ cpuhp_remove_multi_state(dwc_pcie_pmu_hp_state);
+ }
+--
+2.39.5
+
--- /dev/null
+From e87f4f51710c23ca470548b8305ee1a34c203257 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jan 2025 02:13:29 +0800
+Subject: platform/chrome: cros_ec_lpc: Match on Framework ACPI device
+
+From: Daniel Schaefer <dhs@frame.work>
+
+[ Upstream commit d83c45aeec9b223fe6db4175e9d1c4f5699cc37a ]
+
+Load the cros_ec_lpc driver based on a Framework FRMWC004 ACPI device,
+which mirrors GOOG0004, but also applies npcx quirks for Framework
+systems.
+
+Matching on ACPI will let us avoid having to change the SMBIOS match
+rules again and again.
+
+Cc: Tzung-Bi Shih <tzungbi@kernel.org>
+Cc: linux@frame.work
+Cc: Dustin L. Howett <dustin@howett.net>
+Signed-off-by: Daniel Schaefer <dhs@frame.work>
+Link: https://lore.kernel.org/r/20250128181329.8070-1-dhs@frame.work
+Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/chrome/cros_ec_lpc.c | 22 ++++++++++++++--------
+ 1 file changed, 14 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c
+index 626e2635e3da7..ac198d1fd1707 100644
+--- a/drivers/platform/chrome/cros_ec_lpc.c
++++ b/drivers/platform/chrome/cros_ec_lpc.c
+@@ -30,6 +30,7 @@
+
+ #define DRV_NAME "cros_ec_lpcs"
+ #define ACPI_DRV_NAME "GOOG0004"
++#define FRMW_ACPI_DRV_NAME "FRMWC004"
+
+ /* True if ACPI device is present */
+ static bool cros_ec_lpc_acpi_device_found;
+@@ -460,7 +461,7 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
+ acpi_status status;
+ struct cros_ec_device *ec_dev;
+ struct cros_ec_lpc *ec_lpc;
+- struct lpc_driver_data *driver_data;
++ const struct lpc_driver_data *driver_data;
+ u8 buf[2] = {};
+ int irq, ret;
+ u32 quirks;
+@@ -472,6 +473,9 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
+ ec_lpc->mmio_memory_base = EC_LPC_ADDR_MEMMAP;
+
+ driver_data = platform_get_drvdata(pdev);
++ if (!driver_data)
++ driver_data = acpi_device_get_match_data(dev);
++
+ if (driver_data) {
+ quirks = driver_data->quirks;
+
+@@ -625,12 +629,6 @@ static void cros_ec_lpc_remove(struct platform_device *pdev)
+ cros_ec_unregister(ec_dev);
+ }
+
+-static const struct acpi_device_id cros_ec_lpc_acpi_device_ids[] = {
+- { ACPI_DRV_NAME, 0 },
+- { }
+-};
+-MODULE_DEVICE_TABLE(acpi, cros_ec_lpc_acpi_device_ids);
+-
+ static const struct lpc_driver_data framework_laptop_npcx_lpc_driver_data __initconst = {
+ .quirks = CROS_EC_LPC_QUIRK_REMAP_MEMORY,
+ .quirk_mmio_memory_base = 0xE00,
+@@ -642,6 +640,13 @@ static const struct lpc_driver_data framework_laptop_mec_lpc_driver_data __initc
+ .quirk_aml_mutex_name = "ECMT",
+ };
+
++static const struct acpi_device_id cros_ec_lpc_acpi_device_ids[] = {
++ { ACPI_DRV_NAME, 0 },
++ { FRMW_ACPI_DRV_NAME, (kernel_ulong_t)&framework_laptop_npcx_lpc_driver_data },
++ { }
++};
++MODULE_DEVICE_TABLE(acpi, cros_ec_lpc_acpi_device_ids);
++
+ static const struct dmi_system_id cros_ec_lpc_dmi_table[] __initconst = {
+ {
+ /*
+@@ -795,7 +800,8 @@ static int __init cros_ec_lpc_init(void)
+ int ret;
+ const struct dmi_system_id *dmi_match;
+
+- cros_ec_lpc_acpi_device_found = !!cros_ec_lpc_get_device(ACPI_DRV_NAME);
++ cros_ec_lpc_acpi_device_found = !!cros_ec_lpc_get_device(ACPI_DRV_NAME) ||
++ !!cros_ec_lpc_get_device(FRMW_ACPI_DRV_NAME);
+
+ dmi_match = dmi_first_match(cros_ec_lpc_dmi_table);
+
+--
+2.39.5
+
--- /dev/null
+From aaec21d95901ab59dd82378cf2afc8f1776e4993 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Mar 2025 13:50:52 +0100
+Subject: platform/x86: x86-android-tablets: Add select POWER_SUPPLY to Kconfig
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 2c30357e755b087217c7643fda2b8aea6d6deda4 ]
+
+Commit c78dd25138d1 ("platform/x86: x86-android-tablets: Add Vexia EDU
+ATLA 10 EC battery driver"), adds power_supply class registering to
+the x86-android-tablets code.
+
+Add "select POWER_SUPPLY" to the Kconfig entry to avoid these errors:
+
+ERROR: modpost: "power_supply_get_drvdata" [drivers/platform/x86/x86-android-tablets/vexia_atla10_ec.ko] undefined!
+ERROR: modpost: "power_supply_changed" [drivers/platform/x86/x86-android-tablets/vexia_atla10_ec.ko] undefined!
+ERROR: modpost: "devm_power_supply_register" [drivers/platform/x86/x86-android-tablets/vexia_atla10_ec.ko] undefined!
+
+When POWER_SUPPLY support is not enabled.
+
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202503231159.ga9eWMVO-lkp@intel.com/
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20250324125052.374369-1-hdegoede@redhat.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/x86-android-tablets/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/platform/x86/x86-android-tablets/Kconfig b/drivers/platform/x86/x86-android-tablets/Kconfig
+index 88d9e8f2ff24e..c98dfbdfb9dda 100644
+--- a/drivers/platform/x86/x86-android-tablets/Kconfig
++++ b/drivers/platform/x86/x86-android-tablets/Kconfig
+@@ -8,6 +8,7 @@ config X86_ANDROID_TABLETS
+ depends on I2C && SPI && SERIAL_DEV_BUS && ACPI && EFI && GPIOLIB && PMIC_OPREGION
+ select NEW_LEDS
+ select LEDS_CLASS
++ select POWER_SUPPLY
+ help
+ X86 tablets which ship with Android as (part of) the factory image
+ typically have various problems with their DSDTs. The factory kernels
+--
+2.39.5
+
--- /dev/null
+From 9fc27dda8ab3bc9b4ab60650982c703291a8da58 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Feb 2025 20:27:15 +0800
+Subject: pm: cpupower: bench: Prevent NULL dereference on malloc failure
+
+From: Zhongqiu Han <quic_zhonhan@quicinc.com>
+
+[ Upstream commit 208baa3ec9043a664d9acfb8174b332e6b17fb69 ]
+
+If malloc returns NULL due to low memory, 'config' pointer can be NULL.
+Add a check to prevent NULL dereference.
+
+Link: https://lore.kernel.org/r/20250219122715.3892223-1-quic_zhonhan@quicinc.com
+Signed-off-by: Zhongqiu Han <quic_zhonhan@quicinc.com>
+Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/power/cpupower/bench/parse.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/tools/power/cpupower/bench/parse.c b/tools/power/cpupower/bench/parse.c
+index e63dc11fa3a53..48e25be6e1635 100644
+--- a/tools/power/cpupower/bench/parse.c
++++ b/tools/power/cpupower/bench/parse.c
+@@ -120,6 +120,10 @@ FILE *prepare_output(const char *dirname)
+ struct config *prepare_default_config()
+ {
+ struct config *config = malloc(sizeof(struct config));
++ if (!config) {
++ perror("malloc");
++ return NULL;
++ }
+
+ dprintf("loading defaults\n");
+
+--
+2.39.5
+
--- /dev/null
+From 647efc3a79a7b4e852a1ffb1d45eac33d83fa081 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 09:31:39 +0800
+Subject: PM: hibernate: Avoid deadlock in hibernate_compressor_param_set()
+
+From: Lizhi Xu <lizhi.xu@windriver.com>
+
+[ Upstream commit 52323ed1444ea5c2a5f1754ea0a2d9c8c216ccdf ]
+
+syzbot reported a deadlock in lock_system_sleep() (see below).
+
+The write operation to "/sys/module/hibernate/parameters/compressor"
+conflicts with the registration of ieee80211 device, resulting in a deadlock
+when attempting to acquire system_transition_mutex under param_lock.
+
+To avoid this deadlock, change hibernate_compressor_param_set() to use
+mutex_trylock() for attempting to acquire system_transition_mutex and
+return -EBUSY when it fails.
+
+Task flags need not be saved or adjusted before calling
+mutex_trylock(&system_transition_mutex) because the caller is not going
+to end up waiting for this mutex and if it runs concurrently with system
+suspend in progress, it will be frozen properly when it returns to user
+space.
+
+syzbot report:
+
+syz-executor895/5833 is trying to acquire lock:
+ffffffff8e0828c8 (system_transition_mutex){+.+.}-{4:4}, at: lock_system_sleep+0x87/0xa0 kernel/power/main.c:56
+
+but task is already holding lock:
+ffffffff8e07dc68 (param_lock){+.+.}-{4:4}, at: kernel_param_lock kernel/params.c:607 [inline]
+ffffffff8e07dc68 (param_lock){+.+.}-{4:4}, at: param_attr_store+0xe6/0x300 kernel/params.c:586
+
+which lock already depends on the new lock.
+
+the existing dependency chain (in reverse order) is:
+
+-> #3 (param_lock){+.+.}-{4:4}:
+ __mutex_lock_common kernel/locking/mutex.c:585 [inline]
+ __mutex_lock+0x19b/0xb10 kernel/locking/mutex.c:730
+ ieee80211_rate_control_ops_get net/mac80211/rate.c:220 [inline]
+ rate_control_alloc net/mac80211/rate.c:266 [inline]
+ ieee80211_init_rate_ctrl_alg+0x18d/0x6b0 net/mac80211/rate.c:1015
+ ieee80211_register_hw+0x20cd/0x4060 net/mac80211/main.c:1531
+ mac80211_hwsim_new_radio+0x304e/0x54e0 drivers/net/wireless/virtual/mac80211_hwsim.c:5558
+ init_mac80211_hwsim+0x432/0x8c0 drivers/net/wireless/virtual/mac80211_hwsim.c:6910
+ do_one_initcall+0x128/0x700 init/main.c:1257
+ do_initcall_level init/main.c:1319 [inline]
+ do_initcalls init/main.c:1335 [inline]
+ do_basic_setup init/main.c:1354 [inline]
+ kernel_init_freeable+0x5c7/0x900 init/main.c:1568
+ kernel_init+0x1c/0x2b0 init/main.c:1457
+ ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:148
+ ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
+
+-> #2 (rtnl_mutex){+.+.}-{4:4}:
+ __mutex_lock_common kernel/locking/mutex.c:585 [inline]
+ __mutex_lock+0x19b/0xb10 kernel/locking/mutex.c:730
+ wg_pm_notification drivers/net/wireguard/device.c:80 [inline]
+ wg_pm_notification+0x49/0x180 drivers/net/wireguard/device.c:64
+ notifier_call_chain+0xb7/0x410 kernel/notifier.c:85
+ notifier_call_chain_robust kernel/notifier.c:120 [inline]
+ blocking_notifier_call_chain_robust kernel/notifier.c:345 [inline]
+ blocking_notifier_call_chain_robust+0xc9/0x170 kernel/notifier.c:333
+ pm_notifier_call_chain_robust+0x27/0x60 kernel/power/main.c:102
+ snapshot_open+0x189/0x2b0 kernel/power/user.c:77
+ misc_open+0x35a/0x420 drivers/char/misc.c:179
+ chrdev_open+0x237/0x6a0 fs/char_dev.c:414
+ do_dentry_open+0x735/0x1c40 fs/open.c:956
+ vfs_open+0x82/0x3f0 fs/open.c:1086
+ do_open fs/namei.c:3830 [inline]
+ path_openat+0x1e88/0x2d80 fs/namei.c:3989
+ do_filp_open+0x20c/0x470 fs/namei.c:4016
+ do_sys_openat2+0x17a/0x1e0 fs/open.c:1428
+ do_sys_open fs/open.c:1443 [inline]
+ __do_sys_openat fs/open.c:1459 [inline]
+ __se_sys_openat fs/open.c:1454 [inline]
+ __x64_sys_openat+0x175/0x210 fs/open.c:1454
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xcd/0x250 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+-> #1 ((pm_chain_head).rwsem){++++}-{4:4}:
+ down_read+0x9a/0x330 kernel/locking/rwsem.c:1524
+ blocking_notifier_call_chain_robust kernel/notifier.c:344 [inline]
+ blocking_notifier_call_chain_robust+0xa9/0x170 kernel/notifier.c:333
+ pm_notifier_call_chain_robust+0x27/0x60 kernel/power/main.c:102
+ snapshot_open+0x189/0x2b0 kernel/power/user.c:77
+ misc_open+0x35a/0x420 drivers/char/misc.c:179
+ chrdev_open+0x237/0x6a0 fs/char_dev.c:414
+ do_dentry_open+0x735/0x1c40 fs/open.c:956
+ vfs_open+0x82/0x3f0 fs/open.c:1086
+ do_open fs/namei.c:3830 [inline]
+ path_openat+0x1e88/0x2d80 fs/namei.c:3989
+ do_filp_open+0x20c/0x470 fs/namei.c:4016
+ do_sys_openat2+0x17a/0x1e0 fs/open.c:1428
+ do_sys_open fs/open.c:1443 [inline]
+ __do_sys_openat fs/open.c:1459 [inline]
+ __se_sys_openat fs/open.c:1454 [inline]
+ __x64_sys_openat+0x175/0x210 fs/open.c:1454
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xcd/0x250 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+-> #0 (system_transition_mutex){+.+.}-{4:4}:
+ check_prev_add kernel/locking/lockdep.c:3163 [inline]
+ check_prevs_add kernel/locking/lockdep.c:3282 [inline]
+ validate_chain kernel/locking/lockdep.c:3906 [inline]
+ __lock_acquire+0x249e/0x3c40 kernel/locking/lockdep.c:5228
+ lock_acquire.part.0+0x11b/0x380 kernel/locking/lockdep.c:5851
+ __mutex_lock_common kernel/locking/mutex.c:585 [inline]
+ __mutex_lock+0x19b/0xb10 kernel/locking/mutex.c:730
+ lock_system_sleep+0x87/0xa0 kernel/power/main.c:56
+ hibernate_compressor_param_set+0x1c/0x210 kernel/power/hibernate.c:1452
+ param_attr_store+0x18f/0x300 kernel/params.c:588
+ module_attr_store+0x55/0x80 kernel/params.c:924
+ sysfs_kf_write+0x117/0x170 fs/sysfs/file.c:139
+ kernfs_fop_write_iter+0x33d/0x500 fs/kernfs/file.c:334
+ new_sync_write fs/read_write.c:586 [inline]
+ vfs_write+0x5ae/0x1150 fs/read_write.c:679
+ ksys_write+0x12b/0x250 fs/read_write.c:731
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xcd/0x250 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+other info that might help us debug this:
+
+Chain exists of:
+ system_transition_mutex --> rtnl_mutex --> param_lock
+
+ Possible unsafe locking scenario:
+
+ CPU0 CPU1
+ ---- ----
+ lock(param_lock);
+ lock(rtnl_mutex);
+ lock(param_lock);
+ lock(system_transition_mutex);
+
+ *** DEADLOCK ***
+
+Reported-by: syzbot+ace60642828c074eb913@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=ace60642828c074eb913
+Signed-off-by: Lizhi Xu <lizhi.xu@windriver.com>
+Link: https://patch.msgid.link/20250224013139.3994500-1-lizhi.xu@windriver.com
+[ rjw: New subject matching the code changes, changelog edits ]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/power/hibernate.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
+index b483fcea811b1..d8bad1eeedd3e 100644
+--- a/kernel/power/hibernate.c
++++ b/kernel/power/hibernate.c
+@@ -1443,10 +1443,10 @@ static const char * const comp_alg_enabled[] = {
+ static int hibernate_compressor_param_set(const char *compressor,
+ const struct kernel_param *kp)
+ {
+- unsigned int sleep_flags;
+ int index, ret;
+
+- sleep_flags = lock_system_sleep();
++ if (!mutex_trylock(&system_transition_mutex))
++ return -EBUSY;
+
+ index = sysfs_match_string(comp_alg_enabled, compressor);
+ if (index >= 0) {
+@@ -1458,7 +1458,7 @@ static int hibernate_compressor_param_set(const char *compressor,
+ ret = index;
+ }
+
+- unlock_system_sleep(sleep_flags);
++ mutex_unlock(&system_transition_mutex);
+
+ if (ret)
+ pr_debug("Cannot set specified compressor %s\n",
+--
+2.39.5
+
--- /dev/null
+From d6a1d291bbc12151d38e4377e54a7ecfd82c2c66 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Mar 2025 19:07:12 +0800
+Subject: Revert "f2fs: rebuild nat_bits during umount"
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 19426c4988aa85298c1b4caf2889d37ec5c80fea ]
+
+This reverts commit 94c821fb286b545d37549ff30a0c341e066f0d6c.
+
+It reports that there is potential corruption in node footer,
+the most suspious feature is nat_bits, let's revert recovery
+related code.
+
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/checkpoint.c | 21 +++------
+ fs/f2fs/f2fs.h | 32 +++++++++++++-
+ fs/f2fs/node.c | 101 ++++++++++---------------------------------
+ 3 files changed, 59 insertions(+), 95 deletions(-)
+
+diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
+index efda9a0229816..86228f82f54d0 100644
+--- a/fs/f2fs/checkpoint.c
++++ b/fs/f2fs/checkpoint.c
+@@ -1344,21 +1344,13 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc)
+ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+ unsigned long flags;
+
+- if (cpc->reason & CP_UMOUNT) {
+- if (le32_to_cpu(ckpt->cp_pack_total_block_count) +
+- NM_I(sbi)->nat_bits_blocks > BLKS_PER_SEG(sbi)) {
+- clear_ckpt_flags(sbi, CP_NAT_BITS_FLAG);
+- f2fs_notice(sbi, "Disable nat_bits due to no space");
+- } else if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG) &&
+- f2fs_nat_bitmap_enabled(sbi)) {
+- f2fs_enable_nat_bits(sbi);
+- set_ckpt_flags(sbi, CP_NAT_BITS_FLAG);
+- f2fs_notice(sbi, "Rebuild and enable nat_bits");
+- }
+- }
+-
+ spin_lock_irqsave(&sbi->cp_lock, flags);
+
++ if ((cpc->reason & CP_UMOUNT) &&
++ le32_to_cpu(ckpt->cp_pack_total_block_count) >
++ sbi->blocks_per_seg - NM_I(sbi)->nat_bits_blocks)
++ disable_nat_bits(sbi, false);
++
+ if (cpc->reason & CP_TRIMMED)
+ __set_ckpt_flags(ckpt, CP_TRIMMED_FLAG);
+ else
+@@ -1541,8 +1533,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
+ start_blk = __start_cp_next_addr(sbi);
+
+ /* write nat bits */
+- if ((cpc->reason & CP_UMOUNT) &&
+- is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG)) {
++ if (enabled_nat_bits(sbi, cpc)) {
+ __u64 cp_ver = cur_cp_version(ckpt);
+ block_t blk;
+
+diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
+index b52df8aa95350..1c783c2e4902a 100644
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -2231,6 +2231,36 @@ static inline void f2fs_up_write(struct f2fs_rwsem *sem)
+ #endif
+ }
+
++static inline void disable_nat_bits(struct f2fs_sb_info *sbi, bool lock)
++{
++ unsigned long flags;
++ unsigned char *nat_bits;
++
++ /*
++ * In order to re-enable nat_bits we need to call fsck.f2fs by
++ * set_sbi_flag(sbi, SBI_NEED_FSCK). But it may give huge cost,
++ * so let's rely on regular fsck or unclean shutdown.
++ */
++
++ if (lock)
++ spin_lock_irqsave(&sbi->cp_lock, flags);
++ __clear_ckpt_flags(F2FS_CKPT(sbi), CP_NAT_BITS_FLAG);
++ nat_bits = NM_I(sbi)->nat_bits;
++ NM_I(sbi)->nat_bits = NULL;
++ if (lock)
++ spin_unlock_irqrestore(&sbi->cp_lock, flags);
++
++ kvfree(nat_bits);
++}
++
++static inline bool enabled_nat_bits(struct f2fs_sb_info *sbi,
++ struct cp_control *cpc)
++{
++ bool set = is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG);
++
++ return (cpc) ? (cpc->reason & CP_UMOUNT) && set : set;
++}
++
+ static inline void f2fs_lock_op(struct f2fs_sb_info *sbi)
+ {
+ f2fs_down_read(&sbi->cp_rwsem);
+@@ -3671,7 +3701,6 @@ int f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from);
+ int f2fs_truncate_xattr_node(struct inode *inode);
+ int f2fs_wait_on_node_pages_writeback(struct f2fs_sb_info *sbi,
+ unsigned int seq_id);
+-bool f2fs_nat_bitmap_enabled(struct f2fs_sb_info *sbi);
+ int f2fs_remove_inode_page(struct inode *inode);
+ struct page *f2fs_new_inode_page(struct inode *inode);
+ struct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs);
+@@ -3696,7 +3725,6 @@ int f2fs_recover_xattr_data(struct inode *inode, struct page *page);
+ int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct page *page);
+ int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
+ unsigned int segno, struct f2fs_summary_block *sum);
+-void f2fs_enable_nat_bits(struct f2fs_sb_info *sbi);
+ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc);
+ int f2fs_build_node_manager(struct f2fs_sb_info *sbi);
+ void f2fs_destroy_node_manager(struct f2fs_sb_info *sbi);
+diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
+index 9fc07737d8661..12c76e3d1cd49 100644
+--- a/fs/f2fs/node.c
++++ b/fs/f2fs/node.c
+@@ -2277,24 +2277,6 @@ static void __move_free_nid(struct f2fs_sb_info *sbi, struct free_nid *i,
+ }
+ }
+
+-bool f2fs_nat_bitmap_enabled(struct f2fs_sb_info *sbi)
+-{
+- struct f2fs_nm_info *nm_i = NM_I(sbi);
+- unsigned int i;
+- bool ret = true;
+-
+- f2fs_down_read(&nm_i->nat_tree_lock);
+- for (i = 0; i < nm_i->nat_blocks; i++) {
+- if (!test_bit_le(i, nm_i->nat_block_bitmap)) {
+- ret = false;
+- break;
+- }
+- }
+- f2fs_up_read(&nm_i->nat_tree_lock);
+-
+- return ret;
+-}
+-
+ static void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid,
+ bool set, bool build)
+ {
+@@ -2973,23 +2955,7 @@ static void __adjust_nat_entry_set(struct nat_entry_set *nes,
+ list_add_tail(&nes->set_list, head);
+ }
+
+-static void __update_nat_bits(struct f2fs_nm_info *nm_i, unsigned int nat_ofs,
+- unsigned int valid)
+-{
+- if (valid == 0) {
+- __set_bit_le(nat_ofs, nm_i->empty_nat_bits);
+- __clear_bit_le(nat_ofs, nm_i->full_nat_bits);
+- return;
+- }
+-
+- __clear_bit_le(nat_ofs, nm_i->empty_nat_bits);
+- if (valid == NAT_ENTRY_PER_BLOCK)
+- __set_bit_le(nat_ofs, nm_i->full_nat_bits);
+- else
+- __clear_bit_le(nat_ofs, nm_i->full_nat_bits);
+-}
+-
+-static void update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
++static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
+ struct page *page)
+ {
+ struct f2fs_nm_info *nm_i = NM_I(sbi);
+@@ -2998,7 +2964,7 @@ static void update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
+ int valid = 0;
+ int i = 0;
+
+- if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG))
++ if (!enabled_nat_bits(sbi, NULL))
+ return;
+
+ if (nat_index == 0) {
+@@ -3009,36 +2975,17 @@ static void update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
+ if (le32_to_cpu(nat_blk->entries[i].block_addr) != NULL_ADDR)
+ valid++;
+ }
+-
+- __update_nat_bits(nm_i, nat_index, valid);
+-}
+-
+-void f2fs_enable_nat_bits(struct f2fs_sb_info *sbi)
+-{
+- struct f2fs_nm_info *nm_i = NM_I(sbi);
+- unsigned int nat_ofs;
+-
+- f2fs_down_read(&nm_i->nat_tree_lock);
+-
+- for (nat_ofs = 0; nat_ofs < nm_i->nat_blocks; nat_ofs++) {
+- unsigned int valid = 0, nid_ofs = 0;
+-
+- /* handle nid zero due to it should never be used */
+- if (unlikely(nat_ofs == 0)) {
+- valid = 1;
+- nid_ofs = 1;
+- }
+-
+- for (; nid_ofs < NAT_ENTRY_PER_BLOCK; nid_ofs++) {
+- if (!test_bit_le(nid_ofs,
+- nm_i->free_nid_bitmap[nat_ofs]))
+- valid++;
+- }
+-
+- __update_nat_bits(nm_i, nat_ofs, valid);
++ if (valid == 0) {
++ __set_bit_le(nat_index, nm_i->empty_nat_bits);
++ __clear_bit_le(nat_index, nm_i->full_nat_bits);
++ return;
+ }
+
+- f2fs_up_read(&nm_i->nat_tree_lock);
++ __clear_bit_le(nat_index, nm_i->empty_nat_bits);
++ if (valid == NAT_ENTRY_PER_BLOCK)
++ __set_bit_le(nat_index, nm_i->full_nat_bits);
++ else
++ __clear_bit_le(nat_index, nm_i->full_nat_bits);
+ }
+
+ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
+@@ -3057,7 +3004,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
+ * #1, flush nat entries to journal in current hot data summary block.
+ * #2, flush nat entries to nat page.
+ */
+- if ((cpc->reason & CP_UMOUNT) ||
++ if (enabled_nat_bits(sbi, cpc) ||
+ !__has_cursum_space(journal, set->entry_cnt, NAT_JOURNAL))
+ to_journal = false;
+
+@@ -3104,7 +3051,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
+ if (to_journal) {
+ up_write(&curseg->journal_rwsem);
+ } else {
+- update_nat_bits(sbi, start_nid, page);
++ __update_nat_bits(sbi, start_nid, page);
+ f2fs_put_page(page, 1);
+ }
+
+@@ -3135,7 +3082,7 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
+ * during unmount, let's flush nat_bits before checking
+ * nat_cnt[DIRTY_NAT].
+ */
+- if (cpc->reason & CP_UMOUNT) {
++ if (enabled_nat_bits(sbi, cpc)) {
+ f2fs_down_write(&nm_i->nat_tree_lock);
+ remove_nats_in_journal(sbi);
+ f2fs_up_write(&nm_i->nat_tree_lock);
+@@ -3151,7 +3098,7 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
+ * entries, remove all entries from journal and merge them
+ * into nat entry set.
+ */
+- if (cpc->reason & CP_UMOUNT ||
++ if (enabled_nat_bits(sbi, cpc) ||
+ !__has_cursum_space(journal,
+ nm_i->nat_cnt[DIRTY_NAT], NAT_JOURNAL))
+ remove_nats_in_journal(sbi);
+@@ -3188,18 +3135,15 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
+ __u64 cp_ver = cur_cp_version(ckpt);
+ block_t nat_bits_addr;
+
++ if (!enabled_nat_bits(sbi, NULL))
++ return 0;
++
+ nm_i->nat_bits_blocks = F2FS_BLK_ALIGN((nat_bits_bytes << 1) + 8);
+ nm_i->nat_bits = f2fs_kvzalloc(sbi,
+ F2FS_BLK_TO_BYTES(nm_i->nat_bits_blocks), GFP_KERNEL);
+ if (!nm_i->nat_bits)
+ return -ENOMEM;
+
+- nm_i->full_nat_bits = nm_i->nat_bits + 8;
+- nm_i->empty_nat_bits = nm_i->full_nat_bits + nat_bits_bytes;
+-
+- if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG))
+- return 0;
+-
+ nat_bits_addr = __start_cp_addr(sbi) + BLKS_PER_SEG(sbi) -
+ nm_i->nat_bits_blocks;
+ for (i = 0; i < nm_i->nat_bits_blocks; i++) {
+@@ -3216,12 +3160,13 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
+
+ cp_ver |= (cur_cp_crc(ckpt) << 32);
+ if (cpu_to_le64(cp_ver) != *(__le64 *)nm_i->nat_bits) {
+- clear_ckpt_flags(sbi, CP_NAT_BITS_FLAG);
+- f2fs_notice(sbi, "Disable nat_bits due to incorrect cp_ver (%llu, %llu)",
+- cp_ver, le64_to_cpu(*(__le64 *)nm_i->nat_bits));
++ disable_nat_bits(sbi, true);
+ return 0;
+ }
+
++ nm_i->full_nat_bits = nm_i->nat_bits + 8;
++ nm_i->empty_nat_bits = nm_i->full_nat_bits + nat_bits_bytes;
++
+ f2fs_notice(sbi, "Found nat_bits in checkpoint");
+ return 0;
+ }
+@@ -3232,7 +3177,7 @@ static inline void load_free_nid_bitmap(struct f2fs_sb_info *sbi)
+ unsigned int i = 0;
+ nid_t nid, last_nid;
+
+- if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG))
++ if (!enabled_nat_bits(sbi, NULL))
+ return;
+
+ for (i = 0; i < nm_i->nat_blocks; i++) {
+--
+2.39.5
+
--- /dev/null
+From 11ada5bbdf418c4184fa59f1c8c3b23c3b3d34a2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jan 2025 15:38:47 +0530
+Subject: scsi: mpi3mr: Avoid reply queue full condition
+
+From: Ranjan Kumar <ranjan.kumar@broadcom.com>
+
+[ Upstream commit f08b24d82749117ce779cc66689e8594341130d3 ]
+
+To avoid reply queue full condition, update the driver to check IOCFacts
+capabilities for qfull.
+
+Update the operational reply queue's Consumer Index after processing 100
+replies. If pending I/Os on a reply queue exceeds a threshold
+(reply_queue_depth - 200), then return I/O back to OS to retry.
+
+Also increase default admin reply queue size to 2K.
+
+Signed-off-by: Sumit Saxena <sumit.saxena@broadcom.com>
+Signed-off-by: Ranjan Kumar <ranjan.kumar@broadcom.com>
+Link: https://lore.kernel.org/r/20250129100850.25430-2-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.h | 12 +++++++++++-
+ drivers/scsi/mpi3mr/mpi3mr_app.c | 24 ++++++++++++++++++++++++
+ drivers/scsi/mpi3mr/mpi3mr_fw.c | 32 ++++++++++++++++++++++++++++----
+ 3 files changed, 63 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h
+index 1e715fd65a7d4..1b049cea98e1f 100644
+--- a/drivers/scsi/mpi3mr/mpi3mr.h
++++ b/drivers/scsi/mpi3mr/mpi3mr.h
+@@ -81,13 +81,14 @@ extern atomic64_t event_counter;
+
+ /* Admin queue management definitions */
+ #define MPI3MR_ADMIN_REQ_Q_SIZE (2 * MPI3MR_PAGE_SIZE_4K)
+-#define MPI3MR_ADMIN_REPLY_Q_SIZE (4 * MPI3MR_PAGE_SIZE_4K)
++#define MPI3MR_ADMIN_REPLY_Q_SIZE (8 * MPI3MR_PAGE_SIZE_4K)
+ #define MPI3MR_ADMIN_REQ_FRAME_SZ 128
+ #define MPI3MR_ADMIN_REPLY_FRAME_SZ 16
+
+ /* Operational queue management definitions */
+ #define MPI3MR_OP_REQ_Q_QD 512
+ #define MPI3MR_OP_REP_Q_QD 1024
++#define MPI3MR_OP_REP_Q_QD2K 2048
+ #define MPI3MR_OP_REP_Q_QD4K 4096
+ #define MPI3MR_OP_REQ_Q_SEG_SIZE 4096
+ #define MPI3MR_OP_REP_Q_SEG_SIZE 4096
+@@ -329,6 +330,7 @@ enum mpi3mr_reset_reason {
+ #define MPI3MR_RESET_REASON_OSTYPE_SHIFT 28
+ #define MPI3MR_RESET_REASON_IOCNUM_SHIFT 20
+
++
+ /* Queue type definitions */
+ enum queue_type {
+ MPI3MR_DEFAULT_QUEUE = 0,
+@@ -388,6 +390,7 @@ struct mpi3mr_ioc_facts {
+ u16 max_msix_vectors;
+ u8 personality;
+ u8 dma_mask;
++ bool max_req_limit;
+ u8 protocol_flags;
+ u8 sge_mod_mask;
+ u8 sge_mod_value;
+@@ -457,6 +460,8 @@ struct op_req_qinfo {
+ * @enable_irq_poll: Flag to indicate polling is enabled
+ * @in_use: Queue is handled by poll/ISR
+ * @qtype: Type of queue (types defined in enum queue_type)
++ * @qfull_watermark: Watermark defined in reply queue to avoid
++ * reply queue full
+ */
+ struct op_reply_qinfo {
+ u16 ci;
+@@ -472,6 +477,7 @@ struct op_reply_qinfo {
+ bool enable_irq_poll;
+ atomic_t in_use;
+ enum queue_type qtype;
++ u16 qfull_watermark;
+ };
+
+ /**
+@@ -1154,6 +1160,8 @@ struct scmd_priv {
+ * @snapdump_trigger_active: Snapdump trigger active flag
+ * @pci_err_recovery: PCI error recovery in progress
+ * @block_on_pci_err: Block IO during PCI error recovery
++ * @reply_qfull_count: Occurences of reply queue full avoidance kicking-in
++ * @prevent_reply_qfull: Enable reply queue prevention
+ */
+ struct mpi3mr_ioc {
+ struct list_head list;
+@@ -1352,6 +1360,8 @@ struct mpi3mr_ioc {
+ bool fw_release_trigger_active;
+ bool pci_err_recovery;
+ bool block_on_pci_err;
++ atomic_t reply_qfull_count;
++ bool prevent_reply_qfull;
+ };
+
+ /**
+diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c
+index 7589f48aebc80..1532436f0f3af 100644
+--- a/drivers/scsi/mpi3mr/mpi3mr_app.c
++++ b/drivers/scsi/mpi3mr/mpi3mr_app.c
+@@ -3060,6 +3060,29 @@ reply_queue_count_show(struct device *dev, struct device_attribute *attr,
+
+ static DEVICE_ATTR_RO(reply_queue_count);
+
++/**
++ * reply_qfull_count_show - Show reply qfull count
++ * @dev: class device
++ * @attr: Device attributes
++ * @buf: Buffer to copy
++ *
++ * Retrieves the current value of the reply_qfull_count from the mrioc structure and
++ * formats it as a string for display.
++ *
++ * Return: sysfs_emit() return
++ */
++static ssize_t
++reply_qfull_count_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct mpi3mr_ioc *mrioc = shost_priv(shost);
++
++ return sysfs_emit(buf, "%u\n", atomic_read(&mrioc->reply_qfull_count));
++}
++
++static DEVICE_ATTR_RO(reply_qfull_count);
++
+ /**
+ * logging_level_show - Show controller debug level
+ * @dev: class device
+@@ -3152,6 +3175,7 @@ static struct attribute *mpi3mr_host_attrs[] = {
+ &dev_attr_fw_queue_depth.attr,
+ &dev_attr_op_req_q_count.attr,
+ &dev_attr_reply_queue_count.attr,
++ &dev_attr_reply_qfull_count.attr,
+ &dev_attr_logging_level.attr,
+ &dev_attr_adp_state.attr,
+ NULL,
+diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c
+index 5ed31fe57474a..656108dd2ee30 100644
+--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c
++++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c
+@@ -2104,15 +2104,22 @@ static int mpi3mr_create_op_reply_q(struct mpi3mr_ioc *mrioc, u16 qidx)
+ }
+
+ reply_qid = qidx + 1;
+- op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD;
+- if ((mrioc->pdev->device == MPI3_MFGPAGE_DEVID_SAS4116) &&
+- !mrioc->pdev->revision)
+- op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD4K;
++
++ if (mrioc->pdev->device == MPI3_MFGPAGE_DEVID_SAS4116) {
++ if (mrioc->pdev->revision)
++ op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD;
++ else
++ op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD4K;
++ } else
++ op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD2K;
++
+ op_reply_q->ci = 0;
+ op_reply_q->ephase = 1;
+ atomic_set(&op_reply_q->pend_ios, 0);
+ atomic_set(&op_reply_q->in_use, 0);
+ op_reply_q->enable_irq_poll = false;
++ op_reply_q->qfull_watermark =
++ op_reply_q->num_replies - (MPI3MR_THRESHOLD_REPLY_COUNT * 2);
+
+ if (!op_reply_q->q_segments) {
+ retval = mpi3mr_alloc_op_reply_q_segments(mrioc, qidx);
+@@ -2416,8 +2423,10 @@ int mpi3mr_op_request_post(struct mpi3mr_ioc *mrioc,
+ void *segment_base_addr;
+ u16 req_sz = mrioc->facts.op_req_sz;
+ struct segments *segments = op_req_q->q_segments;
++ struct op_reply_qinfo *op_reply_q = NULL;
+
+ reply_qidx = op_req_q->reply_qid - 1;
++ op_reply_q = mrioc->op_reply_qinfo + reply_qidx;
+
+ if (mrioc->unrecoverable)
+ return -EFAULT;
+@@ -2448,6 +2457,15 @@ int mpi3mr_op_request_post(struct mpi3mr_ioc *mrioc,
+ goto out;
+ }
+
++ /* Reply queue is nearing to get full, push back IOs to SML */
++ if ((mrioc->prevent_reply_qfull == true) &&
++ (atomic_read(&op_reply_q->pend_ios) >
++ (op_reply_q->qfull_watermark))) {
++ atomic_inc(&mrioc->reply_qfull_count);
++ retval = -EAGAIN;
++ goto out;
++ }
++
+ segment_base_addr = segments[pi / op_req_q->segment_qd].segment;
+ req_entry = (u8 *)segment_base_addr +
+ ((pi % op_req_q->segment_qd) * req_sz);
+@@ -3091,6 +3109,9 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc,
+ mrioc->facts.dma_mask = (facts_flags &
+ MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK) >>
+ MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT;
++ mrioc->facts.dma_mask = (facts_flags &
++ MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK) >>
++ MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT;
+ mrioc->facts.protocol_flags = facts_data->protocol_flags;
+ mrioc->facts.mpi_version = le32_to_cpu(facts_data->mpi_version.word);
+ mrioc->facts.max_reqs = le16_to_cpu(facts_data->max_outstanding_requests);
+@@ -4214,6 +4235,9 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc)
+ mrioc->shost->transportt = mpi3mr_transport_template;
+ }
+
++ if (mrioc->facts.max_req_limit)
++ mrioc->prevent_reply_qfull = true;
++
+ mrioc->reply_sz = mrioc->facts.reply_sz;
+
+ retval = mpi3mr_check_reset_dma_mask(mrioc);
+--
+2.39.5
+
--- /dev/null
+From cbb3b9c0dbe36bf29aa10ea0dae25f27a4bfcb38 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jan 2025 15:38:49 +0530
+Subject: scsi: mpi3mr: Synchronous access b/w reset and tm thread for reply
+ queue
+
+From: Ranjan Kumar <ranjan.kumar@broadcom.com>
+
+[ Upstream commit f195fc060c738d303a21fae146dbf85e1595fb4c ]
+
+When the task management thread processes reply queues while the reset
+thread resets them, the task management thread accesses an invalid queue ID
+(0xFFFF), set by the reset thread, which points to unallocated memory,
+causing a crash.
+
+Add flag 'io_admin_reset_sync' to synchronize access between the reset,
+I/O, and admin threads. Before a reset, the reset handler sets this flag to
+block I/O and admin processing threads. If any thread bypasses the initial
+check, the reset thread waits up to 10 seconds for processing to finish. If
+the wait exceeds 10 seconds, the controller is marked as unrecoverable.
+
+Signed-off-by: Sumit Saxena <sumit.saxena@broadcom.com>
+Signed-off-by: Ranjan Kumar <ranjan.kumar@broadcom.com>
+Link: https://lore.kernel.org/r/20250129100850.25430-4-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.h | 2 +
+ drivers/scsi/mpi3mr/mpi3mr_fw.c | 67 +++++++++++++++++++++++++++++++--
+ 2 files changed, 66 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h
+index 1b049cea98e1f..ee5a75a4b3bb8 100644
+--- a/drivers/scsi/mpi3mr/mpi3mr.h
++++ b/drivers/scsi/mpi3mr/mpi3mr.h
+@@ -1097,6 +1097,7 @@ struct scmd_priv {
+ * @ts_update_interval: Timestamp update interval
+ * @reset_in_progress: Reset in progress flag
+ * @unrecoverable: Controller unrecoverable flag
++ * @io_admin_reset_sync: Manage state of I/O ops during an admin reset process
+ * @prev_reset_result: Result of previous reset
+ * @reset_mutex: Controller reset mutex
+ * @reset_waitq: Controller reset wait queue
+@@ -1285,6 +1286,7 @@ struct mpi3mr_ioc {
+ u16 ts_update_interval;
+ u8 reset_in_progress;
+ u8 unrecoverable;
++ u8 io_admin_reset_sync;
+ int prev_reset_result;
+ struct mutex reset_mutex;
+ wait_queue_head_t reset_waitq;
+diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c
+index 656108dd2ee30..ec5b1ab287177 100644
+--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c
++++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c
+@@ -17,7 +17,7 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc,
+ struct mpi3_ioc_facts_data *facts_data);
+ static void mpi3mr_pel_wait_complete(struct mpi3mr_ioc *mrioc,
+ struct mpi3mr_drv_cmd *drv_cmd);
+-
++static int mpi3mr_check_op_admin_proc(struct mpi3mr_ioc *mrioc);
+ static int poll_queues;
+ module_param(poll_queues, int, 0444);
+ MODULE_PARM_DESC(poll_queues, "Number of queues for io_uring poll mode. (Range 1 - 126)");
+@@ -459,7 +459,7 @@ int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc)
+ }
+
+ do {
+- if (mrioc->unrecoverable)
++ if (mrioc->unrecoverable || mrioc->io_admin_reset_sync)
+ break;
+
+ mrioc->admin_req_ci = le16_to_cpu(reply_desc->request_queue_ci);
+@@ -554,7 +554,7 @@ int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc,
+ }
+
+ do {
+- if (mrioc->unrecoverable)
++ if (mrioc->unrecoverable || mrioc->io_admin_reset_sync)
+ break;
+
+ req_q_idx = le16_to_cpu(reply_desc->request_queue_id) - 1;
+@@ -4394,6 +4394,7 @@ int mpi3mr_reinit_ioc(struct mpi3mr_ioc *mrioc, u8 is_resume)
+ goto out_failed_noretry;
+ }
+
++ mrioc->io_admin_reset_sync = 0;
+ if (is_resume || mrioc->block_on_pci_err) {
+ dprint_reset(mrioc, "setting up single ISR\n");
+ retval = mpi3mr_setup_isr(mrioc, 1);
+@@ -5252,6 +5253,55 @@ void mpi3mr_pel_get_seqnum_complete(struct mpi3mr_ioc *mrioc,
+ drv_cmd->retry_count = 0;
+ }
+
++/**
++ * mpi3mr_check_op_admin_proc -
++ * @mrioc: Adapter instance reference
++ *
++ * Check if any of the operation reply queues
++ * or the admin reply queue are currently in use.
++ * If any queue is in use, this function waits for
++ * a maximum of 10 seconds for them to become available.
++ *
++ * Return: 0 on success, non-zero on failure.
++ */
++static int mpi3mr_check_op_admin_proc(struct mpi3mr_ioc *mrioc)
++{
++
++ u16 timeout = 10 * 10;
++ u16 elapsed_time = 0;
++ bool op_admin_in_use = false;
++
++ do {
++ op_admin_in_use = false;
++
++ /* Check admin_reply queue first to exit early */
++ if (atomic_read(&mrioc->admin_reply_q_in_use) == 1)
++ op_admin_in_use = true;
++ else {
++ /* Check op_reply queues */
++ int i;
++
++ for (i = 0; i < mrioc->num_queues; i++) {
++ if (atomic_read(&mrioc->op_reply_qinfo[i].in_use) == 1) {
++ op_admin_in_use = true;
++ break;
++ }
++ }
++ }
++
++ if (!op_admin_in_use)
++ break;
++
++ msleep(100);
++
++ } while (++elapsed_time < timeout);
++
++ if (op_admin_in_use)
++ return 1;
++
++ return 0;
++}
++
+ /**
+ * mpi3mr_soft_reset_handler - Reset the controller
+ * @mrioc: Adapter instance reference
+@@ -5332,6 +5382,7 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
+ mpi3mr_wait_for_host_io(mrioc, MPI3MR_RESET_HOST_IOWAIT_TIMEOUT);
+
+ mpi3mr_ioc_disable_intr(mrioc);
++ mrioc->io_admin_reset_sync = 1;
+
+ if (snapdump) {
+ mpi3mr_set_diagsave(mrioc);
+@@ -5359,6 +5410,16 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
+ ioc_err(mrioc, "Failed to issue soft reset to the ioc\n");
+ goto out;
+ }
++
++ retval = mpi3mr_check_op_admin_proc(mrioc);
++ if (retval) {
++ ioc_err(mrioc, "Soft reset failed due to an Admin or I/O queue polling\n"
++ "thread still processing replies even after a 10 second\n"
++ "timeout. Marking the controller as unrecoverable!\n");
++
++ goto out;
++ }
++
+ if (mrioc->num_io_throttle_group !=
+ mrioc->facts.max_io_throttle_group) {
+ ioc_err(mrioc,
+--
+2.39.5
+
--- /dev/null
+From 9b6573882ad7e4d06f6908f904c872a19d5a6c92 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Mar 2025 13:25:14 +0200
+Subject: scsi: st: Fix array overflow in st_setup()
+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 a018d1cf990d0c339fe0e29b762ea5dc10567d67 ]
+
+Change the array size to follow parms size instead of a fixed value.
+
+Reported-by: Chenyuan Yang <chenyuan0y@gmail.com>
+Closes: https://lore.kernel.org/linux-scsi/CALGdzuoubbra4xKOJcsyThdk5Y1BrAmZs==wbqjbkAgmKS39Aw@mail.gmail.com/
+Signed-off-by: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
+Link: https://lore.kernel.org/r/20250311112516.5548-2-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 | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
+index 0dc37fc6f2367..a17441635ff3a 100644
+--- a/drivers/scsi/st.c
++++ b/drivers/scsi/st.c
+@@ -4119,7 +4119,7 @@ static void validate_options(void)
+ */
+ static int __init st_setup(char *str)
+ {
+- int i, len, ints[5];
++ int i, len, ints[ARRAY_SIZE(parms) + 1];
+ char *stp;
+
+ stp = get_options(str, ARRAY_SIZE(ints), ints);
+--
+2.39.5
+
--- /dev/null
+From 8ca26327d1d08428407f661f0559a77d0b3bcf92 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jan 2025 15:07:39 +0800
+Subject: scsi: target: spc: Fix RSOC parameter data header size
+
+From: Chaohai Chen <wdhh66@163.com>
+
+[ Upstream commit b50532318793d28a7628c1ffc129a2226e83e495 ]
+
+The SPC document states that "The COMMAND DATA LENGTH field indicates the
+length in bytes of the command descriptor list".
+
+The length should be subtracted by 4 to represent the length of the
+description list, not 3.
+
+Signed-off-by: Chaohai Chen <wdhh66@163.com>
+Link: https://lore.kernel.org/r/20250115070739.216154-1-wdhh66@163.com
+Reviewed-by: Dmitry Bogdanov <d.bogdanov@yadro.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 | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
+index ea14a38356814..61c065702350e 100644
+--- a/drivers/target/target_core_spc.c
++++ b/drivers/target/target_core_spc.c
+@@ -2243,7 +2243,7 @@ spc_emulate_report_supp_op_codes(struct se_cmd *cmd)
+ response_length += spc_rsoc_encode_command_descriptor(
+ &buf[response_length], rctd, descr);
+ }
+- put_unaligned_be32(response_length - 3, buf);
++ put_unaligned_be32(response_length - 4, buf);
+ } else {
+ response_length = spc_rsoc_encode_one_command_descriptor(
+ &buf[response_length], rctd, descr,
+--
+2.39.5
+
perf-core-add-aux_pause-aux_resume-aux_start_paused.patch
perf-core-simplify-the-perf_event_alloc-error-path.patch
perf-fix-hang-while-freeing-sigtrap-event.patch
+fs-consistently-deref-the-files-table-with-rcu_deref.patch
+umount-allow-superblock-owners-to-force-umount.patch
+pm-cpupower-bench-prevent-null-dereference-on-malloc.patch
+x86-mm-clear-_page_dirty-for-kernel-mappings-when-we.patch
+x86-percpu-disable-named-address-spaces-for-ubsan_bo.patch
+x86-ia32-leave-null-selector-values-0-3-unchanged.patch
+x86-cpu-don-t-clear-x86_feature_lahf_lm-flag-in-init.patch
+perf-arm_pmu-don-t-disable-counter-in-armpmu_add.patch
+perf-dwc_pcie-fix-some-unreleased-resources.patch
+pm-hibernate-avoid-deadlock-in-hibernate_compressor_.patch
+flush-console-log-from-kernel_power_off.patch
+arm64-cputype-add-qcom_cpu_part_kryo_3xx_gold.patch
+xen-mcelog-add-__nonstring-annotations-for-untermina.patch
+x86-mm-ident_map-fix-theoretical-virtual-address-ove.patch
+zstd-increase-dynamic_bmi2-gcc-version-cutoff-from-4.patch
+platform-chrome-cros_ec_lpc-match-on-framework-acpi-.patch
+asoc-sof-topology-use-krealloc_array-to-replace-krea.patch
+hid-pidff-convert-infinite-length-from-linux-api-to-.patch
+hid-pidff-do-not-send-effect-envelope-if-it-s-empty.patch
+hid-pidff-add-missing_delay-quirk-and-its-detection.patch
+hid-pidff-add-missing_pbo-quirk-and-its-detection.patch
+hid-pidff-add-permissive_control-quirk.patch
+hid-pidff-add-hid_pidff_init_with_quirks-and-export-.patch
+hid-pidff-add-fix_wheel_direction-quirk.patch
+hid-add-hid-universal-pidff-driver-and-supported-dev.patch
+hid-pidff-add-periodic_sine_only-quirk.patch
+hid-pidff-fix-null-pointer-dereference-in-pidff_find.patch
+asoc-amd-ps-use-macro-for-acp6.3-pci-revision-id.patch
+alsa-hda-intel-fix-optimus-when-gpu-has-no-sound.patch
+alsa-hda-intel-add-lenovo-ideapad-z570-to-probe-deny.patch
+asoc-fsl_audmix-register-card-device-depends-on-dais.patch
+media-uvcvideo-add-quirk-for-actions-uvc05.patch
+media-s5p-mfc-corrected-nv12m-nv21m-plane-sizes.patch
+mmc-dw_mmc-add-a-quirk-for-accessing-64-bit-fifos-in.patch
+alsa-usb-audio-fix-cme-quirk-for-uf-series-keyboards.patch
+asoc-amd-add-dmi-quirk-for-acp6x-mic-support.patch
+asoc-amd-yc-update-quirk-data-for-new-lenovo-model.patch
+platform-x86-x86-android-tablets-add-select-power_su.patch
+wifi-ath11k-fix-dma-buffer-allocation-to-resolve-swi.patch
+wifi-ath11k-fix-memory-leak-in-ath11k_xxx_remove.patch
+wifi-ath12k-fix-memory-leak-in-ath12k_pci_remove.patch
+wifi-ath12k-fix-invalid-entry-fetch-in-ath12k_dp_mon.patch
+ata-libata-core-add-external-to-the-libata.force-ker.patch
+scsi-mpi3mr-avoid-reply-queue-full-condition.patch
+scsi-mpi3mr-synchronous-access-b-w-reset-and-tm-thre.patch
+net-page_pool-don-t-cast-mp-param-to-devmem.patch
+f2fs-don-t-retry-io-for-corrupted-data-scenario.patch
+wifi-mac80211-add-strict-mode-disabling-workarounds.patch
+wifi-mac80211-ensure-sdata-work-is-canceled-before-i.patch
+scsi-target-spc-fix-rsoc-parameter-data-header-size.patch
+net-usb-asix_devices-add-fibergecko-deviceid.patch
+page_pool-avoid-infinite-loop-to-schedule-delayed-wo.patch
+can-flexcan-add-quirk-to-handle-separate-interrupt-l.patch
+can-flexcan-add-nxp-s32g2-s32g3-soc-support.patch
+jfs-fix-uninit-value-access-of-imap-allocated-in-the.patch
+fs-jfs-cast-inactags-to-s64-to-prevent-potential-ove.patch
+fs-jfs-prevent-integer-overflow-in-ag-size-calculati.patch
+jfs-prevent-copying-of-nlink-with-value-0-from-disk-.patch
+jfs-add-sanity-check-for-agwidth-in-dbmount.patch
+ata-libata-eh-do-not-use-atapi-dma-for-a-device-limi.patch
+net-sfp-add-quirk-for-2.5g-oem-bx-sfp.patch
+wifi-ath12k-fix-invalid-data-access-in-ath12k_dp_rx_.patch
+f2fs-fix-to-avoid-out-of-bounds-access-in-f2fs_trunc.patch
+net-sfp-add-quirk-for-fs-sfp-10gm-t-copper-sfp-modul.patch
+ahci-add-pci-id-for-marvell-88se9215-sata-controller.patch
+ext4-protect-ext4_release_dquot-against-freezing.patch
+revert-f2fs-rebuild-nat_bits-during-umount.patch
+ext4-ignore-xattrs-past-end.patch
+cdc_ether-r8152-thinkpad-hybrid-usb-c-a-dock-quirk.patch
+scsi-st-fix-array-overflow-in-st_setup.patch
+ahci-marvell-88se9215-controllers-prefer-dma-for-ata.patch
+btrfs-harden-block_group-bg_list-against-list_del-ra.patch
+wifi-mt76-mt76x2u-add-tp-link-tl-wdn6200-id-to-devic.patch
+net-vlan-don-t-propagate-flags-on-open.patch
+tracing-fix-return-value-in-__ftrace_event_enable_di.patch
+bluetooth-btintel_pcie-add-device-id-of-whale-peak.patch
+bluetooth-hci_uart-fix-race-during-initialization.patch
+bluetooth-btusb-add-2-hwids-for-mt7922.patch
+bluetooth-hci_qca-use-the-power-sequencer-for-wcn675.patch
+bluetooth-qca-simplify-wcn399x-nvm-loading.patch
+bluetooth-add-quirk-for-broken-read_voice_setting.patch
+bluetooth-add-quirk-for-broken-read_page_scan_type.patch
+drm-allow-encoder-mode_set-even-when-connectors-chan.patch
+drm-xe-bmg-add-new-pci-ids.patch
+drm-xe-vf-don-t-try-to-trigger-a-full-gt-reset-if-vf.patch
+drm-amd-display-update-cursor-request-mode-to-the-be.patch
+drm-amdgpu-unlocked-unmap-only-clear-page-table-leav.patch
+drm-panel-orientation-quirks-add-support-for-ayaneo-.patch
+drm-panel-orientation-quirks-add-quirks-for-aya-neo-.patch
+drm-panel-orientation-quirks-add-quirk-for-aya-neo-s.patch
+drm-panel-orientation-quirks-add-new-quirk-for-gpd-w.patch
+drm-panel-orientation-quirks-add-quirk-for-onexplaye.patch
+drm-debugfs-fix-printk-format-for-bridge-index.patch
+drm-bridge-panel-forbid-initializing-a-panel-with-un.patch
+drm-amd-display-stop-dml2-from-removing-pipes-based-.patch
+drivers-base-devres-allow-to-release-group-on-device.patch
+drm-amdkfd-clamp-queue-size-to-minimum.patch
+drm-amdkfd-fix-mode1-reset-crash-issue.patch
+drm-amdkfd-fix-pqm_destroy_queue-race-with-gpu-reset.patch
+drm-amdkfd-debugfs-hang_hws-skip-gpu-with-mes.patch
+drm-xe-xelp-move-wa_16011163337-from-tunings-to-work.patch
+drm-mediatek-mtk_dpi-move-the-input_2p_en-bit-to-pla.patch
+drm-mediatek-mtk_dpi-explicitly-manage-tvd-clock-in-.patch
+pci-add-rockchip-vendor-id.patch
+drm-amdgpu-handle-amdgpu_cgs_create_device-errors-in.patch
+pci-enable-configuration-rrs-sv-early.patch
+drm-amdgpu-fix-the-race-condition-for-draining-retry.patch
+pci-check-bar-index-for-validity.patch
+pci-vmd-make-vmd_dev-cfg_lock-a-raw_spinlock_t-type.patch
+drm-amdgpu-grab-an-additional-reference-on-the-gang-.patch
+fbdev-omapfb-add-plane-value-check.patch
+tracing-probe-events-add-comments-about-entry-data-s.patch
+ktest-fix-test-failures-due-to-missing-log_file-dire.patch
+tpm-tpm_tis-workaround-failed-command-reception-on-i.patch
+tpm-end-any-active-auth-session-before-shutdown.patch
--- /dev/null
+From 8816de950d38ada681f3d2f9a220219941c1955e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Mar 2025 12:25:23 +0000
+Subject: tpm: End any active auth session before shutdown
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jonathan McDowell <noodles@meta.com>
+
+[ Upstream commit 1dbf74e00a5f882b04b398399b6def65cd51ef21 ]
+
+Lazy flushing of TPM auth sessions can interact badly with IMA + kexec,
+resulting in loaded session handles being leaked across the kexec and
+not cleaned up. Fix by ensuring any active auth session is ended before
+the TPM is told about the shutdown, matching what is done when
+suspending.
+
+Before:
+
+root@debian-qemu-efi:~# tpm2_getcap handles-loaded-session
+root@debian-qemu-efi:~# tpm2_getcap handles-saved-session
+root@debian-qemu-efi:~# kexec --load --kexec-file-syscall …
+root@debian-qemu-efi:~# systemctl kexec
+…
+root@debian-qemu-efi:~# tpm2_getcap handles-loaded-session
+- 0x2000000
+root@debian-qemu-efi:~# tpm2_getcap handles-saved-session
+root@debian-qemu-efi:~#
+(repeat kexec steps)
+root@debian-qemu-efi:~# tpm2_getcap handles-loaded-session
+- 0x2000000
+- 0x2000001
+root@debian-qemu-efi:~# tpm2_getcap handles-saved-session
+root@debian-qemu-efi:~#
+
+After:
+
+root@debian-qemu-efi:~# tpm2_getcap handles-loaded-session
+root@debian-qemu-efi:~# tpm2_getcap handles-saved-session
+root@debian-qemu-efi:~# kexec --load --kexec-file-syscall …
+root@debian-qemu-efi:~# systemctl kexec
+…
+root@debian-qemu-efi:~# tpm2_getcap handles-loaded-session
+root@debian-qemu-efi:~# tpm2_getcap handles-saved-session
+root@debian-qemu-efi:~#
+
+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/tpm-chip.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
+index 7df7abaf3e526..87f01269b9b53 100644
+--- a/drivers/char/tpm/tpm-chip.c
++++ b/drivers/char/tpm/tpm-chip.c
+@@ -300,6 +300,7 @@ int tpm_class_shutdown(struct device *dev)
+ down_write(&chip->ops_sem);
+ if (chip->flags & TPM_CHIP_FLAG_TPM2) {
+ if (!tpm_chip_start(chip)) {
++ tpm2_end_auth_session(chip);
+ tpm2_shutdown(chip, TPM2_SU_CLEAR);
+ tpm_chip_stop(chip);
+ }
+--
+2.39.5
+
--- /dev/null
+From f215f6f5a0d6e0b5f2bbbf22e970499cd8b92bdf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Mar 2025 07:26:18 +0200
+Subject: tpm, tpm_tis: Workaround failed command reception on Infineon devices
+
+From: Jonathan McDowell <noodles@meta.com>
+
+[ Upstream commit de9e33df7762abbfc2a1568291f2c3a3154c6a9d ]
+
+Some Infineon devices have a issue where the status register will get
+stuck with a quick REQUEST_USE / COMMAND_READY sequence. This is not
+simply a matter of requiring a longer timeout; the work around is to
+retry the command submission. Add appropriate logic to do this in the
+send path.
+
+This is fixed in later firmware revisions, but those are not always
+available, and cannot generally be easily updated from outside a
+firmware environment.
+
+Testing has been performed with a simple repeated loop of doing a
+TPM2_CC_GET_CAPABILITY for TPM_CAP_PROP_MANUFACTURER using the Go code
+at:
+
+ https://the.earth.li/~noodles/tpm-stuff/timeout-reproducer-simple.go
+
+It can take several hours to reproduce, and several million operations.
+
+Signed-off-by: Jonathan McDowell <noodles@meta.com>
+Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/char/tpm/tpm_tis_core.c | 17 ++++++++++++++---
+ drivers/char/tpm/tpm_tis_core.h | 1 +
+ include/linux/tpm.h | 1 +
+ 3 files changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
+index fdef214b9f6bf..4cc2ab2d16cc5 100644
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -464,7 +464,10 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len)
+
+ if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c,
+ &priv->int_queue, false) < 0) {
+- rc = -ETIME;
++ if (test_bit(TPM_TIS_STATUS_VALID_RETRY, &priv->flags))
++ rc = -EAGAIN;
++ else
++ rc = -ETIME;
+ goto out_err;
+ }
+ status = tpm_tis_status(chip);
+@@ -481,7 +484,10 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len)
+
+ if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c,
+ &priv->int_queue, false) < 0) {
+- rc = -ETIME;
++ if (test_bit(TPM_TIS_STATUS_VALID_RETRY, &priv->flags))
++ rc = -EAGAIN;
++ else
++ rc = -ETIME;
+ goto out_err;
+ }
+ status = tpm_tis_status(chip);
+@@ -546,9 +552,11 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
+ if (rc >= 0)
+ /* Data transfer done successfully */
+ break;
+- else if (rc != -EIO)
++ else if (rc != -EAGAIN && rc != -EIO)
+ /* Data transfer failed, not recoverable */
+ return rc;
++
++ usleep_range(priv->timeout_min, priv->timeout_max);
+ }
+
+ /* go and do it */
+@@ -1144,6 +1152,9 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
+ priv->timeout_max = TIS_TIMEOUT_MAX_ATML;
+ }
+
++ if (priv->manufacturer_id == TPM_VID_IFX)
++ set_bit(TPM_TIS_STATUS_VALID_RETRY, &priv->flags);
++
+ if (is_bsw()) {
+ priv->ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR,
+ ILB_REMAP_SIZE);
+diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
+index 690ad8e9b7319..970d02c337c7f 100644
+--- a/drivers/char/tpm/tpm_tis_core.h
++++ b/drivers/char/tpm/tpm_tis_core.h
+@@ -89,6 +89,7 @@ enum tpm_tis_flags {
+ TPM_TIS_INVALID_STATUS = 1,
+ TPM_TIS_DEFAULT_CANCELLATION = 2,
+ TPM_TIS_IRQ_TESTED = 3,
++ TPM_TIS_STATUS_VALID_RETRY = 4,
+ };
+
+ struct tpm_tis_data {
+diff --git a/include/linux/tpm.h b/include/linux/tpm.h
+index 20a40ade80308..6c3125300c009 100644
+--- a/include/linux/tpm.h
++++ b/include/linux/tpm.h
+@@ -335,6 +335,7 @@ enum tpm2_cc_attrs {
+ #define TPM_VID_WINBOND 0x1050
+ #define TPM_VID_STM 0x104A
+ #define TPM_VID_ATML 0x1114
++#define TPM_VID_IFX 0x15D1
+
+ enum tpm_chip_flags {
+ TPM_CHIP_FLAG_BOOTSTRAPPED = BIT(0),
+--
+2.39.5
+
--- /dev/null
+From e073aa79b006fe0145f69b7d9d27835622545bdf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Mar 2025 18:08:21 +0100
+Subject: tracing: fix return value in __ftrace_event_enable_disable for
+ TRACE_REG_UNREGISTER
+
+From: Gabriele Paoloni <gpaoloni@redhat.com>
+
+[ Upstream commit 0c588ac0ca6c22b774d9ad4a6594681fdfa57d9d ]
+
+When __ftrace_event_enable_disable invokes the class callback to
+unregister the event, the return value is not reported up to the
+caller, hence leading to event unregister failures being silently
+ignored.
+
+This patch assigns the ret variable to the invocation of the
+event unregister callback, so that its return value is stored
+and reported to the caller, and it raises a warning in case
+of error.
+
+Link: https://lore.kernel.org/20250321170821.101403-1-gpaoloni@redhat.com
+Signed-off-by: Gabriele Paoloni <gpaoloni@redhat.com>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/trace/trace_events.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
+index 29eba68e07859..11dea25ef880a 100644
+--- a/kernel/trace/trace_events.c
++++ b/kernel/trace/trace_events.c
+@@ -790,7 +790,9 @@ static int __ftrace_event_enable_disable(struct trace_event_file *file,
+ clear_bit(EVENT_FILE_FL_RECORDED_TGID_BIT, &file->flags);
+ }
+
+- call->class->reg(call, TRACE_REG_UNREGISTER, file);
++ ret = call->class->reg(call, TRACE_REG_UNREGISTER, file);
++
++ WARN_ON_ONCE(ret);
+ }
+ /* If in SOFT_MODE, just set the SOFT_DISABLE_BIT, else clear it */
+ if (file->flags & EVENT_FILE_FL_SOFT_MODE)
+--
+2.39.5
+
--- /dev/null
+From e6e8c5df40e9367eae84a7607b15bea9a4139566 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Mar 2025 21:19:54 +0900
+Subject: tracing: probe-events: Add comments about entry data storing code
+
+From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+
+[ Upstream commit bb9c6020f4c3a07a90dc36826cb5fbe83f09efd5 ]
+
+Add comments about entry data storing code to __store_entry_arg() and
+traceprobe_get_entry_data_size(). These are a bit complicated because of
+building the entry data storing code and scanning it.
+
+This just add comments, no behavior change.
+
+Link: https://lore.kernel.org/all/174061715004.501424.333819546601401102.stgit@devnote2/
+
+Reported-by: Steven Rostedt <rostedt@goodmis.org>
+Closes: https://lore.kernel.org/all/20250226102223.586d7119@gandalf.local.home/
+Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/trace/trace_probe.c | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
+index 16a5e368e7b77..578919962e5df 100644
+--- a/kernel/trace/trace_probe.c
++++ b/kernel/trace/trace_probe.c
+@@ -770,6 +770,10 @@ static int check_prepare_btf_string_fetch(char *typename,
+
+ #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
+
++/*
++ * Add the entry code to store the 'argnum'th parameter and return the offset
++ * in the entry data buffer where the data will be stored.
++ */
+ static int __store_entry_arg(struct trace_probe *tp, int argnum)
+ {
+ struct probe_entry_arg *earg = tp->entry_arg;
+@@ -793,6 +797,20 @@ static int __store_entry_arg(struct trace_probe *tp, int argnum)
+ tp->entry_arg = earg;
+ }
+
++ /*
++ * The entry code array is repeating the pair of
++ * [FETCH_OP_ARG(argnum)][FETCH_OP_ST_EDATA(offset of entry data buffer)]
++ * and the rest of entries are filled with [FETCH_OP_END].
++ *
++ * To reduce the redundant function parameter fetching, we scan the entry
++ * code array to find the FETCH_OP_ARG which already fetches the 'argnum'
++ * parameter. If it doesn't match, update 'offset' to find the last
++ * offset.
++ * If we find the FETCH_OP_END without matching FETCH_OP_ARG entry, we
++ * will save the entry with FETCH_OP_ARG and FETCH_OP_ST_EDATA, and
++ * return data offset so that caller can find the data offset in the entry
++ * data buffer.
++ */
+ offset = 0;
+ for (i = 0; i < earg->size - 1; i++) {
+ switch (earg->code[i].op) {
+@@ -826,6 +844,16 @@ int traceprobe_get_entry_data_size(struct trace_probe *tp)
+ if (!earg)
+ return 0;
+
++ /*
++ * earg->code[] array has an operation sequence which is run in
++ * the entry handler.
++ * The sequence stopped by FETCH_OP_END and each data stored in
++ * the entry data buffer by FETCH_OP_ST_EDATA. The FETCH_OP_ST_EDATA
++ * stores the data at the data buffer + its offset, and all data are
++ * "unsigned long" size. The offset must be increased when a data is
++ * stored. Thus we need to find the last FETCH_OP_ST_EDATA in the
++ * code array.
++ */
+ for (i = 0; i < earg->size; i++) {
+ switch (earg->code[i].op) {
+ case FETCH_OP_END:
+--
+2.39.5
+
--- /dev/null
+From 371b10f48bb082b3fd89d8ea6a35608f8c71a21b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Mar 2025 12:29:21 -0400
+Subject: umount: Allow superblock owners to force umount
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+[ Upstream commit e1ff7aa34dec7e650159fd7ca8ec6af7cc428d9f ]
+
+Loosen the permission check on forced umount to allow users holding
+CAP_SYS_ADMIN privileges in namespaces that are privileged with respect
+to the userns that originally mounted the filesystem.
+
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Link: https://lore.kernel.org/r/12f212d4ef983714d065a6bb372fbb378753bf4c.1742315194.git.trond.myklebust@hammerspace.com
+Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/namespace.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/fs/namespace.c b/fs/namespace.c
+index 73da51ac5a034..f898de3a6f705 100644
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -1986,6 +1986,7 @@ static void warn_mandlock(void)
+ static int can_umount(const struct path *path, int flags)
+ {
+ struct mount *mnt = real_mount(path->mnt);
++ struct super_block *sb = path->dentry->d_sb;
+
+ if (!may_mount())
+ return -EPERM;
+@@ -1995,7 +1996,7 @@ static int can_umount(const struct path *path, int flags)
+ return -EINVAL;
+ if (mnt->mnt.mnt_flags & MNT_LOCKED) /* Check optimistically */
+ return -EINVAL;
+- if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))
++ if (flags & MNT_FORCE && !ns_capable(sb->s_user_ns, CAP_SYS_ADMIN))
+ return -EPERM;
+ return 0;
+ }
+--
+2.39.5
+
--- /dev/null
+From 2d6cdd99d33a520411b5f7c54d386b2451a8a499 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 19 Jan 2025 22:12:18 +0530
+Subject: wifi: ath11k: Fix DMA buffer allocation to resolve SWIOTLB issues
+
+From: P Praneesh <quic_ppranees@quicinc.com>
+
+[ Upstream commit 1bcd20981834928ccc5d981aacb806bb523d8b29 ]
+
+Currently, the driver allocates cacheable DMA buffers for rings like
+HAL_REO_DST and HAL_WBM2SW_RELEASE. The buffers for HAL_WBM2SW_RELEASE
+are large (1024 KiB), exceeding the SWIOTLB slot size of 256 KiB. This
+leads to "swiotlb buffer is full" error messages on systems without an
+IOMMU that use SWIOTLB, causing driver initialization failures. The driver
+calls dma_map_single() with these large buffers obtained from kzalloc(),
+resulting in ring initialization errors on systems without an IOMMU that
+use SWIOTLB.
+
+To address these issues, replace the flawed buffer allocation mechanism
+with the appropriate DMA API. Specifically, use dma_alloc_noncoherent()
+for cacheable DMA buffers, ensuring proper freeing of buffers with
+dma_free_noncoherent().
+
+Error log:
+[ 10.194343] ath11k_pci 0000:04:00.0: swiotlb buffer is full (sz:1048583 bytes), total 32768 (slots), used 2529 (slots)
+[ 10.194406] ath11k_pci 0000:04:00.0: failed to set up tcl_comp ring (0) :-12
+[ 10.194781] ath11k_pci 0000:04:00.0: failed to init DP: -12
+
+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
+
+Reported-by: Tim Harvey <tharvey@gateworks.com>
+Closes: https://lore.kernel.org/all/20241210041133.GA17116@lst.de/
+Signed-off-by: P Praneesh <quic_ppranees@quicinc.com>
+Tested-by: Tim Harvey <tharvey@gateworks.com>
+Link: https://patch.msgid.link/20250119164219.647059-2-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.c | 35 +++++++++-------------------
+ 1 file changed, 11 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
+index fbf666d0ecf1d..f124b7329e1ac 100644
+--- a/drivers/net/wireless/ath/ath11k/dp.c
++++ b/drivers/net/wireless/ath/ath11k/dp.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 <crypto/hash.h>
+@@ -104,14 +104,12 @@ void ath11k_dp_srng_cleanup(struct ath11k_base *ab, struct dp_srng *ring)
+ if (!ring->vaddr_unaligned)
+ return;
+
+- if (ring->cached) {
+- dma_unmap_single(ab->dev, ring->paddr_unaligned, ring->size,
+- DMA_FROM_DEVICE);
+- kfree(ring->vaddr_unaligned);
+- } else {
++ if (ring->cached)
++ dma_free_noncoherent(ab->dev, ring->size, ring->vaddr_unaligned,
++ ring->paddr_unaligned, DMA_FROM_DEVICE);
++ else
+ dma_free_coherent(ab->dev, ring->size, ring->vaddr_unaligned,
+ ring->paddr_unaligned);
+- }
+
+ ring->vaddr_unaligned = NULL;
+ }
+@@ -249,25 +247,14 @@ int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring,
+ default:
+ cached = false;
+ }
+-
+- if (cached) {
+- ring->vaddr_unaligned = kzalloc(ring->size, GFP_KERNEL);
+- if (!ring->vaddr_unaligned)
+- return -ENOMEM;
+-
+- ring->paddr_unaligned = dma_map_single(ab->dev,
+- ring->vaddr_unaligned,
+- ring->size,
+- DMA_FROM_DEVICE);
+- if (dma_mapping_error(ab->dev, ring->paddr_unaligned)) {
+- kfree(ring->vaddr_unaligned);
+- ring->vaddr_unaligned = NULL;
+- return -ENOMEM;
+- }
+- }
+ }
+
+- if (!cached)
++ if (cached)
++ ring->vaddr_unaligned = dma_alloc_noncoherent(ab->dev, ring->size,
++ &ring->paddr_unaligned,
++ DMA_FROM_DEVICE,
++ GFP_KERNEL);
++ else
+ ring->vaddr_unaligned = dma_alloc_coherent(ab->dev, ring->size,
+ &ring->paddr_unaligned,
+ GFP_KERNEL);
+--
+2.39.5
+
--- /dev/null
+From 664bf85438d27592a9da2eb8d7eafd17247ef8b4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jan 2025 16:49:48 +0800
+Subject: wifi: ath11k: fix memory leak in ath11k_xxx_remove()
+
+From: Miaoqing Pan <quic_miaoqing@quicinc.com>
+
+[ Upstream commit efb24b1f0d29537714dd3cc46fb335ac27855251 ]
+
+The firmware memory was allocated in ath11k_pci_probe() or
+ath11k_ahb_probe(), but not freed in ath11k_xxx_remove() in case
+ATH11K_FLAG_QMI_FAIL bit is set. So call ath11k_fw_destroy() to
+free the memory.
+
+Found while fixing the same problem in ath12k:
+https://lore.kernel.org/linux-wireless/20240314012746.2729101-1-quic_miaoqing@quicinc.com
+
+Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-04546-QCAHSPSWPL_V1_V2_SILICONZ_IOE-1
+
+Signed-off-by: Miaoqing Pan <quic_miaoqing@quicinc.com>
+Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>
+Link: https://patch.msgid.link/20250123084948.1124357-1-quic_miaoqing@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/ahb.c | 4 +++-
+ drivers/net/wireless/ath/ath11k/core.c | 3 +--
+ drivers/net/wireless/ath/ath11k/fw.c | 3 ++-
+ drivers/net/wireless/ath/ath11k/pci.c | 3 ++-
+ 4 files changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c
+index 97b12f51ef28c..9389dc5f4a3da 100644
+--- a/drivers/net/wireless/ath/ath11k/ahb.c
++++ b/drivers/net/wireless/ath/ath11k/ahb.c
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: BSD-3-Clause-Clear
+ /*
+ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+- * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ #include <linux/module.h>
+@@ -1290,6 +1290,7 @@ static void ath11k_ahb_remove(struct platform_device *pdev)
+ ath11k_core_deinit(ab);
+
+ qmi_fail:
++ ath11k_fw_destroy(ab);
+ ath11k_ahb_free_resources(ab);
+ }
+
+@@ -1309,6 +1310,7 @@ static void ath11k_ahb_shutdown(struct platform_device *pdev)
+ ath11k_core_deinit(ab);
+
+ free_resources:
++ ath11k_fw_destroy(ab);
+ ath11k_ahb_free_resources(ab);
+ }
+
+diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
+index ccf4ad35fdc33..7eba6ee054ffe 100644
+--- a/drivers/net/wireless/ath/ath11k/core.c
++++ b/drivers/net/wireless/ath/ath11k/core.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/module.h>
+@@ -2214,7 +2214,6 @@ void ath11k_core_deinit(struct ath11k_base *ab)
+ ath11k_hif_power_down(ab);
+ ath11k_mac_destroy(ab);
+ ath11k_core_soc_destroy(ab);
+- ath11k_fw_destroy(ab);
+ }
+ EXPORT_SYMBOL(ath11k_core_deinit);
+
+diff --git a/drivers/net/wireless/ath/ath11k/fw.c b/drivers/net/wireless/ath/ath11k/fw.c
+index 4e36292a79db8..cbbd8e57119f2 100644
+--- a/drivers/net/wireless/ath/ath11k/fw.c
++++ b/drivers/net/wireless/ath/ath11k/fw.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: BSD-3-Clause-Clear
+ /*
+- * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ #include "core.h"
+@@ -166,3 +166,4 @@ void ath11k_fw_destroy(struct ath11k_base *ab)
+ {
+ release_firmware(ab->fw.fw);
+ }
++EXPORT_SYMBOL(ath11k_fw_destroy);
+diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
+index be9d2c69cc413..6ebfa5d02e2e5 100644
+--- a/drivers/net/wireless/ath/ath11k/pci.c
++++ b/drivers/net/wireless/ath/ath11k/pci.c
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: BSD-3-Clause-Clear
+ /*
+ * Copyright (c) 2019-2020 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/module.h>
+@@ -981,6 +981,7 @@ static void ath11k_pci_remove(struct pci_dev *pdev)
+ ath11k_core_deinit(ab);
+
+ qmi_fail:
++ ath11k_fw_destroy(ab);
+ ath11k_mhi_unregister(ab_pci);
+
+ ath11k_pcic_free_irq(ab);
+--
+2.39.5
+
--- /dev/null
+From fdedb2ea3aaf6b53ade74358d1f5c4cd4e8c9e3b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Feb 2025 14:33:02 +0530
+Subject: wifi: ath12k: Fix invalid data access in ath12k_dp_rx_h_undecap_nwifi
+
+From: Manish Dharanenthiran <quic_mdharane@quicinc.com>
+
+[ Upstream commit 9a0dddfb30f120db3851627935851d262e4e7acb ]
+
+In certain cases, hardware might provide packets with a
+length greater than the maximum native Wi-Fi header length.
+This can lead to accessing and modifying fields in the header
+within the ath12k_dp_rx_h_undecap_nwifi function for
+DP_RX_DECAP_TYPE_NATIVE_WIFI decap type and
+potentially resulting in invalid data access and memory corruption.
+
+Add a sanity check before processing the SKB to prevent invalid
+data access in the undecap native Wi-Fi function for the
+DP_RX_DECAP_TYPE_NATIVE_WIFI decap type.
+
+Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
+
+Signed-off-by: Manish Dharanenthiran <quic_mdharane@quicinc.com>
+Signed-off-by: Tamizh Chelvam Raja <tamizh.raja@oss.qualcomm.com>
+Link: https://patch.msgid.link/20250211090302.4105141-1-tamizh.raja@oss.qualcomm.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_rx.c | 42 +++++++++++++++++++++++--
+ 1 file changed, 40 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
+index 91e3393f7b5f4..4cbba96121a11 100644
+--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
+@@ -2470,6 +2470,29 @@ static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *nap
+ ieee80211_rx_napi(ath12k_ar_to_hw(ar), pubsta, msdu, napi);
+ }
+
++static bool ath12k_dp_rx_check_nwifi_hdr_len_valid(struct ath12k_base *ab,
++ struct hal_rx_desc *rx_desc,
++ struct sk_buff *msdu)
++{
++ struct ieee80211_hdr *hdr;
++ u8 decap_type;
++ u32 hdr_len;
++
++ decap_type = ath12k_dp_rx_h_decap_type(ab, rx_desc);
++ if (decap_type != DP_RX_DECAP_TYPE_NATIVE_WIFI)
++ return true;
++
++ hdr = (struct ieee80211_hdr *)msdu->data;
++ hdr_len = ieee80211_hdrlen(hdr->frame_control);
++
++ if ((likely(hdr_len <= DP_MAX_NWIFI_HDR_LEN)))
++ return true;
++
++ ab->soc_stats.invalid_rbm++;
++ WARN_ON_ONCE(1);
++ return false;
++}
++
+ static int ath12k_dp_rx_process_msdu(struct ath12k *ar,
+ struct sk_buff *msdu,
+ struct sk_buff_head *msdu_list,
+@@ -2528,6 +2551,11 @@ static int ath12k_dp_rx_process_msdu(struct ath12k *ar,
+ }
+ }
+
++ if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, rx_desc, msdu))) {
++ ret = -EINVAL;
++ goto free_out;
++ }
++
+ ath12k_dp_rx_h_ppdu(ar, rx_desc, rx_status);
+ ath12k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_status);
+
+@@ -2880,6 +2908,9 @@ static int ath12k_dp_rx_h_verify_tkip_mic(struct ath12k *ar, struct ath12k_peer
+ RX_FLAG_IV_STRIPPED | RX_FLAG_DECRYPTED;
+ skb_pull(msdu, hal_rx_desc_sz);
+
++ if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, rx_desc, msdu)))
++ return -EINVAL;
++
+ ath12k_dp_rx_h_ppdu(ar, rx_desc, rxs);
+ ath12k_dp_rx_h_undecap(ar, msdu, rx_desc,
+ HAL_ENCRYPT_TYPE_TKIP_MIC, rxs, true);
+@@ -3600,6 +3631,9 @@ static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu,
+ skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
+ skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
+ }
++ if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, desc, msdu)))
++ return -EINVAL;
++
+ ath12k_dp_rx_h_ppdu(ar, desc, status);
+
+ ath12k_dp_rx_h_mpdu(ar, msdu, desc, status);
+@@ -3644,7 +3678,7 @@ static bool ath12k_dp_rx_h_reo_err(struct ath12k *ar, struct sk_buff *msdu,
+ return drop;
+ }
+
+-static void ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu,
++static bool ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu,
+ struct ieee80211_rx_status *status)
+ {
+ struct ath12k_base *ab = ar->ab;
+@@ -3662,6 +3696,9 @@ static void ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu,
+ skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
+ skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
+
++ if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, desc, msdu)))
++ return true;
++
+ ath12k_dp_rx_h_ppdu(ar, desc, status);
+
+ status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR |
+@@ -3669,6 +3706,7 @@ static void ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu,
+
+ ath12k_dp_rx_h_undecap(ar, msdu, desc,
+ HAL_ENCRYPT_TYPE_TKIP_MIC, status, false);
++ return false;
+ }
+
+ static bool ath12k_dp_rx_h_rxdma_err(struct ath12k *ar, struct sk_buff *msdu,
+@@ -3687,7 +3725,7 @@ static bool ath12k_dp_rx_h_rxdma_err(struct ath12k *ar, struct sk_buff *msdu,
+ case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR:
+ err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, rx_desc);
+ if (err_bitmap & HAL_RX_MPDU_ERR_TKIP_MIC) {
+- ath12k_dp_rx_h_tkip_mic_err(ar, msdu, status);
++ drop = ath12k_dp_rx_h_tkip_mic_err(ar, msdu, status);
+ break;
+ }
+ fallthrough;
+--
+2.39.5
+
--- /dev/null
+From d37d30f75c6af4b3c7546e0da3069eb23d0bb924 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 23 Dec 2024 11:31:24 +0530
+Subject: wifi: ath12k: Fix invalid entry fetch in ath12k_dp_mon_srng_process
+
+From: P Praneesh <quic_ppranees@quicinc.com>
+
+[ Upstream commit 63fdc4509bcf483e79548de6bc08bf3c8e504bb3 ]
+
+Currently, ath12k_dp_mon_srng_process uses ath12k_hal_srng_src_get_next_entry
+to fetch the next entry from the destination ring. This is incorrect because
+ath12k_hal_srng_src_get_next_entry is intended for source rings, not destination
+rings. This leads to invalid entry fetches, causing potential data corruption or
+crashes due to accessing incorrect memory locations. This happens because the
+source ring and destination ring have different handling mechanisms and using
+the wrong function results in incorrect pointer arithmetic and ring management.
+
+To fix this issue, replace the call to ath12k_hal_srng_src_get_next_entry with
+ath12k_hal_srng_dst_get_next_entry in ath12k_dp_mon_srng_process. This ensures
+that the correct function is used for fetching entries from the destination
+ring, preventing invalid memory accesses.
+
+Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
+Tested-on: WCN7850 hw2.0 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-7-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/dp_mon.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c
+index 5c6749bc4039d..1706ec27eb9c0 100644
+--- a/drivers/net/wireless/ath/ath12k/dp_mon.c
++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c
+@@ -2533,7 +2533,7 @@ int ath12k_dp_mon_rx_process_stats(struct ath12k *ar, int mac_id,
+ dest_idx = 0;
+ move_next:
+ ath12k_dp_mon_buf_replenish(ab, buf_ring, 1);
+- ath12k_hal_srng_src_get_next_entry(ab, srng);
++ ath12k_hal_srng_dst_get_next_entry(ab, srng);
+ num_buffs_reaped++;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 94ef2be17a6dd78ecc602da92436b373243f8909 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jan 2025 16:02:26 +0800
+Subject: wifi: ath12k: fix memory leak in ath12k_pci_remove()
+
+From: Miaoqing Pan <quic_miaoqing@quicinc.com>
+
+[ Upstream commit 1b24394ed5c8a8d8f7b9e3aa9044c31495d46f2e ]
+
+Kmemleak reported this error:
+
+ unreferenced object 0xffff1c165cec3060 (size 32):
+ comm "insmod", pid 560, jiffies 4296964570 (age 235.596s)
+ backtrace:
+ [<000000005434db68>] __kmem_cache_alloc_node+0x1f4/0x2c0
+ [<000000001203b155>] kmalloc_trace+0x40/0x88
+ [<0000000028adc9c8>] _request_firmware+0xb8/0x608
+ [<00000000cad1aef7>] firmware_request_nowarn+0x50/0x80
+ [<000000005011a682>] local_pci_probe+0x48/0xd0
+ [<00000000077cd295>] pci_device_probe+0xb4/0x200
+ [<0000000087184c94>] really_probe+0x150/0x2c0
+
+The firmware memory was allocated in ath12k_pci_probe(), but not
+freed in ath12k_pci_remove() in case ATH12K_FLAG_QMI_FAIL bit is
+set. So call ath12k_fw_unmap() to free the memory.
+
+Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.2.0-02280-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1
+
+Signed-off-by: Miaoqing Pan <quic_miaoqing@quicinc.com>
+Reviewed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>
+Link: https://patch.msgid.link/20250123080226.1116479-1-quic_miaoqing@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/pci.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
+index bd269aa1740bc..2ff866e1d7d5b 100644
+--- a/drivers/net/wireless/ath/ath12k/pci.c
++++ b/drivers/net/wireless/ath/ath12k/pci.c
+@@ -1541,6 +1541,7 @@ static void ath12k_pci_remove(struct pci_dev *pdev)
+ ath12k_core_deinit(ab);
+
+ qmi_fail:
++ ath12k_fw_unmap(ab);
+ ath12k_mhi_unregister(ab_pci);
+
+ ath12k_pci_free_irq(ab);
+--
+2.39.5
+
--- /dev/null
+From 4bfc8de226d2b07fbe1ec814f950a4db87ade296 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Feb 2025 11:39:16 +0200
+Subject: wifi: mac80211: add strict mode disabling workarounds
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 3ad4fce66e4f9d82abfc366707757e29cc14a9d2 ]
+
+Add a strict mode where we disable certain workarounds and have
+additional checks such as, for now, that VHT capabilities from
+association response match those from beacon/probe response. We
+can extend the checks in the future.
+
+Make it an opt-in setting by the driver so it can be set there
+in some driver-specific way, for example. Also allow setting
+this one hw flag through the hwflags debugfs, by writing a new
+strict=0 or strict=1 value.
+
+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/20250205110958.5cecb0469479.I4a69617dc60ba0d6308416ffbc3102cfd08ba068@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/mac80211.h | 6 ++++++
+ net/mac80211/debugfs.c | 44 +++++++++++++++++++++++++++++++++++++++--
+ net/mac80211/mlme.c | 45 +++++++++++++++++++++++++++++-------------
+ 3 files changed, 79 insertions(+), 16 deletions(-)
+
+diff --git a/include/net/mac80211.h b/include/net/mac80211.h
+index 5b712582f9a9c..3b964f8834e71 100644
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -2826,6 +2826,11 @@ struct ieee80211_txq {
+ * implements MLO, so operation can continue on other links when one
+ * link is switching.
+ *
++ * @IEEE80211_HW_STRICT: strictly enforce certain things mandated by the spec
++ * but otherwise ignored/worked around for interoperability. This is a
++ * HW flag so drivers can opt in according to their own control, e.g. in
++ * testing.
++ *
+ * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
+ */
+ enum ieee80211_hw_flags {
+@@ -2885,6 +2890,7 @@ enum ieee80211_hw_flags {
+ IEEE80211_HW_DISALLOW_PUNCTURING,
+ IEEE80211_HW_DISALLOW_PUNCTURING_5GHZ,
+ IEEE80211_HW_HANDLES_QUIET_CSA,
++ IEEE80211_HW_STRICT,
+
+ /* keep last, obviously */
+ NUM_IEEE80211_HW_FLAGS
+diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
+index 02b5476a4376c..a0710ae0e7a49 100644
+--- a/net/mac80211/debugfs.c
++++ b/net/mac80211/debugfs.c
+@@ -499,6 +499,7 @@ static const char *hw_flag_names[] = {
+ FLAG(DISALLOW_PUNCTURING),
+ FLAG(DISALLOW_PUNCTURING_5GHZ),
+ FLAG(HANDLES_QUIET_CSA),
++ FLAG(STRICT),
+ #undef FLAG
+ };
+
+@@ -531,6 +532,46 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf,
+ return rv;
+ }
+
++static ssize_t hwflags_write(struct file *file, const char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ieee80211_local *local = file->private_data;
++ char buf[100];
++ int val;
++
++ if (count >= sizeof(buf))
++ return -EINVAL;
++
++ if (copy_from_user(buf, user_buf, count))
++ return -EFAULT;
++
++ if (count && buf[count - 1] == '\n')
++ buf[count - 1] = '\0';
++ else
++ buf[count] = '\0';
++
++ if (sscanf(buf, "strict=%d", &val) == 1) {
++ switch (val) {
++ case 0:
++ ieee80211_hw_set(&local->hw, STRICT);
++ return count;
++ case 1:
++ __clear_bit(IEEE80211_HW_STRICT, local->hw.flags);
++ return count;
++ default:
++ return -EINVAL;
++ }
++ }
++
++ return -EINVAL;
++}
++
++static const struct file_operations hwflags_ops = {
++ .open = simple_open,
++ .read = hwflags_read,
++ .write = hwflags_write,
++};
++
+ static ssize_t misc_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+ {
+@@ -581,7 +622,6 @@ static ssize_t queues_read(struct file *file, char __user *user_buf,
+ return simple_read_from_buffer(user_buf, count, ppos, buf, res);
+ }
+
+-DEBUGFS_READONLY_FILE_OPS(hwflags);
+ DEBUGFS_READONLY_FILE_OPS(queues);
+ DEBUGFS_READONLY_FILE_OPS(misc);
+
+@@ -659,7 +699,7 @@ void debugfs_hw_add(struct ieee80211_local *local)
+ #ifdef CONFIG_PM
+ DEBUGFS_ADD_MODE(reset, 0200);
+ #endif
+- DEBUGFS_ADD(hwflags);
++ DEBUGFS_ADD_MODE(hwflags, 0600);
+ DEBUGFS_ADD(user_power);
+ DEBUGFS_ADD(power);
+ DEBUGFS_ADD(hw_conf);
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index 88751b0eb317a..ad0d040569dcd 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -166,6 +166,9 @@ ieee80211_determine_ap_chan(struct ieee80211_sub_if_data *sdata,
+ bool no_vht = false;
+ u32 ht_cfreq;
+
++ if (ieee80211_hw_check(&sdata->local->hw, STRICT))
++ ignore_ht_channel_mismatch = false;
++
+ *chandef = (struct cfg80211_chan_def) {
+ .chan = channel,
+ .width = NL80211_CHAN_WIDTH_20_NOHT,
+@@ -385,7 +388,7 @@ ieee80211_verify_peer_he_mcs_support(struct ieee80211_sub_if_data *sdata,
+ * zeroes, which is nonsense, and completely inconsistent with itself
+ * (it doesn't have 8 streams). Accept the settings in this case anyway.
+ */
+- if (!ap_min_req_set)
++ if (!ieee80211_hw_check(&sdata->local->hw, STRICT) && !ap_min_req_set)
+ return true;
+
+ /* make sure the AP is consistent with itself
+@@ -445,7 +448,7 @@ ieee80211_verify_sta_he_mcs_support(struct ieee80211_sub_if_data *sdata,
+ * zeroes, which is nonsense, and completely inconsistent with itself
+ * (it doesn't have 8 streams). Accept the settings in this case anyway.
+ */
+- if (!ap_min_req_set)
++ if (!ieee80211_hw_check(&sdata->local->hw, STRICT) && !ap_min_req_set)
+ return true;
+
+ /* Need to go over for 80MHz, 160MHz and for 80+80 */
+@@ -1212,13 +1215,15 @@ static bool ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
+ * Some APs apparently get confused if our capabilities are better
+ * than theirs, so restrict what we advertise in the assoc request.
+ */
+- if (!(ap_vht_cap->vht_cap_info &
+- cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)))
+- cap &= ~(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
+- IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
+- else if (!(ap_vht_cap->vht_cap_info &
+- cpu_to_le32(IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)))
+- cap &= ~IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
++ if (!ieee80211_hw_check(&local->hw, STRICT)) {
++ if (!(ap_vht_cap->vht_cap_info &
++ cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)))
++ cap &= ~(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
++ IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
++ else if (!(ap_vht_cap->vht_cap_info &
++ cpu_to_le32(IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)))
++ cap &= ~IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
++ }
+
+ /*
+ * If some other vif is using the MU-MIMO capability we cannot associate
+@@ -1260,14 +1265,16 @@ static bool ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
+ return mu_mimo_owner;
+ }
+
+-static void ieee80211_assoc_add_rates(struct sk_buff *skb,
++static void ieee80211_assoc_add_rates(struct ieee80211_local *local,
++ struct sk_buff *skb,
+ enum nl80211_chan_width width,
+ struct ieee80211_supported_band *sband,
+ struct ieee80211_mgd_assoc_data *assoc_data)
+ {
+ u32 rates;
+
+- if (assoc_data->supp_rates_len) {
++ if (assoc_data->supp_rates_len &&
++ !ieee80211_hw_check(&local->hw, STRICT)) {
+ /*
+ * Get all rates supported by the device and the AP as
+ * some APs don't like getting a superset of their rates
+@@ -1481,7 +1488,7 @@ static size_t ieee80211_assoc_link_elems(struct ieee80211_sub_if_data *sdata,
+ *capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
+
+ if (sband->band != NL80211_BAND_S1GHZ)
+- ieee80211_assoc_add_rates(skb, width, sband, assoc_data);
++ ieee80211_assoc_add_rates(local, skb, width, sband, assoc_data);
+
+ if (*capab & WLAN_CAPABILITY_SPECTRUM_MGMT ||
+ *capab & WLAN_CAPABILITY_RADIO_MEASURE) {
+@@ -1925,7 +1932,8 @@ static int ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
+ * for some reason check it and want it to be set, set the bit for all
+ * pre-EHT connections as we used to do.
+ */
+- if (link->u.mgd.conn.mode < IEEE80211_CONN_MODE_EHT)
++ if (link->u.mgd.conn.mode < IEEE80211_CONN_MODE_EHT &&
++ !ieee80211_hw_check(&local->hw, STRICT))
+ capab |= WLAN_CAPABILITY_ESS;
+
+ /* add the elements for the assoc (main) link */
+@@ -4710,7 +4718,7 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
+ * 2G/3G/4G wifi routers, reported models include the "Onda PN51T",
+ * "Vodafone PocketWiFi 2", "ZTE MF60" and a similar T-Mobile device.
+ */
+- if (!is_6ghz &&
++ if (!ieee80211_hw_check(&local->hw, STRICT) && !is_6ghz &&
+ ((assoc_data->wmm && !elems->wmm_param) ||
+ (link->u.mgd.conn.mode >= IEEE80211_CONN_MODE_HT &&
+ (!elems->ht_cap_elem || !elems->ht_operation)) ||
+@@ -4846,6 +4854,15 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
+ bss_vht_cap = (const void *)elem->data;
+ }
+
++ if (ieee80211_hw_check(&local->hw, STRICT) &&
++ (!bss_vht_cap || memcmp(bss_vht_cap, elems->vht_cap_elem,
++ sizeof(*bss_vht_cap)))) {
++ rcu_read_unlock();
++ ret = false;
++ link_info(link, "VHT capabilities mismatch\n");
++ goto out;
++ }
++
+ ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
+ elems->vht_cap_elem,
+ bss_vht_cap, link_sta);
+--
+2.39.5
+
--- /dev/null
+From e833f35de5a26b58e679f3e66fad1f9ecc175ab4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Feb 2025 11:39:26 +0200
+Subject: wifi: mac80211: ensure sdata->work is canceled before initialized.
+
+From: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+
+[ Upstream commit 6c93fd502023dd919b5987ccbe990735410edd49 ]
+
+This wiphy work is canceled when the iface is stopped,
+and shouldn't be queued for a non-running iface.
+If it happens to be queued for a non-running iface (due to a bug)
+it can cause a corruption of wiphy_work_list when ieee80211_setup_sdata
+is called. Make sure to cancel it in this case and warn on.
+
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Reviewed-by: Johannes Berg <johannes.berg@intel.com>
+Link: https://patch.msgid.link/20250205110958.99204c767c10.I84ce27a239059f6009cee197b252549a11426046@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mac80211/iface.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
+index 8bbfa45e1796d..dbcd75c5d778e 100644
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -8,7 +8,7 @@
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2013-2014 Intel Mobile Communications GmbH
+ * Copyright (c) 2016 Intel Deutschland GmbH
+- * Copyright (C) 2018-2024 Intel Corporation
++ * Copyright (C) 2018-2025 Intel Corporation
+ */
+ #include <linux/slab.h>
+ #include <linux/kernel.h>
+@@ -812,6 +812,9 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
+ */
+ static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
+ {
++ if (WARN_ON(!list_empty(&sdata->work.entry)))
++ wiphy_work_cancel(sdata->local->hw.wiphy, &sdata->work);
++
+ /* free extra data */
+ ieee80211_free_keys(sdata, false);
+
+--
+2.39.5
+
--- /dev/null
+From 2a0aa5c4f1c82a99d108c5d1c8fd23d94c1c8ebc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Mar 2025 18:22:35 +0800
+Subject: wifi: mt76: mt76x2u: add TP-Link TL-WDN6200 ID to device table
+
+From: Icenowy Zheng <uwu@icenowy.me>
+
+[ Upstream commit 06cccc2ebbe6c8a20f714f3a0ff3ff489d3004bb ]
+
+The TP-Link TL-WDN6200 "Driverless" version cards use a MT7612U chipset.
+
+Add the USB ID to mt76x2u driver.
+
+Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
+Link: https://patch.msgid.link/20250317102235.1421726-1-uwu@icenowy.me
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mediatek/mt76/mt76x2/usb.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
+index e832ad53e2393..a4f4d12f904e7 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
++++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
+@@ -22,6 +22,7 @@ static const struct usb_device_id mt76x2u_device_table[] = {
+ { USB_DEVICE(0x0846, 0x9053) }, /* Netgear A6210 */
+ { USB_DEVICE(0x045e, 0x02e6) }, /* XBox One Wireless Adapter */
+ { USB_DEVICE(0x045e, 0x02fe) }, /* XBox One Wireless Adapter */
++ { USB_DEVICE(0x2357, 0x0137) }, /* TP-Link TL-WDN6200 */
+ { },
+ };
+
+--
+2.39.5
+
--- /dev/null
+From 4b2ff6cf1e94a0c0e3e71ed01e36c16a2895b109 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Feb 2025 21:45:05 +0100
+Subject: x86/cpu: Don't clear X86_FEATURE_LAHF_LM flag in init_amd_k8() on AMD
+ when running in a virtual machine
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Max Grobecker <max@grobecker.info>
+
+[ Upstream commit a4248ee16f411ac1ea7dfab228a6659b111e3d65 ]
+
+When running in a virtual machine, we might see the original hardware CPU
+vendor string (i.e. "AuthenticAMD"), but a model and family ID set by the
+hypervisor. In case we run on AMD hardware and the hypervisor sets a model
+ID < 0x14, the LAHF cpu feature is eliminated from the the list of CPU
+capabilities present to circumvent a bug with some BIOSes in conjunction with
+AMD K8 processors.
+
+Parsing the flags list from /proc/cpuinfo seems to be happening mostly in
+bash scripts and prebuilt Docker containers, as it does not need to have
+additionals tools present – even though more reliable ways like using "kcpuid",
+which calls the CPUID instruction instead of parsing a list, should be preferred.
+Scripts, that use /proc/cpuinfo to determine if the current CPU is
+"compliant" with defined microarchitecture levels like x86-64-v2 will falsely
+claim the CPU is incapable of modern CPU instructions when "lahf_lm" is missing
+in that flags list.
+
+This can prevent some docker containers from starting or build scripts to create
+unoptimized binaries.
+
+Admittably, this is more a small inconvenience than a severe bug in the kernel
+and the shoddy scripts that rely on parsing /proc/cpuinfo
+should be fixed instead.
+
+This patch adds an additional check to see if we're running inside a
+virtual machine (X86_FEATURE_HYPERVISOR is present), which, to my
+understanding, can't be present on a real K8 processor as it was introduced
+only with the later/other Athlon64 models.
+
+Example output with the "lahf_lm" flag missing in the flags list
+(should be shown between "hypervisor" and "abm"):
+
+ $ cat /proc/cpuinfo
+ processor : 0
+ vendor_id : AuthenticAMD
+ cpu family : 15
+ model : 6
+ model name : Common KVM processor
+ stepping : 1
+ microcode : 0x1000065
+ cpu MHz : 2599.998
+ cache size : 512 KB
+ physical id : 0
+ siblings : 1
+ core id : 0
+ cpu cores : 1
+ apicid : 0
+ initial apicid : 0
+ fpu : yes
+ fpu_exception : yes
+ cpuid level : 13
+ wp : yes
+ flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca
+ cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx rdtscp
+ lm rep_good nopl cpuid extd_apicid tsc_known_freq pni
+ pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt
+ tsc_deadline_timer aes xsave avx f16c hypervisor abm
+ 3dnowprefetch vmmcall bmi1 avx2 bmi2 xsaveopt
+
+... while kcpuid shows the feature to be present in the CPU:
+
+ # kcpuid -d | grep lahf
+ lahf_lm - LAHF/SAHF available in 64-bit mode
+
+[ mingo: Updated the comment a bit, incorporated Boris's review feedback. ]
+
+Signed-off-by: Max Grobecker <max@grobecker.info>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Cc: linux-kernel@vger.kernel.org
+Cc: Borislav Petkov <bp@alien8.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/cpu/amd.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
+index 79d2e17f6582e..425bed00b2e07 100644
+--- a/arch/x86/kernel/cpu/amd.c
++++ b/arch/x86/kernel/cpu/amd.c
+@@ -627,7 +627,7 @@ static void init_amd_k8(struct cpuinfo_x86 *c)
+ * (model = 0x14) and later actually support it.
+ * (AMD Erratum #110, docId: 25759).
+ */
+- if (c->x86_model < 0x14 && cpu_has(c, X86_FEATURE_LAHF_LM)) {
++ if (c->x86_model < 0x14 && cpu_has(c, X86_FEATURE_LAHF_LM) && !cpu_has(c, X86_FEATURE_HYPERVISOR)) {
+ clear_cpu_cap(c, X86_FEATURE_LAHF_LM);
+ if (!rdmsrl_amd_safe(0xc001100d, &value)) {
+ value &= ~BIT_64(32);
+--
+2.39.5
+
--- /dev/null
+From 89d7b92a5e80e3dc87de4c463ede1e0bc0b9d9fc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Nov 2024 10:45:28 -0800
+Subject: x86/ia32: Leave NULL selector values 0~3 unchanged
+
+From: Xin Li (Intel) <xin@zytor.com>
+
+[ Upstream commit ad546940b5991d3e141238cd80a6d1894b767184 ]
+
+The first GDT descriptor is reserved as 'NULL descriptor'. As bits 0
+and 1 of a segment selector, i.e., the RPL bits, are NOT used to index
+GDT, selector values 0~3 all point to the NULL descriptor, thus values
+0, 1, 2 and 3 are all valid NULL selector values.
+
+When a NULL selector value is to be loaded into a segment register,
+reload_segments() sets its RPL bits. Later IRET zeros ES, FS, GS, and
+DS segment registers if any of them is found to have any nonzero NULL
+selector value. The two operations offset each other to actually effect
+a nop.
+
+Besides, zeroing of RPL in NULL selector values is an information leak
+in pre-FRED systems as userspace can spot any interrupt/exception by
+loading a nonzero NULL selector, and waiting for it to become zero.
+But there is nothing software can do to prevent it before FRED.
+
+ERETU, the only legit instruction to return to userspace from kernel
+under FRED, by design does NOT zero any segment register to avoid this
+problem behavior.
+
+As such, leave NULL selector values 0~3 unchanged and close the leak.
+
+Do the same on 32-bit kernel as well.
+
+Signed-off-by: Xin Li (Intel) <xin@zytor.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Andy Lutomirski <luto@kernel.org>
+Cc: Brian Gerst <brgerst@gmail.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20241126184529.1607334-1-xin@zytor.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/signal_32.c | 62 +++++++++++++++++++++++++------------
+ 1 file changed, 43 insertions(+), 19 deletions(-)
+
+diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c
+index ef654530bf5a9..98123ff10506c 100644
+--- a/arch/x86/kernel/signal_32.c
++++ b/arch/x86/kernel/signal_32.c
+@@ -33,25 +33,55 @@
+ #include <asm/smap.h>
+ #include <asm/gsseg.h>
+
++/*
++ * The first GDT descriptor is reserved as 'NULL descriptor'. As bits 0
++ * and 1 of a segment selector, i.e., the RPL bits, are NOT used to index
++ * GDT, selector values 0~3 all point to the NULL descriptor, thus values
++ * 0, 1, 2 and 3 are all valid NULL selector values.
++ *
++ * However IRET zeros ES, FS, GS, and DS segment registers if any of them
++ * is found to have any nonzero NULL selector value, which can be used by
++ * userspace in pre-FRED systems to spot any interrupt/exception by loading
++ * a nonzero NULL selector and waiting for it to become zero. Before FRED
++ * there was nothing software could do to prevent such an information leak.
++ *
++ * ERETU, the only legit instruction to return to userspace from kernel
++ * under FRED, by design does NOT zero any segment register to avoid this
++ * problem behavior.
++ *
++ * As such, leave NULL selector values 0~3 unchanged.
++ */
++static inline u16 fixup_rpl(u16 sel)
++{
++ return sel <= 3 ? sel : sel | 3;
++}
++
+ #ifdef CONFIG_IA32_EMULATION
+ #include <asm/unistd_32_ia32.h>
+
+ static inline void reload_segments(struct sigcontext_32 *sc)
+ {
+- unsigned int cur;
++ u16 cur;
+
++ /*
++ * Reload fs and gs if they have changed in the signal
++ * handler. This does not handle long fs/gs base changes in
++ * the handler, but does not clobber them at least in the
++ * normal case.
++ */
+ savesegment(gs, cur);
+- if ((sc->gs | 0x03) != cur)
+- load_gs_index(sc->gs | 0x03);
++ if (fixup_rpl(sc->gs) != cur)
++ load_gs_index(fixup_rpl(sc->gs));
+ savesegment(fs, cur);
+- if ((sc->fs | 0x03) != cur)
+- loadsegment(fs, sc->fs | 0x03);
++ if (fixup_rpl(sc->fs) != cur)
++ loadsegment(fs, fixup_rpl(sc->fs));
++
+ savesegment(ds, cur);
+- if ((sc->ds | 0x03) != cur)
+- loadsegment(ds, sc->ds | 0x03);
++ if (fixup_rpl(sc->ds) != cur)
++ loadsegment(ds, fixup_rpl(sc->ds));
+ savesegment(es, cur);
+- if ((sc->es | 0x03) != cur)
+- loadsegment(es, sc->es | 0x03);
++ if (fixup_rpl(sc->es) != cur)
++ loadsegment(es, fixup_rpl(sc->es));
+ }
+
+ #define sigset32_t compat_sigset_t
+@@ -105,18 +135,12 @@ static bool ia32_restore_sigcontext(struct pt_regs *regs,
+ regs->orig_ax = -1;
+
+ #ifdef CONFIG_IA32_EMULATION
+- /*
+- * Reload fs and gs if they have changed in the signal
+- * handler. This does not handle long fs/gs base changes in
+- * the handler, but does not clobber them at least in the
+- * normal case.
+- */
+ reload_segments(&sc);
+ #else
+- loadsegment(gs, sc.gs);
+- regs->fs = sc.fs;
+- regs->es = sc.es;
+- regs->ds = sc.ds;
++ loadsegment(gs, fixup_rpl(sc.gs));
++ regs->fs = fixup_rpl(sc.fs);
++ regs->es = fixup_rpl(sc.es);
++ regs->ds = fixup_rpl(sc.ds);
+ #endif
+
+ return fpu__restore_sig(compat_ptr(sc.fpstate), 1);
+--
+2.39.5
+
--- /dev/null
+From d6588cee343ec45cd81eeed7608c0694ef031e7d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 19:37:32 +0000
+Subject: x86/mm: Clear _PAGE_DIRTY for kernel mappings when we clear _PAGE_RW
+
+From: Matthew Wilcox (Oracle) <willy@infradead.org>
+
+[ Upstream commit c1fcf41cf37f7a3fd3bbf6f0c04aba3ea4258888 ]
+
+The bit pattern of _PAGE_DIRTY set and _PAGE_RW clear is used to mark
+shadow stacks. This is currently checked for in mk_pte() but not
+pfn_pte(). If we add the check to pfn_pte(), it catches vfree()
+calling set_direct_map_invalid_noflush() which calls
+__change_page_attr() which loads the old protection bits from the
+PTE, clears the specified bits and uses pfn_pte() to construct the
+new PTE.
+
+We should, therefore, for kernel mappings, clear the _PAGE_DIRTY bit
+consistently whenever we clear _PAGE_RW. I opted to do it in the
+callers in case we want to use __change_page_attr() to create shadow
+stacks inside the kernel at some point in the future. Arguably, we
+might also want to clear _PAGE_ACCESSED here.
+
+Note that the 3 functions involved:
+
+ __set_pages_np()
+ kernel_map_pages_in_pgd()
+ kernel_unmap_pages_in_pgd()
+
+Only ever manipulate non-swappable kernel mappings, so maintaining
+the DIRTY:1|RW:0 special pattern for shadow stacks and DIRTY:0
+pattern for non-shadow-stack entries can be maintained consistently
+and doesn't result in the unintended clearing of a live dirty bit
+that could corrupt (destroy) dirty bit information for user mappings.
+
+Reported-by: kernel test robot <oliver.sang@intel.com>
+Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
+Link: https://lore.kernel.org/r/174051422675.10177.13226545170101706336.tip-bot2@tip-bot2
+Closes: https://lore.kernel.org/oe-lkp/202502241646.719f4651-lkp@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/mm/pat/set_memory.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
+index 44f7b2ea6a073..69ceb967d73e9 100644
+--- a/arch/x86/mm/pat/set_memory.c
++++ b/arch/x86/mm/pat/set_memory.c
+@@ -2422,7 +2422,7 @@ static int __set_pages_np(struct page *page, int numpages)
+ .pgd = NULL,
+ .numpages = numpages,
+ .mask_set = __pgprot(0),
+- .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW),
++ .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY),
+ .flags = CPA_NO_CHECK_ALIAS };
+
+ /*
+@@ -2501,7 +2501,7 @@ int __init kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, unsigned long address,
+ .pgd = pgd,
+ .numpages = numpages,
+ .mask_set = __pgprot(0),
+- .mask_clr = __pgprot(~page_flags & (_PAGE_NX|_PAGE_RW)),
++ .mask_clr = __pgprot(~page_flags & (_PAGE_NX|_PAGE_RW|_PAGE_DIRTY)),
+ .flags = CPA_NO_CHECK_ALIAS,
+ };
+
+@@ -2544,7 +2544,7 @@ int __init kernel_unmap_pages_in_pgd(pgd_t *pgd, unsigned long address,
+ .pgd = pgd,
+ .numpages = numpages,
+ .mask_set = __pgprot(0),
+- .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW),
++ .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY),
+ .flags = CPA_NO_CHECK_ALIAS,
+ };
+
+--
+2.39.5
+
--- /dev/null
+From 8e1fbc0ef68e8d7e62211c000c46c6342d61eee7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Oct 2024 14:14:55 +0300
+Subject: x86/mm/ident_map: Fix theoretical virtual address overflow to zero
+
+From: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+
+[ Upstream commit f666c92090a41ac5524dade63ff96b3adcf8c2ab ]
+
+The current calculation of the 'next' virtual address in the
+page table initialization functions in arch/x86/mm/ident_map.c
+doesn't protect against wrapping to zero.
+
+This is a theoretical issue that cannot happen currently,
+the problematic case is possible only if the user sets a
+high enough x86_mapping_info::offset value - which no
+current code in the upstream kernel does.
+
+( The wrapping to zero only occurs if the top PGD entry is accessed.
+ There are no such users upstream. Only hibernate_64.c uses
+ x86_mapping_info::offset, and it operates on the direct mapping
+ range, which is not the top PGD entry. )
+
+Should such an overflow happen, it can result in page table
+corruption and a hang.
+
+To future-proof this code, replace the manual 'next' calculation
+with p?d_addr_end() which handles wrapping correctly.
+
+[ Backporter's note: there's no need to backport this patch. ]
+
+Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Reviewed-by: Kai Huang <kai.huang@intel.com>
+Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
+Cc: Andy Lutomirski <luto@kernel.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Link: https://lore.kernel.org/r/20241016111458.846228-2-kirill.shutemov@linux.intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/mm/ident_map.c | 14 +++-----------
+ 1 file changed, 3 insertions(+), 11 deletions(-)
+
+diff --git a/arch/x86/mm/ident_map.c b/arch/x86/mm/ident_map.c
+index 5ab7bd2f1983c..bd5d101c5c379 100644
+--- a/arch/x86/mm/ident_map.c
++++ b/arch/x86/mm/ident_map.c
+@@ -101,9 +101,7 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
+ pmd_t *pmd;
+ bool use_gbpage;
+
+- next = (addr & PUD_MASK) + PUD_SIZE;
+- if (next > end)
+- next = end;
++ next = pud_addr_end(addr, end);
+
+ /* if this is already a gbpage, this portion is already mapped */
+ if (pud_leaf(*pud))
+@@ -154,10 +152,7 @@ static int ident_p4d_init(struct x86_mapping_info *info, p4d_t *p4d_page,
+ p4d_t *p4d = p4d_page + p4d_index(addr);
+ pud_t *pud;
+
+- next = (addr & P4D_MASK) + P4D_SIZE;
+- if (next > end)
+- next = end;
+-
++ next = p4d_addr_end(addr, end);
+ if (p4d_present(*p4d)) {
+ pud = pud_offset(p4d, 0);
+ result = ident_pud_init(info, pud, addr, next);
+@@ -199,10 +194,7 @@ int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
+ pgd_t *pgd = pgd_page + pgd_index(addr);
+ p4d_t *p4d;
+
+- next = (addr & PGDIR_MASK) + PGDIR_SIZE;
+- if (next > end)
+- next = end;
+-
++ next = pgd_addr_end(addr, end);
+ if (pgd_present(*pgd)) {
+ p4d = p4d_offset(pgd, 0);
+ result = ident_p4d_init(info, p4d, addr, next);
+--
+2.39.5
+
--- /dev/null
+From 329b913cc69f9780a4d5f3c4b097d3c579b544e5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Feb 2025 15:06:58 +0100
+Subject: x86/percpu: Disable named address spaces for UBSAN_BOOL with KASAN
+ for GCC < 14.2
+
+From: Uros Bizjak <ubizjak@gmail.com>
+
+[ Upstream commit b6762467a09ba8838c499e4f36561e82fc608ed1 ]
+
+GCC < 14.2 does not correctly propagate address space qualifiers
+with -fsanitize=bool,enum. Together with address sanitizer then
+causes that load to be sanitized.
+
+Disable named address spaces for GCC < 14.2 when both, UBSAN_BOOL
+and KASAN are enabled.
+
+Reported-by: Matt Fleming <matt@readmodwrite.com>
+Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Link: https://lore.kernel.org/r/20250227140715.2276353-1-ubizjak@gmail.com
+Closes: https://lore.kernel.org/lkml/20241213190119.3449103-1-matt@readmodwrite.com/
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/Kconfig | 20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index db38d2b9b7886..e54da3b4d334e 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -2434,18 +2434,20 @@ config CC_HAS_NAMED_AS
+ def_bool $(success,echo 'int __seg_fs fs; int __seg_gs gs;' | $(CC) -x c - -S -o /dev/null)
+ depends on CC_IS_GCC
+
++#
++# -fsanitize=kernel-address (KASAN) and -fsanitize=thread (KCSAN)
++# are incompatible with named address spaces with GCC < 13.3
++# (see GCC PR sanitizer/111736 and also PR sanitizer/115172).
++#
++
+ config CC_HAS_NAMED_AS_FIXED_SANITIZERS
+- def_bool CC_IS_GCC && GCC_VERSION >= 130300
++ def_bool y
++ depends on !(KASAN || KCSAN) || GCC_VERSION >= 130300
++ depends on !(UBSAN_BOOL && KASAN) || GCC_VERSION >= 140200
+
+ config USE_X86_SEG_SUPPORT
+- def_bool y
+- depends on CC_HAS_NAMED_AS
+- #
+- # -fsanitize=kernel-address (KASAN) and -fsanitize=thread
+- # (KCSAN) are incompatible with named address spaces with
+- # GCC < 13.3 - see GCC PR sanitizer/111736.
+- #
+- depends on !(KASAN || KCSAN) || CC_HAS_NAMED_AS_FIXED_SANITIZERS
++ def_bool CC_HAS_NAMED_AS
++ depends on CC_HAS_NAMED_AS_FIXED_SANITIZERS
+
+ config CC_HAS_SLS
+ def_bool $(cc-option,-mharden-sls=all)
+--
+2.39.5
+
--- /dev/null
+From 2a378fc9a256f850377c6f9c15a3e96e875ce7e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Mar 2025 15:22:38 -0700
+Subject: xen/mcelog: Add __nonstring annotations for unterminated strings
+
+From: Kees Cook <kees@kernel.org>
+
+[ Upstream commit 1c3dfc7c6b0f551fdca3f7c1f1e4c73be8adb17d ]
+
+When a character array without a terminating NUL character has a static
+initializer, GCC 15's -Wunterminated-string-initialization will only
+warn if the array lacks the "nonstring" attribute[1]. Mark the arrays
+with __nonstring to and correctly identify the char array as "not a C
+string" and thereby eliminate the warning.
+
+Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117178 [1]
+Cc: Juergen Gross <jgross@suse.com>
+Cc: Stefano Stabellini <sstabellini@kernel.org>
+Cc: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
+Cc: xen-devel@lists.xenproject.org
+Signed-off-by: Kees Cook <kees@kernel.org>
+Acked-by: Juergen Gross <jgross@suse.com>
+Message-ID: <20250310222234.work.473-kees@kernel.org>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/xen/interface/xen-mca.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/xen/interface/xen-mca.h b/include/xen/interface/xen-mca.h
+index 464aa6b3a5f92..1c9afbe8cc260 100644
+--- a/include/xen/interface/xen-mca.h
++++ b/include/xen/interface/xen-mca.h
+@@ -372,7 +372,7 @@ struct xen_mce {
+ #define XEN_MCE_LOG_LEN 32
+
+ struct xen_mce_log {
+- char signature[12]; /* "MACHINECHECK" */
++ char signature[12] __nonstring; /* "MACHINECHECK" */
+ unsigned len; /* = XEN_MCE_LOG_LEN */
+ unsigned next;
+ unsigned flags;
+--
+2.39.5
+
--- /dev/null
+From 127c87c979a107778864ec194e3ab139fbef2d8c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Mar 2025 08:38:43 +0100
+Subject: zstd: Increase DYNAMIC_BMI2 GCC version cutoff from 4.8 to 11.0 to
+ work around compiler segfault
+
+From: Ingo Molnar <mingo@kernel.org>
+
+[ Upstream commit 1400c87e6cac47eb243f260352c854474d9a9073 ]
+
+Due to pending percpu improvements in -next, GCC9 and GCC10 are
+crashing during the build with:
+
+ lib/zstd/compress/huf_compress.c:1033:1: internal compiler error: Segmentation fault
+ 1033 | {
+ | ^
+ Please submit a full bug report,
+ with preprocessed source if appropriate.
+ See <file:///usr/share/doc/gcc-9/README.Bugs> for instructions.
+
+The DYNAMIC_BMI2 feature is a known-challenging feature of
+the ZSTD library, with an existing GCC quirk turning it off
+for GCC versions below 4.8.
+
+Increase the DYNAMIC_BMI2 version cutoff to GCC 11.0 - GCC 10.5
+is the last version known to crash.
+
+Reported-by: Michael Kelley <mhklinux@outlook.com>
+Debugged-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Cc: https://lore.kernel.org/r/SN6PR02MB415723FBCD79365E8D72CA5FD4D82@SN6PR02MB4157.namprd02.prod.outlook.com
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ lib/zstd/common/portability_macros.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/zstd/common/portability_macros.h b/lib/zstd/common/portability_macros.h
+index 0e3b2c0a527db..0dde8bf56595e 100644
+--- a/lib/zstd/common/portability_macros.h
++++ b/lib/zstd/common/portability_macros.h
+@@ -55,7 +55,7 @@
+ #ifndef DYNAMIC_BMI2
+ #if ((defined(__clang__) && __has_attribute(__target__)) \
+ || (defined(__GNUC__) \
+- && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \
++ && (__GNUC__ >= 11))) \
+ && (defined(__x86_64__) || defined(_M_X64)) \
+ && !defined(__BMI2__)
+ # define DYNAMIC_BMI2 1
+--
+2.39.5
+