From: Sasha Levin Date: Thu, 22 May 2025 20:52:55 +0000 (-0400) Subject: Fixes for 6.12 X-Git-Tag: v6.12.31~98 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bfd622fb24a6b3f347b804b7a6dbc9d6b78e8b4f;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.12 Signed-off-by: Sasha Levin --- diff --git a/queue-6.12/__legitimize_mnt-check-for-mnt_sync_umount-should-be.patch b/queue-6.12/__legitimize_mnt-check-for-mnt_sync_umount-should-be.patch new file mode 100644 index 0000000000..18f1314ed2 --- /dev/null +++ b/queue-6.12/__legitimize_mnt-check-for-mnt_sync_umount-should-be.patch @@ -0,0 +1,48 @@ +From c22ca5c1c175a73972fc0d5d3829041004ad95cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 27 Apr 2025 15:41:51 -0400 +Subject: __legitimize_mnt(): check for MNT_SYNC_UMOUNT should be under + mount_lock + +From: Al Viro + +[ Upstream commit 250cf3693060a5f803c5f1ddc082bb06b16112a9 ] + +... or we risk stealing final mntput from sync umount - raising mnt_count +after umount(2) has verified that victim is not busy, but before it +has set MNT_SYNC_UMOUNT; in that case __legitimize_mnt() doesn't see +that it's safe to quietly undo mnt_count increment and leaves dropping +the reference to caller, where it'll be a full-blown mntput(). + +Check under mount_lock is needed; leaving the current one done before +taking that makes no sense - it's nowhere near common enough to bother +with. + +Reviewed-by: Christian Brauner +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + fs/namespace.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/fs/namespace.c b/fs/namespace.c +index c3c1e8c644f2e..c1ac585e41e36 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -750,12 +750,8 @@ int __legitimize_mnt(struct vfsmount *bastard, unsigned seq) + smp_mb(); // see mntput_no_expire() and do_umount() + if (likely(!read_seqretry(&mount_lock, seq))) + return 0; +- if (bastard->mnt_flags & MNT_SYNC_UMOUNT) { +- mnt_add_count(mnt, -1); +- return 1; +- } + lock_mount_hash(); +- if (unlikely(bastard->mnt_flags & MNT_DOOMED)) { ++ if (unlikely(bastard->mnt_flags & (MNT_SYNC_UMOUNT | MNT_DOOMED))) { + mnt_add_count(mnt, -1); + unlock_mount_hash(); + return 1; +-- +2.39.5 + diff --git a/queue-6.12/accel-qaic-mask-out-sr-iov-pci-resources.patch b/queue-6.12/accel-qaic-mask-out-sr-iov-pci-resources.patch new file mode 100644 index 0000000000..3690f5b32e --- /dev/null +++ b/queue-6.12/accel-qaic-mask-out-sr-iov-pci-resources.patch @@ -0,0 +1,42 @@ +From a8af08d06f15bbb170b2cec6c095584dfd414da7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jan 2025 10:09:41 -0700 +Subject: accel/qaic: Mask out SR-IOV PCI resources + +From: Youssef Samir + +[ Upstream commit 8685520474bfc0fe4be83c3cbfe3fb3e1ca1514a ] + +During the initialization of the qaic device, pci_select_bars() is +used to fetch a bitmask of the BARs exposed by the device. On devices +that have Virtual Functions capabilities, the bitmask includes SR-IOV +BARs. + +Use a mask to filter out SR-IOV BARs if they exist. + +Signed-off-by: Youssef Samir +Reviewed-by: Jeffrey Hugo +Signed-off-by: Jeffrey Hugo +Reviewed-by: Lizhi Hou +Link: https://patchwork.freedesktop.org/patch/msgid/20250117170943.2643280-6-quic_jhugo@quicinc.com +Signed-off-by: Sasha Levin +--- + drivers/accel/qaic/qaic_drv.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/accel/qaic/qaic_drv.c b/drivers/accel/qaic/qaic_drv.c +index f139c564eadf9..10e711c96a670 100644 +--- a/drivers/accel/qaic/qaic_drv.c ++++ b/drivers/accel/qaic/qaic_drv.c +@@ -432,7 +432,7 @@ static int init_pci(struct qaic_device *qdev, struct pci_dev *pdev) + int bars; + int ret; + +- bars = pci_select_bars(pdev, IORESOURCE_MEM); ++ bars = pci_select_bars(pdev, IORESOURCE_MEM) & 0x3f; + + /* make sure the device has the expected BARs */ + if (bars != (BIT(0) | BIT(2) | BIT(4))) { +-- +2.39.5 + diff --git a/queue-6.12/acpi-hed-always-initialize-before-evged.patch b/queue-6.12/acpi-hed-always-initialize-before-evged.patch new file mode 100644 index 0000000000..998506b0bb --- /dev/null +++ b/queue-6.12/acpi-hed-always-initialize-before-evged.patch @@ -0,0 +1,67 @@ +From 1faf97e59e93674e451ac5f07225be41a50453ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 14:34:08 +0800 +Subject: ACPI: HED: Always initialize before evged + +From: Xiaofei Tan + +[ Upstream commit cccf6ee090c8c133072d5d5b52ae25f3bc907a16 ] + +When the HED driver is built-in, it initializes after evged because they +both are at the same initcall level, so the initialization ordering +depends on the Makefile order. However, this prevents RAS records +coming in between the evged driver initialization and the HED driver +initialization from being handled. + +If the number of such RAS records is above the APEI HEST error source +number, the HEST resources may be exhausted, and that may affect +subsequent RAS error reporting. + +To fix this issue, change the initcall level of HED to subsys_initcall +and prevent the driver from being built as a module by changing ACPI_HED +in Kconfig from "tristate" to "bool". + +Signed-off-by: Xiaofei Tan +Link: https://patch.msgid.link/20250212063408.927666-1-tanxiaofei@huawei.com +[ rjw: Changelog edits ] +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/Kconfig | 2 +- + drivers/acpi/hed.c | 7 ++++++- + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig +index d67f63d93b2ab..89fa569d63702 100644 +--- a/drivers/acpi/Kconfig ++++ b/drivers/acpi/Kconfig +@@ -443,7 +443,7 @@ config ACPI_SBS + the modules will be called sbs and sbshc. + + config ACPI_HED +- tristate "Hardware Error Device" ++ bool "Hardware Error Device" + help + This driver supports the Hardware Error Device (PNP0C33), + which is used to report some hardware errors notified via +diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c +index 7652515a6be1e..3499f86c411e3 100644 +--- a/drivers/acpi/hed.c ++++ b/drivers/acpi/hed.c +@@ -80,7 +80,12 @@ static struct acpi_driver acpi_hed_driver = { + .remove = acpi_hed_remove, + }, + }; +-module_acpi_driver(acpi_hed_driver); ++ ++static int __init acpi_hed_driver_init(void) ++{ ++ return acpi_bus_register_driver(&acpi_hed_driver); ++} ++subsys_initcall(acpi_hed_driver_init); + + MODULE_AUTHOR("Huang Ying"); + MODULE_DESCRIPTION("ACPI Hardware Error Device Driver"); +-- +2.39.5 + diff --git a/queue-6.12/acpi-pnp-add-intel-oc-watchdog-ids-to-non-pnp-device.patch b/queue-6.12/acpi-pnp-add-intel-oc-watchdog-ids-to-non-pnp-device.patch new file mode 100644 index 0000000000..1625100157 --- /dev/null +++ b/queue-6.12/acpi-pnp-add-intel-oc-watchdog-ids-to-non-pnp-device.patch @@ -0,0 +1,46 @@ +From 0c9eaa40708f780c7ecd4058b50ba6a4faa16a99 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 10:55:07 +0000 +Subject: ACPI: PNP: Add Intel OC Watchdog IDs to non-PNP device list + +From: Diogo Ivo + +[ Upstream commit f06777cf2bbc21dd8c71d6e3906934e56b4e18e4 ] + +Intel Over-Clocking Watchdogs are described in ACPI tables by both the +generic PNP0C02 _CID and their ACPI _HID. The presence of the _CID then +causes the PNP scan handler to attach to the watchdog, preventing the +actual watchdog driver from binding. Address this by adding the ACPI +_HIDs to the list of non-PNP devices, so that the PNP scan handler is +bypassed. + +Note that these watchdogs can be described by multiple _HIDs for what +seems to be identical hardware. This commit is not a complete list of +all the possible watchdog ACPI _HIDs. + +Signed-off-by: Diogo Ivo +Link: https://patch.msgid.link/20250317-ivo-intel_oc_wdt-v3-2-32c396f4eefd@siemens.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/acpi_pnp.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c +index 01abf26764b00..3f5a1840f5733 100644 +--- a/drivers/acpi/acpi_pnp.c ++++ b/drivers/acpi/acpi_pnp.c +@@ -355,8 +355,10 @@ static bool acpi_pnp_match(const char *idstr, const struct acpi_device_id **matc + * device represented by it. + */ + static const struct acpi_device_id acpi_nonpnp_device_ids[] = { ++ {"INT3F0D"}, + {"INTC1080"}, + {"INTC1081"}, ++ {"INTC1099"}, + {""}, + }; + +-- +2.39.5 + diff --git a/queue-6.12/alsa-hda-realtek-add-quirk-for-hp-spectre-x360-15-df.patch b/queue-6.12/alsa-hda-realtek-add-quirk-for-hp-spectre-x360-15-df.patch new file mode 100644 index 0000000000..cf713978e7 --- /dev/null +++ b/queue-6.12/alsa-hda-realtek-add-quirk-for-hp-spectre-x360-15-df.patch @@ -0,0 +1,106 @@ +From ef8e3ec3ff413e4b736341071bdd811cc594a536 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 27 Apr 2025 10:10:34 +0200 +Subject: ALSA: hda/realtek: Add quirk for HP Spectre x360 15-df1xxx + +From: Takashi Iwai + +[ Upstream commit be0c40da888840fe91b45474cb70779e6cbaf7ca ] + +HP Spectre x360 15-df1xxx with SSID 13c:863e requires similar +workarounds that were applied to another HP Spectre x360 models; +it has a mute LED only, no micmute LEDs, and needs the speaker GPIO +seup. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=220054 +Link: https://patch.msgid.link/20250427081035.11567-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 42 +++++++++++++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 0b243adac8cf4..015c66b9003a4 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -6965,6 +6965,41 @@ static void alc285_fixup_hp_spectre_x360_eb1(struct hda_codec *codec, + } + } + ++/* GPIO1 = amplifier on/off */ ++static void alc285_fixup_hp_spectre_x360_df1(struct hda_codec *codec, ++ const struct hda_fixup *fix, ++ int action) ++{ ++ struct alc_spec *spec = codec->spec; ++ static const hda_nid_t conn[] = { 0x02 }; ++ static const struct hda_pintbl pincfgs[] = { ++ { 0x14, 0x90170110 }, /* front/high speakers */ ++ { 0x17, 0x90170130 }, /* back/bass speakers */ ++ { } ++ }; ++ ++ // enable mute led ++ alc285_fixup_hp_mute_led_coefbit(codec, fix, action); ++ ++ switch (action) { ++ case HDA_FIXUP_ACT_PRE_PROBE: ++ /* needed for amp of back speakers */ ++ spec->gpio_mask |= 0x01; ++ spec->gpio_dir |= 0x01; ++ snd_hda_apply_pincfgs(codec, pincfgs); ++ /* share DAC to have unified volume control */ ++ snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn), conn); ++ snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn); ++ break; ++ case HDA_FIXUP_ACT_INIT: ++ /* need to toggle GPIO to enable the amp of back speakers */ ++ alc_update_gpio_data(codec, 0x01, true); ++ msleep(100); ++ alc_update_gpio_data(codec, 0x01, false); ++ break; ++ } ++} ++ + static void alc285_fixup_hp_spectre_x360(struct hda_codec *codec, + const struct hda_fixup *fix, int action) + { +@@ -7730,6 +7765,7 @@ enum { + ALC280_FIXUP_HP_9480M, + ALC245_FIXUP_HP_X360_AMP, + ALC285_FIXUP_HP_SPECTRE_X360_EB1, ++ ALC285_FIXUP_HP_SPECTRE_X360_DF1, + ALC285_FIXUP_HP_ENVY_X360, + ALC288_FIXUP_DELL_HEADSET_MODE, + ALC288_FIXUP_DELL1_MIC_NO_PRESENCE, +@@ -9798,6 +9834,10 @@ static const struct hda_fixup alc269_fixups[] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc285_fixup_hp_spectre_x360_eb1 + }, ++ [ALC285_FIXUP_HP_SPECTRE_X360_DF1] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc285_fixup_hp_spectre_x360_df1 ++ }, + [ALC285_FIXUP_HP_ENVY_X360] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc285_fixup_hp_envy_x360, +@@ -10515,6 +10555,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x86c1, "HP Laptop 15-da3001TU", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), + SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO), + SND_PCI_QUIRK(0x103c, 0x86e7, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1), ++ SND_PCI_QUIRK(0x103c, 0x863e, "HP Spectre x360 15-df1xxx", ALC285_FIXUP_HP_SPECTRE_X360_DF1), + SND_PCI_QUIRK(0x103c, 0x86e8, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1), + SND_PCI_QUIRK(0x103c, 0x86f9, "HP Spectre x360 13-aw0xxx", ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x8716, "HP Elite Dragonfly G2 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), +@@ -11404,6 +11445,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = { + {.id = ALC295_FIXUP_HP_OMEN, .name = "alc295-hp-omen"}, + {.id = ALC285_FIXUP_HP_SPECTRE_X360, .name = "alc285-hp-spectre-x360"}, + {.id = ALC285_FIXUP_HP_SPECTRE_X360_EB1, .name = "alc285-hp-spectre-x360-eb1"}, ++ {.id = ALC285_FIXUP_HP_SPECTRE_X360_DF1, .name = "alc285-hp-spectre-x360-df1"}, + {.id = ALC285_FIXUP_HP_ENVY_X360, .name = "alc285-hp-envy-x360"}, + {.id = ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP, .name = "alc287-ideapad-bass-spk-amp"}, + {.id = ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN, .name = "alc287-yoga9-bass-spk-pin"}, +-- +2.39.5 + diff --git a/queue-6.12/alsa-hda-realtek-enable-pc-beep-passthrough-for-hp-e.patch b/queue-6.12/alsa-hda-realtek-enable-pc-beep-passthrough-for-hp-e.patch new file mode 100644 index 0000000000..4878d330ba --- /dev/null +++ b/queue-6.12/alsa-hda-realtek-enable-pc-beep-passthrough-for-hp-e.patch @@ -0,0 +1,177 @@ +From 6435ab9070e4d022a7da74a1481d193e6fea3c05 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Feb 2025 22:31:03 +0100 +Subject: ALSA: hda/realtek: Enable PC beep passthrough for HP EliteBook 855 G7 + +From: Maciej S. Szmigiero + +[ Upstream commit aa85822c611aef7cd4dc17d27121d43e21bb82f0 ] + +PC speaker works well on this platform in BIOS and in Linux until sound +card drivers are loaded. Then it stops working. + +There seems to be a beep generator node at 0x1a in this CODEC +(ALC269_TYPE_ALC215) but it seems to be only connected to capture mixers +at nodes 0x22 and 0x23. +If I unmute the mixer input for 0x1a at node 0x23 and start recording +from its "ALC285 Analog" capture device I can clearly hear beeps in that +recording. + +So the beep generator is indeed working properly, however I wasn't able to +figure out any way to connect it to speakers. + +However, the bits in the "Passthrough Control" register (0x36) seems to +work at least partially: by zeroing "B" and "h" and setting "S" I can at +least make the PIT PC speaker output appear either in this laptop speakers +or headphones (depending on whether they are connected or not). + +There are some caveats, however: +* If the CODEC gets runtime-suspended the beeps stop so it needs HDA beep +device for keeping it awake during beeping. + +* If the beep generator node is generating any beep the PC beep passthrough +seems to be temporarily inhibited, so the HDA beep device has to be +prevented from using the actual beep generator node - but the beep device +is still necessary due to the previous point. + +* In contrast with other platforms here beep amplification has to be +disabled otherwise the beeps output are WAY louder than they were on pure +BIOS setup. + +Unless someone (from Realtek probably) knows how to make the beep generator +node output appear in speakers / headphones using PC beep passthrough seems +to be the only way to make PC speaker beeping actually work on this +platform. + +Signed-off-by: Maciej S. Szmigiero +Acked-by: kailang@realtek.com +Link: https://patch.msgid.link/7461f695b4daed80f2fc4b1463ead47f04f9ad05.1739741254.git.mail@maciej.szmigiero.name +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + include/sound/hda_codec.h | 1 + + sound/pci/hda/hda_beep.c | 15 +++++++++------ + sound/pci/hda/patch_realtek.c | 34 +++++++++++++++++++++++++++++++++- + 3 files changed, 43 insertions(+), 7 deletions(-) + +diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h +index 575e55aa08ca9..c1fe6290d04dc 100644 +--- a/include/sound/hda_codec.h ++++ b/include/sound/hda_codec.h +@@ -195,6 +195,7 @@ struct hda_codec { + /* beep device */ + struct hda_beep *beep; + unsigned int beep_mode; ++ bool beep_just_power_on; + + /* widget capabilities cache */ + u32 *wcaps; +diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c +index e51d475725576..13a7d92e8d8d0 100644 +--- a/sound/pci/hda/hda_beep.c ++++ b/sound/pci/hda/hda_beep.c +@@ -31,8 +31,9 @@ static void generate_tone(struct hda_beep *beep, int tone) + beep->power_hook(beep, true); + beep->playing = 1; + } +- snd_hda_codec_write(codec, beep->nid, 0, +- AC_VERB_SET_BEEP_CONTROL, tone); ++ if (!codec->beep_just_power_on) ++ snd_hda_codec_write(codec, beep->nid, 0, ++ AC_VERB_SET_BEEP_CONTROL, tone); + if (!tone && beep->playing) { + beep->playing = 0; + if (beep->power_hook) +@@ -212,10 +213,12 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) + struct hda_beep *beep; + int err; + +- if (!snd_hda_get_bool_hint(codec, "beep")) +- return 0; /* disabled explicitly by hints */ +- if (codec->beep_mode == HDA_BEEP_MODE_OFF) +- return 0; /* disabled by module option */ ++ if (!codec->beep_just_power_on) { ++ if (!snd_hda_get_bool_hint(codec, "beep")) ++ return 0; /* disabled explicitly by hints */ ++ if (codec->beep_mode == HDA_BEEP_MODE_OFF) ++ return 0; /* disabled by module option */ ++ } + + beep = kzalloc(sizeof(*beep), GFP_KERNEL); + if (beep == NULL) +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index db72c5fce9d18..0b243adac8cf4 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -28,6 +28,7 @@ + #include + #include "hda_local.h" + #include "hda_auto_parser.h" ++#include "hda_beep.h" + #include "hda_jack.h" + #include "hda_generic.h" + #include "hda_component.h" +@@ -7036,6 +7037,30 @@ static void alc285_fixup_hp_envy_x360(struct hda_codec *codec, + } + } + ++static void alc285_fixup_hp_beep(struct hda_codec *codec, ++ const struct hda_fixup *fix, int action) ++{ ++ if (action == HDA_FIXUP_ACT_PRE_PROBE) { ++ codec->beep_just_power_on = true; ++ } else if (action == HDA_FIXUP_ACT_INIT) { ++#ifdef CONFIG_SND_HDA_INPUT_BEEP ++ /* ++ * Just enable loopback to internal speaker and headphone jack. ++ * Disable amplification to get about the same beep volume as ++ * was on pure BIOS setup before loading the driver. ++ */ ++ alc_update_coef_idx(codec, 0x36, 0x7070, BIT(13)); ++ ++ snd_hda_enable_beep_device(codec, 1); ++ ++#if !IS_ENABLED(CONFIG_INPUT_PCSPKR) ++ dev_warn_once(hda_codec_dev(codec), ++ "enable CONFIG_INPUT_PCSPKR to get PC beeps\n"); ++#endif ++#endif ++ } ++} ++ + /* for hda_fixup_thinkpad_acpi() */ + #include "thinkpad_helper.c" + +@@ -7806,6 +7831,7 @@ enum { + ALC285_FIXUP_HP_GPIO_LED, + ALC285_FIXUP_HP_MUTE_LED, + ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED, ++ ALC285_FIXUP_HP_BEEP_MICMUTE_LED, + ALC236_FIXUP_HP_MUTE_LED_COEFBIT2, + ALC236_FIXUP_HP_GPIO_LED, + ALC236_FIXUP_HP_MUTE_LED, +@@ -9395,6 +9421,12 @@ static const struct hda_fixup alc269_fixups[] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc285_fixup_hp_spectre_x360_mute_led, + }, ++ [ALC285_FIXUP_HP_BEEP_MICMUTE_LED] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc285_fixup_hp_beep, ++ .chained = true, ++ .chain_id = ALC285_FIXUP_HP_MUTE_LED, ++ }, + [ALC236_FIXUP_HP_MUTE_LED_COEFBIT2] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc236_fixup_hp_mute_led_coefbit2, +@@ -10493,7 +10525,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x8730, "HP ProBook 445 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), + SND_PCI_QUIRK(0x103c, 0x8735, "HP ProBook 435 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), + SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_AMP_INIT), +- SND_PCI_QUIRK(0x103c, 0x8760, "HP", ALC285_FIXUP_HP_MUTE_LED), ++ SND_PCI_QUIRK(0x103c, 0x8760, "HP EliteBook 8{4,5}5 G7", ALC285_FIXUP_HP_BEEP_MICMUTE_LED), + SND_PCI_QUIRK(0x103c, 0x876e, "HP ENVY x360 Convertible 13-ay0xxx", ALC245_FIXUP_HP_X360_MUTE_LEDS), + SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x877d, "HP", ALC236_FIXUP_HP_MUTE_LED), +-- +2.39.5 + diff --git a/queue-6.12/alsa-seq-improve-data-consistency-at-polling.patch b/queue-6.12/alsa-seq-improve-data-consistency-at-polling.patch new file mode 100644 index 0000000000..25618aa262 --- /dev/null +++ b/queue-6.12/alsa-seq-improve-data-consistency-at-polling.patch @@ -0,0 +1,70 @@ +From 260eab4705084b13600806b3b93c6cbf5cca9bd8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Mar 2025 09:42:42 +0100 +Subject: ALSA: seq: Improve data consistency at polling + +From: Takashi Iwai + +[ Upstream commit e3cd33ab17c33bd8f1a9df66ec83a15dd8f7afbb ] + +snd_seq_poll() calls snd_seq_write_pool_allocated() that reads out a +field in client->pool object, while it can be updated concurrently via +ioctls, as reported by syzbot. The data race itself is harmless, as +it's merely a poll() call, and the state is volatile. OTOH, the read +out of poll object info from the caller side is fragile, and we can +leave it better in snd_seq_pool_poll_wait() alone. + +A similar pattern is seen in snd_seq_kernel_client_write_poll(), too, +which is called from the OSS sequencer. + +This patch drops the pool checks from the caller side and add the +pool->lock in snd_seq_pool_poll_wait() for better data consistency. + +Reported-by: syzbot+2d373c9936c00d7e120c@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/67c88903.050a0220.15b4b9.0028.GAE@google.com +Link: https://patch.msgid.link/20250307084246.29271-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/core/seq/seq_clientmgr.c | 5 +---- + sound/core/seq/seq_memory.c | 1 + + 2 files changed, 2 insertions(+), 4 deletions(-) + +diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c +index b74de9c0969fc..9e59a97f47472 100644 +--- a/sound/core/seq/seq_clientmgr.c ++++ b/sound/core/seq/seq_clientmgr.c +@@ -1164,8 +1164,7 @@ static __poll_t snd_seq_poll(struct file *file, poll_table * wait) + if (snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_OUTPUT) { + + /* check if data is available in the pool */ +- if (!snd_seq_write_pool_allocated(client) || +- snd_seq_pool_poll_wait(client->pool, file, wait)) ++ if (snd_seq_pool_poll_wait(client->pool, file, wait)) + mask |= EPOLLOUT | EPOLLWRNORM; + } + +@@ -2583,8 +2582,6 @@ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table + if (client == NULL) + return -ENXIO; + +- if (! snd_seq_write_pool_allocated(client)) +- return 1; + if (snd_seq_pool_poll_wait(client->pool, file, wait)) + return 1; + return 0; +diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c +index 20155e3e87c6a..ccde0ca3d2082 100644 +--- a/sound/core/seq/seq_memory.c ++++ b/sound/core/seq/seq_memory.c +@@ -427,6 +427,7 @@ int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file, + poll_table *wait) + { + poll_wait(file, &pool->output_sleep, wait); ++ guard(spinlock_irq)(&pool->lock); + return snd_seq_output_ok(pool); + } + +-- +2.39.5 + diff --git a/queue-6.12/alsa-usb-audio-fix-duplicated-name-in-midi-substream.patch b/queue-6.12/alsa-usb-audio-fix-duplicated-name-in-midi-substream.patch new file mode 100644 index 0000000000..4e708b250f --- /dev/null +++ b/queue-6.12/alsa-usb-audio-fix-duplicated-name-in-midi-substream.patch @@ -0,0 +1,78 @@ +From 4bd27235f91f96a1c21431a83445448d2b46e806 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Apr 2025 20:36:15 +0200 +Subject: ALSA: usb-audio: Fix duplicated name in MIDI substream names + +From: Takashi Iwai + +[ Upstream commit 0759e77a6d9bd34a874da73721ce4a7dc6665023 ] + +The MIDI substream name string is constructed from the combination of +the card shortname (which is taken from USB iProduct) and the USB +iJack. The problem is that some devices put the product name to the +iJack field, too. For example, aplaymidi -l output on the Lanchkey MK +49 are like: + + % aplaymidi -l + Port Client name Port name + 44:0 Launchkey MK4 49 Launchkey MK4 49 Launchkey MK4 + 44:1 Launchkey MK4 49 Launchkey MK4 49 Launchkey MK4 + +where the actual iJack name can't be seen because it's truncated due +to the doubly words. + +For resolving those situations, this patch compares the iJack string +with the card shortname, and drops if both start with the same words. +Then the result becomes like: + + % aplaymidi -l + Port Client name Port name + 40:0 Launchkey MK4 49 Launchkey MK4 49 MIDI In + 40:1 Launchkey MK4 49 Launchkey MK4 49 DAW In + +A caveat is that there are some pre-defined names for certain +devices in the driver code, and this workaround shouldn't be applied +to them. Similarly, when the iJack isn't specified, we should skip +this check, too. The patch added those checks in addition to the +string comparison. + +Suggested-by: Paul Davis +Tested-by: Paul Davis +Link: https://lore.kernel.org/CAFa_cKmEDQWcJatbYWi6A58Zg4Ma9_6Nr3k5LhqwyxC-P_kXtw@mail.gmail.com +Link: https://patch.msgid.link/20250429183626.20773-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/usb/midi.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/sound/usb/midi.c b/sound/usb/midi.c +index 826ac870f2469..a792ada18863a 100644 +--- a/sound/usb/midi.c ++++ b/sound/usb/midi.c +@@ -1885,10 +1885,18 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi, + } + + port_info = find_port_info(umidi, number); +- name_format = port_info ? port_info->name : +- (jack_name != default_jack_name ? "%s %s" : "%s %s %d"); +- snprintf(substream->name, sizeof(substream->name), +- name_format, umidi->card->shortname, jack_name, number + 1); ++ if (port_info || jack_name == default_jack_name || ++ strncmp(umidi->card->shortname, jack_name, strlen(umidi->card->shortname)) != 0) { ++ name_format = port_info ? port_info->name : ++ (jack_name != default_jack_name ? "%s %s" : "%s %s %d"); ++ snprintf(substream->name, sizeof(substream->name), ++ name_format, umidi->card->shortname, jack_name, number + 1); ++ } else { ++ /* The manufacturer included the iProduct name in the jack ++ * name, do not use both ++ */ ++ strscpy(substream->name, jack_name); ++ } + + *rsubstream = substream; + } +-- +2.39.5 + diff --git a/queue-6.12/arch-powerpc-perf-check-the-instruction-type-before-.patch b/queue-6.12/arch-powerpc-perf-check-the-instruction-type-before-.patch new file mode 100644 index 0000000000..23f6e0cb62 --- /dev/null +++ b/queue-6.12/arch-powerpc-perf-check-the-instruction-type-before-.patch @@ -0,0 +1,137 @@ +From b3a17a4ab9167f6a5521c013be9e8020c59219e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jan 2025 18:46:20 +0530 +Subject: arch/powerpc/perf: Check the instruction type before creating sample + with perf_mem_data_src + +From: Athira Rajeev + +[ Upstream commit 2ffb26afa64261139e608bf087a0c1fe24d76d4d ] + +perf mem report aborts as below sometimes (during some corner +case) in powerpc: + + # ./perf mem report 1>out + *** stack smashing detected ***: terminated + Aborted (core dumped) + +The backtrace is as below: + __pthread_kill_implementation () + raise () + abort () + __libc_message + __fortify_fail + __stack_chk_fail + hist_entry.lvl_snprintf + __sort__hpp_entry + __hist_entry__snprintf + hists.fprintf + cmd_report + cmd_mem + +Snippet of code which triggers the issue +from tools/perf/util/sort.c + + static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf, + size_t size, unsigned int width) + { + char out[64]; + + perf_mem__lvl_scnprintf(out, sizeof(out), he->mem_info); + return repsep_snprintf(bf, size, "%-*s", width, out); + } + +The value of "out" is filled from perf_mem_data_src value. +Debugging this further showed that for some corner cases, the +value of "data_src" was pointing to wrong value. This resulted +in bigger size of string and causing stack check fail. + +The perf mem data source values are captured in the sample via +isa207_get_mem_data_src function. The initial check is to fetch +the type of sampled instruction. If the type of instruction is +not valid (not a load/store instruction), the function returns. + +Since 'commit e16fd7f2cb1a ("perf: Use sample_flags for data_src")', +data_src field is not initialized by the perf_sample_data_init() +function. If the PMU driver doesn't set the data_src value to zero if +type is not valid, this will result in uninitailised value for data_src. +The uninitailised value of data_src resulted in stack check fail +followed by abort for "perf mem report". + +When requesting for data source information in the sample, the +instruction type is expected to be load or store instruction. +In ISA v3.0, due to hardware limitation, there are corner cases +where the instruction type other than load or store is observed. +In ISA v3.0 and before values "0" and "7" are considered reserved. +In ISA v3.1, value "7" has been used to indicate "larx/stcx". +Drop the sample if instruction type has reserved values for this +field with a ISA version check. Initialize data_src to zero in +isa207_get_mem_data_src if the instruction type is not load/store. + +Reported-by: Disha Goel +Signed-off-by: Athira Rajeev +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250121131621.39054-1-atrajeev@linux.vnet.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/perf/core-book3s.c | 20 ++++++++++++++++++++ + arch/powerpc/perf/isa207-common.c | 4 +++- + 2 files changed, 23 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c +index 42867469752d7..33d726bb99e3d 100644 +--- a/arch/powerpc/perf/core-book3s.c ++++ b/arch/powerpc/perf/core-book3s.c +@@ -2222,6 +2222,10 @@ static struct pmu power_pmu = { + #define PERF_SAMPLE_ADDR_TYPE (PERF_SAMPLE_ADDR | \ + PERF_SAMPLE_PHYS_ADDR | \ + PERF_SAMPLE_DATA_PAGE_SIZE) ++ ++#define SIER_TYPE_SHIFT 15 ++#define SIER_TYPE_MASK (0x7ull << SIER_TYPE_SHIFT) ++ + /* + * A counter has overflowed; update its count and record + * things if requested. Note that interrupts are hard-disabled +@@ -2290,6 +2294,22 @@ static void record_and_restart(struct perf_event *event, unsigned long val, + is_kernel_addr(mfspr(SPRN_SIAR))) + record = 0; + ++ /* ++ * SIER[46-48] presents instruction type of the sampled instruction. ++ * In ISA v3.0 and before values "0" and "7" are considered reserved. ++ * In ISA v3.1, value "7" has been used to indicate "larx/stcx". ++ * Drop the sample if "type" has reserved values for this field with a ++ * ISA version check. ++ */ ++ if (event->attr.sample_type & PERF_SAMPLE_DATA_SRC && ++ ppmu->get_mem_data_src) { ++ val = (regs->dar & SIER_TYPE_MASK) >> SIER_TYPE_SHIFT; ++ if (val == 0 || (val == 7 && !cpu_has_feature(CPU_FTR_ARCH_31))) { ++ record = 0; ++ atomic64_inc(&event->lost_samples); ++ } ++ } ++ + /* + * Finally record data if requested. + */ +diff --git a/arch/powerpc/perf/isa207-common.c b/arch/powerpc/perf/isa207-common.c +index 56301b2bc8ae8..031a2b63c171d 100644 +--- a/arch/powerpc/perf/isa207-common.c ++++ b/arch/powerpc/perf/isa207-common.c +@@ -321,8 +321,10 @@ void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags, + + sier = mfspr(SPRN_SIER); + val = (sier & ISA207_SIER_TYPE_MASK) >> ISA207_SIER_TYPE_SHIFT; +- if (val != 1 && val != 2 && !(val == 7 && cpu_has_feature(CPU_FTR_ARCH_31))) ++ if (val != 1 && val != 2 && !(val == 7 && cpu_has_feature(CPU_FTR_ARCH_31))) { ++ dsrc->val = 0; + return; ++ } + + idx = (sier & ISA207_SIER_LDST_MASK) >> ISA207_SIER_LDST_SHIFT; + sub_idx = (sier & ISA207_SIER_DATA_SRC_MASK) >> ISA207_SIER_DATA_SRC_SHIFT; +-- +2.39.5 + diff --git a/queue-6.12/arm-at91-pm-fix-at91_suspend_finish-for-zq-calibrati.patch b/queue-6.12/arm-at91-pm-fix-at91_suspend_finish-for-zq-calibrati.patch new file mode 100644 index 0000000000..c1edb48e01 --- /dev/null +++ b/queue-6.12/arm-at91-pm-fix-at91_suspend_finish-for-zq-calibrati.patch @@ -0,0 +1,90 @@ +From 4c69a51859aa9e61c92c6ad43bc67ea9b1b0f7ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 08:51:56 -0700 +Subject: ARM: at91: pm: fix at91_suspend_finish for ZQ calibration + +From: Li Bin + +[ Upstream commit bc4722c3598d0e2c2dbf9609a3d3198993093e2b ] + +For sama7g5 and sama7d65 backup mode, we encountered a "ZQ calibrate error" +during recalibrating the impedance in BootStrap. +We found that the impedance value saved in at91_suspend_finish() before +the DDR entered self-refresh mode did not match the resistor values. The +ZDATA field in the DDR3PHY_ZQ0CR0 register uses a modified gray code to +select the different impedance setting. +But these gray code are incorrect, a workaournd from design team fixed the +bug in the calibration logic. The ZDATA contains four independent impedance +elements, but the algorithm combined the four elements into one. The elements +were fixed using properly shifted offsets. + +Signed-off-by: Li Bin +[nicolas.ferre@microchip.com: fix indentation and combine 2 patches] +Signed-off-by: Nicolas Ferre +Tested-by: Ryan Wanner +Tested-by: Durai Manickam KR +Tested-by: Andrei Simion +Signed-off-by: Ryan Wanner +Link: https://lore.kernel.org/r/28b33f9bcd0ca60ceba032969fe054d38f2b9577.1740671156.git.Ryan.Wanner@microchip.com +Signed-off-by: Claudiu Beznea +Signed-off-by: Sasha Levin +--- + arch/arm/mach-at91/pm.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c +index 05a1547642b60..6c3e6aa22606f 100644 +--- a/arch/arm/mach-at91/pm.c ++++ b/arch/arm/mach-at91/pm.c +@@ -545,11 +545,12 @@ extern u32 at91_pm_suspend_in_sram_sz; + + static int at91_suspend_finish(unsigned long val) + { +- unsigned char modified_gray_code[] = { +- 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05, 0x0c, 0x0d, +- 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09, 0x18, 0x19, 0x1a, 0x1b, +- 0x1e, 0x1f, 0x1c, 0x1d, 0x14, 0x15, 0x16, 0x17, 0x12, 0x13, +- 0x10, 0x11, ++ /* SYNOPSYS workaround to fix a bug in the calibration logic */ ++ unsigned char modified_fix_code[] = { ++ 0x00, 0x01, 0x01, 0x06, 0x07, 0x0c, 0x06, 0x07, 0x0b, 0x18, ++ 0x0a, 0x0b, 0x0c, 0x0d, 0x0d, 0x0a, 0x13, 0x13, 0x12, 0x13, ++ 0x14, 0x15, 0x15, 0x12, 0x18, 0x19, 0x19, 0x1e, 0x1f, 0x14, ++ 0x1e, 0x1f, + }; + unsigned int tmp, index; + int i; +@@ -560,25 +561,25 @@ static int at91_suspend_finish(unsigned long val) + * restore the ZQ0SR0 with the value saved here. But the + * calibration is buggy and restoring some values from ZQ0SR0 + * is forbidden and risky thus we need to provide processed +- * values for these (modified gray code values). ++ * values for these. + */ + tmp = readl(soc_pm.data.ramc_phy + DDR3PHY_ZQ0SR0); + + /* Store pull-down output impedance select. */ + index = (tmp >> DDR3PHY_ZQ0SR0_PDO_OFF) & 0x1f; +- soc_pm.bu->ddr_phy_calibration[0] = modified_gray_code[index]; ++ soc_pm.bu->ddr_phy_calibration[0] = modified_fix_code[index] << DDR3PHY_ZQ0SR0_PDO_OFF; + + /* Store pull-up output impedance select. */ + index = (tmp >> DDR3PHY_ZQ0SR0_PUO_OFF) & 0x1f; +- soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index]; ++ soc_pm.bu->ddr_phy_calibration[0] |= modified_fix_code[index] << DDR3PHY_ZQ0SR0_PUO_OFF; + + /* Store pull-down on-die termination impedance select. */ + index = (tmp >> DDR3PHY_ZQ0SR0_PDODT_OFF) & 0x1f; +- soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index]; ++ soc_pm.bu->ddr_phy_calibration[0] |= modified_fix_code[index] << DDR3PHY_ZQ0SR0_PDODT_OFF; + + /* Store pull-up on-die termination impedance select. */ + index = (tmp >> DDR3PHY_ZQ0SRO_PUODT_OFF) & 0x1f; +- soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index]; ++ soc_pm.bu->ddr_phy_calibration[0] |= modified_fix_code[index] << DDR3PHY_ZQ0SRO_PUODT_OFF; + + /* + * The 1st 8 words of memory might get corrupted in the process +-- +2.39.5 + diff --git a/queue-6.12/arm-tegra-switch-dsi-b-clock-parent-to-plld-on-tegra.patch b/queue-6.12/arm-tegra-switch-dsi-b-clock-parent-to-plld-on-tegra.patch new file mode 100644 index 0000000000..172509fabf --- /dev/null +++ b/queue-6.12/arm-tegra-switch-dsi-b-clock-parent-to-plld-on-tegra.patch @@ -0,0 +1,36 @@ +From 2fc89d1462df3b2daa4ce20ac5e55ae95369ac92 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 12:56:11 +0200 +Subject: ARM: tegra: Switch DSI-B clock parent to PLLD on Tegra114 + +From: Svyatoslav Ryhel + +[ Upstream commit 2b3db788f2f614b875b257cdb079adadedc060f3 ] + +PLLD is usually used as parent clock for internal video devices, like +DSI for example, while PLLD2 is used as parent for HDMI. + +Signed-off-by: Svyatoslav Ryhel +Link: https://lore.kernel.org/r/20250226105615.61087-3-clamor95@gmail.com +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/nvidia/tegra114.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/nvidia/tegra114.dtsi b/arch/arm/boot/dts/nvidia/tegra114.dtsi +index 86f14e2fd29f3..6c057b5069514 100644 +--- a/arch/arm/boot/dts/nvidia/tegra114.dtsi ++++ b/arch/arm/boot/dts/nvidia/tegra114.dtsi +@@ -139,7 +139,7 @@ dsib: dsi@54400000 { + reg = <0x54400000 0x00040000>; + clocks = <&tegra_car TEGRA114_CLK_DSIB>, + <&tegra_car TEGRA114_CLK_DSIBLP>, +- <&tegra_car TEGRA114_CLK_PLL_D2_OUT0>; ++ <&tegra_car TEGRA114_CLK_PLL_D_OUT0>; + clock-names = "dsi", "lp", "parent"; + resets = <&tegra_car 82>; + reset-names = "dsi"; +-- +2.39.5 + diff --git a/queue-6.12/arm64-add-support-for-hip09-spectre-bhb-mitigation.patch b/queue-6.12/arm64-add-support-for-hip09-spectre-bhb-mitigation.patch new file mode 100644 index 0000000000..8268fed0b2 --- /dev/null +++ b/queue-6.12/arm64-add-support-for-hip09-spectre-bhb-mitigation.patch @@ -0,0 +1,58 @@ +From 7a2769eacdd8c7bd50ab0d7a48c45328c31589f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Mar 2025 22:19:00 +0800 +Subject: arm64: Add support for HIP09 Spectre-BHB mitigation + +From: Jinqian Yang + +[ Upstream commit e18c09b204e81702ea63b9f1a81ab003b72e3174 ] + +The HIP09 processor is vulnerable to the Spectre-BHB (Branch History +Buffer) attack, which can be exploited to leak information through +branch prediction side channels. This commit adds the MIDR of HIP09 +to the list for software mitigation. + +Signed-off-by: Jinqian Yang +Link: https://lore.kernel.org/r/20250325141900.2057314-1-yangjinqian1@huawei.com +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/cputype.h | 2 ++ + arch/arm64/kernel/proton-pack.c | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h +index 8a6b7feca3e42..d92a0203e5a93 100644 +--- a/arch/arm64/include/asm/cputype.h ++++ b/arch/arm64/include/asm/cputype.h +@@ -132,6 +132,7 @@ + #define FUJITSU_CPU_PART_A64FX 0x001 + + #define HISI_CPU_PART_TSV110 0xD01 ++#define HISI_CPU_PART_HIP09 0xD02 + + #define APPLE_CPU_PART_M1_ICESTORM 0x022 + #define APPLE_CPU_PART_M1_FIRESTORM 0x023 +@@ -208,6 +209,7 @@ + #define MIDR_NVIDIA_CARMEL MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_CARMEL) + #define MIDR_FUJITSU_A64FX MIDR_CPU_MODEL(ARM_CPU_IMP_FUJITSU, FUJITSU_CPU_PART_A64FX) + #define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110) ++#define MIDR_HISI_HIP09 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_HIP09) + #define MIDR_APPLE_M1_ICESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM) + #define MIDR_APPLE_M1_FIRESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM) + #define MIDR_APPLE_M1_ICESTORM_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_PRO) +diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c +index 8ef3335ecff72..31eaf15d2079a 100644 +--- a/arch/arm64/kernel/proton-pack.c ++++ b/arch/arm64/kernel/proton-pack.c +@@ -904,6 +904,7 @@ static u8 spectre_bhb_loop_affected(void) + MIDR_ALL_VERSIONS(MIDR_CORTEX_A77), + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), + MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_GOLD), ++ MIDR_ALL_VERSIONS(MIDR_HISI_HIP09), + {}, + }; + static const struct midr_range spectre_bhb_k11_list[] = { +-- +2.39.5 + diff --git a/queue-6.12/arm64-mm-check-pmd_table-in-pmd_trans_huge.patch b/queue-6.12/arm64-mm-check-pmd_table-in-pmd_trans_huge.patch new file mode 100644 index 0000000000..6169e13059 --- /dev/null +++ b/queue-6.12/arm64-mm-check-pmd_table-in-pmd_trans_huge.patch @@ -0,0 +1,73 @@ +From fc7e77a74eb958d274881dd11c0189cf3a3eb447 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 10:12:26 +0530 +Subject: arm64/mm: Check pmd_table() in pmd_trans_huge() + +From: Ryan Roberts + +[ Upstream commit d1770e909898c108e8c7d30ca039053e8818a9c9 ] + +Check for pmd_table() in pmd_trans_huge() rather then just checking for the +PMD_TABLE_BIT. But ensure all present-invalid entries are handled correctly +by always setting PTE_VALID before checking with pmd_table(). + +Cc: Will Deacon +Cc: Ard Biesheuvel +Cc: Ryan Roberts +Cc: Mark Rutland +Cc: linux-arm-kernel@lists.infradead.org +Cc: linux-kernel@vger.kernel.org +Signed-off-by: Ryan Roberts +Signed-off-by: Anshuman Khandual +Link: https://lore.kernel.org/r/20250221044227.1145393-8-anshuman.khandual@arm.com +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/pgtable.h | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h +index c329ea061dc98..8ee56ae999c16 100644 +--- a/arch/arm64/include/asm/pgtable.h ++++ b/arch/arm64/include/asm/pgtable.h +@@ -554,18 +554,6 @@ static inline int pmd_protnone(pmd_t pmd) + #endif + + #define pmd_present(pmd) pte_present(pmd_pte(pmd)) +- +-/* +- * THP definitions. +- */ +- +-#ifdef CONFIG_TRANSPARENT_HUGEPAGE +-static inline int pmd_trans_huge(pmd_t pmd) +-{ +- return pmd_val(pmd) && pmd_present(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT); +-} +-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ +- + #define pmd_dirty(pmd) pte_dirty(pmd_pte(pmd)) + #define pmd_young(pmd) pte_young(pmd_pte(pmd)) + #define pmd_valid(pmd) pte_valid(pmd_pte(pmd)) +@@ -725,6 +713,18 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, + #define pmd_leaf_size(pmd) (pmd_cont(pmd) ? CONT_PMD_SIZE : PMD_SIZE) + #define pte_leaf_size(pte) (pte_cont(pte) ? CONT_PTE_SIZE : PAGE_SIZE) + ++#ifdef CONFIG_TRANSPARENT_HUGEPAGE ++static inline int pmd_trans_huge(pmd_t pmd) ++{ ++ /* ++ * If pmd is present-invalid, pmd_table() won't detect it ++ * as a table, so force the valid bit for the comparison. ++ */ ++ return pmd_val(pmd) && pmd_present(pmd) && ++ !pmd_table(__pmd(pmd_val(pmd) | PTE_VALID)); ++} ++#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ ++ + #if defined(CONFIG_ARM64_64K_PAGES) || CONFIG_PGTABLE_LEVELS < 3 + static inline bool pud_sect(pud_t pud) { return false; } + static inline bool pud_table(pud_t pud) { return true; } +-- +2.39.5 + diff --git a/queue-6.12/arm64-mm-check-pud_type_table-in-pud_bad.patch b/queue-6.12/arm64-mm-check-pud_type_table-in-pud_bad.patch new file mode 100644 index 0000000000..128cba9280 --- /dev/null +++ b/queue-6.12/arm64-mm-check-pud_type_table-in-pud_bad.patch @@ -0,0 +1,49 @@ +From 0507249884273f23d95e9ca3a5a9f5e8f1b2cbbb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 10:12:25 +0530 +Subject: arm64/mm: Check PUD_TYPE_TABLE in pud_bad() + +From: Ryan Roberts + +[ Upstream commit bfb1d2b9021c21891427acc86eb848ccedeb274e ] + +pud_bad() is currently defined in terms of pud_table(). Although for some +configs, pud_table() is hard-coded to true i.e. when using 64K base pages +or when page table levels are less than 3. + +pud_bad() is intended to check that the pud is configured correctly. Hence +let's open-code the same check that the full version of pud_table() uses +into pud_bad(). Then it always performs the check regardless of the config. + +Cc: Will Deacon +Cc: Ard Biesheuvel +Cc: Ryan Roberts +Cc: Mark Rutland +Cc: linux-arm-kernel@lists.infradead.org +Cc: linux-kernel@vger.kernel.org +Signed-off-by: Ryan Roberts +Signed-off-by: Anshuman Khandual +Link: https://lore.kernel.org/r/20250221044227.1145393-7-anshuman.khandual@arm.com +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/pgtable.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h +index 8ee56ae999c16..5ba8376735cb0 100644 +--- a/arch/arm64/include/asm/pgtable.h ++++ b/arch/arm64/include/asm/pgtable.h +@@ -806,7 +806,8 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) + pr_err("%s:%d: bad pmd %016llx.\n", __FILE__, __LINE__, pmd_val(e)) + + #define pud_none(pud) (!pud_val(pud)) +-#define pud_bad(pud) (!pud_table(pud)) ++#define pud_bad(pud) ((pud_val(pud) & PUD_TYPE_MASK) != \ ++ PUD_TYPE_TABLE) + #define pud_present(pud) pte_present(pud_pte(pud)) + #ifndef __PAGETABLE_PMD_FOLDED + #define pud_leaf(pud) (pud_present(pud) && !pud_table(pud)) +-- +2.39.5 + diff --git a/queue-6.12/arm64-tegra-p2597-fix-gpio-for-vdd-1v8-dis-regulator.patch b/queue-6.12/arm64-tegra-p2597-fix-gpio-for-vdd-1v8-dis-regulator.patch new file mode 100644 index 0000000000..cd4529d3d5 --- /dev/null +++ b/queue-6.12/arm64-tegra-p2597-fix-gpio-for-vdd-1v8-dis-regulator.patch @@ -0,0 +1,37 @@ +From c7cda983106f40802ca3cd60d0ee7e0bf0a69eea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 12:17:36 +0000 +Subject: arm64: tegra: p2597: Fix gpio for vdd-1v8-dis regulator + +From: Diogo Ivo + +[ Upstream commit f34621f31e3be81456c903287f7e4c0609829e29 ] + +According to the board schematics the enable pin of this regulator is +connected to gpio line #9 of the first instance of the TCA9539 +GPIO expander, so adjust it. + +Signed-off-by: Diogo Ivo +Link: https://lore.kernel.org/r/20250224-diogo-gpio_exp-v1-1-80fb84ac48c6@tecnico.ulisboa.pt +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi +index 63b94a04308e8..38d49d612c0c1 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi +@@ -1686,7 +1686,7 @@ vdd_1v8_dis: regulator-vdd-1v8-dis { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; +- gpio = <&exp1 14 GPIO_ACTIVE_HIGH>; ++ gpio = <&exp1 9 GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <&vdd_1v8>; + }; +-- +2.39.5 + diff --git a/queue-6.12/arm64-tegra-resize-aperture-for-the-igx-pcie-c5-slot.patch b/queue-6.12/arm64-tegra-resize-aperture-for-the-igx-pcie-c5-slot.patch new file mode 100644 index 0000000000..d56f21b0e5 --- /dev/null +++ b/queue-6.12/arm64-tegra-resize-aperture-for-the-igx-pcie-c5-slot.patch @@ -0,0 +1,48 @@ +From 3a8e671f5871b0940679a8f893f8f0ff3a3ab8f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jan 2025 15:19:03 +0000 +Subject: arm64: tegra: Resize aperture for the IGX PCIe C5 slot + +From: Jon Hunter + +[ Upstream commit 6d4bfe6d86af1ef52bdb4592c9afb2037f24f2c4 ] + +Some discrete graphics cards such as the NVIDIA RTX A6000 support +resizable BARs. When connecting an A6000 card to the NVIDIA IGX Orin +platform, resizing the BAR1 aperture to 8GB fails because the current +device-tree configuration for the PCIe C5 slot cannot support this. +Fix this by updating the device-tree 'reg' and 'ranges' properties for +the PCIe C5 slot to support this. + +Signed-off-by: Jon Hunter +Link: https://lore.kernel.org/r/20250116151903.476047-1-jonathanh@nvidia.com +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + .../boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts b/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts +index 36e8880537460..9ce55b4d2de89 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts ++++ b/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts +@@ -302,6 +302,16 @@ pcie@14160000 { + }; + + pcie@141a0000 { ++ reg = <0x00 0x141a0000 0x0 0x00020000 /* appl registers (128K) */ ++ 0x00 0x3a000000 0x0 0x00040000 /* configuration space (256K) */ ++ 0x00 0x3a040000 0x0 0x00040000 /* iATU_DMA reg space (256K) */ ++ 0x00 0x3a080000 0x0 0x00040000 /* DBI reg space (256K) */ ++ 0x2e 0x20000000 0x0 0x10000000>; /* ECAM (256MB) */ ++ ++ ranges = <0x81000000 0x00 0x3a100000 0x00 0x3a100000 0x0 0x00100000 /* downstream I/O (1MB) */ ++ 0x82000000 0x00 0x40000000 0x2e 0x30000000 0x0 0x08000000 /* non-prefetchable memory (128MB) */ ++ 0xc3000000 0x28 0x00000000 0x28 0x00000000 0x6 0x20000000>; /* prefetchable memory (25088MB) */ ++ + status = "okay"; + vddio-pex-ctl-supply = <&vdd_1v8_ls>; + phys = <&p2u_nvhs_0>, <&p2u_nvhs_1>, <&p2u_nvhs_2>, +-- +2.39.5 + diff --git a/queue-6.12/arm64-zynqmp-add-clock-output-names-property-in-cloc.patch b/queue-6.12/arm64-zynqmp-add-clock-output-names-property-in-cloc.patch new file mode 100644 index 0000000000..0e18116459 --- /dev/null +++ b/queue-6.12/arm64-zynqmp-add-clock-output-names-property-in-cloc.patch @@ -0,0 +1,80 @@ +From d90570c5e5adc969fe2c1af5ce5e789eeb4cec37 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Nov 2024 01:57:12 -0800 +Subject: arm64: zynqmp: add clock-output-names property in clock nodes + +From: Naman Trivedi + +[ Upstream commit 385a59e7f7fb3438466a0712cc14672c708bbd57 ] + +Add clock-output-names property to clock nodes, so that the resulting +clock name do not change when clock node name is changed. +Also, replace underscores with hyphens in the clock node names as per +dt-schema rule. + +Signed-off-by: Naman Trivedi +Acked-by: Senthil Nathan Thangaraj +Link: https://lore.kernel.org/r/20241122095712.1166883-1-naman.trivedimanojbhai@amd.com +Signed-off-by: Michal Simek +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi +index 60d1b1acf9a03..385fed8a852af 100644 +--- a/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi ++++ b/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi +@@ -10,39 +10,44 @@ + + #include + / { +- pss_ref_clk: pss_ref_clk { ++ pss_ref_clk: pss-ref-clk { + bootph-all; + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <33333333>; ++ clock-output-names = "pss_ref_clk"; + }; + +- video_clk: video_clk { ++ video_clk: video-clk { + bootph-all; + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <27000000>; ++ clock-output-names = "video_clk"; + }; + +- pss_alt_ref_clk: pss_alt_ref_clk { ++ pss_alt_ref_clk: pss-alt-ref-clk { + bootph-all; + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; ++ clock-output-names = "pss_alt_ref_clk"; + }; + +- gt_crx_ref_clk: gt_crx_ref_clk { ++ gt_crx_ref_clk: gt-crx-ref-clk { + bootph-all; + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <108000000>; ++ clock-output-names = "gt_crx_ref_clk"; + }; + +- aux_ref_clk: aux_ref_clk { ++ aux_ref_clk: aux-ref-clk { + bootph-all; + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <27000000>; ++ clock-output-names = "aux_ref_clk"; + }; + }; + +-- +2.39.5 + diff --git a/queue-6.12/asoc-codecs-pcm3168a-allow-for-24-bit-in-provider-mo.patch b/queue-6.12/asoc-codecs-pcm3168a-allow-for-24-bit-in-provider-mo.patch new file mode 100644 index 0000000000..16932c19bb --- /dev/null +++ b/queue-6.12/asoc-codecs-pcm3168a-allow-for-24-bit-in-provider-mo.patch @@ -0,0 +1,40 @@ +From fc49f17c05ddc55ae2c395be6d215a5ec3ed3b1c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 15:10:43 +0100 +Subject: ASoC: codecs: pcm3168a: Allow for 24-bit in provider mode + +From: Cezary Rojewski + +[ Upstream commit 7d92a38d67e5d937b64b20aa4fd14451ee1772f3 ] + +As per codec device specification, 24-bit is allowed in provider mode. +Update the code to reflect that. + +Signed-off-by: Cezary Rojewski +Link: https://patch.msgid.link/20250203141051.2361323-4-cezary.rojewski@intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/pcm3168a.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c +index fac0617ab95b6..6cbb8d0535b02 100644 +--- a/sound/soc/codecs/pcm3168a.c ++++ b/sound/soc/codecs/pcm3168a.c +@@ -493,9 +493,9 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, + } + break; + case 24: +- if (provider_mode || (format == SND_SOC_DAIFMT_DSP_A) || +- (format == SND_SOC_DAIFMT_DSP_B)) { +- dev_err(component->dev, "24-bit slots not supported in provider mode, or consumer mode using DSP\n"); ++ if (!provider_mode && ((format == SND_SOC_DAIFMT_DSP_A) || ++ (format == SND_SOC_DAIFMT_DSP_B))) { ++ dev_err(component->dev, "24-bit slots not supported in consumer mode using DSP\n"); + return -EINVAL; + } + break; +-- +2.39.5 + diff --git a/queue-6.12/asoc-codecs-wsa883x-correct-vi-sense-channel-mask.patch b/queue-6.12/asoc-codecs-wsa883x-correct-vi-sense-channel-mask.patch new file mode 100644 index 0000000000..ba901876b4 --- /dev/null +++ b/queue-6.12/asoc-codecs-wsa883x-correct-vi-sense-channel-mask.patch @@ -0,0 +1,38 @@ +From dc0e41cd12e735a8903a7d0170ca5e37f61825b0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 20:24:59 +0100 +Subject: ASoC: codecs: wsa883x: Correct VI sense channel mask + +From: Krzysztof Kozlowski + +[ Upstream commit ed3b274abc4008efffebf1997968a3f2720a86d3 ] + +VI sense port on WSA883x speaker takes only one channel, so use 0x1 as +channel mask. This fixes garbage being recorded by the speaker when +testing the VI sense feedback path. + +Cc: Srinivas Kandagatla +Signed-off-by: Krzysztof Kozlowski +Link: https://patch.msgid.link/20250312-asoc-wsa88xx-visense-v1-1-9ca705881122@linaro.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/wsa883x.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c +index 47da5674d7c92..e31b7fb104e6c 100644 +--- a/sound/soc/codecs/wsa883x.c ++++ b/sound/soc/codecs/wsa883x.c +@@ -529,7 +529,7 @@ static const struct sdw_port_config wsa883x_pconfig[WSA883X_MAX_SWR_PORTS] = { + }, + [WSA883X_PORT_VISENSE] = { + .num = WSA883X_PORT_VISENSE + 1, +- .ch_mask = 0x3, ++ .ch_mask = 0x1, + }, + }; + +-- +2.39.5 + diff --git a/queue-6.12/asoc-codecs-wsa884x-correct-vi-sense-channel-mask.patch b/queue-6.12/asoc-codecs-wsa884x-correct-vi-sense-channel-mask.patch new file mode 100644 index 0000000000..19429f5b66 --- /dev/null +++ b/queue-6.12/asoc-codecs-wsa884x-correct-vi-sense-channel-mask.patch @@ -0,0 +1,38 @@ +From 9447f57eaa9ef4ded554c7327267906ad3e9f056 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 20:25:00 +0100 +Subject: ASoC: codecs: wsa884x: Correct VI sense channel mask + +From: Krzysztof Kozlowski + +[ Upstream commit 060fac202eb8e5c83961f0e0bf6dad8ab6e46643 ] + +VI sense port on WSA883x speaker takes only one channel, so use 0x1 as +channel mask. This fixes garbage being recorded by the speaker when +testing the VI sense feedback path. + +Cc: Srinivas Kandagatla +Signed-off-by: Krzysztof Kozlowski +Link: https://patch.msgid.link/20250312-asoc-wsa88xx-visense-v1-2-9ca705881122@linaro.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/wsa884x.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/wsa884x.c b/sound/soc/codecs/wsa884x.c +index 560a2c04b6955..18b0ee8f15a55 100644 +--- a/sound/soc/codecs/wsa884x.c ++++ b/sound/soc/codecs/wsa884x.c +@@ -891,7 +891,7 @@ static const struct sdw_port_config wsa884x_pconfig[WSA884X_MAX_SWR_PORTS] = { + }, + [WSA884X_PORT_VISENSE] = { + .num = WSA884X_PORT_VISENSE + 1, +- .ch_mask = 0x3, ++ .ch_mask = 0x1, + }, + [WSA884X_PORT_CPS] = { + .num = WSA884X_PORT_CPS + 1, +-- +2.39.5 + diff --git a/queue-6.12/asoc-cs42l43-disable-headphone-clamps-during-type-de.patch b/queue-6.12/asoc-cs42l43-disable-headphone-clamps-during-type-de.patch new file mode 100644 index 0000000000..6410d07269 --- /dev/null +++ b/queue-6.12/asoc-cs42l43-disable-headphone-clamps-during-type-de.patch @@ -0,0 +1,50 @@ +From 9ecf254ba8c3a8ad5348ab5e115553b08177bb86 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Apr 2025 10:09:44 +0100 +Subject: ASoC: cs42l43: Disable headphone clamps during type detection + +From: Charles Keepax + +[ Upstream commit 70ad2e6bd180f94be030aef56e59693e36d945f3 ] + +The headphone clamps cause fairly loud pops during type detect +because they sink current from the detection process itself. Disable +the clamps whilst the type detect runs, to improve the detection +pop performance. + +Signed-off-by: Charles Keepax +Link: https://patch.msgid.link/20250423090944.1504538-1-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/cs42l43-jack.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/sound/soc/codecs/cs42l43-jack.c b/sound/soc/codecs/cs42l43-jack.c +index 73d764fc85392..984a7f470a31f 100644 +--- a/sound/soc/codecs/cs42l43-jack.c ++++ b/sound/soc/codecs/cs42l43-jack.c +@@ -654,6 +654,10 @@ static int cs42l43_run_type_detect(struct cs42l43_codec *priv) + + reinit_completion(&priv->type_detect); + ++ regmap_update_bits(cs42l43->regmap, CS42L43_STEREO_MIC_CLAMP_CTRL, ++ CS42L43_SMIC_HPAMP_CLAMP_DIS_FRC_VAL_MASK, ++ CS42L43_SMIC_HPAMP_CLAMP_DIS_FRC_VAL_MASK); ++ + cs42l43_start_hs_bias(priv, true); + regmap_update_bits(cs42l43->regmap, CS42L43_HS2, + CS42L43_HSDET_MODE_MASK, 0x3 << CS42L43_HSDET_MODE_SHIFT); +@@ -665,6 +669,9 @@ static int cs42l43_run_type_detect(struct cs42l43_codec *priv) + CS42L43_HSDET_MODE_MASK, 0x2 << CS42L43_HSDET_MODE_SHIFT); + cs42l43_stop_hs_bias(priv); + ++ regmap_update_bits(cs42l43->regmap, CS42L43_STEREO_MIC_CLAMP_CTRL, ++ CS42L43_SMIC_HPAMP_CLAMP_DIS_FRC_VAL_MASK, 0); ++ + if (!time_left) + return -ETIMEDOUT; + +-- +2.39.5 + diff --git a/queue-6.12/asoc-imx-card-adjust-over-allocation-of-memory-in-im.patch b/queue-6.12/asoc-imx-card-adjust-over-allocation-of-memory-in-im.patch new file mode 100644 index 0000000000..f3aa3ba41b --- /dev/null +++ b/queue-6.12/asoc-imx-card-adjust-over-allocation-of-memory-in-im.patch @@ -0,0 +1,40 @@ +From 1908224ced1af712a80ca55c2b666f1c34cfabdc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 6 Apr 2025 16:08:54 -0500 +Subject: ASoC: imx-card: Adjust over allocation of memory in + imx_card_parse_of() + +From: Chenyuan Yang + +[ Upstream commit a9a69c3b38c89d7992fb53db4abb19104b531d32 ] + +Incorrect types are used as sizeof() arguments in devm_kcalloc(). +It should be sizeof(dai_link_data) for link_data instead of +sizeof(snd_soc_dai_link). + +This is found by our static analysis tool. + +Signed-off-by: Chenyuan Yang +Link: https://patch.msgid.link/20250406210854.149316-1-chenyuan0y@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/fsl/imx-card.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c +index 93dbe40008c00..e5ae435171d68 100644 +--- a/sound/soc/fsl/imx-card.c ++++ b/sound/soc/fsl/imx-card.c +@@ -516,7 +516,7 @@ static int imx_card_parse_of(struct imx_card_data *data) + if (!card->dai_link) + return -ENOMEM; + +- data->link_data = devm_kcalloc(dev, num_links, sizeof(*link), GFP_KERNEL); ++ data->link_data = devm_kcalloc(dev, num_links, sizeof(*link_data), GFP_KERNEL); + if (!data->link_data) + return -ENOMEM; + +-- +2.39.5 + diff --git a/queue-6.12/asoc-intel-bytcr_rt5640-add-dmi-quirk-for-acer-aspir.patch b/queue-6.12/asoc-intel-bytcr_rt5640-add-dmi-quirk-for-acer-aspir.patch new file mode 100644 index 0000000000..c79c7cc3ee --- /dev/null +++ b/queue-6.12/asoc-intel-bytcr_rt5640-add-dmi-quirk-for-acer-aspir.patch @@ -0,0 +1,48 @@ +From cea49373e2c1b797cb91f8f11a08c44849d13c02 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 20 Apr 2025 10:56:59 +0200 +Subject: ASoC: Intel: bytcr_rt5640: Add DMI quirk for Acer Aspire SW3-013 + +From: Takashi Iwai + +[ Upstream commit a549b927ea3f5e50b1394209b64e6e17e31d4db8 ] + +Acer Aspire SW3-013 requires the very same quirk as other Acer Aspire +model for making it working. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=220011 +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/20250420085716.12095-1-tiwai@suse.de +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/intel/boards/bytcr_rt5640.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c +index 1148e9498d8e8..b6434b4731261 100644 +--- a/sound/soc/intel/boards/bytcr_rt5640.c ++++ b/sound/soc/intel/boards/bytcr_rt5640.c +@@ -576,6 +576,19 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { + BYT_RT5640_SSP0_AIF2 | + BYT_RT5640_MCLK_EN), + }, ++ { /* Acer Aspire SW3-013 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Acer"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW3-013"), ++ }, ++ .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | ++ BYT_RT5640_JD_SRC_JD2_IN4N | ++ BYT_RT5640_OVCD_TH_2000UA | ++ BYT_RT5640_OVCD_SF_0P75 | ++ BYT_RT5640_DIFF_MIC | ++ BYT_RT5640_SSP0_AIF1 | ++ BYT_RT5640_MCLK_EN), ++ }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +-- +2.39.5 + diff --git a/queue-6.12/asoc-intel-sdw_utils-add-volume-limit-to-cs42l43-spe.patch b/queue-6.12/asoc-intel-sdw_utils-add-volume-limit-to-cs42l43-spe.patch new file mode 100644 index 0000000000..829c00cfbc --- /dev/null +++ b/queue-6.12/asoc-intel-sdw_utils-add-volume-limit-to-cs42l43-spe.patch @@ -0,0 +1,60 @@ +From 545bd30f3ec0c41474fdbc779a1d970463ce935d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Apr 2025 11:31:19 +0100 +Subject: ASoC: intel/sdw_utils: Add volume limit to cs42l43 speakers + +From: Stefan Binding + +[ Upstream commit 02b44a2b2bdcee03cbb92484d31e9ca1b91b2a38 ] + +The volume control for cs42l43 speakers has a maximum gain of +31.5 dB. +However, for many use cases, this can cause distorted audio, depending +various factors, such as other signal-processing elements in the chain, +for example if the audio passes through a gain control before reaching +the codec or the signal path has been tuned for a particular maximum +gain in the codec. + +In the case of systems which use the soc_sdw_cs42l43 driver, audio will +likely be distorted in all cases above 0 dB, therefore add a volume +limit of 128, which is 0 dB maximum volume inside this driver. + +Signed-off-by: Stefan Binding +Reviewed-by: Charles Keepax +Link: https://patch.msgid.link/20250430103134.24579-2-sbinding@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/sdw_utils/soc_sdw_cs42l43.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/sound/soc/sdw_utils/soc_sdw_cs42l43.c b/sound/soc/sdw_utils/soc_sdw_cs42l43.c +index adb1c008e871d..2dc7787234c36 100644 +--- a/sound/soc/sdw_utils/soc_sdw_cs42l43.c ++++ b/sound/soc/sdw_utils/soc_sdw_cs42l43.c +@@ -20,6 +20,8 @@ + #include + #include + ++#define CS42L43_SPK_VOLUME_0DB 128 /* 0dB Max */ ++ + static const struct snd_soc_dapm_route cs42l43_hs_map[] = { + { "Headphone", NULL, "cs42l43 AMP3_OUT" }, + { "Headphone", NULL, "cs42l43 AMP4_OUT" }, +@@ -117,6 +119,14 @@ int asoc_sdw_cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_so + return -ENOMEM; + } + ++ ret = snd_soc_limit_volume(card, "cs42l43 Speaker Digital Volume", ++ CS42L43_SPK_VOLUME_0DB); ++ if (ret) ++ dev_err(card->dev, "cs42l43 speaker volume limit failed: %d\n", ret); ++ else ++ dev_info(card->dev, "Setting CS42L43 Speaker volume limit to %d\n", ++ CS42L43_SPK_VOLUME_0DB); ++ + ret = snd_soc_dapm_add_routes(&card->dapm, cs42l43_spk_map, + ARRAY_SIZE(cs42l43_spk_map)); + if (ret) +-- +2.39.5 + diff --git a/queue-6.12/asoc-mediatek-mt6359-add-stub-for-mt6359_accdet_enab.patch b/queue-6.12/asoc-mediatek-mt6359-add-stub-for-mt6359_accdet_enab.patch new file mode 100644 index 0000000000..679269acd1 --- /dev/null +++ b/queue-6.12/asoc-mediatek-mt6359-add-stub-for-mt6359_accdet_enab.patch @@ -0,0 +1,48 @@ +From dfbd159f75be911bf4266d61a579c5843ab2d35b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 16:52:17 -0300 +Subject: ASoC: mediatek: mt6359: Add stub for mt6359_accdet_enable_jack_detect +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Nícolas F. R. A. Prado + +[ Upstream commit 0116a7d84b32537a10d9bea1fd1bfc06577ef527 ] + +Add a stub for mt6359_accdet_enable_jack_detect() to prevent linker +failures in the machine sound drivers calling it when +CONFIG_SND_SOC_MT6359_ACCDET is not enabled. + +Suggested-by: AngeloGioacchino Del Regno +Signed-off-by: Nícolas F. R. A. Prado +Link: https://patch.msgid.link/20250306-mt8188-accdet-v3-3-7828e835ff4b@collabora.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/mt6359-accdet.h | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h +index c234f2f4276a1..78ada3a5bfae5 100644 +--- a/sound/soc/codecs/mt6359-accdet.h ++++ b/sound/soc/codecs/mt6359-accdet.h +@@ -123,6 +123,15 @@ struct mt6359_accdet { + struct workqueue_struct *jd_workqueue; + }; + ++#if IS_ENABLED(CONFIG_SND_SOC_MT6359_ACCDET) + int mt6359_accdet_enable_jack_detect(struct snd_soc_component *component, + struct snd_soc_jack *jack); ++#else ++static inline int ++mt6359_accdet_enable_jack_detect(struct snd_soc_component *component, ++ struct snd_soc_jack *jack) ++{ ++ return -EOPNOTSUPP; ++} ++#endif + #endif +-- +2.39.5 + diff --git a/queue-6.12/asoc-mediatek-mt8188-add-reference-for-dmic-clocks.patch b/queue-6.12/asoc-mediatek-mt8188-add-reference-for-dmic-clocks.patch new file mode 100644 index 0000000000..473a78b25d --- /dev/null +++ b/queue-6.12/asoc-mediatek-mt8188-add-reference-for-dmic-clocks.patch @@ -0,0 +1,68 @@ +From 8dd2aac1de497c380d8b16f3a007e3e4d2ed8537 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 11:33:48 -0300 +Subject: ASoC: mediatek: mt8188: Add reference for dmic clocks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Nícolas F. R. A. Prado + +[ Upstream commit bf1800073f4d55f08191b034c86b95881e99b6fd ] + +Add the names for the dmic clocks, aud_afe_dmic* and aud_dmic_hires*, so +they can be acquired and enabled by the platform driver. + +Signed-off-by: Nícolas F. R. A. Prado +Reviewed-by: AngeloGioacchino Del Regno +Link: https://patch.msgid.link/20250225-genio700-dmic-v2-2-3076f5b50ef7@collabora.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/mediatek/mt8188/mt8188-afe-clk.c | 8 ++++++++ + sound/soc/mediatek/mt8188/mt8188-afe-clk.h | 8 ++++++++ + 2 files changed, 16 insertions(+) + +diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-clk.c b/sound/soc/mediatek/mt8188/mt8188-afe-clk.c +index e69c1bb2cb239..7f411b8577823 100644 +--- a/sound/soc/mediatek/mt8188/mt8188-afe-clk.c ++++ b/sound/soc/mediatek/mt8188/mt8188-afe-clk.c +@@ -58,7 +58,15 @@ static const char *aud_clks[MT8188_CLK_NUM] = { + [MT8188_CLK_AUD_ADC] = "aud_adc", + [MT8188_CLK_AUD_DAC_HIRES] = "aud_dac_hires", + [MT8188_CLK_AUD_A1SYS_HP] = "aud_a1sys_hp", ++ [MT8188_CLK_AUD_AFE_DMIC1] = "aud_afe_dmic1", ++ [MT8188_CLK_AUD_AFE_DMIC2] = "aud_afe_dmic2", ++ [MT8188_CLK_AUD_AFE_DMIC3] = "aud_afe_dmic3", ++ [MT8188_CLK_AUD_AFE_DMIC4] = "aud_afe_dmic4", + [MT8188_CLK_AUD_ADC_HIRES] = "aud_adc_hires", ++ [MT8188_CLK_AUD_DMIC_HIRES1] = "aud_dmic_hires1", ++ [MT8188_CLK_AUD_DMIC_HIRES2] = "aud_dmic_hires2", ++ [MT8188_CLK_AUD_DMIC_HIRES3] = "aud_dmic_hires3", ++ [MT8188_CLK_AUD_DMIC_HIRES4] = "aud_dmic_hires4", + [MT8188_CLK_AUD_I2SIN] = "aud_i2sin", + [MT8188_CLK_AUD_TDM_IN] = "aud_tdm_in", + [MT8188_CLK_AUD_I2S_OUT] = "aud_i2s_out", +diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-clk.h b/sound/soc/mediatek/mt8188/mt8188-afe-clk.h +index ec53c171c170a..c6c78d684f3ee 100644 +--- a/sound/soc/mediatek/mt8188/mt8188-afe-clk.h ++++ b/sound/soc/mediatek/mt8188/mt8188-afe-clk.h +@@ -54,7 +54,15 @@ enum { + MT8188_CLK_AUD_ADC, + MT8188_CLK_AUD_DAC_HIRES, + MT8188_CLK_AUD_A1SYS_HP, ++ MT8188_CLK_AUD_AFE_DMIC1, ++ MT8188_CLK_AUD_AFE_DMIC2, ++ MT8188_CLK_AUD_AFE_DMIC3, ++ MT8188_CLK_AUD_AFE_DMIC4, + MT8188_CLK_AUD_ADC_HIRES, ++ MT8188_CLK_AUD_DMIC_HIRES1, ++ MT8188_CLK_AUD_DMIC_HIRES2, ++ MT8188_CLK_AUD_DMIC_HIRES3, ++ MT8188_CLK_AUD_DMIC_HIRES4, + MT8188_CLK_AUD_I2SIN, + MT8188_CLK_AUD_TDM_IN, + MT8188_CLK_AUD_I2S_OUT, +-- +2.39.5 + diff --git a/queue-6.12/asoc-mediatek-mt8188-treat-dmic_gainx_cur-as-non-vol.patch b/queue-6.12/asoc-mediatek-mt8188-treat-dmic_gainx_cur-as-non-vol.patch new file mode 100644 index 0000000000..e94eec1830 --- /dev/null +++ b/queue-6.12/asoc-mediatek-mt8188-treat-dmic_gainx_cur-as-non-vol.patch @@ -0,0 +1,55 @@ +From 414f6e788e644e52a36dbaea25b80d381143edec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 11:33:49 -0300 +Subject: ASoC: mediatek: mt8188: Treat DMIC_GAINx_CUR as non-volatile +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Nícolas F. R. A. Prado + +[ Upstream commit 7d87bde21c73731ddaf15e572020f80999c38ee3 ] + +The DMIC_GAINx_CUR registers contain the current (as in present) gain of +each DMIC. During capture, this gain will ramp up until a target value +is reached, and therefore the register is volatile since it is updated +automatically by hardware. + +However, after capture the register's value returns to the value that +was written to it. So reading these registers returns the current gain, +and writing configures the initial gain for every capture. + +>From an audio configuration perspective, reading the instantaneous gain +is not really useful. Instead, reading back the initial gain that was +configured is the desired behavior. For that reason, consider the +DMIC_GAINx_CUR registers as non-volatile, so the regmap's cache can be +used to retrieve the values, rather than requiring pm runtime resuming +the device. + +Signed-off-by: Nícolas F. R. A. Prado +Reviewed-by: AngeloGioacchino Del Regno +Link: https://patch.msgid.link/20250225-genio700-dmic-v2-3-3076f5b50ef7@collabora.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/mediatek/mt8188/mt8188-afe-pcm.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c +index 73e5c63aeec87..d36520c6272dd 100644 +--- a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c ++++ b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c +@@ -2855,10 +2855,6 @@ static bool mt8188_is_volatile_reg(struct device *dev, unsigned int reg) + case AFE_DMIC3_SRC_DEBUG_MON0: + case AFE_DMIC3_UL_SRC_MON0: + case AFE_DMIC3_UL_SRC_MON1: +- case DMIC_GAIN1_CUR: +- case DMIC_GAIN2_CUR: +- case DMIC_GAIN3_CUR: +- case DMIC_GAIN4_CUR: + case ETDM_IN1_MONITOR: + case ETDM_IN2_MONITOR: + case ETDM_OUT1_MONITOR: +-- +2.39.5 + diff --git a/queue-6.12/asoc-ops-enforce-platform-maximum-on-initial-value.patch b/queue-6.12/asoc-ops-enforce-platform-maximum-on-initial-value.patch new file mode 100644 index 0000000000..99b8d055bc --- /dev/null +++ b/queue-6.12/asoc-ops-enforce-platform-maximum-on-initial-value.patch @@ -0,0 +1,75 @@ +From b9766667f3f9fb66325479fe929ea0d2c0f2cce4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Feb 2025 00:57:22 +0000 +Subject: ASoC: ops: Enforce platform maximum on initial value +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Martin PoviÅ¡er + +[ Upstream commit 783db6851c1821d8b983ffb12b99c279ff64f2ee ] + +Lower the volume if it is violating the platform maximum at its initial +value (i.e. at the time of the 'snd_soc_limit_volume' call). + +Signed-off-by: Martin PoviÅ¡er +[Cherry picked from the Asahi kernel with fixups -- broonie] +Signed-off-by: Mark Brown +Link: https://patch.msgid.link/20250208-asoc-volume-limit-v1-1-b98fcf4cdbad@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/soc-ops.c | 29 ++++++++++++++++++++++++++++- + 1 file changed, 28 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c +index b0e4e4168f38d..fb11003d56cf6 100644 +--- a/sound/soc/soc-ops.c ++++ b/sound/soc/soc-ops.c +@@ -639,6 +639,33 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, + } + EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); + ++static int snd_soc_clip_to_platform_max(struct snd_kcontrol *kctl) ++{ ++ struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; ++ struct snd_ctl_elem_value uctl; ++ int ret; ++ ++ if (!mc->platform_max) ++ return 0; ++ ++ ret = kctl->get(kctl, &uctl); ++ if (ret < 0) ++ return ret; ++ ++ if (uctl.value.integer.value[0] > mc->platform_max) ++ uctl.value.integer.value[0] = mc->platform_max; ++ ++ if (snd_soc_volsw_is_stereo(mc) && ++ uctl.value.integer.value[1] > mc->platform_max) ++ uctl.value.integer.value[1] = mc->platform_max; ++ ++ ret = kctl->put(kctl, &uctl); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ + /** + * snd_soc_limit_volume - Set new limit to an existing volume control. + * +@@ -663,7 +690,7 @@ int snd_soc_limit_volume(struct snd_soc_card *card, + struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; + if (max <= mc->max - mc->min) { + mc->platform_max = max; +- ret = 0; ++ ret = snd_soc_clip_to_platform_max(kctl); + } + } + return ret; +-- +2.39.5 + diff --git a/queue-6.12/asoc-pcm6240-drop-bogus-code-handling-irq-as-gpio.patch b/queue-6.12/asoc-pcm6240-drop-bogus-code-handling-irq-as-gpio.patch new file mode 100644 index 0000000000..9e269a04f5 --- /dev/null +++ b/queue-6.12/asoc-pcm6240-drop-bogus-code-handling-irq-as-gpio.patch @@ -0,0 +1,131 @@ +From 053604cc8f35a1b81f73b9dddbc2dd222b822759 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 14:31:52 +0100 +Subject: ASoC: pcm6240: Drop bogus code handling IRQ as GPIO + +From: Linus Walleij + +[ Upstream commit 17fdf318f5fbe5c27353ae917c0c5a2899d9c259 ] + +The current code for the IRQ in pcm6240 makes no sense: +it looks up an IRQ with of_irq_get(), treat it as a GPIO +by issuing gpio_request(), gpio_direction_input() +and gpio_to_irq() on it. + +This is just wrong, if the device tree assigns the IRQ +from a GPIO number this is just incorrect: it is clearly +stated that GPIO providers and IRQ providers are +orthogonal. + +It is possible to look up an IRQ to a corresponding GPIO +line but this is taking an IRQ and pretending it's a +GPIO, which is just semantically wrong. + +Drop the offending code and treat the IRQ that we get +from the device tree as any other IRQ, see for example +other codec drivers. + +The DT bindings for this codec does not have any in-tree +DTS files, which may explain why things are weird. + +As a bonus, this moves the driver away from the legacy + include. + +Signed-off-by: Linus Walleij +Link: https://patch.msgid.link/20250312-pcm-codecs-v1-3-41ffc4f8fc5c@linaro.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/pcm6240.c | 28 +++++++--------------------- + sound/soc/codecs/pcm6240.h | 7 +------ + 2 files changed, 8 insertions(+), 27 deletions(-) + +diff --git a/sound/soc/codecs/pcm6240.c b/sound/soc/codecs/pcm6240.c +index 5d99877f88397..e59bb77edf091 100644 +--- a/sound/soc/codecs/pcm6240.c ++++ b/sound/soc/codecs/pcm6240.c +@@ -14,7 +14,7 @@ + + #include + #include +-#include ++#include + #include + #include + #include +@@ -2035,10 +2035,8 @@ static const struct regmap_config pcmdevice_i2c_regmap = { + + static void pcmdevice_remove(struct pcmdevice_priv *pcm_dev) + { +- if (gpio_is_valid(pcm_dev->irq_info.gpio)) { +- gpio_free(pcm_dev->irq_info.gpio); +- free_irq(pcm_dev->irq_info.nmb, pcm_dev); +- } ++ if (pcm_dev->irq) ++ free_irq(pcm_dev->irq, pcm_dev); + mutex_destroy(&pcm_dev->codec_lock); + } + +@@ -2110,7 +2108,7 @@ static int pcmdevice_i2c_probe(struct i2c_client *i2c) + ndev = 1; + dev_addrs[0] = i2c->addr; + } +- pcm_dev->irq_info.gpio = of_irq_get(np, 0); ++ pcm_dev->irq = of_irq_get(np, 0); + + for (i = 0; i < ndev; i++) + pcm_dev->addr[i] = dev_addrs[i]; +@@ -2133,22 +2131,10 @@ static int pcmdevice_i2c_probe(struct i2c_client *i2c) + + if (pcm_dev->chip_id == PCM1690) + goto skip_interrupt; +- if (gpio_is_valid(pcm_dev->irq_info.gpio)) { +- dev_dbg(pcm_dev->dev, "irq-gpio = %d", pcm_dev->irq_info.gpio); +- +- ret = gpio_request(pcm_dev->irq_info.gpio, "PCMDEV-IRQ"); +- if (!ret) { +- int gpio = pcm_dev->irq_info.gpio; +- +- gpio_direction_input(gpio); +- pcm_dev->irq_info.nmb = gpio_to_irq(gpio); +- +- } else +- dev_err(pcm_dev->dev, "%s: GPIO %d request error\n", +- __func__, pcm_dev->irq_info.gpio); ++ if (pcm_dev->irq) { ++ dev_dbg(pcm_dev->dev, "irq = %d", pcm_dev->irq); + } else +- dev_err(pcm_dev->dev, "Looking up irq-gpio failed %d\n", +- pcm_dev->irq_info.gpio); ++ dev_err(pcm_dev->dev, "No irq provided\n"); + + skip_interrupt: + ret = devm_snd_soc_register_component(&i2c->dev, +diff --git a/sound/soc/codecs/pcm6240.h b/sound/soc/codecs/pcm6240.h +index 1e125bb972860..2d8f9e798139a 100644 +--- a/sound/soc/codecs/pcm6240.h ++++ b/sound/soc/codecs/pcm6240.h +@@ -208,11 +208,6 @@ struct pcmdevice_regbin { + struct pcmdevice_config_info **cfg_info; + }; + +-struct pcmdevice_irqinfo { +- int gpio; +- int nmb; +-}; +- + struct pcmdevice_priv { + struct snd_soc_component *component; + struct i2c_client *client; +@@ -221,7 +216,7 @@ struct pcmdevice_priv { + struct gpio_desc *hw_rst; + struct regmap *regmap; + struct pcmdevice_regbin regbin; +- struct pcmdevice_irqinfo irq_info; ++ int irq; + unsigned int addr[PCMDEVICE_MAX_I2C_DEVICES]; + unsigned int chip_id; + int cur_conf; +-- +2.39.5 + diff --git a/queue-6.12/asoc-qcom-sm8250-explicitly-set-format-in-sm8250_be_.patch b/queue-6.12/asoc-qcom-sm8250-explicitly-set-format-in-sm8250_be_.patch new file mode 100644 index 0000000000..da0b24f88c --- /dev/null +++ b/queue-6.12/asoc-qcom-sm8250-explicitly-set-format-in-sm8250_be_.patch @@ -0,0 +1,49 @@ +From 5c4d49fd293c279538afc5566ca3613f22bbea05 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 16:14:30 +0000 +Subject: ASoC: qcom: sm8250: explicitly set format in + sm8250_be_hw_params_fixup() + +From: Alexey Klimov + +[ Upstream commit 89be3c15a58b2ccf31e969223c8ac93ca8932d81 ] + +Setting format to s16le is required for compressed playback on compatible +soundcards. + +Cc: Srinivas Kandagatla +Signed-off-by: Alexey Klimov +Link: https://patch.msgid.link/20250228161430.373961-1-alexey.klimov@linaro.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/qcom/sm8250.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c +index 19adadedc88a2..1001fd3213803 100644 +--- a/sound/soc/qcom/sm8250.c ++++ b/sound/soc/qcom/sm8250.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -39,9 +40,11 @@ static int sm8250_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); ++ struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + + rate->min = rate->max = 48000; + channels->min = channels->max = 2; ++ snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.12/asoc-rt722-sdca-add-some-missing-readable-registers.patch b/queue-6.12/asoc-rt722-sdca-add-some-missing-readable-registers.patch new file mode 100644 index 0000000000..504fb69fd4 --- /dev/null +++ b/queue-6.12/asoc-rt722-sdca-add-some-missing-readable-registers.patch @@ -0,0 +1,98 @@ +From 27db8278dbbd806e2fd9d3452985dde34964f400 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jan 2025 15:44:07 +0000 +Subject: ASoC: rt722-sdca: Add some missing readable registers + +From: Charles Keepax + +[ Upstream commit f9a5c4b6afc79073491acdab7f1e943ee3a19fbb ] + +Add a few missing registers from the readable register callback. + +Suggested-by: Shuming Fan +Signed-off-by: Charles Keepax +Reviewed-by: Pierre-Louis Bossart +Link: https://patch.msgid.link/20250107154408.814455-6-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/rt722-sdca-sdw.c | 49 +++++++++++++++++++++++++++++-- + 1 file changed, 46 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c +index 5449d6b5cf3d1..bf83f4bc94fc1 100644 +--- a/sound/soc/codecs/rt722-sdca-sdw.c ++++ b/sound/soc/codecs/rt722-sdca-sdw.c +@@ -28,9 +28,50 @@ static bool rt722_sdca_readable_register(struct device *dev, unsigned int reg) + 0): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_GE49, RT722_SDCA_CTL_DETECTED_MODE, + 0): +- case SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, RT722_SDCA_CTL_HIDTX_CURRENT_OWNER, +- 0) ... SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, +- RT722_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_XU03, RT722_SDCA_CTL_SELECTED_MODE, ++ 0): ++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, ++ RT722_SDCA_CTL_FU_MUTE, CH_L) ... ++ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, ++ RT722_SDCA_CTL_FU_MUTE, CH_R): ++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_XU0D, ++ RT722_SDCA_CTL_SELECTED_MODE, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, ++ RT722_SDCA_CTL_FU_MUTE, CH_L) ... ++ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, ++ RT722_SDCA_CTL_FU_MUTE, CH_R): ++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PDE40, ++ RT722_SDCA_CTL_REQ_POWER_STATE, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PDE12, ++ RT722_SDCA_CTL_REQ_POWER_STATE, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_CS01, ++ RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_CS11, ++ RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, ++ RT722_SDCA_CTL_FU_MUTE, CH_01) ... ++ SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, ++ RT722_SDCA_CTL_FU_MUTE, CH_04): ++ case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_IT26, ++ RT722_SDCA_CTL_VENDOR_DEF, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_PDE2A, ++ RT722_SDCA_CTL_REQ_POWER_STATE, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_CS1F, ++ RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, ++ RT722_SDCA_CTL_HIDTX_CURRENT_OWNER, 0) ... ++ SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, ++ RT722_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, ++ RT722_SDCA_CTL_FU_MUTE, CH_L) ... ++ SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, ++ RT722_SDCA_CTL_FU_MUTE, CH_R): ++ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_OT23, ++ RT722_SDCA_CTL_VENDOR_DEF, CH_08): ++ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_PDE23, ++ RT722_SDCA_CTL_REQ_POWER_STATE, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_CS31, ++ RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): + case RT722_BUF_ADDR_HID1 ... RT722_BUF_ADDR_HID2: + return true; + default: +@@ -74,6 +115,7 @@ static bool rt722_sdca_mbq_readable_register(struct device *dev, unsigned int re + case 0x5600000 ... 0x5600007: + case 0x5700000 ... 0x5700004: + case 0x5800000 ... 0x5800004: ++ case 0x5810000: + case 0x5b00003: + case 0x5c00011: + case 0x5d00006: +@@ -81,6 +123,7 @@ static bool rt722_sdca_mbq_readable_register(struct device *dev, unsigned int re + case 0x5f00030: + case 0x6100000 ... 0x6100051: + case 0x6100055 ... 0x6100057: ++ case 0x6100060: + case 0x6100062: + case 0x6100064 ... 0x6100065: + case 0x6100067: +-- +2.39.5 + diff --git a/queue-6.12/asoc-soc-dai-check-return-value-at-snd_soc_dai_set_t.patch b/queue-6.12/asoc-soc-dai-check-return-value-at-snd_soc_dai_set_t.patch new file mode 100644 index 0000000000..3e8f900b23 --- /dev/null +++ b/queue-6.12/asoc-soc-dai-check-return-value-at-snd_soc_dai_set_t.patch @@ -0,0 +1,54 @@ +From 04ecee4e14acd7ecfb35a5efbb9f88c19a4cd841 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 02:24:38 +0000 +Subject: ASoC: soc-dai: check return value at snd_soc_dai_set_tdm_slot() + +From: Kuninori Morimoto + +[ Upstream commit 7f1186a8d738661b941b298fd6d1d5725ed71428 ] + +snd_soc_dai_set_tdm_slot() calls .xlate_tdm_slot_mask() or +snd_soc_xlate_tdm_slot_mask(), but didn't check its return value. +Let's check it. + +This patch might break existing driver. In such case, let's makes +each func to void instead of int. + +Signed-off-by: Kuninori Morimoto +Link: https://patch.msgid.link/87o6z7yk61.wl-kuninori.morimoto.gx@renesas.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/soc-dai.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c +index 4e08892d24c62..de09d21add453 100644 +--- a/sound/soc/soc-dai.c ++++ b/sound/soc/soc-dai.c +@@ -275,10 +275,11 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, + + if (dai->driver->ops && + dai->driver->ops->xlate_tdm_slot_mask) +- dai->driver->ops->xlate_tdm_slot_mask(slots, +- &tx_mask, &rx_mask); ++ ret = dai->driver->ops->xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); + else +- snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); ++ ret = snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); ++ if (ret) ++ goto err; + + for_each_pcm_streams(stream) + snd_soc_dai_tdm_mask_set(dai, stream, *tdm_mask[stream]); +@@ -287,6 +288,7 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, + dai->driver->ops->set_tdm_slot) + ret = dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, + slots, slot_width); ++err: + return soc_dai_ret(dai, ret); + } + EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); +-- +2.39.5 + diff --git a/queue-6.12/asoc-sun4i-codec-support-hp-det-gpios-property.patch b/queue-6.12/asoc-sun4i-codec-support-hp-det-gpios-property.patch new file mode 100644 index 0000000000..ac6433227d --- /dev/null +++ b/queue-6.12/asoc-sun4i-codec-support-hp-det-gpios-property.patch @@ -0,0 +1,128 @@ +From 120e7700de4352fba94199762f5b5fe25f4779f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Feb 2025 11:02:25 +1300 +Subject: ASoC: sun4i-codec: support hp-det-gpios property + +From: Ryan Walklin + +[ Upstream commit a149377c033afe6557c50892ebbfc0e8b7e2e253 ] + +Add support for GPIO headphone detection with the hp-det-gpios +property. In order for this to properly disable the path upon +removal of headphones, the output must be labelled Headphone which +is a common sink in the driver. + +Describe a headphone jack and detection GPIO in the driver, check for +a corresponding device tree node, and enable jack detection in a new +machine init function if described. + +Signed-off-by: Chris Morgan +Signed-off-by: Ryan Walklin + +-- +Changelog v1..v2: +- Separate DAPM changes into separate patch and add rationale. + +Tested-by: Philippe Simons +Link: https://patch.msgid.link/20250214220247.10810-4-ryan@testtoast.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/sunxi/sun4i-codec.c | 53 +++++++++++++++++++++++++++++++++++ + 1 file changed, 53 insertions(+) + +diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c +index 330bc0c09f56b..93dd88fb805dd 100644 +--- a/sound/soc/sunxi/sun4i-codec.c ++++ b/sound/soc/sunxi/sun4i-codec.c +@@ -21,6 +21,7 @@ + #include + + #include ++#include + #include + #include + #include +@@ -235,6 +236,7 @@ struct sun4i_codec { + struct clk *clk_module; + struct reset_control *rst; + struct gpio_desc *gpio_pa; ++ struct gpio_desc *gpio_hp; + + /* ADC_FIFOC register is at different offset on different SoCs */ + struct regmap_field *reg_adc_fifoc; +@@ -1263,6 +1265,49 @@ static struct snd_soc_dai_driver dummy_cpu_dai = { + .ops = &dummy_dai_ops, + }; + ++static struct snd_soc_jack sun4i_headphone_jack; ++ ++static struct snd_soc_jack_pin sun4i_headphone_jack_pins[] = { ++ { .pin = "Headphone", .mask = SND_JACK_HEADPHONE }, ++}; ++ ++static struct snd_soc_jack_gpio sun4i_headphone_jack_gpio = { ++ .name = "hp-det", ++ .report = SND_JACK_HEADPHONE, ++ .debounce_time = 150, ++}; ++ ++static int sun4i_codec_machine_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_card *card = rtd->card; ++ struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card); ++ int ret; ++ ++ if (scodec->gpio_hp) { ++ ret = snd_soc_card_jack_new_pins(card, "Headphone Jack", ++ SND_JACK_HEADPHONE, ++ &sun4i_headphone_jack, ++ sun4i_headphone_jack_pins, ++ ARRAY_SIZE(sun4i_headphone_jack_pins)); ++ if (ret) { ++ dev_err(rtd->dev, ++ "Headphone jack creation failed: %d\n", ret); ++ return ret; ++ } ++ ++ sun4i_headphone_jack_gpio.desc = scodec->gpio_hp; ++ ret = snd_soc_jack_add_gpios(&sun4i_headphone_jack, 1, ++ &sun4i_headphone_jack_gpio); ++ ++ if (ret) { ++ dev_err(rtd->dev, "Headphone GPIO not added: %d\n", ret); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ + static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev, + int *num_links) + { +@@ -1288,6 +1333,7 @@ static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev, + link->codecs->name = dev_name(dev); + link->platforms->name = dev_name(dev); + link->dai_fmt = SND_SOC_DAIFMT_I2S; ++ link->init = sun4i_codec_machine_init; + + *num_links = 1; + +@@ -1728,6 +1774,13 @@ static int sun4i_codec_probe(struct platform_device *pdev) + return ret; + } + ++ scodec->gpio_hp = devm_gpiod_get_optional(&pdev->dev, "hp-det", GPIOD_IN); ++ if (IS_ERR(scodec->gpio_hp)) { ++ ret = PTR_ERR(scodec->gpio_hp); ++ dev_err_probe(&pdev->dev, ret, "Failed to get hp-det gpio\n"); ++ return ret; ++ } ++ + /* reg_field setup */ + scodec->reg_adc_fifoc = devm_regmap_field_alloc(&pdev->dev, + scodec->regmap, +-- +2.39.5 + diff --git a/queue-6.12/asoc-tas2764-add-reg-defaults-for-tas2764_int_clk_cf.patch b/queue-6.12/asoc-tas2764-add-reg-defaults-for-tas2764_int_clk_cf.patch new file mode 100644 index 0000000000..0c3df757dc --- /dev/null +++ b/queue-6.12/asoc-tas2764-add-reg-defaults-for-tas2764_int_clk_cf.patch @@ -0,0 +1,33 @@ +From 2bb4f14b7a2536b8fa4b8e9874d097c2396d5e7a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Feb 2025 01:03:27 +0000 +Subject: ASoC: tas2764: Add reg defaults for TAS2764_INT_CLK_CFG + +From: Hector Martin + +[ Upstream commit d64c4c3d1c578f98d70db1c5e2535b47adce9d07 ] + +Signed-off-by: Hector Martin +Signed-off-by: Mark Brown +Link: https://patch.msgid.link/20250208-asoc-tas2764-v1-4-dbab892a69b5@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2764.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c +index 58315eab492a1..bc0a73fc7ab41 100644 +--- a/sound/soc/codecs/tas2764.c ++++ b/sound/soc/codecs/tas2764.c +@@ -634,6 +634,7 @@ static const struct reg_default tas2764_reg_defaults[] = { + { TAS2764_TDM_CFG2, 0x0a }, + { TAS2764_TDM_CFG3, 0x10 }, + { TAS2764_TDM_CFG5, 0x42 }, ++ { TAS2764_INT_CLK_CFG, 0x19 }, + }; + + static const struct regmap_range_cfg tas2764_regmap_ranges[] = { +-- +2.39.5 + diff --git a/queue-6.12/asoc-tas2764-mark-sw_reset-as-volatile.patch b/queue-6.12/asoc-tas2764-mark-sw_reset-as-volatile.patch new file mode 100644 index 0000000000..386d77f9b2 --- /dev/null +++ b/queue-6.12/asoc-tas2764-mark-sw_reset-as-volatile.patch @@ -0,0 +1,35 @@ +From 7d8f30b329b7c16aa9c9cc587556193499216d3d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Feb 2025 01:03:26 +0000 +Subject: ASoC: tas2764: Mark SW_RESET as volatile + +From: Hector Martin + +[ Upstream commit f37f1748564ac51d32f7588bd7bfc99913ccab8e ] + +Since the bit is self-clearing. + +Signed-off-by: Hector Martin +Signed-off-by: Mark Brown +Link: https://patch.msgid.link/20250208-asoc-tas2764-v1-3-dbab892a69b5@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2764.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c +index bc0a73fc7ab41..31f94c8cf2844 100644 +--- a/sound/soc/codecs/tas2764.c ++++ b/sound/soc/codecs/tas2764.c +@@ -652,6 +652,7 @@ static const struct regmap_range_cfg tas2764_regmap_ranges[] = { + static bool tas2764_volatile_register(struct device *dev, unsigned int reg) + { + switch (reg) { ++ case TAS2764_SW_RST: + case TAS2764_INT_LTCH0 ... TAS2764_INT_LTCH4: + case TAS2764_INT_CLK_CFG: + return true; +-- +2.39.5 + diff --git a/queue-6.12/asoc-tas2764-power-up-down-amp-on-mute-ops.patch b/queue-6.12/asoc-tas2764-power-up-down-amp-on-mute-ops.patch new file mode 100644 index 0000000000..951e21be89 --- /dev/null +++ b/queue-6.12/asoc-tas2764-power-up-down-amp-on-mute-ops.patch @@ -0,0 +1,108 @@ +From aa61e1a3eba50eecb637475e9a88a6e98fb05114 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Feb 2025 01:03:24 +0000 +Subject: ASoC: tas2764: Power up/down amp on mute ops + +From: Hector Martin + +[ Upstream commit 1c3b5f37409682184669457a5bdf761268eafbe5 ] + +The ASoC convention is that clocks are removed after codec mute, and +power up/down is more about top level power management. For these chips, +the "mute" state still expects a TDM clock, and yanking the clock in +this state will trigger clock errors. So, do the full +shutdown<->mute<->active transition on the mute operation, so the amp is +in software shutdown by the time the clocks are removed. + +This fixes TDM clock errors when streams are stopped. + +Signed-off-by: Hector Martin +Signed-off-by: Mark Brown +Link: https://patch.msgid.link/20250208-asoc-tas2764-v1-1-dbab892a69b5@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2764.c | 51 ++++++++++++++++---------------------- + 1 file changed, 21 insertions(+), 30 deletions(-) + +diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c +index 31f94c8cf2844..39a7d39536fe6 100644 +--- a/sound/soc/codecs/tas2764.c ++++ b/sound/soc/codecs/tas2764.c +@@ -180,33 +180,6 @@ static SOC_ENUM_SINGLE_DECL( + static const struct snd_kcontrol_new tas2764_asi1_mux = + SOC_DAPM_ENUM("ASI1 Source", tas2764_ASI1_src_enum); + +-static int tas2764_dac_event(struct snd_soc_dapm_widget *w, +- struct snd_kcontrol *kcontrol, int event) +-{ +- struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); +- struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component); +- int ret; +- +- switch (event) { +- case SND_SOC_DAPM_POST_PMU: +- tas2764->dac_powered = true; +- ret = tas2764_update_pwr_ctrl(tas2764); +- break; +- case SND_SOC_DAPM_PRE_PMD: +- tas2764->dac_powered = false; +- ret = tas2764_update_pwr_ctrl(tas2764); +- break; +- default: +- dev_err(tas2764->dev, "Unsupported event\n"); +- return -EINVAL; +- } +- +- if (ret < 0) +- return ret; +- +- return 0; +-} +- + static const struct snd_kcontrol_new isense_switch = + SOC_DAPM_SINGLE("Switch", TAS2764_PWR_CTRL, TAS2764_ISENSE_POWER_EN, 1, 1); + static const struct snd_kcontrol_new vsense_switch = +@@ -219,8 +192,7 @@ static const struct snd_soc_dapm_widget tas2764_dapm_widgets[] = { + 1, &isense_switch), + SND_SOC_DAPM_SWITCH("VSENSE", TAS2764_PWR_CTRL, TAS2764_VSENSE_POWER_EN, + 1, &vsense_switch), +- SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2764_dac_event, +- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), ++ SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_OUTPUT("OUT"), + SND_SOC_DAPM_SIGGEN("VMON"), + SND_SOC_DAPM_SIGGEN("IMON") +@@ -241,9 +213,28 @@ static int tas2764_mute(struct snd_soc_dai *dai, int mute, int direction) + { + struct tas2764_priv *tas2764 = + snd_soc_component_get_drvdata(dai->component); ++ int ret; ++ ++ if (!mute) { ++ tas2764->dac_powered = true; ++ ret = tas2764_update_pwr_ctrl(tas2764); ++ if (ret) ++ return ret; ++ } + + tas2764->unmuted = !mute; +- return tas2764_update_pwr_ctrl(tas2764); ++ ret = tas2764_update_pwr_ctrl(tas2764); ++ if (ret) ++ return ret; ++ ++ if (mute) { ++ tas2764->dac_powered = false; ++ ret = tas2764_update_pwr_ctrl(tas2764); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; + } + + static int tas2764_set_bitwidth(struct tas2764_priv *tas2764, int bitwidth) +-- +2.39.5 + diff --git a/queue-6.12/auxdisplay-charlcd-partially-revert-move-hwidth-and-.patch b/queue-6.12/auxdisplay-charlcd-partially-revert-move-hwidth-and-.patch new file mode 100644 index 0000000000..0127a879e5 --- /dev/null +++ b/queue-6.12/auxdisplay-charlcd-partially-revert-move-hwidth-and-.patch @@ -0,0 +1,117 @@ +From fb4e36494e0ad2aea2888f66f15e50c0798338ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 19:27:38 +0200 +Subject: auxdisplay: charlcd: Partially revert "Move hwidth and bwidth to + struct hd44780_common" + +From: Andy Shevchenko + +[ Upstream commit 09965a142078080fe7807bab0f6f1890cb5987a4 ] + +Commit 2545c1c948a6 ("auxdisplay: Move hwidth and bwidth to struct +hd44780_common") makes charlcd_alloc() argument-less effectively dropping +the single allocation for the struct charlcd_priv object along with +the driver specific one. Restore that behaviour here. + +Signed-off-by: Andy Shevchenko +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + drivers/auxdisplay/charlcd.c | 5 +++-- + drivers/auxdisplay/charlcd.h | 5 +++-- + drivers/auxdisplay/hd44780.c | 2 +- + drivers/auxdisplay/lcd2s.c | 2 +- + drivers/auxdisplay/panel.c | 2 +- + 5 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c +index 19b619376d48b..09020bb8ad15f 100644 +--- a/drivers/auxdisplay/charlcd.c ++++ b/drivers/auxdisplay/charlcd.c +@@ -595,18 +595,19 @@ static int charlcd_init(struct charlcd *lcd) + return 0; + } + +-struct charlcd *charlcd_alloc(void) ++struct charlcd *charlcd_alloc(unsigned int drvdata_size) + { + struct charlcd_priv *priv; + struct charlcd *lcd; + +- priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ priv = kzalloc(sizeof(*priv) + drvdata_size, GFP_KERNEL); + if (!priv) + return NULL; + + priv->esc_seq.len = -1; + + lcd = &priv->lcd; ++ lcd->drvdata = priv->drvdata; + + return lcd; + } +diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h +index 4d4287209d04c..d10b89740bcae 100644 +--- a/drivers/auxdisplay/charlcd.h ++++ b/drivers/auxdisplay/charlcd.h +@@ -51,7 +51,7 @@ struct charlcd { + unsigned long y; + } addr; + +- void *drvdata; ++ void *drvdata; /* Set by charlcd_alloc() */ + }; + + /** +@@ -95,7 +95,8 @@ struct charlcd_ops { + }; + + void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on); +-struct charlcd *charlcd_alloc(void); ++ ++struct charlcd *charlcd_alloc(unsigned int drvdata_size); + void charlcd_free(struct charlcd *lcd); + + int charlcd_register(struct charlcd *lcd); +diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c +index 41807ce363399..9428f951c9bf2 100644 +--- a/drivers/auxdisplay/hd44780.c ++++ b/drivers/auxdisplay/hd44780.c +@@ -226,7 +226,7 @@ static int hd44780_probe(struct platform_device *pdev) + if (!hdc) + return -ENOMEM; + +- lcd = charlcd_alloc(); ++ lcd = charlcd_alloc(0); + if (!lcd) + goto fail1; + +diff --git a/drivers/auxdisplay/lcd2s.c b/drivers/auxdisplay/lcd2s.c +index 6422be0dfe20e..0ecf6a9469f24 100644 +--- a/drivers/auxdisplay/lcd2s.c ++++ b/drivers/auxdisplay/lcd2s.c +@@ -307,7 +307,7 @@ static int lcd2s_i2c_probe(struct i2c_client *i2c) + if (err < 0) + return err; + +- lcd = charlcd_alloc(); ++ lcd = charlcd_alloc(0); + if (!lcd) + return -ENOMEM; + +diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c +index 6dc8798d01f98..4da142692d55f 100644 +--- a/drivers/auxdisplay/panel.c ++++ b/drivers/auxdisplay/panel.c +@@ -835,7 +835,7 @@ static void lcd_init(void) + if (!hdc) + return; + +- charlcd = charlcd_alloc(); ++ charlcd = charlcd_alloc(0); + if (!charlcd) { + kfree(hdc); + return; +-- +2.39.5 + diff --git a/queue-6.12/badblocks-fix-a-nonsense-warn_on-which-checks-whethe.patch b/queue-6.12/badblocks-fix-a-nonsense-warn_on-which-checks-whethe.patch new file mode 100644 index 0000000000..d78a59f120 --- /dev/null +++ b/queue-6.12/badblocks-fix-a-nonsense-warn_on-which-checks-whethe.patch @@ -0,0 +1,55 @@ +From c8c407a7308fc6c6717eec28820f262285aba85a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Mar 2025 12:05:56 -0400 +Subject: badblocks: Fix a nonsense WARN_ON() which checks whether a u64 + variable < 0 + +From: Coly Li + +[ Upstream commit 7e76336e14de9a2b67af96012ddd46c5676cf340 ] + +In _badblocks_check(), there are lines of code like this, +1246 sectors -= len; +[snipped] +1251 WARN_ON(sectors < 0); + +The WARN_ON() at line 1257 doesn't make sense because sectors is +unsigned long long type and never to be <0. + +Fix it by checking directly checking whether sectors is less than len. + +Reported-by: Dan Carpenter +Signed-off-by: Coly Li +Reviewed-by: Yu Kuai +Link: https://lore.kernel.org/r/20250309160556.42854-1-colyli@kernel.org +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/badblocks.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/block/badblocks.c b/block/badblocks.c +index db4ec8b9b2a8c..a9709771a1015 100644 +--- a/block/badblocks.c ++++ b/block/badblocks.c +@@ -1349,14 +1349,15 @@ static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors, + len = sectors; + + update_sectors: ++ /* This situation should never happen */ ++ WARN_ON(sectors < len); ++ + s += len; + sectors -= len; + + if (sectors > 0) + goto re_check; + +- WARN_ON(sectors < 0); +- + if (unacked_badblocks > 0) + rv = -1; + else if (acked_badblocks > 0) +-- +2.39.5 + diff --git a/queue-6.12/blk-cgroup-improve-policy-registration-error-handlin.patch b/queue-6.12/blk-cgroup-improve-policy-registration-error-handlin.patch new file mode 100644 index 0000000000..c536e34651 --- /dev/null +++ b/queue-6.12/blk-cgroup-improve-policy-registration-error-handlin.patch @@ -0,0 +1,94 @@ +From 173bba6daab32921822b3008c05d6fa0b3d2af98 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 10:29:24 +0800 +Subject: blk-cgroup: improve policy registration error handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Chen Linxuan + +[ Upstream commit e1a0202c6bfda24002a3ae2115154fa90104c649 ] + +This patch improve the returned error code of blkcg_policy_register(). + +1. Move the validation check for cpd/pd_alloc_fn and cpd/pd_free_fn + function pairs to the start of blkcg_policy_register(). This ensures + we immediately return -EINVAL if the function pairs are not correctly + provided, rather than returning -ENOSPC after locking and unlocking + mutexes unnecessarily. + + Those locks should not contention any problems, as error of policy + registration is a super cold path. + +2. Return -ENOMEM when cpd_alloc_fn() failed. + +Co-authored-by: Wen Tao +Signed-off-by: Wen Tao +Signed-off-by: Chen Linxuan +Reviewed-by: Michal Koutný +Acked-by: Tejun Heo +Reviewed-by: Yu Kuai +Link: https://lore.kernel.org/r/3E333A73B6B6DFC0+20250317022924.150907-1-chenlinxuan@uniontech.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-cgroup.c | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c +index f1cf7f2909f3a..643d6bf66522e 100644 +--- a/block/blk-cgroup.c ++++ b/block/blk-cgroup.c +@@ -1725,27 +1725,27 @@ int blkcg_policy_register(struct blkcg_policy *pol) + struct blkcg *blkcg; + int i, ret; + ++ /* ++ * Make sure cpd/pd_alloc_fn and cpd/pd_free_fn in pairs, and policy ++ * without pd_alloc_fn/pd_free_fn can't be activated. ++ */ ++ if ((!pol->cpd_alloc_fn ^ !pol->cpd_free_fn) || ++ (!pol->pd_alloc_fn ^ !pol->pd_free_fn)) ++ return -EINVAL; ++ + mutex_lock(&blkcg_pol_register_mutex); + mutex_lock(&blkcg_pol_mutex); + + /* find an empty slot */ +- ret = -ENOSPC; + for (i = 0; i < BLKCG_MAX_POLS; i++) + if (!blkcg_policy[i]) + break; + if (i >= BLKCG_MAX_POLS) { + pr_warn("blkcg_policy_register: BLKCG_MAX_POLS too small\n"); ++ ret = -ENOSPC; + goto err_unlock; + } + +- /* +- * Make sure cpd/pd_alloc_fn and cpd/pd_free_fn in pairs, and policy +- * without pd_alloc_fn/pd_free_fn can't be activated. +- */ +- if ((!pol->cpd_alloc_fn ^ !pol->cpd_free_fn) || +- (!pol->pd_alloc_fn ^ !pol->pd_free_fn)) +- goto err_unlock; +- + /* register @pol */ + pol->plid = i; + blkcg_policy[pol->plid] = pol; +@@ -1756,8 +1756,10 @@ int blkcg_policy_register(struct blkcg_policy *pol) + struct blkcg_policy_data *cpd; + + cpd = pol->cpd_alloc_fn(GFP_KERNEL); +- if (!cpd) ++ if (!cpd) { ++ ret = -ENOMEM; + goto err_free_cpds; ++ } + + blkcg->cpd[pol->plid] = cpd; + cpd->blkcg = blkcg; +-- +2.39.5 + diff --git a/queue-6.12/blk-throttle-don-t-take-carryover-for-prioritized-pr.patch b/queue-6.12/blk-throttle-don-t-take-carryover-for-prioritized-pr.patch new file mode 100644 index 0000000000..532fa61b76 --- /dev/null +++ b/queue-6.12/blk-throttle-don-t-take-carryover-for-prioritized-pr.patch @@ -0,0 +1,64 @@ +From 543a90e8dc5fd35e43385ae51cc454ce73ff8a9f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 12:31:20 +0800 +Subject: blk-throttle: don't take carryover for prioritized processing of + metadata + +From: Ming Lei + +[ Upstream commit a9fc8868b350cbf4ff730a4ea9651319cc669516 ] + +Commit 29390bb5661d ("blk-throttle: support prioritized processing of metadata") +takes bytes/ios carryover for prioritized processing of metadata. Turns out +we can support it by charging it directly without trimming slice, and the +result is same with carryover. + +Cc: Tejun Heo +Cc: Josef Bacik +Cc: Yu Kuai +Signed-off-by: Ming Lei +Acked-by: Tejun Heo +Link: https://lore.kernel.org/r/20250305043123.3938491-3-ming.lei@redhat.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-throttle.c | 15 +++++---------- + 1 file changed, 5 insertions(+), 10 deletions(-) + +diff --git a/block/blk-throttle.c b/block/blk-throttle.c +index 2c4192e12efab..6b82fcbd7e774 100644 +--- a/block/blk-throttle.c ++++ b/block/blk-throttle.c +@@ -1593,13 +1593,6 @@ static bool tg_within_limit(struct throtl_grp *tg, struct bio *bio, bool rw) + return tg_may_dispatch(tg, bio, NULL); + } + +-static void tg_dispatch_in_debt(struct throtl_grp *tg, struct bio *bio, bool rw) +-{ +- if (!bio_flagged(bio, BIO_BPS_THROTTLED)) +- tg->carryover_bytes[rw] -= throtl_bio_data_size(bio); +- tg->carryover_ios[rw]--; +-} +- + bool __blk_throtl_bio(struct bio *bio) + { + struct request_queue *q = bdev_get_queue(bio->bi_bdev); +@@ -1636,10 +1629,12 @@ bool __blk_throtl_bio(struct bio *bio) + /* + * IOs which may cause priority inversions are + * dispatched directly, even if they're over limit. +- * Debts are handled by carryover_bytes/ios while +- * calculating wait time. ++ * ++ * Charge and dispatch directly, and our throttle ++ * control algorithm is adaptive, and extra IO bytes ++ * will be throttled for paying the debt + */ +- tg_dispatch_in_debt(tg, bio, rw); ++ throtl_charge_bio(tg, bio); + } else { + /* if above limits, break to queue */ + break; +-- +2.39.5 + diff --git a/queue-6.12/block-fix-race-between-set_blocksize-and-read-paths.patch b/queue-6.12/block-fix-race-between-set_blocksize-and-read-paths.patch new file mode 100644 index 0000000000..24046a38cb --- /dev/null +++ b/queue-6.12/block-fix-race-between-set_blocksize-and-read-paths.patch @@ -0,0 +1,216 @@ +From 4acfc83afbfd346d4560f66161db62f07c6675ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Apr 2025 12:53:42 -0700 +Subject: block: fix race between set_blocksize and read paths + +From: Darrick J. Wong + +[ Upstream commit c0e473a0d226479e8e925d5ba93f751d8df628e9 ] + +With the new large sector size support, it's now the case that +set_blocksize can change i_blksize and the folio order in a manner that +conflicts with a concurrent reader and causes a kernel crash. + +Specifically, let's say that udev-worker calls libblkid to detect the +labels on a block device. The read call can create an order-0 folio to +read the first 4096 bytes from the disk. But then udev is preempted. + +Next, someone tries to mount an 8k-sectorsize filesystem from the same +block device. The filesystem calls set_blksize, which sets i_blksize to +8192 and the minimum folio order to 1. + +Now udev resumes, still holding the order-0 folio it allocated. It then +tries to schedule a read bio and do_mpage_readahead tries to create +bufferheads for the folio. Unfortunately, blocks_per_folio == 0 because +the page size is 4096 but the blocksize is 8192 so no bufferheads are +attached and the bh walk never sets bdev. We then submit the bio with a +NULL block device and crash. + +Therefore, truncate the page cache after flushing but before updating +i_blksize. However, that's not enough -- we also need to lock out file +IO and page faults during the update. Take both the i_rwsem and the +invalidate_lock in exclusive mode for invalidations, and in shared mode +for read/write operations. + +I don't know if this is the correct fix, but xfs/259 found it. + +Signed-off-by: Darrick J. Wong +Reviewed-by: Christoph Hellwig +Reviewed-by: Luis Chamberlain +Tested-by: Shin'ichiro Kawasaki +Link: https://lore.kernel.org/r/174543795699.4139148.2086129139322431423.stgit@frogsfrogsfrogs +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/bdev.c | 17 +++++++++++++++++ + block/blk-zoned.c | 5 ++++- + block/fops.c | 16 ++++++++++++++++ + block/ioctl.c | 6 ++++++ + 4 files changed, 43 insertions(+), 1 deletion(-) + +diff --git a/block/bdev.c b/block/bdev.c +index 738e3c8457e7f..e7daca6565ea6 100644 +--- a/block/bdev.c ++++ b/block/bdev.c +@@ -168,9 +168,26 @@ int set_blocksize(struct file *file, int size) + + /* Don't change the size if it is same as current */ + if (inode->i_blkbits != blksize_bits(size)) { ++ /* ++ * Flush and truncate the pagecache before we reconfigure the ++ * mapping geometry because folio sizes are variable now. If a ++ * reader has already allocated a folio whose size is smaller ++ * than the new min_order but invokes readahead after the new ++ * min_order becomes visible, readahead will think there are ++ * "zero" blocks per folio and crash. Take the inode and ++ * invalidation locks to avoid racing with ++ * read/write/fallocate. ++ */ ++ inode_lock(inode); ++ filemap_invalidate_lock(inode->i_mapping); ++ + sync_blockdev(bdev); ++ kill_bdev(bdev); ++ + inode->i_blkbits = blksize_bits(size); + kill_bdev(bdev); ++ filemap_invalidate_unlock(inode->i_mapping); ++ inode_unlock(inode); + } + return 0; + } +diff --git a/block/blk-zoned.c b/block/blk-zoned.c +index c11db5be25324..414118435240a 100644 +--- a/block/blk-zoned.c ++++ b/block/blk-zoned.c +@@ -347,6 +347,7 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode, + op = REQ_OP_ZONE_RESET; + + /* Invalidate the page cache, including dirty pages. */ ++ inode_lock(bdev->bd_mapping->host); + filemap_invalidate_lock(bdev->bd_mapping); + ret = blkdev_truncate_zone_range(bdev, mode, &zrange); + if (ret) +@@ -368,8 +369,10 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode, + ret = blkdev_zone_mgmt(bdev, op, zrange.sector, zrange.nr_sectors); + + fail: +- if (cmd == BLKRESETZONE) ++ if (cmd == BLKRESETZONE) { + filemap_invalidate_unlock(bdev->bd_mapping); ++ inode_unlock(bdev->bd_mapping->host); ++ } + + return ret; + } +diff --git a/block/fops.c b/block/fops.c +index 43983be5a2b3b..d4b1d942f2700 100644 +--- a/block/fops.c ++++ b/block/fops.c +@@ -721,7 +721,14 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) + ret = direct_write_fallback(iocb, from, ret, + blkdev_buffered_write(iocb, from)); + } else { ++ /* ++ * Take i_rwsem and invalidate_lock to avoid racing with ++ * set_blocksize changing i_blkbits/folio order and punching ++ * out the pagecache. ++ */ ++ inode_lock_shared(bd_inode); + ret = blkdev_buffered_write(iocb, from); ++ inode_unlock_shared(bd_inode); + } + + if (ret > 0) +@@ -732,6 +739,7 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) + + static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to) + { ++ struct inode *bd_inode = bdev_file_inode(iocb->ki_filp); + struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host); + loff_t size = bdev_nr_bytes(bdev); + loff_t pos = iocb->ki_pos; +@@ -768,7 +776,13 @@ static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to) + goto reexpand; + } + ++ /* ++ * Take i_rwsem and invalidate_lock to avoid racing with set_blocksize ++ * changing i_blkbits/folio order and punching out the pagecache. ++ */ ++ inode_lock_shared(bd_inode); + ret = filemap_read(iocb, to, ret); ++ inode_unlock_shared(bd_inode); + + reexpand: + if (unlikely(shorted)) +@@ -811,6 +825,7 @@ static long blkdev_fallocate(struct file *file, int mode, loff_t start, + if ((start | len) & (bdev_logical_block_size(bdev) - 1)) + return -EINVAL; + ++ inode_lock(inode); + filemap_invalidate_lock(inode->i_mapping); + + /* +@@ -843,6 +858,7 @@ static long blkdev_fallocate(struct file *file, int mode, loff_t start, + + fail: + filemap_invalidate_unlock(inode->i_mapping); ++ inode_unlock(inode); + return error; + } + +diff --git a/block/ioctl.c b/block/ioctl.c +index 6554b728bae6a..919066b4bb49c 100644 +--- a/block/ioctl.c ++++ b/block/ioctl.c +@@ -141,6 +141,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode, + if (err) + return err; + ++ inode_lock(bdev->bd_mapping->host); + filemap_invalidate_lock(bdev->bd_mapping); + err = truncate_bdev_range(bdev, mode, start, start + len - 1); + if (err) +@@ -173,6 +174,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode, + blk_finish_plug(&plug); + fail: + filemap_invalidate_unlock(bdev->bd_mapping); ++ inode_unlock(bdev->bd_mapping->host); + return err; + } + +@@ -198,12 +200,14 @@ static int blk_ioctl_secure_erase(struct block_device *bdev, blk_mode_t mode, + end > bdev_nr_bytes(bdev)) + return -EINVAL; + ++ inode_lock(bdev->bd_mapping->host); + filemap_invalidate_lock(bdev->bd_mapping); + err = truncate_bdev_range(bdev, mode, start, end - 1); + if (!err) + err = blkdev_issue_secure_erase(bdev, start >> 9, len >> 9, + GFP_KERNEL); + filemap_invalidate_unlock(bdev->bd_mapping); ++ inode_unlock(bdev->bd_mapping->host); + return err; + } + +@@ -235,6 +239,7 @@ static int blk_ioctl_zeroout(struct block_device *bdev, blk_mode_t mode, + return -EINVAL; + + /* Invalidate the page cache, including dirty pages */ ++ inode_lock(bdev->bd_mapping->host); + filemap_invalidate_lock(bdev->bd_mapping); + err = truncate_bdev_range(bdev, mode, start, end); + if (err) +@@ -245,6 +250,7 @@ static int blk_ioctl_zeroout(struct block_device *bdev, blk_mode_t mode, + + fail: + filemap_invalidate_unlock(bdev->bd_mapping); ++ inode_unlock(bdev->bd_mapping->host); + return err; + } + +-- +2.39.5 + diff --git a/queue-6.12/block-mark-bounce-buffering-as-incompatible-with-int.patch b/queue-6.12/block-mark-bounce-buffering-as-incompatible-with-int.patch new file mode 100644 index 0000000000..5ef549325f --- /dev/null +++ b/queue-6.12/block-mark-bounce-buffering-as-incompatible-with-int.patch @@ -0,0 +1,59 @@ +From 887f043325f7a555fabed1e9ea0d6f15c458176e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 07:44:31 -0800 +Subject: block: mark bounce buffering as incompatible with integrity + +From: Christoph Hellwig + +[ Upstream commit 5fd0268a8806d35dcaf89139bfcda92be51b2b2f ] + +None of the few drivers still using the legacy block layer bounce +buffering support integrity metadata. Explicitly mark the features as +incompatible and stop creating the slab and mempool for integrity +buffers for the bounce bio_set. + +Signed-off-by: Christoph Hellwig +Reviewed-by: Anuj Gupta +Reviewed-by: Martin K. Petersen +Reviewed-by: Hannes Reinecke +Reviewed-by: Johannes Thumshirn +Link: https://lore.kernel.org/r/20250225154449.422989-2-hch@lst.de +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-settings.c | 5 +++++ + block/bounce.c | 2 -- + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/block/blk-settings.c b/block/blk-settings.c +index 1e63e3dd54402..7858c92b44834 100644 +--- a/block/blk-settings.c ++++ b/block/blk-settings.c +@@ -124,6 +124,11 @@ static int blk_validate_integrity_limits(struct queue_limits *lim) + return 0; + } + ++ if (lim->features & BLK_FEAT_BOUNCE_HIGH) { ++ pr_warn("no bounce buffer support for integrity metadata\n"); ++ return -EINVAL; ++ } ++ + if (!IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY)) { + pr_warn("integrity support disabled.\n"); + return -EINVAL; +diff --git a/block/bounce.c b/block/bounce.c +index 0d898cd5ec497..09a9616cf2094 100644 +--- a/block/bounce.c ++++ b/block/bounce.c +@@ -41,8 +41,6 @@ static void init_bounce_bioset(void) + + ret = bioset_init(&bounce_bio_set, BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS); + BUG_ON(ret); +- if (bioset_integrity_create(&bounce_bio_set, BIO_POOL_SIZE)) +- BUG_ON(1); + + ret = bioset_init(&bounce_bio_split, BIO_POOL_SIZE, 0, 0); + BUG_ON(ret); +-- +2.39.5 + diff --git a/queue-6.12/block-only-update-request-sector-if-needed.patch b/queue-6.12/block-only-update-request-sector-if-needed.patch new file mode 100644 index 0000000000..f573b23e5f --- /dev/null +++ b/queue-6.12/block-only-update-request-sector-if-needed.patch @@ -0,0 +1,50 @@ +From ed32721492581310d5488c1acfd9446b5ebf4fe5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 May 2025 13:27:30 +0200 +Subject: block: only update request sector if needed + +From: Johannes Thumshirn + +[ Upstream commit db492e24f9b05547ba12b4783f09c9d943cf42fe ] + +In case of a ZONE APPEND write, regardless of native ZONE APPEND or the +emulation layer in the zone write plugging code, the sector the data got +written to by the device needs to be updated in the bio. + +At the moment, this is done for every native ZONE APPEND write and every +request that is flagged with 'BIO_ZONE_WRITE_PLUGGING'. But thus +superfluously updates the sector for regular writes to a zoned block +device. + +Check if a bio is a native ZONE APPEND write or if the bio is flagged as +'BIO_EMULATES_ZONE_APPEND', meaning the block layer's zone write plugging +code handles the ZONE APPEND and translates it into a regular write and +back. Only if one of these two criterion is met, update the sector in the +bio upon completion. + +Signed-off-by: Johannes Thumshirn +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/dea089581cb6b777c1cd1500b38ac0b61df4b2d1.1746530748.git.jth@kernel.org +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/block/blk.h b/block/blk.h +index 1426f9c281973..e91012247ff29 100644 +--- a/block/blk.h ++++ b/block/blk.h +@@ -482,7 +482,8 @@ static inline void blk_zone_update_request_bio(struct request *rq, + * the original BIO sector so that blk_zone_write_plug_bio_endio() can + * lookup the zone write plug. + */ +- if (req_op(rq) == REQ_OP_ZONE_APPEND || bio_zone_write_plugging(bio)) ++ if (req_op(rq) == REQ_OP_ZONE_APPEND || ++ bio_flagged(bio, BIO_EMULATES_ZONE_APPEND)) + bio->bi_iter.bi_sector = rq->__sector; + } + void blk_zone_write_plug_bio_endio(struct bio *bio); +-- +2.39.5 + diff --git a/queue-6.12/bluetooth-btmtksdio-prevent-enabling-interrupts-afte.patch b/queue-6.12/bluetooth-btmtksdio-prevent-enabling-interrupts-afte.patch new file mode 100644 index 0000000000..98ecdae062 --- /dev/null +++ b/queue-6.12/bluetooth-btmtksdio-prevent-enabling-interrupts-afte.patch @@ -0,0 +1,45 @@ +From 0922694798881d86948270f468bd2c32e2eac5d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 18:25:22 -0700 +Subject: Bluetooth: btmtksdio: Prevent enabling interrupts after IRQ handler + removal + +From: Sean Wang + +[ Upstream commit 6ac4233afb9a389a7629b7f812395d1d1eca5a83 ] + +Ensure interrupts are not re-enabled when the IRQ handler has already been +removed. This prevents unexpected IRQ handler execution due to stale or +unhandled interrupts. + +Modify btmtksdio_txrx_work to check if bdev->func->irq_handler exists +before calling sdio_writel to enable interrupts. + +Co-developed-by: Pedro Tsai +Signed-off-by: Pedro Tsai +Co-developed-by: Felix Freimann +Signed-off-by: Felix Freimann +Signed-off-by: Sean Wang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btmtksdio.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c +index 11d33cd7b08fc..d4ea1ff07b3e7 100644 +--- a/drivers/bluetooth/btmtksdio.c ++++ b/drivers/bluetooth/btmtksdio.c +@@ -610,7 +610,8 @@ static void btmtksdio_txrx_work(struct work_struct *work) + } while (int_status || time_is_before_jiffies(txrx_timeout)); + + /* Enable interrupt */ +- sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL); ++ if (bdev->func->irq_handler) ++ sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL); + + sdio_release_host(bdev->func); + +-- +2.39.5 + diff --git a/queue-6.12/bluetooth-disable-sco-support-if-read_voice_setting-.patch b/queue-6.12/bluetooth-disable-sco-support-if-read_voice_setting-.patch new file mode 100644 index 0000000000..a70cf40886 --- /dev/null +++ b/queue-6.12/bluetooth-disable-sco-support-if-read_voice_setting-.patch @@ -0,0 +1,37 @@ +From f49055f2f9fc27104bb2b52f58c3c857013e59cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Mar 2025 03:23:00 -0300 +Subject: Bluetooth: Disable SCO support if READ_VOICE_SETTING is + unsupported/broken + +From: Pedro Nishiyama + +[ Upstream commit 14d17c78a4b1660c443bae9d38c814edea506f62 ] + +A SCO connection without the proper voice_setting can cause +the controller to lock up. + +Signed-off-by: Pedro Nishiyama +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index bc5b42fce2b80..8894633403519 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -932,6 +932,9 @@ static u8 hci_cc_read_buffer_size(struct hci_dev *hdev, void *data, + hdev->sco_pkts = 8; + } + ++ if (!read_voice_setting_capable(hdev)) ++ hdev->sco_pkts = 0; ++ + hdev->acl_cnt = hdev->acl_pkts; + hdev->sco_cnt = hdev->sco_pkts; + +-- +2.39.5 + diff --git a/queue-6.12/bnxt_en-query-fw-parameters-when-the-caps_change-bit.patch b/queue-6.12/bnxt_en-query-fw-parameters-when-the-caps_change-bit.patch new file mode 100644 index 0000000000..40bd3587c0 --- /dev/null +++ b/queue-6.12/bnxt_en-query-fw-parameters-when-the-caps_change-bit.patch @@ -0,0 +1,57 @@ +From e84b1d73967907862eb93a7fa124a30d6ab12d6f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 11:31:26 -0700 +Subject: bnxt_en: Query FW parameters when the CAPS_CHANGE bit is set + +From: shantiprasad shettar + +[ Upstream commit a6c81e32aeacbfd530d576fa401edd506ec966ef ] + +Newer FW can set the CAPS_CHANGE flag during ifup if some capabilities +or configurations have changed. For example, the CoS queue +configurations may have changed. Support this new flag by treating it +almost like FW reset. The driver will essentially rediscover all +features and capabilities, reconfigure all backing store context memory, +reset everything to default, and reserve all resources. + +Reviewed-by: Somnath Kotur +Reviewed-by: Pavan Chebbi +Signed-off-by: shantiprasad shettar +Signed-off-by: Michael Chan +Link: https://patch.msgid.link/20250310183129.3154117-5-michael.chan@broadcom.com +Reviewed-by: Jacob Keller +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index 12b61a6fcda42..2bb1fce350dbb 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -11783,6 +11783,7 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up) + struct hwrm_func_drv_if_change_input *req; + bool fw_reset = !bp->irq_tbl; + bool resc_reinit = false; ++ bool caps_change = false; + int rc, retry = 0; + u32 flags = 0; + +@@ -11838,8 +11839,11 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up) + set_bit(BNXT_STATE_ABORT_ERR, &bp->state); + return -ENODEV; + } +- if (resc_reinit || fw_reset) { +- if (fw_reset) { ++ if (flags & FUNC_DRV_IF_CHANGE_RESP_FLAGS_CAPS_CHANGE) ++ caps_change = true; ++ ++ if (resc_reinit || fw_reset || caps_change) { ++ if (fw_reset || caps_change) { + set_bit(BNXT_STATE_FW_RESET_DET, &bp->state); + if (!test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) + bnxt_ulp_irq_stop(bp); +-- +2.39.5 + diff --git a/queue-6.12/bonding-report-duplicate-mac-address-in-all-situatio.patch b/queue-6.12/bonding-report-duplicate-mac-address-in-all-situatio.patch new file mode 100644 index 0000000000..a34994fdfe --- /dev/null +++ b/queue-6.12/bonding-report-duplicate-mac-address-in-all-situatio.patch @@ -0,0 +1,47 @@ +From a78fe7703a7fc7380a9324b62183215c6e2fed43 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 03:39:14 +0000 +Subject: bonding: report duplicate MAC address in all situations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Hangbin Liu + +[ Upstream commit 28d68d396a1cd21591e8c6d74afbde33a7ea107e ] + +Normally, a bond uses the MAC address of the first added slave as the bond’s +MAC address. And the bond will set active slave’s MAC address to bond’s +address if fail_over_mac is set to none (0) or follow (2). + +When the first slave is removed, the bond will still use the removed slave’s +MAC address, which can lead to a duplicate MAC address and potentially cause +issues with the switch. To avoid confusion, let's warn the user in all +situations, including when fail_over_mac is set to 2 or not in active-backup +mode. + +Signed-off-by: Hangbin Liu +Reviewed-by: Nikolay Aleksandrov +Link: https://patch.msgid.link/20250225033914.18617-1-liuhangbin@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/bonding/bond_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 4d73abae503d1..4d2e30f4ee250 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -2542,7 +2542,7 @@ static int __bond_release_one(struct net_device *bond_dev, + + RCU_INIT_POINTER(bond->current_arp_slave, NULL); + +- if (!all && (!bond->params.fail_over_mac || ++ if (!all && (bond->params.fail_over_mac != BOND_FOM_ACTIVE || + BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP)) { + if (ether_addr_equal_64bits(bond_dev->dev_addr, slave->perm_hwaddr) && + bond_has_slaves(bond)) +-- +2.39.5 + diff --git a/queue-6.12/book3s64-radix-fix-compile-errors-when-config_arch_w.patch b/queue-6.12/book3s64-radix-fix-compile-errors-when-config_arch_w.patch new file mode 100644 index 0000000000..2f9f26e6b2 --- /dev/null +++ b/queue-6.12/book3s64-radix-fix-compile-errors-when-config_arch_w.patch @@ -0,0 +1,45 @@ +From 5bc9d4c7eb5541ed4b893acc8e799a7a9ee6df28 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 07:44:09 -0500 +Subject: book3s64/radix: Fix compile errors when + CONFIG_ARCH_WANT_OPTIMIZE_DAX_VMEMMAP=n + +From: Ritesh Harjani (IBM) + +[ Upstream commit 29bdc1f1c1df80868fb35bc69d1f073183adc6de ] + +Fix compile errors when CONFIG_ARCH_WANT_OPTIMIZE_DAX_VMEMMAP=n + +Signed-off-by: Ritesh Harjani (IBM) +Signed-off-by: Donet Tom +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/8231763344223c193e3452eab0ae8ea966aff466.1741609795.git.donettom@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/mm/book3s64/radix_pgtable.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c +index 04189689c127e..0d807bf2328d8 100644 +--- a/arch/powerpc/mm/book3s64/radix_pgtable.c ++++ b/arch/powerpc/mm/book3s64/radix_pgtable.c +@@ -988,7 +988,7 @@ int __meminit radix__vmemmap_create_mapping(unsigned long start, + return 0; + } + +- ++#ifdef CONFIG_ARCH_WANT_OPTIMIZE_DAX_VMEMMAP + bool vmemmap_can_optimize(struct vmem_altmap *altmap, struct dev_pagemap *pgmap) + { + if (radix_enabled()) +@@ -996,6 +996,7 @@ bool vmemmap_can_optimize(struct vmem_altmap *altmap, struct dev_pagemap *pgmap) + + return false; + } ++#endif + + int __meminit vmemmap_check_pmd(pmd_t *pmdp, int node, + unsigned long addr, unsigned long next) +-- +2.39.5 + diff --git a/queue-6.12/bpf-allow-pre-ordering-for-bpf-cgroup-progs.patch b/queue-6.12/bpf-allow-pre-ordering-for-bpf-cgroup-progs.patch new file mode 100644 index 0000000000..ebcd61aad6 --- /dev/null +++ b/queue-6.12/bpf-allow-pre-ordering-for-bpf-cgroup-progs.patch @@ -0,0 +1,223 @@ +From c1c2811e9b79c9c8bd90fb733384f88ac68c336e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 15:01:16 -0800 +Subject: bpf: Allow pre-ordering for bpf cgroup progs + +From: Yonghong Song + +[ Upstream commit 4b82b181a26cff8bf7adc3a85a88d121d92edeaf ] + +Currently for bpf progs in a cgroup hierarchy, the effective prog array +is computed from bottom cgroup to upper cgroups (post-ordering). For +example, the following cgroup hierarchy + root cgroup: p1, p2 + subcgroup: p3, p4 +have BPF_F_ALLOW_MULTI for both cgroup levels. +The effective cgroup array ordering looks like + p3 p4 p1 p2 +and at run time, progs will execute based on that order. + +But in some cases, it is desirable to have root prog executes earlier than +children progs (pre-ordering). For example, + - prog p1 intends to collect original pkt dest addresses. + - prog p3 will modify original pkt dest addresses to a proxy address for + security reason. +The end result is that prog p1 gets proxy address which is not what it +wants. Putting p1 to every child cgroup is not desirable either as it +will duplicate itself in many child cgroups. And this is exactly a use case +we are encountering in Meta. + +To fix this issue, let us introduce a flag BPF_F_PREORDER. If the flag +is specified at attachment time, the prog has higher priority and the +ordering with that flag will be from top to bottom (pre-ordering). +For example, in the above example, + root cgroup: p1, p2 + subcgroup: p3, p4 +Let us say p2 and p4 are marked with BPF_F_PREORDER. The final +effective array ordering will be + p2 p4 p3 p1 + +Suggested-by: Andrii Nakryiko +Acked-by: Andrii Nakryiko +Signed-off-by: Yonghong Song +Link: https://lore.kernel.org/r/20250224230116.283071-1-yonghong.song@linux.dev +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + include/linux/bpf-cgroup.h | 1 + + include/uapi/linux/bpf.h | 1 + + kernel/bpf/cgroup.c | 33 +++++++++++++++++++++++++-------- + kernel/bpf/syscall.c | 3 ++- + tools/include/uapi/linux/bpf.h | 1 + + 5 files changed, 30 insertions(+), 9 deletions(-) + +diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h +index ce91d9b2acb9f..7e029c82ae45f 100644 +--- a/include/linux/bpf-cgroup.h ++++ b/include/linux/bpf-cgroup.h +@@ -111,6 +111,7 @@ struct bpf_prog_list { + struct bpf_prog *prog; + struct bpf_cgroup_link *link; + struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE]; ++ u32 flags; + }; + + int cgroup_bpf_inherit(struct cgroup *cgrp); +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index 4a939c90dc2e4..552fd633f8200 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -1206,6 +1206,7 @@ enum bpf_perf_event_type { + #define BPF_F_BEFORE (1U << 3) + #define BPF_F_AFTER (1U << 4) + #define BPF_F_ID (1U << 5) ++#define BPF_F_PREORDER (1U << 6) + #define BPF_F_LINK BPF_F_LINK /* 1 << 13 */ + + /* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the +diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c +index 025d7e2214aeb..c0d606c40195d 100644 +--- a/kernel/bpf/cgroup.c ++++ b/kernel/bpf/cgroup.c +@@ -369,7 +369,7 @@ static struct bpf_prog *prog_list_prog(struct bpf_prog_list *pl) + /* count number of elements in the list. + * it's slow but the list cannot be long + */ +-static u32 prog_list_length(struct hlist_head *head) ++static u32 prog_list_length(struct hlist_head *head, int *preorder_cnt) + { + struct bpf_prog_list *pl; + u32 cnt = 0; +@@ -377,6 +377,8 @@ static u32 prog_list_length(struct hlist_head *head) + hlist_for_each_entry(pl, head, node) { + if (!prog_list_prog(pl)) + continue; ++ if (preorder_cnt && (pl->flags & BPF_F_PREORDER)) ++ (*preorder_cnt)++; + cnt++; + } + return cnt; +@@ -400,7 +402,7 @@ static bool hierarchy_allows_attach(struct cgroup *cgrp, + + if (flags & BPF_F_ALLOW_MULTI) + return true; +- cnt = prog_list_length(&p->bpf.progs[atype]); ++ cnt = prog_list_length(&p->bpf.progs[atype], NULL); + WARN_ON_ONCE(cnt > 1); + if (cnt == 1) + return !!(flags & BPF_F_ALLOW_OVERRIDE); +@@ -423,12 +425,12 @@ static int compute_effective_progs(struct cgroup *cgrp, + struct bpf_prog_array *progs; + struct bpf_prog_list *pl; + struct cgroup *p = cgrp; +- int cnt = 0; ++ int i, j, cnt = 0, preorder_cnt = 0, fstart, bstart, init_bstart; + + /* count number of effective programs by walking parents */ + do { + if (cnt == 0 || (p->bpf.flags[atype] & BPF_F_ALLOW_MULTI)) +- cnt += prog_list_length(&p->bpf.progs[atype]); ++ cnt += prog_list_length(&p->bpf.progs[atype], &preorder_cnt); + p = cgroup_parent(p); + } while (p); + +@@ -439,20 +441,34 @@ static int compute_effective_progs(struct cgroup *cgrp, + /* populate the array with effective progs */ + cnt = 0; + p = cgrp; ++ fstart = preorder_cnt; ++ bstart = preorder_cnt - 1; + do { + if (cnt > 0 && !(p->bpf.flags[atype] & BPF_F_ALLOW_MULTI)) + continue; + ++ init_bstart = bstart; + hlist_for_each_entry(pl, &p->bpf.progs[atype], node) { + if (!prog_list_prog(pl)) + continue; + +- item = &progs->items[cnt]; ++ if (pl->flags & BPF_F_PREORDER) { ++ item = &progs->items[bstart]; ++ bstart--; ++ } else { ++ item = &progs->items[fstart]; ++ fstart++; ++ } + item->prog = prog_list_prog(pl); + bpf_cgroup_storages_assign(item->cgroup_storage, + pl->storage); + cnt++; + } ++ ++ /* reverse pre-ordering progs at this cgroup level */ ++ for (i = bstart + 1, j = init_bstart; i < j; i++, j--) ++ swap(progs->items[i], progs->items[j]); ++ + } while ((p = cgroup_parent(p))); + + *array = progs; +@@ -663,7 +679,7 @@ static int __cgroup_bpf_attach(struct cgroup *cgrp, + */ + return -EPERM; + +- if (prog_list_length(progs) >= BPF_CGROUP_MAX_PROGS) ++ if (prog_list_length(progs, NULL) >= BPF_CGROUP_MAX_PROGS) + return -E2BIG; + + pl = find_attach_entry(progs, prog, link, replace_prog, +@@ -698,6 +714,7 @@ static int __cgroup_bpf_attach(struct cgroup *cgrp, + + pl->prog = prog; + pl->link = link; ++ pl->flags = flags; + bpf_cgroup_storages_assign(pl->storage, storage); + cgrp->bpf.flags[atype] = saved_flags; + +@@ -1073,7 +1090,7 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, + lockdep_is_held(&cgroup_mutex)); + total_cnt += bpf_prog_array_length(effective); + } else { +- total_cnt += prog_list_length(&cgrp->bpf.progs[atype]); ++ total_cnt += prog_list_length(&cgrp->bpf.progs[atype], NULL); + } + } + +@@ -1105,7 +1122,7 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, + u32 id; + + progs = &cgrp->bpf.progs[atype]; +- cnt = min_t(int, prog_list_length(progs), total_cnt); ++ cnt = min_t(int, prog_list_length(progs, NULL), total_cnt); + i = 0; + hlist_for_each_entry(pl, progs, node) { + prog = prog_list_prog(pl); +diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c +index fc048d3c0e69f..ab74a226e3d6d 100644 +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -4042,7 +4042,8 @@ static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog, + #define BPF_F_ATTACH_MASK_BASE \ + (BPF_F_ALLOW_OVERRIDE | \ + BPF_F_ALLOW_MULTI | \ +- BPF_F_REPLACE) ++ BPF_F_REPLACE | \ ++ BPF_F_PREORDER) + + #define BPF_F_ATTACH_MASK_MPROG \ + (BPF_F_REPLACE | \ +diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h +index 4a939c90dc2e4..552fd633f8200 100644 +--- a/tools/include/uapi/linux/bpf.h ++++ b/tools/include/uapi/linux/bpf.h +@@ -1206,6 +1206,7 @@ enum bpf_perf_event_type { + #define BPF_F_BEFORE (1U << 3) + #define BPF_F_AFTER (1U << 4) + #define BPF_F_ID (1U << 5) ++#define BPF_F_PREORDER (1U << 6) + #define BPF_F_LINK BPF_F_LINK /* 1 << 13 */ + + /* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the +-- +2.39.5 + diff --git a/queue-6.12/bpf-copy_verifier_state-should-copy-loop_entry-field.patch b/queue-6.12/bpf-copy_verifier_state-should-copy-loop_entry-field.patch new file mode 100644 index 0000000000..d4aa45aaff --- /dev/null +++ b/queue-6.12/bpf-copy_verifier_state-should-copy-loop_entry-field.patch @@ -0,0 +1,89 @@ +From 29fae98d26e9221a3b8ae8fa40dc70157e945c60 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Feb 2025 03:03:52 -0800 +Subject: bpf: copy_verifier_state() should copy 'loop_entry' field + +From: Eduard Zingerman + +[ Upstream commit bbbc02b7445ebfda13e4847f4f1413c6480a85a9 ] + +The bpf_verifier_state.loop_entry state should be copied by +copy_verifier_state(). Otherwise, .loop_entry values from unrelated +states would poison env->cur_state. + +Additionally, env->stack should not contain any states with +.loop_entry != NULL. The states in env->stack are yet to be verified, +while .loop_entry is set for states that reached an equivalent state. +This means that env->cur_state->loop_entry should always be NULL after +pop_stack(). + +See the selftest in the next commit for an example of the program that +is not safe yet is accepted by verifier w/o this fix. + +This change has some verification performance impact for selftests: + +File Program Insns (A) Insns (B) Insns (DIFF) States (A) States (B) States (DIFF) +---------------------------------- ---------------------------- --------- --------- -------------- ---------- ---------- ------------- +arena_htab.bpf.o arena_htab_llvm 717 426 -291 (-40.59%) 57 37 -20 (-35.09%) +arena_htab_asm.bpf.o arena_htab_asm 597 445 -152 (-25.46%) 47 37 -10 (-21.28%) +arena_list.bpf.o arena_list_del 309 279 -30 (-9.71%) 23 14 -9 (-39.13%) +iters.bpf.o iter_subprog_check_stacksafe 155 141 -14 (-9.03%) 15 14 -1 (-6.67%) +iters.bpf.o iter_subprog_iters 1094 1003 -91 (-8.32%) 88 83 -5 (-5.68%) +iters.bpf.o loop_state_deps2 479 725 +246 (+51.36%) 46 63 +17 (+36.96%) +kmem_cache_iter.bpf.o open_coded_iter 63 59 -4 (-6.35%) 7 6 -1 (-14.29%) +verifier_bits_iter.bpf.o max_words 92 84 -8 (-8.70%) 8 7 -1 (-12.50%) +verifier_iterating_callbacks.bpf.o cond_break2 113 107 -6 (-5.31%) 12 12 +0 (+0.00%) + +And significant negative impact for sched_ext: + +File Program Insns (A) Insns (B) Insns (DIFF) States (A) States (B) States (DIFF) +----------------- ---------------------- --------- --------- -------------------- ---------- ---------- ------------------ +bpf.bpf.o lavd_init 7039 14723 +7684 (+109.16%) 490 1139 +649 (+132.45%) +bpf.bpf.o layered_dispatch 11485 10548 -937 (-8.16%) 848 762 -86 (-10.14%) +bpf.bpf.o layered_dump 7422 1000001 +992579 (+13373.47%) 681 31178 +30497 (+4478.27%) +bpf.bpf.o layered_enqueue 16854 71127 +54273 (+322.02%) 1611 6450 +4839 (+300.37%) +bpf.bpf.o p2dq_dispatch 665 791 +126 (+18.95%) 68 78 +10 (+14.71%) +bpf.bpf.o p2dq_init 2343 2980 +637 (+27.19%) 201 237 +36 (+17.91%) +bpf.bpf.o refresh_layer_cpumasks 16487 674760 +658273 (+3992.68%) 1770 65370 +63600 (+3593.22%) +bpf.bpf.o rusty_select_cpu 1937 40872 +38935 (+2010.07%) 177 3210 +3033 (+1713.56%) +scx_central.bpf.o central_dispatch 636 2687 +2051 (+322.48%) 63 227 +164 (+260.32%) +scx_nest.bpf.o nest_init 636 815 +179 (+28.14%) 60 73 +13 (+21.67%) +scx_qmap.bpf.o qmap_dispatch 2393 3580 +1187 (+49.60%) 196 253 +57 (+29.08%) +scx_qmap.bpf.o qmap_dump 233 318 +85 (+36.48%) 22 30 +8 (+36.36%) +scx_qmap.bpf.o qmap_init 16367 17436 +1069 (+6.53%) 603 669 +66 (+10.95%) + +Note 'layered_dump' program, which now hits 1M instructions limit. +This impact would be mitigated in the next patch. + +Signed-off-by: Eduard Zingerman +Link: https://lore.kernel.org/r/20250215110411.3236773-2-eddyz87@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/verifier.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 592ee3b47635b..1437108f9d7af 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -1447,6 +1447,7 @@ static int copy_verifier_state(struct bpf_verifier_state *dst_state, + dst_state->callback_unroll_depth = src->callback_unroll_depth; + dst_state->used_as_loop_entry = src->used_as_loop_entry; + dst_state->may_goto_depth = src->may_goto_depth; ++ dst_state->loop_entry = src->loop_entry; + for (i = 0; i <= src->curframe; i++) { + dst = dst_state->frame[i]; + if (!dst) { +@@ -18720,6 +18721,8 @@ static int do_check(struct bpf_verifier_env *env) + return err; + break; + } else { ++ if (WARN_ON_ONCE(env->cur_state->loop_entry)) ++ env->cur_state->loop_entry = NULL; + do_print_state = true; + continue; + } +-- +2.39.5 + diff --git a/queue-6.12/bpf-don-t-do-clean_live_states-when-state-loop_entry.patch b/queue-6.12/bpf-don-t-do-clean_live_states-when-state-loop_entry.patch new file mode 100644 index 0000000000..6f76a08210 --- /dev/null +++ b/queue-6.12/bpf-don-t-do-clean_live_states-when-state-loop_entry.patch @@ -0,0 +1,104 @@ +From f6cee4edac9e2662c79efcdca2f38890bf20bedd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Feb 2025 03:03:54 -0800 +Subject: bpf: don't do clean_live_states when state->loop_entry->branches > 0 + +From: Eduard Zingerman + +[ Upstream commit 9e63fdb0cbdf3268c86638a8274f4d5549a82820 ] + +verifier.c:is_state_visited() uses RANGE_WITHIN states comparison rules +for cached states that have loop_entry with non-zero branches count +(meaning that loop_entry's verification is not yet done). + +The RANGE_WITHIN rules in regsafe()/stacksafe() require register and +stack objects types to be identical in current and old states. + +verifier.c:clean_live_states() replaces registers and stack spills +with NOT_INIT/STACK_INVALID marks, if these registers/stack spills are +not read in any child state. This means that clean_live_states() works +against loop convergence logic under some conditions. See selftest in +the next patch for a specific example. + +Mitigate this by prohibiting clean_verifier_state() when +state->loop_entry->branches > 0. + +This undoes negative verification performance impact of the +copy_verifier_state() fix from the previous patch. +Below is comparison between master and current patch. + +selftests: + +File Program Insns (A) Insns (B) Insns (DIFF) States (A) States (B) States (DIFF) +---------------------------------- ---------------------------- --------- --------- --------------- ---------- ---------- -------------- +arena_htab.bpf.o arena_htab_llvm 717 423 -294 (-41.00%) 57 37 -20 (-35.09%) +arena_htab_asm.bpf.o arena_htab_asm 597 445 -152 (-25.46%) 47 37 -10 (-21.28%) +arena_list.bpf.o arena_list_add 1493 1822 +329 (+22.04%) 30 37 +7 (+23.33%) +arena_list.bpf.o arena_list_del 309 261 -48 (-15.53%) 23 15 -8 (-34.78%) +iters.bpf.o checkpoint_states_deletion 18125 22154 +4029 (+22.23%) 818 918 +100 (+12.22%) +iters.bpf.o iter_nested_deeply_iters 593 367 -226 (-38.11%) 67 43 -24 (-35.82%) +iters.bpf.o iter_nested_iters 813 772 -41 (-5.04%) 79 72 -7 (-8.86%) +iters.bpf.o iter_subprog_check_stacksafe 155 135 -20 (-12.90%) 15 14 -1 (-6.67%) +iters.bpf.o iter_subprog_iters 1094 808 -286 (-26.14%) 88 68 -20 (-22.73%) +iters.bpf.o loop_state_deps2 479 356 -123 (-25.68%) 46 35 -11 (-23.91%) +iters.bpf.o triple_continue 35 31 -4 (-11.43%) 3 3 +0 (+0.00%) +kmem_cache_iter.bpf.o open_coded_iter 63 59 -4 (-6.35%) 7 6 -1 (-14.29%) +mptcp_subflow.bpf.o _getsockopt_subflow 501 446 -55 (-10.98%) 25 23 -2 (-8.00%) +pyperf600_iter.bpf.o on_event 12339 6379 -5960 (-48.30%) 441 286 -155 (-35.15%) +verifier_bits_iter.bpf.o max_words 92 84 -8 (-8.70%) 8 7 -1 (-12.50%) +verifier_iterating_callbacks.bpf.o cond_break2 113 192 +79 (+69.91%) 12 21 +9 (+75.00%) + +sched_ext: + +File Program Insns (A) Insns (B) Insns (DIFF) States (A) States (B) States (DIFF) +----------------- ---------------------- --------- --------- ----------------- ---------- ---------- ---------------- +bpf.bpf.o layered_dispatch 11485 9039 -2446 (-21.30%) 848 662 -186 (-21.93%) +bpf.bpf.o layered_dump 7422 5022 -2400 (-32.34%) 681 298 -383 (-56.24%) +bpf.bpf.o layered_enqueue 16854 13753 -3101 (-18.40%) 1611 1308 -303 (-18.81%) +bpf.bpf.o layered_init 1000001 5549 -994452 (-99.45%) 84672 523 -84149 (-99.38%) +bpf.bpf.o layered_runnable 3149 1899 -1250 (-39.70%) 288 151 -137 (-47.57%) +bpf.bpf.o p2dq_init 2343 1936 -407 (-17.37%) 201 170 -31 (-15.42%) +bpf.bpf.o refresh_layer_cpumasks 16487 1285 -15202 (-92.21%) 1770 120 -1650 (-93.22%) +bpf.bpf.o rusty_select_cpu 1937 1386 -551 (-28.45%) 177 125 -52 (-29.38%) +scx_central.bpf.o central_dispatch 636 600 -36 (-5.66%) 63 59 -4 (-6.35%) +scx_central.bpf.o central_init 913 632 -281 (-30.78%) 48 39 -9 (-18.75%) +scx_nest.bpf.o nest_init 636 601 -35 (-5.50%) 60 58 -2 (-3.33%) +scx_pair.bpf.o pair_dispatch 1000001 1914 -998087 (-99.81%) 58169 142 -58027 (-99.76%) +scx_qmap.bpf.o qmap_dispatch 2393 2187 -206 (-8.61%) 196 174 -22 (-11.22%) +scx_qmap.bpf.o qmap_init 16367 22777 +6410 (+39.16%) 603 768 +165 (+27.36%) + +'layered_init' and 'pair_dispatch' hit 1M on master, but are verified +ok with this patch. + +Signed-off-by: Eduard Zingerman +Link: https://lore.kernel.org/r/20250215110411.3236773-4-eddyz87@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/verifier.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 294fbafbeba75..592ee3b47635b 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -17282,12 +17282,16 @@ static void clean_verifier_state(struct bpf_verifier_env *env, + static void clean_live_states(struct bpf_verifier_env *env, int insn, + struct bpf_verifier_state *cur) + { ++ struct bpf_verifier_state *loop_entry; + struct bpf_verifier_state_list *sl; + + sl = *explored_state(env, insn); + while (sl) { + if (sl->state.branches) + goto next; ++ loop_entry = get_loop_entry(&sl->state); ++ if (loop_entry && loop_entry->branches) ++ goto next; + if (sl->state.insn_idx != insn || + !same_callsites(&sl->state, cur)) + goto next; +-- +2.39.5 + diff --git a/queue-6.12/bpf-fix-possible-endless-loop-in-bpf-map-iteration.patch b/queue-6.12/bpf-fix-possible-endless-loop-in-bpf-map-iteration.patch new file mode 100644 index 0000000000..92453dc7f4 --- /dev/null +++ b/queue-6.12/bpf-fix-possible-endless-loop-in-bpf-map-iteration.patch @@ -0,0 +1,37 @@ +From 40448c81395b1cf6bbeae0638d9ea3882c6a4889 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Apr 2025 11:32:51 -0400 +Subject: bpf: fix possible endless loop in BPF map iteration + +From: Brandon Kammerdiener + +[ Upstream commit 75673fda0c557ae26078177dd14d4857afbf128d ] + +The _safe variant used here gets the next element before running the callback, +avoiding the endless loop condition. + +Signed-off-by: Brandon Kammerdiener +Link: https://lore.kernel.org/r/20250424153246.141677-2-brandon.kammerdiener@intel.com +Signed-off-by: Alexei Starovoitov +Acked-by: Hou Tao +Signed-off-by: Sasha Levin +--- + kernel/bpf/hashtab.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c +index bb3ba8ebaf3d2..570e2f7231443 100644 +--- a/kernel/bpf/hashtab.c ++++ b/kernel/bpf/hashtab.c +@@ -2223,7 +2223,7 @@ static long bpf_for_each_hash_elem(struct bpf_map *map, bpf_callback_t callback_ + b = &htab->buckets[i]; + rcu_read_lock(); + head = &b->head; +- hlist_nulls_for_each_entry_rcu(elem, n, head, hash_node) { ++ hlist_nulls_for_each_entry_safe(elem, n, head, hash_node) { + key = elem->key; + if (is_percpu) { + /* current cpu value for percpu map */ +-- +2.39.5 + diff --git a/queue-6.12/bpf-prevent-unsafe-access-to-the-sock-fields-in-the-.patch b/queue-6.12/bpf-prevent-unsafe-access-to-the-sock-fields-in-the-.patch new file mode 100644 index 0000000000..808743bb2e --- /dev/null +++ b/queue-6.12/bpf-prevent-unsafe-access-to-the-sock-fields-in-the-.patch @@ -0,0 +1,150 @@ +From 27d32b043247672b9ee03864ffd7cdc7ef959691 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 15:29:31 +0800 +Subject: bpf: Prevent unsafe access to the sock fields in the BPF timestamping + callback + +From: Jason Xing + +[ Upstream commit fd93eaffb3f977b23bc0a48d4c8616e654fcf133 ] + +The subsequent patch will implement BPF TX timestamping. It will +call the sockops BPF program without holding the sock lock. + +This breaks the current assumption that all sock ops programs will +hold the sock lock. The sock's fields of the uapi's bpf_sock_ops +requires this assumption. + +To address this, a new "u8 is_locked_tcp_sock;" field is added. This +patch sets it in the current sock_ops callbacks. The "is_fullsock" +test is then replaced by the "is_locked_tcp_sock" test during +sock_ops_convert_ctx_access(). + +The new TX timestamping callbacks added in the subsequent patch will +not have this set. This will prevent unsafe access from the new +timestamping callbacks. + +Potentially, we could allow read-only access. However, this would +require identifying which callback is read-safe-only and also requires +additional BPF instruction rewrites in the covert_ctx. Since the BPF +program can always read everything from a socket (e.g., by using +bpf_core_cast), this patch keeps it simple and disables all read +and write access to any socket fields through the bpf_sock_ops +UAPI from the new TX timestamping callback. + +Moreover, note that some of the fields in bpf_sock_ops are specific +to tcp_sock, and sock_ops currently only supports tcp_sock. In +the future, UDP timestamping will be added, which will also break +this assumption. The same idea used in this patch will be reused. +Considering that the current sock_ops only supports tcp_sock, the +variable is named is_locked_"tcp"_sock. + +Signed-off-by: Jason Xing +Signed-off-by: Martin KaFai Lau +Link: https://patch.msgid.link/20250220072940.99994-4-kerneljasonxing@gmail.com +Signed-off-by: Sasha Levin +--- + include/linux/filter.h | 1 + + include/net/tcp.h | 1 + + net/core/filter.c | 8 ++++---- + net/ipv4/tcp_input.c | 2 ++ + net/ipv4/tcp_output.c | 2 ++ + 5 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/include/linux/filter.h b/include/linux/filter.h +index 5118caf8aa1c7..2b1029aeb36ae 100644 +--- a/include/linux/filter.h ++++ b/include/linux/filter.h +@@ -1506,6 +1506,7 @@ struct bpf_sock_ops_kern { + void *skb_data_end; + u8 op; + u8 is_fullsock; ++ u8 is_locked_tcp_sock; + u8 remaining_opt_len; + u64 temp; /* temp and everything after is not + * initialized to 0 before calling +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 3255a199ef60d..c4820759ee0c3 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -2667,6 +2667,7 @@ static inline int tcp_call_bpf(struct sock *sk, int op, u32 nargs, u32 *args) + memset(&sock_ops, 0, offsetof(struct bpf_sock_ops_kern, temp)); + if (sk_fullsock(sk)) { + sock_ops.is_fullsock = 1; ++ sock_ops.is_locked_tcp_sock = 1; + sock_owned_by_me(sk); + } + +diff --git a/net/core/filter.c b/net/core/filter.c +index 99b23fd2f509c..b5de0a192258c 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -10379,10 +10379,10 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type, + } \ + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \ + struct bpf_sock_ops_kern, \ +- is_fullsock), \ ++ is_locked_tcp_sock), \ + fullsock_reg, si->src_reg, \ + offsetof(struct bpf_sock_ops_kern, \ +- is_fullsock)); \ ++ is_locked_tcp_sock)); \ + *insn++ = BPF_JMP_IMM(BPF_JEQ, fullsock_reg, 0, jmp); \ + if (si->dst_reg == si->src_reg) \ + *insn++ = BPF_LDX_MEM(BPF_DW, reg, si->src_reg, \ +@@ -10467,10 +10467,10 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type, + temp)); \ + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \ + struct bpf_sock_ops_kern, \ +- is_fullsock), \ ++ is_locked_tcp_sock), \ + reg, si->dst_reg, \ + offsetof(struct bpf_sock_ops_kern, \ +- is_fullsock)); \ ++ is_locked_tcp_sock)); \ + *insn++ = BPF_JMP_IMM(BPF_JEQ, reg, 0, 2); \ + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \ + struct bpf_sock_ops_kern, sk),\ +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index d29219e067b7f..f5690085a2ac5 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -169,6 +169,7 @@ static void bpf_skops_parse_hdr(struct sock *sk, struct sk_buff *skb) + memset(&sock_ops, 0, offsetof(struct bpf_sock_ops_kern, temp)); + sock_ops.op = BPF_SOCK_OPS_PARSE_HDR_OPT_CB; + sock_ops.is_fullsock = 1; ++ sock_ops.is_locked_tcp_sock = 1; + sock_ops.sk = sk; + bpf_skops_init_skb(&sock_ops, skb, tcp_hdrlen(skb)); + +@@ -185,6 +186,7 @@ static void bpf_skops_established(struct sock *sk, int bpf_op, + memset(&sock_ops, 0, offsetof(struct bpf_sock_ops_kern, temp)); + sock_ops.op = bpf_op; + sock_ops.is_fullsock = 1; ++ sock_ops.is_locked_tcp_sock = 1; + sock_ops.sk = sk; + /* sk with TCP_REPAIR_ON does not have skb in tcp_finish_connect */ + if (skb) +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 6d5387811c32a..ca1e52036d4d2 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -525,6 +525,7 @@ static void bpf_skops_hdr_opt_len(struct sock *sk, struct sk_buff *skb, + sock_owned_by_me(sk); + + sock_ops.is_fullsock = 1; ++ sock_ops.is_locked_tcp_sock = 1; + sock_ops.sk = sk; + } + +@@ -570,6 +571,7 @@ static void bpf_skops_write_hdr_opt(struct sock *sk, struct sk_buff *skb, + sock_owned_by_me(sk); + + sock_ops.is_fullsock = 1; ++ sock_ops.is_locked_tcp_sock = 1; + sock_ops.sk = sk; + } + +-- +2.39.5 + diff --git a/queue-6.12/bpf-return-prog-btf_id-without-capable-check.patch b/queue-6.12/bpf-return-prog-btf_id-without-capable-check.patch new file mode 100644 index 0000000000..de31cfa8fb --- /dev/null +++ b/queue-6.12/bpf-return-prog-btf_id-without-capable-check.patch @@ -0,0 +1,47 @@ +From e31c9a8c1df23609a36d4a45fb2a02ebc4887c0a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 17:40:37 +0000 +Subject: bpf: Return prog btf_id without capable check + +From: Mykyta Yatsenko + +[ Upstream commit 07651ccda9ff10a8ca427670cdd06ce2c8e4269c ] + +Return prog's btf_id from bpf_prog_get_info_by_fd regardless of capable +check. This patch enables scenario, when freplace program, running +from user namespace, requires to query target prog's btf. + +Signed-off-by: Mykyta Yatsenko +Signed-off-by: Andrii Nakryiko +Acked-by: Yonghong Song +Link: https://lore.kernel.org/bpf/20250317174039.161275-3-mykyta.yatsenko5@gmail.com +Signed-off-by: Sasha Levin +--- + kernel/bpf/syscall.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c +index 977c084577565..fc048d3c0e69f 100644 +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -4606,6 +4606,8 @@ static int bpf_prog_get_info_by_fd(struct file *file, + info.recursion_misses = stats.misses; + + info.verified_insns = prog->aux->verified_insns; ++ if (prog->aux->btf) ++ info.btf_id = btf_obj_id(prog->aux->btf); + + if (!bpf_capable()) { + info.jited_prog_len = 0; +@@ -4752,8 +4754,6 @@ static int bpf_prog_get_info_by_fd(struct file *file, + } + } + +- if (prog->aux->btf) +- info.btf_id = btf_obj_id(prog->aux->btf); + info.attach_btf_id = prog->aux->attach_btf_id; + if (attach_btf) + info.attach_btf_obj_id = btf_obj_id(attach_btf); +-- +2.39.5 + diff --git a/queue-6.12/bpf-search-and-add-kfuncs-in-struct_ops-prologue-and.patch b/queue-6.12/bpf-search-and-add-kfuncs-in-struct_ops-prologue-and.patch new file mode 100644 index 0000000000..7fa050b6f3 --- /dev/null +++ b/queue-6.12/bpf-search-and-add-kfuncs-in-struct_ops-prologue-and.patch @@ -0,0 +1,86 @@ +From 6465a7ba98f98917e1ccb49e17de662ee9faf316 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 15:35:44 -0800 +Subject: bpf: Search and add kfuncs in struct_ops prologue and epilogue + +From: Amery Hung + +[ Upstream commit d519594ee2445d7cd1ad51f4db4cee58f8213400 ] + +Currently, add_kfunc_call() is only invoked once before the main +verification loop. Therefore, the verifier could not find the +bpf_kfunc_btf_tab of a new kfunc call which is not seen in user defined +struct_ops operators but introduced in gen_prologue or gen_epilogue +during do_misc_fixup(). Fix this by searching kfuncs in the patching +instruction buffer and add them to prog->aux->kfunc_tab. + +Signed-off-by: Amery Hung +Acked-by: Eduard Zingerman +Acked-by: Martin KaFai Lau +Link: https://lore.kernel.org/r/20250225233545.285481-1-ameryhung@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/verifier.c | 25 ++++++++++++++++++++++++- + 1 file changed, 24 insertions(+), 1 deletion(-) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 8656208aa4bbb..294fbafbeba75 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -2987,6 +2987,21 @@ bpf_jit_find_kfunc_model(const struct bpf_prog *prog, + return res ? &res->func_model : NULL; + } + ++static int add_kfunc_in_insns(struct bpf_verifier_env *env, ++ struct bpf_insn *insn, int cnt) ++{ ++ int i, ret; ++ ++ for (i = 0; i < cnt; i++, insn++) { ++ if (bpf_pseudo_kfunc_call(insn)) { ++ ret = add_kfunc_call(env, insn->imm, insn->off); ++ if (ret < 0) ++ return ret; ++ } ++ } ++ return 0; ++} ++ + static int add_subprog_and_kfunc(struct bpf_verifier_env *env) + { + struct bpf_subprog_info *subprog = env->subprog_info; +@@ -19768,7 +19783,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) + { + struct bpf_subprog_info *subprogs = env->subprog_info; + const struct bpf_verifier_ops *ops = env->ops; +- int i, cnt, size, ctx_field_size, delta = 0, epilogue_cnt = 0; ++ int i, cnt, size, ctx_field_size, ret, delta = 0, epilogue_cnt = 0; + const int insn_cnt = env->prog->len; + struct bpf_insn *epilogue_buf = env->epilogue_buf; + struct bpf_insn *insn_buf = env->insn_buf; +@@ -19797,6 +19812,10 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) + return -ENOMEM; + env->prog = new_prog; + delta += cnt - 1; ++ ++ ret = add_kfunc_in_insns(env, epilogue_buf, epilogue_cnt - 1); ++ if (ret < 0) ++ return ret; + } + } + +@@ -19817,6 +19836,10 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) + + env->prog = new_prog; + delta += cnt - 1; ++ ++ ret = add_kfunc_in_insns(env, insn_buf, cnt - 1); ++ if (ret < 0) ++ return ret; + } + } + +-- +2.39.5 + diff --git a/queue-6.12/bpf-use-kallsyms-to-find-the-function-name-of-a-stru.patch b/queue-6.12/bpf-use-kallsyms-to-find-the-function-name-of-a-stru.patch new file mode 100644 index 0000000000..289cc0b1da --- /dev/null +++ b/queue-6.12/bpf-use-kallsyms-to-find-the-function-name-of-a-stru.patch @@ -0,0 +1,253 @@ +From 463b4752c68492c1fe4fa43590caa5c70157801e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Jan 2025 14:27:19 -0800 +Subject: bpf: Use kallsyms to find the function name of a struct_ops's stub + function + +From: Martin KaFai Lau + +[ Upstream commit 12fdd29d5d71d2987a1aec434b704d850a4d7fcb ] + +In commit 1611603537a4 ("bpf: Create argument information for nullable arguments."), +it introduced a "__nullable" tagging at the argument name of a +stub function. Some background on the commit: +it requires to tag the stub function instead of directly tagging +the "ops" of a struct. This is because the btf func_proto of the "ops" +does not have the argument name and the "__nullable" is tagged at +the argument name. + +To find the stub function of a "ops", it currently relies on a naming +convention on the stub function "st_ops__ops_name". +e.g. tcp_congestion_ops__ssthresh. However, the new kernel +sub system implementing bpf_struct_ops have missed this and +have been surprised that the "__nullable" and the to-be-landed +"__ref" tagging was not effective. + +One option would be to give a warning whenever the stub function does +not follow the naming convention, regardless if it requires arg tagging +or not. + +Instead, this patch uses the kallsyms_lookup approach and removes +the requirement on the naming convention. The st_ops->cfi_stubs has +all the stub function kernel addresses. kallsyms_lookup() is used to +lookup the function name. With the function name, BTF can be used to +find the BTF func_proto. The existing "__nullable" arg name searching +logic will then fall through. + +One notable change is, +if it failed in kallsyms_lookup or it failed in looking up the stub +function name from the BTF, the bpf_struct_ops registration will fail. +This is different from the previous behavior that it silently ignored +the "st_ops__ops_name" function not found error. + +The "tcp_congestion_ops", "sched_ext_ops", and "hid_bpf_ops" can still be +registered successfully after this patch. There is struct_ops_maybe_null +selftest to cover the "__nullable" tagging. + +Other minor changes: +1. Removed the "%s__%s" format from the pr_warn because the naming + convention is removed. +2. The existing bpf_struct_ops_supported() is also moved earlier + because prepare_arg_info needs to use it to decide if the + stub function is NULL before calling the prepare_arg_info. + +Cc: Tejun Heo +Cc: Benjamin Tissoires +Cc: Yonghong Song +Cc: Amery Hung +Signed-off-by: Martin KaFai Lau +Reviewed-by: Amery Hung +Link: https://lore.kernel.org/r/20250127222719.2544255-1-martin.lau@linux.dev +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/bpf_struct_ops.c | 98 +++++++++++++++++-------------------- + 1 file changed, 44 insertions(+), 54 deletions(-) + +diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c +index b70d0eef8a284..477947456371a 100644 +--- a/kernel/bpf/bpf_struct_ops.c ++++ b/kernel/bpf/bpf_struct_ops.c +@@ -147,39 +147,6 @@ void bpf_struct_ops_image_free(void *image) + } + + #define MAYBE_NULL_SUFFIX "__nullable" +-#define MAX_STUB_NAME 128 +- +-/* Return the type info of a stub function, if it exists. +- * +- * The name of a stub function is made up of the name of the struct_ops and +- * the name of the function pointer member, separated by "__". For example, +- * if the struct_ops type is named "foo_ops" and the function pointer +- * member is named "bar", the stub function name would be "foo_ops__bar". +- */ +-static const struct btf_type * +-find_stub_func_proto(const struct btf *btf, const char *st_op_name, +- const char *member_name) +-{ +- char stub_func_name[MAX_STUB_NAME]; +- const struct btf_type *func_type; +- s32 btf_id; +- int cp; +- +- cp = snprintf(stub_func_name, MAX_STUB_NAME, "%s__%s", +- st_op_name, member_name); +- if (cp >= MAX_STUB_NAME) { +- pr_warn("Stub function name too long\n"); +- return NULL; +- } +- btf_id = btf_find_by_name_kind(btf, stub_func_name, BTF_KIND_FUNC); +- if (btf_id < 0) +- return NULL; +- func_type = btf_type_by_id(btf, btf_id); +- if (!func_type) +- return NULL; +- +- return btf_type_by_id(btf, func_type->type); /* FUNC_PROTO */ +-} + + /* Prepare argument info for every nullable argument of a member of a + * struct_ops type. +@@ -204,27 +171,42 @@ find_stub_func_proto(const struct btf *btf, const char *st_op_name, + static int prepare_arg_info(struct btf *btf, + const char *st_ops_name, + const char *member_name, +- const struct btf_type *func_proto, ++ const struct btf_type *func_proto, void *stub_func_addr, + struct bpf_struct_ops_arg_info *arg_info) + { + const struct btf_type *stub_func_proto, *pointed_type; + const struct btf_param *stub_args, *args; + struct bpf_ctx_arg_aux *info, *info_buf; + u32 nargs, arg_no, info_cnt = 0; ++ char ksym[KSYM_SYMBOL_LEN]; ++ const char *stub_fname; ++ s32 stub_func_id; + u32 arg_btf_id; + int offset; + +- stub_func_proto = find_stub_func_proto(btf, st_ops_name, member_name); +- if (!stub_func_proto) +- return 0; ++ stub_fname = kallsyms_lookup((unsigned long)stub_func_addr, NULL, NULL, NULL, ksym); ++ if (!stub_fname) { ++ pr_warn("Cannot find the stub function name for the %s in struct %s\n", ++ member_name, st_ops_name); ++ return -ENOENT; ++ } ++ ++ stub_func_id = btf_find_by_name_kind(btf, stub_fname, BTF_KIND_FUNC); ++ if (stub_func_id < 0) { ++ pr_warn("Cannot find the stub function %s in btf\n", stub_fname); ++ return -ENOENT; ++ } ++ ++ stub_func_proto = btf_type_by_id(btf, stub_func_id); ++ stub_func_proto = btf_type_by_id(btf, stub_func_proto->type); + + /* Check if the number of arguments of the stub function is the same + * as the number of arguments of the function pointer. + */ + nargs = btf_type_vlen(func_proto); + if (nargs != btf_type_vlen(stub_func_proto)) { +- pr_warn("the number of arguments of the stub function %s__%s does not match the number of arguments of the member %s of struct %s\n", +- st_ops_name, member_name, member_name, st_ops_name); ++ pr_warn("the number of arguments of the stub function %s does not match the number of arguments of the member %s of struct %s\n", ++ stub_fname, member_name, st_ops_name); + return -EINVAL; + } + +@@ -254,21 +236,21 @@ static int prepare_arg_info(struct btf *btf, + &arg_btf_id); + if (!pointed_type || + !btf_type_is_struct(pointed_type)) { +- pr_warn("stub function %s__%s has %s tagging to an unsupported type\n", +- st_ops_name, member_name, MAYBE_NULL_SUFFIX); ++ pr_warn("stub function %s has %s tagging to an unsupported type\n", ++ stub_fname, MAYBE_NULL_SUFFIX); + goto err_out; + } + + offset = btf_ctx_arg_offset(btf, func_proto, arg_no); + if (offset < 0) { +- pr_warn("stub function %s__%s has an invalid trampoline ctx offset for arg#%u\n", +- st_ops_name, member_name, arg_no); ++ pr_warn("stub function %s has an invalid trampoline ctx offset for arg#%u\n", ++ stub_fname, arg_no); + goto err_out; + } + + if (args[arg_no].type != stub_args[arg_no].type) { +- pr_warn("arg#%u type in stub function %s__%s does not match with its original func_proto\n", +- arg_no, st_ops_name, member_name); ++ pr_warn("arg#%u type in stub function %s does not match with its original func_proto\n", ++ arg_no, stub_fname); + goto err_out; + } + +@@ -325,6 +307,13 @@ static bool is_module_member(const struct btf *btf, u32 id) + return !strcmp(btf_name_by_offset(btf, t->name_off), "module"); + } + ++int bpf_struct_ops_supported(const struct bpf_struct_ops *st_ops, u32 moff) ++{ ++ void *func_ptr = *(void **)(st_ops->cfi_stubs + moff); ++ ++ return func_ptr ? 0 : -ENOTSUPP; ++} ++ + int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, + struct btf *btf, + struct bpf_verifier_log *log) +@@ -388,7 +377,10 @@ int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, + + for_each_member(i, t, member) { + const struct btf_type *func_proto; ++ void **stub_func_addr; ++ u32 moff; + ++ moff = __btf_member_bit_offset(t, member) / 8; + mname = btf_name_by_offset(btf, member->name_off); + if (!*mname) { + pr_warn("anon member in struct %s is not supported\n", +@@ -414,7 +406,11 @@ int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, + func_proto = btf_type_resolve_func_ptr(btf, + member->type, + NULL); +- if (!func_proto) ++ ++ /* The member is not a function pointer or ++ * the function pointer is not supported. ++ */ ++ if (!func_proto || bpf_struct_ops_supported(st_ops, moff)) + continue; + + if (btf_distill_func_proto(log, btf, +@@ -426,8 +422,9 @@ int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, + goto errout; + } + ++ stub_func_addr = *(void **)(st_ops->cfi_stubs + moff); + err = prepare_arg_info(btf, st_ops->name, mname, +- func_proto, ++ func_proto, stub_func_addr, + arg_info + i); + if (err) + goto errout; +@@ -1153,13 +1150,6 @@ void bpf_struct_ops_put(const void *kdata) + bpf_map_put(&st_map->map); + } + +-int bpf_struct_ops_supported(const struct bpf_struct_ops *st_ops, u32 moff) +-{ +- void *func_ptr = *(void **)(st_ops->cfi_stubs + moff); +- +- return func_ptr ? 0 : -ENOTSUPP; +-} +- + static bool bpf_struct_ops_valid_to_reg(struct bpf_map *map) + { + struct bpf_struct_ops_map *st_map = (struct bpf_struct_ops_map *)map; +-- +2.39.5 + diff --git a/queue-6.12/bpftool-fix-readlink-usage-in-get_fd_type.patch b/queue-6.12/bpftool-fix-readlink-usage-in-get_fd_type.patch new file mode 100644 index 0000000000..99774e557b --- /dev/null +++ b/queue-6.12/bpftool-fix-readlink-usage-in-get_fd_type.patch @@ -0,0 +1,49 @@ +From bf359f58d92cde41cb5fad7b8d15deee90f7d087 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 08:18:57 +0100 +Subject: bpftool: Fix readlink usage in get_fd_type + +From: Viktor Malik + +[ Upstream commit 0053f7d39d491b6138d7c526876d13885cbb65f1 ] + +The `readlink(path, buf, sizeof(buf))` call reads at most sizeof(buf) +bytes and *does not* append null-terminator to buf. With respect to +that, fix two pieces in get_fd_type: + +1. Change the truncation check to contain sizeof(buf) rather than + sizeof(path). +2. Append null-terminator to buf. + +Reported by Coverity. + +Signed-off-by: Viktor Malik +Signed-off-by: Andrii Nakryiko +Reviewed-by: Quentin Monnet +Link: https://lore.kernel.org/bpf/20250129071857.75182-1-vmalik@redhat.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + tools/bpf/bpftool/common.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c +index 9b75639434b81..0a764426d9358 100644 +--- a/tools/bpf/bpftool/common.c ++++ b/tools/bpf/bpftool/common.c +@@ -461,10 +461,11 @@ int get_fd_type(int fd) + p_err("can't read link type: %s", strerror(errno)); + return -1; + } +- if (n == sizeof(path)) { ++ if (n == sizeof(buf)) { + p_err("can't read link type: path too long!"); + return -1; + } ++ buf[n] = '\0'; + + if (strstr(buf, "bpf-map")) + return BPF_OBJ_MAP; +-- +2.39.5 + diff --git a/queue-6.12/bridge-mdb-allow-replace-of-a-host-joined-group.patch b/queue-6.12/bridge-mdb-allow-replace-of-a-host-joined-group.patch new file mode 100644 index 0000000000..e0cf902e47 --- /dev/null +++ b/queue-6.12/bridge-mdb-allow-replace-of-a-host-joined-group.patch @@ -0,0 +1,67 @@ +From 73708fd72e7d6928deac67f6deabf69ae3cda28c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 18:37:15 +0100 +Subject: bridge: mdb: Allow replace of a host-joined group + +From: Petr Machata + +[ Upstream commit d9e9f6d7b7d0c520bb87f19d2cbc57aeeb2091d5 ] + +Attempts to replace an MDB group membership of the host itself are +currently bounced: + + # ip link add name br up type bridge vlan_filtering 1 + # bridge mdb replace dev br port br grp 239.0.0.1 vid 2 + # bridge mdb replace dev br port br grp 239.0.0.1 vid 2 + Error: bridge: Group is already joined by host. + +A similar operation done on a member port would succeed. Ignore the check +for replacement of host group memberships as well. + +The bit of code that this enables is br_multicast_host_join(), which, for +already-joined groups only refreshes the MC group expiration timer, which +is desirable; and a userspace notification, also desirable. + +Change a selftest that exercises this code path from expecting a rejection +to expecting a pass. The rest of MDB selftests pass without modification. + +Signed-off-by: Petr Machata +Reviewed-by: Ido Schimmel +Acked-by: Nikolay Aleksandrov +Link: https://patch.msgid.link/e5c5188b9787ae806609e7ca3aa2a0a501b9b5c4.1738685648.git.petrm@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/bridge/br_mdb.c | 2 +- + tools/testing/selftests/net/forwarding/bridge_mdb.sh | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c +index 1a52a0bca086d..7e1ad229e1330 100644 +--- a/net/bridge/br_mdb.c ++++ b/net/bridge/br_mdb.c +@@ -1040,7 +1040,7 @@ static int br_mdb_add_group(const struct br_mdb_config *cfg, + + /* host join */ + if (!port) { +- if (mp->host_joined) { ++ if (mp->host_joined && !(cfg->nlflags & NLM_F_REPLACE)) { + NL_SET_ERR_MSG_MOD(extack, "Group is already joined by host"); + return -EEXIST; + } +diff --git a/tools/testing/selftests/net/forwarding/bridge_mdb.sh b/tools/testing/selftests/net/forwarding/bridge_mdb.sh +index d9d587454d207..8c1597ebc2d38 100755 +--- a/tools/testing/selftests/net/forwarding/bridge_mdb.sh ++++ b/tools/testing/selftests/net/forwarding/bridge_mdb.sh +@@ -149,7 +149,7 @@ cfg_test_host_common() + check_err $? "Failed to add $name host entry" + + bridge mdb replace dev br0 port br0 grp $grp $state vid 10 &> /dev/null +- check_fail $? "Managed to replace $name host entry" ++ check_err $? "Failed to replace $name host entry" + + bridge mdb del dev br0 port br0 grp $grp $state vid 10 + bridge mdb get dev br0 grp $grp vid 10 &> /dev/null +-- +2.39.5 + diff --git a/queue-6.12/btrfs-avoid-linker-error-in-btrfs_find_create_tree_b.patch b/queue-6.12/btrfs-avoid-linker-error-in-btrfs_find_create_tree_b.patch new file mode 100644 index 0000000000..e597c1f182 --- /dev/null +++ b/queue-6.12/btrfs-avoid-linker-error-in-btrfs_find_create_tree_b.patch @@ -0,0 +1,61 @@ +From 97a62c61168c4d1674ec9acc99df3a1423e0b140 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 10:58:46 +0000 +Subject: btrfs: avoid linker error in btrfs_find_create_tree_block() + +From: Mark Harmstone + +[ Upstream commit 7ef3cbf17d2734ca66c4ed8573be45f4e461e7ee ] + +The inline function btrfs_is_testing() is hardcoded to return 0 if +CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set. Currently we're relying on +the compiler optimizing out the call to alloc_test_extent_buffer() in +btrfs_find_create_tree_block(), as it's not been defined (it's behind an + #ifdef). + +Add a stub version of alloc_test_extent_buffer() to avoid linker errors +on non-standard optimization levels. This problem was seen on GCC 14 +with -O0 and is helps to see symbols that would be otherwise optimized +out. + +Reviewed-by: Qu Wenruo +Signed-off-by: Mark Harmstone +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/extent_io.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index e263d4b0546fa..d322cf82783f9 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -2826,10 +2826,10 @@ struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info, + return eb; + } + +-#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS + struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info, + u64 start) + { ++#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS + struct extent_buffer *eb, *exists = NULL; + int ret; + +@@ -2865,8 +2865,11 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info, + free_eb: + btrfs_release_extent_buffer(eb); + return exists; +-} ++#else ++ /* Stub to avoid linker error when compiled with optimizations turned off. */ ++ return NULL; + #endif ++} + + static struct extent_buffer *grab_extent_buffer( + struct btrfs_fs_info *fs_info, struct page *page) +-- +2.39.5 + diff --git a/queue-6.12/btrfs-avoid-null-pointer-dereference-if-no-valid-csu.patch b/queue-6.12/btrfs-avoid-null-pointer-dereference-if-no-valid-csu.patch new file mode 100644 index 0000000000..d8159906b0 --- /dev/null +++ b/queue-6.12/btrfs-avoid-null-pointer-dereference-if-no-valid-csu.patch @@ -0,0 +1,73 @@ +From 0d0ac8504404233c364e3e313dcda34faa10c3c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Apr 2025 15:17:50 +0930 +Subject: btrfs: avoid NULL pointer dereference if no valid csum tree + +From: Qu Wenruo + +[ Upstream commit f95d186255b319c48a365d47b69bd997fecb674e ] + +[BUG] +When trying read-only scrub on a btrfs with rescue=idatacsums mount +option, it will crash with the following call trace: + + BUG: kernel NULL pointer dereference, address: 0000000000000208 + #PF: supervisor read access in kernel mode + #PF: error_code(0x0000) - not-present page + CPU: 1 UID: 0 PID: 835 Comm: btrfs Tainted: G O 6.15.0-rc3-custom+ #236 PREEMPT(full) + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS unknown 02/02/2022 + RIP: 0010:btrfs_lookup_csums_bitmap+0x49/0x480 [btrfs] + Call Trace: + + scrub_find_fill_first_stripe+0x35b/0x3d0 [btrfs] + scrub_simple_mirror+0x175/0x290 [btrfs] + scrub_stripe+0x5f7/0x6f0 [btrfs] + scrub_chunk+0x9a/0x150 [btrfs] + scrub_enumerate_chunks+0x333/0x660 [btrfs] + btrfs_scrub_dev+0x23e/0x600 [btrfs] + btrfs_ioctl+0x1dcf/0x2f80 [btrfs] + __x64_sys_ioctl+0x97/0xc0 + do_syscall_64+0x4f/0x120 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +[CAUSE] +Mount option "rescue=idatacsums" will completely skip loading the csum +tree, so that any data read will not find any data csum thus we will +ignore data checksum verification. + +Normally call sites utilizing csum tree will check the fs state flag +NO_DATA_CSUMS bit, but unfortunately scrub does not check that bit at all. + +This results in scrub to call btrfs_search_slot() on a NULL pointer +and triggered above crash. + +[FIX] +Check both extent and csum tree root before doing any tree search. + +Reviewed-by: Johannes Thumshirn +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/scrub.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c +index c73a41b1ad560..d8fcc3eb85c88 100644 +--- a/fs/btrfs/scrub.c ++++ b/fs/btrfs/scrub.c +@@ -1541,8 +1541,8 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg, + u64 extent_gen; + int ret; + +- if (unlikely(!extent_root)) { +- btrfs_err(fs_info, "no valid extent root for scrub"); ++ if (unlikely(!extent_root || !csum_root)) { ++ btrfs_err(fs_info, "no valid extent or csum root for scrub"); + return -EUCLEAN; + } + memset(stripe->sectors, 0, sizeof(struct scrub_sector_verification) * +-- +2.39.5 + diff --git a/queue-6.12/btrfs-compression-adjust-cb-compressed_folios-alloca.patch b/queue-6.12/btrfs-compression-adjust-cb-compressed_folios-alloca.patch new file mode 100644 index 0000000000..363349fe27 --- /dev/null +++ b/queue-6.12/btrfs-compression-adjust-cb-compressed_folios-alloca.patch @@ -0,0 +1,43 @@ +From 7be1753bfce931f2dc1a2bd449fad094f29ba9b7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 23:23:29 -0700 +Subject: btrfs: compression: adjust cb->compressed_folios allocation type + +From: Kees Cook + +[ Upstream commit 6f9a8ab796c6528d22de3c504c81fce7dde63d8a ] + +In preparation for making the kmalloc() family of allocators type aware, +we need to make sure that the returned type from the allocation matches +the type of the variable being assigned. (Before, the allocator would +always return "void *", which can be implicitly cast to any pointer type.) + +The assigned type is "struct folio **" but the returned type will be +"struct page **". These are the same allocation size (pointer size), but +the types don't match. Adjust the allocation type to match the assignment. + +Reviewed-by: Qu Wenruo +Signed-off-by: Kees Cook +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/compression.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c +index 40332ab62f101..65d883da86c60 100644 +--- a/fs/btrfs/compression.c ++++ b/fs/btrfs/compression.c +@@ -606,7 +606,7 @@ void btrfs_submit_compressed_read(struct btrfs_bio *bbio) + free_extent_map(em); + + cb->nr_folios = DIV_ROUND_UP(compressed_len, PAGE_SIZE); +- cb->compressed_folios = kcalloc(cb->nr_folios, sizeof(struct page *), GFP_NOFS); ++ cb->compressed_folios = kcalloc(cb->nr_folios, sizeof(struct folio *), GFP_NOFS); + if (!cb->compressed_folios) { + ret = BLK_STS_RESOURCE; + goto out_free_bio; +-- +2.39.5 + diff --git a/queue-6.12/btrfs-correct-the-order-of-prelim_ref-arguments-in-b.patch b/queue-6.12/btrfs-correct-the-order-of-prelim_ref-arguments-in-b.patch new file mode 100644 index 0000000000..3a2db7010b --- /dev/null +++ b/queue-6.12/btrfs-correct-the-order-of-prelim_ref-arguments-in-b.patch @@ -0,0 +1,82 @@ +From a6767dfe1e61038111aa5ec4f3b85e00f91afd79 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 09:25:06 -0400 +Subject: btrfs: correct the order of prelim_ref arguments in btrfs__prelim_ref + +From: Goldwyn Rodrigues + +[ Upstream commit bc7e0975093567f51be8e1bdf4aa5900a3cf0b1e ] + +btrfs_prelim_ref() calls the old and new reference variables in the +incorrect order. This causes a NULL pointer dereference because oldref +is passed as NULL to trace_btrfs_prelim_ref_insert(). + +Note, trace_btrfs_prelim_ref_insert() is being called with newref as +oldref (and oldref as NULL) on purpose in order to print out +the values of newref. + +To reproduce: +echo 1 > /sys/kernel/debug/tracing/events/btrfs/btrfs_prelim_ref_insert/enable + +Perform some writeback operations. + +Backtrace: +BUG: kernel NULL pointer dereference, address: 0000000000000018 + #PF: supervisor read access in kernel mode + #PF: error_code(0x0000) - not-present page + PGD 115949067 P4D 115949067 PUD 11594a067 PMD 0 + Oops: Oops: 0000 [#1] SMP NOPTI + CPU: 1 UID: 0 PID: 1188 Comm: fsstress Not tainted 6.15.0-rc2-tester+ #47 PREEMPT(voluntary) 7ca2cef72d5e9c600f0c7718adb6462de8149622 + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-2-gc13ff2cd-prebuilt.qemu.org 04/01/2014 + RIP: 0010:trace_event_raw_event_btrfs__prelim_ref+0x72/0x130 + Code: e8 43 81 9f ff 48 85 c0 74 78 4d 85 e4 0f 84 8f 00 00 00 49 8b 94 24 c0 06 00 00 48 8b 0a 48 89 48 08 48 8b 52 08 48 89 50 10 <49> 8b 55 18 48 89 50 18 49 8b 55 20 48 89 50 20 41 0f b6 55 28 88 + RSP: 0018:ffffce44820077a0 EFLAGS: 00010286 + RAX: ffff8c6b403f9014 RBX: ffff8c6b55825730 RCX: 304994edf9cf506b + RDX: d8b11eb7f0fdb699 RSI: ffff8c6b403f9010 RDI: ffff8c6b403f9010 + RBP: 0000000000000001 R08: 0000000000000001 R09: 0000000000000010 + R10: 00000000ffffffff R11: 0000000000000000 R12: ffff8c6b4e8fb000 + R13: 0000000000000000 R14: ffffce44820077a8 R15: ffff8c6b4abd1540 + FS: 00007f4dc6813740(0000) GS:ffff8c6c1d378000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 0000000000000018 CR3: 000000010eb42000 CR4: 0000000000750ef0 + PKRU: 55555554 + Call Trace: + + prelim_ref_insert+0x1c1/0x270 + find_parent_nodes+0x12a6/0x1ee0 + ? __entry_text_end+0x101f06/0x101f09 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? srso_alias_return_thunk+0x5/0xfbef5 + btrfs_is_data_extent_shared+0x167/0x640 + ? fiemap_process_hole+0xd0/0x2c0 + extent_fiemap+0xa5c/0xbc0 + ? __entry_text_end+0x101f05/0x101f09 + btrfs_fiemap+0x7e/0xd0 + do_vfs_ioctl+0x425/0x9d0 + __x64_sys_ioctl+0x75/0xc0 + +Signed-off-by: Goldwyn Rodrigues +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + include/trace/events/btrfs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h +index af6b3827fb1d0..3b16b0cc1b7a6 100644 +--- a/include/trace/events/btrfs.h ++++ b/include/trace/events/btrfs.h +@@ -1924,7 +1924,7 @@ DECLARE_EVENT_CLASS(btrfs__prelim_ref, + TP_PROTO(const struct btrfs_fs_info *fs_info, + const struct prelim_ref *oldref, + const struct prelim_ref *newref, u64 tree_size), +- TP_ARGS(fs_info, newref, oldref, tree_size), ++ TP_ARGS(fs_info, oldref, newref, tree_size), + + TP_STRUCT__entry_btrfs( + __field( u64, root_id ) +-- +2.39.5 + diff --git a/queue-6.12/btrfs-fix-non-empty-delayed-iputs-list-on-unmount-du.patch b/queue-6.12/btrfs-fix-non-empty-delayed-iputs-list-on-unmount-du.patch new file mode 100644 index 0000000000..162d980ede --- /dev/null +++ b/queue-6.12/btrfs-fix-non-empty-delayed-iputs-list-on-unmount-du.patch @@ -0,0 +1,85 @@ +From 499fb5133b1bfeff06af13546a29821a4696157b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 14:25:38 +0000 +Subject: btrfs: fix non-empty delayed iputs list on unmount due to async + workers + +From: Filipe Manana + +[ Upstream commit cda76788f8b0f7de3171100e3164ec1ce702292e ] + +At close_ctree() after we have ran delayed iputs either explicitly through +calling btrfs_run_delayed_iputs() or later during the call to +btrfs_commit_super() or btrfs_error_commit_super(), we assert that the +delayed iputs list is empty. + +We have (another) race where this assertion might fail because we have +queued an async write into the fs_info->workers workqueue. Here's how it +happens: + +1) We are submitting a data bio for an inode that is not the data + relocation inode, so we call btrfs_wq_submit_bio(); + +2) btrfs_wq_submit_bio() submits a work for the fs_info->workers queue + that will run run_one_async_done(); + +3) We enter close_ctree(), flush several work queues except + fs_info->workers, explicitly run delayed iputs with a call to + btrfs_run_delayed_iputs() and then again shortly after by calling + btrfs_commit_super() or btrfs_error_commit_super(), which also run + delayed iputs; + +4) run_one_async_done() is executed in the work queue, and because there + was an IO error (bio->bi_status is not 0) it calls btrfs_bio_end_io(), + which drops the final reference on the associated ordered extent by + calling btrfs_put_ordered_extent() - and that adds a delayed iput for + the inode; + +5) At close_ctree() we find that after stopping the cleaner and + transaction kthreads the delayed iputs list is not empty, failing the + following assertion: + + ASSERT(list_empty(&fs_info->delayed_iputs)); + +Fix this by flushing the fs_info->workers workqueue before running delayed +iputs at close_ctree(). + +David reported this when running generic/648, which exercises IO error +paths by using the DM error table. + +Reported-by: David Sterba +Reviewed-by: Qu Wenruo +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/disk-io.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c +index e0e740e4d7c75..147c50ef912ac 100644 +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -4282,6 +4282,19 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info) + */ + btrfs_flush_workqueue(fs_info->delalloc_workers); + ++ /* ++ * We can have ordered extents getting their last reference dropped from ++ * the fs_info->workers queue because for async writes for data bios we ++ * queue a work for that queue, at btrfs_wq_submit_bio(), that runs ++ * run_one_async_done() which calls btrfs_bio_end_io() in case the bio ++ * has an error, and that later function can do the final ++ * btrfs_put_ordered_extent() on the ordered extent attached to the bio, ++ * which adds a delayed iput for the inode. So we must flush the queue ++ * so that we don't have delayed iputs after committing the current ++ * transaction below and stopping the cleaner and transaction kthreads. ++ */ ++ btrfs_flush_workqueue(fs_info->workers); ++ + /* + * When finishing a compressed write bio we schedule a work queue item + * to finish an ordered extent - btrfs_finish_compressed_write_work() +-- +2.39.5 + diff --git a/queue-6.12/btrfs-get-zone-unusable-bytes-while-holding-lock-at-.patch b/queue-6.12/btrfs-get-zone-unusable-bytes-while-holding-lock-at-.patch new file mode 100644 index 0000000000..70d399c574 --- /dev/null +++ b/queue-6.12/btrfs-get-zone-unusable-bytes-while-holding-lock-at-.patch @@ -0,0 +1,68 @@ +From d60927365deef5521d5a7f98a2f5854ea7c8cf78 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 16:12:15 +0000 +Subject: btrfs: get zone unusable bytes while holding lock at + btrfs_reclaim_bgs_work() + +From: Filipe Manana + +[ Upstream commit 1283b8c125a83bf7a7dbe90c33d3472b6d7bf612 ] + +At btrfs_reclaim_bgs_work(), we are grabbing a block group's zone unusable +bytes while not under the protection of the block group's spinlock, so +this can trigger race reports from KCSAN (or similar tools) since that +field is typically updated while holding the lock, such as at +__btrfs_add_free_space_zoned() for example. + +Fix this by grabbing the zone unusable bytes while we are still in the +critical section holding the block group's spinlock, which is right above +where we are currently grabbing it. + +Reviewed-by: Johannes Thumshirn +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/block-group.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c +index 4423d8b716a58..aa8656c8b7e7e 100644 +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -1891,6 +1891,17 @@ void btrfs_reclaim_bgs_work(struct work_struct *work) + up_write(&space_info->groups_sem); + goto next; + } ++ ++ /* ++ * Cache the zone_unusable value before turning the block group ++ * to read only. As soon as the block group is read only it's ++ * zone_unusable value gets moved to the block group's read-only ++ * bytes and isn't available for calculations anymore. We also ++ * cache it before unlocking the block group, to prevent races ++ * (reports from KCSAN and such tools) with tasks updating it. ++ */ ++ zone_unusable = bg->zone_unusable; ++ + spin_unlock(&bg->lock); + spin_unlock(&space_info->lock); + +@@ -1907,13 +1918,6 @@ void btrfs_reclaim_bgs_work(struct work_struct *work) + goto next; + } + +- /* +- * Cache the zone_unusable value before turning the block group +- * to read only. As soon as the blog group is read only it's +- * zone_unusable value gets moved to the block group's read-only +- * bytes and isn't available for calculations anymore. +- */ +- zone_unusable = bg->zone_unusable; + ret = inc_block_group_ro(bg, 0); + up_write(&space_info->groups_sem); + if (ret < 0) +-- +2.39.5 + diff --git a/queue-6.12/btrfs-handle-empty-eb-folios-in-num_extent_folios.patch b/queue-6.12/btrfs-handle-empty-eb-folios-in-num_extent_folios.patch new file mode 100644 index 0000000000..9abbe079ef --- /dev/null +++ b/queue-6.12/btrfs-handle-empty-eb-folios-in-num_extent_folios.patch @@ -0,0 +1,39 @@ +From 0285d6e40261e744f594dbd7b413300383a5adc9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 12:47:50 -0700 +Subject: btrfs: handle empty eb->folios in num_extent_folios() + +From: Boris Burkov + +[ Upstream commit d6fe0c69b3aa5c985380b794bdf8e6e9b1811e60 ] + +num_extent_folios() unconditionally calls folio_order() on +eb->folios[0]. If that is NULL this will be a segfault. It is reasonable +for it to return 0 as the number of folios in the eb when the first +entry is NULL, so do that instead. + +Reviewed-by: Qu Wenruo +Signed-off-by: Boris Burkov +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/extent_io.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h +index 8a36117ed4532..fcb60837d7dc6 100644 +--- a/fs/btrfs/extent_io.h ++++ b/fs/btrfs/extent_io.h +@@ -293,6 +293,8 @@ static inline int num_extent_pages(const struct extent_buffer *eb) + */ + static inline int num_extent_folios(const struct extent_buffer *eb) + { ++ if (!eb->folios[0]) ++ return 0; + if (folio_order(eb->folios[0])) + return 1; + return num_extent_pages(eb); +-- +2.39.5 + diff --git a/queue-6.12/btrfs-make-btrfs_discard_workfn-block_group-ref-expl.patch b/queue-6.12/btrfs-make-btrfs_discard_workfn-block_group-ref-expl.patch new file mode 100644 index 0000000000..ed6476388c --- /dev/null +++ b/queue-6.12/btrfs-make-btrfs_discard_workfn-block_group-ref-expl.patch @@ -0,0 +1,106 @@ +From 15609bda6a77bad1b2a9dc3b711d3f8851bde40d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 15:01:05 -0800 +Subject: btrfs: make btrfs_discard_workfn() block_group ref explicit + +From: Boris Burkov + +[ Upstream commit 895c6721d310c036dcfebb5ab845822229fa35eb ] + +Currently, the async discard machinery owns a ref to the block_group +when the block_group is queued on a discard list. However, to handle +races with discard cancellation and the discard workfn, we have a +specific logic to detect that the block_group is *currently* running in +the workfn, to protect the workfn's usage amidst cancellation. + +As far as I can tell, this doesn't have any overt bugs (though +finish_discard_pass() and remove_from_discard_list() racing can have a +surprising outcome for the caller of remove_from_discard_list() in that +it is again added at the end). + +But it is needlessly complicated to rely on locking and the nullity of +discard_ctl->block_group. Simplify this significantly by just taking a +refcount while we are in the workfn and unconditionally drop it in both +the remove and workfn paths, regardless of if they race. + +Reviewed-by: Filipe Manana +Signed-off-by: Boris Burkov +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/discard.c | 34 ++++++++++++++++------------------ + 1 file changed, 16 insertions(+), 18 deletions(-) + +diff --git a/fs/btrfs/discard.c b/fs/btrfs/discard.c +index e9cdc1759dada..de23c4b3515e5 100644 +--- a/fs/btrfs/discard.c ++++ b/fs/btrfs/discard.c +@@ -168,13 +168,7 @@ static bool remove_from_discard_list(struct btrfs_discard_ctl *discard_ctl, + block_group->discard_eligible_time = 0; + queued = !list_empty(&block_group->discard_list); + list_del_init(&block_group->discard_list); +- /* +- * If the block group is currently running in the discard workfn, we +- * don't want to deref it, since it's still being used by the workfn. +- * The workfn will notice this case and deref the block group when it is +- * finished. +- */ +- if (queued && !running) ++ if (queued) + btrfs_put_block_group(block_group); + + spin_unlock(&discard_ctl->lock); +@@ -273,9 +267,10 @@ static struct btrfs_block_group *peek_discard_list( + block_group->discard_cursor = block_group->start; + block_group->discard_state = BTRFS_DISCARD_EXTENTS; + } +- discard_ctl->block_group = block_group; + } + if (block_group) { ++ btrfs_get_block_group(block_group); ++ discard_ctl->block_group = block_group; + *discard_state = block_group->discard_state; + *discard_index = block_group->discard_index; + } +@@ -506,9 +501,20 @@ static void btrfs_discard_workfn(struct work_struct *work) + + block_group = peek_discard_list(discard_ctl, &discard_state, + &discard_index, now); +- if (!block_group || !btrfs_run_discard_work(discard_ctl)) ++ if (!block_group) + return; ++ if (!btrfs_run_discard_work(discard_ctl)) { ++ spin_lock(&discard_ctl->lock); ++ btrfs_put_block_group(block_group); ++ discard_ctl->block_group = NULL; ++ spin_unlock(&discard_ctl->lock); ++ return; ++ } + if (now < block_group->discard_eligible_time) { ++ spin_lock(&discard_ctl->lock); ++ btrfs_put_block_group(block_group); ++ discard_ctl->block_group = NULL; ++ spin_unlock(&discard_ctl->lock); + btrfs_discard_schedule_work(discard_ctl, false); + return; + } +@@ -560,15 +566,7 @@ static void btrfs_discard_workfn(struct work_struct *work) + spin_lock(&discard_ctl->lock); + discard_ctl->prev_discard = trimmed; + discard_ctl->prev_discard_time = now; +- /* +- * If the block group was removed from the discard list while it was +- * running in this workfn, then we didn't deref it, since this function +- * still owned that reference. But we set the discard_ctl->block_group +- * back to NULL, so we can use that condition to know that now we need +- * to deref the block_group. +- */ +- if (discard_ctl->block_group == NULL) +- btrfs_put_block_group(block_group); ++ btrfs_put_block_group(block_group); + discard_ctl->block_group = NULL; + __btrfs_discard_schedule_work(discard_ctl, now, false); + spin_unlock(&discard_ctl->lock); +-- +2.39.5 + diff --git a/queue-6.12/btrfs-prevent-inline-data-extents-read-from-touching.patch b/queue-6.12/btrfs-prevent-inline-data-extents-read-from-touching.patch new file mode 100644 index 0000000000..ec6ad18bab --- /dev/null +++ b/queue-6.12/btrfs-prevent-inline-data-extents-read-from-touching.patch @@ -0,0 +1,122 @@ +From 98504dd74a2688ff63dba6bf1d9f8abc7f0b322e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Nov 2024 19:15:34 +1030 +Subject: btrfs: prevent inline data extents read from touching blocks beyond + its range + +From: Qu Wenruo + +[ Upstream commit 1a5b5668d711d3d1ef447446beab920826decec3 ] + +Currently reading an inline data extent will zero out the remaining +range in the page. + +This is not yet causing problems even for block size < page size +(subpage) cases because: + +1) An inline data extent always starts at file offset 0 + Meaning at page read, we always read the inline extent first, before + any other blocks in the page. Then later blocks are properly read out + and re-fill the zeroed out ranges. + +2) Currently btrfs will read out the whole page if a buffered write is + not page aligned + So a page is either fully uptodate at buffered write time (covers the + whole page), or we will read out the whole page first. + Meaning there is nothing to lose for such an inline extent read. + +But it's still not ideal: + +- We're zeroing out the page twice + Once done by read_inline_extent()/uncompress_inline(), once done by + btrfs_do_readpage() for ranges beyond i_size. + +- We're touching blocks that don't belong to the inline extent + In the incoming patches, we can have a partial uptodate folio, of + which some dirty blocks can exist while the page is not fully uptodate: + + The page size is 16K and block size is 4K: + + 0 4K 8K 12K 16K + | | |/////////| | + + And range [8K, 12K) is dirtied by a buffered write, the remaining + blocks are not uptodate. + + If range [0, 4K) contains an inline data extent, and we try to read + the whole page, the current behavior will overwrite range [8K, 12K) + with zero and cause data loss. + +So to make the behavior more consistent and in preparation for future +changes, limit the inline data extents read to only zero out the range +inside the first block, not the whole page. + +Reviewed-by: Filipe Manana +Signed-off-by: Qu Wenruo +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/inode.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 0da2611fb9c85..ee8c18d298758 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -6825,6 +6825,7 @@ static noinline int uncompress_inline(struct btrfs_path *path, + { + int ret; + struct extent_buffer *leaf = path->nodes[0]; ++ const u32 blocksize = leaf->fs_info->sectorsize; + char *tmp; + size_t max_size; + unsigned long inline_size; +@@ -6841,7 +6842,7 @@ static noinline int uncompress_inline(struct btrfs_path *path, + + read_extent_buffer(leaf, tmp, ptr, inline_size); + +- max_size = min_t(unsigned long, PAGE_SIZE, max_size); ++ max_size = min_t(unsigned long, blocksize, max_size); + ret = btrfs_decompress(compress_type, tmp, folio, 0, inline_size, + max_size); + +@@ -6853,8 +6854,8 @@ static noinline int uncompress_inline(struct btrfs_path *path, + * cover that region here. + */ + +- if (max_size < PAGE_SIZE) +- folio_zero_range(folio, max_size, PAGE_SIZE - max_size); ++ if (max_size < blocksize) ++ folio_zero_range(folio, max_size, blocksize - max_size); + kfree(tmp); + return ret; + } +@@ -6862,6 +6863,7 @@ static noinline int uncompress_inline(struct btrfs_path *path, + static int read_inline_extent(struct btrfs_inode *inode, struct btrfs_path *path, + struct folio *folio) + { ++ const u32 blocksize = path->nodes[0]->fs_info->sectorsize; + struct btrfs_file_extent_item *fi; + void *kaddr; + size_t copy_size; +@@ -6876,14 +6878,14 @@ static int read_inline_extent(struct btrfs_inode *inode, struct btrfs_path *path + if (btrfs_file_extent_compression(path->nodes[0], fi) != BTRFS_COMPRESS_NONE) + return uncompress_inline(path, folio, fi); + +- copy_size = min_t(u64, PAGE_SIZE, ++ copy_size = min_t(u64, blocksize, + btrfs_file_extent_ram_bytes(path->nodes[0], fi)); + kaddr = kmap_local_folio(folio, 0); + read_extent_buffer(path->nodes[0], kaddr, + btrfs_file_extent_inline_start(fi), copy_size); + kunmap_local(kaddr); +- if (copy_size < PAGE_SIZE) +- folio_zero_range(folio, copy_size, PAGE_SIZE - copy_size); ++ if (copy_size < blocksize) ++ folio_zero_range(folio, copy_size, blocksize - copy_size); + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.12/btrfs-properly-limit-inline-data-extent-according-to.patch b/queue-6.12/btrfs-properly-limit-inline-data-extent-according-to.patch new file mode 100644 index 0000000000..54792afae0 --- /dev/null +++ b/queue-6.12/btrfs-properly-limit-inline-data-extent-according-to.patch @@ -0,0 +1,72 @@ +From a5afc96d757771c992eb3af4629a562ec52ba1dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 14:30:44 +1030 +Subject: btrfs: properly limit inline data extent according to block size + +From: Qu Wenruo + +[ Upstream commit 23019d3e6617a8ec99a8d2f5947aa3dd8a74a1b8 ] + +Btrfs utilizes inline data extent for the following cases: + +- Regular small files +- Symlinks + +And "btrfs check" detects any file extents that are too large as an +error. + +It's not a problem for 4K block size, but for the incoming smaller +block sizes (2K), it can cause problems due to bad limits: + +- Non-compressed inline data extents + We do not allow a non-compressed inline data extent to be as large as + block size. + +- Symlinks + Currently the only real limit on symlinks are 4K, which can be larger + than 2K block size. + +These will result btrfs-check to report too large file extents. + +Fix it by adding proper size checks for the above cases. + +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/inode.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 9ce1270addb04..0da2611fb9c85 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -623,6 +623,10 @@ static bool can_cow_file_range_inline(struct btrfs_inode *inode, + if (size > fs_info->sectorsize) + return false; + ++ /* We do not allow a non-compressed extent to be as large as block size. */ ++ if (data_len >= fs_info->sectorsize) ++ return false; ++ + /* We cannot exceed the maximum inline data size. */ + if (data_len > BTRFS_MAX_INLINE_DATA_SIZE(fs_info)) + return false; +@@ -8691,7 +8695,12 @@ static int btrfs_symlink(struct mnt_idmap *idmap, struct inode *dir, + struct extent_buffer *leaf; + + name_len = strlen(symname); +- if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(fs_info)) ++ /* ++ * Symlinks utilize uncompressed inline extent data, which should not ++ * reach block size. ++ */ ++ if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(fs_info) || ++ name_len >= fs_info->sectorsize) + return -ENAMETOOLONG; + + inode = new_inode(dir->i_sb); +-- +2.39.5 + diff --git a/queue-6.12/btrfs-run-btrfs_error_commit_super-early.patch b/queue-6.12/btrfs-run-btrfs_error_commit_super-early.patch new file mode 100644 index 0000000000..5831e454fe --- /dev/null +++ b/queue-6.12/btrfs-run-btrfs_error_commit_super-early.patch @@ -0,0 +1,98 @@ +From 71eb805f31af11f3055df78c5b20531f2aeb6f73 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Mar 2025 14:36:10 +1030 +Subject: btrfs: run btrfs_error_commit_super() early + +From: Qu Wenruo + +[ Upstream commit df94a342efb451deb0e32b495d1d6cd4bb3a1648 ] + +[BUG] +Even after all the error fixes related the +"ASSERT(list_empty(&fs_info->delayed_iputs));" in close_ctree(), I can +still hit it reliably with my experimental 2K block size. + +[CAUSE] +In my case, all the error is triggered after the fs is already in error +status. + +I find the following call trace to be the cause of race: + + Main thread | endio_write_workers +---------------------------------------------+--------------------------- +close_ctree() | +|- btrfs_error_commit_super() | +| |- btrfs_cleanup_transaction() | +| | |- btrfs_destroy_all_ordered_extents() | +| | |- btrfs_wait_ordered_roots() | +| |- btrfs_run_delayed_iputs() | +| | btrfs_finish_ordered_io() +| | |- btrfs_put_ordered_extent() +| | |- btrfs_add_delayed_iput() +|- ASSERT(list_empty(delayed_iputs)) | + !!! Triggered !!! + +The root cause is that, btrfs_wait_ordered_roots() only wait for +ordered extents to finish their IOs, not to wait for them to finish and +removed. + +[FIX] +Since btrfs_error_commit_super() will flush and wait for all ordered +extents, it should be executed early, before we start flushing the +workqueues. + +And since btrfs_error_commit_super() now runs early, there is no need to +run btrfs_run_delayed_iputs() inside it, so just remove the +btrfs_run_delayed_iputs() call from btrfs_error_commit_super(). + +Reviewed-by: Filipe Manana +Signed-off-by: Qu Wenruo +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/disk-io.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c +index 19e5f8eaae772..e0e740e4d7c75 100644 +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -4254,6 +4254,14 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info) + /* clear out the rbtree of defraggable inodes */ + btrfs_cleanup_defrag_inodes(fs_info); + ++ /* ++ * Handle the error fs first, as it will flush and wait for all ordered ++ * extents. This will generate delayed iputs, thus we want to handle ++ * it first. ++ */ ++ if (unlikely(BTRFS_FS_ERROR(fs_info))) ++ btrfs_error_commit_super(fs_info); ++ + /* + * Wait for any fixup workers to complete. + * If we don't wait for them here and they are still running by the time +@@ -4343,9 +4351,6 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info) + btrfs_err(fs_info, "commit super ret %d", ret); + } + +- if (BTRFS_FS_ERROR(fs_info)) +- btrfs_error_commit_super(fs_info); +- + kthread_stop(fs_info->transaction_kthread); + kthread_stop(fs_info->cleaner_kthread); + +@@ -4468,10 +4473,6 @@ static void btrfs_error_commit_super(struct btrfs_fs_info *fs_info) + /* cleanup FS via transaction */ + btrfs_cleanup_transaction(fs_info); + +- mutex_lock(&fs_info->cleaner_mutex); +- btrfs_run_delayed_iputs(fs_info); +- mutex_unlock(&fs_info->cleaner_mutex); +- + down_write(&fs_info->cleanup_work_sem); + up_write(&fs_info->cleanup_work_sem); + } +-- +2.39.5 + diff --git a/queue-6.12/btrfs-send-return-enametoolong-when-attempting-a-pat.patch b/queue-6.12/btrfs-send-return-enametoolong-when-attempting-a-pat.patch new file mode 100644 index 0000000000..3cffc35250 --- /dev/null +++ b/queue-6.12/btrfs-send-return-enametoolong-when-attempting-a-pat.patch @@ -0,0 +1,46 @@ +From 5fe70cc5c2e4fd256ad700a1e3a66e23e1964295 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 13:09:25 +0000 +Subject: btrfs: send: return -ENAMETOOLONG when attempting a path that is too + long + +From: Filipe Manana + +[ Upstream commit a77749b3e21813566cea050bbb3414ae74562eba ] + +When attempting to build a too long path we are currently returning +-ENOMEM, which is very odd and misleading. So update fs_path_ensure_buf() +to return -ENAMETOOLONG instead. Also, while at it, move the WARN_ON() +into the if statement's expression, as it makes it clear what is being +tested and also has the effect of adding 'unlikely' to the statement, +which allows the compiler to generate better code as this condition is +never expected to happen. + +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/send.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c +index b1015f383f75e..c843b4aefb8ac 100644 +--- a/fs/btrfs/send.c ++++ b/fs/btrfs/send.c +@@ -487,10 +487,8 @@ static int fs_path_ensure_buf(struct fs_path *p, int len) + if (p->buf_len >= len) + return 0; + +- if (len > PATH_MAX) { +- WARN_ON(1); +- return -ENOMEM; +- } ++ if (WARN_ON(len > PATH_MAX)) ++ return -ENAMETOOLONG; + + path_len = p->end - p->start; + old_buf_len = p->buf_len; +-- +2.39.5 + diff --git a/queue-6.12/btrfs-zoned-exit-btrfs_can_activate_zone-if-btrfs_fs.patch b/queue-6.12/btrfs-zoned-exit-btrfs_can_activate_zone-if-btrfs_fs.patch new file mode 100644 index 0000000000..63281ede70 --- /dev/null +++ b/queue-6.12/btrfs-zoned-exit-btrfs_can_activate_zone-if-btrfs_fs.patch @@ -0,0 +1,40 @@ +From 784d3a559cba3422f75db61667062152c4f14697 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 15:05:00 +0100 +Subject: btrfs: zoned: exit btrfs_can_activate_zone if + BTRFS_FS_NEED_ZONE_FINISH is set + +From: Johannes Thumshirn + +[ Upstream commit 26b38e28162ef4ceb1e0482299820fbbd7dbcd92 ] + +If BTRFS_FS_NEED_ZONE_FINISH is already set for the whole filesystem, exit +early in btrfs_can_activate_zone(). There's no need to check if +BTRFS_FS_NEED_ZONE_FINISH needs to be set if it is already set. + +Reviewed-by: Naohiro Aota +Signed-off-by: Johannes Thumshirn +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/zoned.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c +index 2603c9d60fd21..d1167aeb07354 100644 +--- a/fs/btrfs/zoned.c ++++ b/fs/btrfs/zoned.c +@@ -2326,6 +2326,9 @@ bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices, u64 flags) + if (!btrfs_is_zoned(fs_info)) + return true; + ++ if (test_bit(BTRFS_FS_NEED_ZONE_FINISH, &fs_info->flags)) ++ return false; ++ + /* Check if there is a device with active zones left */ + mutex_lock(&fs_info->chunk_mutex); + spin_lock(&fs_info->zone_active_bgs_lock); +-- +2.39.5 + diff --git a/queue-6.12/can-c_can-use-of_property_present-to-test-existence-.patch b/queue-6.12/can-c_can-use-of_property_present-to-test-existence-.patch new file mode 100644 index 0000000000..2801d69283 --- /dev/null +++ b/queue-6.12/can-c_can-use-of_property_present-to-test-existence-.patch @@ -0,0 +1,38 @@ +From 16833ca50849a92a655900498d280237f83d199a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 21:23:14 +0100 +Subject: can: c_can: Use of_property_present() to test existence of DT + property + +From: Krzysztof Kozlowski + +[ Upstream commit ab1bc2290fd8311d49b87c29f1eb123fcb581bee ] + +of_property_read_bool() should be used only on boolean properties. + +Cc: Rob Herring +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Vincent Mailhol +Link: https://patch.msgid.link/20250212-syscon-phandle-args-can-v2-3-ac9a1253396b@linaro.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/c_can/c_can_platform.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c +index 399844809bbea..bb6071a758f36 100644 +--- a/drivers/net/can/c_can/c_can_platform.c ++++ b/drivers/net/can/c_can/c_can_platform.c +@@ -324,7 +324,7 @@ static int c_can_plat_probe(struct platform_device *pdev) + /* Check if we need custom RAMINIT via syscon. Mostly for TI + * platforms. Only supported with DT boot. + */ +- if (np && of_property_read_bool(np, "syscon-raminit")) { ++ if (np && of_property_present(np, "syscon-raminit")) { + u32 id; + struct c_can_raminit *raminit = &priv->raminit_sys; + +-- +2.39.5 + diff --git a/queue-6.12/cgroup-fix-compilation-issue-due-to-cgroup_mutex-not.patch b/queue-6.12/cgroup-fix-compilation-issue-due-to-cgroup_mutex-not.patch new file mode 100644 index 0000000000..9f5a3fc4f6 --- /dev/null +++ b/queue-6.12/cgroup-fix-compilation-issue-due-to-cgroup_mutex-not.patch @@ -0,0 +1,48 @@ +From e30f4f1ba5422c601eb0c9772b611ee2e7c47305 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 07:30:00 +0000 +Subject: cgroup: Fix compilation issue due to cgroup_mutex not being exported +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: gaoxu + +[ Upstream commit 87c259a7a359e73e6c52c68fcbec79988999b4e6 ] + +When adding folio_memcg function call in the zram module for +Android16-6.12, the following error occurs during compilation: +ERROR: modpost: "cgroup_mutex" [../soc-repo/zram.ko] undefined! + +This error is caused by the indirect call to lockdep_is_held(&cgroup_mutex) +within folio_memcg. The export setting for cgroup_mutex is controlled by +the CONFIG_PROVE_RCU macro. If CONFIG_LOCKDEP is enabled while +CONFIG_PROVE_RCU is not, this compilation error will occur. + +To resolve this issue, add a parallel macro CONFIG_LOCKDEP control to +ensure cgroup_mutex is properly exported when needed. + +Signed-off-by: gao xu +Acked-by: Michal Koutný +Signed-off-by: Tejun Heo +Signed-off-by: Sasha Levin +--- + kernel/cgroup/cgroup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c +index e63d6f3b00470..62933468aaf46 100644 +--- a/kernel/cgroup/cgroup.c ++++ b/kernel/cgroup/cgroup.c +@@ -90,7 +90,7 @@ + DEFINE_MUTEX(cgroup_mutex); + DEFINE_SPINLOCK(css_set_lock); + +-#ifdef CONFIG_PROVE_RCU ++#if (defined CONFIG_PROVE_RCU || defined CONFIG_LOCKDEP) + EXPORT_SYMBOL_GPL(cgroup_mutex); + EXPORT_SYMBOL_GPL(css_set_lock); + #endif +-- +2.39.5 + diff --git a/queue-6.12/cgroup-rstat-avoid-disabling-irqs-for-o-num_cpu.patch b/queue-6.12/cgroup-rstat-avoid-disabling-irqs-for-o-num_cpu.patch new file mode 100644 index 0000000000..709005db1c --- /dev/null +++ b/queue-6.12/cgroup-rstat-avoid-disabling-irqs-for-o-num_cpu.patch @@ -0,0 +1,111 @@ +From 161ad2c6209c7993a7ad833ef24bb548cdab5dc2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 00:13:30 -0700 +Subject: cgroup/rstat: avoid disabling irqs for O(num_cpu) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Eric Dumazet + +[ Upstream commit 0efc297a3c4974dbd609ee36fc6345720b6ca735 ] + +cgroup_rstat_flush_locked() grabs the irq safe cgroup_rstat_lock while +iterating all possible cpus. It only drops the lock if there is +scheduler or spin lock contention. If neither, then interrupts can be +disabled for a long time. On large machines this can disable interrupts +for a long enough time to drop network packets. On 400+ CPU machines +I've seen interrupt disabled for over 40 msec. + +Prevent rstat from disabling interrupts while processing all possible +cpus. Instead drop and reacquire cgroup_rstat_lock for each cpu. This +approach was previously discussed in +https://lore.kernel.org/lkml/ZBz%2FV5a7%2F6PZeM7S@slm.duckdns.org/, +though this was in the context of an non-irq rstat spin lock. + +Benchmark this change with: +1) a single stat_reader process with 400 threads, each reading a test + memcg's memory.stat repeatedly for 10 seconds. +2) 400 memory hog processes running in the test memcg and repeatedly + charging memory until oom killed. Then they repeat charging and oom + killing. + +v6.14-rc6 with CONFIG_IRQSOFF_TRACER with stat_reader and hogs, finds +interrupts are disabled by rstat for 45341 usec: + # => started at: _raw_spin_lock_irq + # => ended at: cgroup_rstat_flush + # + # + # _------=> CPU# + # / _-----=> irqs-off/BH-disabled + # | / _----=> need-resched + # || / _---=> hardirq/softirq + # ||| / _--=> preempt-depth + # |||| / _-=> migrate-disable + # ||||| / delay + # cmd pid |||||| time | caller + # \ / |||||| \ | / + stat_rea-96532 52d.... 0us*: _raw_spin_lock_irq + stat_rea-96532 52d.... 45342us : cgroup_rstat_flush + stat_rea-96532 52d.... 45342us : tracer_hardirqs_on <-cgroup_rstat_flush + stat_rea-96532 52d.... 45343us : + => memcg1_stat_format + => memory_stat_format + => memory_stat_show + => seq_read_iter + => vfs_read + => ksys_read + => do_syscall_64 + => entry_SYSCALL_64_after_hwframe + +With this patch the CONFIG_IRQSOFF_TRACER doesn't find rstat to be the +longest holder. The longest irqs-off holder has irqs disabled for +4142 usec, a huge reduction from previous 45341 usec rstat finding. + +Running stat_reader memory.stat reader for 10 seconds: +- without memory hogs: 9.84M accesses => 12.7M accesses +- with memory hogs: 9.46M accesses => 11.1M accesses +The throughput of memory.stat access improves. + +The mode of memory.stat access latency after grouping by of 2 buckets: +- without memory hogs: 64 usec => 16 usec +- with memory hogs: 64 usec => 8 usec +The memory.stat latency improves. + +Signed-off-by: Eric Dumazet +Signed-off-by: Greg Thelen +Tested-by: Greg Thelen +Acked-by: Michal Koutný +Reviewed-by: Yosry Ahmed +Signed-off-by: Tejun Heo +Signed-off-by: Sasha Levin +--- + kernel/cgroup/rstat.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +diff --git a/kernel/cgroup/rstat.c b/kernel/cgroup/rstat.c +index 3e01781aeb7bd..c4ce2f5a9745f 100644 +--- a/kernel/cgroup/rstat.c ++++ b/kernel/cgroup/rstat.c +@@ -323,13 +323,11 @@ static void cgroup_rstat_flush_locked(struct cgroup *cgrp) + rcu_read_unlock(); + } + +- /* play nice and yield if necessary */ +- if (need_resched() || spin_needbreak(&cgroup_rstat_lock)) { +- __cgroup_rstat_unlock(cgrp, cpu); +- if (!cond_resched()) +- cpu_relax(); +- __cgroup_rstat_lock(cgrp, cpu); +- } ++ /* play nice and avoid disabling interrupts for a long time */ ++ __cgroup_rstat_unlock(cgrp, cpu); ++ if (!cond_resched()) ++ cpu_relax(); ++ __cgroup_rstat_lock(cgrp, cpu); + } + } + +-- +2.39.5 + diff --git a/queue-6.12/cifs-add-fallback-for-smb2-create-without-file_read_.patch b/queue-6.12/cifs-add-fallback-for-smb2-create-without-file_read_.patch new file mode 100644 index 0000000000..4d2cbffa4d --- /dev/null +++ b/queue-6.12/cifs-add-fallback-for-smb2-create-without-file_read_.patch @@ -0,0 +1,65 @@ +From f6ed3cfb612385aaa39ac1433c059d824063ef2e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Dec 2024 20:44:23 +0100 +Subject: cifs: Add fallback for SMB2 CREATE without FILE_READ_ATTRIBUTES +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit e255612b5ed9f179abe8196df7c2ba09dd227900 ] + +Some operations, like WRITE, does not require FILE_READ_ATTRIBUTES access. + +So when FILE_READ_ATTRIBUTES is not explicitly requested for +smb2_open_file() then first try to do SMB2 CREATE with FILE_READ_ATTRIBUTES +access (like it was before) and then fallback to SMB2 CREATE without +FILE_READ_ATTRIBUTES access (less common case). + +This change allows to complete WRITE operation to a file when it does not +grant FILE_READ_ATTRIBUTES permission and its parent directory does not +grant READ_DATA permission (parent directory READ_DATA is implicit grant of +child FILE_READ_ATTRIBUTES permission). + +Signed-off-by: Pali Rohár +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/smb2file.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c +index e836bc2193ddd..b313c128ffbab 100644 +--- a/fs/smb/client/smb2file.c ++++ b/fs/smb/client/smb2file.c +@@ -107,16 +107,25 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 + int err_buftype = CIFS_NO_BUFFER; + struct cifs_fid *fid = oparms->fid; + struct network_resiliency_req nr_ioctl_req; ++ bool retry_without_read_attributes = false; + + smb2_path = cifs_convert_path_to_utf16(oparms->path, oparms->cifs_sb); + if (smb2_path == NULL) + return -ENOMEM; + +- oparms->desired_access |= FILE_READ_ATTRIBUTES; ++ if (!(oparms->desired_access & FILE_READ_ATTRIBUTES)) { ++ oparms->desired_access |= FILE_READ_ATTRIBUTES; ++ retry_without_read_attributes = true; ++ } + smb2_oplock = SMB2_OPLOCK_LEVEL_BATCH; + + rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, + &err_buftype); ++ if (rc == -EACCES && retry_without_read_attributes) { ++ oparms->desired_access &= ~FILE_READ_ATTRIBUTES; ++ rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, ++ &err_buftype); ++ } + if (rc && data) { + struct smb2_hdr *hdr = err_iov.iov_base; + +-- +2.39.5 + diff --git a/queue-6.12/cifs-add-validation-check-for-the-fields-in-smb_aces.patch b/queue-6.12/cifs-add-validation-check-for-the-fields-in-smb_aces.patch new file mode 100644 index 0000000000..37ddc6da76 --- /dev/null +++ b/queue-6.12/cifs-add-validation-check-for-the-fields-in-smb_aces.patch @@ -0,0 +1,58 @@ +From 8fcbf5b2c6acceb99a41813e54be5d9739ee9028 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 17:52:19 +0900 +Subject: cifs: add validation check for the fields in smb_aces + +From: Namjae Jeon + +[ Upstream commit eeb827f2922eb07ffbf7d53569cc95b38272646f ] + +cifs.ko is missing validation check when accessing smb_aces. +This patch add validation check for the fields in smb_aces. + +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/cifsacl.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/fs/smb/client/cifsacl.c b/fs/smb/client/cifsacl.c +index e36f0e2d7d21e..9a73478e00688 100644 +--- a/fs/smb/client/cifsacl.c ++++ b/fs/smb/client/cifsacl.c +@@ -811,7 +811,23 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl, + return; + + for (i = 0; i < num_aces; ++i) { ++ if (end_of_acl - acl_base < acl_size) ++ break; ++ + ppace[i] = (struct smb_ace *) (acl_base + acl_size); ++ acl_base = (char *)ppace[i]; ++ acl_size = offsetof(struct smb_ace, sid) + ++ offsetof(struct smb_sid, sub_auth); ++ ++ if (end_of_acl - acl_base < acl_size || ++ ppace[i]->sid.num_subauth == 0 || ++ ppace[i]->sid.num_subauth > SID_MAX_SUB_AUTHORITIES || ++ (end_of_acl - acl_base < ++ acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth) || ++ (le16_to_cpu(ppace[i]->size) < ++ acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth)) ++ break; ++ + #ifdef CONFIG_CIFS_DEBUG2 + dump_ace(ppace[i], end_of_acl); + #endif +@@ -855,7 +871,6 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl, + (void *)ppace[i], + sizeof(struct smb_ace)); */ + +- acl_base = (char *)ppace[i]; + acl_size = le16_to_cpu(ppace[i]->size); + } + +-- +2.39.5 + diff --git a/queue-6.12/cifs-fix-and-improve-cifs_query_path_info-and-cifs_q.patch b/queue-6.12/cifs-fix-and-improve-cifs_query_path_info-and-cifs_q.patch new file mode 100644 index 0000000000..1883ac3959 --- /dev/null +++ b/queue-6.12/cifs-fix-and-improve-cifs_query_path_info-and-cifs_q.patch @@ -0,0 +1,183 @@ +From 611b159a9999bc5cebfe7b8616dd5cd3c6d3a7be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 30 Dec 2024 20:34:18 +0100 +Subject: cifs: Fix and improve cifs_query_path_info() and + cifs_query_file_info() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit 1041c117a2c33cdffc4f695ac4b469e9124d24d5 ] + +When CAP_NT_SMBS was not negotiated then do not issue CIFSSMBQPathInfo() +and CIFSSMBQFileInfo() commands. CIFSSMBQPathInfo() is not supported by +non-NT Win9x SMB server and CIFSSMBQFileInfo() returns from Win9x SMB +server bogus data in Attributes field (for example lot of files are marked +as reparse points, even Win9x does not support them and read-only bit is +not marked for read-only files). Correct information is returned by +CIFSFindFirst() or SMBQueryInformation() command. + +So as a fallback in cifs_query_path_info() function use CIFSFindFirst() +with SMB_FIND_FILE_FULL_DIRECTORY_INFO level which is supported by both NT +and non-NT servers and as a last option use SMBQueryInformation() as it was +before. + +And in function cifs_query_file_info() immediately returns -EOPNOTSUPP when +not communicating with NT server. Client then revalidate inode entry by the +cifs_query_path_info() call, which is working fine. So fstat() syscall on +already opened file will receive correct information. + +Note that both fallback functions in non-UNICODE mode expands wildcards. +Therefore those fallback functions cannot be used on paths which contain +SMB wildcard characters (* ? " > <). + +CIFSFindFirst() returns all 4 time attributes as opposite of +SMBQueryInformation() which returns only one. + +With this change it is possible to query all 4 times attributes from Win9x +server and at the same time, client minimize sending of unsupported +commands to server. + +Signed-off-by: Pali Rohár +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/smb1ops.c | 103 ++++++++++++++++++++++++++++++++++++---- + 1 file changed, 95 insertions(+), 8 deletions(-) + +diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c +index 71fe5aa52630d..088fd84188b95 100644 +--- a/fs/smb/client/smb1ops.c ++++ b/fs/smb/client/smb1ops.c +@@ -541,24 +541,104 @@ static int cifs_query_path_info(const unsigned int xid, + const char *full_path, + struct cifs_open_info_data *data) + { +- int rc; ++ int rc = -EOPNOTSUPP; + FILE_ALL_INFO fi = {}; ++ struct cifs_search_info search_info = {}; ++ bool non_unicode_wildcard = false; + + data->reparse_point = false; + data->adjust_tz = false; + +- /* could do find first instead but this returns more info */ +- rc = CIFSSMBQPathInfo(xid, tcon, full_path, &fi, 0 /* not legacy */, cifs_sb->local_nls, +- cifs_remap(cifs_sb)); + /* +- * BB optimize code so we do not make the above call when server claims +- * no NT SMB support and the above call failed at least once - set flag +- * in tcon or mount. ++ * First try CIFSSMBQPathInfo() function which returns more info ++ * (NumberOfLinks) than CIFSFindFirst() fallback function. ++ * Some servers like Win9x do not support SMB_QUERY_FILE_ALL_INFO over ++ * TRANS2_QUERY_PATH_INFORMATION, but supports it with filehandle over ++ * TRANS2_QUERY_FILE_INFORMATION (function CIFSSMBQFileInfo(). But SMB ++ * Open command on non-NT servers works only for files, does not work ++ * for directories. And moreover Win9x SMB server returns bogus data in ++ * SMB_QUERY_FILE_ALL_INFO Attributes field. So for non-NT servers, ++ * do not even use CIFSSMBQPathInfo() or CIFSSMBQFileInfo() function. ++ */ ++ if (tcon->ses->capabilities & CAP_NT_SMBS) ++ rc = CIFSSMBQPathInfo(xid, tcon, full_path, &fi, 0 /* not legacy */, ++ cifs_sb->local_nls, cifs_remap(cifs_sb)); ++ ++ /* ++ * Non-UNICODE variant of fallback functions below expands wildcards, ++ * so they cannot be used for querying paths with wildcard characters. + */ +- if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { ++ if (rc && !(tcon->ses->capabilities & CAP_UNICODE) && strpbrk(full_path, "*?\"><")) ++ non_unicode_wildcard = true; ++ ++ /* ++ * Then fallback to CIFSFindFirst() which works also with non-NT servers ++ * but does not does not provide NumberOfLinks. ++ */ ++ if ((rc == -EOPNOTSUPP || rc == -EINVAL) && ++ !non_unicode_wildcard) { ++ if (!(tcon->ses->capabilities & tcon->ses->server->vals->cap_nt_find)) ++ search_info.info_level = SMB_FIND_FILE_INFO_STANDARD; ++ else ++ search_info.info_level = SMB_FIND_FILE_FULL_DIRECTORY_INFO; ++ rc = CIFSFindFirst(xid, tcon, full_path, cifs_sb, NULL, ++ CIFS_SEARCH_CLOSE_ALWAYS | CIFS_SEARCH_CLOSE_AT_END, ++ &search_info, false); ++ if (rc == 0) { ++ if (!(tcon->ses->capabilities & tcon->ses->server->vals->cap_nt_find)) { ++ FIND_FILE_STANDARD_INFO *di; ++ int offset = tcon->ses->server->timeAdj; ++ ++ di = (FIND_FILE_STANDARD_INFO *)search_info.srch_entries_start; ++ fi.CreationTime = cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm( ++ di->CreationDate, di->CreationTime, offset))); ++ fi.LastAccessTime = cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm( ++ di->LastAccessDate, di->LastAccessTime, offset))); ++ fi.LastWriteTime = cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm( ++ di->LastWriteDate, di->LastWriteTime, offset))); ++ fi.ChangeTime = fi.LastWriteTime; ++ fi.Attributes = cpu_to_le32(le16_to_cpu(di->Attributes)); ++ fi.AllocationSize = cpu_to_le64(le32_to_cpu(di->AllocationSize)); ++ fi.EndOfFile = cpu_to_le64(le32_to_cpu(di->DataSize)); ++ } else { ++ FILE_FULL_DIRECTORY_INFO *di; ++ ++ di = (FILE_FULL_DIRECTORY_INFO *)search_info.srch_entries_start; ++ fi.CreationTime = di->CreationTime; ++ fi.LastAccessTime = di->LastAccessTime; ++ fi.LastWriteTime = di->LastWriteTime; ++ fi.ChangeTime = di->ChangeTime; ++ fi.Attributes = di->ExtFileAttributes; ++ fi.AllocationSize = di->AllocationSize; ++ fi.EndOfFile = di->EndOfFile; ++ fi.EASize = di->EaSize; ++ } ++ fi.NumberOfLinks = cpu_to_le32(1); ++ fi.DeletePending = 0; ++ fi.Directory = !!(le32_to_cpu(fi.Attributes) & ATTR_DIRECTORY); ++ cifs_buf_release(search_info.ntwrk_buf_start); ++ } else if (!full_path[0]) { ++ /* ++ * CIFSFindFirst() does not work on root path if the ++ * root path was exported on the server from the top ++ * level path (drive letter). ++ */ ++ rc = -EOPNOTSUPP; ++ } ++ } ++ ++ /* ++ * If everything failed then fallback to the legacy SMB command ++ * SMB_COM_QUERY_INFORMATION which works with all servers, but ++ * provide just few information. ++ */ ++ if ((rc == -EOPNOTSUPP || rc == -EINVAL) && !non_unicode_wildcard) { + rc = SMBQueryInformation(xid, tcon, full_path, &fi, cifs_sb->local_nls, + cifs_remap(cifs_sb)); + data->adjust_tz = true; ++ } else if ((rc == -EOPNOTSUPP || rc == -EINVAL) && non_unicode_wildcard) { ++ /* Path with non-UNICODE wildcard character cannot exist. */ ++ rc = -ENOENT; + } + + if (!rc) { +@@ -655,6 +735,13 @@ static int cifs_query_file_info(const unsigned int xid, struct cifs_tcon *tcon, + int rc; + FILE_ALL_INFO fi = {}; + ++ /* ++ * CIFSSMBQFileInfo() for non-NT servers returns bogus data in ++ * Attributes fields. So do not use this command for non-NT servers. ++ */ ++ if (!(tcon->ses->capabilities & CAP_NT_SMBS)) ++ return -EOPNOTSUPP; ++ + if (cfile->symlink_target) { + data->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL); + if (!data->symlink_target) +-- +2.39.5 + diff --git a/queue-6.12/cifs-fix-changing-times-and-read-only-attr-over-smb1.patch b/queue-6.12/cifs-fix-changing-times-and-read-only-attr-over-smb1.patch new file mode 100644 index 0000000000..11a5f2a66f --- /dev/null +++ b/queue-6.12/cifs-fix-changing-times-and-read-only-attr-over-smb1.patch @@ -0,0 +1,334 @@ +From 7923eac171fea5177740f19ab35a606d732a97ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 30 Dec 2024 21:32:39 +0100 +Subject: cifs: Fix changing times and read-only attr over SMB1 + smb_set_file_info() function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit f122121796f91168d0894c2710b8dd71330a34f8 ] + +Function CIFSSMBSetPathInfo() is not supported by non-NT servers and +returns error. Fallback code via open filehandle and CIFSSMBSetFileInfo() +does not work neither because CIFS_open() works also only on NT server. + +Therefore currently the whole smb_set_file_info() function as a SMB1 +callback for the ->set_file_info() does not work with older non-NT SMB +servers, like Win9x and others. + +This change implements fallback code in smb_set_file_info() which will +works with any server and allows to change time values and also to set or +clear read-only attributes. + +To make existing fallback code via CIFSSMBSetFileInfo() working with also +non-NT servers, it is needed to change open function from CIFS_open() +(which is NT specific) to cifs_open_file() which works with any server +(this is just a open wrapper function which choose the correct open +function supported by the server). + +CIFSSMBSetFileInfo() is working also on non-NT servers, but zero time +values are not treated specially. So first it is needed to fill all time +values if some of them are missing, via cifs_query_path_info() call. + +There is another issue, opening file in write-mode (needed for changing +attributes) is not possible when the file has read-only attribute set. +The only option how to clear read-only attribute is via SMB_COM_SETATTR +command. And opening directory is not possible neither and here the +SMB_COM_SETATTR command is the only option how to change attributes. +And CIFSSMBSetFileInfo() does not honor setting read-only attribute, so +for setting is also needed to use SMB_COM_SETATTR command. + +Existing code in cifs_query_path_info() is already using SMB_COM_GETATTR as +a fallback code path (function SMBQueryInformation()), so introduce a new +function SMBSetInformation which will implement SMB_COM_SETATTR command. + +My testing showed that Windows XP SMB1 client is also using SMB_COM_SETATTR +command for setting or clearing read-only attribute against non-NT server. +So this can prove that this is the correct way how to do it. + +With this change it is possible set all 4 time values and all attributes, +including clearing and setting read-only bit on non-NT SMB servers. +Tested against Win98 SMB1 server. + +This change fixes "touch" command which was failing when called on existing +file. And fixes also "chmod +w" and "chmod -w" commands which were also +failing (as they are changing read-only attribute). + +Note that this change depends on following change +"cifs: Improve cifs_query_path_info() and cifs_query_file_info()" +as it require to query all 4 time attribute values. + +Signed-off-by: Pali Rohár +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/cifspdu.h | 5 +- + fs/smb/client/cifsproto.h | 4 ++ + fs/smb/client/cifssmb.c | 57 +++++++++++++++++++ + fs/smb/client/smb1ops.c | 112 +++++++++++++++++++++++++++++++++++--- + 4 files changed, 166 insertions(+), 12 deletions(-) + +diff --git a/fs/smb/client/cifspdu.h b/fs/smb/client/cifspdu.h +index ee78bb6741d62..28f8ca470770d 100644 +--- a/fs/smb/client/cifspdu.h ++++ b/fs/smb/client/cifspdu.h +@@ -1226,10 +1226,9 @@ typedef struct smb_com_query_information_rsp { + typedef struct smb_com_setattr_req { + struct smb_hdr hdr; /* wct = 8 */ + __le16 attr; +- __le16 time_low; +- __le16 time_high; ++ __le32 last_write_time; + __le16 reserved[5]; /* must be zero */ +- __u16 ByteCount; ++ __le16 ByteCount; + __u8 BufferFormat; /* 4 = ASCII */ + unsigned char fileName[]; + } __attribute__((packed)) SETATTR_REQ; +diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h +index 306386e5c171f..6e938b17875f5 100644 +--- a/fs/smb/client/cifsproto.h ++++ b/fs/smb/client/cifsproto.h +@@ -396,6 +396,10 @@ extern int CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon); + extern int CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon, + struct kstatfs *FSData); + ++extern int SMBSetInformation(const unsigned int xid, struct cifs_tcon *tcon, ++ const char *fileName, __le32 attributes, __le64 write_time, ++ const struct nls_table *nls_codepage, ++ struct cifs_sb_info *cifs_sb); + extern int CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon, + const char *fileName, const FILE_BASIC_INFO *data, + const struct nls_table *nls_codepage, +diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c +index e2a14e25da87c..8667f403a0ab6 100644 +--- a/fs/smb/client/cifssmb.c ++++ b/fs/smb/client/cifssmb.c +@@ -5199,6 +5199,63 @@ CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, + return rc; + } + ++int ++SMBSetInformation(const unsigned int xid, struct cifs_tcon *tcon, ++ const char *fileName, __le32 attributes, __le64 write_time, ++ const struct nls_table *nls_codepage, ++ struct cifs_sb_info *cifs_sb) ++{ ++ SETATTR_REQ *pSMB; ++ SETATTR_RSP *pSMBr; ++ struct timespec64 ts; ++ int bytes_returned; ++ int name_len; ++ int rc; ++ ++ cifs_dbg(FYI, "In %s path %s\n", __func__, fileName); ++ ++retry: ++ rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB, ++ (void **) &pSMBr); ++ if (rc) ++ return rc; ++ ++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { ++ name_len = ++ cifsConvertToUTF16((__le16 *) pSMB->fileName, ++ fileName, PATH_MAX, nls_codepage, ++ cifs_remap(cifs_sb)); ++ name_len++; /* trailing null */ ++ name_len *= 2; ++ } else { ++ name_len = copy_path_name(pSMB->fileName, fileName); ++ } ++ /* Only few attributes can be set by this command, others are not accepted by Win9x. */ ++ pSMB->attr = cpu_to_le16(le32_to_cpu(attributes) & ++ (ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE)); ++ /* Zero write time value (in both NT and SETATTR formats) means to not change it. */ ++ if (le64_to_cpu(write_time) != 0) { ++ ts = cifs_NTtimeToUnix(write_time); ++ pSMB->last_write_time = cpu_to_le32(ts.tv_sec); ++ } ++ pSMB->BufferFormat = 0x04; ++ name_len++; /* account for buffer type byte */ ++ inc_rfc1001_len(pSMB, (__u16)name_len); ++ pSMB->ByteCount = cpu_to_le16(name_len); ++ ++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, ++ (struct smb_hdr *) pSMBr, &bytes_returned, 0); ++ if (rc) ++ cifs_dbg(FYI, "Send error in %s = %d\n", __func__, rc); ++ ++ cifs_buf_release(pSMB); ++ ++ if (rc == -EAGAIN) ++ goto retry; ++ ++ return rc; ++} ++ + /* Some legacy servers such as NT4 require that the file times be set on + an open handle, rather than by pathname - this is awkward due to + potential access conflicts on the open, but it is unavoidable for these +diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c +index 088fd84188b95..0385a514f59e9 100644 +--- a/fs/smb/client/smb1ops.c ++++ b/fs/smb/client/smb1ops.c +@@ -912,6 +912,9 @@ smb_set_file_info(struct inode *inode, const char *full_path, + struct cifs_fid fid; + struct cifs_open_parms oparms; + struct cifsFileInfo *open_file; ++ FILE_BASIC_INFO new_buf; ++ struct cifs_open_info_data query_data; ++ __le64 write_time = buf->LastWriteTime; + struct cifsInodeInfo *cinode = CIFS_I(inode); + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + struct tcon_link *tlink = NULL; +@@ -919,20 +922,58 @@ smb_set_file_info(struct inode *inode, const char *full_path, + + /* if the file is already open for write, just use that fileid */ + open_file = find_writable_file(cinode, FIND_WR_FSUID_ONLY); ++ + if (open_file) { + fid.netfid = open_file->fid.netfid; + netpid = open_file->pid; + tcon = tlink_tcon(open_file->tlink); +- goto set_via_filehandle; ++ } else { ++ tlink = cifs_sb_tlink(cifs_sb); ++ if (IS_ERR(tlink)) { ++ rc = PTR_ERR(tlink); ++ tlink = NULL; ++ goto out; ++ } ++ tcon = tlink_tcon(tlink); + } + +- tlink = cifs_sb_tlink(cifs_sb); +- if (IS_ERR(tlink)) { +- rc = PTR_ERR(tlink); +- tlink = NULL; +- goto out; ++ /* ++ * Non-NT servers interprets zero time value in SMB_SET_FILE_BASIC_INFO ++ * over TRANS2_SET_FILE_INFORMATION as a valid time value. NT servers ++ * interprets zero time value as do not change existing value on server. ++ * API of ->set_file_info() callback expects that zero time value has ++ * the NT meaning - do not change. Therefore if server is non-NT and ++ * some time values in "buf" are zero, then fetch missing time values. ++ */ ++ if (!(tcon->ses->capabilities & CAP_NT_SMBS) && ++ (!buf->CreationTime || !buf->LastAccessTime || ++ !buf->LastWriteTime || !buf->ChangeTime)) { ++ rc = cifs_query_path_info(xid, tcon, cifs_sb, full_path, &query_data); ++ if (rc) { ++ if (open_file) { ++ cifsFileInfo_put(open_file); ++ open_file = NULL; ++ } ++ goto out; ++ } ++ /* ++ * Original write_time from buf->LastWriteTime is preserved ++ * as SMBSetInformation() interprets zero as do not change. ++ */ ++ new_buf = *buf; ++ buf = &new_buf; ++ if (!buf->CreationTime) ++ buf->CreationTime = query_data.fi.CreationTime; ++ if (!buf->LastAccessTime) ++ buf->LastAccessTime = query_data.fi.LastAccessTime; ++ if (!buf->LastWriteTime) ++ buf->LastWriteTime = query_data.fi.LastWriteTime; ++ if (!buf->ChangeTime) ++ buf->ChangeTime = query_data.fi.ChangeTime; + } +- tcon = tlink_tcon(tlink); ++ ++ if (open_file) ++ goto set_via_filehandle; + + rc = CIFSSMBSetPathInfo(xid, tcon, full_path, buf, cifs_sb->local_nls, + cifs_sb); +@@ -953,8 +994,45 @@ smb_set_file_info(struct inode *inode, const char *full_path, + .fid = &fid, + }; + +- cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n"); +- rc = CIFS_open(xid, &oparms, &oplock, NULL); ++ if (S_ISDIR(inode->i_mode) && !(tcon->ses->capabilities & CAP_NT_SMBS)) { ++ /* Opening directory path is not possible on non-NT servers. */ ++ rc = -EOPNOTSUPP; ++ } else { ++ /* ++ * Use cifs_open_file() instead of CIFS_open() as the ++ * cifs_open_file() selects the correct function which ++ * works also on non-NT servers. ++ */ ++ rc = cifs_open_file(xid, &oparms, &oplock, NULL); ++ /* ++ * Opening path for writing on non-NT servers is not ++ * possible when the read-only attribute is already set. ++ * Non-NT server in this case returns -EACCES. For those ++ * servers the only possible way how to clear the read-only ++ * bit is via SMB_COM_SETATTR command. ++ */ ++ if (rc == -EACCES && ++ (cinode->cifsAttrs & ATTR_READONLY) && ++ le32_to_cpu(buf->Attributes) != 0 && /* 0 = do not change attrs */ ++ !(le32_to_cpu(buf->Attributes) & ATTR_READONLY) && ++ !(tcon->ses->capabilities & CAP_NT_SMBS)) ++ rc = -EOPNOTSUPP; ++ } ++ ++ /* Fallback to SMB_COM_SETATTR command when absolutelty needed. */ ++ if (rc == -EOPNOTSUPP) { ++ cifs_dbg(FYI, "calling SetInformation since SetPathInfo for attrs/times not supported by this server\n"); ++ rc = SMBSetInformation(xid, tcon, full_path, ++ buf->Attributes != 0 ? buf->Attributes : cpu_to_le32(cinode->cifsAttrs), ++ write_time, ++ cifs_sb->local_nls, cifs_sb); ++ if (rc == 0) ++ cinode->cifsAttrs = le32_to_cpu(buf->Attributes); ++ else ++ rc = -EACCES; ++ goto out; ++ } ++ + if (rc != 0) { + if (rc == -EIO) + rc = -EINVAL; +@@ -962,6 +1040,7 @@ smb_set_file_info(struct inode *inode, const char *full_path, + } + + netpid = current->tgid; ++ cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for attrs/times not supported by this server\n"); + + set_via_filehandle: + rc = CIFSSMBSetFileInfo(xid, tcon, buf, fid.netfid, netpid); +@@ -972,6 +1051,21 @@ smb_set_file_info(struct inode *inode, const char *full_path, + CIFSSMBClose(xid, tcon, fid.netfid); + else + cifsFileInfo_put(open_file); ++ ++ /* ++ * Setting the read-only bit is not honered on non-NT servers when done ++ * via open-semantics. So for setting it, use SMB_COM_SETATTR command. ++ * This command works only after the file is closed, so use it only when ++ * operation was called without the filehandle. ++ */ ++ if (open_file == NULL && ++ !(tcon->ses->capabilities & CAP_NT_SMBS) && ++ le32_to_cpu(buf->Attributes) & ATTR_READONLY) { ++ SMBSetInformation(xid, tcon, full_path, ++ buf->Attributes, ++ 0 /* do not change write time */, ++ cifs_sb->local_nls, cifs_sb); ++ } + out: + if (tlink != NULL) + cifs_put_tlink(tlink); +-- +2.39.5 + diff --git a/queue-6.12/cifs-fix-establishing-netbios-session-for-smb2-conne.patch b/queue-6.12/cifs-fix-establishing-netbios-session-for-smb2-conne.patch new file mode 100644 index 0000000000..afb97cc9e6 --- /dev/null +++ b/queue-6.12/cifs-fix-establishing-netbios-session-for-smb2-conne.patch @@ -0,0 +1,120 @@ +From eee4f7efec7521a621fe6881ba170ab06dc68dae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Oct 2024 22:46:20 +0100 +Subject: cifs: Fix establishing NetBIOS session for SMB2+ connection +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit 781802aa5a5950f99899f13ff9d760f5db81d36d ] + +Function ip_rfc1001_connect() which establish NetBIOS session for SMB +connections, currently uses smb_send() function for sending NetBIOS Session +Request packet. This function expects that the passed buffer is SMB packet +and for SMB2+ connections it mangles packet header, which breaks prepared +NetBIOS Session Request packet. Result is that this function send garbage +packet for SMB2+ connection, which SMB2+ server cannot parse. That function +is not mangling packets for SMB1 connections, so it somehow works for SMB1. + +Fix this problem and instead of smb_send(), use smb_send_kvec() function +which does not mangle prepared packet, this function send them as is. Just +API of this function takes struct msghdr (kvec) instead of packet buffer. + +[MS-SMB2] specification allows SMB2 protocol to use NetBIOS as a transport +protocol. NetBIOS can be used over TCP via port 139. So this is a valid +configuration, just not so common. And even recent Windows versions (e.g. +Windows Server 2022) still supports this configuration: SMB over TCP port +139, including for modern SMB2 and SMB3 dialects. + +This change fixes SMB2 and SMB3 connections over TCP port 139 which +requires establishing of NetBIOS session. Tested that this change fixes +establishing of SMB2 and SMB3 connections with Windows Server 2022. + +Signed-off-by: Pali Rohár +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/cifsproto.h | 3 +++ + fs/smb/client/connect.c | 20 +++++++++++++++----- + fs/smb/client/transport.c | 2 +- + 3 files changed, 19 insertions(+), 6 deletions(-) + +diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h +index 90b7b30abfbd8..306386e5c171f 100644 +--- a/fs/smb/client/cifsproto.h ++++ b/fs/smb/client/cifsproto.h +@@ -31,6 +31,9 @@ extern void cifs_small_buf_release(void *); + extern void free_rsp_buf(int, void *); + extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *, + unsigned int /* length */); ++extern int smb_send_kvec(struct TCP_Server_Info *server, ++ struct msghdr *msg, ++ size_t *sent); + extern unsigned int _get_xid(void); + extern void _free_xid(unsigned int); + #define get_xid() \ +diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c +index 3b4c2e59f1799..8260d0e07a628 100644 +--- a/fs/smb/client/connect.c ++++ b/fs/smb/client/connect.c +@@ -3063,8 +3063,10 @@ ip_rfc1001_connect(struct TCP_Server_Info *server) + * sessinit is sent but no second negprot + */ + struct rfc1002_session_packet req = {}; +- struct smb_hdr *smb_buf = (struct smb_hdr *)&req; ++ struct msghdr msg = {}; ++ struct kvec iov = {}; + unsigned int len; ++ size_t sent; + + req.trailer.session_req.called_len = sizeof(req.trailer.session_req.called_name); + +@@ -3093,10 +3095,18 @@ ip_rfc1001_connect(struct TCP_Server_Info *server) + * As per rfc1002, @len must be the number of bytes that follows the + * length field of a rfc1002 session request payload. + */ +- len = sizeof(req) - offsetof(struct rfc1002_session_packet, trailer.session_req); ++ len = sizeof(req.trailer.session_req); ++ req.type = RFC1002_SESSION_REQUEST; ++ req.flags = 0; ++ req.length = cpu_to_be16(len); ++ len += offsetof(typeof(req), trailer.session_req); ++ iov.iov_base = &req; ++ iov.iov_len = len; ++ iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, &iov, 1, len); ++ rc = smb_send_kvec(server, &msg, &sent); ++ if (rc < 0 || len != sent) ++ return (rc == -EINTR || rc == -EAGAIN) ? rc : -ECONNABORTED; + +- smb_buf->smb_buf_length = cpu_to_be32((RFC1002_SESSION_REQUEST << 24) | len); +- rc = smb_send(server, smb_buf, len); + /* + * RFC1001 layer in at least one server requires very short break before + * negprot presumably because not expecting negprot to follow so fast. +@@ -3105,7 +3115,7 @@ ip_rfc1001_connect(struct TCP_Server_Info *server) + */ + usleep_range(1000, 2000); + +- return rc; ++ return 0; + } + + static int +diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c +index 91812150186c0..9f13a705f7f67 100644 +--- a/fs/smb/client/transport.c ++++ b/fs/smb/client/transport.c +@@ -179,7 +179,7 @@ delete_mid(struct mid_q_entry *mid) + * Our basic "send data to server" function. Should be called with srv_mutex + * held. The caller is responsible for handling the results. + */ +-static int ++int + smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg, + size_t *sent) + { +-- +2.39.5 + diff --git a/queue-6.12/cifs-fix-negotiate-retry-functionality.patch b/queue-6.12/cifs-fix-negotiate-retry-functionality.patch new file mode 100644 index 0000000000..0d02e1ac1c --- /dev/null +++ b/queue-6.12/cifs-fix-negotiate-retry-functionality.patch @@ -0,0 +1,107 @@ +From 4e838f880244f9950a80e812b734fda99d50d0a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 2 Nov 2024 20:06:50 +0100 +Subject: cifs: Fix negotiate retry functionality +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit e94e882a6d69525c07589222cf3a6ff57ad12b5b ] + +SMB negotiate retry functionality in cifs_negotiate() is currently broken +and does not work when doing socket reconnect. Caller of this function, +which is cifs_negotiate_protocol() requires that tcpStatus after successful +execution of negotiate callback stay in CifsInNegotiate. But if the +CIFSSMBNegotiate() called from cifs_negotiate() fails due to connection +issues then tcpStatus is changed as so repeated CIFSSMBNegotiate() call +does not help. + +Fix this problem by moving retrying code from negotiate callback (which is +either cifs_negotiate() or smb2_negotiate()) to cifs_negotiate_protocol() +which is caller of those callbacks. This allows to properly handle and +implement correct transistions between tcpStatus states as function +cifs_negotiate_protocol() already handles it. + +With this change, cifs_negotiate_protocol() now handles also -EAGAIN error +set by the RFC1002_NEGATIVE_SESSION_RESPONSE processing after reconnecting +with NetBIOS session. + +Signed-off-by: Pali Rohár +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/connect.c | 10 ++++++++++ + fs/smb/client/smb1ops.c | 7 ------- + fs/smb/client/smb2ops.c | 3 --- + 3 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c +index 112057c7ca11c..3b4c2e59f1799 100644 +--- a/fs/smb/client/connect.c ++++ b/fs/smb/client/connect.c +@@ -3957,11 +3957,13 @@ int + cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses, + struct TCP_Server_Info *server) + { ++ bool in_retry = false; + int rc = 0; + + if (!server->ops->need_neg || !server->ops->negotiate) + return -ENOSYS; + ++retry: + /* only send once per connect */ + spin_lock(&server->srv_lock); + if (server->tcpStatus != CifsGood && +@@ -3981,6 +3983,14 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses, + spin_unlock(&server->srv_lock); + + rc = server->ops->negotiate(xid, ses, server); ++ if (rc == -EAGAIN) { ++ /* Allow one retry attempt */ ++ if (!in_retry) { ++ in_retry = true; ++ goto retry; ++ } ++ rc = -EHOSTDOWN; ++ } + if (rc == 0) { + spin_lock(&server->srv_lock); + if (server->tcpStatus == CifsInNegotiate) +diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c +index 55cceb8229323..a2dbebd13720b 100644 +--- a/fs/smb/client/smb1ops.c ++++ b/fs/smb/client/smb1ops.c +@@ -426,13 +426,6 @@ cifs_negotiate(const unsigned int xid, + { + int rc; + rc = CIFSSMBNegotiate(xid, ses, server); +- if (rc == -EAGAIN) { +- /* retry only once on 1st time connection */ +- set_credits(server, 1); +- rc = CIFSSMBNegotiate(xid, ses, server); +- if (rc == -EAGAIN) +- rc = -EHOSTDOWN; +- } + return rc; + } + +diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c +index 590b70d71694b..ff50cdfde5fe4 100644 +--- a/fs/smb/client/smb2ops.c ++++ b/fs/smb/client/smb2ops.c +@@ -464,9 +464,6 @@ smb2_negotiate(const unsigned int xid, + server->CurrentMid = 0; + spin_unlock(&server->mid_lock); + rc = SMB2_negotiate(xid, ses, server); +- /* BB we probably don't need to retry with modern servers */ +- if (rc == -EAGAIN) +- rc = -EHOSTDOWN; + return rc; + } + +-- +2.39.5 + diff --git a/queue-6.12/cifs-fix-querying-and-creating-mf-symlinks-over-smb1.patch b/queue-6.12/cifs-fix-querying-and-creating-mf-symlinks-over-smb1.patch new file mode 100644 index 0000000000..e893469630 --- /dev/null +++ b/queue-6.12/cifs-fix-querying-and-creating-mf-symlinks-over-smb1.patch @@ -0,0 +1,69 @@ +From 13951eafb0ad0347dae67980975303d378ffa916 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 28 Dec 2024 21:09:54 +0100 +Subject: cifs: Fix querying and creating MF symlinks over SMB1 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit 4236ac9fe5b8b42756070d4abfb76fed718e87c2 ] + +Old SMB1 servers without CAP_NT_SMBS do not support CIFS_open() function +and instead SMBLegacyOpen() needs to be used. This logic is already handled +in cifs_open_file() function, which is server->ops->open callback function. + +So for querying and creating MF symlinks use open callback function instead +of CIFS_open() function directly. + +This change fixes querying and creating new MF symlinks on Windows 98. +Currently cifs_query_mf_symlink() is not able to detect MF symlink and +cifs_create_mf_symlink() is failing with EIO error. + +Signed-off-by: Pali Rohár +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/link.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/fs/smb/client/link.c b/fs/smb/client/link.c +index 47ddeb7fa1116..aa45ef6ae99a6 100644 +--- a/fs/smb/client/link.c ++++ b/fs/smb/client/link.c +@@ -257,7 +257,7 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + struct cifs_open_parms oparms; + struct cifs_io_parms io_parms = {0}; + int buf_type = CIFS_NO_BUFFER; +- FILE_ALL_INFO file_info; ++ struct cifs_open_info_data query_data; + + oparms = (struct cifs_open_parms) { + .tcon = tcon, +@@ -269,11 +269,11 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + .fid = &fid, + }; + +- rc = CIFS_open(xid, &oparms, &oplock, &file_info); ++ rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &query_data); + if (rc) + return rc; + +- if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { ++ if (query_data.fi.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { + rc = -ENOENT; + /* it's not a symlink */ + goto out; +@@ -312,7 +312,7 @@ cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + .fid = &fid, + }; + +- rc = CIFS_open(xid, &oparms, &oplock, NULL); ++ rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL); + if (rc) + return rc; + +-- +2.39.5 + diff --git a/queue-6.12/cifs-set-default-netbios-rfc1001-server-name-to-host.patch b/queue-6.12/cifs-set-default-netbios-rfc1001-server-name-to-host.patch new file mode 100644 index 0000000000..54ee27d462 --- /dev/null +++ b/queue-6.12/cifs-set-default-netbios-rfc1001-server-name-to-host.patch @@ -0,0 +1,59 @@ +From 3dff2b7f775df9e1455ecedf9e157d5be467c0e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 27 Oct 2024 12:10:52 +0100 +Subject: cifs: Set default Netbios RFC1001 server name to hostname in UNC +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit be786e509c1af9b2dcf25c3d601f05c8c251f482 ] + +Windows SMB servers (including SMB2+) which are working over RFC1001 +require that Netbios server name specified in RFC1001 Session Request +packet is same as the UNC host name. Netbios server name can be already +specified manually via -o servern= option. + +With this change the RFC1001 server name is set automatically by extracting +the hostname from the mount source. + +Signed-off-by: Pali Rohár +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/fs_context.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c +index b015a4f997cb6..8b70d92f48458 100644 +--- a/fs/smb/client/fs_context.c ++++ b/fs/smb/client/fs_context.c +@@ -1058,6 +1058,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, + int i, opt; + bool is_smb3 = !strcmp(fc->fs_type->name, "smb3"); + bool skip_parsing = false; ++ char *hostname; + + cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key); + +@@ -1390,6 +1391,16 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, + cifs_errorf(fc, "OOM when copying UNC string\n"); + goto cifs_parse_mount_err; + } ++ hostname = extract_hostname(ctx->UNC); ++ if (IS_ERR(hostname)) { ++ cifs_errorf(fc, "Cannot extract hostname from UNC string\n"); ++ goto cifs_parse_mount_err; ++ } ++ /* last byte, type, is 0x20 for servr type */ ++ memset(ctx->target_rfc1001_name, 0x20, RFC1001_NAME_LEN_WITH_NULL); ++ for (i = 0; i < RFC1001_NAME_LEN && hostname[i] != 0; i++) ++ ctx->target_rfc1001_name[i] = toupper(hostname[i]); ++ kfree(hostname); + break; + case Opt_user: + kfree(ctx->username); +-- +2.39.5 + diff --git a/queue-6.12/clk-imx8mp-inform-ccf-of-maximum-frequency-of-clocks.patch b/queue-6.12/clk-imx8mp-inform-ccf-of-maximum-frequency-of-clocks.patch new file mode 100644 index 0000000000..db1718a4d2 --- /dev/null +++ b/queue-6.12/clk-imx8mp-inform-ccf-of-maximum-frequency-of-clocks.patch @@ -0,0 +1,214 @@ +From 460b4aa62f0bc3c05696cb82799426e53bdd6af2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 19:26:46 +0100 +Subject: clk: imx8mp: inform CCF of maximum frequency of clocks + +From: Ahmad Fatoum + +[ Upstream commit 06a61b5cb6a8638fa8823cd09b17233b29696fa2 ] + +The IMX8MPCEC datasheet lists maximum frequencies allowed for different +modules. Some of these limits are universal, but some depend on +whether the SoC is operating in nominal or in overdrive mode. + +The imx8mp.dtsi currently assumes overdrive mode and configures some +clocks in accordance with this. Boards wishing to make use of nominal +mode will need to override some of the clock rates manually. + +As operating the clocks outside of their allowed range can lead to +difficult to debug issues, it makes sense to register the maximum rates +allowed in the driver, so the CCF can take them into account. + +Reviewed-by: Peng Fan +Signed-off-by: Ahmad Fatoum +Link: https://lore.kernel.org/r/20250218-imx8m-clk-v4-6-b7697dc2dcd0@pengutronix.de +Signed-off-by: Abel Vesa +Signed-off-by: Sasha Levin +--- + drivers/clk/imx/clk-imx8mp.c | 151 +++++++++++++++++++++++++++++++++++ + 1 file changed, 151 insertions(+) + +diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c +index fb18f507f1213..fe6dac70f1a15 100644 +--- a/drivers/clk/imx/clk-imx8mp.c ++++ b/drivers/clk/imx/clk-imx8mp.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -406,11 +407,151 @@ static const char * const imx8mp_clkout_sels[] = {"audio_pll1_out", "audio_pll2_ + static struct clk_hw **hws; + static struct clk_hw_onecell_data *clk_hw_data; + ++struct imx8mp_clock_constraints { ++ unsigned int clkid; ++ u32 maxrate; ++}; ++ ++/* ++ * Below tables are taken from IMX8MPCEC Rev. 2.1, 07/2023 ++ * Table 13. Maximum frequency of modules. ++ * Probable typos fixed are marked with a comment. ++ */ ++static const struct imx8mp_clock_constraints imx8mp_clock_common_constraints[] = { ++ { IMX8MP_CLK_A53_DIV, 1000 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ENET_AXI, 266666667 }, /* Datasheet claims 266MHz */ ++ { IMX8MP_CLK_NAND_USDHC_BUS, 266666667 }, /* Datasheet claims 266MHz */ ++ { IMX8MP_CLK_MEDIA_APB, 200 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_HDMI_APB, 133333333 }, /* Datasheet claims 133MHz */ ++ { IMX8MP_CLK_ML_AXI, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_AHB, 133333333 }, ++ { IMX8MP_CLK_IPG_ROOT, 66666667 }, ++ { IMX8MP_CLK_AUDIO_AHB, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_DISP2_PIX, 170 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_DRAM_ALT, 666666667 }, ++ { IMX8MP_CLK_DRAM_APB, 200 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_CAN1, 80 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_CAN2, 80 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_PCIE_AUX, 10 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_I2C5, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_I2C6, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_SAI1, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_SAI2, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_SAI3, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_SAI5, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_SAI6, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_ENET_QOS, 125 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ENET_QOS_TIMER, 200 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ENET_REF, 125 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ENET_TIMER, 125 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ENET_PHY_REF, 125 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_NAND, 500 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_QSPI, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_USDHC1, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_USDHC2, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_I2C1, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_I2C2, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_I2C3, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_I2C4, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_UART1, 80 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_UART2, 80 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_UART3, 80 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_UART4, 80 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ECSPI1, 80 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ECSPI2, 80 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_PWM1, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_PWM2, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_PWM3, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_PWM4, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_GPT1, 100 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPT2, 100 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPT3, 100 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPT4, 100 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPT5, 100 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPT6, 100 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_WDOG, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_IPP_DO_CLKO1, 200 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_IPP_DO_CLKO2, 200 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_HDMI_REF_266M, 266 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_USDHC3, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_MIPI_PHY1_REF, 300 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_DISP1_PIX, 250 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_CAM2_PIX, 277 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_LDB, 595 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_MIPI_TEST_BYTE, 200 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ECSPI3, 80 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_PDM, 200 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_SAI7, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_MAIN_AXI, 400 * HZ_PER_MHZ }, ++ { /* Sentinel */ } ++}; ++ ++static const struct imx8mp_clock_constraints imx8mp_clock_nominal_constraints[] = { ++ { IMX8MP_CLK_M7_CORE, 600 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ML_CORE, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU3D_CORE, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU3D_SHADER_CORE, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU2D_CORE, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_AUDIO_AXI_SRC, 600 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_HSIO_AXI, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_ISP, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_VPU_BUS, 600 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_AXI, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_HDMI_AXI, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU_AXI, 600 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU_AHB, 300 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_NOC, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_NOC_IO, 600 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ML_AHB, 300 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_VPU_G1, 600 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_VPU_G2, 500 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_CAM1_PIX, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_VPU_VC8000E, 400 * HZ_PER_MHZ }, /* Datasheet claims 500MHz */ ++ { IMX8MP_CLK_DRAM_CORE, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GIC, 400 * HZ_PER_MHZ }, ++ { /* Sentinel */ } ++}; ++ ++static const struct imx8mp_clock_constraints imx8mp_clock_overdrive_constraints[] = { ++ { IMX8MP_CLK_M7_CORE, 800 * HZ_PER_MHZ}, ++ { IMX8MP_CLK_ML_CORE, 1000 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU3D_CORE, 1000 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU3D_SHADER_CORE, 1000 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU2D_CORE, 1000 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_AUDIO_AXI_SRC, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_HSIO_AXI, 500 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_ISP, 500 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_VPU_BUS, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_AXI, 500 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_HDMI_AXI, 500 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU_AXI, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU_AHB, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_NOC, 1000 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_NOC_IO, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ML_AHB, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_VPU_G1, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_VPU_G2, 700 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_CAM1_PIX, 500 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_VPU_VC8000E, 500 * HZ_PER_MHZ }, /* Datasheet claims 400MHz */ ++ { IMX8MP_CLK_DRAM_CORE, 1000 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GIC, 500 * HZ_PER_MHZ }, ++ { /* Sentinel */ } ++}; ++ ++static void imx8mp_clocks_apply_constraints(const struct imx8mp_clock_constraints constraints[]) ++{ ++ const struct imx8mp_clock_constraints *constr; ++ ++ for (constr = constraints; constr->clkid; constr++) ++ clk_hw_set_rate_range(hws[constr->clkid], 0, constr->maxrate); ++} ++ + static int imx8mp_clocks_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; + struct device_node *np; + void __iomem *anatop_base, *ccm_base; ++ const char *opmode; + int err; + + np = of_find_compatible_node(NULL, NULL, "fsl,imx8mp-anatop"); +@@ -715,6 +856,16 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) + + imx_check_clk_hws(hws, IMX8MP_CLK_END); + ++ imx8mp_clocks_apply_constraints(imx8mp_clock_common_constraints); ++ ++ err = of_property_read_string(np, "fsl,operating-mode", &opmode); ++ if (!err) { ++ if (!strcmp(opmode, "nominal")) ++ imx8mp_clocks_apply_constraints(imx8mp_clock_nominal_constraints); ++ else if (!strcmp(opmode, "overdrive")) ++ imx8mp_clocks_apply_constraints(imx8mp_clock_overdrive_constraints); ++ } ++ + err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data); + if (err < 0) { + dev_err(dev, "failed to register hws for i.MX8MP\n"); +-- +2.39.5 + diff --git a/queue-6.12/clk-qcom-camcc-sm8250-use-clk_rcg2_shared_ops-for-so.patch b/queue-6.12/clk-qcom-camcc-sm8250-use-clk_rcg2_shared_ops-for-so.patch new file mode 100644 index 0000000000..28f28b8b0b --- /dev/null +++ b/queue-6.12/clk-qcom-camcc-sm8250-use-clk_rcg2_shared_ops-for-so.patch @@ -0,0 +1,285 @@ +From ab401264679aeb93d2e204610fc09d3562810f92 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 22:26:12 +0000 +Subject: clk: qcom: camcc-sm8250: Use clk_rcg2_shared_ops for some RCGs + +From: Jordan Crouse + +[ Upstream commit 52b10b591f83dc6d9a1d6c2dc89433470a787ecd ] + +Update some RCGs on the sm8250 camera clock controller to use +clk_rcg2_shared_ops. The shared_ops ensure the RCGs get parked +to the XO during clock disable to prevent the clocks from locking up +when the GDSC is enabled. These mirror similar fixes for other controllers +such as commit e5c359f70e4b ("clk: qcom: camcc: Update the clock ops for +the SC7180"). + +Signed-off-by: Jordan Crouse +Reviewed-by: Dmitry Baryshkov +Reviewed-by: Bryan O'Donoghue +Link: https://lore.kernel.org/r/20250122222612.32351-1-jorcrous@amazon.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/camcc-sm8250.c | 56 ++++++++++++++++----------------- + 1 file changed, 28 insertions(+), 28 deletions(-) + +diff --git a/drivers/clk/qcom/camcc-sm8250.c b/drivers/clk/qcom/camcc-sm8250.c +index 34d2f17520dcc..450ddbebd35f2 100644 +--- a/drivers/clk/qcom/camcc-sm8250.c ++++ b/drivers/clk/qcom/camcc-sm8250.c +@@ -411,7 +411,7 @@ static struct clk_rcg2 cam_cc_bps_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -433,7 +433,7 @@ static struct clk_rcg2 cam_cc_camnoc_axi_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -454,7 +454,7 @@ static struct clk_rcg2 cam_cc_cci_0_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -469,7 +469,7 @@ static struct clk_rcg2 cam_cc_cci_1_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -490,7 +490,7 @@ static struct clk_rcg2 cam_cc_cphy_rx_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -511,7 +511,7 @@ static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -526,7 +526,7 @@ static struct clk_rcg2 cam_cc_csi1phytimer_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -556,7 +556,7 @@ static struct clk_rcg2 cam_cc_csi3phytimer_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -571,7 +571,7 @@ static struct clk_rcg2 cam_cc_csi4phytimer_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -586,7 +586,7 @@ static struct clk_rcg2 cam_cc_csi5phytimer_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -611,7 +611,7 @@ static struct clk_rcg2 cam_cc_fast_ahb_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -634,7 +634,7 @@ static struct clk_rcg2 cam_cc_fd_core_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -649,7 +649,7 @@ static struct clk_rcg2 cam_cc_icp_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -673,7 +673,7 @@ static struct clk_rcg2 cam_cc_ife_0_clk_src = { + .parent_data = cam_cc_parent_data_2, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -710,7 +710,7 @@ static struct clk_rcg2 cam_cc_ife_0_csid_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -734,7 +734,7 @@ static struct clk_rcg2 cam_cc_ife_1_clk_src = { + .parent_data = cam_cc_parent_data_3, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -749,7 +749,7 @@ static struct clk_rcg2 cam_cc_ife_1_csid_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -771,7 +771,7 @@ static struct clk_rcg2 cam_cc_ife_lite_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -786,7 +786,7 @@ static struct clk_rcg2 cam_cc_ife_lite_csid_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -810,7 +810,7 @@ static struct clk_rcg2 cam_cc_ipe_0_clk_src = { + .parent_data = cam_cc_parent_data_4, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_4), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -825,7 +825,7 @@ static struct clk_rcg2 cam_cc_jpeg_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -847,7 +847,7 @@ static struct clk_rcg2 cam_cc_mclk0_clk_src = { + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -862,7 +862,7 @@ static struct clk_rcg2 cam_cc_mclk1_clk_src = { + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -877,7 +877,7 @@ static struct clk_rcg2 cam_cc_mclk2_clk_src = { + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -892,7 +892,7 @@ static struct clk_rcg2 cam_cc_mclk3_clk_src = { + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -907,7 +907,7 @@ static struct clk_rcg2 cam_cc_mclk4_clk_src = { + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -922,7 +922,7 @@ static struct clk_rcg2 cam_cc_mclk5_clk_src = { + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -993,7 +993,7 @@ static struct clk_rcg2 cam_cc_slow_ahb_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +-- +2.39.5 + diff --git a/queue-6.12/clk-qcom-clk-alpha-pll-do-not-use-random-stack-value.patch b/queue-6.12/clk-qcom-clk-alpha-pll-do-not-use-random-stack-value.patch new file mode 100644 index 0000000000..951633a418 --- /dev/null +++ b/queue-6.12/clk-qcom-clk-alpha-pll-do-not-use-random-stack-value.patch @@ -0,0 +1,143 @@ +From 63911ae224540d45a35cbd4cb970ca5c9fbfc05d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 21:01:35 +0100 +Subject: clk: qcom: clk-alpha-pll: Do not use random stack value for recalc + rate + +From: Krzysztof Kozlowski + +[ Upstream commit 7a243e1b814a02ab40793026ef64223155d86395 ] + +If regmap_read() fails, random stack value was used in calculating new +frequency in recalc_rate() callbacks. Such failure is really not +expected as these are all MMIO reads, however code should be here +correct and bail out. This also avoids possible warning on +uninitialized value. + +Signed-off-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20250212-b4-clk-qcom-clean-v3-1-499f37444f5d@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/clk-alpha-pll.c | 52 ++++++++++++++++++++++---------- + 1 file changed, 36 insertions(+), 16 deletions(-) + +diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c +index 10e276dabff93..e76ecc4663511 100644 +--- a/drivers/clk/qcom/clk-alpha-pll.c ++++ b/drivers/clk/qcom/clk-alpha-pll.c +@@ -670,14 +670,19 @@ clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + u32 alpha_width = pll_alpha_width(pll); + +- regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); ++ if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l)) ++ return 0; ++ ++ if (regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl)) ++ return 0; + +- regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl); + if (ctl & PLL_ALPHA_EN) { +- regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &low); ++ if (regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &low)) ++ return 0; + if (alpha_width > 32) { +- regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), +- &high); ++ if (regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), ++ &high)) ++ return 0; + a = (u64)high << 32 | low; + } else { + a = low & GENMASK(alpha_width - 1, 0); +@@ -903,8 +908,11 @@ alpha_pll_huayra_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + u32 l, alpha = 0, ctl, alpha_m, alpha_n; + +- regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); +- regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl); ++ if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l)) ++ return 0; ++ ++ if (regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl)) ++ return 0; + + if (ctl & PLL_ALPHA_EN) { + regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &alpha); +@@ -1098,8 +1106,11 @@ clk_trion_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + u32 l, frac, alpha_width = pll_alpha_width(pll); + +- regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); +- regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &frac); ++ if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l)) ++ return 0; ++ ++ if (regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &frac)) ++ return 0; + + return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width); + } +@@ -1157,7 +1168,8 @@ clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); + u32 ctl; + +- regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl); ++ if (regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl)) ++ return 0; + + ctl >>= PLL_POST_DIV_SHIFT; + ctl &= PLL_POST_DIV_MASK(pll); +@@ -1373,8 +1385,11 @@ static unsigned long alpha_pll_fabia_recalc_rate(struct clk_hw *hw, + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + u32 l, frac, alpha_width = pll_alpha_width(pll); + +- regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); +- regmap_read(pll->clkr.regmap, PLL_FRAC(pll), &frac); ++ if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l)) ++ return 0; ++ ++ if (regmap_read(pll->clkr.regmap, PLL_FRAC(pll), &frac)) ++ return 0; + + return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width); + } +@@ -1524,7 +1539,8 @@ clk_trion_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) + struct regmap *regmap = pll->clkr.regmap; + u32 i, div = 1, val; + +- regmap_read(regmap, PLL_USER_CTL(pll), &val); ++ if (regmap_read(regmap, PLL_USER_CTL(pll), &val)) ++ return 0; + + val >>= pll->post_div_shift; + val &= PLL_POST_DIV_MASK(pll); +@@ -2451,9 +2467,12 @@ static unsigned long alpha_pll_lucid_evo_recalc_rate(struct clk_hw *hw, + struct regmap *regmap = pll->clkr.regmap; + u32 l, frac; + +- regmap_read(regmap, PLL_L_VAL(pll), &l); ++ if (regmap_read(regmap, PLL_L_VAL(pll), &l)) ++ return 0; + l &= LUCID_EVO_PLL_L_VAL_MASK; +- regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac); ++ ++ if (regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac)) ++ return 0; + + return alpha_pll_calc_rate(parent_rate, l, frac, pll_alpha_width(pll)); + } +@@ -2528,7 +2547,8 @@ static unsigned long clk_rivian_evo_pll_recalc_rate(struct clk_hw *hw, + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + u32 l; + +- regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); ++ if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l)) ++ return 0; + + return parent_rate * l; + } +-- +2.39.5 + diff --git a/queue-6.12/clk-qcom-ipq5018-allow-it-to-be-bulid-on-arm32.patch b/queue-6.12/clk-qcom-ipq5018-allow-it-to-be-bulid-on-arm32.patch new file mode 100644 index 0000000000..1e169f3b66 --- /dev/null +++ b/queue-6.12/clk-qcom-ipq5018-allow-it-to-be-bulid-on-arm32.patch @@ -0,0 +1,40 @@ +From 68af772ab3b3da91fd6e00deade6f7fa9959e6ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Oct 2024 00:34:12 +0800 +Subject: clk: qcom: ipq5018: allow it to be bulid on arm32 + +From: Karl Chan + +[ Upstream commit 5d02941c83997b58e8fc15390290c7c6975acaff ] + +There are some ipq5018 based device's firmware only can able to boot +arm32 but the clock driver dont allow it to be compiled on arm32. +Therefore allow GCC for IPQ5018 to be selected when building ARM32 +kernel + +Signed-off-by: Karl Chan +Reviewed-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20241007163414.32458-4-exxxxkc@getgoogleoff.me +[bjorn: Updated commit message, per Dmitry's suggestion] +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig +index 16145f74bbc85..fd605bccf48dc 100644 +--- a/drivers/clk/qcom/Kconfig ++++ b/drivers/clk/qcom/Kconfig +@@ -199,7 +199,7 @@ config IPQ_GCC_4019 + + config IPQ_GCC_5018 + tristate "IPQ5018 Global Clock Controller" +- depends on ARM64 || COMPILE_TEST ++ depends on ARM || ARM64 || COMPILE_TEST + help + Support for global clock controller on ipq5018 devices. + Say Y if you want to use peripheral devices such as UART, SPI, +-- +2.39.5 + diff --git a/queue-6.12/clk-qcom-lpassaudiocc-sc7280-add-support-for-lpass-r.patch b/queue-6.12/clk-qcom-lpassaudiocc-sc7280-add-support-for-lpass-r.patch new file mode 100644 index 0000000000..f79d875500 --- /dev/null +++ b/queue-6.12/clk-qcom-lpassaudiocc-sc7280-add-support-for-lpass-r.patch @@ -0,0 +1,95 @@ +From 185ea39663e9ff1dbde38840167fb9609c99656e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 15:04:55 +0530 +Subject: clk: qcom: lpassaudiocc-sc7280: Add support for LPASS resets for + QCM6490 + +From: Taniya Das + +[ Upstream commit cdbbc480f4146cb659af97f4020601fde5fb65a7 ] + +On the QCM6490 boards, the LPASS firmware controls the complete clock +controller functionalities and associated power domains. However, only +the LPASS resets required to be controlled by the high level OS. Thus, +add support for the resets in the clock driver to enable the Audio SW +driver to assert/deassert the audio resets as needed. + +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Taniya Das +Link: https://lore.kernel.org/r/20250221-lpass_qcm6490_resets-v5-2-6be0c0949a83@quicinc.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/lpassaudiocc-sc7280.c | 23 +++++++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +diff --git a/drivers/clk/qcom/lpassaudiocc-sc7280.c b/drivers/clk/qcom/lpassaudiocc-sc7280.c +index 45e7264770866..22169da08a51a 100644 +--- a/drivers/clk/qcom/lpassaudiocc-sc7280.c ++++ b/drivers/clk/qcom/lpassaudiocc-sc7280.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +@@ -713,14 +714,24 @@ static const struct qcom_reset_map lpass_audio_cc_sc7280_resets[] = { + [LPASS_AUDIO_SWR_WSA_CGCR] = { 0xb0, 1 }, + }; + ++static const struct regmap_config lpass_audio_cc_sc7280_reset_regmap_config = { ++ .name = "lpassaudio_cc_reset", ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .fast_io = true, ++ .max_register = 0xc8, ++}; ++ + static const struct qcom_cc_desc lpass_audio_cc_reset_sc7280_desc = { +- .config = &lpass_audio_cc_sc7280_regmap_config, ++ .config = &lpass_audio_cc_sc7280_reset_regmap_config, + .resets = lpass_audio_cc_sc7280_resets, + .num_resets = ARRAY_SIZE(lpass_audio_cc_sc7280_resets), + }; + + static const struct of_device_id lpass_audio_cc_sc7280_match_table[] = { +- { .compatible = "qcom,sc7280-lpassaudiocc" }, ++ { .compatible = "qcom,qcm6490-lpassaudiocc", .data = &lpass_audio_cc_reset_sc7280_desc }, ++ { .compatible = "qcom,sc7280-lpassaudiocc", .data = &lpass_audio_cc_sc7280_desc }, + { } + }; + MODULE_DEVICE_TABLE(of, lpass_audio_cc_sc7280_match_table); +@@ -752,13 +763,17 @@ static int lpass_audio_cc_sc7280_probe(struct platform_device *pdev) + struct regmap *regmap; + int ret; + ++ desc = device_get_match_data(&pdev->dev); ++ ++ if (of_device_is_compatible(pdev->dev.of_node, "qcom,qcm6490-lpassaudiocc")) ++ return qcom_cc_probe_by_index(pdev, 1, desc); ++ + ret = lpass_audio_setup_runtime_pm(pdev); + if (ret) + return ret; + + lpass_audio_cc_sc7280_regmap_config.name = "lpassaudio_cc"; + lpass_audio_cc_sc7280_regmap_config.max_register = 0x2f000; +- desc = &lpass_audio_cc_sc7280_desc; + + regmap = qcom_cc_map(pdev, desc); + if (IS_ERR(regmap)) { +@@ -772,7 +787,7 @@ static int lpass_audio_cc_sc7280_probe(struct platform_device *pdev) + regmap_write(regmap, 0x4, 0x3b); + regmap_write(regmap, 0x8, 0xff05); + +- ret = qcom_cc_really_probe(&pdev->dev, &lpass_audio_cc_sc7280_desc, regmap); ++ ret = qcom_cc_really_probe(&pdev->dev, desc, regmap); + if (ret) { + dev_err(&pdev->dev, "Failed to register LPASS AUDIO CC clocks\n"); + goto exit; +-- +2.39.5 + diff --git a/queue-6.12/clk-renesas-rzg2l-cpg-refactor-runtime-pm-clock-vali.patch b/queue-6.12/clk-renesas-rzg2l-cpg-refactor-runtime-pm-clock-vali.patch new file mode 100644 index 0000000000..7c3e19d7a8 --- /dev/null +++ b/queue-6.12/clk-renesas-rzg2l-cpg-refactor-runtime-pm-clock-vali.patch @@ -0,0 +1,165 @@ +From 599677263c4691a9779e12dcf80ba3537d09db04 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Dec 2024 21:02:01 +0000 +Subject: clk: renesas: rzg2l-cpg: Refactor Runtime PM clock validation + +From: Lad Prabhakar + +[ Upstream commit f6f73b891bf6beff069fcacc7b4a796e1009bf26 ] + +Refactor rzg2l_cpg_attach_dev to delegate clock validation for Runtime PM +to the updated rzg2l_cpg_is_pm_clk function. Ensure validation of clocks +associated with the power domain while excluding external and core clocks. +Prevent incorrect Runtime PM management for clocks outside the domain's +scope. + +Update rzg2l_cpg_is_pm_clk to operate on a per-power-domain basis. Verify +clkspec.np against the domain's device node, check argument validity, and +validate clock type (CPG_MOD). Use the no_pm_mod_clks array to exclude +specific clocks from PM management. + +Signed-off-by: Lad Prabhakar +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/20241216210201.239855-1-prabhakar.mahadev-lad.rj@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + drivers/clk/renesas/rzg2l-cpg.c | 102 +++++++++++++++++--------------- + 1 file changed, 54 insertions(+), 48 deletions(-) + +diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c +index 229f4540b219e..97d42328fa81a 100644 +--- a/drivers/clk/renesas/rzg2l-cpg.c ++++ b/drivers/clk/renesas/rzg2l-cpg.c +@@ -1549,28 +1549,6 @@ static int rzg2l_cpg_reset_controller_register(struct rzg2l_cpg_priv *priv) + return devm_reset_controller_register(priv->dev, &priv->rcdev); + } + +-static bool rzg2l_cpg_is_pm_clk(struct rzg2l_cpg_priv *priv, +- const struct of_phandle_args *clkspec) +-{ +- const struct rzg2l_cpg_info *info = priv->info; +- unsigned int id; +- unsigned int i; +- +- if (clkspec->args_count != 2) +- return false; +- +- if (clkspec->args[0] != CPG_MOD) +- return false; +- +- id = clkspec->args[1] + info->num_total_core_clks; +- for (i = 0; i < info->num_no_pm_mod_clks; i++) { +- if (info->no_pm_mod_clks[i] == id) +- return false; +- } +- +- return true; +-} +- + /** + * struct rzg2l_cpg_pm_domains - RZ/G2L PM domains data structure + * @onecell_data: cell data +@@ -1595,45 +1573,73 @@ struct rzg2l_cpg_pd { + u16 id; + }; + ++static bool rzg2l_cpg_is_pm_clk(struct rzg2l_cpg_pd *pd, ++ const struct of_phandle_args *clkspec) ++{ ++ if (clkspec->np != pd->genpd.dev.of_node || clkspec->args_count != 2) ++ return false; ++ ++ switch (clkspec->args[0]) { ++ case CPG_MOD: { ++ struct rzg2l_cpg_priv *priv = pd->priv; ++ const struct rzg2l_cpg_info *info = priv->info; ++ unsigned int id = clkspec->args[1]; ++ ++ if (id >= priv->num_mod_clks) ++ return false; ++ ++ id += info->num_total_core_clks; ++ ++ for (unsigned int i = 0; i < info->num_no_pm_mod_clks; i++) { ++ if (info->no_pm_mod_clks[i] == id) ++ return false; ++ } ++ ++ return true; ++ } ++ ++ case CPG_CORE: ++ default: ++ return false; ++ } ++} ++ + static int rzg2l_cpg_attach_dev(struct generic_pm_domain *domain, struct device *dev) + { + struct rzg2l_cpg_pd *pd = container_of(domain, struct rzg2l_cpg_pd, genpd); +- struct rzg2l_cpg_priv *priv = pd->priv; + struct device_node *np = dev->of_node; + struct of_phandle_args clkspec; + bool once = true; + struct clk *clk; ++ unsigned int i; + int error; +- int i = 0; +- +- while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, +- &clkspec)) { +- if (rzg2l_cpg_is_pm_clk(priv, &clkspec)) { +- if (once) { +- once = false; +- error = pm_clk_create(dev); +- if (error) { +- of_node_put(clkspec.np); +- goto err; +- } +- } +- clk = of_clk_get_from_provider(&clkspec); ++ ++ for (i = 0; !of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, &clkspec); i++) { ++ if (!rzg2l_cpg_is_pm_clk(pd, &clkspec)) { + of_node_put(clkspec.np); +- if (IS_ERR(clk)) { +- error = PTR_ERR(clk); +- goto fail_destroy; +- } ++ continue; ++ } + +- error = pm_clk_add_clk(dev, clk); ++ if (once) { ++ once = false; ++ error = pm_clk_create(dev); + if (error) { +- dev_err(dev, "pm_clk_add_clk failed %d\n", +- error); +- goto fail_put; ++ of_node_put(clkspec.np); ++ goto err; + } +- } else { +- of_node_put(clkspec.np); + } +- i++; ++ clk = of_clk_get_from_provider(&clkspec); ++ of_node_put(clkspec.np); ++ if (IS_ERR(clk)) { ++ error = PTR_ERR(clk); ++ goto fail_destroy; ++ } ++ ++ error = pm_clk_add_clk(dev, clk); ++ if (error) { ++ dev_err(dev, "pm_clk_add_clk failed %d\n", error); ++ goto fail_put; ++ } + } + + return 0; +-- +2.39.5 + diff --git a/queue-6.12/clocksource-drivers-timer-riscv-stop-stimecmp-when-c.patch b/queue-6.12/clocksource-drivers-timer-riscv-stop-stimecmp-when-c.patch new file mode 100644 index 0000000000..105e848400 --- /dev/null +++ b/queue-6.12/clocksource-drivers-timer-riscv-stop-stimecmp-when-c.patch @@ -0,0 +1,45 @@ +From 08b7457832b7c2f04a30d5b6b2e8b9f1c34e4833 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 19:41:35 +0800 +Subject: clocksource/drivers/timer-riscv: Stop stimecmp when cpu hotplug + +From: Nick Hu + +[ Upstream commit 70c93b026ed07078e933583591aa9ca6701cd9da ] + +Stop the timer when the cpu is going to be offline otherwise the +timer interrupt may be pending while performing power-down. + +Suggested-by: Anup Patel +Link: https://lore.kernel.org/lkml/20240829033904.477200-3-nick.hu@sifive.com/T/#u +Signed-off-by: Nick Hu +Reviewed-by: Anup Patel +Acked-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20250219114135.27764-3-nick.hu@sifive.com +Signed-off-by: Alexandre Ghiti +Signed-off-by: Sasha Levin +--- + drivers/clocksource/timer-riscv.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c +index 48ce50c5f5e68..4d7cf338824a3 100644 +--- a/drivers/clocksource/timer-riscv.c ++++ b/drivers/clocksource/timer-riscv.c +@@ -126,7 +126,13 @@ static int riscv_timer_starting_cpu(unsigned int cpu) + + static int riscv_timer_dying_cpu(unsigned int cpu) + { ++ /* ++ * Stop the timer when the cpu is going to be offline otherwise ++ * the timer interrupt may be pending while performing power-down. ++ */ ++ riscv_clock_event_stop(); + disable_percpu_irq(riscv_clock_event_irq); ++ + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.12/clocksource-mips-gic-timer-enable-counter-when-cpus-.patch b/queue-6.12/clocksource-mips-gic-timer-enable-counter-when-cpus-.patch new file mode 100644 index 0000000000..29bfc8f150 --- /dev/null +++ b/queue-6.12/clocksource-mips-gic-timer-enable-counter-when-cpus-.patch @@ -0,0 +1,68 @@ +From 3e810787a32f05b346f19fa872661c028e0efd47 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 13:32:47 +0100 +Subject: clocksource: mips-gic-timer: Enable counter when CPUs start +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Paul Burton + +[ Upstream commit 3128b0a2e0cf6e07aa78e5f8cf7dd9cd59dc8174 ] + +In multi-cluster MIPS I6500 systems there is a GIC in each cluster, +each with its own counter. When a cluster powers up the counter will +be stopped, with the COUNTSTOP bit set in the GIC_CONFIG register. + +In single cluster systems, it has been fine to clear COUNTSTOP once +in gic_clocksource_of_init() to start the counter. In multi-cluster +systems, this will only have started the counter in the boot cluster, +and any CPUs in other clusters will find their counter stopped which +will break the GIC clock_event_device. + +Resolve this by having CPUs clear the COUNTSTOP bit when they come +online, using the existing gic_starting_cpu() CPU hotplug callback. This +will allow CPUs in secondary clusters to ensure that the cluster's GIC +counter is running as expected. + +Signed-off-by: Paul Burton +Signed-off-by: Chao-ying Fu +Signed-off-by: Dragan Mladjenovic +Signed-off-by: Aleksandar Rikalo +Reviewed-by: Philippe Mathieu-Daudé +Tested-by: Serge Semin +Tested-by: Gregory CLEMENT +Acked-by: Daniel Lezcano +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + drivers/clocksource/mips-gic-timer.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c +index 110347707ff98..8592910710d17 100644 +--- a/drivers/clocksource/mips-gic-timer.c ++++ b/drivers/clocksource/mips-gic-timer.c +@@ -115,6 +115,9 @@ static void gic_update_frequency(void *data) + + static int gic_starting_cpu(unsigned int cpu) + { ++ /* Ensure the GIC counter is running */ ++ clear_gic_config(GIC_CONFIG_COUNTSTOP); ++ + gic_clockevent_cpu_init(cpu, this_cpu_ptr(&gic_clockevent_device)); + return 0; + } +@@ -252,9 +255,6 @@ static int __init gic_clocksource_of_init(struct device_node *node) + pr_warn("Unable to register clock notifier\n"); + } + +- /* And finally start the counter */ +- clear_gic_config(GIC_CONFIG_COUNTSTOP); +- + /* + * It's safe to use the MIPS GIC timer as a sched clock source only if + * its ticks are stable, which is true on either the platforms with +-- +2.39.5 + diff --git a/queue-6.12/coresight-etb10-change-etb_drvdata-spinlock-s-type-t.patch b/queue-6.12/coresight-etb10-change-etb_drvdata-spinlock-s-type-t.patch new file mode 100644 index 0000000000..97469746c9 --- /dev/null +++ b/queue-6.12/coresight-etb10-change-etb_drvdata-spinlock-s-type-t.patch @@ -0,0 +1,149 @@ +From b8731d9a99796cc6b1e961781908173c6dda3956 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 12:11:06 +0000 +Subject: coresight-etb10: change etb_drvdata spinlock's type to raw_spinlock_t + +From: Yeoreum Yun + +[ Upstream commit 6b80c0abe475ed1017c5e862636049aa1cc17a1a ] + +In coresight-etb10 drivers, etb_drvdata->spinlock can be held +during __schedule() by perf_event_task_sched_out()/in(). + +Since etb_drvdata->spinlock type is spinlock_t and +perf_event_task_sched_out()/in() is called after acquiring rq_lock, +which is raw_spinlock_t (an unsleepable lock), +this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable. + +To address this, change type etb_drvdata->spinlock in coresight-etb10 drivers, +which can be called by perf_event_task_sched_out()/in(), +from spinlock_t to raw_spinlock_t. + +Reviewed-by: James Clark +Reviewed-by: Mike Leach +Signed-off-by: Yeoreum Yun +Signed-off-by: Suzuki K Poulose +Link: https://lore.kernel.org/r/20250306121110.1647948-6-yeoreum.yun@arm.com +Signed-off-by: Sasha Levin +--- + drivers/hwtracing/coresight/coresight-etb10.c | 26 +++++++++---------- + 1 file changed, 13 insertions(+), 13 deletions(-) + +diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c +index aea9ac9c4bd06..7948597d483d2 100644 +--- a/drivers/hwtracing/coresight/coresight-etb10.c ++++ b/drivers/hwtracing/coresight/coresight-etb10.c +@@ -84,7 +84,7 @@ struct etb_drvdata { + struct clk *atclk; + struct coresight_device *csdev; + struct miscdevice miscdev; +- spinlock_t spinlock; ++ raw_spinlock_t spinlock; + local_t reading; + pid_t pid; + u8 *buf; +@@ -145,7 +145,7 @@ static int etb_enable_sysfs(struct coresight_device *csdev) + unsigned long flags; + struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + +- spin_lock_irqsave(&drvdata->spinlock, flags); ++ raw_spin_lock_irqsave(&drvdata->spinlock, flags); + + /* Don't messup with perf sessions. */ + if (coresight_get_mode(csdev) == CS_MODE_PERF) { +@@ -163,7 +163,7 @@ static int etb_enable_sysfs(struct coresight_device *csdev) + + csdev->refcnt++; + out: +- spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + return ret; + } + +@@ -176,7 +176,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data) + struct perf_output_handle *handle = data; + struct cs_buffers *buf = etm_perf_sink_config(handle); + +- spin_lock_irqsave(&drvdata->spinlock, flags); ++ raw_spin_lock_irqsave(&drvdata->spinlock, flags); + + /* No need to continue if the component is already in used by sysFS. */ + if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) { +@@ -219,7 +219,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data) + } + + out: +- spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + return ret; + } + +@@ -352,11 +352,11 @@ static int etb_disable(struct coresight_device *csdev) + struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + unsigned long flags; + +- spin_lock_irqsave(&drvdata->spinlock, flags); ++ raw_spin_lock_irqsave(&drvdata->spinlock, flags); + + csdev->refcnt--; + if (csdev->refcnt) { +- spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + return -EBUSY; + } + +@@ -366,7 +366,7 @@ static int etb_disable(struct coresight_device *csdev) + /* Dissociate from monitored process. */ + drvdata->pid = -1; + coresight_set_mode(csdev, CS_MODE_DISABLED); +- spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + + dev_dbg(&csdev->dev, "ETB disabled\n"); + return 0; +@@ -443,7 +443,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, + + capacity = drvdata->buffer_depth * ETB_FRAME_SIZE_WORDS; + +- spin_lock_irqsave(&drvdata->spinlock, flags); ++ raw_spin_lock_irqsave(&drvdata->spinlock, flags); + + /* Don't do anything if another tracer is using this sink */ + if (csdev->refcnt != 1) +@@ -566,7 +566,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, + __etb_enable_hw(drvdata); + CS_LOCK(drvdata->base); + out: +- spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + + return to_read; + } +@@ -587,13 +587,13 @@ static void etb_dump(struct etb_drvdata *drvdata) + { + unsigned long flags; + +- spin_lock_irqsave(&drvdata->spinlock, flags); ++ raw_spin_lock_irqsave(&drvdata->spinlock, flags); + if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) { + __etb_disable_hw(drvdata); + etb_dump_hw(drvdata); + __etb_enable_hw(drvdata); + } +- spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + + dev_dbg(&drvdata->csdev->dev, "ETB dumped\n"); + } +@@ -746,7 +746,7 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id) + drvdata->base = base; + desc.access = CSDEV_ACCESS_IOMEM(base); + +- spin_lock_init(&drvdata->spinlock); ++ raw_spin_lock_init(&drvdata->spinlock); + + drvdata->buffer_depth = etb_get_buffer_depth(drvdata); + +-- +2.39.5 + diff --git a/queue-6.12/cpufreq-add-sm8650-to-cpufreq-dt-platdev-blocklist.patch b/queue-6.12/cpufreq-add-sm8650-to-cpufreq-dt-platdev-blocklist.patch new file mode 100644 index 0000000000..92e76ae281 --- /dev/null +++ b/queue-6.12/cpufreq-add-sm8650-to-cpufreq-dt-platdev-blocklist.patch @@ -0,0 +1,39 @@ +From e742b76ecbee16cc608f588c0503c2ea1ec89168 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 5 Apr 2025 00:42:19 +0800 +Subject: cpufreq: Add SM8650 to cpufreq-dt-platdev blocklist + +From: Pengyu Luo + +[ Upstream commit fc5414a4774e14e51a93499a6adfdc45f2de82e0 ] + +SM8650 have already been supported by qcom-cpufreq-hw driver, but +never been added to cpufreq-dt-platdev. This makes noise + +[ 0.388525] cpufreq-dt cpufreq-dt: failed register driver: -17 +[ 0.388537] cpufreq-dt cpufreq-dt: probe with driver cpufreq-dt failed with error -17 + +So adding it to the cpufreq-dt-platdev driver's blocklist to fix it. + +Signed-off-by: Pengyu Luo +Signed-off-by: Viresh Kumar +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/cpufreq-dt-platdev.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c +index 78ad3221fe077..67bac12d4d55b 100644 +--- a/drivers/cpufreq/cpufreq-dt-platdev.c ++++ b/drivers/cpufreq/cpufreq-dt-platdev.c +@@ -172,6 +172,7 @@ static const struct of_device_id blocklist[] __initconst = { + { .compatible = "qcom,sm8350", }, + { .compatible = "qcom,sm8450", }, + { .compatible = "qcom,sm8550", }, ++ { .compatible = "qcom,sm8650", }, + + { .compatible = "st,stih407", }, + { .compatible = "st,stih410", }, +-- +2.39.5 + diff --git a/queue-6.12/cpufreq-amd-pstate-remove-unnecessary-driver_lock-in.patch b/queue-6.12/cpufreq-amd-pstate-remove-unnecessary-driver_lock-in.patch new file mode 100644 index 0000000000..b5a636d76f --- /dev/null +++ b/queue-6.12/cpufreq-amd-pstate-remove-unnecessary-driver_lock-in.patch @@ -0,0 +1,37 @@ +From dbe8208444bfe92eb9a22e73c2ef5cd3c498e475 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 08:52:52 +0000 +Subject: cpufreq: amd-pstate: Remove unnecessary driver_lock in set_boost + +From: Dhananjay Ugwekar + +[ Upstream commit db1cafc77aaaf871509da06f4a864e9af6d6791f ] + +set_boost is a per-policy function call, hence a driver wide lock is +unnecessary. Also this mutex_acquire can collide with the mutex_acquire +from the mode-switch path in status_store(), which can lead to a +deadlock. So, remove it. + +Signed-off-by: Dhananjay Ugwekar +Acked-by: Mario Limonciello +Signed-off-by: Viresh Kumar +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/amd-pstate.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c +index 9db5354fdb027..7a16d19322286 100644 +--- a/drivers/cpufreq/amd-pstate.c ++++ b/drivers/cpufreq/amd-pstate.c +@@ -696,7 +696,6 @@ static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state) + pr_err("Boost mode is not supported by this processor or SBIOS\n"); + return -EOPNOTSUPP; + } +- guard(mutex)(&amd_pstate_driver_lock); + + ret = amd_pstate_cpu_boost_update(policy, state); + WRITE_ONCE(cpudata->boost_state, !ret ? state : false); +-- +2.39.5 + diff --git a/queue-6.12/cpufreq-tegra186-share-policy-per-cluster.patch b/queue-6.12/cpufreq-tegra186-share-policy-per-cluster.patch new file mode 100644 index 0000000000..3e7dc950e4 --- /dev/null +++ b/queue-6.12/cpufreq-tegra186-share-policy-per-cluster.patch @@ -0,0 +1,47 @@ +From 575d7d2172f0d5f41a67f408a0ceba00c7e2f36e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 00:28:48 -0500 +Subject: cpufreq: tegra186: Share policy per cluster + +From: Aaron Kling + +[ Upstream commit be4ae8c19492cd6d5de61ccb34ffb3f5ede5eec8 ] + +This functionally brings tegra186 in line with tegra210 and tegra194, +sharing a cpufreq policy between all cores in a cluster. + +Reviewed-by: Sumit Gupta +Acked-by: Thierry Reding +Signed-off-by: Aaron Kling +Signed-off-by: Viresh Kumar +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/tegra186-cpufreq.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/cpufreq/tegra186-cpufreq.c b/drivers/cpufreq/tegra186-cpufreq.c +index 7b8fcfa55038b..4e5b6f9a56d1b 100644 +--- a/drivers/cpufreq/tegra186-cpufreq.c ++++ b/drivers/cpufreq/tegra186-cpufreq.c +@@ -73,11 +73,18 @@ static int tegra186_cpufreq_init(struct cpufreq_policy *policy) + { + struct tegra186_cpufreq_data *data = cpufreq_get_driver_data(); + unsigned int cluster = data->cpus[policy->cpu].bpmp_cluster_id; ++ u32 cpu; + + policy->freq_table = data->clusters[cluster].table; + policy->cpuinfo.transition_latency = 300 * 1000; + policy->driver_data = NULL; + ++ /* set same policy for all cpus in a cluster */ ++ for (cpu = 0; cpu < ARRAY_SIZE(tegra186_cpus); cpu++) { ++ if (data->cpus[cpu].bpmp_cluster_id == cluster) ++ cpumask_set_cpu(cpu, policy->cpus); ++ } ++ + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.12/cpuidle-menu-avoid-discarding-useful-information.patch b/queue-6.12/cpuidle-menu-avoid-discarding-useful-information.patch new file mode 100644 index 0000000000..6b2ca8d1ba --- /dev/null +++ b/queue-6.12/cpuidle-menu-avoid-discarding-useful-information.patch @@ -0,0 +1,65 @@ +From 405e733cf7655cff74103b4739837eac674851e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 15:29:05 +0100 +Subject: cpuidle: menu: Avoid discarding useful information + +From: Rafael J. Wysocki + +[ Upstream commit 85975daeaa4d6ec560bfcd354fc9c08ad7f38888 ] + +When giving up on making a high-confidence prediction, +get_typical_interval() always returns UINT_MAX which means that the +next idle interval prediction will be based entirely on the time till +the next timer. However, the information represented by the most +recent intervals may not be completely useless in those cases. + +Namely, the largest recent idle interval is an upper bound on the +recently observed idle duration, so it is reasonable to assume that +the next idle duration is unlikely to exceed it. Moreover, this is +still true after eliminating the suspected outliers if the sample +set still under consideration is at least as large as 50% of the +maximum sample set size. + +Accordingly, make get_typical_interval() return the current maximum +recent interval value in that case instead of UINT_MAX. + +Signed-off-by: Rafael J. Wysocki +Reported-by: Artem Bityutskiy +Tested-by: Artem Bityutskiy +Reviewed-by: Christian Loehle +Tested-by: Christian Loehle +Tested-by: Aboorva Devarajan +Link: https://patch.msgid.link/7770672.EvYhyI6sBW@rjwysocki.net +Signed-off-by: Sasha Levin +--- + drivers/cpuidle/governors/menu.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c +index f3c9d49f0f2a5..97ffadc7e57a6 100644 +--- a/drivers/cpuidle/governors/menu.c ++++ b/drivers/cpuidle/governors/menu.c +@@ -239,8 +239,19 @@ static unsigned int get_typical_interval(struct menu_device *data) + * This can deal with workloads that have long pauses interspersed + * with sporadic activity with a bunch of short pauses. + */ +- if ((divisor * 4) <= INTERVALS * 3) ++ if (divisor * 4 <= INTERVALS * 3) { ++ /* ++ * If there are sufficiently many data points still under ++ * consideration after the outliers have been eliminated, ++ * returning without a prediction would be a mistake because it ++ * is likely that the next interval will not exceed the current ++ * maximum, so return the latter in that case. ++ */ ++ if (divisor >= INTERVALS / 2) ++ return max; ++ + return UINT_MAX; ++ } + + thresh = max - 1; + goto again; +-- +2.39.5 + diff --git a/queue-6.12/crypto-ahash-set-default-reqsize-from-ahash_alg.patch b/queue-6.12/crypto-ahash-set-default-reqsize-from-ahash_alg.patch new file mode 100644 index 0000000000..dae901e98e --- /dev/null +++ b/queue-6.12/crypto-ahash-set-default-reqsize-from-ahash_alg.patch @@ -0,0 +1,66 @@ +From 98efe9de78192eb674ac4a843f18ade97c3da2a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Feb 2025 11:07:24 +0800 +Subject: crypto: ahash - Set default reqsize from ahash_alg + +From: Herbert Xu + +[ Upstream commit 9e01aaa1033d6e40f8d7cf4f20931a61ce9e3f04 ] + +Add a reqsize field to struct ahash_alg and use it to set the +default reqsize so that algorithms with a static reqsize are +not forced to create an init_tfm function. + +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + crypto/ahash.c | 4 ++++ + include/crypto/hash.h | 3 +++ + 2 files changed, 7 insertions(+) + +diff --git a/crypto/ahash.c b/crypto/ahash.c +index bcd9de009a91b..fe19bf7f15eb9 100644 +--- a/crypto/ahash.c ++++ b/crypto/ahash.c +@@ -473,6 +473,7 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm) + struct ahash_alg *alg = crypto_ahash_alg(hash); + + crypto_ahash_set_statesize(hash, alg->halg.statesize); ++ crypto_ahash_set_reqsize(hash, alg->reqsize); + + if (tfm->__crt_alg->cra_type == &crypto_shash_type) + return crypto_init_ahash_using_shash(tfm); +@@ -638,6 +639,9 @@ static int ahash_prepare_alg(struct ahash_alg *alg) + if (alg->halg.statesize == 0) + return -EINVAL; + ++ if (alg->reqsize && alg->reqsize < alg->halg.statesize) ++ return -EINVAL; ++ + err = hash_prepare_alg(&alg->halg); + if (err) + return err; +diff --git a/include/crypto/hash.h b/include/crypto/hash.h +index 2d5ea9f9ff43e..6692253f0b5be 100644 +--- a/include/crypto/hash.h ++++ b/include/crypto/hash.h +@@ -132,6 +132,7 @@ struct ahash_request { + * This is a counterpart to @init_tfm, used to remove + * various changes set in @init_tfm. + * @clone_tfm: Copy transform into new object, may allocate memory. ++ * @reqsize: Size of the request context. + * @halg: see struct hash_alg_common + */ + struct ahash_alg { +@@ -148,6 +149,8 @@ struct ahash_alg { + void (*exit_tfm)(struct crypto_ahash *tfm); + int (*clone_tfm)(struct crypto_ahash *dst, struct crypto_ahash *src); + ++ unsigned int reqsize; ++ + struct hash_alg_common halg; + }; + +-- +2.39.5 + diff --git a/queue-6.12/crypto-lzo-fix-compression-buffer-overrun.patch b/queue-6.12/crypto-lzo-fix-compression-buffer-overrun.patch new file mode 100644 index 0000000000..2fbc07b177 --- /dev/null +++ b/queue-6.12/crypto-lzo-fix-compression-buffer-overrun.patch @@ -0,0 +1,374 @@ +From 5fe28927b005259e709fded1b922503362d7d641 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 17:04:46 +0800 +Subject: crypto: lzo - Fix compression buffer overrun + +From: Herbert Xu + +[ Upstream commit cc47f07234f72cbd8e2c973cdbf2a6730660a463 ] + +Unlike the decompression code, the compression code in LZO never +checked for output overruns. It instead assumes that the caller +always provides enough buffer space, disregarding the buffer length +provided by the caller. + +Add a safe compression interface that checks for the end of buffer +before each write. Use the safe interface in crypto/lzo. + +Signed-off-by: Herbert Xu +Reviewed-by: David Sterba +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + crypto/lzo-rle.c | 2 +- + crypto/lzo.c | 2 +- + include/linux/lzo.h | 8 +++ + lib/lzo/Makefile | 2 +- + lib/lzo/lzo1x_compress.c | 102 +++++++++++++++++++++++++--------- + lib/lzo/lzo1x_compress_safe.c | 18 ++++++ + 6 files changed, 106 insertions(+), 28 deletions(-) + create mode 100644 lib/lzo/lzo1x_compress_safe.c + +diff --git a/crypto/lzo-rle.c b/crypto/lzo-rle.c +index 0631d975bfac1..0abc2d87f0420 100644 +--- a/crypto/lzo-rle.c ++++ b/crypto/lzo-rle.c +@@ -55,7 +55,7 @@ static int __lzorle_compress(const u8 *src, unsigned int slen, + size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */ + int err; + +- err = lzorle1x_1_compress(src, slen, dst, &tmp_len, ctx); ++ err = lzorle1x_1_compress_safe(src, slen, dst, &tmp_len, ctx); + + if (err != LZO_E_OK) + return -EINVAL; +diff --git a/crypto/lzo.c b/crypto/lzo.c +index ebda132dd22bf..8338851c7406a 100644 +--- a/crypto/lzo.c ++++ b/crypto/lzo.c +@@ -55,7 +55,7 @@ static int __lzo_compress(const u8 *src, unsigned int slen, + size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */ + int err; + +- err = lzo1x_1_compress(src, slen, dst, &tmp_len, ctx); ++ err = lzo1x_1_compress_safe(src, slen, dst, &tmp_len, ctx); + + if (err != LZO_E_OK) + return -EINVAL; +diff --git a/include/linux/lzo.h b/include/linux/lzo.h +index e95c7d1092b28..4d30e3624acd2 100644 +--- a/include/linux/lzo.h ++++ b/include/linux/lzo.h +@@ -24,10 +24,18 @@ + int lzo1x_1_compress(const unsigned char *src, size_t src_len, + unsigned char *dst, size_t *dst_len, void *wrkmem); + ++/* Same as above but does not write more than dst_len to dst. */ ++int lzo1x_1_compress_safe(const unsigned char *src, size_t src_len, ++ unsigned char *dst, size_t *dst_len, void *wrkmem); ++ + /* This requires 'wrkmem' of size LZO1X_1_MEM_COMPRESS */ + int lzorle1x_1_compress(const unsigned char *src, size_t src_len, + unsigned char *dst, size_t *dst_len, void *wrkmem); + ++/* Same as above but does not write more than dst_len to dst. */ ++int lzorle1x_1_compress_safe(const unsigned char *src, size_t src_len, ++ unsigned char *dst, size_t *dst_len, void *wrkmem); ++ + /* safe decompression with overrun testing */ + int lzo1x_decompress_safe(const unsigned char *src, size_t src_len, + unsigned char *dst, size_t *dst_len); +diff --git a/lib/lzo/Makefile b/lib/lzo/Makefile +index 2f58fafbbdddc..fc7b2b7ef4b20 100644 +--- a/lib/lzo/Makefile ++++ b/lib/lzo/Makefile +@@ -1,5 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0-only +-lzo_compress-objs := lzo1x_compress.o ++lzo_compress-objs := lzo1x_compress.o lzo1x_compress_safe.o + lzo_decompress-objs := lzo1x_decompress_safe.o + + obj-$(CONFIG_LZO_COMPRESS) += lzo_compress.o +diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c +index 47d6d43ea9578..7b10ca86a8930 100644 +--- a/lib/lzo/lzo1x_compress.c ++++ b/lib/lzo/lzo1x_compress.c +@@ -18,11 +18,22 @@ + #include + #include "lzodefs.h" + +-static noinline size_t +-lzo1x_1_do_compress(const unsigned char *in, size_t in_len, +- unsigned char *out, size_t *out_len, +- size_t ti, void *wrkmem, signed char *state_offset, +- const unsigned char bitstream_version) ++#undef LZO_UNSAFE ++ ++#ifndef LZO_SAFE ++#define LZO_UNSAFE 1 ++#define LZO_SAFE(name) name ++#define HAVE_OP(x) 1 ++#endif ++ ++#define NEED_OP(x) if (!HAVE_OP(x)) goto output_overrun ++ ++static noinline int ++LZO_SAFE(lzo1x_1_do_compress)(const unsigned char *in, size_t in_len, ++ unsigned char **out, unsigned char *op_end, ++ size_t *tp, void *wrkmem, ++ signed char *state_offset, ++ const unsigned char bitstream_version) + { + const unsigned char *ip; + unsigned char *op; +@@ -30,8 +41,9 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len, + const unsigned char * const ip_end = in + in_len - 20; + const unsigned char *ii; + lzo_dict_t * const dict = (lzo_dict_t *) wrkmem; ++ size_t ti = *tp; + +- op = out; ++ op = *out; + ip = in; + ii = ip; + ip += ti < 4 ? 4 - ti : 0; +@@ -116,25 +128,32 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len, + if (t != 0) { + if (t <= 3) { + op[*state_offset] |= t; ++ NEED_OP(4); + COPY4(op, ii); + op += t; + } else if (t <= 16) { ++ NEED_OP(17); + *op++ = (t - 3); + COPY8(op, ii); + COPY8(op + 8, ii + 8); + op += t; + } else { + if (t <= 18) { ++ NEED_OP(1); + *op++ = (t - 3); + } else { + size_t tt = t - 18; ++ NEED_OP(1); + *op++ = 0; + while (unlikely(tt > 255)) { + tt -= 255; ++ NEED_OP(1); + *op++ = 0; + } ++ NEED_OP(1); + *op++ = tt; + } ++ NEED_OP(t); + do { + COPY8(op, ii); + COPY8(op + 8, ii + 8); +@@ -151,6 +170,7 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len, + if (unlikely(run_length)) { + ip += run_length; + run_length -= MIN_ZERO_RUN_LENGTH; ++ NEED_OP(4); + put_unaligned_le32((run_length << 21) | 0xfffc18 + | (run_length & 0x7), op); + op += 4; +@@ -243,10 +263,12 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len, + ip += m_len; + if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) { + m_off -= 1; ++ NEED_OP(2); + *op++ = (((m_len - 1) << 5) | ((m_off & 7) << 2)); + *op++ = (m_off >> 3); + } else if (m_off <= M3_MAX_OFFSET) { + m_off -= 1; ++ NEED_OP(1); + if (m_len <= M3_MAX_LEN) + *op++ = (M3_MARKER | (m_len - 2)); + else { +@@ -254,14 +276,18 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len, + *op++ = M3_MARKER | 0; + while (unlikely(m_len > 255)) { + m_len -= 255; ++ NEED_OP(1); + *op++ = 0; + } ++ NEED_OP(1); + *op++ = (m_len); + } ++ NEED_OP(2); + *op++ = (m_off << 2); + *op++ = (m_off >> 6); + } else { + m_off -= 0x4000; ++ NEED_OP(1); + if (m_len <= M4_MAX_LEN) + *op++ = (M4_MARKER | ((m_off >> 11) & 8) + | (m_len - 2)); +@@ -282,11 +308,14 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len, + m_len -= M4_MAX_LEN; + *op++ = (M4_MARKER | ((m_off >> 11) & 8)); + while (unlikely(m_len > 255)) { ++ NEED_OP(1); + m_len -= 255; + *op++ = 0; + } ++ NEED_OP(1); + *op++ = (m_len); + } ++ NEED_OP(2); + *op++ = (m_off << 2); + *op++ = (m_off >> 6); + } +@@ -295,14 +324,20 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len, + ii = ip; + goto next; + } +- *out_len = op - out; +- return in_end - (ii - ti); ++ *out = op; ++ *tp = in_end - (ii - ti); ++ return LZO_E_OK; ++ ++output_overrun: ++ return LZO_E_OUTPUT_OVERRUN; + } + +-static int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len, +- unsigned char *out, size_t *out_len, +- void *wrkmem, const unsigned char bitstream_version) ++static int LZO_SAFE(lzogeneric1x_1_compress)( ++ const unsigned char *in, size_t in_len, ++ unsigned char *out, size_t *out_len, ++ void *wrkmem, const unsigned char bitstream_version) + { ++ unsigned char * const op_end = out + *out_len; + const unsigned char *ip = in; + unsigned char *op = out; + unsigned char *data_start; +@@ -326,14 +361,18 @@ static int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len, + while (l > 20) { + size_t ll = min_t(size_t, l, m4_max_offset + 1); + uintptr_t ll_end = (uintptr_t) ip + ll; ++ int err; ++ + if ((ll_end + ((t + ll) >> 5)) <= ll_end) + break; + BUILD_BUG_ON(D_SIZE * sizeof(lzo_dict_t) > LZO1X_1_MEM_COMPRESS); + memset(wrkmem, 0, D_SIZE * sizeof(lzo_dict_t)); +- t = lzo1x_1_do_compress(ip, ll, op, out_len, t, wrkmem, +- &state_offset, bitstream_version); ++ err = LZO_SAFE(lzo1x_1_do_compress)( ++ ip, ll, &op, op_end, &t, wrkmem, ++ &state_offset, bitstream_version); ++ if (err != LZO_E_OK) ++ return err; + ip += ll; +- op += *out_len; + l -= ll; + } + t += l; +@@ -342,20 +381,26 @@ static int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len, + const unsigned char *ii = in + in_len - t; + + if (op == data_start && t <= 238) { ++ NEED_OP(1); + *op++ = (17 + t); + } else if (t <= 3) { + op[state_offset] |= t; + } else if (t <= 18) { ++ NEED_OP(1); + *op++ = (t - 3); + } else { + size_t tt = t - 18; ++ NEED_OP(1); + *op++ = 0; + while (tt > 255) { + tt -= 255; ++ NEED_OP(1); + *op++ = 0; + } ++ NEED_OP(1); + *op++ = tt; + } ++ NEED_OP(t); + if (t >= 16) do { + COPY8(op, ii); + COPY8(op + 8, ii + 8); +@@ -368,31 +413,38 @@ static int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len, + } while (--t > 0); + } + ++ NEED_OP(3); + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = op - out; + return LZO_E_OK; ++ ++output_overrun: ++ return LZO_E_OUTPUT_OVERRUN; + } + +-int lzo1x_1_compress(const unsigned char *in, size_t in_len, +- unsigned char *out, size_t *out_len, +- void *wrkmem) ++int LZO_SAFE(lzo1x_1_compress)(const unsigned char *in, size_t in_len, ++ unsigned char *out, size_t *out_len, ++ void *wrkmem) + { +- return lzogeneric1x_1_compress(in, in_len, out, out_len, wrkmem, 0); ++ return LZO_SAFE(lzogeneric1x_1_compress)( ++ in, in_len, out, out_len, wrkmem, 0); + } + +-int lzorle1x_1_compress(const unsigned char *in, size_t in_len, +- unsigned char *out, size_t *out_len, +- void *wrkmem) ++int LZO_SAFE(lzorle1x_1_compress)(const unsigned char *in, size_t in_len, ++ unsigned char *out, size_t *out_len, ++ void *wrkmem) + { +- return lzogeneric1x_1_compress(in, in_len, out, out_len, +- wrkmem, LZO_VERSION); ++ return LZO_SAFE(lzogeneric1x_1_compress)( ++ in, in_len, out, out_len, wrkmem, LZO_VERSION); + } + +-EXPORT_SYMBOL_GPL(lzo1x_1_compress); +-EXPORT_SYMBOL_GPL(lzorle1x_1_compress); ++EXPORT_SYMBOL_GPL(LZO_SAFE(lzo1x_1_compress)); ++EXPORT_SYMBOL_GPL(LZO_SAFE(lzorle1x_1_compress)); + ++#ifndef LZO_UNSAFE + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("LZO1X-1 Compressor"); ++#endif +diff --git a/lib/lzo/lzo1x_compress_safe.c b/lib/lzo/lzo1x_compress_safe.c +new file mode 100644 +index 0000000000000..371c9f8494928 +--- /dev/null ++++ b/lib/lzo/lzo1x_compress_safe.c +@@ -0,0 +1,18 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * LZO1X Compressor from LZO ++ * ++ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer ++ * ++ * The full LZO package can be found at: ++ * http://www.oberhumer.com/opensource/lzo/ ++ * ++ * Changed for Linux kernel use by: ++ * Nitin Gupta ++ * Richard Purdie ++ */ ++ ++#define LZO_SAFE(name) name##_safe ++#define HAVE_OP(x) ((size_t)(op_end - op) >= (size_t)(x)) ++ ++#include "lzo1x_compress.c" +-- +2.39.5 + diff --git a/queue-6.12/crypto-mxs-dcp-only-set-otp_key-bit-for-otp-key.patch b/queue-6.12/crypto-mxs-dcp-only-set-otp_key-bit-for-otp-key.patch new file mode 100644 index 0000000000..e40306a6a2 --- /dev/null +++ b/queue-6.12/crypto-mxs-dcp-only-set-otp_key-bit-for-otp-key.patch @@ -0,0 +1,45 @@ +From cc9bc41542af3f0046bb04685ff19d3beb376b0a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 08:42:25 +0100 +Subject: crypto: mxs-dcp - Only set OTP_KEY bit for OTP key + +From: Sven Schwermer + +[ Upstream commit caa9dbb76ff52ec848a57245062aaeaa07740adc ] + +While MXS_DCP_CONTROL0_OTP_KEY is set, the CRYPTO_KEY (DCP_PAES_KEY_OTP) +is used even if the UNIQUE_KEY (DCP_PAES_KEY_UNIQUE) is selected. This +is not clearly documented, but this implementation is consistent with +NXP's downstream kernel fork and optee_os. + +Signed-off-by: Sven Schwermer +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/mxs-dcp.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c +index 77a6301f37f0a..29c0c69d5905d 100644 +--- a/drivers/crypto/mxs-dcp.c ++++ b/drivers/crypto/mxs-dcp.c +@@ -265,12 +265,12 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx, + MXS_DCP_CONTROL0_INTERRUPT | + MXS_DCP_CONTROL0_ENABLE_CIPHER; + +- if (key_referenced) +- /* Set OTP key bit to select the key via KEY_SELECT. */ +- desc->control0 |= MXS_DCP_CONTROL0_OTP_KEY; +- else ++ if (!key_referenced) + /* Payload contains the key. */ + desc->control0 |= MXS_DCP_CONTROL0_PAYLOAD_KEY; ++ else if (actx->key[0] == DCP_PAES_KEY_OTP) ++ /* Set OTP key bit to select the key via KEY_SELECT. */ ++ desc->control0 |= MXS_DCP_CONTROL0_OTP_KEY; + + if (rctx->enc) + desc->control0 |= MXS_DCP_CONTROL0_CIPHER_ENCRYPT; +-- +2.39.5 + diff --git a/queue-6.12/crypto-octeontx2-suppress-auth-failure-screaming-due.patch b/queue-6.12/crypto-octeontx2-suppress-auth-failure-screaming-due.patch new file mode 100644 index 0000000000..625dfc16b7 --- /dev/null +++ b/queue-6.12/crypto-octeontx2-suppress-auth-failure-screaming-due.patch @@ -0,0 +1,43 @@ +From 33582ad9031c30e18bc0937d31400f2c65bb8ee6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 13:27:05 +0530 +Subject: crypto: octeontx2 - suppress auth failure screaming due to negative + tests + +From: Shashank Gupta + +[ Upstream commit 64b7871522a4cba99d092e1c849d6f9092868aaa ] + +This patch addresses an issue where authentication failures were being +erroneously reported due to negative test failures in the "ccm(aes)" +selftest. +pr_debug suppress unnecessary screaming of these tests. + +Signed-off-by: Shashank Gupta +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/marvell/octeontx2/otx2_cptvf_reqmgr.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf_reqmgr.c b/drivers/crypto/marvell/octeontx2/otx2_cptvf_reqmgr.c +index 5387c68f3c9df..4262441070372 100644 +--- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_reqmgr.c ++++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_reqmgr.c +@@ -264,9 +264,10 @@ static int cpt_process_ccode(struct otx2_cptlfs_info *lfs, + break; + } + +- dev_err(&pdev->dev, +- "Request failed with software error code 0x%x\n", +- cpt_status->s.uc_compcode); ++ pr_debug("Request failed with software error code 0x%x: algo = %s driver = %s\n", ++ cpt_status->s.uc_compcode, ++ info->req->areq->tfm->__crt_alg->cra_name, ++ info->req->areq->tfm->__crt_alg->cra_driver_name); + otx2_cpt_dump_sg_list(pdev, info->req); + break; + } +-- +2.39.5 + diff --git a/queue-6.12/crypto-skcipher-zap-type-in-crypto_alloc_sync_skciph.patch b/queue-6.12/crypto-skcipher-zap-type-in-crypto_alloc_sync_skciph.patch new file mode 100644 index 0000000000..593d7d760e --- /dev/null +++ b/queue-6.12/crypto-skcipher-zap-type-in-crypto_alloc_sync_skciph.patch @@ -0,0 +1,33 @@ +From 32b9c5acf8b2d1d9d1125c23da88ca3d71e7df42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Feb 2025 08:57:51 +0800 +Subject: crypto: skcipher - Zap type in crypto_alloc_sync_skcipher + +From: Herbert Xu + +[ Upstream commit ee509efc74ddbc59bb5d6fd6e050f9ef25f74bff ] + +The type needs to be zeroed as otherwise the user could use it to +allocate an asynchronous sync skcipher. + +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + crypto/skcipher.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/crypto/skcipher.c b/crypto/skcipher.c +index ceed7f33a67ba..fd3273b519dc0 100644 +--- a/crypto/skcipher.c ++++ b/crypto/skcipher.c +@@ -844,6 +844,7 @@ struct crypto_sync_skcipher *crypto_alloc_sync_skcipher( + + /* Only sync algorithms allowed. */ + mask |= CRYPTO_ALG_ASYNC | CRYPTO_ALG_SKCIPHER_REQSIZE_LARGE; ++ type &= ~(CRYPTO_ALG_ASYNC | CRYPTO_ALG_SKCIPHER_REQSIZE_LARGE); + + tfm = crypto_alloc_tfm(alg_name, &crypto_skcipher_type, type, mask); + +-- +2.39.5 + diff --git a/queue-6.12/dlm-make-tcp-still-work-in-multi-link-env.patch b/queue-6.12/dlm-make-tcp-still-work-in-multi-link-env.patch new file mode 100644 index 0000000000..d00de0e137 --- /dev/null +++ b/queue-6.12/dlm-make-tcp-still-work-in-multi-link-env.patch @@ -0,0 +1,37 @@ +From cfba0beb16b95e847ca9d7d1d4331394b91d371f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 15:36:21 +0800 +Subject: dlm: make tcp still work in multi-link env + +From: Heming Zhao + +[ Upstream commit 03d2b62208a336a3bb984b9465ef6d89a046ea22 ] + +This patch bypasses multi-link errors in TCP mode, allowing dlm +to operate on the first tcp link. + +Signed-off-by: Heming Zhao +Signed-off-by: David Teigland +Signed-off-by: Sasha Levin +--- + fs/dlm/lowcomms.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c +index f2d88a3581695..10461451185e8 100644 +--- a/fs/dlm/lowcomms.c ++++ b/fs/dlm/lowcomms.c +@@ -1826,8 +1826,8 @@ static int dlm_tcp_listen_validate(void) + { + /* We don't support multi-homed hosts */ + if (dlm_local_count > 1) { +- log_print("TCP protocol can't handle multi-homed hosts, try SCTP"); +- return -EINVAL; ++ log_print("Detect multi-homed hosts but use only the first IP address."); ++ log_print("Try SCTP, if you want to enable multi-link."); + } + + return 0; +-- +2.39.5 + diff --git a/queue-6.12/dm-cache-prevent-bug_on-by-blocking-retries-on-faile.patch b/queue-6.12/dm-cache-prevent-bug_on-by-blocking-retries-on-faile.patch new file mode 100644 index 0000000000..4e15568dc4 --- /dev/null +++ b/queue-6.12/dm-cache-prevent-bug_on-by-blocking-retries-on-faile.patch @@ -0,0 +1,121 @@ +From 6b4ef8c7424978499bebcc34cf1fa592999ee43b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 16:41:50 +0800 +Subject: dm cache: prevent BUG_ON by blocking retries on failed device resumes + +From: Ming-Hung Tsai + +[ Upstream commit 5da692e2262b8f81993baa9592f57d12c2703dea ] + +A cache device failing to resume due to mapping errors should not be +retried, as the failure leaves a partially initialized policy object. +Repeating the resume operation risks triggering BUG_ON when reloading +cache mappings into the incomplete policy object. + +Reproduce steps: + +1. create a cache metadata consisting of 512 or more cache blocks, + with some mappings stored in the first array block of the mapping + array. Here we use cache_restore v1.0 to build the metadata. + +cat <> cmeta.xml + + + + + +EOF +dmsetup create cmeta --table "0 8192 linear /dev/sdc 0" +cache_restore -i cmeta.xml -o /dev/mapper/cmeta --metadata-version=2 +dmsetup remove cmeta + +2. wipe the second array block of the mapping array to simulate + data degradations. + +mapping_root=$(dd if=/dev/sdc bs=1c count=8 skip=192 \ +2>/dev/null | hexdump -e '1/8 "%u\n"') +ablock=$(dd if=/dev/sdc bs=1c count=8 skip=$((4096*mapping_root+2056)) \ +2>/dev/null | hexdump -e '1/8 "%u\n"') +dd if=/dev/zero of=/dev/sdc bs=4k count=1 seek=$ablock + +3. try bringing up the cache device. The resume is expected to fail + due to the broken array block. + +dmsetup create cmeta --table "0 8192 linear /dev/sdc 0" +dmsetup create cdata --table "0 65536 linear /dev/sdc 8192" +dmsetup create corig --table "0 524288 linear /dev/sdc 262144" +dmsetup create cache --notable +dmsetup load cache --table "0 524288 cache /dev/mapper/cmeta \ +/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0" +dmsetup resume cache + +4. try resuming the cache again. An unexpected BUG_ON is triggered + while loading cache mappings. + +dmsetup resume cache + +Kernel logs: + +(snip) +------------[ cut here ]------------ +kernel BUG at drivers/md/dm-cache-policy-smq.c:752! +Oops: invalid opcode: 0000 [#1] PREEMPT SMP KASAN NOPTI +CPU: 0 UID: 0 PID: 332 Comm: dmsetup Not tainted 6.13.4 #3 +RIP: 0010:smq_load_mapping+0x3e5/0x570 + +Fix by disallowing resume operations for devices that failed the +initial attempt. + +Signed-off-by: Ming-Hung Tsai +Signed-off-by: Mikulas Patocka +Signed-off-by: Sasha Levin +--- + drivers/md/dm-cache-target.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c +index 849eb6333e980..6aa4095dc5876 100644 +--- a/drivers/md/dm-cache-target.c ++++ b/drivers/md/dm-cache-target.c +@@ -2899,6 +2899,27 @@ static dm_cblock_t get_cache_dev_size(struct cache *cache) + return to_cblock(size); + } + ++static bool can_resume(struct cache *cache) ++{ ++ /* ++ * Disallow retrying the resume operation for devices that failed the ++ * first resume attempt, as the failure leaves the policy object partially ++ * initialized. Retrying could trigger BUG_ON when loading cache mappings ++ * into the incomplete policy object. ++ */ ++ if (cache->sized && !cache->loaded_mappings) { ++ if (get_cache_mode(cache) != CM_WRITE) ++ DMERR("%s: unable to resume a failed-loaded cache, please check metadata.", ++ cache_device_name(cache)); ++ else ++ DMERR("%s: unable to resume cache due to missing proper cache table reload", ++ cache_device_name(cache)); ++ return false; ++ } ++ ++ return true; ++} ++ + static bool can_resize(struct cache *cache, dm_cblock_t new_size) + { + if (from_cblock(new_size) > from_cblock(cache->cache_size)) { +@@ -2947,6 +2968,9 @@ static int cache_preresume(struct dm_target *ti) + struct cache *cache = ti->private; + dm_cblock_t csize = get_cache_dev_size(cache); + ++ if (!can_resume(cache)) ++ return -EINVAL; ++ + /* + * Check to see if the cache has resized. + */ +-- +2.39.5 + diff --git a/queue-6.12/dm-fix-unconditional-io-throttle-caused-by-req_prefl.patch b/queue-6.12/dm-fix-unconditional-io-throttle-caused-by-req_prefl.patch new file mode 100644 index 0000000000..e0cb3944ef --- /dev/null +++ b/queue-6.12/dm-fix-unconditional-io-throttle-caused-by-req_prefl.patch @@ -0,0 +1,82 @@ +From 1ec4b4bf74ddb75fb02a09ab8e7a8bc1864c7107 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 19:20:14 +0800 +Subject: dm: fix unconditional IO throttle caused by REQ_PREFLUSH + +From: Jinliang Zheng + +[ Upstream commit 88f7f56d16f568f19e1a695af34a7f4a6ce537a6 ] + +When a bio with REQ_PREFLUSH is submitted to dm, __send_empty_flush() +generates a flush_bio with REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC, +which causes the flush_bio to be throttled by wbt_wait(). + +An example from v5.4, similar problem also exists in upstream: + + crash> bt 2091206 + PID: 2091206 TASK: ffff2050df92a300 CPU: 109 COMMAND: "kworker/u260:0" + #0 [ffff800084a2f7f0] __switch_to at ffff80004008aeb8 + #1 [ffff800084a2f820] __schedule at ffff800040bfa0c4 + #2 [ffff800084a2f880] schedule at ffff800040bfa4b4 + #3 [ffff800084a2f8a0] io_schedule at ffff800040bfa9c4 + #4 [ffff800084a2f8c0] rq_qos_wait at ffff8000405925bc + #5 [ffff800084a2f940] wbt_wait at ffff8000405bb3a0 + #6 [ffff800084a2f9a0] __rq_qos_throttle at ffff800040592254 + #7 [ffff800084a2f9c0] blk_mq_make_request at ffff80004057cf38 + #8 [ffff800084a2fa60] generic_make_request at ffff800040570138 + #9 [ffff800084a2fae0] submit_bio at ffff8000405703b4 + #10 [ffff800084a2fb50] xlog_write_iclog at ffff800001280834 [xfs] + #11 [ffff800084a2fbb0] xlog_sync at ffff800001280c3c [xfs] + #12 [ffff800084a2fbf0] xlog_state_release_iclog at ffff800001280df4 [xfs] + #13 [ffff800084a2fc10] xlog_write at ffff80000128203c [xfs] + #14 [ffff800084a2fcd0] xlog_cil_push at ffff8000012846dc [xfs] + #15 [ffff800084a2fda0] xlog_cil_push_work at ffff800001284a2c [xfs] + #16 [ffff800084a2fdb0] process_one_work at ffff800040111d08 + #17 [ffff800084a2fe00] worker_thread at ffff8000401121cc + #18 [ffff800084a2fe70] kthread at ffff800040118de4 + +After commit 2def2845cc33 ("xfs: don't allow log IO to be throttled"), +the metadata submitted by xlog_write_iclog() should not be throttled. +But due to the existence of the dm layer, throttling flush_bio indirectly +causes the metadata bio to be throttled. + +Fix this by conditionally adding REQ_IDLE to flush_bio.bi_opf, which makes +wbt_should_throttle() return false to avoid wbt_wait(). + +Signed-off-by: Jinliang Zheng +Reviewed-by: Tianxiang Peng +Reviewed-by: Hao Peng +Signed-off-by: Mikulas Patocka +Signed-off-by: Sasha Levin +--- + drivers/md/dm.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/md/dm.c b/drivers/md/dm.c +index 19230404d8c2b..d29125ee9e72a 100644 +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -1541,14 +1541,18 @@ static void __send_empty_flush(struct clone_info *ci) + { + struct dm_table *t = ci->map; + struct bio flush_bio; ++ blk_opf_t opf = REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC; ++ ++ if ((ci->io->orig_bio->bi_opf & (REQ_IDLE | REQ_SYNC)) == ++ (REQ_IDLE | REQ_SYNC)) ++ opf |= REQ_IDLE; + + /* + * Use an on-stack bio for this, it's safe since we don't + * need to reference it after submit. It's just used as + * the basis for the clone(s). + */ +- bio_init(&flush_bio, ci->io->md->disk->part0, NULL, 0, +- REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC); ++ bio_init(&flush_bio, ci->io->md->disk->part0, NULL, 0, opf); + + ci->bio = &flush_bio; + ci->sector_count = 0; +-- +2.39.5 + diff --git a/queue-6.12/dm-restrict-dm-device-size-to-2-63-512-bytes.patch b/queue-6.12/dm-restrict-dm-device-size-to-2-63-512-bytes.patch new file mode 100644 index 0000000000..974f6adb5c --- /dev/null +++ b/queue-6.12/dm-restrict-dm-device-size-to-2-63-512-bytes.patch @@ -0,0 +1,39 @@ +From 63838f2c630800f60d77ad2167e4994dc5d4ba42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 13:51:32 +0100 +Subject: dm: restrict dm device size to 2^63-512 bytes + +From: Mikulas Patocka + +[ Upstream commit 45fc728515c14f53f6205789de5bfd72a95af3b8 ] + +The devices with size >= 2^63 bytes can't be used reliably by userspace +because the type off_t is a signed 64-bit integer. + +Therefore, we limit the maximum size of a device mapper device to +2^63-512 bytes. + +Signed-off-by: Mikulas Patocka +Signed-off-by: Sasha Levin +--- + drivers/md/dm-table.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c +index 3dc5bc3d29d64..883f01e78324f 100644 +--- a/drivers/md/dm-table.c ++++ b/drivers/md/dm-table.c +@@ -698,6 +698,10 @@ int dm_table_add_target(struct dm_table *t, const char *type, + DMERR("%s: zero-length target", dm_device_name(t->md)); + return -EINVAL; + } ++ if (start + len < start || start + len > LLONG_MAX >> SECTOR_SHIFT) { ++ DMERR("%s: too large device", dm_device_name(t->md)); ++ return -EINVAL; ++ } + + ti->type = dm_get_target_type(type); + if (!ti->type) { +-- +2.39.5 + diff --git a/queue-6.12/dm-vdo-indexer-prevent-unterminated-string-warning.patch b/queue-6.12/dm-vdo-indexer-prevent-unterminated-string-warning.patch new file mode 100644 index 0000000000..56fa76cf94 --- /dev/null +++ b/queue-6.12/dm-vdo-indexer-prevent-unterminated-string-warning.patch @@ -0,0 +1,53 @@ +From 26b0854dfa27b44eccd2d19e1db372be63432dc1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 18:27:12 -0500 +Subject: dm vdo indexer: prevent unterminated string warning +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Chung Chung + +[ Upstream commit f4e99b846c90163d350c69d6581ac38dd5818eb8 ] + +Fix array initialization that triggers a warning: + +error: initializer-string for array of ‘unsigned char’ is too long + [-Werror=unterminated-string-initialization] + +Signed-off-by: Chung Chung +Signed-off-by: Matthew Sakai +Signed-off-by: Mikulas Patocka +Signed-off-by: Sasha Levin +--- + drivers/md/dm-vdo/indexer/index-layout.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/md/dm-vdo/indexer/index-layout.c b/drivers/md/dm-vdo/indexer/index-layout.c +index 627adc24af3b7..053b7845d1f34 100644 +--- a/drivers/md/dm-vdo/indexer/index-layout.c ++++ b/drivers/md/dm-vdo/indexer/index-layout.c +@@ -54,7 +54,6 @@ + * Each save also has a unique nonce. + */ + +-#define MAGIC_SIZE 32 + #define NONCE_INFO_SIZE 32 + #define MAX_SAVES 2 + +@@ -98,9 +97,11 @@ enum region_type { + #define SUPER_VERSION_CURRENT 3 + #define SUPER_VERSION_MAXIMUM 7 + +-static const u8 LAYOUT_MAGIC[MAGIC_SIZE] = "*ALBIREO*SINGLE*FILE*LAYOUT*001*"; ++static const u8 LAYOUT_MAGIC[] = "*ALBIREO*SINGLE*FILE*LAYOUT*001*"; + static const u64 REGION_MAGIC = 0x416c6252676e3031; /* 'AlbRgn01' */ + ++#define MAGIC_SIZE (sizeof(LAYOUT_MAGIC) - 1) ++ + struct region_header { + u64 magic; + u64 region_blocks; +-- +2.39.5 + diff --git a/queue-6.12/dm-vdo-use-a-short-static-string-for-thread-name-pre.patch b/queue-6.12/dm-vdo-use-a-short-static-string-for-thread-name-pre.patch new file mode 100644 index 0000000000..db25dee3f3 --- /dev/null +++ b/queue-6.12/dm-vdo-use-a-short-static-string-for-thread-name-pre.patch @@ -0,0 +1,76 @@ +From 35a4eda668c9bbe8d4ab8887a89ce676ee8d5a62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 18:26:05 -0500 +Subject: dm vdo: use a short static string for thread name prefix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Matthew Sakai + +[ Upstream commit 3280c9313c9adce01550cc9f00edfb1dc7c744da ] + +Also remove MODULE_NAME and a BUG_ON check, both unneeded. + +This fixes a warning about string truncation in snprintf that +will never happen in practice: + +drivers/md/dm-vdo/vdo.c: In function ‘vdo_make’: +drivers/md/dm-vdo/vdo.c:564:5: error: ‘%s’ directive output may be truncated writing up to 55 bytes into a region of size 16 [-Werror=format-truncation=] + "%s%u", MODULE_NAME, instance); + ^~ +drivers/md/dm-vdo/vdo.c:563:2: note: ‘snprintf’ output between 2 and 66 bytes into a destination of size 16 + snprintf(vdo->thread_name_prefix, sizeof(vdo->thread_name_prefix), + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + "%s%u", MODULE_NAME, instance); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Reported-by: John Garry +Reviewed-by: John Garry +Signed-off-by: Matthew Sakai +Signed-off-by: Mikulas Patocka +Signed-off-by: Sasha Levin +--- + drivers/md/dm-vdo/vdo.c | 11 +---------- + 1 file changed, 1 insertion(+), 10 deletions(-) + +diff --git a/drivers/md/dm-vdo/vdo.c b/drivers/md/dm-vdo/vdo.c +index fff847767755a..b897f88250d2a 100644 +--- a/drivers/md/dm-vdo/vdo.c ++++ b/drivers/md/dm-vdo/vdo.c +@@ -31,9 +31,7 @@ + + #include + #include +-#include + #include +-#include + #include + #include + #include +@@ -142,12 +140,6 @@ static void finish_vdo_request_queue(void *ptr) + vdo_unregister_allocating_thread(); + } + +-#ifdef MODULE +-#define MODULE_NAME THIS_MODULE->name +-#else +-#define MODULE_NAME "dm-vdo" +-#endif /* MODULE */ +- + static const struct vdo_work_queue_type default_queue_type = { + .start = start_vdo_request_queue, + .finish = finish_vdo_request_queue, +@@ -559,8 +551,7 @@ int vdo_make(unsigned int instance, struct device_config *config, char **reason, + *vdo_ptr = vdo; + + snprintf(vdo->thread_name_prefix, sizeof(vdo->thread_name_prefix), +- "%s%u", MODULE_NAME, instance); +- BUG_ON(vdo->thread_name_prefix[0] == '\0'); ++ "vdo%u", instance); + result = vdo_allocate(vdo->thread_config.thread_count, + struct vdo_thread, __func__, &vdo->threads); + if (result != VDO_SUCCESS) { +-- +2.39.5 + diff --git a/queue-6.12/dm-vdo-vio-pool-allow-variable-sized-metadata-vios.patch b/queue-6.12/dm-vdo-vio-pool-allow-variable-sized-metadata-vios.patch new file mode 100644 index 0000000000..b8ea79e54a --- /dev/null +++ b/queue-6.12/dm-vdo-vio-pool-allow-variable-sized-metadata-vios.patch @@ -0,0 +1,208 @@ +From ac663217ac4eeab508db348a67511d45ccd9846f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 21:18:05 -0500 +Subject: dm vdo vio-pool: allow variable-sized metadata vios + +From: Ken Raeburn + +[ Upstream commit f979da512553a41a657f2c1198277e84d66f8ce3 ] + +With larger-sized metadata vio pools, vdo will sometimes need to +issue I/O with a smaller size than the allocated size. Since +vio_reset_bio is where the bvec array and I/O size are initialized, +this reset interface must now specify what I/O size to use. + +Signed-off-by: Ken Raeburn +Signed-off-by: Matthew Sakai +Signed-off-by: Mikulas Patocka +Signed-off-by: Sasha Levin +--- + drivers/md/dm-vdo/io-submitter.c | 6 ++++-- + drivers/md/dm-vdo/io-submitter.h | 18 +++++++++++++--- + drivers/md/dm-vdo/types.h | 3 +++ + drivers/md/dm-vdo/vio.c | 36 +++++++++++++++++++------------- + drivers/md/dm-vdo/vio.h | 2 ++ + 5 files changed, 46 insertions(+), 19 deletions(-) + +diff --git a/drivers/md/dm-vdo/io-submitter.c b/drivers/md/dm-vdo/io-submitter.c +index ab62abe18827b..a664be89c15d7 100644 +--- a/drivers/md/dm-vdo/io-submitter.c ++++ b/drivers/md/dm-vdo/io-submitter.c +@@ -327,6 +327,7 @@ void vdo_submit_data_vio(struct data_vio *data_vio) + * @error_handler: the handler for submission or I/O errors (may be NULL) + * @operation: the type of I/O to perform + * @data: the buffer to read or write (may be NULL) ++ * @size: the I/O amount in bytes + * + * The vio is enqueued on a vdo bio queue so that bio submission (which may block) does not block + * other vdo threads. +@@ -338,7 +339,7 @@ void vdo_submit_data_vio(struct data_vio *data_vio) + */ + void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical, + bio_end_io_t callback, vdo_action_fn error_handler, +- blk_opf_t operation, char *data) ++ blk_opf_t operation, char *data, int size) + { + int result; + struct vdo_completion *completion = &vio->completion; +@@ -349,7 +350,8 @@ void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical, + + vdo_reset_completion(completion); + completion->error_handler = error_handler; +- result = vio_reset_bio(vio, data, callback, operation | REQ_META, physical); ++ result = vio_reset_bio_with_size(vio, data, size, callback, operation | REQ_META, ++ physical); + if (result != VDO_SUCCESS) { + continue_vio(vio, result); + return; +diff --git a/drivers/md/dm-vdo/io-submitter.h b/drivers/md/dm-vdo/io-submitter.h +index 80748699496f2..3088f11055fdd 100644 +--- a/drivers/md/dm-vdo/io-submitter.h ++++ b/drivers/md/dm-vdo/io-submitter.h +@@ -8,6 +8,7 @@ + + #include + ++#include "constants.h" + #include "types.h" + + struct io_submitter; +@@ -26,14 +27,25 @@ void vdo_submit_data_vio(struct data_vio *data_vio); + + void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical, + bio_end_io_t callback, vdo_action_fn error_handler, +- blk_opf_t operation, char *data); ++ blk_opf_t operation, char *data, int size); + + static inline void vdo_submit_metadata_vio(struct vio *vio, physical_block_number_t physical, + bio_end_io_t callback, vdo_action_fn error_handler, + blk_opf_t operation) + { + __submit_metadata_vio(vio, physical, callback, error_handler, +- operation, vio->data); ++ operation, vio->data, vio->block_count * VDO_BLOCK_SIZE); ++} ++ ++static inline void vdo_submit_metadata_vio_with_size(struct vio *vio, ++ physical_block_number_t physical, ++ bio_end_io_t callback, ++ vdo_action_fn error_handler, ++ blk_opf_t operation, ++ int size) ++{ ++ __submit_metadata_vio(vio, physical, callback, error_handler, ++ operation, vio->data, size); + } + + static inline void vdo_submit_flush_vio(struct vio *vio, bio_end_io_t callback, +@@ -41,7 +53,7 @@ static inline void vdo_submit_flush_vio(struct vio *vio, bio_end_io_t callback, + { + /* FIXME: Can we just use REQ_OP_FLUSH? */ + __submit_metadata_vio(vio, 0, callback, error_handler, +- REQ_OP_WRITE | REQ_PREFLUSH, NULL); ++ REQ_OP_WRITE | REQ_PREFLUSH, NULL, 0); + } + + #endif /* VDO_IO_SUBMITTER_H */ +diff --git a/drivers/md/dm-vdo/types.h b/drivers/md/dm-vdo/types.h +index dbe892b10f265..cdf36e7d77021 100644 +--- a/drivers/md/dm-vdo/types.h ++++ b/drivers/md/dm-vdo/types.h +@@ -376,6 +376,9 @@ struct vio { + /* The size of this vio in blocks */ + unsigned int block_count; + ++ /* The amount of data to be read or written, in bytes */ ++ unsigned int io_size; ++ + /* The data being read or written. */ + char *data; + +diff --git a/drivers/md/dm-vdo/vio.c b/drivers/md/dm-vdo/vio.c +index b291578f726f5..7c417c1af4516 100644 +--- a/drivers/md/dm-vdo/vio.c ++++ b/drivers/md/dm-vdo/vio.c +@@ -188,14 +188,23 @@ void vdo_set_bio_properties(struct bio *bio, struct vio *vio, bio_end_io_t callb + + /* + * Prepares the bio to perform IO with the specified buffer. May only be used on a VDO-allocated +- * bio, as it assumes the bio wraps a 4k buffer that is 4k aligned, but there does not have to be a +- * vio associated with the bio. ++ * bio, as it assumes the bio wraps a 4k-multiple buffer that is 4k aligned, but there does not ++ * have to be a vio associated with the bio. + */ + int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback, + blk_opf_t bi_opf, physical_block_number_t pbn) + { +- int bvec_count, offset, len, i; ++ return vio_reset_bio_with_size(vio, data, vio->block_count * VDO_BLOCK_SIZE, ++ callback, bi_opf, pbn); ++} ++ ++int vio_reset_bio_with_size(struct vio *vio, char *data, int size, bio_end_io_t callback, ++ blk_opf_t bi_opf, physical_block_number_t pbn) ++{ ++ int bvec_count, offset, i; + struct bio *bio = vio->bio; ++ int vio_size = vio->block_count * VDO_BLOCK_SIZE; ++ int remaining; + + bio_reset(bio, bio->bi_bdev, bi_opf); + vdo_set_bio_properties(bio, vio, callback, bi_opf, pbn); +@@ -204,22 +213,21 @@ int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback, + + bio->bi_io_vec = bio->bi_inline_vecs; + bio->bi_max_vecs = vio->block_count + 1; +- len = VDO_BLOCK_SIZE * vio->block_count; ++ if (VDO_ASSERT(size <= vio_size, "specified size %d is not greater than allocated %d", ++ size, vio_size) != VDO_SUCCESS) ++ size = vio_size; ++ vio->io_size = size; + offset = offset_in_page(data); +- bvec_count = DIV_ROUND_UP(offset + len, PAGE_SIZE); ++ bvec_count = DIV_ROUND_UP(offset + size, PAGE_SIZE); ++ remaining = size; + +- /* +- * If we knew that data was always on one page, or contiguous pages, we wouldn't need the +- * loop. But if we're using vmalloc, it's not impossible that the data is in different +- * pages that can't be merged in bio_add_page... +- */ +- for (i = 0; (i < bvec_count) && (len > 0); i++) { ++ for (i = 0; (i < bvec_count) && (remaining > 0); i++) { + struct page *page; + int bytes_added; + int bytes = PAGE_SIZE - offset; + +- if (bytes > len) +- bytes = len; ++ if (bytes > remaining) ++ bytes = remaining; + + page = is_vmalloc_addr(data) ? vmalloc_to_page(data) : virt_to_page(data); + bytes_added = bio_add_page(bio, page, bytes, offset); +@@ -231,7 +239,7 @@ int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback, + } + + data += bytes; +- len -= bytes; ++ remaining -= bytes; + offset = 0; + } + +diff --git a/drivers/md/dm-vdo/vio.h b/drivers/md/dm-vdo/vio.h +index 3490e9f59b04a..74e8fd7c8c029 100644 +--- a/drivers/md/dm-vdo/vio.h ++++ b/drivers/md/dm-vdo/vio.h +@@ -123,6 +123,8 @@ void vdo_set_bio_properties(struct bio *bio, struct vio *vio, bio_end_io_t callb + + int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback, + blk_opf_t bi_opf, physical_block_number_t pbn); ++int vio_reset_bio_with_size(struct vio *vio, char *data, int size, bio_end_io_t callback, ++ blk_opf_t bi_opf, physical_block_number_t pbn); + + void update_vio_error_stats(struct vio *vio, const char *format, ...) + __printf(2, 3); +-- +2.39.5 + diff --git a/queue-6.12/dma-mapping-avoid-potential-unused-data-compilation-.patch b/queue-6.12/dma-mapping-avoid-potential-unused-data-compilation-.patch new file mode 100644 index 0000000000..bd754f98fc --- /dev/null +++ b/queue-6.12/dma-mapping-avoid-potential-unused-data-compilation-.patch @@ -0,0 +1,50 @@ +From ce99cfd11c6f65658876d9cdaa5fa897d301669e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Apr 2025 09:56:59 +0200 +Subject: dma-mapping: avoid potential unused data compilation warning + +From: Marek Szyprowski + +[ Upstream commit c9b19ea63036fc537a69265acea1b18dabd1cbd3 ] + +When CONFIG_NEED_DMA_MAP_STATE is not defined, dma-mapping clients might +report unused data compilation warnings for dma_unmap_*() calls +arguments. Redefine macros for those calls to let compiler to notice that +it is okay when the provided arguments are not used. + +Reported-by: Andy Shevchenko +Suggested-by: Jakub Kicinski +Signed-off-by: Marek Szyprowski +Tested-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20250415075659.428549-1-m.szyprowski@samsung.com +Signed-off-by: Sasha Levin +--- + include/linux/dma-mapping.h | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h +index 1524da363734a..22b9099927fad 100644 +--- a/include/linux/dma-mapping.h ++++ b/include/linux/dma-mapping.h +@@ -633,10 +633,14 @@ static inline int dma_mmap_wc(struct device *dev, + #else + #define DEFINE_DMA_UNMAP_ADDR(ADDR_NAME) + #define DEFINE_DMA_UNMAP_LEN(LEN_NAME) +-#define dma_unmap_addr(PTR, ADDR_NAME) (0) +-#define dma_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0) +-#define dma_unmap_len(PTR, LEN_NAME) (0) +-#define dma_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) ++#define dma_unmap_addr(PTR, ADDR_NAME) \ ++ ({ typeof(PTR) __p __maybe_unused = PTR; 0; }) ++#define dma_unmap_addr_set(PTR, ADDR_NAME, VAL) \ ++ do { typeof(PTR) __p __maybe_unused = PTR; } while (0) ++#define dma_unmap_len(PTR, LEN_NAME) \ ++ ({ typeof(PTR) __p __maybe_unused = PTR; 0; }) ++#define dma_unmap_len_set(PTR, LEN_NAME, VAL) \ ++ do { typeof(PTR) __p __maybe_unused = PTR; } while (0) + #endif + + #endif /* _LINUX_DMA_MAPPING_H */ +-- +2.39.5 + diff --git a/queue-6.12/dma-mapping-fix-warning-reported-for-missing-prototy.patch b/queue-6.12/dma-mapping-fix-warning-reported-for-missing-prototy.patch new file mode 100644 index 0000000000..54b3990536 --- /dev/null +++ b/queue-6.12/dma-mapping-fix-warning-reported-for-missing-prototy.patch @@ -0,0 +1,66 @@ +From 14a4bcd5edb19a2180a15e62dd54be3dc3cf9c8e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Apr 2025 21:40:34 +1000 +Subject: dma-mapping: Fix warning reported for missing prototype + +From: Balbir Singh + +[ Upstream commit cae5572ec9261f752af834cdaaf5a0ba0afcf256 ] + +lkp reported a warning about missing prototype for a recent patch. + +The kernel-doc style comments are out of sync, move them to the right +function. + +Cc: Marek Szyprowski +Cc: Christoph Hellwig + +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202504190615.g9fANxHw-lkp@intel.com/ + +Signed-off-by: Balbir Singh +[mszyprow: reformatted subject] +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20250422114034.3535515-1-balbirs@nvidia.com +Signed-off-by: Sasha Levin +--- + kernel/dma/mapping.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c +index f7366083b4d00..74d453ec750a1 100644 +--- a/kernel/dma/mapping.c ++++ b/kernel/dma/mapping.c +@@ -897,14 +897,6 @@ int dma_set_coherent_mask(struct device *dev, u64 mask) + } + EXPORT_SYMBOL(dma_set_coherent_mask); + +-/** +- * dma_addressing_limited - return if the device is addressing limited +- * @dev: device to check +- * +- * Return %true if the devices DMA mask is too small to address all memory in +- * the system, else %false. Lack of addressing bits is the prime reason for +- * bounce buffering, but might not be the only one. +- */ + static bool __dma_addressing_limited(struct device *dev) + { + const struct dma_map_ops *ops = get_dma_ops(dev); +@@ -918,6 +910,14 @@ static bool __dma_addressing_limited(struct device *dev) + return !dma_direct_all_ram_mapped(dev); + } + ++/** ++ * dma_addressing_limited - return if the device is addressing limited ++ * @dev: device to check ++ * ++ * Return %true if the devices DMA mask is too small to address all memory in ++ * the system, else %false. Lack of addressing bits is the prime reason for ++ * bounce buffering, but might not be the only one. ++ */ + bool dma_addressing_limited(struct device *dev) + { + if (!__dma_addressing_limited(dev)) +-- +2.39.5 + diff --git a/queue-6.12/dma-mapping.c-dev_dbg-support-for-dma_addressing_lim.patch b/queue-6.12/dma-mapping.c-dev_dbg-support-for-dma_addressing_lim.patch new file mode 100644 index 0000000000..d902b8165f --- /dev/null +++ b/queue-6.12/dma-mapping.c-dev_dbg-support-for-dma_addressing_lim.patch @@ -0,0 +1,83 @@ +From 6320d70e8750f51317c26dd7dcbf1dc3dbd1d9fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Apr 2025 21:37:52 +1000 +Subject: dma/mapping.c: dev_dbg support for dma_addressing_limited +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Balbir Singh + +[ Upstream commit 2042c352e21d19eaf5f9e22fb6afce72293ef28c ] + +In the debug and resolution of an issue involving forced use of bounce +buffers, 7170130e4c72 ("x86/mm/init: Handle the special case of device +private pages in add_pages(), to not increase max_pfn and trigger +dma_addressing_limited() bounce buffers"). It would have been easier +to debug the issue if dma_addressing_limited() had debug information +about the device not being able to address all of memory and thus forcing +all accesses through a bounce buffer. Please see[2] + +Implement dev_dbg to debug the potential use of bounce buffers +when we hit the condition. When swiotlb is used, +dma_addressing_limited() is used to determine the size of maximum dma +buffer size in dma_direct_max_mapping_size(). The debug prints could be +triggered in that check as well (when enabled). + +Link: https://lore.kernel.org/lkml/20250401000752.249348-1-balbirs@nvidia.com/ [1] +Link: https://lore.kernel.org/lkml/20250310112206.4168-1-spasswolf@web.de/ [2] + +Cc: Marek Szyprowski +Cc: Robin Murphy +Cc: "Christian König" +Cc: Ingo Molnar +Cc: Kees Cook +Cc: Bjorn Helgaas +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Andy Lutomirski +Cc: Alex Deucher +Cc: Bert Karwatzki +Cc: Christoph Hellwig + +Signed-off-by: Balbir Singh +Reviewed-by: Christoph Hellwig +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20250414113752.3298276-1-balbirs@nvidia.com +Signed-off-by: Sasha Levin +--- + kernel/dma/mapping.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c +index 864a1121bf086..f7366083b4d00 100644 +--- a/kernel/dma/mapping.c ++++ b/kernel/dma/mapping.c +@@ -905,7 +905,7 @@ EXPORT_SYMBOL(dma_set_coherent_mask); + * the system, else %false. Lack of addressing bits is the prime reason for + * bounce buffering, but might not be the only one. + */ +-bool dma_addressing_limited(struct device *dev) ++static bool __dma_addressing_limited(struct device *dev) + { + const struct dma_map_ops *ops = get_dma_ops(dev); + +@@ -917,6 +917,15 @@ bool dma_addressing_limited(struct device *dev) + return false; + return !dma_direct_all_ram_mapped(dev); + } ++ ++bool dma_addressing_limited(struct device *dev) ++{ ++ if (!__dma_addressing_limited(dev)) ++ return false; ++ ++ dev_dbg(dev, "device is DMA addressing limited\n"); ++ return true; ++} + EXPORT_SYMBOL_GPL(dma_addressing_limited); + + size_t dma_max_mapping_size(struct device *dev) +-- +2.39.5 + diff --git a/queue-6.12/dpll-add-an-assertion-to-check-freq_supported_num.patch b/queue-6.12/dpll-add-an-assertion-to-check-freq_supported_num.patch new file mode 100644 index 0000000000..33fdc867d3 --- /dev/null +++ b/queue-6.12/dpll-add-an-assertion-to-check-freq_supported_num.patch @@ -0,0 +1,43 @@ +From 88e379a687f56f3f051b7b0ccc61583144761644 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 15:02:10 +0000 +Subject: dpll: Add an assertion to check freq_supported_num + +From: Jiasheng Jiang + +[ Upstream commit 39e912a959c19338855b768eaaee2917d7841f71 ] + +Since the driver is broken in the case that src->freq_supported is not +NULL but src->freq_supported_num is 0, add an assertion for it. + +Signed-off-by: Jiasheng Jiang +Reviewed-by: Jiri Pirko +Reviewed-by: Vadim Fedorenko +Reviewed-by: Arkadiusz Kubalewski +Link: https://patch.msgid.link/20250228150210.34404-1-jiashengjiangcool@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/dpll/dpll_core.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c +index 1877201d1aa9f..20bdc52f63a50 100644 +--- a/drivers/dpll/dpll_core.c ++++ b/drivers/dpll/dpll_core.c +@@ -443,8 +443,11 @@ static void dpll_pin_prop_free(struct dpll_pin_properties *prop) + static int dpll_pin_prop_dup(const struct dpll_pin_properties *src, + struct dpll_pin_properties *dst) + { ++ if (WARN_ON(src->freq_supported && !src->freq_supported_num)) ++ return -EINVAL; ++ + memcpy(dst, src, sizeof(*dst)); +- if (src->freq_supported && src->freq_supported_num) { ++ if (src->freq_supported) { + size_t freq_size = src->freq_supported_num * + sizeof(*src->freq_supported); + dst->freq_supported = kmemdup(src->freq_supported, +-- +2.39.5 + diff --git a/queue-6.12/dql-fix-dql-limit-value-when-reset.patch b/queue-6.12/dql-fix-dql-limit-value-when-reset.patch new file mode 100644 index 0000000000..be77e11152 --- /dev/null +++ b/queue-6.12/dql-fix-dql-limit-value-when-reset.patch @@ -0,0 +1,46 @@ +From 130f8cb61ed4cdff36578a7b2dacaca00d65d024 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 16:57:51 +0800 +Subject: dql: Fix dql->limit value when reset. + +From: Jing Su + +[ Upstream commit 3a17f23f7c36bac3a3584aaf97d3e3e0b2790396 ] + +Executing dql_reset after setting a non-zero value for limit_min can +lead to an unreasonable situation where dql->limit is less than +dql->limit_min. + +For instance, after setting +/sys/class/net/eth*/queues/tx-0/byte_queue_limits/limit_min, +an ifconfig down/up operation might cause the ethernet driver to call +netdev_tx_reset_queue, which in turn invokes dql_reset. + +In this case, dql->limit is reset to 0 while dql->limit_min remains +non-zero value, which is unexpected. The limit should always be +greater than or equal to limit_min. + +Signed-off-by: Jing Su +Link: https://patch.msgid.link/Z9qHD1s/NEuQBdgH@pilot-ThinkCentre-M930t-N000 +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + lib/dynamic_queue_limits.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/dynamic_queue_limits.c b/lib/dynamic_queue_limits.c +index e49deddd3de9f..7d1dfbb99b397 100644 +--- a/lib/dynamic_queue_limits.c ++++ b/lib/dynamic_queue_limits.c +@@ -190,7 +190,7 @@ EXPORT_SYMBOL(dql_completed); + void dql_reset(struct dql *dql) + { + /* Reset all dynamic values */ +- dql->limit = 0; ++ dql->limit = dql->min_limit; + dql->num_queued = 0; + dql->num_completed = 0; + dql->last_obj_cnt = 0; +-- +2.39.5 + diff --git a/queue-6.12/drm-add-valid-clones-check.patch b/queue-6.12/drm-add-valid-clones-check.patch new file mode 100644 index 0000000000..5b28ac4dbe --- /dev/null +++ b/queue-6.12/drm-add-valid-clones-check.patch @@ -0,0 +1,70 @@ +From d08c0e9f3594b4b54686440002e51986a7db1bca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Dec 2024 16:43:14 -0800 +Subject: drm: Add valid clones check + +From: Jessica Zhang + +[ Upstream commit 41b4b11da02157c7474caf41d56baae0e941d01a ] + +Check that all encoders attached to a given CRTC are valid +possible_clones of each other. + +Signed-off-by: Jessica Zhang +Reviewed-by: Maxime Ripard +Link: https://patchwork.freedesktop.org/patch/msgid/20241216-concurrent-wb-v4-3-fe220297a7f0@quicinc.com +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/drm_atomic_helper.c | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c +index 32902f77f00dd..40e4e1b6c9110 100644 +--- a/drivers/gpu/drm/drm_atomic_helper.c ++++ b/drivers/gpu/drm/drm_atomic_helper.c +@@ -574,6 +574,30 @@ mode_valid(struct drm_atomic_state *state) + return 0; + } + ++static int drm_atomic_check_valid_clones(struct drm_atomic_state *state, ++ struct drm_crtc *crtc) ++{ ++ struct drm_encoder *drm_enc; ++ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, ++ crtc); ++ ++ drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) { ++ if (!drm_enc->possible_clones) { ++ DRM_DEBUG("enc%d possible_clones is 0\n", drm_enc->base.id); ++ continue; ++ } ++ ++ if ((crtc_state->encoder_mask & drm_enc->possible_clones) != ++ crtc_state->encoder_mask) { ++ DRM_DEBUG("crtc%d failed valid clone check for mask 0x%x\n", ++ crtc->base.id, crtc_state->encoder_mask); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ + /** + * drm_atomic_helper_check_modeset - validate state object for modeset changes + * @dev: DRM device +@@ -745,6 +769,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, + ret = drm_atomic_add_affected_planes(state, crtc); + if (ret != 0) + return ret; ++ ++ ret = drm_atomic_check_valid_clones(state, crtc); ++ if (ret != 0) ++ return ret; + } + + /* +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-add-support-for-disconnected-edp-str.patch b/queue-6.12/drm-amd-display-add-support-for-disconnected-edp-str.patch new file mode 100644 index 0000000000..38564a34b1 --- /dev/null +++ b/queue-6.12/drm-amd-display-add-support-for-disconnected-edp-str.patch @@ -0,0 +1,54 @@ +From 86c790ff507728161ab46200dec60f28319c1217 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 13:46:53 -0500 +Subject: drm/amd/display: Add support for disconnected eDP streams + +From: Harry VanZyllDeJong + +[ Upstream commit 6571bef25fe48c642f7a69ccf7c3198b317c136a ] + +[Why] +eDP may not be connected to the GPU on driver start causing +fail enumeration. + +[How] +Move the virtual signal type check before the eDP connector +signal check. + +Reviewed-by: Wenjing Liu +Signed-off-by: Harry VanZyllDeJong +Signed-off-by: Roman Li +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../drm/amd/display/dc/link/protocols/link_dp_capability.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +index 23e650e39910e..d9a1e1a599674 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +@@ -945,6 +945,9 @@ bool link_decide_link_settings(struct dc_stream_state *stream, + * TODO: add MST specific link training routine + */ + decide_mst_link_settings(link, link_setting); ++ } else if (stream->signal == SIGNAL_TYPE_VIRTUAL) { ++ link_setting->lane_count = LANE_COUNT_FOUR; ++ link_setting->link_rate = LINK_RATE_HIGH3; + } else if (link->connector_signal == SIGNAL_TYPE_EDP) { + /* enable edp link optimization for DSC eDP case */ + if (stream->timing.flags.DSC) { +@@ -967,9 +970,6 @@ bool link_decide_link_settings(struct dc_stream_state *stream, + } else { + edp_decide_link_settings(link, link_setting, req_bw); + } +- } else if (stream->signal == SIGNAL_TYPE_VIRTUAL) { +- link_setting->lane_count = LANE_COUNT_FOUR; +- link_setting->link_rate = LINK_RATE_HIGH3; + } else { + decide_dp_link_settings(link, link_setting, req_bw); + } +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-calculate-the-remain-segments-for-al.patch b/queue-6.12/drm-amd-display-calculate-the-remain-segments-for-al.patch new file mode 100644 index 0000000000..4d57ba6eb9 --- /dev/null +++ b/queue-6.12/drm-amd-display-calculate-the-remain-segments-for-al.patch @@ -0,0 +1,95 @@ +From 1fb20f39e04b7295a80f8a1687b077c5a90ce3be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 20:09:14 +0800 +Subject: drm/amd/display: calculate the remain segments for all pipes + +From: Zhikai Zhai + +[ Upstream commit d3069feecdb5542604d29b59acfd1fd213bad95b ] + +[WHY] +In some cases the remain de-tile buffer segments will be greater +than zero if we don't add the non-top pipe to calculate, at +this time the override de-tile buffer size will be valid and used. +But it makes the de-tile buffer segments used finally for all of pipes +exceed the maximum. + +[HOW] +Add the non-top pipe to calculate the remain de-tile buffer segments. +Don't set override size to use the average according to pipe count +if the value exceed the maximum. + +Reviewed-by: Charlene Liu +Signed-off-by: Zhikai Zhai +Signed-off-by: Tom Chung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../dc/resource/dcn315/dcn315_resource.c | 42 +++++++++---------- + 1 file changed, 20 insertions(+), 22 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c +index f2ce687c0e03c..9cb72805b8d1a 100644 +--- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c +@@ -1699,7 +1699,7 @@ static int dcn315_populate_dml_pipes_from_context( + pipes[pipe_cnt].dout.dsc_input_bpc = 0; + DC_FP_START(); + dcn31_zero_pipe_dcc_fraction(pipes, pipe_cnt); +- if (pixel_rate_crb && !pipe->top_pipe && !pipe->prev_odm_pipe) { ++ if (pixel_rate_crb) { + int bpp = source_format_to_bpp(pipes[pipe_cnt].pipe.src.source_format); + /* Ceil to crb segment size */ + int approx_det_segs_required_for_pstate = dcn_get_approx_det_segs_required_for_pstate( +@@ -1756,28 +1756,26 @@ static int dcn315_populate_dml_pipes_from_context( + continue; + } + +- if (!pipe->top_pipe && !pipe->prev_odm_pipe) { +- bool split_required = pipe->stream->timing.pix_clk_100hz >= dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc) +- || (pipe->plane_state && pipe->plane_state->src_rect.width > 5120); +- +- if (remaining_det_segs > MIN_RESERVED_DET_SEGS && crb_pipes != 0) +- pipes[pipe_cnt].pipe.src.det_size_override += (remaining_det_segs - MIN_RESERVED_DET_SEGS) / crb_pipes + +- (crb_idx < (remaining_det_segs - MIN_RESERVED_DET_SEGS) % crb_pipes ? 1 : 0); +- if (pipes[pipe_cnt].pipe.src.det_size_override > 2 * DCN3_15_MAX_DET_SEGS) { +- /* Clamp to 2 pipe split max det segments */ +- remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override - 2 * (DCN3_15_MAX_DET_SEGS); +- pipes[pipe_cnt].pipe.src.det_size_override = 2 * DCN3_15_MAX_DET_SEGS; +- } +- if (pipes[pipe_cnt].pipe.src.det_size_override > DCN3_15_MAX_DET_SEGS || split_required) { +- /* If we are splitting we must have an even number of segments */ +- remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override % 2; +- pipes[pipe_cnt].pipe.src.det_size_override -= pipes[pipe_cnt].pipe.src.det_size_override % 2; +- } +- /* Convert segments into size for DML use */ +- pipes[pipe_cnt].pipe.src.det_size_override *= DCN3_15_CRB_SEGMENT_SIZE_KB; +- +- crb_idx++; ++ bool split_required = pipe->stream->timing.pix_clk_100hz >= dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc) ++ || (pipe->plane_state && pipe->plane_state->src_rect.width > 5120); ++ ++ if (remaining_det_segs > MIN_RESERVED_DET_SEGS && crb_pipes != 0) ++ pipes[pipe_cnt].pipe.src.det_size_override += (remaining_det_segs - MIN_RESERVED_DET_SEGS) / crb_pipes + ++ (crb_idx < (remaining_det_segs - MIN_RESERVED_DET_SEGS) % crb_pipes ? 1 : 0); ++ if (pipes[pipe_cnt].pipe.src.det_size_override > 2 * DCN3_15_MAX_DET_SEGS) { ++ /* Clamp to 2 pipe split max det segments */ ++ remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override - 2 * (DCN3_15_MAX_DET_SEGS); ++ pipes[pipe_cnt].pipe.src.det_size_override = 2 * DCN3_15_MAX_DET_SEGS; ++ } ++ if (pipes[pipe_cnt].pipe.src.det_size_override > DCN3_15_MAX_DET_SEGS || split_required) { ++ /* If we are splitting we must have an even number of segments */ ++ remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override % 2; ++ pipes[pipe_cnt].pipe.src.det_size_override -= pipes[pipe_cnt].pipe.src.det_size_override % 2; + } ++ /* Convert segments into size for DML use */ ++ pipes[pipe_cnt].pipe.src.det_size_override *= DCN3_15_CRB_SEGMENT_SIZE_KB; ++ ++ crb_idx++; + pipe_cnt++; + } + } +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-call-fp-protect-before-mode-programm.patch b/queue-6.12/drm-amd-display-call-fp-protect-before-mode-programm.patch new file mode 100644 index 0000000000..1ba8fd2171 --- /dev/null +++ b/queue-6.12/drm-amd-display-call-fp-protect-before-mode-programm.patch @@ -0,0 +1,73 @@ +From 8cb706f2b39883f31b872b30211e6606e6764ae2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 10:24:29 -0400 +Subject: drm/amd/display: Call FP Protect Before Mode Programming/Mode Support + +From: Austin Zheng + +[ Upstream commit eba692ca3abca258b3214a6e4126afefad1822f0 ] + +[Why] +Memory allocation occurs within dml21_validate() for adding phantom planes. +May cause kernel to be tainted due to usage of FP Start. + +[How] +Move FP start from dml21_validate to before mode programming/mode support. +Calculations requiring floating point are all done within mode programming +or mode support. + +Reviewed-by: Alvin Lee +Signed-off-by: Austin Zheng +Signed-off-by: Ray Wu +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +(cherry picked from commit fe3250f10819b411808ab9ae1d824c5fc9b59170) +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c +index e3e4f40bd4123..dcbe327209d5d 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c ++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c +@@ -221,7 +221,9 @@ static bool dml21_mode_check_and_programming(const struct dc *in_dc, struct dc_s + if (!result) + return false; + ++ DC_FP_START(); + result = dml2_build_mode_programming(mode_programming); ++ DC_FP_END(); + if (!result) + return false; + +@@ -271,7 +273,9 @@ static bool dml21_check_mode_support(const struct dc *in_dc, struct dc_state *co + mode_support->dml2_instance = dml_init->dml2_instance; + dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx); + dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params.programming = dml_ctx->v21.mode_programming.programming; ++ DC_FP_START(); + is_supported = dml2_check_mode_supported(mode_support); ++ DC_FP_END(); + if (!is_supported) + return false; + +@@ -282,16 +286,12 @@ bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml + { + bool out = false; + +- DC_FP_START(); +- + /* Use dml_validate_only for fast_validate path */ + if (fast_validate) + out = dml21_check_mode_support(in_dc, context, dml_ctx); + else + out = dml21_mode_check_and_programming(in_dc, context, dml_ctx); + +- DC_FP_END(); +- + return out; + } + +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-configure-dtbclk_p-with-optc-only-fo.patch b/queue-6.12/drm-amd-display-configure-dtbclk_p-with-optc-only-fo.patch new file mode 100644 index 0000000000..8021fd4604 --- /dev/null +++ b/queue-6.12/drm-amd-display-configure-dtbclk_p-with-optc-only-fo.patch @@ -0,0 +1,246 @@ +From 1cc31c01ebca4f0e1a47275f332d2fffbda3125e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Sep 2024 16:56:20 -0400 +Subject: drm/amd/display: Configure DTBCLK_P with OPTC only for dcn401 + +From: Dillon Varone + +[ Upstream commit 3c6c8d1a1e3f033f1abf84d6d54c268c35b0fcdd ] + +[WHY] +DTBCLK_P is used to generate virtual pixel clock, and to drive the HPO +stream encoder clock. Programming the required clock when +enabling/disabling both components can cause issues. +For example, if HPO is being disabled and clock source is changed to +REFCLK, virtual pixel rate will then be wrong, causing issues in CRTC. + +[HOW] +Only program the DTBCLK_P when programming CRTC, as its expected it will +be enabled prior to HPO, and disabled after HPO in all valid cases. + +Reviewed-by: Alvin Lee +Signed-off-by: Dillon Varone +Signed-off-by: Fangzhi Zuo +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Stable-dep-of: 874697e12793 ("drm/amd/display: Defer BW-optimization-blocked DRR adjustments") +Signed-off-by: Sasha Levin +--- + .../amd/display/dc/dccg/dcn401/dcn401_dccg.c | 3 - + .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 135 +++++++++++++++++- + .../amd/display/dc/hwss/dcn401/dcn401_hwseq.h | 7 + + .../amd/display/dc/hwss/dcn401/dcn401_init.c | 4 +- + 4 files changed, 142 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c +index 0b889004509ad..62402c7be0a5e 100644 +--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c ++++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c +@@ -580,9 +580,6 @@ static void dccg401_set_dpstreamclk( + int otg_inst, + int dp_hpo_inst) + { +- /* set the dtbclk_p source */ +- dccg401_set_dtbclk_p_src(dccg, src, otg_inst); +- + /* enabled to select one of the DTBCLKs for pipe */ + if (src == REFCLK) + dccg401_disable_dpstreamclk(dccg, dp_hpo_inst); +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +index 62f1e597787e6..b6b333a2461f8 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +@@ -844,6 +844,13 @@ enum dc_status dcn401_enable_stream_timing( + odm_slice_width, last_odm_slice_width); + } + ++ /* set DTBCLK_P */ ++ if (dc->res_pool->dccg->funcs->set_dtbclk_p_src) { ++ if (dc_is_dp_signal(stream->signal) || dc_is_virtual_signal(stream->signal)) { ++ dc->res_pool->dccg->funcs->set_dtbclk_p_src(dc->res_pool->dccg, DPREFCLK, pipe_ctx->stream_res.tg->inst); ++ } ++ } ++ + /* HW program guide assume display already disable + * by unplug sequence. OTG assume stop. + */ +@@ -1007,8 +1014,6 @@ void dcn401_enable_stream(struct pipe_ctx *pipe_ctx) + dccg->funcs->enable_symclk32_se(dccg, dp_hpo_inst, phyd32clk); + } + } else { +- /* need to set DTBCLK_P source to DPREFCLK for DP8B10B */ +- dccg->funcs->set_dtbclk_p_src(dccg, DPREFCLK, tg->inst); + dccg->funcs->enable_symclk_se(dccg, stream_enc->stream_enc_inst, + link_enc->transmitter - TRANSMITTER_UNIPHY_A); + } +@@ -1773,3 +1778,129 @@ void dcn401_program_outstanding_updates(struct dc *dc, + if (hubbub->funcs->program_compbuf_segments) + hubbub->funcs->program_compbuf_segments(hubbub, context->bw_ctx.bw.dcn.arb_regs.compbuf_size, true); + } ++ ++void dcn401_reset_back_end_for_pipe( ++ struct dc *dc, ++ struct pipe_ctx *pipe_ctx, ++ struct dc_state *context) ++{ ++ int i; ++ struct dc_link *link = pipe_ctx->stream->link; ++ const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); ++ ++ DC_LOGGER_INIT(dc->ctx->logger); ++ if (pipe_ctx->stream_res.stream_enc == NULL) { ++ pipe_ctx->stream = NULL; ++ return; ++ } ++ ++ /* DPMS may already disable or */ ++ /* dpms_off status is incorrect due to fastboot ++ * feature. When system resume from S4 with second ++ * screen only, the dpms_off would be true but ++ * VBIOS lit up eDP, so check link status too. ++ */ ++ if (!pipe_ctx->stream->dpms_off || link->link_status.link_active) ++ dc->link_srv->set_dpms_off(pipe_ctx); ++ else if (pipe_ctx->stream_res.audio) ++ dc->hwss.disable_audio_stream(pipe_ctx); ++ ++ /* free acquired resources */ ++ if (pipe_ctx->stream_res.audio) { ++ /*disable az_endpoint*/ ++ pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); ++ ++ /*free audio*/ ++ if (dc->caps.dynamic_audio == true) { ++ /*we have to dynamic arbitrate the audio endpoints*/ ++ /*we free the resource, need reset is_audio_acquired*/ ++ update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, ++ pipe_ctx->stream_res.audio, false); ++ pipe_ctx->stream_res.audio = NULL; ++ } ++ } ++ ++ /* by upper caller loop, parent pipe: pipe0, will be reset last. ++ * back end share by all pipes and will be disable only when disable ++ * parent pipe. ++ */ ++ if (pipe_ctx->top_pipe == NULL) { ++ ++ dc->hwss.set_abm_immediate_disable(pipe_ctx); ++ ++ pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg); ++ ++ pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false); ++ if (pipe_ctx->stream_res.tg->funcs->set_odm_bypass) ++ pipe_ctx->stream_res.tg->funcs->set_odm_bypass( ++ pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing); ++ ++ if (pipe_ctx->stream_res.tg->funcs->set_drr) ++ pipe_ctx->stream_res.tg->funcs->set_drr( ++ pipe_ctx->stream_res.tg, NULL); ++ /* TODO - convert symclk_ref_cnts for otg to a bit map to solve ++ * the case where the same symclk is shared across multiple otg ++ * instances ++ */ ++ if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) ++ link->phy_state.symclk_ref_cnts.otg = 0; ++ if (link->phy_state.symclk_state == SYMCLK_ON_TX_OFF) { ++ link_hwss->disable_link_output(link, ++ &pipe_ctx->link_res, pipe_ctx->stream->signal); ++ link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF; ++ } ++ ++ /* reset DTBCLK_P */ ++ if (dc->res_pool->dccg->funcs->set_dtbclk_p_src) ++ dc->res_pool->dccg->funcs->set_dtbclk_p_src(dc->res_pool->dccg, REFCLK, pipe_ctx->stream_res.tg->inst); ++ } ++ ++ for (i = 0; i < dc->res_pool->pipe_count; i++) ++ if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx) ++ break; ++ ++ if (i == dc->res_pool->pipe_count) ++ return; ++ ++/* ++ * In case of a dangling plane, setting this to NULL unconditionally ++ * causes failures during reset hw ctx where, if stream is NULL, ++ * it is expected that the pipe_ctx pointers to pipes and plane are NULL. ++ */ ++ pipe_ctx->stream = NULL; ++ DC_LOG_DEBUG("Reset back end for pipe %d, tg:%d\n", ++ pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst); ++} ++ ++void dcn401_reset_hw_ctx_wrap( ++ struct dc *dc, ++ struct dc_state *context) ++{ ++ int i; ++ struct dce_hwseq *hws = dc->hwseq; ++ ++ /* Reset Back End*/ ++ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { ++ struct pipe_ctx *pipe_ctx_old = ++ &dc->current_state->res_ctx.pipe_ctx[i]; ++ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; ++ ++ if (!pipe_ctx_old->stream) ++ continue; ++ ++ if (pipe_ctx_old->top_pipe || pipe_ctx_old->prev_odm_pipe) ++ continue; ++ ++ if (!pipe_ctx->stream || ++ pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { ++ struct clock_source *old_clk = pipe_ctx_old->clock_source; ++ ++ if (hws->funcs.reset_back_end_for_pipe) ++ hws->funcs.reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state); ++ if (hws->funcs.enable_stream_gating) ++ hws->funcs.enable_stream_gating(dc, pipe_ctx_old); ++ if (old_clk) ++ old_clk->funcs->cs_power_down(old_clk); ++ } ++ } ++} +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h +index a27e62081685d..6256429c8a4f6 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h +@@ -84,4 +84,11 @@ void adjust_hotspot_between_slices_for_2x_magnify(uint32_t cursor_width, struct + void dcn401_wait_for_det_buffer_update(struct dc *dc, struct dc_state *context, struct pipe_ctx *otg_master); + void dcn401_interdependent_update_lock(struct dc *dc, struct dc_state *context, bool lock); + void dcn401_program_outstanding_updates(struct dc *dc, struct dc_state *context); ++void dcn401_reset_back_end_for_pipe( ++ struct dc *dc, ++ struct pipe_ctx *pipe_ctx, ++ struct dc_state *context); ++void dcn401_reset_hw_ctx_wrap( ++ struct dc *dc, ++ struct dc_state *context); + #endif /* __DC_HWSS_DCN401_H__ */ +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c +index a2ca07235c83d..d6f36b8e1a261 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c +@@ -111,7 +111,7 @@ static const struct hwseq_private_funcs dcn401_private_funcs = { + .power_down = dce110_power_down, + .enable_display_power_gating = dcn10_dummy_display_power_gating, + .blank_pixel_data = dcn20_blank_pixel_data, +- .reset_hw_ctx_wrap = dcn20_reset_hw_ctx_wrap, ++ .reset_hw_ctx_wrap = dcn401_reset_hw_ctx_wrap, + .enable_stream_timing = dcn401_enable_stream_timing, + .edp_backlight_control = dce110_edp_backlight_control, + .setup_vupdate_interrupt = dcn20_setup_vupdate_interrupt, +@@ -136,7 +136,7 @@ static const struct hwseq_private_funcs dcn401_private_funcs = { + .update_mall_sel = dcn32_update_mall_sel, + .calculate_dccg_k1_k2_values = NULL, + .apply_single_controller_ctx_to_hw = dce110_apply_single_controller_ctx_to_hw, +- .reset_back_end_for_pipe = dcn20_reset_back_end_for_pipe, ++ .reset_back_end_for_pipe = dcn401_reset_back_end_for_pipe, + .populate_mcm_luts = NULL, + }; + +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-correct-timing_adjust_pending-flag-s.patch b/queue-6.12/drm-amd-display-correct-timing_adjust_pending-flag-s.patch new file mode 100644 index 0000000000..40565892db --- /dev/null +++ b/queue-6.12/drm-amd-display-correct-timing_adjust_pending-flag-s.patch @@ -0,0 +1,45 @@ +From c0a4bd92d11ff331af2a8eacfd9791a794fd19bc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 10:35:23 +0800 +Subject: drm/amd/display: Correct timing_adjust_pending flag setting. + +From: Zhongwei Zhang + +[ Upstream commit 34935701b7ed1a1ef449310ba041f10964b23cf4 ] + +[Why&How] +stream->adjust will be overwritten by update->crtc_timing_adjust. +We should set update->crtc_timing_adjust->timing_adjust_pending +and then overwrite stream->adjust. +Reset update->crtc_timing_adjust->timing_adjust_pending after +the assignment. + +Reviewed-by: Charlene Liu +Signed-off-by: Zhongwei Zhang +Signed-off-by: Tom Chung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Stable-dep-of: 874697e12793 ("drm/amd/display: Defer BW-optimization-blocked DRR adjustments") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index 3392746f1d420..a76e6fc3fef78 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -2979,8 +2979,9 @@ static void copy_stream_update_to_stream(struct dc *dc, + if (update->crtc_timing_adjust) { + if (stream->adjust.v_total_min != update->crtc_timing_adjust->v_total_min || + stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max) +- stream->adjust.timing_adjust_pending = true; ++ update->crtc_timing_adjust->timing_adjust_pending = true; + stream->adjust = *update->crtc_timing_adjust; ++ update->crtc_timing_adjust->timing_adjust_pending = false; + } + + if (update->dpms_off) +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-defer-bw-optimization-blocked-drr-ad.patch b/queue-6.12/drm-amd-display-defer-bw-optimization-blocked-drr-ad.patch new file mode 100644 index 0000000000..dc772abcef --- /dev/null +++ b/queue-6.12/drm-amd-display-defer-bw-optimization-blocked-drr-ad.patch @@ -0,0 +1,75 @@ +From 09311399ac2354796639e4ea2e411018ec43a3d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Apr 2025 02:54:26 -0400 +Subject: drm/amd/display: Defer BW-optimization-blocked DRR adjustments + +From: John Olender + +[ Upstream commit 874697e127931bf50a37ce9d96ee80f3a08a0c38 ] + +[Why & How] +Instead of dropping DRR updates, defer them. This fixes issues where +monitor continues to see incorrect refresh rate after VRR was turned off +by userspace. + +Fixes: 32953485c558 ("drm/amd/display: Do not update DRR while BW optimizations pending") +Link: https://gitlab.freedesktop.org/drm/amd/-/issues/3546 +Reviewed-by: Sun peng Li +Signed-off-by: John Olender +Signed-off-by: Aurabindo Pillai +Signed-off-by: Ray Wu +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +(cherry picked from commit 53761b7ecd83e6fbb9f2206f8c980a6aa308c844) +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++ + drivers/gpu/drm/amd/display/dc/core/dc.c | 10 +++++++--- + 2 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index ff33760aa4fae..17c03b89abb31 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -365,6 +365,8 @@ get_crtc_by_otg_inst(struct amdgpu_device *adev, + static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state, + struct dm_crtc_state *new_state) + { ++ if (new_state->stream->adjust.timing_adjust_pending) ++ return true; + if (new_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED) + return true; + else if (amdgpu_dm_crtc_vrr_active(old_state) != amdgpu_dm_crtc_vrr_active(new_state)) +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index a76e6fc3fef78..dd4b131fac6cb 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -438,9 +438,12 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, + * Don't adjust DRR while there's bandwidth optimizations pending to + * avoid conflicting with firmware updates. + */ +- if (dc->ctx->dce_version > DCE_VERSION_MAX) +- if (dc->optimized_required || dc->wm_optimized_required) ++ if (dc->ctx->dce_version > DCE_VERSION_MAX) { ++ if (dc->optimized_required || dc->wm_optimized_required) { ++ stream->adjust.timing_adjust_pending = true; + return false; ++ } ++ } + + dc_exit_ips_for_hw_access(dc); + +@@ -2978,7 +2981,8 @@ static void copy_stream_update_to_stream(struct dc *dc, + + if (update->crtc_timing_adjust) { + if (stream->adjust.v_total_min != update->crtc_timing_adjust->v_total_min || +- stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max) ++ stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max || ++ stream->adjust.timing_adjust_pending) + update->crtc_timing_adjust->timing_adjust_pending = true; + stream->adjust = *update->crtc_timing_adjust; + update->crtc_timing_adjust->timing_adjust_pending = false; +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-dm-drop-hw_support-check-in-amdgpu_d.patch b/queue-6.12/drm-amd-display-dm-drop-hw_support-check-in-amdgpu_d.patch new file mode 100644 index 0000000000..6f58dc0552 --- /dev/null +++ b/queue-6.12/drm-amd-display-dm-drop-hw_support-check-in-amdgpu_d.patch @@ -0,0 +1,34 @@ +From 54b8024e2aae7697c22674ae228d5dbeb103a8a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Dec 2024 09:25:18 -0500 +Subject: drm/amd/display/dm: drop hw_support check in amdgpu_dm_i2c_xfer() + +From: Alex Deucher + +[ Upstream commit 33da70bd1e115d7d73f45fb1c09f5ecc448f3f13 ] + +DC supports SW i2c as well. Drop the check. + +Reviewed-by: Harry Wentland +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 1e5984e71bfd7..09ef87c69230e 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -8288,7 +8288,7 @@ static int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, + int i; + int result = -EIO; + +- if (!ddc_service->ddc_pin || !ddc_service->ddc_pin->hw_info.hw_supported) ++ if (!ddc_service->ddc_pin) + return result; + + cmd.payloads = kcalloc(num, sizeof(struct i2c_payload), GFP_KERNEL); +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-do-not-enable-replay-when-vtotal-upd.patch b/queue-6.12/drm-amd-display-do-not-enable-replay-when-vtotal-upd.patch new file mode 100644 index 0000000000..7132d33db4 --- /dev/null +++ b/queue-6.12/drm-amd-display-do-not-enable-replay-when-vtotal-upd.patch @@ -0,0 +1,268 @@ +From 8f58bef6e9924af020e341fe2e2811e6bbac1ada Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 16:18:34 +0800 +Subject: drm/amd/display: Do not enable replay when vtotal update is pending. + +From: Danny Wang + +[ Upstream commit bd00b29b5f236dce677089319176dee5872b5a7a ] + +[Why&How] +Vtotal is not applied to HW when handling vsync interrupt. +Make sure vtotal is aligned before enable replay. + +Reviewed-by: Anthony Koo +Reviewed-by: Robin Chen +Signed-off-by: Danny Wang +Signed-off-by: Zhongwei Zhang +Signed-off-by: Tom Chung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Stable-dep-of: 874697e12793 ("drm/amd/display: Defer BW-optimization-blocked DRR adjustments") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 9 +++++++-- + .../gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 15 +++++++++++++++ + drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 1 + + .../drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 7 ++----- + .../drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 7 ++----- + .../drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 8 ++------ + .../drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c | 4 +--- + .../drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 3 +-- + .../drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 10 +++------- + .../gpu/drm/amd/display/dc/hwss/hw_sequencer.h | 6 ++++++ + 10 files changed, 40 insertions(+), 30 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index 216b525bd75e7..3392746f1d420 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -452,6 +452,7 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, + + if (dc->caps.max_v_total != 0 && + (adjust->v_total_max > dc->caps.max_v_total || adjust->v_total_min > dc->caps.max_v_total)) { ++ stream->adjust.timing_adjust_pending = false; + if (adjust->allow_otg_v_count_halt) + return set_long_vtotal(dc, stream, adjust); + else +@@ -465,7 +466,7 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, + dc->hwss.set_drr(&pipe, + 1, + *adjust); +- ++ stream->adjust.timing_adjust_pending = false; + return true; + } + } +@@ -2975,8 +2976,12 @@ static void copy_stream_update_to_stream(struct dc *dc, + if (update->vrr_active_fixed) + stream->vrr_active_fixed = *update->vrr_active_fixed; + +- if (update->crtc_timing_adjust) ++ if (update->crtc_timing_adjust) { ++ if (stream->adjust.v_total_min != update->crtc_timing_adjust->v_total_min || ++ stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max) ++ stream->adjust.timing_adjust_pending = true; + stream->adjust = *update->crtc_timing_adjust; ++ } + + if (update->dpms_off) + stream->dpms_off = *update->dpms_off; +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +index bb766c2a74176..fdcba960e1e6f 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +@@ -554,6 +554,21 @@ void set_p_state_switch_method( + } + } + ++void set_drr_and_clear_adjust_pending( ++ struct pipe_ctx *pipe_ctx, ++ struct dc_stream_state *stream, ++ struct drr_params *params) ++{ ++ /* params can be null.*/ ++ if (pipe_ctx && pipe_ctx->stream_res.tg && ++ pipe_ctx->stream_res.tg->funcs->set_drr) ++ pipe_ctx->stream_res.tg->funcs->set_drr( ++ pipe_ctx->stream_res.tg, params); ++ ++ if (stream) ++ stream->adjust.timing_adjust_pending = false; ++} ++ + void get_fams2_visual_confirm_color( + struct dc *dc, + struct dc_state *context, +diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +index c10567ec1c819..0ded4bc7825b0 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +@@ -1000,6 +1000,7 @@ struct dc_crtc_timing_adjust { + uint32_t v_total_mid; + uint32_t v_total_mid_frame_num; + uint32_t allow_otg_v_count_halt; ++ uint8_t timing_adjust_pending; + }; + + +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +index 4fbed0298adfa..1e76524d116dc 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +@@ -1653,9 +1653,7 @@ enum dc_status dce110_apply_single_controller_ctx_to_hw( + + params.vertical_total_min = stream->adjust.v_total_min; + params.vertical_total_max = stream->adjust.v_total_max; +- if (pipe_ctx->stream_res.tg->funcs->set_drr) +- pipe_ctx->stream_res.tg->funcs->set_drr( +- pipe_ctx->stream_res.tg, ¶ms); ++ set_drr_and_clear_adjust_pending(pipe_ctx, stream, ¶ms); + + // DRR should set trigger event to monitor surface update event + if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0) +@@ -2103,8 +2101,7 @@ static void set_drr(struct pipe_ctx **pipe_ctx, + struct timing_generator *tg = pipe_ctx[i]->stream_res.tg; + + if ((tg != NULL) && tg->funcs) { +- if (tg->funcs->set_drr) +- tg->funcs->set_drr(tg, ¶ms); ++ set_drr_and_clear_adjust_pending(pipe_ctx[i], pipe_ctx[i]->stream, ¶ms); + if (adjust.v_total_max != 0 && adjust.v_total_min != 0) + if (tg->funcs->set_static_screen_control) + tg->funcs->set_static_screen_control( +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +index d725af14af371..00be0b26689d3 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +@@ -1112,9 +1112,7 @@ static void dcn10_reset_back_end_for_pipe( + pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg); + + pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false); +- if (pipe_ctx->stream_res.tg->funcs->set_drr) +- pipe_ctx->stream_res.tg->funcs->set_drr( +- pipe_ctx->stream_res.tg, NULL); ++ set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL); + if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0; + } +@@ -3217,8 +3215,7 @@ void dcn10_set_drr(struct pipe_ctx **pipe_ctx, + struct timing_generator *tg = pipe_ctx[i]->stream_res.tg; + + if ((tg != NULL) && tg->funcs) { +- if (tg->funcs->set_drr) +- tg->funcs->set_drr(tg, ¶ms); ++ set_drr_and_clear_adjust_pending(pipe_ctx[i], pipe_ctx[i]->stream, ¶ms); + if (adjust.v_total_max != 0 && adjust.v_total_min != 0) + if (tg->funcs->set_static_screen_control) + tg->funcs->set_static_screen_control( +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +index f5f1ccd8303cf..9c5cdb3b80b5d 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +@@ -952,9 +952,7 @@ enum dc_status dcn20_enable_stream_timing( + params.vertical_total_max = stream->adjust.v_total_max; + params.vertical_total_mid = stream->adjust.v_total_mid; + params.vertical_total_mid_frame_num = stream->adjust.v_total_mid_frame_num; +- if (pipe_ctx->stream_res.tg->funcs->set_drr) +- pipe_ctx->stream_res.tg->funcs->set_drr( +- pipe_ctx->stream_res.tg, ¶ms); ++ set_drr_and_clear_adjust_pending(pipe_ctx, stream, ¶ms); + + // DRR should set trigger event to monitor surface update event + if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0) +@@ -2822,9 +2820,7 @@ void dcn20_reset_back_end_for_pipe( + pipe_ctx->stream_res.tg->funcs->set_odm_bypass( + pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing); + +- if (pipe_ctx->stream_res.tg->funcs->set_drr) +- pipe_ctx->stream_res.tg->funcs->set_drr( +- pipe_ctx->stream_res.tg, NULL); ++ set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL); + /* TODO - convert symclk_ref_cnts for otg to a bit map to solve + * the case where the same symclk is shared across multiple otg + * instances +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c +index 3d4b31bd99469..9aa925a0b3b43 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c +@@ -528,9 +528,7 @@ static void dcn31_reset_back_end_for_pipe( + if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0; + +- if (pipe_ctx->stream_res.tg->funcs->set_drr) +- pipe_ctx->stream_res.tg->funcs->set_drr( +- pipe_ctx->stream_res.tg, NULL); ++ set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL); + + link = pipe_ctx->stream->link; + /* DPMS may already disable or */ +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +index 38755ca771401..ca446e08f6a27 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +@@ -1452,8 +1452,7 @@ void dcn35_set_drr(struct pipe_ctx **pipe_ctx, + num_frames = 2 * (frame_rate % 60); + } + } +- if (tg->funcs->set_drr) +- tg->funcs->set_drr(tg, ¶ms); ++ set_drr_and_clear_adjust_pending(pipe_ctx[i], pipe_ctx[i]->stream, ¶ms); + if (adjust.v_total_max != 0 && adjust.v_total_min != 0) + if (tg->funcs->set_static_screen_control) + tg->funcs->set_static_screen_control( +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +index b6b333a2461f8..3279f347660cb 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +@@ -902,10 +902,7 @@ enum dc_status dcn401_enable_stream_timing( + } + + hws->funcs.wait_for_blank_complete(pipe_ctx->stream_res.opp); +- +- if (pipe_ctx->stream_res.tg->funcs->set_drr) +- pipe_ctx->stream_res.tg->funcs->set_drr( +- pipe_ctx->stream_res.tg, ¶ms); ++ set_drr_and_clear_adjust_pending(pipe_ctx, stream, ¶ms); + + /* Event triggers and num frames initialized for DRR, but can be + * later updated for PSR use. Note DRR trigger events are generated +@@ -1835,9 +1832,8 @@ void dcn401_reset_back_end_for_pipe( + pipe_ctx->stream_res.tg->funcs->set_odm_bypass( + pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing); + +- if (pipe_ctx->stream_res.tg->funcs->set_drr) +- pipe_ctx->stream_res.tg->funcs->set_drr( +- pipe_ctx->stream_res.tg, NULL); ++ set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL); ++ + /* TODO - convert symclk_ref_cnts for otg to a bit map to solve + * the case where the same symclk is shared across multiple otg + * instances +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h +index ac92056256233..9ae6259f2db17 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h ++++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h +@@ -46,6 +46,7 @@ struct dce_hwseq; + struct link_resource; + struct dc_dmub_cmd; + struct pg_block_update; ++struct drr_params; + + struct subvp_pipe_control_lock_fast_params { + struct dc *dc; +@@ -509,6 +510,11 @@ void set_p_state_switch_method( + struct dc_state *context, + struct pipe_ctx *pipe_ctx); + ++void set_drr_and_clear_adjust_pending( ++ struct pipe_ctx *pipe_ctx, ++ struct dc_stream_state *stream, ++ struct drr_params *params); ++ + void hwss_execute_sequence(struct dc *dc, + struct block_sequence block_sequence[], + int num_steps); +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-don-t-treat-wb-connector-as-physical.patch b/queue-6.12/drm-amd-display-don-t-treat-wb-connector-as-physical.patch new file mode 100644 index 0000000000..93cda7df51 --- /dev/null +++ b/queue-6.12/drm-amd-display-don-t-treat-wb-connector-as-physical.patch @@ -0,0 +1,157 @@ +From 021441d93ac1b3f654e2d9e8d34bc11b28a7276d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 11:57:49 -0500 +Subject: drm/amd/display: Don't treat wb connector as physical in + create_validate_stream_for_sink + +From: Harry Wentland + +[ Upstream commit cbf4890c6f28fb1ad733e14613fbd33c2004bced ] + +Don't try to operate on a drm_wb_connector as an amdgpu_dm_connector. +While dereferencing aconnector->base will "work" it's wrong and +might lead to unknown bad things. Just... don't. + +Reviewed-by: Alex Hung +Signed-off-by: Harry Wentland +Signed-off-by: Roman Li +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 26 ++++++++++++------- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 +- + .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 6 ++--- + 3 files changed, 20 insertions(+), 14 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index c0ff501687f5b..1e5984e71bfd7 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -7399,12 +7399,12 @@ static enum dc_status dm_validate_stream_and_context(struct dc *dc, + } + + struct dc_stream_state * +-create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, ++create_validate_stream_for_sink(struct drm_connector *connector, + const struct drm_display_mode *drm_mode, + const struct dm_connector_state *dm_state, + const struct dc_stream_state *old_stream) + { +- struct drm_connector *connector = &aconnector->base; ++ struct amdgpu_dm_connector *aconnector = NULL; + struct amdgpu_device *adev = drm_to_adev(connector->dev); + struct dc_stream_state *stream; + const struct drm_connector_state *drm_state = dm_state ? &dm_state->base : NULL; +@@ -7415,8 +7415,12 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, + if (!dm_state) + return NULL; + +- if (aconnector->dc_link->connector_signal == SIGNAL_TYPE_HDMI_TYPE_A || +- aconnector->dc_link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER) ++ if (connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK) ++ aconnector = to_amdgpu_dm_connector(connector); ++ ++ if (aconnector && ++ (aconnector->dc_link->connector_signal == SIGNAL_TYPE_HDMI_TYPE_A || ++ aconnector->dc_link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER)) + bpc_limit = 8; + + do { +@@ -7428,10 +7432,11 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, + break; + } + +- if (aconnector->base.connector_type == DRM_MODE_CONNECTOR_WRITEBACK) ++ dc_result = dc_validate_stream(adev->dm.dc, stream); ++ ++ if (!aconnector) /* writeback connector */ + return stream; + +- dc_result = dc_validate_stream(adev->dm.dc, stream); + if (dc_result == DC_OK && stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) + dc_result = dm_dp_mst_is_port_support_mode(aconnector, stream); + +@@ -7461,7 +7466,7 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, + __func__, __LINE__); + + aconnector->force_yuv420_output = true; +- stream = create_validate_stream_for_sink(aconnector, drm_mode, ++ stream = create_validate_stream_for_sink(connector, drm_mode, + dm_state, old_stream); + aconnector->force_yuv420_output = false; + } +@@ -7476,6 +7481,9 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec + struct dc_sink *dc_sink; + /* TODO: Unhardcode stream count */ + struct dc_stream_state *stream; ++ /* we always have an amdgpu_dm_connector here since we got ++ * here via the amdgpu_dm_connector_helper_funcs ++ */ + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); + + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || +@@ -7500,7 +7508,7 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec + + drm_mode_set_crtcinfo(mode, 0); + +- stream = create_validate_stream_for_sink(aconnector, mode, ++ stream = create_validate_stream_for_sink(connector, mode, + to_dm_connector_state(connector->state), + NULL); + if (stream) { +@@ -10520,7 +10528,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, + if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) + goto skip_modeset; + +- new_stream = create_validate_stream_for_sink(aconnector, ++ new_stream = create_validate_stream_for_sink(connector, + &new_crtc_state->mode, + dm_new_conn_state, + dm_old_crtc_state->stream); +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +index 20ad72d1b0d9b..9603352ee0949 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +@@ -987,7 +987,7 @@ int amdgpu_dm_process_dmub_set_config_sync(struct dc_context *ctx, unsigned int + struct set_config_cmd_payload *payload, enum set_config_status *operation_result); + + struct dc_stream_state * +- create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, ++ create_validate_stream_for_sink(struct drm_connector *connector, + const struct drm_display_mode *drm_mode, + const struct dm_connector_state *dm_state, + const struct dc_stream_state *old_stream); +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +index fca0c31e14d8f..92158009cfa73 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +@@ -1646,7 +1646,6 @@ int pre_validate_dsc(struct drm_atomic_state *state, + + if (ind >= 0) { + struct drm_connector *connector; +- struct amdgpu_dm_connector *aconnector; + struct drm_connector_state *drm_new_conn_state; + struct dm_connector_state *dm_new_conn_state; + struct dm_crtc_state *dm_old_crtc_state; +@@ -1654,15 +1653,14 @@ int pre_validate_dsc(struct drm_atomic_state *state, + connector = + amdgpu_dm_find_first_crtc_matching_connector(state, + state->crtcs[ind].ptr); +- aconnector = to_amdgpu_dm_connector(connector); + drm_new_conn_state = + drm_atomic_get_new_connector_state(state, +- &aconnector->base); ++ connector); + dm_new_conn_state = to_dm_connector_state(drm_new_conn_state); + dm_old_crtc_state = to_dm_crtc_state(state->crtcs[ind].old_state); + + local_dc_state->streams[i] = +- create_validate_stream_for_sink(aconnector, ++ create_validate_stream_for_sink(connector, + &state->crtcs[ind].new_state->mode, + dm_new_conn_state, + dm_old_crtc_state->stream); +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-don-t-try-aux-transactions-on-discon.patch b/queue-6.12/drm-amd-display-don-t-try-aux-transactions-on-discon.patch new file mode 100644 index 0000000000..9e172acce5 --- /dev/null +++ b/queue-6.12/drm-amd-display-don-t-try-aux-transactions-on-discon.patch @@ -0,0 +1,57 @@ +From 001631e85bc15f56f0d25f3d3b1a0d3d99178cb6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jan 2025 13:14:54 -0500 +Subject: drm/amd/display: Don't try AUX transactions on disconnected link + +From: Ilya Bakoulin + +[ Upstream commit e8bffa52e0253cfd689813a620e64521256bc712 ] + +[Why] +Setting link DPMS off in response to HPD disconnect creates AUX +transactions on a link that is supposed to be disconnected. This can +cause issues in some cases when the sink re-asserts HPD and expects +source to re-enable the link. + +[How] +Avoid AUX transactions on disconnected link. + +Reviewed-by: Wenjing Liu +Signed-off-by: Ilya Bakoulin +Signed-off-by: Aurabindo Pillai +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c +index bafa52a0165a0..17c57cf98ec5c 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c +@@ -75,7 +75,8 @@ void dp_disable_link_phy(struct dc_link *link, + struct dc *dc = link->ctx->dc; + + if (!link->wa_flags.dp_keep_receiver_powered && +- !link->skip_implict_edp_power_control) ++ !link->skip_implict_edp_power_control && ++ link->type != dc_connection_none) + dpcd_write_rx_power_ctrl(link, false); + + dc->hwss.disable_link_output(link, link_res, signal); +@@ -163,8 +164,9 @@ enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource + } else { + if (link->fec_state == dc_link_fec_ready) { + fec_config = 0; +- core_link_write_dpcd(link, DP_FEC_CONFIGURATION, +- &fec_config, sizeof(fec_config)); ++ if (link->type != dc_connection_none) ++ core_link_write_dpcd(link, DP_FEC_CONFIGURATION, ++ &fec_config, sizeof(fec_config)); + + link_enc->funcs->fec_set_ready(link_enc, false); + link->fec_state = dc_link_fec_not_ready; +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-enable-urgent-latency-adjustment-on-.patch b/queue-6.12/drm-amd-display-enable-urgent-latency-adjustment-on-.patch new file mode 100644 index 0000000000..ffbdad9f4d --- /dev/null +++ b/queue-6.12/drm-amd-display-enable-urgent-latency-adjustment-on-.patch @@ -0,0 +1,53 @@ +From e252ec8952db15bb116a014b62f6051d86113c76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Apr 2025 15:04:08 -0400 +Subject: drm/amd/display: Enable urgent latency adjustment on DCN35 + +From: Nicholas Susanto + +[ Upstream commit 756c85e4d0ddc497b4ad5b1f41ad54e838e06188 ] + +[Why] + +Urgent latency adjustment was disabled on DCN35 due to issues with P0 +enablement on some platforms. Without urgent latency, underflows occur +when doing certain high timing configurations. After testing, we found +that reenabling urgent latency didn't reintroduce p0 support on multiple +platforms. + +[How] + +renable urgent latency on DCN35 and setting it to 3000 Mhz. + +This reverts commit 3412860cc4c0c484f53f91b371483e6e4440c3e5. + +Reviewed-by: Charlene Liu +Signed-off-by: Nicholas Susanto +Signed-off-by: Zaeem Mohamed +Tested-by: Mark Broadworth +Signed-off-by: Alex Deucher +(cherry picked from commit cd74ce1f0cddffb3f36d0995d0f61e89f0010738) +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c +index 47d785204f29c..beed7adbbd43e 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c +@@ -195,9 +195,9 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = { + .dcn_downspread_percent = 0.5, + .gpuvm_min_page_size_bytes = 4096, + .hostvm_min_page_size_bytes = 4096, +- .do_urgent_latency_adjustment = 0, ++ .do_urgent_latency_adjustment = 1, + .urgent_latency_adjustment_fabric_clock_component_us = 0, +- .urgent_latency_adjustment_fabric_clock_reference_mhz = 0, ++ .urgent_latency_adjustment_fabric_clock_reference_mhz = 3000, + }; + + void dcn35_build_wm_range_table_fpu(struct clk_mgr *clk_mgr) +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-ensure-dmcub-idle-before-reset-on-dc.patch b/queue-6.12/drm-amd-display-ensure-dmcub-idle-before-reset-on-dc.patch new file mode 100644 index 0000000000..3758011530 --- /dev/null +++ b/queue-6.12/drm-amd-display-ensure-dmcub-idle-before-reset-on-dc.patch @@ -0,0 +1,106 @@ +From 6380d5d2da2c068ff5164972dd2595a7ca68f78a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 09:56:53 -0500 +Subject: drm/amd/display: Ensure DMCUB idle before reset on DCN31/DCN35 + +From: Nicholas Kazlauskas + +[ Upstream commit c707ea82c79dbd1d295ec94cc6529a5248c77757 ] + +[Why] +If we soft reset before halt finishes and there are outstanding +memory transactions then the memory interface may produce unexpected +results, such as out of order transactions when the firmware next runs. + +These can manifest as random or unexpected load/store violations. + +[How] +Increase the timeout before soft reset to ensure the DMCUB has quiesced. +This is effectively 1s maximum based on experimentation. + +Use the enable bit check on DCN31 like we're doing on DCN35 and reorder +the reset writes to follow the HW programming guide. + +Ensure we're reading SCRATCH7 instead of SCRATCH8 for the HALT code. +No current versions of DMCUB firmware use the SCRATCH8 boot bit to +dynamically switch where the HALT code goes to maintain backwards +compatibility with PSP. + +Reviewed-by: Dillon Varone +Signed-off-by: Nicholas Kazlauskas +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../gpu/drm/amd/display/dmub/src/dmub_dcn31.c | 17 +++++++++++------ + .../gpu/drm/amd/display/dmub/src/dmub_dcn35.c | 4 ++-- + 2 files changed, 13 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +index d9f31b191c693..1a68b5782cac6 100644 +--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c ++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +@@ -83,8 +83,8 @@ static inline void dmub_dcn31_translate_addr(const union dmub_addr *addr_in, + void dmub_dcn31_reset(struct dmub_srv *dmub) + { + union dmub_gpint_data_register cmd; +- const uint32_t timeout = 100; +- uint32_t in_reset, scratch, i, pwait_mode; ++ const uint32_t timeout = 100000; ++ uint32_t in_reset, is_enabled, scratch, i, pwait_mode; + + REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset); + +@@ -108,7 +108,7 @@ void dmub_dcn31_reset(struct dmub_srv *dmub) + } + + for (i = 0; i < timeout; ++i) { +- scratch = dmub->hw_funcs.get_gpint_response(dmub); ++ scratch = REG_READ(DMCUB_SCRATCH7); + if (scratch == DMUB_GPINT__STOP_FW_RESPONSE) + break; + +@@ -125,9 +125,14 @@ void dmub_dcn31_reset(struct dmub_srv *dmub) + /* Force reset in case we timed out, DMCUB is likely hung. */ + } + +- REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); +- REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); +- REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); ++ REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enabled); ++ ++ if (is_enabled) { ++ REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); ++ REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); ++ REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); ++ } ++ + REG_WRITE(DMCUB_INBOX1_RPTR, 0); + REG_WRITE(DMCUB_INBOX1_WPTR, 0); + REG_WRITE(DMCUB_OUTBOX1_RPTR, 0); +diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c +index 2ccad79053c58..4581eb4794518 100644 +--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c ++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c +@@ -88,7 +88,7 @@ static inline void dmub_dcn35_translate_addr(const union dmub_addr *addr_in, + void dmub_dcn35_reset(struct dmub_srv *dmub) + { + union dmub_gpint_data_register cmd; +- const uint32_t timeout = 100; ++ const uint32_t timeout = 100000; + uint32_t in_reset, is_enabled, scratch, i, pwait_mode; + + REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset); +@@ -113,7 +113,7 @@ void dmub_dcn35_reset(struct dmub_srv *dmub) + } + + for (i = 0; i < timeout; ++i) { +- scratch = dmub->hw_funcs.get_gpint_response(dmub); ++ scratch = REG_READ(DMCUB_SCRATCH7); + if (scratch == DMUB_GPINT__STOP_FW_RESPONSE) + break; + +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-fix-bt2020-ycbcr-limited-full-range-.patch b/queue-6.12/drm-amd-display-fix-bt2020-ycbcr-limited-full-range-.patch new file mode 100644 index 0000000000..3748fd5e72 --- /dev/null +++ b/queue-6.12/drm-amd-display-fix-bt2020-ycbcr-limited-full-range-.patch @@ -0,0 +1,282 @@ +From 187c79514ca83f0139155e897b05df594022d0ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 14:46:27 -0500 +Subject: drm/amd/display: Fix BT2020 YCbCr limited/full range input + +From: Ilya Bakoulin + +[ Upstream commit 07bc2dcbcf403d47d6f305ef7f0d3d489491c5fb ] + +[Why] +BT2020 YCbCr input is not handled properly when full range +quantization is used and limited range is not supported at all. + +[How] +- Add enums for BT2020 YCbCr limited/full range +- Add limited range CSC matrix + +Reviewed-by: Krunoslav Kovac +Signed-off-by: Ilya Bakoulin +Signed-off-by: Roman Li +Tested-by: Robert Mader +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 2 +- + drivers/gpu/drm/amd/display/dc/basics/dc_common.c | 3 ++- + drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 5 +++-- + drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 ++-- + drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 4 +++- + drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 3 ++- + .../gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c | 3 ++- + .../amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c | 3 ++- + .../amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c | 3 ++- + drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h | 6 +++++- + .../gpu/drm/amd/display/modules/info_packet/info_packet.c | 4 ++-- + 12 files changed, 29 insertions(+), 17 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 17c03b89abb31..c0ff501687f5b 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -5552,9 +5552,9 @@ fill_plane_color_attributes(const struct drm_plane_state *plane_state, + + case DRM_COLOR_YCBCR_BT2020: + if (full_range) +- *color_space = COLOR_SPACE_2020_YCBCR; ++ *color_space = COLOR_SPACE_2020_YCBCR_FULL; + else +- return -EINVAL; ++ *color_space = COLOR_SPACE_2020_YCBCR_LIMITED; + break; + + default: +@@ -6050,7 +6050,7 @@ get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing, + if (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB) + color_space = COLOR_SPACE_2020_RGB_FULLRANGE; + else +- color_space = COLOR_SPACE_2020_YCBCR; ++ color_space = COLOR_SPACE_2020_YCBCR_LIMITED; + break; + case DRM_MODE_COLORIMETRY_DEFAULT: // ITU601 + default: +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +index 98e88903d07d5..15d94d2a0e2fb 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +@@ -1145,7 +1145,7 @@ static int amdgpu_current_colorspace_show(struct seq_file *m, void *data) + case COLOR_SPACE_2020_RGB_FULLRANGE: + seq_puts(m, "BT2020_RGB"); + break; +- case COLOR_SPACE_2020_YCBCR: ++ case COLOR_SPACE_2020_YCBCR_LIMITED: + seq_puts(m, "BT2020_YCC"); + break; + default: +diff --git a/drivers/gpu/drm/amd/display/dc/basics/dc_common.c b/drivers/gpu/drm/amd/display/dc/basics/dc_common.c +index b2fc4f8e64825..a51c2701da247 100644 +--- a/drivers/gpu/drm/amd/display/dc/basics/dc_common.c ++++ b/drivers/gpu/drm/amd/display/dc/basics/dc_common.c +@@ -40,7 +40,8 @@ bool is_rgb_cspace(enum dc_color_space output_color_space) + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR601_LIMITED: + case COLOR_SPACE_YCBCR709_LIMITED: +- case COLOR_SPACE_2020_YCBCR: ++ case COLOR_SPACE_2020_YCBCR_LIMITED: ++ case COLOR_SPACE_2020_YCBCR_FULL: + return false; + default: + /* Add a case to switch */ +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +index d2342a91e7e71..d62b00314682f 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +@@ -176,7 +176,7 @@ static bool is_ycbcr2020_type( + { + bool ret = false; + +- if (color_space == COLOR_SPACE_2020_YCBCR) ++ if (color_space == COLOR_SPACE_2020_YCBCR_LIMITED || color_space == COLOR_SPACE_2020_YCBCR_FULL) + ret = true; + return ret; + } +@@ -247,7 +247,8 @@ void color_space_to_black_color( + case COLOR_SPACE_YCBCR709_BLACK: + case COLOR_SPACE_YCBCR601_LIMITED: + case COLOR_SPACE_YCBCR709_LIMITED: +- case COLOR_SPACE_2020_YCBCR: ++ case COLOR_SPACE_2020_YCBCR_LIMITED: ++ case COLOR_SPACE_2020_YCBCR_FULL: + *black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_CV]; + break; + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +index bfcbbea377298..6dbf139c51f72 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +@@ -4215,7 +4215,7 @@ static void set_avi_info_frame( + break; + case COLOR_SPACE_2020_RGB_FULLRANGE: + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: +- case COLOR_SPACE_2020_YCBCR: ++ case COLOR_SPACE_2020_YCBCR_LIMITED: + hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR; + hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; + break; +@@ -4229,7 +4229,7 @@ static void set_avi_info_frame( + break; + } + +- if (pixel_encoding && color_space == COLOR_SPACE_2020_YCBCR && ++ if (pixel_encoding && color_space == COLOR_SPACE_2020_YCBCR_LIMITED && + stream->out_transfer_func.tf == TRANSFER_FUNCTION_GAMMA22) { + hdmi_info.bits.EC0_EC2 = 0; + hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709; +diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +index 0ded4bc7825b0..6fd94c5f6da52 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +@@ -641,7 +641,8 @@ enum dc_color_space { + COLOR_SPACE_YCBCR709_LIMITED, + COLOR_SPACE_2020_RGB_FULLRANGE, + COLOR_SPACE_2020_RGB_LIMITEDRANGE, +- COLOR_SPACE_2020_YCBCR, ++ COLOR_SPACE_2020_YCBCR_LIMITED, ++ COLOR_SPACE_2020_YCBCR_FULL, + COLOR_SPACE_ADOBERGB, + COLOR_SPACE_DCIP3, + COLOR_SPACE_DISPLAYNATIVE, +@@ -649,6 +650,7 @@ enum dc_color_space { + COLOR_SPACE_APPCTRL, + COLOR_SPACE_CUSTOMPOINTS, + COLOR_SPACE_YCBCR709_BLACK, ++ COLOR_SPACE_2020_YCBCR = COLOR_SPACE_2020_YCBCR_LIMITED, + }; + + enum dc_dither_option { +diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +index 5c2825bc9a876..654b919465f08 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +@@ -420,7 +420,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute( + dynamic_range_rgb = 1; /*limited range*/ + break; + case COLOR_SPACE_2020_RGB_FULLRANGE: +- case COLOR_SPACE_2020_YCBCR: ++ case COLOR_SPACE_2020_YCBCR_LIMITED: + case COLOR_SPACE_XR_RGB: + case COLOR_SPACE_MSREF_SCRGB: + case COLOR_SPACE_ADOBERGB: +@@ -432,6 +432,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute( + case COLOR_SPACE_APPCTRL: + case COLOR_SPACE_CUSTOMPOINTS: + case COLOR_SPACE_UNKNOWN: ++ default: + /* do nothing */ + break; + } +diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c +index f496e952ceecb..f8f1e98f646e6 100644 +--- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c +@@ -393,7 +393,7 @@ void enc1_stream_encoder_dp_set_stream_attribute( + break; + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + case COLOR_SPACE_2020_RGB_FULLRANGE: +- case COLOR_SPACE_2020_YCBCR: ++ case COLOR_SPACE_2020_YCBCR_LIMITED: + case COLOR_SPACE_XR_RGB: + case COLOR_SPACE_MSREF_SCRGB: + case COLOR_SPACE_ADOBERGB: +@@ -406,6 +406,7 @@ void enc1_stream_encoder_dp_set_stream_attribute( + case COLOR_SPACE_CUSTOMPOINTS: + case COLOR_SPACE_UNKNOWN: + case COLOR_SPACE_YCBCR709_BLACK: ++ default: + /* do nothing */ + break; + } +diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c +index 0a27e0942a123..0008816cf1553 100644 +--- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c +@@ -634,7 +634,7 @@ void enc401_stream_encoder_dp_set_stream_attribute( + break; + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + case COLOR_SPACE_2020_RGB_FULLRANGE: +- case COLOR_SPACE_2020_YCBCR: ++ case COLOR_SPACE_2020_YCBCR_LIMITED: + case COLOR_SPACE_XR_RGB: + case COLOR_SPACE_MSREF_SCRGB: + case COLOR_SPACE_ADOBERGB: +@@ -647,6 +647,7 @@ void enc401_stream_encoder_dp_set_stream_attribute( + case COLOR_SPACE_CUSTOMPOINTS: + case COLOR_SPACE_UNKNOWN: + case COLOR_SPACE_YCBCR709_BLACK: ++ default: + /* do nothing */ + break; + } +diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c +index 678db949cfe3c..759b453385c46 100644 +--- a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c +@@ -323,7 +323,7 @@ static void dcn31_hpo_dp_stream_enc_set_stream_attribute( + break; + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + case COLOR_SPACE_2020_RGB_FULLRANGE: +- case COLOR_SPACE_2020_YCBCR: ++ case COLOR_SPACE_2020_YCBCR_LIMITED: + case COLOR_SPACE_XR_RGB: + case COLOR_SPACE_MSREF_SCRGB: + case COLOR_SPACE_ADOBERGB: +@@ -336,6 +336,7 @@ static void dcn31_hpo_dp_stream_enc_set_stream_attribute( + case COLOR_SPACE_CUSTOMPOINTS: + case COLOR_SPACE_UNKNOWN: + case COLOR_SPACE_YCBCR709_BLACK: ++ default: + /* do nothing */ + break; + } +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +index 0150f2581ee4c..0c5675d1c5936 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +@@ -119,10 +119,14 @@ static const struct dpp_input_csc_matrix __maybe_unused dpp_input_csc_matrix[] = + { 0x39a6, 0x2568, 0, 0xe0d6, + 0xeedd, 0x2568, 0xf925, 0x9a8, + 0, 0x2568, 0x43ee, 0xdbb2 } }, +- { COLOR_SPACE_2020_YCBCR, ++ { COLOR_SPACE_2020_YCBCR_FULL, + { 0x2F30, 0x2000, 0, 0xE869, + 0xEDB7, 0x2000, 0xFABC, 0xBC6, + 0, 0x2000, 0x3C34, 0xE1E6 } }, ++ { COLOR_SPACE_2020_YCBCR_LIMITED, ++ { 0x35B9, 0x2543, 0, 0xE2B2, ++ 0xEB2F, 0x2543, 0xFA01, 0x0B1F, ++ 0, 0x2543, 0x4489, 0xDB42 } }, + { COLOR_SPACE_2020_RGB_LIMITEDRANGE, + { 0x35E0, 0x255F, 0, 0xE2B3, + 0xEB20, 0x255F, 0xF9FD, 0xB1E, +diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +index a344e2e49b0ea..b3d55cac35694 100644 +--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c ++++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +@@ -383,10 +383,10 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, + colorimetryFormat = ColorimetryYCC_DP_ITU709; + else if (cs == COLOR_SPACE_ADOBERGB) + colorimetryFormat = ColorimetryYCC_DP_AdobeYCC; +- else if (cs == COLOR_SPACE_2020_YCBCR) ++ else if (cs == COLOR_SPACE_2020_YCBCR_LIMITED) + colorimetryFormat = ColorimetryYCC_DP_ITU2020YCbCr; + +- if (cs == COLOR_SPACE_2020_YCBCR && tf == TRANSFER_FUNC_GAMMA_22) ++ if (cs == COLOR_SPACE_2020_YCBCR_LIMITED && tf == TRANSFER_FUNC_GAMMA_22) + colorimetryFormat = ColorimetryYCC_DP_ITU709; + break; + +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-fix-dcn4x-init-failed.patch b/queue-6.12/drm-amd-display-fix-dcn4x-init-failed.patch new file mode 100644 index 0000000000..46044b0097 --- /dev/null +++ b/queue-6.12/drm-amd-display-fix-dcn4x-init-failed.patch @@ -0,0 +1,96 @@ +From c5190603c503fb09eae49e8105dffc4a9f461cfe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 12:37:10 -0500 +Subject: drm/amd/display: fix dcn4x init failed + +From: Charlene Liu + +[ Upstream commit 23ef388a84c72b0614a6c10f866ffeac7e807719 ] + +[why] +failed due to cmdtable not created. +switch atombios cmdtable as default. + +Reviewed-by: Alvin Lee +Signed-off-by: Charlene Liu +Signed-off-by: Zaeem Mohamed +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/bios/command_table2.c | 9 --------- + .../gpu/drm/amd/display/dc/bios/command_table_helper2.c | 3 +-- + 2 files changed, 1 insertion(+), 11 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +index 7d18f372ce7ab..6bc59b7ef007b 100644 +--- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c ++++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +@@ -101,7 +101,6 @@ static void init_dig_encoder_control(struct bios_parser *bp) + bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v1_5; + break; + default: +- dm_output_to_console("Don't have dig_encoder_control for v%d\n", version); + bp->cmd_tbl.dig_encoder_control = encoder_control_fallback; + break; + } +@@ -238,7 +237,6 @@ static void init_transmitter_control(struct bios_parser *bp) + bp->cmd_tbl.transmitter_control = transmitter_control_v1_7; + break; + default: +- dm_output_to_console("Don't have transmitter_control for v%d\n", crev); + bp->cmd_tbl.transmitter_control = transmitter_control_fallback; + break; + } +@@ -408,8 +406,6 @@ static void init_set_pixel_clock(struct bios_parser *bp) + bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7; + break; + default: +- dm_output_to_console("Don't have set_pixel_clock for v%d\n", +- BIOS_CMD_TABLE_PARA_REVISION(setpixelclock)); + bp->cmd_tbl.set_pixel_clock = set_pixel_clock_fallback; + break; + } +@@ -554,7 +550,6 @@ static void init_set_crtc_timing(struct bios_parser *bp) + set_crtc_using_dtd_timing_v3; + break; + default: +- dm_output_to_console("Don't have set_crtc_timing for v%d\n", dtd_version); + bp->cmd_tbl.set_crtc_timing = NULL; + break; + } +@@ -671,8 +666,6 @@ static void init_enable_crtc(struct bios_parser *bp) + bp->cmd_tbl.enable_crtc = enable_crtc_v1; + break; + default: +- dm_output_to_console("Don't have enable_crtc for v%d\n", +- BIOS_CMD_TABLE_PARA_REVISION(enablecrtc)); + bp->cmd_tbl.enable_crtc = NULL; + break; + } +@@ -864,8 +857,6 @@ static void init_set_dce_clock(struct bios_parser *bp) + bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1; + break; + default: +- dm_output_to_console("Don't have set_dce_clock for v%d\n", +- BIOS_CMD_TABLE_PARA_REVISION(setdceclock)); + bp->cmd_tbl.set_dce_clock = NULL; + break; + } +diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +index 73458e2951034..df8139bda142b 100644 +--- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c ++++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +@@ -87,8 +87,7 @@ bool dal_bios_parser_init_cmd_tbl_helper2( + return true; + + default: +- /* Unsupported DCE */ +- BREAK_TO_DEBUGGER(); ++ *h = dal_cmd_tbl_helper_dce112_get_table2(); + return false; + } + } +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-fix-dmub-reset-sequence-for-dcn401.patch b/queue-6.12/drm-amd-display-fix-dmub-reset-sequence-for-dcn401.patch new file mode 100644 index 0000000000..5905c2ba4d --- /dev/null +++ b/queue-6.12/drm-amd-display-fix-dmub-reset-sequence-for-dcn401.patch @@ -0,0 +1,155 @@ +From 40cd1c2b3ed3e0ab8fc5c4410f2b4bd31a54ed51 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 13:10:41 -0500 +Subject: drm/amd/display: Fix DMUB reset sequence for DCN401 + +From: Dillon Varone + +[ Upstream commit 0dfcc2bf269010a6e093793034c048049a40ee93 ] + +[WHY] +It should no longer use DMCUB_SOFT_RESET as it can result +in the memory request path becoming desynchronized. + +[HOW] +To ensure robustness in the reset sequence: +1) Extend timeout on the "halt" command sent via gpint, and check for +controller to enter "wait" as a stronger guarantee that there are no +requests to memory still in flight. +2) Remove usage of DMCUB_SOFT_RESET +3) Rely on PSP to reset the controller safely + +Reviewed-by: Nicholas Kazlauskas +Signed-off-by: Dillon Varone +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../drm/amd/display/dmub/src/dmub_dcn401.c | 47 ++++++++++++------- + .../drm/amd/display/dmub/src/dmub_dcn401.h | 3 +- + 2 files changed, 32 insertions(+), 18 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c +index 39a8cb6d7523c..e1c4fe1c6e3ee 100644 +--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c ++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c +@@ -63,8 +63,10 @@ static inline void dmub_dcn401_translate_addr(const union dmub_addr *addr_in, + void dmub_dcn401_reset(struct dmub_srv *dmub) + { + union dmub_gpint_data_register cmd; +- const uint32_t timeout = 30; +- uint32_t in_reset, scratch, i; ++ const uint32_t timeout_us = 1 * 1000 * 1000; //1s ++ const uint32_t poll_delay_us = 1; //1us ++ uint32_t i = 0; ++ uint32_t in_reset, scratch, pwait_mode; + + REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset); + +@@ -75,32 +77,35 @@ void dmub_dcn401_reset(struct dmub_srv *dmub) + + dmub->hw_funcs.set_gpint(dmub, cmd); + +- /** +- * Timeout covers both the ACK and the wait +- * for remaining work to finish. +- * +- * This is mostly bound by the PHY disable sequence. +- * Each register check will be greater than 1us, so +- * don't bother using udelay. +- */ +- +- for (i = 0; i < timeout; ++i) { ++ for (i = 0; i < timeout_us; i++) { + if (dmub->hw_funcs.is_gpint_acked(dmub, cmd)) + break; ++ ++ udelay(poll_delay_us); + } + +- for (i = 0; i < timeout; ++i) { ++ for (; i < timeout_us; i++) { + scratch = dmub->hw_funcs.get_gpint_response(dmub); + if (scratch == DMUB_GPINT__STOP_FW_RESPONSE) + break; ++ ++ udelay(poll_delay_us); + } + +- /* Force reset in case we timed out, DMCUB is likely hung. */ ++ for (; i < timeout_us; i++) { ++ REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &pwait_mode); ++ if (pwait_mode & (1 << 0)) ++ break; ++ ++ udelay(poll_delay_us); ++ } ++ } ++ ++ if (i >= timeout_us) { ++ /* timeout should never occur */ ++ BREAK_TO_DEBUGGER(); + } + +- REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); +- REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); +- REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); + REG_WRITE(DMCUB_INBOX1_RPTR, 0); + REG_WRITE(DMCUB_INBOX1_WPTR, 0); + REG_WRITE(DMCUB_OUTBOX1_RPTR, 0); +@@ -131,7 +136,10 @@ void dmub_dcn401_backdoor_load(struct dmub_srv *dmub, + + dmub_dcn401_get_fb_base_offset(dmub, &fb_base, &fb_offset); + ++ /* reset and disable DMCUB and MMHUBBUB DMUIF */ + REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1); ++ REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); ++ REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); + + dmub_dcn401_translate_addr(&cw0->offset, fb_base, fb_offset, &offset); + +@@ -151,6 +159,7 @@ void dmub_dcn401_backdoor_load(struct dmub_srv *dmub, + DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top, + DMCUB_REGION3_CW1_ENABLE, 1); + ++ /* release DMCUB reset only to prevent premature execution */ + REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID, + 0x20); + } +@@ -161,7 +170,10 @@ void dmub_dcn401_backdoor_load_zfb_mode(struct dmub_srv *dmub, + { + union dmub_addr offset; + ++ /* reset and disable DMCUB and MMHUBBUB DMUIF */ + REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1); ++ REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); ++ REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); + + offset = cw0->offset; + +@@ -181,6 +193,7 @@ void dmub_dcn401_backdoor_load_zfb_mode(struct dmub_srv *dmub, + DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top, + DMCUB_REGION3_CW1_ENABLE, 1); + ++ /* release DMCUB reset only to prevent premature execution */ + REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID, + 0x20); + } +diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h +index 4c8843b796950..31f95b27e227d 100644 +--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h ++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h +@@ -169,7 +169,8 @@ struct dmub_srv; + DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_EN) \ + DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_ACK) \ + DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_STAT) \ +- DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_EN) ++ DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_EN) \ ++ DMUB_SF(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS) + + struct dmub_srv_dcn401_reg_offset { + #define DMUB_SR(reg) uint32_t reg; +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-fix-incorrect-dpcd-configs-while-rep.patch b/queue-6.12/drm-amd-display-fix-incorrect-dpcd-configs-while-rep.patch new file mode 100644 index 0000000000..ae8ae65c9a --- /dev/null +++ b/queue-6.12/drm-amd-display-fix-incorrect-dpcd-configs-while-rep.patch @@ -0,0 +1,80 @@ +From 181accd35377db6c36ff135e3ee27b4af6574106 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 15:45:43 +0800 +Subject: drm/amd/display: Fix incorrect DPCD configs while Replay/PSR switch + +From: Leon Huang + +[ Upstream commit 0d9cabc8f591ea1cd97c071b853b75b155c13259 ] + +[Why] +When switching between PSR/Replay, +the DPCD config of previous mode is not cleared, +resulting in unexpected behavior in TCON. + +[How] +Initialize the DPCD in setup function + +Reviewed-by: Robin Chen +Signed-off-by: Leon Huang +Signed-off-by: Tom Chung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../link/protocols/link_edp_panel_control.c | 25 ++++++++++++++++--- + 1 file changed, 22 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c +index 3aa05a2be6c09..fa642f4b88c2d 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c +@@ -674,6 +674,18 @@ bool edp_setup_psr(struct dc_link *link, + if (!link) + return false; + ++ //Clear PSR cfg ++ memset(&psr_configuration, 0, sizeof(psr_configuration)); ++ dm_helpers_dp_write_dpcd( ++ link->ctx, ++ link, ++ DP_PSR_EN_CFG, ++ &psr_configuration.raw, ++ sizeof(psr_configuration.raw)); ++ ++ if (link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED) ++ return false; ++ + dc = link->ctx->dc; + dmcu = dc->res_pool->dmcu; + psr = dc->res_pool->psr; +@@ -684,9 +696,6 @@ bool edp_setup_psr(struct dc_link *link, + if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) + return false; + +- +- memset(&psr_configuration, 0, sizeof(psr_configuration)); +- + psr_configuration.bits.ENABLE = 1; + psr_configuration.bits.CRC_VERIFICATION = 1; + psr_configuration.bits.FRAME_CAPTURE_INDICATION = +@@ -950,6 +959,16 @@ bool edp_setup_replay(struct dc_link *link, const struct dc_stream_state *stream + if (!link) + return false; + ++ //Clear Replay config ++ dm_helpers_dp_write_dpcd(link->ctx, link, ++ DP_SINK_PR_ENABLE_AND_CONFIGURATION, ++ (uint8_t *)&(replay_config.raw), sizeof(uint8_t)); ++ ++ if (!(link->replay_settings.config.replay_supported)) ++ return false; ++ ++ link->replay_settings.config.replay_error_status.raw = 0; ++ + dc = link->ctx->dc; + + replay = dc->res_pool->replay; +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-fix-mismatch-type-comparison.patch b/queue-6.12/drm-amd-display-fix-mismatch-type-comparison.patch new file mode 100644 index 0000000000..31e92f874d --- /dev/null +++ b/queue-6.12/drm-amd-display-fix-mismatch-type-comparison.patch @@ -0,0 +1,54 @@ +From 501cf1278e67c98263b57ef90e7eebab30749276 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Dec 2024 17:19:09 -0500 +Subject: drm/amd/display: Fix mismatch type comparison + +From: Assadian, Navid + +[ Upstream commit 26873260d394b1e33cdd720154aedf0af95327f9 ] + +The mismatch type comparison/assignment may cause data loss. Since the +values are always non-negative, it is safe to use unsigned variables to +resolve the mismatch. + +Signed-off-by: Navid Assadian +Reviewed-by: Joshua Aberback +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/spl/dc_spl.c | 4 ++-- + drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c +index 014e8a296f0c7..54c7d6aecf51c 100644 +--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c ++++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c +@@ -875,8 +875,8 @@ static bool spl_get_optimal_number_of_taps( + bool *enable_isharp) + { + int num_part_y, num_part_c; +- int max_taps_y, max_taps_c; +- int min_taps_y, min_taps_c; ++ unsigned int max_taps_y, max_taps_c; ++ unsigned int min_taps_y, min_taps_c; + enum lb_memory_config lb_config; + bool skip_easf = false; + +diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h +index 2a74ff5fdfdbc..a2c28949ec47f 100644 +--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h ++++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h +@@ -479,7 +479,7 @@ struct spl_sharpness_range { + }; + struct adaptive_sharpness { + bool enable; +- int sharpness_level; ++ unsigned int sharpness_level; + struct spl_sharpness_range sharpness_range; + }; + enum linear_light_scaling { // convert it in translation logic +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-fix-p-state-type-when-p-state-is-uns.patch b/queue-6.12/drm-amd-display-fix-p-state-type-when-p-state-is-uns.patch new file mode 100644 index 0000000000..90d26962c0 --- /dev/null +++ b/queue-6.12/drm-amd-display-fix-p-state-type-when-p-state-is-uns.patch @@ -0,0 +1,39 @@ +From 3033a249f554f7c71b57f1b6a6cc5ad1782a9613 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 17:06:42 -0500 +Subject: drm/amd/display: Fix p-state type when p-state is unsupported + +From: Dillon Varone + +[ Upstream commit a025f424af0407b7561bd5e6217295dde3abbc2e ] + +[WHY&HOW] +P-state type would remain on previously used when unsupported which +causes confusion in logging and visual confirm, so set back to zero +when unsupported. + +Reviewed-by: Aric Cyr +Signed-off-by: Dillon Varone +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +index fdcba960e1e6f..d2342a91e7e71 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +@@ -508,6 +508,7 @@ void set_p_state_switch_method( + if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !vba) + return; + ++ pipe_ctx->p_state_type = P_STATE_UNKNOWN; + if (vba->DRAMClockChangeSupport[vba->VoltageLevel][vba->maxMpcComb] != + dm_dram_clock_change_unsupported) { + /* MCLK switching is supported */ +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-guard-against-setting-dispclk-low-fo.patch b/queue-6.12/drm-amd-display-guard-against-setting-dispclk-low-fo.patch new file mode 100644 index 0000000000..4fbc4cd76d --- /dev/null +++ b/queue-6.12/drm-amd-display-guard-against-setting-dispclk-low-fo.patch @@ -0,0 +1,113 @@ +From 34261fb5e830f054fd80915145ff9d2184dd35f2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 23:15:56 +0800 +Subject: drm/amd/display: Guard against setting dispclk low for dcn31x + +From: Jing Zhou + +[ Upstream commit 9c2f4ae64bb6f6d83a54d88b9ee0f369cdbb9fa8 ] + +[WHY] +We should never apply a minimum dispclk value while in +prepare_bandwidth or while displays are active. This is +always an optimizaiton for when all displays are disabled. + +[HOW] +Defer dispclk optimization until safe_to_lower = true +and display_count reaches 0. + +Since 0 has a special value in this logic (ie. no dispclk +required) we also need adjust the logic that clamps it for +the actual request to PMFW. + +Reviewed-by: Charlene Liu +Reviewed-by: Chris Park +Reviewed-by: Eric Yang +Signed-off-by: Jing Zhou +Signed-off-by: Nicholas Kazlauskas +Signed-off-by: Alex Hung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../dc/clk_mgr/dcn315/dcn315_clk_mgr.c | 20 +++++++++++-------- + .../dc/clk_mgr/dcn316/dcn316_clk_mgr.c | 13 +++++++++--- + 2 files changed, 22 insertions(+), 11 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +index a0fb4481d2f1b..827b24b3442ad 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +@@ -130,7 +130,7 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base, + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk; + struct dc *dc = clk_mgr_base->ctx->dc; +- int display_count; ++ int display_count = 0; + bool update_dppclk = false; + bool update_dispclk = false; + bool dpp_clock_lowered = false; +@@ -204,15 +204,19 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base, + update_dppclk = true; + } + +- if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { +- /* No need to apply the w/a if we haven't taken over from bios yet */ +- if (clk_mgr_base->clks.dispclk_khz) +- dcn315_disable_otg_wa(clk_mgr_base, context, true); ++ if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) && ++ (new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) { ++ int requested_dispclk_khz = new_clocks->dispclk_khz; + ++ dcn315_disable_otg_wa(clk_mgr_base, context, true); ++ ++ /* Clamp the requested clock to PMFW based on their limit. */ ++ if (dc->debug.min_disp_clk_khz > 0 && requested_dispclk_khz < dc->debug.min_disp_clk_khz) ++ requested_dispclk_khz = dc->debug.min_disp_clk_khz; ++ ++ dcn315_smu_set_dispclk(clk_mgr, requested_dispclk_khz); + clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; +- dcn315_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); +- if (clk_mgr_base->clks.dispclk_khz) +- dcn315_disable_otg_wa(clk_mgr_base, context, false); ++ dcn315_disable_otg_wa(clk_mgr_base, context, false); + + update_dispclk = true; + } +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +index c3e50c3aaa609..37c39756fece4 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +@@ -140,7 +140,7 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base, + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk; + struct dc *dc = clk_mgr_base->ctx->dc; +- int display_count; ++ int display_count = 0; + bool update_dppclk = false; + bool update_dispclk = false; + bool dpp_clock_lowered = false; +@@ -211,11 +211,18 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base, + update_dppclk = true; + } + +- if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { ++ if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) && ++ (new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) { ++ int requested_dispclk_khz = new_clocks->dispclk_khz; ++ + dcn316_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true); + ++ /* Clamp the requested clock to PMFW based on their limit. */ ++ if (dc->debug.min_disp_clk_khz > 0 && requested_dispclk_khz < dc->debug.min_disp_clk_khz) ++ requested_dispclk_khz = dc->debug.min_disp_clk_khz; ++ ++ dcn316_smu_set_dispclk(clk_mgr, requested_dispclk_khz); + clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; +- dcn316_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); + dcn316_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false); + + update_dispclk = true; +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-guard-against-setting-dispclk-low-wh.patch b/queue-6.12/drm-amd-display-guard-against-setting-dispclk-low-wh.patch new file mode 100644 index 0000000000..70676b602d --- /dev/null +++ b/queue-6.12/drm-amd-display-guard-against-setting-dispclk-low-wh.patch @@ -0,0 +1,65 @@ +From 928eb8f16832eda40469059ff0b711b7ecd2dd35 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 09:49:58 -0500 +Subject: drm/amd/display: Guard against setting dispclk low when active + +From: Nicholas Kazlauskas + +[ Upstream commit 72d7a7fa1f2404fd31c84a8f808b1b37021a3a9e ] + +[Why] +We should never apply a minimum dispclk value while in prepare_bandwidth +or while displays are active. This is always an optimization for when +all displays are disabled. + +[How] +Defer dispclk optimization until safe_to_lower = true and display_count +reaches 0. + +Since 0 has a special value in this logic (ie. no dispclk required) +we also need adjust the logic that clamps it for the actual request +to PMFW. + +Reviewed-by: Gabe Teeger +Reviewed-by: Leo Chen +Reviewed-by: Syed Hassan +Signed-off-by: Nicholas Kazlauskas +Signed-off-by: Roman Li +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +index 7d0d8852ce8d2..a4ac601a30c35 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +@@ -452,14 +452,19 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base, + update_dppclk = true; + } + +- if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { ++ if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) && ++ (new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) { ++ int requested_dispclk_khz = new_clocks->dispclk_khz; ++ + dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true); + +- if (dc->debug.min_disp_clk_khz > 0 && new_clocks->dispclk_khz < dc->debug.min_disp_clk_khz) +- new_clocks->dispclk_khz = dc->debug.min_disp_clk_khz; ++ /* Clamp the requested clock to PMFW based on their limit. */ ++ if (dc->debug.min_disp_clk_khz > 0 && requested_dispclk_khz < dc->debug.min_disp_clk_khz) ++ requested_dispclk_khz = dc->debug.min_disp_clk_khz; + ++ dcn35_smu_set_dispclk(clk_mgr, requested_dispclk_khz); + clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; +- dcn35_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); ++ + dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false); + + update_dispclk = true; +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-handle-max_downscale_src_width-fail-.patch b/queue-6.12/drm-amd-display-handle-max_downscale_src_width-fail-.patch new file mode 100644 index 0000000000..51d6627252 --- /dev/null +++ b/queue-6.12/drm-amd-display-handle-max_downscale_src_width-fail-.patch @@ -0,0 +1,59 @@ +From 7206c0077c86668a379e918a6b6bafa4fbcedd49 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 15:17:56 -0500 +Subject: drm/amd/display: handle max_downscale_src_width fail check + +From: Yihan Zhu + +[ Upstream commit 02a940da2ccc0cc0299811379580852b405a0ea2 ] + +[WHY] +If max_downscale_src_width check fails, we exit early from TAP calculation and left a NULL +value to the scaling data structure to cause the zero divide in the DML validation. + +[HOW] +Call set default TAP calculation before early exit in get_optimal_number_of_taps due to +max downscale limit exceed. + +Reviewed-by: Samson Tam +Signed-off-by: Yihan Zhu +Signed-off-by: Zaeem Mohamed +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c +index 40acebd13e46d..abf439e743f23 100644 +--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c ++++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c +@@ -425,11 +425,6 @@ bool dpp3_get_optimal_number_of_taps( + int min_taps_y, min_taps_c; + enum lb_memory_config lb_config; + +- if (scl_data->viewport.width > scl_data->h_active && +- dpp->ctx->dc->debug.max_downscale_src_width != 0 && +- scl_data->viewport.width > dpp->ctx->dc->debug.max_downscale_src_width) +- return false; +- + /* + * Set default taps if none are provided + * From programming guide: taps = min{ ceil(2*H_RATIO,1), 8} for downscaling +@@ -467,6 +462,12 @@ bool dpp3_get_optimal_number_of_taps( + else + scl_data->taps.h_taps_c = in_taps->h_taps_c; + ++ // Avoid null data in the scl data with this early return, proceed non-adaptive calcualtion first ++ if (scl_data->viewport.width > scl_data->h_active && ++ dpp->ctx->dc->debug.max_downscale_src_width != 0 && ++ scl_data->viewport.width > dpp->ctx->dc->debug.max_downscale_src_width) ++ return false; ++ + /*Ensure we can support the requested number of vtaps*/ + min_taps_y = dc_fixpt_ceil(scl_data->ratios.vert); + min_taps_c = dc_fixpt_ceil(scl_data->ratios.vert_c); +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-increase-block_sequence-array-size.patch b/queue-6.12/drm-amd-display-increase-block_sequence-array-size.patch new file mode 100644 index 0000000000..93125acfac --- /dev/null +++ b/queue-6.12/drm-amd-display-increase-block_sequence-array-size.patch @@ -0,0 +1,46 @@ +From b65629bc0e05e7b7a05478630792959a8818d0e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jan 2025 12:03:23 -0500 +Subject: drm/amd/display: Increase block_sequence array size + +From: Joshua Aberback + +[ Upstream commit 3a7810c212bcf2f722671dadf4b23ff70a7d23ee ] + +[Why] +It's possible to generate more than 50 steps in hwss_build_fast_sequence, +for example with a 6-pipe asic where all pipes are in one MPC chain. This +overflows the block_sequence buffer and corrupts block_sequence_steps, +causing a crash. + +[How] +Expand block_sequence to 100 items. A naive upper bound on the possible +number of steps for a 6-pipe asic, ignoring the potential for steps to be +mutually exclusive, is 91 with current code, therefore 100 is sufficient. + +Reviewed-by: Alvin Lee +Signed-off-by: Joshua Aberback +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h +index e1e3142cdc00a..62fb2009b3028 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h +@@ -621,7 +621,7 @@ struct dc_state { + */ + struct bw_context bw_ctx; + +- struct block_sequence block_sequence[50]; ++ struct block_sequence block_sequence[100]; + unsigned int block_sequence_steps; + struct dc_dmub_cmd dc_dmub_cmd[10]; + unsigned int dmub_cmd_count; +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-initial-psr_version-with-correct-set.patch b/queue-6.12/drm-amd-display-initial-psr_version-with-correct-set.patch new file mode 100644 index 0000000000..19ee6283f2 --- /dev/null +++ b/queue-6.12/drm-amd-display-initial-psr_version-with-correct-set.patch @@ -0,0 +1,40 @@ +From 888a339141c2d29b196be0c915377c8fbd5d9eda Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 14:22:31 +0800 +Subject: drm/amd/display: Initial psr_version with correct setting + +From: Tom Chung + +[ Upstream commit d8c782cac5007e68e7484d420168f12d3490def6 ] + +[Why & How] +The initial setting for psr_version is not correct while +create a virtual link. + +The default psr_version should be DC_PSR_VERSION_UNSUPPORTED. + +Reviewed-by: Roman Li +Signed-off-by: Tom Chung +Signed-off-by: Zaeem Mohamed +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index fa7db10104c45..a99d3e2256f19 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -276,6 +276,7 @@ static bool create_links( + link->link_id.type = OBJECT_TYPE_CONNECTOR; + link->link_id.id = CONNECTOR_ID_VIRTUAL; + link->link_id.enum_id = ENUM_ID_1; ++ link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED; + link->link_enc = kzalloc(sizeof(*link->link_enc), GFP_KERNEL); + + if (!link->link_enc) { +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-not-abort-link-train-when-bw-is-low.patch b/queue-6.12/drm-amd-display-not-abort-link-train-when-bw-is-low.patch new file mode 100644 index 0000000000..558be923a2 --- /dev/null +++ b/queue-6.12/drm-amd-display-not-abort-link-train-when-bw-is-low.patch @@ -0,0 +1,49 @@ +From c062cc4df989af99959a3b0320de505f37616546 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 14:52:30 +0800 +Subject: drm/amd/display: not abort link train when bw is low + +From: Peichen Huang + +[ Upstream commit 8a21da2842bb22b2b80e5902d0438030d729bfd3 ] + +[WHY] +DP tunneling should not abort link train even bandwidth become +too low after downgrade. Otherwise, it would fail compliance test. + +[HOW} +Do link train with downgrade settings even bandwidth is not enough + +Reviewed-by: Cruise Hung +Reviewed-by: Meenakshikumar Somasundaram +Signed-off-by: Peichen Huang +Signed-off-by: Tom Chung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../gpu/drm/amd/display/dc/link/protocols/link_dp_training.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c +index 27b881f947e8b..9385a32a471b8 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c +@@ -1769,13 +1769,10 @@ bool perform_link_training_with_retries( + is_link_bw_min = ((cur_link_settings.link_rate <= LINK_RATE_LOW) && + (cur_link_settings.lane_count <= LANE_COUNT_ONE)); + +- if (is_link_bw_low) { ++ if (is_link_bw_low) + DC_LOG_WARNING( + "%s: Link(%d) bandwidth too low after fallback req_bw(%d) > link_bw(%d)\n", + __func__, link->link_index, req_bw, link_bw); +- +- return false; +- } + } + + msleep(delay_between_attempts); +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-pass-calculated-dram_speed_mts-to-dm.patch b/queue-6.12/drm-amd-display-pass-calculated-dram_speed_mts-to-dm.patch new file mode 100644 index 0000000000..c3bacb1844 --- /dev/null +++ b/queue-6.12/drm-amd-display-pass-calculated-dram_speed_mts-to-dm.patch @@ -0,0 +1,69 @@ +From fe97b59ef5da22df05f39275380bf461927b8502 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 11:57:54 -0500 +Subject: drm/amd/display: pass calculated dram_speed_mts to dml2 + +From: Charlene Liu + +[ Upstream commit b40d022ec06ade9f6c809091dc188422a0f0946d ] + +[why] +currently dml2 is using a hard coded 16 to convert memclk to dram_speed_mts. +for apu, this depends on wck_ratio. + +change to pass the already calculated dram_speed_mts from fpu to dml2. + +v2: use existing calculation of dram_speed_mts for now to avoid regression + +Signed-off-by: Charlene Liu +Signed-off-by: Aurabindo Pillai +Reviewed-by: Roman Li +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c | 2 ++ + drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c | 1 + + drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h | 1 + + 3 files changed, 4 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c +index beed7adbbd43e..c90dee4e9116a 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c +@@ -367,6 +367,8 @@ void dcn35_update_bw_bounding_box_fpu(struct dc *dc, + clock_limits[i].socclk_mhz; + dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].memclk_mhz = + clk_table->entries[i].memclk_mhz * clk_table->entries[i].wck_ratio; ++ ++ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dram_speed_mts = clock_limits[i].dram_speed_mts; + dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz = + clock_limits[i].dtbclk_mhz; + dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dcfclk_levels = +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c +index a201dbb743d79..79d921adc2153 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c +@@ -401,6 +401,7 @@ void dcn351_update_bw_bounding_box_fpu(struct dc *dc, + clock_limits[i].socclk_mhz; + dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].memclk_mhz = + clk_table->entries[i].memclk_mhz * clk_table->entries[i].wck_ratio; ++ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dram_speed_mts = clock_limits[i].dram_speed_mts; + dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz = + clock_limits[i].dtbclk_mhz; + dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dcfclk_levels = +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h +index 0f944fcfd5a5b..785226945699d 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h ++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h +@@ -159,6 +159,7 @@ struct dml2_clks_table_entry { + unsigned int dtbclk_mhz; + unsigned int dispclk_mhz; + unsigned int dppclk_mhz; ++ unsigned int dram_speed_mts; /*which is based on wck_ratio*/ + }; + + struct dml2_clks_num_entries { +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-populate-register-address-for-dentis.patch b/queue-6.12/drm-amd-display-populate-register-address-for-dentis.patch new file mode 100644 index 0000000000..a8b4c5ab8a --- /dev/null +++ b/queue-6.12/drm-amd-display-populate-register-address-for-dentis.patch @@ -0,0 +1,52 @@ +From d5a1591af12e46b77ff24b958c61cb87afb14bf0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jan 2025 15:25:41 -0500 +Subject: drm/amd/display: Populate register address for dentist for dcn401 + +From: Dillon Varone + +[ Upstream commit 5f0d1ef6f16e150ee46cc00b8d233d9d271fe39e ] + +[WHY&HOW] +Address was not previously populated which can result in incorrect +clock frequencies being read on boot. + +Reviewed-by: Alvin Lee +Signed-off-by: Dillon Varone +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c | 2 ++ + drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c +index 8cfc5f4359374..313e52997596a 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c +@@ -24,6 +24,8 @@ + + #include "dml/dcn401/dcn401_fpu.h" + ++#define DCN_BASE__INST0_SEG1 0x000000C0 ++ + #define mmCLK01_CLK0_CLK_PLL_REQ 0x16E37 + #define mmCLK01_CLK0_CLK0_DFS_CNTL 0x16E69 + #define mmCLK01_CLK0_CLK1_DFS_CNTL 0x16E6C +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h +index 7a1ca1e98059b..221645c023b50 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h +@@ -221,6 +221,7 @@ enum dentist_divider_range { + CLK_SF(CLK0_CLK_PLL_REQ, FbMult_frac, mask_sh) + + #define CLK_REG_LIST_DCN401() \ ++ SR(DENTIST_DISPCLK_CNTL), \ + CLK_SR_DCN401(CLK0_CLK_PLL_REQ, CLK01, 0), \ + CLK_SR_DCN401(CLK0_CLK0_DFS_CNTL, CLK01, 0), \ + CLK_SR_DCN401(CLK0_CLK1_DFS_CNTL, CLK01, 0), \ +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-read-lttpr-alpm-caps-during-link-cap.patch b/queue-6.12/drm-amd-display-read-lttpr-alpm-caps-during-link-cap.patch new file mode 100644 index 0000000000..2fa0734af2 --- /dev/null +++ b/queue-6.12/drm-amd-display-read-lttpr-alpm-caps-during-link-cap.patch @@ -0,0 +1,92 @@ +From e0c52d80cec35d3168fb0d94c185c01c8d8456cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 14:34:02 -0500 +Subject: drm/amd/display: Read LTTPR ALPM caps during link cap retrieval + +From: George Shen + +[ Upstream commit de84d580126eb2214937df755cfec5ef0901479e ] + +[Why] +The latest DP spec requires the DP TX to read DPCD F0000h through F0009h +when detecting LTTPR capabilities for the first time. + +[How] +Update LTTPR cap retrieval to read up to F0009h (two more bytes than the +previous F0007h), and store the LTTPR ALPM capabilities. + +Reviewed-by: Wenjing Liu +Signed-off-by: George Shen +Signed-off-by: Roman Li +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 12 ++++++++++++ + .../display/dc/link/protocols/link_dp_capability.c | 6 +++++- + 2 files changed, 17 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +index 41bd95e9177a4..223c3d55544b2 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +@@ -959,6 +959,14 @@ union dp_128b_132b_supported_lttpr_link_rates { + uint8_t raw; + }; + ++union dp_alpm_lttpr_cap { ++ struct { ++ uint8_t AUX_LESS_ALPM_SUPPORTED :1; ++ uint8_t RESERVED :7; ++ } bits; ++ uint8_t raw; ++}; ++ + union dp_sink_video_fallback_formats { + struct { + uint8_t dp_1024x768_60Hz_24bpp_support :1; +@@ -1103,6 +1111,7 @@ struct dc_lttpr_caps { + uint8_t max_ext_timeout; + union dp_main_link_channel_coding_lttpr_cap main_link_channel_coding; + union dp_128b_132b_supported_lttpr_link_rates supported_128b_132b_rates; ++ union dp_alpm_lttpr_cap alpm; + uint8_t aux_rd_interval[MAX_REPEATER_CNT - 1]; + }; + +@@ -1352,6 +1361,9 @@ struct dp_trace { + #ifndef DPCD_MAX_UNCOMPRESSED_PIXEL_RATE_CAP + #define DPCD_MAX_UNCOMPRESSED_PIXEL_RATE_CAP 0x221c + #endif ++#ifndef DP_LTTPR_ALPM_CAPABILITIES ++#define DP_LTTPR_ALPM_CAPABILITIES 0xF0009 ++#endif + #ifndef DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE + #define DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE 0x50 + #endif +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +index d9a1e1a599674..842636c7922b4 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +@@ -1495,7 +1495,7 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link) + + enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link) + { +- uint8_t lttpr_dpcd_data[8] = {0}; ++ uint8_t lttpr_dpcd_data[10] = {0}; + enum dc_status status; + bool is_lttpr_present; + +@@ -1545,6 +1545,10 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link) + lttpr_dpcd_data[DP_PHY_REPEATER_128B132B_RATES - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + ++ link->dpcd_caps.lttpr_caps.alpm.raw = ++ lttpr_dpcd_data[DP_LTTPR_ALPM_CAPABILITIES - ++ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; ++ + /* If this chip cap is set, at least one retimer must exist in the chain + * Override count to 1 if we receive a known bad count (0 or an invalid value) */ + if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-remove-minimum-dispclk-and-apply-oem.patch b/queue-6.12/drm-amd-display-remove-minimum-dispclk-and-apply-oem.patch new file mode 100644 index 0000000000..4173d26141 --- /dev/null +++ b/queue-6.12/drm-amd-display-remove-minimum-dispclk-and-apply-oem.patch @@ -0,0 +1,71 @@ +From 14397f8734aa1734754f3c05af60ca791e7a8a27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 13:53:16 -0500 +Subject: drm/amd/display: remove minimum Dispclk and apply oem panel timing. + +From: Charlene Liu + +[ Upstream commit 756e58e83e89d372b94269c0cde61fe55da76947 ] + +[why & how] +1. apply oem panel timing (not only on OLED) +2. remove MIN_DPP_DISP_CLK request in driver. + +This fix will apply for dcn31x but not +sync with DML's output. + +Reviewed-by: Ovidiu Bunea +Signed-off-by: Charlene Liu +Signed-off-by: Tom Chung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c | 2 -- + drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c | 2 -- + drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 3 ++- + 3 files changed, 2 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +index 827b24b3442ad..e4d22f74f9869 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +@@ -194,8 +194,6 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base, + // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow. + if (new_clocks->dppclk_khz < MIN_DPP_DISP_CLK) + new_clocks->dppclk_khz = MIN_DPP_DISP_CLK; +- if (new_clocks->dispclk_khz < MIN_DPP_DISP_CLK) +- new_clocks->dispclk_khz = MIN_DPP_DISP_CLK; + + if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) { + if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz) +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +index 37c39756fece4..49efea0c8fcff 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +@@ -201,8 +201,6 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base, + // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow. + if (new_clocks->dppclk_khz < 100000) + new_clocks->dppclk_khz = 100000; +- if (new_clocks->dispclk_khz < 100000) +- new_clocks->dispclk_khz = 100000; + + if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) { + if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz) +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +index 1e76524d116dc..59457ca24e1dc 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +@@ -1064,7 +1064,8 @@ void dce110_edp_backlight_control( + DC_LOG_DC("edp_receiver_ready_T9 skipped\n"); + } + +- if (!enable && link->dpcd_sink_ext_caps.bits.oled) { ++ if (!enable) { ++ /*follow oem panel config's requirement*/ + pre_T11_delay += link->panel_config.pps.extra_pre_t11_ms; + msleep(pre_T11_delay); + } +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-request-hw-cursor-on-dcn3.2-with-sub.patch b/queue-6.12/drm-amd-display-request-hw-cursor-on-dcn3.2-with-sub.patch new file mode 100644 index 0000000000..40c195c46d --- /dev/null +++ b/queue-6.12/drm-amd-display-request-hw-cursor-on-dcn3.2-with-sub.patch @@ -0,0 +1,59 @@ +From d6cb0f813d45cf66b2c926284b0418af7d7a54cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 16:39:52 -0500 +Subject: drm/amd/display: Request HW cursor on DCN3.2 with SubVP + +From: Aric Cyr + +[ Upstream commit b74f46f3ce1e5f6336645f1e9ff47c56d5dfdef1 ] + +[why] +When SubVP is active the HW cursor size is limited to 64x64, and +anything larger will force composition which is bad for gaming on +DCN3.2 if the game uses a larger cursor. + +[how] +If HW cursor is requested, typically by a fullscreen game, do not +enable SubVP so that up to 256x256 cursor sizes are available for +DCN3.2. + +Reviewed-by: Aric Cyr +Signed-off-by: Aric Cyr +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 3 ++- + drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 1 + + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index dd4b131fac6cb..fa7db10104c45 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -4744,7 +4744,8 @@ static bool full_update_required(struct dc *dc, + stream_update->lut3d_func || + stream_update->pending_test_pattern || + stream_update->crtc_timing_adjust || +- stream_update->scaler_sharpener_update)) ++ stream_update->scaler_sharpener_update || ++ stream_update->hw_cursor_req)) + return true; + + if (stream) { +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +index 6f490d8d7038c..56dda686e2992 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +@@ -626,6 +626,7 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc, + * - Not TMZ surface + */ + if (pipe->plane_state && !pipe->top_pipe && !pipe->prev_odm_pipe && !dcn32_is_center_timing(pipe) && ++ !pipe->stream->hw_cursor_req && + !(pipe->stream->timing.pix_clk_100hz / 10000 > DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ) && + (!dcn32_is_psr_capable(pipe) || (context->stream_count == 1 && dc->caps.dmub_caps.subvp_psr)) && + dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_NONE && +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-skip-checking-frl_mode-bit-for-pcon-.patch b/queue-6.12/drm-amd-display-skip-checking-frl_mode-bit-for-pcon-.patch new file mode 100644 index 0000000000..4370312ed0 --- /dev/null +++ b/queue-6.12/drm-amd-display-skip-checking-frl_mode-bit-for-pcon-.patch @@ -0,0 +1,70 @@ +From d053aa9690d0fde790630c2d40ad2261e4b0fd27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 22:00:13 -0500 +Subject: drm/amd/display: Skip checking FRL_MODE bit for PCON BW determination + +From: George Shen + +[ Upstream commit 0584bbcf0c53c133081100e4f4c9fe41e598d045 ] + +[Why/How] +Certain PCON will clear the FRL_MODE bit despite supporting the link BW +indicated in the other bits. + +Thus, skip checking the FRL_MODE bit when interpreting the +hdmi_encoded_link_bw struct. + +Reviewed-by: Wenjing Liu +Signed-off-by: George Shen +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../dc/link/protocols/link_dp_capability.c | 30 +++++++++---------- + 1 file changed, 15 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +index 885e749cdc6e9..23e650e39910e 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +@@ -250,21 +250,21 @@ static uint32_t intersect_frl_link_bw_support( + { + uint32_t supported_bw_in_kbps = max_supported_frl_bw_in_kbps; + +- // HDMI_ENCODED_LINK_BW bits are only valid if HDMI Link Configuration bit is 1 (FRL mode) +- if (hdmi_encoded_link_bw.bits.FRL_MODE) { +- if (hdmi_encoded_link_bw.bits.BW_48Gbps) +- supported_bw_in_kbps = 48000000; +- else if (hdmi_encoded_link_bw.bits.BW_40Gbps) +- supported_bw_in_kbps = 40000000; +- else if (hdmi_encoded_link_bw.bits.BW_32Gbps) +- supported_bw_in_kbps = 32000000; +- else if (hdmi_encoded_link_bw.bits.BW_24Gbps) +- supported_bw_in_kbps = 24000000; +- else if (hdmi_encoded_link_bw.bits.BW_18Gbps) +- supported_bw_in_kbps = 18000000; +- else if (hdmi_encoded_link_bw.bits.BW_9Gbps) +- supported_bw_in_kbps = 9000000; +- } ++ /* Skip checking FRL_MODE bit, as certain PCON will clear ++ * it despite supporting the link BW indicated in the other bits. ++ */ ++ if (hdmi_encoded_link_bw.bits.BW_48Gbps) ++ supported_bw_in_kbps = 48000000; ++ else if (hdmi_encoded_link_bw.bits.BW_40Gbps) ++ supported_bw_in_kbps = 40000000; ++ else if (hdmi_encoded_link_bw.bits.BW_32Gbps) ++ supported_bw_in_kbps = 32000000; ++ else if (hdmi_encoded_link_bw.bits.BW_24Gbps) ++ supported_bw_in_kbps = 24000000; ++ else if (hdmi_encoded_link_bw.bits.BW_18Gbps) ++ supported_bw_in_kbps = 18000000; ++ else if (hdmi_encoded_link_bw.bits.BW_9Gbps) ++ supported_bw_in_kbps = 9000000; + + return supported_bw_in_kbps; + } +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-support-multiple-options-during-psr-.patch b/queue-6.12/drm-amd-display-support-multiple-options-during-psr-.patch new file mode 100644 index 0000000000..a00d701db3 --- /dev/null +++ b/queue-6.12/drm-amd-display-support-multiple-options-during-psr-.patch @@ -0,0 +1,81 @@ +From 7ccb1033c4f5df1a03a0b35ccaef018fcfdfd1c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jan 2025 11:21:46 +0800 +Subject: drm/amd/display: Support multiple options during psr entry. + +From: Martin Tsai + +[ Upstream commit 3a5fa55455db6a11248a25f24570c365f9246144 ] + +[WHY] +Some panels may not handle idle pattern properly during PSR entry. + +[HOW] +Add a condition to allow multiple options on power down +sequence during PSR1 entry. + +Reviewed-by: Anthony Koo +Signed-off-by: Martin Tsai +Signed-off-by: Alex Hung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dc_types.h | 7 +++++++ + drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 4 ++++ + drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 6 ++++++ + 3 files changed, 17 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h +index c8bdbbba44ef9..1aca9e96c474f 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_types.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_types.h +@@ -1009,6 +1009,13 @@ struct psr_settings { + unsigned int psr_sdp_transmit_line_num_deadline; + uint8_t force_ffu_mode; + unsigned int psr_power_opt; ++ ++ /** ++ * Some panels cannot handle idle pattern during PSR entry. ++ * To power down phy before disable stream to avoid sending ++ * idle pattern. ++ */ ++ uint8_t power_down_phy_before_disable_stream; + }; + + enum replay_coasting_vtotal_type { +diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +index cae18f8c1c9a0..8821153d0ac3b 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c ++++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +@@ -419,6 +419,10 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, + copy_settings_data->relock_delay_frame_cnt = 0; + if (link->dpcd_caps.sink_dev_id == DP_BRANCH_DEVICE_ID_001CF8) + copy_settings_data->relock_delay_frame_cnt = 2; ++ ++ copy_settings_data->power_down_phy_before_disable_stream = ++ link->psr_settings.power_down_phy_before_disable_stream; ++ + copy_settings_data->dsc_slice_height = psr_context->dsc_slice_height; + + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); +diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +index 7835100b37c41..d743368303682 100644 +--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h ++++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +@@ -2869,6 +2869,12 @@ struct dmub_cmd_psr_copy_settings_data { + * Some panels request main link off before xth vertical line + */ + uint16_t poweroff_before_vertical_line; ++ /** ++ * Some panels cannot handle idle pattern during PSR entry. ++ * To power down phy before disable stream to avoid sending ++ * idle pattern. ++ */ ++ uint8_t power_down_phy_before_disable_stream; + }; + + /** +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-update-cr-aux-rd-interval-interpreta.patch b/queue-6.12/drm-amd-display-update-cr-aux-rd-interval-interpreta.patch new file mode 100644 index 0000000000..ca0c9344c9 --- /dev/null +++ b/queue-6.12/drm-amd-display-update-cr-aux-rd-interval-interpreta.patch @@ -0,0 +1,71 @@ +From be24d5f7426a5d098b7197db5243c9a62413fb3f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jan 2025 11:35:46 -0500 +Subject: drm/amd/display: Update CR AUX RD interval interpretation + +From: George Shen + +[ Upstream commit 6a7fde433231c18164c117592d3e18ced648ad58 ] + +[Why] +DP spec updated to have the CR AUX RD interval match the EQ AUX RD +interval interpretation of DPCD 0000Eh/0220Eh for 8b/10b non-LTTPR mode +and LTTPR transparent mode cases. + +[How] +Update interpretation of DPCD 0000Eh/0220Eh for CR AUX RD interval +during 8b/10b link training. + +Reviewed-by: Michael Strauss +Reviewed-by: Wenjing Liu +Signed-off-by: George Shen +Signed-off-by: Zaeem Mohamed +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../display/dc/link/protocols/link_dp_training_8b_10b.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c +index 3bdce32a85e3c..ae95ec48e5721 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c +@@ -36,7 +36,8 @@ + link->ctx->logger + + static int32_t get_cr_training_aux_rd_interval(struct dc_link *link, +- const struct dc_link_settings *link_settings) ++ const struct dc_link_settings *link_settings, ++ enum lttpr_mode lttpr_mode) + { + union training_aux_rd_interval training_rd_interval; + uint32_t wait_in_micro_secs = 100; +@@ -49,6 +50,8 @@ static int32_t get_cr_training_aux_rd_interval(struct dc_link *link, + DP_TRAINING_AUX_RD_INTERVAL, + (uint8_t *)&training_rd_interval, + sizeof(training_rd_interval)); ++ if (lttpr_mode != LTTPR_MODE_NON_TRANSPARENT) ++ wait_in_micro_secs = 400; + if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) + wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000; + } +@@ -110,7 +113,6 @@ void decide_8b_10b_training_settings( + */ + lt_settings->link_settings.link_spread = link->dp_ss_off ? + LINK_SPREAD_DISABLED : LINK_SPREAD_05_DOWNSPREAD_30KHZ; +- lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting); + lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting); + lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting); + lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting); +@@ -119,6 +121,7 @@ void decide_8b_10b_training_settings( + lt_settings->disallow_per_lane_settings = true; + lt_settings->always_match_dpcd_with_hw_lane_settings = true; + lt_settings->lttpr_mode = dp_decide_8b_10b_lttpr_mode(link); ++ lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting, lt_settings->lttpr_mode); + dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings); + } + +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-display-use-nominal-vblank-if-provided-inste.patch b/queue-6.12/drm-amd-display-use-nominal-vblank-if-provided-inste.patch new file mode 100644 index 0000000000..e5f6ecda5f --- /dev/null +++ b/queue-6.12/drm-amd-display-use-nominal-vblank-if-provided-inste.patch @@ -0,0 +1,51 @@ +From 967add8d3b7996e7c4e07faad51710bc5901cbc5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jan 2025 17:49:36 -0500 +Subject: drm/amd/display: Use Nominal vBlank If Provided Instead Of Capping It + +From: Austin Zheng + +[ Upstream commit 41df56b1fc24cc36fffb10e437385b3a49fbb5e2 ] + +[Why/How] +vBlank used to determine the max vStartup is based on the smallest between +the vblank provided by the timing and vblank in ip_caps. +Extra vblank time is not considered if the vblank provided by the timing ends +up being higher than what's defined by the ip_caps + +Use 1 less than the vblank size in case the timing is interlaced +so vstartup will always be less than vblank_nom. + +Reviewed-by: Dillon Varone +Signed-off-by: Austin Zheng +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c +index e2a3764d9d181..0090b7bc232bf 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c ++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c +@@ -3630,13 +3630,12 @@ static unsigned int CalculateMaxVStartup( + double line_time_us = (double)timing->h_total / ((double)timing->pixel_clock_khz / 1000); + unsigned int vblank_actual = timing->v_total - timing->v_active; + unsigned int vblank_nom_default_in_line = (unsigned int)math_floor2((double)vblank_nom_default_us / line_time_us, 1.0); +- unsigned int vblank_nom_input = (unsigned int)math_min2(timing->vblank_nom, vblank_nom_default_in_line); +- unsigned int vblank_avail = (vblank_nom_input == 0) ? vblank_nom_default_in_line : vblank_nom_input; ++ unsigned int vblank_avail = (timing->vblank_nom == 0) ? vblank_nom_default_in_line : (unsigned int)timing->vblank_nom; + + vblank_size = (unsigned int)math_min2(vblank_actual, vblank_avail); + + if (timing->interlaced && !ptoi_supported) +- max_vstartup_lines = (unsigned int)(math_floor2(vblank_size / 2.0, 1.0)); ++ max_vstartup_lines = (unsigned int)(math_floor2((vblank_size - 1) / 2.0, 1.0)); + else + max_vstartup_lines = vblank_size - (unsigned int)math_max2(1.0, math_ceil2(write_back_delay_us / line_time_us, 1.0)); + #ifdef __DML_VBA_DEBUG__ +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-pm-fetch-current-power-limit-from-pmfw.patch b/queue-6.12/drm-amd-pm-fetch-current-power-limit-from-pmfw.patch new file mode 100644 index 0000000000..f96a146cb5 --- /dev/null +++ b/queue-6.12/drm-amd-pm-fetch-current-power-limit-from-pmfw.patch @@ -0,0 +1,35 @@ +From a1575df5c6909dbd6fdfaa1dd8f589170534a6a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 17:43:01 +0530 +Subject: drm/amd/pm: Fetch current power limit from PMFW + +From: Lijo Lazar + +[ Upstream commit b2a9e562dfa156bd53e62ce571f3f8f65d243f14 ] + +On SMU v13.0.12, always query the firmware to get the current power +limit as it could be updated through other means also. + +Signed-off-by: Lijo Lazar +Reviewed-by: Asad Kamal +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +index 99d2d3092ea54..3fd8da5dc761e 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +@@ -2772,6 +2772,7 @@ int smu_get_power_limit(void *handle, + switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { + case IP_VERSION(13, 0, 2): + case IP_VERSION(13, 0, 6): ++ case IP_VERSION(13, 0, 12): + case IP_VERSION(13, 0, 14): + case IP_VERSION(11, 0, 7): + case IP_VERSION(11, 0, 11): +-- +2.39.5 + diff --git a/queue-6.12/drm-amd-pm-skip-p2s-load-for-smu-v13.0.12.patch b/queue-6.12/drm-amd-pm-skip-p2s-load-for-smu-v13.0.12.patch new file mode 100644 index 0000000000..64c37cd8fd --- /dev/null +++ b/queue-6.12/drm-amd-pm-skip-p2s-load-for-smu-v13.0.12.patch @@ -0,0 +1,38 @@ +From b4e1e9652588887c4b4f0b92bbf3181915972488 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Dec 2024 19:16:37 +0800 +Subject: drm/amd/pm: Skip P2S load for SMU v13.0.12 + +From: Asad Kamal + +[ Upstream commit 1fb85819d629676f1d53f40c3fffa25a33a881e4 ] + +Skip P2S table load for SMU v13.0.12 + +Signed-off-by: Asad Kamal +Reviewed-by: Lijo Lazar +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +index 55ed6247eb61f..9ac694c4f1f7a 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +@@ -275,8 +275,9 @@ static int smu_v13_0_6_init_microcode(struct smu_context *smu) + int var = (adev->pdev->device & 0xF); + char ucode_prefix[15]; + +- /* No need to load P2S tables in IOV mode */ +- if (amdgpu_sriov_vf(adev)) ++ /* No need to load P2S tables in IOV mode or for smu v13.0.12 */ ++ if (amdgpu_sriov_vf(adev) || ++ (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 12))) + return 0; + + if (!(adev->flags & AMD_IS_APU)) { +-- +2.39.5 + diff --git a/queue-6.12/drm-amdgpu-adjust-drm_firmware_drivers_only-handling.patch b/queue-6.12/drm-amdgpu-adjust-drm_firmware_drivers_only-handling.patch new file mode 100644 index 0000000000..fb89f47304 --- /dev/null +++ b/queue-6.12/drm-amdgpu-adjust-drm_firmware_drivers_only-handling.patch @@ -0,0 +1,65 @@ +From 9085aa9327820cfd0b6a3786e922296cf0c5fa03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 20:52:38 -0400 +Subject: drm/amdgpu: adjust drm_firmware_drivers_only() handling + +From: Alex Deucher + +[ Upstream commit e00e5c223878a60e391e5422d173c3382d378f87 ] + +Move to probe so we can check the PCI device type and +only apply the drm_firmware_drivers_only() check for +PCI DISPLAY classes. Also add a module parameter to +override the nomodeset kernel parameter as a workaround +for platforms that have this hardcoded on their kernel +command lines. + +Reviewed-by: Kent Russell +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +index 1b479bd851354..93c3de2d27d3a 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +@@ -172,6 +172,7 @@ uint amdgpu_sdma_phase_quantum = 32; + char *amdgpu_disable_cu; + char *amdgpu_virtual_display; + bool enforce_isolation; ++int amdgpu_modeset = -1; + + /* Specifies the default granularity for SVM, used in buffer + * migration and restoration of backing memory when handling +@@ -1037,6 +1038,13 @@ module_param_named(user_partt_mode, amdgpu_user_partt_mode, uint, 0444); + module_param(enforce_isolation, bool, 0444); + MODULE_PARM_DESC(enforce_isolation, "enforce process isolation between graphics and compute . enforce_isolation = on"); + ++/** ++ * DOC: modeset (int) ++ * Override nomodeset (1 = override, -1 = auto). The default is -1 (auto). ++ */ ++MODULE_PARM_DESC(modeset, "Override nomodeset (1 = enable, -1 = auto)"); ++module_param_named(modeset, amdgpu_modeset, int, 0444); ++ + /** + * DOC: seamless (int) + * Seamless boot will keep the image on the screen during the boot process. +@@ -2248,6 +2256,12 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, + int ret, retry = 0, i; + bool supports_atomic = false; + ++ if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA || ++ (pdev->class >> 8) == PCI_CLASS_DISPLAY_OTHER) { ++ if (drm_firmware_drivers_only() && amdgpu_modeset == -1) ++ return -EINVAL; ++ } ++ + /* skip devices which are owned by radeon */ + for (i = 0; i < ARRAY_SIZE(amdgpu_unsupported_pciidlist); i++) { + if (amdgpu_unsupported_pciidlist[i] == pdev->device) +-- +2.39.5 + diff --git a/queue-6.12/drm-amdgpu-allow-p2p-access-through-xgmi.patch b/queue-6.12/drm-amdgpu-allow-p2p-access-through-xgmi.patch new file mode 100644 index 0000000000..3a722a8378 --- /dev/null +++ b/queue-6.12/drm-amdgpu-allow-p2p-access-through-xgmi.patch @@ -0,0 +1,87 @@ +From 90d1ed349a360345076dcb6880f58ce297cac5fd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Apr 2025 00:19:13 -0400 +Subject: drm/amdgpu: Allow P2P access through XGMI +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Felix Kuehling + +[ Upstream commit a92741e72f91b904c1d8c3d409ed8dbe9c1f2b26 ] + +If peer memory is accessible through XGMI, allow leaving it in VRAM +rather than forcing its migration to GTT on DMABuf attachment. + +Signed-off-by: Felix Kuehling +Tested-by: Hao (Claire) Zhou +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +(cherry picked from commit 372c8d72c3680fdea3fbb2d6b089f76b4a6d596a) +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 30 ++++++++++++++++++++- + 1 file changed, 29 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +index 2f90fff1b9ddc..e63a32c214475 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +@@ -42,6 +42,29 @@ + #include + #include + ++static const struct dma_buf_attach_ops amdgpu_dma_buf_attach_ops; ++ ++/** ++ * dma_buf_attach_adev - Helper to get adev of an attachment ++ * ++ * @attach: attachment ++ * ++ * Returns: ++ * A struct amdgpu_device * if the attaching device is an amdgpu device or ++ * partition, NULL otherwise. ++ */ ++static struct amdgpu_device *dma_buf_attach_adev(struct dma_buf_attachment *attach) ++{ ++ if (attach->importer_ops == &amdgpu_dma_buf_attach_ops) { ++ struct drm_gem_object *obj = attach->importer_priv; ++ struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); ++ ++ return amdgpu_ttm_adev(bo->tbo.bdev); ++ } ++ ++ return NULL; ++} ++ + /** + * amdgpu_dma_buf_attach - &dma_buf_ops.attach implementation + * +@@ -53,11 +76,13 @@ + static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attach) + { ++ struct amdgpu_device *attach_adev = dma_buf_attach_adev(attach); + struct drm_gem_object *obj = dmabuf->priv; + struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); + +- if (pci_p2pdma_distance(adev->pdev, attach->dev, false) < 0) ++ if (!amdgpu_dmabuf_is_xgmi_accessible(attach_adev, bo) && ++ pci_p2pdma_distance(adev->pdev, attach->dev, false) < 0) + attach->peer2peer = false; + + return 0; +@@ -456,6 +481,9 @@ bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev, + struct drm_gem_object *obj = &bo->tbo.base; + struct drm_gem_object *gobj; + ++ if (!adev) ++ return false; ++ + if (obj->import_attach) { + struct dma_buf *dma_buf = obj->import_attach->dmabuf; + +-- +2.39.5 + diff --git a/queue-6.12/drm-amdgpu-discovery-check-ip_discovery-fw-file-avai.patch b/queue-6.12/drm-amdgpu-discovery-check-ip_discovery-fw-file-avai.patch new file mode 100644 index 0000000000..9ab3a6b88f --- /dev/null +++ b/queue-6.12/drm-amdgpu-discovery-check-ip_discovery-fw-file-avai.patch @@ -0,0 +1,92 @@ +From 0dd177485a88232fbee4f7852267030716e167d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 10:39:27 +0800 +Subject: drm/amdgpu/discovery: check ip_discovery fw file available + +From: Flora Cui + +[ Upstream commit 017fbb6690c2245b1b4ef39b66c79d2990fe63dd ] + +Signed-off-by: Flora Cui +Reviewed-by: Alex Deucher +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 31 ++++++++++--------- + 1 file changed, 16 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +index ca8091fd3a24f..018240a2ab96a 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +@@ -111,8 +111,7 @@ + #include "amdgpu_isp.h" + #endif + +-#define FIRMWARE_IP_DISCOVERY "amdgpu/ip_discovery.bin" +-MODULE_FIRMWARE(FIRMWARE_IP_DISCOVERY); ++MODULE_FIRMWARE("amdgpu/ip_discovery.bin"); + + #define mmIP_DISCOVERY_VERSION 0x16A00 + #define mmRCC_CONFIG_MEMSIZE 0xde3 +@@ -295,21 +294,13 @@ static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev, + return ret; + } + +-static int amdgpu_discovery_read_binary_from_file(struct amdgpu_device *adev, uint8_t *binary) ++static int amdgpu_discovery_read_binary_from_file(struct amdgpu_device *adev, ++ uint8_t *binary, ++ const char *fw_name) + { + const struct firmware *fw; +- const char *fw_name; + int r; + +- switch (amdgpu_discovery) { +- case 2: +- fw_name = FIRMWARE_IP_DISCOVERY; +- break; +- default: +- dev_warn(adev->dev, "amdgpu_discovery is not set properly\n"); +- return -EINVAL; +- } +- + r = request_firmware(&fw, fw_name, adev->dev); + if (r) { + dev_err(adev->dev, "can't load firmware \"%s\"\n", +@@ -402,10 +393,19 @@ static int amdgpu_discovery_verify_npsinfo(struct amdgpu_device *adev, + return 0; + } + ++static const char *amdgpu_discovery_get_fw_name(struct amdgpu_device *adev) ++{ ++ if (amdgpu_discovery == 2) ++ return "amdgpu/ip_discovery.bin"; ++ ++ return NULL; ++} ++ + static int amdgpu_discovery_init(struct amdgpu_device *adev) + { + struct table_info *info; + struct binary_header *bhdr; ++ const char *fw_name; + uint16_t offset; + uint16_t size; + uint16_t checksum; +@@ -417,9 +417,10 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev) + return -ENOMEM; + + /* Read from file if it is the preferred option */ +- if (amdgpu_discovery == 2) { ++ fw_name = amdgpu_discovery_get_fw_name(adev); ++ if (fw_name != NULL) { + dev_info(adev->dev, "use ip discovery information from file"); +- r = amdgpu_discovery_read_binary_from_file(adev, adev->mman.discovery_bin); ++ r = amdgpu_discovery_read_binary_from_file(adev, adev->mman.discovery_bin, fw_name); + + if (r) { + dev_err(adev->dev, "failed to read ip discovery binary from file\n"); +-- +2.39.5 + diff --git a/queue-6.12/drm-amdgpu-do-not-program-agp-bar-regs-under-sriov-i.patch b/queue-6.12/drm-amdgpu-do-not-program-agp-bar-regs-under-sriov-i.patch new file mode 100644 index 0000000000..8dc4fd3aa9 --- /dev/null +++ b/queue-6.12/drm-amdgpu-do-not-program-agp-bar-regs-under-sriov-i.patch @@ -0,0 +1,45 @@ +From 46551ff428662e5b910fb7528f97fe1bc637fb6a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 18:38:28 -0500 +Subject: drm/amdgpu: Do not program AGP BAR regs under SRIOV in gfxhub_v1_0.c + +From: Victor Lu + +[ Upstream commit 057fef20b8401110a7bc1c2fe9d804a8a0bf0d24 ] + +SRIOV VF does not have write access to AGP BAR regs. +Skip the writes to avoid a dmesg warning. + +Signed-off-by: Victor Lu +Acked-by: Alex Deucher +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c +index 0e3ddea7b8e0f..a7bfc9f41d0e3 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c +@@ -92,12 +92,12 @@ static void gfxhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev) + { + uint64_t value; + +- /* Program the AGP BAR */ +- WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BASE, 0); +- WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BOT, adev->gmc.agp_start >> 24); +- WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_TOP, adev->gmc.agp_end >> 24); +- + if (!amdgpu_sriov_vf(adev) || adev->asic_type <= CHIP_VEGA10) { ++ /* Program the AGP BAR */ ++ WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BASE, 0); ++ WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BOT, adev->gmc.agp_start >> 24); ++ WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_TOP, adev->gmc.agp_end >> 24); ++ + /* Program the system aperture low logical page number. */ + WREG32_SOC15_RLC(GC, 0, mmMC_VM_SYSTEM_APERTURE_LOW_ADDR, + min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18); +-- +2.39.5 + diff --git a/queue-6.12/drm-amdgpu-enlarge-the-vbios-binary-size-limit.patch b/queue-6.12/drm-amdgpu-enlarge-the-vbios-binary-size-limit.patch new file mode 100644 index 0000000000..5a17d236aa --- /dev/null +++ b/queue-6.12/drm-amdgpu-enlarge-the-vbios-binary-size-limit.patch @@ -0,0 +1,36 @@ +From 23b64bba5d08a57a61b3bded0e0536afd8d3fdc5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Nov 2024 15:58:39 +0800 +Subject: drm/amdgpu: enlarge the VBIOS binary size limit + +From: Shiwu Zhang + +[ Upstream commit 667b96134c9e206aebe40985650bf478935cbe04 ] + +Some chips have a larger VBIOS file so raise the size limit to support +the flashing tool. + +Signed-off-by: Shiwu Zhang +Reviewed-by: Hawking Zhang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +index 31a376f2742a2..48e30e5f83389 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +@@ -44,7 +44,7 @@ + #include "amdgpu_securedisplay.h" + #include "amdgpu_atomfirmware.h" + +-#define AMD_VBIOS_FILE_MAX_SIZE_B (1024*1024*3) ++#define AMD_VBIOS_FILE_MAX_SIZE_B (1024*1024*16) + + static int psp_load_smu_fw(struct psp_context *psp); + static int psp_rap_terminate(struct psp_context *psp); +-- +2.39.5 + diff --git a/queue-6.12/drm-amdgpu-fix-missing-drain-retry-fault-the-last-en.patch b/queue-6.12/drm-amdgpu-fix-missing-drain-retry-fault-the-last-en.patch new file mode 100644 index 0000000000..3868cd5e1f --- /dev/null +++ b/queue-6.12/drm-amdgpu-fix-missing-drain-retry-fault-the-last-en.patch @@ -0,0 +1,55 @@ +From c39e82136173f72caa0ef67bf71ba67aa5f8dc8b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 15:10:22 +0800 +Subject: drm/amdgpu: Fix missing drain retry fault the last entry + +From: Emily Deng + +[ Upstream commit fe2fa3be3d59ba67d6de54a0064441ec233cb50c ] + +While the entry get in svm_range_unmap_from_cpu is the last entry, and +the entry is page fault, it also need to be dropped. So for equal case, +it also need to be dropped. + +v2: +Only modify the svm_range_restore_pages. + +Signed-off-by: Emily Deng +Reviewed-by: Xiaogang Chen +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h | 3 +++ + drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 2 +- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h +index 508f02eb0cf8f..7de10208e8dde 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h +@@ -78,6 +78,9 @@ struct amdgpu_ih_ring { + #define amdgpu_ih_ts_after(t1, t2) \ + (((int64_t)((t2) << 16) - (int64_t)((t1) << 16)) > 0LL) + ++#define amdgpu_ih_ts_after_or_equal(t1, t2) \ ++ (((int64_t)((t2) << 16) - (int64_t)((t1) << 16)) >= 0LL) ++ + /* provided by the ih block */ + struct amdgpu_ih_funcs { + /* ring read/write ptr handling, called from interrupt context */ +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +index b50283864dcd2..f00d41be7fca2 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +@@ -3014,7 +3014,7 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid, + + /* check if this page fault time stamp is before svms->checkpoint_ts */ + if (svms->checkpoint_ts[gpuidx] != 0) { +- if (amdgpu_ih_ts_after(ts, svms->checkpoint_ts[gpuidx])) { ++ if (amdgpu_ih_ts_after_or_equal(ts, svms->checkpoint_ts[gpuidx])) { + pr_debug("draining retry fault, drop fault 0x%llx\n", addr); + r = -EAGAIN; + goto out_unlock_svms; +-- +2.39.5 + diff --git a/queue-6.12/drm-amdgpu-gfx11-don-t-read-registers-in-mqd-init.patch b/queue-6.12/drm-amdgpu-gfx11-don-t-read-registers-in-mqd-init.patch new file mode 100644 index 0000000000..d1fa916e48 --- /dev/null +++ b/queue-6.12/drm-amdgpu-gfx11-don-t-read-registers-in-mqd-init.patch @@ -0,0 +1,178 @@ +From ab97d73375289196975ff9d7c7af9c59152151ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 15:55:33 -0500 +Subject: drm/amdgpu/gfx11: don't read registers in mqd init + +From: Alex Deucher + +[ Upstream commit e27b36ea6ba5f29e91fcfb375ea29503708fcf43 ] + +Just use the default values. There's not need to +get the value from hardware and it could cause problems +if we do that at runtime and gfxoff is active. + +Reviewed-by: Mukul Joshi +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 47 ++++++++++++++++++-------- + 1 file changed, 32 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +index 0357fea8ae1df..1f06b22dbe7c6 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +@@ -63,6 +63,23 @@ + #define regPC_CONFIG_CNTL_1 0x194d + #define regPC_CONFIG_CNTL_1_BASE_IDX 1 + ++#define regCP_GFX_MQD_CONTROL_DEFAULT 0x00000100 ++#define regCP_GFX_HQD_VMID_DEFAULT 0x00000000 ++#define regCP_GFX_HQD_QUEUE_PRIORITY_DEFAULT 0x00000000 ++#define regCP_GFX_HQD_QUANTUM_DEFAULT 0x00000a01 ++#define regCP_GFX_HQD_CNTL_DEFAULT 0x00a00000 ++#define regCP_RB_DOORBELL_CONTROL_DEFAULT 0x00000000 ++#define regCP_GFX_HQD_RPTR_DEFAULT 0x00000000 ++ ++#define regCP_HQD_EOP_CONTROL_DEFAULT 0x00000006 ++#define regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT 0x00000000 ++#define regCP_MQD_CONTROL_DEFAULT 0x00000100 ++#define regCP_HQD_PQ_CONTROL_DEFAULT 0x00308509 ++#define regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT 0x00000000 ++#define regCP_HQD_PQ_RPTR_DEFAULT 0x00000000 ++#define regCP_HQD_PERSISTENT_STATE_DEFAULT 0x0be05501 ++#define regCP_HQD_IB_CONTROL_DEFAULT 0x00300000 ++ + MODULE_FIRMWARE("amdgpu/gc_11_0_0_pfp.bin"); + MODULE_FIRMWARE("amdgpu/gc_11_0_0_me.bin"); + MODULE_FIRMWARE("amdgpu/gc_11_0_0_mec.bin"); +@@ -3896,7 +3913,7 @@ static void gfx_v11_0_gfx_mqd_set_priority(struct amdgpu_device *adev, + if (prop->hqd_pipe_priority == AMDGPU_GFX_PIPE_PRIO_HIGH) + priority = 1; + +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_QUEUE_PRIORITY); ++ tmp = regCP_GFX_HQD_QUEUE_PRIORITY_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_QUEUE_PRIORITY, PRIORITY_LEVEL, priority); + mqd->cp_gfx_hqd_queue_priority = tmp; + } +@@ -3918,14 +3935,14 @@ static int gfx_v11_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_mqd_base_addr_hi = upper_32_bits(prop->mqd_gpu_addr); + + /* set up mqd control */ +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_MQD_CONTROL); ++ tmp = regCP_GFX_MQD_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_MQD_CONTROL, VMID, 0); + tmp = REG_SET_FIELD(tmp, CP_GFX_MQD_CONTROL, PRIV_STATE, 1); + tmp = REG_SET_FIELD(tmp, CP_GFX_MQD_CONTROL, CACHE_POLICY, 0); + mqd->cp_gfx_mqd_control = tmp; + + /* set up gfx_hqd_vimd with 0x0 to indicate the ring buffer's vmid */ +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_VMID); ++ tmp = regCP_GFX_HQD_VMID_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_VMID, VMID, 0); + mqd->cp_gfx_hqd_vmid = 0; + +@@ -3933,7 +3950,7 @@ static int gfx_v11_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, + gfx_v11_0_gfx_mqd_set_priority(adev, mqd, prop); + + /* set up time quantum */ +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_QUANTUM); ++ tmp = regCP_GFX_HQD_QUANTUM_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_QUANTUM, QUANTUM_EN, 1); + mqd->cp_gfx_hqd_quantum = tmp; + +@@ -3955,7 +3972,7 @@ static int gfx_v11_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, + + /* set up the gfx_hqd_control, similar as CP_RB0_CNTL */ + rb_bufsz = order_base_2(prop->queue_size / 4) - 1; +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_CNTL); ++ tmp = regCP_GFX_HQD_CNTL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, RB_BUFSZ, rb_bufsz); + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, RB_BLKSZ, rb_bufsz - 2); + #ifdef __BIG_ENDIAN +@@ -3964,7 +3981,7 @@ static int gfx_v11_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_gfx_hqd_cntl = tmp; + + /* set up cp_doorbell_control */ +- tmp = RREG32_SOC15(GC, 0, regCP_RB_DOORBELL_CONTROL); ++ tmp = regCP_RB_DOORBELL_CONTROL_DEFAULT; + if (prop->use_doorbell) { + tmp = REG_SET_FIELD(tmp, CP_RB_DOORBELL_CONTROL, + DOORBELL_OFFSET, prop->doorbell_index); +@@ -3976,7 +3993,7 @@ static int gfx_v11_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_rb_doorbell_control = tmp; + + /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */ +- mqd->cp_gfx_hqd_rptr = RREG32_SOC15(GC, 0, regCP_GFX_HQD_RPTR); ++ mqd->cp_gfx_hqd_rptr = regCP_GFX_HQD_RPTR_DEFAULT; + + /* active the queue */ + mqd->cp_gfx_hqd_active = 1; +@@ -4062,14 +4079,14 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr); + + /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */ +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_EOP_CONTROL); ++ tmp = regCP_HQD_EOP_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE, + (order_base_2(GFX11_MEC_HPD_SIZE / 4) - 1)); + + mqd->cp_hqd_eop_control = tmp; + + /* enable doorbell? */ +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL); ++ tmp = regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT; + + if (prop->use_doorbell) { + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, +@@ -4098,7 +4115,7 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_mqd_base_addr_hi = upper_32_bits(prop->mqd_gpu_addr); + + /* set MQD vmid to 0 */ +- tmp = RREG32_SOC15(GC, 0, regCP_MQD_CONTROL); ++ tmp = regCP_MQD_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_MQD_CONTROL, VMID, 0); + mqd->cp_mqd_control = tmp; + +@@ -4108,7 +4125,7 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr); + + /* set up the HQD, this is similar to CP_RB0_CNTL */ +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PQ_CONTROL); ++ tmp = regCP_HQD_PQ_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, QUEUE_SIZE, + (order_base_2(prop->queue_size / 4) - 1)); + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE, +@@ -4134,7 +4151,7 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + tmp = 0; + /* enable the doorbell if requested */ + if (prop->use_doorbell) { +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL); ++ tmp = regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, + DOORBELL_OFFSET, prop->doorbell_index); + +@@ -4149,17 +4166,17 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_hqd_pq_doorbell_control = tmp; + + /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */ +- mqd->cp_hqd_pq_rptr = RREG32_SOC15(GC, 0, regCP_HQD_PQ_RPTR); ++ mqd->cp_hqd_pq_rptr = regCP_HQD_PQ_RPTR_DEFAULT; + + /* set the vmid for the queue */ + mqd->cp_hqd_vmid = 0; + +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PERSISTENT_STATE); ++ tmp = regCP_HQD_PERSISTENT_STATE_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x55); + mqd->cp_hqd_persistent_state = tmp; + + /* set MIN_IB_AVAIL_SIZE */ +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_IB_CONTROL); ++ tmp = regCP_HQD_IB_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_IB_CONTROL, MIN_IB_AVAIL_SIZE, 3); + mqd->cp_hqd_ib_control = tmp; + +-- +2.39.5 + diff --git a/queue-6.12/drm-amdgpu-gfx12-don-t-read-registers-in-mqd-init.patch b/queue-6.12/drm-amdgpu-gfx12-don-t-read-registers-in-mqd-init.patch new file mode 100644 index 0000000000..5af41db62c --- /dev/null +++ b/queue-6.12/drm-amdgpu-gfx12-don-t-read-registers-in-mqd-init.patch @@ -0,0 +1,174 @@ +From bc1b6e91b1c039f7204b4d31561b769162c6f288 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 16:08:03 -0500 +Subject: drm/amdgpu/gfx12: don't read registers in mqd init + +From: Alex Deucher + +[ Upstream commit fc3c139cf0432b79fd08e23100a559ee51cd0be4 ] + +Just use the default values. There's not need to +get the value from hardware and it could cause problems +if we do that at runtime and gfxoff is active. + +Reviewed-by: Mukul Joshi +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 48 ++++++++++++++++++-------- + 1 file changed, 33 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c +index 241619ee10e4b..adcfcf594286f 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c +@@ -52,6 +52,24 @@ + + #define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L + ++#define regCP_GFX_MQD_CONTROL_DEFAULT 0x00000100 ++#define regCP_GFX_HQD_VMID_DEFAULT 0x00000000 ++#define regCP_GFX_HQD_QUEUE_PRIORITY_DEFAULT 0x00000000 ++#define regCP_GFX_HQD_QUANTUM_DEFAULT 0x00000a01 ++#define regCP_GFX_HQD_CNTL_DEFAULT 0x00f00000 ++#define regCP_RB_DOORBELL_CONTROL_DEFAULT 0x00000000 ++#define regCP_GFX_HQD_RPTR_DEFAULT 0x00000000 ++ ++#define regCP_HQD_EOP_CONTROL_DEFAULT 0x00000006 ++#define regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT 0x00000000 ++#define regCP_MQD_CONTROL_DEFAULT 0x00000100 ++#define regCP_HQD_PQ_CONTROL_DEFAULT 0x00308509 ++#define regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT 0x00000000 ++#define regCP_HQD_PQ_RPTR_DEFAULT 0x00000000 ++#define regCP_HQD_PERSISTENT_STATE_DEFAULT 0x0be05501 ++#define regCP_HQD_IB_CONTROL_DEFAULT 0x00300000 ++ ++ + MODULE_FIRMWARE("amdgpu/gc_12_0_0_pfp.bin"); + MODULE_FIRMWARE("amdgpu/gc_12_0_0_me.bin"); + MODULE_FIRMWARE("amdgpu/gc_12_0_0_mec.bin"); +@@ -2851,25 +2869,25 @@ static int gfx_v12_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_mqd_base_addr_hi = upper_32_bits(prop->mqd_gpu_addr); + + /* set up mqd control */ +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_MQD_CONTROL); ++ tmp = regCP_GFX_MQD_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_MQD_CONTROL, VMID, 0); + tmp = REG_SET_FIELD(tmp, CP_GFX_MQD_CONTROL, PRIV_STATE, 1); + tmp = REG_SET_FIELD(tmp, CP_GFX_MQD_CONTROL, CACHE_POLICY, 0); + mqd->cp_gfx_mqd_control = tmp; + + /* set up gfx_hqd_vimd with 0x0 to indicate the ring buffer's vmid */ +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_VMID); ++ tmp = regCP_GFX_HQD_VMID_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_VMID, VMID, 0); + mqd->cp_gfx_hqd_vmid = 0; + + /* set up default queue priority level + * 0x0 = low priority, 0x1 = high priority */ +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_QUEUE_PRIORITY); ++ tmp = regCP_GFX_HQD_QUEUE_PRIORITY_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_QUEUE_PRIORITY, PRIORITY_LEVEL, 0); + mqd->cp_gfx_hqd_queue_priority = tmp; + + /* set up time quantum */ +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_QUANTUM); ++ tmp = regCP_GFX_HQD_QUANTUM_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_QUANTUM, QUANTUM_EN, 1); + mqd->cp_gfx_hqd_quantum = tmp; + +@@ -2891,7 +2909,7 @@ static int gfx_v12_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, + + /* set up the gfx_hqd_control, similar as CP_RB0_CNTL */ + rb_bufsz = order_base_2(prop->queue_size / 4) - 1; +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_CNTL); ++ tmp = regCP_GFX_HQD_CNTL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, RB_BUFSZ, rb_bufsz); + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, RB_BLKSZ, rb_bufsz - 2); + #ifdef __BIG_ENDIAN +@@ -2900,7 +2918,7 @@ static int gfx_v12_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_gfx_hqd_cntl = tmp; + + /* set up cp_doorbell_control */ +- tmp = RREG32_SOC15(GC, 0, regCP_RB_DOORBELL_CONTROL); ++ tmp = regCP_RB_DOORBELL_CONTROL_DEFAULT; + if (prop->use_doorbell) { + tmp = REG_SET_FIELD(tmp, CP_RB_DOORBELL_CONTROL, + DOORBELL_OFFSET, prop->doorbell_index); +@@ -2912,7 +2930,7 @@ static int gfx_v12_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_rb_doorbell_control = tmp; + + /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */ +- mqd->cp_gfx_hqd_rptr = RREG32_SOC15(GC, 0, regCP_GFX_HQD_RPTR); ++ mqd->cp_gfx_hqd_rptr = regCP_GFX_HQD_RPTR_DEFAULT; + + /* active the queue */ + mqd->cp_gfx_hqd_active = 1; +@@ -3007,14 +3025,14 @@ static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr); + + /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */ +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_EOP_CONTROL); ++ tmp = regCP_HQD_EOP_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE, + (order_base_2(GFX12_MEC_HPD_SIZE / 4) - 1)); + + mqd->cp_hqd_eop_control = tmp; + + /* enable doorbell? */ +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL); ++ tmp = regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT; + + if (prop->use_doorbell) { + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, +@@ -3043,7 +3061,7 @@ static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_mqd_base_addr_hi = upper_32_bits(prop->mqd_gpu_addr); + + /* set MQD vmid to 0 */ +- tmp = RREG32_SOC15(GC, 0, regCP_MQD_CONTROL); ++ tmp = regCP_MQD_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_MQD_CONTROL, VMID, 0); + mqd->cp_mqd_control = tmp; + +@@ -3053,7 +3071,7 @@ static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr); + + /* set up the HQD, this is similar to CP_RB0_CNTL */ +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PQ_CONTROL); ++ tmp = regCP_HQD_PQ_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, QUEUE_SIZE, + (order_base_2(prop->queue_size / 4) - 1)); + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE, +@@ -3078,7 +3096,7 @@ static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + tmp = 0; + /* enable the doorbell if requested */ + if (prop->use_doorbell) { +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL); ++ tmp = regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, + DOORBELL_OFFSET, prop->doorbell_index); + +@@ -3093,17 +3111,17 @@ static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_hqd_pq_doorbell_control = tmp; + + /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */ +- mqd->cp_hqd_pq_rptr = RREG32_SOC15(GC, 0, regCP_HQD_PQ_RPTR); ++ mqd->cp_hqd_pq_rptr = regCP_HQD_PQ_RPTR_DEFAULT; + + /* set the vmid for the queue */ + mqd->cp_hqd_vmid = 0; + +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PERSISTENT_STATE); ++ tmp = regCP_HQD_PERSISTENT_STATE_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x55); + mqd->cp_hqd_persistent_state = tmp; + + /* set MIN_IB_AVAIL_SIZE */ +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_IB_CONTROL); ++ tmp = regCP_HQD_IB_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_IB_CONTROL, MIN_IB_AVAIL_SIZE, 3); + mqd->cp_hqd_ib_control = tmp; + +-- +2.39.5 + diff --git a/queue-6.12/drm-amdgpu-mes11-fix-set_hw_resources_1-calculation.patch b/queue-6.12/drm-amdgpu-mes11-fix-set_hw_resources_1-calculation.patch new file mode 100644 index 0000000000..455b6cbb20 --- /dev/null +++ b/queue-6.12/drm-amdgpu-mes11-fix-set_hw_resources_1-calculation.patch @@ -0,0 +1,41 @@ +From 054fe174f049544d13d659da22274b9ec636d524 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 09:39:24 -0500 +Subject: drm/amdgpu/mes11: fix set_hw_resources_1 calculation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alex Deucher + +[ Upstream commit 1350dd3691b5f757a948e5b9895d62c422baeb90 ] + +It's GPU page size not CPU page size. In most cases they +are the same, but not always. This can lead to overallocation +on systems with larger pages. + +Cc: Srinivasan Shanmugam +Cc: Christian König +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +index 7a773fcd7752c..49113df8baefd 100644 +--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +@@ -690,7 +690,7 @@ static int mes_v11_0_set_hw_resources(struct amdgpu_mes *mes) + + static int mes_v11_0_set_hw_resources_1(struct amdgpu_mes *mes) + { +- int size = 128 * PAGE_SIZE; ++ int size = 128 * AMDGPU_GPU_PAGE_SIZE; + int ret = 0; + struct amdgpu_device *adev = mes->adev; + union MESAPI_SET_HW_RESOURCES_1 mes_set_hw_res_pkt; +-- +2.39.5 + diff --git a/queue-6.12/drm-amdgpu-release-xcp_mgr-on-exit.patch b/queue-6.12/drm-amdgpu-release-xcp_mgr-on-exit.patch new file mode 100644 index 0000000000..390dead902 --- /dev/null +++ b/queue-6.12/drm-amdgpu-release-xcp_mgr-on-exit.patch @@ -0,0 +1,36 @@ +From c602050350944d1d50d35a41fa5c934b29d81286 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 10:27:55 +0800 +Subject: drm/amdgpu: release xcp_mgr on exit + +From: Flora Cui + +[ Upstream commit b5aaa82e2b12feaaa6958f7fa0917ddcc03c24ee ] + +Free on driver cleanup. + +Reviewed-by: Lijo Lazar +Signed-off-by: Flora Cui +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index 081c0e45779fc..ca0411c9500e7 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -4677,6 +4677,9 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev) + kfree(adev->fru_info); + adev->fru_info = NULL; + ++ kfree(adev->xcp_mgr); ++ adev->xcp_mgr = NULL; ++ + px = amdgpu_device_supports_px(adev_to_drm(adev)); + + if (px || (!dev_is_removable(&adev->pdev->dev) && +-- +2.39.5 + diff --git a/queue-6.12/drm-amdgpu-remove-all-kfd-fences-from-the-bo-on-rele.patch b/queue-6.12/drm-amdgpu-remove-all-kfd-fences-from-the-bo-on-rele.patch new file mode 100644 index 0000000000..e4535c7725 --- /dev/null +++ b/queue-6.12/drm-amdgpu-remove-all-kfd-fences-from-the-bo-on-rele.patch @@ -0,0 +1,179 @@ +From 2857551c382f998f422dd88599e853aa6460a338 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 16:28:49 +0100 +Subject: drm/amdgpu: remove all KFD fences from the BO on release +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Christian König + +[ Upstream commit cb0de06d1b0afb2d0c600ad748069f5ce27730ec ] + +Remove all KFD BOs from the private dma_resv object. + +This prevents the KFD from being evict unecessarily when an exported BO +is released. + +Signed-off-by: Christian König +Signed-off-by: James Zhu +Reviewed-by: Felix Kuehling +Reviewed-and-tested-by: James Zhu +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 5 +- + .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 52 ++++++++----------- + drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 38 ++++++++------ + 3 files changed, 47 insertions(+), 48 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +index f9d1194484423..581fe1a48f376 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +@@ -192,7 +192,7 @@ int kfd_debugfs_kfd_mem_limits(struct seq_file *m, void *data); + #if IS_ENABLED(CONFIG_HSA_AMD) + bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm); + struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f); +-int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo); ++void amdgpu_amdkfd_remove_all_eviction_fences(struct amdgpu_bo *bo); + int amdgpu_amdkfd_evict_userptr(struct mmu_interval_notifier *mni, + unsigned long cur_seq, struct kgd_mem *mem); + int amdgpu_amdkfd_bo_validate_and_fence(struct amdgpu_bo *bo, +@@ -212,9 +212,8 @@ struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f) + } + + static inline +-int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo) ++void amdgpu_amdkfd_remove_all_eviction_fences(struct amdgpu_bo *bo) + { +- return 0; + } + + static inline +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +index fa572ba7f9fc1..1465b3adacb0a 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +@@ -370,40 +370,32 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo, + return 0; + } + +-int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo) ++/** ++ * amdgpu_amdkfd_remove_all_eviction_fences - Remove all eviction fences ++ * @bo: the BO where to remove the evictions fences from. ++ * ++ * This functions should only be used on release when all references to the BO ++ * are already dropped. We remove the eviction fence from the private copy of ++ * the dma_resv object here since that is what is used during release to ++ * determine of the BO is idle or not. ++ */ ++void amdgpu_amdkfd_remove_all_eviction_fences(struct amdgpu_bo *bo) + { +- struct amdgpu_bo *root = bo; +- struct amdgpu_vm_bo_base *vm_bo; +- struct amdgpu_vm *vm; +- struct amdkfd_process_info *info; +- struct amdgpu_amdkfd_fence *ef; +- int ret; +- +- /* we can always get vm_bo from root PD bo.*/ +- while (root->parent) +- root = root->parent; ++ struct dma_resv *resv = &bo->tbo.base._resv; ++ struct dma_fence *fence, *stub; ++ struct dma_resv_iter cursor; + +- vm_bo = root->vm_bo; +- if (!vm_bo) +- return 0; ++ dma_resv_assert_held(resv); + +- vm = vm_bo->vm; +- if (!vm) +- return 0; +- +- info = vm->process_info; +- if (!info || !info->eviction_fence) +- return 0; +- +- ef = container_of(dma_fence_get(&info->eviction_fence->base), +- struct amdgpu_amdkfd_fence, base); +- +- BUG_ON(!dma_resv_trylock(bo->tbo.base.resv)); +- ret = amdgpu_amdkfd_remove_eviction_fence(bo, ef); +- dma_resv_unlock(bo->tbo.base.resv); ++ stub = dma_fence_get_stub(); ++ dma_resv_for_each_fence(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP, fence) { ++ if (!to_amdgpu_amdkfd_fence(fence)) ++ continue; + +- dma_fence_put(&ef->base); +- return ret; ++ dma_resv_replace_fences(resv, fence->context, stub, ++ DMA_RESV_USAGE_BOOKKEEP); ++ } ++ dma_fence_put(stub); + } + + static int amdgpu_amdkfd_bo_validate(struct amdgpu_bo *bo, uint32_t domain, +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +index 4c4bdc4f51b29..fc588ef598c09 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +@@ -1246,28 +1246,36 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo) + if (abo->kfd_bo) + amdgpu_amdkfd_release_notify(abo); + +- /* We only remove the fence if the resv has individualized. */ +- WARN_ON_ONCE(bo->type == ttm_bo_type_kernel +- && bo->base.resv != &bo->base._resv); +- if (bo->base.resv == &bo->base._resv) +- amdgpu_amdkfd_remove_fence_on_pt_pd_bos(abo); ++ /* ++ * We lock the private dma_resv object here and since the BO is about to ++ * be released nobody else should have a pointer to it. ++ * So when this locking here fails something is wrong with the reference ++ * counting. ++ */ ++ if (WARN_ON_ONCE(!dma_resv_trylock(&bo->base._resv))) ++ return; ++ ++ amdgpu_amdkfd_remove_all_eviction_fences(abo); + + if (!bo->resource || bo->resource->mem_type != TTM_PL_VRAM || + !(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE) || + adev->in_suspend || drm_dev_is_unplugged(adev_to_drm(adev))) +- return; ++ goto out; + +- if (WARN_ON_ONCE(!dma_resv_trylock(bo->base.resv))) +- return; ++ r = dma_resv_reserve_fences(&bo->base._resv, 1); ++ if (r) ++ goto out; + +- r = amdgpu_fill_buffer(abo, 0, bo->base.resv, &fence, true); +- if (!WARN_ON(r)) { +- amdgpu_vram_mgr_set_cleared(bo->resource); +- amdgpu_bo_fence(abo, fence, false); +- dma_fence_put(fence); +- } ++ r = amdgpu_fill_buffer(abo, 0, &bo->base._resv, &fence, true); ++ if (WARN_ON(r)) ++ goto out; ++ ++ amdgpu_vram_mgr_set_cleared(bo->resource); ++ dma_resv_add_fence(&bo->base._resv, fence, DMA_RESV_USAGE_KERNEL); ++ dma_fence_put(fence); + +- dma_resv_unlock(bo->base.resv); ++out: ++ dma_resv_unlock(&bo->base._resv); + } + + /** +-- +2.39.5 + diff --git a/queue-6.12/drm-amdgpu-reset-psp-cmd-to-null-after-releasing-the.patch b/queue-6.12/drm-amdgpu-reset-psp-cmd-to-null-after-releasing-the.patch new file mode 100644 index 0000000000..9a81d5f74d --- /dev/null +++ b/queue-6.12/drm-amdgpu-reset-psp-cmd-to-null-after-releasing-the.patch @@ -0,0 +1,45 @@ +From f1a9ee5a1dc5ba4691bcbe1facbccf3646a2d4b0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 14:28:49 +0800 +Subject: drm/amdgpu: reset psp->cmd to NULL after releasing the buffer + +From: Jiang Liu + +[ Upstream commit e92f3f94cad24154fd3baae30c6dfb918492278d ] + +Reset psp->cmd to NULL after releasing the buffer in function psp_sw_fini(). + +Reviewed-by: Lijo Lazar +Signed-off-by: Jiang Liu +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +index d70855d7c61c1..31a376f2742a2 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +@@ -531,7 +531,6 @@ static int psp_sw_fini(void *handle) + { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct psp_context *psp = &adev->psp; +- struct psp_gfx_cmd_resp *cmd = psp->cmd; + + psp_memory_training_fini(psp); + +@@ -541,8 +540,8 @@ static int psp_sw_fini(void *handle) + amdgpu_ucode_release(&psp->cap_fw); + amdgpu_ucode_release(&psp->toc_fw); + +- kfree(cmd); +- cmd = NULL; ++ kfree(psp->cmd); ++ psp->cmd = NULL; + + psp_free_shared_bufs(psp); + +-- +2.39.5 + diff --git a/queue-6.12/drm-amdgpu-set-snoop-bit-for-sdma-for-mi-series.patch b/queue-6.12/drm-amdgpu-set-snoop-bit-for-sdma-for-mi-series.patch new file mode 100644 index 0000000000..0adb8cfc7c --- /dev/null +++ b/queue-6.12/drm-amdgpu-set-snoop-bit-for-sdma-for-mi-series.patch @@ -0,0 +1,368 @@ +From 6beea77658fda7e59e462ff26b55334d375b1d9c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 17:57:47 -0500 +Subject: drm/amdgpu: Set snoop bit for SDMA for MI series + +From: Harish Kasiviswanathan + +[ Upstream commit 3394b1f76d3f8adf695ceed350a5dae49003eb37 ] + +SDMA writes has to probe invalidate RW lines. Set snoop bit in mmhub for +this to happen. + +v2: Missed a few mmhub_v9_4. Added now. +v3: Calculate hub offset once since it doesn't change inside the loop + Modified function names based on review comments. + +Signed-off-by: Harish Kasiviswanathan +Reviewed-by: Philip Yang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c | 25 ++++++++++ + drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c | 27 +++++++++++ + drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c | 31 ++++++++++++ + .../asic_reg/mmhub/mmhub_9_4_1_offset.h | 32 +++++++++++++ + .../asic_reg/mmhub/mmhub_9_4_1_sh_mask.h | 48 +++++++++++++++++++ + 5 files changed, 163 insertions(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c +index 9689e2b5d4e51..2adee2b94c37d 100644 +--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c ++++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c +@@ -172,6 +172,30 @@ static void mmhub_v1_7_init_tlb_regs(struct amdgpu_device *adev) + WREG32_SOC15(MMHUB, 0, regMC_VM_MX_L1_TLB_CNTL, tmp); + } + ++/* Set snoop bit for SDMA so that SDMA writes probe-invalidates RW lines */ ++static void mmhub_v1_7_init_snoop_override_regs(struct amdgpu_device *adev) ++{ ++ uint32_t tmp; ++ int i; ++ uint32_t distance = regDAGB1_WRCLI_GPU_SNOOP_OVERRIDE - ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE; ++ ++ for (i = 0; i < 5; i++) { /* DAGB instances */ ++ tmp = RREG32_SOC15_OFFSET(MMHUB, 0, ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE, i * distance); ++ tmp |= (1 << 15); /* SDMA client is BIT15 */ ++ WREG32_SOC15_OFFSET(MMHUB, 0, ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE, i * distance, tmp); ++ ++ tmp = RREG32_SOC15_OFFSET(MMHUB, 0, ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE, i * distance); ++ tmp |= (1 << 15); ++ WREG32_SOC15_OFFSET(MMHUB, 0, ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE, i * distance, tmp); ++ } ++ ++} ++ + static void mmhub_v1_7_init_cache_regs(struct amdgpu_device *adev) + { + uint32_t tmp; +@@ -337,6 +361,7 @@ static int mmhub_v1_7_gart_enable(struct amdgpu_device *adev) + mmhub_v1_7_init_system_aperture_regs(adev); + mmhub_v1_7_init_tlb_regs(adev); + mmhub_v1_7_init_cache_regs(adev); ++ mmhub_v1_7_init_snoop_override_regs(adev); + + mmhub_v1_7_enable_system_domain(adev); + mmhub_v1_7_disable_identity_aperture(adev); +diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c +index b01bb759d0f4f..2276c644a6974 100644 +--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c ++++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c +@@ -214,6 +214,32 @@ static void mmhub_v1_8_init_tlb_regs(struct amdgpu_device *adev) + } + } + ++/* Set snoop bit for SDMA so that SDMA writes probe-invalidates RW lines */ ++static void mmhub_v1_8_init_snoop_override_regs(struct amdgpu_device *adev) ++{ ++ uint32_t tmp, inst_mask; ++ int i, j; ++ uint32_t distance = regDAGB1_WRCLI_GPU_SNOOP_OVERRIDE - ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE; ++ ++ inst_mask = adev->aid_mask; ++ for_each_inst(i, inst_mask) { ++ for (j = 0; j < 5; j++) { /* DAGB instances */ ++ tmp = RREG32_SOC15_OFFSET(MMHUB, i, ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE, j * distance); ++ tmp |= (1 << 15); /* SDMA client is BIT15 */ ++ WREG32_SOC15_OFFSET(MMHUB, i, ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE, j * distance, tmp); ++ ++ tmp = RREG32_SOC15_OFFSET(MMHUB, i, ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE, j * distance); ++ tmp |= (1 << 15); ++ WREG32_SOC15_OFFSET(MMHUB, i, ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE, j * distance, tmp); ++ } ++ } ++} ++ + static void mmhub_v1_8_init_cache_regs(struct amdgpu_device *adev) + { + uint32_t tmp, inst_mask; +@@ -419,6 +445,7 @@ static int mmhub_v1_8_gart_enable(struct amdgpu_device *adev) + mmhub_v1_8_init_system_aperture_regs(adev); + mmhub_v1_8_init_tlb_regs(adev); + mmhub_v1_8_init_cache_regs(adev); ++ mmhub_v1_8_init_snoop_override_regs(adev); + + mmhub_v1_8_enable_system_domain(adev); + mmhub_v1_8_disable_identity_aperture(adev); +diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c +index ff1b58e446892..fe0710b55c3ac 100644 +--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c ++++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c +@@ -198,6 +198,36 @@ static void mmhub_v9_4_init_tlb_regs(struct amdgpu_device *adev, int hubid) + hubid * MMHUB_INSTANCE_REGISTER_OFFSET, tmp); + } + ++/* Set snoop bit for SDMA so that SDMA writes probe-invalidates RW lines */ ++static void mmhub_v9_4_init_snoop_override_regs(struct amdgpu_device *adev, int hubid) ++{ ++ uint32_t tmp; ++ int i; ++ uint32_t distance = mmDAGB1_WRCLI_GPU_SNOOP_OVERRIDE - ++ mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE; ++ uint32_t huboffset = hubid * MMHUB_INSTANCE_REGISTER_OFFSET; ++ ++ for (i = 0; i < 5 - (2 * hubid); i++) { ++ /* DAGB instances 0 to 4 are in hub0 and 5 to 7 are in hub1 */ ++ tmp = RREG32_SOC15_OFFSET(MMHUB, 0, ++ mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE, ++ huboffset + i * distance); ++ tmp |= (1 << 15); /* SDMA client is BIT15 */ ++ WREG32_SOC15_OFFSET(MMHUB, 0, ++ mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE, ++ huboffset + i * distance, tmp); ++ ++ tmp = RREG32_SOC15_OFFSET(MMHUB, 0, ++ mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE, ++ huboffset + i * distance); ++ tmp |= (1 << 15); ++ WREG32_SOC15_OFFSET(MMHUB, 0, ++ mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE, ++ huboffset + i * distance, tmp); ++ } ++ ++} ++ + static void mmhub_v9_4_init_cache_regs(struct amdgpu_device *adev, int hubid) + { + uint32_t tmp; +@@ -392,6 +422,7 @@ static int mmhub_v9_4_gart_enable(struct amdgpu_device *adev) + if (!amdgpu_sriov_vf(adev)) + mmhub_v9_4_init_cache_regs(adev, i); + ++ mmhub_v9_4_init_snoop_override_regs(adev, i); + mmhub_v9_4_enable_system_domain(adev, i); + if (!amdgpu_sriov_vf(adev)) + mmhub_v9_4_disable_identity_aperture(adev, i); +diff --git a/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_offset.h b/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_offset.h +index c488d4a50cf46..b2252deabc17a 100644 +--- a/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_offset.h ++++ b/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_offset.h +@@ -203,6 +203,10 @@ + #define mmDAGB0_WR_DATA_CREDIT_BASE_IDX 1 + #define mmDAGB0_WR_MISC_CREDIT 0x0058 + #define mmDAGB0_WR_MISC_CREDIT_BASE_IDX 1 ++#define mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE 0x005b ++#define mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1 ++#define mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x005c ++#define mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1 + #define mmDAGB0_WRCLI_ASK_PENDING 0x005d + #define mmDAGB0_WRCLI_ASK_PENDING_BASE_IDX 1 + #define mmDAGB0_WRCLI_GO_PENDING 0x005e +@@ -455,6 +459,10 @@ + #define mmDAGB1_WR_DATA_CREDIT_BASE_IDX 1 + #define mmDAGB1_WR_MISC_CREDIT 0x00d8 + #define mmDAGB1_WR_MISC_CREDIT_BASE_IDX 1 ++#define mmDAGB1_WRCLI_GPU_SNOOP_OVERRIDE 0x00db ++#define mmDAGB1_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1 ++#define mmDAGB1_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x00dc ++#define mmDAGB1_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1 + #define mmDAGB1_WRCLI_ASK_PENDING 0x00dd + #define mmDAGB1_WRCLI_ASK_PENDING_BASE_IDX 1 + #define mmDAGB1_WRCLI_GO_PENDING 0x00de +@@ -707,6 +715,10 @@ + #define mmDAGB2_WR_DATA_CREDIT_BASE_IDX 1 + #define mmDAGB2_WR_MISC_CREDIT 0x0158 + #define mmDAGB2_WR_MISC_CREDIT_BASE_IDX 1 ++#define mmDAGB2_WRCLI_GPU_SNOOP_OVERRIDE 0x015b ++#define mmDAGB2_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1 ++#define mmDAGB2_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x015c ++#define mmDAGB2_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1 + #define mmDAGB2_WRCLI_ASK_PENDING 0x015d + #define mmDAGB2_WRCLI_ASK_PENDING_BASE_IDX 1 + #define mmDAGB2_WRCLI_GO_PENDING 0x015e +@@ -959,6 +971,10 @@ + #define mmDAGB3_WR_DATA_CREDIT_BASE_IDX 1 + #define mmDAGB3_WR_MISC_CREDIT 0x01d8 + #define mmDAGB3_WR_MISC_CREDIT_BASE_IDX 1 ++#define mmDAGB3_WRCLI_GPU_SNOOP_OVERRIDE 0x01db ++#define mmDAGB3_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1 ++#define mmDAGB3_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x01dc ++#define mmDAGB3_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1 + #define mmDAGB3_WRCLI_ASK_PENDING 0x01dd + #define mmDAGB3_WRCLI_ASK_PENDING_BASE_IDX 1 + #define mmDAGB3_WRCLI_GO_PENDING 0x01de +@@ -1211,6 +1227,10 @@ + #define mmDAGB4_WR_DATA_CREDIT_BASE_IDX 1 + #define mmDAGB4_WR_MISC_CREDIT 0x0258 + #define mmDAGB4_WR_MISC_CREDIT_BASE_IDX 1 ++#define mmDAGB4_WRCLI_GPU_SNOOP_OVERRIDE 0x025b ++#define mmDAGB4_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1 ++#define mmDAGB4_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x025c ++#define mmDAGB4_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1 + #define mmDAGB4_WRCLI_ASK_PENDING 0x025d + #define mmDAGB4_WRCLI_ASK_PENDING_BASE_IDX 1 + #define mmDAGB4_WRCLI_GO_PENDING 0x025e +@@ -4793,6 +4813,10 @@ + #define mmDAGB5_WR_DATA_CREDIT_BASE_IDX 1 + #define mmDAGB5_WR_MISC_CREDIT 0x3058 + #define mmDAGB5_WR_MISC_CREDIT_BASE_IDX 1 ++#define mmDAGB5_WRCLI_GPU_SNOOP_OVERRIDE 0x305b ++#define mmDAGB5_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1 ++#define mmDAGB5_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x305c ++#define mmDAGB5_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1 + #define mmDAGB5_WRCLI_ASK_PENDING 0x305d + #define mmDAGB5_WRCLI_ASK_PENDING_BASE_IDX 1 + #define mmDAGB5_WRCLI_GO_PENDING 0x305e +@@ -5045,6 +5069,10 @@ + #define mmDAGB6_WR_DATA_CREDIT_BASE_IDX 1 + #define mmDAGB6_WR_MISC_CREDIT 0x30d8 + #define mmDAGB6_WR_MISC_CREDIT_BASE_IDX 1 ++#define mmDAGB6_WRCLI_GPU_SNOOP_OVERRIDE 0x30db ++#define mmDAGB6_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1 ++#define mmDAGB6_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x30dc ++#define mmDAGB6_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1 + #define mmDAGB6_WRCLI_ASK_PENDING 0x30dd + #define mmDAGB6_WRCLI_ASK_PENDING_BASE_IDX 1 + #define mmDAGB6_WRCLI_GO_PENDING 0x30de +@@ -5297,6 +5325,10 @@ + #define mmDAGB7_WR_DATA_CREDIT_BASE_IDX 1 + #define mmDAGB7_WR_MISC_CREDIT 0x3158 + #define mmDAGB7_WR_MISC_CREDIT_BASE_IDX 1 ++#define mmDAGB7_WRCLI_GPU_SNOOP_OVERRIDE 0x315b ++#define mmDAGB7_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1 ++#define mmDAGB7_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x315c ++#define mmDAGB7_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1 + #define mmDAGB7_WRCLI_ASK_PENDING 0x315d + #define mmDAGB7_WRCLI_ASK_PENDING_BASE_IDX 1 + #define mmDAGB7_WRCLI_GO_PENDING 0x315e +diff --git a/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_sh_mask.h +index 2969fbf282b7d..5069d2fd467f2 100644 +--- a/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_sh_mask.h ++++ b/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_sh_mask.h +@@ -1532,6 +1532,12 @@ + //DAGB0_WRCLI_DBUS_GO_PENDING + #define DAGB0_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0 + #define DAGB0_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL ++//DAGB0_WRCLI_GPU_SNOOP_OVERRIDE ++#define DAGB0_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0 ++#define DAGB0_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL ++//DAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE ++#define DAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0 ++#define DAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL + //DAGB0_DAGB_DLY + #define DAGB0_DAGB_DLY__DLY__SHIFT 0x0 + #define DAGB0_DAGB_DLY__CLI__SHIFT 0x8 +@@ -3207,6 +3213,12 @@ + //DAGB1_WRCLI_DBUS_GO_PENDING + #define DAGB1_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0 + #define DAGB1_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL ++//DAGB1_WRCLI_GPU_SNOOP_OVERRIDE ++#define DAGB1_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0 ++#define DAGB1_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL ++//DAGB1_WRCLI_GPU_SNOOP_OVERRIDE_VALUE ++#define DAGB1_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0 ++#define DAGB1_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL + //DAGB1_DAGB_DLY + #define DAGB1_DAGB_DLY__DLY__SHIFT 0x0 + #define DAGB1_DAGB_DLY__CLI__SHIFT 0x8 +@@ -4882,6 +4894,12 @@ + //DAGB2_WRCLI_DBUS_GO_PENDING + #define DAGB2_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0 + #define DAGB2_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL ++//DAGB2_WRCLI_GPU_SNOOP_OVERRIDE ++#define DAGB2_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0 ++#define DAGB2_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL ++//DAGB2_WRCLI_GPU_SNOOP_OVERRIDE_VALUE ++#define DAGB2_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0 ++#define DAGB2_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL + //DAGB2_DAGB_DLY + #define DAGB2_DAGB_DLY__DLY__SHIFT 0x0 + #define DAGB2_DAGB_DLY__CLI__SHIFT 0x8 +@@ -6557,6 +6575,12 @@ + //DAGB3_WRCLI_DBUS_GO_PENDING + #define DAGB3_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0 + #define DAGB3_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL ++//DAGB3_WRCLI_GPU_SNOOP_OVERRIDE ++#define DAGB3_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0 ++#define DAGB3_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL ++//DAGB3_WRCLI_GPU_SNOOP_OVERRIDE_VALUE ++#define DAGB3_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0 ++#define DAGB3_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL + //DAGB3_DAGB_DLY + #define DAGB3_DAGB_DLY__DLY__SHIFT 0x0 + #define DAGB3_DAGB_DLY__CLI__SHIFT 0x8 +@@ -8232,6 +8256,12 @@ + //DAGB4_WRCLI_DBUS_GO_PENDING + #define DAGB4_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0 + #define DAGB4_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL ++//DAGB4_WRCLI_GPU_SNOOP_OVERRIDE ++#define DAGB4_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0 ++#define DAGB4_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL ++//DAGB4_WRCLI_GPU_SNOOP_OVERRIDE_VALUE ++#define DAGB4_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0 ++#define DAGB4_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL + //DAGB4_DAGB_DLY + #define DAGB4_DAGB_DLY__DLY__SHIFT 0x0 + #define DAGB4_DAGB_DLY__CLI__SHIFT 0x8 +@@ -28737,6 +28767,12 @@ + //DAGB5_WRCLI_DBUS_GO_PENDING + #define DAGB5_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0 + #define DAGB5_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL ++//DAGB5_WRCLI_GPU_SNOOP_OVERRIDE ++#define DAGB5_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0 ++#define DAGB5_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL ++//DAGB5_WRCLI_GPU_SNOOP_OVERRIDE_VALUE ++#define DAGB5_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0 ++#define DAGB5_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL + //DAGB5_DAGB_DLY + #define DAGB5_DAGB_DLY__DLY__SHIFT 0x0 + #define DAGB5_DAGB_DLY__CLI__SHIFT 0x8 +@@ -30412,6 +30448,12 @@ + //DAGB6_WRCLI_DBUS_GO_PENDING + #define DAGB6_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0 + #define DAGB6_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL ++//DAGB6_WRCLI_GPU_SNOOP_OVERRIDE ++#define DAGB6_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0 ++#define DAGB6_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL ++//DAGB6_WRCLI_GPU_SNOOP_OVERRIDE_VALUE ++#define DAGB6_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0 ++#define DAGB6_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL + //DAGB6_DAGB_DLY + #define DAGB6_DAGB_DLY__DLY__SHIFT 0x0 + #define DAGB6_DAGB_DLY__CLI__SHIFT 0x8 +@@ -32087,6 +32129,12 @@ + //DAGB7_WRCLI_DBUS_GO_PENDING + #define DAGB7_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0 + #define DAGB7_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL ++//DAGB7_WRCLI_GPU_SNOOP_OVERRIDE ++#define DAGB7_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0 ++#define DAGB7_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL ++//DAGB7_WRCLI_GPU_SNOOP_OVERRIDE_VALUE ++#define DAGB7_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0 ++#define DAGB7_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL + //DAGB7_DAGB_DLY + #define DAGB7_DAGB_DLY__DLY__SHIFT 0x0 + #define DAGB7_DAGB_DLY__CLI__SHIFT 0x8 +-- +2.39.5 + diff --git a/queue-6.12/drm-amdgpu-skip-pcie_replay_count-sysfs-creation-for.patch b/queue-6.12/drm-amdgpu-skip-pcie_replay_count-sysfs-creation-for.patch new file mode 100644 index 0000000000..7c04b0c855 --- /dev/null +++ b/queue-6.12/drm-amdgpu-skip-pcie_replay_count-sysfs-creation-for.patch @@ -0,0 +1,82 @@ +From d40d4dbac2a94d07a1b9d91f2b810f36428b8bab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 09:32:13 -0400 +Subject: drm/amdgpu: Skip pcie_replay_count sysfs creation for VF + +From: Victor Skvortsov + +[ Upstream commit 9c05636ca72a2dbf41bf0900380f438a0de47319 ] + +VFs cannot read the NAK_COUNTER register. This information is only +available through PMFW metrics. + +Signed-off-by: Victor Skvortsov +Reviewed-by: Lijo Lazar +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 27 ++++++++++++++++------ + 1 file changed, 20 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index cb102ee71d04c..081c0e45779fc 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -170,6 +170,24 @@ static ssize_t amdgpu_device_get_pcie_replay_count(struct device *dev, + static DEVICE_ATTR(pcie_replay_count, 0444, + amdgpu_device_get_pcie_replay_count, NULL); + ++static int amdgpu_device_attr_sysfs_init(struct amdgpu_device *adev) ++{ ++ int ret = 0; ++ ++ if (!amdgpu_sriov_vf(adev)) ++ ret = sysfs_create_file(&adev->dev->kobj, ++ &dev_attr_pcie_replay_count.attr); ++ ++ return ret; ++} ++ ++static void amdgpu_device_attr_sysfs_fini(struct amdgpu_device *adev) ++{ ++ if (!amdgpu_sriov_vf(adev)) ++ sysfs_remove_file(&adev->dev->kobj, ++ &dev_attr_pcie_replay_count.attr); ++} ++ + static ssize_t amdgpu_sysfs_reg_state_get(struct file *f, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t ppos, size_t count) +@@ -4030,11 +4048,6 @@ static bool amdgpu_device_check_iommu_remap(struct amdgpu_device *adev) + } + #endif + +-static const struct attribute *amdgpu_dev_attributes[] = { +- &dev_attr_pcie_replay_count.attr, +- NULL +-}; +- + static void amdgpu_device_set_mcbp(struct amdgpu_device *adev) + { + if (amdgpu_mcbp == 1) +@@ -4477,7 +4490,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, + } else + adev->ucode_sysfs_en = true; + +- r = sysfs_create_files(&adev->dev->kobj, amdgpu_dev_attributes); ++ r = amdgpu_device_attr_sysfs_init(adev); + if (r) + dev_err(adev->dev, "Could not create amdgpu device attr\n"); + +@@ -4614,7 +4627,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev) + amdgpu_pm_sysfs_fini(adev); + if (adev->ucode_sysfs_en) + amdgpu_ucode_sysfs_fini(adev); +- sysfs_remove_files(&adev->dev->kobj, amdgpu_dev_attributes); ++ amdgpu_device_attr_sysfs_fini(adev); + amdgpu_fru_sysfs_fini(adev); + + amdgpu_reg_state_sysfs_fini(adev); +-- +2.39.5 + diff --git a/queue-6.12/drm-amdgpu-update-sriov-video-codec-caps.patch b/queue-6.12/drm-amdgpu-update-sriov-video-codec-caps.patch new file mode 100644 index 0000000000..445d178727 --- /dev/null +++ b/queue-6.12/drm-amdgpu-update-sriov-video-codec-caps.patch @@ -0,0 +1,91 @@ +From 01275c0742f97bff40fdb4fb6a2baf48ad2c9c42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 13:44:32 +0100 +Subject: drm/amdgpu: Update SRIOV video codec caps + +From: David Rosca + +[ Upstream commit 19478f2011f8b53dee401c91423c4e0b73753e4f ] + +There have been multiple fixes to the video caps that are missing for +SRIOV. Update the SRIOV caps with correct values. + +Signed-off-by: David Rosca +Acked-by: Alex Deucher +Reviewed-by: Ruijing Dong +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/nv.c | 16 ++++++++-------- + drivers/gpu/drm/amd/amdgpu/soc21.c | 10 ++-------- + 2 files changed, 10 insertions(+), 16 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c +index 4f94a119d6275..ab0eecbab4125 100644 +--- a/drivers/gpu/drm/amd/amdgpu/nv.c ++++ b/drivers/gpu/drm/amd/amdgpu/nv.c +@@ -141,23 +141,23 @@ static struct amdgpu_video_codec_info sriov_sc_video_codecs_encode_array[] = { + }; + + static struct amdgpu_video_codec_info sriov_sc_video_codecs_decode_array_vcn0[] = { +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 1920, 1088, 3)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 1920, 1088, 5)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 1920, 1088, 4)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)}, + }; + + static struct amdgpu_video_codec_info sriov_sc_video_codecs_decode_array_vcn1[] = { +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 1920, 1088, 3)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 1920, 1088, 5)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 1920, 1088, 4)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, + }; + +diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c +index bba35880badb9..04a1b2a46368f 100644 +--- a/drivers/gpu/drm/amd/amdgpu/soc21.c ++++ b/drivers/gpu/drm/amd/amdgpu/soc21.c +@@ -117,23 +117,17 @@ static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_encode_vcn1 = { + }; + + static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_decode_array_vcn0[] = { +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)}, + }; + + static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_decode_array_vcn1[] = { +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, + }; + +-- +2.39.5 + diff --git a/queue-6.12/drm-amdgpu-use-active-umc-info-from-discovery.patch b/queue-6.12/drm-amdgpu-use-active-umc-info-from-discovery.patch new file mode 100644 index 0000000000..10ac03e922 --- /dev/null +++ b/queue-6.12/drm-amdgpu-use-active-umc-info-from-discovery.patch @@ -0,0 +1,101 @@ +From 92ed2eb8a872c0269c393352f229c13cd1d9223a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 1 Jan 2025 14:23:31 +0530 +Subject: drm/amdgpu: Use active umc info from discovery + +From: Lijo Lazar + +[ Upstream commit f7a594e40517fa2ab25d5ca10e7b6a158f529fb5 ] + +There could be configs where some UMC instances are harvested. This +information is obtained through discovery data and populated in +umc.active_mask. Avoid reassigning this as AID mask, instead use the +mask directly while iterating through umc instances. This is to avoid +accesses to harvested UMC instances. + +v2: fix warning (Alex) + +Signed-off-by: Lijo Lazar +Reviewed-by: Hawking Zhang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c | 42 +++++++++++++++++++++++++ + drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 1 - + 2 files changed, 42 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +index bb7b9b2eaac1a..8da0bddab3d23 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +@@ -383,6 +383,45 @@ int amdgpu_umc_fill_error_record(struct ras_err_data *err_data, + return 0; + } + ++static int amdgpu_umc_loop_all_aid(struct amdgpu_device *adev, umc_func func, ++ void *data) ++{ ++ uint32_t umc_node_inst; ++ uint32_t node_inst; ++ uint32_t umc_inst; ++ uint32_t ch_inst; ++ int ret; ++ ++ /* ++ * This loop is done based on the following - ++ * umc.active mask = mask of active umc instances across all nodes ++ * umc.umc_inst_num = maximum number of umc instancess per node ++ * umc.node_inst_num = maximum number of node instances ++ * Channel instances are not assumed to be harvested. ++ */ ++ dev_dbg(adev->dev, "active umcs :%lx umc_inst per node: %d", ++ adev->umc.active_mask, adev->umc.umc_inst_num); ++ for_each_set_bit(umc_node_inst, &(adev->umc.active_mask), ++ adev->umc.node_inst_num * adev->umc.umc_inst_num) { ++ node_inst = umc_node_inst / adev->umc.umc_inst_num; ++ umc_inst = umc_node_inst % adev->umc.umc_inst_num; ++ LOOP_UMC_CH_INST(ch_inst) { ++ dev_dbg(adev->dev, ++ "node_inst :%d umc_inst: %d ch_inst: %d", ++ node_inst, umc_inst, ch_inst); ++ ret = func(adev, node_inst, umc_inst, ch_inst, data); ++ if (ret) { ++ dev_err(adev->dev, ++ "Node %d umc %d ch %d func returns %d\n", ++ node_inst, umc_inst, ch_inst, ret); ++ return ret; ++ } ++ } ++ } ++ ++ return 0; ++} ++ + int amdgpu_umc_loop_channels(struct amdgpu_device *adev, + umc_func func, void *data) + { +@@ -391,6 +430,9 @@ int amdgpu_umc_loop_channels(struct amdgpu_device *adev, + uint32_t ch_inst = 0; + int ret = 0; + ++ if (adev->aid_mask) ++ return amdgpu_umc_loop_all_aid(adev, func, data); ++ + if (adev->umc.node_inst_num) { + LOOP_UMC_EACH_NODE_INST_AND_CH(node_inst, umc_inst, ch_inst) { + ret = func(adev, node_inst, umc_inst, ch_inst, data); +diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +index 9a212413c6d3a..78c527b56f7c5 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +@@ -1461,7 +1461,6 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev) + adev->umc.umc_inst_num = UMC_V12_0_UMC_INSTANCE_NUM; + adev->umc.node_inst_num /= UMC_V12_0_UMC_INSTANCE_NUM; + adev->umc.channel_offs = UMC_V12_0_PER_CHANNEL_OFFSET; +- adev->umc.active_mask = adev->aid_mask; + adev->umc.retire_unit = UMC_V12_0_BAD_PAGE_NUM_PER_CHANNEL; + if (!adev->gmc.xgmi.connected_to_cpu && !adev->gmc.is_app_apu) + adev->umc.ras = &umc_v12_0_ras; +-- +2.39.5 + diff --git a/queue-6.12/drm-amdkfd-fix-missing-l2-cache-info-in-topology.patch b/queue-6.12/drm-amdkfd-fix-missing-l2-cache-info-in-topology.patch new file mode 100644 index 0000000000..13ca639b2a --- /dev/null +++ b/queue-6.12/drm-amdkfd-fix-missing-l2-cache-info-in-topology.patch @@ -0,0 +1,67 @@ +From 613f39e5acbe96ac1b1061d81df5aeac9f88efa8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jan 2025 15:48:26 -0500 +Subject: drm/amdkfd: fix missing L2 cache info in topology + +From: Eric Huang + +[ Upstream commit 5ffd56822a7159917306d99f18fd15dfd7288f20 ] + +In some ASICs L2 cache info may miss in kfd topology, +because the first bitmap may be empty, that means +the first cu may be inactive, so to find the first +active cu will solve the issue. + +v2: Only find the first active cu in the first xcc + +Signed-off-by: Eric Huang +Acked-by: Alex Deucher +Acked-by: Lijo Lazar +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +index bcb5cdc4a9d81..82da568604b6e 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +@@ -1683,17 +1683,32 @@ static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext, + int cache_type, unsigned int cu_processor_id, + struct kfd_node *knode) + { +- unsigned int cu_sibling_map_mask; ++ unsigned int cu_sibling_map_mask = 0; + int first_active_cu; + int i, j, k, xcc, start, end; + int num_xcc = NUM_XCC(knode->xcc_mask); + struct kfd_cache_properties *pcache = NULL; + enum amdgpu_memory_partition mode; + struct amdgpu_device *adev = knode->adev; ++ bool found = false; + + start = ffs(knode->xcc_mask) - 1; + end = start + num_xcc; +- cu_sibling_map_mask = cu_info->bitmap[start][0][0]; ++ ++ /* To find the bitmap in the first active cu in the first ++ * xcc, it is based on the assumption that evrey xcc must ++ * have at least one active cu. ++ */ ++ for (i = 0; i < gfx_info->max_shader_engines && !found; i++) { ++ for (j = 0; j < gfx_info->max_sh_per_se && !found; j++) { ++ if (cu_info->bitmap[start][i % 4][j % 4]) { ++ cu_sibling_map_mask = ++ cu_info->bitmap[start][i % 4][j % 4]; ++ found = true; ++ } ++ } ++ } ++ + cu_sibling_map_mask &= + ((1 << pcache_info[cache_type].num_cu_shared) - 1); + first_active_cu = ffs(cu_sibling_map_mask); +-- +2.39.5 + diff --git a/queue-6.12/drm-amdkfd-kfd-release_work-possible-circular-lockin.patch b/queue-6.12/drm-amdkfd-kfd-release_work-possible-circular-lockin.patch new file mode 100644 index 0000000000..2d6d04143e --- /dev/null +++ b/queue-6.12/drm-amdkfd-kfd-release_work-possible-circular-lockin.patch @@ -0,0 +1,80 @@ +From 7baa1cf47da76cbe2e06daf65d172356bb0d05b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 20:08:29 -0500 +Subject: drm/amdkfd: KFD release_work possible circular locking + +From: Philip Yang + +[ Upstream commit 1b9366c601039d60546794c63fbb83ce8e53b978 ] + +If waiting for gpu reset done in KFD release_work, thers is WARNING: +possible circular locking dependency detected + + #2 kfd_create_process + kfd_process_mutex + flush kfd release work + + #1 kfd release work + wait for amdgpu reset work + + #0 amdgpu_device_gpu_reset + kgd2kfd_pre_reset + kfd_process_mutex + + Possible unsafe locking scenario: + + CPU0 CPU1 + ---- ---- + lock((work_completion)(&p->release_work)); + lock((wq_completion)kfd_process_wq); + lock((work_completion)(&p->release_work)); + lock((wq_completion)amdgpu-reset-dev); + +To fix this, KFD create process move flush release work outside +kfd_process_mutex. + +Signed-off-by: Philip Yang +Reviewed-by: Felix Kuehling +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdkfd/kfd_process.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +index 0ec8b457494bd..45923da7709fd 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +@@ -842,6 +842,14 @@ struct kfd_process *kfd_create_process(struct task_struct *thread) + return ERR_PTR(-EINVAL); + } + ++ /* If the process just called exec(3), it is possible that the ++ * cleanup of the kfd_process (following the release of the mm ++ * of the old process image) is still in the cleanup work queue. ++ * Make sure to drain any job before trying to recreate any ++ * resource for this process. ++ */ ++ flush_workqueue(kfd_process_wq); ++ + /* + * take kfd processes mutex before starting of process creation + * so there won't be a case where two threads of the same process +@@ -860,14 +868,6 @@ struct kfd_process *kfd_create_process(struct task_struct *thread) + if (process) { + pr_debug("Process already found\n"); + } else { +- /* If the process just called exec(3), it is possible that the +- * cleanup of the kfd_process (following the release of the mm +- * of the old process image) is still in the cleanup work queue. +- * Make sure to drain any job before trying to recreate any +- * resource for this process. +- */ +- flush_workqueue(kfd_process_wq); +- + process = create_process(thread); + if (IS_ERR(process)) + goto out; +-- +2.39.5 + diff --git a/queue-6.12/drm-amdkfd-set-per-process-flags-only-once-cik-vi.patch b/queue-6.12/drm-amdkfd-set-per-process-flags-only-once-cik-vi.patch new file mode 100644 index 0000000000..30d5dcb0e6 --- /dev/null +++ b/queue-6.12/drm-amdkfd-set-per-process-flags-only-once-cik-vi.patch @@ -0,0 +1,301 @@ +From aa8caf2889b62a645fc3e0a9673496de184aa337 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jan 2025 14:07:24 -0500 +Subject: drm/amdkfd: Set per-process flags only once cik/vi + +From: Harish Kasiviswanathan + +[ Upstream commit 289e68503a4533b014f8447e2af28ad44c92c221 ] + +Set per-process static sh_mem config only once during process +initialization. Move all static changes from update_qpd() which is +called each time a queue is created to set_cache_memory_policy() which +is called once during process initialization. + +set_cache_memory_policy() is currently defined only for cik and vi +family. So this commit only focuses on these two. A separate commit will +address other asics. + +Signed-off-by: Harish Kasiviswanathan +Reviewed-by: Amber Lin +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../drm/amd/amdkfd/kfd_device_queue_manager.c | 39 +--------- + .../amd/amdkfd/kfd_device_queue_manager_cik.c | 69 ++++++++++++------ + .../amd/amdkfd/kfd_device_queue_manager_vi.c | 71 ++++++++++++------- + 3 files changed, 94 insertions(+), 85 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +index 951b87e7e3f68..6a58dd8d2130c 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +@@ -2453,14 +2453,6 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm, + return retval; + } + +-/* +- * Low bits must be 0000/FFFF as required by HW, high bits must be 0 to +- * stay in user mode. +- */ +-#define APE1_FIXED_BITS_MASK 0xFFFF80000000FFFFULL +-/* APE1 limit is inclusive and 64K aligned. */ +-#define APE1_LIMIT_ALIGNMENT 0xFFFF +- + static bool set_cache_memory_policy(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + enum cache_policy default_policy, +@@ -2475,34 +2467,6 @@ static bool set_cache_memory_policy(struct device_queue_manager *dqm, + + dqm_lock(dqm); + +- if (alternate_aperture_size == 0) { +- /* base > limit disables APE1 */ +- qpd->sh_mem_ape1_base = 1; +- qpd->sh_mem_ape1_limit = 0; +- } else { +- /* +- * In FSA64, APE1_Base[63:0] = { 16{SH_MEM_APE1_BASE[31]}, +- * SH_MEM_APE1_BASE[31:0], 0x0000 } +- * APE1_Limit[63:0] = { 16{SH_MEM_APE1_LIMIT[31]}, +- * SH_MEM_APE1_LIMIT[31:0], 0xFFFF } +- * Verify that the base and size parameters can be +- * represented in this format and convert them. +- * Additionally restrict APE1 to user-mode addresses. +- */ +- +- uint64_t base = (uintptr_t)alternate_aperture_base; +- uint64_t limit = base + alternate_aperture_size - 1; +- +- if (limit <= base || (base & APE1_FIXED_BITS_MASK) != 0 || +- (limit & APE1_FIXED_BITS_MASK) != APE1_LIMIT_ALIGNMENT) { +- retval = false; +- goto out; +- } +- +- qpd->sh_mem_ape1_base = base >> 16; +- qpd->sh_mem_ape1_limit = limit >> 16; +- } +- + retval = dqm->asic_ops.set_cache_memory_policy( + dqm, + qpd, +@@ -2511,6 +2475,9 @@ static bool set_cache_memory_policy(struct device_queue_manager *dqm, + alternate_aperture_base, + alternate_aperture_size); + ++ if (retval) ++ goto out; ++ + if ((dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) && (qpd->vmid != 0)) + program_sh_mem_settings(dqm, qpd); + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c +index d4d95c7f2e5d4..32bedef912b3b 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c +@@ -27,6 +27,14 @@ + #include "oss/oss_2_4_sh_mask.h" + #include "gca/gfx_7_2_sh_mask.h" + ++/* ++ * Low bits must be 0000/FFFF as required by HW, high bits must be 0 to ++ * stay in user mode. ++ */ ++#define APE1_FIXED_BITS_MASK 0xFFFF80000000FFFFULL ++/* APE1 limit is inclusive and 64K aligned. */ ++#define APE1_LIMIT_ALIGNMENT 0xFFFF ++ + static bool set_cache_memory_policy_cik(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + enum cache_policy default_policy, +@@ -84,6 +92,36 @@ static bool set_cache_memory_policy_cik(struct device_queue_manager *dqm, + { + uint32_t default_mtype; + uint32_t ape1_mtype; ++ unsigned int temp; ++ bool retval = true; ++ ++ if (alternate_aperture_size == 0) { ++ /* base > limit disables APE1 */ ++ qpd->sh_mem_ape1_base = 1; ++ qpd->sh_mem_ape1_limit = 0; ++ } else { ++ /* ++ * In FSA64, APE1_Base[63:0] = { 16{SH_MEM_APE1_BASE[31]}, ++ * SH_MEM_APE1_BASE[31:0], 0x0000 } ++ * APE1_Limit[63:0] = { 16{SH_MEM_APE1_LIMIT[31]}, ++ * SH_MEM_APE1_LIMIT[31:0], 0xFFFF } ++ * Verify that the base and size parameters can be ++ * represented in this format and convert them. ++ * Additionally restrict APE1 to user-mode addresses. ++ */ ++ ++ uint64_t base = (uintptr_t)alternate_aperture_base; ++ uint64_t limit = base + alternate_aperture_size - 1; ++ ++ if (limit <= base || (base & APE1_FIXED_BITS_MASK) != 0 || ++ (limit & APE1_FIXED_BITS_MASK) != APE1_LIMIT_ALIGNMENT) { ++ retval = false; ++ goto out; ++ } ++ ++ qpd->sh_mem_ape1_base = base >> 16; ++ qpd->sh_mem_ape1_limit = limit >> 16; ++ } + + default_mtype = (default_policy == cache_policy_coherent) ? + MTYPE_NONCACHED : +@@ -97,37 +135,22 @@ static bool set_cache_memory_policy_cik(struct device_queue_manager *dqm, + | ALIGNMENT_MODE(SH_MEM_ALIGNMENT_MODE_UNALIGNED) + | DEFAULT_MTYPE(default_mtype) + | APE1_MTYPE(ape1_mtype); +- +- return true; +-} +- +-static int update_qpd_cik(struct device_queue_manager *dqm, +- struct qcm_process_device *qpd) +-{ +- struct kfd_process_device *pdd; +- unsigned int temp; +- +- pdd = qpd_to_pdd(qpd); +- +- /* check if sh_mem_config register already configured */ +- if (qpd->sh_mem_config == 0) { +- qpd->sh_mem_config = +- ALIGNMENT_MODE(SH_MEM_ALIGNMENT_MODE_UNALIGNED) | +- DEFAULT_MTYPE(MTYPE_NONCACHED) | +- APE1_MTYPE(MTYPE_NONCACHED); +- qpd->sh_mem_ape1_limit = 0; +- qpd->sh_mem_ape1_base = 0; +- } +- + /* On dGPU we're always in GPUVM64 addressing mode with 64-bit + * aperture addresses. + */ +- temp = get_sh_mem_bases_nybble_64(pdd); ++ temp = get_sh_mem_bases_nybble_64(qpd_to_pdd(qpd)); + qpd->sh_mem_bases = compute_sh_mem_bases_64bit(temp); + + pr_debug("is32bit process: %d sh_mem_bases nybble: 0x%X and register 0x%X\n", + qpd->pqm->process->is_32bit_user_mode, temp, qpd->sh_mem_bases); + ++out: ++ return retval; ++} ++ ++static int update_qpd_cik(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd) ++{ + return 0; + } + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c +index b291ee0fab943..320518f418903 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c +@@ -27,6 +27,14 @@ + #include "gca/gfx_8_0_sh_mask.h" + #include "oss/oss_3_0_sh_mask.h" + ++/* ++ * Low bits must be 0000/FFFF as required by HW, high bits must be 0 to ++ * stay in user mode. ++ */ ++#define APE1_FIXED_BITS_MASK 0xFFFF80000000FFFFULL ++/* APE1 limit is inclusive and 64K aligned. */ ++#define APE1_LIMIT_ALIGNMENT 0xFFFF ++ + static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + enum cache_policy default_policy, +@@ -85,6 +93,36 @@ static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm, + { + uint32_t default_mtype; + uint32_t ape1_mtype; ++ unsigned int temp; ++ bool retval = true; ++ ++ if (alternate_aperture_size == 0) { ++ /* base > limit disables APE1 */ ++ qpd->sh_mem_ape1_base = 1; ++ qpd->sh_mem_ape1_limit = 0; ++ } else { ++ /* ++ * In FSA64, APE1_Base[63:0] = { 16{SH_MEM_APE1_BASE[31]}, ++ * SH_MEM_APE1_BASE[31:0], 0x0000 } ++ * APE1_Limit[63:0] = { 16{SH_MEM_APE1_LIMIT[31]}, ++ * SH_MEM_APE1_LIMIT[31:0], 0xFFFF } ++ * Verify that the base and size parameters can be ++ * represented in this format and convert them. ++ * Additionally restrict APE1 to user-mode addresses. ++ */ ++ ++ uint64_t base = (uintptr_t)alternate_aperture_base; ++ uint64_t limit = base + alternate_aperture_size - 1; ++ ++ if (limit <= base || (base & APE1_FIXED_BITS_MASK) != 0 || ++ (limit & APE1_FIXED_BITS_MASK) != APE1_LIMIT_ALIGNMENT) { ++ retval = false; ++ goto out; ++ } ++ ++ qpd->sh_mem_ape1_base = base >> 16; ++ qpd->sh_mem_ape1_limit = limit >> 16; ++ } + + default_mtype = (default_policy == cache_policy_coherent) ? + MTYPE_UC : +@@ -100,40 +138,21 @@ static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm, + default_mtype << SH_MEM_CONFIG__DEFAULT_MTYPE__SHIFT | + ape1_mtype << SH_MEM_CONFIG__APE1_MTYPE__SHIFT; + +- return true; +-} +- +-static int update_qpd_vi(struct device_queue_manager *dqm, +- struct qcm_process_device *qpd) +-{ +- struct kfd_process_device *pdd; +- unsigned int temp; +- +- pdd = qpd_to_pdd(qpd); +- +- /* check if sh_mem_config register already configured */ +- if (qpd->sh_mem_config == 0) { +- qpd->sh_mem_config = +- SH_MEM_ALIGNMENT_MODE_UNALIGNED << +- SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT | +- MTYPE_UC << +- SH_MEM_CONFIG__DEFAULT_MTYPE__SHIFT | +- MTYPE_UC << +- SH_MEM_CONFIG__APE1_MTYPE__SHIFT; +- +- qpd->sh_mem_ape1_limit = 0; +- qpd->sh_mem_ape1_base = 0; +- } +- + /* On dGPU we're always in GPUVM64 addressing mode with 64-bit + * aperture addresses. + */ +- temp = get_sh_mem_bases_nybble_64(pdd); ++ temp = get_sh_mem_bases_nybble_64(qpd_to_pdd(qpd)); + qpd->sh_mem_bases = compute_sh_mem_bases_64bit(temp); + + pr_debug("sh_mem_bases nybble: 0x%X and register 0x%X\n", + temp, qpd->sh_mem_bases); ++out: ++ return retval; ++} + ++static int update_qpd_vi(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd) ++{ + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.12/drm-amdkfd-set-per-process-flags-only-once-for-gfx9-.patch b/queue-6.12/drm-amdkfd-set-per-process-flags-only-once-for-gfx9-.patch new file mode 100644 index 0000000000..f0f0264a5c --- /dev/null +++ b/queue-6.12/drm-amdkfd-set-per-process-flags-only-once-for-gfx9-.patch @@ -0,0 +1,292 @@ +From 1fe58243c1becd36c0f05ae5b132d215f37061a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jan 2025 14:13:35 -0500 +Subject: drm/amdkfd: Set per-process flags only once for gfx9/10/11/12 + +From: Harish Kasiviswanathan + +[ Upstream commit 61972cd93af70738a6ad7f93e17cc7f68a01e182 ] + +Define set_cache_memory_policy() for these asics and move all static +changes from update_qpd() which is called each time a queue is created +to set_cache_memory_policy() which is called once during process +initialization + +Signed-off-by: Harish Kasiviswanathan +Reviewed-by: Amber Lin +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../amd/amdkfd/kfd_device_queue_manager_v10.c | 41 +++++++++++-------- + .../amd/amdkfd/kfd_device_queue_manager_v11.c | 41 +++++++++++-------- + .../amd/amdkfd/kfd_device_queue_manager_v12.c | 41 +++++++++++-------- + .../amd/amdkfd/kfd_device_queue_manager_v9.c | 36 +++++++++++++++- + 4 files changed, 107 insertions(+), 52 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c +index 245a90dfc2f6b..b5f5f141353b5 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c +@@ -31,10 +31,17 @@ static int update_qpd_v10(struct device_queue_manager *dqm, + struct qcm_process_device *qpd); + static void init_sdma_vm_v10(struct device_queue_manager *dqm, struct queue *q, + struct qcm_process_device *qpd); ++static bool set_cache_memory_policy_v10(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd, ++ enum cache_policy default_policy, ++ enum cache_policy alternate_policy, ++ void __user *alternate_aperture_base, ++ uint64_t alternate_aperture_size); + + void device_queue_manager_init_v10( + struct device_queue_manager_asic_ops *asic_ops) + { ++ asic_ops->set_cache_memory_policy = set_cache_memory_policy_v10; + asic_ops->update_qpd = update_qpd_v10; + asic_ops->init_sdma_vm = init_sdma_vm_v10; + asic_ops->mqd_manager_init = mqd_manager_init_v10; +@@ -49,27 +56,27 @@ static uint32_t compute_sh_mem_bases_64bit(struct kfd_process_device *pdd) + private_base; + } + +-static int update_qpd_v10(struct device_queue_manager *dqm, +- struct qcm_process_device *qpd) ++static bool set_cache_memory_policy_v10(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd, ++ enum cache_policy default_policy, ++ enum cache_policy alternate_policy, ++ void __user *alternate_aperture_base, ++ uint64_t alternate_aperture_size) + { +- struct kfd_process_device *pdd; +- +- pdd = qpd_to_pdd(qpd); +- +- /* check if sh_mem_config register already configured */ +- if (qpd->sh_mem_config == 0) { +- qpd->sh_mem_config = +- (SH_MEM_ALIGNMENT_MODE_UNALIGNED << +- SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | +- (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT); +- qpd->sh_mem_ape1_limit = 0; +- qpd->sh_mem_ape1_base = 0; +- } +- +- qpd->sh_mem_bases = compute_sh_mem_bases_64bit(pdd); ++ qpd->sh_mem_config = (SH_MEM_ALIGNMENT_MODE_UNALIGNED << ++ SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | ++ (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT); ++ qpd->sh_mem_ape1_limit = 0; ++ qpd->sh_mem_ape1_base = 0; ++ qpd->sh_mem_bases = compute_sh_mem_bases_64bit(qpd_to_pdd(qpd)); + + pr_debug("sh_mem_bases 0x%X\n", qpd->sh_mem_bases); ++ return true; ++} + ++static int update_qpd_v10(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd) ++{ + return 0; + } + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c +index 2e129da7acb43..f436878d0d621 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c +@@ -30,10 +30,17 @@ static int update_qpd_v11(struct device_queue_manager *dqm, + struct qcm_process_device *qpd); + static void init_sdma_vm_v11(struct device_queue_manager *dqm, struct queue *q, + struct qcm_process_device *qpd); ++static bool set_cache_memory_policy_v11(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd, ++ enum cache_policy default_policy, ++ enum cache_policy alternate_policy, ++ void __user *alternate_aperture_base, ++ uint64_t alternate_aperture_size); + + void device_queue_manager_init_v11( + struct device_queue_manager_asic_ops *asic_ops) + { ++ asic_ops->set_cache_memory_policy = set_cache_memory_policy_v11; + asic_ops->update_qpd = update_qpd_v11; + asic_ops->init_sdma_vm = init_sdma_vm_v11; + asic_ops->mqd_manager_init = mqd_manager_init_v11; +@@ -48,28 +55,28 @@ static uint32_t compute_sh_mem_bases_64bit(struct kfd_process_device *pdd) + private_base; + } + +-static int update_qpd_v11(struct device_queue_manager *dqm, +- struct qcm_process_device *qpd) ++static bool set_cache_memory_policy_v11(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd, ++ enum cache_policy default_policy, ++ enum cache_policy alternate_policy, ++ void __user *alternate_aperture_base, ++ uint64_t alternate_aperture_size) + { +- struct kfd_process_device *pdd; +- +- pdd = qpd_to_pdd(qpd); +- +- /* check if sh_mem_config register already configured */ +- if (qpd->sh_mem_config == 0) { +- qpd->sh_mem_config = +- (SH_MEM_ALIGNMENT_MODE_UNALIGNED << +- SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | +- (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT); +- +- qpd->sh_mem_ape1_limit = 0; +- qpd->sh_mem_ape1_base = 0; +- } ++ qpd->sh_mem_config = (SH_MEM_ALIGNMENT_MODE_UNALIGNED << ++ SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | ++ (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT); + +- qpd->sh_mem_bases = compute_sh_mem_bases_64bit(pdd); ++ qpd->sh_mem_ape1_limit = 0; ++ qpd->sh_mem_ape1_base = 0; ++ qpd->sh_mem_bases = compute_sh_mem_bases_64bit(qpd_to_pdd(qpd)); + + pr_debug("sh_mem_bases 0x%X\n", qpd->sh_mem_bases); ++ return true; ++} + ++static int update_qpd_v11(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd) ++{ + return 0; + } + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c +index 4f3295b29dfb1..62ca1c8fcbaf9 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c +@@ -30,10 +30,17 @@ static int update_qpd_v12(struct device_queue_manager *dqm, + struct qcm_process_device *qpd); + static void init_sdma_vm_v12(struct device_queue_manager *dqm, struct queue *q, + struct qcm_process_device *qpd); ++static bool set_cache_memory_policy_v12(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd, ++ enum cache_policy default_policy, ++ enum cache_policy alternate_policy, ++ void __user *alternate_aperture_base, ++ uint64_t alternate_aperture_size); + + void device_queue_manager_init_v12( + struct device_queue_manager_asic_ops *asic_ops) + { ++ asic_ops->set_cache_memory_policy = set_cache_memory_policy_v12; + asic_ops->update_qpd = update_qpd_v12; + asic_ops->init_sdma_vm = init_sdma_vm_v12; + asic_ops->mqd_manager_init = mqd_manager_init_v12; +@@ -48,28 +55,28 @@ static uint32_t compute_sh_mem_bases_64bit(struct kfd_process_device *pdd) + private_base; + } + +-static int update_qpd_v12(struct device_queue_manager *dqm, +- struct qcm_process_device *qpd) ++static bool set_cache_memory_policy_v12(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd, ++ enum cache_policy default_policy, ++ enum cache_policy alternate_policy, ++ void __user *alternate_aperture_base, ++ uint64_t alternate_aperture_size) + { +- struct kfd_process_device *pdd; +- +- pdd = qpd_to_pdd(qpd); +- +- /* check if sh_mem_config register already configured */ +- if (qpd->sh_mem_config == 0) { +- qpd->sh_mem_config = +- (SH_MEM_ALIGNMENT_MODE_UNALIGNED << +- SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | +- (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT); +- +- qpd->sh_mem_ape1_limit = 0; +- qpd->sh_mem_ape1_base = 0; +- } ++ qpd->sh_mem_config = (SH_MEM_ALIGNMENT_MODE_UNALIGNED << ++ SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | ++ (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT); + +- qpd->sh_mem_bases = compute_sh_mem_bases_64bit(pdd); ++ qpd->sh_mem_ape1_limit = 0; ++ qpd->sh_mem_ape1_base = 0; ++ qpd->sh_mem_bases = compute_sh_mem_bases_64bit(qpd_to_pdd(qpd)); + + pr_debug("sh_mem_bases 0x%X\n", qpd->sh_mem_bases); ++ return true; ++} + ++static int update_qpd_v12(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd) ++{ + return 0; + } + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c +index 210bcc048f4c5..3264509408bc8 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c +@@ -30,10 +30,17 @@ static int update_qpd_v9(struct device_queue_manager *dqm, + struct qcm_process_device *qpd); + static void init_sdma_vm_v9(struct device_queue_manager *dqm, struct queue *q, + struct qcm_process_device *qpd); ++static bool set_cache_memory_policy_v9(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd, ++ enum cache_policy default_policy, ++ enum cache_policy alternate_policy, ++ void __user *alternate_aperture_base, ++ uint64_t alternate_aperture_size); + + void device_queue_manager_init_v9( + struct device_queue_manager_asic_ops *asic_ops) + { ++ asic_ops->set_cache_memory_policy = set_cache_memory_policy_v9; + asic_ops->update_qpd = update_qpd_v9; + asic_ops->init_sdma_vm = init_sdma_vm_v9; + asic_ops->mqd_manager_init = mqd_manager_init_v9; +@@ -48,10 +55,37 @@ static uint32_t compute_sh_mem_bases_64bit(struct kfd_process_device *pdd) + private_base; + } + ++static bool set_cache_memory_policy_v9(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd, ++ enum cache_policy default_policy, ++ enum cache_policy alternate_policy, ++ void __user *alternate_aperture_base, ++ uint64_t alternate_aperture_size) ++{ ++ qpd->sh_mem_config = SH_MEM_ALIGNMENT_MODE_UNALIGNED << ++ SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT; ++ ++ if (dqm->dev->kfd->noretry) ++ qpd->sh_mem_config |= 1 << SH_MEM_CONFIG__RETRY_DISABLE__SHIFT; ++ ++ if (KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 4, 3) || ++ KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 4, 4) || ++ KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 5, 0)) ++ qpd->sh_mem_config |= (1 << SH_MEM_CONFIG__F8_MODE__SHIFT); ++ ++ qpd->sh_mem_ape1_limit = 0; ++ qpd->sh_mem_ape1_base = 0; ++ qpd->sh_mem_bases = compute_sh_mem_bases_64bit(qpd_to_pdd(qpd)); ++ ++ pr_debug("sh_mem_bases 0x%X sh_mem_config 0x%X\n", qpd->sh_mem_bases, ++ qpd->sh_mem_config); ++ return true; ++} ++ + static int update_qpd_v9(struct device_queue_manager *dqm, + struct qcm_process_device *qpd) + { +- struct kfd_process_device *pdd; ++ struct kfd_process_device *pdd = qpd_to_pdd(qpd); + + pdd = qpd_to_pdd(qpd); + +-- +2.39.5 + diff --git a/queue-6.12/drm-amdkfd-set-precise-mem-ops-caps-to-disabled-for-.patch b/queue-6.12/drm-amdkfd-set-precise-mem-ops-caps-to-disabled-for-.patch new file mode 100644 index 0000000000..4544691f73 --- /dev/null +++ b/queue-6.12/drm-amdkfd-set-precise-mem-ops-caps-to-disabled-for-.patch @@ -0,0 +1,40 @@ +From 48028dc3efcb6679b30408c2065dacfdf4f97af4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 11:08:21 -0400 +Subject: drm/amdkfd: set precise mem ops caps to disabled for gfx 11 and 12 + +From: Jonathan Kim + +[ Upstream commit f82d27dcff939d3cbecbc60e1b71e2518c37e81d ] + +Clause instructions with precise memory enabled currently hang the +shader so set capabilities flag to disabled since it's unsafe to use +for debugging. + +Signed-off-by: Jonathan Kim +Tested-by: Lancelot Six +Reviewed-by: Harish Kasiviswanathan +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +index 3871591c9aec9..bcb5cdc4a9d81 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +@@ -2002,10 +2002,6 @@ static void kfd_topology_set_capabilities(struct kfd_topology_device *dev) + dev->node_props.debug_prop |= HSA_DBG_WATCH_ADDR_MASK_LO_BIT_GFX10 | + HSA_DBG_WATCH_ADDR_MASK_HI_BIT; + +- if (KFD_GC_VERSION(dev->gpu) >= IP_VERSION(11, 0, 0)) +- dev->node_props.capability |= +- HSA_CAP_TRAP_DEBUG_PRECISE_MEMORY_OPERATIONS_SUPPORTED; +- + if (KFD_GC_VERSION(dev->gpu) >= IP_VERSION(12, 0, 0)) + dev->node_props.capability |= + HSA_CAP_TRAP_DEBUG_PRECISE_ALU_OPERATIONS_SUPPORTED; +-- +2.39.5 + diff --git a/queue-6.12/drm-ast-find-vbios-mode-from-regular-display-size.patch b/queue-6.12/drm-ast-find-vbios-mode-from-regular-display-size.patch new file mode 100644 index 0000000000..42e8a296ad --- /dev/null +++ b/queue-6.12/drm-ast-find-vbios-mode-from-regular-display-size.patch @@ -0,0 +1,89 @@ +From f76e569b97b0992d4a0cdddf5d38bab265130fb0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 10:21:08 +0100 +Subject: drm/ast: Find VBIOS mode from regular display size + +From: Thomas Zimmermann + +[ Upstream commit c81202906b5cd56db403e95db3d29c9dfc8c74c1 ] + +The ast driver looks up supplied display modes from an internal list of +display modes supported by the VBIOS. + +Do not use the crtc_-prefixed display values from struct drm_display_mode +for looking up the VBIOS mode. The fields contain raw values that the +driver programs to hardware. They are affected by display settings like +double-scan or interlace. + +Instead use the regular vdisplay and hdisplay fields for lookup. As the +programmed values can now differ from the values used for lookup, set +struct drm_display_mode.crtc_vdisplay and .crtc_hdisplay from the VBIOS +mode. + +Signed-off-by: Thomas Zimmermann +Reviewed-by: Jocelyn Falempe +Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-9-tzimmermann@suse.de +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/ast/ast_mode.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c +index ed496fb32bf34..24ed1cd3caf17 100644 +--- a/drivers/gpu/drm/ast/ast_mode.c ++++ b/drivers/gpu/drm/ast/ast_mode.c +@@ -131,7 +131,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, + return false; + } + +- switch (mode->crtc_hdisplay) { ++ switch (mode->hdisplay) { + case 640: + vbios_mode->enh_table = &res_640x480[refresh_rate_index]; + break; +@@ -145,7 +145,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, + vbios_mode->enh_table = &res_1152x864[refresh_rate_index]; + break; + case 1280: +- if (mode->crtc_vdisplay == 800) ++ if (mode->vdisplay == 800) + vbios_mode->enh_table = &res_1280x800[refresh_rate_index]; + else + vbios_mode->enh_table = &res_1280x1024[refresh_rate_index]; +@@ -157,7 +157,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, + vbios_mode->enh_table = &res_1440x900[refresh_rate_index]; + break; + case 1600: +- if (mode->crtc_vdisplay == 900) ++ if (mode->vdisplay == 900) + vbios_mode->enh_table = &res_1600x900[refresh_rate_index]; + else + vbios_mode->enh_table = &res_1600x1200[refresh_rate_index]; +@@ -166,7 +166,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, + vbios_mode->enh_table = &res_1680x1050[refresh_rate_index]; + break; + case 1920: +- if (mode->crtc_vdisplay == 1080) ++ if (mode->vdisplay == 1080) + vbios_mode->enh_table = &res_1920x1080[refresh_rate_index]; + else + vbios_mode->enh_table = &res_1920x1200[refresh_rate_index]; +@@ -210,6 +210,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, + hborder = (vbios_mode->enh_table->flags & HBorder) ? 8 : 0; + vborder = (vbios_mode->enh_table->flags & VBorder) ? 8 : 0; + ++ adjusted_mode->crtc_hdisplay = vbios_mode->enh_table->hde; + adjusted_mode->crtc_htotal = vbios_mode->enh_table->ht; + adjusted_mode->crtc_hblank_start = vbios_mode->enh_table->hde + hborder; + adjusted_mode->crtc_hblank_end = vbios_mode->enh_table->ht - hborder; +@@ -219,6 +220,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, + vbios_mode->enh_table->hfp + + vbios_mode->enh_table->hsync); + ++ adjusted_mode->crtc_vdisplay = vbios_mode->enh_table->vde; + adjusted_mode->crtc_vtotal = vbios_mode->enh_table->vt; + adjusted_mode->crtc_vblank_start = vbios_mode->enh_table->vde + vborder; + adjusted_mode->crtc_vblank_end = vbios_mode->enh_table->vt - vborder; +-- +2.39.5 + diff --git a/queue-6.12/drm-atomic-clarify-the-rules-around-drm_atomic_state.patch b/queue-6.12/drm-atomic-clarify-the-rules-around-drm_atomic_state.patch new file mode 100644 index 0000000000..3200e937aa --- /dev/null +++ b/queue-6.12/drm-atomic-clarify-the-rules-around-drm_atomic_state.patch @@ -0,0 +1,90 @@ +From 1fdc960d1ed86da405fa14056741124b79509d5f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jan 2025 18:24:16 +0100 +Subject: drm/atomic: clarify the rules around drm_atomic_state->allow_modeset +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Simona Vetter + +[ Upstream commit c5e3306a424b52e38ad2c28c7f3399fcd03e383d ] + +msm is automagically upgrading normal commits to full modesets, and +that's a big no-no: + +- for one this results in full on->off->on transitions on all these + crtc, at least if you're using the usual helpers. Which seems to be + the case, and is breaking uapi + +- further even if the ctm change itself would not result in flicker, + this can hide modesets for other reasons. Which again breaks the + uapi + +v2: I forgot the case of adding unrelated crtc state. Add that case +and link to the existing kerneldoc explainers. This has come up in an +irc discussion with Manasi and Ville about intel's bigjoiner mode. +Also cc everyone involved in the msm irc discussion, more people +joined after I sent out v1. + +v3: Wording polish from Pekka and Thomas + +Acked-by: Pekka Paalanen +Acked-by: Dmitry Baryshkov +Cc: Maarten Lankhorst +Cc: Maxime Ripard +Cc: Thomas Zimmermann +Cc: David Airlie +Cc: Daniel Vetter +Cc: Pekka Paalanen +Cc: Rob Clark +Cc: Simon Ser +Cc: Manasi Navare +Cc: Ville Syrjälä +Cc: Abhinav Kumar +Cc: Dmitry Baryshkov +Signed-off-by: Simona Vetter +Signed-off-by: Simona Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/20250108172417.160831-1-simona.vetter@ffwll.ch +Signed-off-by: Sasha Levin +--- + include/drm/drm_atomic.h | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h +index 31ca88deb10d2..1ded9a8d4e84d 100644 +--- a/include/drm/drm_atomic.h ++++ b/include/drm/drm_atomic.h +@@ -376,8 +376,27 @@ struct drm_atomic_state { + * + * Allow full modeset. This is used by the ATOMIC IOCTL handler to + * implement the DRM_MODE_ATOMIC_ALLOW_MODESET flag. Drivers should +- * never consult this flag, instead looking at the output of +- * drm_atomic_crtc_needs_modeset(). ++ * generally not consult this flag, but instead look at the output of ++ * drm_atomic_crtc_needs_modeset(). The detailed rules are: ++ * ++ * - Drivers must not consult @allow_modeset in the atomic commit path. ++ * Use drm_atomic_crtc_needs_modeset() instead. ++ * ++ * - Drivers must consult @allow_modeset before adding unrelated struct ++ * drm_crtc_state to this commit by calling ++ * drm_atomic_get_crtc_state(). See also the warning in the ++ * documentation for that function. ++ * ++ * - Drivers must never change this flag, it is under the exclusive ++ * control of userspace. ++ * ++ * - Drivers may consult @allow_modeset in the atomic check path, if ++ * they have the choice between an optimal hardware configuration ++ * which requires a modeset, and a less optimal configuration which ++ * can be committed without a modeset. An example would be suboptimal ++ * scanout FIFO allocation resulting in increased idle power ++ * consumption. This allows userspace to avoid flickering and delays ++ * for the normal composition loop at reasonable cost. + */ + bool allow_modeset : 1; + /** +-- +2.39.5 + diff --git a/queue-6.12/drm-bridge-adv7511-fill-stream-capabilities.patch b/queue-6.12/drm-bridge-adv7511-fill-stream-capabilities.patch new file mode 100644 index 0000000000..bc89ab6bf8 --- /dev/null +++ b/queue-6.12/drm-bridge-adv7511-fill-stream-capabilities.patch @@ -0,0 +1,39 @@ +From c86bd60f50af36d637dd6f6ce97c0d6c552cd4b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jan 2025 18:03:54 +0100 +Subject: drm: bridge: adv7511: fill stream capabilities + +From: Olivier Moysan + +[ Upstream commit c852646f12d4cd5b4f19eeec2976c5d98c0382f8 ] + +Set no_i2s_capture and no_spdif_capture flags in hdmi_codec_pdata structure +to report that the ADV7511 HDMI bridge does not support i2s or spdif audio +capture. + +Signed-off-by: Olivier Moysan +Reviewed-by: Dmitry Baryshkov +Link: https://patchwork.freedesktop.org/patch/msgid/20250108170356.413063-2-olivier.moysan@foss.st.com +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/bridge/adv7511/adv7511_audio.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c +index 8f786592143b6..24e1e11acf697 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c +@@ -244,7 +244,9 @@ static const struct hdmi_codec_pdata codec_data = { + .ops = &adv7511_codec_ops, + .max_i2s_channels = 2, + .i2s = 1, ++ .no_i2s_capture = 1, + .spdif = 1, ++ .no_spdif_capture = 1, + }; + + int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511) +-- +2.39.5 + diff --git a/queue-6.12/drm-buddy-fix-issue-that-force_merge-cannot-free-all.patch b/queue-6.12/drm-buddy-fix-issue-that-force_merge-cannot-free-all.patch new file mode 100644 index 0000000000..6a593ac6ef --- /dev/null +++ b/queue-6.12/drm-buddy-fix-issue-that-force_merge-cannot-free-all.patch @@ -0,0 +1,54 @@ +From d26c1182a9f8e5e54dab4211889be515be055f89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 26 Dec 2024 12:31:15 +0530 +Subject: drm/buddy: fix issue that force_merge cannot free all roots + +From: Lin.Cao + +[ Upstream commit 467dce3817bd2b62ccd6fcfd7aae76f242ac907e ] + +If buddy manager have more than one roots and each root have sub-block +need to be free. When drm_buddy_fini called, the first loop of +force_merge will merge and free all of the sub block of first root, +which offset is 0x0 and size is biggest(more than have of the mm size). +In subsequent force_merge rounds, if we use 0 as start and use remaining +mm size as end, the block of other roots will be skipped in +__force_merge function. It will cause the other roots can not be freed. + +Solution: use roots' offset as the start could fix this issue. + +Signed-off-by: Lin.Cao +Signed-off-by: Arunpravin Paneer Selvam +Reviewed-by: Matthew Auld +Link: https://patchwork.freedesktop.org/patch/msgid/20241226070116.309290-1-Arunpravin.PaneerSelvam@amd.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/drm_buddy.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c +index 103c185bb1c8a..ca42e6081d27c 100644 +--- a/drivers/gpu/drm/drm_buddy.c ++++ b/drivers/gpu/drm/drm_buddy.c +@@ -324,7 +324,7 @@ EXPORT_SYMBOL(drm_buddy_init); + */ + void drm_buddy_fini(struct drm_buddy *mm) + { +- u64 root_size, size; ++ u64 root_size, size, start; + unsigned int order; + int i; + +@@ -332,7 +332,8 @@ void drm_buddy_fini(struct drm_buddy *mm) + + for (i = 0; i < mm->n_roots; ++i) { + order = ilog2(size) - ilog2(mm->chunk_size); +- __force_merge(mm, 0, size, order); ++ start = drm_buddy_block_offset(mm->roots[i]); ++ __force_merge(mm, start, start + size, order); + + WARN_ON(!drm_buddy_block_is_free(mm->roots[i])); + drm_block_free(mm, mm->roots[i]); +-- +2.39.5 + diff --git a/queue-6.12/drm-gem-test-for-imported-gem-buffers-with-helper.patch b/queue-6.12/drm-gem-test-for-imported-gem-buffers-with-helper.patch new file mode 100644 index 0000000000..dbd37b78f7 --- /dev/null +++ b/queue-6.12/drm-gem-test-for-imported-gem-buffers-with-helper.patch @@ -0,0 +1,88 @@ +From 7df9350fe8c3338fee827a28b35418cbb55e3b8a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 18:03:04 +0100 +Subject: drm/gem: Test for imported GEM buffers with helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Thomas Zimmermann + +[ Upstream commit b57aa47d39e94dc47403a745e2024664e544078c ] + +Add drm_gem_is_imported() that tests if a GEM object's buffer has +been imported. Update the GEM code accordingly. + +GEM code usually tests for imports if import_attach has been set +in struct drm_gem_object. But attaching a dma-buf on import requires +a DMA-capable importer device, which is not the case for many serial +busses like USB or I2C. The new helper tests if a GEM object's dma-buf +has been created from the GEM object. + +Signed-off-by: Thomas Zimmermann +Reviewed-by: Anusha Srivatsa +Reviewed-by: Christian König +Link: https://patchwork.freedesktop.org/patch/msgid/20250226172457.217725-2-tzimmermann@suse.de +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/drm_gem.c | 4 ++-- + include/drm/drm_gem.h | 14 ++++++++++++++ + 2 files changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c +index 149b8e25da5bb..426d0867882df 100644 +--- a/drivers/gpu/drm/drm_gem.c ++++ b/drivers/gpu/drm/drm_gem.c +@@ -322,7 +322,7 @@ int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, + return -ENOENT; + + /* Don't allow imported objects to be mapped */ +- if (obj->import_attach) { ++ if (drm_gem_is_imported(obj)) { + ret = -EINVAL; + goto out; + } +@@ -1152,7 +1152,7 @@ void drm_gem_print_info(struct drm_printer *p, unsigned int indent, + drm_vma_node_start(&obj->vma_node)); + drm_printf_indent(p, indent, "size=%zu\n", obj->size); + drm_printf_indent(p, indent, "imported=%s\n", +- str_yes_no(obj->import_attach)); ++ str_yes_no(drm_gem_is_imported(obj))); + + if (obj->funcs->print_info) + obj->funcs->print_info(p, indent, obj); +diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h +index d8b86df2ec0da..70c0f8c83629d 100644 +--- a/include/drm/drm_gem.h ++++ b/include/drm/drm_gem.h +@@ -35,6 +35,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -570,6 +571,19 @@ static inline bool drm_gem_object_is_shared_for_memory_stats(struct drm_gem_obje + return (obj->handle_count > 1) || obj->dma_buf; + } + ++/** ++ * drm_gem_is_imported() - Tests if GEM object's buffer has been imported ++ * @obj: the GEM object ++ * ++ * Returns: ++ * True if the GEM object's buffer has been imported, false otherwise ++ */ ++static inline bool drm_gem_is_imported(const struct drm_gem_object *obj) ++{ ++ /* The dma-buf's priv field points to the original GEM object. */ ++ return obj->dma_buf && (obj->dma_buf->priv != obj); ++} ++ + #ifdef CONFIG_LOCKDEP + /** + * drm_gem_gpuva_set_lock() - Set the lock protecting accesses to the gpuva list. +-- +2.39.5 + diff --git a/queue-6.12/drm-mediatek-mtk_dpi-add-checks-for-reg_h_fre_con-ex.patch b/queue-6.12/drm-mediatek-mtk_dpi-add-checks-for-reg_h_fre_con-ex.patch new file mode 100644 index 0000000000..793c9106ab --- /dev/null +++ b/queue-6.12/drm-mediatek-mtk_dpi-add-checks-for-reg_h_fre_con-ex.patch @@ -0,0 +1,51 @@ +From 07d712d32f771e1511bc804275be08cdba94eb47 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 16:47:58 +0100 +Subject: drm/mediatek: mtk_dpi: Add checks for reg_h_fre_con existence + +From: AngeloGioacchino Del Regno + +[ Upstream commit 8c9da7cd0bbcc90ab444454fecf535320456a312 ] + +In preparation for adding support for newer DPI instances which +do support direct-pin but do not have any H_FRE_CON register, +like the one found in MT8195 and MT8188, add a branch to check +if the reg_h_fre_con variable was declared in the mtk_dpi_conf +structure for the probed SoC DPI version. + +As a note, this is useful specifically only for cases in which +the support_direct_pin variable is true, so mt8195-dpintf is +not affected by any issue. + +Reviewed-by: CK Hu +Signed-off-by: AngeloGioacchino Del Regno +Link: https://patchwork.kernel.org/project/dri-devel/patch/20250217154836.108895-6-angelogioacchino.delregno@collabora.com/ +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/mediatek/mtk_dpi.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c +index 9c11d3158324c..20a50180d4d49 100644 +--- a/drivers/gpu/drm/mediatek/mtk_dpi.c ++++ b/drivers/gpu/drm/mediatek/mtk_dpi.c +@@ -410,12 +410,13 @@ static void mtk_dpi_config_swap_input(struct mtk_dpi *dpi, bool enable) + + static void mtk_dpi_config_2n_h_fre(struct mtk_dpi *dpi) + { +- mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, H_FRE_2N, H_FRE_2N); ++ if (dpi->conf->reg_h_fre_con) ++ mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, H_FRE_2N, H_FRE_2N); + } + + static void mtk_dpi_config_disable_edge(struct mtk_dpi *dpi) + { +- if (dpi->conf->edge_sel_en) ++ if (dpi->conf->edge_sel_en && dpi->conf->reg_h_fre_con) + mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, 0, EDGE_SEL_EN); + } + +-- +2.39.5 + diff --git a/queue-6.12/drm-nouveau-fix-the-broken-marco-gsp_msg_max_size.patch b/queue-6.12/drm-nouveau-fix-the-broken-marco-gsp_msg_max_size.patch new file mode 100644 index 0000000000..93b9014e02 --- /dev/null +++ b/queue-6.12/drm-nouveau-fix-the-broken-marco-gsp_msg_max_size.patch @@ -0,0 +1,39 @@ +From c5baf9fd2d65f57362c25a57799f36f7c4b73b74 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 10:29:50 -0800 +Subject: drm/nouveau: fix the broken marco GSP_MSG_MAX_SIZE + +From: Zhi Wang + +[ Upstream commit bbae6680cfe38b033250b483722e60ccd865976f ] + +The macro GSP_MSG_MAX_SIZE refers to another macro that doesn't exist. +It represents the max GSP message element size. + +Fix the broken marco so it can be used to replace some magic numbers in +the code. + +Signed-off-by: Zhi Wang +Signed-off-by: Danilo Krummrich +Link: https://patchwork.freedesktop.org/patch/msgid/20250124182958.2040494-8-zhiw@nvidia.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +index 9c83bab0a5309..fc84ca214f247 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +@@ -58,7 +58,7 @@ + #include + + #define GSP_MSG_MIN_SIZE GSP_PAGE_SIZE +-#define GSP_MSG_MAX_SIZE GSP_PAGE_MIN_SIZE * 16 ++#define GSP_MSG_MAX_SIZE (GSP_MSG_MIN_SIZE * 16) + + struct r535_gsp_msg { + u8 auth_tag_buffer[16]; +-- +2.39.5 + diff --git a/queue-6.12/drm-panel-edp-add-starry-116khd024006.patch b/queue-6.12/drm-panel-edp-add-starry-116khd024006.patch new file mode 100644 index 0000000000..8fd887ab82 --- /dev/null +++ b/queue-6.12/drm-panel-edp-add-starry-116khd024006.patch @@ -0,0 +1,57 @@ +From dc7114cb5a5a024022d466dcd59580627f04719b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jan 2025 14:28:53 -0800 +Subject: drm/panel-edp: Add Starry 116KHD024006 + +From: Douglas Anderson + +[ Upstream commit 749b5b279e5636cdcef51e15d67b77162cca6caa ] + +We have a few reports of sc7180-trogdor-pompom devices that have a +panel in them that IDs as STA 0x0004 and has the following raw EDID: + + 00 ff ff ff ff ff ff 00 4e 81 04 00 00 00 00 00 + 10 20 01 04 a5 1a 0e 78 0a dc dd 96 5b 5b 91 28 + 1f 52 54 00 00 00 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 8e 1c 56 a0 50 00 1e 30 28 20 + 55 00 00 90 10 00 00 18 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fe + 00 31 31 36 4b 48 44 30 32 34 30 30 36 0a 00 e6 + +We've been unable to locate a datasheet for this panel and our partner +has not been responsive, but all Starry eDP datasheets that we can +find agree on the same timing (delay_100_500_e200) so it should be +safe to use that here instead of the super conservative timings. We'll +still go a little extra conservative and allow `hpd_absent` of 200 +instead of 100 because that won't add any real-world delay in most +cases. + +We'll associate the string from the EDID ("116KHD024006") with this +panel. Given that the ID is the suspicious value of 0x0004 it seems +likely that Starry doesn't always update their IDs but the string will +still work to differentiate if we ever need to in the future. + +Reviewed-by: Neil Armstrong +Signed-off-by: Douglas Anderson +Link: https://patchwork.freedesktop.org/patch/msgid/20250109142853.1.Ibcc3009933fd19507cc9c713ad0c99c7a9e4fe17@changeid +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panel/panel-edp.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c +index 767e47a2b0c14..663af985d1b38 100644 +--- a/drivers/gpu/drm/panel/panel-edp.c ++++ b/drivers/gpu/drm/panel/panel-edp.c +@@ -1983,6 +1983,7 @@ static const struct edp_panel_entry edp_panels[] = { + EDP_PANEL_ENTRY('S', 'H', 'P', 0x153a, &delay_200_500_e50, "LQ140T1JH01"), + EDP_PANEL_ENTRY('S', 'H', 'P', 0x154c, &delay_200_500_p2e100, "LQ116M1JW10"), + ++ EDP_PANEL_ENTRY('S', 'T', 'A', 0x0004, &delay_200_500_e200, "116KHD024006"), + EDP_PANEL_ENTRY('S', 'T', 'A', 0x0100, &delay_100_500_e200, "2081116HHD028001-51D"), + + { /* sentinal */ } +-- +2.39.5 + diff --git a/queue-6.12/drm-rockchip-vop2-add-uv-swap-for-cluster-window.patch b/queue-6.12/drm-rockchip-vop2-add-uv-swap-for-cluster-window.patch new file mode 100644 index 0000000000..7569791283 --- /dev/null +++ b/queue-6.12/drm-rockchip-vop2-add-uv-swap-for-cluster-window.patch @@ -0,0 +1,46 @@ +From 45cdcfb087bbe8e3246d4568cb3f83a40931a5a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 11:44:17 +0800 +Subject: drm/rockchip: vop2: Add uv swap for cluster window + +From: Andy Yan + +[ Upstream commit e7aae9f6d762139f8d2b86db03793ae0ab3dd802 ] + +The Cluster windows of upcoming VOP on rk3576 also support +linear YUV support, we need to set uv swap bit for it. + +As the VOP2_WIN_UV_SWA register defined on rk3568/rk3588 is +0xffffffff, so this register will not be touched on these +two platforms. + +Signed-off-by: Andy Yan +Tested-by: Michael Riesch # on RK3568 +Tested-by: Detlev Casanova +Signed-off-by: Heiko Stuebner +Link: https://patchwork.freedesktop.org/patch/msgid/20250303034436.192400-4-andyshrk@163.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +index 5880d87fe6b3a..2aab2a0956788 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +@@ -1432,10 +1432,8 @@ static void vop2_plane_atomic_update(struct drm_plane *plane, + + rb_swap = vop2_win_rb_swap(fb->format->format); + vop2_win_write(win, VOP2_WIN_RB_SWAP, rb_swap); +- if (!vop2_cluster_window(win)) { +- uv_swap = vop2_win_uv_swap(fb->format->format); +- vop2_win_write(win, VOP2_WIN_UV_SWAP, uv_swap); +- } ++ uv_swap = vop2_win_uv_swap(fb->format->format); ++ vop2_win_write(win, VOP2_WIN_UV_SWAP, uv_swap); + + if (fb->format->is_yuv) { + vop2_win_write(win, VOP2_WIN_UV_VIR, DIV_ROUND_UP(fb->pitches[1], 4)); +-- +2.39.5 + diff --git a/queue-6.12/drm-rockchip-vop2-improve-display-modes-handling-on-.patch b/queue-6.12/drm-rockchip-vop2-improve-display-modes-handling-on-.patch new file mode 100644 index 0000000000..bf36e5526a --- /dev/null +++ b/queue-6.12/drm-rockchip-vop2-improve-display-modes-handling-on-.patch @@ -0,0 +1,112 @@ +From 5d95e19f07a4207466eb8fd3252d63dbb48bf377 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 14:40:06 +0200 +Subject: drm/rockchip: vop2: Improve display modes handling on RK3588 HDMI0 + +From: Cristian Ciocaltea + +[ Upstream commit 2c1268e7aad0819f38e56134bbc2095fd95fde1b ] + +The RK3588 specific implementation is currently quite limited in terms +of handling the full range of display modes supported by the connected +screens, e.g. 2560x1440@75Hz, 2048x1152@60Hz, 1024x768@60Hz are just a +few of them. + +Additionally, it doesn't cope well with non-integer refresh rates like +59.94, 29.97, 23.98, etc. + +Make use of HDMI0 PHY PLL as a more accurate DCLK source to handle +all display modes up to 4K@60Hz. + +Tested-by: FUKAUMI Naoki +Signed-off-by: Cristian Ciocaltea +Signed-off-by: Heiko Stuebner +Link: https://patchwork.freedesktop.org/patch/msgid/20250204-vop2-hdmi0-disp-modes-v3-3-d71c6a196e58@collabora.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 34 ++++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +index 2aab2a0956788..5d7df4c3b08c4 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +@@ -157,6 +157,7 @@ struct vop2_video_port { + struct drm_crtc crtc; + struct vop2 *vop2; + struct clk *dclk; ++ struct clk *dclk_src; + unsigned int id; + const struct vop2_video_port_data *data; + +@@ -211,6 +212,7 @@ struct vop2 { + struct clk *hclk; + struct clk *aclk; + struct clk *pclk; ++ struct clk *pll_hdmiphy0; + + /* optional internal rgb encoder */ + struct rockchip_rgb *rgb; +@@ -219,6 +221,8 @@ struct vop2 { + struct vop2_win win[]; + }; + ++#define VOP2_MAX_DCLK_RATE 600000000 ++ + #define vop2_output_if_is_hdmi(x) ((x) == ROCKCHIP_VOP2_EP_HDMI0 || \ + (x) == ROCKCHIP_VOP2_EP_HDMI1) + +@@ -1051,6 +1055,9 @@ static void vop2_crtc_atomic_disable(struct drm_crtc *crtc, + + vop2_crtc_disable_irq(vp, VP_INT_DSP_HOLD_VALID); + ++ if (vp->dclk_src) ++ clk_set_parent(vp->dclk, vp->dclk_src); ++ + clk_disable_unprepare(vp->dclk); + + vop2->enable_count--; +@@ -2071,6 +2078,27 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, + + vop2_vp_write(vp, RK3568_VP_MIPI_CTRL, 0); + ++ /* ++ * Switch to HDMI PHY PLL as DCLK source for display modes up ++ * to 4K@60Hz, if available, otherwise keep using the system CRU. ++ */ ++ if (vop2->pll_hdmiphy0 && clock <= VOP2_MAX_DCLK_RATE) { ++ drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) { ++ struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder); ++ ++ if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI0) { ++ if (!vp->dclk_src) ++ vp->dclk_src = clk_get_parent(vp->dclk); ++ ++ ret = clk_set_parent(vp->dclk, vop2->pll_hdmiphy0); ++ if (ret < 0) ++ drm_warn(vop2->drm, ++ "Could not switch to HDMI0 PHY PLL: %d\n", ret); ++ break; ++ } ++ } ++ } ++ + clk_set_rate(vp->dclk, clock); + + vop2_post_config(crtc); +@@ -3242,6 +3270,12 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) + return PTR_ERR(vop2->pclk); + } + ++ vop2->pll_hdmiphy0 = devm_clk_get_optional(vop2->dev, "pll_hdmiphy0"); ++ if (IS_ERR(vop2->pll_hdmiphy0)) { ++ drm_err(vop2->drm, "failed to get pll_hdmiphy0\n"); ++ return PTR_ERR(vop2->pll_hdmiphy0); ++ } ++ + vop2->irq = platform_get_irq(pdev, 0); + if (vop2->irq < 0) { + drm_err(vop2->drm, "cannot find irq for vop2\n"); +-- +2.39.5 + diff --git a/queue-6.12/drm-v3d-add-clock-handling.patch b/queue-6.12/drm-v3d-add-clock-handling.patch new file mode 100644 index 0000000000..3fe1e91f12 --- /dev/null +++ b/queue-6.12/drm-v3d-add-clock-handling.patch @@ -0,0 +1,108 @@ +From 78a6a9639f1cc6e50a745e5ee68efa1270fd4e46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Feb 2025 13:50:46 +0100 +Subject: drm/v3d: Add clock handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Stefan Wahren + +[ Upstream commit 4dd40b5f9c3d89b67af0dbe059cf4a51aac6bf06 ] + +Since the initial commit 57692c94dcbe ("drm/v3d: Introduce a new DRM driver +for Broadcom V3D V3.x+") the struct v3d_dev reserved a pointer for +an optional V3D clock. But there wasn't any code, which fetched it. +So add the missing clock handling before accessing any V3D registers. + +Signed-off-by: Stefan Wahren +Reviewed-by: Maíra Canal +Signed-off-by: Maíra Canal +Link: https://patchwork.freedesktop.org/patch/msgid/20250201125046.33030-1-wahrenst@gmx.net +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/v3d/v3d_drv.c | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c +index d7ff1f5fa481f..7c17108da7d2d 100644 +--- a/drivers/gpu/drm/v3d/v3d_drv.c ++++ b/drivers/gpu/drm/v3d/v3d_drv.c +@@ -286,11 +286,21 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) + if (ret) + return ret; + ++ v3d->clk = devm_clk_get_optional(dev, NULL); ++ if (IS_ERR(v3d->clk)) ++ return dev_err_probe(dev, PTR_ERR(v3d->clk), "Failed to get V3D clock\n"); ++ ++ ret = clk_prepare_enable(v3d->clk); ++ if (ret) { ++ dev_err(&pdev->dev, "Couldn't enable the V3D clock\n"); ++ return ret; ++ } ++ + mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO); + mask = DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH)); + ret = dma_set_mask_and_coherent(dev, mask); + if (ret) +- return ret; ++ goto clk_disable; + + v3d->va_width = 30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_VA_WIDTH); + +@@ -310,28 +320,29 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) + ret = PTR_ERR(v3d->reset); + + if (ret == -EPROBE_DEFER) +- return ret; ++ goto clk_disable; + + v3d->reset = NULL; + ret = map_regs(v3d, &v3d->bridge_regs, "bridge"); + if (ret) { + dev_err(dev, + "Failed to get reset control or bridge regs\n"); +- return ret; ++ goto clk_disable; + } + } + + if (v3d->ver < 41) { + ret = map_regs(v3d, &v3d->gca_regs, "gca"); + if (ret) +- return ret; ++ goto clk_disable; + } + + v3d->mmu_scratch = dma_alloc_wc(dev, 4096, &v3d->mmu_scratch_paddr, + GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO); + if (!v3d->mmu_scratch) { + dev_err(dev, "Failed to allocate MMU scratch page\n"); +- return -ENOMEM; ++ ret = -ENOMEM; ++ goto clk_disable; + } + + ret = v3d_gem_init(drm); +@@ -360,6 +371,8 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) + v3d_gem_destroy(drm); + dma_free: + dma_free_wc(dev, 4096, v3d->mmu_scratch, v3d->mmu_scratch_paddr); ++clk_disable: ++ clk_disable_unprepare(v3d->clk); + return ret; + } + +@@ -377,6 +390,8 @@ static void v3d_platform_drm_remove(struct platform_device *pdev) + + dma_free_wc(v3d->drm.dev, 4096, v3d->mmu_scratch, + v3d->mmu_scratch_paddr); ++ ++ clk_disable_unprepare(v3d->clk); + } + + static struct platform_driver v3d_platform_driver = { +-- +2.39.5 + diff --git a/queue-6.12/drm-xe-debugfs-add-missing-xe_pm_runtime_put-in-wedg.patch b/queue-6.12/drm-xe-debugfs-add-missing-xe_pm_runtime_put-in-wedg.patch new file mode 100644 index 0000000000..4c89b99d86 --- /dev/null +++ b/queue-6.12/drm-xe-debugfs-add-missing-xe_pm_runtime_put-in-wedg.patch @@ -0,0 +1,36 @@ +From b7870dbafbf39915dd942704700f6a88f4a90d32 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 23:03:22 +0000 +Subject: drm/xe/debugfs: Add missing xe_pm_runtime_put in wedge_mode_set + +From: Shuicheng Lin + +[ Upstream commit b31e668d3111b100d16fd7db8db335328ce8c6d5 ] + +xe_pm_runtime_put is missed in the failure path. + +Cc: Rodrigo Vivi +Signed-off-by: Shuicheng Lin +Reviewed-by: Rodrigo Vivi +Link: https://patchwork.freedesktop.org/patch/msgid/20250213230322.1180621-1-shuicheng.lin@intel.com +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_debugfs.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c +index 051a37e477f4c..278ce1c37b395 100644 +--- a/drivers/gpu/drm/xe/xe_debugfs.c ++++ b/drivers/gpu/drm/xe/xe_debugfs.c +@@ -156,6 +156,7 @@ static ssize_t wedged_mode_set(struct file *f, const char __user *ubuf, + ret = xe_guc_ads_scheduler_policy_toggle_reset(>->uc.guc.ads); + if (ret) { + xe_gt_err(gt, "Failed to update GuC ADS scheduler policy. GuC may still cause engine reset even with wedged_mode=2\n"); ++ xe_pm_runtime_put(xe); + return -EIO; + } + } +-- +2.39.5 + diff --git a/queue-6.12/drm-xe-debugfs-fixed-the-return-value-of-wedged_mode.patch b/queue-6.12/drm-xe-debugfs-fixed-the-return-value-of-wedged_mode.patch new file mode 100644 index 0000000000..de323910a5 --- /dev/null +++ b/queue-6.12/drm-xe-debugfs-fixed-the-return-value-of-wedged_mode.patch @@ -0,0 +1,51 @@ +From ab7e96abd815d7e340e80fc664ba083efd440bd5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 06:36:15 +0800 +Subject: drm/xe/debugfs: fixed the return value of wedged_mode_set + +From: Xin Wang + +[ Upstream commit 6884d2051011f4db9e2f0b85709c79a8ced13bd6 ] + +It is generally expected that the write() function should return a +positive value indicating the number of bytes written or a negative +error code if an error occurs. Returning 0 is unusual and can lead +to unexpected behavior. + +When the user program writes the same value to wedged_mode twice in +a row, a lockup will occur, because the value expected to be +returned by the write() function inside the program should be equal +to the actual written value instead of 0. + +To reproduce the issue: +echo 1 > /sys/kernel/debug/dri/0/wedged_mode +echo 1 > /sys/kernel/debug/dri/0/wedged_mode <- lockup here + +Signed-off-by: Xin Wang +Cc: Rodrigo Vivi +Cc: Fei Yang +Cc: Shuicheng Lin +Reviewed-by: Rodrigo Vivi +Link: https://patchwork.freedesktop.org/patch/msgid/20250213223615.2327367-1-x.wang@intel.com +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_debugfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c +index fe4319eb13fdf..051a37e477f4c 100644 +--- a/drivers/gpu/drm/xe/xe_debugfs.c ++++ b/drivers/gpu/drm/xe/xe_debugfs.c +@@ -147,7 +147,7 @@ static ssize_t wedged_mode_set(struct file *f, const char __user *ubuf, + return -EINVAL; + + if (xe->wedged.mode == wedged_mode) +- return 0; ++ return size; + + xe->wedged.mode = wedged_mode; + +-- +2.39.5 + diff --git a/queue-6.12/drm-xe-do-not-attempt-to-bootstrap-vf-in-execlists-m.patch b/queue-6.12/drm-xe-do-not-attempt-to-bootstrap-vf-in-execlists-m.patch new file mode 100644 index 0000000000..15c5b49c68 --- /dev/null +++ b/queue-6.12/drm-xe-do-not-attempt-to-bootstrap-vf-in-execlists-m.patch @@ -0,0 +1,39 @@ +From 165f697b004adee0fb19c978e1aa51285033a814 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Dec 2024 09:31:11 +0100 +Subject: drm/xe: Do not attempt to bootstrap VF in execlists mode + +From: Maarten Lankhorst + +[ Upstream commit f3b59457808f61d88178b0afa67cbd017d7ce79e ] + +It was mentioned in a review that there is a possibility of choosing +to load the module with VF in execlists mode. + +Of course this doesn't work, just bomb out as hard as possible. + +Reviewed-by: Lucas De Marchi +Link: https://patchwork.freedesktop.org/patch/msgid/20241210083111.230484-12-dev@lankhorst.se +Signed-off-by: Maarten Lankhorst +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +index 7ddbfeaf494ac..29badbd829ab6 100644 +--- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c ++++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +@@ -235,6 +235,9 @@ int xe_gt_sriov_vf_bootstrap(struct xe_gt *gt) + { + int err; + ++ if (!xe_device_uc_enabled(gt_to_xe(gt))) ++ return -ENODEV; ++ + err = vf_reset_guc_state(gt); + if (unlikely(err)) + return err; +-- +2.39.5 + diff --git a/queue-6.12/drm-xe-fix-xe_tile_init_noalloc-error-propagation.patch b/queue-6.12/drm-xe-fix-xe_tile_init_noalloc-error-propagation.patch new file mode 100644 index 0000000000..1082f163c9 --- /dev/null +++ b/queue-6.12/drm-xe-fix-xe_tile_init_noalloc-error-propagation.patch @@ -0,0 +1,39 @@ +From fb59012fe3561c58691dbc7d176a79dbfa4c1151 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 11:29:00 -0800 +Subject: drm/xe: Fix xe_tile_init_noalloc() error propagation + +From: Lucas De Marchi + +[ Upstream commit 0bcf41171c64234e79eb3552d00f0aad8a47e8d3 ] + +Propagate the error to the caller so initialization properly stops if +sysfs creation fails. + +Reviewed-by: Francois Dugast +Reviewed-by: Himal Prasad Ghimiray +Link: https://patchwork.freedesktop.org/patch/msgid/20250213192909.996148-4-lucas.demarchi@intel.com +Signed-off-by: Lucas De Marchi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_tile.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_tile.c b/drivers/gpu/drm/xe/xe_tile.c +index dda5268507d8e..349beddf9b383 100644 +--- a/drivers/gpu/drm/xe/xe_tile.c ++++ b/drivers/gpu/drm/xe/xe_tile.c +@@ -173,9 +173,7 @@ int xe_tile_init_noalloc(struct xe_tile *tile) + + xe_wa_apply_tile_workarounds(tile); + +- err = xe_tile_sysfs_init(tile); +- +- return 0; ++ return xe_tile_sysfs_init(tile); + } + + void xe_tile_migrate_wait(struct xe_tile *tile) +-- +2.39.5 + diff --git a/queue-6.12/drm-xe-move-suballocator-init-to-after-display-init.patch b/queue-6.12/drm-xe-move-suballocator-init-to-after-display-init.patch new file mode 100644 index 0000000000..f7986655b1 --- /dev/null +++ b/queue-6.12/drm-xe-move-suballocator-init-to-after-display-init.patch @@ -0,0 +1,82 @@ +From acd17cb06774cbae2e84c2c9397c14dc62a621c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Dec 2024 09:31:03 +0100 +Subject: drm/xe: Move suballocator init to after display init + +From: Maarten Lankhorst + +[ Upstream commit 380b0cdaa76bc8f5c16db16eaf48751e792ff041 ] + +No allocations should be done before we have had a chance to preserve +the display fb. + +Reviewed-by: Rodrigo Vivi +Link: https://patchwork.freedesktop.org/patch/msgid/20241210083111.230484-4-dev@lankhorst.se +Signed-off-by: Maarten Lankhorst +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_device.c | 6 ++++++ + drivers/gpu/drm/xe/xe_tile.c | 12 ++++++++---- + drivers/gpu/drm/xe/xe_tile.h | 1 + + 3 files changed, 15 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c +index 5c37bed3c948f..23e02372a49db 100644 +--- a/drivers/gpu/drm/xe/xe_device.c ++++ b/drivers/gpu/drm/xe/xe_device.c +@@ -708,6 +708,12 @@ int xe_device_probe(struct xe_device *xe) + if (err) + goto err; + ++ for_each_tile(tile, xe, id) { ++ err = xe_tile_init(tile); ++ if (err) ++ goto err; ++ } ++ + for_each_gt(gt, xe, id) { + last_gt = id; + +diff --git a/drivers/gpu/drm/xe/xe_tile.c b/drivers/gpu/drm/xe/xe_tile.c +index 349beddf9b383..36c87d7c72fbc 100644 +--- a/drivers/gpu/drm/xe/xe_tile.c ++++ b/drivers/gpu/drm/xe/xe_tile.c +@@ -167,15 +167,19 @@ int xe_tile_init_noalloc(struct xe_tile *tile) + if (err) + return err; + +- tile->mem.kernel_bb_pool = xe_sa_bo_manager_init(tile, SZ_1M, 16); +- if (IS_ERR(tile->mem.kernel_bb_pool)) +- return PTR_ERR(tile->mem.kernel_bb_pool); +- + xe_wa_apply_tile_workarounds(tile); + + return xe_tile_sysfs_init(tile); + } + ++int xe_tile_init(struct xe_tile *tile) ++{ ++ tile->mem.kernel_bb_pool = xe_sa_bo_manager_init(tile, SZ_1M, 16); ++ if (IS_ERR(tile->mem.kernel_bb_pool)) ++ return PTR_ERR(tile->mem.kernel_bb_pool); ++ ++ return 0; ++} + void xe_tile_migrate_wait(struct xe_tile *tile) + { + xe_migrate_wait(tile->migrate); +diff --git a/drivers/gpu/drm/xe/xe_tile.h b/drivers/gpu/drm/xe/xe_tile.h +index 1c9e42ade6b05..eb939316d55b0 100644 +--- a/drivers/gpu/drm/xe/xe_tile.h ++++ b/drivers/gpu/drm/xe/xe_tile.h +@@ -12,6 +12,7 @@ struct xe_tile; + + int xe_tile_init_early(struct xe_tile *tile, struct xe_device *xe, u8 id); + int xe_tile_init_noalloc(struct xe_tile *tile); ++int xe_tile_init(struct xe_tile *tile); + + void xe_tile_migrate_wait(struct xe_tile *tile); + +-- +2.39.5 + diff --git a/queue-6.12/drm-xe-nuke-vm-s-mapping-upon-close.patch b/queue-6.12/drm-xe-nuke-vm-s-mapping-upon-close.patch new file mode 100644 index 0000000000..d3c18dd519 --- /dev/null +++ b/queue-6.12/drm-xe-nuke-vm-s-mapping-upon-close.patch @@ -0,0 +1,195 @@ +From 10a56087e0e9b09cab3bdb77c29571dc36d4547b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 17:26:36 -0800 +Subject: drm/xe: Nuke VM's mapping upon close +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Matthew Brost + +[ Upstream commit 074e40d9c2a84939fe28d7121d3469db50f34a3d ] + +Clear root PT entry and invalidate entire VM's address space when +closing the VM. Will prevent the GPU from accessing any of the VM's +memory after closing. + +v2: + - s/vma/vm in kernel doc (CI) + - Don't nuke migration VM as this occur at driver unload (CI) +v3: + - Rebase and pull into SVM series (Thomas) + - Wait for pending binds (Thomas) +v5: + - Remove xe_gt_tlb_invalidation_fence_fini in error case (Matt Auld) + - Drop local migration bool (Thomas) +v7: + - Add drm_dev_enter/exit protecting invalidation (CI, Matt Auld) + +Signed-off-by: Matthew Brost +Reviewed-by: Thomas Hellström +Link: https://patchwork.freedesktop.org/patch/msgid/20250306012657.3505757-12-matthew.brost@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c | 22 ++++++++++++++ + drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h | 2 ++ + drivers/gpu/drm/xe/xe_pt.c | 14 +++++++++ + drivers/gpu/drm/xe/xe_pt.h | 3 ++ + drivers/gpu/drm/xe/xe_vm.c | 32 +++++++++++++++++++++ + 5 files changed, 73 insertions(+) + +diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c +index 98a450271f5ce..3155825fa46ad 100644 +--- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c ++++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c +@@ -406,6 +406,28 @@ int xe_gt_tlb_invalidation_range(struct xe_gt *gt, + return send_tlb_invalidation(>->uc.guc, fence, action, len); + } + ++/** ++ * xe_gt_tlb_invalidation_vm - Issue a TLB invalidation on this GT for a VM ++ * @gt: graphics tile ++ * @vm: VM to invalidate ++ * ++ * Invalidate entire VM's address space ++ */ ++void xe_gt_tlb_invalidation_vm(struct xe_gt *gt, struct xe_vm *vm) ++{ ++ struct xe_gt_tlb_invalidation_fence fence; ++ u64 range = 1ull << vm->xe->info.va_bits; ++ int ret; ++ ++ xe_gt_tlb_invalidation_fence_init(gt, &fence, true); ++ ++ ret = xe_gt_tlb_invalidation_range(gt, &fence, 0, range, vm->usm.asid); ++ if (ret < 0) ++ return; ++ ++ xe_gt_tlb_invalidation_fence_wait(&fence); ++} ++ + /** + * xe_gt_tlb_invalidation_vma - Issue a TLB invalidation on this GT for a VMA + * @gt: graphics tile +diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h +index 672acfcdf0d70..abe9b03d543e6 100644 +--- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h ++++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h +@@ -12,6 +12,7 @@ + + struct xe_gt; + struct xe_guc; ++struct xe_vm; + struct xe_vma; + + int xe_gt_tlb_invalidation_init_early(struct xe_gt *gt); +@@ -21,6 +22,7 @@ int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt); + int xe_gt_tlb_invalidation_vma(struct xe_gt *gt, + struct xe_gt_tlb_invalidation_fence *fence, + struct xe_vma *vma); ++void xe_gt_tlb_invalidation_vm(struct xe_gt *gt, struct xe_vm *vm); + int xe_gt_tlb_invalidation_range(struct xe_gt *gt, + struct xe_gt_tlb_invalidation_fence *fence, + u64 start, u64 end, u32 asid); +diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c +index 230cf47fb9c5e..fb94ff55c7361 100644 +--- a/drivers/gpu/drm/xe/xe_pt.c ++++ b/drivers/gpu/drm/xe/xe_pt.c +@@ -217,6 +217,20 @@ void xe_pt_destroy(struct xe_pt *pt, u32 flags, struct llist_head *deferred) + xe_pt_free(pt); + } + ++/** ++ * xe_pt_clear() - Clear a page-table. ++ * @xe: xe device. ++ * @pt: The page-table. ++ * ++ * Clears page-table by setting to zero. ++ */ ++void xe_pt_clear(struct xe_device *xe, struct xe_pt *pt) ++{ ++ struct iosys_map *map = &pt->bo->vmap; ++ ++ xe_map_memset(xe, map, 0, 0, SZ_4K); ++} ++ + /** + * DOC: Pagetable building + * +diff --git a/drivers/gpu/drm/xe/xe_pt.h b/drivers/gpu/drm/xe/xe_pt.h +index 9ab386431cadd..8e43912ae8e94 100644 +--- a/drivers/gpu/drm/xe/xe_pt.h ++++ b/drivers/gpu/drm/xe/xe_pt.h +@@ -13,6 +13,7 @@ struct dma_fence; + struct xe_bo; + struct xe_device; + struct xe_exec_queue; ++struct xe_svm_range; + struct xe_sync_entry; + struct xe_tile; + struct xe_vm; +@@ -35,6 +36,8 @@ void xe_pt_populate_empty(struct xe_tile *tile, struct xe_vm *vm, + + void xe_pt_destroy(struct xe_pt *pt, u32 flags, struct llist_head *deferred); + ++void xe_pt_clear(struct xe_device *xe, struct xe_pt *pt); ++ + int xe_pt_update_ops_prepare(struct xe_tile *tile, struct xe_vma_ops *vops); + struct dma_fence *xe_pt_update_ops_run(struct xe_tile *tile, + struct xe_vma_ops *vops); +diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c +index 872de052d670f..de257a032225f 100644 +--- a/drivers/gpu/drm/xe/xe_vm.c ++++ b/drivers/gpu/drm/xe/xe_vm.c +@@ -8,6 +8,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -1581,9 +1582,40 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) + + static void xe_vm_close(struct xe_vm *vm) + { ++ struct xe_device *xe = vm->xe; ++ bool bound; ++ int idx; ++ ++ bound = drm_dev_enter(&xe->drm, &idx); ++ + down_write(&vm->lock); ++ + vm->size = 0; ++ ++ if (!((vm->flags & XE_VM_FLAG_MIGRATION))) { ++ struct xe_tile *tile; ++ struct xe_gt *gt; ++ u8 id; ++ ++ /* Wait for pending binds */ ++ dma_resv_wait_timeout(xe_vm_resv(vm), ++ DMA_RESV_USAGE_BOOKKEEP, ++ false, MAX_SCHEDULE_TIMEOUT); ++ ++ if (bound) { ++ for_each_tile(tile, xe, id) ++ if (vm->pt_root[id]) ++ xe_pt_clear(xe, vm->pt_root[id]); ++ ++ for_each_gt(gt, xe, id) ++ xe_gt_tlb_invalidation_vm(gt, vm); ++ } ++ } ++ + up_write(&vm->lock); ++ ++ if (bound) ++ drm_dev_exit(idx); + } + + void xe_vm_close_and_put(struct xe_vm *vm) +-- +2.39.5 + diff --git a/queue-6.12/drm-xe-oa-ensure-that-polled-read-returns-latest-dat.patch b/queue-6.12/drm-xe-oa-ensure-that-polled-read-returns-latest-dat.patch new file mode 100644 index 0000000000..fcb28ffa77 --- /dev/null +++ b/queue-6.12/drm-xe-oa-ensure-that-polled-read-returns-latest-dat.patch @@ -0,0 +1,37 @@ +From 00a740e47856d1144802612c0e54444f034601e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 17:02:55 -0800 +Subject: drm/xe/oa: Ensure that polled read returns latest data + +From: Umesh Nerlige Ramappa + +[ Upstream commit 98c9d27ab30aa9c6451d3a34e6e297171f273e51 ] + +In polled mode, user calls poll() for read data to be available before +performing a read(). In the duration between these 2 calls, there may be +new data available in the OA buffer. To ensure user reads all available +data, check for latest data in the OA buffer in polled read. + +Signed-off-by: Umesh Nerlige Ramappa +Reviewed-by: Ashutosh Dixit +Link: https://patchwork.freedesktop.org/patch/msgid/20250212010255.1423343-1-umesh.nerlige.ramappa@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_oa.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c +index 448766033690c..d306ed0a04434 100644 +--- a/drivers/gpu/drm/xe/xe_oa.c ++++ b/drivers/gpu/drm/xe/xe_oa.c +@@ -535,6 +535,7 @@ static ssize_t xe_oa_read(struct file *file, char __user *buf, + mutex_unlock(&stream->stream_lock); + } while (!offset && !ret); + } else { ++ xe_oa_buffer_check_unlocked(stream); + mutex_lock(&stream->stream_lock); + ret = __xe_oa_read(stream, buf, count, &offset); + mutex_unlock(&stream->stream_lock); +-- +2.39.5 + diff --git a/queue-6.12/drm-xe-pf-create-a-link-between-pf-and-vf-devices.patch b/queue-6.12/drm-xe-pf-create-a-link-between-pf-and-vf-devices.patch new file mode 100644 index 0000000000..39ec1ebfdd --- /dev/null +++ b/queue-6.12/drm-xe-pf-create-a-link-between-pf-and-vf-devices.patch @@ -0,0 +1,120 @@ +From 3867bffca01d5688d355a7fdbdc3abff028ec0f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 15:58:06 +0530 +Subject: drm/xe/pf: Create a link between PF and VF devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Satyanarayana K V P + +[ Upstream commit 8c0aff7d92e2be25717669eb65a81a89740a24f2 ] + +When both PF and VF devices are enabled on the host, they +resume simultaneously during system resume. + +However, the PF must finish provisioning the VF before any +VFs can successfully resume. + +Establish a parent-child device link between the PF and VF +devices to ensure the correct order of resumption. + +V4 -> V5: +- Added missing break in the error condition. +V3 -> V4: +- Made xe_pci_pf_get_vf_dev() as a static function and updated + input parameter types. +- Updated xe_sriov_warn() to xe_sriov_abort() when VF device + cannot be found. +V2 -> V3: +- Added function documentation for xe_pci_pf_get_vf_dev(). +- Added assertion if not called from PF. +V1 -> V2: +- Added a helper function to get VF pci_dev. +- Updated xe_sriov_notice() to xe_sriov_warn() if vf pci_dev + is not found. + +Signed-off-by: Satyanarayana K V P +Cc: Michał Wajdeczko +Cc: Michał Winiarski +Cc: Piotr Piórkowski +Reviewed-by: Piotr Piorkowski +Signed-off-by: Michal Wajdeczko +Link: https://patchwork.freedesktop.org/patch/msgid/20250224102807.11065-2-satyanarayana.k.v.p@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_pci_sriov.c | 51 +++++++++++++++++++++++++++++++ + 1 file changed, 51 insertions(+) + +diff --git a/drivers/gpu/drm/xe/xe_pci_sriov.c b/drivers/gpu/drm/xe/xe_pci_sriov.c +index aaceee748287e..09ee8a06fe2ed 100644 +--- a/drivers/gpu/drm/xe/xe_pci_sriov.c ++++ b/drivers/gpu/drm/xe/xe_pci_sriov.c +@@ -62,6 +62,55 @@ static void pf_reset_vfs(struct xe_device *xe, unsigned int num_vfs) + xe_gt_sriov_pf_control_trigger_flr(gt, n); + } + ++static struct pci_dev *xe_pci_pf_get_vf_dev(struct xe_device *xe, unsigned int vf_id) ++{ ++ struct pci_dev *pdev = to_pci_dev(xe->drm.dev); ++ ++ xe_assert(xe, IS_SRIOV_PF(xe)); ++ ++ /* caller must use pci_dev_put() */ ++ return pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus), ++ pdev->bus->number, ++ pci_iov_virtfn_devfn(pdev, vf_id)); ++} ++ ++static void pf_link_vfs(struct xe_device *xe, int num_vfs) ++{ ++ struct pci_dev *pdev_pf = to_pci_dev(xe->drm.dev); ++ struct device_link *link; ++ struct pci_dev *pdev_vf; ++ unsigned int n; ++ ++ /* ++ * When both PF and VF devices are enabled on the host, during system ++ * resume they are resuming in parallel. ++ * ++ * But PF has to complete the provision of VF first to allow any VFs to ++ * successfully resume. ++ * ++ * Create a parent-child device link between PF and VF devices that will ++ * enforce correct resume order. ++ */ ++ for (n = 1; n <= num_vfs; n++) { ++ pdev_vf = xe_pci_pf_get_vf_dev(xe, n - 1); ++ ++ /* unlikely, something weird is happening, abort */ ++ if (!pdev_vf) { ++ xe_sriov_err(xe, "Cannot find VF%u device, aborting link%s creation!\n", ++ n, str_plural(num_vfs)); ++ break; ++ } ++ ++ link = device_link_add(&pdev_vf->dev, &pdev_pf->dev, ++ DL_FLAG_AUTOREMOVE_CONSUMER); ++ /* unlikely and harmless, continue with other VFs */ ++ if (!link) ++ xe_sriov_notice(xe, "Failed linking VF%u\n", n); ++ ++ pci_dev_put(pdev_vf); ++ } ++} ++ + static int pf_enable_vfs(struct xe_device *xe, int num_vfs) + { + struct pci_dev *pdev = to_pci_dev(xe->drm.dev); +@@ -92,6 +141,8 @@ static int pf_enable_vfs(struct xe_device *xe, int num_vfs) + if (err < 0) + goto failed; + ++ pf_link_vfs(xe, num_vfs); ++ + xe_sriov_info(xe, "Enabled %u of %u VF%s\n", + num_vfs, total_vfs, str_plural(total_vfs)); + return num_vfs; +-- +2.39.5 + diff --git a/queue-6.12/drm-xe-pf-reset-guc-vf-config-when-unprovisioning-cr.patch b/queue-6.12/drm-xe-pf-reset-guc-vf-config-when-unprovisioning-cr.patch new file mode 100644 index 0000000000..8525908fc9 --- /dev/null +++ b/queue-6.12/drm-xe-pf-reset-guc-vf-config-when-unprovisioning-cr.patch @@ -0,0 +1,114 @@ +From 7f110a9fb626ffb2db99ea1be7decb372b4c172e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 20:59:47 +0100 +Subject: drm/xe/pf: Reset GuC VF config when unprovisioning critical resource +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Michal Wajdeczko + +[ Upstream commit 33f17e2cbd930a2a00eb007d9b241b6db010a880 ] + +GuC firmware counts received VF configuration KLVs and may start +validation of the complete VF config even if some resources where +unprovisioned in the meantime, leading to unexpected errors like: + + $ echo 1 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/contexts_quota + $ echo 0 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/contexts_quota + $ echo 1 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/doorbells_quota + $ echo 0 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/doorbells_quota + $ echo 1 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/ggtt_quota + tee: '/sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/ggtt_quota': Input/output error + +To mitigate this problem trigger explicit VF config reset after +unprovisioning any of the critical resources (GGTT, context or +doorbell IDs) that GuC is monitoring. + +Signed-off-by: Michal Wajdeczko +Reviewed-by: Michał Winiarski +Link: https://patchwork.freedesktop.org/patch/msgid/20250129195947.764-3-michal.wajdeczko@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 37 +++++++++++++++++++--- + 1 file changed, 33 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +index c9ed996b9cb0c..786f0dba41437 100644 +--- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c ++++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +@@ -323,6 +323,26 @@ static int pf_push_full_vf_config(struct xe_gt *gt, unsigned int vfid) + return err; + } + ++static int pf_push_vf_cfg(struct xe_gt *gt, unsigned int vfid, bool reset) ++{ ++ int err = 0; ++ ++ xe_gt_assert(gt, vfid); ++ lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); ++ ++ if (reset) ++ err = pf_send_vf_cfg_reset(gt, vfid); ++ if (!err) ++ err = pf_push_full_vf_config(gt, vfid); ++ ++ return err; ++} ++ ++static int pf_refresh_vf_cfg(struct xe_gt *gt, unsigned int vfid) ++{ ++ return pf_push_vf_cfg(gt, vfid, true); ++} ++ + static u64 pf_get_ggtt_alignment(struct xe_gt *gt) + { + struct xe_device *xe = gt_to_xe(gt); +@@ -419,6 +439,10 @@ static int pf_provision_vf_ggtt(struct xe_gt *gt, unsigned int vfid, u64 size) + return err; + + pf_release_vf_config_ggtt(gt, config); ++ ++ err = pf_refresh_vf_cfg(gt, vfid); ++ if (unlikely(err)) ++ return err; + } + xe_gt_assert(gt, !xe_ggtt_node_allocated(config->ggtt_region)); + +@@ -744,6 +768,10 @@ static int pf_provision_vf_ctxs(struct xe_gt *gt, unsigned int vfid, u32 num_ctx + return ret; + + pf_release_config_ctxs(gt, config); ++ ++ ret = pf_refresh_vf_cfg(gt, vfid); ++ if (unlikely(ret)) ++ return ret; + } + + if (!num_ctxs) +@@ -1041,6 +1069,10 @@ static int pf_provision_vf_dbs(struct xe_gt *gt, unsigned int vfid, u32 num_dbs) + return ret; + + pf_release_config_dbs(gt, config); ++ ++ ret = pf_refresh_vf_cfg(gt, vfid); ++ if (unlikely(ret)) ++ return ret; + } + + if (!num_dbs) +@@ -2003,10 +2035,7 @@ int xe_gt_sriov_pf_config_push(struct xe_gt *gt, unsigned int vfid, bool refresh + xe_gt_assert(gt, vfid); + + mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); +- if (refresh) +- err = pf_send_vf_cfg_reset(gt, vfid); +- if (!err) +- err = pf_push_full_vf_config(gt, vfid); ++ err = pf_push_vf_cfg(gt, vfid, refresh); + mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); + + if (unlikely(err)) { +-- +2.39.5 + diff --git a/queue-6.12/drm-xe-reject-bo-eviction-if-bo-is-bound-to-current-.patch b/queue-6.12/drm-xe-reject-bo-eviction-if-bo-is-bound-to-current-.patch new file mode 100644 index 0000000000..077e0ab21e --- /dev/null +++ b/queue-6.12/drm-xe-reject-bo-eviction-if-bo-is-bound-to-current-.patch @@ -0,0 +1,68 @@ +From 777504a7d8edce1c8426c06caff06fe874446ee6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jan 2025 16:01:37 -0500 +Subject: drm/xe: Reject BO eviction if BO is bound to current VM +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Oak Zeng + +[ Upstream commit 0af944f0e3082ff517958b1cea76fb9b8cb379dd ] + +This is a follow up fix for +https://patchwork.freedesktop.org/patch/msgid/20241203021929.1919730-1-oak.zeng@intel.com +The overall goal is to fail vm_bind when there is memory pressure. See more +details in the commit message of above patch. Abbove patch fixes the issue +when user pass in a vm_id parameter during gem_create. If user doesn't pass +in a vm_id during gem_create, above patch doesn't help. + +This patch further reject BO eviction (which could be triggered by bo validation) +if BO is bound to the current VM. vm_bind could fail due to the eviction failure. +The BO to VM reverse mapping structure is used to determine whether BO is bound +to VM. + +v2: +Move vm_bo definition from function scope to if(evict) clause (Thomas) +Further constraint the condition by adding ctx->resv (Thomas) +Add a short comment describe the change. + +Suggested-by: Thomas Hellström +Signed-off-by: Oak Zeng +Reviewed-by: Thomas Hellström +Signed-off-by: Thomas Hellström +Link: https://patchwork.freedesktop.org/patch/msgid/20250110210137.3181576-1-oak.zeng@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_bo.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c +index 35a8242a9f541..8acc4640f0a28 100644 +--- a/drivers/gpu/drm/xe/xe_bo.c ++++ b/drivers/gpu/drm/xe/xe_bo.c +@@ -702,6 +702,21 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict, + goto out; + } + ++ /* Reject BO eviction if BO is bound to current VM. */ ++ if (evict && ctx->resv) { ++ struct drm_gpuvm_bo *vm_bo; ++ ++ drm_gem_for_each_gpuvm_bo(vm_bo, &bo->ttm.base) { ++ struct xe_vm *vm = gpuvm_to_vm(vm_bo->vm); ++ ++ if (xe_vm_resv(vm) == ctx->resv && ++ xe_vm_in_preempt_fence_mode(vm)) { ++ ret = -EBUSY; ++ goto out; ++ } ++ } ++ } ++ + /* + * Failed multi-hop where the old_mem is still marked as + * TTM_PL_FLAG_TEMPORARY, should just be a dummy move. +-- +2.39.5 + diff --git a/queue-6.12/drm-xe-relay-don-t-use-gfp_kernel-for-new-transactio.patch b/queue-6.12/drm-xe-relay-don-t-use-gfp_kernel-for-new-transactio.patch new file mode 100644 index 0000000000..a1458dc6fb --- /dev/null +++ b/queue-6.12/drm-xe-relay-don-t-use-gfp_kernel-for-new-transactio.patch @@ -0,0 +1,62 @@ +From b438bed4acfc7cb612d891ce88c0c5ec4f824019 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 16:37:13 +0100 +Subject: drm/xe/relay: Don't use GFP_KERNEL for new transactions + +From: Michal Wajdeczko + +[ Upstream commit 78d5d1e20d1de9422f013338a0f2311448588ba7 ] + +VFs use a relay transaction during the resume/reset flow and use +of the GFP_KERNEL flag may conflict with the reclaim: + + -> #0 (fs_reclaim){+.+.}-{0:0}: + [ ] __lock_acquire+0x1874/0x2bc0 + [ ] lock_acquire+0xd2/0x310 + [ ] fs_reclaim_acquire+0xc5/0x100 + [ ] mempool_alloc_noprof+0x5c/0x1b0 + [ ] __relay_get_transaction+0xdc/0xa10 [xe] + [ ] relay_send_to+0x251/0xe50 [xe] + [ ] xe_guc_relay_send_to_pf+0x79/0x3a0 [xe] + [ ] xe_gt_sriov_vf_connect+0x90/0x4d0 [xe] + [ ] xe_uc_init_hw+0x157/0x3b0 [xe] + [ ] do_gt_restart+0x1ae/0x650 [xe] + [ ] xe_gt_resume+0xb6/0x120 [xe] + [ ] xe_pm_runtime_resume+0x15b/0x370 [xe] + [ ] xe_pci_runtime_resume+0x73/0x90 [xe] + [ ] pci_pm_runtime_resume+0xa0/0x100 + [ ] __rpm_callback+0x4d/0x170 + [ ] rpm_callback+0x64/0x70 + [ ] rpm_resume+0x594/0x790 + [ ] __pm_runtime_resume+0x4e/0x90 + [ ] xe_pm_runtime_get_ioctl+0x9c/0x160 [xe] + +Since we have a preallocated pool of relay transactions, which +should cover all our normal relay use cases, we may use the +GFP_NOWAIT flag when allocating new outgoing transactions. + +Signed-off-by: Michal Wajdeczko +Tested-by: Marcin Bernatowicz +Reviewed-by: Marcin Bernatowicz +Link: https://patchwork.freedesktop.org/patch/msgid/20250131153713.808-1-michal.wajdeczko@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_guc_relay.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xe/xe_guc_relay.c b/drivers/gpu/drm/xe/xe_guc_relay.c +index ade6162dc2598..0e5b43e1518ea 100644 +--- a/drivers/gpu/drm/xe/xe_guc_relay.c ++++ b/drivers/gpu/drm/xe/xe_guc_relay.c +@@ -224,7 +224,7 @@ __relay_get_transaction(struct xe_guc_relay *relay, bool incoming, u32 remote, u + * with CTB lock held which is marked as used in the reclaim path. + * Btw, that's one of the reason why we use mempool here! + */ +- txn = mempool_alloc(&relay->pool, incoming ? GFP_ATOMIC : GFP_KERNEL); ++ txn = mempool_alloc(&relay->pool, incoming ? GFP_ATOMIC : GFP_NOWAIT); + if (!txn) + return ERR_PTR(-ENOMEM); + +-- +2.39.5 + diff --git a/queue-6.12/drm-xe-retry-bo-allocation.patch b/queue-6.12/drm-xe-retry-bo-allocation.patch new file mode 100644 index 0000000000..d1c386bf85 --- /dev/null +++ b/queue-6.12/drm-xe-retry-bo-allocation.patch @@ -0,0 +1,61 @@ +From 430fef42b4cdb18231d51f97e842f05e9cb8c6cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 17:26:26 -0800 +Subject: drm/xe: Retry BO allocation + +From: Matthew Brost + +[ Upstream commit 1d724a2f1b2c3f0cba4975784a808482e0631adf ] + +TTM doesn't support fair eviction via WW locking, this mitigated in by +using retry loops in exec and preempt rebind worker. Extend this retry +loop to BO allocation. Once TTM supports fair eviction this patch can be +reverted. + +v4: + - Keep line break (Stuart) + +Signed-off-by: Matthew Brost +Reviewed-by: Gwan-gyeong Mun +Reviewed-by: Stuart Summers +Link: https://patchwork.freedesktop.org/patch/msgid/20250306012657.3505757-2-matthew.brost@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_bo.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c +index 84e327b569252..35a8242a9f541 100644 +--- a/drivers/gpu/drm/xe/xe_bo.c ++++ b/drivers/gpu/drm/xe/xe_bo.c +@@ -1975,6 +1975,7 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data, + struct xe_file *xef = to_xe_file(file); + struct drm_xe_gem_create *args = data; + struct xe_vm *vm = NULL; ++ ktime_t end = 0; + struct xe_bo *bo; + unsigned int bo_flags; + u32 handle; +@@ -2047,6 +2048,10 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data, + vm = xe_vm_lookup(xef, args->vm_id); + if (XE_IOCTL_DBG(xe, !vm)) + return -ENOENT; ++ } ++ ++retry: ++ if (vm) { + err = xe_vm_lock(vm, true); + if (err) + goto out_vm; +@@ -2060,6 +2065,8 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data, + + if (IS_ERR(bo)) { + err = PTR_ERR(bo); ++ if (xe_vm_validate_should_retry(NULL, err, &end)) ++ goto retry; + goto out_vm; + } + +-- +2.39.5 + diff --git a/queue-6.12/drm-xe-sa-always-call-drm_suballoc_manager_fini.patch b/queue-6.12/drm-xe-sa-always-call-drm_suballoc_manager_fini.patch new file mode 100644 index 0000000000..2225f34985 --- /dev/null +++ b/queue-6.12/drm-xe-sa-always-call-drm_suballoc_manager_fini.patch @@ -0,0 +1,51 @@ +From 57aaf1ddc383ba5ba1bdac8afe52efe3c8e4e770 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Dec 2024 20:41:54 +0100 +Subject: drm/xe/sa: Always call drm_suballoc_manager_fini() + +From: Michal Wajdeczko + +[ Upstream commit 9cd3f4efc870463f17f6c29114c61fb6bfcaa291 ] + +After successful call to drm_suballoc_manager_init() we should +make sure to call drm_suballoc_manager_fini() as it may include +some cleanup code even if we didn't start using it for real. + +As we can abort init() early due to kvzalloc() failure, we should +either explicitly call drm_suballoc_manager_fini() or, even better, +postpone drm_suballoc_manager_init() once we finish all other +preparation steps, so we can rely on fini() that will do cleanup. + +Signed-off-by: Michal Wajdeczko +Cc: Matthew Brost +Reviewed-by: Matthew Brost +Link: https://patchwork.freedesktop.org/patch/msgid/20241220194205.995-2-michal.wajdeczko@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_sa.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_sa.c b/drivers/gpu/drm/xe/xe_sa.c +index fe2cb2a96f788..1d42547590067 100644 +--- a/drivers/gpu/drm/xe/xe_sa.c ++++ b/drivers/gpu/drm/xe/xe_sa.c +@@ -57,8 +57,6 @@ struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 + } + sa_manager->bo = bo; + sa_manager->is_iomem = bo->vmap.is_iomem; +- +- drm_suballoc_manager_init(&sa_manager->base, managed_size, align); + sa_manager->gpu_addr = xe_bo_ggtt_addr(bo); + + if (bo->vmap.is_iomem) { +@@ -72,6 +70,7 @@ struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 + memset(sa_manager->cpu_ptr, 0, bo->ttm.base.size); + } + ++ drm_suballoc_manager_init(&sa_manager->base, managed_size, align); + ret = drmm_add_action_or_reset(&xe->drm, xe_sa_bo_manager_fini, + sa_manager); + if (ret) +-- +2.39.5 + diff --git a/queue-6.12/drm-xe-stop-ignoring-errors-from-xe_ttm_stolen_mgr_i.patch b/queue-6.12/drm-xe-stop-ignoring-errors-from-xe_ttm_stolen_mgr_i.patch new file mode 100644 index 0000000000..6c7669388f --- /dev/null +++ b/queue-6.12/drm-xe-stop-ignoring-errors-from-xe_ttm_stolen_mgr_i.patch @@ -0,0 +1,108 @@ +From 69413931fc792b46883e86fa9d3b9022cacbfddc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 11:29:01 -0800 +Subject: drm/xe: Stop ignoring errors from xe_ttm_stolen_mgr_init() + +From: Lucas De Marchi + +[ Upstream commit ff57025c358603555f1e0ae0d50282a460433594 ] + +Make sure to differentiate normal behavior, e.g. there's no stolen, from +allocation errors or failure to initialize lower layers. + +Reviewed-by: Francois Dugast +Reviewed-by: Himal Prasad Ghimiray +Link: https://patchwork.freedesktop.org/patch/msgid/20250213192909.996148-5-lucas.demarchi@intel.com +Signed-off-by: Lucas De Marchi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_device.c | 4 +++- + drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c | 17 +++++++++-------- + drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h | 2 +- + 3 files changed, 13 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c +index bb85208cf1a94..5c37bed3c948f 100644 +--- a/drivers/gpu/drm/xe/xe_device.c ++++ b/drivers/gpu/drm/xe/xe_device.c +@@ -694,7 +694,9 @@ int xe_device_probe(struct xe_device *xe) + } + + /* Allocate and map stolen after potential VRAM resize */ +- xe_ttm_stolen_mgr_init(xe); ++ err = xe_ttm_stolen_mgr_init(xe); ++ if (err) ++ return err; + + /* + * Now that GT is initialized (TTM in particular), +diff --git a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c +index f7113cf6109d5..ef84fa757b26f 100644 +--- a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c ++++ b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c +@@ -201,17 +201,16 @@ static u64 detect_stolen(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr) + #endif + } + +-void xe_ttm_stolen_mgr_init(struct xe_device *xe) ++int xe_ttm_stolen_mgr_init(struct xe_device *xe) + { +- struct xe_ttm_stolen_mgr *mgr = drmm_kzalloc(&xe->drm, sizeof(*mgr), GFP_KERNEL); + struct pci_dev *pdev = to_pci_dev(xe->drm.dev); ++ struct xe_ttm_stolen_mgr *mgr; + u64 stolen_size, io_size; + int err; + +- if (!mgr) { +- drm_dbg_kms(&xe->drm, "Stolen mgr init failed\n"); +- return; +- } ++ mgr = drmm_kzalloc(&xe->drm, sizeof(*mgr), GFP_KERNEL); ++ if (!mgr) ++ return -ENOMEM; + + if (IS_SRIOV_VF(xe)) + stolen_size = 0; +@@ -224,7 +223,7 @@ void xe_ttm_stolen_mgr_init(struct xe_device *xe) + + if (!stolen_size) { + drm_dbg_kms(&xe->drm, "No stolen memory support\n"); +- return; ++ return 0; + } + + /* +@@ -240,7 +239,7 @@ void xe_ttm_stolen_mgr_init(struct xe_device *xe) + io_size, PAGE_SIZE); + if (err) { + drm_dbg_kms(&xe->drm, "Stolen mgr init failed: %i\n", err); +- return; ++ return err; + } + + drm_dbg_kms(&xe->drm, "Initialized stolen memory support with %llu bytes\n", +@@ -248,6 +247,8 @@ void xe_ttm_stolen_mgr_init(struct xe_device *xe) + + if (io_size) + mgr->mapping = devm_ioremap_wc(&pdev->dev, mgr->io_base, io_size); ++ ++ return 0; + } + + u64 xe_ttm_stolen_io_offset(struct xe_bo *bo, u32 offset) +diff --git a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h +index 1777245ff8101..8e877d1e839bd 100644 +--- a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h ++++ b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h +@@ -12,7 +12,7 @@ struct ttm_resource; + struct xe_bo; + struct xe_device; + +-void xe_ttm_stolen_mgr_init(struct xe_device *xe); ++int xe_ttm_stolen_mgr_init(struct xe_device *xe); + int xe_ttm_stolen_io_mem_reserve(struct xe_device *xe, struct ttm_resource *mem); + bool xe_ttm_stolen_cpu_access_needs_ggtt(struct xe_device *xe); + u64 xe_ttm_stolen_io_offset(struct xe_bo *bo, u32 offset); +-- +2.39.5 + diff --git a/queue-6.12/drm-xe-vf-retry-sending-mmio-request-to-guc-on-timeo.patch b/queue-6.12/drm-xe-vf-retry-sending-mmio-request-to-guc-on-timeo.patch new file mode 100644 index 0000000000..f357e5f20a --- /dev/null +++ b/queue-6.12/drm-xe-vf-retry-sending-mmio-request-to-guc-on-timeo.patch @@ -0,0 +1,64 @@ +From 681cead80b289ad55402949c2d1d9b1495bd9df1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 15:58:07 +0530 +Subject: drm/xe/vf: Retry sending MMIO request to GUC on timeout error +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Satyanarayana K V P + +[ Upstream commit ba757a65d2a28d46a8ccf50538f4f05036983f1b ] + +Add support to allow retrying the sending of MMIO requests +from the VF to the GUC in the event of an error. During the +suspend/resume process, VFs begin resuming only after the PF has +resumed. Although the PF resumes, the GUC reset and provisioning +occur later in a separate worker process. + +When there are a large number of VFs, some may attempt to resume +before the PF has completed its provisioning. Therefore, if a +MMIO request from a VF fails during this period, we will retry +sending the request up to GUC_RESET_VF_STATE_RETRY_MAX times, +which is set to a maximum of 10 attempts. + +Signed-off-by: Satyanarayana K V P +Cc: Michał Wajdeczko +Cc: Michał Winiarski +Cc: Piotr Piórkowski +Reviewed-by: Piotr Piorkowski +Signed-off-by: Michal Wajdeczko +Link: https://patchwork.freedesktop.org/patch/msgid/20250224102807.11065-3-satyanarayana.k.v.p@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +index f982d6f9f218d..7ddbfeaf494ac 100644 +--- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c ++++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +@@ -46,12 +46,19 @@ static int guc_action_vf_reset(struct xe_guc *guc) + return ret > 0 ? -EPROTO : ret; + } + ++#define GUC_RESET_VF_STATE_RETRY_MAX 10 + static int vf_reset_guc_state(struct xe_gt *gt) + { ++ unsigned int retry = GUC_RESET_VF_STATE_RETRY_MAX; + struct xe_guc *guc = >->uc.guc; + int err; + +- err = guc_action_vf_reset(guc); ++ do { ++ err = guc_action_vf_reset(guc); ++ if (!err || err != -ETIMEDOUT) ++ break; ++ } while (--retry); ++ + if (unlikely(err)) + xe_gt_sriov_err(gt, "Failed to reset GuC state (%pe)\n", ERR_PTR(err)); + return err; +-- +2.39.5 + diff --git a/queue-6.12/drm-xe-xe_gen_wa_oob-replace-program_invocation_shor.patch b/queue-6.12/drm-xe-xe_gen_wa_oob-replace-program_invocation_shor.patch new file mode 100644 index 0000000000..11dfced26d --- /dev/null +++ b/queue-6.12/drm-xe-xe_gen_wa_oob-replace-program_invocation_shor.patch @@ -0,0 +1,58 @@ +From 2d319cfa1595f9ffe38e1cd5ffab65dbba5a190b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 07:23:13 +0100 +Subject: drm/xe: xe_gen_wa_oob: replace program_invocation_short_name + +From: Daniel Gomez + +[ Upstream commit 89eb42b5539f6ae6a0cabcb39e5b6fcc83c106a1 ] + +program_invocation_short_name may not be available in other systems. +Instead, replace it with the argv[0] to pass the executable name. + +Fixes build error when program_invocation_short_name is not available: + +drivers/gpu/drm/xe/xe_gen_wa_oob.c:34:3: error: use of +undeclared identifier 'program_invocation_short_name' 34 | +program_invocation_short_name); | ^ 1 error +generated. + +Suggested-by: Masahiro Yamada +Signed-off-by: Daniel Gomez +Reviewed-by: Lucas De Marchi +Link: https://patchwork.freedesktop.org/patch/msgid/20250224-macos-build-support-xe-v3-1-d2c9ed3a27cc@samsung.com +Signed-off-by: Lucas De Marchi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_gen_wa_oob.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_gen_wa_oob.c b/drivers/gpu/drm/xe/xe_gen_wa_oob.c +index 904cf47925aa1..ed9183599e31c 100644 +--- a/drivers/gpu/drm/xe/xe_gen_wa_oob.c ++++ b/drivers/gpu/drm/xe/xe_gen_wa_oob.c +@@ -28,10 +28,10 @@ + "\n" \ + "#endif\n" + +-static void print_usage(FILE *f) ++static void print_usage(FILE *f, const char *progname) + { + fprintf(f, "usage: %s \n", +- program_invocation_short_name); ++ progname); + } + + static void print_parse_error(const char *err_msg, const char *line, +@@ -144,7 +144,7 @@ int main(int argc, const char *argv[]) + + if (argc < 3) { + fprintf(stderr, "ERROR: wrong arguments\n"); +- print_usage(stderr); ++ print_usage(stderr, argv[0]); + return 1; + } + +-- +2.39.5 + diff --git a/queue-6.12/edac-ie31200-work-around-false-positive-build-warnin.patch b/queue-6.12/edac-ie31200-work-around-false-positive-build-warnin.patch new file mode 100644 index 0000000000..ccb4cb18d9 --- /dev/null +++ b/queue-6.12/edac-ie31200-work-around-false-positive-build-warnin.patch @@ -0,0 +1,105 @@ +From 5677d466ab4cfe1cb52fa66053eb9f11ac530827 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 07:50:26 +0100 +Subject: EDAC/ie31200: work around false positive build warning + +From: Arnd Bergmann + +[ Upstream commit c29dfd661fe2f8d1b48c7f00590929c04b25bf40 ] + +gcc-14 produces a bogus warning in some configurations: + +drivers/edac/ie31200_edac.c: In function 'ie31200_probe1.isra': +drivers/edac/ie31200_edac.c:412:26: error: 'dimm_info' is used uninitialized [-Werror=uninitialized] + 412 | struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL]; + | ^~~~~~~~~ +drivers/edac/ie31200_edac.c:412:26: note: 'dimm_info' declared here + 412 | struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL]; + | ^~~~~~~~~ + +I don't see any way the unintialized access could really happen here, +but I can see why the compiler gets confused by the two loops. + +Instead, rework the two nested loops to only read the addr_decode +registers and then keep only one instance of the dimm info structure. + +[Tony: Qiuxu pointed out that the "populate DIMM info" comment was left +behind in the refactor and suggested moving it. I deleted the comment +as unnecessry in front os a call to populate_dimm_info(). That seems +pretty self-describing.] + +Signed-off-by: Arnd Bergmann +Acked-by: Jason Baron +Signed-off-by: Tony Luck +Link: https://lore.kernel.org/all/20250122065031.1321015-1-arnd@kernel.org +Signed-off-by: Sasha Levin +--- + drivers/edac/ie31200_edac.c | 28 +++++++++++++--------------- + 1 file changed, 13 insertions(+), 15 deletions(-) + +diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c +index 56be8ef40f376..e3635fba63b49 100644 +--- a/drivers/edac/ie31200_edac.c ++++ b/drivers/edac/ie31200_edac.c +@@ -405,10 +405,9 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) + int i, j, ret; + struct mem_ctl_info *mci = NULL; + struct edac_mc_layer layers[2]; +- struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL]; + void __iomem *window; + struct ie31200_priv *priv; +- u32 addr_decode, mad_offset; ++ u32 addr_decode[IE31200_CHANNELS], mad_offset; + + /* + * Kaby Lake, Coffee Lake seem to work like Skylake. Please re-visit +@@ -466,19 +465,10 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) + mad_offset = IE31200_MAD_DIMM_0_OFFSET; + } + +- /* populate DIMM info */ + for (i = 0; i < IE31200_CHANNELS; i++) { +- addr_decode = readl(window + mad_offset + ++ addr_decode[i] = readl(window + mad_offset + + (i * 4)); +- edac_dbg(0, "addr_decode: 0x%x\n", addr_decode); +- for (j = 0; j < IE31200_DIMMS_PER_CHANNEL; j++) { +- populate_dimm_info(&dimm_info[i][j], addr_decode, j, +- skl); +- edac_dbg(0, "size: 0x%x, rank: %d, width: %d\n", +- dimm_info[i][j].size, +- dimm_info[i][j].dual_rank, +- dimm_info[i][j].x16_width); +- } ++ edac_dbg(0, "addr_decode: 0x%x\n", addr_decode[i]); + } + + /* +@@ -489,14 +479,22 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) + */ + for (i = 0; i < IE31200_DIMMS_PER_CHANNEL; i++) { + for (j = 0; j < IE31200_CHANNELS; j++) { ++ struct dimm_data dimm_info; + struct dimm_info *dimm; + unsigned long nr_pages; + +- nr_pages = IE31200_PAGES(dimm_info[j][i].size, skl); ++ populate_dimm_info(&dimm_info, addr_decode[j], i, ++ skl); ++ edac_dbg(0, "size: 0x%x, rank: %d, width: %d\n", ++ dimm_info.size, ++ dimm_info.dual_rank, ++ dimm_info.x16_width); ++ ++ nr_pages = IE31200_PAGES(dimm_info.size, skl); + if (nr_pages == 0) + continue; + +- if (dimm_info[j][i].dual_rank) { ++ if (dimm_info.dual_rank) { + nr_pages = nr_pages / 2; + dimm = edac_get_dimm(mci, (i * 2) + 1, j, 0); + dimm->nr_pages = nr_pages; +-- +2.39.5 + diff --git a/queue-6.12/eeprom-ee1004-check-chip-before-probing.patch b/queue-6.12/eeprom-ee1004-check-chip-before-probing.patch new file mode 100644 index 0000000000..553dd9a3f5 --- /dev/null +++ b/queue-6.12/eeprom-ee1004-check-chip-before-probing.patch @@ -0,0 +1,38 @@ +From e031aa5dd5350af76ecd6ef4ecd1abc4c8e6aa27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 16:09:59 -0600 +Subject: eeprom: ee1004: Check chip before probing + +From: Eddie James + +[ Upstream commit d9406677428e9234ea62bb2d2f5e996d1b777760 ] + +Like other eeprom drivers, check if the device is really there and +functional before probing. + +Signed-off-by: Eddie James +Link: https://lore.kernel.org/r/20250218220959.721698-1-eajames@linux.ibm.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/misc/eeprom/ee1004.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/misc/eeprom/ee1004.c b/drivers/misc/eeprom/ee1004.c +index 89224d4af4a20..e13f9fdd9d7b1 100644 +--- a/drivers/misc/eeprom/ee1004.c ++++ b/drivers/misc/eeprom/ee1004.c +@@ -304,6 +304,10 @@ static int ee1004_probe(struct i2c_client *client) + I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_READ_BYTE_DATA)) + return -EPFNOSUPPORT; + ++ err = i2c_smbus_read_byte(client); ++ if (err < 0) ++ return -ENODEV; ++ + mutex_lock(&ee1004_bus_lock); + + err = ee1004_init_bus_data(client); +-- +2.39.5 + diff --git a/queue-6.12/erofs-initialize-decompression-early.patch b/queue-6.12/erofs-initialize-decompression-early.patch new file mode 100644 index 0000000000..4c4a360187 --- /dev/null +++ b/queue-6.12/erofs-initialize-decompression-early.patch @@ -0,0 +1,176 @@ +From 91290d9af1cb9e8f671aee4d0be57c40826a5f40 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 13:48:40 +0800 +Subject: erofs: initialize decompression early + +From: Gao Xiang + +[ Upstream commit fe1e57d44d7f106df9048e815e4862cf63921220 ] + + - Rename erofs_init_managed_cache() to z_erofs_init_super(); + - Move the initialization of managed_pslots into z_erofs_init_super() too; + - Move z_erofs_init_super() and packed inode preparation upwards, before + the root inode initialization. + +Therefore, the root directory can also be compressible. + +Signed-off-by: Gao Xiang +Acked-by: Chao Yu +Link: https://lore.kernel.org/r/20250317054840.3483000-1-hsiangkao@linux.alibaba.com +Signed-off-by: Sasha Levin +--- + fs/erofs/internal.h | 4 ++-- + fs/erofs/super.c | 46 ++++++++++++++++++++++----------------------- + fs/erofs/zdata.c | 4 ++-- + 3 files changed, 26 insertions(+), 28 deletions(-) + +diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h +index edbabb3256c9a..2c11e8f3048e9 100644 +--- a/fs/erofs/internal.h ++++ b/fs/erofs/internal.h +@@ -453,6 +453,7 @@ int __init erofs_init_shrinker(void); + void erofs_exit_shrinker(void); + int __init z_erofs_init_subsystem(void); + void z_erofs_exit_subsystem(void); ++int z_erofs_init_super(struct super_block *sb); + unsigned long z_erofs_shrink_scan(struct erofs_sb_info *sbi, + unsigned long nr_shrink); + int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, +@@ -462,7 +463,6 @@ void z_erofs_put_gbuf(void *ptr); + int z_erofs_gbuf_growsize(unsigned int nrpages); + int __init z_erofs_gbuf_init(void); + void z_erofs_gbuf_exit(void); +-int erofs_init_managed_cache(struct super_block *sb); + int z_erofs_parse_cfgs(struct super_block *sb, struct erofs_super_block *dsb); + #else + static inline void erofs_shrinker_register(struct super_block *sb) {} +@@ -471,7 +471,7 @@ static inline int erofs_init_shrinker(void) { return 0; } + static inline void erofs_exit_shrinker(void) {} + static inline int z_erofs_init_subsystem(void) { return 0; } + static inline void z_erofs_exit_subsystem(void) {} +-static inline int erofs_init_managed_cache(struct super_block *sb) { return 0; } ++static inline int z_erofs_init_super(struct super_block *sb) { return 0; } + #endif /* !CONFIG_EROFS_FS_ZIP */ + + #ifdef CONFIG_EROFS_FS_BACKED_BY_FILE +diff --git a/fs/erofs/super.c b/fs/erofs/super.c +index 5b279977c9d5d..3421448fef0e3 100644 +--- a/fs/erofs/super.c ++++ b/fs/erofs/super.c +@@ -664,9 +664,16 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) + else + sb->s_flags &= ~SB_POSIXACL; + +-#ifdef CONFIG_EROFS_FS_ZIP +- xa_init(&sbi->managed_pslots); +-#endif ++ err = z_erofs_init_super(sb); ++ if (err) ++ return err; ++ ++ if (erofs_sb_has_fragments(sbi) && sbi->packed_nid) { ++ inode = erofs_iget(sb, sbi->packed_nid); ++ if (IS_ERR(inode)) ++ return PTR_ERR(inode); ++ sbi->packed_inode = inode; ++ } + + inode = erofs_iget(sb, sbi->root_nid); + if (IS_ERR(inode)) +@@ -678,24 +685,11 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) + iput(inode); + return -EINVAL; + } +- + sb->s_root = d_make_root(inode); + if (!sb->s_root) + return -ENOMEM; + + erofs_shrinker_register(sb); +- if (erofs_sb_has_fragments(sbi) && sbi->packed_nid) { +- sbi->packed_inode = erofs_iget(sb, sbi->packed_nid); +- if (IS_ERR(sbi->packed_inode)) { +- err = PTR_ERR(sbi->packed_inode); +- sbi->packed_inode = NULL; +- return err; +- } +- } +- err = erofs_init_managed_cache(sb); +- if (err) +- return err; +- + err = erofs_xattr_prefixes_init(sb); + if (err) + return err; +@@ -831,6 +825,16 @@ static int erofs_init_fs_context(struct fs_context *fc) + return 0; + } + ++static void erofs_drop_internal_inodes(struct erofs_sb_info *sbi) ++{ ++ iput(sbi->packed_inode); ++ sbi->packed_inode = NULL; ++#ifdef CONFIG_EROFS_FS_ZIP ++ iput(sbi->managed_cache); ++ sbi->managed_cache = NULL; ++#endif ++} ++ + static void erofs_kill_sb(struct super_block *sb) + { + struct erofs_sb_info *sbi = EROFS_SB(sb); +@@ -840,6 +844,7 @@ static void erofs_kill_sb(struct super_block *sb) + kill_anon_super(sb); + else + kill_block_super(sb); ++ erofs_drop_internal_inodes(sbi); + fs_put_dax(sbi->dif0.dax_dev, NULL); + erofs_fscache_unregister_fs(sb); + erofs_sb_free(sbi); +@@ -850,17 +855,10 @@ static void erofs_put_super(struct super_block *sb) + { + struct erofs_sb_info *const sbi = EROFS_SB(sb); + +- DBG_BUGON(!sbi); +- + erofs_unregister_sysfs(sb); + erofs_shrinker_unregister(sb); + erofs_xattr_prefixes_cleanup(sb); +-#ifdef CONFIG_EROFS_FS_ZIP +- iput(sbi->managed_cache); +- sbi->managed_cache = NULL; +-#endif +- iput(sbi->packed_inode); +- sbi->packed_inode = NULL; ++ erofs_drop_internal_inodes(sbi); + erofs_free_dev_context(sbi->devs); + sbi->devs = NULL; + erofs_fscache_unregister_fs(sb); +diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c +index e5e94afc5af88..74521d7dbee1d 100644 +--- a/fs/erofs/zdata.c ++++ b/fs/erofs/zdata.c +@@ -663,18 +663,18 @@ static const struct address_space_operations z_erofs_cache_aops = { + .invalidate_folio = z_erofs_cache_invalidate_folio, + }; + +-int erofs_init_managed_cache(struct super_block *sb) ++int z_erofs_init_super(struct super_block *sb) + { + struct inode *const inode = new_inode(sb); + + if (!inode) + return -ENOMEM; +- + set_nlink(inode, 1); + inode->i_size = OFFSET_MAX; + inode->i_mapping->a_ops = &z_erofs_cache_aops; + mapping_set_gfp_mask(inode->i_mapping, GFP_KERNEL); + EROFS_SB(sb)->managed_cache = inode; ++ xa_init(&EROFS_SB(sb)->managed_pslots); + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.12/eth-fbnic-set-iff_unicast_flt-to-avoid-enabling-prom.patch b/queue-6.12/eth-fbnic-set-iff_unicast_flt-to-avoid-enabling-prom.patch new file mode 100644 index 0000000000..005f66ac2b --- /dev/null +++ b/queue-6.12/eth-fbnic-set-iff_unicast_flt-to-avoid-enabling-prom.patch @@ -0,0 +1,73 @@ +From c61af6b822c62369fa867f46e3876d640374bf31 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 17:00:38 -0800 +Subject: eth: fbnic: set IFF_UNICAST_FLT to avoid enabling promiscuous mode + when adding unicast addrs + +From: Alexander Duyck + +[ Upstream commit 09717c28b76c30b1dc8c261c855ffb2406abab2e ] + +I realized when we were adding unicast addresses we were enabling +promiscuous mode. I did a bit of digging and realized we had overlooked +setting the driver private flag to indicate we supported unicast filtering. + +Example below shows the table with 00deadbeef01 as the main NIC address, +and 5 additional addresses in the 00deadbeefX0 format. + + # cat $dbgfs/mac_addr + Idx S TCAM Bitmap Addr/Mask + ---------------------------------- + 00 0 00000000,00000000 000000000000 + 000000000000 + 01 0 00000000,00000000 000000000000 + 000000000000 + 02 0 00000000,00000000 000000000000 + 000000000000 + ... + 24 0 00000000,00000000 000000000000 + 000000000000 + 25 1 00100000,00000000 00deadbeef50 + 000000000000 + 26 1 00100000,00000000 00deadbeef40 + 000000000000 + 27 1 00100000,00000000 00deadbeef30 + 000000000000 + 28 1 00100000,00000000 00deadbeef20 + 000000000000 + 29 1 00100000,00000000 00deadbeef10 + 000000000000 + 30 1 00100000,00000000 00deadbeef01 + 000000000000 + 31 0 00000000,00000000 000000000000 + 000000000000 + +Before rule 31 would be active. With this change it correctly sticks +to just the unicast filters. + +Signed-off-by: Alexander Duyck +Signed-off-by: Jakub Kicinski +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250204010038.1404268-2-kuba@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/meta/fbnic/fbnic_netdev.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c +index a400616a24d41..79e94632533c8 100644 +--- a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c ++++ b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c +@@ -544,6 +544,8 @@ struct net_device *fbnic_netdev_alloc(struct fbnic_dev *fbd) + fbnic_rss_key_fill(fbn->rss_key); + fbnic_rss_init_en_mask(fbn); + ++ netdev->priv_flags |= IFF_UNICAST_FLT; ++ + netdev->features |= + NETIF_F_RXHASH | + NETIF_F_SG | +-- +2.39.5 + diff --git a/queue-6.12/eth-mlx4-don-t-try-to-complete-xdp-frames-in-netpoll.patch b/queue-6.12/eth-mlx4-don-t-try-to-complete-xdp-frames-in-netpoll.patch new file mode 100644 index 0000000000..c9e6a73c81 --- /dev/null +++ b/queue-6.12/eth-mlx4-don-t-try-to-complete-xdp-frames-in-netpoll.patch @@ -0,0 +1,39 @@ +From 391a9ea87bb03951eb75a89ae178b2b682c77175 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 17:06:33 -0800 +Subject: eth: mlx4: don't try to complete XDP frames in netpoll + +From: Jakub Kicinski + +[ Upstream commit 8fdeafd66edaf420ea0063a1f13442fe3470fe70 ] + +mlx4 doesn't support ndo_xdp_xmit / XDP_REDIRECT and wasn't +using page pool until now, so it could run XDP completions +in netpoll (NAPI budget == 0) just fine. Page pool has calling +context requirements, make sure we don't try to call it from +what is potentially HW IRQ context. + +Reviewed-by: Tariq Toukan +Link: https://patch.msgid.link/20250213010635.1354034-3-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx4/en_tx.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c +index 1ddb11cb25f91..6e077d202827a 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c ++++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c +@@ -450,6 +450,8 @@ int mlx4_en_process_tx_cq(struct net_device *dev, + + if (unlikely(!priv->port_up)) + return 0; ++ if (unlikely(!napi_budget) && cq->type == TX_XDP) ++ return 0; + + netdev_txq_bql_complete_prefetchw(ring->tx_queue); + +-- +2.39.5 + diff --git a/queue-6.12/exfat-call-bh_read-in-get_block-only-when-necessary.patch b/queue-6.12/exfat-call-bh_read-in-get_block-only-when-necessary.patch new file mode 100644 index 0000000000..20ad14baeb --- /dev/null +++ b/queue-6.12/exfat-call-bh_read-in-get_block-only-when-necessary.patch @@ -0,0 +1,222 @@ +From aad2ce8dfaf5a7075448dcae7de6baeae6260a0d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Mar 2025 00:01:16 +0900 +Subject: exfat: call bh_read in get_block only when necessary + +From: Sungjong Seo + +[ Upstream commit c73e680d1f84059e1b1ea82a537f6ccc1c563eb4 ] + +With commit 11a347fb6cef ("exfat: change to get file size from DataLength"), +exfat_get_block() can now handle valid_size. However, most partial +unwritten blocks that could be mapped with other blocks are being +inefficiently processed separately as individual blocks. + +Except for partial unwritten blocks that require independent processing, +let's handle them simply as before. + +Signed-off-by: Sungjong Seo +Reviewed-by: Yuezhang Mo +Signed-off-by: Namjae Jeon +Signed-off-by: Sasha Levin +--- + fs/exfat/inode.c | 159 +++++++++++++++++++++++------------------------ + 1 file changed, 77 insertions(+), 82 deletions(-) + +diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c +index 3801516ac5071..cc4dcb7a32b57 100644 +--- a/fs/exfat/inode.c ++++ b/fs/exfat/inode.c +@@ -274,9 +274,11 @@ static int exfat_get_block(struct inode *inode, sector_t iblock, + sector_t last_block; + sector_t phys = 0; + sector_t valid_blks; ++ loff_t i_size; + + mutex_lock(&sbi->s_lock); +- last_block = EXFAT_B_TO_BLK_ROUND_UP(i_size_read(inode), sb); ++ i_size = i_size_read(inode); ++ last_block = EXFAT_B_TO_BLK_ROUND_UP(i_size, sb); + if (iblock >= last_block && !create) + goto done; + +@@ -305,102 +307,95 @@ static int exfat_get_block(struct inode *inode, sector_t iblock, + if (buffer_delay(bh_result)) + clear_buffer_delay(bh_result); + +- if (create) { ++ /* ++ * In most cases, we just need to set bh_result to mapped, unmapped ++ * or new status as follows: ++ * 1. i_size == valid_size ++ * 2. write case (create == 1) ++ * 3. direct_read (!bh_result->b_folio) ++ * -> the unwritten part will be zeroed in exfat_direct_IO() ++ * ++ * Otherwise, in the case of buffered read, it is necessary to take ++ * care the last nested block if valid_size is not equal to i_size. ++ */ ++ if (i_size == ei->valid_size || create || !bh_result->b_folio) + valid_blks = EXFAT_B_TO_BLK_ROUND_UP(ei->valid_size, sb); ++ else ++ valid_blks = EXFAT_B_TO_BLK(ei->valid_size, sb); + +- if (iblock + max_blocks < valid_blks) { +- /* The range has been written, map it */ +- goto done; +- } else if (iblock < valid_blks) { +- /* +- * The range has been partially written, +- * map the written part. +- */ +- max_blocks = valid_blks - iblock; +- goto done; +- } ++ /* The range has been fully written, map it */ ++ if (iblock + max_blocks < valid_blks) ++ goto done; + +- /* The area has not been written, map and mark as new. */ +- set_buffer_new(bh_result); ++ /* The range has been partially written, map the written part */ ++ if (iblock < valid_blks) { ++ max_blocks = valid_blks - iblock; ++ goto done; ++ } + ++ /* The area has not been written, map and mark as new for create case */ ++ if (create) { ++ set_buffer_new(bh_result); + ei->valid_size = EXFAT_BLK_TO_B(iblock + max_blocks, sb); + mark_inode_dirty(inode); +- } else { +- valid_blks = EXFAT_B_TO_BLK(ei->valid_size, sb); ++ goto done; ++ } + +- if (iblock + max_blocks < valid_blks) { +- /* The range has been written, map it */ +- goto done; +- } else if (iblock < valid_blks) { +- /* +- * The area has been partially written, +- * map the written part. +- */ +- max_blocks = valid_blks - iblock; ++ /* ++ * The area has just one block partially written. ++ * In that case, we should read and fill the unwritten part of ++ * a block with zero. ++ */ ++ if (bh_result->b_folio && iblock == valid_blks && ++ (ei->valid_size & (sb->s_blocksize - 1))) { ++ loff_t size, pos; ++ void *addr; ++ ++ max_blocks = 1; ++ ++ /* ++ * No buffer_head is allocated. ++ * (1) bmap: It's enough to set blocknr without I/O. ++ * (2) read: The unwritten part should be filled with zero. ++ * If a folio does not have any buffers, ++ * let's returns -EAGAIN to fallback to ++ * block_read_full_folio() for per-bh IO. ++ */ ++ if (!folio_buffers(bh_result->b_folio)) { ++ err = -EAGAIN; + goto done; +- } else if (iblock == valid_blks && +- (ei->valid_size & (sb->s_blocksize - 1))) { +- /* +- * The block has been partially written, +- * zero the unwritten part and map the block. +- */ +- loff_t size, pos; +- void *addr; +- +- max_blocks = 1; +- +- /* +- * For direct read, the unwritten part will be zeroed in +- * exfat_direct_IO() +- */ +- if (!bh_result->b_folio) +- goto done; +- +- /* +- * No buffer_head is allocated. +- * (1) bmap: It's enough to fill bh_result without I/O. +- * (2) read: The unwritten part should be filled with 0 +- * If a folio does not have any buffers, +- * let's returns -EAGAIN to fallback to +- * per-bh IO like block_read_full_folio(). +- */ +- if (!folio_buffers(bh_result->b_folio)) { +- err = -EAGAIN; +- goto done; +- } ++ } + +- pos = EXFAT_BLK_TO_B(iblock, sb); +- size = ei->valid_size - pos; +- addr = folio_address(bh_result->b_folio) + +- offset_in_folio(bh_result->b_folio, pos); ++ pos = EXFAT_BLK_TO_B(iblock, sb); ++ size = ei->valid_size - pos; ++ addr = folio_address(bh_result->b_folio) + ++ offset_in_folio(bh_result->b_folio, pos); + +- /* Check if bh->b_data points to proper addr in folio */ +- if (bh_result->b_data != addr) { +- exfat_fs_error_ratelimit(sb, ++ /* Check if bh->b_data points to proper addr in folio */ ++ if (bh_result->b_data != addr) { ++ exfat_fs_error_ratelimit(sb, + "b_data(%p) != folio_addr(%p)", + bh_result->b_data, addr); +- err = -EINVAL; +- goto done; +- } +- +- /* Read a block */ +- err = bh_read(bh_result, 0); +- if (err < 0) +- goto done; ++ err = -EINVAL; ++ goto done; ++ } + +- /* Zero unwritten part of a block */ +- memset(bh_result->b_data + size, 0, +- bh_result->b_size - size); ++ /* Read a block */ ++ err = bh_read(bh_result, 0); ++ if (err < 0) ++ goto done; + +- err = 0; +- } else { +- /* +- * The range has not been written, clear the mapped flag +- * to only zero the cache and do not read from disk. +- */ +- clear_buffer_mapped(bh_result); +- } ++ /* Zero unwritten part of a block */ ++ memset(bh_result->b_data + size, 0, bh_result->b_size - size); ++ err = 0; ++ goto done; + } ++ ++ /* ++ * The area has not been written, clear mapped for read/bmap cases. ++ * If so, it will be filled with zero without reading from disk. ++ */ ++ clear_buffer_mapped(bh_result); + done: + bh_result->b_size = EXFAT_BLK_TO_B(max_blocks, sb); + if (err < 0) +-- +2.39.5 + diff --git a/queue-6.12/exit-fix-the-usage-of-delay_group_leader-exit_code-i.patch b/queue-6.12/exit-fix-the-usage-of-delay_group_leader-exit_code-i.patch new file mode 100644 index 0000000000..d840b6ff36 --- /dev/null +++ b/queue-6.12/exit-fix-the-usage-of-delay_group_leader-exit_code-i.patch @@ -0,0 +1,52 @@ +From 9591f9ea1e2a52280934f3c69e9687a87b93e360 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 18:19:41 +0100 +Subject: exit: fix the usage of delay_group_leader->exit_code in + do_notify_parent() and pidfs_exit() + +From: Oleg Nesterov + +[ Upstream commit 9133607de37a4887c6f89ed937176a0a0c1ebb17 ] + +Consider a process with a group leader L and a sub-thread T. +L does sys_exit(1), then T does sys_exit_group(2). + +In this case wait_task_zombie(L) will notice SIGNAL_GROUP_EXIT and use +L->signal->group_exit_code, this is correct. + +But, before that, do_notify_parent(L) called by release_task(T) will use +L->exit_code != L->signal->group_exit_code, and this is not consistent. +We don't really care, I think that nobody relies on the info which comes +with SIGCHLD, if nothing else SIGCHLD < SIGRTMIN can be queued only once. + +But pidfs_exit() is more problematic, I think pidfs_exit_info->exit_code +should report ->group_exit_code in this case, just like wait_task_zombie(). + +TODO: with this change we can hopefully cleanup (or may be even kill) the +similar SIGNAL_GROUP_EXIT checks, at least in wait_task_zombie(). + +Signed-off-by: Oleg Nesterov +Link: https://lore.kernel.org/r/20250324171941.GA13114@redhat.com +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + kernel/exit.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/kernel/exit.c b/kernel/exit.c +index 619f0014c33be..9d888f26bf784 100644 +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -266,6 +266,9 @@ void release_task(struct task_struct *p) + leader = p->group_leader; + if (leader != p && thread_group_empty(leader) + && leader->exit_state == EXIT_ZOMBIE) { ++ /* for pidfs_exit() and do_notify_parent() */ ++ if (leader->signal->flags & SIGNAL_GROUP_EXIT) ++ leader->exit_code = leader->signal->group_exit_code; + /* + * If we were the last child thread and the leader has + * exited already, and the leader's parent ignores SIGCHLD, +-- +2.39.5 + diff --git a/queue-6.12/ext4-do-not-convert-the-unwritten-extents-if-data-wr.patch b/queue-6.12/ext4-do-not-convert-the-unwritten-extents-if-data-wr.patch new file mode 100644 index 0000000000..4d22d87876 --- /dev/null +++ b/queue-6.12/ext4-do-not-convert-the-unwritten-extents-if-data-wr.patch @@ -0,0 +1,90 @@ +From c232ea8a5725fa5baef85b1d628cc6514eeeb5a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 19:05:26 +0800 +Subject: ext4: do not convert the unwritten extents if data writeback fails + +From: Baokun Li + +[ Upstream commit e856f93e0fb249955f7d5efb18fe20500a9ccc6d ] + +When dioread_nolock is turned on (the default), it will convert unwritten +extents to written at ext4_end_io_end(), even if the data writeback fails. + +It leads to the possibility that stale data may be exposed when the +physical block corresponding to the file data is read-only (i.e., writes +return -EIO, but reads are normal). + +Therefore a new ext4_io_end->flags EXT4_IO_END_FAILED is added, which +indicates that some bio write-back failed in the current ext4_io_end. +When this flag is set, the unwritten to written conversion is no longer +performed. Users can read the data normally until the caches are dropped, +after that, the failed extents can only be read to all 0. + +Signed-off-by: Baokun Li +Reviewed-by: Jan Kara +Reviewed-by: Zhang Yi +Link: https://patch.msgid.link/20250122110533.4116662-3-libaokun@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/ext4.h | 3 ++- + fs/ext4/page-io.c | 16 ++++++++++++++-- + 2 files changed, 16 insertions(+), 3 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index bbffb76d9a904..75df7eeee50d8 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -278,7 +278,8 @@ struct ext4_system_blocks { + /* + * Flags for ext4_io_end->flags + */ +-#define EXT4_IO_END_UNWRITTEN 0x0001 ++#define EXT4_IO_END_UNWRITTEN 0x0001 ++#define EXT4_IO_END_FAILED 0x0002 + + struct ext4_io_end_vec { + struct list_head list; /* list of io_end_vec */ +diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c +index b7b9261fec3b5..cb023922c93c8 100644 +--- a/fs/ext4/page-io.c ++++ b/fs/ext4/page-io.c +@@ -181,14 +181,25 @@ static int ext4_end_io_end(ext4_io_end_t *io_end) + "list->prev 0x%p\n", + io_end, inode->i_ino, io_end->list.next, io_end->list.prev); + +- io_end->handle = NULL; /* Following call will use up the handle */ +- ret = ext4_convert_unwritten_io_end_vec(handle, io_end); ++ /* ++ * Do not convert the unwritten extents if data writeback fails, ++ * or stale data may be exposed. ++ */ ++ io_end->handle = NULL; /* Following call will use up the handle */ ++ if (unlikely(io_end->flag & EXT4_IO_END_FAILED)) { ++ ret = -EIO; ++ if (handle) ++ jbd2_journal_free_reserved(handle); ++ } else { ++ ret = ext4_convert_unwritten_io_end_vec(handle, io_end); ++ } + if (ret < 0 && !ext4_forced_shutdown(inode->i_sb)) { + ext4_msg(inode->i_sb, KERN_EMERG, + "failed to convert unwritten extents to written " + "extents -- potential data loss! " + "(inode %lu, error %d)", inode->i_ino, ret); + } ++ + ext4_clear_io_unwritten_flag(io_end); + ext4_release_io_end(io_end); + return ret; +@@ -344,6 +355,7 @@ static void ext4_end_bio(struct bio *bio) + bio->bi_status, inode->i_ino, + (unsigned long long) + bi_sector >> (inode->i_blkbits - 9)); ++ io_end->flag |= EXT4_IO_END_FAILED; + mapping_set_error(inode->i_mapping, + blk_status_to_errno(bio->bi_status)); + } +-- +2.39.5 + diff --git a/queue-6.12/ext4-don-t-write-back-data-before-punch-hole-in-nojo.patch b/queue-6.12/ext4-don-t-write-back-data-before-punch-hole-in-nojo.patch new file mode 100644 index 0000000000..80c6957061 --- /dev/null +++ b/queue-6.12/ext4-don-t-write-back-data-before-punch-hole-in-nojo.patch @@ -0,0 +1,71 @@ +From ef006c48e325e2d6d8bd1f8e55816c93414dc416 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Dec 2024 09:16:30 +0800 +Subject: ext4: don't write back data before punch hole in nojournal mode + +From: Zhang Yi + +[ Upstream commit 43d0105e2c7523cc6b14cad65e2044e829c0a07a ] + +There is no need to write back all data before punching a hole in +non-journaled mode since it will be dropped soon after removing space. +Therefore, the call to filemap_write_and_wait_range() can be eliminated. +Besides, similar to ext4_zero_range(), we must address the case of +partially punched folios when block size < page size. It is essential to +remove writable userspace mappings to ensure that the folio can be +faulted again during subsequent mmap write access. + +In journaled mode, we need to write dirty pages out before discarding +page cache in case of crash before committing the freeing data +transaction, which could expose old, stale data, even if synchronization +has been performed. + +Signed-off-by: Zhang Yi +Reviewed-by: Jan Kara +Reviewed-by: Ojaswin Mujoo +Link: https://patch.msgid.link/20241220011637.1157197-4-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/inode.c | 18 +++++------------- + 1 file changed, 5 insertions(+), 13 deletions(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 487d9aec56c9d..819be57bb4ecf 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3933,17 +3933,6 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length) + + trace_ext4_punch_hole(inode, offset, length, 0); + +- /* +- * Write out all dirty pages to avoid race conditions +- * Then release them. +- */ +- if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { +- ret = filemap_write_and_wait_range(mapping, offset, +- offset + length - 1); +- if (ret) +- return ret; +- } +- + inode_lock(inode); + + /* No need to punch hole beyond i_size */ +@@ -4005,8 +3994,11 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length) + ret = ext4_update_disksize_before_punch(inode, offset, length); + if (ret) + goto out_dio; +- truncate_pagecache_range(inode, first_block_offset, +- last_block_offset); ++ ++ ret = ext4_truncate_page_cache_block_range(inode, ++ first_block_offset, last_block_offset + 1); ++ if (ret) ++ goto out_dio; + } + + if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) +-- +2.39.5 + diff --git a/queue-6.12/ext4-on-a-remount-only-log-the-ro-or-r-w-state-when-.patch b/queue-6.12/ext4-on-a-remount-only-log-the-ro-or-r-w-state-when-.patch new file mode 100644 index 0000000000..3a58e02e8d --- /dev/null +++ b/queue-6.12/ext4-on-a-remount-only-log-the-ro-or-r-w-state-when-.patch @@ -0,0 +1,56 @@ +From 4d20b4edd11e4d0e2a3bbd96f8e21f1be3f9c1cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 11:10:11 -0600 +Subject: ext4: on a remount, only log the ro or r/w state when it has changed + +From: Nicolas Bretz + +[ Upstream commit d7b0befd09320e3356a75cb96541c030515e7f5f ] + +A user complained that a message such as: + +EXT4-fs (nvme0n1p3): re-mounted UUID ro. Quota mode: none. + +implied that the file system was previously mounted read/write and was +now remounted read-only, when it could have been some other mount +state that had changed by the "mount -o remount" operation. Fix this +by only logging "ro"or "r/w" when it has changed. + +https://bugzilla.kernel.org/show_bug.cgi?id=219132 + +Signed-off-by: Nicolas Bretz +Link: https://patch.msgid.link/20250319171011.8372-1-bretznic@gmail.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/super.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 4291ab3c20be6..473909c4a3784 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -6744,6 +6744,7 @@ static int ext4_reconfigure(struct fs_context *fc) + { + struct super_block *sb = fc->root->d_sb; + int ret; ++ bool old_ro = sb_rdonly(sb); + + fc->s_fs_info = EXT4_SB(sb); + +@@ -6755,9 +6756,9 @@ static int ext4_reconfigure(struct fs_context *fc) + if (ret < 0) + return ret; + +- ext4_msg(sb, KERN_INFO, "re-mounted %pU %s. Quota mode: %s.", +- &sb->s_uuid, sb_rdonly(sb) ? "ro" : "r/w", +- ext4_quota_mode(sb)); ++ ext4_msg(sb, KERN_INFO, "re-mounted %pU%s.", ++ &sb->s_uuid, ++ (old_ro != sb_rdonly(sb)) ? (sb_rdonly(sb) ? " ro" : " r/w") : ""); + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.12/ext4-reject-the-data_err-abort-option-in-nojournal-m.patch b/queue-6.12/ext4-reject-the-data_err-abort-option-in-nojournal-m.patch new file mode 100644 index 0000000000..85d2b5c837 --- /dev/null +++ b/queue-6.12/ext4-reject-the-data_err-abort-option-in-nojournal-m.patch @@ -0,0 +1,56 @@ +From 14c7c899263192c282693be8b855db07c55c6607 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 19:05:27 +0800 +Subject: ext4: reject the 'data_err=abort' option in nojournal mode + +From: Baokun Li + +[ Upstream commit 26343ca0df715097065b02a6cddb4a029d5b9327 ] + +data_err=abort aborts the journal on I/O errors. However, this option is +meaningless if journal is disabled, so it is rejected in nojournal mode +to reduce unnecessary checks. Also, this option is ignored upon remount. + +Signed-off-by: Baokun Li +Reviewed-by: Zhang Yi +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20250122110533.4116662-4-libaokun@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/super.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 473909c4a3784..99117d1e1bdd5 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -2787,6 +2787,13 @@ static int ext4_check_opt_consistency(struct fs_context *fc, + } + + if (is_remount) { ++ if (!sbi->s_journal && ++ ctx_test_mount_opt(ctx, EXT4_MOUNT_DATA_ERR_ABORT)) { ++ ext4_msg(NULL, KERN_WARNING, ++ "Remounting fs w/o journal so ignoring data_err option"); ++ ctx_clear_mount_opt(ctx, EXT4_MOUNT_DATA_ERR_ABORT); ++ } ++ + if (ctx_test_mount_opt(ctx, EXT4_MOUNT_DAX_ALWAYS) && + (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)) { + ext4_msg(NULL, KERN_ERR, "can't mount with " +@@ -5396,6 +5403,11 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) + "data=, fs mounted w/o journal"); + goto failed_mount3a; + } ++ if (test_opt(sb, DATA_ERR_ABORT)) { ++ ext4_msg(sb, KERN_ERR, ++ "can't mount with data_err=abort, fs mounted w/o journal"); ++ goto failed_mount3a; ++ } + sbi->s_def_mount_opt &= ~EXT4_MOUNT_JOURNAL_CHECKSUM; + clear_opt(sb, JOURNAL_CHECKSUM); + clear_opt(sb, DATA_FLAGS); +-- +2.39.5 + diff --git a/queue-6.12/ext4-remove-writable-userspace-mappings-before-trunc.patch b/queue-6.12/ext4-remove-writable-userspace-mappings-before-trunc.patch new file mode 100644 index 0000000000..f6c7f9d201 --- /dev/null +++ b/queue-6.12/ext4-remove-writable-userspace-mappings-before-trunc.patch @@ -0,0 +1,185 @@ +From 93d42835eccd4978b8138f758f57a3d23b13f394 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Dec 2024 09:16:28 +0800 +Subject: ext4: remove writable userspace mappings before truncating page cache + +From: Zhang Yi + +[ Upstream commit 17207d0bb209e8b40f27d7f3f96e82a78af0bf2c ] + +When zeroing a range of folios on the filesystem which block size is +less than the page size, the file's mapped blocks within one page will +be marked as unwritten, we should remove writable userspace mappings to +ensure that ext4_page_mkwrite() can be called during subsequent write +access to these partial folios. Otherwise, data written by subsequent +mmap writes may not be saved to disk. + + $mkfs.ext4 -b 1024 /dev/vdb + $mount /dev/vdb /mnt + $xfs_io -t -f -c "pwrite -S 0x58 0 4096" -c "mmap -rw 0 4096" \ + -c "mwrite -S 0x5a 2048 2048" -c "fzero 2048 2048" \ + -c "mwrite -S 0x59 2048 2048" -c "close" /mnt/foo + + $od -Ax -t x1z /mnt/foo + 000000 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 + * + 000800 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 + * + 001000 + + $umount /mnt && mount /dev/vdb /mnt + $od -Ax -t x1z /mnt/foo + 000000 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 + * + 000800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * + 001000 + +Fix this by introducing ext4_truncate_page_cache_block_range() to remove +writable userspace mappings when truncating a partial folio range. +Additionally, move the journal data mode-specific handlers and +truncate_pagecache_range() into this function, allowing it to serve as a +common helper that correctly manages the page cache in preparation for +block range manipulations. + +Signed-off-by: Zhang Yi +Reviewed-by: Jan Kara +Reviewed-by: Ojaswin Mujoo +Link: https://patch.msgid.link/20241220011637.1157197-2-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/ext4.h | 2 ++ + fs/ext4/extents.c | 19 ++++---------- + fs/ext4/inode.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 70 insertions(+), 14 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 75df7eeee50d8..c2e6989a568c2 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -3013,6 +3013,8 @@ extern int ext4_inode_attach_jinode(struct inode *inode); + extern int ext4_can_truncate(struct inode *inode); + extern int ext4_truncate(struct inode *); + extern int ext4_break_layouts(struct inode *); ++extern int ext4_truncate_page_cache_block_range(struct inode *inode, ++ loff_t start, loff_t end); + extern int ext4_punch_hole(struct file *file, loff_t offset, loff_t length); + extern void ext4_set_inode_flags(struct inode *, bool init); + extern int ext4_alloc_da_blocks(struct inode *inode); +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 60909af2d4a53..ba3419958a832 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4667,22 +4667,13 @@ static long ext4_zero_range(struct file *file, loff_t offset, + goto out_mutex; + } + +- /* +- * For journalled data we need to write (and checkpoint) pages +- * before discarding page cache to avoid inconsitent data on +- * disk in case of crash before zeroing trans is committed. +- */ +- if (ext4_should_journal_data(inode)) { +- ret = filemap_write_and_wait_range(mapping, start, +- end - 1); +- if (ret) { +- filemap_invalidate_unlock(mapping); +- goto out_mutex; +- } ++ /* Now release the pages and zero block aligned part of pages */ ++ ret = ext4_truncate_page_cache_block_range(inode, start, end); ++ if (ret) { ++ filemap_invalidate_unlock(mapping); ++ goto out_mutex; + } + +- /* Now release the pages and zero block aligned part of pages */ +- truncate_pagecache_range(inode, start, end - 1); + inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); + + ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 819be57bb4ecf..38fe9a213d09b 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -3879,6 +3880,68 @@ int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset, + return ret; + } + ++static inline void ext4_truncate_folio(struct inode *inode, ++ loff_t start, loff_t end) ++{ ++ unsigned long blocksize = i_blocksize(inode); ++ struct folio *folio; ++ ++ /* Nothing to be done if no complete block needs to be truncated. */ ++ if (round_up(start, blocksize) >= round_down(end, blocksize)) ++ return; ++ ++ folio = filemap_lock_folio(inode->i_mapping, start >> PAGE_SHIFT); ++ if (IS_ERR(folio)) ++ return; ++ ++ if (folio_mkclean(folio)) ++ folio_mark_dirty(folio); ++ folio_unlock(folio); ++ folio_put(folio); ++} ++ ++int ext4_truncate_page_cache_block_range(struct inode *inode, ++ loff_t start, loff_t end) ++{ ++ unsigned long blocksize = i_blocksize(inode); ++ int ret; ++ ++ /* ++ * For journalled data we need to write (and checkpoint) pages ++ * before discarding page cache to avoid inconsitent data on disk ++ * in case of crash before freeing or unwritten converting trans ++ * is committed. ++ */ ++ if (ext4_should_journal_data(inode)) { ++ ret = filemap_write_and_wait_range(inode->i_mapping, start, ++ end - 1); ++ if (ret) ++ return ret; ++ goto truncate_pagecache; ++ } ++ ++ /* ++ * If the block size is less than the page size, the file's mapped ++ * blocks within one page could be freed or converted to unwritten. ++ * So it's necessary to remove writable userspace mappings, and then ++ * ext4_page_mkwrite() can be called during subsequent write access ++ * to these partial folios. ++ */ ++ if (!IS_ALIGNED(start | end, PAGE_SIZE) && ++ blocksize < PAGE_SIZE && start < inode->i_size) { ++ loff_t page_boundary = round_up(start, PAGE_SIZE); ++ ++ ext4_truncate_folio(inode, start, min(page_boundary, end)); ++ if (end > page_boundary) ++ ext4_truncate_folio(inode, ++ round_down(end, PAGE_SIZE), end); ++ } ++ ++truncate_pagecache: ++ truncate_pagecache_range(inode, start, end - 1); ++ return 0; ++} ++ + static void ext4_wait_dax_page(struct inode *inode) + { + filemap_invalidate_unlock(inode->i_mapping); +-- +2.39.5 + diff --git a/queue-6.12/ext4-reorder-capability-check-last.patch b/queue-6.12/ext4-reorder-capability-check-last.patch new file mode 100644 index 0000000000..e06ff5c8fe --- /dev/null +++ b/queue-6.12/ext4-reorder-capability-check-last.patch @@ -0,0 +1,55 @@ +From 15c17152b7f486b575660779fed33906f56d097b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Mar 2025 17:06:39 +0100 +Subject: ext4: reorder capability check last +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Christian Göttsche + +[ Upstream commit 1b419c889c0767a5b66d0a6c566cae491f1cb0f7 ] + +capable() calls refer to enabled LSMs whether to permit or deny the +request. This is relevant in connection with SELinux, where a +capability check results in a policy decision and by default a denial +message on insufficient permission is issued. +It can lead to three undesired cases: + 1. A denial message is generated, even in case the operation was an + unprivileged one and thus the syscall succeeded, creating noise. + 2. To avoid the noise from 1. the policy writer adds a rule to ignore + those denial messages, hiding future syscalls, where the task + performs an actual privileged operation, leading to hidden limited + functionality of that task. + 3. To avoid the noise from 1. the policy writer adds a rule to permit + the task the requested capability, while it does not need it, + violating the principle of least privilege. + +Signed-off-by: Christian Göttsche +Reviewed-by: Serge Hallyn +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20250302160657.127253-2-cgoettsche@seltendoof.de +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/balloc.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c +index 8042ad8738089..c48fd36b2d74c 100644 +--- a/fs/ext4/balloc.c ++++ b/fs/ext4/balloc.c +@@ -649,8 +649,8 @@ static int ext4_has_free_clusters(struct ext4_sb_info *sbi, + /* Hm, nope. Are (enough) root reserved clusters available? */ + if (uid_eq(sbi->s_resuid, current_fsuid()) || + (!gid_eq(sbi->s_resgid, GLOBAL_ROOT_GID) && in_group_p(sbi->s_resgid)) || +- capable(CAP_SYS_RESOURCE) || +- (flags & EXT4_MB_USE_ROOT_BLOCKS)) { ++ (flags & EXT4_MB_USE_ROOT_BLOCKS) || ++ capable(CAP_SYS_RESOURCE)) { + + if (free_clusters >= (nclusters + dirty_clusters + + resv_clusters)) +-- +2.39.5 + diff --git a/queue-6.12/f2fs-defer-readonly-check-vs-norecovery.patch b/queue-6.12/f2fs-defer-readonly-check-vs-norecovery.patch new file mode 100644 index 0000000000..c4de5874ae --- /dev/null +++ b/queue-6.12/f2fs-defer-readonly-check-vs-norecovery.patch @@ -0,0 +1,56 @@ +From 0aee74b380502a70551552e1a423ea85d1b2bdfb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 11:12:17 -0600 +Subject: f2fs: defer readonly check vs norecovery + +From: Eric Sandeen + +[ Upstream commit 9cca49875997a1a7e92800a828a62bacb0f577b9 ] + +Defer the readonly-vs-norecovery check until after option parsing is done +so that option parsing does not require an active superblock for the test. +Add a helpful message, while we're at it. + +(I think could be moved back into parsing after we switch to the new mount +API if desired, as the fs context will have RO state available.) + +Signed-off-by: Eric Sandeen +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/super.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 573cc4725e2e8..280debf2df4f6 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -728,10 +728,8 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) + set_opt(sbi, DISABLE_ROLL_FORWARD); + break; + case Opt_norecovery: +- /* this option mounts f2fs with ro */ ++ /* requires ro mount, checked in f2fs_default_check */ + set_opt(sbi, NORECOVERY); +- if (!f2fs_readonly(sb)) +- return -EINVAL; + break; + case Opt_discard: + if (!f2fs_hw_support_discard(sbi)) { +@@ -1406,6 +1404,12 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) + f2fs_err(sbi, "Allow to mount readonly mode only"); + return -EROFS; + } ++ ++ if (test_opt(sbi, NORECOVERY) && !f2fs_readonly(sbi->sb)) { ++ f2fs_err(sbi, "norecovery requires readonly mount"); ++ return -EINVAL; ++ } ++ + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.12/f2fs-introduce-f2fs_base_attr-for-global-sysfs-entri.patch b/queue-6.12/f2fs-introduce-f2fs_base_attr-for-global-sysfs-entri.patch new file mode 100644 index 0000000000..4b0be5f618 --- /dev/null +++ b/queue-6.12/f2fs-introduce-f2fs_base_attr-for-global-sysfs-entri.patch @@ -0,0 +1,155 @@ +From ab71a104aa2ef9c1c70827e66076064a25f955d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 05:06:07 +0000 +Subject: f2fs: introduce f2fs_base_attr for global sysfs entries + +From: Jaegeuk Kim + +[ Upstream commit 21925ede449e038ed6f9efdfe0e79f15bddc34bc ] + +In /sys/fs/f2fs/features, there's no f2fs_sb_info, so let's avoid to get +the pointer. + +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/sysfs.c | 74 ++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 52 insertions(+), 22 deletions(-) + +diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c +index d9a44f03e558b..7df638f901a1f 100644 +--- a/fs/f2fs/sysfs.c ++++ b/fs/f2fs/sysfs.c +@@ -61,6 +61,12 @@ struct f2fs_attr { + int id; + }; + ++struct f2fs_base_attr { ++ struct attribute attr; ++ ssize_t (*show)(struct f2fs_base_attr *a, char *buf); ++ ssize_t (*store)(struct f2fs_base_attr *a, const char *buf, size_t len); ++}; ++ + static ssize_t f2fs_sbi_show(struct f2fs_attr *a, + struct f2fs_sb_info *sbi, char *buf); + +@@ -864,6 +870,25 @@ static void f2fs_sb_release(struct kobject *kobj) + complete(&sbi->s_kobj_unregister); + } + ++static ssize_t f2fs_base_attr_show(struct kobject *kobj, ++ struct attribute *attr, char *buf) ++{ ++ struct f2fs_base_attr *a = container_of(attr, ++ struct f2fs_base_attr, attr); ++ ++ return a->show ? a->show(a, buf) : 0; ++} ++ ++static ssize_t f2fs_base_attr_store(struct kobject *kobj, ++ struct attribute *attr, ++ const char *buf, size_t len) ++{ ++ struct f2fs_base_attr *a = container_of(attr, ++ struct f2fs_base_attr, attr); ++ ++ return a->store ? a->store(a, buf, len) : 0; ++} ++ + /* + * Note that there are three feature list entries: + * 1) /sys/fs/f2fs/features +@@ -882,14 +907,13 @@ static void f2fs_sb_release(struct kobject *kobj) + * please add new on-disk feature in this list only. + * - ref. F2FS_SB_FEATURE_RO_ATTR() + */ +-static ssize_t f2fs_feature_show(struct f2fs_attr *a, +- struct f2fs_sb_info *sbi, char *buf) ++static ssize_t f2fs_feature_show(struct f2fs_base_attr *a, char *buf) + { + return sysfs_emit(buf, "supported\n"); + } + + #define F2FS_FEATURE_RO_ATTR(_name) \ +-static struct f2fs_attr f2fs_attr_##_name = { \ ++static struct f2fs_base_attr f2fs_base_attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = 0444 }, \ + .show = f2fs_feature_show, \ + } +@@ -1258,37 +1282,38 @@ static struct attribute *f2fs_attrs[] = { + }; + ATTRIBUTE_GROUPS(f2fs); + ++#define BASE_ATTR_LIST(name) (&f2fs_base_attr_##name.attr) + static struct attribute *f2fs_feat_attrs[] = { + #ifdef CONFIG_FS_ENCRYPTION +- ATTR_LIST(encryption), +- ATTR_LIST(test_dummy_encryption_v2), ++ BASE_ATTR_LIST(encryption), ++ BASE_ATTR_LIST(test_dummy_encryption_v2), + #if IS_ENABLED(CONFIG_UNICODE) +- ATTR_LIST(encrypted_casefold), ++ BASE_ATTR_LIST(encrypted_casefold), + #endif + #endif /* CONFIG_FS_ENCRYPTION */ + #ifdef CONFIG_BLK_DEV_ZONED +- ATTR_LIST(block_zoned), ++ BASE_ATTR_LIST(block_zoned), + #endif +- ATTR_LIST(atomic_write), +- ATTR_LIST(extra_attr), +- ATTR_LIST(project_quota), +- ATTR_LIST(inode_checksum), +- ATTR_LIST(flexible_inline_xattr), +- ATTR_LIST(quota_ino), +- ATTR_LIST(inode_crtime), +- ATTR_LIST(lost_found), ++ BASE_ATTR_LIST(atomic_write), ++ BASE_ATTR_LIST(extra_attr), ++ BASE_ATTR_LIST(project_quota), ++ BASE_ATTR_LIST(inode_checksum), ++ BASE_ATTR_LIST(flexible_inline_xattr), ++ BASE_ATTR_LIST(quota_ino), ++ BASE_ATTR_LIST(inode_crtime), ++ BASE_ATTR_LIST(lost_found), + #ifdef CONFIG_FS_VERITY +- ATTR_LIST(verity), ++ BASE_ATTR_LIST(verity), + #endif +- ATTR_LIST(sb_checksum), ++ BASE_ATTR_LIST(sb_checksum), + #if IS_ENABLED(CONFIG_UNICODE) +- ATTR_LIST(casefold), ++ BASE_ATTR_LIST(casefold), + #endif +- ATTR_LIST(readonly), ++ BASE_ATTR_LIST(readonly), + #ifdef CONFIG_F2FS_FS_COMPRESSION +- ATTR_LIST(compression), ++ BASE_ATTR_LIST(compression), + #endif +- ATTR_LIST(pin_file), ++ BASE_ATTR_LIST(pin_file), + NULL, + }; + ATTRIBUTE_GROUPS(f2fs_feat); +@@ -1362,9 +1387,14 @@ static struct kset f2fs_kset = { + .kobj = {.ktype = &f2fs_ktype}, + }; + ++static const struct sysfs_ops f2fs_feat_attr_ops = { ++ .show = f2fs_base_attr_show, ++ .store = f2fs_base_attr_store, ++}; ++ + static const struct kobj_type f2fs_feat_ktype = { + .default_groups = f2fs_feat_groups, +- .sysfs_ops = &f2fs_attr_ops, ++ .sysfs_ops = &f2fs_feat_attr_ops, + }; + + static struct kobject f2fs_feat = { +-- +2.39.5 + diff --git a/queue-6.12/fbcon-use-correct-erase-colour-for-clearing-in-fbcon.patch b/queue-6.12/fbcon-use-correct-erase-colour-for-clearing-in-fbcon.patch new file mode 100644 index 0000000000..9a9b319246 --- /dev/null +++ b/queue-6.12/fbcon-use-correct-erase-colour-for-clearing-in-fbcon.patch @@ -0,0 +1,242 @@ +From 07ead22454beffa529280a887534e7e1f1041855 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Feb 2025 21:33:46 +0100 +Subject: fbcon: Use correct erase colour for clearing in fbcon + +From: Zsolt Kajtar + +[ Upstream commit 892c788d73fe4a94337ed092cb998c49fa8ecaf4 ] + +The erase colour calculation for fbcon clearing should use get_color instead +of attr_col_ec, like everything else. The latter is similar but is not correct. +For example it's missing the depth dependent remapping and doesn't care about +blanking. + +The problem can be reproduced by setting up the background colour to grey +(vt.color=0x70) and having an fbcon console set to 2bpp (4 shades of gray). +Now the background attribute should be 1 (dark gray) on the console. + +If the screen is scrolled when pressing enter in a shell prompt at the bottom +line then the new line is cleared using colour 7 instead of 1. That's not +something fillrect likes (at 2bbp it expect 0-3) so the result is interesting. + +This patch switches to get_color with vc_video_erase_char to determine the +erase colour from attr_col_ec. That makes the latter function redundant as +no other users were left. + +Use correct erase colour for clearing in fbcon + +Signed-off-by: Zsolt Kajtar +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + drivers/video/fbdev/core/bitblit.c | 5 ++-- + drivers/video/fbdev/core/fbcon.c | 10 +++++--- + drivers/video/fbdev/core/fbcon.h | 38 +--------------------------- + drivers/video/fbdev/core/fbcon_ccw.c | 5 ++-- + drivers/video/fbdev/core/fbcon_cw.c | 5 ++-- + drivers/video/fbdev/core/fbcon_ud.c | 5 ++-- + drivers/video/fbdev/core/tileblit.c | 8 +++--- + 7 files changed, 18 insertions(+), 58 deletions(-) + +diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c +index 3ff1b2a8659e8..f9475c14f7339 100644 +--- a/drivers/video/fbdev/core/bitblit.c ++++ b/drivers/video/fbdev/core/bitblit.c +@@ -59,12 +59,11 @@ static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy, + } + + static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy, +- int sx, int height, int width) ++ int sx, int height, int width, int fg, int bg) + { +- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + struct fb_fillrect region; + +- region.color = attr_bgcol_ec(bgshift, vc, info); ++ region.color = bg; + region.dx = sx * vc->vc_font.width; + region.dy = sy * vc->vc_font.height; + region.width = width * vc->vc_font.width; +diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c +index e8b4e8c119b5c..07d127110ca4c 100644 +--- a/drivers/video/fbdev/core/fbcon.c ++++ b/drivers/video/fbdev/core/fbcon.c +@@ -1258,7 +1258,7 @@ static void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, + { + struct fb_info *info = fbcon_info_from_console(vc->vc_num); + struct fbcon_ops *ops = info->fbcon_par; +- ++ int fg, bg; + struct fbcon_display *p = &fb_display[vc->vc_num]; + u_int y_break; + +@@ -1279,16 +1279,18 @@ static void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, + fbcon_clear_margins(vc, 0); + } + ++ fg = get_color(vc, info, vc->vc_video_erase_char, 1); ++ bg = get_color(vc, info, vc->vc_video_erase_char, 0); + /* Split blits that cross physical y_wrap boundary */ + + y_break = p->vrows - p->yscroll; + if (sy < y_break && sy + height - 1 >= y_break) { + u_int b = y_break - sy; +- ops->clear(vc, info, real_y(p, sy), sx, b, width); ++ ops->clear(vc, info, real_y(p, sy), sx, b, width, fg, bg); + ops->clear(vc, info, real_y(p, sy + b), sx, height - b, +- width); ++ width, fg, bg); + } else +- ops->clear(vc, info, real_y(p, sy), sx, height, width); ++ ops->clear(vc, info, real_y(p, sy), sx, height, width, fg, bg); + } + + static void fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, +diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h +index df70ea5ec5b37..4d97e6d8a16a2 100644 +--- a/drivers/video/fbdev/core/fbcon.h ++++ b/drivers/video/fbdev/core/fbcon.h +@@ -55,7 +55,7 @@ struct fbcon_ops { + void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy, + int sx, int dy, int dx, int height, int width); + void (*clear)(struct vc_data *vc, struct fb_info *info, int sy, +- int sx, int height, int width); ++ int sx, int height, int width, int fb, int bg); + void (*putcs)(struct vc_data *vc, struct fb_info *info, + const unsigned short *s, int count, int yy, int xx, + int fg, int bg); +@@ -116,42 +116,6 @@ static inline int mono_col(const struct fb_info *info) + return (~(0xfff << max_len)) & 0xff; + } + +-static inline int attr_col_ec(int shift, struct vc_data *vc, +- struct fb_info *info, int is_fg) +-{ +- int is_mono01; +- int col; +- int fg; +- int bg; +- +- if (!vc) +- return 0; +- +- if (vc->vc_can_do_color) +- return is_fg ? attr_fgcol(shift,vc->vc_video_erase_char) +- : attr_bgcol(shift,vc->vc_video_erase_char); +- +- if (!info) +- return 0; +- +- col = mono_col(info); +- is_mono01 = info->fix.visual == FB_VISUAL_MONO01; +- +- if (attr_reverse(vc->vc_video_erase_char)) { +- fg = is_mono01 ? col : 0; +- bg = is_mono01 ? 0 : col; +- } +- else { +- fg = is_mono01 ? 0 : col; +- bg = is_mono01 ? col : 0; +- } +- +- return is_fg ? fg : bg; +-} +- +-#define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0) +-#define attr_fgcol_ec(fgshift, vc, info) attr_col_ec(fgshift, vc, info, 1) +- + /* + * Scroll Method + */ +diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c +index f9b794ff7d396..89ef4ba7e8672 100644 +--- a/drivers/video/fbdev/core/fbcon_ccw.c ++++ b/drivers/video/fbdev/core/fbcon_ccw.c +@@ -78,14 +78,13 @@ static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, + } + + static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, +- int sx, int height, int width) ++ int sx, int height, int width, int fg, int bg) + { + struct fbcon_ops *ops = info->fbcon_par; + struct fb_fillrect region; +- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + u32 vyres = GETVYRES(ops->p, info); + +- region.color = attr_bgcol_ec(bgshift,vc,info); ++ region.color = bg; + region.dx = sy * vc->vc_font.height; + region.dy = vyres - ((sx + width) * vc->vc_font.width); + region.height = width * vc->vc_font.width; +diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c +index 903f6fc174e14..b9dac7940fb77 100644 +--- a/drivers/video/fbdev/core/fbcon_cw.c ++++ b/drivers/video/fbdev/core/fbcon_cw.c +@@ -63,14 +63,13 @@ static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, + } + + static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, +- int sx, int height, int width) ++ int sx, int height, int width, int fg, int bg) + { + struct fbcon_ops *ops = info->fbcon_par; + struct fb_fillrect region; +- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + u32 vxres = GETVXRES(ops->p, info); + +- region.color = attr_bgcol_ec(bgshift,vc,info); ++ region.color = bg; + region.dx = vxres - ((sy + height) * vc->vc_font.height); + region.dy = sx * vc->vc_font.width; + region.height = width * vc->vc_font.width; +diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c +index 594331936fd3c..0af7913a2abdc 100644 +--- a/drivers/video/fbdev/core/fbcon_ud.c ++++ b/drivers/video/fbdev/core/fbcon_ud.c +@@ -64,15 +64,14 @@ static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, + } + + static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, +- int sx, int height, int width) ++ int sx, int height, int width, int fg, int bg) + { + struct fbcon_ops *ops = info->fbcon_par; + struct fb_fillrect region; +- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + u32 vyres = GETVYRES(ops->p, info); + u32 vxres = GETVXRES(ops->p, info); + +- region.color = attr_bgcol_ec(bgshift,vc,info); ++ region.color = bg; + region.dy = vyres - ((sy + height) * vc->vc_font.height); + region.dx = vxres - ((sx + width) * vc->vc_font.width); + region.width = width * vc->vc_font.width; +diff --git a/drivers/video/fbdev/core/tileblit.c b/drivers/video/fbdev/core/tileblit.c +index eff7ec4da1671..45b0828fad1cf 100644 +--- a/drivers/video/fbdev/core/tileblit.c ++++ b/drivers/video/fbdev/core/tileblit.c +@@ -32,16 +32,14 @@ static void tile_bmove(struct vc_data *vc, struct fb_info *info, int sy, + } + + static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy, +- int sx, int height, int width) ++ int sx, int height, int width, int fg, int bg) + { + struct fb_tilerect rect; +- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; +- int fgshift = (vc->vc_hi_font_mask) ? 9 : 8; + + rect.index = vc->vc_video_erase_char & + ((vc->vc_hi_font_mask) ? 0x1ff : 0xff); +- rect.fg = attr_fgcol_ec(fgshift, vc, info); +- rect.bg = attr_bgcol_ec(bgshift, vc, info); ++ rect.fg = fg; ++ rect.bg = bg; + rect.sx = sx; + rect.sy = sy; + rect.width = width; +-- +2.39.5 + diff --git a/queue-6.12/fbdev-core-tileblit-implement-missing-margin-clearin.patch b/queue-6.12/fbdev-core-tileblit-implement-missing-margin-clearin.patch new file mode 100644 index 0000000000..65b941072e --- /dev/null +++ b/queue-6.12/fbdev-core-tileblit-implement-missing-margin-clearin.patch @@ -0,0 +1,95 @@ +From ecc387801b878053ebc8e8fb123b99c602ace104 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Feb 2025 09:18:09 +0100 +Subject: fbdev: core: tileblit: Implement missing margin clearing for tileblit + +From: Zsolt Kajtar + +[ Upstream commit 76d3ca89981354e1f85a3e0ad9ac4217d351cc72 ] + +I was wondering why there's garbage at the bottom of the screen when +tile blitting is used with an odd mode like 1080, 600 or 200. Sure there's +only space for half a tile but the same area is clean when the buffer +is bitmap. + +Then later I found that it's supposed to be cleaned but that's not +implemented. So I took what's in bitblit and adapted it for tileblit. + +This implementation was tested for both the horizontal and vertical case, +and now does the same as what's done for bitmap buffers. + +If anyone is interested to reproduce the problem then I could bet that'd +be on a S3 or Ark. Just set up a mode with an odd line count and make +sure that the virtual size covers the complete tile at the bottom. E.g. +for 600 lines that's 608 virtual lines for a 16 tall tile. Then the +bottom area should be cleaned. + +For the right side it's more difficult as there the drivers won't let an +odd size happen, unless the code is modified. But once it reports back a +few pixel columns short then fbcon won't use the last column. With the +patch that column is now clean. + +Btw. the virtual size should be rounded up by the driver for both axes +(not only the horizontal) so that it's dividable by the tile size. +That's a driver bug but correcting it is not in scope for this patch. + +Implement missing margin clearing for tileblit + +Signed-off-by: Zsolt Kajtar +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + drivers/video/fbdev/core/tileblit.c | 37 ++++++++++++++++++++++++++++- + 1 file changed, 36 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/fbdev/core/tileblit.c b/drivers/video/fbdev/core/tileblit.c +index 45b0828fad1cf..d342b90c42b7f 100644 +--- a/drivers/video/fbdev/core/tileblit.c ++++ b/drivers/video/fbdev/core/tileblit.c +@@ -74,7 +74,42 @@ static void tile_putcs(struct vc_data *vc, struct fb_info *info, + static void tile_clear_margins(struct vc_data *vc, struct fb_info *info, + int color, int bottom_only) + { +- return; ++ unsigned int cw = vc->vc_font.width; ++ unsigned int ch = vc->vc_font.height; ++ unsigned int rw = info->var.xres - (vc->vc_cols*cw); ++ unsigned int bh = info->var.yres - (vc->vc_rows*ch); ++ unsigned int rs = info->var.xres - rw; ++ unsigned int bs = info->var.yres - bh; ++ unsigned int vwt = info->var.xres_virtual / cw; ++ unsigned int vht = info->var.yres_virtual / ch; ++ struct fb_tilerect rect; ++ ++ rect.index = vc->vc_video_erase_char & ++ ((vc->vc_hi_font_mask) ? 0x1ff : 0xff); ++ rect.fg = color; ++ rect.bg = color; ++ ++ if ((int) rw > 0 && !bottom_only) { ++ rect.sx = (info->var.xoffset + rs + cw - 1) / cw; ++ rect.sy = 0; ++ rect.width = (rw + cw - 1) / cw; ++ rect.height = vht; ++ if (rect.width + rect.sx > vwt) ++ rect.width = vwt - rect.sx; ++ if (rect.sx < vwt) ++ info->tileops->fb_tilefill(info, &rect); ++ } ++ ++ if ((int) bh > 0) { ++ rect.sx = info->var.xoffset / cw; ++ rect.sy = (info->var.yoffset + bs) / ch; ++ rect.width = rs / cw; ++ rect.height = (bh + ch - 1) / ch; ++ if (rect.height + rect.sy > vht) ++ rect.height = vht - rect.sy; ++ if (rect.sy < vht) ++ info->tileops->fb_tilefill(info, &rect); ++ } + } + + static void tile_cursor(struct vc_data *vc, struct fb_info *info, bool enable, +-- +2.39.5 + diff --git a/queue-6.12/fbdev-fsl-diu-fb-add-missing-device_remove_file.patch b/queue-6.12/fbdev-fsl-diu-fb-add-missing-device_remove_file.patch new file mode 100644 index 0000000000..66d24e5ad3 --- /dev/null +++ b/queue-6.12/fbdev-fsl-diu-fb-add-missing-device_remove_file.patch @@ -0,0 +1,33 @@ +From 6749ee14d893b0592e1a841db3f1aed4c3e08578 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 09:54:31 +0800 +Subject: fbdev: fsl-diu-fb: add missing device_remove_file() + +From: Shixiong Ou + +[ Upstream commit 86d16cd12efa547ed43d16ba7a782c1251c80ea8 ] + +Call device_remove_file() when driver remove. + +Signed-off-by: Shixiong Ou +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + drivers/video/fbdev/fsl-diu-fb.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/video/fbdev/fsl-diu-fb.c b/drivers/video/fbdev/fsl-diu-fb.c +index 5ac8201c35337..b71d15794ce8b 100644 +--- a/drivers/video/fbdev/fsl-diu-fb.c ++++ b/drivers/video/fbdev/fsl-diu-fb.c +@@ -1827,6 +1827,7 @@ static void fsl_diu_remove(struct platform_device *pdev) + int i; + + data = dev_get_drvdata(&pdev->dev); ++ device_remove_file(&pdev->dev, &data->dev_attr); + disable_lcdc(&data->fsl_diu_info[0]); + + free_irq(data->irq, data->diu_reg); +-- +2.39.5 + diff --git a/queue-6.12/firmware-arm_ffa-handle-the-presence-of-host-partiti.patch b/queue-6.12/firmware-arm_ffa-handle-the-presence-of-host-partiti.patch new file mode 100644 index 0000000000..f1bfadd297 --- /dev/null +++ b/queue-6.12/firmware-arm_ffa-handle-the-presence-of-host-partiti.patch @@ -0,0 +1,46 @@ +From a11600ad993853581882e32c9dd1348884a77e8d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 15:38:48 +0000 +Subject: firmware: arm_ffa: Handle the presence of host partition in the + partition info + +From: Sudeep Holla + +[ Upstream commit 2f622a8b0722d332a2a149794a3add47bc9bdcf3 ] + +Currently it is assumed that the firmware doesn't present the host +partition in the list of partitions presented as part of the response +to PARTITION_INFO_GET from the firmware. However, there are few +platforms that prefer to present the same in the list of partitions. +It is not manadatory but not restricted as well. + +So handle the same by making sure to check the presence of the host +VM ID in the XArray partition information maintained/managed in the +driver before attempting to add it. + +Tested-by: Viresh Kumar +Message-Id: <20250217-ffa_updates-v3-7-bd1d9de615e7@arm.com> +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index 8dc8654f9f4b2..47751b2c057ae 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -1449,6 +1449,10 @@ static int ffa_setup_partitions(void) + + kfree(pbuf); + ++ /* Check if the host is already added as part of partition info */ ++ if (xa_load(&drv_info->partition_info, drv_info->vm_id)) ++ return 0; ++ + /* Allocate for the host */ + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) { +-- +2.39.5 + diff --git a/queue-6.12/firmware-arm_ffa-reject-higher-major-version-as-inco.patch b/queue-6.12/firmware-arm_ffa-reject-higher-major-version-as-inco.patch new file mode 100644 index 0000000000..9b6903ac4b --- /dev/null +++ b/queue-6.12/firmware-arm_ffa-reject-higher-major-version-as-inco.patch @@ -0,0 +1,50 @@ +From da31d1f852ce38d71086637e0c973e8c67ff1dfe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 15:38:53 +0000 +Subject: firmware: arm_ffa: Reject higher major version as incompatible + +From: Sudeep Holla + +[ Upstream commit efff6a7f16b34fd902f342b58bd8bafc2d6f2fd1 ] + +When the firmware compatibility was handled previously in the commit +8e3f9da608f1 ("firmware: arm_ffa: Handle compatibility with different firmware versions"), +we only addressed firmware versions that have higher minor versions +compared to the driver version which is should be considered compatible +unless the firmware returns NOT_SUPPORTED. + +However, if the firmware reports higher major version than the driver +supported, we need to reject it. If the firmware can work in a compatible +mode with the driver requested version, it must return the same major +version as requested. + +Tested-by: Viresh Kumar +Message-Id: <20250217-ffa_updates-v3-12-bd1d9de615e7@arm.com> +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index dce448687e28e..8dc8654f9f4b2 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -150,6 +150,14 @@ static int ffa_version_check(u32 *version) + return -EOPNOTSUPP; + } + ++ if (FFA_MAJOR_VERSION(ver.a0) > FFA_MAJOR_VERSION(FFA_DRIVER_VERSION)) { ++ pr_err("Incompatible v%d.%d! Latest supported v%d.%d\n", ++ FFA_MAJOR_VERSION(ver.a0), FFA_MINOR_VERSION(ver.a0), ++ FFA_MAJOR_VERSION(FFA_DRIVER_VERSION), ++ FFA_MINOR_VERSION(FFA_DRIVER_VERSION)); ++ return -EINVAL; ++ } ++ + if (ver.a0 < FFA_MIN_VERSION) { + pr_err("Incompatible v%d.%d! Earliest supported v%d.%d\n", + FFA_MAJOR_VERSION(ver.a0), FFA_MINOR_VERSION(ver.a0), +-- +2.39.5 + diff --git a/queue-6.12/firmware-arm_ffa-set-dma_mask-for-ffa-devices.patch b/queue-6.12/firmware-arm_ffa-set-dma_mask-for-ffa-devices.patch new file mode 100644 index 0000000000..2621deef22 --- /dev/null +++ b/queue-6.12/firmware-arm_ffa-set-dma_mask-for-ffa-devices.patch @@ -0,0 +1,37 @@ +From b536915bdab48de69b3258b4540c70821c9090ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jan 2025 15:35:52 +0530 +Subject: firmware: arm_ffa: Set dma_mask for ffa devices + +From: Viresh Kumar + +[ Upstream commit cc0aac7ca17e0ea3ca84b552fc79f3e86fd07f53 ] + +Set dma_mask for FFA devices, otherwise DMA allocation using the device pointer +lead to following warning: + +WARNING: CPU: 1 PID: 1 at kernel/dma/mapping.c:597 dma_alloc_attrs+0xe0/0x124 + +Signed-off-by: Viresh Kumar +Message-Id: +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/bus.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c +index dfda5ffc14db7..dea3eb741d95d 100644 +--- a/drivers/firmware/arm_ffa/bus.c ++++ b/drivers/firmware/arm_ffa/bus.c +@@ -212,6 +212,7 @@ ffa_device_register(const struct ffa_partition_info *part_info, + dev = &ffa_dev->dev; + dev->bus = &ffa_bus_type; + dev->release = ffa_release_device; ++ dev->dma_mask = &dev->coherent_dma_mask; + dev_set_name(&ffa_dev->dev, "arm-ffa-%d", id); + + ffa_dev->id = id; +-- +2.39.5 + diff --git a/queue-6.12/firmware-arm_scmi-relax-duplicate-name-constraint-ac.patch b/queue-6.12/firmware-arm_scmi-relax-duplicate-name-constraint-ac.patch new file mode 100644 index 0000000000..a5203ea7bc --- /dev/null +++ b/queue-6.12/firmware-arm_scmi-relax-duplicate-name-constraint-ac.patch @@ -0,0 +1,76 @@ +From b9939b7dc777b1f332dfeeacfa1c9db255313d0d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 14:18:20 +0000 +Subject: firmware: arm_scmi: Relax duplicate name constraint across protocol + ids + +From: Sudeep Holla + +[ Upstream commit 21ee965267bcbdd733be0f35344fa0f0226d7861 ] + +Currently in scmi_protocol_device_request(), no duplicate scmi device +name is allowed across any protocol. However scmi_dev_match_id() first +matches the protocol id and then the name. So, there is no strict +requirement to keep this scmi device name unique across all the protocols. + +Relax the constraint on the duplicate name across the protocols and +inhibit only within the same protocol id. + +Message-Id: <20250131141822.514342-1-sudeep.holla@arm.com> +Reviewed-by: Dhruva Gole +Reviewed-by: Peng Fan +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_scmi/bus.c | 19 ++++++------------- + 1 file changed, 6 insertions(+), 13 deletions(-) + +diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c +index 782c9bec8361c..73a6ab4a224d7 100644 +--- a/drivers/firmware/arm_scmi/bus.c ++++ b/drivers/firmware/arm_scmi/bus.c +@@ -42,7 +42,7 @@ static atomic_t scmi_syspower_registered = ATOMIC_INIT(0); + * This helper let an SCMI driver request specific devices identified by the + * @id_table to be created for each active SCMI instance. + * +- * The requested device name MUST NOT be already existent for any protocol; ++ * The requested device name MUST NOT be already existent for this protocol; + * at first the freshly requested @id_table is annotated in the IDR table + * @scmi_requested_devices and then the requested device is advertised to any + * registered party via the @scmi_requested_devices_nh notification chain. +@@ -52,7 +52,6 @@ static atomic_t scmi_syspower_registered = ATOMIC_INIT(0); + static int scmi_protocol_device_request(const struct scmi_device_id *id_table) + { + int ret = 0; +- unsigned int id = 0; + struct list_head *head, *phead = NULL; + struct scmi_requested_dev *rdev; + +@@ -67,19 +66,13 @@ static int scmi_protocol_device_request(const struct scmi_device_id *id_table) + } + + /* +- * Search for the matching protocol rdev list and then search +- * of any existent equally named device...fails if any duplicate found. ++ * Find the matching protocol rdev list and then search of any ++ * existent equally named device...fails if any duplicate found. + */ + mutex_lock(&scmi_requested_devices_mtx); +- idr_for_each_entry(&scmi_requested_devices, head, id) { +- if (!phead) { +- /* A list found registered in the IDR is never empty */ +- rdev = list_first_entry(head, struct scmi_requested_dev, +- node); +- if (rdev->id_table->protocol_id == +- id_table->protocol_id) +- phead = head; +- } ++ phead = idr_find(&scmi_requested_devices, id_table->protocol_id); ++ if (phead) { ++ head = phead; + list_for_each_entry(rdev, head, node) { + if (!strcmp(rdev->id_table->name, id_table->name)) { + pr_err("Ignoring duplicate request [%d] %s\n", +-- +2.39.5 + diff --git a/queue-6.12/firmware-xilinx-dont-send-linux-address-to-get-fpga-.patch b/queue-6.12/firmware-xilinx-dont-send-linux-address-to-get-fpga-.patch new file mode 100644 index 0000000000..53ae2f6da1 --- /dev/null +++ b/queue-6.12/firmware-xilinx-dont-send-linux-address-to-get-fpga-.patch @@ -0,0 +1,52 @@ +From 71f0c94fdb48e169ef3edf9bbf7db548eb57fb46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 11:19:51 +0530 +Subject: firmware: xilinx: Dont send linux address to get fpga config get + status + +From: Siva Durga Prasad Paladugu + +[ Upstream commit 5abc174016052caff1bcf4cedb159bd388411e98 ] + +Fpga get config status just returns status through ret_payload and there +is no need to allocate local buf and send its address through SMC args. +Moreover, the address that is being passed till now is linux virtual +address and is incorrect. +Corresponding modification has been done in the firmware to avoid using the +address sent by linux. + +Signed-off-by: Siva Durga Prasad Paladugu +Signed-off-by: Nava kishore Manne +Link: https://lore.kernel.org/r/20250207054951.1650534-1-nava.kishore.manne@amd.com +Signed-off-by: Michal Simek +Signed-off-by: Sasha Levin +--- + drivers/firmware/xilinx/zynqmp.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c +index add8acf66a9c7..5578158f13750 100644 +--- a/drivers/firmware/xilinx/zynqmp.c ++++ b/drivers/firmware/xilinx/zynqmp.c +@@ -1012,17 +1012,13 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status); + int zynqmp_pm_fpga_get_config_status(u32 *value) + { + u32 ret_payload[PAYLOAD_ARG_CNT]; +- u32 buf, lower_addr, upper_addr; + int ret; + + if (!value) + return -EINVAL; + +- lower_addr = lower_32_bits((u64)&buf); +- upper_addr = upper_32_bits((u64)&buf); +- + ret = zynqmp_pm_invoke_fn(PM_FPGA_READ, ret_payload, 4, +- XILINX_ZYNQMP_PM_FPGA_CONFIG_STAT_OFFSET, lower_addr, upper_addr, ++ XILINX_ZYNQMP_PM_FPGA_CONFIG_STAT_OFFSET, 0, 0, + XILINX_ZYNQMP_PM_FPGA_READ_CONFIG_REG); + + *value = ret_payload[1]; +-- +2.39.5 + diff --git a/queue-6.12/fpga-altera-cvp-increase-credit-timeout.patch b/queue-6.12/fpga-altera-cvp-increase-credit-timeout.patch new file mode 100644 index 0000000000..ce944a806b --- /dev/null +++ b/queue-6.12/fpga-altera-cvp-increase-credit-timeout.patch @@ -0,0 +1,43 @@ +From 409ab908b8af98312cd98c923eefa1c947a65209 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 06:12:49 +0800 +Subject: fpga: altera-cvp: Increase credit timeout + +From: Kuhanh Murugasen Krishnan + +[ Upstream commit 0f05886a40fdc55016ba4d9ae0a9c41f8312f15b ] + +Increase the timeout for SDM (Secure device manager) data credits from +20ms to 40ms. Internal stress tests running at 500 loops failed with the +current timeout of 20ms. At the start of a FPGA configuration, the CVP +host driver reads the transmit credits from SDM. It then sends bitstream +FPGA data to SDM based on the total credits. Each credit allows the +CVP host driver to send 4kBytes of data. There are situations whereby, +the SDM did not respond in time during testing. + +Signed-off-by: Ang Tien Sung +Signed-off-by: Kuhanh Murugasen Krishnan +Acked-by: Xu Yilun +Link: https://lore.kernel.org/r/20250212221249.2715929-1-tien.sung.ang@intel.com +Signed-off-by: Xu Yilun +Signed-off-by: Sasha Levin +--- + drivers/fpga/altera-cvp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c +index 6b09144324453..5af0bd33890c0 100644 +--- a/drivers/fpga/altera-cvp.c ++++ b/drivers/fpga/altera-cvp.c +@@ -52,7 +52,7 @@ + /* V2 Defines */ + #define VSE_CVP_TX_CREDITS 0x49 /* 8bit */ + +-#define V2_CREDIT_TIMEOUT_US 20000 ++#define V2_CREDIT_TIMEOUT_US 40000 + #define V2_CHECK_CREDIT_US 10 + #define V2_POLL_TIMEOUT_US 1000000 + #define V2_USER_TIMEOUT_US 500000 +-- +2.39.5 + diff --git a/queue-6.12/fs-buffer-introduce-sleeping-flavors-for-pagecache-l.patch b/queue-6.12/fs-buffer-introduce-sleeping-flavors-for-pagecache-l.patch new file mode 100644 index 0000000000..4652f1b7a9 --- /dev/null +++ b/queue-6.12/fs-buffer-introduce-sleeping-flavors-for-pagecache-l.patch @@ -0,0 +1,76 @@ +From c61a716ed7cc0ed687c3c71ef8713d2b20afe03b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 18:59:16 -0700 +Subject: fs/buffer: introduce sleeping flavors for pagecache lookups + +From: Davidlohr Bueso + +[ Upstream commit 2814a7d3d2ff5d2cdd22936f641f758fdb971fa0 ] + +Add __find_get_block_nonatomic() and sb_find_get_block_nonatomic() +calls for which users will be converted where safe. These versions +will take the folio lock instead of the mapping's private_lock. + +Reviewed-by: Jan Kara +Signed-off-by: Davidlohr Bueso +Link: https://kdevops.org/ext4/v6.15-rc2.html # [0] +Link: https://lore.kernel.org/all/aAAEvcrmREWa1SKF@bombadil.infradead.org/ # [1] +Link: https://lore.kernel.org/20250418015921.132400-3-dave@stgolabs.net +Tested-by: kdevops@lists.linux.dev +Reviewed-by: Luis Chamberlain +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/buffer.c | 9 +++++++++ + include/linux/buffer_head.h | 8 ++++++++ + 2 files changed, 17 insertions(+) + +diff --git a/fs/buffer.c b/fs/buffer.c +index ba464c2002061..b04705eb6cc57 100644 +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -1420,6 +1420,15 @@ __find_get_block(struct block_device *bdev, sector_t block, unsigned size) + } + EXPORT_SYMBOL(__find_get_block); + ++/* same as __find_get_block() but allows sleeping contexts */ ++struct buffer_head * ++__find_get_block_nonatomic(struct block_device *bdev, sector_t block, ++ unsigned size) ++{ ++ return find_get_block_common(bdev, block, size, false); ++} ++EXPORT_SYMBOL(__find_get_block_nonatomic); ++ + /** + * bdev_getblk - Get a buffer_head in a block device's buffer cache. + * @bdev: The block device. +diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h +index 932139c5d46f5..ffcd76d977703 100644 +--- a/include/linux/buffer_head.h ++++ b/include/linux/buffer_head.h +@@ -223,6 +223,8 @@ void __wait_on_buffer(struct buffer_head *); + wait_queue_head_t *bh_waitq_head(struct buffer_head *bh); + struct buffer_head *__find_get_block(struct block_device *bdev, sector_t block, + unsigned size); ++struct buffer_head *__find_get_block_nonatomic(struct block_device *bdev, ++ sector_t block, unsigned size); + struct buffer_head *bdev_getblk(struct block_device *bdev, sector_t block, + unsigned size, gfp_t gfp); + void __brelse(struct buffer_head *); +@@ -398,6 +400,12 @@ sb_find_get_block(struct super_block *sb, sector_t block) + return __find_get_block(sb->s_bdev, block, sb->s_blocksize); + } + ++static inline struct buffer_head * ++sb_find_get_block_nonatomic(struct super_block *sb, sector_t block) ++{ ++ return __find_get_block_nonatomic(sb->s_bdev, block, sb->s_blocksize); ++} ++ + static inline void + map_bh(struct buffer_head *bh, struct super_block *sb, sector_t block) + { +-- +2.39.5 + diff --git a/queue-6.12/fs-buffer-split-locking-for-pagecache-lookups.patch b/queue-6.12/fs-buffer-split-locking-for-pagecache-lookups.patch new file mode 100644 index 0000000000..22588bba4f --- /dev/null +++ b/queue-6.12/fs-buffer-split-locking-for-pagecache-lookups.patch @@ -0,0 +1,125 @@ +From 2897cbf60f8a57ab14753a4569399f1e95aab3c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 18:59:15 -0700 +Subject: fs/buffer: split locking for pagecache lookups + +From: Davidlohr Bueso + +[ Upstream commit 7ffe3de53a885dbb5836541c2178bd07d1bad7df ] + +Callers of __find_get_block() may or may not allow for blocking +semantics, and is currently assumed that it will not. Layout +two paths based on this. The the private_lock scheme will +continued to be used for atomic contexts. Otherwise take the +folio lock instead, which protects the buffers, such as +vs migration and try_to_free_buffers(). + +Per the "hack idea", the latter can alleviate contention on +the private_lock for bdev mappings. For reasons of determinism +and avoid making bugs hard to reproduce, the trylocking is not +attempted. + +No change in semantics. All lookup users still take the spinlock. + +Reviewed-by: Jan Kara +Signed-off-by: Davidlohr Bueso +Link: https://kdevops.org/ext4/v6.15-rc2.html # [0] +Link: https://lore.kernel.org/all/aAAEvcrmREWa1SKF@bombadil.infradead.org/ # [1] +Link: https://lore.kernel.org/20250418015921.132400-2-dave@stgolabs.net +Tested-by: kdevops@lists.linux.dev +Reviewed-by: Luis Chamberlain +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/buffer.c | 41 +++++++++++++++++++++++++---------------- + 1 file changed, 25 insertions(+), 16 deletions(-) + +diff --git a/fs/buffer.c b/fs/buffer.c +index 32bd0f4c42236..ba464c2002061 100644 +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -176,18 +176,8 @@ void end_buffer_write_sync(struct buffer_head *bh, int uptodate) + } + EXPORT_SYMBOL(end_buffer_write_sync); + +-/* +- * Various filesystems appear to want __find_get_block to be non-blocking. +- * But it's the page lock which protects the buffers. To get around this, +- * we get exclusion from try_to_free_buffers with the blockdev mapping's +- * i_private_lock. +- * +- * Hack idea: for the blockdev mapping, i_private_lock contention +- * may be quite high. This code could TryLock the page, and if that +- * succeeds, there is no need to take i_private_lock. +- */ + static struct buffer_head * +-__find_get_block_slow(struct block_device *bdev, sector_t block) ++__find_get_block_slow(struct block_device *bdev, sector_t block, bool atomic) + { + struct address_space *bd_mapping = bdev->bd_mapping; + const int blkbits = bd_mapping->host->i_blkbits; +@@ -204,7 +194,16 @@ __find_get_block_slow(struct block_device *bdev, sector_t block) + if (IS_ERR(folio)) + goto out; + +- spin_lock(&bd_mapping->i_private_lock); ++ /* ++ * Folio lock protects the buffers. Callers that cannot block ++ * will fallback to serializing vs try_to_free_buffers() via ++ * the i_private_lock. ++ */ ++ if (atomic) ++ spin_lock(&bd_mapping->i_private_lock); ++ else ++ folio_lock(folio); ++ + head = folio_buffers(folio); + if (!head) + goto out_unlock; +@@ -236,7 +235,10 @@ __find_get_block_slow(struct block_device *bdev, sector_t block) + 1 << blkbits); + } + out_unlock: +- spin_unlock(&bd_mapping->i_private_lock); ++ if (atomic) ++ spin_unlock(&bd_mapping->i_private_lock); ++ else ++ folio_unlock(folio); + folio_put(folio); + out: + return ret; +@@ -1394,14 +1396,15 @@ lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size) + * it in the LRU and mark it as accessed. If it is not present then return + * NULL + */ +-struct buffer_head * +-__find_get_block(struct block_device *bdev, sector_t block, unsigned size) ++static struct buffer_head * ++find_get_block_common(struct block_device *bdev, sector_t block, ++ unsigned size, bool atomic) + { + struct buffer_head *bh = lookup_bh_lru(bdev, block, size); + + if (bh == NULL) { + /* __find_get_block_slow will mark the page accessed */ +- bh = __find_get_block_slow(bdev, block); ++ bh = __find_get_block_slow(bdev, block, atomic); + if (bh) + bh_lru_install(bh); + } else +@@ -1409,6 +1412,12 @@ __find_get_block(struct block_device *bdev, sector_t block, unsigned size) + + return bh; + } ++ ++struct buffer_head * ++__find_get_block(struct block_device *bdev, sector_t block, unsigned size) ++{ ++ return find_get_block_common(bdev, block, size, true); ++} + EXPORT_SYMBOL(__find_get_block); + + /** +-- +2.39.5 + diff --git a/queue-6.12/fs-buffer-use-sleeping-version-of-__find_get_block.patch b/queue-6.12/fs-buffer-use-sleeping-version-of-__find_get_block.patch new file mode 100644 index 0000000000..efc5b519af --- /dev/null +++ b/queue-6.12/fs-buffer-use-sleeping-version-of-__find_get_block.patch @@ -0,0 +1,63 @@ +From 41a1c35203be1f9fb4e851c0ec7caafdfc89c249 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 18:59:17 -0700 +Subject: fs/buffer: use sleeping version of __find_get_block() + +From: Davidlohr Bueso + +[ Upstream commit 5b67d43976828dea2394eae2556b369bb7a61f64 ] + +Convert to the new nonatomic flavor to benefit from potential performance +benefits and adapt in the future vs migration such that semantics +are kept. + +Convert write_boundary_block() which already takes the buffer +lock as well as bdev_getblk() depending on the respective gpf flags. +There are no changes in semantics. + +Suggested-by: Jan Kara +Reviewed-by: Jan Kara +Signed-off-by: Davidlohr Bueso +Link: https://kdevops.org/ext4/v6.15-rc2.html # [0] +Link: https://lore.kernel.org/all/aAAEvcrmREWa1SKF@bombadil.infradead.org/ # [1] +Link: https://lore.kernel.org/20250418015921.132400-4-dave@stgolabs.net +Tested-by: kdevops@lists.linux.dev # [0] [1] +Reviewed-by: Luis Chamberlain +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/buffer.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/fs/buffer.c b/fs/buffer.c +index b04705eb6cc57..e9e84512a027a 100644 +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -658,7 +658,9 @@ EXPORT_SYMBOL(generic_buffers_fsync); + void write_boundary_block(struct block_device *bdev, + sector_t bblock, unsigned blocksize) + { +- struct buffer_head *bh = __find_get_block(bdev, bblock + 1, blocksize); ++ struct buffer_head *bh; ++ ++ bh = __find_get_block_nonatomic(bdev, bblock + 1, blocksize); + if (bh) { + if (buffer_dirty(bh)) + write_dirty_buffer(bh, 0); +@@ -1446,7 +1448,12 @@ EXPORT_SYMBOL(__find_get_block_nonatomic); + struct buffer_head *bdev_getblk(struct block_device *bdev, sector_t block, + unsigned size, gfp_t gfp) + { +- struct buffer_head *bh = __find_get_block(bdev, block, size); ++ struct buffer_head *bh; ++ ++ if (gfpflags_allow_blocking(gfp)) ++ bh = __find_get_block_nonatomic(bdev, block, size); ++ else ++ bh = __find_get_block(bdev, block, size); + + might_alloc(gfp); + if (bh) +-- +2.39.5 + diff --git a/queue-6.12/fs-ext4-use-sleeping-version-of-sb_find_get_block.patch b/queue-6.12/fs-ext4-use-sleeping-version-of-sb_find_get_block.patch new file mode 100644 index 0000000000..5041f404a9 --- /dev/null +++ b/queue-6.12/fs-ext4-use-sleeping-version-of-sb_find_get_block.patch @@ -0,0 +1,45 @@ +From b17ced97330cd7979a120e24cba921f869d4d861 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 18:59:20 -0700 +Subject: fs/ext4: use sleeping version of sb_find_get_block() + +From: Davidlohr Bueso + +[ Upstream commit 6e8f57fd09c9fb569d10b2ccc3878155b702591a ] + +Enable ext4_free_blocks() to use it, which has a cond_resched to begin +with. Convert to the new nonatomic flavor to benefit from potential +performance benefits and adapt in the future vs migration such that +semantics are kept. + +Suggested-by: Jan Kara +Reviewed-by: Jan Kara +Signed-off-by: Davidlohr Bueso +Link: https://kdevops.org/ext4/v6.15-rc2.html # [0] +Link: https://lore.kernel.org/all/aAAEvcrmREWa1SKF@bombadil.infradead.org/ # [1] +Link: https://lore.kernel.org/20250418015921.132400-7-dave@stgolabs.net +Tested-by: kdevops@lists.linux.dev +Reviewed-by: Luis Chamberlain +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/ext4/mballoc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index 92f49d7eb3c00..109cf88e7caac 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -6644,7 +6644,8 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, + for (i = 0; i < count; i++) { + cond_resched(); + if (is_metadata) +- bh = sb_find_get_block(inode->i_sb, block + i); ++ bh = sb_find_get_block_nonatomic(inode->i_sb, ++ block + i); + ext4_forget(handle, is_metadata, inode, bh, block + i); + } + } +-- +2.39.5 + diff --git a/queue-6.12/fs-jbd2-use-sleeping-version-of-__find_get_block.patch b/queue-6.12/fs-jbd2-use-sleeping-version-of-__find_get_block.patch new file mode 100644 index 0000000000..b23d00c639 --- /dev/null +++ b/queue-6.12/fs-jbd2-use-sleeping-version-of-__find_get_block.patch @@ -0,0 +1,85 @@ +From 0cb2501c96be84c28109a6be7e5a95117dc61b7f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 18:59:19 -0700 +Subject: fs/jbd2: use sleeping version of __find_get_block() + +From: Davidlohr Bueso + +[ Upstream commit f76d4c28a46a9260d85e00dafc8f46d369365d33 ] + +Convert to the new nonatomic flavor to benefit from potential +performance benefits and adapt in the future vs migration such +that semantics are kept. + +- jbd2_journal_revoke(): can sleep (has might_sleep() in the beginning) + +- jbd2_journal_cancel_revoke(): only used from do_get_write_access() and + do_get_create_access() which do sleep. So can sleep. + +- jbd2_clear_buffer_revoked_flags() - only called from journal commit code + which sleeps. So can sleep. + +Suggested-by: Jan Kara +Reviewed-by: Jan Kara +Signed-off-by: Davidlohr Bueso +Link: https://kdevops.org/ext4/v6.15-rc2.html # [0] +Link: https://lore.kernel.org/all/aAAEvcrmREWa1SKF@bombadil.infradead.org/ # [1] +Link: https://lore.kernel.org/20250418015921.132400-6-dave@stgolabs.net +Tested-by: kdevops@lists.linux.dev +Reviewed-by: Luis Chamberlain +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/jbd2/revoke.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c +index ce63d5fde9c3a..f68fc8c255f00 100644 +--- a/fs/jbd2/revoke.c ++++ b/fs/jbd2/revoke.c +@@ -345,7 +345,8 @@ int jbd2_journal_revoke(handle_t *handle, unsigned long long blocknr, + bh = bh_in; + + if (!bh) { +- bh = __find_get_block(bdev, blocknr, journal->j_blocksize); ++ bh = __find_get_block_nonatomic(bdev, blocknr, ++ journal->j_blocksize); + if (bh) + BUFFER_TRACE(bh, "found on hash"); + } +@@ -355,7 +356,8 @@ int jbd2_journal_revoke(handle_t *handle, unsigned long long blocknr, + + /* If there is a different buffer_head lying around in + * memory anywhere... */ +- bh2 = __find_get_block(bdev, blocknr, journal->j_blocksize); ++ bh2 = __find_get_block_nonatomic(bdev, blocknr, ++ journal->j_blocksize); + if (bh2) { + /* ... and it has RevokeValid status... */ + if (bh2 != bh && buffer_revokevalid(bh2)) +@@ -466,7 +468,8 @@ int jbd2_journal_cancel_revoke(handle_t *handle, struct journal_head *jh) + * state machine will get very upset later on. */ + if (need_cancel) { + struct buffer_head *bh2; +- bh2 = __find_get_block(bh->b_bdev, bh->b_blocknr, bh->b_size); ++ bh2 = __find_get_block_nonatomic(bh->b_bdev, bh->b_blocknr, ++ bh->b_size); + if (bh2) { + if (bh2 != bh) + clear_buffer_revoked(bh2); +@@ -495,9 +498,9 @@ void jbd2_clear_buffer_revoked_flags(journal_t *journal) + struct jbd2_revoke_record_s *record; + struct buffer_head *bh; + record = (struct jbd2_revoke_record_s *)list_entry; +- bh = __find_get_block(journal->j_fs_dev, +- record->blocknr, +- journal->j_blocksize); ++ bh = __find_get_block_nonatomic(journal->j_fs_dev, ++ record->blocknr, ++ journal->j_blocksize); + if (bh) { + clear_buffer_revoked(bh); + __brelse(bh); +-- +2.39.5 + diff --git a/queue-6.12/fs-mpage-avoid-negative-shift-for-large-blocksize.patch b/queue-6.12/fs-mpage-avoid-negative-shift-for-large-blocksize.patch new file mode 100644 index 0000000000..629f3eda20 --- /dev/null +++ b/queue-6.12/fs-mpage-avoid-negative-shift-for-large-blocksize.patch @@ -0,0 +1,49 @@ +From f2345d09fc1cbee743f0fae7e636e69045e8ec0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 14:38:18 -0800 +Subject: fs/mpage: avoid negative shift for large blocksize + +From: Hannes Reinecke + +[ Upstream commit 86c60efd7c0ede43bd677f2eee1d84200528df1e ] + +For large blocksizes the number of block bits is larger than PAGE_SHIFT, +so calculate the sector number from the byte offset instead. This is +required to enable large folios with buffer-heads. + +Reviewed-by: "Matthew Wilcox (Oracle)" +Signed-off-by: Luis Chamberlain +Signed-off-by: Hannes Reinecke +Link: https://lore.kernel.org/r/20250221223823.1680616-4-mcgrof@kernel.org +Reviewed-by: Hannes Reinecke +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/mpage.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/mpage.c b/fs/mpage.c +index 82aecf3727437..a3c82206977f6 100644 +--- a/fs/mpage.c ++++ b/fs/mpage.c +@@ -181,7 +181,7 @@ static struct bio *do_mpage_readpage(struct mpage_readpage_args *args) + if (folio_buffers(folio)) + goto confused; + +- block_in_file = (sector_t)folio->index << (PAGE_SHIFT - blkbits); ++ block_in_file = folio_pos(folio) >> blkbits; + last_block = block_in_file + args->nr_pages * blocks_per_page; + last_block_in_file = (i_size_read(inode) + blocksize - 1) >> blkbits; + if (last_block > last_block_in_file) +@@ -527,7 +527,7 @@ static int __mpage_writepage(struct folio *folio, struct writeback_control *wbc, + * The page has no buffers: map it to disk + */ + BUG_ON(!folio_test_uptodate(folio)); +- block_in_file = (sector_t)folio->index << (PAGE_SHIFT - blkbits); ++ block_in_file = folio_pos(folio) >> blkbits; + /* + * Whole page beyond EOF? Skip allocating blocks to avoid leaking + * space. +-- +2.39.5 + diff --git a/queue-6.12/fs-ocfs2-use-sleeping-version-of-__find_get_block.patch b/queue-6.12/fs-ocfs2-use-sleeping-version-of-__find_get_block.patch new file mode 100644 index 0000000000..0ed48980c9 --- /dev/null +++ b/queue-6.12/fs-ocfs2-use-sleeping-version-of-__find_get_block.patch @@ -0,0 +1,44 @@ +From 845bc2817038b7a0cbb65812d850b945519c7130 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 18:59:18 -0700 +Subject: fs/ocfs2: use sleeping version of __find_get_block() + +From: Davidlohr Bueso + +[ Upstream commit a0b5ff07491010789fcb012bc8f9dad9d26f9a8b ] + +This is a path that allows for blocking as it does IO. Convert +to the new nonatomic flavor to benefit from potential performance +benefits and adapt in the future vs migration such that semantics +are kept. + +Suggested-by: Jan Kara +Reviewed-by: Jan Kara +Signed-off-by: Davidlohr Bueso +Link: https://kdevops.org/ext4/v6.15-rc2.html # [0] +Link: https://lore.kernel.org/all/aAAEvcrmREWa1SKF@bombadil.infradead.org/ # [1] +Link: https://lore.kernel.org/20250418015921.132400-5-dave@stgolabs.net +Tested-by: kdevops@lists.linux.dev +Reviewed-by: Luis Chamberlain +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/ocfs2/journal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c +index 2ebee1dced1b2..c2a73bfb16aa4 100644 +--- a/fs/ocfs2/journal.c ++++ b/fs/ocfs2/journal.c +@@ -1271,7 +1271,7 @@ static int ocfs2_force_read_journal(struct inode *inode) + } + + for (i = 0; i < p_blocks; i++, p_blkno++) { +- bh = __find_get_block(osb->sb->s_bdev, p_blkno, ++ bh = __find_get_block_nonatomic(osb->sb->s_bdev, p_blkno, + osb->sb->s_blocksize); + /* block not cached. */ + if (!bh) +-- +2.39.5 + diff --git a/queue-6.12/fuse-return-eperm-rather-than-enosys-from-link.patch b/queue-6.12/fuse-return-eperm-rather-than-enosys-from-link.patch new file mode 100644 index 0000000000..089bb9af60 --- /dev/null +++ b/queue-6.12/fuse-return-eperm-rather-than-enosys-from-link.patch @@ -0,0 +1,36 @@ +From 2f25ea731c746fdd66008d7ee567fe7aacf6c834 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 09:17:53 +0800 +Subject: fuse: Return EPERM rather than ENOSYS from link() + +From: Matt Johnston + +[ Upstream commit 8344213571b2ac8caf013cfd3b37bc3467c3a893 ] + +link() is documented to return EPERM when a filesystem doesn't support +the operation, return that instead. + +Link: https://github.com/libfuse/libfuse/issues/925 +Signed-off-by: Matt Johnston +Signed-off-by: Miklos Szeredi +Signed-off-by: Sasha Levin +--- + fs/fuse/dir.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c +index a1e86ec07c38b..ff543dc09130e 100644 +--- a/fs/fuse/dir.c ++++ b/fs/fuse/dir.c +@@ -1133,6 +1133,8 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, + else if (err == -EINTR) + fuse_invalidate_attr(inode); + ++ if (err == -ENOSYS) ++ err = -EPERM; + return err; + } + +-- +2.39.5 + diff --git a/queue-6.12/genirq-msi-store-the-iommu-iova-directly-in-msi_desc.patch b/queue-6.12/genirq-msi-store-the-iommu-iova-directly-in-msi_desc.patch new file mode 100644 index 0000000000..793708ca03 --- /dev/null +++ b/queue-6.12/genirq-msi-store-the-iommu-iova-directly-in-msi_desc.patch @@ -0,0 +1,175 @@ +From 37e79f542e8dd33af973a1ae4fc93090f05654e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 17:31:36 -0800 +Subject: genirq/msi: Store the IOMMU IOVA directly in msi_desc instead of + iommu_cookie + +From: Jason Gunthorpe + +[ Upstream commit 1f7df3a691740a7736bbc99dc4ed536120eb4746 ] + +The IOMMU translation for MSI message addresses has been a 2-step process, +separated in time: + + 1) iommu_dma_prepare_msi(): A cookie pointer containing the IOVA address + is stored in the MSI descriptor when an MSI interrupt is allocated. + + 2) iommu_dma_compose_msi_msg(): this cookie pointer is used to compute a + translated message address. + +This has an inherent lifetime problem for the pointer stored in the cookie +that must remain valid between the two steps. However, there is no locking +at the irq layer that helps protect the lifetime. Today, this works under +the assumption that the iommu domain is not changed while MSI interrupts +being programmed. This is true for normal DMA API users within the kernel, +as the iommu domain is attached before the driver is probed and cannot be +changed while a driver is attached. + +Classic VFIO type1 also prevented changing the iommu domain while VFIO was +running as it does not support changing the "container" after starting up. + +However, iommufd has improved this so that the iommu domain can be changed +during VFIO operation. This potentially allows userspace to directly race +VFIO_DEVICE_ATTACH_IOMMUFD_PT (which calls iommu_attach_group()) and +VFIO_DEVICE_SET_IRQS (which calls into iommu_dma_compose_msi_msg()). + +This potentially causes both the cookie pointer and the unlocked call to +iommu_get_domain_for_dev() on the MSI translation path to become UAFs. + +Fix the MSI cookie UAF by removing the cookie pointer. The translated IOVA +address is already known during iommu_dma_prepare_msi() and cannot change. +Thus, it can simply be stored as an integer in the MSI descriptor. + +The other UAF related to iommu_get_domain_for_dev() will be addressed in +patch "iommu: Make iommu_dma_prepare_msi() into a generic operation" by +using the IOMMU group mutex. + +Link: https://patch.msgid.link/r/a4f2cd76b9dc1833ee6c1cf325cba57def22231c.1740014950.git.nicolinc@nvidia.com +Signed-off-by: Nicolin Chen +Reviewed-by: Thomas Gleixner +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/iommu/dma-iommu.c | 28 +++++++++++++--------------- + include/linux/msi.h | 33 ++++++++++++--------------------- + 2 files changed, 25 insertions(+), 36 deletions(-) + +diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c +index 2a9fa0c8cc00f..0f0caf59023c7 100644 +--- a/drivers/iommu/dma-iommu.c ++++ b/drivers/iommu/dma-iommu.c +@@ -1815,7 +1815,7 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr) + static DEFINE_MUTEX(msi_prepare_lock); /* see below */ + + if (!domain || !domain->iova_cookie) { +- desc->iommu_cookie = NULL; ++ msi_desc_set_iommu_msi_iova(desc, 0, 0); + return 0; + } + +@@ -1827,11 +1827,12 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr) + mutex_lock(&msi_prepare_lock); + msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain); + mutex_unlock(&msi_prepare_lock); +- +- msi_desc_set_iommu_cookie(desc, msi_page); +- + if (!msi_page) + return -ENOMEM; ++ ++ msi_desc_set_iommu_msi_iova( ++ desc, msi_page->iova, ++ ilog2(cookie_msi_granule(domain->iova_cookie))); + return 0; + } + +@@ -1842,18 +1843,15 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr) + */ + void iommu_dma_compose_msi_msg(struct msi_desc *desc, struct msi_msg *msg) + { +- struct device *dev = msi_desc_to_dev(desc); +- const struct iommu_domain *domain = iommu_get_domain_for_dev(dev); +- const struct iommu_dma_msi_page *msi_page; ++#ifdef CONFIG_IRQ_MSI_IOMMU ++ if (desc->iommu_msi_shift) { ++ u64 msi_iova = desc->iommu_msi_iova << desc->iommu_msi_shift; + +- msi_page = msi_desc_get_iommu_cookie(desc); +- +- if (!domain || !domain->iova_cookie || WARN_ON(!msi_page)) +- return; +- +- msg->address_hi = upper_32_bits(msi_page->iova); +- msg->address_lo &= cookie_msi_granule(domain->iova_cookie) - 1; +- msg->address_lo += lower_32_bits(msi_page->iova); ++ msg->address_hi = upper_32_bits(msi_iova); ++ msg->address_lo = lower_32_bits(msi_iova) | ++ (msg->address_lo & ((1 << desc->iommu_msi_shift) - 1)); ++ } ++#endif + } + + static int iommu_dma_init(void) +diff --git a/include/linux/msi.h b/include/linux/msi.h +index 59a421fc42bf0..63d0e51f7a801 100644 +--- a/include/linux/msi.h ++++ b/include/linux/msi.h +@@ -165,6 +165,10 @@ struct msi_desc_data { + * @dev: Pointer to the device which uses this descriptor + * @msg: The last set MSI message cached for reuse + * @affinity: Optional pointer to a cpu affinity mask for this descriptor ++ * @iommu_msi_iova: Optional shifted IOVA from the IOMMU to override the msi_addr. ++ * Only used if iommu_msi_shift != 0 ++ * @iommu_msi_shift: Indicates how many bits of the original address should be ++ * preserved when using iommu_msi_iova. + * @sysfs_attr: Pointer to sysfs device attribute + * + * @write_msi_msg: Callback that may be called when the MSI message +@@ -183,7 +187,8 @@ struct msi_desc { + struct msi_msg msg; + struct irq_affinity_desc *affinity; + #ifdef CONFIG_IRQ_MSI_IOMMU +- const void *iommu_cookie; ++ u64 iommu_msi_iova : 58; ++ u64 iommu_msi_shift : 6; + #endif + #ifdef CONFIG_SYSFS + struct device_attribute *sysfs_attrs; +@@ -284,28 +289,14 @@ struct msi_desc *msi_next_desc(struct device *dev, unsigned int domid, + + #define msi_desc_to_dev(desc) ((desc)->dev) + +-#ifdef CONFIG_IRQ_MSI_IOMMU +-static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc) +-{ +- return desc->iommu_cookie; +-} +- +-static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc, +- const void *iommu_cookie) +-{ +- desc->iommu_cookie = iommu_cookie; +-} +-#else +-static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc) ++static inline void msi_desc_set_iommu_msi_iova(struct msi_desc *desc, u64 msi_iova, ++ unsigned int msi_shift) + { +- return NULL; +-} +- +-static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc, +- const void *iommu_cookie) +-{ +-} ++#ifdef CONFIG_IRQ_MSI_IOMMU ++ desc->iommu_msi_iova = msi_iova >> msi_shift; ++ desc->iommu_msi_shift = msi_shift; + #endif ++} + + int msi_domain_insert_msi_desc(struct device *dev, unsigned int domid, + struct msi_desc *init_desc); +-- +2.39.5 + diff --git a/queue-6.12/gfs2-check-for-empty-queue-in-run_queue.patch b/queue-6.12/gfs2-check-for-empty-queue-in-run_queue.patch new file mode 100644 index 0000000000..3c00f9159c --- /dev/null +++ b/queue-6.12/gfs2-check-for-empty-queue-in-run_queue.patch @@ -0,0 +1,65 @@ +From 08d60b86830ca8e02e4daeca23e247005835b516 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 14:58:39 +0100 +Subject: gfs2: Check for empty queue in run_queue + +From: Andreas Gruenbacher + +[ Upstream commit d838605fea6eabae3746a276fd448f6719eb3926 ] + +In run_queue(), check if the queue of pending requests is empty instead +of blindly assuming that it won't be. + +Signed-off-by: Andreas Gruenbacher +Signed-off-by: Sasha Levin +--- + fs/gfs2/glock.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c +index a51fe42732c4c..4f1eca99786b6 100644 +--- a/fs/gfs2/glock.c ++++ b/fs/gfs2/glock.c +@@ -843,12 +843,13 @@ static void run_queue(struct gfs2_glock *gl, const int nonblock) + __releases(&gl->gl_lockref.lock) + __acquires(&gl->gl_lockref.lock) + { +- struct gfs2_holder *gh = NULL; ++ struct gfs2_holder *gh; + + if (test_bit(GLF_LOCK, &gl->gl_flags)) + return; + set_bit(GLF_LOCK, &gl->gl_flags); + ++ /* While a demote is in progress, the GLF_LOCK flag must be set. */ + GLOCK_BUG_ON(gl, test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags)); + + if (test_bit(GLF_DEMOTE, &gl->gl_flags) && +@@ -860,18 +861,22 @@ __acquires(&gl->gl_lockref.lock) + set_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags); + GLOCK_BUG_ON(gl, gl->gl_demote_state == LM_ST_EXCLUSIVE); + gl->gl_target = gl->gl_demote_state; ++ do_xmote(gl, NULL, gl->gl_target); ++ return; + } else { + if (test_bit(GLF_DEMOTE, &gl->gl_flags)) + gfs2_demote_wake(gl); + if (do_promote(gl)) + goto out_unlock; + gh = find_first_waiter(gl); ++ if (!gh) ++ goto out_unlock; + gl->gl_target = gh->gh_state; + if (!(gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) + do_error(gl, 0); /* Fail queued try locks */ ++ do_xmote(gl, gh, gl->gl_target); ++ return; + } +- do_xmote(gl, gh, gl->gl_target); +- return; + + out_sched: + clear_bit(GLF_LOCK, &gl->gl_flags); +-- +2.39.5 + diff --git a/queue-6.12/hid-usbkbd-fix-the-bit-shift-number-for-led_kana.patch b/queue-6.12/hid-usbkbd-fix-the-bit-shift-number-for-led_kana.patch new file mode 100644 index 0000000000..fda6bd08f8 --- /dev/null +++ b/queue-6.12/hid-usbkbd-fix-the-bit-shift-number-for-led_kana.patch @@ -0,0 +1,34 @@ +From be4d0ffcf0986018a2be0ade52de6305f326142b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Nov 2024 10:35:18 +0800 +Subject: HID: usbkbd: Fix the bit shift number for LED_KANA + +From: junan + +[ Upstream commit d73a4bfa2881a6859b384b75a414c33d4898b055 ] + +Since "LED_KANA" was defined as "0x04", the shift number should be "4". + +Signed-off-by: junan +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/usbhid/usbkbd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c +index c439ed2f16dbc..af6bc76dbf649 100644 +--- a/drivers/hid/usbhid/usbkbd.c ++++ b/drivers/hid/usbhid/usbkbd.c +@@ -160,7 +160,7 @@ static int usb_kbd_event(struct input_dev *dev, unsigned int type, + return -1; + + spin_lock_irqsave(&kbd->leds_lock, flags); +- kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) | ++ kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 4) | (!!test_bit(LED_COMPOSE, dev->led) << 3) | + (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) | + (!!test_bit(LED_NUML, dev->led)); + +-- +2.39.5 + diff --git a/queue-6.12/hrtimers-replace-hrtimer_clock_to_base_table-with-sw.patch b/queue-6.12/hrtimers-replace-hrtimer_clock_to_base_table-with-sw.patch new file mode 100644 index 0000000000..a4c7fdba04 --- /dev/null +++ b/queue-6.12/hrtimers-replace-hrtimer_clock_to_base_table-with-sw.patch @@ -0,0 +1,87 @@ +From 9c25489ab1f01dfe329d2edabf7d8b1f9c401c0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 15:43:33 +0200 +Subject: hrtimers: Replace hrtimer_clock_to_base_table with switch-case + +From: Andy Shevchenko + +[ Upstream commit 4441b976dfeff0d3579e8da3c0283300c618a553 ] + +Clang and GCC complain about overlapped initialisers in the +hrtimer_clock_to_base_table definition. With `make W=1` and CONFIG_WERROR=y +(which is default nowadays) this breaks the build: + + CC kernel/time/hrtimer.o +kernel/time/hrtimer.c:124:21: error: initializer overrides prior initialization of this subobject [-Werror,-Winitializer-overrides] + 124 | [CLOCK_REALTIME] = HRTIMER_BASE_REALTIME, + +kernel/time/hrtimer.c:122:27: note: previous initialization is here + 122 | [0 ... MAX_CLOCKS - 1] = HRTIMER_MAX_CLOCK_BASES, + +(and similar for CLOCK_MONOTONIC, CLOCK_BOOTTIME, and CLOCK_TAI). + +hrtimer_clockid_to_base(), which uses the table, is only used in +__hrtimer_init(), which is not a hotpath. + +Therefore replace the table lookup with a switch case in +hrtimer_clockid_to_base() to avoid this warning. + +Signed-off-by: Andy Shevchenko +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/all/20250214134424.3367619-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Sasha Levin +--- + kernel/time/hrtimer.c | 29 ++++++++++++----------------- + 1 file changed, 12 insertions(+), 17 deletions(-) + +diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c +index db9c06bb23116..06fbc226341fd 100644 +--- a/kernel/time/hrtimer.c ++++ b/kernel/time/hrtimer.c +@@ -117,16 +117,6 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = + .csd = CSD_INIT(retrigger_next_event, NULL) + }; + +-static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = { +- /* Make sure we catch unsupported clockids */ +- [0 ... MAX_CLOCKS - 1] = HRTIMER_MAX_CLOCK_BASES, +- +- [CLOCK_REALTIME] = HRTIMER_BASE_REALTIME, +- [CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC, +- [CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME, +- [CLOCK_TAI] = HRTIMER_BASE_TAI, +-}; +- + static inline bool hrtimer_base_is_online(struct hrtimer_cpu_base *base) + { + if (!IS_ENABLED(CONFIG_HOTPLUG_CPU)) +@@ -1597,14 +1587,19 @@ u64 hrtimer_next_event_without(const struct hrtimer *exclude) + + static inline int hrtimer_clockid_to_base(clockid_t clock_id) + { +- if (likely(clock_id < MAX_CLOCKS)) { +- int base = hrtimer_clock_to_base_table[clock_id]; +- +- if (likely(base != HRTIMER_MAX_CLOCK_BASES)) +- return base; ++ switch (clock_id) { ++ case CLOCK_REALTIME: ++ return HRTIMER_BASE_REALTIME; ++ case CLOCK_MONOTONIC: ++ return HRTIMER_BASE_MONOTONIC; ++ case CLOCK_BOOTTIME: ++ return HRTIMER_BASE_BOOTTIME; ++ case CLOCK_TAI: ++ return HRTIMER_BASE_TAI; ++ default: ++ WARN(1, "Invalid clockid %d. Using MONOTONIC\n", clock_id); ++ return HRTIMER_BASE_MONOTONIC; + } +- WARN(1, "Invalid clockid %d. Using MONOTONIC\n", clock_id); +- return HRTIMER_BASE_MONOTONIC; + } + + static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id, +-- +2.39.5 + diff --git a/queue-6.12/hwmon-dell-smm-increment-the-number-of-fans.patch b/queue-6.12/hwmon-dell-smm-increment-the-number-of-fans.patch new file mode 100644 index 0000000000..3d0f26577e --- /dev/null +++ b/queue-6.12/hwmon-dell-smm-increment-the-number-of-fans.patch @@ -0,0 +1,86 @@ +From 601b179356f5a05163f06dcb8a4f02cad62c3542 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 00:52:50 -0500 +Subject: hwmon: (dell-smm) Increment the number of fans + +From: Kurt Borja + +[ Upstream commit dbcfcb239b3b452ef8782842c36fb17dd1b9092f ] + +Some Alienware laptops that support the SMM interface, may have up to 4 +fans. + +Tested on an Alienware x15 r1. + +Signed-off-by: Kurt Borja +Link: https://lore.kernel.org/r/20250304055249.51940-2-kuurtb@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + Documentation/hwmon/dell-smm-hwmon.rst | 14 +++++++------- + drivers/hwmon/dell-smm-hwmon.c | 5 ++++- + 2 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/Documentation/hwmon/dell-smm-hwmon.rst b/Documentation/hwmon/dell-smm-hwmon.rst +index 74905675d71f9..5a4edb6565cf9 100644 +--- a/Documentation/hwmon/dell-smm-hwmon.rst ++++ b/Documentation/hwmon/dell-smm-hwmon.rst +@@ -32,12 +32,12 @@ Temperature sensors and fans can be queried and set via the standard + =============================== ======= ======================================= + Name Perm Description + =============================== ======= ======================================= +-fan[1-3]_input RO Fan speed in RPM. +-fan[1-3]_label RO Fan label. +-fan[1-3]_min RO Minimal Fan speed in RPM +-fan[1-3]_max RO Maximal Fan speed in RPM +-fan[1-3]_target RO Expected Fan speed in RPM +-pwm[1-3] RW Control the fan PWM duty-cycle. ++fan[1-4]_input RO Fan speed in RPM. ++fan[1-4]_label RO Fan label. ++fan[1-4]_min RO Minimal Fan speed in RPM ++fan[1-4]_max RO Maximal Fan speed in RPM ++fan[1-4]_target RO Expected Fan speed in RPM ++pwm[1-4] RW Control the fan PWM duty-cycle. + pwm1_enable WO Enable or disable automatic BIOS fan + control (not supported on all laptops, + see below for details). +@@ -93,7 +93,7 @@ Again, when you find new codes, we'd be happy to have your patches! + --------------------------- + + The driver also exports the fans as thermal cooling devices with +-``type`` set to ``dell-smm-fan[1-3]``. This allows for easy fan control ++``type`` set to ``dell-smm-fan[1-4]``. This allows for easy fan control + using one of the thermal governors. + + Module parameters +diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c +index f5bdf842040e6..b043fbd15c9da 100644 +--- a/drivers/hwmon/dell-smm-hwmon.c ++++ b/drivers/hwmon/dell-smm-hwmon.c +@@ -73,7 +73,7 @@ + #define DELL_SMM_LEGACY_EXECUTE 0x1 + + #define DELL_SMM_NO_TEMP 10 +-#define DELL_SMM_NO_FANS 3 ++#define DELL_SMM_NO_FANS 4 + + struct smm_regs { + unsigned int eax; +@@ -1074,11 +1074,14 @@ static const struct hwmon_channel_info * const dell_smm_info[] = { + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX | + HWMON_F_TARGET, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX | ++ HWMON_F_TARGET, ++ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX | + HWMON_F_TARGET + ), + HWMON_CHANNEL_INFO(pwm, + HWMON_PWM_INPUT | HWMON_PWM_ENABLE, + HWMON_PWM_INPUT, ++ HWMON_PWM_INPUT, + HWMON_PWM_INPUT + ), + NULL +-- +2.39.5 + diff --git a/queue-6.12/hwmon-gpio-fan-add-missing-mutex-locks.patch b/queue-6.12/hwmon-gpio-fan-add-missing-mutex-locks.patch new file mode 100644 index 0000000000..5a5d382f15 --- /dev/null +++ b/queue-6.12/hwmon-gpio-fan-add-missing-mutex-locks.patch @@ -0,0 +1,75 @@ +From 29c668f3098b2a168ad21f779a8d6e543e3ea992 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 15:59:30 +0100 +Subject: hwmon: (gpio-fan) Add missing mutex locks + +From: Alexander Stein + +[ Upstream commit 9fee7d19bab635f89223cc40dfd2c8797fdc4988 ] + +set_fan_speed() is expected to be called with fan_data->lock being locked. +Add locking for proper synchronization. + +Signed-off-by: Alexander Stein +Link: https://lore.kernel.org/r/20250210145934.761280-3-alexander.stein@ew.tq-group.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/gpio-fan.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c +index d92c536be9af7..b779240328d59 100644 +--- a/drivers/hwmon/gpio-fan.c ++++ b/drivers/hwmon/gpio-fan.c +@@ -393,7 +393,12 @@ static int gpio_fan_set_cur_state(struct thermal_cooling_device *cdev, + if (state >= fan_data->num_speed) + return -EINVAL; + ++ mutex_lock(&fan_data->lock); ++ + set_fan_speed(fan_data, state); ++ ++ mutex_unlock(&fan_data->lock); ++ + return 0; + } + +@@ -489,7 +494,11 @@ MODULE_DEVICE_TABLE(of, of_gpio_fan_match); + + static void gpio_fan_stop(void *data) + { ++ struct gpio_fan_data *fan_data = data; ++ ++ mutex_lock(&fan_data->lock); + set_fan_speed(data, 0); ++ mutex_unlock(&fan_data->lock); + } + + static int gpio_fan_probe(struct platform_device *pdev) +@@ -562,7 +571,9 @@ static int gpio_fan_suspend(struct device *dev) + + if (fan_data->gpios) { + fan_data->resume_speed = fan_data->speed_index; ++ mutex_lock(&fan_data->lock); + set_fan_speed(fan_data, 0); ++ mutex_unlock(&fan_data->lock); + } + + return 0; +@@ -572,8 +583,11 @@ static int gpio_fan_resume(struct device *dev) + { + struct gpio_fan_data *fan_data = dev_get_drvdata(dev); + +- if (fan_data->gpios) ++ if (fan_data->gpios) { ++ mutex_lock(&fan_data->lock); + set_fan_speed(fan_data, fan_data->resume_speed); ++ mutex_unlock(&fan_data->lock); ++ } + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.12/hwmon-xgene-hwmon-use-appropriate-type-for-the-laten.patch b/queue-6.12/hwmon-xgene-hwmon-use-appropriate-type-for-the-laten.patch new file mode 100644 index 0000000000..b4ae613df0 --- /dev/null +++ b/queue-6.12/hwmon-xgene-hwmon-use-appropriate-type-for-the-laten.patch @@ -0,0 +1,45 @@ +From 4e1a420da098cd76abb9069ea29326bf4caa86c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 09:54:08 +0000 +Subject: hwmon: (xgene-hwmon) use appropriate type for the latency value + +From: Andrey Vatoropin + +[ Upstream commit 8df0f002827e18632dcd986f7546c1abf1953a6f ] + +The expression PCC_NUM_RETRIES * pcc_chan->latency is currently being +evaluated using 32-bit arithmetic. + +Since a value of type 'u64' is used to store the eventual result, +and this result is later sent to the function usecs_to_jiffies with +input parameter unsigned int, the current data type is too wide to +store the value of ctx->usecs_lat. + +Change the data type of "usecs_lat" to a more suitable (narrower) type. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Signed-off-by: Andrey Vatoropin +Link: https://lore.kernel.org/r/20250204095400.95013-1-a.vatoropin@crpt.ru +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/xgene-hwmon.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c +index 92d82faf237fc..4e05077e4256d 100644 +--- a/drivers/hwmon/xgene-hwmon.c ++++ b/drivers/hwmon/xgene-hwmon.c +@@ -105,7 +105,7 @@ struct xgene_hwmon_dev { + + phys_addr_t comm_base_addr; + void *pcc_comm_addr; +- u64 usecs_lat; ++ unsigned int usecs_lat; + }; + + /* +-- +2.39.5 + diff --git a/queue-6.12/hypfs_create_cpu_files-add-missing-check-for-hypfs_m.patch b/queue-6.12/hypfs_create_cpu_files-add-missing-check-for-hypfs_m.patch new file mode 100644 index 0000000000..f450d36097 --- /dev/null +++ b/queue-6.12/hypfs_create_cpu_files-add-missing-check-for-hypfs_m.patch @@ -0,0 +1,31 @@ +From 1d289341a1cf75e1e45d218acdf4c1470b87bd66 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 22:06:04 -0400 +Subject: hypfs_create_cpu_files(): add missing check for hypfs_mkdir() failure + +From: Al Viro + +[ Upstream commit 00cdfdcfa0806202aea56b02cedbf87ef1e75df8 ] + +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + arch/s390/hypfs/hypfs_diag_fs.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/s390/hypfs/hypfs_diag_fs.c b/arch/s390/hypfs/hypfs_diag_fs.c +index 00a6d370a2803..280266a74f378 100644 +--- a/arch/s390/hypfs/hypfs_diag_fs.c ++++ b/arch/s390/hypfs/hypfs_diag_fs.c +@@ -208,6 +208,8 @@ static int hypfs_create_cpu_files(struct dentry *cpus_dir, void *cpu_info) + snprintf(buffer, TMP_SIZE, "%d", cpu_info__cpu_addr(diag204_get_info_type(), + cpu_info)); + cpu_dir = hypfs_mkdir(cpus_dir, buffer); ++ if (IS_ERR(cpu_dir)) ++ return PTR_ERR(cpu_dir); + rc = hypfs_create_u64(cpu_dir, "mgmtime", + cpu_info__acc_time(diag204_get_info_type(), cpu_info) - + cpu_info__lp_time(diag204_get_info_type(), cpu_info)); +-- +2.39.5 + diff --git a/queue-6.12/i2c-designware-fix-an-error-handling-path-in-i2c_dw_.patch b/queue-6.12/i2c-designware-fix-an-error-handling-path-in-i2c_dw_.patch new file mode 100644 index 0000000000..cad67e4408 --- /dev/null +++ b/queue-6.12/i2c-designware-fix-an-error-handling-path-in-i2c_dw_.patch @@ -0,0 +1,44 @@ +From 344270d1f1ed57614870e894fdb52741908982f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 May 2025 19:56:41 +0200 +Subject: i2c: designware: Fix an error handling path in i2c_dw_pci_probe() + +From: Christophe JAILLET + +[ Upstream commit 1cfe51ef07ca3286581d612debfb0430eeccbb65 ] + +If navi_amd_register_client() fails, the previous i2c_dw_probe() call +should be undone by a corresponding i2c_del_adapter() call, as already done +in the remove function. + +Fixes: 17631e8ca2d3 ("i2c: designware: Add driver support for AMD NAVI GPU") +Signed-off-by: Christophe JAILLET +Cc: # v5.13+ +Acked-by: Jarkko Nikula +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/fcd9651835a32979df8802b2db9504c523a8ebbb.1747158983.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-designware-pcidrv.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c +index 433cb285d3b20..5ea6d40373e7e 100644 +--- a/drivers/i2c/busses/i2c-designware-pcidrv.c ++++ b/drivers/i2c/busses/i2c-designware-pcidrv.c +@@ -278,9 +278,11 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, + + if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) { + dev->slave = i2c_new_ccgx_ucsi(&dev->adapter, dev->irq, &dgpu_node); +- if (IS_ERR(dev->slave)) ++ if (IS_ERR(dev->slave)) { ++ i2c_del_adapter(&dev->adapter); + return dev_err_probe(device, PTR_ERR(dev->slave), + "register UCSI failed\n"); ++ } + } + + pm_runtime_set_autosuspend_delay(device, 1000); +-- +2.39.5 + diff --git a/queue-6.12/i2c-designware-use-temporary-variable-for-struct-dev.patch b/queue-6.12/i2c-designware-use-temporary-variable-for-struct-dev.patch new file mode 100644 index 0000000000..3098cf26a1 --- /dev/null +++ b/queue-6.12/i2c-designware-use-temporary-variable-for-struct-dev.patch @@ -0,0 +1,229 @@ +From 980be9efe6686b1310c6d5b07aa86c83f04a720c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Sep 2024 15:44:19 +0300 +Subject: i2c: designware: Use temporary variable for struct device + +From: Andy Shevchenko + +[ Upstream commit d2f94dccab8319063dd1fbc1738b4a280c2e4009 ] + +Use temporary variable for struct device to make code neater. + +Reviewed-by: Mario Limonciello +Reviewed-by: Andi Shyti +Signed-off-by: Andy Shevchenko +Acked-by: Jarkko Nikula +Signed-off-by: Andi Shyti +Stable-dep-of: 1cfe51ef07ca ("i2c: designware: Fix an error handling path in i2c_dw_pci_probe()") +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-designware-pcidrv.c | 29 ++++++------- + drivers/i2c/busses/i2c-designware-platdrv.c | 48 ++++++++++----------- + 2 files changed, 37 insertions(+), 40 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c +index 7b2c5d71a7fce..433cb285d3b20 100644 +--- a/drivers/i2c/busses/i2c-designware-pcidrv.c ++++ b/drivers/i2c/busses/i2c-designware-pcidrv.c +@@ -207,6 +207,7 @@ static const struct software_node dgpu_node = { + static int i2c_dw_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) + { ++ struct device *device = &pdev->dev; + struct dw_i2c_dev *dev; + struct i2c_adapter *adap; + int r; +@@ -214,25 +215,22 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, + struct dw_scl_sda_cfg *cfg; + + if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) +- return dev_err_probe(&pdev->dev, -EINVAL, +- "Invalid driver data %ld\n", ++ return dev_err_probe(device, -EINVAL, "Invalid driver data %ld\n", + id->driver_data); + + controller = &dw_pci_controllers[id->driver_data]; + + r = pcim_enable_device(pdev); + if (r) +- return dev_err_probe(&pdev->dev, r, +- "Failed to enable I2C PCI device\n"); ++ return dev_err_probe(device, r, "Failed to enable I2C PCI device\n"); + + pci_set_master(pdev); + + r = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev)); + if (r) +- return dev_err_probe(&pdev->dev, r, +- "I/O memory remapping failed\n"); ++ return dev_err_probe(device, r, "I/O memory remapping failed\n"); + +- dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); ++ dev = devm_kzalloc(device, sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + +@@ -242,7 +240,7 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, + + dev->get_clk_rate_khz = controller->get_clk_rate_khz; + dev->base = pcim_iomap_table(pdev)[0]; +- dev->dev = &pdev->dev; ++ dev->dev = device; + dev->irq = pci_irq_vector(pdev, 0); + dev->flags |= controller->flags; + +@@ -281,14 +279,14 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, + if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) { + dev->slave = i2c_new_ccgx_ucsi(&dev->adapter, dev->irq, &dgpu_node); + if (IS_ERR(dev->slave)) +- return dev_err_probe(dev->dev, PTR_ERR(dev->slave), ++ return dev_err_probe(device, PTR_ERR(dev->slave), + "register UCSI failed\n"); + } + +- pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); +- pm_runtime_use_autosuspend(&pdev->dev); +- pm_runtime_put_autosuspend(&pdev->dev); +- pm_runtime_allow(&pdev->dev); ++ pm_runtime_set_autosuspend_delay(device, 1000); ++ pm_runtime_use_autosuspend(device); ++ pm_runtime_put_autosuspend(device); ++ pm_runtime_allow(device); + + return 0; + } +@@ -296,11 +294,12 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, + static void i2c_dw_pci_remove(struct pci_dev *pdev) + { + struct dw_i2c_dev *dev = pci_get_drvdata(pdev); ++ struct device *device = &pdev->dev; + + i2c_dw_disable(dev); + +- pm_runtime_forbid(&pdev->dev); +- pm_runtime_get_noresume(&pdev->dev); ++ pm_runtime_forbid(device); ++ pm_runtime_get_noresume(device); + + i2c_del_adapter(&dev->adapter); + } +diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c +index 2d0c7348e4917..a3e86930bf418 100644 +--- a/drivers/i2c/busses/i2c-designware-platdrv.c ++++ b/drivers/i2c/busses/i2c-designware-platdrv.c +@@ -205,6 +205,7 @@ static void i2c_dw_remove_lock_support(struct dw_i2c_dev *dev) + + static int dw_i2c_plat_probe(struct platform_device *pdev) + { ++ struct device *device = &pdev->dev; + struct i2c_adapter *adap; + struct dw_i2c_dev *dev; + int irq, ret; +@@ -213,15 +214,15 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) + if (irq < 0) + return irq; + +- dev = devm_kzalloc(&pdev->dev, sizeof(struct dw_i2c_dev), GFP_KERNEL); ++ dev = devm_kzalloc(device, sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + +- dev->flags = (uintptr_t)device_get_match_data(&pdev->dev); +- if (device_property_present(&pdev->dev, "wx,i2c-snps-model")) ++ dev->flags = (uintptr_t)device_get_match_data(device); ++ if (device_property_present(device, "wx,i2c-snps-model")) + dev->flags = MODEL_WANGXUN_SP | ACCESS_POLLING; + +- dev->dev = &pdev->dev; ++ dev->dev = device; + dev->irq = irq; + platform_set_drvdata(pdev, dev); + +@@ -229,7 +230,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) + if (ret) + return ret; + +- dev->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); ++ dev->rst = devm_reset_control_get_optional_exclusive(device, NULL); + if (IS_ERR(dev->rst)) + return PTR_ERR(dev->rst); + +@@ -246,13 +247,13 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) + i2c_dw_configure(dev); + + /* Optional interface clock */ +- dev->pclk = devm_clk_get_optional(&pdev->dev, "pclk"); ++ dev->pclk = devm_clk_get_optional(device, "pclk"); + if (IS_ERR(dev->pclk)) { + ret = PTR_ERR(dev->pclk); + goto exit_reset; + } + +- dev->clk = devm_clk_get_optional(&pdev->dev, NULL); ++ dev->clk = devm_clk_get_optional(device, NULL); + if (IS_ERR(dev->clk)) { + ret = PTR_ERR(dev->clk); + goto exit_reset; +@@ -280,28 +281,24 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) + I2C_CLASS_HWMON : I2C_CLASS_DEPRECATED; + adap->nr = -1; + +- if (dev->flags & ACCESS_NO_IRQ_SUSPEND) { +- dev_pm_set_driver_flags(&pdev->dev, +- DPM_FLAG_SMART_PREPARE); +- } else { +- dev_pm_set_driver_flags(&pdev->dev, +- DPM_FLAG_SMART_PREPARE | +- DPM_FLAG_SMART_SUSPEND); +- } ++ if (dev->flags & ACCESS_NO_IRQ_SUSPEND) ++ dev_pm_set_driver_flags(device, DPM_FLAG_SMART_PREPARE); ++ else ++ dev_pm_set_driver_flags(device, DPM_FLAG_SMART_PREPARE | DPM_FLAG_SMART_SUSPEND); + +- device_enable_async_suspend(&pdev->dev); ++ device_enable_async_suspend(device); + + /* The code below assumes runtime PM to be disabled. */ +- WARN_ON(pm_runtime_enabled(&pdev->dev)); ++ WARN_ON(pm_runtime_enabled(device)); + +- pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); +- pm_runtime_use_autosuspend(&pdev->dev); +- pm_runtime_set_active(&pdev->dev); ++ pm_runtime_set_autosuspend_delay(device, 1000); ++ pm_runtime_use_autosuspend(device); ++ pm_runtime_set_active(device); + + if (dev->shared_with_punit) +- pm_runtime_get_noresume(&pdev->dev); ++ pm_runtime_get_noresume(device); + +- pm_runtime_enable(&pdev->dev); ++ pm_runtime_enable(device); + + ret = i2c_dw_probe(dev); + if (ret) +@@ -319,15 +316,16 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) + static void dw_i2c_plat_remove(struct platform_device *pdev) + { + struct dw_i2c_dev *dev = platform_get_drvdata(pdev); ++ struct device *device = &pdev->dev; + +- pm_runtime_get_sync(&pdev->dev); ++ pm_runtime_get_sync(device); + + i2c_del_adapter(&dev->adapter); + + i2c_dw_disable(dev); + +- pm_runtime_dont_use_autosuspend(&pdev->dev); +- pm_runtime_put_sync(&pdev->dev); ++ pm_runtime_dont_use_autosuspend(device); ++ pm_runtime_put_sync(device); + dw_i2c_plat_pm_cleanup(dev); + + i2c_dw_remove_lock_support(dev); +-- +2.39.5 + diff --git a/queue-6.12/i2c-pxa-fix-call-balance-of-i2c-clk-handling-routine.patch b/queue-6.12/i2c-pxa-fix-call-balance-of-i2c-clk-handling-routine.patch new file mode 100644 index 0000000000..46087e3623 --- /dev/null +++ b/queue-6.12/i2c-pxa-fix-call-balance-of-i2c-clk-handling-routine.patch @@ -0,0 +1,41 @@ +From a4b2d247e183c0496bb024c5e264587c8a3d1b15 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 20:28:03 +0300 +Subject: i2c: pxa: fix call balance of i2c->clk handling routines + +From: Vitalii Mordan + +[ Upstream commit be7113d2e2a6f20cbee99c98d261a1fd6fd7b549 ] + +If the clock i2c->clk was not enabled in i2c_pxa_probe(), it should not be +disabled in any path. + +Found by Linux Verification Center (linuxtesting.org) with Klever. + +Signed-off-by: Vitalii Mordan +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20250212172803.1422136-1-mordan@ispras.ru +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-pxa.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c +index 4d76e71cdd4be..afc1a8171f59e 100644 +--- a/drivers/i2c/busses/i2c-pxa.c ++++ b/drivers/i2c/busses/i2c-pxa.c +@@ -1503,7 +1503,10 @@ static int i2c_pxa_probe(struct platform_device *dev) + i2c->adap.name); + } + +- clk_prepare_enable(i2c->clk); ++ ret = clk_prepare_enable(i2c->clk); ++ if (ret) ++ return dev_err_probe(&dev->dev, ret, ++ "failed to enable clock\n"); + + if (i2c->use_pio) { + i2c->adap.algo = &i2c_pxa_pio_algorithm; +-- +2.39.5 + diff --git a/queue-6.12/i2c-qup-vote-for-interconnect-bandwidth-to-dram.patch b/queue-6.12/i2c-qup-vote-for-interconnect-bandwidth-to-dram.patch new file mode 100644 index 0000000000..1141fb4537 --- /dev/null +++ b/queue-6.12/i2c-qup-vote-for-interconnect-bandwidth-to-dram.patch @@ -0,0 +1,139 @@ +From d0cc26edaddd09ee9814c7f4ce5aefa5aad10095 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Nov 2023 10:48:37 +0100 +Subject: i2c: qup: Vote for interconnect bandwidth to DRAM + +From: Stephan Gerhold + +[ Upstream commit d4f35233a6345f62637463ef6e0708f44ffaa583 ] + +When the I2C QUP controller is used together with a DMA engine it needs +to vote for the interconnect path to the DRAM. Otherwise it may be +unable to access the memory quickly enough. + +The requested peak bandwidth is dependent on the I2C core clock. + +To avoid sending votes too often the bandwidth is always requested when +a DMA transfer starts, but dropped only on runtime suspend. Runtime +suspend should only happen if no transfer is active. After resumption we +can defer the next vote until the first DMA transfer actually happens. + +The implementation is largely identical to the one introduced for +spi-qup in commit ecdaa9473019 ("spi: qup: Vote for interconnect +bandwidth to DRAM") since both drivers represent the same hardware +block. + +Signed-off-by: Stephan Gerhold +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20231128-i2c-qup-dvfs-v1-3-59a0e3039111@kernkonzept.com +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-qup.c | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c +index d480162a4d394..eb97abcb4cd33 100644 +--- a/drivers/i2c/busses/i2c-qup.c ++++ b/drivers/i2c/busses/i2c-qup.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -150,6 +151,8 @@ + /* TAG length for DATA READ in RX FIFO */ + #define READ_RX_TAGS_LEN 2 + ++#define QUP_BUS_WIDTH 8 ++ + static unsigned int scl_freq; + module_param_named(scl_freq, scl_freq, uint, 0444); + MODULE_PARM_DESC(scl_freq, "SCL frequency override"); +@@ -227,6 +230,7 @@ struct qup_i2c_dev { + int irq; + struct clk *clk; + struct clk *pclk; ++ struct icc_path *icc_path; + struct i2c_adapter adap; + + int clk_ctl; +@@ -255,6 +259,10 @@ struct qup_i2c_dev { + /* To configure when bus is in run state */ + u32 config_run; + ++ /* bandwidth votes */ ++ u32 src_clk_freq; ++ u32 cur_bw_clk_freq; ++ + /* dma parameters */ + bool is_dma; + /* To check if the current transfer is using DMA */ +@@ -453,6 +461,23 @@ static int qup_i2c_bus_active(struct qup_i2c_dev *qup, int len) + return ret; + } + ++static int qup_i2c_vote_bw(struct qup_i2c_dev *qup, u32 clk_freq) ++{ ++ u32 needed_peak_bw; ++ int ret; ++ ++ if (qup->cur_bw_clk_freq == clk_freq) ++ return 0; ++ ++ needed_peak_bw = Bps_to_icc(clk_freq * QUP_BUS_WIDTH); ++ ret = icc_set_bw(qup->icc_path, 0, needed_peak_bw); ++ if (ret) ++ return ret; ++ ++ qup->cur_bw_clk_freq = clk_freq; ++ return 0; ++} ++ + static void qup_i2c_write_tx_fifo_v1(struct qup_i2c_dev *qup) + { + struct qup_i2c_block *blk = &qup->blk; +@@ -838,6 +863,10 @@ static int qup_i2c_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, + int ret = 0; + int idx = 0; + ++ ret = qup_i2c_vote_bw(qup, qup->src_clk_freq); ++ if (ret) ++ return ret; ++ + enable_irq(qup->irq); + ret = qup_i2c_req_dma(qup); + +@@ -1643,6 +1672,7 @@ static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup) + config = readl(qup->base + QUP_CONFIG); + config |= QUP_CLOCK_AUTO_GATE; + writel(config, qup->base + QUP_CONFIG); ++ qup_i2c_vote_bw(qup, 0); + clk_disable_unprepare(qup->pclk); + } + +@@ -1743,6 +1773,11 @@ static int qup_i2c_probe(struct platform_device *pdev) + goto fail_dma; + } + qup->is_dma = true; ++ ++ qup->icc_path = devm_of_icc_get(&pdev->dev, NULL); ++ if (IS_ERR(qup->icc_path)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(qup->icc_path), ++ "failed to get interconnect path\n"); + } + + nodma: +@@ -1791,6 +1826,7 @@ static int qup_i2c_probe(struct platform_device *pdev) + qup_i2c_enable_clocks(qup); + src_clk_freq = clk_get_rate(qup->clk); + } ++ qup->src_clk_freq = src_clk_freq; + + /* + * Bootloaders might leave a pending interrupt on certain QUP's, +-- +2.39.5 + diff --git a/queue-6.12/i3c-master-svc-fix-missing-stop-for-master-request.patch b/queue-6.12/i3c-master-svc-fix-missing-stop-for-master-request.patch new file mode 100644 index 0000000000..dacca7df2e --- /dev/null +++ b/queue-6.12/i3c-master-svc-fix-missing-stop-for-master-request.patch @@ -0,0 +1,37 @@ +From 33e496dc56a478c35961feca37f8186487c14c63 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 13:36:06 +0800 +Subject: i3c: master: svc: Fix missing STOP for master request + +From: Stanley Chu + +[ Upstream commit 0430bf9bc1ac068c8b8c540eb93e5751872efc51 ] + +The controller driver nacked the master request but didn't emit a +STOP to end the transaction. The driver shall refuse the unsupported +requests and return the controller state to IDLE by emitting a STOP. + +Signed-off-by: Stanley Chu +Reviewed-by: Frank Li +Link: https://lore.kernel.org/r/20250318053606.3087121-4-yschu@nuvoton.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + drivers/i3c/master/svc-i3c-master.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c +index 7911814ad82ac..6ffe022dbb5b4 100644 +--- a/drivers/i3c/master/svc-i3c-master.c ++++ b/drivers/i3c/master/svc-i3c-master.c +@@ -511,6 +511,7 @@ static void svc_i3c_master_ibi_work(struct work_struct *work) + queue_work(master->base.wq, &master->hj_work); + break; + case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST: ++ svc_i3c_master_emit_stop(master); + default: + break; + } +-- +2.39.5 + diff --git a/queue-6.12/i3c-master-svc-flush-fifo-before-sending-dynamic-add.patch b/queue-6.12/i3c-master-svc-flush-fifo-before-sending-dynamic-add.patch new file mode 100644 index 0000000000..46096afdea --- /dev/null +++ b/queue-6.12/i3c-master-svc-flush-fifo-before-sending-dynamic-add.patch @@ -0,0 +1,40 @@ +From bd6843098dd9387bfb4ac0751947f5fab62f06a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 11:22:50 -0500 +Subject: i3c: master: svc: Flush FIFO before sending Dynamic Address + Assignment(DAA) + +From: Frank Li + +[ Upstream commit a892ee4cf22a50e1d6988d0464a9a421f3e5db2f ] + +Ensure the FIFO is empty before issuing the DAA command to prevent +incorrect command data from being sent. Align with other data transfers, +such as svc_i3c_master_start_xfer_locked(), which flushes the FIFO before +sending a command. + +Signed-off-by: Frank Li +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20250129162250.3629189-1-Frank.Li@nxp.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + drivers/i3c/master/svc-i3c-master.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c +index 6ffe022dbb5b4..62913feae45dd 100644 +--- a/drivers/i3c/master/svc-i3c-master.c ++++ b/drivers/i3c/master/svc-i3c-master.c +@@ -860,6 +860,8 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master, + u32 reg; + int ret, i; + ++ svc_i3c_master_flush_fifo(master); ++ + while (true) { + /* SVC_I3C_MCTRL_REQUEST_PROC_DAA have two mode, ENTER DAA or PROCESS DAA. + * +-- +2.39.5 + diff --git a/queue-6.12/ice-count-combined-queues-using-rx-tx-count.patch b/queue-6.12/ice-count-combined-queues-using-rx-tx-count.patch new file mode 100644 index 0000000000..4df72268b3 --- /dev/null +++ b/queue-6.12/ice-count-combined-queues-using-rx-tx-count.patch @@ -0,0 +1,40 @@ +From 32e4baee8897e12275fa0d89993399642eb23617 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Dec 2024 07:58:09 +0100 +Subject: ice: count combined queues using Rx/Tx count + +From: Michal Swiatkowski + +[ Upstream commit c3a392bdd31adc474f1009ee85c13fdd01fe800d ] + +Previous implementation assumes that there is 1:1 matching between +vectors and queues. It isn't always true. + +Get minimum value from Rx/Tx queues to determine combined queues number. + +Reviewed-by: Jacob Keller +Tested-by: Pucha Himasekhar Reddy +Signed-off-by: Michal Swiatkowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_ethtool.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c +index 7d1feeb317be3..2a2acbeb57221 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c +@@ -3817,8 +3817,7 @@ static u32 ice_get_combined_cnt(struct ice_vsi *vsi) + ice_for_each_q_vector(vsi, q_idx) { + struct ice_q_vector *q_vector = vsi->q_vectors[q_idx]; + +- if (q_vector->rx.rx_ring && q_vector->tx.tx_ring) +- combined++; ++ combined += min(q_vector->num_ring_tx, q_vector->num_ring_rx); + } + + return combined; +-- +2.39.5 + diff --git a/queue-6.12/ice-init-flow-director-before-rdma.patch b/queue-6.12/ice-init-flow-director-before-rdma.patch new file mode 100644 index 0000000000..465a2a6e06 --- /dev/null +++ b/queue-6.12/ice-init-flow-director-before-rdma.patch @@ -0,0 +1,60 @@ +From 3b3bdec990892ad9e6640a641a7c93f50784d881 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Dec 2024 07:58:17 +0100 +Subject: ice: init flow director before RDMA + +From: Michal Swiatkowski + +[ Upstream commit d67627e7b53203ca150e54723abbed81a0716286 ] + +Flow director needs only one MSI-X. Load it before RDMA to save MSI-X +for it. + +Reviewed-by: Jacob Keller +Tested-by: Pucha Himasekhar Reddy +Signed-off-by: Michal Swiatkowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_main.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index ca707dfcb286e..63d2105fce933 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -5175,11 +5175,12 @@ int ice_load(struct ice_pf *pf) + + ice_napi_add(vsi); + ++ ice_init_features(pf); ++ + err = ice_init_rdma(pf); + if (err) + goto err_init_rdma; + +- ice_init_features(pf); + ice_service_task_restart(pf); + + clear_bit(ICE_DOWN, pf->state); +@@ -5187,6 +5188,7 @@ int ice_load(struct ice_pf *pf) + return 0; + + err_init_rdma: ++ ice_deinit_features(pf); + ice_tc_indir_block_unregister(vsi); + err_tc_indir_block_register: + ice_unregister_netdev(vsi); +@@ -5210,8 +5212,8 @@ void ice_unload(struct ice_pf *pf) + + devl_assert_locked(priv_to_devlink(pf)); + +- ice_deinit_features(pf); + ice_deinit_rdma(pf); ++ ice_deinit_features(pf); + ice_tc_indir_block_unregister(vsi); + ice_unregister_netdev(vsi); + ice_devlink_destroy_pf_port(pf); +-- +2.39.5 + diff --git a/queue-6.12/ice-treat-dyn_allowed-only-as-suggestion.patch b/queue-6.12/ice-treat-dyn_allowed-only-as-suggestion.patch new file mode 100644 index 0000000000..df8ef5e832 --- /dev/null +++ b/queue-6.12/ice-treat-dyn_allowed-only-as-suggestion.patch @@ -0,0 +1,133 @@ +From 0bff30fa0536333140573016852755dc1abbc2d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Dec 2024 07:58:14 +0100 +Subject: ice: treat dyn_allowed only as suggestion + +From: Michal Swiatkowski + +[ Upstream commit a8c2d3932c1106af2764cc6869b29bcf3cb5bc47 ] + +It can be needed to have some MSI-X allocated as static and rest as +dynamic. For example on PF VSI. We want to always have minimum one MSI-X +on it, because of that it is allocated as a static one, rest can be +dynamic if it is supported. + +Change the ice_get_irq_res() to allow using static entries if they are +free even if caller wants dynamic one. + +Adjust limit values to the new approach. Min and max in limit means the +values that are valid, so decrease max and num_static by one. + +Set vsi::irq_dyn_alloc if dynamic allocation is supported. + +Reviewed-by: Jacob Keller +Reviewed-by: Wojciech Drewek +Tested-by: Pucha Himasekhar Reddy +Signed-off-by: Michal Swiatkowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_irq.c | 25 ++++++++++++------------ + drivers/net/ethernet/intel/ice/ice_lib.c | 2 ++ + 2 files changed, 15 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_irq.c b/drivers/net/ethernet/intel/ice/ice_irq.c +index ad82ff7d19957..09f9c7ba52795 100644 +--- a/drivers/net/ethernet/intel/ice/ice_irq.c ++++ b/drivers/net/ethernet/intel/ice/ice_irq.c +@@ -45,7 +45,7 @@ static void ice_free_irq_res(struct ice_pf *pf, u16 index) + /** + * ice_get_irq_res - get an interrupt resource + * @pf: board private structure +- * @dyn_only: force entry to be dynamically allocated ++ * @dyn_allowed: allow entry to be dynamically allocated + * + * Allocate new irq entry in the free slot of the tracker. Since xarray + * is used, always allocate new entry at the lowest possible index. Set +@@ -53,11 +53,12 @@ static void ice_free_irq_res(struct ice_pf *pf, u16 index) + * + * Returns allocated irq entry or NULL on failure. + */ +-static struct ice_irq_entry *ice_get_irq_res(struct ice_pf *pf, bool dyn_only) ++static struct ice_irq_entry *ice_get_irq_res(struct ice_pf *pf, ++ bool dyn_allowed) + { +- struct xa_limit limit = { .max = pf->irq_tracker.num_entries, ++ struct xa_limit limit = { .max = pf->irq_tracker.num_entries - 1, + .min = 0 }; +- unsigned int num_static = pf->irq_tracker.num_static; ++ unsigned int num_static = pf->irq_tracker.num_static - 1; + struct ice_irq_entry *entry; + unsigned int index; + int ret; +@@ -66,9 +67,9 @@ static struct ice_irq_entry *ice_get_irq_res(struct ice_pf *pf, bool dyn_only) + if (!entry) + return NULL; + +- /* skip preallocated entries if the caller says so */ +- if (dyn_only) +- limit.min = num_static; ++ /* only already allocated if the caller says so */ ++ if (!dyn_allowed) ++ limit.max = num_static; + + ret = xa_alloc(&pf->irq_tracker.entries, &index, entry, limit, + GFP_KERNEL); +@@ -78,7 +79,7 @@ static struct ice_irq_entry *ice_get_irq_res(struct ice_pf *pf, bool dyn_only) + entry = NULL; + } else { + entry->index = index; +- entry->dynamic = index >= num_static; ++ entry->dynamic = index > num_static; + } + + return entry; +@@ -272,7 +273,7 @@ int ice_init_interrupt_scheme(struct ice_pf *pf) + /** + * ice_alloc_irq - Allocate new interrupt vector + * @pf: board private structure +- * @dyn_only: force dynamic allocation of the interrupt ++ * @dyn_allowed: allow dynamic allocation of the interrupt + * + * Allocate new interrupt vector for a given owner id. + * return struct msi_map with interrupt details and track +@@ -285,20 +286,20 @@ int ice_init_interrupt_scheme(struct ice_pf *pf) + * interrupt will be allocated with pci_msix_alloc_irq_at. + * + * Some callers may only support dynamically allocated interrupts. +- * This is indicated with dyn_only flag. ++ * This is indicated with dyn_allowed flag. + * + * On failure, return map with negative .index. The caller + * is expected to check returned map index. + * + */ +-struct msi_map ice_alloc_irq(struct ice_pf *pf, bool dyn_only) ++struct msi_map ice_alloc_irq(struct ice_pf *pf, bool dyn_allowed) + { + int sriov_base_vector = pf->sriov_base_vector; + struct msi_map map = { .index = -ENOENT }; + struct device *dev = ice_pf_to_dev(pf); + struct ice_irq_entry *entry; + +- entry = ice_get_irq_res(pf, dyn_only); ++ entry = ice_get_irq_res(pf, dyn_allowed); + if (!entry) + return map; + +diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c +index 121a5ad5c8e10..8961eebe67aa2 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_lib.c +@@ -567,6 +567,8 @@ ice_vsi_alloc_def(struct ice_vsi *vsi, struct ice_channel *ch) + return -ENOMEM; + } + ++ vsi->irq_dyn_alloc = pci_msix_can_alloc_dyn(vsi->back->pdev); ++ + switch (vsi->type) { + case ICE_VSI_PF: + case ICE_VSI_SF: +-- +2.39.5 + diff --git a/queue-6.12/ieee802154-ca8210-use-proper-setters-and-getters-for.patch b/queue-6.12/ieee802154-ca8210-use-proper-setters-and-getters-for.patch new file mode 100644 index 0000000000..cd18f2b9dd --- /dev/null +++ b/queue-6.12/ieee802154-ca8210-use-proper-setters-and-getters-for.patch @@ -0,0 +1,77 @@ +From 88d8c797cfb1d1bfcd59c4387f16fd75d3221099 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 12:55:34 +0200 +Subject: ieee802154: ca8210: Use proper setters and getters for bitwise types + +From: Andy Shevchenko + +[ Upstream commit 169b2262205836a5d1213ff44dca2962276bece1 ] + +Sparse complains that the driver doesn't respect the bitwise types: + +drivers/net/ieee802154/ca8210.c:1796:27: warning: incorrect type in assignment (different base types) +drivers/net/ieee802154/ca8210.c:1796:27: expected restricted __le16 [addressable] [assigned] [usertype] pan_id +drivers/net/ieee802154/ca8210.c:1796:27: got unsigned short [usertype] +drivers/net/ieee802154/ca8210.c:1801:25: warning: incorrect type in assignment (different base types) +drivers/net/ieee802154/ca8210.c:1801:25: expected restricted __le16 [addressable] [assigned] [usertype] pan_id +drivers/net/ieee802154/ca8210.c:1801:25: got unsigned short [usertype] +drivers/net/ieee802154/ca8210.c:1928:28: warning: incorrect type in argument 3 (different base types) +drivers/net/ieee802154/ca8210.c:1928:28: expected unsigned short [usertype] dst_pan_id +drivers/net/ieee802154/ca8210.c:1928:28: got restricted __le16 [addressable] [usertype] pan_id + +Use proper setters and getters for bitwise types. + +Note, in accordance with [1] the protocol is little endian. + +Link: https://www.cascoda.com/wp-content/uploads/2018/11/CA-8210_datasheet_0418.pdf [1] +Reviewed-by: Miquel Raynal +Reviewed-by: Linus Walleij +Signed-off-by: Andy Shevchenko +Link: https://lore.kernel.org/20250305105656.2133487-2-andriy.shevchenko@linux.intel.com +Signed-off-by: Stefan Schmidt +Signed-off-by: Sasha Levin +--- + drivers/net/ieee802154/ca8210.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c +index 753215ebc67c7..a036910f60828 100644 +--- a/drivers/net/ieee802154/ca8210.c ++++ b/drivers/net/ieee802154/ca8210.c +@@ -1446,8 +1446,7 @@ static u8 mcps_data_request( + command.pdata.data_req.src_addr_mode = src_addr_mode; + command.pdata.data_req.dst.mode = dst_address_mode; + if (dst_address_mode != MAC_MODE_NO_ADDR) { +- command.pdata.data_req.dst.pan_id[0] = LS_BYTE(dst_pan_id); +- command.pdata.data_req.dst.pan_id[1] = MS_BYTE(dst_pan_id); ++ put_unaligned_le16(dst_pan_id, command.pdata.data_req.dst.pan_id); + if (dst_address_mode == MAC_MODE_SHORT_ADDR) { + command.pdata.data_req.dst.address[0] = LS_BYTE( + dst_addr->short_address +@@ -1795,12 +1794,12 @@ static int ca8210_skb_rx( + } + hdr.source.mode = data_ind[0]; + dev_dbg(&priv->spi->dev, "srcAddrMode: %#03x\n", hdr.source.mode); +- hdr.source.pan_id = *(u16 *)&data_ind[1]; ++ hdr.source.pan_id = cpu_to_le16(get_unaligned_le16(&data_ind[1])); + dev_dbg(&priv->spi->dev, "srcPanId: %#06x\n", hdr.source.pan_id); + memcpy(&hdr.source.extended_addr, &data_ind[3], 8); + hdr.dest.mode = data_ind[11]; + dev_dbg(&priv->spi->dev, "dstAddrMode: %#03x\n", hdr.dest.mode); +- hdr.dest.pan_id = *(u16 *)&data_ind[12]; ++ hdr.dest.pan_id = cpu_to_le16(get_unaligned_le16(&data_ind[12])); + dev_dbg(&priv->spi->dev, "dstPanId: %#06x\n", hdr.dest.pan_id); + memcpy(&hdr.dest.extended_addr, &data_ind[14], 8); + +@@ -1927,7 +1926,7 @@ static int ca8210_skb_tx( + status = mcps_data_request( + header.source.mode, + header.dest.mode, +- header.dest.pan_id, ++ le16_to_cpu(header.dest.pan_id), + (union macaddr *)&header.dest.extended_addr, + skb->len - mac_len, + &skb->data[mac_len], +-- +2.39.5 + diff --git a/queue-6.12/iio-adc-ad7944-don-t-use-storagebits-for-sizing.patch b/queue-6.12/iio-adc-ad7944-don-t-use-storagebits-for-sizing.patch new file mode 100644 index 0000000000..301d2028bf --- /dev/null +++ b/queue-6.12/iio-adc-ad7944-don-t-use-storagebits-for-sizing.patch @@ -0,0 +1,98 @@ +From 080c265ca08391f072576bfca58f2bff5980ae98 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 14:09:07 -0600 +Subject: iio: adc: ad7944: don't use storagebits for sizing + +From: David Lechner + +[ Upstream commit 503d20ed8cf7c7b40ec0bd94f53c490c1d91c31b ] + +Replace use of storagebits with realbits for determining the number of +bytes needed for SPI transfers. + +When adding SPI offload support, storagebits will always be 32 rather +than 16 for 16-bit 16-bit chips so we can no longer rely on storagebits +being the correct size expected by the SPI framework (it always uses +4 bytes for > 16-bit xfers and 2 bytes for > 8-bit xfers). Instead, +derive the correct size from realbits since it will always be correct +even when SPI offloading is used. + +Reviewed-by: Jonathan Cameron +Reviewed-vy: Nuno Sa +Signed-off-by: David Lechner +Link: https://patch.msgid.link/20250207-dlech-mainline-spi-engine-offload-2-v8-10-e48a489be48c@baylibre.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/ad7944.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/drivers/iio/adc/ad7944.c b/drivers/iio/adc/ad7944.c +index 0f36138a71445..58a25792cec37 100644 +--- a/drivers/iio/adc/ad7944.c ++++ b/drivers/iio/adc/ad7944.c +@@ -98,6 +98,9 @@ struct ad7944_chip_info { + const struct iio_chan_spec channels[2]; + }; + ++/* get number of bytes for SPI xfer */ ++#define AD7944_SPI_BYTES(scan_type) ((scan_type).realbits > 16 ? 4 : 2) ++ + /* + * AD7944_DEFINE_CHIP_INFO - Define a chip info structure for a specific chip + * @_name: The name of the chip +@@ -164,7 +167,7 @@ static int ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc * + + /* Then we can read the data during the acquisition phase */ + xfers[2].rx_buf = &adc->sample.raw; +- xfers[2].len = BITS_TO_BYTES(chan->scan_type.storagebits); ++ xfers[2].len = AD7944_SPI_BYTES(chan->scan_type); + xfers[2].bits_per_word = chan->scan_type.realbits; + + spi_message_init_with_transfers(&adc->msg, xfers, 3); +@@ -193,7 +196,7 @@ static int ad7944_4wire_mode_init_msg(struct device *dev, struct ad7944_adc *adc + xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS; + + xfers[1].rx_buf = &adc->sample.raw; +- xfers[1].len = BITS_TO_BYTES(chan->scan_type.storagebits); ++ xfers[1].len = AD7944_SPI_BYTES(chan->scan_type); + xfers[1].bits_per_word = chan->scan_type.realbits; + + spi_message_init_with_transfers(&adc->msg, xfers, 2); +@@ -228,7 +231,7 @@ static int ad7944_chain_mode_init_msg(struct device *dev, struct ad7944_adc *adc + xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS; + + xfers[1].rx_buf = adc->chain_mode_buf; +- xfers[1].len = BITS_TO_BYTES(chan->scan_type.storagebits) * n_chain_dev; ++ xfers[1].len = AD7944_SPI_BYTES(chan->scan_type) * n_chain_dev; + xfers[1].bits_per_word = chan->scan_type.realbits; + + spi_message_init_with_transfers(&adc->msg, xfers, 2); +@@ -274,12 +277,12 @@ static int ad7944_single_conversion(struct ad7944_adc *adc, + return ret; + + if (adc->spi_mode == AD7944_SPI_MODE_CHAIN) { +- if (chan->scan_type.storagebits > 16) ++ if (chan->scan_type.realbits > 16) + *val = ((u32 *)adc->chain_mode_buf)[chan->scan_index]; + else + *val = ((u16 *)adc->chain_mode_buf)[chan->scan_index]; + } else { +- if (chan->scan_type.storagebits > 16) ++ if (chan->scan_type.realbits > 16) + *val = adc->sample.raw.u32; + else + *val = adc->sample.raw.u16; +@@ -409,8 +412,7 @@ static int ad7944_chain_mode_alloc(struct device *dev, + /* 1 word for each voltage channel + aligned u64 for timestamp */ + + chain_mode_buf_size = ALIGN(n_chain_dev * +- BITS_TO_BYTES(chan[0].scan_type.storagebits), sizeof(u64)) +- + sizeof(u64); ++ AD7944_SPI_BYTES(chan[0].scan_type), sizeof(u64)) + sizeof(u64); + buf = devm_kzalloc(dev, chain_mode_buf_size, GFP_KERNEL); + if (!buf) + return -ENOMEM; +-- +2.39.5 + diff --git a/queue-6.12/ima-process_measurement-needlessly-takes-inode_lock-.patch b/queue-6.12/ima-process_measurement-needlessly-takes-inode_lock-.patch new file mode 100644 index 0000000000..14a9ba9712 --- /dev/null +++ b/queue-6.12/ima-process_measurement-needlessly-takes-inode_lock-.patch @@ -0,0 +1,43 @@ +From b06d09c6ca135751a3feda0d7e3131db20583566 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Mar 2025 11:09:11 -0500 +Subject: ima: process_measurement() needlessly takes inode_lock() on MAY_READ + +From: Frederick Lawler + +[ Upstream commit 30d68cb0c37ebe2dc63aa1d46a28b9163e61caa2 ] + +On IMA policy update, if a measure rule exists in the policy, +IMA_MEASURE is set for ima_policy_flags which makes the violation_check +variable always true. Coupled with a no-action on MAY_READ for a +FILE_CHECK call, we're always taking the inode_lock(). + +This becomes a performance problem for extremely heavy read-only workloads. +Therefore, prevent this only in the case there's no action to be taken. + +Signed-off-by: Frederick Lawler +Acked-by: Roberto Sassu +Signed-off-by: Mimi Zohar +Signed-off-by: Sasha Levin +--- + security/integrity/ima/ima_main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c +index a9aab10bebcaa..2f3f267e72167 100644 +--- a/security/integrity/ima/ima_main.c ++++ b/security/integrity/ima/ima_main.c +@@ -245,7 +245,9 @@ static int process_measurement(struct file *file, const struct cred *cred, + &allowed_algos); + violation_check = ((func == FILE_CHECK || func == MMAP_CHECK || + func == MMAP_CHECK_REQPROT) && +- (ima_policy_flag & IMA_MEASURE)); ++ (ima_policy_flag & IMA_MEASURE) && ++ ((action & IMA_MEASURE) || ++ (file->f_mode & FMODE_WRITE))); + if (!action && !violation_check) + return 0; + +-- +2.39.5 + diff --git a/queue-6.12/intel_th-avoid-using-deprecated-page-mapping-index-f.patch b/queue-6.12/intel_th-avoid-using-deprecated-page-mapping-index-f.patch new file mode 100644 index 0000000000..17cdd6b10b --- /dev/null +++ b/queue-6.12/intel_th-avoid-using-deprecated-page-mapping-index-f.patch @@ -0,0 +1,145 @@ +From cac19d703186f4d2e0b6f35bff3eafd1a669d0df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Mar 2025 13:56:08 +0100 +Subject: intel_th: avoid using deprecated page->mapping, index fields + +From: Lorenzo Stoakes + +[ Upstream commit 8e553520596bbd5ce832e26e9d721e6a0c797b8b ] + +The struct page->mapping, index fields are deprecated and soon to be only +available as part of a folio. + +It is likely the intel_th code which sets page->mapping, index is was +implemented out of concern that some aspect of the page fault logic may +encounter unexpected problems should they not. + +However, the appropriate interface for inserting kernel-allocated memory is +vm_insert_page() in a VM_MIXEDMAP. By using the helper function +vmf_insert_mixed() we can do this with minimal churn in the existing fault +handler. + +By doing so, we bypass the remainder of the faulting logic. The pages are +still pinned so there is no possibility of anything unexpected being done +with the pages once established. + +It would also be reasonable to pre-map everything on fault, however to +minimise churn we retain the fault handler. + +We also eliminate all code which clears page->mapping on teardown as this +has now become unnecessary. + +The MSU code relies on faulting to function correctly, so is by definition +dependent on CONFIG_MMU. We avoid spurious reports about compilation +failure for unsupported platforms by making this requirement explicit in +Kconfig as part of this change too. + +Signed-off-by: Lorenzo Stoakes +Acked-by: Alexander Shishkin +Link: https://lore.kernel.org/r/20250331125608.60300-1-lorenzo.stoakes@oracle.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/hwtracing/intel_th/Kconfig | 1 + + drivers/hwtracing/intel_th/msu.c | 31 +++++++----------------------- + 2 files changed, 8 insertions(+), 24 deletions(-) + +diff --git a/drivers/hwtracing/intel_th/Kconfig b/drivers/hwtracing/intel_th/Kconfig +index 4b6359326ede9..4f7d2b6d79e29 100644 +--- a/drivers/hwtracing/intel_th/Kconfig ++++ b/drivers/hwtracing/intel_th/Kconfig +@@ -60,6 +60,7 @@ config INTEL_TH_STH + + config INTEL_TH_MSU + tristate "Intel(R) Trace Hub Memory Storage Unit" ++ depends on MMU + help + Memory Storage Unit (MSU) trace output device enables + storing STP traces to system memory. It supports single +diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c +index 66123d684ac9e..93b65a9731d72 100644 +--- a/drivers/hwtracing/intel_th/msu.c ++++ b/drivers/hwtracing/intel_th/msu.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + #ifdef CONFIG_X86 + #include +@@ -967,7 +968,6 @@ static void msc_buffer_contig_free(struct msc *msc) + for (off = 0; off < msc->nr_pages << PAGE_SHIFT; off += PAGE_SIZE) { + struct page *page = virt_to_page(msc->base + off); + +- page->mapping = NULL; + __free_page(page); + } + +@@ -1149,9 +1149,6 @@ static void __msc_buffer_win_free(struct msc *msc, struct msc_window *win) + int i; + + for_each_sg(win->sgt->sgl, sg, win->nr_segs, i) { +- struct page *page = msc_sg_page(sg); +- +- page->mapping = NULL; + dma_free_coherent(msc_dev(win->msc)->parent->parent, PAGE_SIZE, + sg_virt(sg), sg_dma_address(sg)); + } +@@ -1592,22 +1589,10 @@ static void msc_mmap_close(struct vm_area_struct *vma) + { + struct msc_iter *iter = vma->vm_file->private_data; + struct msc *msc = iter->msc; +- unsigned long pg; + + if (!atomic_dec_and_mutex_lock(&msc->mmap_count, &msc->buf_mutex)) + return; + +- /* drop page _refcounts */ +- for (pg = 0; pg < msc->nr_pages; pg++) { +- struct page *page = msc_buffer_get_page(msc, pg); +- +- if (WARN_ON_ONCE(!page)) +- continue; +- +- if (page->mapping) +- page->mapping = NULL; +- } +- + /* last mapping -- drop user_count */ + atomic_dec(&msc->user_count); + mutex_unlock(&msc->buf_mutex); +@@ -1617,16 +1602,14 @@ static vm_fault_t msc_mmap_fault(struct vm_fault *vmf) + { + struct msc_iter *iter = vmf->vma->vm_file->private_data; + struct msc *msc = iter->msc; ++ struct page *page; + +- vmf->page = msc_buffer_get_page(msc, vmf->pgoff); +- if (!vmf->page) ++ page = msc_buffer_get_page(msc, vmf->pgoff); ++ if (!page) + return VM_FAULT_SIGBUS; + +- get_page(vmf->page); +- vmf->page->mapping = vmf->vma->vm_file->f_mapping; +- vmf->page->index = vmf->pgoff; +- +- return 0; ++ get_page(page); ++ return vmf_insert_mixed(vmf->vma, vmf->address, page_to_pfn_t(page)); + } + + static const struct vm_operations_struct msc_mmap_ops = { +@@ -1667,7 +1650,7 @@ static int intel_th_msc_mmap(struct file *file, struct vm_area_struct *vma) + atomic_dec(&msc->user_count); + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); +- vm_flags_set(vma, VM_DONTEXPAND | VM_DONTCOPY); ++ vm_flags_set(vma, VM_DONTEXPAND | VM_DONTCOPY | VM_MIXEDMAP); + vma->vm_ops = &msc_mmap_ops; + return ret; + } +-- +2.39.5 + diff --git a/queue-6.12/io_uring-don-t-duplicate-flushing-in-io_req_post_cqe.patch b/queue-6.12/io_uring-don-t-duplicate-flushing-in-io_req_post_cqe.patch new file mode 100644 index 0000000000..05a64ea0ce --- /dev/null +++ b/queue-6.12/io_uring-don-t-duplicate-flushing-in-io_req_post_cqe.patch @@ -0,0 +1,47 @@ +From 5b4b7f9d492b3a3267af896852bd735cba2440d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Apr 2025 12:28:39 +0100 +Subject: io_uring: don't duplicate flushing in io_req_post_cqe + +From: Pavel Begunkov + +[ Upstream commit 5e16f1a68d28965c12b6fa227a306fef8a680f84 ] + +io_req_post_cqe() sets submit_state.cq_flush so that +*flush_completions() can take care of batch commiting CQEs. Don't commit +it twice by using __io_cq_unlock_post(). + +Signed-off-by: Pavel Begunkov +Link: https://lore.kernel.org/r/41c416660c509cee676b6cad96081274bcb459f3.1745493861.git.asml.silence@gmail.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/io_uring.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index 8ef0603c07f11..985c87ea09a90 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -874,10 +874,15 @@ bool io_req_post_cqe(struct io_kiocb *req, s32 res, u32 cflags) + lockdep_assert(!io_wq_current_is_worker()); + lockdep_assert_held(&ctx->uring_lock); + +- __io_cq_lock(ctx); +- posted = io_fill_cqe_aux(ctx, req->cqe.user_data, res, cflags); ++ if (!ctx->lockless_cq) { ++ spin_lock(&ctx->completion_lock); ++ posted = io_fill_cqe_aux(ctx, req->cqe.user_data, res, cflags); ++ spin_unlock(&ctx->completion_lock); ++ } else { ++ posted = io_fill_cqe_aux(ctx, req->cqe.user_data, res, cflags); ++ } ++ + ctx->submit_state.cq_flush = true; +- __io_cq_unlock_post(ctx); + return posted; + } + +-- +2.39.5 + diff --git a/queue-6.12/io_uring-fdinfo-annotate-racy-sq-cq-head-tail-reads.patch b/queue-6.12/io_uring-fdinfo-annotate-racy-sq-cq-head-tail-reads.patch new file mode 100644 index 0000000000..89ef545e46 --- /dev/null +++ b/queue-6.12/io_uring-fdinfo-annotate-racy-sq-cq-head-tail-reads.patch @@ -0,0 +1,47 @@ +From a4f2a220136145e6d285703465b26447f1dc4235 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Apr 2025 07:17:17 -0600 +Subject: io_uring/fdinfo: annotate racy sq/cq head/tail reads + +From: Jens Axboe + +[ Upstream commit f024d3a8ded0d8d2129ae123d7a5305c29ca44ce ] + +syzbot complains about the cached sq head read, and it's totally right. +But we don't need to care, it's just reading fdinfo, and reading the +CQ or SQ tail/head entries are known racy in that they are just a view +into that very instant and may of course be outdated by the time they +are reported. + +Annotate both the SQ head and CQ tail read with data_race() to avoid +this syzbot complaint. + +Link: https://lore.kernel.org/io-uring/6811f6dc.050a0220.39e3a1.0d0e.GAE@google.com/ +Reported-by: syzbot+3e77fd302e99f5af9394@syzkaller.appspotmail.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/fdinfo.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/io_uring/fdinfo.c b/io_uring/fdinfo.c +index 6b1247664b355..ecdbe473a49f7 100644 +--- a/io_uring/fdinfo.c ++++ b/io_uring/fdinfo.c +@@ -83,11 +83,11 @@ __cold void io_uring_show_fdinfo(struct seq_file *m, struct file *file) + seq_printf(m, "SqMask:\t0x%x\n", sq_mask); + seq_printf(m, "SqHead:\t%u\n", sq_head); + seq_printf(m, "SqTail:\t%u\n", sq_tail); +- seq_printf(m, "CachedSqHead:\t%u\n", ctx->cached_sq_head); ++ seq_printf(m, "CachedSqHead:\t%u\n", data_race(ctx->cached_sq_head)); + seq_printf(m, "CqMask:\t0x%x\n", cq_mask); + seq_printf(m, "CqHead:\t%u\n", cq_head); + seq_printf(m, "CqTail:\t%u\n", cq_tail); +- seq_printf(m, "CachedCqTail:\t%u\n", ctx->cached_cq_tail); ++ seq_printf(m, "CachedCqTail:\t%u\n", data_race(ctx->cached_cq_tail)); + seq_printf(m, "SQEs:\t%u\n", sq_tail - sq_head); + sq_entries = min(sq_tail - sq_head, ctx->sq_entries); + for (i = 0; i < sq_entries; i++) { +-- +2.39.5 + diff --git a/queue-6.12/io_uring-msg-initialise-msg-request-opcode.patch b/queue-6.12/io_uring-msg-initialise-msg-request-opcode.patch new file mode 100644 index 0000000000..a69a2cc478 --- /dev/null +++ b/queue-6.12/io_uring-msg-initialise-msg-request-opcode.patch @@ -0,0 +1,36 @@ +From 666701a2c1b6774fd20220e1f5cc5b81529f7bc0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Mar 2025 23:11:50 +0000 +Subject: io_uring/msg: initialise msg request opcode + +From: Pavel Begunkov + +[ Upstream commit 9cc0bbdaba2a66ad90bc6ce45163b7745baffe98 ] + +It's risky to have msg request opcode set to garbage, so at least +initialise it to nop. Later we might want to add a user inaccessible +opcode for such cases. + +Signed-off-by: Pavel Begunkov +Link: https://lore.kernel.org/r/9afe650fcb348414a4529d89f52eb8969ba06efd.1743190078.git.asml.silence@gmail.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/msg_ring.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/io_uring/msg_ring.c b/io_uring/msg_ring.c +index 7fd9badcfaf81..35b1b585e9cbe 100644 +--- a/io_uring/msg_ring.c ++++ b/io_uring/msg_ring.c +@@ -94,6 +94,7 @@ static int io_msg_remote_post(struct io_ring_ctx *ctx, struct io_kiocb *req, + kmem_cache_free(req_cachep, req); + return -EOWNERDEAD; + } ++ req->opcode = IORING_OP_NOP; + req->cqe.user_data = user_data; + io_req_set_res(req, res, cflags); + percpu_ref_get(&ctx->refs); +-- +2.39.5 + diff --git a/queue-6.12/iommu-amd-pgtbl_v2-improve-error-handling.patch b/queue-6.12/iommu-amd-pgtbl_v2-improve-error-handling.patch new file mode 100644 index 0000000000..ef1d93d6af --- /dev/null +++ b/queue-6.12/iommu-amd-pgtbl_v2-improve-error-handling.patch @@ -0,0 +1,36 @@ +From 4b04cce2a9c3856638252801d1f2360903718a35 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 16:23:16 +0000 +Subject: iommu/amd/pgtbl_v2: Improve error handling + +From: Vasant Hegde + +[ Upstream commit 36a1cfd497435ba5e37572fe9463bb62a7b1b984 ] + +Return -ENOMEM if v2_alloc_pte() fails to allocate memory. + +Signed-off-by: Vasant Hegde +Reviewed-by: Jason Gunthorpe +Link: https://lore.kernel.org/r/20250227162320.5805-4-vasant.hegde@amd.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/io_pgtable_v2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iommu/amd/io_pgtable_v2.c b/drivers/iommu/amd/io_pgtable_v2.c +index c616de2c5926e..a56a273963059 100644 +--- a/drivers/iommu/amd/io_pgtable_v2.c ++++ b/drivers/iommu/amd/io_pgtable_v2.c +@@ -254,7 +254,7 @@ static int iommu_v2_map_pages(struct io_pgtable_ops *ops, unsigned long iova, + pte = v2_alloc_pte(cfg->amd.nid, pgtable->pgd, + iova, map_size, gfp, &updated); + if (!pte) { +- ret = -EINVAL; ++ ret = -ENOMEM; + goto out; + } + +-- +2.39.5 + diff --git a/queue-6.12/iommu-keep-dev-iommu-state-consistent.patch b/queue-6.12/iommu-keep-dev-iommu-state-consistent.patch new file mode 100644 index 0000000000..67ce0be129 --- /dev/null +++ b/queue-6.12/iommu-keep-dev-iommu-state-consistent.patch @@ -0,0 +1,88 @@ +From 73525cebeb5f7fd3ffdf6567abaf794632c593de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 15:46:32 +0000 +Subject: iommu: Keep dev->iommu state consistent + +From: Robin Murphy + +[ Upstream commit 3832862eb9c4dfa0e80b2522bfaedbc8a43de97d ] + +At the moment, if of_iommu_configure() allocates dev->iommu itself via +iommu_fwspec_init(), then suffers a DT parsing failure, it cleans up the +fwspec but leaves the empty dev_iommu hanging around. So far this is +benign (if a tiny bit wasteful), but we'd like to be able to reason +about dev->iommu having a consistent and unambiguous lifecycle. Thus +make sure that the of_iommu cleanup undoes precisely whatever it did. + +Signed-off-by: Robin Murphy +Reviewed-by: Jason Gunthorpe +Link: https://lore.kernel.org/r/d219663a3f23001f23d520a883ac622d70b4e642.1740753261.git.robin.murphy@arm.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/iommu-priv.h | 2 ++ + drivers/iommu/iommu.c | 2 +- + drivers/iommu/of_iommu.c | 6 +++++- + 3 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/iommu/iommu-priv.h b/drivers/iommu/iommu-priv.h +index de5b54eaa8bf1..a5913c0b02a0a 100644 +--- a/drivers/iommu/iommu-priv.h ++++ b/drivers/iommu/iommu-priv.h +@@ -17,6 +17,8 @@ static inline const struct iommu_ops *dev_iommu_ops(struct device *dev) + return dev->iommu->iommu_dev->ops; + } + ++void dev_iommu_free(struct device *dev); ++ + const struct iommu_ops *iommu_ops_from_fwnode(const struct fwnode_handle *fwnode); + + static inline const struct iommu_ops *iommu_fwspec_ops(struct iommu_fwspec *fwspec) +diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c +index cac3dce111689..879009adef407 100644 +--- a/drivers/iommu/iommu.c ++++ b/drivers/iommu/iommu.c +@@ -347,7 +347,7 @@ static struct dev_iommu *dev_iommu_get(struct device *dev) + return param; + } + +-static void dev_iommu_free(struct device *dev) ++void dev_iommu_free(struct device *dev) + { + struct dev_iommu *param = dev->iommu; + +diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c +index e7a6a1611d193..e3fcab925a547 100644 +--- a/drivers/iommu/of_iommu.c ++++ b/drivers/iommu/of_iommu.c +@@ -118,6 +118,7 @@ static void of_pci_check_device_ats(struct device *dev, struct device_node *np) + int of_iommu_configure(struct device *dev, struct device_node *master_np, + const u32 *id) + { ++ bool dev_iommu_present; + int err; + + if (!master_np) +@@ -129,6 +130,7 @@ int of_iommu_configure(struct device *dev, struct device_node *master_np, + mutex_unlock(&iommu_probe_device_lock); + return 0; + } ++ dev_iommu_present = dev->iommu; + + /* + * We don't currently walk up the tree looking for a parent IOMMU. +@@ -149,8 +151,10 @@ int of_iommu_configure(struct device *dev, struct device_node *master_np, + err = of_iommu_configure_device(master_np, dev, id); + } + +- if (err) ++ if (err && dev_iommu_present) + iommu_fwspec_free(dev); ++ else if (err && dev->iommu) ++ dev_iommu_free(dev); + mutex_unlock(&iommu_probe_device_lock); + + if (!err && dev->bus) +-- +2.39.5 + diff --git a/queue-6.12/iommu-vt-d-move-scalable-mode-ats-enablement-to-prob.patch b/queue-6.12/iommu-vt-d-move-scalable-mode-ats-enablement-to-prob.patch new file mode 100644 index 0000000000..2e126b180e --- /dev/null +++ b/queue-6.12/iommu-vt-d-move-scalable-mode-ats-enablement-to-prob.patch @@ -0,0 +1,165 @@ +From 45bad9afb01cf09b1301a08c8e036758f4560543 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 10:47:47 +0800 +Subject: iommu/vt-d: Move scalable mode ATS enablement to probe path + +From: Lu Baolu + +[ Upstream commit 5518f239aff1baf772c5748da3add7243c5fb5df ] + +Device ATS is currently enabled when a domain is attached to the device +and disabled when the domain is detached. This creates a limitation: +when the IOMMU is operating in scalable mode and IOPF is enabled, the +device's domain cannot be changed. + +The previous code enables ATS when a domain is set to a device's RID and +disables it during RID domain switch. So, if a PASID is set with a +domain requiring PRI, ATS should remain enabled until the domain is +removed. During the PASID domain's lifecycle, if the RID's domain +changes, PRI will be disrupted because it depends on ATS, which is +disabled when the blocking domain is set for the device's RID. + +Remove this limitation by moving ATS enablement to the device probe path. + +Signed-off-by: Lu Baolu +Reviewed-by: Kevin Tian +Tested-by: Zhangfei Gao +Link: https://lore.kernel.org/r/20250228092631.3425464-5-baolu.lu@linux.intel.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/intel/iommu.c | 51 ++++++++++++++++++++----------------- + 1 file changed, 27 insertions(+), 24 deletions(-) + +diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c +index 157542c07aaaf..737f33cddc43f 100644 +--- a/drivers/iommu/intel/iommu.c ++++ b/drivers/iommu/intel/iommu.c +@@ -1284,32 +1284,28 @@ static bool dev_needs_extra_dtlb_flush(struct pci_dev *pdev) + return true; + } + +-static void iommu_enable_pci_caps(struct device_domain_info *info) ++static void iommu_enable_pci_ats(struct device_domain_info *info) + { + struct pci_dev *pdev; + +- if (!dev_is_pci(info->dev)) ++ if (!info->ats_supported) + return; + + pdev = to_pci_dev(info->dev); +- if (info->ats_supported && pci_ats_page_aligned(pdev) && +- !pci_enable_ats(pdev, VTD_PAGE_SHIFT)) ++ if (!pci_ats_page_aligned(pdev)) ++ return; ++ ++ if (!pci_enable_ats(pdev, VTD_PAGE_SHIFT)) + info->ats_enabled = 1; + } + +-static void iommu_disable_pci_caps(struct device_domain_info *info) ++static void iommu_disable_pci_ats(struct device_domain_info *info) + { +- struct pci_dev *pdev; +- +- if (!dev_is_pci(info->dev)) ++ if (!info->ats_enabled) + return; + +- pdev = to_pci_dev(info->dev); +- +- if (info->ats_enabled) { +- pci_disable_ats(pdev); +- info->ats_enabled = 0; +- } ++ pci_disable_ats(to_pci_dev(info->dev)); ++ info->ats_enabled = 0; + } + + static void intel_flush_iotlb_all(struct iommu_domain *domain) +@@ -1722,12 +1718,19 @@ domain_context_mapping(struct dmar_domain *domain, struct device *dev) + struct device_domain_info *info = dev_iommu_priv_get(dev); + struct intel_iommu *iommu = info->iommu; + u8 bus = info->bus, devfn = info->devfn; ++ int ret; + + if (!dev_is_pci(dev)) + return domain_context_mapping_one(domain, iommu, bus, devfn); + +- return pci_for_each_dma_alias(to_pci_dev(dev), +- domain_context_mapping_cb, domain); ++ ret = pci_for_each_dma_alias(to_pci_dev(dev), ++ domain_context_mapping_cb, domain); ++ if (ret) ++ return ret; ++ ++ iommu_enable_pci_ats(info); ++ ++ return 0; + } + + /* Return largest possible superpage level for a given mapping */ +@@ -1987,8 +1990,6 @@ static int dmar_domain_attach_device(struct dmar_domain *domain, + if (ret) + goto out_block_translation; + +- iommu_enable_pci_caps(info); +- + ret = cache_tag_assign_domain(domain, dev, IOMMU_NO_PASID); + if (ret) + goto out_block_translation; +@@ -3368,6 +3369,7 @@ static void domain_context_clear(struct device_domain_info *info) + + pci_for_each_dma_alias(to_pci_dev(info->dev), + &domain_context_clear_one_cb, info); ++ iommu_disable_pci_ats(info); + } + + /* +@@ -3384,7 +3386,6 @@ void device_block_translation(struct device *dev) + if (info->domain) + cache_tag_unassign_domain(info->domain, dev, IOMMU_NO_PASID); + +- iommu_disable_pci_caps(info); + if (!dev_is_real_dma_subdevice(dev)) { + if (sm_supported(iommu)) + intel_pasid_tear_down_entry(iommu, dev, +@@ -3964,6 +3965,9 @@ static struct iommu_device *intel_iommu_probe_device(struct device *dev) + !pci_enable_pasid(pdev, info->pasid_supported & ~1)) + info->pasid_enabled = 1; + ++ if (sm_supported(iommu)) ++ iommu_enable_pci_ats(info); ++ + return &iommu->iommu; + free_table: + intel_pasid_free_table(dev); +@@ -3980,6 +3984,8 @@ static void intel_iommu_release_device(struct device *dev) + struct device_domain_info *info = dev_iommu_priv_get(dev); + struct intel_iommu *iommu = info->iommu; + ++ iommu_disable_pci_ats(info); ++ + if (info->pasid_enabled) { + pci_disable_pasid(to_pci_dev(dev)); + info->pasid_enabled = 0; +@@ -4581,13 +4587,10 @@ static int identity_domain_attach_dev(struct iommu_domain *domain, struct device + if (dev_is_real_dma_subdevice(dev)) + return 0; + +- if (sm_supported(iommu)) { ++ if (sm_supported(iommu)) + ret = intel_pasid_setup_pass_through(iommu, dev, IOMMU_NO_PASID); +- if (!ret) +- iommu_enable_pci_caps(info); +- } else { ++ else + ret = device_setup_pass_through(dev); +- } + + return ret; + } +-- +2.39.5 + diff --git a/queue-6.12/iommufd-disallow-allocating-nested-parent-domain-wit.patch b/queue-6.12/iommufd-disallow-allocating-nested-parent-domain-wit.patch new file mode 100644 index 0000000000..51f817f3eb --- /dev/null +++ b/queue-6.12/iommufd-disallow-allocating-nested-parent-domain-wit.patch @@ -0,0 +1,63 @@ +From c3dd9ce314ac02f6a3e638d6a00723ef18760c73 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 02:40:12 -0800 +Subject: iommufd: Disallow allocating nested parent domain with fault ID + +From: Yi Liu + +[ Upstream commit 1062d81086156e42878d701b816d2f368b53a77c ] + +Allocating a domain with a fault ID indicates that the domain is faultable. +However, there is a gap for the nested parent domain to support PRI. Some +hardware lacks the capability to distinguish whether PRI occurs at stage 1 +or stage 2. This limitation may require software-based page table walking +to resolve. Since no in-tree IOMMU driver currently supports this +functionality, it is disallowed. For more details, refer to the related +discussion at [1]. + +[1] https://lore.kernel.org/linux-iommu/bd1655c6-8b2f-4cfa-adb1-badc00d01811@intel.com/ + +Link: https://patch.msgid.link/r/20250226104012.82079-1-yi.l.liu@intel.com +Suggested-by: Lu Baolu +Signed-off-by: Yi Liu +Reviewed-by: Kevin Tian +Reviewed-by: Lu Baolu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/iommu/iommufd/hw_pagetable.c | 3 +++ + tools/testing/selftests/iommu/iommufd.c | 4 ++++ + 2 files changed, 7 insertions(+) + +diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c +index d06bf6e6c19fd..2454627a8b61b 100644 +--- a/drivers/iommu/iommufd/hw_pagetable.c ++++ b/drivers/iommu/iommufd/hw_pagetable.c +@@ -122,6 +122,9 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas, + if ((flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING) && + !device_iommu_capable(idev->dev, IOMMU_CAP_DIRTY_TRACKING)) + return ERR_PTR(-EOPNOTSUPP); ++ if ((flags & IOMMU_HWPT_FAULT_ID_VALID) && ++ (flags & IOMMU_HWPT_ALLOC_NEST_PARENT)) ++ return ERR_PTR(-EOPNOTSUPP); + + hwpt_paging = __iommufd_object_alloc( + ictx, hwpt_paging, IOMMUFD_OBJ_HWPT_PAGING, common.obj); +diff --git a/tools/testing/selftests/iommu/iommufd.c b/tools/testing/selftests/iommu/iommufd.c +index 4927b9add5add..06f252733660a 100644 +--- a/tools/testing/selftests/iommu/iommufd.c ++++ b/tools/testing/selftests/iommu/iommufd.c +@@ -289,6 +289,10 @@ TEST_F(iommufd_ioas, alloc_hwpt_nested) + &test_hwpt_id); + test_err_hwpt_alloc(EINVAL, self->device_id, self->device_id, 0, + &test_hwpt_id); ++ test_err_hwpt_alloc(EOPNOTSUPP, self->device_id, self->ioas_id, ++ IOMMU_HWPT_ALLOC_NEST_PARENT | ++ IOMMU_HWPT_FAULT_ID_VALID, ++ &test_hwpt_id); + + test_cmd_hwpt_alloc(self->device_id, self->ioas_id, + IOMMU_HWPT_ALLOC_NEST_PARENT, +-- +2.39.5 + diff --git a/queue-6.12/iommufd-extend-iommu_get_hw_info-to-report-pasid-cap.patch b/queue-6.12/iommufd-extend-iommu_get_hw_info-to-report-pasid-cap.patch new file mode 100644 index 0000000000..3251881851 --- /dev/null +++ b/queue-6.12/iommufd-extend-iommu_get_hw_info-to-report-pasid-cap.patch @@ -0,0 +1,197 @@ +From e60f7337211d074862bef142bb68c72fd510a4c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 11:01:42 -0700 +Subject: iommufd: Extend IOMMU_GET_HW_INFO to report PASID capability + +From: Yi Liu + +[ Upstream commit 803f97298e7de9242eb677a1351dcafbbcc9117e ] + +PASID usage requires PASID support in both device and IOMMU. Since the +iommu drivers always enable the PASID capability for the device if it +is supported, this extends the IOMMU_GET_HW_INFO to report the PASID +capability to userspace. Also, enhances the selftest accordingly. + +Link: https://patch.msgid.link/r/20250321180143.8468-5-yi.l.liu@intel.com +Cc: Bjorn Helgaas +Reviewed-by: Kevin Tian +Reviewed-by: Jason Gunthorpe +Tested-by: Zhangfei Gao #aarch64 platform +Tested-by: Nicolin Chen +Signed-off-by: Yi Liu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/iommu/iommufd/device.c | 34 +++++++++++++++++++++++++++++++++- + drivers/pci/ats.c | 33 +++++++++++++++++++++++++++++++++ + include/linux/pci-ats.h | 3 +++ + include/uapi/linux/iommufd.h | 14 +++++++++++++- + 4 files changed, 82 insertions(+), 2 deletions(-) + +diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c +index 3fd8920e79ffb..74480ae6bfc0b 100644 +--- a/drivers/iommu/iommufd/device.c ++++ b/drivers/iommu/iommufd/device.c +@@ -3,6 +3,7 @@ + */ + #include + #include ++#include + #include + #include + +@@ -1304,7 +1305,8 @@ int iommufd_get_hw_info(struct iommufd_ucmd *ucmd) + void *data; + int rc; + +- if (cmd->flags || cmd->__reserved) ++ if (cmd->flags || cmd->__reserved[0] || cmd->__reserved[1] || ++ cmd->__reserved[2]) + return -EOPNOTSUPP; + + idev = iommufd_get_device(ucmd, cmd->dev_id); +@@ -1361,6 +1363,36 @@ int iommufd_get_hw_info(struct iommufd_ucmd *ucmd) + if (device_iommu_capable(idev->dev, IOMMU_CAP_DIRTY_TRACKING)) + cmd->out_capabilities |= IOMMU_HW_CAP_DIRTY_TRACKING; + ++ cmd->out_max_pasid_log2 = 0; ++ /* ++ * Currently, all iommu drivers enable PASID in the probe_device() ++ * op if iommu and device supports it. So the max_pasids stored in ++ * dev->iommu indicates both PASID support and enable status. A ++ * non-zero dev->iommu->max_pasids means PASID is supported and ++ * enabled. The iommufd only reports PASID capability to userspace ++ * if it's enabled. ++ */ ++ if (idev->dev->iommu->max_pasids) { ++ cmd->out_max_pasid_log2 = ilog2(idev->dev->iommu->max_pasids); ++ ++ if (dev_is_pci(idev->dev)) { ++ struct pci_dev *pdev = to_pci_dev(idev->dev); ++ int ctrl; ++ ++ ctrl = pci_pasid_status(pdev); ++ ++ WARN_ON_ONCE(ctrl < 0 || ++ !(ctrl & PCI_PASID_CTRL_ENABLE)); ++ ++ if (ctrl & PCI_PASID_CTRL_EXEC) ++ cmd->out_capabilities |= ++ IOMMU_HW_CAP_PCI_PASID_EXEC; ++ if (ctrl & PCI_PASID_CTRL_PRIV) ++ cmd->out_capabilities |= ++ IOMMU_HW_CAP_PCI_PASID_PRIV; ++ } ++ } ++ + rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd)); + out_free: + kfree(data); +diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c +index 6afff1f1b1430..c331b108e71de 100644 +--- a/drivers/pci/ats.c ++++ b/drivers/pci/ats.c +@@ -538,4 +538,37 @@ int pci_max_pasids(struct pci_dev *pdev) + return (1 << FIELD_GET(PCI_PASID_CAP_WIDTH, supported)); + } + EXPORT_SYMBOL_GPL(pci_max_pasids); ++ ++/** ++ * pci_pasid_status - Check the PASID status ++ * @pdev: PCI device structure ++ * ++ * Returns a negative value when no PASID capability is present. ++ * Otherwise the value of the control register is returned. ++ * Status reported are: ++ * ++ * PCI_PASID_CTRL_ENABLE - PASID enabled ++ * PCI_PASID_CTRL_EXEC - Execute permission enabled ++ * PCI_PASID_CTRL_PRIV - Privileged mode enabled ++ */ ++int pci_pasid_status(struct pci_dev *pdev) ++{ ++ int pasid; ++ u16 ctrl; ++ ++ if (pdev->is_virtfn) ++ pdev = pci_physfn(pdev); ++ ++ pasid = pdev->pasid_cap; ++ if (!pasid) ++ return -EINVAL; ++ ++ pci_read_config_word(pdev, pasid + PCI_PASID_CTRL, &ctrl); ++ ++ ctrl &= PCI_PASID_CTRL_ENABLE | PCI_PASID_CTRL_EXEC | ++ PCI_PASID_CTRL_PRIV; ++ ++ return ctrl; ++} ++EXPORT_SYMBOL_GPL(pci_pasid_status); + #endif /* CONFIG_PCI_PASID */ +diff --git a/include/linux/pci-ats.h b/include/linux/pci-ats.h +index 0e8b74e63767a..75c6c86cf09dc 100644 +--- a/include/linux/pci-ats.h ++++ b/include/linux/pci-ats.h +@@ -42,6 +42,7 @@ int pci_enable_pasid(struct pci_dev *pdev, int features); + void pci_disable_pasid(struct pci_dev *pdev); + int pci_pasid_features(struct pci_dev *pdev); + int pci_max_pasids(struct pci_dev *pdev); ++int pci_pasid_status(struct pci_dev *pdev); + #else /* CONFIG_PCI_PASID */ + static inline int pci_enable_pasid(struct pci_dev *pdev, int features) + { return -EINVAL; } +@@ -50,6 +51,8 @@ static inline int pci_pasid_features(struct pci_dev *pdev) + { return -EINVAL; } + static inline int pci_max_pasids(struct pci_dev *pdev) + { return -EINVAL; } ++static inline int pci_pasid_status(struct pci_dev *pdev) ++{ return -EINVAL; } + #endif /* CONFIG_PCI_PASID */ + + #endif /* LINUX_PCI_ATS_H */ +diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h +index 8c4470742dcd9..41048271a0667 100644 +--- a/include/uapi/linux/iommufd.h ++++ b/include/uapi/linux/iommufd.h +@@ -504,9 +504,17 @@ enum iommu_hw_info_type { + * IOMMU_HWPT_GET_DIRTY_BITMAP + * IOMMU_HWPT_SET_DIRTY_TRACKING + * ++ * @IOMMU_HW_CAP_PCI_PASID_EXEC: Execute Permission Supported, user ignores it ++ * when the struct ++ * iommu_hw_info::out_max_pasid_log2 is zero. ++ * @IOMMU_HW_CAP_PCI_PASID_PRIV: Privileged Mode Supported, user ignores it ++ * when the struct ++ * iommu_hw_info::out_max_pasid_log2 is zero. + */ + enum iommufd_hw_capabilities { + IOMMU_HW_CAP_DIRTY_TRACKING = 1 << 0, ++ IOMMU_HW_CAP_PCI_PASID_EXEC = 1 << 1, ++ IOMMU_HW_CAP_PCI_PASID_PRIV = 1 << 2, + }; + + /** +@@ -522,6 +530,9 @@ enum iommufd_hw_capabilities { + * iommu_hw_info_type. + * @out_capabilities: Output the generic iommu capability info type as defined + * in the enum iommu_hw_capabilities. ++ * @out_max_pasid_log2: Output the width of PASIDs. 0 means no PASID support. ++ * PCI devices turn to out_capabilities to check if the ++ * specific capabilities is supported or not. + * @__reserved: Must be 0 + * + * Query an iommu type specific hardware information data from an iommu behind +@@ -545,7 +556,8 @@ struct iommu_hw_info { + __u32 data_len; + __aligned_u64 data_uptr; + __u32 out_data_type; +- __u32 __reserved; ++ __u8 out_max_pasid_log2; ++ __u8 __reserved[3]; + __aligned_u64 out_capabilities; + }; + #define IOMMU_GET_HW_INFO _IO(IOMMUFD_TYPE, IOMMUFD_CMD_GET_HW_INFO) +-- +2.39.5 + diff --git a/queue-6.12/ip-fib_rules-fetch-net-from-fib_rule-in-fib-46-_rule.patch b/queue-6.12/ip-fib_rules-fetch-net-from-fib_rule-in-fib-46-_rule.patch new file mode 100644 index 0000000000..516d274797 --- /dev/null +++ b/queue-6.12/ip-fib_rules-fetch-net-from-fib_rule-in-fib-46-_rule.patch @@ -0,0 +1,61 @@ +From fa5086f407ec81ade83be1d9942fae8dd5211a25 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 16:24:58 +0900 +Subject: ip: fib_rules: Fetch net from fib_rule in fib[46]_rule_configure(). + +From: Kuniyuki Iwashima + +[ Upstream commit 5a1ccffd30a08f5a2428cd5fbb3ab03e8eb6c66d ] + +The following patch will not set skb->sk from VRF path. + +Let's fetch net from fib_rule->fr_net instead of sock_net(skb->sk) +in fib[46]_rule_configure(). + +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Eric Dumazet +Reviewed-by: Ido Schimmel +Tested-by: Ido Schimmel +Link: https://patch.msgid.link/20250207072502.87775-5-kuniyu@amazon.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/fib_rules.c | 4 ++-- + net/ipv6/fib6_rules.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c +index b07292d50ee76..4563e5303c1a8 100644 +--- a/net/ipv4/fib_rules.c ++++ b/net/ipv4/fib_rules.c +@@ -245,9 +245,9 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, + struct nlattr **tb, + struct netlink_ext_ack *extack) + { +- struct net *net = sock_net(skb->sk); ++ struct fib4_rule *rule4 = (struct fib4_rule *)rule; ++ struct net *net = rule->fr_net; + int err = -EINVAL; +- struct fib4_rule *rule4 = (struct fib4_rule *) rule; + + if (!inet_validate_dscp(frh->tos)) { + NL_SET_ERR_MSG(extack, +diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c +index 04a9ed5e8310f..29185c9ebd020 100644 +--- a/net/ipv6/fib6_rules.c ++++ b/net/ipv6/fib6_rules.c +@@ -365,9 +365,9 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, + struct nlattr **tb, + struct netlink_ext_ack *extack) + { ++ struct fib6_rule *rule6 = (struct fib6_rule *)rule; ++ struct net *net = rule->fr_net; + int err = -EINVAL; +- struct net *net = sock_net(skb->sk); +- struct fib6_rule *rule6 = (struct fib6_rule *) rule; + + if (!inet_validate_dscp(frh->tos)) { + NL_SET_ERR_MSG(extack, +-- +2.39.5 + diff --git a/queue-6.12/ipv4-fib-move-fib_valid_key_len-to-rtm_to_fib_config.patch b/queue-6.12/ipv4-fib-move-fib_valid_key_len-to-rtm_to_fib_config.patch new file mode 100644 index 0000000000..2bb14ee8d6 --- /dev/null +++ b/queue-6.12/ipv4-fib-move-fib_valid_key_len-to-rtm_to_fib_config.patch @@ -0,0 +1,128 @@ +From a020d6a95d8ea59a06788bf69a89048fd5d7b2fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 20:23:27 -0800 +Subject: ipv4: fib: Move fib_valid_key_len() to rtm_to_fib_config(). + +From: Kuniyuki Iwashima + +[ Upstream commit 254ba7e6032d3fc738050d500b0c1d8197af90ca ] + +fib_valid_key_len() is called in the beginning of fib_table_insert() +or fib_table_delete() to check if the prefix length is valid. + +fib_table_insert() and fib_table_delete() are called from 3 paths + + - ip_rt_ioctl() + - inet_rtm_newroute() / inet_rtm_delroute() + - fib_magic() + +In the first ioctl() path, rtentry_to_fib_config() checks the prefix +length with bad_mask(). Also, fib_magic() always passes the correct +prefix: 32 or ifa->ifa_prefixlen, which is already validated. + +Let's move fib_valid_key_len() to the rtnetlink path, rtm_to_fib_config(). + +While at it, 2 direct returns in rtm_to_fib_config() are changed to +goto to match other places in the same function + +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Eric Dumazet +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20250228042328.96624-12-kuniyu@amazon.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/fib_frontend.c | 18 ++++++++++++++++-- + net/ipv4/fib_trie.c | 22 ---------------------- + 2 files changed, 16 insertions(+), 24 deletions(-) + +diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c +index 793e6781399a4..5b7c41333d6fc 100644 +--- a/net/ipv4/fib_frontend.c ++++ b/net/ipv4/fib_frontend.c +@@ -829,19 +829,33 @@ static int rtm_to_fib_config(struct net *net, struct sk_buff *skb, + } + } + ++ if (cfg->fc_dst_len > 32) { ++ NL_SET_ERR_MSG(extack, "Invalid prefix length"); ++ err = -EINVAL; ++ goto errout; ++ } ++ ++ if (cfg->fc_dst_len < 32 && (ntohl(cfg->fc_dst) << cfg->fc_dst_len)) { ++ NL_SET_ERR_MSG(extack, "Invalid prefix for given prefix length"); ++ err = -EINVAL; ++ goto errout; ++ } ++ + if (cfg->fc_nh_id) { + if (cfg->fc_oif || cfg->fc_gw_family || + cfg->fc_encap || cfg->fc_mp) { + NL_SET_ERR_MSG(extack, + "Nexthop specification and nexthop id are mutually exclusive"); +- return -EINVAL; ++ err = -EINVAL; ++ goto errout; + } + } + + if (has_gw && has_via) { + NL_SET_ERR_MSG(extack, + "Nexthop configuration can not contain both GATEWAY and VIA"); +- return -EINVAL; ++ err = -EINVAL; ++ goto errout; + } + + if (!cfg->fc_table) +diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c +index 09e31757e96c7..cc86031d2050f 100644 +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -1193,22 +1193,6 @@ static int fib_insert_alias(struct trie *t, struct key_vector *tp, + return 0; + } + +-static bool fib_valid_key_len(u32 key, u8 plen, struct netlink_ext_ack *extack) +-{ +- if (plen > KEYLENGTH) { +- NL_SET_ERR_MSG(extack, "Invalid prefix length"); +- return false; +- } +- +- if ((plen < KEYLENGTH) && (key << plen)) { +- NL_SET_ERR_MSG(extack, +- "Invalid prefix for given prefix length"); +- return false; +- } +- +- return true; +-} +- + static void fib_remove_alias(struct trie *t, struct key_vector *tp, + struct key_vector *l, struct fib_alias *old); + +@@ -1229,9 +1213,6 @@ int fib_table_insert(struct net *net, struct fib_table *tb, + + key = ntohl(cfg->fc_dst); + +- if (!fib_valid_key_len(key, plen, extack)) +- return -EINVAL; +- + pr_debug("Insert table=%u %08x/%d\n", tb->tb_id, key, plen); + + fi = fib_create_info(cfg, extack); +@@ -1723,9 +1704,6 @@ int fib_table_delete(struct net *net, struct fib_table *tb, + + key = ntohl(cfg->fc_dst); + +- if (!fib_valid_key_len(key, plen, extack)) +- return -EINVAL; +- + l = fib_find_node(t, &tp, key); + if (!l) + return -ESRCH; +-- +2.39.5 + diff --git a/queue-6.12/ipv4-ip_gre-fix-set-but-not-used-warning-in-ipgre_er.patch b/queue-6.12/ipv4-ip_gre-fix-set-but-not-used-warning-in-ipgre_er.patch new file mode 100644 index 0000000000..04d996759c --- /dev/null +++ b/queue-6.12/ipv4-ip_gre-fix-set-but-not-used-warning-in-ipgre_er.patch @@ -0,0 +1,78 @@ +From 34bd9b0c2ee1ea50981dba6a185f953f57b25cc5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 22:36:54 +0100 +Subject: ipv4: ip_gre: Fix set but not used warning in ipgre_err() if + IPv4-only +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Geert Uytterhoeven + +[ Upstream commit 50f37fc2a39c4a8cc4813629b4cf239b71c6097d ] + +if CONFIG_NET_IPGRE is enabled, but CONFIG_IPV6 is disabled: + + net/ipv4/ip_gre.c: In function ‘ipgre_err’: + net/ipv4/ip_gre.c:144:22: error: variable ‘data_len’ set but not used [-Werror=unused-but-set-variable] + 144 | unsigned int data_len = 0; + | ^~~~~~~~ + +Fix this by moving all data_len processing inside the IPV6-only section +that uses its result. + +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202501121007.2GofXmh5-lkp@intel.com/ +Signed-off-by: Geert Uytterhoeven +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/d09113cfe2bfaca02f3dddf832fb5f48dd20958b.1738704881.git.geert@linux-m68k.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/ip_gre.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c +index f1f31ebfc7934..9667f27740258 100644 +--- a/net/ipv4/ip_gre.c ++++ b/net/ipv4/ip_gre.c +@@ -141,7 +141,6 @@ static int ipgre_err(struct sk_buff *skb, u32 info, + const struct iphdr *iph; + const int type = icmp_hdr(skb)->type; + const int code = icmp_hdr(skb)->code; +- unsigned int data_len = 0; + struct ip_tunnel *t; + + if (tpi->proto == htons(ETH_P_TEB)) +@@ -182,7 +181,6 @@ static int ipgre_err(struct sk_buff *skb, u32 info, + case ICMP_TIME_EXCEEDED: + if (code != ICMP_EXC_TTL) + return 0; +- data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */ + break; + + case ICMP_REDIRECT: +@@ -190,10 +188,16 @@ static int ipgre_err(struct sk_buff *skb, u32 info, + } + + #if IS_ENABLED(CONFIG_IPV6) +- if (tpi->proto == htons(ETH_P_IPV6) && +- !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len, +- type, data_len)) +- return 0; ++ if (tpi->proto == htons(ETH_P_IPV6)) { ++ unsigned int data_len = 0; ++ ++ if (type == ICMP_TIME_EXCEEDED) ++ data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */ ++ ++ if (!ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len, ++ type, data_len)) ++ return 0; ++ } + #endif + + if (t->parms.iph.daddr == 0 || +-- +2.39.5 + diff --git a/queue-6.12/ipv6-save-dontfrag-in-cork.patch b/queue-6.12/ipv6-save-dontfrag-in-cork.patch new file mode 100644 index 0000000000..465d96e881 --- /dev/null +++ b/queue-6.12/ipv6-save-dontfrag-in-cork.patch @@ -0,0 +1,103 @@ +From adfc6beaee5df86875b1f94d7d7adad71e98f147 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 22:34:09 -0500 +Subject: ipv6: save dontfrag in cork + +From: Willem de Bruijn + +[ Upstream commit a18dfa9925b9ef6107ea3aa5814ca3c704d34a8a ] + +When spanning datagram construction over multiple send calls using +MSG_MORE, per datagram settings are configured on the first send. + +That is when ip(6)_setup_cork stores these settings for subsequent use +in __ip(6)_append_data and others. + +The only flag that escaped this was dontfrag. As a result, a datagram +could be constructed with df=0 on the first sendmsg, but df=1 on a +next. Which is what cmsg_ip.sh does in an upcoming MSG_MORE test in +the "diff" scenario. + +Changing datagram conditions in the middle of constructing an skb +makes this already complex code path even more convoluted. It is here +unintentional. Bring this flag in line with expected sockopt/cmsg +behavior. + +And stop passing ipc6 to __ip6_append_data, to avoid such issues +in the future. This is already the case for __ip_append_data. + +inet6_cork had a 6 byte hole, so the 1B flag has no impact. + +Signed-off-by: Willem de Bruijn +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20250307033620.411611-3-willemdebruijn.kernel@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/linux/ipv6.h | 1 + + net/ipv6/ip6_output.c | 9 +++++---- + 2 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h +index a6e2aadbb91bd..5aeeed22f35bf 100644 +--- a/include/linux/ipv6.h ++++ b/include/linux/ipv6.h +@@ -207,6 +207,7 @@ struct inet6_cork { + struct ipv6_txoptions *opt; + u8 hop_limit; + u8 tclass; ++ u8 dontfrag:1; + }; + + /* struct ipv6_pinfo - ipv6 private area */ +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 434ddf263b88a..89a61e040e6a1 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1386,6 +1386,7 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork, + } + v6_cork->hop_limit = ipc6->hlimit; + v6_cork->tclass = ipc6->tclass; ++ v6_cork->dontfrag = ipc6->dontfrag; + if (rt->dst.flags & DST_XFRM_TUNNEL) + mtu = READ_ONCE(np->pmtudisc) >= IPV6_PMTUDISC_PROBE ? + READ_ONCE(rt->dst.dev->mtu) : dst_mtu(&rt->dst); +@@ -1417,7 +1418,7 @@ static int __ip6_append_data(struct sock *sk, + int getfrag(void *from, char *to, int offset, + int len, int odd, struct sk_buff *skb), + void *from, size_t length, int transhdrlen, +- unsigned int flags, struct ipcm6_cookie *ipc6) ++ unsigned int flags) + { + struct sk_buff *skb, *skb_prev = NULL; + struct inet_cork *cork = &cork_full->base; +@@ -1471,7 +1472,7 @@ static int __ip6_append_data(struct sock *sk, + if (headersize + transhdrlen > mtu) + goto emsgsize; + +- if (cork->length + length > mtu - headersize && ipc6->dontfrag && ++ if (cork->length + length > mtu - headersize && v6_cork->dontfrag && + (sk->sk_protocol == IPPROTO_UDP || + sk->sk_protocol == IPPROTO_ICMPV6 || + sk->sk_protocol == IPPROTO_RAW)) { +@@ -1843,7 +1844,7 @@ int ip6_append_data(struct sock *sk, + + return __ip6_append_data(sk, &sk->sk_write_queue, &inet->cork, + &np->cork, sk_page_frag(sk), getfrag, +- from, length, transhdrlen, flags, ipc6); ++ from, length, transhdrlen, flags); + } + EXPORT_SYMBOL_GPL(ip6_append_data); + +@@ -2048,7 +2049,7 @@ struct sk_buff *ip6_make_skb(struct sock *sk, + err = __ip6_append_data(sk, &queue, cork, &v6_cork, + ¤t->task_frag, getfrag, from, + length + exthdrlen, transhdrlen + exthdrlen, +- flags, ipc6); ++ flags); + if (err) { + __ip6_flush_pending_frames(sk, &queue, cork, &v6_cork); + return ERR_PTR(err); +-- +2.39.5 + diff --git a/queue-6.12/irqchip-riscv-aplic-add-support-for-hart-indexes.patch b/queue-6.12/irqchip-riscv-aplic-add-support-for-hart-indexes.patch new file mode 100644 index 0000000000..d01657dfed --- /dev/null +++ b/queue-6.12/irqchip-riscv-aplic-add-support-for-hart-indexes.patch @@ -0,0 +1,97 @@ +From 83e6d88a21b3da2fa401429a1daf92ba772e81a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 11:16:37 +0200 +Subject: irqchip/riscv-aplic: Add support for hart indexes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Vladimir Kondratiev + +[ Upstream commit b93afe8a3ac53ae52296d65acfaa9c5f582a48cc ] + +RISC-V APLIC specification defines "hart index" in: + + https://github.com/riscv/riscv-aia + +Within a given interrupt domain, each of the domain’s harts has a unique +index number in the range 0 to 2^14 − 1 (= 16,383). The index number a +domain associates with a hart may or may not have any relationship to the +unique hart identifier (“hart ID”) that the RISC-V Privileged Architecture +assigns to the hart. Two different interrupt domains may employ entirely +different index numbers for the same set of harts. + +Further, this document says in "4.5 Memory-mapped control region for an +interrupt domain": + +The array of IDC structures may include some for potential hart index +numbers that are not actual hart index numbers in the domain. For example, +the first IDC structure is always for hart index 0, but 0 is not +necessarily a valid index number for any hart in the domain. + +Support arbitrary hart indices specified in an optional APLIC property +"riscv,hart-indexes" which is specified as an array of u32 elements, one +per interrupt target. If this property is not specified, fallback to use +logical hart indices within the domain. + +Signed-off-by: Vladimir Kondratiev +Signed-off-by: Thomas Gleixner +Reviewed-by: Anup Patel +Link: https://lore.kernel.org/all/20250129091637.1667279-3-vladimir.kondratiev@mobileye.com +Signed-off-by: Sasha Levin +--- + drivers/irqchip/irq-riscv-aplic-direct.c | 24 +++++++++++++++++++++--- + 1 file changed, 21 insertions(+), 3 deletions(-) + +diff --git a/drivers/irqchip/irq-riscv-aplic-direct.c b/drivers/irqchip/irq-riscv-aplic-direct.c +index 7cd6b646774b9..205ad61d15e49 100644 +--- a/drivers/irqchip/irq-riscv-aplic-direct.c ++++ b/drivers/irqchip/irq-riscv-aplic-direct.c +@@ -31,7 +31,7 @@ struct aplic_direct { + }; + + struct aplic_idc { +- unsigned int hart_index; ++ u32 hart_index; + void __iomem *regs; + struct aplic_direct *direct; + }; +@@ -219,6 +219,20 @@ static int aplic_direct_parse_parent_hwirq(struct device *dev, u32 index, + return 0; + } + ++static int aplic_direct_get_hart_index(struct device *dev, u32 logical_index, ++ u32 *hart_index) ++{ ++ const char *prop_hart_index = "riscv,hart-indexes"; ++ struct device_node *np = to_of_node(dev->fwnode); ++ ++ if (!np || !of_property_present(np, prop_hart_index)) { ++ *hart_index = logical_index; ++ return 0; ++ } ++ ++ return of_property_read_u32_index(np, prop_hart_index, logical_index, hart_index); ++} ++ + int aplic_direct_setup(struct device *dev, void __iomem *regs) + { + int i, j, rc, cpu, current_cpu, setup_count = 0; +@@ -265,8 +279,12 @@ int aplic_direct_setup(struct device *dev, void __iomem *regs) + cpumask_set_cpu(cpu, &direct->lmask); + + idc = per_cpu_ptr(&aplic_idcs, cpu); +- idc->hart_index = i; +- idc->regs = priv->regs + APLIC_IDC_BASE + i * APLIC_IDC_SIZE; ++ rc = aplic_direct_get_hart_index(dev, i, &idc->hart_index); ++ if (rc) { ++ dev_warn(dev, "hart index not found for IDC%d\n", i); ++ continue; ++ } ++ idc->regs = priv->regs + APLIC_IDC_BASE + idc->hart_index * APLIC_IDC_SIZE; + idc->direct = direct; + + aplic_idc_set_delivery(idc, true); +-- +2.39.5 + diff --git a/queue-6.12/irqchip-riscv-imsic-separate-next-and-previous-point.patch b/queue-6.12/irqchip-riscv-imsic-separate-next-and-previous-point.patch new file mode 100644 index 0000000000..45a227d878 --- /dev/null +++ b/queue-6.12/irqchip-riscv-imsic-separate-next-and-previous-point.patch @@ -0,0 +1,274 @@ +From 4b533771d0285f90bfdcfc1330f59275033c083c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:26:53 +0530 +Subject: irqchip/riscv-imsic: Separate next and previous pointers in IMSIC + vector + +From: Anup Patel + +[ Upstream commit 0f67911e821c67ecfccc365a2103ce276a9a56fe ] + +Currently, there is only one "move" pointer in struct imsic_vector so +during vector movement the old vector points to the new vector and new +vector points to itself. + +To support forced cleanup of the old vector, add separate "move_next" and +"move_prev" pointers to struct imsic_vector, where during vector movement +the "move_next" pointer of the old vector points to the new vector and the +"move_prev" pointer of the new vector points to the old vector. + +Both "move_next" and "move_prev" pointers are cleared separately by +__imsic_local_sync() with a restriction that "move_prev" on the new +CPU is cleared only after the old CPU has cleared "move_next". + +Signed-off-by: Anup Patel +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/all/20250217085657.789309-8-apatel@ventanamicro.com +Signed-off-by: Sasha Levin +--- + drivers/irqchip/irq-riscv-imsic-early.c | 8 ++- + drivers/irqchip/irq-riscv-imsic-state.c | 96 +++++++++++++++++-------- + drivers/irqchip/irq-riscv-imsic-state.h | 7 +- + 3 files changed, 78 insertions(+), 33 deletions(-) + +diff --git a/drivers/irqchip/irq-riscv-imsic-early.c b/drivers/irqchip/irq-riscv-imsic-early.c +index c5c2e6929a2f5..b5def6268936e 100644 +--- a/drivers/irqchip/irq-riscv-imsic-early.c ++++ b/drivers/irqchip/irq-riscv-imsic-early.c +@@ -77,6 +77,12 @@ static void imsic_handle_irq(struct irq_desc *desc) + struct imsic_vector *vec; + unsigned long local_id; + ++ /* ++ * Process pending local synchronization instead of waiting ++ * for per-CPU local timer to expire. ++ */ ++ imsic_local_sync_all(false); ++ + chained_irq_enter(chip, desc); + + while ((local_id = csr_swap(CSR_TOPEI, 0))) { +@@ -120,7 +126,7 @@ static int imsic_starting_cpu(unsigned int cpu) + * Interrupts identities might have been enabled/disabled while + * this CPU was not running so sync-up local enable/disable state. + */ +- imsic_local_sync_all(); ++ imsic_local_sync_all(true); + + /* Enable local interrupt delivery */ + imsic_local_delivery(true); +diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c +index b97e6cd89ed74..1aeba76d72795 100644 +--- a/drivers/irqchip/irq-riscv-imsic-state.c ++++ b/drivers/irqchip/irq-riscv-imsic-state.c +@@ -124,10 +124,11 @@ void __imsic_eix_update(unsigned long base_id, unsigned long num_id, bool pend, + } + } + +-static void __imsic_local_sync(struct imsic_local_priv *lpriv) ++static bool __imsic_local_sync(struct imsic_local_priv *lpriv) + { + struct imsic_local_config *mlocal; + struct imsic_vector *vec, *mvec; ++ bool ret = true; + int i; + + lockdep_assert_held(&lpriv->lock); +@@ -143,35 +144,75 @@ static void __imsic_local_sync(struct imsic_local_priv *lpriv) + __imsic_id_clear_enable(i); + + /* +- * If the ID was being moved to a new ID on some other CPU +- * then we can get a MSI during the movement so check the +- * ID pending bit and re-trigger the new ID on other CPU +- * using MMIO write. ++ * Clear the previous vector pointer of the new vector only ++ * after the movement is complete on the old CPU. + */ +- mvec = READ_ONCE(vec->move); +- WRITE_ONCE(vec->move, NULL); +- if (mvec && mvec != vec) { ++ mvec = READ_ONCE(vec->move_prev); ++ if (mvec) { ++ /* ++ * If the old vector has not been updated then ++ * try again in the next sync-up call. ++ */ ++ if (READ_ONCE(mvec->move_next)) { ++ ret = false; ++ continue; ++ } ++ ++ WRITE_ONCE(vec->move_prev, NULL); ++ } ++ ++ /* ++ * If a vector was being moved to a new vector on some other ++ * CPU then we can get a MSI during the movement so check the ++ * ID pending bit and re-trigger the new ID on other CPU using ++ * MMIO write. ++ */ ++ mvec = READ_ONCE(vec->move_next); ++ if (mvec) { + if (__imsic_id_read_clear_pending(i)) { + mlocal = per_cpu_ptr(imsic->global.local, mvec->cpu); + writel_relaxed(mvec->local_id, mlocal->msi_va); + } + ++ WRITE_ONCE(vec->move_next, NULL); + imsic_vector_free(&lpriv->vectors[i]); + } + + skip: + bitmap_clear(lpriv->dirty_bitmap, i, 1); + } ++ ++ return ret; + } + +-void imsic_local_sync_all(void) ++#ifdef CONFIG_SMP ++static void __imsic_local_timer_start(struct imsic_local_priv *lpriv) ++{ ++ lockdep_assert_held(&lpriv->lock); ++ ++ if (!timer_pending(&lpriv->timer)) { ++ lpriv->timer.expires = jiffies + 1; ++ add_timer_on(&lpriv->timer, smp_processor_id()); ++ } ++} ++#else ++static inline void __imsic_local_timer_start(struct imsic_local_priv *lpriv) ++{ ++} ++#endif ++ ++void imsic_local_sync_all(bool force_all) + { + struct imsic_local_priv *lpriv = this_cpu_ptr(imsic->lpriv); + unsigned long flags; + + raw_spin_lock_irqsave(&lpriv->lock, flags); +- bitmap_fill(lpriv->dirty_bitmap, imsic->global.nr_ids + 1); +- __imsic_local_sync(lpriv); ++ ++ if (force_all) ++ bitmap_fill(lpriv->dirty_bitmap, imsic->global.nr_ids + 1); ++ if (!__imsic_local_sync(lpriv)) ++ __imsic_local_timer_start(lpriv); ++ + raw_spin_unlock_irqrestore(&lpriv->lock, flags); + } + +@@ -190,12 +231,7 @@ void imsic_local_delivery(bool enable) + #ifdef CONFIG_SMP + static void imsic_local_timer_callback(struct timer_list *timer) + { +- struct imsic_local_priv *lpriv = this_cpu_ptr(imsic->lpriv); +- unsigned long flags; +- +- raw_spin_lock_irqsave(&lpriv->lock, flags); +- __imsic_local_sync(lpriv); +- raw_spin_unlock_irqrestore(&lpriv->lock, flags); ++ imsic_local_sync_all(false); + } + + static void __imsic_remote_sync(struct imsic_local_priv *lpriv, unsigned int cpu) +@@ -216,14 +252,11 @@ static void __imsic_remote_sync(struct imsic_local_priv *lpriv, unsigned int cpu + */ + if (cpu_online(cpu)) { + if (cpu == smp_processor_id()) { +- __imsic_local_sync(lpriv); +- return; ++ if (__imsic_local_sync(lpriv)) ++ return; + } + +- if (!timer_pending(&lpriv->timer)) { +- lpriv->timer.expires = jiffies + 1; +- add_timer_on(&lpriv->timer, cpu); +- } ++ __imsic_local_timer_start(lpriv); + } + } + #else +@@ -278,8 +311,9 @@ void imsic_vector_unmask(struct imsic_vector *vec) + raw_spin_unlock(&lpriv->lock); + } + +-static bool imsic_vector_move_update(struct imsic_local_priv *lpriv, struct imsic_vector *vec, +- bool new_enable, struct imsic_vector *new_move) ++static bool imsic_vector_move_update(struct imsic_local_priv *lpriv, ++ struct imsic_vector *vec, bool is_old_vec, ++ bool new_enable, struct imsic_vector *move_vec) + { + unsigned long flags; + bool enabled; +@@ -289,7 +323,10 @@ static bool imsic_vector_move_update(struct imsic_local_priv *lpriv, struct imsi + /* Update enable and move details */ + enabled = READ_ONCE(vec->enable); + WRITE_ONCE(vec->enable, new_enable); +- WRITE_ONCE(vec->move, new_move); ++ if (is_old_vec) ++ WRITE_ONCE(vec->move_next, move_vec); ++ else ++ WRITE_ONCE(vec->move_prev, move_vec); + + /* Mark the vector as dirty and synchronize */ + bitmap_set(lpriv->dirty_bitmap, vec->local_id, 1); +@@ -322,8 +359,8 @@ void imsic_vector_move(struct imsic_vector *old_vec, struct imsic_vector *new_ve + * interrupt on the old vector while device was being moved + * to the new vector. + */ +- enabled = imsic_vector_move_update(old_lpriv, old_vec, false, new_vec); +- imsic_vector_move_update(new_lpriv, new_vec, enabled, new_vec); ++ enabled = imsic_vector_move_update(old_lpriv, old_vec, true, false, new_vec); ++ imsic_vector_move_update(new_lpriv, new_vec, false, enabled, old_vec); + } + + #ifdef CONFIG_GENERIC_IRQ_DEBUGFS +@@ -386,7 +423,8 @@ struct imsic_vector *imsic_vector_alloc(unsigned int hwirq, const struct cpumask + vec = &lpriv->vectors[local_id]; + vec->hwirq = hwirq; + vec->enable = false; +- vec->move = NULL; ++ vec->move_next = NULL; ++ vec->move_prev = NULL; + + return vec; + } +diff --git a/drivers/irqchip/irq-riscv-imsic-state.h b/drivers/irqchip/irq-riscv-imsic-state.h +index 391e442808275..f02842b84ed58 100644 +--- a/drivers/irqchip/irq-riscv-imsic-state.h ++++ b/drivers/irqchip/irq-riscv-imsic-state.h +@@ -23,7 +23,8 @@ struct imsic_vector { + unsigned int hwirq; + /* Details accessed using local lock held */ + bool enable; +- struct imsic_vector *move; ++ struct imsic_vector *move_next; ++ struct imsic_vector *move_prev; + }; + + struct imsic_local_priv { +@@ -74,7 +75,7 @@ static inline void __imsic_id_clear_enable(unsigned long id) + __imsic_eix_update(id, 1, false, false); + } + +-void imsic_local_sync_all(void); ++void imsic_local_sync_all(bool force_all); + void imsic_local_delivery(bool enable); + + void imsic_vector_mask(struct imsic_vector *vec); +@@ -87,7 +88,7 @@ static inline bool imsic_vector_isenabled(struct imsic_vector *vec) + + static inline struct imsic_vector *imsic_vector_get_move(struct imsic_vector *vec) + { +- return READ_ONCE(vec->move); ++ return READ_ONCE(vec->move_prev); + } + + void imsic_vector_move(struct imsic_vector *old_vec, struct imsic_vector *new_vec); +-- +2.39.5 + diff --git a/queue-6.12/irqchip-riscv-imsic-set-irq_set_affinity-for-imsic-b.patch b/queue-6.12/irqchip-riscv-imsic-set-irq_set_affinity-for-imsic-b.patch new file mode 100644 index 0000000000..d3ba72788a --- /dev/null +++ b/queue-6.12/irqchip-riscv-imsic-set-irq_set_affinity-for-imsic-b.patch @@ -0,0 +1,85 @@ +From dde029165a50ddad5ef1c1bfec3c9482376c5534 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:26:47 +0530 +Subject: irqchip/riscv-imsic: Set irq_set_affinity() for IMSIC base + +From: Andrew Jones + +[ Upstream commit 999f458c1771354371ba367dd84f55f9a62a4233 ] + +The IMSIC driver assigns the IMSIC domain specific imsic_irq_set_affinity() +callback to the per device leaf MSI domain. That's a layering violation as +it is called with the leaf domain data and not with the IMSIC domain +data. This prevents moving the IMSIC driver to the common MSI library which +uses the generic msi_domain_set_affinity() callback for device MSI domains. + +Instead of using imsic_irq_set_affinity() for leaf MSI domains, use +imsic_irq_set_affinity() for the non-leaf IMSIC base domain and use +irq_chip_set_affinity_parent() for leaf MSI domains. + +[ tglx: Massaged change log ] + +Signed-off-by: Andrew Jones +Signed-off-by: Anup Patel +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/all/20250217085657.789309-2-apatel@ventanamicro.com +Signed-off-by: Sasha Levin +--- + drivers/irqchip/irq-riscv-imsic-platform.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/drivers/irqchip/irq-riscv-imsic-platform.c b/drivers/irqchip/irq-riscv-imsic-platform.c +index c708780e8760f..5d7c30ad8855b 100644 +--- a/drivers/irqchip/irq-riscv-imsic-platform.c ++++ b/drivers/irqchip/irq-riscv-imsic-platform.c +@@ -96,9 +96,8 @@ static int imsic_irq_set_affinity(struct irq_data *d, const struct cpumask *mask + bool force) + { + struct imsic_vector *old_vec, *new_vec; +- struct irq_data *pd = d->parent_data; + +- old_vec = irq_data_get_irq_chip_data(pd); ++ old_vec = irq_data_get_irq_chip_data(d); + if (WARN_ON(!old_vec)) + return -ENOENT; + +@@ -116,13 +115,13 @@ static int imsic_irq_set_affinity(struct irq_data *d, const struct cpumask *mask + return -ENOSPC; + + /* Point device to the new vector */ +- imsic_msi_update_msg(d, new_vec); ++ imsic_msi_update_msg(irq_get_irq_data(d->irq), new_vec); + + /* Update irq descriptors with the new vector */ +- pd->chip_data = new_vec; ++ d->chip_data = new_vec; + +- /* Update effective affinity of parent irq data */ +- irq_data_update_effective_affinity(pd, cpumask_of(new_vec->cpu)); ++ /* Update effective affinity */ ++ irq_data_update_effective_affinity(d, cpumask_of(new_vec->cpu)); + + /* Move state of the old vector to the new vector */ + imsic_vector_move(old_vec, new_vec); +@@ -135,6 +134,9 @@ static struct irq_chip imsic_irq_base_chip = { + .name = "IMSIC", + .irq_mask = imsic_irq_mask, + .irq_unmask = imsic_irq_unmask, ++#ifdef CONFIG_SMP ++ .irq_set_affinity = imsic_irq_set_affinity, ++#endif + .irq_retrigger = imsic_irq_retrigger, + .irq_compose_msi_msg = imsic_irq_compose_msg, + .flags = IRQCHIP_SKIP_SET_WAKE | +@@ -245,7 +247,7 @@ static bool imsic_init_dev_msi_info(struct device *dev, + if (WARN_ON_ONCE(domain != real_parent)) + return false; + #ifdef CONFIG_SMP +- info->chip->irq_set_affinity = imsic_irq_set_affinity; ++ info->chip->irq_set_affinity = irq_chip_set_affinity_parent; + #endif + break; + default: +-- +2.39.5 + diff --git a/queue-6.12/jbd2-do-not-try-to-recover-wiped-journal.patch b/queue-6.12/jbd2-do-not-try-to-recover-wiped-journal.patch new file mode 100644 index 0000000000..20ae135a5b --- /dev/null +++ b/queue-6.12/jbd2-do-not-try-to-recover-wiped-journal.patch @@ -0,0 +1,58 @@ +From b7176936f7aef8dbc4a8fbd424af2624ccbcdb9d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 10:46:59 +0100 +Subject: jbd2: do not try to recover wiped journal + +From: Jan Kara + +[ Upstream commit a662f3c03b754e1f97a2781fa242e95bdb139798 ] + +If a journal is wiped, we will set journal->j_tail to 0. However if +'write' argument is not set (as it happens for read-only device or for +ocfs2), the on-disk superblock is not updated accordingly and thus +jbd2_journal_recover() cat try to recover the wiped journal. Fix the +check in jbd2_journal_recover() to use journal->j_tail for checking +empty journal instead. + +Signed-off-by: Jan Kara +Reviewed-by: Zhang Yi +Link: https://patch.msgid.link/20250206094657.20865-4-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/jbd2/recovery.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c +index 667f67342c522..f85f401526c54 100644 +--- a/fs/jbd2/recovery.c ++++ b/fs/jbd2/recovery.c +@@ -287,19 +287,20 @@ static int fc_do_one_pass(journal_t *journal, + int jbd2_journal_recover(journal_t *journal) + { + int err, err2; +- journal_superblock_t * sb; +- + struct recovery_info info; + + memset(&info, 0, sizeof(info)); +- sb = journal->j_superblock; + + /* + * The journal superblock's s_start field (the current log head) + * is always zero if, and only if, the journal was cleanly +- * unmounted. ++ * unmounted. We use its in-memory version j_tail here because ++ * jbd2_journal_wipe() could have updated it without updating journal ++ * superblock. + */ +- if (!sb->s_start) { ++ if (!journal->j_tail) { ++ journal_superblock_t *sb = journal->j_superblock; ++ + jbd2_debug(1, "No recovery required, last transaction %d, head block %u\n", + be32_to_cpu(sb->s_sequence), be32_to_cpu(sb->s_head)); + journal->j_transaction_sequence = be32_to_cpu(sb->s_sequence) + 1; +-- +2.39.5 + diff --git a/queue-6.12/kbuild-fix-argument-parsing-in-scripts-config.patch b/queue-6.12/kbuild-fix-argument-parsing-in-scripts-config.patch new file mode 100644 index 0000000000..095cd7d7f9 --- /dev/null +++ b/queue-6.12/kbuild-fix-argument-parsing-in-scripts-config.patch @@ -0,0 +1,82 @@ +From 25631aaa96f36bd745fd3d639eec91ed5ffea5e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Mar 2025 17:21:37 -0500 +Subject: kbuild: fix argument parsing in scripts/config + +From: Seyediman Seyedarab + +[ Upstream commit f757f6011c92b5a01db742c39149bed9e526478f ] + +The script previously assumed --file was always the first argument, +which caused issues when it appeared later. This patch updates the +parsing logic to scan all arguments to find --file, sets the config +file correctly, and resets the argument list with the remaining +commands. + +It also fixes --refresh to respect --file by passing KCONFIG_CONFIG=$FN +to make oldconfig. + +Signed-off-by: Seyediman Seyedarab +Signed-off-by: Masahiro Yamada +Signed-off-by: Sasha Levin +--- + scripts/config | 26 ++++++++++++++++---------- + 1 file changed, 16 insertions(+), 10 deletions(-) + +diff --git a/scripts/config b/scripts/config +index ff88e2faefd35..ea475c07de283 100755 +--- a/scripts/config ++++ b/scripts/config +@@ -32,6 +32,7 @@ commands: + Disable option directly after other option + --module-after|-M beforeopt option + Turn option into module directly after other option ++ --refresh Refresh the config using old settings + + commands can be repeated multiple times + +@@ -124,16 +125,22 @@ undef_var() { + txt_delete "^# $name is not set" "$FN" + } + +-if [ "$1" = "--file" ]; then +- FN="$2" +- if [ "$FN" = "" ] ; then +- usage ++FN=.config ++CMDS=() ++while [[ $# -gt 0 ]]; do ++ if [ "$1" = "--file" ]; then ++ if [ "$2" = "" ]; then ++ usage ++ fi ++ FN="$2" ++ shift 2 ++ else ++ CMDS+=("$1") ++ shift + fi +- shift 2 +-else +- FN=.config +-fi ++done + ++set -- "${CMDS[@]}" + if [ "$1" = "" ] ; then + usage + fi +@@ -217,9 +224,8 @@ while [ "$1" != "" ] ; do + set_var "${CONFIG_}$B" "${CONFIG_}$B=m" "${CONFIG_}$A" + ;; + +- # undocumented because it ignores --file (fixme) + --refresh) +- yes "" | make oldconfig ++ yes "" | make oldconfig KCONFIG_CONFIG=$FN + ;; + + *) +-- +2.39.5 + diff --git a/queue-6.12/kconfig-do-not-clear-symbol_valid-when-reading-inclu.patch b/queue-6.12/kconfig-do-not-clear-symbol_valid-when-reading-inclu.patch new file mode 100644 index 0000000000..b1ef39b52c --- /dev/null +++ b/queue-6.12/kconfig-do-not-clear-symbol_valid-when-reading-inclu.patch @@ -0,0 +1,90 @@ +From a8fc1a1142c59f43b58ab3e6f411924ce68af4b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Feb 2025 03:41:55 +0900 +Subject: kconfig: do not clear SYMBOL_VALID when reading + include/config/auto.conf + +From: Masahiro Yamada + +[ Upstream commit 226ac19c217f24f0927d0a73cf9ee613971a188d ] + +When conf_read_simple() is called with S_DEF_AUTO, it is meant to read +previous symbol values from include/config/auto.conf to determine which +include/config/* files should be touched. + +This process should not modify the current symbol status in any way. +However, conf_touch_deps() currently invalidates all symbol values and +recalculates them, which is totally unneeded. + +Signed-off-by: Masahiro Yamada +Signed-off-by: Sasha Levin +--- + scripts/kconfig/confdata.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c +index 3b55e7a4131d9..ac95661a1c9dd 100644 +--- a/scripts/kconfig/confdata.c ++++ b/scripts/kconfig/confdata.c +@@ -385,7 +385,7 @@ int conf_read_simple(const char *name, int def) + + def_flags = SYMBOL_DEF << def; + for_all_symbols(sym) { +- sym->flags &= ~(def_flags|SYMBOL_VALID); ++ sym->flags &= ~def_flags; + switch (sym->type) { + case S_INT: + case S_HEX: +@@ -398,7 +398,11 @@ int conf_read_simple(const char *name, int def) + } + } + +- expr_invalidate_all(); ++ if (def == S_DEF_USER) { ++ for_all_symbols(sym) ++ sym->flags &= ~SYMBOL_VALID; ++ expr_invalidate_all(); ++ } + + while (getline_stripped(&line, &line_asize, in) != -1) { + struct menu *choice; +@@ -464,6 +468,9 @@ int conf_read_simple(const char *name, int def) + if (conf_set_sym_val(sym, def, def_flags, val)) + continue; + ++ if (def != S_DEF_USER) ++ continue; ++ + /* + * If this is a choice member, give it the highest priority. + * If conflicting CONFIG options are given from an input file, +@@ -967,10 +974,8 @@ static int conf_touch_deps(void) + depfile_path[depfile_prefix_len] = 0; + + conf_read_simple(name, S_DEF_AUTO); +- sym_calc_value(modules_sym); + + for_all_symbols(sym) { +- sym_calc_value(sym); + if (sym_is_choice(sym)) + continue; + if (sym->flags & SYMBOL_WRITE) { +@@ -1084,12 +1089,12 @@ int conf_write_autoconf(int overwrite) + if (ret) + return -1; + +- if (conf_touch_deps()) +- return 1; +- + for_all_symbols(sym) + sym_calc_value(sym); + ++ if (conf_touch_deps()) ++ return 1; ++ + ret = __conf_write_autoconf(conf_get_autoheader_name(), + print_symbol_for_c, + &comment_style_c); +-- +2.39.5 + diff --git a/queue-6.12/kconfig-merge_config-use-an-empty-file-as-initfile.patch b/queue-6.12/kconfig-merge_config-use-an-empty-file-as-initfile.patch new file mode 100644 index 0000000000..881f4bca53 --- /dev/null +++ b/queue-6.12/kconfig-merge_config-use-an-empty-file-as-initfile.patch @@ -0,0 +1,48 @@ +From 341195dbe36798d3b5b86782e37251806b23f516 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Mar 2025 14:28:37 +0000 +Subject: kconfig: merge_config: use an empty file as initfile + +From: Daniel Gomez + +[ Upstream commit a26fe287eed112b4e21e854f173c8918a6a8596d ] + +The scripts/kconfig/merge_config.sh script requires an existing +$INITFILE (or the $1 argument) as a base file for merging Kconfig +fragments. However, an empty $INITFILE can serve as an initial starting +point, later referenced by the KCONFIG_ALLCONFIG Makefile variable +if -m is not used. This variable can point to any configuration file +containing preset config symbols (the merged output) as stated in +Documentation/kbuild/kconfig.rst. When -m is used $INITFILE will +contain just the merge output requiring the user to run make (i.e. +KCONFIG_ALLCONFIG=<$INITFILE> make or make +olddefconfig). + +Instead of failing when `$INITFILE` is missing, create an empty file and +use it as the starting point for merges. + +Signed-off-by: Daniel Gomez +Signed-off-by: Masahiro Yamada +Signed-off-by: Sasha Levin +--- + scripts/kconfig/merge_config.sh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh +index 0b7952471c18f..79c09b378be81 100755 +--- a/scripts/kconfig/merge_config.sh ++++ b/scripts/kconfig/merge_config.sh +@@ -112,8 +112,8 @@ INITFILE=$1 + shift; + + if [ ! -r "$INITFILE" ]; then +- echo "The base file '$INITFILE' does not exist. Exit." >&2 +- exit 1 ++ echo "The base file '$INITFILE' does not exist. Creating one..." >&2 ++ touch "$INITFILE" + fi + + MERGE_LIST=$* +-- +2.39.5 + diff --git a/queue-6.12/kernfs-acquire-kernfs_rwsem-in-kernfs_get_parent_den.patch b/queue-6.12/kernfs-acquire-kernfs_rwsem-in-kernfs_get_parent_den.patch new file mode 100644 index 0000000000..61c00e7d10 --- /dev/null +++ b/queue-6.12/kernfs-acquire-kernfs_rwsem-in-kernfs_get_parent_den.patch @@ -0,0 +1,41 @@ +From 47f4808a74c1abb8ff4a358d4a3fa28e5aec9039 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 15:50:19 +0100 +Subject: kernfs: Acquire kernfs_rwsem in kernfs_get_parent_dentry(). + +From: Sebastian Andrzej Siewior + +[ Upstream commit 122ab92dee80582c39740609a627198dd5b6b595 ] + +kernfs_get_parent_dentry() passes kernfs_node::parent to +kernfs_get_inode(). + +Acquire kernfs_root::kernfs_rwsem to ensure kernfs_node::parent isn't +replaced during the operation. + +Acked-by: Tejun Heo +Signed-off-by: Sebastian Andrzej Siewior +Link: https://lore.kernel.org/r/20250213145023.2820193-3-bigeasy@linutronix.de +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + fs/kernfs/mount.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c +index 0f6379ae258d1..4a0ff08d589ca 100644 +--- a/fs/kernfs/mount.c ++++ b/fs/kernfs/mount.c +@@ -145,7 +145,9 @@ static struct dentry *kernfs_fh_to_parent(struct super_block *sb, + static struct dentry *kernfs_get_parent_dentry(struct dentry *child) + { + struct kernfs_node *kn = kernfs_dentry_node(child); ++ struct kernfs_root *root = kernfs_root(kn); + ++ guard(rwsem_read)(&root->kernfs_rwsem); + return d_obtain_alias(kernfs_get_inode(child->d_sb, kn->parent)); + } + +-- +2.39.5 + diff --git a/queue-6.12/kernfs-acquire-kernfs_rwsem-in-kernfs_node_dentry.patch b/queue-6.12/kernfs-acquire-kernfs_rwsem-in-kernfs_node_dentry.patch new file mode 100644 index 0000000000..1061f23182 --- /dev/null +++ b/queue-6.12/kernfs-acquire-kernfs_rwsem-in-kernfs_node_dentry.patch @@ -0,0 +1,49 @@ +From 9bb7d9f7370173a25f5494ebd70085a8a54e33bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 15:50:20 +0100 +Subject: kernfs: Acquire kernfs_rwsem in kernfs_node_dentry(). + +From: Sebastian Andrzej Siewior + +[ Upstream commit 5b2fabf7fe8f745ff214ff003e6067b64f172271 ] + +kernfs_node_dentry() passes kernfs_node::name to +lookup_positive_unlocked(). + +Acquire kernfs_root::kernfs_rwsem to ensure the node is not renamed +during the operation. + +Acked-by: Tejun Heo +Signed-off-by: Sebastian Andrzej Siewior +Link: https://lore.kernel.org/r/20250213145023.2820193-4-bigeasy@linutronix.de +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + fs/kernfs/mount.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c +index 1358c21837f1a..0f6379ae258d1 100644 +--- a/fs/kernfs/mount.c ++++ b/fs/kernfs/mount.c +@@ -207,6 +207,7 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn, + { + struct dentry *dentry; + struct kernfs_node *knparent; ++ struct kernfs_root *root; + + BUG_ON(sb->s_op != &kernfs_sops); + +@@ -216,6 +217,9 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn, + if (!kn->parent) + return dentry; + ++ root = kernfs_root(kn); ++ guard(rwsem_read)(&root->kernfs_rwsem); ++ + knparent = find_next_ancestor(kn, NULL); + if (WARN_ON(!knparent)) { + dput(dentry); +-- +2.39.5 + diff --git a/queue-6.12/kernfs-acquire-kernfs_rwsem-in-kernfs_notify_workfn.patch b/queue-6.12/kernfs-acquire-kernfs_rwsem-in-kernfs_notify_workfn.patch new file mode 100644 index 0000000000..ef962184bf --- /dev/null +++ b/queue-6.12/kernfs-acquire-kernfs_rwsem-in-kernfs_notify_workfn.patch @@ -0,0 +1,47 @@ +From 079fbf2ff1f0e3107a47874c3cb8ee013bf89409 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 15:50:18 +0100 +Subject: kernfs: Acquire kernfs_rwsem in kernfs_notify_workfn(). + +From: Sebastian Andrzej Siewior + +[ Upstream commit 400188ae361a9d9a72a47a6cedaf2d2efcc84aa8 ] + +kernfs_notify_workfn() dereferences kernfs_node::name and passes it +later to fsnotify(). If the node is renamed then the previously observed +name pointer becomes invalid. + +Acquire kernfs_root::kernfs_rwsem to block renames of the node. + +Acked-by: Tejun Heo +Signed-off-by: Sebastian Andrzej Siewior +Link: https://lore.kernel.org/r/20250213145023.2820193-2-bigeasy@linutronix.de +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + fs/kernfs/file.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c +index 8502ef68459b9..165d8e37976ba 100644 +--- a/fs/kernfs/file.c ++++ b/fs/kernfs/file.c +@@ -911,6 +911,7 @@ static void kernfs_notify_workfn(struct work_struct *work) + /* kick fsnotify */ + + down_read(&root->kernfs_supers_rwsem); ++ down_read(&root->kernfs_rwsem); + list_for_each_entry(info, &kernfs_root(kn)->supers, node) { + struct kernfs_node *parent; + struct inode *p_inode = NULL; +@@ -947,6 +948,7 @@ static void kernfs_notify_workfn(struct work_struct *work) + iput(inode); + } + ++ up_read(&root->kernfs_rwsem); + up_read(&root->kernfs_supers_rwsem); + kernfs_put(kn); + goto repeat; +-- +2.39.5 + diff --git a/queue-6.12/kernfs-don-t-re-lock-kernfs_root-kernfs_rwsem-in-ker.patch b/queue-6.12/kernfs-don-t-re-lock-kernfs_root-kernfs_rwsem-in-ker.patch new file mode 100644 index 0000000000..c1741ed7ba --- /dev/null +++ b/queue-6.12/kernfs-don-t-re-lock-kernfs_root-kernfs_rwsem-in-ker.patch @@ -0,0 +1,56 @@ +From 6247ef751c277b43adbe8b0e75696f1e59cf2921 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 15:50:21 +0100 +Subject: kernfs: Don't re-lock kernfs_root::kernfs_rwsem in + kernfs_fop_readdir(). + +From: Sebastian Andrzej Siewior + +[ Upstream commit 9aab10a0249eab4ec77c6a5e4f66442610c12a09 ] + +The readdir operation iterates over all entries and invokes dir_emit() +for every entry passing kernfs_node::name as argument. +Since the name argument can change, and become invalid, the +kernfs_root::kernfs_rwsem lock should not be dropped to prevent renames +during the operation. + +The lock drop around dir_emit() has been initially introduced in commit + 1e5289c97bba2 ("sysfs: Cache the last sysfs_dirent to improve readdir scalability v2") + +to avoid holding a global lock during a page fault. The lock drop is +wrong since the support of renames and not a big burden since the lock +is no longer global. + +Don't re-acquire kernfs_root::kernfs_rwsem while copying the name to the +userpace buffer. + +Acked-by: Tejun Heo +Signed-off-by: Sebastian Andrzej Siewior +Link: https://lore.kernel.org/r/20250213145023.2820193-5-bigeasy@linutronix.de +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + fs/kernfs/dir.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c +index 458519e416fe7..5a1fea414996e 100644 +--- a/fs/kernfs/dir.c ++++ b/fs/kernfs/dir.c +@@ -1868,10 +1868,10 @@ static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx) + file->private_data = pos; + kernfs_get(pos); + +- up_read(&root->kernfs_rwsem); +- if (!dir_emit(ctx, name, len, ino, type)) ++ if (!dir_emit(ctx, name, len, ino, type)) { ++ up_read(&root->kernfs_rwsem); + return 0; +- down_read(&root->kernfs_rwsem); ++ } + } + up_read(&root->kernfs_rwsem); + file->private_data = NULL; +-- +2.39.5 + diff --git a/queue-6.12/kernfs-use-rcu-to-access-kernfs_node-parent.patch b/queue-6.12/kernfs-use-rcu-to-access-kernfs_node-parent.patch new file mode 100644 index 0000000000..e06cb323e0 --- /dev/null +++ b/queue-6.12/kernfs-use-rcu-to-access-kernfs_node-parent.patch @@ -0,0 +1,988 @@ +From 10d6731fc902f64ab2457c34c7d2cd1503e9cc34 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 15:50:22 +0100 +Subject: kernfs: Use RCU to access kernfs_node::parent. + +From: Sebastian Andrzej Siewior + +[ Upstream commit 633488947ef66b194377411322dc9e12aab79b65 ] + +kernfs_rename_lock is used to obtain stable kernfs_node::{name|parent} +pointer. This is a preparation to access kernfs_node::parent under RCU +and ensure that the pointer remains stable under the RCU lifetime +guarantees. + +For a complete path, as it is done in kernfs_path_from_node(), the +kernfs_rename_lock is still required in order to obtain a stable parent +relationship while computing the relevant node depth. This must not +change while the nodes are inspected in order to build the path. +If the kernfs user never moves the nodes (changes the parent) then the +kernfs_rename_lock is not required and the RCU guarantees are +sufficient. This "restriction" can be set with +KERNFS_ROOT_INVARIANT_PARENT. Otherwise the lock is required. + +Rename kernfs_node::parent to kernfs_node::__parent to denote the RCU +access and use RCU accessor while accessing the node. +Make cgroup use KERNFS_ROOT_INVARIANT_PARENT since the parent here can +not change. + +Acked-by: Tejun Heo +Cc: Yonghong Song +Signed-off-by: Sebastian Andrzej Siewior +Link: https://lore.kernel.org/r/20250213145023.2820193-6-bigeasy@linutronix.de +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/cpu/resctrl/rdtgroup.c | 65 +++++++++---- + fs/kernfs/dir.c | 96 ++++++++++++------- + fs/kernfs/kernfs-internal.h | 32 ++++++- + fs/kernfs/mount.c | 10 +- + fs/kernfs/symlink.c | 23 ++--- + fs/sysfs/file.c | 24 +++-- + include/linux/kernfs.h | 10 +- + kernel/cgroup/cgroup-v1.c | 2 +- + kernel/cgroup/cgroup.c | 24 ++++- + .../selftests/bpf/progs/profiler.inc.h | 2 +- + 10 files changed, 195 insertions(+), 93 deletions(-) + +diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c +index 2d48db66fca85..d4d7ccf1253b8 100644 +--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c ++++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c +@@ -948,10 +948,20 @@ static int rdt_last_cmd_status_show(struct kernfs_open_file *of, + return 0; + } + ++static void *rdt_kn_parent_priv(struct kernfs_node *kn) ++{ ++ /* ++ * The parent pointer is only valid within RCU section since it can be ++ * replaced. ++ */ ++ guard(rcu)(); ++ return rcu_dereference(kn->__parent)->priv; ++} ++ + static int rdt_num_closids_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + + seq_printf(seq, "%u\n", s->num_closid); + return 0; +@@ -960,7 +970,7 @@ static int rdt_num_closids_show(struct kernfs_open_file *of, + static int rdt_default_ctrl_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + struct rdt_resource *r = s->res; + + seq_printf(seq, "%x\n", r->default_ctrl); +@@ -970,7 +980,7 @@ static int rdt_default_ctrl_show(struct kernfs_open_file *of, + static int rdt_min_cbm_bits_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + struct rdt_resource *r = s->res; + + seq_printf(seq, "%u\n", r->cache.min_cbm_bits); +@@ -980,7 +990,7 @@ static int rdt_min_cbm_bits_show(struct kernfs_open_file *of, + static int rdt_shareable_bits_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + struct rdt_resource *r = s->res; + + seq_printf(seq, "%x\n", r->cache.shareable_bits); +@@ -1004,7 +1014,7 @@ static int rdt_shareable_bits_show(struct kernfs_open_file *of, + static int rdt_bit_usage_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + /* + * Use unsigned long even though only 32 bits are used to ensure + * test_bit() is used safely. +@@ -1086,7 +1096,7 @@ static int rdt_bit_usage_show(struct kernfs_open_file *of, + static int rdt_min_bw_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + struct rdt_resource *r = s->res; + + seq_printf(seq, "%u\n", r->membw.min_bw); +@@ -1096,7 +1106,7 @@ static int rdt_min_bw_show(struct kernfs_open_file *of, + static int rdt_num_rmids_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct rdt_resource *r = of->kn->parent->priv; ++ struct rdt_resource *r = rdt_kn_parent_priv(of->kn); + + seq_printf(seq, "%d\n", r->num_rmid); + +@@ -1106,7 +1116,7 @@ static int rdt_num_rmids_show(struct kernfs_open_file *of, + static int rdt_mon_features_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct rdt_resource *r = of->kn->parent->priv; ++ struct rdt_resource *r = rdt_kn_parent_priv(of->kn); + struct mon_evt *mevt; + + list_for_each_entry(mevt, &r->evt_list, list) { +@@ -1121,7 +1131,7 @@ static int rdt_mon_features_show(struct kernfs_open_file *of, + static int rdt_bw_gran_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + struct rdt_resource *r = s->res; + + seq_printf(seq, "%u\n", r->membw.bw_gran); +@@ -1131,7 +1141,7 @@ static int rdt_bw_gran_show(struct kernfs_open_file *of, + static int rdt_delay_linear_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + struct rdt_resource *r = s->res; + + seq_printf(seq, "%u\n", r->membw.delay_linear); +@@ -1149,7 +1159,7 @@ static int max_threshold_occ_show(struct kernfs_open_file *of, + static int rdt_thread_throttle_mode_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + struct rdt_resource *r = s->res; + + if (r->membw.throttle_mode == THREAD_THROTTLE_PER_THREAD) +@@ -1214,7 +1224,7 @@ static enum resctrl_conf_type resctrl_peer_type(enum resctrl_conf_type my_type) + static int rdt_has_sparse_bitmasks_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + struct rdt_resource *r = s->res; + + seq_printf(seq, "%u\n", r->cache.arch_has_sparse_bitmasks); +@@ -1626,7 +1636,7 @@ static int mbm_config_show(struct seq_file *s, struct rdt_resource *r, u32 evtid + static int mbm_total_bytes_config_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct rdt_resource *r = of->kn->parent->priv; ++ struct rdt_resource *r = rdt_kn_parent_priv(of->kn); + + mbm_config_show(seq, r, QOS_L3_MBM_TOTAL_EVENT_ID); + +@@ -1636,7 +1646,7 @@ static int mbm_total_bytes_config_show(struct kernfs_open_file *of, + static int mbm_local_bytes_config_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct rdt_resource *r = of->kn->parent->priv; ++ struct rdt_resource *r = rdt_kn_parent_priv(of->kn); + + mbm_config_show(seq, r, QOS_L3_MBM_LOCAL_EVENT_ID); + +@@ -1742,7 +1752,7 @@ static ssize_t mbm_total_bytes_config_write(struct kernfs_open_file *of, + char *buf, size_t nbytes, + loff_t off) + { +- struct rdt_resource *r = of->kn->parent->priv; ++ struct rdt_resource *r = rdt_kn_parent_priv(of->kn); + int ret; + + /* Valid input requires a trailing newline */ +@@ -1768,7 +1778,7 @@ static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, + char *buf, size_t nbytes, + loff_t off) + { +- struct rdt_resource *r = of->kn->parent->priv; ++ struct rdt_resource *r = rdt_kn_parent_priv(of->kn); + int ret; + + /* Valid input requires a trailing newline */ +@@ -2430,12 +2440,13 @@ static struct rdtgroup *kernfs_to_rdtgroup(struct kernfs_node *kn) + * resource. "info" and its subdirectories don't + * have rdtgroup structures, so return NULL here. + */ +- if (kn == kn_info || kn->parent == kn_info) ++ if (kn == kn_info || ++ rcu_access_pointer(kn->__parent) == kn_info) + return NULL; + else + return kn->priv; + } else { +- return kn->parent->priv; ++ return rdt_kn_parent_priv(kn); + } + } + +@@ -3759,9 +3770,18 @@ static int rdtgroup_rmdir_ctrl(struct rdtgroup *rdtgrp, cpumask_var_t tmpmask) + return 0; + } + ++static struct kernfs_node *rdt_kn_parent(struct kernfs_node *kn) ++{ ++ /* ++ * Valid within the RCU section it was obtained or while rdtgroup_mutex ++ * is held. ++ */ ++ return rcu_dereference_check(kn->__parent, lockdep_is_held(&rdtgroup_mutex)); ++} ++ + static int rdtgroup_rmdir(struct kernfs_node *kn) + { +- struct kernfs_node *parent_kn = kn->parent; ++ struct kernfs_node *parent_kn; + struct rdtgroup *rdtgrp; + cpumask_var_t tmpmask; + int ret = 0; +@@ -3774,6 +3794,7 @@ static int rdtgroup_rmdir(struct kernfs_node *kn) + ret = -EPERM; + goto out; + } ++ parent_kn = rdt_kn_parent(kn); + + /* + * If the rdtgroup is a ctrl_mon group and parent directory +@@ -3842,6 +3863,7 @@ static void mongrp_reparent(struct rdtgroup *rdtgrp, + static int rdtgroup_rename(struct kernfs_node *kn, + struct kernfs_node *new_parent, const char *new_name) + { ++ struct kernfs_node *kn_parent; + struct rdtgroup *new_prdtgrp; + struct rdtgroup *rdtgrp; + cpumask_var_t tmpmask; +@@ -3876,8 +3898,9 @@ static int rdtgroup_rename(struct kernfs_node *kn, + goto out; + } + +- if (rdtgrp->type != RDTMON_GROUP || !kn->parent || +- !is_mon_groups(kn->parent, kn->name)) { ++ kn_parent = rdt_kn_parent(kn); ++ if (rdtgrp->type != RDTMON_GROUP || !kn_parent || ++ !is_mon_groups(kn_parent, kn->name)) { + rdt_last_cmd_puts("Source must be a MON group\n"); + ret = -EPERM; + goto out; +diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c +index 5a1fea414996e..d2306641b569c 100644 +--- a/fs/kernfs/dir.c ++++ b/fs/kernfs/dir.c +@@ -17,7 +17,7 @@ + + #include "kernfs-internal.h" + +-static DEFINE_RWLOCK(kernfs_rename_lock); /* kn->parent and ->name */ ++DEFINE_RWLOCK(kernfs_rename_lock); /* kn->parent and ->name */ + /* + * Don't use rename_lock to piggy back on pr_cont_buf. We don't want to + * call pr_cont() while holding rename_lock. Because sometimes pr_cont() +@@ -56,7 +56,7 @@ static int kernfs_name_locked(struct kernfs_node *kn, char *buf, size_t buflen) + if (!kn) + return strscpy(buf, "(null)", buflen); + +- return strscpy(buf, kn->parent ? kn->name : "/", buflen); ++ return strscpy(buf, rcu_access_pointer(kn->__parent) ? kn->name : "/", buflen); + } + + /* kernfs_node_depth - compute depth from @from to @to */ +@@ -64,9 +64,9 @@ static size_t kernfs_depth(struct kernfs_node *from, struct kernfs_node *to) + { + size_t depth = 0; + +- while (to->parent && to != from) { ++ while (rcu_dereference(to->__parent) && to != from) { + depth++; +- to = to->parent; ++ to = rcu_dereference(to->__parent); + } + return depth; + } +@@ -84,18 +84,18 @@ static struct kernfs_node *kernfs_common_ancestor(struct kernfs_node *a, + db = kernfs_depth(rb->kn, b); + + while (da > db) { +- a = a->parent; ++ a = rcu_dereference(a->__parent); + da--; + } + while (db > da) { +- b = b->parent; ++ b = rcu_dereference(b->__parent); + db--; + } + + /* worst case b and a will be the same at root */ + while (b != a) { +- b = b->parent; +- a = a->parent; ++ b = rcu_dereference(b->__parent); ++ a = rcu_dereference(a->__parent); + } + + return a; +@@ -168,8 +168,9 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to, + + /* Calculate how many bytes we need for the rest */ + for (i = depth_to - 1; i >= 0; i--) { ++ + for (kn = kn_to, j = 0; j < i; j++) +- kn = kn->parent; ++ kn = rcu_dereference(kn->__parent); + + len += scnprintf(buf + len, buflen - len, "/%s", kn->name); + } +@@ -226,6 +227,7 @@ int kernfs_path_from_node(struct kernfs_node *to, struct kernfs_node *from, + unsigned long flags; + int ret; + ++ guard(rcu)(); + read_lock_irqsave(&kernfs_rename_lock, flags); + ret = kernfs_path_from_node_locked(to, from, buf, buflen); + read_unlock_irqrestore(&kernfs_rename_lock, flags); +@@ -295,7 +297,7 @@ struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn) + unsigned long flags; + + read_lock_irqsave(&kernfs_rename_lock, flags); +- parent = kn->parent; ++ parent = kernfs_parent(kn); + kernfs_get(parent); + read_unlock_irqrestore(&kernfs_rename_lock, flags); + +@@ -360,8 +362,12 @@ static int kernfs_sd_compare(const struct kernfs_node *left, + */ + static int kernfs_link_sibling(struct kernfs_node *kn) + { +- struct rb_node **node = &kn->parent->dir.children.rb_node; + struct rb_node *parent = NULL; ++ struct kernfs_node *kn_parent; ++ struct rb_node **node; ++ ++ kn_parent = kernfs_parent(kn); ++ node = &kn_parent->dir.children.rb_node; + + while (*node) { + struct kernfs_node *pos; +@@ -380,13 +386,13 @@ static int kernfs_link_sibling(struct kernfs_node *kn) + + /* add new node and rebalance the tree */ + rb_link_node(&kn->rb, parent, node); +- rb_insert_color(&kn->rb, &kn->parent->dir.children); ++ rb_insert_color(&kn->rb, &kn_parent->dir.children); + + /* successfully added, account subdir number */ + down_write(&kernfs_root(kn)->kernfs_iattr_rwsem); + if (kernfs_type(kn) == KERNFS_DIR) +- kn->parent->dir.subdirs++; +- kernfs_inc_rev(kn->parent); ++ kn_parent->dir.subdirs++; ++ kernfs_inc_rev(kn_parent); + up_write(&kernfs_root(kn)->kernfs_iattr_rwsem); + + return 0; +@@ -407,16 +413,19 @@ static int kernfs_link_sibling(struct kernfs_node *kn) + */ + static bool kernfs_unlink_sibling(struct kernfs_node *kn) + { ++ struct kernfs_node *kn_parent; ++ + if (RB_EMPTY_NODE(&kn->rb)) + return false; + ++ kn_parent = kernfs_parent(kn); + down_write(&kernfs_root(kn)->kernfs_iattr_rwsem); + if (kernfs_type(kn) == KERNFS_DIR) +- kn->parent->dir.subdirs--; +- kernfs_inc_rev(kn->parent); ++ kn_parent->dir.subdirs--; ++ kernfs_inc_rev(kn_parent); + up_write(&kernfs_root(kn)->kernfs_iattr_rwsem); + +- rb_erase(&kn->rb, &kn->parent->dir.children); ++ rb_erase(&kn->rb, &kn_parent->dir.children); + RB_CLEAR_NODE(&kn->rb); + return true; + } +@@ -562,7 +571,7 @@ void kernfs_put(struct kernfs_node *kn) + * Moving/renaming is always done while holding reference. + * kn->parent won't change beneath us. + */ +- parent = kn->parent; ++ parent = kernfs_parent(kn); + + WARN_ONCE(atomic_read(&kn->active) != KN_DEACTIVATED_BIAS, + "kernfs_put: %s/%s: released with incorrect active_ref %d\n", +@@ -701,7 +710,7 @@ struct kernfs_node *kernfs_new_node(struct kernfs_node *parent, + name, mode, uid, gid, flags); + if (kn) { + kernfs_get(parent); +- kn->parent = parent; ++ rcu_assign_pointer(kn->__parent, parent); + } + return kn; + } +@@ -769,13 +778,14 @@ struct kernfs_node *kernfs_find_and_get_node_by_id(struct kernfs_root *root, + */ + int kernfs_add_one(struct kernfs_node *kn) + { +- struct kernfs_node *parent = kn->parent; +- struct kernfs_root *root = kernfs_root(parent); ++ struct kernfs_root *root = kernfs_root(kn); + struct kernfs_iattrs *ps_iattr; ++ struct kernfs_node *parent; + bool has_ns; + int ret; + + down_write(&root->kernfs_rwsem); ++ parent = kernfs_parent(kn); + + ret = -EINVAL; + has_ns = kernfs_ns_enabled(parent); +@@ -949,6 +959,11 @@ struct kernfs_node *kernfs_walk_and_get_ns(struct kernfs_node *parent, + return kn; + } + ++unsigned int kernfs_root_flags(struct kernfs_node *kn) ++{ ++ return kernfs_root(kn)->flags; ++} ++ + /** + * kernfs_create_root - create a new kernfs hierarchy + * @scops: optional syscall operations for the hierarchy +@@ -1111,7 +1126,7 @@ struct kernfs_node *kernfs_create_empty_dir(struct kernfs_node *parent, + + static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags) + { +- struct kernfs_node *kn; ++ struct kernfs_node *kn, *parent; + struct kernfs_root *root; + + if (flags & LOOKUP_RCU) +@@ -1162,8 +1177,9 @@ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags) + if (!kernfs_active(kn)) + goto out_bad; + ++ parent = kernfs_parent(kn); + /* The kernfs node has been moved? */ +- if (kernfs_dentry_node(dentry->d_parent) != kn->parent) ++ if (kernfs_dentry_node(dentry->d_parent) != parent) + goto out_bad; + + /* The kernfs node has been renamed */ +@@ -1171,7 +1187,7 @@ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags) + goto out_bad; + + /* The kernfs node has been moved to a different namespace */ +- if (kn->parent && kernfs_ns_enabled(kn->parent) && ++ if (parent && kernfs_ns_enabled(parent) && + kernfs_info(dentry->d_sb)->ns != kn->ns) + goto out_bad; + +@@ -1364,7 +1380,7 @@ static struct kernfs_node *kernfs_next_descendant_post(struct kernfs_node *pos, + return kernfs_leftmost_descendant(rb_to_kn(rbn)); + + /* no sibling left, visit parent */ +- return pos->parent; ++ return kernfs_parent(pos); + } + + static void kernfs_activate_one(struct kernfs_node *kn) +@@ -1376,7 +1392,7 @@ static void kernfs_activate_one(struct kernfs_node *kn) + if (kernfs_active(kn) || (kn->flags & (KERNFS_HIDDEN | KERNFS_REMOVING))) + return; + +- WARN_ON_ONCE(kn->parent && RB_EMPTY_NODE(&kn->rb)); ++ WARN_ON_ONCE(rcu_access_pointer(kn->__parent) && RB_EMPTY_NODE(&kn->rb)); + WARN_ON_ONCE(atomic_read(&kn->active) != KN_DEACTIVATED_BIAS); + + atomic_sub(KN_DEACTIVATED_BIAS, &kn->active); +@@ -1446,7 +1462,7 @@ void kernfs_show(struct kernfs_node *kn, bool show) + + static void __kernfs_remove(struct kernfs_node *kn) + { +- struct kernfs_node *pos; ++ struct kernfs_node *pos, *parent; + + /* Short-circuit if non-root @kn has already finished removal. */ + if (!kn) +@@ -1458,7 +1474,7 @@ static void __kernfs_remove(struct kernfs_node *kn) + * This is for kernfs_remove_self() which plays with active ref + * after removal. + */ +- if (kn->parent && RB_EMPTY_NODE(&kn->rb)) ++ if (kernfs_parent(kn) && RB_EMPTY_NODE(&kn->rb)) + return; + + pr_debug("kernfs %s: removing\n", kn->name); +@@ -1484,14 +1500,14 @@ static void __kernfs_remove(struct kernfs_node *kn) + kernfs_get(pos); + + kernfs_drain(pos); +- ++ parent = kernfs_parent(pos); + /* + * kernfs_unlink_sibling() succeeds once per node. Use it + * to decide who's responsible for cleanups. + */ +- if (!pos->parent || kernfs_unlink_sibling(pos)) { ++ if (!parent || kernfs_unlink_sibling(pos)) { + struct kernfs_iattrs *ps_iattr = +- pos->parent ? pos->parent->iattr : NULL; ++ parent ? parent->iattr : NULL; + + /* update timestamps on the parent */ + down_write(&kernfs_root(kn)->kernfs_iattr_rwsem); +@@ -1721,7 +1737,7 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, + int error; + + /* can't move or rename root */ +- if (!kn->parent) ++ if (!rcu_access_pointer(kn->__parent)) + return -EINVAL; + + root = kernfs_root(kn); +@@ -1732,8 +1748,15 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, + (new_parent->flags & KERNFS_EMPTY_DIR)) + goto out; + ++ old_parent = kernfs_parent(kn); ++ if (root->flags & KERNFS_ROOT_INVARIANT_PARENT) { ++ error = -EINVAL; ++ if (WARN_ON_ONCE(old_parent != new_parent)) ++ goto out; ++ } ++ + error = 0; +- if ((kn->parent == new_parent) && (kn->ns == new_ns) && ++ if ((old_parent == new_parent) && (kn->ns == new_ns) && + (strcmp(kn->name, new_name) == 0)) + goto out; /* nothing to rename */ + +@@ -1760,8 +1783,8 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, + /* rename_lock protects ->parent and ->name accessors */ + write_lock_irq(&kernfs_rename_lock); + +- old_parent = kn->parent; +- kn->parent = new_parent; ++ old_parent = kernfs_parent(kn); ++ rcu_assign_pointer(kn->__parent, new_parent); + + kn->ns = new_ns; + if (new_name) { +@@ -1794,7 +1817,8 @@ static struct kernfs_node *kernfs_dir_pos(const void *ns, + { + if (pos) { + int valid = kernfs_active(pos) && +- pos->parent == parent && hash == pos->hash; ++ rcu_access_pointer(pos->__parent) == parent && ++ hash == pos->hash; + kernfs_put(pos); + if (!valid) + pos = NULL; +diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h +index b42ee6547cdc1..c43bee18b79f7 100644 +--- a/fs/kernfs/kernfs-internal.h ++++ b/fs/kernfs/kernfs-internal.h +@@ -19,6 +19,8 @@ + #include + #include + ++extern rwlock_t kernfs_rename_lock; ++ + struct kernfs_iattrs { + kuid_t ia_uid; + kgid_t ia_gid; +@@ -64,11 +66,14 @@ struct kernfs_root { + * + * Return: the kernfs_root @kn belongs to. + */ +-static inline struct kernfs_root *kernfs_root(struct kernfs_node *kn) ++static inline struct kernfs_root *kernfs_root(const struct kernfs_node *kn) + { ++ const struct kernfs_node *knp; + /* if parent exists, it's always a dir; otherwise, @sd is a dir */ +- if (kn->parent) +- kn = kn->parent; ++ guard(rcu)(); ++ knp = rcu_dereference(kn->__parent); ++ if (knp) ++ kn = knp; + return kn->dir.root; + } + +@@ -97,6 +102,27 @@ struct kernfs_super_info { + }; + #define kernfs_info(SB) ((struct kernfs_super_info *)(SB->s_fs_info)) + ++static inline bool kernfs_root_is_locked(const struct kernfs_node *kn) ++{ ++ return lockdep_is_held(&kernfs_root(kn)->kernfs_rwsem); ++} ++ ++static inline struct kernfs_node *kernfs_parent(const struct kernfs_node *kn) ++{ ++ /* ++ * The kernfs_node::__parent remains valid within a RCU section. The kn ++ * can be reparented (and renamed) which changes the entry. This can be ++ * avoided by locking kernfs_root::kernfs_rwsem or kernfs_rename_lock. ++ * Both locks can be used to obtain a reference on __parent. Once the ++ * reference count reaches 0 then the node is about to be freed ++ * and can not be renamed (or become a different parent) anymore. ++ */ ++ return rcu_dereference_check(kn->__parent, ++ kernfs_root_is_locked(kn) || ++ lockdep_is_held(&kernfs_rename_lock) || ++ !atomic_read(&kn->count)); ++} ++ + static inline struct kernfs_node *kernfs_dentry_node(struct dentry *dentry) + { + if (d_really_is_negative(dentry)) +diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c +index 4a0ff08d589ca..2252b16e6ef0b 100644 +--- a/fs/kernfs/mount.c ++++ b/fs/kernfs/mount.c +@@ -148,7 +148,7 @@ static struct dentry *kernfs_get_parent_dentry(struct dentry *child) + struct kernfs_root *root = kernfs_root(kn); + + guard(rwsem_read)(&root->kernfs_rwsem); +- return d_obtain_alias(kernfs_get_inode(child->d_sb, kn->parent)); ++ return d_obtain_alias(kernfs_get_inode(child->d_sb, kernfs_parent(kn))); + } + + static const struct export_operations kernfs_export_ops = { +@@ -188,10 +188,10 @@ static struct kernfs_node *find_next_ancestor(struct kernfs_node *child, + return NULL; + } + +- while (child->parent != parent) { +- if (!child->parent) ++ while (kernfs_parent(child) != parent) { ++ child = kernfs_parent(child); ++ if (!child) + return NULL; +- child = child->parent; + } + + return child; +@@ -216,7 +216,7 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn, + dentry = dget(sb->s_root); + + /* Check if this is the root kernfs_node */ +- if (!kn->parent) ++ if (!rcu_access_pointer(kn->__parent)) + return dentry; + + root = kernfs_root(kn); +diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c +index 45371a70caa71..05c62ca93c53d 100644 +--- a/fs/kernfs/symlink.c ++++ b/fs/kernfs/symlink.c +@@ -62,10 +62,10 @@ static int kernfs_get_target_path(struct kernfs_node *parent, + + /* go up to the root, stop at the base */ + base = parent; +- while (base->parent) { +- kn = target->parent; +- while (kn->parent && base != kn) +- kn = kn->parent; ++ while (kernfs_parent(base)) { ++ kn = kernfs_parent(target); ++ while (kernfs_parent(kn) && base != kn) ++ kn = kernfs_parent(kn); + + if (base == kn) + break; +@@ -75,14 +75,14 @@ static int kernfs_get_target_path(struct kernfs_node *parent, + + strcpy(s, "../"); + s += 3; +- base = base->parent; ++ base = kernfs_parent(base); + } + + /* determine end of target string for reverse fillup */ + kn = target; +- while (kn->parent && kn != base) { ++ while (kernfs_parent(kn) && kn != base) { + len += strlen(kn->name) + 1; +- kn = kn->parent; ++ kn = kernfs_parent(kn); + } + + /* check limits */ +@@ -94,7 +94,7 @@ static int kernfs_get_target_path(struct kernfs_node *parent, + + /* reverse fillup of target string from target to base */ + kn = target; +- while (kn->parent && kn != base) { ++ while (kernfs_parent(kn) && kn != base) { + int slen = strlen(kn->name); + + len -= slen; +@@ -102,7 +102,7 @@ static int kernfs_get_target_path(struct kernfs_node *parent, + if (len) + s[--len] = '/'; + +- kn = kn->parent; ++ kn = kernfs_parent(kn); + } + + return 0; +@@ -111,12 +111,13 @@ static int kernfs_get_target_path(struct kernfs_node *parent, + static int kernfs_getlink(struct inode *inode, char *path) + { + struct kernfs_node *kn = inode->i_private; +- struct kernfs_node *parent = kn->parent; ++ struct kernfs_node *parent; + struct kernfs_node *target = kn->symlink.target_kn; +- struct kernfs_root *root = kernfs_root(parent); ++ struct kernfs_root *root = kernfs_root(kn); + int error; + + down_read(&root->kernfs_rwsem); ++ parent = kernfs_parent(kn); + error = kernfs_get_target_path(parent, target, path); + up_read(&root->kernfs_rwsem); + +diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c +index d1995e2d6c943..3671a3fd60198 100644 +--- a/fs/sysfs/file.c ++++ b/fs/sysfs/file.c +@@ -19,13 +19,19 @@ + + #include "sysfs.h" + ++static struct kobject *sysfs_file_kobj(struct kernfs_node *kn) ++{ ++ guard(rcu)(); ++ return rcu_dereference(kn->__parent)->priv; ++} ++ + /* + * Determine ktype->sysfs_ops for the given kernfs_node. This function + * must be called while holding an active reference. + */ + static const struct sysfs_ops *sysfs_file_ops(struct kernfs_node *kn) + { +- struct kobject *kobj = kn->parent->priv; ++ struct kobject *kobj = sysfs_file_kobj(kn); + + if (kn->flags & KERNFS_LOCKDEP) + lockdep_assert_held(kn); +@@ -40,7 +46,7 @@ static const struct sysfs_ops *sysfs_file_ops(struct kernfs_node *kn) + static int sysfs_kf_seq_show(struct seq_file *sf, void *v) + { + struct kernfs_open_file *of = sf->private; +- struct kobject *kobj = of->kn->parent->priv; ++ struct kobject *kobj = sysfs_file_kobj(of->kn); + const struct sysfs_ops *ops = sysfs_file_ops(of->kn); + ssize_t count; + char *buf; +@@ -78,7 +84,7 @@ static ssize_t sysfs_kf_bin_read(struct kernfs_open_file *of, char *buf, + size_t count, loff_t pos) + { + struct bin_attribute *battr = of->kn->priv; +- struct kobject *kobj = of->kn->parent->priv; ++ struct kobject *kobj = sysfs_file_kobj(of->kn); + loff_t size = file_inode(of->file)->i_size; + + if (!count) +@@ -102,7 +108,7 @@ static ssize_t sysfs_kf_read(struct kernfs_open_file *of, char *buf, + size_t count, loff_t pos) + { + const struct sysfs_ops *ops = sysfs_file_ops(of->kn); +- struct kobject *kobj = of->kn->parent->priv; ++ struct kobject *kobj = sysfs_file_kobj(of->kn); + ssize_t len; + + /* +@@ -128,7 +134,7 @@ static ssize_t sysfs_kf_write(struct kernfs_open_file *of, char *buf, + size_t count, loff_t pos) + { + const struct sysfs_ops *ops = sysfs_file_ops(of->kn); +- struct kobject *kobj = of->kn->parent->priv; ++ struct kobject *kobj = sysfs_file_kobj(of->kn); + + if (!count) + return 0; +@@ -141,7 +147,7 @@ static ssize_t sysfs_kf_bin_write(struct kernfs_open_file *of, char *buf, + size_t count, loff_t pos) + { + struct bin_attribute *battr = of->kn->priv; +- struct kobject *kobj = of->kn->parent->priv; ++ struct kobject *kobj = sysfs_file_kobj(of->kn); + loff_t size = file_inode(of->file)->i_size; + + if (size) { +@@ -162,7 +168,7 @@ static int sysfs_kf_bin_mmap(struct kernfs_open_file *of, + struct vm_area_struct *vma) + { + struct bin_attribute *battr = of->kn->priv; +- struct kobject *kobj = of->kn->parent->priv; ++ struct kobject *kobj = sysfs_file_kobj(of->kn); + + return battr->mmap(of->file, kobj, battr, vma); + } +@@ -171,7 +177,7 @@ static loff_t sysfs_kf_bin_llseek(struct kernfs_open_file *of, loff_t offset, + int whence) + { + struct bin_attribute *battr = of->kn->priv; +- struct kobject *kobj = of->kn->parent->priv; ++ struct kobject *kobj = sysfs_file_kobj(of->kn); + + if (battr->llseek) + return battr->llseek(of->file, kobj, battr, offset, whence); +@@ -482,7 +488,7 @@ EXPORT_SYMBOL_GPL(sysfs_break_active_protection); + */ + void sysfs_unbreak_active_protection(struct kernfs_node *kn) + { +- struct kobject *kobj = kn->parent->priv; ++ struct kobject *kobj = sysfs_file_kobj(kn); + + kernfs_unbreak_active_protection(kn); + kernfs_put(kn); +diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h +index 87c79d076d6d7..5dda9a268e44c 100644 +--- a/include/linux/kernfs.h ++++ b/include/linux/kernfs.h +@@ -147,6 +147,11 @@ enum kernfs_root_flag { + * Support user xattrs to be written to nodes rooted at this root. + */ + KERNFS_ROOT_SUPPORT_USER_XATTR = 0x0008, ++ ++ /* ++ * Renames must not change the parent node. ++ */ ++ KERNFS_ROOT_INVARIANT_PARENT = 0x0010, + }; + + /* type-specific structures for kernfs_node union members */ +@@ -199,8 +204,8 @@ struct kernfs_node { + * never moved to a different parent, it is safe to access the + * parent directly. + */ +- struct kernfs_node *parent; + const char *name; ++ struct kernfs_node __rcu *__parent; + + struct rb_node rb; + +@@ -416,6 +421,7 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn, + struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops, + unsigned int flags, void *priv); + void kernfs_destroy_root(struct kernfs_root *root); ++unsigned int kernfs_root_flags(struct kernfs_node *kn); + + struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent, + const char *name, umode_t mode, +@@ -514,6 +520,8 @@ kernfs_create_root(struct kernfs_syscall_ops *scops, unsigned int flags, + { return ERR_PTR(-ENOSYS); } + + static inline void kernfs_destroy_root(struct kernfs_root *root) { } ++static inline unsigned int kernfs_root_flags(struct kernfs_node *kn) ++{ return 0; } + + static inline struct kernfs_node * + kernfs_create_dir_ns(struct kernfs_node *parent, const char *name, +diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c +index e28d5f0d20ed0..c9752eb607ec9 100644 +--- a/kernel/cgroup/cgroup-v1.c ++++ b/kernel/cgroup/cgroup-v1.c +@@ -844,7 +844,7 @@ static int cgroup1_rename(struct kernfs_node *kn, struct kernfs_node *new_parent + + if (kernfs_type(kn) != KERNFS_DIR) + return -ENOTDIR; +- if (kn->parent != new_parent) ++ if (rcu_access_pointer(kn->__parent) != new_parent) + return -EIO; + + /* +diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c +index 62933468aaf46..6f3d942482350 100644 +--- a/kernel/cgroup/cgroup.c ++++ b/kernel/cgroup/cgroup.c +@@ -633,9 +633,22 @@ int cgroup_task_count(const struct cgroup *cgrp) + return count; + } + ++static struct cgroup *kn_priv(struct kernfs_node *kn) ++{ ++ struct kernfs_node *parent; ++ /* ++ * The parent can not be replaced due to KERNFS_ROOT_INVARIANT_PARENT. ++ * Therefore it is always safe to dereference this pointer outside of a ++ * RCU section. ++ */ ++ parent = rcu_dereference_check(kn->__parent, ++ kernfs_root_flags(kn) & KERNFS_ROOT_INVARIANT_PARENT); ++ return parent->priv; ++} ++ + struct cgroup_subsys_state *of_css(struct kernfs_open_file *of) + { +- struct cgroup *cgrp = of->kn->parent->priv; ++ struct cgroup *cgrp = kn_priv(of->kn); + struct cftype *cft = of_cft(of); + + /* +@@ -1612,7 +1625,7 @@ void cgroup_kn_unlock(struct kernfs_node *kn) + if (kernfs_type(kn) == KERNFS_DIR) + cgrp = kn->priv; + else +- cgrp = kn->parent->priv; ++ cgrp = kn_priv(kn); + + cgroup_unlock(); + +@@ -1644,7 +1657,7 @@ struct cgroup *cgroup_kn_lock_live(struct kernfs_node *kn, bool drain_offline) + if (kernfs_type(kn) == KERNFS_DIR) + cgrp = kn->priv; + else +- cgrp = kn->parent->priv; ++ cgrp = kn_priv(kn); + + /* + * We're gonna grab cgroup_mutex which nests outside kernfs +@@ -2118,7 +2131,8 @@ int cgroup_setup_root(struct cgroup_root *root, u16 ss_mask) + root->kf_root = kernfs_create_root(kf_sops, + KERNFS_ROOT_CREATE_DEACTIVATED | + KERNFS_ROOT_SUPPORT_EXPORTOP | +- KERNFS_ROOT_SUPPORT_USER_XATTR, ++ KERNFS_ROOT_SUPPORT_USER_XATTR | ++ KERNFS_ROOT_INVARIANT_PARENT, + root_cgrp); + if (IS_ERR(root->kf_root)) { + ret = PTR_ERR(root->kf_root); +@@ -4144,7 +4158,7 @@ static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf, + size_t nbytes, loff_t off) + { + struct cgroup_file_ctx *ctx = of->priv; +- struct cgroup *cgrp = of->kn->parent->priv; ++ struct cgroup *cgrp = kn_priv(of->kn); + struct cftype *cft = of_cft(of); + struct cgroup_subsys_state *css; + int ret; +diff --git a/tools/testing/selftests/bpf/progs/profiler.inc.h b/tools/testing/selftests/bpf/progs/profiler.inc.h +index 8bd1ebd7d6afd..813143b4985dc 100644 +--- a/tools/testing/selftests/bpf/progs/profiler.inc.h ++++ b/tools/testing/selftests/bpf/progs/profiler.inc.h +@@ -223,7 +223,7 @@ static INLINE void* read_full_cgroup_path(struct kernfs_node* cgroup_node, + if (bpf_cmp_likely(filepart_length, <=, MAX_PATH)) { + payload += filepart_length; + } +- cgroup_node = BPF_CORE_READ(cgroup_node, parent); ++ cgroup_node = BPF_CORE_READ(cgroup_node, __parent); + } + return payload; + } +-- +2.39.5 + diff --git a/queue-6.12/kunit-tool-use-qboot-on-qemu-x86_64.patch b/queue-6.12/kunit-tool-use-qboot-on-qemu-x86_64.patch new file mode 100644 index 0000000000..ac7d74704c --- /dev/null +++ b/queue-6.12/kunit-tool-use-qboot-on-qemu-x86_64.patch @@ -0,0 +1,46 @@ +From f5152796a339a5be91d89654f9329b7c03f4f73f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 11:01:42 +0000 +Subject: kunit: tool: Use qboot on QEMU x86_64 + +From: Brendan Jackman + +[ Upstream commit 08fafac4c9f289a9d9a22d838921e4b3eb22c664 ] + +As noted in [0], SeaBIOS (QEMU default) makes a mess of the terminal, +qboot does not. + +It turns out this is actually useful with kunit.py, since the user is +exposed to this issue if they set --raw_output=all. + +qboot is also faster than SeaBIOS, but it's is marginal for this +usecase. + +[0] https://lore.kernel.org/all/CA+i-1C0wYb-gZ8Mwh3WSVpbk-LF-Uo+njVbASJPe1WXDURoV7A@mail.gmail.com/ + +Both SeaBIOS and qboot are x86-specific. + +Link: https://lore.kernel.org/r/20250124-kunit-qboot-v1-1-815e4d4c6f7c@google.com +Signed-off-by: Brendan Jackman +Reviewed-by: David Gow +Signed-off-by: Shuah Khan +Signed-off-by: Sasha Levin +--- + tools/testing/kunit/qemu_configs/x86_64.py | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/tools/testing/kunit/qemu_configs/x86_64.py b/tools/testing/kunit/qemu_configs/x86_64.py +index dc79490768630..4a6bf4e048f5b 100644 +--- a/tools/testing/kunit/qemu_configs/x86_64.py ++++ b/tools/testing/kunit/qemu_configs/x86_64.py +@@ -7,4 +7,6 @@ CONFIG_SERIAL_8250_CONSOLE=y''', + qemu_arch='x86_64', + kernel_path='arch/x86/boot/bzImage', + kernel_command_line='console=ttyS0', +- extra_qemu_params=[]) ++ # qboot is faster than SeaBIOS and doesn't mess up ++ # the terminal. ++ extra_qemu_params=['-bios', 'qboot.rom']) +-- +2.39.5 + diff --git a/queue-6.12/leds-pwm-multicolor-add-check-for-fwnode_property_re.patch b/queue-6.12/leds-pwm-multicolor-add-check-for-fwnode_property_re.patch new file mode 100644 index 0000000000..0a44dfecab --- /dev/null +++ b/queue-6.12/leds-pwm-multicolor-add-check-for-fwnode_property_re.patch @@ -0,0 +1,40 @@ +From 9786e6d583ffe70d1d274bc486363a17b2520dbc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 23 Feb 2025 20:14:59 +0800 +Subject: leds: pwm-multicolor: Add check for fwnode_property_read_u32 + +From: Yuanjun Gong + +[ Upstream commit 6d91124e7edc109f114b1afe6d00d85d0d0ac174 ] + +Add a check to the return value of fwnode_property_read_u32() +in case it fails. + +Signed-off-by: Yuanjun Gong +Link: https://lore.kernel.org/r/20250223121459.2889484-1-ruc_gongyuanjun@163.com +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/leds/rgb/leds-pwm-multicolor.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/leds/rgb/leds-pwm-multicolor.c b/drivers/leds/rgb/leds-pwm-multicolor.c +index e1a81e0109e8a..c0aa34b1d0e2d 100644 +--- a/drivers/leds/rgb/leds-pwm-multicolor.c ++++ b/drivers/leds/rgb/leds-pwm-multicolor.c +@@ -135,8 +135,11 @@ static int led_pwm_mc_probe(struct platform_device *pdev) + + /* init the multicolor's LED class device */ + cdev = &priv->mc_cdev.led_cdev; +- fwnode_property_read_u32(mcnode, "max-brightness", ++ ret = fwnode_property_read_u32(mcnode, "max-brightness", + &cdev->max_brightness); ++ if (ret) ++ goto release_mcnode; ++ + cdev->flags = LED_CORE_SUSPENDRESUME; + cdev->brightness_set_blocking = led_pwm_mc_set; + +-- +2.39.5 + diff --git a/queue-6.12/leds-trigger-netdev-configure-led-blink-interval-for.patch b/queue-6.12/leds-trigger-netdev-configure-led-blink-interval-for.patch new file mode 100644 index 0000000000..d92a516a1d --- /dev/null +++ b/queue-6.12/leds-trigger-netdev-configure-led-blink-interval-for.patch @@ -0,0 +1,84 @@ +From f79f727c1ab20bda817c4012ce14c64974bb1c68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jan 2025 12:36:53 +0100 +Subject: leds: trigger: netdev: Configure LED blink interval for HW offload + +From: Marek Vasut + +[ Upstream commit c629c972b310af41e9e072febb6dae9a299edde6 ] + +In case a PHY LED implements .blink_set callback to set LED blink +interval, call it even if .hw_control is already set, as that LED +blink interval likely controls the blink rate of that HW offloaded +LED. For PHY LEDs, that can be their activity blinking interval. + +The software blinking is not affected by this change. + +With this change, the LED interval setting looks something like this: +$ echo netdev > /sys/class/leds/led:green:lan/trigger +$ echo 1 > /sys/class/leds/led:green:lan/brightness +$ echo 250 > /sys/class/leds/led:green:lan/interval + +Signed-off-by: Marek Vasut +Link: https://lore.kernel.org/r/20250120113740.91807-1-marex@denx.de +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/leds/trigger/ledtrig-netdev.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c +index 4b0863db901a9..356a55ced2c28 100644 +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -68,6 +68,7 @@ struct led_netdev_data { + unsigned int last_activity; + + unsigned long mode; ++ unsigned long blink_delay; + int link_speed; + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported_link_modes); + u8 duplex; +@@ -86,6 +87,10 @@ static void set_baseline_state(struct led_netdev_data *trigger_data) + /* Already validated, hw control is possible with the requested mode */ + if (trigger_data->hw_control) { + led_cdev->hw_control_set(led_cdev, trigger_data->mode); ++ if (led_cdev->blink_set) { ++ led_cdev->blink_set(led_cdev, &trigger_data->blink_delay, ++ &trigger_data->blink_delay); ++ } + + return; + } +@@ -454,10 +459,11 @@ static ssize_t interval_store(struct device *dev, + size_t size) + { + struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); ++ struct led_classdev *led_cdev = trigger_data->led_cdev; + unsigned long value; + int ret; + +- if (trigger_data->hw_control) ++ if (trigger_data->hw_control && !led_cdev->blink_set) + return -EINVAL; + + ret = kstrtoul(buf, 0, &value); +@@ -466,9 +472,13 @@ static ssize_t interval_store(struct device *dev, + + /* impose some basic bounds on the timer interval */ + if (value >= 5 && value <= 10000) { +- cancel_delayed_work_sync(&trigger_data->work); ++ if (trigger_data->hw_control) { ++ trigger_data->blink_delay = value; ++ } else { ++ cancel_delayed_work_sync(&trigger_data->work); + +- atomic_set(&trigger_data->interval, msecs_to_jiffies(value)); ++ atomic_set(&trigger_data->interval, msecs_to_jiffies(value)); ++ } + set_baseline_state(trigger_data); /* resets timer */ + } + +-- +2.39.5 + diff --git a/queue-6.12/libbpf-fix-ldx-stx-st-co-re-relocation-size-adjustme.patch b/queue-6.12/libbpf-fix-ldx-stx-st-co-re-relocation-size-adjustme.patch new file mode 100644 index 0000000000..f467012036 --- /dev/null +++ b/queue-6.12/libbpf-fix-ldx-stx-st-co-re-relocation-size-adjustme.patch @@ -0,0 +1,92 @@ +From 12c1088c278a74c6a17b523e4cd9d975f7a0ac59 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 17:48:08 -0800 +Subject: libbpf: fix LDX/STX/ST CO-RE relocation size adjustment logic + +From: Andrii Nakryiko + +[ Upstream commit 06096d19ee3897a7e70922580159607fe315da7a ] + +Libbpf has a somewhat obscure feature of automatically adjusting the +"size" of LDX/STX/ST instruction (memory store and load instructions), +based on originally recorded access size (u8, u16, u32, or u64) and the +actual size of the field on target kernel. This is meant to facilitate +using BPF CO-RE on 32-bit architectures (pointers are always 64-bit in +BPF, but host kernel's BTF will have it as 32-bit type), as well as +generally supporting safe type changes (unsigned integer type changes +can be transparently "relocated"). + +One issue that surfaced only now, 5 years after this logic was +implemented, is how this all works when dealing with fields that are +arrays. This isn't all that easy and straightforward to hit (see +selftests that reproduce this condition), but one of sched_ext BPF +programs did hit it with innocent looking loop. + +Long story short, libbpf used to calculate entire array size, instead of +making sure to only calculate array's element size. But it's the element +that is loaded by LDX/STX/ST instructions (1, 2, 4, or 8 bytes), so +that's what libbpf should check. This patch adjusts the logic for +arrays and fixed the issue. + +Reported-by: Emil Tsalapatis +Signed-off-by: Andrii Nakryiko +Acked-by: Eduard Zingerman +Link: https://lore.kernel.org/r/20250207014809.1573841-1-andrii@kernel.org +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/relo_core.c | 24 ++++++++++++++++++++---- + 1 file changed, 20 insertions(+), 4 deletions(-) + +diff --git a/tools/lib/bpf/relo_core.c b/tools/lib/bpf/relo_core.c +index 63a4d5ad12d1a..26cde1b27174b 100644 +--- a/tools/lib/bpf/relo_core.c ++++ b/tools/lib/bpf/relo_core.c +@@ -683,7 +683,7 @@ static int bpf_core_calc_field_relo(const char *prog_name, + { + const struct bpf_core_accessor *acc; + const struct btf_type *t; +- __u32 byte_off, byte_sz, bit_off, bit_sz, field_type_id; ++ __u32 byte_off, byte_sz, bit_off, bit_sz, field_type_id, elem_id; + const struct btf_member *m; + const struct btf_type *mt; + bool bitfield; +@@ -706,8 +706,14 @@ static int bpf_core_calc_field_relo(const char *prog_name, + if (!acc->name) { + if (relo->kind == BPF_CORE_FIELD_BYTE_OFFSET) { + *val = spec->bit_offset / 8; +- /* remember field size for load/store mem size */ +- sz = btf__resolve_size(spec->btf, acc->type_id); ++ /* remember field size for load/store mem size; ++ * note, for arrays we care about individual element ++ * sizes, not the overall array size ++ */ ++ t = skip_mods_and_typedefs(spec->btf, acc->type_id, &elem_id); ++ while (btf_is_array(t)) ++ t = skip_mods_and_typedefs(spec->btf, btf_array(t)->type, &elem_id); ++ sz = btf__resolve_size(spec->btf, elem_id); + if (sz < 0) + return -EINVAL; + *field_sz = sz; +@@ -767,7 +773,17 @@ static int bpf_core_calc_field_relo(const char *prog_name, + case BPF_CORE_FIELD_BYTE_OFFSET: + *val = byte_off; + if (!bitfield) { +- *field_sz = byte_sz; ++ /* remember field size for load/store mem size; ++ * note, for arrays we care about individual element ++ * sizes, not the overall array size ++ */ ++ t = skip_mods_and_typedefs(spec->btf, field_type_id, &elem_id); ++ while (btf_is_array(t)) ++ t = skip_mods_and_typedefs(spec->btf, btf_array(t)->type, &elem_id); ++ sz = btf__resolve_size(spec->btf, elem_id); ++ if (sz < 0) ++ return -EINVAL; ++ *field_sz = sz; + *type_id = field_type_id; + } + break; +-- +2.39.5 + diff --git a/queue-6.12/libbpf-fix-out-of-bound-read.patch b/queue-6.12/libbpf-fix-out-of-bound-read.patch new file mode 100644 index 0000000000..c1bea58c30 --- /dev/null +++ b/queue-6.12/libbpf-fix-out-of-bound-read.patch @@ -0,0 +1,43 @@ +From b9119a807ee2bd305525d9fdf3ae64becd443626 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Feb 2025 02:31:11 +0530 +Subject: libbpf: Fix out-of-bound read + +From: Nandakumar Edamana + +[ Upstream commit 236d3910117e9f97ebf75e511d8bcc950f1a4e5f ] + +In `set_kcfg_value_str`, an untrusted string is accessed with the assumption +that it will be at least two characters long due to the presence of checks for +opening and closing quotes. But the check for the closing quote +(value[len - 1] != '"') misses the fact that it could be checking the opening +quote itself in case of an invalid input that consists of just the opening +quote. + +This commit adds an explicit check to make sure the string is at least two +characters long. + +Signed-off-by: Nandakumar Edamana +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20250221210110.3182084-1-nandakumar@nandakumar.co.in +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/libbpf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c +index 5b45f76059296..a6bbae1e4c6b9 100644 +--- a/tools/lib/bpf/libbpf.c ++++ b/tools/lib/bpf/libbpf.c +@@ -2074,7 +2074,7 @@ static int set_kcfg_value_str(struct extern_desc *ext, char *ext_val, + } + + len = strlen(value); +- if (value[len - 1] != '"') { ++ if (len < 2 || value[len - 1] != '"') { + pr_warn("extern (kcfg) '%s': invalid string config '%s'\n", + ext->name, value); + return -EINVAL; +-- +2.39.5 + diff --git a/queue-6.12/libbpf-pass-bpf-token-from-find_prog_btf_id-to-bpf_b.patch b/queue-6.12/libbpf-pass-bpf-token-from-find_prog_btf_id-to-bpf_b.patch new file mode 100644 index 0000000000..ab86ecb911 --- /dev/null +++ b/queue-6.12/libbpf-pass-bpf-token-from-find_prog_btf_id-to-bpf_b.patch @@ -0,0 +1,166 @@ +From da78c30fd182b84458551ef74f482bcd478a17b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 17:40:38 +0000 +Subject: libbpf: Pass BPF token from find_prog_btf_id to BPF_BTF_GET_FD_BY_ID + +From: Mykyta Yatsenko + +[ Upstream commit 974ef9f0d23edc1a802691c585b84514b414a96d ] + +Pass BPF token from bpf_program__set_attach_target to +BPF_BTF_GET_FD_BY_ID bpf command. +When freplace program attaches to target program, it needs to look up +for BTF of the target, this may require BPF token, if, for example, +running from user namespace. + +Signed-off-by: Mykyta Yatsenko +Signed-off-by: Andrii Nakryiko +Acked-by: Yonghong Song +Link: https://lore.kernel.org/bpf/20250317174039.161275-4-mykyta.yatsenko5@gmail.com +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/bpf.c | 3 ++- + tools/lib/bpf/bpf.h | 3 ++- + tools/lib/bpf/btf.c | 15 +++++++++++++-- + tools/lib/bpf/libbpf.c | 10 +++++----- + tools/lib/bpf/libbpf_internal.h | 1 + + 5 files changed, 23 insertions(+), 9 deletions(-) + +diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c +index 2a4c71501a17d..72470acce67b7 100644 +--- a/tools/lib/bpf/bpf.c ++++ b/tools/lib/bpf/bpf.c +@@ -1095,7 +1095,7 @@ int bpf_map_get_fd_by_id(__u32 id) + int bpf_btf_get_fd_by_id_opts(__u32 id, + const struct bpf_get_fd_by_id_opts *opts) + { +- const size_t attr_sz = offsetofend(union bpf_attr, open_flags); ++ const size_t attr_sz = offsetofend(union bpf_attr, fd_by_id_token_fd); + union bpf_attr attr; + int fd; + +@@ -1105,6 +1105,7 @@ int bpf_btf_get_fd_by_id_opts(__u32 id, + memset(&attr, 0, attr_sz); + attr.btf_id = id; + attr.open_flags = OPTS_GET(opts, open_flags, 0); ++ attr.fd_by_id_token_fd = OPTS_GET(opts, token_fd, 0); + + fd = sys_bpf_fd(BPF_BTF_GET_FD_BY_ID, &attr, attr_sz); + return libbpf_err_errno(fd); +diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h +index a4a7b1ad1b631..b93d00968cba1 100644 +--- a/tools/lib/bpf/bpf.h ++++ b/tools/lib/bpf/bpf.h +@@ -484,9 +484,10 @@ LIBBPF_API int bpf_link_get_next_id(__u32 start_id, __u32 *next_id); + struct bpf_get_fd_by_id_opts { + size_t sz; /* size of this struct for forward/backward compatibility */ + __u32 open_flags; /* permissions requested for the operation on fd */ ++ __u32 token_fd; + size_t :0; + }; +-#define bpf_get_fd_by_id_opts__last_field open_flags ++#define bpf_get_fd_by_id_opts__last_field token_fd + + LIBBPF_API int bpf_prog_get_fd_by_id(__u32 id); + LIBBPF_API int bpf_prog_get_fd_by_id_opts(__u32 id, +diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c +index 27e7bfae953bd..3a7e0ba9f5923 100644 +--- a/tools/lib/bpf/btf.c ++++ b/tools/lib/bpf/btf.c +@@ -1618,12 +1618,18 @@ struct btf *btf_get_from_fd(int btf_fd, struct btf *base_btf) + return btf; + } + +-struct btf *btf__load_from_kernel_by_id_split(__u32 id, struct btf *base_btf) ++struct btf *btf_load_from_kernel(__u32 id, struct btf *base_btf, int token_fd) + { + struct btf *btf; + int btf_fd; ++ LIBBPF_OPTS(bpf_get_fd_by_id_opts, opts); ++ ++ if (token_fd) { ++ opts.open_flags |= BPF_F_TOKEN_FD; ++ opts.token_fd = token_fd; ++ } + +- btf_fd = bpf_btf_get_fd_by_id(id); ++ btf_fd = bpf_btf_get_fd_by_id_opts(id, &opts); + if (btf_fd < 0) + return libbpf_err_ptr(-errno); + +@@ -1633,6 +1639,11 @@ struct btf *btf__load_from_kernel_by_id_split(__u32 id, struct btf *base_btf) + return libbpf_ptr(btf); + } + ++struct btf *btf__load_from_kernel_by_id_split(__u32 id, struct btf *base_btf) ++{ ++ return btf_load_from_kernel(id, base_btf, 0); ++} ++ + struct btf *btf__load_from_kernel_by_id(__u32 id) + { + return btf__load_from_kernel_by_id_split(id, NULL); +diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c +index 5ff643e60d09c..5b45f76059296 100644 +--- a/tools/lib/bpf/libbpf.c ++++ b/tools/lib/bpf/libbpf.c +@@ -9936,7 +9936,7 @@ int libbpf_find_vmlinux_btf_id(const char *name, + return libbpf_err(err); + } + +-static int libbpf_find_prog_btf_id(const char *name, __u32 attach_prog_fd) ++static int libbpf_find_prog_btf_id(const char *name, __u32 attach_prog_fd, int token_fd) + { + struct bpf_prog_info info; + __u32 info_len = sizeof(info); +@@ -9956,7 +9956,7 @@ static int libbpf_find_prog_btf_id(const char *name, __u32 attach_prog_fd) + pr_warn("The target program doesn't have BTF\n"); + goto out; + } +- btf = btf__load_from_kernel_by_id(info.btf_id); ++ btf = btf_load_from_kernel(info.btf_id, NULL, token_fd); + err = libbpf_get_error(btf); + if (err) { + pr_warn("Failed to get BTF %d of the program: %d\n", info.btf_id, err); +@@ -10039,7 +10039,7 @@ static int libbpf_find_attach_btf_id(struct bpf_program *prog, const char *attac + pr_warn("prog '%s': attach program FD is not set\n", prog->name); + return -EINVAL; + } +- err = libbpf_find_prog_btf_id(attach_name, attach_prog_fd); ++ err = libbpf_find_prog_btf_id(attach_name, attach_prog_fd, prog->obj->token_fd); + if (err < 0) { + pr_warn("prog '%s': failed to find BPF program (FD %d) BTF ID for '%s': %d\n", + prog->name, attach_prog_fd, attach_name, err); +@@ -12804,7 +12804,7 @@ struct bpf_link *bpf_program__attach_freplace(const struct bpf_program *prog, + if (target_fd) { + LIBBPF_OPTS(bpf_link_create_opts, target_opts); + +- btf_id = libbpf_find_prog_btf_id(attach_func_name, target_fd); ++ btf_id = libbpf_find_prog_btf_id(attach_func_name, target_fd, prog->obj->token_fd); + if (btf_id < 0) + return libbpf_err_ptr(btf_id); + +@@ -13629,7 +13629,7 @@ int bpf_program__set_attach_target(struct bpf_program *prog, + + if (attach_prog_fd) { + btf_id = libbpf_find_prog_btf_id(attach_func_name, +- attach_prog_fd); ++ attach_prog_fd, prog->obj->token_fd); + if (btf_id < 0) + return libbpf_err(btf_id); + } else { +diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h +index 408df59e07719..bd7adb8594d40 100644 +--- a/tools/lib/bpf/libbpf_internal.h ++++ b/tools/lib/bpf/libbpf_internal.h +@@ -408,6 +408,7 @@ int libbpf__load_raw_btf(const char *raw_types, size_t types_len, + int btf_load_into_kernel(struct btf *btf, + char *log_buf, size_t log_sz, __u32 log_level, + int token_fd); ++struct btf *btf_load_from_kernel(__u32 id, struct btf *base_btf, int token_fd); + + struct btf *btf_get_from_fd(int btf_fd, struct btf *base_btf); + void btf_get_kernel_prefix_kind(enum bpf_attach_type attach_type, +-- +2.39.5 + diff --git a/queue-6.12/libnvdimm-labels-fix-divide-error-in-nd_label_data_i.patch b/queue-6.12/libnvdimm-labels-fix-divide-error-in-nd_label_data_i.patch new file mode 100644 index 0000000000..cfb25dc636 --- /dev/null +++ b/queue-6.12/libnvdimm-labels-fix-divide-error-in-nd_label_data_i.patch @@ -0,0 +1,64 @@ +From b589caebbffea6213b76013900f70bc3e805730c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Mar 2025 12:22:22 +0100 +Subject: libnvdimm/labels: Fix divide error in nd_label_data_init() + +From: Robert Richter + +[ Upstream commit ef1d3455bbc1922f94a91ed58d3d7db440652959 ] + +If a faulty CXL memory device returns a broken zero LSA size in its +memory device information (Identify Memory Device (Opcode 4000h), CXL +spec. 3.1, 8.2.9.9.1.1), a divide error occurs in the libnvdimm +driver: + + Oops: divide error: 0000 [#1] PREEMPT SMP NOPTI + RIP: 0010:nd_label_data_init+0x10e/0x800 [libnvdimm] + +Code and flow: + +1) CXL Command 4000h returns LSA size = 0 +2) config_size is assigned to zero LSA size (CXL pmem driver): + +drivers/cxl/pmem.c: .config_size = mds->lsa_size, + +3) max_xfer is set to zero (nvdimm driver): + +drivers/nvdimm/label.c: max_xfer = min_t(size_t, ndd->nsarea.max_xfer, config_size); + +4) A subsequent DIV_ROUND_UP() causes a division by zero: + +drivers/nvdimm/label.c: /* Make our initial read size a multiple of max_xfer size */ +drivers/nvdimm/label.c: read_size = min(DIV_ROUND_UP(read_size, max_xfer) * max_xfer, +drivers/nvdimm/label.c- config_size); + +Fix this by checking the config size parameter by extending an +existing check. + +Signed-off-by: Robert Richter +Reviewed-by: Pankaj Gupta +Reviewed-by: Ira Weiny +Link: https://patch.msgid.link/20250320112223.608320-1-rrichter@amd.com +Signed-off-by: Ira Weiny +Signed-off-by: Sasha Levin +--- + drivers/nvdimm/label.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c +index 082253a3a9560..04f4a049599a1 100644 +--- a/drivers/nvdimm/label.c ++++ b/drivers/nvdimm/label.c +@@ -442,7 +442,8 @@ int nd_label_data_init(struct nvdimm_drvdata *ndd) + if (ndd->data) + return 0; + +- if (ndd->nsarea.status || ndd->nsarea.max_xfer == 0) { ++ if (ndd->nsarea.status || ndd->nsarea.max_xfer == 0 || ++ ndd->nsarea.config_size == 0) { + dev_dbg(ndd->dev, "failed to init config data area: (%u:%u)\n", + ndd->nsarea.max_xfer, ndd->nsarea.config_size); + return -ENXIO; +-- +2.39.5 + diff --git a/queue-6.12/lockdep-fix-wait-context-check-on-softirq-for-preemp.patch b/queue-6.12/lockdep-fix-wait-context-check-on-softirq-for-preemp.patch new file mode 100644 index 0000000000..e9e7b0f8b5 --- /dev/null +++ b/queue-6.12/lockdep-fix-wait-context-check-on-softirq-for-preemp.patch @@ -0,0 +1,99 @@ +From c4da04f1b6a92ed457d0468d578cfbec40ad563c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 07:33:22 -0700 +Subject: lockdep: Fix wait context check on softirq for PREEMPT_RT + +From: Ryo Takakura + +[ Upstream commit 61c39d8c83e2077f33e0a2c8980a76a7f323f0ce ] + +Since: + + 0c1d7a2c2d32 ("lockdep: Remove softirq accounting on PREEMPT_RT.") + +the wait context test for mutex usage within "in softirq context" fails +as it references @softirq_context: + + | wait context tests | + -------------------------------------------------------------------------- + | rcu | raw | spin |mutex | + -------------------------------------------------------------------------- + in hardirq context: ok | ok | ok | ok | + in hardirq context (not threaded): ok | ok | ok | ok | + in softirq context: ok | ok | ok |FAILED| + +As a fix, add lockdep map for BH disabled section. This fixes the +issue by letting us catch cases when local_bh_disable() gets called +with preemption disabled where local_lock doesn't get acquired. +In the case of "in softirq context" selftest, local_bh_disable() was +being called with preemption disable as it's early in the boot. + +[ boqun: Move the lockdep annotations into __local_bh_*() to avoid false + positives because of unpaired local_bh_disable() reported by + Borislav Petkov and Peter Zijlstra, and make bh_lock_map + only exist for PREEMPT_RT. ] + +[ mingo: Restored authorship and improved the bh_lock_map definition. ] + +Signed-off-by: Ryo Takakura +Signed-off-by: Boqun Feng +Signed-off-by: Ingo Molnar +Link: https://lore.kernel.org/r/20250321143322.79651-1-boqun.feng@gmail.com +Signed-off-by: Sasha Levin +--- + kernel/softirq.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/kernel/softirq.c b/kernel/softirq.c +index 8c4524ce65faf..00ff176350413 100644 +--- a/kernel/softirq.c ++++ b/kernel/softirq.c +@@ -126,6 +126,18 @@ static DEFINE_PER_CPU(struct softirq_ctrl, softirq_ctrl) = { + .lock = INIT_LOCAL_LOCK(softirq_ctrl.lock), + }; + ++#ifdef CONFIG_DEBUG_LOCK_ALLOC ++static struct lock_class_key bh_lock_key; ++struct lockdep_map bh_lock_map = { ++ .name = "local_bh", ++ .key = &bh_lock_key, ++ .wait_type_outer = LD_WAIT_FREE, ++ .wait_type_inner = LD_WAIT_CONFIG, /* PREEMPT_RT makes BH preemptible. */ ++ .lock_type = LD_LOCK_PERCPU, ++}; ++EXPORT_SYMBOL_GPL(bh_lock_map); ++#endif ++ + /** + * local_bh_blocked() - Check for idle whether BH processing is blocked + * +@@ -148,6 +160,8 @@ void __local_bh_disable_ip(unsigned long ip, unsigned int cnt) + + WARN_ON_ONCE(in_hardirq()); + ++ lock_map_acquire_read(&bh_lock_map); ++ + /* First entry of a task into a BH disabled section? */ + if (!current->softirq_disable_cnt) { + if (preemptible()) { +@@ -211,6 +225,8 @@ void __local_bh_enable_ip(unsigned long ip, unsigned int cnt) + WARN_ON_ONCE(in_hardirq()); + lockdep_assert_irqs_enabled(); + ++ lock_map_release(&bh_lock_map); ++ + local_irq_save(flags); + curcnt = __this_cpu_read(softirq_ctrl.cnt); + +@@ -261,6 +277,8 @@ static inline void ksoftirqd_run_begin(void) + /* Counterpart to ksoftirqd_run_begin() */ + static inline void ksoftirqd_run_end(void) + { ++ /* pairs with the lock_map_acquire_read() in ksoftirqd_run_begin() */ ++ lock_map_release(&bh_lock_map); + __local_bh_enable(SOFTIRQ_OFFSET, true); + WARN_ON_ONCE(in_interrupt()); + local_irq_enable(); +-- +2.39.5 + diff --git a/queue-6.12/loop-check-in-lo_flags_direct_io-in-loop_default_blo.patch b/queue-6.12/loop-check-in-lo_flags_direct_io-in-loop_default_blo.patch new file mode 100644 index 0000000000..b7544cbf28 --- /dev/null +++ b/queue-6.12/loop-check-in-lo_flags_direct_io-in-loop_default_blo.patch @@ -0,0 +1,40 @@ +From ef90256884af79b879dab890a6cdaf0026a4f557 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 13:00:40 +0100 +Subject: loop: check in LO_FLAGS_DIRECT_IO in loop_default_blocksize + +From: Christoph Hellwig + +[ Upstream commit f6f9e32fe1e454ae8ac0190b2c2bd6074914beec ] + +We can't go below the minimum direct I/O size no matter if direct I/O is +enabled by passing in an O_DIRECT file descriptor or due to the explicit +flag. Now that LO_FLAGS_DIRECT_IO is set earlier after assigning a +backing file, loop_default_blocksize can check it instead of the +O_DIRECT flag to handle both conditions. + +Signed-off-by: Christoph Hellwig +Reviewed-by: Damien Le Moal +Link: https://lore.kernel.org/r/20250131120120.1315125-4-hch@lst.de +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/block/loop.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/block/loop.c b/drivers/block/loop.c +index 6bd44ec2c9b1a..fa9c77b8f4d23 100644 +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -916,7 +916,7 @@ static unsigned int loop_default_blocksize(struct loop_device *lo, + struct block_device *backing_bdev) + { + /* In case of direct I/O, match underlying block size */ +- if ((lo->lo_backing_file->f_flags & O_DIRECT) && backing_bdev) ++ if ((lo->lo_flags & LO_FLAGS_DIRECT_IO) && backing_bdev) + return bdev_logical_block_size(backing_bdev); + return SECTOR_SIZE; + } +-- +2.39.5 + diff --git a/queue-6.12/mailbox-pcc-use-acpi_os_ioremap-instead-of-ioremap.patch b/queue-6.12/mailbox-pcc-use-acpi_os_ioremap-instead-of-ioremap.patch new file mode 100644 index 0000000000..2638fa8da0 --- /dev/null +++ b/queue-6.12/mailbox-pcc-use-acpi_os_ioremap-instead-of-ioremap.patch @@ -0,0 +1,49 @@ +From 447e64f82bd12d1345910b87b861dd3e3be4a34c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 15:28:51 +0000 +Subject: mailbox: pcc: Use acpi_os_ioremap() instead of ioremap() + +From: Sudeep Holla + +[ Upstream commit d181acea5b864e91f38f5771b8961215ce5017ae ] + +The Platform Communication Channel (PCC) mailbox driver currently uses +ioremap() to map channel shared memory regions. However it is preferred +to use acpi_os_ioremap(), which is mapping function specific to EFI/ACPI +defined memory regions. It ensures that the correct memory attributes +are applied when mapping ACPI-provided regions. + +While at it, also add checks for handling any errors with the mapping. + +Acked-by: Huisong Li +Tested-by: Huisong Li +Tested-by: Adam Young +Signed-off-by: Sudeep Holla +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/pcc.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c +index f8215a8f656a4..49254d99a8ad6 100644 +--- a/drivers/mailbox/pcc.c ++++ b/drivers/mailbox/pcc.c +@@ -419,8 +419,12 @@ int pcc_mbox_ioremap(struct mbox_chan *chan) + return -1; + pchan_info = chan->con_priv; + pcc_mbox_chan = &pchan_info->chan; +- pcc_mbox_chan->shmem = ioremap(pcc_mbox_chan->shmem_base_addr, +- pcc_mbox_chan->shmem_size); ++ ++ pcc_mbox_chan->shmem = acpi_os_ioremap(pcc_mbox_chan->shmem_base_addr, ++ pcc_mbox_chan->shmem_size); ++ if (!pcc_mbox_chan->shmem) ++ return -ENXIO; ++ + return 0; + } + EXPORT_SYMBOL_GPL(pcc_mbox_ioremap); +-- +2.39.5 + diff --git a/queue-6.12/mailbox-use-error-ret-code-of-of_parse_phandle_with_.patch b/queue-6.12/mailbox-use-error-ret-code-of-of_parse_phandle_with_.patch new file mode 100644 index 0000000000..395c6c766a --- /dev/null +++ b/queue-6.12/mailbox-use-error-ret-code-of-of_parse_phandle_with_.patch @@ -0,0 +1,45 @@ +From d9bd5d918832283161732ff824ad0e2b5250812c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 08:27:13 +0000 +Subject: mailbox: use error ret code of of_parse_phandle_with_args() + +From: Tudor Ambarus + +[ Upstream commit 24fdd5074b205cfb0ef4cd0751a2d03031455929 ] + +In case of error, of_parse_phandle_with_args() returns -EINVAL when the +passed index is negative, or -ENOENT when the index is for an empty +phandle. The mailbox core overwrote the error return code with a less +precise -ENODEV. Use the error returned code from +of_parse_phandle_with_args(). + +Signed-off-by: Tudor Ambarus +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/mailbox.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c +index d3d26a2c98956..cb174e788a96c 100644 +--- a/drivers/mailbox/mailbox.c ++++ b/drivers/mailbox/mailbox.c +@@ -415,11 +415,12 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index) + + mutex_lock(&con_mutex); + +- if (of_parse_phandle_with_args(dev->of_node, "mboxes", +- "#mbox-cells", index, &spec)) { ++ ret = of_parse_phandle_with_args(dev->of_node, "mboxes", "#mbox-cells", ++ index, &spec); ++ if (ret) { + dev_dbg(dev, "%s: can't parse \"mboxes\" property\n", __func__); + mutex_unlock(&con_mutex); +- return ERR_PTR(-ENODEV); ++ return ERR_PTR(ret); + } + + chan = ERR_PTR(-EPROBE_DEFER); +-- +2.39.5 + diff --git a/queue-6.12/mctp-fix-incorrect-tx-flow-invalidation-condition-in.patch b/queue-6.12/mctp-fix-incorrect-tx-flow-invalidation-condition-in.patch new file mode 100644 index 0000000000..5a2007111a --- /dev/null +++ b/queue-6.12/mctp-fix-incorrect-tx-flow-invalidation-condition-in.patch @@ -0,0 +1,41 @@ +From 055b660be507baec9d3ca5ceeb5cdcd5e89e2896 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Mar 2025 16:10:08 +0800 +Subject: mctp: Fix incorrect tx flow invalidation condition in mctp-i2c + +From: Daniel Hsu + +[ Upstream commit 70facbf978ac90c6da17a3de2a8dd111b06f1bac ] + +Previously, the condition for invalidating the tx flow in +mctp_i2c_invalidate_tx_flow() checked if `rc` was nonzero. +However, this could incorrectly trigger the invalidation +even when `rc > 0` was returned as a success status. + +This patch updates the condition to explicitly check for `rc < 0`, +ensuring that only error cases trigger the invalidation. + +Signed-off-by: Daniel Hsu +Reviewed-by: Jeremy Kerr +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/mctp/mctp-i2c.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/mctp/mctp-i2c.c b/drivers/net/mctp/mctp-i2c.c +index 6622de48fc9e7..503a9174321c6 100644 +--- a/drivers/net/mctp/mctp-i2c.c ++++ b/drivers/net/mctp/mctp-i2c.c +@@ -538,7 +538,7 @@ static void mctp_i2c_xmit(struct mctp_i2c_dev *midev, struct sk_buff *skb) + rc = __i2c_transfer(midev->adapter, &msg, 1); + + /* on tx errors, the flow can no longer be considered valid */ +- if (rc) ++ if (rc < 0) + mctp_i2c_invalidate_tx_flow(midev, skb); + + break; +-- +2.39.5 + diff --git a/queue-6.12/media-adv7180-disable-test-pattern-control-on-adv718.patch b/queue-6.12/media-adv7180-disable-test-pattern-control-on-adv718.patch new file mode 100644 index 0000000000..48170580c9 --- /dev/null +++ b/queue-6.12/media-adv7180-disable-test-pattern-control-on-adv718.patch @@ -0,0 +1,131 @@ +From f08f30b2a35f77403ae41590970047194b01e620 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Feb 2025 00:09:07 +0100 +Subject: media: adv7180: Disable test-pattern control on adv7180 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Niklas Söderlund + +[ Upstream commit a980bc5f56b0292336e408f657f79e574e8067c0 ] + +The register that enables selecting a test-pattern to be outputted in +free-run mode (FREE_RUN_PAT_SEL[2:0]) is only available on adv7280 based +devices, not the adv7180 based ones. + +Add a flag to mark devices that are capable of generating test-patterns, +and those that are not. And only register the control on supported +devices. + +Signed-off-by: Niklas Söderlund +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/i2c/adv7180.c | 34 ++++++++++++++++++++++------------ + 1 file changed, 22 insertions(+), 12 deletions(-) + +diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c +index 819ff9f7c90fe..2a20a4fad796c 100644 +--- a/drivers/media/i2c/adv7180.c ++++ b/drivers/media/i2c/adv7180.c +@@ -195,6 +195,7 @@ struct adv7180_state; + #define ADV7180_FLAG_V2 BIT(1) + #define ADV7180_FLAG_MIPI_CSI2 BIT(2) + #define ADV7180_FLAG_I2P BIT(3) ++#define ADV7180_FLAG_TEST_PATTERN BIT(4) + + struct adv7180_chip_info { + unsigned int flags; +@@ -682,11 +683,15 @@ static int adv7180_init_controls(struct adv7180_state *state) + ADV7180_HUE_MAX, 1, ADV7180_HUE_DEF); + v4l2_ctrl_new_custom(&state->ctrl_hdl, &adv7180_ctrl_fast_switch, NULL); + +- v4l2_ctrl_new_std_menu_items(&state->ctrl_hdl, &adv7180_ctrl_ops, +- V4L2_CID_TEST_PATTERN, +- ARRAY_SIZE(test_pattern_menu) - 1, +- 0, ARRAY_SIZE(test_pattern_menu) - 1, +- test_pattern_menu); ++ if (state->chip_info->flags & ADV7180_FLAG_TEST_PATTERN) { ++ v4l2_ctrl_new_std_menu_items(&state->ctrl_hdl, ++ &adv7180_ctrl_ops, ++ V4L2_CID_TEST_PATTERN, ++ ARRAY_SIZE(test_pattern_menu) - 1, ++ 0, ++ ARRAY_SIZE(test_pattern_menu) - 1, ++ test_pattern_menu); ++ } + + state->sd.ctrl_handler = &state->ctrl_hdl; + if (state->ctrl_hdl.error) { +@@ -1221,7 +1226,7 @@ static const struct adv7180_chip_info adv7182_info = { + }; + + static const struct adv7180_chip_info adv7280_info = { +- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P, ++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P | ADV7180_FLAG_TEST_PATTERN, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN3) | +@@ -1235,7 +1240,8 @@ static const struct adv7180_chip_info adv7280_info = { + }; + + static const struct adv7180_chip_info adv7280_m_info = { +- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P, ++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P | ++ ADV7180_FLAG_TEST_PATTERN, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN3) | +@@ -1256,7 +1262,8 @@ static const struct adv7180_chip_info adv7280_m_info = { + }; + + static const struct adv7180_chip_info adv7281_info = { +- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2, ++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ++ ADV7180_FLAG_TEST_PATTERN, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN7) | +@@ -1271,7 +1278,8 @@ static const struct adv7180_chip_info adv7281_info = { + }; + + static const struct adv7180_chip_info adv7281_m_info = { +- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2, ++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ++ ADV7180_FLAG_TEST_PATTERN, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN3) | +@@ -1291,7 +1299,8 @@ static const struct adv7180_chip_info adv7281_m_info = { + }; + + static const struct adv7180_chip_info adv7281_ma_info = { +- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2, ++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ++ ADV7180_FLAG_TEST_PATTERN, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN3) | +@@ -1316,7 +1325,7 @@ static const struct adv7180_chip_info adv7281_ma_info = { + }; + + static const struct adv7180_chip_info adv7282_info = { +- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P, ++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P | ADV7180_FLAG_TEST_PATTERN, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN7) | +@@ -1331,7 +1340,8 @@ static const struct adv7180_chip_info adv7282_info = { + }; + + static const struct adv7180_chip_info adv7282_m_info = { +- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P, ++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P | ++ ADV7180_FLAG_TEST_PATTERN, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN3) | +-- +2.39.5 + diff --git a/queue-6.12/media-c8sectpfe-call-of_node_put-i2c_bus-only-once-i.patch b/queue-6.12/media-c8sectpfe-call-of_node_put-i2c_bus-only-once-i.patch new file mode 100644 index 0000000000..64a25a9a74 --- /dev/null +++ b/queue-6.12/media-c8sectpfe-call-of_node_put-i2c_bus-only-once-i.patch @@ -0,0 +1,45 @@ +From 9770160e0708362fff8d01e944e026917e3077b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Oct 2024 15:50:15 +0200 +Subject: media: c8sectpfe: Call of_node_put(i2c_bus) only once in + c8sectpfe_probe() + +From: Markus Elfring + +[ Upstream commit b773530a34df0687020520015057075f8b7b4ac4 ] + +An of_node_put(i2c_bus) call was immediately used after a pointer check +for an of_find_i2c_adapter_by_node() call in this function implementation. +Thus call such a function only once instead directly before the check. + +This issue was transformed by using the Coccinelle software. + +Signed-off-by: Markus Elfring +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c +index 67d3d6e50d2e2..ed3a107965cc9 100644 +--- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c ++++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c +@@ -797,13 +797,12 @@ static int c8sectpfe_probe(struct platform_device *pdev) + } + tsin->i2c_adapter = + of_find_i2c_adapter_by_node(i2c_bus); ++ of_node_put(i2c_bus); + if (!tsin->i2c_adapter) { + dev_err(&pdev->dev, "No i2c adapter found\n"); +- of_node_put(i2c_bus); + ret = -ENODEV; + goto err_node_put; + } +- of_node_put(i2c_bus); + + /* Acquire reset GPIO and activate it */ + tsin->rst_gpio = devm_fwnode_gpiod_get(dev, +-- +2.39.5 + diff --git a/queue-6.12/media-cx231xx-set-device_caps-for-417.patch b/queue-6.12/media-cx231xx-set-device_caps-for-417.patch new file mode 100644 index 0000000000..09e1260047 --- /dev/null +++ b/queue-6.12/media-cx231xx-set-device_caps-for-417.patch @@ -0,0 +1,40 @@ +From b833aafb62c4bb7c72bef6bdebe2758e72cf5f85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 14:13:24 +0100 +Subject: media: cx231xx: set device_caps for 417 + +From: Hans Verkuil + +[ Upstream commit a79efc44b51432490538a55b9753a721f7d3ea42 ] + +The video_device for the MPEG encoder did not set device_caps. + +Add this, otherwise the video device can't be registered (you get a +WARN_ON instead). + +Not seen before since currently 417 support is disabled, but I found +this while experimenting with it. + +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/usb/cx231xx/cx231xx-417.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c +index abb967c8bd352..6cb130eb32d58 100644 +--- a/drivers/media/usb/cx231xx/cx231xx-417.c ++++ b/drivers/media/usb/cx231xx/cx231xx-417.c +@@ -1722,6 +1722,8 @@ static void cx231xx_video_dev_init( + vfd->lock = &dev->lock; + vfd->release = video_device_release_empty; + vfd->ctrl_handler = &dev->mpeg_ctrl_handler.hdl; ++ vfd->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | ++ V4L2_CAP_VIDEO_CAPTURE; + video_set_drvdata(vfd, dev); + if (dev->tuner_type == TUNER_ABSENT) { + v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY); +-- +2.39.5 + diff --git a/queue-6.12/media-i2c-imx219-correct-the-minimum-vblanking-value.patch b/queue-6.12/media-i2c-imx219-correct-the-minimum-vblanking-value.patch new file mode 100644 index 0000000000..cd1d4a105f --- /dev/null +++ b/queue-6.12/media-i2c-imx219-correct-the-minimum-vblanking-value.patch @@ -0,0 +1,40 @@ +From 6df4d594e67986c11cb60e2ebe51ed447b68253e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 12:34:36 +0530 +Subject: media: i2c: imx219: Correct the minimum vblanking value + +From: David Plowman + +[ Upstream commit e3b82d49bf676f3c873e642038765eac32ab6d39 ] + +The datasheet for this sensor documents the minimum vblanking as being +32 lines. It does fix some problems with occasional black lines at the +bottom of images (tested on Raspberry Pi). + +Signed-off-by: David Plowman +Reviewed-by: Jacopo Mondi +Reviewed-by: Dave Stevenson +Signed-off-by: Jai Luthra +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/i2c/imx219.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c +index 906aa314b7f84..eaa1496c71bb2 100644 +--- a/drivers/media/i2c/imx219.c ++++ b/drivers/media/i2c/imx219.c +@@ -74,7 +74,7 @@ + #define IMX219_REG_VTS CCI_REG16(0x0160) + #define IMX219_VTS_MAX 0xffff + +-#define IMX219_VBLANK_MIN 4 ++#define IMX219_VBLANK_MIN 32 + + /* HBLANK control - read only */ + #define IMX219_PPL_DEFAULT 3448 +-- +2.39.5 + diff --git a/queue-6.12/media-imx335-set-vblank-immediately.patch b/queue-6.12/media-imx335-set-vblank-immediately.patch new file mode 100644 index 0000000000..49a4e8f36a --- /dev/null +++ b/queue-6.12/media-imx335-set-vblank-immediately.patch @@ -0,0 +1,66 @@ +From 8a3fcaaab84400909e46a900179a06d9388cdbda Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 18:17:31 +0900 +Subject: media: imx335: Set vblank immediately + +From: Paul Elder + +[ Upstream commit c0aa40f45fef80b4182704d1bc089cbf8ae8bed0 ] + +When the vblank v4l2 control is set, it does not get written to the +hardware unless exposure is also changed. Change the behavior such that +the vblank is written immediately when the control is set, as setting +the vblank without changing the exposure is a valid use case (such as +for changing the frame rate). + +Signed-off-by: Paul Elder +Reviewed-by: Kieran Bingham +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/i2c/imx335.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c +index fcfd1d851bd4a..0beb80b8c4581 100644 +--- a/drivers/media/i2c/imx335.c ++++ b/drivers/media/i2c/imx335.c +@@ -559,12 +559,14 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl) + imx335->vblank, + imx335->vblank + imx335->cur_mode->height); + +- return __v4l2_ctrl_modify_range(imx335->exp_ctrl, +- IMX335_EXPOSURE_MIN, +- imx335->vblank + +- imx335->cur_mode->height - +- IMX335_EXPOSURE_OFFSET, +- 1, IMX335_EXPOSURE_DEFAULT); ++ ret = __v4l2_ctrl_modify_range(imx335->exp_ctrl, ++ IMX335_EXPOSURE_MIN, ++ imx335->vblank + ++ imx335->cur_mode->height - ++ IMX335_EXPOSURE_OFFSET, ++ 1, IMX335_EXPOSURE_DEFAULT); ++ if (ret) ++ return ret; + } + + /* +@@ -575,6 +577,13 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl) + return 0; + + switch (ctrl->id) { ++ case V4L2_CID_VBLANK: ++ exposure = imx335->exp_ctrl->val; ++ analog_gain = imx335->again_ctrl->val; ++ ++ ret = imx335_update_exp_gain(imx335, exposure, analog_gain); ++ ++ break; + case V4L2_CID_EXPOSURE: + exposure = ctrl->val; + analog_gain = imx335->again_ctrl->val; +-- +2.39.5 + diff --git a/queue-6.12/media-qcom-camss-add-default-case-in-vfe_src_pad_cod.patch b/queue-6.12/media-qcom-camss-add-default-case-in-vfe_src_pad_cod.patch new file mode 100644 index 0000000000..9ea3083179 --- /dev/null +++ b/queue-6.12/media-qcom-camss-add-default-case-in-vfe_src_pad_cod.patch @@ -0,0 +1,38 @@ +From 73ac4ff467a0c1afd8af098e2c8ce86ca34f7662 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 10:01:27 +0530 +Subject: media: qcom: camss: Add default case in vfe_src_pad_code + +From: Depeng Shao + +[ Upstream commit 2f4204bb00b32eca3391a468d3b37e87feb96fa9 ] + +Add a default case in vfe_src_pad_code to get rid of a compile +warning if a new hw enum is added. + +Signed-off-by: Depeng Shao +Reviewed-by: Bryan O'Donoghue +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/platform/qcom/camss/camss-vfe.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c +index 83c5a36d071fc..8f6b0eccefb48 100644 +--- a/drivers/media/platform/qcom/camss/camss-vfe.c ++++ b/drivers/media/platform/qcom/camss/camss-vfe.c +@@ -398,6 +398,10 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, + return sink_code; + } + break; ++ default: ++ WARN(1, "Unsupported HW version: %x\n", ++ vfe->camss->res->version); ++ break; + } + return 0; + } +-- +2.39.5 + diff --git a/queue-6.12/media-qcom-camss-csid-only-add-tpg-v4l2-ctrl-if-tpg-.patch b/queue-6.12/media-qcom-camss-csid-only-add-tpg-v4l2-ctrl-if-tpg-.patch new file mode 100644 index 0000000000..1b242e67c5 --- /dev/null +++ b/queue-6.12/media-qcom-camss-csid-only-add-tpg-v4l2-ctrl-if-tpg-.patch @@ -0,0 +1,141 @@ +From 99aac56eccccccd8650abeb71c9c369aaab78439 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 10:01:28 +0530 +Subject: media: qcom: camss: csid: Only add TPG v4l2 ctrl if TPG hardware is + available + +From: Depeng Shao + +[ Upstream commit 2f1361f862a68063f37362f1beb400e78e289581 ] + +There is no CSID TPG on some SoCs, so the v4l2 ctrl in CSID driver +shouldn't be registered. Checking the supported TPG modes to indicate +if the TPG hardware exists or not and only registering v4l2 ctrl for +CSID only when the TPG hardware is present. + +Signed-off-by: Depeng Shao +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + .../media/platform/qcom/camss/camss-csid.c | 60 +++++++++++-------- + 1 file changed, 35 insertions(+), 25 deletions(-) + +diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c +index 858db5d4ca75c..e51f2ed3f0315 100644 +--- a/drivers/media/platform/qcom/camss/camss-csid.c ++++ b/drivers/media/platform/qcom/camss/camss-csid.c +@@ -683,11 +683,13 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable) + int ret; + + if (enable) { +- ret = v4l2_ctrl_handler_setup(&csid->ctrls); +- if (ret < 0) { +- dev_err(csid->camss->dev, +- "could not sync v4l2 controls: %d\n", ret); +- return ret; ++ if (csid->testgen.nmodes != CSID_PAYLOAD_MODE_DISABLED) { ++ ret = v4l2_ctrl_handler_setup(&csid->ctrls); ++ if (ret < 0) { ++ dev_err(csid->camss->dev, ++ "could not sync v4l2 controls: %d\n", ret); ++ return ret; ++ } + } + + if (!csid->testgen.enabled && +@@ -761,7 +763,8 @@ static void csid_try_format(struct csid_device *csid, + break; + + case MSM_CSID_PAD_SRC: +- if (csid->testgen_mode->cur.val == 0) { ++ if (csid->testgen.nmodes == CSID_PAYLOAD_MODE_DISABLED || ++ csid->testgen_mode->cur.val == 0) { + /* Test generator is disabled, */ + /* keep pad formats in sync */ + u32 code = fmt->code; +@@ -811,7 +814,8 @@ static int csid_enum_mbus_code(struct v4l2_subdev *sd, + + code->code = csid->res->formats->formats[code->index].code; + } else { +- if (csid->testgen_mode->cur.val == 0) { ++ if (csid->testgen.nmodes == CSID_PAYLOAD_MODE_DISABLED || ++ csid->testgen_mode->cur.val == 0) { + struct v4l2_mbus_framefmt *sink_fmt; + + sink_fmt = __csid_get_format(csid, sd_state, +@@ -1190,7 +1194,8 @@ static int csid_link_setup(struct media_entity *entity, + + /* If test generator is enabled */ + /* do not allow a link from CSIPHY to CSID */ +- if (csid->testgen_mode->cur.val != 0) ++ if (csid->testgen.nmodes != CSID_PAYLOAD_MODE_DISABLED && ++ csid->testgen_mode->cur.val != 0) + return -EBUSY; + + sd = media_entity_to_v4l2_subdev(remote->entity); +@@ -1283,24 +1288,27 @@ int msm_csid_register_entity(struct csid_device *csid, + MSM_CSID_NAME, csid->id); + v4l2_set_subdevdata(sd, csid); + +- ret = v4l2_ctrl_handler_init(&csid->ctrls, 1); +- if (ret < 0) { +- dev_err(dev, "Failed to init ctrl handler: %d\n", ret); +- return ret; +- } ++ if (csid->testgen.nmodes != CSID_PAYLOAD_MODE_DISABLED) { ++ ret = v4l2_ctrl_handler_init(&csid->ctrls, 1); ++ if (ret < 0) { ++ dev_err(dev, "Failed to init ctrl handler: %d\n", ret); ++ return ret; ++ } + +- csid->testgen_mode = v4l2_ctrl_new_std_menu_items(&csid->ctrls, +- &csid_ctrl_ops, V4L2_CID_TEST_PATTERN, +- csid->testgen.nmodes, 0, 0, +- csid->testgen.modes); ++ csid->testgen_mode = ++ v4l2_ctrl_new_std_menu_items(&csid->ctrls, ++ &csid_ctrl_ops, V4L2_CID_TEST_PATTERN, ++ csid->testgen.nmodes, 0, 0, ++ csid->testgen.modes); + +- if (csid->ctrls.error) { +- dev_err(dev, "Failed to init ctrl: %d\n", csid->ctrls.error); +- ret = csid->ctrls.error; +- goto free_ctrl; +- } ++ if (csid->ctrls.error) { ++ dev_err(dev, "Failed to init ctrl: %d\n", csid->ctrls.error); ++ ret = csid->ctrls.error; ++ goto free_ctrl; ++ } + +- csid->subdev.ctrl_handler = &csid->ctrls; ++ csid->subdev.ctrl_handler = &csid->ctrls; ++ } + + ret = csid_init_formats(sd, NULL); + if (ret < 0) { +@@ -1331,7 +1339,8 @@ int msm_csid_register_entity(struct csid_device *csid, + media_cleanup: + media_entity_cleanup(&sd->entity); + free_ctrl: +- v4l2_ctrl_handler_free(&csid->ctrls); ++ if (csid->testgen.nmodes != CSID_PAYLOAD_MODE_DISABLED) ++ v4l2_ctrl_handler_free(&csid->ctrls); + + return ret; + } +@@ -1344,7 +1353,8 @@ void msm_csid_unregister_entity(struct csid_device *csid) + { + v4l2_device_unregister_subdev(&csid->subdev); + media_entity_cleanup(&csid->subdev.entity); +- v4l2_ctrl_handler_free(&csid->ctrls); ++ if (csid->testgen.nmodes != CSID_PAYLOAD_MODE_DISABLED) ++ v4l2_ctrl_handler_free(&csid->ctrls); + } + + inline bool csid_is_lite(struct csid_device *csid) +-- +2.39.5 + diff --git a/queue-6.12/media-tc358746-improve-calculation-of-the-d-phy-timi.patch b/queue-6.12/media-tc358746-improve-calculation-of-the-d-phy-timi.patch new file mode 100644 index 0000000000..7370d31c3c --- /dev/null +++ b/queue-6.12/media-tc358746-improve-calculation-of-the-d-phy-timi.patch @@ -0,0 +1,80 @@ +From f6498b7806e50e1ae786d97501c98dfde3aa242a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jan 2025 17:07:01 +0100 +Subject: media: tc358746: improve calculation of the D-PHY timing registers + +From: Matthias Fend + +[ Upstream commit 78d7265e2e1ce349e7f3c6a085f2b66d7b73f4ca ] + +When calculating D-PHY registers, using data rates that are not multiples +of 16 can lead to precision loss in division operations. This can result in +register values that produce timing violations against the MIPI standard. + +An example: +cfg->hs_clk_rate = 294MHz +hf_clk = 18 + +If the desired value in cfg->init is 100us, which is the minimum allowed +value, then the LINEINITCNT register is calculated as 1799. But since the +actual clock is 18.375MHz instead of 18MHz, this setting results in a time +that is shorter than 100us and thus violates the standard. The correct +value for LINEINITCNT would be 1837. + +Improve the precision of calculations by using Hz instead of MHz as unit. + +Signed-off-by: Matthias Fend +Reviewed-by: Marco Felsch +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/i2c/tc358746.c | 19 +++++++------------ + 1 file changed, 7 insertions(+), 12 deletions(-) + +diff --git a/drivers/media/i2c/tc358746.c b/drivers/media/i2c/tc358746.c +index 389582420ba78..048a1a381b333 100644 +--- a/drivers/media/i2c/tc358746.c ++++ b/drivers/media/i2c/tc358746.c +@@ -460,24 +460,20 @@ static int tc358746_apply_misc_config(struct tc358746 *tc358746) + return err; + } + +-/* Use MHz as base so the div needs no u64 */ +-static u32 tc358746_cfg_to_cnt(unsigned int cfg_val, +- unsigned int clk_mhz, +- unsigned int time_base) ++static u32 tc358746_cfg_to_cnt(unsigned long cfg_val, unsigned long clk_hz, ++ unsigned long long time_base) + { +- return DIV_ROUND_UP(cfg_val * clk_mhz, time_base); ++ return div64_u64((u64)cfg_val * clk_hz + time_base - 1, time_base); + } + +-static u32 tc358746_ps_to_cnt(unsigned int cfg_val, +- unsigned int clk_mhz) ++static u32 tc358746_ps_to_cnt(unsigned long cfg_val, unsigned long clk_hz) + { +- return tc358746_cfg_to_cnt(cfg_val, clk_mhz, USEC_PER_SEC); ++ return tc358746_cfg_to_cnt(cfg_val, clk_hz, PSEC_PER_SEC); + } + +-static u32 tc358746_us_to_cnt(unsigned int cfg_val, +- unsigned int clk_mhz) ++static u32 tc358746_us_to_cnt(unsigned long cfg_val, unsigned long clk_hz) + { +- return tc358746_cfg_to_cnt(cfg_val, clk_mhz, 1); ++ return tc358746_cfg_to_cnt(cfg_val, clk_hz, USEC_PER_SEC); + } + + static int tc358746_apply_dphy_config(struct tc358746 *tc358746) +@@ -492,7 +488,6 @@ static int tc358746_apply_dphy_config(struct tc358746 *tc358746) + + /* The hs_byte_clk is also called SYSCLK in the excel sheet */ + hs_byte_clk = cfg->hs_clk_rate / 8; +- hs_byte_clk /= HZ_PER_MHZ; + hf_clk = hs_byte_clk / 2; + + val = tc358746_us_to_cnt(cfg->init, hf_clk) - 1; +-- +2.39.5 + diff --git a/queue-6.12/media-test-drivers-vivid-don-t-call-schedule-in-loop.patch b/queue-6.12/media-test-drivers-vivid-don-t-call-schedule-in-loop.patch new file mode 100644 index 0000000000..45d176b000 --- /dev/null +++ b/queue-6.12/media-test-drivers-vivid-don-t-call-schedule-in-loop.patch @@ -0,0 +1,128 @@ +From 57c7200ed48395cfd92e3c688fa4c6c7a3a8a638 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Dec 2024 16:00:16 +0100 +Subject: media: test-drivers: vivid: don't call schedule in loop + +From: Hans Verkuil + +[ Upstream commit e4740118b752005cbed339aec9a1d1c43620e0b9 ] + +Artem reported that the CPU load was 100% when capturing from +vivid at low resolution with ffmpeg. + +This was caused by: + +while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && + !kthread_should_stop()) + schedule(); + +If there are no other processes running that can be scheduled, +then this is basically a busy-loop. + +Change it to wait_event_interruptible_timeout() which doesn't +have that problem. + +Signed-off-by: Hans Verkuil +Reported-by: Artem S. Tashkinov +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219570 +Reviewed-by: Nicolas Dufresne +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/test-drivers/vivid/vivid-kthread-cap.c | 11 ++++++++--- + drivers/media/test-drivers/vivid/vivid-kthread-out.c | 11 ++++++++--- + .../media/test-drivers/vivid/vivid-kthread-touch.c | 11 ++++++++--- + drivers/media/test-drivers/vivid/vivid-sdr-cap.c | 11 ++++++++--- + 4 files changed, 32 insertions(+), 12 deletions(-) + +diff --git a/drivers/media/test-drivers/vivid/vivid-kthread-cap.c b/drivers/media/test-drivers/vivid/vivid-kthread-cap.c +index 669bd96da4c79..273e8ed8c2a90 100644 +--- a/drivers/media/test-drivers/vivid/vivid-kthread-cap.c ++++ b/drivers/media/test-drivers/vivid/vivid-kthread-cap.c +@@ -789,9 +789,14 @@ static int vivid_thread_vid_cap(void *data) + next_jiffies_since_start = jiffies_since_start; + + wait_jiffies = next_jiffies_since_start - jiffies_since_start; +- while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && +- !kthread_should_stop()) +- schedule(); ++ if (!time_is_after_jiffies(cur_jiffies + wait_jiffies)) ++ continue; ++ ++ wait_queue_head_t wait; ++ ++ init_waitqueue_head(&wait); ++ wait_event_interruptible_timeout(wait, kthread_should_stop(), ++ cur_jiffies + wait_jiffies - jiffies); + } + dprintk(dev, 1, "Video Capture Thread End\n"); + return 0; +diff --git a/drivers/media/test-drivers/vivid/vivid-kthread-out.c b/drivers/media/test-drivers/vivid/vivid-kthread-out.c +index fac6208b51da8..015a7b166a1e6 100644 +--- a/drivers/media/test-drivers/vivid/vivid-kthread-out.c ++++ b/drivers/media/test-drivers/vivid/vivid-kthread-out.c +@@ -235,9 +235,14 @@ static int vivid_thread_vid_out(void *data) + next_jiffies_since_start = jiffies_since_start; + + wait_jiffies = next_jiffies_since_start - jiffies_since_start; +- while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && +- !kthread_should_stop()) +- schedule(); ++ if (!time_is_after_jiffies(cur_jiffies + wait_jiffies)) ++ continue; ++ ++ wait_queue_head_t wait; ++ ++ init_waitqueue_head(&wait); ++ wait_event_interruptible_timeout(wait, kthread_should_stop(), ++ cur_jiffies + wait_jiffies - jiffies); + } + dprintk(dev, 1, "Video Output Thread End\n"); + return 0; +diff --git a/drivers/media/test-drivers/vivid/vivid-kthread-touch.c b/drivers/media/test-drivers/vivid/vivid-kthread-touch.c +index fa711ee36a3fb..c862689786b69 100644 +--- a/drivers/media/test-drivers/vivid/vivid-kthread-touch.c ++++ b/drivers/media/test-drivers/vivid/vivid-kthread-touch.c +@@ -135,9 +135,14 @@ static int vivid_thread_touch_cap(void *data) + next_jiffies_since_start = jiffies_since_start; + + wait_jiffies = next_jiffies_since_start - jiffies_since_start; +- while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && +- !kthread_should_stop()) +- schedule(); ++ if (!time_is_after_jiffies(cur_jiffies + wait_jiffies)) ++ continue; ++ ++ wait_queue_head_t wait; ++ ++ init_waitqueue_head(&wait); ++ wait_event_interruptible_timeout(wait, kthread_should_stop(), ++ cur_jiffies + wait_jiffies - jiffies); + } + dprintk(dev, 1, "Touch Capture Thread End\n"); + return 0; +diff --git a/drivers/media/test-drivers/vivid/vivid-sdr-cap.c b/drivers/media/test-drivers/vivid/vivid-sdr-cap.c +index 38cda33dffb2a..97cfc58b70571 100644 +--- a/drivers/media/test-drivers/vivid/vivid-sdr-cap.c ++++ b/drivers/media/test-drivers/vivid/vivid-sdr-cap.c +@@ -206,9 +206,14 @@ static int vivid_thread_sdr_cap(void *data) + next_jiffies_since_start = jiffies_since_start; + + wait_jiffies = next_jiffies_since_start - jiffies_since_start; +- while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && +- !kthread_should_stop()) +- schedule(); ++ if (!time_is_after_jiffies(cur_jiffies + wait_jiffies)) ++ continue; ++ ++ wait_queue_head_t wait; ++ ++ init_waitqueue_head(&wait); ++ wait_event_interruptible_timeout(wait, kthread_should_stop(), ++ cur_jiffies + wait_jiffies - jiffies); + } + dprintk(dev, 1, "SDR Capture Thread End\n"); + return 0; +-- +2.39.5 + diff --git a/queue-6.12/media-uvcvideo-add-sanity-check-to-uvc_ioctl_xu_ctrl.patch b/queue-6.12/media-uvcvideo-add-sanity-check-to-uvc_ioctl_xu_ctrl.patch new file mode 100644 index 0000000000..5230360378 --- /dev/null +++ b/queue-6.12/media-uvcvideo-add-sanity-check-to-uvc_ioctl_xu_ctrl.patch @@ -0,0 +1,42 @@ +From 985a81d3a04e7d324421ea5ebb7b25cff8dc1685 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 11:55:51 +0000 +Subject: media: uvcvideo: Add sanity check to uvc_ioctl_xu_ctrl_map + +From: Ricardo Ribalda + +[ Upstream commit 990262fdfce24d6055df9711424343d94d829e6a ] + +Do not process unknown data types. + +Tested-by: Yunke Cao +Reviewed-by: Hans de Goede +Signed-off-by: Ricardo Ribalda +Link: https://lore.kernel.org/r/20250203-uvc-roi-v17-15-5900a9fed613@chromium.org +Signed-off-by: Hans de Goede +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/usb/uvc/uvc_v4l2.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c +index 7bcd706281daf..cb7d9fb589fca 100644 +--- a/drivers/media/usb/uvc/uvc_v4l2.c ++++ b/drivers/media/usb/uvc/uvc_v4l2.c +@@ -106,6 +106,12 @@ static int uvc_ioctl_xu_ctrl_map(struct uvc_video_chain *chain, + struct uvc_control_mapping *map; + int ret; + ++ if (xmap->data_type > UVC_CTRL_DATA_TYPE_BITMASK) { ++ uvc_dbg(chain->dev, CONTROL, ++ "Unsupported UVC data type %u\n", xmap->data_type); ++ return -EINVAL; ++ } ++ + map = kzalloc(sizeof(*map), GFP_KERNEL); + if (map == NULL) + return -ENOMEM; +-- +2.39.5 + diff --git a/queue-6.12/media-uvcvideo-handle-uvc-menu-translation-inside-uv.patch b/queue-6.12/media-uvcvideo-handle-uvc-menu-translation-inside-uv.patch new file mode 100644 index 0000000000..1c787dd9d8 --- /dev/null +++ b/queue-6.12/media-uvcvideo-handle-uvc-menu-translation-inside-uv.patch @@ -0,0 +1,161 @@ +From ba2a6e3f7382143a3c8b2839438f74a4046478eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 11:55:40 +0000 +Subject: media: uvcvideo: Handle uvc menu translation inside uvc_get_le_value + +From: Ricardo Ribalda + +[ Upstream commit 9109a0b4cb10fd681e9c6e9a4497a6fec5b91c39 ] + +map->get() gets a value from an uvc_control in "UVC format" and converts +it to a value that can be consumed by v4l2. + +Instead of using a special get function for V4L2_CTRL_TYPE_MENU, we +were converting from uvc_get_le_value in two different places. + +Move the conversion to uvc_get_le_value(). + +Reviewed-by: Hans de Goede +Tested-by: Yunke Cao +Signed-off-by: Ricardo Ribalda +Link: https://lore.kernel.org/r/20250203-uvc-roi-v17-4-5900a9fed613@chromium.org +Signed-off-by: Hans de Goede +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/usb/uvc/uvc_ctrl.c | 77 +++++++++++++------------------- + 1 file changed, 32 insertions(+), 45 deletions(-) + +diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c +index 4837d8df9c038..58d1bc80253e8 100644 +--- a/drivers/media/usb/uvc/uvc_ctrl.c ++++ b/drivers/media/usb/uvc/uvc_ctrl.c +@@ -862,6 +862,25 @@ static inline void uvc_clear_bit(u8 *data, int bit) + data[bit >> 3] &= ~(1 << (bit & 7)); + } + ++static s32 uvc_menu_to_v4l2_menu(struct uvc_control_mapping *mapping, s32 val) ++{ ++ unsigned int i; ++ ++ for (i = 0; BIT(i) <= mapping->menu_mask; ++i) { ++ u32 menu_value; ++ ++ if (!test_bit(i, &mapping->menu_mask)) ++ continue; ++ ++ menu_value = uvc_mapping_get_menu_value(mapping, i); ++ ++ if (menu_value == val) ++ return i; ++ } ++ ++ return val; ++} ++ + /* + * Extract the bit string specified by mapping->offset and mapping->size + * from the little-endian data stored at 'data' and return the result as +@@ -896,6 +915,16 @@ static s32 uvc_get_le_value(struct uvc_control_mapping *mapping, + if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) + value |= -(value & (1 << (mapping->size - 1))); + ++ /* If it is a menu, convert from uvc to v4l2. */ ++ if (mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) ++ return value; ++ ++ switch (query) { ++ case UVC_GET_CUR: ++ case UVC_GET_DEF: ++ return uvc_menu_to_v4l2_menu(mapping, value); ++ } ++ + return value; + } + +@@ -1060,32 +1089,6 @@ static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain, + return 0; + } + +-static s32 __uvc_ctrl_get_value(struct uvc_control_mapping *mapping, +- const u8 *data) +-{ +- s32 value = mapping->get(mapping, UVC_GET_CUR, data); +- +- if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { +- unsigned int i; +- +- for (i = 0; BIT(i) <= mapping->menu_mask; ++i) { +- u32 menu_value; +- +- if (!test_bit(i, &mapping->menu_mask)) +- continue; +- +- menu_value = uvc_mapping_get_menu_value(mapping, i); +- +- if (menu_value == value) { +- value = i; +- break; +- } +- } +- } +- +- return value; +-} +- + static int __uvc_ctrl_load_cur(struct uvc_video_chain *chain, + struct uvc_control *ctrl) + { +@@ -1136,8 +1139,8 @@ static int __uvc_ctrl_get(struct uvc_video_chain *chain, + if (ret < 0) + return ret; + +- *value = __uvc_ctrl_get_value(mapping, +- uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); ++ *value = mapping->get(mapping, UVC_GET_CUR, ++ uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); + + return 0; + } +@@ -1287,7 +1290,6 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, + { + struct uvc_control_mapping *master_map = NULL; + struct uvc_control *master_ctrl = NULL; +- unsigned int i; + + memset(v4l2_ctrl, 0, sizeof(*v4l2_ctrl)); + v4l2_ctrl->id = mapping->id; +@@ -1330,21 +1332,6 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, + v4l2_ctrl->minimum = ffs(mapping->menu_mask) - 1; + v4l2_ctrl->maximum = fls(mapping->menu_mask) - 1; + v4l2_ctrl->step = 1; +- +- for (i = 0; BIT(i) <= mapping->menu_mask; ++i) { +- u32 menu_value; +- +- if (!test_bit(i, &mapping->menu_mask)) +- continue; +- +- menu_value = uvc_mapping_get_menu_value(mapping, i); +- +- if (menu_value == v4l2_ctrl->default_value) { +- v4l2_ctrl->default_value = i; +- break; +- } +- } +- + return 0; + + case V4L2_CTRL_TYPE_BOOLEAN: +@@ -1627,7 +1614,7 @@ void uvc_ctrl_status_event(struct uvc_video_chain *chain, + uvc_ctrl_set_handle(handle, ctrl, NULL); + + list_for_each_entry(mapping, &ctrl->info.mappings, list) { +- s32 value = __uvc_ctrl_get_value(mapping, data); ++ s32 value = mapping->get(mapping, UVC_GET_CUR, data); + + /* + * handle may be NULL here if the device sends auto-update +-- +2.39.5 + diff --git a/queue-6.12/media-v4l-memset-argument-to-0-before-calling-get_mb.patch b/queue-6.12/media-v4l-memset-argument-to-0-before-calling-get_mb.patch new file mode 100644 index 0000000000..b5b164b3bc --- /dev/null +++ b/queue-6.12/media-v4l-memset-argument-to-0-before-calling-get_mb.patch @@ -0,0 +1,55 @@ +From ad7def4200d9e66885c8bcbb4ff83bdbbd6dc6d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Dec 2024 10:48:49 +0200 +Subject: media: v4l: Memset argument to 0 before calling get_mbus_config pad + op + +From: Sakari Ailus + +[ Upstream commit 91d6a99acfa5ce9f95ede775074b80f7193bd717 ] + +Memset the config argument to get_mbus_config V4L2 sub-device pad +operation to zero before calling the operation. This ensures the callers +don't need to bother with it nor the implementations need to set all +fields that may not be relevant to them. + +Signed-off-by: Sakari Ailus +Reviewed-by: Tomi Valkeinen +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/v4l2-core/v4l2-subdev.c | 2 ++ + include/media/v4l2-subdev.h | 4 +++- + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c +index 3a4ba08810d24..1193852bad599 100644 +--- a/drivers/media/v4l2-core/v4l2-subdev.c ++++ b/drivers/media/v4l2-core/v4l2-subdev.c +@@ -439,6 +439,8 @@ static int call_enum_dv_timings(struct v4l2_subdev *sd, + static int call_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad, + struct v4l2_mbus_config *config) + { ++ memset(config, 0, sizeof(*config)); ++ + return check_pad(sd, pad) ? : + sd->ops->pad->get_mbus_config(sd, pad, config); + } +diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h +index 8daa0929865cf..43343f1586d13 100644 +--- a/include/media/v4l2-subdev.h ++++ b/include/media/v4l2-subdev.h +@@ -821,7 +821,9 @@ struct v4l2_subdev_state { + * possible configuration from the remote end, likely calling + * this operation as close as possible to stream on time. The + * operation shall fail if the pad index it has been called on +- * is not valid or in case of unrecoverable failures. ++ * is not valid or in case of unrecoverable failures. The ++ * config argument has been memset to 0 just before calling ++ * the op. + * + * @set_routing: Enable or disable data connection routes described in the + * subdevice routing table. Subdevs that implement this operation +-- +2.39.5 + diff --git a/queue-6.12/mei-vsc-use-struct-vsc_tp_packet-as-vsc-tp-tx_buf-an.patch b/queue-6.12/mei-vsc-use-struct-vsc_tp_packet-as-vsc-tp-tx_buf-an.patch new file mode 100644 index 0000000000..60013e59d4 --- /dev/null +++ b/queue-6.12/mei-vsc-use-struct-vsc_tp_packet-as-vsc-tp-tx_buf-an.patch @@ -0,0 +1,82 @@ +From 7344e327ada73f2c74c910e3688b95cbeee3c348 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 15:12:03 +0100 +Subject: mei: vsc: Use struct vsc_tp_packet as vsc-tp tx_buf and rx_buf type + +From: Hans de Goede + +[ Upstream commit f88c0c72ffb014e5eba676ee337c4eb3b1d6a119 ] + +vsc_tp.tx_buf and vsc_tp.rx_buf point to a struct vsc_tp_packet, use +the correct type instead of "void *" and use sizeof(*ptr) when allocating +memory for these buffers. + +Signed-off-by: Hans de Goede +Reviewed-by: Alexander Usyskin +Reviewed-by: Sakari Ailus +Link: https://lore.kernel.org/r/20250318141203.94342-3-hdegoede@redhat.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/misc/mei/vsc-tp.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/misc/mei/vsc-tp.c b/drivers/misc/mei/vsc-tp.c +index eb51fbe8d92fb..ad7c7f1573191 100644 +--- a/drivers/misc/mei/vsc-tp.c ++++ b/drivers/misc/mei/vsc-tp.c +@@ -71,8 +71,8 @@ struct vsc_tp { + u32 seq; + + /* command buffer */ +- void *tx_buf; +- void *rx_buf; ++ struct vsc_tp_packet *tx_buf; ++ struct vsc_tp_packet *rx_buf; + + atomic_t assert_cnt; + wait_queue_head_t xfer_wait; +@@ -164,7 +164,7 @@ static int vsc_tp_xfer_helper(struct vsc_tp *tp, struct vsc_tp_packet *pkt, + { + int ret, offset = 0, cpy_len, src_len, dst_len = sizeof(struct vsc_tp_packet_hdr); + int next_xfer_len = VSC_TP_PACKET_SIZE(pkt) + VSC_TP_XFER_TIMEOUT_BYTES; +- u8 *src, *crc_src, *rx_buf = tp->rx_buf; ++ u8 *src, *crc_src, *rx_buf = (u8 *)tp->rx_buf; + int count_down = VSC_TP_MAX_XFER_COUNT; + u32 recv_crc = 0, crc = ~0; + struct vsc_tp_packet_hdr ack; +@@ -324,7 +324,7 @@ int vsc_tp_rom_xfer(struct vsc_tp *tp, const void *obuf, void *ibuf, size_t len) + guard(mutex)(&tp->mutex); + + /* rom xfer is big endian */ +- cpu_to_be32_array(tp->tx_buf, obuf, words); ++ cpu_to_be32_array((u32 *)tp->tx_buf, obuf, words); + + ret = read_poll_timeout(gpiod_get_value_cansleep, ret, + !ret, VSC_TP_ROM_XFER_POLL_DELAY_US, +@@ -340,7 +340,7 @@ int vsc_tp_rom_xfer(struct vsc_tp *tp, const void *obuf, void *ibuf, size_t len) + return ret; + + if (ibuf) +- be32_to_cpu_array(ibuf, tp->rx_buf, words); ++ be32_to_cpu_array(ibuf, (u32 *)tp->rx_buf, words); + + return ret; + } +@@ -496,11 +496,11 @@ static int vsc_tp_probe(struct spi_device *spi) + if (!tp) + return -ENOMEM; + +- tp->tx_buf = devm_kzalloc(dev, VSC_TP_MAX_XFER_SIZE, GFP_KERNEL); ++ tp->tx_buf = devm_kzalloc(dev, sizeof(*tp->tx_buf), GFP_KERNEL); + if (!tp->tx_buf) + return -ENOMEM; + +- tp->rx_buf = devm_kzalloc(dev, VSC_TP_MAX_XFER_SIZE, GFP_KERNEL); ++ tp->rx_buf = devm_kzalloc(dev, sizeof(*tp->rx_buf), GFP_KERNEL); + if (!tp->rx_buf) + return -ENOMEM; + +-- +2.39.5 + diff --git a/queue-6.12/mfd-axp20x-axp717-add-axp717_ts_pin_cfg-to-writeable.patch b/queue-6.12/mfd-axp20x-axp717-add-axp717_ts_pin_cfg-to-writeable.patch new file mode 100644 index 0000000000..78be73295d --- /dev/null +++ b/queue-6.12/mfd-axp20x-axp717-add-axp717_ts_pin_cfg-to-writeable.patch @@ -0,0 +1,49 @@ +From eb326e717c2073c7dd5fc984e9dc6679eb024743 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 09:58:32 -0600 +Subject: mfd: axp20x: AXP717: Add AXP717_TS_PIN_CFG to writeable regs + +From: Chris Morgan + +[ Upstream commit bfad07fe298bfba0c7ddab87c5b5325970203a1e ] + +Add AXP717_TS_PIN_CFG (register 0x50) to the table of writeable +registers so that the temperature sensor can be configured by the +battery driver. + +Signed-off-by: Chris Morgan +Link: https://lore.kernel.org/r/20250204155835.161973-3-macroalpha82@gmail.com +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/mfd/axp20x.c | 1 + + include/linux/mfd/axp20x.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c +index 4051551757f2d..3780929039710 100644 +--- a/drivers/mfd/axp20x.c ++++ b/drivers/mfd/axp20x.c +@@ -214,6 +214,7 @@ static const struct regmap_range axp717_writeable_ranges[] = { + regmap_reg_range(AXP717_VSYS_V_POWEROFF, AXP717_VSYS_V_POWEROFF), + regmap_reg_range(AXP717_IRQ0_EN, AXP717_IRQ4_EN), + regmap_reg_range(AXP717_IRQ0_STATE, AXP717_IRQ4_STATE), ++ regmap_reg_range(AXP717_TS_PIN_CFG, AXP717_TS_PIN_CFG), + regmap_reg_range(AXP717_ICC_CHG_SET, AXP717_CV_CHG_SET), + regmap_reg_range(AXP717_DCDC_OUTPUT_CONTROL, AXP717_CPUSLDO_CONTROL), + regmap_reg_range(AXP717_ADC_CH_EN_CONTROL, AXP717_ADC_CH_EN_CONTROL), +diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h +index f4dfc1871a95b..d1c21ad6440d1 100644 +--- a/include/linux/mfd/axp20x.h ++++ b/include/linux/mfd/axp20x.h +@@ -135,6 +135,7 @@ enum axp20x_variants { + #define AXP717_IRQ2_STATE 0x4a + #define AXP717_IRQ3_STATE 0x4b + #define AXP717_IRQ4_STATE 0x4c ++#define AXP717_TS_PIN_CFG 0x50 + #define AXP717_ICC_CHG_SET 0x62 + #define AXP717_ITERM_CHG_SET 0x63 + #define AXP717_CV_CHG_SET 0x64 +-- +2.39.5 + diff --git a/queue-6.12/mfd-tps65219-remove-tps65219_reg_ti_dev_id-check.patch b/queue-6.12/mfd-tps65219-remove-tps65219_reg_ti_dev_id-check.patch new file mode 100644 index 0000000000..7c73a4a7e1 --- /dev/null +++ b/queue-6.12/mfd-tps65219-remove-tps65219_reg_ti_dev_id-check.patch @@ -0,0 +1,58 @@ +From 063cc2f1f9e40e18b041d8c527b23ef24540a1ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 11:37:23 -0600 +Subject: mfd: tps65219: Remove TPS65219_REG_TI_DEV_ID check + +From: Shree Ramamoorthy + +[ Upstream commit 76b58d5111fdcffce615beb71520bc7a6f1742c9 ] + +The chipid macro/variable and regmap_read function call is not needed +because the TPS65219_REG_TI_DEV_ID register value is not a consistent value +across TPS65219 PMIC config versions. Reading from the DEV_ID register +without a consistent value to compare it to isn't useful. There isn't a +way to verify the match data ID is the same ID read from the DEV_ID device +register. 0xF0 isn't a DEV_ID value consistent across TPS65219 NVM +configurations. + +For TPS65215, there is a consistent value in bits 5-0 of the DEV_ID +register. However, there are other error checks in place within probe() +that apply to both PMICs rather than keeping this isolated check for one +PMIC. + +Signed-off-by: Shree Ramamoorthy +Link: https://lore.kernel.org/r/20250206173725.386720-4-s-ramamoorthy@ti.com +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/mfd/tps65219.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/drivers/mfd/tps65219.c b/drivers/mfd/tps65219.c +index 57ff5cb294a66..d3b77abec786e 100644 +--- a/drivers/mfd/tps65219.c ++++ b/drivers/mfd/tps65219.c +@@ -228,7 +228,6 @@ static const struct regmap_irq_chip tps65219_irq_chip = { + static int tps65219_probe(struct i2c_client *client) + { + struct tps65219 *tps; +- unsigned int chipid; + bool pwr_button; + int ret; + +@@ -253,12 +252,6 @@ static int tps65219_probe(struct i2c_client *client) + if (ret) + return ret; + +- ret = regmap_read(tps->regmap, TPS65219_REG_TI_DEV_ID, &chipid); +- if (ret) { +- dev_err(tps->dev, "Failed to read device ID: %d\n", ret); +- return ret; +- } +- + ret = devm_mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO, + tps65219_cells, ARRAY_SIZE(tps65219_cells), + NULL, 0, regmap_irq_get_domain(tps->irq_data)); +-- +2.39.5 + diff --git a/queue-6.12/mips-pm-cps-use-per-cpu-variables-as-per-cpu-not-per.patch b/queue-6.12/mips-pm-cps-use-per-cpu-variables-as-per-cpu-not-per.patch new file mode 100644 index 0000000000..bdee974524 --- /dev/null +++ b/queue-6.12/mips-pm-cps-use-per-cpu-variables-as-per-cpu-not-per.patch @@ -0,0 +1,128 @@ +From ffa0cd408bd7ce1b2902fd51fe50b692e5e76ac2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 13:32:48 +0100 +Subject: MIPS: pm-cps: Use per-CPU variables as per-CPU, not per-core + +From: Paul Burton + +[ Upstream commit 00a134fc2bb4a5f8fada58cf7ff4259149691d64 ] + +The pm-cps code has up until now used per-CPU variables indexed by core, +rather than CPU number, in order to share data amongst sibling CPUs (ie. +VPs/threads in a core). This works fine for single cluster systems, but +with multi-cluster systems a core number is no longer unique in the +system, leading to sharing between CPUs that are not actually siblings. + +Avoid this issue by using per-CPU variables as they are more generally +used - ie. access them using CPU numbers rather than core numbers. +Sharing between siblings is then accomplished by: + - Assigning the same pointer to entries for each sibling CPU for the + nc_asm_enter & ready_count variables, which allow this by virtue of + being per-CPU pointers. + + - Indexing by the first CPU set in a CPUs cpu_sibling_map in the case + of pm_barrier, for which we can't use the previous approach because + the per-CPU variable is not a pointer. + +Signed-off-by: Paul Burton +Signed-off-by: Dragan Mladjenovic +Signed-off-by: Aleksandar Rikalo +Tested-by: Serge Semin +Tested-by: Gregory CLEMENT +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + arch/mips/kernel/pm-cps.c | 30 +++++++++++++++++------------- + 1 file changed, 17 insertions(+), 13 deletions(-) + +diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c +index d09ca77e624d7..9369a8dc385e2 100644 +--- a/arch/mips/kernel/pm-cps.c ++++ b/arch/mips/kernel/pm-cps.c +@@ -57,10 +57,7 @@ static DEFINE_PER_CPU_ALIGNED(u32*, ready_count); + /* Indicates online CPUs coupled with the current CPU */ + static DEFINE_PER_CPU_ALIGNED(cpumask_t, online_coupled); + +-/* +- * Used to synchronize entry to deep idle states. Actually per-core rather +- * than per-CPU. +- */ ++/* Used to synchronize entry to deep idle states */ + static DEFINE_PER_CPU_ALIGNED(atomic_t, pm_barrier); + + /* Saved CPU state across the CPS_PM_POWER_GATED state */ +@@ -112,9 +109,10 @@ int cps_pm_enter_state(enum cps_pm_state state) + cps_nc_entry_fn entry; + struct core_boot_config *core_cfg; + struct vpe_boot_config *vpe_cfg; ++ atomic_t *barrier; + + /* Check that there is an entry function for this state */ +- entry = per_cpu(nc_asm_enter, core)[state]; ++ entry = per_cpu(nc_asm_enter, cpu)[state]; + if (!entry) + return -EINVAL; + +@@ -150,7 +148,7 @@ int cps_pm_enter_state(enum cps_pm_state state) + smp_mb__after_atomic(); + + /* Create a non-coherent mapping of the core ready_count */ +- core_ready_count = per_cpu(ready_count, core); ++ core_ready_count = per_cpu(ready_count, cpu); + nc_addr = kmap_noncoherent(virt_to_page(core_ready_count), + (unsigned long)core_ready_count); + nc_addr += ((unsigned long)core_ready_count & ~PAGE_MASK); +@@ -158,7 +156,8 @@ int cps_pm_enter_state(enum cps_pm_state state) + + /* Ensure ready_count is zero-initialised before the assembly runs */ + WRITE_ONCE(*nc_core_ready_count, 0); +- coupled_barrier(&per_cpu(pm_barrier, core), online); ++ barrier = &per_cpu(pm_barrier, cpumask_first(&cpu_sibling_map[cpu])); ++ coupled_barrier(barrier, online); + + /* Run the generated entry code */ + left = entry(online, nc_core_ready_count); +@@ -629,12 +628,14 @@ static void *cps_gen_entry_code(unsigned cpu, enum cps_pm_state state) + + static int cps_pm_online_cpu(unsigned int cpu) + { +- enum cps_pm_state state; +- unsigned core = cpu_core(&cpu_data[cpu]); ++ unsigned int sibling, core; + void *entry_fn, *core_rc; ++ enum cps_pm_state state; ++ ++ core = cpu_core(&cpu_data[cpu]); + + for (state = CPS_PM_NC_WAIT; state < CPS_PM_STATE_COUNT; state++) { +- if (per_cpu(nc_asm_enter, core)[state]) ++ if (per_cpu(nc_asm_enter, cpu)[state]) + continue; + if (!test_bit(state, state_support)) + continue; +@@ -646,16 +647,19 @@ static int cps_pm_online_cpu(unsigned int cpu) + clear_bit(state, state_support); + } + +- per_cpu(nc_asm_enter, core)[state] = entry_fn; ++ for_each_cpu(sibling, &cpu_sibling_map[cpu]) ++ per_cpu(nc_asm_enter, sibling)[state] = entry_fn; + } + +- if (!per_cpu(ready_count, core)) { ++ if (!per_cpu(ready_count, cpu)) { + core_rc = kmalloc(sizeof(u32), GFP_KERNEL); + if (!core_rc) { + pr_err("Failed allocate core %u ready_count\n", core); + return -ENOMEM; + } +- per_cpu(ready_count, core) = core_rc; ++ ++ for_each_cpu(sibling, &cpu_sibling_map[cpu]) ++ per_cpu(ready_count, sibling) = core_rc; + } + + return 0; +-- +2.39.5 + diff --git a/queue-6.12/mips-use-arch-specific-syscall-name-match-function.patch b/queue-6.12/mips-use-arch-specific-syscall-name-match-function.patch new file mode 100644 index 0000000000..837ec8e32d --- /dev/null +++ b/queue-6.12/mips-use-arch-specific-syscall-name-match-function.patch @@ -0,0 +1,55 @@ +From 5fa8e0fd560852226d63f065e876509f485161ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Jun 2020 10:54:35 +0800 +Subject: MIPS: Use arch specific syscall name match function + +From: Bibo Mao + +[ Upstream commit 756276ce78d5624dc814f9d99f7d16c8fd51076e ] + +On MIPS system, most of the syscall function name begin with prefix +sys_. Some syscalls are special such as clone/fork, function name of +these begin with __sys_. Since scratch registers need be saved in +stack when these system calls happens. + +With ftrace system call method, system call functions are declared with +SYSCALL_DEFINEx, metadata of the system call symbol name begins with +sys_. Here mips specific function arch_syscall_match_sym_name is used to +compare function name between sys_call_table[] and metadata of syscall +symbol. + +Signed-off-by: Bibo Mao +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + arch/mips/include/asm/ftrace.h | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h +index dc025888f6d28..b41fc10446688 100644 +--- a/arch/mips/include/asm/ftrace.h ++++ b/arch/mips/include/asm/ftrace.h +@@ -91,4 +91,20 @@ void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra, + + #endif /* __ASSEMBLY__ */ + #endif /* CONFIG_FUNCTION_TRACER */ ++ ++#ifdef CONFIG_FTRACE_SYSCALLS ++#ifndef __ASSEMBLY__ ++/* ++ * Some syscall entry functions on mips start with "__sys_" (fork and clone, ++ * for instance). We should also match the sys_ variant with those. ++ */ ++#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME ++static inline bool arch_syscall_match_sym_name(const char *sym, ++ const char *name) ++{ ++ return !strcmp(sym, name) || ++ (!strncmp(sym, "__sys_", 6) && !strcmp(sym + 6, name + 4)); ++} ++#endif /* __ASSEMBLY__ */ ++#endif /* CONFIG_FTRACE_SYSCALLS */ + #endif /* _ASM_MIPS_FTRACE_H */ +-- +2.39.5 + diff --git a/queue-6.12/misc-pci_endpoint_test-give-disabled-bars-a-distinct.patch b/queue-6.12/misc-pci_endpoint_test-give-disabled-bars-a-distinct.patch new file mode 100644 index 0000000000..72f30667c9 --- /dev/null +++ b/queue-6.12/misc-pci_endpoint_test-give-disabled-bars-a-distinct.patch @@ -0,0 +1,66 @@ +From da9a781a08da1733c44b7de6c9f0a88461d62e48 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 13:01:48 +0100 +Subject: misc: pci_endpoint_test: Give disabled BARs a distinct error code +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Niklas Cassel + +[ Upstream commit 7e80bbef1d697dbce7a39cfad0df770880fe3f29 ] + +The current code returns -ENOMEM if test->bar[barno] is NULL. + +There can be two reasons why test->bar[barno] is NULL: + + 1) The pci_ioremap_bar() call in pci_endpoint_test_probe() failed. + 2) The BAR was skipped, because it is disabled by the endpoint. + +Many PCI endpoint controller drivers will disable all BARs in their +init function. A disabled BAR will have a size of 0. + +A PCI endpoint function driver will be able to enable any BAR that +is not marked as BAR_RESERVED (which means that the BAR should not +be touched by the EPF driver). + +Thus, perform check if the size is 0, before checking if +test->bar[barno] is NULL, such that we can return different errors. + +This will allow the selftests to return SKIP instead of FAIL for +disabled BARs. + +Signed-off-by: Niklas Cassel +Reviewed-by: Manivannan Sadhasivam +Link: https://lore.kernel.org/r/20250123120147.3603409-3-cassel@kernel.org +Signed-off-by: Manivannan Sadhasivam +[kwilczynski: commit log] +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/misc/pci_endpoint_test.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c +index e22afb420d099..f05256b7c2084 100644 +--- a/drivers/misc/pci_endpoint_test.c ++++ b/drivers/misc/pci_endpoint_test.c +@@ -287,11 +287,13 @@ static bool pci_endpoint_test_bar(struct pci_endpoint_test *test, + void *read_buf __free(kfree) = NULL; + struct pci_dev *pdev = test->pdev; + ++ bar_size = pci_resource_len(pdev, barno); ++ if (!bar_size) ++ return -ENODATA; ++ + if (!test->bar[barno]) + return false; + +- bar_size = pci_resource_len(pdev, barno); +- + if (barno == test->test_reg_bar) + bar_size = 0x4; + +-- +2.39.5 + diff --git a/queue-6.12/mmc-dw_mmc-add-exynos7870-dw-mmc-support.patch b/queue-6.12/mmc-dw_mmc-add-exynos7870-dw-mmc-support.patch new file mode 100644 index 0000000000..a0e0c89d07 --- /dev/null +++ b/queue-6.12/mmc-dw_mmc-add-exynos7870-dw-mmc-support.patch @@ -0,0 +1,174 @@ +From 4ba191f7bd2ced6905583a047f57c2e38f05f2f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 00:17:49 +0530 +Subject: mmc: dw_mmc: add exynos7870 DW MMC support + +From: Kaustabh Chakraborty + +[ Upstream commit 7cbe799ac10fd8be85af5e0615c4337f81e575f3 ] + +Add support for Exynos7870 DW MMC controllers, for both SMU and non-SMU +variants. These controllers require a quirk to access 64-bit FIFO in 32-bit +accesses (DW_MMC_QUIRK_FIFO64_32). + +Signed-off-by: Kaustabh Chakraborty +Link: https://lore.kernel.org/r/20250219-exynos7870-mmc-v2-3-b4255a3e39ed@disroot.org +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/dw_mmc-exynos.c | 41 +++++++++++++++++++++++++++++++- + 1 file changed, 40 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c +index 6dc057718d2cb..89682f10e69f3 100644 +--- a/drivers/mmc/host/dw_mmc-exynos.c ++++ b/drivers/mmc/host/dw_mmc-exynos.c +@@ -27,6 +27,8 @@ enum dw_mci_exynos_type { + DW_MCI_TYPE_EXYNOS5420_SMU, + DW_MCI_TYPE_EXYNOS7, + DW_MCI_TYPE_EXYNOS7_SMU, ++ DW_MCI_TYPE_EXYNOS7870, ++ DW_MCI_TYPE_EXYNOS7870_SMU, + DW_MCI_TYPE_ARTPEC8, + }; + +@@ -69,6 +71,12 @@ static struct dw_mci_exynos_compatible { + }, { + .compatible = "samsung,exynos7-dw-mshc-smu", + .ctrl_type = DW_MCI_TYPE_EXYNOS7_SMU, ++ }, { ++ .compatible = "samsung,exynos7870-dw-mshc", ++ .ctrl_type = DW_MCI_TYPE_EXYNOS7870, ++ }, { ++ .compatible = "samsung,exynos7870-dw-mshc-smu", ++ .ctrl_type = DW_MCI_TYPE_EXYNOS7870_SMU, + }, { + .compatible = "axis,artpec8-dw-mshc", + .ctrl_type = DW_MCI_TYPE_ARTPEC8, +@@ -85,6 +93,8 @@ static inline u8 dw_mci_exynos_get_ciu_div(struct dw_mci *host) + return EXYNOS4210_FIXED_CIU_CLK_DIV; + else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL64)) + 1; + else +@@ -100,7 +110,8 @@ static void dw_mci_exynos_config_smu(struct dw_mci *host) + * set for non-ecryption mode at this time. + */ + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420_SMU || +- priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU) { ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU) { + mci_writel(host, MPSBEGIN0, 0); + mci_writel(host, MPSEND0, SDMMC_ENDING_SEC_NR_MAX); + mci_writel(host, MPSCTRL0, SDMMC_MPSCTRL_SECURE_WRITE_BIT | +@@ -126,6 +137,12 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) + DQS_CTRL_GET_RD_DELAY(priv->saved_strobe_ctrl); + } + ++ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU) { ++ /* Quirk needed for certain Exynos SoCs */ ++ host->quirks |= DW_MMC_QUIRK_FIFO64_32; ++ } ++ + if (priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) { + /* Quirk needed for the ARTPEC-8 SoC */ + host->quirks |= DW_MMC_QUIRK_EXTENDED_TMOUT; +@@ -143,6 +160,8 @@ static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing) + + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + clksel = mci_readl(host, CLKSEL64); + else +@@ -152,6 +171,8 @@ static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing) + + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + mci_writel(host, CLKSEL64, clksel); + else +@@ -222,6 +243,8 @@ static int dw_mci_exynos_resume_noirq(struct device *dev) + + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + clksel = mci_readl(host, CLKSEL64); + else +@@ -230,6 +253,8 @@ static int dw_mci_exynos_resume_noirq(struct device *dev) + if (clksel & SDMMC_CLKSEL_WAKEUP_INT) { + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + mci_writel(host, CLKSEL64, clksel); + else +@@ -409,6 +434,8 @@ static inline u8 dw_mci_exynos_get_clksmpl(struct dw_mci *host) + + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + return SDMMC_CLKSEL_CCLK_SAMPLE(mci_readl(host, CLKSEL64)); + else +@@ -422,6 +449,8 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample) + + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + clksel = mci_readl(host, CLKSEL64); + else +@@ -429,6 +458,8 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample) + clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample); + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + mci_writel(host, CLKSEL64, clksel); + else +@@ -443,6 +474,8 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host) + + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + clksel = mci_readl(host, CLKSEL64); + else +@@ -453,6 +486,8 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host) + + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + mci_writel(host, CLKSEL64, clksel); + else +@@ -632,6 +667,10 @@ static const struct of_device_id dw_mci_exynos_match[] = { + .data = &exynos_drv_data, }, + { .compatible = "samsung,exynos7-dw-mshc-smu", + .data = &exynos_drv_data, }, ++ { .compatible = "samsung,exynos7870-dw-mshc", ++ .data = &exynos_drv_data, }, ++ { .compatible = "samsung,exynos7870-dw-mshc-smu", ++ .data = &exynos_drv_data, }, + { .compatible = "axis,artpec8-dw-mshc", + .data = &artpec_drv_data, }, + {}, +-- +2.39.5 + diff --git a/queue-6.12/mmc-host-wait-for-vdd-to-settle-on-card-power-off.patch b/queue-6.12/mmc-host-wait-for-vdd-to-settle-on-card-power-off.patch new file mode 100644 index 0000000000..993897b5bf --- /dev/null +++ b/queue-6.12/mmc-host-wait-for-vdd-to-settle-on-card-power-off.patch @@ -0,0 +1,46 @@ +From 3a44ce978a711e0c3739e5821d6337150f7ff582 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 14:50:21 -0500 +Subject: mmc: host: Wait for Vdd to settle on card power off + +From: Erick Shepherd + +[ Upstream commit 31e75ed964582257f59156ce6a42860e1ae4cc39 ] + +The SD spec version 6.0 section 6.4.1.5 requires that Vdd must be +lowered to less than 0.5V for a minimum of 1 ms when powering off a +card. Increase wait to 15 ms so that voltage has time to drain down +to 0.5V and cards can power off correctly. Issues with voltage drain +time were only observed on Apollo Lake and Bay Trail host controllers +so this fix is limited to those devices. + +Signed-off-by: Erick Shepherd +Acked-by: Adrian Hunter +Link: https://lore.kernel.org/r/20250314195021.1588090-1-erick.shepherd@ni.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/sdhci-pci-core.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c +index 2e2e15e2d8fb8..b0b1d403f3527 100644 +--- a/drivers/mmc/host/sdhci-pci-core.c ++++ b/drivers/mmc/host/sdhci-pci-core.c +@@ -609,8 +609,12 @@ static void sdhci_intel_set_power(struct sdhci_host *host, unsigned char mode, + + sdhci_set_power(host, mode, vdd); + +- if (mode == MMC_POWER_OFF) ++ if (mode == MMC_POWER_OFF) { ++ if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_APL_SD || ++ slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BYT_SD) ++ usleep_range(15000, 17500); + return; ++ } + + /* + * Bus power might not enable after D3 -> D0 transition due to the +-- +2.39.5 + diff --git a/queue-6.12/mmc-sdhci-disable-sd-card-clock-before-changing-para.patch b/queue-6.12/mmc-sdhci-disable-sd-card-clock-before-changing-para.patch new file mode 100644 index 0000000000..e5cc5f1637 --- /dev/null +++ b/queue-6.12/mmc-sdhci-disable-sd-card-clock-before-changing-para.patch @@ -0,0 +1,54 @@ +From c997762379c4efdf58c48725bbd4f06ade02af5e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 15:46:45 -0600 +Subject: mmc: sdhci: Disable SD card clock before changing parameters +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Erick Shepherd + +[ Upstream commit fb3bbc46c94f261b6156ee863c1b06c84cf157dc ] + +Per the SD Host Controller Simplified Specification v4.20 §3.2.3, change +the SD card clock parameters only after first disabling the external card +clock. Doing this fixes a spurious clock pulse on Baytrail and Apollo Lake +SD controllers which otherwise breaks voltage switching with a specific +Swissbit SD card. + +Signed-off-by: Kyle Roeschley +Signed-off-by: Brad Mouring +Signed-off-by: Erick Shepherd +Acked-by: Adrian Hunter +Link: https://lore.kernel.org/r/20250211214645.469279-1-erick.shepherd@ni.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/sdhci.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c +index 4b91c9e966357..8ae76300d157d 100644 +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c +@@ -2035,10 +2035,15 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) + + host->mmc->actual_clock = 0; + +- sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); ++ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); ++ if (clk & SDHCI_CLOCK_CARD_EN) ++ sdhci_writew(host, clk & ~SDHCI_CLOCK_CARD_EN, ++ SDHCI_CLOCK_CONTROL); + +- if (clock == 0) ++ if (clock == 0) { ++ sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + return; ++ } + + clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); + sdhci_enable_clk(host, clk); +-- +2.39.5 + diff --git a/queue-6.12/mptcp-pm-userspace-flags-clearer-msg-if-no-remote-ad.patch b/queue-6.12/mptcp-pm-userspace-flags-clearer-msg-if-no-remote-ad.patch new file mode 100644 index 0000000000..33bd608e4f --- /dev/null +++ b/queue-6.12/mptcp-pm-userspace-flags-clearer-msg-if-no-remote-ad.patch @@ -0,0 +1,55 @@ +From 3149c6263cfdabbbf7c919051f261ca1a9ac0d8a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 14:59:20 +0100 +Subject: mptcp: pm: userspace: flags: clearer msg if no remote addr + +From: Matthieu Baerts (NGI0) + +[ Upstream commit 58b21309f97b08b6b9814d1ee1419249eba9ef08 ] + +Since its introduction in commit 892f396c8e68 ("mptcp: netlink: issue +MP_PRIO signals from userspace PMs"), it was mandatory to specify the +remote address, because of the 'if (rem->addr.family == AF_UNSPEC)' +check done later one. + +In theory, this attribute can be optional, but it sounds better to be +precise to avoid sending the MP_PRIO on the wrong subflow, e.g. if there +are multiple subflows attached to the same local ID. This can be relaxed +later on if there is a need to act on multiple subflows with one +command. + +For the moment, the check to see if attr_rem is NULL can be removed, +because mptcp_pm_parse_entry() will do this check as well, no need to do +that differently here. + +Reviewed-by: Geliang Tang +Signed-off-by: Matthieu Baerts (NGI0) +Reviewed-by: Simon Horman +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/mptcp/pm_userspace.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c +index e35178f5205fa..bb76295d04c56 100644 +--- a/net/mptcp/pm_userspace.c ++++ b/net/mptcp/pm_userspace.c +@@ -589,11 +589,9 @@ int mptcp_userspace_pm_set_flags(struct sk_buff *skb, struct genl_info *info) + if (ret < 0) + goto set_flags_err; + +- if (attr_rem) { +- ret = mptcp_pm_parse_entry(attr_rem, info, false, &rem); +- if (ret < 0) +- goto set_flags_err; +- } ++ ret = mptcp_pm_parse_entry(attr_rem, info, false, &rem); ++ if (ret < 0) ++ goto set_flags_err; + + if (loc.addr.family == AF_UNSPEC || + rem.addr.family == AF_UNSPEC) { +-- +2.39.5 + diff --git a/queue-6.12/net-enetc-refactor-bulk-flipping-of-rx-buffers-to-se.patch b/queue-6.12/net-enetc-refactor-bulk-flipping-of-rx-buffers-to-se.patch new file mode 100644 index 0000000000..0392ce3029 --- /dev/null +++ b/queue-6.12/net-enetc-refactor-bulk-flipping-of-rx-buffers-to-se.patch @@ -0,0 +1,66 @@ +From be3e420965eb62cb41a4f2c74d957600571e3c25 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 15:00:04 +0300 +Subject: net: enetc: refactor bulk flipping of RX buffers to separate function + +From: Vladimir Oltean + +[ Upstream commit 1d587faa5be7e9785b682cc5f58ba8f4100c13ea ] + +This small snippet of code ensures that we do something with the array +of RX software buffer descriptor elements after passing the skb to the +stack. In this case, we see if the other half of the page is reusable, +and if so, we "turn around" the buffers, making them directly usable by +enetc_refill_rx_ring() without going to enetc_new_page(). + +We will need to perform this kind of buffer flipping from a new code +path, i.e. from XDP_PASS. Currently, enetc_build_skb() does it there +buffer by buffer, but in a subsequent change we will stop using +enetc_build_skb() for XDP_PASS. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Wei Fang +Link: https://patch.msgid.link/20250417120005.3288549-3-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/enetc/enetc.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c +index f662a5d54986c..d8272b7a55fcb 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc.c +@@ -1572,6 +1572,16 @@ static void enetc_xdp_drop(struct enetc_bdr *rx_ring, int rx_ring_first, + } + } + ++static void enetc_bulk_flip_buff(struct enetc_bdr *rx_ring, int rx_ring_first, ++ int rx_ring_last) ++{ ++ while (rx_ring_first != rx_ring_last) { ++ enetc_flip_rx_buff(rx_ring, ++ &rx_ring->rx_swbd[rx_ring_first]); ++ enetc_bdr_idx_inc(rx_ring, &rx_ring_first); ++ } ++} ++ + static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring, + struct napi_struct *napi, int work_limit, + struct bpf_prog *prog) +@@ -1687,11 +1697,7 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring, + enetc_xdp_drop(rx_ring, orig_i, i); + rx_ring->stats.xdp_redirect_failures++; + } else { +- while (orig_i != i) { +- enetc_flip_rx_buff(rx_ring, +- &rx_ring->rx_swbd[orig_i]); +- enetc_bdr_idx_inc(rx_ring, &orig_i); +- } ++ enetc_bulk_flip_buff(rx_ring, orig_i, i); + xdp_redirect_frm_cnt++; + rx_ring->stats.xdp_redirect++; + } +-- +2.39.5 + diff --git a/queue-6.12/net-ethernet-mtk_ppe_offload-allow-qinq-double-eth_p.patch b/queue-6.12/net-ethernet-mtk_ppe_offload-allow-qinq-double-eth_p.patch new file mode 100644 index 0000000000..5648285cb1 --- /dev/null +++ b/queue-6.12/net-ethernet-mtk_ppe_offload-allow-qinq-double-eth_p.patch @@ -0,0 +1,88 @@ +From fade2d707dfc24460f66f19d795454e0302423e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 21:15:09 +0100 +Subject: net: ethernet: mtk_ppe_offload: Allow QinQ, double ETH_P_8021Q only + +From: Eric Woudstra + +[ Upstream commit 7fe0353606d77a32c4c7f2814833dd1c043ebdd2 ] + +mtk_foe_entry_set_vlan() in mtk_ppe.c already supports double vlan +tagging, but mtk_flow_offload_replace() in mtk_ppe_offload.c only allows +for 1 vlan tag, optionally in combination with pppoe and dsa tags. + +However, mtk_foe_entry_set_vlan() only allows for setting the vlan id. +The protocol cannot be set, it is always ETH_P_8021Q, for inner and outer +tag. This patch adds QinQ support to mtk_flow_offload_replace(), only in +the case that both inner and outer tags are ETH_P_8021Q. + +Only PPPoE-in-Q (as before) and Q-in-Q are allowed. A combination +of PPPoE and Q-in-Q is not allowed. + +Signed-off-by: Eric Woudstra +Link: https://patch.msgid.link/20250225201509.20843-1-ericwouds@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/mediatek/mtk_ppe_offload.c | 22 +++++++++---------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +index f20bb390df3ad..c855fb799ce14 100644 +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -34,8 +34,10 @@ struct mtk_flow_data { + u16 vlan_in; + + struct { +- u16 id; +- __be16 proto; ++ struct { ++ u16 id; ++ __be16 proto; ++ } vlans[2]; + u8 num; + } vlan; + struct { +@@ -349,18 +351,19 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f, + case FLOW_ACTION_CSUM: + break; + case FLOW_ACTION_VLAN_PUSH: +- if (data.vlan.num == 1 || ++ if (data.vlan.num + data.pppoe.num == 2 || + act->vlan.proto != htons(ETH_P_8021Q)) + return -EOPNOTSUPP; + +- data.vlan.id = act->vlan.vid; +- data.vlan.proto = act->vlan.proto; ++ data.vlan.vlans[data.vlan.num].id = act->vlan.vid; ++ data.vlan.vlans[data.vlan.num].proto = act->vlan.proto; + data.vlan.num++; + break; + case FLOW_ACTION_VLAN_POP: + break; + case FLOW_ACTION_PPPOE_PUSH: +- if (data.pppoe.num == 1) ++ if (data.pppoe.num == 1 || ++ data.vlan.num == 2) + return -EOPNOTSUPP; + + data.pppoe.sid = act->pppoe.sid; +@@ -450,12 +453,9 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f, + if (offload_type == MTK_PPE_PKT_TYPE_BRIDGE) + foe.bridge.vlan = data.vlan_in; + +- if (data.vlan.num == 1) { +- if (data.vlan.proto != htons(ETH_P_8021Q)) +- return -EOPNOTSUPP; ++ for (i = 0; i < data.vlan.num; i++) ++ mtk_foe_entry_set_vlan(eth, &foe, data.vlan.vlans[i].id); + +- mtk_foe_entry_set_vlan(eth, &foe, data.vlan.id); +- } + if (data.pppoe.num == 1) + mtk_foe_entry_set_pppoe(eth, &foe, data.pppoe.sid); + +-- +2.39.5 + diff --git a/queue-6.12/net-ethernet-ti-cpsw_new-populate-netdev-of_node.patch b/queue-6.12/net-ethernet-ti-cpsw_new-populate-netdev-of_node.patch new file mode 100644 index 0000000000..97a2cd93ce --- /dev/null +++ b/queue-6.12/net-ethernet-ti-cpsw_new-populate-netdev-of_node.patch @@ -0,0 +1,37 @@ +From 7e65dea44969911128d1d0d921dd2cb075621b6c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 08:46:57 +0100 +Subject: net: ethernet: ti: cpsw_new: populate netdev of_node + +From: Alexander Sverdlin + +[ Upstream commit 7ff1c88fc89688c27f773ba956f65f0c11367269 ] + +So that of_find_net_device_by_node() can find CPSW ports and other DSA +switches can be stacked downstream. Tested in conjunction with KSZ8873. + +Reviewed-by: Siddharth Vadapalli +Reviewed-by: Andrew Lunn +Signed-off-by: Alexander Sverdlin +Link: https://patch.msgid.link/20250303074703.1758297-1-alexander.sverdlin@siemens.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/ti/cpsw_new.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c +index 557cc71b9dd22..0eee1a0527b5c 100644 +--- a/drivers/net/ethernet/ti/cpsw_new.c ++++ b/drivers/net/ethernet/ti/cpsw_new.c +@@ -1417,6 +1417,7 @@ static int cpsw_create_ports(struct cpsw_common *cpsw) + ndev->netdev_ops = &cpsw_netdev_ops; + ndev->ethtool_ops = &cpsw_ethtool_ops; + SET_NETDEV_DEV(ndev, dev); ++ ndev->dev.of_node = slave_data->slave_node; + + if (!napi_ndev) { + /* CPSW Host port CPDMA interface is shared between +-- +2.39.5 + diff --git a/queue-6.12/net-ethtool-prevent-flow-steering-to-rss-contexts-wh.patch b/queue-6.12/net-ethtool-prevent-flow-steering-to-rss-contexts-wh.patch new file mode 100644 index 0000000000..399ccc4c10 --- /dev/null +++ b/queue-6.12/net-ethtool-prevent-flow-steering-to-rss-contexts-wh.patch @@ -0,0 +1,48 @@ +From 78153538a016587abd0c3ceded6e4b8895dbadcc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 15:53:28 -0800 +Subject: net: ethtool: prevent flow steering to RSS contexts which don't exist + +From: Jakub Kicinski + +[ Upstream commit de7f7582dff292832fbdeaeff34e6b2ee6f9f95f ] + +Since commit 42dc431f5d0e ("ethtool: rss: prevent rss ctx deletion +when in use") we prevent removal of RSS contexts pointed to by +existing flow rules. Core should also prevent creation of rules +which point to RSS context which don't exist in the first place. + +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20250206235334.1425329-2-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index 8b9692c35e706..6ed01cec97a8e 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -993,10 +993,14 @@ static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, + return rc; + + /* Nonzero ring with RSS only makes sense if NIC adds them together */ +- if (cmd == ETHTOOL_SRXCLSRLINS && info.fs.flow_type & FLOW_RSS && +- !ops->cap_rss_rxnfc_adds && +- ethtool_get_flow_spec_ring(info.fs.ring_cookie)) +- return -EINVAL; ++ if (cmd == ETHTOOL_SRXCLSRLINS && info.fs.flow_type & FLOW_RSS) { ++ if (!ops->cap_rss_rxnfc_adds && ++ ethtool_get_flow_spec_ring(info.fs.ring_cookie)) ++ return -EINVAL; ++ ++ if (!xa_load(&dev->ethtool->rss_ctx, info.rss_context)) ++ return -EINVAL; ++ } + + if (cmd == ETHTOOL_SRXFH && ops->get_rxfh) { + struct ethtool_rxfh_param rxfh = {}; +-- +2.39.5 + diff --git a/queue-6.12/net-fec-refactor-mac-reset-to-function.patch b/queue-6.12/net-fec-refactor-mac-reset-to-function.patch new file mode 100644 index 0000000000..91e5a9ff44 --- /dev/null +++ b/queue-6.12/net-fec-refactor-mac-reset-to-function.patch @@ -0,0 +1,118 @@ +From 3d4ca7653f3bab9afc8e9164589edc8258072546 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 13:12:55 +0100 +Subject: net: fec: Refactor MAC reset to function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Csókás, Bence + +[ Upstream commit 67800d296191d0a9bde0a7776f99ca1ddfa0fc26 ] + +The core is reset both in `fec_restart()` (called on link-up) and +`fec_stop()` (going to sleep, driver remove etc.). These two functions +had their separate implementations, which was at first only a register +write and a `udelay()` (and the accompanying block comment). However, +since then we got soft-reset (MAC disable) and Wake-on-LAN support, which +meant that these implementations diverged, often causing bugs. + +For instance, as of now, `fec_stop()` does not check for +`FEC_QUIRK_NO_HARD_RESET`, meaning the MII/RMII mode is cleared on eg. +a PM power-down event; and `fec_restart()` missed the refactor renaming +the "magic" constant `1` to `FEC_ECR_RESET`. + +To harmonize current implementations, and eliminate this source of +potential future bugs, refactor implementation to a common function. + +Reviewed-by: Michal Swiatkowski +Reviewed-by: Jacob Keller +Reviewed-by: Simon Horman +Signed-off-by: Csókás, Bence +Link: https://patch.msgid.link/20250207121255.161146-2-csokas.bence@prolan.hu +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_main.c | 52 +++++++++++------------ + 1 file changed, 25 insertions(+), 27 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index 04906897615d8..479ced24096b8 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -1098,6 +1098,29 @@ static void fec_enet_enable_ring(struct net_device *ndev) + } + } + ++/* Whack a reset. We should wait for this. ++ * For i.MX6SX SOC, enet use AXI bus, we use disable MAC ++ * instead of reset MAC itself. ++ */ ++static void fec_ctrl_reset(struct fec_enet_private *fep, bool allow_wol) ++{ ++ u32 val; ++ ++ if (!allow_wol || !(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) { ++ if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES || ++ ((fep->quirks & FEC_QUIRK_NO_HARD_RESET) && fep->link)) { ++ writel(0, fep->hwp + FEC_ECNTRL); ++ } else { ++ writel(FEC_ECR_RESET, fep->hwp + FEC_ECNTRL); ++ udelay(10); ++ } ++ } else { ++ val = readl(fep->hwp + FEC_ECNTRL); ++ val |= (FEC_ECR_MAGICEN | FEC_ECR_SLEEP); ++ writel(val, fep->hwp + FEC_ECNTRL); ++ } ++} ++ + /* + * This function is called to start or restart the FEC during a link + * change, transmit timeout, or to reconfigure the FEC. The network +@@ -1114,17 +1137,7 @@ fec_restart(struct net_device *ndev) + if (fep->bufdesc_ex) + fec_ptp_save_state(fep); + +- /* Whack a reset. We should wait for this. +- * For i.MX6SX SOC, enet use AXI bus, we use disable MAC +- * instead of reset MAC itself. +- */ +- if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES || +- ((fep->quirks & FEC_QUIRK_NO_HARD_RESET) && fep->link)) { +- writel(0, fep->hwp + FEC_ECNTRL); +- } else { +- writel(1, fep->hwp + FEC_ECNTRL); +- udelay(10); +- } ++ fec_ctrl_reset(fep, false); + + /* + * enet-mac reset will reset mac address registers too, +@@ -1378,22 +1391,7 @@ fec_stop(struct net_device *ndev) + if (fep->bufdesc_ex) + fec_ptp_save_state(fep); + +- /* Whack a reset. We should wait for this. +- * For i.MX6SX SOC, enet use AXI bus, we use disable MAC +- * instead of reset MAC itself. +- */ +- if (!(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) { +- if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES) { +- writel(0, fep->hwp + FEC_ECNTRL); +- } else { +- writel(FEC_ECR_RESET, fep->hwp + FEC_ECNTRL); +- udelay(10); +- } +- } else { +- val = readl(fep->hwp + FEC_ECNTRL); +- val |= (FEC_ECR_MAGICEN | FEC_ECR_SLEEP); +- writel(val, fep->hwp + FEC_ECNTRL); +- } ++ fec_ctrl_reset(fep, true); + writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); + writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); + +-- +2.39.5 + diff --git a/queue-6.12/net-flush_backlog-small-changes.patch b/queue-6.12/net-flush_backlog-small-changes.patch new file mode 100644 index 0000000000..1647036c99 --- /dev/null +++ b/queue-6.12/net-flush_backlog-small-changes.patch @@ -0,0 +1,75 @@ +From 21b19293a9a774de47c621d858564246d6eab678 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 14:48:25 +0000 +Subject: net: flush_backlog() small changes + +From: Eric Dumazet + +[ Upstream commit cbe08724c18078564abefbf6591078a7c98e5e0f ] + +Add READ_ONCE() around reads of skb->dev->reg_state, because +this field can be changed from other threads/cpus. + +Instead of calling dev_kfree_skb_irq() and kfree_skb() +while interrupts are masked and locks held, +use a temporary list and use __skb_queue_purge_reason() + +Use SKB_DROP_REASON_DEV_READY drop reason to better +describe why these skbs are dropped. + +Signed-off-by: Eric Dumazet +Reviewed-by: Jason Xing +Link: https://patch.msgid.link/20250204144825.316785-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/dev.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/net/core/dev.c b/net/core/dev.c +index 7b7b36c43c82c..2ba2160dd093a 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -6034,16 +6034,18 @@ static DEFINE_PER_CPU(struct work_struct, flush_works); + static void flush_backlog(struct work_struct *work) + { + struct sk_buff *skb, *tmp; ++ struct sk_buff_head list; + struct softnet_data *sd; + ++ __skb_queue_head_init(&list); + local_bh_disable(); + sd = this_cpu_ptr(&softnet_data); + + backlog_lock_irq_disable(sd); + skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) { +- if (skb->dev->reg_state == NETREG_UNREGISTERING) { ++ if (READ_ONCE(skb->dev->reg_state) == NETREG_UNREGISTERING) { + __skb_unlink(skb, &sd->input_pkt_queue); +- dev_kfree_skb_irq(skb); ++ __skb_queue_tail(&list, skb); + rps_input_queue_head_incr(sd); + } + } +@@ -6051,14 +6053,16 @@ static void flush_backlog(struct work_struct *work) + + local_lock_nested_bh(&softnet_data.process_queue_bh_lock); + skb_queue_walk_safe(&sd->process_queue, skb, tmp) { +- if (skb->dev->reg_state == NETREG_UNREGISTERING) { ++ if (READ_ONCE(skb->dev->reg_state) == NETREG_UNREGISTERING) { + __skb_unlink(skb, &sd->process_queue); +- kfree_skb(skb); ++ __skb_queue_tail(&list, skb); + rps_input_queue_head_incr(sd); + } + } + local_unlock_nested_bh(&softnet_data.process_queue_bh_lock); + local_bh_enable(); ++ ++ __skb_queue_purge_reason(&list, SKB_DROP_REASON_DEV_READY); + } + + static bool flush_required(int cpu) +-- +2.39.5 + diff --git a/queue-6.12/net-hsr-fix-prp-duplicate-detection.patch b/queue-6.12/net-hsr-fix-prp-duplicate-detection.patch new file mode 100644 index 0000000000..bb4dfaa64f --- /dev/null +++ b/queue-6.12/net-hsr-fix-prp-duplicate-detection.patch @@ -0,0 +1,247 @@ +From 55d9c52cd28c646d1ceb9d4cba3cdd7df0e8b2d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Mar 2025 18:16:59 +0200 +Subject: net: hsr: Fix PRP duplicate detection + +From: Jaakko Karrenpalo + +[ Upstream commit 05fd00e5e7b1ac60d264f72423fba38cc382b447 ] + +Add PRP specific function for handling duplicate +packets. This is needed because of potential +L2 802.1p prioritization done by network switches. + +The L2 prioritization can re-order the PRP packets +from a node causing the existing implementation to +discard the frame(s) that have been received 'late' +because the sequence number is before the previous +received packet. This can happen if the node is +sending multiple frames back-to-back with different +priority. + +Signed-off-by: Jaakko Karrenpalo +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250307161700.1045-1-jkarrenpalo@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_device.c | 2 + + net/hsr/hsr_forward.c | 4 +- + net/hsr/hsr_framereg.c | 95 ++++++++++++++++++++++++++++++++++++++++-- + net/hsr/hsr_framereg.h | 8 +++- + net/hsr/hsr_main.h | 2 + + 5 files changed, 104 insertions(+), 7 deletions(-) + +diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c +index 44048d7538ddc..9d0754b3642fd 100644 +--- a/net/hsr/hsr_device.c ++++ b/net/hsr/hsr_device.c +@@ -543,6 +543,7 @@ static struct hsr_proto_ops hsr_ops = { + .drop_frame = hsr_drop_frame, + .fill_frame_info = hsr_fill_frame_info, + .invalid_dan_ingress_frame = hsr_invalid_dan_ingress_frame, ++ .register_frame_out = hsr_register_frame_out, + }; + + static struct hsr_proto_ops prp_ops = { +@@ -553,6 +554,7 @@ static struct hsr_proto_ops prp_ops = { + .fill_frame_info = prp_fill_frame_info, + .handle_san_frame = prp_handle_san_frame, + .update_san_info = prp_update_san_info, ++ .register_frame_out = prp_register_frame_out, + }; + + void hsr_dev_setup(struct net_device *dev) +diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c +index c0217476eb17f..ace4e355d1647 100644 +--- a/net/hsr/hsr_forward.c ++++ b/net/hsr/hsr_forward.c +@@ -524,8 +524,8 @@ static void hsr_forward_do(struct hsr_frame_info *frame) + * Also for SAN, this shouldn't be done. + */ + if (!frame->is_from_san && +- hsr_register_frame_out(port, frame->node_src, +- frame->sequence_nr)) ++ hsr->proto_ops->register_frame_out && ++ hsr->proto_ops->register_frame_out(port, frame)) + continue; + + if (frame->is_supervision && port->type == HSR_PT_MASTER && +diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c +index 73bc6f659812f..85991fab7db58 100644 +--- a/net/hsr/hsr_framereg.c ++++ b/net/hsr/hsr_framereg.c +@@ -35,6 +35,7 @@ static bool seq_nr_after(u16 a, u16 b) + + #define seq_nr_before(a, b) seq_nr_after((b), (a)) + #define seq_nr_before_or_eq(a, b) (!seq_nr_after((a), (b))) ++#define PRP_DROP_WINDOW_LEN 32768 + + bool hsr_addr_is_redbox(struct hsr_priv *hsr, unsigned char *addr) + { +@@ -176,8 +177,11 @@ static struct hsr_node *hsr_add_node(struct hsr_priv *hsr, + new_node->time_in[i] = now; + new_node->time_out[i] = now; + } +- for (i = 0; i < HSR_PT_PORTS; i++) ++ for (i = 0; i < HSR_PT_PORTS; i++) { + new_node->seq_out[i] = seq_out; ++ new_node->seq_expected[i] = seq_out + 1; ++ new_node->seq_start[i] = seq_out + 1; ++ } + + if (san && hsr->proto_ops->handle_san_frame) + hsr->proto_ops->handle_san_frame(san, rx_port, new_node); +@@ -482,9 +486,11 @@ void hsr_register_frame_in(struct hsr_node *node, struct hsr_port *port, + * 0 otherwise, or + * negative error code on error + */ +-int hsr_register_frame_out(struct hsr_port *port, struct hsr_node *node, +- u16 sequence_nr) ++int hsr_register_frame_out(struct hsr_port *port, struct hsr_frame_info *frame) + { ++ struct hsr_node *node = frame->node_src; ++ u16 sequence_nr = frame->sequence_nr; ++ + spin_lock_bh(&node->seq_out_lock); + if (seq_nr_before_or_eq(sequence_nr, node->seq_out[port->type]) && + time_is_after_jiffies(node->time_out[port->type] + +@@ -499,6 +505,89 @@ int hsr_register_frame_out(struct hsr_port *port, struct hsr_node *node, + return 0; + } + ++/* Adaptation of the PRP duplicate discard algorithm described in wireshark ++ * wiki (https://wiki.wireshark.org/PRP) ++ * ++ * A drop window is maintained for both LANs with start sequence set to the ++ * first sequence accepted on the LAN that has not been seen on the other LAN, ++ * and expected sequence set to the latest received sequence number plus one. ++ * ++ * When a frame is received on either LAN it is compared against the received ++ * frames on the other LAN. If it is outside the drop window of the other LAN ++ * the frame is accepted and the drop window is updated. ++ * The drop window for the other LAN is reset. ++ * ++ * 'port' is the outgoing interface ++ * 'frame' is the frame to be sent ++ * ++ * Return: ++ * 1 if frame can be shown to have been sent recently on this interface, ++ * 0 otherwise ++ */ ++int prp_register_frame_out(struct hsr_port *port, struct hsr_frame_info *frame) ++{ ++ enum hsr_port_type other_port; ++ enum hsr_port_type rcv_port; ++ struct hsr_node *node; ++ u16 sequence_diff; ++ u16 sequence_exp; ++ u16 sequence_nr; ++ ++ /* out-going frames are always in order ++ * and can be checked the same way as for HSR ++ */ ++ if (frame->port_rcv->type == HSR_PT_MASTER) ++ return hsr_register_frame_out(port, frame); ++ ++ /* for PRP we should only forward frames from the slave ports ++ * to the master port ++ */ ++ if (port->type != HSR_PT_MASTER) ++ return 1; ++ ++ node = frame->node_src; ++ sequence_nr = frame->sequence_nr; ++ sequence_exp = sequence_nr + 1; ++ rcv_port = frame->port_rcv->type; ++ other_port = rcv_port == HSR_PT_SLAVE_A ? HSR_PT_SLAVE_B : ++ HSR_PT_SLAVE_A; ++ ++ spin_lock_bh(&node->seq_out_lock); ++ if (time_is_before_jiffies(node->time_out[port->type] + ++ msecs_to_jiffies(HSR_ENTRY_FORGET_TIME)) || ++ (node->seq_start[rcv_port] == node->seq_expected[rcv_port] && ++ node->seq_start[other_port] == node->seq_expected[other_port])) { ++ /* the node hasn't been sending for a while ++ * or both drop windows are empty, forward the frame ++ */ ++ node->seq_start[rcv_port] = sequence_nr; ++ } else if (seq_nr_before(sequence_nr, node->seq_expected[other_port]) && ++ seq_nr_before_or_eq(node->seq_start[other_port], sequence_nr)) { ++ /* drop the frame, update the drop window for the other port ++ * and reset our drop window ++ */ ++ node->seq_start[other_port] = sequence_exp; ++ node->seq_expected[rcv_port] = sequence_exp; ++ node->seq_start[rcv_port] = node->seq_expected[rcv_port]; ++ spin_unlock_bh(&node->seq_out_lock); ++ return 1; ++ } ++ ++ /* update the drop window for the port where this frame was received ++ * and clear the drop window for the other port ++ */ ++ node->seq_start[other_port] = node->seq_expected[other_port]; ++ node->seq_expected[rcv_port] = sequence_exp; ++ sequence_diff = sequence_exp - node->seq_start[rcv_port]; ++ if (sequence_diff > PRP_DROP_WINDOW_LEN) ++ node->seq_start[rcv_port] = sequence_exp - PRP_DROP_WINDOW_LEN; ++ ++ node->time_out[port->type] = jiffies; ++ node->seq_out[port->type] = sequence_nr; ++ spin_unlock_bh(&node->seq_out_lock); ++ return 0; ++} ++ + static struct hsr_port *get_late_port(struct hsr_priv *hsr, + struct hsr_node *node) + { +diff --git a/net/hsr/hsr_framereg.h b/net/hsr/hsr_framereg.h +index 993fa950d8144..b04948659d84d 100644 +--- a/net/hsr/hsr_framereg.h ++++ b/net/hsr/hsr_framereg.h +@@ -44,8 +44,7 @@ void hsr_addr_subst_dest(struct hsr_node *node_src, struct sk_buff *skb, + + void hsr_register_frame_in(struct hsr_node *node, struct hsr_port *port, + u16 sequence_nr); +-int hsr_register_frame_out(struct hsr_port *port, struct hsr_node *node, +- u16 sequence_nr); ++int hsr_register_frame_out(struct hsr_port *port, struct hsr_frame_info *frame); + + void hsr_prune_nodes(struct timer_list *t); + void hsr_prune_proxy_nodes(struct timer_list *t); +@@ -73,6 +72,8 @@ void prp_update_san_info(struct hsr_node *node, bool is_sup); + bool hsr_is_node_in_db(struct list_head *node_db, + const unsigned char addr[ETH_ALEN]); + ++int prp_register_frame_out(struct hsr_port *port, struct hsr_frame_info *frame); ++ + struct hsr_node { + struct list_head mac_list; + /* Protect R/W access to seq_out */ +@@ -89,6 +90,9 @@ struct hsr_node { + bool san_b; + u16 seq_out[HSR_PT_PORTS]; + bool removed; ++ /* PRP specific duplicate handling */ ++ u16 seq_expected[HSR_PT_PORTS]; ++ u16 seq_start[HSR_PT_PORTS]; + struct rcu_head rcu_head; + }; + +diff --git a/net/hsr/hsr_main.h b/net/hsr/hsr_main.h +index fcfeb79bb0401..e26244456f639 100644 +--- a/net/hsr/hsr_main.h ++++ b/net/hsr/hsr_main.h +@@ -183,6 +183,8 @@ struct hsr_proto_ops { + struct hsr_frame_info *frame); + bool (*invalid_dan_ingress_frame)(__be16 protocol); + void (*update_san_info)(struct hsr_node *node, bool is_sup); ++ int (*register_frame_out)(struct hsr_port *port, ++ struct hsr_frame_info *frame); + }; + + struct hsr_self_node { +-- +2.39.5 + diff --git a/queue-6.12/net-ipv6-init-tunnel-link-netns-before-registering-d.patch b/queue-6.12/net-ipv6-init-tunnel-link-netns-before-registering-d.patch new file mode 100644 index 0000000000..41b6e62125 --- /dev/null +++ b/queue-6.12/net-ipv6-init-tunnel-link-netns-before-registering-d.patch @@ -0,0 +1,157 @@ +From 9b2cd75ebd74be49d505e115806c531620c885b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 20:50:33 +0800 +Subject: net: ipv6: Init tunnel link-netns before registering dev + +From: Xiao Liang + +[ Upstream commit db014522f35606031d8ac58b4aed6b1ed84f03d1 ] + +Currently some IPv6 tunnel drivers set tnl->net to dev_net(dev) in +ndo_init(), which is called in register_netdevice(). However, it lacks +the context of link-netns when we enable cross-net tunnels at device +registration time. + +Let's move the init of tunnel link-netns before register_netdevice(). + +ip6_gre has already initialized netns, so just remove the redundant +assignment. + +Signed-off-by: Xiao Liang +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250219125039.18024-8-shaw.leon@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/ip6_gre.c | 2 -- + net/ipv6/ip6_tunnel.c | 3 ++- + net/ipv6/ip6_vti.c | 3 ++- + net/ipv6/sit.c | 8 +++++--- + 4 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c +index 235808cfec705..68e9a41eed491 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -1498,7 +1498,6 @@ static int ip6gre_tunnel_init_common(struct net_device *dev) + tunnel = netdev_priv(dev); + + tunnel->dev = dev; +- tunnel->net = dev_net(dev); + strcpy(tunnel->parms.name, dev->name); + + ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); +@@ -1882,7 +1881,6 @@ static int ip6erspan_tap_init(struct net_device *dev) + tunnel = netdev_priv(dev); + + tunnel->dev = dev; +- tunnel->net = dev_net(dev); + strcpy(tunnel->parms.name, dev->name); + + ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); +diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c +index 48fd53b989726..5350c9bb2319b 100644 +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -1878,7 +1878,6 @@ ip6_tnl_dev_init_gen(struct net_device *dev) + int t_hlen; + + t->dev = dev; +- t->net = dev_net(dev); + + ret = dst_cache_init(&t->dst_cache, GFP_KERNEL); + if (ret) +@@ -1940,6 +1939,7 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev) + struct net *net = dev_net(dev); + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + ++ t->net = net; + t->parms.proto = IPPROTO_IPV6; + + rcu_assign_pointer(ip6n->tnls_wc[0], t); +@@ -2013,6 +2013,7 @@ static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev, + int err; + + nt = netdev_priv(dev); ++ nt->net = net; + + if (ip_tunnel_netlink_encap_parms(data, &ipencap)) { + err = ip6_tnl_encap_setup(nt, &ipencap); +diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c +index 590737c275379..0123504691443 100644 +--- a/net/ipv6/ip6_vti.c ++++ b/net/ipv6/ip6_vti.c +@@ -925,7 +925,6 @@ static inline int vti6_dev_init_gen(struct net_device *dev) + struct ip6_tnl *t = netdev_priv(dev); + + t->dev = dev; +- t->net = dev_net(dev); + netdev_hold(dev, &t->dev_tracker, GFP_KERNEL); + netdev_lockdep_set_classes(dev); + return 0; +@@ -958,6 +957,7 @@ static int __net_init vti6_fb_tnl_dev_init(struct net_device *dev) + struct net *net = dev_net(dev); + struct vti6_net *ip6n = net_generic(net, vti6_net_id); + ++ t->net = net; + t->parms.proto = IPPROTO_IPV6; + + rcu_assign_pointer(ip6n->tnls_wc[0], t); +@@ -1008,6 +1008,7 @@ static int vti6_newlink(struct net *src_net, struct net_device *dev, + vti6_netlink_parms(data, &nt->parms); + + nt->parms.proto = IPPROTO_IPV6; ++ nt->net = net; + + if (vti6_locate(net, &nt->parms, 0)) + return -EEXIST; +diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c +index 39bd8951bfca1..3c15a0ae228e2 100644 +--- a/net/ipv6/sit.c ++++ b/net/ipv6/sit.c +@@ -269,6 +269,7 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net, + + nt = netdev_priv(dev); + ++ nt->net = net; + nt->parms = *parms; + if (ipip6_tunnel_create(dev) < 0) + goto failed_free; +@@ -1449,7 +1450,6 @@ static int ipip6_tunnel_init(struct net_device *dev) + int err; + + tunnel->dev = dev; +- tunnel->net = dev_net(dev); + strcpy(tunnel->parms.name, dev->name); + + ipip6_tunnel_bind_dev(dev); +@@ -1563,6 +1563,7 @@ static int ipip6_newlink(struct net *src_net, struct net_device *dev, + int err; + + nt = netdev_priv(dev); ++ nt->net = net; + + if (ip_tunnel_netlink_encap_parms(data, &ipencap)) { + err = ip_tunnel_encap_setup(nt, &ipencap); +@@ -1858,6 +1859,9 @@ static int __net_init sit_init_net(struct net *net) + */ + sitn->fb_tunnel_dev->netns_local = true; + ++ t = netdev_priv(sitn->fb_tunnel_dev); ++ t->net = net; ++ + err = register_netdev(sitn->fb_tunnel_dev); + if (err) + goto err_reg_dev; +@@ -1865,8 +1869,6 @@ static int __net_init sit_init_net(struct net *net) + ipip6_tunnel_clone_6rd(sitn->fb_tunnel_dev, sitn); + ipip6_fb_tunnel_init(sitn->fb_tunnel_dev); + +- t = netdev_priv(sitn->fb_tunnel_dev); +- + strcpy(t->parms.name, sitn->fb_tunnel_dev->name); + return 0; + +-- +2.39.5 + diff --git a/queue-6.12/net-mana-fix-warning-in-the-writer-of-client-oob.patch b/queue-6.12/net-mana-fix-warning-in-the-writer-of-client-oob.patch new file mode 100644 index 0000000000..3b96cfc454 --- /dev/null +++ b/queue-6.12/net-mana-fix-warning-in-the-writer-of-client-oob.patch @@ -0,0 +1,37 @@ +From 9ac65064550c9696d1de7b2405e84a13c6a56f95 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jan 2025 09:27:14 -0800 +Subject: net/mana: fix warning in the writer of client oob + +From: Konstantin Taranov + +[ Upstream commit 5ec7e1c86c441c46a374577bccd9488abea30037 ] + +Do not warn on missing pad_data when oob is in sgl. + +Signed-off-by: Konstantin Taranov +Link: https://patch.msgid.link/1737394039-28772-9-git-send-email-kotaranov@linux.microsoft.com +Reviewed-by: Shiraz Saleem +Reviewed-by: Long Li +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/microsoft/mana/gdma_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c +index 36802e0a8b570..9bac4083d8a09 100644 +--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c ++++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c +@@ -1044,7 +1044,7 @@ static u32 mana_gd_write_client_oob(const struct gdma_wqe_request *wqe_req, + header->inline_oob_size_div4 = client_oob_size / sizeof(u32); + + if (oob_in_sgl) { +- WARN_ON_ONCE(!pad_data || wqe_req->num_sge < 2); ++ WARN_ON_ONCE(wqe_req->num_sge < 2); + + header->client_oob_in_sgl = 1; + +-- +2.39.5 + diff --git a/queue-6.12/net-mlx4_core-avoid-impossible-mlx4_db_alloc-order-v.patch b/queue-6.12/net-mlx4_core-avoid-impossible-mlx4_db_alloc-order-v.patch new file mode 100644 index 0000000000..13b554c8f1 --- /dev/null +++ b/queue-6.12/net-mlx4_core-avoid-impossible-mlx4_db_alloc-order-v.patch @@ -0,0 +1,78 @@ +From f98e9fb5d0bc3c09de54d00fb6436119e8486eb2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 09:45:05 -0800 +Subject: net/mlx4_core: Avoid impossible mlx4_db_alloc() order value + +From: Kees Cook + +[ Upstream commit 4a6f18f28627e121bd1f74b5fcc9f945d6dbeb1e ] + +GCC can see that the value range for "order" is capped, but this leads +it to consider that it might be negative, leading to a false positive +warning (with GCC 15 with -Warray-bounds -fdiagnostics-details): + +../drivers/net/ethernet/mellanox/mlx4/alloc.c:691:47: error: array subscript -1 is below array bounds of 'long unsigned int *[2]' [-Werror=array-bounds=] + 691 | i = find_first_bit(pgdir->bits[o], MLX4_DB_PER_PAGE >> o); + | ~~~~~~~~~~~^~~ + 'mlx4_alloc_db_from_pgdir': events 1-2 + 691 | i = find_first_bit(pgdir->bits[o], MLX4_DB_PER_PAGE >> o); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | | | | | (2) out of array bounds here + | (1) when the condition is evaluated to true In file included from ../drivers/net/ethernet/mellanox/mlx4/mlx4.h:53, + from ../drivers/net/ethernet/mellanox/mlx4/alloc.c:42: +../include/linux/mlx4/device.h:664:33: note: while referencing 'bits' + 664 | unsigned long *bits[2]; + | ^~~~ + +Switch the argument to unsigned int, which removes the compiler needing +to consider negative values. + +Signed-off-by: Kees Cook +Link: https://patch.msgid.link/20250210174504.work.075-kees@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx4/alloc.c | 6 +++--- + include/linux/mlx4/device.h | 2 +- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx4/alloc.c b/drivers/net/ethernet/mellanox/mlx4/alloc.c +index b330020dc0d67..f2bded847e61d 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/alloc.c ++++ b/drivers/net/ethernet/mellanox/mlx4/alloc.c +@@ -682,9 +682,9 @@ static struct mlx4_db_pgdir *mlx4_alloc_db_pgdir(struct device *dma_device) + } + + static int mlx4_alloc_db_from_pgdir(struct mlx4_db_pgdir *pgdir, +- struct mlx4_db *db, int order) ++ struct mlx4_db *db, unsigned int order) + { +- int o; ++ unsigned int o; + int i; + + for (o = order; o <= 1; ++o) { +@@ -712,7 +712,7 @@ static int mlx4_alloc_db_from_pgdir(struct mlx4_db_pgdir *pgdir, + return 0; + } + +-int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, int order) ++int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, unsigned int order) + { + struct mlx4_priv *priv = mlx4_priv(dev); + struct mlx4_db_pgdir *pgdir; +diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h +index 27f42f713c891..86f0f2a25a3d6 100644 +--- a/include/linux/mlx4/device.h ++++ b/include/linux/mlx4/device.h +@@ -1135,7 +1135,7 @@ int mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, + int mlx4_buf_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, + struct mlx4_buf *buf); + +-int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, int order); ++int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, unsigned int order); + void mlx4_db_free(struct mlx4_dev *dev, struct mlx4_db *db); + + int mlx4_alloc_hwq_res(struct mlx4_dev *dev, struct mlx4_hwq_resources *wqres, +-- +2.39.5 + diff --git a/queue-6.12/net-mlx5-apply-rate-limiting-to-high-temperature-war.patch b/queue-6.12/net-mlx5-apply-rate-limiting-to-high-temperature-war.patch new file mode 100644 index 0000000000..b54f9aeb3e --- /dev/null +++ b/queue-6.12/net-mlx5-apply-rate-limiting-to-high-temperature-war.patch @@ -0,0 +1,45 @@ +From 5403ddd741aece4b2579b633e7d9509d23ec2103 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 11:46:38 +0200 +Subject: net/mlx5: Apply rate-limiting to high temperature warning + +From: Shahar Shitrit + +[ Upstream commit 9dd3d5d258aceb37bdf09c8b91fa448f58ea81f0 ] + +Wrap the high temperature warning in a temperature event with +a call to net_ratelimit() to prevent flooding the kernel log +with repeated warning messages when temperature exceeds the +threshold multiple times within a short duration. + +Signed-off-by: Shahar Shitrit +Signed-off-by: Tariq Toukan +Reviewed-by: Mateusz Polchlopek +Link: https://patch.msgid.link/20250213094641.226501-2-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/events.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/events.c b/drivers/net/ethernet/mellanox/mlx5/core/events.c +index cd8d107f7d9e3..fc6e56305cbbc 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/events.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/events.c +@@ -169,9 +169,10 @@ static int temp_warn(struct notifier_block *nb, unsigned long type, void *data) + value_lsb &= 0x1; + value_msb = be64_to_cpu(eqe->data.temp_warning.sensor_warning_msb); + +- mlx5_core_warn(events->dev, +- "High temperature on sensors with bit set %llx %llx", +- value_msb, value_lsb); ++ if (net_ratelimit()) ++ mlx5_core_warn(events->dev, ++ "High temperature on sensors with bit set %llx %llx", ++ value_msb, value_lsb); + + return NOTIFY_OK; + } +-- +2.39.5 + diff --git a/queue-6.12/net-mlx5-avoid-report-two-health-errors-on-same-synd.patch b/queue-6.12/net-mlx5-avoid-report-two-health-errors-on-same-synd.patch new file mode 100644 index 0000000000..7362b5a8fb --- /dev/null +++ b/queue-6.12/net-mlx5-avoid-report-two-health-errors-on-same-synd.patch @@ -0,0 +1,42 @@ +From 00a9da08d9ea4958ef9b9b73f8731132c415a515 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 14:25:40 +0200 +Subject: net/mlx5: Avoid report two health errors on same syndrome + +From: Moshe Shemesh + +[ Upstream commit b5d7b2f04ebcff740f44ef4d295b3401aeb029f4 ] + +In case health counter has not increased for few polling intervals, miss +counter will reach max misses threshold and health report will be +triggered for FW health reporter. In case syndrome found on same health +poll another health report will be triggered. + +Avoid two health reports on same syndrome by marking this syndrome as +already known. + +Signed-off-by: Moshe Shemesh +Reviewed-by: Shahar Shitrit +Signed-off-by: Tariq Toukan +Reviewed-by: Kalesh AP +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/health.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c +index a6329ca2d9bff..52c8035547be5 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/health.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c +@@ -799,6 +799,7 @@ static void poll_health(struct timer_list *t) + health->prev = count; + if (health->miss_counter == MAX_MISSES) { + mlx5_core_err(dev, "device's health compromised - reached miss count\n"); ++ health->synd = ioread8(&h->synd); + print_health_info(dev); + queue_work(health->wq, &health->report_work); + } +-- +2.39.5 + diff --git a/queue-6.12/net-mlx5-change-pool_next_size-define-value-and-make.patch b/queue-6.12/net-mlx5-change-pool_next_size-define-value-and-make.patch new file mode 100644 index 0000000000..7bc25502fd --- /dev/null +++ b/queue-6.12/net-mlx5-change-pool_next_size-define-value-and-make.patch @@ -0,0 +1,108 @@ +From 6b02bb6d380941391c44ed8c3c4e3d7adb5d83d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 10:58:08 +0200 +Subject: net/mlx5: Change POOL_NEXT_SIZE define value and make it global + +From: Patrisious Haddad + +[ Upstream commit 80df31f384b4146a62a01b3d4beb376cc7b9a89e ] + +Change POOL_NEXT_SIZE define value from 0 to BIT(30), since this define +is used to request the available maximum sized flow table, and zero doesn't +make sense for it, whereas some places in the driver use zero explicitly +expecting the smallest table size possible but instead due to this +define they end up allocating the biggest table size unawarely. + +In addition move the definition to "include/linux/mlx5/fs.h" to expose the +define to IB driver as well, while appropriately renaming it. + +Signed-off-by: Patrisious Haddad +Reviewed-by: Maor Gottlieb +Reviewed-by: Mark Bloch +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/20250219085808.349923-3-tariqt@nvidia.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c | 2 +- + drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c | 6 ++++-- + drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h | 2 -- + drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c | 3 ++- + include/linux/mlx5/fs.h | 2 ++ + 5 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c +index 8587cd572da53..bdb825aa87268 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c +@@ -96,7 +96,7 @@ static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw) + if (!flow_group_in) + return -ENOMEM; + +- ft_attr.max_fte = POOL_NEXT_SIZE; ++ ft_attr.max_fte = MLX5_FS_MAX_POOL_SIZE; + ft_attr.prio = LEGACY_FDB_PRIO; + fdb = mlx5_create_flow_table(root_ns, &ft_attr); + if (IS_ERR(fdb)) { +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c +index c14590acc7726..f6abfd00d7e68 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c +@@ -50,10 +50,12 @@ mlx5_ft_pool_get_avail_sz(struct mlx5_core_dev *dev, enum fs_flow_table_type tab + int i, found_i = -1; + + for (i = ARRAY_SIZE(FT_POOLS) - 1; i >= 0; i--) { +- if (dev->priv.ft_pool->ft_left[i] && FT_POOLS[i] >= desired_size && ++ if (dev->priv.ft_pool->ft_left[i] && ++ (FT_POOLS[i] >= desired_size || ++ desired_size == MLX5_FS_MAX_POOL_SIZE) && + FT_POOLS[i] <= max_ft_size) { + found_i = i; +- if (desired_size != POOL_NEXT_SIZE) ++ if (desired_size != MLX5_FS_MAX_POOL_SIZE) + break; + } + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h +index 25f4274b372b5..173e312db7204 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h +@@ -7,8 +7,6 @@ + #include + #include "fs_core.h" + +-#define POOL_NEXT_SIZE 0 +- + int mlx5_ft_pool_init(struct mlx5_core_dev *dev); + void mlx5_ft_pool_destroy(struct mlx5_core_dev *dev); + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c +index 711d14dea2485..d313cb7f0ed88 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c +@@ -161,7 +161,8 @@ mlx5_chains_create_table(struct mlx5_fs_chains *chains, + ft_attr.flags |= (MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT | + MLX5_FLOW_TABLE_TUNNEL_EN_DECAP); + +- sz = (chain == mlx5_chains_get_nf_ft_chain(chains)) ? FT_TBL_SZ : POOL_NEXT_SIZE; ++ sz = (chain == mlx5_chains_get_nf_ft_chain(chains)) ? ++ FT_TBL_SZ : MLX5_FS_MAX_POOL_SIZE; + ft_attr.max_fte = sz; + + /* We use chains_default_ft(chains) as the table's next_ft till +diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h +index b744e554f014d..db5c9ddef1702 100644 +--- a/include/linux/mlx5/fs.h ++++ b/include/linux/mlx5/fs.h +@@ -40,6 +40,8 @@ + + #define MLX5_SET_CFG(p, f, v) MLX5_SET(create_flow_group_in, p, f, v) + ++#define MLX5_FS_MAX_POOL_SIZE BIT(30) ++ + enum mlx5_flow_destination_type { + MLX5_FLOW_DESTINATION_TYPE_NONE, + MLX5_FLOW_DESTINATION_TYPE_VPORT, +-- +2.39.5 + diff --git a/queue-6.12/net-mlx5-extend-ethtool-loopback-selftest-to-support.patch b/queue-6.12/net-mlx5-extend-ethtool-loopback-selftest-to-support.patch new file mode 100644 index 0000000000..18f4104e2c --- /dev/null +++ b/queue-6.12/net-mlx5-extend-ethtool-loopback-selftest-to-support.patch @@ -0,0 +1,41 @@ +From dc278d6865aec60c5a0e1b55cd416b271ca75133 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Feb 2025 12:17:15 +0200 +Subject: net/mlx5: Extend Ethtool loopback selftest to support non-linear SKB + +From: Alexei Lazar + +[ Upstream commit 95b9606b15bb3ce1198d28d2393dd0e1f0a5f3e9 ] + +Current loopback test validation ignores non-linear SKB case in +the SKB access, which can lead to failures in scenarios such as +when HW GRO is enabled. +Linearize the SKB so both cases will be handled. + +Signed-off-by: Alexei Lazar +Reviewed-by: Dragos Tatulea +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/20250209101716.112774-15-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c +index 1d60465cc2ca4..2f7a543feca62 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c +@@ -166,6 +166,9 @@ mlx5e_test_loopback_validate(struct sk_buff *skb, + struct udphdr *udph; + struct iphdr *iph; + ++ if (skb_linearize(skb)) ++ goto out; ++ + /* We are only going to peek, no need to clone the SKB */ + if (MLX5E_TEST_PKT_SIZE - ETH_HLEN > skb_headlen(skb)) + goto out; +-- +2.39.5 + diff --git a/queue-6.12/net-mlx5-modify-lsb-bitmask-in-temperature-event-to-.patch b/queue-6.12/net-mlx5-modify-lsb-bitmask-in-temperature-event-to-.patch new file mode 100644 index 0000000000..abdae7659d --- /dev/null +++ b/queue-6.12/net-mlx5-modify-lsb-bitmask-in-temperature-event-to-.patch @@ -0,0 +1,46 @@ +From 9b5cada437957fbe15fea50301c7271d1abdd431 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 11:46:40 +0200 +Subject: net/mlx5: Modify LSB bitmask in temperature event to include only the + first bit + +From: Shahar Shitrit + +[ Upstream commit 633f16d7e07c129a36b882c05379e01ce5bdb542 ] + +In the sensor_count field of the MTEWE register, bits 1-62 are +supported only for unmanaged switches, not for NICs, and bit 63 +is reserved for internal use. + +To prevent confusing output that may include set bits that are +not relevant to NIC sensors, we update the bitmask to retain only +the first bit, which corresponds to the sensor ASIC. + +Signed-off-by: Shahar Shitrit +Signed-off-by: Tariq Toukan +Reviewed-by: Mateusz Polchlopek +Link: https://patch.msgid.link/20250213094641.226501-4-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/events.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/events.c b/drivers/net/ethernet/mellanox/mlx5/core/events.c +index d91ea53eb394d..cd8d107f7d9e3 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/events.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/events.c +@@ -163,6 +163,10 @@ static int temp_warn(struct notifier_block *nb, unsigned long type, void *data) + u64 value_msb; + + value_lsb = be64_to_cpu(eqe->data.temp_warning.sensor_warning_lsb); ++ /* bit 1-63 are not supported for NICs, ++ * hence read only bit 0 (asic) from lsb. ++ */ ++ value_lsb &= 0x1; + value_msb = be64_to_cpu(eqe->data.temp_warning.sensor_warning_msb); + + mlx5_core_warn(events->dev, +-- +2.39.5 + diff --git a/queue-6.12/net-mlx5-xdp-enable-tx-side-xdp-multi-buffer-support.patch b/queue-6.12/net-mlx5-xdp-enable-tx-side-xdp-multi-buffer-support.patch new file mode 100644 index 0000000000..3d97215274 --- /dev/null +++ b/queue-6.12/net-mlx5-xdp-enable-tx-side-xdp-multi-buffer-support.patch @@ -0,0 +1,206 @@ +From 7484380154dc81c8d7c8d33ae3de16ac308b66fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Feb 2025 12:17:16 +0200 +Subject: net/mlx5: XDP, Enable TX side XDP multi-buffer support + +From: Alexei Lazar + +[ Upstream commit 1a9304859b3a4119579524c293b902a8927180f3 ] + +In XDP scenarios, fragmented packets can occur if the MTU is larger +than the page size, even when the packet size fits within the linear +part. +If XDP multi-buffer support is disabled, the fragmented part won't be +handled in the TX flow, leading to packet drops. + +Since XDP multi-buffer support is always available, this commit removes +the conditional check for enabling it. +This ensures that XDP multi-buffer support is always enabled, +regardless of the `is_xdp_mb` parameter, and guarantees the handling of +fragmented packets in such scenarios. + +Signed-off-by: Alexei Lazar +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/20250209101716.112774-16-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en.h | 1 - + .../ethernet/mellanox/mlx5/core/en/params.c | 1 - + .../ethernet/mellanox/mlx5/core/en/params.h | 1 - + .../mellanox/mlx5/core/en/reporter_tx.c | 1 - + .../net/ethernet/mellanox/mlx5/core/en/xdp.c | 49 ++++++++----------- + .../net/ethernet/mellanox/mlx5/core/en_main.c | 29 ----------- + 6 files changed, 21 insertions(+), 61 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h +index 57b7298a0e793..d6266f6a96d6e 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h +@@ -385,7 +385,6 @@ enum { + MLX5E_SQ_STATE_VLAN_NEED_L2_INLINE, + MLX5E_SQ_STATE_PENDING_XSK_TX, + MLX5E_SQ_STATE_PENDING_TLS_RX_RESYNC, +- MLX5E_SQ_STATE_XDP_MULTIBUF, + MLX5E_NUM_SQ_STATES, /* Must be kept last */ + }; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +index 31eb99f09c63c..8c4d710e85675 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +@@ -1242,7 +1242,6 @@ void mlx5e_build_xdpsq_param(struct mlx5_core_dev *mdev, + mlx5e_build_sq_param_common(mdev, param); + MLX5_SET(wq, wq, log_wq_sz, params->log_sq_size); + param->is_mpw = MLX5E_GET_PFLAG(params, MLX5E_PFLAG_XDP_TX_MPWQE); +- param->is_xdp_mb = !mlx5e_rx_is_linear_skb(mdev, params, xsk); + mlx5e_build_tx_cq_param(mdev, params, ¶m->cqp); + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.h b/drivers/net/ethernet/mellanox/mlx5/core/en/params.h +index 3f8986f9d8629..bd5877acc5b1e 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.h +@@ -33,7 +33,6 @@ struct mlx5e_sq_param { + struct mlx5_wq_param wq; + bool is_mpw; + bool is_tls; +- bool is_xdp_mb; + u16 stop_room; + }; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +index c8adf309ecad0..dbd9482359e1e 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +@@ -16,7 +16,6 @@ static const char * const sq_sw_state_type_name[] = { + [MLX5E_SQ_STATE_VLAN_NEED_L2_INLINE] = "vlan_need_l2_inline", + [MLX5E_SQ_STATE_PENDING_XSK_TX] = "pending_xsk_tx", + [MLX5E_SQ_STATE_PENDING_TLS_RX_RESYNC] = "pending_tls_rx_resync", +- [MLX5E_SQ_STATE_XDP_MULTIBUF] = "xdp_multibuf", + }; + + static int mlx5e_wait_for_sq_flush(struct mlx5e_txqsq *sq) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c +index 4610621a340e5..08ab0999f7b31 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c +@@ -546,6 +546,7 @@ mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd, + bool inline_ok; + bool linear; + u16 pi; ++ int i; + + struct mlx5e_xdpsq_stats *stats = sq->stats; + +@@ -612,41 +613,33 @@ mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd, + + cseg->opmod_idx_opcode = cpu_to_be32((sq->pc << 8) | MLX5_OPCODE_SEND); + +- if (test_bit(MLX5E_SQ_STATE_XDP_MULTIBUF, &sq->state)) { +- int i; +- +- memset(&cseg->trailer, 0, sizeof(cseg->trailer)); +- memset(eseg, 0, sizeof(*eseg) - sizeof(eseg->trailer)); +- +- eseg->inline_hdr.sz = cpu_to_be16(inline_hdr_sz); ++ memset(&cseg->trailer, 0, sizeof(cseg->trailer)); ++ memset(eseg, 0, sizeof(*eseg) - sizeof(eseg->trailer)); + +- for (i = 0; i < num_frags; i++) { +- skb_frag_t *frag = &xdptxdf->sinfo->frags[i]; +- dma_addr_t addr; ++ eseg->inline_hdr.sz = cpu_to_be16(inline_hdr_sz); + +- addr = xdptxdf->dma_arr ? xdptxdf->dma_arr[i] : +- page_pool_get_dma_addr(skb_frag_page(frag)) + +- skb_frag_off(frag); ++ for (i = 0; i < num_frags; i++) { ++ skb_frag_t *frag = &xdptxdf->sinfo->frags[i]; ++ dma_addr_t addr; + +- dseg->addr = cpu_to_be64(addr); +- dseg->byte_count = cpu_to_be32(skb_frag_size(frag)); +- dseg->lkey = sq->mkey_be; +- dseg++; +- } ++ addr = xdptxdf->dma_arr ? xdptxdf->dma_arr[i] : ++ page_pool_get_dma_addr(skb_frag_page(frag)) + ++ skb_frag_off(frag); + +- cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt); ++ dseg->addr = cpu_to_be64(addr); ++ dseg->byte_count = cpu_to_be32(skb_frag_size(frag)); ++ dseg->lkey = sq->mkey_be; ++ dseg++; ++ } + +- sq->db.wqe_info[pi] = (struct mlx5e_xdp_wqe_info) { +- .num_wqebbs = num_wqebbs, +- .num_pkts = 1, +- }; ++ cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt); + +- sq->pc += num_wqebbs; +- } else { +- cseg->fm_ce_se = 0; ++ sq->db.wqe_info[pi] = (struct mlx5e_xdp_wqe_info) { ++ .num_wqebbs = num_wqebbs, ++ .num_pkts = 1, ++ }; + +- sq->pc++; +- } ++ sq->pc += num_wqebbs; + + xsk_tx_metadata_request(meta, &mlx5e_xsk_tx_metadata_ops, eseg); + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 3e9ad3cb8121d..38055537b12ac 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -2030,41 +2030,12 @@ int mlx5e_open_xdpsq(struct mlx5e_channel *c, struct mlx5e_params *params, + csp.min_inline_mode = sq->min_inline_mode; + set_bit(MLX5E_SQ_STATE_ENABLED, &sq->state); + +- if (param->is_xdp_mb) +- set_bit(MLX5E_SQ_STATE_XDP_MULTIBUF, &sq->state); +- + err = mlx5e_create_sq_rdy(c->mdev, param, &csp, 0, &sq->sqn); + if (err) + goto err_free_xdpsq; + + mlx5e_set_xmit_fp(sq, param->is_mpw); + +- if (!param->is_mpw && !test_bit(MLX5E_SQ_STATE_XDP_MULTIBUF, &sq->state)) { +- unsigned int ds_cnt = MLX5E_TX_WQE_EMPTY_DS_COUNT + 1; +- unsigned int inline_hdr_sz = 0; +- int i; +- +- if (sq->min_inline_mode != MLX5_INLINE_MODE_NONE) { +- inline_hdr_sz = MLX5E_XDP_MIN_INLINE; +- ds_cnt++; +- } +- +- /* Pre initialize fixed WQE fields */ +- for (i = 0; i < mlx5_wq_cyc_get_size(&sq->wq); i++) { +- struct mlx5e_tx_wqe *wqe = mlx5_wq_cyc_get_wqe(&sq->wq, i); +- struct mlx5_wqe_ctrl_seg *cseg = &wqe->ctrl; +- struct mlx5_wqe_eth_seg *eseg = &wqe->eth; +- +- sq->db.wqe_info[i] = (struct mlx5e_xdp_wqe_info) { +- .num_wqebbs = 1, +- .num_pkts = 1, +- }; +- +- cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt); +- eseg->inline_hdr.sz = cpu_to_be16(inline_hdr_sz); +- } +- } +- + return 0; + + err_free_xdpsq: +-- +2.39.5 + diff --git a/queue-6.12/net-mlx5e-add-correct-match-to-check-ipsec-syndromes.patch b/queue-6.12/net-mlx5e-add-correct-match-to-check-ipsec-syndromes.patch new file mode 100644 index 0000000000..03c8478234 --- /dev/null +++ b/queue-6.12/net-mlx5e-add-correct-match-to-check-ipsec-syndromes.patch @@ -0,0 +1,148 @@ +From 3fb87b8e74c817b226104597aed2dfa3b6bb66dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 23:39:53 +0200 +Subject: net/mlx5e: Add correct match to check IPSec syndromes for switchdev + mode + +From: Jianbo Liu + +[ Upstream commit 85e4a808af2545fefaf18c8fe50071b06fcbdabc ] + +In commit dddb49b63d86 ("net/mlx5e: Add IPsec and ASO syndromes check +in HW"), IPSec and ASO syndromes checks after decryption for the +specified ASO object were added. But they are correct only for eswith +in legacy mode. For switchdev mode, metadata register c1 is used to +save the mapped id (not ASO object id). So, need to change the match +accordingly for the check rules in status table. + +Signed-off-by: Jianbo Liu +Reviewed-by: Leon Romanovsky +Reviewed-by: Patrisious Haddad +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/20250220213959.504304-4-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/en_accel/ipsec_fs.c | 28 ++++++++++++++----- + .../mellanox/mlx5/core/esw/ipsec_fs.c | 13 +++++++++ + .../mellanox/mlx5/core/esw/ipsec_fs.h | 5 ++++ + include/linux/mlx5/eswitch.h | 2 ++ + 4 files changed, 41 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +index 57861d34d46f8..59b9653f573c8 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +@@ -165,6 +165,25 @@ static void ipsec_rx_status_pass_destroy(struct mlx5e_ipsec *ipsec, + #endif + } + ++static void ipsec_rx_rule_add_match_obj(struct mlx5e_ipsec_sa_entry *sa_entry, ++ struct mlx5e_ipsec_rx *rx, ++ struct mlx5_flow_spec *spec) ++{ ++ struct mlx5e_ipsec *ipsec = sa_entry->ipsec; ++ ++ if (rx == ipsec->rx_esw) { ++ mlx5_esw_ipsec_rx_rule_add_match_obj(sa_entry, spec); ++ } else { ++ MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, ++ misc_parameters_2.metadata_reg_c_2); ++ MLX5_SET(fte_match_param, spec->match_value, ++ misc_parameters_2.metadata_reg_c_2, ++ sa_entry->ipsec_obj_id | BIT(31)); ++ ++ spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2; ++ } ++} ++ + static int rx_add_rule_drop_auth_trailer(struct mlx5e_ipsec_sa_entry *sa_entry, + struct mlx5e_ipsec_rx *rx) + { +@@ -200,11 +219,8 @@ static int rx_add_rule_drop_auth_trailer(struct mlx5e_ipsec_sa_entry *sa_entry, + + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.ipsec_syndrome); + MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.ipsec_syndrome, 1); +- MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_2); +- MLX5_SET(fte_match_param, spec->match_value, +- misc_parameters_2.metadata_reg_c_2, +- sa_entry->ipsec_obj_id | BIT(31)); + spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2; ++ ipsec_rx_rule_add_match_obj(sa_entry, rx, spec); + rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); +@@ -281,10 +297,8 @@ static int rx_add_rule_drop_replay(struct mlx5e_ipsec_sa_entry *sa_entry, struct + + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_4); + MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_4, 1); +- MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_2); +- MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_2, +- sa_entry->ipsec_obj_id | BIT(31)); + spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2; ++ ipsec_rx_rule_add_match_obj(sa_entry, rx, spec); + rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c +index ed977ae75fab8..4bba2884c1c05 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c +@@ -85,6 +85,19 @@ int mlx5_esw_ipsec_rx_setup_modify_header(struct mlx5e_ipsec_sa_entry *sa_entry, + return err; + } + ++void mlx5_esw_ipsec_rx_rule_add_match_obj(struct mlx5e_ipsec_sa_entry *sa_entry, ++ struct mlx5_flow_spec *spec) ++{ ++ MLX5_SET(fte_match_param, spec->match_criteria, ++ misc_parameters_2.metadata_reg_c_1, ++ ESW_IPSEC_RX_MAPPED_ID_MATCH_MASK); ++ MLX5_SET(fte_match_param, spec->match_value, ++ misc_parameters_2.metadata_reg_c_1, ++ sa_entry->rx_mapped_id << ESW_ZONE_ID_BITS); ++ ++ spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2; ++} ++ + void mlx5_esw_ipsec_rx_id_mapping_remove(struct mlx5e_ipsec_sa_entry *sa_entry) + { + struct mlx5e_ipsec *ipsec = sa_entry->ipsec; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h +index ac9c65b89166e..514c15258b1d1 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h +@@ -20,6 +20,8 @@ int mlx5_esw_ipsec_rx_ipsec_obj_id_search(struct mlx5e_priv *priv, u32 id, + void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_tx_create_attr *attr); + void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev); ++void mlx5_esw_ipsec_rx_rule_add_match_obj(struct mlx5e_ipsec_sa_entry *sa_entry, ++ struct mlx5_flow_spec *spec); + #else + static inline void mlx5_esw_ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_rx_create_attr *attr) {} +@@ -48,5 +50,8 @@ static inline void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_tx_create_attr *attr) {} + + static inline void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev) {} ++static inline void ++mlx5_esw_ipsec_rx_rule_add_match_obj(struct mlx5e_ipsec_sa_entry *sa_entry, ++ struct mlx5_flow_spec *spec) {} + #endif /* CONFIG_MLX5_ESWITCH */ + #endif /* __MLX5_ESW_IPSEC_FS_H__ */ +diff --git a/include/linux/mlx5/eswitch.h b/include/linux/mlx5/eswitch.h +index df73a2ccc9af3..67256e776566c 100644 +--- a/include/linux/mlx5/eswitch.h ++++ b/include/linux/mlx5/eswitch.h +@@ -147,6 +147,8 @@ u32 mlx5_eswitch_get_vport_metadata_for_set(struct mlx5_eswitch *esw, + + /* reuse tun_opts for the mapped ipsec obj id when tun_id is 0 (invalid) */ + #define ESW_IPSEC_RX_MAPPED_ID_MASK GENMASK(ESW_TUN_OPTS_BITS - 1, 0) ++#define ESW_IPSEC_RX_MAPPED_ID_MATCH_MASK \ ++ GENMASK(31 - ESW_RESERVED_BITS, ESW_ZONE_ID_BITS) + + u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev); + u16 mlx5_eswitch_get_total_vports(const struct mlx5_core_dev *dev); +-- +2.39.5 + diff --git a/queue-6.12/net-mlx5e-avoid-warn_on-when-configuring-mqprio-with.patch b/queue-6.12/net-mlx5e-avoid-warn_on-when-configuring-mqprio-with.patch new file mode 100644 index 0000000000..27354ff2b2 --- /dev/null +++ b/queue-6.12/net-mlx5e-avoid-warn_on-when-configuring-mqprio-with.patch @@ -0,0 +1,49 @@ +From 21ff6801089234902e04aec82e7db8486946fd43 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 23:35:16 +0200 +Subject: net/mlx5e: Avoid WARN_ON when configuring MQPRIO with HTB offload + enabled + +From: Carolina Jubran + +[ Upstream commit 689805dcc474c2accb5cffbbcea1c06ee4a54570 ] + +When attempting to enable MQPRIO while HTB offload is already +configured, the driver currently returns `-EINVAL` and triggers a +`WARN_ON`, leading to an unnecessary call trace. + +Update the code to handle this case more gracefully by returning +`-EOPNOTSUPP` instead, while also providing a helpful user message. + +Signed-off-by: Carolina Jubran +Reviewed-by: Yael Chemla +Reviewed-by: Cosmin Ratiu +Signed-off-by: Tariq Toukan +Reviewed-by: Kalesh AP +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 38055537b12ac..4a2f58a9d7066 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -3759,8 +3759,11 @@ static int mlx5e_setup_tc_mqprio(struct mlx5e_priv *priv, + /* MQPRIO is another toplevel qdisc that can't be attached + * simultaneously with the offloaded HTB. + */ +- if (WARN_ON(mlx5e_selq_is_htb_enabled(&priv->selq))) +- return -EINVAL; ++ if (mlx5e_selq_is_htb_enabled(&priv->selq)) { ++ NL_SET_ERR_MSG_MOD(mqprio->extack, ++ "MQPRIO cannot be configured when HTB offload is enabled."); ++ return -EOPNOTSUPP; ++ } + + switch (mqprio->mode) { + case TC_MQPRIO_MODE_DCB: +-- +2.39.5 + diff --git a/queue-6.12/net-mlx5e-reduce-rep-rxq-depth-to-256-for-ecpf.patch b/queue-6.12/net-mlx5e-reduce-rep-rxq-depth-to-256-for-ecpf.patch new file mode 100644 index 0000000000..dc3c8f29ff --- /dev/null +++ b/queue-6.12/net-mlx5e-reduce-rep-rxq-depth-to-256-for-ecpf.patch @@ -0,0 +1,75 @@ +From 8aebbc2114a6d387d7473933ac92c5fddb616566 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Feb 2025 12:17:08 +0200 +Subject: net/mlx5e: reduce rep rxq depth to 256 for ECPF + +From: William Tu + +[ Upstream commit b9cc8f9d700867aaa77aedddfea85e53d5e5d584 ] + +By experiments, a single queue representor netdev consumes kernel +memory around 2.8MB, and 1.8MB out of the 2.8MB is due to page +pool for the RXQ. Scaling to a thousand representors consumes 2.8GB, +which becomes a memory pressure issue for embedded devices such as +BlueField-2 16GB / BlueField-3 32GB memory. + +Since representor netdevs mostly handles miss traffic, and ideally, +most of the traffic will be offloaded, reduce the default non-uplink +rep netdev's RXQ default depth from 1024 to 256 if mdev is ecpf eswitch +manager. This saves around 1MB of memory per regular RQ, +(1024 - 256) * 2KB, allocated from page pool. + +With rxq depth of 256, the netlink page pool tool reports +$./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml \ + --dump page-pool-get + {'id': 277, + 'ifindex': 9, + 'inflight': 128, + 'inflight-mem': 786432, + 'napi-id': 775}] + +This is due to mtu 1500 + headroom consumes half pages, so 256 rxq +entries consumes around 128 pages (thus create a page pool with +size 128), shown above at inflight. + +Note that each netdev has multiple types of RQs, including +Regular RQ, XSK, PTP, Drop, Trap RQ. Since non-uplink representor +only supports regular rq, this patch only changes the regular RQ's +default depth. + +Signed-off-by: William Tu +Reviewed-by: Bodong Wang +Reviewed-by: Saeed Mahameed +Signed-off-by: Tariq Toukan +Reviewed-by: Michal Swiatkowski +Link: https://patch.msgid.link/20250209101716.112774-8-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +index fd1f460b7be65..18ec392d17404 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +@@ -65,6 +65,7 @@ + #define MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE \ + max(0x7, MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE) + #define MLX5E_REP_PARAMS_DEF_NUM_CHANNELS 1 ++#define MLX5E_REP_PARAMS_DEF_LOG_RQ_SIZE 0x8 + + static const char mlx5e_rep_driver_name[] = "mlx5e_rep"; + +@@ -854,6 +855,8 @@ static void mlx5e_build_rep_params(struct net_device *netdev) + + /* RQ */ + mlx5e_build_rq_params(mdev, params); ++ if (!mlx5e_is_uplink_rep(priv) && mlx5_core_is_ecpf(mdev)) ++ params->log_rq_mtu_frames = MLX5E_REP_PARAMS_DEF_LOG_RQ_SIZE; + + /* If netdev is already registered (e.g. move from nic profile to uplink, + * RTNL lock must be held before triggering netdev notifiers. +-- +2.39.5 + diff --git a/queue-6.12/net-mlx5e-reduce-the-max-log-mpwrq-sz-for-ecpf-and-r.patch b/queue-6.12/net-mlx5e-reduce-the-max-log-mpwrq-sz-for-ecpf-and-r.patch new file mode 100644 index 0000000000..97faa1ecd1 --- /dev/null +++ b/queue-6.12/net-mlx5e-reduce-the-max-log-mpwrq-sz-for-ecpf-and-r.patch @@ -0,0 +1,92 @@ +From 1c71ab780360893fa0cfda1f9550a630e3c691a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Feb 2025 12:17:07 +0200 +Subject: net/mlx5e: reduce the max log mpwrq sz for ECPF and reps + +From: William Tu + +[ Upstream commit e1d68ea58c7e9ebacd9ad7a99b25a3578fa62182 ] + +For the ECPF and representors, reduce the max MPWRQ size from 256KB (18) +to 128KB (17). This prepares the later patch for saving representor +memory. + +With Striding RQ, there is a minimum of 4 MPWQEs. So with 128KB of max +MPWRQ size, the minimal memory is 4 * 128KB = 512KB. When creating page +pool, consider 1500 mtu, the minimal page pool size will be 512KB/4KB = +128 pages = 256 rx ring entries (2 entries per page). + +Before this patch, setting RX ringsize (ethtool -G rx) to 256 causes +driver to allocate page pool size more than it needs due to max MPWRQ +is 256KB (18). Ex: 4 * 256KB = 1MB, 1MB/4KB = 256 pages, but actually +128 pages is good enough. Reducing the max MPWRQ to 128KB fixes the +limitation. + +Signed-off-by: William Tu +Signed-off-by: Tariq Toukan +Reviewed-by: Michal Swiatkowski +Link: https://patch.msgid.link/20250209101716.112774-7-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en.h | 2 -- + .../net/ethernet/mellanox/mlx5/core/en/params.c | 15 +++++++++++---- + 2 files changed, 11 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h +index d6266f6a96d6e..e048a667e0758 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h +@@ -94,8 +94,6 @@ struct page_pool; + #define MLX5_MPWRQ_DEF_LOG_STRIDE_SZ(mdev) \ + MLX5_MPWRQ_LOG_STRIDE_SZ(mdev, order_base_2(MLX5E_RX_MAX_HEAD)) + +-#define MLX5_MPWRQ_MAX_LOG_WQE_SZ 18 +- + /* Keep in sync with mlx5e_mpwrq_log_wqe_sz. + * These are theoretical maximums, which can be further restricted by + * capabilities. These values are used for static resource allocations and +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +index 8c4d710e85675..58ec5e44aa7ad 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +@@ -10,6 +10,9 @@ + #include + #include + ++#define MLX5_MPWRQ_MAX_LOG_WQE_SZ 18 ++#define MLX5_REP_MPWRQ_MAX_LOG_WQE_SZ 17 ++ + static u8 mlx5e_mpwrq_min_page_shift(struct mlx5_core_dev *mdev) + { + u8 min_page_shift = MLX5_CAP_GEN_2(mdev, log_min_mkey_entity_size); +@@ -103,18 +106,22 @@ u8 mlx5e_mpwrq_log_wqe_sz(struct mlx5_core_dev *mdev, u8 page_shift, + enum mlx5e_mpwrq_umr_mode umr_mode) + { + u8 umr_entry_size = mlx5e_mpwrq_umr_entry_size(umr_mode); +- u8 max_pages_per_wqe, max_log_mpwqe_size; ++ u8 max_pages_per_wqe, max_log_wqe_size_calc; ++ u8 max_log_wqe_size_cap; + u16 max_wqe_size; + + /* Keep in sync with MLX5_MPWRQ_MAX_PAGES_PER_WQE. */ + max_wqe_size = mlx5e_get_max_sq_aligned_wqebbs(mdev) * MLX5_SEND_WQE_BB; + max_pages_per_wqe = ALIGN_DOWN(max_wqe_size - sizeof(struct mlx5e_umr_wqe), + MLX5_UMR_FLEX_ALIGNMENT) / umr_entry_size; +- max_log_mpwqe_size = ilog2(max_pages_per_wqe) + page_shift; ++ max_log_wqe_size_calc = ilog2(max_pages_per_wqe) + page_shift; ++ ++ WARN_ON_ONCE(max_log_wqe_size_calc < MLX5E_ORDER2_MAX_PACKET_MTU); + +- WARN_ON_ONCE(max_log_mpwqe_size < MLX5E_ORDER2_MAX_PACKET_MTU); ++ max_log_wqe_size_cap = mlx5_core_is_ecpf(mdev) ? ++ MLX5_REP_MPWRQ_MAX_LOG_WQE_SZ : MLX5_MPWRQ_MAX_LOG_WQE_SZ; + +- return min_t(u8, max_log_mpwqe_size, MLX5_MPWRQ_MAX_LOG_WQE_SZ); ++ return min_t(u8, max_log_wqe_size_calc, max_log_wqe_size_cap); + } + + u8 mlx5e_mpwrq_pages_per_wqe(struct mlx5_core_dev *mdev, u8 page_shift, +-- +2.39.5 + diff --git a/queue-6.12/net-mlx5e-set-the-tx_queue_len-for-pfifo_fast.patch b/queue-6.12/net-mlx5e-set-the-tx_queue_len-for-pfifo_fast.patch new file mode 100644 index 0000000000..f839dd6853 --- /dev/null +++ b/queue-6.12/net-mlx5e-set-the-tx_queue_len-for-pfifo_fast.patch @@ -0,0 +1,44 @@ +From 8eecccf10491a733371f6876b16f705aebe68231 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Feb 2025 12:17:09 +0200 +Subject: net/mlx5e: set the tx_queue_len for pfifo_fast + +From: William Tu + +[ Upstream commit a38cc5706fb9f7dc4ee3a443f61de13ce1e410ed ] + +By default, the mq netdev creates a pfifo_fast qdisc. On a +system with 16 core, the pfifo_fast with 3 bands consumes +16 * 3 * 8 (size of pointer) * 1024 (default tx queue len) += 393KB. The patch sets the tx qlen to representor default +value, 128 (1< +Reviewed-by: Daniel Jurgens +Signed-off-by: Tariq Toukan +Reviewed-by: Michal Swiatkowski +Link: https://patch.msgid.link/20250209101716.112774-9-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +index 0657d10765357..fd1f460b7be65 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +@@ -885,6 +885,8 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev, + netdev->ethtool_ops = &mlx5e_rep_ethtool_ops; + + netdev->watchdog_timeo = 15 * HZ; ++ if (mlx5_core_is_ecpf(mdev)) ++ netdev->tx_queue_len = 1 << MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE; + + #if IS_ENABLED(CONFIG_MLX5_CLS_ACT) + netdev->hw_features |= NETIF_F_HW_TC; +-- +2.39.5 + diff --git a/queue-6.12/net-page_pool-avoid-false-positive-warning-if-napi-w.patch b/queue-6.12/net-page_pool-avoid-false-positive-warning-if-napi-w.patch new file mode 100644 index 0000000000..7771f0eb13 --- /dev/null +++ b/queue-6.12/net-page_pool-avoid-false-positive-warning-if-napi-w.patch @@ -0,0 +1,72 @@ +From ce6df84395d0a10d697df996cb9ac977d5133331 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 14:56:37 -0800 +Subject: net: page_pool: avoid false positive warning if NAPI was never added + +From: Jakub Kicinski + +[ Upstream commit c1e00bc4be06cacee6307cedb9b55bbaddb5044d ] + +We expect NAPI to be in disabled state when page pool is torn down. +But it is also legal if the NAPI is completely uninitialized. + +Reviewed-by: Mina Almasry +Link: https://patch.msgid.link/20250206225638.1387810-4-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/dev.h | 12 ++++++++++++ + net/core/page_pool.c | 7 ++----- + 2 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/net/core/dev.h b/net/core/dev.h +index 2e3bb7669984a..764e0097ccf22 100644 +--- a/net/core/dev.h ++++ b/net/core/dev.h +@@ -148,6 +148,18 @@ void xdp_do_check_flushed(struct napi_struct *napi); + static inline void xdp_do_check_flushed(struct napi_struct *napi) { } + #endif + ++/* Best effort check that NAPI is not idle (can't be scheduled to run) */ ++static inline void napi_assert_will_not_race(const struct napi_struct *napi) ++{ ++ /* uninitialized instance, can't race */ ++ if (!napi->poll_list.next) ++ return; ++ ++ /* SCHED bit is set on disabled instances */ ++ WARN_ON(!test_bit(NAPI_STATE_SCHED, &napi->state)); ++ WARN_ON(READ_ONCE(napi->list_owner) != -1); ++} ++ + void kick_defer_list_purge(struct softnet_data *sd, unsigned int cpu); + + #define XMIT_RECURSION_LIMIT 8 +diff --git a/net/core/page_pool.c b/net/core/page_pool.c +index 7b20f6fcb82c0..c8ce069605c42 100644 +--- a/net/core/page_pool.c ++++ b/net/core/page_pool.c +@@ -25,6 +25,7 @@ + + #include + ++#include "dev.h" + #include "mp_dmabuf_devmem.h" + #include "netmem_priv.h" + #include "page_pool_priv.h" +@@ -1108,11 +1109,7 @@ void page_pool_disable_direct_recycling(struct page_pool *pool) + if (!pool->p.napi) + return; + +- /* To avoid races with recycling and additional barriers make sure +- * pool and NAPI are unlinked when NAPI is disabled. +- */ +- WARN_ON(!test_bit(NAPI_STATE_SCHED, &pool->p.napi->state)); +- WARN_ON(READ_ONCE(pool->p.napi->list_owner) != -1); ++ napi_assert_will_not_race(pool->p.napi); + + WRITE_ONCE(pool->p.napi, NULL); + } +-- +2.39.5 + diff --git a/queue-6.12/net-phy-nxp-c45-tja11xx-add-match_phy_device-to-tja1.patch b/queue-6.12/net-phy-nxp-c45-tja11xx-add-match_phy_device-to-tja1.patch new file mode 100644 index 0000000000..bbd52bfef8 --- /dev/null +++ b/queue-6.12/net-phy-nxp-c45-tja11xx-add-match_phy_device-to-tja1.patch @@ -0,0 +1,118 @@ +From dec8859b4c827bea5c5bd1431ecddd2ce7d5f9db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 17:43:19 +0200 +Subject: net: phy: nxp-c45-tja11xx: add match_phy_device to TJA1103/TJA1104 + +From: Andrei Botila + +[ Upstream commit a06a868a0cd96bc51401cdea897313a3f6ad01a0 ] + +Add .match_phy_device for the existing TJAs to differentiate between +TJA1103 and TJA1104. +TJA1103 and TJA1104 share the same PHY_ID but TJA1104 has MACsec +capabilities while TJA1103 doesn't. + +Signed-off-by: Andrei Botila +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250228154320.2979000-2-andrei.botila@oss.nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/nxp-c45-tja11xx.c | 54 +++++++++++++++++++++++++++++-- + 1 file changed, 52 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c +index 9788b820c6be7..99a5eee77bec1 100644 +--- a/drivers/net/phy/nxp-c45-tja11xx.c ++++ b/drivers/net/phy/nxp-c45-tja11xx.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* NXP C45 PHY driver +- * Copyright 2021-2023 NXP ++ * Copyright 2021-2025 NXP + * Author: Radu Pirea + */ + +@@ -18,6 +18,8 @@ + + #include "nxp-c45-tja11xx.h" + ++#define PHY_ID_MASK GENMASK(31, 4) ++/* Same id: TJA1103, TJA1104 */ + #define PHY_ID_TJA_1103 0x001BB010 + #define PHY_ID_TJA_1120 0x001BB031 + +@@ -1930,6 +1932,30 @@ static void tja1120_nmi_handler(struct phy_device *phydev, + } + } + ++static int nxp_c45_macsec_ability(struct phy_device *phydev) ++{ ++ bool macsec_ability; ++ int phy_abilities; ++ ++ phy_abilities = phy_read_mmd(phydev, MDIO_MMD_VEND1, ++ VEND1_PORT_ABILITIES); ++ macsec_ability = !!(phy_abilities & MACSEC_ABILITY); ++ ++ return macsec_ability; ++} ++ ++static int tja1103_match_phy_device(struct phy_device *phydev) ++{ ++ return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) && ++ !nxp_c45_macsec_ability(phydev); ++} ++ ++static int tja1104_match_phy_device(struct phy_device *phydev) ++{ ++ return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) && ++ nxp_c45_macsec_ability(phydev); ++} ++ + static const struct nxp_c45_regmap tja1120_regmap = { + .vend1_ptp_clk_period = 0x1020, + .vend1_event_msg_filt = 0x9010, +@@ -2000,7 +2026,6 @@ static const struct nxp_c45_phy_data tja1120_phy_data = { + + static struct phy_driver nxp_c45_driver[] = { + { +- PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103), + .name = "NXP C45 TJA1103", + .get_features = nxp_c45_get_features, + .driver_data = &tja1103_phy_data, +@@ -2022,6 +2047,31 @@ static struct phy_driver nxp_c45_driver[] = { + .get_sqi = nxp_c45_get_sqi, + .get_sqi_max = nxp_c45_get_sqi_max, + .remove = nxp_c45_remove, ++ .match_phy_device = tja1103_match_phy_device, ++ }, ++ { ++ .name = "NXP C45 TJA1104", ++ .get_features = nxp_c45_get_features, ++ .driver_data = &tja1103_phy_data, ++ .probe = nxp_c45_probe, ++ .soft_reset = nxp_c45_soft_reset, ++ .config_aneg = genphy_c45_config_aneg, ++ .config_init = nxp_c45_config_init, ++ .config_intr = tja1103_config_intr, ++ .handle_interrupt = nxp_c45_handle_interrupt, ++ .read_status = genphy_c45_read_status, ++ .suspend = genphy_c45_pma_suspend, ++ .resume = genphy_c45_pma_resume, ++ .get_sset_count = nxp_c45_get_sset_count, ++ .get_strings = nxp_c45_get_strings, ++ .get_stats = nxp_c45_get_stats, ++ .cable_test_start = nxp_c45_cable_test_start, ++ .cable_test_get_status = nxp_c45_cable_test_get_status, ++ .set_loopback = genphy_c45_loopback, ++ .get_sqi = nxp_c45_get_sqi, ++ .get_sqi_max = nxp_c45_get_sqi_max, ++ .remove = nxp_c45_remove, ++ .match_phy_device = tja1104_match_phy_device, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120), +-- +2.39.5 + diff --git a/queue-6.12/net-phylink-use-pl-link_interface-in-phylink_expects.patch b/queue-6.12/net-phylink-use-pl-link_interface-in-phylink_expects.patch new file mode 100644 index 0000000000..dc13a13833 --- /dev/null +++ b/queue-6.12/net-phylink-use-pl-link_interface-in-phylink_expects.patch @@ -0,0 +1,59 @@ +From ecab843997900d659195333e7e718f6b53932d92 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 20:15:17 +0800 +Subject: net: phylink: use pl->link_interface in phylink_expects_phy() + +From: Choong Yong Liang + +[ Upstream commit b63263555eaafbf9ab1a82f2020bbee872d83759 ] + +The phylink_expects_phy() function allows MAC drivers to check if they are +expecting a PHY to attach. The checking condition in phylink_expects_phy() +aims to achieve the same result as the checking condition in +phylink_attach_phy(). + +However, the checking condition in phylink_expects_phy() uses +pl->link_config.interface, while phylink_attach_phy() uses +pl->link_interface. + +Initially, both pl->link_interface and pl->link_config.interface are set +to SGMII, and pl->cfg_link_an_mode is set to MLO_AN_INBAND. + +When the interface switches from SGMII to 2500BASE-X, +pl->link_config.interface is updated by phylink_major_config(). +At this point, pl->cfg_link_an_mode remains MLO_AN_INBAND, and +pl->link_config.interface is set to 2500BASE-X. +Subsequently, when the STMMAC interface is taken down +administratively and brought back up, it is blocked by +phylink_expects_phy(). + +Since phylink_expects_phy() and phylink_attach_phy() aim to achieve the +same result, phylink_expects_phy() should check pl->link_interface, +which never changes, instead of pl->link_config.interface, which is +updated by phylink_major_config(). + +Reviewed-by: Russell King (Oracle) +Signed-off-by: Choong Yong Liang +Link: https://patch.msgid.link/20250227121522.1802832-2-yong.liang.choong@linux.intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/phylink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c +index 3e9957b6aa148..b78dfcbec936c 100644 +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -1811,7 +1811,7 @@ bool phylink_expects_phy(struct phylink *pl) + { + if (pl->cfg_link_an_mode == MLO_AN_FIXED || + (pl->cfg_link_an_mode == MLO_AN_INBAND && +- phy_interface_mode_is_8023z(pl->link_config.interface))) ++ phy_interface_mode_is_8023z(pl->link_interface))) + return false; + return true; + } +-- +2.39.5 + diff --git a/queue-6.12/net-pktgen-fix-access-outside-of-user-given-buffer-i.patch b/queue-6.12/net-pktgen-fix-access-outside-of-user-given-buffer-i.patch new file mode 100644 index 0000000000..4b50ce427f --- /dev/null +++ b/queue-6.12/net-pktgen-fix-access-outside-of-user-given-buffer-i.patch @@ -0,0 +1,50 @@ +From bff7e807bc71e3e6bd8fb1c231554924719a6e95 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 09:45:27 +0100 +Subject: net: pktgen: fix access outside of user given buffer in + pktgen_thread_write() + +From: Peter Seiderer + +[ Upstream commit 425e64440ad0a2f03bdaf04be0ae53dededbaa77 ] + +Honour the user given buffer size for the strn_len() calls (otherwise +strn_len() will access memory outside of the user given buffer). + +Signed-off-by: Peter Seiderer +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250219084527.20488-8-ps.report@gmx.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/pktgen.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/net/core/pktgen.c b/net/core/pktgen.c +index 4d87da56c56a0..762ede0278990 100644 +--- a/net/core/pktgen.c ++++ b/net/core/pktgen.c +@@ -1898,8 +1898,8 @@ static ssize_t pktgen_thread_write(struct file *file, + i = len; + + /* Read variable name */ +- +- len = strn_len(&user_buffer[i], sizeof(name) - 1); ++ max = min(sizeof(name) - 1, count - i); ++ len = strn_len(&user_buffer[i], max); + if (len < 0) + return len; + +@@ -1929,7 +1929,8 @@ static ssize_t pktgen_thread_write(struct file *file, + if (!strcmp(name, "add_device")) { + char f[32]; + memset(f, 0, 32); +- len = strn_len(&user_buffer[i], sizeof(f) - 1); ++ max = min(sizeof(f) - 1, count - i); ++ len = strn_len(&user_buffer[i], max); + if (len < 0) { + ret = len; + goto out; +-- +2.39.5 + diff --git a/queue-6.12/net-pktgen-fix-mpls-maximum-labels-list-parsing.patch b/queue-6.12/net-pktgen-fix-mpls-maximum-labels-list-parsing.patch new file mode 100644 index 0000000000..0a507650f2 --- /dev/null +++ b/queue-6.12/net-pktgen-fix-mpls-maximum-labels-list-parsing.patch @@ -0,0 +1,52 @@ +From d66e2bef4ea37fce0cceec71a3ddbd050211a693 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 14:56:00 +0100 +Subject: net: pktgen: fix mpls maximum labels list parsing + +From: Peter Seiderer + +[ Upstream commit 2b15a0693f70d1e8119743ee89edbfb1271b3ea8 ] + +Fix mpls maximum labels list parsing up to MAX_MPLS_LABELS entries (instead +of up to MAX_MPLS_LABELS - 1). + +Addresses the following: + + $ echo "mpls 00000f00,00000f01,00000f02,00000f03,00000f04,00000f05,00000f06,00000f07,00000f08,00000f09,00000f0a,00000f0b,00000f0c,00000f0d,00000f0e,00000f0f" > /proc/net/pktgen/lo\@0 + -bash: echo: write error: Argument list too long + +Signed-off-by: Peter Seiderer +Reviewed-by: Simon Horman +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/core/pktgen.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/core/pktgen.c b/net/core/pktgen.c +index b6db4910359bb..4d87da56c56a0 100644 +--- a/net/core/pktgen.c ++++ b/net/core/pktgen.c +@@ -898,6 +898,10 @@ static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev) + pkt_dev->nr_labels = 0; + do { + __u32 tmp; ++ ++ if (n >= MAX_MPLS_LABELS) ++ return -E2BIG; ++ + len = hex32_arg(&buffer[i], 8, &tmp); + if (len <= 0) + return len; +@@ -909,8 +913,6 @@ static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev) + return -EFAULT; + i++; + n++; +- if (n >= MAX_MPLS_LABELS) +- return -E2BIG; + } while (c == ','); + + pkt_dev->nr_labels = n; +-- +2.39.5 + diff --git a/queue-6.12/net-smc-use-the-correct-ndev-to-find-pnetid-by-pneti.patch b/queue-6.12/net-smc-use-the-correct-ndev-to-find-pnetid-by-pneti.patch new file mode 100644 index 0000000000..3780c9e902 --- /dev/null +++ b/queue-6.12/net-smc-use-the-correct-ndev-to-find-pnetid-by-pneti.patch @@ -0,0 +1,120 @@ +From 9b501e74411c8dbd50e4945a6036437da12b0095 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 20:43:04 +0800 +Subject: net/smc: use the correct ndev to find pnetid by pnetid table + +From: Guangguan Wang + +[ Upstream commit bfc6c67ec2d64d0ca4e5cc3e1ac84298a10b8d62 ] + +When using smc_pnet in SMC, it will only search the pnetid in the +base_ndev of the netdev hierarchy(both HW PNETID and User-defined +sw pnetid). This may not work for some scenarios when using SMC in +container on cloud environment. +In container, there have choices of different container network, +such as directly using host network, virtual network IPVLAN, veth, +etc. Different choices of container network have different netdev +hierarchy. Examples of netdev hierarchy show below. (eth0 and eth1 +in host below is the netdev directly related to the physical device). + _______________________________ + | _________________ | + | |POD | | + | | | | + | | eth0_________ | | + | |____| |__| | + | | | | + | | | | + | eth1|base_ndev| eth0_______ | + | | | | RDMA || + | host |_________| |_______|| + --------------------------------- + netdev hierarchy if directly using host network + ________________________________ + | _________________ | + | |POD __________ | | + | | |upper_ndev| | | + | |eth0|__________| | | + | |_______|_________| | + | |lower netdev | + | __|______ | + | eth1| | eth0_______ | + | |base_ndev| | RDMA || + | host |_________| |_______|| + --------------------------------- + netdev hierarchy if using IPVLAN + _______________________________ + | _____________________ | + | |POD _________ | | + | | |base_ndev|| | + | |eth0(veth)|_________|| | + | |____________|________| | + | |pairs | + | _______|_ | + | | | eth0_______ | + | veth|base_ndev| | RDMA || + | |_________| |_______|| + | _________ | + | eth1|base_ndev| | + | host |_________| | + --------------------------------- + netdev hierarchy if using veth +Due to some reasons, the eth1 in host is not RDMA attached netdevice, +pnetid is needed to map the eth1(in host) with RDMA device so that POD +can do SMC-R. Because the eth1(in host) is managed by CNI plugin(such +as Terway, network management plugin in container environment), and in +cloud environment the eth(in host) can dynamically be inserted by CNI +when POD create and dynamically be removed by CNI when POD destroy and +no POD related to the eth(in host) anymore. It is hard to config the +pnetid to the eth1(in host). But it is easy to config the pnetid to the +netdevice which can be seen in POD. When do SMC-R, both the container +directly using host network and the container using veth network can +successfully match the RDMA device, because the configured pnetid netdev +is a base_ndev. But the container using IPVLAN can not successfully +match the RDMA device and 0x03030000 fallback happens, because the +configured pnetid netdev is not a base_ndev. Additionally, if config +pnetid to the eth1(in host) also can not work for matching RDMA device +when using veth network and doing SMC-R in POD. + +To resolve the problems list above, this patch extends to search user +-defined sw pnetid in the clc handshake ndev when no pnetid can be found +in the base_ndev, and the base_ndev take precedence over ndev for backward +compatibility. This patch also can unify the pnetid setup of different +network choices list above in container(Config user-defined sw pnetid in +the netdevice can be seen in POD). + +Signed-off-by: Guangguan Wang +Reviewed-by: Wenjia Zhang +Reviewed-by: Halil Pasic +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/smc/smc_pnet.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c +index 716808f374a8d..b391c2ef463f2 100644 +--- a/net/smc/smc_pnet.c ++++ b/net/smc/smc_pnet.c +@@ -1079,14 +1079,16 @@ static void smc_pnet_find_roce_by_pnetid(struct net_device *ndev, + struct smc_init_info *ini) + { + u8 ndev_pnetid[SMC_MAX_PNETID_LEN]; ++ struct net_device *base_ndev; + struct net *net; + +- ndev = pnet_find_base_ndev(ndev); ++ base_ndev = pnet_find_base_ndev(ndev); + net = dev_net(ndev); +- if (smc_pnetid_by_dev_port(ndev->dev.parent, ndev->dev_port, ++ if (smc_pnetid_by_dev_port(base_ndev->dev.parent, base_ndev->dev_port, + ndev_pnetid) && ++ smc_pnet_find_ndev_pnetid_by_table(base_ndev, ndev_pnetid) && + smc_pnet_find_ndev_pnetid_by_table(ndev, ndev_pnetid)) { +- smc_pnet_find_rdma_dev(ndev, ini); ++ smc_pnet_find_rdma_dev(base_ndev, ini); + return; /* pnetid could not be determined */ + } + _smc_pnet_find_roce_by_pnetid(ndev_pnetid, ini, NULL, net); +-- +2.39.5 + diff --git a/queue-6.12/net-stmmac-dwmac-loongson-set-correct-tx-rx-_fifo_si.patch b/queue-6.12/net-stmmac-dwmac-loongson-set-correct-tx-rx-_fifo_si.patch new file mode 100644 index 0000000000..1ce0489395 --- /dev/null +++ b/queue-6.12/net-stmmac-dwmac-loongson-set-correct-tx-rx-_fifo_si.patch @@ -0,0 +1,52 @@ +From 73a4fa816f73ef6d610beceb63385cdc2537373b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 21:43:28 +0800 +Subject: net: stmmac: dwmac-loongson: Set correct {tx,rx}_fifo_size + +From: Huacai Chen + +[ Upstream commit 8dbf0c7556454b52af91bae305ca71500c31495c ] + +Now for dwmac-loongson {tx,rx}_fifo_size are uninitialised, which means +zero. This means dwmac-loongson doesn't support changing MTU because in +stmmac_change_mtu() it requires the fifo size be no less than MTU. Thus, +set the correct tx_fifo_size and rx_fifo_size for it (16KB multiplied by +queue counts). + +Here {tx,rx}_fifo_size is initialised with the initial value (also the +maximum value) of {tx,rx}_queues_to_use. So it will keep as 16KB if we +don't change the queue count, and will be larger than 16KB if we change +(decrease) the queue count. However stmmac_change_mtu() still work well +with current logic (MTU cannot be larger than 16KB for stmmac). + +Note: the Fixes tag picked here is the oldest commit and key commit of +the dwmac-loongson series "stmmac: Add Loongson platform support". + +Acked-by: Yanteng Si +Reviewed-by: Simon Horman +Signed-off-by: Chong Qiao +Signed-off-by: Huacai Chen +Link: https://patch.msgid.link/20250210134328.2755328-1-chenhuacai@loongson.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +index ab7c2750c1042..702ea5a00b56d 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +@@ -590,6 +590,9 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id + if (ret) + goto err_disable_device; + ++ plat->tx_fifo_size = SZ_16K * plat->tx_queues_to_use; ++ plat->rx_fifo_size = SZ_16K * plat->rx_queues_to_use; ++ + if (dev_of_node(&pdev->dev)) + ret = loongson_dwmac_dt_config(pdev, plat, &res); + else +-- +2.39.5 + diff --git a/queue-6.12/net-stmmac-dwmac-rk-validate-grf-and-peripheral-grf-.patch b/queue-6.12/net-stmmac-dwmac-rk-validate-grf-and-peripheral-grf-.patch new file mode 100644 index 0000000000..90d80af709 --- /dev/null +++ b/queue-6.12/net-stmmac-dwmac-rk-validate-grf-and-peripheral-grf-.patch @@ -0,0 +1,91 @@ +From 33e91f950c3e04bef5db3e4dbf7bd7087446297b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 21:37:14 +0000 +Subject: net: stmmac: dwmac-rk: Validate GRF and peripheral GRF during probe + +From: Jonas Karlman + +[ Upstream commit 247e84f66a3d1946193d739fec5dc3d69833fd00 ] + +All Rockchip GMAC variants typically write to GRF regs to control e.g. +interface mode, speed and MAC rx/tx delay. Newer SoCs such as RK3576 and +RK3588 use a mix of GRF and peripheral GRF regs. These syscon regmaps is +located with help of a rockchip,grf and rockchip,php-grf phandle. + +However, validating the rockchip,grf and rockchip,php-grf syscon regmap +is deferred until e.g. interface mode or speed is configured, inside the +individual SoC specific operations. + +Change to validate the rockchip,grf and rockchip,php-grf syscon regmap +at probe time to simplify all SoC specific operations. + +This should not introduce any backward compatibility issues as all +GMAC nodes have been added together with a rockchip,grf phandle (and +rockchip,php-grf where required) in their initial commit. + +Signed-off-by: Jonas Karlman +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250308213720.2517944-3-jonas@kwiboo.se +Reviewed-by: Sebastian Reichel +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/stmicro/stmmac/dwmac-rk.c | 21 +++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +index 50073bdade46e..8f90eae937741 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +@@ -33,6 +33,7 @@ struct rk_gmac_ops { + void (*set_clock_selection)(struct rk_priv_data *bsp_priv, bool input, + bool enable); + void (*integrated_phy_powerup)(struct rk_priv_data *bsp_priv); ++ bool php_grf_required; + bool regs_valid; + u32 regs[]; + }; +@@ -1263,6 +1264,7 @@ static const struct rk_gmac_ops rk3576_ops = { + .set_rgmii_speed = rk3576_set_gmac_speed, + .set_rmii_speed = rk3576_set_gmac_speed, + .set_clock_selection = rk3576_set_clock_selection, ++ .php_grf_required = true, + .regs_valid = true, + .regs = { + 0x2a220000, /* gmac0 */ +@@ -1410,6 +1412,7 @@ static const struct rk_gmac_ops rk3588_ops = { + .set_rgmii_speed = rk3588_set_gmac_speed, + .set_rmii_speed = rk3588_set_gmac_speed, + .set_clock_selection = rk3588_set_clock_selection, ++ .php_grf_required = true, + .regs_valid = true, + .regs = { + 0xfe1b0000, /* gmac0 */ +@@ -1830,8 +1833,22 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev, + + bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node, + "rockchip,grf"); +- bsp_priv->php_grf = syscon_regmap_lookup_by_phandle(dev->of_node, +- "rockchip,php-grf"); ++ if (IS_ERR(bsp_priv->grf)) { ++ dev_err_probe(dev, PTR_ERR(bsp_priv->grf), ++ "failed to lookup rockchip,grf\n"); ++ return ERR_CAST(bsp_priv->grf); ++ } ++ ++ if (ops->php_grf_required) { ++ bsp_priv->php_grf = ++ syscon_regmap_lookup_by_phandle(dev->of_node, ++ "rockchip,php-grf"); ++ if (IS_ERR(bsp_priv->php_grf)) { ++ dev_err_probe(dev, PTR_ERR(bsp_priv->php_grf), ++ "failed to lookup rockchip,php-grf\n"); ++ return ERR_CAST(bsp_priv->php_grf); ++ } ++ } + + if (plat->phy_node) { + bsp_priv->integrated_phy = of_property_read_bool(plat->phy_node, +-- +2.39.5 + diff --git a/queue-6.12/net-tn40xx-add-pci-id-of-the-aqr105-based-tehuti-tn4.patch b/queue-6.12/net-tn40xx-add-pci-id-of-the-aqr105-based-tehuti-tn4.patch new file mode 100644 index 0000000000..1dcd71b379 --- /dev/null +++ b/queue-6.12/net-tn40xx-add-pci-id-of-the-aqr105-based-tehuti-tn4.patch @@ -0,0 +1,43 @@ +From a494fe540dc05a9864ab3c626cba6fd8a3313216 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Mar 2025 11:45:58 +0100 +Subject: net: tn40xx: add pci-id of the aqr105-based Tehuti TN4010 cards + +From: Hans-Frieder Vogt + +[ Upstream commit 53377b5c2952097527b01ce2f1d9a9332f042f70 ] + +Add the PCI-ID of the AQR105-based Tehuti TN4010 cards to allow loading +of the tn40xx driver on these cards. Here, I chose the detailed definition +with the subvendor ID similar to the QT2025 cards with the PCI-ID +TEHUTI:0x4022, because there is a card with an AQ2104 hiding amongst the +AQR105 cards, and they all come with the same PCI-ID (TEHUTI:0x4025). But +the AQ2104 is currently not supported. + +Signed-off-by: Hans-Frieder Vogt +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250322-tn9510-v3a-v7-7-672a9a3d8628@gmx.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/tehuti/tn40.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/ethernet/tehuti/tn40.c b/drivers/net/ethernet/tehuti/tn40.c +index 259bdac24cf21..a6965258441c4 100644 +--- a/drivers/net/ethernet/tehuti/tn40.c ++++ b/drivers/net/ethernet/tehuti/tn40.c +@@ -1832,6 +1832,10 @@ static const struct pci_device_id tn40_id_table[] = { + PCI_VENDOR_ID_ASUSTEK, 0x8709) }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_TEHUTI, 0x4022, + PCI_VENDOR_ID_EDIMAX, 0x8103) }, ++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_TEHUTI, PCI_DEVICE_ID_TEHUTI_TN9510, ++ PCI_VENDOR_ID_TEHUTI, 0x3015) }, ++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_TEHUTI, PCI_DEVICE_ID_TEHUTI_TN9510, ++ PCI_VENDOR_ID_EDIMAX, 0x8102) }, + { } + }; + +-- +2.39.5 + diff --git a/queue-6.12/net-tn40xx-create-swnode-for-mdio-and-aqr105-phy-and.patch b/queue-6.12/net-tn40xx-create-swnode-for-mdio-and-aqr105-phy-and.patch new file mode 100644 index 0000000000..b2e1c5d7d2 --- /dev/null +++ b/queue-6.12/net-tn40xx-create-swnode-for-mdio-and-aqr105-phy-and.patch @@ -0,0 +1,240 @@ +From 0a89babea10188330a8255dfffe0c56eb01d6e60 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Mar 2025 11:45:56 +0100 +Subject: net: tn40xx: create swnode for mdio and aqr105 phy and add to mdiobus + +From: Hans-Frieder Vogt + +[ Upstream commit 25b6a6d29d4082f6ac231c056ac321a996eb55c9 ] + +In case of an AQR105-based device, create a software node for the mdio +function, with a child node for the Aquantia AQR105 PHY, providing a +firmware-name (and a bit more, which may be used for future checks) to +allow the PHY to load a MAC specific firmware from the file system. + +The name of the PHY software node follows the naming convention suggested +in the patch for the mdiobus_scan function (in the same patch series). + +Signed-off-by: Hans-Frieder Vogt +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250322-tn9510-v3a-v7-5-672a9a3d8628@gmx.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/tehuti/tn40.c | 5 +- + drivers/net/ethernet/tehuti/tn40.h | 33 ++++++++++ + drivers/net/ethernet/tehuti/tn40_mdio.c | 82 ++++++++++++++++++++++++- + 3 files changed, 117 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/tehuti/tn40.c b/drivers/net/ethernet/tehuti/tn40.c +index a6965258441c4..558b791a97edd 100644 +--- a/drivers/net/ethernet/tehuti/tn40.c ++++ b/drivers/net/ethernet/tehuti/tn40.c +@@ -1778,7 +1778,7 @@ static int tn40_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + ret = tn40_phy_register(priv); + if (ret) { + dev_err(&pdev->dev, "failed to set up PHY.\n"); +- goto err_free_irq; ++ goto err_cleanup_swnodes; + } + + ret = tn40_priv_init(priv); +@@ -1795,6 +1795,8 @@ static int tn40_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + return 0; + err_unregister_phydev: + tn40_phy_unregister(priv); ++err_cleanup_swnodes: ++ tn40_swnodes_cleanup(priv); + err_free_irq: + pci_free_irq_vectors(pdev); + err_unset_drvdata: +@@ -1816,6 +1818,7 @@ static void tn40_remove(struct pci_dev *pdev) + unregister_netdev(ndev); + + tn40_phy_unregister(priv); ++ tn40_swnodes_cleanup(priv); + pci_free_irq_vectors(priv->pdev); + pci_set_drvdata(pdev, NULL); + iounmap(priv->regs); +diff --git a/drivers/net/ethernet/tehuti/tn40.h b/drivers/net/ethernet/tehuti/tn40.h +index 490781fe51205..25da8686d4691 100644 +--- a/drivers/net/ethernet/tehuti/tn40.h ++++ b/drivers/net/ethernet/tehuti/tn40.h +@@ -4,10 +4,13 @@ + #ifndef _TN40_H_ + #define _TN40_H_ + ++#include + #include "tn40_regs.h" + + #define TN40_DRV_NAME "tn40xx" + ++#define PCI_DEVICE_ID_TEHUTI_TN9510 0x4025 ++ + #define TN40_MDIO_SPEED_1MHZ (1) + #define TN40_MDIO_SPEED_6MHZ (6) + +@@ -102,10 +105,39 @@ struct tn40_txdb { + int size; /* Number of elements in the db */ + }; + ++#define NODE_PROP(_NAME, _PROP) ( \ ++ (const struct software_node) { \ ++ .name = _NAME, \ ++ .properties = _PROP, \ ++ }) ++ ++#define NODE_PAR_PROP(_NAME, _PAR, _PROP) ( \ ++ (const struct software_node) { \ ++ .name = _NAME, \ ++ .parent = _PAR, \ ++ .properties = _PROP, \ ++ }) ++ ++enum tn40_swnodes { ++ SWNODE_MDIO, ++ SWNODE_PHY, ++ SWNODE_MAX ++}; ++ ++struct tn40_nodes { ++ char phy_name[32]; ++ char mdio_name[32]; ++ struct property_entry phy_props[3]; ++ struct software_node swnodes[SWNODE_MAX]; ++ const struct software_node *group[SWNODE_MAX + 1]; ++}; ++ + struct tn40_priv { + struct net_device *ndev; + struct pci_dev *pdev; + ++ struct tn40_nodes nodes; ++ + struct napi_struct napi; + /* RX FIFOs: 1 for data (full) descs, and 2 for free descs */ + struct tn40_rxd_fifo rxd_fifo0; +@@ -225,6 +257,7 @@ static inline void tn40_write_reg(struct tn40_priv *priv, u32 reg, u32 val) + + int tn40_set_link_speed(struct tn40_priv *priv, u32 speed); + ++void tn40_swnodes_cleanup(struct tn40_priv *priv); + int tn40_mdiobus_init(struct tn40_priv *priv); + + int tn40_phy_register(struct tn40_priv *priv); +diff --git a/drivers/net/ethernet/tehuti/tn40_mdio.c b/drivers/net/ethernet/tehuti/tn40_mdio.c +index af18615d64a8a..5bb0cbc87d064 100644 +--- a/drivers/net/ethernet/tehuti/tn40_mdio.c ++++ b/drivers/net/ethernet/tehuti/tn40_mdio.c +@@ -14,6 +14,8 @@ + (FIELD_PREP(TN40_MDIO_PRTAD_MASK, (port)))) + #define TN40_MDIO_CMD_READ BIT(15) + ++#define AQR105_FIRMWARE "tehuti/aqr105-tn40xx.cld" ++ + static void tn40_mdio_set_speed(struct tn40_priv *priv, u32 speed) + { + void __iomem *regs = priv->regs; +@@ -111,6 +113,56 @@ static int tn40_mdio_write_c45(struct mii_bus *mii_bus, int addr, int devnum, + return tn40_mdio_write(mii_bus->priv, addr, devnum, regnum, val); + } + ++/* registers an mdio node and an aqr105 PHY at address 1 ++ * tn40_mdio-%id { ++ * ethernet-phy@1 { ++ * compatible = "ethernet-phy-id03a1.b4a3"; ++ * reg = <1>; ++ * firmware-name = AQR105_FIRMWARE; ++ * }; ++ * }; ++ */ ++static int tn40_swnodes_register(struct tn40_priv *priv) ++{ ++ struct tn40_nodes *nodes = &priv->nodes; ++ struct pci_dev *pdev = priv->pdev; ++ struct software_node *swnodes; ++ u32 id; ++ ++ id = pci_dev_id(pdev); ++ ++ snprintf(nodes->phy_name, sizeof(nodes->phy_name), "ethernet-phy@1"); ++ snprintf(nodes->mdio_name, sizeof(nodes->mdio_name), "tn40_mdio-%x", ++ id); ++ ++ swnodes = nodes->swnodes; ++ ++ swnodes[SWNODE_MDIO] = NODE_PROP(nodes->mdio_name, NULL); ++ ++ nodes->phy_props[0] = PROPERTY_ENTRY_STRING("compatible", ++ "ethernet-phy-id03a1.b4a3"); ++ nodes->phy_props[1] = PROPERTY_ENTRY_U32("reg", 1); ++ nodes->phy_props[2] = PROPERTY_ENTRY_STRING("firmware-name", ++ AQR105_FIRMWARE); ++ swnodes[SWNODE_PHY] = NODE_PAR_PROP(nodes->phy_name, ++ &swnodes[SWNODE_MDIO], ++ nodes->phy_props); ++ ++ nodes->group[SWNODE_PHY] = &swnodes[SWNODE_PHY]; ++ nodes->group[SWNODE_MDIO] = &swnodes[SWNODE_MDIO]; ++ return software_node_register_node_group(nodes->group); ++} ++ ++void tn40_swnodes_cleanup(struct tn40_priv *priv) ++{ ++ /* cleanup of swnodes is only needed for AQR105-based cards */ ++ if (priv->pdev->device == PCI_DEVICE_ID_TEHUTI_TN9510) { ++ fwnode_handle_put(dev_fwnode(&priv->mdio->dev)); ++ device_remove_software_node(&priv->mdio->dev); ++ software_node_unregister_node_group(priv->nodes.group); ++ } ++} ++ + int tn40_mdiobus_init(struct tn40_priv *priv) + { + struct pci_dev *pdev = priv->pdev; +@@ -129,14 +181,40 @@ int tn40_mdiobus_init(struct tn40_priv *priv) + + bus->read_c45 = tn40_mdio_read_c45; + bus->write_c45 = tn40_mdio_write_c45; ++ priv->mdio = bus; ++ ++ /* provide swnodes for AQR105-based cards only */ ++ if (pdev->device == PCI_DEVICE_ID_TEHUTI_TN9510) { ++ ret = tn40_swnodes_register(priv); ++ if (ret) { ++ pr_err("swnodes failed\n"); ++ return ret; ++ } ++ ++ ret = device_add_software_node(&bus->dev, ++ priv->nodes.group[SWNODE_MDIO]); ++ if (ret) { ++ dev_err(&pdev->dev, ++ "device_add_software_node failed: %d\n", ret); ++ goto err_swnodes_unregister; ++ } ++ } + + ret = devm_mdiobus_register(&pdev->dev, bus); + if (ret) { + dev_err(&pdev->dev, "failed to register mdiobus %d %u %u\n", + ret, bus->state, MDIOBUS_UNREGISTERED); +- return ret; ++ goto err_swnodes_cleanup; + } + tn40_mdio_set_speed(priv, TN40_MDIO_SPEED_6MHZ); +- priv->mdio = bus; + return 0; ++ ++err_swnodes_unregister: ++ software_node_unregister_node_group(priv->nodes.group); ++ return ret; ++err_swnodes_cleanup: ++ tn40_swnodes_cleanup(priv); ++ return ret; + } ++ ++MODULE_FIRMWARE(AQR105_FIRMWARE); +-- +2.39.5 + diff --git a/queue-6.12/net-xgene-v2-remove-incorrect-acpi_ptr-annotation.patch b/queue-6.12/net-xgene-v2-remove-incorrect-acpi_ptr-annotation.patch new file mode 100644 index 0000000000..ea06df4dfa --- /dev/null +++ b/queue-6.12/net-xgene-v2-remove-incorrect-acpi_ptr-annotation.patch @@ -0,0 +1,47 @@ +From 65498a41bb5038b13107f46a883d66d0b2a3702d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 17:33:33 +0100 +Subject: net: xgene-v2: remove incorrect ACPI_PTR annotation + +From: Arnd Bergmann + +[ Upstream commit 01358e8fe922f716c05d7864ac2213b2440026e7 ] + +Building with W=1 shows a warning about xge_acpi_match being unused when +CONFIG_ACPI is disabled: + +drivers/net/ethernet/apm/xgene-v2/main.c:723:36: error: unused variable 'xge_acpi_match' [-Werror,-Wunused-const-variable] + +Signed-off-by: Arnd Bergmann +Link: https://patch.msgid.link/20250225163341.4168238-2-arnd@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/apm/xgene-v2/main.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c b/drivers/net/ethernet/apm/xgene-v2/main.c +index 9e90c23814910..68335935cea77 100644 +--- a/drivers/net/ethernet/apm/xgene-v2/main.c ++++ b/drivers/net/ethernet/apm/xgene-v2/main.c +@@ -9,8 +9,6 @@ + + #include "main.h" + +-static const struct acpi_device_id xge_acpi_match[]; +- + static int xge_get_resources(struct xge_pdata *pdata) + { + struct platform_device *pdev; +@@ -731,7 +729,7 @@ MODULE_DEVICE_TABLE(acpi, xge_acpi_match); + static struct platform_driver xge_driver = { + .driver = { + .name = "xgene-enet-v2", +- .acpi_match_table = ACPI_PTR(xge_acpi_match), ++ .acpi_match_table = xge_acpi_match, + }, + .probe = xge_probe, + .remove_new = xge_remove, +-- +2.39.5 + diff --git a/queue-6.12/netfilter-conntrack-bound-nf_conntrack-sysctl-writes.patch b/queue-6.12/netfilter-conntrack-bound-nf_conntrack-sysctl-writes.patch new file mode 100644 index 0000000000..cc1fca50ac --- /dev/null +++ b/queue-6.12/netfilter-conntrack-bound-nf_conntrack-sysctl-writes.patch @@ -0,0 +1,85 @@ +From 0c5014e4005aae48d6225bd73f0c6f083ccfcf4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 18:06:30 +0100 +Subject: netfilter: conntrack: Bound nf_conntrack sysctl writes + +From: Nicolas Bouchinet + +[ Upstream commit 8b6861390ffee6b8ed78b9395e3776c16fec6579 ] + +nf_conntrack_max and nf_conntrack_expect_max sysctls were authorized to +be written any negative value, which would then be stored in the +unsigned int variables nf_conntrack_max and nf_ct_expect_max variables. + +While the do_proc_dointvec_conv function is supposed to limit writing +handled by proc_dointvec proc_handler to INT_MAX. Such a negative value +being written in an unsigned int leads to a very high value, exceeding +this limit. + +Moreover, the nf_conntrack_expect_max sysctl documentation specifies the +minimum value is 1. + +The proc_handlers have thus been updated to proc_dointvec_minmax in +order to specify the following write bounds : + +* Bound nf_conntrack_max sysctl writings between SYSCTL_ZERO + and SYSCTL_INT_MAX. + +* Bound nf_conntrack_expect_max sysctl writings between SYSCTL_ONE + and SYSCTL_INT_MAX as defined in the sysctl documentation. + +With this patch applied, sysctl writes outside the defined in the bound +will thus lead to a write error : + +``` +sysctl -w net.netfilter.nf_conntrack_expect_max=-1 +sysctl: setting key "net.netfilter.nf_conntrack_expect_max": Invalid argument +``` + +Signed-off-by: Nicolas Bouchinet +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_standalone.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c +index 7d4f0fa8b609d..3ea60ff7a6a49 100644 +--- a/net/netfilter/nf_conntrack_standalone.c ++++ b/net/netfilter/nf_conntrack_standalone.c +@@ -619,7 +619,9 @@ static struct ctl_table nf_ct_sysctl_table[] = { + .data = &nf_conntrack_max, + .maxlen = sizeof(int), + .mode = 0644, +- .proc_handler = proc_dointvec, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = SYSCTL_ZERO, ++ .extra2 = SYSCTL_INT_MAX, + }, + [NF_SYSCTL_CT_COUNT] = { + .procname = "nf_conntrack_count", +@@ -655,7 +657,9 @@ static struct ctl_table nf_ct_sysctl_table[] = { + .data = &nf_ct_expect_max, + .maxlen = sizeof(int), + .mode = 0644, +- .proc_handler = proc_dointvec, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = SYSCTL_ONE, ++ .extra2 = SYSCTL_INT_MAX, + }, + [NF_SYSCTL_CT_ACCT] = { + .procname = "nf_conntrack_acct", +@@ -948,7 +952,9 @@ static struct ctl_table nf_ct_netfilter_table[] = { + .data = &nf_conntrack_max, + .maxlen = sizeof(int), + .mode = 0644, +- .proc_handler = proc_dointvec, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = SYSCTL_ZERO, ++ .extra2 = SYSCTL_INT_MAX, + }, + }; + +-- +2.39.5 + diff --git a/queue-6.12/nfs-don-t-allow-waiting-for-exiting-tasks.patch b/queue-6.12/nfs-don-t-allow-waiting-for-exiting-tasks.patch new file mode 100644 index 0000000000..4ded87342f --- /dev/null +++ b/queue-6.12/nfs-don-t-allow-waiting-for-exiting-tasks.patch @@ -0,0 +1,108 @@ +From b6612f215bae8602e540e2575fb365b2b6e167b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Mar 2025 13:19:18 -0400 +Subject: NFS: Don't allow waiting for exiting tasks + +From: Trond Myklebust + +[ Upstream commit 8d3ca331026a7f9700d3747eed59a67b8f828cdc ] + +Once a task calls exit_signals() it can no longer be signalled. So do +not allow it to do killable waits. + +Reviewed-by: Jeff Layton +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/inode.c | 2 ++ + fs/nfs/internal.h | 5 +++++ + fs/nfs/nfs3proc.c | 2 +- + fs/nfs/nfs4proc.c | 9 +++++++-- + 4 files changed, 15 insertions(+), 3 deletions(-) + +diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c +index 596f351701372..330273cf94531 100644 +--- a/fs/nfs/inode.c ++++ b/fs/nfs/inode.c +@@ -74,6 +74,8 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr) + + int nfs_wait_bit_killable(struct wait_bit_key *key, int mode) + { ++ if (unlikely(nfs_current_task_exiting())) ++ return -EINTR; + schedule(); + if (signal_pending_state(mode, current)) + return -ERESTARTSYS; +diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h +index 8b568a514fd1c..1be4be3d4a2b6 100644 +--- a/fs/nfs/internal.h ++++ b/fs/nfs/internal.h +@@ -901,6 +901,11 @@ static inline u32 nfs_stateid_hash(const nfs4_stateid *stateid) + NFS4_STATEID_OTHER_SIZE); + } + ++static inline bool nfs_current_task_exiting(void) ++{ ++ return (current->flags & PF_EXITING) != 0; ++} ++ + static inline bool nfs_error_is_fatal(int err) + { + switch (err) { +diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c +index 1566163c6d85b..88b0fb343ae04 100644 +--- a/fs/nfs/nfs3proc.c ++++ b/fs/nfs/nfs3proc.c +@@ -39,7 +39,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) + __set_current_state(TASK_KILLABLE|TASK_FREEZABLE_UNSAFE); + schedule_timeout(NFS_JUKEBOX_RETRY_TIME); + res = -ERESTARTSYS; +- } while (!fatal_signal_pending(current)); ++ } while (!fatal_signal_pending(current) && !nfs_current_task_exiting()); + return res; + } + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index ca01f79c82e4a..11f2b5cb3b06b 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -434,6 +434,8 @@ static int nfs4_delay_killable(long *timeout) + { + might_sleep(); + ++ if (unlikely(nfs_current_task_exiting())) ++ return -EINTR; + __set_current_state(TASK_KILLABLE|TASK_FREEZABLE_UNSAFE); + schedule_timeout(nfs4_update_delay(timeout)); + if (!__fatal_signal_pending(current)) +@@ -445,6 +447,8 @@ static int nfs4_delay_interruptible(long *timeout) + { + might_sleep(); + ++ if (unlikely(nfs_current_task_exiting())) ++ return -EINTR; + __set_current_state(TASK_INTERRUPTIBLE|TASK_FREEZABLE_UNSAFE); + schedule_timeout(nfs4_update_delay(timeout)); + if (!signal_pending(current)) +@@ -1765,7 +1769,8 @@ static void nfs_set_open_stateid_locked(struct nfs4_state *state, + rcu_read_unlock(); + trace_nfs4_open_stateid_update_wait(state->inode, stateid, 0); + +- if (!fatal_signal_pending(current)) { ++ if (!fatal_signal_pending(current) && ++ !nfs_current_task_exiting()) { + if (schedule_timeout(5*HZ) == 0) + status = -EAGAIN; + else +@@ -3569,7 +3574,7 @@ static bool nfs4_refresh_open_old_stateid(nfs4_stateid *dst, + write_sequnlock(&state->seqlock); + trace_nfs4_close_stateid_update_wait(state->inode, dst, 0); + +- if (fatal_signal_pending(current)) ++ if (fatal_signal_pending(current) || nfs_current_task_exiting()) + status = -EINTR; + else + if (schedule_timeout(5*HZ) != 0) +-- +2.39.5 + diff --git a/queue-6.12/nfsv4-check-for-delegation-validity-in-nfs_start_del.patch b/queue-6.12/nfsv4-check-for-delegation-validity-in-nfs_start_del.patch new file mode 100644 index 0000000000..eeb84fccdf --- /dev/null +++ b/queue-6.12/nfsv4-check-for-delegation-validity-in-nfs_start_del.patch @@ -0,0 +1,36 @@ +From 52edd4862750fe1b16575e21605fa2819f2e066e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Mar 2025 19:20:53 -0400 +Subject: NFSv4: Check for delegation validity in + nfs_start_delegation_return_locked() + +From: Trond Myklebust + +[ Upstream commit 9e8f324bd44c1fe026b582b75213de4eccfa1163 ] + +Check that the delegation is still attached after taking the spin lock +in nfs_start_delegation_return_locked(). + +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/delegation.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c +index 325ba0663a6de..8bdbc4dca89ca 100644 +--- a/fs/nfs/delegation.c ++++ b/fs/nfs/delegation.c +@@ -307,7 +307,8 @@ nfs_start_delegation_return_locked(struct nfs_inode *nfsi) + if (delegation == NULL) + goto out; + spin_lock(&delegation->lock); +- if (!test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) { ++ if (delegation->inode && ++ !test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) { + clear_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags); + /* Refcount matched in nfs_end_delegation_return() */ + ret = nfs_get_delegation(delegation); +-- +2.39.5 + diff --git a/queue-6.12/nfsv4-treat-enetunreach-errors-as-fatal-for-state-re.patch b/queue-6.12/nfsv4-treat-enetunreach-errors-as-fatal-for-state-re.patch new file mode 100644 index 0000000000..deef76f45e --- /dev/null +++ b/queue-6.12/nfsv4-treat-enetunreach-errors-as-fatal-for-state-re.patch @@ -0,0 +1,46 @@ +From bb59afa435f57c5539c799619b62012a6c99cd69 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 20:35:33 -0400 +Subject: NFSv4: Treat ENETUNREACH errors as fatal for state recovery + +From: Trond Myklebust + +[ Upstream commit 0af5fb5ed3d2fd9e110c6112271f022b744a849a ] + +If a containerised process is killed and causes an ENETUNREACH or +ENETDOWN error to be propagated to the state manager, then mark the +nfs_client as being dead so that we don't loop in functions that are +expecting recovery to succeed. + +Reviewed-by: Jeff Layton +Reviewed-by: Benjamin Coddington +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs4state.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c +index dafd61186557f..397a86011878f 100644 +--- a/fs/nfs/nfs4state.c ++++ b/fs/nfs/nfs4state.c +@@ -2740,7 +2740,15 @@ static void nfs4_state_manager(struct nfs_client *clp) + pr_warn_ratelimited("NFS: state manager%s%s failed on NFSv4 server %s" + " with error %d\n", section_sep, section, + clp->cl_hostname, -status); +- ssleep(1); ++ switch (status) { ++ case -ENETDOWN: ++ case -ENETUNREACH: ++ nfs_mark_client_ready(clp, -EIO); ++ break; ++ default: ++ ssleep(1); ++ break; ++ } + out_drain: + memalloc_nofs_restore(memflags); + nfs4_end_drain_session(clp); +-- +2.39.5 + diff --git a/queue-6.12/nvme-map-uring_cmd-data-even-if-address-is-0.patch b/queue-6.12/nvme-map-uring_cmd-data-even-if-address-is-0.patch new file mode 100644 index 0000000000..fb58d15d26 --- /dev/null +++ b/queue-6.12/nvme-map-uring_cmd-data-even-if-address-is-0.patch @@ -0,0 +1,48 @@ +From 507ae214217d2abf9346d8e9f5360bd0eb9635c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 14:39:13 -0800 +Subject: nvme: map uring_cmd data even if address is 0 + +From: Xinyu Zhang + +[ Upstream commit 99fde895ff56ac2241e7b7b4566731d72f2fdaa7 ] + +When using kernel registered bvec fixed buffers, the "address" is +actually the offset into the bvec rather than userspace address. +Therefore it can be 0. + +We can skip checking whether the address is NULL before mapping +uring_cmd data. Bad userspace address will be handled properly later when +the user buffer is imported. + +With this patch, we will be able to use the kernel registered bvec fixed +buffers in io_uring NVMe passthru with ublk zero-copy support. + +Reviewed-by: Caleb Sander Mateos +Reviewed-by: Jens Axboe +Reviewed-by: Ming Lei +Signed-off-by: Xinyu Zhang +Signed-off-by: Keith Busch +Link: https://lore.kernel.org/r/20250227223916.143006-4-kbusch@meta.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/nvme/host/ioctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c +index a1b3c538a4bd2..d128e6cf6f1b0 100644 +--- a/drivers/nvme/host/ioctl.c ++++ b/drivers/nvme/host/ioctl.c +@@ -515,7 +515,7 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns, + return PTR_ERR(req); + req->timeout = d.timeout_ms ? msecs_to_jiffies(d.timeout_ms) : 0; + +- if (d.addr && d.data_len) { ++ if (d.data_len) { + ret = nvme_map_user_request(req, d.addr, + d.data_len, nvme_to_user_ptr(d.metadata), + d.metadata_len, 0, ioucmd, vec); +-- +2.39.5 + diff --git a/queue-6.12/nvme-pci-add-quirks-for-device-126f-1001.patch b/queue-6.12/nvme-pci-add-quirks-for-device-126f-1001.patch new file mode 100644 index 0000000000..a01fe0a4a2 --- /dev/null +++ b/queue-6.12/nvme-pci-add-quirks-for-device-126f-1001.patch @@ -0,0 +1,49 @@ +From a7cfc4b882c8747a783139b17c7c4c40b0d22386 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Apr 2025 20:17:25 +0800 +Subject: nvme-pci: add quirks for device 126f:1001 + +From: Wentao Guan + +[ Upstream commit 5b960f92ac3e5b4d7f60a506a6b6735eead1da01 ] + +This commit adds NVME_QUIRK_NO_DEEPEST_PS and NVME_QUIRK_BOGUS_NID for +device [126f:1001]. + +It is similar to commit e89086c43f05 ("drivers/nvme: Add quirks for +device 126f:2262") + +Diff is according the dmesg, use NVME_QUIRK_IGNORE_DEV_SUBNQN. + +dmesg | grep -i nvme0: + nvme nvme0: pci function 0000:01:00.0 + nvme nvme0: missing or invalid SUBNQN field. + nvme nvme0: 12/0/0 default/read/poll queues + +Link:https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e89086c43f0500bc7c4ce225495b73b8ce234c1f +Signed-off-by: Wentao Guan +Signed-off-by: WangYuli +Reviewed-by: Sagi Grimberg +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + drivers/nvme/host/pci.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index 265b3608ae26e..f2c06bb96c8d2 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -3587,6 +3587,9 @@ static const struct pci_device_id nvme_id_table[] = { + .driver_data = NVME_QUIRK_BOGUS_NID, }, + { PCI_DEVICE(0x1217, 0x8760), /* O2 Micro 64GB Steam Deck */ + .driver_data = NVME_QUIRK_DMAPOOL_ALIGN_512, }, ++ { PCI_DEVICE(0x126f, 0x1001), /* Silicon Motion generic */ ++ .driver_data = NVME_QUIRK_NO_DEEPEST_PS | ++ NVME_QUIRK_IGNORE_DEV_SUBNQN, }, + { PCI_DEVICE(0x126f, 0x2262), /* Silicon Motion generic */ + .driver_data = NVME_QUIRK_NO_DEEPEST_PS | + NVME_QUIRK_BOGUS_NID, }, +-- +2.39.5 + diff --git a/queue-6.12/nvme-pci-add-quirks-for-wdc-blue-sn550-15b7-5009.patch b/queue-6.12/nvme-pci-add-quirks-for-wdc-blue-sn550-15b7-5009.patch new file mode 100644 index 0000000000..fc87f5deca --- /dev/null +++ b/queue-6.12/nvme-pci-add-quirks-for-wdc-blue-sn550-15b7-5009.patch @@ -0,0 +1,87 @@ +From ca623d56a62ec6607d8358b00ad2b1c6f1629d06 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Apr 2025 10:40:10 +0800 +Subject: nvme-pci: add quirks for WDC Blue SN550 15b7:5009 + +From: Wentao Guan + +[ Upstream commit ab35ad950d439ec3409509835d229b3d93d3c7f9 ] + +Add two quirks for the WDC Blue SN550 (PCI ID 15b7:5009) based on user +reports and hardware analysis: + + - NVME_QUIRK_NO_DEEPEST_PS: + liaozw talked to me the problem and solved with + nvme_core.default_ps_max_latency_us=0, so add the quirk. + I also found some reports in the following link. + + - NVME_QUIRK_BROKEN_MSI: + after get the lspci from Jack Rio. + I think that the disk also have NVME_QUIRK_BROKEN_MSI. + described in commit d5887dc6b6c0 ("nvme-pci: Add quirk for broken MSIs") + as sean said in link which match the MSI 1/32 and MSI-X 17. + +Log: +lspci -nn | grep -i memory +03:00.0 Non-Volatile memory controller [0108]: Sandisk Corp SanDisk Ultra 3D / WD PC SN530, IX SN530, Blue SN550 NVMe SSD (DRAM-less) [15b7:5009] (rev 01) +lspci -v -d 15b7:5009 +03:00.0 Non-Volatile memory controller: Sandisk Corp SanDisk Ultra 3D / WD PC SN530, IX SN530, Blue SN550 NVMe SSD (DRAM-less) (rev 01) (prog-if 02 [NVM Express]) + Subsystem: Sandisk Corp WD Blue SN550 NVMe SSD + Flags: bus master, fast devsel, latency 0, IRQ 35, IOMMU group 10 + Memory at fe800000 (64-bit, non-prefetchable) [size=16K] + Memory at fe804000 (64-bit, non-prefetchable) [size=256] + Capabilities: [80] Power Management version 3 + Capabilities: [90] MSI: Enable- Count=1/32 Maskable- 64bit+ + Capabilities: [b0] MSI-X: Enable+ Count=17 Masked- + Capabilities: [c0] Express Endpoint, MSI 00 + Capabilities: [100] Advanced Error Reporting + Capabilities: [150] Device Serial Number 00-00-00-00-00-00-00-00 + Capabilities: [1b8] Latency Tolerance Reporting + Capabilities: [300] Secondary PCI Express + Capabilities: [900] L1 PM Substates + Kernel driver in use: nvme +dmesg | grep nvme +[ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-6.12.20-amd64-desktop-rolling root=UUID= ro splash quiet nvme_core.default_ps_max_latency_us=0 DEEPIN_GFXMODE= +[ 0.059301] Kernel command line: BOOT_IMAGE=/vmlinuz-6.12.20-amd64-desktop-rolling root=UUID= ro splash quiet nvme_core.default_ps_max_latency_us=0 DEEPIN_GFXMODE= +[ 0.542430] nvme nvme0: pci function 0000:03:00.0 +[ 0.560426] nvme nvme0: allocated 32 MiB host memory buffer. +[ 0.562491] nvme nvme0: 16/0/0 default/read/poll queues +[ 0.567764] nvme0n1: p1 p2 p3 p4 p5 p6 p7 p8 p9 +[ 6.388726] EXT4-fs (nvme0n1p7): mounted filesystem ro with ordered data mode. Quota mode: none. +[ 6.893421] EXT4-fs (nvme0n1p7): re-mounted r/w. Quota mode: none. +[ 7.125419] Adding 16777212k swap on /dev/nvme0n1p8. Priority:-2 extents:1 across:16777212k SS +[ 7.157588] EXT4-fs (nvme0n1p6): mounted filesystem r/w with ordered data mode. Quota mode: none. +[ 7.165021] EXT4-fs (nvme0n1p9): mounted filesystem r/w with ordered data mode. Quota mode: none. +[ 8.036932] nvme nvme0: using unchecked data buffer +[ 8.096023] block nvme0n1: No UUID available providing old NGUID + +Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d5887dc6b6c054d0da3cd053afc15b7be1f45ff6 +Link: https://lore.kernel.org/all/20240422162822.3539156-1-sean.anderson@linux.dev/ +Reported-by: liaozw +Closes: https://bbs.deepin.org.cn/post/286300 +Reported-by: rugk +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=208123 +Signed-off-by: Wentao Guan +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + drivers/nvme/host/pci.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index f2c06bb96c8d2..cd8a10f6accff 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -3613,6 +3613,9 @@ static const struct pci_device_id nvme_id_table[] = { + NVME_QUIRK_IGNORE_DEV_SUBNQN, }, + { PCI_DEVICE(0x15b7, 0x5008), /* Sandisk SN530 */ + .driver_data = NVME_QUIRK_BROKEN_MSI }, ++ { PCI_DEVICE(0x15b7, 0x5009), /* Sandisk SN550 */ ++ .driver_data = NVME_QUIRK_BROKEN_MSI | ++ NVME_QUIRK_NO_DEEPEST_PS }, + { PCI_DEVICE(0x1987, 0x5012), /* Phison E12 */ + .driver_data = NVME_QUIRK_BOGUS_NID, }, + { PCI_DEVICE(0x1987, 0x5016), /* Phison E16 */ +-- +2.39.5 + diff --git a/queue-6.12/nvmem-core-fix-bit-offsets-of-more-than-one-byte.patch b/queue-6.12/nvmem-core-fix-bit-offsets-of-more-than-one-byte.patch new file mode 100644 index 0000000000..87cdb0ccf1 --- /dev/null +++ b/queue-6.12/nvmem-core-fix-bit-offsets-of-more-than-one-byte.patch @@ -0,0 +1,76 @@ +From a3f1d24e0fc73ca4bc699723dcaa656db1b12190 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Apr 2025 12:22:46 +0100 +Subject: nvmem: core: fix bit offsets of more than one byte + +From: Dmitry Baryshkov + +[ Upstream commit 7a06ef75107799675ea6e4d73b9df37e18e352a8 ] + +If the NVMEM specifies a stride to access data, reading particular cell +might require bit offset that is bigger than one byte. Rework NVMEM core +code to support bit offsets of more than 8 bits. + +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20250411112251.68002-9-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/nvmem/core.c | 24 +++++++++++++++++------- + 1 file changed, 17 insertions(+), 7 deletions(-) + +diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c +index d00a3b015635c..8af2a569c23aa 100644 +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -824,7 +824,9 @@ static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_nod + if (addr && len == (2 * sizeof(u32))) { + info.bit_offset = be32_to_cpup(addr++); + info.nbits = be32_to_cpup(addr); +- if (info.bit_offset >= BITS_PER_BYTE || info.nbits < 1) { ++ if (info.bit_offset >= BITS_PER_BYTE * info.bytes || ++ info.nbits < 1 || ++ info.bit_offset + info.nbits > BITS_PER_BYTE * info.bytes) { + dev_err(dev, "nvmem: invalid bits on %pOF\n", child); + of_node_put(child); + return -EINVAL; +@@ -1617,21 +1619,29 @@ EXPORT_SYMBOL_GPL(nvmem_cell_put); + static void nvmem_shift_read_buffer_in_place(struct nvmem_cell_entry *cell, void *buf) + { + u8 *p, *b; +- int i, extra, bit_offset = cell->bit_offset; ++ int i, extra, bytes_offset; ++ int bit_offset = cell->bit_offset; + + p = b = buf; +- if (bit_offset) { ++ ++ bytes_offset = bit_offset / BITS_PER_BYTE; ++ b += bytes_offset; ++ bit_offset %= BITS_PER_BYTE; ++ ++ if (bit_offset % BITS_PER_BYTE) { + /* First shift */ +- *b++ >>= bit_offset; ++ *p = *b++ >> bit_offset; + + /* setup rest of the bytes if any */ + for (i = 1; i < cell->bytes; i++) { + /* Get bits from next byte and shift them towards msb */ +- *p |= *b << (BITS_PER_BYTE - bit_offset); ++ *p++ |= *b << (BITS_PER_BYTE - bit_offset); + +- p = b; +- *b++ >>= bit_offset; ++ *p = *b++ >> bit_offset; + } ++ } else if (p != b) { ++ memmove(p, b, cell->bytes - bytes_offset); ++ p += cell->bytes - 1; + } else { + /* point to the msb */ + p += cell->bytes - 1; +-- +2.39.5 + diff --git a/queue-6.12/nvmem-core-update-raw_len-if-the-bit-reading-is-requ.patch b/queue-6.12/nvmem-core-update-raw_len-if-the-bit-reading-is-requ.patch new file mode 100644 index 0000000000..701261f893 --- /dev/null +++ b/queue-6.12/nvmem-core-update-raw_len-if-the-bit-reading-is-requ.patch @@ -0,0 +1,42 @@ +From 28a7b109d67c2871d7a96136e86ce99b58900231 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Apr 2025 12:22:48 +0100 +Subject: nvmem: core: update raw_len if the bit reading is required + +From: Dmitry Baryshkov + +[ Upstream commit 6786484223d5705bf7f919c1e5055d478ebeec32 ] + +If NVMEM cell uses bit offset or specifies bit truncation, update +raw_len manually (following the cell->bytes update), ensuring that the +NVMEM access is still word-aligned. + +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20250411112251.68002-11-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/nvmem/core.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c +index 3671d156c7c33..d1869e6de3844 100644 +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -581,9 +581,11 @@ static int nvmem_cell_info_to_nvmem_cell_entry_nodup(struct nvmem_device *nvmem, + cell->nbits = info->nbits; + cell->np = info->np; + +- if (cell->nbits) ++ if (cell->nbits) { + cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset, + BITS_PER_BYTE); ++ cell->raw_len = ALIGN(cell->bytes, nvmem->word_size); ++ } + + if (!IS_ALIGNED(cell->offset, nvmem->stride)) { + dev_err(&nvmem->dev, +-- +2.39.5 + diff --git a/queue-6.12/nvmem-core-verify-cell-s-raw_len.patch b/queue-6.12/nvmem-core-verify-cell-s-raw_len.patch new file mode 100644 index 0000000000..5d84984a7e --- /dev/null +++ b/queue-6.12/nvmem-core-verify-cell-s-raw_len.patch @@ -0,0 +1,48 @@ +From 5af84817c963c39301177eb04b735c42a2e8b54e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Apr 2025 12:22:47 +0100 +Subject: nvmem: core: verify cell's raw_len + +From: Dmitry Baryshkov + +[ Upstream commit 13bcd440f2ff38cd7e42a179c223d4b833158b33 ] + +Check that the NVMEM cell's raw_len is a aligned to word_size. Otherwise +Otherwise drivers might face incomplete read while accessing the last +part of the NVMEM cell. + +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20250411112251.68002-10-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/nvmem/core.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c +index 8af2a569c23aa..3671d156c7c33 100644 +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -592,6 +592,18 @@ static int nvmem_cell_info_to_nvmem_cell_entry_nodup(struct nvmem_device *nvmem, + return -EINVAL; + } + ++ if (!IS_ALIGNED(cell->raw_len, nvmem->word_size)) { ++ dev_err(&nvmem->dev, ++ "cell %s raw len %zd unaligned to nvmem word size %d\n", ++ cell->name ?: "", cell->raw_len, ++ nvmem->word_size); ++ ++ if (info->raw_len) ++ return -EINVAL; ++ ++ cell->raw_len = ALIGN(cell->raw_len, nvmem->word_size); ++ } ++ + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.12/nvmem-qfprom-switch-to-4-byte-aligned-reads.patch b/queue-6.12/nvmem-qfprom-switch-to-4-byte-aligned-reads.patch new file mode 100644 index 0000000000..0390db5542 --- /dev/null +++ b/queue-6.12/nvmem-qfprom-switch-to-4-byte-aligned-reads.patch @@ -0,0 +1,84 @@ +From c7837806df09de0bf933a7f4994b0f0fade1db89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Apr 2025 12:22:49 +0100 +Subject: nvmem: qfprom: switch to 4-byte aligned reads + +From: Dmitry Baryshkov + +[ Upstream commit 3566a737db87a9bf360c2fd36433c5149f805f2e ] + +All platforms since Snapdragon 8 Gen1 (SM8450) require using 4-byte +reads to access QFPROM data. While older platforms were more than happy +with 1-byte reads, change the qfprom driver to use 4-byte reads for all +the platforms. Specify stride and word size of 4 bytes. To retain +compatibility with the existing DT and to simplify porting data from +vendor kernels, use fixup_dt_cell_info in order to bump alignment +requirements. + +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20250411112251.68002-12-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/nvmem/qfprom.c | 26 ++++++++++++++++++++------ + 1 file changed, 20 insertions(+), 6 deletions(-) + +diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c +index 116a39e804c70..a872c640b8c5a 100644 +--- a/drivers/nvmem/qfprom.c ++++ b/drivers/nvmem/qfprom.c +@@ -321,19 +321,32 @@ static int qfprom_reg_read(void *context, + unsigned int reg, void *_val, size_t bytes) + { + struct qfprom_priv *priv = context; +- u8 *val = _val; +- int i = 0, words = bytes; ++ u32 *val = _val; + void __iomem *base = priv->qfpcorrected; ++ int words = DIV_ROUND_UP(bytes, sizeof(u32)); ++ int i; + + if (read_raw_data && priv->qfpraw) + base = priv->qfpraw; + +- while (words--) +- *val++ = readb(base + reg + i++); ++ for (i = 0; i < words; i++) ++ *val++ = readl(base + reg + i * sizeof(u32)); + + return 0; + } + ++/* Align reads to word boundary */ ++static void qfprom_fixup_dt_cell_info(struct nvmem_device *nvmem, ++ struct nvmem_cell_info *cell) ++{ ++ unsigned int byte_offset = cell->offset % sizeof(u32); ++ ++ cell->bit_offset += byte_offset * BITS_PER_BYTE; ++ cell->offset -= byte_offset; ++ if (byte_offset && !cell->nbits) ++ cell->nbits = cell->bytes * BITS_PER_BYTE; ++} ++ + static void qfprom_runtime_disable(void *data) + { + pm_runtime_disable(data); +@@ -358,10 +371,11 @@ static int qfprom_probe(struct platform_device *pdev) + struct nvmem_config econfig = { + .name = "qfprom", + .add_legacy_fixed_of_cells = true, +- .stride = 1, +- .word_size = 1, ++ .stride = 4, ++ .word_size = 4, + .id = NVMEM_DEVID_AUTO, + .reg_read = qfprom_reg_read, ++ .fixup_dt_cell_info = qfprom_fixup_dt_cell_info, + }; + struct device *dev = &pdev->dev; + struct resource *res; +-- +2.39.5 + diff --git a/queue-6.12/nvmem-rockchip-otp-add-rk3576-variant-data.patch b/queue-6.12/nvmem-rockchip-otp-add-rk3576-variant-data.patch new file mode 100644 index 0000000000..f8ce23e1b3 --- /dev/null +++ b/queue-6.12/nvmem-rockchip-otp-add-rk3576-variant-data.patch @@ -0,0 +1,55 @@ +From a6797dddc00e97cb3718370730babe169e6d4e5c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Apr 2025 12:22:42 +0100 +Subject: nvmem: rockchip-otp: add rk3576 variant data + +From: Heiko Stuebner + +[ Upstream commit 50d75a13a9ce880a5ef07a4ccc63ba561cc2e69a ] + +The variant works very similar to the rk3588, just with a different +read-offset and size. + +Signed-off-by: Heiko Stuebner +Tested-by: Nicolas Frattaroli +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20250411112251.68002-5-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/nvmem/rockchip-otp.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c +index 3edfbfc2d7220..d88f12c532426 100644 +--- a/drivers/nvmem/rockchip-otp.c ++++ b/drivers/nvmem/rockchip-otp.c +@@ -274,6 +274,14 @@ static const struct rockchip_data px30_data = { + .reg_read = px30_otp_read, + }; + ++static const struct rockchip_data rk3576_data = { ++ .size = 0x100, ++ .read_offset = 0x700, ++ .clks = px30_otp_clocks, ++ .num_clks = ARRAY_SIZE(px30_otp_clocks), ++ .reg_read = rk3588_otp_read, ++}; ++ + static const char * const rk3588_otp_clocks[] = { + "otp", "apb_pclk", "phy", "arb", + }; +@@ -295,6 +303,10 @@ static const struct of_device_id rockchip_otp_match[] = { + .compatible = "rockchip,rk3308-otp", + .data = &px30_data, + }, ++ { ++ .compatible = "rockchip,rk3576-otp", ++ .data = &rk3576_data, ++ }, + { + .compatible = "rockchip,rk3588-otp", + .data = &rk3588_data, +-- +2.39.5 + diff --git a/queue-6.12/nvmem-rockchip-otp-move-read-offset-into-variant-dat.patch b/queue-6.12/nvmem-rockchip-otp-move-read-offset-into-variant-dat.patch new file mode 100644 index 0000000000..bd4133d0a7 --- /dev/null +++ b/queue-6.12/nvmem-rockchip-otp-move-read-offset-into-variant-dat.patch @@ -0,0 +1,67 @@ +From c0a5f0d237538ec3ea246f3b1cb2936911f2666c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Apr 2025 12:22:39 +0100 +Subject: nvmem: rockchip-otp: Move read-offset into variant-data + +From: Heiko Stuebner + +[ Upstream commit 6907e8093b3070d877ee607e5ceede60cfd08bde ] + +The RK3588 has an offset into the OTP area where the readable area begins +and automatically adds this to the start address. +Other variants are very much similar to rk3588, just with a different +offset, so move that value into variant-data. + +To match the size in bytes, store this value also in bytes and not in +number of blocks. + +Signed-off-by: Heiko Stuebner +Tested-by: Nicolas Frattaroli +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20250411112251.68002-2-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/nvmem/rockchip-otp.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c +index ebc3f0b24166b..3edfbfc2d7220 100644 +--- a/drivers/nvmem/rockchip-otp.c ++++ b/drivers/nvmem/rockchip-otp.c +@@ -59,7 +59,6 @@ + #define RK3588_OTPC_AUTO_EN 0x08 + #define RK3588_OTPC_INT_ST 0x84 + #define RK3588_OTPC_DOUT0 0x20 +-#define RK3588_NO_SECURE_OFFSET 0x300 + #define RK3588_NBYTES 4 + #define RK3588_BURST_NUM 1 + #define RK3588_BURST_SHIFT 8 +@@ -69,6 +68,7 @@ + + struct rockchip_data { + int size; ++ int read_offset; + const char * const *clks; + int num_clks; + nvmem_reg_read_t reg_read; +@@ -196,7 +196,7 @@ static int rk3588_otp_read(void *context, unsigned int offset, + addr_start = round_down(offset, RK3588_NBYTES) / RK3588_NBYTES; + addr_end = round_up(offset + bytes, RK3588_NBYTES) / RK3588_NBYTES; + addr_len = addr_end - addr_start; +- addr_start += RK3588_NO_SECURE_OFFSET; ++ addr_start += otp->data->read_offset / RK3588_NBYTES; + + buf = kzalloc(array_size(addr_len, RK3588_NBYTES), GFP_KERNEL); + if (!buf) +@@ -280,6 +280,7 @@ static const char * const rk3588_otp_clocks[] = { + + static const struct rockchip_data rk3588_data = { + .size = 0x400, ++ .read_offset = 0xc00, + .clks = rk3588_otp_clocks, + .num_clks = ARRAY_SIZE(rk3588_otp_clocks), + .reg_read = rk3588_otp_read, +-- +2.39.5 + diff --git a/queue-6.12/nvmet-tcp-don-t-restore-null-sk_state_change.patch b/queue-6.12/nvmet-tcp-don-t-restore-null-sk_state_change.patch new file mode 100644 index 0000000000..e88af5da49 --- /dev/null +++ b/queue-6.12/nvmet-tcp-don-t-restore-null-sk_state_change.patch @@ -0,0 +1,227 @@ +From 8ebbbdb53ca3a45ae211002a067662e6d79f226b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Apr 2025 16:06:21 +1000 +Subject: nvmet-tcp: don't restore null sk_state_change + +From: Alistair Francis + +[ Upstream commit 46d22b47df2741996af277a2838b95f130436c13 ] + +queue->state_change is set as part of nvmet_tcp_set_queue_sock(), but if +the TCP connection isn't established when nvmet_tcp_set_queue_sock() is +called then queue->state_change isn't set and sock->sk->sk_state_change +isn't replaced. + +As such we don't need to restore sock->sk->sk_state_change if +queue->state_change is NULL. + +This avoids NULL pointer dereferences such as this: + +[ 286.462026][ C0] BUG: kernel NULL pointer dereference, address: 0000000000000000 +[ 286.462814][ C0] #PF: supervisor instruction fetch in kernel mode +[ 286.463796][ C0] #PF: error_code(0x0010) - not-present page +[ 286.464392][ C0] PGD 8000000140620067 P4D 8000000140620067 PUD 114201067 PMD 0 +[ 286.465086][ C0] Oops: Oops: 0010 [#1] SMP KASAN PTI +[ 286.465559][ C0] CPU: 0 UID: 0 PID: 1628 Comm: nvme Not tainted 6.15.0-rc2+ #11 PREEMPT(voluntary) +[ 286.466393][ C0] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-3.fc41 04/01/2014 +[ 286.467147][ C0] RIP: 0010:0x0 +[ 286.467420][ C0] Code: Unable to access opcode bytes at 0xffffffffffffffd6. +[ 286.467977][ C0] RSP: 0018:ffff8883ae008580 EFLAGS: 00010246 +[ 286.468425][ C0] RAX: 0000000000000000 RBX: ffff88813fd34100 RCX: ffffffffa386cc43 +[ 286.469019][ C0] RDX: 1ffff11027fa68b6 RSI: 0000000000000008 RDI: ffff88813fd34100 +[ 286.469545][ C0] RBP: ffff88813fd34160 R08: 0000000000000000 R09: ffffed1027fa682c +[ 286.470072][ C0] R10: ffff88813fd34167 R11: 0000000000000000 R12: ffff88813fd344c3 +[ 286.470585][ C0] R13: ffff88813fd34112 R14: ffff88813fd34aec R15: ffff888132cdd268 +[ 286.471070][ C0] FS: 00007fe3c04c7d80(0000) GS:ffff88840743f000(0000) knlGS:0000000000000000 +[ 286.471644][ C0] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 286.472543][ C0] CR2: ffffffffffffffd6 CR3: 000000012daca000 CR4: 00000000000006f0 +[ 286.473500][ C0] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[ 286.474467][ C0] DR3: 0000000000000000 DR6: 00000000ffff07f0 DR7: 0000000000000400 +[ 286.475453][ C0] Call Trace: +[ 286.476102][ C0] +[ 286.476719][ C0] tcp_fin+0x2bb/0x440 +[ 286.477429][ C0] tcp_data_queue+0x190f/0x4e60 +[ 286.478174][ C0] ? __build_skb_around+0x234/0x330 +[ 286.478940][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.479659][ C0] ? __pfx_tcp_data_queue+0x10/0x10 +[ 286.480431][ C0] ? tcp_try_undo_loss+0x640/0x6c0 +[ 286.481196][ C0] ? seqcount_lockdep_reader_access.constprop.0+0x82/0x90 +[ 286.482046][ C0] ? kvm_clock_get_cycles+0x14/0x30 +[ 286.482769][ C0] ? ktime_get+0x66/0x150 +[ 286.483433][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.484146][ C0] tcp_rcv_established+0x6e4/0x2050 +[ 286.484857][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.485523][ C0] ? ipv4_dst_check+0x160/0x2b0 +[ 286.486203][ C0] ? __pfx_tcp_rcv_established+0x10/0x10 +[ 286.486917][ C0] ? lock_release+0x217/0x2c0 +[ 286.487595][ C0] tcp_v4_do_rcv+0x4d6/0x9b0 +[ 286.488279][ C0] tcp_v4_rcv+0x2af8/0x3e30 +[ 286.488904][ C0] ? raw_local_deliver+0x51b/0xad0 +[ 286.489551][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.490198][ C0] ? __pfx_tcp_v4_rcv+0x10/0x10 +[ 286.490813][ C0] ? __pfx_raw_local_deliver+0x10/0x10 +[ 286.491487][ C0] ? __pfx_nf_confirm+0x10/0x10 [nf_conntrack] +[ 286.492275][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.492900][ C0] ip_protocol_deliver_rcu+0x8f/0x370 +[ 286.493579][ C0] ip_local_deliver_finish+0x297/0x420 +[ 286.494268][ C0] ip_local_deliver+0x168/0x430 +[ 286.494867][ C0] ? __pfx_ip_local_deliver+0x10/0x10 +[ 286.495498][ C0] ? __pfx_ip_local_deliver_finish+0x10/0x10 +[ 286.496204][ C0] ? ip_rcv_finish_core+0x19a/0x1f20 +[ 286.496806][ C0] ? lock_release+0x217/0x2c0 +[ 286.497414][ C0] ip_rcv+0x455/0x6e0 +[ 286.497945][ C0] ? __pfx_ip_rcv+0x10/0x10 +[ 286.498550][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.499137][ C0] ? __pfx_ip_rcv_finish+0x10/0x10 +[ 286.499763][ C0] ? lock_release+0x217/0x2c0 +[ 286.500327][ C0] ? dl_scaled_delta_exec+0xd1/0x2c0 +[ 286.500922][ C0] ? __pfx_ip_rcv+0x10/0x10 +[ 286.501480][ C0] __netif_receive_skb_one_core+0x166/0x1b0 +[ 286.502173][ C0] ? __pfx___netif_receive_skb_one_core+0x10/0x10 +[ 286.502903][ C0] ? lock_acquire+0x2b2/0x310 +[ 286.503487][ C0] ? process_backlog+0x372/0x1350 +[ 286.504087][ C0] ? lock_release+0x217/0x2c0 +[ 286.504642][ C0] process_backlog+0x3b9/0x1350 +[ 286.505214][ C0] ? process_backlog+0x372/0x1350 +[ 286.505779][ C0] __napi_poll.constprop.0+0xa6/0x490 +[ 286.506363][ C0] net_rx_action+0x92e/0xe10 +[ 286.506889][ C0] ? __pfx_net_rx_action+0x10/0x10 +[ 286.507437][ C0] ? timerqueue_add+0x1f0/0x320 +[ 286.507977][ C0] ? sched_clock_cpu+0x68/0x540 +[ 286.508492][ C0] ? lock_acquire+0x2b2/0x310 +[ 286.509043][ C0] ? kvm_sched_clock_read+0xd/0x20 +[ 286.509607][ C0] ? handle_softirqs+0x1aa/0x7d0 +[ 286.510187][ C0] handle_softirqs+0x1f2/0x7d0 +[ 286.510754][ C0] ? __pfx_handle_softirqs+0x10/0x10 +[ 286.511348][ C0] ? irqtime_account_irq+0x181/0x290 +[ 286.511937][ C0] ? __dev_queue_xmit+0x85d/0x3450 +[ 286.512510][ C0] do_softirq.part.0+0x89/0xc0 +[ 286.513100][ C0] +[ 286.513548][ C0] +[ 286.513953][ C0] __local_bh_enable_ip+0x112/0x140 +[ 286.514522][ C0] ? __dev_queue_xmit+0x85d/0x3450 +[ 286.515072][ C0] __dev_queue_xmit+0x872/0x3450 +[ 286.515619][ C0] ? nft_do_chain+0xe16/0x15b0 [nf_tables] +[ 286.516252][ C0] ? __pfx___dev_queue_xmit+0x10/0x10 +[ 286.516817][ C0] ? selinux_ip_postroute+0x43c/0xc50 +[ 286.517433][ C0] ? __pfx_selinux_ip_postroute+0x10/0x10 +[ 286.518061][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.518606][ C0] ? ip_output+0x164/0x4a0 +[ 286.519149][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.519671][ C0] ? ip_finish_output2+0x17d5/0x1fb0 +[ 286.520258][ C0] ip_finish_output2+0xb4b/0x1fb0 +[ 286.520787][ C0] ? __pfx_ip_finish_output2+0x10/0x10 +[ 286.521355][ C0] ? __ip_finish_output+0x15d/0x750 +[ 286.521890][ C0] ip_output+0x164/0x4a0 +[ 286.522372][ C0] ? __pfx_ip_output+0x10/0x10 +[ 286.522872][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.523402][ C0] ? _raw_spin_unlock_irqrestore+0x4c/0x60 +[ 286.524031][ C0] ? __pfx_ip_finish_output+0x10/0x10 +[ 286.524605][ C0] ? __ip_queue_xmit+0x999/0x2260 +[ 286.525200][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.525744][ C0] ? ipv4_dst_check+0x16a/0x2b0 +[ 286.526279][ C0] ? lock_release+0x217/0x2c0 +[ 286.526793][ C0] __ip_queue_xmit+0x1883/0x2260 +[ 286.527324][ C0] ? __skb_clone+0x54c/0x730 +[ 286.527827][ C0] __tcp_transmit_skb+0x209b/0x37a0 +[ 286.528374][ C0] ? __pfx___tcp_transmit_skb+0x10/0x10 +[ 286.528952][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.529472][ C0] ? seqcount_lockdep_reader_access.constprop.0+0x82/0x90 +[ 286.530152][ C0] ? trace_hardirqs_on+0x12/0x120 +[ 286.530691][ C0] tcp_write_xmit+0xb81/0x88b0 +[ 286.531224][ C0] ? mod_memcg_state+0x4d/0x60 +[ 286.531736][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.532253][ C0] __tcp_push_pending_frames+0x90/0x320 +[ 286.532826][ C0] tcp_send_fin+0x141/0xb50 +[ 286.533352][ C0] ? __pfx_tcp_send_fin+0x10/0x10 +[ 286.533908][ C0] ? __local_bh_enable_ip+0xab/0x140 +[ 286.534495][ C0] inet_shutdown+0x243/0x320 +[ 286.535077][ C0] nvme_tcp_alloc_queue+0xb3b/0x2590 [nvme_tcp] +[ 286.535709][ C0] ? do_raw_spin_lock+0x129/0x260 +[ 286.536314][ C0] ? __pfx_nvme_tcp_alloc_queue+0x10/0x10 [nvme_tcp] +[ 286.536996][ C0] ? do_raw_spin_unlock+0x54/0x1e0 +[ 286.537550][ C0] ? _raw_spin_unlock+0x29/0x50 +[ 286.538127][ C0] ? do_raw_spin_lock+0x129/0x260 +[ 286.538664][ C0] ? __pfx_do_raw_spin_lock+0x10/0x10 +[ 286.539249][ C0] ? nvme_tcp_alloc_admin_queue+0xd5/0x340 [nvme_tcp] +[ 286.539892][ C0] ? __wake_up+0x40/0x60 +[ 286.540392][ C0] nvme_tcp_alloc_admin_queue+0xd5/0x340 [nvme_tcp] +[ 286.541047][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.541589][ C0] nvme_tcp_setup_ctrl+0x8b/0x7a0 [nvme_tcp] +[ 286.542254][ C0] ? _raw_spin_unlock_irqrestore+0x4c/0x60 +[ 286.542887][ C0] ? __pfx_nvme_tcp_setup_ctrl+0x10/0x10 [nvme_tcp] +[ 286.543568][ C0] ? trace_hardirqs_on+0x12/0x120 +[ 286.544166][ C0] ? _raw_spin_unlock_irqrestore+0x35/0x60 +[ 286.544792][ C0] ? nvme_change_ctrl_state+0x196/0x2e0 [nvme_core] +[ 286.545477][ C0] nvme_tcp_create_ctrl+0x839/0xb90 [nvme_tcp] +[ 286.546126][ C0] nvmf_dev_write+0x3db/0x7e0 [nvme_fabrics] +[ 286.546775][ C0] ? rw_verify_area+0x69/0x520 +[ 286.547334][ C0] vfs_write+0x218/0xe90 +[ 286.547854][ C0] ? do_syscall_64+0x9f/0x190 +[ 286.548408][ C0] ? trace_hardirqs_on_prepare+0xdb/0x120 +[ 286.549037][ C0] ? syscall_exit_to_user_mode+0x93/0x280 +[ 286.549659][ C0] ? __pfx_vfs_write+0x10/0x10 +[ 286.550259][ C0] ? do_syscall_64+0x9f/0x190 +[ 286.550840][ C0] ? syscall_exit_to_user_mode+0x8e/0x280 +[ 286.551516][ C0] ? trace_hardirqs_on_prepare+0xdb/0x120 +[ 286.552180][ C0] ? syscall_exit_to_user_mode+0x93/0x280 +[ 286.552834][ C0] ? ksys_read+0xf5/0x1c0 +[ 286.553386][ C0] ? __pfx_ksys_read+0x10/0x10 +[ 286.553964][ C0] ksys_write+0xf5/0x1c0 +[ 286.554499][ C0] ? __pfx_ksys_write+0x10/0x10 +[ 286.555072][ C0] ? trace_hardirqs_on_prepare+0xdb/0x120 +[ 286.555698][ C0] ? syscall_exit_to_user_mode+0x93/0x280 +[ 286.556319][ C0] ? do_syscall_64+0x54/0x190 +[ 286.556866][ C0] do_syscall_64+0x93/0x190 +[ 286.557420][ C0] ? rcu_read_unlock+0x17/0x60 +[ 286.557986][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.558526][ C0] ? lock_release+0x217/0x2c0 +[ 286.559087][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.559659][ C0] ? count_memcg_events.constprop.0+0x4a/0x60 +[ 286.560476][ C0] ? exc_page_fault+0x7a/0x110 +[ 286.561064][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.561647][ C0] ? lock_release+0x217/0x2c0 +[ 286.562257][ C0] ? do_user_addr_fault+0x171/0xa00 +[ 286.562839][ C0] ? do_user_addr_fault+0x4a2/0xa00 +[ 286.563453][ C0] ? irqentry_exit_to_user_mode+0x84/0x270 +[ 286.564112][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.564677][ C0] ? irqentry_exit_to_user_mode+0x84/0x270 +[ 286.565317][ C0] ? trace_hardirqs_on_prepare+0xdb/0x120 +[ 286.565922][ C0] entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 286.566542][ C0] RIP: 0033:0x7fe3c05e6504 +[ 286.567102][ C0] Code: c7 00 16 00 00 00 b8 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 80 3d c5 8b 10 00 00 74 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 55 48 89 e5 48 83 ec 20 48 89 +[ 286.568931][ C0] RSP: 002b:00007fff76444f58 EFLAGS: 00000202 ORIG_RAX: 0000000000000001 +[ 286.569807][ C0] RAX: ffffffffffffffda RBX: 000000003b40d930 RCX: 00007fe3c05e6504 +[ 286.570621][ C0] RDX: 00000000000000cf RSI: 000000003b40d930 RDI: 0000000000000003 +[ 286.571443][ C0] RBP: 0000000000000003 R08: 00000000000000cf R09: 000000003b40d930 +[ 286.572246][ C0] R10: 0000000000000000 R11: 0000000000000202 R12: 000000003b40cd60 +[ 286.573069][ C0] R13: 00000000000000cf R14: 00007fe3c07417f8 R15: 00007fe3c073502e +[ 286.573886][ C0] + +Closes: https://lore.kernel.org/linux-nvme/5hdonndzoqa265oq3bj6iarwtfk5dewxxjtbjvn5uqnwclpwt6@a2n6w3taxxex/ +Signed-off-by: Alistair Francis +Reviewed-by: Sagi Grimberg +Tested-by: Shin'ichiro Kawasaki +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + drivers/nvme/target/tcp.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c +index 4f9cac8a5abe0..259ad77c03c50 100644 +--- a/drivers/nvme/target/tcp.c ++++ b/drivers/nvme/target/tcp.c +@@ -1560,6 +1560,9 @@ static void nvmet_tcp_restore_socket_callbacks(struct nvmet_tcp_queue *queue) + { + struct socket *sock = queue->sock; + ++ if (!queue->state_change) ++ return; ++ + write_lock_bh(&sock->sk->sk_callback_lock); + sock->sk->sk_data_ready = queue->data_ready; + sock->sk->sk_state_change = queue->state_change; +-- +2.39.5 + diff --git a/queue-6.12/objtool-fix-error-handling-inconsistencies-in-check.patch b/queue-6.12/objtool-fix-error-handling-inconsistencies-in-check.patch new file mode 100644 index 0000000000..1806ba7ee3 --- /dev/null +++ b/queue-6.12/objtool-fix-error-handling-inconsistencies-in-check.patch @@ -0,0 +1,67 @@ +From 62db3a5bf283982e2ecab1e2712f103975f005b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 12:29:00 -0700 +Subject: objtool: Fix error handling inconsistencies in check() + +From: Josh Poimboeuf + +[ Upstream commit b745962cb97569aad026806bb0740663cf813147 ] + +Make sure all fatal errors are funneled through the 'out' label with a +negative ret. + +Signed-off-by: Josh Poimboeuf +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Brendan Jackman +Link: https://lore.kernel.org/r/0f49d6a27a080b4012e84e6df1e23097f44cc082.1741975349.git.jpoimboe@kernel.org +Signed-off-by: Sasha Levin +--- + tools/objtool/check.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index 0757b98b0a445..4fce0074076f3 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -4758,8 +4758,10 @@ int check(struct objtool_file *file) + init_cfi_state(&force_undefined_cfi); + force_undefined_cfi.force_undefined = true; + +- if (!cfi_hash_alloc(1UL << (file->elf->symbol_bits - 3))) ++ if (!cfi_hash_alloc(1UL << (file->elf->symbol_bits - 3))) { ++ ret = -1; + goto out; ++ } + + cfi_hash_add(&init_cfi); + cfi_hash_add(&func_cfi); +@@ -4776,7 +4778,7 @@ int check(struct objtool_file *file) + if (opts.retpoline) { + ret = validate_retpoline(file); + if (ret < 0) +- return ret; ++ goto out; + warnings += ret; + } + +@@ -4812,7 +4814,7 @@ int check(struct objtool_file *file) + */ + ret = validate_unrets(file); + if (ret < 0) +- return ret; ++ goto out; + warnings += ret; + } + +@@ -4875,7 +4877,7 @@ int check(struct objtool_file *file) + if (opts.prefix) { + ret = add_prefix_symbols(file); + if (ret < 0) +- return ret; ++ goto out; + warnings += ret; + } + +-- +2.39.5 + diff --git a/queue-6.12/objtool-properly-disable-uaccess-validation.patch b/queue-6.12/objtool-properly-disable-uaccess-validation.patch new file mode 100644 index 0000000000..1be4ab1ab2 --- /dev/null +++ b/queue-6.12/objtool-properly-disable-uaccess-validation.patch @@ -0,0 +1,68 @@ +From cf78c17cdc92d09fc97409f43d53a6b2809cbc6b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 14:55:58 -0700 +Subject: objtool: Properly disable uaccess validation + +From: Josh Poimboeuf + +[ Upstream commit e1a9dda74dbffbc3fa2069ff418a1876dc99fb14 ] + +If opts.uaccess isn't set, the uaccess validation is disabled, but only +partially: it doesn't read the uaccess_safe_builtin list but still tries +to do the validation. Disable it completely to prevent false warnings. + +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/0e95581c1d2107fb5f59418edf2b26bba38b0cbb.1742852846.git.jpoimboe@kernel.org +Signed-off-by: Sasha Levin +--- + tools/objtool/check.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index bea6461ac340d..0757b98b0a445 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -3353,7 +3353,7 @@ static int handle_insn_ops(struct instruction *insn, + if (update_cfi_state(insn, next_insn, &state->cfi, op)) + return 1; + +- if (!insn->alt_group) ++ if (!opts.uaccess || !insn->alt_group) + continue; + + if (op->dest.type == OP_DEST_PUSHF) { +@@ -3820,6 +3820,9 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, + return 0; + + case INSN_STAC: ++ if (!opts.uaccess) ++ break; ++ + if (state.uaccess) { + WARN_INSN(insn, "recursive UACCESS enable"); + return 1; +@@ -3829,6 +3832,9 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, + break; + + case INSN_CLAC: ++ if (!opts.uaccess) ++ break; ++ + if (!state.uaccess && func) { + WARN_INSN(insn, "redundant UACCESS disable"); + return 1; +@@ -4304,7 +4310,8 @@ static int validate_symbol(struct objtool_file *file, struct section *sec, + if (!insn || insn->ignore || insn->visited) + return 0; + +- state->uaccess = sym->uaccess_safe; ++ if (opts.uaccess) ++ state->uaccess = sym->uaccess_safe; + + ret = validate_branch(file, insn_func(insn), insn, *state); + if (ret) +-- +2.39.5 + diff --git a/queue-6.12/octeontx2-af-rpm-register-driver-with-pci-subsys-ids.patch b/queue-6.12/octeontx2-af-rpm-register-driver-with-pci-subsys-ids.patch new file mode 100644 index 0000000000..1edb4e92c7 --- /dev/null +++ b/queue-6.12/octeontx2-af-rpm-register-driver-with-pci-subsys-ids.patch @@ -0,0 +1,67 @@ +From 44b588a89f8a92a2c49793ee8d606c309f83bfd8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 09:26:03 +0530 +Subject: Octeontx2-af: RPM: Register driver with PCI subsys IDs + +From: Hariprasad Kelam + +[ Upstream commit fc9167192f29485be5621e2e9c8208b717b65753 ] + +Although the PCI device ID and Vendor ID for the RPM (MAC) block +have remained the same across Octeon CN10K and the next-generation +CN20K silicon, Hardware architecture has changed (NIX mapped RPMs +and RFOE Mapped RPMs). + +Add PCI Subsystem IDs to the device table to ensure that this driver +can be probed from NIX mapped RPM devices only. + +Signed-off-by: Hariprasad Kelam +Link: https://patch.msgid.link/20250224035603.1220913-1-hkelam@marvell.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/octeontx2/af/cgx.c | 14 ++++++++++++-- + drivers/net/ethernet/marvell/octeontx2/af/rvu.h | 2 ++ + 2 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +index e43c4608d3ba3..971993586fb49 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +@@ -66,8 +66,18 @@ static int cgx_fwi_link_change(struct cgx *cgx, int lmac_id, bool en); + /* Supported devices */ + static const struct pci_device_id cgx_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_CGX) }, +- { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_RPM) }, +- { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10KB_RPM) }, ++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_RPM, ++ PCI_ANY_ID, PCI_SUBSYS_DEVID_CN10K_A) }, ++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_RPM, ++ PCI_ANY_ID, PCI_SUBSYS_DEVID_CNF10K_A) }, ++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_RPM, ++ PCI_ANY_ID, PCI_SUBSYS_DEVID_CNF10K_B) }, ++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10KB_RPM, ++ PCI_ANY_ID, PCI_SUBSYS_DEVID_CN10K_B) }, ++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10KB_RPM, ++ PCI_ANY_ID, PCI_SUBSYS_DEVID_CN20KA) }, ++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10KB_RPM, ++ PCI_ANY_ID, PCI_SUBSYS_DEVID_CNF20KA) }, + { 0, } /* end of table */ + }; + +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +index 8555edbb1c8f9..f94bf04788e98 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +@@ -30,6 +30,8 @@ + #define PCI_SUBSYS_DEVID_CNF10K_A 0xBA00 + #define PCI_SUBSYS_DEVID_CNF10K_B 0xBC00 + #define PCI_SUBSYS_DEVID_CN10K_B 0xBD00 ++#define PCI_SUBSYS_DEVID_CN20KA 0xC220 ++#define PCI_SUBSYS_DEVID_CNF20KA 0xC320 + + /* PCI BAR nos */ + #define PCI_AF_REG_BAR_NUM 0 +-- +2.39.5 + diff --git a/queue-6.12/orangefs-do-not-truncate-file-size.patch b/queue-6.12/orangefs-do-not-truncate-file-size.patch new file mode 100644 index 0000000000..e55d31c1d5 --- /dev/null +++ b/queue-6.12/orangefs-do-not-truncate-file-size.patch @@ -0,0 +1,50 @@ +From 43c8bf678e68b19bbd1285e0b84ce2af21803805 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 20:47:25 +0000 +Subject: orangefs: Do not truncate file size + +From: Matthew Wilcox (Oracle) + +[ Upstream commit 062e8093592fb866b8e016641a8b27feb6ac509d ] + +'len' is used to store the result of i_size_read(), so making 'len' +a size_t results in truncation to 4GiB on 32-bit systems. + +Signed-off-by: "Matthew Wilcox (Oracle)" +Link: https://lore.kernel.org/r/20250305204734.1475264-2-willy@infradead.org +Tested-by: Mike Marshall +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/orangefs/inode.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c +index aae6d2b8767df..63d7c1ca0dfd3 100644 +--- a/fs/orangefs/inode.c ++++ b/fs/orangefs/inode.c +@@ -23,9 +23,9 @@ static int orangefs_writepage_locked(struct page *page, + struct orangefs_write_range *wr = NULL; + struct iov_iter iter; + struct bio_vec bv; +- size_t len, wlen; ++ size_t wlen; + ssize_t ret; +- loff_t off; ++ loff_t len, off; + + set_page_writeback(page); + +@@ -91,8 +91,7 @@ static int orangefs_writepages_work(struct orangefs_writepages *ow, + struct orangefs_write_range *wrp, wr; + struct iov_iter iter; + ssize_t ret; +- size_t len; +- loff_t off; ++ loff_t len, off; + int i; + + len = i_size_read(inode); +-- +2.39.5 + diff --git a/queue-6.12/pci-brcmstb-add-a-softdep-to-mip-msi-x-driver.patch b/queue-6.12/pci-brcmstb-add-a-softdep-to-mip-msi-x-driver.patch new file mode 100644 index 0000000000..8dc4cf770f --- /dev/null +++ b/queue-6.12/pci-brcmstb-add-a-softdep-to-mip-msi-x-driver.patch @@ -0,0 +1,41 @@ +From e579727b2972dd7e328a0df00b34f88eb92045b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 10:35:56 +0200 +Subject: PCI: brcmstb: Add a softdep to MIP MSI-X driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Stanimir Varbanov + +[ Upstream commit 2294059118c550464dd8906286324d90c33b152b ] + +Then the brcmstb PCIe driver and MIP MSI-X interrupt controller +drivers are built as modules there could be a race in probing. + +To avoid this, add a softdep to MIP driver to guarantee that +MIP driver will be load first. + +Signed-off-by: Stanimir Varbanov +Reviewed-by: Florian Fainelli +Tested-by: Ivan T. Ivanov +Link: https://lore.kernel.org/r/20250224083559.47645-5-svarbanov@suse.de +[kwilczynski: commit log] +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-brcmstb.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c +index 32ffb0c14c3ca..81f085cebf627 100644 +--- a/drivers/pci/controller/pcie-brcmstb.c ++++ b/drivers/pci/controller/pcie-brcmstb.c +@@ -1947,3 +1947,4 @@ module_platform_driver(brcm_pcie_driver); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Broadcom STB PCIe RC driver"); + MODULE_AUTHOR("Broadcom"); ++MODULE_SOFTDEP("pre: irq_bcm2712_mip"); +-- +2.39.5 + diff --git a/queue-6.12/pci-brcmstb-expand-inbound-window-size-up-to-64gb.patch b/queue-6.12/pci-brcmstb-expand-inbound-window-size-up-to-64gb.patch new file mode 100644 index 0000000000..55100f0a21 --- /dev/null +++ b/queue-6.12/pci-brcmstb-expand-inbound-window-size-up-to-64gb.patch @@ -0,0 +1,48 @@ +From 5455770e0f68048d58d0db6a21328c9c360e9c80 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 10:35:58 +0200 +Subject: PCI: brcmstb: Expand inbound window size up to 64GB +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Stanimir Varbanov + +[ Upstream commit 25a98c727015638baffcfa236e3f37b70cedcf87 ] + +The BCM2712 memory map can support up to 64GB of system memory, thus +expand the inbound window size in calculation helper function. + +The change is safe for the currently supported SoCs that have smaller +inbound window sizes. + +Signed-off-by: Stanimir Varbanov +Reviewed-by: Florian Fainelli +Reviewed-by: Jim Quinlan +Tested-by: Ivan T. Ivanov +Link: https://lore.kernel.org/r/20250224083559.47645-7-svarbanov@suse.de +[kwilczynski: commit log] +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-brcmstb.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c +index 792d24cea5747..32ffb0c14c3ca 100644 +--- a/drivers/pci/controller/pcie-brcmstb.c ++++ b/drivers/pci/controller/pcie-brcmstb.c +@@ -309,8 +309,8 @@ static int brcm_pcie_encode_ibar_size(u64 size) + if (log2_in >= 12 && log2_in <= 15) + /* Covers 4KB to 32KB (inclusive) */ + return (log2_in - 12) + 0x1c; +- else if (log2_in >= 16 && log2_in <= 35) +- /* Covers 64KB to 32GB, (inclusive) */ ++ else if (log2_in >= 16 && log2_in <= 36) ++ /* Covers 64KB to 64GB, (inclusive) */ + return log2_in - 15; + /* Something is awry so disable */ + return 0; +-- +2.39.5 + diff --git a/queue-6.12/pci-dwc-ep-ensure-proper-iteration-over-outbound-map.patch b/queue-6.12/pci-dwc-ep-ensure-proper-iteration-over-outbound-map.patch new file mode 100644 index 0000000000..446a146753 --- /dev/null +++ b/queue-6.12/pci-dwc-ep-ensure-proper-iteration-over-outbound-map.patch @@ -0,0 +1,45 @@ +From cd2bcab75a91aa66f98922149e4e58c2845b46de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Mar 2025 15:15:46 -0500 +Subject: PCI: dwc: ep: Ensure proper iteration over outbound map windows + +From: Frank Li + +[ Upstream commit f3e1dccba0a0833fc9a05fb838ebeb6ea4ca0e1a ] + +Most systems' PCIe outbound map windows have non-zero physical addresses, +but the possibility of encountering zero increased after following commit +("PCI: dwc: Use parent_bus_offset"). + +'ep->outbound_addr[n]', representing 'parent_bus_address', might be 0 on +some hardware, which trims high address bits through bus fabric before +sending to the PCIe controller. + +Replace the iteration logic with 'for_each_set_bit()' to ensure only +allocated map windows are iterated when determining the ATU index from a +given address. + +Link: https://lore.kernel.org/r/20250315201548.858189-12-helgaas@kernel.org +Signed-off-by: Frank Li +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/dwc/pcie-designware-ep.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c +index dea19250598a6..9e7e94f32b436 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-ep.c ++++ b/drivers/pci/controller/dwc/pcie-designware-ep.c +@@ -280,7 +280,7 @@ static int dw_pcie_find_index(struct dw_pcie_ep *ep, phys_addr_t addr, + u32 index; + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + +- for (index = 0; index < pci->num_ob_windows; index++) { ++ for_each_set_bit(index, ep->ob_window_map, pci->num_ob_windows) { + if (ep->outbound_addr[index] != addr) + continue; + *atu_index = index; +-- +2.39.5 + diff --git a/queue-6.12/pci-dwc-use-resource-start-as-ioremap-input-in-dw_pc.patch b/queue-6.12/pci-dwc-use-resource-start-as-ioremap-input-in-dw_pc.patch new file mode 100644 index 0000000000..126f0f0406 --- /dev/null +++ b/queue-6.12/pci-dwc-use-resource-start-as-ioremap-input-in-dw_pc.patch @@ -0,0 +1,46 @@ +From dbf5654ac17d8d4fa6f95f59065f95b1809a30d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Mar 2025 15:15:36 -0500 +Subject: PCI: dwc: Use resource start as ioremap() input in + dw_pcie_pme_turn_off() + +From: Frank Li + +[ Upstream commit 8f4a489b370e6612700aa16b9e4373b2d85d7503 ] + +The msg_res region translates writes into PCIe Message TLPs. Previously we +mapped this region using atu.cpu_addr, the input address programmed into +the ATU. + +"cpu_addr" is a misnomer because when a bus fabric translates addresses +between the CPU and the ATU, the ATU input address is different from the +CPU address. A future patch will rename "cpu_addr" and correct the value +to be the ATU input address instead of the CPU physical address. + +Map the msg_res region before writing to it using the msg_res resource +start, a CPU physical address. + +Link: https://lore.kernel.org/r/20250315201548.858189-2-helgaas@kernel.org +Signed-off-by: Frank Li +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/dwc/pcie-designware-host.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c +index 120e2aca5164a..d428457d9c432 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-host.c ++++ b/drivers/pci/controller/dwc/pcie-designware-host.c +@@ -902,7 +902,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci) + if (ret) + return ret; + +- mem = ioremap(atu.cpu_addr, pci->region_align); ++ mem = ioremap(pci->pp.msg_res->start, pci->region_align); + if (!mem) + return -ENOMEM; + +-- +2.39.5 + diff --git a/queue-6.12/pci-endpoint-pci-epf-test-fix-double-free-that-cause.patch b/queue-6.12/pci-endpoint-pci-epf-test-fix-double-free-that-cause.patch new file mode 100644 index 0000000000..373a7b7bf8 --- /dev/null +++ b/queue-6.12/pci-endpoint-pci-epf-test-fix-double-free-that-cause.patch @@ -0,0 +1,70 @@ +From 93f381c5e867e370af8a6a71ea11a0b5167ebd83 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 13:30:43 +0100 +Subject: PCI: endpoint: pci-epf-test: Fix double free that causes kernel to + oops +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Christian Bruel + +[ Upstream commit 934e9d137d937706004c325fa1474f9e3f1ba10a ] + +Fix a kernel oops found while testing the stm32_pcie Endpoint driver +with handling of PERST# deassertion: + +During EP initialization, pci_epf_test_alloc_space() allocates all BARs, +which are further freed if epc_set_bar() fails (for instance, due to no +free inbound window). + +However, when pci_epc_set_bar() fails, the error path: + + pci_epc_set_bar() -> + pci_epf_free_space() + +does not clear the previous assignment to epf_test->reg[bar]. + +Then, if the host reboots, the PERST# deassertion restarts the BAR +allocation sequence with the same allocation failure (no free inbound +window), creating a double free situation since epf_test->reg[bar] was +deallocated and is still non-NULL. + +Thus, make sure that pci_epf_alloc_space() and pci_epf_free_space() +invocations are symmetric, and as such, set epf_test->reg[bar] to NULL +when memory is freed. + +Reviewed-by: Niklas Cassel +Reviewed-by: Manivannan Sadhasivam +Signed-off-by: Christian Bruel +Link: https://lore.kernel.org/r/20250124123043.96112-1-christian.bruel@foss.st.com +[kwilczynski: commit log] +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/pci/endpoint/functions/pci-epf-test.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c +index 14b4c68ab4e1a..21aa3709e2577 100644 +--- a/drivers/pci/endpoint/functions/pci-epf-test.c ++++ b/drivers/pci/endpoint/functions/pci-epf-test.c +@@ -703,6 +703,7 @@ static int pci_epf_test_set_bar(struct pci_epf *epf) + if (ret) { + pci_epf_free_space(epf, epf_test->reg[bar], bar, + PRIMARY_INTERFACE); ++ epf_test->reg[bar] = NULL; + dev_err(dev, "Failed to set BAR%d\n", bar); + if (bar == test_reg_bar) + return ret; +@@ -878,6 +879,7 @@ static void pci_epf_test_free_space(struct pci_epf *epf) + + pci_epf_free_space(epf, epf_test->reg[bar], bar, + PRIMARY_INTERFACE); ++ epf_test->reg[bar] = NULL; + } + } + +-- +2.39.5 + diff --git a/queue-6.12/pci-epf-mhi-update-device-id-for-sa8775p.patch b/queue-6.12/pci-epf-mhi-update-device-id-for-sa8775p.patch new file mode 100644 index 0000000000..72559d960a --- /dev/null +++ b/queue-6.12/pci-epf-mhi-update-device-id-for-sa8775p.patch @@ -0,0 +1,39 @@ +From 5c8798c18a788a2161e5a208ecfd5e54b49d7716 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Dec 2024 12:24:20 +0530 +Subject: PCI: epf-mhi: Update device ID for SA8775P +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Mrinmay Sarkar + +[ Upstream commit 4f13dd9e2b1d2b317bb36704f8a7bd1d3017f7a2 ] + +Update device ID for the Qcom SA8775P SoC. + +Signed-off-by: Mrinmay Sarkar +Link: https://lore.kernel.org/r/20241205065422.2515086-3-quic_msarkar@quicinc.com +[kwilczynski: commit log] +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/pci/endpoint/functions/pci-epf-mhi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pci/endpoint/functions/pci-epf-mhi.c b/drivers/pci/endpoint/functions/pci-epf-mhi.c +index 54286a40bdfbf..6643a88c7a0ce 100644 +--- a/drivers/pci/endpoint/functions/pci-epf-mhi.c ++++ b/drivers/pci/endpoint/functions/pci-epf-mhi.c +@@ -125,7 +125,7 @@ static const struct pci_epf_mhi_ep_info sm8450_info = { + + static struct pci_epf_header sa8775p_header = { + .vendorid = PCI_VENDOR_ID_QCOM, +- .deviceid = 0x0306, /* FIXME: Update deviceid for sa8775p EP */ ++ .deviceid = 0x0116, + .baseclass_code = PCI_CLASS_OTHERS, + .interrupt_pin = PCI_INTERRUPT_INTA, + }; +-- +2.39.5 + diff --git a/queue-6.12/pci-fix-old_size-lower-bound-in-calculate_iosize-too.patch b/queue-6.12/pci-fix-old_size-lower-bound-in-calculate_iosize-too.patch new file mode 100644 index 0000000000..df4af544ce --- /dev/null +++ b/queue-6.12/pci-fix-old_size-lower-bound-in-calculate_iosize-too.patch @@ -0,0 +1,48 @@ +From f0f40375eb2c907b130a1783551b68bfff23d0d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Dec 2024 19:56:12 +0200 +Subject: PCI: Fix old_size lower bound in calculate_iosize() too +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit ff61f380de5652e723168341480cc7adf1dd6213 ] + +Commit 903534fa7d30 ("PCI: Fix resource double counting on remove & +rescan") fixed double counting of mem resources because of old_size being +applied too early. + +Fix a similar counting bug on the io resource side. + +Link: https://lore.kernel.org/r/20241216175632.4175-6-ilpo.jarvinen@linux.intel.com +Signed-off-by: Ilpo Järvinen +Signed-off-by: Bjorn Helgaas +Tested-by: Xiaochun Lee +Signed-off-by: Sasha Levin +--- + drivers/pci/setup-bus.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c +index f16c7ce3bf3fc..1eceabef9e84d 100644 +--- a/drivers/pci/setup-bus.c ++++ b/drivers/pci/setup-bus.c +@@ -814,11 +814,9 @@ static resource_size_t calculate_iosize(resource_size_t size, + size = (size & 0xff) + ((size & ~0xffUL) << 2); + #endif + size = size + size1; +- if (size < old_size) +- size = old_size; + +- size = ALIGN(max(size, add_size) + children_add_size, align); +- return size; ++ size = max(size, add_size) + children_add_size; ++ return ALIGN(max(size, old_size), align); + } + + static resource_size_t calculate_memsize(resource_size_t size, +-- +2.39.5 + diff --git a/queue-6.12/pci-vmd-disable-msi-remapping-bypass-under-xen.patch b/queue-6.12/pci-vmd-disable-msi-remapping-bypass-under-xen.patch new file mode 100644 index 0000000000..94b2b2979e --- /dev/null +++ b/queue-6.12/pci-vmd-disable-msi-remapping-bypass-under-xen.patch @@ -0,0 +1,78 @@ +From e0dc536d3a0df78e2bf0618e85b4001dd7f8df2d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 10:20:56 +0100 +Subject: PCI: vmd: Disable MSI remapping bypass under Xen +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Roger Pau Monne + +[ Upstream commit 6c4d5aadf5df31ea0ac025980670eee9beaf466b ] + +MSI remapping bypass (directly configuring MSI entries for devices on the +VMD bus) won't work under Xen, as Xen is not aware of devices in such bus, +and hence cannot configure the entries using the pIRQ interface in the PV +case, and in the PVH case traps won't be setup for MSI entries for such +devices. + +Until Xen is aware of devices in the VMD bus prevent the +VMD_FEAT_CAN_BYPASS_MSI_REMAP capability from being used when running as +any kind of Xen guest. + +The MSI remapping bypass is an optional feature of VMD bridges, and hence +when running under Xen it will be masked and devices will be forced to +redirect its interrupts from the VMD bridge. That mode of operation must +always be supported by VMD bridges and works when Xen is not aware of +devices behind the VMD bridge. + +Signed-off-by: Roger Pau Monné +Acked-by: Bjorn Helgaas +Message-ID: <20250219092059.90850-3-roger.pau@citrix.com> +Signed-off-by: Juergen Gross +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/vmd.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c +index 94ceec50a2b94..8df064b62a2ff 100644 +--- a/drivers/pci/controller/vmd.c ++++ b/drivers/pci/controller/vmd.c +@@ -17,6 +17,8 @@ + #include + #include + ++#include ++ + #include + + #define VMD_CFGBAR 0 +@@ -970,6 +972,24 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id) + struct vmd_dev *vmd; + int err; + ++ if (xen_domain()) { ++ /* ++ * Xen doesn't have knowledge about devices in the VMD bus ++ * because the config space of devices behind the VMD bridge is ++ * not known to Xen, and hence Xen cannot discover or configure ++ * them in any way. ++ * ++ * Bypass of MSI remapping won't work in that case as direct ++ * write by Linux to the MSI entries won't result in functional ++ * interrupts, as Xen is the entity that manages the host ++ * interrupt controller and must configure interrupts. However ++ * multiplexing of interrupts by the VMD bridge will work under ++ * Xen, so force the usage of that mode which must always be ++ * supported by VMD bridges. ++ */ ++ features &= ~VMD_FEAT_CAN_BYPASS_MSI_REMAP; ++ } ++ + if (resource_size(&dev->resource[VMD_CFGBAR]) < (1 << 20)) + return -ENOMEM; + +-- +2.39.5 + diff --git a/queue-6.12/perf-amd-ibs-fix-config-to-sample-period-calculation.patch b/queue-6.12/perf-amd-ibs-fix-config-to-sample-period-calculation.patch new file mode 100644 index 0000000000..2b665ed281 --- /dev/null +++ b/queue-6.12/perf-amd-ibs-fix-config-to-sample-period-calculation.patch @@ -0,0 +1,74 @@ +From 5dccbd9f2fc70e58ee1012a1293741451d409eb8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jan 2025 05:44:32 +0000 +Subject: perf/amd/ibs: Fix ->config to sample period calculation for OP PMU + +From: Ravi Bangoria + +[ Upstream commit 598bdf4fefff5af4ce6d26d16f7b2a20808fc4cb ] + +Instead of using standard perf_event_attr->freq=0 and ->sample_period +fields, IBS event in 'sample period mode' can also be opened by setting +period value directly in perf_event_attr->config in a MaxCnt bit-field +format. + +IBS OP MaxCnt bits are defined as: + + (high bits) IbsOpCtl[26:20] = IbsOpMaxCnt[26:20] + (low bits) IbsOpCtl[15:0] = IbsOpMaxCnt[19:4] + +Perf event sample period can be derived from MaxCnt bits as: + + sample_period = (high bits) | ((low_bits) << 4); + +However, current code just masks MaxCnt bits and shifts all of them, +including high bits, which is incorrect. Fix it. + +Signed-off-by: Ravi Bangoria +Signed-off-by: Peter Zijlstra (Intel) +Acked-by: Namhyung Kim +Link: https://lkml.kernel.org/r/20250115054438.1021-4-ravi.bangoria@amd.com +Signed-off-by: Sasha Levin +--- + arch/x86/events/amd/ibs.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c +index 8f3b5764e139d..d34ee6f04f18f 100644 +--- a/arch/x86/events/amd/ibs.c ++++ b/arch/x86/events/amd/ibs.c +@@ -272,7 +272,7 @@ static int perf_ibs_init(struct perf_event *event) + { + struct hw_perf_event *hwc = &event->hw; + struct perf_ibs *perf_ibs; +- u64 max_cnt, config; ++ u64 config; + int ret; + + perf_ibs = get_ibs_pmu(event->attr.type); +@@ -309,10 +309,19 @@ static int perf_ibs_init(struct perf_event *event) + if (!hwc->sample_period) + hwc->sample_period = 0x10; + } else { +- max_cnt = config & perf_ibs->cnt_mask; ++ u64 period = 0; ++ ++ if (perf_ibs == &perf_ibs_op) { ++ period = (config & IBS_OP_MAX_CNT) << 4; ++ if (ibs_caps & IBS_CAPS_OPCNTEXT) ++ period |= config & IBS_OP_MAX_CNT_EXT_MASK; ++ } else { ++ period = (config & IBS_FETCH_MAX_CNT) << 4; ++ } ++ + config &= ~perf_ibs->cnt_mask; +- event->attr.sample_period = max_cnt << 4; +- hwc->sample_period = event->attr.sample_period; ++ event->attr.sample_period = period; ++ hwc->sample_period = period; + } + + if (!hwc->sample_period) +-- +2.39.5 + diff --git a/queue-6.12/perf-amd-ibs-fix-perf_ibs_op.cnt_mask-for-curcnt.patch b/queue-6.12/perf-amd-ibs-fix-perf_ibs_op.cnt_mask-for-curcnt.patch new file mode 100644 index 0000000000..71016586d7 --- /dev/null +++ b/queue-6.12/perf-amd-ibs-fix-perf_ibs_op.cnt_mask-for-curcnt.patch @@ -0,0 +1,63 @@ +From 47edcb211109882dfb221fdca11da6ca4d04e8a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jan 2025 05:44:33 +0000 +Subject: perf/amd/ibs: Fix perf_ibs_op.cnt_mask for CurCnt + +From: Ravi Bangoria + +[ Upstream commit 46dcf85566170d4528b842bf83ffc350d71771fa ] + +IBS Op uses two counters: MaxCnt and CurCnt. MaxCnt is programmed with +the desired sample period. IBS hw generates sample when CurCnt reaches +to MaxCnt. The size of these counter used to be 20 bits but later they +were extended to 27 bits. The 7 bit extension is indicated by CPUID +Fn8000_001B_EAX[6 / OpCntExt]. + +perf_ibs->cnt_mask variable contains bit masks for MaxCnt and CurCnt. +But IBS driver does not set upper 7 bits of CurCnt in cnt_mask even +when OpCntExt CPUID bit is set. Fix this. + +IBS driver uses cnt_mask[CurCnt] bits only while disabling an event. +Fortunately, CurCnt bits are not read from MSR while re-enabling the +event, instead MaxCnt is programmed with desired period and CurCnt is +set to 0. Hence, we did not see any issues so far. + +Signed-off-by: Ravi Bangoria +Signed-off-by: Peter Zijlstra (Intel) +Acked-by: Namhyung Kim +Link: https://lkml.kernel.org/r/20250115054438.1021-5-ravi.bangoria@amd.com +Signed-off-by: Sasha Levin +--- + arch/x86/events/amd/ibs.c | 3 ++- + arch/x86/include/asm/perf_event.h | 1 + + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c +index c3a2f6f57770a..8f3b5764e139d 100644 +--- a/arch/x86/events/amd/ibs.c ++++ b/arch/x86/events/amd/ibs.c +@@ -1222,7 +1222,8 @@ static __init int perf_ibs_op_init(void) + if (ibs_caps & IBS_CAPS_OPCNTEXT) { + perf_ibs_op.max_period |= IBS_OP_MAX_CNT_EXT_MASK; + perf_ibs_op.config_mask |= IBS_OP_MAX_CNT_EXT_MASK; +- perf_ibs_op.cnt_mask |= IBS_OP_MAX_CNT_EXT_MASK; ++ perf_ibs_op.cnt_mask |= (IBS_OP_MAX_CNT_EXT_MASK | ++ IBS_OP_CUR_CNT_EXT_MASK); + } + + if (ibs_caps & IBS_CAPS_ZEN4) +diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h +index 7505bb5d260ab..aa351c4a20eee 100644 +--- a/arch/x86/include/asm/perf_event.h ++++ b/arch/x86/include/asm/perf_event.h +@@ -520,6 +520,7 @@ struct pebs_xmm { + */ + #define IBS_OP_CUR_CNT (0xFFF80ULL<<32) + #define IBS_OP_CUR_CNT_RAND (0x0007FULL<<32) ++#define IBS_OP_CUR_CNT_EXT_MASK (0x7FULL<<52) + #define IBS_OP_CNT_CTL (1ULL<<19) + #define IBS_OP_VAL (1ULL<<18) + #define IBS_OP_ENABLE (1ULL<<17) +-- +2.39.5 + diff --git a/queue-6.12/perf-arm_pmuv3-call-kvm_vcpu_pmu_resync_el0-before-e.patch b/queue-6.12/perf-arm_pmuv3-call-kvm_vcpu_pmu_resync_el0-before-e.patch new file mode 100644 index 0000000000..9342eb8be7 --- /dev/null +++ b/queue-6.12/perf-arm_pmuv3-call-kvm_vcpu_pmu_resync_el0-before-e.patch @@ -0,0 +1,44 @@ +From 878851b069dd494ada0d926f70f8a2591b15f2ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 14:39:56 -0600 +Subject: perf: arm_pmuv3: Call kvm_vcpu_pmu_resync_el0() before enabling + counters + +From: Rob Herring (Arm) + +[ Upstream commit 04bd15c4cbc3f7bd2399d1baab958c5e738dbfc9 ] + +Counting events related to setup of the PMU is not desired, but +kvm_vcpu_pmu_resync_el0() is called just after the PMU counters have +been enabled. Move the call to before enabling the counters. + +Signed-off-by: Rob Herring (Arm) +Reviewed-by: Anshuman Khandual +Tested-by: James Clark +Link: https://lore.kernel.org/r/20250218-arm-brbe-v19-v20-1-4e9922fc2e8e@kernel.org +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/perf/arm_pmuv3.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c +index 0afe02f879b45..d9b56f0f90942 100644 +--- a/drivers/perf/arm_pmuv3.c ++++ b/drivers/perf/arm_pmuv3.c +@@ -816,10 +816,10 @@ static void armv8pmu_start(struct arm_pmu *cpu_pmu) + else + armv8pmu_disable_user_access(); + ++ kvm_vcpu_pmu_resync_el0(); ++ + /* Enable all counters */ + armv8pmu_pmcr_write(armv8pmu_pmcr_read() | ARMV8_PMU_PMCR_E); +- +- kvm_vcpu_pmu_resync_el0(); + } + + static void armv8pmu_stop(struct arm_pmu *cpu_pmu) +-- +2.39.5 + diff --git a/queue-6.12/perf-avoid-the-read-if-the-count-is-already-updated.patch b/queue-6.12/perf-avoid-the-read-if-the-count-is-already-updated.patch new file mode 100644 index 0000000000..6b8dd84782 --- /dev/null +++ b/queue-6.12/perf-avoid-the-read-if-the-count-is-already-updated.patch @@ -0,0 +1,144 @@ +From 05f2e06606f07903a60482c4611d98e11e65f549 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jan 2025 07:23:02 -0800 +Subject: perf: Avoid the read if the count is already updated + +From: Peter Zijlstra (Intel) + +[ Upstream commit 8ce939a0fa194939cc1f92dbd8bc1a7806e7d40a ] + +The event may have been updated in the PMU-specific implementation, +e.g., Intel PEBS counters snapshotting. The common code should not +read and overwrite the value. + +The PERF_SAMPLE_READ in the data->sample_type can be used to detect +whether the PMU-specific value is available. If yes, avoid the +pmu->read() in the common code. Add a new flag, skip_read, to track the +case. + +Factor out a perf_pmu_read() to clean up the code. + +Signed-off-by: Peter Zijlstra (Intel) +Signed-off-by: Kan Liang +Signed-off-by: Peter Zijlstra (Intel) +Link: https://lkml.kernel.org/r/20250121152303.3128733-3-kan.liang@linux.intel.com +Signed-off-by: Sasha Levin +--- + include/linux/perf_event.h | 8 +++++++- + kernel/events/core.c | 33 ++++++++++++++++----------------- + kernel/events/ring_buffer.c | 1 + + 3 files changed, 24 insertions(+), 18 deletions(-) + +diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h +index 0997077bcc52a..ce64b4b937f06 100644 +--- a/include/linux/perf_event.h ++++ b/include/linux/perf_event.h +@@ -1063,7 +1063,13 @@ struct perf_output_handle { + struct perf_buffer *rb; + unsigned long wakeup; + unsigned long size; +- u64 aux_flags; ++ union { ++ u64 flags; /* perf_output*() */ ++ u64 aux_flags; /* perf_aux_output*() */ ++ struct { ++ u64 skip_read : 1; ++ }; ++ }; + union { + void *addr; + unsigned long head; +diff --git a/kernel/events/core.c b/kernel/events/core.c +index 19dde12f23b83..285a4548450bd 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -1195,6 +1195,12 @@ static void perf_assert_pmu_disabled(struct pmu *pmu) + WARN_ON_ONCE(*this_cpu_ptr(pmu->pmu_disable_count) == 0); + } + ++static inline void perf_pmu_read(struct perf_event *event) ++{ ++ if (event->state == PERF_EVENT_STATE_ACTIVE) ++ event->pmu->read(event); ++} ++ + static void get_ctx(struct perf_event_context *ctx) + { + refcount_inc(&ctx->refcount); +@@ -3482,8 +3488,7 @@ static void __perf_event_sync_stat(struct perf_event *event, + * we know the event must be on the current CPU, therefore we + * don't need to use it. + */ +- if (event->state == PERF_EVENT_STATE_ACTIVE) +- event->pmu->read(event); ++ perf_pmu_read(event); + + perf_event_update_time(event); + +@@ -4634,15 +4639,8 @@ static void __perf_event_read(void *info) + + pmu->read(event); + +- for_each_sibling_event(sub, event) { +- if (sub->state == PERF_EVENT_STATE_ACTIVE) { +- /* +- * Use sibling's PMU rather than @event's since +- * sibling could be on different (eg: software) PMU. +- */ +- sub->pmu->read(sub); +- } +- } ++ for_each_sibling_event(sub, event) ++ perf_pmu_read(sub); + + data->ret = pmu->commit_txn(pmu); + +@@ -7408,9 +7406,8 @@ static void perf_output_read_group(struct perf_output_handle *handle, + if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) + values[n++] = running; + +- if ((leader != event) && +- (leader->state == PERF_EVENT_STATE_ACTIVE)) +- leader->pmu->read(leader); ++ if ((leader != event) && !handle->skip_read) ++ perf_pmu_read(leader); + + values[n++] = perf_event_count(leader, self); + if (read_format & PERF_FORMAT_ID) +@@ -7423,9 +7420,8 @@ static void perf_output_read_group(struct perf_output_handle *handle, + for_each_sibling_event(sub, leader) { + n = 0; + +- if ((sub != event) && +- (sub->state == PERF_EVENT_STATE_ACTIVE)) +- sub->pmu->read(sub); ++ if ((sub != event) && !handle->skip_read) ++ perf_pmu_read(sub); + + values[n++] = perf_event_count(sub, self); + if (read_format & PERF_FORMAT_ID) +@@ -7484,6 +7480,9 @@ void perf_output_sample(struct perf_output_handle *handle, + { + u64 sample_type = data->type; + ++ if (data->sample_flags & PERF_SAMPLE_READ) ++ handle->skip_read = 1; ++ + perf_output_put(handle, *header); + + if (sample_type & PERF_SAMPLE_IDENTIFIER) +diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c +index bbfa22c0a1597..6ecbbc57cdfde 100644 +--- a/kernel/events/ring_buffer.c ++++ b/kernel/events/ring_buffer.c +@@ -185,6 +185,7 @@ __perf_output_begin(struct perf_output_handle *handle, + + handle->rb = rb; + handle->event = event; ++ handle->flags = 0; + + have_lost = local_read(&rb->lost); + if (unlikely(have_lost)) { +-- +2.39.5 + diff --git a/queue-6.12/perf-core-clean-up-perf_try_init_event.patch b/queue-6.12/perf-core-clean-up-perf_try_init_event.patch new file mode 100644 index 0000000000..3286399365 --- /dev/null +++ b/queue-6.12/perf-core-clean-up-perf_try_init_event.patch @@ -0,0 +1,107 @@ +From 0945f764fdef893577edeea18ced9c3fc22f2d12 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 11:21:28 +0100 +Subject: perf/core: Clean up perf_try_init_event() + +From: Peter Zijlstra + +[ Upstream commit da02f54e81db2f7bf6af9d1d0cfc5b41ec6d0dcb ] + +Make sure that perf_try_init_event() doesn't leave event->pmu nor +event->destroy set on failure. + +Signed-off-by: Peter Zijlstra (Intel) +Signed-off-by: Ingo Molnar +Acked-by: Ravi Bangoria +Link: https://lore.kernel.org/r/20250205102449.110145835@infradead.org +Signed-off-by: Sasha Levin +--- + kernel/events/core.c | 65 ++++++++++++++++++++++++++------------------ + 1 file changed, 38 insertions(+), 27 deletions(-) + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index edafe9fc4bdd0..19dde12f23b83 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -11978,40 +11978,51 @@ static int perf_try_init_event(struct pmu *pmu, struct perf_event *event) + if (ctx) + perf_event_ctx_unlock(event->group_leader, ctx); + +- if (!ret) { +- if (!(pmu->capabilities & PERF_PMU_CAP_EXTENDED_REGS) && +- has_extended_regs(event)) +- ret = -EOPNOTSUPP; ++ if (ret) ++ goto err_pmu; + +- if (pmu->capabilities & PERF_PMU_CAP_NO_EXCLUDE && +- event_has_any_exclude_flag(event)) +- ret = -EINVAL; ++ if (!(pmu->capabilities & PERF_PMU_CAP_EXTENDED_REGS) && ++ has_extended_regs(event)) { ++ ret = -EOPNOTSUPP; ++ goto err_destroy; ++ } + +- if (pmu->scope != PERF_PMU_SCOPE_NONE && event->cpu >= 0) { +- const struct cpumask *cpumask = perf_scope_cpu_topology_cpumask(pmu->scope, event->cpu); +- struct cpumask *pmu_cpumask = perf_scope_cpumask(pmu->scope); +- int cpu; +- +- if (pmu_cpumask && cpumask) { +- cpu = cpumask_any_and(pmu_cpumask, cpumask); +- if (cpu >= nr_cpu_ids) +- ret = -ENODEV; +- else +- event->event_caps |= PERF_EV_CAP_READ_SCOPE; +- } else { +- ret = -ENODEV; +- } +- } ++ if (pmu->capabilities & PERF_PMU_CAP_NO_EXCLUDE && ++ event_has_any_exclude_flag(event)) { ++ ret = -EINVAL; ++ goto err_destroy; ++ } + +- if (ret && event->destroy) +- event->destroy(event); ++ if (pmu->scope != PERF_PMU_SCOPE_NONE && event->cpu >= 0) { ++ const struct cpumask *cpumask; ++ struct cpumask *pmu_cpumask; ++ int cpu; ++ ++ cpumask = perf_scope_cpu_topology_cpumask(pmu->scope, event->cpu); ++ pmu_cpumask = perf_scope_cpumask(pmu->scope); ++ ++ ret = -ENODEV; ++ if (!pmu_cpumask || !cpumask) ++ goto err_destroy; ++ ++ cpu = cpumask_any_and(pmu_cpumask, cpumask); ++ if (cpu >= nr_cpu_ids) ++ goto err_destroy; ++ ++ event->event_caps |= PERF_EV_CAP_READ_SCOPE; + } + +- if (ret) { +- event->pmu = NULL; +- module_put(pmu->module); ++ return 0; ++ ++err_destroy: ++ if (event->destroy) { ++ event->destroy(event); ++ event->destroy = NULL; + } + ++err_pmu: ++ event->pmu = NULL; ++ module_put(pmu->module); + return ret; + } + +-- +2.39.5 + diff --git a/queue-6.12/perf-hw_breakpoint-return-eopnotsupp-for-unsupported.patch b/queue-6.12/perf-hw_breakpoint-return-eopnotsupp-for-unsupported.patch new file mode 100644 index 0000000000..f7a0b8e272 --- /dev/null +++ b/queue-6.12/perf-hw_breakpoint-return-eopnotsupp-for-unsupported.patch @@ -0,0 +1,54 @@ +From 123d326f14b72218826317c14d1c2d68b40d62b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 14:54:51 +0530 +Subject: perf/hw_breakpoint: Return EOPNOTSUPP for unsupported breakpoint type + +From: Saket Kumar Bhaskar + +[ Upstream commit 061c991697062f3bf87b72ed553d1d33a0e370dd ] + +Currently, __reserve_bp_slot() returns -ENOSPC for unsupported +breakpoint types on the architecture. For example, powerpc +does not support hardware instruction breakpoints. This causes +the perf_skip BPF selftest to fail, as neither ENOENT nor +EOPNOTSUPP is returned by perf_event_open for unsupported +breakpoint types. As a result, the test that should be skipped +for this arch is not correctly identified. + +To resolve this, hw_breakpoint_event_init() should exit early by +checking for unsupported breakpoint types using +hw_breakpoint_slots_cached() and return the appropriate error +(-EOPNOTSUPP). + +Signed-off-by: Saket Kumar Bhaskar +Signed-off-by: Ingo Molnar +Cc: Marco Elver +Cc: Dmitry Vyukov +Cc: Ian Rogers +Cc: Frederic Weisbecker +Link: https://lore.kernel.org/r/20250303092451.1862862-1-skb99@linux.ibm.com +Signed-off-by: Sasha Levin +--- + kernel/events/hw_breakpoint.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c +index 6c2cb4e4f48da..8f3f624419aa9 100644 +--- a/kernel/events/hw_breakpoint.c ++++ b/kernel/events/hw_breakpoint.c +@@ -950,9 +950,10 @@ static int hw_breakpoint_event_init(struct perf_event *bp) + return -ENOENT; + + /* +- * no branch sampling for breakpoint events ++ * Check if breakpoint type is supported before proceeding. ++ * Also, no branch sampling for breakpoint events. + */ +- if (has_branch_stack(bp)) ++ if (!hw_breakpoint_slots_cached(find_slot_idx(bp->attr.bp_type)) || has_branch_stack(bp)) + return -EOPNOTSUPP; + + err = register_perf_hw_breakpoint(bp); +-- +2.39.5 + diff --git a/queue-6.12/phy-core-don-t-require-set_mode-callback-for-phy_get.patch b/queue-6.12/phy-core-don-t-require-set_mode-callback-for-phy_get.patch new file mode 100644 index 0000000000..b94847601b --- /dev/null +++ b/queue-6.12/phy-core-don-t-require-set_mode-callback-for-phy_get.patch @@ -0,0 +1,54 @@ +From 926f6fb20c83803820bda8c789ad688a8e65a430 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Feb 2025 14:31:45 +0200 +Subject: phy: core: don't require set_mode() callback for phy_get_mode() to + work + +From: Dmitry Baryshkov + +[ Upstream commit d58c04e305afbaa9dda7969151f06c4efe2c98b0 ] + +As reported by Damon Ding, the phy_get_mode() call doesn't work as +expected unless the PHY driver has a .set_mode() call. This prompts PHY +drivers to have empty stubs for .set_mode() for the sake of being able +to get the mode. + +Make .set_mode() callback truly optional and update PHY's mode even if +it there is none. + +Cc: Damon Ding +Link: https://lore.kernel.org/r/96f8310f-93f1-4bcb-8637-137e1159ff83@rock-chips.com +Tested-by: Damon Ding +Signed-off-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20250209-phy-fix-set-moe-v2-1-76e248503856@linaro.org +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/phy-core.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c +index 413f76e2d1744..e0a6a272f5714 100644 +--- a/drivers/phy/phy-core.c ++++ b/drivers/phy/phy-core.c +@@ -405,13 +405,14 @@ EXPORT_SYMBOL_GPL(phy_power_off); + + int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode) + { +- int ret; ++ int ret = 0; + +- if (!phy || !phy->ops->set_mode) ++ if (!phy) + return 0; + + mutex_lock(&phy->mutex); +- ret = phy->ops->set_mode(phy, mode, submode); ++ if (phy->ops->set_mode) ++ ret = phy->ops->set_mode(phy, mode, submode); + if (!ret) + phy->attrs.mode = mode; + mutex_unlock(&phy->mutex); +-- +2.39.5 + diff --git a/queue-6.12/phy-exynos5-usbdrd-fix-eds-distribution-tuning-gs101.patch b/queue-6.12/phy-exynos5-usbdrd-fix-eds-distribution-tuning-gs101.patch new file mode 100644 index 0000000000..9ea1afb72c --- /dev/null +++ b/queue-6.12/phy-exynos5-usbdrd-fix-eds-distribution-tuning-gs101.patch @@ -0,0 +1,57 @@ +From 93bfabab446db73c84e53f4d071635ac85c86bf5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 6 Dec 2024 16:31:04 +0000 +Subject: phy: exynos5-usbdrd: fix EDS distribution tuning (gs101) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: André Draszik + +[ Upstream commit 21860f340ba76ee042e5431ff92537f89bc11476 ] + +This code's intention is to configure lane0 and lane2 tunings, but for +lane2 there is a typo and it ends up tuning something else. + +Fix the typo, as it doesn't appear to make sense to apply different +tunings for lane0 vs lane2. + +The same typo appears to exist in the bootloader, hence we restore the +original value in the typo'd registers as well. This can be removed +once / if the bootloader is updated. + +Note that this is incorrect in the downstream driver as well - the +values had been copied from there. + +Reviewed-by: Peter Griffin +Tested-by: Peter Griffin +Signed-off-by: André Draszik +Tested-by: Will McVicker +Link: https://lore.kernel.org/r/20241206-gs101-phy-lanes-orientation-phy-v4-4-f5961268b149@linaro.org +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/samsung/phy-exynos5-usbdrd.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c +index 46b8f6987c62c..28d02ae60cc14 100644 +--- a/drivers/phy/samsung/phy-exynos5-usbdrd.c ++++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c +@@ -1513,8 +1513,11 @@ static const struct exynos5_usbdrd_phy_tuning gs101_tunes_pipe3_preinit[] = { + PHY_TUNING_ENTRY_PMA(0x09e0, -1, 0x00), + PHY_TUNING_ENTRY_PMA(0x09e4, -1, 0x36), + PHY_TUNING_ENTRY_PMA(0x1e7c, -1, 0x06), +- PHY_TUNING_ENTRY_PMA(0x1e90, -1, 0x00), +- PHY_TUNING_ENTRY_PMA(0x1e94, -1, 0x36), ++ PHY_TUNING_ENTRY_PMA(0x19e0, -1, 0x00), ++ PHY_TUNING_ENTRY_PMA(0x19e4, -1, 0x36), ++ /* fix bootloader bug */ ++ PHY_TUNING_ENTRY_PMA(0x1e90, -1, 0x02), ++ PHY_TUNING_ENTRY_PMA(0x1e94, -1, 0x0b), + /* improve LVCC */ + PHY_TUNING_ENTRY_PMA(0x08f0, -1, 0x30), + PHY_TUNING_ENTRY_PMA(0x18f0, -1, 0x30), +-- +2.39.5 + diff --git a/queue-6.12/phy-phy-rockchip-samsung-hdptx-swap-the-definitions-.patch b/queue-6.12/phy-phy-rockchip-samsung-hdptx-swap-the-definitions-.patch new file mode 100644 index 0000000000..95ddf966ab --- /dev/null +++ b/queue-6.12/phy-phy-rockchip-samsung-hdptx-swap-the-definitions-.patch @@ -0,0 +1,41 @@ +From 12686d8faf1a16931ae3f023e950fd5f4c4a0fd9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 18:51:54 +0800 +Subject: phy: phy-rockchip-samsung-hdptx: Swap the definitions of LCPLL_REF + and ROPLL_REF + +From: Damon Ding + +[ Upstream commit 2947c8065e9efdd3b6434d2817dc8896234a3fc0 ] + +According to the datasheet, setting the dig_clk_sel bit of CMN_REG(0097) +to 1'b1 selects LCPLL as the reference clock, while setting it to 1'b0 +selects the ROPLL. + +Signed-off-by: Damon Ding +Reviewed-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20250205105157.580060-2-damon.ding@rock-chips.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +index be6f1ca9095aa..dc6e01dff5c74 100644 +--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c ++++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +@@ -94,8 +94,8 @@ + #define LCPLL_ALONE_MODE BIT(1) + /* CMN_REG(0097) */ + #define DIG_CLK_SEL BIT(1) +-#define ROPLL_REF BIT(1) +-#define LCPLL_REF 0 ++#define LCPLL_REF BIT(1) ++#define ROPLL_REF 0 + /* CMN_REG(0099) */ + #define CMN_ROPLL_ALONE_MODE BIT(2) + #define ROPLL_ALONE_MODE BIT(2) +-- +2.39.5 + diff --git a/queue-6.12/phy-renesas-rcar-gen3-usb2-assert-pll-reset-on-phy-p.patch b/queue-6.12/phy-renesas-rcar-gen3-usb2-assert-pll-reset-on-phy-p.patch new file mode 100644 index 0000000000..e16e4a404d --- /dev/null +++ b/queue-6.12/phy-renesas-rcar-gen3-usb2-assert-pll-reset-on-phy-p.patch @@ -0,0 +1,50 @@ +From f7a07c8345d8f879e5501160b9eaa3f73f0e216c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 May 2025 15:50:31 +0300 +Subject: phy: renesas: rcar-gen3-usb2: Assert PLL reset on PHY power off + +From: Claudiu Beznea + +[ Upstream commit 9ce71e85b29eb63e48e294479742e670513f03a0 ] + +Assert PLL reset on PHY power off. This saves power. + +Fixes: f3b5a8d9b50d ("phy: rcar-gen3-usb2: Add R-Car Gen3 USB2 PHY driver") +Cc: stable@vger.kernel.org +Reviewed-by: Yoshihiro Shimoda +Tested-by: Yoshihiro Shimoda +Reviewed-by: Lad Prabhakar +Signed-off-by: Claudiu Beznea +Link: https://lore.kernel.org/r/20250507125032.565017-5-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/renesas/phy-rcar-gen3-usb2.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +index 188e903445aeb..b45aee8f59644 100644 +--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c ++++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +@@ -540,9 +540,17 @@ static int rcar_gen3_phy_usb2_power_off(struct phy *p) + struct rcar_gen3_chan *channel = rphy->ch; + int ret = 0; + +- scoped_guard(spinlock_irqsave, &channel->lock) ++ scoped_guard(spinlock_irqsave, &channel->lock) { + rphy->powered = false; + ++ if (rcar_gen3_are_all_rphys_power_off(channel)) { ++ u32 val = readl(channel->base + USB2_USBCTR); ++ ++ val |= USB2_USBCTR_PLL_RST; ++ writel(val, channel->base + USB2_USBCTR); ++ } ++ } ++ + if (channel->vbus) + ret = regulator_disable(channel->vbus); + +-- +2.39.5 + diff --git a/queue-6.12/phy-renesas-rcar-gen3-usb2-lock-around-hardware-regi.patch b/queue-6.12/phy-renesas-rcar-gen3-usb2-lock-around-hardware-regi.patch new file mode 100644 index 0000000000..947cbb187b --- /dev/null +++ b/queue-6.12/phy-renesas-rcar-gen3-usb2-lock-around-hardware-regi.patch @@ -0,0 +1,199 @@ +From 099423f96e7fe0f986f912b30dfe75783879fb0a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 May 2025 15:50:30 +0300 +Subject: phy: renesas: rcar-gen3-usb2: Lock around hardware registers and + driver data + +From: Claudiu Beznea + +[ Upstream commit 55a387ebb9219cbe4edfa8ba9996ccb0e7ad4932 ] + +The phy-rcar-gen3-usb2 driver exposes four individual PHYs that are +requested and configured by PHY users. The struct phy_ops APIs access the +same set of registers to configure all PHYs. Additionally, PHY settings can +be modified through sysfs or an IRQ handler. While some struct phy_ops APIs +are protected by a driver-wide mutex, others rely on individual +PHY-specific mutexes. + +This approach can lead to various issues, including: +1/ the IRQ handler may interrupt PHY settings in progress, racing with + hardware configuration protected by a mutex lock +2/ due to msleep(20) in rcar_gen3_init_otg(), while a configuration thread + suspends to wait for the delay, another thread may try to configure + another PHY (with phy_init() + phy_power_on()); re-running the + phy_init() goes to the exact same configuration code, re-running the + same hardware configuration on the same set of registers (and bits) + which might impact the result of the msleep for the 1st configuring + thread +3/ sysfs can configure the hardware (though role_store()) and it can + still race with the phy_init()/phy_power_on() APIs calling into the + drivers struct phy_ops + +To address these issues, add a spinlock to protect hardware register access +and driver private data structures (e.g., calls to +rcar_gen3_is_any_rphy_initialized()). Checking driver-specific data remains +necessary as all PHY instances share common settings. With this change, +the existing mutex protection is removed and the cleanup.h helpers are +used. + +While at it, to keep the code simpler, do not skip +regulator_enable()/regulator_disable() APIs in +rcar_gen3_phy_usb2_power_on()/rcar_gen3_phy_usb2_power_off() as the +regulators enable/disable operations are reference counted anyway. + +Fixes: f3b5a8d9b50d ("phy: rcar-gen3-usb2: Add R-Car Gen3 USB2 PHY driver") +Cc: stable@vger.kernel.org +Reviewed-by: Yoshihiro Shimoda +Tested-by: Yoshihiro Shimoda +Reviewed-by: Lad Prabhakar +Signed-off-by: Claudiu Beznea +Link: https://lore.kernel.org/r/20250507125032.565017-4-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Vinod Koul +Stable-dep-of: 9ce71e85b29e ("phy: renesas: rcar-gen3-usb2: Assert PLL reset on PHY power off") +Signed-off-by: Sasha Levin +--- + drivers/phy/renesas/phy-rcar-gen3-usb2.c | 49 +++++++++++++----------- + 1 file changed, 26 insertions(+), 23 deletions(-) + +diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +index 4cd1b6e677482..188e903445aeb 100644 +--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c ++++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +@@ -9,6 +9,7 @@ + * Copyright (C) 2014 Cogent Embedded, Inc. + */ + ++#include + #include + #include + #include +@@ -118,7 +119,7 @@ struct rcar_gen3_chan { + struct regulator *vbus; + struct reset_control *rstc; + struct work_struct work; +- struct mutex lock; /* protects rphys[...].powered */ ++ spinlock_t lock; /* protects access to hardware and driver data structure. */ + enum usb_dr_mode dr_mode; + u32 obint_enable_bits; + bool extcon_host; +@@ -348,6 +349,8 @@ static ssize_t role_store(struct device *dev, struct device_attribute *attr, + bool is_b_device; + enum phy_mode cur_mode, new_mode; + ++ guard(spinlock_irqsave)(&ch->lock); ++ + if (!ch->is_otg_channel || !rcar_gen3_is_any_otg_rphy_initialized(ch)) + return -EIO; + +@@ -415,7 +418,7 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch) + val = readl(usb2_base + USB2_ADPCTRL); + writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL); + } +- msleep(20); ++ mdelay(20); + + writel(0xffffffff, usb2_base + USB2_OBINTSTA); + writel(ch->obint_enable_bits, usb2_base + USB2_OBINTEN); +@@ -436,12 +439,14 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch) + if (pm_runtime_suspended(dev)) + goto rpm_put; + +- status = readl(usb2_base + USB2_OBINTSTA); +- if (status & ch->obint_enable_bits) { +- dev_vdbg(dev, "%s: %08x\n", __func__, status); +- writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA); +- rcar_gen3_device_recognition(ch); +- ret = IRQ_HANDLED; ++ scoped_guard(spinlock, &ch->lock) { ++ status = readl(usb2_base + USB2_OBINTSTA); ++ if (status & ch->obint_enable_bits) { ++ dev_vdbg(dev, "%s: %08x\n", __func__, status); ++ writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA); ++ rcar_gen3_device_recognition(ch); ++ ret = IRQ_HANDLED; ++ } + } + + rpm_put: +@@ -456,6 +461,8 @@ static int rcar_gen3_phy_usb2_init(struct phy *p) + void __iomem *usb2_base = channel->base; + u32 val; + ++ guard(spinlock_irqsave)(&channel->lock); ++ + /* Initialize USB2 part */ + val = readl(usb2_base + USB2_INT_ENABLE); + val |= USB2_INT_ENABLE_UCOM_INTEN | rphy->int_enable_bits; +@@ -482,6 +489,8 @@ static int rcar_gen3_phy_usb2_exit(struct phy *p) + void __iomem *usb2_base = channel->base; + u32 val; + ++ guard(spinlock_irqsave)(&channel->lock); ++ + rphy->initialized = false; + + val = readl(usb2_base + USB2_INT_ENABLE); +@@ -501,16 +510,17 @@ static int rcar_gen3_phy_usb2_power_on(struct phy *p) + u32 val; + int ret = 0; + +- mutex_lock(&channel->lock); +- if (!rcar_gen3_are_all_rphys_power_off(channel)) +- goto out; +- + if (channel->vbus) { + ret = regulator_enable(channel->vbus); + if (ret) +- goto out; ++ return ret; + } + ++ guard(spinlock_irqsave)(&channel->lock); ++ ++ if (!rcar_gen3_are_all_rphys_power_off(channel)) ++ goto out; ++ + val = readl(usb2_base + USB2_USBCTR); + val |= USB2_USBCTR_PLL_RST; + writel(val, usb2_base + USB2_USBCTR); +@@ -520,7 +530,6 @@ static int rcar_gen3_phy_usb2_power_on(struct phy *p) + out: + /* The powered flag should be set for any other phys anyway */ + rphy->powered = true; +- mutex_unlock(&channel->lock); + + return 0; + } +@@ -531,18 +540,12 @@ static int rcar_gen3_phy_usb2_power_off(struct phy *p) + struct rcar_gen3_chan *channel = rphy->ch; + int ret = 0; + +- mutex_lock(&channel->lock); +- rphy->powered = false; +- +- if (!rcar_gen3_are_all_rphys_power_off(channel)) +- goto out; ++ scoped_guard(spinlock_irqsave, &channel->lock) ++ rphy->powered = false; + + if (channel->vbus) + ret = regulator_disable(channel->vbus); + +-out: +- mutex_unlock(&channel->lock); +- + return ret; + } + +@@ -753,7 +756,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) + if (phy_data->no_adp_ctrl) + channel->obint_enable_bits = USB2_OBINT_IDCHG_EN; + +- mutex_init(&channel->lock); ++ spin_lock_init(&channel->lock); + for (i = 0; i < NUM_OF_PHYS; i++) { + channel->rphys[i].phy = devm_phy_create(dev, NULL, + phy_data->phy_usb2_ops); +-- +2.39.5 + diff --git a/queue-6.12/phy-renesas-rcar-gen3-usb2-move-irq-request-in-probe.patch b/queue-6.12/phy-renesas-rcar-gen3-usb2-move-irq-request-in-probe.patch new file mode 100644 index 0000000000..058c98f685 --- /dev/null +++ b/queue-6.12/phy-renesas-rcar-gen3-usb2-move-irq-request-in-probe.patch @@ -0,0 +1,144 @@ +From 1cfbe64823cd782cc08318490f59f3a92c7834db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 May 2025 15:50:29 +0300 +Subject: phy: renesas: rcar-gen3-usb2: Move IRQ request in probe + +From: Claudiu Beznea + +[ Upstream commit de76809f60cc938d3580bbbd5b04b7d12af6ce3a ] + +Commit 08b0ad375ca6 ("phy: renesas: rcar-gen3-usb2: move IRQ registration +to init") moved the IRQ request operation from probe to +struct phy_ops::phy_init API to avoid triggering interrupts (which lead to +register accesses) while the PHY clocks (enabled through runtime PM APIs) +are not active. If this happens, it results in a synchronous abort. + +One way to reproduce this issue is by enabling CONFIG_DEBUG_SHIRQ, which +calls free_irq() on driver removal. + +Move the IRQ request and free operations back to probe, and take the +runtime PM state into account in IRQ handler. This commit is preparatory +for the subsequent fixes in this series. + +Reviewed-by: Yoshihiro Shimoda +Tested-by: Yoshihiro Shimoda +Reviewed-by: Lad Prabhakar +Signed-off-by: Claudiu Beznea +Link: https://lore.kernel.org/r/20250507125032.565017-3-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Vinod Koul +Stable-dep-of: 9ce71e85b29e ("phy: renesas: rcar-gen3-usb2: Assert PLL reset on PHY power off") +Signed-off-by: Sasha Levin +--- + drivers/phy/renesas/phy-rcar-gen3-usb2.c | 46 +++++++++++++----------- + 1 file changed, 26 insertions(+), 20 deletions(-) + +diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +index 513fd35dcaa95..4cd1b6e677482 100644 +--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c ++++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +@@ -120,7 +120,6 @@ struct rcar_gen3_chan { + struct work_struct work; + struct mutex lock; /* protects rphys[...].powered */ + enum usb_dr_mode dr_mode; +- int irq; + u32 obint_enable_bits; + bool extcon_host; + bool is_otg_channel; +@@ -428,16 +427,25 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch) + { + struct rcar_gen3_chan *ch = _ch; + void __iomem *usb2_base = ch->base; +- u32 status = readl(usb2_base + USB2_OBINTSTA); ++ struct device *dev = ch->dev; + irqreturn_t ret = IRQ_NONE; ++ u32 status; + ++ pm_runtime_get_noresume(dev); ++ ++ if (pm_runtime_suspended(dev)) ++ goto rpm_put; ++ ++ status = readl(usb2_base + USB2_OBINTSTA); + if (status & ch->obint_enable_bits) { +- dev_vdbg(ch->dev, "%s: %08x\n", __func__, status); ++ dev_vdbg(dev, "%s: %08x\n", __func__, status); + writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA); + rcar_gen3_device_recognition(ch); + ret = IRQ_HANDLED; + } + ++rpm_put: ++ pm_runtime_put_noidle(dev); + return ret; + } + +@@ -447,17 +455,6 @@ static int rcar_gen3_phy_usb2_init(struct phy *p) + struct rcar_gen3_chan *channel = rphy->ch; + void __iomem *usb2_base = channel->base; + u32 val; +- int ret; +- +- if (!rcar_gen3_is_any_rphy_initialized(channel) && channel->irq >= 0) { +- INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work); +- ret = request_irq(channel->irq, rcar_gen3_phy_usb2_irq, +- IRQF_SHARED, dev_name(channel->dev), channel); +- if (ret < 0) { +- dev_err(channel->dev, "No irq handler (%d)\n", channel->irq); +- return ret; +- } +- } + + /* Initialize USB2 part */ + val = readl(usb2_base + USB2_INT_ENABLE); +@@ -493,9 +490,6 @@ static int rcar_gen3_phy_usb2_exit(struct phy *p) + val &= ~USB2_INT_ENABLE_UCOM_INTEN; + writel(val, usb2_base + USB2_INT_ENABLE); + +- if (channel->irq >= 0 && !rcar_gen3_is_any_rphy_initialized(channel)) +- free_irq(channel->irq, channel); +- + return 0; + } + +@@ -701,7 +695,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) + struct device *dev = &pdev->dev; + struct rcar_gen3_chan *channel; + struct phy_provider *provider; +- int ret = 0, i; ++ int ret = 0, i, irq; + + if (!dev->of_node) { + dev_err(dev, "This driver needs device tree\n"); +@@ -717,8 +711,6 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) + return PTR_ERR(channel->base); + + channel->obint_enable_bits = USB2_OBINT_BITS; +- /* get irq number here and request_irq for OTG in phy_init */ +- channel->irq = platform_get_irq_optional(pdev, 0); + channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node); + if (channel->dr_mode != USB_DR_MODE_UNKNOWN) { + channel->is_otg_channel = true; +@@ -787,6 +779,20 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) + channel->vbus = NULL; + } + ++ irq = platform_get_irq_optional(pdev, 0); ++ if (irq < 0 && irq != -ENXIO) { ++ ret = irq; ++ goto error; ++ } else if (irq > 0) { ++ INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work); ++ ret = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq, ++ IRQF_SHARED, dev_name(dev), channel); ++ if (ret < 0) { ++ dev_err(dev, "Failed to request irq (%d)\n", irq); ++ goto error; ++ } ++ } ++ + provider = devm_of_phy_provider_register(dev, rcar_gen3_phy_usb2_xlate); + if (IS_ERR(provider)) { + dev_err(dev, "Failed to register PHY provider\n"); +-- +2.39.5 + diff --git a/queue-6.12/phy-rockchip-usbdp-only-verify-link-rates-lanes-volt.patch b/queue-6.12/phy-rockchip-usbdp-only-verify-link-rates-lanes-volt.patch new file mode 100644 index 0000000000..5038e85f3e --- /dev/null +++ b/queue-6.12/phy-rockchip-usbdp-only-verify-link-rates-lanes-volt.patch @@ -0,0 +1,175 @@ +From d1d5f1410e92cfe5970889b29c1f4a2bdd9bc7ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 16:00:07 +0800 +Subject: phy: rockchip: usbdp: Only verify link rates/lanes/voltage when the + corresponding set flags are set + +From: Andy Yan + +[ Upstream commit 969a38be437b68dc9e12e3c3f08911c9f9c8be73 ] + +According documentation of phy_configure_opts_dp, at the configure +stage, link rates should only be verify/configure when set_rate +flag is set, the same applies to lanes and voltage. + +So do it as the documentation says. +Because voltage setting depends on the lanes, link rates set +previously, so record the link rates and lanes at it's verify stage. + +Signed-off-by: Andy Yan +Link: https://lore.kernel.org/r/20250312080041.524546-1-andyshrk@163.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/rockchip/phy-rockchip-usbdp.c | 87 ++++++++++++++--------- + 1 file changed, 53 insertions(+), 34 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c +index f5c6d264d89ed..d2021f7941e3e 100644 +--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c ++++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c +@@ -187,6 +187,8 @@ struct rk_udphy { + u32 dp_aux_din_sel; + bool dp_sink_hpd_sel; + bool dp_sink_hpd_cfg; ++ unsigned int link_rate; ++ unsigned int lanes; + u8 bw; + int id; + +@@ -1102,15 +1104,19 @@ static int rk_udphy_dp_phy_power_off(struct phy *phy) + return 0; + } + +-static int rk_udphy_dp_phy_verify_link_rate(unsigned int link_rate) ++/* ++ * Verify link rate ++ */ ++static int rk_udphy_dp_phy_verify_link_rate(struct rk_udphy *udphy, ++ struct phy_configure_opts_dp *dp) + { +- switch (link_rate) { ++ switch (dp->link_rate) { + case 1620: + case 2700: + case 5400: + case 8100: ++ udphy->link_rate = dp->link_rate; + break; +- + default: + return -EINVAL; + } +@@ -1118,45 +1124,44 @@ static int rk_udphy_dp_phy_verify_link_rate(unsigned int link_rate) + return 0; + } + +-static int rk_udphy_dp_phy_verify_config(struct rk_udphy *udphy, +- struct phy_configure_opts_dp *dp) ++static int rk_udphy_dp_phy_verify_lanes(struct rk_udphy *udphy, ++ struct phy_configure_opts_dp *dp) + { +- int i, ret; +- +- /* If changing link rate was required, verify it's supported. */ +- ret = rk_udphy_dp_phy_verify_link_rate(dp->link_rate); +- if (ret) +- return ret; +- +- /* Verify lane count. */ + switch (dp->lanes) { + case 1: + case 2: + case 4: + /* valid lane count. */ ++ udphy->lanes = dp->lanes; + break; + + default: + return -EINVAL; + } + +- /* +- * If changing voltages is required, check swing and pre-emphasis +- * levels, per-lane. +- */ +- if (dp->set_voltages) { +- /* Lane count verified previously. */ +- for (i = 0; i < dp->lanes; i++) { +- if (dp->voltage[i] > 3 || dp->pre[i] > 3) +- return -EINVAL; ++ return 0; ++} + +- /* +- * Sum of voltage swing and pre-emphasis levels cannot +- * exceed 3. +- */ +- if (dp->voltage[i] + dp->pre[i] > 3) +- return -EINVAL; +- } ++/* ++ * If changing voltages is required, check swing and pre-emphasis ++ * levels, per-lane. ++ */ ++static int rk_udphy_dp_phy_verify_voltages(struct rk_udphy *udphy, ++ struct phy_configure_opts_dp *dp) ++{ ++ int i; ++ ++ /* Lane count verified previously. */ ++ for (i = 0; i < udphy->lanes; i++) { ++ if (dp->voltage[i] > 3 || dp->pre[i] > 3) ++ return -EINVAL; ++ ++ /* ++ * Sum of voltage swing and pre-emphasis levels cannot ++ * exceed 3. ++ */ ++ if (dp->voltage[i] + dp->pre[i] > 3) ++ return -EINVAL; + } + + return 0; +@@ -1196,9 +1201,23 @@ static int rk_udphy_dp_phy_configure(struct phy *phy, + u32 i, val, lane; + int ret; + +- ret = rk_udphy_dp_phy_verify_config(udphy, dp); +- if (ret) +- return ret; ++ if (dp->set_rate) { ++ ret = rk_udphy_dp_phy_verify_link_rate(udphy, dp); ++ if (ret) ++ return ret; ++ } ++ ++ if (dp->set_lanes) { ++ ret = rk_udphy_dp_phy_verify_lanes(udphy, dp); ++ if (ret) ++ return ret; ++ } ++ ++ if (dp->set_voltages) { ++ ret = rk_udphy_dp_phy_verify_voltages(udphy, dp); ++ if (ret) ++ return ret; ++ } + + if (dp->set_rate) { + regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, +@@ -1243,9 +1262,9 @@ static int rk_udphy_dp_phy_configure(struct phy *phy, + } + + if (dp->set_voltages) { +- for (i = 0; i < dp->lanes; i++) { ++ for (i = 0; i < udphy->lanes; i++) { + lane = udphy->dp_lane_sel[i]; +- switch (dp->link_rate) { ++ switch (udphy->link_rate) { + case 1620: + case 2700: + regmap_update_bits(udphy->pma_regmap, +-- +2.39.5 + diff --git a/queue-6.12/pidfs-improve-multi-threaded-exec-and-premature-thre.patch b/queue-6.12/pidfs-improve-multi-threaded-exec-and-premature-thre.patch new file mode 100644 index 0000000000..fe0daee09e --- /dev/null +++ b/queue-6.12/pidfs-improve-multi-threaded-exec-and-premature-thre.patch @@ -0,0 +1,129 @@ +From 19f4b04c738203169f7d4ae792891d1766eca3ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Mar 2025 14:24:08 +0100 +Subject: pidfs: improve multi-threaded exec and premature thread-group leader + exit polling + +From: Christian Brauner + +[ Upstream commit 0fb482728ba1ee2130eaa461bf551f014447997c ] + +This is another attempt trying to make pidfd polling for multi-threaded +exec and premature thread-group leader exit consistent. + +A quick recap of these two cases: + +(1) During a multi-threaded exec by a subthread, i.e., non-thread-group + leader thread, all other threads in the thread-group including the + thread-group leader are killed and the struct pid of the + thread-group leader will be taken over by the subthread that called + exec. IOW, two tasks change their TIDs. + +(2) A premature thread-group leader exit means that the thread-group + leader exited before all of the other subthreads in the thread-group + have exited. + +Both cases lead to inconsistencies for pidfd polling with PIDFD_THREAD. +Any caller that holds a PIDFD_THREAD pidfd to the current thread-group +leader may or may not see an exit notification on the file descriptor +depending on when poll is performed. If the poll is performed before the +exec of the subthread has concluded an exit notification is generated +for the old thread-group leader. If the poll is performed after the exec +of the subthread has concluded no exit notification is generated for the +old thread-group leader. + +The correct behavior would be to simply not generate an exit +notification on the struct pid of a subhthread exec because the struct +pid is taken over by the subthread and thus remains alive. + +But this is difficult to handle because a thread-group may exit +prematurely as mentioned in (2). In that case an exit notification is +reliably generated but the subthreads may continue to run for an +indeterminate amount of time and thus also may exec at some point. + +So far there was no way to distinguish between (1) and (2) internally. +This tiny series tries to address this problem by discarding +PIDFD_THREAD notification on premature thread-group leader exit. + +If that works correctly then no exit notifications are generated for a +PIDFD_THREAD pidfd for a thread-group leader until all subthreads have +been reaped. If a subthread should exec aftewards no exit notification +will be generated until that task exits or it creates subthreads and +repeates the cycle. + +Co-Developed-by: Oleg Nesterov +Signed-off-by: Oleg Nesterov +Link: https://lore.kernel.org/r/20250320-work-pidfs-thread_group-v4-1-da678ce805bf@kernel.org +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/pidfs.c | 9 +++++---- + kernel/exit.c | 6 +++--- + kernel/signal.c | 3 +-- + 3 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/fs/pidfs.c b/fs/pidfs.c +index 80675b6bf8845..52b7e4f767327 100644 +--- a/fs/pidfs.c ++++ b/fs/pidfs.c +@@ -95,20 +95,21 @@ static void pidfd_show_fdinfo(struct seq_file *m, struct file *f) + static __poll_t pidfd_poll(struct file *file, struct poll_table_struct *pts) + { + struct pid *pid = pidfd_pid(file); +- bool thread = file->f_flags & PIDFD_THREAD; + struct task_struct *task; + __poll_t poll_flags = 0; + + poll_wait(file, &pid->wait_pidfd, pts); + /* +- * Depending on PIDFD_THREAD, inform pollers when the thread +- * or the whole thread-group exits. ++ * Don't wake waiters if the thread-group leader exited ++ * prematurely. They either get notified when the last subthread ++ * exits or not at all if one of the remaining subthreads execs ++ * and assumes the struct pid of the old thread-group leader. + */ + guard(rcu)(); + task = pid_task(pid, PIDTYPE_PID); + if (!task) + poll_flags = EPOLLIN | EPOLLRDNORM | EPOLLHUP; +- else if (task->exit_state && (thread || thread_group_empty(task))) ++ else if (task->exit_state && !delay_group_leader(task)) + poll_flags = EPOLLIN | EPOLLRDNORM; + + return poll_flags; +diff --git a/kernel/exit.c b/kernel/exit.c +index 9d888f26bf784..c94d23ccd1520 100644 +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -745,10 +745,10 @@ static void exit_notify(struct task_struct *tsk, int group_dead) + + tsk->exit_state = EXIT_ZOMBIE; + /* +- * sub-thread or delay_group_leader(), wake up the +- * PIDFD_THREAD waiters. ++ * Ignore thread-group leaders that exited before all ++ * subthreads did. + */ +- if (!thread_group_empty(tsk)) ++ if (!delay_group_leader(tsk)) + do_notify_pidfd(tsk); + + if (unlikely(tsk->ptrace)) { +diff --git a/kernel/signal.c b/kernel/signal.c +index 2ae45e6eb6bb8..468b589c39e69 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -2063,8 +2063,7 @@ bool do_notify_parent(struct task_struct *tsk, int sig) + WARN_ON_ONCE(!tsk->ptrace && + (tsk->group_leader != tsk || !thread_group_empty(tsk))); + /* +- * tsk is a group leader and has no threads, wake up the +- * non-PIDFD_THREAD waiters. ++ * Notify for thread-group leaders without subthreads. + */ + if (thread_group_empty(tsk)) + do_notify_pidfd(tsk); +-- +2.39.5 + diff --git a/queue-6.12/pinctrl-bcm281xx-use-unsigned-int-instead-of-bare-un.patch b/queue-6.12/pinctrl-bcm281xx-use-unsigned-int-instead-of-bare-un.patch new file mode 100644 index 0000000000..7f45144c85 --- /dev/null +++ b/queue-6.12/pinctrl-bcm281xx-use-unsigned-int-instead-of-bare-un.patch @@ -0,0 +1,177 @@ +From 1dd1a477ca53cf55649b1a987001f57e2f07f0c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 21:54:47 +0100 +Subject: pinctrl: bcm281xx: Use "unsigned int" instead of bare "unsigned" + +From: Artur Weber + +[ Upstream commit 07b5a2a13f4704c5eae3be7277ec54ffdba45f72 ] + +Replace uses of bare "unsigned" with "unsigned int" to fix checkpatch +warnings. No functional change. + +Signed-off-by: Artur Weber +Link: https://lore.kernel.org/20250303-bcm21664-pinctrl-v3-2-5f8b80e4ab51@gmail.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/bcm/pinctrl-bcm281xx.c | 44 +++++++++++++------------- + 1 file changed, 22 insertions(+), 22 deletions(-) + +diff --git a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c +index cf6efa9c0364a..a039b490cdb8e 100644 +--- a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c ++++ b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c +@@ -72,7 +72,7 @@ static enum bcm281xx_pin_type hdmi_pin = BCM281XX_PIN_TYPE_HDMI; + struct bcm281xx_pin_function { + const char *name; + const char * const *groups; +- const unsigned ngroups; ++ const unsigned int ngroups; + }; + + /* +@@ -84,10 +84,10 @@ struct bcm281xx_pinctrl_data { + + /* List of all pins */ + const struct pinctrl_pin_desc *pins; +- const unsigned npins; ++ const unsigned int npins; + + const struct bcm281xx_pin_function *functions; +- const unsigned nfunctions; ++ const unsigned int nfunctions; + + struct regmap *regmap; + }; +@@ -941,7 +941,7 @@ static struct bcm281xx_pinctrl_data bcm281xx_pinctrl = { + }; + + static inline enum bcm281xx_pin_type pin_type_get(struct pinctrl_dev *pctldev, +- unsigned pin) ++ unsigned int pin) + { + struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); + +@@ -985,7 +985,7 @@ static int bcm281xx_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) + } + + static const char *bcm281xx_pinctrl_get_group_name(struct pinctrl_dev *pctldev, +- unsigned group) ++ unsigned int group) + { + struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); + +@@ -993,9 +993,9 @@ static const char *bcm281xx_pinctrl_get_group_name(struct pinctrl_dev *pctldev, + } + + static int bcm281xx_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, +- unsigned group, ++ unsigned int group, + const unsigned **pins, +- unsigned *num_pins) ++ unsigned int *num_pins) + { + struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); + +@@ -1007,7 +1007,7 @@ static int bcm281xx_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, + + static void bcm281xx_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, +- unsigned offset) ++ unsigned int offset) + { + seq_printf(s, " %s", dev_name(pctldev->dev)); + } +@@ -1029,7 +1029,7 @@ static int bcm281xx_pinctrl_get_fcns_count(struct pinctrl_dev *pctldev) + } + + static const char *bcm281xx_pinctrl_get_fcn_name(struct pinctrl_dev *pctldev, +- unsigned function) ++ unsigned int function) + { + struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); + +@@ -1037,9 +1037,9 @@ static const char *bcm281xx_pinctrl_get_fcn_name(struct pinctrl_dev *pctldev, + } + + static int bcm281xx_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev, +- unsigned function, ++ unsigned int function, + const char * const **groups, +- unsigned * const num_groups) ++ unsigned int * const num_groups) + { + struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); + +@@ -1050,8 +1050,8 @@ static int bcm281xx_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev, + } + + static int bcm281xx_pinmux_set(struct pinctrl_dev *pctldev, +- unsigned function, +- unsigned group) ++ unsigned int function, ++ unsigned int group) + { + struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); + const struct bcm281xx_pin_function *f = &pdata->functions[function]; +@@ -1082,7 +1082,7 @@ static const struct pinmux_ops bcm281xx_pinctrl_pinmux_ops = { + }; + + static int bcm281xx_pinctrl_pin_config_get(struct pinctrl_dev *pctldev, +- unsigned pin, ++ unsigned int pin, + unsigned long *config) + { + return -ENOTSUPP; +@@ -1091,9 +1091,9 @@ static int bcm281xx_pinctrl_pin_config_get(struct pinctrl_dev *pctldev, + + /* Goes through the configs and update register val/mask */ + static int bcm281xx_std_pin_update(struct pinctrl_dev *pctldev, +- unsigned pin, ++ unsigned int pin, + unsigned long *configs, +- unsigned num_configs, ++ unsigned int num_configs, + u32 *val, + u32 *mask) + { +@@ -1207,9 +1207,9 @@ static const u16 bcm281xx_pullup_map[] = { + + /* Goes through the configs and update register val/mask */ + static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev, +- unsigned pin, ++ unsigned int pin, + unsigned long *configs, +- unsigned num_configs, ++ unsigned int num_configs, + u32 *val, + u32 *mask) + { +@@ -1277,9 +1277,9 @@ static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev, + + /* Goes through the configs and update register val/mask */ + static int bcm281xx_hdmi_pin_update(struct pinctrl_dev *pctldev, +- unsigned pin, ++ unsigned int pin, + unsigned long *configs, +- unsigned num_configs, ++ unsigned int num_configs, + u32 *val, + u32 *mask) + { +@@ -1321,9 +1321,9 @@ static int bcm281xx_hdmi_pin_update(struct pinctrl_dev *pctldev, + } + + static int bcm281xx_pinctrl_pin_config_set(struct pinctrl_dev *pctldev, +- unsigned pin, ++ unsigned int pin, + unsigned long *configs, +- unsigned num_configs) ++ unsigned int num_configs) + { + struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); + enum bcm281xx_pin_type pin_type; +-- +2.39.5 + diff --git a/queue-6.12/pinctrl-devicetree-do-not-goto-err-when-probing-hogs.patch b/queue-6.12/pinctrl-devicetree-do-not-goto-err-when-probing-hogs.patch new file mode 100644 index 0000000000..6655daf652 --- /dev/null +++ b/queue-6.12/pinctrl-devicetree-do-not-goto-err-when-probing-hogs.patch @@ -0,0 +1,110 @@ +From ece469a82c226eb09718e9738b2b1375ff0bc23f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jan 2025 18:00:09 +0100 +Subject: pinctrl: devicetree: do not goto err when probing hogs in + pinctrl_dt_to_map + +From: Valentin Caron + +[ Upstream commit c98868e816209e568c9d72023ba0bc1e4d96e611 ] + +Cross case in pinctrl framework make impossible to an hogged pin and +another, not hogged, used within the same device-tree node. For example +with this simplified device-tree : + + &pinctrl { + pinctrl_pin_1: pinctrl-pin-1 { + pins = "dummy-pinctrl-pin"; + }; + }; + + &rtc { + pinctrl-names = "default" + pinctrl-0 = <&pinctrl_pin_1 &rtc_pin_1> + + rtc_pin_1: rtc-pin-1 { + pins = "dummy-rtc-pin"; + }; + }; + +"pinctrl_pin_1" configuration is never set. This produces this path in +the code: + + really_probe() + pinctrl_bind_pins() + | devm_pinctrl_get() + | pinctrl_get() + | create_pinctrl() + | pinctrl_dt_to_map() + | // Hog pin create an abort for all pins of the node + | ret = dt_to_map_one_config() + | | /* Do not defer probing of hogs (circular loop) */ + | | if (np_pctldev == p->dev->of_node) + | | return -ENODEV; + | if (ret) + | goto err + | + call_driver_probe() + stm32_rtc_probe() + pinctrl_enable() + pinctrl_claim_hogs() + create_pinctrl() + for_each_maps(maps_node, i, map) + // Not hog pin is skipped + if (pctldev && strcmp(dev_name(pctldev->dev), + map->ctrl_dev_name)) + continue; + +At the first call of create_pinctrl() the hogged pin produces an abort to +avoid a defer of hogged pins. All other pin configurations are trashed. + +At the second call, create_pinctrl is now called with pctldev parameter to +get hogs, but in this context only hogs are set. And other pins are +skipped. + +To handle this, do not produce an abort in the first call of +create_pinctrl(). Classic pin configuration will be set in +pinctrl_bind_pins() context. And the hogged pin configuration will be set +in pinctrl_claim_hogs() context. + +Signed-off-by: Valentin Caron +Link: https://lore.kernel.org/20250116170009.2075544-1-valentin.caron@foss.st.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/devicetree.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c +index 6a94ecd6a8dea..0b7f74beb6a6a 100644 +--- a/drivers/pinctrl/devicetree.c ++++ b/drivers/pinctrl/devicetree.c +@@ -143,10 +143,14 @@ static int dt_to_map_one_config(struct pinctrl *p, + pctldev = get_pinctrl_dev_from_of_node(np_pctldev); + if (pctldev) + break; +- /* Do not defer probing of hogs (circular loop) */ ++ /* ++ * Do not defer probing of hogs (circular loop) ++ * ++ * Return 1 to let the caller catch the case. ++ */ + if (np_pctldev == p->dev->of_node) { + of_node_put(np_pctldev); +- return -ENODEV; ++ return 1; + } + } + of_node_put(np_pctldev); +@@ -265,6 +269,8 @@ int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev) + ret = dt_to_map_one_config(p, pctldev, statename, + np_config); + of_node_put(np_config); ++ if (ret == 1) ++ continue; + if (ret < 0) + goto err; + } +-- +2.39.5 + diff --git a/queue-6.12/pinctrl-meson-define-the-pull-up-down-resistor-value.patch b/queue-6.12/pinctrl-meson-define-the-pull-up-down-resistor-value.patch new file mode 100644 index 0000000000..b9b8f4b32f --- /dev/null +++ b/queue-6.12/pinctrl-meson-define-the-pull-up-down-resistor-value.patch @@ -0,0 +1,53 @@ +From e1d0d02dfcd535b2aa550e789a4b1edf170a66bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 29 Mar 2025 20:01:32 +0100 +Subject: pinctrl: meson: define the pull up/down resistor value as 60 kOhm + +From: Martin Blumenstingl + +[ Upstream commit e56088a13708757da68ad035269d69b93ac8c389 ] + +The public datasheets of the following Amlogic SoCs describe a typical +resistor value for the built-in pull up/down resistor: +- Meson8/8b/8m2: not documented +- GXBB (S905): 60 kOhm +- GXL (S905X): 60 kOhm +- GXM (S912): 60 kOhm +- G12B (S922X): 60 kOhm +- SM1 (S905D3): 60 kOhm + +The public G12B and SM1 datasheets additionally state min and max +values: +- min value: 50 kOhm for both, pull-up and pull-down +- max value for the pull-up: 70 kOhm +- max value for the pull-down: 130 kOhm + +Use 60 kOhm in the pinctrl-meson driver as well so it's shown in the +debugfs output. It may not be accurate for Meson8/8b/8m2 but in reality +60 kOhm is closer to the actual value than 1 Ohm. + +Signed-off-by: Martin Blumenstingl +Reviewed-by: Neil Armstrong +Link: https://lore.kernel.org/20250329190132.855196-1-martin.blumenstingl@googlemail.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/meson/pinctrl-meson.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c +index 253a0cc57e396..e5a32a0532eee 100644 +--- a/drivers/pinctrl/meson/pinctrl-meson.c ++++ b/drivers/pinctrl/meson/pinctrl-meson.c +@@ -487,7 +487,7 @@ static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin, + case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_PULL_UP: + if (meson_pinconf_get_pull(pc, pin) == param) +- arg = 1; ++ arg = 60000; + else + return -EINVAL; + break; +-- +2.39.5 + diff --git a/queue-6.12/pinctrl-renesas-rzg2l-add-suspend-resume-support-for.patch b/queue-6.12/pinctrl-renesas-rzg2l-add-suspend-resume-support-for.patch new file mode 100644 index 0000000000..cc4080e2bd --- /dev/null +++ b/queue-6.12/pinctrl-renesas-rzg2l-add-suspend-resume-support-for.patch @@ -0,0 +1,92 @@ +From 97275c2ed34285ae55d6467f27d8f3597fc0067c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 12:01:16 +0200 +Subject: pinctrl: renesas: rzg2l: Add suspend/resume support for pull up/down + +From: Claudiu Beznea + +[ Upstream commit b2bd65fbb617353e3c46ba5206b3b030fa0f260c ] + +The Renesas RZ/G3S supports a power-saving mode where power to most of +the SoC components is lost, including the PIN controller. Save and +restore the pull-up/pull-down register contents to ensure the +functionality is preserved after a suspend/resume cycle. + +Signed-off-by: Claudiu Beznea +Reviewed-by: Lad Prabhakar +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/20250205100116.2032765-1-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/renesas/pinctrl-rzg2l.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +index d90685cfe2e1a..bde58f5a743cb 100644 +--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c ++++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +@@ -311,6 +311,7 @@ struct rzg2l_pinctrl_pin_settings { + * @pmc: PMC registers cache + * @pfc: PFC registers cache + * @iolh: IOLH registers cache ++ * @pupd: PUPD registers cache + * @ien: IEN registers cache + * @sd_ch: SD_CH registers cache + * @eth_poc: ET_POC registers cache +@@ -324,6 +325,7 @@ struct rzg2l_pinctrl_reg_cache { + u32 *pfc; + u32 *iolh[2]; + u32 *ien[2]; ++ u32 *pupd[2]; + u8 sd_ch[2]; + u8 eth_poc[2]; + u8 eth_mode; +@@ -2539,6 +2541,11 @@ static int rzg2l_pinctrl_reg_cache_alloc(struct rzg2l_pinctrl *pctrl) + if (!cache->ien[i]) + return -ENOMEM; + ++ cache->pupd[i] = devm_kcalloc(pctrl->dev, nports, sizeof(*cache->pupd[i]), ++ GFP_KERNEL); ++ if (!cache->pupd[i]) ++ return -ENOMEM; ++ + /* Allocate dedicated cache. */ + dedicated_cache->iolh[i] = devm_kcalloc(pctrl->dev, n_dedicated_pins, + sizeof(*dedicated_cache->iolh[i]), +@@ -2779,7 +2786,7 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen + struct rzg2l_pinctrl_reg_cache *cache = pctrl->cache; + + for (u32 port = 0; port < nports; port++) { +- bool has_iolh, has_ien; ++ bool has_iolh, has_ien, has_pupd; + u32 off, caps; + u8 pincnt; + u64 cfg; +@@ -2791,6 +2798,7 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen + caps = FIELD_GET(PIN_CFG_MASK, cfg); + has_iolh = !!(caps & (PIN_CFG_IOLH_A | PIN_CFG_IOLH_B | PIN_CFG_IOLH_C)); + has_ien = !!(caps & PIN_CFG_IEN); ++ has_pupd = !!(caps & PIN_CFG_PUPD); + + if (suspend) + RZG2L_PCTRL_REG_ACCESS32(suspend, pctrl->base + PFC(off), cache->pfc[port]); +@@ -2809,6 +2817,15 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen + } + } + ++ if (has_pupd) { ++ RZG2L_PCTRL_REG_ACCESS32(suspend, pctrl->base + PUPD(off), ++ cache->pupd[0][port]); ++ if (pincnt >= 4) { ++ RZG2L_PCTRL_REG_ACCESS32(suspend, pctrl->base + PUPD(off), ++ cache->pupd[1][port]); ++ } ++ } ++ + RZG2L_PCTRL_REG_ACCESS16(suspend, pctrl->base + PM(off), cache->pm[port]); + RZG2L_PCTRL_REG_ACCESS8(suspend, pctrl->base + P(off), cache->p[port]); + +-- +2.39.5 + diff --git a/queue-6.12/pinctrl-sophgo-avoid-to-modify-untouched-bit-when-se.patch b/queue-6.12/pinctrl-sophgo-avoid-to-modify-untouched-bit-when-se.patch new file mode 100644 index 0000000000..e0d4f5b345 --- /dev/null +++ b/queue-6.12/pinctrl-sophgo-avoid-to-modify-untouched-bit-when-se.patch @@ -0,0 +1,162 @@ +From d43a1dd0704dbaaae59881429a3f00217c347197 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 13:17:49 +0800 +Subject: pinctrl: sophgo: avoid to modify untouched bit when setting cv1800 + pinconf + +From: Inochi Amaoto + +[ Upstream commit ef1a5121ae3da02372fcb66d9632ed3d47ad5637 ] + +When setting pinconf configuration for cv1800 SoC, the driver just writes +the value. It may zero some bits of the pinconf register and cause some +unexpected error. Add a mask to avoid this. + +Signed-off-by: Inochi Amaoto +Link: https://lore.kernel.org/20250211051801.470800-2-inochiama@gmail.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/sophgo/pinctrl-cv18xx.c | 33 +++++++++++++++++-------- + 1 file changed, 23 insertions(+), 10 deletions(-) + +diff --git a/drivers/pinctrl/sophgo/pinctrl-cv18xx.c b/drivers/pinctrl/sophgo/pinctrl-cv18xx.c +index 57f2674e75d68..84b4850771ce2 100644 +--- a/drivers/pinctrl/sophgo/pinctrl-cv18xx.c ++++ b/drivers/pinctrl/sophgo/pinctrl-cv18xx.c +@@ -574,10 +574,10 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl, + struct cv1800_pin *pin, + unsigned long *configs, + unsigned int num_configs, +- u32 *value) ++ u32 *value, u32 *mask) + { + int i; +- u32 v = 0; ++ u32 v = 0, m = 0; + enum cv1800_pin_io_type type; + int ret; + +@@ -596,10 +596,12 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl, + case PIN_CONFIG_BIAS_PULL_DOWN: + v &= ~PIN_IO_PULLDOWN; + v |= FIELD_PREP(PIN_IO_PULLDOWN, arg); ++ m |= PIN_IO_PULLDOWN; + break; + case PIN_CONFIG_BIAS_PULL_UP: + v &= ~PIN_IO_PULLUP; + v |= FIELD_PREP(PIN_IO_PULLUP, arg); ++ m |= PIN_IO_PULLUP; + break; + case PIN_CONFIG_DRIVE_STRENGTH_UA: + ret = cv1800_pinctrl_oc2reg(pctrl, pin, arg); +@@ -607,6 +609,7 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl, + return ret; + v &= ~PIN_IO_DRIVE; + v |= FIELD_PREP(PIN_IO_DRIVE, ret); ++ m |= PIN_IO_DRIVE; + break; + case PIN_CONFIG_INPUT_SCHMITT_UV: + ret = cv1800_pinctrl_schmitt2reg(pctrl, pin, arg); +@@ -614,6 +617,7 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl, + return ret; + v &= ~PIN_IO_SCHMITT; + v |= FIELD_PREP(PIN_IO_SCHMITT, ret); ++ m |= PIN_IO_SCHMITT; + break; + case PIN_CONFIG_POWER_SOURCE: + /* Ignore power source as it is always fixed */ +@@ -621,10 +625,12 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl, + case PIN_CONFIG_SLEW_RATE: + v &= ~PIN_IO_OUT_FAST_SLEW; + v |= FIELD_PREP(PIN_IO_OUT_FAST_SLEW, arg); ++ m |= PIN_IO_OUT_FAST_SLEW; + break; + case PIN_CONFIG_BIAS_BUS_HOLD: + v &= ~PIN_IO_BUS_HOLD; + v |= FIELD_PREP(PIN_IO_BUS_HOLD, arg); ++ m |= PIN_IO_BUS_HOLD; + break; + default: + return -ENOTSUPP; +@@ -632,17 +638,19 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl, + } + + *value = v; ++ *mask = m; + + return 0; + } + + static int cv1800_pin_set_config(struct cv1800_pinctrl *pctrl, + unsigned int pin_id, +- u32 value) ++ u32 value, u32 mask) + { + struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id); + unsigned long flags; + void __iomem *addr; ++ u32 reg; + + if (!pin) + return -EINVAL; +@@ -650,7 +658,10 @@ static int cv1800_pin_set_config(struct cv1800_pinctrl *pctrl, + addr = cv1800_pinctrl_get_component_addr(pctrl, &pin->conf); + + raw_spin_lock_irqsave(&pctrl->lock, flags); +- writel(value, addr); ++ reg = readl(addr); ++ reg &= ~mask; ++ reg |= value; ++ writel(reg, addr); + raw_spin_unlock_irqrestore(&pctrl->lock, flags); + + return 0; +@@ -662,16 +673,17 @@ static int cv1800_pconf_set(struct pinctrl_dev *pctldev, + { + struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id); +- u32 value; ++ u32 value, mask; + + if (!pin) + return -ENODEV; + + if (cv1800_pinconf_compute_config(pctrl, pin, +- configs, num_configs, &value)) ++ configs, num_configs, ++ &value, &mask)) + return -ENOTSUPP; + +- return cv1800_pin_set_config(pctrl, pin_id, value); ++ return cv1800_pin_set_config(pctrl, pin_id, value, mask); + } + + static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev, +@@ -682,7 +694,7 @@ static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev, + struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + const struct group_desc *group; + const struct cv1800_pin_mux_config *pinmuxs; +- u32 value; ++ u32 value, mask; + int i; + + group = pinctrl_generic_get_group(pctldev, gsel); +@@ -692,11 +704,12 @@ static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev, + pinmuxs = group->data; + + if (cv1800_pinconf_compute_config(pctrl, pinmuxs[0].pin, +- configs, num_configs, &value)) ++ configs, num_configs, ++ &value, &mask)) + return -ENOTSUPP; + + for (i = 0; i < group->grp.npins; i++) +- cv1800_pin_set_config(pctrl, group->grp.pins[i], value); ++ cv1800_pin_set_config(pctrl, group->grp.pins[i], value, mask); + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.12/pinctrl-tegra-restore-sfsel-bit-when-freeing-pins.patch b/queue-6.12/pinctrl-tegra-restore-sfsel-bit-when-freeing-pins.patch new file mode 100644 index 0000000000..de1258aab0 --- /dev/null +++ b/queue-6.12/pinctrl-tegra-restore-sfsel-bit-when-freeing-pins.patch @@ -0,0 +1,183 @@ +From f83ff5ff7d6c27fc4bcf3359bf3ea69abe6a9ae5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 16:19:39 +0530 +Subject: pinctrl-tegra: Restore SFSEL bit when freeing pins + +From: Prathamesh Shete + +[ Upstream commit c12bfa0fee65940b10ff5187349f76c6f6b1df9c ] + +Each pin can be configured as a Special Function IO (SFIO) or GPIO, +where the SFIO enables the pin to operate in alternative modes such as +I2C, SPI, etc. + +The current implementation sets all the pins back to SFIO mode +even if they were initially in GPIO mode. This can cause glitches +on the pins when pinctrl_gpio_free() is called. + +Avoid these undesired glitches by storing the pin's SFIO/GPIO +state on GPIO request and restoring it on GPIO free. + +Signed-off-by: Prathamesh Shete +Link: https://lore.kernel.org/20250305104939.15168-2-pshete@nvidia.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/tegra/pinctrl-tegra.c | 59 +++++++++++++++++++++++---- + drivers/pinctrl/tegra/pinctrl-tegra.h | 6 +++ + 2 files changed, 57 insertions(+), 8 deletions(-) + +diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c +index 3b046450bd3ff..27823e4207347 100644 +--- a/drivers/pinctrl/tegra/pinctrl-tegra.c ++++ b/drivers/pinctrl/tegra/pinctrl-tegra.c +@@ -278,8 +278,8 @@ static int tegra_pinctrl_set_mux(struct pinctrl_dev *pctldev, + return 0; + } + +-static const struct tegra_pingroup *tegra_pinctrl_get_group(struct pinctrl_dev *pctldev, +- unsigned int offset) ++static int tegra_pinctrl_get_group_index(struct pinctrl_dev *pctldev, ++ unsigned int offset) + { + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + unsigned int group, num_pins, j; +@@ -292,12 +292,35 @@ static const struct tegra_pingroup *tegra_pinctrl_get_group(struct pinctrl_dev * + continue; + for (j = 0; j < num_pins; j++) { + if (offset == pins[j]) +- return &pmx->soc->groups[group]; ++ return group; + } + } + +- dev_err(pctldev->dev, "Pingroup not found for pin %u\n", offset); +- return NULL; ++ return -EINVAL; ++} ++ ++static const struct tegra_pingroup *tegra_pinctrl_get_group(struct pinctrl_dev *pctldev, ++ unsigned int offset, ++ int group_index) ++{ ++ struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); ++ ++ if (group_index < 0 || group_index > pmx->soc->ngroups) ++ return NULL; ++ ++ return &pmx->soc->groups[group_index]; ++} ++ ++static struct tegra_pingroup_config *tegra_pinctrl_get_group_config(struct pinctrl_dev *pctldev, ++ unsigned int offset, ++ int group_index) ++{ ++ struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); ++ ++ if (group_index < 0) ++ return NULL; ++ ++ return &pmx->pingroup_configs[group_index]; + } + + static int tegra_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev, +@@ -306,12 +329,15 @@ static int tegra_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev, + { + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + const struct tegra_pingroup *group; ++ struct tegra_pingroup_config *config; ++ int group_index; + u32 value; + + if (!pmx->soc->sfsel_in_mux) + return 0; + +- group = tegra_pinctrl_get_group(pctldev, offset); ++ group_index = tegra_pinctrl_get_group_index(pctldev, offset); ++ group = tegra_pinctrl_get_group(pctldev, offset, group_index); + + if (!group) + return -EINVAL; +@@ -319,7 +345,11 @@ static int tegra_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev, + if (group->mux_reg < 0 || group->sfsel_bit < 0) + return -EINVAL; + ++ config = tegra_pinctrl_get_group_config(pctldev, offset, group_index); ++ if (!config) ++ return -EINVAL; + value = pmx_readl(pmx, group->mux_bank, group->mux_reg); ++ config->is_sfsel = (value & BIT(group->sfsel_bit)) != 0; + value &= ~BIT(group->sfsel_bit); + pmx_writel(pmx, value, group->mux_bank, group->mux_reg); + +@@ -332,12 +362,15 @@ static void tegra_pinctrl_gpio_disable_free(struct pinctrl_dev *pctldev, + { + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + const struct tegra_pingroup *group; ++ struct tegra_pingroup_config *config; ++ int group_index; + u32 value; + + if (!pmx->soc->sfsel_in_mux) + return; + +- group = tegra_pinctrl_get_group(pctldev, offset); ++ group_index = tegra_pinctrl_get_group_index(pctldev, offset); ++ group = tegra_pinctrl_get_group(pctldev, offset, group_index); + + if (!group) + return; +@@ -345,8 +378,12 @@ static void tegra_pinctrl_gpio_disable_free(struct pinctrl_dev *pctldev, + if (group->mux_reg < 0 || group->sfsel_bit < 0) + return; + ++ config = tegra_pinctrl_get_group_config(pctldev, offset, group_index); ++ if (!config) ++ return; + value = pmx_readl(pmx, group->mux_bank, group->mux_reg); +- value |= BIT(group->sfsel_bit); ++ if (config->is_sfsel) ++ value |= BIT(group->sfsel_bit); + pmx_writel(pmx, value, group->mux_bank, group->mux_reg); + } + +@@ -791,6 +828,12 @@ int tegra_pinctrl_probe(struct platform_device *pdev, + pmx->dev = &pdev->dev; + pmx->soc = soc_data; + ++ pmx->pingroup_configs = devm_kcalloc(&pdev->dev, ++ pmx->soc->ngroups, sizeof(*pmx->pingroup_configs), ++ GFP_KERNEL); ++ if (!pmx->pingroup_configs) ++ return -ENOMEM; ++ + /* + * Each mux group will appear in 4 functions' list of groups. + * This over-allocates slightly, since not all groups are mux groups. +diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.h b/drivers/pinctrl/tegra/pinctrl-tegra.h +index b3289bdf727d8..b97136685f7a8 100644 +--- a/drivers/pinctrl/tegra/pinctrl-tegra.h ++++ b/drivers/pinctrl/tegra/pinctrl-tegra.h +@@ -8,6 +8,10 @@ + #ifndef __PINMUX_TEGRA_H__ + #define __PINMUX_TEGRA_H__ + ++struct tegra_pingroup_config { ++ bool is_sfsel; ++}; ++ + struct tegra_pmx { + struct device *dev; + struct pinctrl_dev *pctl; +@@ -21,6 +25,8 @@ struct tegra_pmx { + int nbanks; + void __iomem **regs; + u32 *backup_regs; ++ /* Array of size soc->ngroups */ ++ struct tegra_pingroup_config *pingroup_configs; + }; + + enum tegra_pinconf_param { +-- +2.39.5 + diff --git a/queue-6.12/platform-x86-asus-wmi-disable-oobe-state-after-resum.patch b/queue-6.12/platform-x86-asus-wmi-disable-oobe-state-after-resum.patch new file mode 100644 index 0000000000..6a917ed62e --- /dev/null +++ b/queue-6.12/platform-x86-asus-wmi-disable-oobe-state-after-resum.patch @@ -0,0 +1,72 @@ +From eb252db794cdfab455f76fca78117ce390be075e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Apr 2025 20:06:08 +0600 +Subject: platform/x86: asus-wmi: Disable OOBE state after resume from + hibernation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pavel Nikulin + +[ Upstream commit 77bdac73754e4c0c564c1ca80fe3d9c93b0e715a ] + +ASUS firmware resets OOBE state during S4 suspend, so the keyboard +blinks during resume from hibernation. This patch disables OOBE state +after resume from hibernation. + +Signed-off-by: Pavel Nikulin +Link: https://lore.kernel.org/r/20250418140706.1691-1-pavel@noa-labs.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/asus-wmi.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index a1cff9ff35a92..9d79c5ea8b495 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -304,6 +304,7 @@ struct asus_wmi { + + u32 kbd_rgb_dev; + bool kbd_rgb_state_available; ++ bool oobe_state_available; + + u8 throttle_thermal_policy_mode; + u32 throttle_thermal_policy_dev; +@@ -1826,7 +1827,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus) + goto error; + } + +- if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_OOBE)) { ++ if (asus->oobe_state_available) { + /* + * Disable OOBE state, so that e.g. the keyboard backlight + * works. +@@ -4741,6 +4742,7 @@ static int asus_wmi_add(struct platform_device *pdev) + asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU); + asus->dgpu_disable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU); + asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE); ++ asus->oobe_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_OOBE); + asus->ally_mcu_usb_switch = acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE) + && dmi_check_system(asus_ally_mcu_quirk); + +@@ -4994,6 +4996,13 @@ static int asus_hotk_restore(struct device *device) + } + if (!IS_ERR_OR_NULL(asus->kbd_led.dev)) + kbd_led_update(asus); ++ if (asus->oobe_state_available) { ++ /* ++ * Disable OOBE state, so that e.g. the keyboard backlight ++ * works. ++ */ ++ asus_wmi_set_devstate(ASUS_WMI_DEVID_OOBE, 1, NULL); ++ } + + if (asus_wmi_has_fnlock_key(asus)) + asus_wmi_fnlock_update(asus); +-- +2.39.5 + diff --git a/queue-6.12/platform-x86-ideapad-laptop-add-support-for-some-new.patch b/queue-6.12/platform-x86-ideapad-laptop-add-support-for-some-new.patch new file mode 100644 index 0000000000..c2cdeda6d3 --- /dev/null +++ b/queue-6.12/platform-x86-ideapad-laptop-add-support-for-some-new.patch @@ -0,0 +1,63 @@ +From 33245ee3fc8993631eb03cd2460209242da51704 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Apr 2025 09:07:38 +0200 +Subject: platform/x86: ideapad-laptop: add support for some new buttons +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: GaÅ¡per Nemgar + +[ Upstream commit 02c6e43397c39edd0c172859bf8c851b46be09a8 ] + +Add entries to unsupported WMI codes in ideapad_keymap[] and one +check for WMI code 0x13d to trigger platform_profile_cycle(). + +Signed-off-by: GaÅ¡per Nemgar +Reviewed-by: Hans de Goede +Link: https://lore.kernel.org/r/20250418070738.7171-1-gasper.nemgar@gmail.com +[ij: joined nested if ()s & major tweaks to changelog] +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/ideapad-laptop.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c +index c908f52ed717b..bdb4cbee42058 100644 +--- a/drivers/platform/x86/ideapad-laptop.c ++++ b/drivers/platform/x86/ideapad-laptop.c +@@ -1297,6 +1297,16 @@ static const struct key_entry ideapad_keymap[] = { + /* Specific to some newer models */ + { KE_KEY, 0x3e | IDEAPAD_WMI_KEY, { KEY_MICMUTE } }, + { KE_KEY, 0x3f | IDEAPAD_WMI_KEY, { KEY_RFKILL } }, ++ /* Star- (User Assignable Key) */ ++ { KE_KEY, 0x44 | IDEAPAD_WMI_KEY, { KEY_PROG1 } }, ++ /* Eye */ ++ { KE_KEY, 0x45 | IDEAPAD_WMI_KEY, { KEY_PROG3 } }, ++ /* Performance toggle also Fn+Q, handled inside ideapad_wmi_notify() */ ++ { KE_KEY, 0x3d | IDEAPAD_WMI_KEY, { KEY_PROG4 } }, ++ /* shift + prtsc */ ++ { KE_KEY, 0x2d | IDEAPAD_WMI_KEY, { KEY_CUT } }, ++ { KE_KEY, 0x29 | IDEAPAD_WMI_KEY, { KEY_TOUCHPAD_TOGGLE } }, ++ { KE_KEY, 0x2a | IDEAPAD_WMI_KEY, { KEY_ROOT_MENU } }, + + { KE_END }, + }; +@@ -2083,6 +2093,12 @@ static void ideapad_wmi_notify(struct wmi_device *wdev, union acpi_object *data) + dev_dbg(&wdev->dev, "WMI fn-key event: 0x%llx\n", + data->integer.value); + ++ /* performance button triggered by 0x3d */ ++ if (data->integer.value == 0x3d && priv->dytc) { ++ platform_profile_cycle(); ++ break; ++ } ++ + /* 0x02 FnLock, 0x03 Esc */ + if (data->integer.value == 0x02 || data->integer.value == 0x03) + ideapad_fn_lock_led_notify(priv, data->integer.value == 0x02); +-- +2.39.5 + diff --git a/queue-6.12/platform-x86-intel-hid-add-pantherlake-support.patch b/queue-6.12/platform-x86-intel-hid-add-pantherlake-support.patch new file mode 100644 index 0000000000..895deb3815 --- /dev/null +++ b/queue-6.12/platform-x86-intel-hid-add-pantherlake-support.patch @@ -0,0 +1,62 @@ +From 8a3e7ef184be24d0af94eeb22161c4ff4f4f8b7a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Apr 2025 09:43:32 +0530 +Subject: platform/x86/intel: hid: Add Pantherlake support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Saranya Gopal + +[ Upstream commit 12df9ec3e1955aed6a0c839f2375cd8e5d5150cf ] + +Add Pantherlake ACPI device ID to the Intel HID driver. + +While there, clean up the device ID table to remove the ", 0" parts. + +Suggested-by: Andy Shevchenko +Signed-off-by: Saranya Gopal +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20250421041332.830136-1-saranya.gopal@intel.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel/hid.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +diff --git a/drivers/platform/x86/intel/hid.c b/drivers/platform/x86/intel/hid.c +index 9a609358956f3..59392f1a0d8ad 100644 +--- a/drivers/platform/x86/intel/hid.c ++++ b/drivers/platform/x86/intel/hid.c +@@ -44,16 +44,17 @@ MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Alex Hung"); + + static const struct acpi_device_id intel_hid_ids[] = { +- {"INT33D5", 0}, +- {"INTC1051", 0}, +- {"INTC1054", 0}, +- {"INTC1070", 0}, +- {"INTC1076", 0}, +- {"INTC1077", 0}, +- {"INTC1078", 0}, +- {"INTC107B", 0}, +- {"INTC10CB", 0}, +- {"", 0}, ++ { "INT33D5" }, ++ { "INTC1051" }, ++ { "INTC1054" }, ++ { "INTC1070" }, ++ { "INTC1076" }, ++ { "INTC1077" }, ++ { "INTC1078" }, ++ { "INTC107B" }, ++ { "INTC10CB" }, ++ { "INTC10CC" }, ++ { } + }; + MODULE_DEVICE_TABLE(acpi, intel_hid_ids); + +-- +2.39.5 + diff --git a/queue-6.12/pmdomain-imx-gpcv2-use-proper-helper-for-property-de.patch b/queue-6.12/pmdomain-imx-gpcv2-use-proper-helper-for-property-de.patch new file mode 100644 index 0000000000..6ae984096c --- /dev/null +++ b/queue-6.12/pmdomain-imx-gpcv2-use-proper-helper-for-property-de.patch @@ -0,0 +1,40 @@ +From de711920f8d279953913570b5a7956c633dcc3ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 20:18:32 +0100 +Subject: pmdomain: imx: gpcv2: use proper helper for property detection + +From: Ahmad Fatoum + +[ Upstream commit 6568cb40e73163fa25e2779f7234b169b2e1a32e ] + +Starting with commit c141ecc3cecd7 ("of: Warn when of_property_read_bool() +is used on non-boolean properties"), probing the gpcv2 device on i.MX8M +SoCs leads to warnings when LOCKDEP is enabled. + +Fix this by checking property presence with of_property_present as +intended. + +Signed-off-by: Ahmad Fatoum +Link: https://lore.kernel.org/r/20250218-gpcv2-of-property-present-v1-1-3bb1a9789654@pengutronix.de +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/pmdomain/imx/gpcv2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pmdomain/imx/gpcv2.c b/drivers/pmdomain/imx/gpcv2.c +index e03c2cb39a693..0dbf1893abfa3 100644 +--- a/drivers/pmdomain/imx/gpcv2.c ++++ b/drivers/pmdomain/imx/gpcv2.c +@@ -1361,7 +1361,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev) + } + + if (IS_ENABLED(CONFIG_LOCKDEP) && +- of_property_read_bool(domain->dev->of_node, "power-domains")) ++ of_property_present(domain->dev->of_node, "power-domains")) + lockdep_set_subclass(&domain->genpd.mlock, 1); + + ret = of_genpd_add_provider_simple(domain->dev->of_node, +-- +2.39.5 + diff --git a/queue-6.12/pnfs-flexfiles-report-enetdown-as-a-connection-error.patch b/queue-6.12/pnfs-flexfiles-report-enetdown-as-a-connection-error.patch new file mode 100644 index 0000000000..42ccdad9f2 --- /dev/null +++ b/queue-6.12/pnfs-flexfiles-report-enetdown-as-a-connection-error.patch @@ -0,0 +1,37 @@ +From df0905a10288d4ab80af6bb88942ad8b8269df3f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Mar 2025 12:45:01 -0400 +Subject: pNFS/flexfiles: Report ENETDOWN as a connection error + +From: Trond Myklebust + +[ Upstream commit aa42add73ce9b9e3714723d385c254b75814e335 ] + +If the client should see an ENETDOWN when trying to connect to the data +server, it might still be able to talk to the metadata server through +another NIC. If so, report the error. + +Signed-off-by: Trond Myklebust +Reviewed-by: Jeff Layton +Tested-by: Jeff Layton +Acked-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfs/flexfilelayout/flexfilelayout.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c +index a1cfe4cc60c4b..8f7ea4076653d 100644 +--- a/fs/nfs/flexfilelayout/flexfilelayout.c ++++ b/fs/nfs/flexfilelayout/flexfilelayout.c +@@ -1263,6 +1263,7 @@ static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg, + case -ECONNRESET: + case -EHOSTDOWN: + case -EHOSTUNREACH: ++ case -ENETDOWN: + case -ENETUNREACH: + case -EADDRINUSE: + case -ENOBUFS: +-- +2.39.5 + diff --git a/queue-6.12/pnp-expand-length-of-fixup-id-string.patch b/queue-6.12/pnp-expand-length-of-fixup-id-string.patch new file mode 100644 index 0000000000..bd9c19649c --- /dev/null +++ b/queue-6.12/pnp-expand-length-of-fixup-id-string.patch @@ -0,0 +1,39 @@ +From b306e9779eeecc72b2e7d41f7cca776c1d481e49 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 15:24:33 -0700 +Subject: PNP: Expand length of fixup id string + +From: Kees Cook + +[ Upstream commit 425b1c97b07f2290700f708edabef32861e2b2db ] + +GCC 15's -Wunterminated-string-initialization saw that "id" was not +including the required trailing NUL character. Instead of marking "id" +with __nonstring[1], expand the length of the string as it is used in +(debugging) format strings that expect a properly formed C string. + +Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117178 [1] +Signed-off-by: Kees Cook +Link: https://patch.msgid.link/20250310222432.work.826-kees@kernel.org +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + include/linux/pnp.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/pnp.h b/include/linux/pnp.h +index b7a7158aaf65e..23fe3eaf242d6 100644 +--- a/include/linux/pnp.h ++++ b/include/linux/pnp.h +@@ -290,7 +290,7 @@ static inline void pnp_set_drvdata(struct pnp_dev *pdev, void *data) + } + + struct pnp_fixup { +- char id[7]; ++ char id[8]; + void (*quirk_function) (struct pnp_dev *dev); /* fixup function */ + }; + +-- +2.39.5 + diff --git a/queue-6.12/posix-timers-add-cond_resched-to-posix_timer_add-sea.patch b/queue-6.12/posix-timers-add-cond_resched-to-posix_timer_add-sea.patch new file mode 100644 index 0000000000..1eaf05269b --- /dev/null +++ b/queue-6.12/posix-timers-add-cond_resched-to-posix_timer_add-sea.patch @@ -0,0 +1,41 @@ +From 7760142a7869d24acaea7597a1d3d84016e8aa5a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 17:48:17 +0100 +Subject: posix-timers: Add cond_resched() to posix_timer_add() search loop + +From: Eric Dumazet + +[ Upstream commit 5f2909c6cd13564a07ae692a95457f52295c4f22 ] + +With a large number of POSIX timers the search for a valid ID might cause a +soft lockup on PREEMPT_NONE/VOLUNTARY kernels. + +Add cond_resched() to the loop to prevent that. + +[ tglx: Split out from Eric's series ] + +Signed-off-by: Eric Dumazet +Signed-off-by: Thomas Gleixner +Reviewed-by: Frederic Weisbecker +Link: https://lore.kernel.org/all/20250214135911.2037402-2-edumazet@google.com +Link: https://lore.kernel.org/all/20250308155623.635612865@linutronix.de +Signed-off-by: Sasha Levin +--- + kernel/time/posix-timers.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c +index 4576aaed13b23..896ff735034ce 100644 +--- a/kernel/time/posix-timers.c ++++ b/kernel/time/posix-timers.c +@@ -118,6 +118,7 @@ static int posix_timer_add(struct k_itimer *timer) + return id; + } + spin_unlock(&hash_lock); ++ cond_resched(); + } + /* POSIX return code when no timer ID could be allocated */ + return -EAGAIN; +-- +2.39.5 + diff --git a/queue-6.12/posix-timers-ensure-that-timer-initialization-is-ful.patch b/queue-6.12/posix-timers-ensure-that-timer-initialization-is-ful.patch new file mode 100644 index 0000000000..bd16c98fb8 --- /dev/null +++ b/queue-6.12/posix-timers-ensure-that-timer-initialization-is-ful.patch @@ -0,0 +1,84 @@ +From ef135dc8e5d557aa788c7b6aabfd11ca4a890569 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 17:48:10 +0100 +Subject: posix-timers: Ensure that timer initialization is fully visible + +From: Thomas Gleixner + +[ Upstream commit 2389c6efd3ad8edb3bcce0019b4edcc7d9c7de19 ] + +Frederic pointed out that the memory operations to initialize the timer are +not guaranteed to be visible, when __lock_timer() observes timer::it_signal +valid under timer::it_lock: + + T0 T1 + --------- ----------- + do_timer_create() + // A + new_timer->.... = .... + spin_lock(current->sighand) + // B + WRITE_ONCE(new_timer->it_signal, current->signal) + spin_unlock(current->sighand) + sys_timer_*() + t = __lock_timer() + spin_lock(&timr->it_lock) + // observes B + if (timr->it_signal == current->signal) + return timr; + if (!t) + return; + // Is not guaranteed to observe A + +Protect the write of timer::it_signal, which makes the timer valid, with +timer::it_lock as well. This guarantees that T1 must observe the +initialization A completely, when it observes the valid signal pointer +under timer::it_lock. sighand::siglock must still be taken to protect the +signal::posix_timers list. + +Reported-by: Frederic Weisbecker +Suggested-by: Frederic Weisbecker +Signed-off-by: Thomas Gleixner +Reviewed-by: Frederic Weisbecker +Link: https://lore.kernel.org/all/20250308155623.507944489@linutronix.de +Signed-off-by: Sasha Levin +--- + kernel/time/posix-timers.c | 21 ++++++++++++++------- + 1 file changed, 14 insertions(+), 7 deletions(-) + +diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c +index 896ff735034ce..c5d9bfbb082b8 100644 +--- a/kernel/time/posix-timers.c ++++ b/kernel/time/posix-timers.c +@@ -514,14 +514,21 @@ static int do_timer_create(clockid_t which_clock, struct sigevent *event, + if (error) + goto out; + +- spin_lock_irq(¤t->sighand->siglock); +- /* This makes the timer valid in the hash table */ +- WRITE_ONCE(new_timer->it_signal, current->signal); +- hlist_add_head(&new_timer->list, ¤t->signal->posix_timers); +- spin_unlock_irq(¤t->sighand->siglock); + /* +- * After unlocking sighand::siglock @new_timer is subject to +- * concurrent removal and cannot be touched anymore ++ * timer::it_lock ensures that __lock_timer() observes a fully ++ * initialized timer when it observes a valid timer::it_signal. ++ * ++ * sighand::siglock is required to protect signal::posix_timers. ++ */ ++ scoped_guard (spinlock_irq, &new_timer->it_lock) { ++ guard(spinlock)(¤t->sighand->siglock); ++ /* This makes the timer valid in the hash table */ ++ WRITE_ONCE(new_timer->it_signal, current->signal); ++ hlist_add_head(&new_timer->list, ¤t->signal->posix_timers); ++ } ++ /* ++ * After unlocking @new_timer is subject to concurrent removal and ++ * cannot be touched anymore + */ + return 0; + out: +-- +2.39.5 + diff --git a/queue-6.12/power-supply-axp20x_battery-update-temp-sensor-for-a.patch b/queue-6.12/power-supply-axp20x_battery-update-temp-sensor-for-a.patch new file mode 100644 index 0000000000..6c03c17aae --- /dev/null +++ b/queue-6.12/power-supply-axp20x_battery-update-temp-sensor-for-a.patch @@ -0,0 +1,73 @@ +From 00c8f743eb2db24c473dae02c43de82786b19bc1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 09:58:33 -0600 +Subject: power: supply: axp20x_battery: Update temp sensor for AXP717 from + device tree + +From: Chris Morgan + +[ Upstream commit bbcfe510ecd47f2db4c8653c7dfa9dc7a55b1583 ] + +Allow a boolean property of "x-powers,no-thermistor" to specify devices +where the ts pin is not connected to anything. This works around an +issue found with some devices where the efuse is not programmed +correctly from the factory or when the register gets set erroneously. + +Signed-off-by: Chris Morgan +Tested-by: Philippe Simons +Link: https://lore.kernel.org/r/20250204155835.161973-4-macroalpha82@gmail.com +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + drivers/power/supply/axp20x_battery.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c +index 57eba1ddb17ba..88fbae613e8bc 100644 +--- a/drivers/power/supply/axp20x_battery.c ++++ b/drivers/power/supply/axp20x_battery.c +@@ -89,6 +89,8 @@ + #define AXP717_BAT_CC_MIN_UA 0 + #define AXP717_BAT_CC_MAX_UA 3008000 + ++#define AXP717_TS_PIN_DISABLE BIT(4) ++ + struct axp20x_batt_ps; + + struct axp_data { +@@ -117,6 +119,7 @@ struct axp20x_batt_ps { + /* Maximum constant charge current */ + unsigned int max_ccc; + const struct axp_data *data; ++ bool ts_disable; + }; + + static int axp20x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt, +@@ -983,6 +986,24 @@ static void axp717_set_battery_info(struct platform_device *pdev, + int ccc = info->constant_charge_current_max_ua; + int val; + ++ axp_batt->ts_disable = (device_property_read_bool(axp_batt->dev, ++ "x-powers,no-thermistor")); ++ ++ /* ++ * Under rare conditions an incorrectly programmed efuse for ++ * the temp sensor on the PMIC may trigger a fault condition. ++ * Allow users to hard-code if the ts pin is not used to work ++ * around this problem. Note that this requires the battery ++ * be correctly defined in the device tree with a monitored ++ * battery node. ++ */ ++ if (axp_batt->ts_disable) { ++ regmap_update_bits(axp_batt->regmap, ++ AXP717_TS_PIN_CFG, ++ AXP717_TS_PIN_DISABLE, ++ AXP717_TS_PIN_DISABLE); ++ } ++ + if (vmin > 0 && axp717_set_voltage_min_design(axp_batt, vmin)) + dev_err(&pdev->dev, + "couldn't set voltage_min_design\n"); +-- +2.39.5 + diff --git a/queue-6.12/powerpc-prom_init-fixup-missing-size-cells-on-powerb.patch b/queue-6.12/powerpc-prom_init-fixup-missing-size-cells-on-powerb.patch new file mode 100644 index 0000000000..c6fa4ff09b --- /dev/null +++ b/queue-6.12/powerpc-prom_init-fixup-missing-size-cells-on-powerb.patch @@ -0,0 +1,44 @@ +From e54e285a44668071c93d922e9dc2eec7829d44f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 18:19:09 +0100 +Subject: powerpc/prom_init: Fixup missing #size-cells on PowerBook6,7 + +From: Andreas Schwab + +[ Upstream commit 7e67ef889c9ab7246547db73d524459f47403a77 ] + +Similar to the PowerMac3,1, the PowerBook6,7 is missing the #size-cells +property on the i2s node. + +Depends-on: commit 045b14ca5c36 ("of: WARN on deprecated #address-cells/#size-cells handling") +Signed-off-by: Andreas Schwab +Acked-by: Rob Herring (Arm) +[maddy: added "commit" work in depends-on to avoid checkpatch error] +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/875xmizl6a.fsf@igel.home +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/prom_init.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c +index 935568d68196d..b1dc4cb9f78e6 100644 +--- a/arch/powerpc/kernel/prom_init.c ++++ b/arch/powerpc/kernel/prom_init.c +@@ -2982,11 +2982,11 @@ static void __init fixup_device_tree_pmac(void) + char type[8]; + phandle node; + +- // Some pmacs are missing #size-cells on escc nodes ++ // Some pmacs are missing #size-cells on escc or i2s nodes + for (node = 0; prom_next_node(&node); ) { + type[0] = '\0'; + prom_getprop(node, "device_type", type, sizeof(type)); +- if (prom_strcmp(type, "escc")) ++ if (prom_strcmp(type, "escc") && prom_strcmp(type, "i2s")) + continue; + + if (prom_getproplen(node, "#size-cells") != PROM_ERROR) +-- +2.39.5 + diff --git a/queue-6.12/powerpc-pseries-iommu-create-ddw-for-devices-with-dm.patch b/queue-6.12/powerpc-pseries-iommu-create-ddw-for-devices-with-dm.patch new file mode 100644 index 0000000000..1e0ec3d0f2 --- /dev/null +++ b/queue-6.12/powerpc-pseries-iommu-create-ddw-for-devices-with-dm.patch @@ -0,0 +1,254 @@ +From 349c1e84757a8583b89979238e659144a25afc71 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jan 2025 10:48:14 -0600 +Subject: powerpc/pseries/iommu: create DDW for devices with DMA mask less than + 64-bits + +From: Gaurav Batra + +[ Upstream commit 67dfc11982f7e3c37f0977e74671da2391b29181 ] + +Starting with PAPR level 2.13, platform supports placing PHB in limited +address mode. Devices that support DMA masks less that 64-bit but greater +than 32-bits are placed in limited address mode. In this mode, the +starting DMA address returned by the DDW is 4GB. + +When the device driver calls dma_supported, with mask less then 64-bit, the +PowerPC IOMMU driver places PHB in the Limited Addressing Mode before +creating DDW. + +Signed-off-by: Gaurav Batra +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250108164814.73250-1-gbatra@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/pseries/iommu.c | 110 +++++++++++++++++++++---- + 1 file changed, 94 insertions(+), 16 deletions(-) + +diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c +index 8f32340960e21..d6ebc19fb99c5 100644 +--- a/arch/powerpc/platforms/pseries/iommu.c ++++ b/arch/powerpc/platforms/pseries/iommu.c +@@ -52,7 +52,8 @@ enum { + enum { + DDW_EXT_SIZE = 0, + DDW_EXT_RESET_DMA_WIN = 1, +- DDW_EXT_QUERY_OUT_SIZE = 2 ++ DDW_EXT_QUERY_OUT_SIZE = 2, ++ DDW_EXT_LIMITED_ADDR_MODE = 3 + }; + + static struct iommu_table *iommu_pseries_alloc_table(int node) +@@ -1327,6 +1328,54 @@ static void reset_dma_window(struct pci_dev *dev, struct device_node *par_dn) + ret); + } + ++/* ++ * Platforms support placing PHB in limited address mode starting with LoPAR ++ * level 2.13 implement. In this mode, the DMA address returned by DDW is over ++ * 4GB but, less than 64-bits. This benefits IO adapters that don't support ++ * 64-bits for DMA addresses. ++ */ ++static int limited_dma_window(struct pci_dev *dev, struct device_node *par_dn) ++{ ++ int ret; ++ u32 cfg_addr, reset_dma_win, las_supported; ++ u64 buid; ++ struct device_node *dn; ++ struct pci_dn *pdn; ++ ++ ret = ddw_read_ext(par_dn, DDW_EXT_RESET_DMA_WIN, &reset_dma_win); ++ if (ret) ++ goto out; ++ ++ ret = ddw_read_ext(par_dn, DDW_EXT_LIMITED_ADDR_MODE, &las_supported); ++ ++ /* Limited Address Space extension available on the platform but DDW in ++ * limited addressing mode not supported ++ */ ++ if (!ret && !las_supported) ++ ret = -EPROTO; ++ ++ if (ret) { ++ dev_info(&dev->dev, "Limited Address Space for DDW not Supported, err: %d", ret); ++ goto out; ++ } ++ ++ dn = pci_device_to_OF_node(dev); ++ pdn = PCI_DN(dn); ++ buid = pdn->phb->buid; ++ cfg_addr = (pdn->busno << 16) | (pdn->devfn << 8); ++ ++ ret = rtas_call(reset_dma_win, 4, 1, NULL, cfg_addr, BUID_HI(buid), ++ BUID_LO(buid), 1); ++ if (ret) ++ dev_info(&dev->dev, ++ "ibm,reset-pe-dma-windows(%x) for Limited Addr Support: %x %x %x returned %d ", ++ reset_dma_win, cfg_addr, BUID_HI(buid), BUID_LO(buid), ++ ret); ++ ++out: ++ return ret; ++} ++ + /* Return largest page shift based on "IO Page Sizes" output of ibm,query-pe-dma-window. */ + static int iommu_get_page_shift(u32 query_page_size) + { +@@ -1394,7 +1443,7 @@ static struct property *ddw_property_create(const char *propname, u32 liobn, u64 + * + * returns true if can map all pages (direct mapping), false otherwise.. + */ +-static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) ++static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn, u64 dma_mask) + { + int len = 0, ret; + int max_ram_len = order_base_2(ddw_memory_hotplug_max()); +@@ -1413,6 +1462,9 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + bool pmem_present; + struct pci_dn *pci = PCI_DN(pdn); + struct property *default_win = NULL; ++ bool limited_addr_req = false, limited_addr_enabled = false; ++ int dev_max_ddw; ++ int ddw_sz; + + dn = of_find_node_by_type(NULL, "ibm,pmemory"); + pmem_present = dn != NULL; +@@ -1439,7 +1491,6 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + * the ibm,ddw-applicable property holds the tokens for: + * ibm,query-pe-dma-window + * ibm,create-pe-dma-window +- * ibm,remove-pe-dma-window + * for the given node in that order. + * the property is actually in the parent, not the PE + */ +@@ -1459,6 +1510,20 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + if (ret != 0) + goto out_failed; + ++ /* DMA Limited Addressing required? This is when the driver has ++ * requested to create DDW but supports mask which is less than 64-bits ++ */ ++ limited_addr_req = (dma_mask != DMA_BIT_MASK(64)); ++ ++ /* place the PHB in Limited Addressing mode */ ++ if (limited_addr_req) { ++ if (limited_dma_window(dev, pdn)) ++ goto out_failed; ++ ++ /* PHB is in Limited address mode */ ++ limited_addr_enabled = true; ++ } ++ + /* + * If there is no window available, remove the default DMA window, + * if it's present. This will make all the resources available to the +@@ -1505,6 +1570,15 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + goto out_failed; + } + ++ /* Maximum DMA window size that the device can address (in log2) */ ++ dev_max_ddw = fls64(dma_mask); ++ ++ /* If the device DMA mask is less than 64-bits, make sure the DMA window ++ * size is not bigger than what the device can access ++ */ ++ ddw_sz = min(order_base_2(query.largest_available_block << page_shift), ++ dev_max_ddw); ++ + /* + * The "ibm,pmemory" can appear anywhere in the address space. + * Assuming it is still backed by page structs, try MAX_PHYSMEM_BITS +@@ -1513,23 +1587,21 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + */ + len = max_ram_len; + if (pmem_present) { +- if (query.largest_available_block >= +- (1ULL << (MAX_PHYSMEM_BITS - page_shift))) ++ if (ddw_sz >= MAX_PHYSMEM_BITS) + len = MAX_PHYSMEM_BITS; + else + dev_info(&dev->dev, "Skipping ibm,pmemory"); + } + + /* check if the available block * number of ptes will map everything */ +- if (query.largest_available_block < (1ULL << (len - page_shift))) { ++ if (ddw_sz < len) { + dev_dbg(&dev->dev, + "can't map partition max 0x%llx with %llu %llu-sized pages\n", + 1ULL << len, + query.largest_available_block, + 1ULL << page_shift); + +- len = order_base_2(query.largest_available_block << page_shift); +- ++ len = ddw_sz; + dynamic_mapping = true; + } else { + direct_mapping = !default_win_removed || +@@ -1543,8 +1615,9 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + */ + if (default_win_removed && pmem_present && !direct_mapping) { + /* DDW is big enough to be split */ +- if ((query.largest_available_block << page_shift) >= +- MIN_DDW_VPMEM_DMA_WINDOW + (1ULL << max_ram_len)) { ++ if ((1ULL << ddw_sz) >= ++ MIN_DDW_VPMEM_DMA_WINDOW + (1ULL << max_ram_len)) { ++ + direct_mapping = true; + + /* offset of the Dynamic part of DDW */ +@@ -1555,8 +1628,7 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + dynamic_mapping = true; + + /* create max size DDW possible */ +- len = order_base_2(query.largest_available_block +- << page_shift); ++ len = ddw_sz; + } + } + +@@ -1685,7 +1757,7 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + __remove_dma_window(pdn, ddw_avail, create.liobn); + + out_failed: +- if (default_win_removed) ++ if (default_win_removed || limited_addr_enabled) + reset_dma_window(dev, pdn); + + fpdn = kzalloc(sizeof(*fpdn), GFP_KERNEL); +@@ -1704,6 +1776,9 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + dev->dev.bus_dma_limit = dev->dev.archdata.dma_offset + + (1ULL << max_ram_len); + ++ dev_info(&dev->dev, "lsa_required: %x, lsa_enabled: %x, direct mapping: %x\n", ++ limited_addr_req, limited_addr_enabled, direct_mapping); ++ + return direct_mapping; + } + +@@ -1829,8 +1904,11 @@ static bool iommu_bypass_supported_pSeriesLP(struct pci_dev *pdev, u64 dma_mask) + { + struct device_node *dn = pci_device_to_OF_node(pdev), *pdn; + +- /* only attempt to use a new window if 64-bit DMA is requested */ +- if (dma_mask < DMA_BIT_MASK(64)) ++ /* For DDW, DMA mask should be more than 32-bits. For mask more then ++ * 32-bits but less then 64-bits, DMA addressing is supported in ++ * Limited Addressing mode. ++ */ ++ if (dma_mask <= DMA_BIT_MASK(32)) + return false; + + dev_dbg(&pdev->dev, "node is %pOF\n", dn); +@@ -1843,7 +1921,7 @@ static bool iommu_bypass_supported_pSeriesLP(struct pci_dev *pdev, u64 dma_mask) + */ + pdn = pci_dma_find(dn, NULL); + if (pdn && PCI_DN(pdn)) +- return enable_ddw(pdev, pdn); ++ return enable_ddw(pdev, pdn, dma_mask); + + return false; + } +-- +2.39.5 + diff --git a/queue-6.12/powerpc-pseries-iommu-memory-notifier-incorrectly-ad.patch b/queue-6.12/powerpc-pseries-iommu-memory-notifier-incorrectly-ad.patch new file mode 100644 index 0000000000..2aa64e6ec2 --- /dev/null +++ b/queue-6.12/powerpc-pseries-iommu-memory-notifier-incorrectly-ad.patch @@ -0,0 +1,138 @@ +From d60e0ef2ac366cf7d6b9ca2bba9adf40a871b739 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 12:38:54 -0600 +Subject: powerpc/pseries/iommu: memory notifier incorrectly adds TCEs for + pmemory + +From: Gaurav Batra + +[ Upstream commit 6aa989ab2bd0d37540c812b4270006ff794662e7 ] + +iommu_mem_notifier() is invoked when RAM is dynamically added/removed. This +notifier call is responsible to add/remove TCEs from the Dynamic DMA Window +(DDW) when TCEs are pre-mapped. TCEs are pre-mapped only for RAM and not +for persistent memory (pmemory). For DMA buffers in pmemory, TCEs are +dynamically mapped when the device driver instructs to do so. + +The issue is 'daxctl' command is capable of adding pmemory as "System RAM" +after LPAR boot. The command to do so is - + +daxctl reconfigure-device --mode=system-ram dax0.0 --force + +This will dynamically add pmemory range to LPAR RAM eventually invoking +iommu_mem_notifier(). The address range of pmemory is way beyond the Max +RAM that the LPAR can have. Which means, this range is beyond the DDW +created for the device, at device initialization time. + +As a result when TCEs are pre-mapped for the pmemory range, by +iommu_mem_notifier(), PHYP HCALL returns H_PARAMETER. This failed the +command, daxctl, to add pmemory as RAM. + +The solution is to not pre-map TCEs for pmemory. + +Signed-off-by: Gaurav Batra +Tested-by: Donet Tom +Reviewed-by: Donet Tom +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250130183854.92258-1-gbatra@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/include/asm/mmzone.h | 1 + + arch/powerpc/mm/numa.c | 2 +- + arch/powerpc/platforms/pseries/iommu.c | 29 ++++++++++++++------------ + 3 files changed, 18 insertions(+), 14 deletions(-) + +diff --git a/arch/powerpc/include/asm/mmzone.h b/arch/powerpc/include/asm/mmzone.h +index d99863cd6cde4..049152f8d597a 100644 +--- a/arch/powerpc/include/asm/mmzone.h ++++ b/arch/powerpc/include/asm/mmzone.h +@@ -29,6 +29,7 @@ extern cpumask_var_t node_to_cpumask_map[]; + #ifdef CONFIG_MEMORY_HOTPLUG + extern unsigned long max_pfn; + u64 memory_hotplug_max(void); ++u64 hot_add_drconf_memory_max(void); + #else + #define memory_hotplug_max() memblock_end_of_DRAM() + #endif +diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c +index 3c1da08304d03..603a0f652ba61 100644 +--- a/arch/powerpc/mm/numa.c ++++ b/arch/powerpc/mm/numa.c +@@ -1336,7 +1336,7 @@ int hot_add_scn_to_nid(unsigned long scn_addr) + return nid; + } + +-static u64 hot_add_drconf_memory_max(void) ++u64 hot_add_drconf_memory_max(void) + { + struct device_node *memory = NULL; + struct device_node *dn = NULL; +diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c +index ae6f7a235d8b2..8f32340960e21 100644 +--- a/arch/powerpc/platforms/pseries/iommu.c ++++ b/arch/powerpc/platforms/pseries/iommu.c +@@ -1284,17 +1284,13 @@ static LIST_HEAD(failed_ddw_pdn_list); + + static phys_addr_t ddw_memory_hotplug_max(void) + { +- resource_size_t max_addr = memory_hotplug_max(); +- struct device_node *memory; ++ resource_size_t max_addr; + +- for_each_node_by_type(memory, "memory") { +- struct resource res; +- +- if (of_address_to_resource(memory, 0, &res)) +- continue; +- +- max_addr = max_t(resource_size_t, max_addr, res.end + 1); +- } ++#if defined(CONFIG_NUMA) && defined(CONFIG_MEMORY_HOTPLUG) ++ max_addr = hot_add_drconf_memory_max(); ++#else ++ max_addr = memblock_end_of_DRAM(); ++#endif + + return max_addr; + } +@@ -1600,7 +1596,7 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + + if (direct_mapping) { + /* DDW maps the whole partition, so enable direct DMA mapping */ +- ret = walk_system_ram_range(0, memblock_end_of_DRAM() >> PAGE_SHIFT, ++ ret = walk_system_ram_range(0, ddw_memory_hotplug_max() >> PAGE_SHIFT, + win64->value, tce_setrange_multi_pSeriesLP_walk); + if (ret) { + dev_info(&dev->dev, "failed to map DMA window for %pOF: %d\n", +@@ -2349,11 +2345,17 @@ static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action, + struct memory_notify *arg = data; + int ret = 0; + ++ /* This notifier can get called when onlining persistent memory as well. ++ * TCEs are not pre-mapped for persistent memory. Persistent memory will ++ * always be above ddw_memory_hotplug_max() ++ */ ++ + switch (action) { + case MEM_GOING_ONLINE: + spin_lock(&dma_win_list_lock); + list_for_each_entry(window, &dma_win_list, list) { +- if (window->direct) { ++ if (window->direct && (arg->start_pfn << PAGE_SHIFT) < ++ ddw_memory_hotplug_max()) { + ret |= tce_setrange_multi_pSeriesLP(arg->start_pfn, + arg->nr_pages, window->prop); + } +@@ -2365,7 +2367,8 @@ static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action, + case MEM_OFFLINE: + spin_lock(&dma_win_list_lock); + list_for_each_entry(window, &dma_win_list, list) { +- if (window->direct) { ++ if (window->direct && (arg->start_pfn << PAGE_SHIFT) < ++ ddw_memory_hotplug_max()) { + ret |= tce_clearrange_multi_pSeriesLP(arg->start_pfn, + arg->nr_pages, window->prop); + } +-- +2.39.5 + diff --git a/queue-6.12/printk-check-con_suspend-when-unblanking-a-console.patch b/queue-6.12/printk-check-con_suspend-when-unblanking-a-console.patch new file mode 100644 index 0000000000..9784f4b4ea --- /dev/null +++ b/queue-6.12/printk-check-con_suspend-when-unblanking-a-console.patch @@ -0,0 +1,59 @@ +From bf4408e68c8ff4421cb0b82b29f48ca4f1cb0fcc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 16:59:05 -0300 +Subject: printk: Check CON_SUSPEND when unblanking a console + +From: Marcos Paulo de Souza + +[ Upstream commit 72c96a2dacc0fb056d13a5f02b0845c4c910fe54 ] + +The commit 9e70a5e109a4 ("printk: Add per-console suspended state") +introduced the CON_SUSPENDED flag for consoles. The suspended consoles +will stop receiving messages, so don't unblank suspended consoles +because it won't be showing anything either way. + +Signed-off-by: Marcos Paulo de Souza +Reviewed-by: Petr Mladek +Reviewed-by: John Ogness +Link: https://lore.kernel.org/r/20250226-printk-renaming-v1-5-0b878577f2e6@suse.com +Signed-off-by: Petr Mladek +Signed-off-by: Sasha Levin +--- + kernel/printk/printk.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c +index 881a26e18c658..3a91b739e8f30 100644 +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -3310,7 +3310,12 @@ void console_unblank(void) + */ + cookie = console_srcu_read_lock(); + for_each_console_srcu(c) { +- if ((console_srcu_read_flags(c) & CON_ENABLED) && c->unblank) { ++ short flags = console_srcu_read_flags(c); ++ ++ if (flags & CON_SUSPENDED) ++ continue; ++ ++ if ((flags & CON_ENABLED) && c->unblank) { + found_unblank = true; + break; + } +@@ -3347,7 +3352,12 @@ void console_unblank(void) + + cookie = console_srcu_read_lock(); + for_each_console_srcu(c) { +- if ((console_srcu_read_flags(c) & CON_ENABLED) && c->unblank) ++ short flags = console_srcu_read_flags(c); ++ ++ if (flags & CON_SUSPENDED) ++ continue; ++ ++ if ((flags & CON_ENABLED) && c->unblank) + c->unblank(); + } + console_srcu_read_unlock(cookie); +-- +2.39.5 + diff --git a/queue-6.12/pstore-change-kmsg_bytes-storage-size-to-u32.patch b/queue-6.12/pstore-change-kmsg_bytes-storage-size-to-u32.patch new file mode 100644 index 0000000000..a050d7b7e0 --- /dev/null +++ b/queue-6.12/pstore-change-kmsg_bytes-storage-size-to-u32.patch @@ -0,0 +1,108 @@ +From c90e28881334dcbe3d369c4a4941b0ce39f0ce31 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 11:16:59 -0800 +Subject: pstore: Change kmsg_bytes storage size to u32 + +From: Kees Cook + +[ Upstream commit 5674609535bafa834ab014d90d9bbe8e89223a0b ] + +The types around kmsg_bytes were inconsistent. The global was unsigned +long, the argument to pstore_set_kmsg_bytes() was int, and the filesystem +option was u32. Given other internal limits, there's not much sense +in making a single pstore record larger than INT_MAX and it can't be +negative, so use u32 everywhere. Additionally, use READ/WRITE_ONCE and a +local variable in pstore_dump() to avoid kmsg_bytes changing during a +dump. + +Link: https://lore.kernel.org/r/20250206191655.work.798-kees@kernel.org +Signed-off-by: Kees Cook +Signed-off-by: Sasha Levin +--- + fs/pstore/inode.c | 2 +- + fs/pstore/internal.h | 4 ++-- + fs/pstore/platform.c | 11 ++++++----- + 3 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c +index 56815799ce798..9de6b280c4f41 100644 +--- a/fs/pstore/inode.c ++++ b/fs/pstore/inode.c +@@ -265,7 +265,7 @@ static void parse_options(char *options) + static int pstore_show_options(struct seq_file *m, struct dentry *root) + { + if (kmsg_bytes != CONFIG_PSTORE_DEFAULT_KMSG_BYTES) +- seq_printf(m, ",kmsg_bytes=%lu", kmsg_bytes); ++ seq_printf(m, ",kmsg_bytes=%u", kmsg_bytes); + return 0; + } + +diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h +index 801d6c0b170c3..a0fc511969100 100644 +--- a/fs/pstore/internal.h ++++ b/fs/pstore/internal.h +@@ -6,7 +6,7 @@ + #include + #include + +-extern unsigned long kmsg_bytes; ++extern unsigned int kmsg_bytes; + + #ifdef CONFIG_PSTORE_FTRACE + extern void pstore_register_ftrace(void); +@@ -35,7 +35,7 @@ static inline void pstore_unregister_pmsg(void) {} + + extern struct pstore_info *psinfo; + +-extern void pstore_set_kmsg_bytes(int); ++extern void pstore_set_kmsg_bytes(unsigned int bytes); + extern void pstore_get_records(int); + extern void pstore_get_backend_records(struct pstore_info *psi, + struct dentry *root, int quiet); +diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c +index f56b066ab80ce..557cf9d40177f 100644 +--- a/fs/pstore/platform.c ++++ b/fs/pstore/platform.c +@@ -92,8 +92,8 @@ module_param(compress, charp, 0444); + MODULE_PARM_DESC(compress, "compression to use"); + + /* How much of the kernel log to snapshot */ +-unsigned long kmsg_bytes = CONFIG_PSTORE_DEFAULT_KMSG_BYTES; +-module_param(kmsg_bytes, ulong, 0444); ++unsigned int kmsg_bytes = CONFIG_PSTORE_DEFAULT_KMSG_BYTES; ++module_param(kmsg_bytes, uint, 0444); + MODULE_PARM_DESC(kmsg_bytes, "amount of kernel log to snapshot (in bytes)"); + + static void *compress_workspace; +@@ -107,9 +107,9 @@ static void *compress_workspace; + static char *big_oops_buf; + static size_t max_compressed_size; + +-void pstore_set_kmsg_bytes(int bytes) ++void pstore_set_kmsg_bytes(unsigned int bytes) + { +- kmsg_bytes = bytes; ++ WRITE_ONCE(kmsg_bytes, bytes); + } + + /* Tag each group of saved records with a sequence number */ +@@ -278,6 +278,7 @@ static void pstore_dump(struct kmsg_dumper *dumper, + struct kmsg_dump_detail *detail) + { + struct kmsg_dump_iter iter; ++ unsigned int remaining = READ_ONCE(kmsg_bytes); + unsigned long total = 0; + const char *why; + unsigned int part = 1; +@@ -300,7 +301,7 @@ static void pstore_dump(struct kmsg_dumper *dumper, + kmsg_dump_rewind(&iter); + + oopscount++; +- while (total < kmsg_bytes) { ++ while (total < remaining) { + char *dst; + size_t dst_size; + int header_size; +-- +2.39.5 + diff --git a/queue-6.12/r8152-add-vendor-device-id-pair-for-dell-alienware-a.patch b/queue-6.12/r8152-add-vendor-device-id-pair-for-dell-alienware-a.patch new file mode 100644 index 0000000000..5a3582e71d --- /dev/null +++ b/queue-6.12/r8152-add-vendor-device-id-pair-for-dell-alienware-a.patch @@ -0,0 +1,50 @@ +From 8f4b77a6ac92b2645ad3192d37038d77a6e94658 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 23:40:33 +0100 +Subject: r8152: add vendor/device ID pair for Dell Alienware AW1022z + +From: Aleksander Jan Bajkowski + +[ Upstream commit 848b09d53d923b4caee5491f57a5c5b22d81febc ] + +The Dell AW1022z is an RTL8156B based 2.5G Ethernet controller. + +Add the vendor and product ID values to the driver. This makes Ethernet +work with the adapter. + +Signed-off-by: Aleksander Jan Bajkowski +Link: https://patch.msgid.link/20250206224033.980115-1-olek2@wp.pl +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/usb/r8152.c | 1 + + include/linux/usb/r8152.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c +index 96fa3857d8e25..2cab046749a92 100644 +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -10085,6 +10085,7 @@ static const struct usb_device_id rtl8152_table[] = { + { USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff) }, + { USB_DEVICE(VENDOR_ID_TPLINK, 0x0601) }, + { USB_DEVICE(VENDOR_ID_DLINK, 0xb301) }, ++ { USB_DEVICE(VENDOR_ID_DELL, 0xb097) }, + { USB_DEVICE(VENDOR_ID_ASUS, 0x1976) }, + {} + }; +diff --git a/include/linux/usb/r8152.h b/include/linux/usb/r8152.h +index 33a4c146dc19c..2ca60828f28bb 100644 +--- a/include/linux/usb/r8152.h ++++ b/include/linux/usb/r8152.h +@@ -30,6 +30,7 @@ + #define VENDOR_ID_NVIDIA 0x0955 + #define VENDOR_ID_TPLINK 0x2357 + #define VENDOR_ID_DLINK 0x2001 ++#define VENDOR_ID_DELL 0x413c + #define VENDOR_ID_ASUS 0x0b05 + + #if IS_REACHABLE(CONFIG_USB_RTL8152) +-- +2.39.5 + diff --git a/queue-6.12/r8169-disable-rtl8126-zrx-dc-timeout.patch b/queue-6.12/r8169-disable-rtl8126-zrx-dc-timeout.patch new file mode 100644 index 0000000000..bf3f5ae8ea --- /dev/null +++ b/queue-6.12/r8169-disable-rtl8126-zrx-dc-timeout.patch @@ -0,0 +1,70 @@ +From 1e859877d0e392e3a2a97926da6a00c0fb2bf999 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 16:37:21 +0800 +Subject: r8169: disable RTL8126 ZRX-DC timeout + +From: ChunHao Lin + +[ Upstream commit b48688ea3c9ac8d5d910c6e91fb7f80d846581f0 ] + +Disable it due to it dose not meet ZRX-DC specification. If it is enabled, +device will exit L1 substate every 100ms. Disable it for saving more power +in L1 substate. + +Signed-off-by: ChunHao Lin +Reviewed-by: Heiner Kallweit +Link: https://patch.msgid.link/20250318083721.4127-3-hau@realtek.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/realtek/r8169_main.c | 27 +++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c +index 5ed2818bac257..3420b6cf8189f 100644 +--- a/drivers/net/ethernet/realtek/r8169_main.c ++++ b/drivers/net/ethernet/realtek/r8169_main.c +@@ -2850,6 +2850,32 @@ static u32 rtl_csi_read(struct rtl8169_private *tp, int addr) + RTL_R32(tp, CSIDR) : ~0; + } + ++static void rtl_disable_zrxdc_timeout(struct rtl8169_private *tp) ++{ ++ struct pci_dev *pdev = tp->pci_dev; ++ u32 csi; ++ int rc; ++ u8 val; ++ ++#define RTL_GEN3_RELATED_OFF 0x0890 ++#define RTL_GEN3_ZRXDC_NONCOMPL 0x1 ++ if (pdev->cfg_size > RTL_GEN3_RELATED_OFF) { ++ rc = pci_read_config_byte(pdev, RTL_GEN3_RELATED_OFF, &val); ++ if (rc == PCIBIOS_SUCCESSFUL) { ++ val &= ~RTL_GEN3_ZRXDC_NONCOMPL; ++ rc = pci_write_config_byte(pdev, RTL_GEN3_RELATED_OFF, ++ val); ++ if (rc == PCIBIOS_SUCCESSFUL) ++ return; ++ } ++ } ++ ++ netdev_notice_once(tp->dev, ++ "No native access to PCI extended config space, falling back to CSI\n"); ++ csi = rtl_csi_read(tp, RTL_GEN3_RELATED_OFF); ++ rtl_csi_write(tp, RTL_GEN3_RELATED_OFF, csi & ~RTL_GEN3_ZRXDC_NONCOMPL); ++} ++ + static void rtl_set_aspm_entry_latency(struct rtl8169_private *tp, u8 val) + { + struct pci_dev *pdev = tp->pci_dev; +@@ -3816,6 +3842,7 @@ static void rtl_hw_start_8125b(struct rtl8169_private *tp) + + static void rtl_hw_start_8126a(struct rtl8169_private *tp) + { ++ rtl_disable_zrxdc_timeout(tp); + rtl_set_def_aspm_entry_latency(tp); + rtl_hw_start_8125_common(tp); + } +-- +2.39.5 + diff --git a/queue-6.12/r8169-don-t-scan-phy-addresses-0.patch b/queue-6.12/r8169-don-t-scan-phy-addresses-0.patch new file mode 100644 index 0000000000..c6216ac826 --- /dev/null +++ b/queue-6.12/r8169-don-t-scan-phy-addresses-0.patch @@ -0,0 +1,36 @@ +From 69a307f5fa0eeec6920ba25a4120a4a554443434 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 07:58:17 +0100 +Subject: r8169: don't scan PHY addresses > 0 + +From: Heiner Kallweit + +[ Upstream commit faac69a4ae5abb49e62c79c66b51bb905c9aa5ec ] + +The PHY address is a dummy, because r8169 PHY access registers +don't support a PHY address. Therefore scan address 0 only. + +Signed-off-by: Heiner Kallweit +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/830637dd-4016-4a68-92b3-618fcac6589d@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/realtek/r8169_main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c +index 3420b6cf8189f..85bb5121cd245 100644 +--- a/drivers/net/ethernet/realtek/r8169_main.c ++++ b/drivers/net/ethernet/realtek/r8169_main.c +@@ -5258,6 +5258,7 @@ static int r8169_mdio_register(struct rtl8169_private *tp) + new_bus->priv = tp; + new_bus->parent = &pdev->dev; + new_bus->irq[0] = PHY_MAC_INTERRUPT; ++ new_bus->phy_mask = GENMASK(31, 1); + snprintf(new_bus->id, MII_BUS_ID_SIZE, "r8169-%x-%x", + pci_domain_nr(pdev->bus), pci_dev_id(pdev)); + +-- +2.39.5 + diff --git a/queue-6.12/rcu-fix-get_state_synchronize_rcu_full-gp-start-dete.patch b/queue-6.12/rcu-fix-get_state_synchronize_rcu_full-gp-start-dete.patch new file mode 100644 index 0000000000..a2fb296681 --- /dev/null +++ b/queue-6.12/rcu-fix-get_state_synchronize_rcu_full-gp-start-dete.patch @@ -0,0 +1,248 @@ +From 810f6648011b4f7f7b952821e9ad2663a5a1bdea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Dec 2024 14:15:07 -0800 +Subject: rcu: Fix get_state_synchronize_rcu_full() GP-start detection +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Paul E. McKenney + +[ Upstream commit 85aad7cc417877054c65bd490dc037b087ef21b4 ] + +The get_state_synchronize_rcu_full() and poll_state_synchronize_rcu_full() +functions use the root rcu_node structure's ->gp_seq field to detect +the beginnings and ends of grace periods, respectively. This choice is +necessary for the poll_state_synchronize_rcu_full() function because +(give or take counter wrap), the following sequence is guaranteed not +to trigger: + + get_state_synchronize_rcu_full(&rgos); + synchronize_rcu(); + WARN_ON_ONCE(!poll_state_synchronize_rcu_full(&rgos)); + +The RCU callbacks that awaken synchronize_rcu() instances are +guaranteed not to be invoked before the root rcu_node structure's +->gp_seq field is updated to indicate the end of the grace period. +However, these callbacks might start being invoked immediately +thereafter, in particular, before rcu_state.gp_seq has been updated. +Therefore, poll_state_synchronize_rcu_full() must refer to the +root rcu_node structure's ->gp_seq field. Because this field is +updated under this structure's ->lock, any code following a call to +poll_state_synchronize_rcu_full() will be fully ordered after the +full grace-period computation, as is required by RCU's memory-ordering +semantics. + +By symmetry, the get_state_synchronize_rcu_full() function should also +use this same root rcu_node structure's ->gp_seq field. But it turns out +that symmetry is profoundly (though extremely infrequently) destructive +in this case. To see this, consider the following sequence of events: + +1. CPU 0 starts a new grace period, and updates rcu_state.gp_seq + accordingly. + +2. As its first step of grace-period initialization, CPU 0 examines + the current CPU hotplug state and decides that it need not wait + for CPU 1, which is currently offline. + +3. CPU 1 comes online, and updates its state. But this does not + affect the current grace period, but rather the one after that. + After all, CPU 1 was offline when the current grace period + started, so all pre-existing RCU readers on CPU 1 must have + completed or been preempted before it last went offline. + The current grace period therefore has nothing it needs to wait + for on CPU 1. + +4. CPU 1 switches to an rcutorture kthread which is running + rcutorture's rcu_torture_reader() function, which starts a new + RCU reader. + +5. CPU 2 is running rcutorture's rcu_torture_writer() function + and collects a new polled grace-period "cookie" using + get_state_synchronize_rcu_full(). Because the newly started + grace period has not completed initialization, the root rcu_node + structure's ->gp_seq field has not yet been updated to indicate + that this new grace period has already started. + + This cookie is therefore set up for the end of the current grace + period (rather than the end of the following grace period). + +6. CPU 0 finishes grace-period initialization. + +7. If CPU 1’s rcutorture reader is preempted, it will be added to + the ->blkd_tasks list, but because CPU 1’s ->qsmask bit is not + set in CPU 1's leaf rcu_node structure, the ->gp_tasks pointer + will not be updated.  Thus, this grace period will not wait on + it.  Which is only fair, given that the CPU did not come online + until after the grace period officially started. + +8. CPUs 0 and 2 then detect the new grace period and then report + a quiescent state to the RCU core. + +9. Because CPU 1 was offline at the start of the current grace + period, CPUs 0 and 2 are the only CPUs that this grace period + needs to wait on. So the grace period ends and post-grace-period + cleanup starts. In particular, the root rcu_node structure's + ->gp_seq field is updated to indicate that this grace period + has now ended. + +10. CPU 2 continues running rcu_torture_writer() and sees that, + from the viewpoint of the root rcu_node structure consulted by + the poll_state_synchronize_rcu_full() function, the grace period + has ended.  It therefore updates state accordingly. + +11. CPU 1 is still running the same RCU reader, which notices this + update and thus complains about the too-short grace period. + +The fix is for the get_state_synchronize_rcu_full() function to use +rcu_state.gp_seq instead of the root rcu_node structure's ->gp_seq field. +With this change in place, if step 5's cookie indicates that the grace +period has not yet started, then any prior code executed by CPU 2 must +have happened before CPU 1 came online. This will in turn prevent CPU +1's code in steps 3 and 11 from spanning CPU 2's grace-period wait, +thus preventing CPU 1 from being subjected to a too-short grace period. + +This commit therefore makes this change. Note that there is no change to +the poll_state_synchronize_rcu_full() function, which as noted above, +must continue to use the root rcu_node structure's ->gp_seq field. +This is of course an asymmetry between these two functions, but is an +asymmetry that is absolutely required for correct operation. It is a +common human tendency to greatly value symmetry, and sometimes symmetry +is a wonderful thing. Other times, symmetry results in poor performance. +But in this case, symmetry is just plain wrong. + +Nevertheless, the asymmetry does require an additional adjustment. +It is possible for get_state_synchronize_rcu_full() to see a given +grace period as having started, but for an immediately following +poll_state_synchronize_rcu_full() to see it as having not yet started. +Given the current rcu_seq_done_exact() implementation, this will +result in a false-positive indication that the grace period is done +from poll_state_synchronize_rcu_full(). This is dealt with by making +rcu_seq_done_exact() reach back three grace periods rather than just +two of them. + +However, simply changing get_state_synchronize_rcu_full() function to +use rcu_state.gp_seq instead of the root rcu_node structure's ->gp_seq +field results in a theoretical bug in kernels booted with +rcutree.rcu_normal_wake_from_gp=1 due to the following sequence of +events: + +o The rcu_gp_init() function invokes rcu_seq_start() to officially + start a new grace period. + +o A new RCU reader begins, referencing X from some RCU-protected + list. The new grace period is not obligated to wait for this + reader. + +o An updater removes X, then calls synchronize_rcu(), which queues + a wait element. + +o The grace period ends, awakening the updater, which frees X + while the reader is still referencing it. + +The reason that this is theoretical is that although the grace period +has officially started, none of the CPUs are officially aware of this, +and thus will have to assume that the RCU reader pre-dated the start of +the grace period. Detailed explanation can be found at [2] and [3]. + +Except for kernels built with CONFIG_PROVE_RCU=y, which use the polled +grace-period APIs, which can and do complain bitterly when this sequence +of events occurs. Not only that, there might be some future RCU +grace-period mechanism that pulls this sequence of events from theory +into practice. This commit therefore also pulls the call to +rcu_sr_normal_gp_init() to precede that to rcu_seq_start(). + +Although this fixes commit 91a967fd6934 ("rcu: Add full-sized polling +for get_completed*() and poll_state*()"), it is not clear that it is +worth backporting this commit. First, it took me many weeks to convince +rcutorture to reproduce this more frequently than once per year. +Second, this cannot be reproduced at all without frequent CPU-hotplug +operations, as in waiting all of 50 milliseconds from the end of the +previous operation until starting the next one. Third, the TREE03.boot +settings cause multi-millisecond delays during RCU grace-period +initialization, which greatly increase the probability of the above +sequence of events. (Don't do this in production workloads!) Fourth, +the TREE03 rcutorture scenario was modified to use four-CPU guest OSes, +to have a single-rcu_node combining tree, no testing of RCU priority +boosting, and no random preemption, and these modifications were +necessary to reproduce this issue in a reasonable timeframe. Fifth, +extremely heavy use of get_state_synchronize_rcu_full() and/or +poll_state_synchronize_rcu_full() is required to reproduce this, and as +of v6.12, only kfree_rcu() uses it, and even then not particularly +heavily. + +[boqun: Apply the fix [1], and add the comment before the moved +rcu_sr_normal_gp_init(). Additional links are added for explanation.] + +Signed-off-by: Paul E. McKenney +Reviewed-by: Frederic Weisbecker +Reviewed-by: Joel Fernandes (Google) +Tested-by: Uladzislau Rezki (Sony) +Link: https://lore.kernel.org/rcu/d90bd6d9-d15c-4b9b-8a69-95336e74e8f4@paulmck-laptop/ [1] +Link: https://lore.kernel.org/rcu/20250303001507.GA3994772@joelnvbox/ [2] +Link: https://lore.kernel.org/rcu/Z8bcUsZ9IpRi1QoP@pc636/ [3] +Reviewed-by: Joel Fernandes +Signed-off-by: Boqun Feng +Signed-off-by: Sasha Levin +--- + kernel/rcu/rcu.h | 2 +- + kernel/rcu/tree.c | 15 +++++++++++---- + 2 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h +index feb3ac1dc5d59..f87c9d6d36fcb 100644 +--- a/kernel/rcu/rcu.h ++++ b/kernel/rcu/rcu.h +@@ -162,7 +162,7 @@ static inline bool rcu_seq_done_exact(unsigned long *sp, unsigned long s) + { + unsigned long cur_s = READ_ONCE(*sp); + +- return ULONG_CMP_GE(cur_s, s) || ULONG_CMP_LT(cur_s, s - (2 * RCU_SEQ_STATE_MASK + 1)); ++ return ULONG_CMP_GE(cur_s, s) || ULONG_CMP_LT(cur_s, s - (3 * RCU_SEQ_STATE_MASK + 1)); + } + + /* +diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c +index 8e52c1dd06284..4ed8632195217 100644 +--- a/kernel/rcu/tree.c ++++ b/kernel/rcu/tree.c +@@ -1822,10 +1822,14 @@ static noinline_for_stack bool rcu_gp_init(void) + + /* Advance to a new grace period and initialize state. */ + record_gp_stall_check_time(); ++ /* ++ * A new wait segment must be started before gp_seq advanced, so ++ * that previous gp waiters won't observe the new gp_seq. ++ */ ++ start_new_poll = rcu_sr_normal_gp_init(); + /* Record GP times before starting GP, hence rcu_seq_start(). */ + rcu_seq_start(&rcu_state.gp_seq); + ASSERT_EXCLUSIVE_WRITER(rcu_state.gp_seq); +- start_new_poll = rcu_sr_normal_gp_init(); + trace_rcu_grace_period(rcu_state.name, rcu_state.gp_seq, TPS("start")); + rcu_poll_gp_seq_start(&rcu_state.gp_seq_polled_snap); + raw_spin_unlock_irq_rcu_node(rnp); +@@ -4183,14 +4187,17 @@ EXPORT_SYMBOL_GPL(get_state_synchronize_rcu); + */ + void get_state_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp) + { +- struct rcu_node *rnp = rcu_get_root(); +- + /* + * Any prior manipulation of RCU-protected data must happen + * before the loads from ->gp_seq and ->expedited_sequence. + */ + smp_mb(); /* ^^^ */ +- rgosp->rgos_norm = rcu_seq_snap(&rnp->gp_seq); ++ ++ // Yes, rcu_state.gp_seq, not rnp_root->gp_seq, the latter's use ++ // in poll_state_synchronize_rcu_full() notwithstanding. Use of ++ // the latter here would result in too-short grace periods due to ++ // interactions with newly onlined CPUs. ++ rgosp->rgos_norm = rcu_seq_snap(&rcu_state.gp_seq); + rgosp->rgos_exp = rcu_seq_snap(&rcu_state.expedited_sequence); + } + EXPORT_SYMBOL_GPL(get_state_synchronize_rcu_full); +-- +2.39.5 + diff --git a/queue-6.12/rcu-fix-header-guard-for-rcu_all_qs.patch b/queue-6.12/rcu-fix-header-guard-for-rcu_all_qs.patch new file mode 100644 index 0000000000..a6f24489b9 --- /dev/null +++ b/queue-6.12/rcu-fix-header-guard-for-rcu_all_qs.patch @@ -0,0 +1,44 @@ +From 90137af73c9fb4c5d1ca5e75907c66f9a645827e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Dec 2024 20:06:52 -0800 +Subject: rcu: fix header guard for rcu_all_qs() + +From: Ankur Arora + +[ Upstream commit ad6b5b73ff565e88aca7a7d1286788d80c97ba71 ] + +rcu_all_qs() is defined for !CONFIG_PREEMPT_RCU but the declaration +is conditioned on CONFIG_PREEMPTION. + +With CONFIG_PREEMPT_LAZY, CONFIG_PREEMPTION=y does not imply +CONFIG_PREEMPT_RCU=y. + +Decouple the two. + +Cc: Paul E. McKenney +Reviewed-by: Frederic Weisbecker +Reviewed-by: Sebastian Andrzej Siewior +Signed-off-by: Ankur Arora +Signed-off-by: Paul E. McKenney +Signed-off-by: Boqun Feng +Signed-off-by: Sasha Levin +--- + include/linux/rcutree.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h +index 90a684f94776e..ae8b5cb475a36 100644 +--- a/include/linux/rcutree.h ++++ b/include/linux/rcutree.h +@@ -104,7 +104,7 @@ extern int rcu_scheduler_active; + void rcu_end_inkernel_boot(void); + bool rcu_inkernel_boot_has_ended(void); + bool rcu_is_watching(void); +-#ifndef CONFIG_PREEMPTION ++#ifndef CONFIG_PREEMPT_RCU + void rcu_all_qs(void); + #endif + +-- +2.39.5 + diff --git a/queue-6.12/rcu-handle-quiescent-states-for-preempt_rcu-n-preemp.patch b/queue-6.12/rcu-handle-quiescent-states-for-preempt_rcu-n-preemp.patch new file mode 100644 index 0000000000..8f0f538007 --- /dev/null +++ b/queue-6.12/rcu-handle-quiescent-states-for-preempt_rcu-n-preemp.patch @@ -0,0 +1,63 @@ +From 883a1da2dd727a10e12dd8756d383ce4cd97b91f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Dec 2024 20:06:56 -0800 +Subject: rcu: handle quiescent states for PREEMPT_RCU=n, PREEMPT_COUNT=y + +From: Ankur Arora + +[ Upstream commit 83b28cfe796464ebbde1cf7916c126da6d572685 ] + +With PREEMPT_RCU=n, cond_resched() provides urgently needed quiescent +states for read-side critical sections via rcu_all_qs(). +One reason why this was needed: lacking preempt-count, the tick +handler has no way of knowing whether it is executing in a +read-side critical section or not. + +With (PREEMPT_LAZY=y, PREEMPT_DYNAMIC=n), we get (PREEMPT_COUNT=y, +PREEMPT_RCU=n). In this configuration cond_resched() is a stub and +does not provide quiescent states via rcu_all_qs(). +(PREEMPT_RCU=y provides this information via rcu_read_unlock() and +its nesting counter.) + +So, use the availability of preempt_count() to report quiescent states +in rcu_flavor_sched_clock_irq(). + +Suggested-by: Paul E. McKenney +Reviewed-by: Sebastian Andrzej Siewior +Signed-off-by: Ankur Arora +Reviewed-by: Frederic Weisbecker +Signed-off-by: Paul E. McKenney +Signed-off-by: Boqun Feng +Signed-off-by: Sasha Levin +--- + kernel/rcu/tree_plugin.h | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h +index 1c7cbd145d5e3..75ba4d5788c0f 100644 +--- a/kernel/rcu/tree_plugin.h ++++ b/kernel/rcu/tree_plugin.h +@@ -974,13 +974,16 @@ static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp) + */ + static void rcu_flavor_sched_clock_irq(int user) + { +- if (user || rcu_is_cpu_rrupt_from_idle()) { ++ if (user || rcu_is_cpu_rrupt_from_idle() || ++ (IS_ENABLED(CONFIG_PREEMPT_COUNT) && ++ (preempt_count() == HARDIRQ_OFFSET))) { + + /* + * Get here if this CPU took its interrupt from user +- * mode or from the idle loop, and if this is not a +- * nested interrupt. In this case, the CPU is in +- * a quiescent state, so note it. ++ * mode, from the idle loop without this being a nested ++ * interrupt, or while not holding the task preempt count ++ * (with PREEMPT_COUNT=y). In this case, the CPU is in a ++ * quiescent state, so note it. + * + * No memory barrier is required here because rcu_qs() + * references only CPU-local variables that other CPUs +-- +2.39.5 + diff --git a/queue-6.12/rcu-handle-unstable-rdp-in-rcu_read_unlock_strict.patch b/queue-6.12/rcu-handle-unstable-rdp-in-rcu_read_unlock_strict.patch new file mode 100644 index 0000000000..134e9207d7 --- /dev/null +++ b/queue-6.12/rcu-handle-unstable-rdp-in-rcu_read_unlock_strict.patch @@ -0,0 +1,68 @@ +From 0245be6a50e054178f24b7fc6eb991a59758db8c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Dec 2024 20:06:55 -0800 +Subject: rcu: handle unstable rdp in rcu_read_unlock_strict() + +From: Ankur Arora + +[ Upstream commit fcf0e25ad4c8d14d2faab4d9a17040f31efce205 ] + +rcu_read_unlock_strict() can be called with preemption enabled +which can make for an unstable rdp and a racy norm value. + +Fix this by dropping the preempt-count in __rcu_read_unlock() +after the call to rcu_read_unlock_strict(), adjusting the +preempt-count check appropriately. + +Suggested-by: Frederic Weisbecker +Signed-off-by: Ankur Arora +Reviewed-by: Frederic Weisbecker +Signed-off-by: Paul E. McKenney +Signed-off-by: Boqun Feng +Signed-off-by: Sasha Levin +--- + include/linux/rcupdate.h | 2 +- + kernel/rcu/tree_plugin.h | 11 ++++++++++- + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h +index bd69ddc102fbc..0844ab3288519 100644 +--- a/include/linux/rcupdate.h ++++ b/include/linux/rcupdate.h +@@ -95,9 +95,9 @@ static inline void __rcu_read_lock(void) + + static inline void __rcu_read_unlock(void) + { +- preempt_enable(); + if (IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD)) + rcu_read_unlock_strict(); ++ preempt_enable(); + } + + static inline int rcu_preempt_depth(void) +diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h +index 75ba4d5788c0f..304e3405e6ec7 100644 +--- a/kernel/rcu/tree_plugin.h ++++ b/kernel/rcu/tree_plugin.h +@@ -832,8 +832,17 @@ void rcu_read_unlock_strict(void) + { + struct rcu_data *rdp; + +- if (irqs_disabled() || preempt_count() || !rcu_state.gp_kthread) ++ if (irqs_disabled() || in_atomic_preempt_off() || !rcu_state.gp_kthread) + return; ++ ++ /* ++ * rcu_report_qs_rdp() can only be invoked with a stable rdp and ++ * from the local CPU. ++ * ++ * The in_atomic_preempt_off() check ensures that we come here holding ++ * the last preempt_count (which will get dropped once we return to ++ * __rcu_read_unlock(). ++ */ + rdp = this_cpu_ptr(&rcu_data); + rdp->cpu_no_qs.b.norm = false; + rcu_report_qs_rdp(rdp); +-- +2.39.5 + diff --git a/queue-6.12/rdma-core-fix-best-page-size-finding-when-it-can-cro.patch b/queue-6.12/rdma-core-fix-best-page-size-finding-when-it-can-cro.patch new file mode 100644 index 0000000000..b4b48b0122 --- /dev/null +++ b/queue-6.12/rdma-core-fix-best-page-size-finding-when-it-can-cro.patch @@ -0,0 +1,139 @@ +From 5d73f58630925bb001cff677390e4817646f2277 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:16:23 +0000 +Subject: RDMA/core: Fix best page size finding when it can cross SG entries + +From: Michael Margolin + +[ Upstream commit 486055f5e09df959ad4e3aa4ee75b5c91ddeec2e ] + +A single scatter-gather entry is limited by a 32 bits "length" field +that is practically 4GB - PAGE_SIZE. This means that even when the +memory is physically contiguous, we might need more than one entry to +represent it. Additionally when using dmabuf, the sg_table might be +originated outside the subsystem and optimized for other needs. + +For instance an SGT of 16GB GPU continuous memory might look like this: +(a real life example) + +dma_address 34401400000, length fffff000 +dma_address 345013ff000, length fffff000 +dma_address 346013fe000, length fffff000 +dma_address 347013fd000, length fffff000 +dma_address 348013fc000, length 4000 + +Since ib_umem_find_best_pgsz works within SG entries, in the above case +we will result with the worst possible 4KB page size. + +Fix this by taking into consideration only the alignment of addresses of +real discontinuity points rather than treating SG entries as such, and +adjust the page iterator to correctly handle cross SG entry pages. + +There is currently an assumption that drivers do not ask for pages +bigger than maximal DMA size supported by their devices. + +Reviewed-by: Firas Jahjah +Reviewed-by: Yonatan Nachum +Signed-off-by: Michael Margolin +Link: https://patch.msgid.link/20250217141623.12428-1-mrgolin@amazon.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/umem.c | 36 ++++++++++++++++++++++++--------- + drivers/infiniband/core/verbs.c | 11 +++++----- + 2 files changed, 32 insertions(+), 15 deletions(-) + +diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c +index 07c571c7b6999..c5b6863947605 100644 +--- a/drivers/infiniband/core/umem.c ++++ b/drivers/infiniband/core/umem.c +@@ -80,9 +80,12 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem, + unsigned long pgsz_bitmap, + unsigned long virt) + { +- struct scatterlist *sg; ++ unsigned long curr_len = 0; ++ dma_addr_t curr_base = ~0; + unsigned long va, pgoff; ++ struct scatterlist *sg; + dma_addr_t mask; ++ dma_addr_t end; + int i; + + umem->iova = va = virt; +@@ -107,17 +110,30 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem, + pgoff = umem->address & ~PAGE_MASK; + + for_each_sgtable_dma_sg(&umem->sgt_append.sgt, sg, i) { +- /* Walk SGL and reduce max page size if VA/PA bits differ +- * for any address. ++ /* If the current entry is physically contiguous with the previous ++ * one, no need to take its start addresses into consideration. + */ +- mask |= (sg_dma_address(sg) + pgoff) ^ va; ++ if (check_add_overflow(curr_base, curr_len, &end) || ++ end != sg_dma_address(sg)) { ++ ++ curr_base = sg_dma_address(sg); ++ curr_len = 0; ++ ++ /* Reduce max page size if VA/PA bits differ */ ++ mask |= (curr_base + pgoff) ^ va; ++ ++ /* The alignment of any VA matching a discontinuity point ++ * in the physical memory sets the maximum possible page ++ * size as this must be a starting point of a new page that ++ * needs to be aligned. ++ */ ++ if (i != 0) ++ mask |= va; ++ } ++ ++ curr_len += sg_dma_len(sg); + va += sg_dma_len(sg) - pgoff; +- /* Except for the last entry, the ending iova alignment sets +- * the maximum possible page size as the low bits of the iova +- * must be zero when starting the next chunk. +- */ +- if (i != (umem->sgt_append.sgt.nents - 1)) +- mask |= va; ++ + pgoff = 0; + } + +diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c +index 473ee0831307c..dc40001072a5e 100644 +--- a/drivers/infiniband/core/verbs.c ++++ b/drivers/infiniband/core/verbs.c +@@ -3109,22 +3109,23 @@ EXPORT_SYMBOL(__rdma_block_iter_start); + bool __rdma_block_iter_next(struct ib_block_iter *biter) + { + unsigned int block_offset; +- unsigned int sg_delta; ++ unsigned int delta; + + if (!biter->__sg_nents || !biter->__sg) + return false; + + biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance; + block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1); +- sg_delta = BIT_ULL(biter->__pg_bit) - block_offset; ++ delta = BIT_ULL(biter->__pg_bit) - block_offset; + +- if (sg_dma_len(biter->__sg) - biter->__sg_advance > sg_delta) { +- biter->__sg_advance += sg_delta; +- } else { ++ while (biter->__sg_nents && biter->__sg && ++ sg_dma_len(biter->__sg) - biter->__sg_advance <= delta) { ++ delta -= sg_dma_len(biter->__sg) - biter->__sg_advance; + biter->__sg_advance = 0; + biter->__sg = sg_next(biter->__sg); + biter->__sg_nents--; + } ++ biter->__sg_advance += delta; + + return true; + } +-- +2.39.5 + diff --git a/queue-6.12/rdma-uverbs-propagate-errors-from-rdma_lookup_get_uo.patch b/queue-6.12/rdma-uverbs-propagate-errors-from-rdma_lookup_get_uo.patch new file mode 100644 index 0000000000..ca6c8f1c4e --- /dev/null +++ b/queue-6.12/rdma-uverbs-propagate-errors-from-rdma_lookup_get_uo.patch @@ -0,0 +1,432 @@ +From 98910dac3d7637cba7c3c001616363ad06ea2713 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 15:54:13 +0200 +Subject: RDMA/uverbs: Propagate errors from rdma_lookup_get_uobject() + +From: Maher Sanalla + +[ Upstream commit 81f8f7454ad9e0bf95efdec6542afdc9a6ab1e24 ] + +Currently, the IB uverbs API calls uobj_get_uobj_read(), which in turn +uses the rdma_lookup_get_uobject() helper to retrieve user objects. +In case of failure, uobj_get_uobj_read() returns NULL, overriding the +error code from rdma_lookup_get_uobject(). The IB uverbs API then +translates this NULL to -EINVAL, masking the actual error and +complicating debugging. For example, applications calling ibv_modify_qp +that fails with EBUSY when retrieving the QP uobject will see the +overridden error code EINVAL instead, masking the actual error. + +Furthermore, based on rdma-core commit: +"2a22f1ced5f3 ("Merge pull request #1568 from jakemoroni/master")" +Kernel's IB uverbs return values are either ignored and passed on as is +to application or overridden with other errnos in a few cases. + +Thus, to improve error reporting and debuggability, propagate the +original error from rdma_lookup_get_uobject() instead of replacing it +with EINVAL. + +Signed-off-by: Maher Sanalla +Link: https://patch.msgid.link/64f9d3711b183984e939962c2f83383904f97dfb.1740577869.git.leon@kernel.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/uverbs_cmd.c | 144 ++++++++++++++------------- + include/rdma/uverbs_std_types.h | 2 +- + 2 files changed, 77 insertions(+), 69 deletions(-) + +diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c +index edef79daed3fa..535bb99ed9f5f 100644 +--- a/drivers/infiniband/core/uverbs_cmd.c ++++ b/drivers/infiniband/core/uverbs_cmd.c +@@ -718,8 +718,8 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs) + goto err_free; + + pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs); +- if (!pd) { +- ret = -EINVAL; ++ if (IS_ERR(pd)) { ++ ret = PTR_ERR(pd); + goto err_free; + } + +@@ -809,8 +809,8 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs) + if (cmd.flags & IB_MR_REREG_PD) { + new_pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, + attrs); +- if (!new_pd) { +- ret = -EINVAL; ++ if (IS_ERR(new_pd)) { ++ ret = PTR_ERR(new_pd); + goto put_uobjs; + } + } else { +@@ -919,8 +919,8 @@ static int ib_uverbs_alloc_mw(struct uverbs_attr_bundle *attrs) + return PTR_ERR(uobj); + + pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs); +- if (!pd) { +- ret = -EINVAL; ++ if (IS_ERR(pd)) { ++ ret = PTR_ERR(pd); + goto err_free; + } + +@@ -1127,8 +1127,8 @@ static int ib_uverbs_resize_cq(struct uverbs_attr_bundle *attrs) + return ret; + + cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs); +- if (!cq) +- return -EINVAL; ++ if (IS_ERR(cq)) ++ return PTR_ERR(cq); + + ret = cq->device->ops.resize_cq(cq, cmd.cqe, &attrs->driver_udata); + if (ret) +@@ -1189,8 +1189,8 @@ static int ib_uverbs_poll_cq(struct uverbs_attr_bundle *attrs) + return ret; + + cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs); +- if (!cq) +- return -EINVAL; ++ if (IS_ERR(cq)) ++ return PTR_ERR(cq); + + /* we copy a struct ib_uverbs_poll_cq_resp to user space */ + header_ptr = attrs->ucore.outbuf; +@@ -1238,8 +1238,8 @@ static int ib_uverbs_req_notify_cq(struct uverbs_attr_bundle *attrs) + return ret; + + cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs); +- if (!cq) +- return -EINVAL; ++ if (IS_ERR(cq)) ++ return PTR_ERR(cq); + + ib_req_notify_cq(cq, cmd.solicited_only ? + IB_CQ_SOLICITED : IB_CQ_NEXT_COMP); +@@ -1321,8 +1321,8 @@ static int create_qp(struct uverbs_attr_bundle *attrs, + ind_tbl = uobj_get_obj_read(rwq_ind_table, + UVERBS_OBJECT_RWQ_IND_TBL, + cmd->rwq_ind_tbl_handle, attrs); +- if (!ind_tbl) { +- ret = -EINVAL; ++ if (IS_ERR(ind_tbl)) { ++ ret = PTR_ERR(ind_tbl); + goto err_put; + } + +@@ -1360,8 +1360,10 @@ static int create_qp(struct uverbs_attr_bundle *attrs, + if (cmd->is_srq) { + srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, + cmd->srq_handle, attrs); +- if (!srq || srq->srq_type == IB_SRQT_XRC) { +- ret = -EINVAL; ++ if (IS_ERR(srq) || ++ srq->srq_type == IB_SRQT_XRC) { ++ ret = IS_ERR(srq) ? PTR_ERR(srq) : ++ -EINVAL; + goto err_put; + } + } +@@ -1371,23 +1373,29 @@ static int create_qp(struct uverbs_attr_bundle *attrs, + rcq = uobj_get_obj_read( + cq, UVERBS_OBJECT_CQ, + cmd->recv_cq_handle, attrs); +- if (!rcq) { +- ret = -EINVAL; ++ if (IS_ERR(rcq)) { ++ ret = PTR_ERR(rcq); + goto err_put; + } + } + } + } + +- if (has_sq) ++ if (has_sq) { + scq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, + cmd->send_cq_handle, attrs); ++ if (IS_ERR(scq)) { ++ ret = PTR_ERR(scq); ++ goto err_put; ++ } ++ } ++ + if (!ind_tbl && cmd->qp_type != IB_QPT_XRC_INI) + rcq = rcq ?: scq; + pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd->pd_handle, + attrs); +- if (!pd || (!scq && has_sq)) { +- ret = -EINVAL; ++ if (IS_ERR(pd)) { ++ ret = PTR_ERR(pd); + goto err_put; + } + +@@ -1482,18 +1490,18 @@ static int create_qp(struct uverbs_attr_bundle *attrs, + err_put: + if (!IS_ERR(xrcd_uobj)) + uobj_put_read(xrcd_uobj); +- if (pd) ++ if (!IS_ERR_OR_NULL(pd)) + uobj_put_obj_read(pd); +- if (scq) ++ if (!IS_ERR_OR_NULL(scq)) + rdma_lookup_put_uobject(&scq->uobject->uevent.uobject, + UVERBS_LOOKUP_READ); +- if (rcq && rcq != scq) ++ if (!IS_ERR_OR_NULL(rcq) && rcq != scq) + rdma_lookup_put_uobject(&rcq->uobject->uevent.uobject, + UVERBS_LOOKUP_READ); +- if (srq) ++ if (!IS_ERR_OR_NULL(srq)) + rdma_lookup_put_uobject(&srq->uobject->uevent.uobject, + UVERBS_LOOKUP_READ); +- if (ind_tbl) ++ if (!IS_ERR_OR_NULL(ind_tbl)) + uobj_put_obj_read(ind_tbl); + + uobj_alloc_abort(&obj->uevent.uobject, attrs); +@@ -1655,8 +1663,8 @@ static int ib_uverbs_query_qp(struct uverbs_attr_bundle *attrs) + } + + qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs); +- if (!qp) { +- ret = -EINVAL; ++ if (IS_ERR(qp)) { ++ ret = PTR_ERR(qp); + goto out; + } + +@@ -1761,8 +1769,8 @@ static int modify_qp(struct uverbs_attr_bundle *attrs, + + qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd->base.qp_handle, + attrs); +- if (!qp) { +- ret = -EINVAL; ++ if (IS_ERR(qp)) { ++ ret = PTR_ERR(qp); + goto out; + } + +@@ -2028,8 +2036,8 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs) + return -ENOMEM; + + qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs); +- if (!qp) { +- ret = -EINVAL; ++ if (IS_ERR(qp)) { ++ ret = PTR_ERR(qp); + goto out; + } + +@@ -2066,9 +2074,9 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs) + + ud->ah = uobj_get_obj_read(ah, UVERBS_OBJECT_AH, + user_wr->wr.ud.ah, attrs); +- if (!ud->ah) { ++ if (IS_ERR(ud->ah)) { ++ ret = PTR_ERR(ud->ah); + kfree(ud); +- ret = -EINVAL; + goto out_put; + } + ud->remote_qpn = user_wr->wr.ud.remote_qpn; +@@ -2305,8 +2313,8 @@ static int ib_uverbs_post_recv(struct uverbs_attr_bundle *attrs) + return PTR_ERR(wr); + + qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs); +- if (!qp) { +- ret = -EINVAL; ++ if (IS_ERR(qp)) { ++ ret = PTR_ERR(qp); + goto out; + } + +@@ -2356,8 +2364,8 @@ static int ib_uverbs_post_srq_recv(struct uverbs_attr_bundle *attrs) + return PTR_ERR(wr); + + srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs); +- if (!srq) { +- ret = -EINVAL; ++ if (IS_ERR(srq)) { ++ ret = PTR_ERR(srq); + goto out; + } + +@@ -2413,8 +2421,8 @@ static int ib_uverbs_create_ah(struct uverbs_attr_bundle *attrs) + } + + pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs); +- if (!pd) { +- ret = -EINVAL; ++ if (IS_ERR(pd)) { ++ ret = PTR_ERR(pd); + goto err; + } + +@@ -2483,8 +2491,8 @@ static int ib_uverbs_attach_mcast(struct uverbs_attr_bundle *attrs) + return ret; + + qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs); +- if (!qp) +- return -EINVAL; ++ if (IS_ERR(qp)) ++ return PTR_ERR(qp); + + obj = qp->uobject; + +@@ -2533,8 +2541,8 @@ static int ib_uverbs_detach_mcast(struct uverbs_attr_bundle *attrs) + return ret; + + qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs); +- if (!qp) +- return -EINVAL; ++ if (IS_ERR(qp)) ++ return PTR_ERR(qp); + + obj = qp->uobject; + mutex_lock(&obj->mcast_lock); +@@ -2668,8 +2676,8 @@ static int kern_spec_to_ib_spec_action(struct uverbs_attr_bundle *attrs, + UVERBS_OBJECT_FLOW_ACTION, + kern_spec->action.handle, + attrs); +- if (!ib_spec->action.act) +- return -EINVAL; ++ if (IS_ERR(ib_spec->action.act)) ++ return PTR_ERR(ib_spec->action.act); + ib_spec->action.size = + sizeof(struct ib_flow_spec_action_handle); + flow_resources_add(uflow_res, +@@ -2686,8 +2694,8 @@ static int kern_spec_to_ib_spec_action(struct uverbs_attr_bundle *attrs, + UVERBS_OBJECT_COUNTERS, + kern_spec->flow_count.handle, + attrs); +- if (!ib_spec->flow_count.counters) +- return -EINVAL; ++ if (IS_ERR(ib_spec->flow_count.counters)) ++ return PTR_ERR(ib_spec->flow_count.counters); + ib_spec->flow_count.size = + sizeof(struct ib_flow_spec_action_count); + flow_resources_add(uflow_res, +@@ -2905,14 +2913,14 @@ static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs) + return PTR_ERR(obj); + + pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs); +- if (!pd) { +- err = -EINVAL; ++ if (IS_ERR(pd)) { ++ err = PTR_ERR(pd); + goto err_uobj; + } + + cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs); +- if (!cq) { +- err = -EINVAL; ++ if (IS_ERR(cq)) { ++ err = PTR_ERR(cq); + goto err_put_pd; + } + +@@ -3013,8 +3021,8 @@ static int ib_uverbs_ex_modify_wq(struct uverbs_attr_bundle *attrs) + return -EINVAL; + + wq = uobj_get_obj_read(wq, UVERBS_OBJECT_WQ, cmd.wq_handle, attrs); +- if (!wq) +- return -EINVAL; ++ if (IS_ERR(wq)) ++ return PTR_ERR(wq); + + if (cmd.attr_mask & IB_WQ_FLAGS) { + wq_attr.flags = cmd.flags; +@@ -3097,8 +3105,8 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs) + num_read_wqs++) { + wq = uobj_get_obj_read(wq, UVERBS_OBJECT_WQ, + wqs_handles[num_read_wqs], attrs); +- if (!wq) { +- err = -EINVAL; ++ if (IS_ERR(wq)) { ++ err = PTR_ERR(wq); + goto put_wqs; + } + +@@ -3253,8 +3261,8 @@ static int ib_uverbs_ex_create_flow(struct uverbs_attr_bundle *attrs) + } + + qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs); +- if (!qp) { +- err = -EINVAL; ++ if (IS_ERR(qp)) { ++ err = PTR_ERR(qp); + goto err_uobj; + } + +@@ -3400,15 +3408,15 @@ static int __uverbs_create_xsrq(struct uverbs_attr_bundle *attrs, + if (ib_srq_has_cq(cmd->srq_type)) { + attr.ext.cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, + cmd->cq_handle, attrs); +- if (!attr.ext.cq) { +- ret = -EINVAL; ++ if (IS_ERR(attr.ext.cq)) { ++ ret = PTR_ERR(attr.ext.cq); + goto err_put_xrcd; + } + } + + pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd->pd_handle, attrs); +- if (!pd) { +- ret = -EINVAL; ++ if (IS_ERR(pd)) { ++ ret = PTR_ERR(pd); + goto err_put_cq; + } + +@@ -3515,8 +3523,8 @@ static int ib_uverbs_modify_srq(struct uverbs_attr_bundle *attrs) + return ret; + + srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs); +- if (!srq) +- return -EINVAL; ++ if (IS_ERR(srq)) ++ return PTR_ERR(srq); + + attr.max_wr = cmd.max_wr; + attr.srq_limit = cmd.srq_limit; +@@ -3543,8 +3551,8 @@ static int ib_uverbs_query_srq(struct uverbs_attr_bundle *attrs) + return ret; + + srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs); +- if (!srq) +- return -EINVAL; ++ if (IS_ERR(srq)) ++ return PTR_ERR(srq); + + ret = ib_query_srq(srq, &attr); + +@@ -3669,8 +3677,8 @@ static int ib_uverbs_ex_modify_cq(struct uverbs_attr_bundle *attrs) + return -EOPNOTSUPP; + + cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs); +- if (!cq) +- return -EINVAL; ++ if (IS_ERR(cq)) ++ return PTR_ERR(cq); + + ret = rdma_set_cq_moderation(cq, cmd.attr.cq_count, cmd.attr.cq_period); + +diff --git a/include/rdma/uverbs_std_types.h b/include/rdma/uverbs_std_types.h +index fe05121169589..555ea3d142a46 100644 +--- a/include/rdma/uverbs_std_types.h ++++ b/include/rdma/uverbs_std_types.h +@@ -34,7 +34,7 @@ + static inline void *_uobj_get_obj_read(struct ib_uobject *uobj) + { + if (IS_ERR(uobj)) +- return NULL; ++ return ERR_CAST(uobj); + return uobj->object; + } + #define uobj_get_obj_read(_object, _type, _id, _attrs) \ +-- +2.39.5 + diff --git a/queue-6.12/regulator-ad5398-add-device-tree-support.patch b/queue-6.12/regulator-ad5398-add-device-tree-support.patch new file mode 100644 index 0000000000..f451ad21f7 --- /dev/null +++ b/queue-6.12/regulator-ad5398-add-device-tree-support.patch @@ -0,0 +1,63 @@ +From ad33376242fedac840a21f3199e78d870993e949 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jan 2025 17:31:43 +0000 +Subject: regulator: ad5398: Add device tree support + +From: Isaac Scott + +[ Upstream commit 5a6a461079decea452fdcae955bccecf92e07e97 ] + +Previously, the ad5398 driver used only platform_data, which is +deprecated in favour of device tree. This caused the AD5398 to fail to +probe as it could not load its init_data. If the AD5398 has a device +tree node, pull the init_data from there using +of_get_regulator_init_data. + +Signed-off-by: Isaac Scott +Acked-by: Michael Hennerich +Link: https://patch.msgid.link/20250128173143.959600-4-isaac.scott@ideasonboard.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/ad5398.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c +index 40f7dba42b5ad..404cbe32711e7 100644 +--- a/drivers/regulator/ad5398.c ++++ b/drivers/regulator/ad5398.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + #define AD5398_CURRENT_EN_MASK 0x8000 + +@@ -221,15 +222,20 @@ static int ad5398_probe(struct i2c_client *client) + const struct ad5398_current_data_format *df = + (struct ad5398_current_data_format *)id->driver_data; + +- if (!init_data) +- return -EINVAL; +- + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + config.dev = &client->dev; ++ if (client->dev.of_node) ++ init_data = of_get_regulator_init_data(&client->dev, ++ client->dev.of_node, ++ &ad5398_reg); ++ if (!init_data) ++ return -EINVAL; ++ + config.init_data = init_data; ++ config.of_node = client->dev.of_node; + config.driver_data = chip; + + chip->client = client; +-- +2.39.5 + diff --git a/queue-6.12/remoteproc-qcom_wcnss-handle-platforms-with-only-sin.patch b/queue-6.12/remoteproc-qcom_wcnss-handle-platforms-with-only-sin.patch new file mode 100644 index 0000000000..14de03291e --- /dev/null +++ b/queue-6.12/remoteproc-qcom_wcnss-handle-platforms-with-only-sin.patch @@ -0,0 +1,113 @@ +From 35475f3e1e2054f9549f75e0325e1512f5c4c2f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 20:56:48 +0100 +Subject: remoteproc: qcom_wcnss: Handle platforms with only single power + domain +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Matti Lehtimäki + +[ Upstream commit 65991ea8a6d1e68effdc01d95ebe39f1653f7b71 ] + +Both MSM8974 and MSM8226 have only CX as power domain with MX & PX being +handled as regulators. Handle this case by reodering pd_names to have CX +first, and handling that the driver core will already attach a single +power domain internally. + +Signed-off-by: Matti Lehtimäki +[luca: minor changes] +Signed-off-by: Luca Weiss +Link: https://lore.kernel.org/r/20250206-wcnss-singlepd-v2-2-9a53ee953dee@lucaweiss.eu +[bjorn: Added missing braces to else after multi-statement if] +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/qcom_wcnss.c | 33 ++++++++++++++++++++++++++------- + 1 file changed, 26 insertions(+), 7 deletions(-) + +diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c +index a7bb9da27029d..735d373a9f636 100644 +--- a/drivers/remoteproc/qcom_wcnss.c ++++ b/drivers/remoteproc/qcom_wcnss.c +@@ -117,10 +117,10 @@ static const struct wcnss_data pronto_v1_data = { + .pmu_offset = 0x1004, + .spare_offset = 0x1088, + +- .pd_names = { "mx", "cx" }, ++ .pd_names = { "cx", "mx" }, + .vregs = (struct wcnss_vreg_info[]) { +- { "vddmx", 950000, 1150000, 0 }, + { "vddcx", .super_turbo = true}, ++ { "vddmx", 950000, 1150000, 0 }, + { "vddpx", 1800000, 1800000, 0 }, + }, + .num_pd_vregs = 2, +@@ -131,10 +131,10 @@ static const struct wcnss_data pronto_v2_data = { + .pmu_offset = 0x1004, + .spare_offset = 0x1088, + +- .pd_names = { "mx", "cx" }, ++ .pd_names = { "cx", "mx" }, + .vregs = (struct wcnss_vreg_info[]) { +- { "vddmx", 1287500, 1287500, 0 }, + { "vddcx", .super_turbo = true }, ++ { "vddmx", 1287500, 1287500, 0 }, + { "vddpx", 1800000, 1800000, 0 }, + }, + .num_pd_vregs = 2, +@@ -397,8 +397,17 @@ static irqreturn_t wcnss_stop_ack_interrupt(int irq, void *dev) + static int wcnss_init_pds(struct qcom_wcnss *wcnss, + const char * const pd_names[WCNSS_MAX_PDS]) + { ++ struct device *dev = wcnss->dev; + int i, ret; + ++ /* Handle single power domain */ ++ if (dev->pm_domain) { ++ wcnss->pds[0] = dev; ++ wcnss->num_pds = 1; ++ pm_runtime_enable(dev); ++ return 0; ++ } ++ + for (i = 0; i < WCNSS_MAX_PDS; i++) { + if (!pd_names[i]) + break; +@@ -418,8 +427,15 @@ static int wcnss_init_pds(struct qcom_wcnss *wcnss, + + static void wcnss_release_pds(struct qcom_wcnss *wcnss) + { ++ struct device *dev = wcnss->dev; + int i; + ++ /* Handle single power domain */ ++ if (wcnss->num_pds == 1 && dev->pm_domain) { ++ pm_runtime_disable(dev); ++ return; ++ } ++ + for (i = 0; i < wcnss->num_pds; i++) + dev_pm_domain_detach(wcnss->pds[i], false); + } +@@ -437,10 +453,13 @@ static int wcnss_init_regulators(struct qcom_wcnss *wcnss, + * the regulators for the power domains. For old device trees we need to + * reserve extra space to manage them through the regulator interface. + */ +- if (wcnss->num_pds) +- info += num_pd_vregs; +- else ++ if (wcnss->num_pds) { ++ info += wcnss->num_pds; ++ /* Handle single power domain case */ ++ num_vregs += num_pd_vregs - wcnss->num_pds; ++ } else { + num_vregs += num_pd_vregs; ++ } + + bulk = devm_kcalloc(wcnss->dev, + num_vregs, sizeof(struct regulator_bulk_data), +-- +2.39.5 + diff --git a/queue-6.12/revert-drm-amd-display-exit-idle-optimizations-befor.patch b/queue-6.12/revert-drm-amd-display-exit-idle-optimizations-befor.patch new file mode 100644 index 0000000000..ba84423315 --- /dev/null +++ b/queue-6.12/revert-drm-amd-display-exit-idle-optimizations-befor.patch @@ -0,0 +1,58 @@ +From 63197dda759fda30c933234215efa3b7083c1b98 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jan 2025 13:29:51 +0800 +Subject: Revert "drm/amd/display: Exit idle optimizations before attempt to + access PHY" + +From: Brandon Syu + +[ Upstream commit be704e5ef4bd66dee9bb3f876964327e3a247d31 ] + +This reverts commit de612738e9771bd66aeb20044486c457c512f684. + +Reason to revert: screen flashes or gray screen appeared half of the +screen after resume from S4/S5. + +Reviewed-by: Charlene Liu +Signed-off-by: Brandon Syu +Signed-off-by: Alex Hung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +index 59457ca24e1dc..ccdc9d4101863 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +@@ -1888,7 +1888,6 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) + bool can_apply_edp_fast_boot = false; + bool can_apply_seamless_boot = false; + bool keep_edp_vdd_on = false; +- struct dc_bios *dcb = dc->ctx->dc_bios; + DC_LOGGER_INIT(); + + +@@ -1965,8 +1964,6 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) + hws->funcs.edp_backlight_control(edp_link_with_sink, false); + } + /*resume from S3, no vbios posting, no need to power down again*/ +- if (dcb && dcb->funcs && !dcb->funcs->is_accelerated_mode(dcb)) +- clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr); + + power_down_all_hw_blocks(dc); + +@@ -1979,8 +1976,6 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) + disable_vga_and_power_gate_all_controllers(dc); + if (edp_link_with_sink && !keep_edp_vdd_on) + dc->hwss.edp_power_control(edp_link_with_sink, false); +- if (dcb && dcb->funcs && !dcb->funcs->is_accelerated_mode(dcb)) +- clk_mgr_optimize_pwr_state(dc, dc->clk_mgr); + } + bios_set_scratch_acc_mode_change(dc->ctx->dc_bios, 1); + } +-- +2.39.5 + diff --git a/queue-6.12/revert-drm-amd-display-request-hw-cursor-on-dcn3.2-w.patch b/queue-6.12/revert-drm-amd-display-request-hw-cursor-on-dcn3.2-w.patch new file mode 100644 index 0000000000..4675b63ed5 --- /dev/null +++ b/queue-6.12/revert-drm-amd-display-request-hw-cursor-on-dcn3.2-w.patch @@ -0,0 +1,38 @@ +From fc95fbbd339c2642e2d89f01b63122815d171c71 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 11:46:52 -0500 +Subject: Revert "drm/amd/display: Request HW cursor on DCN3.2 with SubVP" + +From: Leo Zeng + +[ Upstream commit 8ae6dfc0b61b170cf13832d4cfe2a0c744e621a7 ] + +This reverts commit 13437c91606c9232c747475e202fe3827cd53264. + +Reason to revert: idle power regression found in testing. + +Reviewed-by: Dillon Varone +Signed-off-by: Leo Zeng +Signed-off-by: Roman Li +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +index 56dda686e2992..6f490d8d7038c 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +@@ -626,7 +626,6 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc, + * - Not TMZ surface + */ + if (pipe->plane_state && !pipe->top_pipe && !pipe->prev_odm_pipe && !dcn32_is_center_timing(pipe) && +- !pipe->stream->hw_cursor_req && + !(pipe->stream->timing.pix_clk_100hz / 10000 > DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ) && + (!dcn32_is_psr_capable(pipe) || (context->stream_count == 1 && dc->caps.dmub_caps.subvp_psr)) && + dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_NONE && +-- +2.39.5 + diff --git a/queue-6.12/riscv-allow-nommu-kernels-to-access-all-of-ram.patch b/queue-6.12/riscv-allow-nommu-kernels-to-access-all-of-ram.patch new file mode 100644 index 0000000000..7c6cfce2c4 --- /dev/null +++ b/queue-6.12/riscv-allow-nommu-kernels-to-access-all-of-ram.patch @@ -0,0 +1,80 @@ +From 00aad305a360310aefb97a5346b709aec43790fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 26 Oct 2024 10:13:54 -0700 +Subject: riscv: Allow NOMMU kernels to access all of RAM + +From: Samuel Holland + +[ Upstream commit 2c0391b29b27f315c1b4c29ffde66f50b29fab99 ] + +NOMMU kernels currently cannot access memory below the kernel link +address. Remove this restriction by setting PAGE_OFFSET to the actual +start of RAM, as determined from the devicetree. The kernel link address +must be a constant, so keep using CONFIG_PAGE_OFFSET for that purpose. + +Signed-off-by: Samuel Holland +Reviewed-by: Jesse Taube +Link: https://lore.kernel.org/r/20241026171441.3047904-3-samuel.holland@sifive.com +Signed-off-by: Palmer Dabbelt +Signed-off-by: Sasha Levin +--- + arch/riscv/include/asm/page.h | 12 ++++-------- + arch/riscv/include/asm/pgtable.h | 2 +- + 2 files changed, 5 insertions(+), 9 deletions(-) + +diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h +index febf820d50583..e8beadc2bffda 100644 +--- a/arch/riscv/include/asm/page.h ++++ b/arch/riscv/include/asm/page.h +@@ -26,12 +26,9 @@ + * When not using MMU this corresponds to the first free page in + * physical memory (aligned on a page boundary). + */ +-#ifdef CONFIG_64BIT + #ifdef CONFIG_MMU ++#ifdef CONFIG_64BIT + #define PAGE_OFFSET kernel_map.page_offset +-#else +-#define PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL) +-#endif + /* + * By default, CONFIG_PAGE_OFFSET value corresponds to SV57 address space so + * define the PAGE_OFFSET value for SV48 and SV39. +@@ -41,6 +38,9 @@ + #else + #define PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL) + #endif /* CONFIG_64BIT */ ++#else ++#define PAGE_OFFSET ((unsigned long)phys_ram_base) ++#endif /* CONFIG_MMU */ + + #ifndef __ASSEMBLY__ + +@@ -97,11 +97,7 @@ typedef struct page *pgtable_t; + #define MIN_MEMBLOCK_ADDR 0 + #endif + +-#ifdef CONFIG_MMU + #define ARCH_PFN_OFFSET (PFN_DOWN((unsigned long)phys_ram_base)) +-#else +-#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT) +-#endif /* CONFIG_MMU */ + + struct kernel_mapping { + unsigned long page_offset; +diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h +index c0866ada5bbc4..479550cdb440f 100644 +--- a/arch/riscv/include/asm/pgtable.h ++++ b/arch/riscv/include/asm/pgtable.h +@@ -12,7 +12,7 @@ + #include + + #ifndef CONFIG_MMU +-#define KERNEL_LINK_ADDR PAGE_OFFSET ++#define KERNEL_LINK_ADDR _AC(CONFIG_PAGE_OFFSET, UL) + #define KERN_VIRT_SIZE (UL(-1)) + #else + +-- +2.39.5 + diff --git a/queue-6.12/riscv-call-secondary-mmu-notifier-when-flushing-the-.patch b/queue-6.12/riscv-call-secondary-mmu-notifier-when-flushing-the-.patch new file mode 100644 index 0000000000..04a5bb0180 --- /dev/null +++ b/queue-6.12/riscv-call-secondary-mmu-notifier-when-flushing-the-.patch @@ -0,0 +1,140 @@ +From fb21ddcf8fce2edf49b918928760bcd9c2388b90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 15:24:24 +0100 +Subject: riscv: Call secondary mmu notifier when flushing the tlb +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alexandre Ghiti + +[ Upstream commit d9be2b9b60497a82aeceec3a98d8b37fdd2960f2 ] + +This is required to allow the IOMMU driver to correctly flush its own +TLB. + +Reviewed-by: Clément Léger +Reviewed-by: Samuel Holland +Link: https://lore.kernel.org/r/20250113142424.30487-1-alexghiti@rivosinc.com +Signed-off-by: Alexandre Ghiti +Signed-off-by: Sasha Levin +--- + arch/riscv/mm/tlbflush.c | 37 ++++++++++++++++++++++--------------- + 1 file changed, 22 insertions(+), 15 deletions(-) + +diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c +index 9b6e86ce38674..bb77607c87aa2 100644 +--- a/arch/riscv/mm/tlbflush.c ++++ b/arch/riscv/mm/tlbflush.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -78,10 +79,17 @@ static void __ipi_flush_tlb_range_asid(void *info) + local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid); + } + +-static void __flush_tlb_range(const struct cpumask *cmask, unsigned long asid, ++static inline unsigned long get_mm_asid(struct mm_struct *mm) ++{ ++ return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID; ++} ++ ++static void __flush_tlb_range(struct mm_struct *mm, ++ const struct cpumask *cmask, + unsigned long start, unsigned long size, + unsigned long stride) + { ++ unsigned long asid = get_mm_asid(mm); + unsigned int cpu; + + if (cpumask_empty(cmask)) +@@ -105,30 +113,26 @@ static void __flush_tlb_range(const struct cpumask *cmask, unsigned long asid, + } + + put_cpu(); +-} + +-static inline unsigned long get_mm_asid(struct mm_struct *mm) +-{ +- return cntx2asid(atomic_long_read(&mm->context.id)); ++ if (mm) ++ mmu_notifier_arch_invalidate_secondary_tlbs(mm, start, start + size); + } + + void flush_tlb_mm(struct mm_struct *mm) + { +- __flush_tlb_range(mm_cpumask(mm), get_mm_asid(mm), +- 0, FLUSH_TLB_MAX_SIZE, PAGE_SIZE); ++ __flush_tlb_range(mm, mm_cpumask(mm), 0, FLUSH_TLB_MAX_SIZE, PAGE_SIZE); + } + + void flush_tlb_mm_range(struct mm_struct *mm, + unsigned long start, unsigned long end, + unsigned int page_size) + { +- __flush_tlb_range(mm_cpumask(mm), get_mm_asid(mm), +- start, end - start, page_size); ++ __flush_tlb_range(mm, mm_cpumask(mm), start, end - start, page_size); + } + + void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) + { +- __flush_tlb_range(mm_cpumask(vma->vm_mm), get_mm_asid(vma->vm_mm), ++ __flush_tlb_range(vma->vm_mm, mm_cpumask(vma->vm_mm), + addr, PAGE_SIZE, PAGE_SIZE); + } + +@@ -161,13 +165,13 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + } + } + +- __flush_tlb_range(mm_cpumask(vma->vm_mm), get_mm_asid(vma->vm_mm), ++ __flush_tlb_range(vma->vm_mm, mm_cpumask(vma->vm_mm), + start, end - start, stride_size); + } + + void flush_tlb_kernel_range(unsigned long start, unsigned long end) + { +- __flush_tlb_range(cpu_online_mask, FLUSH_TLB_NO_ASID, ++ __flush_tlb_range(NULL, cpu_online_mask, + start, end - start, PAGE_SIZE); + } + +@@ -175,7 +179,7 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end) + void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end) + { +- __flush_tlb_range(mm_cpumask(vma->vm_mm), get_mm_asid(vma->vm_mm), ++ __flush_tlb_range(vma->vm_mm, mm_cpumask(vma->vm_mm), + start, end - start, PMD_SIZE); + } + #endif +@@ -189,7 +193,10 @@ void arch_tlbbatch_add_pending(struct arch_tlbflush_unmap_batch *batch, + struct mm_struct *mm, + unsigned long uaddr) + { ++ unsigned long start = uaddr & PAGE_MASK; ++ + cpumask_or(&batch->cpumask, &batch->cpumask, mm_cpumask(mm)); ++ mmu_notifier_arch_invalidate_secondary_tlbs(mm, start, start + PAGE_SIZE); + } + + void arch_flush_tlb_batched_pending(struct mm_struct *mm) +@@ -199,7 +206,7 @@ void arch_flush_tlb_batched_pending(struct mm_struct *mm) + + void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch) + { +- __flush_tlb_range(&batch->cpumask, FLUSH_TLB_NO_ASID, 0, +- FLUSH_TLB_MAX_SIZE, PAGE_SIZE); ++ __flush_tlb_range(NULL, &batch->cpumask, ++ 0, FLUSH_TLB_MAX_SIZE, PAGE_SIZE); + cpumask_clear(&batch->cpumask); + } +-- +2.39.5 + diff --git a/queue-6.12/rtc-ds1307-stop-disabling-alarms-on-probe.patch b/queue-6.12/rtc-ds1307-stop-disabling-alarms-on-probe.patch new file mode 100644 index 0000000000..1b0c62f1f2 --- /dev/null +++ b/queue-6.12/rtc-ds1307-stop-disabling-alarms-on-probe.patch @@ -0,0 +1,38 @@ +From a65354c0edcdd519e212f4b5047616c7aae2791d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 23:37:44 +0100 +Subject: rtc: ds1307: stop disabling alarms on probe + +From: Alexandre Belloni + +[ Upstream commit dcec12617ee61beed928e889607bf37e145bf86b ] + +It is a bad practice to disable alarms on probe or remove as this will +prevent alarms across reboots. + +Link: https://lore.kernel.org/r/20250303223744.1135672-1-alexandre.belloni@bootlin.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-ds1307.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c +index 872e0b679be48..5efbe69bf5ca8 100644 +--- a/drivers/rtc/rtc-ds1307.c ++++ b/drivers/rtc/rtc-ds1307.c +@@ -1807,10 +1807,8 @@ static int ds1307_probe(struct i2c_client *client) + * For some variants, be sure alarms can trigger when we're + * running on Vbackup (BBSQI/BBSQW) + */ +- if (want_irq || ds1307_can_wakeup_device) { ++ if (want_irq || ds1307_can_wakeup_device) + regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit; +- regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE); +- } + + regmap_write(ds1307->regmap, DS1337_REG_CONTROL, + regs[0]); +-- +2.39.5 + diff --git a/queue-6.12/rtc-rv3032-fix-eerd-location.patch b/queue-6.12/rtc-rv3032-fix-eerd-location.patch new file mode 100644 index 0000000000..ec3c40dc0f --- /dev/null +++ b/queue-6.12/rtc-rv3032-fix-eerd-location.patch @@ -0,0 +1,34 @@ +From bdec44a3625517fe7175f382dd3c013d58e92118 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 22:42:41 +0100 +Subject: rtc: rv3032: fix EERD location + +From: Alexandre Belloni + +[ Upstream commit b0f9cb4a0706b0356e84d67e48500b77b343debe ] + +EERD is bit 2 in CTRL1 + +Link: https://lore.kernel.org/r/20250306214243.1167692-1-alexandre.belloni@bootlin.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-rv3032.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/rtc/rtc-rv3032.c b/drivers/rtc/rtc-rv3032.c +index 35b2e36b426a0..cb01038a2e27f 100644 +--- a/drivers/rtc/rtc-rv3032.c ++++ b/drivers/rtc/rtc-rv3032.c +@@ -69,7 +69,7 @@ + #define RV3032_CLKOUT2_FD_MSK GENMASK(6, 5) + #define RV3032_CLKOUT2_OS BIT(7) + +-#define RV3032_CTRL1_EERD BIT(3) ++#define RV3032_CTRL1_EERD BIT(2) + #define RV3032_CTRL1_WADA BIT(5) + + #define RV3032_CTRL2_STOP BIT(0) +-- +2.39.5 + diff --git a/queue-6.12/s390-tlb-use-mm_has_pgste-instead-of-mm_alloc_pgste.patch b/queue-6.12/s390-tlb-use-mm_has_pgste-instead-of-mm_alloc_pgste.patch new file mode 100644 index 0000000000..20767ad0e1 --- /dev/null +++ b/queue-6.12/s390-tlb-use-mm_has_pgste-instead-of-mm_alloc_pgste.patch @@ -0,0 +1,39 @@ +From d9110c8dd7fea7d5ccbd5669a82ca2ffed90d2ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 12:42:59 +0100 +Subject: s390/tlb: Use mm_has_pgste() instead of mm_alloc_pgste() + +From: Heiko Carstens + +[ Upstream commit 9291ea091b29bb3e37c4b3416c7c1e49e472c7d5 ] + +An mm has pgstes only after s390_enable_sie() has been called, while +mm_alloc_pgste() may be always true (e.g. via sysctl setting). + +Limit the calls to gmap_unlink() in pte_free_tlb() to those cases +where there might be something to unlink. + +Reviewed-by: Alexander Gordeev +Signed-off-by: Heiko Carstens +Signed-off-by: Vasily Gorbik +Signed-off-by: Sasha Levin +--- + arch/s390/include/asm/tlb.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h +index e95b2c8081eb8..793afe236df07 100644 +--- a/arch/s390/include/asm/tlb.h ++++ b/arch/s390/include/asm/tlb.h +@@ -85,7 +85,7 @@ static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, + tlb->mm->context.flush_mm = 1; + tlb->freed_tables = 1; + tlb->cleared_pmds = 1; +- if (mm_alloc_pgste(tlb->mm)) ++ if (mm_has_pgste(tlb->mm)) + gmap_unlink(tlb->mm, (unsigned long *)pte, address); + tlb_remove_ptdesc(tlb, pte); + } +-- +2.39.5 + diff --git a/queue-6.12/s390-vfio-ap-fix-no-ap-queue-sharing-allowed-message.patch b/queue-6.12/s390-vfio-ap-fix-no-ap-queue-sharing-allowed-message.patch new file mode 100644 index 0000000000..a25e5cc7e3 --- /dev/null +++ b/queue-6.12/s390-vfio-ap-fix-no-ap-queue-sharing-allowed-message.patch @@ -0,0 +1,192 @@ +From f84ec31ee430bfdc1b1b922f26c52b3f252f98ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 06:32:57 -0400 +Subject: s390/vfio-ap: Fix no AP queue sharing allowed message written to + kernel log + +From: Anthony Krowiak + +[ Upstream commit d33d729afcc8ad2148d99f9bc499b33fd0c0d73b ] + +An erroneous message is written to the kernel log when either of the +following actions are taken by a user: + +1. Assign an adapter or domain to a vfio_ap mediated device via its sysfs + assign_adapter or assign_domain attributes that would result in one or + more AP queues being assigned that are already assigned to a different + mediated device. Sharing of queues between mdevs is not allowed. + +2. Reserve an adapter or domain for the host device driver via the AP bus + driver's sysfs apmask or aqmask attribute that would result in providing + host access to an AP queue that is in use by a vfio_ap mediated device. + Reserving a queue for a host driver that is in use by an mdev is not + allowed. + +In both cases, the assignment will return an error; however, a message like +the following is written to the kernel log: + +vfio_ap_mdev e1839397-51a0-4e3c-91e0-c3b9c3d3047d: Userspace may not +re-assign queue 00.0028 already assigned to \ +e1839397-51a0-4e3c-91e0-c3b9c3d3047d + +Notice the mdev reporting the error is the same as the mdev identified +in the message as the one to which the queue is being assigned. +It is perfectly okay to assign a queue to an mdev to which it is +already assigned; the assignment is simply ignored by the vfio_ap device +driver. + +This patch logs more descriptive and accurate messages for both 1 and 2 +above to the kernel log: + +Example for 1: +vfio_ap_mdev 0fe903a0-a323-44db-9daf-134c68627d61: Userspace may not assign +queue 00.0033 to mdev: already assigned to \ +62177883-f1bb-47f0-914d-32a22e3a8804 + +Example for 2: +vfio_ap_mdev 62177883-f1bb-47f0-914d-32a22e3a8804: Can not reserve queue +00.0033 for host driver: in use by mdev + +Signed-off-by: Anthony Krowiak +Link: https://lore.kernel.org/r/20250311103304.1539188-1-akrowiak@linux.ibm.com +Signed-off-by: Heiko Carstens +Signed-off-by: Vasily Gorbik +Signed-off-by: Sasha Levin +--- + drivers/s390/crypto/vfio_ap_ops.c | 72 ++++++++++++++++++++----------- + 1 file changed, 46 insertions(+), 26 deletions(-) + +diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c +index 9f76f2d7b66e5..3bac163057d89 100644 +--- a/drivers/s390/crypto/vfio_ap_ops.c ++++ b/drivers/s390/crypto/vfio_ap_ops.c +@@ -851,48 +851,66 @@ static void vfio_ap_mdev_remove(struct mdev_device *mdev) + vfio_put_device(&matrix_mdev->vdev); + } + +-#define MDEV_SHARING_ERR "Userspace may not re-assign queue %02lx.%04lx " \ +- "already assigned to %s" ++#define MDEV_SHARING_ERR "Userspace may not assign queue %02lx.%04lx to mdev: already assigned to %s" + +-static void vfio_ap_mdev_log_sharing_err(struct ap_matrix_mdev *matrix_mdev, +- unsigned long *apm, +- unsigned long *aqm) ++#define MDEV_IN_USE_ERR "Can not reserve queue %02lx.%04lx for host driver: in use by mdev" ++ ++static void vfio_ap_mdev_log_sharing_err(struct ap_matrix_mdev *assignee, ++ struct ap_matrix_mdev *assigned_to, ++ unsigned long *apm, unsigned long *aqm) + { + unsigned long apid, apqi; +- const struct device *dev = mdev_dev(matrix_mdev->mdev); +- const char *mdev_name = dev_name(dev); + +- for_each_set_bit_inv(apid, apm, AP_DEVICES) ++ for_each_set_bit_inv(apid, apm, AP_DEVICES) { ++ for_each_set_bit_inv(apqi, aqm, AP_DOMAINS) { ++ dev_warn(mdev_dev(assignee->mdev), MDEV_SHARING_ERR, ++ apid, apqi, dev_name(mdev_dev(assigned_to->mdev))); ++ } ++ } ++} ++ ++static void vfio_ap_mdev_log_in_use_err(struct ap_matrix_mdev *assignee, ++ unsigned long *apm, unsigned long *aqm) ++{ ++ unsigned long apid, apqi; ++ ++ for_each_set_bit_inv(apid, apm, AP_DEVICES) { + for_each_set_bit_inv(apqi, aqm, AP_DOMAINS) +- dev_warn(dev, MDEV_SHARING_ERR, apid, apqi, mdev_name); ++ dev_warn(mdev_dev(assignee->mdev), MDEV_IN_USE_ERR, apid, apqi); ++ } + } + + /** + * vfio_ap_mdev_verify_no_sharing - verify APQNs are not shared by matrix mdevs + * ++ * @assignee: the matrix mdev to which @mdev_apm and @mdev_aqm are being ++ * assigned; or, NULL if this function was called by the AP bus ++ * driver in_use callback to verify none of the APQNs being reserved ++ * for the host device driver are in use by a vfio_ap mediated device + * @mdev_apm: mask indicating the APIDs of the APQNs to be verified + * @mdev_aqm: mask indicating the APQIs of the APQNs to be verified + * +- * Verifies that each APQN derived from the Cartesian product of a bitmap of +- * AP adapter IDs and AP queue indexes is not configured for any matrix +- * mediated device. AP queue sharing is not allowed. ++ * Verifies that each APQN derived from the Cartesian product of APIDs ++ * represented by the bits set in @mdev_apm and the APQIs of the bits set in ++ * @mdev_aqm is not assigned to a mediated device other than the mdev to which ++ * the APQN is being assigned (@assignee). AP queue sharing is not allowed. + * + * Return: 0 if the APQNs are not shared; otherwise return -EADDRINUSE. + */ +-static int vfio_ap_mdev_verify_no_sharing(unsigned long *mdev_apm, ++static int vfio_ap_mdev_verify_no_sharing(struct ap_matrix_mdev *assignee, ++ unsigned long *mdev_apm, + unsigned long *mdev_aqm) + { +- struct ap_matrix_mdev *matrix_mdev; ++ struct ap_matrix_mdev *assigned_to; + DECLARE_BITMAP(apm, AP_DEVICES); + DECLARE_BITMAP(aqm, AP_DOMAINS); + +- list_for_each_entry(matrix_mdev, &matrix_dev->mdev_list, node) { ++ list_for_each_entry(assigned_to, &matrix_dev->mdev_list, node) { + /* +- * If the input apm and aqm are fields of the matrix_mdev +- * object, then move on to the next matrix_mdev. ++ * If the mdev to which the mdev_apm and mdev_aqm is being ++ * assigned is the same as the mdev being verified + */ +- if (mdev_apm == matrix_mdev->matrix.apm && +- mdev_aqm == matrix_mdev->matrix.aqm) ++ if (assignee == assigned_to) + continue; + + memset(apm, 0, sizeof(apm)); +@@ -902,15 +920,16 @@ static int vfio_ap_mdev_verify_no_sharing(unsigned long *mdev_apm, + * We work on full longs, as we can only exclude the leftover + * bits in non-inverse order. The leftover is all zeros. + */ +- if (!bitmap_and(apm, mdev_apm, matrix_mdev->matrix.apm, +- AP_DEVICES)) ++ if (!bitmap_and(apm, mdev_apm, assigned_to->matrix.apm, AP_DEVICES)) + continue; + +- if (!bitmap_and(aqm, mdev_aqm, matrix_mdev->matrix.aqm, +- AP_DOMAINS)) ++ if (!bitmap_and(aqm, mdev_aqm, assigned_to->matrix.aqm, AP_DOMAINS)) + continue; + +- vfio_ap_mdev_log_sharing_err(matrix_mdev, apm, aqm); ++ if (assignee) ++ vfio_ap_mdev_log_sharing_err(assignee, assigned_to, apm, aqm); ++ else ++ vfio_ap_mdev_log_in_use_err(assigned_to, apm, aqm); + + return -EADDRINUSE; + } +@@ -939,7 +958,8 @@ static int vfio_ap_mdev_validate_masks(struct ap_matrix_mdev *matrix_mdev) + matrix_mdev->matrix.aqm)) + return -EADDRNOTAVAIL; + +- return vfio_ap_mdev_verify_no_sharing(matrix_mdev->matrix.apm, ++ return vfio_ap_mdev_verify_no_sharing(matrix_mdev, ++ matrix_mdev->matrix.apm, + matrix_mdev->matrix.aqm); + } + +@@ -2467,7 +2487,7 @@ int vfio_ap_mdev_resource_in_use(unsigned long *apm, unsigned long *aqm) + + mutex_lock(&matrix_dev->guests_lock); + mutex_lock(&matrix_dev->mdevs_lock); +- ret = vfio_ap_mdev_verify_no_sharing(apm, aqm); ++ ret = vfio_ap_mdev_verify_no_sharing(NULL, apm, aqm); + mutex_unlock(&matrix_dev->mdevs_lock); + mutex_unlock(&matrix_dev->guests_lock); + +-- +2.39.5 + diff --git a/queue-6.12/samples-bpf-fix-compilation-failure-for-samples-bpf-.patch b/queue-6.12/samples-bpf-fix-compilation-failure-for-samples-bpf-.patch new file mode 100644 index 0000000000..4f643227df --- /dev/null +++ b/queue-6.12/samples-bpf-fix-compilation-failure-for-samples-bpf-.patch @@ -0,0 +1,59 @@ +From 3a50b5dcfdaa2bb97cd46645738da5d4ff17f3e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 17:50:42 +0800 +Subject: samples/bpf: Fix compilation failure for samples/bpf on LoongArch + Fedora + +From: Haoran Jiang + +[ Upstream commit 548762f05d19c5542db7590bcdfb9be1fb928376 ] + +When building the latest samples/bpf on LoongArch Fedora + + make M=samples/bpf + +There are compilation errors as follows: + +In file included from ./linux/samples/bpf/sockex2_kern.c:2: +In file included from ./include/uapi/linux/in.h:25: +In file included from ./include/linux/socket.h:8: +In file included from ./include/linux/uio.h:9: +In file included from ./include/linux/thread_info.h:60: +In file included from ./arch/loongarch/include/asm/thread_info.h:15: +In file included from ./arch/loongarch/include/asm/processor.h:13: +In file included from ./arch/loongarch/include/asm/cpu-info.h:11: +./arch/loongarch/include/asm/loongarch.h:13:10: fatal error: 'larchintrin.h' file not found + ^~~~~~~~~~~~~~~ +1 error generated. + +larchintrin.h is included in /usr/lib64/clang/14.0.6/include, +and the header file location is specified at compile time. + +Test on LoongArch Fedora: +https://github.com/fedora-remix-loongarch/releases-info + +Signed-off-by: Haoran Jiang +Signed-off-by: zhangxi +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20250425095042.838824-1-jianghaoran@kylinos.cn +Signed-off-by: Sasha Levin +--- + samples/bpf/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile +index 7afe040cf43b3..f06f88b26183c 100644 +--- a/samples/bpf/Makefile ++++ b/samples/bpf/Makefile +@@ -400,7 +400,7 @@ $(obj)/%.o: $(src)/%.c + @echo " CLANG-bpf " $@ + $(Q)$(CLANG) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(BPF_EXTRA_CFLAGS) \ + -I$(obj) -I$(srctree)/tools/testing/selftests/bpf/ \ +- -I$(LIBBPF_INCLUDE) \ ++ -I$(LIBBPF_INCLUDE) $(CLANG_SYS_INCLUDES) \ + -D__KERNEL__ -D__BPF_TRACING__ -Wno-unused-value -Wno-pointer-sign \ + -D__TARGET_ARCH_$(SRCARCH) -Wno-compare-distinct-pointer-types \ + -Wno-gnu-variable-sized-type-not-at-end \ +-- +2.39.5 + diff --git a/queue-6.12/sched-reduce-the-default-slice-to-avoid-tasks-gettin.patch b/queue-6.12/sched-reduce-the-default-slice-to-avoid-tasks-gettin.patch new file mode 100644 index 0000000000..f684dc9f75 --- /dev/null +++ b/queue-6.12/sched-reduce-the-default-slice-to-avoid-tasks-gettin.patch @@ -0,0 +1,80 @@ +From c6c8e11a91749b5edb18e82a61ccf9e715fc0fff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Feb 2025 15:53:23 +0800 +Subject: sched: Reduce the default slice to avoid tasks getting an extra tick + +From: zihan zhou <15645113830zzh@gmail.com> + +[ Upstream commit 2ae891b826958b60919ea21c727f77bcd6ffcc2c ] + +The old default value for slice is 0.75 msec * (1 + ilog(ncpus)) which +means that we have a default slice of: + + 0.75 for 1 cpu + 1.50 up to 3 cpus + 2.25 up to 7 cpus + 3.00 for 8 cpus and above. + +For HZ=250 and HZ=100, because of the tick accuracy, the runtime of +tasks is far higher than their slice. + +For HZ=1000 with 8 cpus or more, the accuracy of tick is already +satisfactory, but there is still an issue that tasks will get an extra +tick because the tick often arrives a little faster than expected. In +this case, the task can only wait until the next tick to consider that it +has reached its deadline, and will run 1ms longer. + +vruntime + sysctl_sched_base_slice = deadline + |-----------|-----------|-----------|-----------| + 1ms 1ms 1ms 1ms + ^ ^ ^ ^ + tick1 tick2 tick3 tick4(nearly 4ms) + +There are two reasons for tick error: clockevent precision and the +CONFIG_IRQ_TIME_ACCOUNTING/CONFIG_PARAVIRT_TIME_ACCOUNTING. with +CONFIG_IRQ_TIME_ACCOUNTING every tick will be less than 1ms, but even +without it, because of clockevent precision, tick still often less than +1ms. + +In order to make scheduling more precise, we changed 0.75 to 0.70, +Using 0.70 instead of 0.75 should not change much for other configs +and would fix this issue: + + 0.70 for 1 cpu + 1.40 up to 3 cpus + 2.10 up to 7 cpus + 2.8 for 8 cpus and above. + +This does not guarantee that tasks can run the slice time accurately +every time, but occasionally running an extra tick has little impact. + +Signed-off-by: zihan zhou <15645113830zzh@gmail.com> +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Vincent Guittot +Link: https://lkml.kernel.org/r/20250208075322.13139-1-15645113830zzh@gmail.com +Signed-off-by: Sasha Levin +--- + kernel/sched/fair.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index 990d0828bf2a9..443f6a9ef3f8f 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -71,10 +71,10 @@ unsigned int sysctl_sched_tunable_scaling = SCHED_TUNABLESCALING_LOG; + /* + * Minimal preemption granularity for CPU-bound tasks: + * +- * (default: 0.75 msec * (1 + ilog(ncpus)), units: nanoseconds) ++ * (default: 0.70 msec * (1 + ilog(ncpus)), units: nanoseconds) + */ +-unsigned int sysctl_sched_base_slice = 750000ULL; +-static unsigned int normalized_sysctl_sched_base_slice = 750000ULL; ++unsigned int sysctl_sched_base_slice = 700000ULL; ++static unsigned int normalized_sysctl_sched_base_slice = 700000ULL; + + const_debug unsigned int sysctl_sched_migration_cost = 500000UL; + +-- +2.39.5 + diff --git a/queue-6.12/scsi-logging-fix-scsi_logging_level-bounds.patch b/queue-6.12/scsi-logging-fix-scsi_logging_level-bounds.patch new file mode 100644 index 0000000000..1e68d2ebb8 --- /dev/null +++ b/queue-6.12/scsi-logging-fix-scsi_logging_level-bounds.patch @@ -0,0 +1,41 @@ +From 2510a5a2ce613b9850a2f347d5c1476194e9c6be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 10:58:19 +0100 +Subject: scsi: logging: Fix scsi_logging_level bounds + +From: Nicolas Bouchinet + +[ Upstream commit 2cef5b4472c602e6c5a119aca869d9d4050586f3 ] + +Bound scsi_logging_level sysctl writings between SYSCTL_ZERO and +SYSCTL_INT_MAX. + +The proc_handler has thus been updated to proc_dointvec_minmax. + +Signed-off-by: Nicolas Bouchinet +Link: https://lore.kernel.org/r/20250224095826.16458-5-nicolas.bouchinet@clip-os.org +Reviewed-by: Joel Granados +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/scsi_sysctl.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/scsi_sysctl.c b/drivers/scsi/scsi_sysctl.c +index 093774d775346..daa160459c9b3 100644 +--- a/drivers/scsi/scsi_sysctl.c ++++ b/drivers/scsi/scsi_sysctl.c +@@ -17,7 +17,9 @@ static struct ctl_table scsi_table[] = { + .data = &scsi_logging_level, + .maxlen = sizeof(scsi_logging_level), + .mode = 0644, +- .proc_handler = proc_dointvec }, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = SYSCTL_ZERO, ++ .extra2 = SYSCTL_INT_MAX }, + }; + + static struct ctl_table_header *scsi_table_header; +-- +2.39.5 + diff --git a/queue-6.12/scsi-lpfc-free-phba-irq-in-lpfc_sli4_enable_msi-when.patch b/queue-6.12/scsi-lpfc-free-phba-irq-in-lpfc_sli4_enable_msi-when.patch new file mode 100644 index 0000000000..776b40b1d8 --- /dev/null +++ b/queue-6.12/scsi-lpfc-free-phba-irq-in-lpfc_sli4_enable_msi-when.patch @@ -0,0 +1,47 @@ +From 8db278501e479338ed214b7c1c2ae7a4e9b1c1ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 16:05:20 -0800 +Subject: scsi: lpfc: Free phba irq in lpfc_sli4_enable_msi() when + pci_irq_vector() fails + +From: Justin Tee + +[ Upstream commit f0842902b383982d1f72c490996aa8fc29a7aa0d ] + +Fix smatch warning regarding missed calls to free_irq(). Free the phba IRQ +in the failed pci_irq_vector cases. + +lpfc_init.c: lpfc_sli4_enable_msi() warn: 'phba->pcidev->irq' from + request_irq() not released. + +Signed-off-by: Justin Tee +Link: https://lore.kernel.org/r/20250131000524.163662-3-justintee8345@gmail.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/lpfc/lpfc_init.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c +index a3658ef1141b2..50c761991191f 100644 +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -13190,6 +13190,7 @@ lpfc_sli4_enable_msi(struct lpfc_hba *phba) + eqhdl = lpfc_get_eq_hdl(0); + rc = pci_irq_vector(phba->pcidev, 0); + if (rc < 0) { ++ free_irq(phba->pcidev->irq, phba); + pci_free_irq_vectors(phba->pcidev); + lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, + "0496 MSI pci_irq_vec failed (%d)\n", rc); +@@ -13270,6 +13271,7 @@ lpfc_sli4_enable_intr(struct lpfc_hba *phba, uint32_t cfg_mode) + eqhdl = lpfc_get_eq_hdl(0); + retval = pci_irq_vector(phba->pcidev, 0); + if (retval < 0) { ++ free_irq(phba->pcidev->irq, phba); + lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, + "0502 INTR pci_irq_vec failed (%d)\n", + retval); +-- +2.39.5 + diff --git a/queue-6.12/scsi-lpfc-handle-duplicate-d_ids-in-ndlp-search-by-d.patch b/queue-6.12/scsi-lpfc-handle-duplicate-d_ids-in-ndlp-search-by-d.patch new file mode 100644 index 0000000000..d232be92d2 --- /dev/null +++ b/queue-6.12/scsi-lpfc-handle-duplicate-d_ids-in-ndlp-search-by-d.patch @@ -0,0 +1,66 @@ +From 16c14b77e82d6adabc90e640de870875cb2f1963 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 16:05:22 -0800 +Subject: scsi: lpfc: Handle duplicate D_IDs in ndlp search-by D_ID routine + +From: Justin Tee + +[ Upstream commit 56c3d809b7b450379162d0b8a70bbe71ab8db706 ] + +After a port swap between separate fabrics, there may be multiple nodes in +the vport's fc_nodes list with the same fabric well known address. +Duplication is temporary and eventually resolves itself after dev_loss_tmo +expires, but nameserver queries may still occur before dev_loss_tmo. This +possibly results in returning stale fabric ndlp objects. Fix by adding an +nlp_state check to ensure the ndlp search routine returns the correct newer +allocated ndlp fabric object. + +Signed-off-by: Justin Tee +Link: https://lore.kernel.org/r/20250131000524.163662-5-justintee8345@gmail.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/lpfc/lpfc_hbadisc.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c +index 6e8d8a96c54fb..31dcabebc9b6d 100644 +--- a/drivers/scsi/lpfc/lpfc_hbadisc.c ++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c +@@ -5622,6 +5622,7 @@ static struct lpfc_nodelist * + __lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did) + { + struct lpfc_nodelist *ndlp; ++ struct lpfc_nodelist *np = NULL; + uint32_t data1; + + list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { +@@ -5636,14 +5637,20 @@ __lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did) + ndlp, ndlp->nlp_DID, + ndlp->nlp_flag, data1, ndlp->nlp_rpi, + ndlp->active_rrqs_xri_bitmap); +- return ndlp; ++ ++ /* Check for new or potentially stale node */ ++ if (ndlp->nlp_state != NLP_STE_UNUSED_NODE) ++ return ndlp; ++ np = ndlp; + } + } + +- /* FIND node did NOT FOUND */ +- lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, +- "0932 FIND node did x%x NOT FOUND.\n", did); +- return NULL; ++ if (!np) ++ /* FIND node did NOT FOUND */ ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, ++ "0932 FIND node did x%x NOT FOUND.\n", did); ++ ++ return np; + } + + struct lpfc_nodelist * +-- +2.39.5 + diff --git a/queue-6.12/scsi-lpfc-ignore-ndlp-rport-mismatch-in-dev_loss_tmo.patch b/queue-6.12/scsi-lpfc-ignore-ndlp-rport-mismatch-in-dev_loss_tmo.patch new file mode 100644 index 0000000000..4f5272325b --- /dev/null +++ b/queue-6.12/scsi-lpfc-ignore-ndlp-rport-mismatch-in-dev_loss_tmo.patch @@ -0,0 +1,58 @@ +From b057f204657f9f7b43bde5bf0c277b3bb9bc5b42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 16:05:21 -0800 +Subject: scsi: lpfc: Ignore ndlp rport mismatch in dev_loss_tmo callbk + +From: Justin Tee + +[ Upstream commit 23ed62897746f49f195d819ce6edeb1db27d1b72 ] + +With repeated port swaps between separate fabrics, there can be multiple +registrations for fabric well known address 0xfffffe. This can cause ndlp +reference confusion due to the usage of a single ndlp ptr that stores the +rport object in fc_rport struct private storage during transport +registration. Subsequent registrations update the ndlp->rport field with +the newer rport, so when transport layer triggers dev_loss_tmo for the +earlier registered rport the ndlp->rport private storage is referencing the +newer rport instead of the older rport in dev_loss_tmo callbk. + +Because the older ndlp->rport object is already cleaned up elsewhere in +driver code during the time of fabric swap, check that the rport provided +in dev_loss_tmo callbk actually matches the rport stored in the LLDD's +ndlp->rport field. Otherwise, skip dev_loss_tmo work on a stale rport. + +Signed-off-by: Justin Tee +Link: https://lore.kernel.org/r/20250131000524.163662-4-justintee8345@gmail.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/lpfc/lpfc_hbadisc.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c +index 31dcabebc9b6d..f2e4237ff3d99 100644 +--- a/drivers/scsi/lpfc/lpfc_hbadisc.c ++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c +@@ -227,10 +227,16 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) + if (ndlp->nlp_state == NLP_STE_MAPPED_NODE) + return; + +- /* check for recovered fabric node */ +- if (ndlp->nlp_state == NLP_STE_UNMAPPED_NODE && +- ndlp->nlp_DID == Fabric_DID) ++ /* Ignore callback for a mismatched (stale) rport */ ++ if (ndlp->rport != rport) { ++ lpfc_vlog_msg(vport, KERN_WARNING, LOG_NODE, ++ "6788 fc rport mismatch: d_id x%06x ndlp x%px " ++ "fc rport x%px node rport x%px state x%x " ++ "refcnt %u\n", ++ ndlp->nlp_DID, ndlp, rport, ndlp->rport, ++ ndlp->nlp_state, kref_read(&ndlp->kref)); + return; ++ } + + if (rport->port_name != wwn_to_u64(ndlp->nlp_portname.u.wwn)) + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, +-- +2.39.5 + diff --git a/queue-6.12/scsi-mpi3mr-add-level-check-to-control-event-logging.patch b/queue-6.12/scsi-mpi3mr-add-level-check-to-control-event-logging.patch new file mode 100644 index 0000000000..cb0374a353 --- /dev/null +++ b/queue-6.12/scsi-mpi3mr-add-level-check-to-control-event-logging.patch @@ -0,0 +1,37 @@ +From e8bc974d29d18d51b864ac416a9fcc8362a0f0b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Apr 2025 15:45:46 +0530 +Subject: scsi: mpi3mr: Add level check to control event logging + +From: Ranjan Kumar + +[ Upstream commit b0b7ee3b574a72283399b9232f6190be07f220c0 ] + +Ensure event logs are only generated when the debug logging level +MPI3_DEBUG_EVENT is enabled. This prevents unnecessary logging. + +Signed-off-by: Ranjan Kumar +Link: https://lore.kernel.org/r/20250415101546.204018-1-ranjan.kumar@broadcom.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/mpi3mr/mpi3mr_fw.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c +index c0a372868e1d7..f6d3db3fd0d8e 100644 +--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c ++++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c +@@ -174,6 +174,9 @@ static void mpi3mr_print_event_data(struct mpi3mr_ioc *mrioc, + char *desc = NULL; + u16 event; + ++ if (!(mrioc->logging_level & MPI3_DEBUG_EVENT)) ++ return; ++ + event = event_reply->event; + + switch (event) { +-- +2.39.5 + diff --git a/queue-6.12/scsi-mpi3mr-update-timestamp-only-for-supervisor-ioc.patch b/queue-6.12/scsi-mpi3mr-update-timestamp-only-for-supervisor-ioc.patch new file mode 100644 index 0000000000..35699e8474 --- /dev/null +++ b/queue-6.12/scsi-mpi3mr-update-timestamp-only-for-supervisor-ioc.patch @@ -0,0 +1,44 @@ +From 8aaf91b811af447aef12a06fa44833199aef5cf4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 19:55:26 +0530 +Subject: scsi: mpi3mr: Update timestamp only for supervisor IOCs + +From: Ranjan Kumar + +[ Upstream commit 83a9d30d29f275571f6e8f879f04b2379be7eb6c ] + +The driver issues the time stamp update command periodically. Even if the +command fails with supervisor only IOC Status. + +Instead check the Non-Supervisor capability bit reported by IOC as part of +IOC Facts. + +Co-developed-by: Sumit Saxena +Signed-off-by: Sumit Saxena +Signed-off-by: Ranjan Kumar +Link: https://lore.kernel.org/r/20250220142528.20837-3-ranjan.kumar@broadcom.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/mpi3mr/mpi3mr_fw.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c +index f6d3db3fd0d8e..604f37e5c0c35 100644 +--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c ++++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c +@@ -2747,7 +2747,10 @@ static void mpi3mr_watchdog_work(struct work_struct *work) + return; + } + +- if (mrioc->ts_update_counter++ >= mrioc->ts_update_interval) { ++ if (!(mrioc->facts.ioc_capabilities & ++ MPI3_IOCFACTS_CAPABILITY_NON_SUPERVISOR_IOC) && ++ (mrioc->ts_update_counter++ >= mrioc->ts_update_interval)) { ++ + mrioc->ts_update_counter = 0; + mpi3mr_sync_timestamp(mrioc); + } +-- +2.39.5 + diff --git a/queue-6.12/scsi-mpt3sas-send-a-diag-reset-if-target-reset-fails.patch b/queue-6.12/scsi-mpt3sas-send-a-diag-reset-if-target-reset-fails.patch new file mode 100644 index 0000000000..09c722244c --- /dev/null +++ b/queue-6.12/scsi-mpt3sas-send-a-diag-reset-if-target-reset-fails.patch @@ -0,0 +1,64 @@ +From 761e19929da3beaaeabe0919bbf1fbfcc4b77462 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 17:26:55 -0800 +Subject: scsi: mpt3sas: Send a diag reset if target reset fails + +From: Shivasharan S + +[ Upstream commit 5612d6d51ed2634a033c95de2edec7449409cbb9 ] + +When an IOCTL times out and driver issues a target reset, if firmware +fails the task management elevate the recovery by issuing a diag reset to +controller. + +Signed-off-by: Shivasharan S +Link: https://lore.kernel.org/r/1739410016-27503-5-git-send-email-shivasharan.srikanteshwara@broadcom.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/mpt3sas/mpt3sas_ctl.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c +index 87784c96249a7..47faa27bc3559 100644 +--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c ++++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c +@@ -679,6 +679,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, + size_t data_in_sz = 0; + long ret; + u16 device_handle = MPT3SAS_INVALID_DEVICE_HANDLE; ++ int tm_ret; + + issue_reset = 0; + +@@ -1120,18 +1121,25 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, + if (pcie_device && (!ioc->tm_custom_handling) && + (!(mpt3sas_scsih_is_pcie_scsi_device( + pcie_device->device_info)))) +- mpt3sas_scsih_issue_locked_tm(ioc, ++ tm_ret = mpt3sas_scsih_issue_locked_tm(ioc, + le16_to_cpu(mpi_request->FunctionDependent1), + 0, 0, 0, + MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, + 0, pcie_device->reset_timeout, + MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE); + else +- mpt3sas_scsih_issue_locked_tm(ioc, ++ tm_ret = mpt3sas_scsih_issue_locked_tm(ioc, + le16_to_cpu(mpi_request->FunctionDependent1), + 0, 0, 0, + MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, + 0, 30, MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET); ++ ++ if (tm_ret != SUCCESS) { ++ ioc_info(ioc, ++ "target reset failed, issue hard reset: handle (0x%04x)\n", ++ le16_to_cpu(mpi_request->FunctionDependent1)); ++ mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); ++ } + } else + mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); + } +-- +2.39.5 + diff --git a/queue-6.12/scsi-scsi_debug-first-fixes-for-tapes.patch b/queue-6.12/scsi-scsi_debug-first-fixes-for-tapes.patch new file mode 100644 index 0000000000..3da71fad22 --- /dev/null +++ b/queue-6.12/scsi-scsi_debug-first-fixes-for-tapes.patch @@ -0,0 +1,165 @@ +From c02cabed8ef2e147b1df5477bf87ae559ddc3bbe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 11:26:30 +0200 +Subject: scsi: scsi_debug: First fixes for tapes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kai Mäkisara + +[ Upstream commit f69da85d5d5cc5b7dfb963a6c6c1ac0dd9002341 ] + +Patch includes the following: + + - Enable MODE SENSE/SELECT without actual page (to read/write only the + Block Descriptor) + + - Store the density code and block size in the Block Descriptor (only + short version for tapes) + + - Fix REWIND not to use the wrong page filling function + +Signed-off-by: Kai Mäkisara +Link: https://lore.kernel.org/r/20250213092636.2510-2-Kai.Makisara@kolumbus.fi +Reviewed-by: John Meneghini +Tested-by: John Meneghini +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/scsi_debug.c | 55 ++++++++++++++++++++++++++++++++++----- + 1 file changed, 49 insertions(+), 6 deletions(-) + +diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c +index 680ba180a6725..89a2aaccdcfce 100644 +--- a/drivers/scsi/scsi_debug.c ++++ b/drivers/scsi/scsi_debug.c +@@ -173,6 +173,10 @@ static const char *sdebug_version_date = "20210520"; + #define DEF_ZBC_MAX_OPEN_ZONES 8 + #define DEF_ZBC_NR_CONV_ZONES 1 + ++/* Default parameters for tape drives */ ++#define TAPE_DEF_DENSITY 0x0 ++#define TAPE_DEF_BLKSIZE 0 ++ + #define SDEBUG_LUN_0_VAL 0 + + /* bit mask values for sdebug_opts */ +@@ -363,6 +367,10 @@ struct sdebug_dev_info { + ktime_t create_ts; /* time since bootup that this device was created */ + struct sdeb_zone_state *zstate; + ++ /* For tapes */ ++ unsigned int tape_blksize; ++ unsigned int tape_density; ++ + struct dentry *debugfs_entry; + struct spinlock list_lock; + struct list_head inject_err_list; +@@ -773,7 +781,7 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEM_P1 + 1] = { + /* 20 */ + {0, 0x1e, 0, 0, NULL, NULL, /* ALLOW REMOVAL */ + {6, 0, 0, 0, 0x3, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +- {0, 0x1, 0, 0, resp_start_stop, NULL, /* REWIND ?? */ ++ {0, 0x1, 0, 0, NULL, NULL, /* REWIND ?? */ + {6, 0x1, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, + {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ATA_PT */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +@@ -2742,7 +2750,7 @@ static int resp_mode_sense(struct scsi_cmnd *scp, + unsigned char *ap; + unsigned char *arr __free(kfree); + unsigned char *cmd = scp->cmnd; +- bool dbd, llbaa, msense_6, is_disk, is_zbc; ++ bool dbd, llbaa, msense_6, is_disk, is_zbc, is_tape; + + arr = kzalloc(SDEBUG_MAX_MSENSE_SZ, GFP_ATOMIC); + if (!arr) +@@ -2755,7 +2763,8 @@ static int resp_mode_sense(struct scsi_cmnd *scp, + llbaa = msense_6 ? false : !!(cmd[1] & 0x10); + is_disk = (sdebug_ptype == TYPE_DISK); + is_zbc = devip->zoned; +- if ((is_disk || is_zbc) && !dbd) ++ is_tape = (sdebug_ptype == TYPE_TAPE); ++ if ((is_disk || is_zbc || is_tape) && !dbd) + bd_len = llbaa ? 16 : 8; + else + bd_len = 0; +@@ -2793,15 +2802,25 @@ static int resp_mode_sense(struct scsi_cmnd *scp, + put_unaligned_be32(0xffffffff, ap + 0); + else + put_unaligned_be32(sdebug_capacity, ap + 0); +- put_unaligned_be16(sdebug_sector_size, ap + 6); ++ if (is_tape) { ++ ap[0] = devip->tape_density; ++ put_unaligned_be16(devip->tape_blksize, ap + 6); ++ } else ++ put_unaligned_be16(sdebug_sector_size, ap + 6); + offset += bd_len; + ap = arr + offset; + } else if (16 == bd_len) { ++ if (is_tape) { ++ mk_sense_invalid_fld(scp, SDEB_IN_DATA, 1, 4); ++ return check_condition_result; ++ } + put_unaligned_be64((u64)sdebug_capacity, ap + 0); + put_unaligned_be32(sdebug_sector_size, ap + 12); + offset += bd_len; + ap = arr + offset; + } ++ if (cmd[2] == 0) ++ goto only_bd; /* Only block descriptor requested */ + + /* + * N.B. If len>0 before resp_*_pg() call, then form of that call should be: +@@ -2902,6 +2921,7 @@ static int resp_mode_sense(struct scsi_cmnd *scp, + default: + goto bad_pcode; + } ++only_bd: + if (msense_6) + arr[0] = offset - 1; + else +@@ -2945,8 +2965,27 @@ static int resp_mode_select(struct scsi_cmnd *scp, + __func__, param_len, res); + md_len = mselect6 ? (arr[0] + 1) : (get_unaligned_be16(arr + 0) + 2); + bd_len = mselect6 ? arr[3] : get_unaligned_be16(arr + 6); +- off = bd_len + (mselect6 ? 4 : 8); +- if (md_len > 2 || off >= res) { ++ off = (mselect6 ? 4 : 8); ++ if (sdebug_ptype == TYPE_TAPE) { ++ int blksize; ++ ++ if (bd_len != 8) { ++ mk_sense_invalid_fld(scp, SDEB_IN_DATA, ++ mselect6 ? 3 : 6, -1); ++ return check_condition_result; ++ } ++ blksize = get_unaligned_be16(arr + off + 6); ++ if ((blksize % 4) != 0) { ++ mk_sense_invalid_fld(scp, SDEB_IN_DATA, off + 6, -1); ++ return check_condition_result; ++ } ++ devip->tape_density = arr[off]; ++ devip->tape_blksize = blksize; ++ } ++ off += bd_len; ++ if (off >= res) ++ return 0; /* No page written, just descriptors */ ++ if (md_len > 2) { + mk_sense_invalid_fld(scp, SDEB_IN_DATA, 0, -1); + return check_condition_result; + } +@@ -5835,6 +5874,10 @@ static struct sdebug_dev_info *sdebug_device_create( + } else { + devip->zoned = false; + } ++ if (sdebug_ptype == TYPE_TAPE) { ++ devip->tape_density = TAPE_DEF_DENSITY; ++ devip->tape_blksize = TAPE_DEF_BLKSIZE; ++ } + devip->create_ts = ktime_get_boottime(); + atomic_set(&devip->stopped, (sdeb_tur_ms_to_ready > 0 ? 2 : 0)); + spin_lock_init(&devip->list_lock); +-- +2.39.5 + diff --git a/queue-6.12/scsi-st-erase-does-not-change-tape-location.patch b/queue-6.12/scsi-st-erase-does-not-change-tape-location.patch new file mode 100644 index 0000000000..24ca231f16 --- /dev/null +++ b/queue-6.12/scsi-st-erase-does-not-change-tape-location.patch @@ -0,0 +1,38 @@ +From 54bd97ac8749bc55e6de8579a2b6c730039a72a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 13:25:15 +0200 +Subject: scsi: st: ERASE does not change tape location +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kai Mäkisara + +[ Upstream commit ad77cebf97bd42c93ab4e3bffd09f2b905c1959a ] + +The SCSI ERASE command erases from the current position onwards. Don't +clear the position variables. + +Signed-off-by: Kai Mäkisara +Link: https://lore.kernel.org/r/20250311112516.5548-3-Kai.Makisara@kolumbus.fi +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/st.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c +index 1c0951168f646..1cfd7e71dcdde 100644 +--- a/drivers/scsi/st.c ++++ b/drivers/scsi/st.c +@@ -2894,7 +2894,6 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon + timeout = STp->long_timeout * 8; + + DEBC_printk(STp, "Erasing tape.\n"); +- fileno = blkno = at_sm = 0; + break; + case MTSETBLK: /* Set block length */ + case MTSETDENSITY: /* Set tape density */ +-- +2.39.5 + diff --git a/queue-6.12/scsi-st-restore-some-drive-settings-after-reset.patch b/queue-6.12/scsi-st-restore-some-drive-settings-after-reset.patch new file mode 100644 index 0000000000..1a99b92e28 --- /dev/null +++ b/queue-6.12/scsi-st-restore-some-drive-settings-after-reset.patch @@ -0,0 +1,113 @@ +From 21524a84f4c1f7c83d171c7dec7fb4e36e067527 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jan 2025 21:49:22 +0200 +Subject: scsi: st: Restore some drive settings after reset +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kai Mäkisara + +[ Upstream commit 7081dc75df79696d8322d01821c28e53416c932c ] + +Some of the allowed operations put the tape into a known position to +continue operation assuming only the tape position has changed. But reset +sets partition, density and block size to drive default values. These +should be restored to the values before reset. + +Normally the current block size and density are stored by the drive. If +the settings have been changed, the changed values have to be saved by the +driver across reset. + +Signed-off-by: Kai Mäkisara +Link: https://lore.kernel.org/r/20250120194925.44432-2-Kai.Makisara@kolumbus.fi +Reviewed-by: John Meneghini +Tested-by: John Meneghini +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/st.c | 24 +++++++++++++++++++++--- + drivers/scsi/st.h | 2 ++ + 2 files changed, 23 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c +index 1cfd7e71dcdde..3e982c166baf9 100644 +--- a/drivers/scsi/st.c ++++ b/drivers/scsi/st.c +@@ -952,7 +952,6 @@ static void reset_state(struct scsi_tape *STp) + STp->partition = find_partition(STp); + if (STp->partition < 0) + STp->partition = 0; +- STp->new_partition = STp->partition; + } + } + +@@ -2926,14 +2925,17 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon + if (cmd_in == MTSETDENSITY) { + (STp->buffer)->b_data[4] = arg; + STp->density_changed = 1; /* At least we tried ;-) */ ++ STp->changed_density = arg; + } else if (cmd_in == SET_DENS_AND_BLK) + (STp->buffer)->b_data[4] = arg >> 24; + else + (STp->buffer)->b_data[4] = STp->density; + if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) { + ltmp = arg & MT_ST_BLKSIZE_MASK; +- if (cmd_in == MTSETBLK) ++ if (cmd_in == MTSETBLK) { + STp->blksize_changed = 1; /* At least we tried ;-) */ ++ STp->changed_blksize = arg; ++ } + } else + ltmp = STp->block_size; + (STp->buffer)->b_data[9] = (ltmp >> 16); +@@ -3634,9 +3636,25 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) + retval = (-EIO); + goto out; + } +- reset_state(STp); ++ reset_state(STp); /* Clears pos_unknown */ + /* remove this when the midlevel properly clears was_reset */ + STp->device->was_reset = 0; ++ ++ /* Fix the device settings after reset, ignore errors */ ++ if (mtc.mt_op == MTREW || mtc.mt_op == MTSEEK || ++ mtc.mt_op == MTEOM) { ++ if (STp->can_partitions) { ++ /* STp->new_partition contains the ++ * latest partition set ++ */ ++ STp->partition = 0; ++ switch_partition(STp); ++ } ++ if (STp->density_changed) ++ st_int_ioctl(STp, MTSETDENSITY, STp->changed_density); ++ if (STp->blksize_changed) ++ st_int_ioctl(STp, MTSETBLK, STp->changed_blksize); ++ } + } + + if (mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK && +diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h +index 1aaaf5369a40f..6d31b894ee84c 100644 +--- a/drivers/scsi/st.h ++++ b/drivers/scsi/st.h +@@ -165,6 +165,7 @@ struct scsi_tape { + unsigned char compression_changed; + unsigned char drv_buffer; + unsigned char density; ++ unsigned char changed_density; + unsigned char door_locked; + unsigned char autorew_dev; /* auto-rewind device */ + unsigned char rew_at_close; /* rewind necessary at close */ +@@ -172,6 +173,7 @@ struct scsi_tape { + unsigned char cleaning_req; /* cleaning requested? */ + unsigned char first_tur; /* first TEST UNIT READY */ + int block_size; ++ int changed_blksize; + int min_block; + int max_block; + int recover_count; /* From tape opening */ +-- +2.39.5 + diff --git a/queue-6.12/scsi-st-tighten-the-page-format-heuristics-with-mode.patch b/queue-6.12/scsi-st-tighten-the-page-format-heuristics-with-mode.patch new file mode 100644 index 0000000000..4ec3b75fb8 --- /dev/null +++ b/queue-6.12/scsi-st-tighten-the-page-format-heuristics-with-mode.patch @@ -0,0 +1,47 @@ +From 2ffff5e7aa5c4dfb313c626af8976c38cd59af4e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 13:25:16 +0200 +Subject: scsi: st: Tighten the page format heuristics with MODE SELECT +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kai Mäkisara + +[ Upstream commit 8db816c6f176321e42254badd5c1a8df8bfcfdb4 ] + +In the days when SCSI-2 was emerging, some drives did claim SCSI-2 but did +not correctly implement it. The st driver first tries MODE SELECT with the +page format bit set to set the block descriptor. If not successful, the +non-page format is tried. + +The test only tests the sense code and this triggers also from illegal +parameter in the parameter list. The test is limited to "old" devices and +made more strict to remove false alarms. + +Signed-off-by: Kai Mäkisara +Link: https://lore.kernel.org/r/20250311112516.5548-4-Kai.Makisara@kolumbus.fi +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/st.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c +index a17441635ff3a..1c0951168f646 100644 +--- a/drivers/scsi/st.c ++++ b/drivers/scsi/st.c +@@ -3081,7 +3081,9 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon + cmd_in == MTSETDRVBUFFER || + cmd_in == SET_DENS_AND_BLK) { + if (cmdstatp->sense_hdr.sense_key == ILLEGAL_REQUEST && +- !(STp->use_pf & PF_TESTED)) { ++ cmdstatp->sense_hdr.asc == 0x24 && ++ (STp->device)->scsi_level <= SCSI_2 && ++ !(STp->use_pf & PF_TESTED)) { + /* Try the other possible state of Page Format if not + already tried */ + STp->use_pf = (STp->use_pf ^ USE_PF) | PF_TESTED; +-- +2.39.5 + diff --git a/queue-6.12/scsi-target-iscsi-fix-timeout-on-deleted-connection.patch b/queue-6.12/scsi-target-iscsi-fix-timeout-on-deleted-connection.patch new file mode 100644 index 0000000000..c52765ce3e --- /dev/null +++ b/queue-6.12/scsi-target-iscsi-fix-timeout-on-deleted-connection.patch @@ -0,0 +1,57 @@ +From 165678224cfa95213e0460f42305f423e6e28c5c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Dec 2024 13:17:57 +0300 +Subject: scsi: target: iscsi: Fix timeout on deleted connection + +From: Dmitry Bogdanov + +[ Upstream commit 7f533cc5ee4c4436cee51dc58e81dfd9c3384418 ] + +NOPIN response timer may expire on a deleted connection and crash with +such logs: + +Did not receive response to NOPIN on CID: 0, failing connection for I_T Nexus (null),i,0x00023d000125,iqn.2017-01.com.iscsi.target,t,0x3d + +BUG: Kernel NULL pointer dereference on read at 0x00000000 +NIP strlcpy+0x8/0xb0 +LR iscsit_fill_cxn_timeout_err_stats+0x5c/0xc0 [iscsi_target_mod] +Call Trace: + iscsit_handle_nopin_response_timeout+0xfc/0x120 [iscsi_target_mod] + call_timer_fn+0x58/0x1f0 + run_timer_softirq+0x740/0x860 + __do_softirq+0x16c/0x420 + irq_exit+0x188/0x1c0 + timer_interrupt+0x184/0x410 + +That is because nopin response timer may be re-started on nopin timer +expiration. + +Stop nopin timer before stopping the nopin response timer to be sure +that no one of them will be re-started. + +Signed-off-by: Dmitry Bogdanov +Link: https://lore.kernel.org/r/20241224101757.32300-1-d.bogdanov@yadro.com +Reviewed-by: Maurizio Lombardi +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/target/iscsi/iscsi_target.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c +index 6002283cbebab..68bbdf3ee101d 100644 +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -4317,8 +4317,8 @@ int iscsit_close_connection( + spin_unlock(&iscsit_global->ts_bitmap_lock); + + iscsit_stop_timers_for_cmds(conn); +- iscsit_stop_nopin_response_timer(conn); + iscsit_stop_nopin_timer(conn); ++ iscsit_stop_nopin_response_timer(conn); + + if (conn->conn_transport->iscsit_wait_conn) + conn->conn_transport->iscsit_wait_conn(conn); +-- +2.39.5 + diff --git a/queue-6.12/scsi-target-spc-fix-loop-traversal-in-spc_rsoc_get_d.patch b/queue-6.12/scsi-target-spc-fix-loop-traversal-in-spc_rsoc_get_d.patch new file mode 100644 index 0000000000..2ff916f30e --- /dev/null +++ b/queue-6.12/scsi-target-spc-fix-loop-traversal-in-spc_rsoc_get_d.patch @@ -0,0 +1,68 @@ +From b0856a7850b388e46c689b55020a050fb725b3b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 16:55:42 +0800 +Subject: scsi: target: spc: Fix loop traversal in spc_rsoc_get_descr() + +From: Chaohai Chen + +[ Upstream commit 04ad06e41d1c74cc323b20a7bd023c47bd0e0c38 ] + +Stop traversing after finding the appropriate descriptor. + +Signed-off-by: Chaohai Chen +Link: https://lore.kernel.org/r/20250124085542.109088-1-wdhh66@163.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/target/target_core_spc.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c +index 61c065702350e..701dcbd7b63cf 100644 +--- a/drivers/target/target_core_spc.c ++++ b/drivers/target/target_core_spc.c +@@ -2151,8 +2151,10 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) + if (descr->serv_action_valid) + return TCM_INVALID_CDB_FIELD; + +- if (!descr->enabled || descr->enabled(descr, cmd)) ++ if (!descr->enabled || descr->enabled(descr, cmd)) { + *opcode = descr; ++ return TCM_NO_SENSE; ++ } + break; + case 0x2: + /* +@@ -2166,8 +2168,10 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) + if (descr->serv_action_valid && + descr->service_action == requested_sa) { + if (!descr->enabled || descr->enabled(descr, +- cmd)) ++ cmd)) { + *opcode = descr; ++ return TCM_NO_SENSE; ++ } + } else if (!descr->serv_action_valid) + return TCM_INVALID_CDB_FIELD; + break; +@@ -2180,13 +2184,15 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) + */ + if (descr->service_action == requested_sa) + if (!descr->enabled || descr->enabled(descr, +- cmd)) ++ cmd)) { + *opcode = descr; ++ return TCM_NO_SENSE; ++ } + break; + } + } + +- return 0; ++ return TCM_NO_SENSE; + } + + static sense_reason_t +-- +2.39.5 + diff --git a/queue-6.12/scsi-ufs-introduce-quirk-to-extend-pa_hibern8time-fo.patch b/queue-6.12/scsi-ufs-introduce-quirk-to-extend-pa_hibern8time-fo.patch new file mode 100644 index 0000000000..2d763e1744 --- /dev/null +++ b/queue-6.12/scsi-ufs-introduce-quirk-to-extend-pa_hibern8time-fo.patch @@ -0,0 +1,101 @@ +From c6e5e6e58a0e3cecae3ac5ddf9a0cbcd935ed6b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Apr 2025 17:46:30 +0530 +Subject: scsi: ufs: Introduce quirk to extend PA_HIBERN8TIME for UFS devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Manish Pandey + +[ Upstream commit 569330a34a31a52c904239439984a59972c11d28 ] + +Samsung UFS devices require additional time in hibern8 mode before +exiting, beyond the negotiated handshaking phase between the host and +device. Introduce a quirk to increase the PA_HIBERN8TIME parameter by +100 µs, a value derived from experiments, to ensure a proper hibernation +process. + +Signed-off-by: Manish Pandey +Link: https://lore.kernel.org/r/20250411121630.21330-3-quic_mapa@quicinc.com +Reviewed-by: Bean Huo +Reviewed-by: Manivannan Sadhasivam +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/ufs/core/ufshcd.c | 29 +++++++++++++++++++++++++++++ + include/ufs/ufs_quirks.h | 6 ++++++ + 2 files changed, 35 insertions(+) + +diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c +index a9b032d2f4a8d..247e425428c88 100644 +--- a/drivers/ufs/core/ufshcd.c ++++ b/drivers/ufs/core/ufshcd.c +@@ -278,6 +278,7 @@ static const struct ufs_dev_quirk ufs_fixups[] = { + .model = UFS_ANY_MODEL, + .quirk = UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM | + UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE | ++ UFS_DEVICE_QUIRK_PA_HIBER8TIME | + UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS }, + { .wmanufacturerid = UFS_VENDOR_SKHYNIX, + .model = UFS_ANY_MODEL, +@@ -8459,6 +8460,31 @@ static int ufshcd_quirk_tune_host_pa_tactivate(struct ufs_hba *hba) + return ret; + } + ++/** ++ * ufshcd_quirk_override_pa_h8time - Ensures proper adjustment of PA_HIBERN8TIME. ++ * @hba: per-adapter instance ++ * ++ * Some UFS devices require specific adjustments to the PA_HIBERN8TIME parameter ++ * to ensure proper hibernation timing. This function retrieves the current ++ * PA_HIBERN8TIME value and increments it by 100us. ++ */ ++static void ufshcd_quirk_override_pa_h8time(struct ufs_hba *hba) ++{ ++ u32 pa_h8time; ++ int ret; ++ ++ ret = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_HIBERN8TIME), &pa_h8time); ++ if (ret) { ++ dev_err(hba->dev, "Failed to get PA_HIBERN8TIME: %d\n", ret); ++ return; ++ } ++ ++ /* Increment by 1 to increase hibernation time by 100 µs */ ++ ret = ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HIBERN8TIME), pa_h8time + 1); ++ if (ret) ++ dev_err(hba->dev, "Failed updating PA_HIBERN8TIME: %d\n", ret); ++} ++ + static void ufshcd_tune_unipro_params(struct ufs_hba *hba) + { + ufshcd_vops_apply_dev_quirks(hba); +@@ -8469,6 +8495,9 @@ static void ufshcd_tune_unipro_params(struct ufs_hba *hba) + + if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE) + ufshcd_quirk_tune_host_pa_tactivate(hba); ++ ++ if (hba->dev_quirks & UFS_DEVICE_QUIRK_PA_HIBER8TIME) ++ ufshcd_quirk_override_pa_h8time(hba); + } + + static void ufshcd_clear_dbg_ufs_stats(struct ufs_hba *hba) +diff --git a/include/ufs/ufs_quirks.h b/include/ufs/ufs_quirks.h +index 41ff44dfa1db3..f52de5ed1b3b6 100644 +--- a/include/ufs/ufs_quirks.h ++++ b/include/ufs/ufs_quirks.h +@@ -107,4 +107,10 @@ struct ufs_dev_quirk { + */ + #define UFS_DEVICE_QUIRK_DELAY_AFTER_LPM (1 << 11) + ++/* ++ * Some ufs devices may need more time to be in hibern8 before exiting. ++ * Enable this quirk to give it an additional 100us. ++ */ ++#define UFS_DEVICE_QUIRK_PA_HIBER8TIME (1 << 12) ++ + #endif /* UFS_QUIRKS_H_ */ +-- +2.39.5 + diff --git a/queue-6.12/selftests-bpf-mitigate-sockmap_ktls-disconnect_after.patch b/queue-6.12/selftests-bpf-mitigate-sockmap_ktls-disconnect_after.patch new file mode 100644 index 0000000000..2cfd07756b --- /dev/null +++ b/queue-6.12/selftests-bpf-mitigate-sockmap_ktls-disconnect_after.patch @@ -0,0 +1,50 @@ +From fd6c40f66a754e4c86049b00fb8c7357fce7a715 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Apr 2025 10:02:46 -0700 +Subject: selftests/bpf: Mitigate sockmap_ktls disconnect_after_delete failure + +From: Ihor Solodrai + +[ Upstream commit f2858f308131a09e33afb766cd70119b5b900569 ] + +"sockmap_ktls disconnect_after_delete" test has been failing on BPF CI +after recent merges from netdev: +* https://github.com/kernel-patches/bpf/actions/runs/14458537639 +* https://github.com/kernel-patches/bpf/actions/runs/14457178732 + +It happens because disconnect has been disabled for TLS [1], and it +renders the test case invalid. + +Removing all the test code creates a conflict between bpf and +bpf-next, so for now only remove the offending assert [2]. + +The test will be removed later on bpf-next. + +[1] https://lore.kernel.org/netdev/20250404180334.3224206-1-kuba@kernel.org/ +[2] https://lore.kernel.org/bpf/cfc371285323e1a3f3b006bfcf74e6cf7ad65258@linux.dev/ + +Signed-off-by: Ihor Solodrai +Signed-off-by: Andrii Nakryiko +Reviewed-by: Jiayuan Chen +Link: https://lore.kernel.org/bpf/20250416170246.2438524-1-ihor.solodrai@linux.dev +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c b/tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c +index 2d0796314862a..0a99fd404f6dc 100644 +--- a/tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c ++++ b/tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c +@@ -68,7 +68,6 @@ static void test_sockmap_ktls_disconnect_after_delete(int family, int map) + goto close_cli; + + err = disconnect(cli); +- ASSERT_OK(err, "disconnect"); + + close_cli: + close(cli); +-- +2.39.5 + diff --git a/queue-6.12/selftests-net-have-gro.sh-t-return-a-correct-exit-co.patch b/queue-6.12/selftests-net-have-gro.sh-t-return-a-correct-exit-co.patch new file mode 100644 index 0000000000..352e08ea60 --- /dev/null +++ b/queue-6.12/selftests-net-have-gro.sh-t-return-a-correct-exit-co.patch @@ -0,0 +1,37 @@ +From 37f2a19e8ba4337a58badabef1f67f369e14a6d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 11:27:23 -0800 +Subject: selftests/net: have `gro.sh -t` return a correct exit code + +From: Kevin Krakauer + +[ Upstream commit 784e6abd99f24024a8998b5916795f0bec9d2fd9 ] + +Modify gro.sh to return a useful exit code when the -t flag is used. It +formerly returned 0 no matter what. + +Tested: Ran `gro.sh -t large` and verified that test failures return 1. +Signed-off-by: Kevin Krakauer +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20250226192725.621969-2-krakauer@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/gro.sh | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/net/gro.sh b/tools/testing/selftests/net/gro.sh +index 02c21ff4ca81f..aabd6e5480b8e 100755 +--- a/tools/testing/selftests/net/gro.sh ++++ b/tools/testing/selftests/net/gro.sh +@@ -100,5 +100,6 @@ trap cleanup EXIT + if [[ "${test}" == "all" ]]; then + run_all_tests + else +- run_test "${proto}" "${test}" ++ exit_code=$(run_test "${proto}" "${test}") ++ exit $exit_code + fi; +-- +2.39.5 + diff --git a/queue-6.12/serial-mctrl_gpio-split-disable_ms-into-sync-and-no_.patch b/queue-6.12/serial-mctrl_gpio-split-disable_ms-into-sync-and-no_.patch new file mode 100644 index 0000000000..364528a80b --- /dev/null +++ b/queue-6.12/serial-mctrl_gpio-split-disable_ms-into-sync-and-no_.patch @@ -0,0 +1,247 @@ +From 3248841827441e81c96226bc07369ba5cee44d5a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 07:21:53 +0100 +Subject: serial: mctrl_gpio: split disable_ms into sync and no_sync APIs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alexis Lothoré + +[ Upstream commit 1bd2aad57da95f7f2d2bb52f7ad15c0f4993a685 ] + +The following splat has been observed on a SAMA5D27 platform using +atmel_serial: + +BUG: sleeping function called from invalid context at kernel/irq/manage.c:738 +in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 27, name: kworker/u5:0 +preempt_count: 1, expected: 0 +INFO: lockdep is turned off. +irq event stamp: 0 +hardirqs last enabled at (0): [<00000000>] 0x0 +hardirqs last disabled at (0): [] copy_process+0x1c4c/0x7bec +softirqs last enabled at (0): [] copy_process+0x1ca0/0x7bec +softirqs last disabled at (0): [<00000000>] 0x0 +CPU: 0 UID: 0 PID: 27 Comm: kworker/u5:0 Not tainted 6.13.0-rc7+ #74 +Hardware name: Atmel SAMA5 +Workqueue: hci0 hci_power_on [bluetooth] +Call trace: + unwind_backtrace from show_stack+0x18/0x1c + show_stack from dump_stack_lvl+0x44/0x70 + dump_stack_lvl from __might_resched+0x38c/0x598 + __might_resched from disable_irq+0x1c/0x48 + disable_irq from mctrl_gpio_disable_ms+0x74/0xc0 + mctrl_gpio_disable_ms from atmel_disable_ms.part.0+0x80/0x1f4 + atmel_disable_ms.part.0 from atmel_set_termios+0x764/0x11e8 + atmel_set_termios from uart_change_line_settings+0x15c/0x994 + uart_change_line_settings from uart_set_termios+0x2b0/0x668 + uart_set_termios from tty_set_termios+0x600/0x8ec + tty_set_termios from ttyport_set_flow_control+0x188/0x1e0 + ttyport_set_flow_control from wilc_setup+0xd0/0x524 [hci_wilc] + wilc_setup [hci_wilc] from hci_dev_open_sync+0x330/0x203c [bluetooth] + hci_dev_open_sync [bluetooth] from hci_dev_do_open+0x40/0xb0 [bluetooth] + hci_dev_do_open [bluetooth] from hci_power_on+0x12c/0x664 [bluetooth] + hci_power_on [bluetooth] from process_one_work+0x998/0x1a38 + process_one_work from worker_thread+0x6e0/0xfb4 + worker_thread from kthread+0x3d4/0x484 + kthread from ret_from_fork+0x14/0x28 + +This warning is emitted when trying to toggle, at the highest level, +some flow control (with serdev_device_set_flow_control) in a device +driver. At the lowest level, the atmel_serial driver is using +serial_mctrl_gpio lib to enable/disable the corresponding IRQs +accordingly. The warning emitted by CONFIG_DEBUG_ATOMIC_SLEEP is due to +disable_irq (called in mctrl_gpio_disable_ms) being possibly called in +some atomic context (some tty drivers perform modem lines configuration +in regions protected by port lock). + +Split mctrl_gpio_disable_ms into two differents APIs, a non-blocking one +and a blocking one. Replace mctrl_gpio_disable_ms calls with the +relevant version depending on whether the call is protected by some port +lock. + +Suggested-by: Jiri Slaby +Signed-off-by: Alexis Lothoré +Acked-by: Richard Genoud +Link: https://lore.kernel.org/r/20250217-atomic_sleep_mctrl_serial_gpio-v3-1-59324b313eef@bootlin.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + Documentation/driver-api/serial/driver.rst | 2 +- + drivers/tty/serial/8250/8250_port.c | 2 +- + drivers/tty/serial/atmel_serial.c | 2 +- + drivers/tty/serial/imx.c | 2 +- + drivers/tty/serial/serial_mctrl_gpio.c | 34 +++++++++++++++++----- + drivers/tty/serial/serial_mctrl_gpio.h | 17 +++++++++-- + drivers/tty/serial/sh-sci.c | 2 +- + drivers/tty/serial/stm32-usart.c | 2 +- + 8 files changed, 47 insertions(+), 16 deletions(-) + +diff --git a/Documentation/driver-api/serial/driver.rst b/Documentation/driver-api/serial/driver.rst +index 84b43061c11be..60434f2b02863 100644 +--- a/Documentation/driver-api/serial/driver.rst ++++ b/Documentation/driver-api/serial/driver.rst +@@ -103,4 +103,4 @@ Some helpers are provided in order to set/get modem control lines via GPIO. + .. kernel-doc:: drivers/tty/serial/serial_mctrl_gpio.c + :identifiers: mctrl_gpio_init mctrl_gpio_free mctrl_gpio_to_gpiod + mctrl_gpio_set mctrl_gpio_get mctrl_gpio_enable_ms +- mctrl_gpio_disable_ms ++ mctrl_gpio_disable_ms_sync mctrl_gpio_disable_ms_no_sync +diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c +index c1376727642a7..0519679929652 100644 +--- a/drivers/tty/serial/8250/8250_port.c ++++ b/drivers/tty/serial/8250/8250_port.c +@@ -1657,7 +1657,7 @@ static void serial8250_disable_ms(struct uart_port *port) + if (up->bugs & UART_BUG_NOMSR) + return; + +- mctrl_gpio_disable_ms(up->gpios); ++ mctrl_gpio_disable_ms_no_sync(up->gpios); + + up->ier &= ~UART_IER_MSI; + serial_port_out(port, UART_IER, up->ier); +diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c +index 09b246c9e389e..8bd39586a49f7 100644 +--- a/drivers/tty/serial/atmel_serial.c ++++ b/drivers/tty/serial/atmel_serial.c +@@ -700,7 +700,7 @@ static void atmel_disable_ms(struct uart_port *port) + + atmel_port->ms_irq_enabled = false; + +- mctrl_gpio_disable_ms(atmel_port->gpios); ++ mctrl_gpio_disable_ms_no_sync(atmel_port->gpios); + + if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS)) + idr |= ATMEL_US_CTSIC; +diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c +index 90974d338f3c0..8e3b15534bc72 100644 +--- a/drivers/tty/serial/imx.c ++++ b/drivers/tty/serial/imx.c +@@ -1596,7 +1596,7 @@ static void imx_uart_shutdown(struct uart_port *port) + imx_uart_dma_exit(sport); + } + +- mctrl_gpio_disable_ms(sport->gpios); ++ mctrl_gpio_disable_ms_sync(sport->gpios); + + uart_port_lock_irqsave(&sport->port, &flags); + ucr2 = imx_uart_readl(sport, UCR2); +diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c +index 8855688a5b6c0..ca55bcc0b6111 100644 +--- a/drivers/tty/serial/serial_mctrl_gpio.c ++++ b/drivers/tty/serial/serial_mctrl_gpio.c +@@ -322,11 +322,7 @@ void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios) + } + EXPORT_SYMBOL_GPL(mctrl_gpio_enable_ms); + +-/** +- * mctrl_gpio_disable_ms - disable irqs and handling of changes to the ms lines +- * @gpios: gpios to disable +- */ +-void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios) ++static void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios, bool sync) + { + enum mctrl_gpio_idx i; + +@@ -342,10 +338,34 @@ void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios) + if (!gpios->irq[i]) + continue; + +- disable_irq(gpios->irq[i]); ++ if (sync) ++ disable_irq(gpios->irq[i]); ++ else ++ disable_irq_nosync(gpios->irq[i]); + } + } +-EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms); ++ ++/** ++ * mctrl_gpio_disable_ms_sync - disable irqs and handling of changes to the ms ++ * lines, and wait for any pending IRQ to be processed ++ * @gpios: gpios to disable ++ */ ++void mctrl_gpio_disable_ms_sync(struct mctrl_gpios *gpios) ++{ ++ mctrl_gpio_disable_ms(gpios, true); ++} ++EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms_sync); ++ ++/** ++ * mctrl_gpio_disable_ms_no_sync - disable irqs and handling of changes to the ++ * ms lines, and return immediately ++ * @gpios: gpios to disable ++ */ ++void mctrl_gpio_disable_ms_no_sync(struct mctrl_gpios *gpios) ++{ ++ mctrl_gpio_disable_ms(gpios, false); ++} ++EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms_no_sync); + + void mctrl_gpio_enable_irq_wake(struct mctrl_gpios *gpios) + { +diff --git a/drivers/tty/serial/serial_mctrl_gpio.h b/drivers/tty/serial/serial_mctrl_gpio.h +index fc76910fb105a..79e97838ebe56 100644 +--- a/drivers/tty/serial/serial_mctrl_gpio.h ++++ b/drivers/tty/serial/serial_mctrl_gpio.h +@@ -87,9 +87,16 @@ void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios); + void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios); + + /* +- * Disable gpio interrupts to report status line changes. ++ * Disable gpio interrupts to report status line changes, and block until ++ * any corresponding IRQ is processed + */ +-void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios); ++void mctrl_gpio_disable_ms_sync(struct mctrl_gpios *gpios); ++ ++/* ++ * Disable gpio interrupts to report status line changes, and return ++ * immediately ++ */ ++void mctrl_gpio_disable_ms_no_sync(struct mctrl_gpios *gpios); + + /* + * Enable gpio wakeup interrupts to enable wake up source. +@@ -148,7 +155,11 @@ static inline void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios) + { + } + +-static inline void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios) ++static inline void mctrl_gpio_disable_ms_sync(struct mctrl_gpios *gpios) ++{ ++} ++ ++static inline void mctrl_gpio_disable_ms_no_sync(struct mctrl_gpios *gpios) + { + } + +diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c +index f43059e1b5c28..80efe3b0ed0c3 100644 +--- a/drivers/tty/serial/sh-sci.c ++++ b/drivers/tty/serial/sh-sci.c +@@ -2297,7 +2297,7 @@ static void sci_shutdown(struct uart_port *port) + dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); + + s->autorts = false; +- mctrl_gpio_disable_ms(to_sci_port(port)->gpios); ++ mctrl_gpio_disable_ms_sync(to_sci_port(port)->gpios); + + uart_port_lock_irqsave(port, &flags); + sci_stop_rx(port); +diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c +index 9b9981352b1e1..e685cace5c854 100644 +--- a/drivers/tty/serial/stm32-usart.c ++++ b/drivers/tty/serial/stm32-usart.c +@@ -944,7 +944,7 @@ static void stm32_usart_enable_ms(struct uart_port *port) + + static void stm32_usart_disable_ms(struct uart_port *port) + { +- mctrl_gpio_disable_ms(to_stm32_port(port)->gpios); ++ mctrl_gpio_disable_ms_sync(to_stm32_port(port)->gpios); + } + + /* Transmit stop */ +-- +2.39.5 + diff --git a/queue-6.12/serial-sh-sci-update-the-suspend-resume-support.patch b/queue-6.12/serial-sh-sci-update-the-suspend-resume-support.patch new file mode 100644 index 0000000000..064e5cd419 --- /dev/null +++ b/queue-6.12/serial-sh-sci-update-the-suspend-resume-support.patch @@ -0,0 +1,164 @@ +From 9469f6e0b2edebbb7ee4448e03e2fb802c628f12 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 13:33:13 +0200 +Subject: serial: sh-sci: Update the suspend/resume support + +From: Claudiu Beznea + +[ Upstream commit 22a6984c5b5df8eab864d7f3e8b94d5a554d31ab ] + +The Renesas RZ/G3S supports a power saving mode where power to most of the +SoC components is turned off. When returning from this power saving mode, +SoC components need to be re-configured. + +The SCIFs on the Renesas RZ/G3S need to be re-configured as well when +returning from this power saving mode. The sh-sci code already configures +the SCIF clocks, power domain and registers by calling uart_resume_port() +in sci_resume(). On suspend path the SCIF UART ports are suspended +accordingly (by calling uart_suspend_port() in sci_suspend()). The only +missing setting is the reset signal. For this assert/de-assert the reset +signal on driver suspend/resume. + +In case the no_console_suspend is specified by the user, the registers need +to be saved on suspend path and restore on resume path. To do this the +sci_console_save()/sci_console_restore() functions were added. There is no +need to cache/restore the status or FIFO registers. Only the control +registers. The registers that will be saved/restored on suspend/resume are +specified by the struct sci_suspend_regs data structure. + +Signed-off-by: Claudiu Beznea +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/r/20250207113313.545432-1-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/sh-sci.c | 71 +++++++++++++++++++++++++++++++++++-- + 1 file changed, 69 insertions(+), 2 deletions(-) + +diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c +index 80efe3b0ed0c3..779074b1c2be4 100644 +--- a/drivers/tty/serial/sh-sci.c ++++ b/drivers/tty/serial/sh-sci.c +@@ -104,6 +104,15 @@ struct plat_sci_reg { + u8 offset, size; + }; + ++struct sci_suspend_regs { ++ u16 scsmr; ++ u16 scscr; ++ u16 scfcr; ++ u16 scsptr; ++ u8 scbrr; ++ u8 semr; ++}; ++ + struct sci_port_params { + const struct plat_sci_reg regs[SCIx_NR_REGS]; + unsigned int fifosize; +@@ -134,6 +143,8 @@ struct sci_port { + struct dma_chan *chan_tx; + struct dma_chan *chan_rx; + ++ struct reset_control *rstc; ++ + #ifdef CONFIG_SERIAL_SH_SCI_DMA + struct dma_chan *chan_tx_saved; + struct dma_chan *chan_rx_saved; +@@ -153,6 +164,7 @@ struct sci_port { + int rx_trigger; + struct timer_list rx_fifo_timer; + int rx_fifo_timeout; ++ struct sci_suspend_regs suspend_regs; + u16 hscif_tot; + + bool has_rtscts; +@@ -3384,6 +3396,7 @@ static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev, + } + + sp = &sci_ports[id]; ++ sp->rstc = rstc; + *dev_id = id; + + p->type = SCI_OF_TYPE(data); +@@ -3532,13 +3545,57 @@ static int sci_probe(struct platform_device *dev) + return 0; + } + ++static void sci_console_save(struct sci_port *s) ++{ ++ struct sci_suspend_regs *regs = &s->suspend_regs; ++ struct uart_port *port = &s->port; ++ ++ if (sci_getreg(port, SCSMR)->size) ++ regs->scsmr = sci_serial_in(port, SCSMR); ++ if (sci_getreg(port, SCSCR)->size) ++ regs->scscr = sci_serial_in(port, SCSCR); ++ if (sci_getreg(port, SCFCR)->size) ++ regs->scfcr = sci_serial_in(port, SCFCR); ++ if (sci_getreg(port, SCSPTR)->size) ++ regs->scsptr = sci_serial_in(port, SCSPTR); ++ if (sci_getreg(port, SCBRR)->size) ++ regs->scbrr = sci_serial_in(port, SCBRR); ++ if (sci_getreg(port, SEMR)->size) ++ regs->semr = sci_serial_in(port, SEMR); ++} ++ ++static void sci_console_restore(struct sci_port *s) ++{ ++ struct sci_suspend_regs *regs = &s->suspend_regs; ++ struct uart_port *port = &s->port; ++ ++ if (sci_getreg(port, SCSMR)->size) ++ sci_serial_out(port, SCSMR, regs->scsmr); ++ if (sci_getreg(port, SCSCR)->size) ++ sci_serial_out(port, SCSCR, regs->scscr); ++ if (sci_getreg(port, SCFCR)->size) ++ sci_serial_out(port, SCFCR, regs->scfcr); ++ if (sci_getreg(port, SCSPTR)->size) ++ sci_serial_out(port, SCSPTR, regs->scsptr); ++ if (sci_getreg(port, SCBRR)->size) ++ sci_serial_out(port, SCBRR, regs->scbrr); ++ if (sci_getreg(port, SEMR)->size) ++ sci_serial_out(port, SEMR, regs->semr); ++} ++ + static __maybe_unused int sci_suspend(struct device *dev) + { + struct sci_port *sport = dev_get_drvdata(dev); + +- if (sport) ++ if (sport) { + uart_suspend_port(&sci_uart_driver, &sport->port); + ++ if (!console_suspend_enabled && uart_console(&sport->port)) ++ sci_console_save(sport); ++ else ++ return reset_control_assert(sport->rstc); ++ } ++ + return 0; + } + +@@ -3546,8 +3603,18 @@ static __maybe_unused int sci_resume(struct device *dev) + { + struct sci_port *sport = dev_get_drvdata(dev); + +- if (sport) ++ if (sport) { ++ if (!console_suspend_enabled && uart_console(&sport->port)) { ++ sci_console_restore(sport); ++ } else { ++ int ret = reset_control_deassert(sport->rstc); ++ ++ if (ret) ++ return ret; ++ } ++ + uart_resume_port(&sci_uart_driver, &sport->port); ++ } + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.12/series b/queue-6.12/series new file mode 100644 index 0000000000..7afdb13c14 --- /dev/null +++ b/queue-6.12/series @@ -0,0 +1,551 @@ +drm-amd-display-configure-dtbclk_p-with-optc-only-fo.patch +drm-amd-display-do-not-enable-replay-when-vtotal-upd.patch +drm-amd-display-correct-timing_adjust_pending-flag-s.patch +drm-amd-display-defer-bw-optimization-blocked-drr-ad.patch +i2c-designware-use-temporary-variable-for-struct-dev.patch +i2c-designware-fix-an-error-handling-path-in-i2c_dw_.patch +phy-renesas-rcar-gen3-usb2-move-irq-request-in-probe.patch +phy-renesas-rcar-gen3-usb2-lock-around-hardware-regi.patch +phy-renesas-rcar-gen3-usb2-assert-pll-reset-on-phy-p.patch +cpufreq-add-sm8650-to-cpufreq-dt-platdev-blocklist.patch +nvmem-rockchip-otp-move-read-offset-into-variant-dat.patch +nvmem-rockchip-otp-add-rk3576-variant-data.patch +nvmem-core-fix-bit-offsets-of-more-than-one-byte.patch +nvmem-core-verify-cell-s-raw_len.patch +nvmem-core-update-raw_len-if-the-bit-reading-is-requ.patch +nvmem-qfprom-switch-to-4-byte-aligned-reads.patch +scsi-target-iscsi-fix-timeout-on-deleted-connection.patch +scsi-ufs-introduce-quirk-to-extend-pa_hibern8time-fo.patch +virtio_ring-fix-data-race-by-tagging-event_triggered.patch +dma-mapping.c-dev_dbg-support-for-dma_addressing_lim.patch +intel_th-avoid-using-deprecated-page-mapping-index-f.patch +mei-vsc-use-struct-vsc_tp_packet-as-vsc-tp-tx_buf-an.patch +dma-mapping-avoid-potential-unused-data-compilation-.patch +cgroup-fix-compilation-issue-due-to-cgroup_mutex-not.patch +vhost_task-fix-vhost_task_create-documentation.patch +vhost-scsi-protect-vq-log_used-with-vq-mutex.patch +scsi-mpi3mr-add-level-check-to-control-event-logging.patch +net-enetc-refactor-bulk-flipping-of-rx-buffers-to-se.patch +dma-mapping-fix-warning-reported-for-missing-prototy.patch +ima-process_measurement-needlessly-takes-inode_lock-.patch +fs-buffer-split-locking-for-pagecache-lookups.patch +fs-buffer-introduce-sleeping-flavors-for-pagecache-l.patch +fs-buffer-use-sleeping-version-of-__find_get_block.patch +fs-ocfs2-use-sleeping-version-of-__find_get_block.patch +fs-jbd2-use-sleeping-version-of-__find_get_block.patch +fs-ext4-use-sleeping-version-of-sb_find_get_block.patch +drm-amd-display-enable-urgent-latency-adjustment-on-.patch +drm-amdgpu-allow-p2p-access-through-xgmi.patch +selftests-bpf-mitigate-sockmap_ktls-disconnect_after.patch +block-fix-race-between-set_blocksize-and-read-paths.patch +io_uring-don-t-duplicate-flushing-in-io_req_post_cqe.patch +bpf-fix-possible-endless-loop-in-bpf-map-iteration.patch +samples-bpf-fix-compilation-failure-for-samples-bpf-.patch +kconfig-merge_config-use-an-empty-file-as-initfile.patch +x86-fred-fix-system-hang-during-s4-resume-with-fred-.patch +s390-vfio-ap-fix-no-ap-queue-sharing-allowed-message.patch +cifs-add-fallback-for-smb2-create-without-file_read_.patch +cifs-fix-querying-and-creating-mf-symlinks-over-smb1.patch +cifs-fix-negotiate-retry-functionality.patch +smb-client-store-original-io-parameters-and-prevent-.patch +fuse-return-eperm-rather-than-enosys-from-link.patch +exfat-call-bh_read-in-get_block-only-when-necessary.patch +io_uring-msg-initialise-msg-request-opcode.patch +nfsv4-check-for-delegation-validity-in-nfs_start_del.patch +nfs-don-t-allow-waiting-for-exiting-tasks.patch +sunrpc-don-t-allow-waiting-for-exiting-tasks.patch +arm64-add-support-for-hip09-spectre-bhb-mitigation.patch +iommufd-extend-iommu_get_hw_info-to-report-pasid-cap.patch +tracing-mark-binary-printing-functions-with-__printf.patch +acpi-pnp-add-intel-oc-watchdog-ids-to-non-pnp-device.patch +tpm-convert-warn-to-dbg-in-tpm2_start_auth_session.patch +mailbox-pcc-use-acpi_os_ioremap-instead-of-ioremap.patch +mailbox-use-error-ret-code-of-of_parse_phandle_with_.patch +riscv-allow-nommu-kernels-to-access-all-of-ram.patch +fbdev-fsl-diu-fb-add-missing-device_remove_file.patch +fbcon-use-correct-erase-colour-for-clearing-in-fbcon.patch +fbdev-core-tileblit-implement-missing-margin-clearin.patch +cifs-set-default-netbios-rfc1001-server-name-to-host.patch +cifs-add-validation-check-for-the-fields-in-smb_aces.patch +cifs-fix-establishing-netbios-session-for-smb2-conne.patch +nfsv4-treat-enetunreach-errors-as-fatal-for-state-re.patch +sunrpc-rpc_clnt_set_transport-must-not-change-the-au.patch +sunrpc-rpcbind-should-never-reset-the-port-to-the-va.patch +spi-rockchip-fix-register-out-of-bounds-access.patch +asoc-codecs-wsa884x-correct-vi-sense-channel-mask.patch +asoc-codecs-wsa883x-correct-vi-sense-channel-mask.patch +mctp-fix-incorrect-tx-flow-invalidation-condition-in.patch +net-tn40xx-add-pci-id-of-the-aqr105-based-tehuti-tn4.patch +net-tn40xx-create-swnode-for-mdio-and-aqr105-phy-and.patch +thermal-drivers-mediatek-lvts-start-sensor-interrupt.patch +thermal-drivers-qoriq-power-down-tmu-on-system-suspe.patch +bluetooth-btmtksdio-prevent-enabling-interrupts-afte.patch +bluetooth-disable-sco-support-if-read_voice_setting-.patch +exit-fix-the-usage-of-delay_group_leader-exit_code-i.patch +dql-fix-dql-limit-value-when-reset.patch +lockdep-fix-wait-context-check-on-softirq-for-preemp.patch +objtool-properly-disable-uaccess-validation.patch +pci-dwc-ep-ensure-proper-iteration-over-outbound-map.patch +r8169-disable-rtl8126-zrx-dc-timeout.patch +tools-build-don-t-pass-test-log-files-to-linker.patch +pnfs-flexfiles-report-enetdown-as-a-connection-error.patch +drm-amdgpu-discovery-check-ip_discovery-fw-file-avai.patch +drm-amdkfd-set-precise-mem-ops-caps-to-disabled-for-.patch +pci-vmd-disable-msi-remapping-bypass-under-xen.patch +xen-pci-do-not-register-devices-with-segments-0x1000.patch +ext4-on-a-remount-only-log-the-ro-or-r-w-state-when-.patch +libnvdimm-labels-fix-divide-error-in-nd_label_data_i.patch +pidfs-improve-multi-threaded-exec-and-premature-thre.patch +staging-vchiq_arm-create-keep-alive-thread-during-pr.patch +mmc-host-wait-for-vdd-to-settle-on-card-power-off.patch +drm-amdgpu-skip-pcie_replay_count-sysfs-creation-for.patch +cgroup-rstat-avoid-disabling-irqs-for-o-num_cpu.patch +wifi-mt76-only-mark-tx-status-failed-frames-as-acked.patch +wifi-mt76-mt7996-fix-ser-reset-trigger-on-wed-reset.patch +wifi-mt76-mt7996-revise-txs-size.patch +wifi-mt76-mt7925-load-the-appropriate-clc-data-based.patch +wifi-mt76-mt7925-fix-fails-to-enter-low-power-mode-i.patch +x86-headers-replace-__assembly__-with-__assembler__-.patch +x86-stackprotector-64-only-export-__ref_stack_chk_gu.patch +x86-smpboot-fix-init-delay-assignment-for-extended-i.patch +x86-microcode-update-the-intel-processor-flag-scan-c.patch +x86-mm-check-return-value-from-memblock_phys_alloc_r.patch +i2c-qup-vote-for-interconnect-bandwidth-to-dram.patch +i2c-pxa-fix-call-balance-of-i2c-clk-handling-routine.patch +btrfs-make-btrfs_discard_workfn-block_group-ref-expl.patch +btrfs-avoid-linker-error-in-btrfs_find_create_tree_b.patch +btrfs-run-btrfs_error_commit_super-early.patch +btrfs-fix-non-empty-delayed-iputs-list-on-unmount-du.patch +btrfs-properly-limit-inline-data-extent-according-to.patch +btrfs-prevent-inline-data-extents-read-from-touching.patch +btrfs-get-zone-unusable-bytes-while-holding-lock-at-.patch +btrfs-send-return-enametoolong-when-attempting-a-pat.patch +btrfs-zoned-exit-btrfs_can_activate_zone-if-btrfs_fs.patch +blk-cgroup-improve-policy-registration-error-handlin.patch +drm-amdgpu-release-xcp_mgr-on-exit.patch +drm-amd-display-guard-against-setting-dispclk-low-fo.patch +drm-amdgpu-adjust-drm_firmware_drivers_only-handling.patch +i3c-master-svc-fix-missing-stop-for-master-request.patch +s390-tlb-use-mm_has_pgste-instead-of-mm_alloc_pgste.patch +dlm-make-tcp-still-work-in-multi-link-env.patch +clocksource-drivers-timer-riscv-stop-stimecmp-when-c.patch +um-store-full-csgsfs-and-ss-register-from-mcontext.patch +um-update-min_low_pfn-to-match-changes-in-uml_reserv.patch +wifi-mwifiex-fix-ht40-bandwidth-issue.patch +bnxt_en-query-fw-parameters-when-the-caps_change-bit.patch +riscv-call-secondary-mmu-notifier-when-flushing-the-.patch +ext4-reorder-capability-check-last.patch +hypfs_create_cpu_files-add-missing-check-for-hypfs_m.patch +scsi-st-tighten-the-page-format-heuristics-with-mode.patch +scsi-st-erase-does-not-change-tape-location.patch +vfio-pci-handle-intx-irq_notconnected.patch +libbpf-pass-bpf-token-from-find_prog_btf_id-to-bpf_b.patch +bpf-return-prog-btf_id-without-capable-check.patch +pci-dwc-use-resource-start-as-ioremap-input-in-dw_pc.patch +jbd2-do-not-try-to-recover-wiped-journal.patch +tcp-reorganize-tcp_in_ack_event-and-tcp_count_delive.patch +rtc-rv3032-fix-eerd-location.patch +objtool-fix-error-handling-inconsistencies-in-check.patch +thunderbolt-do-not-add-non-active-nvm-if-nvm-upgrade.patch +erofs-initialize-decompression-early.patch +spi-spi-mux-fix-coverity-issue-unchecked-return-valu.patch +asoc-pcm6240-drop-bogus-code-handling-irq-as-gpio.patch +asoc-mediatek-mt6359-add-stub-for-mt6359_accdet_enab.patch +bpf-allow-pre-ordering-for-bpf-cgroup-progs.patch +kbuild-fix-argument-parsing-in-scripts-config.patch +kconfig-do-not-clear-symbol_valid-when-reading-inclu.patch +crypto-octeontx2-suppress-auth-failure-screaming-due.patch +dm-restrict-dm-device-size-to-2-63-512-bytes.patch +net-smc-use-the-correct-ndev-to-find-pnetid-by-pneti.patch +xen-add-support-for-xenserver-6.1-platform-device.patch +pinctrl-tegra-restore-sfsel-bit-when-freeing-pins.patch +mfd-tps65219-remove-tps65219_reg_ti_dev_id-check.patch +drm-amdgpu-gfx12-don-t-read-registers-in-mqd-init.patch +drm-amdgpu-gfx11-don-t-read-registers-in-mqd-init.patch +drm-amdgpu-update-sriov-video-codec-caps.patch +asoc-sun4i-codec-support-hp-det-gpios-property.patch +clk-qcom-lpassaudiocc-sc7280-add-support-for-lpass-r.patch +f2fs-defer-readonly-check-vs-norecovery.patch +ext4-reject-the-data_err-abort-option-in-nojournal-m.patch +ext4-do-not-convert-the-unwritten-extents-if-data-wr.patch +rdma-uverbs-propagate-errors-from-rdma_lookup_get_uo.patch +posix-timers-add-cond_resched-to-posix_timer_add-sea.patch +posix-timers-ensure-that-timer-initialization-is-ful.patch +net-stmmac-dwmac-rk-validate-grf-and-peripheral-grf-.patch +net-hsr-fix-prp-duplicate-detection.patch +timer_list-don-t-use-pk-through-printk.patch +wifi-rtw89-set-force-he-tb-mode-when-connecting-to-1.patch +netfilter-conntrack-bound-nf_conntrack-sysctl-writes.patch +pnp-expand-length-of-fixup-id-string.patch +phy-rockchip-usbdp-only-verify-link-rates-lanes-volt.patch +arm64-mm-check-pmd_table-in-pmd_trans_huge.patch +arm64-mm-check-pud_type_table-in-pud_bad.patch +mmc-dw_mmc-add-exynos7870-dw-mmc-support.patch +mmc-sdhci-disable-sd-card-clock-before-changing-para.patch +usb-xhci-don-t-change-the-status-of-stalled-tds-on-f.patch +wifi-iwlwifi-mvm-fix-setting-the-tk-when-associated.patch +hwmon-dell-smm-increment-the-number-of-fans.patch +iommu-keep-dev-iommu-state-consistent.patch +printk-check-con_suspend-when-unblanking-a-console.patch +wifi-iwlwifi-don-t-warn-when-if-there-is-a-fw-error.patch +wifi-iwlwifi-w-a-fw-smps-mode-selection.patch +wifi-iwlwifi-fix-debug-actions-order.patch +wifi-iwlwifi-mark-br-device-not-integrated.patch +wifi-iwlwifi-fix-the-eckv-uefi-variable-name.patch +wifi-mac80211-fix-warning-on-disconnect-during-faile.patch +wifi-mac80211_hwsim-fix-mld-address-translation.patch +wifi-cfg80211-allow-ir-in-20-mhz-configurations.patch +ipv6-save-dontfrag-in-cork.patch +drm-amd-display-remove-minimum-dispclk-and-apply-oem.patch +drm-amd-display-calculate-the-remain-segments-for-al.patch +drm-amd-display-not-abort-link-train-when-bw-is-low.patch +drm-amd-display-fix-incorrect-dpcd-configs-while-rep.patch +gfs2-check-for-empty-queue-in-run_queue.patch +auxdisplay-charlcd-partially-revert-move-hwidth-and-.patch +asoc-qcom-sm8250-explicitly-set-format-in-sm8250_be_.patch +badblocks-fix-a-nonsense-warn_on-which-checks-whethe.patch +coresight-etb10-change-etb_drvdata-spinlock-s-type-t.patch +iommu-vt-d-move-scalable-mode-ats-enablement-to-prob.patch +iommu-amd-pgtbl_v2-improve-error-handling.patch +cpufreq-tegra186-share-policy-per-cluster.patch +watchdog-aspeed-update-bootstatus-handling.patch +pci-endpoint-pci-epf-test-fix-double-free-that-cause.patch +misc-pci_endpoint_test-give-disabled-bars-a-distinct.patch +crypto-lzo-fix-compression-buffer-overrun.patch +crypto-mxs-dcp-only-set-otp_key-bit-for-otp-key.patch +drm-amdkfd-set-per-process-flags-only-once-for-gfx9-.patch +drm-amdkfd-set-per-process-flags-only-once-cik-vi.patch +drm-amdgpu-fix-missing-drain-retry-fault-the-last-en.patch +arm64-tegra-p2597-fix-gpio-for-vdd-1v8-dis-regulator.patch +arm64-tegra-resize-aperture-for-the-igx-pcie-c5-slot.patch +powerpc-prom_init-fixup-missing-size-cells-on-powerb.patch +alsa-seq-improve-data-consistency-at-polling.patch +tcp-bring-back-numa-dispersion-in-inet_ehash_locks_a.patch +rtc-ds1307-stop-disabling-alarms-on-probe.patch +ieee802154-ca8210-use-proper-setters-and-getters-for.patch +drm-xe-nuke-vm-s-mapping-upon-close.patch +drm-xe-retry-bo-allocation.patch +soc-samsung-include-linux-array_size.h-where-needed.patch +arm-tegra-switch-dsi-b-clock-parent-to-plld-on-tegra.patch +media-c8sectpfe-call-of_node_put-i2c_bus-only-once-i.patch +usb-xhci-set-page-size-to-the-xhci-supported-size.patch +dm-cache-prevent-bug_on-by-blocking-retries-on-faile.patch +soc-mediatek-mtk-mutex-add-dpi1-sof-eof-to-mt8188-mu.patch +orangefs-do-not-truncate-file-size.patch +drm-gem-test-for-imported-gem-buffers-with-helper.patch +net-phylink-use-pl-link_interface-in-phylink_expects.patch +blk-throttle-don-t-take-carryover-for-prioritized-pr.patch +remoteproc-qcom_wcnss-handle-platforms-with-only-sin.patch +drm-amdgpu-do-not-program-agp-bar-regs-under-sriov-i.patch +drm-amd-display-ensure-dmcub-idle-before-reset-on-dc.patch +drm-amd-display-skip-checking-frl_mode-bit-for-pcon-.patch +drm-amd-display-fix-dmub-reset-sequence-for-dcn401.patch +drm-amd-display-fix-p-state-type-when-p-state-is-uns.patch +drm-amd-display-request-hw-cursor-on-dcn3.2-with-sub.patch +perf-core-clean-up-perf_try_init_event.patch +media-cx231xx-set-device_caps-for-417.patch +pinctrl-bcm281xx-use-unsigned-int-instead-of-bare-un.patch +rcu-fix-get_state_synchronize_rcu_full-gp-start-dete.patch +net-ethernet-ti-cpsw_new-populate-netdev-of_node.patch +net-phy-nxp-c45-tja11xx-add-match_phy_device-to-tja1.patch +dpll-add-an-assertion-to-check-freq_supported_num.patch +ublk-enforce-ublks_max-only-for-unprivileged-devices.patch +iommufd-disallow-allocating-nested-parent-domain-wit.patch +media-imx335-set-vblank-immediately.patch +net-pktgen-fix-mpls-maximum-labels-list-parsing.patch +perf-hw_breakpoint-return-eopnotsupp-for-unsupported.patch +alsa-hda-realtek-enable-pc-beep-passthrough-for-hp-e.patch +scsi-logging-fix-scsi_logging_level-bounds.patch +ipv4-fib-move-fib_valid_key_len-to-rtm_to_fib_config.patch +drm-rockchip-vop2-add-uv-swap-for-cluster-window.patch +block-mark-bounce-buffering-as-incompatible-with-int.patch +ublk-complete-command-synchronously-on-error.patch +media-uvcvideo-add-sanity-check-to-uvc_ioctl_xu_ctrl.patch +media-uvcvideo-handle-uvc-menu-translation-inside-uv.patch +clk-imx8mp-inform-ccf-of-maximum-frequency-of-clocks.patch +x86-bugs-make-spectre-user-default-depend-on-mitigat.patch +hwmon-gpio-fan-add-missing-mutex-locks.patch +arm-at91-pm-fix-at91_suspend_finish-for-zq-calibrati.patch +drm-mediatek-mtk_dpi-add-checks-for-reg_h_fre_con-ex.patch +fpga-altera-cvp-increase-credit-timeout.patch +perf-arm_pmuv3-call-kvm_vcpu_pmu_resync_el0-before-e.patch +soc-apple-rtkit-use-high-prio-work-queue.patch +soc-apple-rtkit-implement-oslog-buffers-properly.patch +wifi-ath12k-report-proper-tx-completion-status-to-ma.patch +pci-brcmstb-expand-inbound-window-size-up-to-64gb.patch +pci-brcmstb-add-a-softdep-to-mip-msi-x-driver.patch +nvme-map-uring_cmd-data-even-if-address-is-0.patch +firmware-arm_ffa-set-dma_mask-for-ffa-devices.patch +drm-xe-vf-retry-sending-mmio-request-to-guc-on-timeo.patch +drm-xe-pf-create-a-link-between-pf-and-vf-devices.patch +net-mlx5-avoid-report-two-health-errors-on-same-synd.patch +selftests-net-have-gro.sh-t-return-a-correct-exit-co.patch +pinctrl-sophgo-avoid-to-modify-untouched-bit-when-se.patch +drm-amdkfd-kfd-release_work-possible-circular-lockin.patch +drm-xe-xe_gen_wa_oob-replace-program_invocation_shor.patch +leds-pwm-multicolor-add-check-for-fwnode_property_re.patch +net-ethernet-mtk_ppe_offload-allow-qinq-double-eth_p.patch +net-xgene-v2-remove-incorrect-acpi_ptr-annotation.patch +bonding-report-duplicate-mac-address-in-all-situatio.patch +wifi-ath12k-improve-bss-discovery-with-hidden-ssid-i.patch +soc-ti-k3-socinfo-do-not-use-syscon-helper-to-build-.patch +bpf-search-and-add-kfuncs-in-struct_ops-prologue-and.patch +octeontx2-af-rpm-register-driver-with-pci-subsys-ids.patch +x86-build-fix-broken-copy-command-in-genimage.sh-whe.patch +drm-amd-display-handle-max_downscale_src_width-fail-.patch +drm-amd-display-fix-dcn4x-init-failed.patch +drm-amd-display-fix-mismatch-type-comparison.patch +asoc-mediatek-mt8188-treat-dmic_gainx_cur-as-non-vol.patch +asoc-mediatek-mt8188-add-reference-for-dmic-clocks.patch +x86-nmi-add-an-emergency-handler-in-nmi_desc-use-it-.patch +vhost-scsi-return-queue-full-for-page-alloc-failures.patch +vdpa-mlx5-fix-mlx5_vdpa_get_config-endianness-on-big.patch +cpuidle-menu-avoid-discarding-useful-information.patch +media-adv7180-disable-test-pattern-control-on-adv718.patch +media-tc358746-improve-calculation-of-the-d-phy-timi.patch +net-mlx5e-add-correct-match-to-check-ipsec-syndromes.patch +scsi-mpi3mr-update-timestamp-only-for-supervisor-ioc.patch +loop-check-in-lo_flags_direct_io-in-loop_default_blo.patch +libbpf-fix-out-of-bound-read.patch +dm-fix-unconditional-io-throttle-caused-by-req_prefl.patch +fs-mpage-avoid-negative-shift-for-large-blocksize.patch +scsi-scsi_debug-first-fixes-for-tapes.patch +net-mlx5-change-pool_next_size-define-value-and-make.patch +x86-kaslr-reduce-kaslr-entropy-on-most-x86-systems.patch +crypto-ahash-set-default-reqsize-from-ahash_alg.patch +crypto-skcipher-zap-type-in-crypto_alloc_sync_skciph.patch +net-ipv6-init-tunnel-link-netns-before-registering-d.patch +drm-xe-oa-ensure-that-polled-read-returns-latest-dat.patch +mips-use-arch-specific-syscall-name-match-function.patch +drm-amdgpu-remove-all-kfd-fences-from-the-bo-on-rele.patch +x86-locking-use-alt_output_sp-for-percpu_-try_-cmpxc.patch +genirq-msi-store-the-iommu-iova-directly-in-msi_desc.patch +mips-pm-cps-use-per-cpu-variables-as-per-cpu-not-per.patch +clocksource-mips-gic-timer-enable-counter-when-cpus-.patch +pci-epf-mhi-update-device-id-for-sa8775p.patch +scsi-mpt3sas-send-a-diag-reset-if-target-reset-fails.patch +wifi-rtw88-fix-rtw_init_vht_cap-for-rtl8814au.patch +wifi-rtw88-fix-rtw_init_ht_cap-for-rtl8814au.patch +wifi-rtw88-fix-rtw_desc_to_mcsrate-to-handle-mcs16-3.patch +wifi-rtw89-fw-propagate-error-code-from-rtw89_h2c_tx.patch +wifi-rtw89-fw-get-sb_sel_ver-via-get_unaligned_le32.patch +wifi-rtw89-fw-add-blacklist-to-avoid-obsolete-secure.patch +wifi-rtw89-8922a-fix-incorrect-sta-id-in-eht-mu-ppdu.patch +net-pktgen-fix-access-outside-of-user-given-buffer-i.patch +power-supply-axp20x_battery-update-temp-sensor-for-a.patch +edac-ie31200-work-around-false-positive-build-warnin.patch +bpf-prevent-unsafe-access-to-the-sock-fields-in-the-.patch +i3c-master-svc-flush-fifo-before-sending-dynamic-add.patch +mfd-axp20x-axp717-add-axp717_ts_pin_cfg-to-writeable.patch +eeprom-ee1004-check-chip-before-probing.patch +irqchip-riscv-imsic-separate-next-and-previous-point.patch +drm-amd-pm-fetch-current-power-limit-from-pmfw.patch +drm-amd-display-add-support-for-disconnected-edp-str.patch +drm-amd-display-guard-against-setting-dispclk-low-wh.patch +drm-amd-display-fix-bt2020-ycbcr-limited-full-range-.patch +drm-amd-display-read-lttpr-alpm-caps-during-link-cap.patch +revert-drm-amd-display-request-hw-cursor-on-dcn3.2-w.patch +drm-amd-display-don-t-treat-wb-connector-as-physical.patch +serial-mctrl_gpio-split-disable_ms-into-sync-and-no_.patch +rdma-core-fix-best-page-size-finding-when-it-can-cro.patch +pmdomain-imx-gpcv2-use-proper-helper-for-property-de.patch +can-c_can-use-of_property_present-to-test-existence-.patch +bpf-don-t-do-clean_live_states-when-state-loop_entry.patch +bpf-copy_verifier_state-should-copy-loop_entry-field.patch +eth-mlx4-don-t-try-to-complete-xdp-frames-in-netpoll.patch +pci-fix-old_size-lower-bound-in-calculate_iosize-too.patch +acpi-hed-always-initialize-before-evged.patch +vxlan-join-leave-mc-group-after-remote-changes.patch +x86-relocs-handle-r_x86_64_rex_gotpcrelx-relocations.patch +x86-boot-disable-stack-protector-for-early-boot-code.patch +hrtimers-replace-hrtimer_clock_to_base_table-with-sw.patch +irqchip-riscv-imsic-set-irq_set_affinity-for-imsic-b.patch +media-test-drivers-vivid-don-t-call-schedule-in-loop.patch +net-mlx5-modify-lsb-bitmask-in-temperature-event-to-.patch +net-mlx5-apply-rate-limiting-to-high-temperature-war.patch +firmware-arm_ffa-reject-higher-major-version-as-inco.patch +firmware-arm_ffa-handle-the-presence-of-host-partiti.patch +firmware-xilinx-dont-send-linux-address-to-get-fpga-.patch +asoc-ops-enforce-platform-maximum-on-initial-value.patch +asoc-tas2764-add-reg-defaults-for-tas2764_int_clk_cf.patch +asoc-tas2764-mark-sw_reset-as-volatile.patch +asoc-tas2764-power-up-down-amp-on-mute-ops.patch +asoc-soc-dai-check-return-value-at-snd_soc_dai_set_t.patch +pinctrl-devicetree-do-not-goto-err-when-probing-hogs.patch +smack-recognize-ipv4-cipso-w-o-categories.patch +smack-revert-smackfs-added-check-catlen.patch +kunit-tool-use-qboot-on-qemu-x86_64.patch +kernfs-don-t-re-lock-kernfs_root-kernfs_rwsem-in-ker.patch +kernfs-acquire-kernfs_rwsem-in-kernfs_node_dentry.patch +kernfs-acquire-kernfs_rwsem-in-kernfs_get_parent_den.patch +kernfs-acquire-kernfs_rwsem-in-kernfs_notify_workfn.patch +media-i2c-imx219-correct-the-minimum-vblanking-value.patch +media-v4l-memset-argument-to-0-before-calling-get_mb.patch +libbpf-fix-ldx-stx-st-co-re-relocation-size-adjustme.patch +net-mlx4_core-avoid-impossible-mlx4_db_alloc-order-v.patch +drm-xe-stop-ignoring-errors-from-xe_ttm_stolen_mgr_i.patch +drm-xe-fix-xe_tile_init_noalloc-error-propagation.patch +clk-qcom-ipq5018-allow-it-to-be-bulid-on-arm32.patch +clk-qcom-clk-alpha-pll-do-not-use-random-stack-value.patch +drm-xe-debugfs-fixed-the-return-value-of-wedged_mode.patch +drm-xe-debugfs-add-missing-xe_pm_runtime_put-in-wedg.patch +x86-ibt-handle-fineibt-in-handle_cfi_failure.patch +x86-traps-cleanup-and-robustify-decode_bug.patch +sched-reduce-the-default-slice-to-avoid-tasks-gettin.patch +serial-sh-sci-update-the-suspend-resume-support.patch +pinctrl-renesas-rzg2l-add-suspend-resume-support-for.patch +phy-phy-rockchip-samsung-hdptx-swap-the-definitions-.patch +phy-core-don-t-require-set_mode-callback-for-phy_get.patch +phy-exynos5-usbdrd-fix-eds-distribution-tuning-gs101.patch +soundwire-amd-change-the-soundwire-wake-enable-disab.patch +soundwire-cadence_master-set-frame-shape-and-divider.patch +net-stmmac-dwmac-loongson-set-correct-tx-rx-_fifo_si.patch +drm-amdgpu-mes11-fix-set_hw_resources_1-calculation.patch +drm-amdkfd-fix-missing-l2-cache-info-in-topology.patch +drm-amdgpu-set-snoop-bit-for-sdma-for-mi-series.patch +drm-amd-display-pass-calculated-dram_speed_mts-to-dm.patch +drm-amd-display-don-t-try-aux-transactions-on-discon.patch +drm-amdgpu-reset-psp-cmd-to-null-after-releasing-the.patch +drm-amd-pm-skip-p2s-load-for-smu-v13.0.12.patch +drm-amd-display-support-multiple-options-during-psr-.patch +revert-drm-amd-display-exit-idle-optimizations-befor.patch +drm-amd-display-update-cr-aux-rd-interval-interpreta.patch +drm-amd-display-initial-psr_version-with-correct-set.patch +drm-amd-display-increase-block_sequence-array-size.patch +drm-amd-display-use-nominal-vblank-if-provided-inste.patch +drm-amd-display-populate-register-address-for-dentis.patch +drm-amdgpu-use-active-umc-info-from-discovery.patch +drm-amdgpu-enlarge-the-vbios-binary-size-limit.patch +drm-amd-display-dm-drop-hw_support-check-in-amdgpu_d.patch +scsi-target-spc-fix-loop-traversal-in-spc_rsoc_get_d.patch +net-mlx5-xdp-enable-tx-side-xdp-multi-buffer-support.patch +net-mlx5-extend-ethtool-loopback-selftest-to-support.patch +net-mlx5e-set-the-tx_queue_len-for-pfifo_fast.patch +net-mlx5e-reduce-rep-rxq-depth-to-256-for-ecpf.patch +net-mlx5e-reduce-the-max-log-mpwrq-sz-for-ecpf-and-r.patch +drm-v3d-add-clock-handling.patch +xfrm-prevent-high-seq-input-in-non-esn-mode.patch +wifi-ath12k-fix-the-ampdu-id-fetch-in-the-hal_rx_mpd.patch +mptcp-pm-userspace-flags-clearer-msg-if-no-remote-ad.patch +wifi-iwlwifi-use-correct-imr-dump-variable.patch +wifi-iwlwifi-don-t-warn-during-reprobe.patch +wifi-mac80211-don-t-unconditionally-call-drv_mgd_com.patch +wifi-mac80211-remove-misplaced-drv_mgd_complete_tx-c.patch +wifi-mac80211-set-ieee80211_prep_tx_info-link_id-upo.patch +net-fec-refactor-mac-reset-to-function.patch +powerpc-pseries-iommu-memory-notifier-incorrectly-ad.patch +powerpc-pseries-iommu-create-ddw-for-devices-with-dm.patch +arch-powerpc-perf-check-the-instruction-type-before-.patch +ip-fib_rules-fetch-net-from-fib_rule-in-fib-46-_rule.patch +r8152-add-vendor-device-id-pair-for-dell-alienware-a.patch +iio-adc-ad7944-don-t-use-storagebits-for-sizing.patch +pstore-change-kmsg_bytes-storage-size-to-u32.patch +leds-trigger-netdev-configure-led-blink-interval-for.patch +net-ethtool-prevent-flow-steering-to-rss-contexts-wh.patch +ext4-don-t-write-back-data-before-punch-hole-in-nojo.patch +ext4-remove-writable-userspace-mappings-before-trunc.patch +wifi-rtw88-fix-download_firmware_validate-for-rtl881.patch +wifi-rtw88-fix-__rtw_download_firmware-for-rtl8814au.patch +wifi-rtw89-coex-assign-value-over-than-0-to-avoid-fi.patch +wifi-rtw89-fw-validate-multi-firmware-header-before-.patch +wifi-rtw89-fw-validate-multi-firmware-header-before-.patch-29952 +wifi-rtw89-call-power_on-ahead-before-selecting-firm.patch +clk-qcom-camcc-sm8250-use-clk_rcg2_shared_ops-for-so.patch +net-page_pool-avoid-false-positive-warning-if-napi-w.patch +tools-power-turbostat-clustered-uncore-mhz-counters-.patch +hwmon-xgene-hwmon-use-appropriate-type-for-the-laten.patch +f2fs-introduce-f2fs_base_attr-for-global-sysfs-entri.patch +media-qcom-camss-csid-only-add-tpg-v4l2-ctrl-if-tpg-.patch +media-qcom-camss-add-default-case-in-vfe_src_pad_cod.patch +drm-rockchip-vop2-improve-display-modes-handling-on-.patch +eth-fbnic-set-iff_unicast_flt-to-avoid-enabling-prom.patch +tools-ynl-gen-don-t-output-external-constants.patch +net-mlx5e-avoid-warn_on-when-configuring-mqprio-with.patch +cpufreq-amd-pstate-remove-unnecessary-driver_lock-in.patch +vxlan-annotate-fdb-data-races.patch +ipv4-ip_gre-fix-set-but-not-used-warning-in-ipgre_er.patch +r8169-don-t-scan-phy-addresses-0.patch +net-flush_backlog-small-changes.patch +bridge-mdb-allow-replace-of-a-host-joined-group.patch +ice-init-flow-director-before-rdma.patch +ice-treat-dyn_allowed-only-as-suggestion.patch +rcu-handle-quiescent-states-for-preempt_rcu-n-preemp.patch +rcu-handle-unstable-rdp-in-rcu_read_unlock_strict.patch +rcu-fix-header-guard-for-rcu_all_qs.patch +perf-avoid-the-read-if-the-count-is-already-updated.patch +ice-count-combined-queues-using-rx-tx-count.patch +drm-xe-relay-don-t-use-gfp_kernel-for-new-transactio.patch +net-mana-fix-warning-in-the-writer-of-client-oob.patch +scsi-lpfc-handle-duplicate-d_ids-in-ndlp-search-by-d.patch +scsi-lpfc-ignore-ndlp-rport-mismatch-in-dev_loss_tmo.patch +scsi-lpfc-free-phba-irq-in-lpfc_sli4_enable_msi-when.patch +scsi-st-restore-some-drive-settings-after-reset.patch +wifi-ath12k-avoid-napi_sync-before-napi_enable.patch +hid-usbkbd-fix-the-bit-shift-number-for-led_kana.patch +arm64-zynqmp-add-clock-output-names-property-in-cloc.patch +asoc-codecs-pcm3168a-allow-for-24-bit-in-provider-mo.patch +asoc-rt722-sdca-add-some-missing-readable-registers.patch +irqchip-riscv-aplic-add-support-for-hart-indexes.patch +dm-vdo-vio-pool-allow-variable-sized-metadata-vios.patch +dm-vdo-indexer-prevent-unterminated-string-warning.patch +dm-vdo-use-a-short-static-string-for-thread-name-pre.patch +drm-ast-find-vbios-mode-from-regular-display-size.patch +bpf-use-kallsyms-to-find-the-function-name-of-a-stru.patch +bpftool-fix-readlink-usage-in-get_fd_type.patch +firmware-arm_scmi-relax-duplicate-name-constraint-ac.patch +perf-amd-ibs-fix-perf_ibs_op.cnt_mask-for-curcnt.patch +perf-amd-ibs-fix-config-to-sample-period-calculation.patch +clk-renesas-rzg2l-cpg-refactor-runtime-pm-clock-vali.patch +wifi-rtl8xxxu-retry-firmware-download-on-error.patch +wifi-rtw88-don-t-use-static-local-variable-in-rtw882.patch +wifi-rtw89-add-wiphy_lock-to-work-that-isn-t-held-wi.patch +spi-zynqmp-gqspi-always-acknowledge-interrupts.patch +regulator-ad5398-add-device-tree-support.patch +wifi-ath12k-fix-ath12k_hal_tx_cmd_ext_desc_setup-inf.patch +accel-qaic-mask-out-sr-iov-pci-resources.patch +drm-xe-pf-reset-guc-vf-config-when-unprovisioning-cr.patch +wifi-ath9k-return-by-of_get_mac_address.patch +wifi-ath12k-fetch-regdb.bin-file-from-board-2.bin.patch +wifi-ath12k-fix-end-offset-bit-definition-in-monitor.patch +drm-bridge-adv7511-fill-stream-capabilities.patch +drm-nouveau-fix-the-broken-marco-gsp_msg_max_size.patch +wifi-ath11k-use-dma_alloc_noncoherent-for-rx_tid-buf.patch +drm-xe-move-suballocator-init-to-after-display-init.patch +drm-xe-do-not-attempt-to-bootstrap-vf-in-execlists-m.patch +wifi-rtw89-coex-separated-wi-fi-connecting-event-fro.patch +drm-xe-sa-always-call-drm_suballoc_manager_fini.patch +drm-xe-reject-bo-eviction-if-bo-is-bound-to-current-.patch +drm-atomic-clarify-the-rules-around-drm_atomic_state.patch +drm-buddy-fix-issue-that-force_merge-cannot-free-all.patch +drm-panel-edp-add-starry-116khd024006.patch +drm-add-valid-clones-check.patch +kernfs-use-rcu-to-access-kernfs_node-parent.patch +asoc-imx-card-adjust-over-allocation-of-memory-in-im.patch +book3s64-radix-fix-compile-errors-when-config_arch_w.patch +pinctrl-meson-define-the-pull-up-down-resistor-value.patch +smb-server-smb2pdu-check-return-value-of-xa_store.patch +platform-x86-intel-hid-add-pantherlake-support.patch +platform-x86-asus-wmi-disable-oobe-state-after-resum.patch +platform-x86-ideapad-laptop-add-support-for-some-new.patch +asoc-cs42l43-disable-headphone-clamps-during-type-de.patch +asoc-intel-bytcr_rt5640-add-dmi-quirk-for-acer-aspir.patch +alsa-hda-realtek-add-quirk-for-hp-spectre-x360-15-df.patch +nvme-pci-add-quirks-for-device-126f-1001.patch +nvme-pci-add-quirks-for-wdc-blue-sn550-15b7-5009.patch +alsa-usb-audio-fix-duplicated-name-in-midi-substream.patch +nvmet-tcp-don-t-restore-null-sk_state_change.patch +io_uring-fdinfo-annotate-racy-sq-cq-head-tail-reads.patch +cifs-fix-and-improve-cifs_query_path_info-and-cifs_q.patch +cifs-fix-changing-times-and-read-only-attr-over-smb1.patch +asoc-intel-sdw_utils-add-volume-limit-to-cs42l43-spe.patch +btrfs-compression-adjust-cb-compressed_folios-alloca.patch +btrfs-correct-the-order-of-prelim_ref-arguments-in-b.patch +btrfs-handle-empty-eb-folios-in-num_extent_folios.patch +btrfs-avoid-null-pointer-dereference-if-no-valid-csu.patch +tools-ynl-gen-validate-0-len-strings-from-kernel.patch +block-only-update-request-sector-if-needed.patch +wifi-iwlwifi-add-support-for-killer-on-mtl.patch +x86-kconfig-make-cfi_auto_default-depend-on-rust-or-.patch +xenbus-allow-pvh-dom0-a-non-local-xenstore.patch +drm-amd-display-call-fp-protect-before-mode-programm.patch +__legitimize_mnt-check-for-mnt_sync_umount-should-be.patch diff --git a/queue-6.12/smack-recognize-ipv4-cipso-w-o-categories.patch b/queue-6.12/smack-recognize-ipv4-cipso-w-o-categories.patch new file mode 100644 index 0000000000..72958d0e22 --- /dev/null +++ b/queue-6.12/smack-recognize-ipv4-cipso-w-o-categories.patch @@ -0,0 +1,75 @@ +From 2bd85938b32bef7a73efbcf328c3cce3e375c8aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jan 2025 02:40:34 +0300 +Subject: smack: recognize ipv4 CIPSO w/o categories + +From: Konstantin Andreev + +[ Upstream commit a158a937d864d0034fea14913c1f09c6d5f574b8 ] + +If SMACK label has CIPSO representation w/o categories, e.g.: + +| # cat /smack/cipso2 +| foo 10 +| @ 250/2 +| ... + +then SMACK does not recognize such CIPSO in input ipv4 packets +and substitues '*' label instead. Audit records may look like + +| lsm=SMACK fn=smack_socket_sock_rcv_skb action=denied +| subject="*" object="_" requested=w pid=0 comm="swapper/1" ... + +This happens in two steps: + +1) security/smack/smackfs.c`smk_set_cipso + does not clear NETLBL_SECATTR_MLS_CAT + from (struct smack_known *)skp->smk_netlabel.flags + on assigning CIPSO w/o categories: + +| rcu_assign_pointer(skp->smk_netlabel.attr.mls.cat, ncats.attr.mls.cat); +| skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl; + +2) security/smack/smack_lsm.c`smack_from_secattr + can not match skp->smk_netlabel with input packet's + struct netlbl_lsm_secattr *sap + because sap->flags have not NETLBL_SECATTR_MLS_CAT (what is correct) + but skp->smk_netlabel.flags have (what is incorrect): + +| if ((sap->flags & NETLBL_SECATTR_MLS_CAT) == 0) { +| if ((skp->smk_netlabel.flags & +| NETLBL_SECATTR_MLS_CAT) == 0) +| found = 1; +| break; +| } + +This commit sets/clears NETLBL_SECATTR_MLS_CAT in +skp->smk_netlabel.flags according to the presense of CIPSO categories. +The update of smk_netlabel is not atomic, so input packets processing +still may be incorrect during short time while update proceeds. + +Signed-off-by: Konstantin Andreev +Signed-off-by: Casey Schaufler +Signed-off-by: Sasha Levin +--- + security/smack/smackfs.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c +index 5dd1e164f9b13..d27e8b916bfb9 100644 +--- a/security/smack/smackfs.c ++++ b/security/smack/smackfs.c +@@ -933,6 +933,10 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, + if (rc >= 0) { + old_cat = skp->smk_netlabel.attr.mls.cat; + rcu_assign_pointer(skp->smk_netlabel.attr.mls.cat, ncats.attr.mls.cat); ++ if (ncats.attr.mls.cat) ++ skp->smk_netlabel.flags |= NETLBL_SECATTR_MLS_CAT; ++ else ++ skp->smk_netlabel.flags &= ~(u32)NETLBL_SECATTR_MLS_CAT; + skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl; + synchronize_rcu(); + netlbl_catmap_free(old_cat); +-- +2.39.5 + diff --git a/queue-6.12/smack-revert-smackfs-added-check-catlen.patch b/queue-6.12/smack-revert-smackfs-added-check-catlen.patch new file mode 100644 index 0000000000..4a20b82475 --- /dev/null +++ b/queue-6.12/smack-revert-smackfs-added-check-catlen.patch @@ -0,0 +1,64 @@ +From e5d25204ff1278a24a92f68a8a9c6bd5854f5b32 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jan 2025 02:40:33 +0300 +Subject: smack: Revert "smackfs: Added check catlen" + +From: Konstantin Andreev + +[ Upstream commit c7fb50cecff9cad19fdac5b37337eae4e42b94c7 ] + +This reverts commit ccfd889acb06eab10b98deb4b5eef0ec74157ea0 + +The indicated commit +* does not describe the problem that change tries to solve +* has programming issues +* introduces a bug: forever clears NETLBL_SECATTR_MLS_CAT + in (struct smack_known *)skp->smk_netlabel.flags + +Reverting the commit to reapproach original problem + +Signed-off-by: Konstantin Andreev +Signed-off-by: Casey Schaufler +Signed-off-by: Sasha Levin +--- + security/smack/smackfs.c | 17 +++-------------- + 1 file changed, 3 insertions(+), 14 deletions(-) + +diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c +index d27e8b916bfb9..1e35c9f807b2b 100644 +--- a/security/smack/smackfs.c ++++ b/security/smack/smackfs.c +@@ -830,7 +830,7 @@ static int smk_open_cipso(struct inode *inode, struct file *file) + static ssize_t smk_set_cipso(struct file *file, const char __user *buf, + size_t count, loff_t *ppos, int format) + { +- struct netlbl_lsm_catmap *old_cat, *new_cat = NULL; ++ struct netlbl_lsm_catmap *old_cat; + struct smack_known *skp; + struct netlbl_lsm_secattr ncats; + char mapcatset[SMK_CIPSOLEN]; +@@ -917,19 +917,8 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, + + smack_catset_bit(cat, mapcatset); + } +- ncats.flags = 0; +- if (catlen == 0) { +- ncats.attr.mls.cat = NULL; +- ncats.attr.mls.lvl = maplevel; +- new_cat = netlbl_catmap_alloc(GFP_ATOMIC); +- if (new_cat) +- new_cat->next = ncats.attr.mls.cat; +- ncats.attr.mls.cat = new_cat; +- skp->smk_netlabel.flags &= ~(1U << 3); +- rc = 0; +- } else { +- rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN); +- } ++ ++ rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN); + if (rc >= 0) { + old_cat = skp->smk_netlabel.attr.mls.cat; + rcu_assign_pointer(skp->smk_netlabel.attr.mls.cat, ncats.attr.mls.cat); +-- +2.39.5 + diff --git a/queue-6.12/smb-client-store-original-io-parameters-and-prevent-.patch b/queue-6.12/smb-client-store-original-io-parameters-and-prevent-.patch new file mode 100644 index 0000000000..e82a353b7f --- /dev/null +++ b/queue-6.12/smb-client-store-original-io-parameters-and-prevent-.patch @@ -0,0 +1,211 @@ +From aa05216e99d038bf68e41d070c56f24b2e835d6e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Mar 2025 21:33:14 +0800 +Subject: smb: client: Store original IO parameters and prevent zero IO sizes + +From: Wang Zhaolong + +[ Upstream commit 287906b20035a04a234d1a3c64f760a5678387be ] + +During mount option processing and negotiation with the server, the +original user-specified rsize/wsize values were being modified directly. +This makes it impossible to recover these values after a connection +reset, leading to potential degraded performance after reconnection. + +The other problem is that When negotiating read and write sizes, there are +cases where the negotiated values might calculate to zero, especially +during reconnection when server->max_read or server->max_write might be +reset. In general, these values come from the negotiation response. +According to MS-SMB2 specification, these values should be at least 65536 +bytes. + +This patch improves IO parameter handling: + +1. Adds vol_rsize and vol_wsize fields to store the original user-specified + values separately from the negotiated values +2. Uses got_rsize/got_wsize flags to determine if values were + user-specified rather than checking for non-zero values, which is more + reliable +3. Adds a prevent_zero_iosize() helper function to ensure IO sizes are + never negotiated down to zero, which could happen in edge cases like + when server->max_read/write is zero + +The changes make the CIFS client more resilient to unusual server +responses and reconnection scenarios, preventing potential failures +when IO sizes are calculated to be zero. + +Signed-off-by: Wang Zhaolong +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/fs_context.c | 2 ++ + fs/smb/client/fs_context.h | 3 +++ + fs/smb/client/smb1ops.c | 6 +++--- + fs/smb/client/smb2ops.c | 27 +++++++++++++++++++-------- + fs/smb/common/smb2pdu.h | 3 +++ + 5 files changed, 30 insertions(+), 11 deletions(-) + +diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c +index 69cca4f17dbaa..b015a4f997cb6 100644 +--- a/fs/smb/client/fs_context.c ++++ b/fs/smb/client/fs_context.c +@@ -1267,6 +1267,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, + case Opt_rsize: + ctx->rsize = result.uint_32; + ctx->got_rsize = true; ++ ctx->vol_rsize = ctx->rsize; + break; + case Opt_wsize: + ctx->wsize = result.uint_32; +@@ -1282,6 +1283,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, + ctx->wsize, PAGE_SIZE); + } + } ++ ctx->vol_wsize = ctx->wsize; + break; + case Opt_acregmax: + if (result.uint_32 > CIFS_MAX_ACTIMEO / HZ) { +diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h +index ac6baa774ad3a..c7e00025518f7 100644 +--- a/fs/smb/client/fs_context.h ++++ b/fs/smb/client/fs_context.h +@@ -263,6 +263,9 @@ struct smb3_fs_context { + bool use_client_guid:1; + /* reuse existing guid for multichannel */ + u8 client_guid[SMB2_CLIENT_GUID_SIZE]; ++ /* User-specified original r/wsize value */ ++ unsigned int vol_rsize; ++ unsigned int vol_wsize; + unsigned int bsize; + unsigned int rasize; + unsigned int rsize; +diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c +index a2dbebd13720b..71fe5aa52630d 100644 +--- a/fs/smb/client/smb1ops.c ++++ b/fs/smb/client/smb1ops.c +@@ -437,8 +437,8 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) + unsigned int wsize; + + /* start with specified wsize, or default */ +- if (ctx->wsize) +- wsize = ctx->wsize; ++ if (ctx->got_wsize) ++ wsize = ctx->vol_wsize; + else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) + wsize = CIFS_DEFAULT_IOSIZE; + else +@@ -490,7 +490,7 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) + else + defsize = server->maxBuf - sizeof(READ_RSP); + +- rsize = ctx->rsize ? ctx->rsize : defsize; ++ rsize = ctx->got_rsize ? ctx->vol_rsize : defsize; + + /* + * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to +diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c +index ff50cdfde5fe4..74bcc51ccd32f 100644 +--- a/fs/smb/client/smb2ops.c ++++ b/fs/smb/client/smb2ops.c +@@ -467,6 +467,17 @@ smb2_negotiate(const unsigned int xid, + return rc; + } + ++static inline unsigned int ++prevent_zero_iosize(unsigned int size, const char *type) ++{ ++ if (size == 0) { ++ cifs_dbg(VFS, "SMB: Zero %ssize calculated, using minimum value %u\n", ++ type, CIFS_MIN_DEFAULT_IOSIZE); ++ return CIFS_MIN_DEFAULT_IOSIZE; ++ } ++ return size; ++} ++ + static unsigned int + smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) + { +@@ -474,12 +485,12 @@ smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) + unsigned int wsize; + + /* start with specified wsize, or default */ +- wsize = ctx->wsize ? ctx->wsize : CIFS_DEFAULT_IOSIZE; ++ wsize = ctx->got_wsize ? ctx->vol_wsize : CIFS_DEFAULT_IOSIZE; + wsize = min_t(unsigned int, wsize, server->max_write); + if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) + wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE); + +- return wsize; ++ return prevent_zero_iosize(wsize, "w"); + } + + static unsigned int +@@ -489,7 +500,7 @@ smb3_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) + unsigned int wsize; + + /* start with specified wsize, or default */ +- wsize = ctx->wsize ? ctx->wsize : SMB3_DEFAULT_IOSIZE; ++ wsize = ctx->got_wsize ? ctx->vol_wsize : SMB3_DEFAULT_IOSIZE; + wsize = min_t(unsigned int, wsize, server->max_write); + #ifdef CONFIG_CIFS_SMB_DIRECT + if (server->rdma) { +@@ -511,7 +522,7 @@ smb3_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) + if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) + wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE); + +- return wsize; ++ return prevent_zero_iosize(wsize, "w"); + } + + static unsigned int +@@ -521,13 +532,13 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) + unsigned int rsize; + + /* start with specified rsize, or default */ +- rsize = ctx->rsize ? ctx->rsize : CIFS_DEFAULT_IOSIZE; ++ rsize = ctx->got_rsize ? ctx->vol_rsize : CIFS_DEFAULT_IOSIZE; + rsize = min_t(unsigned int, rsize, server->max_read); + + if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) + rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE); + +- return rsize; ++ return prevent_zero_iosize(rsize, "r"); + } + + static unsigned int +@@ -537,7 +548,7 @@ smb3_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) + unsigned int rsize; + + /* start with specified rsize, or default */ +- rsize = ctx->rsize ? ctx->rsize : SMB3_DEFAULT_IOSIZE; ++ rsize = ctx->got_rsize ? ctx->vol_rsize : SMB3_DEFAULT_IOSIZE; + rsize = min_t(unsigned int, rsize, server->max_read); + #ifdef CONFIG_CIFS_SMB_DIRECT + if (server->rdma) { +@@ -560,7 +571,7 @@ smb3_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) + if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) + rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE); + +- return rsize; ++ return prevent_zero_iosize(rsize, "r"); + } + + /* +diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h +index 9f272cc8f5660..0a4ca286f4169 100644 +--- a/fs/smb/common/smb2pdu.h ++++ b/fs/smb/common/smb2pdu.h +@@ -95,6 +95,9 @@ + */ + #define SMB3_DEFAULT_IOSIZE (4 * 1024 * 1024) + ++/* According to MS-SMB2 specification The minimum recommended value is 65536.*/ ++#define CIFS_MIN_DEFAULT_IOSIZE (65536) ++ + /* + * SMB2 Header Definition + * +-- +2.39.5 + diff --git a/queue-6.12/smb-server-smb2pdu-check-return-value-of-xa_store.patch b/queue-6.12/smb-server-smb2pdu-check-return-value-of-xa_store.patch new file mode 100644 index 0000000000..85205037e9 --- /dev/null +++ b/queue-6.12/smb-server-smb2pdu-check-return-value-of-xa_store.patch @@ -0,0 +1,50 @@ +From d0632d61a123846a420317c981d207a673188115 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Apr 2025 20:26:25 +0100 +Subject: smb: server: smb2pdu: check return value of xa_store() + +From: Salah Triki + +[ Upstream commit af5226abb40cae959f424f7ca614787a1c87ce48 ] + +xa_store() may fail so check its return value and return error code if +error occurred. + +Signed-off-by: Salah Triki +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/smb2pdu.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c +index f0760d786502f..08d9a7cfba8cd 100644 +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -1448,7 +1448,7 @@ static int ntlm_authenticate(struct ksmbd_work *work, + { + struct ksmbd_conn *conn = work->conn; + struct ksmbd_session *sess = work->sess; +- struct channel *chann = NULL; ++ struct channel *chann = NULL, *old; + struct ksmbd_user *user; + u64 prev_id; + int sz, rc; +@@ -1560,7 +1560,12 @@ static int ntlm_authenticate(struct ksmbd_work *work, + return -ENOMEM; + + chann->conn = conn; +- xa_store(&sess->ksmbd_chann_list, (long)conn, chann, KSMBD_DEFAULT_GFP); ++ old = xa_store(&sess->ksmbd_chann_list, (long)conn, chann, ++ KSMBD_DEFAULT_GFP); ++ if (xa_is_err(old)) { ++ kfree(chann); ++ return xa_err(old); ++ } + } + } + +-- +2.39.5 + diff --git a/queue-6.12/soc-apple-rtkit-implement-oslog-buffers-properly.patch b/queue-6.12/soc-apple-rtkit-implement-oslog-buffers-properly.patch new file mode 100644 index 0000000000..189c3f49bd --- /dev/null +++ b/queue-6.12/soc-apple-rtkit-implement-oslog-buffers-properly.patch @@ -0,0 +1,156 @@ +From 5139f7cff4f7444a914fb671bc076374d4bd2328 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 19:00:04 +0000 +Subject: soc: apple: rtkit: Implement OSLog buffers properly + +From: Hector Martin + +[ Upstream commit a06398687065e0c334dc5fc4d2778b5b87292e43 ] + +Apparently nobody can figure out where the old logic came from, but it +seems like it has never been actually used on any supported firmware to +this day. OSLog buffers were apparently never requested. + +But starting with 13.3, we actually need this implemented properly for +MTP (and later AOP) to work, so let's actually do that. + +Signed-off-by: Hector Martin +Reviewed-by: Alyssa Rosenzweig +Link: https://lore.kernel.org/r/20250226-apple-soc-misc-v2-2-c3ec37f9021b@svenpeter.dev +Signed-off-by: Sven Peter +Signed-off-by: Sasha Levin +--- + drivers/soc/apple/rtkit-internal.h | 1 + + drivers/soc/apple/rtkit.c | 56 ++++++++++++++++++------------ + 2 files changed, 35 insertions(+), 22 deletions(-) + +diff --git a/drivers/soc/apple/rtkit-internal.h b/drivers/soc/apple/rtkit-internal.h +index 27c9fa745fd52..b8d5244678f01 100644 +--- a/drivers/soc/apple/rtkit-internal.h ++++ b/drivers/soc/apple/rtkit-internal.h +@@ -44,6 +44,7 @@ struct apple_rtkit { + + struct apple_rtkit_shmem ioreport_buffer; + struct apple_rtkit_shmem crashlog_buffer; ++ struct apple_rtkit_shmem oslog_buffer; + + struct apple_rtkit_shmem syslog_buffer; + char *syslog_msg_buffer; +diff --git a/drivers/soc/apple/rtkit.c b/drivers/soc/apple/rtkit.c +index 00d59a81db88b..45ccbe2cbcd63 100644 +--- a/drivers/soc/apple/rtkit.c ++++ b/drivers/soc/apple/rtkit.c +@@ -66,8 +66,9 @@ enum { + #define APPLE_RTKIT_SYSLOG_MSG_SIZE GENMASK_ULL(31, 24) + + #define APPLE_RTKIT_OSLOG_TYPE GENMASK_ULL(63, 56) +-#define APPLE_RTKIT_OSLOG_INIT 1 +-#define APPLE_RTKIT_OSLOG_ACK 3 ++#define APPLE_RTKIT_OSLOG_BUFFER_REQUEST 1 ++#define APPLE_RTKIT_OSLOG_SIZE GENMASK_ULL(55, 36) ++#define APPLE_RTKIT_OSLOG_IOVA GENMASK_ULL(35, 0) + + #define APPLE_RTKIT_MIN_SUPPORTED_VERSION 11 + #define APPLE_RTKIT_MAX_SUPPORTED_VERSION 12 +@@ -251,15 +252,21 @@ static int apple_rtkit_common_rx_get_buffer(struct apple_rtkit *rtk, + struct apple_rtkit_shmem *buffer, + u8 ep, u64 msg) + { +- size_t n_4kpages = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_SIZE, msg); + u64 reply; + int err; + ++ /* The different size vs. IOVA shifts look odd but are indeed correct this way */ ++ if (ep == APPLE_RTKIT_EP_OSLOG) { ++ buffer->size = FIELD_GET(APPLE_RTKIT_OSLOG_SIZE, msg); ++ buffer->iova = FIELD_GET(APPLE_RTKIT_OSLOG_IOVA, msg) << 12; ++ } else { ++ buffer->size = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_SIZE, msg) << 12; ++ buffer->iova = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_IOVA, msg); ++ } ++ + buffer->buffer = NULL; + buffer->iomem = NULL; + buffer->is_mapped = false; +- buffer->iova = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_IOVA, msg); +- buffer->size = n_4kpages << 12; + + dev_dbg(rtk->dev, "RTKit: buffer request for 0x%zx bytes at %pad\n", + buffer->size, &buffer->iova); +@@ -284,11 +291,21 @@ static int apple_rtkit_common_rx_get_buffer(struct apple_rtkit *rtk, + } + + if (!buffer->is_mapped) { +- reply = FIELD_PREP(APPLE_RTKIT_SYSLOG_TYPE, +- APPLE_RTKIT_BUFFER_REQUEST); +- reply |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_SIZE, n_4kpages); +- reply |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_IOVA, +- buffer->iova); ++ /* oslog uses different fields and needs a shifted IOVA instead of size */ ++ if (ep == APPLE_RTKIT_EP_OSLOG) { ++ reply = FIELD_PREP(APPLE_RTKIT_OSLOG_TYPE, ++ APPLE_RTKIT_OSLOG_BUFFER_REQUEST); ++ reply |= FIELD_PREP(APPLE_RTKIT_OSLOG_SIZE, buffer->size); ++ reply |= FIELD_PREP(APPLE_RTKIT_OSLOG_IOVA, ++ buffer->iova >> 12); ++ } else { ++ reply = FIELD_PREP(APPLE_RTKIT_SYSLOG_TYPE, ++ APPLE_RTKIT_BUFFER_REQUEST); ++ reply |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_SIZE, ++ buffer->size >> 12); ++ reply |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_IOVA, ++ buffer->iova); ++ } + apple_rtkit_send_message(rtk, ep, reply, NULL, false); + } + +@@ -482,25 +499,18 @@ static void apple_rtkit_syslog_rx(struct apple_rtkit *rtk, u64 msg) + } + } + +-static void apple_rtkit_oslog_rx_init(struct apple_rtkit *rtk, u64 msg) +-{ +- u64 ack; +- +- dev_dbg(rtk->dev, "RTKit: oslog init: msg: 0x%llx\n", msg); +- ack = FIELD_PREP(APPLE_RTKIT_OSLOG_TYPE, APPLE_RTKIT_OSLOG_ACK); +- apple_rtkit_send_message(rtk, APPLE_RTKIT_EP_OSLOG, ack, NULL, false); +-} +- + static void apple_rtkit_oslog_rx(struct apple_rtkit *rtk, u64 msg) + { + u8 type = FIELD_GET(APPLE_RTKIT_OSLOG_TYPE, msg); + + switch (type) { +- case APPLE_RTKIT_OSLOG_INIT: +- apple_rtkit_oslog_rx_init(rtk, msg); ++ case APPLE_RTKIT_OSLOG_BUFFER_REQUEST: ++ apple_rtkit_common_rx_get_buffer(rtk, &rtk->oslog_buffer, ++ APPLE_RTKIT_EP_OSLOG, msg); + break; + default: +- dev_warn(rtk->dev, "RTKit: Unknown oslog message: %llx\n", msg); ++ dev_warn(rtk->dev, "RTKit: Unknown oslog message: %llx\n", ++ msg); + } + } + +@@ -710,6 +720,7 @@ int apple_rtkit_reinit(struct apple_rtkit *rtk) + + apple_rtkit_free_buffer(rtk, &rtk->ioreport_buffer); + apple_rtkit_free_buffer(rtk, &rtk->crashlog_buffer); ++ apple_rtkit_free_buffer(rtk, &rtk->oslog_buffer); + apple_rtkit_free_buffer(rtk, &rtk->syslog_buffer); + + kfree(rtk->syslog_msg_buffer); +@@ -890,6 +901,7 @@ void apple_rtkit_free(struct apple_rtkit *rtk) + + apple_rtkit_free_buffer(rtk, &rtk->ioreport_buffer); + apple_rtkit_free_buffer(rtk, &rtk->crashlog_buffer); ++ apple_rtkit_free_buffer(rtk, &rtk->oslog_buffer); + apple_rtkit_free_buffer(rtk, &rtk->syslog_buffer); + + kfree(rtk->syslog_msg_buffer); +-- +2.39.5 + diff --git a/queue-6.12/soc-apple-rtkit-use-high-prio-work-queue.patch b/queue-6.12/soc-apple-rtkit-use-high-prio-work-queue.patch new file mode 100644 index 0000000000..39e079ca30 --- /dev/null +++ b/queue-6.12/soc-apple-rtkit-use-high-prio-work-queue.patch @@ -0,0 +1,42 @@ +From 06f4bb55662aac15f78ebfe199ac47a671881708 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 19:00:05 +0000 +Subject: soc: apple: rtkit: Use high prio work queue + +From: Janne Grunau + +[ Upstream commit 22af2fac88fa5dbc310bfe7d0b66d4de3ac47305 ] + +rtkit messages as communication with the DCP firmware for framebuffer +swaps or input events are time critical so use WQ_HIGHPRI to prevent +user space CPU load to increase latency. +With kwin_wayland 6's explicit sync mode user space load was able to +delay the IOMFB rtkit communication enough to miss vsync for surface +swaps. Minimal test scenario is constantly resizing a glxgears +Xwayland window. + +Signed-off-by: Janne Grunau +Reviewed-by: Alyssa Rosenzweig +Link: https://lore.kernel.org/r/20250226-apple-soc-misc-v2-3-c3ec37f9021b@svenpeter.dev +Signed-off-by: Sven Peter +Signed-off-by: Sasha Levin +--- + drivers/soc/apple/rtkit.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/soc/apple/rtkit.c b/drivers/soc/apple/rtkit.c +index e6d940292c9fb..00d59a81db88b 100644 +--- a/drivers/soc/apple/rtkit.c ++++ b/drivers/soc/apple/rtkit.c +@@ -667,7 +667,7 @@ struct apple_rtkit *apple_rtkit_init(struct device *dev, void *cookie, + rtk->mbox->rx = apple_rtkit_rx; + rtk->mbox->cookie = rtk; + +- rtk->wq = alloc_ordered_workqueue("rtkit-%s", WQ_MEM_RECLAIM, ++ rtk->wq = alloc_ordered_workqueue("rtkit-%s", WQ_HIGHPRI | WQ_MEM_RECLAIM, + dev_name(rtk->dev)); + if (!rtk->wq) { + ret = -ENOMEM; +-- +2.39.5 + diff --git a/queue-6.12/soc-mediatek-mtk-mutex-add-dpi1-sof-eof-to-mt8188-mu.patch b/queue-6.12/soc-mediatek-mtk-mutex-add-dpi1-sof-eof-to-mt8188-mu.patch new file mode 100644 index 0000000000..8eb61e802e --- /dev/null +++ b/queue-6.12/soc-mediatek-mtk-mutex-add-dpi1-sof-eof-to-mt8188-mu.patch @@ -0,0 +1,69 @@ +From 24b4b52aa2a2e39a57c9c9e12f1b455cd5dd14f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 11:00:05 +0100 +Subject: soc: mediatek: mtk-mutex: Add DPI1 SOF/EOF to MT8188 mutex tables + +From: AngeloGioacchino Del Regno + +[ Upstream commit 694e0b7c1747603243da874de9cbbf8cb806ca44 ] + +MT8188 uses DPI1 to output to the HDMI controller: add the +Start of Frame and End of Frame configuration for the DPI1 +IP to the tables to unblock generation and sending of these +signals to the GCE. + +Link: https://lore.kernel.org/r/20250212100012.33001-2-angelogioacchino.delregno@collabora.com +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + drivers/soc/mediatek/mtk-mutex.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c +index 5250c1d702eb9..aaa965d4b050a 100644 +--- a/drivers/soc/mediatek/mtk-mutex.c ++++ b/drivers/soc/mediatek/mtk-mutex.c +@@ -155,6 +155,7 @@ + #define MT8188_MUTEX_MOD_DISP1_VPP_MERGE3 23 + #define MT8188_MUTEX_MOD_DISP1_VPP_MERGE4 24 + #define MT8188_MUTEX_MOD_DISP1_DISP_MIXER 30 ++#define MT8188_MUTEX_MOD_DISP1_DPI1 38 + #define MT8188_MUTEX_MOD_DISP1_DP_INTF1 39 + + #define MT8195_MUTEX_MOD_DISP_OVL0 0 +@@ -289,6 +290,7 @@ + #define MT8188_MUTEX_SOF_DSI0 1 + #define MT8188_MUTEX_SOF_DP_INTF0 3 + #define MT8188_MUTEX_SOF_DP_INTF1 4 ++#define MT8188_MUTEX_SOF_DPI1 5 + #define MT8195_MUTEX_SOF_DSI0 1 + #define MT8195_MUTEX_SOF_DSI1 2 + #define MT8195_MUTEX_SOF_DP_INTF0 3 +@@ -301,6 +303,7 @@ + #define MT8188_MUTEX_EOF_DSI0 (MT8188_MUTEX_SOF_DSI0 << 7) + #define MT8188_MUTEX_EOF_DP_INTF0 (MT8188_MUTEX_SOF_DP_INTF0 << 7) + #define MT8188_MUTEX_EOF_DP_INTF1 (MT8188_MUTEX_SOF_DP_INTF1 << 7) ++#define MT8188_MUTEX_EOF_DPI1 (MT8188_MUTEX_SOF_DPI1 << 7) + #define MT8195_MUTEX_EOF_DSI0 (MT8195_MUTEX_SOF_DSI0 << 7) + #define MT8195_MUTEX_EOF_DSI1 (MT8195_MUTEX_SOF_DSI1 << 7) + #define MT8195_MUTEX_EOF_DP_INTF0 (MT8195_MUTEX_SOF_DP_INTF0 << 7) +@@ -472,6 +475,7 @@ static const u8 mt8188_mutex_mod[DDP_COMPONENT_ID_MAX] = { + [DDP_COMPONENT_PWM0] = MT8188_MUTEX_MOD2_DISP_PWM0, + [DDP_COMPONENT_DP_INTF0] = MT8188_MUTEX_MOD_DISP_DP_INTF0, + [DDP_COMPONENT_DP_INTF1] = MT8188_MUTEX_MOD_DISP1_DP_INTF1, ++ [DDP_COMPONENT_DPI1] = MT8188_MUTEX_MOD_DISP1_DPI1, + [DDP_COMPONENT_ETHDR_MIXER] = MT8188_MUTEX_MOD_DISP1_DISP_MIXER, + [DDP_COMPONENT_MDP_RDMA0] = MT8188_MUTEX_MOD_DISP1_MDP_RDMA0, + [DDP_COMPONENT_MDP_RDMA1] = MT8188_MUTEX_MOD_DISP1_MDP_RDMA1, +@@ -686,6 +690,8 @@ static const u16 mt8188_mutex_sof[DDP_MUTEX_SOF_MAX] = { + [MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE, + [MUTEX_SOF_DSI0] = + MT8188_MUTEX_SOF_DSI0 | MT8188_MUTEX_EOF_DSI0, ++ [MUTEX_SOF_DPI1] = ++ MT8188_MUTEX_SOF_DPI1 | MT8188_MUTEX_EOF_DPI1, + [MUTEX_SOF_DP_INTF0] = + MT8188_MUTEX_SOF_DP_INTF0 | MT8188_MUTEX_EOF_DP_INTF0, + [MUTEX_SOF_DP_INTF1] = +-- +2.39.5 + diff --git a/queue-6.12/soc-samsung-include-linux-array_size.h-where-needed.patch b/queue-6.12/soc-samsung-include-linux-array_size.h-where-needed.patch new file mode 100644 index 0000000000..c4a8f6793d --- /dev/null +++ b/queue-6.12/soc-samsung-include-linux-array_size.h-where-needed.patch @@ -0,0 +1,119 @@ +From 3d24971a7f3821813f5d462943422e3cf8279ed8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 22:14:02 +0100 +Subject: soc: samsung: include linux/array_size.h where needed + +From: Arnd Bergmann + +[ Upstream commit 4c57930f68d90e0d52c396d058cfa9ed8447a6c4 ] + +This does not necessarily get included through asm/io.h: + +drivers/soc/samsung/exynos3250-pmu.c:120:18: error: use of undeclared identifier 'ARRAY_SIZE' + 120 | for (i = 0; i < ARRAY_SIZE(exynos3250_list_feed); i++) { + | ^ +drivers/soc/samsung/exynos5250-pmu.c:162:18: error: use of undeclared identifier 'ARRAY_SIZE' + 162 | for (i = 0; i < ARRAY_SIZE(exynos5_list_both_cnt_feed); i++) { + | ^ + +Signed-off-by: Arnd Bergmann +Link: https://lore.kernel.org/r/20250305211446.43772-1-arnd@kernel.org +Signed-off-by: Krzysztof Kozlowski +Signed-off-by: Sasha Levin +--- + drivers/soc/samsung/exynos-asv.c | 1 + + drivers/soc/samsung/exynos-chipid.c | 1 + + drivers/soc/samsung/exynos-pmu.c | 1 + + drivers/soc/samsung/exynos-usi.c | 1 + + drivers/soc/samsung/exynos3250-pmu.c | 1 + + drivers/soc/samsung/exynos5250-pmu.c | 1 + + drivers/soc/samsung/exynos5420-pmu.c | 1 + + 7 files changed, 7 insertions(+) + +diff --git a/drivers/soc/samsung/exynos-asv.c b/drivers/soc/samsung/exynos-asv.c +index 97006cc3b9461..8e681f5195264 100644 +--- a/drivers/soc/samsung/exynos-asv.c ++++ b/drivers/soc/samsung/exynos-asv.c +@@ -9,6 +9,7 @@ + * Samsung Exynos SoC Adaptive Supply Voltage support + */ + ++#include + #include + #include + #include +diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c +index bba8d86ae1bb0..dedfe6d0fb3f3 100644 +--- a/drivers/soc/samsung/exynos-chipid.c ++++ b/drivers/soc/samsung/exynos-chipid.c +@@ -12,6 +12,7 @@ + * Samsung Exynos SoC Adaptive Supply Voltage and Chip ID support + */ + ++#include + #include + #include + #include +diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c +index dd5256e5aae1a..c40313886a012 100644 +--- a/drivers/soc/samsung/exynos-pmu.c ++++ b/drivers/soc/samsung/exynos-pmu.c +@@ -5,6 +5,7 @@ + // + // Exynos - CPU PMU(Power Management Unit) support + ++#include + #include + #include + #include +diff --git a/drivers/soc/samsung/exynos-usi.c b/drivers/soc/samsung/exynos-usi.c +index 114352695ac2b..5a93a68dba87f 100644 +--- a/drivers/soc/samsung/exynos-usi.c ++++ b/drivers/soc/samsung/exynos-usi.c +@@ -6,6 +6,7 @@ + * Samsung Exynos USI driver (Universal Serial Interface). + */ + ++#include + #include + #include + #include +diff --git a/drivers/soc/samsung/exynos3250-pmu.c b/drivers/soc/samsung/exynos3250-pmu.c +index 30f230ed1769c..4bad12a995422 100644 +--- a/drivers/soc/samsung/exynos3250-pmu.c ++++ b/drivers/soc/samsung/exynos3250-pmu.c +@@ -5,6 +5,7 @@ + // + // Exynos3250 - CPU PMU (Power Management Unit) support + ++#include + #include + #include + +diff --git a/drivers/soc/samsung/exynos5250-pmu.c b/drivers/soc/samsung/exynos5250-pmu.c +index 7a2d50be6b4ac..2ae5c3e1b07a3 100644 +--- a/drivers/soc/samsung/exynos5250-pmu.c ++++ b/drivers/soc/samsung/exynos5250-pmu.c +@@ -5,6 +5,7 @@ + // + // Exynos5250 - CPU PMU (Power Management Unit) support + ++#include + #include + #include + +diff --git a/drivers/soc/samsung/exynos5420-pmu.c b/drivers/soc/samsung/exynos5420-pmu.c +index 6fedcd78cb451..58a2209795f78 100644 +--- a/drivers/soc/samsung/exynos5420-pmu.c ++++ b/drivers/soc/samsung/exynos5420-pmu.c +@@ -5,6 +5,7 @@ + // + // Exynos5420 - CPU PMU (Power Management Unit) support + ++#include + #include + #include + #include +-- +2.39.5 + diff --git a/queue-6.12/soc-ti-k3-socinfo-do-not-use-syscon-helper-to-build-.patch b/queue-6.12/soc-ti-k3-socinfo-do-not-use-syscon-helper-to-build-.patch new file mode 100644 index 0000000000..260cfb198a --- /dev/null +++ b/queue-6.12/soc-ti-k3-socinfo-do-not-use-syscon-helper-to-build-.patch @@ -0,0 +1,68 @@ +From 1c8b298976d56424d8f8ed0cb2d2b21f9136240c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 12:17:26 -0600 +Subject: soc: ti: k3-socinfo: Do not use syscon helper to build regmap + +From: Andrew Davis + +[ Upstream commit a5caf03188e44388e8c618dcbe5fffad1a249385 ] + +The syscon helper device_node_to_regmap() is used to fetch a regmap +registered to a device node. It also currently creates this regmap +if the node did not already have a regmap associated with it. This +should only be used on "syscon" nodes. This driver is not such a +device and instead uses device_node_to_regmap() on its own node as +a hacky way to create a regmap for itself. + +This will not work going forward and so we should create our regmap +the normal way by defining our regmap_config, fetching our memory +resource, then using the normal regmap_init_mmio() function. + +Signed-off-by: Andrew Davis +Link: https://lore.kernel.org/r/20250123181726.597144-1-afd@ti.com +Signed-off-by: Nishanth Menon +Signed-off-by: Sasha Levin +--- + drivers/soc/ti/k3-socinfo.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/soc/ti/k3-socinfo.c b/drivers/soc/ti/k3-socinfo.c +index 4fb0f0a248288..704039eb3c078 100644 +--- a/drivers/soc/ti/k3-socinfo.c ++++ b/drivers/soc/ti/k3-socinfo.c +@@ -105,6 +105,12 @@ k3_chipinfo_variant_to_sr(unsigned int partno, unsigned int variant, + return -ENODEV; + } + ++static const struct regmap_config k3_chipinfo_regmap_cfg = { ++ .reg_bits = 32, ++ .val_bits = 32, ++ .reg_stride = 4, ++}; ++ + static int k3_chipinfo_probe(struct platform_device *pdev) + { + struct device_node *node = pdev->dev.of_node; +@@ -112,13 +118,18 @@ static int k3_chipinfo_probe(struct platform_device *pdev) + struct device *dev = &pdev->dev; + struct soc_device *soc_dev; + struct regmap *regmap; ++ void __iomem *base; + u32 partno_id; + u32 variant; + u32 jtag_id; + u32 mfg; + int ret; + +- regmap = device_node_to_regmap(node); ++ base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ regmap = regmap_init_mmio(dev, base, &k3_chipinfo_regmap_cfg); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + +-- +2.39.5 + diff --git a/queue-6.12/soundwire-amd-change-the-soundwire-wake-enable-disab.patch b/queue-6.12/soundwire-amd-change-the-soundwire-wake-enable-disab.patch new file mode 100644 index 0000000000..6182513cb9 --- /dev/null +++ b/queue-6.12/soundwire-amd-change-the-soundwire-wake-enable-disab.patch @@ -0,0 +1,46 @@ +From 1e61312314a45c69ece240ab1d0b4e472fe3b9e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 12:28:36 +0530 +Subject: soundwire: amd: change the soundwire wake enable/disable sequence + +From: Vijendar Mukunda + +[ Upstream commit dcc48a73eae7f791b1a6856ea1bcc4079282c88d ] + +During runtime suspend scenario, SoundWire wake should be enabled and +during system level suspend scenario SoundWire wake should be disabled. + +Implement the SoundWire wake enable/disable sequence as per design flow +for SoundWire poweroff mode. + +Signed-off-by: Vijendar Mukunda +Link: https://lore.kernel.org/r/20250207065841.4718-2-Vijendar.Mukunda@amd.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/soundwire/amd_manager.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/soundwire/amd_manager.c b/drivers/soundwire/amd_manager.c +index 0d01849c35861..e3d5e6c1d582c 100644 +--- a/drivers/soundwire/amd_manager.c ++++ b/drivers/soundwire/amd_manager.c +@@ -1110,6 +1110,7 @@ static int __maybe_unused amd_suspend(struct device *dev) + amd_sdw_wake_enable(amd_manager, false); + return amd_sdw_clock_stop(amd_manager); + } else if (amd_manager->power_mode_mask & AMD_SDW_POWER_OFF_MODE) { ++ amd_sdw_wake_enable(amd_manager, false); + /* + * As per hardware programming sequence on AMD platforms, + * clock stop should be invoked first before powering-off +@@ -1137,6 +1138,7 @@ static int __maybe_unused amd_suspend_runtime(struct device *dev) + amd_sdw_wake_enable(amd_manager, true); + return amd_sdw_clock_stop(amd_manager); + } else if (amd_manager->power_mode_mask & AMD_SDW_POWER_OFF_MODE) { ++ amd_sdw_wake_enable(amd_manager, true); + ret = amd_sdw_clock_stop(amd_manager); + if (ret) + return ret; +-- +2.39.5 + diff --git a/queue-6.12/soundwire-cadence_master-set-frame-shape-and-divider.patch b/queue-6.12/soundwire-cadence_master-set-frame-shape-and-divider.patch new file mode 100644 index 0000000000..a492eb2e63 --- /dev/null +++ b/queue-6.12/soundwire-cadence_master-set-frame-shape-and-divider.patch @@ -0,0 +1,95 @@ +From 1a489af338c6d57bfa7bb5ed5628da4ac89654d5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 15:42:31 +0800 +Subject: soundwire: cadence_master: set frame shape and divider based on + actual clk freq +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Bard Liao + +[ Upstream commit e738d77f78b3ac085dfb51be414e93464abba7ec ] + +Frame shape and curr_dr_freq could be updated by sdw_compute_bus_params(). +Peripherals will set curr_dr_freq as their frequency. Managers +should do the same. Then update frame shape according to the actual +bus frequency. + +Signed-off-by: Bard Liao +Reviewed-by: Ranjani Sridharan +Reviewed-by: Péter Ujfalusi +Reviewed-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20250205074232.87537-2-yung-chuan.liao@linux.intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/soundwire/cadence_master.c | 22 +++++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c +index 05652e983539b..6f2b5ec5c87c6 100644 +--- a/drivers/soundwire/cadence_master.c ++++ b/drivers/soundwire/cadence_master.c +@@ -1341,7 +1341,7 @@ static u32 cdns_set_initial_frame_shape(int n_rows, int n_cols) + return val; + } + +-static void cdns_init_clock_ctrl(struct sdw_cdns *cdns) ++static int cdns_init_clock_ctrl(struct sdw_cdns *cdns) + { + struct sdw_bus *bus = &cdns->bus; + struct sdw_master_prop *prop = &bus->prop; +@@ -1355,14 +1355,25 @@ static void cdns_init_clock_ctrl(struct sdw_cdns *cdns) + prop->default_row, + prop->default_col); + ++ if (!prop->default_frame_rate || !prop->default_row) { ++ dev_err(cdns->dev, "Default frame_rate %d or row %d is invalid\n", ++ prop->default_frame_rate, prop->default_row); ++ return -EINVAL; ++ } ++ + /* Set clock divider */ +- divider = (prop->mclk_freq / prop->max_clk_freq) - 1; ++ divider = (prop->mclk_freq * SDW_DOUBLE_RATE_FACTOR / ++ bus->params.curr_dr_freq) - 1; + + cdns_updatel(cdns, CDNS_MCP_CLK_CTRL0, + CDNS_MCP_CLK_MCLKD_MASK, divider); + cdns_updatel(cdns, CDNS_MCP_CLK_CTRL1, + CDNS_MCP_CLK_MCLKD_MASK, divider); + ++ /* Set frame shape base on the actual bus frequency. */ ++ prop->default_col = bus->params.curr_dr_freq / ++ prop->default_frame_rate / prop->default_row; ++ + /* + * Frame shape changes after initialization have to be done + * with the bank switch mechanism +@@ -1375,6 +1386,8 @@ static void cdns_init_clock_ctrl(struct sdw_cdns *cdns) + ssp_interval = prop->default_frame_rate / SDW_CADENCE_GSYNC_HZ; + cdns_writel(cdns, CDNS_MCP_SSP_CTRL0, ssp_interval); + cdns_writel(cdns, CDNS_MCP_SSP_CTRL1, ssp_interval); ++ ++ return 0; + } + + /** +@@ -1383,9 +1396,12 @@ static void cdns_init_clock_ctrl(struct sdw_cdns *cdns) + */ + int sdw_cdns_init(struct sdw_cdns *cdns) + { ++ int ret; + u32 val; + +- cdns_init_clock_ctrl(cdns); ++ ret = cdns_init_clock_ctrl(cdns); ++ if (ret) ++ return ret; + + sdw_cdns_check_self_clearing_bits(cdns, __func__, false, 0); + +-- +2.39.5 + diff --git a/queue-6.12/spi-rockchip-fix-register-out-of-bounds-access.patch b/queue-6.12/spi-rockchip-fix-register-out-of-bounds-access.patch new file mode 100644 index 0000000000..9961ad27d4 --- /dev/null +++ b/queue-6.12/spi-rockchip-fix-register-out-of-bounds-access.patch @@ -0,0 +1,37 @@ +From a45f064a93e437c9911c653c95eb2960958cc3e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 13:57:53 +0100 +Subject: spi-rockchip: Fix register out of bounds access + +From: Luis de Arquer + +[ Upstream commit 7a874e8b54ea21094f7fd2d428b164394c6cb316 ] + +Do not write native chip select stuff for GPIO chip selects. +GPIOs can be numbered much higher than native CS. +Also, it makes no sense. + +Signed-off-by: Luis de Arquer +Link: https://patch.msgid.link/365ccddfba110549202b3520f4401a6a936e82a8.camel@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-rockchip.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c +index 40a64a598a749..5008489d6fac8 100644 +--- a/drivers/spi/spi-rockchip.c ++++ b/drivers/spi/spi-rockchip.c +@@ -547,7 +547,7 @@ static int rockchip_spi_config(struct rockchip_spi *rs, + cr0 |= (spi->mode & 0x3U) << CR0_SCPH_OFFSET; + if (spi->mode & SPI_LSB_FIRST) + cr0 |= CR0_FBM_LSB << CR0_FBM_OFFSET; +- if (spi->mode & SPI_CS_HIGH) ++ if ((spi->mode & SPI_CS_HIGH) && !(spi_get_csgpiod(spi, 0))) + cr0 |= BIT(spi_get_chipselect(spi, 0)) << CR0_SOI_OFFSET; + + if (xfer->rx_buf && xfer->tx_buf) +-- +2.39.5 + diff --git a/queue-6.12/spi-spi-mux-fix-coverity-issue-unchecked-return-valu.patch b/queue-6.12/spi-spi-mux-fix-coverity-issue-unchecked-return-valu.patch new file mode 100644 index 0000000000..f380e4c64a --- /dev/null +++ b/queue-6.12/spi-spi-mux-fix-coverity-issue-unchecked-return-valu.patch @@ -0,0 +1,40 @@ +From 58654f04f132cc05806837505578503aa9380244 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Mar 2025 23:46:06 -0600 +Subject: spi: spi-mux: Fix coverity issue, unchecked return value + +From: Sergio Perez Gonzalez + +[ Upstream commit 5a5fc308418aca275a898d638bc38c093d101855 ] + +The return value of spi_setup() is not captured within +spi_mux_select() and it is assumed to be always success. + +CID: 1638374 + +Signed-off-by: Sergio Perez Gonzalez +Link: https://patch.msgid.link/20250316054651.13242-1-sperezglz@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-mux.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/spi/spi-mux.c b/drivers/spi/spi-mux.c +index c02c4204442f5..0eb35c4e3987e 100644 +--- a/drivers/spi/spi-mux.c ++++ b/drivers/spi/spi-mux.c +@@ -68,9 +68,7 @@ static int spi_mux_select(struct spi_device *spi) + + priv->current_cs = spi_get_chipselect(spi, 0); + +- spi_setup(priv->spi); +- +- return 0; ++ return spi_setup(priv->spi); + } + + static int spi_mux_setup(struct spi_device *spi) +-- +2.39.5 + diff --git a/queue-6.12/spi-zynqmp-gqspi-always-acknowledge-interrupts.patch b/queue-6.12/spi-zynqmp-gqspi-always-acknowledge-interrupts.patch new file mode 100644 index 0000000000..e4ea0238e4 --- /dev/null +++ b/queue-6.12/spi-zynqmp-gqspi-always-acknowledge-interrupts.patch @@ -0,0 +1,72 @@ +From 11edf8708c24cf58a15aeea06c43c610d6a00130 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jan 2025 17:41:30 -0500 +Subject: spi: zynqmp-gqspi: Always acknowledge interrupts + +From: Sean Anderson + +[ Upstream commit 89785306453ce6d949e783f6936821a0b7649ee2 ] + +RXEMPTY can cause an IRQ, even though we may not do anything about it +(such as if we are waiting for more received data). We must still handle +these IRQs because we can tell they were caused by the device. + +Signed-off-by: Sean Anderson +Link: https://patch.msgid.link/20250116224130.2684544-6-sean.anderson@linux.dev +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-zynqmp-gqspi.c | 20 ++++++++------------ + 1 file changed, 8 insertions(+), 12 deletions(-) + +diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c +index b9df39e06e7cd..4b091b4d4ff37 100644 +--- a/drivers/spi/spi-zynqmp-gqspi.c ++++ b/drivers/spi/spi-zynqmp-gqspi.c +@@ -799,7 +799,6 @@ static void zynqmp_process_dma_irq(struct zynqmp_qspi *xqspi) + static irqreturn_t zynqmp_qspi_irq(int irq, void *dev_id) + { + struct zynqmp_qspi *xqspi = (struct zynqmp_qspi *)dev_id; +- irqreturn_t ret = IRQ_NONE; + u32 status, mask, dma_status = 0; + + status = zynqmp_gqspi_read(xqspi, GQSPI_ISR_OFST); +@@ -814,27 +813,24 @@ static irqreturn_t zynqmp_qspi_irq(int irq, void *dev_id) + dma_status); + } + +- if (mask & GQSPI_ISR_TXNOT_FULL_MASK) { ++ if (!mask && !dma_status) ++ return IRQ_NONE; ++ ++ if (mask & GQSPI_ISR_TXNOT_FULL_MASK) + zynqmp_qspi_filltxfifo(xqspi, GQSPI_TX_FIFO_FILL); +- ret = IRQ_HANDLED; +- } + +- if (dma_status & GQSPI_QSPIDMA_DST_I_STS_DONE_MASK) { ++ if (dma_status & GQSPI_QSPIDMA_DST_I_STS_DONE_MASK) + zynqmp_process_dma_irq(xqspi); +- ret = IRQ_HANDLED; +- } else if (!(mask & GQSPI_IER_RXEMPTY_MASK) && +- (mask & GQSPI_IER_GENFIFOEMPTY_MASK)) { ++ else if (!(mask & GQSPI_IER_RXEMPTY_MASK) && ++ (mask & GQSPI_IER_GENFIFOEMPTY_MASK)) + zynqmp_qspi_readrxfifo(xqspi, GQSPI_RX_FIFO_FILL); +- ret = IRQ_HANDLED; +- } + + if (xqspi->bytes_to_receive == 0 && xqspi->bytes_to_transfer == 0 && + ((status & GQSPI_IRQ_MASK) == GQSPI_IRQ_MASK)) { + zynqmp_gqspi_write(xqspi, GQSPI_IDR_OFST, GQSPI_ISR_IDR_MASK); + complete(&xqspi->data_completion); +- ret = IRQ_HANDLED; + } +- return ret; ++ return IRQ_HANDLED; + } + + /** +-- +2.39.5 + diff --git a/queue-6.12/staging-vchiq_arm-create-keep-alive-thread-during-pr.patch b/queue-6.12/staging-vchiq_arm-create-keep-alive-thread-during-pr.patch new file mode 100644 index 0000000000..ad834cbb94 --- /dev/null +++ b/queue-6.12/staging-vchiq_arm-create-keep-alive-thread-during-pr.patch @@ -0,0 +1,129 @@ +From 5b21673a24281f10e600e1e7f0f9f174b4592e1e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Mar 2025 13:50:13 +0100 +Subject: staging: vchiq_arm: Create keep-alive thread during probe + +From: Stefan Wahren + +[ Upstream commit 86bc8821700665ad3962f3ef0d93667f59cf7031 ] + +Creating the keep-alive thread in vchiq_platform_init_state have +the following advantages: +- abort driver probe if kthread_create fails (more consistent behavior) +- make resource release process easier + +Since vchiq_keepalive_thread_func is defined below +vchiq_platform_init_state, the latter must be moved. + +Signed-off-by: Stefan Wahren +Link: https://lore.kernel.org/r/20250309125014.37166-5-wahrenst@gmx.net +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + .../interface/vchiq_arm/vchiq_arm.c | 69 +++++++++---------- + 1 file changed, 34 insertions(+), 35 deletions(-) + +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +index 97787002080a1..1a9432646b70a 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -588,29 +588,6 @@ static int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state + return 0; + } + +-int +-vchiq_platform_init_state(struct vchiq_state *state) +-{ +- struct vchiq_arm_state *platform_state; +- +- platform_state = devm_kzalloc(state->dev, sizeof(*platform_state), GFP_KERNEL); +- if (!platform_state) +- return -ENOMEM; +- +- rwlock_init(&platform_state->susp_res_lock); +- +- init_completion(&platform_state->ka_evt); +- atomic_set(&platform_state->ka_use_count, 0); +- atomic_set(&platform_state->ka_use_ack_count, 0); +- atomic_set(&platform_state->ka_release_count, 0); +- +- platform_state->state = state; +- +- state->platform_state = (struct opaque_platform_state *)platform_state; +- +- return 0; +-} +- + static struct vchiq_arm_state *vchiq_platform_get_arm_state(struct vchiq_state *state) + { + return (struct vchiq_arm_state *)state->platform_state; +@@ -1358,6 +1335,39 @@ vchiq_keepalive_thread_func(void *v) + return 0; + } + ++int ++vchiq_platform_init_state(struct vchiq_state *state) ++{ ++ struct vchiq_arm_state *platform_state; ++ char threadname[16]; ++ ++ platform_state = devm_kzalloc(state->dev, sizeof(*platform_state), GFP_KERNEL); ++ if (!platform_state) ++ return -ENOMEM; ++ ++ snprintf(threadname, sizeof(threadname), "vchiq-keep/%d", ++ state->id); ++ platform_state->ka_thread = kthread_create(&vchiq_keepalive_thread_func, ++ (void *)state, threadname); ++ if (IS_ERR(platform_state->ka_thread)) { ++ dev_err(state->dev, "couldn't create thread %s\n", threadname); ++ return PTR_ERR(platform_state->ka_thread); ++ } ++ ++ rwlock_init(&platform_state->susp_res_lock); ++ ++ init_completion(&platform_state->ka_evt); ++ atomic_set(&platform_state->ka_use_count, 0); ++ atomic_set(&platform_state->ka_use_ack_count, 0); ++ atomic_set(&platform_state->ka_release_count, 0); ++ ++ platform_state->state = state; ++ ++ state->platform_state = (struct opaque_platform_state *)platform_state; ++ ++ return 0; ++} ++ + int + vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, + enum USE_TYPE_E use_type) +@@ -1678,7 +1688,6 @@ void vchiq_platform_conn_state_changed(struct vchiq_state *state, + enum vchiq_connstate newstate) + { + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); +- char threadname[16]; + + dev_dbg(state->dev, "suspend: %d: %s->%s\n", + state->id, get_conn_state_name(oldstate), get_conn_state_name(newstate)); +@@ -1693,17 +1702,7 @@ void vchiq_platform_conn_state_changed(struct vchiq_state *state, + + arm_state->first_connect = 1; + write_unlock_bh(&arm_state->susp_res_lock); +- snprintf(threadname, sizeof(threadname), "vchiq-keep/%d", +- state->id); +- arm_state->ka_thread = kthread_create(&vchiq_keepalive_thread_func, +- (void *)state, +- threadname); +- if (IS_ERR(arm_state->ka_thread)) { +- dev_err(state->dev, "suspend: Couldn't create thread %s\n", +- threadname); +- } else { +- wake_up_process(arm_state->ka_thread); +- } ++ wake_up_process(arm_state->ka_thread); + } + + static const struct of_device_id vchiq_of_match[] = { +-- +2.39.5 + diff --git a/queue-6.12/sunrpc-don-t-allow-waiting-for-exiting-tasks.patch b/queue-6.12/sunrpc-don-t-allow-waiting-for-exiting-tasks.patch new file mode 100644 index 0000000000..3d6b17f14e --- /dev/null +++ b/queue-6.12/sunrpc-don-t-allow-waiting-for-exiting-tasks.patch @@ -0,0 +1,35 @@ +From 50353376b010a007e52d9814b140a21bbce5d94f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Mar 2025 12:52:52 -0400 +Subject: SUNRPC: Don't allow waiting for exiting tasks + +From: Trond Myklebust + +[ Upstream commit 14e41b16e8cb677bb440dca2edba8b041646c742 ] + +Once a task calls exit_signals() it can no longer be signalled. So do +not allow it to do killable waits. + +Reviewed-by: Jeff Layton +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + net/sunrpc/sched.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c +index 9b45fbdc90cab..73bc39281ef5f 100644 +--- a/net/sunrpc/sched.c ++++ b/net/sunrpc/sched.c +@@ -276,6 +276,8 @@ EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue); + + static int rpc_wait_bit_killable(struct wait_bit_key *key, int mode) + { ++ if (unlikely(current->flags & PF_EXITING)) ++ return -EINTR; + schedule(); + if (signal_pending_state(mode, current)) + return -ERESTARTSYS; +-- +2.39.5 + diff --git a/queue-6.12/sunrpc-rpc_clnt_set_transport-must-not-change-the-au.patch b/queue-6.12/sunrpc-rpc_clnt_set_transport-must-not-change-the-au.patch new file mode 100644 index 0000000000..16ec5aa0c7 --- /dev/null +++ b/queue-6.12/sunrpc-rpc_clnt_set_transport-must-not-change-the-au.patch @@ -0,0 +1,38 @@ +From c9b4ac22c6d9576b608626c8f37f068180e60bc2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 19:35:01 -0400 +Subject: SUNRPC: rpc_clnt_set_transport() must not change the autobind setting + +From: Trond Myklebust + +[ Upstream commit bf9be373b830a3e48117da5d89bb6145a575f880 ] + +The autobind setting was supposed to be determined in rpc_create(), +since commit c2866763b402 ("SUNRPC: use sockaddr + size when creating +remote transport endpoints"). + +Reviewed-by: Jeff Layton +Reviewed-by: Benjamin Coddington +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + net/sunrpc/clnt.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c +index 0090162ee8c35..17a4de75bfaf6 100644 +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -270,9 +270,6 @@ static struct rpc_xprt *rpc_clnt_set_transport(struct rpc_clnt *clnt, + old = rcu_dereference_protected(clnt->cl_xprt, + lockdep_is_held(&clnt->cl_lock)); + +- if (!xprt_bound(xprt)) +- clnt->cl_autobind = 1; +- + clnt->cl_timeout = timeout; + rcu_assign_pointer(clnt->cl_xprt, xprt); + spin_unlock(&clnt->cl_lock); +-- +2.39.5 + diff --git a/queue-6.12/sunrpc-rpcbind-should-never-reset-the-port-to-the-va.patch b/queue-6.12/sunrpc-rpcbind-should-never-reset-the-port-to-the-va.patch new file mode 100644 index 0000000000..674bea7cb1 --- /dev/null +++ b/queue-6.12/sunrpc-rpcbind-should-never-reset-the-port-to-the-va.patch @@ -0,0 +1,40 @@ +From baf4a5bd49614d0fc00e3ff7651ad3d6a9829dae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 19:05:48 -0400 +Subject: SUNRPC: rpcbind should never reset the port to the value '0' + +From: Trond Myklebust + +[ Upstream commit 214c13e380ad7636631279f426387f9c4e3c14d9 ] + +If we already had a valid port number for the RPC service, then we +should not allow the rpcbind client to set it to the invalid value '0'. + +Reviewed-by: Jeff Layton +Reviewed-by: Benjamin Coddington +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + net/sunrpc/rpcb_clnt.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c +index 102c3818bc54d..53bcca365fb1c 100644 +--- a/net/sunrpc/rpcb_clnt.c ++++ b/net/sunrpc/rpcb_clnt.c +@@ -820,9 +820,10 @@ static void rpcb_getport_done(struct rpc_task *child, void *data) + } + + trace_rpcb_setport(child, map->r_status, map->r_port); +- xprt->ops->set_port(xprt, map->r_port); +- if (map->r_port) ++ if (map->r_port) { ++ xprt->ops->set_port(xprt, map->r_port); + xprt_set_bound(xprt); ++ } + } + + /* +-- +2.39.5 + diff --git a/queue-6.12/tcp-bring-back-numa-dispersion-in-inet_ehash_locks_a.patch b/queue-6.12/tcp-bring-back-numa-dispersion-in-inet_ehash_locks_a.patch new file mode 100644 index 0000000000..8847403569 --- /dev/null +++ b/queue-6.12/tcp-bring-back-numa-dispersion-in-inet_ehash_locks_a.patch @@ -0,0 +1,105 @@ +From 7812a0785a9d6a095954bcf58bd7f7fd1c7e6243 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 13:05:50 +0000 +Subject: tcp: bring back NUMA dispersion in inet_ehash_locks_alloc() + +From: Eric Dumazet + +[ Upstream commit f8ece40786c9342249aa0a1b55e148ee23b2a746 ] + +We have platforms with 6 NUMA nodes and 480 cpus. + +inet_ehash_locks_alloc() currently allocates a single 64KB page +to hold all ehash spinlocks. This adds more pressure on a single node. + +Change inet_ehash_locks_alloc() to use vmalloc() to spread +the spinlocks on all online nodes, driven by NUMA policies. + +At boot time, NUMA policy is interleave=all, meaning that +tcp_hashinfo.ehash_locks gets hash dispersion on all nodes. + +Tested: + +lack5:~# grep inet_ehash_locks_alloc /proc/vmallocinfo +0x00000000d9aec4d1-0x00000000a828b652 69632 inet_ehash_locks_alloc+0x90/0x100 pages=16 vmalloc N0=2 N1=3 N2=3 N3=3 N4=3 N5=2 + +lack5:~# echo 8192 >/proc/sys/net/ipv4/tcp_child_ehash_entries +lack5:~# numactl --interleave=all unshare -n bash -c "grep inet_ehash_locks_alloc /proc/vmallocinfo" +0x000000004e99d30c-0x00000000763f3279 36864 inet_ehash_locks_alloc+0x90/0x100 pages=8 vmalloc N0=1 N1=2 N2=2 N3=1 N4=1 N5=1 +0x00000000d9aec4d1-0x00000000a828b652 69632 inet_ehash_locks_alloc+0x90/0x100 pages=16 vmalloc N0=2 N1=3 N2=3 N3=3 N4=3 N5=2 + +lack5:~# numactl --interleave=0,5 unshare -n bash -c "grep inet_ehash_locks_alloc /proc/vmallocinfo" +0x00000000fd73a33e-0x0000000004b9a177 36864 inet_ehash_locks_alloc+0x90/0x100 pages=8 vmalloc N0=4 N5=4 +0x00000000d9aec4d1-0x00000000a828b652 69632 inet_ehash_locks_alloc+0x90/0x100 pages=16 vmalloc N0=2 N1=3 N2=3 N3=3 N4=3 N5=2 + +lack5:~# echo 1024 >/proc/sys/net/ipv4/tcp_child_ehash_entries +lack5:~# numactl --interleave=all unshare -n bash -c "grep inet_ehash_locks_alloc /proc/vmallocinfo" +0x00000000db07d7a2-0x00000000ad697d29 8192 inet_ehash_locks_alloc+0x90/0x100 pages=1 vmalloc N2=1 +0x00000000d9aec4d1-0x00000000a828b652 69632 inet_ehash_locks_alloc+0x90/0x100 pages=16 vmalloc N0=2 N1=3 N2=3 N3=3 N4=3 N5=2 + +Signed-off-by: Eric Dumazet +Tested-by: Jason Xing +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250305130550.1865988-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/inet_hashtables.c | 37 ++++++++++++++++++++++++++----------- + 1 file changed, 26 insertions(+), 11 deletions(-) + +diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c +index 9bfcfd016e182..2b4a588247639 100644 +--- a/net/ipv4/inet_hashtables.c ++++ b/net/ipv4/inet_hashtables.c +@@ -1230,22 +1230,37 @@ int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo) + { + unsigned int locksz = sizeof(spinlock_t); + unsigned int i, nblocks = 1; ++ spinlock_t *ptr = NULL; + +- if (locksz != 0) { +- /* allocate 2 cache lines or at least one spinlock per cpu */ +- nblocks = max(2U * L1_CACHE_BYTES / locksz, 1U); +- nblocks = roundup_pow_of_two(nblocks * num_possible_cpus()); ++ if (locksz == 0) ++ goto set_mask; + +- /* no more locks than number of hash buckets */ +- nblocks = min(nblocks, hashinfo->ehash_mask + 1); ++ /* Allocate 2 cache lines or at least one spinlock per cpu. */ ++ nblocks = max(2U * L1_CACHE_BYTES / locksz, 1U) * num_possible_cpus(); + +- hashinfo->ehash_locks = kvmalloc_array(nblocks, locksz, GFP_KERNEL); +- if (!hashinfo->ehash_locks) +- return -ENOMEM; ++ /* At least one page per NUMA node. */ ++ nblocks = max(nblocks, num_online_nodes() * PAGE_SIZE / locksz); ++ ++ nblocks = roundup_pow_of_two(nblocks); ++ ++ /* No more locks than number of hash buckets. */ ++ nblocks = min(nblocks, hashinfo->ehash_mask + 1); + +- for (i = 0; i < nblocks; i++) +- spin_lock_init(&hashinfo->ehash_locks[i]); ++ if (num_online_nodes() > 1) { ++ /* Use vmalloc() to allow NUMA policy to spread pages ++ * on all available nodes if desired. ++ */ ++ ptr = vmalloc_array(nblocks, locksz); ++ } ++ if (!ptr) { ++ ptr = kvmalloc_array(nblocks, locksz, GFP_KERNEL); ++ if (!ptr) ++ return -ENOMEM; + } ++ for (i = 0; i < nblocks; i++) ++ spin_lock_init(&ptr[i]); ++ hashinfo->ehash_locks = ptr; ++set_mask: + hashinfo->ehash_locks_mask = nblocks - 1; + return 0; + } +-- +2.39.5 + diff --git a/queue-6.12/tcp-reorganize-tcp_in_ack_event-and-tcp_count_delive.patch b/queue-6.12/tcp-reorganize-tcp_in_ack_event-and-tcp_count_delive.patch new file mode 100644 index 0000000000..aa8d610700 --- /dev/null +++ b/queue-6.12/tcp-reorganize-tcp_in_ack_event-and-tcp_count_delive.patch @@ -0,0 +1,155 @@ +From e35d1f83d28daf393cb845b5155afdd3e933371b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 23:38:41 +0100 +Subject: tcp: reorganize tcp_in_ack_event() and tcp_count_delivered() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit 149dfb31615e22271d2525f078c95ea49bc4db24 ] + +- Move tcp_count_delivered() earlier and split tcp_count_delivered_ce() + out of it +- Move tcp_in_ack_event() later +- While at it, remove the inline from tcp_in_ack_event() and let + the compiler to decide + +Accurate ECN's heuristics does not know if there is going +to be ACE field based CE counter increase or not until after +rtx queue has been processed. Only then the number of ACKed +bytes/pkts is available. As CE or not affects presence of +FLAG_ECE, that information for tcp_in_ack_event is not yet +available in the old location of the call to tcp_in_ack_event(). + +Signed-off-by: Ilpo Järvinen +Signed-off-by: Chia-Yu Chang +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_input.c | 56 +++++++++++++++++++++++++------------------- + 1 file changed, 32 insertions(+), 24 deletions(-) + +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index d93a5a89c5692..d29219e067b7f 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -419,6 +419,20 @@ static bool tcp_ecn_rcv_ecn_echo(const struct tcp_sock *tp, const struct tcphdr + return false; + } + ++static void tcp_count_delivered_ce(struct tcp_sock *tp, u32 ecn_count) ++{ ++ tp->delivered_ce += ecn_count; ++} ++ ++/* Updates the delivered and delivered_ce counts */ ++static void tcp_count_delivered(struct tcp_sock *tp, u32 delivered, ++ bool ece_ack) ++{ ++ tp->delivered += delivered; ++ if (ece_ack) ++ tcp_count_delivered_ce(tp, delivered); ++} ++ + /* Buffer size and advertised window tuning. + * + * 1. Tuning sk->sk_sndbuf, when connection enters established state. +@@ -1154,15 +1168,6 @@ void tcp_mark_skb_lost(struct sock *sk, struct sk_buff *skb) + } + } + +-/* Updates the delivered and delivered_ce counts */ +-static void tcp_count_delivered(struct tcp_sock *tp, u32 delivered, +- bool ece_ack) +-{ +- tp->delivered += delivered; +- if (ece_ack) +- tp->delivered_ce += delivered; +-} +- + /* This procedure tags the retransmission queue when SACKs arrive. + * + * We have three tag bits: SACKED(S), RETRANS(R) and LOST(L). +@@ -3862,12 +3867,23 @@ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag) + } + } + +-static inline void tcp_in_ack_event(struct sock *sk, u32 flags) ++static void tcp_in_ack_event(struct sock *sk, int flag) + { + const struct inet_connection_sock *icsk = inet_csk(sk); + +- if (icsk->icsk_ca_ops->in_ack_event) +- icsk->icsk_ca_ops->in_ack_event(sk, flags); ++ if (icsk->icsk_ca_ops->in_ack_event) { ++ u32 ack_ev_flags = 0; ++ ++ if (flag & FLAG_WIN_UPDATE) ++ ack_ev_flags |= CA_ACK_WIN_UPDATE; ++ if (flag & FLAG_SLOWPATH) { ++ ack_ev_flags |= CA_ACK_SLOWPATH; ++ if (flag & FLAG_ECE) ++ ack_ev_flags |= CA_ACK_ECE; ++ } ++ ++ icsk->icsk_ca_ops->in_ack_event(sk, ack_ev_flags); ++ } + } + + /* Congestion control has updated the cwnd already. So if we're in +@@ -3984,12 +4000,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) + tcp_snd_una_update(tp, ack); + flag |= FLAG_WIN_UPDATE; + +- tcp_in_ack_event(sk, CA_ACK_WIN_UPDATE); +- + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPHPACKS); + } else { +- u32 ack_ev_flags = CA_ACK_SLOWPATH; +- + if (ack_seq != TCP_SKB_CB(skb)->end_seq) + flag |= FLAG_DATA; + else +@@ -4001,19 +4013,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) + flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una, + &sack_state); + +- if (tcp_ecn_rcv_ecn_echo(tp, tcp_hdr(skb))) { ++ if (tcp_ecn_rcv_ecn_echo(tp, tcp_hdr(skb))) + flag |= FLAG_ECE; +- ack_ev_flags |= CA_ACK_ECE; +- } + + if (sack_state.sack_delivered) + tcp_count_delivered(tp, sack_state.sack_delivered, + flag & FLAG_ECE); +- +- if (flag & FLAG_WIN_UPDATE) +- ack_ev_flags |= CA_ACK_WIN_UPDATE; +- +- tcp_in_ack_event(sk, ack_ev_flags); + } + + /* This is a deviation from RFC3168 since it states that: +@@ -4040,6 +4045,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) + + tcp_rack_update_reo_wnd(sk, &rs); + ++ tcp_in_ack_event(sk, flag); ++ + if (tp->tlp_high_seq) + tcp_process_tlp_ack(sk, ack, flag); + +@@ -4071,6 +4078,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) + return 1; + + no_queue: ++ tcp_in_ack_event(sk, flag); + /* If data was DSACKed, see if we can undo a cwnd reduction. */ + if (flag & FLAG_DSACKING_ACK) { + tcp_fastretrans_alert(sk, prior_snd_una, num_dupack, &flag, +-- +2.39.5 + diff --git a/queue-6.12/thermal-drivers-mediatek-lvts-start-sensor-interrupt.patch b/queue-6.12/thermal-drivers-mediatek-lvts-start-sensor-interrupt.patch new file mode 100644 index 0000000000..d3998b5ab2 --- /dev/null +++ b/queue-6.12/thermal-drivers-mediatek-lvts-start-sensor-interrupt.patch @@ -0,0 +1,50 @@ +From ff6ab28aa5823fce285bb200fef171a7a3da44f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 10:27:15 -0300 +Subject: thermal/drivers/mediatek/lvts: Start sensor interrupts disabled +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Nícolas F. R. A. Prado + +[ Upstream commit 2738fb3ec6838a10d2c4ce65cefdb3b90b11bd61 ] + +Interrupts are enabled per sensor in lvts_update_irq_mask() as needed, +there's no point in enabling all of them during initialization. Change +the MONINT register initial value so all sensor interrupts start +disabled. + +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Nícolas F. R. A. Prado +Link: https://lore.kernel.org/r/20250113-mt8192-lvts-filtered-suspend-fix-v2-4-07a25200c7c6@collabora.com +Signed-off-by: Daniel Lezcano +Signed-off-by: Sasha Levin +--- + drivers/thermal/mediatek/lvts_thermal.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c +index 4b3225377e8f8..3295b27ab70d2 100644 +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -65,7 +65,6 @@ + #define LVTS_HW_FILTER 0x0 + #define LVTS_TSSEL_CONF 0x13121110 + #define LVTS_CALSCALE_CONF 0x300 +-#define LVTS_MONINT_CONF 0x0300318C + + #define LVTS_MONINT_OFFSET_SENSOR0 0xC + #define LVTS_MONINT_OFFSET_SENSOR1 0x180 +@@ -929,7 +928,7 @@ static int lvts_irq_init(struct lvts_ctrl *lvts_ctrl) + * The LVTS_MONINT register layout is the same as the LVTS_MONINTSTS + * register, except we set the bits to enable the interrupt. + */ +- writel(LVTS_MONINT_CONF, LVTS_MONINT(lvts_ctrl->base)); ++ writel(0, LVTS_MONINT(lvts_ctrl->base)); + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.12/thermal-drivers-qoriq-power-down-tmu-on-system-suspe.patch b/queue-6.12/thermal-drivers-qoriq-power-down-tmu-on-system-suspe.patch new file mode 100644 index 0000000000..de95ba9106 --- /dev/null +++ b/queue-6.12/thermal-drivers-qoriq-power-down-tmu-on-system-suspe.patch @@ -0,0 +1,63 @@ +From 3b497a1154a7eef219f027e3569798f86f74b07e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Dec 2024 11:48:59 -0500 +Subject: thermal/drivers/qoriq: Power down TMU on system suspend + +From: Alice Guo + +[ Upstream commit 229f3feb4b0442835b27d519679168bea2de96c2 ] + +Enable power-down of TMU (Thermal Management Unit) for TMU version 2 during +system suspend to save power. Save approximately 4.3mW on VDD_ANA_1P8 on +i.MX93 platforms. + +Signed-off-by: Alice Guo +Signed-off-by: Frank Li +Link: https://lore.kernel.org/r/20241209164859.3758906-2-Frank.Li@nxp.com +Signed-off-by: Daniel Lezcano +Signed-off-by: Sasha Levin +--- + drivers/thermal/qoriq_thermal.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c +index 52e26be8c53df..aed2729f63d06 100644 +--- a/drivers/thermal/qoriq_thermal.c ++++ b/drivers/thermal/qoriq_thermal.c +@@ -18,6 +18,7 @@ + #define SITES_MAX 16 + #define TMR_DISABLE 0x0 + #define TMR_ME 0x80000000 ++#define TMR_CMD BIT(29) + #define TMR_ALPF 0x0c000000 + #define TMR_ALPF_V2 0x03000000 + #define TMTMIR_DEFAULT 0x0000000f +@@ -356,6 +357,12 @@ static int qoriq_tmu_suspend(struct device *dev) + if (ret) + return ret; + ++ if (data->ver > TMU_VER1) { ++ ret = regmap_set_bits(data->regmap, REGS_TMR, TMR_CMD); ++ if (ret) ++ return ret; ++ } ++ + clk_disable_unprepare(data->clk); + + return 0; +@@ -370,6 +377,12 @@ static int qoriq_tmu_resume(struct device *dev) + if (ret) + return ret; + ++ if (data->ver > TMU_VER1) { ++ ret = regmap_clear_bits(data->regmap, REGS_TMR, TMR_CMD); ++ if (ret) ++ return ret; ++ } ++ + /* Enable monitoring */ + return regmap_update_bits(data->regmap, REGS_TMR, TMR_ME, TMR_ME); + } +-- +2.39.5 + diff --git a/queue-6.12/thunderbolt-do-not-add-non-active-nvm-if-nvm-upgrade.patch b/queue-6.12/thunderbolt-do-not-add-non-active-nvm-if-nvm-upgrade.patch new file mode 100644 index 0000000000..480dbac596 --- /dev/null +++ b/queue-6.12/thunderbolt-do-not-add-non-active-nvm-if-nvm-upgrade.patch @@ -0,0 +1,42 @@ +From 54f69643af741ade857c12d5fa5163c50c3eb9d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 14:56:20 +0200 +Subject: thunderbolt: Do not add non-active NVM if NVM upgrade is disabled for + retimer + +From: Mika Westerberg + +[ Upstream commit ad79c278e478ca8c1a3bf8e7a0afba8f862a48a1 ] + +This is only used to write a new NVM in order to upgrade the retimer +firmware. It does not make sense to expose it if upgrade is disabled. +This also makes it consistent with the router NVM upgrade. + +Signed-off-by: Mika Westerberg +Signed-off-by: Sasha Levin +--- + drivers/thunderbolt/retimer.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/thunderbolt/retimer.c b/drivers/thunderbolt/retimer.c +index eeb64433ebbca..3488be7620674 100644 +--- a/drivers/thunderbolt/retimer.c ++++ b/drivers/thunderbolt/retimer.c +@@ -93,9 +93,11 @@ static int tb_retimer_nvm_add(struct tb_retimer *rt) + if (ret) + goto err_nvm; + +- ret = tb_nvm_add_non_active(nvm, nvm_write); +- if (ret) +- goto err_nvm; ++ if (!rt->no_nvm_upgrade) { ++ ret = tb_nvm_add_non_active(nvm, nvm_write); ++ if (ret) ++ goto err_nvm; ++ } + + rt->nvm = nvm; + dev_dbg(&rt->dev, "NVM version %x.%x\n", nvm->major, nvm->minor); +-- +2.39.5 + diff --git a/queue-6.12/timer_list-don-t-use-pk-through-printk.patch b/queue-6.12/timer_list-don-t-use-pk-through-printk.patch new file mode 100644 index 0000000000..11dfe1d630 --- /dev/null +++ b/queue-6.12/timer_list-don-t-use-pk-through-printk.patch @@ -0,0 +1,65 @@ +From 514b7f59baa5cf2e6fd99a584d87335175b667ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 10:54:47 +0100 +Subject: timer_list: Don't use %pK through printk() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Thomas Weißschuh + +[ Upstream commit a52067c24ccf6ee4c85acffa0f155e9714f9adce ] + +This reverts commit f590308536db ("timer debug: Hide kernel addresses via +%pK in /proc/timer_list") + +The timer list helper SEQ_printf() uses either the real seq_printf() for +procfs output or vprintk() to print to the kernel log, when invoked from +SysRq-q. It uses %pK for printing pointers. + +In the past %pK was prefered over %p as it would not leak raw pointer +values into the kernel log. Since commit ad67b74d2469 ("printk: hash +addresses printed with %p") the regular %p has been improved to avoid this +issue. + +Furthermore, restricted pointers ("%pK") were never meant to be used +through printk(). They can still unintentionally leak raw pointers or +acquire sleeping looks in atomic contexts. + +Switch to the regular pointer formatting which is safer, easier to reason +about and sufficient here. + +Signed-off-by: Thomas Weißschuh +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/lkml/20250113171731-dc10e3c1-da64-4af0-b767-7c7070468023@linutronix.de/ +Link: https://lore.kernel.org/all/20250311-restricted-pointers-timer-v1-1-6626b91e54ab@linutronix.de +Signed-off-by: Sasha Levin +--- + kernel/time/timer_list.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c +index 1c311c46da507..cfbb46cc4e761 100644 +--- a/kernel/time/timer_list.c ++++ b/kernel/time/timer_list.c +@@ -46,7 +46,7 @@ static void + print_timer(struct seq_file *m, struct hrtimer *taddr, struct hrtimer *timer, + int idx, u64 now) + { +- SEQ_printf(m, " #%d: <%pK>, %ps", idx, taddr, timer->function); ++ SEQ_printf(m, " #%d: <%p>, %ps", idx, taddr, timer->function); + SEQ_printf(m, ", S:%02x", timer->state); + SEQ_printf(m, "\n"); + SEQ_printf(m, " # expires at %Lu-%Lu nsecs [in %Ld to %Ld nsecs]\n", +@@ -98,7 +98,7 @@ print_active_timers(struct seq_file *m, struct hrtimer_clock_base *base, + static void + print_base(struct seq_file *m, struct hrtimer_clock_base *base, u64 now) + { +- SEQ_printf(m, " .base: %pK\n", base); ++ SEQ_printf(m, " .base: %p\n", base); + SEQ_printf(m, " .index: %d\n", base->index); + + SEQ_printf(m, " .resolution: %u nsecs\n", hrtimer_resolution); +-- +2.39.5 + diff --git a/queue-6.12/tools-build-don-t-pass-test-log-files-to-linker.patch b/queue-6.12/tools-build-don-t-pass-test-log-files-to-linker.patch new file mode 100644 index 0000000000..30605d8a52 --- /dev/null +++ b/queue-6.12/tools-build-don-t-pass-test-log-files-to-linker.patch @@ -0,0 +1,48 @@ +From 3712bd8ca7875cac673cee41d82ded18f237de70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 14:36:23 -0700 +Subject: tools/build: Don't pass test log files to linker + +From: Ian Rogers + +[ Upstream commit 935e7cb5bb80106ff4f2fe39640f430134ef8cd8 ] + +Separate test log files from object files. Depend on test log output +but don't pass to the linker. + +Reviewed-by: James Clark +Signed-off-by: Ian Rogers +Link: https://lore.kernel.org/r/20250311213628.569562-2-irogers@google.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/build/Makefile.build | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build +index 5fb3fb3d97e0f..ffe988867703b 100644 +--- a/tools/build/Makefile.build ++++ b/tools/build/Makefile.build +@@ -149,6 +149,10 @@ objprefix := $(subst ./,,$(OUTPUT)$(dir)/) + obj-y := $(addprefix $(objprefix),$(obj-y)) + subdir-obj-y := $(addprefix $(objprefix),$(subdir-obj-y)) + ++# Separate out test log files from real build objects. ++test-y := $(filter %_log, $(obj-y)) ++obj-y := $(filter-out %_log, $(obj-y)) ++ + # Final '$(obj)-in.o' object + in-target := $(objprefix)$(obj)-in.o + +@@ -159,7 +163,7 @@ $(subdir-y): + + $(sort $(subdir-obj-y)): $(subdir-y) ; + +-$(in-target): $(obj-y) FORCE ++$(in-target): $(obj-y) $(test-y) FORCE + $(call rule_mkdir) + $(call if_changed,$(host)ld_multi) + +-- +2.39.5 + diff --git a/queue-6.12/tools-power-turbostat-clustered-uncore-mhz-counters-.patch b/queue-6.12/tools-power-turbostat-clustered-uncore-mhz-counters-.patch new file mode 100644 index 0000000000..f917f6fb90 --- /dev/null +++ b/queue-6.12/tools-power-turbostat-clustered-uncore-mhz-counters-.patch @@ -0,0 +1,84 @@ +From 91d4186f306387a8fd94543622c190fd2f2a764d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 21:46:24 -0600 +Subject: tools/power turbostat: Clustered Uncore MHz counters should honor + show/hide options +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Len Brown + +[ Upstream commit 1c7c7388e6c31f46b26a884d80b45efbad8237b2 ] + +The clustered uncore frequency counters, UMHz*.* +should honor the --show and --hide options. + +All non-specified counters should be implicityly hidden. +But when --show was used, UMHz*.* showed up anyway: + +$ sudo turbostat -q -S --show Busy% +Busy%  UMHz0.0  UMHz1.0  UMHz2.0  UMHz3.0  UMHz4.0 + +Indeed, there was no string that can be used to explicitly +show or hide clustered uncore counters. + +Even through they are dynamically probed and added, +group the clustered UMHz*.* counters with the legacy +built-in-counter "UncMHz" for show/hide. + +turbostat --show Busy% + does not show UMHz*.*. +turbostat --show UncMHz + shows either UncMHz or UMHz*.*, if present +turbostat --hide UncMHz + hides either UncMHz or UMHz*.*, if present + +Reported-by: Artem Bityutskiy +Signed-off-by: Len Brown +Tested-by: Artem Bityutskiy +Signed-off-by: Sasha Levin +--- + tools/power/x86/turbostat/turbostat.8 | 1 + + tools/power/x86/turbostat/turbostat.c | 13 ++++++++++++- + 2 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 +index a3cf1d17163ae..e4b00e13302b3 100644 +--- a/tools/power/x86/turbostat/turbostat.8 ++++ b/tools/power/x86/turbostat/turbostat.8 +@@ -199,6 +199,7 @@ The system configuration dump (if --quiet is not used) is followed by statistics + \fBUncMHz\fP per-package uncore MHz, instantaneous sample. + .PP + \fBUMHz1.0\fP per-package uncore MHz for domain=1 and fabric_cluster=0, instantaneous sample. System summary is the average of all packages. ++For the "--show" and "--hide" options, use "UncMHz" to operate on all UMHz*.* as a group. + .SH TOO MUCH INFORMATION EXAMPLE + By default, turbostat dumps all possible information -- a system configuration header, followed by columns for all counters. + This is ideal for remote debugging, use the "--out" option to save everything to a text file, and get that file to the expert helping you debug. +diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c +index 77ef60980ee58..12424bf08551d 100644 +--- a/tools/power/x86/turbostat/turbostat.c ++++ b/tools/power/x86/turbostat/turbostat.c +@@ -6445,7 +6445,18 @@ static void probe_intel_uncore_frequency_cluster(void) + sprintf(path, "%s/current_freq_khz", path_base); + sprintf(name_buf, "UMHz%d.%d", domain_id, cluster_id); + +- add_counter(0, path, name_buf, 0, SCOPE_PACKAGE, COUNTER_K2M, FORMAT_AVERAGE, 0, package_id); ++ /* ++ * Once add_couter() is called, that counter is always read ++ * and reported -- So it is effectively (enabled & present). ++ * Only call add_counter() here if legacy BIC_UNCORE_MHZ (UncMHz) ++ * is (enabled). Since we are in this routine, we ++ * know we will not probe and set (present) the legacy counter. ++ * ++ * This allows "--show/--hide UncMHz" to be effective for ++ * the clustered MHz counters, as a group. ++ */ ++ if BIC_IS_ENABLED(BIC_UNCORE_MHZ) ++ add_counter(0, path, name_buf, 0, SCOPE_PACKAGE, COUNTER_K2M, FORMAT_AVERAGE, 0, package_id); + + if (quiet) + continue; +-- +2.39.5 + diff --git a/queue-6.12/tools-ynl-gen-don-t-output-external-constants.patch b/queue-6.12/tools-ynl-gen-don-t-output-external-constants.patch new file mode 100644 index 0000000000..256bdd2759 --- /dev/null +++ b/queue-6.12/tools-ynl-gen-don-t-output-external-constants.patch @@ -0,0 +1,40 @@ +From c381b451a7733406d1e47277910d3d0715d28a2c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 13:55:09 -0800 +Subject: tools: ynl-gen: don't output external constants + +From: Jakub Kicinski + +[ Upstream commit 7e8b24e24ac46038e48c9a042e7d9b31855cbca5 ] + +A definition with a "header" property is an "external" definition +for C code, as in it is defined already in another C header file. +Other languages will need the exact value but C codegen should +not recreate it. So don't output those definitions in the uAPI +header. + +Signed-off-by: Jakub Kicinski +Link: https://patch.msgid.link/20250203215510.1288728-1-kuba@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + tools/net/ynl/ynl-gen-c.py | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/tools/net/ynl/ynl-gen-c.py b/tools/net/ynl/ynl-gen-c.py +index 463f1394ab971..c78f1c1bca75c 100755 +--- a/tools/net/ynl/ynl-gen-c.py ++++ b/tools/net/ynl/ynl-gen-c.py +@@ -2417,6 +2417,9 @@ def render_uapi(family, cw): + + defines = [] + for const in family['definitions']: ++ if const.get('header'): ++ continue ++ + if const['type'] != 'const': + cw.writes_defines(defines) + defines = [] +-- +2.39.5 + diff --git a/queue-6.12/tools-ynl-gen-validate-0-len-strings-from-kernel.patch b/queue-6.12/tools-ynl-gen-validate-0-len-strings-from-kernel.patch new file mode 100644 index 0000000000..b68633775e --- /dev/null +++ b/queue-6.12/tools-ynl-gen-validate-0-len-strings-from-kernel.patch @@ -0,0 +1,38 @@ +From 50ec4baff1f0eea8bb79251ac85ca1dad64edb5a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 May 2025 21:30:50 -0700 +Subject: tools: ynl-gen: validate 0 len strings from kernel + +From: David Wei + +[ Upstream commit 4720f9707c783f642332dee3d56dccaefa850e42 ] + +Strings from the kernel are guaranteed to be null terminated and +ynl_attr_validate() checks for this. But it doesn't check if the string +has a len of 0, which would cause problems when trying to access +data[len - 1]. Fix this by checking that len is positive. + +Signed-off-by: David Wei +Link: https://patch.msgid.link/20250503043050.861238-1-dw@davidwei.uk +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/net/ynl/lib/ynl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/net/ynl/lib/ynl.c b/tools/net/ynl/lib/ynl.c +index ce32cb35007d6..c4da34048ef85 100644 +--- a/tools/net/ynl/lib/ynl.c ++++ b/tools/net/ynl/lib/ynl.c +@@ -364,7 +364,7 @@ int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr) + "Invalid attribute (binary %s)", policy->name); + return -1; + case YNL_PT_NUL_STR: +- if ((!policy->len || len <= policy->len) && !data[len - 1]) ++ if (len && (!policy->len || len <= policy->len) && !data[len - 1]) + break; + yerr(yarg->ys, YNL_ERROR_ATTR_INVALID, + "Invalid attribute (string %s)", policy->name); +-- +2.39.5 + diff --git a/queue-6.12/tpm-convert-warn-to-dbg-in-tpm2_start_auth_session.patch b/queue-6.12/tpm-convert-warn-to-dbg-in-tpm2_start_auth_session.patch new file mode 100644 index 0000000000..a295d3b54f --- /dev/null +++ b/queue-6.12/tpm-convert-warn-to-dbg-in-tpm2_start_auth_session.patch @@ -0,0 +1,47 @@ +From eb609d9be74156706a2103b1427c3472014666cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Mar 2025 10:56:44 +0000 +Subject: tpm: Convert warn to dbg in tpm2_start_auth_session() + +From: Jonathan McDowell + +[ Upstream commit 6359691b4fbcaf3ed86f53043a1f7c6cc54c09be ] + +TPM2 sessions have been flushed lazily since commit df745e25098dc ("tpm: +Lazily flush the auth session"). If /dev/tpm{rm}0 is not accessed +in-between two in-kernel calls, it is possible that a TPM2 session is +re-started before the previous one has been completed. + +This causes a spurios warning in a legit run-time condition, which is also +correctly addressed with a fast return path: + +[ 2.944047] tpm tpm0: auth session is active + +Address the issue by changing dev_warn_once() call to a dev_dbg_once() +call. + +[jarkko: Rewrote the commit message, and instead of dropping converted + to a debug message.] +Signed-off-by: Jonathan McDowell +Signed-off-by: Jarkko Sakkinen +Signed-off-by: Sasha Levin +--- + drivers/char/tpm/tpm2-sessions.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c +index ecea089157301..cf0b831540447 100644 +--- a/drivers/char/tpm/tpm2-sessions.c ++++ b/drivers/char/tpm/tpm2-sessions.c +@@ -974,7 +974,7 @@ int tpm2_start_auth_session(struct tpm_chip *chip) + int rc; + + if (chip->auth) { +- dev_warn_once(&chip->dev, "auth session is active\n"); ++ dev_dbg_once(&chip->dev, "auth session is active\n"); + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.12/tracing-mark-binary-printing-functions-with-__printf.patch b/queue-6.12/tracing-mark-binary-printing-functions-with-__printf.patch new file mode 100644 index 0000000000..c2b14bdbac --- /dev/null +++ b/queue-6.12/tracing-mark-binary-printing-functions-with-__printf.patch @@ -0,0 +1,158 @@ +From b2426af09e43844befcdb556dbdf5625bd0cb972 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 16:40:49 +0200 +Subject: tracing: Mark binary printing functions with __printf() attribute +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Andy Shevchenko + +[ Upstream commit 196a062641fe68d9bfe0ad36b6cd7628c99ad22c ] + +Binary printing functions are using printf() type of format, and compiler +is not happy about them as is: + +kernel/trace/trace.c:3292:9: error: function ‘trace_vbprintk’ might be a candidate for ‘gnu_printf’ format attribute [-Werror=suggest-attribute=format] +kernel/trace/trace_seq.c:182:9: error: function ‘trace_seq_bprintf’ might be a candidate for ‘gnu_printf’ format attribute [-Werror=suggest-attribute=format] + +Fix the compilation errors by adding __printf() attribute. + +While at it, move existing __printf() attributes from the implementations +to the declarations. IT also fixes incorrect attribute parameters that are +used for trace_array_printk(). + +Signed-off-by: Andy Shevchenko +Reviewed-by: Kees Cook +Reviewed-by: Petr Mladek +Link: https://lore.kernel.org/r/20250321144822.324050-4-andriy.shevchenko@linux.intel.com +Signed-off-by: Petr Mladek +Signed-off-by: Sasha Levin +--- + include/linux/trace.h | 4 ++-- + include/linux/trace_seq.h | 8 ++++---- + kernel/trace/trace.c | 11 +++-------- + kernel/trace/trace.h | 16 +++++++++------- + 4 files changed, 18 insertions(+), 21 deletions(-) + +diff --git a/include/linux/trace.h b/include/linux/trace.h +index fdcd76b7be83d..7eaad857dee04 100644 +--- a/include/linux/trace.h ++++ b/include/linux/trace.h +@@ -72,8 +72,8 @@ static inline int unregister_ftrace_export(struct trace_export *export) + static inline void trace_printk_init_buffers(void) + { + } +-static inline int trace_array_printk(struct trace_array *tr, unsigned long ip, +- const char *fmt, ...) ++static inline __printf(3, 4) ++int trace_array_printk(struct trace_array *tr, unsigned long ip, const char *fmt, ...) + { + return 0; + } +diff --git a/include/linux/trace_seq.h b/include/linux/trace_seq.h +index 1ef95c0287f05..a93ed5ac32265 100644 +--- a/include/linux/trace_seq.h ++++ b/include/linux/trace_seq.h +@@ -88,8 +88,8 @@ extern __printf(2, 3) + void trace_seq_printf(struct trace_seq *s, const char *fmt, ...); + extern __printf(2, 0) + void trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args); +-extern void +-trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary); ++extern __printf(2, 0) ++void trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary); + extern int trace_print_seq(struct seq_file *m, struct trace_seq *s); + extern int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, + int cnt); +@@ -113,8 +113,8 @@ static inline __printf(2, 3) + void trace_seq_printf(struct trace_seq *s, const char *fmt, ...) + { + } +-static inline void +-trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary) ++static inline __printf(2, 0) ++void trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary) + { + } + +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index 06104c2c66ab2..e773b0adcfc0a 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -3343,10 +3343,9 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args) + } + EXPORT_SYMBOL_GPL(trace_vbprintk); + +-__printf(3, 0) +-static int +-__trace_array_vprintk(struct trace_buffer *buffer, +- unsigned long ip, const char *fmt, va_list args) ++static __printf(3, 0) ++int __trace_array_vprintk(struct trace_buffer *buffer, ++ unsigned long ip, const char *fmt, va_list args) + { + struct trace_event_call *call = &event_print; + struct ring_buffer_event *event; +@@ -3399,7 +3398,6 @@ __trace_array_vprintk(struct trace_buffer *buffer, + return len; + } + +-__printf(3, 0) + int trace_array_vprintk(struct trace_array *tr, + unsigned long ip, const char *fmt, va_list args) + { +@@ -3429,7 +3427,6 @@ int trace_array_vprintk(struct trace_array *tr, + * Note, trace_array_init_printk() must be called on @tr before this + * can be used. + */ +-__printf(3, 0) + int trace_array_printk(struct trace_array *tr, + unsigned long ip, const char *fmt, ...) + { +@@ -3474,7 +3471,6 @@ int trace_array_init_printk(struct trace_array *tr) + } + EXPORT_SYMBOL_GPL(trace_array_init_printk); + +-__printf(3, 4) + int trace_array_printk_buf(struct trace_buffer *buffer, + unsigned long ip, const char *fmt, ...) + { +@@ -3490,7 +3486,6 @@ int trace_array_printk_buf(struct trace_buffer *buffer, + return ret; + } + +-__printf(2, 0) + int trace_vprintk(unsigned long ip, const char *fmt, va_list args) + { + return trace_array_vprintk(printk_trace, ip, fmt, args); +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index 04ea327198ba8..82da3ac140242 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -818,13 +818,15 @@ static inline void __init disable_tracing_selftest(const char *reason) + + extern void *head_page(struct trace_array_cpu *data); + extern unsigned long long ns2usecs(u64 nsec); +-extern int +-trace_vbprintk(unsigned long ip, const char *fmt, va_list args); +-extern int +-trace_vprintk(unsigned long ip, const char *fmt, va_list args); +-extern int +-trace_array_vprintk(struct trace_array *tr, +- unsigned long ip, const char *fmt, va_list args); ++ ++__printf(2, 0) ++int trace_vbprintk(unsigned long ip, const char *fmt, va_list args); ++__printf(2, 0) ++int trace_vprintk(unsigned long ip, const char *fmt, va_list args); ++__printf(3, 0) ++int trace_array_vprintk(struct trace_array *tr, ++ unsigned long ip, const char *fmt, va_list args); ++__printf(3, 4) + int trace_array_printk_buf(struct trace_buffer *buffer, + unsigned long ip, const char *fmt, ...); + void trace_printk_seq(struct trace_seq *s); +-- +2.39.5 + diff --git a/queue-6.12/ublk-complete-command-synchronously-on-error.patch b/queue-6.12/ublk-complete-command-synchronously-on-error.patch new file mode 100644 index 0000000000..11301936fd --- /dev/null +++ b/queue-6.12/ublk-complete-command-synchronously-on-error.patch @@ -0,0 +1,74 @@ +From 6f4adf23886b0c4d6e1c1efd71db82131fceae1a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 14:24:55 -0700 +Subject: ublk: complete command synchronously on error + +From: Caleb Sander Mateos + +[ Upstream commit 603f9be21c1894e462416e3324962d6c9c2b95f8 ] + +In case of an error, ublk's ->uring_cmd() functions currently return +-EIOCBQUEUED and immediately call io_uring_cmd_done(). -EIOCBQUEUED and +io_uring_cmd_done() are intended for asynchronous completions. For +synchronous completions, the ->uring_cmd() function can just return the +negative return code directly. This skips io_uring_cmd_del_cancelable(), +and deferring the completion to task work. So return the error code +directly from __ublk_ch_uring_cmd() and ublk_ctrl_uring_cmd(). + +Update ublk_ch_uring_cmd_cb(), which currently ignores the return value +from __ublk_ch_uring_cmd(), to call io_uring_cmd_done() for synchronous +completions. + +Signed-off-by: Caleb Sander Mateos +Reviewed-by: Ming Lei +Reviewed-by: Keith Busch +Link: https://lore.kernel.org/r/20250225212456.2902549-1-csander@purestorage.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/block/ublk_drv.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c +index 5ec5d580ef506..a01a547c562f3 100644 +--- a/drivers/block/ublk_drv.c ++++ b/drivers/block/ublk_drv.c +@@ -1881,10 +1881,9 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd, + return -EIOCBQUEUED; + + out: +- io_uring_cmd_done(cmd, ret, 0, issue_flags); + pr_devel("%s: complete: cmd op %d, tag %d ret %x io_flags %x\n", + __func__, cmd_op, tag, ret, io->flags); +- return -EIOCBQUEUED; ++ return ret; + } + + static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub, +@@ -1940,7 +1939,10 @@ static inline int ublk_ch_uring_cmd_local(struct io_uring_cmd *cmd, + static void ublk_ch_uring_cmd_cb(struct io_uring_cmd *cmd, + unsigned int issue_flags) + { +- ublk_ch_uring_cmd_local(cmd, issue_flags); ++ int ret = ublk_ch_uring_cmd_local(cmd, issue_flags); ++ ++ if (ret != -EIOCBQUEUED) ++ io_uring_cmd_done(cmd, ret, 0, issue_flags); + } + + static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags) +@@ -3065,10 +3067,9 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd, + if (ub) + ublk_put_device(ub); + out: +- io_uring_cmd_done(cmd, ret, 0, issue_flags); + pr_devel("%s: cmd done ret %d cmd_op %x, dev id %d qid %d\n", + __func__, ret, cmd->cmd_op, header->dev_id, header->queue_id); +- return -EIOCBQUEUED; ++ return ret; + } + + static const struct file_operations ublk_ctl_fops = { +-- +2.39.5 + diff --git a/queue-6.12/ublk-enforce-ublks_max-only-for-unprivileged-devices.patch b/queue-6.12/ublk-enforce-ublks_max-only-for-unprivileged-devices.patch new file mode 100644 index 0000000000..f4a0d39c9f --- /dev/null +++ b/queue-6.12/ublk-enforce-ublks_max-only-for-unprivileged-devices.patch @@ -0,0 +1,136 @@ +From a90c67cc873985c8bf1e5228bfb9f429f21041a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 21:31:48 -0700 +Subject: ublk: enforce ublks_max only for unprivileged devices + +From: Uday Shankar + +[ Upstream commit 80bdfbb3545b6f16680a72c825063d08a6b44c7a ] + +Commit 403ebc877832 ("ublk_drv: add module parameter of ublks_max for +limiting max allowed ublk dev"), claimed ublks_max was added to prevent +a DoS situation with an untrusted user creating too many ublk devices. +If that's the case, ublks_max should only restrict the number of +unprivileged ublk devices in the system. Enforce the limit only for +unprivileged ublk devices, and rename variables accordingly. Leave the +external-facing parameter name unchanged, since changing it may break +systems which use it (but still update its documentation to reflect its +new meaning). + +As a result of this change, in a system where there are only normal +(non-unprivileged) devices, the maximum number of such devices is +increased to 1 << MINORBITS, or 1048576. That ought to be enough for +anyone, right? + +Signed-off-by: Uday Shankar +Reviewed-by: Ming Lei +Link: https://lore.kernel.org/r/20250228-ublks_max-v1-1-04b7379190c0@purestorage.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/block/ublk_drv.c | 42 ++++++++++++++++++++++++++-------------- + 1 file changed, 27 insertions(+), 15 deletions(-) + +diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c +index 38b9e485e520d..5ec5d580ef506 100644 +--- a/drivers/block/ublk_drv.c ++++ b/drivers/block/ublk_drv.c +@@ -484,15 +484,17 @@ static wait_queue_head_t ublk_idr_wq; /* wait until one idr is freed */ + + static DEFINE_MUTEX(ublk_ctl_mutex); + ++ ++#define UBLK_MAX_UBLKS UBLK_MINORS ++ + /* +- * Max ublk devices allowed to add ++ * Max unprivileged ublk devices allowed to add + * + * It can be extended to one per-user limit in future or even controlled + * by cgroup. + */ +-#define UBLK_MAX_UBLKS UBLK_MINORS +-static unsigned int ublks_max = 64; +-static unsigned int ublks_added; /* protected by ublk_ctl_mutex */ ++static unsigned int unprivileged_ublks_max = 64; ++static unsigned int unprivileged_ublks_added; /* protected by ublk_ctl_mutex */ + + static struct miscdevice ublk_misc; + +@@ -2203,7 +2205,8 @@ static int ublk_add_chdev(struct ublk_device *ub) + if (ret) + goto fail; + +- ublks_added++; ++ if (ub->dev_info.flags & UBLK_F_UNPRIVILEGED_DEV) ++ unprivileged_ublks_added++; + return 0; + fail: + put_device(dev); +@@ -2241,12 +2244,17 @@ static int ublk_add_tag_set(struct ublk_device *ub) + + static void ublk_remove(struct ublk_device *ub) + { ++ bool unprivileged; ++ + ublk_stop_dev(ub); + cancel_work_sync(&ub->stop_work); + cancel_work_sync(&ub->quiesce_work); + cdev_device_del(&ub->cdev, &ub->cdev_dev); ++ unprivileged = ub->dev_info.flags & UBLK_F_UNPRIVILEGED_DEV; + ublk_put_device(ub); +- ublks_added--; ++ ++ if (unprivileged) ++ unprivileged_ublks_added--; + } + + static struct ublk_device *ublk_get_device_from_id(int idx) +@@ -2495,7 +2503,8 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd) + return ret; + + ret = -EACCES; +- if (ublks_added >= ublks_max) ++ if ((info.flags & UBLK_F_UNPRIVILEGED_DEV) && ++ unprivileged_ublks_added >= unprivileged_ublks_max) + goto out_unlock; + + ret = -ENOMEM; +@@ -3123,23 +3132,26 @@ static void __exit ublk_exit(void) + module_init(ublk_init); + module_exit(ublk_exit); + +-static int ublk_set_max_ublks(const char *buf, const struct kernel_param *kp) ++static int ublk_set_max_unprivileged_ublks(const char *buf, ++ const struct kernel_param *kp) + { + return param_set_uint_minmax(buf, kp, 0, UBLK_MAX_UBLKS); + } + +-static int ublk_get_max_ublks(char *buf, const struct kernel_param *kp) ++static int ublk_get_max_unprivileged_ublks(char *buf, ++ const struct kernel_param *kp) + { +- return sysfs_emit(buf, "%u\n", ublks_max); ++ return sysfs_emit(buf, "%u\n", unprivileged_ublks_max); + } + +-static const struct kernel_param_ops ublk_max_ublks_ops = { +- .set = ublk_set_max_ublks, +- .get = ublk_get_max_ublks, ++static const struct kernel_param_ops ublk_max_unprivileged_ublks_ops = { ++ .set = ublk_set_max_unprivileged_ublks, ++ .get = ublk_get_max_unprivileged_ublks, + }; + +-module_param_cb(ublks_max, &ublk_max_ublks_ops, &ublks_max, 0644); +-MODULE_PARM_DESC(ublks_max, "max number of ublk devices allowed to add(default: 64)"); ++module_param_cb(ublks_max, &ublk_max_unprivileged_ublks_ops, ++ &unprivileged_ublks_max, 0644); ++MODULE_PARM_DESC(ublks_max, "max number of unprivileged ublk devices allowed to add(default: 64)"); + + MODULE_AUTHOR("Ming Lei "); + MODULE_DESCRIPTION("Userspace block device"); +-- +2.39.5 + diff --git a/queue-6.12/um-store-full-csgsfs-and-ss-register-from-mcontext.patch b/queue-6.12/um-store-full-csgsfs-and-ss-register-from-mcontext.patch new file mode 100644 index 0000000000..776c12c5c0 --- /dev/null +++ b/queue-6.12/um-store-full-csgsfs-and-ss-register-from-mcontext.patch @@ -0,0 +1,40 @@ +From ad85e4dca18fdd467c10fdfdf1e08cd0e1e2a351 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 19:18:19 +0100 +Subject: um: Store full CSGSFS and SS register from mcontext + +From: Benjamin Berg + +[ Upstream commit cef721e0d53d2b64f2ba177c63a0dfdd7c0daf17 ] + +Doing this allows using registers as retrieved from an mcontext to be +pushed to a process using PTRACE_SETREGS. + +It is not entirely clear to me why CSGSFS was masked. Doing so creates +issues when using the mcontext as process state in seccomp and simply +copying the register appears to work perfectly fine for ptrace. + +Signed-off-by: Benjamin Berg +Link: https://patch.msgid.link/20250224181827.647129-2-benjamin@sipsolutions.net +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + arch/x86/um/os-Linux/mcontext.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/arch/x86/um/os-Linux/mcontext.c b/arch/x86/um/os-Linux/mcontext.c +index e80ab7d281177..1b0d95328b2c7 100644 +--- a/arch/x86/um/os-Linux/mcontext.c ++++ b/arch/x86/um/os-Linux/mcontext.c +@@ -27,7 +27,6 @@ void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc) + COPY(RIP); + COPY2(EFLAGS, EFL); + COPY2(CS, CSGSFS); +- regs->gp[CS / sizeof(unsigned long)] &= 0xffff; +- regs->gp[CS / sizeof(unsigned long)] |= 3; ++ regs->gp[SS / sizeof(unsigned long)] = mc->gregs[REG_CSGSFS] >> 48; + #endif + } +-- +2.39.5 + diff --git a/queue-6.12/um-update-min_low_pfn-to-match-changes-in-uml_reserv.patch b/queue-6.12/um-update-min_low_pfn-to-match-changes-in-uml_reserv.patch new file mode 100644 index 0000000000..3206599cd9 --- /dev/null +++ b/queue-6.12/um-update-min_low_pfn-to-match-changes-in-uml_reserv.patch @@ -0,0 +1,36 @@ +From 7ad9baf4ee5f0774501256ce0dfb785fe206e4de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 12:18:55 +0800 +Subject: um: Update min_low_pfn to match changes in uml_reserved + +From: Tiwei Bie + +[ Upstream commit e82cf3051e6193f61e03898f8dba035199064d36 ] + +When uml_reserved is updated, min_low_pfn must also be updated +accordingly. Otherwise, min_low_pfn will not accurately reflect +the lowest available PFN. + +Signed-off-by: Tiwei Bie +Link: https://patch.msgid.link/20250221041855.1156109-1-tiwei.btw@antgroup.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + arch/um/kernel/mem.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c +index a5b4fe2ad9315..6ca9ea4a230bc 100644 +--- a/arch/um/kernel/mem.c ++++ b/arch/um/kernel/mem.c +@@ -70,6 +70,7 @@ void __init mem_init(void) + map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0); + memblock_free((void *)brk_end, uml_reserved - brk_end); + uml_reserved = brk_end; ++ min_low_pfn = PFN_UP(__pa(uml_reserved)); + + /* this will put all low memory onto the freelists */ + memblock_free_all(); +-- +2.39.5 + diff --git a/queue-6.12/usb-xhci-don-t-change-the-status-of-stalled-tds-on-f.patch b/queue-6.12/usb-xhci-don-t-change-the-status-of-stalled-tds-on-f.patch new file mode 100644 index 0000000000..d76612ac21 --- /dev/null +++ b/queue-6.12/usb-xhci-don-t-change-the-status-of-stalled-tds-on-f.patch @@ -0,0 +1,68 @@ +From ab919c30185c3182a9727af4cee5bcf4c3f41418 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 17:45:50 +0200 +Subject: usb: xhci: Don't change the status of stalled TDs on failed Stop EP + +From: Michal Pecio + +[ Upstream commit dfc88357b6b6356dadea06b2c0bc8041f5e11720 ] + +When the device stalls an endpoint, current TD is assigned -EPIPE +status and Reset Endpoint is queued. If a Stop Endpoint is pending +at the time, it will run before Reset Endpoint and fail due to the +stall. Its handler will change TD's status to -EPROTO before Reset +Endpoint handler runs and initiates giveback. + +Check if the stall has already been handled and don't try to do it +again. Since xhci_handle_halted_endpoint() performs this check too, +not overwriting td->status is the only difference. + +I haven't seen this case yet, but I have seen a related one where +the xHC has already executed Reset Endpoint, EP Context state is +now Stopped and EP_HALTED is set. If the xHC took a bit longer to +execute Reset Endpoint, said case would become this one. + +Signed-off-by: Michal Pecio +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20250311154551.4035726-3-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-ring.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index 3e70e4f6bf083..fbc8419a54730 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1156,7 +1156,14 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, + */ + switch (GET_EP_CTX_STATE(ep_ctx)) { + case EP_STATE_HALTED: +- xhci_dbg(xhci, "Stop ep completion raced with stall, reset ep\n"); ++ xhci_dbg(xhci, "Stop ep completion raced with stall\n"); ++ /* ++ * If the halt happened before Stop Endpoint failed, its transfer event ++ * should have already been handled and Reset Endpoint should be pending. ++ */ ++ if (ep->ep_state & EP_HALTED) ++ goto reset_done; ++ + if (ep->ep_state & EP_HAS_STREAMS) { + reset_type = EP_SOFT_RESET; + } else { +@@ -1167,8 +1174,11 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, + } + /* reset ep, reset handler cleans up cancelled tds */ + err = xhci_handle_halted_endpoint(xhci, ep, td, reset_type); ++ xhci_dbg(xhci, "Stop ep completion resetting ep, status %d\n", err); + if (err) + break; ++reset_done: ++ /* Reset EP handler will clean up cancelled TDs */ + ep->ep_state &= ~EP_STOP_CMD_PENDING; + return; + case EP_STATE_STOPPED: +-- +2.39.5 + diff --git a/queue-6.12/usb-xhci-set-page-size-to-the-xhci-supported-size.patch b/queue-6.12/usb-xhci-set-page-size-to-the-xhci-supported-size.patch new file mode 100644 index 0000000000..761fe051b9 --- /dev/null +++ b/queue-6.12/usb-xhci-set-page-size-to-the-xhci-supported-size.patch @@ -0,0 +1,126 @@ +From 001fdaaa34664b82d493cf4e28c9232c7b534576 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 16:49:48 +0200 +Subject: usb: xhci: set page size to the xHCI-supported size + +From: Niklas Neronin + +[ Upstream commit 68c1f1671650b49bbd26e6a65ddcf33f2565efa3 ] + +The current xHCI driver does not validate whether a page size of 4096 +bytes is supported. Address the issue by setting the page size to the +value supported by the xHCI controller, as read from the Page Size +register. In the event of an unexpected value; default to a 4K page size. + +Additionally, this commit removes unnecessary debug messages and instead +prints the supported and used page size once. + +The xHCI controller supports page sizes of (2^{(n+12)}) bytes, where 'n' +is the Page Size Bit. Only one page size is supported, with a maximum +page size of 128 KB. + +Signed-off-by: Niklas Neronin +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20250306144954.3507700-10-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-mem.c | 34 ++++++++++++++++++---------------- + drivers/usb/host/xhci.h | 8 ++++---- + 2 files changed, 22 insertions(+), 20 deletions(-) + +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index 8c26275696df9..f9c51e0f2e37c 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -1959,7 +1959,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) + xhci->interrupters = NULL; + + xhci->page_size = 0; +- xhci->page_shift = 0; + xhci->usb2_rhub.bus_state.bus_suspended = 0; + xhci->usb3_rhub.bus_state.bus_suspended = 0; + } +@@ -2378,6 +2377,22 @@ xhci_create_secondary_interrupter(struct usb_hcd *hcd, unsigned int segs, + } + EXPORT_SYMBOL_GPL(xhci_create_secondary_interrupter); + ++static void xhci_hcd_page_size(struct xhci_hcd *xhci) ++{ ++ u32 page_size; ++ ++ page_size = readl(&xhci->op_regs->page_size) & XHCI_PAGE_SIZE_MASK; ++ if (!is_power_of_2(page_size)) { ++ xhci_warn(xhci, "Invalid page size register = 0x%x\n", page_size); ++ /* Fallback to 4K page size, since that's common */ ++ page_size = 1; ++ } ++ ++ xhci->page_size = page_size << 12; ++ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "HCD page size set to %iK", ++ xhci->page_size >> 10); ++} ++ + int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) + { + struct xhci_interrupter *ir; +@@ -2385,7 +2400,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) + dma_addr_t dma; + unsigned int val, val2; + u64 val_64; +- u32 page_size, temp; ++ u32 temp; + int i; + + INIT_LIST_HEAD(&xhci->cmd_list); +@@ -2394,20 +2409,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) + INIT_DELAYED_WORK(&xhci->cmd_timer, xhci_handle_command_timeout); + init_completion(&xhci->cmd_ring_stop_completion); + +- page_size = readl(&xhci->op_regs->page_size); +- xhci_dbg_trace(xhci, trace_xhci_dbg_init, +- "Supported page size register = 0x%x", page_size); +- val = ffs(page_size) - 1; +- if (val < 16) +- xhci_dbg_trace(xhci, trace_xhci_dbg_init, +- "Supported page size of %iK", (1 << (val + 12)) / 1024); +- else +- xhci_warn(xhci, "WARN: no supported page size\n"); +- /* Use 4K pages, since that's common and the minimum the HC supports */ +- xhci->page_shift = 12; +- xhci->page_size = 1 << xhci->page_shift; +- xhci_dbg_trace(xhci, trace_xhci_dbg_init, +- "HCD page size set to %iK", xhci->page_size / 1024); ++ xhci_hcd_page_size(xhci); + + /* + * Program the Number of Device Slots Enabled field in the CONFIG +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 2a954efa53e80..c4d5b90ef90a8 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -211,6 +211,9 @@ struct xhci_op_regs { + #define CONFIG_CIE (1 << 9) + /* bits 10:31 - reserved and should be preserved */ + ++/* bits 15:0 - HCD page shift bit */ ++#define XHCI_PAGE_SIZE_MASK 0xffff ++ + /** + * struct xhci_intr_reg - Interrupt Register Set + * @irq_pending: IMAN - Interrupt Management Register. Used to enable +@@ -1503,10 +1506,7 @@ struct xhci_hcd { + u16 max_interrupters; + /* imod_interval in ns (I * 250ns) */ + u32 imod_interval; +- /* 4KB min, 128MB max */ +- int page_size; +- /* Valid values are 12 to 20, inclusive */ +- int page_shift; ++ u32 page_size; + /* MSI-X/MSI vectors */ + int nvecs; + /* optional clocks */ +-- +2.39.5 + diff --git a/queue-6.12/vdpa-mlx5-fix-mlx5_vdpa_get_config-endianness-on-big.patch b/queue-6.12/vdpa-mlx5-fix-mlx5_vdpa_get_config-endianness-on-big.patch new file mode 100644 index 0000000000..b534fa1114 --- /dev/null +++ b/queue-6.12/vdpa-mlx5-fix-mlx5_vdpa_get_config-endianness-on-big.patch @@ -0,0 +1,52 @@ +From ac813a8ecf94773fabcdf582b4365b15787a48b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 11:31:27 -0600 +Subject: vdpa/mlx5: Fix mlx5_vdpa_get_config() endianness on big-endian + machines +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Konstantin Shkolnyy + +[ Upstream commit 439252e167ac45a5d46f573aac1da7d8f3e051ad ] + +mlx5_vdpa_dev_add() doesn’t initialize mvdev->actual_features. It’s +initialized later by mlx5_vdpa_set_driver_features(). However, +mlx5_vdpa_get_config() depends on the VIRTIO_F_VERSION_1 flag in +actual_features, to return data with correct endianness. When it’s called +before mlx5_vdpa_set_driver_features(), the data are incorrectly returned +as big-endian on big-endian machines, while QEMU then interprets them as +little-endian. + +The fix is to initialize this VIRTIO_F_VERSION_1 as early as possible, +especially considering that mlx5_vdpa_dev_add() insists on this flag to +always be set anyway. + +Signed-off-by: Konstantin Shkolnyy +Message-Id: <20250204173127.166673-1-kshk@linux.ibm.com> +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Dragos Tatulea +Acked-by: Jason Wang +Signed-off-by: Sasha Levin +--- + drivers/vdpa/mlx5/net/mlx5_vnet.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c +index 5f581e71e2010..76aedac37a788 100644 +--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c ++++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c +@@ -3884,6 +3884,9 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name, + ndev->mvdev.max_vqs = max_vqs; + mvdev = &ndev->mvdev; + mvdev->mdev = mdev; ++ /* cpu_to_mlx5vdpa16() below depends on this flag */ ++ mvdev->actual_features = ++ (device_features & BIT_ULL(VIRTIO_F_VERSION_1)); + + ndev->vqs = kcalloc(max_vqs, sizeof(*ndev->vqs), GFP_KERNEL); + ndev->event_cbs = kcalloc(max_vqs + 1, sizeof(*ndev->event_cbs), GFP_KERNEL); +-- +2.39.5 + diff --git a/queue-6.12/vfio-pci-handle-intx-irq_notconnected.patch b/queue-6.12/vfio-pci-handle-intx-irq_notconnected.patch new file mode 100644 index 0000000000..b9516d2697 --- /dev/null +++ b/queue-6.12/vfio-pci-handle-intx-irq_notconnected.patch @@ -0,0 +1,84 @@ +From 599f1568fe8d98f804e5b3cc4b210385085d1b54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 17:06:21 -0600 +Subject: vfio/pci: Handle INTx IRQ_NOTCONNECTED + +From: Alex Williamson + +[ Upstream commit 860be250fc32de9cb24154bf21b4e36f40925707 ] + +Some systems report INTx as not routed by setting pdev->irq to +IRQ_NOTCONNECTED, resulting in a -ENOTCONN error when trying to +setup eventfd signaling. Include this in the set of conditions +for which the PIN register is virtualized to zero. + +Additionally consolidate vfio_pci_get_irq_count() to use this +virtualized value in reporting INTx support via ioctl and sanity +checking ioctl paths since pdev->irq is re-used when the device +is in MSI mode. + +The combination of these results in both the config space of the +device and the ioctl interface behaving as if the device does not +support INTx. + +Reviewed-by: Kevin Tian +Link: https://lore.kernel.org/r/20250311230623.1264283-1-alex.williamson@redhat.com +Signed-off-by: Alex Williamson +Signed-off-by: Sasha Levin +--- + drivers/vfio/pci/vfio_pci_config.c | 3 ++- + drivers/vfio/pci/vfio_pci_core.c | 10 +--------- + drivers/vfio/pci/vfio_pci_intrs.c | 2 +- + 3 files changed, 4 insertions(+), 11 deletions(-) + +diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c +index ea2745c1ac5e6..8ea38e7421df4 100644 +--- a/drivers/vfio/pci/vfio_pci_config.c ++++ b/drivers/vfio/pci/vfio_pci_config.c +@@ -1813,7 +1813,8 @@ int vfio_config_init(struct vfio_pci_core_device *vdev) + cpu_to_le16(PCI_COMMAND_MEMORY); + } + +- if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx) ++ if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx || ++ vdev->pdev->irq == IRQ_NOTCONNECTED) + vconfig[PCI_INTERRUPT_PIN] = 0; + + ret = vfio_cap_init(vdev); +diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c +index c9eaba2276365..087c273a547fa 100644 +--- a/drivers/vfio/pci/vfio_pci_core.c ++++ b/drivers/vfio/pci/vfio_pci_core.c +@@ -727,15 +727,7 @@ EXPORT_SYMBOL_GPL(vfio_pci_core_finish_enable); + static int vfio_pci_get_irq_count(struct vfio_pci_core_device *vdev, int irq_type) + { + if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) { +- u8 pin; +- +- if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || +- vdev->nointx || vdev->pdev->is_virtfn) +- return 0; +- +- pci_read_config_byte(vdev->pdev, PCI_INTERRUPT_PIN, &pin); +- +- return pin ? 1 : 0; ++ return vdev->vconfig[PCI_INTERRUPT_PIN] ? 1 : 0; + } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) { + u8 pos; + u16 flags; +diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c +index 8382c58343356..565966351dfad 100644 +--- a/drivers/vfio/pci/vfio_pci_intrs.c ++++ b/drivers/vfio/pci/vfio_pci_intrs.c +@@ -259,7 +259,7 @@ static int vfio_intx_enable(struct vfio_pci_core_device *vdev, + if (!is_irq_none(vdev)) + return -EINVAL; + +- if (!pdev->irq) ++ if (!pdev->irq || pdev->irq == IRQ_NOTCONNECTED) + return -ENODEV; + + name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-intx(%s)", pci_name(pdev)); +-- +2.39.5 + diff --git a/queue-6.12/vhost-scsi-protect-vq-log_used-with-vq-mutex.patch b/queue-6.12/vhost-scsi-protect-vq-log_used-with-vq-mutex.patch new file mode 100644 index 0000000000..40313591fe --- /dev/null +++ b/queue-6.12/vhost-scsi-protect-vq-log_used-with-vq-mutex.patch @@ -0,0 +1,82 @@ +From be3a28326ee30cad49baa936163f7c49fb3f6ad8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Apr 2025 23:29:46 -0700 +Subject: vhost-scsi: protect vq->log_used with vq->mutex + +From: Dongli Zhang + +[ Upstream commit f591cf9fce724e5075cc67488c43c6e39e8cbe27 ] + +The vhost-scsi completion path may access vq->log_base when vq->log_used is +already set to false. + + vhost-thread QEMU-thread + +vhost_scsi_complete_cmd_work() +-> vhost_add_used() + -> vhost_add_used_n() + if (unlikely(vq->log_used)) + QEMU disables vq->log_used + via VHOST_SET_VRING_ADDR. + mutex_lock(&vq->mutex); + vq->log_used = false now! + mutex_unlock(&vq->mutex); + + QEMU gfree(vq->log_base) + log_used() + -> log_write(vq->log_base) + +Assuming the VMM is QEMU. The vq->log_base is from QEMU userpace and can be +reclaimed via gfree(). As a result, this causes invalid memory writes to +QEMU userspace. + +The control queue path has the same issue. + +Signed-off-by: Dongli Zhang +Acked-by: Jason Wang +Reviewed-by: Mike Christie +Message-Id: <20250403063028.16045-2-dongli.zhang@oracle.com> +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Sasha Levin +--- + drivers/vhost/scsi.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c +index 35a03306d1345..ecad2f53b7635 100644 +--- a/drivers/vhost/scsi.c ++++ b/drivers/vhost/scsi.c +@@ -571,6 +571,9 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) + int ret; + + llnode = llist_del_all(&svq->completion_list); ++ ++ mutex_lock(&svq->vq.mutex); ++ + llist_for_each_entry_safe(cmd, t, llnode, tvc_completion_list) { + se_cmd = &cmd->tvc_se_cmd; + +@@ -604,6 +607,8 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) + vhost_scsi_release_cmd_res(se_cmd); + } + ++ mutex_unlock(&svq->vq.mutex); ++ + if (signal) + vhost_signal(&svq->vs->dev, &svq->vq); + } +@@ -1346,8 +1351,11 @@ static void vhost_scsi_tmf_resp_work(struct vhost_work *work) + else + resp_code = VIRTIO_SCSI_S_FUNCTION_REJECTED; + ++ mutex_lock(&tmf->svq->vq.mutex); + vhost_scsi_send_tmf_resp(tmf->vhost, &tmf->svq->vq, tmf->in_iovs, + tmf->vq_desc, &tmf->resp_iov, resp_code); ++ mutex_unlock(&tmf->svq->vq.mutex); ++ + vhost_scsi_release_tmf_res(tmf); + } + +-- +2.39.5 + diff --git a/queue-6.12/vhost-scsi-return-queue-full-for-page-alloc-failures.patch b/queue-6.12/vhost-scsi-return-queue-full-for-page-alloc-failures.patch new file mode 100644 index 0000000000..e4f9f6a721 --- /dev/null +++ b/queue-6.12/vhost-scsi-return-queue-full-for-page-alloc-failures.patch @@ -0,0 +1,79 @@ +From ce67bfc522b2d6ba2c694ae607336d34a4173ecb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Dec 2024 13:15:11 -0600 +Subject: vhost-scsi: Return queue full for page alloc failures during copy + +From: Mike Christie + +[ Upstream commit 891b99eab0f89dbe08d216f4ab71acbeaf7a3102 ] + +This has us return queue full if we can't allocate a page during the +copy operation so the initiator can retry. + +Signed-off-by: Mike Christie +Message-Id: <20241203191705.19431-5-michael.christie@oracle.com> +Signed-off-by: Michael S. Tsirkin +Acked-by: Stefan Hajnoczi +Signed-off-by: Sasha Levin +--- + drivers/vhost/scsi.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c +index ecad2f53b7635..38d243d914d00 100644 +--- a/drivers/vhost/scsi.c ++++ b/drivers/vhost/scsi.c +@@ -762,7 +762,7 @@ vhost_scsi_copy_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter, + size_t len = iov_iter_count(iter); + unsigned int nbytes = 0; + struct page *page; +- int i; ++ int i, ret; + + if (cmd->tvc_data_direction == DMA_FROM_DEVICE) { + cmd->saved_iter_addr = dup_iter(&cmd->saved_iter, iter, +@@ -775,6 +775,7 @@ vhost_scsi_copy_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter, + page = alloc_page(GFP_KERNEL); + if (!page) { + i--; ++ ret = -ENOMEM; + goto err; + } + +@@ -782,8 +783,10 @@ vhost_scsi_copy_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter, + sg_set_page(&sg[i], page, nbytes, 0); + + if (cmd->tvc_data_direction == DMA_TO_DEVICE && +- copy_page_from_iter(page, 0, nbytes, iter) != nbytes) ++ copy_page_from_iter(page, 0, nbytes, iter) != nbytes) { ++ ret = -EFAULT; + goto err; ++ } + + len -= nbytes; + } +@@ -798,7 +801,7 @@ vhost_scsi_copy_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter, + for (; i >= 0; i--) + __free_page(sg_page(&sg[i])); + kfree(cmd->saved_iter_addr); +- return -ENOMEM; ++ return ret; + } + + static int +@@ -1282,9 +1285,9 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) + " %d\n", cmd, exp_data_len, prot_bytes, data_direction); + + if (data_direction != DMA_NONE) { +- if (unlikely(vhost_scsi_mapal(cmd, prot_bytes, +- &prot_iter, exp_data_len, +- &data_iter))) { ++ ret = vhost_scsi_mapal(cmd, prot_bytes, &prot_iter, ++ exp_data_len, &data_iter); ++ if (unlikely(ret)) { + vq_err(vq, "Failed to map iov to sgl\n"); + vhost_scsi_release_cmd_res(&cmd->tvc_se_cmd); + goto err; +-- +2.39.5 + diff --git a/queue-6.12/vhost_task-fix-vhost_task_create-documentation.patch b/queue-6.12/vhost_task-fix-vhost_task_create-documentation.patch new file mode 100644 index 0000000000..e062ee3c4a --- /dev/null +++ b/queue-6.12/vhost_task-fix-vhost_task_create-documentation.patch @@ -0,0 +1,40 @@ +From f378c9e3e4ef85e66bb0aac8ccafad71c0fb5e72 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Mar 2025 13:44:35 +0100 +Subject: vhost_task: fix vhost_task_create() documentation + +From: Stefano Garzarella + +[ Upstream commit fec0abf52609c20279243699d08b660c142ce0aa ] + +Commit cb380909ae3b ("vhost: return task creation error instead of NULL") +changed the return value of vhost_task_create(), but did not update the +documentation. + +Reflect the change in the documentation: on an error, vhost_task_create() +returns an ERR_PTR() and no longer NULL. + +Signed-off-by: Stefano Garzarella +Message-Id: <20250327124435.142831-1-sgarzare@redhat.com> +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Sasha Levin +--- + kernel/vhost_task.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/vhost_task.c b/kernel/vhost_task.c +index 2ef2e1b800916..2f844c279a3e0 100644 +--- a/kernel/vhost_task.c ++++ b/kernel/vhost_task.c +@@ -111,7 +111,7 @@ EXPORT_SYMBOL_GPL(vhost_task_stop); + * @arg: data to be passed to fn and handled_kill + * @name: the thread's name + * +- * This returns a specialized task for use by the vhost layer or NULL on ++ * This returns a specialized task for use by the vhost layer or ERR_PTR() on + * failure. The returned task is inactive, and the caller must fire it up + * through vhost_task_start(). + */ +-- +2.39.5 + diff --git a/queue-6.12/virtio_ring-fix-data-race-by-tagging-event_triggered.patch b/queue-6.12/virtio_ring-fix-data-race-by-tagging-event_triggered.patch new file mode 100644 index 0000000000..44ef3a28ed --- /dev/null +++ b/queue-6.12/virtio_ring-fix-data-race-by-tagging-event_triggered.patch @@ -0,0 +1,71 @@ +From edcd4e5d7c5772a609bede9e26e49dbf70acddee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 21:04:12 +0800 +Subject: virtio_ring: Fix data race by tagging event_triggered as racy for + KCSAN + +From: Zhongqiu Han + +[ Upstream commit 2e2f925fe737576df2373931c95e1a2b66efdfef ] + +syzbot reports a data-race when accessing the event_triggered, here is the +simplified stack when the issue occurred: + +================================================================== +BUG: KCSAN: data-race in virtqueue_disable_cb / virtqueue_enable_cb_delayed + +write to 0xffff8881025bc452 of 1 bytes by task 3288 on cpu 0: + virtqueue_enable_cb_delayed+0x42/0x3c0 drivers/virtio/virtio_ring.c:2653 + start_xmit+0x230/0x1310 drivers/net/virtio_net.c:3264 + __netdev_start_xmit include/linux/netdevice.h:5151 [inline] + netdev_start_xmit include/linux/netdevice.h:5160 [inline] + xmit_one net/core/dev.c:3800 [inline] + +read to 0xffff8881025bc452 of 1 bytes by interrupt on cpu 1: + virtqueue_disable_cb_split drivers/virtio/virtio_ring.c:880 [inline] + virtqueue_disable_cb+0x92/0x180 drivers/virtio/virtio_ring.c:2566 + skb_xmit_done+0x5f/0x140 drivers/net/virtio_net.c:777 + vring_interrupt+0x161/0x190 drivers/virtio/virtio_ring.c:2715 + __handle_irq_event_percpu+0x95/0x490 kernel/irq/handle.c:158 + handle_irq_event_percpu kernel/irq/handle.c:193 [inline] + +value changed: 0x01 -> 0x00 +================================================================== + +When the data race occurs, the function virtqueue_enable_cb_delayed() sets +event_triggered to false, and virtqueue_disable_cb_split/packed() reads it +as false due to the race condition. Since event_triggered is an unreliable +hint used for optimization, this should only cause the driver temporarily +suggest that the device not send an interrupt notification when the event +index is used. + +Fix this KCSAN reported data-race issue by explicitly tagging the access as +data_racy. + +Reported-by: syzbot+efe683d57990864b8c8e@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/67c7761a.050a0220.15b4b9.0018.GAE@google.com/ +Signed-off-by: Zhongqiu Han +Message-Id: <20250312130412.3516307-1-quic_zhonhan@quicinc.com> +Signed-off-by: Michael S. Tsirkin +Acked-by: Jason Wang +Signed-off-by: Sasha Levin +--- + drivers/virtio/virtio_ring.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c +index 1f8a322eb00be..147926c8bae09 100644 +--- a/drivers/virtio/virtio_ring.c ++++ b/drivers/virtio/virtio_ring.c +@@ -2530,7 +2530,7 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *_vq) + struct vring_virtqueue *vq = to_vvq(_vq); + + if (vq->event_triggered) +- vq->event_triggered = false; ++ data_race(vq->event_triggered = false); + + return vq->packed_ring ? virtqueue_enable_cb_delayed_packed(_vq) : + virtqueue_enable_cb_delayed_split(_vq); +-- +2.39.5 + diff --git a/queue-6.12/vxlan-annotate-fdb-data-races.patch b/queue-6.12/vxlan-annotate-fdb-data-races.patch new file mode 100644 index 0000000000..135373b2a6 --- /dev/null +++ b/queue-6.12/vxlan-annotate-fdb-data-races.patch @@ -0,0 +1,144 @@ +From ace72a73123362e6535f029b324eb26418ac15b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 16:55:42 +0200 +Subject: vxlan: Annotate FDB data races + +From: Ido Schimmel + +[ Upstream commit f6205f8215f12a96518ac9469ff76294ae7bd612 ] + +The 'used' and 'updated' fields in the FDB entry structure can be +accessed concurrently by multiple threads, leading to reports such as +[1]. Can be reproduced using [2]. + +Suppress these reports by annotating these accesses using +READ_ONCE() / WRITE_ONCE(). + +[1] +BUG: KCSAN: data-race in vxlan_xmit / vxlan_xmit + +write to 0xffff942604d263a8 of 8 bytes by task 286 on cpu 0: + vxlan_xmit+0xb29/0x2380 + dev_hard_start_xmit+0x84/0x2f0 + __dev_queue_xmit+0x45a/0x1650 + packet_xmit+0x100/0x150 + packet_sendmsg+0x2114/0x2ac0 + __sys_sendto+0x318/0x330 + __x64_sys_sendto+0x76/0x90 + x64_sys_call+0x14e8/0x1c00 + do_syscall_64+0x9e/0x1a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +read to 0xffff942604d263a8 of 8 bytes by task 287 on cpu 2: + vxlan_xmit+0xadf/0x2380 + dev_hard_start_xmit+0x84/0x2f0 + __dev_queue_xmit+0x45a/0x1650 + packet_xmit+0x100/0x150 + packet_sendmsg+0x2114/0x2ac0 + __sys_sendto+0x318/0x330 + __x64_sys_sendto+0x76/0x90 + x64_sys_call+0x14e8/0x1c00 + do_syscall_64+0x9e/0x1a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +value changed: 0x00000000fffbac6e -> 0x00000000fffbac6f + +Reported by Kernel Concurrency Sanitizer on: +CPU: 2 UID: 0 PID: 287 Comm: mausezahn Not tainted 6.13.0-rc7-01544-gb4b270f11a02 #5 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-3.fc41 04/01/2014 + +[2] + #!/bin/bash + + set +H + echo whitelist > /sys/kernel/debug/kcsan + echo !vxlan_xmit > /sys/kernel/debug/kcsan + + ip link add name vx0 up type vxlan id 10010 dstport 4789 local 192.0.2.1 + bridge fdb add 00:11:22:33:44:55 dev vx0 self static dst 198.51.100.1 + taskset -c 0 mausezahn vx0 -a own -b 00:11:22:33:44:55 -c 0 -q & + taskset -c 2 mausezahn vx0 -a own -b 00:11:22:33:44:55 -c 0 -q & + +Reviewed-by: Petr Machata +Signed-off-by: Ido Schimmel +Reviewed-by: Eric Dumazet +Reviewed-by: Nikolay Aleksandrov +Link: https://patch.msgid.link/20250204145549.1216254-2-idosch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/vxlan/vxlan_core.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c +index 01f66760e1328..474faccf75fd9 100644 +--- a/drivers/net/vxlan/vxlan_core.c ++++ b/drivers/net/vxlan/vxlan_core.c +@@ -227,9 +227,9 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan, + be32_to_cpu(fdb->vni))) + goto nla_put_failure; + +- ci.ndm_used = jiffies_to_clock_t(now - fdb->used); ++ ci.ndm_used = jiffies_to_clock_t(now - READ_ONCE(fdb->used)); + ci.ndm_confirmed = 0; +- ci.ndm_updated = jiffies_to_clock_t(now - fdb->updated); ++ ci.ndm_updated = jiffies_to_clock_t(now - READ_ONCE(fdb->updated)); + ci.ndm_refcnt = 0; + + if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci)) +@@ -434,8 +434,8 @@ static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan, + struct vxlan_fdb *f; + + f = __vxlan_find_mac(vxlan, mac, vni); +- if (f && f->used != jiffies) +- f->used = jiffies; ++ if (f && READ_ONCE(f->used) != jiffies) ++ WRITE_ONCE(f->used, jiffies); + + return f; + } +@@ -1009,12 +1009,12 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan, + !(f->flags & NTF_VXLAN_ADDED_BY_USER)) { + if (f->state != state) { + f->state = state; +- f->updated = jiffies; ++ WRITE_ONCE(f->updated, jiffies); + notify = 1; + } + if (f->flags != fdb_flags) { + f->flags = fdb_flags; +- f->updated = jiffies; ++ WRITE_ONCE(f->updated, jiffies); + notify = 1; + } + } +@@ -1048,7 +1048,7 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan, + } + + if (ndm_flags & NTF_USE) +- f->used = jiffies; ++ WRITE_ONCE(f->used, jiffies); + + if (notify) { + if (rd == NULL) +@@ -1477,7 +1477,7 @@ static bool vxlan_snoop(struct net_device *dev, + src_mac, &rdst->remote_ip.sa, &src_ip->sa); + + rdst->remote_ip = *src_ip; +- f->updated = jiffies; ++ WRITE_ONCE(f->updated, jiffies); + vxlan_fdb_notify(vxlan, f, rdst, RTM_NEWNEIGH, true, NULL); + } else { + u32 hash_index = fdb_head_index(vxlan, src_mac, vni); +@@ -2825,7 +2825,7 @@ static void vxlan_cleanup(struct timer_list *t) + if (f->flags & NTF_EXT_LEARNED) + continue; + +- timeout = f->used + vxlan->cfg.age_interval * HZ; ++ timeout = READ_ONCE(f->used) + vxlan->cfg.age_interval * HZ; + if (time_before_eq(timeout, jiffies)) { + netdev_dbg(vxlan->dev, + "garbage collect %pM\n", +-- +2.39.5 + diff --git a/queue-6.12/vxlan-join-leave-mc-group-after-remote-changes.patch b/queue-6.12/vxlan-join-leave-mc-group-after-remote-changes.patch new file mode 100644 index 0000000000..7003faccb9 --- /dev/null +++ b/queue-6.12/vxlan-join-leave-mc-group-after-remote-changes.patch @@ -0,0 +1,113 @@ +From 576644915f40ebe078ae5b0775a49d23fda53177 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 17:18:21 +0100 +Subject: vxlan: Join / leave MC group after remote changes + +From: Petr Machata + +[ Upstream commit d42d543368343c0449a4e433b5f02e063a86209c ] + +When a vxlan netdevice is brought up, if its default remote is a multicast +address, the device joins the indicated group. + +Therefore when the multicast remote address changes, the device should +leave the current group and subscribe to the new one. Similarly when the +interface used for endpoint communication is changed in a situation when +multicast remote is configured. This is currently not done. + +Both vxlan_igmp_join() and vxlan_igmp_leave() can however fail. So it is +possible that with such fix, the netdevice will end up in an inconsistent +situation where the old group is not joined anymore, but joining the new +group fails. Should we join the new group first, and leave the old one +second, we might end up in the opposite situation, where both groups are +joined. Undoing any of this during rollback is going to be similarly +problematic. + +One solution would be to just forbid the change when the netdevice is up. +However in vnifilter mode, changing the group address is allowed, and these +problems are simply ignored (see vxlan_vni_update_group()): + + # ip link add name br up type bridge vlan_filtering 1 + # ip link add vx1 up master br type vxlan external vnifilter local 192.0.2.1 dev lo dstport 4789 + # bridge vni add dev vx1 vni 200 group 224.0.0.1 + # tcpdump -i lo & + # bridge vni add dev vx1 vni 200 group 224.0.0.2 + 18:55:46.523438 IP 0.0.0.0 > 224.0.0.22: igmp v3 report, 1 group record(s) + 18:55:46.943447 IP 0.0.0.0 > 224.0.0.22: igmp v3 report, 1 group record(s) + # bridge vni + dev vni group/remote + vx1 200 224.0.0.2 + +Having two different modes of operation for conceptually the same interface +is silly, so in this patch, just do what the vnifilter code does and deal +with the errors by crossing fingers real hard. + +The vnifilter code leaves old before joining new, and in case of join / +leave failures does not roll back the configuration changes that have +already been applied, but bails out of joining if it could not leave. Do +the same here: leave before join, apply changes unconditionally and do not +attempt to join if we couldn't leave. + +Signed-off-by: Petr Machata +Reviewed-by: Ido Schimmel +Reviewed-by: Nikolay Aleksandrov +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/vxlan/vxlan_core.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c +index 5e7cdd1b806fb..01f66760e1328 100644 +--- a/drivers/net/vxlan/vxlan_core.c ++++ b/drivers/net/vxlan/vxlan_core.c +@@ -4340,6 +4340,7 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], + struct netlink_ext_ack *extack) + { + struct vxlan_dev *vxlan = netdev_priv(dev); ++ bool rem_ip_changed, change_igmp; + struct net_device *lowerdev; + struct vxlan_config conf; + struct vxlan_rdst *dst; +@@ -4363,8 +4364,13 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], + if (err) + return err; + ++ rem_ip_changed = !vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip); ++ change_igmp = vxlan->dev->flags & IFF_UP && ++ (rem_ip_changed || ++ dst->remote_ifindex != conf.remote_ifindex); ++ + /* handle default dst entry */ +- if (!vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip)) { ++ if (rem_ip_changed) { + u32 hash_index = fdb_head_index(vxlan, all_zeros_mac, conf.vni); + + spin_lock_bh(&vxlan->hash_lock[hash_index]); +@@ -4408,6 +4414,9 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], + } + } + ++ if (change_igmp && vxlan_addr_multicast(&dst->remote_ip)) ++ err = vxlan_multicast_leave(vxlan); ++ + if (conf.age_interval != vxlan->cfg.age_interval) + mod_timer(&vxlan->age_timer, jiffies); + +@@ -4415,7 +4424,12 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], + if (lowerdev && lowerdev != dst->remote_dev) + dst->remote_dev = lowerdev; + vxlan_config_apply(dev, &conf, lowerdev, vxlan->net, true); +- return 0; ++ ++ if (!err && change_igmp && ++ vxlan_addr_multicast(&dst->remote_ip)) ++ err = vxlan_multicast_join(vxlan); ++ ++ return err; + } + + static void vxlan_dellink(struct net_device *dev, struct list_head *head) +-- +2.39.5 + diff --git a/queue-6.12/watchdog-aspeed-update-bootstatus-handling.patch b/queue-6.12/watchdog-aspeed-update-bootstatus-handling.patch new file mode 100644 index 0000000000..d9da841880 --- /dev/null +++ b/queue-6.12/watchdog-aspeed-update-bootstatus-handling.patch @@ -0,0 +1,182 @@ +From 1fd8fea7a5d3a95b6a0a26adc71bd656c455f453 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 17:37:37 +0800 +Subject: watchdog: aspeed: Update bootstatus handling + +From: Chin-Ting Kuo + +[ Upstream commit 5c03f9f4d36292150c14ebd90788c4d3273ed9dc ] + +The boot status in the watchdog device struct is updated during +controller probe stage. Application layer can get the boot status +through the command, cat /sys/class/watchdog/watchdogX/bootstatus. +The bootstatus can be, +WDIOF_CARDRESET => System is reset due to WDT timeout occurs. +Others => Other reset events, e.g., power on reset. + +On ASPEED platforms, boot status is recorded in the SCU registers. +- AST2400: Only a bit is used to represent system reset triggered by + any WDT controller. +- AST2500/AST2600: System reset triggered by different WDT controllers + can be distinguished by different SCU bits. + +Besides, on AST2400 and AST2500, since alternating boot event is +also triggered by using WDT timeout mechanism, it is classified +as WDIOF_CARDRESET. + +Signed-off-by: Chin-Ting Kuo +Reviewed-by: Andrew Jeffery +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/20250113093737.845097-2-chin-ting_kuo@aspeedtech.com +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +Signed-off-by: Sasha Levin +--- + drivers/watchdog/aspeed_wdt.c | 81 ++++++++++++++++++++++++++++++++++- + 1 file changed, 79 insertions(+), 2 deletions(-) + +diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c +index b4773a6aaf8cc..369635b38ca0e 100644 +--- a/drivers/watchdog/aspeed_wdt.c ++++ b/drivers/watchdog/aspeed_wdt.c +@@ -11,21 +11,30 @@ + #include + #include + #include ++#include + #include + #include + #include + #include ++#include + #include + + static bool nowayout = WATCHDOG_NOWAYOUT; + module_param(nowayout, bool, 0); + MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); ++struct aspeed_wdt_scu { ++ const char *compatible; ++ u32 reset_status_reg; ++ u32 wdt_reset_mask; ++ u32 wdt_reset_mask_shift; ++}; + + struct aspeed_wdt_config { + u32 ext_pulse_width_mask; + u32 irq_shift; + u32 irq_mask; ++ struct aspeed_wdt_scu scu; + }; + + struct aspeed_wdt { +@@ -39,18 +48,36 @@ static const struct aspeed_wdt_config ast2400_config = { + .ext_pulse_width_mask = 0xff, + .irq_shift = 0, + .irq_mask = 0, ++ .scu = { ++ .compatible = "aspeed,ast2400-scu", ++ .reset_status_reg = 0x3c, ++ .wdt_reset_mask = 0x1, ++ .wdt_reset_mask_shift = 1, ++ }, + }; + + static const struct aspeed_wdt_config ast2500_config = { + .ext_pulse_width_mask = 0xfffff, + .irq_shift = 12, + .irq_mask = GENMASK(31, 12), ++ .scu = { ++ .compatible = "aspeed,ast2500-scu", ++ .reset_status_reg = 0x3c, ++ .wdt_reset_mask = 0x1, ++ .wdt_reset_mask_shift = 2, ++ }, + }; + + static const struct aspeed_wdt_config ast2600_config = { + .ext_pulse_width_mask = 0xfffff, + .irq_shift = 0, + .irq_mask = GENMASK(31, 10), ++ .scu = { ++ .compatible = "aspeed,ast2600-scu", ++ .reset_status_reg = 0x74, ++ .wdt_reset_mask = 0xf, ++ .wdt_reset_mask_shift = 16, ++ }, + }; + + static const struct of_device_id aspeed_wdt_of_table[] = { +@@ -213,6 +240,56 @@ static int aspeed_wdt_restart(struct watchdog_device *wdd, + return 0; + } + ++static void aspeed_wdt_update_bootstatus(struct platform_device *pdev, ++ struct aspeed_wdt *wdt) ++{ ++ const struct resource *res; ++ struct aspeed_wdt_scu scu = wdt->cfg->scu; ++ struct regmap *scu_base; ++ u32 reset_mask_width; ++ u32 reset_mask_shift; ++ u32 idx = 0; ++ u32 status; ++ int ret; ++ ++ if (!of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt")) { ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ idx = ((intptr_t)wdt->base & 0x00000fff) / resource_size(res); ++ } ++ ++ scu_base = syscon_regmap_lookup_by_compatible(scu.compatible); ++ if (IS_ERR(scu_base)) { ++ wdt->wdd.bootstatus = WDIOS_UNKNOWN; ++ return; ++ } ++ ++ ret = regmap_read(scu_base, scu.reset_status_reg, &status); ++ if (ret) { ++ wdt->wdd.bootstatus = WDIOS_UNKNOWN; ++ return; ++ } ++ ++ reset_mask_width = hweight32(scu.wdt_reset_mask); ++ reset_mask_shift = scu.wdt_reset_mask_shift + ++ reset_mask_width * idx; ++ ++ if (status & (scu.wdt_reset_mask << reset_mask_shift)) ++ wdt->wdd.bootstatus = WDIOF_CARDRESET; ++ ++ /* clear wdt reset event flag */ ++ if (of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt") || ++ of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2500-wdt")) { ++ ret = regmap_read(scu_base, scu.reset_status_reg, &status); ++ if (!ret) { ++ status &= ~(scu.wdt_reset_mask << reset_mask_shift); ++ regmap_write(scu_base, scu.reset_status_reg, status); ++ } ++ } else { ++ regmap_write(scu_base, scu.reset_status_reg, ++ scu.wdt_reset_mask << reset_mask_shift); ++ } ++} ++ + /* access_cs0 shows if cs0 is accessible, hence the reverted bit */ + static ssize_t access_cs0_show(struct device *dev, + struct device_attribute *attr, char *buf) +@@ -458,10 +535,10 @@ static int aspeed_wdt_probe(struct platform_device *pdev) + writel(duration - 1, wdt->base + WDT_RESET_WIDTH); + } + ++ aspeed_wdt_update_bootstatus(pdev, wdt); ++ + status = readl(wdt->base + WDT_TIMEOUT_STATUS); + if (status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY) { +- wdt->wdd.bootstatus = WDIOF_CARDRESET; +- + if (of_device_is_compatible(np, "aspeed,ast2400-wdt") || + of_device_is_compatible(np, "aspeed,ast2500-wdt")) + wdt->wdd.groups = bswitch_groups; +-- +2.39.5 + diff --git a/queue-6.12/wifi-ath11k-use-dma_alloc_noncoherent-for-rx_tid-buf.patch b/queue-6.12/wifi-ath11k-use-dma_alloc_noncoherent-for-rx_tid-buf.patch new file mode 100644 index 0000000000..fd8938d201 --- /dev/null +++ b/queue-6.12/wifi-ath11k-use-dma_alloc_noncoherent-for-rx_tid-buf.patch @@ -0,0 +1,277 @@ +From c5775b6da8875b32f425f425ba1b13d3fe475d6c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 19 Jan 2025 22:12:19 +0530 +Subject: wifi: ath11k: Use dma_alloc_noncoherent for rx_tid buffer allocation + +From: P Praneesh + +[ Upstream commit eeadc6baf8b3dcd32787cc84f0473dc2a2850370 ] + +Currently, the driver allocates cacheable DMA buffers for the rx_tid +structure using kzalloc() and dma_map_single(). These buffers are +long-lived and can persist for the lifetime of the peer, which is not +advisable. Instead of using kzalloc() and dma_map_single() for allocating +cacheable DMA buffers, utilize the dma_alloc_noncoherent() helper for the +allocation of long-lived cacheable DMA buffers, such as the peer's rx_tid. +Since dma_alloc_noncoherent() returns unaligned physical and virtual +addresses, align them internally before use within the driver. This +ensures proper allocation of non-coherent memory through the kernel +helper. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3 + +Signed-off-by: P Praneesh +Tested-by: Tim Harvey +Link: https://patch.msgid.link/20250119164219.647059-3-quic_ppranees@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/dp.h | 6 +- + drivers/net/wireless/ath/ath11k/dp_rx.c | 117 +++++++++++------------- + 2 files changed, 58 insertions(+), 65 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h +index 65d2bc0687c88..eaf902c25e192 100644 +--- a/drivers/net/wireless/ath/ath11k/dp.h ++++ b/drivers/net/wireless/ath/ath11k/dp.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ + /* + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2023, 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef ATH11K_DP_H +@@ -20,7 +20,6 @@ struct ath11k_ext_irq_grp; + + struct dp_rx_tid { + u8 tid; +- u32 *vaddr; + dma_addr_t paddr; + u32 size; + u32 ba_win_sz; +@@ -37,6 +36,9 @@ struct dp_rx_tid { + /* Timer info related to fragments */ + struct timer_list frag_timer; + struct ath11k_base *ab; ++ u32 *vaddr_unaligned; ++ dma_addr_t paddr_unaligned; ++ u32 unaligned_size; + }; + + #define DP_REO_DESC_FREE_THRESHOLD 64 +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index 40b52d12b4323..bfb8e7b1a300c 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: BSD-3-Clause-Clear + /* + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +@@ -675,11 +675,11 @@ void ath11k_dp_reo_cmd_list_cleanup(struct ath11k_base *ab) + list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) { + list_del(&cmd->list); + rx_tid = &cmd->data; +- if (rx_tid->vaddr) { +- dma_unmap_single(ab->dev, rx_tid->paddr, +- rx_tid->size, DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; ++ if (rx_tid->vaddr_unaligned) { ++ dma_free_noncoherent(ab->dev, rx_tid->unaligned_size, ++ rx_tid->vaddr_unaligned, ++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL); ++ rx_tid->vaddr_unaligned = NULL; + } + kfree(cmd); + } +@@ -689,11 +689,11 @@ void ath11k_dp_reo_cmd_list_cleanup(struct ath11k_base *ab) + list_del(&cmd_cache->list); + dp->reo_cmd_cache_flush_count--; + rx_tid = &cmd_cache->data; +- if (rx_tid->vaddr) { +- dma_unmap_single(ab->dev, rx_tid->paddr, +- rx_tid->size, DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; ++ if (rx_tid->vaddr_unaligned) { ++ dma_free_noncoherent(ab->dev, rx_tid->unaligned_size, ++ rx_tid->vaddr_unaligned, ++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL); ++ rx_tid->vaddr_unaligned = NULL; + } + kfree(cmd_cache); + } +@@ -708,11 +708,11 @@ static void ath11k_dp_reo_cmd_free(struct ath11k_dp *dp, void *ctx, + if (status != HAL_REO_CMD_SUCCESS) + ath11k_warn(dp->ab, "failed to flush rx tid hw desc, tid %d status %d\n", + rx_tid->tid, status); +- if (rx_tid->vaddr) { +- dma_unmap_single(dp->ab->dev, rx_tid->paddr, rx_tid->size, +- DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; ++ if (rx_tid->vaddr_unaligned) { ++ dma_free_noncoherent(dp->ab->dev, rx_tid->unaligned_size, ++ rx_tid->vaddr_unaligned, ++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL); ++ rx_tid->vaddr_unaligned = NULL; + } + } + +@@ -749,10 +749,10 @@ static void ath11k_dp_reo_cache_flush(struct ath11k_base *ab, + if (ret) { + ath11k_err(ab, "failed to send HAL_REO_CMD_FLUSH_CACHE cmd, tid %d (%d)\n", + rx_tid->tid, ret); +- dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size, +- DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; ++ dma_free_noncoherent(ab->dev, rx_tid->unaligned_size, ++ rx_tid->vaddr_unaligned, ++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL); ++ rx_tid->vaddr_unaligned = NULL; + } + } + +@@ -802,10 +802,10 @@ static void ath11k_dp_rx_tid_del_func(struct ath11k_dp *dp, void *ctx, + + return; + free_desc: +- dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size, +- DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; ++ dma_free_noncoherent(ab->dev, rx_tid->unaligned_size, ++ rx_tid->vaddr_unaligned, ++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL); ++ rx_tid->vaddr_unaligned = NULL; + } + + void ath11k_peer_rx_tid_delete(struct ath11k *ar, +@@ -831,14 +831,16 @@ void ath11k_peer_rx_tid_delete(struct ath11k *ar, + if (ret != -ESHUTDOWN) + ath11k_err(ar->ab, "failed to send HAL_REO_CMD_UPDATE_RX_QUEUE cmd, tid %d (%d)\n", + tid, ret); +- dma_unmap_single(ar->ab->dev, rx_tid->paddr, rx_tid->size, +- DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; ++ dma_free_noncoherent(ar->ab->dev, rx_tid->unaligned_size, ++ rx_tid->vaddr_unaligned, ++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL); ++ rx_tid->vaddr_unaligned = NULL; + } + + rx_tid->paddr = 0; ++ rx_tid->paddr_unaligned = 0; + rx_tid->size = 0; ++ rx_tid->unaligned_size = 0; + } + + static int ath11k_dp_rx_link_desc_return(struct ath11k_base *ab, +@@ -982,10 +984,9 @@ static void ath11k_dp_rx_tid_mem_free(struct ath11k_base *ab, + if (!rx_tid->active) + goto unlock_exit; + +- dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size, +- DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; ++ dma_free_noncoherent(ab->dev, rx_tid->unaligned_size, rx_tid->vaddr_unaligned, ++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL); ++ rx_tid->vaddr_unaligned = NULL; + + rx_tid->active = false; + +@@ -1000,9 +1001,8 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id, + struct ath11k_base *ab = ar->ab; + struct ath11k_peer *peer; + struct dp_rx_tid *rx_tid; +- u32 hw_desc_sz; +- u32 *addr_aligned; +- void *vaddr; ++ u32 hw_desc_sz, *vaddr; ++ void *vaddr_unaligned; + dma_addr_t paddr; + int ret; + +@@ -1050,49 +1050,40 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id, + else + hw_desc_sz = ath11k_hal_reo_qdesc_size(DP_BA_WIN_SZ_MAX, tid); + +- vaddr = kzalloc(hw_desc_sz + HAL_LINK_DESC_ALIGN - 1, GFP_ATOMIC); +- if (!vaddr) { ++ rx_tid->unaligned_size = hw_desc_sz + HAL_LINK_DESC_ALIGN - 1; ++ vaddr_unaligned = dma_alloc_noncoherent(ab->dev, rx_tid->unaligned_size, &paddr, ++ DMA_BIDIRECTIONAL, GFP_ATOMIC); ++ if (!vaddr_unaligned) { + spin_unlock_bh(&ab->base_lock); + return -ENOMEM; + } + +- addr_aligned = PTR_ALIGN(vaddr, HAL_LINK_DESC_ALIGN); +- +- ath11k_hal_reo_qdesc_setup(addr_aligned, tid, ba_win_sz, +- ssn, pn_type); +- +- paddr = dma_map_single(ab->dev, addr_aligned, hw_desc_sz, +- DMA_BIDIRECTIONAL); +- +- ret = dma_mapping_error(ab->dev, paddr); +- if (ret) { +- spin_unlock_bh(&ab->base_lock); +- ath11k_warn(ab, "failed to setup dma map for peer %pM rx tid %d: %d\n", +- peer_mac, tid, ret); +- goto err_mem_free; +- } +- +- rx_tid->vaddr = vaddr; +- rx_tid->paddr = paddr; ++ rx_tid->vaddr_unaligned = vaddr_unaligned; ++ vaddr = PTR_ALIGN(vaddr_unaligned, HAL_LINK_DESC_ALIGN); ++ rx_tid->paddr_unaligned = paddr; ++ rx_tid->paddr = rx_tid->paddr_unaligned + ((unsigned long)vaddr - ++ (unsigned long)rx_tid->vaddr_unaligned); ++ ath11k_hal_reo_qdesc_setup(vaddr, tid, ba_win_sz, ssn, pn_type); + rx_tid->size = hw_desc_sz; + rx_tid->active = true; + ++ /* After dma_alloc_noncoherent, vaddr is being modified for reo qdesc setup. ++ * Since these changes are not reflected in the device, driver now needs to ++ * explicitly call dma_sync_single_for_device. ++ */ ++ dma_sync_single_for_device(ab->dev, rx_tid->paddr, ++ rx_tid->size, ++ DMA_TO_DEVICE); + spin_unlock_bh(&ab->base_lock); + +- ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac, +- paddr, tid, 1, ba_win_sz); ++ ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac, rx_tid->paddr, ++ tid, 1, ba_win_sz); + if (ret) { + ath11k_warn(ar->ab, "failed to setup rx reorder queue for peer %pM tid %d: %d\n", + peer_mac, tid, ret); + ath11k_dp_rx_tid_mem_free(ab, peer_mac, vdev_id, tid); + } + +- return ret; +- +-err_mem_free: +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; +- + return ret; + } + +-- +2.39.5 + diff --git a/queue-6.12/wifi-ath12k-avoid-napi_sync-before-napi_enable.patch b/queue-6.12/wifi-ath12k-avoid-napi_sync-before-napi_enable.patch new file mode 100644 index 0000000000..b72fb0b239 --- /dev/null +++ b/queue-6.12/wifi-ath12k-avoid-napi_sync-before-napi_enable.patch @@ -0,0 +1,78 @@ +From 0db630222afc021fdafd49c6a4c2b09ba19098c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 14:30:58 +0530 +Subject: wifi: ath12k: Avoid napi_sync() before napi_enable() + +From: Avula Sri Charan + +[ Upstream commit 268c73d470a5790a492a2fc2ded084b909d144f3 ] + +In case of MHI error a reset work will be queued which will try +napi_disable() after napi_synchronize(). + +As the napi will be only enabled after qmi_firmware_ready event, +trying napi_synchronize() before napi_enable() will result in +indefinite sleep in case of a firmware crash in QMI init sequence. + +To avoid this, introduce napi_enabled flag to check if napi is enabled +or not before calling napi_synchronize(). + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Avula Sri Charan +Signed-off-by: Tamizh Chelvam Raja +Reviewed-by: Aditya Kumar Singh +Link: https://patch.msgid.link/20250124090058.3194299-1-quic_tamizhr@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/pci.c | 13 ++++++++++--- + 2 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index 7f2e9a9b40977..3faf3430effb9 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -148,6 +148,7 @@ struct ath12k_ext_irq_grp { + u32 num_irq; + u32 grp_id; + u64 timestamp; ++ bool napi_enabled; + struct napi_struct napi; + struct net_device *napi_ndev; + }; +diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c +index 2ff866e1d7d5b..45d537066345a 100644 +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -481,8 +481,11 @@ static void __ath12k_pci_ext_irq_disable(struct ath12k_base *ab) + + ath12k_pci_ext_grp_disable(irq_grp); + +- napi_synchronize(&irq_grp->napi); +- napi_disable(&irq_grp->napi); ++ if (irq_grp->napi_enabled) { ++ napi_synchronize(&irq_grp->napi); ++ napi_disable(&irq_grp->napi); ++ irq_grp->napi_enabled = false; ++ } + } + } + +@@ -1112,7 +1115,11 @@ void ath12k_pci_ext_irq_enable(struct ath12k_base *ab) + for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) { + struct ath12k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; + +- napi_enable(&irq_grp->napi); ++ if (!irq_grp->napi_enabled) { ++ napi_enable(&irq_grp->napi); ++ irq_grp->napi_enabled = true; ++ } ++ + ath12k_pci_ext_grp_enable(irq_grp); + } + +-- +2.39.5 + diff --git a/queue-6.12/wifi-ath12k-fetch-regdb.bin-file-from-board-2.bin.patch b/queue-6.12/wifi-ath12k-fetch-regdb.bin-file-from-board-2.bin.patch new file mode 100644 index 0000000000..a581eb5158 --- /dev/null +++ b/queue-6.12/wifi-ath12k-fetch-regdb.bin-file-from-board-2.bin.patch @@ -0,0 +1,77 @@ +From 7327c41d9f405f876a8ae1a9ec53b1f67665bbbf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jan 2025 08:58:35 +0530 +Subject: wifi: ath12k: Fetch regdb.bin file from board-2.bin + +From: Aaradhana Sahu + +[ Upstream commit 24f587572acf7509127dbdfcbf1b681ef84eeba0 ] + +Currently, ath12k_core_fetch_regdb() finds regdb.bin file through +board id's but in board-2.bin file regdb.bin file is present with +default board id because of which regdb.bin is not fetched. + +Add support to fetch regdb.bin file from board-2.bin through +default board id. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Aaradhana Sahu +Reviewed-by: Aditya Kumar Singh +Link: https://patch.msgid.link/20250116032835.118397-1-quic_aarasahu@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/core.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c +index 51252e8bc1ae9..8bb8ee98188bf 100644 +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -161,7 +161,7 @@ EXPORT_SYMBOL(ath12k_core_resume); + + static int __ath12k_core_create_board_name(struct ath12k_base *ab, char *name, + size_t name_len, bool with_variant, +- bool bus_type_mode) ++ bool bus_type_mode, bool with_default) + { + /* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */ + char variant[9 + ATH12K_QMI_BDF_EXT_STR_LENGTH] = { 0 }; +@@ -192,7 +192,9 @@ static int __ath12k_core_create_board_name(struct ath12k_base *ab, char *name, + "bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s", + ath12k_bus_str(ab->hif.bus), + ab->qmi.target.chip_id, +- ab->qmi.target.board_id, variant); ++ with_default ? ++ ATH12K_BOARD_ID_DEFAULT : ab->qmi.target.board_id, ++ variant); + break; + } + +@@ -204,19 +206,19 @@ static int __ath12k_core_create_board_name(struct ath12k_base *ab, char *name, + static int ath12k_core_create_board_name(struct ath12k_base *ab, char *name, + size_t name_len) + { +- return __ath12k_core_create_board_name(ab, name, name_len, true, false); ++ return __ath12k_core_create_board_name(ab, name, name_len, true, false, false); + } + + static int ath12k_core_create_fallback_board_name(struct ath12k_base *ab, char *name, + size_t name_len) + { +- return __ath12k_core_create_board_name(ab, name, name_len, false, false); ++ return __ath12k_core_create_board_name(ab, name, name_len, false, false, true); + } + + static int ath12k_core_create_bus_type_board_name(struct ath12k_base *ab, char *name, + size_t name_len) + { +- return __ath12k_core_create_board_name(ab, name, name_len, false, true); ++ return __ath12k_core_create_board_name(ab, name, name_len, false, true, true); + } + + const struct firmware *ath12k_core_firmware_request(struct ath12k_base *ab, +-- +2.39.5 + diff --git a/queue-6.12/wifi-ath12k-fix-ath12k_hal_tx_cmd_ext_desc_setup-inf.patch b/queue-6.12/wifi-ath12k-fix-ath12k_hal_tx_cmd_ext_desc_setup-inf.patch new file mode 100644 index 0000000000..d096be59e0 --- /dev/null +++ b/queue-6.12/wifi-ath12k-fix-ath12k_hal_tx_cmd_ext_desc_setup-inf.patch @@ -0,0 +1,41 @@ +From a2a13e99dbfc02ee55759b46fc77241c38dcea12 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Jan 2025 08:13:06 +0100 +Subject: wifi: ath12k: fix ath12k_hal_tx_cmd_ext_desc_setup() info1 override + +From: Nicolas Escande + +[ Upstream commit df11edfba49e5fb69f4c9e7cb76082b89c417f78 ] + +Since inception there is an obvious typo laying around in +ath12k_hal_tx_cmd_ext_desc_setup(). Instead of initializing + adding +flags to tcl_ext_cmd->info1, we initialize + override. This will be needed +in the future to make broadcast frames work with ethernet encapsulation. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Nicolas Escande +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20250127071306.1454699-1-nico.escande@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index ad21fbfbcbe22..201ffdb8c44ae 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -117,7 +117,7 @@ static void ath12k_hal_tx_cmd_ext_desc_setup(struct ath12k_base *ab, + le32_encode_bits(ti->data_len, + HAL_TX_MSDU_EXT_INFO1_BUF_LEN); + +- tcl_ext_cmd->info1 = le32_encode_bits(1, HAL_TX_MSDU_EXT_INFO1_EXTN_OVERRIDE) | ++ tcl_ext_cmd->info1 |= le32_encode_bits(1, HAL_TX_MSDU_EXT_INFO1_EXTN_OVERRIDE) | + le32_encode_bits(ti->encap_type, + HAL_TX_MSDU_EXT_INFO1_ENCAP_TYPE) | + le32_encode_bits(ti->encrypt_type, +-- +2.39.5 + diff --git a/queue-6.12/wifi-ath12k-fix-end-offset-bit-definition-in-monitor.patch b/queue-6.12/wifi-ath12k-fix-end-offset-bit-definition-in-monitor.patch new file mode 100644 index 0000000000..46013655bb --- /dev/null +++ b/queue-6.12/wifi-ath12k-fix-end-offset-bit-definition-in-monitor.patch @@ -0,0 +1,43 @@ +From ec7a31fe4936ecd990c1d5ab7926c8f2ca6808b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Dec 2024 11:31:25 +0530 +Subject: wifi: ath12k: Fix end offset bit definition in monitor ring + descriptor + +From: P Praneesh + +[ Upstream commit 6788a666000d600bd8f2e9f991cad9cc805e7f01 ] + +End offset for the monitor destination ring descriptor is defined as +16 bits, while the firmware definition specifies only 12 bits. +The remaining bits (bit 12 to bit 15) are reserved and may contain +junk values, leading to invalid information retrieval. Fix this issue +by updating the correct genmask values. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 + +Signed-off-by: P Praneesh +Link: https://patch.msgid.link/20241223060132.3506372-8-quic_ppranees@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/hal_desc.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/hal_desc.h b/drivers/net/wireless/ath/ath12k/hal_desc.h +index 739f73370015e..4f745cfd7d8e7 100644 +--- a/drivers/net/wireless/ath/ath12k/hal_desc.h ++++ b/drivers/net/wireless/ath/ath12k/hal_desc.h +@@ -2966,7 +2966,7 @@ struct hal_mon_buf_ring { + + #define HAL_MON_DEST_COOKIE_BUF_ID GENMASK(17, 0) + +-#define HAL_MON_DEST_INFO0_END_OFFSET GENMASK(15, 0) ++#define HAL_MON_DEST_INFO0_END_OFFSET GENMASK(11, 0) + #define HAL_MON_DEST_INFO0_FLUSH_DETECTED BIT(16) + #define HAL_MON_DEST_INFO0_END_OF_PPDU BIT(17) + #define HAL_MON_DEST_INFO0_INITIATOR BIT(18) +-- +2.39.5 + diff --git a/queue-6.12/wifi-ath12k-fix-the-ampdu-id-fetch-in-the-hal_rx_mpd.patch b/queue-6.12/wifi-ath12k-fix-the-ampdu-id-fetch-in-the-hal_rx_mpd.patch new file mode 100644 index 0000000000..6975012cdf --- /dev/null +++ b/queue-6.12/wifi-ath12k-fix-the-ampdu-id-fetch-in-the-hal_rx_mpd.patch @@ -0,0 +1,106 @@ +From 62123b542e883bdac9400984f3a770aa36f5f470 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 07:08:51 +0530 +Subject: wifi: ath12k: fix the ampdu id fetch in the HAL_RX_MPDU_START TLV + +From: P Praneesh + +[ Upstream commit dff4f278ee1ef12d822b7ed2a1048d27037209bb ] + +Currently, ampdu id is update with peer id mask which is incorrect. +Therefore, update the ampdu id with PPDU id mask value. Also move +the ampdu_id field inside the user stats since it is a user id based +statistics. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 + +Signed-off-by: P Praneesh +Reviewed-by: Vasanthakumar Thiagarajan +Signed-off-by: Karthikeyan Periyasamy +Link: https://patch.msgid.link/20250206013854.174765-7-quic_periyasa@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/dp_mon.c | 16 ++++++++++------ + drivers/net/wireless/ath/ath12k/hal_rx.h | 3 ++- + 2 files changed, 12 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c +index 4c98b9de1e584..6a88745369447 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: BSD-3-Clause-Clear + /* + * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include "dp_mon.h" +@@ -666,6 +666,11 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k_base *ab, + if (userid < HAL_MAX_UL_MU_USERS) { + struct hal_rx_user_status *rxuser_stats = + &ppdu_info->userstats[userid]; ++ ++ if (ppdu_info->num_mpdu_fcs_ok > 1 || ++ ppdu_info->num_mpdu_fcs_err > 1) ++ ppdu_info->userstats[userid].ampdu_present = true; ++ + ppdu_info->num_users += 1; + + ath12k_dp_mon_rx_handle_ofdma_info(tlv_data, rxuser_stats); +@@ -783,8 +788,8 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k_base *ab, + if (userid < HAL_MAX_UL_MU_USERS) { + info[0] = __le32_to_cpu(mpdu_start->info0); + ppdu_info->userid = userid; +- ppdu_info->ampdu_id[userid] = +- u32_get_bits(info[0], HAL_RX_MPDU_START_INFO1_PEERID); ++ ppdu_info->userstats[userid].ampdu_id = ++ u32_get_bits(info[0], HAL_RX_MPDU_START_INFO0_PPDU_ID); + } + + mon_mpdu = kzalloc(sizeof(*mon_mpdu), GFP_ATOMIC); +@@ -1020,15 +1025,14 @@ static void ath12k_dp_mon_update_radiotap(struct ath12k *ar, + { + struct ieee80211_supported_band *sband; + u8 *ptr = NULL; +- u16 ampdu_id = ppduinfo->ampdu_id[ppduinfo->userid]; + + rxs->flag |= RX_FLAG_MACTIME_START; + rxs->signal = ppduinfo->rssi_comb + ATH12K_DEFAULT_NOISE_FLOOR; + rxs->nss = ppduinfo->nss + 1; + +- if (ampdu_id) { ++ if (ppduinfo->userstats[ppduinfo->userid].ampdu_present) { + rxs->flag |= RX_FLAG_AMPDU_DETAILS; +- rxs->ampdu_reference = ampdu_id; ++ rxs->ampdu_reference = ppduinfo->userstats[ppduinfo->userid].ampdu_id; + } + + if (ppduinfo->he_mu_flags) { +diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.h b/drivers/net/wireless/ath/ath12k/hal_rx.h +index 095216eabc01d..8c37cbc01b1c5 100644 +--- a/drivers/net/wireless/ath/ath12k/hal_rx.h ++++ b/drivers/net/wireless/ath/ath12k/hal_rx.h +@@ -143,6 +143,8 @@ struct hal_rx_user_status { + u32 mpdu_fcs_ok_bitmap[HAL_RX_NUM_WORDS_PER_PPDU_BITMAP]; + u32 mpdu_ok_byte_count; + u32 mpdu_err_byte_count; ++ bool ampdu_present; ++ u16 ampdu_id; + }; + + #define HAL_MAX_UL_MU_USERS 37 +@@ -226,7 +228,6 @@ struct hal_rx_mon_ppdu_info { + u8 addr4[ETH_ALEN]; + struct hal_rx_user_status userstats[HAL_MAX_UL_MU_USERS]; + u8 userid; +- u16 ampdu_id[HAL_MAX_UL_MU_USERS]; + bool first_msdu_in_mpdu; + bool is_ampdu; + u8 medium_prot_type; +-- +2.39.5 + diff --git a/queue-6.12/wifi-ath12k-improve-bss-discovery-with-hidden-ssid-i.patch b/queue-6.12/wifi-ath12k-improve-bss-discovery-with-hidden-ssid-i.patch new file mode 100644 index 0000000000..32a3acd618 --- /dev/null +++ b/queue-6.12/wifi-ath12k-improve-bss-discovery-with-hidden-ssid-i.patch @@ -0,0 +1,59 @@ +From cd206b0d520cd9666e1dff08e991e52fe7f8d50b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 11:30:05 +0530 +Subject: wifi: ath12k: Improve BSS discovery with hidden SSID in 6 GHz band + +From: Ramasamy Kaliappan + +[ Upstream commit 27d38bdfd416f4db70e09c3bef3b030c86fd235a ] + +Currently, sometimes, the station is unable to identify the configured +AP SSID in its scan results when the AP is not broadcasting its name +publicly and has a hidden SSID. + +Currently, channel dwell time for an ath12k station is 30 ms. Sometimes, +station can send broadcast probe request to AP close to the end of dwell +time. In some of these cases, before AP sends a response to the received +probe request, the dwell time on the station side would come to an end. +So, the station will move to scan next channel and will not be able to +acknowledge the unicast probe response. + +Resolve this issue by increasing station's channel dwell time to 70 ms, +so that the it remains on the same channel for a longer period. This +would increase the station's chance of receiving probe response from the +AP. The station will then send a response acknowledgment back to the AP, +thus leading to successful scan and BSS discovery. + +With an increased dwell time, scan would take longer than it takes now. +But, this fix is an improvement for hidden SSID scan issue. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Ramasamy Kaliappan +Signed-off-by: Roopni Devanathan +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20250207060005.153835-1-quic_rdevanat@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/wmi.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index a6ba97949440e..30836a09d5506 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -2206,8 +2206,8 @@ void ath12k_wmi_start_scan_init(struct ath12k *ar, + arg->dwell_time_active = 50; + arg->dwell_time_active_2g = 0; + arg->dwell_time_passive = 150; +- arg->dwell_time_active_6g = 40; +- arg->dwell_time_passive_6g = 30; ++ arg->dwell_time_active_6g = 70; ++ arg->dwell_time_passive_6g = 70; + arg->min_rest_time = 50; + arg->max_rest_time = 500; + arg->repeat_probe_time = 0; +-- +2.39.5 + diff --git a/queue-6.12/wifi-ath12k-report-proper-tx-completion-status-to-ma.patch b/queue-6.12/wifi-ath12k-report-proper-tx-completion-status-to-ma.patch new file mode 100644 index 0000000000..ef02cf0570 --- /dev/null +++ b/queue-6.12/wifi-ath12k-report-proper-tx-completion-status-to-ma.patch @@ -0,0 +1,56 @@ +From 46288aa0baf9d3af3af68052d6aedb482e8a8de6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Nov 2024 23:04:32 +0530 +Subject: wifi: ath12k: Report proper tx completion status to mac80211 + +From: Vinith Kumar R + +[ Upstream commit d2d9c9b8de725e1006d3aa3d18678a732f5d3584 ] + +Currently Tx completion for few exception packets are received from +firmware and the tx status updated to mac80211. The tx status values of +HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP and HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL +are considered as tx failure and reported as tx failure to mac80211. +But these failure status is due to internal firmware tx drop and these +packets were not tried to transmit in the air. +In case of mesh this invalid tx status report might trigger mpath broken +issue due to increase in mpath fail average. +So do not report these tx status as tx failure instead free the skb +by calling ieee80211_free_txskb(), and that will be accounted as dropped +frame. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Vinith Kumar R +Signed-off-by: Tamizh Chelvam Raja +Acked-by: Jeff Johnson +Link: https://patch.msgid.link/20241122173432.2064858-1-quic_tamizhr@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index 44406e0b4a342..ad21fbfbcbe22 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -557,13 +557,13 @@ ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab, + + switch (wbm_status) { + case HAL_WBM_REL_HTT_TX_COMP_STATUS_OK: +- case HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP: +- case HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL: + ts.acked = (wbm_status == HAL_WBM_REL_HTT_TX_COMP_STATUS_OK); + ts.ack_rssi = le32_get_bits(status_desc->info2, + HTT_TX_WBM_COMP_INFO2_ACK_RSSI); + ath12k_dp_tx_htt_tx_complete_buf(ab, msdu, tx_ring, &ts); + break; ++ case HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP: ++ case HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL: + case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ: + case HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT: + ath12k_dp_tx_free_txbuf(ab, msdu, mac_id, tx_ring); +-- +2.39.5 + diff --git a/queue-6.12/wifi-ath9k-return-by-of_get_mac_address.patch b/queue-6.12/wifi-ath9k-return-by-of_get_mac_address.patch new file mode 100644 index 0000000000..04dfd51c2d --- /dev/null +++ b/queue-6.12/wifi-ath9k-return-by-of_get_mac_address.patch @@ -0,0 +1,46 @@ +From a30438390010dd0ab87e7c85c31e822be1b6d436 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Nov 2024 14:23:26 -0800 +Subject: wifi: ath9k: return by of_get_mac_address +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Rosen Penev + +[ Upstream commit dfffb317519f88534bb82797f055f0a2fd867e7b ] + +When using nvmem, ath9k could potentially be loaded before nvmem, which +loads after mtd. This is an issue if DT contains an nvmem mac address. + +If nvmem is not ready in time for ath9k, -EPROBE_DEFER is returned. Pass +it to _probe so that ath9k can properly grab a potentially present MAC +address. + +Signed-off-by: Rosen Penev +Acked-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20241105222326.194417-1-rosenp@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/init.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c +index 7fad7e75af6a3..619bebd389bd2 100644 +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -691,7 +691,9 @@ static int ath9k_of_init(struct ath_softc *sc) + ah->ah_flags |= AH_NO_EEP_SWAP; + } + +- of_get_mac_address(np, common->macaddr); ++ ret = of_get_mac_address(np, common->macaddr); ++ if (ret == -EPROBE_DEFER) ++ return ret; + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.12/wifi-cfg80211-allow-ir-in-20-mhz-configurations.patch b/queue-6.12/wifi-cfg80211-allow-ir-in-20-mhz-configurations.patch new file mode 100644 index 0000000000..3b2a1c7a65 --- /dev/null +++ b/queue-6.12/wifi-cfg80211-allow-ir-in-20-mhz-configurations.patch @@ -0,0 +1,199 @@ +From 263cd9340690db374ac3e9d77582da09e8158bad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:03:30 +0200 +Subject: wifi: cfg80211: allow IR in 20 MHz configurations + +From: Anjaneyulu + +[ Upstream commit cf4bd1608882792d4742e27a819493312904a680 ] + +Some regulatory bodies doesn't allow IR (initiate radioation) on a +specific subband, but allows it for channels with a bandwidth of 20 MHz. +Add a channel flag that indicates that, and consider it in +cfg80211_reg_check_beaconing. + +While on it, fix the kernel doc of enum nl80211_reg_rule_flags and +change it to use BIT(). + +Signed-off-by: Anjaneyulu +Co-developed-by: Somashekhar Puttagangaiah +Signed-off-by: Somashekhar Puttagangaiah +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308225541.d3ab352a73ff.I8a8f79e1c9eb74936929463960ee2a324712fe51@changeid +[fix typo] +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + include/net/cfg80211.h | 3 +++ + include/uapi/linux/nl80211.h | 52 ++++++++++++++++++++---------------- + net/wireless/chan.c | 8 +++++- + net/wireless/nl80211.c | 4 +++ + net/wireless/reg.c | 4 ++- + 5 files changed, 46 insertions(+), 25 deletions(-) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index 941dc62f3027c..8a712ca73f2b0 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -127,6 +127,8 @@ struct wiphy; + * even if it is otherwise disabled. + * @IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP: Allow using this channel for AP operation + * with very low power (VLP), even if otherwise set to NO_IR. ++ * @IEEE80211_CHAN_ALLOW_20MHZ_ACTIVITY: Allow activity on a 20 MHz channel, ++ * even if otherwise set to NO_IR. + */ + enum ieee80211_channel_flags { + IEEE80211_CHAN_DISABLED = BIT(0), +@@ -155,6 +157,7 @@ enum ieee80211_channel_flags { + IEEE80211_CHAN_NO_6GHZ_AFC_CLIENT = BIT(23), + IEEE80211_CHAN_CAN_MONITOR = BIT(24), + IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP = BIT(25), ++ IEEE80211_CHAN_ALLOW_20MHZ_ACTIVITY = BIT(26), + }; + + #define IEEE80211_CHAN_NO_HT40 \ +diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h +index f97f5adc8d518..c2d7faf8d87fa 100644 +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -4294,6 +4294,8 @@ enum nl80211_wmm_rule { + * otherwise completely disabled. + * @NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP: This channel can be used for a + * very low power (VLP) AP, despite being NO_IR. ++ * @NL80211_FREQUENCY_ATTR_ALLOW_20MHZ_ACTIVITY: This channel can be active in ++ * 20 MHz bandwidth, despite being NO_IR. + * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number + * currently defined + * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use +@@ -4338,6 +4340,7 @@ enum nl80211_frequency_attr { + NL80211_FREQUENCY_ATTR_NO_6GHZ_AFC_CLIENT, + NL80211_FREQUENCY_ATTR_CAN_MONITOR, + NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP, ++ NL80211_FREQUENCY_ATTR_ALLOW_20MHZ_ACTIVITY, + + /* keep last */ + __NL80211_FREQUENCY_ATTR_AFTER_LAST, +@@ -4549,31 +4552,34 @@ enum nl80211_sched_scan_match_attr { + * @NL80211_RRF_NO_6GHZ_AFC_CLIENT: Client connection to AFC AP not allowed + * @NL80211_RRF_ALLOW_6GHZ_VLP_AP: Very low power (VLP) AP can be permitted + * despite NO_IR configuration. ++ * @NL80211_RRF_ALLOW_20MHZ_ACTIVITY: Allow activity in 20 MHz bandwidth, ++ * despite NO_IR configuration. + */ + enum nl80211_reg_rule_flags { +- NL80211_RRF_NO_OFDM = 1<<0, +- NL80211_RRF_NO_CCK = 1<<1, +- NL80211_RRF_NO_INDOOR = 1<<2, +- NL80211_RRF_NO_OUTDOOR = 1<<3, +- NL80211_RRF_DFS = 1<<4, +- NL80211_RRF_PTP_ONLY = 1<<5, +- NL80211_RRF_PTMP_ONLY = 1<<6, +- NL80211_RRF_NO_IR = 1<<7, +- __NL80211_RRF_NO_IBSS = 1<<8, +- NL80211_RRF_AUTO_BW = 1<<11, +- NL80211_RRF_IR_CONCURRENT = 1<<12, +- NL80211_RRF_NO_HT40MINUS = 1<<13, +- NL80211_RRF_NO_HT40PLUS = 1<<14, +- NL80211_RRF_NO_80MHZ = 1<<15, +- NL80211_RRF_NO_160MHZ = 1<<16, +- NL80211_RRF_NO_HE = 1<<17, +- NL80211_RRF_NO_320MHZ = 1<<18, +- NL80211_RRF_NO_EHT = 1<<19, +- NL80211_RRF_PSD = 1<<20, +- NL80211_RRF_DFS_CONCURRENT = 1<<21, +- NL80211_RRF_NO_6GHZ_VLP_CLIENT = 1<<22, +- NL80211_RRF_NO_6GHZ_AFC_CLIENT = 1<<23, +- NL80211_RRF_ALLOW_6GHZ_VLP_AP = 1<<24, ++ NL80211_RRF_NO_OFDM = 1 << 0, ++ NL80211_RRF_NO_CCK = 1 << 1, ++ NL80211_RRF_NO_INDOOR = 1 << 2, ++ NL80211_RRF_NO_OUTDOOR = 1 << 3, ++ NL80211_RRF_DFS = 1 << 4, ++ NL80211_RRF_PTP_ONLY = 1 << 5, ++ NL80211_RRF_PTMP_ONLY = 1 << 6, ++ NL80211_RRF_NO_IR = 1 << 7, ++ __NL80211_RRF_NO_IBSS = 1 << 8, ++ NL80211_RRF_AUTO_BW = 1 << 11, ++ NL80211_RRF_IR_CONCURRENT = 1 << 12, ++ NL80211_RRF_NO_HT40MINUS = 1 << 13, ++ NL80211_RRF_NO_HT40PLUS = 1 << 14, ++ NL80211_RRF_NO_80MHZ = 1 << 15, ++ NL80211_RRF_NO_160MHZ = 1 << 16, ++ NL80211_RRF_NO_HE = 1 << 17, ++ NL80211_RRF_NO_320MHZ = 1 << 18, ++ NL80211_RRF_NO_EHT = 1 << 19, ++ NL80211_RRF_PSD = 1 << 20, ++ NL80211_RRF_DFS_CONCURRENT = 1 << 21, ++ NL80211_RRF_NO_6GHZ_VLP_CLIENT = 1 << 22, ++ NL80211_RRF_NO_6GHZ_AFC_CLIENT = 1 << 23, ++ NL80211_RRF_ALLOW_6GHZ_VLP_AP = 1 << 24, ++ NL80211_RRF_ALLOW_20MHZ_ACTIVITY = 1 << 25, + }; + + #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR +diff --git a/net/wireless/chan.c b/net/wireless/chan.c +index e579d7e1425fe..c4f3fefeb3544 100644 +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c +@@ -6,7 +6,7 @@ + * + * Copyright 2009 Johannes Berg + * Copyright 2013-2014 Intel Mobile Communications GmbH +- * Copyright 2018-2024 Intel Corporation ++ * Copyright 2018-2025 Intel Corporation + */ + + #include +@@ -1621,6 +1621,12 @@ bool cfg80211_reg_check_beaconing(struct wiphy *wiphy, + if (cfg->reg_power == IEEE80211_REG_VLP_AP) + permitting_flags |= IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP; + ++ if ((cfg->iftype == NL80211_IFTYPE_P2P_GO || ++ cfg->iftype == NL80211_IFTYPE_AP) && ++ (chandef->width == NL80211_CHAN_WIDTH_20_NOHT || ++ chandef->width == NL80211_CHAN_WIDTH_20)) ++ permitting_flags |= IEEE80211_CHAN_ALLOW_20MHZ_ACTIVITY; ++ + return _cfg80211_reg_can_beacon(wiphy, chandef, cfg->iftype, + check_no_ir ? IEEE80211_CHAN_NO_IR : 0, + permitting_flags); +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index ecfceddce00fc..c778ffa1c8efd 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -1213,6 +1213,10 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy, + if ((chan->flags & IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP) && + nla_put_flag(msg, NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP)) + goto nla_put_failure; ++ if ((chan->flags & IEEE80211_CHAN_ALLOW_20MHZ_ACTIVITY) && ++ nla_put_flag(msg, ++ NL80211_FREQUENCY_ATTR_ALLOW_20MHZ_ACTIVITY)) ++ goto nla_put_failure; + } + + if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, +diff --git a/net/wireless/reg.c b/net/wireless/reg.c +index 2b626078739c5..f6846eb0f4b84 100644 +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -5,7 +5,7 @@ + * Copyright 2008-2011 Luis R. Rodriguez + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright 2017 Intel Deutschland GmbH +- * Copyright (C) 2018 - 2024 Intel Corporation ++ * Copyright (C) 2018 - 2025 Intel Corporation + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above +@@ -1603,6 +1603,8 @@ static u32 map_regdom_flags(u32 rd_flags) + channel_flags |= IEEE80211_CHAN_PSD; + if (rd_flags & NL80211_RRF_ALLOW_6GHZ_VLP_AP) + channel_flags |= IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP; ++ if (rd_flags & NL80211_RRF_ALLOW_20MHZ_ACTIVITY) ++ channel_flags |= IEEE80211_CHAN_ALLOW_20MHZ_ACTIVITY; + return channel_flags; + } + +-- +2.39.5 + diff --git a/queue-6.12/wifi-iwlwifi-add-support-for-killer-on-mtl.patch b/queue-6.12/wifi-iwlwifi-add-support-for-killer-on-mtl.patch new file mode 100644 index 0000000000..94c1506d6c --- /dev/null +++ b/queue-6.12/wifi-iwlwifi-add-support-for-killer-on-mtl.patch @@ -0,0 +1,36 @@ +From f4404227bb6fda77c8bf5f1c00a9e61950b63860 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 May 2025 21:42:59 +0200 +Subject: wifi: iwlwifi: add support for Killer on MTL + +From: Johannes Berg + +[ Upstream commit ebedf8b7f05b9c886d68d63025db8d1b12343157 ] + +For now, we need another entry for these devices, this +will be changed completely for 6.16. + +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219926 +Link: https://patch.msgid.link/20250506214258.2efbdc9e9a82.I31915ec252bd1c74bd53b89a0e214e42a74b6f2e@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +index 9141ea57abfce..68989d183e82a 100644 +--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c ++++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +@@ -587,6 +587,8 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = { + IWL_DEV_INFO(0x7A70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), + IWL_DEV_INFO(0x7AF0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), + IWL_DEV_INFO(0x7AF0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), ++ IWL_DEV_INFO(0x7F70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), ++ IWL_DEV_INFO(0x7F70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), + + IWL_DEV_INFO(0x271C, 0x0214, iwl9260_2ac_cfg, iwl9260_1_name), + IWL_DEV_INFO(0x7E40, 0x1691, iwl_cfg_ma, iwl_ax411_killer_1690s_name), +-- +2.39.5 + diff --git a/queue-6.12/wifi-iwlwifi-don-t-warn-during-reprobe.patch b/queue-6.12/wifi-iwlwifi-don-t-warn-during-reprobe.patch new file mode 100644 index 0000000000..7224a40f8b --- /dev/null +++ b/queue-6.12/wifi-iwlwifi-don-t-warn-during-reprobe.patch @@ -0,0 +1,43 @@ +From 04c5406d0f267c7c7ccfb44943ee0ba2e75ae2d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 14:55:35 +0200 +Subject: wifi: iwlwifi: don't warn during reprobe + +From: Miri Korenblit + +[ Upstream commit 696cca64308dc641d0bbe4aa2c09dd9752aa288d ] + +During reprobe, the sw state is being destroyd, and so is the +connection. When the peer STA is being removed, the opmode sends a +command to flush the TXQs of the STA and uses iwl_trans_wait_txq_empty. + +This one warns if the FW is not alive, but it really shouldn't if +there is a FW error - and return silently instead, just like we do when +sending a hcmd. + +Signed-off-by: Miri Korenblit +Reviewed-by: Johannes Berg +Link: https://patch.msgid.link/20250205145347.76425b10e5a0.I3bf0de2eb090a8b94c4e36d93dd91df61fadb808@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +index 311b167ea09ed..510e04b721da6 100644 +--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +@@ -454,6 +454,9 @@ IWL_EXPORT_SYMBOL(iwl_trans_txq_enable_cfg); + + int iwl_trans_wait_txq_empty(struct iwl_trans *trans, int queue) + { ++ if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status))) ++ return -EIO; ++ + if (WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, + "bad state = %d\n", trans->state)) + return -EIO; +-- +2.39.5 + diff --git a/queue-6.12/wifi-iwlwifi-don-t-warn-when-if-there-is-a-fw-error.patch b/queue-6.12/wifi-iwlwifi-don-t-warn-when-if-there-is-a-fw-error.patch new file mode 100644 index 0000000000..af1367cea5 --- /dev/null +++ b/queue-6.12/wifi-iwlwifi-don-t-warn-when-if-there-is-a-fw-error.patch @@ -0,0 +1,47 @@ +From b4a393cdb9b31edbcb7d20a903946115e81425d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:19:23 +0200 +Subject: wifi: iwlwifi: don't warn when if there is a FW error + +From: Miri Korenblit + +[ Upstream commit c7f50d0433a016d43681592836a3d484817bfb34 ] + +iwl_trans_reclaim is warning if it is called when the FW is not alive. +But if it is called when there is a pending restart, i.e. after a FW +error, there is no need to warn, instead - return silently. + +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308231427.ba3d90b22c25.I9332506af1997faefcf0bdb51d98d5e874051722@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +index 3b3dcaf33c9d9..311b167ea09ed 100644 +--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +@@ -2,7 +2,7 @@ + /* + * Copyright (C) 2015 Intel Mobile Communications GmbH + * Copyright (C) 2016-2017 Intel Deutschland GmbH +- * Copyright (C) 2019-2021, 2023-2024 Intel Corporation ++ * Copyright (C) 2019-2021, 2023-2025 Intel Corporation + */ + #include + #include +@@ -419,6 +419,9 @@ IWL_EXPORT_SYMBOL(iwl_trans_tx); + void iwl_trans_reclaim(struct iwl_trans *trans, int queue, int ssn, + struct sk_buff_head *skbs, bool is_flush) + { ++ if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status))) ++ return; ++ + if (WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, + "bad state = %d\n", trans->state)) + return; +-- +2.39.5 + diff --git a/queue-6.12/wifi-iwlwifi-fix-debug-actions-order.patch b/queue-6.12/wifi-iwlwifi-fix-debug-actions-order.patch new file mode 100644 index 0000000000..08d1960db6 --- /dev/null +++ b/queue-6.12/wifi-iwlwifi-fix-debug-actions-order.patch @@ -0,0 +1,74 @@ +From de98ee79802a1c0d86c278d71fddaf6c717e1e76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:19:18 +0200 +Subject: wifi: iwlwifi: fix debug actions order + +From: Johannes Berg + +[ Upstream commit eb29b4ffafb20281624dcd2cbb768d6f30edf600 ] + +The order of actions taken for debug was implemented incorrectly. +Now we implemented the dump split and do the FW reset only in the +middle of the dump (rather than the FW killing itself on error.) +As a result, some of the actions taken when applying the config +will now crash the device, so we need to fix the order. + +Signed-off-by: Johannes Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308231427.6de7fa8e63ed.I40632c48e2a67a8aca05def572a934b88ce7934b@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +index 08d990ba8a794..ce787326aa69d 100644 +--- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + /* +- * Copyright (C) 2018-2024 Intel Corporation ++ * Copyright (C) 2018-2025 Intel Corporation + */ + #include + #include "iwl-drv.h" +@@ -1372,15 +1372,15 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt, + switch (tp_id) { + case IWL_FW_INI_TIME_POINT_EARLY: + iwl_dbg_tlv_init_cfg(fwrt); +- iwl_dbg_tlv_apply_config(fwrt, conf_list); + iwl_dbg_tlv_update_drams(fwrt); + iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL); ++ iwl_dbg_tlv_apply_config(fwrt, conf_list); + break; + case IWL_FW_INI_TIME_POINT_AFTER_ALIVE: + iwl_dbg_tlv_apply_buffers(fwrt); + iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list); +- iwl_dbg_tlv_apply_config(fwrt, conf_list); + iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL); ++ iwl_dbg_tlv_apply_config(fwrt, conf_list); + break; + case IWL_FW_INI_TIME_POINT_PERIODIC: + iwl_dbg_tlv_set_periodic_trigs(fwrt); +@@ -1390,14 +1390,14 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt, + case IWL_FW_INI_TIME_POINT_MISSED_BEACONS: + case IWL_FW_INI_TIME_POINT_FW_DHC_NOTIFICATION: + iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list); +- iwl_dbg_tlv_apply_config(fwrt, conf_list); + iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, + iwl_dbg_tlv_check_fw_pkt); ++ iwl_dbg_tlv_apply_config(fwrt, conf_list); + break; + default: + iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list); +- iwl_dbg_tlv_apply_config(fwrt, conf_list); + iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL); ++ iwl_dbg_tlv_apply_config(fwrt, conf_list); + break; + } + } +-- +2.39.5 + diff --git a/queue-6.12/wifi-iwlwifi-fix-the-eckv-uefi-variable-name.patch b/queue-6.12/wifi-iwlwifi-fix-the-eckv-uefi-variable-name.patch new file mode 100644 index 0000000000..321a26a6f0 --- /dev/null +++ b/queue-6.12/wifi-iwlwifi-fix-the-eckv-uefi-variable-name.patch @@ -0,0 +1,71 @@ +From 85e3526640f174b7554272093170c854948aee9a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:19:13 +0200 +Subject: wifi: iwlwifi: fix the ECKV UEFI variable name + +From: Emmanuel Grumbach + +[ Upstream commit 3ea2970b0578011ab8402ad0cff39712255f63df ] + +This UEFI variable name was badly named. Fix its name and also use the +right GUID to find it: we need to use the BT_WIFI (a.k.a. Common) GUID. + +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308231426.78c998d0fa71.I2bc9d72c1dc2c4d7028f0265634a940c2fadbbb5@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 8 +++++--- + drivers/net/wireless/intel/iwlwifi/fw/uefi.h | 4 ++-- + 2 files changed, 7 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +index 834f7c9bb9e92..86d6286a15378 100644 +--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c ++++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + /* +- * Copyright(c) 2021-2024 Intel Corporation ++ * Copyright(c) 2021-2025 Intel Corporation + */ + + #include "iwl-drv.h" +@@ -673,8 +673,10 @@ int iwl_uefi_get_eckv(struct iwl_fw_runtime *fwrt, u32 *extl_clk) + struct uefi_cnv_var_eckv *data; + int ret = 0; + +- data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_ECKV_NAME, +- "ECKV", sizeof(*data), NULL); ++ data = iwl_uefi_get_verified_variable_guid(fwrt->trans, ++ &IWL_EFI_WIFI_BT_GUID, ++ IWL_UEFI_ECKV_NAME, ++ "ECKV", sizeof(*data), NULL); + if (IS_ERR(data)) + return -EINVAL; + +diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +index e525d449e656e..c931f5cedb0b9 100644 +--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h ++++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +@@ -1,6 +1,6 @@ + /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ + /* +- * Copyright(c) 2021-2024 Intel Corporation ++ * Copyright(c) 2021-2025 Intel Corporation + */ + #ifndef __iwl_fw_uefi__ + #define __iwl_fw_uefi__ +@@ -19,7 +19,7 @@ + #define IWL_UEFI_WTAS_NAME L"UefiCnvWlanWTAS" + #define IWL_UEFI_SPLC_NAME L"UefiCnvWlanSPLC" + #define IWL_UEFI_WRDD_NAME L"UefiCnvWlanWRDD" +-#define IWL_UEFI_ECKV_NAME L"UefiCnvWlanECKV" ++#define IWL_UEFI_ECKV_NAME L"UefiCnvCommonECKV" + #define IWL_UEFI_DSM_NAME L"UefiCnvWlanGeneralCfg" + #define IWL_UEFI_WBEM_NAME L"UefiCnvWlanWBEM" + #define IWL_UEFI_PUNCTURING_NAME L"UefiCnvWlanPuncturing" +-- +2.39.5 + diff --git a/queue-6.12/wifi-iwlwifi-mark-br-device-not-integrated.patch b/queue-6.12/wifi-iwlwifi-mark-br-device-not-integrated.patch new file mode 100644 index 0000000000..945f9b5240 --- /dev/null +++ b/queue-6.12/wifi-iwlwifi-mark-br-device-not-integrated.patch @@ -0,0 +1,40 @@ +From b29136ef1788984b2d67b4ec5b25bd10dc4aa365 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:19:17 +0200 +Subject: wifi: iwlwifi: mark Br device not integrated + +From: Johannes Berg + +[ Upstream commit 5f0ab2f35a43773a0dfe1297129a8dbff906b932 ] + +This is a discrete device, don't mark it as integrated. +This also means we cannot set the LTR delay. + +Signed-off-by: Johannes Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308231427.9bb69393fcc9.I197129383e5441c8139cbb0e810ae0b71198a37c@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c +index ab7c0f8d54f42..d3542af0f625e 100644 +--- a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c ++++ b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c +@@ -148,11 +148,9 @@ const struct iwl_cfg_trans_params iwl_br_trans_cfg = { + .mq_rx_supported = true, + .rf_id = true, + .gen2 = true, +- .integrated = true, + .umac_prph_offset = 0x300000, + .xtal_latency = 12000, + .low_latency_xtal = true, +- .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US, + }; + + const char iwl_br_name[] = "Intel(R) TBD Br device"; +-- +2.39.5 + diff --git a/queue-6.12/wifi-iwlwifi-mvm-fix-setting-the-tk-when-associated.patch b/queue-6.12/wifi-iwlwifi-mvm-fix-setting-the-tk-when-associated.patch new file mode 100644 index 0000000000..a555b8bf82 --- /dev/null +++ b/queue-6.12/wifi-iwlwifi-mvm-fix-setting-the-tk-when-associated.patch @@ -0,0 +1,41 @@ +From f73792049f3bd73551e6bda556189b40c3ed8ad5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:19:25 +0200 +Subject: wifi: iwlwifi: mvm: fix setting the TK when associated + +From: Avraham Stern + +[ Upstream commit 3ad61970ac9e164be1b09b46c01aa942e8966132 ] + +When running secured ranging and the initiator is associated with +the responder, the TK was not set in the range request command. +Fix it. + +Signed-off-by: Avraham Stern +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308231427.603dc31579d9.Icd19d797e56483c08dd22c55b96fee481c4d2f3d@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +index 55245f913286b..2ed7a0d77ef83 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +@@ -773,7 +773,11 @@ iwl_mvm_ftm_set_secured_ranging(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + + target.bssid = bssid; + target.cipher = cipher; ++ target.tk = NULL; + ieee80211_iter_keys(mvm->hw, vif, iter, &target); ++ ++ if (!WARN_ON(!target.tk)) ++ memcpy(tk, target.tk, TK_11AZ_LEN); + } else { + memcpy(tk, entry->tk, sizeof(entry->tk)); + } +-- +2.39.5 + diff --git a/queue-6.12/wifi-iwlwifi-use-correct-imr-dump-variable.patch b/queue-6.12/wifi-iwlwifi-use-correct-imr-dump-variable.patch new file mode 100644 index 0000000000..abac16398a --- /dev/null +++ b/queue-6.12/wifi-iwlwifi-use-correct-imr-dump-variable.patch @@ -0,0 +1,45 @@ +From b64bde75433883a703f5672c1e2a25c5856205a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 14:55:46 +0200 +Subject: wifi: iwlwifi: use correct IMR dump variable + +From: Johannes Berg + +[ Upstream commit 21e4d29ac0def546d57bacebe4a51cbed1209b03 ] + +We shouldn't dump the reg_data here which dumps the last +entry again, it should use the imr_reg_data. + +Signed-off-by: Johannes Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250205145347.3313b18667d1.Iaa9ab66b1d397912a573525e060d39ea01b29d19@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +index 6594216f873c4..cd284767ff4ba 100644 +--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c ++++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + /* +- * Copyright (C) 2005-2014, 2018-2024 Intel Corporation ++ * Copyright (C) 2005-2014, 2018-2025 Intel Corporation + * Copyright (C) 2013-2015 Intel Mobile Communications GmbH + * Copyright (C) 2015-2017 Intel Deutschland GmbH + */ +@@ -2691,7 +2691,7 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt, + } + /* collect DRAM_IMR region in the last */ + if (imr_reg_data.reg_tlv) +- size += iwl_dump_ini_mem(fwrt, list, ®_data, ++ size += iwl_dump_ini_mem(fwrt, list, &imr_reg_data, + &iwl_dump_ini_region_ops[IWL_FW_INI_REGION_DRAM_IMR]); + + if (size) { +-- +2.39.5 + diff --git a/queue-6.12/wifi-iwlwifi-w-a-fw-smps-mode-selection.patch b/queue-6.12/wifi-iwlwifi-w-a-fw-smps-mode-selection.patch new file mode 100644 index 0000000000..7cc9c243ff --- /dev/null +++ b/queue-6.12/wifi-iwlwifi-w-a-fw-smps-mode-selection.patch @@ -0,0 +1,99 @@ +From 415ab8ad60eef1e2014f36b9d80787ef999cf205 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:19:19 +0200 +Subject: wifi: iwlwifi: w/a FW SMPS mode selection + +From: Daniel Gabay + +[ Upstream commit b2e709805ce955f80803b7cab3421813c79e1df4 ] + +The FW is now responsible of determining the SMPS mode. +If the user disabled power save in a certain vif, we send the vif-level +power command to clear out the POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK bit +for that vif. +But erroneously, the FW checks DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK in +the device-level command to determine the SMPS mode. + +To W/A this, send also the device-level command when the power save of a +vif changes, and disable power save if there is any vif that has power +save disabled. + +Signed-off-by: Daniel Gabay +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308231427.7bf205efa027.I2c793ff1fc2a6779a95faaee1ded348100fd97f1@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 15 +++++++++++++++ + .../net/wireless/intel/iwlwifi/mvm/mld-mac80211.c | 3 ++- + drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 3 +++ + 3 files changed, 20 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +index d37d83d246354..3fd257f770baa 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +@@ -4096,6 +4096,20 @@ iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm, + return 0; + } + ++void iwl_mvm_smps_workaround(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ++ bool update) ++{ ++ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); ++ ++ if (!iwl_mvm_has_rlc_offload(mvm)) ++ return; ++ ++ mvmvif->ps_disabled = !vif->cfg.ps; ++ ++ if (update) ++ iwl_mvm_power_update_mac(mvm); ++} ++ + /* Common part for MLD and non-MLD modes */ + int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +@@ -4188,6 +4202,7 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw, + new_state == IEEE80211_STA_AUTHORIZED) { + ret = iwl_mvm_sta_state_assoc_to_authorized(mvm, vif, sta, + callbacks); ++ iwl_mvm_smps_workaround(mvm, vif, true); + } else if (old_state == IEEE80211_STA_AUTHORIZED && + new_state == IEEE80211_STA_ASSOC) { + ret = iwl_mvm_sta_state_authorized_to_assoc(mvm, vif, sta, +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c +index e252f0dcea205..04da02bdd9536 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + /* +- * Copyright (C) 2022-2024 Intel Corporation ++ * Copyright (C) 2022-2025 Intel Corporation + */ + #include "mvm.h" + +@@ -961,6 +961,7 @@ static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm, + } + + if (changes & BSS_CHANGED_PS) { ++ iwl_mvm_smps_workaround(mvm, vif, false); + ret = iwl_mvm_power_update_mac(mvm); + if (ret) + IWL_ERR(mvm, "failed to update power mode\n"); +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +index ef07cff203b0d..7d86d273092ac 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +@@ -3042,4 +3042,7 @@ iwl_mvm_send_ap_tx_power_constraint_cmd(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + bool is_ap); ++ ++void iwl_mvm_smps_workaround(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ++ bool update); + #endif /* __IWL_MVM_H__ */ +-- +2.39.5 + diff --git a/queue-6.12/wifi-mac80211-don-t-unconditionally-call-drv_mgd_com.patch b/queue-6.12/wifi-mac80211-don-t-unconditionally-call-drv_mgd_com.patch new file mode 100644 index 0000000000..d232592c3a --- /dev/null +++ b/queue-6.12/wifi-mac80211-don-t-unconditionally-call-drv_mgd_com.patch @@ -0,0 +1,39 @@ +From 303c99cdbf3706bf368a5cb9b88d2f6601e2f458 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 11:39:22 +0200 +Subject: wifi: mac80211: don't unconditionally call drv_mgd_complete_tx() + +From: Johannes Berg + +[ Upstream commit 1798271b3604b902d45033ec569f2bf77e94ecc2 ] + +We might not have called drv_mgd_prepare_tx(), so only call +drv_mgd_complete_tx() under the same conditions. + +Signed-off-by: Johannes Berg +Reviewed-by: Emmanuel Grumbach +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250205110958.e091fc39a351.Ie6a3cdca070612a0aa4b3c6914ab9ed602d1f456@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/mlme.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 3a279ded46c2f..6a29877fd7b37 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -3589,7 +3589,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, + if (tx) + ieee80211_flush_queues(local, sdata, false); + +- drv_mgd_complete_tx(sdata->local, sdata, &info); ++ if (tx || frame_buf) ++ drv_mgd_complete_tx(sdata->local, sdata, &info); + + /* clear AP addr only after building the needed mgmt frames */ + eth_zero_addr(sdata->deflink.u.mgd.bssid); +-- +2.39.5 + diff --git a/queue-6.12/wifi-mac80211-fix-warning-on-disconnect-during-faile.patch b/queue-6.12/wifi-mac80211-fix-warning-on-disconnect-during-faile.patch new file mode 100644 index 0000000000..22a1d650d5 --- /dev/null +++ b/queue-6.12/wifi-mac80211-fix-warning-on-disconnect-during-faile.patch @@ -0,0 +1,39 @@ +From 872af8c3bb160ae8868c9f00bd6527238a70920e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:03:36 +0200 +Subject: wifi: mac80211: fix warning on disconnect during failed ML reconf + +From: Johannes Berg + +[ Upstream commit 0e104aa3676d020f6c442cd7fbaeb72adaaab6fc ] + +If multi-link reconfiguration fails, we can disconnect with a local link +already allocated but the BSS entry not assigned yet, which leads to a +warning in cfg80211. Add a check to avoid the warning. + +Signed-off-by: Johannes Berg +Reviewed-by: Ilan Peer +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308225541.699bd9cbabe5.I599d5ff69092a65e916e2acd25137ae9df8debe8@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/mlme.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index cc8c5d18b130d..3a279ded46c2f 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -4033,7 +4033,7 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) + struct ieee80211_link_data *link; + + link = sdata_dereference(sdata->link[link_id], sdata); +- if (!link) ++ if (!link || !link->conf->bss) + continue; + cfg80211_unlink_bss(local->hw.wiphy, link->conf->bss); + link->conf->bss = NULL; +-- +2.39.5 + diff --git a/queue-6.12/wifi-mac80211-remove-misplaced-drv_mgd_complete_tx-c.patch b/queue-6.12/wifi-mac80211-remove-misplaced-drv_mgd_complete_tx-c.patch new file mode 100644 index 0000000000..b1cec3eb6b --- /dev/null +++ b/queue-6.12/wifi-mac80211-remove-misplaced-drv_mgd_complete_tx-c.patch @@ -0,0 +1,41 @@ +From 0127ccf9df0401050b89f3ada28a07c83d57b0f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 11:39:21 +0200 +Subject: wifi: mac80211: remove misplaced drv_mgd_complete_tx() call + +From: Johannes Berg + +[ Upstream commit f4995cdc4d02d0abc8e9fcccad5c71ce676c1e3f ] + +In the original commit 15fae3410f1d ("mac80211: notify driver on +mgd TX completion") I evidently made a mistake and placed the +call in the "associated" if, rather than the "assoc_data". Later +I noticed the missing call and placed it in commit c042600c17d8 +("wifi: mac80211: adding missing drv_mgd_complete_tx() call"), +but didn't remove the wrong one. Remove it now. + +Signed-off-by: Johannes Berg +Reviewed-by: Emmanuel Grumbach +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250205110958.6ed954179bbf.Id8ef8835b7e6da3bf913c76f77d201017dc8a3c9@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/mlme.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 6a29877fd7b37..6a23a24f7d794 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -9220,7 +9220,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, + ieee80211_report_disconnect(sdata, frame_buf, + sizeof(frame_buf), true, + req->reason_code, false); +- drv_mgd_complete_tx(sdata->local, sdata, &info); + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.12/wifi-mac80211-set-ieee80211_prep_tx_info-link_id-upo.patch b/queue-6.12/wifi-mac80211-set-ieee80211_prep_tx_info-link_id-upo.patch new file mode 100644 index 0000000000..f935ac62a7 --- /dev/null +++ b/queue-6.12/wifi-mac80211-set-ieee80211_prep_tx_info-link_id-upo.patch @@ -0,0 +1,96 @@ +From 33bbbf8d2263ec1031555b3a90fc768b3d5db6ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 11:39:20 +0200 +Subject: wifi: mac80211: set ieee80211_prep_tx_info::link_id upon Auth Rx + +From: Emmanuel Grumbach + +[ Upstream commit 8c60179b64434894eac1ffab7396bac131bc8b6e ] + +This will be used by the low level driver. +Note that link_id will be 0 in case of a non-MLO authentication. +Also fix a call-site of mgd_prepare_tx() where the link_id was not +populated. + +Update the documentation to reflect the current state +ieee80211_prep_tx_info::link_id is also available in mgd_complete_tx(). + +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250205110958.6a590f189ce5.I1fc5c0da26b143f5b07191eb592f01f7083d55ae@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + include/net/mac80211.h | 4 ++-- + net/mac80211/driver-ops.h | 3 ++- + net/mac80211/mlme.c | 4 +++- + 3 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index 3b964f8834e71..fee854892bec5 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -7,7 +7,7 @@ + * Copyright 2007-2010 Johannes Berg + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright (C) 2015 - 2017 Intel Deutschland GmbH +- * Copyright (C) 2018 - 2024 Intel Corporation ++ * Copyright (C) 2018 - 2025 Intel Corporation + */ + + #ifndef MAC80211_H +@@ -3803,7 +3803,7 @@ enum ieee80211_reconfig_type { + * @was_assoc: set if this call is due to deauth/disassoc + * while just having been associated + * @link_id: the link id on which the frame will be TX'ed. +- * Only used with the mgd_prepare_tx() method. ++ * 0 for a non-MLO connection. + */ + struct ieee80211_prep_tx_info { + u16 duration; +diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h +index a06644084d15d..d1c10f5f95160 100644 +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -2,7 +2,7 @@ + /* + * Portions of this file + * Copyright(c) 2016 Intel Deutschland GmbH +-* Copyright (C) 2018-2019, 2021-2024 Intel Corporation ++* Copyright (C) 2018-2019, 2021-2025 Intel Corporation + */ + + #ifndef __MAC80211_DRIVER_OPS +@@ -955,6 +955,7 @@ static inline void drv_mgd_complete_tx(struct ieee80211_local *local, + return; + WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION); + ++ info->link_id = info->link_id < 0 ? 0 : info->link_id; + trace_drv_mgd_complete_tx(local, sdata, info->duration, + info->subtype, info->success); + if (local->ops->mgd_complete_tx) +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 6a23a24f7d794..8fa9b9dd46118 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -8,7 +8,7 @@ + * Copyright 2007, Michael Wu + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright (C) 2015 - 2017 Intel Deutschland GmbH +- * Copyright (C) 2018 - 2024 Intel Corporation ++ * Copyright (C) 2018 - 2025 Intel Corporation + */ + + #include +@@ -4307,6 +4307,8 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, + auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); + status_code = le16_to_cpu(mgmt->u.auth.status_code); + ++ info.link_id = ifmgd->auth_data->link_id; ++ + if (auth_alg != ifmgd->auth_data->algorithm || + (auth_alg != WLAN_AUTH_SAE && + auth_transaction != ifmgd->auth_data->expected_transaction) || +-- +2.39.5 + diff --git a/queue-6.12/wifi-mac80211_hwsim-fix-mld-address-translation.patch b/queue-6.12/wifi-mac80211_hwsim-fix-mld-address-translation.patch new file mode 100644 index 0000000000..789a6d2628 --- /dev/null +++ b/queue-6.12/wifi-mac80211_hwsim-fix-mld-address-translation.patch @@ -0,0 +1,59 @@ +From 8287a113fc177ddd7152d15521c08a76568573f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:03:34 +0200 +Subject: wifi: mac80211_hwsim: Fix MLD address translation + +From: Ilan Peer + +[ Upstream commit 65bff0be9b154621b617fc2e4bd89f1e18e97cdb ] + +Do address translations only between shared links. It is +possible that while an non-AP MLD station and an AP MLD +station have shared links, the frame is intended to be sent +on a link which is not shared (for example when sending a +probe response). + +Signed-off-by: Ilan Peer +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308225541.1aa461270bb6.Ic21592e1b1634653f02b80628cb2152f6e9de367@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/virtual/mac80211_hwsim.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c +index 3f424f14de4ec..4a2b7c9921bc6 100644 +--- a/drivers/net/wireless/virtual/mac80211_hwsim.c ++++ b/drivers/net/wireless/virtual/mac80211_hwsim.c +@@ -4,7 +4,7 @@ + * Copyright (c) 2008, Jouni Malinen + * Copyright (c) 2011, Javier Lopez + * Copyright (c) 2016 - 2017 Intel Deutschland GmbH +- * Copyright (C) 2018 - 2024 Intel Corporation ++ * Copyright (C) 2018 - 2025 Intel Corporation + */ + + /* +@@ -1983,11 +1983,13 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, + return; + } + +- if (sta && sta->mlo) { +- if (WARN_ON(!link_sta)) { +- ieee80211_free_txskb(hw, skb); +- return; +- } ++ /* Do address translations only between shared links. It is ++ * possible that while an non-AP MLD station and an AP MLD ++ * station have shared links, the frame is intended to be sent ++ * on a link which is not shared (for example when sending a ++ * probe response). ++ */ ++ if (sta && sta->mlo && link_sta) { + /* address translation to link addresses on TX */ + ether_addr_copy(hdr->addr1, link_sta->addr); + ether_addr_copy(hdr->addr2, bss_conf->addr); +-- +2.39.5 + diff --git a/queue-6.12/wifi-mt76-mt7925-fix-fails-to-enter-low-power-mode-i.patch b/queue-6.12/wifi-mt76-mt7925-fix-fails-to-enter-low-power-mode-i.patch new file mode 100644 index 0000000000..071419516b --- /dev/null +++ b/queue-6.12/wifi-mt76-mt7925-fix-fails-to-enter-low-power-mode-i.patch @@ -0,0 +1,44 @@ +From 8df495c55c5c87d036ac835a65a0b4a4649e72f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jan 2025 13:06:22 +0800 +Subject: wifi: mt76: mt7925: fix fails to enter low power mode in suspend + state + +From: Quan Zhou + +[ Upstream commit 2d5630b0c9466ac6549495828aa7dce7424a272a ] + +The mt7925 sometimes fails to enter low power mode during suspend. +This is caused by the chip firmware sending an additional ACK event +to the host after processing the suspend command. Due to timing issues, +this event may not reach the host, causing the chip to get stuck. +To resolve this, the ACK flag in the suspend command is removed, +as it is not needed in the MT7925 architecture. This prevents the +firmware from sending the additional ACK event, ensuring the device +can reliably enter low power mode during suspend. + +Signed-off-by: Quan Zhou +Link: https://patch.msgid.link/d056938144a3a0336c3a4e3cec6f271899f32bf7.1736775666.git.quan.zhou@mediatek.com +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +index 5b14bf434df36..2396e1795fe17 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +@@ -3287,6 +3287,9 @@ int mt7925_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb, + else + uni_txd->option = MCU_CMD_UNI_EXT_ACK; + ++ if (cmd == MCU_UNI_CMD(HIF_CTRL)) ++ uni_txd->option &= ~MCU_CMD_ACK; ++ + goto exit; + } + +-- +2.39.5 + diff --git a/queue-6.12/wifi-mt76-mt7925-load-the-appropriate-clc-data-based.patch b/queue-6.12/wifi-mt76-mt7925-load-the-appropriate-clc-data-based.patch new file mode 100644 index 0000000000..478dd8e442 --- /dev/null +++ b/queue-6.12/wifi-mt76-mt7925-load-the-appropriate-clc-data-based.patch @@ -0,0 +1,134 @@ +From 935cee0c3f574cda215ee2b2a39ae1cafab3c842 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 19:36:44 +0800 +Subject: wifi: mt76: mt7925: load the appropriate CLC data based on hardware + type + +From: Ming Yen Hsieh + +[ Upstream commit f2027ef3f733d3f0bb7f27fa3343784058f946ab ] + +Read the EEPROM to determine the hardware type and uses this to load the +correct CLC data. + +Signed-off-by: Ming Yen Hsieh +Link: https://patch.msgid.link/20250304113649.867387-1-mingyen.hsieh@mediatek.com +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + .../net/wireless/mediatek/mt76/mt7925/mcu.c | 61 ++++++++++++++++++- + .../wireless/mediatek/mt76/mt7925/mt7925.h | 3 + + 2 files changed, 63 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +index 8476f9caa98db..5b14bf434df36 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +@@ -616,6 +616,54 @@ int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev, + return ret; + } + ++static int mt7925_mcu_read_eeprom(struct mt792x_dev *dev, u32 offset, u8 *val) ++{ ++ struct { ++ u8 rsv[4]; ++ ++ __le16 tag; ++ __le16 len; ++ ++ __le32 addr; ++ __le32 valid; ++ u8 data[MT7925_EEPROM_BLOCK_SIZE]; ++ } __packed req = { ++ .tag = cpu_to_le16(1), ++ .len = cpu_to_le16(sizeof(req) - 4), ++ .addr = cpu_to_le32(round_down(offset, ++ MT7925_EEPROM_BLOCK_SIZE)), ++ }; ++ struct evt { ++ u8 rsv[4]; ++ ++ __le16 tag; ++ __le16 len; ++ ++ __le32 ver; ++ __le32 addr; ++ __le32 valid; ++ __le32 size; ++ __le32 magic_num; ++ __le32 type; ++ __le32 rsv1[4]; ++ u8 data[32]; ++ } __packed *res; ++ struct sk_buff *skb; ++ int ret; ++ ++ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WM_UNI_CMD_QUERY(EFUSE_CTRL), ++ &req, sizeof(req), true, &skb); ++ if (ret) ++ return ret; ++ ++ res = (struct evt *)skb->data; ++ *val = res->data[offset % MT7925_EEPROM_BLOCK_SIZE]; ++ ++ dev_kfree_skb(skb); ++ ++ return 0; ++} ++ + static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name) + { + const struct mt76_connac2_fw_trailer *hdr; +@@ -624,13 +672,20 @@ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name) + struct mt76_dev *mdev = &dev->mt76; + struct mt792x_phy *phy = &dev->phy; + const struct firmware *fw; ++ u8 *clc_base = NULL, hw_encap = 0; + int ret, i, len, offset = 0; +- u8 *clc_base = NULL; + + if (mt7925_disable_clc || + mt76_is_usb(&dev->mt76)) + return 0; + ++ if (mt76_is_mmio(&dev->mt76)) { ++ ret = mt7925_mcu_read_eeprom(dev, MT_EE_HW_TYPE, &hw_encap); ++ if (ret) ++ return ret; ++ hw_encap = u8_get_bits(hw_encap, MT_EE_HW_TYPE_ENCAP); ++ } ++ + ret = request_firmware(&fw, fw_name, mdev->dev); + if (ret) + return ret; +@@ -675,6 +730,10 @@ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name) + if (phy->clc[clc->idx]) + continue; + ++ /* header content sanity */ ++ if (u8_get_bits(clc->type, MT_EE_HW_TYPE_ENCAP) != hw_encap) ++ continue; ++ + phy->clc[clc->idx] = devm_kmemdup(mdev->dev, clc, + le32_to_cpu(clc->len), + GFP_KERNEL); +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h +index df3c705d1cb3f..4ad779329b8f0 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h +@@ -147,9 +147,12 @@ enum mt7925_eeprom_field { + MT_EE_CHIP_ID = 0x000, + MT_EE_VERSION = 0x002, + MT_EE_MAC_ADDR = 0x004, ++ MT_EE_HW_TYPE = 0xa71, + __MT_EE_MAX = 0x9ff + }; + ++#define MT_EE_HW_TYPE_ENCAP GENMASK(1, 0) ++ + enum { + TXPWR_USER, + TXPWR_EEPROM, +-- +2.39.5 + diff --git a/queue-6.12/wifi-mt76-mt7996-fix-ser-reset-trigger-on-wed-reset.patch b/queue-6.12/wifi-mt76-mt7996-fix-ser-reset-trigger-on-wed-reset.patch new file mode 100644 index 0000000000..e9134883e1 --- /dev/null +++ b/queue-6.12/wifi-mt76-mt7996-fix-ser-reset-trigger-on-wed-reset.patch @@ -0,0 +1,51 @@ +From f5739daa13bed5b6dcd9afde0e3ad0740a867199 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 11:36:39 +0100 +Subject: wifi: mt76: mt7996: fix SER reset trigger on WED reset + +From: Rex Lu + +[ Upstream commit 8d38abdf6c182225c5c0a81451fa51b7b36a635d ] + +The firmware needs a specific trigger when WED is being reset due to an +ethernet reset condition. This helps prevent further L1 SER failure. + +Signed-off-by: Rex Lu +Link: https://patch.msgid.link/20250311103646.43346-2-nbd@nbd.name +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7996/mcu.h | 3 ++- + drivers/net/wireless/mediatek/mt76/mt7996/mmio.c | 2 +- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +index 43468bcaffc6d..a75e1c9435bb0 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +@@ -908,7 +908,8 @@ enum { + UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE, + UNI_CMD_SER_SET_RECOVER_L3_BF, + UNI_CMD_SER_SET_RECOVER_L4_MDP, +- UNI_CMD_SER_SET_RECOVER_FULL, ++ UNI_CMD_SER_SET_RECOVER_FROM_ETH, ++ UNI_CMD_SER_SET_RECOVER_FULL = 8, + UNI_CMD_SER_SET_SYSTEM_ASSERT, + /* action */ + UNI_CMD_SER_ENABLE = 1, +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +index 442f72450352b..b6209ed1cfe01 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +@@ -281,7 +281,7 @@ static int mt7996_mmio_wed_reset(struct mtk_wed_device *wed) + if (test_and_set_bit(MT76_STATE_WED_RESET, &mphy->state)) + return -EBUSY; + +- ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_L1, ++ ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_FROM_ETH, + mphy->band_idx); + if (ret) + goto out; +-- +2.39.5 + diff --git a/queue-6.12/wifi-mt76-mt7996-revise-txs-size.patch b/queue-6.12/wifi-mt76-mt7996-revise-txs-size.patch new file mode 100644 index 0000000000..b2475a511b --- /dev/null +++ b/queue-6.12/wifi-mt76-mt7996-revise-txs-size.patch @@ -0,0 +1,61 @@ +From 239f14fec56d69f165ef222dbc999d09dbb62afc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 11:36:38 +0100 +Subject: wifi: mt76: mt7996: revise TXS size + +From: Benjamin Lin + +[ Upstream commit 593c829b4326f7b3b15a69e97c9044ecbad3c319 ] + +Size of MPDU/PPDU TXS is 12 DWs. +In mt7996/mt7992, last 4 DWs are reserved, so TXS size was mistakenly +considered to be 8 DWs. However, in mt7990, 9th DW of TXS starts to be used. + +Signed-off-by: Benjamin Lin +Link: https://patch.msgid.link/20250311103646.43346-1-nbd@nbd.name +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h | 3 +++ + drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 4 ++-- + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h +index db0c29e65185c..487ad716f872a 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h ++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h +@@ -314,6 +314,9 @@ enum tx_frag_idx { + #define MT_TXFREE_INFO_COUNT GENMASK(27, 24) + #define MT_TXFREE_INFO_STAT GENMASK(29, 28) + ++#define MT_TXS_HDR_SIZE 4 /* Unit: DW */ ++#define MT_TXS_SIZE 12 /* Unit: DW */ ++ + #define MT_TXS0_BW GENMASK(31, 29) + #define MT_TXS0_TID GENMASK(28, 26) + #define MT_TXS0_AMPDU BIT(25) +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +index f590902fdeea3..ef2d7eaaaffdd 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +@@ -1399,7 +1399,7 @@ bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len) + mt7996_mac_tx_free(dev, data, len); + return false; + case PKT_TYPE_TXS: +- for (rxd += 4; rxd + 8 <= end; rxd += 8) ++ for (rxd += MT_TXS_HDR_SIZE; rxd + MT_TXS_SIZE <= end; rxd += MT_TXS_SIZE) + mt7996_mac_add_txs(dev, rxd); + return false; + case PKT_TYPE_RX_FW_MONITOR: +@@ -1442,7 +1442,7 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, + mt7996_mcu_rx_event(dev, skb); + break; + case PKT_TYPE_TXS: +- for (rxd += 4; rxd + 8 <= end; rxd += 8) ++ for (rxd += MT_TXS_HDR_SIZE; rxd + MT_TXS_SIZE <= end; rxd += MT_TXS_SIZE) + mt7996_mac_add_txs(dev, rxd); + dev_kfree_skb(skb); + break; +-- +2.39.5 + diff --git a/queue-6.12/wifi-mt76-only-mark-tx-status-failed-frames-as-acked.patch b/queue-6.12/wifi-mt76-only-mark-tx-status-failed-frames-as-acked.patch new file mode 100644 index 0000000000..e6af348b0c --- /dev/null +++ b/queue-6.12/wifi-mt76-only-mark-tx-status-failed-frames-as-acked.patch @@ -0,0 +1,111 @@ +From 962bf712b773ea798eea81856d6c318f6aa694d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 11:36:43 +0100 +Subject: wifi: mt76: only mark tx-status-failed frames as ACKed on mt76x0/2 + +From: Felix Fietkau + +[ Upstream commit 0c5a89ceddc1728a40cb3313948401dd70e3c649 ] + +The interrupt status polling is unreliable, which can cause status events +to get lost. On all newer chips, txs-timeout is an indication that the +packet was either never sent, or never acked. +Fixes issues with inactivity polling. + +Link: https://patch.msgid.link/20250311103646.43346-6-nbd@nbd.name +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt76.h | 1 + + drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 3 ++- + drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 3 ++- + drivers/net/wireless/mediatek/mt76/mt76x2/pci.c | 3 ++- + drivers/net/wireless/mediatek/mt76/mt76x2/usb.c | 3 ++- + drivers/net/wireless/mediatek/mt76/tx.c | 3 ++- + 6 files changed, 11 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h +index e2e9b5ece74e2..a6ac8e5512eba 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76.h ++++ b/drivers/net/wireless/mediatek/mt76/mt76.h +@@ -489,6 +489,7 @@ struct mt76_hw_cap { + #define MT_DRV_RX_DMA_HDR BIT(3) + #define MT_DRV_HW_MGMT_TXQ BIT(4) + #define MT_DRV_AMSDU_OFFLOAD BIT(5) ++#define MT_DRV_IGNORE_TXS_FAILED BIT(6) + + struct mt76_driver_ops { + u32 drv_flags; +diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +index 1eb955f3ca130..911e162a45980 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +@@ -156,7 +156,8 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id) + static const struct mt76_driver_ops drv_ops = { + .txwi_size = sizeof(struct mt76x02_txwi), + .drv_flags = MT_DRV_TX_ALIGNED4_SKBS | +- MT_DRV_SW_RX_AIRTIME, ++ MT_DRV_SW_RX_AIRTIME | ++ MT_DRV_IGNORE_TXS_FAILED, + .survey_flags = SURVEY_INFO_TIME_TX, + .update_survey = mt76x02_update_channel, + .set_channel = mt76x0_set_channel, +diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +index b031c500b7415..90e5666c0857d 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +@@ -214,7 +214,8 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, + const struct usb_device_id *id) + { + static const struct mt76_driver_ops drv_ops = { +- .drv_flags = MT_DRV_SW_RX_AIRTIME, ++ .drv_flags = MT_DRV_SW_RX_AIRTIME | ++ MT_DRV_IGNORE_TXS_FAILED, + .survey_flags = SURVEY_INFO_TIME_TX, + .update_survey = mt76x02_update_channel, + .set_channel = mt76x0_set_channel, +diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c +index 67c9d1caa0bd6..55f076231bdc5 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c +@@ -22,7 +22,8 @@ mt76x2e_probe(struct pci_dev *pdev, const struct pci_device_id *id) + static const struct mt76_driver_ops drv_ops = { + .txwi_size = sizeof(struct mt76x02_txwi), + .drv_flags = MT_DRV_TX_ALIGNED4_SKBS | +- MT_DRV_SW_RX_AIRTIME, ++ MT_DRV_SW_RX_AIRTIME | ++ MT_DRV_IGNORE_TXS_FAILED, + .survey_flags = SURVEY_INFO_TIME_TX, + .update_survey = mt76x02_update_channel, + .set_channel = mt76x2e_set_channel, +diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +index a4f4d12f904e7..84ef80ab4afbf 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +@@ -30,7 +30,8 @@ static int mt76x2u_probe(struct usb_interface *intf, + const struct usb_device_id *id) + { + static const struct mt76_driver_ops drv_ops = { +- .drv_flags = MT_DRV_SW_RX_AIRTIME, ++ .drv_flags = MT_DRV_SW_RX_AIRTIME | ++ MT_DRV_IGNORE_TXS_FAILED, + .survey_flags = SURVEY_INFO_TIME_TX, + .update_survey = mt76x02_update_channel, + .set_channel = mt76x2u_set_channel, +diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c +index ce193e625666b..065a1e4537457 100644 +--- a/drivers/net/wireless/mediatek/mt76/tx.c ++++ b/drivers/net/wireless/mediatek/mt76/tx.c +@@ -100,7 +100,8 @@ __mt76_tx_status_skb_done(struct mt76_dev *dev, struct sk_buff *skb, u8 flags, + return; + + /* Tx status can be unreliable. if it fails, mark the frame as ACKed */ +- if (flags & MT_TX_CB_TXS_FAILED) { ++ if (flags & MT_TX_CB_TXS_FAILED && ++ (dev->drv->drv_flags & MT_DRV_IGNORE_TXS_FAILED)) { + info->status.rates[0].count = 0; + info->status.rates[0].idx = -1; + info->flags |= IEEE80211_TX_STAT_ACK; +-- +2.39.5 + diff --git a/queue-6.12/wifi-mwifiex-fix-ht40-bandwidth-issue.patch b/queue-6.12/wifi-mwifiex-fix-ht40-bandwidth-issue.patch new file mode 100644 index 0000000000..32cf8deb69 --- /dev/null +++ b/queue-6.12/wifi-mwifiex-fix-ht40-bandwidth-issue.patch @@ -0,0 +1,47 @@ +From e42e2920e39e672fad3280c951852f30f7fe2a4a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 17:42:38 +0800 +Subject: wifi: mwifiex: Fix HT40 bandwidth issue. + +From: Jeff Chen + +[ Upstream commit 4fcfcbe457349267fe048524078e8970807c1a5b ] + +This patch addresses an issue where, despite the AP supporting 40MHz +bandwidth, the connection was limited to 20MHz. Without this fix, +even if the access point supports 40MHz, the bandwidth after +connection remains at 20MHz. This issue is not a regression. + +Signed-off-by: Jeff Chen +Reviewed-by: Francesco Dolcini +Link: https://patch.msgid.link/20250314094238.2097341-1-jeff.chen_1@nxp.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/marvell/mwifiex/11n.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/marvell/mwifiex/11n.c b/drivers/net/wireless/marvell/mwifiex/11n.c +index 66f0f5377ac18..738bafc3749b0 100644 +--- a/drivers/net/wireless/marvell/mwifiex/11n.c ++++ b/drivers/net/wireless/marvell/mwifiex/11n.c +@@ -403,12 +403,14 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, + + if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && + bss_desc->bcn_ht_oper->ht_param & +- IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) ++ IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) { ++ chan_list->chan_scan_param[0].radio_type |= ++ CHAN_BW_40MHZ << 2; + SET_SECONDARYCHAN(chan_list->chan_scan_param[0]. + radio_type, + (bss_desc->bcn_ht_oper->ht_param & + IEEE80211_HT_PARAM_CHA_SEC_OFFSET)); +- ++ } + *buffer += struct_size(chan_list, chan_scan_param, 1); + ret_len += struct_size(chan_list, chan_scan_param, 1); + } +-- +2.39.5 + diff --git a/queue-6.12/wifi-rtl8xxxu-retry-firmware-download-on-error.patch b/queue-6.12/wifi-rtl8xxxu-retry-firmware-download-on-error.patch new file mode 100644 index 0000000000..80ad4b87d4 --- /dev/null +++ b/queue-6.12/wifi-rtl8xxxu-retry-firmware-download-on-error.patch @@ -0,0 +1,67 @@ +From 87aff57c1de042e4912fa33a22e4bc24ad209208 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Jan 2025 20:48:28 +0100 +Subject: wifi: rtl8xxxu: retry firmware download on error + +From: Soeren Moch + +[ Upstream commit 3d3e28feca7ac8c6cf2a390dbbe1f97e3feb7f36 ] + +Occasionally there is an EPROTO error during firmware download. +This error is converted to EAGAIN in the download function. +But nobody tries again and so device probe fails. + +Implement download retry to fix this. + +This error was observed (and fix tested) on a tbs2910 board [1] +with an embedded RTL8188EU (0bda:8179) device behind a USB hub. + +[1] arch/arm/boot/dts/nxp/imx/imx6q-tbs2910.dts + +Signed-off-by: Soeren Moch +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250127194828.599379-1-smoch@web.de +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtl8xxxu/core.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c b/drivers/net/wireless/realtek/rtl8xxxu/core.c +index 4ce0c05c51291..569856ca677f6 100644 +--- a/drivers/net/wireless/realtek/rtl8xxxu/core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c +@@ -860,9 +860,10 @@ rtl8xxxu_writeN(struct rtl8xxxu_priv *priv, u16 addr, u8 *buf, u16 len) + return len; + + write_error: +- dev_info(&udev->dev, +- "%s: Failed to write block at addr: %04x size: %04x\n", +- __func__, addr, blocksize); ++ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_WRITE) ++ dev_info(&udev->dev, ++ "%s: Failed to write block at addr: %04x size: %04x\n", ++ __func__, addr, blocksize); + return -EAGAIN; + } + +@@ -4064,8 +4065,14 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) + */ + rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, fops->trxff_boundary); + +- ret = rtl8xxxu_download_firmware(priv); +- dev_dbg(dev, "%s: download_firmware %i\n", __func__, ret); ++ for (int retry = 5; retry >= 0 ; retry--) { ++ ret = rtl8xxxu_download_firmware(priv); ++ dev_dbg(dev, "%s: download_firmware %i\n", __func__, ret); ++ if (ret != -EAGAIN) ++ break; ++ if (retry) ++ dev_dbg(dev, "%s: retry firmware download\n", __func__); ++ } + if (ret) + goto exit; + ret = rtl8xxxu_start_firmware(priv); +-- +2.39.5 + diff --git a/queue-6.12/wifi-rtw88-don-t-use-static-local-variable-in-rtw882.patch b/queue-6.12/wifi-rtw88-don-t-use-static-local-variable-in-rtw882.patch new file mode 100644 index 0000000000..99b1c0aaeb --- /dev/null +++ b/queue-6.12/wifi-rtw88-don-t-use-static-local-variable-in-rtw882.patch @@ -0,0 +1,78 @@ +From dbea83d64eb1e19b0f78e8fdb3f5286cd114540b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 26 Jan 2025 16:03:11 +0200 +Subject: wifi: rtw88: Don't use static local variable in + rtw8822b_set_tx_power_index_by_rate + +From: Bitterblue Smith + +[ Upstream commit 00451eb3bec763f708e7e58326468c1e575e5a66 ] + +Some users want to plug two identical USB devices at the same time. +This static variable could theoretically cause them to use incorrect +TX power values. + +Move the variable to the caller and pass a pointer to it to +rtw8822b_set_tx_power_index_by_rate(). + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/8a60f581-0ab5-4d98-a97d-dd83b605008f@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/rtw8822b.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +index 6edb17aea90e0..4a6c0a9266a09 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +@@ -976,11 +976,11 @@ static void rtw8822b_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, + } + + static void +-rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs) ++rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, ++ u8 rs, u32 *phy_pwr_idx) + { + struct rtw_hal *hal = &rtwdev->hal; + static const u32 offset_txagc[2] = {0x1d00, 0x1d80}; +- static u32 phy_pwr_idx; + u8 rate, rate_idx, pwr_index, shift; + int j; + +@@ -988,12 +988,12 @@ rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs) + rate = rtw_rate_section[rs][j]; + pwr_index = hal->tx_pwr_tbl[path][rate]; + shift = rate & 0x3; +- phy_pwr_idx |= ((u32)pwr_index << (shift * 8)); ++ *phy_pwr_idx |= ((u32)pwr_index << (shift * 8)); + if (shift == 0x3) { + rate_idx = rate & 0xfc; + rtw_write32(rtwdev, offset_txagc[path] + rate_idx, +- phy_pwr_idx); +- phy_pwr_idx = 0; ++ *phy_pwr_idx); ++ *phy_pwr_idx = 0; + } + } + } +@@ -1001,11 +1001,13 @@ rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs) + static void rtw8822b_set_tx_power_index(struct rtw_dev *rtwdev) + { + struct rtw_hal *hal = &rtwdev->hal; ++ u32 phy_pwr_idx = 0; + int rs, path; + + for (path = 0; path < hal->rf_path_num; path++) { + for (rs = 0; rs < RTW_RATE_SECTION_MAX; rs++) +- rtw8822b_set_tx_power_index_by_rate(rtwdev, path, rs); ++ rtw8822b_set_tx_power_index_by_rate(rtwdev, path, rs, ++ &phy_pwr_idx); + } + } + +-- +2.39.5 + diff --git a/queue-6.12/wifi-rtw88-fix-__rtw_download_firmware-for-rtl8814au.patch b/queue-6.12/wifi-rtw88-fix-__rtw_download_firmware-for-rtl8814au.patch new file mode 100644 index 0000000000..c7c2450f1c --- /dev/null +++ b/queue-6.12/wifi-rtw88-fix-__rtw_download_firmware-for-rtl8814au.patch @@ -0,0 +1,49 @@ +From bfc1a42749f85aa868587f7652ab81a4bd3fd6e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 20:36:56 +0200 +Subject: wifi: rtw88: Fix __rtw_download_firmware() for RTL8814AU + +From: Bitterblue Smith + +[ Upstream commit 8425f5c8f04dbcf11ade78f984a494fc0b90e7a0 ] + +Don't call ltecoex_read_reg() and ltecoex_reg_write() when the +ltecoex_addr member of struct rtw_chip_info is NULL. The RTL8814AU +doesn't have this feature. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/55b5641f-094e-4f94-9f79-ac053733f2cf@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/mac.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c +index 564f5988ee82a..d1c4f5cdcb21d 100644 +--- a/drivers/net/wireless/realtek/rtw88/mac.c ++++ b/drivers/net/wireless/realtek/rtw88/mac.c +@@ -783,7 +783,8 @@ static int __rtw_download_firmware(struct rtw_dev *rtwdev, + if (!check_firmware_size(data, size)) + return -EINVAL; + +- if (!ltecoex_read_reg(rtwdev, 0x38, <ecoex_bckp)) ++ if (rtwdev->chip->ltecoex_addr && ++ !ltecoex_read_reg(rtwdev, 0x38, <ecoex_bckp)) + return -EBUSY; + + wlan_cpu_enable(rtwdev, false); +@@ -801,7 +802,8 @@ static int __rtw_download_firmware(struct rtw_dev *rtwdev, + + wlan_cpu_enable(rtwdev, true); + +- if (!ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp)) { ++ if (rtwdev->chip->ltecoex_addr && ++ !ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp)) { + ret = -EBUSY; + goto dlfw_fail; + } +-- +2.39.5 + diff --git a/queue-6.12/wifi-rtw88-fix-download_firmware_validate-for-rtl881.patch b/queue-6.12/wifi-rtw88-fix-download_firmware_validate-for-rtl881.patch new file mode 100644 index 0000000000..e521dd16f0 --- /dev/null +++ b/queue-6.12/wifi-rtw88-fix-download_firmware_validate-for-rtl881.patch @@ -0,0 +1,49 @@ +From 7779fd53b5467d3f3960d8445dcfeab9f8d4866c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 20:37:36 +0200 +Subject: wifi: rtw88: Fix download_firmware_validate() for RTL8814AU + +From: Bitterblue Smith + +[ Upstream commit 9e8243025cc06abc975c876dffda052073207ab3 ] + +After the firmware is uploaded, download_firmware_validate() checks some +bits in REG_MCUFW_CTRL to see if everything went okay. The +RTL8814AU power on sequence sets bits 13 and 12 to 2, which this +function does not expect, so it thinks the firmware upload failed. + +Make download_firmware_validate() ignore bits 13 and 12. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/049d2887-22fc-47b7-9e59-62627cb525f8@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/reg.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h +index 4d9b8668e8b04..2708ee2f12a47 100644 +--- a/drivers/net/wireless/realtek/rtw88/reg.h ++++ b/drivers/net/wireless/realtek/rtw88/reg.h +@@ -109,6 +109,7 @@ + #define BIT_SHIFT_ROM_PGE 16 + #define BIT_FW_INIT_RDY BIT(15) + #define BIT_FW_DW_RDY BIT(14) ++#define BIT_CPU_CLK_SEL (BIT(12) | BIT(13)) + #define BIT_RPWM_TOGGLE BIT(7) + #define BIT_RAM_DL_SEL BIT(7) /* legacy only */ + #define BIT_DMEM_CHKSUM_OK BIT(6) +@@ -126,7 +127,7 @@ + BIT_CHECK_SUM_OK) + #define FW_READY_LEGACY (BIT_MCUFWDL_RDY | BIT_FWDL_CHK_RPT | \ + BIT_WINTINI_RDY | BIT_RAM_DL_SEL) +-#define FW_READY_MASK 0xffff ++#define FW_READY_MASK (0xffff & ~BIT_CPU_CLK_SEL) + + #define REG_MCU_TST_CFG 0x84 + #define VAL_FW_TRIGGER 0x1 +-- +2.39.5 + diff --git a/queue-6.12/wifi-rtw88-fix-rtw_desc_to_mcsrate-to-handle-mcs16-3.patch b/queue-6.12/wifi-rtw88-fix-rtw_desc_to_mcsrate-to-handle-mcs16-3.patch new file mode 100644 index 0000000000..a1a539b99a --- /dev/null +++ b/queue-6.12/wifi-rtw88-fix-rtw_desc_to_mcsrate-to-handle-mcs16-3.patch @@ -0,0 +1,42 @@ +From b0dcddcb87a0765155e6475003b5d0ded3c3ed1a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 01:29:52 +0200 +Subject: wifi: rtw88: Fix rtw_desc_to_mcsrate() to handle MCS16-31 + +From: Bitterblue Smith + +[ Upstream commit 86d04f8f991a0509e318fe886d5a1cf795736c7d ] + +This function translates the rate number reported by the hardware into +something mac80211 can understand. It was ignoring the 3SS and 4SS HT +rates. Translate them too. + +Also set *nss to 0 for the HT rates, just to make sure it's +initialised. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/d0a5a86b-4869-47f6-a5a7-01c0f987cc7f@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/util.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/util.c b/drivers/net/wireless/realtek/rtw88/util.c +index e222d3c01a77e..66819f6944055 100644 +--- a/drivers/net/wireless/realtek/rtw88/util.c ++++ b/drivers/net/wireless/realtek/rtw88/util.c +@@ -101,7 +101,8 @@ void rtw_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss) + *nss = 4; + *mcs = rate - DESC_RATEVHT4SS_MCS0; + } else if (rate >= DESC_RATEMCS0 && +- rate <= DESC_RATEMCS15) { ++ rate <= DESC_RATEMCS31) { ++ *nss = 0; + *mcs = rate - DESC_RATEMCS0; + } + } +-- +2.39.5 + diff --git a/queue-6.12/wifi-rtw88-fix-rtw_init_ht_cap-for-rtl8814au.patch b/queue-6.12/wifi-rtw88-fix-rtw_init_ht_cap-for-rtl8814au.patch new file mode 100644 index 0000000000..e942a5eac8 --- /dev/null +++ b/queue-6.12/wifi-rtw88-fix-rtw_init_ht_cap-for-rtl8814au.patch @@ -0,0 +1,59 @@ +From ba0a5b0fd6d0f573129ee9080bc6f14ced6c97b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 01:30:22 +0200 +Subject: wifi: rtw88: Fix rtw_init_ht_cap() for RTL8814AU + +From: Bitterblue Smith + +[ Upstream commit c7eea1ba05ca5b0dbf77a27cf2e1e6e2fb3c0043 ] + +Set the RX mask and the highest RX rate according to the number of +spatial streams the chip can receive. For RTL8814AU that is 3. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/4e786f50-ed1c-4387-8b28-e6ff00e35e81@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/main.c | 17 ++++++----------- + 1 file changed, 6 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c +index 2c81e4cae039e..a808af2f085ec 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.c ++++ b/drivers/net/wireless/realtek/rtw88/main.c +@@ -1543,6 +1543,7 @@ static void rtw_init_ht_cap(struct rtw_dev *rtwdev, + { + const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_efuse *efuse = &rtwdev->efuse; ++ int i; + + ht_cap->ht_supported = true; + ht_cap->cap = 0; +@@ -1562,17 +1563,11 @@ static void rtw_init_ht_cap(struct rtw_dev *rtwdev, + ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + ht_cap->ampdu_density = chip->ampdu_density; + ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; +- if (efuse->hw_cap.nss > 1) { +- ht_cap->mcs.rx_mask[0] = 0xFF; +- ht_cap->mcs.rx_mask[1] = 0xFF; +- ht_cap->mcs.rx_mask[4] = 0x01; +- ht_cap->mcs.rx_highest = cpu_to_le16(300); +- } else { +- ht_cap->mcs.rx_mask[0] = 0xFF; +- ht_cap->mcs.rx_mask[1] = 0x00; +- ht_cap->mcs.rx_mask[4] = 0x01; +- ht_cap->mcs.rx_highest = cpu_to_le16(150); +- } ++ ++ for (i = 0; i < efuse->hw_cap.nss; i++) ++ ht_cap->mcs.rx_mask[i] = 0xFF; ++ ht_cap->mcs.rx_mask[4] = 0x01; ++ ht_cap->mcs.rx_highest = cpu_to_le16(150 * efuse->hw_cap.nss); + } + + static void rtw_init_vht_cap(struct rtw_dev *rtwdev, +-- +2.39.5 + diff --git a/queue-6.12/wifi-rtw88-fix-rtw_init_vht_cap-for-rtl8814au.patch b/queue-6.12/wifi-rtw88-fix-rtw_init_vht_cap-for-rtl8814au.patch new file mode 100644 index 0000000000..7be4e82dca --- /dev/null +++ b/queue-6.12/wifi-rtw88-fix-rtw_init_vht_cap-for-rtl8814au.patch @@ -0,0 +1,68 @@ +From 070dc0a1d1c328bd0ea95468e0d7f52a6ea5ab01 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 01:30:48 +0200 +Subject: wifi: rtw88: Fix rtw_init_vht_cap() for RTL8814AU + +From: Bitterblue Smith + +[ Upstream commit 6be7544d19fcfcb729495e793bc6181f85bb8949 ] + +Set the MCS maps and the highest rates according to the number of +spatial streams the chip has. For RTL8814AU that is 3. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/e86aa009-b5bf-4b3a-8112-ea5e3cd49465@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/main.c | 23 +++++++++-------------- + 1 file changed, 9 insertions(+), 14 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c +index bbdef38c7e341..2c81e4cae039e 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.c ++++ b/drivers/net/wireless/realtek/rtw88/main.c +@@ -1579,8 +1579,9 @@ static void rtw_init_vht_cap(struct rtw_dev *rtwdev, + struct ieee80211_sta_vht_cap *vht_cap) + { + struct rtw_efuse *efuse = &rtwdev->efuse; +- u16 mcs_map; ++ u16 mcs_map = 0; + __le16 highest; ++ int i; + + if (efuse->hw_cap.ptcl != EFUSE_HW_CAP_IGNORE && + efuse->hw_cap.ptcl != EFUSE_HW_CAP_PTCL_VHT) +@@ -1603,21 +1604,15 @@ static void rtw_init_vht_cap(struct rtw_dev *rtwdev, + if (rtw_chip_has_rx_ldpc(rtwdev)) + vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC; + +- mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | +- IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | +- IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | +- IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | +- IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | +- IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | +- IEEE80211_VHT_MCS_NOT_SUPPORTED << 14; +- if (efuse->hw_cap.nss > 1) { +- highest = cpu_to_le16(780); +- mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << 2; +- } else { +- highest = cpu_to_le16(390); +- mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << 2; ++ for (i = 0; i < 8; i++) { ++ if (i < efuse->hw_cap.nss) ++ mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2); ++ else ++ mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2); + } + ++ highest = cpu_to_le16(390 * efuse->hw_cap.nss); ++ + vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); + vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); + vht_cap->vht_mcs.rx_highest = highest; +-- +2.39.5 + diff --git a/queue-6.12/wifi-rtw89-8922a-fix-incorrect-sta-id-in-eht-mu-ppdu.patch b/queue-6.12/wifi-rtw89-8922a-fix-incorrect-sta-id-in-eht-mu-ppdu.patch new file mode 100644 index 0000000000..a597311a6d --- /dev/null +++ b/queue-6.12/wifi-rtw89-8922a-fix-incorrect-sta-id-in-eht-mu-ppdu.patch @@ -0,0 +1,41 @@ +From ef48e063634ebdfa97aa5e0565d7b737f7739141 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:12:35 +0800 +Subject: wifi: rtw89: 8922a: fix incorrect STA-ID in EHT MU PPDU + +From: Kuan-Chung Chen + +[ Upstream commit bdce0574243b43b3bb2064f609c0c326df44c4c6 ] + +EHT MU PPDU contains user field of EHT-SIG field with STA-ID that +must match AID subfield in the Associate Response. Add a necessary +setting to prevent these from being inconsistent. + +Signed-off-by: Kuan-Chung Chen +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250217061235.32031-1-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/fw.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index 93d760b8b5e35..9346fe082040c 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -3128,9 +3128,10 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, + CCTLINFO_G7_W5_NOMINAL_PKT_PADDING3 | + CCTLINFO_G7_W5_NOMINAL_PKT_PADDING4); + +- h2c->w6 = le32_encode_bits(vif->type == NL80211_IFTYPE_STATION ? 1 : 0, ++ h2c->w6 = le32_encode_bits(vif->cfg.aid, CCTLINFO_G7_W6_AID12_PAID) | ++ le32_encode_bits(vif->type == NL80211_IFTYPE_STATION ? 1 : 0, + CCTLINFO_G7_W6_ULDL); +- h2c->m6 = cpu_to_le32(CCTLINFO_G7_W6_ULDL); ++ h2c->m6 = cpu_to_le32(CCTLINFO_G7_W6_AID12_PAID | CCTLINFO_G7_W6_ULDL); + + if (rtwsta_link) { + h2c->w8 = le32_encode_bits(link_sta->he_cap.has_he, +-- +2.39.5 + diff --git a/queue-6.12/wifi-rtw89-add-wiphy_lock-to-work-that-isn-t-held-wi.patch b/queue-6.12/wifi-rtw89-add-wiphy_lock-to-work-that-isn-t-held-wi.patch new file mode 100644 index 0000000000..3c07e1a65c --- /dev/null +++ b/queue-6.12/wifi-rtw89-add-wiphy_lock-to-work-that-isn-t-held-wi.patch @@ -0,0 +1,72 @@ +From ad733f6142e71a25be0ed71b8f295eed572595fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 14:03:01 +0800 +Subject: wifi: rtw89: add wiphy_lock() to work that isn't held wiphy_lock() + yet + +From: Ping-Ke Shih + +[ Upstream commit ebfc9199df05d37b67f4d1b7ee997193f3d2e7c8 ] + +To ensure where are protected by driver mutex can also be protected by +wiphy_lock(), so afterward we can remove driver mutex safely. + +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250122060310.31976-2-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/regd.c | 2 ++ + drivers/net/wireless/realtek/rtw89/ser.c | 4 ++++ + 2 files changed, 6 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c +index bb064a086970b..e8df68818da01 100644 +--- a/drivers/net/wireless/realtek/rtw89/regd.c ++++ b/drivers/net/wireless/realtek/rtw89/regd.c +@@ -695,6 +695,7 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct rtw89_dev *rtwdev = hw->priv; + ++ wiphy_lock(wiphy); + mutex_lock(&rtwdev->mutex); + rtw89_leave_ps_mode(rtwdev); + +@@ -712,6 +713,7 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request + + exit: + mutex_unlock(&rtwdev->mutex); ++ wiphy_unlock(wiphy); + } + + /* Maximum Transmit Power field (@raw) can be EIRP or PSD. +diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c +index 7b203bb7f151a..02c2ac12f197a 100644 +--- a/drivers/net/wireless/realtek/rtw89/ser.c ++++ b/drivers/net/wireless/realtek/rtw89/ser.c +@@ -156,9 +156,11 @@ static void ser_state_run(struct rtw89_ser *ser, u8 evt) + rtw89_debug(rtwdev, RTW89_DBG_SER, "ser: %s receive %s\n", + ser_st_name(ser), ser_ev_name(ser, evt)); + ++ wiphy_lock(rtwdev->hw->wiphy); + mutex_lock(&rtwdev->mutex); + rtw89_leave_lps(rtwdev); + mutex_unlock(&rtwdev->mutex); ++ wiphy_unlock(rtwdev->hw->wiphy); + + ser->st_tbl[ser->state].st_func(ser, evt); + } +@@ -707,9 +709,11 @@ static void ser_l2_reset_st_hdl(struct rtw89_ser *ser, u8 evt) + + switch (evt) { + case SER_EV_STATE_IN: ++ wiphy_lock(rtwdev->hw->wiphy); + mutex_lock(&rtwdev->mutex); + ser_l2_reset_st_pre_hdl(ser); + mutex_unlock(&rtwdev->mutex); ++ wiphy_unlock(rtwdev->hw->wiphy); + + ieee80211_restart_hw(rtwdev->hw); + ser_set_alarm(ser, SER_RECFG_TIMEOUT, SER_EV_L2_RECFG_TIMEOUT); +-- +2.39.5 + diff --git a/queue-6.12/wifi-rtw89-call-power_on-ahead-before-selecting-firm.patch b/queue-6.12/wifi-rtw89-call-power_on-ahead-before-selecting-firm.patch new file mode 100644 index 0000000000..8333cca831 --- /dev/null +++ b/queue-6.12/wifi-rtw89-call-power_on-ahead-before-selecting-firm.patch @@ -0,0 +1,168 @@ +From f57ee9a8468718e730f68ea164e05b6e20f53a80 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 15:29:08 +0800 +Subject: wifi: rtw89: call power_on ahead before selecting firmware + +From: Ping-Ke Shih + +[ Upstream commit d078f5857a00c06fa0ddee26d3cb722e938e1688 ] + +Driver selects firmware by hardware version, which normally can be read +from registers before selecting firmware. However, certain chips such as +RTL8851B, it needs to read hardware version from efuse while doing +power_on, but do power_on after selecting firmware in current flow. + +To resolve this flow problem, move power_on out from +rtw89_mac_partial_init(), and call rtw89_mac_pwr_on() separately at +proper places to have expected flow. + +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250203072911.47313-2-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/core.c | 23 +++++++++++------- + drivers/net/wireless/realtek/rtw89/mac.c | 29 ++++++++++++++++------- + drivers/net/wireless/realtek/rtw89/mac.h | 1 + + 3 files changed, 36 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c +index f82a26be6fa82..83b22bd0ce81a 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.c ++++ b/drivers/net/wireless/realtek/rtw89/core.c +@@ -4862,8 +4862,6 @@ static int rtw89_chip_efuse_info_setup(struct rtw89_dev *rtwdev) + + rtw89_hci_mac_pre_deinit(rtwdev); + +- rtw89_mac_pwr_off(rtwdev); +- + return 0; + } + +@@ -4944,36 +4942,45 @@ int rtw89_chip_info_setup(struct rtw89_dev *rtwdev) + + rtw89_read_chip_ver(rtwdev); + ++ ret = rtw89_mac_pwr_on(rtwdev); ++ if (ret) { ++ rtw89_err(rtwdev, "failed to power on\n"); ++ return ret; ++ } ++ + ret = rtw89_wait_firmware_completion(rtwdev); + if (ret) { + rtw89_err(rtwdev, "failed to wait firmware completion\n"); +- return ret; ++ goto out; + } + + ret = rtw89_fw_recognize(rtwdev); + if (ret) { + rtw89_err(rtwdev, "failed to recognize firmware\n"); +- return ret; ++ goto out; + } + + ret = rtw89_chip_efuse_info_setup(rtwdev); + if (ret) +- return ret; ++ goto out; + + ret = rtw89_fw_recognize_elements(rtwdev); + if (ret) { + rtw89_err(rtwdev, "failed to recognize firmware elements\n"); +- return ret; ++ goto out; + } + + ret = rtw89_chip_board_info_setup(rtwdev); + if (ret) +- return ret; ++ goto out; + + rtw89_core_setup_rfe_parms(rtwdev); + rtwdev->ps_mode = rtw89_update_ps_mode(rtwdev); + +- return 0; ++out: ++ rtw89_mac_pwr_off(rtwdev); ++ ++ return ret; + } + EXPORT_SYMBOL(rtw89_chip_info_setup); + +diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c +index 04e254bd6b17f..9b09d4b7dea59 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.c ++++ b/drivers/net/wireless/realtek/rtw89/mac.c +@@ -1491,6 +1491,21 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on) + #undef PWR_ACT + } + ++int rtw89_mac_pwr_on(struct rtw89_dev *rtwdev) ++{ ++ int ret; ++ ++ ret = rtw89_mac_power_switch(rtwdev, true); ++ if (ret) { ++ rtw89_mac_power_switch(rtwdev, false); ++ ret = rtw89_mac_power_switch(rtwdev, true); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ + void rtw89_mac_pwr_off(struct rtw89_dev *rtwdev) + { + rtw89_mac_power_switch(rtwdev, false); +@@ -3918,14 +3933,6 @@ int rtw89_mac_partial_init(struct rtw89_dev *rtwdev, bool include_bb) + { + int ret; + +- ret = rtw89_mac_power_switch(rtwdev, true); +- if (ret) { +- rtw89_mac_power_switch(rtwdev, false); +- ret = rtw89_mac_power_switch(rtwdev, true); +- if (ret) +- return ret; +- } +- + rtw89_mac_ctrl_hci_dma_trx(rtwdev, true); + + if (include_bb) { +@@ -3958,6 +3965,10 @@ int rtw89_mac_init(struct rtw89_dev *rtwdev) + bool include_bb = !!chip->bbmcu_nr; + int ret; + ++ ret = rtw89_mac_pwr_on(rtwdev); ++ if (ret) ++ return ret; ++ + ret = rtw89_mac_partial_init(rtwdev, include_bb); + if (ret) + goto fail; +@@ -3989,7 +4000,7 @@ int rtw89_mac_init(struct rtw89_dev *rtwdev) + + return ret; + fail: +- rtw89_mac_power_switch(rtwdev, false); ++ rtw89_mac_pwr_off(rtwdev); + + return ret; + } +diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h +index 5ba1133b79d64..7974849f41e25 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.h ++++ b/drivers/net/wireless/realtek/rtw89/mac.h +@@ -1120,6 +1120,7 @@ rtw89_write32_port_set(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_l + rtw89_write32_set(rtwdev, reg, bit); + } + ++int rtw89_mac_pwr_on(struct rtw89_dev *rtwdev); + void rtw89_mac_pwr_off(struct rtw89_dev *rtwdev); + int rtw89_mac_partial_init(struct rtw89_dev *rtwdev, bool include_bb); + int rtw89_mac_init(struct rtw89_dev *rtwdev); +-- +2.39.5 + diff --git a/queue-6.12/wifi-rtw89-coex-assign-value-over-than-0-to-avoid-fi.patch b/queue-6.12/wifi-rtw89-coex-assign-value-over-than-0-to-avoid-fi.patch new file mode 100644 index 0000000000..6db0902553 --- /dev/null +++ b/queue-6.12/wifi-rtw89-coex-assign-value-over-than-0-to-avoid-fi.patch @@ -0,0 +1,42 @@ +From 647e580fd18c847d064104754558146f4bedc356 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 09:32:31 +0800 +Subject: wifi: rtw89: coex: Assign value over than 0 to avoid firmware timer + hang + +From: Ching-Te Ku + +[ Upstream commit 2e4c4717b3f6f019c71af984564b6e4d0ae8d0bd ] + +If the slot duration is 0, the firmware timer will trigger timer hang at +the timer initializing state in a low rate due to hardware algorithm. + +Signed-off-by: Ching-Te Ku +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250205013233.10945-2-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/coex.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c +index 8d54d71fcf539..5f878f086f7cf 100644 +--- a/drivers/net/wireless/realtek/rtw89/coex.c ++++ b/drivers/net/wireless/realtek/rtw89/coex.c +@@ -89,10 +89,10 @@ static const struct rtw89_btc_fbtc_slot s_def[] = { + [CXST_B4] = __DEF_FBTC_SLOT(50, 0xe5555555, SLOT_MIX), + [CXST_LK] = __DEF_FBTC_SLOT(20, 0xea5a5a5a, SLOT_ISO), + [CXST_BLK] = __DEF_FBTC_SLOT(500, 0x55555555, SLOT_MIX), +- [CXST_E2G] = __DEF_FBTC_SLOT(0, 0xea5a5a5a, SLOT_MIX), +- [CXST_E5G] = __DEF_FBTC_SLOT(0, 0xffffffff, SLOT_ISO), ++ [CXST_E2G] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_MIX), ++ [CXST_E5G] = __DEF_FBTC_SLOT(5, 0xffffffff, SLOT_ISO), + [CXST_EBT] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX), +- [CXST_ENULL] = __DEF_FBTC_SLOT(0, 0xaaaaaaaa, SLOT_ISO), ++ [CXST_ENULL] = __DEF_FBTC_SLOT(5, 0xaaaaaaaa, SLOT_ISO), + [CXST_WLK] = __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX), + [CXST_W1FDD] = __DEF_FBTC_SLOT(50, 0xffffffff, SLOT_ISO), + [CXST_B1FDD] = __DEF_FBTC_SLOT(50, 0xffffdfff, SLOT_ISO), +-- +2.39.5 + diff --git a/queue-6.12/wifi-rtw89-coex-separated-wi-fi-connecting-event-fro.patch b/queue-6.12/wifi-rtw89-coex-separated-wi-fi-connecting-event-fro.patch new file mode 100644 index 0000000000..8c016cafb1 --- /dev/null +++ b/queue-6.12/wifi-rtw89-coex-separated-wi-fi-connecting-event-fro.patch @@ -0,0 +1,59 @@ +From b659357ef7cdec0b54e38908abe7f9cc9de384b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jan 2025 09:54:15 +0800 +Subject: wifi: rtw89: coex: Separated Wi-Fi connecting event from Wi-Fi scan + event + +From: Ching-Te Ku + +[ Upstream commit 4a57346652154bb339c48b41166df9154cff33f5 ] + +Wi-Fi connecting process don't need to assign to firmware slot control, +if assign firmware slot control for Wi-Fi connecting event, firmware will +not toggle slots because driver don't tell the slot schedule to firmware. +Wi-Fi connecting event end should also cancel the 4way handshake status. + +Signed-off-by: Ching-Te Ku +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250110015416.10704-3-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/coex.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c +index 5f878f086f7cf..6cdbf02f405ae 100644 +--- a/drivers/net/wireless/realtek/rtw89/coex.c ++++ b/drivers/net/wireless/realtek/rtw89/coex.c +@@ -5356,7 +5356,8 @@ static void _action_wl_scan(struct rtw89_dev *rtwdev) + struct rtw89_btc_wl_info *wl = &btc->cx.wl; + struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; + +- if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) { ++ if (btc->cx.state_map != BTC_WLINKING && ++ RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) { + _action_wl_25g_mcc(rtwdev); + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n"); + } else if (rtwdev->dbcc_en) { +@@ -7178,6 +7179,8 @@ void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx) + _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); + } + ++ btc->dm.tdma_instant_excute = 1; ++ + _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH); + } + +@@ -7630,7 +7633,8 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + else + wl->status.map.connecting = 0; + +- if (state == BTC_ROLE_MSTS_STA_DIS_CONN) ++ if (state == BTC_ROLE_MSTS_STA_DIS_CONN || ++ state == BTC_ROLE_MSTS_STA_CONN_END) + wl->status.map._4way = false; + + _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO); +-- +2.39.5 + diff --git a/queue-6.12/wifi-rtw89-fw-add-blacklist-to-avoid-obsolete-secure.patch b/queue-6.12/wifi-rtw89-fw-add-blacklist-to-avoid-obsolete-secure.patch new file mode 100644 index 0000000000..86147a1e95 --- /dev/null +++ b/queue-6.12/wifi-rtw89-fw-add-blacklist-to-avoid-obsolete-secure.patch @@ -0,0 +1,229 @@ +From 3d93caea03a632f84e2b5394e9301b5982583273 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:43:04 +0800 +Subject: wifi: rtw89: fw: add blacklist to avoid obsolete secure firmware + +From: Ping-Ke Shih + +[ Upstream commit f11d042b3a2e92ab1aa10e0da8e290bcdcf31d39 ] + +To ensure secure chip only runs expected secure firmware, stop using +obsolete firmware in blacklist which weakness or flaw was found. + +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250217064308.43559-2-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/core.h | 2 + + drivers/net/wireless/realtek/rtw89/fw.c | 52 ++++++++++++++++++- + drivers/net/wireless/realtek/rtw89/fw.h | 12 +++++ + drivers/net/wireless/realtek/rtw89/rtw8851b.c | 1 + + drivers/net/wireless/realtek/rtw89/rtw8852a.c | 1 + + drivers/net/wireless/realtek/rtw89/rtw8852b.c | 1 + + .../net/wireless/realtek/rtw89/rtw8852bt.c | 1 + + drivers/net/wireless/realtek/rtw89/rtw8852c.c | 1 + + drivers/net/wireless/realtek/rtw89/rtw8922a.c | 1 + + 9 files changed, 71 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h +index ff3048d2489f1..4f64ea392e6c9 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.h ++++ b/drivers/net/wireless/realtek/rtw89/core.h +@@ -17,6 +17,7 @@ struct rtw89_dev; + struct rtw89_pci_info; + struct rtw89_mac_gen_def; + struct rtw89_phy_gen_def; ++struct rtw89_fw_blacklist; + struct rtw89_efuse_block_cfg; + struct rtw89_h2c_rf_tssi; + struct rtw89_fw_txpwr_track_cfg; +@@ -4232,6 +4233,7 @@ struct rtw89_chip_info { + bool try_ce_fw; + u8 bbmcu_nr; + u32 needed_fw_elms; ++ const struct rtw89_fw_blacklist *fw_blacklist; + u32 fifo_size; + bool small_fifo_size; + u32 dle_scc_rsvd_size; +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index f0e87af68d8cb..93d760b8b5e35 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -38,6 +38,16 @@ struct rtw89_arp_rsp { + + static const u8 mss_signature[] = {0x4D, 0x53, 0x53, 0x4B, 0x50, 0x4F, 0x4F, 0x4C}; + ++const struct rtw89_fw_blacklist rtw89_fw_blacklist_default = { ++ .ver = 0x00, ++ .list = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ }, ++}; ++EXPORT_SYMBOL(rtw89_fw_blacklist_default); ++ + union rtw89_fw_element_arg { + size_t offset; + enum rtw89_rf_path rf_path; +@@ -315,6 +325,46 @@ static int __parse_formatted_mssc(struct rtw89_dev *rtwdev, + return 0; + } + ++static int __check_secure_blacklist(struct rtw89_dev *rtwdev, ++ struct rtw89_fw_bin_info *info, ++ struct rtw89_fw_hdr_section_info *section_info, ++ const void *content) ++{ ++ const struct rtw89_fw_blacklist *chip_blacklist = rtwdev->chip->fw_blacklist; ++ const union rtw89_fw_section_mssc_content *section_content = content; ++ struct rtw89_fw_secure *sec = &rtwdev->fw.sec; ++ u8 byte_idx; ++ u8 bit_mask; ++ ++ if (!sec->secure_boot) ++ return 0; ++ ++ if (!info->secure_section_exist || section_info->ignore) ++ return 0; ++ ++ if (!chip_blacklist) { ++ rtw89_err(rtwdev, "chip no blacklist for secure firmware\n"); ++ return -ENOENT; ++ } ++ ++ byte_idx = section_content->blacklist.bit_in_chip_list >> 3; ++ bit_mask = BIT(section_content->blacklist.bit_in_chip_list & 0x7); ++ ++ if (section_content->blacklist.ver > chip_blacklist->ver) { ++ rtw89_err(rtwdev, "chip blacklist out of date (%u, %u)\n", ++ section_content->blacklist.ver, chip_blacklist->ver); ++ return -EINVAL; ++ } ++ ++ if (chip_blacklist->list[byte_idx] & bit_mask) { ++ rtw89_err(rtwdev, "firmware %u in chip blacklist\n", ++ section_content->blacklist.ver); ++ return -EPERM; ++ } ++ ++ return 0; ++} ++ + static int __parse_security_section(struct rtw89_dev *rtwdev, + struct rtw89_fw_bin_info *info, + struct rtw89_fw_hdr_section_info *section_info, +@@ -340,7 +390,7 @@ static int __parse_security_section(struct rtw89_dev *rtwdev, + info->secure_section_exist = true; + } + +- return 0; ++ return __check_secure_blacklist(rtwdev, info, section_info, content); + } + + static int rtw89_fw_hdr_parser_v1(struct rtw89_dev *rtwdev, const u8 *fw, u32 len, +diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h +index ccbbc43f33fee..502ece540b9dc 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.h ++++ b/drivers/net/wireless/realtek/rtw89/fw.h +@@ -639,6 +639,11 @@ struct rtw89_fw_mss_pool_hdr { + } __packed; + + union rtw89_fw_section_mssc_content { ++ struct { ++ u8 pad[0x20]; ++ u8 bit_in_chip_list; ++ u8 ver; ++ } __packed blacklist; + struct { + u8 pad[58]; + __le32 v; +@@ -649,6 +654,13 @@ union rtw89_fw_section_mssc_content { + } __packed key_sign_len; + } __packed; + ++struct rtw89_fw_blacklist { ++ u8 ver; ++ u8 list[32]; ++}; ++ ++extern const struct rtw89_fw_blacklist rtw89_fw_blacklist_default; ++ + static inline void SET_CTRL_INFO_MACID(void *table, u32 val) + { + le32p_replace_bits((__le32 *)(table) + 0, val, GENMASK(6, 0)); +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c +index f9766bf30e71d..0d2a1e712b345 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c +@@ -2443,6 +2443,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = { + .try_ce_fw = true, + .bbmcu_nr = 0, + .needed_fw_elms = 0, ++ .fw_blacklist = NULL, + .fifo_size = 196608, + .small_fifo_size = true, + .dle_scc_rsvd_size = 98304, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c +index 42d369d2e916a..5f08207936c68 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c +@@ -2159,6 +2159,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { + .try_ce_fw = false, + .bbmcu_nr = 0, + .needed_fw_elms = 0, ++ .fw_blacklist = NULL, + .fifo_size = 458752, + .small_fifo_size = false, + .dle_scc_rsvd_size = 0, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c +index 364aa21cbd446..0e03d97ba1cf6 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c +@@ -797,6 +797,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { + .try_ce_fw = true, + .bbmcu_nr = 0, + .needed_fw_elms = 0, ++ .fw_blacklist = &rtw89_fw_blacklist_default, + .fifo_size = 196608, + .small_fifo_size = true, + .dle_scc_rsvd_size = 98304, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c +index dab7e71ec6a14..1dd3e51bab9f3 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c +@@ -731,6 +731,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = { + .try_ce_fw = true, + .bbmcu_nr = 0, + .needed_fw_elms = RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS_NO_6GHZ, ++ .fw_blacklist = &rtw89_fw_blacklist_default, + .fifo_size = 458752, + .small_fifo_size = true, + .dle_scc_rsvd_size = 98304, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c +index dbe77abb2c488..5e2592cf1a9fa 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c +@@ -2936,6 +2936,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { + .try_ce_fw = false, + .bbmcu_nr = 0, + .needed_fw_elms = 0, ++ .fw_blacklist = &rtw89_fw_blacklist_default, + .fifo_size = 458752, + .small_fifo_size = false, + .dle_scc_rsvd_size = 0, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c +index ef7747adbcc2b..64a41f24b2adb 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c +@@ -2632,6 +2632,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = { + .try_ce_fw = false, + .bbmcu_nr = 1, + .needed_fw_elms = RTW89_BE_GEN_DEF_NEEDED_FW_ELEMENTS, ++ .fw_blacklist = &rtw89_fw_blacklist_default, + .fifo_size = 589824, + .small_fifo_size = false, + .dle_scc_rsvd_size = 0, +-- +2.39.5 + diff --git a/queue-6.12/wifi-rtw89-fw-get-sb_sel_ver-via-get_unaligned_le32.patch b/queue-6.12/wifi-rtw89-fw-get-sb_sel_ver-via-get_unaligned_le32.patch new file mode 100644 index 0000000000..da6a7af124 --- /dev/null +++ b/queue-6.12/wifi-rtw89-fw-get-sb_sel_ver-via-get_unaligned_le32.patch @@ -0,0 +1,36 @@ +From 0f8ea39a1b5a1a8bc50560df87c71682528282bc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:43:05 +0800 +Subject: wifi: rtw89: fw: get sb_sel_ver via get_unaligned_le32() + +From: Ping-Ke Shih + +[ Upstream commit 2f9da853f4d848d23bade4c22931ea0f5a011674 ] + +The sb_sel_ver is selection version for secure boot recorded in firmware +binary data, and its size is 4 and offset is 58 (not natural alignment). +Use get_unaligned_le32() to get this value safely. Find this by reviewing. + +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250217064308.43559-3-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/fw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index 9d26502a2885a..f0e87af68d8cb 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -285,7 +285,7 @@ static int __parse_formatted_mssc(struct rtw89_dev *rtwdev, + if (!sec->secure_boot) + goto out; + +- sb_sel_ver = le32_to_cpu(section_content->sb_sel_ver.v); ++ sb_sel_ver = get_unaligned_le32(§ion_content->sb_sel_ver.v); + if (sb_sel_ver && sb_sel_ver != sec->sb_sel_mgn) + goto ignore; + +-- +2.39.5 + diff --git a/queue-6.12/wifi-rtw89-fw-propagate-error-code-from-rtw89_h2c_tx.patch b/queue-6.12/wifi-rtw89-fw-propagate-error-code-from-rtw89_h2c_tx.patch new file mode 100644 index 0000000000..8af4cde4b2 --- /dev/null +++ b/queue-6.12/wifi-rtw89-fw-propagate-error-code-from-rtw89_h2c_tx.patch @@ -0,0 +1,42 @@ +From 28a308fb5776f08234564ef8276bd78f5be8bac0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:43:06 +0800 +Subject: wifi: rtw89: fw: propagate error code from rtw89_h2c_tx() + +From: Ping-Ke Shih + +[ Upstream commit 56e1acaa0f80620b8e2c3410db35b4b975782b0a ] + +The error code should be propagated to callers during downloading firmware +header and body. Remove unnecessary assignment of -1. + +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250217064308.43559-4-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/fw.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index 620e076d1b597..9d26502a2885a 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -1234,7 +1234,6 @@ static int __rtw89_fw_download_hdr(struct rtw89_dev *rtwdev, + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); +- ret = -1; + goto fail; + } + +@@ -1311,7 +1310,6 @@ static int __rtw89_fw_download_main(struct rtw89_dev *rtwdev, + ret = rtw89_h2c_tx(rtwdev, skb, true); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); +- ret = -1; + goto fail; + } + +-- +2.39.5 + diff --git a/queue-6.12/wifi-rtw89-fw-validate-multi-firmware-header-before-.patch b/queue-6.12/wifi-rtw89-fw-validate-multi-firmware-header-before-.patch new file mode 100644 index 0000000000..e07fa66563 --- /dev/null +++ b/queue-6.12/wifi-rtw89-fw-validate-multi-firmware-header-before-.patch @@ -0,0 +1,73 @@ +From ba8d64cbf590ba3149c39062f4c474e98909de0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 15:29:11 +0800 +Subject: wifi: rtw89: fw: validate multi-firmware header before getting its + size + +From: Ping-Ke Shih + +[ Upstream commit 2b8bdc5237014cc61784b3676cbaca5325959f3d ] + +To access firmware elements appended after multi-firmware, add its size +as offset to get start address of firmware elements. + + +-----+-------+------+---------+--------------+ -- + | sig | fw_nr | rsvd | version | reserved | \ + +---------------------------------------------+ | + fw 0 | cv | type | mp | rsvd | shift | size | rsvd | | + +---------------------------------------------+ | + fw 1 | cv | type | mp | rsvd | shift | size | rsvd | | + +---------------------------------------------+ | + fw N-1 | ... | | + +=============================================+ | mfw size + | fw 0 content | | + +=============================================+ | + | fw 1 content | | + +=============================================+ | + | ... | | + +=============================================+ | + | fw N -1 content | | + +=============================================+ --/ + | fw element TLV X | + +=============================================+ + | fw element TLV Y | + +=============================================+ + | fw element TLV Z | + +=============================================+ + +To avoid Coverity warning when getting mfw size, validate it header ahead. + +Addresses-Coverity-ID: 1544385 ("Untrusted array index read") + +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250203072911.47313-5-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/fw.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index 9346fe082040c..520dc0bc01956 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -563,12 +563,17 @@ static u32 rtw89_mfw_get_size(struct rtw89_dev *rtwdev) + (const struct rtw89_mfw_hdr *)firmware->data; + const struct rtw89_mfw_info *mfw_info; + u32 size; ++ int ret; + + if (mfw_hdr->sig != RTW89_MFW_SIG) { + rtw89_warn(rtwdev, "not mfw format\n"); + return 0; + } + ++ ret = rtw89_mfw_validate_hdr(rtwdev, firmware, mfw_hdr); ++ if (ret) ++ return ret; ++ + mfw_info = &mfw_hdr->info[mfw_hdr->fw_nr - 1]; + size = le32_to_cpu(mfw_info->shift) + le32_to_cpu(mfw_info->size); + +-- +2.39.5 + diff --git a/queue-6.12/wifi-rtw89-fw-validate-multi-firmware-header-before-.patch-29952 b/queue-6.12/wifi-rtw89-fw-validate-multi-firmware-header-before-.patch-29952 new file mode 100644 index 0000000000..cbdf7f4f97 --- /dev/null +++ b/queue-6.12/wifi-rtw89-fw-validate-multi-firmware-header-before-.patch-29952 @@ -0,0 +1,107 @@ +From eda9fd28c0a4e8468aa88da2fd777943a114da57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 15:29:10 +0800 +Subject: wifi: rtw89: fw: validate multi-firmware header before accessing + +From: Ping-Ke Shih + +[ Upstream commit 1f0efffd597893404aea5c3d4f1bdaa1c61d4434 ] + +A firmeware file contains multi-firmware with a header to represent +contents. The mfw_hdr->fw_nr is to define number of firmware in file. + + +-----+-------+------+---------+--------------+ + | sig | fw_nr | rsvd | version | reserved | + +---------------------------------------------+ -- + fw 0 | cv | type | mp | rsvd | shift | size | rsvd | \ + +---------------------------------------------+ | + fw 1 | cv | type | mp | rsvd | shift | size | rsvd | | mfw_hdr->fw_nr + +---------------------------------------------+ | + fw N-1 | ... | / + +=============================================+ -- + | fw 0 content | + | (pointed by fw0 shift/size) | + +=============================================+ + +To avoid Coverity warning, validate header is in range of firmware size, +and also validate the range of actual firmware content is in range. + +Addresses-Coverity-ID: 1494046 ("Untrusted loop bound") + +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250203072911.47313-4-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/fw.c | 35 +++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index 520dc0bc01956..e5c90050e7115 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -501,6 +501,30 @@ static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, + } + } + ++static int rtw89_mfw_validate_hdr(struct rtw89_dev *rtwdev, ++ const struct firmware *firmware, ++ const struct rtw89_mfw_hdr *mfw_hdr) ++{ ++ const void *mfw = firmware->data; ++ u32 mfw_len = firmware->size; ++ u8 fw_nr = mfw_hdr->fw_nr; ++ const void *ptr; ++ ++ if (fw_nr == 0) { ++ rtw89_err(rtwdev, "mfw header has no fw entry\n"); ++ return -ENOENT; ++ } ++ ++ ptr = &mfw_hdr->info[fw_nr]; ++ ++ if (ptr > mfw + mfw_len) { ++ rtw89_err(rtwdev, "mfw header out of address\n"); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ + static + int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, + struct rtw89_fw_suit *fw_suit, bool nowarn) +@@ -511,6 +535,7 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, + u32 mfw_len = firmware->size; + const struct rtw89_mfw_hdr *mfw_hdr = (const struct rtw89_mfw_hdr *)mfw; + const struct rtw89_mfw_info *mfw_info = NULL, *tmp; ++ int ret; + int i; + + if (mfw_hdr->sig != RTW89_MFW_SIG) { +@@ -523,6 +548,10 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, + return 0; + } + ++ ret = rtw89_mfw_validate_hdr(rtwdev, firmware, mfw_hdr); ++ if (ret) ++ return ret; ++ + for (i = 0; i < mfw_hdr->fw_nr; i++) { + tmp = &mfw_hdr->info[i]; + if (tmp->type != type) +@@ -552,6 +581,12 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, + found: + fw_suit->data = mfw + le32_to_cpu(mfw_info->shift); + fw_suit->size = le32_to_cpu(mfw_info->size); ++ ++ if (fw_suit->data + fw_suit->size > mfw + mfw_len) { ++ rtw89_err(rtwdev, "fw_suit %d out of address\n", type); ++ return -EFAULT; ++ } ++ + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.12/wifi-rtw89-set-force-he-tb-mode-when-connecting-to-1.patch b/queue-6.12/wifi-rtw89-set-force-he-tb-mode-when-connecting-to-1.patch new file mode 100644 index 0000000000..3435b261d3 --- /dev/null +++ b/queue-6.12/wifi-rtw89-set-force-he-tb-mode-when-connecting-to-1.patch @@ -0,0 +1,105 @@ +From 85b661ca54f2051fc431eaea0a8e1b8743b0569b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 10:11:44 +0800 +Subject: wifi: rtw89: set force HE TB mode when connecting to 11ax AP + +From: Dian-Syuan Yang + +[ Upstream commit a9b56f219a0fa550f92e65ac58443a7892380e09 ] + +Some of 11ax AP set the UL HE-SIG-A2 reserved subfield to all 0s, which +will cause the 11be chip to recognize trigger frame as EHT. We propose +a method to bypass the "UL HE-SIG-A2 reserved subfield" and always uses +HE TB in response to the AP's trigger frame. + +Signed-off-by: Dian-Syuan Yang +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250306021144.12854-6-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/mac.c | 26 +++++++++++++++++++ + drivers/net/wireless/realtek/rtw89/mac.h | 2 ++ + drivers/net/wireless/realtek/rtw89/mac80211.c | 1 + + drivers/net/wireless/realtek/rtw89/reg.h | 4 +++ + 4 files changed, 33 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c +index 4574aa62839b0..04e254bd6b17f 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.c ++++ b/drivers/net/wireless/realtek/rtw89/mac.c +@@ -4745,6 +4745,32 @@ void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev, + rtw89_write32_set(rtwdev, reg, mac->narrow_bw_ru_dis.mask); + } + ++void rtw89_mac_set_he_tb(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) ++{ ++ struct ieee80211_bss_conf *bss_conf; ++ bool set; ++ u32 reg; ++ ++ if (rtwdev->chip->chip_gen != RTW89_CHIP_BE) ++ return; ++ ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ set = bss_conf->he_support && !bss_conf->eht_support; ++ ++ rcu_read_unlock(); ++ ++ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_CLIENT_OM_CTRL, ++ rtwvif_link->mac_idx); ++ ++ if (set) ++ rtw89_write32_set(rtwdev, reg, B_BE_TRIG_DIS_EHTTB); ++ else ++ rtw89_write32_clr(rtwdev, reg, B_BE_TRIG_DIS_EHTTB); ++} ++ + void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { + rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif_link); +diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h +index 0c269961a5731..5ba1133b79d64 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.h ++++ b/drivers/net/wireless/realtek/rtw89/mac.h +@@ -1160,6 +1160,8 @@ void rtw89_mac_port_cfg_rx_sync(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool en); + void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link); ++void rtw89_mac_set_he_tb(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link); + void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); + void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en); + int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif); +diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c +index 8351a70d325d4..3a1a2b243adf0 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac80211.c ++++ b/drivers/net/wireless/realtek/rtw89/mac80211.c +@@ -669,6 +669,7 @@ static void __rtw89_ops_bss_link_assoc(struct rtw89_dev *rtwdev, + rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, rtwvif_link); + rtw89_mac_port_update(rtwdev, rtwvif_link); + rtw89_mac_set_he_obss_narrow_bw_ru(rtwdev, rtwvif_link); ++ rtw89_mac_set_he_tb(rtwdev, rtwvif_link); + } + + static void __rtw89_ops_bss_assoc(struct rtw89_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h +index 69678eab23093..9fbcc7fee290f 100644 +--- a/drivers/net/wireless/realtek/rtw89/reg.h ++++ b/drivers/net/wireless/realtek/rtw89/reg.h +@@ -7093,6 +7093,10 @@ + #define B_BE_MACLBK_RDY_NUM_MASK GENMASK(7, 3) + #define B_BE_MACLBK_EN BIT(0) + ++#define R_BE_CLIENT_OM_CTRL 0x11040 ++#define R_BE_CLIENT_OM_CTRL_C1 0x15040 ++#define B_BE_TRIG_DIS_EHTTB BIT(24) ++ + #define R_BE_WMAC_NAV_CTL 0x11080 + #define R_BE_WMAC_NAV_CTL_C1 0x15080 + #define B_BE_WMAC_NAV_UPPER_EN BIT(26) +-- +2.39.5 + diff --git a/queue-6.12/x86-boot-disable-stack-protector-for-early-boot-code.patch b/queue-6.12/x86-boot-disable-stack-protector-for-early-boot-code.patch new file mode 100644 index 0000000000..7aac650751 --- /dev/null +++ b/queue-6.12/x86-boot-disable-stack-protector-for-early-boot-code.patch @@ -0,0 +1,44 @@ +From f3a1f548fbc2cab8c4d91ecfea486ba5fca42986 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 14:07:35 -0500 +Subject: x86/boot: Disable stack protector for early boot code + +From: Brian Gerst + +[ Upstream commit a9a76b38aaf577887103e3ebb41d70e6aa5a4b19 ] + +On 64-bit, this will prevent crashes when the canary access is changed +from %gs:40 to %gs:__stack_chk_guard(%rip). RIP-relative addresses from +the identity-mapped early boot code will target the wrong address with +zero-based percpu. KASLR could then shift that address to an unmapped +page causing a crash on boot. + +This early boot code runs well before user-space is active and does not +need stack protector enabled. + +Signed-off-by: Brian Gerst +Signed-off-by: Ingo Molnar +Reviewed-by: Ard Biesheuvel +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/20250123190747.745588-4-brgerst@gmail.com +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/Makefile | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile +index f7918980667a3..f42c0903ef86d 100644 +--- a/arch/x86/kernel/Makefile ++++ b/arch/x86/kernel/Makefile +@@ -44,6 +44,8 @@ KCOV_INSTRUMENT_unwind_orc.o := n + KCOV_INSTRUMENT_unwind_frame.o := n + KCOV_INSTRUMENT_unwind_guess.o := n + ++CFLAGS_head32.o := -fno-stack-protector ++CFLAGS_head64.o := -fno-stack-protector + CFLAGS_irq.o := -I $(src)/../include/asm/trace + + obj-y += head_$(BITS).o +-- +2.39.5 + diff --git a/queue-6.12/x86-bugs-make-spectre-user-default-depend-on-mitigat.patch b/queue-6.12/x86-bugs-make-spectre-user-default-depend-on-mitigat.patch new file mode 100644 index 0000000000..87d143d023 --- /dev/null +++ b/queue-6.12/x86-bugs-make-spectre-user-default-depend-on-mitigat.patch @@ -0,0 +1,96 @@ +From 487e0bbdeea67b065f371a2ad345896a6e3cc543 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 31 Oct 2024 04:06:17 -0700 +Subject: x86/bugs: Make spectre user default depend on MITIGATION_SPECTRE_V2 + +From: Breno Leitao + +[ Upstream commit 98fdaeb296f51ef08e727a7cc72e5b5c864c4f4d ] + +Change the default value of spectre v2 in user mode to respect the +CONFIG_MITIGATION_SPECTRE_V2 config option. + +Currently, user mode spectre v2 is set to auto +(SPECTRE_V2_USER_CMD_AUTO) by default, even if +CONFIG_MITIGATION_SPECTRE_V2 is disabled. + +Set the spectre_v2 value to auto (SPECTRE_V2_USER_CMD_AUTO) if the +Spectre v2 config (CONFIG_MITIGATION_SPECTRE_V2) is enabled, otherwise +set the value to none (SPECTRE_V2_USER_CMD_NONE). + +Important to say the command line argument "spectre_v2_user" overwrites +the default value in both cases. + +When CONFIG_MITIGATION_SPECTRE_V2 is not set, users have the flexibility +to opt-in for specific mitigations independently. In this scenario, +setting spectre_v2= will not enable spectre_v2_user=, and command line +options spectre_v2_user and spectre_v2 are independent when +CONFIG_MITIGATION_SPECTRE_V2=n. + +Signed-off-by: Breno Leitao +Signed-off-by: Ingo Molnar +Reviewed-by: Pawan Gupta +Acked-by: Josh Poimboeuf +Cc: Peter Zijlstra +Cc: David Kaplan +Link: https://lore.kernel.org/r/20241031-x86_bugs_last_v2-v2-2-b7ff1dab840e@debian.org +Signed-off-by: Sasha Levin +--- + Documentation/admin-guide/kernel-parameters.txt | 2 ++ + arch/x86/kernel/cpu/bugs.c | 10 +++++++--- + 2 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt +index e691f75c97e7b..b5cb361485541 100644 +--- a/Documentation/admin-guide/kernel-parameters.txt ++++ b/Documentation/admin-guide/kernel-parameters.txt +@@ -6261,6 +6261,8 @@ + + Selecting 'on' will also enable the mitigation + against user space to user space task attacks. ++ Selecting specific mitigation does not force enable ++ user mitigations. + + Selecting 'off' will disable both the kernel and + the user space protections. +diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c +index c683abd640fde..0e9ab0b9a4942 100644 +--- a/arch/x86/kernel/cpu/bugs.c ++++ b/arch/x86/kernel/cpu/bugs.c +@@ -1442,9 +1442,13 @@ static __ro_after_init enum spectre_v2_mitigation_cmd spectre_v2_cmd; + static enum spectre_v2_user_cmd __init + spectre_v2_parse_user_cmdline(void) + { ++ enum spectre_v2_user_cmd mode; + char arg[20]; + int ret, i; + ++ mode = IS_ENABLED(CONFIG_MITIGATION_SPECTRE_V2) ? ++ SPECTRE_V2_USER_CMD_AUTO : SPECTRE_V2_USER_CMD_NONE; ++ + switch (spectre_v2_cmd) { + case SPECTRE_V2_CMD_NONE: + return SPECTRE_V2_USER_CMD_NONE; +@@ -1457,7 +1461,7 @@ spectre_v2_parse_user_cmdline(void) + ret = cmdline_find_option(boot_command_line, "spectre_v2_user", + arg, sizeof(arg)); + if (ret < 0) +- return SPECTRE_V2_USER_CMD_AUTO; ++ return mode; + + for (i = 0; i < ARRAY_SIZE(v2_user_options); i++) { + if (match_option(arg, ret, v2_user_options[i].option)) { +@@ -1467,8 +1471,8 @@ spectre_v2_parse_user_cmdline(void) + } + } + +- pr_err("Unknown user space protection option (%s). Switching to AUTO select\n", arg); +- return SPECTRE_V2_USER_CMD_AUTO; ++ pr_err("Unknown user space protection option (%s). Switching to default\n", arg); ++ return mode; + } + + static inline bool spectre_v2_in_ibrs_mode(enum spectre_v2_mitigation mode) +-- +2.39.5 + diff --git a/queue-6.12/x86-build-fix-broken-copy-command-in-genimage.sh-whe.patch b/queue-6.12/x86-build-fix-broken-copy-command-in-genimage.sh-whe.patch new file mode 100644 index 0000000000..3c458aa599 --- /dev/null +++ b/queue-6.12/x86-build-fix-broken-copy-command-in-genimage.sh-whe.patch @@ -0,0 +1,58 @@ +From 6bbf7ec9011b48f5d232a02fcb8acd541ff1ce90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jan 2025 12:05:00 +0000 +Subject: x86/build: Fix broken copy command in genimage.sh when making + isoimage + +From: Nir Lichtman + +[ Upstream commit e451630226bd09dc730eedb4e32cab1cc7155ae8 ] + +Problem: Currently when running the "make isoimage" command there is an +error related to wrong parameters passed to the cp command: + + "cp: missing destination file operand after 'arch/x86/boot/isoimage/'" + +This is caused because FDINITRDS is an empty array. + +Solution: Check if FDINITRDS is empty before executing the "cp" command, +similar to how it is done in the case of hdimage. + +Signed-off-by: Nir Lichtman +Signed-off-by: Ingo Molnar +Cc: "H. Peter Anvin" +Cc: Ard Biesheuvel +Cc: Masahiro Yamada +Cc: Michal Marek +Link: https://lore.kernel.org/r/20250110120500.GA923218@lichtman.org +Signed-off-by: Sasha Levin +--- + arch/x86/boot/genimage.sh | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/boot/genimage.sh b/arch/x86/boot/genimage.sh +index c9299aeb7333e..3882ead513f74 100644 +--- a/arch/x86/boot/genimage.sh ++++ b/arch/x86/boot/genimage.sh +@@ -22,6 +22,7 @@ + # This script requires: + # bash + # syslinux ++# genisoimage + # mtools (for fdimage* and hdimage) + # edk2/OVMF (for hdimage) + # +@@ -251,7 +252,9 @@ geniso() { + cp "$isolinux" "$ldlinux" "$tmp_dir" + cp "$FBZIMAGE" "$tmp_dir"/linux + echo default linux "$KCMDLINE" > "$tmp_dir"/isolinux.cfg +- cp "${FDINITRDS[@]}" "$tmp_dir"/ ++ if [ ${#FDINITRDS[@]} -gt 0 ]; then ++ cp "${FDINITRDS[@]}" "$tmp_dir"/ ++ fi + genisoimage -J -r -appid 'LINUX_BOOT' -input-charset=utf-8 \ + -quiet -o "$FIMAGE" -b isolinux.bin \ + -c boot.cat -no-emul-boot -boot-load-size 4 \ +-- +2.39.5 + diff --git a/queue-6.12/x86-fred-fix-system-hang-during-s4-resume-with-fred-.patch b/queue-6.12/x86-fred-fix-system-hang-during-s4-resume-with-fred-.patch new file mode 100644 index 0000000000..58db963484 --- /dev/null +++ b/queue-6.12/x86-fred-fix-system-hang-during-s4-resume-with-fred-.patch @@ -0,0 +1,76 @@ +From 8f6ba1b65ddb93088b3239769134a597e220b480 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Apr 2025 00:57:27 -0700 +Subject: x86/fred: Fix system hang during S4 resume with FRED enabled + +From: Xin Li (Intel) + +[ Upstream commit e5f1e8af9c9e151ecd665f6d2e36fb25fec3b110 ] + +Upon a wakeup from S4, the restore kernel starts and initializes the +FRED MSRs as needed from its perspective. It then loads a hibernation +image, including the image kernel, and attempts to load image pages +directly into their original page frames used before hibernation unless +those frames are currently in use. Once all pages are moved to their +original locations, it jumps to a "trampoline" page in the image kernel. + +At this point, the image kernel takes control, but the FRED MSRs still +contain values set by the restore kernel, which may differ from those +set by the image kernel before hibernation. Therefore, the image kernel +must ensure the FRED MSRs have the same values as before hibernation. +Since these values depend only on the location of the kernel text and +data, they can be recomputed from scratch. + +Reported-by: Xi Pardee +Reported-by: Todd Brandt +Tested-by: Todd Brandt +Suggested-by: H. Peter Anvin (Intel) +Signed-off-by: Xin Li (Intel) +Signed-off-by: Ingo Molnar +Reviewed-by: Rafael J. Wysocki +Reviewed-by: H. Peter Anvin (Intel) +Cc: Andy Lutomirski +Cc: Brian Gerst +Cc: Juergen Gross +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/20250401075728.3626147-1-xin@zytor.com +Signed-off-by: Sasha Levin +--- + arch/x86/power/cpu.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c +index 63230ff8cf4f0..08e76a5ca1553 100644 +--- a/arch/x86/power/cpu.c ++++ b/arch/x86/power/cpu.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #ifdef CONFIG_X86_32 + __visible unsigned long saved_context_ebx; +@@ -231,6 +232,19 @@ static void notrace __restore_processor_state(struct saved_context *ctxt) + */ + #ifdef CONFIG_X86_64 + wrmsrl(MSR_GS_BASE, ctxt->kernelmode_gs_base); ++ ++ /* ++ * Reinitialize FRED to ensure the FRED MSRs contain the same values ++ * as before hibernation. ++ * ++ * Note, the setup of FRED RSPs requires access to percpu data ++ * structures. Therefore, FRED reinitialization can only occur after ++ * the percpu access pointer (i.e., MSR_GS_BASE) is restored. ++ */ ++ if (ctxt->cr4 & X86_CR4_FRED) { ++ cpu_init_fred_exceptions(); ++ cpu_init_fred_rsps(); ++ } + #else + loadsegment(fs, __KERNEL_PERCPU); + #endif +-- +2.39.5 + diff --git a/queue-6.12/x86-headers-replace-__assembly__-with-__assembler__-.patch b/queue-6.12/x86-headers-replace-__assembly__-with-__assembler__-.patch new file mode 100644 index 0000000000..b9c14c25c1 --- /dev/null +++ b/queue-6.12/x86-headers-replace-__assembly__-with-__assembler__-.patch @@ -0,0 +1,232 @@ +From 771a8e570e4b02aaba0b4df0ac7e6e2ceec01630 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 11:42:56 +0100 +Subject: x86/headers: Replace __ASSEMBLY__ with __ASSEMBLER__ in UAPI headers + +From: Thomas Huth + +[ Upstream commit 8a141be3233af7d4f7014ebc44d5452d46b2b1be ] + +__ASSEMBLY__ is only defined by the Makefile of the kernel, so +this is not really useful for UAPI headers (unless the userspace +Makefile defines it, too). Let's switch to __ASSEMBLER__ which +gets set automatically by the compiler when compiling assembly +code. + +Signed-off-by: Thomas Huth +Signed-off-by: Ingo Molnar +Cc: "H. Peter Anvin" +Cc: Linus Torvalds +Cc: Kees Cook +Cc: Brian Gerst +Link: https://lore.kernel.org/r/20250310104256.123527-1-thuth@redhat.com +Signed-off-by: Sasha Levin +--- + arch/x86/include/uapi/asm/bootparam.h | 4 ++-- + arch/x86/include/uapi/asm/e820.h | 4 ++-- + arch/x86/include/uapi/asm/ldt.h | 4 ++-- + arch/x86/include/uapi/asm/msr.h | 4 ++-- + arch/x86/include/uapi/asm/ptrace-abi.h | 6 +++--- + arch/x86/include/uapi/asm/ptrace.h | 4 ++-- + arch/x86/include/uapi/asm/setup_data.h | 4 ++-- + arch/x86/include/uapi/asm/signal.h | 8 ++++---- + 8 files changed, 19 insertions(+), 19 deletions(-) + +diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h +index 9b82eebd7add5..dafbf581c515d 100644 +--- a/arch/x86/include/uapi/asm/bootparam.h ++++ b/arch/x86/include/uapi/asm/bootparam.h +@@ -26,7 +26,7 @@ + #define XLF_5LEVEL_ENABLED (1<<6) + #define XLF_MEM_ENCRYPTION (1<<7) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + #include +@@ -210,6 +210,6 @@ enum x86_hardware_subarch { + X86_NR_SUBARCHS, + }; + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _ASM_X86_BOOTPARAM_H */ +diff --git a/arch/x86/include/uapi/asm/e820.h b/arch/x86/include/uapi/asm/e820.h +index 2f491efe3a126..55bc668671560 100644 +--- a/arch/x86/include/uapi/asm/e820.h ++++ b/arch/x86/include/uapi/asm/e820.h +@@ -54,7 +54,7 @@ + */ + #define E820_RESERVED_KERN 128 + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + struct e820entry { + __u64 addr; /* start of memory segment */ +@@ -76,7 +76,7 @@ struct e820map { + #define BIOS_ROM_BASE 0xffe00000 + #define BIOS_ROM_END 0xffffffff + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + + #endif /* _UAPI_ASM_X86_E820_H */ +diff --git a/arch/x86/include/uapi/asm/ldt.h b/arch/x86/include/uapi/asm/ldt.h +index d62ac5db093b4..a82c039d8e6a7 100644 +--- a/arch/x86/include/uapi/asm/ldt.h ++++ b/arch/x86/include/uapi/asm/ldt.h +@@ -12,7 +12,7 @@ + /* The size of each LDT entry. */ + #define LDT_ENTRY_SIZE 8 + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + /* + * Note on 64bit base and limit is ignored and you cannot set DS/ES/CS + * not to the default values if you still want to do syscalls. This +@@ -44,5 +44,5 @@ struct user_desc { + #define MODIFY_LDT_CONTENTS_STACK 1 + #define MODIFY_LDT_CONTENTS_CODE 2 + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + #endif /* _ASM_X86_LDT_H */ +diff --git a/arch/x86/include/uapi/asm/msr.h b/arch/x86/include/uapi/asm/msr.h +index e7516b402a00f..4b8917ca28fe7 100644 +--- a/arch/x86/include/uapi/asm/msr.h ++++ b/arch/x86/include/uapi/asm/msr.h +@@ -2,7 +2,7 @@ + #ifndef _UAPI_ASM_X86_MSR_H + #define _UAPI_ASM_X86_MSR_H + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + #include +@@ -10,5 +10,5 @@ + #define X86_IOC_RDMSR_REGS _IOWR('c', 0xA0, __u32[8]) + #define X86_IOC_WRMSR_REGS _IOWR('c', 0xA1, __u32[8]) + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + #endif /* _UAPI_ASM_X86_MSR_H */ +diff --git a/arch/x86/include/uapi/asm/ptrace-abi.h b/arch/x86/include/uapi/asm/ptrace-abi.h +index 16074b9c93bb5..5823584dea132 100644 +--- a/arch/x86/include/uapi/asm/ptrace-abi.h ++++ b/arch/x86/include/uapi/asm/ptrace-abi.h +@@ -25,7 +25,7 @@ + + #else /* __i386__ */ + +-#if defined(__ASSEMBLY__) || defined(__FRAME_OFFSETS) ++#if defined(__ASSEMBLER__) || defined(__FRAME_OFFSETS) + /* + * C ABI says these regs are callee-preserved. They aren't saved on kernel entry + * unless syscall needs a complete, fully filled "struct pt_regs". +@@ -57,7 +57,7 @@ + #define EFLAGS 144 + #define RSP 152 + #define SS 160 +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + /* top of stack page */ + #define FRAME_SIZE 168 +@@ -87,7 +87,7 @@ + + #define PTRACE_SINGLEBLOCK 33 /* resume execution until next branch */ + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + #endif + +diff --git a/arch/x86/include/uapi/asm/ptrace.h b/arch/x86/include/uapi/asm/ptrace.h +index 85165c0edafc8..e0b5b4f6226b1 100644 +--- a/arch/x86/include/uapi/asm/ptrace.h ++++ b/arch/x86/include/uapi/asm/ptrace.h +@@ -7,7 +7,7 @@ + #include + + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #ifdef __i386__ + /* this struct defines the way the registers are stored on the +@@ -81,6 +81,6 @@ struct pt_regs { + + + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #endif /* _UAPI_ASM_X86_PTRACE_H */ +diff --git a/arch/x86/include/uapi/asm/setup_data.h b/arch/x86/include/uapi/asm/setup_data.h +index b111b0c185449..50c45ead4e7c9 100644 +--- a/arch/x86/include/uapi/asm/setup_data.h ++++ b/arch/x86/include/uapi/asm/setup_data.h +@@ -18,7 +18,7 @@ + #define SETUP_INDIRECT (1<<31) + #define SETUP_TYPE_MAX (SETUP_ENUM_MAX | SETUP_INDIRECT) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + +@@ -78,6 +78,6 @@ struct ima_setup_data { + __u64 size; + } __attribute__((packed)); + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _UAPI_ASM_X86_SETUP_DATA_H */ +diff --git a/arch/x86/include/uapi/asm/signal.h b/arch/x86/include/uapi/asm/signal.h +index f777346450ec3..1067efabf18b5 100644 +--- a/arch/x86/include/uapi/asm/signal.h ++++ b/arch/x86/include/uapi/asm/signal.h +@@ -2,7 +2,7 @@ + #ifndef _UAPI_ASM_X86_SIGNAL_H + #define _UAPI_ASM_X86_SIGNAL_H + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + #include + +@@ -16,7 +16,7 @@ struct siginfo; + typedef unsigned long sigset_t; + + #endif /* __KERNEL__ */ +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + + #define SIGHUP 1 +@@ -68,7 +68,7 @@ typedef unsigned long sigset_t; + + #include + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + + # ifndef __KERNEL__ +@@ -106,6 +106,6 @@ typedef struct sigaltstack { + __kernel_size_t ss_size; + } stack_t; + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _UAPI_ASM_X86_SIGNAL_H */ +-- +2.39.5 + diff --git a/queue-6.12/x86-ibt-handle-fineibt-in-handle_cfi_failure.patch b/queue-6.12/x86-ibt-handle-fineibt-in-handle_cfi_failure.patch new file mode 100644 index 0000000000..13b561b443 --- /dev/null +++ b/queue-6.12/x86-ibt-handle-fineibt-in-handle_cfi_failure.patch @@ -0,0 +1,140 @@ +From 8812d91b07c8ff7a1ab61015c54621ac22dcf9d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 12:45:47 +0100 +Subject: x86/ibt: Handle FineIBT in handle_cfi_failure() + +From: Peter Zijlstra + +[ Upstream commit 882b86fd4e0d49bf91148dbadcdbece19ded40e6 ] + +Sami reminded me that FineIBT failure does not hook into the regular +CFI failure case, and as such CFI_PERMISSIVE does not work. + +Reported-by: Sami Tolvanen +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Sami Tolvanen +Link: https://lkml.kernel.org/r/20250214092619.GB21726@noisy.programming.kicks-ass.net +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/cfi.h | 11 +++++++++++ + arch/x86/kernel/alternative.c | 30 ++++++++++++++++++++++++++++++ + arch/x86/kernel/cfi.c | 22 ++++++++++++++++++---- + 3 files changed, 59 insertions(+), 4 deletions(-) + +diff --git a/arch/x86/include/asm/cfi.h b/arch/x86/include/asm/cfi.h +index 31d19c815f992..7dd5ab239c87b 100644 +--- a/arch/x86/include/asm/cfi.h ++++ b/arch/x86/include/asm/cfi.h +@@ -126,6 +126,17 @@ static inline int cfi_get_offset(void) + + extern u32 cfi_get_func_hash(void *func); + ++#ifdef CONFIG_FINEIBT ++extern bool decode_fineibt_insn(struct pt_regs *regs, unsigned long *target, u32 *type); ++#else ++static inline bool ++decode_fineibt_insn(struct pt_regs *regs, unsigned long *target, u32 *type) ++{ ++ return false; ++} ++ ++#endif ++ + #else + static inline enum bug_trap_type handle_cfi_failure(struct pt_regs *regs) + { +diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c +index 66e77bd7d5116..6ab96bc764cfa 100644 +--- a/arch/x86/kernel/alternative.c ++++ b/arch/x86/kernel/alternative.c +@@ -1254,6 +1254,7 @@ asm( ".pushsection .rodata \n" + " endbr64 \n" + " subl $0x12345678, %r10d \n" + " je fineibt_preamble_end \n" ++ "fineibt_preamble_ud2: \n" + " ud2 \n" + " nop \n" + "fineibt_preamble_end: \n" +@@ -1261,9 +1262,11 @@ asm( ".pushsection .rodata \n" + ); + + extern u8 fineibt_preamble_start[]; ++extern u8 fineibt_preamble_ud2[]; + extern u8 fineibt_preamble_end[]; + + #define fineibt_preamble_size (fineibt_preamble_end - fineibt_preamble_start) ++#define fineibt_preamble_ud2 (fineibt_preamble_ud2 - fineibt_preamble_start) + #define fineibt_preamble_hash 7 + + asm( ".pushsection .rodata \n" +@@ -1568,6 +1571,33 @@ static void poison_cfi(void *addr) + } + } + ++/* ++ * regs->ip points to a UD2 instruction, return true and fill out target and ++ * type when this UD2 is from a FineIBT preamble. ++ * ++ * We check the preamble by checking for the ENDBR instruction relative to the ++ * UD2 instruction. ++ */ ++bool decode_fineibt_insn(struct pt_regs *regs, unsigned long *target, u32 *type) ++{ ++ unsigned long addr = regs->ip - fineibt_preamble_ud2; ++ u32 endbr, hash; ++ ++ __get_kernel_nofault(&endbr, addr, u32, Efault); ++ if (endbr != gen_endbr()) ++ return false; ++ ++ *target = addr + fineibt_preamble_size; ++ ++ __get_kernel_nofault(&hash, addr + fineibt_preamble_hash, u32, Efault); ++ *type = (u32)regs->r10 + hash; ++ ++ return true; ++ ++Efault: ++ return false; ++} ++ + #else + + static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, +diff --git a/arch/x86/kernel/cfi.c b/arch/x86/kernel/cfi.c +index e6bf78fac1462..f6905bef0af84 100644 +--- a/arch/x86/kernel/cfi.c ++++ b/arch/x86/kernel/cfi.c +@@ -70,11 +70,25 @@ enum bug_trap_type handle_cfi_failure(struct pt_regs *regs) + unsigned long target; + u32 type; + +- if (!is_cfi_trap(regs->ip)) +- return BUG_TRAP_TYPE_NONE; ++ switch (cfi_mode) { ++ case CFI_KCFI: ++ if (!is_cfi_trap(regs->ip)) ++ return BUG_TRAP_TYPE_NONE; ++ ++ if (!decode_cfi_insn(regs, &target, &type)) ++ return report_cfi_failure_noaddr(regs, regs->ip); ++ ++ break; + +- if (!decode_cfi_insn(regs, &target, &type)) +- return report_cfi_failure_noaddr(regs, regs->ip); ++ case CFI_FINEIBT: ++ if (!decode_fineibt_insn(regs, &target, &type)) ++ return BUG_TRAP_TYPE_NONE; ++ ++ break; ++ ++ default: ++ return BUG_TRAP_TYPE_NONE; ++ } + + return report_cfi_failure(regs, regs->ip, &target, type); + } +-- +2.39.5 + diff --git a/queue-6.12/x86-kaslr-reduce-kaslr-entropy-on-most-x86-systems.patch b/queue-6.12/x86-kaslr-reduce-kaslr-entropy-on-most-x86-systems.patch new file mode 100644 index 0000000000..ddbeb2fe34 --- /dev/null +++ b/queue-6.12/x86-kaslr-reduce-kaslr-entropy-on-most-x86-systems.patch @@ -0,0 +1,88 @@ +From 1cc42ab326bc21dd8eb3cf9852cda10c55363242 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 10:42:34 +1100 +Subject: x86/kaslr: Reduce KASLR entropy on most x86 systems + +From: Balbir Singh + +[ Upstream commit 7ffb791423c7c518269a9aad35039ef824a40adb ] + +When CONFIG_PCI_P2PDMA=y (which is basically enabled on all +large x86 distros), it maps the PFN's via a ZONE_DEVICE +mapping using devm_memremap_pages(). The mapped virtual +address range corresponds to the pci_resource_start() +of the BAR address and size corresponding to the BAR length. + +When KASLR is enabled, the direct map range of the kernel is +reduced to the size of physical memory plus additional padding. +If the BAR address is beyond this limit, PCI peer to peer DMA +mappings fail. + +Fix this by not shrinking the size of the direct map when +CONFIG_PCI_P2PDMA=y. + +This reduces the total available entropy, but it's better than +the current work around of having to disable KASLR completely. + +[ mingo: Clarified the changelog to point out the broad impact ... ] + +Signed-off-by: Balbir Singh +Signed-off-by: Ingo Molnar +Reviewed-by: Kees Cook +Acked-by: Bjorn Helgaas # drivers/pci/Kconfig +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Andy Lutomirski +Link: https://lore.kernel.org/lkml/20250206023201.1481957-1-balbirs@nvidia.com/ +Link: https://lore.kernel.org/r/20250206234234.1912585-1-balbirs@nvidia.com +-- + arch/x86/mm/kaslr.c | 10 ++++++++-- + drivers/pci/Kconfig | 6 ++++++ + 2 files changed, 14 insertions(+), 2 deletions(-) +Signed-off-by: Sasha Levin +--- + arch/x86/mm/kaslr.c | 10 ++++++++-- + drivers/pci/Kconfig | 6 ++++++ + 2 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/mm/kaslr.c b/arch/x86/mm/kaslr.c +index 230f1dee4f095..e0b0ec0f82457 100644 +--- a/arch/x86/mm/kaslr.c ++++ b/arch/x86/mm/kaslr.c +@@ -109,8 +109,14 @@ void __init kernel_randomize_memory(void) + memory_tb = DIV_ROUND_UP(max_pfn << PAGE_SHIFT, 1UL << TB_SHIFT) + + CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING; + +- /* Adapt physical memory region size based on available memory */ +- if (memory_tb < kaslr_regions[0].size_tb) ++ /* ++ * Adapt physical memory region size based on available memory, ++ * except when CONFIG_PCI_P2PDMA is enabled. P2PDMA exposes the ++ * device BAR space assuming the direct map space is large enough ++ * for creating a ZONE_DEVICE mapping in the direct map corresponding ++ * to the physical BAR address. ++ */ ++ if (!IS_ENABLED(CONFIG_PCI_P2PDMA) && (memory_tb < kaslr_regions[0].size_tb)) + kaslr_regions[0].size_tb = memory_tb; + + /* +diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig +index 0d94e4a967d81..7cef00d9d7ab6 100644 +--- a/drivers/pci/Kconfig ++++ b/drivers/pci/Kconfig +@@ -194,6 +194,12 @@ config PCI_P2PDMA + P2P DMA transactions must be between devices behind the same root + port. + ++ Enabling this option will reduce the entropy of x86 KASLR memory ++ regions. For example - on a 46 bit system, the entropy goes down ++ from 16 bits to 15 bits. The actual reduction in entropy depends ++ on the physical address bits, on processor features, kernel config ++ (5 level page table) and physical memory present on the system. ++ + If unsure, say N. + + config PCI_LABEL +-- +2.39.5 + diff --git a/queue-6.12/x86-kconfig-make-cfi_auto_default-depend-on-rust-or-.patch b/queue-6.12/x86-kconfig-make-cfi_auto_default-depend-on-rust-or-.patch new file mode 100644 index 0000000000..062e8ecefe --- /dev/null +++ b/queue-6.12/x86-kconfig-make-cfi_auto_default-depend-on-rust-or-.patch @@ -0,0 +1,95 @@ +From 811a1f29f30a4525ac8021ee7c6bf8f991c08c45 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Apr 2025 11:54:20 +0000 +Subject: x86/Kconfig: make CFI_AUTO_DEFAULT depend on !RUST or Rust >= 1.88 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Paweł Anikiel + +[ Upstream commit 5595c31c370957aabe739ac3996aedba8267603f ] + +Calling core::fmt::write() from rust code while FineIBT is enabled +results in a kernel panic: + +[ 4614.199779] kernel BUG at arch/x86/kernel/cet.c:132! +[ 4614.205343] Oops: invalid opcode: 0000 [#1] PREEMPT SMP NOPTI +[ 4614.211781] CPU: 2 UID: 0 PID: 6057 Comm: dmabuf_dump Tainted: G U O 6.12.17-android16-0-g6ab38c534a43 #1 9da040f27673ec3945e23b998a0f8bd64c846599 +[ 4614.227832] Tainted: [U]=USER, [O]=OOT_MODULE +[ 4614.241247] RIP: 0010:do_kernel_cp_fault+0xea/0xf0 +... +[ 4614.398144] RIP: 0010:_RNvXs5_NtNtNtCs3o2tGsuHyou_4core3fmt3num3impyNtB9_7Display3fmt+0x0/0x20 +[ 4614.407792] Code: 48 f7 df 48 0f 48 f9 48 89 f2 89 c6 5d e9 18 fd ff ff 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 41 81 ea 14 61 af 2c 74 03 0f 0b 90 <66> 0f 1f 00 55 48 89 e5 48 89 f2 48 8b 3f be 01 00 00 00 5d e9 e7 +[ 4614.428775] RSP: 0018:ffffb95acfa4ba68 EFLAGS: 00010246 +[ 4614.434609] RAX: 0000000000000000 RBX: 0000000000000010 RCX: 0000000000000000 +[ 4614.442587] RDX: 0000000000000007 RSI: ffffb95acfa4ba70 RDI: ffffb95acfa4bc88 +[ 4614.450557] RBP: ffffb95acfa4bae0 R08: ffff0a00ffffff05 R09: 0000000000000070 +[ 4614.458527] R10: 0000000000000000 R11: ffffffffab67eaf0 R12: ffffb95acfa4bcc8 +[ 4614.466493] R13: ffffffffac5d50f0 R14: 0000000000000000 R15: 0000000000000000 +[ 4614.474473] ? __cfi__RNvXs5_NtNtNtCs3o2tGsuHyou_4core3fmt3num3impyNtB9_7Display3fmt+0x10/0x10 +[ 4614.484118] ? _RNvNtCs3o2tGsuHyou_4core3fmt5write+0x1d2/0x250 + +This happens because core::fmt::write() calls +core::fmt::rt::Argument::fmt(), which currently has CFI disabled: + +library/core/src/fmt/rt.rs: +171 // FIXME: Transmuting formatter in new and indirectly branching to/calling +172 // it here is an explicit CFI violation. +173 #[allow(inline_no_sanitize)] +174 #[no_sanitize(cfi, kcfi)] +175 #[inline] +176 pub(super) unsafe fn fmt(&self, f: &mut Formatter<'_>) -> Result { + +This causes a Control Protection exception, because FineIBT has sealed +off the original function's endbr64. + +This makes rust currently incompatible with FineIBT. Add a Kconfig +dependency that prevents FineIBT from getting turned on by default +if rust is enabled. + +[ Rust 1.88.0 (scheduled for 2025-06-26) should have this fixed [1], + and thus we relaxed the condition with Rust >= 1.88. + + When `objtool` lands checking for this with e.g. [2], the plan is + to ideally run that in upstream Rust's CI to prevent regressions + early [3], since we do not control `core`'s source code. + + Alice tested the Rust PR backported to an older compiler. + + Peter would like that Rust provides a stable `core` which can be + pulled into the kernel: "Relying on that much out of tree code is + 'unfortunate'". + + - Miguel ] + +Signed-off-by: Paweł Anikiel +Reviewed-by: Alice Ryhl +Acked-by: Peter Zijlstra +Link: https://github.com/rust-lang/rust/pull/139632 [1] +Link: https://lore.kernel.org/rust-for-linux/20250410154556.GB9003@noisy.programming.kicks-ass.net/ [2] +Link: https://github.com/rust-lang/rust/pull/139632#issuecomment-2801950873 [3] +Link: https://lore.kernel.org/r/20250410115420.366349-1-panikiel@google.com +Link: https://lore.kernel.org/r/att0-CANiq72kjDM0cKALVy4POEzhfdT4nO7tqz0Pm7xM+3=_0+L1t=A@mail.gmail.com +[ Reduced splat. - Miguel ] +Signed-off-by: Miguel Ojeda +Signed-off-by: Sasha Levin +--- + arch/x86/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index 7b3622ba4c3c8..15425c9bdc2bc 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -2420,6 +2420,7 @@ config STRICT_SIGALTSTACK_SIZE + config CFI_AUTO_DEFAULT + bool "Attempt to use FineIBT by default at boot time" + depends on FINEIBT ++ depends on !RUST || RUSTC_VERSION >= 108800 + default y + help + Attempt to use FineIBT by default at boot time. If enabled, +-- +2.39.5 + diff --git a/queue-6.12/x86-locking-use-alt_output_sp-for-percpu_-try_-cmpxc.patch b/queue-6.12/x86-locking-use-alt_output_sp-for-percpu_-try_-cmpxc.patch new file mode 100644 index 0000000000..8aa183f87a --- /dev/null +++ b/queue-6.12/x86-locking-use-alt_output_sp-for-percpu_-try_-cmpxc.patch @@ -0,0 +1,93 @@ +From b4f78e42808b7c786170fbd01e1839d4a2910e04 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 16:07:46 +0100 +Subject: x86/locking: Use ALT_OUTPUT_SP() for + percpu_{,try_}cmpxchg{64,128}_op() + +From: Uros Bizjak + +[ Upstream commit 4087e16b033140cf2ce509ec23503bddec818a16 ] + +percpu_{,try_}cmpxchg{64,128}() macros use CALL instruction inside +asm statement in one of their alternatives. Use ALT_OUTPUT_SP() +macro to add required dependence on %esp register. + +ALT_OUTPUT_SP() implements the above dependence by adding +ASM_CALL_CONSTRAINT to its arguments. This constraint should be used +for any inline asm which has a CALL instruction, otherwise the +compiler may schedule the asm before the frame pointer gets set up +by the containing function, causing objtool to print a "call without +frame pointer save/setup" warning. + +Signed-off-by: Uros Bizjak +Signed-off-by: Ingo Molnar +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/20250214150929.5780-1-ubizjak@gmail.com +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/percpu.h | 28 ++++++++++++++-------------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h +index c55a79d5feaeb..2d9c250b3c8d8 100644 +--- a/arch/x86/include/asm/percpu.h ++++ b/arch/x86/include/asm/percpu.h +@@ -349,9 +349,9 @@ do { \ + \ + asm qual (ALTERNATIVE("call this_cpu_cmpxchg8b_emu", \ + "cmpxchg8b " __percpu_arg([var]), X86_FEATURE_CX8) \ +- : [var] "+m" (__my_cpu_var(_var)), \ +- "+a" (old__.low), \ +- "+d" (old__.high) \ ++ : ALT_OUTPUT_SP([var] "+m" (__my_cpu_var(_var)), \ ++ "+a" (old__.low), \ ++ "+d" (old__.high)) \ + : "b" (new__.low), \ + "c" (new__.high), \ + "S" (&(_var)) \ +@@ -380,10 +380,10 @@ do { \ + asm qual (ALTERNATIVE("call this_cpu_cmpxchg8b_emu", \ + "cmpxchg8b " __percpu_arg([var]), X86_FEATURE_CX8) \ + CC_SET(z) \ +- : CC_OUT(z) (success), \ +- [var] "+m" (__my_cpu_var(_var)), \ +- "+a" (old__.low), \ +- "+d" (old__.high) \ ++ : ALT_OUTPUT_SP(CC_OUT(z) (success), \ ++ [var] "+m" (__my_cpu_var(_var)), \ ++ "+a" (old__.low), \ ++ "+d" (old__.high)) \ + : "b" (new__.low), \ + "c" (new__.high), \ + "S" (&(_var)) \ +@@ -420,9 +420,9 @@ do { \ + \ + asm qual (ALTERNATIVE("call this_cpu_cmpxchg16b_emu", \ + "cmpxchg16b " __percpu_arg([var]), X86_FEATURE_CX16) \ +- : [var] "+m" (__my_cpu_var(_var)), \ +- "+a" (old__.low), \ +- "+d" (old__.high) \ ++ : ALT_OUTPUT_SP([var] "+m" (__my_cpu_var(_var)), \ ++ "+a" (old__.low), \ ++ "+d" (old__.high)) \ + : "b" (new__.low), \ + "c" (new__.high), \ + "S" (&(_var)) \ +@@ -451,10 +451,10 @@ do { \ + asm qual (ALTERNATIVE("call this_cpu_cmpxchg16b_emu", \ + "cmpxchg16b " __percpu_arg([var]), X86_FEATURE_CX16) \ + CC_SET(z) \ +- : CC_OUT(z) (success), \ +- [var] "+m" (__my_cpu_var(_var)), \ +- "+a" (old__.low), \ +- "+d" (old__.high) \ ++ : ALT_OUTPUT_SP(CC_OUT(z) (success), \ ++ [var] "+m" (__my_cpu_var(_var)), \ ++ "+a" (old__.low), \ ++ "+d" (old__.high)) \ + : "b" (new__.low), \ + "c" (new__.high), \ + "S" (&(_var)) \ +-- +2.39.5 + diff --git a/queue-6.12/x86-microcode-update-the-intel-processor-flag-scan-c.patch b/queue-6.12/x86-microcode-update-the-intel-processor-flag-scan-c.patch new file mode 100644 index 0000000000..1f6b7d8854 --- /dev/null +++ b/queue-6.12/x86-microcode-update-the-intel-processor-flag-scan-c.patch @@ -0,0 +1,59 @@ +From 543bab893a1f6fe4ffe3eef38e9046b572918e75 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 18:41:21 +0000 +Subject: x86/microcode: Update the Intel processor flag scan check + +From: Sohil Mehta + +[ Upstream commit 7e6b0a2e4152f4046af95eeb46f8b4f9b2a7398d ] + +The Family model check to read the processor flag MSR is misleading and +potentially incorrect. It doesn't consider Family while comparing the +model number. The original check did have a Family number but it got +lost/moved during refactoring. + +intel_collect_cpu_info() is called through multiple paths such as early +initialization, CPU hotplug as well as IFS image load. Some of these +flows would be error prone due to the ambiguous check. + +Correct the processor flag scan check to use a Family number and update +it to a VFM based one to make it more readable. + +Signed-off-by: Sohil Mehta +Signed-off-by: Ingo Molnar +Acked-by: Dave Hansen +Link: https://lore.kernel.org/r/20250219184133.816753-4-sohil.mehta@intel.com +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/intel-family.h | 1 + + arch/x86/kernel/cpu/microcode/intel.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h +index 62d8b9448dc5c..c6198fbcc1d77 100644 +--- a/arch/x86/include/asm/intel-family.h ++++ b/arch/x86/include/asm/intel-family.h +@@ -46,6 +46,7 @@ + #define INTEL_ANY IFM(X86_FAMILY_ANY, X86_MODEL_ANY) + + #define INTEL_PENTIUM_PRO IFM(6, 0x01) ++#define INTEL_PENTIUM_III_DESCHUTES IFM(6, 0x05) + + #define INTEL_CORE_YONAH IFM(6, 0x0E) + +diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c +index df5650eb3f088..362cc71bbc866 100644 +--- a/arch/x86/kernel/cpu/microcode/intel.c ++++ b/arch/x86/kernel/cpu/microcode/intel.c +@@ -74,7 +74,7 @@ void intel_collect_cpu_info(struct cpu_signature *sig) + sig->pf = 0; + sig->rev = intel_get_microcode_revision(); + +- if (x86_model(sig->sig) >= 5 || x86_family(sig->sig) > 6) { ++ if (IFM(x86_family(sig->sig), x86_model(sig->sig)) >= INTEL_PENTIUM_III_DESCHUTES) { + unsigned int val[2]; + + /* get processor flags from MSR 0x17 */ +-- +2.39.5 + diff --git a/queue-6.12/x86-mm-check-return-value-from-memblock_phys_alloc_r.patch b/queue-6.12/x86-mm-check-return-value-from-memblock_phys_alloc_r.patch new file mode 100644 index 0000000000..4d94d66f2b --- /dev/null +++ b/queue-6.12/x86-mm-check-return-value-from-memblock_phys_alloc_r.patch @@ -0,0 +1,53 @@ +From f1962511b535336d75cab7fdc37659726230bc63 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Nov 2024 20:36:59 +0300 +Subject: x86/mm: Check return value from memblock_phys_alloc_range() + +From: Philip Redkin + +[ Upstream commit 631ca8909fd5c62b9fda9edda93924311a78a9c4 ] + +At least with CONFIG_PHYSICAL_START=0x100000, if there is < 4 MiB of +contiguous free memory available at this point, the kernel will crash +and burn because memblock_phys_alloc_range() returns 0 on failure, +which leads memblock_phys_free() to throw the first 4 MiB of physical +memory to the wolves. + +At a minimum it should fail gracefully with a meaningful diagnostic, +but in fact everything seems to work fine without the weird reserve +allocation. + +Signed-off-by: Philip Redkin +Signed-off-by: Ingo Molnar +Cc: Dave Hansen +Cc: Rik van Riel +Cc: "H. Peter Anvin" +Link: https://lore.kernel.org/r/94b3e98f-96a7-3560-1f76-349eb95ccf7f@rarity.fan +Signed-off-by: Sasha Levin +--- + arch/x86/mm/init.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c +index 101725c149c42..9cbc1e6057d3c 100644 +--- a/arch/x86/mm/init.c ++++ b/arch/x86/mm/init.c +@@ -645,8 +645,13 @@ static void __init memory_map_top_down(unsigned long map_start, + */ + addr = memblock_phys_alloc_range(PMD_SIZE, PMD_SIZE, map_start, + map_end); +- memblock_phys_free(addr, PMD_SIZE); +- real_end = addr + PMD_SIZE; ++ if (!addr) { ++ pr_warn("Failed to release memory for alloc_low_pages()"); ++ real_end = max(map_start, ALIGN_DOWN(map_end, PMD_SIZE)); ++ } else { ++ memblock_phys_free(addr, PMD_SIZE); ++ real_end = addr + PMD_SIZE; ++ } + + /* step_size need to be small so pgt_buf from BRK could cover it */ + step_size = PMD_SIZE; +-- +2.39.5 + diff --git a/queue-6.12/x86-nmi-add-an-emergency-handler-in-nmi_desc-use-it-.patch b/queue-6.12/x86-nmi-add-an-emergency-handler-in-nmi_desc-use-it-.patch new file mode 100644 index 0000000000..3843cff12f --- /dev/null +++ b/queue-6.12/x86-nmi-add-an-emergency-handler-in-nmi_desc-use-it-.patch @@ -0,0 +1,173 @@ +From c14d1a0208b7516b242bd94f0e7ae6a36f071b13 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 14:18:44 -0500 +Subject: x86/nmi: Add an emergency handler in nmi_desc & use it in + nmi_shootdown_cpus() + +From: Waiman Long + +[ Upstream commit fe37c699ae3eed6e02ee55fbf5cb9ceb7fcfd76c ] + +Depending on the type of panics, it was found that the +__register_nmi_handler() function can be called in NMI context from +nmi_shootdown_cpus() leading to a lockdep splat: + + WARNING: inconsistent lock state + inconsistent {INITIAL USE} -> {IN-NMI} usage. + + lock(&nmi_desc[0].lock); + + lock(&nmi_desc[0].lock); + + Call Trace: + _raw_spin_lock_irqsave + __register_nmi_handler + nmi_shootdown_cpus + kdump_nmi_shootdown_cpus + native_machine_crash_shutdown + __crash_kexec + +In this particular case, the following panic message was printed before: + + Kernel panic - not syncing: Fatal hardware error! + +This message seemed to be given out from __ghes_panic() running in +NMI context. + +The __register_nmi_handler() function which takes the nmi_desc lock +with irq disabled shouldn't be called from NMI context as this can +lead to deadlock. + +The nmi_shootdown_cpus() function can only be invoked once. After the +first invocation, all other CPUs should be stuck in the newly added +crash_nmi_callback() and cannot respond to a second NMI. + +Fix it by adding a new emergency NMI handler to the nmi_desc +structure and provide a new set_emergency_nmi_handler() helper to set +crash_nmi_callback() in any context. The new emergency handler will +preempt other handlers in the linked list. That will eliminate the need +to take any lock and serve the panic in NMI use case. + +Signed-off-by: Waiman Long +Signed-off-by: Ingo Molnar +Acked-by: Rik van Riel +Cc: Thomas Gleixner +Link: https://lore.kernel.org/r/20250206191844.131700-1-longman@redhat.com +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/nmi.h | 2 ++ + arch/x86/kernel/nmi.c | 42 ++++++++++++++++++++++++++++++++++++++ + arch/x86/kernel/reboot.c | 10 +++------ + 3 files changed, 47 insertions(+), 7 deletions(-) + +diff --git a/arch/x86/include/asm/nmi.h b/arch/x86/include/asm/nmi.h +index 41a0ebb699ec6..f677382093f36 100644 +--- a/arch/x86/include/asm/nmi.h ++++ b/arch/x86/include/asm/nmi.h +@@ -56,6 +56,8 @@ int __register_nmi_handler(unsigned int, struct nmiaction *); + + void unregister_nmi_handler(unsigned int, const char *); + ++void set_emergency_nmi_handler(unsigned int type, nmi_handler_t handler); ++ + void stop_nmi(void); + void restart_nmi(void); + void local_touch_nmi(void); +diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c +index ed163c8c8604e..9a95d00f14233 100644 +--- a/arch/x86/kernel/nmi.c ++++ b/arch/x86/kernel/nmi.c +@@ -40,8 +40,12 @@ + #define CREATE_TRACE_POINTS + #include + ++/* ++ * An emergency handler can be set in any context including NMI ++ */ + struct nmi_desc { + raw_spinlock_t lock; ++ nmi_handler_t emerg_handler; + struct list_head head; + }; + +@@ -132,9 +136,22 @@ static void nmi_check_duration(struct nmiaction *action, u64 duration) + static int nmi_handle(unsigned int type, struct pt_regs *regs) + { + struct nmi_desc *desc = nmi_to_desc(type); ++ nmi_handler_t ehandler; + struct nmiaction *a; + int handled=0; + ++ /* ++ * Call the emergency handler, if set ++ * ++ * In the case of crash_nmi_callback() emergency handler, it will ++ * return in the case of the crashing CPU to enable it to complete ++ * other necessary crashing actions ASAP. Other handlers in the ++ * linked list won't need to be run. ++ */ ++ ehandler = desc->emerg_handler; ++ if (ehandler) ++ return ehandler(type, regs); ++ + rcu_read_lock(); + + /* +@@ -224,6 +241,31 @@ void unregister_nmi_handler(unsigned int type, const char *name) + } + EXPORT_SYMBOL_GPL(unregister_nmi_handler); + ++/** ++ * set_emergency_nmi_handler - Set emergency handler ++ * @type: NMI type ++ * @handler: the emergency handler to be stored ++ * ++ * Set an emergency NMI handler which, if set, will preempt all the other ++ * handlers in the linked list. If a NULL handler is passed in, it will clear ++ * it. It is expected that concurrent calls to this function will not happen ++ * or the system is screwed beyond repair. ++ */ ++void set_emergency_nmi_handler(unsigned int type, nmi_handler_t handler) ++{ ++ struct nmi_desc *desc = nmi_to_desc(type); ++ ++ if (WARN_ON_ONCE(desc->emerg_handler == handler)) ++ return; ++ desc->emerg_handler = handler; ++ ++ /* ++ * Ensure the emergency handler is visible to other CPUs before ++ * function return ++ */ ++ smp_wmb(); ++} ++ + static void + pci_serr_error(unsigned char reason, struct pt_regs *regs) + { +diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c +index dc1dd3f3e67fc..9aaac1f9f45b5 100644 +--- a/arch/x86/kernel/reboot.c ++++ b/arch/x86/kernel/reboot.c +@@ -926,15 +926,11 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback) + shootdown_callback = callback; + + atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); +- /* Would it be better to replace the trap vector here? */ +- if (register_nmi_handler(NMI_LOCAL, crash_nmi_callback, +- NMI_FLAG_FIRST, "crash")) +- return; /* Return what? */ ++ + /* +- * Ensure the new callback function is set before sending +- * out the NMI ++ * Set emergency handler to preempt other handlers. + */ +- wmb(); ++ set_emergency_nmi_handler(NMI_LOCAL, crash_nmi_callback); + + apic_send_IPI_allbutself(NMI_VECTOR); + +-- +2.39.5 + diff --git a/queue-6.12/x86-relocs-handle-r_x86_64_rex_gotpcrelx-relocations.patch b/queue-6.12/x86-relocs-handle-r_x86_64_rex_gotpcrelx-relocations.patch new file mode 100644 index 0000000000..63cb567c05 --- /dev/null +++ b/queue-6.12/x86-relocs-handle-r_x86_64_rex_gotpcrelx-relocations.patch @@ -0,0 +1,58 @@ +From e2c328b432149ff61d399af825c934869c86116e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 14:07:37 -0500 +Subject: x86/relocs: Handle R_X86_64_REX_GOTPCRELX relocations + +From: Brian Gerst + +[ Upstream commit cb7927fda002ca49ae62e2782c1692acc7b80c67 ] + +Clang may produce R_X86_64_REX_GOTPCRELX relocations when redefining the +stack protector location. Treat them as another type of PC-relative +relocation. + +Signed-off-by: Brian Gerst +Signed-off-by: Ingo Molnar +Reviewed-by: Ard Biesheuvel +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/20250123190747.745588-6-brgerst@gmail.com +Signed-off-by: Sasha Levin +--- + arch/x86/tools/relocs.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c +index c101bed619400..7f390e3374a76 100644 +--- a/arch/x86/tools/relocs.c ++++ b/arch/x86/tools/relocs.c +@@ -32,6 +32,11 @@ static struct relocs relocs32; + static struct relocs relocs32neg; + static struct relocs relocs64; + # define FMT PRIu64 ++ ++#ifndef R_X86_64_REX_GOTPCRELX ++# define R_X86_64_REX_GOTPCRELX 42 ++#endif ++ + #else + # define FMT PRIu32 + #endif +@@ -227,6 +232,7 @@ static const char *rel_type(unsigned type) + REL_TYPE(R_X86_64_PC16), + REL_TYPE(R_X86_64_8), + REL_TYPE(R_X86_64_PC8), ++ REL_TYPE(R_X86_64_REX_GOTPCRELX), + #else + REL_TYPE(R_386_NONE), + REL_TYPE(R_386_32), +@@ -861,6 +867,7 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, + + case R_X86_64_PC32: + case R_X86_64_PLT32: ++ case R_X86_64_REX_GOTPCRELX: + /* + * PC relative relocations don't need to be adjusted unless + * referencing a percpu symbol. +-- +2.39.5 + diff --git a/queue-6.12/x86-smpboot-fix-init-delay-assignment-for-extended-i.patch b/queue-6.12/x86-smpboot-fix-init-delay-assignment-for-extended-i.patch new file mode 100644 index 0000000000..461882942e --- /dev/null +++ b/queue-6.12/x86-smpboot-fix-init-delay-assignment-for-extended-i.patch @@ -0,0 +1,50 @@ +From de9f5b7bb79edee808c7d356acfcdfc67f2345f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 18:41:28 +0000 +Subject: x86/smpboot: Fix INIT delay assignment for extended Intel Families + +From: Sohil Mehta + +[ Upstream commit 7a2ad752746bfb13e89a83984ecc52a48bae4969 ] + +Some old crusty CPUs need an extra delay that slows down booting. See +the comment above 'init_udelay' for details. Newer CPUs don't need the +delay. + +Right now, for Intel, Family 6 and only Family 6 skips the delay. That +leaves out both the Family 15 (Pentium 4s) and brand new Family 18/19 +models. + +The omission of Family 15 (Pentium 4s) seems like an oversight and 18/19 +do not need the delay. + +Skip the delay on all Intel processors Family 6 and beyond. + +Signed-off-by: Sohil Mehta +Signed-off-by: Ingo Molnar +Link: https://lore.kernel.org/r/20250219184133.816753-11-sohil.mehta@intel.com +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/smpboot.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c +index f1fac08fdef28..2c451de702c87 100644 +--- a/arch/x86/kernel/smpboot.c ++++ b/arch/x86/kernel/smpboot.c +@@ -681,9 +681,9 @@ static void __init smp_quirk_init_udelay(void) + return; + + /* if modern processor, use no delay */ +- if (((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 6)) || +- ((boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) && (boot_cpu_data.x86 >= 0x18)) || +- ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && (boot_cpu_data.x86 >= 0xF))) { ++ if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && boot_cpu_data.x86_vfm >= INTEL_PENTIUM_PRO) || ++ (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON && boot_cpu_data.x86 >= 0x18) || ++ (boot_cpu_data.x86_vendor == X86_VENDOR_AMD && boot_cpu_data.x86 >= 0xF)) { + init_udelay = 0; + return; + } +-- +2.39.5 + diff --git a/queue-6.12/x86-stackprotector-64-only-export-__ref_stack_chk_gu.patch b/queue-6.12/x86-stackprotector-64-only-export-__ref_stack_chk_gu.patch new file mode 100644 index 0000000000..f0f5d63306 --- /dev/null +++ b/queue-6.12/x86-stackprotector-64-only-export-__ref_stack_chk_gu.patch @@ -0,0 +1,45 @@ +From b6982925e93b8b7bd20a3795cfbf87a6e0332ff8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 12:48:49 +0100 +Subject: x86/stackprotector/64: Only export __ref_stack_chk_guard on + CONFIG_SMP +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ingo Molnar + +[ Upstream commit 91d5451d97ce35cbd510277fa3b7abf9caa4e34d ] + +The __ref_stack_chk_guard symbol doesn't exist on UP: + + :4:15: error: ‘__ref_stack_chk_guard’ undeclared here (not in a function) + +Fix the #ifdef around the entry.S export. + +Signed-off-by: Ingo Molnar +Cc: Brian Gerst +Cc: Ard Biesheuvel +Cc: Uros Bizjak +Link: https://lore.kernel.org/r/20250123190747.745588-8-brgerst@gmail.com +Signed-off-by: Sasha Levin +--- + arch/x86/entry/entry.S | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/x86/entry/entry.S b/arch/x86/entry/entry.S +index 58e3124ee2b42..5b96249734ada 100644 +--- a/arch/x86/entry/entry.S ++++ b/arch/x86/entry/entry.S +@@ -63,7 +63,7 @@ THUNK warn_thunk_thunk, __warn_thunk + * entirely in the C code, and use an alias emitted by the linker script + * instead. + */ +-#ifdef CONFIG_STACKPROTECTOR ++#if defined(CONFIG_STACKPROTECTOR) && defined(CONFIG_SMP) + EXPORT_SYMBOL(__ref_stack_chk_guard); + #endif + #endif +-- +2.39.5 + diff --git a/queue-6.12/x86-traps-cleanup-and-robustify-decode_bug.patch b/queue-6.12/x86-traps-cleanup-and-robustify-decode_bug.patch new file mode 100644 index 0000000000..d2218c71c7 --- /dev/null +++ b/queue-6.12/x86-traps-cleanup-and-robustify-decode_bug.patch @@ -0,0 +1,192 @@ +From 91f62dbac4e2e0740df12c32a5153eee89ac4b3c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 13:15:36 +0100 +Subject: x86/traps: Cleanup and robustify decode_bug() + +From: Peter Zijlstra + +[ Upstream commit c20ad96c9a8f0aeaf4e4057730a22de2657ad0c2 ] + +Notably, don't attempt to decode an immediate when MOD == 3. + +Additionally have it return the instruction length, such that WARN +like bugs can more reliably skip to the correct instruction. + +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Sami Tolvanen +Link: https://lore.kernel.org/r/20250207122546.721120726@infradead.org +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/bug.h | 5 ++- + arch/x86/include/asm/ibt.h | 4 +- + arch/x86/kernel/traps.c | 82 ++++++++++++++++++++++++++++---------- + 3 files changed, 65 insertions(+), 26 deletions(-) + +diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h +index 806649c7f23dc..9a0f29be1a9ea 100644 +--- a/arch/x86/include/asm/bug.h ++++ b/arch/x86/include/asm/bug.h +@@ -22,8 +22,9 @@ + #define SECOND_BYTE_OPCODE_UD2 0x0b + + #define BUG_NONE 0xffff +-#define BUG_UD1 0xfffe +-#define BUG_UD2 0xfffd ++#define BUG_UD2 0xfffe ++#define BUG_UD1 0xfffd ++#define BUG_UD1_UBSAN 0xfffc + + #ifdef CONFIG_GENERIC_BUG + +diff --git a/arch/x86/include/asm/ibt.h b/arch/x86/include/asm/ibt.h +index 1e59581d500ca..b778ae6e67ee8 100644 +--- a/arch/x86/include/asm/ibt.h ++++ b/arch/x86/include/asm/ibt.h +@@ -41,7 +41,7 @@ + _ASM_PTR fname "\n\t" \ + ".popsection\n\t" + +-static inline __attribute_const__ u32 gen_endbr(void) ++static __always_inline __attribute_const__ u32 gen_endbr(void) + { + u32 endbr; + +@@ -56,7 +56,7 @@ static inline __attribute_const__ u32 gen_endbr(void) + return endbr; + } + +-static inline __attribute_const__ u32 gen_endbr_poison(void) ++static __always_inline __attribute_const__ u32 gen_endbr_poison(void) + { + /* + * 4 byte NOP that isn't NOP4 (in fact it is OSP NOP3), such that it +diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c +index 5e3e036e6e537..b18fc7539b8d7 100644 +--- a/arch/x86/kernel/traps.c ++++ b/arch/x86/kernel/traps.c +@@ -94,10 +94,17 @@ __always_inline int is_valid_bugaddr(unsigned long addr) + + /* + * Check for UD1 or UD2, accounting for Address Size Override Prefixes. +- * If it's a UD1, get the ModRM byte to pass along to UBSan. ++ * If it's a UD1, further decode to determine its use: ++ * ++ * UBSan{0}: 67 0f b9 00 ud1 (%eax),%eax ++ * UBSan{10}: 67 0f b9 40 10 ud1 0x10(%eax),%eax ++ * static_call: 0f b9 cc ud1 %esp,%ecx ++ * ++ * Notably UBSAN uses EAX, static_call uses ECX. + */ +-__always_inline int decode_bug(unsigned long addr, u32 *imm) ++__always_inline int decode_bug(unsigned long addr, s32 *imm, int *len) + { ++ unsigned long start = addr; + u8 v; + + if (addr < TASK_SIZE_MAX) +@@ -110,24 +117,42 @@ __always_inline int decode_bug(unsigned long addr, u32 *imm) + return BUG_NONE; + + v = *(u8 *)(addr++); +- if (v == SECOND_BYTE_OPCODE_UD2) ++ if (v == SECOND_BYTE_OPCODE_UD2) { ++ *len = addr - start; + return BUG_UD2; ++ } + +- if (!IS_ENABLED(CONFIG_UBSAN_TRAP) || v != SECOND_BYTE_OPCODE_UD1) ++ if (v != SECOND_BYTE_OPCODE_UD1) + return BUG_NONE; + +- /* Retrieve the immediate (type value) for the UBSAN UD1 */ +- v = *(u8 *)(addr++); +- if (X86_MODRM_RM(v) == 4) +- addr++; +- + *imm = 0; +- if (X86_MODRM_MOD(v) == 1) +- *imm = *(u8 *)addr; +- else if (X86_MODRM_MOD(v) == 2) +- *imm = *(u32 *)addr; +- else +- WARN_ONCE(1, "Unexpected MODRM_MOD: %u\n", X86_MODRM_MOD(v)); ++ v = *(u8 *)(addr++); /* ModRM */ ++ ++ if (X86_MODRM_MOD(v) != 3 && X86_MODRM_RM(v) == 4) ++ addr++; /* SIB */ ++ ++ /* Decode immediate, if present */ ++ switch (X86_MODRM_MOD(v)) { ++ case 0: if (X86_MODRM_RM(v) == 5) ++ addr += 4; /* RIP + disp32 */ ++ break; ++ ++ case 1: *imm = *(s8 *)addr; ++ addr += 1; ++ break; ++ ++ case 2: *imm = *(s32 *)addr; ++ addr += 4; ++ break; ++ ++ case 3: break; ++ } ++ ++ /* record instruction length */ ++ *len = addr - start; ++ ++ if (X86_MODRM_REG(v) == 0) /* EAX */ ++ return BUG_UD1_UBSAN; + + return BUG_UD1; + } +@@ -258,10 +283,10 @@ static inline void handle_invalid_op(struct pt_regs *regs) + static noinstr bool handle_bug(struct pt_regs *regs) + { + bool handled = false; +- int ud_type; +- u32 imm; ++ int ud_type, ud_len; ++ s32 ud_imm; + +- ud_type = decode_bug(regs->ip, &imm); ++ ud_type = decode_bug(regs->ip, &ud_imm, &ud_len); + if (ud_type == BUG_NONE) + return handled; + +@@ -281,15 +306,28 @@ static noinstr bool handle_bug(struct pt_regs *regs) + */ + if (regs->flags & X86_EFLAGS_IF) + raw_local_irq_enable(); +- if (ud_type == BUG_UD2) { ++ ++ switch (ud_type) { ++ case BUG_UD2: + if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN || + handle_cfi_failure(regs) == BUG_TRAP_TYPE_WARN) { +- regs->ip += LEN_UD2; ++ regs->ip += ud_len; + handled = true; + } +- } else if (IS_ENABLED(CONFIG_UBSAN_TRAP)) { +- pr_crit("%s at %pS\n", report_ubsan_failure(regs, imm), (void *)regs->ip); ++ break; ++ ++ case BUG_UD1_UBSAN: ++ if (IS_ENABLED(CONFIG_UBSAN_TRAP)) { ++ pr_crit("%s at %pS\n", ++ report_ubsan_failure(regs, ud_imm), ++ (void *)regs->ip); ++ } ++ break; ++ ++ default: ++ break; + } ++ + if (regs->flags & X86_EFLAGS_IF) + raw_local_irq_disable(); + instrumentation_end(); +-- +2.39.5 + diff --git a/queue-6.12/xen-add-support-for-xenserver-6.1-platform-device.patch b/queue-6.12/xen-add-support-for-xenserver-6.1-platform-device.patch new file mode 100644 index 0000000000..ea0546af9a --- /dev/null +++ b/queue-6.12/xen-add-support-for-xenserver-6.1-platform-device.patch @@ -0,0 +1,65 @@ +From c9d3c4c2a685de13e844502936fcb45566e99e0f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 14:50:15 +0000 +Subject: xen: Add support for XenServer 6.1 platform device + +From: Frediano Ziglio + +[ Upstream commit 2356f15caefc0cc63d9cc5122641754f76ef9b25 ] + +On XenServer on Windows machine a platform device with ID 2 instead of +1 is used. + +This device is mainly identical to device 1 but due to some Windows +update behaviour it was decided to use a device with a different ID. + +This causes compatibility issues with Linux which expects, if Xen +is detected, to find a Xen platform device (5853:0001) otherwise code +will crash due to some missing initialization (specifically grant +tables). Specifically from dmesg + + RIP: 0010:gnttab_expand+0x29/0x210 + Code: 90 0f 1f 44 00 00 55 31 d2 48 89 e5 41 57 41 56 41 55 41 89 fd + 41 54 53 48 83 ec 10 48 8b 05 7e 9a 49 02 44 8b 35 a7 9a 49 02 + <8b> 48 04 8d 44 39 ff f7 f1 45 8d 24 06 89 c3 e8 43 fe ff ff + 44 39 + RSP: 0000:ffffba34c01fbc88 EFLAGS: 00010086 + ... + +The device 2 is presented by Xapi adding device specification to +Qemu command line. + +Signed-off-by: Frediano Ziglio +Acked-by: Juergen Gross +Message-ID: <20250227145016.25350-1-frediano.ziglio@cloud.com> +Signed-off-by: Juergen Gross +Signed-off-by: Sasha Levin +--- + drivers/xen/platform-pci.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c +index 544d3f9010b92..1db82da56db62 100644 +--- a/drivers/xen/platform-pci.c ++++ b/drivers/xen/platform-pci.c +@@ -26,6 +26,8 @@ + + #define DRV_NAME "xen-platform-pci" + ++#define PCI_DEVICE_ID_XEN_PLATFORM_XS61 0x0002 ++ + static unsigned long platform_mmio; + static unsigned long platform_mmio_alloc; + static unsigned long platform_mmiolen; +@@ -174,6 +176,8 @@ static int platform_pci_probe(struct pci_dev *pdev, + static const struct pci_device_id platform_pci_tbl[] = { + {PCI_VENDOR_ID_XEN, PCI_DEVICE_ID_XEN_PLATFORM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, ++ {PCI_VENDOR_ID_XEN, PCI_DEVICE_ID_XEN_PLATFORM_XS61, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0,} + }; + +-- +2.39.5 + diff --git a/queue-6.12/xen-pci-do-not-register-devices-with-segments-0x1000.patch b/queue-6.12/xen-pci-do-not-register-devices-with-segments-0x1000.patch new file mode 100644 index 0000000000..acc7383c5d --- /dev/null +++ b/queue-6.12/xen-pci-do-not-register-devices-with-segments-0x1000.patch @@ -0,0 +1,97 @@ +From e3fc61275ab72609e718e8a2a5e405d743550821 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 10:20:55 +0100 +Subject: xen/pci: Do not register devices with segments >= 0x10000 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Roger Pau Monne + +[ Upstream commit 5ccf1b8ae76ddf348e02a0d1564ff9baf8b6c415 ] + +The current hypercall interface for doing PCI device operations always uses +a segment field that has a 16 bit width. However on Linux there are buses +like VMD that hook up devices into the PCI hierarchy at segment >= 0x10000, +after the maximum possible segment enumerated in ACPI. + +Attempting to register or manage those devices with Xen would result in +errors at best, or overlaps with existing devices living on the truncated +equivalent segment values. Note also that the VMD segment numbers are +arbitrarily assigned by the OS, and hence there would need to be some +negotiation between Xen and the OS to agree on how to enumerate VMD +segments and devices behind them. + +Skip notifying Xen about those devices. Given how VMD bridges can +multiplex interrupts on behalf of devices behind them there's no need for +Xen to be aware of such devices for them to be usable by Linux. + +Signed-off-by: Roger Pau Monné +Acked-by: Juergen Gross +Message-ID: <20250219092059.90850-2-roger.pau@citrix.com> +Signed-off-by: Juergen Gross +Signed-off-by: Sasha Levin +--- + drivers/xen/pci.c | 32 ++++++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +diff --git a/drivers/xen/pci.c b/drivers/xen/pci.c +index 416f231809cb6..bfe07adb3e3a6 100644 +--- a/drivers/xen/pci.c ++++ b/drivers/xen/pci.c +@@ -43,6 +43,18 @@ static int xen_add_device(struct device *dev) + pci_mcfg_reserved = true; + } + #endif ++ ++ if (pci_domain_nr(pci_dev->bus) >> 16) { ++ /* ++ * The hypercall interface is limited to 16bit PCI segment ++ * values, do not attempt to register devices with Xen in ++ * segments greater or equal than 0x10000. ++ */ ++ dev_info(dev, ++ "not registering with Xen: invalid PCI segment\n"); ++ return 0; ++ } ++ + if (pci_seg_supported) { + DEFINE_RAW_FLEX(struct physdev_pci_device_add, add, optarr, 1); + +@@ -149,6 +161,16 @@ static int xen_remove_device(struct device *dev) + int r; + struct pci_dev *pci_dev = to_pci_dev(dev); + ++ if (pci_domain_nr(pci_dev->bus) >> 16) { ++ /* ++ * The hypercall interface is limited to 16bit PCI segment ++ * values. ++ */ ++ dev_info(dev, ++ "not unregistering with Xen: invalid PCI segment\n"); ++ return 0; ++ } ++ + if (pci_seg_supported) { + struct physdev_pci_device device = { + .seg = pci_domain_nr(pci_dev->bus), +@@ -182,6 +204,16 @@ int xen_reset_device(const struct pci_dev *dev) + .flags = PCI_DEVICE_RESET_FLR, + }; + ++ if (pci_domain_nr(dev->bus) >> 16) { ++ /* ++ * The hypercall interface is limited to 16bit PCI segment ++ * values. ++ */ ++ dev_info(&dev->dev, ++ "unable to notify Xen of device reset: invalid PCI segment\n"); ++ return 0; ++ } ++ + return HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_reset, &device); + } + EXPORT_SYMBOL_GPL(xen_reset_device); +-- +2.39.5 + diff --git a/queue-6.12/xenbus-allow-pvh-dom0-a-non-local-xenstore.patch b/queue-6.12/xenbus-allow-pvh-dom0-a-non-local-xenstore.patch new file mode 100644 index 0000000000..bea8139e69 --- /dev/null +++ b/queue-6.12/xenbus-allow-pvh-dom0-a-non-local-xenstore.patch @@ -0,0 +1,69 @@ +From 7da0c765a6ef62d454e03efd8c4c306468bbd179 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 May 2025 16:44:56 -0400 +Subject: xenbus: Allow PVH dom0 a non-local xenstore + +From: Jason Andryuk + +[ Upstream commit 90989869baae47ee2aa3bcb6f6eb9fbbe4287958 ] + +Make xenbus_init() allow a non-local xenstore for a PVH dom0 - it is +currently forced to XS_LOCAL. With Hyperlaunch booting dom0 and a +xenstore stubdom, dom0 can be handled as a regular XS_HVM following the +late init path. + +Ideally we'd drop the use of xen_initial_domain() and just check for the +event channel instead. However, ARM has a xen,enhanced no-xenstore +mode, where the event channel and PFN would both be 0. Retain the +xen_initial_domain() check, and use that for an additional check when +the event channel is 0. + +Check the full 64bit HVM_PARAM_STORE_EVTCHN value to catch the off +chance that high bits are set for the 32bit event channel. + +Signed-off-by: Jason Andryuk +Change-Id: I5506da42e4c6b8e85079fefb2f193c8de17c7437 +Reviewed-by: Stefano Stabellini +Signed-off-by: Juergen Gross +Message-ID: <20250506204456.5220-1-jason.andryuk@amd.com> +Signed-off-by: Sasha Levin +--- + drivers/xen/xenbus/xenbus_probe.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c +index 6d32ffb011365..86fe6e7790566 100644 +--- a/drivers/xen/xenbus/xenbus_probe.c ++++ b/drivers/xen/xenbus/xenbus_probe.c +@@ -966,9 +966,15 @@ static int __init xenbus_init(void) + if (xen_pv_domain()) + xen_store_domain_type = XS_PV; + if (xen_hvm_domain()) ++ { + xen_store_domain_type = XS_HVM; +- if (xen_hvm_domain() && xen_initial_domain()) +- xen_store_domain_type = XS_LOCAL; ++ err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v); ++ if (err) ++ goto out_error; ++ xen_store_evtchn = (int)v; ++ if (!v && xen_initial_domain()) ++ xen_store_domain_type = XS_LOCAL; ++ } + if (xen_pv_domain() && !xen_start_info->store_evtchn) + xen_store_domain_type = XS_LOCAL; + if (xen_pv_domain() && xen_start_info->store_evtchn) +@@ -987,10 +993,6 @@ static int __init xenbus_init(void) + xen_store_interface = gfn_to_virt(xen_store_gfn); + break; + case XS_HVM: +- err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v); +- if (err) +- goto out_error; +- xen_store_evtchn = (int)v; + err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v); + if (err) + goto out_error; +-- +2.39.5 + diff --git a/queue-6.12/xfrm-prevent-high-seq-input-in-non-esn-mode.patch b/queue-6.12/xfrm-prevent-high-seq-input-in-non-esn-mode.patch new file mode 100644 index 0000000000..57d61a758d --- /dev/null +++ b/queue-6.12/xfrm-prevent-high-seq-input-in-non-esn-mode.patch @@ -0,0 +1,53 @@ +From 495948964d304b2179bfc1a06c7da9295e2cd900 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 20:27:49 +0200 +Subject: xfrm: prevent high SEQ input in non-ESN mode + +From: Leon Romanovsky + +[ Upstream commit e3aa43a50a6455831e3c32dabc7ece38d9cd9d05 ] + +In non-ESN mode, the SEQ numbers are limited to 32 bits and seq_hi/oseq_hi +are not used. So make sure that user gets proper error message, in case +such assignment occurred. + +Signed-off-by: Leon Romanovsky +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_user.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index 87013623773a2..da2a1c00ca8a6 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -178,6 +178,12 @@ static inline int verify_replay(struct xfrm_usersa_info *p, + "Replay seq and seq_hi should be 0 for output SA"); + return -EINVAL; + } ++ if (rs->oseq_hi && !(p->flags & XFRM_STATE_ESN)) { ++ NL_SET_ERR_MSG( ++ extack, ++ "Replay oseq_hi should be 0 in non-ESN mode for output SA"); ++ return -EINVAL; ++ } + if (rs->bmp_len) { + NL_SET_ERR_MSG(extack, "Replay bmp_len should 0 for output SA"); + return -EINVAL; +@@ -190,6 +196,12 @@ static inline int verify_replay(struct xfrm_usersa_info *p, + "Replay oseq and oseq_hi should be 0 for input SA"); + return -EINVAL; + } ++ if (rs->seq_hi && !(p->flags & XFRM_STATE_ESN)) { ++ NL_SET_ERR_MSG( ++ extack, ++ "Replay seq_hi should be 0 in non-ESN mode for input SA"); ++ return -EINVAL; ++ } + } + + return 0; +-- +2.39.5 +