From: Sasha Levin Date: Mon, 7 Apr 2025 14:02:12 +0000 (-0400) Subject: Fixes for 6.14 X-Git-Tag: v5.4.292~85 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c626f5e59dd6342007de2fef5bdd07ffaf6abdd2;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.14 Signed-off-by: Sasha Levin --- diff --git a/queue-6.14/accel-amdxdna-return-error-when-setting-clock-failed.patch b/queue-6.14/accel-amdxdna-return-error-when-setting-clock-failed.patch new file mode 100644 index 0000000000..a7a7eb3359 --- /dev/null +++ b/queue-6.14/accel-amdxdna-return-error-when-setting-clock-failed.patch @@ -0,0 +1,49 @@ +From 11dae4a8048b692831d9cddaca339e1d3333f655 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jan 2025 11:48:11 -0800 +Subject: accel/amdxdna: Return error when setting clock failed for npu1 + +From: Lizhi Hou + +[ Upstream commit 0c2768bf818904db705ff18674f771c3c4d8bbca ] + +Due to miss returning error when setting clock, the smatch static +checker reports warning: + drivers/accel/amdxdna/aie2_smu.c:68 npu1_set_dpm() + error: uninitialized symbol 'freq'. + +Fixes: f4d7b8a6bc8c ("accel/amdxdna: Enhance power management settings") +Reported-by: Dan Carpenter +Closes: https://lore.kernel.org/dri-devel/202267d0-882e-4593-b58d-be9274592f9b@stanley.mountain/ +Signed-off-by: Lizhi Hou +Reviewed-by: Mario Limonciello +Signed-off-by: Mario Limonciello +Link: https://patchwork.freedesktop.org/patch/msgid/20250109194811.499505-1-lizhi.hou@amd.com +Signed-off-by: Sasha Levin +--- + drivers/accel/amdxdna/aie2_smu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/accel/amdxdna/aie2_smu.c b/drivers/accel/amdxdna/aie2_smu.c +index 73388443c6767..d303701b0ded4 100644 +--- a/drivers/accel/amdxdna/aie2_smu.c ++++ b/drivers/accel/amdxdna/aie2_smu.c +@@ -64,6 +64,7 @@ int npu1_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level) + if (ret) { + XDNA_ERR(ndev->xdna, "Set npu clock to %d failed, ret %d\n", + ndev->priv->dpm_clk_tbl[dpm_level].npuclk, ret); ++ return ret; + } + ndev->npuclk_freq = freq; + +@@ -72,6 +73,7 @@ int npu1_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level) + if (ret) { + XDNA_ERR(ndev->xdna, "Set h clock to %d failed, ret %d\n", + ndev->priv->dpm_clk_tbl[dpm_level].hclk, ret); ++ return ret; + } + ndev->hclk_freq = freq; + ndev->dpm_level = dpm_level; +-- +2.39.5 + diff --git a/queue-6.14/acpi-processor-idle-return-an-error-if-both-p_lvl-2-.patch b/queue-6.14/acpi-processor-idle-return-an-error-if-both-p_lvl-2-.patch new file mode 100644 index 0000000000..05ab6bf9e8 --- /dev/null +++ b/queue-6.14/acpi-processor-idle-return-an-error-if-both-p_lvl-2-.patch @@ -0,0 +1,58 @@ +From f49d9ebdbdd552f36876d955fe71ea058ac545f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Mar 2025 15:30:39 +0100 +Subject: ACPI: processor: idle: Return an error if both P_LVL{2,3} idle states + are invalid + +From: Giovanni Gherdovich + +[ Upstream commit 9e9b893404d43894d69a18dd2fc8fcf1c36abb7e ] + +Prior to commit 496121c02127 ("ACPI: processor: idle: Allow probing on +platforms with one ACPI C-state"), the acpi_idle driver wouldn't load on +systems without a valid C-State at least as deep as C2. + +The behavior was desirable for guests on hypervisors such as VMWare +ESXi, which by default don't have the _CST ACPI method, and set the C2 +and C3 latencies to 101 and 1001 microseconds respectively via the FADT, +to signify they're unsupported. + +Since the above change though, these virtualized deployments end up +loading acpi_idle, and thus entering the default C1 C-State set by +acpi_processor_get_power_info_default(); this is undesirable for a +system that's communicating to the OS it doesn't want C-States (missing +_CST, and invalid C2/C3 in FADT). + +Make acpi_processor_get_power_info_fadt() return -ENODEV in that case, +so that acpi_processor_get_cstate_info() exits early and doesn't set +pr->flags.power = 1. + +Fixes: 496121c02127 ("ACPI: processor: idle: Allow probing on platforms with one ACPI C-state") +Signed-off-by: Giovanni Gherdovich +Reviewed-by: Zhang Rui +Link: https://patch.msgid.link/20250328143040.9348-1-ggherdovich@suse.cz +[ rjw: Changelog edits ] +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/processor_idle.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c +index 698897b29de24..2df1296ff44d5 100644 +--- a/drivers/acpi/processor_idle.c ++++ b/drivers/acpi/processor_idle.c +@@ -268,6 +268,10 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) + ACPI_CX_DESC_LEN, "ACPI P_LVL3 IOPORT 0x%x", + pr->power.states[ACPI_STATE_C3].address); + ++ if (!pr->power.states[ACPI_STATE_C2].address && ++ !pr->power.states[ACPI_STATE_C3].address) ++ return -ENODEV; ++ + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/alsa-hda-realtek-always-honor-no_shutup_pins.patch b/queue-6.14/alsa-hda-realtek-always-honor-no_shutup_pins.patch new file mode 100644 index 0000000000..4216d5d3a3 --- /dev/null +++ b/queue-6.14/alsa-hda-realtek-always-honor-no_shutup_pins.patch @@ -0,0 +1,55 @@ +From dd05e91aeb29d9d7a2d0bc8152c475cdd01c71ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Mar 2025 15:30:19 +0100 +Subject: ALSA: hda/realtek: Always honor no_shutup_pins + +From: Takashi Iwai + +[ Upstream commit 5a0c72c1da3cbc0cd4940a95d1be2830104c6edf ] + +The workaround for Dell machines to skip the pin-shutup for mic pins +introduced alc_headset_mic_no_shutup() that is replaced from the +generic snd_hda_shutup_pins() for certain codecs. The problem is that +the call is done unconditionally even if spec->no_shutup_pins is set. +This seems causing problems on other platforms like Lenovo. + +This patch corrects the behavior and the driver honors always +spec->no_shutup_pins flag and skips alc_headset_mic_no_shutup() if +it's set. + +Fixes: dad3197da7a3 ("ALSA: hda/realtek - Fixup headphone noise via runtime suspend") +Reported-and-tested-by: Oleg Gorobets +Link: https://patch.msgid.link/20250315143020.27184-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 78aab243c8b65..abe269fb8ce00 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -586,6 +586,9 @@ static void alc_shutup_pins(struct hda_codec *codec) + { + struct alc_spec *spec = codec->spec; + ++ if (spec->no_shutup_pins) ++ return; ++ + switch (codec->core.vendor_id) { + case 0x10ec0236: + case 0x10ec0256: +@@ -601,8 +604,7 @@ static void alc_shutup_pins(struct hda_codec *codec) + alc_headset_mic_no_shutup(codec); + break; + default: +- if (!spec->no_shutup_pins) +- snd_hda_shutup_pins(codec); ++ snd_hda_shutup_pins(codec); + break; + } + } +-- +2.39.5 + diff --git a/queue-6.14/alsa-hda-realtek-fix-built-in-mic-assignment-on-asus.patch b/queue-6.14/alsa-hda-realtek-fix-built-in-mic-assignment-on-asus.patch new file mode 100644 index 0000000000..87fe4bc749 --- /dev/null +++ b/queue-6.14/alsa-hda-realtek-fix-built-in-mic-assignment-on-asus.patch @@ -0,0 +1,44 @@ +From a0af232affebf5ff4b739263de676b591453a0b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 16:32:32 +0100 +Subject: ALSA: hda/realtek: Fix built-in mic assignment on ASUS VivoBook + X515UA + +From: Takashi Iwai + +[ Upstream commit 829ee558f3527fd602c6e2e9f270959d1de09fe0 ] + +ASUS VivoBook X515UA with PCI SSID 1043:106f had a default quirk +pickup via pin table that applies ALC256_FIXUP_ASUS_MIC, but this adds +a bogus built-in mic pin 0x13 enabled. This was no big problem +because the pin 0x13 was assigned as the secondary mic, but the recent +fix made the entries sorted, hence this bogus pin appeared now as the +primary input and it broke. + +For fixing the bug, put the right quirk entry for this device pointing +to ALC256_FIXUP_ASUS_MIC_NO_PRESENCE. + +Fixes: 3b4309546b48 ("ALSA: hda: Fix headset detection failure due to unstable sort") +Link: https://bugzilla.kernel.org/show_bug.cgi?id=219897 +Link: https://patch.msgid.link/20250324153233.21195-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index abe269fb8ce00..d70c72bda90a5 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -10702,6 +10702,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), + SND_PCI_QUIRK(0x1043, 0x1054, "ASUS G614FH/FM/FP", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), ++ SND_PCI_QUIRK(0x1043, 0x106f, "ASUS VivoBook X515UA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1043, 0x1074, "ASUS G614PH/PM/PP", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x1043, 0x10a1, "ASUS UX391UA", ALC294_FIXUP_ASUS_SPK), + SND_PCI_QUIRK(0x1043, 0x10a4, "ASUS TP3407SA", ALC287_FIXUP_TAS2781_I2C), +-- +2.39.5 + diff --git a/queue-6.14/alsa-hda-realtek-fix-built-in-mic-breakage-on-asus-v.patch b/queue-6.14/alsa-hda-realtek-fix-built-in-mic-breakage-on-asus-v.patch new file mode 100644 index 0000000000..9a2c5b500f --- /dev/null +++ b/queue-6.14/alsa-hda-realtek-fix-built-in-mic-breakage-on-asus-v.patch @@ -0,0 +1,38 @@ +From d95843570aad4438f3bd2dc8ad4d9973322ed9fd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Mar 2025 16:22:01 +0100 +Subject: ALSA: hda/realtek: Fix built-in mic breakage on ASUS VivoBook X515JA + +From: Takashi Iwai + +[ Upstream commit 84c3c08f5a6c2e2209428b76156bcaf349c3a62d ] + +ASUS VivoBook X515JA with PCI SSID 1043:14f2 also hits the same issue +as other VivoBook model about the mic pin assignment, and the same +workaround is required to apply ALC256_FIXUP_ASUS_MIC_NO_PRESENCE +quirk. + +Fixes: 3b4309546b48 ("ALSA: hda: Fix headset detection failure due to unstable sort") +Link: https://bugzilla.kernel.org/show_bug.cgi?id=219902 +Link: https://patch.msgid.link/20250326152205.26733-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index d70c72bda90a5..9df400f7a144e 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -10736,6 +10736,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1043, 0x1493, "ASUS GV601VV/VU/VJ/VQ/VI", ALC285_FIXUP_ASUS_HEADSET_MIC), + SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G614JY/JZ/JG", ALC245_FIXUP_CS35L41_SPI_2), + SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS G513PI/PU/PV", ALC287_FIXUP_CS35L41_I2C_2), ++ SND_PCI_QUIRK(0x1043, 0x14f2, "ASUS VivoBook X515JA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1043, 0x1503, "ASUS G733PY/PZ/PZV/PYV", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A), + SND_PCI_QUIRK(0x1043, 0x1533, "ASUS GV302XA/XJ/XQ/XU/XV/XI", ALC287_FIXUP_CS35L41_I2C_2), +-- +2.39.5 + diff --git a/queue-6.14/alsa-hda-realtek-fix-built-in-mic-on-another-asus-vi.patch b/queue-6.14/alsa-hda-realtek-fix-built-in-mic-on-another-asus-vi.patch new file mode 100644 index 0000000000..89d1b50251 --- /dev/null +++ b/queue-6.14/alsa-hda-realtek-fix-built-in-mic-on-another-asus-vi.patch @@ -0,0 +1,38 @@ +From 5b82285d4ebbced65f6c3ad6639c79c184b8e223 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Apr 2025 09:42:07 +0200 +Subject: ALSA: hda/realtek: Fix built-in mic on another ASUS VivoBook model + +From: Takashi Iwai + +[ Upstream commit 8983dc1b66c0e1928a263b8af0bb06f6cb9229c4 ] + +There is another VivoBook model which built-in mic got broken recently +by the fix of the pin sort. Apply the correct quirk +ALC256_FIXUP_ASUS_MIC_NO_PRESENCE to this model for addressing the +regression, too. + +Fixes: 3b4309546b48 ("ALSA: hda: Fix headset detection failure due to unstable sort") +Closes: https://lore.kernel.org/Z95s5T6OXFPjRnKf@eldamar.lan +Link: https://patch.msgid.link/20250402074208.7347-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 9df400f7a144e..65ece19a6dd7d 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -10776,6 +10776,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1043, 0x1c43, "ASUS UX8406MA", ALC245_FIXUP_CS35L41_SPI_2), + SND_PCI_QUIRK(0x1043, 0x1c62, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), + SND_PCI_QUIRK(0x1043, 0x1c63, "ASUS GU605M", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1), ++ SND_PCI_QUIRK(0x1043, 0x1c80, "ASUS VivoBook TP401", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1043, 0x1c92, "ASUS ROG Strix G15", ALC285_FIXUP_ASUS_G533Z_PINS), + SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JU/JV/JI", ALC285_FIXUP_ASUS_HEADSET_MIC), + SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JY/JZ/JI/JG", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS), +-- +2.39.5 + diff --git a/queue-6.14/alsa-timer-don-t-take-register_mutex-with-copy_from-.patch b/queue-6.14/alsa-timer-don-t-take-register_mutex-with-copy_from-.patch new file mode 100644 index 0000000000..206a45fba6 --- /dev/null +++ b/queue-6.14/alsa-timer-don-t-take-register_mutex-with-copy_from-.patch @@ -0,0 +1,263 @@ +From 0cc401e774be66a104416d1cca411739caf0d8b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 18:26:52 +0100 +Subject: ALSA: timer: Don't take register_mutex with copy_from/to_user() + +From: Takashi Iwai + +[ Upstream commit 3424c8f53bc63c87712a7fc22dc13d0cc85fb0d6 ] + +The infamous mmap_lock taken in copy_from/to_user() can be often +problematic when it's called inside another mutex, as they might lead +to deadlocks. + +In the case of ALSA timer code, the bad pattern is with +guard(mutex)(®ister_mutex) that covers copy_from/to_user() -- which +was mistakenly introduced at converting to guard(), and it had been +carefully worked around in the past. + +This patch fixes those pieces simply by moving copy_from/to_user() out +of the register mutex lock again. + +Fixes: 3923de04c817 ("ALSA: pcm: oss: Use guard() for setup") +Reported-by: syzbot+2b96f44164236dda0f3b@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/67dd86c8.050a0220.25ae54.0059.GAE@google.com +Link: https://patch.msgid.link/20250321172653.14310-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/core/timer.c | 147 ++++++++++++++++++++++++--------------------- + 1 file changed, 77 insertions(+), 70 deletions(-) + +diff --git a/sound/core/timer.c b/sound/core/timer.c +index fbada79380f9e..d774b9b71ce23 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -1515,91 +1515,97 @@ static void snd_timer_user_copy_id(struct snd_timer_id *id, struct snd_timer *ti + id->subdevice = timer->tmr_subdevice; + } + +-static int snd_timer_user_next_device(struct snd_timer_id __user *_tid) ++static void get_next_device(struct snd_timer_id *id) + { +- struct snd_timer_id id; + struct snd_timer *timer; + struct list_head *p; + +- if (copy_from_user(&id, _tid, sizeof(id))) +- return -EFAULT; +- guard(mutex)(®ister_mutex); +- if (id.dev_class < 0) { /* first item */ ++ if (id->dev_class < 0) { /* first item */ + if (list_empty(&snd_timer_list)) +- snd_timer_user_zero_id(&id); ++ snd_timer_user_zero_id(id); + else { + timer = list_entry(snd_timer_list.next, + struct snd_timer, device_list); +- snd_timer_user_copy_id(&id, timer); ++ snd_timer_user_copy_id(id, timer); + } + } else { +- switch (id.dev_class) { ++ switch (id->dev_class) { + case SNDRV_TIMER_CLASS_GLOBAL: +- id.device = id.device < 0 ? 0 : id.device + 1; ++ id->device = id->device < 0 ? 0 : id->device + 1; + list_for_each(p, &snd_timer_list) { + timer = list_entry(p, struct snd_timer, device_list); + if (timer->tmr_class > SNDRV_TIMER_CLASS_GLOBAL) { +- snd_timer_user_copy_id(&id, timer); ++ snd_timer_user_copy_id(id, timer); + break; + } +- if (timer->tmr_device >= id.device) { +- snd_timer_user_copy_id(&id, timer); ++ if (timer->tmr_device >= id->device) { ++ snd_timer_user_copy_id(id, timer); + break; + } + } + if (p == &snd_timer_list) +- snd_timer_user_zero_id(&id); ++ snd_timer_user_zero_id(id); + break; + case SNDRV_TIMER_CLASS_CARD: + case SNDRV_TIMER_CLASS_PCM: +- if (id.card < 0) { +- id.card = 0; ++ if (id->card < 0) { ++ id->card = 0; + } else { +- if (id.device < 0) { +- id.device = 0; ++ if (id->device < 0) { ++ id->device = 0; + } else { +- if (id.subdevice < 0) +- id.subdevice = 0; +- else if (id.subdevice < INT_MAX) +- id.subdevice++; ++ if (id->subdevice < 0) ++ id->subdevice = 0; ++ else if (id->subdevice < INT_MAX) ++ id->subdevice++; + } + } + list_for_each(p, &snd_timer_list) { + timer = list_entry(p, struct snd_timer, device_list); +- if (timer->tmr_class > id.dev_class) { +- snd_timer_user_copy_id(&id, timer); ++ if (timer->tmr_class > id->dev_class) { ++ snd_timer_user_copy_id(id, timer); + break; + } +- if (timer->tmr_class < id.dev_class) ++ if (timer->tmr_class < id->dev_class) + continue; +- if (timer->card->number > id.card) { +- snd_timer_user_copy_id(&id, timer); ++ if (timer->card->number > id->card) { ++ snd_timer_user_copy_id(id, timer); + break; + } +- if (timer->card->number < id.card) ++ if (timer->card->number < id->card) + continue; +- if (timer->tmr_device > id.device) { +- snd_timer_user_copy_id(&id, timer); ++ if (timer->tmr_device > id->device) { ++ snd_timer_user_copy_id(id, timer); + break; + } +- if (timer->tmr_device < id.device) ++ if (timer->tmr_device < id->device) + continue; +- if (timer->tmr_subdevice > id.subdevice) { +- snd_timer_user_copy_id(&id, timer); ++ if (timer->tmr_subdevice > id->subdevice) { ++ snd_timer_user_copy_id(id, timer); + break; + } +- if (timer->tmr_subdevice < id.subdevice) ++ if (timer->tmr_subdevice < id->subdevice) + continue; +- snd_timer_user_copy_id(&id, timer); ++ snd_timer_user_copy_id(id, timer); + break; + } + if (p == &snd_timer_list) +- snd_timer_user_zero_id(&id); ++ snd_timer_user_zero_id(id); + break; + default: +- snd_timer_user_zero_id(&id); ++ snd_timer_user_zero_id(id); + } + } ++} ++ ++static int snd_timer_user_next_device(struct snd_timer_id __user *_tid) ++{ ++ struct snd_timer_id id; ++ ++ if (copy_from_user(&id, _tid, sizeof(id))) ++ return -EFAULT; ++ scoped_guard(mutex, ®ister_mutex) ++ get_next_device(&id); + if (copy_to_user(_tid, &id, sizeof(*_tid))) + return -EFAULT; + return 0; +@@ -1620,23 +1626,24 @@ static int snd_timer_user_ginfo(struct file *file, + tid = ginfo->tid; + memset(ginfo, 0, sizeof(*ginfo)); + ginfo->tid = tid; +- guard(mutex)(®ister_mutex); +- t = snd_timer_find(&tid); +- if (!t) +- return -ENODEV; +- ginfo->card = t->card ? t->card->number : -1; +- if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) +- ginfo->flags |= SNDRV_TIMER_FLG_SLAVE; +- strscpy(ginfo->id, t->id, sizeof(ginfo->id)); +- strscpy(ginfo->name, t->name, sizeof(ginfo->name)); +- scoped_guard(spinlock_irq, &t->lock) +- ginfo->resolution = snd_timer_hw_resolution(t); +- if (t->hw.resolution_min > 0) { +- ginfo->resolution_min = t->hw.resolution_min; +- ginfo->resolution_max = t->hw.resolution_max; +- } +- list_for_each(p, &t->open_list_head) { +- ginfo->clients++; ++ scoped_guard(mutex, ®ister_mutex) { ++ t = snd_timer_find(&tid); ++ if (!t) ++ return -ENODEV; ++ ginfo->card = t->card ? t->card->number : -1; ++ if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) ++ ginfo->flags |= SNDRV_TIMER_FLG_SLAVE; ++ strscpy(ginfo->id, t->id, sizeof(ginfo->id)); ++ strscpy(ginfo->name, t->name, sizeof(ginfo->name)); ++ scoped_guard(spinlock_irq, &t->lock) ++ ginfo->resolution = snd_timer_hw_resolution(t); ++ if (t->hw.resolution_min > 0) { ++ ginfo->resolution_min = t->hw.resolution_min; ++ ginfo->resolution_max = t->hw.resolution_max; ++ } ++ list_for_each(p, &t->open_list_head) { ++ ginfo->clients++; ++ } + } + if (copy_to_user(_ginfo, ginfo, sizeof(*ginfo))) + return -EFAULT; +@@ -1674,31 +1681,31 @@ static int snd_timer_user_gstatus(struct file *file, + struct snd_timer_gstatus gstatus; + struct snd_timer_id tid; + struct snd_timer *t; +- int err = 0; + + if (copy_from_user(&gstatus, _gstatus, sizeof(gstatus))) + return -EFAULT; + tid = gstatus.tid; + memset(&gstatus, 0, sizeof(gstatus)); + gstatus.tid = tid; +- guard(mutex)(®ister_mutex); +- t = snd_timer_find(&tid); +- if (t != NULL) { +- guard(spinlock_irq)(&t->lock); +- gstatus.resolution = snd_timer_hw_resolution(t); +- if (t->hw.precise_resolution) { +- t->hw.precise_resolution(t, &gstatus.resolution_num, +- &gstatus.resolution_den); ++ scoped_guard(mutex, ®ister_mutex) { ++ t = snd_timer_find(&tid); ++ if (t != NULL) { ++ guard(spinlock_irq)(&t->lock); ++ gstatus.resolution = snd_timer_hw_resolution(t); ++ if (t->hw.precise_resolution) { ++ t->hw.precise_resolution(t, &gstatus.resolution_num, ++ &gstatus.resolution_den); ++ } else { ++ gstatus.resolution_num = gstatus.resolution; ++ gstatus.resolution_den = 1000000000uL; ++ } + } else { +- gstatus.resolution_num = gstatus.resolution; +- gstatus.resolution_den = 1000000000uL; ++ return -ENODEV; + } +- } else { +- err = -ENODEV; + } +- if (err >= 0 && copy_to_user(_gstatus, &gstatus, sizeof(gstatus))) +- err = -EFAULT; +- return err; ++ if (copy_to_user(_gstatus, &gstatus, sizeof(gstatus))) ++ return -EFAULT; ++ return 0; + } + + static int snd_timer_user_tselect(struct file *file, +-- +2.39.5 + diff --git a/queue-6.14/alsa-usb-audio-separate-djm-a9-cap-lvl-options.patch b/queue-6.14/alsa-usb-audio-separate-djm-a9-cap-lvl-options.patch new file mode 100644 index 0000000000..575d93ae94 --- /dev/null +++ b/queue-6.14/alsa-usb-audio-separate-djm-a9-cap-lvl-options.patch @@ -0,0 +1,63 @@ +From fe2ce89c33427871c92907d0267668441549d7b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Mar 2025 15:33:23 +0000 +Subject: ALSA: usb-audio: separate DJM-A9 cap lvl options + +From: Olivia Mackintosh + +[ Upstream commit 38e94cefbf45c1edc5b751ab90a3088f7c6fac1a ] + +Mixer quicks for the Pioneer DJM-A9 mixer was added in 5289d00 with +additional capture level values added to the common DJM array of values. + +This breaks the existing DJM mixers however as alsa-utils relies on +enumeration of the actual mixer options based on the value array which +results in error when storing state. + +This commit just separates the A9 values into a separate array and +references them in the corresponding mixer control. + +Fixes: 5289d0069639 ("ALSA: usb-audio: Add Pioneer DJ/AlphaTheta DJM-A9 Mixer") +Signed-off-by: Olivia Mackintosh +Link: https://patch.msgid.link/20250316153323.16381-1-livvy@base.nu +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/usb/mixer_quirks.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c +index 3d36d22f8e9e6..62b28e9d83c7a 100644 +--- a/sound/usb/mixer_quirks.c ++++ b/sound/usb/mixer_quirks.c +@@ -3688,8 +3688,7 @@ static const char *snd_djm_get_label(u8 device_idx, u16 wvalue, u16 windex) + + // common DJM capture level option values + static const u16 snd_djm_opts_cap_level[] = { +- 0x0000, 0x0100, 0x0200, 0x0300, 0x400, 0x500 }; +- ++ 0x0000, 0x0100, 0x0200, 0x0300 }; + + // DJM-250MK2 + static const u16 snd_djm_opts_250mk2_cap1[] = { +@@ -3831,6 +3830,8 @@ static const struct snd_djm_ctl snd_djm_ctls_750mk2[] = { + + + // DJM-A9 ++static const u16 snd_djm_opts_a9_cap_level[] = { ++ 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500 }; + static const u16 snd_djm_opts_a9_cap1[] = { + 0x0107, 0x0108, 0x0109, 0x010a, 0x010e, + 0x111, 0x112, 0x113, 0x114, 0x0131, 0x132, 0x133, 0x134 }; +@@ -3844,7 +3845,7 @@ static const u16 snd_djm_opts_a9_cap5[] = { + 0x0501, 0x0502, 0x0503, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509, 0x050a, 0x050e }; + + static const struct snd_djm_ctl snd_djm_ctls_a9[] = { +- SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL), ++ SND_DJM_CTL("Capture Level", a9_cap_level, 0, SND_DJM_WINDEX_CAPLVL), + SND_DJM_CTL("Master Input", a9_cap1, 3, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch1 Input", a9_cap2, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch2 Input", a9_cap3, 2, SND_DJM_WINDEX_CAP), +-- +2.39.5 + diff --git a/queue-6.14/arch-powerpc-drop-generic_ptdump-from-mpc885_ads_def.patch b/queue-6.14/arch-powerpc-drop-generic_ptdump-from-mpc885_ads_def.patch new file mode 100644 index 0000000000..0b2cf70eab --- /dev/null +++ b/queue-6.14/arch-powerpc-drop-generic_ptdump-from-mpc885_ads_def.patch @@ -0,0 +1,52 @@ +From 32d7501b039ae52a082dfa2a60f150d308e1e1aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 17:54:01 +0530 +Subject: arch/powerpc: drop GENERIC_PTDUMP from mpc885_ads_defconfig + +From: Anshuman Khandual + +[ Upstream commit 2c5e6ac2db64ace51f66a9f3b3b3ab9553d748e8 ] + +GENERIC_PTDUMP gets selected on powerpc explicitly and hence can be +dropped off from mpc885_ads_defconfig. Replace with CONFIG_PTDUMP_DEBUGFS +instead. + +Link: https://lkml.kernel.org/r/20250226122404.1927473-3-anshuman.khandual@arm.com +Fixes: e084728393a5 ("powerpc/ptdump: Convert powerpc to GENERIC_PTDUMP") +Signed-off-by: Anshuman Khandual +Suggested-by: Christophe Leroy +Reviewed-by: Christophe Leroy +Cc: Madhavan Srinivasan +Cc: Michael Ellerman +Cc: Nicholas Piggin +Cc: Catalin Marinas +Cc: Heiko Carstens +Cc: Ingo Molnar +Cc: Jonathan Corbet +Cc: Marc Zyngier +Cc: Mark Rutland +Cc: Palmer Dabbelt +Cc: Paul Walmsley +Cc: Steven Price +Cc: Thomas Gleixner +Cc: Vasily Gorbik +Cc: Will Deacon +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + arch/powerpc/configs/mpc885_ads_defconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/powerpc/configs/mpc885_ads_defconfig b/arch/powerpc/configs/mpc885_ads_defconfig +index 77306be62e9ee..129355f87f80f 100644 +--- a/arch/powerpc/configs/mpc885_ads_defconfig ++++ b/arch/powerpc/configs/mpc885_ads_defconfig +@@ -78,4 +78,4 @@ CONFIG_DEBUG_VM_PGTABLE=y + CONFIG_DETECT_HUNG_TASK=y + CONFIG_BDI_SWITCH=y + CONFIG_PPC_EARLY_DEBUG=y +-CONFIG_GENERIC_PTDUMP=y ++CONFIG_PTDUMP_DEBUGFS=y +-- +2.39.5 + diff --git a/queue-6.14/arcnet-add-null-check-in-com20020pci_probe.patch b/queue-6.14/arcnet-add-null-check-in-com20020pci_probe.patch new file mode 100644 index 0000000000..910a6726af --- /dev/null +++ b/queue-6.14/arcnet-add-null-check-in-com20020pci_probe.patch @@ -0,0 +1,67 @@ +From e8ebf4ac0f77b2f59a033cafc33db785481b32e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Apr 2025 21:50:36 +0800 +Subject: arcnet: Add NULL check in com20020pci_probe() + +From: Henry Martin + +[ Upstream commit fda8c491db2a90ff3e6fbbae58e495b4ddddeca3 ] + +devm_kasprintf() returns NULL when memory allocation fails. Currently, +com20020pci_probe() does not check for this case, which results in a +NULL pointer dereference. + +Add NULL check after devm_kasprintf() to prevent this issue and ensure +no resources are left allocated. + +Fixes: 6b17a597fc2f ("arcnet: restoring support for multiple Sohard Arcnet cards") +Signed-off-by: Henry Martin +Link: https://patch.msgid.link/20250402135036.44697-1-bsdhenrymartin@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/arcnet/com20020-pci.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c +index c5e571ec94c99..0472bcdff1307 100644 +--- a/drivers/net/arcnet/com20020-pci.c ++++ b/drivers/net/arcnet/com20020-pci.c +@@ -251,18 +251,33 @@ static int com20020pci_probe(struct pci_dev *pdev, + card->tx_led.default_trigger = devm_kasprintf(&pdev->dev, + GFP_KERNEL, "arc%d-%d-tx", + dev->dev_id, i); ++ if (!card->tx_led.default_trigger) { ++ ret = -ENOMEM; ++ goto err_free_arcdev; ++ } + card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "pci:green:tx:%d-%d", + dev->dev_id, i); +- ++ if (!card->tx_led.name) { ++ ret = -ENOMEM; ++ goto err_free_arcdev; ++ } + card->tx_led.dev = &dev->dev; + card->recon_led.brightness_set = led_recon_set; + card->recon_led.default_trigger = devm_kasprintf(&pdev->dev, + GFP_KERNEL, "arc%d-%d-recon", + dev->dev_id, i); ++ if (!card->recon_led.default_trigger) { ++ ret = -ENOMEM; ++ goto err_free_arcdev; ++ } + card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "pci:red:recon:%d-%d", + dev->dev_id, i); ++ if (!card->recon_led.name) { ++ ret = -ENOMEM; ++ goto err_free_arcdev; ++ } + card->recon_led.dev = &dev->dev; + + ret = devm_led_classdev_register(&pdev->dev, &card->tx_led); +-- +2.39.5 + diff --git a/queue-6.14/arm-dts-imx6ul-tqma6ul1-change-include-order-to-disa.patch b/queue-6.14/arm-dts-imx6ul-tqma6ul1-change-include-order-to-disa.patch new file mode 100644 index 0000000000..f7927b6aa1 --- /dev/null +++ b/queue-6.14/arm-dts-imx6ul-tqma6ul1-change-include-order-to-disa.patch @@ -0,0 +1,55 @@ +From 78f90e25c33b09c60326f5c5a03f16c93b1756cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 15:44:35 +0100 +Subject: ARM: dts: imx6ul-tqma6ul1: Change include order to disable fec2 node + +From: Max Merchel + +[ Upstream commit 22d8f69c8ddcd036d6e81589e95a058b86272bd1 ] + +TQMa6UL1 has only one FEC which needs to be disabled as one of the last +steps. +imx6ul-tqma6ul2.dtsi can't be included in imx6ul-tqma6ul1.dtsi as the +defaults from imx6ul.dtsi will be applied again. + +Fixes: 7b8861d8e627 ("ARM: dts: imx6ul: add TQ-Systems MBa6ULx device trees") +Signed-off-by: Max Merchel +Signed-off-by: Alexander Stein +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul1-mba6ulx.dts | 3 ++- + arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul1.dtsi | 2 -- + 2 files changed, 2 insertions(+), 3 deletions(-) + +diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul1-mba6ulx.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul1-mba6ulx.dts +index f2a5f17f312e5..2e7b96e7b791d 100644 +--- a/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul1-mba6ulx.dts ++++ b/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul1-mba6ulx.dts +@@ -6,8 +6,9 @@ + + /dts-v1/; + +-#include "imx6ul-tqma6ul1.dtsi" ++#include "imx6ul-tqma6ul2.dtsi" + #include "mba6ulx.dtsi" ++#include "imx6ul-tqma6ul1.dtsi" + + / { + model = "TQ-Systems TQMa6UL1 SoM on MBa6ULx board"; +diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul1.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul1.dtsi +index 24192d012ef7e..79c8c5529135a 100644 +--- a/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul1.dtsi ++++ b/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul1.dtsi +@@ -4,8 +4,6 @@ + * Author: Markus Niebel + */ + +-#include "imx6ul-tqma6ul2.dtsi" +- + / { + model = "TQ-Systems TQMa6UL1 SoM"; + compatible = "tq,imx6ul-tqma6ul1", "fsl,imx6ul"; +-- +2.39.5 + diff --git a/queue-6.14/arm-dts-omap4-panda-a4-add-missing-model-and-compati.patch b/queue-6.14/arm-dts-omap4-panda-a4-add-missing-model-and-compati.patch new file mode 100644 index 0000000000..3e1b9e3450 --- /dev/null +++ b/queue-6.14/arm-dts-omap4-panda-a4-add-missing-model-and-compati.patch @@ -0,0 +1,42 @@ +From e8459767e1e36b246044ebebbe8ec837815ca992 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 11:49:01 -0600 +Subject: ARM: dts: omap4-panda-a4: Add missing model and compatible properties + +From: Tom Rini + +[ Upstream commit ea07a4775df03852c353514b5b7646a17bd425be ] + +When moving the model and compatible properties out of the common +Pandaboard files and in to the specific boards, the omap4-panda-a4 +file wasn't updated as well and so has lacked a model and compatible +entry ever since. + +Fixes: a1a57abaaf82 ("ARM: dts: omap4-panda: Fix model and SoC family details") +Signed-off-by: Tom Rini +Link: https://lore.kernel.org/r/20250123174901.1182176-2-trini@konsulko.com +Signed-off-by: Kevin Hilman +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/ti/omap/omap4-panda-a4.dts | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm/boot/dts/ti/omap/omap4-panda-a4.dts b/arch/arm/boot/dts/ti/omap/omap4-panda-a4.dts +index 8fd076e5d1b01..4b8bfd0188add 100644 +--- a/arch/arm/boot/dts/ti/omap/omap4-panda-a4.dts ++++ b/arch/arm/boot/dts/ti/omap/omap4-panda-a4.dts +@@ -7,6 +7,11 @@ + #include "omap443x.dtsi" + #include "omap4-panda-common.dtsi" + ++/ { ++ model = "TI OMAP4 PandaBoard (A4)"; ++ compatible = "ti,omap4-panda-a4", "ti,omap4-panda", "ti,omap4430", "ti,omap4"; ++}; ++ + /* Pandaboard Rev A4+ have external pullups on SCL & SDA */ + &dss_hdmi_pins { + pinctrl-single,pins = < +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-imx8mp-add-audio_axi_clk_root-to-audiomix-.patch b/queue-6.14/arm64-dts-imx8mp-add-audio_axi_clk_root-to-audiomix-.patch new file mode 100644 index 0000000000..efcaf89ccb --- /dev/null +++ b/queue-6.14/arm64-dts-imx8mp-add-audio_axi_clk_root-to-audiomix-.patch @@ -0,0 +1,43 @@ +From 0db2ef6be00873d03827f8fad73cfa24a3ebf4c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 11:45:12 -0500 +Subject: arm64: dts: imx8mp: add AUDIO_AXI_CLK_ROOT to AUDIOMIX block + +From: Laurentiu Mihalcea + +[ Upstream commit cfe47a3d3f7440cd1bdf2a169b325257eba01534 ] + +Needed because the DSP and OCRAM_A components from AUDIOMIX are clocked +by AUDIO_AXI_CLK_ROOT instead of AUDIO_AHB_CLK_ROOT. + +Fixes: b86c3afabb4f ("arm64: dts: imx8mp: Add SAI, SDMA, AudioMIX") +Signed-off-by: Laurentiu Mihalcea +Reviewed-by: Iuliana Prodan +Reviewed-by: Peng Fan +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/freescale/imx8mp.dtsi | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi +index e0d3b8cba221e..86c3055789ba7 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi ++++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi +@@ -1619,10 +1619,11 @@ + <&clk IMX8MP_CLK_SAI3>, + <&clk IMX8MP_CLK_SAI5>, + <&clk IMX8MP_CLK_SAI6>, +- <&clk IMX8MP_CLK_SAI7>; ++ <&clk IMX8MP_CLK_SAI7>, ++ <&clk IMX8MP_CLK_AUDIO_AXI_ROOT>; + clock-names = "ahb", + "sai1", "sai2", "sai3", +- "sai5", "sai6", "sai7"; ++ "sai5", "sai6", "sai7", "axi"; + power-domains = <&pgc_audio>; + assigned-clocks = <&clk IMX8MP_AUDIO_PLL1>, + <&clk IMX8MP_AUDIO_PLL2>; +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-imx8mp-change-audio_axi_clk_root-freq.-to-.patch b/queue-6.14/arm64-dts-imx8mp-change-audio_axi_clk_root-freq.-to-.patch new file mode 100644 index 0000000000..6be70fe98b --- /dev/null +++ b/queue-6.14/arm64-dts-imx8mp-change-audio_axi_clk_root-freq.-to-.patch @@ -0,0 +1,40 @@ +From 62f5e3a40c2d8b0c377de07721674f8bacb45060 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 11:45:13 -0500 +Subject: arm64: dts: imx8mp: change AUDIO_AXI_CLK_ROOT freq. to 800MHz + +From: Laurentiu Mihalcea + +[ Upstream commit c54e2f908da30a6c66195a6d0aba6412c673ec2c ] + +AUDIO_AXI_CLK_ROOT can't run at currently requested 600MHz w/ its parent +SYS_PLL1 configured at 800MHz. Configure it to run at 800MHz as some +applications running on the DSP expect the core to run at this frequency +anyways. This change also affects the AUDIOMIX NoC. + +Fixes: b739681b3f8b ("arm64: dts: imx8mp: Fix SDMA2/3 clocks") +Signed-off-by: Laurentiu Mihalcea +Reviewed-by: Iuliana Prodan +Reviewed-by: Peng Fan +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/freescale/imx8mp.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi +index 86c3055789ba7..54147bce3b838 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi ++++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi +@@ -834,7 +834,7 @@ + assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>, + <&clk IMX8MP_SYS_PLL1_800M>; + assigned-clock-rates = <400000000>, +- <600000000>; ++ <800000000>; + }; + + pgc_gpu2d: power-domain@6 { +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-imx8mp-skov-correct-pmic-board-limits.patch b/queue-6.14/arm64-dts-imx8mp-skov-correct-pmic-board-limits.patch new file mode 100644 index 0000000000..4a74eed24e --- /dev/null +++ b/queue-6.14/arm64-dts-imx8mp-skov-correct-pmic-board-limits.patch @@ -0,0 +1,99 @@ +From 21ed7eae30ebf0d38c6a36adf098ecdaa3d49dad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jan 2025 17:06:36 +0100 +Subject: arm64: dts: imx8mp-skov: correct PMIC board limits + +From: Ahmad Fatoum + +[ Upstream commit d19a6f79961df1c29d8b2ac93b01b96788f209fa ] + +The PMIC voltage constraints in the device tree currently describe the +permissible range of the PMIC. This is unnecessary as this information +already exists in the driver and wrong as it doesn't account for +board-specific constraints, e.g. a 2.1V on VDD_SOC would fry the SoC and +a maximum voltage of 3.4V on the VDD_3V3 rail may be unexpected across +the board. + +Fix this by adjusting constraints to reflect the board limits. + +Fixes: 6d382d51d979 ("arm64: dts: freescale: Add SKOV IMX8MP CPU revB board") +Signed-off-by: Ahmad Fatoum +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + .../boot/dts/freescale/imx8mp-skov-reva.dtsi | 24 +++++++++---------- + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/arch/arm64/boot/dts/freescale/imx8mp-skov-reva.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-skov-reva.dtsi +index 59813ef8e2bb3..ae82166b5c266 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mp-skov-reva.dtsi ++++ b/arch/arm64/boot/dts/freescale/imx8mp-skov-reva.dtsi +@@ -247,8 +247,8 @@ + + reg_vdd_arm: BUCK2 { + regulator-name = "VDD_ARM"; +- regulator-min-microvolt = <600000>; +- regulator-max-microvolt = <2187500>; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <1000000>; + vin-supply = <®_5v_p>; + regulator-boot-on; + regulator-always-on; +@@ -259,8 +259,8 @@ + + reg_vdd_3v3: BUCK4 { + regulator-name = "VDD_3V3"; +- regulator-min-microvolt = <600000>; +- regulator-max-microvolt = <3400000>; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; + vin-supply = <®_5v_p>; + regulator-boot-on; + regulator-always-on; +@@ -268,8 +268,8 @@ + + reg_vdd_1v8: BUCK5 { + regulator-name = "VDD_1V8"; +- regulator-min-microvolt = <600000>; +- regulator-max-microvolt = <3400000>; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; + vin-supply = <®_5v_p>; + regulator-boot-on; + regulator-always-on; +@@ -277,8 +277,8 @@ + + reg_nvcc_dram_1v1: BUCK6 { + regulator-name = "NVCC_DRAM_1V1"; +- regulator-min-microvolt = <600000>; +- regulator-max-microvolt = <3400000>; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1100000>; + vin-supply = <®_5v_p>; + regulator-boot-on; + regulator-always-on; +@@ -286,8 +286,8 @@ + + reg_nvcc_snvs_1v8: LDO1 { + regulator-name = "NVCC_SNVS_1V8"; +- regulator-min-microvolt = <1600000>; +- regulator-max-microvolt = <3300000>; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; + vin-supply = <®_5v_p>; + regulator-boot-on; + regulator-always-on; +@@ -295,8 +295,8 @@ + + reg_vdda_1v8: LDO3 { + regulator-name = "VDDA_1V8"; +- regulator-min-microvolt = <800000>; +- regulator-max-microvolt = <3300000>; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; + vin-supply = <®_5v_p>; + regulator-boot-on; + regulator-always-on; +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-imx8mp-skov-operate-cpu-at-850-mv-by-defau.patch b/queue-6.14/arm64-dts-imx8mp-skov-operate-cpu-at-850-mv-by-defau.patch new file mode 100644 index 0000000000..9ad7823053 --- /dev/null +++ b/queue-6.14/arm64-dts-imx8mp-skov-operate-cpu-at-850-mv-by-defau.patch @@ -0,0 +1,61 @@ +From 60d14b70e672353e35aed903f400d2e8a64a8b50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jan 2025 17:06:37 +0100 +Subject: arm64: dts: imx8mp-skov: operate CPU at 850 mV by default + +From: Ahmad Fatoum + +[ Upstream commit 3d8ffe5702b24a0bd9d97446c0740110325f379b ] + +The Skov i.MX8MP boards are passively cooled and heatsink is specced for +continuous operation at 1.2 GHz only. Short bouts of 1.6 GHz are ok, +but these should be invoked intentionally, not as part of +suspend/resume cycles. + +Therefore, configure RUN frequency as 850 mV and remove the higher +voltage operating points from those permissible for suspend. + +Fixes: 6d382d51d979 ("arm64: dts: freescale: Add SKOV IMX8MP CPU revB board") +Signed-off-by: Ahmad Fatoum +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + .../boot/dts/freescale/imx8mp-skov-reva.dtsi | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/freescale/imx8mp-skov-reva.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-skov-reva.dtsi +index ae82166b5c266..7ae686d37ddac 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mp-skov-reva.dtsi ++++ b/arch/arm64/boot/dts/freescale/imx8mp-skov-reva.dtsi +@@ -163,6 +163,19 @@ + }; + }; + ++/* ++ * Board is passively cooled and heatsink is specced for continuous operation ++ * at 1.2 GHz only. Short bouts of 1.6 GHz are ok, but these should be done ++ * intentionally, not as part of suspend/resume cycles. ++ */ ++&{/opp-table/opp-1600000000} { ++ /delete-property/ opp-suspend; ++}; ++ ++&{/opp-table/opp-1800000000} { ++ /delete-property/ opp-suspend; ++}; ++ + &A53_0 { + cpu-supply = <®_vdd_arm>; + }; +@@ -253,7 +266,7 @@ + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <3125>; +- nxp,dvs-run-voltage = <950000>; ++ nxp,dvs-run-voltage = <850000>; + nxp,dvs-standby-voltage = <850000>; + }; + +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-mediatek-mt6359-fix-dtbs_check-error-for-a.patch b/queue-6.14/arm64-dts-mediatek-mt6359-fix-dtbs_check-error-for-a.patch new file mode 100644 index 0000000000..4cb872e857 --- /dev/null +++ b/queue-6.14/arm64-dts-mediatek-mt6359-fix-dtbs_check-error-for-a.patch @@ -0,0 +1,42 @@ +From 8a8781c70a6c3b66e482d4f03c136573e7a76372 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 19:37:36 +0800 +Subject: arm64: dts: mediatek: mt6359: fix dtbs_check error for audio-codec + +From: Macpaul Lin + +[ Upstream commit 76b35f59bbe66d3eda8a98021bc01f9200131f09 ] + +This change fixes these dtbs_check errors for audio-codec: +1. pmic: 'mt6359codec' does not match any of the regexes: 'pinctrl-[0-9]+' + - Replace device node name to generic 'audio-codec' +2. pmic: regulators: 'compatible' is a required property + - Add 'mediatek,mt6359-codec' to compatible. + +Fixes: 3b7d143be4b7 ("arm64: dts: mt6359: add PMIC MT6359 related nodes") +Signed-off-by: Macpaul Lin +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20250217113736.1867808-1-macpaul.lin@mediatek.com +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt6359.dtsi | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt6359.dtsi b/arch/arm64/boot/dts/mediatek/mt6359.dtsi +index 150ad84d5d2b3..7b10f9c59819a 100644 +--- a/arch/arm64/boot/dts/mediatek/mt6359.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt6359.dtsi +@@ -15,7 +15,8 @@ + #io-channel-cells = <1>; + }; + +- mt6359codec: mt6359codec { ++ mt6359codec: audio-codec { ++ compatible = "mediatek,mt6359-codec"; + }; + + regulators { +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-mediatek-mt8173-elm-drop-pmic-s-address-ce.patch b/queue-6.14/arm64-dts-mediatek-mt8173-elm-drop-pmic-s-address-ce.patch new file mode 100644 index 0000000000..bec8866311 --- /dev/null +++ b/queue-6.14/arm64-dts-mediatek-mt8173-elm-drop-pmic-s-address-ce.patch @@ -0,0 +1,46 @@ +From 405223dd87f3a5e71f4c646273491b52c1151254 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jan 2025 16:34:21 +0800 +Subject: arm64: dts: mediatek: mt8173-elm: Drop pmic's #address-cells and + #size-cells + +From: Chen-Yu Tsai + +[ Upstream commit aaa0b40e157c65aaa5e0ad903675f245333381bb ] + +The PMIC has child nodes for each of its functions. It is not an actual +bus and no addressing is involved. + +Dropping the bogus properties fixes a DT validation error: + + arch/arm64/boot/dts/mediatek/mt8173-elm.dtb: pmic: '#address-cells', '#size-cells' do not match any of the regexes: 'pinctrl-[0-9]+' + from schema $id: http://devicetree.org/schemas/mfd/mediatek,mt6397.yaml# + +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202412212322.JTFpRD7X-lkp@intel.com/ +Fixes: 689b937bedde ("arm64: dts: mediatek: add mt8173 elm and hana board") +Signed-off-by: Chen-Yu Tsai +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20250108083424.2732375-1-wenst@chromium.org +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi b/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi +index b5d4b5baf4785..0d995b342d463 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi +@@ -925,8 +925,6 @@ + &pwrap { + pmic: pmic { + compatible = "mediatek,mt6397"; +- #address-cells = <1>; +- #size-cells = <1>; + interrupts-extended = <&pio 11 IRQ_TYPE_LEVEL_HIGH>; + interrupt-controller; + #interrupt-cells = <2>; +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-mediatek-mt8173-fix-some-node-names.patch b/queue-6.14/arm64-dts-mediatek-mt8173-fix-some-node-names.patch new file mode 100644 index 0000000000..0b4e435ab1 --- /dev/null +++ b/queue-6.14/arm64-dts-mediatek-mt8173-fix-some-node-names.patch @@ -0,0 +1,57 @@ +From a3a98687ae8b94d780818a89c5b6a49256ce6245 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jan 2025 16:34:23 +0800 +Subject: arm64: dts: mediatek: mt8173: Fix some node names + +From: Chen-Yu Tsai + +[ Upstream commit be035e4a26edf8fdcbc4fe95d16c28deade13bb0 ] + +Some node names are incorrect, causing DT validations due to mismatches. + +Fixes: b3a372484157 ("arm64: dts: Add mediatek MT8173 SoC and evaluation board dts and Makefile") +Fixes: f2ce70149568 ("arm64: dts: mt8173: Add clock controller device nodes") +Cc: Eddie Huang +Cc: Sascha Hauer +Signed-off-by: Chen-Yu Tsai +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20250108083424.2732375-3-wenst@chromium.org +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8173.dtsi | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi +index 3458be7f7f611..0ca63e8c4e16c 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi +@@ -352,14 +352,14 @@ + #clock-cells = <1>; + }; + +- infracfg: power-controller@10001000 { ++ infracfg: clock-controller@10001000 { + compatible = "mediatek,mt8173-infracfg", "syscon"; + reg = <0 0x10001000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + +- pericfg: power-controller@10003000 { ++ pericfg: clock-controller@10003000 { + compatible = "mediatek,mt8173-pericfg", "syscon"; + reg = <0 0x10003000 0 0x1000>; + #clock-cells = <1>; +@@ -564,7 +564,7 @@ + memory-region = <&vpu_dma_reserved>; + }; + +- sysirq: intpol-controller@10200620 { ++ sysirq: interrupt-controller@10200620 { + compatible = "mediatek,mt8173-sysirq", + "mediatek,mt6577-sysirq"; + interrupt-controller; +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-mediatek-mt8390-genio-700-evk-move-common-.patch b/queue-6.14/arm64-dts-mediatek-mt8390-genio-700-evk-move-common-.patch new file mode 100644 index 0000000000..fa4d3c63d4 --- /dev/null +++ b/queue-6.14/arm64-dts-mediatek-mt8390-genio-700-evk-move-common-.patch @@ -0,0 +1,2133 @@ +From c73f4bb74707d8a88e28675386b29635d82bebcb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 11:38:10 +0100 +Subject: arm64: dts: mediatek: mt8390-genio-700-evk: Move common parts to dtsi + +From: Louis-Alexis Eyraud + +[ Upstream commit 73955991b8fb959eb3d8b5307255810e4fb37b24 ] + +In preparation for introducing the Genio 510 EVK board support, split +mt8390-genio-700-evk.dts file in two to create mt8390-genio-common.dtsi +file, containing common definitions for both boards. + +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Louis-Alexis Eyraud +Link: https://lore.kernel.org/r/20250206-dts_mt8370-genio-510-v3-3-5ca5c3257a4c@collabora.com +Signed-off-by: AngeloGioacchino Del Regno +Stable-dep-of: 18aa138d125d ("arm64: dts: mediatek: mt8390-genio-common: Fix duplicated regulator name") +Signed-off-by: Sasha Levin +--- + .../dts/mediatek/mt8390-genio-700-evk.dts | 1033 +--------------- + .../dts/mediatek/mt8390-genio-common.dtsi | 1046 +++++++++++++++++ + 2 files changed, 1047 insertions(+), 1032 deletions(-) + create mode 100644 arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi + +diff --git a/arch/arm64/boot/dts/mediatek/mt8390-genio-700-evk.dts b/arch/arm64/boot/dts/mediatek/mt8390-genio-700-evk.dts +index 04e4a2f73799d..612336713a64e 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8390-genio-700-evk.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8390-genio-700-evk.dts +@@ -8,1047 +8,16 @@ + /dts-v1/; + + #include "mt8188.dtsi" +-#include "mt6359.dtsi" +-#include +-#include +-#include +-#include +-#include +-#include +-#include ++#include "mt8390-genio-common.dtsi" + + / { + model = "MediaTek Genio-700 EVK"; + compatible = "mediatek,mt8390-evk", "mediatek,mt8390", + "mediatek,mt8188"; + +- aliases { +- ethernet0 = ð +- i2c0 = &i2c0; +- i2c1 = &i2c1; +- i2c2 = &i2c2; +- i2c3 = &i2c3; +- i2c4 = &i2c4; +- i2c5 = &i2c5; +- i2c6 = &i2c6; +- mmc0 = &mmc0; +- mmc1 = &mmc1; +- serial0 = &uart0; +- }; +- +- chosen { +- stdout-path = "serial0:921600n8"; +- }; +- +- firmware { +- optee { +- compatible = "linaro,optee-tz"; +- method = "smc"; +- }; +- }; +- + memory@40000000 { + device_type = "memory"; + reg = <0 0x40000000 0x2 0x00000000>; + }; +- +- reserved-memory { +- #address-cells = <2>; +- #size-cells = <2>; +- ranges; +- +- /* +- * 12 MiB reserved for OP-TEE (BL32) +- * +-----------------------+ 0x43e0_0000 +- * | SHMEM 2MiB | +- * +-----------------------+ 0x43c0_0000 +- * | | TA_RAM 8MiB | +- * + TZDRAM +--------------+ 0x4340_0000 +- * | | TEE_RAM 2MiB | +- * +-----------------------+ 0x4320_0000 +- */ +- optee_reserved: optee@43200000 { +- no-map; +- reg = <0 0x43200000 0 0x00c00000>; +- }; +- +- scp_mem: memory@50000000 { +- compatible = "shared-dma-pool"; +- reg = <0 0x50000000 0 0x2900000>; +- no-map; +- }; +- +- /* 2 MiB reserved for ARM Trusted Firmware (BL31) */ +- bl31_secmon_reserved: memory@54600000 { +- no-map; +- reg = <0 0x54600000 0x0 0x200000>; +- }; +- +- apu_mem: memory@55000000 { +- compatible = "shared-dma-pool"; +- reg = <0 0x55000000 0 0x1400000>; /* 20 MB */ +- }; +- +- vpu_mem: memory@57000000 { +- compatible = "shared-dma-pool"; +- reg = <0 0x57000000 0 0x1400000>; /* 20 MB */ +- }; +- +- adsp_mem: memory@60000000 { +- compatible = "shared-dma-pool"; +- reg = <0 0x60000000 0 0xf00000>; +- no-map; +- }; +- +- afe_dma_mem: memory@60f00000 { +- compatible = "shared-dma-pool"; +- reg = <0 0x60f00000 0 0x100000>; +- no-map; +- }; +- +- adsp_dma_mem: memory@61000000 { +- compatible = "shared-dma-pool"; +- reg = <0 0x61000000 0 0x100000>; +- no-map; +- }; +- }; +- +- common_fixed_5v: regulator-0 { +- compatible = "regulator-fixed"; +- regulator-name = "vdd_5v"; +- regulator-min-microvolt = <5000000>; +- regulator-max-microvolt = <5000000>; +- gpio = <&pio 10 GPIO_ACTIVE_HIGH>; +- enable-active-high; +- regulator-always-on; +- vin-supply = <®_vsys>; +- }; +- +- edp_panel_fixed_3v3: regulator-1 { +- compatible = "regulator-fixed"; +- regulator-name = "vedp_3v3"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- enable-active-high; +- gpio = <&pio 15 GPIO_ACTIVE_HIGH>; +- pinctrl-names = "default"; +- pinctrl-0 = <&edp_panel_3v3_en_pins>; +- vin-supply = <®_vsys>; +- }; +- +- gpio_fixed_3v3: regulator-2 { +- compatible = "regulator-fixed"; +- regulator-name = "ext_3v3"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- gpio = <&pio 9 GPIO_ACTIVE_HIGH>; +- enable-active-high; +- regulator-always-on; +- vin-supply = <®_vsys>; +- }; +- +- /* system wide 4.2V power rail from charger */ +- reg_vsys: regulator-vsys { +- compatible = "regulator-fixed"; +- regulator-name = "vsys"; +- regulator-always-on; +- regulator-boot-on; +- }; +- +- /* used by mmc2 */ +- sdio_fixed_1v8: regulator-3 { +- compatible = "regulator-fixed"; +- regulator-name = "vio18_conn"; +- regulator-min-microvolt = <1800000>; +- regulator-max-microvolt = <1800000>; +- enable-active-high; +- regulator-always-on; +- }; +- +- /* used by mmc2 */ +- sdio_fixed_3v3: regulator-4 { +- compatible = "regulator-fixed"; +- regulator-name = "wifi_3v3"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- gpio = <&pio 74 GPIO_ACTIVE_HIGH>; +- enable-active-high; +- regulator-always-on; +- vin-supply = <®_vsys>; +- }; +- +- touch0_fixed_3v3: regulator-5 { +- compatible = "regulator-fixed"; +- regulator-name = "vio33_tp1"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- gpio = <&pio 119 GPIO_ACTIVE_HIGH>; +- enable-active-high; +- vin-supply = <®_vsys>; +- }; +- +- usb_hub_fixed_3v3: regulator-6 { +- compatible = "regulator-fixed"; +- regulator-name = "vhub_3v3"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- gpio = <&pio 112 GPIO_ACTIVE_HIGH>; /* HUB_3V3_EN */ +- startup-delay-us = <10000>; +- enable-active-high; +- vin-supply = <®_vsys>; +- }; +- +- usb_p0_vbus: regulator-7 { +- compatible = "regulator-fixed"; +- regulator-name = "vbus_p0"; +- regulator-min-microvolt = <5000000>; +- regulator-max-microvolt = <5000000>; +- gpio = <&pio 84 GPIO_ACTIVE_HIGH>; +- enable-active-high; +- vin-supply = <®_vsys>; +- }; +- +- usb_p1_vbus: regulator-8 { +- compatible = "regulator-fixed"; +- regulator-name = "vbus_p1"; +- regulator-min-microvolt = <5000000>; +- regulator-max-microvolt = <5000000>; +- gpio = <&pio 87 GPIO_ACTIVE_HIGH>; +- enable-active-high; +- vin-supply = <®_vsys>; +- }; +- +- /* used by ssusb2 */ +- usb_p2_vbus: regulator-9 { +- compatible = "regulator-fixed"; +- regulator-name = "wifi_3v3"; +- regulator-min-microvolt = <5000000>; +- regulator-max-microvolt = <5000000>; +- enable-active-high; +- }; +-}; +- +-&adsp { +- memory-region = <&adsp_dma_mem>, <&adsp_mem>; +- status = "okay"; +-}; +- +-&afe { +- memory-region = <&afe_dma_mem>; +- status = "okay"; +-}; +- +-&gpu { +- mali-supply = <&mt6359_vproc2_buck_reg>; +- status = "okay"; +-}; +- +-&i2c0 { +- pinctrl-names = "default"; +- pinctrl-0 = <&i2c0_pins>; +- clock-frequency = <400000>; +- status = "okay"; +- +- touchscreen@5d { +- compatible = "goodix,gt9271"; +- reg = <0x5d>; +- interrupt-parent = <&pio>; +- interrupts-extended = <&pio 6 IRQ_TYPE_EDGE_RISING>; +- irq-gpios = <&pio 6 GPIO_ACTIVE_HIGH>; +- reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; +- AVDD28-supply = <&touch0_fixed_3v3>; +- VDDIO-supply = <&mt6359_vio18_ldo_reg>; +- pinctrl-names = "default"; +- pinctrl-0 = <&touch_pins>; +- }; +-}; +- +-&i2c1 { +- pinctrl-names = "default"; +- pinctrl-0 = <&i2c1_pins>; +- clock-frequency = <400000>; +- status = "okay"; +-}; +- +-&i2c2 { +- pinctrl-names = "default"; +- pinctrl-0 = <&i2c2_pins>; +- clock-frequency = <400000>; +- status = "okay"; +-}; +- +-&i2c3 { +- pinctrl-names = "default"; +- pinctrl-0 = <&i2c3_pins>; +- clock-frequency = <400000>; +- status = "okay"; +-}; +- +-&i2c4 { +- pinctrl-names = "default"; +- pinctrl-0 = <&i2c4_pins>; +- clock-frequency = <1000000>; +- status = "okay"; +-}; +- +-&i2c5 { +- pinctrl-names = "default"; +- pinctrl-0 = <&i2c5_pins>; +- clock-frequency = <400000>; +- status = "okay"; +-}; +- +-&i2c6 { +- pinctrl-names = "default"; +- pinctrl-0 = <&i2c6_pins>; +- clock-frequency = <400000>; +- status = "okay"; +-}; +- +-&mfg0 { +- domain-supply = <&mt6359_vproc2_buck_reg>; +-}; +- +-&mfg1 { +- domain-supply = <&mt6359_vsram_others_ldo_reg>; +-}; +- +-&mmc0 { +- status = "okay"; +- pinctrl-names = "default", "state_uhs"; +- pinctrl-0 = <&mmc0_default_pins>; +- pinctrl-1 = <&mmc0_uhs_pins>; +- bus-width = <8>; +- max-frequency = <200000000>; +- cap-mmc-highspeed; +- mmc-hs200-1_8v; +- mmc-hs400-1_8v; +- supports-cqe; +- cap-mmc-hw-reset; +- no-sdio; +- no-sd; +- hs400-ds-delay = <0x1481b>; +- vmmc-supply = <&mt6359_vemc_1_ldo_reg>; +- vqmmc-supply = <&mt6359_vufs_ldo_reg>; +- non-removable; +-}; +- +-&mmc1 { +- status = "okay"; +- pinctrl-names = "default", "state_uhs"; +- pinctrl-0 = <&mmc1_default_pins>; +- pinctrl-1 = <&mmc1_uhs_pins>; +- bus-width = <4>; +- max-frequency = <200000000>; +- cap-sd-highspeed; +- sd-uhs-sdr50; +- sd-uhs-sdr104; +- no-mmc; +- no-sdio; +- cd-gpios = <&pio 2 GPIO_ACTIVE_LOW>; +- vmmc-supply = <&mt6359_vpa_buck_reg>; +- vqmmc-supply = <&mt6359_vsim1_ldo_reg>; +-}; +- +-&mt6359_vbbck_ldo_reg { +- regulator-always-on; +-}; +- +-&mt6359_vcn18_ldo_reg { +- regulator-name = "vcn18_pmu"; +- regulator-always-on; +-}; +- +-&mt6359_vcn33_2_bt_ldo_reg { +- regulator-name = "vcn33_2_pmu"; +- regulator-always-on; +-}; +- +-&mt6359_vcore_buck_reg { +- regulator-name = "dvdd_proc_l"; +- regulator-always-on; +-}; +- +-&mt6359_vgpu11_buck_reg { +- regulator-name = "dvdd_core"; +- regulator-always-on; +-}; +- +-&mt6359_vpa_buck_reg { +- regulator-name = "vpa_pmu"; +- regulator-max-microvolt = <3100000>; +-}; +- +-&mt6359_vproc2_buck_reg { +- /* The name "vgpu" is required by mtk-regulator-coupler */ +- regulator-name = "vgpu"; +- regulator-min-microvolt = <550000>; +- regulator-max-microvolt = <800000>; +- regulator-coupled-with = <&mt6359_vsram_others_ldo_reg>; +- regulator-coupled-max-spread = <6250>; +-}; +- +-&mt6359_vpu_buck_reg { +- regulator-name = "dvdd_adsp"; +- regulator-always-on; +-}; +- +-&mt6359_vrf12_ldo_reg { +- regulator-name = "va12_abb2_pmu"; +- regulator-always-on; +-}; +- +-&mt6359_vsim1_ldo_reg { +- regulator-name = "vsim1_pmu"; +- regulator-enable-ramp-delay = <480>; +-}; +- +-&mt6359_vsram_others_ldo_reg { +- /* The name "vsram_gpu" is required by mtk-regulator-coupler */ +- regulator-name = "vsram_gpu"; +- regulator-min-microvolt = <750000>; +- regulator-max-microvolt = <800000>; +- regulator-coupled-with = <&mt6359_vproc2_buck_reg>; +- regulator-coupled-max-spread = <6250>; +-}; +- +-&mt6359_vufs_ldo_reg { +- regulator-name = "vufs18_pmu"; +- regulator-always-on; +-}; +- +-&mt6359codec { +- mediatek,mic-type-0 = <1>; /* ACC */ +- mediatek,mic-type-1 = <3>; /* DCC */ +-}; +- +-&pcie { +- pinctrl-names = "default"; +- pinctrl-0 = <&pcie_pins_default>; +- status = "okay"; +-}; +- +-&pciephy { +- status = "okay"; +-}; +- +-&pio { +- audio_default_pins: audio-default-pins { +- pins-cmd-dat { +- pinmux = , +- , +- , +- , +- , +- , +- , +- , +- , +- , +- , +- , +- , +- , +- , +- , +- , +- , +- , +- , +- , +- ; +- }; +- }; +- +- dptx_pins: dptx-pins { +- pins-cmd-dat { +- pinmux = ; +- bias-pull-up; +- }; +- }; +- +- edp_panel_3v3_en_pins: edp-panel-3v3-en-pins { +- pins1 { +- pinmux = ; +- output-high; +- }; +- }; +- +- eth_default_pins: eth-default-pins { +- pins-cc { +- pinmux = , +- , +- , +- ; +- drive-strength = <8>; +- }; +- +- pins-mdio { +- pinmux = , +- ; +- drive-strength = <8>; +- input-enable; +- }; +- +- pins-power { +- pinmux = , +- ; +- output-high; +- }; +- +- pins-rxd { +- pinmux = , +- , +- , +- ; +- drive-strength = <8>; +- }; +- +- pins-txd { +- pinmux = , +- , +- , +- ; +- drive-strength = <8>; +- }; +- }; +- +- eth_sleep_pins: eth-sleep-pins { +- pins-cc { +- pinmux = , +- , +- , +- ; +- }; +- +- pins-mdio { +- pinmux = , +- ; +- input-disable; +- bias-disable; +- }; +- +- pins-rxd { +- pinmux = , +- , +- , +- ; +- }; +- +- pins-txd { +- pinmux = , +- , +- , +- ; +- }; +- }; +- +- i2c0_pins: i2c0-pins { +- pins { +- pinmux = , +- ; +- bias-pull-up = ; +- drive-strength-microamp = <1000>; +- }; +- }; +- +- i2c1_pins: i2c1-pins { +- pins { +- pinmux = , +- ; +- bias-pull-up = ; +- drive-strength-microamp = <1000>; +- }; +- }; +- +- i2c2_pins: i2c2-pins { +- pins { +- pinmux = , +- ; +- bias-pull-up = ; +- drive-strength-microamp = <1000>; +- }; +- }; +- +- i2c3_pins: i2c3-pins { +- pins { +- pinmux = , +- ; +- bias-pull-up = ; +- drive-strength-microamp = <1000>; +- }; +- }; +- +- i2c4_pins: i2c4-pins { +- pins { +- pinmux = , +- ; +- bias-pull-up = ; +- drive-strength-microamp = <1000>; +- }; +- }; +- +- i2c5_pins: i2c5-pins { +- pins { +- pinmux = , +- ; +- bias-pull-up = ; +- drive-strength-microamp = <1000>; +- }; +- }; +- +- i2c6_pins: i2c6-pins { +- pins { +- pinmux = , +- ; +- bias-pull-up = ; +- drive-strength-microamp = <1000>; +- }; +- }; +- +- gpio_key_pins: gpio-key-pins { +- pins { +- pinmux = , +- , +- ; +- }; +- }; +- +- mmc0_default_pins: mmc0-default-pins { +- pins-clk { +- pinmux = ; +- drive-strength = <6>; +- bias-pull-down = ; +- }; +- +- pins-cmd-dat { +- pinmux = , +- , +- , +- , +- , +- , +- , +- , +- ; +- input-enable; +- drive-strength = <6>; +- bias-pull-up = ; +- }; +- +- pins-rst { +- pinmux = ; +- drive-strength = <6>; +- bias-pull-up = ; +- }; +- }; +- +- mmc0_uhs_pins: mmc0-uhs-pins { +- pins-clk { +- pinmux = ; +- drive-strength = <8>; +- bias-pull-down = ; +- }; +- +- pins-cmd-dat { +- pinmux = , +- , +- , +- , +- , +- , +- , +- , +- ; +- input-enable; +- drive-strength = <8>; +- bias-pull-up = ; +- }; +- +- pins-ds { +- pinmux = ; +- drive-strength = <8>; +- bias-pull-down = ; +- }; +- +- pins-rst { +- pinmux = ; +- drive-strength = <8>; +- bias-pull-up = ; +- }; +- }; +- +- mmc1_default_pins: mmc1-default-pins { +- pins-clk { +- pinmux = ; +- drive-strength = <6>; +- bias-pull-down = ; +- }; +- +- pins-cmd-dat { +- pinmux = , +- , +- , +- , +- ; +- input-enable; +- drive-strength = <6>; +- bias-pull-up = ; +- }; +- +- pins-insert { +- pinmux = ; +- bias-pull-up; +- }; +- }; +- +- mmc1_uhs_pins: mmc1-uhs-pins { +- pins-clk { +- pinmux = ; +- drive-strength = <6>; +- bias-pull-down = ; +- }; +- +- pins-cmd-dat { +- pinmux = , +- , +- , +- , +- ; +- input-enable; +- drive-strength = <6>; +- bias-pull-up = ; +- }; +- }; +- +- mmc2_default_pins: mmc2-default-pins { +- pins-clk { +- pinmux = ; +- drive-strength = <4>; +- bias-pull-down = ; +- }; +- +- pins-cmd-dat { +- pinmux = , +- , +- , +- , +- ; +- input-enable; +- drive-strength = <6>; +- bias-pull-up = ; +- }; +- +- pins-pcm { +- pinmux = ; +- }; +- }; +- +- mmc2_uhs_pins: mmc2-uhs-pins { +- pins-clk { +- pinmux = ; +- drive-strength = <4>; +- bias-pull-down = ; +- }; +- +- pins-cmd-dat { +- pinmux = , +- , +- , +- , +- ; +- input-enable; +- drive-strength = <6>; +- bias-pull-up = ; +- }; +- }; +- +- mmc2_eint_pins: mmc2-eint-pins { +- pins-dat1 { +- pinmux = ; +- input-enable; +- bias-pull-up = ; +- }; +- }; +- +- mmc2_dat1_pins: mmc2-dat1-pins { +- pins-dat1 { +- pinmux = ; +- input-enable; +- drive-strength = <6>; +- bias-pull-up = ; +- }; +- }; +- +- panel_default_pins: panel-default-pins { +- pins-dcdc { +- pinmux = ; +- output-low; +- }; +- +- pins-en { +- pinmux = ; +- output-low; +- }; +- +- pins-rst { +- pinmux = ; +- output-high; +- }; +- }; +- +- pcie_pins_default: pcie-default { +- mux { +- pinmux = , +- , +- ; +- bias-pull-up; +- }; +- }; +- +- rt1715_int_pins: rt1715-int-pins { +- pins_cmd0_dat { +- pinmux = ; +- bias-pull-up; +- input-enable; +- }; +- }; +- +- spi0_pins: spi0-pins { +- pins-spi { +- pinmux = , +- , +- , +- ; +- bias-disable; +- }; +- }; +- +- spi1_pins: spi1-pins { +- pins-spi { +- pinmux = , +- , +- , +- ; +- bias-disable; +- }; +- }; +- +- spi2_pins: spi2-pins { +- pins-spi { +- pinmux = , +- , +- , +- ; +- bias-disable; +- }; +- }; +- +- touch_pins: touch-pins { +- pins-irq { +- pinmux = ; +- input-enable; +- bias-disable; +- }; +- +- pins-reset { +- pinmux = ; +- output-high; +- }; +- }; +- +- uart0_pins: uart0-pins { +- pins { +- pinmux = , +- ; +- bias-pull-up; +- }; +- }; +- +- uart1_pins: uart1-pins { +- pins { +- pinmux = , +- ; +- bias-pull-up; +- }; +- }; +- +- uart2_pins: uart2-pins { +- pins { +- pinmux = , +- ; +- bias-pull-up; +- }; +- }; +- +- usb_default_pins: usb-default-pins { +- pins-iddig { +- pinmux = ; +- input-enable; +- bias-pull-up; +- }; +- +- pins-valid { +- pinmux = ; +- input-enable; +- }; +- +- pins-vbus { +- pinmux = ; +- output-high; +- }; +- +- }; +- +- usb1_default_pins: usb1-default-pins { +- pins-valid { +- pinmux = ; +- input-enable; +- }; +- +- pins-usb-hub-3v3-en { +- pinmux = ; +- output-high; +- }; +- }; +- +- wifi_pwrseq_pins: wifi-pwrseq-pins { +- pins-wifi-enable { +- pinmux = ; +- output-low; +- }; +- }; +-}; +- +-ð { +- phy-mode ="rgmii-id"; +- phy-handle = <ðernet_phy0>; +- pinctrl-names = "default", "sleep"; +- pinctrl-0 = <ð_default_pins>; +- pinctrl-1 = <ð_sleep_pins>; +- mediatek,mac-wol; +- snps,reset-gpio = <&pio 147 GPIO_ACTIVE_HIGH>; +- snps,reset-delays-us = <0 10000 10000>; +- status = "okay"; +-}; +- +-ð_mdio { +- ethernet_phy0: ethernet-phy@1 { +- compatible = "ethernet-phy-id001c.c916"; +- reg = <0x1>; +- }; +-}; +- +-&pmic { +- interrupt-parent = <&pio>; +- interrupts = <222 IRQ_TYPE_LEVEL_HIGH>; +- +- mt6359keys: keys { +- compatible = "mediatek,mt6359-keys"; +- mediatek,long-press-mode = <1>; +- power-off-time-sec = <0>; +- +- power-key { +- linux,keycodes = ; +- wakeup-source; +- }; +- }; +-}; +- +-&scp { +- memory-region = <&scp_mem>; +- status = "okay"; +-}; +- +-&sound { +- compatible = "mediatek,mt8390-mt6359-evk", "mediatek,mt8188-mt6359-evb"; +- model = "mt8390-evk"; +- pinctrl-names = "default"; +- pinctrl-0 = <&audio_default_pins>; +- audio-routing = +- "Headphone", "Headphone L", +- "Headphone", "Headphone R"; +- mediatek,adsp = <&adsp>; +- status = "okay"; +- +- dai-link-0 { +- link-name = "DL_SRC_BE"; +- +- codec { +- sound-dai = <&pmic 0>; +- }; +- }; +-}; +- +-&spi2 { +- pinctrl-0 = <&spi2_pins>; +- pinctrl-names = "default"; +- mediatek,pad-select = <0>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "okay"; + }; + +-&uart0 { +- pinctrl-0 = <&uart0_pins>; +- pinctrl-names = "default"; +- status = "okay"; +-}; +- +-&uart1 { +- pinctrl-0 = <&uart1_pins>; +- pinctrl-names = "default"; +- status = "okay"; +-}; +- +-&uart2 { +- pinctrl-0 = <&uart2_pins>; +- pinctrl-names = "default"; +- status = "okay"; +-}; +- +-&u3phy0 { +- status = "okay"; +-}; +- +-&u3phy1 { +- status = "okay"; +-}; +- +-&u3phy2 { +- status = "okay"; +-}; +- +-&xhci0 { +- status = "okay"; +- vusb33-supply = <&mt6359_vusb_ldo_reg>; +-}; +- +-&xhci1 { +- status = "okay"; +- vusb33-supply = <&mt6359_vusb_ldo_reg>; +- #address-cells = <1>; +- #size-cells = <0>; +- +- hub_2_0: hub@1 { +- compatible = "usb451,8025"; +- reg = <1>; +- peer-hub = <&hub_3_0>; +- reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>; +- vdd-supply = <&usb_hub_fixed_3v3>; +- }; +- +- hub_3_0: hub@2 { +- compatible = "usb451,8027"; +- reg = <2>; +- peer-hub = <&hub_2_0>; +- reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>; +- vdd-supply = <&usb_hub_fixed_3v3>; +- }; +-}; +- +-&xhci2 { +- status = "okay"; +- vusb33-supply = <&mt6359_vusb_ldo_reg>; +- vbus-supply = <&sdio_fixed_3v3>; /* wifi_3v3 */ +-}; +diff --git a/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi b/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi +new file mode 100644 +index 0000000000000..a37cf102a6e92 +--- /dev/null ++++ b/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi +@@ -0,0 +1,1046 @@ ++// SPDX-License-Identifier: (GPL-2.0 OR MIT) ++/* ++ * Copyright (C) 2023 MediaTek Inc. ++ * Author: Chris Chen ++ * Pablo Sun ++ * Macpaul Lin ++ * ++ * Copyright (C) 2025 Collabora Ltd. ++ * Louis-Alexis Eyraud ++ * AngeloGioacchino Del Regno ++ */ ++ ++#include "mt6359.dtsi" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/ { ++ aliases { ++ ethernet0 = ð ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2c2 = &i2c2; ++ i2c3 = &i2c3; ++ i2c4 = &i2c4; ++ i2c5 = &i2c5; ++ i2c6 = &i2c6; ++ mmc0 = &mmc0; ++ mmc1 = &mmc1; ++ serial0 = &uart0; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:921600n8"; ++ }; ++ ++ firmware { ++ optee { ++ compatible = "linaro,optee-tz"; ++ method = "smc"; ++ }; ++ }; ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* ++ * 12 MiB reserved for OP-TEE (BL32) ++ * +-----------------------+ 0x43e0_0000 ++ * | SHMEM 2MiB | ++ * +-----------------------+ 0x43c0_0000 ++ * | | TA_RAM 8MiB | ++ * + TZDRAM +--------------+ 0x4340_0000 ++ * | | TEE_RAM 2MiB | ++ * +-----------------------+ 0x4320_0000 ++ */ ++ optee_reserved: optee@43200000 { ++ no-map; ++ reg = <0 0x43200000 0 0x00c00000>; ++ }; ++ ++ scp_mem: memory@50000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0 0x50000000 0 0x2900000>; ++ no-map; ++ }; ++ ++ /* 2 MiB reserved for ARM Trusted Firmware (BL31) */ ++ bl31_secmon_reserved: memory@54600000 { ++ no-map; ++ reg = <0 0x54600000 0x0 0x200000>; ++ }; ++ ++ apu_mem: memory@55000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0 0x55000000 0 0x1400000>; /* 20 MB */ ++ }; ++ ++ vpu_mem: memory@57000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0 0x57000000 0 0x1400000>; /* 20 MB */ ++ }; ++ ++ adsp_mem: memory@60000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0 0x60000000 0 0xf00000>; ++ no-map; ++ }; ++ ++ afe_dma_mem: memory@60f00000 { ++ compatible = "shared-dma-pool"; ++ reg = <0 0x60f00000 0 0x100000>; ++ no-map; ++ }; ++ ++ adsp_dma_mem: memory@61000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0 0x61000000 0 0x100000>; ++ no-map; ++ }; ++ }; ++ ++ common_fixed_5v: regulator-0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vdd_5v"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ gpio = <&pio 10 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ regulator-always-on; ++ vin-supply = <®_vsys>; ++ }; ++ ++ edp_panel_fixed_3v3: regulator-1 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vedp_3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ enable-active-high; ++ gpio = <&pio 15 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&edp_panel_3v3_en_pins>; ++ vin-supply = <®_vsys>; ++ }; ++ ++ gpio_fixed_3v3: regulator-2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "ext_3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&pio 9 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ regulator-always-on; ++ vin-supply = <®_vsys>; ++ }; ++ ++ /* system wide 4.2V power rail from charger */ ++ reg_vsys: regulator-vsys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vsys"; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ /* used by mmc2 */ ++ sdio_fixed_1v8: regulator-3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vio18_conn"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ /* used by mmc2 */ ++ sdio_fixed_3v3: regulator-4 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wifi_3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&pio 74 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ regulator-always-on; ++ vin-supply = <®_vsys>; ++ }; ++ ++ touch0_fixed_3v3: regulator-5 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vio33_tp1"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&pio 119 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ vin-supply = <®_vsys>; ++ }; ++ ++ usb_hub_fixed_3v3: regulator-6 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vhub_3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&pio 112 GPIO_ACTIVE_HIGH>; /* HUB_3V3_EN */ ++ startup-delay-us = <10000>; ++ enable-active-high; ++ vin-supply = <®_vsys>; ++ }; ++ ++ usb_p0_vbus: regulator-7 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vbus_p0"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ gpio = <&pio 84 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ vin-supply = <®_vsys>; ++ }; ++ ++ usb_p1_vbus: regulator-8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vbus_p1"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ gpio = <&pio 87 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ vin-supply = <®_vsys>; ++ }; ++ ++ /* used by ssusb2 */ ++ usb_p2_vbus: regulator-9 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wifi_3v3"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ enable-active-high; ++ }; ++}; ++ ++&adsp { ++ memory-region = <&adsp_dma_mem>, <&adsp_mem>; ++ status = "okay"; ++}; ++ ++&afe { ++ memory-region = <&afe_dma_mem>; ++ status = "okay"; ++}; ++ ++&gpu { ++ mali-supply = <&mt6359_vproc2_buck_reg>; ++ status = "okay"; ++}; ++ ++&i2c0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins>; ++ clock-frequency = <400000>; ++ status = "okay"; ++ ++ touchscreen@5d { ++ compatible = "goodix,gt9271"; ++ reg = <0x5d>; ++ interrupt-parent = <&pio>; ++ interrupts-extended = <&pio 6 IRQ_TYPE_EDGE_RISING>; ++ irq-gpios = <&pio 6 GPIO_ACTIVE_HIGH>; ++ reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; ++ AVDD28-supply = <&touch0_fixed_3v3>; ++ VDDIO-supply = <&mt6359_vio18_ldo_reg>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&touch_pins>; ++ }; ++}; ++ ++&i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; ++ clock-frequency = <400000>; ++ status = "okay"; ++}; ++ ++&i2c2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c2_pins>; ++ clock-frequency = <400000>; ++ status = "okay"; ++}; ++ ++&i2c3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c3_pins>; ++ clock-frequency = <400000>; ++ status = "okay"; ++}; ++ ++&i2c4 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c4_pins>; ++ clock-frequency = <1000000>; ++ status = "okay"; ++}; ++ ++&i2c5 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c5_pins>; ++ clock-frequency = <400000>; ++ status = "okay"; ++}; ++ ++&i2c6 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c6_pins>; ++ clock-frequency = <400000>; ++ status = "okay"; ++}; ++ ++&mfg0 { ++ domain-supply = <&mt6359_vproc2_buck_reg>; ++}; ++ ++&mfg1 { ++ domain-supply = <&mt6359_vsram_others_ldo_reg>; ++}; ++ ++&mmc0 { ++ status = "okay"; ++ pinctrl-names = "default", "state_uhs"; ++ pinctrl-0 = <&mmc0_default_pins>; ++ pinctrl-1 = <&mmc0_uhs_pins>; ++ bus-width = <8>; ++ max-frequency = <200000000>; ++ cap-mmc-highspeed; ++ mmc-hs200-1_8v; ++ mmc-hs400-1_8v; ++ supports-cqe; ++ cap-mmc-hw-reset; ++ no-sdio; ++ no-sd; ++ hs400-ds-delay = <0x1481b>; ++ vmmc-supply = <&mt6359_vemc_1_ldo_reg>; ++ vqmmc-supply = <&mt6359_vufs_ldo_reg>; ++ non-removable; ++}; ++ ++&mmc1 { ++ status = "okay"; ++ pinctrl-names = "default", "state_uhs"; ++ pinctrl-0 = <&mmc1_default_pins>; ++ pinctrl-1 = <&mmc1_uhs_pins>; ++ bus-width = <4>; ++ max-frequency = <200000000>; ++ cap-sd-highspeed; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ no-mmc; ++ no-sdio; ++ cd-gpios = <&pio 2 GPIO_ACTIVE_LOW>; ++ vmmc-supply = <&mt6359_vpa_buck_reg>; ++ vqmmc-supply = <&mt6359_vsim1_ldo_reg>; ++}; ++ ++&mt6359_vbbck_ldo_reg { ++ regulator-always-on; ++}; ++ ++&mt6359_vcn18_ldo_reg { ++ regulator-name = "vcn18_pmu"; ++ regulator-always-on; ++}; ++ ++&mt6359_vcn33_2_bt_ldo_reg { ++ regulator-name = "vcn33_2_pmu"; ++ regulator-always-on; ++}; ++ ++&mt6359_vcore_buck_reg { ++ regulator-name = "dvdd_proc_l"; ++ regulator-always-on; ++}; ++ ++&mt6359_vgpu11_buck_reg { ++ regulator-name = "dvdd_core"; ++ regulator-always-on; ++}; ++ ++&mt6359_vpa_buck_reg { ++ regulator-name = "vpa_pmu"; ++ regulator-max-microvolt = <3100000>; ++}; ++ ++&mt6359_vproc2_buck_reg { ++ /* The name "vgpu" is required by mtk-regulator-coupler */ ++ regulator-name = "vgpu"; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <800000>; ++ regulator-coupled-with = <&mt6359_vsram_others_ldo_reg>; ++ regulator-coupled-max-spread = <6250>; ++}; ++ ++&mt6359_vpu_buck_reg { ++ regulator-name = "dvdd_adsp"; ++ regulator-always-on; ++}; ++ ++&mt6359_vrf12_ldo_reg { ++ regulator-name = "va12_abb2_pmu"; ++ regulator-always-on; ++}; ++ ++&mt6359_vsim1_ldo_reg { ++ regulator-name = "vsim1_pmu"; ++ regulator-enable-ramp-delay = <480>; ++}; ++ ++&mt6359_vsram_others_ldo_reg { ++ /* The name "vsram_gpu" is required by mtk-regulator-coupler */ ++ regulator-name = "vsram_gpu"; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <800000>; ++ regulator-coupled-with = <&mt6359_vproc2_buck_reg>; ++ regulator-coupled-max-spread = <6250>; ++}; ++ ++&mt6359_vufs_ldo_reg { ++ regulator-name = "vufs18_pmu"; ++ regulator-always-on; ++}; ++ ++&mt6359codec { ++ mediatek,mic-type-0 = <1>; /* ACC */ ++ mediatek,mic-type-1 = <3>; /* DCC */ ++}; ++ ++&pcie { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie_pins_default>; ++ status = "okay"; ++}; ++ ++&pciephy { ++ status = "okay"; ++}; ++ ++&pio { ++ audio_default_pins: audio-default-pins { ++ pins-cmd-dat { ++ pinmux = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ }; ++ }; ++ ++ dptx_pins: dptx-pins { ++ pins-cmd-dat { ++ pinmux = ; ++ bias-pull-up; ++ }; ++ }; ++ ++ edp_panel_3v3_en_pins: edp-panel-3v3-en-pins { ++ pins1 { ++ pinmux = ; ++ output-high; ++ }; ++ }; ++ ++ eth_default_pins: eth-default-pins { ++ pins-cc { ++ pinmux = , ++ , ++ , ++ ; ++ drive-strength = <8>; ++ }; ++ ++ pins-mdio { ++ pinmux = , ++ ; ++ drive-strength = <8>; ++ input-enable; ++ }; ++ ++ pins-power { ++ pinmux = , ++ ; ++ output-high; ++ }; ++ ++ pins-rxd { ++ pinmux = , ++ , ++ , ++ ; ++ drive-strength = <8>; ++ }; ++ ++ pins-txd { ++ pinmux = , ++ , ++ , ++ ; ++ drive-strength = <8>; ++ }; ++ }; ++ ++ eth_sleep_pins: eth-sleep-pins { ++ pins-cc { ++ pinmux = , ++ , ++ , ++ ; ++ }; ++ ++ pins-mdio { ++ pinmux = , ++ ; ++ input-disable; ++ bias-disable; ++ }; ++ ++ pins-rxd { ++ pinmux = , ++ , ++ , ++ ; ++ }; ++ ++ pins-txd { ++ pinmux = , ++ , ++ , ++ ; ++ }; ++ }; ++ ++ i2c0_pins: i2c0-pins { ++ pins { ++ pinmux = , ++ ; ++ bias-pull-up = ; ++ drive-strength-microamp = <1000>; ++ }; ++ }; ++ ++ i2c1_pins: i2c1-pins { ++ pins { ++ pinmux = , ++ ; ++ bias-pull-up = ; ++ drive-strength-microamp = <1000>; ++ }; ++ }; ++ ++ i2c2_pins: i2c2-pins { ++ pins { ++ pinmux = , ++ ; ++ bias-pull-up = ; ++ drive-strength-microamp = <1000>; ++ }; ++ }; ++ ++ i2c3_pins: i2c3-pins { ++ pins { ++ pinmux = , ++ ; ++ bias-pull-up = ; ++ drive-strength-microamp = <1000>; ++ }; ++ }; ++ ++ i2c4_pins: i2c4-pins { ++ pins { ++ pinmux = , ++ ; ++ bias-pull-up = ; ++ drive-strength-microamp = <1000>; ++ }; ++ }; ++ ++ i2c5_pins: i2c5-pins { ++ pins { ++ pinmux = , ++ ; ++ bias-pull-up = ; ++ drive-strength-microamp = <1000>; ++ }; ++ }; ++ ++ i2c6_pins: i2c6-pins { ++ pins { ++ pinmux = , ++ ; ++ bias-pull-up = ; ++ drive-strength-microamp = <1000>; ++ }; ++ }; ++ ++ gpio_key_pins: gpio-key-pins { ++ pins { ++ pinmux = , ++ , ++ ; ++ }; ++ }; ++ ++ mmc0_default_pins: mmc0-default-pins { ++ pins-clk { ++ pinmux = ; ++ drive-strength = <6>; ++ bias-pull-down = ; ++ }; ++ ++ pins-cmd-dat { ++ pinmux = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ input-enable; ++ drive-strength = <6>; ++ bias-pull-up = ; ++ }; ++ ++ pins-rst { ++ pinmux = ; ++ drive-strength = <6>; ++ bias-pull-up = ; ++ }; ++ }; ++ ++ mmc0_uhs_pins: mmc0-uhs-pins { ++ pins-clk { ++ pinmux = ; ++ drive-strength = <8>; ++ bias-pull-down = ; ++ }; ++ ++ pins-cmd-dat { ++ pinmux = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ input-enable; ++ drive-strength = <8>; ++ bias-pull-up = ; ++ }; ++ ++ pins-ds { ++ pinmux = ; ++ drive-strength = <8>; ++ bias-pull-down = ; ++ }; ++ ++ pins-rst { ++ pinmux = ; ++ drive-strength = <8>; ++ bias-pull-up = ; ++ }; ++ }; ++ ++ mmc1_default_pins: mmc1-default-pins { ++ pins-clk { ++ pinmux = ; ++ drive-strength = <6>; ++ bias-pull-down = ; ++ }; ++ ++ pins-cmd-dat { ++ pinmux = , ++ , ++ , ++ , ++ ; ++ input-enable; ++ drive-strength = <6>; ++ bias-pull-up = ; ++ }; ++ ++ pins-insert { ++ pinmux = ; ++ bias-pull-up; ++ }; ++ }; ++ ++ mmc1_uhs_pins: mmc1-uhs-pins { ++ pins-clk { ++ pinmux = ; ++ drive-strength = <6>; ++ bias-pull-down = ; ++ }; ++ ++ pins-cmd-dat { ++ pinmux = , ++ , ++ , ++ , ++ ; ++ input-enable; ++ drive-strength = <6>; ++ bias-pull-up = ; ++ }; ++ }; ++ ++ mmc2_default_pins: mmc2-default-pins { ++ pins-clk { ++ pinmux = ; ++ drive-strength = <4>; ++ bias-pull-down = ; ++ }; ++ ++ pins-cmd-dat { ++ pinmux = , ++ , ++ , ++ , ++ ; ++ input-enable; ++ drive-strength = <6>; ++ bias-pull-up = ; ++ }; ++ ++ pins-pcm { ++ pinmux = ; ++ }; ++ }; ++ ++ mmc2_uhs_pins: mmc2-uhs-pins { ++ pins-clk { ++ pinmux = ; ++ drive-strength = <4>; ++ bias-pull-down = ; ++ }; ++ ++ pins-cmd-dat { ++ pinmux = , ++ , ++ , ++ , ++ ; ++ input-enable; ++ drive-strength = <6>; ++ bias-pull-up = ; ++ }; ++ }; ++ ++ mmc2_eint_pins: mmc2-eint-pins { ++ pins-dat1 { ++ pinmux = ; ++ input-enable; ++ bias-pull-up = ; ++ }; ++ }; ++ ++ mmc2_dat1_pins: mmc2-dat1-pins { ++ pins-dat1 { ++ pinmux = ; ++ input-enable; ++ drive-strength = <6>; ++ bias-pull-up = ; ++ }; ++ }; ++ ++ panel_default_pins: panel-default-pins { ++ pins-dcdc { ++ pinmux = ; ++ output-low; ++ }; ++ ++ pins-en { ++ pinmux = ; ++ output-low; ++ }; ++ ++ pins-rst { ++ pinmux = ; ++ output-high; ++ }; ++ }; ++ ++ pcie_pins_default: pcie-default { ++ mux { ++ pinmux = , ++ , ++ ; ++ bias-pull-up; ++ }; ++ }; ++ ++ rt1715_int_pins: rt1715-int-pins { ++ pins_cmd0_dat { ++ pinmux = ; ++ bias-pull-up; ++ input-enable; ++ }; ++ }; ++ ++ spi0_pins: spi0-pins { ++ pins-spi { ++ pinmux = , ++ , ++ , ++ ; ++ bias-disable; ++ }; ++ }; ++ ++ spi1_pins: spi1-pins { ++ pins-spi { ++ pinmux = , ++ , ++ , ++ ; ++ bias-disable; ++ }; ++ }; ++ ++ spi2_pins: spi2-pins { ++ pins-spi { ++ pinmux = , ++ , ++ , ++ ; ++ bias-disable; ++ }; ++ }; ++ ++ touch_pins: touch-pins { ++ pins-irq { ++ pinmux = ; ++ input-enable; ++ bias-disable; ++ }; ++ ++ pins-reset { ++ pinmux = ; ++ output-high; ++ }; ++ }; ++ ++ uart0_pins: uart0-pins { ++ pins { ++ pinmux = , ++ ; ++ bias-pull-up; ++ }; ++ }; ++ ++ uart1_pins: uart1-pins { ++ pins { ++ pinmux = , ++ ; ++ bias-pull-up; ++ }; ++ }; ++ ++ uart2_pins: uart2-pins { ++ pins { ++ pinmux = , ++ ; ++ bias-pull-up; ++ }; ++ }; ++ ++ usb_default_pins: usb-default-pins { ++ pins-iddig { ++ pinmux = ; ++ input-enable; ++ bias-pull-up; ++ }; ++ ++ pins-valid { ++ pinmux = ; ++ input-enable; ++ }; ++ ++ pins-vbus { ++ pinmux = ; ++ output-high; ++ }; ++ ++ }; ++ ++ usb1_default_pins: usb1-default-pins { ++ pins-valid { ++ pinmux = ; ++ input-enable; ++ }; ++ ++ pins-usb-hub-3v3-en { ++ pinmux = ; ++ output-high; ++ }; ++ }; ++ ++ wifi_pwrseq_pins: wifi-pwrseq-pins { ++ pins-wifi-enable { ++ pinmux = ; ++ output-low; ++ }; ++ }; ++}; ++ ++ð { ++ phy-mode ="rgmii-id"; ++ phy-handle = <ðernet_phy0>; ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <ð_default_pins>; ++ pinctrl-1 = <ð_sleep_pins>; ++ mediatek,mac-wol; ++ snps,reset-gpio = <&pio 147 GPIO_ACTIVE_HIGH>; ++ snps,reset-delays-us = <0 10000 10000>; ++ status = "okay"; ++}; ++ ++ð_mdio { ++ ethernet_phy0: ethernet-phy@1 { ++ compatible = "ethernet-phy-id001c.c916"; ++ reg = <0x1>; ++ }; ++}; ++ ++&pmic { ++ interrupt-parent = <&pio>; ++ interrupts = <222 IRQ_TYPE_LEVEL_HIGH>; ++ ++ mt6359keys: keys { ++ compatible = "mediatek,mt6359-keys"; ++ mediatek,long-press-mode = <1>; ++ power-off-time-sec = <0>; ++ ++ power-key { ++ linux,keycodes = ; ++ wakeup-source; ++ }; ++ }; ++}; ++ ++&scp { ++ memory-region = <&scp_mem>; ++ status = "okay"; ++}; ++ ++&sound { ++ compatible = "mediatek,mt8390-mt6359-evk", "mediatek,mt8188-mt6359-evb"; ++ model = "mt8390-evk"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&audio_default_pins>; ++ audio-routing = ++ "Headphone", "Headphone L", ++ "Headphone", "Headphone R"; ++ mediatek,adsp = <&adsp>; ++ status = "okay"; ++ ++ dai-link-0 { ++ link-name = "DL_SRC_BE"; ++ ++ codec { ++ sound-dai = <&pmic 0>; ++ }; ++ }; ++}; ++ ++&spi2 { ++ pinctrl-0 = <&spi2_pins>; ++ pinctrl-names = "default"; ++ mediatek,pad-select = <0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++}; ++ ++&uart0 { ++ pinctrl-0 = <&uart0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-0 = <&uart1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&uart2 { ++ pinctrl-0 = <&uart2_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&u3phy0 { ++ status = "okay"; ++}; ++ ++&u3phy1 { ++ status = "okay"; ++}; ++ ++&u3phy2 { ++ status = "okay"; ++}; ++ ++&xhci0 { ++ status = "okay"; ++ vusb33-supply = <&mt6359_vusb_ldo_reg>; ++}; ++ ++&xhci1 { ++ status = "okay"; ++ vusb33-supply = <&mt6359_vusb_ldo_reg>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hub_2_0: hub@1 { ++ compatible = "usb451,8025"; ++ reg = <1>; ++ peer-hub = <&hub_3_0>; ++ reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>; ++ vdd-supply = <&usb_hub_fixed_3v3>; ++ }; ++ ++ hub_3_0: hub@2 { ++ compatible = "usb451,8027"; ++ reg = <2>; ++ peer-hub = <&hub_2_0>; ++ reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>; ++ vdd-supply = <&usb_hub_fixed_3v3>; ++ }; ++}; ++ ++&xhci2 { ++ status = "okay"; ++ vusb33-supply = <&mt6359_vusb_ldo_reg>; ++ vbus-supply = <&sdio_fixed_3v3>; /* wifi_3v3 */ ++}; +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-mediatek-mt8390-genio-common-fix-duplicate.patch b/queue-6.14/arm64-dts-mediatek-mt8390-genio-common-fix-duplicate.patch new file mode 100644 index 0000000000..510a091fbd --- /dev/null +++ b/queue-6.14/arm64-dts-mediatek-mt8390-genio-common-fix-duplicate.patch @@ -0,0 +1,39 @@ +From 273b782e8415bcdf1bd410ccdb21fb21ec19faae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 09:49:52 +0100 +Subject: arm64: dts: mediatek: mt8390-genio-common: Fix duplicated regulator + name + +From: Louis-Alexis Eyraud + +[ Upstream commit 18aa138d125dd56838edbdb8c813e91e5e95d496 ] + +usb_p2_vbus regulator has the same regulator-name property value as +sdio_fixed_3v3, so change it to avoid this. + +Fixes: a4fd1943bf9b ("arm64: dts: mediatek: mt8390-genio-700-evk: update regulator names") +Signed-off-by: Louis-Alexis Eyraud +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20250221-fix-mtk8390-genio-common-dup-regulator-name-v1-1-92f7b9f7a414@collabora.com +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi b/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi +index a37cf102a6e92..e828864433a6f 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8390-genio-common.dtsi +@@ -213,7 +213,7 @@ + /* used by ssusb2 */ + usb_p2_vbus: regulator-9 { + compatible = "regulator-fixed"; +- regulator-name = "wifi_3v3"; ++ regulator-name = "vbus_p2"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-renesas-r8a774c0-re-add-voltages-to-opp-ta.patch b/queue-6.14/arm64-dts-renesas-r8a774c0-re-add-voltages-to-opp-ta.patch new file mode 100644 index 0000000000..a442af7682 --- /dev/null +++ b/queue-6.14/arm64-dts-renesas-r8a774c0-re-add-voltages-to-opp-ta.patch @@ -0,0 +1,61 @@ +From cd29b6175b6c4e82171a6c5a9cc23c6a8b9706da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Oct 2024 11:14:20 +0200 +Subject: arm64: dts: renesas: r8a774c0: Re-add voltages to OPP table + +From: Geert Uytterhoeven + +[ Upstream commit ea34dd0f029f4a30c055ddb6daaf7a6f3bee21ed ] + +When CONFIG_ENERGY_MODEL=y: + + cpu cpu0: EM: invalid perf. state: -22 + +When removing the (incorrect) voltages from the Operating Points +Parameters tables, it was assumed they were optional, and unused, when +none of the CPU nodes is tied to a regulator using the "cpu-supply" +property. This assumption turned out to be incorrect, causing the +reported error message. + +Fix this by re-adding the (correct) voltages. Note that because all +voltages are identical, all operating points are considered to have the +same efficiency, and the energy model always picks the one with the +highest clock rate. + +Reported-by: Renesas Test Team via Kuninori Morimoto +Fixes: 554edc3e9239bb81 ("arm64: dts: renesas: r8a774c0: Remove bogus voltages from OPP table") +Signed-off-by: Geert Uytterhoeven +Link: https://lore.kernel.org/2046da75f3db95b62f86c0482063c4d04c2b47d5.1728377971.git.geert+renesas@glider.be +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/renesas/r8a774c0.dtsi | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi +index 7655d5e3a0341..522e20924e94a 100644 +--- a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi +@@ -47,16 +47,20 @@ + cluster1_opp: opp-table-1 { + compatible = "operating-points-v2"; + opp-shared; ++ + opp-800000000 { + opp-hz = /bits/ 64 <800000000>; ++ opp-microvolt = <1030000>; + clock-latency-ns = <300000>; + }; + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000>; ++ opp-microvolt = <1030000>; + clock-latency-ns = <300000>; + }; + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; ++ opp-microvolt = <1030000>; + clock-latency-ns = <300000>; + opp-suspend; + }; +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-renesas-r8a77990-re-add-voltages-to-opp-ta.patch b/queue-6.14/arm64-dts-renesas-r8a77990-re-add-voltages-to-opp-ta.patch new file mode 100644 index 0000000000..301707c20e --- /dev/null +++ b/queue-6.14/arm64-dts-renesas-r8a77990-re-add-voltages-to-opp-ta.patch @@ -0,0 +1,61 @@ +From 6725d4bd494632ab2a62031a583c6c4da0608471 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Oct 2024 11:14:21 +0200 +Subject: arm64: dts: renesas: r8a77990: Re-add voltages to OPP table + +From: Geert Uytterhoeven + +[ Upstream commit c193f877770291f30d1e00bc6f2bb0757fe7a532 ] + +When CONFIG_ENERGY_MODEL=y: + + cpu cpu0: EM: invalid perf. state: -22 + +When removing the (incorrect) voltages from the Operating Points +Parameters tables, it was assumed they were optional, and unused, when +none of the CPU nodes is tied to a regulator using the "cpu-supply" +property. This assumption turned out to be incorrect, causing the +reported error message. + +Fix this by re-adding the (correct) voltages. Note that because all +voltages are identical, all operating points are considered to have the +same efficiency, and the energy model always picks the one with the +highest clock rate. + +Reported-by: Renesas Test Team via Kuninori Morimoto +Fixes: fb76b0fae3ca8803 ("arm64: dts: renesas: r8a77990: Remove bogus voltages from OPP table") +Signed-off-by: Geert Uytterhoeven +Link: https://lore.kernel.org/80890bc244670bc3e8d6fc89fb2c3cb23e7025f5.1728377971.git.geert+renesas@glider.be +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/renesas/r8a77990.dtsi | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi +index 233af3081e84a..50fbf7251665a 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi +@@ -47,16 +47,20 @@ + cluster1_opp: opp-table-1 { + compatible = "operating-points-v2"; + opp-shared; ++ + opp-800000000 { + opp-hz = /bits/ 64 <800000000>; ++ opp-microvolt = <1030000>; + clock-latency-ns = <300000>; + }; + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000>; ++ opp-microvolt = <1030000>; + clock-latency-ns = <300000>; + }; + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; ++ opp-microvolt = <1030000>; + clock-latency-ns = <300000>; + opp-suspend; + }; +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-rockchip-fix-pcie-reset-gpio-on-orange-pi-.patch b/queue-6.14/arm64-dts-rockchip-fix-pcie-reset-gpio-on-orange-pi-.patch new file mode 100644 index 0000000000..beae3b8e2e --- /dev/null +++ b/queue-6.14/arm64-dts-rockchip-fix-pcie-reset-gpio-on-orange-pi-.patch @@ -0,0 +1,38 @@ +From 73b59636f65a3f380ea79636140bba432bd1bc4c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 22:12:39 +0800 +Subject: arm64: dts: rockchip: Fix pcie reset gpio on Orange Pi 5 Max + +From: Jianfeng Liu + +[ Upstream commit e0945a08fc7f7ed26c8dae286a3d30a68ad37d50 ] + +According to the schematic, pcie reset gpio is GPIO3_D4, +not GPIO4_D4. + +Fixes: c600d252dc52 ("arm64: dts: rockchip: Add Orange Pi 5 Max board") +Signed-off-by: Jianfeng Liu +Reviewed-by: Jimmy Hon +Link: https://lore.kernel.org/r/20250311141245.2719796-1-liujianfeng1994@gmail.com +Signed-off-by: Heiko Stuebner +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-compact.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-compact.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-compact.dtsi +index 87090cb98020b..bcf3cf704a00e 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-compact.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-compact.dtsi +@@ -73,7 +73,7 @@ + + /* phy2 */ + &pcie2x1l1 { +- reset-gpios = <&gpio4 RK_PD4 GPIO_ACTIVE_HIGH>; ++ reset-gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie_eth>; + status = "okay"; + }; +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-rockchip-fix-pwm-pinctrl-names.patch b/queue-6.14/arm64-dts-rockchip-fix-pwm-pinctrl-names.patch new file mode 100644 index 0000000000..a0f781aee3 --- /dev/null +++ b/queue-6.14/arm64-dts-rockchip-fix-pwm-pinctrl-names.patch @@ -0,0 +1,91 @@ +From 44db6910476fc4e5b8a2ef7ed2755b9a31f97bac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 14:09:17 +0000 +Subject: arm64: dts: rockchip: Fix PWM pinctrl names + +From: Yao Zi + +[ Upstream commit 09b0a7b63a6cda138e2e47c6acb2aee80338624c ] + +These Rockchip boards assign "active" as the pinctrl name for PWM +controllers, which has never been supported in mainline Rockchip PWM +driver. It seems the name used by downstream kernel is accidentally +brought into maineline. Let's fix them. + +Fixes: 4403e1237be3 ("arm64: dts: rockchip: Add devicetree for board roc-rk3308-cc") +Fixes: 964ed0807b5f ("arm64: dts: rockchip: add rk3318 A95X Z2 board") +Fixes: e7a095908227 ("arm64: dts: rockchip: Add devicetree for NanoPC-T4") +Fixes: 3f5d336d64d6 ("arm64: dts: rockchip: Add support for rk3588s based board Cool Pi 4B") +Signed-off-by: Yao Zi +Link: https://lore.kernel.org/r/20250310140916.14384-2-ziyao@disroot.org +Signed-off-by: Heiko Stuebner +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts | 2 +- + arch/arm64/boot/dts/rockchip/rk3318-a95x-z2.dts | 4 ++-- + arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi | 2 +- + arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts | 2 +- + 4 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts +index 629121de5a13d..5e71819489920 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts +@@ -147,7 +147,7 @@ + + &pwm5 { + status = "okay"; +- pinctrl-names = "active"; ++ pinctrl-names = "default"; + pinctrl-0 = <&pwm5_pin_pull_down>; + }; + +diff --git a/arch/arm64/boot/dts/rockchip/rk3318-a95x-z2.dts b/arch/arm64/boot/dts/rockchip/rk3318-a95x-z2.dts +index a94114fb7cc1d..96c27fc5005d1 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3318-a95x-z2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3318-a95x-z2.dts +@@ -274,13 +274,13 @@ + + &pwm0 { + pinctrl-0 = <&pwm0_pin_pull_up>; +- pinctrl-names = "active"; ++ pinctrl-names = "default"; + status = "okay"; + }; + + &pwm1 { + pinctrl-0 = <&pwm1_pin_pull_up>; +- pinctrl-names = "active"; ++ pinctrl-names = "default"; + status = "okay"; + }; + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi +index b169be06d4d1f..c8eb5481f43d0 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi +@@ -603,7 +603,7 @@ + }; + + &pwm2 { +- pinctrl-names = "active"; ++ pinctrl-names = "default"; + pinctrl-0 = <&pwm2_pin_pull_down>; + status = "okay"; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts b/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts +index 9c394f733bbfb..b2c30122aacc5 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts +@@ -429,7 +429,7 @@ + }; + + &pwm13 { +- pinctrl-names = "active"; ++ pinctrl-names = "default"; + pinctrl-0 = <&pwm13m2_pins>; + status = "okay"; + }; +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-rockchip-move-rk356x-scmi-shmem-to-reserve.patch b/queue-6.14/arm64-dts-rockchip-move-rk356x-scmi-shmem-to-reserve.patch new file mode 100644 index 0000000000..60d424c20b --- /dev/null +++ b/queue-6.14/arm64-dts-rockchip-move-rk356x-scmi-shmem-to-reserve.patch @@ -0,0 +1,67 @@ +From 595c29081ddee4e94067a8f489637cbd9408982f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 18:00:01 +0800 +Subject: arm64: dts: rockchip: Move rk356x scmi SHMEM to reserved memory + +From: Chukun Pan + +[ Upstream commit 8fbb9376f0c489dfdc7e20d16e90686b29dec8f2 ] + +0x0 to 0xf0000000 are SDRAM memory areas where 0x10f000 is located. +So move the SHMEM memory of arm_scmi to the reserved memory node. + +Fixes: a3adc0b9071d ("arm64: dts: rockchip: add core dtsi for RK3568 SoC") +Signed-off-by: Chukun Pan +Link: https://lore.kernel.org/r/20250308100001.572657-2-amadeus@jmu.edu.cn +Signed-off-by: Heiko Stuebner +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/rockchip/rk356x-base.dtsi | 25 +++++++++---------- + 1 file changed, 12 insertions(+), 13 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi b/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi +index e553906291140..8421d4b8c7719 100644 +--- a/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi +@@ -174,6 +174,18 @@ + method = "smc"; + }; + ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ scmi_shmem: shmem@10f000 { ++ compatible = "arm,scmi-shmem"; ++ reg = <0x0 0x0010f000 0x0 0x100>; ++ no-map; ++ }; ++ }; ++ + timer { + compatible = "arm,armv8-timer"; + interrupts = , +@@ -199,19 +211,6 @@ + #clock-cells = <0>; + }; + +- sram@10f000 { +- compatible = "mmio-sram"; +- reg = <0x0 0x0010f000 0x0 0x100>; +- #address-cells = <1>; +- #size-cells = <1>; +- ranges = <0 0x0 0x0010f000 0x100>; +- +- scmi_shmem: sram@0 { +- compatible = "arm,scmi-shmem"; +- reg = <0x0 0x100>; +- }; +- }; +- + sata1: sata@fc400000 { + compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci"; + reg = <0 0xfc400000 0 0x1000>; +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-rockchip-remove-bluetooth-node-from-rock-3.patch b/queue-6.14/arm64-dts-rockchip-remove-bluetooth-node-from-rock-3.patch new file mode 100644 index 0000000000..492d6ab559 --- /dev/null +++ b/queue-6.14/arm64-dts-rockchip-remove-bluetooth-node-from-rock-3.patch @@ -0,0 +1,53 @@ +From 23e160a095adec86821e172347c406b70088118b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 00:50:51 +0800 +Subject: arm64: dts: rockchip: Remove bluetooth node from rock-3a + +From: Chen-Yu Tsai + +[ Upstream commit 6b68387cf5ff5d7b86b189135affb0c679e3384a ] + +The Bluetooth node described in the device tree is actually on an M.2 +slot. What module is present depends on what the end user installed, +and should be left to an overlay. + +Remove the existing bluetooth node. This gets rid of bogus timeout +errors. + +Fixes: 8cf890aabd45 ("arm64: dts: rockchip: Add nodes for SDIO/UART Wi-Fi/Bluetooth modules to Radxa Rock 3A") +Signed-off-by: Chen-Yu Tsai +Link: https://lore.kernel.org/r/20250220165051.1889055-1-wens@kernel.org +Signed-off-by: Heiko Stuebner +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts | 14 -------------- + 1 file changed, 14 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts b/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts +index ac79140a9ecd6..44cfdfeed6681 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts +@@ -778,20 +778,6 @@ + pinctrl-0 = <&uart1m0_xfer &uart1m0_ctsn &uart1m0_rtsn>; + uart-has-rtscts; + status = "okay"; +- +- bluetooth { +- compatible = "brcm,bcm43438-bt"; +- clocks = <&rk809 1>; +- clock-names = "lpo"; +- device-wakeup-gpios = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>; +- host-wakeup-gpios = <&gpio4 RK_PB4 GPIO_ACTIVE_HIGH>; +- shutdown-gpios = <&gpio4 RK_PB2 GPIO_ACTIVE_HIGH>; +- pinctrl-names = "default"; +- pinctrl-0 = <&bt_host_wake &bt_wake &bt_enable>; +- vbat-supply = <&vcc3v3_sys>; +- vddio-supply = <&vcc_1v8>; +- /* vddio comes from regulator on module, use IO bank voltage instead */ +- }; + }; + + &uart2 { +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-rockchip-remove-ethm0_clk0_25m_out-from-si.patch b/queue-6.14/arm64-dts-rockchip-remove-ethm0_clk0_25m_out-from-si.patch new file mode 100644 index 0000000000..616a4dfb34 --- /dev/null +++ b/queue-6.14/arm64-dts-rockchip-remove-ethm0_clk0_25m_out-from-si.patch @@ -0,0 +1,51 @@ +From cb9456de3136fee760ab3a2678b5f6c81a6934f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 16:35:50 +0100 +Subject: arm64: dts: rockchip: remove ethm0_clk0_25m_out from Sige5 gmac0 + +From: Nicolas Frattaroli + +[ Upstream commit 73d246b4402c3356f6b3d13665de3a51eea7b555 ] + +The GPIO3 A4 pin on the ArmSoM Sige5 is routed to the 40-pin GPIO +header. This pin can serve a variety of functions, including ones of +questionable use to us on a GPIO header such as the 25MHz clock of the +ethernet controller. + +Unfortunately, this is the precise function that it is being claimed for +by the gmac0 node in the Sige5 board dts, meaning it can't be used for +anything else despite serving no useful function in this role. Since it +goes through a RS0108 bidirectional voltage level translator with a +maximum data rate of 24Mbit/s in push-pull mode and 2Mbit/s data rate in +open-drain mode, it's doubtful as to whether the 25MHz clock signal +would even survive to the actual user-accessible pin it terminates in. + +Remove it to leave the pin for users to play with. It's infinitely more +useful as a GPIO or even as a PWM. + +Fixes: 40f742b07ab2 ("arm64: dts: rockchip: Add rk3576-armsom-sige5 board") +Signed-off-by: Nicolas Frattaroli +Link: https://lore.kernel.org/r/20250314-rk3576-sige5-eth-clk-begone-v1-1-2858338fc555@collabora.com +Signed-off-by: Heiko Stuebner +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts b/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts +index 7c7331936a7fd..a9b9db31d2a3e 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts +@@ -182,8 +182,7 @@ + ð0m0_tx_bus2 + ð0m0_rx_bus2 + ð0m0_rgmii_clk +- ð0m0_rgmii_bus +- ðm0_clk0_25m_out>; ++ ð0m0_rgmii_bus>; + + phy-handle = <&rgmii_phy0>; + status = "okay"; +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-ti-k3-am62-verdin-dahlia-add-microphone-ja.patch b/queue-6.14/arm64-dts-ti-k3-am62-verdin-dahlia-add-microphone-ja.patch new file mode 100644 index 0000000000..8101c5941e --- /dev/null +++ b/queue-6.14/arm64-dts-ti-k3-am62-verdin-dahlia-add-microphone-ja.patch @@ -0,0 +1,51 @@ +From df562fa576be720a5c3ae7e6d385975958ea89dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 15:46:04 +0100 +Subject: arm64: dts: ti: k3-am62-verdin-dahlia: add Microphone Jack to sound + card + +From: Stefan Eichenberger + +[ Upstream commit 7139df64e7c13c079b754476355c62b490213055 ] + +The simple-audio-card's microphone widget currently connects to the +headphone jack. Routing the microphone input to the microphone jack +allows for independent operation of the microphone and headphones. + +This resolves the following boot-time kernel log message, which +indicated a conflict when the microphone and headphone functions were +not separated: + debugfs: File 'Headphone Jack' in directory 'dapm' already present! + +Fixes: f5bf894c865b ("arm64: dts: ti: verdin-am62: dahlia: add sound card") +Signed-off-by: Stefan Eichenberger +Reviewed-by: Francesco Dolcini +Reviewed-by: Jai Luthra +Link: https://lore.kernel.org/r/20250217144643.178222-1-eichest@gmail.com +Signed-off-by: Vignesh Raghavendra +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/ti/k3-am62-verdin-dahlia.dtsi | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/boot/dts/ti/k3-am62-verdin-dahlia.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin-dahlia.dtsi +index 9202181fbd652..fcc4cb2e9389b 100644 +--- a/arch/arm64/boot/dts/ti/k3-am62-verdin-dahlia.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-am62-verdin-dahlia.dtsi +@@ -28,10 +28,10 @@ + "Headphone Jack", "HPOUTR", + "IN2L", "Line In Jack", + "IN2R", "Line In Jack", +- "Headphone Jack", "MICBIAS", +- "IN1L", "Headphone Jack"; ++ "Microphone Jack", "MICBIAS", ++ "IN1L", "Microphone Jack"; + simple-audio-card,widgets = +- "Microphone", "Headphone Jack", ++ "Microphone", "Microphone Jack", + "Headphone", "Headphone Jack", + "Line", "Line In Jack"; + +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-ti-k3-am62p-enable-audio_refclkx.patch b/queue-6.14/arm64-dts-ti-k3-am62p-enable-audio_refclkx.patch new file mode 100644 index 0000000000..6021b022aa --- /dev/null +++ b/queue-6.14/arm64-dts-ti-k3-am62p-enable-audio_refclkx.patch @@ -0,0 +1,57 @@ +From 9476161bf4294fe4796ce46f84f5d5627a71ca51 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 16:39:11 +0100 +Subject: arm64: dts: ti: k3-am62p: Enable AUDIO_REFCLKx + +From: Francesco Dolcini + +[ Upstream commit 6a02c9aa222ce0fff47f526686690f84b7a97f4e ] + +On AM62P-based SoCs the AUDIO_REFCLKx clocks can be used as an input to +external peripherals when configured through CTRL_MMR, so add the +clock nodes. + +Link: http://downloads.ti.com/tisci/esd/latest/5_soc_doc/am62px/clocks.html +Signed-off-by: Francesco Dolcini +Link: https://lore.kernel.org/r/20250206153911.414702-1-francesco@dolcini.it +Signed-off-by: Vignesh Raghavendra +Stable-dep-of: 33bab9d84e52 ("arm64: dts: ti: k3-am62p: fix pinctrl settings") +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/ti/k3-am62p-main.dtsi | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi +index 420c77c8e9e5e..4b47b07743305 100644 +--- a/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi +@@ -42,6 +42,26 @@ + ti,interrupt-ranges = <5 69 35>; + }; + ++&main_conf { ++ audio_refclk0: clock-controller@82e0 { ++ compatible = "ti,am62-audio-refclk"; ++ reg = <0x82e0 0x4>; ++ clocks = <&k3_clks 157 0>; ++ assigned-clocks = <&k3_clks 157 0>; ++ assigned-clock-parents = <&k3_clks 157 16>; ++ #clock-cells = <0>; ++ }; ++ ++ audio_refclk1: clock-controller@82e4 { ++ compatible = "ti,am62-audio-refclk"; ++ reg = <0x82e4 0x4>; ++ clocks = <&k3_clks 157 18>; ++ assigned-clocks = <&k3_clks 157 18>; ++ assigned-clock-parents = <&k3_clks 157 34>; ++ #clock-cells = <0>; ++ }; ++}; ++ + &main_pmx0 { + pinctrl-single,gpio-range = + <&main_pmx0_range 0 32 PIN_GPIO_RANGE_IOPAD>, +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-ti-k3-am62p-fix-pinctrl-settings.patch b/queue-6.14/arm64-dts-ti-k3-am62p-fix-pinctrl-settings.patch new file mode 100644 index 0000000000..5d7f937f08 --- /dev/null +++ b/queue-6.14/arm64-dts-ti-k3-am62p-fix-pinctrl-settings.patch @@ -0,0 +1,87 @@ +From 07ae7d3237fb73125737e34ad17009de6b67f8c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 10:14:46 +0100 +Subject: arm64: dts: ti: k3-am62p: fix pinctrl settings + +From: Michael Walle + +[ Upstream commit 33bab9d84e52188cf73c3573fd7cf3ec0e01d007 ] + +It appears that pinctrl-single is misused on this SoC to control both +the mux and the input and output and bias settings. This results in +non-working pinctrl configurations for GPIOs within the device tree. + +This is what happens: + (1) During startup the pinctrl settings are applied according to the + device tree. I.e. the pin is configured as output and with + pull-ups enabled. + (2) During startup a device driver requests a GPIO. + (3) pinctrl-single is applying the default GPIO setting according to + the pinctrl-single,gpio-range property. + +This would work as expected if the pinctrl-single is only controlling +the function mux, but it also controls the input/output buffer enable, +the pull-up and pull-down settings etc (pinctrl-single,function-mask +covers the entire pad setting instead of just the mux field). + +Remove the pinctrl-single,gpio-range property, so that no settings are +applied during a gpio_request() call. + +Fixes: d72d73a44c3c ("arm64: dts: ti: k3-am62p: Add gpio-ranges properties") +Signed-off-by: Michael Walle +Link: https://lore.kernel.org/r/20250221091447.595199-1-mwalle@kernel.org +Signed-off-by: Vignesh Raghavendra +Signed-off-by: Sasha Levin +--- + .../boot/dts/ti/k3-am62p-j722s-common-mcu.dtsi | 8 -------- + arch/arm64/boot/dts/ti/k3-am62p-main.dtsi | 14 -------------- + 2 files changed, 22 deletions(-) + +diff --git a/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-mcu.dtsi +index b33aff0d65c9d..bd6a00d13aea7 100644 +--- a/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-mcu.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-mcu.dtsi +@@ -12,15 +12,7 @@ + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; +- pinctrl-single,gpio-range = +- <&mcu_pmx_range 0 21 PIN_GPIO_RANGE_IOPAD>, +- <&mcu_pmx_range 23 1 PIN_GPIO_RANGE_IOPAD>, +- <&mcu_pmx_range 32 2 PIN_GPIO_RANGE_IOPAD>; + bootph-all; +- +- mcu_pmx_range: gpio-range { +- #pinctrl-single,gpio-range-cells = <3>; +- }; + }; + + mcu_esm: esm@4100000 { +diff --git a/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi +index 4b47b07743305..6aea9d3f134e4 100644 +--- a/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi +@@ -62,20 +62,6 @@ + }; + }; + +-&main_pmx0 { +- pinctrl-single,gpio-range = +- <&main_pmx0_range 0 32 PIN_GPIO_RANGE_IOPAD>, +- <&main_pmx0_range 33 38 PIN_GPIO_RANGE_IOPAD>, +- <&main_pmx0_range 72 22 PIN_GPIO_RANGE_IOPAD>, +- <&main_pmx0_range 137 5 PIN_GPIO_RANGE_IOPAD>, +- <&main_pmx0_range 143 3 PIN_GPIO_RANGE_IOPAD>, +- <&main_pmx0_range 149 2 PIN_GPIO_RANGE_IOPAD>; +- +- main_pmx0_range: gpio-range { +- #pinctrl-single,gpio-range-cells = <3>; +- }; +-}; +- + &main_gpio0 { + gpio-ranges = <&main_pmx0 0 0 32>, <&main_pmx0 32 33 38>, + <&main_pmx0 70 72 22>; +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-ti-k3-j722s-evm-fix-usb2.0_mux_sel-to-sele.patch b/queue-6.14/arm64-dts-ti-k3-j722s-evm-fix-usb2.0_mux_sel-to-sele.patch new file mode 100644 index 0000000000..51ca1a14e3 --- /dev/null +++ b/queue-6.14/arm64-dts-ti-k3-j722s-evm-fix-usb2.0_mux_sel-to-sele.patch @@ -0,0 +1,48 @@ +From 15093816191d069673d9648e89c286f6275d5e77 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jan 2025 18:27:26 +0530 +Subject: arm64: dts: ti: k3-j722s-evm: Fix USB2.0_MUX_SEL to select Type-C + +From: Hrushikesh Salunke + +[ Upstream commit bc8d9e6b5821c40ab5dd3a81e096cb114939de50 ] + +J722S SOC has two usb controllers USB0 and USB1. USB0 is brought out on +the EVM as a stacked USB connector which has one Type-A and one Type-C +port. These Type-A and Type-C ports are connected to MUX so only +one of them can be enabled at a time. + +Commit under Fixes, tries to enable the USB0 instance of USB to +interface with the Type-C port via the USB hub, by configuring the +USB2.0_MUX_SEL to GPIO_ACTIVE_HIGH. But it is observed on J722S-EVM +that Type-A port is enabled instead of Type-C port. + +Fix this by setting USB2.0_MUX_SEL to GPIO_ACTIVE_LOW to enable Type-C +port. + +Fixes: 485705df5d5f ("arm64: dts: ti: k3-j722s: Enable PCIe and USB support on J722S-EVM") +Signed-off-by: Hrushikesh Salunke +Reviewed-by: Roger Quadros +Link: https://lore.kernel.org/r/20250116125726.2549489-1-h-salunke@ti.com +Signed-off-by: Vignesh Raghavendra +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/ti/k3-j722s-evm.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/ti/k3-j722s-evm.dts b/arch/arm64/boot/dts/ti/k3-j722s-evm.dts +index d184e9c1a0a59..adee69607fdbf 100644 +--- a/arch/arm64/boot/dts/ti/k3-j722s-evm.dts ++++ b/arch/arm64/boot/dts/ti/k3-j722s-evm.dts +@@ -590,7 +590,7 @@ + p05-hog { + /* P05 - USB2.0_MUX_SEL */ + gpio-hog; +- gpios = <5 GPIO_ACTIVE_HIGH>; ++ gpios = <5 GPIO_ACTIVE_LOW>; + output-high; + }; + +-- +2.39.5 + diff --git a/queue-6.14/arm64-dts-ti-k3-j722s-fix-pinctrl-settings.patch b/queue-6.14/arm64-dts-ti-k3-j722s-fix-pinctrl-settings.patch new file mode 100644 index 0000000000..ab0b29c728 --- /dev/null +++ b/queue-6.14/arm64-dts-ti-k3-j722s-fix-pinctrl-settings.patch @@ -0,0 +1,67 @@ +From e3d0c431a66331b646452574ad0b400b8c030e17 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 10:14:47 +0100 +Subject: arm64: dts: ti: k3-j722s: fix pinctrl settings + +From: Michael Walle + +[ Upstream commit 06daad327d043c23bc1ab4cdb519f589094b9e98 ] + +It appears that pinctrl-single is misused on this SoC to control both +the mux and the input and output and bias settings. This results in +non-working pinctrl configurations for GPIOs within the device tree. + +This is what happens: + (1) During startup the pinctrl settings are applied according to the + device tree. I.e. the pin is configured as output and with + pull-ups enabled. + (2) During startup a device driver requests a GPIO. + (3) pinctrl-single is applying the default GPIO setting according to + the pinctrl-single,gpio-range property. + +This would work as expected if the pinctrl-single is only controlling +the function mux, but it also controls the input/output buffer enable, +the pull-up and pull-down settings etc (pinctrl-single,function-mask +covers the entire pad setting instead of just the mux field). + +Remove the pinctrl-single,gpio-range property, so that no settings are +applied during a gpio_request() call. + +Fixes: 5e5c50964e2e ("arm64: dts: ti: k3-j722s: Add gpio-ranges properties") +Signed-off-by: Michael Walle +Link: https://lore.kernel.org/r/20250221091447.595199-2-mwalle@kernel.org +Signed-off-by: Vignesh Raghavendra +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/ti/k3-j722s-main.dtsi | 15 --------------- + 1 file changed, 15 deletions(-) + +diff --git a/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi b/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi +index 3ac2d45a05585..6da7b3a2943c4 100644 +--- a/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi +@@ -251,21 +251,6 @@ + ti,interrupt-ranges = <7 71 21>; + }; + +-&main_pmx0 { +- pinctrl-single,gpio-range = +- <&main_pmx0_range 0 32 PIN_GPIO_RANGE_IOPAD>, +- <&main_pmx0_range 33 38 PIN_GPIO_RANGE_IOPAD>, +- <&main_pmx0_range 72 17 PIN_GPIO_RANGE_IOPAD>, +- <&main_pmx0_range 101 25 PIN_GPIO_RANGE_IOPAD>, +- <&main_pmx0_range 137 5 PIN_GPIO_RANGE_IOPAD>, +- <&main_pmx0_range 143 3 PIN_GPIO_RANGE_IOPAD>, +- <&main_pmx0_range 149 2 PIN_GPIO_RANGE_IOPAD>; +- +- main_pmx0_range: gpio-range { +- #pinctrl-single,gpio-range-cells = <3>; +- }; +-}; +- + &main_gpio0 { + gpio-ranges = <&main_pmx0 0 0 32>, <&main_pmx0 32 33 38>, + <&main_pmx0 70 72 17>; +-- +2.39.5 + diff --git a/queue-6.14/arm64-realm-use-aliased-addresses-for-device-dma-to-.patch b/queue-6.14/arm64-realm-use-aliased-addresses-for-device-dma-to-.patch new file mode 100644 index 0000000000..778a654283 --- /dev/null +++ b/queue-6.14/arm64-realm-use-aliased-addresses-for-device-dma-to-.patch @@ -0,0 +1,66 @@ +From b245f1945344e7e8cf92c96e7ce6718e33a4dc85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 14:41:50 +0000 +Subject: arm64: realm: Use aliased addresses for device DMA to shared buffers + +From: Suzuki K Poulose + +[ Upstream commit 7d953a06241624ee2efb172d037a4168978f4147 ] + +When a device performs DMA to a shared buffer using physical addresses, +(without Stage1 translation), the device must use the "{I}PA address" with the +top bit set in Realm. This is to make sure that a trusted device will be able +to write to shared buffers as well as the protected buffers. Thus, a Realm must +always program the full address including the "protection" bit, like AMD SME +encryption bits. + +Enable this by providing arm64 specific dma_addr_{encrypted, canonical} +helpers for Realms. Please note that the VMM needs to similarly make sure that +the SMMU Stage2 in the Non-secure world is setup accordingly to map IPA at the +unprotected alias. + +Cc: Will Deacon +Cc: Jean-Philippe Brucker +Cc: Robin Murphy +Cc: Steven Price +Cc: Christoph Hellwig +Cc: Marek Szyprowski +Cc: Tom Lendacky +Cc: Aneesh Kumar K.V +Signed-off-by: Suzuki K Poulose +Reviewed-by: Gavin Shan +Acked-by: Catalin Marinas +Reviewed-by: Robin Murphy +Acked-by: Marek Szyprowski +Fixes: 42be24a4178f ("arm64: Enable memory encrypt for Realms") +Acked-by: Will Deacon +Link: https://lore.kernel.org/r/20250227144150.1667735-4-suzuki.poulose@arm.com +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/mem_encrypt.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/arch/arm64/include/asm/mem_encrypt.h b/arch/arm64/include/asm/mem_encrypt.h +index f8f78f622dd2c..a2a1eeb36d4b5 100644 +--- a/arch/arm64/include/asm/mem_encrypt.h ++++ b/arch/arm64/include/asm/mem_encrypt.h +@@ -21,4 +21,15 @@ static inline bool force_dma_unencrypted(struct device *dev) + return is_realm_world(); + } + ++/* ++ * For Arm CCA guests, canonical addresses are "encrypted", so no changes ++ * required for dma_addr_encrypted(). ++ * The unencrypted DMA buffers must be accessed via the unprotected IPA, ++ * "top IPA bit" set. ++ */ ++#define dma_addr_unencrypted(x) ((x) | PROT_NS_SHARED) ++ ++/* Clear the "top" IPA bit while converting back */ ++#define dma_addr_canonical(x) ((x) & ~PROT_NS_SHARED) ++ + #endif /* __ASM_MEM_ENCRYPT_H */ +-- +2.39.5 + diff --git a/queue-6.14/asoc-amd-acp-fix-for-enabling-dmic-on-acp-platforms-.patch b/queue-6.14/asoc-amd-acp-fix-for-enabling-dmic-on-acp-platforms-.patch new file mode 100644 index 0000000000..6d37fd6c2c --- /dev/null +++ b/queue-6.14/asoc-amd-acp-fix-for-enabling-dmic-on-acp-platforms-.patch @@ -0,0 +1,60 @@ +From 50a3c72994f10d1bbc1f6b0588f0e06f84cfbeef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 00:02:01 +0530 +Subject: ASoC: amd: acp: Fix for enabling DMIC on acp platforms via _DSD entry + +From: Venkata Prasad Potturu + +[ Upstream commit 02e1cf7a352a3ba5f768849f2b4fcaaaa19f89e3 ] + +Add condition check to register ACP PDM sound card by reading +_WOV acpi entry. + +Fixes: 09068d624c49 ("ASoC: amd: acp: fix for acp platform device creation failure") + +Signed-off-by: Venkata Prasad Potturu +Link: https://patch.msgid.link/20250310183201.11979-15-venkataprasad.potturu@amd.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/amd/acp/acp-legacy-common.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c +index 7acc7ed2e8cc9..b9f085c560c2d 100644 +--- a/sound/soc/amd/acp/acp-legacy-common.c ++++ b/sound/soc/amd/acp/acp-legacy-common.c +@@ -13,6 +13,7 @@ + */ + + #include "amd.h" ++#include + #include + #include + +@@ -445,7 +446,9 @@ void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip) + { + struct acpi_device *pdm_dev; + const union acpi_object *obj; +- u32 pdm_addr; ++ acpi_handle handle; ++ acpi_integer dmic_status; ++ u32 pdm_addr, ret; + + switch (chip->acp_rev) { + case ACP_RN_PCI_ID: +@@ -477,6 +480,11 @@ void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip) + obj->integer.value == pdm_addr) + chip->is_pdm_dev = true; + } ++ ++ handle = ACPI_HANDLE(&pci->dev); ++ ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status); ++ if (!ACPI_FAILURE(ret)) ++ chip->is_pdm_dev = dmic_status; + } + } + EXPORT_SYMBOL_NS_GPL(check_acp_config, "SND_SOC_ACP_COMMON"); +-- +2.39.5 + diff --git a/queue-6.14/asoc-codecs-rt5665-fix-some-error-handling-paths-in-.patch b/queue-6.14/asoc-codecs-rt5665-fix-some-error-handling-paths-in-.patch new file mode 100644 index 0000000000..b93ab0976c --- /dev/null +++ b/queue-6.14/asoc-codecs-rt5665-fix-some-error-handling-paths-in-.patch @@ -0,0 +1,100 @@ +From 531c2c36f109ea20aa9f52855d747c7fee39d704 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Mar 2025 08:45:49 +0100 +Subject: ASoC: codecs: rt5665: Fix some error handling paths in rt5665_probe() + +From: Christophe JAILLET + +[ Upstream commit 1ebd4944266e86a7ce274f197847f5a6399651e8 ] + +Should an error occur after a successful regulator_bulk_enable() call, +regulator_bulk_disable() should be called, as already done in the remove +function. + +Instead of adding an error handling path in the probe, switch from +devm_regulator_bulk_get() to devm_regulator_bulk_get_enable() and +simplify the remove function and some other places accordingly. + +Finally, add a missing const when defining rt5665_supply_names to please +checkpatch and constify a few bytes. + +Fixes: 33ada14a26c8 ("ASoC: add rt5665 codec driver") +Signed-off-by: Christophe JAILLET +Link: https://patch.msgid.link/e3c2aa1b2fdfa646752d94f4af968630c0d58248.1742629525.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/rt5665.c | 24 ++++-------------------- + 1 file changed, 4 insertions(+), 20 deletions(-) + +diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c +index 47df14ba52784..4f0236b34a2d9 100644 +--- a/sound/soc/codecs/rt5665.c ++++ b/sound/soc/codecs/rt5665.c +@@ -31,9 +31,7 @@ + #include "rl6231.h" + #include "rt5665.h" + +-#define RT5665_NUM_SUPPLIES 3 +- +-static const char *rt5665_supply_names[RT5665_NUM_SUPPLIES] = { ++static const char * const rt5665_supply_names[] = { + "AVDD", + "MICVDD", + "VBAT", +@@ -46,7 +44,6 @@ struct rt5665_priv { + struct gpio_desc *gpiod_ldo1_en; + struct gpio_desc *gpiod_reset; + struct snd_soc_jack *hs_jack; +- struct regulator_bulk_data supplies[RT5665_NUM_SUPPLIES]; + struct delayed_work jack_detect_work; + struct delayed_work calibrate_work; + struct delayed_work jd_check_work; +@@ -4471,8 +4468,6 @@ static void rt5665_remove(struct snd_soc_component *component) + struct rt5665_priv *rt5665 = snd_soc_component_get_drvdata(component); + + regmap_write(rt5665->regmap, RT5665_RESET, 0); +- +- regulator_bulk_disable(ARRAY_SIZE(rt5665->supplies), rt5665->supplies); + } + + #ifdef CONFIG_PM +@@ -4758,7 +4753,7 @@ static int rt5665_i2c_probe(struct i2c_client *i2c) + { + struct rt5665_platform_data *pdata = dev_get_platdata(&i2c->dev); + struct rt5665_priv *rt5665; +- int i, ret; ++ int ret; + unsigned int val; + + rt5665 = devm_kzalloc(&i2c->dev, sizeof(struct rt5665_priv), +@@ -4774,24 +4769,13 @@ static int rt5665_i2c_probe(struct i2c_client *i2c) + else + rt5665_parse_dt(rt5665, &i2c->dev); + +- for (i = 0; i < ARRAY_SIZE(rt5665->supplies); i++) +- rt5665->supplies[i].supply = rt5665_supply_names[i]; +- +- ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(rt5665->supplies), +- rt5665->supplies); ++ ret = devm_regulator_bulk_get_enable(&i2c->dev, ARRAY_SIZE(rt5665_supply_names), ++ rt5665_supply_names); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); + return ret; + } + +- ret = regulator_bulk_enable(ARRAY_SIZE(rt5665->supplies), +- rt5665->supplies); +- if (ret != 0) { +- dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); +- return ret; +- } +- +- + rt5665->gpiod_ldo1_en = devm_gpiod_get_optional(&i2c->dev, + "realtek,ldo1-en", + GPIOD_OUT_HIGH); +-- +2.39.5 + diff --git a/queue-6.14/asoc-cs35l41-check-the-return-value-from-spi_setup.patch b/queue-6.14/asoc-cs35l41-check-the-return-value-from-spi_setup.patch new file mode 100644 index 0000000000..06ef98e3e2 --- /dev/null +++ b/queue-6.14/asoc-cs35l41-check-the-return-value-from-spi_setup.patch @@ -0,0 +1,52 @@ +From 5512eebee85118bbc097ad4a7273d30673910879 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 16:56:37 +0500 +Subject: ASoC: cs35l41: check the return value from spi_setup() + +From: Vitaliy Shevtsov + +[ Upstream commit ad5a0970f86d82e39ebd06d45a1f7aa48a1316f8 ] + +Currently the return value from spi_setup() is not checked for a failure. +It is unlikely it will ever fail in this particular case but it is still +better to add this check for the sake of completeness and correctness. This +is cheap since it is performed once when the device is being probed. + +Handle spi_setup() return value. + +Found by Linux Verification Center (linuxtesting.org) with Svace. + +Fixes: 872fc0b6bde8 ("ASoC: cs35l41: Set the max SPI speed for the whole device") +Signed-off-by: Vitaliy Shevtsov +Link: https://patch.msgid.link/20250304115643.2748-1-v.shevtsov@mt-integration.ru +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/cs35l41-spi.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/cs35l41-spi.c b/sound/soc/codecs/cs35l41-spi.c +index a6db44520c060..f9b6bf7bea9c9 100644 +--- a/sound/soc/codecs/cs35l41-spi.c ++++ b/sound/soc/codecs/cs35l41-spi.c +@@ -32,13 +32,16 @@ static int cs35l41_spi_probe(struct spi_device *spi) + const struct regmap_config *regmap_config = &cs35l41_regmap_spi; + struct cs35l41_hw_cfg *hw_cfg = dev_get_platdata(&spi->dev); + struct cs35l41_private *cs35l41; ++ int ret; + + cs35l41 = devm_kzalloc(&spi->dev, sizeof(struct cs35l41_private), GFP_KERNEL); + if (!cs35l41) + return -ENOMEM; + + spi->max_speed_hz = CS35L41_SPI_MAX_FREQ; +- spi_setup(spi); ++ ret = spi_setup(spi); ++ if (ret < 0) ++ return ret; + + spi_set_drvdata(spi, cs35l41); + cs35l41->regmap = devm_regmap_init_spi(spi, regmap_config); +-- +2.39.5 + diff --git a/queue-6.14/asoc-imx-card-add-null-check-in-imx_card_probe.patch b/queue-6.14/asoc-imx-card-add-null-check-in-imx_card_probe.patch new file mode 100644 index 0000000000..e18cdb778d --- /dev/null +++ b/queue-6.14/asoc-imx-card-add-null-check-in-imx_card_probe.patch @@ -0,0 +1,50 @@ +From d667c0625a28635bf8329f012560dfb83824fa60 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Apr 2025 22:25:10 +0800 +Subject: ASoC: imx-card: Add NULL check in imx_card_probe() + +From: Henry Martin + +[ Upstream commit 93d34608fd162f725172e780b1c60cc93a920719 ] + +devm_kasprintf() returns NULL when memory allocation fails. Currently, +imx_card_probe() does not check for this case, which results in a NULL +pointer dereference. + +Add NULL check after devm_kasprintf() to prevent this issue. + +Fixes: aa736700f42f ("ASoC: imx-card: Add imx-card machine driver") +Signed-off-by: Henry Martin +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20250401142510.29900-1-bsdhenrymartin@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/fsl/imx-card.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c +index ac043ad367ace..21f617f6f9fa8 100644 +--- a/sound/soc/fsl/imx-card.c ++++ b/sound/soc/fsl/imx-card.c +@@ -767,6 +767,8 @@ static int imx_card_probe(struct platform_device *pdev) + data->dapm_routes[i].sink = + devm_kasprintf(&pdev->dev, GFP_KERNEL, "%d %s", + i + 1, "Playback"); ++ if (!data->dapm_routes[i].sink) ++ return -ENOMEM; + data->dapm_routes[i].source = "CPU-Playback"; + } + } +@@ -784,6 +786,8 @@ static int imx_card_probe(struct platform_device *pdev) + data->dapm_routes[i].source = + devm_kasprintf(&pdev->dev, GFP_KERNEL, "%d %s", + i + 1, "Capture"); ++ if (!data->dapm_routes[i].source) ++ return -ENOMEM; + data->dapm_routes[i].sink = "CPU-Capture"; + } + } +-- +2.39.5 + diff --git a/queue-6.14/asoc-simple-card-utils-don-t-use-__free-device_node-.patch b/queue-6.14/asoc-simple-card-utils-don-t-use-__free-device_node-.patch new file mode 100644 index 0000000000..9abf31c902 --- /dev/null +++ b/queue-6.14/asoc-simple-card-utils-don-t-use-__free-device_node-.patch @@ -0,0 +1,65 @@ +From 753349371f2b3d98fc87bec4655baa8e4f85cc94 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 00:29:30 +0000 +Subject: ASoC: simple-card-utils: Don't use __free(device_node) at + graph_util_parse_dai() + +From: Kuninori Morimoto + +[ Upstream commit de74ec718e0788e1998eb7289ad07970e27cae27 ] + +commit 419d1918105e ("ASoC: simple-card-utils: use __free(device_node) for +device node") uses __free(device_node) for dlc->of_node, but we need to +keep it while driver is in use. + +Don't use __free(device_node) in graph_util_parse_dai(). + +Fixes: 419d1918105e ("ASoC: simple-card-utils: use __free(device_node) for device node") +Reported-by: Thuan Nguyen +Reported-by: Detlev Casanova +Signed-off-by: Kuninori Morimoto +Tested-by: Thuan Nguyen +Tested-by: Detlev Casanova +Link: https://patch.msgid.link/87eczisyhh.wl-kuninori.morimoto.gx@renesas.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/generic/simple-card-utils.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c +index c2445c5ccd84c..32efb30c55d69 100644 +--- a/sound/soc/generic/simple-card-utils.c ++++ b/sound/soc/generic/simple-card-utils.c +@@ -1077,6 +1077,7 @@ static int graph_get_dai_id(struct device_node *ep) + int graph_util_parse_dai(struct device *dev, struct device_node *ep, + struct snd_soc_dai_link_component *dlc, int *is_single_link) + { ++ struct device_node *node; + struct of_phandle_args args = {}; + struct snd_soc_dai *dai; + int ret; +@@ -1084,7 +1085,7 @@ int graph_util_parse_dai(struct device *dev, struct device_node *ep, + if (!ep) + return 0; + +- struct device_node *node __free(device_node) = of_graph_get_port_parent(ep); ++ node = of_graph_get_port_parent(ep); + + /* + * Try to find from DAI node +@@ -1126,8 +1127,10 @@ int graph_util_parse_dai(struct device *dev, struct device_node *ep, + * if he unbinded CPU or Codec. + */ + ret = snd_soc_get_dlc(&args, dlc); +- if (ret < 0) ++ if (ret < 0) { ++ of_node_put(node); + return ret; ++ } + + parse_dai_end: + if (is_single_link) +-- +2.39.5 + diff --git a/queue-6.14/asoc-tegra-use-non-atomic-timeout-for-adx-status-reg.patch b/queue-6.14/asoc-tegra-use-non-atomic-timeout-for-adx-status-reg.patch new file mode 100644 index 0000000000..8aaab31ffa --- /dev/null +++ b/queue-6.14/asoc-tegra-use-non-atomic-timeout-for-adx-status-reg.patch @@ -0,0 +1,55 @@ +From 4ad39880096b8edbd37a3fb2e1dc76a1870660ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 06:20:10 +0000 +Subject: ASoC: tegra: Use non-atomic timeout for ADX status register + +From: Ritu Chaudhary + +[ Upstream commit f1d742c35b659fb0122da0a8ff09ad9309cb29d8 ] + +ADX startup() callback uses atomic poll timeout on ADX status register. + +This is unnecessary because: + +- The startup() callback itself is non-atomic. +- The subsequent timeout call in the same function already uses a + non-atomic version. + +Using atomic version can hog CPU when it is not really needed, +so replace it with non-atomic version. + +Fixes: a99ab6f395a9e ("ASoC: tegra: Add Tegra210 based ADX driver") +Signed-off-by: Ritu Chaudhary +Signed-off-by: Sheetal +Link: https://patch.msgid.link/20250311062010.33412-1-sheetal@nvidia.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/tegra/tegra210_adx.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/tegra/tegra210_adx.c b/sound/soc/tegra/tegra210_adx.c +index 0aa93b948378f..3c10e09976ad0 100644 +--- a/sound/soc/tegra/tegra210_adx.c ++++ b/sound/soc/tegra/tegra210_adx.c +@@ -1,5 +1,5 @@ + // SPDX-License-Identifier: GPL-2.0-only +-// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES. ++// SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES. + // All rights reserved. + // + // tegra210_adx.c - Tegra210 ADX driver +@@ -57,8 +57,8 @@ static int tegra210_adx_startup(struct snd_pcm_substream *substream, + int err; + + /* Ensure if ADX status is disabled */ +- err = regmap_read_poll_timeout_atomic(adx->regmap, TEGRA210_ADX_STATUS, +- val, !(val & 0x1), 10, 10000); ++ err = regmap_read_poll_timeout(adx->regmap, TEGRA210_ADX_STATUS, ++ val, !(val & 0x1), 10, 10000); + if (err < 0) { + dev_err(dai->dev, "failed to stop ADX, err = %d\n", err); + return err; +-- +2.39.5 + diff --git a/queue-6.14/asoc-ti-j721e-evm-fix-clock-configuration-for-ti-j72.patch b/queue-6.14/asoc-ti-j721e-evm-fix-clock-configuration-for-ti-j72.patch new file mode 100644 index 0000000000..3c97faab2b --- /dev/null +++ b/queue-6.14/asoc-ti-j721e-evm-fix-clock-configuration-for-ti-j72.patch @@ -0,0 +1,41 @@ +From 8e8ab02d040a142c6057021de2be8235e1613e21 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 17:05:24 +0530 +Subject: ASoC: ti: j721e-evm: Fix clock configuration for ti,j7200-cpb-audio + compatible + +From: Jayesh Choudhary + +[ Upstream commit 45ff65e30deb919604e68faed156ad96ce7474d9 ] + +For 'ti,j7200-cpb-audio' compatible, there is support for only one PLL for +48k. For 11025, 22050, 44100 and 88200 sampling rates, due to absence of +J721E_CLK_PARENT_44100, we get EINVAL while running any audio application. +Add support for these rates by using the 48k parent clock and adjusting +the clock for these rates later in j721e_configure_refclk. + +Fixes: 6748d0559059 ("ASoC: ti: Add custom machine driver for j721e EVM (CPB and IVI)") +Signed-off-by: Jayesh Choudhary +Link: https://patch.msgid.link/20250318113524.57100-1-j-choudhary@ti.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/ti/j721e-evm.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/soc/ti/j721e-evm.c b/sound/soc/ti/j721e-evm.c +index d9d1e021f5b2e..0f96cc45578d8 100644 +--- a/sound/soc/ti/j721e-evm.c ++++ b/sound/soc/ti/j721e-evm.c +@@ -182,6 +182,8 @@ static int j721e_configure_refclk(struct j721e_priv *priv, + clk_id = J721E_CLK_PARENT_48000; + else if (!(rate % 11025) && priv->pll_rates[J721E_CLK_PARENT_44100]) + clk_id = J721E_CLK_PARENT_44100; ++ else if (!(rate % 11025) && priv->pll_rates[J721E_CLK_PARENT_48000]) ++ clk_id = J721E_CLK_PARENT_48000; + else + return ret; + +-- +2.39.5 + diff --git a/queue-6.14/ata-libata-fix-ncq-non-data-log-not-supported-print.patch b/queue-6.14/ata-libata-fix-ncq-non-data-log-not-supported-print.patch new file mode 100644 index 0000000000..c8fbd0f026 --- /dev/null +++ b/queue-6.14/ata-libata-fix-ncq-non-data-log-not-supported-print.patch @@ -0,0 +1,47 @@ +From 20cc6aca0761a4afab8d65cac9e74be8476a6cce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 12:17:55 +0100 +Subject: ata: libata: Fix NCQ Non-Data log not supported print + +From: Niklas Cassel + +[ Upstream commit b500ee5fde1bd0c85026dfcdadbc175548fb5216 ] + +Currently, both ata_dev_config_ncq_send_recv() - which checks for NCQ +Send/Recv Log (Log Address 13h) and ata_dev_config_ncq_non_data() - +which checks for NCQ Non-Data Log (Log Address 12h), uses the same +print when the log is not supported: + + "NCQ Send/Recv Log not supported" + +This seems like a copy paste error, since NCQ Non-Data Log is actually +a separate log. + +Fix the print to reference the correct log. + +Fixes: 284b3b77ea88 ("libata: NCQ encapsulation for ZAC MANAGEMENT OUT") +Reviewed-by: Damien Le Moal +Reviewed-by: Hannes Reinecke +Link: https://lore.kernel.org/r/20250317111754.1666084-2-cassel@kernel.org +Signed-off-by: Niklas Cassel +Signed-off-by: Sasha Levin +--- + drivers/ata/libata-core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index d956735e2a764..3d730c10f7bea 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -2243,7 +2243,7 @@ static void ata_dev_config_ncq_non_data(struct ata_device *dev) + + if (!ata_log_supported(dev, ATA_LOG_NCQ_NON_DATA)) { + ata_dev_warn(dev, +- "NCQ Send/Recv Log not supported\n"); ++ "NCQ Non-Data Log not supported\n"); + return; + } + err_mask = ata_read_log_page(dev, ATA_LOG_NCQ_NON_DATA, +-- +2.39.5 + diff --git a/queue-6.14/auxdisplay-max6959-should-select-bitreverse.patch b/queue-6.14/auxdisplay-max6959-should-select-bitreverse.patch new file mode 100644 index 0000000000..e70d59fd00 --- /dev/null +++ b/queue-6.14/auxdisplay-max6959-should-select-bitreverse.patch @@ -0,0 +1,38 @@ +From 65e48e6384ef646fe24115bb38a1ad5a4f9060d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 08:48:42 +0100 +Subject: auxdisplay: MAX6959 should select BITREVERSE + +From: Geert Uytterhoeven + +[ Upstream commit fce85f3da08b76c1b052f53a9f6f9c40a8a10660 ] + +If CONFIG_BITREVERSE is not enabled: + + max6959.c:(.text+0x92): undefined reference to `byte_rev_table' + +Fixes: a9bcd02fa42217c7 ("auxdisplay: Add driver for MAX695x 7-segment LED controllers") +Reported-by: kernel test robot +Closes: https://lore.kernel.org/202502161703.3Vr4M7qg-lkp@intel.com/ +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Andy Shevchenko +Signed-off-by: Sasha Levin +--- + drivers/auxdisplay/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig +index 8934e6ad5772b..bedc6133f970a 100644 +--- a/drivers/auxdisplay/Kconfig ++++ b/drivers/auxdisplay/Kconfig +@@ -503,6 +503,7 @@ config HT16K33 + config MAX6959 + tristate "Maxim MAX6958/6959 7-segment LED controller" + depends on I2C ++ select BITREVERSE + select REGMAP_I2C + select LINEDISP + help +-- +2.39.5 + diff --git a/queue-6.14/auxdisplay-panel-fix-an-api-misuse-in-panel.c.patch b/queue-6.14/auxdisplay-panel-fix-an-api-misuse-in-panel.c.patch new file mode 100644 index 0000000000..82322e47c6 --- /dev/null +++ b/queue-6.14/auxdisplay-panel-fix-an-api-misuse-in-panel.c.patch @@ -0,0 +1,46 @@ +From 32318b47fcf801888cff65dfe89e9e4d5d8b9108 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 14:36:25 +0200 +Subject: auxdisplay: panel: Fix an API misuse in panel.c + +From: Andy Shevchenko + +[ Upstream commit 72e1c440c848624ad4cfac93d69d8a999a20355b ] + +Variable allocated by charlcd_alloc() should be released +by charlcd_free(). The following patch changed kfree() to +charlcd_free() to fix an API misuse. + +Reviewed-by: Geert Uytterhoeven +Fixes: 718e05ed92ec ("auxdisplay: Introduce hd44780_common.[ch]") +Signed-off-by: Andy Shevchenko +Signed-off-by: Sasha Levin +--- + drivers/auxdisplay/panel.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c +index a731f28455b45..6dc8798d01f98 100644 +--- a/drivers/auxdisplay/panel.c ++++ b/drivers/auxdisplay/panel.c +@@ -1664,7 +1664,7 @@ static void panel_attach(struct parport *port) + if (lcd.enabled) + charlcd_unregister(lcd.charlcd); + err_unreg_device: +- kfree(lcd.charlcd); ++ charlcd_free(lcd.charlcd); + lcd.charlcd = NULL; + parport_unregister_device(pprt); + pprt = NULL; +@@ -1692,7 +1692,7 @@ static void panel_detach(struct parport *port) + charlcd_unregister(lcd.charlcd); + lcd.initialized = false; + kfree(lcd.charlcd->drvdata); +- kfree(lcd.charlcd); ++ charlcd_free(lcd.charlcd); + lcd.charlcd = NULL; + } + +-- +2.39.5 + diff --git a/queue-6.14/ax25-remove-broken-autobind.patch b/queue-6.14/ax25-remove-broken-autobind.patch new file mode 100644 index 0000000000..b54c96d6b2 --- /dev/null +++ b/queue-6.14/ax25-remove-broken-autobind.patch @@ -0,0 +1,233 @@ +From 717f4279f7f6f4dd12e52befe0f6302738dbb57c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 13:53:52 +0300 +Subject: ax25: Remove broken autobind + +From: Murad Masimov + +[ Upstream commit 2f6efbabceb6b2914ee9bafb86d9a51feae9cce8 ] + +Binding AX25 socket by using the autobind feature leads to memory leaks +in ax25_connect() and also refcount leaks in ax25_release(). Memory +leak was detected with kmemleak: + +================================================================ +unreferenced object 0xffff8880253cd680 (size 96): +backtrace: +__kmalloc_node_track_caller_noprof (./include/linux/kmemleak.h:43) +kmemdup_noprof (mm/util.c:136) +ax25_rt_autobind (net/ax25/ax25_route.c:428) +ax25_connect (net/ax25/af_ax25.c:1282) +__sys_connect_file (net/socket.c:2045) +__sys_connect (net/socket.c:2064) +__x64_sys_connect (net/socket.c:2067) +do_syscall_64 (arch/x86/entry/common.c:52 arch/x86/entry/common.c:83) +entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130) +================================================================ + +When socket is bound, refcounts must be incremented the way it is done +in ax25_bind() and ax25_setsockopt() (SO_BINDTODEVICE). In case of +autobind, the refcounts are not incremented. + +This bug leads to the following issue reported by Syzkaller: + +================================================================ +ax25_connect(): syz-executor318 uses autobind, please contact jreuter@yaina.de +------------[ cut here ]------------ +refcount_t: decrement hit 0; leaking memory. +WARNING: CPU: 0 PID: 5317 at lib/refcount.c:31 refcount_warn_saturate+0xfa/0x1d0 lib/refcount.c:31 +Modules linked in: +CPU: 0 UID: 0 PID: 5317 Comm: syz-executor318 Not tainted 6.14.0-rc4-syzkaller-00278-gece144f151ac #0 +Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 +RIP: 0010:refcount_warn_saturate+0xfa/0x1d0 lib/refcount.c:31 +... +Call Trace: + + __refcount_dec include/linux/refcount.h:336 [inline] + refcount_dec include/linux/refcount.h:351 [inline] + ref_tracker_free+0x6af/0x7e0 lib/ref_tracker.c:236 + netdev_tracker_free include/linux/netdevice.h:4302 [inline] + netdev_put include/linux/netdevice.h:4319 [inline] + ax25_release+0x368/0x960 net/ax25/af_ax25.c:1080 + __sock_release net/socket.c:647 [inline] + sock_close+0xbc/0x240 net/socket.c:1398 + __fput+0x3e9/0x9f0 fs/file_table.c:464 + __do_sys_close fs/open.c:1580 [inline] + __se_sys_close fs/open.c:1565 [inline] + __x64_sys_close+0x7f/0x110 fs/open.c:1565 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + ... + +================================================================ + +Considering the issues above and the comments left in the code that say: +"check if we can remove this feature. It is broken."; "autobinding in this +may or may not work"; - it is better to completely remove this feature than +to fix it because it is broken and leads to various kinds of memory bugs. + +Now calling connect() without first binding socket will result in an +error (-EINVAL). Userspace software that relies on the autobind feature +might get broken. However, this feature does not seem widely used with +this specific driver as it was not reliable at any point of time, and it +is already broken anyway. E.g. ax25-tools and ax25-apps packages for +popular distributions do not use the autobind feature for AF_AX25. + +Found by Linux Verification Center (linuxtesting.org) with Syzkaller. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+33841dc6aa3e1d86b78a@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=33841dc6aa3e1d86b78a +Signed-off-by: Murad Masimov +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + include/net/ax25.h | 1 - + net/ax25/af_ax25.c | 30 ++++++------------ + net/ax25/ax25_route.c | 74 ------------------------------------------- + 3 files changed, 10 insertions(+), 95 deletions(-) + +diff --git a/include/net/ax25.h b/include/net/ax25.h +index 4ee141aae0a29..a7bba42dde153 100644 +--- a/include/net/ax25.h ++++ b/include/net/ax25.h +@@ -418,7 +418,6 @@ void ax25_rt_device_down(struct net_device *); + int ax25_rt_ioctl(unsigned int, void __user *); + extern const struct seq_operations ax25_rt_seqops; + ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev); +-int ax25_rt_autobind(ax25_cb *, ax25_address *); + struct sk_buff *ax25_rt_build_path(struct sk_buff *, ax25_address *, + ax25_address *, ax25_digi *); + void ax25_rt_free(void); +diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c +index 9f3b8b682adb2..3ee7dba343100 100644 +--- a/net/ax25/af_ax25.c ++++ b/net/ax25/af_ax25.c +@@ -1270,28 +1270,18 @@ static int __must_check ax25_connect(struct socket *sock, + } + } + +- /* +- * Must bind first - autobinding in this may or may not work. If +- * the socket is already bound, check to see if the device has +- * been filled in, error if it hasn't. +- */ ++ /* Must bind first - autobinding does not work. */ + if (sock_flag(sk, SOCK_ZAPPED)) { +- /* check if we can remove this feature. It is broken. */ +- printk(KERN_WARNING "ax25_connect(): %s uses autobind, please contact jreuter@yaina.de\n", +- current->comm); +- if ((err = ax25_rt_autobind(ax25, &fsa->fsa_ax25.sax25_call)) < 0) { +- kfree(digi); +- goto out_release; +- } ++ kfree(digi); ++ err = -EINVAL; ++ goto out_release; ++ } + +- ax25_fillin_cb(ax25, ax25->ax25_dev); +- ax25_cb_add(ax25); +- } else { +- if (ax25->ax25_dev == NULL) { +- kfree(digi); +- err = -EHOSTUNREACH; +- goto out_release; +- } ++ /* Check to see if the device has been filled in, error if it hasn't. */ ++ if (ax25->ax25_dev == NULL) { ++ kfree(digi); ++ err = -EHOSTUNREACH; ++ goto out_release; + } + + if (sk->sk_type == SOCK_SEQPACKET && +diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c +index 69de75db0c9c2..10577434f40bf 100644 +--- a/net/ax25/ax25_route.c ++++ b/net/ax25/ax25_route.c +@@ -373,80 +373,6 @@ ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev) + return ax25_rt; + } + +-/* +- * Adjust path: If you specify a default route and want to connect +- * a target on the digipeater path but w/o having a special route +- * set before, the path has to be truncated from your target on. +- */ +-static inline void ax25_adjust_path(ax25_address *addr, ax25_digi *digipeat) +-{ +- int k; +- +- for (k = 0; k < digipeat->ndigi; k++) { +- if (ax25cmp(addr, &digipeat->calls[k]) == 0) +- break; +- } +- +- digipeat->ndigi = k; +-} +- +- +-/* +- * Find which interface to use. +- */ +-int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) +-{ +- ax25_uid_assoc *user; +- ax25_route *ax25_rt; +- int err = 0; +- +- ax25_route_lock_use(); +- ax25_rt = ax25_get_route(addr, NULL); +- if (!ax25_rt) { +- ax25_route_lock_unuse(); +- return -EHOSTUNREACH; +- } +- rcu_read_lock(); +- if ((ax25->ax25_dev = ax25_dev_ax25dev(ax25_rt->dev)) == NULL) { +- err = -EHOSTUNREACH; +- goto put; +- } +- +- user = ax25_findbyuid(current_euid()); +- if (user) { +- ax25->source_addr = user->call; +- ax25_uid_put(user); +- } else { +- if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) { +- err = -EPERM; +- goto put; +- } +- ax25->source_addr = *(ax25_address *)ax25->ax25_dev->dev->dev_addr; +- } +- +- if (ax25_rt->digipeat != NULL) { +- ax25->digipeat = kmemdup(ax25_rt->digipeat, sizeof(ax25_digi), +- GFP_ATOMIC); +- if (ax25->digipeat == NULL) { +- err = -ENOMEM; +- goto put; +- } +- ax25_adjust_path(addr, ax25->digipeat); +- } +- +- if (ax25->sk != NULL) { +- local_bh_disable(); +- bh_lock_sock(ax25->sk); +- sock_reset_flag(ax25->sk, SOCK_ZAPPED); +- bh_unlock_sock(ax25->sk); +- local_bh_enable(); +- } +- +-put: +- rcu_read_unlock(); +- ax25_route_lock_unuse(); +- return err; +-} + + struct sk_buff *ax25_rt_build_path(struct sk_buff *skb, ax25_address *src, + ax25_address *dest, ax25_digi *digi) +-- +2.39.5 + diff --git a/queue-6.14/badblocks-attempt-to-merge-adjacent-badblocks-during.patch b/queue-6.14/badblocks-attempt-to-merge-adjacent-badblocks-during.patch new file mode 100644 index 0000000000..fe26f583f5 --- /dev/null +++ b/queue-6.14/badblocks-attempt-to-merge-adjacent-badblocks-during.patch @@ -0,0 +1,47 @@ +From 88dfd098aadb9986552567153282d31ff6a4e389 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 15:54:58 +0800 +Subject: badblocks: attempt to merge adjacent badblocks during + ack_all_badblocks + +From: Li Nan + +[ Upstream commit 32e9ad4d11f69949ff331e35a417871ee0d31d99 ] + +If ack and unack badblocks are adjacent, they will not be merged and will +remain as two separate badblocks. Even after the bad blocks are written +to disk and both become ack, they will still remain as two independent +bad blocks. This is not ideal as it wastes the limited space for +badblocks. Therefore, during ack_all_badblocks(), attempt to merge +badblocks if they are adjacent. + +Fixes: aa511ff8218b ("badblocks: switch to the improved badblock handling code") +Signed-off-by: Li Nan +Reviewed-by: Yu Kuai +Acked-by: Coly Li +Link: https://lore.kernel.org/r/20250227075507.151331-4-zhengqixing@huaweicloud.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/badblocks.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/block/badblocks.c b/block/badblocks.c +index f069c93e986df..ad8652fbe1c8f 100644 +--- a/block/badblocks.c ++++ b/block/badblocks.c +@@ -1491,6 +1491,11 @@ void ack_all_badblocks(struct badblocks *bb) + p[i] = BB_MAKE(start, len, 1); + } + } ++ ++ for (i = 0; i < bb->count ; i++) ++ while (try_adjacent_combine(bb, i)) ++ ; ++ + bb->unacked_exist = 0; + } + write_sequnlock_irq(&bb->lock); +-- +2.39.5 + diff --git a/queue-6.14/badblocks-factor-out-a-helper-try_adjacent_combine.patch b/queue-6.14/badblocks-factor-out-a-helper-try_adjacent_combine.patch new file mode 100644 index 0000000000..f8384cf1bf --- /dev/null +++ b/queue-6.14/badblocks-factor-out-a-helper-try_adjacent_combine.patch @@ -0,0 +1,82 @@ +From 9be4e70d08006c6f75fedbf790ea7b8f90952dd7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 15:54:57 +0800 +Subject: badblocks: factor out a helper try_adjacent_combine + +From: Li Nan + +[ Upstream commit 270b68fee9688428e0a98d4a2c3e6d4c434a84ba ] + +Factor out try_adjacent_combine(), and it will be used in the later patch. + +Signed-off-by: Li Nan +Reviewed-by: Yu Kuai +Link: https://lore.kernel.org/r/20250227075507.151331-3-zhengqixing@huaweicloud.com +Signed-off-by: Jens Axboe +Stable-dep-of: 32e9ad4d11f6 ("badblocks: attempt to merge adjacent badblocks during ack_all_badblocks") +Signed-off-by: Sasha Levin +--- + block/badblocks.c | 40 ++++++++++++++++++++++++++-------------- + 1 file changed, 26 insertions(+), 14 deletions(-) + +diff --git a/block/badblocks.c b/block/badblocks.c +index bcee057efc476..f069c93e986df 100644 +--- a/block/badblocks.c ++++ b/block/badblocks.c +@@ -855,6 +855,31 @@ static void badblocks_update_acked(struct badblocks *bb) + bb->unacked_exist = 0; + } + ++/* ++ * Return 'true' if the range indicated by 'bad' is exactly backward ++ * overlapped with the bad range (from bad table) indexed by 'behind'. ++ */ ++static bool try_adjacent_combine(struct badblocks *bb, int prev) ++{ ++ u64 *p = bb->page; ++ ++ if (prev >= 0 && (prev + 1) < bb->count && ++ BB_END(p[prev]) == BB_OFFSET(p[prev + 1]) && ++ (BB_LEN(p[prev]) + BB_LEN(p[prev + 1])) <= BB_MAX_LEN && ++ BB_ACK(p[prev]) == BB_ACK(p[prev + 1])) { ++ p[prev] = BB_MAKE(BB_OFFSET(p[prev]), ++ BB_LEN(p[prev]) + BB_LEN(p[prev + 1]), ++ BB_ACK(p[prev])); ++ ++ if ((prev + 2) < bb->count) ++ memmove(p + prev + 1, p + prev + 2, ++ (bb->count - (prev + 2)) * 8); ++ bb->count--; ++ return true; ++ } ++ return false; ++} ++ + /* Do exact work to set bad block range into the bad block table */ + static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + int acknowledged) +@@ -1022,20 +1047,7 @@ static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + * merged. (prev < 0) condition is not handled here, + * because it's already complicated enough. + */ +- if (prev >= 0 && +- (prev + 1) < bb->count && +- BB_END(p[prev]) == BB_OFFSET(p[prev + 1]) && +- (BB_LEN(p[prev]) + BB_LEN(p[prev + 1])) <= BB_MAX_LEN && +- BB_ACK(p[prev]) == BB_ACK(p[prev + 1])) { +- p[prev] = BB_MAKE(BB_OFFSET(p[prev]), +- BB_LEN(p[prev]) + BB_LEN(p[prev + 1]), +- BB_ACK(p[prev])); +- +- if ((prev + 2) < bb->count) +- memmove(p + prev + 1, p + prev + 2, +- (bb->count - (prev + 2)) * 8); +- bb->count--; +- } ++ try_adjacent_combine(bb, prev); + + if (space_desired && !badblocks_full(bb)) { + s = orig_start; +-- +2.39.5 + diff --git a/queue-6.14/badblocks-fix-error-shitf-ops.patch b/queue-6.14/badblocks-fix-error-shitf-ops.patch new file mode 100644 index 0000000000..d24d4344da --- /dev/null +++ b/queue-6.14/badblocks-fix-error-shitf-ops.patch @@ -0,0 +1,62 @@ +From 955b89957d1dca67c4a45cfb9b071dd65c4743a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 15:54:56 +0800 +Subject: badblocks: Fix error shitf ops + +From: Li Nan + +[ Upstream commit 7d83c5d73c1a3c7b71ba70d0ad2ae66e7a0e7ace ] + +'bb->shift' is used directly in badblocks. It is wrong, fix it. + +Fixes: 3ea3354cb9f0 ("badblocks: improve badblocks_check() for multiple ranges handling") +Signed-off-by: Li Nan +Reviewed-by: Yu Kuai +Acked-by: Coly Li +Link: https://lore.kernel.org/r/20250227075507.151331-2-zhengqixing@huaweicloud.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/badblocks.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/block/badblocks.c b/block/badblocks.c +index db4ec8b9b2a8c..bcee057efc476 100644 +--- a/block/badblocks.c ++++ b/block/badblocks.c +@@ -880,8 +880,8 @@ static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + /* round the start down, and the end up */ + sector_t next = s + sectors; + +- rounddown(s, bb->shift); +- roundup(next, bb->shift); ++ rounddown(s, 1 << bb->shift); ++ roundup(next, 1 << bb->shift); + sectors = next - s; + } + +@@ -1157,8 +1157,8 @@ static int _badblocks_clear(struct badblocks *bb, sector_t s, int sectors) + * isn't than to think a block is not bad when it is. + */ + target = s + sectors; +- roundup(s, bb->shift); +- rounddown(target, bb->shift); ++ roundup(s, 1 << bb->shift); ++ rounddown(target, 1 << bb->shift); + sectors = target - s; + } + +@@ -1288,8 +1288,8 @@ static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors, + + /* round the start down, and the end up */ + target = s + sectors; +- rounddown(s, bb->shift); +- roundup(target, bb->shift); ++ rounddown(s, 1 << bb->shift); ++ roundup(target, 1 << bb->shift); + sectors = target - s; + } + +-- +2.39.5 + diff --git a/queue-6.14/badblocks-fix-merge-issue-when-new-badblocks-align-w.patch b/queue-6.14/badblocks-fix-merge-issue-when-new-badblocks-align-w.patch new file mode 100644 index 0000000000..6572bb46cc --- /dev/null +++ b/queue-6.14/badblocks-fix-merge-issue-when-new-badblocks-align-w.patch @@ -0,0 +1,63 @@ +From 3b3b7cdbb75ea62ad0d91a8afd71e49c70ad7bbb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 15:55:03 +0800 +Subject: badblocks: fix merge issue when new badblocks align with pre+1 + +From: Li Nan + +[ Upstream commit 9ec65dec634a752ab0a1203510ee190356e4cf1a ] + +There is a merge issue when adding badblocks as follow: + echo 0 10 > bad_blocks + echo 30 10 > bad_blocks + echo 20 10 > bad_blocks + cat bad_blocks + 0 10 + 20 10 //should be merged with (30 10) + 30 10 + +In this case, if new badblocks does not intersect with prev, it is added +by insert_at(). If there is an intersection with prev+1, the merge will +be processed in the next re_insert loop. + +However, when the end of the new badblocks is exactly equal to the offset +of prev+1, no further re_insert loop occurs, and the two badblocks are not +merge. + +Fix it by inc prev, badblocks can be merged during the subsequent code. + +Fixes: aa511ff8218b ("badblocks: switch to the improved badblock handling code") +Signed-off-by: Li Nan +Reviewed-by: Yu Kuai +Link: https://lore.kernel.org/r/20250227075507.151331-9-zhengqixing@huaweicloud.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/badblocks.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/block/badblocks.c b/block/badblocks.c +index 43430bd3efa7d..52206a42191da 100644 +--- a/block/badblocks.c ++++ b/block/badblocks.c +@@ -892,7 +892,7 @@ static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + len = insert_at(bb, 0, &bad); + bb->count++; + added++; +- hint = 0; ++ hint = ++prev; + goto update_sectors; + } + +@@ -951,7 +951,7 @@ static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + len = insert_at(bb, prev + 1, &bad); + bb->count++; + added++; +- hint = prev + 1; ++ hint = ++prev; + + update_sectors: + s += len; +-- +2.39.5 + diff --git a/queue-6.14/badblocks-fix-missing-bad-blocks-on-retry-in-_badblo.patch b/queue-6.14/badblocks-fix-missing-bad-blocks-on-retry-in-_badblo.patch new file mode 100644 index 0000000000..449185d18c --- /dev/null +++ b/queue-6.14/badblocks-fix-missing-bad-blocks-on-retry-in-_badblo.patch @@ -0,0 +1,109 @@ +From dbfbef4a5143aa0e4c99f1e4aab9bf3896e82249 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 15:55:04 +0800 +Subject: badblocks: fix missing bad blocks on retry in _badblocks_check() + +From: Zheng Qixing + +[ Upstream commit 5236f041fa6c81c71eabad44897e54a0d6d5bbf6 ] + +The bad blocks check would miss bad blocks when retrying under contention, +as checking parameters are not reset. These stale values from the previous +attempt could lead to incorrect scanning in the subsequent retry. + +Move seqlock to outer function and reinitialize checking state for each +retry. This ensures a clean state for each check attempt, preventing any +missed bad blocks. + +Fixes: 3ea3354cb9f0 ("badblocks: improve badblocks_check() for multiple ranges handling") +Signed-off-by: Zheng Qixing +Reviewed-by: Yu Kuai +Acked-by: Coly Li +Link: https://lore.kernel.org/r/20250227075507.151331-10-zhengqixing@huaweicloud.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/badblocks.c | 50 +++++++++++++++++++++++------------------------ + 1 file changed, 24 insertions(+), 26 deletions(-) + +diff --git a/block/badblocks.c b/block/badblocks.c +index 52206a42191da..f84a35d683b1f 100644 +--- a/block/badblocks.c ++++ b/block/badblocks.c +@@ -1195,31 +1195,12 @@ static int _badblocks_clear(struct badblocks *bb, sector_t s, int sectors) + static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors, + sector_t *first_bad, int *bad_sectors) + { +- int unacked_badblocks, acked_badblocks; + int prev = -1, hint = -1, set = 0; + struct badblocks_context bad; +- unsigned int seq; ++ int unacked_badblocks = 0; ++ int acked_badblocks = 0; ++ u64 *p = bb->page; + int len, rv; +- u64 *p; +- +- WARN_ON(bb->shift < 0 || sectors == 0); +- +- if (bb->shift > 0) { +- sector_t target; +- +- /* round the start down, and the end up */ +- target = s + sectors; +- rounddown(s, 1 << bb->shift); +- roundup(target, 1 << bb->shift); +- sectors = target - s; +- } +- +-retry: +- seq = read_seqbegin(&bb->lock); +- +- p = bb->page; +- unacked_badblocks = 0; +- acked_badblocks = 0; + + re_check: + bad.start = s; +@@ -1285,9 +1266,6 @@ static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors, + else + rv = 0; + +- if (read_seqretry(&bb->lock, seq)) +- goto retry; +- + return rv; + } + +@@ -1328,7 +1306,27 @@ static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors, + int badblocks_check(struct badblocks *bb, sector_t s, int sectors, + sector_t *first_bad, int *bad_sectors) + { +- return _badblocks_check(bb, s, sectors, first_bad, bad_sectors); ++ unsigned int seq; ++ int rv; ++ ++ WARN_ON(bb->shift < 0 || sectors == 0); ++ ++ if (bb->shift > 0) { ++ /* round the start down, and the end up */ ++ sector_t target = s + sectors; ++ ++ rounddown(s, 1 << bb->shift); ++ roundup(target, 1 << bb->shift); ++ sectors = target - s; ++ } ++ ++retry: ++ seq = read_seqbegin(&bb->lock); ++ rv = _badblocks_check(bb, s, sectors, first_bad, bad_sectors); ++ if (read_seqretry(&bb->lock, seq)) ++ goto retry; ++ ++ return rv; + } + EXPORT_SYMBOL_GPL(badblocks_check); + +-- +2.39.5 + diff --git a/queue-6.14/badblocks-fix-the-using-of-max_badblocks.patch b/queue-6.14/badblocks-fix-the-using-of-max_badblocks.patch new file mode 100644 index 0000000000..0eb389ec9f --- /dev/null +++ b/queue-6.14/badblocks-fix-the-using-of-max_badblocks.patch @@ -0,0 +1,50 @@ +From 648c417665dc62406d88a32311eaf19ccd1ff154 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 15:55:01 +0800 +Subject: badblocks: fix the using of MAX_BADBLOCKS + +From: Li Nan + +[ Upstream commit 37446680dfbfbba7cbedd680047182f70a0b857b ] + +The number of badblocks cannot exceed MAX_BADBLOCKS, but it should be +allowed to equal MAX_BADBLOCKS. + +Fixes: aa511ff8218b ("badblocks: switch to the improved badblock handling code") +Fixes: c3c6a86e9efc ("badblocks: add helper routines for badblock ranges handling") +Signed-off-by: Li Nan +Reviewed-by: Zhu Yanjun +Reviewed-by: Yu Kuai +Acked-by: Coly Li +Link: https://lore.kernel.org/r/20250227075507.151331-7-zhengqixing@huaweicloud.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/badblocks.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/block/badblocks.c b/block/badblocks.c +index 88f27d4f38563..43430bd3efa7d 100644 +--- a/block/badblocks.c ++++ b/block/badblocks.c +@@ -700,7 +700,7 @@ static bool can_front_overwrite(struct badblocks *bb, int prev, + *extra = 2; + } + +- if ((bb->count + (*extra)) >= MAX_BADBLOCKS) ++ if ((bb->count + (*extra)) > MAX_BADBLOCKS) + return false; + + return true; +@@ -1135,7 +1135,7 @@ static int _badblocks_clear(struct badblocks *bb, sector_t s, int sectors) + if ((BB_OFFSET(p[prev]) < bad.start) && + (BB_END(p[prev]) > (bad.start + bad.len))) { + /* Splitting */ +- if ((bb->count + 1) < MAX_BADBLOCKS) { ++ if ((bb->count + 1) <= MAX_BADBLOCKS) { + len = front_splitting_clear(bb, prev, &bad); + bb->count += 1; + cleared++; +-- +2.39.5 + diff --git a/queue-6.14/badblocks-return-boolean-from-badblocks_set-and-badb.patch b/queue-6.14/badblocks-return-boolean-from-badblocks_set-and-badb.patch new file mode 100644 index 0000000000..c5fd32b764 --- /dev/null +++ b/queue-6.14/badblocks-return-boolean-from-badblocks_set-and-badb.patch @@ -0,0 +1,286 @@ +From 4a60d95cb3aa8a557e7bdf2cda4120c49b2b9541 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 15:55:05 +0800 +Subject: badblocks: return boolean from badblocks_set() and badblocks_clear() + +From: Zheng Qixing + +[ Upstream commit c8775aefba959cdfbaa25408a84d3dd15bbeb991 ] + +Change the return type of badblocks_set() and badblocks_clear() +from int to bool, indicating success or failure. Specifically: + +- _badblocks_set() and _badblocks_clear() functions now return +true for success and false for failure. +- All calls to these functions are updated to handle the new +boolean return type. +- This change improves code clarity and ensures a more consistent +handling of success and failure states. + +Signed-off-by: Zheng Qixing +Reviewed-by: Yu Kuai +Acked-by: Coly Li +Acked-by: Ira Weiny +Link: https://lore.kernel.org/r/20250227075507.151331-11-zhengqixing@huaweicloud.com +Signed-off-by: Jens Axboe +Stable-dep-of: d301f164c3fb ("badblocks: use sector_t instead of int to avoid truncation of badblocks length") +Signed-off-by: Sasha Levin +--- + block/badblocks.c | 41 +++++++++++++++++------------------ + drivers/block/null_blk/main.c | 14 ++++++------ + drivers/md/md.c | 35 +++++++++++++++--------------- + drivers/nvdimm/badrange.c | 2 +- + include/linux/badblocks.h | 6 ++--- + 5 files changed, 49 insertions(+), 49 deletions(-) + +diff --git a/block/badblocks.c b/block/badblocks.c +index f84a35d683b1f..753250a04c3fa 100644 +--- a/block/badblocks.c ++++ b/block/badblocks.c +@@ -836,8 +836,8 @@ static bool try_adjacent_combine(struct badblocks *bb, int prev) + } + + /* Do exact work to set bad block range into the bad block table */ +-static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, +- int acknowledged) ++static bool _badblocks_set(struct badblocks *bb, sector_t s, int sectors, ++ int acknowledged) + { + int len = 0, added = 0; + struct badblocks_context bad; +@@ -847,11 +847,11 @@ static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + + if (bb->shift < 0) + /* badblocks are disabled */ +- return 1; ++ return false; + + if (sectors == 0) + /* Invalid sectors number */ +- return 1; ++ return false; + + if (bb->shift) { + /* round the start down, and the end up */ +@@ -981,7 +981,7 @@ static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + + write_sequnlock_irqrestore(&bb->lock, flags); + +- return sectors; ++ return sectors == 0; + } + + /* +@@ -1052,21 +1052,20 @@ static int front_splitting_clear(struct badblocks *bb, int prev, + } + + /* Do the exact work to clear bad block range from the bad block table */ +-static int _badblocks_clear(struct badblocks *bb, sector_t s, int sectors) ++static bool _badblocks_clear(struct badblocks *bb, sector_t s, int sectors) + { + struct badblocks_context bad; + int prev = -1, hint = -1; + int len = 0, cleared = 0; +- int rv = 0; + u64 *p; + + if (bb->shift < 0) + /* badblocks are disabled */ +- return 1; ++ return false; + + if (sectors == 0) + /* Invalid sectors number */ +- return 1; ++ return false; + + if (bb->shift) { + sector_t target; +@@ -1186,9 +1185,9 @@ static int _badblocks_clear(struct badblocks *bb, sector_t s, int sectors) + write_sequnlock_irq(&bb->lock); + + if (!cleared) +- rv = 1; ++ return false; + +- return rv; ++ return true; + } + + /* Do the exact work to check bad blocks range from the bad block table */ +@@ -1342,12 +1341,12 @@ EXPORT_SYMBOL_GPL(badblocks_check); + * decide how best to handle it. + * + * Return: +- * 0: success +- * other: failed to set badblocks (out of space). Parital setting will be ++ * true: success ++ * false: failed to set badblocks (out of space). Parital setting will be + * treated as failure. + */ +-int badblocks_set(struct badblocks *bb, sector_t s, int sectors, +- int acknowledged) ++bool badblocks_set(struct badblocks *bb, sector_t s, int sectors, ++ int acknowledged) + { + return _badblocks_set(bb, s, sectors, acknowledged); + } +@@ -1364,10 +1363,10 @@ EXPORT_SYMBOL_GPL(badblocks_set); + * drop the remove request. + * + * Return: +- * 0: success +- * 1: failed to clear badblocks ++ * true: success ++ * false: failed to clear badblocks + */ +-int badblocks_clear(struct badblocks *bb, sector_t s, int sectors) ++bool badblocks_clear(struct badblocks *bb, sector_t s, int sectors) + { + return _badblocks_clear(bb, s, sectors); + } +@@ -1489,10 +1488,10 @@ ssize_t badblocks_store(struct badblocks *bb, const char *page, size_t len, + return -EINVAL; + } + +- if (badblocks_set(bb, sector, length, !unack)) ++ if (!badblocks_set(bb, sector, length, !unack)) + return -ENOSPC; +- else +- return len; ++ ++ return len; + } + EXPORT_SYMBOL_GPL(badblocks_store); + +diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c +index cca278f1d2ce7..f2a5f65abbf8b 100644 +--- a/drivers/block/null_blk/main.c ++++ b/drivers/block/null_blk/main.c +@@ -561,14 +561,14 @@ static ssize_t nullb_device_badblocks_store(struct config_item *item, + goto out; + /* enable badblocks */ + cmpxchg(&t_dev->badblocks.shift, -1, 0); +- if (buf[0] == '+') +- ret = badblocks_set(&t_dev->badblocks, start, +- end - start + 1, 1); +- else +- ret = badblocks_clear(&t_dev->badblocks, start, +- end - start + 1); +- if (ret == 0) ++ if (buf[0] == '+') { ++ if (badblocks_set(&t_dev->badblocks, start, ++ end - start + 1, 1)) ++ ret = count; ++ } else if (badblocks_clear(&t_dev->badblocks, start, ++ end - start + 1)) { + ret = count; ++ } + out: + kfree(orig); + return ret; +diff --git a/drivers/md/md.c b/drivers/md/md.c +index f501bc5f68f1a..ef859ccb03661 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -1754,7 +1754,7 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_ + count <<= sb->bblog_shift; + if (bb + 1 == 0) + break; +- if (badblocks_set(&rdev->badblocks, sector, count, 1)) ++ if (!badblocks_set(&rdev->badblocks, sector, count, 1)) + return -EINVAL; + } + } else if (sb->bblog_offset != 0) +@@ -9850,7 +9850,6 @@ int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors, + int is_new) + { + struct mddev *mddev = rdev->mddev; +- int rv; + + /* + * Recording new badblocks for faulty rdev will force unnecessary +@@ -9866,33 +9865,35 @@ int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors, + s += rdev->new_data_offset; + else + s += rdev->data_offset; +- rv = badblocks_set(&rdev->badblocks, s, sectors, 0); +- if (rv == 0) { +- /* Make sure they get written out promptly */ +- if (test_bit(ExternalBbl, &rdev->flags)) +- sysfs_notify_dirent_safe(rdev->sysfs_unack_badblocks); +- sysfs_notify_dirent_safe(rdev->sysfs_state); +- set_mask_bits(&mddev->sb_flags, 0, +- BIT(MD_SB_CHANGE_CLEAN) | BIT(MD_SB_CHANGE_PENDING)); +- md_wakeup_thread(rdev->mddev->thread); +- return 1; +- } else ++ ++ if (!badblocks_set(&rdev->badblocks, s, sectors, 0)) + return 0; ++ ++ /* Make sure they get written out promptly */ ++ if (test_bit(ExternalBbl, &rdev->flags)) ++ sysfs_notify_dirent_safe(rdev->sysfs_unack_badblocks); ++ sysfs_notify_dirent_safe(rdev->sysfs_state); ++ set_mask_bits(&mddev->sb_flags, 0, ++ BIT(MD_SB_CHANGE_CLEAN) | BIT(MD_SB_CHANGE_PENDING)); ++ md_wakeup_thread(rdev->mddev->thread); ++ return 1; + } + EXPORT_SYMBOL_GPL(rdev_set_badblocks); + + int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors, + int is_new) + { +- int rv; + if (is_new) + s += rdev->new_data_offset; + else + s += rdev->data_offset; +- rv = badblocks_clear(&rdev->badblocks, s, sectors); +- if ((rv == 0) && test_bit(ExternalBbl, &rdev->flags)) ++ ++ if (!badblocks_clear(&rdev->badblocks, s, sectors)) ++ return 0; ++ ++ if (test_bit(ExternalBbl, &rdev->flags)) + sysfs_notify_dirent_safe(rdev->sysfs_badblocks); +- return rv; ++ return 1; + } + EXPORT_SYMBOL_GPL(rdev_clear_badblocks); + +diff --git a/drivers/nvdimm/badrange.c b/drivers/nvdimm/badrange.c +index a002ea6fdd842..ee478ccde7c6c 100644 +--- a/drivers/nvdimm/badrange.c ++++ b/drivers/nvdimm/badrange.c +@@ -167,7 +167,7 @@ static void set_badblock(struct badblocks *bb, sector_t s, int num) + dev_dbg(bb->dev, "Found a bad range (0x%llx, 0x%llx)\n", + (u64) s * 512, (u64) num * 512); + /* this isn't an error as the hardware will still throw an exception */ +- if (badblocks_set(bb, s, num, 1)) ++ if (!badblocks_set(bb, s, num, 1)) + dev_info_once(bb->dev, "%s: failed for sector %llx\n", + __func__, (u64) s); + } +diff --git a/include/linux/badblocks.h b/include/linux/badblocks.h +index 670f2dae692fb..8764bed9ff167 100644 +--- a/include/linux/badblocks.h ++++ b/include/linux/badblocks.h +@@ -50,9 +50,9 @@ struct badblocks_context { + + int badblocks_check(struct badblocks *bb, sector_t s, int sectors, + sector_t *first_bad, int *bad_sectors); +-int badblocks_set(struct badblocks *bb, sector_t s, int sectors, +- int acknowledged); +-int badblocks_clear(struct badblocks *bb, sector_t s, int sectors); ++bool badblocks_set(struct badblocks *bb, sector_t s, int sectors, ++ int acknowledged); ++bool badblocks_clear(struct badblocks *bb, sector_t s, int sectors); + void ack_all_badblocks(struct badblocks *bb); + ssize_t badblocks_show(struct badblocks *bb, char *page, int unack); + ssize_t badblocks_store(struct badblocks *bb, const char *page, size_t len, +-- +2.39.5 + diff --git a/queue-6.14/badblocks-return-error-directly-when-setting-badbloc.patch b/queue-6.14/badblocks-return-error-directly-when-setting-badbloc.patch new file mode 100644 index 0000000000..c254571d09 --- /dev/null +++ b/queue-6.14/badblocks-return-error-directly-when-setting-badbloc.patch @@ -0,0 +1,226 @@ +From 4efb86ce993cdf6d54e085c0d37c470469c68932 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 15:54:59 +0800 +Subject: badblocks: return error directly when setting badblocks exceeds 512 + +From: Li Nan + +[ Upstream commit 28243dcd1f49cc8be398a1396d16a45527882ce5 ] + +In the current handling of badblocks settings, a lot of processing has +been done for scenarios where the number of badblocks exceeds 512. +This makes the code look quite complex and also introduces some issues, + +For example, if there is 512 badblocks already: + for((i=0; i<510; i++)); do ((sector=i*2)); echo "$sector 1" > bad_blocks; done + echo 2100 10 > bad_blocks + echo 2200 10 > bad_blocks +Set new one, exceed 512: + echo 2000 500 > bad_blocks +Expected: + 2000 500 +Actual: + 2100 400 + +In fact, a disk shouldn't have too many badblocks, and for disks with +512 badblocks, attempting to set more bad blocks doesn't make much sense. +At that point, the more appropriate action would be to replace the disk. +Therefore, to resolve these issues and simplify the code somewhat, return +error directly when setting badblocks exceeds 512. + +Fixes: aa511ff8218b ("badblocks: switch to the improved badblock handling code") +Signed-off-by: Li Nan +Reviewed-by: Yu Kuai +Link: https://lore.kernel.org/r/20250227075507.151331-5-zhengqixing@huaweicloud.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/badblocks.c | 121 ++++++++-------------------------------------- + 1 file changed, 19 insertions(+), 102 deletions(-) + +diff --git a/block/badblocks.c b/block/badblocks.c +index ad8652fbe1c8f..1c8b8f65f6df4 100644 +--- a/block/badblocks.c ++++ b/block/badblocks.c +@@ -527,51 +527,6 @@ static int prev_badblocks(struct badblocks *bb, struct badblocks_context *bad, + return ret; + } + +-/* +- * Return 'true' if the range indicated by 'bad' can be backward merged +- * with the bad range (from the bad table) index by 'behind'. +- */ +-static bool can_merge_behind(struct badblocks *bb, +- struct badblocks_context *bad, int behind) +-{ +- sector_t sectors = bad->len; +- sector_t s = bad->start; +- u64 *p = bb->page; +- +- if ((s < BB_OFFSET(p[behind])) && +- ((s + sectors) >= BB_OFFSET(p[behind])) && +- ((BB_END(p[behind]) - s) <= BB_MAX_LEN) && +- BB_ACK(p[behind]) == bad->ack) +- return true; +- return false; +-} +- +-/* +- * Do backward merge for range indicated by 'bad' and the bad range +- * (from the bad table) indexed by 'behind'. The return value is merged +- * sectors from bad->len. +- */ +-static int behind_merge(struct badblocks *bb, struct badblocks_context *bad, +- int behind) +-{ +- sector_t sectors = bad->len; +- sector_t s = bad->start; +- u64 *p = bb->page; +- int merged = 0; +- +- WARN_ON(s >= BB_OFFSET(p[behind])); +- WARN_ON((s + sectors) < BB_OFFSET(p[behind])); +- +- if (s < BB_OFFSET(p[behind])) { +- merged = BB_OFFSET(p[behind]) - s; +- p[behind] = BB_MAKE(s, BB_LEN(p[behind]) + merged, bad->ack); +- +- WARN_ON((BB_LEN(p[behind]) + merged) >= BB_MAX_LEN); +- } +- +- return merged; +-} +- + /* + * Return 'true' if the range indicated by 'bad' can be forward + * merged with the bad range (from the bad table) indexed by 'prev'. +@@ -884,11 +839,9 @@ static bool try_adjacent_combine(struct badblocks *bb, int prev) + static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + int acknowledged) + { +- int retried = 0, space_desired = 0; +- int orig_len, len = 0, added = 0; ++ int len = 0, added = 0; + struct badblocks_context bad; + int prev = -1, hint = -1; +- sector_t orig_start; + unsigned long flags; + int rv = 0; + u64 *p; +@@ -912,8 +865,6 @@ static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + + write_seqlock_irqsave(&bb->lock, flags); + +- orig_start = s; +- orig_len = sectors; + bad.ack = acknowledged; + p = bb->page; + +@@ -922,6 +873,11 @@ static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + bad.len = sectors; + len = 0; + ++ if (badblocks_full(bb)) { ++ rv = 1; ++ goto out; ++ } ++ + if (badblocks_empty(bb)) { + len = insert_at(bb, 0, &bad); + bb->count++; +@@ -933,32 +889,14 @@ static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + + /* start before all badblocks */ + if (prev < 0) { +- if (!badblocks_full(bb)) { +- /* insert on the first */ +- if (bad.len > (BB_OFFSET(p[0]) - bad.start)) +- bad.len = BB_OFFSET(p[0]) - bad.start; +- len = insert_at(bb, 0, &bad); +- bb->count++; +- added++; +- hint = 0; +- goto update_sectors; +- } +- +- /* No sapce, try to merge */ +- if (overlap_behind(bb, &bad, 0)) { +- if (can_merge_behind(bb, &bad, 0)) { +- len = behind_merge(bb, &bad, 0); +- added++; +- } else { +- len = BB_OFFSET(p[0]) - s; +- space_desired = 1; +- } +- hint = 0; +- goto update_sectors; +- } +- +- /* no table space and give up */ +- goto out; ++ /* insert on the first */ ++ if (bad.len > (BB_OFFSET(p[0]) - bad.start)) ++ bad.len = BB_OFFSET(p[0]) - bad.start; ++ len = insert_at(bb, 0, &bad); ++ bb->count++; ++ added++; ++ hint = 0; ++ goto update_sectors; + } + + /* in case p[prev-1] can be merged with p[prev] */ +@@ -978,6 +916,11 @@ static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + int extra = 0; + + if (!can_front_overwrite(bb, prev, &bad, &extra)) { ++ if (extra > 0) { ++ rv = 1; ++ goto out; ++ } ++ + len = min_t(sector_t, + BB_END(p[prev]) - s, sectors); + hint = prev; +@@ -1004,24 +947,6 @@ static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + goto update_sectors; + } + +- /* if no space in table, still try to merge in the covered range */ +- if (badblocks_full(bb)) { +- /* skip the cannot-merge range */ +- if (((prev + 1) < bb->count) && +- overlap_behind(bb, &bad, prev + 1) && +- ((s + sectors) >= BB_END(p[prev + 1]))) { +- len = BB_END(p[prev + 1]) - s; +- hint = prev + 1; +- goto update_sectors; +- } +- +- /* no retry any more */ +- len = sectors; +- space_desired = 1; +- hint = -1; +- goto update_sectors; +- } +- + /* cannot merge and there is space in bad table */ + if ((prev + 1) < bb->count && + overlap_behind(bb, &bad, prev + 1)) +@@ -1049,14 +974,6 @@ static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + */ + try_adjacent_combine(bb, prev); + +- if (space_desired && !badblocks_full(bb)) { +- s = orig_start; +- sectors = orig_len; +- space_desired = 0; +- if (retried++ < 3) +- goto re_insert; +- } +- + out: + if (added) { + set_changed(bb); +-- +2.39.5 + diff --git a/queue-6.14/badblocks-return-error-if-any-badblock-set-fails.patch b/queue-6.14/badblocks-return-error-if-any-badblock-set-fails.patch new file mode 100644 index 0000000000..9e18a93e5e --- /dev/null +++ b/queue-6.14/badblocks-return-error-if-any-badblock-set-fails.patch @@ -0,0 +1,104 @@ +From 3c0b44827a70392da241d2feee74aa0e5e5d7ff8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 15:55:00 +0800 +Subject: badblocks: return error if any badblock set fails +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Li Nan + +[ Upstream commit 7f500f0a59b1d7345a05ec4ae703babf34b7e470 ] + +_badblocks_set() returns success if at least one badblock is set +successfully, even if others fail. This can lead to data inconsistencies +in raid, where a failed badblock set should trigger the disk to be kicked +out to prevent future reads from failed write areas. + +_badblocks_set() should return error if any badblock set fails. Instead +of relying on 'rv', directly returning 'sectors' for clearer logic. If all +badblocks are successfully set, 'sectors' will be 0, otherwise it +indicates the number of badblocks that have not been set yet, thus +signaling failure. + +By the way, it can also fix an issue: when a newly set unack badblock is +included in an existing ack badblock, the setting will return an error. +··· + echo "0 100" /sys/block/md0/md/dev-loop1/bad_blocks + echo "0 100" /sys/block/md0/md/dev-loop1/unacknowledged_bad_blocks + -bash: echo: write error: No space left on device +``` +After fix, it will return success. + +Fixes: aa511ff8218b ("badblocks: switch to the improved badblock handling code") +Signed-off-by: Li Nan +Reviewed-by: Yu Kuai +Acked-by: Coly Li +Link: https://lore.kernel.org/r/20250227075507.151331-6-zhengqixing@huaweicloud.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/badblocks.c | 17 +++++------------ + 1 file changed, 5 insertions(+), 12 deletions(-) + +diff --git a/block/badblocks.c b/block/badblocks.c +index 1c8b8f65f6df4..88f27d4f38563 100644 +--- a/block/badblocks.c ++++ b/block/badblocks.c +@@ -843,7 +843,6 @@ static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + struct badblocks_context bad; + int prev = -1, hint = -1; + unsigned long flags; +- int rv = 0; + u64 *p; + + if (bb->shift < 0) +@@ -873,10 +872,8 @@ static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + bad.len = sectors; + len = 0; + +- if (badblocks_full(bb)) { +- rv = 1; ++ if (badblocks_full(bb)) + goto out; +- } + + if (badblocks_empty(bb)) { + len = insert_at(bb, 0, &bad); +@@ -916,10 +913,8 @@ static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + int extra = 0; + + if (!can_front_overwrite(bb, prev, &bad, &extra)) { +- if (extra > 0) { +- rv = 1; ++ if (extra > 0) + goto out; +- } + + len = min_t(sector_t, + BB_END(p[prev]) - s, sectors); +@@ -986,10 +981,7 @@ static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + + write_sequnlock_irqrestore(&bb->lock, flags); + +- if (!added) +- rv = 1; +- +- return rv; ++ return sectors; + } + + /* +@@ -1353,7 +1345,8 @@ EXPORT_SYMBOL_GPL(badblocks_check); + * + * Return: + * 0: success +- * 1: failed to set badblocks (out of space) ++ * other: failed to set badblocks (out of space). Parital setting will be ++ * treated as failure. + */ + int badblocks_set(struct badblocks *bb, sector_t s, int sectors, + int acknowledged) +-- +2.39.5 + diff --git a/queue-6.14/badblocks-use-sector_t-instead-of-int-to-avoid-trunc.patch b/queue-6.14/badblocks-use-sector_t-instead-of-int-to-avoid-trunc.patch new file mode 100644 index 0000000000..a7baea350b --- /dev/null +++ b/queue-6.14/badblocks-use-sector_t-instead-of-int-to-avoid-trunc.patch @@ -0,0 +1,319 @@ +From b8dfd8b712cd178fcba07d17a0ca14ee03654c84 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 15:55:07 +0800 +Subject: badblocks: use sector_t instead of int to avoid truncation of + badblocks length + +From: Zheng Qixing + +[ Upstream commit d301f164c3fbff611bd71f57dfa553b9219f0f5e ] + +There is a truncation of badblocks length issue when set badblocks as +follow: + +echo "2055 4294967299" > bad_blocks +cat bad_blocks +2055 3 + +Change 'sectors' argument type from 'int' to 'sector_t'. + +This change avoids truncation of badblocks length for large sectors by +replacing 'int' with 'sector_t' (u64), enabling proper handling of larger +disk sizes and ensuring compatibility with 64-bit sector addressing. + +Fixes: 9e0e252a048b ("badblocks: Add core badblock management code") +Signed-off-by: Zheng Qixing +Reviewed-by: Yu Kuai +Acked-by: Coly Li +Link: https://lore.kernel.org/r/20250227075507.151331-13-zhengqixing@huaweicloud.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/badblocks.c | 20 ++++++++------------ + drivers/block/null_blk/main.c | 3 +-- + drivers/md/md.h | 6 +++--- + drivers/md/raid1-10.c | 2 +- + drivers/md/raid1.c | 4 ++-- + drivers/md/raid10.c | 8 ++++---- + drivers/nvdimm/nd.h | 2 +- + drivers/nvdimm/pfn_devs.c | 7 ++++--- + drivers/nvdimm/pmem.c | 2 +- + include/linux/badblocks.h | 8 ++++---- + 10 files changed, 29 insertions(+), 33 deletions(-) + +diff --git a/block/badblocks.c b/block/badblocks.c +index 753250a04c3fa..dc147c0179612 100644 +--- a/block/badblocks.c ++++ b/block/badblocks.c +@@ -836,7 +836,7 @@ static bool try_adjacent_combine(struct badblocks *bb, int prev) + } + + /* Do exact work to set bad block range into the bad block table */ +-static bool _badblocks_set(struct badblocks *bb, sector_t s, int sectors, ++static bool _badblocks_set(struct badblocks *bb, sector_t s, sector_t sectors, + int acknowledged) + { + int len = 0, added = 0; +@@ -960,8 +960,6 @@ static bool _badblocks_set(struct badblocks *bb, sector_t s, int sectors, + if (sectors > 0) + goto re_insert; + +- WARN_ON(sectors < 0); +- + /* + * Check whether the following already set range can be + * merged. (prev < 0) condition is not handled here, +@@ -1052,7 +1050,7 @@ static int front_splitting_clear(struct badblocks *bb, int prev, + } + + /* Do the exact work to clear bad block range from the bad block table */ +-static bool _badblocks_clear(struct badblocks *bb, sector_t s, int sectors) ++static bool _badblocks_clear(struct badblocks *bb, sector_t s, sector_t sectors) + { + struct badblocks_context bad; + int prev = -1, hint = -1; +@@ -1175,8 +1173,6 @@ static bool _badblocks_clear(struct badblocks *bb, sector_t s, int sectors) + if (sectors > 0) + goto re_clear; + +- WARN_ON(sectors < 0); +- + if (cleared) { + badblocks_update_acked(bb); + set_changed(bb); +@@ -1191,8 +1187,8 @@ static bool _badblocks_clear(struct badblocks *bb, sector_t s, int sectors) + } + + /* Do the exact work to check bad blocks range from the bad block table */ +-static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors, +- sector_t *first_bad, int *bad_sectors) ++static int _badblocks_check(struct badblocks *bb, sector_t s, sector_t sectors, ++ sector_t *first_bad, sector_t *bad_sectors) + { + int prev = -1, hint = -1, set = 0; + struct badblocks_context bad; +@@ -1302,8 +1298,8 @@ static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors, + * -1: there are bad blocks which have not yet been acknowledged in metadata. + * plus the start/length of the first bad section we overlap. + */ +-int badblocks_check(struct badblocks *bb, sector_t s, int sectors, +- sector_t *first_bad, int *bad_sectors) ++int badblocks_check(struct badblocks *bb, sector_t s, sector_t sectors, ++ sector_t *first_bad, sector_t *bad_sectors) + { + unsigned int seq; + int rv; +@@ -1345,7 +1341,7 @@ EXPORT_SYMBOL_GPL(badblocks_check); + * false: failed to set badblocks (out of space). Parital setting will be + * treated as failure. + */ +-bool badblocks_set(struct badblocks *bb, sector_t s, int sectors, ++bool badblocks_set(struct badblocks *bb, sector_t s, sector_t sectors, + int acknowledged) + { + return _badblocks_set(bb, s, sectors, acknowledged); +@@ -1366,7 +1362,7 @@ EXPORT_SYMBOL_GPL(badblocks_set); + * true: success + * false: failed to clear badblocks + */ +-bool badblocks_clear(struct badblocks *bb, sector_t s, int sectors) ++bool badblocks_clear(struct badblocks *bb, sector_t s, sector_t sectors) + { + return _badblocks_clear(bb, s, sectors); + } +diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c +index f2a5f65abbf8b..59a10b0d122ce 100644 +--- a/drivers/block/null_blk/main.c ++++ b/drivers/block/null_blk/main.c +@@ -1327,8 +1327,7 @@ blk_status_t null_handle_badblocks(struct nullb_cmd *cmd, sector_t sector, + struct badblocks *bb = &cmd->nq->dev->badblocks; + struct nullb_device *dev = cmd->nq->dev; + unsigned int block_sectors = dev->blocksize >> SECTOR_SHIFT; +- sector_t first_bad; +- int bad_sectors; ++ sector_t first_bad, bad_sectors; + unsigned int partial_io_sectors = 0; + + if (!badblocks_check(bb, sector, *nr_sectors, &first_bad, &bad_sectors)) +diff --git a/drivers/md/md.h b/drivers/md/md.h +index def808064ad8e..cc31c795369da 100644 +--- a/drivers/md/md.h ++++ b/drivers/md/md.h +@@ -266,8 +266,8 @@ enum flag_bits { + Nonrot, /* non-rotational device (SSD) */ + }; + +-static inline int is_badblock(struct md_rdev *rdev, sector_t s, int sectors, +- sector_t *first_bad, int *bad_sectors) ++static inline int is_badblock(struct md_rdev *rdev, sector_t s, sector_t sectors, ++ sector_t *first_bad, sector_t *bad_sectors) + { + if (unlikely(rdev->badblocks.count)) { + int rv = badblocks_check(&rdev->badblocks, rdev->data_offset + s, +@@ -284,7 +284,7 @@ static inline int rdev_has_badblock(struct md_rdev *rdev, sector_t s, + int sectors) + { + sector_t first_bad; +- int bad_sectors; ++ sector_t bad_sectors; + + return is_badblock(rdev, s, sectors, &first_bad, &bad_sectors); + } +diff --git a/drivers/md/raid1-10.c b/drivers/md/raid1-10.c +index 4378d3250bd75..62b980b12f93a 100644 +--- a/drivers/md/raid1-10.c ++++ b/drivers/md/raid1-10.c +@@ -247,7 +247,7 @@ static inline int raid1_check_read_range(struct md_rdev *rdev, + sector_t this_sector, int *len) + { + sector_t first_bad; +- int bad_sectors; ++ sector_t bad_sectors; + + /* no bad block overlap */ + if (!is_badblock(rdev, this_sector, *len, &first_bad, &bad_sectors)) +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 44dcfebff4f03..15829ab192d2b 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -1535,7 +1535,7 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, + atomic_inc(&rdev->nr_pending); + if (test_bit(WriteErrorSeen, &rdev->flags)) { + sector_t first_bad; +- int bad_sectors; ++ sector_t bad_sectors; + int is_bad; + + is_bad = is_badblock(rdev, r1_bio->sector, max_sectors, +@@ -2882,7 +2882,7 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr, + } else { + /* may need to read from here */ + sector_t first_bad = MaxSector; +- int bad_sectors; ++ sector_t bad_sectors; + + if (is_badblock(rdev, sector_nr, good_sectors, + &first_bad, &bad_sectors)) { +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index 918a09f0ddd45..af010b64be63b 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -747,7 +747,7 @@ static struct md_rdev *read_balance(struct r10conf *conf, + + for (slot = 0; slot < conf->copies ; slot++) { + sector_t first_bad; +- int bad_sectors; ++ sector_t bad_sectors; + sector_t dev_sector; + unsigned int pending; + bool nonrot; +@@ -1430,7 +1430,7 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio, + if (rdev && test_bit(WriteErrorSeen, &rdev->flags)) { + sector_t first_bad; + sector_t dev_sector = r10_bio->devs[i].addr; +- int bad_sectors; ++ sector_t bad_sectors; + int is_bad; + + is_bad = is_badblock(rdev, dev_sector, max_sectors, +@@ -3404,7 +3404,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, + sector_t from_addr, to_addr; + struct md_rdev *rdev = conf->mirrors[d].rdev; + sector_t sector, first_bad; +- int bad_sectors; ++ sector_t bad_sectors; + if (!rdev || + !test_bit(In_sync, &rdev->flags)) + continue; +@@ -3600,7 +3600,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, + for (i = 0; i < conf->copies; i++) { + int d = r10_bio->devs[i].devnum; + sector_t first_bad, sector; +- int bad_sectors; ++ sector_t bad_sectors; + struct md_rdev *rdev; + + if (r10_bio->devs[i].repl_bio) +diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h +index 5ca06e9a2d292..cc5c8f3f81e8d 100644 +--- a/drivers/nvdimm/nd.h ++++ b/drivers/nvdimm/nd.h +@@ -673,7 +673,7 @@ static inline bool is_bad_pmem(struct badblocks *bb, sector_t sector, + { + if (bb->count) { + sector_t first_bad; +- int num_bad; ++ sector_t num_bad; + + return !!badblocks_check(bb, sector, len / 512, &first_bad, + &num_bad); +diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c +index cfdfe0eaa5121..8f3e816e805d8 100644 +--- a/drivers/nvdimm/pfn_devs.c ++++ b/drivers/nvdimm/pfn_devs.c +@@ -367,9 +367,10 @@ static int nd_pfn_clear_memmap_errors(struct nd_pfn *nd_pfn) + struct nd_namespace_common *ndns = nd_pfn->ndns; + void *zero_page = page_address(ZERO_PAGE(0)); + struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb; +- int num_bad, meta_num, rc, bb_present; ++ int meta_num, rc, bb_present; + sector_t first_bad, meta_start; + struct nd_namespace_io *nsio; ++ sector_t num_bad; + + if (nd_pfn->mode != PFN_MODE_PMEM) + return 0; +@@ -394,7 +395,7 @@ static int nd_pfn_clear_memmap_errors(struct nd_pfn *nd_pfn) + bb_present = badblocks_check(&nd_region->bb, meta_start, + meta_num, &first_bad, &num_bad); + if (bb_present) { +- dev_dbg(&nd_pfn->dev, "meta: %x badblocks at %llx\n", ++ dev_dbg(&nd_pfn->dev, "meta: %llx badblocks at %llx\n", + num_bad, first_bad); + nsoff = ALIGN_DOWN((nd_region->ndr_start + + (first_bad << 9)) - nsio->res.start, +@@ -413,7 +414,7 @@ static int nd_pfn_clear_memmap_errors(struct nd_pfn *nd_pfn) + } + if (rc) { + dev_err(&nd_pfn->dev, +- "error clearing %x badblocks at %llx\n", ++ "error clearing %llx badblocks at %llx\n", + num_bad, first_bad); + return rc; + } +diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c +index d81faa9d89c93..43156e1576c93 100644 +--- a/drivers/nvdimm/pmem.c ++++ b/drivers/nvdimm/pmem.c +@@ -249,7 +249,7 @@ __weak long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff, + unsigned int num = PFN_PHYS(nr_pages) >> SECTOR_SHIFT; + struct badblocks *bb = &pmem->bb; + sector_t first_bad; +- int num_bad; ++ sector_t num_bad; + + if (kaddr) + *kaddr = pmem->virt_addr + offset; +diff --git a/include/linux/badblocks.h b/include/linux/badblocks.h +index 8764bed9ff167..996493917f366 100644 +--- a/include/linux/badblocks.h ++++ b/include/linux/badblocks.h +@@ -48,11 +48,11 @@ struct badblocks_context { + int ack; + }; + +-int badblocks_check(struct badblocks *bb, sector_t s, int sectors, +- sector_t *first_bad, int *bad_sectors); +-bool badblocks_set(struct badblocks *bb, sector_t s, int sectors, ++int badblocks_check(struct badblocks *bb, sector_t s, sector_t sectors, ++ sector_t *first_bad, sector_t *bad_sectors); ++bool badblocks_set(struct badblocks *bb, sector_t s, sector_t sectors, + int acknowledged); +-bool badblocks_clear(struct badblocks *bb, sector_t s, int sectors); ++bool badblocks_clear(struct badblocks *bb, sector_t s, sector_t sectors); + void ack_all_badblocks(struct badblocks *bb); + ssize_t badblocks_show(struct badblocks *bb, char *page, int unack); + ssize_t badblocks_store(struct badblocks *bb, const char *page, size_t len, +-- +2.39.5 + diff --git a/queue-6.14/blk-throttle-fix-lower-bps-rate-by-throtl_trim_slice.patch b/queue-6.14/blk-throttle-fix-lower-bps-rate-by-throtl_trim_slice.patch new file mode 100644 index 0000000000..cb1e0d0ae5 --- /dev/null +++ b/queue-6.14/blk-throttle-fix-lower-bps-rate-by-throtl_trim_slice.patch @@ -0,0 +1,105 @@ +From 1507addf84feaf50d438a531d5909833a478319b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 20:06:45 +0800 +Subject: blk-throttle: fix lower bps rate by throtl_trim_slice() + +From: Yu Kuai + +[ Upstream commit 29cb955934302a5da525db6b327c795572538426 ] + +The bio submission time may be a few jiffies more than the expected +waiting time, due to 'extra_bytes' can't be divided in +tg_within_bps_limit(), and also due to timer wakeup delay. +In this case, adjust slice_start to jiffies will discard the extra wait time, +causing lower rate than expected. + +Current in-tree code already covers deviation by rounddown(), but turns +out it is not enough, because jiffies - slice_start can be a multiple of +throtl_slice. + +For example, assume bps_limit is 1000bytes, 1 jiffes is 10ms, and +slice is 20ms(2 jiffies), expected rate is 1000 / 1000 * 20 = 20 bytes +per slice. + +If user issues two 21 bytes IO, then wait time will be 30ms for the +first IO: + +bytes_allowed = 20, extra_bytes = 1; +jiffy_wait = 1 + 2 = 3 jiffies + +and consider +extra 1 jiffies by timer, throtl_trim_slice() will be called at: + +jiffies = 40ms +slice_start = 0ms, slice_end= 40ms +bytes_disp = 21 + +In this case, before the patch, real rate in the first two slices is +10.5 bytes per slice, and slice will be updated to: + +jiffies = 40ms +slice_start = 40ms, slice_end = 60ms, +bytes_disp = 0; + +Hence the second IO will have to wait another 30ms; + +With the patch, the real rate in the first slice is 20 bytes per slice, +which is the same as expected, and slice will be updated: + +jiffies=40ms, +slice_start = 20ms, slice_end = 60ms, +bytes_disp = 1; + +And now, there is still 19 bytes allowed in the second slice, and the +second IO will only have to wait 10ms; + +This problem will cause blktests throtl/001 failure in case of +CONFIG_HZ_100=y, fix it by preserving one extra finished slice in +throtl_trim_slice(). + +Fixes: e43473b7f223 ("blkio: Core implementation of throttle policy") +Reported-by: Ming Lei +Closes: https://lore.kernel.org/linux-block/20250222092823.210318-3-yukuai1@huaweicloud.com/ +Reviewed-by: Ming Lei +Acked-by: Tejun Heo +Signed-off-by: Yu Kuai +Link: https://lore.kernel.org/r/20250227120645.812815-1-yukuai1@huaweicloud.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-throttle.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/block/blk-throttle.c b/block/blk-throttle.c +index 8d149aff9fd0b..a52f0d6b40ad4 100644 +--- a/block/blk-throttle.c ++++ b/block/blk-throttle.c +@@ -599,14 +599,23 @@ static inline void throtl_trim_slice(struct throtl_grp *tg, bool rw) + * sooner, then we need to reduce slice_end. A high bogus slice_end + * is bad because it does not allow new slice to start. + */ +- + throtl_set_slice_end(tg, rw, jiffies + tg->td->throtl_slice); + + time_elapsed = rounddown(jiffies - tg->slice_start[rw], + tg->td->throtl_slice); +- if (!time_elapsed) ++ /* Don't trim slice until at least 2 slices are used */ ++ if (time_elapsed < tg->td->throtl_slice * 2) + return; + ++ /* ++ * The bio submission time may be a few jiffies more than the expected ++ * waiting time, due to 'extra_bytes' can't be divided in ++ * tg_within_bps_limit(), and also due to timer wakeup delay. In this ++ * case, adjust slice_start will discard the extra wait time, causing ++ * lower rate than expected. Therefore, other than the above rounddown, ++ * one extra slice is preserved for deviation. ++ */ ++ time_elapsed -= tg->td->throtl_slice; + bytes_trim = calculate_bytes_allowed(tg_bps_limit(tg, rw), + time_elapsed) + + tg->carryover_bytes[rw]; +-- +2.39.5 + diff --git a/queue-6.14/block-correctly-initialize-blk_integrity_nogenerate-.patch b/queue-6.14/block-correctly-initialize-blk_integrity_nogenerate-.patch new file mode 100644 index 0000000000..d595f87ce7 --- /dev/null +++ b/queue-6.14/block-correctly-initialize-blk_integrity_nogenerate-.patch @@ -0,0 +1,43 @@ +From 7a8cc2ea6f1877a2779ab00a7218ff09bfd65484 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 12:00:33 +0530 +Subject: block: Correctly initialize BLK_INTEGRITY_NOGENERATE and + BLK_INTEGRITY_NOVERIFY + +From: Anuj Gupta + +[ Upstream commit 85f72925000e924291a0ebf63d2234994a4f22bd ] + +Currently, BLK_INTEGRITY_NOGENERATE and BLK_INTEGRITY_NOVERIFY are not +explicitly set during integrity initialization. This can lead to +incorrect reporting of read_verify and write_generate sysfs values, +particularly when a device does not support integrity. Ensure that these +flags are correctly initialized by default. + +Reported-by: M Nikhil +Link: https://lore.kernel.org/linux-block/f6130475-3ccd-45d2-abde-3ccceada0f0a@linux.ibm.com/ +Fixes: 9f4aa46f2a74 ("block: invert the BLK_INTEGRITY_{GENERATE,VERIFY} flags") +Signed-off-by: Anuj Gupta +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/20250305063033.1813-3-anuj20.g@samsung.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-settings.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/block/blk-settings.c b/block/blk-settings.c +index 0b0641fa33c02..66721afeea546 100644 +--- a/block/blk-settings.c ++++ b/block/blk-settings.c +@@ -114,6 +114,7 @@ static int blk_validate_integrity_limits(struct queue_limits *lim) + pr_warn("invalid PI settings.\n"); + return -EINVAL; + } ++ bi->flags |= BLK_INTEGRITY_NOGENERATE | BLK_INTEGRITY_NOVERIFY; + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/block-ensure-correct-integrity-capability-propagatio.patch b/queue-6.14/block-ensure-correct-integrity-capability-propagatio.patch new file mode 100644 index 0000000000..e9d8ef14bd --- /dev/null +++ b/queue-6.14/block-ensure-correct-integrity-capability-propagatio.patch @@ -0,0 +1,94 @@ +From 71f0afd75f0f73e37df7b7bb1e5c18901dc29cb5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 12:00:32 +0530 +Subject: block: ensure correct integrity capability propagation in stacked + devices + +From: Anuj Gupta + +[ Upstream commit 677e332e4885a17def5efa4788b6e725a737b63c ] + +queue_limits_stack_integrity() incorrectly sets +BLK_INTEGRITY_DEVICE_CAPABLE for a DM device even when none of its +underlying devices support integrity. This happens because the flag is +inherited unconditionally. Ensure that integrity capabilities are +correctly propagated only when the underlying devices actually support +integrity. + +Reported-by: M Nikhil +Link: https://lore.kernel.org/linux-block/f6130475-3ccd-45d2-abde-3ccceada0f0a@linux.ibm.com/ +Fixes: c6e56cf6b2e7 ("block: move integrity information into queue_limits") +Signed-off-by: Anuj Gupta +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/20250305063033.1813-2-anuj20.g@samsung.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-settings.c | 50 +++++++++++++++++++------------------------- + 1 file changed, 21 insertions(+), 29 deletions(-) + +diff --git a/block/blk-settings.c b/block/blk-settings.c +index b9c6f0ec1c499..0b0641fa33c02 100644 +--- a/block/blk-settings.c ++++ b/block/blk-settings.c +@@ -867,36 +867,28 @@ bool queue_limits_stack_integrity(struct queue_limits *t, + if (!IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY)) + return true; + +- if (!ti->tuple_size) { +- /* inherit the settings from the first underlying device */ +- if (!(ti->flags & BLK_INTEGRITY_STACKED)) { +- ti->flags = BLK_INTEGRITY_DEVICE_CAPABLE | +- (bi->flags & BLK_INTEGRITY_REF_TAG); +- ti->csum_type = bi->csum_type; +- ti->tuple_size = bi->tuple_size; +- ti->pi_offset = bi->pi_offset; +- ti->interval_exp = bi->interval_exp; +- ti->tag_size = bi->tag_size; +- goto done; +- } +- if (!bi->tuple_size) +- goto done; ++ if (ti->flags & BLK_INTEGRITY_STACKED) { ++ if (ti->tuple_size != bi->tuple_size) ++ goto incompatible; ++ if (ti->interval_exp != bi->interval_exp) ++ goto incompatible; ++ if (ti->tag_size != bi->tag_size) ++ goto incompatible; ++ if (ti->csum_type != bi->csum_type) ++ goto incompatible; ++ if ((ti->flags & BLK_INTEGRITY_REF_TAG) != ++ (bi->flags & BLK_INTEGRITY_REF_TAG)) ++ goto incompatible; ++ } else { ++ ti->flags = BLK_INTEGRITY_STACKED; ++ ti->flags |= (bi->flags & BLK_INTEGRITY_DEVICE_CAPABLE) | ++ (bi->flags & BLK_INTEGRITY_REF_TAG); ++ ti->csum_type = bi->csum_type; ++ ti->tuple_size = bi->tuple_size; ++ ti->pi_offset = bi->pi_offset; ++ ti->interval_exp = bi->interval_exp; ++ ti->tag_size = bi->tag_size; + } +- +- if (ti->tuple_size != bi->tuple_size) +- goto incompatible; +- if (ti->interval_exp != bi->interval_exp) +- goto incompatible; +- if (ti->tag_size != bi->tag_size) +- goto incompatible; +- if (ti->csum_type != bi->csum_type) +- goto incompatible; +- if ((ti->flags & BLK_INTEGRITY_REF_TAG) != +- (bi->flags & BLK_INTEGRITY_REF_TAG)) +- goto incompatible; +- +-done: +- ti->flags |= BLK_INTEGRITY_STACKED; + return true; + + incompatible: +-- +2.39.5 + diff --git a/queue-6.14/block-fix-adding-folio-to-bio.patch b/queue-6.14/block-fix-adding-folio-to-bio.patch new file mode 100644 index 0000000000..87b54da21b --- /dev/null +++ b/queue-6.14/block-fix-adding-folio-to-bio.patch @@ -0,0 +1,65 @@ +From 1f136a1567901115cd1068011c5ffea6259f7f0d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 22:51:36 +0800 +Subject: block: fix adding folio to bio + +From: Ming Lei + +[ Upstream commit 26064d3e2b4d9a14df1072980e558c636fb023ea ] + +>4GB folio is possible on some ARCHs, such as aarch64, 16GB hugepage +is supported, then 'offset' of folio can't be held in 'unsigned int', +cause warning in bio_add_folio_nofail() and IO failure. + +Fix it by adjusting 'page' & trimming 'offset' so that `->bi_offset` won't +be overflow, and folio can be added to bio successfully. + +Fixes: ed9832bc08db ("block: introduce folio awareness and add a bigger size from folio") +Cc: Kundan Kumar +Cc: Matthew Wilcox (Oracle) +Cc: Christoph Hellwig +Cc: Luis Chamberlain +Cc: Gavin Shan +Signed-off-by: Ming Lei +Reviewed-by: Matthew Wilcox (Oracle) +Link: https://lore.kernel.org/r/20250312145136.2891229-1-ming.lei@redhat.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/bio.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/block/bio.c b/block/bio.c +index 6ac5983ba51e6..6deea10b2cd3d 100644 +--- a/block/bio.c ++++ b/block/bio.c +@@ -1026,9 +1026,10 @@ EXPORT_SYMBOL(bio_add_page); + void bio_add_folio_nofail(struct bio *bio, struct folio *folio, size_t len, + size_t off) + { ++ unsigned long nr = off / PAGE_SIZE; ++ + WARN_ON_ONCE(len > UINT_MAX); +- WARN_ON_ONCE(off > UINT_MAX); +- __bio_add_page(bio, &folio->page, len, off); ++ __bio_add_page(bio, folio_page(folio, nr), len, off % PAGE_SIZE); + } + EXPORT_SYMBOL_GPL(bio_add_folio_nofail); + +@@ -1049,9 +1050,11 @@ EXPORT_SYMBOL_GPL(bio_add_folio_nofail); + bool bio_add_folio(struct bio *bio, struct folio *folio, size_t len, + size_t off) + { +- if (len > UINT_MAX || off > UINT_MAX) ++ unsigned long nr = off / PAGE_SIZE; ++ ++ if (len > UINT_MAX) + return false; +- return bio_add_page(bio, &folio->page, len, off) > 0; ++ return bio_add_page(bio, folio_page(folio, nr), len, off % PAGE_SIZE) > 0; + } + EXPORT_SYMBOL(bio_add_folio); + +-- +2.39.5 + diff --git a/queue-6.14/bluetooth-add-quirk-for-broken-read_page_scan_type.patch b/queue-6.14/bluetooth-add-quirk-for-broken-read_page_scan_type.patch new file mode 100644 index 0000000000..092180d29e --- /dev/null +++ b/queue-6.14/bluetooth-add-quirk-for-broken-read_page_scan_type.patch @@ -0,0 +1,57 @@ +From 2ba31213c0b6db5a08325aca7b286d63e042d234 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Mar 2025 03:22:59 -0300 +Subject: Bluetooth: Add quirk for broken READ_PAGE_SCAN_TYPE + +From: Pedro Nishiyama + +[ Upstream commit 127881334eaad639e0a19a399ee8c91d6c9dc982 ] + +Some fake controllers cannot be initialized because they return a smaller +report than expected for READ_PAGE_SCAN_TYPE. + +Signed-off-by: Pedro Nishiyama +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: 1f04b0e5e3b9 ("Bluetooth: btusb: Fix regression in the initialization of fake Bluetooth controllers") +Signed-off-by: Sasha Levin +--- + include/net/bluetooth/hci.h | 8 ++++++++ + net/bluetooth/hci_sync.c | 3 ++- + 2 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h +index 295d97e312e1d..aa684d2b079fa 100644 +--- a/include/net/bluetooth/hci.h ++++ b/include/net/bluetooth/hci.h +@@ -362,6 +362,14 @@ enum { + * This quirk must be set before hci_register_dev is called. + */ + HCI_QUIRK_BROKEN_READ_VOICE_SETTING, ++ ++ /* When this quirk is set, the HCI_OP_READ_PAGE_SCAN_TYPE command is ++ * skipped. This is required for a subset of the CSR controller clones ++ * which erroneously claim to support it. ++ * ++ * This quirk must be set before hci_register_dev is called. ++ */ ++ HCI_QUIRK_BROKEN_READ_PAGE_SCAN_TYPE, + }; + + /* HCI device flags */ +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index 0c6a85abba2c5..cf60a8da943a5 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -4132,7 +4132,8 @@ static int hci_read_page_scan_type_sync(struct hci_dev *hdev) + * support the Read Page Scan Type command. Check support for + * this command in the bit mask of supported commands. + */ +- if (!(hdev->commands[13] & 0x01)) ++ if (!(hdev->commands[13] & 0x01) || ++ test_bit(HCI_QUIRK_BROKEN_READ_PAGE_SCAN_TYPE, &hdev->quirks)) + return 0; + + return __hci_cmd_sync_status(hdev, HCI_OP_READ_PAGE_SCAN_TYPE, +-- +2.39.5 + diff --git a/queue-6.14/bluetooth-add-quirk-for-broken-read_voice_setting.patch b/queue-6.14/bluetooth-add-quirk-for-broken-read_voice_setting.patch new file mode 100644 index 0000000000..b704ee5604 --- /dev/null +++ b/queue-6.14/bluetooth-add-quirk-for-broken-read_voice_setting.patch @@ -0,0 +1,73 @@ +From f885ed988e02e089c938b2dd9719ccd003d0505a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Mar 2025 03:22:58 -0300 +Subject: Bluetooth: Add quirk for broken READ_VOICE_SETTING + +From: Pedro Nishiyama + +[ Upstream commit ff26b2dd6568392f60fa67a4e58279938025c3af ] + +Some fake controllers cannot be initialized because they return a smaller +report than expected for READ_VOICE_SETTING. + +Signed-off-by: Pedro Nishiyama +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: 1f04b0e5e3b9 ("Bluetooth: btusb: Fix regression in the initialization of fake Bluetooth controllers") +Signed-off-by: Sasha Levin +--- + include/net/bluetooth/hci.h | 8 ++++++++ + include/net/bluetooth/hci_core.h | 4 ++++ + net/bluetooth/hci_sync.c | 3 +++ + 3 files changed, 15 insertions(+) + +diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h +index 3ec915738112b..295d97e312e1d 100644 +--- a/include/net/bluetooth/hci.h ++++ b/include/net/bluetooth/hci.h +@@ -354,6 +354,14 @@ enum { + * during the hdev->setup vendor callback. + */ + HCI_QUIRK_FIXUP_LE_EXT_ADV_REPORT_PHY, ++ ++ /* When this quirk is set, the HCI_OP_READ_VOICE_SETTING command is ++ * skipped. This is required for a subset of the CSR controller clones ++ * which erroneously claim to support it. ++ * ++ * This quirk must be set before hci_register_dev is called. ++ */ ++ HCI_QUIRK_BROKEN_READ_VOICE_SETTING, + }; + + /* HCI device flags */ +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index 6281063cbd8e4..8649ad17408bb 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -1925,6 +1925,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn); + ((dev)->commands[20] & 0x10 && \ + !test_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks)) + ++#define read_voice_setting_capable(dev) \ ++ ((dev)->commands[9] & 0x04 && \ ++ !test_bit(HCI_QUIRK_BROKEN_READ_VOICE_SETTING, &(dev)->quirks)) ++ + /* Use enhanced synchronous connection if command is supported and its quirk + * has not been set. + */ +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index dd770ef5ec368..0c6a85abba2c5 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -3696,6 +3696,9 @@ static int hci_read_local_name_sync(struct hci_dev *hdev) + /* Read Voice Setting */ + static int hci_read_voice_setting_sync(struct hci_dev *hdev) + { ++ if (!read_voice_setting_capable(hdev)) ++ return 0; ++ + return __hci_cmd_sync_status(hdev, HCI_OP_READ_VOICE_SETTING, + 0, NULL, HCI_CMD_TIMEOUT); + } +-- +2.39.5 + diff --git a/queue-6.14/bluetooth-btnxpuart-fix-kernel-panic-during-fw-relea.patch b/queue-6.14/bluetooth-btnxpuart-fix-kernel-panic-during-fw-relea.patch new file mode 100644 index 0000000000..340f240053 --- /dev/null +++ b/queue-6.14/bluetooth-btnxpuart-fix-kernel-panic-during-fw-relea.patch @@ -0,0 +1,88 @@ +From f14e5b6d569855b4810e9626ddce4e714e7005db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 17:32:31 +0530 +Subject: Bluetooth: btnxpuart: Fix kernel panic during FW release + +From: Neeraj Sanjay Kale + +[ Upstream commit 1f77c05408c96bc0b58ae476a9cadc9e5b9cfd0f ] + +This fixes a kernel panic seen during release FW in a stress test +scenario where WLAN and BT FW download occurs simultaneously, and due to +a HW bug, chip sends out only 1 bootloader signatures. + +When driver receives the bootloader signature, it enters FW download +mode, but since no consequtive bootloader signatures seen, FW file is +not requested. + +After 60 seconds, when FW download times out, release_firmware causes a +kernel panic. + +[ 2601.949184] Unable to handle kernel paging request at virtual address 0000312e6f006573 +[ 2601.992076] user pgtable: 4k pages, 48-bit VAs, pgdp=0000000111802000 +[ 2601.992080] [0000312e6f006573] pgd=0000000000000000, p4d=0000000000000000 +[ 2601.992087] Internal error: Oops: 0000000096000021 [#1] PREEMPT SMP +[ 2601.992091] Modules linked in: algif_hash algif_skcipher af_alg btnxpuart(O) pciexxx(O) mlan(O) overlay fsl_jr_uio caam_jr caamkeyblob_desc caamhash_desc caamalg_desc crypto_engine authenc libdes crct10dif_ce polyval_ce snd_soc_fsl_easrc snd_soc_fsl_asoc_card imx8_media_dev(C) snd_soc_fsl_micfil polyval_generic snd_soc_fsl_xcvr snd_soc_fsl_sai snd_soc_imx_audmux snd_soc_fsl_asrc snd_soc_imx_card snd_soc_imx_hdmi snd_soc_fsl_aud2htx snd_soc_fsl_utils imx_pcm_dma dw_hdmi_cec flexcan can_dev +[ 2602.001825] CPU: 2 PID: 20060 Comm: hciconfig Tainted: G C O 6.6.23-lts-next-06236-gb586a521770e #1 +[ 2602.010182] Hardware name: NXP i.MX8MPlus EVK board (DT) +[ 2602.010185] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) +[ 2602.010191] pc : _raw_spin_lock+0x34/0x68 +[ 2602.010201] lr : free_fw_priv+0x20/0xfc +[ 2602.020561] sp : ffff800089363b30 +[ 2602.020563] x29: ffff800089363b30 x28: ffff0000d0eb5880 x27: 0000000000000000 +[ 2602.020570] x26: 0000000000000000 x25: ffff0000d728b330 x24: 0000000000000000 +[ 2602.020577] x23: ffff0000dc856f38 +[ 2602.033797] x22: ffff800089363b70 x21: ffff0000dc856000 +[ 2602.033802] x20: ff00312e6f006573 x19: ffff0000d0d9ea80 x18: 0000000000000000 +[ 2602.033809] x17: 0000000000000000 x16: 0000000000000000 x15: 0000aaaad80dd480 +[ 2602.083320] x14: 0000000000000000 x13: 00000000000001b9 x12: 0000000000000002 +[ 2602.083326] x11: 0000000000000000 x10: 0000000000000a60 x9 : ffff800089363a30 +[ 2602.083333] x8 : ffff0001793d75c0 x7 : ffff0000d6dbc400 x6 : 0000000000000000 +[ 2602.083339] x5 : 00000000410fd030 x4 : 0000000000000000 x3 : 0000000000000001 +[ 2602.083346] x2 : 0000000000000000 x1 : 0000000000000001 x0 : ff00312e6f006573 +[ 2602.083354] Call trace: +[ 2602.083356] _raw_spin_lock+0x34/0x68 +[ 2602.083364] release_firmware+0x48/0x6c +[ 2602.083370] nxp_setup+0x3c4/0x540 [btnxpuart] +[ 2602.083383] hci_dev_open_sync+0xf0/0xa34 +[ 2602.083391] hci_dev_open+0xd8/0x178 +[ 2602.083399] hci_sock_ioctl+0x3b0/0x590 +[ 2602.083405] sock_do_ioctl+0x60/0x118 +[ 2602.083413] sock_ioctl+0x2f4/0x374 +[ 2602.091430] __arm64_sys_ioctl+0xac/0xf0 +[ 2602.091437] invoke_syscall+0x48/0x110 +[ 2602.091445] el0_svc_common.constprop.0+0xc0/0xe0 +[ 2602.091452] do_el0_svc+0x1c/0x28 +[ 2602.091457] el0_svc+0x40/0xe4 +[ 2602.091465] el0t_64_sync_handler+0x120/0x12c +[ 2602.091470] el0t_64_sync+0x190/0x194 + +Fixes: e3c4891098c8 ("Bluetooth: btnxpuart: Handle FW Download Abort scenario") +Fixes: 689ca16e5232 ("Bluetooth: NXP: Add protocol support for NXP Bluetooth chipsets") +Signed-off-by: Neeraj Sanjay Kale +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btnxpuart.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c +index aa5ec1d444a9d..6d66668d670a9 100644 +--- a/drivers/bluetooth/btnxpuart.c ++++ b/drivers/bluetooth/btnxpuart.c +@@ -651,8 +651,10 @@ static int nxp_download_firmware(struct hci_dev *hdev) + &nxpdev->tx_state), + msecs_to_jiffies(60000)); + +- release_firmware(nxpdev->fw); +- memset(nxpdev->fw_name, 0, sizeof(nxpdev->fw_name)); ++ if (nxpdev->fw && strlen(nxpdev->fw_name)) { ++ release_firmware(nxpdev->fw); ++ memset(nxpdev->fw_name, 0, sizeof(nxpdev->fw_name)); ++ } + + if (err == 0) { + bt_dev_err(hdev, "FW Download Timeout. offset: %d", +-- +2.39.5 + diff --git a/queue-6.14/bluetooth-btusb-fix-regression-in-the-initialization.patch b/queue-6.14/bluetooth-btusb-fix-regression-in-the-initialization.patch new file mode 100644 index 0000000000..c7c79b1c99 --- /dev/null +++ b/queue-6.14/bluetooth-btusb-fix-regression-in-the-initialization.patch @@ -0,0 +1,42 @@ +From 30106906bb597d4fa4062b220f04d8826c988b3e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Mar 2025 03:23:01 -0300 +Subject: Bluetooth: btusb: Fix regression in the initialization of fake + Bluetooth controllers + +From: Pedro Nishiyama + +[ Upstream commit 1f04b0e5e3b90b30f3ae7bee7e3d42a55fa91d5f ] + +Set HCI_READ_VOICE_SETTING and HCI_READ_PAGE_SCAN_TYPE as broken. + +Once the min/max length of the commands began to be asserted, these fake +controllers can no longer be initialized because they return a smaller +report for these commands. + +This affects various fake controllers reusing the 0A12:0001 VID/PID. + +Fixes: c8992cffbe74 ("Bluetooth: hci_event: Use of a function table to handle Command Complete") +Signed-off-by: Pedro Nishiyama +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index a0fc465458b2f..699ff21d97675 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2477,6 +2477,8 @@ static int btusb_setup_csr(struct hci_dev *hdev) + set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks); + set_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks); + set_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks); ++ set_bit(HCI_QUIRK_BROKEN_READ_VOICE_SETTING, &hdev->quirks); ++ set_bit(HCI_QUIRK_BROKEN_READ_PAGE_SCAN_TYPE, &hdev->quirks); + + /* Clear the reset quirk since this is not an actual + * early Bluetooth 1.1 device from CSR. +-- +2.39.5 + diff --git a/queue-6.14/bluetooth-hci-add-definition-of-hci_rp_remote_name_r.patch b/queue-6.14/bluetooth-hci-add-definition-of-hci_rp_remote_name_r.patch new file mode 100644 index 0000000000..5112d9a7f8 --- /dev/null +++ b/queue-6.14/bluetooth-hci-add-definition-of-hci_rp_remote_name_r.patch @@ -0,0 +1,77 @@ +From 527f6fb0dd8726fd77120cab89c83e41a35fe955 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 02:50:34 +0800 +Subject: Bluetooth: HCI: Add definition of hci_rp_remote_name_req_cancel + +From: Wentao Guan + +[ Upstream commit e8c00f5433d020a2230226abe7e43f43dc686920 ] + +Return Parameters is not only status, also bdaddr: + +BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 4, Part E +page 1870: +BLUETOOTH CORE SPECIFICATION Version 5.0 | Vol 2, Part E +page 802: + +Return parameters: + Status: + Size: 1 octet + BD_ADDR: + Size: 6 octets + +Note that it also fixes the warning: +"Bluetooth: hci0: unexpected cc 0x041a length: 7 > 1" + +Fixes: c8992cffbe741 ("Bluetooth: hci_event: Use of a function table to handle Command Complete") +Signed-off-by: Wentao Guan +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + include/net/bluetooth/hci.h | 5 +++++ + net/bluetooth/hci_event.c | 6 +++--- + 2 files changed, 8 insertions(+), 3 deletions(-) + +diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h +index 6da61c185c949..a8586c3058c7c 100644 +--- a/include/net/bluetooth/hci.h ++++ b/include/net/bluetooth/hci.h +@@ -879,6 +879,11 @@ struct hci_cp_remote_name_req_cancel { + bdaddr_t bdaddr; + } __packed; + ++struct hci_rp_remote_name_req_cancel { ++ __u8 status; ++ bdaddr_t bdaddr; ++} __packed; ++ + #define HCI_OP_READ_REMOTE_FEATURES 0x041b + struct hci_cp_read_remote_features { + __le16 handle; +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index ab95e49f042ea..dd86b7a242b72 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -151,7 +151,7 @@ static u8 hci_cc_exit_periodic_inq(struct hci_dev *hdev, void *data, + static u8 hci_cc_remote_name_req_cancel(struct hci_dev *hdev, void *data, + struct sk_buff *skb) + { +- struct hci_ev_status *rp = data; ++ struct hci_rp_remote_name_req_cancel *rp = data; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + +@@ -4012,8 +4012,8 @@ static const struct hci_cc { + HCI_CC_STATUS(HCI_OP_INQUIRY_CANCEL, hci_cc_inquiry_cancel), + HCI_CC_STATUS(HCI_OP_PERIODIC_INQ, hci_cc_periodic_inq), + HCI_CC_STATUS(HCI_OP_EXIT_PERIODIC_INQ, hci_cc_exit_periodic_inq), +- HCI_CC_STATUS(HCI_OP_REMOTE_NAME_REQ_CANCEL, +- hci_cc_remote_name_req_cancel), ++ HCI_CC(HCI_OP_REMOTE_NAME_REQ_CANCEL, hci_cc_remote_name_req_cancel, ++ sizeof(struct hci_rp_remote_name_req_cancel)), + HCI_CC(HCI_OP_ROLE_DISCOVERY, hci_cc_role_discovery, + sizeof(struct hci_rp_role_discovery)), + HCI_CC(HCI_OP_READ_LINK_POLICY, hci_cc_read_link_policy, +-- +2.39.5 + diff --git a/queue-6.14/bluetooth-hci_core-enable-buffer-flow-control-for-sc.patch b/queue-6.14/bluetooth-hci_core-enable-buffer-flow-control-for-sc.patch new file mode 100644 index 0000000000..3ef429b4d5 --- /dev/null +++ b/queue-6.14/bluetooth-hci_core-enable-buffer-flow-control-for-sc.patch @@ -0,0 +1,279 @@ +From 7193c84cbde49daf79a51968e55c30045b8e84c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 11:14:20 -0400 +Subject: Bluetooth: hci_core: Enable buffer flow control for SCO/eSCO + +From: Luiz Augusto von Dentz + +[ Upstream commit 13218453521d75916dfed55efb8e809bfc03cb4b ] + +This enables buffer flow control for SCO/eSCO +(see: Bluetooth Core 6.0 spec: 6.22. Synchronous Flow Control Enable), +recently this has caused the following problem and is actually a nice +addition for the likes of Socket TX complete: + +< HCI Command: Read Buffer Size (0x04|0x0005) plen 0 +> HCI Event: Command Complete (0x0e) plen 11 + Read Buffer Size (0x04|0x0005) ncmd 1 + Status: Success (0x00) + ACL MTU: 1021 ACL max packet: 5 + SCO MTU: 240 SCO max packet: 8 +... +< SCO Data TX: Handle 257 flags 0x00 dlen 120 +< SCO Data TX: Handle 257 flags 0x00 dlen 120 +< SCO Data TX: Handle 257 flags 0x00 dlen 120 +< SCO Data TX: Handle 257 flags 0x00 dlen 120 +< SCO Data TX: Handle 257 flags 0x00 dlen 120 +< SCO Data TX: Handle 257 flags 0x00 dlen 120 +< SCO Data TX: Handle 257 flags 0x00 dlen 120 +< SCO Data TX: Handle 257 flags 0x00 dlen 120 +< SCO Data TX: Handle 257 flags 0x00 dlen 120 +> HCI Event: Hardware Error (0x10) plen 1 + Code: 0x0a + +To fix the code will now attempt to enable buffer flow control when +HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED is set by the driver: + +< HCI Command: Write Sync Fl.. (0x03|0x002f) plen 1 + Flow control: Enabled (0x01) +> HCI Event: Command Complete (0x0e) plen 4 + Write Sync Flow Control Enable (0x03|0x002f) ncmd 1 + Status: Success (0x00) + +On success then HCI_SCO_FLOWCTL would be set which indicates sco_cnt +shall be used for flow contro. + +Fixes: 7fedd3bb6b77 ("Bluetooth: Prioritize SCO traffic") +Signed-off-by: Luiz Augusto von Dentz +Tested-by: Pauli Virtanen +Signed-off-by: Sasha Levin +--- + include/net/bluetooth/hci.h | 13 +++++++ + include/net/bluetooth/hci_core.h | 1 + + net/bluetooth/hci_core.c | 62 +++++++++++++++----------------- + net/bluetooth/hci_event.c | 2 ++ + net/bluetooth/hci_sync.c | 24 +++++++++++++ + 5 files changed, 68 insertions(+), 34 deletions(-) + +diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h +index aa684d2b079fa..6da61c185c949 100644 +--- a/include/net/bluetooth/hci.h ++++ b/include/net/bluetooth/hci.h +@@ -208,6 +208,13 @@ enum { + */ + HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, + ++ /* When this quirk is set consider Sync Flow Control as supported by ++ * the driver. ++ * ++ * This quirk must be set before hci_register_dev is called. ++ */ ++ HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED, ++ + /* When this quirk is set, the LE states reported through the + * HCI_LE_READ_SUPPORTED_STATES are invalid/broken. + * +@@ -448,6 +455,7 @@ enum { + HCI_WIDEBAND_SPEECH_ENABLED, + HCI_EVENT_FILTER_CONFIGURED, + HCI_PA_SYNC, ++ HCI_SCO_FLOWCTL, + + HCI_DUT_MODE, + HCI_VENDOR_DIAG, +@@ -1544,6 +1552,11 @@ struct hci_rp_read_tx_power { + __s8 tx_power; + } __packed; + ++#define HCI_OP_WRITE_SYNC_FLOWCTL 0x0c2f ++struct hci_cp_write_sync_flowctl { ++ __u8 enable; ++} __packed; ++ + #define HCI_OP_READ_PAGE_SCAN_TYPE 0x0c46 + struct hci_rp_read_page_scan_type { + __u8 status; +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index 8649ad17408bb..f0b49aad519eb 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -1858,6 +1858,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn); + #define lmp_hold_capable(dev) ((dev)->features[0][0] & LMP_HOLD) + #define lmp_sniff_capable(dev) ((dev)->features[0][0] & LMP_SNIFF) + #define lmp_park_capable(dev) ((dev)->features[0][1] & LMP_PARK) ++#define lmp_sco_capable(dev) ((dev)->features[0][1] & LMP_SCO) + #define lmp_inq_rssi_capable(dev) ((dev)->features[0][3] & LMP_RSSI_INQ) + #define lmp_esco_capable(dev) ((dev)->features[0][3] & LMP_ESCO) + #define lmp_bredr_capable(dev) (!((dev)->features[0][4] & LMP_NO_BREDR)) +diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c +index 012fc107901a6..94d9147612daf 100644 +--- a/net/bluetooth/hci_core.c ++++ b/net/bluetooth/hci_core.c +@@ -3552,42 +3552,27 @@ static void __check_timeout(struct hci_dev *hdev, unsigned int cnt, u8 type) + } + + /* Schedule SCO */ +-static void hci_sched_sco(struct hci_dev *hdev) ++static void hci_sched_sco(struct hci_dev *hdev, __u8 type) + { + struct hci_conn *conn; + struct sk_buff *skb; +- int quote; ++ int quote, *cnt; ++ unsigned int pkts = hdev->sco_pkts; + +- BT_DBG("%s", hdev->name); ++ bt_dev_dbg(hdev, "type %u", type); + +- if (!hci_conn_num(hdev, SCO_LINK)) ++ if (!hci_conn_num(hdev, type) || !pkts) + return; + +- while (hdev->sco_cnt && (conn = hci_low_sent(hdev, SCO_LINK, "e))) { +- while (quote-- && (skb = skb_dequeue(&conn->data_q))) { +- BT_DBG("skb %p len %d", skb, skb->len); +- hci_send_frame(hdev, skb); +- +- conn->sent++; +- if (conn->sent == ~0) +- conn->sent = 0; +- } +- } +-} +- +-static void hci_sched_esco(struct hci_dev *hdev) +-{ +- struct hci_conn *conn; +- struct sk_buff *skb; +- int quote; +- +- BT_DBG("%s", hdev->name); +- +- if (!hci_conn_num(hdev, ESCO_LINK)) +- return; ++ /* Use sco_pkts if flow control has not been enabled which will limit ++ * the amount of buffer sent in a row. ++ */ ++ if (!hci_dev_test_flag(hdev, HCI_SCO_FLOWCTL)) ++ cnt = &pkts; ++ else ++ cnt = &hdev->sco_cnt; + +- while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK, +- "e))) { ++ while (*cnt && (conn = hci_low_sent(hdev, type, "e))) { + while (quote-- && (skb = skb_dequeue(&conn->data_q))) { + BT_DBG("skb %p len %d", skb, skb->len); + hci_send_frame(hdev, skb); +@@ -3595,8 +3580,17 @@ static void hci_sched_esco(struct hci_dev *hdev) + conn->sent++; + if (conn->sent == ~0) + conn->sent = 0; ++ (*cnt)--; + } + } ++ ++ /* Rescheduled if all packets were sent and flow control is not enabled ++ * as there could be more packets queued that could not be sent and ++ * since no HCI_EV_NUM_COMP_PKTS event will be generated the reschedule ++ * needs to be forced. ++ */ ++ if (!pkts && !hci_dev_test_flag(hdev, HCI_SCO_FLOWCTL)) ++ queue_work(hdev->workqueue, &hdev->tx_work); + } + + static void hci_sched_acl_pkt(struct hci_dev *hdev) +@@ -3632,8 +3626,8 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev) + chan->conn->sent++; + + /* Send pending SCO packets right away */ +- hci_sched_sco(hdev); +- hci_sched_esco(hdev); ++ hci_sched_sco(hdev, SCO_LINK); ++ hci_sched_sco(hdev, ESCO_LINK); + } + } + +@@ -3688,8 +3682,8 @@ static void hci_sched_le(struct hci_dev *hdev) + chan->conn->sent++; + + /* Send pending SCO packets right away */ +- hci_sched_sco(hdev); +- hci_sched_esco(hdev); ++ hci_sched_sco(hdev, SCO_LINK); ++ hci_sched_sco(hdev, ESCO_LINK); + } + } + +@@ -3734,8 +3728,8 @@ static void hci_tx_work(struct work_struct *work) + + if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { + /* Schedule queues and send stuff to HCI driver */ +- hci_sched_sco(hdev); +- hci_sched_esco(hdev); ++ hci_sched_sco(hdev, SCO_LINK); ++ hci_sched_sco(hdev, ESCO_LINK); + hci_sched_iso(hdev); + hci_sched_acl(hdev); + hci_sched_le(hdev); +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 903b0b52692aa..ab95e49f042ea 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -4442,9 +4442,11 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data, + break; + + case SCO_LINK: ++ case ESCO_LINK: + hdev->sco_cnt += count; + if (hdev->sco_cnt > hdev->sco_pkts) + hdev->sco_cnt = hdev->sco_pkts; ++ + break; + + case ISO_LINK: +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index cf60a8da943a5..14c3ee5c6a1e8 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -3769,6 +3769,28 @@ static int hci_write_ca_timeout_sync(struct hci_dev *hdev) + sizeof(param), ¶m, HCI_CMD_TIMEOUT); + } + ++/* Enable SCO flow control if supported */ ++static int hci_write_sync_flowctl_sync(struct hci_dev *hdev) ++{ ++ struct hci_cp_write_sync_flowctl cp; ++ int err; ++ ++ /* Check if the controller supports SCO and HCI_OP_WRITE_SYNC_FLOWCTL */ ++ if (!lmp_sco_capable(hdev) || !(hdev->commands[10] & BIT(4)) || ++ !test_bit(HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED, &hdev->quirks)) ++ return 0; ++ ++ memset(&cp, 0, sizeof(cp)); ++ cp.enable = 0x01; ++ ++ err = __hci_cmd_sync_status(hdev, HCI_OP_WRITE_SYNC_FLOWCTL, ++ sizeof(cp), &cp, HCI_CMD_TIMEOUT); ++ if (!err) ++ hci_dev_set_flag(hdev, HCI_SCO_FLOWCTL); ++ ++ return err; ++} ++ + /* BR Controller init stage 2 command sequence */ + static const struct hci_init_stage br_init2[] = { + /* HCI_OP_READ_BUFFER_SIZE */ +@@ -3787,6 +3809,8 @@ static const struct hci_init_stage br_init2[] = { + HCI_INIT(hci_clear_event_filter_sync), + /* HCI_OP_WRITE_CA_TIMEOUT */ + HCI_INIT(hci_write_ca_timeout_sync), ++ /* HCI_OP_WRITE_SYNC_FLOWCTL */ ++ HCI_INIT(hci_write_sync_flowctl_sync), + {} + }; + +-- +2.39.5 + diff --git a/queue-6.14/bluetooth-hci_event-fix-handling-of-hci_ev_le_direct.patch b/queue-6.14/bluetooth-hci_event-fix-handling-of-hci_ev_le_direct.patch new file mode 100644 index 0000000000..7863911b99 --- /dev/null +++ b/queue-6.14/bluetooth-hci_event-fix-handling-of-hci_ev_le_direct.patch @@ -0,0 +1,81 @@ +From 982e28dc71449cfb332a05e70453581fcf2419e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Mar 2025 11:22:23 -0400 +Subject: Bluetooth: hci_event: Fix handling of HCI_EV_LE_DIRECT_ADV_REPORT + +From: Luiz Augusto von Dentz + +[ Upstream commit 3a7fdfb7d876910cfe734488f553dbbc938f8f16 ] + +Some controllers seems to generate HCI_EV_LE_DIRECT_ADV_REPORT even when +scan_filter is not set to 0x02 or 0x03, which indicates that local +privacy is enabled, causing them to be ignored thus breaking +auto-connect logic: + +< HCI Command: LE Set Scan Parameters (0x08|0x000b) plen 7 + Type: Passive (0x00) + Interval: 60.000 msec (0x0060) + Window: 30.000 msec (0x0030) + Own address type: Public (0x00) + Filter policy: Ignore not in accept list (0x01) +... +> HCI Event: LE Meta Event (0x3e) plen 18 + LE Direct Advertising Report (0x0b) + Num reports: 1 + Event type: Connectable directed - ADV_DIRECT_IND (0x01) + Address type: Random (0x01) + Address: XX:XX:XX:XX:XX:XX (Static) + Direct address type: Random (0x01) + Direct address: XX:XX:XX:XX:XX:XX (Non-Resolvable) + RSSI: -54 dBm (0xca) + +So this attempts to mitigate the above problem by skipping checking of +direct_addr if local privacy is not enabled. + +Link: https://github.com/bluez/bluez/issues/1138 +Fixes: e209e5ccc5ac ("Bluetooth: MGMT: Mark LL Privacy as stable") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index dd86b7a242b72..e2bfbcee06a80 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -6053,8 +6053,17 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, + * a LE Direct Advertising Report event. In that case it is + * important to see if the address is matching the local + * controller address. ++ * ++ * If local privacy is not enable the controller shall not be ++ * generating such event since according to its documentation it is only ++ * valid for filter_policy 0x02 and 0x03, but the fact that it did ++ * generate LE Direct Advertising Report means it is probably broken and ++ * won't generate any other event which can potentially break ++ * auto-connect logic so in case local privacy is not enable this ++ * ignores the direct_addr so it works as a regular report. + */ +- if (!hci_dev_test_flag(hdev, HCI_MESH) && direct_addr) { ++ if (!hci_dev_test_flag(hdev, HCI_MESH) && direct_addr && ++ hci_dev_test_flag(hdev, HCI_PRIVACY)) { + direct_addr_type = ev_bdaddr_type(hdev, direct_addr_type, + &bdaddr_resolved); + +@@ -6064,12 +6073,6 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, + if (!hci_bdaddr_is_rpa(direct_addr, direct_addr_type)) + return; + +- /* If the controller is not using resolvable random +- * addresses, then this report can be ignored. +- */ +- if (!hci_dev_test_flag(hdev, HCI_PRIVACY)) +- return; +- + /* If the local IRK of the controller does not match + * with the resolvable random address provided, then + * this report can be ignored. +-- +2.39.5 + diff --git a/queue-6.14/bnxt_en-linearize-tx-skb-if-the-fragments-exceed-the.patch b/queue-6.14/bnxt_en-linearize-tx-skb-if-the-fragments-exceed-the.patch new file mode 100644 index 0000000000..09c65bd000 --- /dev/null +++ b/queue-6.14/bnxt_en-linearize-tx-skb-if-the-fragments-exceed-the.patch @@ -0,0 +1,68 @@ +From ae9c78eae569420c26f490dac0c0edb1a4c386c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 14:16:39 -0700 +Subject: bnxt_en: Linearize TX SKB if the fragments exceed the max + +From: Michael Chan + +[ Upstream commit b91e82129400bdc40ee1232aa7e32ae6027f9b4f ] + +If skb_shinfo(skb)->nr_frags excceds what the chip can support, +linearize the SKB and warn once to let the user know. +net.core.max_skb_frags can be lowered, for example, to avoid the +issue. + +Fixes: 3948b05950fd ("net: introduce a config option to tweak MAX_SKB_FRAGS") +Reviewed-by: Somnath Kotur +Reviewed-by: Kalesh AP +Reviewed-by: Andy Gospodarek +Signed-off-by: Michael Chan +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250321211639.3812992-3-michael.chan@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 11 +++++++++++ + drivers/net/ethernet/broadcom/bnxt/bnxt.h | 4 ++++ + 2 files changed, 15 insertions(+) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index 158e9789c1f46..2cd79b59cf002 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -485,6 +485,17 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev) + txr = &bp->tx_ring[bp->tx_ring_map[i]]; + prod = txr->tx_prod; + ++#if (MAX_SKB_FRAGS > TX_MAX_FRAGS) ++ if (skb_shinfo(skb)->nr_frags > TX_MAX_FRAGS) { ++ netdev_warn_once(dev, "SKB has too many (%d) fragments, max supported is %d. SKB will be linearized.\n", ++ skb_shinfo(skb)->nr_frags, TX_MAX_FRAGS); ++ if (skb_linearize(skb)) { ++ dev_kfree_skb_any(skb); ++ dev_core_stats_tx_dropped_inc(dev); ++ return NETDEV_TX_OK; ++ } ++ } ++#endif + free_size = bnxt_tx_avail(bp, txr); + if (unlikely(free_size < skb_shinfo(skb)->nr_frags + 2)) { + /* We must have raced with NAPI cleanup */ +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h +index 3b4a044db73e3..d621fb621f30c 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h +@@ -84,6 +84,10 @@ struct tx_bd { + + #define TX_BD_CNT(n) (((n) << TX_BD_FLAGS_BD_CNT_SHIFT) & TX_BD_FLAGS_BD_CNT) + ++#define TX_MAX_BD_CNT 32 ++ ++#define TX_MAX_FRAGS (TX_MAX_BD_CNT - 2) ++ + struct tx_bd_ext { + __le32 tx_bd_hsize_lflags; + #define TX_BD_FLAGS_TCP_UDP_CHKSUM (1 << 0) +-- +2.39.5 + diff --git a/queue-6.14/bnxt_en-mask-the-bd_cnt-field-in-the-tx-bd-properly.patch b/queue-6.14/bnxt_en-mask-the-bd_cnt-field-in-the-tx-bd-properly.patch new file mode 100644 index 0000000000..6f3ebef6c9 --- /dev/null +++ b/queue-6.14/bnxt_en-mask-the-bd_cnt-field-in-the-tx-bd-properly.patch @@ -0,0 +1,90 @@ +From b60503b054192adc55d782f885a5a21e81013648 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 14:16:38 -0700 +Subject: bnxt_en: Mask the bd_cnt field in the TX BD properly + +From: Michael Chan + +[ Upstream commit 107b25db61122d8f990987895c2912927b8b6e3f ] + +The bd_cnt field in the TX BD specifies the total number of BDs for +the TX packet. The bd_cnt field has 5 bits and the maximum number +supported is 32 with the value 0. + +CONFIG_MAX_SKB_FRAGS can be modified and the total number of SKB +fragments can approach or exceed the maximum supported by the chip. +Add a macro to properly mask the bd_cnt field so that the value 32 +will be properly masked and set to 0 in the bd_cnd field. + +Without this patch, the out-of-range bd_cnt value will corrupt the +TX BD and may cause TX timeout. + +The next patch will check for values exceeding 32. + +Fixes: 3948b05950fd ("net: introduce a config option to tweak MAX_SKB_FRAGS") +Reviewed-by: Kalesh AP +Reviewed-by: Somnath Kotur +Reviewed-by: Andy Gospodarek +Signed-off-by: Michael Chan +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250321211639.3812992-2-michael.chan@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 4 ++-- + drivers/net/ethernet/broadcom/bnxt/bnxt.h | 2 ++ + drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 3 +-- + 3 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index 0ddc3d41e2d81..158e9789c1f46 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -564,7 +564,7 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev) + TX_BD_FLAGS_LHINT_512_AND_SMALLER | + TX_BD_FLAGS_COAL_NOW | + TX_BD_FLAGS_PACKET_END | +- (2 << TX_BD_FLAGS_BD_CNT_SHIFT)); ++ TX_BD_CNT(2)); + + if (skb->ip_summed == CHECKSUM_PARTIAL) + tx_push1->tx_bd_hsize_lflags = +@@ -639,7 +639,7 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev) + + dma_unmap_addr_set(tx_buf, mapping, mapping); + flags = (len << TX_BD_LEN_SHIFT) | TX_BD_TYPE_LONG_TX_BD | +- ((last_frag + 2) << TX_BD_FLAGS_BD_CNT_SHIFT); ++ TX_BD_CNT(last_frag + 2); + + txbd->tx_bd_haddr = cpu_to_le64(mapping); + txbd->tx_bd_opaque = SET_TX_OPAQUE(bp, txr, prod, 2 + last_frag); +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h +index 2373f423a523e..3b4a044db73e3 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h +@@ -82,6 +82,8 @@ struct tx_bd { + #define TX_OPAQUE_PROD(bp, opq) ((TX_OPAQUE_IDX(opq) + TX_OPAQUE_BDS(opq)) &\ + (bp)->tx_ring_mask) + ++#define TX_BD_CNT(n) (((n) << TX_BD_FLAGS_BD_CNT_SHIFT) & TX_BD_FLAGS_BD_CNT) ++ + struct tx_bd_ext { + __le32 tx_bd_hsize_lflags; + #define TX_BD_FLAGS_TCP_UDP_CHKSUM (1 << 0) +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +index 299822cacca48..d71bad3cfd6bd 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +@@ -48,8 +48,7 @@ struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp, + tx_buf->page = virt_to_head_page(xdp->data); + + txbd = &txr->tx_desc_ring[TX_RING(bp, prod)][TX_IDX(prod)]; +- flags = (len << TX_BD_LEN_SHIFT) | +- ((num_frags + 1) << TX_BD_FLAGS_BD_CNT_SHIFT) | ++ flags = (len << TX_BD_LEN_SHIFT) | TX_BD_CNT(num_frags + 1) | + bnxt_lhint_arr[len >> 9]; + txbd->tx_bd_len_flags_type = cpu_to_le32(flags); + txbd->tx_bd_opaque = SET_TX_OPAQUE(bp, txr, prod, 1 + num_frags); +-- +2.39.5 + diff --git a/queue-6.14/bonding-check-xdp-prog-when-set-bond-mode.patch b/queue-6.14/bonding-check-xdp-prog-when-set-bond-mode.patch new file mode 100644 index 0000000000..9ae79de527 --- /dev/null +++ b/queue-6.14/bonding-check-xdp-prog-when-set-bond-mode.patch @@ -0,0 +1,146 @@ +From f739897ecd68bfdd86ea0d727bacdfd867d85909 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 12:48:52 +0800 +Subject: bonding: check xdp prog when set bond mode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Wang Liang + +[ Upstream commit 094ee6017ea09c11d6af187935a949df32803ce0 ] + +Following operations can trigger a warning[1]: + + ip netns add ns1 + ip netns exec ns1 ip link add bond0 type bond mode balance-rr + ip netns exec ns1 ip link set dev bond0 xdp obj af_xdp_kern.o sec xdp + ip netns exec ns1 ip link set bond0 type bond mode broadcast + ip netns del ns1 + +When delete the namespace, dev_xdp_uninstall() is called to remove xdp +program on bond dev, and bond_xdp_set() will check the bond mode. If bond +mode is changed after attaching xdp program, the warning may occur. + +Some bond modes (broadcast, etc.) do not support native xdp. Set bond mode +with xdp program attached is not good. Add check for xdp program when set +bond mode. + + [1] + ------------[ cut here ]------------ + WARNING: CPU: 0 PID: 11 at net/core/dev.c:9912 unregister_netdevice_many_notify+0x8d9/0x930 + Modules linked in: + CPU: 0 UID: 0 PID: 11 Comm: kworker/u4:0 Not tainted 6.14.0-rc4 #107 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.15.0-0-g2dd4b9b3f840-prebuilt.qemu.org 04/01/2014 + Workqueue: netns cleanup_net + RIP: 0010:unregister_netdevice_many_notify+0x8d9/0x930 + Code: 00 00 48 c7 c6 6f e3 a2 82 48 c7 c7 d0 b3 96 82 e8 9c 10 3e ... + RSP: 0018:ffffc90000063d80 EFLAGS: 00000282 + RAX: 00000000ffffffa1 RBX: ffff888004959000 RCX: 00000000ffffdfff + RDX: 0000000000000000 RSI: 00000000ffffffea RDI: ffffc90000063b48 + RBP: ffffc90000063e28 R08: ffffffff82d39b28 R09: 0000000000009ffb + R10: 0000000000000175 R11: ffffffff82d09b40 R12: ffff8880049598e8 + R13: 0000000000000001 R14: dead000000000100 R15: ffffc90000045000 + FS: 0000000000000000(0000) GS:ffff888007a00000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 000000000d406b60 CR3: 000000000483e000 CR4: 00000000000006f0 + Call Trace: + + ? __warn+0x83/0x130 + ? unregister_netdevice_many_notify+0x8d9/0x930 + ? report_bug+0x18e/0x1a0 + ? handle_bug+0x54/0x90 + ? exc_invalid_op+0x18/0x70 + ? asm_exc_invalid_op+0x1a/0x20 + ? unregister_netdevice_many_notify+0x8d9/0x930 + ? bond_net_exit_batch_rtnl+0x5c/0x90 + cleanup_net+0x237/0x3d0 + process_one_work+0x163/0x390 + worker_thread+0x293/0x3b0 + ? __pfx_worker_thread+0x10/0x10 + kthread+0xec/0x1e0 + ? __pfx_kthread+0x10/0x10 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x2f/0x50 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + ---[ end trace 0000000000000000 ]--- + +Fixes: 9e2ee5c7e7c3 ("net, bonding: Add XDP support to the bonding driver") +Signed-off-by: Wang Liang +Acked-by: Jussi Maki +Reviewed-by: Nikolay Aleksandrov +Reviewed-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20250321044852.1086551-1-wangliang74@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/bonding/bond_main.c | 8 ++++---- + drivers/net/bonding/bond_options.c | 3 +++ + include/net/bonding.h | 1 + + 3 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index e45bba240cbcd..4da5fcb7def47 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -322,9 +322,9 @@ static bool bond_sk_check(struct bonding *bond) + } + } + +-static bool bond_xdp_check(struct bonding *bond) ++bool bond_xdp_check(struct bonding *bond, int mode) + { +- switch (BOND_MODE(bond)) { ++ switch (mode) { + case BOND_MODE_ROUNDROBIN: + case BOND_MODE_ACTIVEBACKUP: + return true; +@@ -1937,7 +1937,7 @@ void bond_xdp_set_features(struct net_device *bond_dev) + + ASSERT_RTNL(); + +- if (!bond_xdp_check(bond) || !bond_has_slaves(bond)) { ++ if (!bond_xdp_check(bond, BOND_MODE(bond)) || !bond_has_slaves(bond)) { + xdp_clear_features_flag(bond_dev); + return; + } +@@ -5699,7 +5699,7 @@ static int bond_xdp_set(struct net_device *dev, struct bpf_prog *prog, + + ASSERT_RTNL(); + +- if (!bond_xdp_check(bond)) { ++ if (!bond_xdp_check(bond, BOND_MODE(bond))) { + BOND_NL_ERR(dev, extack, + "No native XDP support for the current bonding mode"); + return -EOPNOTSUPP; +diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c +index d1b095af253bd..91893c29b8995 100644 +--- a/drivers/net/bonding/bond_options.c ++++ b/drivers/net/bonding/bond_options.c +@@ -868,6 +868,9 @@ static bool bond_set_xfrm_features(struct bonding *bond) + static int bond_option_mode_set(struct bonding *bond, + const struct bond_opt_value *newval) + { ++ if (bond->xdp_prog && !bond_xdp_check(bond, newval->value)) ++ return -EOPNOTSUPP; ++ + if (!bond_mode_uses_arp(newval->value)) { + if (bond->params.arp_interval) { + netdev_dbg(bond->dev, "%s mode is incompatible with arp monitoring, start mii monitoring\n", +diff --git a/include/net/bonding.h b/include/net/bonding.h +index 8bb5f016969f1..95f67b308c19a 100644 +--- a/include/net/bonding.h ++++ b/include/net/bonding.h +@@ -695,6 +695,7 @@ void bond_debug_register(struct bonding *bond); + void bond_debug_unregister(struct bonding *bond); + void bond_debug_reregister(struct bonding *bond); + const char *bond_mode_name(int mode); ++bool bond_xdp_check(struct bonding *bond, int mode); + void bond_setup(struct net_device *bond_dev); + unsigned int bond_get_num_tx_queues(void); + int bond_netlink_init(void); +-- +2.39.5 + diff --git a/queue-6.14/bpf-fix-array-bounds-error-with-may_goto.patch b/queue-6.14/bpf-fix-array-bounds-error-with-may_goto.patch new file mode 100644 index 0000000000..13471c05f6 --- /dev/null +++ b/queue-6.14/bpf-fix-array-bounds-error-with-may_goto.patch @@ -0,0 +1,102 @@ +From c6c22a4a90e96b65f4e90a626982f65b5381c160 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 17:18:21 +0800 +Subject: bpf: Fix array bounds error with may_goto + +From: Jiayuan Chen + +[ Upstream commit 6ebc5030e0c5a698f1dd9a6684cddf6ccaed64a0 ] + +may_goto uses an additional 8 bytes on the stack, which causes the +interpreters[] array to go out of bounds when calculating index by +stack_size. + +1. If a BPF program is rewritten, re-evaluate the stack size. For non-JIT +cases, reject loading directly. + +2. For non-JIT cases, calculating interpreters[idx] may still cause +out-of-bounds array access, and just warn about it. + +3. For jit_requested cases, the execution of bpf_func also needs to be +warned. So move the definition of function __bpf_prog_ret0_warn out of +the macro definition CONFIG_BPF_JIT_ALWAYS_ON. + +Reported-by: syzbot+d2a2c639d03ac200a4f1@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/bpf/0000000000000f823606139faa5d@google.com/ +Fixes: 011832b97b311 ("bpf: Introduce may_goto instruction") +Signed-off-by: Jiayuan Chen +Link: https://lore.kernel.org/r/20250214091823.46042-2-mrpre@163.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/core.c | 19 +++++++++++++++---- + kernel/bpf/verifier.c | 7 +++++++ + 2 files changed, 22 insertions(+), 4 deletions(-) + +diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c +index da729cbbaeb90..a0200fbbace99 100644 +--- a/kernel/bpf/core.c ++++ b/kernel/bpf/core.c +@@ -2290,17 +2290,18 @@ void bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth) + insn->code = BPF_JMP | BPF_CALL_ARGS; + } + #endif +-#else ++#endif ++ + static unsigned int __bpf_prog_ret0_warn(const void *ctx, + const struct bpf_insn *insn) + { + /* If this handler ever gets executed, then BPF_JIT_ALWAYS_ON +- * is not working properly, so warn about it! ++ * is not working properly, or interpreter is being used when ++ * prog->jit_requested is not 0, so warn about it! + */ + WARN_ON_ONCE(1); + return 0; + } +-#endif + + bool bpf_prog_map_compatible(struct bpf_map *map, + const struct bpf_prog *fp) +@@ -2380,8 +2381,18 @@ static void bpf_prog_select_func(struct bpf_prog *fp) + { + #ifndef CONFIG_BPF_JIT_ALWAYS_ON + u32 stack_depth = max_t(u32, fp->aux->stack_depth, 1); ++ u32 idx = (round_up(stack_depth, 32) / 32) - 1; + +- fp->bpf_func = interpreters[(round_up(stack_depth, 32) / 32) - 1]; ++ /* may_goto may cause stack size > 512, leading to idx out-of-bounds. ++ * But for non-JITed programs, we don't need bpf_func, so no bounds ++ * check needed. ++ */ ++ if (!fp->jit_requested && ++ !WARN_ON_ONCE(idx >= ARRAY_SIZE(interpreters))) { ++ fp->bpf_func = interpreters[idx]; ++ } else { ++ fp->bpf_func = __bpf_prog_ret0_warn; ++ } + #else + fp->bpf_func = __bpf_prog_ret0_warn; + #endif +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 60611df77957a..c6f3b5f4ff2be 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -21897,6 +21897,13 @@ static int do_misc_fixups(struct bpf_verifier_env *env) + if (subprogs[cur_subprog + 1].start == i + delta + 1) { + subprogs[cur_subprog].stack_depth += stack_depth_extra; + subprogs[cur_subprog].stack_extra = stack_depth_extra; ++ ++ stack_depth = subprogs[cur_subprog].stack_depth; ++ if (stack_depth > MAX_BPF_STACK && !prog->jit_requested) { ++ verbose(env, "stack size %d(extra %d) is too large\n", ++ stack_depth, stack_depth_extra); ++ return -EINVAL; ++ } + cur_subprog++; + stack_depth = subprogs[cur_subprog].stack_depth; + stack_depth_extra = 0; +-- +2.39.5 + diff --git a/queue-6.14/bpf-use-preempt_count-directly-in-bpf_send_signal_co.patch b/queue-6.14/bpf-use-preempt_count-directly-in-bpf_send_signal_co.patch new file mode 100644 index 0000000000..0f68bc2d5c --- /dev/null +++ b/queue-6.14/bpf-use-preempt_count-directly-in-bpf_send_signal_co.patch @@ -0,0 +1,47 @@ +From aca870978c3660d28dcba346e34cb6304e68256e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 12:22:59 +0800 +Subject: bpf: Use preempt_count() directly in bpf_send_signal_common() + +From: Hou Tao + +[ Upstream commit b4a8b5bba712a711d8ca1f7d04646db63f9c88f5 ] + +bpf_send_signal_common() uses preemptible() to check whether or not the +current context is preemptible. If it is preemptible, it will use +irq_work to send the signal asynchronously instead of trying to hold a +spin-lock, because spin-lock is sleepable under PREEMPT_RT. + +However, preemptible() depends on CONFIG_PREEMPT_COUNT. When +CONFIG_PREEMPT_COUNT is turned off (e.g., CONFIG_PREEMPT_VOLUNTARY=y), +!preemptible() will be evaluated as 1 and bpf_send_signal_common() will +use irq_work unconditionally. + +Fix it by unfolding "!preemptible()" and using "preempt_count() != 0 || +irqs_disabled()" instead. + +Fixes: 87c544108b61 ("bpf: Send signals asynchronously if !preemptible") +Signed-off-by: Hou Tao +Link: https://lore.kernel.org/r/20250220042259.1583319-1-houtao@huaweicloud.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/trace/bpf_trace.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c +index adc947587eb81..a612f6f182e51 100644 +--- a/kernel/trace/bpf_trace.c ++++ b/kernel/trace/bpf_trace.c +@@ -843,7 +843,7 @@ static int bpf_send_signal_common(u32 sig, enum pid_type type, struct task_struc + if (unlikely(is_global_init(task))) + return -EPERM; + +- if (!preemptible()) { ++ if (preempt_count() != 0 || irqs_disabled()) { + /* Do an early check on signal validity. Otherwise, + * the error is lost in deferred irq_work. + */ +-- +2.39.5 + diff --git a/queue-6.14/broadcom-fix-supported-flag-check-in-periodic-output.patch b/queue-6.14/broadcom-fix-supported-flag-check-in-periodic-output.patch new file mode 100644 index 0000000000..fcab0bbd4e --- /dev/null +++ b/queue-6.14/broadcom-fix-supported-flag-check-in-periodic-output.patch @@ -0,0 +1,45 @@ +From aa53dd267268671b7afc038a24ba8c62921e5ce0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 15:15:53 -0700 +Subject: broadcom: fix supported flag check in periodic output function + +From: Jacob Keller + +[ Upstream commit af2b428f7992c07b0767c9a3c341b54d9069542e ] + +In bcm_ptp_perout_locked, the driver rejects requests which have +PTP_PEROUT_PHASE set. This appears to be an attempt to reject any +unsupported flags. Unfortunately, this only checks one flag, but does not +protect against PTP_PEROUT_ONE_SHOT, or any future flags which may be +added. + +Fix the check to ensure that no flag other than the supported +PTP_PEROUT_DUTY_CYCLE is set. + +Fixes: 7bfe91efd525 ("net: phy: Add support for 1PPS out and external timestamps") +Signed-off-by: Jacob Keller +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250312-jk-net-fixes-supported-extts-flags-v2-4-ea930ba82459@intel.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/phy/bcm-phy-ptp.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/phy/bcm-phy-ptp.c b/drivers/net/phy/bcm-phy-ptp.c +index 208e8f561e069..eba8b5fb1365f 100644 +--- a/drivers/net/phy/bcm-phy-ptp.c ++++ b/drivers/net/phy/bcm-phy-ptp.c +@@ -597,7 +597,8 @@ static int bcm_ptp_perout_locked(struct bcm_ptp_private *priv, + + period = BCM_MAX_PERIOD_8NS; /* write nonzero value */ + +- if (req->flags & PTP_PEROUT_PHASE) ++ /* Reject unsupported flags */ ++ if (req->flags & ~PTP_PEROUT_DUTY_CYCLE) + return -EOPNOTSUPP; + + if (req->flags & PTP_PEROUT_DUTY_CYCLE) +-- +2.39.5 + diff --git a/queue-6.14/btrfs-don-t-clobber-ret-in-btrfs_validate_super.patch b/queue-6.14/btrfs-don-t-clobber-ret-in-btrfs_validate_super.patch new file mode 100644 index 0000000000..a852ba6cd5 --- /dev/null +++ b/queue-6.14/btrfs-don-t-clobber-ret-in-btrfs_validate_super.patch @@ -0,0 +1,42 @@ +From 9f8f951678a86d65c0fc6cb58ae972abf745d028 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 16:39:25 +0000 +Subject: btrfs: don't clobber ret in btrfs_validate_super() + +From: Mark Harmstone + +[ Upstream commit 9db9c7dd5b4e1d3205137a094805980082c37716 ] + +Commit 2a9bb78cfd36 ("btrfs: validate system chunk array at +btrfs_validate_super()") introduces a call to validate_sys_chunk_array() +in btrfs_validate_super(), which clobbers the value of ret set earlier. +This has the effect of negating the validity checks done earlier, making +it so btrfs could potentially try to mount invalid filesystems. + +Fixes: 2a9bb78cfd36 ("btrfs: validate system chunk array at btrfs_validate_super()") +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/disk-io.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c +index f09db62e61a1b..70b61bc237e98 100644 +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -2561,6 +2561,9 @@ int btrfs_validate_super(const struct btrfs_fs_info *fs_info, + ret = -EINVAL; + } + ++ if (ret) ++ return ret; ++ + ret = validate_sys_chunk_array(fs_info, sb); + + /* +-- +2.39.5 + diff --git a/queue-6.14/btrfs-fix-block-group-refcount-race-in-btrfs_create_.patch b/queue-6.14/btrfs-fix-block-group-refcount-race-in-btrfs_create_.patch new file mode 100644 index 0000000000..2c07b1014c --- /dev/null +++ b/queue-6.14/btrfs-fix-block-group-refcount-race-in-btrfs_create_.patch @@ -0,0 +1,113 @@ +From 060790d9734f67d2bc10039d1a9867103c3b08a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 15:03:13 -0800 +Subject: btrfs: fix block group refcount race in + btrfs_create_pending_block_groups() + +From: Boris Burkov + +[ Upstream commit 2d8e5168d48a91e7a802d3003e72afb4304bebfa ] + +Block group creation is done in two phases, which results in a slightly +unintuitive property: a block group can be allocated/deallocated from +after btrfs_make_block_group() adds it to the space_info with +btrfs_add_bg_to_space_info(), but before creation is completely completed +in btrfs_create_pending_block_groups(). As a result, it is possible for a +block group to go unused and have 'btrfs_mark_bg_unused' called on it +concurrently with 'btrfs_create_pending_block_groups'. This causes a +number of issues, which were fixed with the block group flag +'BLOCK_GROUP_FLAG_NEW'. + +However, this fix is not quite complete. Since it does not use the +unused_bg_lock, it is possible for the following race to occur: + +btrfs_create_pending_block_groups btrfs_mark_bg_unused + if list_empty // false + list_del_init + clear_bit + else if (test_bit) // true + list_move_tail + +And we get into the exact same broken ref count and invalid new_bgs +state for transaction cleanup that BLOCK_GROUP_FLAG_NEW was designed to +prevent. + +The broken refcount aspect will result in a warning like: + + [1272.943527] refcount_t: underflow; use-after-free. + [1272.943967] WARNING: CPU: 1 PID: 61 at lib/refcount.c:28 refcount_warn_saturate+0xba/0x110 + [1272.944731] Modules linked in: btrfs virtio_net xor zstd_compress raid6_pq null_blk [last unloaded: btrfs] + [1272.945550] CPU: 1 UID: 0 PID: 61 Comm: kworker/u32:1 Kdump: loaded Tainted: G W 6.14.0-rc5+ #108 + [1272.946368] Tainted: [W]=WARN + [1272.946585] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.16.3-1-1 04/01/2014 + [1272.947273] Workqueue: btrfs_discard btrfs_discard_workfn [btrfs] + [1272.947788] RIP: 0010:refcount_warn_saturate+0xba/0x110 + [1272.949532] RSP: 0018:ffffbf1200247df0 EFLAGS: 00010282 + [1272.949901] RAX: 0000000000000000 RBX: ffffa14b00e3f800 RCX: 0000000000000000 + [1272.950437] RDX: 0000000000000000 RSI: ffffbf1200247c78 RDI: 00000000ffffdfff + [1272.950986] RBP: ffffa14b00dc2860 R08: 00000000ffffdfff R09: ffffffff90526268 + [1272.951512] R10: ffffffff904762c0 R11: 0000000063666572 R12: ffffa14b00dc28c0 + [1272.952024] R13: 0000000000000000 R14: ffffa14b00dc2868 R15: 000001285dcd12c0 + [1272.952850] FS: 0000000000000000(0000) GS:ffffa14d33c40000(0000) knlGS:0000000000000000 + [1272.953458] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + [1272.953931] CR2: 00007f838cbda000 CR3: 000000010104e000 CR4: 00000000000006f0 + [1272.954474] Call Trace: + [1272.954655] + [1272.954812] ? refcount_warn_saturate+0xba/0x110 + [1272.955173] ? __warn.cold+0x93/0xd7 + [1272.955487] ? refcount_warn_saturate+0xba/0x110 + [1272.955816] ? report_bug+0xe7/0x120 + [1272.956103] ? handle_bug+0x53/0x90 + [1272.956424] ? exc_invalid_op+0x13/0x60 + [1272.956700] ? asm_exc_invalid_op+0x16/0x20 + [1272.957011] ? refcount_warn_saturate+0xba/0x110 + [1272.957399] btrfs_discard_cancel_work.cold+0x26/0x2b [btrfs] + [1272.957853] btrfs_put_block_group.cold+0x5d/0x8e [btrfs] + [1272.958289] btrfs_discard_workfn+0x194/0x380 [btrfs] + [1272.958729] process_one_work+0x130/0x290 + [1272.959026] worker_thread+0x2ea/0x420 + [1272.959335] ? __pfx_worker_thread+0x10/0x10 + [1272.959644] kthread+0xd7/0x1c0 + [1272.959872] ? __pfx_kthread+0x10/0x10 + [1272.960172] ret_from_fork+0x30/0x50 + [1272.960474] ? __pfx_kthread+0x10/0x10 + [1272.960745] ret_from_fork_asm+0x1a/0x30 + [1272.961035] + [1272.961238] ---[ end trace 0000000000000000 ]--- + +Though we have seen them in the async discard workfn as well. It is +most likely to happen after a relocation finishes which cancels discard, +tears down the block group, etc. + +Fix this fully by taking the lock around the list_del_init + clear_bit +so that the two are done atomically. + +Fixes: 0657b20c5a76 ("btrfs: fix use-after-free of new block group that became unused") +Reviewed-by: Qu Wenruo +Reviewed-by: Filipe Manana +Signed-off-by: Boris Burkov +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/block-group.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c +index 3a89a6c3a7aa1..b96b235943344 100644 +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -2796,8 +2796,11 @@ void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans) + /* Already aborted the transaction if it failed. */ + next: + btrfs_dec_delayed_refs_rsv_bg_inserts(fs_info); ++ ++ spin_lock(&fs_info->unused_bgs_lock); + list_del_init(&block_group->bg_list); + clear_bit(BLOCK_GROUP_FLAG_NEW, &block_group->runtime_flags); ++ spin_unlock(&fs_info->unused_bgs_lock); + + /* + * If the block group is still unused, add it to the list of +-- +2.39.5 + diff --git a/queue-6.14/btrfs-fix-reclaimed-bytes-accounting-after-automatic.patch b/queue-6.14/btrfs-fix-reclaimed-bytes-accounting-after-automatic.patch new file mode 100644 index 0000000000..f4943d6122 --- /dev/null +++ b/queue-6.14/btrfs-fix-reclaimed-bytes-accounting-after-automatic.patch @@ -0,0 +1,128 @@ +From c659b36d65c1bd7e2f79e836cb0be25637a217db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 16:22:22 +0000 +Subject: btrfs: fix reclaimed bytes accounting after automatic block group + reclaim + +From: Filipe Manana + +[ Upstream commit 620768704326c9a71ea9c8324ffda8748d8d4f10 ] + +We are considering the used bytes counter of a block group as the amount +to update the space info's reclaim bytes counter after relocating the +block group, but this value alone is often not enough. This is because we +may have a reserved extent (or more) and in that case its size is +reflected in the reserved counter of the block group - the size of the +extent is only transferred from the reserved counter to the used counter +of the block group when the delayed ref for the extent is run - typically +when committing the transaction (or when flushing delayed refs due to +ENOSPC on space reservation). Such call chain for data extents is: + + btrfs_run_delayed_refs_for_head() + run_one_delayed_ref() + run_delayed_data_ref() + alloc_reserved_file_extent() + alloc_reserved_extent() + btrfs_update_block_group() + -> transfers the extent size from the reserved + counter to the used counter + +For metadata extents: + + btrfs_run_delayed_refs_for_head() + run_one_delayed_ref() + run_delayed_tree_ref() + alloc_reserved_tree_block() + alloc_reserved_extent() + btrfs_update_block_group() + -> transfers the extent size from the reserved + counter to the used counter + +Since relocation flushes delalloc, waits for ordered extent completion +and commits the current transaction before doing the actual relocation +work, the correct amount of reclaimed space is therefore the sum of the +"used" and "reserved" counters of the block group before we call +btrfs_relocate_chunk() at btrfs_reclaim_bgs_work(). + +So fix this by taking the "reserved" counter into consideration. + +Fixes: 243192b67649 ("btrfs: report reclaim stats in sysfs") +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/block-group.c | 28 +++++++++++++++++++++------- + 1 file changed, 21 insertions(+), 7 deletions(-) + +diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c +index ed0b1a955d74a..3a89a6c3a7aa1 100644 +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -1824,6 +1824,7 @@ void btrfs_reclaim_bgs_work(struct work_struct *work) + while (!list_empty(&fs_info->reclaim_bgs)) { + u64 zone_unusable; + u64 used; ++ u64 reserved; + int ret = 0; + + bg = list_first_entry(&fs_info->reclaim_bgs, +@@ -1916,21 +1917,32 @@ void btrfs_reclaim_bgs_work(struct work_struct *work) + goto next; + + /* +- * Grab the used bytes counter while holding the block group's +- * spinlock to prevent races with tasks concurrently updating it +- * due to extent allocation and deallocation (running +- * btrfs_update_block_group()) - we have set the block group to +- * RO but that only prevents extent reservation, allocation +- * happens after reservation. ++ * The amount of bytes reclaimed corresponds to the sum of the ++ * "used" and "reserved" counters. We have set the block group ++ * to RO above, which prevents reservations from happening but ++ * we may have existing reservations for which allocation has ++ * not yet been done - btrfs_update_block_group() was not yet ++ * called, which is where we will transfer a reserved extent's ++ * size from the "reserved" counter to the "used" counter - this ++ * happens when running delayed references. When we relocate the ++ * chunk below, relocation first flushes dellaloc, waits for ++ * ordered extent completion (which is where we create delayed ++ * references for data extents) and commits the current ++ * transaction (which runs delayed references), and only after ++ * it does the actual work to move extents out of the block ++ * group. So the reported amount of reclaimed bytes is ++ * effectively the sum of the 'used' and 'reserved' counters. + */ + spin_lock(&bg->lock); + used = bg->used; ++ reserved = bg->reserved; + spin_unlock(&bg->lock); + + btrfs_info(fs_info, +- "reclaiming chunk %llu with %llu%% used %llu%% unusable", ++ "reclaiming chunk %llu with %llu%% used %llu%% reserved %llu%% unusable", + bg->start, + div64_u64(used * 100, bg->length), ++ div64_u64(reserved * 100, bg->length), + div64_u64(zone_unusable * 100, bg->length)); + trace_btrfs_reclaim_block_group(bg); + ret = btrfs_relocate_chunk(fs_info, bg->start); +@@ -1939,6 +1951,7 @@ void btrfs_reclaim_bgs_work(struct work_struct *work) + btrfs_err(fs_info, "error relocating chunk %llu", + bg->start); + used = 0; ++ reserved = 0; + spin_lock(&space_info->lock); + space_info->reclaim_errors++; + if (READ_ONCE(space_info->periodic_reclaim)) +@@ -1948,6 +1961,7 @@ void btrfs_reclaim_bgs_work(struct work_struct *work) + spin_lock(&space_info->lock); + space_info->reclaim_count++; + space_info->reclaim_bytes += used; ++ space_info->reclaim_bytes += reserved; + spin_unlock(&space_info->lock); + + next: +-- +2.39.5 + diff --git a/queue-6.14/btrfs-get-used-bytes-while-holding-lock-at-btrfs_rec.patch b/queue-6.14/btrfs-get-used-bytes-while-holding-lock-at-btrfs_rec.patch new file mode 100644 index 0000000000..21088ff7fa --- /dev/null +++ b/queue-6.14/btrfs-get-used-bytes-while-holding-lock-at-btrfs_rec.patch @@ -0,0 +1,88 @@ +From 4abecc47eec15e60389d368a028cb064117870a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 15:40:26 +0000 +Subject: btrfs: get used bytes while holding lock at btrfs_reclaim_bgs_work() + +From: Filipe Manana + +[ Upstream commit ba5d06440cae63edc4f49465baf78f1f43e55c77 ] + +At btrfs_reclaim_bgs_work(), we are grabbing twice the used bytes counter +of the block group while not holding the block group's spinlock. This can +result in races, reported by KCSAN and similar tools, since a concurrent +task can be updating that counter while at btrfs_update_block_group(). + +So avoid these races by grabbing the counter in a critical section +delimited by the block group's spinlock after setting the block group to +RO mode. This also avoids using two different values of the counter in +case it changes in between each read. This silences KCSAN and is required +for the next patch in the series too. + +Fixes: 243192b67649 ("btrfs: report reclaim stats in sysfs") +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/block-group.c | 21 ++++++++++++++++----- + 1 file changed, 16 insertions(+), 5 deletions(-) + +diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c +index c0a8f7d92acc5..ed0b1a955d74a 100644 +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -1823,7 +1823,7 @@ void btrfs_reclaim_bgs_work(struct work_struct *work) + list_sort(NULL, &fs_info->reclaim_bgs, reclaim_bgs_cmp); + while (!list_empty(&fs_info->reclaim_bgs)) { + u64 zone_unusable; +- u64 reclaimed; ++ u64 used; + int ret = 0; + + bg = list_first_entry(&fs_info->reclaim_bgs, +@@ -1915,19 +1915,30 @@ void btrfs_reclaim_bgs_work(struct work_struct *work) + if (ret < 0) + goto next; + ++ /* ++ * Grab the used bytes counter while holding the block group's ++ * spinlock to prevent races with tasks concurrently updating it ++ * due to extent allocation and deallocation (running ++ * btrfs_update_block_group()) - we have set the block group to ++ * RO but that only prevents extent reservation, allocation ++ * happens after reservation. ++ */ ++ spin_lock(&bg->lock); ++ used = bg->used; ++ spin_unlock(&bg->lock); ++ + btrfs_info(fs_info, + "reclaiming chunk %llu with %llu%% used %llu%% unusable", + bg->start, +- div64_u64(bg->used * 100, bg->length), ++ div64_u64(used * 100, bg->length), + div64_u64(zone_unusable * 100, bg->length)); + trace_btrfs_reclaim_block_group(bg); +- reclaimed = bg->used; + ret = btrfs_relocate_chunk(fs_info, bg->start); + if (ret) { + btrfs_dec_block_group_ro(bg); + btrfs_err(fs_info, "error relocating chunk %llu", + bg->start); +- reclaimed = 0; ++ used = 0; + spin_lock(&space_info->lock); + space_info->reclaim_errors++; + if (READ_ONCE(space_info->periodic_reclaim)) +@@ -1936,7 +1947,7 @@ void btrfs_reclaim_bgs_work(struct work_struct *work) + } + spin_lock(&space_info->lock); + space_info->reclaim_count++; +- space_info->reclaim_bytes += reclaimed; ++ space_info->reclaim_bytes += used; + spin_unlock(&space_info->lock); + + next: +-- +2.39.5 + diff --git a/queue-6.14/bus-qcom-ssc-block-bus-fix-the-error-handling-path-o.patch b/queue-6.14/bus-qcom-ssc-block-bus-fix-the-error-handling-path-o.patch new file mode 100644 index 0000000000..810efa66d7 --- /dev/null +++ b/queue-6.14/bus-qcom-ssc-block-bus-fix-the-error-handling-path-o.patch @@ -0,0 +1,84 @@ +From e0694c2bcd5c5ea015a6fd635197959fe212dc8e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Mar 2025 17:21:35 +0100 +Subject: bus: qcom-ssc-block-bus: Fix the error handling path of + qcom_ssc_block_bus_probe() + +From: Christophe JAILLET + +[ Upstream commit f41658cd081ad7697796b3dacd9a717a57919268 ] + +If qcom_ssc_block_bus_pds_enable() fails, the previous call to +qcom_ssc_block_bus_pds_attach() must be undone, as already done in the +remove function. + +In order to do that, move the code related to the power domains management +to the end of the function, in order to avoid many changes in all the error +handling path that would need to go through the new error handling path. + +Fixes: 97d485edc1d9 ("bus: add driver for initializing the SSC bus on (some) qcom SoCs") +Signed-off-by: Christophe JAILLET +Link: https://lore.kernel.org/r/1b89ec7438c9a893c09083e8591772c8ad3cb599.1740932040.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/bus/qcom-ssc-block-bus.c | 31 +++++++++++++++++++------------ + 1 file changed, 19 insertions(+), 12 deletions(-) + +diff --git a/drivers/bus/qcom-ssc-block-bus.c b/drivers/bus/qcom-ssc-block-bus.c +index c95a985e34988..7f5fd4e0940dc 100644 +--- a/drivers/bus/qcom-ssc-block-bus.c ++++ b/drivers/bus/qcom-ssc-block-bus.c +@@ -264,18 +264,6 @@ static int qcom_ssc_block_bus_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, data); + +- data->pd_names = qcom_ssc_block_pd_names; +- data->num_pds = ARRAY_SIZE(qcom_ssc_block_pd_names); +- +- /* power domains */ +- ret = qcom_ssc_block_bus_pds_attach(&pdev->dev, data->pds, data->pd_names, data->num_pds); +- if (ret < 0) +- return dev_err_probe(&pdev->dev, ret, "error when attaching power domains\n"); +- +- ret = qcom_ssc_block_bus_pds_enable(data->pds, data->num_pds); +- if (ret < 0) +- return dev_err_probe(&pdev->dev, ret, "error when enabling power domains\n"); +- + /* low level overrides for when the HW logic doesn't "just work" */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpm_sscaon_config0"); + data->reg_mpm_sscaon_config0 = devm_ioremap_resource(&pdev->dev, res); +@@ -343,11 +331,30 @@ static int qcom_ssc_block_bus_probe(struct platform_device *pdev) + + data->ssc_axi_halt = halt_args.args[0]; + ++ /* power domains */ ++ data->pd_names = qcom_ssc_block_pd_names; ++ data->num_pds = ARRAY_SIZE(qcom_ssc_block_pd_names); ++ ++ ret = qcom_ssc_block_bus_pds_attach(&pdev->dev, data->pds, data->pd_names, data->num_pds); ++ if (ret < 0) ++ return dev_err_probe(&pdev->dev, ret, "error when attaching power domains\n"); ++ ++ ret = qcom_ssc_block_bus_pds_enable(data->pds, data->num_pds); ++ if (ret < 0) { ++ dev_err_probe(&pdev->dev, ret, "error when enabling power domains\n"); ++ goto err_detach_pds_bus; ++ } ++ + qcom_ssc_block_bus_init(&pdev->dev); + + of_platform_populate(np, NULL, NULL, &pdev->dev); + + return 0; ++ ++err_detach_pds_bus: ++ qcom_ssc_block_bus_pds_detach(&pdev->dev, data->pds, data->num_pds); ++ ++ return ret; + } + + static void qcom_ssc_block_bus_remove(struct platform_device *pdev) +-- +2.39.5 + diff --git a/queue-6.14/bus-qcom-ssc-block-bus-remove-some-duplicated-iounma.patch b/queue-6.14/bus-qcom-ssc-block-bus-remove-some-duplicated-iounma.patch new file mode 100644 index 0000000000..326ac39a74 --- /dev/null +++ b/queue-6.14/bus-qcom-ssc-block-bus-remove-some-duplicated-iounma.patch @@ -0,0 +1,41 @@ +From 71faa339348263af2e408b16626c076935d71de2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Mar 2025 17:21:34 +0100 +Subject: bus: qcom-ssc-block-bus: Remove some duplicated iounmap() calls + +From: Christophe JAILLET + +[ Upstream commit a9ac4ba7dcace2b3b91e7b87bf0ba97c47edd94f ] + +reg_mpm_sscaon_config[01] are allocated with devm_ioremap_resource(). So, +they will be unmapped automatically by the manage resource framework. + +Remove the incorrect explicit iounmap() calls from the remove function. + +Fixes: 97d485edc1d9 ("bus: add driver for initializing the SSC bus on (some) qcom SoCs") +Signed-off-by: Christophe JAILLET +Reviewed-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/efd06711b126e761a06eb5ef82daf9ad4e116a10.1740932040.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/bus/qcom-ssc-block-bus.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/drivers/bus/qcom-ssc-block-bus.c b/drivers/bus/qcom-ssc-block-bus.c +index 85d781a32df4b..c95a985e34988 100644 +--- a/drivers/bus/qcom-ssc-block-bus.c ++++ b/drivers/bus/qcom-ssc-block-bus.c +@@ -356,9 +356,6 @@ static void qcom_ssc_block_bus_remove(struct platform_device *pdev) + + qcom_ssc_block_bus_deinit(&pdev->dev); + +- iounmap(data->reg_mpm_sscaon_config0); +- iounmap(data->reg_mpm_sscaon_config1); +- + qcom_ssc_block_bus_pds_disable(data->pds, data->num_pds); + qcom_ssc_block_bus_pds_detach(&pdev->dev, data->pds, data->num_pds); + pm_runtime_disable(&pdev->dev); +-- +2.39.5 + diff --git a/queue-6.14/can-rockchip_canfd-rkcanfd_chip_fifo_setup-remove-du.patch b/queue-6.14/can-rockchip_canfd-rkcanfd_chip_fifo_setup-remove-du.patch new file mode 100644 index 0000000000..a474e08b08 --- /dev/null +++ b/queue-6.14/can-rockchip_canfd-rkcanfd_chip_fifo_setup-remove-du.patch @@ -0,0 +1,45 @@ +From 81701b83b5f21cfe5efe3cd21641731e555ae289 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Jan 2025 13:16:44 +0100 +Subject: can: rockchip_canfd: rkcanfd_chip_fifo_setup(): remove duplicated + setup of RX FIFO + +From: Robin van der Gracht + +[ Upstream commit d9e1cc087a55286fe028e0f078159b30d7da90bd ] + +The rockchip_canfd driver doesn't make use of the TXE FIFO. + +Although the comment states that the TXE FIFO is setup, it's actually +a setup of the RX FIFO. The regular setup of the RX FIFO follows. + +Remove the duplicated setup of the RX FIFO. + +Fixes: ff60bfbaf67f ("can: rockchip_canfd: add driver for Rockchip CAN-FD controller") +Signed-off-by: Robin van der Gracht +Link: https://patch.msgid.link/20250219-rk3568-canfd-v1-1-453869358c72@pengutronix.de +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/rockchip/rockchip_canfd-core.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/drivers/net/can/rockchip/rockchip_canfd-core.c b/drivers/net/can/rockchip/rockchip_canfd-core.c +index d9a937ba126c3..46201c126703c 100644 +--- a/drivers/net/can/rockchip/rockchip_canfd-core.c ++++ b/drivers/net/can/rockchip/rockchip_canfd-core.c +@@ -236,11 +236,6 @@ static void rkcanfd_chip_fifo_setup(struct rkcanfd_priv *priv) + { + u32 reg; + +- /* TXE FIFO */ +- reg = rkcanfd_read(priv, RKCANFD_REG_RX_FIFO_CTRL); +- reg |= RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_ENABLE; +- rkcanfd_write(priv, RKCANFD_REG_RX_FIFO_CTRL, reg); +- + /* RX FIFO */ + reg = rkcanfd_read(priv, RKCANFD_REG_RX_FIFO_CTRL); + reg |= RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_ENABLE; +-- +2.39.5 + diff --git a/queue-6.14/clk-amlogic-g12a-fix-mmc-a-peripheral-clock.patch b/queue-6.14/clk-amlogic-g12a-fix-mmc-a-peripheral-clock.patch new file mode 100644 index 0000000000..9d48591cfe --- /dev/null +++ b/queue-6.14/clk-amlogic-g12a-fix-mmc-a-peripheral-clock.patch @@ -0,0 +1,45 @@ +From 78494485e4126a52cf4f092f4d50ee0e4fabc8d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Dec 2024 11:03:23 +0100 +Subject: clk: amlogic: g12a: fix mmc A peripheral clock + +From: Jerome Brunet + +[ Upstream commit 0079e77c08de692cb20b38e408365c830a44b1ef ] + +The bit index of the peripheral clock for mmc A is wrong +This was probably not a problem for mmc A as the peripheral is likely left +enabled by the bootloader. + +No issues has been reported so far but it could be a problem, most likely +some form of conflict between the ethernet and mmc A clock, breaking +ethernet on init. + +Use the value provided by the documentation for mmc A before this +becomes an actual problem. + +Fixes: 085a4ea93d54 ("clk: meson: g12a: add peripheral clock controller") +Reviewed-by: Neil Armstrong +Link: https://lore.kernel.org/r/20241213-amlogic-clk-g12a-mmca-fix-v1-1-5af421f58b64@baylibre.com +Signed-off-by: Jerome Brunet +Signed-off-by: Sasha Levin +--- + drivers/clk/meson/g12a.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c +index 563759c51f747..ceabebb1863d6 100644 +--- a/drivers/clk/meson/g12a.c ++++ b/drivers/clk/meson/g12a.c +@@ -4323,7 +4323,7 @@ static MESON_GATE(g12a_spicc_1, HHI_GCLK_MPEG0, 14); + static MESON_GATE(g12a_hiu_reg, HHI_GCLK_MPEG0, 19); + static MESON_GATE(g12a_mipi_dsi_phy, HHI_GCLK_MPEG0, 20); + static MESON_GATE(g12a_assist_misc, HHI_GCLK_MPEG0, 23); +-static MESON_GATE(g12a_emmc_a, HHI_GCLK_MPEG0, 4); ++static MESON_GATE(g12a_emmc_a, HHI_GCLK_MPEG0, 24); + static MESON_GATE(g12a_emmc_b, HHI_GCLK_MPEG0, 25); + static MESON_GATE(g12a_emmc_c, HHI_GCLK_MPEG0, 26); + static MESON_GATE(g12a_audio_codec, HHI_GCLK_MPEG0, 28); +-- +2.39.5 + diff --git a/queue-6.14/clk-amlogic-g12b-fix-cluster-a-parent-data.patch b/queue-6.14/clk-amlogic-g12b-fix-cluster-a-parent-data.patch new file mode 100644 index 0000000000..7c80856dfb --- /dev/null +++ b/queue-6.14/clk-amlogic-g12b-fix-cluster-a-parent-data.patch @@ -0,0 +1,105 @@ +From a50f2a1b95d9fe71bc834afc3404998410cc1bce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Dec 2024 15:30:17 +0100 +Subject: clk: amlogic: g12b: fix cluster A parent data + +From: Jerome Brunet + +[ Upstream commit 8995f8f108c3ac5ad52b12a6cfbbc7b3b32e9a58 ] + +Several clocks used by both g12a and g12b use the g12a cpu A clock hw +pointer as clock parent. This is incorrect on g12b since the parents of +cluster A cpu clock are different. Also the hw clock provided as parent to +these children is not even registered clock on g12b. + +Fix the problem by reverting to the global namespace and let CCF pick +the appropriate, as it is already done for other clocks, such as +cpu_clk_trace_div. + +Fixes: 25e682a02d91 ("clk: meson: g12a: migrate to the new parent description method") +Reviewed-by: Neil Armstrong +Link: https://lore.kernel.org/r/20241213-amlogic-clk-g12a-cpua-parent-fix-v1-1-d8c0f41865fe@baylibre.com +Signed-off-by: Jerome Brunet +Signed-off-by: Sasha Levin +--- + drivers/clk/meson/g12a.c | 36 ++++++++++++++++++++++++------------ + 1 file changed, 24 insertions(+), 12 deletions(-) + +diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c +index cfffd434e998e..563759c51f747 100644 +--- a/drivers/clk/meson/g12a.c ++++ b/drivers/clk/meson/g12a.c +@@ -1137,8 +1137,18 @@ static struct clk_regmap g12a_cpu_clk_div16_en = { + .hw.init = &(struct clk_init_data) { + .name = "cpu_clk_div16_en", + .ops = &clk_regmap_gate_ro_ops, +- .parent_hws = (const struct clk_hw *[]) { +- &g12a_cpu_clk.hw ++ .parent_data = &(const struct clk_parent_data) { ++ /* ++ * Note: ++ * G12A and G12B have different cpu clocks (with ++ * different struct clk_hw). We fallback to the global ++ * naming string mechanism so this clock picks ++ * up the appropriate one. Same goes for the other ++ * clock using cpu cluster A clock output and present ++ * on both G12 variant. ++ */ ++ .name = "cpu_clk", ++ .index = -1, + }, + .num_parents = 1, + /* +@@ -1203,7 +1213,10 @@ static struct clk_regmap g12a_cpu_clk_apb_div = { + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk_apb_div", + .ops = &clk_regmap_divider_ro_ops, +- .parent_hws = (const struct clk_hw *[]) { &g12a_cpu_clk.hw }, ++ .parent_data = &(const struct clk_parent_data) { ++ .name = "cpu_clk", ++ .index = -1, ++ }, + .num_parents = 1, + }, + }; +@@ -1237,7 +1250,10 @@ static struct clk_regmap g12a_cpu_clk_atb_div = { + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk_atb_div", + .ops = &clk_regmap_divider_ro_ops, +- .parent_hws = (const struct clk_hw *[]) { &g12a_cpu_clk.hw }, ++ .parent_data = &(const struct clk_parent_data) { ++ .name = "cpu_clk", ++ .index = -1, ++ }, + .num_parents = 1, + }, + }; +@@ -1271,7 +1287,10 @@ static struct clk_regmap g12a_cpu_clk_axi_div = { + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk_axi_div", + .ops = &clk_regmap_divider_ro_ops, +- .parent_hws = (const struct clk_hw *[]) { &g12a_cpu_clk.hw }, ++ .parent_data = &(const struct clk_parent_data) { ++ .name = "cpu_clk", ++ .index = -1, ++ }, + .num_parents = 1, + }, + }; +@@ -1306,13 +1325,6 @@ static struct clk_regmap g12a_cpu_clk_trace_div = { + .name = "cpu_clk_trace_div", + .ops = &clk_regmap_divider_ro_ops, + .parent_data = &(const struct clk_parent_data) { +- /* +- * Note: +- * G12A and G12B have different cpu_clks (with +- * different struct clk_hw). We fallback to the global +- * naming string mechanism so cpu_clk_trace_div picks +- * up the appropriate one. +- */ + .name = "cpu_clk", + .index = -1, + }, +-- +2.39.5 + diff --git a/queue-6.14/clk-amlogic-gxbb-drop-incorrect-flag-on-32k-clock.patch b/queue-6.14/clk-amlogic-gxbb-drop-incorrect-flag-on-32k-clock.patch new file mode 100644 index 0000000000..96bf0d6d82 --- /dev/null +++ b/queue-6.14/clk-amlogic-gxbb-drop-incorrect-flag-on-32k-clock.patch @@ -0,0 +1,43 @@ +From 2f8d146cd080a55fbd95717269038c1459428053 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Dec 2024 11:25:36 +0100 +Subject: clk: amlogic: gxbb: drop incorrect flag on 32k clock + +From: Jerome Brunet + +[ Upstream commit f38f7fe4830c5cb4eac138249225f119e7939965 ] + +gxbb_32k_clk_div sets CLK_DIVIDER_ROUND_CLOSEST in the init_data flag which +is incorrect. This is field is not where the divider flags belong. + +Thankfully, CLK_DIVIDER_ROUND_CLOSEST maps to bit 4 which is an unused +clock flag, so there is no unintended consequence to this error. + +Effectively, the clock has been used without CLK_DIVIDER_ROUND_CLOSEST +so far, so just drop it. + +Fixes: 14c735c8e308 ("clk: meson-gxbb: Add EE 32K Clock for CEC") +Reviewed-by: Neil Armstrong +Link: https://lore.kernel.org/r/20241220-amlogic-clk-gxbb-32k-fixes-v1-1-baca56ecf2db@baylibre.com +Signed-off-by: Jerome Brunet +Signed-off-by: Sasha Levin +--- + drivers/clk/meson/gxbb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c +index 8575b84853859..df9250de51dc8 100644 +--- a/drivers/clk/meson/gxbb.c ++++ b/drivers/clk/meson/gxbb.c +@@ -1306,7 +1306,7 @@ static struct clk_regmap gxbb_32k_clk_div = { + &gxbb_32k_clk_sel.hw + }, + .num_parents = 1, +- .flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST, ++ .flags = CLK_SET_RATE_PARENT, + }, + }; + +-- +2.39.5 + diff --git a/queue-6.14/clk-amlogic-gxbb-drop-non-existing-32k-clock-parent.patch b/queue-6.14/clk-amlogic-gxbb-drop-non-existing-32k-clock-parent.patch new file mode 100644 index 0000000000..6f5086a394 --- /dev/null +++ b/queue-6.14/clk-amlogic-gxbb-drop-non-existing-32k-clock-parent.patch @@ -0,0 +1,62 @@ +From a53f7c7e6ed1e89c1ebd3b87a128a1cad5928be0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Dec 2024 11:25:37 +0100 +Subject: clk: amlogic: gxbb: drop non existing 32k clock parent + +From: Jerome Brunet + +[ Upstream commit 7915d7d5407c026fa9343befb4d3343f7a345f97 ] + +The 32k clock reference a parent 'cts_slow_oscin' with a fixme note saying +that this clock should be provided by AO controller. + +The HW probably has this clock but it does not exist at the moment in +any controller implementation. Furthermore, referencing clock by the global +name should be avoided whenever possible. + +There is no reason to keep this hack around, at least for now. + +Fixes: 14c735c8e308 ("clk: meson-gxbb: Add EE 32K Clock for CEC") +Reviewed-by: Neil Armstrong +Link: https://lore.kernel.org/r/20241220-amlogic-clk-gxbb-32k-fixes-v1-2-baca56ecf2db@baylibre.com +Signed-off-by: Jerome Brunet +Signed-off-by: Sasha Levin +--- + drivers/clk/meson/gxbb.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c +index df9250de51dc8..3abb44a2532b9 100644 +--- a/drivers/clk/meson/gxbb.c ++++ b/drivers/clk/meson/gxbb.c +@@ -1266,14 +1266,13 @@ static struct clk_regmap gxbb_cts_i958 = { + }, + }; + ++/* ++ * This table skips a clock named 'cts_slow_oscin' in the documentation ++ * This clock does not exist yet in this controller or the AO one ++ */ ++static u32 gxbb_32k_clk_parents_val_table[] = { 0, 2, 3 }; + static const struct clk_parent_data gxbb_32k_clk_parent_data[] = { + { .fw_name = "xtal", }, +- /* +- * FIXME: This clock is provided by the ao clock controller but the +- * clock is not yet part of the binding of this controller, so string +- * name must be use to set this parent. +- */ +- { .name = "cts_slow_oscin", .index = -1 }, + { .hw = &gxbb_fclk_div3.hw }, + { .hw = &gxbb_fclk_div5.hw }, + }; +@@ -1283,6 +1282,7 @@ static struct clk_regmap gxbb_32k_clk_sel = { + .offset = HHI_32K_CLK_CNTL, + .mask = 0x3, + .shift = 16, ++ .table = gxbb_32k_clk_parents_val_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "32k_clk_sel", +-- +2.39.5 + diff --git a/queue-6.14/clk-clk-imx8mp-audiomix-fix-dsp-ocram_a-clock-parent.patch b/queue-6.14/clk-clk-imx8mp-audiomix-fix-dsp-ocram_a-clock-parent.patch new file mode 100644 index 0000000000..1bc318d898 --- /dev/null +++ b/queue-6.14/clk-clk-imx8mp-audiomix-fix-dsp-ocram_a-clock-parent.patch @@ -0,0 +1,49 @@ +From 43431630cf05c3bc46d1c359cdb0875f46d30e64 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 11:45:11 -0500 +Subject: clk: clk-imx8mp-audiomix: fix dsp/ocram_a clock parents + +From: Laurentiu Mihalcea + +[ Upstream commit 91be7d27099dedf813b80702e4ca117d1fb38ce6 ] + +The DSP and OCRAM_A modules from AUDIOMIX are clocked by +AUDIO_AXI_CLK_ROOT, not AUDIO_AHB_CLK_ROOT. Update the clock data +accordingly. + +Fixes: 6cd95f7b151c ("clk: imx: imx8mp: Add audiomix block control") +Signed-off-by: Laurentiu Mihalcea +Reviewed-by: Iuliana Prodan +Reviewed-by: Peng Fan +Link: https://lore.kernel.org/r/20250226164513.33822-3-laurentiumihalcea111@gmail.com +Signed-off-by: Abel Vesa +Signed-off-by: Sasha Levin +--- + drivers/clk/imx/clk-imx8mp-audiomix.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/imx/clk-imx8mp-audiomix.c b/drivers/clk/imx/clk-imx8mp-audiomix.c +index c409fc7e06186..775f62dddb11d 100644 +--- a/drivers/clk/imx/clk-imx8mp-audiomix.c ++++ b/drivers/clk/imx/clk-imx8mp-audiomix.c +@@ -180,14 +180,14 @@ static struct clk_imx8mp_audiomix_sel sels[] = { + CLK_GATE("asrc", ASRC_IPG), + CLK_GATE("pdm", PDM_IPG), + CLK_GATE("earc", EARC_IPG), +- CLK_GATE("ocrama", OCRAMA_IPG), ++ CLK_GATE_PARENT("ocrama", OCRAMA_IPG, "axi"), + CLK_GATE("aud2htx", AUD2HTX_IPG), + CLK_GATE_PARENT("earc_phy", EARC_PHY, "sai_pll_out_div2"), + CLK_GATE("sdma2", SDMA2_ROOT), + CLK_GATE("sdma3", SDMA3_ROOT), + CLK_GATE("spba2", SPBA2_ROOT), +- CLK_GATE("dsp", DSP_ROOT), +- CLK_GATE("dspdbg", DSPDBG_ROOT), ++ CLK_GATE_PARENT("dsp", DSP_ROOT, "axi"), ++ CLK_GATE_PARENT("dspdbg", DSPDBG_ROOT, "axi"), + CLK_GATE("edma", EDMA_ROOT), + CLK_GATE_PARENT("audpll", AUDPLL_ROOT, "osc_24m"), + CLK_GATE("mu2", MU2_ROOT), +-- +2.39.5 + diff --git a/queue-6.14/clk-mmp-fix-null-vs-is_err-check.patch b/queue-6.14/clk-mmp-fix-null-vs-is_err-check.patch new file mode 100644 index 0000000000..cc59251343 --- /dev/null +++ b/queue-6.14/clk-mmp-fix-null-vs-is_err-check.patch @@ -0,0 +1,40 @@ +From 57eaf04d14a98d89512f0c8294a58e05f85a3357 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Mar 2025 14:47:07 +0800 +Subject: clk: mmp: Fix NULL vs IS_ERR() check + +From: Charles Han + +[ Upstream commit 00153c64a72d336cc61f4141e5be53b49b7797e1 ] + +The devm_kzalloc() function returns NULL on error, not error pointers. +Fix the check. + +Fixes: 03437e857b0a ("clk: mmp: Add Marvell PXA1908 APMU driver") +Signed-off-by: Charles Han +Link: https://lore.kernel.org/r/20250307064708.209511-1-hanchunchao@inspur.com +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/mmp/clk-pxa1908-apmu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/mmp/clk-pxa1908-apmu.c b/drivers/clk/mmp/clk-pxa1908-apmu.c +index 8cfb1258202f6..d3a070687fc5b 100644 +--- a/drivers/clk/mmp/clk-pxa1908-apmu.c ++++ b/drivers/clk/mmp/clk-pxa1908-apmu.c +@@ -87,8 +87,8 @@ static int pxa1908_apmu_probe(struct platform_device *pdev) + struct pxa1908_clk_unit *pxa_unit; + + pxa_unit = devm_kzalloc(&pdev->dev, sizeof(*pxa_unit), GFP_KERNEL); +- if (IS_ERR(pxa_unit)) +- return PTR_ERR(pxa_unit); ++ if (!pxa_unit) ++ return -ENOMEM; + + pxa_unit->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(pxa_unit->base)) +-- +2.39.5 + diff --git a/queue-6.14/clk-qcom-gcc-msm8953-fix-stuck-venus0_core0-clock.patch b/queue-6.14/clk-qcom-gcc-msm8953-fix-stuck-venus0_core0-clock.patch new file mode 100644 index 0000000000..68095c80ac --- /dev/null +++ b/queue-6.14/clk-qcom-gcc-msm8953-fix-stuck-venus0_core0-clock.patch @@ -0,0 +1,43 @@ +From 4a76881a4830ec110c37dc40c8917edbd55d0ab5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Mar 2025 16:26:18 +0100 +Subject: clk: qcom: gcc-msm8953: fix stuck venus0_core0 clock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Vladimir Lypak + +[ Upstream commit cdc59600bccf2cb4c483645438a97d4ec55f326b ] + +This clock can't be enable with VENUS_CORE0 GDSC turned off. But that +GDSC is under HW control so it can be turned off at any moment. +Instead of checking the dependent clock we can just vote for it to +enable later when GDSC gets turned on. + +Fixes: 9bb6cfc3c77e6 ("clk: qcom: Add Global Clock Controller driver for MSM8953") +Signed-off-by: Vladimir Lypak +Signed-off-by: Barnabás Czémán +Link: https://lore.kernel.org/r/20250315-clock-fix-v1-2-2efdc4920dda@mainlining.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/gcc-msm8953.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/qcom/gcc-msm8953.c b/drivers/clk/qcom/gcc-msm8953.c +index 855a61966f3ef..8f29ecc74c50b 100644 +--- a/drivers/clk/qcom/gcc-msm8953.c ++++ b/drivers/clk/qcom/gcc-msm8953.c +@@ -3770,7 +3770,7 @@ static struct clk_branch gcc_venus0_axi_clk = { + + static struct clk_branch gcc_venus0_core0_vcodec0_clk = { + .halt_reg = 0x4c02c, +- .halt_check = BRANCH_HALT, ++ .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x4c02c, + .enable_mask = BIT(0), +-- +2.39.5 + diff --git a/queue-6.14/clk-qcom-gcc-sm8650-do-not-turn-off-usb-gdscs-during.patch b/queue-6.14/clk-qcom-gcc-sm8650-do-not-turn-off-usb-gdscs-during.patch new file mode 100644 index 0000000000..5157b7b6fe --- /dev/null +++ b/queue-6.14/clk-qcom-gcc-sm8650-do-not-turn-off-usb-gdscs-during.patch @@ -0,0 +1,53 @@ +From cdfae3212b754eddd1f0dccae299bd12329aec6f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 20:00:29 +0100 +Subject: clk: qcom: gcc-sm8650: Do not turn off USB GDSCs during + gdsc_disable() + +From: Neil Armstrong + +[ Upstream commit 8b75c2973997e66fd897b7e87b5ba2f3d683e94b ] + +With PWRSTS_OFF_ON, USB GDSCs are turned off during gdsc_disable(). This +can happen during scenarios such as system suspend and breaks the resume +of USB controller from suspend. + +So use PWRSTS_RET_ON to indicate the GDSC driver to not turn off the GDSCs +during gdsc_disable() and allow the hardware to transition the GDSCs to +retention when the parent domain enters low power state during system +suspend. + +Fixes: c58225b7e3d7 ("clk: qcom: add the SM8650 Global Clock Controller driver, part 1") +Signed-off-by: Neil Armstrong +Link: https://lore.kernel.org/r/20250305-topic-sm8650-upstream-fix-usb-suspend-v1-1-649036ab0557@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/gcc-sm8650.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/qcom/gcc-sm8650.c b/drivers/clk/qcom/gcc-sm8650.c +index 9dd5c48f33bed..fa1672c4e7d81 100644 +--- a/drivers/clk/qcom/gcc-sm8650.c ++++ b/drivers/clk/qcom/gcc-sm8650.c +@@ -3497,7 +3497,7 @@ static struct gdsc usb30_prim_gdsc = { + .pd = { + .name = "usb30_prim_gdsc", + }, +- .pwrsts = PWRSTS_OFF_ON, ++ .pwrsts = PWRSTS_RET_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, + }; + +@@ -3506,7 +3506,7 @@ static struct gdsc usb3_phy_gdsc = { + .pd = { + .name = "usb3_phy_gdsc", + }, +- .pwrsts = PWRSTS_OFF_ON, ++ .pwrsts = PWRSTS_RET_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, + }; + +-- +2.39.5 + diff --git a/queue-6.14/clk-qcom-gcc-x1e80100-unregister-gcc_gpu_cfg_ahb_clk.patch b/queue-6.14/clk-qcom-gcc-x1e80100-unregister-gcc_gpu_cfg_ahb_clk.patch new file mode 100644 index 0000000000..234fc7d60c --- /dev/null +++ b/queue-6.14/clk-qcom-gcc-x1e80100-unregister-gcc_gpu_cfg_ahb_clk.patch @@ -0,0 +1,99 @@ +From e81f759cc0ed0db8c9e5a8bec1ad2593f1655021 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jan 2025 17:54:18 +0100 +Subject: clk: qcom: gcc-x1e80100: Unregister + GCC_GPU_CFG_AHB_CLK/GCC_DISP_XO_CLK + +From: Konrad Dybcio + +[ Upstream commit b60521eff227ef459e03879cbea2b2bd85a8d7af ] + +The GPU clock is required for CPU access to GPUSS registers. It was +previously decided (on this and many more platforms) that the added +overhead/hassle introduced by keeping track of it would not bring much +measurable improvement in the power department. + +The display clock is basically the same story over again. + +Now, we're past that discussion and this commit is not trying to change +that. Instead, the clocks are both force-enabled in .probe *and* +registered with the common clock framework, resulting in them being +toggled off after ignore_unused. + +Unregister said clocks to fix breakage when clk_ignore_unused is absent +(as it should be). + +Fixes: 161b7c401f4b ("clk: qcom: Add Global Clock controller (GCC) driver for X1E80100") +Signed-off-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20250111-topic-x1e_fixups-v1-1-77dc39237c12@oss.qualcomm.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/gcc-x1e80100.c | 30 ------------------------------ + 1 file changed, 30 deletions(-) + +diff --git a/drivers/clk/qcom/gcc-x1e80100.c b/drivers/clk/qcom/gcc-x1e80100.c +index 7288af845434d..009f39139b644 100644 +--- a/drivers/clk/qcom/gcc-x1e80100.c ++++ b/drivers/clk/qcom/gcc-x1e80100.c +@@ -2564,19 +2564,6 @@ static struct clk_branch gcc_disp_hf_axi_clk = { + }, + }; + +-static struct clk_branch gcc_disp_xo_clk = { +- .halt_reg = 0x27018, +- .halt_check = BRANCH_HALT, +- .clkr = { +- .enable_reg = 0x27018, +- .enable_mask = BIT(0), +- .hw.init = &(const struct clk_init_data) { +- .name = "gcc_disp_xo_clk", +- .ops = &clk_branch2_ops, +- }, +- }, +-}; +- + static struct clk_branch gcc_gp1_clk = { + .halt_reg = 0x64000, + .halt_check = BRANCH_HALT, +@@ -2631,21 +2618,6 @@ static struct clk_branch gcc_gp3_clk = { + }, + }; + +-static struct clk_branch gcc_gpu_cfg_ahb_clk = { +- .halt_reg = 0x71004, +- .halt_check = BRANCH_HALT_VOTED, +- .hwcg_reg = 0x71004, +- .hwcg_bit = 1, +- .clkr = { +- .enable_reg = 0x71004, +- .enable_mask = BIT(0), +- .hw.init = &(const struct clk_init_data) { +- .name = "gcc_gpu_cfg_ahb_clk", +- .ops = &clk_branch2_ops, +- }, +- }, +-}; +- + static struct clk_branch gcc_gpu_gpll0_cph_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { +@@ -6268,7 +6240,6 @@ static struct clk_regmap *gcc_x1e80100_clocks[] = { + [GCC_CNOC_PCIE_TUNNEL_CLK] = &gcc_cnoc_pcie_tunnel_clk.clkr, + [GCC_DDRSS_GPU_AXI_CLK] = &gcc_ddrss_gpu_axi_clk.clkr, + [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr, +- [GCC_DISP_XO_CLK] = &gcc_disp_xo_clk.clkr, + [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, + [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr, + [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, +@@ -6281,7 +6252,6 @@ static struct clk_regmap *gcc_x1e80100_clocks[] = { + [GCC_GPLL7] = &gcc_gpll7.clkr, + [GCC_GPLL8] = &gcc_gpll8.clkr, + [GCC_GPLL9] = &gcc_gpll9.clkr, +- [GCC_GPU_CFG_AHB_CLK] = &gcc_gpu_cfg_ahb_clk.clkr, + [GCC_GPU_GPLL0_CPH_CLK_SRC] = &gcc_gpu_gpll0_cph_clk_src.clkr, + [GCC_GPU_GPLL0_DIV_CPH_CLK_SRC] = &gcc_gpu_gpll0_div_cph_clk_src.clkr, + [GCC_GPU_MEMNOC_GFX_CLK] = &gcc_gpu_memnoc_gfx_clk.clkr, +-- +2.39.5 + diff --git a/queue-6.14/clk-qcom-ipq5424-fix-software-and-hardware-flow-cont.patch b/queue-6.14/clk-qcom-ipq5424-fix-software-and-hardware-flow-cont.patch new file mode 100644 index 0000000000..f42608274f --- /dev/null +++ b/queue-6.14/clk-qcom-ipq5424-fix-software-and-hardware-flow-cont.patch @@ -0,0 +1,67 @@ +From 2804ad2c48e2694d234ac4cc40103cc798e23a6c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 11:39:14 +0530 +Subject: clk: qcom: ipq5424: fix software and hardware flow control error of + UART +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Manikanta Mylavarapu + +[ Upstream commit 4b28beb882a0a1af0ce47a8a87e7877a3ae6ad36 ] + +The UART’s software and hardware flow control are currently not +functioning correctly. + +For software flow control, the following error is encountered: +qcom_geni_serial 1a80000.serial: Couldn't find suitable +clock rate for 56000000, 3500000, 2500000, 1152000, 921600, 19200 + +During hardware flow control testing, a “Retry 0: Got ZCAN error” is +observed. + +To address these issues, update the UART frequency table to include all +supported frequencies according to the frequency plan. + +Fixes: 21b5d5a4a311 ("clk: qcom: add Global Clock controller (GCC) driver for IPQ5424 SoC") +Signed-off-by: Manikanta Mylavarapu +Link: https://lore.kernel.org/r/20250124060914.1564681-1-quic_mmanikan@quicinc.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/gcc-ipq5424.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/drivers/clk/qcom/gcc-ipq5424.c b/drivers/clk/qcom/gcc-ipq5424.c +index 107424395ef17..3d42f3d85c7a9 100644 +--- a/drivers/clk/qcom/gcc-ipq5424.c ++++ b/drivers/clk/qcom/gcc-ipq5424.c +@@ -592,13 +592,19 @@ static struct clk_rcg2 gcc_qupv3_spi1_clk_src = { + }; + + static const struct freq_tbl ftbl_gcc_qupv3_uart0_clk_src[] = { +- F(960000, P_XO, 10, 2, 5), +- F(4800000, P_XO, 5, 0, 0), +- F(9600000, P_XO, 2, 4, 5), +- F(16000000, P_GPLL0_OUT_MAIN, 10, 1, 5), ++ F(3686400, P_GCC_GPLL0_OUT_MAIN_DIV_CLK_SRC, 1, 144, 15625), ++ F(7372800, P_GCC_GPLL0_OUT_MAIN_DIV_CLK_SRC, 1, 288, 15625), ++ F(14745600, P_GCC_GPLL0_OUT_MAIN_DIV_CLK_SRC, 1, 576, 15625), + F(24000000, P_XO, 1, 0, 0), + F(25000000, P_GPLL0_OUT_MAIN, 16, 1, 2), +- F(50000000, P_GPLL0_OUT_MAIN, 16, 0, 0), ++ F(32000000, P_GPLL0_OUT_MAIN, 1, 1, 25), ++ F(40000000, P_GPLL0_OUT_MAIN, 1, 1, 20), ++ F(46400000, P_GPLL0_OUT_MAIN, 1, 29, 500), ++ F(48000000, P_GPLL0_OUT_MAIN, 1, 3, 50), ++ F(51200000, P_GPLL0_OUT_MAIN, 1, 8, 125), ++ F(56000000, P_GPLL0_OUT_MAIN, 1, 7, 100), ++ F(58982400, P_GPLL0_OUT_MAIN, 1, 1152, 15625), ++ F(60000000, P_GPLL0_OUT_MAIN, 1, 3, 40), + F(64000000, P_GPLL0_OUT_MAIN, 12.5, 0, 0), + { } + }; +-- +2.39.5 + diff --git a/queue-6.14/clk-qcom-mmcc-sdm660-fix-stuck-video_subcore0-clock.patch b/queue-6.14/clk-qcom-mmcc-sdm660-fix-stuck-video_subcore0-clock.patch new file mode 100644 index 0000000000..b2da2ff174 --- /dev/null +++ b/queue-6.14/clk-qcom-mmcc-sdm660-fix-stuck-video_subcore0-clock.patch @@ -0,0 +1,42 @@ +From 6c5e74050c2239604012037e66d09446848afd3c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Mar 2025 16:26:17 +0100 +Subject: clk: qcom: mmcc-sdm660: fix stuck video_subcore0 clock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Barnabás Czémán + +[ Upstream commit 000cbe3896c56bf5c625e286ff096533a6b27657 ] + +This clock can't be enable with VENUS_CORE0 GDSC turned off. But that +GDSC is under HW control so it can be turned off at any moment. +Instead of checking the dependent clock we can just vote for it to +enable later when GDSC gets turned on. + +Fixes: 5db3ae8b33de6 ("clk: qcom: Add SDM660 Multimedia Clock Controller (MMCC) driver") +Signed-off-by: Barnabás Czémán +Link: https://lore.kernel.org/r/20250315-clock-fix-v1-1-2efdc4920dda@mainlining.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/mmcc-sdm660.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/qcom/mmcc-sdm660.c b/drivers/clk/qcom/mmcc-sdm660.c +index 98ba5b4518fb3..b9f02d91004e8 100644 +--- a/drivers/clk/qcom/mmcc-sdm660.c ++++ b/drivers/clk/qcom/mmcc-sdm660.c +@@ -2544,7 +2544,7 @@ static struct clk_branch video_core_clk = { + + static struct clk_branch video_subcore0_clk = { + .halt_reg = 0x1048, +- .halt_check = BRANCH_HALT, ++ .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x1048, + .enable_mask = BIT(0), +-- +2.39.5 + diff --git a/queue-6.14/clk-renesas-r8a08g045-check-the-source-of-the-cpu-pl.patch b/queue-6.14/clk-renesas-r8a08g045-check-the-source-of-the-cpu-pl.patch new file mode 100644 index 0000000000..6ca7b1a169 --- /dev/null +++ b/queue-6.14/clk-renesas-r8a08g045-check-the-source-of-the-cpu-pl.patch @@ -0,0 +1,140 @@ +From 444f638464180ca1ce480190ed555837840d9603 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jan 2025 16:20:58 +0200 +Subject: clk: renesas: r8a08g045: Check the source of the CPU PLL settings + +From: Claudiu Beznea + +[ Upstream commit dc0f16c1b76293ac942a783e960abfd19e95fdf5 ] + +On the RZ/G3S SoC, the CPU PLL settings can be set and retrieved through +the CPG_PLL1_CLK1 and CPG_PLL1_CLK2 registers. However, these settings +are applied only when CPG_PLL1_SETTING.SEL_PLL1 is set to 0. +Otherwise, the CPU PLL operates at the default frequency of 1.1 GHz. +Hence add support to the PLL driver for returning the 1.1 GHz frequency +when the CPU PLL is configured with the default frequency. + +Fixes: 01eabef547e6 ("clk: renesas: rzg2l: Add support for RZ/G3S PLL") +Fixes: de60a3ebe410 ("clk: renesas: Add minimal boot support for RZ/G3S SoC") +Signed-off-by: Claudiu Beznea +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/20250115142059.1833063-1-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + drivers/clk/renesas/r9a08g045-cpg.c | 5 +++-- + drivers/clk/renesas/rzg2l-cpg.c | 13 ++++++++++++- + drivers/clk/renesas/rzg2l-cpg.h | 10 +++++++--- + 3 files changed, 22 insertions(+), 6 deletions(-) + +diff --git a/drivers/clk/renesas/r9a08g045-cpg.c b/drivers/clk/renesas/r9a08g045-cpg.c +index 0e7e3bf05b52d..cb63d397429f6 100644 +--- a/drivers/clk/renesas/r9a08g045-cpg.c ++++ b/drivers/clk/renesas/r9a08g045-cpg.c +@@ -51,7 +51,7 @@ + #define G3S_SEL_SDHI2 SEL_PLL_PACK(G3S_CPG_SDHI_DSEL, 8, 2) + + /* PLL 1/4/6 configuration registers macro. */ +-#define G3S_PLL146_CONF(clk1, clk2) ((clk1) << 22 | (clk2) << 12) ++#define G3S_PLL146_CONF(clk1, clk2, setting) ((clk1) << 22 | (clk2) << 12 | (setting)) + + #define DEF_G3S_MUX(_name, _id, _conf, _parent_names, _mux_flags, _clk_flags) \ + DEF_TYPE(_name, _id, CLK_TYPE_MUX, .conf = (_conf), \ +@@ -134,7 +134,8 @@ static const struct cpg_core_clk r9a08g045_core_clks[] __initconst = { + + /* Internal Core Clocks */ + DEF_FIXED(".osc_div1000", CLK_OSC_DIV1000, CLK_EXTAL, 1, 1000), +- DEF_G3S_PLL(".pll1", CLK_PLL1, CLK_EXTAL, G3S_PLL146_CONF(0x4, 0x8)), ++ DEF_G3S_PLL(".pll1", CLK_PLL1, CLK_EXTAL, G3S_PLL146_CONF(0x4, 0x8, 0x100), ++ 1100000000UL), + DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 200, 3), + DEF_FIXED(".pll3", CLK_PLL3, CLK_EXTAL, 200, 3), + DEF_FIXED(".pll4", CLK_PLL4, CLK_EXTAL, 100, 3), +diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c +index ddf722ca79eb0..4bd8862dc82be 100644 +--- a/drivers/clk/renesas/rzg2l-cpg.c ++++ b/drivers/clk/renesas/rzg2l-cpg.c +@@ -51,6 +51,7 @@ + #define RZG3S_DIV_M GENMASK(25, 22) + #define RZG3S_DIV_NI GENMASK(21, 13) + #define RZG3S_DIV_NF GENMASK(12, 1) ++#define RZG3S_SEL_PLL BIT(0) + + #define CLK_ON_R(reg) (reg) + #define CLK_MON_R(reg) (0x180 + (reg)) +@@ -60,6 +61,7 @@ + #define GET_REG_OFFSET(val) ((val >> 20) & 0xfff) + #define GET_REG_SAMPLL_CLK1(val) ((val >> 22) & 0xfff) + #define GET_REG_SAMPLL_CLK2(val) ((val >> 12) & 0xfff) ++#define GET_REG_SAMPLL_SETTING(val) ((val) & 0xfff) + + #define CPG_WEN_BIT BIT(16) + +@@ -943,6 +945,7 @@ rzg2l_cpg_sipll5_register(const struct cpg_core_clk *core, + + struct pll_clk { + struct clk_hw hw; ++ unsigned long default_rate; + unsigned int conf; + unsigned int type; + void __iomem *base; +@@ -980,12 +983,19 @@ static unsigned long rzg3s_cpg_pll_clk_recalc_rate(struct clk_hw *hw, + { + struct pll_clk *pll_clk = to_pll(hw); + struct rzg2l_cpg_priv *priv = pll_clk->priv; +- u32 nir, nfr, mr, pr, val; ++ u32 nir, nfr, mr, pr, val, setting; + u64 rate; + + if (pll_clk->type != CLK_TYPE_G3S_PLL) + return parent_rate; + ++ setting = GET_REG_SAMPLL_SETTING(pll_clk->conf); ++ if (setting) { ++ val = readl(priv->base + setting); ++ if (val & RZG3S_SEL_PLL) ++ return pll_clk->default_rate; ++ } ++ + val = readl(priv->base + GET_REG_SAMPLL_CLK1(pll_clk->conf)); + + pr = 1 << FIELD_GET(RZG3S_DIV_P, val); +@@ -1038,6 +1048,7 @@ rzg2l_cpg_pll_clk_register(const struct cpg_core_clk *core, + pll_clk->base = priv->base; + pll_clk->priv = priv; + pll_clk->type = core->type; ++ pll_clk->default_rate = core->default_rate; + + ret = devm_clk_hw_register(dev, &pll_clk->hw); + if (ret) +diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h +index 881a89b5a7100..b74c94a16986e 100644 +--- a/drivers/clk/renesas/rzg2l-cpg.h ++++ b/drivers/clk/renesas/rzg2l-cpg.h +@@ -102,7 +102,10 @@ struct cpg_core_clk { + const struct clk_div_table *dtable; + const u32 *mtable; + const unsigned long invalid_rate; +- const unsigned long max_rate; ++ union { ++ const unsigned long max_rate; ++ const unsigned long default_rate; ++ }; + const char * const *parent_names; + notifier_fn_t notifier; + u32 flag; +@@ -144,8 +147,9 @@ enum clk_types { + DEF_TYPE(_name, _id, _type, .parent = _parent) + #define DEF_SAMPLL(_name, _id, _parent, _conf) \ + DEF_TYPE(_name, _id, CLK_TYPE_SAM_PLL, .parent = _parent, .conf = _conf) +-#define DEF_G3S_PLL(_name, _id, _parent, _conf) \ +- DEF_TYPE(_name, _id, CLK_TYPE_G3S_PLL, .parent = _parent, .conf = _conf) ++#define DEF_G3S_PLL(_name, _id, _parent, _conf, _default_rate) \ ++ DEF_TYPE(_name, _id, CLK_TYPE_G3S_PLL, .parent = _parent, .conf = _conf, \ ++ .default_rate = _default_rate) + #define DEF_INPUT(_name, _id) \ + DEF_TYPE(_name, _id, CLK_TYPE_IN) + #define DEF_FIXED(_name, _id, _parent, _mult, _div) \ +-- +2.39.5 + diff --git a/queue-6.14/clk-rockchip-rk3328-fix-wrong-clk_ref_usb3otg-parent.patch b/queue-6.14/clk-rockchip-rk3328-fix-wrong-clk_ref_usb3otg-parent.patch new file mode 100644 index 0000000000..a9cffdf23f --- /dev/null +++ b/queue-6.14/clk-rockchip-rk3328-fix-wrong-clk_ref_usb3otg-parent.patch @@ -0,0 +1,39 @@ +From 5b9569cbdb251d1e4daa05edeacc3a987c65c4b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jan 2025 01:26:22 +0000 +Subject: clk: rockchip: rk3328: fix wrong clk_ref_usb3otg parent + +From: Peter Geis + +[ Upstream commit a9e60f1ffe1ca57d6af6a2573e2f950e76efbf5b ] + +Correct the clk_ref_usb3otg parent to fix clock control for the usb3 +controller on rk3328. Verified against the rk3328 trm, the rk3228h trm, +and the rk3328 usb3 phy clock map. + +Fixes: fe3511ad8a1c ("clk: rockchip: add clock controller for rk3328") +Signed-off-by: Peter Geis +Reviewed-by: Dragan Simic +Link: https://lore.kernel.org/r/20250115012628.1035928-2-pgwipeout@gmail.com +Signed-off-by: Heiko Stuebner +Signed-off-by: Sasha Levin +--- + drivers/clk/rockchip/clk-rk3328.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3328.c b/drivers/clk/rockchip/clk-rk3328.c +index 3bb87b27b662d..cf60fcf2fa5cd 100644 +--- a/drivers/clk/rockchip/clk-rk3328.c ++++ b/drivers/clk/rockchip/clk-rk3328.c +@@ -201,7 +201,7 @@ PNAME(mux_aclk_peri_pre_p) = { "cpll_peri", + "gpll_peri", + "hdmiphy_peri" }; + PNAME(mux_ref_usb3otg_src_p) = { "xin24m", +- "clk_usb3otg_ref" }; ++ "clk_ref_usb3otg_src" }; + PNAME(mux_xin24m_32k_p) = { "xin24m", + "clk_rtc32k" }; + PNAME(mux_mac2io_src_p) = { "clk_mac2io_src", +-- +2.39.5 + diff --git a/queue-6.14/clk-samsung-fix-ubsan-panic-in-samsung_clk_init.patch b/queue-6.14/clk-samsung-fix-ubsan-panic-in-samsung_clk_init.patch new file mode 100644 index 0000000000..deaba87fb6 --- /dev/null +++ b/queue-6.14/clk-samsung-fix-ubsan-panic-in-samsung_clk_init.patch @@ -0,0 +1,53 @@ +From d5bae3a314d13f73df7ef524d3057f5e869aa001 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 10:32:52 -0800 +Subject: clk: samsung: Fix UBSAN panic in samsung_clk_init() + +From: Will McVicker + +[ Upstream commit d19d7345a7bcdb083b65568a11b11adffe0687af ] + +With UBSAN_ARRAY_BOUNDS=y, I'm hitting the below panic due to +dereferencing `ctx->clk_data.hws` before setting +`ctx->clk_data.num = nr_clks`. Move that up to fix the crash. + + UBSAN: array index out of bounds: 00000000f2005512 [#1] PREEMPT SMP + + Call trace: + samsung_clk_init+0x110/0x124 (P) + samsung_clk_init+0x48/0x124 (L) + samsung_cmu_register_one+0x3c/0xa0 + exynos_arm64_register_cmu+0x54/0x64 + __gs101_cmu_top_of_clk_init_declare+0x28/0x60 + ... + +Fixes: e620a1e061c4 ("drivers/clk: convert VL struct to struct_size") +Signed-off-by: Will McVicker +Link: https://lore.kernel.org/r/20250212183253.509771-1-willmcvicker@google.com +Signed-off-by: Krzysztof Kozlowski +Signed-off-by: Sasha Levin +--- + drivers/clk/samsung/clk.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c +index 283c523763e6b..8d440cf56bd45 100644 +--- a/drivers/clk/samsung/clk.c ++++ b/drivers/clk/samsung/clk.c +@@ -74,12 +74,12 @@ struct samsung_clk_provider * __init samsung_clk_init(struct device *dev, + if (!ctx) + panic("could not allocate clock provider context.\n"); + ++ ctx->clk_data.num = nr_clks; + for (i = 0; i < nr_clks; ++i) + ctx->clk_data.hws[i] = ERR_PTR(-ENOENT); + + ctx->dev = dev; + ctx->reg_base = base; +- ctx->clk_data.num = nr_clks; + spin_lock_init(&ctx->lock); + + return ctx; +-- +2.39.5 + diff --git a/queue-6.14/clk-stm32f4-fix-an-uninitialized-variable.patch b/queue-6.14/clk-stm32f4-fix-an-uninitialized-variable.patch new file mode 100644 index 0000000000..0b9e7c8dd3 --- /dev/null +++ b/queue-6.14/clk-stm32f4-fix-an-uninitialized-variable.patch @@ -0,0 +1,49 @@ +From d7d1d917372a847eb1ac7177cff8bd97c1c3748d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 12:16:54 +0100 +Subject: clk: stm32f4: fix an uninitialized variable + +From: Dario Binacchi + +[ Upstream commit 9c981c868f5f335e1b51e766b5d36799de163d43 ] + +The variable s, used by pr_debug() to print the mnemonic of the modulation +depth in use, was not initialized. Fix the output by addressing the correct +mnemonic. + +Fixes: 65b3516dbe50 ("clk: stm32f4: support spread spectrum clock generation") +Reported-by: Dan Carpenter +Closes: https://lore.kernel.org/r/77355eb9-19b3-46e5-a003-c21c0fae5bcd@stanley.mountain +Signed-off-by: Dario Binacchi +Link: https://lore.kernel.org/r/20250124111711.1051436-1-dario.binacchi@amarulasolutions.com +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/clk-stm32f4.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c +index f476883bc93ba..85e23961ec341 100644 +--- a/drivers/clk/clk-stm32f4.c ++++ b/drivers/clk/clk-stm32f4.c +@@ -888,7 +888,6 @@ static int __init stm32f4_pll_ssc_parse_dt(struct device_node *np, + struct stm32f4_pll_ssc *conf) + { + int ret; +- const char *s; + + if (!conf) + return -EINVAL; +@@ -916,7 +915,8 @@ static int __init stm32f4_pll_ssc_parse_dt(struct device_node *np, + conf->mod_type = ret; + + pr_debug("%pOF: SSCG settings: mod_freq: %d, mod_depth: %d mod_method: %s [%d]\n", +- np, conf->mod_freq, conf->mod_depth, s, conf->mod_type); ++ np, conf->mod_freq, conf->mod_depth, ++ stm32f4_ssc_mod_methods[ret], conf->mod_type); + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/context_tracking-always-inline-ct_-nmi-irq-_-enter-e.patch b/queue-6.14/context_tracking-always-inline-ct_-nmi-irq-_-enter-e.patch new file mode 100644 index 0000000000..caca17e15b --- /dev/null +++ b/queue-6.14/context_tracking-always-inline-ct_-nmi-irq-_-enter-e.patch @@ -0,0 +1,57 @@ +From 94a833eea33280aa8d5b576a3f40bf1446685656 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Mar 2025 21:26:45 -0700 +Subject: context_tracking: Always inline ct_{nmi,irq}_{enter,exit}() + +From: Josh Poimboeuf + +[ Upstream commit 9ac50f7311dc8b39e355582f14c1e82da47a8196 ] + +Thanks to CONFIG_DEBUG_SECTION_MISMATCH, empty functions can be +generated out of line. These can be called from noinstr code, so make +sure they're always inlined. + +Fixes the following warnings: + + vmlinux.o: warning: objtool: irqentry_nmi_enter+0xa2: call to ct_nmi_enter() leaves .noinstr.text section + vmlinux.o: warning: objtool: irqentry_nmi_exit+0x16: call to ct_nmi_exit() leaves .noinstr.text section + vmlinux.o: warning: objtool: irqentry_exit+0x78: call to ct_irq_exit() leaves .noinstr.text section + +Fixes: 6f0e6c1598b1 ("context_tracking: Take IRQ eqs entrypoints over RCU") +Reported-by: Randy Dunlap +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Cc: Frederic Weisbecker +Cc: Paul E. McKenney +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/8509bce3f536bcd4ae7af3a2cf6930d48c5e631a.1743481539.git.jpoimboe@kernel.org +Closes: https://lore.kernel.org/d1eca076-fdde-484a-b33e-70e0d167c36d@infradead.org +Signed-off-by: Sasha Levin +--- + include/linux/context_tracking_irq.h | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/include/linux/context_tracking_irq.h b/include/linux/context_tracking_irq.h +index c50b5670c4a52..197916ee91a4b 100644 +--- a/include/linux/context_tracking_irq.h ++++ b/include/linux/context_tracking_irq.h +@@ -10,12 +10,12 @@ void ct_irq_exit_irqson(void); + void ct_nmi_enter(void); + void ct_nmi_exit(void); + #else +-static inline void ct_irq_enter(void) { } +-static inline void ct_irq_exit(void) { } ++static __always_inline void ct_irq_enter(void) { } ++static __always_inline void ct_irq_exit(void) { } + static inline void ct_irq_enter_irqson(void) { } + static inline void ct_irq_exit_irqson(void) { } +-static inline void ct_nmi_enter(void) { } +-static inline void ct_nmi_exit(void) { } ++static __always_inline void ct_nmi_enter(void) { } ++static __always_inline void ct_nmi_exit(void) { } + #endif + + #endif +-- +2.39.5 + diff --git a/queue-6.14/coredump-fixes-core_pipe_limit-sysctl-proc_handler.patch b/queue-6.14/coredump-fixes-core_pipe_limit-sysctl-proc_handler.patch new file mode 100644 index 0000000000..2d99baf783 --- /dev/null +++ b/queue-6.14/coredump-fixes-core_pipe_limit-sysctl-proc_handler.patch @@ -0,0 +1,55 @@ +From d2cd7b2f6a644d94a3de5b8ffb2ad1c56d8940a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jan 2025 14:22:08 +0100 +Subject: coredump: Fixes core_pipe_limit sysctl proc_handler + +From: Nicolas Bouchinet + +[ Upstream commit 049439e22825507a90d4dedf3934e24fd0a8ff62 ] + +proc_dointvec converts a string to a vector of signed int, which is +stored in the unsigned int .data core_pipe_limit. +It was thus authorized to write a negative value to core_pipe_limit +sysctl which once stored in core_pipe_limit, leads to the signed int +dump_count check against core_pipe_limit never be true. The same can be +achieved with core_pipe_limit set to INT_MAX. + +Any negative write or >= to INT_MAX in core_pipe_limit sysctl would +hypothetically allow a user to create very high load on the system by +running processes that produces a coredump in case the core_pattern +sysctl is configured to pipe core files to user space helper. +Memory or PID exhaustion should happen before but it anyway breaks the +core_pipe_limit semantic. + +This commit fixes this by changing core_pipe_limit sysctl's proc_handler +to proc_dointvec_minmax and bound checking between SYSCTL_ZERO and +SYSCTL_INT_MAX. + +Fixes: a293980c2e26 ("exec: let do_coredump() limit the number of concurrent dumps to pipes") +Signed-off-by: Nicolas Bouchinet +Reviewed-by: Jan Kara +Reviewed-by: Kees Cook +Signed-off-by: Joel Granados +Signed-off-by: Sasha Levin +--- + fs/coredump.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/fs/coredump.c b/fs/coredump.c +index 4375c70144d0a..4ebec51fe4f22 100644 +--- a/fs/coredump.c ++++ b/fs/coredump.c +@@ -1016,7 +1016,9 @@ static const struct ctl_table coredump_sysctls[] = { + .data = &core_pipe_limit, + .maxlen = sizeof(unsigned int), + .mode = 0644, +- .proc_handler = proc_dointvec, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = SYSCTL_ZERO, ++ .extra2 = SYSCTL_INT_MAX, + }, + { + .procname = "core_file_note_size_limit", +-- +2.39.5 + diff --git a/queue-6.14/coresight-catu-fix-number-of-pages-while-using-64k-p.patch b/queue-6.14/coresight-catu-fix-number-of-pages-while-using-64k-p.patch new file mode 100644 index 0000000000..24bae1d3e3 --- /dev/null +++ b/queue-6.14/coresight-catu-fix-number-of-pages-while-using-64k-p.patch @@ -0,0 +1,41 @@ +From 38f10f26540eea8b970d65ed036ab0daff56908d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jan 2025 21:53:48 +0000 +Subject: coresight: catu: Fix number of pages while using 64k pages + +From: Ilkka Koskinen + +[ Upstream commit 0e14e062f5ff98aa15264dfa87c5f5e924028561 ] + +Trying to record a trace on kernel with 64k pages resulted in -ENOMEM. +This happens due to a bug in calculating the number of table pages, which +returns zero. Fix the issue by rounding up. + +$ perf record --kcore -e cs_etm/@tmc_etr55,cycacc,branch_broadcast/k --per-thread taskset --cpu-list 1 dd if=/dev/zero of=/dev/null +failed to mmap with 12 (Cannot allocate memory) + +Fixes: 8ed536b1e283 ("coresight: catu: Add support for scatter gather tables") +Signed-off-by: Ilkka Koskinen +Signed-off-by: Suzuki K Poulose +Link: https://lore.kernel.org/r/20250109215348.5483-1-ilkka@os.amperecomputing.com +Signed-off-by: Sasha Levin +--- + drivers/hwtracing/coresight/coresight-catu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c +index 275cc0d9f505f..3378bb77e6b41 100644 +--- a/drivers/hwtracing/coresight/coresight-catu.c ++++ b/drivers/hwtracing/coresight/coresight-catu.c +@@ -269,7 +269,7 @@ catu_init_sg_table(struct device *catu_dev, int node, + * Each table can address upto 1MB and we can have + * CATU_PAGES_PER_SYSPAGE tables in a system page. + */ +- nr_tpages = DIV_ROUND_UP(size, SZ_1M) / CATU_PAGES_PER_SYSPAGE; ++ nr_tpages = DIV_ROUND_UP(size, CATU_PAGES_PER_SYSPAGE * SZ_1M); + catu_table = tmc_alloc_sg_table(catu_dev, node, nr_tpages, + size >> PAGE_SHIFT, pages); + if (IS_ERR(catu_table)) +-- +2.39.5 + diff --git a/queue-6.14/coresight-etm4x-add-isb-before-reading-the-trcstatr.patch b/queue-6.14/coresight-etm4x-add-isb-before-reading-the-trcstatr.patch new file mode 100644 index 0000000000..3f938c9fa0 --- /dev/null +++ b/queue-6.14/coresight-etm4x-add-isb-before-reading-the-trcstatr.patch @@ -0,0 +1,196 @@ +From 708469dac7719f8c1fd32af1602b87e6b58e2996 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jan 2025 17:04:20 +0800 +Subject: coresight-etm4x: add isb() before reading the TRCSTATR + +From: Yuanfang Zhang + +[ Upstream commit 4ff6039ffb79a4a8a44b63810a8a2f2b43264856 ] + +As recommended by section 4.3.7 ("Synchronization when using system +instructions to progrom the trace unit") of ARM IHI 0064H.b, the +self-hosted trace analyzer must perform a Context synchronization +event between writing to the TRCPRGCTLR and reading the TRCSTATR. +Additionally, add an ISB between the each read of TRCSTATR on +coresight_timeout() when using system instructions to program the +trace unit. + +Fixes: 1ab3bb9df5e3 ("coresight: etm4x: Add necessary synchronization for sysreg access") +Signed-off-by: Yuanfang Zhang +Signed-off-by: Suzuki K Poulose +Link: https://lore.kernel.org/r/20250116-etm_sync-v4-1-39f2b05e9514@quicinc.com +Signed-off-by: Sasha Levin +--- + drivers/hwtracing/coresight/coresight-core.c | 20 ++++++-- + .../coresight/coresight-etm4x-core.c | 48 +++++++++++++++++-- + include/linux/coresight.h | 4 ++ + 3 files changed, 62 insertions(+), 10 deletions(-) + +diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c +index 0a9380350fb52..4936dc2f7a56b 100644 +--- a/drivers/hwtracing/coresight/coresight-core.c ++++ b/drivers/hwtracing/coresight/coresight-core.c +@@ -1092,18 +1092,20 @@ static void coresight_remove_conns(struct coresight_device *csdev) + } + + /** +- * coresight_timeout - loop until a bit has changed to a specific register +- * state. ++ * coresight_timeout_action - loop until a bit has changed to a specific register ++ * state, with a callback after every trial. + * @csa: coresight device access for the device + * @offset: Offset of the register from the base of the device. + * @position: the position of the bit of interest. + * @value: the value the bit should have. ++ * @cb: Call back after each trial. + * + * Return: 0 as soon as the bit has taken the desired state or -EAGAIN if + * TIMEOUT_US has elapsed, which ever happens first. + */ +-int coresight_timeout(struct csdev_access *csa, u32 offset, +- int position, int value) ++int coresight_timeout_action(struct csdev_access *csa, u32 offset, ++ int position, int value, ++ coresight_timeout_cb_t cb) + { + int i; + u32 val; +@@ -1119,7 +1121,8 @@ int coresight_timeout(struct csdev_access *csa, u32 offset, + if (!(val & BIT(position))) + return 0; + } +- ++ if (cb) ++ cb(csa, offset, position, value); + /* + * Delay is arbitrary - the specification doesn't say how long + * we are expected to wait. Extra check required to make sure +@@ -1131,6 +1134,13 @@ int coresight_timeout(struct csdev_access *csa, u32 offset, + + return -EAGAIN; + } ++EXPORT_SYMBOL_GPL(coresight_timeout_action); ++ ++int coresight_timeout(struct csdev_access *csa, u32 offset, ++ int position, int value) ++{ ++ return coresight_timeout_action(csa, offset, position, value, NULL); ++} + EXPORT_SYMBOL_GPL(coresight_timeout); + + u32 coresight_relaxed_read32(struct coresight_device *csdev, u32 offset) +diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c +index 2c1a60577728e..5bda265d02340 100644 +--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c ++++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c +@@ -428,6 +428,29 @@ static void etm4_check_arch_features(struct etmv4_drvdata *drvdata, + } + #endif /* CONFIG_ETM4X_IMPDEF_FEATURE */ + ++static void etm4x_sys_ins_barrier(struct csdev_access *csa, u32 offset, int pos, int val) ++{ ++ if (!csa->io_mem) ++ isb(); ++} ++ ++/* ++ * etm4x_wait_status: Poll for TRCSTATR. == . While using system ++ * instruction to access the trace unit, each access must be separated by a ++ * synchronization barrier. See ARM IHI0064H.b section "4.3.7 Synchronization of ++ * register updates", for system instructions section, in "Notes": ++ * ++ * "In particular, whenever disabling or enabling the trace unit, a poll of ++ * TRCSTATR needs explicit synchronization between each read of TRCSTATR" ++ */ ++static int etm4x_wait_status(struct csdev_access *csa, int pos, int val) ++{ ++ if (!csa->io_mem) ++ return coresight_timeout_action(csa, TRCSTATR, pos, val, ++ etm4x_sys_ins_barrier); ++ return coresight_timeout(csa, TRCSTATR, pos, val); ++} ++ + static int etm4_enable_hw(struct etmv4_drvdata *drvdata) + { + int i, rc; +@@ -459,7 +482,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) + isb(); + + /* wait for TRCSTATR.IDLE to go up */ +- if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) ++ if (etm4x_wait_status(csa, TRCSTATR_IDLE_BIT, 1)) + dev_err(etm_dev, + "timeout while waiting for Idle Trace Status\n"); + if (drvdata->nr_pe) +@@ -552,7 +575,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) + isb(); + + /* wait for TRCSTATR.IDLE to go back down to '0' */ +- if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0)) ++ if (etm4x_wait_status(csa, TRCSTATR_IDLE_BIT, 0)) + dev_err(etm_dev, + "timeout while waiting for Idle Trace Status\n"); + +@@ -941,10 +964,25 @@ static void etm4_disable_hw(void *info) + tsb_csync(); + etm4x_relaxed_write32(csa, control, TRCPRGCTLR); + ++ /* ++ * As recommended by section 4.3.7 ("Synchronization when using system ++ * instructions to progrom the trace unit") of ARM IHI 0064H.b, the ++ * self-hosted trace analyzer must perform a Context synchronization ++ * event between writing to the TRCPRGCTLR and reading the TRCSTATR. ++ */ ++ if (!csa->io_mem) ++ isb(); ++ + /* wait for TRCSTATR.PMSTABLE to go to '1' */ +- if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1)) ++ if (etm4x_wait_status(csa, TRCSTATR_PMSTABLE_BIT, 1)) + dev_err(etm_dev, + "timeout while waiting for PM stable Trace Status\n"); ++ /* ++ * As recommended by section 4.3.7 (Synchronization of register updates) ++ * of ARM IHI 0064H.b. ++ */ ++ isb(); ++ + /* read the status of the single shot comparators */ + for (i = 0; i < drvdata->nr_ss_cmp; i++) { + config->ss_status[i] = +@@ -1746,7 +1784,7 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata) + etm4_os_lock(drvdata); + + /* wait for TRCSTATR.PMSTABLE to go up */ +- if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1)) { ++ if (etm4x_wait_status(csa, TRCSTATR_PMSTABLE_BIT, 1)) { + dev_err(etm_dev, + "timeout while waiting for PM Stable Status\n"); + etm4_os_unlock(drvdata); +@@ -1837,7 +1875,7 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata) + state->trcpdcr = etm4x_read32(csa, TRCPDCR); + + /* wait for TRCSTATR.IDLE to go up */ +- if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) { ++ if (etm4x_wait_status(csa, TRCSTATR_PMSTABLE_BIT, 1)) { + dev_err(etm_dev, + "timeout while waiting for Idle Trace Status\n"); + etm4_os_unlock(drvdata); +diff --git a/include/linux/coresight.h b/include/linux/coresight.h +index 17276965ff1d0..6ddcbb8be5165 100644 +--- a/include/linux/coresight.h ++++ b/include/linux/coresight.h +@@ -649,6 +649,10 @@ extern int coresight_enable_sysfs(struct coresight_device *csdev); + extern void coresight_disable_sysfs(struct coresight_device *csdev); + extern int coresight_timeout(struct csdev_access *csa, u32 offset, + int position, int value); ++typedef void (*coresight_timeout_cb_t) (struct csdev_access *, u32, int, int); ++extern int coresight_timeout_action(struct csdev_access *csa, u32 offset, ++ int position, int value, ++ coresight_timeout_cb_t cb); + + extern int coresight_claim_device(struct coresight_device *csdev); + extern int coresight_claim_device_unlocked(struct coresight_device *csdev); +-- +2.39.5 + diff --git a/queue-6.14/cpufreq-amd-pstate-add-missing-null-ptr-check-in-amd.patch b/queue-6.14/cpufreq-amd-pstate-add-missing-null-ptr-check-in-amd.patch new file mode 100644 index 0000000000..38f41ecbc4 --- /dev/null +++ b/queue-6.14/cpufreq-amd-pstate-add-missing-null-ptr-check-in-amd.patch @@ -0,0 +1,39 @@ +From cd1aa8322e1b534597f09693fe835a859069bca2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 11:25:21 +0000 +Subject: cpufreq/amd-pstate: Add missing NULL ptr check in amd_pstate_update + +From: Dhananjay Ugwekar + +[ Upstream commit 426db24d4db2e4f0d6720aeb7795eafcb9e82640 ] + +Check if policy is NULL before dereferencing it in amd_pstate_update. + +Fixes: e8f555daacd3 ("cpufreq/amd-pstate: fix setting policy current frequency value") +Signed-off-by: Dhananjay Ugwekar +Reviewed-by: Mario Limonciello +Reviewed-by: Gautham R. Shenoy +Link: https://lore.kernel.org/r/20250205112523.201101-11-dhananjay.ugwekar@amd.com +Signed-off-by: Mario Limonciello +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/amd-pstate.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c +index 32f1b659904bc..bd63837eabb4e 100644 +--- a/drivers/cpufreq/amd-pstate.c ++++ b/drivers/cpufreq/amd-pstate.c +@@ -538,6 +538,9 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u8 min_perf, + struct cpufreq_policy *policy = cpufreq_cpu_get(cpudata->cpu); + u8 nominal_perf = READ_ONCE(cpudata->nominal_perf); + ++ if (!policy) ++ return; ++ + des_perf = clamp_t(u8, des_perf, min_perf, max_perf); + + max_freq = READ_ONCE(cpudata->max_limit_freq); +-- +2.39.5 + diff --git a/queue-6.14/cpufreq-amd-pstate-convert-all-perf-values-to-u8.patch b/queue-6.14/cpufreq-amd-pstate-convert-all-perf-values-to-u8.patch new file mode 100644 index 0000000000..8186ae38af --- /dev/null +++ b/queue-6.14/cpufreq-amd-pstate-convert-all-perf-values-to-u8.patch @@ -0,0 +1,373 @@ +From f13465948afc310862d717712b5f549025a0bcf1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 11:25:17 +0000 +Subject: cpufreq/amd-pstate: Convert all perf values to u8 + +From: Dhananjay Ugwekar + +[ Upstream commit 555bbe67a622b297405e246d1868dbda3284bde8 ] + +All perf values are always within 0-255 range, hence convert their +datatype to u8 everywhere. + +Signed-off-by: Dhananjay Ugwekar +Reviewed-by: Mario Limonciello +Reviewed-by: Gautham R. Shenoy +Link: https://lore.kernel.org/r/20250205112523.201101-7-dhananjay.ugwekar@amd.com +Signed-off-by: Mario Limonciello +Stable-dep-of: 426db24d4db2 ("cpufreq/amd-pstate: Add missing NULL ptr check in amd_pstate_update") +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/amd-pstate-trace.h | 46 +++++++++++------------ + drivers/cpufreq/amd-pstate.c | 60 +++++++++++++++--------------- + drivers/cpufreq/amd-pstate.h | 18 ++++----- + 3 files changed, 62 insertions(+), 62 deletions(-) + +diff --git a/drivers/cpufreq/amd-pstate-trace.h b/drivers/cpufreq/amd-pstate-trace.h +index 8d692415d9050..f457d4af2c62e 100644 +--- a/drivers/cpufreq/amd-pstate-trace.h ++++ b/drivers/cpufreq/amd-pstate-trace.h +@@ -24,9 +24,9 @@ + + TRACE_EVENT(amd_pstate_perf, + +- TP_PROTO(unsigned long min_perf, +- unsigned long target_perf, +- unsigned long capacity, ++ TP_PROTO(u8 min_perf, ++ u8 target_perf, ++ u8 capacity, + u64 freq, + u64 mperf, + u64 aperf, +@@ -47,9 +47,9 @@ TRACE_EVENT(amd_pstate_perf, + ), + + TP_STRUCT__entry( +- __field(unsigned long, min_perf) +- __field(unsigned long, target_perf) +- __field(unsigned long, capacity) ++ __field(u8, min_perf) ++ __field(u8, target_perf) ++ __field(u8, capacity) + __field(unsigned long long, freq) + __field(unsigned long long, mperf) + __field(unsigned long long, aperf) +@@ -70,10 +70,10 @@ TRACE_EVENT(amd_pstate_perf, + __entry->fast_switch = fast_switch; + ), + +- TP_printk("amd_min_perf=%lu amd_des_perf=%lu amd_max_perf=%lu freq=%llu mperf=%llu aperf=%llu tsc=%llu cpu_id=%u fast_switch=%s", +- (unsigned long)__entry->min_perf, +- (unsigned long)__entry->target_perf, +- (unsigned long)__entry->capacity, ++ TP_printk("amd_min_perf=%hhu amd_des_perf=%hhu amd_max_perf=%hhu freq=%llu mperf=%llu aperf=%llu tsc=%llu cpu_id=%u fast_switch=%s", ++ (u8)__entry->min_perf, ++ (u8)__entry->target_perf, ++ (u8)__entry->capacity, + (unsigned long long)__entry->freq, + (unsigned long long)__entry->mperf, + (unsigned long long)__entry->aperf, +@@ -86,10 +86,10 @@ TRACE_EVENT(amd_pstate_perf, + TRACE_EVENT(amd_pstate_epp_perf, + + TP_PROTO(unsigned int cpu_id, +- unsigned int highest_perf, +- unsigned int epp, +- unsigned int min_perf, +- unsigned int max_perf, ++ u8 highest_perf, ++ u8 epp, ++ u8 min_perf, ++ u8 max_perf, + bool boost + ), + +@@ -102,10 +102,10 @@ TRACE_EVENT(amd_pstate_epp_perf, + + TP_STRUCT__entry( + __field(unsigned int, cpu_id) +- __field(unsigned int, highest_perf) +- __field(unsigned int, epp) +- __field(unsigned int, min_perf) +- __field(unsigned int, max_perf) ++ __field(u8, highest_perf) ++ __field(u8, epp) ++ __field(u8, min_perf) ++ __field(u8, max_perf) + __field(bool, boost) + ), + +@@ -118,12 +118,12 @@ TRACE_EVENT(amd_pstate_epp_perf, + __entry->boost = boost; + ), + +- TP_printk("cpu%u: [%u<->%u]/%u, epp=%u, boost=%u", ++ TP_printk("cpu%u: [%hhu<->%hhu]/%hhu, epp=%hhu, boost=%u", + (unsigned int)__entry->cpu_id, +- (unsigned int)__entry->min_perf, +- (unsigned int)__entry->max_perf, +- (unsigned int)__entry->highest_perf, +- (unsigned int)__entry->epp, ++ (u8)__entry->min_perf, ++ (u8)__entry->max_perf, ++ (u8)__entry->highest_perf, ++ (u8)__entry->epp, + (bool)__entry->boost + ) + ); +diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c +index 3ef10aae0502f..32f1b659904bc 100644 +--- a/drivers/cpufreq/amd-pstate.c ++++ b/drivers/cpufreq/amd-pstate.c +@@ -186,7 +186,7 @@ static inline int get_mode_idx_from_str(const char *str, size_t size) + static DEFINE_MUTEX(amd_pstate_limits_lock); + static DEFINE_MUTEX(amd_pstate_driver_lock); + +-static s16 msr_get_epp(struct amd_cpudata *cpudata) ++static u8 msr_get_epp(struct amd_cpudata *cpudata) + { + u64 value; + int ret; +@@ -207,7 +207,7 @@ static inline s16 amd_pstate_get_epp(struct amd_cpudata *cpudata) + return static_call(amd_pstate_get_epp)(cpudata); + } + +-static s16 shmem_get_epp(struct amd_cpudata *cpudata) ++static u8 shmem_get_epp(struct amd_cpudata *cpudata) + { + u64 epp; + int ret; +@@ -218,11 +218,11 @@ static s16 shmem_get_epp(struct amd_cpudata *cpudata) + return ret; + } + +- return (s16)(epp & 0xff); ++ return FIELD_GET(AMD_CPPC_EPP_PERF_MASK, epp); + } + +-static int msr_update_perf(struct amd_cpudata *cpudata, u32 min_perf, +- u32 des_perf, u32 max_perf, u32 epp, bool fast_switch) ++static int msr_update_perf(struct amd_cpudata *cpudata, u8 min_perf, ++ u8 des_perf, u8 max_perf, u8 epp, bool fast_switch) + { + u64 value, prev; + +@@ -257,15 +257,15 @@ static int msr_update_perf(struct amd_cpudata *cpudata, u32 min_perf, + DEFINE_STATIC_CALL(amd_pstate_update_perf, msr_update_perf); + + static inline int amd_pstate_update_perf(struct amd_cpudata *cpudata, +- u32 min_perf, u32 des_perf, +- u32 max_perf, u32 epp, ++ u8 min_perf, u8 des_perf, ++ u8 max_perf, u8 epp, + bool fast_switch) + { + return static_call(amd_pstate_update_perf)(cpudata, min_perf, des_perf, + max_perf, epp, fast_switch); + } + +-static int msr_set_epp(struct amd_cpudata *cpudata, u32 epp) ++static int msr_set_epp(struct amd_cpudata *cpudata, u8 epp) + { + u64 value, prev; + int ret; +@@ -292,12 +292,12 @@ static int msr_set_epp(struct amd_cpudata *cpudata, u32 epp) + + DEFINE_STATIC_CALL(amd_pstate_set_epp, msr_set_epp); + +-static inline int amd_pstate_set_epp(struct amd_cpudata *cpudata, u32 epp) ++static inline int amd_pstate_set_epp(struct amd_cpudata *cpudata, u8 epp) + { + return static_call(amd_pstate_set_epp)(cpudata, epp); + } + +-static int shmem_set_epp(struct amd_cpudata *cpudata, u32 epp) ++static int shmem_set_epp(struct amd_cpudata *cpudata, u8 epp) + { + int ret; + struct cppc_perf_ctrls perf_ctrls; +@@ -320,7 +320,7 @@ static int amd_pstate_set_energy_pref_index(struct cpufreq_policy *policy, + int pref_index) + { + struct amd_cpudata *cpudata = policy->driver_data; +- int epp; ++ u8 epp; + + if (!pref_index) + epp = cpudata->epp_default; +@@ -479,8 +479,8 @@ static inline int amd_pstate_init_perf(struct amd_cpudata *cpudata) + return static_call(amd_pstate_init_perf)(cpudata); + } + +-static int shmem_update_perf(struct amd_cpudata *cpudata, u32 min_perf, +- u32 des_perf, u32 max_perf, u32 epp, bool fast_switch) ++static int shmem_update_perf(struct amd_cpudata *cpudata, u8 min_perf, ++ u8 des_perf, u8 max_perf, u8 epp, bool fast_switch) + { + struct cppc_perf_ctrls perf_ctrls; + +@@ -531,14 +531,14 @@ static inline bool amd_pstate_sample(struct amd_cpudata *cpudata) + return true; + } + +-static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf, +- u32 des_perf, u32 max_perf, bool fast_switch, int gov_flags) ++static void amd_pstate_update(struct amd_cpudata *cpudata, u8 min_perf, ++ u8 des_perf, u8 max_perf, bool fast_switch, int gov_flags) + { + unsigned long max_freq; + struct cpufreq_policy *policy = cpufreq_cpu_get(cpudata->cpu); +- u32 nominal_perf = READ_ONCE(cpudata->nominal_perf); ++ u8 nominal_perf = READ_ONCE(cpudata->nominal_perf); + +- des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf); ++ des_perf = clamp_t(u8, des_perf, min_perf, max_perf); + + max_freq = READ_ONCE(cpudata->max_limit_freq); + policy->cur = div_u64(des_perf * max_freq, max_perf); +@@ -550,7 +550,7 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf, + + /* limit the max perf when core performance boost feature is disabled */ + if (!cpudata->boost_supported) +- max_perf = min_t(unsigned long, nominal_perf, max_perf); ++ max_perf = min_t(u8, nominal_perf, max_perf); + + if (trace_amd_pstate_perf_enabled() && amd_pstate_sample(cpudata)) { + trace_amd_pstate_perf(min_perf, des_perf, max_perf, cpudata->freq, +@@ -591,7 +591,8 @@ static int amd_pstate_verify(struct cpufreq_policy_data *policy_data) + + static int amd_pstate_update_min_max_limit(struct cpufreq_policy *policy) + { +- u32 max_limit_perf, min_limit_perf, max_perf, max_freq; ++ u8 max_limit_perf, min_limit_perf, max_perf; ++ u32 max_freq; + struct amd_cpudata *cpudata = policy->driver_data; + + max_perf = READ_ONCE(cpudata->highest_perf); +@@ -615,7 +616,7 @@ static int amd_pstate_update_freq(struct cpufreq_policy *policy, + { + struct cpufreq_freqs freqs; + struct amd_cpudata *cpudata = policy->driver_data; +- unsigned long des_perf, cap_perf; ++ u8 des_perf, cap_perf; + + if (!cpudata->max_freq) + return -ENODEV; +@@ -670,8 +671,7 @@ static void amd_pstate_adjust_perf(unsigned int cpu, + unsigned long target_perf, + unsigned long capacity) + { +- unsigned long max_perf, min_perf, des_perf, +- cap_perf, min_limit_perf; ++ u8 max_perf, min_perf, des_perf, cap_perf, min_limit_perf; + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); + struct amd_cpudata *cpudata; + +@@ -907,8 +907,8 @@ static int amd_pstate_init_freq(struct amd_cpudata *cpudata) + { + int ret; + u32 min_freq, max_freq; +- u32 highest_perf, nominal_perf, nominal_freq; +- u32 lowest_nonlinear_perf, lowest_nonlinear_freq; ++ u8 highest_perf, nominal_perf, lowest_nonlinear_perf; ++ u32 nominal_freq, lowest_nonlinear_freq; + struct cppc_perf_caps cppc_perf; + + ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf); +@@ -1115,7 +1115,7 @@ static ssize_t show_amd_pstate_lowest_nonlinear_freq(struct cpufreq_policy *poli + static ssize_t show_amd_pstate_highest_perf(struct cpufreq_policy *policy, + char *buf) + { +- u32 perf; ++ u8 perf; + struct amd_cpudata *cpudata = policy->driver_data; + + perf = READ_ONCE(cpudata->highest_perf); +@@ -1126,7 +1126,7 @@ static ssize_t show_amd_pstate_highest_perf(struct cpufreq_policy *policy, + static ssize_t show_amd_pstate_prefcore_ranking(struct cpufreq_policy *policy, + char *buf) + { +- u32 perf; ++ u8 perf; + struct amd_cpudata *cpudata = policy->driver_data; + + perf = READ_ONCE(cpudata->prefcore_ranking); +@@ -1189,7 +1189,7 @@ static ssize_t show_energy_performance_preference( + struct cpufreq_policy *policy, char *buf) + { + struct amd_cpudata *cpudata = policy->driver_data; +- int preference; ++ u8 preference; + + switch (cpudata->epp_cached) { + case AMD_CPPC_EPP_PERFORMANCE: +@@ -1551,7 +1551,7 @@ static void amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy) + static int amd_pstate_epp_update_limit(struct cpufreq_policy *policy) + { + struct amd_cpudata *cpudata = policy->driver_data; +- u32 epp; ++ u8 epp; + + amd_pstate_update_min_max_limit(policy); + +@@ -1600,7 +1600,7 @@ static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy) + static int amd_pstate_epp_reenable(struct cpufreq_policy *policy) + { + struct amd_cpudata *cpudata = policy->driver_data; +- u64 max_perf; ++ u8 max_perf; + int ret; + + ret = amd_pstate_cppc_enable(true); +@@ -1637,7 +1637,7 @@ static int amd_pstate_epp_cpu_online(struct cpufreq_policy *policy) + static int amd_pstate_epp_cpu_offline(struct cpufreq_policy *policy) + { + struct amd_cpudata *cpudata = policy->driver_data; +- int min_perf; ++ u8 min_perf; + + if (cpudata->suspended) + return 0; +diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h +index 9747e3be6ceee..19d405c6d805e 100644 +--- a/drivers/cpufreq/amd-pstate.h ++++ b/drivers/cpufreq/amd-pstate.h +@@ -70,13 +70,13 @@ struct amd_cpudata { + struct freq_qos_request req[2]; + u64 cppc_req_cached; + +- u32 highest_perf; +- u32 nominal_perf; +- u32 lowest_nonlinear_perf; +- u32 lowest_perf; +- u32 prefcore_ranking; +- u32 min_limit_perf; +- u32 max_limit_perf; ++ u8 highest_perf; ++ u8 nominal_perf; ++ u8 lowest_nonlinear_perf; ++ u8 lowest_perf; ++ u8 prefcore_ranking; ++ u8 min_limit_perf; ++ u8 max_limit_perf; + u32 min_limit_freq; + u32 max_limit_freq; + +@@ -93,11 +93,11 @@ struct amd_cpudata { + bool hw_prefcore; + + /* EPP feature related attributes*/ +- s16 epp_cached; ++ u8 epp_cached; + u32 policy; + u64 cppc_cap1_cached; + bool suspended; +- s16 epp_default; ++ u8 epp_default; + }; + + /* +-- +2.39.5 + diff --git a/queue-6.14/cpufreq-amd-pstate-modify-the-min_perf-calculation-i.patch b/queue-6.14/cpufreq-amd-pstate-modify-the-min_perf-calculation-i.patch new file mode 100644 index 0000000000..6e38836c28 --- /dev/null +++ b/queue-6.14/cpufreq-amd-pstate-modify-the-min_perf-calculation-i.patch @@ -0,0 +1,73 @@ +From 5486c84961edce173a4ae864b8ae52a120f1a5b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 11:25:14 +0000 +Subject: cpufreq/amd-pstate: Modify the min_perf calculation in adjust_perf + callback + +From: Dhananjay Ugwekar + +[ Upstream commit 6ceb877d5cecd5417d63239bf833a1cd5f8f271c ] + +Instead of setting a fixed floor at lowest_nonlinear_perf, use the +min_limit_perf value, so that it gives the user the freedom to lower the +floor further. + +There are two minimum frequency/perf limits that we need to consider in +the adjust_perf callback. One provided by schedutil i.e. the sg_cpu->bw_min +value passed in _min_perf arg, another is the effective value of +min_freq_qos request that is updated in cpudata->min_limit_perf. Modify the +code to use the bigger of these two values. + +Signed-off-by: Dhananjay Ugwekar +Reviewed-by: Mario Limonciello +Reviewed-by: Gautham R. Shenoy +Link: https://lore.kernel.org/r/20250205112523.201101-4-dhananjay.ugwekar@amd.com +Signed-off-by: Mario Limonciello +Stable-dep-of: 426db24d4db2 ("cpufreq/amd-pstate: Add missing NULL ptr check in amd_pstate_update") +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/amd-pstate.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c +index 313550fa62d41..17595a2454e1c 100644 +--- a/drivers/cpufreq/amd-pstate.c ++++ b/drivers/cpufreq/amd-pstate.c +@@ -672,7 +672,7 @@ static void amd_pstate_adjust_perf(unsigned int cpu, + unsigned long capacity) + { + unsigned long max_perf, min_perf, des_perf, +- cap_perf, lowest_nonlinear_perf; ++ cap_perf, min_limit_perf; + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); + struct amd_cpudata *cpudata; + +@@ -684,20 +684,20 @@ static void amd_pstate_adjust_perf(unsigned int cpu, + if (policy->min != cpudata->min_limit_freq || policy->max != cpudata->max_limit_freq) + amd_pstate_update_min_max_limit(policy); + +- + cap_perf = READ_ONCE(cpudata->highest_perf); +- lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf); ++ min_limit_perf = READ_ONCE(cpudata->min_limit_perf); + + des_perf = cap_perf; + if (target_perf < capacity) + des_perf = DIV_ROUND_UP(cap_perf * target_perf, capacity); + +- min_perf = READ_ONCE(cpudata->lowest_perf); + if (_min_perf < capacity) + min_perf = DIV_ROUND_UP(cap_perf * _min_perf, capacity); ++ else ++ min_perf = cap_perf; + +- if (min_perf < lowest_nonlinear_perf) +- min_perf = lowest_nonlinear_perf; ++ if (min_perf < min_limit_perf) ++ min_perf = min_limit_perf; + + max_perf = cpudata->max_limit_perf; + if (max_perf < min_perf) +-- +2.39.5 + diff --git a/queue-6.14/cpufreq-amd-pstate-pass-min-max_limit_perf-as-min-ma.patch b/queue-6.14/cpufreq-amd-pstate-pass-min-max_limit_perf-as-min-ma.patch new file mode 100644 index 0000000000..1467e06713 --- /dev/null +++ b/queue-6.14/cpufreq-amd-pstate-pass-min-max_limit_perf-as-min-ma.patch @@ -0,0 +1,65 @@ +From b1824fed88e5d54fcd0c153cc31cdef75a26a2af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 11:25:16 +0000 +Subject: cpufreq/amd-pstate: Pass min/max_limit_perf as min/max_perf to + amd_pstate_update + +From: Dhananjay Ugwekar + +[ Upstream commit e9869c836b2a460c48e2d69ae79d786303dbffda ] + +Currently, amd_pstate_update_freq passes the hardware perf limits as +min/max_perf to amd_pstate_update, which eventually gets programmed into +the min/max_perf fields of the CPPC_REQ register. + +Instead pass the effective perf limits i.e. min/max_limit_perf values to +amd_pstate_update as min/max_perf. + +Signed-off-by: Dhananjay Ugwekar +Reviewed-by: Mario Limonciello +Reviewed-by: Gautham R. Shenoy +Link: https://lore.kernel.org/r/20250205112523.201101-6-dhananjay.ugwekar@amd.com +Signed-off-by: Mario Limonciello +Stable-dep-of: 426db24d4db2 ("cpufreq/amd-pstate: Add missing NULL ptr check in amd_pstate_update") +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/amd-pstate.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c +index 17595a2454e1c..3ef10aae0502f 100644 +--- a/drivers/cpufreq/amd-pstate.c ++++ b/drivers/cpufreq/amd-pstate.c +@@ -615,7 +615,7 @@ static int amd_pstate_update_freq(struct cpufreq_policy *policy, + { + struct cpufreq_freqs freqs; + struct amd_cpudata *cpudata = policy->driver_data; +- unsigned long max_perf, min_perf, des_perf, cap_perf; ++ unsigned long des_perf, cap_perf; + + if (!cpudata->max_freq) + return -ENODEV; +@@ -624,8 +624,6 @@ static int amd_pstate_update_freq(struct cpufreq_policy *policy, + amd_pstate_update_min_max_limit(policy); + + cap_perf = READ_ONCE(cpudata->highest_perf); +- min_perf = READ_ONCE(cpudata->lowest_perf); +- max_perf = cap_perf; + + freqs.old = policy->cur; + freqs.new = target_freq; +@@ -642,8 +640,9 @@ static int amd_pstate_update_freq(struct cpufreq_policy *policy, + if (!fast_switch) + cpufreq_freq_transition_begin(policy, &freqs); + +- amd_pstate_update(cpudata, min_perf, des_perf, +- max_perf, fast_switch, policy->governor->flags); ++ amd_pstate_update(cpudata, cpudata->min_limit_perf, des_perf, ++ cpudata->max_limit_perf, fast_switch, ++ policy->governor->flags); + + if (!fast_switch) + cpufreq_freq_transition_end(policy, &freqs, false); +-- +2.39.5 + diff --git a/queue-6.14/cpufreq-governor-fix-negative-idle_time-handling-in-.patch b/queue-6.14/cpufreq-governor-fix-negative-idle_time-handling-in-.patch new file mode 100644 index 0000000000..b10ce2d622 --- /dev/null +++ b/queue-6.14/cpufreq-governor-fix-negative-idle_time-handling-in-.patch @@ -0,0 +1,116 @@ +From b45ed5fa4606caacc9cba89ec6f012c53dc493ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 11:55:10 +0800 +Subject: cpufreq: governor: Fix negative 'idle_time' handling in dbs_update() + +From: Jie Zhan + +[ Upstream commit 3698dd6b139dc37b35a9ad83d9330c1f99666c02 ] + +We observed an issue that the CPU frequency can't raise up with a 100% CPU +load when NOHZ is off and the 'conservative' governor is selected. + +'idle_time' can be negative if it's obtained from get_cpu_idle_time_jiffy() +when NOHZ is off. This was found and explained in commit 9485e4ca0b48 +("cpufreq: governor: Fix handling of special cases in dbs_update()"). + +However, commit 7592019634f8 ("cpufreq: governors: Fix long idle detection +logic in load calculation") introduced a comparison between 'idle_time' and +'samling_rate' to detect a long idle interval. While 'idle_time' is +converted to int before comparison, it's actually promoted to unsigned +again when compared with an unsigned 'sampling_rate'. Hence, this leads to +wrong idle interval detection when it's in fact 100% busy and sets +policy_dbs->idle_periods to a very large value. 'conservative' adjusts the +frequency to minimum because of the large 'idle_periods', such that the +frequency can't raise up. 'Ondemand' doesn't use policy_dbs->idle_periods +so it fortunately avoids the issue. + +Correct negative 'idle_time' to 0 before any use of it in dbs_update(). + +Fixes: 7592019634f8 ("cpufreq: governors: Fix long idle detection logic in load calculation") +Signed-off-by: Jie Zhan +Reviewed-by: Chen Yu +Link: https://patch.msgid.link/20250213035510.2402076-1-zhanjie9@hisilicon.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/cpufreq_governor.c | 45 +++++++++++++++--------------- + 1 file changed, 23 insertions(+), 22 deletions(-) + +diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c +index af44ee6a64304..1a7fcaf39cc9b 100644 +--- a/drivers/cpufreq/cpufreq_governor.c ++++ b/drivers/cpufreq/cpufreq_governor.c +@@ -145,7 +145,23 @@ unsigned int dbs_update(struct cpufreq_policy *policy) + time_elapsed = update_time - j_cdbs->prev_update_time; + j_cdbs->prev_update_time = update_time; + +- idle_time = cur_idle_time - j_cdbs->prev_cpu_idle; ++ /* ++ * cur_idle_time could be smaller than j_cdbs->prev_cpu_idle if ++ * it's obtained from get_cpu_idle_time_jiffy() when NOHZ is ++ * off, where idle_time is calculated by the difference between ++ * time elapsed in jiffies and "busy time" obtained from CPU ++ * statistics. If a CPU is 100% busy, the time elapsed and busy ++ * time should grow with the same amount in two consecutive ++ * samples, but in practice there could be a tiny difference, ++ * making the accumulated idle time decrease sometimes. Hence, ++ * in this case, idle_time should be regarded as 0 in order to ++ * make the further process correct. ++ */ ++ if (cur_idle_time > j_cdbs->prev_cpu_idle) ++ idle_time = cur_idle_time - j_cdbs->prev_cpu_idle; ++ else ++ idle_time = 0; ++ + j_cdbs->prev_cpu_idle = cur_idle_time; + + if (ignore_nice) { +@@ -162,7 +178,7 @@ unsigned int dbs_update(struct cpufreq_policy *policy) + * calls, so the previous load value can be used then. + */ + load = j_cdbs->prev_load; +- } else if (unlikely((int)idle_time > 2 * sampling_rate && ++ } else if (unlikely(idle_time > 2 * sampling_rate && + j_cdbs->prev_load)) { + /* + * If the CPU had gone completely idle and a task has +@@ -189,30 +205,15 @@ unsigned int dbs_update(struct cpufreq_policy *policy) + load = j_cdbs->prev_load; + j_cdbs->prev_load = 0; + } else { +- if (time_elapsed >= idle_time) { ++ if (time_elapsed > idle_time) + load = 100 * (time_elapsed - idle_time) / time_elapsed; +- } else { +- /* +- * That can happen if idle_time is returned by +- * get_cpu_idle_time_jiffy(). In that case +- * idle_time is roughly equal to the difference +- * between time_elapsed and "busy time" obtained +- * from CPU statistics. Then, the "busy time" +- * can end up being greater than time_elapsed +- * (for example, if jiffies_64 and the CPU +- * statistics are updated by different CPUs), +- * so idle_time may in fact be negative. That +- * means, though, that the CPU was busy all +- * the time (on the rough average) during the +- * last sampling interval and 100 can be +- * returned as the load. +- */ +- load = (int)idle_time < 0 ? 100 : 0; +- } ++ else ++ load = 0; ++ + j_cdbs->prev_load = load; + } + +- if (unlikely((int)idle_time > 2 * sampling_rate)) { ++ if (unlikely(idle_time > 2 * sampling_rate)) { + unsigned int periods = idle_time / sampling_rate; + + if (periods < idle_periods) +-- +2.39.5 + diff --git a/queue-6.14/cpufreq-init-cpufreq-only-for-present-cpus.patch b/queue-6.14/cpufreq-init-cpufreq-only-for-present-cpus.patch new file mode 100644 index 0000000000..c44f0828ba --- /dev/null +++ b/queue-6.14/cpufreq-init-cpufreq-only-for-present-cpus.patch @@ -0,0 +1,232 @@ +From 83d0908a96219c736e4d7b21c92ceb66ca634f2f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 09:39:28 +0800 +Subject: cpufreq: Init cpufreq only for present CPUs + +From: Jacky Bai + +[ Upstream commit 45f589b7167f36290d29c79e3a442dc0b13c086a ] + +for_each_possible_cpu() is currently used to initialize cpufreq. +However, in cpu_dev_register_generic(), for_each_present_cpu() +is used to register CPU devices which means the CPU devices are +only registered for present CPUs and not all possible CPUs. + +With nosmp or maxcpus=0, only the boot CPU is present, lead +to the cpufreq probe failure or defer probe due to no cpu device +available for not present CPUs. + +Change for_each_possible_cpu() to for_each_present_cpu() in the +above cpufreq drivers to ensure it only registers cpufreq for +CPUs that are actually present. + +Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in GENERIC_CPU_DEVICES") +Reviewed-by: Sudeep Holla +Signed-off-by: Jacky Bai +Signed-off-by: Viresh Kumar +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/armada-8k-cpufreq.c | 2 +- + drivers/cpufreq/cpufreq-dt.c | 2 +- + drivers/cpufreq/mediatek-cpufreq-hw.c | 2 +- + drivers/cpufreq/mediatek-cpufreq.c | 2 +- + drivers/cpufreq/mvebu-cpufreq.c | 2 +- + drivers/cpufreq/qcom-cpufreq-hw.c | 2 +- + drivers/cpufreq/qcom-cpufreq-nvmem.c | 8 ++++---- + drivers/cpufreq/scmi-cpufreq.c | 2 +- + drivers/cpufreq/scpi-cpufreq.c | 2 +- + drivers/cpufreq/sun50i-cpufreq-nvmem.c | 6 +++--- + drivers/cpufreq/virtual-cpufreq.c | 2 +- + 11 files changed, 16 insertions(+), 16 deletions(-) + +diff --git a/drivers/cpufreq/armada-8k-cpufreq.c b/drivers/cpufreq/armada-8k-cpufreq.c +index 7a979db81f098..5a3545bd0d8d2 100644 +--- a/drivers/cpufreq/armada-8k-cpufreq.c ++++ b/drivers/cpufreq/armada-8k-cpufreq.c +@@ -47,7 +47,7 @@ static void __init armada_8k_get_sharing_cpus(struct clk *cur_clk, + { + int cpu; + +- for_each_possible_cpu(cpu) { ++ for_each_present_cpu(cpu) { + struct device *cpu_dev; + struct clk *clk; + +diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c +index 3a7c3372bda75..f3913eea5e553 100644 +--- a/drivers/cpufreq/cpufreq-dt.c ++++ b/drivers/cpufreq/cpufreq-dt.c +@@ -303,7 +303,7 @@ static int dt_cpufreq_probe(struct platform_device *pdev) + int ret, cpu; + + /* Request resources early so we can return in case of -EPROBE_DEFER */ +- for_each_possible_cpu(cpu) { ++ for_each_present_cpu(cpu) { + ret = dt_cpufreq_early_init(&pdev->dev, cpu); + if (ret) + goto err; +diff --git a/drivers/cpufreq/mediatek-cpufreq-hw.c b/drivers/cpufreq/mediatek-cpufreq-hw.c +index 9252ebd60373f..478257523cc3c 100644 +--- a/drivers/cpufreq/mediatek-cpufreq-hw.c ++++ b/drivers/cpufreq/mediatek-cpufreq-hw.c +@@ -304,7 +304,7 @@ static int mtk_cpufreq_hw_driver_probe(struct platform_device *pdev) + struct regulator *cpu_reg; + + /* Make sure that all CPU supplies are available before proceeding. */ +- for_each_possible_cpu(cpu) { ++ for_each_present_cpu(cpu) { + cpu_dev = get_cpu_device(cpu); + if (!cpu_dev) + return dev_err_probe(&pdev->dev, -EPROBE_DEFER, +diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c +index 663f61565cf72..2e4f9ca0af350 100644 +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -632,7 +632,7 @@ static int mtk_cpufreq_probe(struct platform_device *pdev) + return dev_err_probe(&pdev->dev, -ENODEV, + "failed to get mtk cpufreq platform data\n"); + +- for_each_possible_cpu(cpu) { ++ for_each_present_cpu(cpu) { + info = mtk_cpu_dvfs_info_lookup(cpu); + if (info) + continue; +diff --git a/drivers/cpufreq/mvebu-cpufreq.c b/drivers/cpufreq/mvebu-cpufreq.c +index 7f3cfe668f307..2aad4c04673cc 100644 +--- a/drivers/cpufreq/mvebu-cpufreq.c ++++ b/drivers/cpufreq/mvebu-cpufreq.c +@@ -56,7 +56,7 @@ static int __init armada_xp_pmsu_cpufreq_init(void) + * it), and registers the clock notifier that will take care + * of doing the PMSU part of a frequency transition. + */ +- for_each_possible_cpu(cpu) { ++ for_each_present_cpu(cpu) { + struct device *cpu_dev; + struct clk *clk; + int ret; +diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c +index b2e7e89feaac4..dce7cad1813fb 100644 +--- a/drivers/cpufreq/qcom-cpufreq-hw.c ++++ b/drivers/cpufreq/qcom-cpufreq-hw.c +@@ -306,7 +306,7 @@ static void qcom_get_related_cpus(int index, struct cpumask *m) + struct of_phandle_args args; + int cpu, ret; + +- for_each_possible_cpu(cpu) { ++ for_each_present_cpu(cpu) { + cpu_np = of_cpu_device_node_get(cpu); + if (!cpu_np) + continue; +diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c +index 3a8ed723a23e5..54f8117103c85 100644 +--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c ++++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c +@@ -489,7 +489,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev) + nvmem_cell_put(speedbin_nvmem); + } + +- for_each_possible_cpu(cpu) { ++ for_each_present_cpu(cpu) { + struct dev_pm_opp_config config = { + .supported_hw = NULL, + }; +@@ -543,7 +543,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev) + dev_err(cpu_dev, "Failed to register platform device\n"); + + free_opp: +- for_each_possible_cpu(cpu) { ++ for_each_present_cpu(cpu) { + dev_pm_domain_detach_list(drv->cpus[cpu].pd_list); + dev_pm_opp_clear_config(drv->cpus[cpu].opp_token); + } +@@ -557,7 +557,7 @@ static void qcom_cpufreq_remove(struct platform_device *pdev) + + platform_device_unregister(cpufreq_dt_pdev); + +- for_each_possible_cpu(cpu) { ++ for_each_present_cpu(cpu) { + dev_pm_domain_detach_list(drv->cpus[cpu].pd_list); + dev_pm_opp_clear_config(drv->cpus[cpu].opp_token); + } +@@ -568,7 +568,7 @@ static int qcom_cpufreq_suspend(struct device *dev) + struct qcom_cpufreq_drv *drv = dev_get_drvdata(dev); + unsigned int cpu; + +- for_each_possible_cpu(cpu) ++ for_each_present_cpu(cpu) + qcom_cpufreq_suspend_pd_devs(drv, cpu); + + return 0; +diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c +index b8fe758aeb010..914bf2c940a03 100644 +--- a/drivers/cpufreq/scmi-cpufreq.c ++++ b/drivers/cpufreq/scmi-cpufreq.c +@@ -104,7 +104,7 @@ scmi_get_sharing_cpus(struct device *cpu_dev, int domain, + int cpu, tdomain; + struct device *tcpu_dev; + +- for_each_possible_cpu(cpu) { ++ for_each_present_cpu(cpu) { + if (cpu == cpu_dev->id) + continue; + +diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c +index 9e09565e41c09..1f97b949763fa 100644 +--- a/drivers/cpufreq/scpi-cpufreq.c ++++ b/drivers/cpufreq/scpi-cpufreq.c +@@ -65,7 +65,7 @@ scpi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask) + if (domain < 0) + return domain; + +- for_each_possible_cpu(cpu) { ++ for_each_present_cpu(cpu) { + if (cpu == cpu_dev->id) + continue; + +diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c +index 17d6a149f580d..47d6840b34899 100644 +--- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c ++++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c +@@ -262,7 +262,7 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev) + snprintf(name, sizeof(name), "speed%d", speed); + config.prop_name = name; + +- for_each_possible_cpu(cpu) { ++ for_each_present_cpu(cpu) { + struct device *cpu_dev = get_cpu_device(cpu); + + if (!cpu_dev) { +@@ -288,7 +288,7 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev) + pr_err("Failed to register platform device\n"); + + free_opp: +- for_each_possible_cpu(cpu) ++ for_each_present_cpu(cpu) + dev_pm_opp_clear_config(opp_tokens[cpu]); + kfree(opp_tokens); + +@@ -302,7 +302,7 @@ static void sun50i_cpufreq_nvmem_remove(struct platform_device *pdev) + + platform_device_unregister(cpufreq_dt_pdev); + +- for_each_possible_cpu(cpu) ++ for_each_present_cpu(cpu) + dev_pm_opp_clear_config(opp_tokens[cpu]); + + kfree(opp_tokens); +diff --git a/drivers/cpufreq/virtual-cpufreq.c b/drivers/cpufreq/virtual-cpufreq.c +index a050b3a6737f0..272dc3c85106c 100644 +--- a/drivers/cpufreq/virtual-cpufreq.c ++++ b/drivers/cpufreq/virtual-cpufreq.c +@@ -138,7 +138,7 @@ static int virt_cpufreq_get_sharing_cpus(struct cpufreq_policy *policy) + cur_perf_domain = readl_relaxed(base + policy->cpu * + PER_CPU_OFFSET + REG_PERF_DOMAIN_OFFSET); + +- for_each_possible_cpu(cpu) { ++ for_each_present_cpu(cpu) { + cpu_dev = get_cpu_device(cpu); + if (!cpu_dev) + continue; +-- +2.39.5 + diff --git a/queue-6.14/cpufreq-scpi-compare-khz-instead-of-hz.patch b/queue-6.14/cpufreq-scpi-compare-khz-instead-of-hz.patch new file mode 100644 index 0000000000..05786eaaf9 --- /dev/null +++ b/queue-6.14/cpufreq-scpi-compare-khz-instead-of-hz.patch @@ -0,0 +1,52 @@ +From 220e48d13faf15344257cc4884c63b5065075c4b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 25 Jan 2025 08:49:49 +0000 +Subject: cpufreq: scpi: compare kHz instead of Hz + +From: zuoqian + +[ Upstream commit 4742da9774a416908ef8e3916164192c15c0e2d1 ] + +The CPU rate from clk_get_rate() may not be divisible by 1000 +(e.g., 133333333). But the rate calculated from frequency(kHz) is +always divisible by 1000 (e.g., 133333000). +Comparing the rate causes a warning during CPU scaling: +"cpufreq: __target_index: Failed to change cpu frequency: -5". +When we choose to compare kHz here, the issue does not occur. + +Fixes: 343a8d17fa8d ("cpufreq: scpi: remove arm_big_little dependency") +Signed-off-by: zuoqian +Reviewed-by: Dan Carpenter +Signed-off-by: Viresh Kumar +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/scpi-cpufreq.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c +index cd89c1b9832c0..9e09565e41c09 100644 +--- a/drivers/cpufreq/scpi-cpufreq.c ++++ b/drivers/cpufreq/scpi-cpufreq.c +@@ -39,8 +39,9 @@ static unsigned int scpi_cpufreq_get_rate(unsigned int cpu) + static int + scpi_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index) + { +- u64 rate = policy->freq_table[index].frequency * 1000; ++ unsigned long freq_khz = policy->freq_table[index].frequency; + struct scpi_data *priv = policy->driver_data; ++ unsigned long rate = freq_khz * 1000; + int ret; + + ret = clk_set_rate(priv->clk, rate); +@@ -48,7 +49,7 @@ scpi_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index) + if (ret) + return ret; + +- if (clk_get_rate(priv->clk) != rate) ++ if (clk_get_rate(priv->clk) / 1000 != freq_khz) + return -EIO; + + return 0; +-- +2.39.5 + diff --git a/queue-6.14/cpufreq-tegra194-allow-building-for-tegra234.patch b/queue-6.14/cpufreq-tegra194-allow-building-for-tegra234.patch new file mode 100644 index 0000000000..8882a83a17 --- /dev/null +++ b/queue-6.14/cpufreq-tegra194-allow-building-for-tegra234.patch @@ -0,0 +1,36 @@ +From 3fce387a379f6230cba40486eac97b4c9c916a4a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 12:51:59 -0600 +Subject: cpufreq: tegra194: Allow building for Tegra234 + +From: Aaron Kling + +[ Upstream commit 4a1e3bf61fc78ad100018adb573355303915dca3 ] + +Support was added for Tegra234 in the referenced commit, but the Kconfig +was not updated to allow building for the arch. + +Fixes: 273bc890a2a8 ("cpufreq: tegra194: Add support for Tegra234") +Signed-off-by: Aaron Kling +Signed-off-by: Viresh Kumar +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/Kconfig.arm | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm +index 9e46960f6a862..4f9cb943d945c 100644 +--- a/drivers/cpufreq/Kconfig.arm ++++ b/drivers/cpufreq/Kconfig.arm +@@ -254,7 +254,7 @@ config ARM_TEGRA186_CPUFREQ + + config ARM_TEGRA194_CPUFREQ + tristate "Tegra194 CPUFreq support" +- depends on ARCH_TEGRA_194_SOC || (64BIT && COMPILE_TEST) ++ depends on ARCH_TEGRA_194_SOC || ARCH_TEGRA_234_SOC || (64BIT && COMPILE_TEST) + depends on TEGRA_BPMP + default y + help +-- +2.39.5 + diff --git a/queue-6.14/cpuidle-init-cpuidle-only-for-present-cpus.patch b/queue-6.14/cpuidle-init-cpuidle-only-for-present-cpus.patch new file mode 100644 index 0000000000..bce83c25d1 --- /dev/null +++ b/queue-6.14/cpuidle-init-cpuidle-only-for-present-cpus.patch @@ -0,0 +1,141 @@ +From f0cfd877edb54e0afbdfb87ff8e2697c14a83e23 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Mar 2025 22:55:47 +0800 +Subject: cpuidle: Init cpuidle only for present CPUs + +From: Jacky Bai + +[ Upstream commit 68cb0139fec8e05b93978dc0ef1bc8df90a86419 ] + +for_each_possible_cpu() is currently used to initialize cpuidle +in below cpuidle drivers: + drivers/cpuidle/cpuidle-arm.c + drivers/cpuidle/cpuidle-big_little.c + drivers/cpuidle/cpuidle-psci.c + drivers/cpuidle/cpuidle-qcom-spm.c + drivers/cpuidle/cpuidle-riscv-sbi.c + +However, in cpu_dev_register_generic(), for_each_present_cpu() +is used to register CPU devices which means the CPU devices are +only registered for present CPUs and not all possible CPUs. + +With nosmp or maxcpus=0, only the boot CPU is present, lead +to the failure: + + | Failed to register cpuidle device for cpu1 + +Then rollback to cancel all CPUs' cpuidle registration. + +Change for_each_possible_cpu() to for_each_present_cpu() in the +above cpuidle drivers to ensure it only registers cpuidle devices +for CPUs that are actually present. + +Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in GENERIC_CPU_DEVICES") +Reviewed-by: Dhruva Gole +Reviewed-by: Sudeep Holla +Tested-by: Yuanjie Yang +Signed-off-by: Jacky Bai +Reviewed-by: Ulf Hansson +Link: https://patch.msgid.link/20250307145547.2784821-1-ping.bai@nxp.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/cpuidle/cpuidle-arm.c | 8 ++++---- + drivers/cpuidle/cpuidle-big_little.c | 2 +- + drivers/cpuidle/cpuidle-psci.c | 4 ++-- + drivers/cpuidle/cpuidle-qcom-spm.c | 2 +- + drivers/cpuidle/cpuidle-riscv-sbi.c | 4 ++-- + 5 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/drivers/cpuidle/cpuidle-arm.c b/drivers/cpuidle/cpuidle-arm.c +index caba6f4bb1b79..e044fefdb8167 100644 +--- a/drivers/cpuidle/cpuidle-arm.c ++++ b/drivers/cpuidle/cpuidle-arm.c +@@ -137,9 +137,9 @@ static int __init arm_idle_init_cpu(int cpu) + /* + * arm_idle_init - Initializes arm cpuidle driver + * +- * Initializes arm cpuidle driver for all CPUs, if any CPU fails +- * to register cpuidle driver then rollback to cancel all CPUs +- * registration. ++ * Initializes arm cpuidle driver for all present CPUs, if any ++ * CPU fails to register cpuidle driver then rollback to cancel ++ * all CPUs registration. + */ + static int __init arm_idle_init(void) + { +@@ -147,7 +147,7 @@ static int __init arm_idle_init(void) + struct cpuidle_driver *drv; + struct cpuidle_device *dev; + +- for_each_possible_cpu(cpu) { ++ for_each_present_cpu(cpu) { + ret = arm_idle_init_cpu(cpu); + if (ret) + goto out_fail; +diff --git a/drivers/cpuidle/cpuidle-big_little.c b/drivers/cpuidle/cpuidle-big_little.c +index 74972deda0ead..4abba42fcc311 100644 +--- a/drivers/cpuidle/cpuidle-big_little.c ++++ b/drivers/cpuidle/cpuidle-big_little.c +@@ -148,7 +148,7 @@ static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int part_id) + if (!cpumask) + return -ENOMEM; + +- for_each_possible_cpu(cpu) ++ for_each_present_cpu(cpu) + if (smp_cpuid_part(cpu) == part_id) + cpumask_set_cpu(cpu, cpumask); + +diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c +index 2562dc001fc1d..a4594c3d6562d 100644 +--- a/drivers/cpuidle/cpuidle-psci.c ++++ b/drivers/cpuidle/cpuidle-psci.c +@@ -400,7 +400,7 @@ static int psci_idle_init_cpu(struct device *dev, int cpu) + /* + * psci_idle_probe - Initializes PSCI cpuidle driver + * +- * Initializes PSCI cpuidle driver for all CPUs, if any CPU fails ++ * Initializes PSCI cpuidle driver for all present CPUs, if any CPU fails + * to register cpuidle driver then rollback to cancel all CPUs + * registration. + */ +@@ -410,7 +410,7 @@ static int psci_cpuidle_probe(struct platform_device *pdev) + struct cpuidle_driver *drv; + struct cpuidle_device *dev; + +- for_each_possible_cpu(cpu) { ++ for_each_present_cpu(cpu) { + ret = psci_idle_init_cpu(&pdev->dev, cpu); + if (ret) + goto out_fail; +diff --git a/drivers/cpuidle/cpuidle-qcom-spm.c b/drivers/cpuidle/cpuidle-qcom-spm.c +index 3ab240e0e1229..5f386761b1562 100644 +--- a/drivers/cpuidle/cpuidle-qcom-spm.c ++++ b/drivers/cpuidle/cpuidle-qcom-spm.c +@@ -135,7 +135,7 @@ static int spm_cpuidle_drv_probe(struct platform_device *pdev) + if (ret) + return dev_err_probe(&pdev->dev, ret, "set warm boot addr failed"); + +- for_each_possible_cpu(cpu) { ++ for_each_present_cpu(cpu) { + ret = spm_cpuidle_register(&pdev->dev, cpu); + if (ret && ret != -ENODEV) { + dev_err(&pdev->dev, +diff --git a/drivers/cpuidle/cpuidle-riscv-sbi.c b/drivers/cpuidle/cpuidle-riscv-sbi.c +index 0c92a628bbd40..0fe1ece9fbdca 100644 +--- a/drivers/cpuidle/cpuidle-riscv-sbi.c ++++ b/drivers/cpuidle/cpuidle-riscv-sbi.c +@@ -529,8 +529,8 @@ static int sbi_cpuidle_probe(struct platform_device *pdev) + return ret; + } + +- /* Initialize CPU idle driver for each CPU */ +- for_each_possible_cpu(cpu) { ++ /* Initialize CPU idle driver for each present CPU */ ++ for_each_present_cpu(cpu) { + ret = sbi_cpuidle_init_cpu(&pdev->dev, cpu); + if (ret) { + pr_debug("HART%ld: idle driver init failed\n", +-- +2.39.5 + diff --git a/queue-6.14/crypto-api-call-crypto_alg_put-in-crypto_unregister_.patch b/queue-6.14/crypto-api-call-crypto_alg_put-in-crypto_unregister_.patch new file mode 100644 index 0000000000..871d642c94 --- /dev/null +++ b/queue-6.14/crypto-api-call-crypto_alg_put-in-crypto_unregister_.patch @@ -0,0 +1,37 @@ +From db969228e5fd9eca992281a76f1089d9c9cba85e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Mar 2025 17:50:24 +0800 +Subject: crypto: api - Call crypto_alg_put in crypto_unregister_alg + +From: Herbert Xu + +[ Upstream commit 27b13425349e94ad77b174b032674097cab241c8 ] + +Instead of calling cra_destroy by hand, call it through +crypto_alg_put so that the correct unwinding functions are called +through crypto_destroy_alg. + +Fixes: 3d6979bf3bd5 ("crypto: api - Add cra_type->destroy hook") +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + crypto/algapi.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/crypto/algapi.c b/crypto/algapi.c +index 5318c214debb0..6120329eadada 100644 +--- a/crypto/algapi.c ++++ b/crypto/algapi.c +@@ -464,8 +464,7 @@ void crypto_unregister_alg(struct crypto_alg *alg) + if (WARN_ON(refcount_read(&alg->cra_refcnt) != 1)) + return; + +- if (alg->cra_destroy) +- alg->cra_destroy(alg); ++ crypto_alg_put(alg); + + crypto_remove_final(&list); + } +-- +2.39.5 + diff --git a/queue-6.14/crypto-api-fix-larval-relookup-type-and-mask.patch b/queue-6.14/crypto-api-fix-larval-relookup-type-and-mask.patch new file mode 100644 index 0000000000..fe1196e86c --- /dev/null +++ b/queue-6.14/crypto-api-fix-larval-relookup-type-and-mask.patch @@ -0,0 +1,93 @@ +From 6da9a9702aac6a15e66cb72dfcec6338346f7167 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 10:31:25 +0800 +Subject: crypto: api - Fix larval relookup type and mask + +From: Herbert Xu + +[ Upstream commit 7505436e2925d89a13706a295a6734d6cabb4b43 ] + +When the lookup is retried after instance construction, it uses +the type and mask from the larval, which may not match the values +used by the caller. For example, if the caller is requesting for +a !NEEDS_FALLBACK algorithm, it may end up getting an algorithm +that needs fallbacks. + +Fix this by making the caller supply the type/mask and using that +for the lookup. + +Reported-by: Coiby Xu +Fixes: 96ad59552059 ("crypto: api - Remove instance larval fulfilment") +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + crypto/api.c | 17 +++++++---------- + 1 file changed, 7 insertions(+), 10 deletions(-) + +diff --git a/crypto/api.c b/crypto/api.c +index bfd177a4313a0..c2c4eb14ef955 100644 +--- a/crypto/api.c ++++ b/crypto/api.c +@@ -36,7 +36,8 @@ EXPORT_SYMBOL_GPL(crypto_chain); + DEFINE_STATIC_KEY_FALSE(__crypto_boot_test_finished); + #endif + +-static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg); ++static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg, ++ u32 type, u32 mask); + static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type, + u32 mask); + +@@ -145,7 +146,7 @@ static struct crypto_alg *crypto_larval_add(const char *name, u32 type, + if (alg != &larval->alg) { + kfree(larval); + if (crypto_is_larval(alg)) +- alg = crypto_larval_wait(alg); ++ alg = crypto_larval_wait(alg, type, mask); + } + + return alg; +@@ -197,7 +198,8 @@ static void crypto_start_test(struct crypto_larval *larval) + crypto_schedule_test(larval); + } + +-static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg) ++static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg, ++ u32 type, u32 mask) + { + struct crypto_larval *larval; + long time_left; +@@ -219,12 +221,7 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg) + crypto_larval_kill(larval); + alg = ERR_PTR(-ETIMEDOUT); + } else if (!alg) { +- u32 type; +- u32 mask; +- + alg = &larval->alg; +- type = alg->cra_flags & ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD); +- mask = larval->mask; + alg = crypto_alg_lookup(alg->cra_name, type, mask) ?: + ERR_PTR(-EAGAIN); + } else if (IS_ERR(alg)) +@@ -304,7 +301,7 @@ static struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, + } + + if (!IS_ERR_OR_NULL(alg) && crypto_is_larval(alg)) +- alg = crypto_larval_wait(alg); ++ alg = crypto_larval_wait(alg, type, mask); + else if (alg) + ; + else if (!(mask & CRYPTO_ALG_TESTED)) +@@ -352,7 +349,7 @@ struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask) + ok = crypto_probing_notify(CRYPTO_MSG_ALG_REQUEST, larval); + + if (ok == NOTIFY_STOP) +- alg = crypto_larval_wait(larval); ++ alg = crypto_larval_wait(larval, type, mask); + else { + crypto_mod_put(larval); + alg = ERR_PTR(-ENOENT); +-- +2.39.5 + diff --git a/queue-6.14/crypto-bpf-add-module_description-for-skcipher.patch b/queue-6.14/crypto-bpf-add-module_description-for-skcipher.patch new file mode 100644 index 0000000000..8ae8854a5c --- /dev/null +++ b/queue-6.14/crypto-bpf-add-module_description-for-skcipher.patch @@ -0,0 +1,37 @@ +From a30fec32841b19165be7cae0ad4dddebd6bc69c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 13:55:55 +0100 +Subject: crypto: bpf - Add MODULE_DESCRIPTION for skcipher + +From: Arnd Bergmann + +[ Upstream commit f307c87ea06c64b87fcd3221a682cd713cde51e9 ] + +All modules should have a description, building with extra warnings +enabled prints this outfor the for bpf_crypto_skcipher module: + +WARNING: modpost: missing MODULE_DESCRIPTION() in crypto/bpf_crypto_skcipher.o + +Add a description line. + +Fixes: fda4f71282b2 ("bpf: crypto: add skcipher to bpf crypto") +Signed-off-by: Arnd Bergmann +Reviewed-by: Vadim Fedorenko +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + crypto/bpf_crypto_skcipher.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/crypto/bpf_crypto_skcipher.c b/crypto/bpf_crypto_skcipher.c +index b5e657415770a..a88798d3e8c87 100644 +--- a/crypto/bpf_crypto_skcipher.c ++++ b/crypto/bpf_crypto_skcipher.c +@@ -80,3 +80,4 @@ static void __exit bpf_crypto_skcipher_exit(void) + module_init(bpf_crypto_skcipher_init); + module_exit(bpf_crypto_skcipher_exit); + MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("Symmetric key cipher support for BPF"); +-- +2.39.5 + diff --git a/queue-6.14/crypto-hisilicon-sec2-fix-for-aead-auth-key-length.patch b/queue-6.14/crypto-hisilicon-sec2-fix-for-aead-auth-key-length.patch new file mode 100644 index 0000000000..8775a1e6e9 --- /dev/null +++ b/queue-6.14/crypto-hisilicon-sec2-fix-for-aead-auth-key-length.patch @@ -0,0 +1,52 @@ +From 6f739a3f70742e024a70e197a291fe5b5612cac3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 11:56:26 +0800 +Subject: crypto: hisilicon/sec2 - fix for aead auth key length + +From: Wenkai Lin + +[ Upstream commit 1b284ffc30b02808a0de698667cbcf5ce5f9144e ] + +According to the HMAC RFC, the authentication key +can be 0 bytes, and the hardware can handle this +scenario. Therefore, remove the incorrect validation +for this case. + +Fixes: 2f072d75d1ab ("crypto: hisilicon - Add aead support on SEC2") +Signed-off-by: Wenkai Lin +Signed-off-by: Chenghai Huang +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/hisilicon/sec2/sec_crypto.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c +index 82827d637492a..8ea5305bc320f 100644 +--- a/drivers/crypto/hisilicon/sec2/sec_crypto.c ++++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c +@@ -1085,11 +1085,6 @@ static int sec_aead_auth_set_key(struct sec_auth_ctx *ctx, + struct crypto_shash *hash_tfm = ctx->hash_tfm; + int blocksize, digestsize, ret; + +- if (!keys->authkeylen) { +- pr_err("hisi_sec2: aead auth key error!\n"); +- return -EINVAL; +- } +- + blocksize = crypto_shash_blocksize(hash_tfm); + digestsize = crypto_shash_digestsize(hash_tfm); + if (keys->authkeylen > blocksize) { +@@ -1101,7 +1096,8 @@ static int sec_aead_auth_set_key(struct sec_auth_ctx *ctx, + } + ctx->a_key_len = digestsize; + } else { +- memcpy(ctx->a_key, keys->authkey, keys->authkeylen); ++ if (keys->authkeylen) ++ memcpy(ctx->a_key, keys->authkey, keys->authkeylen); + ctx->a_key_len = keys->authkeylen; + } + +-- +2.39.5 + diff --git a/queue-6.14/crypto-hisilicon-sec2-fix-for-aead-authsize-alignmen.patch b/queue-6.14/crypto-hisilicon-sec2-fix-for-aead-authsize-alignmen.patch new file mode 100644 index 0000000000..56b84fdd8e --- /dev/null +++ b/queue-6.14/crypto-hisilicon-sec2-fix-for-aead-authsize-alignmen.patch @@ -0,0 +1,106 @@ +From 2e57eacf8ceaadc541dc39c4aa5172f66829e06e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 11:56:27 +0800 +Subject: crypto: hisilicon/sec2 - fix for aead authsize alignment + +From: Wenkai Lin + +[ Upstream commit a49cc71e219040d771a8c1254879984f98192811 ] + +The hardware only supports authentication sizes +that are 4-byte aligned. Therefore, the driver +switches to software computation in this case. + +Fixes: 2f072d75d1ab ("crypto: hisilicon - Add aead support on SEC2") +Signed-off-by: Wenkai Lin +Signed-off-by: Chenghai Huang +Signed-off-by: Herbert Xu +Stable-dep-of: f4f353cb7ae9 ("crypto: hisilicon/sec2 - fix for sec spec check") +Signed-off-by: Sasha Levin +--- + drivers/crypto/hisilicon/sec2/sec_crypto.c | 22 +++++++++------------- + 1 file changed, 9 insertions(+), 13 deletions(-) + +diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c +index 66bc07da9eb6f..50223e3c4bccf 100644 +--- a/drivers/crypto/hisilicon/sec2/sec_crypto.c ++++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c +@@ -57,7 +57,6 @@ + #define SEC_TYPE_MASK 0x0F + #define SEC_DONE_MASK 0x0001 + #define SEC_ICV_MASK 0x000E +-#define SEC_SQE_LEN_RATE_MASK 0x3 + + #define SEC_TOTAL_IV_SZ(depth) (SEC_IV_SIZE * (depth)) + #define SEC_SGL_SGE_NR 128 +@@ -80,16 +79,16 @@ + #define SEC_TOTAL_PBUF_SZ(depth) (PAGE_SIZE * SEC_PBUF_PAGE_NUM(depth) + \ + SEC_PBUF_LEFT_SZ(depth)) + +-#define SEC_SQE_LEN_RATE 4 + #define SEC_SQE_CFLAG 2 + #define SEC_SQE_AEAD_FLAG 3 + #define SEC_SQE_DONE 0x1 + #define SEC_ICV_ERR 0x2 +-#define MIN_MAC_LEN 4 + #define MAC_LEN_MASK 0x1U + #define MAX_INPUT_DATA_LEN 0xFFFE00 + #define BITS_MASK 0xFF ++#define WORD_MASK 0x3 + #define BYTE_BITS 0x8 ++#define BYTES_TO_WORDS(bcount) ((bcount) >> 2) + #define SEC_XTS_NAME_SZ 0x3 + #define IV_CM_CAL_NUM 2 + #define IV_CL_MASK 0x7 +@@ -1175,7 +1174,7 @@ static int sec_aead_setkey(struct crypto_aead *tfm, const u8 *key, + goto bad_key; + } + +- if (ctx->a_ctx.a_key_len & SEC_SQE_LEN_RATE_MASK) { ++ if (ctx->a_ctx.a_key_len & WORD_MASK) { + ret = -EINVAL; + dev_err(dev, "AUTH key length error!\n"); + goto bad_key; +@@ -1583,11 +1582,10 @@ static void sec_auth_bd_fill_ex(struct sec_auth_ctx *ctx, int dir, + + sec_sqe->type2.a_key_addr = cpu_to_le64(ctx->a_key_dma); + +- sec_sqe->type2.mac_key_alg = cpu_to_le32(authsize / SEC_SQE_LEN_RATE); ++ sec_sqe->type2.mac_key_alg = cpu_to_le32(BYTES_TO_WORDS(authsize)); + + sec_sqe->type2.mac_key_alg |= +- cpu_to_le32((u32)((ctx->a_key_len) / +- SEC_SQE_LEN_RATE) << SEC_AKEY_OFFSET); ++ cpu_to_le32((u32)BYTES_TO_WORDS(ctx->a_key_len) << SEC_AKEY_OFFSET); + + sec_sqe->type2.mac_key_alg |= + cpu_to_le32((u32)(ctx->a_alg) << SEC_AEAD_ALG_OFFSET); +@@ -1639,12 +1637,10 @@ static void sec_auth_bd_fill_ex_v3(struct sec_auth_ctx *ctx, int dir, + sqe3->a_key_addr = cpu_to_le64(ctx->a_key_dma); + + sqe3->auth_mac_key |= +- cpu_to_le32((u32)(authsize / +- SEC_SQE_LEN_RATE) << SEC_MAC_OFFSET_V3); ++ cpu_to_le32(BYTES_TO_WORDS(authsize) << SEC_MAC_OFFSET_V3); + + sqe3->auth_mac_key |= +- cpu_to_le32((u32)(ctx->a_key_len / +- SEC_SQE_LEN_RATE) << SEC_AKEY_OFFSET_V3); ++ cpu_to_le32((u32)BYTES_TO_WORDS(ctx->a_key_len) << SEC_AKEY_OFFSET_V3); + + sqe3->auth_mac_key |= + cpu_to_le32((u32)(ctx->a_alg) << SEC_AUTH_ALG_OFFSET_V3); +@@ -2234,8 +2230,8 @@ static int sec_aead_spec_check(struct sec_ctx *ctx, struct sec_req *sreq) + struct device *dev = ctx->dev; + int ret; + +- /* Hardware does not handle cases where authsize is less than 4 bytes */ +- if (unlikely(sz < MIN_MAC_LEN)) { ++ /* Hardware does not handle cases where authsize is not 4 bytes aligned */ ++ if (c_mode == SEC_CMODE_CBC && (sz & WORD_MASK)) { + sreq->aead_req.fallback = true; + return -EINVAL; + } +-- +2.39.5 + diff --git a/queue-6.14/crypto-hisilicon-sec2-fix-for-sec-spec-check.patch b/queue-6.14/crypto-hisilicon-sec2-fix-for-sec-spec-check.patch new file mode 100644 index 0000000000..5b2ead3eb1 --- /dev/null +++ b/queue-6.14/crypto-hisilicon-sec2-fix-for-sec-spec-check.patch @@ -0,0 +1,277 @@ +From 05369364c8787ff08b6ee16a362d24b0c0e97a68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 11:56:28 +0800 +Subject: crypto: hisilicon/sec2 - fix for sec spec check + +From: Wenkai Lin + +[ Upstream commit f4f353cb7ae9bb43e34943edb693532a39118eca ] + +During encryption and decryption, user requests +must be checked first, if the specifications that +are not supported by the hardware are used, the +software computing is used for processing. + +Fixes: 2f072d75d1ab ("crypto: hisilicon - Add aead support on SEC2") +Signed-off-by: Wenkai Lin +Signed-off-by: Chenghai Huang +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/hisilicon/sec2/sec.h | 1 - + drivers/crypto/hisilicon/sec2/sec_crypto.c | 101 ++++++++------------- + 2 files changed, 39 insertions(+), 63 deletions(-) + +diff --git a/drivers/crypto/hisilicon/sec2/sec.h b/drivers/crypto/hisilicon/sec2/sec.h +index 4b99702308228..703920b49c7c0 100644 +--- a/drivers/crypto/hisilicon/sec2/sec.h ++++ b/drivers/crypto/hisilicon/sec2/sec.h +@@ -37,7 +37,6 @@ struct sec_aead_req { + u8 *a_ivin; + dma_addr_t a_ivin_dma; + struct aead_request *aead_req; +- bool fallback; + }; + + /* SEC request of Crypto */ +diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c +index 50223e3c4bccf..82827d637492a 100644 +--- a/drivers/crypto/hisilicon/sec2/sec_crypto.c ++++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c +@@ -690,14 +690,10 @@ static int sec_skcipher_fbtfm_init(struct crypto_skcipher *tfm) + + c_ctx->fallback = false; + +- /* Currently, only XTS mode need fallback tfm when using 192bit key */ +- if (likely(strncmp(alg, "xts", SEC_XTS_NAME_SZ))) +- return 0; +- + c_ctx->fbtfm = crypto_alloc_sync_skcipher(alg, 0, + CRYPTO_ALG_NEED_FALLBACK); + if (IS_ERR(c_ctx->fbtfm)) { +- pr_err("failed to alloc xts mode fallback tfm!\n"); ++ pr_err("failed to alloc fallback tfm for %s!\n", alg); + return PTR_ERR(c_ctx->fbtfm); + } + +@@ -857,7 +853,7 @@ static int sec_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, + } + + memcpy(c_ctx->c_key, key, keylen); +- if (c_ctx->fallback && c_ctx->fbtfm) { ++ if (c_ctx->fbtfm) { + ret = crypto_sync_skcipher_setkey(c_ctx->fbtfm, key, keylen); + if (ret) { + dev_err(dev, "failed to set fallback skcipher key!\n"); +@@ -1159,8 +1155,10 @@ static int sec_aead_setkey(struct crypto_aead *tfm, const u8 *key, + } + + ret = crypto_authenc_extractkeys(&keys, key, keylen); +- if (ret) ++ if (ret) { ++ dev_err(dev, "sec extract aead keys err!\n"); + goto bad_key; ++ } + + ret = sec_aead_aes_set_key(c_ctx, &keys); + if (ret) { +@@ -1174,12 +1172,6 @@ static int sec_aead_setkey(struct crypto_aead *tfm, const u8 *key, + goto bad_key; + } + +- if (ctx->a_ctx.a_key_len & WORD_MASK) { +- ret = -EINVAL; +- dev_err(dev, "AUTH key length error!\n"); +- goto bad_key; +- } +- + ret = sec_aead_fallback_setkey(a_ctx, tfm, key, keylen); + if (ret) { + dev_err(dev, "set sec fallback key err!\n"); +@@ -1999,8 +1991,7 @@ static int sec_aead_sha512_ctx_init(struct crypto_aead *tfm) + return sec_aead_ctx_init(tfm, "sha512"); + } + +-static int sec_skcipher_cryptlen_check(struct sec_ctx *ctx, +- struct sec_req *sreq) ++static int sec_skcipher_cryptlen_check(struct sec_ctx *ctx, struct sec_req *sreq) + { + u32 cryptlen = sreq->c_req.sk_req->cryptlen; + struct device *dev = ctx->dev; +@@ -2022,10 +2013,6 @@ static int sec_skcipher_cryptlen_check(struct sec_ctx *ctx, + } + break; + case SEC_CMODE_CTR: +- if (unlikely(ctx->sec->qm.ver < QM_HW_V3)) { +- dev_err(dev, "skcipher HW version error!\n"); +- ret = -EINVAL; +- } + break; + default: + ret = -EINVAL; +@@ -2034,17 +2021,21 @@ static int sec_skcipher_cryptlen_check(struct sec_ctx *ctx, + return ret; + } + +-static int sec_skcipher_param_check(struct sec_ctx *ctx, struct sec_req *sreq) ++static int sec_skcipher_param_check(struct sec_ctx *ctx, ++ struct sec_req *sreq, bool *need_fallback) + { + struct skcipher_request *sk_req = sreq->c_req.sk_req; + struct device *dev = ctx->dev; + u8 c_alg = ctx->c_ctx.c_alg; + +- if (unlikely(!sk_req->src || !sk_req->dst || +- sk_req->cryptlen > MAX_INPUT_DATA_LEN)) { ++ if (unlikely(!sk_req->src || !sk_req->dst)) { + dev_err(dev, "skcipher input param error!\n"); + return -EINVAL; + } ++ ++ if (sk_req->cryptlen > MAX_INPUT_DATA_LEN) ++ *need_fallback = true; ++ + sreq->c_req.c_len = sk_req->cryptlen; + + if (ctx->pbuf_supported && sk_req->cryptlen <= SEC_PBUF_SZ) +@@ -2102,6 +2093,7 @@ static int sec_skcipher_crypto(struct skcipher_request *sk_req, bool encrypt) + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(sk_req); + struct sec_req *req = skcipher_request_ctx(sk_req); + struct sec_ctx *ctx = crypto_skcipher_ctx(tfm); ++ bool need_fallback = false; + int ret; + + if (!sk_req->cryptlen) { +@@ -2115,11 +2107,11 @@ static int sec_skcipher_crypto(struct skcipher_request *sk_req, bool encrypt) + req->c_req.encrypt = encrypt; + req->ctx = ctx; + +- ret = sec_skcipher_param_check(ctx, req); ++ ret = sec_skcipher_param_check(ctx, req, &need_fallback); + if (unlikely(ret)) + return -EINVAL; + +- if (unlikely(ctx->c_ctx.fallback)) ++ if (unlikely(ctx->c_ctx.fallback || need_fallback)) + return sec_skcipher_soft_crypto(ctx, sk_req, encrypt); + + return ctx->req_op->process(ctx, req); +@@ -2227,52 +2219,35 @@ static int sec_aead_spec_check(struct sec_ctx *ctx, struct sec_req *sreq) + struct crypto_aead *tfm = crypto_aead_reqtfm(req); + size_t sz = crypto_aead_authsize(tfm); + u8 c_mode = ctx->c_ctx.c_mode; +- struct device *dev = ctx->dev; + int ret; + +- /* Hardware does not handle cases where authsize is not 4 bytes aligned */ +- if (c_mode == SEC_CMODE_CBC && (sz & WORD_MASK)) { +- sreq->aead_req.fallback = true; ++ if (unlikely(ctx->sec->qm.ver == QM_HW_V2 && !sreq->c_req.c_len)) + return -EINVAL; +- } + + if (unlikely(req->cryptlen + req->assoclen > MAX_INPUT_DATA_LEN || +- req->assoclen > SEC_MAX_AAD_LEN)) { +- dev_err(dev, "aead input spec error!\n"); ++ req->assoclen > SEC_MAX_AAD_LEN)) + return -EINVAL; +- } + + if (c_mode == SEC_CMODE_CCM) { +- if (unlikely(req->assoclen > SEC_MAX_CCM_AAD_LEN)) { +- dev_err_ratelimited(dev, "CCM input aad parameter is too long!\n"); ++ if (unlikely(req->assoclen > SEC_MAX_CCM_AAD_LEN)) + return -EINVAL; +- } +- ret = aead_iv_demension_check(req); +- if (ret) { +- dev_err(dev, "aead input iv param error!\n"); +- return ret; +- } +- } + +- if (sreq->c_req.encrypt) +- sreq->c_req.c_len = req->cryptlen; +- else +- sreq->c_req.c_len = req->cryptlen - sz; +- if (c_mode == SEC_CMODE_CBC) { +- if (unlikely(sreq->c_req.c_len & (AES_BLOCK_SIZE - 1))) { +- dev_err(dev, "aead crypto length error!\n"); ++ ret = aead_iv_demension_check(req); ++ if (unlikely(ret)) ++ return -EINVAL; ++ } else if (c_mode == SEC_CMODE_CBC) { ++ if (unlikely(sz & WORD_MASK)) ++ return -EINVAL; ++ if (unlikely(ctx->a_ctx.a_key_len & WORD_MASK)) + return -EINVAL; +- } + } + + return 0; + } + +-static int sec_aead_param_check(struct sec_ctx *ctx, struct sec_req *sreq) ++static int sec_aead_param_check(struct sec_ctx *ctx, struct sec_req *sreq, bool *need_fallback) + { + struct aead_request *req = sreq->aead_req.aead_req; +- struct crypto_aead *tfm = crypto_aead_reqtfm(req); +- size_t authsize = crypto_aead_authsize(tfm); + struct device *dev = ctx->dev; + u8 c_alg = ctx->c_ctx.c_alg; + +@@ -2281,12 +2256,10 @@ static int sec_aead_param_check(struct sec_ctx *ctx, struct sec_req *sreq) + return -EINVAL; + } + +- if (ctx->sec->qm.ver == QM_HW_V2) { +- if (unlikely(!req->cryptlen || (!sreq->c_req.encrypt && +- req->cryptlen <= authsize))) { +- sreq->aead_req.fallback = true; +- return -EINVAL; +- } ++ if (unlikely(ctx->c_ctx.c_mode == SEC_CMODE_CBC && ++ sreq->c_req.c_len & (AES_BLOCK_SIZE - 1))) { ++ dev_err(dev, "aead cbc mode input data length error!\n"); ++ return -EINVAL; + } + + /* Support AES or SM4 */ +@@ -2295,8 +2268,10 @@ static int sec_aead_param_check(struct sec_ctx *ctx, struct sec_req *sreq) + return -EINVAL; + } + +- if (unlikely(sec_aead_spec_check(ctx, sreq))) ++ if (unlikely(sec_aead_spec_check(ctx, sreq))) { ++ *need_fallback = true; + return -EINVAL; ++ } + + if (ctx->pbuf_supported && (req->cryptlen + req->assoclen) <= + SEC_PBUF_SZ) +@@ -2340,17 +2315,19 @@ static int sec_aead_crypto(struct aead_request *a_req, bool encrypt) + struct crypto_aead *tfm = crypto_aead_reqtfm(a_req); + struct sec_req *req = aead_request_ctx(a_req); + struct sec_ctx *ctx = crypto_aead_ctx(tfm); ++ size_t sz = crypto_aead_authsize(tfm); ++ bool need_fallback = false; + int ret; + + req->flag = a_req->base.flags; + req->aead_req.aead_req = a_req; + req->c_req.encrypt = encrypt; + req->ctx = ctx; +- req->aead_req.fallback = false; ++ req->c_req.c_len = a_req->cryptlen - (req->c_req.encrypt ? 0 : sz); + +- ret = sec_aead_param_check(ctx, req); ++ ret = sec_aead_param_check(ctx, req, &need_fallback); + if (unlikely(ret)) { +- if (req->aead_req.fallback) ++ if (need_fallback) + return sec_aead_soft_crypto(ctx, a_req, encrypt); + return -EINVAL; + } +-- +2.39.5 + diff --git a/queue-6.14/crypto-iaa-test-the-correct-request-flag.patch b/queue-6.14/crypto-iaa-test-the-correct-request-flag.patch new file mode 100644 index 0000000000..1d565ccd23 --- /dev/null +++ b/queue-6.14/crypto-iaa-test-the-correct-request-flag.patch @@ -0,0 +1,43 @@ +From 3ec2c95901527e6516c5fd45c7e652dd145e43e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 18:14:55 +0800 +Subject: crypto: iaa - Test the correct request flag + +From: Herbert Xu + +[ Upstream commit fc4bd01d9ff592f620c499686245c093440db0e8 ] + +Test the correct flags for the MAY_SLEEP bit. + +Fixes: 2ec6761df889 ("crypto: iaa - Add support for deflate-iaa compression algorithm") +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/intel/iaa/iaa_crypto_main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/crypto/intel/iaa/iaa_crypto_main.c b/drivers/crypto/intel/iaa/iaa_crypto_main.c +index c3776b0de51d7..990ea46955bbf 100644 +--- a/drivers/crypto/intel/iaa/iaa_crypto_main.c ++++ b/drivers/crypto/intel/iaa/iaa_crypto_main.c +@@ -1537,7 +1537,7 @@ static int iaa_comp_acompress(struct acomp_req *req) + iaa_wq = idxd_wq_get_private(wq); + + if (!req->dst) { +- gfp_t flags = req->flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC; ++ gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC; + + /* incompressible data will always be < 2 * slen */ + req->dlen = 2 * req->slen; +@@ -1619,7 +1619,7 @@ static int iaa_comp_acompress(struct acomp_req *req) + + static int iaa_comp_adecompress_alloc_dest(struct acomp_req *req) + { +- gfp_t flags = req->flags & CRYPTO_TFM_REQ_MAY_SLEEP ? ++ gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? + GFP_KERNEL : GFP_ATOMIC; + struct crypto_tfm *tfm = req->base.tfm; + dma_addr_t src_addr, dst_addr; +-- +2.39.5 + diff --git a/queue-6.14/crypto-nx-fix-uninitialised-hv_nxc-on-error.patch b/queue-6.14/crypto-nx-fix-uninitialised-hv_nxc-on-error.patch new file mode 100644 index 0000000000..3863e19a8e --- /dev/null +++ b/queue-6.14/crypto-nx-fix-uninitialised-hv_nxc-on-error.patch @@ -0,0 +1,95 @@ +From ebb4643ac31992713902d95c85ab00adbfd2158e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Mar 2025 16:50:42 +0800 +Subject: crypto: nx - Fix uninitialised hv_nxc on error + +From: Herbert Xu + +[ Upstream commit 9b00eb923f3e60ca76cbc8b31123716f3a87ac6a ] + +The compiler correctly warns that hv_nxc may be used uninitialised +as that will occur when NX-GZIP is unavailable. + +Fix it by rearranging the code and delay setting caps_feat until +the final query succeeds. + +Fixes: b4ba22114c78 ("crypto/nx: Get NX capabilities for GZIP coprocessor type") +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/nx/nx-common-pseries.c | 37 ++++++++++++--------------- + 1 file changed, 17 insertions(+), 20 deletions(-) + +diff --git a/drivers/crypto/nx/nx-common-pseries.c b/drivers/crypto/nx/nx-common-pseries.c +index 1660c5cf3641c..56129bdf53ab0 100644 +--- a/drivers/crypto/nx/nx-common-pseries.c ++++ b/drivers/crypto/nx/nx-common-pseries.c +@@ -1145,6 +1145,7 @@ static void __init nxcop_get_capabilities(void) + { + struct hv_vas_all_caps *hv_caps; + struct hv_nx_cop_caps *hv_nxc; ++ u64 feat; + int rc; + + hv_caps = kmalloc(sizeof(*hv_caps), GFP_KERNEL); +@@ -1155,27 +1156,26 @@ static void __init nxcop_get_capabilities(void) + */ + rc = h_query_vas_capabilities(H_QUERY_NX_CAPABILITIES, 0, + (u64)virt_to_phys(hv_caps)); ++ if (!rc) ++ feat = be64_to_cpu(hv_caps->feat_type); ++ kfree(hv_caps); + if (rc) +- goto out; ++ return; ++ if (!(feat & VAS_NX_GZIP_FEAT_BIT)) ++ return; + +- caps_feat = be64_to_cpu(hv_caps->feat_type); + /* + * NX-GZIP feature available + */ +- if (caps_feat & VAS_NX_GZIP_FEAT_BIT) { +- hv_nxc = kmalloc(sizeof(*hv_nxc), GFP_KERNEL); +- if (!hv_nxc) +- goto out; +- /* +- * Get capabilities for NX-GZIP feature +- */ +- rc = h_query_vas_capabilities(H_QUERY_NX_CAPABILITIES, +- VAS_NX_GZIP_FEAT, +- (u64)virt_to_phys(hv_nxc)); +- } else { +- pr_err("NX-GZIP feature is not available\n"); +- rc = -EINVAL; +- } ++ hv_nxc = kmalloc(sizeof(*hv_nxc), GFP_KERNEL); ++ if (!hv_nxc) ++ return; ++ /* ++ * Get capabilities for NX-GZIP feature ++ */ ++ rc = h_query_vas_capabilities(H_QUERY_NX_CAPABILITIES, ++ VAS_NX_GZIP_FEAT, ++ (u64)virt_to_phys(hv_nxc)); + + if (!rc) { + nx_cop_caps.descriptor = be64_to_cpu(hv_nxc->descriptor); +@@ -1185,13 +1185,10 @@ static void __init nxcop_get_capabilities(void) + be64_to_cpu(hv_nxc->min_compress_len); + nx_cop_caps.min_decompress_len = + be64_to_cpu(hv_nxc->min_decompress_len); +- } else { +- caps_feat = 0; ++ caps_feat = feat; + } + + kfree(hv_nxc); +-out: +- kfree(hv_caps); + } + + static const struct vio_device_id nx842_vio_driver_ids[] = { +-- +2.39.5 + diff --git a/queue-6.14/crypto-powerpc-mark-ghashp8-ppc.o-as-an-object_files.patch b/queue-6.14/crypto-powerpc-mark-ghashp8-ppc.o-as-an-object_files.patch new file mode 100644 index 0000000000..ef31659f76 --- /dev/null +++ b/queue-6.14/crypto-powerpc-mark-ghashp8-ppc.o-as-an-object_files.patch @@ -0,0 +1,87 @@ +From 7fd5f457356d2c0ec0768e0d6b0b304422d9a28c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 00:02:39 +0100 +Subject: crypto: powerpc: Mark ghashp8-ppc.o as an OBJECT_FILES_NON_STANDARD + +From: Christophe Leroy + +[ Upstream commit 1e4d73d06c98f5a1af4f7591cf7c2c4eee5b94fa ] + +The following build warning has been reported: + + arch/powerpc/crypto/ghashp8-ppc.o: warning: objtool: .text+0x22c: unannotated intra-function call + +This happens due to commit bb7f054f4de2 ("objtool/powerpc: Add support +for decoding all types of uncond branches") + +Disassembly of arch/powerpc/crypto/ghashp8-ppc.o shows: + + arch/powerpc/crypto/ghashp8-ppc.o: file format elf64-powerpcle + + Disassembly of section .text: + + 0000000000000140 : + 140: f8 ff 00 3c lis r0,-8 + ... + 20c: 20 00 80 4e blr + 210: 00 00 00 00 .long 0x0 + 214: 00 0c 14 00 .long 0x140c00 + 218: 00 00 04 00 .long 0x40000 + 21c: 00 00 00 00 .long 0x0 + 220: 47 48 41 53 rlwimi. r1,r26,9,1,3 + 224: 48 20 66 6f xoris r6,r27,8264 + 228: 72 20 50 6f xoris r16,r26,8306 + 22c: 77 65 72 49 bla 1726574 <== + ... + +It corresponds to the following code in ghashp8-ppc.o : + + _GLOBAL(gcm_ghash_p8) + lis 0,0xfff8 + ... + blr + .long 0 + .byte 0,12,0x14,0,0,0,4,0 + .long 0 + .size gcm_ghash_p8,.-gcm_ghash_p8 + + .byte 71,72,65,83,72,32,102,111,114,32,80,111,119,101,114,73,83,65,32,50,46,48,55,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 + .align 2 + .align 2 + +In fact this is raw data that is after the function end and that is +not text so shouldn't be disassembled as text. But ghashp8-ppc.S is +generated by a perl script and should have been marked as +OBJECT_FILES_NON_STANDARD. + +Now that 'bla' is understood as a call instruction, that raw data +is mis-interpreted as an infra-function call. + +Mark ghashp8-ppc.o as a OBJECT_FILES_NON_STANDARD to avoid this +warning. + +Reported-by: Venkat Rao Bagalkote +Closes: https://lore.kernel.org/all/8c4c3fc2-2bd7-4148-af68-2f504d6119e0@linux.ibm.com +Fixes: 109303336a0c ("crypto: vmx - Move to arch/powerpc/crypto") +Signed-off-by: Christophe Leroy +Tested-By: Venkat Rao Bagalkote +Reviewed-by: Sathvika Vasireddy +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/7aa7eb73fe6bc95ac210510e22394ca0ae227b69.1741128786.git.christophe.leroy@csgroup.eu +Signed-off-by: Sasha Levin +--- + arch/powerpc/crypto/Makefile | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/powerpc/crypto/Makefile b/arch/powerpc/crypto/Makefile +index 9b38f4a7bc152..2f00b22b0823e 100644 +--- a/arch/powerpc/crypto/Makefile ++++ b/arch/powerpc/crypto/Makefile +@@ -51,3 +51,4 @@ $(obj)/aesp8-ppc.S $(obj)/ghashp8-ppc.S: $(obj)/%.S: $(src)/%.pl FORCE + OBJECT_FILES_NON_STANDARD_aesp10-ppc.o := y + OBJECT_FILES_NON_STANDARD_ghashp10-ppc.o := y + OBJECT_FILES_NON_STANDARD_aesp8-ppc.o := y ++OBJECT_FILES_NON_STANDARD_ghashp8-ppc.o := y +-- +2.39.5 + diff --git a/queue-6.14/crypto-qat-remove-access-to-parity-register-for-qat-.patch b/queue-6.14/crypto-qat-remove-access-to-parity-register-for-qat-.patch new file mode 100644 index 0000000000..6e6c48322e --- /dev/null +++ b/queue-6.14/crypto-qat-remove-access-to-parity-register-for-qat-.patch @@ -0,0 +1,114 @@ +From 53fee94d27913b65a7218cf32ed17eb90beb9965 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 15:09:31 +0000 +Subject: crypto: qat - remove access to parity register for QAT GEN4 + +From: Bairavi Alagappan + +[ Upstream commit 92c6a707d82f0629debf1c21dd87717776d96af2 ] + +The firmware already handles parity errors reported by the accelerators +by clearing them through the corresponding SSMSOFTERRORPARITY register. +To ensure consistent behavior and prevent race conditions between the +driver and firmware, remove the logic that checks the SSMSOFTERRORPARITY +registers. + +Additionally, change the return type of the function +adf_handle_rf_parr_err() to void, as it consistently returns false. +Parity errors are recoverable and do not necessitate a device reset. + +Fixes: 895f7d532c84 ("crypto: qat - add handling of errors from ERRSOU2 for QAT GEN4") +Signed-off-by: Bairavi Alagappan +Reviewed-by: Andy Shevchenko +Signed-off-by: Giovanni Cabiddu +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + .../intel/qat/qat_common/adf_gen4_ras.c | 57 ++----------------- + 1 file changed, 5 insertions(+), 52 deletions(-) + +diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_ras.c b/drivers/crypto/intel/qat/qat_common/adf_gen4_ras.c +index bf0ea09faa650..0f7f00a19e7dc 100644 +--- a/drivers/crypto/intel/qat/qat_common/adf_gen4_ras.c ++++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_ras.c +@@ -1043,63 +1043,16 @@ static bool adf_handle_ssmcpppar_err(struct adf_accel_dev *accel_dev, + return reset_required; + } + +-static bool adf_handle_rf_parr_err(struct adf_accel_dev *accel_dev, ++static void adf_handle_rf_parr_err(struct adf_accel_dev *accel_dev, + void __iomem *csr, u32 iastatssm) + { +- struct adf_dev_err_mask *err_mask = GET_ERR_MASK(accel_dev); +- u32 reg; +- + if (!(iastatssm & ADF_GEN4_IAINTSTATSSM_SSMSOFTERRORPARITY_BIT)) +- return false; +- +- reg = ADF_CSR_RD(csr, ADF_GEN4_SSMSOFTERRORPARITY_SRC); +- reg &= ADF_GEN4_SSMSOFTERRORPARITY_SRC_BIT; +- if (reg) { +- ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR); +- ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITY_SRC, reg); +- } +- +- reg = ADF_CSR_RD(csr, ADF_GEN4_SSMSOFTERRORPARITY_ATH_CPH); +- reg &= err_mask->parerr_ath_cph_mask; +- if (reg) { +- ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR); +- ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITY_ATH_CPH, reg); +- } +- +- reg = ADF_CSR_RD(csr, ADF_GEN4_SSMSOFTERRORPARITY_CPR_XLT); +- reg &= err_mask->parerr_cpr_xlt_mask; +- if (reg) { +- ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR); +- ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITY_CPR_XLT, reg); +- } +- +- reg = ADF_CSR_RD(csr, ADF_GEN4_SSMSOFTERRORPARITY_DCPR_UCS); +- reg &= err_mask->parerr_dcpr_ucs_mask; +- if (reg) { +- ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR); +- ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITY_DCPR_UCS, reg); +- } +- +- reg = ADF_CSR_RD(csr, ADF_GEN4_SSMSOFTERRORPARITY_PKE); +- reg &= err_mask->parerr_pke_mask; +- if (reg) { +- ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR); +- ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITY_PKE, reg); +- } +- +- if (err_mask->parerr_wat_wcp_mask) { +- reg = ADF_CSR_RD(csr, ADF_GEN4_SSMSOFTERRORPARITY_WAT_WCP); +- reg &= err_mask->parerr_wat_wcp_mask; +- if (reg) { +- ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR); +- ADF_CSR_WR(csr, ADF_GEN4_SSMSOFTERRORPARITY_WAT_WCP, +- reg); +- } +- } ++ return; + ++ ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR); + dev_err(&GET_DEV(accel_dev), "Slice ssm soft parity error reported"); + +- return false; ++ return; + } + + static bool adf_handle_ser_err_ssmsh(struct adf_accel_dev *accel_dev, +@@ -1171,8 +1124,8 @@ static bool adf_handle_iaintstatssm(struct adf_accel_dev *accel_dev, + reset_required |= adf_handle_slice_hang_error(accel_dev, csr, iastatssm); + reset_required |= adf_handle_spppar_err(accel_dev, csr, iastatssm); + reset_required |= adf_handle_ssmcpppar_err(accel_dev, csr, iastatssm); +- reset_required |= adf_handle_rf_parr_err(accel_dev, csr, iastatssm); + reset_required |= adf_handle_ser_err_ssmsh(accel_dev, csr, iastatssm); ++ adf_handle_rf_parr_err(accel_dev, csr, iastatssm); + + ADF_CSR_WR(csr, ADF_GEN4_IAINTSTATSSM, iastatssm); + +-- +2.39.5 + diff --git a/queue-6.14/crypto-qat-set-parity-error-mask-for-qat_420xx.patch b/queue-6.14/crypto-qat-set-parity-error-mask-for-qat_420xx.patch new file mode 100644 index 0000000000..9cdb73462a --- /dev/null +++ b/queue-6.14/crypto-qat-set-parity-error-mask-for-qat_420xx.patch @@ -0,0 +1,58 @@ +From e659a3953457d51e3a9284eab1700a85d996020f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 13:14:29 +0000 +Subject: crypto: qat - set parity error mask for qat_420xx + +From: Bairavi Alagappan + +[ Upstream commit f9555d18084985c80a91baa4fdb7d205b401a754 ] + +The field parerr_wat_wcp_mask in the structure adf_dev_err_mask enables +the detection and reporting of parity errors for the wireless cipher and +wireless authentication accelerators. + +Set the parerr_wat_wcp_mask field, which was inadvertently omitted +during the initial enablement of the qat_420xx driver, to ensure that +parity errors are enabled for those accelerators. + +In addition, fix the string used to report such errors that was +inadvertently set to "ath_cph" (authentication and cipher). + +Fixes: fcf60f4bcf54 ("crypto: qat - add support for 420xx devices") +Signed-off-by: Bairavi Alagappan +Signed-off-by: Giovanni Cabiddu +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c | 1 + + drivers/crypto/intel/qat/qat_common/adf_gen4_ras.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c b/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c +index 9faef33e54bd3..a17adc4beda2e 100644 +--- a/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c ++++ b/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c +@@ -420,6 +420,7 @@ static void adf_gen4_set_err_mask(struct adf_dev_err_mask *dev_err_mask) + dev_err_mask->parerr_cpr_xlt_mask = ADF_420XX_PARITYERRORMASK_CPR_XLT_MASK; + dev_err_mask->parerr_dcpr_ucs_mask = ADF_420XX_PARITYERRORMASK_DCPR_UCS_MASK; + dev_err_mask->parerr_pke_mask = ADF_420XX_PARITYERRORMASK_PKE_MASK; ++ dev_err_mask->parerr_wat_wcp_mask = ADF_420XX_PARITYERRORMASK_WAT_WCP_MASK; + dev_err_mask->ssmfeatren_mask = ADF_420XX_SSMFEATREN_MASK; + } + +diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_ras.c b/drivers/crypto/intel/qat/qat_common/adf_gen4_ras.c +index 2dd3772bf58a6..bf0ea09faa650 100644 +--- a/drivers/crypto/intel/qat/qat_common/adf_gen4_ras.c ++++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_ras.c +@@ -695,7 +695,7 @@ static bool adf_handle_slice_hang_error(struct adf_accel_dev *accel_dev, + if (err_mask->parerr_wat_wcp_mask) + adf_poll_slicehang_csr(accel_dev, csr, + ADF_GEN4_SLICEHANGSTATUS_WAT_WCP, +- "ath_cph"); ++ "wat_wcp"); + + return false; + } +-- +2.39.5 + diff --git a/queue-6.14/crypto-tegra-check-return-value-for-hash-do_one_req.patch b/queue-6.14/crypto-tegra-check-return-value-for-hash-do_one_req.patch new file mode 100644 index 0000000000..fbedc25b91 --- /dev/null +++ b/queue-6.14/crypto-tegra-check-return-value-for-hash-do_one_req.patch @@ -0,0 +1,86 @@ +From 476c7d7d0cd2824a5333896895849b0ae1780382 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 14:46:04 +0530 +Subject: crypto: tegra - check return value for hash do_one_req + +From: Akhil R + +[ Upstream commit dcf8b7e49b86738296c77fb58c123dd2d74a22a7 ] + +Initialize and check the return value in hash *do_one_req() functions +and exit the function if there is an error. This fixes the +'uninitialized variable' warnings reported by testbots. + +Reported-by: kernel test robot +Reported-by: Dan Carpenter +Closes: https://lore.kernel.org/r/202412071747.flPux4oB-lkp@intel.com/ +Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver") +Signed-off-by: Akhil R +Signed-off-by: Herbert Xu +Stable-dep-of: ff4b7df0b511 ("crypto: tegra - Fix HASH intermediate result handling") +Signed-off-by: Sasha Levin +--- + drivers/crypto/tegra/tegra-se-aes.c | 10 ++++++++-- + drivers/crypto/tegra/tegra-se-hash.c | 7 +++++++ + 2 files changed, 15 insertions(+), 2 deletions(-) + +diff --git a/drivers/crypto/tegra/tegra-se-aes.c b/drivers/crypto/tegra/tegra-se-aes.c +index c2b8891a905dc..dd147fa4af977 100644 +--- a/drivers/crypto/tegra/tegra-se-aes.c ++++ b/drivers/crypto/tegra/tegra-se-aes.c +@@ -1596,18 +1596,24 @@ static int tegra_cmac_do_one_req(struct crypto_engine *engine, void *areq) + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm); + struct tegra_se *se = ctx->se; +- int ret; ++ int ret = 0; + + if (rctx->task & SHA_UPDATE) { + ret = tegra_cmac_do_update(req); ++ if (ret) ++ goto out; ++ + rctx->task &= ~SHA_UPDATE; + } + + if (rctx->task & SHA_FINAL) { + ret = tegra_cmac_do_final(req); ++ if (ret) ++ goto out; ++ + rctx->task &= ~SHA_FINAL; + } +- ++out: + crypto_finalize_hash_request(se->engine, req, ret); + + return 0; +diff --git a/drivers/crypto/tegra/tegra-se-hash.c b/drivers/crypto/tegra/tegra-se-hash.c +index b4a179a8febd5..0ae5ce67bdd04 100644 +--- a/drivers/crypto/tegra/tegra-se-hash.c ++++ b/drivers/crypto/tegra/tegra-se-hash.c +@@ -437,14 +437,21 @@ static int tegra_sha_do_one_req(struct crypto_engine *engine, void *areq) + + if (rctx->task & SHA_UPDATE) { + ret = tegra_sha_do_update(req); ++ if (ret) ++ goto out; ++ + rctx->task &= ~SHA_UPDATE; + } + + if (rctx->task & SHA_FINAL) { + ret = tegra_sha_do_final(req); ++ if (ret) ++ goto out; ++ + rctx->task &= ~SHA_FINAL; + } + ++out: + crypto_finalize_hash_request(se->engine, req, ret); + + return 0; +-- +2.39.5 + diff --git a/queue-6.14/crypto-tegra-do-not-use-fixed-size-buffers.patch b/queue-6.14/crypto-tegra-do-not-use-fixed-size-buffers.patch new file mode 100644 index 0000000000..7977c361a2 --- /dev/null +++ b/queue-6.14/crypto-tegra-do-not-use-fixed-size-buffers.patch @@ -0,0 +1,381 @@ +From 5cecfa0a288e98e728a65ca85ba7ae63c4f8a2a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 14:46:02 +0530 +Subject: crypto: tegra - Do not use fixed size buffers + +From: Akhil R + +[ Upstream commit 1cb328da4e8f34350c61a2b6548766c79b4bb64c ] + +Allocate the buffer based on the request instead of a fixed buffer +length. In operations which may require larger buffer size, a fixed +buffer may fail. + +Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver") +Signed-off-by: Akhil R +Signed-off-by: Herbert Xu +Stable-dep-of: ff4b7df0b511 ("crypto: tegra - Fix HASH intermediate result handling") +Signed-off-by: Sasha Levin +--- + drivers/crypto/tegra/tegra-se-aes.c | 124 ++++++++++++++------------- + drivers/crypto/tegra/tegra-se-hash.c | 38 +++++--- + drivers/crypto/tegra/tegra-se.h | 2 - + 3 files changed, 89 insertions(+), 75 deletions(-) + +diff --git a/drivers/crypto/tegra/tegra-se-aes.c b/drivers/crypto/tegra/tegra-se-aes.c +index 7da7e169a314b..c2b8891a905dc 100644 +--- a/drivers/crypto/tegra/tegra-se-aes.c ++++ b/drivers/crypto/tegra/tegra-se-aes.c +@@ -263,12 +263,6 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq) + unsigned int cmdlen; + int ret; + +- rctx->datbuf.buf = dma_alloc_coherent(se->dev, SE_AES_BUFLEN, +- &rctx->datbuf.addr, GFP_KERNEL); +- if (!rctx->datbuf.buf) +- return -ENOMEM; +- +- rctx->datbuf.size = SE_AES_BUFLEN; + rctx->iv = (u32 *)req->iv; + rctx->len = req->cryptlen; + +@@ -278,6 +272,12 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq) + rctx->len += AES_BLOCK_SIZE - (rctx->len % AES_BLOCK_SIZE); + } + ++ rctx->datbuf.size = rctx->len; ++ rctx->datbuf.buf = dma_alloc_coherent(se->dev, rctx->datbuf.size, ++ &rctx->datbuf.addr, GFP_KERNEL); ++ if (!rctx->datbuf.buf) ++ return -ENOMEM; ++ + scatterwalk_map_and_copy(rctx->datbuf.buf, req->src, 0, req->cryptlen, 0); + + /* Prepare the command and submit for execution */ +@@ -289,7 +289,7 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq) + scatterwalk_map_and_copy(rctx->datbuf.buf, req->dst, 0, req->cryptlen, 1); + + /* Free the buffer */ +- dma_free_coherent(ctx->se->dev, SE_AES_BUFLEN, ++ dma_free_coherent(ctx->se->dev, rctx->datbuf.size, + rctx->datbuf.buf, rctx->datbuf.addr); + + crypto_finalize_skcipher_request(se->engine, req, ret); +@@ -1117,6 +1117,11 @@ static int tegra_ccm_crypt_init(struct aead_request *req, struct tegra_se *se, + rctx->assoclen = req->assoclen; + rctx->authsize = crypto_aead_authsize(tfm); + ++ if (rctx->encrypt) ++ rctx->cryptlen = req->cryptlen; ++ else ++ rctx->cryptlen = req->cryptlen - rctx->authsize; ++ + memcpy(iv, req->iv, 16); + + ret = tegra_ccm_check_iv(iv); +@@ -1145,30 +1150,26 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq) + struct tegra_se *se = ctx->se; + int ret; + ++ ret = tegra_ccm_crypt_init(req, se, rctx); ++ if (ret) ++ return ret; ++ + /* Allocate buffers required */ +- rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, SE_AES_BUFLEN, ++ rctx->inbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen + 100; ++ rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->inbuf.size, + &rctx->inbuf.addr, GFP_KERNEL); + if (!rctx->inbuf.buf) + return -ENOMEM; + +- rctx->inbuf.size = SE_AES_BUFLEN; +- +- rctx->outbuf.buf = dma_alloc_coherent(ctx->se->dev, SE_AES_BUFLEN, ++ rctx->outbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen + 100; ++ rctx->outbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->outbuf.size, + &rctx->outbuf.addr, GFP_KERNEL); + if (!rctx->outbuf.buf) { + ret = -ENOMEM; + goto outbuf_err; + } + +- rctx->outbuf.size = SE_AES_BUFLEN; +- +- ret = tegra_ccm_crypt_init(req, se, rctx); +- if (ret) +- goto out; +- + if (rctx->encrypt) { +- rctx->cryptlen = req->cryptlen; +- + /* CBC MAC Operation */ + ret = tegra_ccm_compute_auth(ctx, rctx); + if (ret) +@@ -1179,8 +1180,6 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq) + if (ret) + goto out; + } else { +- rctx->cryptlen = req->cryptlen - ctx->authsize; +- + /* CTR operation */ + ret = tegra_ccm_do_ctr(ctx, rctx); + if (ret) +@@ -1193,11 +1192,11 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq) + } + + out: +- dma_free_coherent(ctx->se->dev, SE_AES_BUFLEN, ++ dma_free_coherent(ctx->se->dev, rctx->inbuf.size, + rctx->outbuf.buf, rctx->outbuf.addr); + + outbuf_err: +- dma_free_coherent(ctx->se->dev, SE_AES_BUFLEN, ++ dma_free_coherent(ctx->se->dev, rctx->outbuf.size, + rctx->inbuf.buf, rctx->inbuf.addr); + + crypto_finalize_aead_request(ctx->se->engine, req, ret); +@@ -1213,23 +1212,6 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq) + struct tegra_aead_reqctx *rctx = aead_request_ctx(req); + int ret; + +- /* Allocate buffers required */ +- rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, SE_AES_BUFLEN, +- &rctx->inbuf.addr, GFP_KERNEL); +- if (!rctx->inbuf.buf) +- return -ENOMEM; +- +- rctx->inbuf.size = SE_AES_BUFLEN; +- +- rctx->outbuf.buf = dma_alloc_coherent(ctx->se->dev, SE_AES_BUFLEN, +- &rctx->outbuf.addr, GFP_KERNEL); +- if (!rctx->outbuf.buf) { +- ret = -ENOMEM; +- goto outbuf_err; +- } +- +- rctx->outbuf.size = SE_AES_BUFLEN; +- + rctx->src_sg = req->src; + rctx->dst_sg = req->dst; + rctx->assoclen = req->assoclen; +@@ -1243,6 +1225,21 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq) + memcpy(rctx->iv, req->iv, GCM_AES_IV_SIZE); + rctx->iv[3] = (1 << 24); + ++ /* Allocate buffers required */ ++ rctx->inbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen; ++ rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->inbuf.size, ++ &rctx->inbuf.addr, GFP_KERNEL); ++ if (!rctx->inbuf.buf) ++ return -ENOMEM; ++ ++ rctx->outbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen; ++ rctx->outbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->outbuf.size, ++ &rctx->outbuf.addr, GFP_KERNEL); ++ if (!rctx->outbuf.buf) { ++ ret = -ENOMEM; ++ goto outbuf_err; ++ } ++ + /* If there is associated data perform GMAC operation */ + if (rctx->assoclen) { + ret = tegra_gcm_do_gmac(ctx, rctx); +@@ -1266,11 +1263,11 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq) + ret = tegra_gcm_do_verify(ctx->se, rctx); + + out: +- dma_free_coherent(ctx->se->dev, SE_AES_BUFLEN, ++ dma_free_coherent(ctx->se->dev, rctx->outbuf.size, + rctx->outbuf.buf, rctx->outbuf.addr); + + outbuf_err: +- dma_free_coherent(ctx->se->dev, SE_AES_BUFLEN, ++ dma_free_coherent(ctx->se->dev, rctx->inbuf.size, + rctx->inbuf.buf, rctx->inbuf.addr); + + /* Finalize the request if there are no errors */ +@@ -1497,6 +1494,11 @@ static int tegra_cmac_do_update(struct ahash_request *req) + return 0; + } + ++ rctx->datbuf.buf = dma_alloc_coherent(se->dev, rctx->datbuf.size, ++ &rctx->datbuf.addr, GFP_KERNEL); ++ if (!rctx->datbuf.buf) ++ return -ENOMEM; ++ + /* Copy the previous residue first */ + if (rctx->residue.size) + memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size); +@@ -1529,6 +1531,9 @@ static int tegra_cmac_do_update(struct ahash_request *req) + if (!(rctx->task & SHA_FINAL)) + tegra_cmac_copy_result(ctx->se, rctx); + ++ dma_free_coherent(ctx->se->dev, rctx->datbuf.size, ++ rctx->datbuf.buf, rctx->datbuf.addr); ++ + return ret; + } + +@@ -1543,10 +1548,20 @@ static int tegra_cmac_do_final(struct ahash_request *req) + + if (!req->nbytes && !rctx->total_len && ctx->fallback_tfm) { + return crypto_shash_tfm_digest(ctx->fallback_tfm, +- rctx->datbuf.buf, 0, req->result); ++ NULL, 0, req->result); ++ } ++ ++ if (rctx->residue.size) { ++ rctx->datbuf.buf = dma_alloc_coherent(se->dev, rctx->residue.size, ++ &rctx->datbuf.addr, GFP_KERNEL); ++ if (!rctx->datbuf.buf) { ++ ret = -ENOMEM; ++ goto out_free; ++ } ++ ++ memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size); + } + +- memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size); + rctx->datbuf.size = rctx->residue.size; + rctx->total_len += rctx->residue.size; + rctx->config = tegra234_aes_cfg(SE_ALG_CMAC, 0); +@@ -1565,8 +1580,10 @@ static int tegra_cmac_do_final(struct ahash_request *req) + writel(0, se->base + se->hw->regs->result + (i * 4)); + + out: +- dma_free_coherent(se->dev, SE_SHA_BUFLEN, +- rctx->datbuf.buf, rctx->datbuf.addr); ++ if (rctx->residue.size) ++ dma_free_coherent(se->dev, rctx->datbuf.size, ++ rctx->datbuf.buf, rctx->datbuf.addr); ++out_free: + dma_free_coherent(se->dev, crypto_ahash_blocksize(tfm) * 2, + rctx->residue.buf, rctx->residue.addr); + return ret; +@@ -1672,28 +1689,15 @@ static int tegra_cmac_init(struct ahash_request *req) + rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size * 2, + &rctx->residue.addr, GFP_KERNEL); + if (!rctx->residue.buf) +- goto resbuf_fail; ++ return -ENOMEM; + + rctx->residue.size = 0; + +- rctx->datbuf.buf = dma_alloc_coherent(se->dev, SE_SHA_BUFLEN, +- &rctx->datbuf.addr, GFP_KERNEL); +- if (!rctx->datbuf.buf) +- goto datbuf_fail; +- +- rctx->datbuf.size = 0; +- + /* Clear any previous result */ + for (i = 0; i < CMAC_RESULT_REG_COUNT; i++) + writel(0, se->base + se->hw->regs->result + (i * 4)); + + return 0; +- +-datbuf_fail: +- dma_free_coherent(se->dev, rctx->blk_size, rctx->residue.buf, +- rctx->residue.addr); +-resbuf_fail: +- return -ENOMEM; + } + + static int tegra_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, +diff --git a/drivers/crypto/tegra/tegra-se-hash.c b/drivers/crypto/tegra/tegra-se-hash.c +index c7b2a062a03c0..b4a179a8febd5 100644 +--- a/drivers/crypto/tegra/tegra-se-hash.c ++++ b/drivers/crypto/tegra/tegra-se-hash.c +@@ -332,6 +332,11 @@ static int tegra_sha_do_update(struct ahash_request *req) + return 0; + } + ++ rctx->datbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->datbuf.size, ++ &rctx->datbuf.addr, GFP_KERNEL); ++ if (!rctx->datbuf.buf) ++ return -ENOMEM; ++ + /* Copy the previous residue first */ + if (rctx->residue.size) + memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size); +@@ -368,6 +373,9 @@ static int tegra_sha_do_update(struct ahash_request *req) + if (!(rctx->task & SHA_FINAL)) + tegra_sha_copy_hash_result(se, rctx); + ++ dma_free_coherent(ctx->se->dev, rctx->datbuf.size, ++ rctx->datbuf.buf, rctx->datbuf.addr); ++ + return ret; + } + +@@ -380,7 +388,17 @@ static int tegra_sha_do_final(struct ahash_request *req) + u32 *cpuvaddr = se->cmdbuf->addr; + int size, ret = 0; + +- memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size); ++ if (rctx->residue.size) { ++ rctx->datbuf.buf = dma_alloc_coherent(se->dev, rctx->residue.size, ++ &rctx->datbuf.addr, GFP_KERNEL); ++ if (!rctx->datbuf.buf) { ++ ret = -ENOMEM; ++ goto out_free; ++ } ++ ++ memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size); ++ } ++ + rctx->datbuf.size = rctx->residue.size; + rctx->total_len += rctx->residue.size; + +@@ -397,8 +415,10 @@ static int tegra_sha_do_final(struct ahash_request *req) + memcpy(req->result, rctx->digest.buf, rctx->digest.size); + + out: +- dma_free_coherent(se->dev, SE_SHA_BUFLEN, +- rctx->datbuf.buf, rctx->datbuf.addr); ++ if (rctx->residue.size) ++ dma_free_coherent(se->dev, rctx->datbuf.size, ++ rctx->datbuf.buf, rctx->datbuf.addr); ++out_free: + dma_free_coherent(se->dev, crypto_ahash_blocksize(tfm), + rctx->residue.buf, rctx->residue.addr); + dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf, +@@ -527,19 +547,11 @@ static int tegra_sha_init(struct ahash_request *req) + if (!rctx->residue.buf) + goto resbuf_fail; + +- rctx->datbuf.buf = dma_alloc_coherent(se->dev, SE_SHA_BUFLEN, +- &rctx->datbuf.addr, GFP_KERNEL); +- if (!rctx->datbuf.buf) +- goto datbuf_fail; +- + return 0; + +-datbuf_fail: +- dma_free_coherent(se->dev, rctx->blk_size, rctx->residue.buf, +- rctx->residue.addr); + resbuf_fail: +- dma_free_coherent(se->dev, SE_SHA_BUFLEN, rctx->datbuf.buf, +- rctx->datbuf.addr); ++ dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf, ++ rctx->digest.addr); + digbuf_fail: + return -ENOMEM; + } +diff --git a/drivers/crypto/tegra/tegra-se.h b/drivers/crypto/tegra/tegra-se.h +index b54aefe717a17..e196a90eedb92 100644 +--- a/drivers/crypto/tegra/tegra-se.h ++++ b/drivers/crypto/tegra/tegra-se.h +@@ -340,8 +340,6 @@ + #define SE_CRYPTO_CTR_REG_COUNT 4 + #define SE_MAX_KEYSLOT 15 + #define SE_MAX_MEM_ALLOC SZ_4M +-#define SE_AES_BUFLEN 0x8000 +-#define SE_SHA_BUFLEN 0x2000 + + #define SHA_FIRST BIT(0) + #define SHA_UPDATE BIT(1) +-- +2.39.5 + diff --git a/queue-6.14/crypto-tegra-finalize-crypto-req-on-error.patch b/queue-6.14/crypto-tegra-finalize-crypto-req-on-error.patch new file mode 100644 index 0000000000..7001bae24c --- /dev/null +++ b/queue-6.14/crypto-tegra-finalize-crypto-req-on-error.patch @@ -0,0 +1,123 @@ +From d7ebfd477052da78ae34c3c219f017989c30473b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 14:46:03 +0530 +Subject: crypto: tegra - finalize crypto req on error + +From: Akhil R + +[ Upstream commit 1e245948ca0c252f561792fabb45de5518301d97 ] + +Call the crypto finalize function before exiting *do_one_req() functions. +This allows the driver to take up further requests even if the previous +one fails. + +Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver") +Signed-off-by: Akhil R +Signed-off-by: Herbert Xu +Stable-dep-of: b157e7a228ae ("crypto: tegra - Reserve keyslots to allocate dynamically") +Signed-off-by: Sasha Levin +--- + drivers/crypto/tegra/tegra-se-aes.c | 28 +++++++++++++++++----------- + 1 file changed, 17 insertions(+), 11 deletions(-) + +diff --git a/drivers/crypto/tegra/tegra-se-aes.c b/drivers/crypto/tegra/tegra-se-aes.c +index be0a0b51f5a59..a1b469c3a55ba 100644 +--- a/drivers/crypto/tegra/tegra-se-aes.c ++++ b/drivers/crypto/tegra/tegra-se-aes.c +@@ -275,8 +275,10 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq) + rctx->datbuf.size = rctx->len; + rctx->datbuf.buf = dma_alloc_coherent(se->dev, rctx->datbuf.size, + &rctx->datbuf.addr, GFP_KERNEL); +- if (!rctx->datbuf.buf) +- return -ENOMEM; ++ if (!rctx->datbuf.buf) { ++ ret = -ENOMEM; ++ goto out_finalize; ++ } + + scatterwalk_map_and_copy(rctx->datbuf.buf, req->src, 0, req->cryptlen, 0); + +@@ -292,6 +294,7 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq) + dma_free_coherent(ctx->se->dev, rctx->datbuf.size, + rctx->datbuf.buf, rctx->datbuf.addr); + ++out_finalize: + crypto_finalize_skcipher_request(se->engine, req, ret); + + return 0; +@@ -1155,21 +1158,21 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq) + + ret = tegra_ccm_crypt_init(req, se, rctx); + if (ret) +- return ret; ++ goto out_finalize; + + /* Allocate buffers required */ + rctx->inbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen + 100; + rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->inbuf.size, + &rctx->inbuf.addr, GFP_KERNEL); + if (!rctx->inbuf.buf) +- return -ENOMEM; ++ goto out_finalize; + + rctx->outbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen + 100; + rctx->outbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->outbuf.size, + &rctx->outbuf.addr, GFP_KERNEL); + if (!rctx->outbuf.buf) { + ret = -ENOMEM; +- goto outbuf_err; ++ goto out_free_inbuf; + } + + if (rctx->encrypt) { +@@ -1198,10 +1201,11 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq) + dma_free_coherent(ctx->se->dev, rctx->inbuf.size, + rctx->outbuf.buf, rctx->outbuf.addr); + +-outbuf_err: ++out_free_inbuf: + dma_free_coherent(ctx->se->dev, rctx->outbuf.size, + rctx->inbuf.buf, rctx->inbuf.addr); + ++out_finalize: + crypto_finalize_aead_request(ctx->se->engine, req, ret); + + return 0; +@@ -1232,15 +1236,17 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq) + rctx->inbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen; + rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->inbuf.size, + &rctx->inbuf.addr, GFP_KERNEL); +- if (!rctx->inbuf.buf) +- return -ENOMEM; ++ if (!rctx->inbuf.buf) { ++ ret = -ENOMEM; ++ goto out_finalize; ++ } + + rctx->outbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen; + rctx->outbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->outbuf.size, + &rctx->outbuf.addr, GFP_KERNEL); + if (!rctx->outbuf.buf) { + ret = -ENOMEM; +- goto outbuf_err; ++ goto out_free_inbuf; + } + + /* If there is associated data perform GMAC operation */ +@@ -1269,11 +1275,11 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq) + dma_free_coherent(ctx->se->dev, rctx->outbuf.size, + rctx->outbuf.buf, rctx->outbuf.addr); + +-outbuf_err: ++out_free_inbuf: + dma_free_coherent(ctx->se->dev, rctx->inbuf.size, + rctx->inbuf.buf, rctx->inbuf.addr); + +- /* Finalize the request if there are no errors */ ++out_finalize: + crypto_finalize_aead_request(ctx->se->engine, req, ret); + + return 0; +-- +2.39.5 + diff --git a/queue-6.14/crypto-tegra-fix-cmac-intermediate-result-handling.patch b/queue-6.14/crypto-tegra-fix-cmac-intermediate-result-handling.patch new file mode 100644 index 0000000000..c6eb8ea9ad --- /dev/null +++ b/queue-6.14/crypto-tegra-fix-cmac-intermediate-result-handling.patch @@ -0,0 +1,69 @@ +From d426a8bd3381089443564cc7056113b3367c3660 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 14:46:07 +0530 +Subject: crypto: tegra - Fix CMAC intermediate result handling + +From: Akhil R + +[ Upstream commit ce390d6c2675d2e24d798169a1a0e3cdbc076907 ] + +Saving and restoring of the intermediate results are needed if there is +context switch caused by another ongoing request on the same engine. +This is therefore not only to support import/export functionality. +Hence, save and restore the intermediate result for every non-first task. + +Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver") +Signed-off-by: Akhil R +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/tegra/tegra-se-aes.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/drivers/crypto/tegra/tegra-se-aes.c b/drivers/crypto/tegra/tegra-se-aes.c +index 5d8237cda58f0..cdcf05e235cad 100644 +--- a/drivers/crypto/tegra/tegra-se-aes.c ++++ b/drivers/crypto/tegra/tegra-se-aes.c +@@ -1541,9 +1541,8 @@ static int tegra_cmac_do_update(struct ahash_request *req) + rctx->residue.size = nresidue; + + /* +- * If this is not the first 'update' call, paste the previous copied ++ * If this is not the first task, paste the previous copied + * intermediate results to the registers so that it gets picked up. +- * This is to support the import/export functionality. + */ + if (!(rctx->task & SHA_FIRST)) + tegra_cmac_paste_result(ctx->se, rctx); +@@ -1551,13 +1550,7 @@ static int tegra_cmac_do_update(struct ahash_request *req) + cmdlen = tegra_cmac_prep_cmd(ctx, rctx); + ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen); + +- /* +- * If this is not the final update, copy the intermediate results +- * from the registers so that it can be used in the next 'update' +- * call. This is to support the import/export functionality. +- */ +- if (!(rctx->task & SHA_FINAL)) +- tegra_cmac_copy_result(ctx->se, rctx); ++ tegra_cmac_copy_result(ctx->se, rctx); + + dma_free_coherent(ctx->se->dev, rctx->datbuf.size, + rctx->datbuf.buf, rctx->datbuf.addr); +@@ -1594,6 +1587,13 @@ static int tegra_cmac_do_final(struct ahash_request *req) + rctx->total_len += rctx->residue.size; + rctx->config = tegra234_aes_cfg(SE_ALG_CMAC, 0); + ++ /* ++ * If this is not the first task, paste the previous copied ++ * intermediate results to the registers so that it gets picked up. ++ */ ++ if (!(rctx->task & SHA_FIRST)) ++ tegra_cmac_paste_result(ctx->se, rctx); ++ + /* Prepare command and submit */ + cmdlen = tegra_cmac_prep_cmd(ctx, rctx); + ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen); +-- +2.39.5 + diff --git a/queue-6.14/crypto-tegra-fix-format-specifier-in-tegra_sha_prep_.patch b/queue-6.14/crypto-tegra-fix-format-specifier-in-tegra_sha_prep_.patch new file mode 100644 index 0000000000..4e5d6d7ea8 --- /dev/null +++ b/queue-6.14/crypto-tegra-fix-format-specifier-in-tegra_sha_prep_.patch @@ -0,0 +1,55 @@ +From 4b6262ff26cff07d5ceeb2b9754f48b29c75cd3c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 16:29:31 +0100 +Subject: crypto: tegra - Fix format specifier in tegra_sha_prep_cmd() + +From: Nathan Chancellor + +[ Upstream commit 795e5bdb0ada2c77ea28611d88f1d5d7ca9b2f4d ] + +When building for 32-bit targets, for which ssize_t is 'int' instead of +'long', there is a warning due to an incorrect format specifier: + + In file included from include/linux/printk.h:610, + from include/linux/kernel.h:31, + from include/linux/clk.h:13, + from drivers/crypto/tegra/tegra-se-hash.c:7: + drivers/crypto/tegra/tegra-se-hash.c: In function 'tegra_sha_prep_cmd': + drivers/crypto/tegra/tegra-se-hash.c:343:26: error: format '%lu' expects argument of type 'long unsigned int', but argument 6 has type 'ssize_t' {aka 'int'} [-Werror=format=] + 343 | dev_dbg(se->dev, "msg len %llu msg left %llu sz %lu cfg %#x", + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ... + drivers/crypto/tegra/tegra-se-hash.c:343:59: note: format string is defined here + 343 | dev_dbg(se->dev, "msg len %llu msg left %llu sz %lu cfg %#x", + | ~~^ + | | + | long unsigned int + | %u + cc1: all warnings being treated as errors + +Use '%zd', the proper specifier for ssize_t, to resolve the warning. + +Fixes: ff4b7df0b511 ("crypto: tegra - Fix HASH intermediate result handling") +Signed-off-by: Nathan Chancellor +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/tegra/tegra-se-hash.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/crypto/tegra/tegra-se-hash.c b/drivers/crypto/tegra/tegra-se-hash.c +index 65a50f29bd7e6..42d007b7af45d 100644 +--- a/drivers/crypto/tegra/tegra-se-hash.c ++++ b/drivers/crypto/tegra/tegra-se-hash.c +@@ -340,7 +340,7 @@ static int tegra_sha_prep_cmd(struct tegra_sha_ctx *ctx, u32 *cpuvaddr, + cpuvaddr[i++] = host1x_uclass_incr_syncpt_cond_f(1) | + host1x_uclass_incr_syncpt_indx_f(se->syncpt_id); + +- dev_dbg(se->dev, "msg len %llu msg left %llu sz %lu cfg %#x", ++ dev_dbg(se->dev, "msg len %llu msg left %llu sz %zd cfg %#x", + msg_len, msg_left, rctx->datbuf.size, rctx->config); + + return i; +-- +2.39.5 + diff --git a/queue-6.14/crypto-tegra-fix-hash-intermediate-result-handling.patch b/queue-6.14/crypto-tegra-fix-hash-intermediate-result-handling.patch new file mode 100644 index 0000000000..06aefe35e8 --- /dev/null +++ b/queue-6.14/crypto-tegra-fix-hash-intermediate-result-handling.patch @@ -0,0 +1,303 @@ +From 29612f8b942862360a362ff1856ddb521bc74772 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 14:46:06 +0530 +Subject: crypto: tegra - Fix HASH intermediate result handling + +From: Akhil R + +[ Upstream commit ff4b7df0b511b6121f3386607f02c16fb5d41192 ] + +The intermediate hash values generated during an update task were +handled incorrectly in the driver. The values have a defined format for +each algorithm. Copying and pasting from the HASH_RESULT register +balantly would not work for all the supported algorithms. This incorrect +handling causes failures when there is a context switch between multiple +operations. + +To handle the expected format correctly, add a separate buffer for +storing the intermediate results for each request. Remove the previous +copy/paste functions which read/wrote to the registers directly. Instead +configure the hardware to get the intermediate result copied to the +buffer and use host1x path to restore the intermediate hash results. + +Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver") +Signed-off-by: Akhil R +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/tegra/tegra-se-hash.c | 149 +++++++++++++++++---------- + drivers/crypto/tegra/tegra-se.h | 1 + + 2 files changed, 98 insertions(+), 52 deletions(-) + +diff --git a/drivers/crypto/tegra/tegra-se-hash.c b/drivers/crypto/tegra/tegra-se-hash.c +index 07e4c7320ec8d..8bed13552ab9e 100644 +--- a/drivers/crypto/tegra/tegra-se-hash.c ++++ b/drivers/crypto/tegra/tegra-se-hash.c +@@ -34,6 +34,7 @@ struct tegra_sha_reqctx { + struct tegra_se_datbuf datbuf; + struct tegra_se_datbuf residue; + struct tegra_se_datbuf digest; ++ struct tegra_se_datbuf intr_res; + unsigned int alg; + unsigned int config; + unsigned int total_len; +@@ -211,9 +212,62 @@ static int tegra_sha_fallback_export(struct ahash_request *req, void *out) + return crypto_ahash_export(&rctx->fallback_req, out); + } + +-static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr, ++static int tegra_se_insert_hash_result(struct tegra_sha_ctx *ctx, u32 *cpuvaddr, ++ struct tegra_sha_reqctx *rctx) ++{ ++ __be32 *res_be = (__be32 *)rctx->intr_res.buf; ++ u32 *res = (u32 *)rctx->intr_res.buf; ++ int i = 0, j; ++ ++ cpuvaddr[i++] = 0; ++ cpuvaddr[i++] = host1x_opcode_setpayload(HASH_RESULT_REG_COUNT); ++ cpuvaddr[i++] = se_host1x_opcode_incr_w(SE_SHA_HASH_RESULT); ++ ++ for (j = 0; j < HASH_RESULT_REG_COUNT; j++) { ++ int idx = j; ++ ++ /* ++ * The initial, intermediate and final hash value of SHA-384, SHA-512 ++ * in SHA_HASH_RESULT registers follow the below layout of bytes. ++ * ++ * +---------------+------------+ ++ * | HASH_RESULT_0 | B4...B7 | ++ * +---------------+------------+ ++ * | HASH_RESULT_1 | B0...B3 | ++ * +---------------+------------+ ++ * | HASH_RESULT_2 | B12...B15 | ++ * +---------------+------------+ ++ * | HASH_RESULT_3 | B8...B11 | ++ * +---------------+------------+ ++ * | ...... | ++ * +---------------+------------+ ++ * | HASH_RESULT_14| B60...B63 | ++ * +---------------+------------+ ++ * | HASH_RESULT_15| B56...B59 | ++ * +---------------+------------+ ++ * ++ */ ++ if (ctx->alg == SE_ALG_SHA384 || ctx->alg == SE_ALG_SHA512) ++ idx = (j % 2) ? j - 1 : j + 1; ++ ++ /* For SHA-1, SHA-224, SHA-256, SHA-384, SHA-512 the initial ++ * intermediate and final hash value when stored in ++ * SHA_HASH_RESULT registers, the byte order is NOT in ++ * little-endian. ++ */ ++ if (ctx->alg <= SE_ALG_SHA512) ++ cpuvaddr[i++] = be32_to_cpu(res_be[idx]); ++ else ++ cpuvaddr[i++] = res[idx]; ++ } ++ ++ return i; ++} ++ ++static int tegra_sha_prep_cmd(struct tegra_sha_ctx *ctx, u32 *cpuvaddr, + struct tegra_sha_reqctx *rctx) + { ++ struct tegra_se *se = ctx->se; + u64 msg_len, msg_left; + int i = 0; + +@@ -241,7 +295,7 @@ static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr, + cpuvaddr[i++] = upper_32_bits(msg_left); + cpuvaddr[i++] = 0; + cpuvaddr[i++] = 0; +- cpuvaddr[i++] = host1x_opcode_setpayload(6); ++ cpuvaddr[i++] = host1x_opcode_setpayload(2); + cpuvaddr[i++] = se_host1x_opcode_incr_w(SE_SHA_CFG); + cpuvaddr[i++] = rctx->config; + +@@ -249,15 +303,29 @@ static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr, + cpuvaddr[i++] = SE_SHA_TASK_HASH_INIT; + rctx->task &= ~SHA_FIRST; + } else { +- cpuvaddr[i++] = 0; ++ /* ++ * If it isn't the first task, program the HASH_RESULT register ++ * with the intermediate result from the previous task ++ */ ++ i += tegra_se_insert_hash_result(ctx, cpuvaddr + i, rctx); + } + ++ cpuvaddr[i++] = host1x_opcode_setpayload(4); ++ cpuvaddr[i++] = se_host1x_opcode_incr_w(SE_SHA_IN_ADDR); + cpuvaddr[i++] = rctx->datbuf.addr; + cpuvaddr[i++] = (u32)(SE_ADDR_HI_MSB(upper_32_bits(rctx->datbuf.addr)) | + SE_ADDR_HI_SZ(rctx->datbuf.size)); +- cpuvaddr[i++] = rctx->digest.addr; +- cpuvaddr[i++] = (u32)(SE_ADDR_HI_MSB(upper_32_bits(rctx->digest.addr)) | +- SE_ADDR_HI_SZ(rctx->digest.size)); ++ ++ if (rctx->task & SHA_UPDATE) { ++ cpuvaddr[i++] = rctx->intr_res.addr; ++ cpuvaddr[i++] = (u32)(SE_ADDR_HI_MSB(upper_32_bits(rctx->intr_res.addr)) | ++ SE_ADDR_HI_SZ(rctx->intr_res.size)); ++ } else { ++ cpuvaddr[i++] = rctx->digest.addr; ++ cpuvaddr[i++] = (u32)(SE_ADDR_HI_MSB(upper_32_bits(rctx->digest.addr)) | ++ SE_ADDR_HI_SZ(rctx->digest.size)); ++ } ++ + if (rctx->key_id) { + cpuvaddr[i++] = host1x_opcode_setpayload(1); + cpuvaddr[i++] = se_host1x_opcode_nonincr_w(SE_SHA_CRYPTO_CFG); +@@ -266,36 +334,18 @@ static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr, + + cpuvaddr[i++] = host1x_opcode_setpayload(1); + cpuvaddr[i++] = se_host1x_opcode_nonincr_w(SE_SHA_OPERATION); +- cpuvaddr[i++] = SE_SHA_OP_WRSTALL | +- SE_SHA_OP_START | ++ cpuvaddr[i++] = SE_SHA_OP_WRSTALL | SE_SHA_OP_START | + SE_SHA_OP_LASTBUF; + cpuvaddr[i++] = se_host1x_opcode_nonincr(host1x_uclass_incr_syncpt_r(), 1); + cpuvaddr[i++] = host1x_uclass_incr_syncpt_cond_f(1) | + host1x_uclass_incr_syncpt_indx_f(se->syncpt_id); + +- dev_dbg(se->dev, "msg len %llu msg left %llu cfg %#x", +- msg_len, msg_left, rctx->config); ++ dev_dbg(se->dev, "msg len %llu msg left %llu sz %lu cfg %#x", ++ msg_len, msg_left, rctx->datbuf.size, rctx->config); + + return i; + } + +-static void tegra_sha_copy_hash_result(struct tegra_se *se, struct tegra_sha_reqctx *rctx) +-{ +- int i; +- +- for (i = 0; i < HASH_RESULT_REG_COUNT; i++) +- rctx->result[i] = readl(se->base + se->hw->regs->result + (i * 4)); +-} +- +-static void tegra_sha_paste_hash_result(struct tegra_se *se, struct tegra_sha_reqctx *rctx) +-{ +- int i; +- +- for (i = 0; i < HASH_RESULT_REG_COUNT; i++) +- writel(rctx->result[i], +- se->base + se->hw->regs->result + (i * 4)); +-} +- + static int tegra_sha_do_init(struct ahash_request *req) + { + struct tegra_sha_reqctx *rctx = ahash_request_ctx(req); +@@ -325,8 +375,17 @@ static int tegra_sha_do_init(struct ahash_request *req) + if (!rctx->residue.buf) + goto resbuf_fail; + ++ rctx->intr_res.size = HASH_RESULT_REG_COUNT * 4; ++ rctx->intr_res.buf = dma_alloc_coherent(se->dev, rctx->intr_res.size, ++ &rctx->intr_res.addr, GFP_KERNEL); ++ if (!rctx->intr_res.buf) ++ goto intr_res_fail; ++ + return 0; + ++intr_res_fail: ++ dma_free_coherent(se->dev, rctx->residue.size, rctx->residue.buf, ++ rctx->residue.addr); + resbuf_fail: + dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf, + rctx->digest.addr); +@@ -356,7 +415,6 @@ static int tegra_sha_do_update(struct ahash_request *req) + + rctx->src_sg = req->src; + rctx->datbuf.size = (req->nbytes + rctx->residue.size) - nresidue; +- rctx->total_len += rctx->datbuf.size; + + /* + * If nbytes are less than a block size, copy it residue and +@@ -365,12 +423,12 @@ static int tegra_sha_do_update(struct ahash_request *req) + if (nblks < 1) { + scatterwalk_map_and_copy(rctx->residue.buf + rctx->residue.size, + rctx->src_sg, 0, req->nbytes, 0); +- + rctx->residue.size += req->nbytes; ++ + return 0; + } + +- rctx->datbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->datbuf.size, ++ rctx->datbuf.buf = dma_alloc_coherent(se->dev, rctx->datbuf.size, + &rctx->datbuf.addr, GFP_KERNEL); + if (!rctx->datbuf.buf) + return -ENOMEM; +@@ -387,31 +445,15 @@ static int tegra_sha_do_update(struct ahash_request *req) + + /* Update residue value with the residue after current block */ + rctx->residue.size = nresidue; ++ rctx->total_len += rctx->datbuf.size; + + rctx->config = tegra_sha_get_config(rctx->alg) | +- SE_SHA_DST_HASH_REG; +- +- /* +- * If this is not the first 'update' call, paste the previous copied +- * intermediate results to the registers so that it gets picked up. +- * This is to support the import/export functionality. +- */ +- if (!(rctx->task & SHA_FIRST)) +- tegra_sha_paste_hash_result(se, rctx); +- +- size = tegra_sha_prep_cmd(se, cpuvaddr, rctx); ++ SE_SHA_DST_MEMORY; + ++ size = tegra_sha_prep_cmd(ctx, cpuvaddr, rctx); + ret = tegra_se_host1x_submit(se, se->cmdbuf, size); + +- /* +- * If this is not the final update, copy the intermediate results +- * from the registers so that it can be used in the next 'update' +- * call. This is to support the import/export functionality. +- */ +- if (!(rctx->task & SHA_FINAL)) +- tegra_sha_copy_hash_result(se, rctx); +- +- dma_free_coherent(ctx->se->dev, rctx->datbuf.size, ++ dma_free_coherent(se->dev, rctx->datbuf.size, + rctx->datbuf.buf, rctx->datbuf.addr); + + return ret; +@@ -443,8 +485,7 @@ static int tegra_sha_do_final(struct ahash_request *req) + rctx->config = tegra_sha_get_config(rctx->alg) | + SE_SHA_DST_MEMORY; + +- size = tegra_sha_prep_cmd(se, cpuvaddr, rctx); +- ++ size = tegra_sha_prep_cmd(ctx, cpuvaddr, rctx); + ret = tegra_se_host1x_submit(se, se->cmdbuf, size); + if (ret) + goto out; +@@ -461,6 +502,10 @@ static int tegra_sha_do_final(struct ahash_request *req) + rctx->residue.buf, rctx->residue.addr); + dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf, + rctx->digest.addr); ++ ++ dma_free_coherent(se->dev, rctx->intr_res.size, rctx->intr_res.buf, ++ rctx->intr_res.addr); ++ + return ret; + } + +diff --git a/drivers/crypto/tegra/tegra-se.h b/drivers/crypto/tegra/tegra-se.h +index e1ec37bfb80a8..0f5bcf27358bd 100644 +--- a/drivers/crypto/tegra/tegra-se.h ++++ b/drivers/crypto/tegra/tegra-se.h +@@ -24,6 +24,7 @@ + #define SE_STREAM_ID 0x90 + + #define SE_SHA_CFG 0x4004 ++#define SE_SHA_IN_ADDR 0x400c + #define SE_SHA_KEY_ADDR 0x4094 + #define SE_SHA_KEY_DATA 0x4098 + #define SE_SHA_KEYMANIFEST 0x409c +-- +2.39.5 + diff --git a/queue-6.14/crypto-tegra-reserve-keyslots-to-allocate-dynamicall.patch b/queue-6.14/crypto-tegra-reserve-keyslots-to-allocate-dynamicall.patch new file mode 100644 index 0000000000..805047d148 --- /dev/null +++ b/queue-6.14/crypto-tegra-reserve-keyslots-to-allocate-dynamicall.patch @@ -0,0 +1,499 @@ +From fdc1292745f6360fbea6dfb4c1321a35ac93dad6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 14:46:09 +0530 +Subject: crypto: tegra - Reserve keyslots to allocate dynamically + +From: Akhil R + +[ Upstream commit b157e7a228aee9b48c2de05129476b822aa7956d ] + +The HW supports only storing 15 keys at a time. This limits the number +of tfms that can work without failutes. Reserve keyslots to solve this +and use the reserved ones during the encryption/decryption operation. +This allow users to have the capability of hardware protected keys +and faster operations if there are limited number of tfms while not +halting the operation if there are more tfms. + +Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver") +Signed-off-by: Akhil R +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/tegra/tegra-se-aes.c | 139 +++++++++++++++++++++++----- + drivers/crypto/tegra/tegra-se-key.c | 19 +++- + drivers/crypto/tegra/tegra-se.h | 28 ++++++ + 3 files changed, 164 insertions(+), 22 deletions(-) + +diff --git a/drivers/crypto/tegra/tegra-se-aes.c b/drivers/crypto/tegra/tegra-se-aes.c +index a1b469c3a55ba..ca9d0cca1f748 100644 +--- a/drivers/crypto/tegra/tegra-se-aes.c ++++ b/drivers/crypto/tegra/tegra-se-aes.c +@@ -28,6 +28,9 @@ struct tegra_aes_ctx { + u32 ivsize; + u32 key1_id; + u32 key2_id; ++ u32 keylen; ++ u8 key1[AES_MAX_KEY_SIZE]; ++ u8 key2[AES_MAX_KEY_SIZE]; + }; + + struct tegra_aes_reqctx { +@@ -43,8 +46,9 @@ struct tegra_aead_ctx { + struct tegra_se *se; + unsigned int authsize; + u32 alg; +- u32 keylen; + u32 key_id; ++ u32 keylen; ++ u8 key[AES_MAX_KEY_SIZE]; + }; + + struct tegra_aead_reqctx { +@@ -56,8 +60,8 @@ struct tegra_aead_reqctx { + unsigned int cryptlen; + unsigned int authsize; + bool encrypt; +- u32 config; + u32 crypto_config; ++ u32 config; + u32 key_id; + u32 iv[4]; + u8 authdata[16]; +@@ -67,6 +71,8 @@ struct tegra_cmac_ctx { + struct tegra_se *se; + unsigned int alg; + u32 key_id; ++ u32 keylen; ++ u8 key[AES_MAX_KEY_SIZE]; + struct crypto_shash *fallback_tfm; + }; + +@@ -260,11 +266,13 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq) + struct tegra_aes_ctx *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req)); + struct tegra_aes_reqctx *rctx = skcipher_request_ctx(req); + struct tegra_se *se = ctx->se; +- unsigned int cmdlen; ++ unsigned int cmdlen, key1_id, key2_id; + int ret; + + rctx->iv = (u32 *)req->iv; + rctx->len = req->cryptlen; ++ key1_id = ctx->key1_id; ++ key2_id = ctx->key2_id; + + /* Pad input to AES Block size */ + if (ctx->alg != SE_ALG_XTS) { +@@ -282,6 +290,29 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq) + + scatterwalk_map_and_copy(rctx->datbuf.buf, req->src, 0, req->cryptlen, 0); + ++ rctx->config = tegra234_aes_cfg(ctx->alg, rctx->encrypt); ++ rctx->crypto_config = tegra234_aes_crypto_cfg(ctx->alg, rctx->encrypt); ++ ++ if (!key1_id) { ++ ret = tegra_key_submit_reserved_aes(ctx->se, ctx->key1, ++ ctx->keylen, ctx->alg, &key1_id); ++ if (ret) ++ goto out; ++ } ++ ++ rctx->crypto_config |= SE_AES_KEY_INDEX(key1_id); ++ ++ if (ctx->alg == SE_ALG_XTS) { ++ if (!key2_id) { ++ ret = tegra_key_submit_reserved_xts(ctx->se, ctx->key2, ++ ctx->keylen, ctx->alg, &key2_id); ++ if (ret) ++ goto out; ++ } ++ ++ rctx->crypto_config |= SE_AES_KEY2_INDEX(key2_id); ++ } ++ + /* Prepare the command and submit for execution */ + cmdlen = tegra_aes_prep_cmd(ctx, rctx); + ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen); +@@ -290,10 +321,17 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq) + tegra_aes_update_iv(req, ctx); + scatterwalk_map_and_copy(rctx->datbuf.buf, req->dst, 0, req->cryptlen, 1); + ++out: + /* Free the buffer */ + dma_free_coherent(ctx->se->dev, rctx->datbuf.size, + rctx->datbuf.buf, rctx->datbuf.addr); + ++ if (tegra_key_is_reserved(key1_id)) ++ tegra_key_invalidate_reserved(ctx->se, key1_id, ctx->alg); ++ ++ if (tegra_key_is_reserved(key2_id)) ++ tegra_key_invalidate_reserved(ctx->se, key2_id, ctx->alg); ++ + out_finalize: + crypto_finalize_skcipher_request(se->engine, req, ret); + +@@ -316,6 +354,7 @@ static int tegra_aes_cra_init(struct crypto_skcipher *tfm) + ctx->se = se_alg->se_dev; + ctx->key1_id = 0; + ctx->key2_id = 0; ++ ctx->keylen = 0; + + algname = crypto_tfm_alg_name(&tfm->base); + ret = se_algname_to_algid(algname); +@@ -344,13 +383,20 @@ static int tegra_aes_setkey(struct crypto_skcipher *tfm, + const u8 *key, u32 keylen) + { + struct tegra_aes_ctx *ctx = crypto_skcipher_ctx(tfm); ++ int ret; + + if (aes_check_keylen(keylen)) { + dev_dbg(ctx->se->dev, "invalid key length (%d)\n", keylen); + return -EINVAL; + } + +- return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key1_id); ++ ret = tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key1_id); ++ if (ret) { ++ ctx->keylen = keylen; ++ memcpy(ctx->key1, key, keylen); ++ } ++ ++ return 0; + } + + static int tegra_xts_setkey(struct crypto_skcipher *tfm, +@@ -368,11 +414,17 @@ static int tegra_xts_setkey(struct crypto_skcipher *tfm, + + ret = tegra_key_submit(ctx->se, key, len, + ctx->alg, &ctx->key1_id); +- if (ret) +- return ret; ++ if (ret) { ++ ctx->keylen = len; ++ memcpy(ctx->key1, key, len); ++ } + +- return tegra_key_submit(ctx->se, key + len, len, ++ ret = tegra_key_submit(ctx->se, key + len, len, + ctx->alg, &ctx->key2_id); ++ if (ret) { ++ ctx->keylen = len; ++ memcpy(ctx->key2, key + len, len); ++ } + + return 0; + } +@@ -450,12 +502,6 @@ static int tegra_aes_crypt(struct skcipher_request *req, bool encrypt) + req->iv = NULL; + + rctx->encrypt = encrypt; +- rctx->config = tegra234_aes_cfg(ctx->alg, encrypt); +- rctx->crypto_config = tegra234_aes_crypto_cfg(ctx->alg, encrypt); +- rctx->crypto_config |= SE_AES_KEY_INDEX(ctx->key1_id); +- +- if (ctx->key2_id) +- rctx->crypto_config |= SE_AES_KEY2_INDEX(ctx->key2_id); + + return crypto_transfer_skcipher_request_to_engine(ctx->se->engine, req); + } +@@ -721,7 +767,7 @@ static int tegra_gcm_do_gmac(struct tegra_aead_ctx *ctx, struct tegra_aead_reqct + + rctx->config = tegra234_aes_cfg(SE_ALG_GMAC, rctx->encrypt); + rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_GMAC, rctx->encrypt) | +- SE_AES_KEY_INDEX(ctx->key_id); ++ SE_AES_KEY_INDEX(rctx->key_id); + + cmdlen = tegra_gmac_prep_cmd(ctx, rctx); + +@@ -738,7 +784,7 @@ static int tegra_gcm_do_crypt(struct tegra_aead_ctx *ctx, struct tegra_aead_reqc + + rctx->config = tegra234_aes_cfg(SE_ALG_GCM, rctx->encrypt); + rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_GCM, rctx->encrypt) | +- SE_AES_KEY_INDEX(ctx->key_id); ++ SE_AES_KEY_INDEX(rctx->key_id); + + /* Prepare command and submit */ + cmdlen = tegra_gcm_crypt_prep_cmd(ctx, rctx); +@@ -761,7 +807,7 @@ static int tegra_gcm_do_final(struct tegra_aead_ctx *ctx, struct tegra_aead_reqc + + rctx->config = tegra234_aes_cfg(SE_ALG_GCM_FINAL, rctx->encrypt); + rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_GCM_FINAL, rctx->encrypt) | +- SE_AES_KEY_INDEX(ctx->key_id); ++ SE_AES_KEY_INDEX(rctx->key_id); + + /* Prepare command and submit */ + cmdlen = tegra_gcm_prep_final_cmd(se, cpuvaddr, rctx); +@@ -892,7 +938,7 @@ static int tegra_ccm_do_cbcmac(struct tegra_aead_ctx *ctx, struct tegra_aead_req + rctx->config = tegra234_aes_cfg(SE_ALG_CBC_MAC, rctx->encrypt); + rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_CBC_MAC, + rctx->encrypt) | +- SE_AES_KEY_INDEX(ctx->key_id); ++ SE_AES_KEY_INDEX(rctx->key_id); + + /* Prepare command and submit */ + cmdlen = tegra_cbcmac_prep_cmd(ctx, rctx); +@@ -1079,7 +1125,7 @@ static int tegra_ccm_do_ctr(struct tegra_aead_ctx *ctx, struct tegra_aead_reqctx + + rctx->config = tegra234_aes_cfg(SE_ALG_CTR, rctx->encrypt); + rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_CTR, rctx->encrypt) | +- SE_AES_KEY_INDEX(ctx->key_id); ++ SE_AES_KEY_INDEX(rctx->key_id); + + /* Copy authdata in the top of buffer for encryption/decryption */ + if (rctx->encrypt) +@@ -1160,6 +1206,8 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq) + if (ret) + goto out_finalize; + ++ rctx->key_id = ctx->key_id; ++ + /* Allocate buffers required */ + rctx->inbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen + 100; + rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->inbuf.size, +@@ -1175,6 +1223,13 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq) + goto out_free_inbuf; + } + ++ if (!ctx->key_id) { ++ ret = tegra_key_submit_reserved_aes(ctx->se, ctx->key, ++ ctx->keylen, ctx->alg, &rctx->key_id); ++ if (ret) ++ goto out; ++ } ++ + if (rctx->encrypt) { + /* CBC MAC Operation */ + ret = tegra_ccm_compute_auth(ctx, rctx); +@@ -1205,6 +1260,9 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq) + dma_free_coherent(ctx->se->dev, rctx->outbuf.size, + rctx->inbuf.buf, rctx->inbuf.addr); + ++ if (tegra_key_is_reserved(rctx->key_id)) ++ tegra_key_invalidate_reserved(ctx->se, rctx->key_id, ctx->alg); ++ + out_finalize: + crypto_finalize_aead_request(ctx->se->engine, req, ret); + +@@ -1232,6 +1290,8 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq) + memcpy(rctx->iv, req->iv, GCM_AES_IV_SIZE); + rctx->iv[3] = (1 << 24); + ++ rctx->key_id = ctx->key_id; ++ + /* Allocate buffers required */ + rctx->inbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen; + rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->inbuf.size, +@@ -1249,6 +1309,13 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq) + goto out_free_inbuf; + } + ++ if (!ctx->key_id) { ++ ret = tegra_key_submit_reserved_aes(ctx->se, ctx->key, ++ ctx->keylen, ctx->alg, &rctx->key_id); ++ if (ret) ++ goto out; ++ } ++ + /* If there is associated data perform GMAC operation */ + if (rctx->assoclen) { + ret = tegra_gcm_do_gmac(ctx, rctx); +@@ -1279,6 +1346,9 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq) + dma_free_coherent(ctx->se->dev, rctx->inbuf.size, + rctx->inbuf.buf, rctx->inbuf.addr); + ++ if (tegra_key_is_reserved(rctx->key_id)) ++ tegra_key_invalidate_reserved(ctx->se, rctx->key_id, ctx->alg); ++ + out_finalize: + crypto_finalize_aead_request(ctx->se->engine, req, ret); + +@@ -1301,6 +1371,7 @@ static int tegra_aead_cra_init(struct crypto_aead *tfm) + + ctx->se = se_alg->se_dev; + ctx->key_id = 0; ++ ctx->keylen = 0; + + ret = se_algname_to_algid(algname); + if (ret < 0) { +@@ -1382,13 +1453,20 @@ static int tegra_aead_setkey(struct crypto_aead *tfm, + const u8 *key, u32 keylen) + { + struct tegra_aead_ctx *ctx = crypto_aead_ctx(tfm); ++ int ret; + + if (aes_check_keylen(keylen)) { + dev_dbg(ctx->se->dev, "invalid key length (%d)\n", keylen); + return -EINVAL; + } + +- return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id); ++ ret = tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id); ++ if (ret) { ++ ctx->keylen = keylen; ++ memcpy(ctx->key, key, keylen); ++ } ++ ++ return 0; + } + + static unsigned int tegra_cmac_prep_cmd(struct tegra_cmac_ctx *ctx, +@@ -1473,6 +1551,7 @@ static int tegra_cmac_do_init(struct ahash_request *req) + rctx->total_len = 0; + rctx->datbuf.size = 0; + rctx->residue.size = 0; ++ rctx->key_id = ctx->key_id; + rctx->task |= SHA_FIRST; + rctx->blk_size = crypto_ahash_blocksize(tfm); + +@@ -1517,7 +1596,7 @@ static int tegra_cmac_do_update(struct ahash_request *req) + rctx->datbuf.size = (req->nbytes + rctx->residue.size) - nresidue; + rctx->total_len += rctx->datbuf.size; + rctx->config = tegra234_aes_cfg(SE_ALG_CMAC, 0); +- rctx->crypto_config = SE_AES_KEY_INDEX(ctx->key_id); ++ rctx->crypto_config = SE_AES_KEY_INDEX(rctx->key_id); + + /* + * Keep one block and residue bytes in residue and +@@ -1643,6 +1722,13 @@ static int tegra_cmac_do_one_req(struct crypto_engine *engine, void *areq) + rctx->task &= ~SHA_INIT; + } + ++ if (!ctx->key_id) { ++ ret = tegra_key_submit_reserved_aes(ctx->se, ctx->key, ++ ctx->keylen, ctx->alg, &rctx->key_id); ++ if (ret) ++ goto out; ++ } ++ + if (rctx->task & SHA_UPDATE) { + ret = tegra_cmac_do_update(req); + if (ret) +@@ -1659,6 +1745,9 @@ static int tegra_cmac_do_one_req(struct crypto_engine *engine, void *areq) + rctx->task &= ~SHA_FINAL; + } + out: ++ if (tegra_key_is_reserved(rctx->key_id)) ++ tegra_key_invalidate_reserved(ctx->se, rctx->key_id, ctx->alg); ++ + crypto_finalize_hash_request(se->engine, req, ret); + + return 0; +@@ -1699,6 +1788,7 @@ static int tegra_cmac_cra_init(struct crypto_tfm *tfm) + + ctx->se = se_alg->se_dev; + ctx->key_id = 0; ++ ctx->keylen = 0; + + ret = se_algname_to_algid(algname); + if (ret < 0) { +@@ -1727,6 +1817,7 @@ static int tegra_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, + unsigned int keylen) + { + struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm); ++ int ret; + + if (aes_check_keylen(keylen)) { + dev_dbg(ctx->se->dev, "invalid key length (%d)\n", keylen); +@@ -1736,7 +1827,13 @@ static int tegra_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, + if (ctx->fallback_tfm) + crypto_shash_setkey(ctx->fallback_tfm, key, keylen); + +- return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id); ++ ret = tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id); ++ if (ret) { ++ ctx->keylen = keylen; ++ memcpy(ctx->key, key, keylen); ++ } ++ ++ return 0; + } + + static int tegra_cmac_init(struct ahash_request *req) +diff --git a/drivers/crypto/tegra/tegra-se-key.c b/drivers/crypto/tegra/tegra-se-key.c +index 276b261fb6df1..956fa9b4e9b1a 100644 +--- a/drivers/crypto/tegra/tegra-se-key.c ++++ b/drivers/crypto/tegra/tegra-se-key.c +@@ -141,6 +141,23 @@ void tegra_key_invalidate(struct tegra_se *se, u32 keyid, u32 alg) + tegra_keyslot_free(keyid); + } + ++void tegra_key_invalidate_reserved(struct tegra_se *se, u32 keyid, u32 alg) ++{ ++ u8 zkey[AES_MAX_KEY_SIZE] = {0}; ++ ++ if (!keyid) ++ return; ++ ++ /* Overwrite the key with 0s */ ++ tegra_key_insert(se, zkey, AES_MAX_KEY_SIZE, keyid, alg); ++} ++ ++inline int tegra_key_submit_reserved(struct tegra_se *se, const u8 *key, ++ u32 keylen, u32 alg, u32 *keyid) ++{ ++ return tegra_key_insert(se, key, keylen, *keyid, alg); ++} ++ + int tegra_key_submit(struct tegra_se *se, const u8 *key, u32 keylen, u32 alg, u32 *keyid) + { + int ret; +@@ -149,7 +166,7 @@ int tegra_key_submit(struct tegra_se *se, const u8 *key, u32 keylen, u32 alg, u3 + if (!tegra_key_in_kslt(*keyid)) { + *keyid = tegra_keyslot_alloc(); + if (!(*keyid)) { +- dev_err(se->dev, "failed to allocate key slot\n"); ++ dev_dbg(se->dev, "failed to allocate key slot\n"); + return -ENOMEM; + } + } +diff --git a/drivers/crypto/tegra/tegra-se.h b/drivers/crypto/tegra/tegra-se.h +index 0f5bcf27358bd..b6cac9384f666 100644 +--- a/drivers/crypto/tegra/tegra-se.h ++++ b/drivers/crypto/tegra/tegra-se.h +@@ -342,6 +342,9 @@ + #define SE_MAX_KEYSLOT 15 + #define SE_MAX_MEM_ALLOC SZ_4M + ++#define TEGRA_AES_RESERVED_KSLT 14 ++#define TEGRA_XTS_RESERVED_KSLT 15 ++ + #define SHA_FIRST BIT(0) + #define SHA_INIT BIT(1) + #define SHA_UPDATE BIT(2) +@@ -502,9 +505,34 @@ void tegra_deinit_aes(struct tegra_se *se); + void tegra_deinit_hash(struct tegra_se *se); + int tegra_key_submit(struct tegra_se *se, const u8 *key, + u32 keylen, u32 alg, u32 *keyid); ++ ++int tegra_key_submit_reserved(struct tegra_se *se, const u8 *key, ++ u32 keylen, u32 alg, u32 *keyid); ++ + void tegra_key_invalidate(struct tegra_se *se, u32 keyid, u32 alg); ++void tegra_key_invalidate_reserved(struct tegra_se *se, u32 keyid, u32 alg); + int tegra_se_host1x_submit(struct tegra_se *se, struct tegra_se_cmdbuf *cmdbuf, u32 size); + ++static inline int tegra_key_submit_reserved_aes(struct tegra_se *se, const u8 *key, ++ u32 keylen, u32 alg, u32 *keyid) ++{ ++ *keyid = TEGRA_AES_RESERVED_KSLT; ++ return tegra_key_submit_reserved(se, key, keylen, alg, keyid); ++} ++ ++static inline int tegra_key_submit_reserved_xts(struct tegra_se *se, const u8 *key, ++ u32 keylen, u32 alg, u32 *keyid) ++{ ++ *keyid = TEGRA_XTS_RESERVED_KSLT; ++ return tegra_key_submit_reserved(se, key, keylen, alg, keyid); ++} ++ ++static inline bool tegra_key_is_reserved(u32 keyid) ++{ ++ return ((keyid == TEGRA_AES_RESERVED_KSLT) || ++ (keyid == TEGRA_XTS_RESERVED_KSLT)); ++} ++ + /* HOST1x OPCODES */ + static inline u32 host1x_opcode_setpayload(unsigned int payload) + { +-- +2.39.5 + diff --git a/queue-6.14/crypto-tegra-set-iv-to-null-explicitly-for-aes-ecb.patch b/queue-6.14/crypto-tegra-set-iv-to-null-explicitly-for-aes-ecb.patch new file mode 100644 index 0000000000..6d95683e9a --- /dev/null +++ b/queue-6.14/crypto-tegra-set-iv-to-null-explicitly-for-aes-ecb.patch @@ -0,0 +1,40 @@ +From 0536036485a5ad970b82e16aae85b97ac3513b70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 14:46:08 +0530 +Subject: crypto: tegra - Set IV to NULL explicitly for AES ECB + +From: Akhil R + +[ Upstream commit bde558220866e74f19450e16d9a2472b488dfedf ] + +It may happen that the variable req->iv may have stale values or +zero sized buffer by default and may end up getting used during +encryption/decryption. This inturn may corrupt the results or break the +operation. Set the req->iv variable to NULL explicitly for algorithms +like AES-ECB where IV is not used. + +Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver") +Signed-off-by: Akhil R +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/tegra/tegra-se-aes.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/crypto/tegra/tegra-se-aes.c b/drivers/crypto/tegra/tegra-se-aes.c +index cdcf05e235cad..be0a0b51f5a59 100644 +--- a/drivers/crypto/tegra/tegra-se-aes.c ++++ b/drivers/crypto/tegra/tegra-se-aes.c +@@ -443,6 +443,9 @@ static int tegra_aes_crypt(struct skcipher_request *req, bool encrypt) + if (!req->cryptlen) + return 0; + ++ if (ctx->alg == SE_ALG_ECB) ++ req->iv = NULL; ++ + rctx->encrypt = encrypt; + rctx->config = tegra234_aes_cfg(ctx->alg, encrypt); + rctx->crypto_config = tegra234_aes_crypto_cfg(ctx->alg, encrypt); +-- +2.39.5 + diff --git a/queue-6.14/crypto-tegra-transfer-hash-init-function-to-crypto-e.patch b/queue-6.14/crypto-tegra-transfer-hash-init-function-to-crypto-e.patch new file mode 100644 index 0000000000..5ea576e894 --- /dev/null +++ b/queue-6.14/crypto-tegra-transfer-hash-init-function-to-crypto-e.patch @@ -0,0 +1,311 @@ +From 9640ad86228f3af9cb0460ee64c18a36a9c77925 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 14:46:05 +0530 +Subject: crypto: tegra - Transfer HASH init function to crypto engine + +From: Akhil R + +[ Upstream commit 97ee15ea101629d2ffe21d3c5dc03b8d8be43603 ] + +Ahash init() function was called asynchronous to the crypto engine queue. +This could corrupt the request context if there is any ongoing operation +for the same request. Queue the init function as well to the crypto +engine queue so that this scenario can be avoided. + +Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver") +Signed-off-by: Akhil R +Signed-off-by: Herbert Xu +Stable-dep-of: ff4b7df0b511 ("crypto: tegra - Fix HASH intermediate result handling") +Signed-off-by: Sasha Levin +--- + drivers/crypto/tegra/tegra-se-aes.c | 81 ++++++++++++--------- + drivers/crypto/tegra/tegra-se-hash.c | 101 +++++++++++++++------------ + drivers/crypto/tegra/tegra-se.h | 5 +- + 3 files changed, 109 insertions(+), 78 deletions(-) + +diff --git a/drivers/crypto/tegra/tegra-se-aes.c b/drivers/crypto/tegra/tegra-se-aes.c +index dd147fa4af977..5d8237cda58f0 100644 +--- a/drivers/crypto/tegra/tegra-se-aes.c ++++ b/drivers/crypto/tegra/tegra-se-aes.c +@@ -1453,6 +1453,34 @@ static void tegra_cmac_paste_result(struct tegra_se *se, struct tegra_cmac_reqct + se->base + se->hw->regs->result + (i * 4)); + } + ++static int tegra_cmac_do_init(struct ahash_request *req) ++{ ++ struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm); ++ struct tegra_se *se = ctx->se; ++ int i; ++ ++ rctx->total_len = 0; ++ rctx->datbuf.size = 0; ++ rctx->residue.size = 0; ++ rctx->task |= SHA_FIRST; ++ rctx->blk_size = crypto_ahash_blocksize(tfm); ++ ++ rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size * 2, ++ &rctx->residue.addr, GFP_KERNEL); ++ if (!rctx->residue.buf) ++ return -ENOMEM; ++ ++ rctx->residue.size = 0; ++ ++ /* Clear any previous result */ ++ for (i = 0; i < CMAC_RESULT_REG_COUNT; i++) ++ writel(0, se->base + se->hw->regs->result + (i * 4)); ++ ++ return 0; ++} ++ + static int tegra_cmac_do_update(struct ahash_request *req) + { + struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req); +@@ -1598,6 +1626,14 @@ static int tegra_cmac_do_one_req(struct crypto_engine *engine, void *areq) + struct tegra_se *se = ctx->se; + int ret = 0; + ++ if (rctx->task & SHA_INIT) { ++ ret = tegra_cmac_do_init(req); ++ if (ret) ++ goto out; ++ ++ rctx->task &= ~SHA_INIT; ++ } ++ + if (rctx->task & SHA_UPDATE) { + ret = tegra_cmac_do_update(req); + if (ret) +@@ -1678,34 +1714,6 @@ static void tegra_cmac_cra_exit(struct crypto_tfm *tfm) + tegra_key_invalidate(ctx->se, ctx->key_id, ctx->alg); + } + +-static int tegra_cmac_init(struct ahash_request *req) +-{ +- struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req); +- struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); +- struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm); +- struct tegra_se *se = ctx->se; +- int i; +- +- rctx->total_len = 0; +- rctx->datbuf.size = 0; +- rctx->residue.size = 0; +- rctx->task = SHA_FIRST; +- rctx->blk_size = crypto_ahash_blocksize(tfm); +- +- rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size * 2, +- &rctx->residue.addr, GFP_KERNEL); +- if (!rctx->residue.buf) +- return -ENOMEM; +- +- rctx->residue.size = 0; +- +- /* Clear any previous result */ +- for (i = 0; i < CMAC_RESULT_REG_COUNT; i++) +- writel(0, se->base + se->hw->regs->result + (i * 4)); +- +- return 0; +-} +- + static int tegra_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, + unsigned int keylen) + { +@@ -1722,6 +1730,17 @@ static int tegra_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, + return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id); + } + ++static int tegra_cmac_init(struct ahash_request *req) ++{ ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm); ++ struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req); ++ ++ rctx->task = SHA_INIT; ++ ++ return crypto_transfer_hash_request_to_engine(ctx->se->engine, req); ++} ++ + static int tegra_cmac_update(struct ahash_request *req) + { + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); +@@ -1760,13 +1779,9 @@ static int tegra_cmac_digest(struct ahash_request *req) + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm); + struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req); +- int ret; + +- ret = tegra_cmac_init(req); +- if (ret) +- return ret; ++ rctx->task |= SHA_INIT | SHA_UPDATE | SHA_FINAL; + +- rctx->task |= SHA_UPDATE | SHA_FINAL; + return crypto_transfer_hash_request_to_engine(ctx->se->engine, req); + } + +diff --git a/drivers/crypto/tegra/tegra-se-hash.c b/drivers/crypto/tegra/tegra-se-hash.c +index 0ae5ce67bdd04..07e4c7320ec8d 100644 +--- a/drivers/crypto/tegra/tegra-se-hash.c ++++ b/drivers/crypto/tegra/tegra-se-hash.c +@@ -296,6 +296,44 @@ static void tegra_sha_paste_hash_result(struct tegra_se *se, struct tegra_sha_re + se->base + se->hw->regs->result + (i * 4)); + } + ++static int tegra_sha_do_init(struct ahash_request *req) ++{ ++ struct tegra_sha_reqctx *rctx = ahash_request_ctx(req); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm); ++ struct tegra_se *se = ctx->se; ++ ++ if (ctx->fallback) ++ return tegra_sha_fallback_init(req); ++ ++ rctx->total_len = 0; ++ rctx->datbuf.size = 0; ++ rctx->residue.size = 0; ++ rctx->key_id = ctx->key_id; ++ rctx->task |= SHA_FIRST; ++ rctx->alg = ctx->alg; ++ rctx->blk_size = crypto_ahash_blocksize(tfm); ++ rctx->digest.size = crypto_ahash_digestsize(tfm); ++ ++ rctx->digest.buf = dma_alloc_coherent(se->dev, rctx->digest.size, ++ &rctx->digest.addr, GFP_KERNEL); ++ if (!rctx->digest.buf) ++ goto digbuf_fail; ++ ++ rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size, ++ &rctx->residue.addr, GFP_KERNEL); ++ if (!rctx->residue.buf) ++ goto resbuf_fail; ++ ++ return 0; ++ ++resbuf_fail: ++ dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf, ++ rctx->digest.addr); ++digbuf_fail: ++ return -ENOMEM; ++} ++ + static int tegra_sha_do_update(struct ahash_request *req) + { + struct tegra_sha_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); +@@ -435,6 +473,14 @@ static int tegra_sha_do_one_req(struct crypto_engine *engine, void *areq) + struct tegra_se *se = ctx->se; + int ret = 0; + ++ if (rctx->task & SHA_INIT) { ++ ret = tegra_sha_do_init(req); ++ if (ret) ++ goto out; ++ ++ rctx->task &= ~SHA_INIT; ++ } ++ + if (rctx->task & SHA_UPDATE) { + ret = tegra_sha_do_update(req); + if (ret) +@@ -525,44 +571,6 @@ static void tegra_sha_cra_exit(struct crypto_tfm *tfm) + tegra_key_invalidate(ctx->se, ctx->key_id, ctx->alg); + } + +-static int tegra_sha_init(struct ahash_request *req) +-{ +- struct tegra_sha_reqctx *rctx = ahash_request_ctx(req); +- struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); +- struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm); +- struct tegra_se *se = ctx->se; +- +- if (ctx->fallback) +- return tegra_sha_fallback_init(req); +- +- rctx->total_len = 0; +- rctx->datbuf.size = 0; +- rctx->residue.size = 0; +- rctx->key_id = ctx->key_id; +- rctx->task = SHA_FIRST; +- rctx->alg = ctx->alg; +- rctx->blk_size = crypto_ahash_blocksize(tfm); +- rctx->digest.size = crypto_ahash_digestsize(tfm); +- +- rctx->digest.buf = dma_alloc_coherent(se->dev, rctx->digest.size, +- &rctx->digest.addr, GFP_KERNEL); +- if (!rctx->digest.buf) +- goto digbuf_fail; +- +- rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size, +- &rctx->residue.addr, GFP_KERNEL); +- if (!rctx->residue.buf) +- goto resbuf_fail; +- +- return 0; +- +-resbuf_fail: +- dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf, +- rctx->digest.addr); +-digbuf_fail: +- return -ENOMEM; +-} +- + static int tegra_hmac_fallback_setkey(struct tegra_sha_ctx *ctx, const u8 *key, + unsigned int keylen) + { +@@ -588,6 +596,17 @@ static int tegra_hmac_setkey(struct crypto_ahash *tfm, const u8 *key, + return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id); + } + ++static int tegra_sha_init(struct ahash_request *req) ++{ ++ struct tegra_sha_reqctx *rctx = ahash_request_ctx(req); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm); ++ ++ rctx->task = SHA_INIT; ++ ++ return crypto_transfer_hash_request_to_engine(ctx->se->engine, req); ++} ++ + static int tegra_sha_update(struct ahash_request *req) + { + struct tegra_sha_reqctx *rctx = ahash_request_ctx(req); +@@ -635,16 +654,12 @@ static int tegra_sha_digest(struct ahash_request *req) + struct tegra_sha_reqctx *rctx = ahash_request_ctx(req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm); +- int ret; + + if (ctx->fallback) + return tegra_sha_fallback_digest(req); + +- ret = tegra_sha_init(req); +- if (ret) +- return ret; ++ rctx->task |= SHA_INIT | SHA_UPDATE | SHA_FINAL; + +- rctx->task |= SHA_UPDATE | SHA_FINAL; + return crypto_transfer_hash_request_to_engine(ctx->se->engine, req); + } + +diff --git a/drivers/crypto/tegra/tegra-se.h b/drivers/crypto/tegra/tegra-se.h +index e196a90eedb92..e1ec37bfb80a8 100644 +--- a/drivers/crypto/tegra/tegra-se.h ++++ b/drivers/crypto/tegra/tegra-se.h +@@ -342,8 +342,9 @@ + #define SE_MAX_MEM_ALLOC SZ_4M + + #define SHA_FIRST BIT(0) +-#define SHA_UPDATE BIT(1) +-#define SHA_FINAL BIT(2) ++#define SHA_INIT BIT(1) ++#define SHA_UPDATE BIT(2) ++#define SHA_FINAL BIT(3) + + /* Security Engine operation modes */ + enum se_aes_alg { +-- +2.39.5 + diff --git a/queue-6.14/crypto-tegra-use-hmac-fallback-when-keyslots-are-ful.patch b/queue-6.14/crypto-tegra-use-hmac-fallback-when-keyslots-are-ful.patch new file mode 100644 index 0000000000..5da06b8f37 --- /dev/null +++ b/queue-6.14/crypto-tegra-use-hmac-fallback-when-keyslots-are-ful.patch @@ -0,0 +1,49 @@ +From 8018efa399820d641d69d3bd70dc7a3bed57dc6f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 14:46:10 +0530 +Subject: crypto: tegra - Use HMAC fallback when keyslots are full + +From: Akhil R + +[ Upstream commit f80a2e2e77bedd0aa645a60f89b4f581c70accda ] + +The intermediate results for HMAC is stored in the allocated keyslot by +the hardware. Dynamic allocation of keyslot during an operation is hence +not possible. As the number of keyslots are limited in the hardware, +fallback to the HMAC software implementation if keyslots are not available + +Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver") +Signed-off-by: Akhil R +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/tegra/tegra-se-hash.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/crypto/tegra/tegra-se-hash.c b/drivers/crypto/tegra/tegra-se-hash.c +index 8bed13552ab9e..65a50f29bd7e6 100644 +--- a/drivers/crypto/tegra/tegra-se-hash.c ++++ b/drivers/crypto/tegra/tegra-se-hash.c +@@ -632,13 +632,18 @@ static int tegra_hmac_setkey(struct crypto_ahash *tfm, const u8 *key, + unsigned int keylen) + { + struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm); ++ int ret; + + if (aes_check_keylen(keylen)) + return tegra_hmac_fallback_setkey(ctx, key, keylen); + ++ ret = tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id); ++ if (ret) ++ return tegra_hmac_fallback_setkey(ctx, key, keylen); ++ + ctx->fallback = false; + +- return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id); ++ return 0; + } + + static int tegra_sha_init(struct ahash_request *req) +-- +2.39.5 + diff --git a/queue-6.14/crypto-tegra-use-separate-buffer-for-setkey.patch b/queue-6.14/crypto-tegra-use-separate-buffer-for-setkey.patch new file mode 100644 index 0000000000..09b8c66cbc --- /dev/null +++ b/queue-6.14/crypto-tegra-use-separate-buffer-for-setkey.patch @@ -0,0 +1,251 @@ +From 4dcc3500a0190f7a2beadbd80a91801c60b254cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 14:46:01 +0530 +Subject: crypto: tegra - Use separate buffer for setkey + +From: Akhil R + +[ Upstream commit bcfc8fc53f3acb3213fb9d28675244aa4ce208e0 ] + +The buffer which sends the commands to host1x was shared for all tasks +in the engine. This causes a problem with the setkey() function as it +gets called asynchronous to the crypto engine queue. Modifying the same +cmdbuf in setkey() will corrupt the ongoing host1x task and in turn +break the encryption/decryption operation. Hence use a separate cmdbuf +for setkey(). + +Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver") +Signed-off-by: Akhil R +Signed-off-by: Herbert Xu +Stable-dep-of: ff4b7df0b511 ("crypto: tegra - Fix HASH intermediate result handling") +Signed-off-by: Sasha Levin +--- + drivers/crypto/tegra/tegra-se-aes.c | 16 ++++++++-------- + drivers/crypto/tegra/tegra-se-hash.c | 13 +++++++------ + drivers/crypto/tegra/tegra-se-key.c | 10 ++++++++-- + drivers/crypto/tegra/tegra-se-main.c | 16 ++++++++++++---- + drivers/crypto/tegra/tegra-se.h | 3 ++- + 5 files changed, 37 insertions(+), 21 deletions(-) + +diff --git a/drivers/crypto/tegra/tegra-se-aes.c b/drivers/crypto/tegra/tegra-se-aes.c +index d734c9a567868..7da7e169a314b 100644 +--- a/drivers/crypto/tegra/tegra-se-aes.c ++++ b/drivers/crypto/tegra/tegra-se-aes.c +@@ -282,7 +282,7 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq) + + /* Prepare the command and submit for execution */ + cmdlen = tegra_aes_prep_cmd(ctx, rctx); +- ret = tegra_se_host1x_submit(se, cmdlen); ++ ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen); + + /* Copy the result */ + tegra_aes_update_iv(req, ctx); +@@ -719,7 +719,7 @@ static int tegra_gcm_do_gmac(struct tegra_aead_ctx *ctx, struct tegra_aead_reqct + + cmdlen = tegra_gmac_prep_cmd(ctx, rctx); + +- return tegra_se_host1x_submit(se, cmdlen); ++ return tegra_se_host1x_submit(se, se->cmdbuf, cmdlen); + } + + static int tegra_gcm_do_crypt(struct tegra_aead_ctx *ctx, struct tegra_aead_reqctx *rctx) +@@ -736,7 +736,7 @@ static int tegra_gcm_do_crypt(struct tegra_aead_ctx *ctx, struct tegra_aead_reqc + + /* Prepare command and submit */ + cmdlen = tegra_gcm_crypt_prep_cmd(ctx, rctx); +- ret = tegra_se_host1x_submit(se, cmdlen); ++ ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen); + if (ret) + return ret; + +@@ -759,7 +759,7 @@ static int tegra_gcm_do_final(struct tegra_aead_ctx *ctx, struct tegra_aead_reqc + + /* Prepare command and submit */ + cmdlen = tegra_gcm_prep_final_cmd(se, cpuvaddr, rctx); +- ret = tegra_se_host1x_submit(se, cmdlen); ++ ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen); + if (ret) + return ret; + +@@ -891,7 +891,7 @@ static int tegra_ccm_do_cbcmac(struct tegra_aead_ctx *ctx, struct tegra_aead_req + /* Prepare command and submit */ + cmdlen = tegra_cbcmac_prep_cmd(ctx, rctx); + +- return tegra_se_host1x_submit(se, cmdlen); ++ return tegra_se_host1x_submit(se, se->cmdbuf, cmdlen); + } + + static int tegra_ccm_set_msg_len(u8 *block, unsigned int msglen, int csize) +@@ -1098,7 +1098,7 @@ static int tegra_ccm_do_ctr(struct tegra_aead_ctx *ctx, struct tegra_aead_reqctx + + /* Prepare command and submit */ + cmdlen = tegra_ctr_prep_cmd(ctx, rctx); +- ret = tegra_se_host1x_submit(se, cmdlen); ++ ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen); + if (ret) + return ret; + +@@ -1519,8 +1519,8 @@ static int tegra_cmac_do_update(struct ahash_request *req) + tegra_cmac_paste_result(ctx->se, rctx); + + cmdlen = tegra_cmac_prep_cmd(ctx, rctx); ++ ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen); + +- ret = tegra_se_host1x_submit(se, cmdlen); + /* + * If this is not the final update, copy the intermediate results + * from the registers so that it can be used in the next 'update' +@@ -1553,7 +1553,7 @@ static int tegra_cmac_do_final(struct ahash_request *req) + + /* Prepare command and submit */ + cmdlen = tegra_cmac_prep_cmd(ctx, rctx); +- ret = tegra_se_host1x_submit(se, cmdlen); ++ ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen); + if (ret) + goto out; + +diff --git a/drivers/crypto/tegra/tegra-se-hash.c b/drivers/crypto/tegra/tegra-se-hash.c +index 0b5cdd5676b17..c7b2a062a03c0 100644 +--- a/drivers/crypto/tegra/tegra-se-hash.c ++++ b/drivers/crypto/tegra/tegra-se-hash.c +@@ -300,8 +300,9 @@ static int tegra_sha_do_update(struct ahash_request *req) + { + struct tegra_sha_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); + struct tegra_sha_reqctx *rctx = ahash_request_ctx(req); ++ struct tegra_se *se = ctx->se; + unsigned int nblks, nresidue, size, ret; +- u32 *cpuvaddr = ctx->se->cmdbuf->addr; ++ u32 *cpuvaddr = se->cmdbuf->addr; + + nresidue = (req->nbytes + rctx->residue.size) % rctx->blk_size; + nblks = (req->nbytes + rctx->residue.size) / rctx->blk_size; +@@ -353,11 +354,11 @@ static int tegra_sha_do_update(struct ahash_request *req) + * This is to support the import/export functionality. + */ + if (!(rctx->task & SHA_FIRST)) +- tegra_sha_paste_hash_result(ctx->se, rctx); ++ tegra_sha_paste_hash_result(se, rctx); + +- size = tegra_sha_prep_cmd(ctx->se, cpuvaddr, rctx); ++ size = tegra_sha_prep_cmd(se, cpuvaddr, rctx); + +- ret = tegra_se_host1x_submit(ctx->se, size); ++ ret = tegra_se_host1x_submit(se, se->cmdbuf, size); + + /* + * If this is not the final update, copy the intermediate results +@@ -365,7 +366,7 @@ static int tegra_sha_do_update(struct ahash_request *req) + * call. This is to support the import/export functionality. + */ + if (!(rctx->task & SHA_FINAL)) +- tegra_sha_copy_hash_result(ctx->se, rctx); ++ tegra_sha_copy_hash_result(se, rctx); + + return ret; + } +@@ -388,7 +389,7 @@ static int tegra_sha_do_final(struct ahash_request *req) + + size = tegra_sha_prep_cmd(se, cpuvaddr, rctx); + +- ret = tegra_se_host1x_submit(se, size); ++ ret = tegra_se_host1x_submit(se, se->cmdbuf, size); + if (ret) + goto out; + +diff --git a/drivers/crypto/tegra/tegra-se-key.c b/drivers/crypto/tegra/tegra-se-key.c +index ac14678dbd30d..276b261fb6df1 100644 +--- a/drivers/crypto/tegra/tegra-se-key.c ++++ b/drivers/crypto/tegra/tegra-se-key.c +@@ -115,11 +115,17 @@ static int tegra_key_insert(struct tegra_se *se, const u8 *key, + u32 keylen, u16 slot, u32 alg) + { + const u32 *keyval = (u32 *)key; +- u32 *addr = se->cmdbuf->addr, size; ++ u32 *addr = se->keybuf->addr, size; ++ int ret; ++ ++ mutex_lock(&kslt_lock); + + size = tegra_key_prep_ins_cmd(se, addr, keyval, keylen, slot, alg); ++ ret = tegra_se_host1x_submit(se, se->keybuf, size); + +- return tegra_se_host1x_submit(se, size); ++ mutex_unlock(&kslt_lock); ++ ++ return ret; + } + + void tegra_key_invalidate(struct tegra_se *se, u32 keyid, u32 alg) +diff --git a/drivers/crypto/tegra/tegra-se-main.c b/drivers/crypto/tegra/tegra-se-main.c +index 918c0b10614d4..1c94f1de05467 100644 +--- a/drivers/crypto/tegra/tegra-se-main.c ++++ b/drivers/crypto/tegra/tegra-se-main.c +@@ -141,7 +141,7 @@ static struct tegra_se_cmdbuf *tegra_se_host1x_bo_alloc(struct tegra_se *se, ssi + return cmdbuf; + } + +-int tegra_se_host1x_submit(struct tegra_se *se, u32 size) ++int tegra_se_host1x_submit(struct tegra_se *se, struct tegra_se_cmdbuf *cmdbuf, u32 size) + { + struct host1x_job *job; + int ret; +@@ -160,9 +160,9 @@ int tegra_se_host1x_submit(struct tegra_se *se, u32 size) + job->engine_fallback_streamid = se->stream_id; + job->engine_streamid_offset = SE_STREAM_ID; + +- se->cmdbuf->words = size; ++ cmdbuf->words = size; + +- host1x_job_add_gather(job, &se->cmdbuf->bo, size, 0); ++ host1x_job_add_gather(job, &cmdbuf->bo, size, 0); + + ret = host1x_job_pin(job, se->dev); + if (ret) { +@@ -220,14 +220,22 @@ static int tegra_se_client_init(struct host1x_client *client) + goto syncpt_put; + } + ++ se->keybuf = tegra_se_host1x_bo_alloc(se, SZ_4K); ++ if (!se->keybuf) { ++ ret = -ENOMEM; ++ goto cmdbuf_put; ++ } ++ + ret = se->hw->init_alg(se); + if (ret) { + dev_err(se->dev, "failed to register algorithms\n"); +- goto cmdbuf_put; ++ goto keybuf_put; + } + + return 0; + ++keybuf_put: ++ tegra_se_cmdbuf_put(&se->keybuf->bo); + cmdbuf_put: + tegra_se_cmdbuf_put(&se->cmdbuf->bo); + syncpt_put: +diff --git a/drivers/crypto/tegra/tegra-se.h b/drivers/crypto/tegra/tegra-se.h +index b9dd7ceb8783c..b54aefe717a17 100644 +--- a/drivers/crypto/tegra/tegra-se.h ++++ b/drivers/crypto/tegra/tegra-se.h +@@ -420,6 +420,7 @@ struct tegra_se { + struct host1x_client client; + struct host1x_channel *channel; + struct tegra_se_cmdbuf *cmdbuf; ++ struct tegra_se_cmdbuf *keybuf; + struct crypto_engine *engine; + struct host1x_syncpt *syncpt; + struct device *dev; +@@ -502,7 +503,7 @@ void tegra_deinit_hash(struct tegra_se *se); + int tegra_key_submit(struct tegra_se *se, const u8 *key, + u32 keylen, u32 alg, u32 *keyid); + void tegra_key_invalidate(struct tegra_se *se, u32 keyid, u32 alg); +-int tegra_se_host1x_submit(struct tegra_se *se, u32 size); ++int tegra_se_host1x_submit(struct tegra_se *se, struct tegra_se_cmdbuf *cmdbuf, u32 size); + + /* HOST1x OPCODES */ + static inline u32 host1x_opcode_setpayload(unsigned int payload) +-- +2.39.5 + diff --git a/queue-6.14/dlm-prevent-npd-when-writing-a-positive-value-to-eve.patch b/queue-6.14/dlm-prevent-npd-when-writing-a-positive-value-to-eve.patch new file mode 100644 index 0000000000..81c40b8d60 --- /dev/null +++ b/queue-6.14/dlm-prevent-npd-when-writing-a-positive-value-to-eve.patch @@ -0,0 +1,46 @@ +From 236f8ee5e8170d7affb8df38872e855469662f30 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 13:16:22 -0600 +Subject: dlm: prevent NPD when writing a positive value to event_done + +From: Thadeu Lima de Souza Cascardo + +[ Upstream commit 8e2bad543eca5c25cd02cbc63d72557934d45f13 ] + +do_uevent returns the value written to event_done. In case it is a +positive value, new_lockspace would undo all the work, and lockspace +would not be set. __dlm_new_lockspace, however, would treat that +positive value as a success due to commit 8511a2728ab8 ("dlm: fix use +count with multiple joins"). + +Down the line, device_create_lockspace would pass that NULL lockspace to +dlm_find_lockspace_local, leading to a NULL pointer dereference. + +Treating such positive values as successes prevents the problem. Given +this has been broken for so long, this is unlikely to break userspace +expectations. + +Fixes: 8511a2728ab8 ("dlm: fix use count with multiple joins") +Signed-off-by: Thadeu Lima de Souza Cascardo +Signed-off-by: David Teigland +Signed-off-by: Sasha Levin +--- + fs/dlm/lockspace.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c +index 8afac6e2dff00..1929327ffbe1c 100644 +--- a/fs/dlm/lockspace.c ++++ b/fs/dlm/lockspace.c +@@ -576,7 +576,7 @@ static int new_lockspace(const char *name, const char *cluster, + lockspace to start running (via sysfs) in dlm_ls_start(). */ + + error = do_uevent(ls, 1); +- if (error) ++ if (error < 0) + goto out_recoverd; + + /* wait until recovery is successful or failed */ +-- +2.39.5 + diff --git a/queue-6.14/dma-fix-encryption-bit-clearing-for-dma_to_phys.patch b/queue-6.14/dma-fix-encryption-bit-clearing-for-dma_to_phys.patch new file mode 100644 index 0000000000..39f1c3d819 --- /dev/null +++ b/queue-6.14/dma-fix-encryption-bit-clearing-for-dma_to_phys.patch @@ -0,0 +1,61 @@ +From 3c67cb8b6b093bcea8f1f55dd3c36267fca04e74 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 14:41:48 +0000 +Subject: dma: Fix encryption bit clearing for dma_to_phys + +From: Suzuki K Poulose + +[ Upstream commit c380931712d16e23f6aa90703f438330139e9731 ] + +phys_to_dma() sets the encryption bit on the translated DMA address. But +dma_to_phys() clears the encryption bit after it has been translated back +to the physical address, which could fail if the device uses DMA ranges. + +AMD SME doesn't use the DMA ranges and thus this is harmless. But as we +are about to add support for other architectures, let us fix this. + +Reported-by: Aneesh Kumar K.V +Link: https://lkml.kernel.org/r/yq5amsen9stc.fsf@kernel.org +Cc: Will Deacon +Cc: Jean-Philippe Brucker +Cc: Robin Murphy +Cc: Steven Price +Cc: Christoph Hellwig +Cc: Marek Szyprowski +Cc: Tom Lendacky +Reviewed-by: Robin Murphy +Acked-by: Tom Lendacky +Signed-off-by: Suzuki K Poulose +Reviewed-by: Gavin Shan +Acked-by: Marek Szyprowski +Fixes: 42be24a4178f ("arm64: Enable memory encrypt for Realms") +Acked-by: Will Deacon +Link: https://lore.kernel.org/r/20250227144150.1667735-2-suzuki.poulose@arm.com +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + include/linux/dma-direct.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h +index d7e30d4f7503a..d20ecc24cb0f5 100644 +--- a/include/linux/dma-direct.h ++++ b/include/linux/dma-direct.h +@@ -101,12 +101,13 @@ static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dma_addr) + { + phys_addr_t paddr; + ++ dma_addr = __sme_clr(dma_addr); + if (dev->dma_range_map) + paddr = translate_dma_to_phys(dev, dma_addr); + else + paddr = dma_addr; + +- return __sme_clr(paddr); ++ return paddr; + } + #endif /* !CONFIG_ARCH_HAS_PHYS_TO_DMA */ + +-- +2.39.5 + diff --git a/queue-6.14/dma-introduce-generic-dma_addr_-crypted-helpers.patch b/queue-6.14/dma-introduce-generic-dma_addr_-crypted-helpers.patch new file mode 100644 index 0000000000..ff3b7355de --- /dev/null +++ b/queue-6.14/dma-introduce-generic-dma_addr_-crypted-helpers.patch @@ -0,0 +1,137 @@ +From 07fc72dc449db39d65ab2b1db6109fc46af52fae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 14:41:49 +0000 +Subject: dma: Introduce generic dma_addr_*crypted helpers + +From: Suzuki K Poulose + +[ Upstream commit b66e2ee7b6c8d45bbe4b6f6885ee27511506812c ] + +AMD SME added __sme_set/__sme_clr primitives to modify the DMA address for +encrypted/decrypted traffic. However this doesn't fit in with other models, +e.g., Arm CCA where the meanings are the opposite. i.e., "decrypted" traffic +has a bit set and "encrypted" traffic has the top bit cleared. + +In preparation for adding the support for Arm CCA DMA conversions, convert the +existing primitives to more generic ones that can be provided by the backends. +i.e., add helpers to + 1. dma_addr_encrypted - Convert a DMA address to "encrypted" [ == __sme_set() ] + 2. dma_addr_unencrypted - Convert a DMA address to "decrypted" [ None exists today ] + 3. dma_addr_canonical - Clear any "encryption"/"decryption" bits from DMA + address [ SME uses __sme_clr() ] and convert to a canonical DMA address. + +Since the original __sme_xxx helpers come from linux/mem_encrypt.h, use that +as the home for the new definitions and provide dummy ones when none is provided +by the architectures. + +With the above, phys_to_dma_unencrypted() uses the newly added dma_addr_unencrypted() +helper and to make it a bit more easier to read and avoid double conversion, +provide __phys_to_dma(). + +Suggested-by: Robin Murphy +Cc: Will Deacon +Cc: Jean-Philippe Brucker +Cc: Robin Murphy +Cc: Steven Price +Cc: Christoph Hellwig +Cc: Marek Szyprowski +Cc: Tom Lendacky +Cc: Aneesh Kumar K.V +Signed-off-by: Suzuki K Poulose +Reviewed-by: Robin Murphy +Reviewed-by: Gavin Shan +Acked-by: Marek Szyprowski +Fixes: 42be24a4178f ("arm64: Enable memory encrypt for Realms") +Acked-by: Will Deacon +Link: https://lore.kernel.org/r/20250227144150.1667735-3-suzuki.poulose@arm.com +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + include/linux/dma-direct.h | 12 ++++++++---- + include/linux/mem_encrypt.h | 23 +++++++++++++++++++++++ + 2 files changed, 31 insertions(+), 4 deletions(-) + +diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h +index d20ecc24cb0f5..f3bc0bcd70980 100644 +--- a/include/linux/dma-direct.h ++++ b/include/linux/dma-direct.h +@@ -78,14 +78,18 @@ static inline dma_addr_t dma_range_map_max(const struct bus_dma_region *map) + #define phys_to_dma_unencrypted phys_to_dma + #endif + #else +-static inline dma_addr_t phys_to_dma_unencrypted(struct device *dev, +- phys_addr_t paddr) ++static inline dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr) + { + if (dev->dma_range_map) + return translate_phys_to_dma(dev, paddr); + return paddr; + } + ++static inline dma_addr_t phys_to_dma_unencrypted(struct device *dev, ++ phys_addr_t paddr) ++{ ++ return dma_addr_unencrypted(__phys_to_dma(dev, paddr)); ++} + /* + * If memory encryption is supported, phys_to_dma will set the memory encryption + * bit in the DMA address, and dma_to_phys will clear it. +@@ -94,14 +98,14 @@ static inline dma_addr_t phys_to_dma_unencrypted(struct device *dev, + */ + static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) + { +- return __sme_set(phys_to_dma_unencrypted(dev, paddr)); ++ return dma_addr_encrypted(__phys_to_dma(dev, paddr)); + } + + static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dma_addr) + { + phys_addr_t paddr; + +- dma_addr = __sme_clr(dma_addr); ++ dma_addr = dma_addr_canonical(dma_addr); + if (dev->dma_range_map) + paddr = translate_dma_to_phys(dev, dma_addr); + else +diff --git a/include/linux/mem_encrypt.h b/include/linux/mem_encrypt.h +index ae45263892611..07584c5e36fb4 100644 +--- a/include/linux/mem_encrypt.h ++++ b/include/linux/mem_encrypt.h +@@ -26,11 +26,34 @@ + */ + #define __sme_set(x) ((x) | sme_me_mask) + #define __sme_clr(x) ((x) & ~sme_me_mask) ++ ++#define dma_addr_encrypted(x) __sme_set(x) ++#define dma_addr_canonical(x) __sme_clr(x) ++ + #else + #define __sme_set(x) (x) + #define __sme_clr(x) (x) + #endif + ++/* ++ * dma_addr_encrypted() and dma_addr_unencrypted() are for converting a given DMA ++ * address to the respective type of addressing. ++ * ++ * dma_addr_canonical() is used to reverse any conversions for encrypted/decrypted ++ * back to the canonical address. ++ */ ++#ifndef dma_addr_encrypted ++#define dma_addr_encrypted(x) (x) ++#endif ++ ++#ifndef dma_addr_unencrypted ++#define dma_addr_unencrypted(x) (x) ++#endif ++ ++#ifndef dma_addr_canonical ++#define dma_addr_canonical(x) (x) ++#endif ++ + #endif /* __ASSEMBLY__ */ + + #endif /* __MEM_ENCRYPT_H__ */ +-- +2.39.5 + diff --git a/queue-6.14/dmaengine-ae4dma-use-the-msi-count-and-its-correspon.patch b/queue-6.14/dmaengine-ae4dma-use-the-msi-count-and-its-correspon.patch new file mode 100644 index 0000000000..7ecc6eb53c --- /dev/null +++ b/queue-6.14/dmaengine-ae4dma-use-the-msi-count-and-its-correspon.patch @@ -0,0 +1,40 @@ +From b49fe2c0df16e12fc409c519975003dc401392cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 21:55:10 +0530 +Subject: dmaengine: ae4dma: Use the MSI count and its corresponding IRQ number + +From: Basavaraj Natikar + +[ Upstream commit feba04e6fdf4daccc83fc09d499a3e32c178edb4 ] + +Instead of using the defined maximum hardware queue, which can lead to +incorrect values if the counts mismatch, use the exact supported MSI +count and its corresponding IRQ number. + +Fixes: 90a30e268d9b ("dmaengine: ae4dma: Add AMD ae4dma controller driver") +Signed-off-by: Basavaraj Natikar +Link: https://lore.kernel.org/r/20250203162511.911946-3-Basavaraj.Natikar@amd.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/amd/ae4dma/ae4dma-pci.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/dma/amd/ae4dma/ae4dma-pci.c b/drivers/dma/amd/ae4dma/ae4dma-pci.c +index aad0dc4294a39..587c5a10c1a8b 100644 +--- a/drivers/dma/amd/ae4dma/ae4dma-pci.c ++++ b/drivers/dma/amd/ae4dma/ae4dma-pci.c +@@ -46,8 +46,8 @@ static int ae4_get_irqs(struct ae4_device *ae4) + + } else { + ae4_msix->msix_count = ret; +- for (i = 0; i < MAX_AE4_HW_QUEUES; i++) +- ae4->ae4_irq[i] = ae4_msix->msix_entry[i].vector; ++ for (i = 0; i < ae4_msix->msix_count; i++) ++ ae4->ae4_irq[i] = pci_irq_vector(pdev, i); + } + + return ret; +-- +2.39.5 + diff --git a/queue-6.14/dmaengine-fsl-edma-cleanup-chan-after-dma_async_devi.patch b/queue-6.14/dmaengine-fsl-edma-cleanup-chan-after-dma_async_devi.patch new file mode 100644 index 0000000000..c97fd163b6 --- /dev/null +++ b/queue-6.14/dmaengine-fsl-edma-cleanup-chan-after-dma_async_devi.patch @@ -0,0 +1,52 @@ +From 870f6af853bc328c3c9a56ff68ba090c33b0a249 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 15:17:19 +0800 +Subject: dmaengine: fsl-edma: cleanup chan after dma_async_device_unregister + +From: Peng Fan + +[ Upstream commit c9c59da76ce9cb3f215b66eb3708cda1134a5206 ] + +There is kernel dump when do module test: +sysfs: cannot create duplicate filename +/devices/platform/soc@0/44000000.bus/44000000.dma-controller/dma/dma0chan0 + __dma_async_device_channel_register+0x128/0x19c + dma_async_device_register+0x150/0x454 + fsl_edma_probe+0x6cc/0x8a0 + platform_probe+0x68/0xc8 + +fsl_edma_cleanup_vchan will unlink vchan.chan.device_node, while +dma_async_device_unregister needs the link to do +__dma_async_device_channel_unregister. So need move fsl_edma_cleanup_vchan +after dma_async_device_unregister to make sure channel could be freed. + +So clean up chan after dma_async_device_unregister to address this. + +Fixes: 6f93b93b2a1b ("dmaengine: fsl-edma: kill the tasklets upon exit") +Reviewed-by: Frank Li +Signed-off-by: Peng Fan +Link: https://lore.kernel.org/r/20250228071720.3780479-1-peng.fan@oss.nxp.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/fsl-edma-main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c +index f989b6c9c0a98..133bdb48d1a5c 100644 +--- a/drivers/dma/fsl-edma-main.c ++++ b/drivers/dma/fsl-edma-main.c +@@ -802,9 +802,9 @@ static void fsl_edma_remove(struct platform_device *pdev) + struct fsl_edma_engine *fsl_edma = platform_get_drvdata(pdev); + + fsl_edma_irq_exit(pdev, fsl_edma); +- fsl_edma_cleanup_vchan(&fsl_edma->dma_dev); + of_dma_controller_free(np); + dma_async_device_unregister(&fsl_edma->dma_dev); ++ fsl_edma_cleanup_vchan(&fsl_edma->dma_dev); + fsl_disable_clocks(fsl_edma, fsl_edma->drvdata->dmamuxs); + } + +-- +2.39.5 + diff --git a/queue-6.14/dmaengine-fsl-edma-free-irq-correctly-in-remove-path.patch b/queue-6.14/dmaengine-fsl-edma-free-irq-correctly-in-remove-path.patch new file mode 100644 index 0000000000..af6a2c207b --- /dev/null +++ b/queue-6.14/dmaengine-fsl-edma-free-irq-correctly-in-remove-path.patch @@ -0,0 +1,77 @@ +From a755d6d9ebaf889775ef528542a3cd205e81a1f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 15:17:20 +0800 +Subject: dmaengine: fsl-edma: free irq correctly in remove path + +From: Peng Fan + +[ Upstream commit fa70c4c3c580c239a0f9e83a14770ab026e8d820 ] + +Add fsl_edma->txirq/errirq check to avoid below warning because no +errirq at i.MX9 platform. Otherwise there will be kernel dump: +WARNING: CPU: 0 PID: 11 at kernel/irq/devres.c:144 devm_free_irq+0x74/0x80 +Modules linked in: +CPU: 0 UID: 0 PID: 11 Comm: kworker/u8:0 Not tainted 6.12.0-rc7#18 +Hardware name: NXP i.MX93 11X11 EVK board (DT) +Workqueue: events_unbound deferred_probe_work_func +pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) +pc : devm_free_irq+0x74/0x80 +lr : devm_free_irq+0x48/0x80 +Call trace: + devm_free_irq+0x74/0x80 (P) + devm_free_irq+0x48/0x80 (L) + fsl_edma_remove+0xc4/0xc8 + platform_remove+0x28/0x44 + device_remove+0x4c/0x80 + +Fixes: 44eb827264de ("dmaengine: fsl-edma: request per-channel IRQ only when channel is allocated") +Reviewed-by: Frank Li +Signed-off-by: Peng Fan +Link: https://lore.kernel.org/r/20250228071720.3780479-2-peng.fan@oss.nxp.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/fsl-edma-main.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c +index 133bdb48d1a5c..e3e0e88a76d3c 100644 +--- a/drivers/dma/fsl-edma-main.c ++++ b/drivers/dma/fsl-edma-main.c +@@ -401,6 +401,7 @@ fsl_edma2_irq_init(struct platform_device *pdev, + + /* The last IRQ is for eDMA err */ + if (i == count - 1) { ++ fsl_edma->errirq = irq; + ret = devm_request_irq(&pdev->dev, irq, + fsl_edma_err_handler, + 0, "eDMA2-ERR", fsl_edma); +@@ -420,10 +421,13 @@ static void fsl_edma_irq_exit( + struct platform_device *pdev, struct fsl_edma_engine *fsl_edma) + { + if (fsl_edma->txirq == fsl_edma->errirq) { +- devm_free_irq(&pdev->dev, fsl_edma->txirq, fsl_edma); ++ if (fsl_edma->txirq >= 0) ++ devm_free_irq(&pdev->dev, fsl_edma->txirq, fsl_edma); + } else { +- devm_free_irq(&pdev->dev, fsl_edma->txirq, fsl_edma); +- devm_free_irq(&pdev->dev, fsl_edma->errirq, fsl_edma); ++ if (fsl_edma->txirq >= 0) ++ devm_free_irq(&pdev->dev, fsl_edma->txirq, fsl_edma); ++ if (fsl_edma->errirq >= 0) ++ devm_free_irq(&pdev->dev, fsl_edma->errirq, fsl_edma); + } + } + +@@ -620,6 +624,8 @@ static int fsl_edma_probe(struct platform_device *pdev) + if (!fsl_edma) + return -ENOMEM; + ++ fsl_edma->errirq = -EINVAL; ++ fsl_edma->txirq = -EINVAL; + fsl_edma->drvdata = drvdata; + fsl_edma->n_chans = chans; + mutex_init(&fsl_edma->fsl_edma_mutex); +-- +2.39.5 + diff --git a/queue-6.14/dmaengine-ptdma-utilize-the-ae4dma-engine-s-multi-qu.patch b/queue-6.14/dmaengine-ptdma-utilize-the-ae4dma-engine-s-multi-qu.patch new file mode 100644 index 0000000000..b5744517b2 --- /dev/null +++ b/queue-6.14/dmaengine-ptdma-utilize-the-ae4dma-engine-s-multi-qu.patch @@ -0,0 +1,211 @@ +From 9c8ef7c93e8a8e368c62e14aaa4dea4ec796d011 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 21:55:11 +0530 +Subject: dmaengine: ptdma: Utilize the AE4DMA engine's multi-queue + functionality +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Basavaraj Natikar + +[ Upstream commit 6565439894570a07b00dba0b739729fe6b56fba4 ] + +As AE4DMA offers multi-channel functionality compared to PTDMA’s single +queue, utilize multi-queue, which supports higher speeds than PTDMA, to +achieve higher performance using the AE4DMA workqueue based mechanism. + +Fixes: 69a47b16a51b ("dmaengine: ptdma: Extend ptdma to support multi-channel and version") +Signed-off-by: Basavaraj Natikar +Link: https://lore.kernel.org/r/20250203162511.911946-4-Basavaraj.Natikar@amd.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/amd/ae4dma/ae4dma.h | 2 + + drivers/dma/amd/ptdma/ptdma-dmaengine.c | 90 ++++++++++++++++++++++++- + 2 files changed, 89 insertions(+), 3 deletions(-) + +diff --git a/drivers/dma/amd/ae4dma/ae4dma.h b/drivers/dma/amd/ae4dma/ae4dma.h +index 265c5d4360080..57f6048726bb6 100644 +--- a/drivers/dma/amd/ae4dma/ae4dma.h ++++ b/drivers/dma/amd/ae4dma/ae4dma.h +@@ -37,6 +37,8 @@ + #define AE4_DMA_VERSION 4 + #define CMD_AE4_DESC_DW0_VAL 2 + ++#define AE4_TIME_OUT 5000 ++ + struct ae4_msix { + int msix_count; + struct msix_entry msix_entry[MAX_AE4_HW_QUEUES]; +diff --git a/drivers/dma/amd/ptdma/ptdma-dmaengine.c b/drivers/dma/amd/ptdma/ptdma-dmaengine.c +index 35c84ec9608b4..715ac3ae067b8 100644 +--- a/drivers/dma/amd/ptdma/ptdma-dmaengine.c ++++ b/drivers/dma/amd/ptdma/ptdma-dmaengine.c +@@ -198,8 +198,10 @@ static struct pt_dma_desc *pt_handle_active_desc(struct pt_dma_chan *chan, + { + struct dma_async_tx_descriptor *tx_desc; + struct virt_dma_desc *vd; ++ struct pt_device *pt; + unsigned long flags; + ++ pt = chan->pt; + /* Loop over descriptors until one is found with commands */ + do { + if (desc) { +@@ -217,7 +219,7 @@ static struct pt_dma_desc *pt_handle_active_desc(struct pt_dma_chan *chan, + + spin_lock_irqsave(&chan->vc.lock, flags); + +- if (desc) { ++ if (pt->ver != AE4_DMA_VERSION && desc) { + if (desc->status != DMA_COMPLETE) { + if (desc->status != DMA_ERROR) + desc->status = DMA_COMPLETE; +@@ -235,7 +237,7 @@ static struct pt_dma_desc *pt_handle_active_desc(struct pt_dma_chan *chan, + + spin_unlock_irqrestore(&chan->vc.lock, flags); + +- if (tx_desc) { ++ if (pt->ver != AE4_DMA_VERSION && tx_desc) { + dmaengine_desc_get_callback_invoke(tx_desc, NULL); + dma_run_dependencies(tx_desc); + vchan_vdesc_fini(vd); +@@ -245,11 +247,25 @@ static struct pt_dma_desc *pt_handle_active_desc(struct pt_dma_chan *chan, + return NULL; + } + ++static inline bool ae4_core_queue_full(struct pt_cmd_queue *cmd_q) ++{ ++ u32 front_wi = readl(cmd_q->reg_control + AE4_WR_IDX_OFF); ++ u32 rear_ri = readl(cmd_q->reg_control + AE4_RD_IDX_OFF); ++ ++ if (((MAX_CMD_QLEN + front_wi - rear_ri) % MAX_CMD_QLEN) >= (MAX_CMD_QLEN - 1)) ++ return true; ++ ++ return false; ++} ++ + static void pt_cmd_callback(void *data, int err) + { + struct pt_dma_desc *desc = data; ++ struct ae4_cmd_queue *ae4cmd_q; + struct dma_chan *dma_chan; + struct pt_dma_chan *chan; ++ struct ae4_device *ae4; ++ struct pt_device *pt; + int ret; + + if (err == -EINPROGRESS) +@@ -257,11 +273,32 @@ static void pt_cmd_callback(void *data, int err) + + dma_chan = desc->vd.tx.chan; + chan = to_pt_chan(dma_chan); ++ pt = chan->pt; + + if (err) + desc->status = DMA_ERROR; + + while (true) { ++ if (pt->ver == AE4_DMA_VERSION) { ++ ae4 = container_of(pt, struct ae4_device, pt); ++ ae4cmd_q = &ae4->ae4cmd_q[chan->id]; ++ ++ if (ae4cmd_q->q_cmd_count >= (CMD_Q_LEN - 1) || ++ ae4_core_queue_full(&ae4cmd_q->cmd_q)) { ++ wake_up(&ae4cmd_q->q_w); ++ ++ if (wait_for_completion_timeout(&ae4cmd_q->cmp, ++ msecs_to_jiffies(AE4_TIME_OUT)) ++ == 0) { ++ dev_err(pt->dev, "TIMEOUT %d:\n", ae4cmd_q->id); ++ break; ++ } ++ ++ reinit_completion(&ae4cmd_q->cmp); ++ continue; ++ } ++ } ++ + /* Check for DMA descriptor completion */ + desc = pt_handle_active_desc(chan, desc); + +@@ -296,6 +333,49 @@ static struct pt_dma_desc *pt_alloc_dma_desc(struct pt_dma_chan *chan, + return desc; + } + ++static void pt_cmd_callback_work(void *data, int err) ++{ ++ struct dma_async_tx_descriptor *tx_desc; ++ struct pt_dma_desc *desc = data; ++ struct dma_chan *dma_chan; ++ struct virt_dma_desc *vd; ++ struct pt_dma_chan *chan; ++ unsigned long flags; ++ ++ dma_chan = desc->vd.tx.chan; ++ chan = to_pt_chan(dma_chan); ++ ++ if (err == -EINPROGRESS) ++ return; ++ ++ tx_desc = &desc->vd.tx; ++ vd = &desc->vd; ++ ++ if (err) ++ desc->status = DMA_ERROR; ++ ++ spin_lock_irqsave(&chan->vc.lock, flags); ++ if (desc) { ++ if (desc->status != DMA_COMPLETE) { ++ if (desc->status != DMA_ERROR) ++ desc->status = DMA_COMPLETE; ++ ++ dma_cookie_complete(tx_desc); ++ dma_descriptor_unmap(tx_desc); ++ } else { ++ tx_desc = NULL; ++ } ++ } ++ spin_unlock_irqrestore(&chan->vc.lock, flags); ++ ++ if (tx_desc) { ++ dmaengine_desc_get_callback_invoke(tx_desc, NULL); ++ dma_run_dependencies(tx_desc); ++ list_del(&desc->vd.node); ++ vchan_vdesc_fini(vd); ++ } ++} ++ + static struct pt_dma_desc *pt_create_desc(struct dma_chan *dma_chan, + dma_addr_t dst, + dma_addr_t src, +@@ -327,6 +407,7 @@ static struct pt_dma_desc *pt_create_desc(struct dma_chan *dma_chan, + desc->len = len; + + if (pt->ver == AE4_DMA_VERSION) { ++ pt_cmd->pt_cmd_callback = pt_cmd_callback_work; + ae4 = container_of(pt, struct ae4_device, pt); + ae4cmd_q = &ae4->ae4cmd_q[chan->id]; + mutex_lock(&ae4cmd_q->cmd_lock); +@@ -367,13 +448,16 @@ static void pt_issue_pending(struct dma_chan *dma_chan) + { + struct pt_dma_chan *chan = to_pt_chan(dma_chan); + struct pt_dma_desc *desc; ++ struct pt_device *pt; + unsigned long flags; + bool engine_is_idle = true; + ++ pt = chan->pt; ++ + spin_lock_irqsave(&chan->vc.lock, flags); + + desc = pt_next_dma_desc(chan); +- if (desc) ++ if (desc && pt->ver != AE4_DMA_VERSION) + engine_is_idle = false; + + vchan_issue_pending(&chan->vc); +-- +2.39.5 + diff --git a/queue-6.14/drivers-clk-qcom-ipq5424-fix-the-freq-table-of-sdcc1.patch b/queue-6.14/drivers-clk-qcom-ipq5424-fix-the-freq-table-of-sdcc1.patch new file mode 100644 index 0000000000..52c949c684 --- /dev/null +++ b/queue-6.14/drivers-clk-qcom-ipq5424-fix-the-freq-table-of-sdcc1.patch @@ -0,0 +1,53 @@ +From dcacbc9cbf3774f3e7785850076dd75a43ede05c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 16:59:00 +0530 +Subject: drivers: clk: qcom: ipq5424: fix the freq table of sdcc1_apps clock + +From: Manikanta Mylavarapu + +[ Upstream commit e9ed0ac3ccba65c17ed0d59c77a340a75abc317b ] + +The divider values in the sdcc1_apps frequency table were incorrectly +updated, assuming the frequency of gpll2_out_main to be 1152MHz. +However, the frequency of the gpll2_out_main clock is actually 576MHz +(gpll2/2). + +Due to these incorrect divider values, the sdcc1_apps clock is running +at half of the expected frequency. + +Fixing the frequency table of sdcc1_apps allows the sdcc1_apps clock to +run according to the frequency plan. + +Fixes: 21b5d5a4a311 ("clk: qcom: add Global Clock controller (GCC) driver for IPQ5424 SoC") +Signed-off-by: Manikanta Mylavarapu +Reviewed-by: Kathiravan Thirumoorthy +Link: https://lore.kernel.org/r/20250306112900.3319330-1-quic_mmanikan@quicinc.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/gcc-ipq5424.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/clk/qcom/gcc-ipq5424.c b/drivers/clk/qcom/gcc-ipq5424.c +index d5b218b76e291..107424395ef17 100644 +--- a/drivers/clk/qcom/gcc-ipq5424.c ++++ b/drivers/clk/qcom/gcc-ipq5424.c +@@ -634,11 +634,11 @@ static struct clk_rcg2 gcc_qupv3_uart1_clk_src = { + static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = { + F(144000, P_XO, 16, 12, 125), + F(400000, P_XO, 12, 1, 5), +- F(24000000, P_XO, 1, 0, 0), +- F(48000000, P_GPLL2_OUT_MAIN, 12, 1, 2), +- F(96000000, P_GPLL2_OUT_MAIN, 6, 1, 2), ++ F(24000000, P_GPLL2_OUT_MAIN, 12, 1, 2), ++ F(48000000, P_GPLL2_OUT_MAIN, 12, 0, 0), ++ F(96000000, P_GPLL2_OUT_MAIN, 6, 0, 0), + F(177777778, P_GPLL0_OUT_MAIN, 4.5, 0, 0), +- F(192000000, P_GPLL2_OUT_MAIN, 6, 0, 0), ++ F(192000000, P_GPLL2_OUT_MAIN, 3, 0, 0), + F(200000000, P_GPLL0_OUT_MAIN, 4, 0, 0), + { } + }; +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-avoid-npd-when-asic-does-not-support.patch b/queue-6.14/drm-amd-display-avoid-npd-when-asic-does-not-support.patch new file mode 100644 index 0000000000..56e47004e3 --- /dev/null +++ b/queue-6.14/drm-amd-display-avoid-npd-when-asic-does-not-support.patch @@ -0,0 +1,149 @@ +From 694b6129bf6901f9126b31d54d7c58ffb8a5cb70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 10:06:38 -0300 +Subject: drm/amd/display: avoid NPD when ASIC does not support DMUB + +From: Thadeu Lima de Souza Cascardo + +[ Upstream commit 42d9d7bed270247f134190ba0cb05bbd072f58c2 ] + +ctx->dmub_srv will de NULL if the ASIC does not support DMUB, which is +tested in dm_dmub_sw_init. + +However, it will be dereferenced in dmub_hw_lock_mgr_cmd if +should_use_dmub_lock returns true. + +This has been the case since dmub support has been added for PSR1. + +Fix this by checking for dmub_srv in should_use_dmub_lock. + +[ 37.440832] BUG: kernel NULL pointer dereference, address: 0000000000000058 +[ 37.447808] #PF: supervisor read access in kernel mode +[ 37.452959] #PF: error_code(0x0000) - not-present page +[ 37.458112] PGD 0 P4D 0 +[ 37.460662] Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI +[ 37.465553] CPU: 2 UID: 1000 PID: 1745 Comm: DrmThread Not tainted 6.14.0-rc1-00003-gd62e938120f0 #23 99720e1cb1e0fc4773b8513150932a07de3c6e88 +[ 37.478324] Hardware name: Google Morphius/Morphius, BIOS Google_Morphius.13434.858.0 10/26/2023 +[ 37.487103] RIP: 0010:dmub_hw_lock_mgr_cmd+0x77/0xb0 +[ 37.492074] Code: 44 24 0e 00 00 00 00 48 c7 04 24 45 00 00 0c 40 88 74 24 0d 0f b6 02 88 44 24 0c 8b 01 89 44 24 08 85 f6 75 05 c6 44 24 0e 01 <48> 8b 7f 58 48 89 e6 ba 01 00 00 00 e8 08 3c 2a 00 65 48 8b 04 5 +[ 37.510822] RSP: 0018:ffff969442853300 EFLAGS: 00010202 +[ 37.516052] RAX: 0000000000000000 RBX: ffff92db03000000 RCX: ffff969442853358 +[ 37.523185] RDX: ffff969442853368 RSI: 0000000000000001 RDI: 0000000000000000 +[ 37.530322] RBP: 0000000000000001 R08: 00000000000004a7 R09: 00000000000004a5 +[ 37.537453] R10: 0000000000000476 R11: 0000000000000062 R12: ffff92db0ade8000 +[ 37.544589] R13: ffff92da01180ae0 R14: ffff92da011802a8 R15: ffff92db03000000 +[ 37.551725] FS: 0000784a9cdfc6c0(0000) GS:ffff92db2af00000(0000) knlGS:0000000000000000 +[ 37.559814] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 37.565562] CR2: 0000000000000058 CR3: 0000000112b1c000 CR4: 00000000003506f0 +[ 37.572697] Call Trace: +[ 37.575152] +[ 37.577258] ? __die_body+0x66/0xb0 +[ 37.580756] ? page_fault_oops+0x3e7/0x4a0 +[ 37.584861] ? exc_page_fault+0x3e/0xe0 +[ 37.588706] ? exc_page_fault+0x5c/0xe0 +[ 37.592550] ? asm_exc_page_fault+0x22/0x30 +[ 37.596742] ? dmub_hw_lock_mgr_cmd+0x77/0xb0 +[ 37.601107] dcn10_cursor_lock+0x1e1/0x240 +[ 37.605211] program_cursor_attributes+0x81/0x190 +[ 37.609923] commit_planes_for_stream+0x998/0x1ef0 +[ 37.614722] update_planes_and_stream_v2+0x41e/0x5c0 +[ 37.619703] dc_update_planes_and_stream+0x78/0x140 +[ 37.624588] amdgpu_dm_atomic_commit_tail+0x4362/0x49f0 +[ 37.629832] ? srso_return_thunk+0x5/0x5f +[ 37.633847] ? mark_held_locks+0x6d/0xd0 +[ 37.637774] ? _raw_spin_unlock_irq+0x24/0x50 +[ 37.642135] ? srso_return_thunk+0x5/0x5f +[ 37.646148] ? lockdep_hardirqs_on+0x95/0x150 +[ 37.650510] ? srso_return_thunk+0x5/0x5f +[ 37.654522] ? _raw_spin_unlock_irq+0x2f/0x50 +[ 37.658883] ? srso_return_thunk+0x5/0x5f +[ 37.662897] ? wait_for_common+0x186/0x1c0 +[ 37.666998] ? srso_return_thunk+0x5/0x5f +[ 37.671009] ? drm_crtc_next_vblank_start+0xc3/0x170 +[ 37.675983] commit_tail+0xf5/0x1c0 +[ 37.679478] drm_atomic_helper_commit+0x2a2/0x2b0 +[ 37.684186] drm_atomic_commit+0xd6/0x100 +[ 37.688199] ? __cfi___drm_printfn_info+0x10/0x10 +[ 37.692911] drm_atomic_helper_update_plane+0xe5/0x130 +[ 37.698054] drm_mode_cursor_common+0x501/0x670 +[ 37.702600] ? __cfi_drm_mode_cursor_ioctl+0x10/0x10 +[ 37.707572] drm_mode_cursor_ioctl+0x48/0x70 +[ 37.711851] drm_ioctl_kernel+0xf2/0x150 +[ 37.715781] drm_ioctl+0x363/0x590 +[ 37.719189] ? __cfi_drm_mode_cursor_ioctl+0x10/0x10 +[ 37.724165] amdgpu_drm_ioctl+0x41/0x80 +[ 37.728013] __se_sys_ioctl+0x7f/0xd0 +[ 37.731685] do_syscall_64+0x87/0x100 +[ 37.735355] ? vma_end_read+0x12/0xe0 +[ 37.739024] ? srso_return_thunk+0x5/0x5f +[ 37.743041] ? find_held_lock+0x47/0xf0 +[ 37.746884] ? vma_end_read+0x12/0xe0 +[ 37.750552] ? srso_return_thunk+0x5/0x5f +[ 37.754565] ? lock_release+0x1c4/0x2e0 +[ 37.758406] ? vma_end_read+0x12/0xe0 +[ 37.762079] ? exc_page_fault+0x84/0xe0 +[ 37.765921] ? srso_return_thunk+0x5/0x5f +[ 37.769938] ? lockdep_hardirqs_on+0x95/0x150 +[ 37.774303] ? srso_return_thunk+0x5/0x5f +[ 37.778317] ? exc_page_fault+0x84/0xe0 +[ 37.782163] entry_SYSCALL_64_after_hwframe+0x55/0x5d +[ 37.787218] RIP: 0033:0x784aa5ec3059 +[ 37.790803] Code: 04 25 28 00 00 00 48 89 45 c8 31 c0 48 8d 45 10 c7 45 b0 10 00 00 00 48 89 45 b8 48 8d 45 d0 48 89 45 c0 b8 10 00 00 00 0f 05 <41> 89 c0 3d 00 f0 ff ff 77 1d 48 8b 45 c8 64 48 2b 04 25 28 00 0 +[ 37.809553] RSP: 002b:0000784a9cdf90e0 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 +[ 37.817121] RAX: ffffffffffffffda RBX: 0000784a9cdf917c RCX: 0000784aa5ec3059 +[ 37.824256] RDX: 0000784a9cdf917c RSI: 00000000c01c64a3 RDI: 0000000000000020 +[ 37.831391] RBP: 0000784a9cdf9130 R08: 0000000000000100 R09: 0000000000ff0000 +[ 37.838525] R10: 0000000000000000 R11: 0000000000000246 R12: 0000025c01606ed0 +[ 37.845657] R13: 0000025c00030200 R14: 00000000c01c64a3 R15: 0000000000000020 +[ 37.852799] +[ 37.854992] Modules linked in: +[ 37.864546] gsmi: Log Shutdown Reason 0x03 +[ 37.868656] CR2: 0000000000000058 +[ 37.871979] ---[ end trace 0000000000000000 ]--- +[ 37.880976] RIP: 0010:dmub_hw_lock_mgr_cmd+0x77/0xb0 +[ 37.885954] Code: 44 24 0e 00 00 00 00 48 c7 04 24 45 00 00 0c 40 88 74 24 0d 0f b6 02 88 44 24 0c 8b 01 89 44 24 08 85 f6 75 05 c6 44 24 0e 01 <48> 8b 7f 58 48 89 e6 ba 01 00 00 00 e8 08 3c 2a 00 65 48 8b 04 5 +[ 37.904703] RSP: 0018:ffff969442853300 EFLAGS: 00010202 +[ 37.909933] RAX: 0000000000000000 RBX: ffff92db03000000 RCX: ffff969442853358 +[ 37.917068] RDX: ffff969442853368 RSI: 0000000000000001 RDI: 0000000000000000 +[ 37.924201] RBP: 0000000000000001 R08: 00000000000004a7 R09: 00000000000004a5 +[ 37.931336] R10: 0000000000000476 R11: 0000000000000062 R12: ffff92db0ade8000 +[ 37.938469] R13: ffff92da01180ae0 R14: ffff92da011802a8 R15: ffff92db03000000 +[ 37.945602] FS: 0000784a9cdfc6c0(0000) GS:ffff92db2af00000(0000) knlGS:0000000000000000 +[ 37.953689] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 37.959435] CR2: 0000000000000058 CR3: 0000000112b1c000 CR4: 00000000003506f0 +[ 37.966570] Kernel panic - not syncing: Fatal exception +[ 37.971901] Kernel Offset: 0x30200000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff) +[ 37.982840] gsmi: Log Shutdown Reason 0x02 + +Fixes: b5c764d6ed55 ("drm/amd/display: Use HW lock mgr for PSR1") +Signed-off-by: Thadeu Lima de Souza Cascardo +Cc: Sun peng Li +Cc: Tom Chung +Cc: Daniel Wheeler +Cc: Alex Deucher +Reviewed-by: Rodrigo Siqueira +Reviewed-by: Leo Li +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c +index 6e2fce329d738..d37ecfdde4f1b 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c +@@ -63,6 +63,10 @@ void dmub_hw_lock_mgr_inbox0_cmd(struct dc_dmub_srv *dmub_srv, + + bool should_use_dmub_lock(struct dc_link *link) + { ++ /* ASIC doesn't support DMUB */ ++ if (!link->ctx->dmub_srv) ++ return false; ++ + if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) + return true; + +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-fix-an-indent-issue-in-dml21.patch b/queue-6.14/drm-amd-display-fix-an-indent-issue-in-dml21.patch new file mode 100644 index 0000000000..ee6ea67a7d --- /dev/null +++ b/queue-6.14/drm-amd-display-fix-an-indent-issue-in-dml21.patch @@ -0,0 +1,41 @@ +From f2c36536987f5a48589aeb8b5dea82b4a8ba75bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 09:45:12 -0500 +Subject: drm/amd/display: fix an indent issue in DML21 + +From: Aurabindo Pillai + +[ Upstream commit a1addcf8499a566496847f1e36e1cf0b4ad72a26 ] + +Remove extraneous tab and newline in dml2_core_dcn4.c that was +reported by the bot + +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202502211920.txUfwtSj-lkp@intel.com/ +Fixes: 70839da6360 ("drm/amd/display: Add new DCN401 sources") +Signed-off-by: Aurabindo Pillai +Reviewed-by: Harry Wentland +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c +index d68b4567e218a..7216d25c783e6 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c ++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c +@@ -141,9 +141,8 @@ bool core_dcn4_initialize(struct dml2_core_initialize_in_out *in_out) + core->clean_me_up.mode_lib.ip.subvp_fw_processing_delay_us = core_dcn4_ip_caps_base.subvp_pstate_allow_width_us; + core->clean_me_up.mode_lib.ip.subvp_swath_height_margin_lines = core_dcn4_ip_caps_base.subvp_swath_height_margin_lines; + } else { +- memcpy(&core->clean_me_up.mode_lib.ip, &core_dcn4_ip_caps_base, sizeof(struct dml2_core_ip_params)); ++ memcpy(&core->clean_me_up.mode_lib.ip, &core_dcn4_ip_caps_base, sizeof(struct dml2_core_ip_params)); + patch_ip_params_with_ip_caps(&core->clean_me_up.mode_lib.ip, in_out->ip_caps); +- + core->clean_me_up.mode_lib.ip.imall_supported = false; + } + +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-fix-type-mismatch-in-calculatedynami.patch b/queue-6.14/drm-amd-display-fix-type-mismatch-in-calculatedynami.patch new file mode 100644 index 0000000000..7c2efb9d57 --- /dev/null +++ b/queue-6.14/drm-amd-display-fix-type-mismatch-in-calculatedynami.patch @@ -0,0 +1,64 @@ +From d116c2be95e5a2f47da5556fd020a034500600ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 01:28:51 +0500 +Subject: drm/amd/display: fix type mismatch in + CalculateDynamicMetadataParameters() + +From: Vitaliy Shevtsov + +[ Upstream commit c3c584c18c90a024a54716229809ba36424f9660 ] + +There is a type mismatch between what CalculateDynamicMetadataParameters() +takes and what is passed to it. Currently this function accepts several +args as signed long but it's called with unsigned integers and integer. On +some systems where long is 32 bits and one of these unsigned int params is +greater than INT_MAX it may cause passing input params as negative values. + +Fix this by changing these argument types from long to unsigned int and to +int respectively. Also this will align the function's definition with +similar functions in other dcn* drivers. + +Found by Linux Verification Center (linuxtesting.org) with Svace. + +Fixes: 6725a88f88a7 ("drm/amd/display: Add DCN3 DML") +Signed-off-by: Vitaliy Shevtsov +Reviewed-by: Alex Hung +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../amd/display/dc/dml/dcn30/display_mode_vba_30.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +index cee1b351e1058..f1fe49401bc0a 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +@@ -281,10 +281,10 @@ static void CalculateDynamicMetadataParameters( + double DISPCLK, + double DCFClkDeepSleep, + double PixelClock, +- long HTotal, +- long VBlank, +- long DynamicMetadataTransmittedBytes, +- long DynamicMetadataLinesBeforeActiveRequired, ++ unsigned int HTotal, ++ unsigned int VBlank, ++ unsigned int DynamicMetadataTransmittedBytes, ++ int DynamicMetadataLinesBeforeActiveRequired, + int InterlaceEnable, + bool ProgressiveToInterlaceUnitInOPP, + double *Tsetup, +@@ -3265,8 +3265,8 @@ static double CalculateWriteBackDelay( + + + static void CalculateDynamicMetadataParameters(int MaxInterDCNTileRepeaters, double DPPCLK, double DISPCLK, +- double DCFClkDeepSleep, double PixelClock, long HTotal, long VBlank, long DynamicMetadataTransmittedBytes, +- long DynamicMetadataLinesBeforeActiveRequired, int InterlaceEnable, bool ProgressiveToInterlaceUnitInOPP, ++ double DCFClkDeepSleep, double PixelClock, unsigned int HTotal, unsigned int VBlank, unsigned int DynamicMetadataTransmittedBytes, ++ int DynamicMetadataLinesBeforeActiveRequired, int InterlaceEnable, bool ProgressiveToInterlaceUnitInOPP, + double *Tsetup, double *Tdmbf, double *Tdmec, double *Tdmsks) + { + double TotalRepeaterDelayTime = 0; +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-mes-enable-compute-pipes-across-all-mec.patch b/queue-6.14/drm-amdgpu-mes-enable-compute-pipes-across-all-mec.patch new file mode 100644 index 0000000000..25e6f23cb2 --- /dev/null +++ b/queue-6.14/drm-amdgpu-mes-enable-compute-pipes-across-all-mec.patch @@ -0,0 +1,37 @@ +From bb975ce79fc186642298b5c5e036010a2062663b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 10:42:45 -0400 +Subject: drm/amdgpu/mes: enable compute pipes across all MEC + +From: Alex Deucher + +[ Upstream commit a52077b6b6f7d1553d2dc89666f111f89d7418e0 ] + +Enable pipes on both MECs for MES. + +Fixes: 745f46b6a99f ("drm/amdgpu: enable mes v12 self test") +Acked-by: Lijo Lazar +Reviewed-by: Prike Liang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +index c16ad5f790d15..6fa20980a0b15 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +@@ -145,8 +145,7 @@ int amdgpu_mes_init(struct amdgpu_device *adev) + adev->mes.vmid_mask_gfxhub = 0xffffff00; + + for (i = 0; i < AMDGPU_MES_MAX_COMPUTE_PIPES; i++) { +- /* use only 1st MEC pipes */ +- if (i >= adev->gfx.mec.num_pipe_per_mec) ++ if (i >= (adev->gfx.mec.num_pipe_per_mec * adev->gfx.mec.num_mec)) + break; + adev->mes.compute_hqd_mask[i] = 0xc; + } +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-mes-optimize-compute-loop-handling.patch b/queue-6.14/drm-amdgpu-mes-optimize-compute-loop-handling.patch new file mode 100644 index 0000000000..0b9de92cf5 --- /dev/null +++ b/queue-6.14/drm-amdgpu-mes-optimize-compute-loop-handling.patch @@ -0,0 +1,36 @@ +From 5f166fa5514a7a7f18921c2d8f45ca915911628e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 09:56:00 -0400 +Subject: drm/amdgpu/mes: optimize compute loop handling + +From: Alex Deucher + +[ Upstream commit 5608ddf6e94c41a673170b2a7e3aad485fd8b88a ] + +Break when we get to the end of the supported pipes +rather than continuing the loop. + +Reviewed-by: Shaoyun.liu +Signed-off-by: Alex Deucher +Stable-dep-of: a52077b6b6f7 ("drm/amdgpu/mes: enable compute pipes across all MEC") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +index 709c11cbeabd8..c16ad5f790d15 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +@@ -147,7 +147,7 @@ int amdgpu_mes_init(struct amdgpu_device *adev) + for (i = 0; i < AMDGPU_MES_MAX_COMPUTE_PIPES; i++) { + /* use only 1st MEC pipes */ + if (i >= adev->gfx.mec.num_pipe_per_mec) +- continue; ++ break; + adev->mes.compute_hqd_mask[i] = 0xc; + } + +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-refine-smu-send-msg-debug-log-format.patch b/queue-6.14/drm-amdgpu-refine-smu-send-msg-debug-log-format.patch new file mode 100644 index 0000000000..7d2a5207e1 --- /dev/null +++ b/queue-6.14/drm-amdgpu-refine-smu-send-msg-debug-log-format.patch @@ -0,0 +1,39 @@ +From 7fcf2551bc3667ecfbfe884a46484075433bcd15 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 15:46:42 +0800 +Subject: drm/amdgpu: refine smu send msg debug log format + +From: Yang Wang + +[ Upstream commit 8c6631234557515a7567c6251505a98e9793c8a6 ] + +remove unnecessary line breaks. + +[ 51.280860] amdgpu 0000:24:00.0: amdgpu: smu send message: GetEnabledSmuFeaturesHigh(13) param: 0x00000000, resp: 0x00000001, readval: 0x00003763 + +Fixes: 0cd2bc06de72 ("drm/amd/pm: enable amdgpu smu send message log") +Signed-off-by: Yang Wang +Reviewed-by: Kenneth Feng +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +index 9f55207ea9bc3..d834d134ad2b8 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +@@ -459,8 +459,7 @@ int smu_cmn_send_smc_msg_with_param(struct smu_context *smu, + } + if (read_arg) { + smu_cmn_read_arg(smu, read_arg); +- dev_dbg(adev->dev, "smu send message: %s(%d) param: 0x%08x, resp: 0x%08x,\ +- readval: 0x%08x\n", ++ dev_dbg(adev->dev, "smu send message: %s(%d) param: 0x%08x, resp: 0x%08x, readval: 0x%08x\n", + smu_get_message_name(smu, msg), index, param, reg, *read_arg); + } else { + dev_dbg(adev->dev, "smu send message: %s(%d) param: 0x%08x, resp: 0x%08x\n", +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-replace-mutex-with-spinlock-for-rlcg-regi.patch b/queue-6.14/drm-amdgpu-replace-mutex-with-spinlock-for-rlcg-regi.patch new file mode 100644 index 0000000000..0d11f2bad0 --- /dev/null +++ b/queue-6.14/drm-amdgpu-replace-mutex-with-spinlock-for-rlcg-regi.patch @@ -0,0 +1,180 @@ +From 31464bda296652204fcd991cfe72376e570b0684 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 14:22:17 +0530 +Subject: drm/amdgpu: Replace Mutex with Spinlock for RLCG register access to + avoid Priority Inversion in SRIOV +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Srinivasan Shanmugam + +[ Upstream commit dc0297f3198bd60108ccbd167ee5d9fa4af31ed0 ] + +RLCG Register Access is a way for virtual functions to safely access GPU +registers in a virtualized environment., including TLB flushes and +register reads. When multiple threads or VFs try to access the same +registers simultaneously, it can lead to race conditions. By using the +RLCG interface, the driver can serialize access to the registers. This +means that only one thread can access the registers at a time, +preventing conflicts and ensuring that operations are performed +correctly. Additionally, when a low-priority task holds a mutex that a +high-priority task needs, ie., If a thread holding a spinlock tries to +acquire a mutex, it can lead to priority inversion. register access in +amdgpu_virt_rlcg_reg_rw especially in a fast code path is critical. + +The call stack shows that the function amdgpu_virt_rlcg_reg_rw is being +called, which attempts to acquire the mutex. This function is invoked +from amdgpu_sriov_wreg, which in turn is called from +gmc_v11_0_flush_gpu_tlb. + +The [ BUG: Invalid wait context ] indicates that a thread is trying to +acquire a mutex while it is in a context that does not allow it to sleep +(like holding a spinlock). + +Fixes the below: + +[ 253.013423] ============================= +[ 253.013434] [ BUG: Invalid wait context ] +[ 253.013446] 6.12.0-amdstaging-drm-next-lol-050225 #14 Tainted: G U OE +[ 253.013464] ----------------------------- +[ 253.013475] kworker/0:1/10 is trying to lock: +[ 253.013487] ffff9f30542e3cf8 (&adev->virt.rlcg_reg_lock){+.+.}-{3:3}, at: amdgpu_virt_rlcg_reg_rw+0xf6/0x330 [amdgpu] +[ 253.013815] other info that might help us debug this: +[ 253.013827] context-{4:4} +[ 253.013835] 3 locks held by kworker/0:1/10: +[ 253.013847] #0: ffff9f3040050f58 ((wq_completion)events){+.+.}-{0:0}, at: process_one_work+0x3f5/0x680 +[ 253.013877] #1: ffffb789c008be40 ((work_completion)(&wfc.work)){+.+.}-{0:0}, at: process_one_work+0x1d6/0x680 +[ 253.013905] #2: ffff9f3054281838 (&adev->gmc.invalidate_lock){+.+.}-{2:2}, at: gmc_v11_0_flush_gpu_tlb+0x198/0x4f0 [amdgpu] +[ 253.014154] stack backtrace: +[ 253.014164] CPU: 0 UID: 0 PID: 10 Comm: kworker/0:1 Tainted: G U OE 6.12.0-amdstaging-drm-next-lol-050225 #14 +[ 253.014189] Tainted: [U]=USER, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE +[ 253.014203] Hardware name: Microsoft Corporation Virtual Machine/Virtual Machine, BIOS Hyper-V UEFI Release v4.1 11/18/2024 +[ 253.014224] Workqueue: events work_for_cpu_fn +[ 253.014241] Call Trace: +[ 253.014250] +[ 253.014260] dump_stack_lvl+0x9b/0xf0 +[ 253.014275] dump_stack+0x10/0x20 +[ 253.014287] __lock_acquire+0xa47/0x2810 +[ 253.014303] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 253.014321] lock_acquire+0xd1/0x300 +[ 253.014333] ? amdgpu_virt_rlcg_reg_rw+0xf6/0x330 [amdgpu] +[ 253.014562] ? __lock_acquire+0xa6b/0x2810 +[ 253.014578] __mutex_lock+0x85/0xe20 +[ 253.014591] ? amdgpu_virt_rlcg_reg_rw+0xf6/0x330 [amdgpu] +[ 253.014782] ? sched_clock_noinstr+0x9/0x10 +[ 253.014795] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 253.014808] ? local_clock_noinstr+0xe/0xc0 +[ 253.014822] ? amdgpu_virt_rlcg_reg_rw+0xf6/0x330 [amdgpu] +[ 253.015012] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 253.015029] mutex_lock_nested+0x1b/0x30 +[ 253.015044] ? mutex_lock_nested+0x1b/0x30 +[ 253.015057] amdgpu_virt_rlcg_reg_rw+0xf6/0x330 [amdgpu] +[ 253.015249] amdgpu_sriov_wreg+0xc5/0xd0 [amdgpu] +[ 253.015435] gmc_v11_0_flush_gpu_tlb+0x44b/0x4f0 [amdgpu] +[ 253.015667] gfx_v11_0_hw_init+0x499/0x29c0 [amdgpu] +[ 253.015901] ? __pfx_smu_v13_0_update_pcie_parameters+0x10/0x10 [amdgpu] +[ 253.016159] ? srso_alias_return_thunk+0x5/0xfbef5 +[ 253.016173] ? smu_hw_init+0x18d/0x300 [amdgpu] +[ 253.016403] amdgpu_device_init+0x29ad/0x36a0 [amdgpu] +[ 253.016614] amdgpu_driver_load_kms+0x1a/0xc0 [amdgpu] +[ 253.017057] amdgpu_pci_probe+0x1c2/0x660 [amdgpu] +[ 253.017493] local_pci_probe+0x4b/0xb0 +[ 253.017746] work_for_cpu_fn+0x1a/0x30 +[ 253.017995] process_one_work+0x21e/0x680 +[ 253.018248] worker_thread+0x190/0x330 +[ 253.018500] ? __pfx_worker_thread+0x10/0x10 +[ 253.018746] kthread+0xe7/0x120 +[ 253.018988] ? __pfx_kthread+0x10/0x10 +[ 253.019231] ret_from_fork+0x3c/0x60 +[ 253.019468] ? __pfx_kthread+0x10/0x10 +[ 253.019701] ret_from_fork_asm+0x1a/0x30 +[ 253.019939] + +v2: s/spin_trylock/spin_lock_irqsave to be safe (Christian). + +Fixes: e864180ee49b ("drm/amdgpu: Add lock around VF RLCG interface") +Cc: lin cao +Cc: Jingwen Chen +Cc: Victor Skvortsov +Cc: Zhigang Luo +Cc: Christian König +Cc: Alex Deucher +Signed-off-by: Srinivasan Shanmugam +Suggested-by: Alex Deucher +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- + drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 5 +++-- + drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 3 ++- + 3 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index 018dfccd771ba..f5909977eed4b 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -4223,7 +4223,6 @@ int amdgpu_device_init(struct amdgpu_device *adev, + mutex_init(&adev->grbm_idx_mutex); + mutex_init(&adev->mn_lock); + mutex_init(&adev->virt.vf_errors.lock); +- mutex_init(&adev->virt.rlcg_reg_lock); + hash_init(adev->mn_hash); + mutex_init(&adev->psp.mutex); + mutex_init(&adev->notifier_lock); +@@ -4249,6 +4248,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, + spin_lock_init(&adev->se_cac_idx_lock); + spin_lock_init(&adev->audio_endpt_idx_lock); + spin_lock_init(&adev->mm_stats.lock); ++ spin_lock_init(&adev->virt.rlcg_reg_lock); + spin_lock_init(&adev->wb.lock); + + INIT_LIST_HEAD(&adev->reset_list); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +index 0af469ec6fccd..13e5709ea1caa 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +@@ -1017,6 +1017,7 @@ u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 f + void *scratch_reg2; + void *scratch_reg3; + void *spare_int; ++ unsigned long flags; + + if (!adev->gfx.rlc.rlcg_reg_access_supported) { + dev_err(adev->dev, +@@ -1038,7 +1039,7 @@ u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 f + scratch_reg2 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg2; + scratch_reg3 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg3; + +- mutex_lock(&adev->virt.rlcg_reg_lock); ++ spin_lock_irqsave(&adev->virt.rlcg_reg_lock, flags); + + if (reg_access_ctrl->spare_int) + spare_int = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->spare_int; +@@ -1097,7 +1098,7 @@ u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 f + + ret = readl(scratch_reg0); + +- mutex_unlock(&adev->virt.rlcg_reg_lock); ++ spin_unlock_irqrestore(&adev->virt.rlcg_reg_lock, flags); + + return ret; + } +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +index 5381b8d596e62..0ca73343a7689 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +@@ -279,7 +279,8 @@ struct amdgpu_virt { + /* the ucode id to signal the autoload */ + uint32_t autoload_ucode_id; + +- struct mutex rlcg_reg_lock; ++ /* Spinlock to protect access to the RLCG register interface */ ++ spinlock_t rlcg_reg_lock; + + union amd_sriov_ras_caps ras_en_caps; + union amd_sriov_ras_caps ras_telemetry_en_caps; +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-umsch-declare-umsch-firmware.patch b/queue-6.14/drm-amdgpu-umsch-declare-umsch-firmware.patch new file mode 100644 index 0000000000..206502629f --- /dev/null +++ b/queue-6.14/drm-amdgpu-umsch-declare-umsch-firmware.patch @@ -0,0 +1,36 @@ +From 64b3f97d2dc82158e48630e43c0c99d2678efc9f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 16:20:15 -0500 +Subject: drm/amdgpu/umsch: declare umsch firmware + +From: Alex Deucher + +[ Upstream commit fe652becdbfccf265f4cea0eb379418d08c6596a ] + +Needed to be properly picked up for the initrd, etc. + +Fixes: 3488c79beafa ("drm/amdgpu: add initial support for UMSCH") +Reviewed-by: Saleemkhan Jamadar +Signed-off-by: Alex Deucher +Cc: Lang Yu +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c +index 2cfa2447d13e7..78319988b0545 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c +@@ -32,6 +32,8 @@ + #include "amdgpu_umsch_mm.h" + #include "umsch_mm_v4_0.h" + ++MODULE_FIRMWARE("amdgpu/umsch_mm_4_0_0.bin"); ++ + int amdgpu_umsch_mm_submit_pkt(struct amdgpu_umsch_mm *umsch, void *pkt, int ndws) + { + struct amdgpu_ring *ring = &umsch->ring; +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-umsch-fix-ucode-check.patch b/queue-6.14/drm-amdgpu-umsch-fix-ucode-check.patch new file mode 100644 index 0000000000..4a53e82fe0 --- /dev/null +++ b/queue-6.14/drm-amdgpu-umsch-fix-ucode-check.patch @@ -0,0 +1,43 @@ +From fac711527dddba4b881586e41625a3df426b3a9d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 16:31:43 -0500 +Subject: drm/amdgpu/umsch: fix ucode check + +From: Alex Deucher + +[ Upstream commit c917e39cbdcd9fff421184db6cc461cc58d52c17 ] + +Return an error if the IP version doesn't match otherwise +we end up passing a NULL string to amdgpu_ucode_request. +We should never hit this in practice today since we only +enable the umsch code on the supported IP versions, but +add a check to be safe. + +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202502130406.iWQ0eBug-lkp@intel.com/ +Fixes: 020620424b27 ("drm/amd: Use a constant format string for amdgpu_ucode_request") +Reviewed-by: Saleemkhan Jamadar +Signed-off-by: Alex Deucher +Cc: Arnd Bergmann +Cc: Lang Yu +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c +index 78319988b0545..a7f2648245ec0 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c +@@ -129,7 +129,7 @@ int amdgpu_umsch_mm_init_microcode(struct amdgpu_umsch_mm *umsch) + fw_name = "amdgpu/umsch_mm_4_0_0.bin"; + break; + default: +- break; ++ return -EINVAL; + } + + r = amdgpu_ucode_request(adev, &adev->umsch_mm.fw, AMDGPU_UCODE_REQUIRED, +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-umsch-remove-vpe-test-from-umsch.patch b/queue-6.14/drm-amdgpu-umsch-remove-vpe-test-from-umsch.patch new file mode 100644 index 0000000000..a836d7dbb0 --- /dev/null +++ b/queue-6.14/drm-amdgpu-umsch-remove-vpe-test-from-umsch.patch @@ -0,0 +1,504 @@ +From 8b90ea91c46812426cd113658d7f1e9e6c45ae80 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Dec 2024 17:27:44 +0530 +Subject: drm/amdgpu/umsch: remove vpe test from umsch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Saleemkhan Jamadar + +[ Upstream commit b0bebbe4ea2a25937d341fa1f2ab2cd8ce339cad ] + +current test is more intrusive for user queue test + +Signed-off-by: Saleemkhan Jamadar +Suggested-by: Christian Koenig +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Stable-dep-of: fe652becdbfc ("drm/amdgpu/umsch: declare umsch firmware") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c | 459 +------------------ + 1 file changed, 1 insertion(+), 458 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c +index dde15c6a96e1a..2cfa2447d13e7 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c +@@ -32,463 +32,6 @@ + #include "amdgpu_umsch_mm.h" + #include "umsch_mm_v4_0.h" + +-struct umsch_mm_test_ctx_data { +- uint8_t process_csa[PAGE_SIZE]; +- uint8_t vpe_ctx_csa[PAGE_SIZE]; +- uint8_t vcn_ctx_csa[PAGE_SIZE]; +-}; +- +-struct umsch_mm_test_mqd_data { +- uint8_t vpe_mqd[PAGE_SIZE]; +- uint8_t vcn_mqd[PAGE_SIZE]; +-}; +- +-struct umsch_mm_test_ring_data { +- uint8_t vpe_ring[PAGE_SIZE]; +- uint8_t vpe_ib[PAGE_SIZE]; +- uint8_t vcn_ring[PAGE_SIZE]; +- uint8_t vcn_ib[PAGE_SIZE]; +-}; +- +-struct umsch_mm_test_queue_info { +- uint64_t mqd_addr; +- uint64_t csa_addr; +- uint32_t doorbell_offset_0; +- uint32_t doorbell_offset_1; +- enum UMSCH_SWIP_ENGINE_TYPE engine; +-}; +- +-struct umsch_mm_test { +- struct amdgpu_bo *ctx_data_obj; +- uint64_t ctx_data_gpu_addr; +- uint32_t *ctx_data_cpu_addr; +- +- struct amdgpu_bo *mqd_data_obj; +- uint64_t mqd_data_gpu_addr; +- uint32_t *mqd_data_cpu_addr; +- +- struct amdgpu_bo *ring_data_obj; +- uint64_t ring_data_gpu_addr; +- uint32_t *ring_data_cpu_addr; +- +- +- struct amdgpu_vm *vm; +- struct amdgpu_bo_va *bo_va; +- uint32_t pasid; +- uint32_t vm_cntx_cntl; +- uint32_t num_queues; +-}; +- +-static int map_ring_data(struct amdgpu_device *adev, struct amdgpu_vm *vm, +- struct amdgpu_bo *bo, struct amdgpu_bo_va **bo_va, +- uint64_t addr, uint32_t size) +-{ +- struct amdgpu_sync sync; +- struct drm_exec exec; +- int r; +- +- amdgpu_sync_create(&sync); +- +- drm_exec_init(&exec, 0, 0); +- drm_exec_until_all_locked(&exec) { +- r = drm_exec_lock_obj(&exec, &bo->tbo.base); +- drm_exec_retry_on_contention(&exec); +- if (unlikely(r)) +- goto error_fini_exec; +- +- r = amdgpu_vm_lock_pd(vm, &exec, 0); +- drm_exec_retry_on_contention(&exec); +- if (unlikely(r)) +- goto error_fini_exec; +- } +- +- *bo_va = amdgpu_vm_bo_add(adev, vm, bo); +- if (!*bo_va) { +- r = -ENOMEM; +- goto error_fini_exec; +- } +- +- r = amdgpu_vm_bo_map(adev, *bo_va, addr, 0, size, +- AMDGPU_PTE_READABLE | AMDGPU_PTE_WRITEABLE | +- AMDGPU_PTE_EXECUTABLE); +- +- if (r) +- goto error_del_bo_va; +- +- +- r = amdgpu_vm_bo_update(adev, *bo_va, false); +- if (r) +- goto error_del_bo_va; +- +- amdgpu_sync_fence(&sync, (*bo_va)->last_pt_update); +- +- r = amdgpu_vm_update_pdes(adev, vm, false); +- if (r) +- goto error_del_bo_va; +- +- amdgpu_sync_fence(&sync, vm->last_update); +- +- amdgpu_sync_wait(&sync, false); +- drm_exec_fini(&exec); +- +- amdgpu_sync_free(&sync); +- +- return 0; +- +-error_del_bo_va: +- amdgpu_vm_bo_del(adev, *bo_va); +- amdgpu_sync_free(&sync); +- +-error_fini_exec: +- drm_exec_fini(&exec); +- amdgpu_sync_free(&sync); +- return r; +-} +- +-static int unmap_ring_data(struct amdgpu_device *adev, struct amdgpu_vm *vm, +- struct amdgpu_bo *bo, struct amdgpu_bo_va *bo_va, +- uint64_t addr) +-{ +- struct drm_exec exec; +- long r; +- +- drm_exec_init(&exec, 0, 0); +- drm_exec_until_all_locked(&exec) { +- r = drm_exec_lock_obj(&exec, &bo->tbo.base); +- drm_exec_retry_on_contention(&exec); +- if (unlikely(r)) +- goto out_unlock; +- +- r = amdgpu_vm_lock_pd(vm, &exec, 0); +- drm_exec_retry_on_contention(&exec); +- if (unlikely(r)) +- goto out_unlock; +- } +- +- +- r = amdgpu_vm_bo_unmap(adev, bo_va, addr); +- if (r) +- goto out_unlock; +- +- amdgpu_vm_bo_del(adev, bo_va); +- +-out_unlock: +- drm_exec_fini(&exec); +- +- return r; +-} +- +-static void setup_vpe_queue(struct amdgpu_device *adev, +- struct umsch_mm_test *test, +- struct umsch_mm_test_queue_info *qinfo) +-{ +- struct MQD_INFO *mqd = (struct MQD_INFO *)test->mqd_data_cpu_addr; +- uint64_t ring_gpu_addr = test->ring_data_gpu_addr; +- +- mqd->rb_base_lo = (ring_gpu_addr >> 8); +- mqd->rb_base_hi = (ring_gpu_addr >> 40); +- mqd->rb_size = PAGE_SIZE / 4; +- mqd->wptr_val = 0; +- mqd->rptr_val = 0; +- mqd->unmapped = 1; +- +- if (adev->vpe.collaborate_mode) +- memcpy(++mqd, test->mqd_data_cpu_addr, sizeof(struct MQD_INFO)); +- +- qinfo->mqd_addr = test->mqd_data_gpu_addr; +- qinfo->csa_addr = test->ctx_data_gpu_addr + +- offsetof(struct umsch_mm_test_ctx_data, vpe_ctx_csa); +- qinfo->doorbell_offset_0 = 0; +- qinfo->doorbell_offset_1 = 0; +-} +- +-static void setup_vcn_queue(struct amdgpu_device *adev, +- struct umsch_mm_test *test, +- struct umsch_mm_test_queue_info *qinfo) +-{ +-} +- +-static int add_test_queue(struct amdgpu_device *adev, +- struct umsch_mm_test *test, +- struct umsch_mm_test_queue_info *qinfo) +-{ +- struct umsch_mm_add_queue_input queue_input = {}; +- int r; +- +- queue_input.process_id = test->pasid; +- queue_input.page_table_base_addr = amdgpu_gmc_pd_addr(test->vm->root.bo); +- +- queue_input.process_va_start = 0; +- queue_input.process_va_end = (adev->vm_manager.max_pfn - 1) << AMDGPU_GPU_PAGE_SHIFT; +- +- queue_input.process_quantum = 100000; /* 10ms */ +- queue_input.process_csa_addr = test->ctx_data_gpu_addr + +- offsetof(struct umsch_mm_test_ctx_data, process_csa); +- +- queue_input.context_quantum = 10000; /* 1ms */ +- queue_input.context_csa_addr = qinfo->csa_addr; +- +- queue_input.inprocess_context_priority = CONTEXT_PRIORITY_LEVEL_NORMAL; +- queue_input.context_global_priority_level = CONTEXT_PRIORITY_LEVEL_NORMAL; +- queue_input.doorbell_offset_0 = qinfo->doorbell_offset_0; +- queue_input.doorbell_offset_1 = qinfo->doorbell_offset_1; +- +- queue_input.engine_type = qinfo->engine; +- queue_input.mqd_addr = qinfo->mqd_addr; +- queue_input.vm_context_cntl = test->vm_cntx_cntl; +- +- amdgpu_umsch_mm_lock(&adev->umsch_mm); +- r = adev->umsch_mm.funcs->add_queue(&adev->umsch_mm, &queue_input); +- amdgpu_umsch_mm_unlock(&adev->umsch_mm); +- if (r) +- return r; +- +- return 0; +-} +- +-static int remove_test_queue(struct amdgpu_device *adev, +- struct umsch_mm_test *test, +- struct umsch_mm_test_queue_info *qinfo) +-{ +- struct umsch_mm_remove_queue_input queue_input = {}; +- int r; +- +- queue_input.doorbell_offset_0 = qinfo->doorbell_offset_0; +- queue_input.doorbell_offset_1 = qinfo->doorbell_offset_1; +- queue_input.context_csa_addr = qinfo->csa_addr; +- +- amdgpu_umsch_mm_lock(&adev->umsch_mm); +- r = adev->umsch_mm.funcs->remove_queue(&adev->umsch_mm, &queue_input); +- amdgpu_umsch_mm_unlock(&adev->umsch_mm); +- if (r) +- return r; +- +- return 0; +-} +- +-static int submit_vpe_queue(struct amdgpu_device *adev, struct umsch_mm_test *test) +-{ +- struct MQD_INFO *mqd = (struct MQD_INFO *)test->mqd_data_cpu_addr; +- uint32_t *ring = test->ring_data_cpu_addr + +- offsetof(struct umsch_mm_test_ring_data, vpe_ring) / 4; +- uint32_t *ib = test->ring_data_cpu_addr + +- offsetof(struct umsch_mm_test_ring_data, vpe_ib) / 4; +- uint64_t ib_gpu_addr = test->ring_data_gpu_addr + +- offsetof(struct umsch_mm_test_ring_data, vpe_ib); +- uint32_t *fence = ib + 2048 / 4; +- uint64_t fence_gpu_addr = ib_gpu_addr + 2048; +- const uint32_t test_pattern = 0xdeadbeef; +- int i; +- +- ib[0] = VPE_CMD_HEADER(VPE_CMD_OPCODE_FENCE, 0); +- ib[1] = lower_32_bits(fence_gpu_addr); +- ib[2] = upper_32_bits(fence_gpu_addr); +- ib[3] = test_pattern; +- +- ring[0] = VPE_CMD_HEADER(VPE_CMD_OPCODE_INDIRECT, 0); +- ring[1] = (ib_gpu_addr & 0xffffffe0); +- ring[2] = upper_32_bits(ib_gpu_addr); +- ring[3] = 4; +- ring[4] = 0; +- ring[5] = 0; +- +- mqd->wptr_val = (6 << 2); +- if (adev->vpe.collaborate_mode) +- (++mqd)->wptr_val = (6 << 2); +- +- WDOORBELL32(adev->umsch_mm.agdb_index[CONTEXT_PRIORITY_LEVEL_NORMAL], mqd->wptr_val); +- +- for (i = 0; i < adev->usec_timeout; i++) { +- if (*fence == test_pattern) +- return 0; +- udelay(1); +- } +- +- dev_err(adev->dev, "vpe queue submission timeout\n"); +- +- return -ETIMEDOUT; +-} +- +-static int submit_vcn_queue(struct amdgpu_device *adev, struct umsch_mm_test *test) +-{ +- return 0; +-} +- +-static int setup_umsch_mm_test(struct amdgpu_device *adev, +- struct umsch_mm_test *test) +-{ +- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)]; +- int r; +- +- test->vm_cntx_cntl = hub->vm_cntx_cntl; +- +- test->vm = kzalloc(sizeof(*test->vm), GFP_KERNEL); +- if (!test->vm) { +- r = -ENOMEM; +- return r; +- } +- +- r = amdgpu_vm_init(adev, test->vm, -1); +- if (r) +- goto error_free_vm; +- +- r = amdgpu_pasid_alloc(16); +- if (r < 0) +- goto error_fini_vm; +- test->pasid = r; +- +- r = amdgpu_bo_create_kernel(adev, sizeof(struct umsch_mm_test_ctx_data), +- PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT, +- &test->ctx_data_obj, +- &test->ctx_data_gpu_addr, +- (void **)&test->ctx_data_cpu_addr); +- if (r) +- goto error_free_pasid; +- +- memset(test->ctx_data_cpu_addr, 0, sizeof(struct umsch_mm_test_ctx_data)); +- +- r = amdgpu_bo_create_kernel(adev, PAGE_SIZE, +- PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT, +- &test->mqd_data_obj, +- &test->mqd_data_gpu_addr, +- (void **)&test->mqd_data_cpu_addr); +- if (r) +- goto error_free_ctx_data_obj; +- +- memset(test->mqd_data_cpu_addr, 0, PAGE_SIZE); +- +- r = amdgpu_bo_create_kernel(adev, sizeof(struct umsch_mm_test_ring_data), +- PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT, +- &test->ring_data_obj, +- NULL, +- (void **)&test->ring_data_cpu_addr); +- if (r) +- goto error_free_mqd_data_obj; +- +- memset(test->ring_data_cpu_addr, 0, sizeof(struct umsch_mm_test_ring_data)); +- +- test->ring_data_gpu_addr = AMDGPU_VA_RESERVED_BOTTOM; +- r = map_ring_data(adev, test->vm, test->ring_data_obj, &test->bo_va, +- test->ring_data_gpu_addr, sizeof(struct umsch_mm_test_ring_data)); +- if (r) +- goto error_free_ring_data_obj; +- +- return 0; +- +-error_free_ring_data_obj: +- amdgpu_bo_free_kernel(&test->ring_data_obj, NULL, +- (void **)&test->ring_data_cpu_addr); +-error_free_mqd_data_obj: +- amdgpu_bo_free_kernel(&test->mqd_data_obj, &test->mqd_data_gpu_addr, +- (void **)&test->mqd_data_cpu_addr); +-error_free_ctx_data_obj: +- amdgpu_bo_free_kernel(&test->ctx_data_obj, &test->ctx_data_gpu_addr, +- (void **)&test->ctx_data_cpu_addr); +-error_free_pasid: +- amdgpu_pasid_free(test->pasid); +-error_fini_vm: +- amdgpu_vm_fini(adev, test->vm); +-error_free_vm: +- kfree(test->vm); +- +- return r; +-} +- +-static void cleanup_umsch_mm_test(struct amdgpu_device *adev, +- struct umsch_mm_test *test) +-{ +- unmap_ring_data(adev, test->vm, test->ring_data_obj, +- test->bo_va, test->ring_data_gpu_addr); +- amdgpu_bo_free_kernel(&test->mqd_data_obj, &test->mqd_data_gpu_addr, +- (void **)&test->mqd_data_cpu_addr); +- amdgpu_bo_free_kernel(&test->ring_data_obj, NULL, +- (void **)&test->ring_data_cpu_addr); +- amdgpu_bo_free_kernel(&test->ctx_data_obj, &test->ctx_data_gpu_addr, +- (void **)&test->ctx_data_cpu_addr); +- amdgpu_pasid_free(test->pasid); +- amdgpu_vm_fini(adev, test->vm); +- kfree(test->vm); +-} +- +-static int setup_test_queues(struct amdgpu_device *adev, +- struct umsch_mm_test *test, +- struct umsch_mm_test_queue_info *qinfo) +-{ +- int i, r; +- +- for (i = 0; i < test->num_queues; i++) { +- if (qinfo[i].engine == UMSCH_SWIP_ENGINE_TYPE_VPE) +- setup_vpe_queue(adev, test, &qinfo[i]); +- else +- setup_vcn_queue(adev, test, &qinfo[i]); +- +- r = add_test_queue(adev, test, &qinfo[i]); +- if (r) +- return r; +- } +- +- return 0; +-} +- +-static int submit_test_queues(struct amdgpu_device *adev, +- struct umsch_mm_test *test, +- struct umsch_mm_test_queue_info *qinfo) +-{ +- int i, r; +- +- for (i = 0; i < test->num_queues; i++) { +- if (qinfo[i].engine == UMSCH_SWIP_ENGINE_TYPE_VPE) +- r = submit_vpe_queue(adev, test); +- else +- r = submit_vcn_queue(adev, test); +- if (r) +- return r; +- } +- +- return 0; +-} +- +-static void cleanup_test_queues(struct amdgpu_device *adev, +- struct umsch_mm_test *test, +- struct umsch_mm_test_queue_info *qinfo) +-{ +- int i; +- +- for (i = 0; i < test->num_queues; i++) +- remove_test_queue(adev, test, &qinfo[i]); +-} +- +-static int umsch_mm_test(struct amdgpu_device *adev) +-{ +- struct umsch_mm_test_queue_info qinfo[] = { +- { .engine = UMSCH_SWIP_ENGINE_TYPE_VPE }, +- }; +- struct umsch_mm_test test = { .num_queues = ARRAY_SIZE(qinfo) }; +- int r; +- +- r = setup_umsch_mm_test(adev, &test); +- if (r) +- return r; +- +- r = setup_test_queues(adev, &test, qinfo); +- if (r) +- goto cleanup; +- +- r = submit_test_queues(adev, &test, qinfo); +- if (r) +- goto cleanup; +- +- cleanup_test_queues(adev, &test, qinfo); +- cleanup_umsch_mm_test(adev, &test); +- +- return 0; +- +-cleanup: +- cleanup_test_queues(adev, &test, qinfo); +- cleanup_umsch_mm_test(adev, &test); +- return r; +-} +- + int amdgpu_umsch_mm_submit_pkt(struct amdgpu_umsch_mm *umsch, void *pkt, int ndws) + { + struct amdgpu_ring *ring = &umsch->ring; +@@ -792,7 +335,7 @@ static int umsch_mm_late_init(struct amdgpu_ip_block *ip_block) + if (amdgpu_in_reset(adev) || adev->in_s0ix || adev->in_suspend) + return 0; + +- return umsch_mm_test(adev); ++ return 0; + } + + static int umsch_mm_sw_init(struct amdgpu_ip_block *ip_block) +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-vcn5.0.1-use-correct-dpm-helper.patch b/queue-6.14/drm-amdgpu-vcn5.0.1-use-correct-dpm-helper.patch new file mode 100644 index 0000000000..dbe257bfb2 --- /dev/null +++ b/queue-6.14/drm-amdgpu-vcn5.0.1-use-correct-dpm-helper.patch @@ -0,0 +1,57 @@ +From 626a456207c1f23d550513377a858e526f94e985 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 17:45:14 -0500 +Subject: drm/amdgpu/vcn5.0.1: use correct dpm helper + +From: Alex Deucher + +[ Upstream commit 0487f50310cfeec1bb4480a67294fc7081c5ed22 ] + +The VCN and UVD helpers were split in +commit ff69bba05f08 ("drm/amd/pm: add inst to dpm_set_powergating_by_smu") +However, this happened in parallel to the vcn 5.0.1 +development so it was missed there. + +Fixes: 346492f30ce3 ("drm/amdgpu: Add VCN_5_0_1 support") +Reviewed-by: Lijo Lazar +Signed-off-by: Alex Deucher +Cc: Sonny Jiang +Cc: Boyuan Zhang +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +index 8b463c977d08f..8b0b3739a5377 100644 +--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c ++++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +@@ -575,8 +575,10 @@ static int vcn_v5_0_1_start(struct amdgpu_device *adev) + uint32_t tmp; + int i, j, k, r, vcn_inst; + +- if (adev->pm.dpm_enabled) +- amdgpu_dpm_enable_uvd(adev, true); ++ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { ++ if (adev->pm.dpm_enabled) ++ amdgpu_dpm_enable_vcn(adev, true, i); ++ } + + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { + fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; +@@ -816,8 +818,10 @@ static int vcn_v5_0_1_stop(struct amdgpu_device *adev) + WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0); + } + +- if (adev->pm.dpm_enabled) +- amdgpu_dpm_enable_uvd(adev, false); ++ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { ++ if (adev->pm.dpm_enabled) ++ amdgpu_dpm_enable_vcn(adev, false, i); ++ } + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/drm-amdkfd-fix-circular-locking-dependency-in-svm_ra.patch b/queue-6.14/drm-amdkfd-fix-circular-locking-dependency-in-svm_ra.patch new file mode 100644 index 0000000000..f829f51104 --- /dev/null +++ b/queue-6.14/drm-amdkfd-fix-circular-locking-dependency-in-svm_ra.patch @@ -0,0 +1,279 @@ +From 71325927c8d8085cd03afbd6c80ba828c855d064 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 13:46:32 +0530 +Subject: drm/amdkfd: Fix Circular Locking Dependency in + 'svm_range_cpu_invalidate_pagetables' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Srinivasan Shanmugam + +[ Upstream commit fddc45026311c05a5355fd34b9dc0a1d7eaef4a2 ] + +This commit addresses a circular locking dependency in the +svm_range_cpu_invalidate_pagetables function. The function previously +held a lock while determining whether to perform an unmap or eviction +operation, which could lead to deadlocks. + +Fixes the below: + +[ 223.418794] ====================================================== +[ 223.418820] WARNING: possible circular locking dependency detected +[ 223.418845] 6.12.0-amdstaging-drm-next-lol-050225 #14 Tainted: G U OE +[ 223.418869] ------------------------------------------------------ +[ 223.418889] kfdtest/3939 is trying to acquire lock: +[ 223.418906] ffff8957552eae38 (&dqm->lock_hidden){+.+.}-{3:3}, at: evict_process_queues_cpsch+0x43/0x210 [amdgpu] +[ 223.419302] + but task is already holding lock: +[ 223.419303] ffff8957556b83b0 (&prange->lock){+.+.}-{3:3}, at: svm_range_cpu_invalidate_pagetables+0x9d/0x850 [amdgpu] +[ 223.419447] Console: switching to colour dummy device 80x25 +[ 223.419477] [IGT] amd_basic: executing +[ 223.419599] + which lock already depends on the new lock. + +[ 223.419611] + the existing dependency chain (in reverse order) is: +[ 223.419621] + -> #2 (&prange->lock){+.+.}-{3:3}: +[ 223.419636] __mutex_lock+0x85/0xe20 +[ 223.419647] mutex_lock_nested+0x1b/0x30 +[ 223.419656] svm_range_validate_and_map+0x2f1/0x15b0 [amdgpu] +[ 223.419954] svm_range_set_attr+0xe8c/0x1710 [amdgpu] +[ 223.420236] svm_ioctl+0x46/0x50 [amdgpu] +[ 223.420503] kfd_ioctl_svm+0x50/0x90 [amdgpu] +[ 223.420763] kfd_ioctl+0x409/0x6d0 [amdgpu] +[ 223.421024] __x64_sys_ioctl+0x95/0xd0 +[ 223.421036] x64_sys_call+0x1205/0x20d0 +[ 223.421047] do_syscall_64+0x87/0x140 +[ 223.421056] entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 223.421068] + -> #1 (reservation_ww_class_mutex){+.+.}-{3:3}: +[ 223.421084] __ww_mutex_lock.constprop.0+0xab/0x1560 +[ 223.421095] ww_mutex_lock+0x2b/0x90 +[ 223.421103] amdgpu_amdkfd_alloc_gtt_mem+0xcc/0x2b0 [amdgpu] +[ 223.421361] add_queue_mes+0x3bc/0x440 [amdgpu] +[ 223.421623] unhalt_cpsch+0x1ae/0x240 [amdgpu] +[ 223.421888] kgd2kfd_start_sched+0x5e/0xd0 [amdgpu] +[ 223.422148] amdgpu_amdkfd_start_sched+0x3d/0x50 [amdgpu] +[ 223.422414] amdgpu_gfx_enforce_isolation_handler+0x132/0x270 [amdgpu] +[ 223.422662] process_one_work+0x21e/0x680 +[ 223.422673] worker_thread+0x190/0x330 +[ 223.422682] kthread+0xe7/0x120 +[ 223.422690] ret_from_fork+0x3c/0x60 +[ 223.422699] ret_from_fork_asm+0x1a/0x30 +[ 223.422708] + -> #0 (&dqm->lock_hidden){+.+.}-{3:3}: +[ 223.422723] __lock_acquire+0x16f4/0x2810 +[ 223.422734] lock_acquire+0xd1/0x300 +[ 223.422742] __mutex_lock+0x85/0xe20 +[ 223.422751] mutex_lock_nested+0x1b/0x30 +[ 223.422760] evict_process_queues_cpsch+0x43/0x210 [amdgpu] +[ 223.423025] kfd_process_evict_queues+0x8a/0x1d0 [amdgpu] +[ 223.423285] kgd2kfd_quiesce_mm+0x43/0x90 [amdgpu] +[ 223.423540] svm_range_cpu_invalidate_pagetables+0x4a7/0x850 [amdgpu] +[ 223.423807] __mmu_notifier_invalidate_range_start+0x1f5/0x250 +[ 223.423819] copy_page_range+0x1e94/0x1ea0 +[ 223.423829] copy_process+0x172f/0x2ad0 +[ 223.423839] kernel_clone+0x9c/0x3f0 +[ 223.423847] __do_sys_clone+0x66/0x90 +[ 223.423856] __x64_sys_clone+0x25/0x30 +[ 223.423864] x64_sys_call+0x1d7c/0x20d0 +[ 223.423872] do_syscall_64+0x87/0x140 +[ 223.423880] entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 223.423891] + other info that might help us debug this: + +[ 223.423903] Chain exists of: + &dqm->lock_hidden --> reservation_ww_class_mutex --> &prange->lock + +[ 223.423926] Possible unsafe locking scenario: + +[ 223.423935] CPU0 CPU1 +[ 223.423942] ---- ---- +[ 223.423949] lock(&prange->lock); +[ 223.423958] lock(reservation_ww_class_mutex); +[ 223.423970] lock(&prange->lock); +[ 223.423981] lock(&dqm->lock_hidden); +[ 223.423990] + *** DEADLOCK *** + +[ 223.423999] 5 locks held by kfdtest/3939: +[ 223.424006] #0: ffffffffb82b4fc0 (dup_mmap_sem){.+.+}-{0:0}, at: copy_process+0x1387/0x2ad0 +[ 223.424026] #1: ffff89575eda81b0 (&mm->mmap_lock){++++}-{3:3}, at: copy_process+0x13a8/0x2ad0 +[ 223.424046] #2: ffff89575edaf3b0 (&mm->mmap_lock/1){+.+.}-{3:3}, at: copy_process+0x13e4/0x2ad0 +[ 223.424066] #3: ffffffffb82e76e0 (mmu_notifier_invalidate_range_start){+.+.}-{0:0}, at: copy_page_range+0x1cea/0x1ea0 +[ 223.424088] #4: ffff8957556b83b0 (&prange->lock){+.+.}-{3:3}, at: svm_range_cpu_invalidate_pagetables+0x9d/0x850 [amdgpu] +[ 223.424365] + stack backtrace: +[ 223.424374] CPU: 0 UID: 0 PID: 3939 Comm: kfdtest Tainted: G U OE 6.12.0-amdstaging-drm-next-lol-050225 #14 +[ 223.424392] Tainted: [U]=USER, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE +[ 223.424401] Hardware name: Gigabyte Technology Co., Ltd. X570 AORUS PRO WIFI/X570 AORUS PRO WIFI, BIOS F36a 02/16/2022 +[ 223.424416] Call Trace: +[ 223.424423] +[ 223.424430] dump_stack_lvl+0x9b/0xf0 +[ 223.424441] dump_stack+0x10/0x20 +[ 223.424449] print_circular_bug+0x275/0x350 +[ 223.424460] check_noncircular+0x157/0x170 +[ 223.424469] ? __bfs+0xfd/0x2c0 +[ 223.424481] __lock_acquire+0x16f4/0x2810 +[ 223.424490] ? srso_return_thunk+0x5/0x5f +[ 223.424505] lock_acquire+0xd1/0x300 +[ 223.424514] ? evict_process_queues_cpsch+0x43/0x210 [amdgpu] +[ 223.424783] __mutex_lock+0x85/0xe20 +[ 223.424792] ? evict_process_queues_cpsch+0x43/0x210 [amdgpu] +[ 223.425058] ? srso_return_thunk+0x5/0x5f +[ 223.425067] ? mark_held_locks+0x54/0x90 +[ 223.425076] ? evict_process_queues_cpsch+0x43/0x210 [amdgpu] +[ 223.425339] ? srso_return_thunk+0x5/0x5f +[ 223.425350] mutex_lock_nested+0x1b/0x30 +[ 223.425358] ? mutex_lock_nested+0x1b/0x30 +[ 223.425367] evict_process_queues_cpsch+0x43/0x210 [amdgpu] +[ 223.425631] kfd_process_evict_queues+0x8a/0x1d0 [amdgpu] +[ 223.425893] kgd2kfd_quiesce_mm+0x43/0x90 [amdgpu] +[ 223.426156] svm_range_cpu_invalidate_pagetables+0x4a7/0x850 [amdgpu] +[ 223.426423] ? srso_return_thunk+0x5/0x5f +[ 223.426436] __mmu_notifier_invalidate_range_start+0x1f5/0x250 +[ 223.426450] copy_page_range+0x1e94/0x1ea0 +[ 223.426461] ? srso_return_thunk+0x5/0x5f +[ 223.426474] ? srso_return_thunk+0x5/0x5f +[ 223.426484] ? lock_acquire+0xd1/0x300 +[ 223.426494] ? copy_process+0x1718/0x2ad0 +[ 223.426502] ? srso_return_thunk+0x5/0x5f +[ 223.426510] ? sched_clock_noinstr+0x9/0x10 +[ 223.426519] ? local_clock_noinstr+0xe/0xc0 +[ 223.426528] ? copy_process+0x1718/0x2ad0 +[ 223.426537] ? srso_return_thunk+0x5/0x5f +[ 223.426550] copy_process+0x172f/0x2ad0 +[ 223.426569] kernel_clone+0x9c/0x3f0 +[ 223.426577] ? __schedule+0x4c9/0x1b00 +[ 223.426586] ? srso_return_thunk+0x5/0x5f +[ 223.426594] ? sched_clock_noinstr+0x9/0x10 +[ 223.426602] ? srso_return_thunk+0x5/0x5f +[ 223.426610] ? local_clock_noinstr+0xe/0xc0 +[ 223.426619] ? schedule+0x107/0x1a0 +[ 223.426629] __do_sys_clone+0x66/0x90 +[ 223.426643] __x64_sys_clone+0x25/0x30 +[ 223.426652] x64_sys_call+0x1d7c/0x20d0 +[ 223.426661] do_syscall_64+0x87/0x140 +[ 223.426671] ? srso_return_thunk+0x5/0x5f +[ 223.426679] ? common_nsleep+0x44/0x50 +[ 223.426690] ? srso_return_thunk+0x5/0x5f +[ 223.426698] ? trace_hardirqs_off+0x52/0xd0 +[ 223.426709] ? srso_return_thunk+0x5/0x5f +[ 223.426717] ? syscall_exit_to_user_mode+0xcc/0x200 +[ 223.426727] ? srso_return_thunk+0x5/0x5f +[ 223.426736] ? do_syscall_64+0x93/0x140 +[ 223.426748] ? srso_return_thunk+0x5/0x5f +[ 223.426756] ? up_write+0x1c/0x1e0 +[ 223.426765] ? srso_return_thunk+0x5/0x5f +[ 223.426775] ? srso_return_thunk+0x5/0x5f +[ 223.426783] ? trace_hardirqs_off+0x52/0xd0 +[ 223.426792] ? srso_return_thunk+0x5/0x5f +[ 223.426800] ? syscall_exit_to_user_mode+0xcc/0x200 +[ 223.426810] ? srso_return_thunk+0x5/0x5f +[ 223.426818] ? do_syscall_64+0x93/0x140 +[ 223.426826] ? syscall_exit_to_user_mode+0xcc/0x200 +[ 223.426836] ? srso_return_thunk+0x5/0x5f +[ 223.426844] ? do_syscall_64+0x93/0x140 +[ 223.426853] ? srso_return_thunk+0x5/0x5f +[ 223.426861] ? irqentry_exit+0x6b/0x90 +[ 223.426869] ? srso_return_thunk+0x5/0x5f +[ 223.426877] ? exc_page_fault+0xa7/0x2c0 +[ 223.426888] entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 223.426898] RIP: 0033:0x7f46758eab57 +[ 223.426906] Code: ba 04 00 f3 0f 1e fa 64 48 8b 04 25 10 00 00 00 45 31 c0 31 d2 31 f6 bf 11 00 20 01 4c 8d 90 d0 02 00 00 b8 38 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 41 41 89 c0 85 c0 75 2c 64 48 8b 04 25 10 00 +[ 223.426930] RSP: 002b:00007fff5c3e5188 EFLAGS: 00000246 ORIG_RAX: 0000000000000038 +[ 223.426943] RAX: ffffffffffffffda RBX: 00007f4675f8c040 RCX: 00007f46758eab57 +[ 223.426954] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000001200011 +[ 223.426965] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000 +[ 223.426975] R10: 00007f4675e81a50 R11: 0000000000000246 R12: 0000000000000001 +[ 223.426986] R13: 00007fff5c3e5470 R14: 00007fff5c3e53e0 R15: 00007fff5c3e5410 +[ 223.427004] + +v2: To resolve this issue, the allocation of the process context buffer +(`proc_ctx_bo`) has been moved from the `add_queue_mes` function to the +`pqm_create_queue` function. This change ensures that the buffer is +allocated only when the first queue for a process is created and only if +the Micro Engine Scheduler (MES) is enabled. (Felix) + +v3: Fix typo s/Memory Execution Scheduler (MES)/Micro Engine Scheduler +in commit message. (Lijo) + +Fixes: 438b39ac74e2 ("drm/amdkfd: pause autosuspend when creating pdd") +Cc: Jesse Zhang +Cc: Yunxiang Li +Cc: Philip Yang +Cc: Alex Sierra +Cc: Felix Kuehling +Cc: Christian König +Cc: Alex Deucher +Signed-off-by: Srinivasan Shanmugam +Reviewed-by: Felix Kuehling +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../drm/amd/amdkfd/kfd_device_queue_manager.c | 15 --------------- + .../drm/amd/amdkfd/kfd_process_queue_manager.c | 16 ++++++++++++++++ + 2 files changed, 16 insertions(+), 15 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 34c2c42c0f95c..ad9cb50a9fa38 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +@@ -207,21 +207,6 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q, + if (!down_read_trylock(&adev->reset_domain->sem)) + return -EIO; + +- if (!pdd->proc_ctx_cpu_ptr) { +- r = amdgpu_amdkfd_alloc_gtt_mem(adev, +- AMDGPU_MES_PROC_CTX_SIZE, +- &pdd->proc_ctx_bo, +- &pdd->proc_ctx_gpu_addr, +- &pdd->proc_ctx_cpu_ptr, +- false); +- if (r) { +- dev_err(adev->dev, +- "failed to allocate process context bo\n"); +- return r; +- } +- memset(pdd->proc_ctx_cpu_ptr, 0, AMDGPU_MES_PROC_CTX_SIZE); +- } +- + memset(&queue_input, 0x0, sizeof(struct mes_add_queue_input)); + queue_input.process_id = qpd->pqm->process->pasid; + queue_input.page_table_base_addr = qpd->page_table_base; +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +index bd36a75309e12..6c02bc36d6344 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +@@ -363,10 +363,26 @@ int pqm_create_queue(struct process_queue_manager *pqm, + if (retval != 0) + return retval; + ++ /* Register process if this is the first queue */ + if (list_empty(&pdd->qpd.queues_list) && + list_empty(&pdd->qpd.priv_queue_list)) + dev->dqm->ops.register_process(dev->dqm, &pdd->qpd); + ++ /* Allocate proc_ctx_bo only if MES is enabled and this is the first queue */ ++ if (!pdd->proc_ctx_cpu_ptr && dev->kfd->shared_resources.enable_mes) { ++ retval = amdgpu_amdkfd_alloc_gtt_mem(dev->adev, ++ AMDGPU_MES_PROC_CTX_SIZE, ++ &pdd->proc_ctx_bo, ++ &pdd->proc_ctx_gpu_addr, ++ &pdd->proc_ctx_cpu_ptr, ++ false); ++ if (retval) { ++ dev_err(dev->adev->dev, "failed to allocate process context bo\n"); ++ return retval; ++ } ++ memset(pdd->proc_ctx_cpu_ptr, 0, AMDGPU_MES_PROC_CTX_SIZE); ++ } ++ + pqn = kzalloc(sizeof(*pqn), GFP_KERNEL); + if (!pqn) { + retval = -ENOMEM; +-- +2.39.5 + diff --git a/queue-6.14/drm-bridge-it6505-fix-hdcp-v-match-check-is-not-perf.patch b/queue-6.14/drm-bridge-it6505-fix-hdcp-v-match-check-is-not-perf.patch new file mode 100644 index 0000000000..33cc72cd9e --- /dev/null +++ b/queue-6.14/drm-bridge-it6505-fix-hdcp-v-match-check-is-not-perf.patch @@ -0,0 +1,51 @@ +From d8c6d0530a0f39a26b2427280f7f2f3107c8fd31 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jan 2025 15:01:51 +0800 +Subject: drm/bridge: it6505: fix HDCP V match check is not performed correctly + +From: Hermes Wu + +[ Upstream commit a5072fc77fb9e38fa9fd883642c83c3720049159 ] + +Fix a typo where V compare incorrectly compares av[] with av[] itself, +which can result in HDCP failure. + +The loop of V compare is expected to iterate for 5 times +which compare V array form av[0][] to av[4][]. +It should check loop counter reach the last statement "i == 5" +before return true + +Fixes: 0989c02c7a5c ("drm/bridge: it6505: fix HDCP CTS compare V matching") +Signed-off-by: Hermes Wu +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20250121-fix-hdcp-v-comp-v4-1-185f45c728dc@ite.com.tw +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/bridge/ite-it6505.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c +index 88ef76a37fe6a..76dabca04d0d1 100644 +--- a/drivers/gpu/drm/bridge/ite-it6505.c ++++ b/drivers/gpu/drm/bridge/ite-it6505.c +@@ -2250,12 +2250,13 @@ static bool it6505_hdcp_part2_ksvlist_check(struct it6505 *it6505) + continue; + } + +- for (i = 0; i < 5; i++) { ++ for (i = 0; i < 5; i++) + if (bv[i][3] != av[i][0] || bv[i][2] != av[i][1] || +- av[i][1] != av[i][2] || bv[i][0] != av[i][3]) ++ bv[i][1] != av[i][2] || bv[i][0] != av[i][3]) + break; + +- DRM_DEV_DEBUG_DRIVER(dev, "V' all match!! %d, %d", retry, i); ++ if (i == 5) { ++ DRM_DEV_DEBUG_DRIVER(dev, "V' all match!! %d", retry); + return true; + } + } +-- +2.39.5 + diff --git a/queue-6.14/drm-bridge-ti-sn65dsi86-fix-multiple-instances.patch b/queue-6.14/drm-bridge-ti-sn65dsi86-fix-multiple-instances.patch new file mode 100644 index 0000000000..ac86d7c374 --- /dev/null +++ b/queue-6.14/drm-bridge-ti-sn65dsi86-fix-multiple-instances.patch @@ -0,0 +1,52 @@ +From 9c7116ec63b84c3adc39ee65e0217593862cbb2c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Dec 2024 15:18:46 +0100 +Subject: drm/bridge: ti-sn65dsi86: Fix multiple instances + +From: Geert Uytterhoeven + +[ Upstream commit 574f5ee2c85a00a579549d50e9fc9c6c072ee4c4 ] + +Each bridge instance creates up to four auxiliary devices with different +names. However, their IDs are always zero, causing duplicate filename +errors when a system has multiple bridges: + + sysfs: cannot create duplicate filename '/bus/auxiliary/devices/ti_sn65dsi86.gpio.0' + +Fix this by using a unique instance ID per bridge instance. The +instance ID is derived from the I2C adapter number and the bridge's I2C +address, to support multiple instances on the same bus. + +Fixes: bf73537f411b ("drm/bridge: ti-sn65dsi86: Break GPIO and MIPI-to-eDP bridge into sub-drivers") +Signed-off-by: Geert Uytterhoeven +Reviewed-by: Douglas Anderson +Signed-off-by: Douglas Anderson +Link: https://patchwork.freedesktop.org/patch/msgid/7a68a0e3f927e26edca6040067fb653eb06efb79.1733840089.git.geert+renesas@glider.be +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/bridge/ti-sn65dsi86.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c +index e4d9006b59f1b..b3d617505dda7 100644 +--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c ++++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c +@@ -480,6 +480,7 @@ static int ti_sn65dsi86_add_aux_device(struct ti_sn65dsi86 *pdata, + const char *name) + { + struct device *dev = pdata->dev; ++ const struct i2c_client *client = to_i2c_client(dev); + struct auxiliary_device *aux; + int ret; + +@@ -488,6 +489,7 @@ static int ti_sn65dsi86_add_aux_device(struct ti_sn65dsi86 *pdata, + return -ENOMEM; + + aux->name = name; ++ aux->id = (client->adapter->nr << 10) | client->addr; + aux->dev.parent = dev; + aux->dev.release = ti_sn65dsi86_aux_device_release; + device_set_of_node_from_dev(&aux->dev, dev); +-- +2.39.5 + diff --git a/queue-6.14/drm-dp_mst-fix-drm-rad-print.patch b/queue-6.14/drm-dp_mst-fix-drm-rad-print.patch new file mode 100644 index 0000000000..47c22ac205 --- /dev/null +++ b/queue-6.14/drm-dp_mst-fix-drm-rad-print.patch @@ -0,0 +1,95 @@ +From 51b6dbe6426f83faec6cde0f6a613ebeb3ae84d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 17:10:59 +0800 +Subject: drm/dp_mst: Fix drm RAD print +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Wayne Lin + +[ Upstream commit 6bbce873a9c97cb12f5455c497be279ac58e707f ] + +[Why] +The RAD of sideband message printed today is incorrect. +For RAD stored within MST branch +- If MST branch LCT is 1, it's RAD array is untouched and remained as 0. +- If MST branch LCT is larger than 1, use nibble to store the up facing + port number in cascaded sequence as illustrated below: + + u8 RAD[0] = (LCT_2_UFP << 4) | LCT_3_UFP + RAD[1] = (LCT_4_UFP << 4) | LCT_5_UFP + ... + +In drm_dp_mst_rad_to_str(), it wrongly to use BIT_MASK(4) to fetch the port +number of one nibble. + +[How] +Adjust the code by: +- RAD array items are valuable only for LCT >= 1. +- Use 0xF as the mask to replace BIT_MASK(4) + +V2: +- Document how RAD is constructed (Imre) + +V3: +- Adjust the comment for rad[] so kdoc formats it properly (Lyude) + +Fixes: 2f015ec6eab6 ("drm/dp_mst: Add sideband down request tracing + selftests") +Cc: Imre Deak +Cc: Ville Syrjälä +Cc: Harry Wentland +Cc: Lyude Paul +Reviewed-by: Lyude Paul +Signed-off-by: Wayne Lin +Signed-off-by: Lyude Paul +Link: https://patchwork.freedesktop.org/patch/msgid/20250113091100.3314533-2-Wayne.Lin@amd.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/display/drm_dp_mst_topology.c | 8 ++++---- + include/drm/display/drm_dp_mst_helper.h | 7 +++++++ + 2 files changed, 11 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c +index 6d09bef671da0..314b394cb7e12 100644 +--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c ++++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c +@@ -175,13 +175,13 @@ static int + drm_dp_mst_rad_to_str(const u8 rad[8], u8 lct, char *out, size_t len) + { + int i; +- u8 unpacked_rad[16]; ++ u8 unpacked_rad[16] = {}; + +- for (i = 0; i < lct; i++) { ++ for (i = 1; i < lct; i++) { + if (i % 2) +- unpacked_rad[i] = rad[i / 2] >> 4; ++ unpacked_rad[i] = rad[(i - 1) / 2] >> 4; + else +- unpacked_rad[i] = rad[i / 2] & BIT_MASK(4); ++ unpacked_rad[i] = rad[(i - 1) / 2] & 0xF; + } + + /* TODO: Eventually add something to printk so we can format the rad +diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h +index e39de161c9386..2cfe1d4bfc960 100644 +--- a/include/drm/display/drm_dp_mst_helper.h ++++ b/include/drm/display/drm_dp_mst_helper.h +@@ -222,6 +222,13 @@ struct drm_dp_mst_branch { + */ + struct list_head destroy_next; + ++ /** ++ * @rad: Relative Address of the MST branch. ++ * For &drm_dp_mst_topology_mgr.mst_primary, it's rad[8] are all 0, ++ * unset and unused. For MST branches connected after mst_primary, ++ * in each element of rad[] the nibbles are ordered by the most ++ * signifcant 4 bits first and the least significant 4 bits second. ++ */ + u8 rad[8]; + u8 lct; + int num_ports; +-- +2.39.5 + diff --git a/queue-6.14/drm-file-add-fdinfo-helper-for-printing-regions-with.patch b/queue-6.14/drm-file-add-fdinfo-helper-for-printing-regions-with.patch new file mode 100644 index 0000000000..658b65bb67 --- /dev/null +++ b/queue-6.14/drm-file-add-fdinfo-helper-for-printing-regions-with.patch @@ -0,0 +1,108 @@ +From cea979a51b85d5b32d3065278ebcfe1393f063bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 17:28:10 +0000 +Subject: drm/file: Add fdinfo helper for printing regions with prefix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Adrián Larumbe + +[ Upstream commit af6c2b7c46e16701fba44a21326cb634786e3e71 ] + +This is motivated by the desire of some drivers (eg. Panthor) to print the +size of internal memory regions with a prefix that reflects the driver +name, as suggested in the previous documentation commit. + +That means adding a new argument to print_size and making it available for +DRM users. + +Cc: Tvrtko Ursulin +Reviewed-by: Tvrtko Ursulin +Signed-off-by: Adrián Larumbe +Signed-off-by: Boris Brezillon +Link: https://patchwork.freedesktop.org/patch/msgid/20250130172851.941597-3-adrian.larumbe@collabora.com +Stable-dep-of: e379856b428a ("drm/panthor: Replace sleep locks with spinlocks in fdinfo path") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/drm_file.c | 26 ++++++++++++++++++-------- + include/drm/drm_file.h | 5 +++++ + 2 files changed, 23 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c +index 2289e71e2fa24..c299cd94d3f78 100644 +--- a/drivers/gpu/drm/drm_file.c ++++ b/drivers/gpu/drm/drm_file.c +@@ -830,8 +830,11 @@ void drm_send_event(struct drm_device *dev, struct drm_pending_event *e) + } + EXPORT_SYMBOL(drm_send_event); + +-static void print_size(struct drm_printer *p, const char *stat, +- const char *region, u64 sz) ++void drm_fdinfo_print_size(struct drm_printer *p, ++ const char *prefix, ++ const char *stat, ++ const char *region, ++ u64 sz) + { + const char *units[] = {"", " KiB", " MiB"}; + unsigned u; +@@ -842,8 +845,10 @@ static void print_size(struct drm_printer *p, const char *stat, + sz = div_u64(sz, SZ_1K); + } + +- drm_printf(p, "drm-%s-%s:\t%llu%s\n", stat, region, sz, units[u]); ++ drm_printf(p, "%s-%s-%s:\t%llu%s\n", ++ prefix, stat, region, sz, units[u]); + } ++EXPORT_SYMBOL(drm_fdinfo_print_size); + + int drm_memory_stats_is_zero(const struct drm_memory_stats *stats) + { +@@ -868,17 +873,22 @@ void drm_print_memory_stats(struct drm_printer *p, + enum drm_gem_object_status supported_status, + const char *region) + { +- print_size(p, "total", region, stats->private + stats->shared); +- print_size(p, "shared", region, stats->shared); ++ const char *prefix = "drm"; ++ ++ drm_fdinfo_print_size(p, prefix, "total", region, ++ stats->private + stats->shared); ++ drm_fdinfo_print_size(p, prefix, "shared", region, stats->shared); + + if (supported_status & DRM_GEM_OBJECT_ACTIVE) +- print_size(p, "active", region, stats->active); ++ drm_fdinfo_print_size(p, prefix, "active", region, stats->active); + + if (supported_status & DRM_GEM_OBJECT_RESIDENT) +- print_size(p, "resident", region, stats->resident); ++ drm_fdinfo_print_size(p, prefix, "resident", region, ++ stats->resident); + + if (supported_status & DRM_GEM_OBJECT_PURGEABLE) +- print_size(p, "purgeable", region, stats->purgeable); ++ drm_fdinfo_print_size(p, prefix, "purgeable", region, ++ stats->purgeable); + } + EXPORT_SYMBOL(drm_print_memory_stats); + +diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h +index ef817926cddd3..94d365b225052 100644 +--- a/include/drm/drm_file.h ++++ b/include/drm/drm_file.h +@@ -495,6 +495,11 @@ struct drm_memory_stats { + enum drm_gem_object_status; + + int drm_memory_stats_is_zero(const struct drm_memory_stats *stats); ++void drm_fdinfo_print_size(struct drm_printer *p, ++ const char *prefix, ++ const char *stat, ++ const char *region, ++ u64 sz); + void drm_print_memory_stats(struct drm_printer *p, + const struct drm_memory_stats *stats, + enum drm_gem_object_status supported_status, +-- +2.39.5 + diff --git a/queue-6.14/drm-mediatek-dp-drm_err-dev_err-in-hpd-path-to-avoid.patch b/queue-6.14/drm-mediatek-dp-drm_err-dev_err-in-hpd-path-to-avoid.patch new file mode 100644 index 0000000000..286800ec94 --- /dev/null +++ b/queue-6.14/drm-mediatek-dp-drm_err-dev_err-in-hpd-path-to-avoid.patch @@ -0,0 +1,69 @@ +From 60fc7fe4271654facd0aa3c3a8fd14db4adbbec0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jan 2025 09:42:50 -0800 +Subject: drm/mediatek: dp: drm_err => dev_err in HPD path to avoid NULL ptr + +From: Douglas Anderson + +[ Upstream commit 106a6de46cf4887d535018185ec528ce822d6d84 ] + +The function mtk_dp_wait_hpd_asserted() may be called before the +`mtk_dp->drm_dev` pointer is assigned in mtk_dp_bridge_attach(). +Specifically it can be called via this callpath: + - mtk_edp_wait_hpd_asserted + - [panel probe] + - dp_aux_ep_probe + +Using "drm" level prints anywhere in this callpath causes a NULL +pointer dereference. Change the error message directly in +mtk_dp_wait_hpd_asserted() to dev_err() to avoid this. Also change the +error messages in mtk_dp_parse_capabilities(), which is called by +mtk_dp_wait_hpd_asserted(). + +While touching these prints, also add the error code to them to make +future debugging easier. + +Fixes: 7eacba9a083b ("drm/mediatek: dp: Add .wait_hpd_asserted() for AUX bus") +Signed-off-by: Douglas Anderson +Reviewed-by: CK Hu +Link: https://patchwork.kernel.org/project/dri-devel/patch/20250116094249.1.I29b0b621abb613ddc70ab4996426a3909e1aa75f@changeid/ +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/mediatek/mtk_dp.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c +index cd385ba4c66aa..d2cf09124d108 100644 +--- a/drivers/gpu/drm/mediatek/mtk_dp.c ++++ b/drivers/gpu/drm/mediatek/mtk_dp.c +@@ -1766,7 +1766,7 @@ static int mtk_dp_parse_capabilities(struct mtk_dp *mtk_dp) + + ret = drm_dp_dpcd_readb(&mtk_dp->aux, DP_MSTM_CAP, &val); + if (ret < 1) { +- drm_err(mtk_dp->drm_dev, "Read mstm cap failed\n"); ++ dev_err(mtk_dp->dev, "Read mstm cap failed: %zd\n", ret); + return ret == 0 ? -EIO : ret; + } + +@@ -1776,7 +1776,7 @@ static int mtk_dp_parse_capabilities(struct mtk_dp *mtk_dp) + DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0, + &val); + if (ret < 1) { +- drm_err(mtk_dp->drm_dev, "Read irq vector failed\n"); ++ dev_err(mtk_dp->dev, "Read irq vector failed: %zd\n", ret); + return ret == 0 ? -EIO : ret; + } + +@@ -2059,7 +2059,7 @@ static int mtk_dp_wait_hpd_asserted(struct drm_dp_aux *mtk_aux, unsigned long wa + + ret = mtk_dp_parse_capabilities(mtk_dp); + if (ret) { +- drm_err(mtk_dp->drm_dev, "Can't parse capabilities\n"); ++ dev_err(mtk_dp->dev, "Can't parse capabilities: %d\n", ret); + return ret; + } + +-- +2.39.5 + diff --git a/queue-6.14/drm-mediatek-dsi-fix-error-codes-in-mtk_dsi_host_tra.patch b/queue-6.14/drm-mediatek-dsi-fix-error-codes-in-mtk_dsi_host_tra.patch new file mode 100644 index 0000000000..0fe4a64f87 --- /dev/null +++ b/queue-6.14/drm-mediatek-dsi-fix-error-codes-in-mtk_dsi_host_tra.patch @@ -0,0 +1,64 @@ +From 5c3765639766ee637cce2cab5ac3ac44d0b33292 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jan 2025 12:35:57 +0300 +Subject: drm/mediatek: dsi: fix error codes in mtk_dsi_host_transfer() + +From: Dan Carpenter + +[ Upstream commit dcb166ee43c3d594e7b73a24f6e8cf5663eeff2c ] + +There is a type bug because the return statement: + + return ret < 0 ? ret : recv_cnt; + +The issue is that ret is an int, recv_cnt is a u32 and the function +returns ssize_t, which is a signed long. The way that the type promotion +works is that the negative error codes are first cast to u32 and then +to signed long. The error codes end up being positive instead of +negative and the callers treat them as success. + +Fixes: 81cc7e51c4f1 ("drm/mediatek: Allow commands to be sent during video mode") +Reported-by: kernel test robot +Closes: https://lore.kernel.org/r/202412210801.iADw0oIH-lkp@intel.com/ +Signed-off-by: Dan Carpenter +Reviewed-by: Mattijs Korpershoek +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: CK Hu +Link: https://patchwork.kernel.org/project/dri-devel/patch/b754a408-4f39-4e37-b52d-7706c132e27f@stanley.mountain/ +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/mediatek/mtk_dsi.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c +index 40752f2320548..852aeef9f38dc 100644 +--- a/drivers/gpu/drm/mediatek/mtk_dsi.c ++++ b/drivers/gpu/drm/mediatek/mtk_dsi.c +@@ -1116,12 +1116,12 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host, + const struct mipi_dsi_msg *msg) + { + struct mtk_dsi *dsi = host_to_dsi(host); +- u32 recv_cnt, i; ++ ssize_t recv_cnt; + u8 read_data[16]; + void *src_addr; + u8 irq_flag = CMD_DONE_INT_FLAG; + u32 dsi_mode; +- int ret; ++ int ret, i; + + dsi_mode = readl(dsi->regs + DSI_MODE_CTRL); + if (dsi_mode & MODE) { +@@ -1170,7 +1170,7 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host, + if (recv_cnt) + memcpy(msg->rx_buf, src_addr, recv_cnt); + +- DRM_INFO("dsi get %d byte data from the panel address(0x%x)\n", ++ DRM_INFO("dsi get %zd byte data from the panel address(0x%x)\n", + recv_cnt, *((u8 *)(msg->tx_buf))); + + restore_dsi_mode: +-- +2.39.5 + diff --git a/queue-6.14/drm-mediatek-fix-config_updating-flag-never-false-wh.patch b/queue-6.14/drm-mediatek-fix-config_updating-flag-never-false-wh.patch new file mode 100644 index 0000000000..9114c5efd5 --- /dev/null +++ b/queue-6.14/drm-mediatek-fix-config_updating-flag-never-false-wh.patch @@ -0,0 +1,53 @@ +From 7edbbf569662e4e0d9dea5b352b5d3083f8ae2cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 13:12:21 +0800 +Subject: drm/mediatek: Fix config_updating flag never false when no mbox + channel + +From: Jason-JH Lin + +[ Upstream commit 4ba973c8bad04d59fd4efa62512f4d9cee131714 ] + +When CONFIG_MTK_CMDQ is enabled, if the display is controlled by the CPU +while other hardware is controlled by the GCE, the display will encounter +a mbox request channel failure. +However, it will still enter the CONFIG_MTK_CMDQ statement, causing the +config_updating flag to never be set to false. As a result, no page flip +event is sent back to user space, and the screen does not update. + +Fixes: da03801ad08f ("drm/mediatek: Move mtk_crtc_finish_page_flip() to ddp_cmdq_cb()") +Signed-off-by: Jason-JH Lin +Reviewed-by: CK Hu +Link: https://patchwork.kernel.org/project/dri-devel/patch/20250224051301.3538484-1-jason-jh.lin@mediatek.com/ +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/mediatek/mtk_crtc.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c +index 5674f5707cca8..8f6fba4217ece 100644 +--- a/drivers/gpu/drm/mediatek/mtk_crtc.c ++++ b/drivers/gpu/drm/mediatek/mtk_crtc.c +@@ -620,13 +620,16 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank) + + mbox_send_message(mtk_crtc->cmdq_client.chan, cmdq_handle); + mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0); ++ goto update_config_out; + } +-#else ++#endif + spin_lock_irqsave(&mtk_crtc->config_lock, flags); + mtk_crtc->config_updating = false; + spin_unlock_irqrestore(&mtk_crtc->config_lock, flags); +-#endif + ++#if IS_REACHABLE(CONFIG_MTK_CMDQ) ++update_config_out: ++#endif + mutex_unlock(&mtk_crtc->hw_lock); + } + +-- +2.39.5 + diff --git a/queue-6.14/drm-mediatek-mtk_hdmi-fix-typo-for-aud_sampe_size-me.patch b/queue-6.14/drm-mediatek-mtk_hdmi-fix-typo-for-aud_sampe_size-me.patch new file mode 100644 index 0000000000..a157580966 --- /dev/null +++ b/queue-6.14/drm-mediatek-mtk_hdmi-fix-typo-for-aud_sampe_size-me.patch @@ -0,0 +1,66 @@ +From 9e9fc8dd818456d66aa5b7133500b5ebd9fd0179 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 16:48:12 +0100 +Subject: drm/mediatek: mtk_hdmi: Fix typo for aud_sampe_size member + +From: AngeloGioacchino Del Regno + +[ Upstream commit 72fcb88e7bbc053ed4fc74cebb0315b98a0f20c3 ] + +Rename member aud_sampe_size of struct hdmi_audio_param to +aud_sample_size to fix a typo and enhance readability. + +This commit brings no functional changes. + +Fixes: 8f83f26891e1 ("drm/mediatek: Add HDMI support") +Reviewed-by: CK Hu +Signed-off-by: AngeloGioacchino Del Regno +Link: https://patchwork.kernel.org/project/linux-mediatek/patch/20250217154836.108895-20-angelogioacchino.delregno@collabora.com/ +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/mediatek/mtk_hdmi.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c +index 1018a9a7433f9..250ad0d4027d6 100644 +--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c ++++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c +@@ -137,7 +137,7 @@ enum hdmi_aud_channel_swap_type { + + struct hdmi_audio_param { + enum hdmi_audio_coding_type aud_codec; +- enum hdmi_audio_sample_size aud_sampe_size; ++ enum hdmi_audio_sample_size aud_sample_size; + enum hdmi_aud_input_type aud_input_type; + enum hdmi_aud_i2s_fmt aud_i2s_fmt; + enum hdmi_aud_mclk aud_mclk; +@@ -1075,7 +1075,7 @@ static int mtk_hdmi_output_init(struct mtk_hdmi *hdmi) + + hdmi->csp = HDMI_COLORSPACE_RGB; + aud_param->aud_codec = HDMI_AUDIO_CODING_TYPE_PCM; +- aud_param->aud_sampe_size = HDMI_AUDIO_SAMPLE_SIZE_16; ++ aud_param->aud_sample_size = HDMI_AUDIO_SAMPLE_SIZE_16; + aud_param->aud_input_type = HDMI_AUD_INPUT_I2S; + aud_param->aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT; + aud_param->aud_mclk = HDMI_AUD_MCLK_128FS; +@@ -1573,14 +1573,14 @@ static int mtk_hdmi_audio_hw_params(struct device *dev, void *data, + switch (daifmt->fmt) { + case HDMI_I2S: + hdmi_params.aud_codec = HDMI_AUDIO_CODING_TYPE_PCM; +- hdmi_params.aud_sampe_size = HDMI_AUDIO_SAMPLE_SIZE_16; ++ hdmi_params.aud_sample_size = HDMI_AUDIO_SAMPLE_SIZE_16; + hdmi_params.aud_input_type = HDMI_AUD_INPUT_I2S; + hdmi_params.aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT; + hdmi_params.aud_mclk = HDMI_AUD_MCLK_128FS; + break; + case HDMI_SPDIF: + hdmi_params.aud_codec = HDMI_AUDIO_CODING_TYPE_PCM; +- hdmi_params.aud_sampe_size = HDMI_AUDIO_SAMPLE_SIZE_16; ++ hdmi_params.aud_sample_size = HDMI_AUDIO_SAMPLE_SIZE_16; + hdmi_params.aud_input_type = HDMI_AUD_INPUT_SPDIF; + break; + default: +-- +2.39.5 + diff --git a/queue-6.14/drm-mediatek-mtk_hdmi-unregister-audio-platform-devi.patch b/queue-6.14/drm-mediatek-mtk_hdmi-unregister-audio-platform-devi.patch new file mode 100644 index 0000000000..5e97bf086c --- /dev/null +++ b/queue-6.14/drm-mediatek-mtk_hdmi-unregister-audio-platform-devi.patch @@ -0,0 +1,85 @@ +From ae3dbae615687464c7d90f9e88c564cad9cbf674 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 16:48:10 +0100 +Subject: drm/mediatek: mtk_hdmi: Unregister audio platform device on failure + +From: AngeloGioacchino Del Regno + +[ Upstream commit 0be123cafc06eed0fd1227166a66e786434b0c50 ] + +The probe function of this driver may fail after registering the +audio platform device: in that case, the state is not getting +cleaned up, leaving this device registered. + +Adding up to the mix, should the probe function of this driver +return a probe deferral for N times, we're registering up to N +audio platform devices and, again, never freeing them up. + +To fix this, add a pointer to the audio platform device in the +mtk_hdmi structure, and add a devm action to unregister it upon +driver removal or probe failure. + +Fixes: 8f83f26891e1 ("drm/mediatek: Add HDMI support") +Reviewed-by: CK Hu +Signed-off-by: AngeloGioacchino Del Regno +Link: https://patchwork.kernel.org/project/linux-mediatek/patch/20250217154836.108895-18-angelogioacchino.delregno@collabora.com/ +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/mediatek/mtk_hdmi.c | 25 +++++++++++++++++++------ + 1 file changed, 19 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c +index ca82bc829cb96..1018a9a7433f9 100644 +--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c ++++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c +@@ -173,6 +173,7 @@ struct mtk_hdmi { + unsigned int sys_offset; + void __iomem *regs; + enum hdmi_colorspace csp; ++ struct platform_device *audio_pdev; + struct hdmi_audio_param aud_param; + bool audio_enable; + bool powered; +@@ -1662,6 +1663,11 @@ static const struct hdmi_codec_ops mtk_hdmi_audio_codec_ops = { + .hook_plugged_cb = mtk_hdmi_audio_hook_plugged_cb, + }; + ++static void mtk_hdmi_unregister_audio_driver(void *data) ++{ ++ platform_device_unregister(data); ++} ++ + static int mtk_hdmi_register_audio_driver(struct device *dev) + { + struct mtk_hdmi *hdmi = dev_get_drvdata(dev); +@@ -1672,13 +1678,20 @@ static int mtk_hdmi_register_audio_driver(struct device *dev) + .data = hdmi, + .no_capture_mute = 1, + }; +- struct platform_device *pdev; ++ int ret; + +- pdev = platform_device_register_data(dev, HDMI_CODEC_DRV_NAME, +- PLATFORM_DEVID_AUTO, &codec_data, +- sizeof(codec_data)); +- if (IS_ERR(pdev)) +- return PTR_ERR(pdev); ++ hdmi->audio_pdev = platform_device_register_data(dev, ++ HDMI_CODEC_DRV_NAME, ++ PLATFORM_DEVID_AUTO, ++ &codec_data, ++ sizeof(codec_data)); ++ if (IS_ERR(hdmi->audio_pdev)) ++ return PTR_ERR(hdmi->audio_pdev); ++ ++ ret = devm_add_action_or_reset(dev, mtk_hdmi_unregister_audio_driver, ++ hdmi->audio_pdev); ++ if (ret) ++ return ret; + + DRM_INFO("%s driver bound to HDMI\n", HDMI_CODEC_DRV_NAME); + return 0; +-- +2.39.5 + diff --git a/queue-6.14/drm-msm-a6xx-fix-a6xx-indexed-regs-in-devcoreduump.patch b/queue-6.14/drm-msm-a6xx-fix-a6xx-indexed-regs-in-devcoreduump.patch new file mode 100644 index 0000000000..e14f67ebc5 --- /dev/null +++ b/queue-6.14/drm-msm-a6xx-fix-a6xx-indexed-regs-in-devcoreduump.patch @@ -0,0 +1,38 @@ +From 4b8a2bd1fe29f0f08ba7c3d2a8aedf39ec6bac68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 13:31:24 -0800 +Subject: drm/msm/a6xx: Fix a6xx indexed-regs in devcoreduump + +From: Rob Clark + +[ Upstream commit 06dd5d86c6aef1c7609ca3a5ffa4097e475e2213 ] + +Somehow, possibly as a result of rebase gone badly, setting +nr_indexed_regs for pre-a650 a6xx devices lost the setting of +nr_indexed_regs, resulting in values getting snapshot, but omitted +from the devcoredump. + +Fixes: e997ae5f45ca ("drm/msm/a6xx: Mostly implement A7xx gpu_state") +Signed-off-by: Rob Clark +Patchwork: https://patchwork.freedesktop.org/patch/640289/ +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +index 0fcae53c0b140..159665cb6b14f 100644 +--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c ++++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +@@ -1507,6 +1507,8 @@ static void a6xx_get_indexed_registers(struct msm_gpu *gpu, + + /* Restore the size in the hardware */ + gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, mempool_size); ++ ++ a6xx_state->nr_indexed_regs = count; + } + + static void a7xx_get_indexed_registers(struct msm_gpu *gpu, +-- +2.39.5 + diff --git a/queue-6.14/drm-msm-dpu-don-t-set-crtc_state-mode_changed-from-a.patch b/queue-6.14/drm-msm-dpu-don-t-set-crtc_state-mode_changed-from-a.patch new file mode 100644 index 0000000000..425f5eb03a --- /dev/null +++ b/queue-6.14/drm-msm-dpu-don-t-set-crtc_state-mode_changed-from-a.patch @@ -0,0 +1,191 @@ +From 20dc1bf23d34572fbc92cf0fabb15c0d989ae82a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 14:43:36 +0200 +Subject: drm/msm/dpu: don't set crtc_state->mode_changed from atomic_check() + +From: Dmitry Baryshkov + +[ Upstream commit 2dde2aadaed113feb724c19063ac61e2f6ba61a4 ] + +The MSM driver uses drm_atomic_helper_check() which mandates that none +of the atomic_check() callbacks toggles crtc_state->mode_changed. +Perform corresponding check before calling the drm_atomic_helper_check() +function. + +Fixes: 8b45a26f2ba9 ("drm/msm/dpu: reserve cdm blocks for writeback in case of YUV output") +Reported-by: Simona Vetter +Closes: https://lore.kernel.org/dri-devel/ZtW_S0j5AEr4g0QW@phenom.ffwll.local/ +Reviewed-by: Abhinav Kumar +[DB: dropped the WARN_ON] +Signed-off-by: Dmitry Baryshkov +Patchwork: https://patchwork.freedesktop.org/patch/633400/ +Link: https://lore.kernel.org/r/20250123-drm-dirty-modeset-v2-4-bbfd3a6cd1a4@linaro.org +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 32 ++++++++++++++++++--- + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 4 +++ + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 24 ++++++++++++++++ + drivers/gpu/drm/msm/msm_atomic.c | 13 ++++++++- + drivers/gpu/drm/msm/msm_kms.h | 7 +++++ + 5 files changed, 75 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +index 9928e72dfabda..7b56da24711e4 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +@@ -760,6 +760,34 @@ static void dpu_encoder_assign_crtc_resources(struct dpu_kms *dpu_kms, + cstate->num_mixers = num_lm; + } + ++/** ++ * dpu_encoder_virt_check_mode_changed: check if full modeset is required ++ * @drm_enc: Pointer to drm encoder structure ++ * @crtc_state: Corresponding CRTC state to be checked ++ * @conn_state: Corresponding Connector's state to be checked ++ * ++ * Check if the changes in the object properties demand full mode set. ++ */ ++int dpu_encoder_virt_check_mode_changed(struct drm_encoder *drm_enc, ++ struct drm_crtc_state *crtc_state, ++ struct drm_connector_state *conn_state) ++{ ++ struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc); ++ struct msm_display_topology topology; ++ ++ DPU_DEBUG_ENC(dpu_enc, "\n"); ++ ++ /* Using mode instead of adjusted_mode as it wasn't computed yet */ ++ topology = dpu_encoder_get_topology(dpu_enc, &crtc_state->mode, crtc_state, conn_state); ++ ++ if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm) ++ crtc_state->mode_changed = true; ++ else if (!topology.needs_cdm && dpu_enc->cur_master->hw_cdm) ++ crtc_state->mode_changed = true; ++ ++ return 0; ++} ++ + static int dpu_encoder_virt_atomic_check( + struct drm_encoder *drm_enc, + struct drm_crtc_state *crtc_state, +@@ -793,10 +821,6 @@ static int dpu_encoder_virt_atomic_check( + + topology = dpu_encoder_get_topology(dpu_enc, adj_mode, crtc_state, conn_state); + +- if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm) +- crtc_state->mode_changed = true; +- else if (!topology.needs_cdm && dpu_enc->cur_master->hw_cdm) +- crtc_state->mode_changed = true; + /* + * Release and Allocate resources on every modeset + */ +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +index 92b5ee390788d..da133ee4701a3 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +@@ -88,4 +88,8 @@ void dpu_encoder_cleanup_wb_job(struct drm_encoder *drm_enc, + + bool dpu_encoder_is_valid_for_commit(struct drm_encoder *drm_enc); + ++int dpu_encoder_virt_check_mode_changed(struct drm_encoder *drm_enc, ++ struct drm_crtc_state *crtc_state, ++ struct drm_connector_state *conn_state); ++ + #endif /* __DPU_ENCODER_H__ */ +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +index 97e9cb8c2b099..8741dc6fc8ddc 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +@@ -446,6 +446,29 @@ static void dpu_kms_disable_commit(struct msm_kms *kms) + pm_runtime_put_sync(&dpu_kms->pdev->dev); + } + ++static int dpu_kms_check_mode_changed(struct msm_kms *kms, struct drm_atomic_state *state) ++{ ++ struct drm_crtc_state *new_crtc_state; ++ struct drm_connector *connector; ++ struct drm_connector_state *new_conn_state; ++ int i; ++ ++ for_each_new_connector_in_state(state, connector, new_conn_state, i) { ++ struct drm_encoder *encoder; ++ ++ if (!new_conn_state->crtc || !new_conn_state->best_encoder) ++ continue; ++ ++ new_crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); ++ ++ encoder = new_conn_state->best_encoder; ++ ++ dpu_encoder_virt_check_mode_changed(encoder, new_crtc_state, new_conn_state); ++ } ++ ++ return 0; ++} ++ + static void dpu_kms_flush_commit(struct msm_kms *kms, unsigned crtc_mask) + { + struct dpu_kms *dpu_kms = to_dpu_kms(kms); +@@ -1062,6 +1085,7 @@ static const struct msm_kms_funcs kms_funcs = { + .irq = dpu_core_irq, + .enable_commit = dpu_kms_enable_commit, + .disable_commit = dpu_kms_disable_commit, ++ .check_mode_changed = dpu_kms_check_mode_changed, + .flush_commit = dpu_kms_flush_commit, + .wait_flush = dpu_kms_wait_flush, + .complete_commit = dpu_kms_complete_commit, +diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c +index a7a2384044ffd..364df245e3a20 100644 +--- a/drivers/gpu/drm/msm/msm_atomic.c ++++ b/drivers/gpu/drm/msm/msm_atomic.c +@@ -183,10 +183,16 @@ static unsigned get_crtc_mask(struct drm_atomic_state *state) + + int msm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) + { ++ struct msm_drm_private *priv = dev->dev_private; ++ struct msm_kms *kms = priv->kms; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; + struct drm_crtc *crtc; +- int i; ++ int i, ret = 0; + ++ /* ++ * FIXME: stop setting allow_modeset and move this check to the DPU ++ * driver. ++ */ + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, + new_crtc_state, i) { + if ((old_crtc_state->ctm && !new_crtc_state->ctm) || +@@ -196,6 +202,11 @@ int msm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) + } + } + ++ if (kms && kms->funcs && kms->funcs->check_mode_changed) ++ ret = kms->funcs->check_mode_changed(kms, state); ++ if (ret) ++ return ret; ++ + return drm_atomic_helper_check(dev, state); + } + +diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h +index e60162744c669..ec2a75af89b09 100644 +--- a/drivers/gpu/drm/msm/msm_kms.h ++++ b/drivers/gpu/drm/msm/msm_kms.h +@@ -59,6 +59,13 @@ struct msm_kms_funcs { + void (*enable_commit)(struct msm_kms *kms); + void (*disable_commit)(struct msm_kms *kms); + ++ /** ++ * @check_mode_changed: ++ * ++ * Verify if the commit requires a full modeset on one of CRTCs. ++ */ ++ int (*check_mode_changed)(struct msm_kms *kms, struct drm_atomic_state *state); ++ + /** + * Prepare for atomic commit. This is called after any previous + * (async or otherwise) commit has completed. +-- +2.39.5 + diff --git a/queue-6.14/drm-msm-dpu-don-t-use-active-in-atomic_check.patch b/queue-6.14/drm-msm-dpu-don-t-use-active-in-atomic_check.patch new file mode 100644 index 0000000000..2a01945080 --- /dev/null +++ b/queue-6.14/drm-msm-dpu-don-t-use-active-in-atomic_check.patch @@ -0,0 +1,65 @@ +From 3877c7df157472d93b5ddf6527feafcbe69e87b0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 14:43:33 +0200 +Subject: drm/msm/dpu: don't use active in atomic_check() + +From: Dmitry Baryshkov + +[ Upstream commit 25b4614843bcc56ba150f7c99905125a019e656c ] + +The driver isn't supposed to consult crtc_state->active/active_check for +resource allocation. Instead all resources should be allocated if +crtc_state->enabled is set. Stop consulting active / active_changed in +order to determine whether the hardware resources should be +(re)allocated. + +Fixes: ccc862b957c6 ("drm/msm/dpu: Fix reservation failures in modeset") +Reported-by: Simona Vetter +Closes: https://lore.kernel.org/dri-devel/ZtW_S0j5AEr4g0QW@phenom.ffwll.local/ +Reviewed-by: Simona Vetter +Reviewed-by: Abhinav Kumar +Signed-off-by: Dmitry Baryshkov +Patchwork: https://patchwork.freedesktop.org/patch/633393/ +Link: https://lore.kernel.org/r/20250123-drm-dirty-modeset-v2-1-bbfd3a6cd1a4@linaro.org +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 4 ---- + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 3 +-- + 2 files changed, 1 insertion(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +index e5dcd41a361f4..29485e76f531f 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +@@ -1262,10 +1262,6 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, + + DRM_DEBUG_ATOMIC("%s: check\n", dpu_crtc->name); + +- /* force a full mode set if active state changed */ +- if (crtc_state->active_changed) +- crtc_state->mode_changed = true; +- + if (cstate->num_mixers) { + rc = _dpu_crtc_check_and_setup_lm_bounds(crtc, crtc_state); + if (rc) +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +index 48e6e8d74c855..ee7dacf8a1cb6 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +@@ -793,12 +793,11 @@ static int dpu_encoder_virt_atomic_check( + crtc_state->mode_changed = true; + /* + * Release and Allocate resources on every modeset +- * Dont allocate when active is false. + */ + if (drm_atomic_crtc_needs_modeset(crtc_state)) { + dpu_rm_release(global_state, drm_enc); + +- if (!crtc_state->active_changed || crtc_state->enable) ++ if (crtc_state->enable) + ret = dpu_rm_reserve(&dpu_kms->rm, global_state, + drm_enc, crtc_state, &topology); + if (!ret) +-- +2.39.5 + diff --git a/queue-6.14/drm-msm-dpu-fall-back-to-a-single-dsc-encoder-1-1-1-.patch b/queue-6.14/drm-msm-dpu-fall-back-to-a-single-dsc-encoder-1-1-1-.patch new file mode 100644 index 0000000000..156ecf28e6 --- /dev/null +++ b/queue-6.14/drm-msm-dpu-fall-back-to-a-single-dsc-encoder-1-1-1-.patch @@ -0,0 +1,140 @@ +From 0308388f2cbfd97e6a73eaf02efaba5c1912f0c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 17:23:44 +0100 +Subject: drm/msm/dpu: Fall back to a single DSC encoder (1:1:1) on small SoCs + +From: Marijn Suijten + +[ Upstream commit b6090ffb30f3301d3831774f9c3e2f1b1141a399 ] + +Some SoCs such as SC7280 (used in the Fairphone 5) have only a single +DSC "hard slice" encoder. The current hardcoded use of 2:2:1 topology +(2 LM and 2 DSC for a single interface) make it impossible to use +Display Stream Compression panels with mainline, which is exactly what's +installed on the Fairphone 5. + +By loosening the hardcoded `num_dsc = 2` to fall back to `num_dsc = +1` when the catalog only contains one entry, we can trivially support +this phone and unblock further panel enablement on mainline. A few +more supporting changes in this patch ensure hardcoded constants of 2 +DSC encoders are replaced to count or read back the actual number of +DSC hardware blocks that are enabled for the given virtual encoder. +Likewise DSC_MODE_SPLIT_PANEL can no longer be unconditionally enabled. + +Cc: Luca Weiss +Signed-off-by: Marijn Suijten +Reviewed-by: Dmitry Baryshkov +Tested-by: Luca Weiss +Reviewed-by: Jessica Zhang +Tested-by: Danila Tikhonov +Patchwork: https://patchwork.freedesktop.org/patch/633318/ +Link: https://lore.kernel.org/r/20250122-dpu-111-topology-v2-1-505e95964af9@somainline.org +Signed-off-by: Dmitry Baryshkov +Stable-dep-of: d245ce568929 ("drm/msm/dpu: Remove arbitrary limit of 1 interface in DSC topology") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 47 +++++++++++---------- + 1 file changed, 25 insertions(+), 22 deletions(-) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +index ee7dacf8a1cb6..88591b6f9e350 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +@@ -622,9 +622,9 @@ bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc) + if (dpu_enc->phys_encs[i]) + intf_count++; + +- /* See dpu_encoder_get_topology, we only support 2:2:1 topology */ +- if (dpu_enc->dsc) +- num_dsc = 2; ++ for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) ++ if (dpu_enc->hw_dsc[i]) ++ num_dsc++; + + return (num_dsc > 0) && (num_dsc > intf_count); + } +@@ -686,13 +686,19 @@ static struct msm_display_topology dpu_encoder_get_topology( + + if (dsc) { + /* +- * In case of Display Stream Compression (DSC), we would use +- * 2 DSC encoders, 2 layer mixers and 1 interface +- * this is power optimal and can drive up to (including) 4k +- * screens ++ * Use 2 DSC encoders and 2 layer mixers per single interface ++ * when Display Stream Compression (DSC) is enabled, ++ * and when enough DSC blocks are available. ++ * This is power-optimal and can drive up to (including) 4k ++ * screens. + */ +- topology.num_dsc = 2; +- topology.num_lm = 2; ++ if (dpu_kms->catalog->dsc_count >= 2) { ++ topology.num_dsc = 2; ++ topology.num_lm = 2; ++ } else { ++ topology.num_dsc = 1; ++ topology.num_lm = 1; ++ } + topology.num_intf = 1; + } + +@@ -2019,7 +2025,6 @@ static void dpu_encoder_dsc_pipe_cfg(struct dpu_hw_ctl *ctl, + static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc, + struct drm_dsc_config *dsc) + { +- /* coding only for 2LM, 2enc, 1 dsc config */ + struct dpu_encoder_phys *enc_master = dpu_enc->cur_master; + struct dpu_hw_ctl *ctl = enc_master->hw_ctl; + struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC]; +@@ -2029,22 +2034,24 @@ static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc, + int dsc_common_mode; + int pic_width; + u32 initial_lines; ++ int num_dsc = 0; + int i; + + for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { + hw_pp[i] = dpu_enc->hw_pp[i]; + hw_dsc[i] = dpu_enc->hw_dsc[i]; + +- if (!hw_pp[i] || !hw_dsc[i]) { +- DPU_ERROR_ENC(dpu_enc, "invalid params for DSC\n"); +- return; +- } ++ if (!hw_pp[i] || !hw_dsc[i]) ++ break; ++ ++ num_dsc++; + } + +- dsc_common_mode = 0; + pic_width = dsc->pic_width; + +- dsc_common_mode = DSC_MODE_SPLIT_PANEL; ++ dsc_common_mode = 0; ++ if (num_dsc > 1) ++ dsc_common_mode |= DSC_MODE_SPLIT_PANEL; + if (dpu_encoder_use_dsc_merge(enc_master->parent)) + dsc_common_mode |= DSC_MODE_MULTIPLEX; + if (enc_master->intf_mode == INTF_MODE_VIDEO) +@@ -2053,14 +2060,10 @@ static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc, + this_frame_slices = pic_width / dsc->slice_width; + intf_ip_w = this_frame_slices * dsc->slice_width; + +- /* +- * dsc merge case: when using 2 encoders for the same stream, +- * no. of slices need to be same on both the encoders. +- */ +- enc_ip_w = intf_ip_w / 2; ++ enc_ip_w = intf_ip_w / num_dsc; + initial_lines = dpu_encoder_dsc_initial_line_calc(dsc, enc_ip_w); + +- for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) ++ for (i = 0; i < num_dsc; i++) + dpu_encoder_dsc_pipe_cfg(ctl, hw_dsc[i], hw_pp[i], + dsc, dsc_common_mode, initial_lines); + } +-- +2.39.5 + diff --git a/queue-6.14/drm-msm-dpu-move-needs_cdm-setting-to-dpu_encoder_ge.patch b/queue-6.14/drm-msm-dpu-move-needs_cdm-setting-to-dpu_encoder_ge.patch new file mode 100644 index 0000000000..d88e34f8ee --- /dev/null +++ b/queue-6.14/drm-msm-dpu-move-needs_cdm-setting-to-dpu_encoder_ge.patch @@ -0,0 +1,109 @@ +From 996a471646e63b7dd3024f4233557b9b92186169 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 14:43:34 +0200 +Subject: drm/msm/dpu: move needs_cdm setting to dpu_encoder_get_topology() + +From: Dmitry Baryshkov + +[ Upstream commit 7d39f5bb82c0d7155037982dd0ff583a68db1c34 ] + +As a preparation for calling dpu_encoder_get_topology() from different +places, move the code setting topology->needs_cdm to that function +(instead of patching topology separately). + +Reviewed-by: Abhinav Kumar +Signed-off-by: Dmitry Baryshkov +Patchwork: https://patchwork.freedesktop.org/patch/633395/ +Link: https://lore.kernel.org/r/20250123-drm-dirty-modeset-v2-2-bbfd3a6cd1a4@linaro.org +Stable-dep-of: 2dde2aadaed1 ("drm/msm/dpu: don't set crtc_state->mode_changed from atomic_check()") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 41 +++++++++++---------- + 1 file changed, 22 insertions(+), 19 deletions(-) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +index e3555765eefb1..66dc2b1dee7f8 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +@@ -652,8 +652,11 @@ static struct msm_display_topology dpu_encoder_get_topology( + struct dpu_kms *dpu_kms, + struct drm_display_mode *mode, + struct drm_crtc_state *crtc_state, ++ struct drm_connector_state *conn_state, + struct drm_dsc_config *dsc) + { ++ struct msm_drm_private *priv = dpu_enc->base.dev->dev_private; ++ struct msm_display_info *disp_info = &dpu_enc->disp_info; + struct msm_display_topology topology = {0}; + int i, intf_count = 0; + +@@ -703,6 +706,23 @@ static struct msm_display_topology dpu_encoder_get_topology( + } + } + ++ /* ++ * Use CDM only for writeback or DP at the moment as other interfaces cannot handle it. ++ * If writeback itself cannot handle cdm for some reason it will fail in its atomic_check() ++ * earlier. ++ */ ++ if (disp_info->intf_type == INTF_WB && conn_state->writeback_job) { ++ struct drm_framebuffer *fb; ++ ++ fb = conn_state->writeback_job->fb; ++ ++ if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb))) ++ topology.needs_cdm = true; ++ } else if (disp_info->intf_type == INTF_DP) { ++ if (msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], mode)) ++ topology.needs_cdm = true; ++ } ++ + return topology; + } + +@@ -750,9 +770,7 @@ static int dpu_encoder_virt_atomic_check( + struct dpu_kms *dpu_kms; + struct drm_display_mode *adj_mode; + struct msm_display_topology topology; +- struct msm_display_info *disp_info; + struct dpu_global_state *global_state; +- struct drm_framebuffer *fb; + struct drm_dsc_config *dsc; + int ret = 0; + +@@ -766,7 +784,6 @@ static int dpu_encoder_virt_atomic_check( + DPU_DEBUG_ENC(dpu_enc, "\n"); + + priv = drm_enc->dev->dev_private; +- disp_info = &dpu_enc->disp_info; + dpu_kms = to_dpu_kms(priv->kms); + adj_mode = &crtc_state->adjusted_mode; + global_state = dpu_kms_get_global_state(crtc_state->state); +@@ -777,22 +794,8 @@ static int dpu_encoder_virt_atomic_check( + + dsc = dpu_encoder_get_dsc_config(drm_enc); + +- topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode, crtc_state, dsc); +- +- /* +- * Use CDM only for writeback or DP at the moment as other interfaces cannot handle it. +- * If writeback itself cannot handle cdm for some reason it will fail in its atomic_check() +- * earlier. +- */ +- if (disp_info->intf_type == INTF_WB && conn_state->writeback_job) { +- fb = conn_state->writeback_job->fb; +- +- if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb))) +- topology.needs_cdm = true; +- } else if (disp_info->intf_type == INTF_DP) { +- if (msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], adj_mode)) +- topology.needs_cdm = true; +- } ++ topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode, crtc_state, conn_state, ++ dsc); + + if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm) + crtc_state->mode_changed = true; +-- +2.39.5 + diff --git a/queue-6.14/drm-msm-dpu-remove-arbitrary-limit-of-1-interface-in.patch b/queue-6.14/drm-msm-dpu-remove-arbitrary-limit-of-1-interface-in.patch new file mode 100644 index 0000000000..f06e209f09 --- /dev/null +++ b/queue-6.14/drm-msm-dpu-remove-arbitrary-limit-of-1-interface-in.patch @@ -0,0 +1,62 @@ +From 96a07bce4785db8054d9f41552013e090fa0c77c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 12:17:43 +0100 +Subject: drm/msm/dpu: Remove arbitrary limit of 1 interface in DSC topology + +From: Marijn Suijten + +[ Upstream commit d245ce568929e30f650e260631f7ad14970d7c2c ] + +When DSC is enabled the number of interfaces is forced to be 1, and +documented that it is a "power-optimal" layout to use two DSC encoders +together with two Layer Mixers. However, the same layout (two DSC +hard-slice encoders with two LMs) is also used when the display is +fed with data over two instead of one interface (common on 4k@120Hz +smartphone panels with Dual-DSI). Solve this by simply removing the +num_intf = 1 assignment as the count is already calculated by computing +the number of physical encoders within the virtual encoder. + +Fixes: 7e9cc175b159 ("drm/msm/disp/dpu1: Add support for DSC in topology") +Reviewed-by: Dmitry Baryshkov +Reviewed-by: Jessica Zhang +Signed-off-by: Marijn Suijten +Patchwork: https://patchwork.freedesktop.org/patch/637649/ +Link: https://lore.kernel.org/r/20250217-drm-msm-initial-dualpipe-dsc-fixes-v3-3-913100d6103f@somainline.org +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +index 88591b6f9e350..e3555765eefb1 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +@@ -686,20 +686,21 @@ static struct msm_display_topology dpu_encoder_get_topology( + + if (dsc) { + /* +- * Use 2 DSC encoders and 2 layer mixers per single interface ++ * Use 2 DSC encoders, 2 layer mixers and 1 or 2 interfaces + * when Display Stream Compression (DSC) is enabled, + * and when enough DSC blocks are available. + * This is power-optimal and can drive up to (including) 4k + * screens. + */ +- if (dpu_kms->catalog->dsc_count >= 2) { ++ WARN(topology.num_intf > 2, ++ "DSC topology cannot support more than 2 interfaces\n"); ++ if (intf_count >= 2 || dpu_kms->catalog->dsc_count >= 2) { + topology.num_dsc = 2; + topology.num_lm = 2; + } else { + topology.num_dsc = 1; + topology.num_lm = 1; + } +- topology.num_intf = 1; + } + + return topology; +-- +2.39.5 + diff --git a/queue-6.14/drm-msm-dpu-simplify-dpu_encoder_get_topology-interf.patch b/queue-6.14/drm-msm-dpu-simplify-dpu_encoder_get_topology-interf.patch new file mode 100644 index 0000000000..ca0875a65d --- /dev/null +++ b/queue-6.14/drm-msm-dpu-simplify-dpu_encoder_get_topology-interf.patch @@ -0,0 +1,68 @@ +From 9ac3a887d8b528aea5352412286f351b0eba0c04 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 14:43:35 +0200 +Subject: drm/msm/dpu: simplify dpu_encoder_get_topology() interface + +From: Dmitry Baryshkov + +[ Upstream commit 41921f231abf9a3a95550b2b565df8e4329319cb ] + +As a preparation for calling dpu_encoder_get_topology() from different +code paths, simplify its calling interface, obtaining some data pointers +internally instead passing them via arguments. + +Reviewed-by: Abhinav Kumar +Signed-off-by: Dmitry Baryshkov +Patchwork: https://patchwork.freedesktop.org/patch/633396/ +Link: https://lore.kernel.org/r/20250123-drm-dirty-modeset-v2-3-bbfd3a6cd1a4@linaro.org +Stable-dep-of: 2dde2aadaed1 ("drm/msm/dpu: don't set crtc_state->mode_changed from atomic_check()") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +index 66dc2b1dee7f8..9928e72dfabda 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +@@ -649,14 +649,14 @@ struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc) + + static struct msm_display_topology dpu_encoder_get_topology( + struct dpu_encoder_virt *dpu_enc, +- struct dpu_kms *dpu_kms, + struct drm_display_mode *mode, + struct drm_crtc_state *crtc_state, +- struct drm_connector_state *conn_state, +- struct drm_dsc_config *dsc) ++ struct drm_connector_state *conn_state) + { + struct msm_drm_private *priv = dpu_enc->base.dev->dev_private; + struct msm_display_info *disp_info = &dpu_enc->disp_info; ++ struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms); ++ struct drm_dsc_config *dsc = dpu_encoder_get_dsc_config(&dpu_enc->base); + struct msm_display_topology topology = {0}; + int i, intf_count = 0; + +@@ -771,7 +771,6 @@ static int dpu_encoder_virt_atomic_check( + struct drm_display_mode *adj_mode; + struct msm_display_topology topology; + struct dpu_global_state *global_state; +- struct drm_dsc_config *dsc; + int ret = 0; + + if (!drm_enc || !crtc_state || !conn_state) { +@@ -792,10 +791,7 @@ static int dpu_encoder_virt_atomic_check( + + trace_dpu_enc_atomic_check(DRMID(drm_enc)); + +- dsc = dpu_encoder_get_dsc_config(drm_enc); +- +- topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode, crtc_state, conn_state, +- dsc); ++ topology = dpu_encoder_get_topology(dpu_enc, adj_mode, crtc_state, conn_state); + + if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm) + crtc_state->mode_changed = true; +-- +2.39.5 + diff --git a/queue-6.14/drm-msm-dsi-phy-program-clock-inverters-in-correct-r.patch b/queue-6.14/drm-msm-dsi-phy-program-clock-inverters-in-correct-r.patch new file mode 100644 index 0000000000..0ae4991491 --- /dev/null +++ b/queue-6.14/drm-msm-dsi-phy-program-clock-inverters-in-correct-r.patch @@ -0,0 +1,42 @@ +From 06455d83d17dbb97615cca36874df18c00cfe1c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 12:55:04 +0100 +Subject: drm/msm/dsi/phy: Program clock inverters in correct register + +From: Krzysztof Kozlowski + +[ Upstream commit baf49072877726616c7f5943a6b45eb86bfeca0a ] + +Since SM8250 all downstream sources program clock inverters in +PLL_CLOCK_INVERTERS_1 register and leave the PLL_CLOCK_INVERTERS as +reset value (0x0). The most recent Hardware Programming Guide for 3 nm, +4 nm, 5 nm and 7 nm PHYs also mention PLL_CLOCK_INVERTERS_1. + +Signed-off-by: Krzysztof Kozlowski +Fixes: 1ef7c99d145c ("drm/msm/dsi: add support for 7nm DSI PHY/PLL") +Reviewed-by: Dmitry Baryshkov +Reported-by: Abhinav Kumar +Patchwork: https://patchwork.freedesktop.org/patch/634489/ +Link: https://lore.kernel.org/r/20250129115504.40080-1-krzysztof.kozlowski@linaro.org +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +index 798168180c1ab..a2c87c84aa05b 100644 +--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c ++++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +@@ -305,7 +305,7 @@ static void dsi_pll_commit(struct dsi_pll_7nm *pll, struct dsi_pll_config *confi + writel(pll->phy->cphy_mode ? 0x00 : 0x10, + base + REG_DSI_7nm_PHY_PLL_CMODE_1); + writel(config->pll_clock_inverters, +- base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS); ++ base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS_1); + } + + static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, unsigned long rate, +-- +2.39.5 + diff --git a/queue-6.14/drm-msm-dsi-set-phy-usescase-and-mode-before-registe.patch b/queue-6.14/drm-msm-dsi-set-phy-usescase-and-mode-before-registe.patch new file mode 100644 index 0000000000..781f8e18b1 --- /dev/null +++ b/queue-6.14/drm-msm-dsi-set-phy-usescase-and-mode-before-registe.patch @@ -0,0 +1,102 @@ +From 753a48ae6384ce86bf8bd088708f0d2fbcea4699 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 12:17:42 +0100 +Subject: drm/msm/dsi: Set PHY usescase (and mode) before registering DSI host + +From: Marijn Suijten + +[ Upstream commit 660c396c98c061f9696bebacc178b74072e80054 ] + +Ordering issues here cause an uninitialized (default STANDALONE) +usecase to be programmed (which appears to be a MUX) in some cases +when msm_dsi_host_register() is called, leading to the slave PLL in +bonded-DSI mode to source from a clock parent (dsi1vco) that is off. + +This should seemingly not be a problem as the actual dispcc clocks from +DSI1 that are muxed in the clock tree of DSI0 are way further down, this +bit still seems to have an effect on them somehow and causes the right +side of the panel controlled by DSI1 to not function. + +In an ideal world this code is refactored to no longer have such +error-prone calls "across subsystems", and instead model the "PLL src" +register field as a regular mux so that changing the clock parents +programmatically or in DTS via `assigned-clock-parents` has the +desired effect. +But for the avid reader, the clocks that we *are* muxing into DSI0's +tree are way further down, so if this bit turns out to be a simple mux +between dsiXvco and out_div, that shouldn't have any effect as this +whole tree is off anyway. + +Fixes: 57bf43389337 ("drm/msm/dsi: Pass down use case to PHY") +Reviewed-by: Abhinav Kumar +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Marijn Suijten +Patchwork: https://patchwork.freedesktop.org/patch/637650/ +Link: https://lore.kernel.org/r/20250217-drm-msm-initial-dualpipe-dsc-fixes-v3-2-913100d6103f@somainline.org +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/dsi/dsi_manager.c | 32 ++++++++++++++++++--------- + 1 file changed, 21 insertions(+), 11 deletions(-) + +diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c +index a210b7c9e5ca2..4fabb01345aa2 100644 +--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c ++++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c +@@ -74,17 +74,35 @@ static int dsi_mgr_setup_components(int id) + int ret; + + if (!IS_BONDED_DSI()) { ++ /* ++ * Set the usecase before calling msm_dsi_host_register(), which would ++ * already program the PLL source mux based on a default usecase. ++ */ ++ msm_dsi_phy_set_usecase(msm_dsi->phy, MSM_DSI_PHY_STANDALONE); ++ msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); ++ + ret = msm_dsi_host_register(msm_dsi->host); + if (ret) + return ret; +- +- msm_dsi_phy_set_usecase(msm_dsi->phy, MSM_DSI_PHY_STANDALONE); +- msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); + } else if (other_dsi) { + struct msm_dsi *master_link_dsi = IS_MASTER_DSI_LINK(id) ? + msm_dsi : other_dsi; + struct msm_dsi *slave_link_dsi = IS_MASTER_DSI_LINK(id) ? + other_dsi : msm_dsi; ++ ++ /* ++ * PLL0 is to drive both DSI link clocks in bonded DSI mode. ++ * ++ * Set the usecase before calling msm_dsi_host_register(), which would ++ * already program the PLL source mux based on a default usecase. ++ */ ++ msm_dsi_phy_set_usecase(clk_master_dsi->phy, ++ MSM_DSI_PHY_MASTER); ++ msm_dsi_phy_set_usecase(clk_slave_dsi->phy, ++ MSM_DSI_PHY_SLAVE); ++ msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); ++ msm_dsi_host_set_phy_mode(other_dsi->host, other_dsi->phy); ++ + /* Register slave host first, so that slave DSI device + * has a chance to probe, and do not block the master + * DSI device's probe. +@@ -98,14 +116,6 @@ static int dsi_mgr_setup_components(int id) + ret = msm_dsi_host_register(master_link_dsi->host); + if (ret) + return ret; +- +- /* PLL0 is to drive both 2 DSI link clocks in bonded DSI mode. */ +- msm_dsi_phy_set_usecase(clk_master_dsi->phy, +- MSM_DSI_PHY_MASTER); +- msm_dsi_phy_set_usecase(clk_slave_dsi->phy, +- MSM_DSI_PHY_SLAVE); +- msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); +- msm_dsi_host_set_phy_mode(other_dsi->host, other_dsi->phy); + } + + return 0; +-- +2.39.5 + diff --git a/queue-6.14/drm-msm-dsi-use-existing-per-interface-slice-count-i.patch b/queue-6.14/drm-msm-dsi-use-existing-per-interface-slice-count-i.patch new file mode 100644 index 0000000000..0a4cca957b --- /dev/null +++ b/queue-6.14/drm-msm-dsi-use-existing-per-interface-slice-count-i.patch @@ -0,0 +1,107 @@ +From aa72269c9319da1669d2f50fda01405503ada39d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 12:17:41 +0100 +Subject: drm/msm/dsi: Use existing per-interface slice count in DSC timing + +From: Marijn Suijten + +[ Upstream commit 14ad809ceb66d0874cbe4bd5ca9edf0de8d9ad96 ] + +When configuring the timing of DSI hosts (interfaces) in +dsi_timing_setup() all values written to registers are taking +bonded-mode into account by dividing the original mode width by 2 +(half the data is sent over each of the two DSI hosts), but the full +width instead of the interface width is passed as hdisplay parameter to +dsi_update_dsc_timing(). + +Currently only msm_dsc_get_slices_per_intf() is called within +dsi_update_dsc_timing() with the `hdisplay` argument which clearly +documents that it wants the width of a single interface (which, again, +in bonded DSI mode is half the total width of the mode) resulting in all +subsequent values to be completely off. + +However, as soon as we start to pass the halved hdisplay +into dsi_update_dsc_timing() we might as well discard +msm_dsc_get_slices_per_intf() since the value it calculates is already +available in dsc->slice_count which is per-interface by the current +design of MSM DPU/DSI implementations and their use of the DRM DSC +helpers. + +Fixes: 08802f515c3c ("drm/msm/dsi: Add support for DSC configuration") +Reviewed-by: Dmitry Baryshkov +Reviewed-by: Jessica Zhang +Signed-off-by: Marijn Suijten +Patchwork: https://patchwork.freedesktop.org/patch/637648/ +Link: https://lore.kernel.org/r/20250217-drm-msm-initial-dualpipe-dsc-fixes-v3-1-913100d6103f@somainline.org +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/dsi/dsi_host.c | 8 ++++---- + drivers/gpu/drm/msm/msm_dsc_helper.h | 11 ----------- + 2 files changed, 4 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c +index 007311c21fdaa..42e100a8adca0 100644 +--- a/drivers/gpu/drm/msm/dsi/dsi_host.c ++++ b/drivers/gpu/drm/msm/dsi/dsi_host.c +@@ -846,7 +846,7 @@ static void dsi_ctrl_enable(struct msm_dsi_host *msm_host, + dsi_write(msm_host, REG_DSI_CPHY_MODE_CTRL, BIT(0)); + } + +-static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mode, u32 hdisplay) ++static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mode) + { + struct drm_dsc_config *dsc = msm_host->dsc; + u32 reg, reg_ctrl, reg_ctrl2; +@@ -858,7 +858,7 @@ static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mod + /* first calculate dsc parameters and then program + * compress mode registers + */ +- slice_per_intf = msm_dsc_get_slices_per_intf(dsc, hdisplay); ++ slice_per_intf = dsc->slice_count; + + total_bytes_per_intf = dsc->slice_chunk_size * slice_per_intf; + bytes_per_pkt = dsc->slice_chunk_size; /* * slice_per_pkt; */ +@@ -991,7 +991,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) + + if (msm_host->mode_flags & MIPI_DSI_MODE_VIDEO) { + if (msm_host->dsc) +- dsi_update_dsc_timing(msm_host, false, mode->hdisplay); ++ dsi_update_dsc_timing(msm_host, false); + + dsi_write(msm_host, REG_DSI_ACTIVE_H, + DSI_ACTIVE_H_START(ha_start) | +@@ -1012,7 +1012,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) + DSI_ACTIVE_VSYNC_VPOS_END(vs_end)); + } else { /* command mode */ + if (msm_host->dsc) +- dsi_update_dsc_timing(msm_host, true, mode->hdisplay); ++ dsi_update_dsc_timing(msm_host, true); + + /* image data and 1 byte write_memory_start cmd */ + if (!msm_host->dsc) +diff --git a/drivers/gpu/drm/msm/msm_dsc_helper.h b/drivers/gpu/drm/msm/msm_dsc_helper.h +index b9049fe1e2790..63f95523b2cbb 100644 +--- a/drivers/gpu/drm/msm/msm_dsc_helper.h ++++ b/drivers/gpu/drm/msm/msm_dsc_helper.h +@@ -12,17 +12,6 @@ + #include + #include + +-/** +- * msm_dsc_get_slices_per_intf() - calculate number of slices per interface +- * @dsc: Pointer to drm dsc config struct +- * @intf_width: interface width in pixels +- * Returns: Integer representing the number of slices for the given interface +- */ +-static inline u32 msm_dsc_get_slices_per_intf(const struct drm_dsc_config *dsc, u32 intf_width) +-{ +- return DIV_ROUND_UP(intf_width, dsc->slice_width); +-} +- + /** + * msm_dsc_get_bytes_per_line() - calculate bytes per line + * @dsc: Pointer to drm dsc config struct +-- +2.39.5 + diff --git a/queue-6.14/drm-msm-gem-fix-error-code-msm_parse_deps.patch b/queue-6.14/drm-msm-gem-fix-error-code-msm_parse_deps.patch new file mode 100644 index 0000000000..ca3fc0df3d --- /dev/null +++ b/queue-6.14/drm-msm-gem-fix-error-code-msm_parse_deps.patch @@ -0,0 +1,39 @@ +From 059c78219060cdfdf2d3f056d310a46b65b91d77 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 10:32:11 +0300 +Subject: drm/msm/gem: Fix error code msm_parse_deps() + +From: Dan Carpenter + +[ Upstream commit 0b305b7cadce835505bd93183a599acb1f800a05 ] + +The SUBMIT_ERROR() macro turns the error code negative. This extra '-' +operation turns it back to positive EINVAL again. The error code is +passed to ERR_PTR() and since positive values are not an IS_ERR() it +eventually will lead to an oops. Delete the '-'. + +Fixes: 866e43b945bf ("drm/msm: UAPI error reporting") +Signed-off-by: Dan Carpenter +Patchwork: https://patchwork.freedesktop.org/patch/637625/ +Signed-off-by: Rob Clark +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/msm_gem_submit.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c +index dee4704030368..3e9aa2cc38ef9 100644 +--- a/drivers/gpu/drm/msm/msm_gem_submit.c ++++ b/drivers/gpu/drm/msm/msm_gem_submit.c +@@ -509,7 +509,7 @@ static struct drm_syncobj **msm_parse_deps(struct msm_gem_submit *submit, + } + + if (syncobj_desc.flags & ~MSM_SUBMIT_SYNCOBJ_FLAGS) { +- ret = -SUBMIT_ERROR(EINVAL, submit, "invalid syncobj flags: %x", syncobj_desc.flags); ++ ret = SUBMIT_ERROR(EINVAL, submit, "invalid syncobj flags: %x", syncobj_desc.flags); + break; + } + +-- +2.39.5 + diff --git a/queue-6.14/drm-panel-ilitek-ili9882t-fix-gpio-name-in-error-mes.patch b/queue-6.14/drm-panel-ilitek-ili9882t-fix-gpio-name-in-error-mes.patch new file mode 100644 index 0000000000..13dac7dd79 --- /dev/null +++ b/queue-6.14/drm-panel-ilitek-ili9882t-fix-gpio-name-in-error-mes.patch @@ -0,0 +1,38 @@ +From 1d5d35b495b83235dcfbc6ba4041ffa12cae3a3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 12:04:28 +0000 +Subject: drm/panel: ilitek-ili9882t: fix GPIO name in error message + +From: John Keeping + +[ Upstream commit 4ce2c7e201c265df1c62a9190a98a98803208b8f ] + +This driver uses the enable-gpios property and it is confusing that the +error message refers to reset-gpios. Use the correct name when the +enable GPIO is not found. + +Fixes: e2450d32e5fb5 ("drm/panel: ili9882t: Break out as separate driver") +Signed-off-by: John Keeping +Signed-off-by: Linus Walleij +Link: https://patchwork.freedesktop.org/patch/msgid/20250217120428.3779197-1-jkeeping@inmusicbrands.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panel/panel-ilitek-ili9882t.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c +index 266a087fe14c1..3c24a63b6be8c 100644 +--- a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c ++++ b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c +@@ -607,7 +607,7 @@ static int ili9882t_add(struct ili9882t *ili) + + ili->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); + if (IS_ERR(ili->enable_gpio)) { +- dev_err(dev, "cannot get reset-gpios %ld\n", ++ dev_err(dev, "cannot get enable-gpios %ld\n", + PTR_ERR(ili->enable_gpio)); + return PTR_ERR(ili->enable_gpio); + } +-- +2.39.5 + diff --git a/queue-6.14/drm-panthor-avoid-sleep-locking-in-the-internal-bo-s.patch b/queue-6.14/drm-panthor-avoid-sleep-locking-in-the-internal-bo-s.patch new file mode 100644 index 0000000000..55a46ee7cc --- /dev/null +++ b/queue-6.14/drm-panthor-avoid-sleep-locking-in-the-internal-bo-s.patch @@ -0,0 +1,245 @@ +From 5618520687a1aabaad30d8689d6733e1d6efaf92 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 19:08:46 +0000 +Subject: drm/panthor: Avoid sleep locking in the internal BO size path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Adrián Larumbe + +[ Upstream commit c63c3bfdde2656a3ead50ac3ce4a51a634e22dab ] + +Commit 434e5ca5b5d7 ("drm/panthor: Expose size of driver internal BO's over +fdinfo") locks the VMS xarray, to avoid UAF errors when the same VM is +being concurrently destroyed by another thread. However, that puts the +current thread in atomic context, which means taking the VMS' heap locks +will trigger a warning as the thread is no longer allowed to sleep. + +Because in this case replacing the heap mutex with a spinlock isn't +feasible, the fdinfo handler no longer traverses the list of heaps for +every single VM associated with an open DRM file. Instead, when a new heap +chunk is allocated, its size is accumulated into a pool-wide tally, which +also makes the atomic context code path somewhat faster. + +Signed-off-by: Adrián Larumbe +Fixes: 434e5ca5b5d7 ("drm/panthor: Expose size of driver internal BO's over fdinfo") +Reviewed-by: Boris Brezillon +Reviewed-by: Steven Price +Signed-off-by: Steven Price +Link: https://patchwork.freedesktop.org/patch/msgid/20250303190923.1639985-2-adrian.larumbe@collabora.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panthor/panthor_heap.c | 62 +++++++++++++------------- + drivers/gpu/drm/panthor/panthor_mmu.c | 8 +--- + 2 files changed, 31 insertions(+), 39 deletions(-) + +diff --git a/drivers/gpu/drm/panthor/panthor_heap.c b/drivers/gpu/drm/panthor/panthor_heap.c +index db0285ce58126..3bdf61c142644 100644 +--- a/drivers/gpu/drm/panthor/panthor_heap.c ++++ b/drivers/gpu/drm/panthor/panthor_heap.c +@@ -97,6 +97,9 @@ struct panthor_heap_pool { + + /** @gpu_contexts: Buffer object containing the GPU heap contexts. */ + struct panthor_kernel_bo *gpu_contexts; ++ ++ /** @size: Size of all chunks across all heaps in the pool. */ ++ atomic_t size; + }; + + static int panthor_heap_ctx_stride(struct panthor_device *ptdev) +@@ -118,7 +121,7 @@ static void *panthor_get_heap_ctx(struct panthor_heap_pool *pool, int id) + panthor_get_heap_ctx_offset(pool, id); + } + +-static void panthor_free_heap_chunk(struct panthor_vm *vm, ++static void panthor_free_heap_chunk(struct panthor_heap_pool *pool, + struct panthor_heap *heap, + struct panthor_heap_chunk *chunk) + { +@@ -127,12 +130,13 @@ static void panthor_free_heap_chunk(struct panthor_vm *vm, + heap->chunk_count--; + mutex_unlock(&heap->lock); + ++ atomic_sub(heap->chunk_size, &pool->size); ++ + panthor_kernel_bo_destroy(chunk->bo); + kfree(chunk); + } + +-static int panthor_alloc_heap_chunk(struct panthor_device *ptdev, +- struct panthor_vm *vm, ++static int panthor_alloc_heap_chunk(struct panthor_heap_pool *pool, + struct panthor_heap *heap, + bool initial_chunk) + { +@@ -144,7 +148,7 @@ static int panthor_alloc_heap_chunk(struct panthor_device *ptdev, + if (!chunk) + return -ENOMEM; + +- chunk->bo = panthor_kernel_bo_create(ptdev, vm, heap->chunk_size, ++ chunk->bo = panthor_kernel_bo_create(pool->ptdev, pool->vm, heap->chunk_size, + DRM_PANTHOR_BO_NO_MMAP, + DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC, + PANTHOR_VM_KERNEL_AUTO_VA); +@@ -180,6 +184,8 @@ static int panthor_alloc_heap_chunk(struct panthor_device *ptdev, + heap->chunk_count++; + mutex_unlock(&heap->lock); + ++ atomic_add(heap->chunk_size, &pool->size); ++ + return 0; + + err_destroy_bo: +@@ -191,17 +197,16 @@ static int panthor_alloc_heap_chunk(struct panthor_device *ptdev, + return ret; + } + +-static void panthor_free_heap_chunks(struct panthor_vm *vm, ++static void panthor_free_heap_chunks(struct panthor_heap_pool *pool, + struct panthor_heap *heap) + { + struct panthor_heap_chunk *chunk, *tmp; + + list_for_each_entry_safe(chunk, tmp, &heap->chunks, node) +- panthor_free_heap_chunk(vm, heap, chunk); ++ panthor_free_heap_chunk(pool, heap, chunk); + } + +-static int panthor_alloc_heap_chunks(struct panthor_device *ptdev, +- struct panthor_vm *vm, ++static int panthor_alloc_heap_chunks(struct panthor_heap_pool *pool, + struct panthor_heap *heap, + u32 chunk_count) + { +@@ -209,7 +214,7 @@ static int panthor_alloc_heap_chunks(struct panthor_device *ptdev, + u32 i; + + for (i = 0; i < chunk_count; i++) { +- ret = panthor_alloc_heap_chunk(ptdev, vm, heap, true); ++ ret = panthor_alloc_heap_chunk(pool, heap, true); + if (ret) + return ret; + } +@@ -226,7 +231,7 @@ panthor_heap_destroy_locked(struct panthor_heap_pool *pool, u32 handle) + if (!heap) + return -EINVAL; + +- panthor_free_heap_chunks(pool->vm, heap); ++ panthor_free_heap_chunks(pool, heap); + mutex_destroy(&heap->lock); + kfree(heap); + return 0; +@@ -308,8 +313,7 @@ int panthor_heap_create(struct panthor_heap_pool *pool, + heap->max_chunks = max_chunks; + heap->target_in_flight = target_in_flight; + +- ret = panthor_alloc_heap_chunks(pool->ptdev, vm, heap, +- initial_chunk_count); ++ ret = panthor_alloc_heap_chunks(pool, heap, initial_chunk_count); + if (ret) + goto err_free_heap; + +@@ -342,7 +346,7 @@ int panthor_heap_create(struct panthor_heap_pool *pool, + return id; + + err_free_heap: +- panthor_free_heap_chunks(pool->vm, heap); ++ panthor_free_heap_chunks(pool, heap); + mutex_destroy(&heap->lock); + kfree(heap); + +@@ -389,6 +393,7 @@ int panthor_heap_return_chunk(struct panthor_heap_pool *pool, + removed = chunk; + list_del(&chunk->node); + heap->chunk_count--; ++ atomic_sub(heap->chunk_size, &pool->size); + break; + } + } +@@ -466,7 +471,7 @@ int panthor_heap_grow(struct panthor_heap_pool *pool, + * further jobs in this queue fail immediately instead of having to + * wait for the job timeout. + */ +- ret = panthor_alloc_heap_chunk(pool->ptdev, pool->vm, heap, false); ++ ret = panthor_alloc_heap_chunk(pool, heap, false); + if (ret) + goto out_unlock; + +@@ -560,6 +565,8 @@ panthor_heap_pool_create(struct panthor_device *ptdev, struct panthor_vm *vm) + if (ret) + goto err_destroy_pool; + ++ atomic_add(pool->gpu_contexts->obj->size, &pool->size); ++ + return pool; + + err_destroy_pool: +@@ -594,8 +601,10 @@ void panthor_heap_pool_destroy(struct panthor_heap_pool *pool) + xa_for_each(&pool->xa, i, heap) + drm_WARN_ON(&pool->ptdev->base, panthor_heap_destroy_locked(pool, i)); + +- if (!IS_ERR_OR_NULL(pool->gpu_contexts)) ++ if (!IS_ERR_OR_NULL(pool->gpu_contexts)) { ++ atomic_sub(pool->gpu_contexts->obj->size, &pool->size); + panthor_kernel_bo_destroy(pool->gpu_contexts); ++ } + + /* Reflects the fact the pool has been destroyed. */ + pool->vm = NULL; +@@ -605,27 +614,16 @@ void panthor_heap_pool_destroy(struct panthor_heap_pool *pool) + } + + /** +- * panthor_heap_pool_size() - Calculate size of all chunks across all heaps in a pool +- * @pool: Pool whose total chunk size to calculate. ++ * panthor_heap_pool_size() - Get a heap pool's total size ++ * @pool: Pool whose total chunks size to return + * +- * This function adds the size of all heap chunks across all heaps in the +- * argument pool. It also adds the size of the gpu contexts kernel bo. +- * It is meant to be used by fdinfo for displaying the size of internal +- * driver BO's that aren't exposed to userspace through a GEM handle. ++ * Returns the aggregated size of all chunks for all heaps in the pool + * + */ + size_t panthor_heap_pool_size(struct panthor_heap_pool *pool) + { +- struct panthor_heap *heap; +- unsigned long i; +- size_t size = 0; +- +- down_read(&pool->lock); +- xa_for_each(&pool->xa, i, heap) +- size += heap->chunk_size * heap->chunk_count; +- up_read(&pool->lock); +- +- size += pool->gpu_contexts->obj->size; ++ if (!pool) ++ return 0; + +- return size; ++ return atomic_read(&pool->size); + } +diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c +index 11771ca8147f9..1202de8811c2a 100644 +--- a/drivers/gpu/drm/panthor/panthor_mmu.c ++++ b/drivers/gpu/drm/panthor/panthor_mmu.c +@@ -1960,13 +1960,7 @@ void panthor_vm_heaps_sizes(struct panthor_file *pfile, struct drm_memory_stats + + xa_lock(&pfile->vms->xa); + xa_for_each(&pfile->vms->xa, i, vm) { +- size_t size = 0; +- +- mutex_lock(&vm->heaps.lock); +- if (vm->heaps.pool) +- size = panthor_heap_pool_size(vm->heaps.pool); +- mutex_unlock(&vm->heaps.lock); +- ++ size_t size = panthor_heap_pool_size(vm->heaps.pool); + stats->resident += size; + if (vm->as.id >= 0) + stats->active += size; +-- +2.39.5 + diff --git a/queue-6.14/drm-panthor-clean-up-fw-version-information-display.patch b/queue-6.14/drm-panthor-clean-up-fw-version-information-display.patch new file mode 100644 index 0000000000..5611036773 --- /dev/null +++ b/queue-6.14/drm-panthor-clean-up-fw-version-information-display.patch @@ -0,0 +1,67 @@ +From d780913eb6c767d9885664b4f787537f4fefbcac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 16:12:48 +0000 +Subject: drm/panthor: Clean up FW version information display + +From: Steven Price + +[ Upstream commit 3b87886bfb038de2c62e627079472ba612e89410 ] + +Assigning a string to an array which is too small to include the NUL +byte at the end causes a warning on some compilers. But this function +also has some other oddities like the 'header' array which is only ever +used within sizeof(). + +Tidy up the function by removing the 'header' array, allow the NUL byte +to be present in git_sha_header, and calculate the length directly from +git_sha_header. + +Reported-by: Will Deacon +Closes: https://lore.kernel.org/all/20250213154237.GA11897@willie-the-truck/ +Fixes: 9d443deb0441 ("drm/panthor: Display FW version information") +Signed-off-by: Steven Price +Acked-by: Will Deacon +Reviewed-by: Boris Brezillon +Link: https://patchwork.freedesktop.org/patch/msgid/20250213161248.1642392-1-steven.price@arm.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panthor/panthor_fw.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor/panthor_fw.c +index 68eb4fb4d3a8a..a024b475b6887 100644 +--- a/drivers/gpu/drm/panthor/panthor_fw.c ++++ b/drivers/gpu/drm/panthor/panthor_fw.c +@@ -637,8 +637,8 @@ static int panthor_fw_read_build_info(struct panthor_device *ptdev, + u32 ehdr) + { + struct panthor_fw_build_info_hdr hdr; +- char header[9]; +- const char git_sha_header[sizeof(header)] = "git_sha: "; ++ static const char git_sha_header[] = "git_sha: "; ++ const int header_len = sizeof(git_sha_header) - 1; + int ret; + + ret = panthor_fw_binary_iter_read(ptdev, iter, &hdr, sizeof(hdr)); +@@ -652,8 +652,7 @@ static int panthor_fw_read_build_info(struct panthor_device *ptdev, + return 0; + } + +- if (memcmp(git_sha_header, fw->data + hdr.meta_start, +- sizeof(git_sha_header))) { ++ if (memcmp(git_sha_header, fw->data + hdr.meta_start, header_len)) { + /* Not the expected header, this isn't metadata we understand */ + return 0; + } +@@ -666,7 +665,7 @@ static int panthor_fw_read_build_info(struct panthor_device *ptdev, + } + + drm_info(&ptdev->base, "Firmware git sha: %s\n", +- fw->data + hdr.meta_start + sizeof(git_sha_header)); ++ fw->data + hdr.meta_start + header_len); + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/drm-panthor-expose-size-of-driver-internal-bo-s-over.patch b/queue-6.14/drm-panthor-expose-size-of-driver-internal-bo-s-over.patch new file mode 100644 index 0000000000..d5b7944ec4 --- /dev/null +++ b/queue-6.14/drm-panthor-expose-size-of-driver-internal-bo-s-over.patch @@ -0,0 +1,305 @@ +From a37045555c5f99e63e4e64225cb67b7965b55f05 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 17:28:11 +0000 +Subject: drm/panthor: Expose size of driver internal BO's over fdinfo +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Adrián Larumbe + +[ Upstream commit 434e5ca5b5d7ea415670d4fcb399d90d355a1e38 ] + +This will display the sizes of kenrel BO's bound to an open file, which are +otherwise not exposed to UM through a handle. + +The sizes recorded are as follows: + - Per group: suspend buffer, protm-suspend buffer, syncobjcs + - Per queue: ringbuffer, profiling slots, firmware interface + - For all heaps in all heap pools across all VM's bound to an open file, + record size of all heap chuks, and for each pool the gpu_context BO too. + +This does not record the size of FW regions, as these aren't bound to a +specific open file and remain active through the whole life of the driver. + +Reviewed-by: Liviu Dudau +Reviewed-by: Mihail Atanassov +Reviewed-by: Steven Price +Reviewed-by: Boris Brezillon +Signed-off-by: Adrián Larumbe +Signed-off-by: Boris Brezillon +Link: https://patchwork.freedesktop.org/patch/msgid/20250130172851.941597-4-adrian.larumbe@collabora.com +Stable-dep-of: e379856b428a ("drm/panthor: Replace sleep locks with spinlocks in fdinfo path") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panthor/panthor_drv.c | 14 +++++++ + drivers/gpu/drm/panthor/panthor_heap.c | 26 ++++++++++++ + drivers/gpu/drm/panthor/panthor_heap.h | 2 + + drivers/gpu/drm/panthor/panthor_mmu.c | 33 +++++++++++++++ + drivers/gpu/drm/panthor/panthor_mmu.h | 3 ++ + drivers/gpu/drm/panthor/panthor_sched.c | 56 ++++++++++++++++++++++++- + drivers/gpu/drm/panthor/panthor_sched.h | 3 ++ + 7 files changed, 136 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c +index 08136e790ca0a..06fe46e320738 100644 +--- a/drivers/gpu/drm/panthor/panthor_drv.c ++++ b/drivers/gpu/drm/panthor/panthor_drv.c +@@ -1458,12 +1458,26 @@ static void panthor_gpu_show_fdinfo(struct panthor_device *ptdev, + drm_printf(p, "drm-curfreq-panthor:\t%lu Hz\n", ptdev->current_frequency); + } + ++static void panthor_show_internal_memory_stats(struct drm_printer *p, struct drm_file *file) ++{ ++ char *drv_name = file->minor->dev->driver->name; ++ struct panthor_file *pfile = file->driver_priv; ++ struct drm_memory_stats stats = {0}; ++ ++ panthor_fdinfo_gather_group_mem_info(pfile, &stats); ++ panthor_vm_heaps_sizes(pfile, &stats); ++ ++ drm_fdinfo_print_size(p, drv_name, "resident", "memory", stats.resident); ++ drm_fdinfo_print_size(p, drv_name, "active", "memory", stats.active); ++} ++ + static void panthor_show_fdinfo(struct drm_printer *p, struct drm_file *file) + { + struct drm_device *dev = file->minor->dev; + struct panthor_device *ptdev = container_of(dev, struct panthor_device, base); + + panthor_gpu_show_fdinfo(ptdev, file->driver_priv, p); ++ panthor_show_internal_memory_stats(p, file); + + drm_show_memory_stats(p, file); + } +diff --git a/drivers/gpu/drm/panthor/panthor_heap.c b/drivers/gpu/drm/panthor/panthor_heap.c +index 3796a9eb22af2..db0285ce58126 100644 +--- a/drivers/gpu/drm/panthor/panthor_heap.c ++++ b/drivers/gpu/drm/panthor/panthor_heap.c +@@ -603,3 +603,29 @@ void panthor_heap_pool_destroy(struct panthor_heap_pool *pool) + + panthor_heap_pool_put(pool); + } ++ ++/** ++ * panthor_heap_pool_size() - Calculate size of all chunks across all heaps in a pool ++ * @pool: Pool whose total chunk size to calculate. ++ * ++ * This function adds the size of all heap chunks across all heaps in the ++ * argument pool. It also adds the size of the gpu contexts kernel bo. ++ * It is meant to be used by fdinfo for displaying the size of internal ++ * driver BO's that aren't exposed to userspace through a GEM handle. ++ * ++ */ ++size_t panthor_heap_pool_size(struct panthor_heap_pool *pool) ++{ ++ struct panthor_heap *heap; ++ unsigned long i; ++ size_t size = 0; ++ ++ down_read(&pool->lock); ++ xa_for_each(&pool->xa, i, heap) ++ size += heap->chunk_size * heap->chunk_count; ++ up_read(&pool->lock); ++ ++ size += pool->gpu_contexts->obj->size; ++ ++ return size; ++} +diff --git a/drivers/gpu/drm/panthor/panthor_heap.h b/drivers/gpu/drm/panthor/panthor_heap.h +index 25a5f2bba4457..e3358d4e8edb2 100644 +--- a/drivers/gpu/drm/panthor/panthor_heap.h ++++ b/drivers/gpu/drm/panthor/panthor_heap.h +@@ -27,6 +27,8 @@ struct panthor_heap_pool * + panthor_heap_pool_get(struct panthor_heap_pool *pool); + void panthor_heap_pool_put(struct panthor_heap_pool *pool); + ++size_t panthor_heap_pool_size(struct panthor_heap_pool *pool); ++ + int panthor_heap_grow(struct panthor_heap_pool *pool, + u64 heap_gpu_va, + u32 renderpasses_in_flight, +diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c +index c39e3eb1c15d5..11771ca8147f9 100644 +--- a/drivers/gpu/drm/panthor/panthor_mmu.c ++++ b/drivers/gpu/drm/panthor/panthor_mmu.c +@@ -1941,6 +1941,39 @@ struct panthor_heap_pool *panthor_vm_get_heap_pool(struct panthor_vm *vm, bool c + return pool; + } + ++/** ++ * panthor_vm_heaps_sizes() - Calculate size of all heap chunks across all ++ * heaps over all the heap pools in a VM ++ * @pfile: File. ++ * @stats: Memory stats to be updated. ++ * ++ * Calculate all heap chunk sizes in all heap pools bound to a VM. If the VM ++ * is active, record the size as active as well. ++ */ ++void panthor_vm_heaps_sizes(struct panthor_file *pfile, struct drm_memory_stats *stats) ++{ ++ struct panthor_vm *vm; ++ unsigned long i; ++ ++ if (!pfile->vms) ++ return; ++ ++ xa_lock(&pfile->vms->xa); ++ xa_for_each(&pfile->vms->xa, i, vm) { ++ size_t size = 0; ++ ++ mutex_lock(&vm->heaps.lock); ++ if (vm->heaps.pool) ++ size = panthor_heap_pool_size(vm->heaps.pool); ++ mutex_unlock(&vm->heaps.lock); ++ ++ stats->resident += size; ++ if (vm->as.id >= 0) ++ stats->active += size; ++ } ++ xa_unlock(&pfile->vms->xa); ++} ++ + static u64 mair_to_memattr(u64 mair, bool coherent) + { + u64 memattr = 0; +diff --git a/drivers/gpu/drm/panthor/panthor_mmu.h b/drivers/gpu/drm/panthor/panthor_mmu.h +index 8d21e83d8aba1..fc274637114e5 100644 +--- a/drivers/gpu/drm/panthor/panthor_mmu.h ++++ b/drivers/gpu/drm/panthor/panthor_mmu.h +@@ -9,6 +9,7 @@ + + struct drm_exec; + struct drm_sched_job; ++struct drm_memory_stats; + struct panthor_gem_object; + struct panthor_heap_pool; + struct panthor_vm; +@@ -37,6 +38,8 @@ int panthor_vm_flush_all(struct panthor_vm *vm); + struct panthor_heap_pool * + panthor_vm_get_heap_pool(struct panthor_vm *vm, bool create); + ++void panthor_vm_heaps_sizes(struct panthor_file *pfile, struct drm_memory_stats *stats); ++ + struct panthor_vm *panthor_vm_get(struct panthor_vm *vm); + void panthor_vm_put(struct panthor_vm *vm); + struct panthor_vm *panthor_vm_create(struct panthor_device *ptdev, bool for_mcu, +diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c +index 1349581196780..2f92ef2b5ab99 100644 +--- a/drivers/gpu/drm/panthor/panthor_sched.c ++++ b/drivers/gpu/drm/panthor/panthor_sched.c +@@ -628,7 +628,7 @@ struct panthor_group { + */ + struct panthor_kernel_bo *syncobjs; + +- /** @fdinfo: Per-file total cycle and timestamp values reference. */ ++ /** @fdinfo: Per-file info exposed through /proc//fdinfo */ + struct { + /** @data: Total sampled values for jobs in queues from this group. */ + struct panthor_gpu_usage data; +@@ -638,6 +638,9 @@ struct panthor_group { + * and job post-completion processing function + */ + struct mutex lock; ++ ++ /** @fdinfo.kbo_sizes: Aggregate size of private kernel BO's held by the group. */ ++ size_t kbo_sizes; + } fdinfo; + + /** @state: Group state. */ +@@ -3383,6 +3386,29 @@ group_create_queue(struct panthor_group *group, + return ERR_PTR(ret); + } + ++static void add_group_kbo_sizes(struct panthor_device *ptdev, ++ struct panthor_group *group) ++{ ++ struct panthor_queue *queue; ++ int i; ++ ++ if (drm_WARN_ON(&ptdev->base, IS_ERR_OR_NULL(group))) ++ return; ++ if (drm_WARN_ON(&ptdev->base, ptdev != group->ptdev)) ++ return; ++ ++ group->fdinfo.kbo_sizes += group->suspend_buf->obj->size; ++ group->fdinfo.kbo_sizes += group->protm_suspend_buf->obj->size; ++ group->fdinfo.kbo_sizes += group->syncobjs->obj->size; ++ ++ for (i = 0; i < group->queue_count; i++) { ++ queue = group->queues[i]; ++ group->fdinfo.kbo_sizes += queue->ringbuf->obj->size; ++ group->fdinfo.kbo_sizes += queue->iface.mem->obj->size; ++ group->fdinfo.kbo_sizes += queue->profiling.slots->obj->size; ++ } ++} ++ + #define MAX_GROUPS_PER_POOL 128 + + int panthor_group_create(struct panthor_file *pfile, +@@ -3507,6 +3533,7 @@ int panthor_group_create(struct panthor_file *pfile, + } + mutex_unlock(&sched->reset.lock); + ++ add_group_kbo_sizes(group->ptdev, group); + mutex_init(&group->fdinfo.lock); + + return gid; +@@ -3626,6 +3653,33 @@ void panthor_group_pool_destroy(struct panthor_file *pfile) + pfile->groups = NULL; + } + ++/** ++ * panthor_fdinfo_gather_group_mem_info() - Retrieve aggregate size of all private kernel BO's ++ * belonging to all the groups owned by an open Panthor file ++ * @pfile: File. ++ * @stats: Memory statistics to be updated. ++ * ++ */ ++void ++panthor_fdinfo_gather_group_mem_info(struct panthor_file *pfile, ++ struct drm_memory_stats *stats) ++{ ++ struct panthor_group_pool *gpool = pfile->groups; ++ struct panthor_group *group; ++ unsigned long i; ++ ++ if (IS_ERR_OR_NULL(gpool)) ++ return; ++ ++ xa_lock(&gpool->xa); ++ xa_for_each(&gpool->xa, i, group) { ++ stats->resident += group->fdinfo.kbo_sizes; ++ if (group->csg_id >= 0) ++ stats->active += group->fdinfo.kbo_sizes; ++ } ++ xa_unlock(&gpool->xa); ++} ++ + static void job_release(struct kref *ref) + { + struct panthor_job *job = container_of(ref, struct panthor_job, refcount); +diff --git a/drivers/gpu/drm/panthor/panthor_sched.h b/drivers/gpu/drm/panthor/panthor_sched.h +index 5ae6b4bde7c50..e650a445cf507 100644 +--- a/drivers/gpu/drm/panthor/panthor_sched.h ++++ b/drivers/gpu/drm/panthor/panthor_sched.h +@@ -9,6 +9,7 @@ struct dma_fence; + struct drm_file; + struct drm_gem_object; + struct drm_sched_job; ++struct drm_memory_stats; + struct drm_panthor_group_create; + struct drm_panthor_queue_create; + struct drm_panthor_group_get_state; +@@ -36,6 +37,8 @@ void panthor_job_update_resvs(struct drm_exec *exec, struct drm_sched_job *job); + + int panthor_group_pool_create(struct panthor_file *pfile); + void panthor_group_pool_destroy(struct panthor_file *pfile); ++void panthor_fdinfo_gather_group_mem_info(struct panthor_file *pfile, ++ struct drm_memory_stats *stats); + + int panthor_sched_init(struct panthor_device *ptdev); + void panthor_sched_unplug(struct panthor_device *ptdev); +-- +2.39.5 + diff --git a/queue-6.14/drm-panthor-fix-a-race-between-the-reset-and-suspend.patch b/queue-6.14/drm-panthor-fix-a-race-between-the-reset-and-suspend.patch new file mode 100644 index 0000000000..6302a707c8 --- /dev/null +++ b/queue-6.14/drm-panthor-fix-a-race-between-the-reset-and-suspend.patch @@ -0,0 +1,80 @@ +From eba19235c328f83f21b367a1c29cff18b4fb6767 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Dec 2024 10:24:57 +0100 +Subject: drm/panthor: Fix a race between the reset and suspend path + +From: Boris Brezillon + +[ Upstream commit 57e233c3bd63f32d2c7e937db2e16b98f723ce2f ] + +If a reset is scheduled when the suspend happens, we drop the +reset-pending info on the floor assuming the resume will fix things, +but the resume logic might try a fast reset. If we're lucky, the +fast reset fails and we fallback to a slow reset, but if the FW was +corrupted in a way that makes it partially functional (it boots but +doesn't quite do what it's expected to do), we won't notice immediately +that things are not working correctly, leading to a new reset further +down the road. + +Fixes: 5fe909cae118 ("drm/panthor: Add the device logical block") +Signed-off-by: Boris Brezillon +Reviewed-by: Liviu Dudau +Reviewed-by: Steven Price +Signed-off-by: Steven Price +Link: https://patchwork.freedesktop.org/patch/msgid/20241217092457.1582053-1-boris.brezillon@collabora.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panthor/panthor_device.c | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c +index 0a37cfeeb181c..a9da1d1eeb707 100644 +--- a/drivers/gpu/drm/panthor/panthor_device.c ++++ b/drivers/gpu/drm/panthor/panthor_device.c +@@ -128,14 +128,11 @@ static void panthor_device_reset_work(struct work_struct *work) + struct panthor_device *ptdev = container_of(work, struct panthor_device, reset.work); + int ret = 0, cookie; + +- if (atomic_read(&ptdev->pm.state) != PANTHOR_DEVICE_PM_STATE_ACTIVE) { +- /* +- * No need for a reset as the device has been (or will be) +- * powered down +- */ +- atomic_set(&ptdev->reset.pending, 0); ++ /* If the device is entering suspend, we don't reset. A slow reset will ++ * be forced at resume time instead. ++ */ ++ if (atomic_read(&ptdev->pm.state) != PANTHOR_DEVICE_PM_STATE_ACTIVE) + return; +- } + + if (!drm_dev_enter(&ptdev->base, &cookie)) + return; +@@ -477,6 +474,14 @@ int panthor_device_resume(struct device *dev) + + if (panthor_device_is_initialized(ptdev) && + drm_dev_enter(&ptdev->base, &cookie)) { ++ /* If there was a reset pending at the time we suspended the ++ * device, we force a slow reset. ++ */ ++ if (atomic_read(&ptdev->reset.pending)) { ++ ptdev->reset.fast = false; ++ atomic_set(&ptdev->reset.pending, 0); ++ } ++ + ret = panthor_device_resume_hw_components(ptdev); + if (ret && ptdev->reset.fast) { + drm_err(&ptdev->base, "Fast reset failed, trying a slow reset"); +@@ -493,9 +498,6 @@ int panthor_device_resume(struct device *dev) + goto err_suspend_devfreq; + } + +- if (atomic_read(&ptdev->reset.pending)) +- queue_work(ptdev->reset.wq, &ptdev->reset.work); +- + /* Clear all IOMEM mappings pointing to this device after we've + * resumed. This way the fake mappings pointing to the dummy pages + * are removed and the real iomem mapping will be restored on next +-- +2.39.5 + diff --git a/queue-6.14/drm-panthor-fix-race-condition-when-gathering-fdinfo.patch b/queue-6.14/drm-panthor-fix-race-condition-when-gathering-fdinfo.patch new file mode 100644 index 0000000000..5d2c8b8b29 --- /dev/null +++ b/queue-6.14/drm-panthor-fix-race-condition-when-gathering-fdinfo.patch @@ -0,0 +1,51 @@ +From 46688cadec453fc9131fd937bac4020eadc5c1db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 17:28:13 +0000 +Subject: drm/panthor: Fix race condition when gathering fdinfo group samples +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Adrián Larumbe + +[ Upstream commit 0590c94c3596d6c1a3d549ae611366f2ad4e1d8d ] + +Commit e16635d88fa0 ("drm/panthor: add DRM fdinfo support") failed to +protect access to groups with an xarray lock, which could lead to +use-after-free errors. + +Fixes: e16635d88fa0 ("drm/panthor: add DRM fdinfo support") +Reviewed-by: Boris Brezillon +Reviewed-by: Steven Price +Signed-off-by: Adrián Larumbe +Signed-off-by: Boris Brezillon +Link: https://patchwork.freedesktop.org/patch/msgid/20250130172851.941597-6-adrian.larumbe@collabora.com +Link: https://patchwork.freedesktop.org/patch/msgid/20250107173310.88329-1-florent.tomasin@arm.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panthor/panthor_sched.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c +index 77b184c3fb0ce..1349581196780 100644 +--- a/drivers/gpu/drm/panthor/panthor_sched.c ++++ b/drivers/gpu/drm/panthor/panthor_sched.c +@@ -2878,6 +2878,7 @@ void panthor_fdinfo_gather_group_samples(struct panthor_file *pfile) + if (IS_ERR_OR_NULL(gpool)) + return; + ++ xa_lock(&gpool->xa); + xa_for_each(&gpool->xa, i, group) { + mutex_lock(&group->fdinfo.lock); + pfile->stats.cycles += group->fdinfo.data.cycles; +@@ -2886,6 +2887,7 @@ void panthor_fdinfo_gather_group_samples(struct panthor_file *pfile) + group->fdinfo.data.time = 0; + mutex_unlock(&group->fdinfo.lock); + } ++ xa_unlock(&gpool->xa); + } + + static void group_sync_upd_work(struct work_struct *work) +-- +2.39.5 + diff --git a/queue-6.14/drm-panthor-replace-sleep-locks-with-spinlocks-in-fd.patch b/queue-6.14/drm-panthor-replace-sleep-locks-with-spinlocks-in-fd.patch new file mode 100644 index 0000000000..7359587848 --- /dev/null +++ b/queue-6.14/drm-panthor-replace-sleep-locks-with-spinlocks-in-fd.patch @@ -0,0 +1,115 @@ +From e681dd915e278af95a773a116f557e963b57ff30 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 19:08:45 +0000 +Subject: drm/panthor: Replace sleep locks with spinlocks in fdinfo path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Adrián Larumbe + +[ Upstream commit e379856b428acafb8ed689f31d65814da6447b2e ] + +Commit 0590c94c3596 ("drm/panthor: Fix race condition when gathering fdinfo +group samples") introduced an xarray lock to deal with potential +use-after-free errors when accessing groups fdinfo figures. However, this +toggles the kernel's atomic context status, so the next nested mutex lock +will raise a warning when the kernel is compiled with mutex debug options: + +CONFIG_DEBUG_RT_MUTEXES=y +CONFIG_DEBUG_MUTEXES=y + +Replace Panthor's group fdinfo data mutex with a guarded spinlock. + +Signed-off-by: Adrián Larumbe +Fixes: 0590c94c3596 ("drm/panthor: Fix race condition when gathering fdinfo group samples") +Reviewed-by: Liviu Dudau +Reviewed-by: Boris Brezillon +Reviewed-by: Steven Price +Signed-off-by: Steven Price +Link: https://patchwork.freedesktop.org/patch/msgid/20250303190923.1639985-1-adrian.larumbe@collabora.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panthor/panthor_sched.c | 26 ++++++++++++------------- + 1 file changed, 12 insertions(+), 14 deletions(-) + +diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c +index 2f92ef2b5ab99..b8dbeb1586f64 100644 +--- a/drivers/gpu/drm/panthor/panthor_sched.c ++++ b/drivers/gpu/drm/panthor/panthor_sched.c +@@ -9,6 +9,7 @@ + #include + + #include ++#include + #include + #include + #include +@@ -634,10 +635,10 @@ struct panthor_group { + struct panthor_gpu_usage data; + + /** +- * @lock: Mutex to govern concurrent access from drm file's fdinfo callback +- * and job post-completion processing function ++ * @fdinfo.lock: Spinlock to govern concurrent access from drm file's fdinfo ++ * callback and job post-completion processing function + */ +- struct mutex lock; ++ spinlock_t lock; + + /** @fdinfo.kbo_sizes: Aggregate size of private kernel BO's held by the group. */ + size_t kbo_sizes; +@@ -913,8 +914,6 @@ static void group_release_work(struct work_struct *work) + release_work); + u32 i; + +- mutex_destroy(&group->fdinfo.lock); +- + for (i = 0; i < group->queue_count; i++) + group_free_queue(group, group->queues[i]); + +@@ -2864,12 +2863,12 @@ static void update_fdinfo_stats(struct panthor_job *job) + struct panthor_job_profiling_data *slots = queue->profiling.slots->kmap; + struct panthor_job_profiling_data *data = &slots[job->profiling.slot]; + +- mutex_lock(&group->fdinfo.lock); +- if (job->profiling.mask & PANTHOR_DEVICE_PROFILING_CYCLES) +- fdinfo->cycles += data->cycles.after - data->cycles.before; +- if (job->profiling.mask & PANTHOR_DEVICE_PROFILING_TIMESTAMP) +- fdinfo->time += data->time.after - data->time.before; +- mutex_unlock(&group->fdinfo.lock); ++ scoped_guard(spinlock, &group->fdinfo.lock) { ++ if (job->profiling.mask & PANTHOR_DEVICE_PROFILING_CYCLES) ++ fdinfo->cycles += data->cycles.after - data->cycles.before; ++ if (job->profiling.mask & PANTHOR_DEVICE_PROFILING_TIMESTAMP) ++ fdinfo->time += data->time.after - data->time.before; ++ } + } + + void panthor_fdinfo_gather_group_samples(struct panthor_file *pfile) +@@ -2883,12 +2882,11 @@ void panthor_fdinfo_gather_group_samples(struct panthor_file *pfile) + + xa_lock(&gpool->xa); + xa_for_each(&gpool->xa, i, group) { +- mutex_lock(&group->fdinfo.lock); ++ guard(spinlock)(&group->fdinfo.lock); + pfile->stats.cycles += group->fdinfo.data.cycles; + pfile->stats.time += group->fdinfo.data.time; + group->fdinfo.data.cycles = 0; + group->fdinfo.data.time = 0; +- mutex_unlock(&group->fdinfo.lock); + } + xa_unlock(&gpool->xa); + } +@@ -3534,7 +3532,7 @@ int panthor_group_create(struct panthor_file *pfile, + mutex_unlock(&sched->reset.lock); + + add_group_kbo_sizes(group->ptdev, group); +- mutex_init(&group->fdinfo.lock); ++ spin_lock_init(&group->fdinfo.lock); + + return gid; + +-- +2.39.5 + diff --git a/queue-6.14/drm-panthor-update-cs_status_-defines-to-correct-val.patch b/queue-6.14/drm-panthor-update-cs_status_-defines-to-correct-val.patch new file mode 100644 index 0000000000..c842dc08eb --- /dev/null +++ b/queue-6.14/drm-panthor-update-cs_status_-defines-to-correct-val.patch @@ -0,0 +1,50 @@ +From ae691db6418db92c0f36dfbb23d0ba4ba766c511 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 18:04:32 +0000 +Subject: drm/panthor: Update CS_STATUS_ defines to correct values +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ashley Smith + +[ Upstream commit c82734fbdc50dc9e568e8686622eaa4498acb81e ] + +Values for SC_STATUS_BLOCKED_REASON_ are documented in the G610 "Odin" +GPU specification (CS_STATUS_BLOCKED_REASON register). + +This change updates the defines to the correct values. + +Fixes: 2718d91816ee ("drm/panthor: Add the FW logical block") +Signed-off-by: Ashley Smith +Reviewed-by: Liviu Dudau +Reviewed-by: Adrián Larumbe +Reviewed-by: Boris Brezillon +Reviewed-by: Steven Price +Signed-off-by: Steven Price +Link: https://patchwork.freedesktop.org/patch/msgid/20250303180444.3768993-1-ashley.smith@collabora.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panthor/panthor_fw.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/panthor/panthor_fw.h b/drivers/gpu/drm/panthor/panthor_fw.h +index 22448abde9923..6598d96c6d2aa 100644 +--- a/drivers/gpu/drm/panthor/panthor_fw.h ++++ b/drivers/gpu/drm/panthor/panthor_fw.h +@@ -102,9 +102,9 @@ struct panthor_fw_cs_output_iface { + #define CS_STATUS_BLOCKED_REASON_SB_WAIT 1 + #define CS_STATUS_BLOCKED_REASON_PROGRESS_WAIT 2 + #define CS_STATUS_BLOCKED_REASON_SYNC_WAIT 3 +-#define CS_STATUS_BLOCKED_REASON_DEFERRED 5 +-#define CS_STATUS_BLOCKED_REASON_RES 6 +-#define CS_STATUS_BLOCKED_REASON_FLUSH 7 ++#define CS_STATUS_BLOCKED_REASON_DEFERRED 4 ++#define CS_STATUS_BLOCKED_REASON_RESOURCE 5 ++#define CS_STATUS_BLOCKED_REASON_FLUSH 6 + #define CS_STATUS_BLOCKED_REASON_MASK GENMASK(3, 0) + u32 status_blocked_reason; + u32 status_wait_sync_value_hi; +-- +2.39.5 + diff --git a/queue-6.14/drm-ssd130x-ensure-ssd132x-pitch-is-correct.patch b/queue-6.14/drm-ssd130x-ensure-ssd132x-pitch-is-correct.patch new file mode 100644 index 0000000000..2b6f763ae0 --- /dev/null +++ b/queue-6.14/drm-ssd130x-ensure-ssd132x-pitch-is-correct.patch @@ -0,0 +1,48 @@ +From 8bd1dd29bee064b59d10aca1b829e487d99bf428 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jan 2025 11:01:38 +0000 +Subject: drm/ssd130x: ensure ssd132x pitch is correct + +From: John Keeping + +[ Upstream commit 229adcffdb54b13332d2afd2dc5d203418d50908 ] + +The bounding rectangle is adjusted to ensure it aligns to +SSD132X_SEGMENT_WIDTH, which may adjust the pitch. Calculate the pitch +after aligning the left and right edge. + +Fixes: fdd591e00a9c ("drm/ssd130x: Add support for the SSD132x OLED controller family") +Signed-off-by: John Keeping +Reviewed-by: Javier Martinez Canillas +Link: https://patchwork.freedesktop.org/patch/msgid/20250115110139.1672488-3-jkeeping@inmusicbrands.com +Signed-off-by: Javier Martinez Canillas +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/solomon/ssd130x.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c +index 4bb663f984ce3..dd2006d51c7a2 100644 +--- a/drivers/gpu/drm/solomon/ssd130x.c ++++ b/drivers/gpu/drm/solomon/ssd130x.c +@@ -1037,7 +1037,7 @@ static int ssd132x_fb_blit_rect(struct drm_framebuffer *fb, + struct drm_format_conv_state *fmtcnv_state) + { + struct ssd130x_device *ssd130x = drm_to_ssd130x(fb->dev); +- unsigned int dst_pitch = drm_rect_width(rect); ++ unsigned int dst_pitch; + struct iosys_map dst; + int ret = 0; + +@@ -1046,6 +1046,8 @@ static int ssd132x_fb_blit_rect(struct drm_framebuffer *fb, + rect->x2 = min_t(unsigned int, round_up(rect->x2, SSD132X_SEGMENT_WIDTH), + ssd130x->width); + ++ dst_pitch = drm_rect_width(rect); ++ + ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE); + if (ret) + return ret; +-- +2.39.5 + diff --git a/queue-6.14/drm-ssd130x-fix-ssd132x-encoding.patch b/queue-6.14/drm-ssd130x-fix-ssd132x-encoding.patch new file mode 100644 index 0000000000..f7d0b96766 --- /dev/null +++ b/queue-6.14/drm-ssd130x-fix-ssd132x-encoding.patch @@ -0,0 +1,40 @@ +From 9077bd66d997a00996d4b7c904dbd6c49c525d1d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jan 2025 11:01:37 +0000 +Subject: drm/ssd130x: fix ssd132x encoding + +From: John Keeping + +[ Upstream commit 1e14484677c8e87548f5f0d4eb8800e408004404 ] + +The ssd132x buffer is encoded one pixel per nibble, with two pixels in +each byte. When encoding an 8-bit greyscale input, take the top 4-bits +as the value and ensure the two pixels are distinct and do not overwrite +each other. + +Fixes: fdd591e00a9c ("drm/ssd130x: Add support for the SSD132x OLED controller family") +Signed-off-by: John Keeping +Reviewed-by: Javier Martinez Canillas +Link: https://patchwork.freedesktop.org/patch/msgid/20250115110139.1672488-2-jkeeping@inmusicbrands.com +Signed-off-by: Javier Martinez Canillas +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/solomon/ssd130x.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c +index b777690fd6607..4bb663f984ce3 100644 +--- a/drivers/gpu/drm/solomon/ssd130x.c ++++ b/drivers/gpu/drm/solomon/ssd130x.c +@@ -880,7 +880,7 @@ static int ssd132x_update_rect(struct ssd130x_device *ssd130x, + u8 n1 = buf[i * width + j]; + u8 n2 = buf[i * width + j + 1]; + +- data_array[array_idx++] = (n2 << 4) | n1; ++ data_array[array_idx++] = (n2 & 0xf0) | (n1 >> 4); + } + } + +-- +2.39.5 + diff --git a/queue-6.14/drm-ssd130x-set-spi-.id_table-to-prevent-an-spi-core.patch b/queue-6.14/drm-ssd130x-set-spi-.id_table-to-prevent-an-spi-core.patch new file mode 100644 index 0000000000..fb7fd3a898 --- /dev/null +++ b/queue-6.14/drm-ssd130x-set-spi-.id_table-to-prevent-an-spi-core.patch @@ -0,0 +1,95 @@ +From 1828bd7806d3a902b079d9d50efc4dc15a7ae2ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 31 Dec 2024 12:44:58 +0100 +Subject: drm/ssd130x: Set SPI .id_table to prevent an SPI core warning + +From: Javier Martinez Canillas + +[ Upstream commit 5d40d4fae6f2fb789f48207a9d4772bbee970b5c ] + +The only reason for the ssd130x-spi driver to have an spi_device_id table +is that the SPI core always reports an "spi:" MODALIAS, even when the SPI +device has been registered via a Device Tree Blob. + +Without spi_device_id table information in the module's metadata, module +autoloading would not work because there won't be an alias that matches +the MODALIAS reported by the SPI core. + +This spi_device_id table is not needed for device matching though, since +the of_device_id table is always used in this case. For this reason, the +struct spi_driver .id_table member is currently not set in the SPI driver. + +Because the spi_device_id table is always required for module autoloading, +the SPI core checks during driver registration that both an of_device_id +table and a spi_device_id table are present and that they contain the same +entries for all the SPI devices. + +Not setting the .id_table member in the driver then confuses the core and +leads to the following warning when the ssd130x-spi driver is registered: + + [ 41.091198] SPI driver ssd130x-spi has no spi_device_id for sinowealth,sh1106 + [ 41.098614] SPI driver ssd130x-spi has no spi_device_id for solomon,ssd1305 + [ 41.105862] SPI driver ssd130x-spi has no spi_device_id for solomon,ssd1306 + [ 41.113062] SPI driver ssd130x-spi has no spi_device_id for solomon,ssd1307 + [ 41.120247] SPI driver ssd130x-spi has no spi_device_id for solomon,ssd1309 + [ 41.127449] SPI driver ssd130x-spi has no spi_device_id for solomon,ssd1322 + [ 41.134627] SPI driver ssd130x-spi has no spi_device_id for solomon,ssd1325 + [ 41.141784] SPI driver ssd130x-spi has no spi_device_id for solomon,ssd1327 + [ 41.149021] SPI driver ssd130x-spi has no spi_device_id for solomon,ssd1331 + +To prevent the warning, set the .id_table even though it's not necessary. + +Since the check is done even for built-in drivers, drop the condition to +only define the ID table when the driver is built as a module. Finally, +rename the variable to use the "_spi_id" convention used for ID tables. + +Fixes: 74373977d2ca ("drm/solomon: Add SSD130x OLED displays SPI support") +Reviewed-by: Dmitry Baryshkov +Link: https://patchwork.freedesktop.org/patch/msgid/20241231114516.2063201-1-javierm@redhat.com +Signed-off-by: Javier Martinez Canillas +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/solomon/ssd130x-spi.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/solomon/ssd130x-spi.c b/drivers/gpu/drm/solomon/ssd130x-spi.c +index 08334be386946..7c935870f7d2a 100644 +--- a/drivers/gpu/drm/solomon/ssd130x-spi.c ++++ b/drivers/gpu/drm/solomon/ssd130x-spi.c +@@ -151,7 +151,6 @@ static const struct of_device_id ssd130x_of_match[] = { + }; + MODULE_DEVICE_TABLE(of, ssd130x_of_match); + +-#if IS_MODULE(CONFIG_DRM_SSD130X_SPI) + /* + * The SPI core always reports a MODALIAS uevent of the form "spi:", even + * if the device was registered via OF. This means that the module will not be +@@ -160,7 +159,7 @@ MODULE_DEVICE_TABLE(of, ssd130x_of_match); + * To workaround this issue, add a SPI device ID table. Even when this should + * not be needed for this driver to match the registered SPI devices. + */ +-static const struct spi_device_id ssd130x_spi_table[] = { ++static const struct spi_device_id ssd130x_spi_id[] = { + /* ssd130x family */ + { "sh1106", SH1106_ID }, + { "ssd1305", SSD1305_ID }, +@@ -175,14 +174,14 @@ static const struct spi_device_id ssd130x_spi_table[] = { + { "ssd1331", SSD1331_ID }, + { /* sentinel */ } + }; +-MODULE_DEVICE_TABLE(spi, ssd130x_spi_table); +-#endif ++MODULE_DEVICE_TABLE(spi, ssd130x_spi_id); + + static struct spi_driver ssd130x_spi_driver = { + .driver = { + .name = DRIVER_NAME, + .of_match_table = ssd130x_of_match, + }, ++ .id_table = ssd130x_spi_id, + .probe = ssd130x_spi_probe, + .remove = ssd130x_spi_remove, + .shutdown = ssd130x_spi_shutdown, +-- +2.39.5 + diff --git a/queue-6.14/drm-vkms-fix-use-after-free-and-double-free-on-init-.patch b/queue-6.14/drm-vkms-fix-use-after-free-and-double-free-on-init-.patch new file mode 100644 index 0000000000..83ade6e797 --- /dev/null +++ b/queue-6.14/drm-vkms-fix-use-after-free-and-double-free-on-init-.patch @@ -0,0 +1,76 @@ +From 85fdf745f8fd6c2092f30d8e2f128535d353130c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 09:49:12 +0100 +Subject: drm/vkms: Fix use after free and double free on init error +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: José Expósito + +[ Upstream commit ed15511a773df86205bda66c37193569575ae828 ] + +If the driver initialization fails, the vkms_exit() function might +access an uninitialized or freed default_config pointer and it might +double free it. + +Fix both possible errors by initializing default_config only when the +driver initialization succeeded. + +Reported-by: Louis Chauvet +Closes: https://lore.kernel.org/all/Z5uDHcCmAwiTsGte@louis-chauvet-laptop/ +Fixes: 2df7af93fdad ("drm/vkms: Add vkms_config type") +Signed-off-by: José Expósito +Reviewed-by: Thomas Zimmermann +Reviewed-by: Louis Chauvet +Link: https://patchwork.freedesktop.org/patch/msgid/20250212084912.3196-1-jose.exposito89@gmail.com +Signed-off-by: Louis Chauvet +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/vkms/vkms_drv.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c +index e0409aba93496..7fefef690ab6b 100644 +--- a/drivers/gpu/drm/vkms/vkms_drv.c ++++ b/drivers/gpu/drm/vkms/vkms_drv.c +@@ -244,17 +244,19 @@ static int __init vkms_init(void) + if (!config) + return -ENOMEM; + +- default_config = config; +- + config->cursor = enable_cursor; + config->writeback = enable_writeback; + config->overlay = enable_overlay; + + ret = vkms_create(config); +- if (ret) ++ if (ret) { + kfree(config); ++ return ret; ++ } + +- return ret; ++ default_config = config; ++ ++ return 0; + } + + static void vkms_destroy(struct vkms_config *config) +@@ -278,9 +280,10 @@ static void vkms_destroy(struct vkms_config *config) + + static void __exit vkms_exit(void) + { +- if (default_config->dev) +- vkms_destroy(default_config); ++ if (!default_config) ++ return; + ++ vkms_destroy(default_config); + kfree(default_config); + } + +-- +2.39.5 + diff --git a/queue-6.14/drm-xlnx-zynqmp-fix-max-dma-segment-size.patch b/queue-6.14/drm-xlnx-zynqmp-fix-max-dma-segment-size.patch new file mode 100644 index 0000000000..881ddebb23 --- /dev/null +++ b/queue-6.14/drm-xlnx-zynqmp-fix-max-dma-segment-size.patch @@ -0,0 +1,38 @@ +From 8482eb38ab63d51e860846931c58449893894801 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jan 2025 11:03:39 +0200 +Subject: drm: xlnx: zynqmp: Fix max dma segment size + +From: Tomi Valkeinen + +[ Upstream commit 28b529a98525123acd37372a04d21e87ec2edcf7 ] + +Fix "mapping sg segment longer than device claims to support" warning by +setting the max segment size. + +Fixes: d76271d22694 ("drm: xlnx: DRM/KMS driver for Xilinx ZynqMP DisplayPort Subsystem") +Reviewed-by: Sean Anderson +Tested-by: Sean Anderson +Signed-off-by: Tomi Valkeinen +Link: https://patchwork.freedesktop.org/patch/msgid/20250115-xilinx-formats-v2-10-160327ca652a@ideasonboard.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xlnx/zynqmp_dpsub.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c +index f953ca48a9303..3a9544b97bc53 100644 +--- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c ++++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c +@@ -201,6 +201,8 @@ static int zynqmp_dpsub_probe(struct platform_device *pdev) + if (ret) + return ret; + ++ dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); ++ + /* Try the reserved memory. Proceed if there's none. */ + of_reserved_mem_device_init(&pdev->dev); + +-- +2.39.5 + diff --git a/queue-6.14/drm-xlnx-zynqmp_dpsub-add-null-check-in-zynqmp_audio.patch b/queue-6.14/drm-xlnx-zynqmp_dpsub-add-null-check-in-zynqmp_audio.patch new file mode 100644 index 0000000000..d8c6b6d5a2 --- /dev/null +++ b/queue-6.14/drm-xlnx-zynqmp_dpsub-add-null-check-in-zynqmp_audio.patch @@ -0,0 +1,49 @@ +From 9f32e3d51a824f91a3e0ebec46edd876db7e77d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 18:20:49 +0800 +Subject: drm: xlnx: zynqmp_dpsub: Add NULL check in zynqmp_audio_init + +From: Charles Han + +[ Upstream commit d0660f9c588a1246a1a543c91a1e3cad910237da ] + +devm_kasprintf() calls can return null pointers on failure. +But some return values were not checked in zynqmp_audio_init(). + +Add NULL check in zynqmp_audio_init(), avoid referencing null +pointers in the subsequent code. + +Fixes: 3ec5c1579305 ("drm: xlnx: zynqmp_dpsub: Add DP audio support") +Reviewed-by: Laurent Pinchart +Signed-off-by: Charles Han +Signed-off-by: Tomi Valkeinen +Link: https://patchwork.freedesktop.org/patch/msgid/20250211102049.6468-1-hanchunchao@inspur.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xlnx/zynqmp_dp_audio.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp_audio.c b/drivers/gpu/drm/xlnx/zynqmp_dp_audio.c +index fa5f0ace60842..f07ff4eb3a6de 100644 +--- a/drivers/gpu/drm/xlnx/zynqmp_dp_audio.c ++++ b/drivers/gpu/drm/xlnx/zynqmp_dp_audio.c +@@ -323,12 +323,16 @@ int zynqmp_audio_init(struct zynqmp_dpsub *dpsub) + + audio->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "%s-dai", dev_name(dev)); ++ if (!audio->dai_name) ++ return -ENOMEM; + + for (unsigned int i = 0; i < ZYNQMP_NUM_PCMS; ++i) { + audio->link_names[i] = devm_kasprintf(dev, GFP_KERNEL, + "%s-dp-%u", dev_name(dev), i); + audio->pcm_names[i] = devm_kasprintf(dev, GFP_KERNEL, + "%s-pcm-%u", dev_name(dev), i); ++ if (!audio->link_names[i] || !audio->pcm_names[i]) ++ return -ENOMEM; + } + + audio->base = devm_platform_ioremap_resource_byname(pdev, "aud"); +-- +2.39.5 + diff --git a/queue-6.14/drm-zynqmp_dp-fix-a-deadlock-in-zynqmp_dp_ignore_hpd.patch b/queue-6.14/drm-zynqmp_dp-fix-a-deadlock-in-zynqmp_dp_ignore_hpd.patch new file mode 100644 index 0000000000..db5a6e67cc --- /dev/null +++ b/queue-6.14/drm-zynqmp_dp-fix-a-deadlock-in-zynqmp_dp_ignore_hpd.patch @@ -0,0 +1,44 @@ +From ac72133823056b4005378dab4e9e40fc7e7383b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 11:25:27 -0500 +Subject: drm: zynqmp_dp: Fix a deadlock in zynqmp_dp_ignore_hpd_set() + +From: Bart Van Assche + +[ Upstream commit f887685ee0eb4ef716391355568181230338f6eb ] + +Instead of attempting the same mutex twice, lock and unlock it. + +This bug has been detected by the Clang thread-safety analyzer. + +Cc: Sean Anderson +Cc: Tomi Valkeinen +Fixes: 28edaacb821c ("drm: zynqmp_dp: Add debugfs interface for compliance testing") +Signed-off-by: Bart Van Assche +Reviewed-by: Sean Anderson +Signed-off-by: Sean Anderson +Reviewed-by: Laurent Pinchart +Reviewed-by: Sean Anderson +Signed-off-by: Tomi Valkeinen +Link: https://patchwork.freedesktop.org/patch/msgid/20250207162528.1651426-2-sean.anderson@linux.dev +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xlnx/zynqmp_dp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c +index 979f6d3239ba6..189a08cdc73c0 100644 +--- a/drivers/gpu/drm/xlnx/zynqmp_dp.c ++++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c +@@ -2295,7 +2295,7 @@ static int zynqmp_dp_ignore_hpd_set(void *data, u64 val) + + mutex_lock(&dp->lock); + dp->ignore_hpd = val; +- mutex_lock(&dp->lock); ++ mutex_unlock(&dp->lock); + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/dt-bindings-vendor-prefixes-add-gocontroll.patch b/queue-6.14/dt-bindings-vendor-prefixes-add-gocontroll.patch new file mode 100644 index 0000000000..983dea8efa --- /dev/null +++ b/queue-6.14/dt-bindings-vendor-prefixes-add-gocontroll.patch @@ -0,0 +1,37 @@ +From e467127c10ac2bca122cab771a03b55efd1fb1c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 15:19:13 +0100 +Subject: dt-bindings: vendor-prefixes: add GOcontroll + +From: Maud Spierings + +[ Upstream commit 5f0d2de417166698c8eba433b696037ce04730da ] + +GOcontroll produces embedded linux systems and IO modules to use in +these systems, add its prefix. + +Acked-by: Rob Herring (Arm) +Signed-off-by: Maud Spierings +Link: https://patch.msgid.link/20250226-initial_display-v2-2-23fafa130817@gocontroll.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml +index 5079ca6ce1d1e..b5979832ddce6 100644 +--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml ++++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml +@@ -593,6 +593,8 @@ patternProperties: + description: GlobalTop Technology, Inc. + "^gmt,.*": + description: Global Mixed-mode Technology, Inc. ++ "^gocontroll,.*": ++ description: GOcontroll Modular Embedded Electronics B.V. + "^goldelico,.*": + description: Golden Delicious Computers GmbH & Co. KG + "^goodix,.*": +-- +2.39.5 + diff --git a/queue-6.14/dummycon-fix-default-rows-cols.patch b/queue-6.14/dummycon-fix-default-rows-cols.patch new file mode 100644 index 0000000000..36d58ca94c --- /dev/null +++ b/queue-6.14/dummycon-fix-default-rows-cols.patch @@ -0,0 +1,60 @@ +From a937db248eae72989f61ee2e5077cc22dac3045c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 17:44:22 +0100 +Subject: dummycon: fix default rows/cols + +From: Arnd Bergmann + +[ Upstream commit beefaba1978c04ea2950d34236f58fe6cf6a7f58 ] + +dummycon fails to build on ARM/footbridge when the VGA console is +disabled, since I got the dependencies slightly wrong in a previous +patch: + +drivers/video/console/dummycon.c: In function 'dummycon_init': +drivers/video/console/dummycon.c:27:25: error: 'CONFIG_DUMMY_CONSOLE_COLUMNS' undeclared (first use in this function); did you mean 'CONFIG_DUMMY_CONSOLE'? + 27 | #define DUMMY_COLUMNS CONFIG_DUMMY_CONSOLE_COLUMNS +drivers/video/console/dummycon.c:28:25: error: 'CONFIG_DUMMY_CONSOLE_ROWS' undeclared (first use in this function); did you mean 'CONFIG_DUMMY_CONSOLE'? + 28 | #define DUMMY_ROWS CONFIG_DUMMY_CONSOLE_ROWS + +This only showed up after many thousand randconfig builds on Arm, and +doesn't matter in practice, but should still be fixed. Address it by +using the default row/columns on footbridge after all in that corner +case. + +Fixes: 4293b0925149 ("dummycon: limit Arm console size hack to footbridge") +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202409151512.LML1slol-lkp@intel.com/ +Signed-off-by: Arnd Bergmann +Reviewed-by: Thomas Zimmermann +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + drivers/video/console/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig +index bc31db6ef7d26..c4a8f74df2493 100644 +--- a/drivers/video/console/Kconfig ++++ b/drivers/video/console/Kconfig +@@ -52,7 +52,7 @@ config DUMMY_CONSOLE + + config DUMMY_CONSOLE_COLUMNS + int "Initial number of console screen columns" +- depends on DUMMY_CONSOLE && !ARCH_FOOTBRIDGE ++ depends on DUMMY_CONSOLE && !(ARCH_FOOTBRIDGE && VGA_CONSOLE) + default 160 if PARISC + default 80 + help +@@ -62,7 +62,7 @@ config DUMMY_CONSOLE_COLUMNS + + config DUMMY_CONSOLE_ROWS + int "Initial number of console screen rows" +- depends on DUMMY_CONSOLE && !ARCH_FOOTBRIDGE ++ depends on DUMMY_CONSOLE && !(ARCH_FOOTBRIDGE && VGA_CONSOLE) + default 64 if PARISC + default 30 if ARM + default 25 +-- +2.39.5 + diff --git a/queue-6.14/e1000e-change-k1-configuration-on-mtp-and-later-plat.patch b/queue-6.14/e1000e-change-k1-configuration-on-mtp-and-later-plat.patch new file mode 100644 index 0000000000..f64d39f371 --- /dev/null +++ b/queue-6.14/e1000e-change-k1-configuration-on-mtp-and-later-plat.patch @@ -0,0 +1,178 @@ +From aa602b1b17efbc6f0eee9b2cb13f6f930bd6b52b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 16:05:56 +0200 +Subject: e1000e: change k1 configuration on MTP and later platforms + +From: Vitaly Lifshits + +[ Upstream commit efaaf344bc2917cbfa5997633bc18a05d3aed27f ] + +Starting from Meteor Lake, the Kumeran interface between the integrated +MAC and the I219 PHY works at a different frequency. This causes sporadic +MDI errors when accessing the PHY, and in rare circumstances could lead +to packet corruption. + +To overcome this, introduce minor changes to the Kumeran idle +state (K1) parameters during device initialization. Hardware reset +reverts this configuration, therefore it needs to be applied in a few +places. + +Fixes: cc23f4f0b6b9 ("e1000e: Add support for Meteor Lake") +Signed-off-by: Vitaly Lifshits +Tested-by: Avigail Dahan +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/e1000e/defines.h | 3 + + drivers/net/ethernet/intel/e1000e/ich8lan.c | 80 +++++++++++++++++++-- + drivers/net/ethernet/intel/e1000e/ich8lan.h | 4 ++ + 3 files changed, 82 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h +index 5e2cfa73f8891..8294a7c4f122c 100644 +--- a/drivers/net/ethernet/intel/e1000e/defines.h ++++ b/drivers/net/ethernet/intel/e1000e/defines.h +@@ -803,4 +803,7 @@ + /* SerDes Control */ + #define E1000_GEN_POLL_TIMEOUT 640 + ++#define E1000_FEXTNVM12_PHYPD_CTRL_MASK 0x00C00000 ++#define E1000_FEXTNVM12_PHYPD_CTRL_P1 0x00800000 ++ + #endif /* _E1000_DEFINES_H_ */ +diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c +index 2f9655cf5dd9e..364378133526a 100644 +--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c ++++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c +@@ -285,6 +285,45 @@ static void e1000_toggle_lanphypc_pch_lpt(struct e1000_hw *hw) + } + } + ++/** ++ * e1000_reconfigure_k1_exit_timeout - reconfigure K1 exit timeout to ++ * align to MTP and later platform requirements. ++ * @hw: pointer to the HW structure ++ * ++ * Context: PHY semaphore must be held by caller. ++ * Return: 0 on success, negative on failure ++ */ ++static s32 e1000_reconfigure_k1_exit_timeout(struct e1000_hw *hw) ++{ ++ u16 phy_timeout; ++ u32 fextnvm12; ++ s32 ret_val; ++ ++ if (hw->mac.type < e1000_pch_mtp) ++ return 0; ++ ++ /* Change Kumeran K1 power down state from P0s to P1 */ ++ fextnvm12 = er32(FEXTNVM12); ++ fextnvm12 &= ~E1000_FEXTNVM12_PHYPD_CTRL_MASK; ++ fextnvm12 |= E1000_FEXTNVM12_PHYPD_CTRL_P1; ++ ew32(FEXTNVM12, fextnvm12); ++ ++ /* Wait for the interface the settle */ ++ usleep_range(1000, 1100); ++ ++ /* Change K1 exit timeout */ ++ ret_val = e1e_rphy_locked(hw, I217_PHY_TIMEOUTS_REG, ++ &phy_timeout); ++ if (ret_val) ++ return ret_val; ++ ++ phy_timeout &= ~I217_PHY_TIMEOUTS_K1_EXIT_TO_MASK; ++ phy_timeout |= 0xF00; ++ ++ return e1e_wphy_locked(hw, I217_PHY_TIMEOUTS_REG, ++ phy_timeout); ++} ++ + /** + * e1000_init_phy_workarounds_pchlan - PHY initialization workarounds + * @hw: pointer to the HW structure +@@ -327,15 +366,22 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw) + * LANPHYPC Value bit to force the interconnect to PCIe mode. + */ + switch (hw->mac.type) { ++ case e1000_pch_mtp: ++ case e1000_pch_lnp: ++ case e1000_pch_ptp: ++ case e1000_pch_nvp: ++ /* At this point the PHY might be inaccessible so don't ++ * propagate the failure ++ */ ++ if (e1000_reconfigure_k1_exit_timeout(hw)) ++ e_dbg("Failed to reconfigure K1 exit timeout\n"); ++ ++ fallthrough; + case e1000_pch_lpt: + case e1000_pch_spt: + case e1000_pch_cnp: + case e1000_pch_tgp: + case e1000_pch_adp: +- case e1000_pch_mtp: +- case e1000_pch_lnp: +- case e1000_pch_ptp: +- case e1000_pch_nvp: + if (e1000_phy_is_accessible_pchlan(hw)) + break; + +@@ -419,8 +465,20 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw) + * the PHY is in. + */ + ret_val = hw->phy.ops.check_reset_block(hw); +- if (ret_val) ++ if (ret_val) { + e_err("ME blocked access to PHY after reset\n"); ++ goto out; ++ } ++ ++ if (hw->mac.type >= e1000_pch_mtp) { ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) { ++ e_err("Failed to reconfigure K1 exit timeout\n"); ++ goto out; ++ } ++ ret_val = e1000_reconfigure_k1_exit_timeout(hw); ++ hw->phy.ops.release(hw); ++ } + } + + out: +@@ -4888,6 +4946,18 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) + u16 i; + + e1000_initialize_hw_bits_ich8lan(hw); ++ if (hw->mac.type >= e1000_pch_mtp) { ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) ++ return ret_val; ++ ++ ret_val = e1000_reconfigure_k1_exit_timeout(hw); ++ hw->phy.ops.release(hw); ++ if (ret_val) { ++ e_dbg("Error failed to reconfigure K1 exit timeout\n"); ++ return ret_val; ++ } ++ } + + /* Initialize identification LED */ + ret_val = mac->ops.id_led_init(hw); +diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.h b/drivers/net/ethernet/intel/e1000e/ich8lan.h +index 2504b11c3169f..5feb589a9b5ff 100644 +--- a/drivers/net/ethernet/intel/e1000e/ich8lan.h ++++ b/drivers/net/ethernet/intel/e1000e/ich8lan.h +@@ -219,6 +219,10 @@ + #define I217_PLL_CLOCK_GATE_REG PHY_REG(772, 28) + #define I217_PLL_CLOCK_GATE_MASK 0x07FF + ++/* PHY Timeouts */ ++#define I217_PHY_TIMEOUTS_REG PHY_REG(770, 21) ++#define I217_PHY_TIMEOUTS_K1_EXIT_TO_MASK 0x0FC0 ++ + #define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in ms */ + + /* Inband Control */ +-- +2.39.5 + diff --git a/queue-6.14/edac-ie31200-fix-the-dimm-size-mask-for-several-socs.patch b/queue-6.14/edac-ie31200-fix-the-dimm-size-mask-for-several-socs.patch new file mode 100644 index 0000000000..1c0b0cb9c9 --- /dev/null +++ b/queue-6.14/edac-ie31200-fix-the-dimm-size-mask-for-several-socs.patch @@ -0,0 +1,46 @@ +From 05670eb4a34bb36f06bbf9096f97ba18954ae4c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 09:14:02 +0800 +Subject: EDAC/ie31200: Fix the DIMM size mask for several SoCs + +From: Qiuxu Zhuo + +[ Upstream commit 3427befbbca6b19fe0e37f91d66ce5221de70bf1 ] + +The DIMM size mask for {Sky, Kaby, Coffee} Lake is not bits{7:0}, +but bits{5:0}. Fix it. + +Fixes: 953dee9bbd24 ("EDAC, ie31200_edac: Add Skylake support") +Signed-off-by: Qiuxu Zhuo +Signed-off-by: Tony Luck +Tested-by: Gary Wang +Link: https://lore.kernel.org/r/20250310011411.31685-3-qiuxu.zhuo@intel.com +Signed-off-by: Sasha Levin +--- + drivers/edac/ie31200_edac.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c +index c3d34d1fc9ad7..da4008c22f0d3 100644 +--- a/drivers/edac/ie31200_edac.c ++++ b/drivers/edac/ie31200_edac.c +@@ -165,6 +165,7 @@ + #define IE31200_MAD_DIMM_0_OFFSET 0x5004 + #define IE31200_MAD_DIMM_0_OFFSET_SKL 0x500C + #define IE31200_MAD_DIMM_SIZE GENMASK_ULL(7, 0) ++#define IE31200_MAD_DIMM_SIZE_SKL GENMASK_ULL(5, 0) + #define IE31200_MAD_DIMM_A_RANK BIT(17) + #define IE31200_MAD_DIMM_A_RANK_SHIFT 17 + #define IE31200_MAD_DIMM_A_RANK_SKL BIT(10) +@@ -378,7 +379,7 @@ static void __iomem *ie31200_map_mchbar(struct pci_dev *pdev) + static void __skl_populate_dimm_info(struct dimm_data *dd, u32 addr_decode, + int chan) + { +- dd->size = (addr_decode >> (chan << 4)) & IE31200_MAD_DIMM_SIZE; ++ dd->size = (addr_decode >> (chan << 4)) & IE31200_MAD_DIMM_SIZE_SKL; + dd->dual_rank = (addr_decode & (IE31200_MAD_DIMM_A_RANK_SKL << (chan << 4))) ? 1 : 0; + dd->x16_width = ((addr_decode & (IE31200_MAD_DIMM_A_WIDTH_SKL << (chan << 4))) >> + (IE31200_MAD_DIMM_A_WIDTH_SKL_SHIFT + (chan << 4))); +-- +2.39.5 + diff --git a/queue-6.14/edac-ie31200-fix-the-error-path-order-of-ie31200_ini.patch b/queue-6.14/edac-ie31200-fix-the-error-path-order-of-ie31200_ini.patch new file mode 100644 index 0000000000..137ad65f8c --- /dev/null +++ b/queue-6.14/edac-ie31200-fix-the-error-path-order-of-ie31200_ini.patch @@ -0,0 +1,68 @@ +From 57835521fcf564c1bf227f439a7437fcd3e38fb3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 09:14:03 +0800 +Subject: EDAC/ie31200: Fix the error path order of ie31200_init() + +From: Qiuxu Zhuo + +[ Upstream commit 231e341036d9988447e3b3345cf741a98139199e ] + +The error path order of ie31200_init() is incorrect, fix it. + +Fixes: 709ed1bcef12 ("EDAC/ie31200: Fallback if host bridge device is already initialized") +Signed-off-by: Qiuxu Zhuo +Signed-off-by: Tony Luck +Tested-by: Gary Wang +Link: https://lore.kernel.org/r/20250310011411.31685-4-qiuxu.zhuo@intel.com +Signed-off-by: Sasha Levin +--- + drivers/edac/ie31200_edac.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c +index da4008c22f0d3..9b02a6b43ab58 100644 +--- a/drivers/edac/ie31200_edac.c ++++ b/drivers/edac/ie31200_edac.c +@@ -621,7 +621,7 @@ static int __init ie31200_init(void) + + pci_rc = pci_register_driver(&ie31200_driver); + if (pci_rc < 0) +- goto fail0; ++ return pci_rc; + + if (!mci_pdev) { + ie31200_registered = 0; +@@ -632,11 +632,13 @@ static int __init ie31200_init(void) + if (mci_pdev) + break; + } ++ + if (!mci_pdev) { + edac_dbg(0, "ie31200 pci_get_device fail\n"); + pci_rc = -ENODEV; +- goto fail1; ++ goto fail0; + } ++ + pci_rc = ie31200_init_one(mci_pdev, &ie31200_pci_tbl[i]); + if (pci_rc < 0) { + edac_dbg(0, "ie31200 init fail\n"); +@@ -644,12 +646,12 @@ static int __init ie31200_init(void) + goto fail1; + } + } +- return 0; + ++ return 0; + fail1: +- pci_unregister_driver(&ie31200_driver); +-fail0: + pci_dev_put(mci_pdev); ++fail0: ++ pci_unregister_driver(&ie31200_driver); + + return pci_rc; + } +-- +2.39.5 + diff --git a/queue-6.14/edac-ie31200-fix-the-size-of-edac_mc_layer_chip_sele.patch b/queue-6.14/edac-ie31200-fix-the-size-of-edac_mc_layer_chip_sele.patch new file mode 100644 index 0000000000..456a12d6f5 --- /dev/null +++ b/queue-6.14/edac-ie31200-fix-the-size-of-edac_mc_layer_chip_sele.patch @@ -0,0 +1,48 @@ +From 06c0d94f87bb78338e7764d90cb7c4822bf101d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 09:14:01 +0800 +Subject: EDAC/ie31200: Fix the size of EDAC_MC_LAYER_CHIP_SELECT layer + +From: Qiuxu Zhuo + +[ Upstream commit d59d844e319d97682c8de29b88d2d60922a683b3 ] + +The EDAC_MC_LAYER_CHIP_SELECT layer pertains to the rank, not the DIMM. +Fix its size to reflect the number of ranks instead of the number of DIMMs. +Also delete the unused macros IE31200_{DIMMS,RANKS}. + +Fixes: 7ee40b897d18 ("ie31200_edac: Introduce the driver") +Signed-off-by: Qiuxu Zhuo +Signed-off-by: Tony Luck +Tested-by: Gary Wang +Link: https://lore.kernel.org/r/20250310011411.31685-2-qiuxu.zhuo@intel.com +Signed-off-by: Sasha Levin +--- + drivers/edac/ie31200_edac.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c +index 4fc16922dc1af..c3d34d1fc9ad7 100644 +--- a/drivers/edac/ie31200_edac.c ++++ b/drivers/edac/ie31200_edac.c +@@ -94,8 +94,6 @@ + (((did) & PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_MASK) == \ + PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_MASK)) + +-#define IE31200_DIMMS 4 +-#define IE31200_RANKS 8 + #define IE31200_RANKS_PER_CHANNEL 4 + #define IE31200_DIMMS_PER_CHANNEL 2 + #define IE31200_CHANNELS 2 +@@ -429,7 +427,7 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) + + nr_channels = how_many_channels(pdev); + layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; +- layers[0].size = IE31200_DIMMS; ++ layers[0].size = IE31200_RANKS_PER_CHANNEL; + layers[0].is_virt_csrow = true; + layers[1].type = EDAC_MC_LAYER_CHANNEL; + layers[1].size = nr_channels; +-- +2.39.5 + diff --git a/queue-6.14/edac-igen6-fix-the-flood-of-invalid-error-reports.patch b/queue-6.14/edac-igen6-fix-the-flood-of-invalid-error-reports.patch new file mode 100644 index 0000000000..f694215a42 --- /dev/null +++ b/queue-6.14/edac-igen6-fix-the-flood-of-invalid-error-reports.patch @@ -0,0 +1,66 @@ +From 9bbbb61d1175a7e2b9d45a3daa12a789c970b470 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 16:33:54 +0800 +Subject: EDAC/igen6: Fix the flood of invalid error reports + +From: Qiuxu Zhuo + +[ Upstream commit 267e5b1d267539d9a927dc04aab6f15aca57da92 ] + +The ECC_ERROR_LOG register of certain SoCs may contain the invalid value +~0, which results in a flood of invalid error reports in polling mode. + +Fix the flood of invalid error reports by skipping the invalid ECC error +log value ~0. + +Fixes: e14232afa944 ("EDAC/igen6: Add polling support") +Reported-by: Ramses +Closes: https://lore.kernel.org/all/OISL8Rv--F-9@well-founded.dev/ +Tested-by: Ramses +Reported-by: John +Closes: https://lore.kernel.org/all/p5YcxOE6M3Ncxpn2-Ia_wCt61EM4LwIiN3LroQvT_-G2jMrFDSOW5k2A9D8UUzD2toGpQBN1eI0sL5dSKnkO8iteZegLoQEj-DwQaMhGx4A=@proton.me/ +Tested-by: John +Signed-off-by: Qiuxu Zhuo +Signed-off-by: Tony Luck +Link: https://lore.kernel.org/r/20250212083354.31919-1-qiuxu.zhuo@intel.com +Signed-off-by: Sasha Levin +--- + drivers/edac/igen6_edac.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +diff --git a/drivers/edac/igen6_edac.c b/drivers/edac/igen6_edac.c +index fdf3a84fe6988..595908af9e5c9 100644 +--- a/drivers/edac/igen6_edac.c ++++ b/drivers/edac/igen6_edac.c +@@ -785,13 +785,22 @@ static u64 ecclog_read_and_clear(struct igen6_imc *imc) + { + u64 ecclog = readq(imc->window + ECC_ERROR_LOG_OFFSET); + +- if (ecclog & (ECC_ERROR_LOG_CE | ECC_ERROR_LOG_UE)) { +- /* Clear CE/UE bits by writing 1s */ +- writeq(ecclog, imc->window + ECC_ERROR_LOG_OFFSET); +- return ecclog; +- } ++ /* ++ * Quirk: The ECC_ERROR_LOG register of certain SoCs may contain ++ * the invalid value ~0. This will result in a flood of invalid ++ * error reports in polling mode. Skip it. ++ */ ++ if (ecclog == ~0) ++ return 0; + +- return 0; ++ /* Neither a CE nor a UE. Skip it.*/ ++ if (!(ecclog & (ECC_ERROR_LOG_CE | ECC_ERROR_LOG_UE))) ++ return 0; ++ ++ /* Clear CE/UE bits by writing 1s */ ++ writeq(ecclog, imc->window + ECC_ERROR_LOG_OFFSET); ++ ++ return ecclog; + } + + static void errsts_clear(struct igen6_imc *imc) +-- +2.39.5 + diff --git a/queue-6.14/edac-skx_common-i10nm-fix-some-missing-error-reports.patch b/queue-6.14/edac-skx_common-i10nm-fix-some-missing-error-reports.patch new file mode 100644 index 0000000000..3de6c661c7 --- /dev/null +++ b/queue-6.14/edac-skx_common-i10nm-fix-some-missing-error-reports.patch @@ -0,0 +1,144 @@ +From 62f3738a2c97d884889f72081308e267b74fcc23 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 08:27:28 +0800 +Subject: EDAC/{skx_common,i10nm}: Fix some missing error reports on Emerald + Rapids + +From: Qiuxu Zhuo + +[ Upstream commit d9207cf7760f5f5599e9ff7eb0fedf56821a1d59 ] + +When doing error injection to some memory DIMMs on certain Intel Emerald +Rapids servers, the i10nm_edac missed error reports for some memory DIMMs. + +Certain BIOS configurations may hide some memory controllers, and the +i10nm_edac doesn't enumerate these hidden memory controllers. However, the +ADXL decodes memory errors using memory controller physical indices even +if there are hidden memory controllers. Therefore, the memory controller +physical indices reported by the ADXL may mismatch the logical indices +enumerated by the i10nm_edac, resulting in missed error reports for some +memory DIMMs. + +Fix this issue by creating a mapping table from memory controller physical +indices (used by the ADXL) to logical indices (used by the i10nm_edac) and +using it to convert the physical indices to the logical indices during the +error handling process. + +Fixes: c545f5e41225 ("EDAC/i10nm: Skip the absent memory controllers") +Reported-by: Kevin Chang +Tested-by: Kevin Chang +Reported-by: Thomas Chen +Tested-by: Thomas Chen +Signed-off-by: Qiuxu Zhuo +Signed-off-by: Tony Luck +Link: https://lore.kernel.org/r/20250214002728.6287-1-qiuxu.zhuo@intel.com +Signed-off-by: Sasha Levin +--- + drivers/edac/i10nm_base.c | 2 ++ + drivers/edac/skx_common.c | 33 +++++++++++++++++++++++++++++++++ + drivers/edac/skx_common.h | 11 +++++++++++ + 3 files changed, 46 insertions(+) + +diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c +index f45d849d3f150..355a977019e94 100644 +--- a/drivers/edac/i10nm_base.c ++++ b/drivers/edac/i10nm_base.c +@@ -751,6 +751,8 @@ static int i10nm_get_ddr_munits(void) + continue; + } else { + d->imc[lmc].mdev = mdev; ++ if (res_cfg->type == SPR) ++ skx_set_mc_mapping(d, i, lmc); + lmc++; + } + } +diff --git a/drivers/edac/skx_common.c b/drivers/edac/skx_common.c +index f7bd930e058fe..fa5b442b18449 100644 +--- a/drivers/edac/skx_common.c ++++ b/drivers/edac/skx_common.c +@@ -121,6 +121,35 @@ void skx_adxl_put(void) + } + EXPORT_SYMBOL_GPL(skx_adxl_put); + ++static void skx_init_mc_mapping(struct skx_dev *d) ++{ ++ /* ++ * By default, the BIOS presents all memory controllers within each ++ * socket to the EDAC driver. The physical indices are the same as ++ * the logical indices of the memory controllers enumerated by the ++ * EDAC driver. ++ */ ++ for (int i = 0; i < NUM_IMC; i++) ++ d->mc_mapping[i] = i; ++} ++ ++void skx_set_mc_mapping(struct skx_dev *d, u8 pmc, u8 lmc) ++{ ++ edac_dbg(0, "Set the mapping of mc phy idx to logical idx: %02d -> %02d\n", ++ pmc, lmc); ++ ++ d->mc_mapping[pmc] = lmc; ++} ++EXPORT_SYMBOL_GPL(skx_set_mc_mapping); ++ ++static u8 skx_get_mc_mapping(struct skx_dev *d, u8 pmc) ++{ ++ edac_dbg(0, "Get the mapping of mc phy idx to logical idx: %02d -> %02d\n", ++ pmc, d->mc_mapping[pmc]); ++ ++ return d->mc_mapping[pmc]; ++} ++ + static bool skx_adxl_decode(struct decoded_addr *res, enum error_source err_src) + { + struct skx_dev *d; +@@ -188,6 +217,8 @@ static bool skx_adxl_decode(struct decoded_addr *res, enum error_source err_src) + return false; + } + ++ res->imc = skx_get_mc_mapping(d, res->imc); ++ + for (i = 0; i < adxl_component_count; i++) { + if (adxl_values[i] == ~0x0ull) + continue; +@@ -326,6 +357,8 @@ int skx_get_all_bus_mappings(struct res_config *cfg, struct list_head **list) + d->bus[0], d->bus[1], d->bus[2], d->bus[3]); + list_add_tail(&d->list, &dev_edac_list); + prev = pdev; ++ ++ skx_init_mc_mapping(d); + } + + if (list) +diff --git a/drivers/edac/skx_common.h b/drivers/edac/skx_common.h +index b0845bdd45164..ca5408803f878 100644 +--- a/drivers/edac/skx_common.h ++++ b/drivers/edac/skx_common.h +@@ -93,6 +93,16 @@ struct skx_dev { + struct pci_dev *uracu; /* for i10nm CPU */ + struct pci_dev *pcu_cr3; /* for HBM memory detection */ + u32 mcroute; ++ /* ++ * Some server BIOS may hide certain memory controllers, and the ++ * EDAC driver skips those hidden memory controllers. However, the ++ * ADXL still decodes memory error address using physical memory ++ * controller indices. The mapping table is used to convert the ++ * physical indices (reported by ADXL) to the logical indices ++ * (used the EDAC driver) of present memory controllers during the ++ * error handling process. ++ */ ++ u8 mc_mapping[NUM_IMC]; + struct skx_imc { + struct mem_ctl_info *mci; + struct pci_dev *mdev; /* for i10nm CPU */ +@@ -242,6 +252,7 @@ void skx_adxl_put(void); + void skx_set_decode(skx_decode_f decode, skx_show_retry_log_f show_retry_log); + void skx_set_mem_cfg(bool mem_cfg_2lm); + void skx_set_res_cfg(struct res_config *cfg); ++void skx_set_mc_mapping(struct skx_dev *d, u8 pmc, u8 lmc); + + int skx_get_src_id(struct skx_dev *d, int off, u8 *id); + +-- +2.39.5 + diff --git a/queue-6.14/erofs-allow-16-byte-volume-name-again.patch b/queue-6.14/erofs-allow-16-byte-volume-name-again.patch new file mode 100644 index 0000000000..4871a2b34a --- /dev/null +++ b/queue-6.14/erofs-allow-16-byte-volume-name-again.patch @@ -0,0 +1,66 @@ +From 1854d6cef80d34dc423d3f23ddd30aaf8b6dc61a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 11:39:34 +0800 +Subject: erofs: allow 16-byte volume name again + +From: Gao Xiang + +[ Upstream commit 579450277780159b8ba94a08b2f1d1da2002aec5 ] + +Actually, volume name doesn't need to include the NIL terminator if +the string length matches the on-disk field size as mentioned in [1]. + +I tend to relax it together with the upcoming 48-bit block addressing +(or stable kernels which backport this fix) so that we could have a +chance to record a 16-byte volume name like ext4. + +Since in-memory `volume_name` has no user, just get rid of the unneeded +check for now. `sbi->uuid` is useless and avoid it too. + +[1] https://lore.kernel.org/r/96efe46b-dcce-4490-bba1-a0b00932d1cc@linux.alibaba.com + +Fixes: a64d9493f587 ("staging: erofs: refuse to mount images with malformed volume name") +Reviewed-by: Chao Yu +Signed-off-by: Gao Xiang +Link: https://lore.kernel.org/r/20250225033934.2542635-1-hsiangkao@linux.alibaba.com +Signed-off-by: Sasha Levin +--- + fs/erofs/internal.h | 2 -- + fs/erofs/super.c | 8 -------- + 2 files changed, 10 deletions(-) + +diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h +index 686d835eb533a..efd25f3101f1f 100644 +--- a/fs/erofs/internal.h ++++ b/fs/erofs/internal.h +@@ -152,8 +152,6 @@ struct erofs_sb_info { + /* used for statfs, f_files - f_favail */ + u64 inos; + +- u8 uuid[16]; /* 128-bit uuid for volume */ +- u8 volume_name[16]; /* volume name */ + u32 feature_compat; + u32 feature_incompat; + +diff --git a/fs/erofs/super.c b/fs/erofs/super.c +index 827b626656494..9f2bce5af9c83 100644 +--- a/fs/erofs/super.c ++++ b/fs/erofs/super.c +@@ -317,14 +317,6 @@ static int erofs_read_superblock(struct super_block *sb) + + super_set_uuid(sb, (void *)dsb->uuid, sizeof(dsb->uuid)); + +- ret = strscpy(sbi->volume_name, dsb->volume_name, +- sizeof(dsb->volume_name)); +- if (ret < 0) { /* -E2BIG */ +- erofs_err(sb, "bad volume name without NIL terminator"); +- ret = -EFSCORRUPTED; +- goto out; +- } +- + /* parse on-disk compression configurations */ + ret = z_erofs_parse_cfgs(sb, dsb); + if (ret < 0) +-- +2.39.5 + diff --git a/queue-6.14/eth-bnxt-fix-out-of-range-access-of-vnic_info-array.patch b/queue-6.14/eth-bnxt-fix-out-of-range-access-of-vnic_info-array.patch new file mode 100644 index 0000000000..a1d3630f7c --- /dev/null +++ b/queue-6.14/eth-bnxt-fix-out-of-range-access-of-vnic_info-array.patch @@ -0,0 +1,48 @@ +From bcc58d7daad601f746a701413619a6e379613587 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Mar 2025 02:58:37 +0000 +Subject: eth: bnxt: fix out-of-range access of vnic_info array + +From: Taehee Yoo + +[ Upstream commit 919f9f497dbcee75d487400e8f9815b74a6a37df ] + +The bnxt_queue_{start | stop}() access vnic_info as much as allocated, +which indicates bp->nr_vnics. +So, it should not reach bp->vnic_info[bp->nr_vnics]. + +Fixes: 661958552eda ("eth: bnxt: do not use BNXT_VNIC_NTUPLE unconditionally in queue restart logic") +Signed-off-by: Taehee Yoo +Reviewed-by: Michael Chan +Link: https://patch.msgid.link/20250316025837.939527-1-ap420073@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index 55f553debd3b2..0ddc3d41e2d81 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -15651,7 +15651,7 @@ static int bnxt_queue_start(struct net_device *dev, void *qmem, int idx) + cpr = &rxr->bnapi->cp_ring; + cpr->sw_stats->rx.rx_resets++; + +- for (i = 0; i <= bp->nr_vnics; i++) { ++ for (i = 0; i < bp->nr_vnics; i++) { + vnic = &bp->vnic_info[i]; + + rc = bnxt_hwrm_vnic_set_rss_p5(bp, vnic, true); +@@ -15679,7 +15679,7 @@ static int bnxt_queue_stop(struct net_device *dev, void *qmem, int idx) + struct bnxt_vnic_info *vnic; + int i; + +- for (i = 0; i <= bp->nr_vnics; i++) { ++ for (i = 0; i < bp->nr_vnics; i++) { + vnic = &bp->vnic_info[i]; + vnic->mru = 0; + bnxt_hwrm_vnic_update(bp, vnic, +-- +2.39.5 + diff --git a/queue-6.14/exfat-fix-missing-shutdown-check.patch b/queue-6.14/exfat-fix-missing-shutdown-check.patch new file mode 100644 index 0000000000..b0574c2772 --- /dev/null +++ b/queue-6.14/exfat-fix-missing-shutdown-check.patch @@ -0,0 +1,97 @@ +From 20b10cc11097c71a987ce322046b9ab1d89cc303 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 15:02:07 +0800 +Subject: exfat: fix missing shutdown check + +From: Yuezhang Mo + +[ Upstream commit 47e35366bc6fa3cf189a8305bce63992495f3efa ] + +xfstests generic/730 test failed because after deleting the device +that still had dirty data, the file could still be read without +returning an error. The reason is the missing shutdown check in +->read_iter. + +I also noticed that shutdown checks were missing from ->write_iter, +->splice_read, and ->mmap. This commit adds shutdown checks to all +of them. + +Fixes: f761fcdd289d ("exfat: Implement sops->shutdown and ioctl") +Signed-off-by: Yuezhang Mo +Signed-off-by: Namjae Jeon +Signed-off-by: Sasha Levin +--- + fs/exfat/file.c | 29 +++++++++++++++++++++++++++-- + 1 file changed, 27 insertions(+), 2 deletions(-) + +diff --git a/fs/exfat/file.c b/fs/exfat/file.c +index 807349d8ea050..841a5b18e3dfd 100644 +--- a/fs/exfat/file.c ++++ b/fs/exfat/file.c +@@ -582,6 +582,9 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter) + loff_t pos = iocb->ki_pos; + loff_t valid_size; + ++ if (unlikely(exfat_forced_shutdown(inode->i_sb))) ++ return -EIO; ++ + inode_lock(inode); + + valid_size = ei->valid_size; +@@ -635,6 +638,16 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter) + return ret; + } + ++static ssize_t exfat_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) ++{ ++ struct inode *inode = file_inode(iocb->ki_filp); ++ ++ if (unlikely(exfat_forced_shutdown(inode->i_sb))) ++ return -EIO; ++ ++ return generic_file_read_iter(iocb, iter); ++} ++ + static vm_fault_t exfat_page_mkwrite(struct vm_fault *vmf) + { + int err; +@@ -672,14 +685,26 @@ static const struct vm_operations_struct exfat_file_vm_ops = { + + static int exfat_file_mmap(struct file *file, struct vm_area_struct *vma) + { ++ if (unlikely(exfat_forced_shutdown(file_inode(file)->i_sb))) ++ return -EIO; ++ + file_accessed(file); + vma->vm_ops = &exfat_file_vm_ops; + return 0; + } + ++static ssize_t exfat_splice_read(struct file *in, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, unsigned int flags) ++{ ++ if (unlikely(exfat_forced_shutdown(file_inode(in)->i_sb))) ++ return -EIO; ++ ++ return filemap_splice_read(in, ppos, pipe, len, flags); ++} ++ + const struct file_operations exfat_file_operations = { + .llseek = generic_file_llseek, +- .read_iter = generic_file_read_iter, ++ .read_iter = exfat_file_read_iter, + .write_iter = exfat_file_write_iter, + .unlocked_ioctl = exfat_ioctl, + #ifdef CONFIG_COMPAT +@@ -687,7 +712,7 @@ const struct file_operations exfat_file_operations = { + #endif + .mmap = exfat_file_mmap, + .fsync = exfat_file_fsync, +- .splice_read = filemap_splice_read, ++ .splice_read = exfat_splice_read, + .splice_write = iter_file_splice_write, + }; + +-- +2.39.5 + diff --git a/queue-6.14/exfat-fix-the-infinite-loop-in-exfat_find_last_clust.patch b/queue-6.14/exfat-fix-the-infinite-loop-in-exfat_find_last_clust.patch new file mode 100644 index 0000000000..f4efd7f019 --- /dev/null +++ b/queue-6.14/exfat-fix-the-infinite-loop-in-exfat_find_last_clust.patch @@ -0,0 +1,46 @@ +From 7c1f33aa393e713ec14db1520b837cdaa1a06e3d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 10:53:10 +0800 +Subject: exfat: fix the infinite loop in exfat_find_last_cluster() + +From: Yuezhang Mo + +[ Upstream commit b0522303f67255926b946aa66885a0104d1b2980 ] + +In exfat_find_last_cluster(), the cluster chain is traversed until +the EOF cluster. If the cluster chain includes a loop due to file +system corruption, the EOF cluster cannot be traversed, resulting +in an infinite loop. + +If the number of clusters indicated by the file size is inconsistent +with the cluster chain length, exfat_find_last_cluster() will return +an error, so if this inconsistency is found, the traversal can be +aborted without traversing to the EOF cluster. + +Reported-by: syzbot+f7d147e6db52b1e09dba@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=f7d147e6db52b1e09dba +Tested-by: syzbot+f7d147e6db52b1e09dba@syzkaller.appspotmail.com +Fixes: 31023864e67a ("exfat: add fat entry operations") +Signed-off-by: Yuezhang Mo +Signed-off-by: Namjae Jeon +Signed-off-by: Sasha Levin +--- + fs/exfat/fatent.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/exfat/fatent.c b/fs/exfat/fatent.c +index 6f3651c6ca91e..8df5ad6ebb10c 100644 +--- a/fs/exfat/fatent.c ++++ b/fs/exfat/fatent.c +@@ -265,7 +265,7 @@ int exfat_find_last_cluster(struct super_block *sb, struct exfat_chain *p_chain, + clu = next; + if (exfat_ent_get(sb, clu, &next)) + return -EIO; +- } while (next != EXFAT_EOF_CLUSTER); ++ } while (next != EXFAT_EOF_CLUSTER && count <= p_chain->size); + + if (p_chain->size != count) { + exfat_fs_error(sb, +-- +2.39.5 + diff --git a/queue-6.14/ext4-add-ext4_flags_emergency_ro-bit.patch b/queue-6.14/ext4-add-ext4_flags_emergency_ro-bit.patch new file mode 100644 index 0000000000..10440dfaa7 --- /dev/null +++ b/queue-6.14/ext4-add-ext4_flags_emergency_ro-bit.patch @@ -0,0 +1,53 @@ +From 2040986d1a6849625362cc2174a4cfcdac1ed897 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 19:41:25 +0800 +Subject: ext4: add EXT4_FLAGS_EMERGENCY_RO bit + +From: Baokun Li + +[ Upstream commit f3054e53c2f367bd3cf6535afe9ab13198d2d739 ] + +EXT4_FLAGS_EMERGENCY_RO Indicates that the current file system has become +read-only due to some error. Compared to SB_RDONLY, setting it does not +require a lock because we won't clear it, which avoids over-coupling with +vfs freeze. Also, add a helper function ext4_emergency_ro() to check if +the bit is set. + +Signed-off-by: Baokun Li +Reviewed-by: Jan Kara +Reviewed-by: Zhang Yi +Link: https://patch.msgid.link/20250122114130.229709-3-libaokun@huaweicloud.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: 8f984530c242 ("ext4: correct behavior under errors=remount-ro mode") +Signed-off-by: Sasha Levin +--- + fs/ext4/ext4.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index b3528e4eba180..7f5fd1a433662 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -2236,6 +2236,7 @@ enum { + EXT4_FLAGS_RESIZING, /* Avoid superblock update and resize race */ + EXT4_FLAGS_SHUTDOWN, /* Prevent access to the file system */ + EXT4_FLAGS_BDEV_IS_DAX, /* Current block device support DAX */ ++ EXT4_FLAGS_EMERGENCY_RO,/* Emergency read-only due to fs errors */ + }; + + static inline int ext4_forced_shutdown(struct super_block *sb) +@@ -2243,6 +2244,11 @@ static inline int ext4_forced_shutdown(struct super_block *sb) + return test_bit(EXT4_FLAGS_SHUTDOWN, &EXT4_SB(sb)->s_ext4_flags); + } + ++static inline int ext4_emergency_ro(struct super_block *sb) ++{ ++ return test_bit(EXT4_FLAGS_EMERGENCY_RO, &EXT4_SB(sb)->s_ext4_flags); ++} ++ + /* + * Default values for user and/or group using reserved blocks + */ +-- +2.39.5 + diff --git a/queue-6.14/ext4-add-missing-brelse-for-bh2-in-ext4_dx_add_entry.patch b/queue-6.14/ext4-add-missing-brelse-for-bh2-in-ext4_dx_add_entry.patch new file mode 100644 index 0000000000..3aa2ed5f25 --- /dev/null +++ b/queue-6.14/ext4-add-missing-brelse-for-bh2-in-ext4_dx_add_entry.patch @@ -0,0 +1,77 @@ +From c00a37265b9447a15db9112fffc1e8c59688ef08 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 00:20:48 +0800 +Subject: ext4: add missing brelse() for bh2 in ext4_dx_add_entry() + +From: Kemeng Shi + +[ Upstream commit eb640af64db6d4702a85ab001b9cc7f4c5dd6abb ] + +Add missing brelse() for bh2 in ext4_dx_add_entry(). + +Fixes: ac27a0ec112a ("[PATCH] ext4: initial copy of files from ext3") +Signed-off-by: Kemeng Shi +Reviewed-by: Ojaswin Mujoo +Reviewed-by: Zhang Yi +Link: https://patch.msgid.link/20250123162050.2114499-2-shikemeng@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/namei.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c +index 536d56d150726..8e49cb7118581 100644 +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -2577,8 +2577,10 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname, + BUFFER_TRACE(frame->bh, "get_write_access"); + err = ext4_journal_get_write_access(handle, sb, frame->bh, + EXT4_JTR_NONE); +- if (err) ++ if (err) { ++ brelse(bh2); + goto journal_error; ++ } + if (!add_level) { + unsigned icount1 = icount/2, icount2 = icount - icount1; + unsigned hash2 = dx_get_hash(entries + icount1); +@@ -2589,8 +2591,10 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname, + err = ext4_journal_get_write_access(handle, sb, + (frame - 1)->bh, + EXT4_JTR_NONE); +- if (err) ++ if (err) { ++ brelse(bh2); + goto journal_error; ++ } + + memcpy((char *) entries2, (char *) (entries + icount1), + icount2 * sizeof(struct dx_entry)); +@@ -2609,8 +2613,10 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname, + dxtrace(dx_show_index("node", + ((struct dx_node *) bh2->b_data)->entries)); + err = ext4_handle_dirty_dx_node(handle, dir, bh2); +- if (err) ++ if (err) { ++ brelse(bh2); + goto journal_error; ++ } + brelse (bh2); + err = ext4_handle_dirty_dx_node(handle, dir, + (frame - 1)->bh); +@@ -2635,8 +2641,10 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname, + "Creating %d level index...\n", + dxroot->info.indirect_levels)); + err = ext4_handle_dirty_dx_node(handle, dir, frame->bh); +- if (err) ++ if (err) { ++ brelse(bh2); + goto journal_error; ++ } + err = ext4_handle_dirty_dx_node(handle, dir, bh2); + brelse(bh2); + restart = 1; +-- +2.39.5 + diff --git a/queue-6.14/ext4-avoid-journaling-sb-update-on-error-if-journal-.patch b/queue-6.14/ext4-avoid-journaling-sb-update-on-error-if-journal-.patch new file mode 100644 index 0000000000..1deeba68aa --- /dev/null +++ b/queue-6.14/ext4-avoid-journaling-sb-update-on-error-if-journal-.patch @@ -0,0 +1,173 @@ +From 65d2d49dd037af531914ea3c67d8da391c06d09b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 13:22:56 +0530 +Subject: ext4: avoid journaling sb update on error if journal is destroying + +From: Ojaswin Mujoo + +[ Upstream commit ce2f26e73783b4a7c46a86e3af5b5c8de0971790 ] + +Presently we always BUG_ON if trying to start a transaction on a journal marked +with JBD2_UNMOUNT, since this should never happen. However, while ltp running +stress tests, it was observed that in case of some error handling paths, it is +possible for update_super_work to start a transaction after the journal is +destroyed eg: + +(umount) +ext4_kill_sb + kill_block_super + generic_shutdown_super + sync_filesystem /* commits all txns */ + evict_inodes + /* might start a new txn */ + ext4_put_super + flush_work(&sbi->s_sb_upd_work) /* flush the workqueue */ + jbd2_journal_destroy + journal_kill_thread + journal->j_flags |= JBD2_UNMOUNT; + jbd2_journal_commit_transaction + jbd2_journal_get_descriptor_buffer + jbd2_journal_bmap + ext4_journal_bmap + ext4_map_blocks + ... + ext4_inode_error + ext4_handle_error + schedule_work(&sbi->s_sb_upd_work) + + /* work queue kicks in */ + update_super_work + jbd2_journal_start + start_this_handle + BUG_ON(journal->j_flags & + JBD2_UNMOUNT) + +Hence, introduce a new mount flag to indicate journal is destroying and only do +a journaled (and deferred) update of sb if this flag is not set. Otherwise, just +fallback to an un-journaled commit. + +Further, in the journal destroy path, we have the following sequence: + + 1. Set mount flag indicating journal is destroying + 2. force a commit and wait for it + 3. flush pending sb updates + +This sequence is important as it ensures that, after this point, there is no sb +update that might be journaled so it is safe to update the sb outside the +journal. (To avoid race discussed in 2d01ddc86606) + +Also, we don't need a similar check in ext4_grp_locked_error since it is only +called from mballoc and AFAICT it would be always valid to schedule work here. + +Fixes: 2d01ddc86606 ("ext4: save error info to sb through journal if available") +Reported-by: Mahesh Kumar +Signed-off-by: Ojaswin Mujoo +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/9613c465d6ff00cd315602f99283d5f24018c3f7.1742279837.git.ojaswin@linux.ibm.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/ext4.h | 3 ++- + fs/ext4/ext4_jbd2.h | 15 +++++++++++++++ + fs/ext4/super.c | 16 ++++++++-------- + 3 files changed, 25 insertions(+), 9 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 7f5fd1a433662..df30d9f235123 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1821,7 +1821,8 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) + */ + enum { + EXT4_MF_MNTDIR_SAMPLED, +- EXT4_MF_FC_INELIGIBLE /* Fast commit ineligible */ ++ EXT4_MF_FC_INELIGIBLE, /* Fast commit ineligible */ ++ EXT4_MF_JOURNAL_DESTROY /* Journal is in process of destroying */ + }; + + static inline void ext4_set_mount_flag(struct super_block *sb, int bit) +diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h +index 930778e507cc4..ada46189b0860 100644 +--- a/fs/ext4/ext4_jbd2.h ++++ b/fs/ext4/ext4_jbd2.h +@@ -521,6 +521,21 @@ static inline int ext4_journal_destroy(struct ext4_sb_info *sbi, journal_t *jour + { + int err = 0; + ++ /* ++ * At this point only two things can be operating on the journal. ++ * JBD2 thread performing transaction commit and s_sb_upd_work ++ * issuing sb update through the journal. Once we set ++ * EXT4_JOURNAL_DESTROY, new ext4_handle_error() calls will not ++ * queue s_sb_upd_work and ext4_force_commit() makes sure any ++ * ext4_handle_error() calls from the running transaction commit are ++ * finished. Hence no new s_sb_upd_work can be queued after we ++ * flush it here. ++ */ ++ ext4_set_mount_flag(sbi->s_sb, EXT4_MF_JOURNAL_DESTROY); ++ ++ ext4_force_commit(sbi->s_sb); ++ flush_work(&sbi->s_sb_upd_work); ++ + err = jbd2_journal_destroy(journal); + sbi->s_journal = NULL; + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index f658c017055f3..b666ef71a034a 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -716,9 +716,13 @@ static void ext4_handle_error(struct super_block *sb, bool force_ro, int error, + * In case the fs should keep running, we need to writeout + * superblock through the journal. Due to lock ordering + * constraints, it may not be safe to do it right here so we +- * defer superblock flushing to a workqueue. ++ * defer superblock flushing to a workqueue. We just need to be ++ * careful when the journal is already shutting down. If we get ++ * here in that case, just update the sb directly as the last ++ * transaction won't commit anyway. + */ +- if (continue_fs && journal) ++ if (continue_fs && journal && ++ !ext4_test_mount_flag(sb, EXT4_MF_JOURNAL_DESTROY)) + schedule_work(&EXT4_SB(sb)->s_sb_upd_work); + else + ext4_commit_super(sb); +@@ -1303,7 +1307,6 @@ static void ext4_put_super(struct super_block *sb) + ext4_unregister_li_request(sb); + ext4_quotas_off(sb, EXT4_MAXQUOTAS); + +- flush_work(&sbi->s_sb_upd_work); + destroy_workqueue(sbi->rsv_conversion_wq); + ext4_release_orphan_info(sb); + +@@ -1313,7 +1316,8 @@ static void ext4_put_super(struct super_block *sb) + if ((err < 0) && !aborted) { + ext4_abort(sb, -err, "Couldn't clean up the journal"); + } +- } ++ } else ++ flush_work(&sbi->s_sb_upd_work); + + ext4_es_unregister_shrinker(sbi); + timer_shutdown_sync(&sbi->s_err_report); +@@ -4972,8 +4976,6 @@ static int ext4_load_and_init_journal(struct super_block *sb, + return 0; + + out: +- /* flush s_sb_upd_work before destroying the journal. */ +- flush_work(&sbi->s_sb_upd_work); + ext4_journal_destroy(sbi, sbi->s_journal); + return -EINVAL; + } +@@ -5663,8 +5665,6 @@ failed_mount8: __maybe_unused + sbi->s_ea_block_cache = NULL; + + if (sbi->s_journal) { +- /* flush s_sb_upd_work before journal destroy. */ +- flush_work(&sbi->s_sb_upd_work); + ext4_journal_destroy(sbi, sbi->s_journal); + } + failed_mount3a: +-- +2.39.5 + diff --git a/queue-6.14/ext4-convert-ext4_flags_-defines-to-enum.patch b/queue-6.14/ext4-convert-ext4_flags_-defines-to-enum.patch new file mode 100644 index 0000000000..65efd2b7d6 --- /dev/null +++ b/queue-6.14/ext4-convert-ext4_flags_-defines-to-enum.patch @@ -0,0 +1,44 @@ +From cb59aebb8e91ab456be0622d78f2e2b09b136c63 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 19:41:24 +0800 +Subject: ext4: convert EXT4_FLAGS_* defines to enum + +From: Baokun Li + +[ Upstream commit 99708f8a9d30081a71638d6f4e216350a4340cc3 ] + +Do away with the defines and use an enum as it's cleaner. + +Signed-off-by: Baokun Li +Reviewed-by: Jan Kara +Reviewed-by: Zhang Yi +Link: https://patch.msgid.link/20250122114130.229709-2-libaokun@huaweicloud.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: 8f984530c242 ("ext4: correct behavior under errors=remount-ro mode") +Signed-off-by: Sasha Levin +--- + fs/ext4/ext4.h | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 4e7de7eaa374a..b3528e4eba180 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -2232,9 +2232,11 @@ extern int ext4_feature_set_ok(struct super_block *sb, int readonly); + /* + * Superblock flags + */ +-#define EXT4_FLAGS_RESIZING 0 +-#define EXT4_FLAGS_SHUTDOWN 1 +-#define EXT4_FLAGS_BDEV_IS_DAX 2 ++enum { ++ EXT4_FLAGS_RESIZING, /* Avoid superblock update and resize race */ ++ EXT4_FLAGS_SHUTDOWN, /* Prevent access to the file system */ ++ EXT4_FLAGS_BDEV_IS_DAX, /* Current block device support DAX */ ++}; + + static inline int ext4_forced_shutdown(struct super_block *sb) + { +-- +2.39.5 + diff --git a/queue-6.14/ext4-correct-behavior-under-errors-remount-ro-mode.patch b/queue-6.14/ext4-correct-behavior-under-errors-remount-ro-mode.patch new file mode 100644 index 0000000000..c5b19775d5 --- /dev/null +++ b/queue-6.14/ext4-correct-behavior-under-errors-remount-ro-mode.patch @@ -0,0 +1,76 @@ +From 815e5c1d935de53a552f69718135a3e471644b4d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 19:41:28 +0800 +Subject: ext4: correct behavior under errors=remount-ro mode + +From: Baokun Li + +[ Upstream commit 8f984530c242c569bafecfa35bce969a9b8fb0dd ] + +And after commit 95257987a638 ("ext4: drop EXT4_MF_FS_ABORTED flag") in +v6.6-rc1, the EXT4_FLAGS_SHUTDOWN bit is set in ext4_handle_error() under +errors=remount-ro mode. This causes the read to fail even when the error +is triggered in errors=remount-ro mode. + +To correct the behavior under errors=remount-ro, EXT4_FLAGS_SHUTDOWN is +replaced by the newly introduced EXT4_FLAGS_EMERGENCY_RO. This new flag +only prevents writes, matching the previous behavior with SB_RDONLY. + +Fixes: 95257987a638 ("ext4: drop EXT4_MF_FS_ABORTED flag") +Closes: https://lore.kernel.org/all/22d652f6-cb3c-43f5-b2fe-0a4bb6516a04@huawei.com/ +Suggested-by: Jan Kara +Signed-off-by: Baokun Li +Reviewed-by: Zhang Yi +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20250122114130.229709-6-libaokun@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/super.c | 19 ++++++++----------- + 1 file changed, 8 insertions(+), 11 deletions(-) + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index a50e5c31b9378..0ff0c3d0a3c08 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -707,11 +707,8 @@ static void ext4_handle_error(struct super_block *sb, bool force_ro, int error, + if (test_opt(sb, WARN_ON_ERROR)) + WARN_ON_ONCE(1); + +- if (!continue_fs && !sb_rdonly(sb)) { +- set_bit(EXT4_FLAGS_SHUTDOWN, &EXT4_SB(sb)->s_ext4_flags); +- if (journal) +- jbd2_journal_abort(journal, -EIO); +- } ++ if (!continue_fs && !ext4_emergency_ro(sb) && journal) ++ jbd2_journal_abort(journal, -EIO); + + if (!bdev_read_only(sb->s_bdev)) { + save_error_info(sb, error, ino, block, func, line); +@@ -737,17 +734,17 @@ static void ext4_handle_error(struct super_block *sb, bool force_ro, int error, + sb->s_id); + } + +- if (sb_rdonly(sb) || continue_fs) ++ if (ext4_emergency_ro(sb) || continue_fs) + return; + + ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only"); + /* +- * EXT4_FLAGS_SHUTDOWN was set which stops all filesystem +- * modifications. We don't set SB_RDONLY because that requires +- * sb->s_umount semaphore and setting it without proper remount +- * procedure is confusing code such as freeze_super() leading to +- * deadlocks and other problems. ++ * We don't set SB_RDONLY because that requires sb->s_umount ++ * semaphore and setting it without proper remount procedure is ++ * confusing code such as freeze_super() leading to deadlocks ++ * and other problems. + */ ++ set_bit(EXT4_FLAGS_EMERGENCY_RO, &EXT4_SB(sb)->s_ext4_flags); + } + + static void update_super_work(struct work_struct *work) +-- +2.39.5 + diff --git a/queue-6.14/ext4-define-ext4_journal_destroy-wrapper.patch b/queue-6.14/ext4-define-ext4_journal_destroy-wrapper.patch new file mode 100644 index 0000000000..757a714f83 --- /dev/null +++ b/queue-6.14/ext4-define-ext4_journal_destroy-wrapper.patch @@ -0,0 +1,114 @@ +From 270eb329c745cbae85aec252be8f6844c756a87e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 13:22:55 +0530 +Subject: ext4: define ext4_journal_destroy wrapper + +From: Ojaswin Mujoo + +[ Upstream commit 5a02a6204ca37e7c22fbb55a789c503f05e8e89a ] + +Define an ext4 wrapper over jbd2_journal_destroy to make sure we +have consistent behavior during journal destruction. This will also +come useful in the next patch where we add some ext4 specific logic +in the destroy path. + +Reviewed-by: Jan Kara +Reviewed-by: Baokun Li +Signed-off-by: Ojaswin Mujoo +Link: https://patch.msgid.link/c3ba78c5c419757e6d5f2d8ebb4a8ce9d21da86a.1742279837.git.ojaswin@linux.ibm.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: ce2f26e73783 ("ext4: avoid journaling sb update on error if journal is destroying") +Signed-off-by: Sasha Levin +--- + fs/ext4/ext4_jbd2.h | 14 ++++++++++++++ + fs/ext4/super.c | 16 ++++++---------- + 2 files changed, 20 insertions(+), 10 deletions(-) + +diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h +index 0c77697d5e90d..930778e507cc4 100644 +--- a/fs/ext4/ext4_jbd2.h ++++ b/fs/ext4/ext4_jbd2.h +@@ -513,4 +513,18 @@ static inline int ext4_should_dioread_nolock(struct inode *inode) + return 1; + } + ++/* ++ * Pass journal explicitly as it may not be cached in the sbi->s_journal in some ++ * cases ++ */ ++static inline int ext4_journal_destroy(struct ext4_sb_info *sbi, journal_t *journal) ++{ ++ int err = 0; ++ ++ err = jbd2_journal_destroy(journal); ++ sbi->s_journal = NULL; ++ ++ return err; ++} ++ + #endif /* _EXT4_JBD2_H */ +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 0d1c3eefe438a..f658c017055f3 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -1309,8 +1309,7 @@ static void ext4_put_super(struct super_block *sb) + + if (sbi->s_journal) { + aborted = is_journal_aborted(sbi->s_journal); +- err = jbd2_journal_destroy(sbi->s_journal); +- sbi->s_journal = NULL; ++ err = ext4_journal_destroy(sbi, sbi->s_journal); + if ((err < 0) && !aborted) { + ext4_abort(sb, -err, "Couldn't clean up the journal"); + } +@@ -4975,8 +4974,7 @@ static int ext4_load_and_init_journal(struct super_block *sb, + out: + /* flush s_sb_upd_work before destroying the journal. */ + flush_work(&sbi->s_sb_upd_work); +- jbd2_journal_destroy(sbi->s_journal); +- sbi->s_journal = NULL; ++ ext4_journal_destroy(sbi, sbi->s_journal); + return -EINVAL; + } + +@@ -5667,8 +5665,7 @@ failed_mount8: __maybe_unused + if (sbi->s_journal) { + /* flush s_sb_upd_work before journal destroy. */ + flush_work(&sbi->s_sb_upd_work); +- jbd2_journal_destroy(sbi->s_journal); +- sbi->s_journal = NULL; ++ ext4_journal_destroy(sbi, sbi->s_journal); + } + failed_mount3a: + ext4_es_unregister_shrinker(sbi); +@@ -5973,7 +5970,7 @@ static journal_t *ext4_open_dev_journal(struct super_block *sb, + return journal; + + out_journal: +- jbd2_journal_destroy(journal); ++ ext4_journal_destroy(EXT4_SB(sb), journal); + out_bdev: + bdev_fput(bdev_file); + return ERR_PTR(errno); +@@ -6090,8 +6087,7 @@ static int ext4_load_journal(struct super_block *sb, + EXT4_SB(sb)->s_journal = journal; + err = ext4_clear_journal_err(sb, es); + if (err) { +- EXT4_SB(sb)->s_journal = NULL; +- jbd2_journal_destroy(journal); ++ ext4_journal_destroy(EXT4_SB(sb), journal); + return err; + } + +@@ -6109,7 +6105,7 @@ static int ext4_load_journal(struct super_block *sb, + return 0; + + err_out: +- jbd2_journal_destroy(journal); ++ ext4_journal_destroy(EXT4_SB(sb), journal); + return err; + } + +-- +2.39.5 + diff --git a/queue-6.14/ext4-fix-out-of-bound-read-in-ext4_xattr_inode_dec_r.patch b/queue-6.14/ext4-fix-out-of-bound-read-in-ext4_xattr_inode_dec_r.patch new file mode 100644 index 0000000000..d2c3ee75a0 --- /dev/null +++ b/queue-6.14/ext4-fix-out-of-bound-read-in-ext4_xattr_inode_dec_r.patch @@ -0,0 +1,199 @@ +From af217f4c41103594e1b1b4704f78d71822d1bfdc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Feb 2025 14:31:41 +0800 +Subject: ext4: fix out-of-bound read in ext4_xattr_inode_dec_ref_all() + +From: Ye Bin + +[ Upstream commit 5701875f9609b000d91351eaa6bfd97fe2f157f4 ] + +There's issue as follows: +BUG: KASAN: use-after-free in ext4_xattr_inode_dec_ref_all+0x6ff/0x790 +Read of size 4 at addr ffff88807b003000 by task syz-executor.0/15172 + +CPU: 3 PID: 15172 Comm: syz-executor.0 +Call Trace: + __dump_stack lib/dump_stack.c:82 [inline] + dump_stack+0xbe/0xfd lib/dump_stack.c:123 + print_address_description.constprop.0+0x1e/0x280 mm/kasan/report.c:400 + __kasan_report.cold+0x6c/0x84 mm/kasan/report.c:560 + kasan_report+0x3a/0x50 mm/kasan/report.c:585 + ext4_xattr_inode_dec_ref_all+0x6ff/0x790 fs/ext4/xattr.c:1137 + ext4_xattr_delete_inode+0x4c7/0xda0 fs/ext4/xattr.c:2896 + ext4_evict_inode+0xb3b/0x1670 fs/ext4/inode.c:323 + evict+0x39f/0x880 fs/inode.c:622 + iput_final fs/inode.c:1746 [inline] + iput fs/inode.c:1772 [inline] + iput+0x525/0x6c0 fs/inode.c:1758 + ext4_orphan_cleanup fs/ext4/super.c:3298 [inline] + ext4_fill_super+0x8c57/0xba40 fs/ext4/super.c:5300 + mount_bdev+0x355/0x410 fs/super.c:1446 + legacy_get_tree+0xfe/0x220 fs/fs_context.c:611 + vfs_get_tree+0x8d/0x2f0 fs/super.c:1576 + do_new_mount fs/namespace.c:2983 [inline] + path_mount+0x119a/0x1ad0 fs/namespace.c:3316 + do_mount+0xfc/0x110 fs/namespace.c:3329 + __do_sys_mount fs/namespace.c:3540 [inline] + __se_sys_mount+0x219/0x2e0 fs/namespace.c:3514 + do_syscall_64+0x33/0x40 arch/x86/entry/common.c:46 + entry_SYSCALL_64_after_hwframe+0x67/0xd1 + +Memory state around the buggy address: + ffff88807b002f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ffff88807b002f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +>ffff88807b003000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ^ + ffff88807b003080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ffff88807b003100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + +Above issue happens as ext4_xattr_delete_inode() isn't check xattr +is valid if xattr is in inode. +To solve above issue call xattr_check_inode() check if xattr if valid +in inode. In fact, we can directly verify in ext4_iget_extra_inode(), +so that there is no divergent verification. + +Fixes: e50e5129f384 ("ext4: xattr-in-inode support") +Signed-off-by: Ye Bin +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20250208063141.1539283-3-yebin@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/inode.c | 5 +++++ + fs/ext4/xattr.c | 26 +------------------------- + fs/ext4/xattr.h | 7 +++++++ + 3 files changed, 13 insertions(+), 25 deletions(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 64e280fed9119..891bd1e2d19f8 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4674,6 +4674,11 @@ static inline int ext4_iget_extra_inode(struct inode *inode, + *magic == cpu_to_le32(EXT4_XATTR_MAGIC)) { + int err; + ++ err = xattr_check_inode(inode, IHDR(inode, raw_inode), ++ ITAIL(inode, raw_inode)); ++ if (err) ++ return err; ++ + ext4_set_inode_state(inode, EXT4_STATE_XATTR); + err = ext4_find_inline_data_nolock(inode); + if (!err && ext4_has_inline_data(inode)) +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index 0e4494863d153..a10fb8a9d02dc 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -308,7 +308,7 @@ __ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh, + __ext4_xattr_check_block((inode), (bh), __func__, __LINE__) + + +-static inline int ++int + __xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header, + void *end, const char *function, unsigned int line) + { +@@ -316,9 +316,6 @@ __xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header, + function, line); + } + +-#define xattr_check_inode(inode, header, end) \ +- __xattr_check_inode((inode), (header), (end), __func__, __LINE__) +- + static int + xattr_find_entry(struct inode *inode, struct ext4_xattr_entry **pentry, + void *end, int name_index, const char *name, int sorted) +@@ -650,9 +647,6 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name, + raw_inode = ext4_raw_inode(&iloc); + header = IHDR(inode, raw_inode); + end = ITAIL(inode, raw_inode); +- error = xattr_check_inode(inode, header, end); +- if (error) +- goto cleanup; + entry = IFIRST(header); + error = xattr_find_entry(inode, &entry, end, name_index, name, 0); + if (error) +@@ -783,7 +777,6 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size) + struct ext4_xattr_ibody_header *header; + struct ext4_inode *raw_inode; + struct ext4_iloc iloc; +- void *end; + int error; + + if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR)) +@@ -793,14 +786,9 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size) + return error; + raw_inode = ext4_raw_inode(&iloc); + header = IHDR(inode, raw_inode); +- end = ITAIL(inode, raw_inode); +- error = xattr_check_inode(inode, header, end); +- if (error) +- goto cleanup; + error = ext4_xattr_list_entries(dentry, IFIRST(header), + buffer, buffer_size); + +-cleanup: + brelse(iloc.bh); + return error; + } +@@ -868,7 +856,6 @@ int ext4_get_inode_usage(struct inode *inode, qsize_t *usage) + struct ext4_xattr_ibody_header *header; + struct ext4_xattr_entry *entry; + qsize_t ea_inode_refs = 0; +- void *end; + int ret; + + lockdep_assert_held_read(&EXT4_I(inode)->xattr_sem); +@@ -879,10 +866,6 @@ int ext4_get_inode_usage(struct inode *inode, qsize_t *usage) + goto out; + raw_inode = ext4_raw_inode(&iloc); + header = IHDR(inode, raw_inode); +- end = ITAIL(inode, raw_inode); +- ret = xattr_check_inode(inode, header, end); +- if (ret) +- goto out; + + for (entry = IFIRST(header); !IS_LAST_ENTRY(entry); + entry = EXT4_XATTR_NEXT(entry)) +@@ -2237,9 +2220,6 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i, + is->s.here = is->s.first; + is->s.end = ITAIL(inode, raw_inode); + if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) { +- error = xattr_check_inode(inode, header, is->s.end); +- if (error) +- return error; + /* Find the named attribute. */ + error = xattr_find_entry(inode, &is->s.here, is->s.end, + i->name_index, i->name, 0); +@@ -2790,10 +2770,6 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, + min_offs = end - base; + total_ino = sizeof(struct ext4_xattr_ibody_header) + sizeof(u32); + +- error = xattr_check_inode(inode, header, end); +- if (error) +- goto cleanup; +- + ifree = ext4_xattr_free_space(base, &min_offs, base, &total_ino); + if (ifree >= isize_diff) + goto shift; +diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h +index 5197f17ffd9a2..1fedf44d4fb65 100644 +--- a/fs/ext4/xattr.h ++++ b/fs/ext4/xattr.h +@@ -209,6 +209,13 @@ extern int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode, + extern struct mb_cache *ext4_xattr_create_cache(void); + extern void ext4_xattr_destroy_cache(struct mb_cache *); + ++extern int ++__xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header, ++ void *end, const char *function, unsigned int line); ++ ++#define xattr_check_inode(inode, header, end) \ ++ __xattr_check_inode((inode), (header), (end), __func__, __LINE__) ++ + #ifdef CONFIG_EXT4_FS_SECURITY + extern int ext4_init_security(handle_t *handle, struct inode *inode, + struct inode *dir, const struct qstr *qstr); +-- +2.39.5 + diff --git a/queue-6.14/ext4-fix-potential-null-dereference-in-ext4-kunit-te.patch b/queue-6.14/ext4-fix-potential-null-dereference-in-ext4-kunit-te.patch new file mode 100644 index 0000000000..dca1dba6ea --- /dev/null +++ b/queue-6.14/ext4-fix-potential-null-dereference-in-ext4-kunit-te.patch @@ -0,0 +1,47 @@ +From b378698db9cf5d0e576c0cd0efc78c46766f8431 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jan 2025 17:24:21 +0800 +Subject: ext4: fix potential null dereference in ext4 kunit test + +From: Charles Han + +[ Upstream commit 57e7239ce0ed14e81e414c99d57f516f6220a995 ] + +kunit_kzalloc() may return a NULL pointer, dereferencing it +without NULL check may lead to NULL dereference. +Add a NULL check for grp. + +Fixes: ac96b56a2fbd ("ext4: Add unit test for mb_mark_used") +Fixes: b7098e1fa7bc ("ext4: Add unit test for mb_free_blocks") +Signed-off-by: Charles Han +Reviewed-by: Kemeng Shi +Link: https://patch.msgid.link/20250110092421.35619-1-hanchunchao@inspur.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/mballoc-test.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/ext4/mballoc-test.c b/fs/ext4/mballoc-test.c +index bb2a223b207c1..d634c12f19847 100644 +--- a/fs/ext4/mballoc-test.c ++++ b/fs/ext4/mballoc-test.c +@@ -796,6 +796,7 @@ static void test_mb_mark_used(struct kunit *test) + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buddy); + grp = kunit_kzalloc(test, offsetof(struct ext4_group_info, + bb_counters[MB_NUM_ORDERS(sb)]), GFP_KERNEL); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, grp); + + ret = ext4_mb_load_buddy(sb, TEST_GOAL_GROUP, &e4b); + KUNIT_ASSERT_EQ(test, ret, 0); +@@ -860,6 +861,7 @@ static void test_mb_free_blocks(struct kunit *test) + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buddy); + grp = kunit_kzalloc(test, offsetof(struct ext4_group_info, + bb_counters[MB_NUM_ORDERS(sb)]), GFP_KERNEL); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, grp); + + ret = ext4_mb_load_buddy(sb, TEST_GOAL_GROUP, &e4b); + KUNIT_ASSERT_EQ(test, ret, 0); +-- +2.39.5 + diff --git a/queue-6.14/ext4-goto-right-label-out_mmap_sem-in-ext4_setattr.patch b/queue-6.14/ext4-goto-right-label-out_mmap_sem-in-ext4_setattr.patch new file mode 100644 index 0000000000..d21a7867f6 --- /dev/null +++ b/queue-6.14/ext4-goto-right-label-out_mmap_sem-in-ext4_setattr.patch @@ -0,0 +1,61 @@ +From f2b8543ba420b681be5b098971d9de451aac005c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 19:22:47 +0800 +Subject: ext4: goto right label 'out_mmap_sem' in ext4_setattr() + +From: Baokun Li + +[ Upstream commit 7e91ae31e2d264155dfd102101afc2de7bd74a64 ] + +Otherwise, if ext4_inode_attach_jinode() fails, a hung task will +happen because filemap_invalidate_unlock() isn't called to unlock +mapping->invalidate_lock. Like this: + +EXT4-fs error (device sda) in ext4_setattr:5557: Out of memory +INFO: task fsstress:374 blocked for more than 122 seconds. + Not tainted 6.14.0-rc1-next-20250206-xfstests-dirty #726 +"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +task:fsstress state:D stack:0 pid:374 tgid:374 ppid:373 + task_flags:0x440140 flags:0x00000000 +Call Trace: + + __schedule+0x2c9/0x7f0 + schedule+0x27/0xa0 + schedule_preempt_disabled+0x15/0x30 + rwsem_down_read_slowpath+0x278/0x4c0 + down_read+0x59/0xb0 + page_cache_ra_unbounded+0x65/0x1b0 + filemap_get_pages+0x124/0x3e0 + filemap_read+0x114/0x3d0 + vfs_read+0x297/0x360 + ksys_read+0x6c/0xe0 + do_syscall_64+0x4b/0x110 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +Fixes: c7fc0366c656 ("ext4: partial zero eof block on unaligned inode size extension") +Signed-off-by: Baokun Li +Reviewed-by: Jan Kara +Reviewed-by: Brian Foster +Link: https://patch.msgid.link/20250213112247.3168709-1-libaokun@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/inode.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 891bd1e2d19f8..4009f9017a0e9 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -5477,7 +5477,7 @@ int ext4_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + oldsize & (inode->i_sb->s_blocksize - 1)) { + error = ext4_inode_attach_jinode(inode); + if (error) +- goto err_out; ++ goto out_mmap_sem; + } + + handle = ext4_journal_start(inode, EXT4_HT_INODE, 3); +-- +2.39.5 + diff --git a/queue-6.14/ext4-introduce-itail-helper.patch b/queue-6.14/ext4-introduce-itail-helper.patch new file mode 100644 index 0000000000..252e766a55 --- /dev/null +++ b/queue-6.14/ext4-introduce-itail-helper.patch @@ -0,0 +1,88 @@ +From 192e8c85dbe031bcbd6eb461a48def57ea1ceefc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Feb 2025 14:31:40 +0800 +Subject: ext4: introduce ITAIL helper + +From: Ye Bin + +[ Upstream commit 69f3a3039b0d0003de008659cafd5a1eaaa0a7a4 ] + +Introduce ITAIL helper to get the bound of xattr in inode. + +Signed-off-by: Ye Bin +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20250208063141.1539283-2-yebin@huaweicloud.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: 5701875f9609 ("ext4: fix out-of-bound read in ext4_xattr_inode_dec_ref_all()") +Signed-off-by: Sasha Levin +--- + fs/ext4/xattr.c | 10 +++++----- + fs/ext4/xattr.h | 3 +++ + 2 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index 7647e9f6e1903..0e4494863d153 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -649,7 +649,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name, + return error; + raw_inode = ext4_raw_inode(&iloc); + header = IHDR(inode, raw_inode); +- end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; ++ end = ITAIL(inode, raw_inode); + error = xattr_check_inode(inode, header, end); + if (error) + goto cleanup; +@@ -793,7 +793,7 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size) + return error; + raw_inode = ext4_raw_inode(&iloc); + header = IHDR(inode, raw_inode); +- end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; ++ end = ITAIL(inode, raw_inode); + error = xattr_check_inode(inode, header, end); + if (error) + goto cleanup; +@@ -879,7 +879,7 @@ int ext4_get_inode_usage(struct inode *inode, qsize_t *usage) + goto out; + raw_inode = ext4_raw_inode(&iloc); + header = IHDR(inode, raw_inode); +- end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; ++ end = ITAIL(inode, raw_inode); + ret = xattr_check_inode(inode, header, end); + if (ret) + goto out; +@@ -2235,7 +2235,7 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i, + header = IHDR(inode, raw_inode); + is->s.base = is->s.first = IFIRST(header); + is->s.here = is->s.first; +- is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; ++ is->s.end = ITAIL(inode, raw_inode); + if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) { + error = xattr_check_inode(inode, header, is->s.end); + if (error) +@@ -2786,7 +2786,7 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, + */ + + base = IFIRST(header); +- end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; ++ end = ITAIL(inode, raw_inode); + min_offs = end - base; + total_ino = sizeof(struct ext4_xattr_ibody_header) + sizeof(u32); + +diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h +index b25c2d7b5f991..5197f17ffd9a2 100644 +--- a/fs/ext4/xattr.h ++++ b/fs/ext4/xattr.h +@@ -67,6 +67,9 @@ struct ext4_xattr_entry { + ((void *)raw_inode + \ + EXT4_GOOD_OLD_INODE_SIZE + \ + EXT4_I(inode)->i_extra_isize)) ++#define ITAIL(inode, raw_inode) \ ++ ((void *)(raw_inode) + \ ++ EXT4_SB((inode)->i_sb)->s_inode_size) + #define IFIRST(hdr) ((struct ext4_xattr_entry *)((hdr)+1)) + + /* +-- +2.39.5 + diff --git a/queue-6.14/ext4-show-emergency_ro-when-ext4_flags_emergency_ro-.patch b/queue-6.14/ext4-show-emergency_ro-when-ext4_flags_emergency_ro-.patch new file mode 100644 index 0000000000..df557d774d --- /dev/null +++ b/queue-6.14/ext4-show-emergency_ro-when-ext4_flags_emergency_ro-.patch @@ -0,0 +1,47 @@ +From ec76c939740490625b92629679d1464594f68bc7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 19:41:29 +0800 +Subject: ext4: show 'emergency_ro' when EXT4_FLAGS_EMERGENCY_RO is set + +From: Baokun Li + +[ Upstream commit 6b76715d5e41fc332b0b879e66fad6ef3db07a3f ] + +After commit d3476f3dad4a ("ext4: don't set SB_RDONLY after filesystem +errors") in v6.12-rc1, the 'errors=remount-ro' mode no longer sets +SB_RDONLY on errors, which results in us seeing the filesystem is still +in rw state after errors. + +Therefore, after setting EXT4_FLAGS_EMERGENCY_RO, display the emergency_ro +option so that users can query whether the current file system has become +emergency read-only due to errors through commands such as 'mount' or +'cat /proc/fs/ext4/sdx/options'. + +Fixes: d3476f3dad4a ("ext4: don't set SB_RDONLY after filesystem errors") +Signed-off-by: Baokun Li +Reviewed-by: Jan Kara +Reviewed-by: Zhang Yi +Link: https://patch.msgid.link/20250122114130.229709-7-libaokun@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/super.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 0ff0c3d0a3c08..0d1c3eefe438a 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3035,6 +3035,9 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb, + if (nodefs && !test_opt(sb, NO_PREFETCH_BLOCK_BITMAPS)) + SEQ_OPTS_PUTS("prefetch_block_bitmaps"); + ++ if (ext4_emergency_ro(sb)) ++ SEQ_OPTS_PUTS("emergency_ro"); ++ + ext4_show_quota_options(seq, sb); + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/ext4-verify-fast-symlink-length.patch b/queue-6.14/ext4-verify-fast-symlink-length.patch new file mode 100644 index 0000000000..697d2090a1 --- /dev/null +++ b/queue-6.14/ext4-verify-fast-symlink-length.patch @@ -0,0 +1,52 @@ +From 4fa22c1b541e019fb28acad46dae6ecfb4932523 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 10:44:55 +0100 +Subject: ext4: verify fast symlink length + +From: Jan Kara + +[ Upstream commit 5f920d5d60839f7cbbb1ed50eac68d8bc0a73a7c ] + +Verify fast symlink length stored in inode->i_size matches the string +stored in the inode to avoid surprises from corrupted filesystems. + +Reported-by: syzbot+48a99e426f29859818c0@syzkaller.appspotmail.com +Tested-by: syzbot+48a99e426f29859818c0@syzkaller.appspotmail.com +Fixes: bae80473f7b0 ("ext4: use inode_set_cached_link()") +Suggested-by: Darrick J. Wong +Signed-off-by: Jan Kara +Reviewed-by: Baokun Li +Reviewed-by: Darrick J. Wong +Link: https://patch.msgid.link/20250206094454.20522-2-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/inode.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 7c54ae5fcbd45..64e280fed9119 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -5007,8 +5007,16 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, + inode->i_op = &ext4_encrypted_symlink_inode_operations; + } else if (ext4_inode_is_fast_symlink(inode)) { + inode->i_op = &ext4_fast_symlink_inode_operations; +- nd_terminate_link(ei->i_data, inode->i_size, +- sizeof(ei->i_data) - 1); ++ if (inode->i_size == 0 || ++ inode->i_size >= sizeof(ei->i_data) || ++ strnlen((char *)ei->i_data, inode->i_size + 1) != ++ inode->i_size) { ++ ext4_error_inode(inode, function, line, 0, ++ "invalid fast symlink length %llu", ++ (unsigned long long)inode->i_size); ++ ret = -EFSCORRUPTED; ++ goto bad_inode; ++ } + inode_set_cached_link(inode, (char *)ei->i_data, + inode->i_size); + } else { +-- +2.39.5 + diff --git a/queue-6.14/f2fs-add-check-for-deleted-inode.patch b/queue-6.14/f2fs-add-check-for-deleted-inode.patch new file mode 100644 index 0000000000..28cc23f1b8 --- /dev/null +++ b/queue-6.14/f2fs-add-check-for-deleted-inode.patch @@ -0,0 +1,49 @@ +From 37b0a5cc380da6b81b1eb53611824e96f094b5fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 23:54:20 +0800 +Subject: f2fs: add check for deleted inode + +From: Leo Stone + +[ Upstream commit 81edb983b3f5d6900d3e337b9af7b1bec4bef0f2 ] + +The syzbot reproducer mounts a f2fs image, then tries to unlink an +existing file. However, the unlinked file already has a link count of 0 +when it is read for the first time in do_read_inode(). + +Add a check to sanity_check_inode() for i_nlink == 0. + +[Chao Yu: rebase the code and fix orphan inode recovery issue] +Reported-by: syzbot+b01a36acd7007e273a83@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=b01a36acd7007e273a83 +Fixes: 39a53e0ce0df ("f2fs: add superblock and major in-memory structure") +Signed-off-by: Leo Stone +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/namei.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c +index a278c7da81778..3d85d8116dae7 100644 +--- a/fs/f2fs/namei.c ++++ b/fs/f2fs/namei.c +@@ -502,6 +502,14 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry, + goto out; + } + ++ if (inode->i_nlink == 0) { ++ f2fs_warn(F2FS_I_SB(inode), "%s: inode (ino=%lx) has zero i_nlink", ++ __func__, inode->i_ino); ++ err = -EFSCORRUPTED; ++ set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK); ++ goto out_iput; ++ } ++ + if (IS_ENCRYPTED(dir) && + (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) && + !fscrypt_has_permitted_context(dir, inode)) { +-- +2.39.5 + diff --git a/queue-6.14/f2fs-fix-missing-discard-for-active-segments.patch b/queue-6.14/f2fs-fix-missing-discard-for-active-segments.patch new file mode 100644 index 0000000000..dd5de328c6 --- /dev/null +++ b/queue-6.14/f2fs-fix-missing-discard-for-active-segments.patch @@ -0,0 +1,85 @@ +From 7149db20149d056f93d295655ba0ce0ee30ea94c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 04:16:24 -0600 +Subject: f2fs: fix missing discard for active segments + +From: Chunhai Guo + +[ Upstream commit 21263d035ff21fa0ccf79adba20bab9cd8cca0f2 ] + +During a checkpoint, the current active segment X may not be handled +properly. This occurs when segment X has 0 valid blocks and a non-zero +number of discard blocks, for the following reasons: + +locate_dirty_segment() does not mark any active segment as a prefree +segment. As a result, segment X is not included in dirty_segmap[PRE], and +f2fs_clear_prefree_segments() skips it when handling prefree segments. + +add_discard_addrs() skips any segment with 0 valid blocks, so segment X is +also skipped. + +Consequently, no `struct discard_cmd` is actually created for segment X. +However, the ckpt_valid_map and cur_valid_map of segment X are synced by +seg_info_to_raw_sit() during the current checkpoint process. As a result, +it cannot find the missing discard bits even in subsequent checkpoints. +Consequently, the value of sbi->discard_blks remains non-zero. Thus, when +f2fs is umounted, CP_TRIMMED_FLAG will not be set due to the non-zero +sbi->discard_blks. + +Relevant code process: + +f2fs_write_checkpoint() + f2fs_flush_sit_entries() + list_for_each_entry_safe(ses, tmp, head, set_list) { + for_each_set_bit_from(segno, bitmap, end) { + ... + add_discard_addrs(sbi, cpc, false); // skip segment X due to its 0 valid blocks + ... + seg_info_to_raw_sit(); // sync ckpt_valid_map with cur_valid_map for segment X + ... + } + } + f2fs_clear_prefree_segments(); // segment X is not included in dirty_segmap[PRE] and is skipped + +This issue is easy to reproduce with the following operations: + +root # mkfs.f2fs -f /dev/f2fs_dev +root # mount -t f2fs /dev/f2fs_dev /mnt_point +root # dd if=/dev/blk_dev of=/mnt_point/1.bin bs=4k count=256 +root # sync +root # rm /mnt_point/1.bin +root # umount /mnt_point +root # dump.f2fs /dev/f2fs_dev | grep "checkpoint state" +Info: checkpoint state = 45 : crc compacted_summary unmount ---- 'trimmed' flag is missing + +Since add_discard_addrs() can handle active segments with non-zero valid +blocks, it is reasonable to fix this issue by allowing it to also handle +active segments with 0 valid blocks. + +Fixes: b29555505d81 ("f2fs: add key functions for small discards") +Signed-off-by: Chunhai Guo +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/segment.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index 2b415926641f0..384bca002ec9a 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -2096,7 +2096,9 @@ static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc, + return false; + + if (!force) { +- if (!f2fs_realtime_discard_enable(sbi) || !se->valid_blocks || ++ if (!f2fs_realtime_discard_enable(sbi) || ++ (!se->valid_blocks && ++ !IS_CURSEG(sbi, cpc->trim_start)) || + SM_I(sbi)->dcc_info->nr_discards >= + SM_I(sbi)->dcc_info->max_discards) + return false; +-- +2.39.5 + diff --git a/queue-6.14/f2fs-fix-potential-deadloop-in-prepare_compress_over.patch b/queue-6.14/f2fs-fix-potential-deadloop-in-prepare_compress_over.patch new file mode 100644 index 0000000000..06b308cdeb --- /dev/null +++ b/queue-6.14/f2fs-fix-potential-deadloop-in-prepare_compress_over.patch @@ -0,0 +1,107 @@ +From 4adf850a3f52f1b29810f60192cb33653c7c53d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 11:23:29 +0800 +Subject: f2fs: fix potential deadloop in prepare_compress_overwrite() + +From: Chao Yu + +[ Upstream commit 3147ee567dd9004a49826ddeaf0a4b12865d4409 ] + +Jan Prusakowski reported a kernel hang issue as below: + +When running xfstests on linux-next kernel (6.14.0-rc3, 6.12) I +encountered a problem in generic/475 test where fsstress process +gets blocked in __f2fs_write_data_pages() and the test hangs. +The options I used are: + +MKFS_OPTIONS -- -O compression -O extra_attr -O project_quota -O quota /dev/vdc +MOUNT_OPTIONS -- -o acl,user_xattr -o discard,compress_extension=* /dev/vdc /vdc + +INFO: task kworker/u8:0:11 blocked for more than 122 seconds. + Not tainted 6.14.0-rc3-xfstests-lockdep #1 +"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +task:kworker/u8:0 state:D stack:0 pid:11 tgid:11 ppid:2 task_flags:0x4208160 flags:0x00004000 +Workqueue: writeback wb_workfn (flush-253:0) +Call Trace: + + __schedule+0x309/0x8e0 + schedule+0x3a/0x100 + schedule_preempt_disabled+0x15/0x30 + __mutex_lock+0x59a/0xdb0 + __f2fs_write_data_pages+0x3ac/0x400 + do_writepages+0xe8/0x290 + __writeback_single_inode+0x5c/0x360 + writeback_sb_inodes+0x22f/0x570 + wb_writeback+0xb0/0x410 + wb_do_writeback+0x47/0x2f0 + wb_workfn+0x5a/0x1c0 + process_one_work+0x223/0x5b0 + worker_thread+0x1d5/0x3c0 + kthread+0xfd/0x230 + ret_from_fork+0x31/0x50 + ret_from_fork_asm+0x1a/0x30 + + +The root cause is: once generic/475 starts toload error table to dm +device, f2fs_prepare_compress_overwrite() will loop reading compressed +cluster pages due to IO error, meanwhile it has held .writepages lock, +it can block all other writeback tasks. + +Let's fix this issue w/ below changes: +- add f2fs_handle_page_eio() in prepare_compress_overwrite() to +detect IO error. +- detect cp_error earler in f2fs_read_multi_pages(). + +Fixes: 4c8ff7095bef ("f2fs: support data compression") +Reported-by: Jan Prusakowski +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/compress.c | 1 + + fs/f2fs/data.c | 10 ++++++---- + 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c +index 985690d81a82c..9b94810675c19 100644 +--- a/fs/f2fs/compress.c ++++ b/fs/f2fs/compress.c +@@ -1150,6 +1150,7 @@ static int prepare_compress_overwrite(struct compress_ctx *cc, + f2fs_compress_ctx_add_page(cc, page_folio(page)); + + if (!PageUptodate(page)) { ++ f2fs_handle_page_eio(sbi, page_folio(page), DATA); + release_and_retry: + f2fs_put_rpages(cc); + f2fs_unlock_rpages(cc, i + 1); +diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c +index de4da6d9cd93a..8440a1ed24f23 100644 +--- a/fs/f2fs/data.c ++++ b/fs/f2fs/data.c +@@ -2178,6 +2178,12 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret, + int i; + int ret = 0; + ++ if (unlikely(f2fs_cp_error(sbi))) { ++ ret = -EIO; ++ from_dnode = false; ++ goto out_put_dnode; ++ } ++ + f2fs_bug_on(sbi, f2fs_cluster_is_empty(cc)); + + last_block_in_file = F2FS_BYTES_TO_BLK(f2fs_readpage_limit(inode) + +@@ -2221,10 +2227,6 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret, + if (ret) + goto out; + +- if (unlikely(f2fs_cp_error(sbi))) { +- ret = -EIO; +- goto out_put_dnode; +- } + f2fs_bug_on(sbi, dn.data_blkaddr != COMPRESS_ADDR); + + skip_reading_dnode: +-- +2.39.5 + diff --git a/queue-6.14/f2fs-fix-to-avoid-accessing-uninitialized-curseg.patch b/queue-6.14/f2fs-fix-to-avoid-accessing-uninitialized-curseg.patch new file mode 100644 index 0000000000..c3515d706e --- /dev/null +++ b/queue-6.14/f2fs-fix-to-avoid-accessing-uninitialized-curseg.patch @@ -0,0 +1,121 @@ +From 429f22515d290f68286cb49c8b080dd8c1177746 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 18:29:23 +0800 +Subject: f2fs: fix to avoid accessing uninitialized curseg + +From: Chao Yu + +[ Upstream commit 986c50f6bca109c6cf362b4e2babcb85aba958f6 ] + +syzbot reports a f2fs bug as below: + +F2FS-fs (loop3): Stopped filesystem due to reason: 7 +kworker/u8:7: attempt to access beyond end of device +BUG: unable to handle page fault for address: ffffed1604ea3dfa +RIP: 0010:get_ckpt_valid_blocks fs/f2fs/segment.h:361 [inline] +RIP: 0010:has_curseg_enough_space fs/f2fs/segment.h:570 [inline] +RIP: 0010:__get_secs_required fs/f2fs/segment.h:620 [inline] +RIP: 0010:has_not_enough_free_secs fs/f2fs/segment.h:633 [inline] +RIP: 0010:has_enough_free_secs+0x575/0x1660 fs/f2fs/segment.h:649 + + f2fs_is_checkpoint_ready fs/f2fs/segment.h:671 [inline] + f2fs_write_inode+0x425/0x540 fs/f2fs/inode.c:791 + write_inode fs/fs-writeback.c:1525 [inline] + __writeback_single_inode+0x708/0x10d0 fs/fs-writeback.c:1745 + writeback_sb_inodes+0x820/0x1360 fs/fs-writeback.c:1976 + wb_writeback+0x413/0xb80 fs/fs-writeback.c:2156 + wb_do_writeback fs/fs-writeback.c:2303 [inline] + wb_workfn+0x410/0x1080 fs/fs-writeback.c:2343 + process_one_work kernel/workqueue.c:3236 [inline] + process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3317 + worker_thread+0x870/0xd30 kernel/workqueue.c:3398 + kthread+0x7a9/0x920 kernel/kthread.c:464 + ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:148 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 + +Commit 8b10d3653735 ("f2fs: introduce FAULT_NO_SEGMENT") allows to trigger +no free segment fault in allocator, then it will update curseg->segno to +NULL_SEGNO, though, CP_ERROR_FLAG has been set, f2fs_write_inode() missed +to check the flag, and access invalid curseg->segno directly in below call +path, then resulting in panic: + +- f2fs_write_inode + - f2fs_is_checkpoint_ready + - has_enough_free_secs + - has_not_enough_free_secs + - __get_secs_required + - has_curseg_enough_space + - get_ckpt_valid_blocks + : access invalid curseg->segno + +To avoid this issue, let's: +- check CP_ERROR_FLAG flag in prior to f2fs_is_checkpoint_ready() in +f2fs_write_inode(). +- in has_curseg_enough_space(), save curseg->segno into a temp variable, +and verify its validation before use. + +Fixes: 8b10d3653735 ("f2fs: introduce FAULT_NO_SEGMENT") +Reported-by: syzbot+b6b347b7a4ea1b2e29b6@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/67973c2b.050a0220.11b1bb.0089.GAE@google.com +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/inode.c | 7 +++++++ + fs/f2fs/segment.h | 9 ++++++++- + 2 files changed, 15 insertions(+), 1 deletion(-) + +diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c +index 3dd25f64d6f1e..cd17d6f4c291f 100644 +--- a/fs/f2fs/inode.c ++++ b/fs/f2fs/inode.c +@@ -789,6 +789,13 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) + !is_inode_flag_set(inode, FI_DIRTY_INODE)) + return 0; + ++ /* ++ * no need to update inode page, ultimately f2fs_evict_inode() will ++ * clear dirty status of inode. ++ */ ++ if (f2fs_cp_error(sbi)) ++ return -EIO; ++ + if (!f2fs_is_checkpoint_ready(sbi)) { + f2fs_mark_inode_dirty_sync(inode, true); + return -ENOSPC; +diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h +index 943be4f1d6d2d..0465dc00b349d 100644 +--- a/fs/f2fs/segment.h ++++ b/fs/f2fs/segment.h +@@ -559,13 +559,16 @@ static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi, + unsigned int node_blocks, unsigned int data_blocks, + unsigned int dent_blocks) + { +- + unsigned int segno, left_blocks, blocks; + int i; + + /* check current data/node sections in the worst case. */ + for (i = CURSEG_HOT_DATA; i < NR_PERSISTENT_LOG; i++) { + segno = CURSEG_I(sbi, i)->segno; ++ ++ if (unlikely(segno == NULL_SEGNO)) ++ return false; ++ + left_blocks = CAP_BLKS_PER_SEC(sbi) - + get_ckpt_valid_blocks(sbi, segno, true); + +@@ -576,6 +579,10 @@ static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi, + + /* check current data section for dentry blocks. */ + segno = CURSEG_I(sbi, CURSEG_HOT_DATA)->segno; ++ ++ if (unlikely(segno == NULL_SEGNO)) ++ return false; ++ + left_blocks = CAP_BLKS_PER_SEC(sbi) - + get_ckpt_valid_blocks(sbi, segno, true); + if (dent_blocks > left_blocks) +-- +2.39.5 + diff --git a/queue-6.14/f2fs-fix-to-avoid-panic-once-fallocation-fails-for-p.patch b/queue-6.14/f2fs-fix-to-avoid-panic-once-fallocation-fails-for-p.patch new file mode 100644 index 0000000000..4e64e132d7 --- /dev/null +++ b/queue-6.14/f2fs-fix-to-avoid-panic-once-fallocation-fails-for-p.patch @@ -0,0 +1,143 @@ +From 19bd25f40497a1da6e392a84695dded151dc2949 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 14:36:57 +0800 +Subject: f2fs: fix to avoid panic once fallocation fails for pinfile + +From: Chao Yu + +[ Upstream commit 48ea8b200414ac69ea96f4c231f5c7ef1fbeffef ] + +syzbot reports a f2fs bug as below: + +------------[ cut here ]------------ +kernel BUG at fs/f2fs/segment.c:2746! +CPU: 0 UID: 0 PID: 5323 Comm: syz.0.0 Not tainted 6.13.0-rc2-syzkaller-00018-g7cb1b4663150 #0 +RIP: 0010:get_new_segment fs/f2fs/segment.c:2746 [inline] +RIP: 0010:new_curseg+0x1f52/0x1f70 fs/f2fs/segment.c:2876 +Call Trace: + + __allocate_new_segment+0x1ce/0x940 fs/f2fs/segment.c:3210 + f2fs_allocate_new_section fs/f2fs/segment.c:3224 [inline] + f2fs_allocate_pinning_section+0xfa/0x4e0 fs/f2fs/segment.c:3238 + f2fs_expand_inode_data+0x696/0xca0 fs/f2fs/file.c:1830 + f2fs_fallocate+0x537/0xa10 fs/f2fs/file.c:1940 + vfs_fallocate+0x569/0x6e0 fs/open.c:327 + do_vfs_ioctl+0x258c/0x2e40 fs/ioctl.c:885 + __do_sys_ioctl fs/ioctl.c:904 [inline] + __se_sys_ioctl+0x80/0x170 fs/ioctl.c:892 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Concurrent pinfile allocation may run out of free section, result in +panic in get_new_segment(), let's expand pin_sem lock coverage to +include f2fs_gc(), so that we can make sure to reclaim enough free +space for following allocation. + +In addition, do below changes to enhance error path handling: +- call f2fs_bug_on() only in non-pinfile allocation path in +get_new_segment(). +- call reset_curseg_fields() to reset all fields of curseg in +new_curseg() + +Fixes: f5a53edcf01e ("f2fs: support aligned pinned file") +Reported-by: syzbot+15669ec8c35ddf6c3d43@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/linux-f2fs-devel/675cd64e.050a0220.37aaf.00bb.GAE@google.com +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/file.c | 8 +++++--- + fs/f2fs/segment.c | 20 ++++++++++---------- + 2 files changed, 15 insertions(+), 13 deletions(-) + +diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c +index f92a9fba9991b..1bb70499ab598 100644 +--- a/fs/f2fs/file.c ++++ b/fs/f2fs/file.c +@@ -1834,18 +1834,20 @@ static int f2fs_expand_inode_data(struct inode *inode, loff_t offset, + + map.m_len = sec_blks; + next_alloc: ++ f2fs_down_write(&sbi->pin_sem); ++ + if (has_not_enough_free_secs(sbi, 0, f2fs_sb_has_blkzoned(sbi) ? + ZONED_PIN_SEC_REQUIRED_COUNT : + GET_SEC_FROM_SEG(sbi, overprovision_segments(sbi)))) { + f2fs_down_write(&sbi->gc_lock); + stat_inc_gc_call_count(sbi, FOREGROUND); + err = f2fs_gc(sbi, &gc_control); +- if (err && err != -ENODATA) ++ if (err && err != -ENODATA) { ++ f2fs_up_write(&sbi->pin_sem); + goto out_err; ++ } + } + +- f2fs_down_write(&sbi->pin_sem); +- + err = f2fs_allocate_pinning_section(sbi); + if (err) { + f2fs_up_write(&sbi->pin_sem); +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index c282e8a0a2ec1..6ebe25eafafa5 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -2806,7 +2806,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi, + MAIN_SECS(sbi)); + if (secno >= MAIN_SECS(sbi)) { + ret = -ENOSPC; +- f2fs_bug_on(sbi, 1); ++ f2fs_bug_on(sbi, !pinning); + goto out_unlock; + } + } +@@ -2848,7 +2848,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi, + out_unlock: + spin_unlock(&free_i->segmap_lock); + +- if (ret == -ENOSPC) ++ if (ret == -ENOSPC && !pinning) + f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_NO_SEGMENT); + return ret; + } +@@ -2921,6 +2921,13 @@ static unsigned int __get_next_segno(struct f2fs_sb_info *sbi, int type) + return curseg->segno; + } + ++static void reset_curseg_fields(struct curseg_info *curseg) ++{ ++ curseg->inited = false; ++ curseg->segno = NULL_SEGNO; ++ curseg->next_segno = 0; ++} ++ + /* + * Allocate a current working segment. + * This function always allocates a free segment in LFS manner. +@@ -2939,7 +2946,7 @@ static int new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec) + ret = get_new_segment(sbi, &segno, new_sec, pinning); + if (ret) { + if (ret == -ENOSPC) +- curseg->segno = NULL_SEGNO; ++ reset_curseg_fields(curseg); + return ret; + } + +@@ -3710,13 +3717,6 @@ static void f2fs_randomize_chunk(struct f2fs_sb_info *sbi, + get_random_u32_inclusive(1, sbi->max_fragment_hole); + } + +-static void reset_curseg_fields(struct curseg_info *curseg) +-{ +- curseg->inited = false; +- curseg->segno = NULL_SEGNO; +- curseg->next_segno = 0; +-} +- + int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, + block_t old_blkaddr, block_t *new_blkaddr, + struct f2fs_summary *sum, int type, +-- +2.39.5 + diff --git a/queue-6.14/f2fs-fix-to-avoid-running-out-of-free-segments.patch b/queue-6.14/f2fs-fix-to-avoid-running-out-of-free-segments.patch new file mode 100644 index 0000000000..7b619af96d --- /dev/null +++ b/queue-6.14/f2fs-fix-to-avoid-running-out-of-free-segments.patch @@ -0,0 +1,63 @@ +From 629a19dd61c5085f59fedd02978760b3208cfa91 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 17:01:25 +0800 +Subject: f2fs: fix to avoid running out of free segments + +From: Chao Yu + +[ Upstream commit f7f8932ca6bb22494ef6db671633ad3b4d982271 ] + +If checkpoint is disabled, GC can not reclaim any segments, we need +to detect such condition and bail out from fallocate() of a pinfile, +rather than letting allocator running out of free segment, which may +cause f2fs to be shutdown. + +reproducer: +mkfs.f2fs -f /dev/vda 16777216 +mount -o checkpoint=disable:10% /dev/vda /mnt/f2fs +for ((i=0;i<4096;i++)) do { dd if=/dev/zero of=/mnt/f2fs/$i bs=1M count=1; } done +sync +for ((i=0;i<4096;i+=2)) do { rm /mnt/f2fs/$i; } done +sync +touch /mnt/f2fs/pinfile +f2fs_io pinfile set /mnt/f2fs/pinfile +f2fs_io fallocate 0 0 4201644032 /mnt/f2fs/pinfile + +cat /sys/kernel/debug/f2fs/status +output: + - Free: 0 (0) + +Fixes: f5a53edcf01e ("f2fs: support aligned pinned file") +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/file.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c +index 1bb70499ab598..44a658662462d 100644 +--- a/fs/f2fs/file.c ++++ b/fs/f2fs/file.c +@@ -1836,6 +1836,18 @@ static int f2fs_expand_inode_data(struct inode *inode, loff_t offset, + next_alloc: + f2fs_down_write(&sbi->pin_sem); + ++ if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { ++ if (has_not_enough_free_secs(sbi, 0, 0)) { ++ f2fs_up_write(&sbi->pin_sem); ++ err = -ENOSPC; ++ f2fs_warn_ratelimited(sbi, ++ "ino:%lu, start:%lu, end:%lu, need to trigger GC to " ++ "reclaim enough free segment when checkpoint is enabled", ++ inode->i_ino, pg_start, pg_end); ++ goto out_err; ++ } ++ } ++ + if (has_not_enough_free_secs(sbi, 0, f2fs_sb_has_blkzoned(sbi) ? + ZONED_PIN_SEC_REQUIRED_COUNT : + GET_SEC_FROM_SEG(sbi, overprovision_segments(sbi)))) { +-- +2.39.5 + diff --git a/queue-6.14/f2fs-fix-to-call-f2fs_recover_quota_end-correctly.patch b/queue-6.14/f2fs-fix-to-call-f2fs_recover_quota_end-correctly.patch new file mode 100644 index 0000000000..318858148f --- /dev/null +++ b/queue-6.14/f2fs-fix-to-call-f2fs_recover_quota_end-correctly.patch @@ -0,0 +1,40 @@ +From 077e9591077e9c1c9f7373aff11075597a422209 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 11:25:00 +0800 +Subject: f2fs: fix to call f2fs_recover_quota_end() correctly + +From: Chao Yu + +[ Upstream commit d8f5b91d77a651705d3f76ba0ebd5d7981533333 ] + +f2fs_recover_quota_begin() and f2fs_recover_quota_end() should be called +in pair, there is some cases we may skip calling f2fs_recover_quota_end(), +fix it. + +Fixes: e1bb7d3d9cbf ("f2fs: fix to recover quota data correctly") +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/super.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 1beff52ae80b3..26b1021427ae0 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -4800,10 +4800,10 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) + } + } + ++reset_checkpoint: + #ifdef CONFIG_QUOTA + f2fs_recover_quota_end(sbi, quota_enabled); + #endif +-reset_checkpoint: + /* + * If the f2fs is not readonly and fsync data recovery succeeds, + * write pointer consistency of cursegs and other zones are already +-- +2.39.5 + diff --git a/queue-6.14/f2fs-fix-to-set-.discard_granularity-correctly.patch b/queue-6.14/f2fs-fix-to-set-.discard_granularity-correctly.patch new file mode 100644 index 0000000000..b2fe55f3f9 --- /dev/null +++ b/queue-6.14/f2fs-fix-to-set-.discard_granularity-correctly.patch @@ -0,0 +1,46 @@ +From 7c9b5e269fa0d03c0e62b4f3638fb2157027ef01 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 14:20:07 +0800 +Subject: f2fs: fix to set .discard_granularity correctly + +From: Chao Yu + +[ Upstream commit 1b60b23975d6d81703826e3797738e471c3009c6 ] + +commit 4f993264fe29 ("f2fs: introduce discard_unit mount option") introduced +a bug, when we enable discard_unit=section option, it will set +.discard_granularity to BLKS_PER_SEC(), however discard granularity only +supports [1, 512], once section size is not equal to segment size, it will +cause issue_discard_thread() in DPOLICY_BG mode will not select discard entry +w/ any granularity to issue. + +Fixes: 4f993264fe29 ("f2fs: introduce discard_unit mount option") +Reviewed-by: Daeho Jeong +Signed-off-by: Yohan Joung +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/segment.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index 6ebe25eafafa5..2b415926641f0 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -2320,10 +2320,9 @@ static int create_discard_cmd_control(struct f2fs_sb_info *sbi) + dcc->discard_granularity = DEFAULT_DISCARD_GRANULARITY; + dcc->max_ordered_discard = DEFAULT_MAX_ORDERED_DISCARD_GRANULARITY; + dcc->discard_io_aware = DPOLICY_IO_AWARE_ENABLE; +- if (F2FS_OPTION(sbi).discard_unit == DISCARD_UNIT_SEGMENT) ++ if (F2FS_OPTION(sbi).discard_unit == DISCARD_UNIT_SEGMENT || ++ F2FS_OPTION(sbi).discard_unit == DISCARD_UNIT_SECTION) + dcc->discard_granularity = BLKS_PER_SEG(sbi); +- else if (F2FS_OPTION(sbi).discard_unit == DISCARD_UNIT_SECTION) +- dcc->discard_granularity = BLKS_PER_SEC(sbi); + + INIT_LIST_HEAD(&dcc->entry_list); + for (i = 0; i < MAX_PLIST_NUM; i++) +-- +2.39.5 + diff --git a/queue-6.14/f2fs-quota-fix-to-avoid-warning-in-dquot_writeback_d.patch b/queue-6.14/f2fs-quota-fix-to-avoid-warning-in-dquot_writeback_d.patch new file mode 100644 index 0000000000..f04c76395f --- /dev/null +++ b/queue-6.14/f2fs-quota-fix-to-avoid-warning-in-dquot_writeback_d.patch @@ -0,0 +1,335 @@ +From 5b80e8732f7280ffa5ab74857f686c2692e38128 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Feb 2025 10:33:21 +0800 +Subject: f2fs: quota: fix to avoid warning in dquot_writeback_dquots() + +From: Chao Yu + +[ Upstream commit eb85c2410d6f581e957cd03a644ff6ddbe592af9 ] + +F2FS-fs (dm-59): checkpoint=enable has some unwritten data. + +------------[ cut here ]------------ +WARNING: CPU: 6 PID: 8013 at fs/quota/dquot.c:691 dquot_writeback_dquots+0x2fc/0x308 +pc : dquot_writeback_dquots+0x2fc/0x308 +lr : f2fs_quota_sync+0xcc/0x1c4 +Call trace: +dquot_writeback_dquots+0x2fc/0x308 +f2fs_quota_sync+0xcc/0x1c4 +f2fs_write_checkpoint+0x3d4/0x9b0 +f2fs_issue_checkpoint+0x1bc/0x2c0 +f2fs_sync_fs+0x54/0x150 +f2fs_do_sync_file+0x2f8/0x814 +__f2fs_ioctl+0x1960/0x3244 +f2fs_ioctl+0x54/0xe0 +__arm64_sys_ioctl+0xa8/0xe4 +invoke_syscall+0x58/0x114 + +checkpoint and f2fs_remount may race as below, resulting triggering warning +in dquot_writeback_dquots(). + +atomic write remount + - do_remount + - down_write(&sb->s_umount); + - f2fs_remount +- ioctl + - f2fs_do_sync_file + - f2fs_sync_fs + - f2fs_write_checkpoint + - block_operations + - locked = down_read_trylock(&sbi->sb->s_umount) + : fail to lock due to the write lock was held by remount + - up_write(&sb->s_umount); + - f2fs_quota_sync + - dquot_writeback_dquots + - WARN_ON_ONCE(!rwsem_is_locked(&sb->s_umount)) + : trigger warning because s_umount lock was unlocked by remount + +If checkpoint comes from mount/umount/remount/freeze/quotactl, caller of +checkpoint has already held s_umount lock, calling dquot_writeback_dquots() +in the context should be safe. + +So let's record task to sbi->umount_lock_holder, so that checkpoint can +know whether the lock has held in the context or not by checking current +w/ it. + +In addition, in order to not misrepresent caller of checkpoint, we should +not allow to trigger async checkpoint for those callers: mount/umount/remount/ +freeze/quotactl. + +Fixes: af033b2aa8a8 ("f2fs: guarantee journalled quota data by checkpoint") +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/checkpoint.c | 15 ++++++---- + fs/f2fs/f2fs.h | 3 +- + fs/f2fs/super.c | 65 ++++++++++++++++++++++++++++++++++---------- + 3 files changed, 61 insertions(+), 22 deletions(-) + +diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c +index efda9a0229816..bd890738b94d7 100644 +--- a/fs/f2fs/checkpoint.c ++++ b/fs/f2fs/checkpoint.c +@@ -1237,7 +1237,7 @@ static int block_operations(struct f2fs_sb_info *sbi) + retry_flush_quotas: + f2fs_lock_all(sbi); + if (__need_flush_quota(sbi)) { +- int locked; ++ bool need_lock = sbi->umount_lock_holder != current; + + if (++cnt > DEFAULT_RETRY_QUOTA_FLUSH_COUNT) { + set_sbi_flag(sbi, SBI_QUOTA_SKIP_FLUSH); +@@ -1246,11 +1246,13 @@ static int block_operations(struct f2fs_sb_info *sbi) + } + f2fs_unlock_all(sbi); + +- /* only failed during mount/umount/freeze/quotactl */ +- locked = down_read_trylock(&sbi->sb->s_umount); +- f2fs_quota_sync(sbi->sb, -1); +- if (locked) ++ /* don't grab s_umount lock during mount/umount/remount/freeze/quotactl */ ++ if (!need_lock) { ++ f2fs_do_quota_sync(sbi->sb, -1); ++ } else if (down_read_trylock(&sbi->sb->s_umount)) { ++ f2fs_do_quota_sync(sbi->sb, -1); + up_read(&sbi->sb->s_umount); ++ } + cond_resched(); + goto retry_flush_quotas; + } +@@ -1867,7 +1869,8 @@ int f2fs_issue_checkpoint(struct f2fs_sb_info *sbi) + struct cp_control cpc; + + cpc.reason = __get_cp_reason(sbi); +- if (!test_opt(sbi, MERGE_CHECKPOINT) || cpc.reason != CP_SYNC) { ++ if (!test_opt(sbi, MERGE_CHECKPOINT) || cpc.reason != CP_SYNC || ++ sbi->umount_lock_holder == current) { + int ret; + + f2fs_down_write(&sbi->gc_lock); +diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h +index 1afa7be16e7da..493dda2d4b663 100644 +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -1659,6 +1659,7 @@ struct f2fs_sb_info { + + unsigned int nquota_files; /* # of quota sysfile */ + struct f2fs_rwsem quota_sem; /* blocking cp for flags */ ++ struct task_struct *umount_lock_holder; /* s_umount lock holder */ + + /* # of pages, see count_type */ + atomic_t nr_pages[NR_COUNT_TYPE]; +@@ -3624,7 +3625,7 @@ int f2fs_inode_dirtied(struct inode *inode, bool sync); + void f2fs_inode_synced(struct inode *inode); + int f2fs_dquot_initialize(struct inode *inode); + int f2fs_enable_quota_files(struct f2fs_sb_info *sbi, bool rdonly); +-int f2fs_quota_sync(struct super_block *sb, int type); ++int f2fs_do_quota_sync(struct super_block *sb, int type); + loff_t max_file_blocks(struct inode *inode); + void f2fs_quota_off_umount(struct super_block *sb); + void f2fs_save_errors(struct f2fs_sb_info *sbi, unsigned char flag); +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 19b67828ae325..1beff52ae80b3 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -1737,22 +1737,28 @@ int f2fs_sync_fs(struct super_block *sb, int sync) + + static int f2fs_freeze(struct super_block *sb) + { ++ struct f2fs_sb_info *sbi = F2FS_SB(sb); ++ + if (f2fs_readonly(sb)) + return 0; + + /* IO error happened before */ +- if (unlikely(f2fs_cp_error(F2FS_SB(sb)))) ++ if (unlikely(f2fs_cp_error(sbi))) + return -EIO; + + /* must be clean, since sync_filesystem() was already called */ +- if (is_sbi_flag_set(F2FS_SB(sb), SBI_IS_DIRTY)) ++ if (is_sbi_flag_set(sbi, SBI_IS_DIRTY)) + return -EINVAL; + ++ sbi->umount_lock_holder = current; ++ + /* Let's flush checkpoints and stop the thread. */ +- f2fs_flush_ckpt_thread(F2FS_SB(sb)); ++ f2fs_flush_ckpt_thread(sbi); ++ ++ sbi->umount_lock_holder = NULL; + + /* to avoid deadlock on f2fs_evict_inode->SB_FREEZE_FS */ +- set_sbi_flag(F2FS_SB(sb), SBI_IS_FREEZING); ++ set_sbi_flag(sbi, SBI_IS_FREEZING); + return 0; + } + +@@ -2329,6 +2335,8 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) + org_mount_opt = sbi->mount_opt; + old_sb_flags = sb->s_flags; + ++ sbi->umount_lock_holder = current; ++ + #ifdef CONFIG_QUOTA + org_mount_opt.s_jquota_fmt = F2FS_OPTION(sbi).s_jquota_fmt; + for (i = 0; i < MAXQUOTAS; i++) { +@@ -2552,6 +2560,8 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) + + limit_reserve_root(sbi); + *flags = (*flags & ~SB_LAZYTIME) | (sb->s_flags & SB_LAZYTIME); ++ ++ sbi->umount_lock_holder = NULL; + return 0; + restore_checkpoint: + if (need_enable_checkpoint) { +@@ -2592,6 +2602,8 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) + #endif + sbi->mount_opt = org_mount_opt; + sb->s_flags = old_sb_flags; ++ ++ sbi->umount_lock_holder = NULL; + return err; + } + +@@ -2908,7 +2920,7 @@ static int f2fs_quota_sync_file(struct f2fs_sb_info *sbi, int type) + return ret; + } + +-int f2fs_quota_sync(struct super_block *sb, int type) ++int f2fs_do_quota_sync(struct super_block *sb, int type) + { + struct f2fs_sb_info *sbi = F2FS_SB(sb); + struct quota_info *dqopt = sb_dqopt(sb); +@@ -2956,11 +2968,21 @@ int f2fs_quota_sync(struct super_block *sb, int type) + return ret; + } + ++static int f2fs_quota_sync(struct super_block *sb, int type) ++{ ++ int ret; ++ ++ F2FS_SB(sb)->umount_lock_holder = current; ++ ret = f2fs_do_quota_sync(sb, type); ++ F2FS_SB(sb)->umount_lock_holder = NULL; ++ return ret; ++} ++ + static int f2fs_quota_on(struct super_block *sb, int type, int format_id, + const struct path *path) + { + struct inode *inode; +- int err; ++ int err = 0; + + /* if quota sysfile exists, deny enabling quota with specific file */ + if (f2fs_sb_has_quota_ino(F2FS_SB(sb))) { +@@ -2971,31 +2993,34 @@ static int f2fs_quota_on(struct super_block *sb, int type, int format_id, + if (path->dentry->d_sb != sb) + return -EXDEV; + +- err = f2fs_quota_sync(sb, type); ++ F2FS_SB(sb)->umount_lock_holder = current; ++ ++ err = f2fs_do_quota_sync(sb, type); + if (err) +- return err; ++ goto out; + + inode = d_inode(path->dentry); + + err = filemap_fdatawrite(inode->i_mapping); + if (err) +- return err; ++ goto out; + + err = filemap_fdatawait(inode->i_mapping); + if (err) +- return err; ++ goto out; + + err = dquot_quota_on(sb, type, format_id, path); + if (err) +- return err; ++ goto out; + + inode_lock(inode); + F2FS_I(inode)->i_flags |= F2FS_QUOTA_DEFAULT_FL; + f2fs_set_inode_flags(inode); + inode_unlock(inode); + f2fs_mark_inode_dirty_sync(inode, false); +- +- return 0; ++out: ++ F2FS_SB(sb)->umount_lock_holder = NULL; ++ return err; + } + + static int __f2fs_quota_off(struct super_block *sb, int type) +@@ -3006,7 +3031,7 @@ static int __f2fs_quota_off(struct super_block *sb, int type) + if (!inode || !igrab(inode)) + return dquot_quota_off(sb, type); + +- err = f2fs_quota_sync(sb, type); ++ err = f2fs_do_quota_sync(sb, type); + if (err) + goto out_put; + +@@ -3029,6 +3054,8 @@ static int f2fs_quota_off(struct super_block *sb, int type) + struct f2fs_sb_info *sbi = F2FS_SB(sb); + int err; + ++ F2FS_SB(sb)->umount_lock_holder = current; ++ + err = __f2fs_quota_off(sb, type); + + /* +@@ -3038,6 +3065,9 @@ static int f2fs_quota_off(struct super_block *sb, int type) + */ + if (is_journalled_quota(sbi)) + set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); ++ ++ F2FS_SB(sb)->umount_lock_holder = NULL; ++ + return err; + } + +@@ -3170,7 +3200,7 @@ int f2fs_dquot_initialize(struct inode *inode) + return 0; + } + +-int f2fs_quota_sync(struct super_block *sb, int type) ++int f2fs_do_quota_sync(struct super_block *sb, int type) + { + return 0; + } +@@ -4703,6 +4733,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) + if (err) + goto free_compress_inode; + ++ sbi->umount_lock_holder = current; + #ifdef CONFIG_QUOTA + /* Enable quota usage during mount */ + if (f2fs_sb_has_quota_ino(sbi) && !f2fs_readonly(sb)) { +@@ -4829,6 +4860,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) + f2fs_update_time(sbi, CP_TIME); + f2fs_update_time(sbi, REQ_TIME); + clear_sbi_flag(sbi, SBI_CP_DISABLED_QUICK); ++ ++ sbi->umount_lock_holder = NULL; + return 0; + + sync_free_meta: +@@ -4931,6 +4964,8 @@ static void kill_f2fs_super(struct super_block *sb) + struct f2fs_sb_info *sbi = F2FS_SB(sb); + + if (sb->s_root) { ++ sbi->umount_lock_holder = current; ++ + set_sbi_flag(sbi, SBI_IS_CLOSE); + f2fs_stop_gc_thread(sbi); + f2fs_stop_discard_thread(sbi); +-- +2.39.5 + diff --git a/queue-6.14/fbdev-au1100fb-move-a-variable-assignment-behind-a-n.patch b/queue-6.14/fbdev-au1100fb-move-a-variable-assignment-behind-a-n.patch new file mode 100644 index 0000000000..79435b3090 --- /dev/null +++ b/queue-6.14/fbdev-au1100fb-move-a-variable-assignment-behind-a-n.patch @@ -0,0 +1,52 @@ +From 68d9da34a2d9d9b443bfbc268011f9bf050dc7c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Apr 2023 21:35:36 +0200 +Subject: fbdev: au1100fb: Move a variable assignment behind a null pointer + check +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Markus Elfring + +[ Upstream commit 2df2c0caaecfd869b49e14f2b8df822397c5dd7f ] + +The address of a data structure member was determined before +a corresponding null pointer check in the implementation of +the function “au1100fb_setmode”. + +This issue was detected by using the Coccinelle software. + +Fixes: 3b495f2bb749 ("Au1100 FB driver uplift for 2.6.") +Signed-off-by: Markus Elfring +Acked-by: Uwe Kleine-König +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + drivers/video/fbdev/au1100fb.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/fbdev/au1100fb.c b/drivers/video/fbdev/au1100fb.c +index 840f221607635..6251a6b07b3a1 100644 +--- a/drivers/video/fbdev/au1100fb.c ++++ b/drivers/video/fbdev/au1100fb.c +@@ -137,13 +137,15 @@ static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi) + */ + int au1100fb_setmode(struct au1100fb_device *fbdev) + { +- struct fb_info *info = &fbdev->info; ++ struct fb_info *info; + u32 words; + int index; + + if (!fbdev) + return -EINVAL; + ++ info = &fbdev->info; ++ + /* Update var-dependent FB info */ + if (panel_is_active(fbdev->panel) || panel_is_color(fbdev->panel)) { + if (info->var.bits_per_pixel <= 8) { +-- +2.39.5 + diff --git a/queue-6.14/fbdev-sm501fb-add-some-geometry-checks.patch b/queue-6.14/fbdev-sm501fb-add-some-geometry-checks.patch new file mode 100644 index 0000000000..dd31ad1d89 --- /dev/null +++ b/queue-6.14/fbdev-sm501fb-add-some-geometry-checks.patch @@ -0,0 +1,44 @@ +From b9e251f45794be17cb98b049652d85d8df231127 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 01:30:11 +0000 +Subject: fbdev: sm501fb: Add some geometry checks. + +From: Danila Chernetsov + +[ Upstream commit aee50bd88ea5fde1ff4cc021385598f81a65830c ] + +Added checks for xoffset, yoffset settings. +Incorrect settings of these parameters can lead to errors +in sm501fb_pan_ functions. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: 5fc404e47bdf ("[PATCH] fb: SM501 framebuffer driver") +Signed-off-by: Danila Chernetsov +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + drivers/video/fbdev/sm501fb.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/video/fbdev/sm501fb.c b/drivers/video/fbdev/sm501fb.c +index 7734377b2d87b..ed6f4f43e2d52 100644 +--- a/drivers/video/fbdev/sm501fb.c ++++ b/drivers/video/fbdev/sm501fb.c +@@ -327,6 +327,13 @@ static int sm501fb_check_var(struct fb_var_screeninfo *var, + if (var->xres_virtual > 4096 || var->yres_virtual > 2048) + return -EINVAL; + ++ /* geometry sanity checks */ ++ if (var->xres + var->xoffset > var->xres_virtual) ++ return -EINVAL; ++ ++ if (var->yres + var->yoffset > var->yres_virtual) ++ return -EINVAL; ++ + /* can cope with 8,16 or 32bpp */ + + if (var->bits_per_pixel <= 8) +-- +2.39.5 + diff --git a/queue-6.14/firmware-arm_ffa-explicitly-cast-return-value-from-f.patch b/queue-6.14/firmware-arm_ffa-explicitly-cast-return-value-from-f.patch new file mode 100644 index 0000000000..f604e4e928 --- /dev/null +++ b/queue-6.14/firmware-arm_ffa-explicitly-cast-return-value-from-f.patch @@ -0,0 +1,46 @@ +From 4e874672303a2a66d44c2843124d08bf39621035 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 09:56:31 +0000 +Subject: firmware: arm_ffa: Explicitly cast return value from FFA_VERSION + before comparison + +From: Sudeep Holla + +[ Upstream commit cecf6a504137aa238d768ae440a1f6488cb2f436 ] + +The return value ver.a0 is unsigned long type and FFA_RET_NOT_SUPPORTED +is a negative value. + +Since the return value from the firmware can be just 32-bit even on +64-bit systems as FFA specification mentions it as int32 error code in +w0 register, explicitly casting to s32 ensures correct sign interpretation +when comparing against a signed error code FFA_RET_NOT_SUPPORTED. + +Without casting, comparison between unsigned long and a negative +constant could lead to unintended results due to type promotions. + +Fixes: 3bbfe9871005 ("firmware: arm_ffa: Add initial Arm FFA driver support") +Reported-by: Andrei Homescu +Message-Id: <20250221095633.506678-1-sudeep.holla@arm.com> +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index 8aa05bbab5c8d..ce1ec015e076b 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -145,7 +145,7 @@ static int ffa_version_check(u32 *version) + .a0 = FFA_VERSION, .a1 = FFA_DRIVER_VERSION, + }, &ver); + +- if (ver.a0 == FFA_RET_NOT_SUPPORTED) { ++ if ((s32)ver.a0 == FFA_RET_NOT_SUPPORTED) { + pr_info("FFA_VERSION returned not supported\n"); + return -EOPNOTSUPP; + } +-- +2.39.5 + diff --git a/queue-6.14/firmware-arm_ffa-explicitly-cast-return-value-from-n.patch b/queue-6.14/firmware-arm_ffa-explicitly-cast-return-value-from-n.patch new file mode 100644 index 0000000000..4620c8e137 --- /dev/null +++ b/queue-6.14/firmware-arm_ffa-explicitly-cast-return-value-from-n.patch @@ -0,0 +1,46 @@ +From a17458e55b2ade0385ccc1827840b8a350dd3dac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 09:56:32 +0000 +Subject: firmware: arm_ffa: Explicitly cast return value from + NOTIFICATION_INFO_GET + +From: Sudeep Holla + +[ Upstream commit 3e282f41585c4dd49b688bd6395fd6f21a57c9f7 ] + +The return value ret.a2 is of type unsigned long and FFA_RET_NO_DATA is +a negative value. + +Since the return value from the firmware can be just 32-bit even on +64-bit systems as FFA specification mentions it as int32 error code in +w0 register, explicitly casting to s32 ensures correct sign interpretation +when comparing against a signed error code FFA_RET_NO_DATA. + +Without casting, comparison between unsigned long and a negative +constant could lead to unintended results due to type promotions. + +Fixes: 3522be48d82b ("firmware: arm_ffa: Implement the NOTIFICATION_INFO_GET interface") +Reported-by: Andrei Homescu +Message-Id: <20250221095633.506678-2-sudeep.holla@arm.com> +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index ce1ec015e076b..25b52acae4662 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -899,7 +899,7 @@ static void ffa_notification_info_get(void) + }, &ret); + + if (ret.a0 != FFA_FN_NATIVE(SUCCESS) && ret.a0 != FFA_SUCCESS) { +- if (ret.a2 != FFA_RET_NO_DATA) ++ if ((s32)ret.a2 != FFA_RET_NO_DATA) + pr_err("Notification Info fetch failed: 0x%lx (0x%lx)", + ret.a0, ret.a2); + return; +-- +2.39.5 + diff --git a/queue-6.14/firmware-arm_ffa-refactor-addition-of-partition-info.patch b/queue-6.14/firmware-arm_ffa-refactor-addition-of-partition-info.patch new file mode 100644 index 0000000000..13114b51e2 --- /dev/null +++ b/queue-6.14/firmware-arm_ffa-refactor-addition-of-partition-info.patch @@ -0,0 +1,103 @@ +From 9e230bbe11f5387cf82f2f2a92dbc982417d4469 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 15:38:47 +0000 +Subject: firmware: arm_ffa: Refactor addition of partition information into + XArray + +From: Viresh Kumar + +[ Upstream commit 3c3d6767466ea316869c9f2bdd976aec8ce44545 ] + +Move the common code handling addition of the FF-A partition information +into the XArray as a new routine. No functional change. + +Signed-off-by: Viresh Kumar +Message-Id: <20250217-ffa_updates-v3-6-bd1d9de615e7@arm.com> +Signed-off-by: Sudeep Holla +Stable-dep-of: 46dcd68aacca ("firmware: arm_ffa: Unregister the FF-A devices when cleaning up the partitions") +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 47 +++++++++++++++---------------- + 1 file changed, 22 insertions(+), 25 deletions(-) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index 2c2ec3c35f156..353900c33eee3 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -1384,11 +1384,30 @@ static struct notifier_block ffa_bus_nb = { + .notifier_call = ffa_bus_notifier, + }; + ++static int ffa_xa_add_partition_info(int vm_id) ++{ ++ struct ffa_dev_part_info *info; ++ int ret; ++ ++ info = kzalloc(sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ rwlock_init(&info->rw_lock); ++ ret = xa_insert(&drv_info->partition_info, vm_id, info, GFP_KERNEL); ++ if (ret) { ++ pr_err("%s: failed to save partition ID 0x%x - ret:%d. Abort.\n", ++ __func__, vm_id, ret); ++ kfree(info); ++ } ++ ++ return ret; ++} ++ + static int ffa_setup_partitions(void) + { + int count, idx, ret; + struct ffa_device *ffa_dev; +- struct ffa_dev_part_info *info; + struct ffa_partition_info *pbuf, *tpbuf; + + if (drv_info->version == FFA_VERSION_1_0) { +@@ -1422,39 +1441,17 @@ static int ffa_setup_partitions(void) + !(tpbuf->properties & FFA_PARTITION_AARCH64_EXEC)) + ffa_mode_32bit_set(ffa_dev); + +- info = kzalloc(sizeof(*info), GFP_KERNEL); +- if (!info) { ++ if (ffa_xa_add_partition_info(ffa_dev->vm_id)) { + ffa_device_unregister(ffa_dev); + continue; + } +- rwlock_init(&info->rw_lock); +- ret = xa_insert(&drv_info->partition_info, tpbuf->id, +- info, GFP_KERNEL); +- if (ret) { +- pr_err("%s: failed to save partition ID 0x%x - ret:%d\n", +- __func__, tpbuf->id, ret); +- ffa_device_unregister(ffa_dev); +- kfree(info); +- } + } + + kfree(pbuf); + + /* Allocate for the host */ +- info = kzalloc(sizeof(*info), GFP_KERNEL); +- if (!info) { +- /* Already registered devices are freed on bus_exit */ +- ffa_partitions_cleanup(); +- return -ENOMEM; +- } +- +- rwlock_init(&info->rw_lock); +- ret = xa_insert(&drv_info->partition_info, drv_info->vm_id, +- info, GFP_KERNEL); ++ ret = ffa_xa_add_partition_info(drv_info->vm_id); + if (ret) { +- pr_err("%s: failed to save Host partition ID 0x%x - ret:%d. Abort.\n", +- __func__, drv_info->vm_id, ret); +- kfree(info); + /* Already registered devices are freed on bus_exit */ + ffa_partitions_cleanup(); + } +-- +2.39.5 + diff --git a/queue-6.14/firmware-arm_ffa-skip-the-first-partition-id-when-pa.patch b/queue-6.14/firmware-arm_ffa-skip-the-first-partition-id-when-pa.patch new file mode 100644 index 0000000000..d6c6738708 --- /dev/null +++ b/queue-6.14/firmware-arm_ffa-skip-the-first-partition-id-when-pa.patch @@ -0,0 +1,42 @@ +From cc35797aae950253d5e40b90aa505b5c9621a495 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 23 Feb 2025 21:39:09 +0000 +Subject: firmware: arm_ffa: Skip the first/partition ID when parsing vCPU list + +From: Sudeep Holla + +[ Upstream commit c67c2332f8c80b03990914dfb66950c8d2fb87d8 ] + +The FF-A notification id list received in response to the call +FFA_NOTIFICATION_INFO_GET is encoded as: partition ID followed by 0 or +more vCPU ID. The count includes all of them. + +Fix the issue by skipping the first/partition ID so that only the list +of vCPU IDs are processed correctly for a given partition ID. The first/ +partition ID is read before the start of the loop. + +Fixes: 3522be48d82b ("firmware: arm_ffa: Implement the NOTIFICATION_INFO_GET interface") +Reported-by: Andrei Homescu +Message-Id: <20250223213909.1197786-1-sudeep.holla@arm.com> +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index 25b52acae4662..655672a880959 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -935,7 +935,7 @@ static void ffa_notification_info_get(void) + } + + /* Per vCPU Notification */ +- for (idx = 0; idx < ids_count[list]; idx++) { ++ for (idx = 1; idx < ids_count[list]; idx++) { + if (ids_processed >= max_ids - 1) + break; + +-- +2.39.5 + diff --git a/queue-6.14/firmware-arm_ffa-unregister-the-ff-a-devices-when-cl.patch b/queue-6.14/firmware-arm_ffa-unregister-the-ff-a-devices-when-cl.patch new file mode 100644 index 0000000000..23ca225b75 --- /dev/null +++ b/queue-6.14/firmware-arm_ffa-unregister-the-ff-a-devices-when-cl.patch @@ -0,0 +1,100 @@ +From 7920b99227df2ef3bff852a28108e0d7c0200b06 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 15:38:49 +0000 +Subject: firmware: arm_ffa: Unregister the FF-A devices when cleaning up the + partitions + +From: Sudeep Holla + +[ Upstream commit 46dcd68aaccac0812c12ec3f4e59c8963e2760ad ] + +Both the FF-A core and the bus were in a single module before the +commit 18c250bd7ed0 ("firmware: arm_ffa: Split bus and driver into distinct modules"). + +The arm_ffa_bus_exit() takes care of unregistering all the FF-A devices. +Now that there are 2 distinct modules, if the core driver is unloaded and +reloaded, it will end up adding duplicate FF-A devices as the previously +registered devices weren't unregistered when we cleaned up the modules. + +Fix the same by unregistering all the FF-A devices on the FF-A bus during +the cleaning up of the partitions and hence the cleanup of the module. + +Fixes: 18c250bd7ed0 ("firmware: arm_ffa: Split bus and driver into distinct modules") +Tested-by: Viresh Kumar +Message-Id: <20250217-ffa_updates-v3-8-bd1d9de615e7@arm.com> +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/bus.c | 3 ++- + drivers/firmware/arm_ffa/driver.c | 7 ++++--- + include/linux/arm_ffa.h | 3 +++ + 3 files changed, 9 insertions(+), 4 deletions(-) + +diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c +index dfda5ffc14db7..fa09a82b44921 100644 +--- a/drivers/firmware/arm_ffa/bus.c ++++ b/drivers/firmware/arm_ffa/bus.c +@@ -160,11 +160,12 @@ static int __ffa_devices_unregister(struct device *dev, void *data) + return 0; + } + +-static void ffa_devices_unregister(void) ++void ffa_devices_unregister(void) + { + bus_for_each_dev(&ffa_bus_type, NULL, NULL, + __ffa_devices_unregister); + } ++EXPORT_SYMBOL_GPL(ffa_devices_unregister); + + bool ffa_device_is_valid(struct ffa_device *ffa_dev) + { +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index 353900c33eee3..8aa05bbab5c8d 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -1451,10 +1451,8 @@ static int ffa_setup_partitions(void) + + /* Allocate for the host */ + ret = ffa_xa_add_partition_info(drv_info->vm_id); +- if (ret) { +- /* Already registered devices are freed on bus_exit */ ++ if (ret) + ffa_partitions_cleanup(); +- } + + return ret; + } +@@ -1464,6 +1462,9 @@ static void ffa_partitions_cleanup(void) + struct ffa_dev_part_info *info; + unsigned long idx; + ++ /* Clean up/free all registered devices */ ++ ffa_devices_unregister(); ++ + xa_for_each(&drv_info->partition_info, idx, info) { + xa_erase(&drv_info->partition_info, idx); + kfree(info); +diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h +index 74169dd0f6594..53f2837ce7df4 100644 +--- a/include/linux/arm_ffa.h ++++ b/include/linux/arm_ffa.h +@@ -176,6 +176,7 @@ void ffa_device_unregister(struct ffa_device *ffa_dev); + int ffa_driver_register(struct ffa_driver *driver, struct module *owner, + const char *mod_name); + void ffa_driver_unregister(struct ffa_driver *driver); ++void ffa_devices_unregister(void); + bool ffa_device_is_valid(struct ffa_device *ffa_dev); + + #else +@@ -188,6 +189,8 @@ ffa_device_register(const struct ffa_partition_info *part_info, + + static inline void ffa_device_unregister(struct ffa_device *dev) {} + ++static inline void ffa_devices_unregister(void) {} ++ + static inline int + ffa_driver_register(struct ffa_driver *driver, struct module *owner, + const char *mod_name) +-- +2.39.5 + diff --git a/queue-6.14/firmware-arm_scmi-use-ioread64-instead-of-ioread64_h.patch b/queue-6.14/firmware-arm_scmi-use-ioread64-instead-of-ioread64_h.patch new file mode 100644 index 0000000000..726bb23aad --- /dev/null +++ b/queue-6.14/firmware-arm_scmi-use-ioread64-instead-of-ioread64_h.patch @@ -0,0 +1,53 @@ +From 9a6febb54c3a7e384bb12a8a64d39d7df2204645 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 15:43:34 +0100 +Subject: firmware: arm_scmi: use ioread64() instead of ioread64_hi_lo() + +From: Arnd Bergmann + +[ Upstream commit 3b8c56d8072750fd9625f03b92d8d6000c98628f ] + +The scmi_common_fastchannel_db_ring() function calls either ioread64() +or ioread64_hi_lo() depending on whether it is compiler for 32-bit +or 64-bit architectures. + +The same logic is used to define ioread64() itself in the +linux/io-64-nonatomic-hi-lo.h header file, so the special case +is not really needed. + +The behavior here should not change at all. + +Fixes: 6f9ea4dabd2d ("firmware: arm_scmi: Generalize the fast channel support") +Reviewed-by: Sudeep Holla +Link: https://lore.kernel.org/r/20250304144346.1025658-1-arnd@kernel.org +Signed-off-by: Arnd Bergmann +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_scmi/driver.c | 10 ---------- + 1 file changed, 10 deletions(-) + +diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c +index 60050da54bf24..1c75a4c9c3716 100644 +--- a/drivers/firmware/arm_scmi/driver.c ++++ b/drivers/firmware/arm_scmi/driver.c +@@ -1997,17 +1997,7 @@ static void scmi_common_fastchannel_db_ring(struct scmi_fc_db_info *db) + else if (db->width == 4) + SCMI_PROTO_FC_RING_DB(32); + else /* db->width == 8 */ +-#ifdef CONFIG_64BIT + SCMI_PROTO_FC_RING_DB(64); +-#else +- { +- u64 val = 0; +- +- if (db->mask) +- val = ioread64_hi_lo(db->addr) & db->mask; +- iowrite64_hi_lo(db->set | val, db->addr); +- } +-#endif + } + + /** +-- +2.39.5 + diff --git a/queue-6.14/firmware-cs_dsp-ensure-cs_dsp_load-_coeff-returns-0-.patch b/queue-6.14/firmware-cs_dsp-ensure-cs_dsp_load-_coeff-returns-0-.patch new file mode 100644 index 0000000000..69fb60292b --- /dev/null +++ b/queue-6.14/firmware-cs_dsp-ensure-cs_dsp_load-_coeff-returns-0-.patch @@ -0,0 +1,67 @@ +From 220fc23726bccfc7cb9f5ea1a732e5a85d84e1d5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 23 Mar 2025 17:05:29 +0000 +Subject: firmware: cs_dsp: Ensure cs_dsp_load[_coeff]() returns 0 on success + +From: Richard Fitzgerald + +[ Upstream commit 2593f7e0dc93a898a84220b3fb180d86f1ca8c60 ] + +Set ret = 0 on successful completion of the processing loop in +cs_dsp_load() and cs_dsp_load_coeff() to ensure that the function +returns 0 on success. + +All normal firmware files will have at least one data block, and +processing this block will set ret == 0, from the result of either +regmap_raw_write() or cs_dsp_parse_coeff(). + +The kunit tests create a dummy firmware file that contains only the +header, without any data blocks. This gives cs_dsp a file to "load" +that will not cause any side-effects. As there aren't any data blocks, +the processing loop will not set ret == 0. + +Originally there was a line after the processing loop: + + ret = regmap_async_complete(regmap); + +which would set ret == 0 before the function returned. + +Commit fe08b7d5085a ("firmware: cs_dsp: Remove async regmap writes") +changed the regmap write to a normal sync write, so the call to +regmap_async_complete() wasn't necessary and was removed. It was +overlooked that the ret here wasn't only to check the result of +regmap_async_complete(), it also set the final return value of the +function. + +Fixes: fe08b7d5085a ("firmware: cs_dsp: Remove async regmap writes") +Signed-off-by: Richard Fitzgerald +Link: https://patch.msgid.link/20250323170529.197205-1-rf@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/firmware/cirrus/cs_dsp.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/firmware/cirrus/cs_dsp.c b/drivers/firmware/cirrus/cs_dsp.c +index 42433c19eb308..560724ce21aa3 100644 +--- a/drivers/firmware/cirrus/cs_dsp.c ++++ b/drivers/firmware/cirrus/cs_dsp.c +@@ -1631,6 +1631,7 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, + + cs_dsp_debugfs_save_wmfwname(dsp, file); + ++ ret = 0; + out_fw: + cs_dsp_buf_free(&buf_list); + +@@ -2338,6 +2339,7 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware + + cs_dsp_debugfs_save_binname(dsp, file); + ++ ret = 0; + out_fw: + cs_dsp_buf_free(&buf_list); + +-- +2.39.5 + diff --git a/queue-6.14/fs-9p-fix-null-pointer-dereference-on-mkdir.patch b/queue-6.14/fs-9p-fix-null-pointer-dereference-on-mkdir.patch new file mode 100644 index 0000000000..dfb0e52896 --- /dev/null +++ b/queue-6.14/fs-9p-fix-null-pointer-dereference-on-mkdir.patch @@ -0,0 +1,73 @@ +From fb0d96f44e3c5a4fad615ca626e0193bb9b7efa2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 13:59:32 +0100 +Subject: fs/9p: fix NULL pointer dereference on mkdir + +From: Christian Schoenebeck + +[ Upstream commit 3f61ac7c65bdb26accb52f9db66313597e759821 ] + +When a 9p tree was mounted with option 'posixacl', parent directory had a +default ACL set for its subdirectories, e.g.: + + setfacl -m default:group:simpsons:rwx parentdir + +then creating a subdirectory crashed 9p client, as v9fs_fid_add() call in +function v9fs_vfs_mkdir_dotl() sets the passed 'fid' pointer to NULL +(since dafbe689736) even though the subsequent v9fs_set_create_acl() call +expects a valid non-NULL 'fid' pointer: + + [ 37.273191] BUG: kernel NULL pointer dereference, address: 0000000000000000 + ... + [ 37.322338] Call Trace: + [ 37.323043] + [ 37.323621] ? __die (arch/x86/kernel/dumpstack.c:421 arch/x86/kernel/dumpstack.c:434) + [ 37.324448] ? page_fault_oops (arch/x86/mm/fault.c:714) + [ 37.325532] ? search_module_extables (kernel/module/main.c:3733) + [ 37.326742] ? p9_client_walk (net/9p/client.c:1165) 9pnet + [ 37.328006] ? search_bpf_extables (kernel/bpf/core.c:804) + [ 37.329142] ? exc_page_fault (./arch/x86/include/asm/paravirt.h:686 arch/x86/mm/fault.c:1488 arch/x86/mm/fault.c:1538) + [ 37.330196] ? asm_exc_page_fault (./arch/x86/include/asm/idtentry.h:574) + [ 37.331330] ? p9_client_walk (net/9p/client.c:1165) 9pnet + [ 37.332562] ? v9fs_fid_xattr_get (fs/9p/xattr.c:30) 9p + [ 37.333824] v9fs_fid_xattr_set (fs/9p/fid.h:23 fs/9p/xattr.c:121) 9p + [ 37.335077] v9fs_set_acl (fs/9p/acl.c:276) 9p + [ 37.336112] v9fs_set_create_acl (fs/9p/acl.c:307) 9p + [ 37.337326] v9fs_vfs_mkdir_dotl (fs/9p/vfs_inode_dotl.c:411) 9p + [ 37.338590] vfs_mkdir (fs/namei.c:4313) + [ 37.339535] do_mkdirat (fs/namei.c:4336) + [ 37.340465] __x64_sys_mkdir (fs/namei.c:4354) + [ 37.341455] do_syscall_64 (arch/x86/entry/common.c:52 arch/x86/entry/common.c:83) + [ 37.342447] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130) + +Fix this by simply swapping the sequence of these two calls in +v9fs_vfs_mkdir_dotl(), i.e. calling v9fs_set_create_acl() before +v9fs_fid_add(). + +Fixes: dafbe689736f ("9p fid refcount: cleanup p9_fid_put calls") +Reported-by: syzbot+5b667f9a1fee4ba3775a@syzkaller.appspotmail.com +Signed-off-by: Christian Schoenebeck +Message-ID: +Signed-off-by: Dominique Martinet +Signed-off-by: Sasha Levin +--- + fs/9p/vfs_inode_dotl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c +index 143ac03b7425c..3397939fd2d5a 100644 +--- a/fs/9p/vfs_inode_dotl.c ++++ b/fs/9p/vfs_inode_dotl.c +@@ -407,8 +407,8 @@ static int v9fs_vfs_mkdir_dotl(struct mnt_idmap *idmap, + err); + goto error; + } +- v9fs_fid_add(dentry, &fid); + v9fs_set_create_acl(inode, fid, dacl, pacl); ++ v9fs_fid_add(dentry, &fid); + d_instantiate(dentry, inode); + err = 0; + inc_nlink(dir); +-- +2.39.5 + diff --git a/queue-6.14/fs-ntfs3-factor-out-ntfs_-create-remove-_proc_root.patch b/queue-6.14/fs-ntfs3-factor-out-ntfs_-create-remove-_proc_root.patch new file mode 100644 index 0000000000..3521fbd27d --- /dev/null +++ b/queue-6.14/fs-ntfs3-factor-out-ntfs_-create-remove-_proc_root.patch @@ -0,0 +1,77 @@ +From c62d692a50cdaa31fc57f4902b49c94701f970be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Oct 2024 15:40:24 +0800 +Subject: fs/ntfs3: Factor out ntfs_{create/remove}_proc_root() + +From: Ye Bin + +[ Upstream commit c5a396295370fa99ddc0c4c4d25f8a3ee4f013d8 ] + +Introduce ntfs_create_proc_root()/ntfs_remove_proc_root() for +create/remove "/proc/fs/ntfs3". + +Signed-off-by: Ye Bin +Signed-off-by: Konstantin Komarov +Stable-dep-of: 1d1a7e252549 ("fs/ntfs3: Fix 'proc_info_root' leak when init ntfs failed") +Signed-off-by: Sasha Levin +--- + fs/ntfs3/super.c | 26 +++++++++++++++++--------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c +index 415492fc655ac..66047cf0e6e81 100644 +--- a/fs/ntfs3/super.c ++++ b/fs/ntfs3/super.c +@@ -586,9 +586,24 @@ static void ntfs_remove_procdir(struct super_block *sb) + remove_proc_entry(sb->s_id, proc_info_root); + sbi->procdir = NULL; + } ++ ++static void ntfs_create_proc_root(void) ++{ ++ proc_info_root = proc_mkdir("fs/ntfs3", NULL); ++} ++ ++static void ntfs_remove_proc_root(void) ++{ ++ if (proc_info_root) { ++ remove_proc_entry("fs/ntfs3", NULL); ++ proc_info_root = NULL; ++ } ++} + #else + static void ntfs_create_procdir(struct super_block *sb) {} + static void ntfs_remove_procdir(struct super_block *sb) {} ++static void ntfs_create_proc_root(void) {} ++static void ntfs_remove_proc_root(void) {} + #endif + + static struct kmem_cache *ntfs_inode_cachep; +@@ -1866,10 +1881,7 @@ static int __init init_ntfs_fs(void) + if (IS_ENABLED(CONFIG_NTFS3_LZX_XPRESS)) + pr_info("ntfs3: Read-only LZX/Xpress compression included\n"); + +-#ifdef CONFIG_PROC_FS +- /* Create "/proc/fs/ntfs3" */ +- proc_info_root = proc_mkdir("fs/ntfs3", NULL); +-#endif ++ ntfs_create_proc_root(); + + err = ntfs3_init_bitmap(); + if (err) +@@ -1903,11 +1915,7 @@ static void __exit exit_ntfs_fs(void) + unregister_filesystem(&ntfs_fs_type); + unregister_as_ntfs_legacy(); + ntfs3_exit_bitmap(); +- +-#ifdef CONFIG_PROC_FS +- if (proc_info_root) +- remove_proc_entry("fs/ntfs3", NULL); +-#endif ++ ntfs_remove_proc_root(); + } + + MODULE_LICENSE("GPL"); +-- +2.39.5 + diff --git a/queue-6.14/fs-ntfs3-factor-out-ntfs_-create-remove-_procdir.patch b/queue-6.14/fs-ntfs3-factor-out-ntfs_-create-remove-_procdir.patch new file mode 100644 index 0000000000..6a87417012 --- /dev/null +++ b/queue-6.14/fs-ntfs3-factor-out-ntfs_-create-remove-_procdir.patch @@ -0,0 +1,107 @@ +From 4bc97603d26e18bbd0e98f129d78cc267e2bca55 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Oct 2024 15:40:23 +0800 +Subject: fs/ntfs3: Factor out ntfs_{create/remove}_procdir() + +From: Ye Bin + +[ Upstream commit e2d74c47a3d3d84a5fa444f380c126328b44f4db ] + +Introduce ntfs_create_procdir() and ntfs_remove_procdir() to +create/remove "/proc/fs/ntfs3/.." + +Signed-off-by: Ye Bin +Signed-off-by: Konstantin Komarov +Stable-dep-of: 1d1a7e252549 ("fs/ntfs3: Fix 'proc_info_root' leak when init ntfs failed") +Signed-off-by: Sasha Levin +--- + fs/ntfs3/super.c | 59 +++++++++++++++++++++++++++++------------------- + 1 file changed, 36 insertions(+), 23 deletions(-) + +diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c +index 6a0f6b0a3ab2a..415492fc655ac 100644 +--- a/fs/ntfs3/super.c ++++ b/fs/ntfs3/super.c +@@ -555,6 +555,40 @@ static const struct proc_ops ntfs3_label_fops = { + .proc_write = ntfs3_label_write, + }; + ++static void ntfs_create_procdir(struct super_block *sb) ++{ ++ struct proc_dir_entry *e; ++ ++ if (!proc_info_root) ++ return; ++ ++ e = proc_mkdir(sb->s_id, proc_info_root); ++ if (e) { ++ struct ntfs_sb_info *sbi = sb->s_fs_info; ++ ++ proc_create_data("volinfo", 0444, e, ++ &ntfs3_volinfo_fops, sb); ++ proc_create_data("label", 0644, e, ++ &ntfs3_label_fops, sb); ++ sbi->procdir = e; ++ } ++} ++ ++static void ntfs_remove_procdir(struct super_block *sb) ++{ ++ struct ntfs_sb_info *sbi = sb->s_fs_info; ++ ++ if (!sbi->procdir) ++ return; ++ ++ remove_proc_entry("label", sbi->procdir); ++ remove_proc_entry("volinfo", sbi->procdir); ++ remove_proc_entry(sb->s_id, proc_info_root); ++ sbi->procdir = NULL; ++} ++#else ++static void ntfs_create_procdir(struct super_block *sb) {} ++static void ntfs_remove_procdir(struct super_block *sb) {} + #endif + + static struct kmem_cache *ntfs_inode_cachep; +@@ -644,15 +678,7 @@ static void ntfs_put_super(struct super_block *sb) + { + struct ntfs_sb_info *sbi = sb->s_fs_info; + +-#ifdef CONFIG_PROC_FS +- // Remove /proc/fs/ntfs3/.. +- if (sbi->procdir) { +- remove_proc_entry("label", sbi->procdir); +- remove_proc_entry("volinfo", sbi->procdir); +- remove_proc_entry(sb->s_id, proc_info_root); +- sbi->procdir = NULL; +- } +-#endif ++ ntfs_remove_procdir(sb); + + /* Mark rw ntfs as clear, if possible. */ + ntfs_set_state(sbi, NTFS_DIRTY_CLEAR); +@@ -1590,20 +1616,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) + kfree(boot2); + } + +-#ifdef CONFIG_PROC_FS +- /* Create /proc/fs/ntfs3/.. */ +- if (proc_info_root) { +- struct proc_dir_entry *e = proc_mkdir(sb->s_id, proc_info_root); +- static_assert((S_IRUGO | S_IWUSR) == 0644); +- if (e) { +- proc_create_data("volinfo", S_IRUGO, e, +- &ntfs3_volinfo_fops, sb); +- proc_create_data("label", S_IRUGO | S_IWUSR, e, +- &ntfs3_label_fops, sb); +- sbi->procdir = e; +- } +- } +-#endif ++ ntfs_create_procdir(sb); + + if (is_legacy_ntfs(sb)) + sb->s_flags |= SB_RDONLY; +-- +2.39.5 + diff --git a/queue-6.14/fs-ntfs3-fix-a-couple-integer-overflows-on-32bit-sys.patch b/queue-6.14/fs-ntfs3-fix-a-couple-integer-overflows-on-32bit-sys.patch new file mode 100644 index 0000000000..0aef971de8 --- /dev/null +++ b/queue-6.14/fs-ntfs3-fix-a-couple-integer-overflows-on-32bit-sys.patch @@ -0,0 +1,45 @@ +From 57c1461e9e879b26391a86387b59f8ff6cc1ac58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Feb 2025 23:52:00 +0300 +Subject: fs/ntfs3: Fix a couple integer overflows on 32bit systems + +From: Dan Carpenter + +[ Upstream commit 5ad414f4df2294b28836b5b7b69787659d6aa708 ] + +On 32bit systems the "off + sizeof(struct NTFS_DE)" addition can +have an integer wrapping issue. Fix it by using size_add(). + +Fixes: 82cae269cfa9 ("fs/ntfs3: Add initialization of super block") +Signed-off-by: Dan Carpenter +Signed-off-by: Konstantin Komarov +Signed-off-by: Sasha Levin +--- + fs/ntfs3/index.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c +index 7eb9fae22f8da..78d20e4baa2c9 100644 +--- a/fs/ntfs3/index.c ++++ b/fs/ntfs3/index.c +@@ -618,7 +618,7 @@ static bool index_hdr_check(const struct INDEX_HDR *hdr, u32 bytes) + u32 off = le32_to_cpu(hdr->de_off); + + if (!IS_ALIGNED(off, 8) || tot > bytes || end > tot || +- off + sizeof(struct NTFS_DE) > end) { ++ size_add(off, sizeof(struct NTFS_DE)) > end) { + /* incorrect index buffer. */ + return false; + } +@@ -736,7 +736,7 @@ static struct NTFS_DE *hdr_find_e(const struct ntfs_index *indx, + if (end > total) + return NULL; + +- if (off + sizeof(struct NTFS_DE) > end) ++ if (size_add(off, sizeof(struct NTFS_DE)) > end) + return NULL; + + e = Add2Ptr(hdr, off); +-- +2.39.5 + diff --git a/queue-6.14/fs-ntfs3-fix-proc_info_root-leak-when-init-ntfs-fail.patch b/queue-6.14/fs-ntfs3-fix-proc_info_root-leak-when-init-ntfs-fail.patch new file mode 100644 index 0000000000..3b2824cc88 --- /dev/null +++ b/queue-6.14/fs-ntfs3-fix-proc_info_root-leak-when-init-ntfs-fail.patch @@ -0,0 +1,61 @@ +From 0b4fcc07bb89402b2a3727c6dfd430c22c0e1e41 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Oct 2024 15:40:25 +0800 +Subject: fs/ntfs3: Fix 'proc_info_root' leak when init ntfs failed + +From: Ye Bin + +[ Upstream commit 1d1a7e2525491f56901f5f63370a0775768044b8 ] + +There's a issue as follows: + proc_dir_entry 'fs/ntfs3' already registered + WARNING: CPU: 3 PID: 9788 at fs/proc/generic.c:375 proc_register+0x418/0x590 + Modules linked in: ntfs3(E+) + Call Trace: + + _proc_mkdir+0x165/0x200 + init_ntfs_fs+0x36/0xf90 [ntfs3] + do_one_initcall+0x115/0x6c0 + do_init_module+0x253/0x760 + load_module+0x55f2/0x6c80 + init_module_from_file+0xd2/0x130 + __x64_sys_finit_module+0xbf/0x130 + do_syscall_64+0x72/0x1c0 + +Above issue happens as missing destroy 'proc_info_root' when error +happens after create 'proc_info_root' in init_ntfs_fs(). +So destroy 'proc_info_root' in error path in init_ntfs_fs(). + +Fixes: 7832e123490a ("fs/ntfs3: Add support /proc/fs/ntfs3//volinfo and /proc/fs/ntfs3//label") +Signed-off-by: Ye Bin +Signed-off-by: Konstantin Komarov +Signed-off-by: Sasha Levin +--- + fs/ntfs3/super.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c +index 66047cf0e6e81..920a1ab47b631 100644 +--- a/fs/ntfs3/super.c ++++ b/fs/ntfs3/super.c +@@ -1885,7 +1885,7 @@ static int __init init_ntfs_fs(void) + + err = ntfs3_init_bitmap(); + if (err) +- return err; ++ goto out2; + + ntfs_inode_cachep = kmem_cache_create( + "ntfs_inode_cache", sizeof(struct ntfs_inode), 0, +@@ -1905,6 +1905,8 @@ static int __init init_ntfs_fs(void) + kmem_cache_destroy(ntfs_inode_cachep); + out1: + ntfs3_exit_bitmap(); ++out2: ++ ntfs_remove_proc_root(); + return err; + } + +-- +2.39.5 + diff --git a/queue-6.14/fs-ntfs3-prevent-integer-overflow-in-hdr_first_de.patch b/queue-6.14/fs-ntfs3-prevent-integer-overflow-in-hdr_first_de.patch new file mode 100644 index 0000000000..ff9f1489cd --- /dev/null +++ b/queue-6.14/fs-ntfs3-prevent-integer-overflow-in-hdr_first_de.patch @@ -0,0 +1,38 @@ +From df1897c4d7e6e99025bb35b6a3c72be0b383e864 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Feb 2025 23:52:10 +0300 +Subject: fs/ntfs3: Prevent integer overflow in hdr_first_de() + +From: Dan Carpenter + +[ Upstream commit 6bb81b94f7a9cba6bde9a905cef52a65317a8b04 ] + +The "de_off" and "used" variables come from the disk so they both need to +check. The problem is that on 32bit systems if they're both greater than +UINT_MAX - 16 then the check does work as intended because of an integer +overflow. + +Fixes: 60ce8dfde035 ("fs/ntfs3: Fix wrong if in hdr_first_de") +Signed-off-by: Dan Carpenter +Signed-off-by: Konstantin Komarov +Signed-off-by: Sasha Levin +--- + fs/ntfs3/ntfs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/ntfs3/ntfs.h b/fs/ntfs3/ntfs.h +index 241f2ffdd9201..1ff13b6f96132 100644 +--- a/fs/ntfs3/ntfs.h ++++ b/fs/ntfs3/ntfs.h +@@ -717,7 +717,7 @@ static inline struct NTFS_DE *hdr_first_de(const struct INDEX_HDR *hdr) + struct NTFS_DE *e; + u16 esize; + +- if (de_off >= used || de_off + sizeof(struct NTFS_DE) > used ) ++ if (de_off >= used || size_add(de_off, sizeof(struct NTFS_DE)) > used) + return NULL; + + e = Add2Ptr(hdr, de_off); +-- +2.39.5 + diff --git a/queue-6.14/fs-ntfs3-update-inode-i_mapping-a_ops-on-compression.patch b/queue-6.14/fs-ntfs3-update-inode-i_mapping-a_ops-on-compression.patch new file mode 100644 index 0000000000..313d83203e --- /dev/null +++ b/queue-6.14/fs-ntfs3-update-inode-i_mapping-a_ops-on-compression.patch @@ -0,0 +1,98 @@ +From f677c9b719b7e370c0133c3b868f8521d64b4198 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 17:03:41 +0300 +Subject: fs/ntfs3: Update inode->i_mapping->a_ops on compression state + +From: Konstantin Komarov + +[ Upstream commit b432163ebd15a0fb74051949cb61456d6c55ccbd ] + +Update inode->i_mapping->a_ops when the compression state changes to +ensure correct address space operations. +Clear ATTR_FLAG_SPARSED/FILE_ATTRIBUTE_SPARSE_FILE when enabling +compression to prevent flag conflicts. + +v2: +Additionally, ensure that all dirty pages are flushed and concurrent access +to the page cache is blocked. + +Fixes: 6b39bfaeec44 ("fs/ntfs3: Add support for the compression attribute") +Reported-by: Kun Hu , Jiaji Qin +Signed-off-by: Konstantin Komarov +Signed-off-by: Sasha Levin +--- + fs/ntfs3/attrib.c | 3 ++- + fs/ntfs3/file.c | 22 ++++++++++++++++++++-- + fs/ntfs3/frecord.c | 6 ++++-- + 3 files changed, 26 insertions(+), 5 deletions(-) + +diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c +index af94e3737470d..e946f75eb5406 100644 +--- a/fs/ntfs3/attrib.c ++++ b/fs/ntfs3/attrib.c +@@ -2664,8 +2664,9 @@ int attr_set_compress(struct ntfs_inode *ni, bool compr) + attr->nres.run_off = cpu_to_le16(run_off); + } + +- /* Update data attribute flags. */ ++ /* Update attribute flags. */ + if (compr) { ++ attr->flags &= ~ATTR_FLAG_SPARSED; + attr->flags |= ATTR_FLAG_COMPRESSED; + attr->nres.c_unit = NTFS_LZNT_CUNIT; + } else { +diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c +index 3f96a11804c90..e9f701f884e72 100644 +--- a/fs/ntfs3/file.c ++++ b/fs/ntfs3/file.c +@@ -101,8 +101,26 @@ int ntfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry, + /* Allowed to change compression for empty files and for directories only. */ + if (!is_dedup(ni) && !is_encrypted(ni) && + (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) { +- /* Change compress state. */ +- int err = ni_set_compress(inode, flags & FS_COMPR_FL); ++ int err = 0; ++ struct address_space *mapping = inode->i_mapping; ++ ++ /* write out all data and wait. */ ++ filemap_invalidate_lock(mapping); ++ err = filemap_write_and_wait(mapping); ++ ++ if (err >= 0) { ++ /* Change compress state. */ ++ bool compr = flags & FS_COMPR_FL; ++ err = ni_set_compress(inode, compr); ++ ++ /* For files change a_ops too. */ ++ if (!err) ++ mapping->a_ops = compr ? &ntfs_aops_cmpr : ++ &ntfs_aops; ++ } ++ ++ filemap_invalidate_unlock(mapping); ++ + if (err) + return err; + } +diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c +index 5df6a0b5add90..81271196c5571 100644 +--- a/fs/ntfs3/frecord.c ++++ b/fs/ntfs3/frecord.c +@@ -3434,10 +3434,12 @@ int ni_set_compress(struct inode *inode, bool compr) + } + + ni->std_fa = std->fa; +- if (compr) ++ if (compr) { ++ std->fa &= ~FILE_ATTRIBUTE_SPARSE_FILE; + std->fa |= FILE_ATTRIBUTE_COMPRESSED; +- else ++ } else { + std->fa &= ~FILE_ATTRIBUTE_COMPRESSED; ++ } + + if (ni->std_fa != std->fa) { + ni->std_fa = std->fa; +-- +2.39.5 + diff --git a/queue-6.14/fs-procfs-fix-the-comment-above-proc_pid_wchan.patch b/queue-6.14/fs-procfs-fix-the-comment-above-proc_pid_wchan.patch new file mode 100644 index 0000000000..8a0377c8f0 --- /dev/null +++ b/queue-6.14/fs-procfs-fix-the-comment-above-proc_pid_wchan.patch @@ -0,0 +1,41 @@ +From d89bbb76e618cd157398685ce4b1dcb2ff0c0dfe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 14:02:22 -0700 +Subject: fs/procfs: fix the comment above proc_pid_wchan() + +From: Bart Van Assche + +[ Upstream commit 6287fbad1cd91f0c25cdc3a580499060828a8f30 ] + +proc_pid_wchan() used to report kernel addresses to user space but that is +no longer the case today. Bring the comment above proc_pid_wchan() in +sync with the implementation. + +Link: https://lkml.kernel.org/r/20250319210222.1518771-1-bvanassche@acm.org +Fixes: b2f73922d119 ("fs/proc, core/debug: Don't expose absolute kernel addresses via wchan") +Signed-off-by: Bart Van Assche +Cc: Kees Cook +Cc: Eric W. Biederman +Cc: Alexey Dobriyan +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + fs/proc/base.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/proc/base.c b/fs/proc/base.c +index cd89e956c3224..7feb8f41aa253 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -416,7 +416,7 @@ static const struct file_operations proc_pid_cmdline_ops = { + #ifdef CONFIG_KALLSYMS + /* + * Provides a wchan file via kallsyms in a proper one-value-per-file format. +- * Returns the resolved symbol. If that fails, simply return the address. ++ * Returns the resolved symbol to user space. + */ + static int proc_pid_wchan(struct seq_file *m, struct pid_namespace *ns, + struct pid *pid, struct task_struct *task) +-- +2.39.5 + diff --git a/queue-6.14/fs-support-o_path-fds-with-fsconfig_set_fd.patch b/queue-6.14/fs-support-o_path-fds-with-fsconfig_set_fd.patch new file mode 100644 index 0000000000..a6955562e2 --- /dev/null +++ b/queue-6.14/fs-support-o_path-fds-with-fsconfig_set_fd.patch @@ -0,0 +1,54 @@ +From 90d0d971d55deb93101e46093d3426cd48dc6140 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 13:38:59 +0100 +Subject: fs: support O_PATH fds with FSCONFIG_SET_FD + +From: Christian Brauner + +[ Upstream commit 0ff053b98a0f039e52c2bd8d0cb38f2831edfaf5 ] + +Let FSCONFIG_SET_FD handle O_PATH file descriptors. This is particularly +useful in the context of overlayfs where layers can be specified via +file descriptors instead of paths. But userspace must currently use +non-O_PATH file desriptors which is often pointless especially if +the file descriptors have been created via open_tree(OPEN_TREE_CLONE). + +Link: https://lore.kernel.org/r/20250210-work-overlayfs-v2-1-ed2a949b674b@kernel.org +Fixes: a08557d19ef41 ("ovl: specify layers via file descriptors") +Reviewed-by: Amir Goldstein +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/autofs/autofs_i.h | 2 ++ + fs/fsopen.c | 2 +- + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h +index 77c7991d89aac..23cea74f9933b 100644 +--- a/fs/autofs/autofs_i.h ++++ b/fs/autofs/autofs_i.h +@@ -218,6 +218,8 @@ void autofs_clean_ino(struct autofs_info *); + + static inline int autofs_check_pipe(struct file *pipe) + { ++ if (pipe->f_mode & FMODE_PATH) ++ return -EINVAL; + if (!(pipe->f_mode & FMODE_CAN_WRITE)) + return -EINVAL; + if (!S_ISFIFO(file_inode(pipe)->i_mode)) +diff --git a/fs/fsopen.c b/fs/fsopen.c +index 094a7f510edfe..1aaf4cb2afb29 100644 +--- a/fs/fsopen.c ++++ b/fs/fsopen.c +@@ -453,7 +453,7 @@ SYSCALL_DEFINE5(fsconfig, + case FSCONFIG_SET_FD: + param.type = fs_value_is_file; + ret = -EBADF; +- param.file = fget(aux); ++ param.file = fget_raw(aux); + if (!param.file) + goto out_key; + param.dirfd = aux; +-- +2.39.5 + diff --git a/queue-6.14/fuse-fix-dax-truncate-punch_hole-fault-path.patch b/queue-6.14/fuse-fix-dax-truncate-punch_hole-fault-path.patch new file mode 100644 index 0000000000..70c59f0fc8 --- /dev/null +++ b/queue-6.14/fuse-fix-dax-truncate-punch_hole-fault-path.patch @@ -0,0 +1,146 @@ +From 7e87dc3b98df36e6cecc77142dfea68ec8c9482c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 14:30:56 +1100 +Subject: fuse: fix dax truncate/punch_hole fault path + +From: Alistair Popple + +[ Upstream commit 7851bf649d423edd7286b292739f2eefded3d35c ] + +Patch series "fs/dax: Fix ZONE_DEVICE page reference counts", v9. + +Device and FS DAX pages have always maintained their own page reference +counts without following the normal rules for page reference counting. In +particular pages are considered free when the refcount hits one rather +than zero and refcounts are not added when mapping the page. + +Tracking this requires special PTE bits (PTE_DEVMAP) and a secondary +mechanism for allowing GUP to hold references on the page (see +get_dev_pagemap). However there doesn't seem to be any reason why FS DAX +pages need their own reference counting scheme. + +By treating the refcounts on these pages the same way as normal pages we +can remove a lot of special checks. In particular pXd_trans_huge() +becomes the same as pXd_leaf(), although I haven't made that change here. +It also frees up a valuable SW define PTE bit on architectures that have +devmap PTE bits defined. + +It also almost certainly allows further clean-up of the devmap managed +functions, but I have left that as a future improvment. It also enables +support for compound ZONE_DEVICE pages which is one of my primary +motivators for doing this work. + +This patch (of 20): + +FS DAX requires file systems to call into the DAX layout prior to +unlinking inodes to ensure there is no ongoing DMA or other remote access +to the direct mapped page. The fuse file system implements +fuse_dax_break_layouts() to do this which includes a comment indicating +that passing dmap_end == 0 leads to unmapping of the whole file. + +However this is not true - passing dmap_end == 0 will not unmap anything +before dmap_start, and further more dax_layout_busy_page_range() will not +scan any of the range to see if there maybe ongoing DMA access to the +range. Fix this by passing -1 for dmap_end to fuse_dax_break_layouts() +which will invalidate the entire file range to +dax_layout_busy_page_range(). + +Link: https://lkml.kernel.org/r/cover.8068ad144a7eea4a813670301f4d2a86a8e68ec4.1740713401.git-series.apopple@nvidia.com +Link: https://lkml.kernel.org/r/f09a34b6c40032022e4ddee6fadb7cc676f08867.1740713401.git-series.apopple@nvidia.com +Fixes: 6ae330cad6ef ("virtiofs: serialize truncate/punch_hole and dax fault path") +Signed-off-by: Alistair Popple +Co-developed-by: Dan Williams +Signed-off-by: Dan Williams +Reviewed-by: Balbir Singh +Tested-by: Alison Schofield +Cc: Vivek Goyal +Cc: Alexander Gordeev +Cc: Asahi Lina +Cc: Bjorn Helgaas +Cc: Catalin Marinas +Cc: Christian Borntraeger +Cc: Christoph Hellwig +Cc: Chunyan Zhang +Cc: "Darrick J. Wong" +Cc: Dave Chinner +Cc: Dave Hansen +Cc: Dave Jiang +Cc: David Hildenbrand +Cc: Gerald Schaefer +Cc: Heiko Carstens +Cc: Huacai Chen +Cc: Ira Weiny +Cc: Jan Kara +Cc: Jason Gunthorpe +Cc: Jason Gunthorpe +Cc: John Hubbard +Cc: linmiaohe +Cc: Logan Gunthorpe +Cc: Matthew Wilcow (Oracle) +Cc: Michael "Camp Drill Sergeant" Ellerman +Cc: Nicholas Piggin +Cc: Peter Xu +Cc: Sven Schnelle +Cc: Ted Ts'o +Cc: Vasily Gorbik +Cc: Vishal Verma +Cc: WANG Xuerui +Cc: Will Deacon +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + fs/fuse/dax.c | 1 - + fs/fuse/dir.c | 2 +- + fs/fuse/file.c | 4 ++-- + 3 files changed, 3 insertions(+), 4 deletions(-) + +diff --git a/fs/fuse/dax.c b/fs/fuse/dax.c +index 0b6ee6dd1fd65..b7f805d2a14fd 100644 +--- a/fs/fuse/dax.c ++++ b/fs/fuse/dax.c +@@ -682,7 +682,6 @@ static int __fuse_dax_break_layouts(struct inode *inode, bool *retry, + 0, 0, fuse_wait_dax_page(inode)); + } + +-/* dmap_end == 0 leads to unmapping of whole file */ + int fuse_dax_break_layouts(struct inode *inode, u64 dmap_start, + u64 dmap_end) + { +diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c +index 3805f9b06c9d2..3b031d24d3691 100644 +--- a/fs/fuse/dir.c ++++ b/fs/fuse/dir.c +@@ -1940,7 +1940,7 @@ int fuse_do_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + if (FUSE_IS_DAX(inode) && is_truncate) { + filemap_invalidate_lock(mapping); + fault_blocked = true; +- err = fuse_dax_break_layouts(inode, 0, 0); ++ err = fuse_dax_break_layouts(inode, 0, -1); + if (err) { + filemap_invalidate_unlock(mapping); + return err; +diff --git a/fs/fuse/file.c b/fs/fuse/file.c +index d63e56fd3dd20..754378dd9f715 100644 +--- a/fs/fuse/file.c ++++ b/fs/fuse/file.c +@@ -253,7 +253,7 @@ static int fuse_open(struct inode *inode, struct file *file) + + if (dax_truncate) { + filemap_invalidate_lock(inode->i_mapping); +- err = fuse_dax_break_layouts(inode, 0, 0); ++ err = fuse_dax_break_layouts(inode, 0, -1); + if (err) + goto out_inode_unlock; + } +@@ -3205,7 +3205,7 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, + inode_lock(inode); + if (block_faults) { + filemap_invalidate_lock(inode->i_mapping); +- err = fuse_dax_break_layouts(inode, 0, 0); ++ err = fuse_dax_break_layouts(inode, 0, -1); + if (err) + goto out; + } +-- +2.39.5 + diff --git a/queue-6.14/gfs2-minor-evict-fix.patch b/queue-6.14/gfs2-minor-evict-fix.patch new file mode 100644 index 0000000000..62c7b3e7c7 --- /dev/null +++ b/queue-6.14/gfs2-minor-evict-fix.patch @@ -0,0 +1,64 @@ +From c61dd7276d798ffa404e3ff101dc02126e5da4b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 11:28:23 +0100 +Subject: gfs2: minor evict fix + +From: Andreas Gruenbacher + +[ Upstream commit e9e38ed7250f8ef6b2928216156c09df8b4834b3 ] + +In evict_should_delete(), when gfs2_upgrade_iopen_glock() fails, we +detach the iopen glock from the inode without calling +glock_clear_object(). This leads to a warning in glock_set_object() +when the same inode is recreated and the glock is reused. +Fix that by only detaching the iopen glock in gfs2_evict_inode(). + +In addition, remove the dequeue code from evict_should_delete(); we +already perform a conditional dequeue in gfs2_evict_inode(). + +Signed-off-by: Andreas Gruenbacher +Stable-dep-of: 41a8e04c94b8 ("gfs2: skip if we cannot defer delete") +Signed-off-by: Sasha Levin +--- + fs/gfs2/super.c | 17 +++-------------- + 1 file changed, 3 insertions(+), 14 deletions(-) + +diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c +index 92a3b6ddafdc1..ff8fdc6134ff5 100644 +--- a/fs/gfs2/super.c ++++ b/fs/gfs2/super.c +@@ -1338,12 +1338,8 @@ static enum evict_behavior evict_should_delete(struct inode *inode, + + /* Must not read inode block until block type has been verified */ + ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, gh); +- if (unlikely(ret)) { +- glock_clear_object(ip->i_iopen_gh.gh_gl, ip); +- ip->i_iopen_gh.gh_flags |= GL_NOCACHE; +- gfs2_glock_dq_uninit(&ip->i_iopen_gh); ++ if (unlikely(ret)) + return EVICT_SHOULD_DEFER_DELETE; +- } + + if (gfs2_inode_already_deleted(ip->i_gl, ip->i_no_formal_ino)) + return EVICT_SHOULD_SKIP_DELETE; +@@ -1363,15 +1359,8 @@ static enum evict_behavior evict_should_delete(struct inode *inode, + + should_delete: + if (gfs2_holder_initialized(&ip->i_iopen_gh) && +- test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) { +- enum evict_behavior behavior = +- gfs2_upgrade_iopen_glock(inode); +- +- if (behavior != EVICT_SHOULD_DELETE) { +- gfs2_holder_uninit(&ip->i_iopen_gh); +- return behavior; +- } +- } ++ test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) ++ return gfs2_upgrade_iopen_glock(inode); + return EVICT_SHOULD_DELETE; + } + +-- +2.39.5 + diff --git a/queue-6.14/gfs2-skip-if-we-cannot-defer-delete.patch b/queue-6.14/gfs2-skip-if-we-cannot-defer-delete.patch new file mode 100644 index 0000000000..3daacd95d0 --- /dev/null +++ b/queue-6.14/gfs2-skip-if-we-cannot-defer-delete.patch @@ -0,0 +1,49 @@ +From 35e46358e18114e6385d3bd49f060a06914dd930 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 22:13:28 +0100 +Subject: gfs2: skip if we cannot defer delete + +From: Andreas Gruenbacher + +[ Upstream commit 41a8e04c94b868023986ec35ca06756e31e1e229 ] + +In gfs2_evict_inode(), in the unlikely case that we cannot defer +deleting the inode, it is not safe to fall back to deleting the inode; +the only valid choice we have is to skip the delete. + +In addition, in evict_should_delete(), if we cannot lock the inode glock +exclusively, we are in a bad enough state that skipping the delete is +likely a better choice than trying to recover from the failure later. + +Fixes: c5b7a2400edc ("gfs2: Only defer deletes when we have an iopen glock") +Signed-off-by: Andreas Gruenbacher +Signed-off-by: Sasha Levin +--- + fs/gfs2/super.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c +index ff8fdc6134ff5..0e6ad7bf32be8 100644 +--- a/fs/gfs2/super.c ++++ b/fs/gfs2/super.c +@@ -1339,7 +1339,7 @@ static enum evict_behavior evict_should_delete(struct inode *inode, + /* Must not read inode block until block type has been verified */ + ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, gh); + if (unlikely(ret)) +- return EVICT_SHOULD_DEFER_DELETE; ++ return EVICT_SHOULD_SKIP_DELETE; + + if (gfs2_inode_already_deleted(ip->i_gl, ip->i_no_formal_ino)) + return EVICT_SHOULD_SKIP_DELETE; +@@ -1498,7 +1498,7 @@ static void gfs2_evict_inode(struct inode *inode) + gfs2_glock_put(io_gl); + goto out; + } +- behavior = EVICT_SHOULD_DELETE; ++ behavior = EVICT_SHOULD_SKIP_DELETE; + } + if (behavior == EVICT_SHOULD_DELETE) + ret = evict_unlinked_inode(inode); +-- +2.39.5 + diff --git a/queue-6.14/gpu-cdns-mhdp8546-fix-call-balance-of-mhdp-clk-handl.patch b/queue-6.14/gpu-cdns-mhdp8546-fix-call-balance-of-mhdp-clk-handl.patch new file mode 100644 index 0000000000..49b2b6d9ee --- /dev/null +++ b/queue-6.14/gpu-cdns-mhdp8546-fix-call-balance-of-mhdp-clk-handl.patch @@ -0,0 +1,85 @@ +From 00bd980ed8bdca4c7af52b060c3d8381aa14b882 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 18:46:32 +0300 +Subject: gpu: cdns-mhdp8546: fix call balance of mhdp->clk handling routines + +From: Vitalii Mordan + +[ Upstream commit f65727be3fa5f252c8d982d15023aab8255ded19 ] + +If the clock mhdp->clk was not enabled in cdns_mhdp_probe(), it should not +be disabled in any path. + +The return value of clk_prepare_enable() is not checked. If mhdp->clk was +not enabled, it may be disabled in the error path of cdns_mhdp_probe() +(e.g., if cdns_mhdp_load_firmware() fails) or in cdns_mhdp_remove() after +a successful cdns_mhdp_probe() call. + +Use the devm_clk_get_enabled() helper function to ensure proper call +balance for mhdp->clk. + +Found by Linux Verification Center (linuxtesting.org) with Klever. + +Fixes: fb43aa0acdfd ("drm: bridge: Add support for Cadence MHDP8546 DPI/DP bridge") +Signed-off-by: Vitalii Mordan +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20250214154632.1907425-1-mordan@ispras.ru +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c | 12 +++--------- + 1 file changed, 3 insertions(+), 9 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +index d081850e3c03e..d4e4f484cbe5e 100644 +--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c ++++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +@@ -2463,9 +2463,9 @@ static int cdns_mhdp_probe(struct platform_device *pdev) + if (!mhdp) + return -ENOMEM; + +- clk = devm_clk_get(dev, NULL); ++ clk = devm_clk_get_enabled(dev, NULL); + if (IS_ERR(clk)) { +- dev_err(dev, "couldn't get clk: %ld\n", PTR_ERR(clk)); ++ dev_err(dev, "couldn't get and enable clk: %ld\n", PTR_ERR(clk)); + return PTR_ERR(clk); + } + +@@ -2504,14 +2504,12 @@ static int cdns_mhdp_probe(struct platform_device *pdev) + + mhdp->info = of_device_get_match_data(dev); + +- clk_prepare_enable(clk); +- + pm_runtime_enable(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) { + dev_err(dev, "pm_runtime_resume_and_get failed\n"); + pm_runtime_disable(dev); +- goto clk_disable; ++ return ret; + } + + if (mhdp->info && mhdp->info->ops && mhdp->info->ops->init) { +@@ -2590,8 +2588,6 @@ static int cdns_mhdp_probe(struct platform_device *pdev) + runtime_put: + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); +-clk_disable: +- clk_disable_unprepare(mhdp->clk); + + return ret; + } +@@ -2632,8 +2628,6 @@ static void cdns_mhdp_remove(struct platform_device *pdev) + cancel_work_sync(&mhdp->modeset_retry_work); + flush_work(&mhdp->hpd_work); + /* Ignoring mhdp->hdcp.check_work and mhdp->hdcp.prop_work here. */ +- +- clk_disable_unprepare(mhdp->clk); + } + + static const struct of_device_id mhdp_ids[] = { +-- +2.39.5 + diff --git a/queue-6.14/greybus-gb-beagleplay-add-error-handling-for-gb_grey.patch b/queue-6.14/greybus-gb-beagleplay-add-error-handling-for-gb_grey.patch new file mode 100644 index 0000000000..1cba7d2fce --- /dev/null +++ b/queue-6.14/greybus-gb-beagleplay-add-error-handling-for-gb_grey.patch @@ -0,0 +1,42 @@ +From 47df7aa56dcd17f986f1b76ff4ad88b06a3f4b55 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jan 2025 22:05:47 +0800 +Subject: greybus: gb-beagleplay: Add error handling for gb_greybus_init + +From: Wentao Liang + +[ Upstream commit be382372d55d65b5c7e5a523793ca5e403f8c595 ] + +Add error handling for the gb_greybus_init(bg) function call +during the firmware reflash process to maintain consistency +in error handling throughout the codebase. If initialization +fails, log an error and return FW_UPLOAD_ERR_RW_ERROR. + +Fixes: 0cf7befa3ea2 ("greybus: gb-beagleplay: Add firmware upload API") +Signed-off-by: Wentao Liang +Reviewed-by: Ayush Singh +Link: https://lore.kernel.org/r/20250120140547.1460-1-vulab@iscas.ac.cn +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/greybus/gb-beagleplay.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/greybus/gb-beagleplay.c b/drivers/greybus/gb-beagleplay.c +index 473ac3f2d3821..da31f1131afca 100644 +--- a/drivers/greybus/gb-beagleplay.c ++++ b/drivers/greybus/gb-beagleplay.c +@@ -912,7 +912,9 @@ static enum fw_upload_err cc1352_prepare(struct fw_upload *fw_upload, + cc1352_bootloader_reset(bg); + WRITE_ONCE(bg->flashing_mode, false); + msleep(200); +- gb_greybus_init(bg); ++ if (gb_greybus_init(bg) < 0) ++ return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_RW_ERROR, ++ "Failed to initialize greybus"); + gb_beagleplay_start_svc(bg); + return FW_UPLOAD_ERR_FW_INVALID; + } +-- +2.39.5 + diff --git a/queue-6.14/hid-remove-superfluous-and-wrong-makefile-entry-for-.patch b/queue-6.14/hid-remove-superfluous-and-wrong-makefile-entry-for-.patch new file mode 100644 index 0000000000..900d516569 --- /dev/null +++ b/queue-6.14/hid-remove-superfluous-and-wrong-makefile-entry-for-.patch @@ -0,0 +1,44 @@ +From 039ca97ddf380958af6777f31b02999454c78c31 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 09:08:22 +0100 +Subject: HID: remove superfluous (and wrong) Makefile entry for + CONFIG_INTEL_ISH_FIRMWARE_DOWNLOADER + +From: Jiri Kosina + +[ Upstream commit fe0fb58325e519008e2606a5aa2cff7ad23e212d ] + +The line + + obj-$(INTEL_ISH_FIRMWARE_DOWNLOADER) += intel-ish-hid/ + +in top-level HID Makefile is both superfluous (as CONFIG_INTEL_ISH_FIRMWARE_DOWNLOADER +depends on CONFIG_INTEL_ISH_HID, which contains intel-ish-hid/ already) and wrong (as it's +missing the CONFIG_ prefix). + +Just remove it. + +Fixes: 91b228107da3e ("HID: intel-ish-hid: ISH firmware loader client driver") +Reported-by: Jiri Slaby +Acked-by: Srinivas Pandruvada +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/Makefile | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile +index 482b096eea280..0abfe51704a0b 100644 +--- a/drivers/hid/Makefile ++++ b/drivers/hid/Makefile +@@ -166,7 +166,6 @@ obj-$(CONFIG_USB_KBD) += usbhid/ + obj-$(CONFIG_I2C_HID_CORE) += i2c-hid/ + + obj-$(CONFIG_INTEL_ISH_HID) += intel-ish-hid/ +-obj-$(INTEL_ISH_FIRMWARE_DOWNLOADER) += intel-ish-hid/ + + obj-$(CONFIG_AMD_SFH_HID) += amd-sfh-hid/ + +-- +2.39.5 + diff --git a/queue-6.14/i3c-master-svc-fix-missing-the-ibi-rules.patch b/queue-6.14/i3c-master-svc-fix-missing-the-ibi-rules.patch new file mode 100644 index 0000000000..fc26ca17b3 --- /dev/null +++ b/queue-6.14/i3c-master-svc-fix-missing-the-ibi-rules.patch @@ -0,0 +1,40 @@ +From 8833eaf12fb142876cb6313377bde13eeaf20262 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 13:36:04 +0800 +Subject: i3c: master: svc: Fix missing the IBI rules + +From: Stanley Chu + +[ Upstream commit 9cecad134d84d14dc72a0eea7a107691c3e5a837 ] + +The code does not add IBI rules for devices with controller capability. +However, the secondary controller has the controller capability and works +at target mode when the device is probed. Therefore, add IBI rules for +such devices. + +Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver") +Signed-off-by: Stanley Chu +Reviewed-by: Frank Li +Link: https://lore.kernel.org/r/20250318053606.3087121-2-yschu@nuvoton.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + drivers/i3c/master/svc-i3c-master.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c +index d6057d8c7dec4..ecc07c17f4c79 100644 +--- a/drivers/i3c/master/svc-i3c-master.c ++++ b/drivers/i3c/master/svc-i3c-master.c +@@ -1037,7 +1037,7 @@ static int svc_i3c_update_ibirules(struct svc_i3c_master *master) + + /* Create the IBIRULES register for both cases */ + i3c_bus_for_each_i3cdev(&master->base.bus, dev) { +- if (I3C_BCR_DEVICE_ROLE(dev->info.bcr) == I3C_BCR_I3C_MASTER) ++ if (!(dev->info.bcr & I3C_BCR_IBI_REQ_CAP)) + continue; + + if (dev->info.bcr & I3C_BCR_IBI_PAYLOAD) { +-- +2.39.5 + diff --git a/queue-6.14/ib-mad-check-available-slots-before-posting-receive-.patch b/queue-6.14/ib-mad-check-available-slots-before-posting-receive-.patch new file mode 100644 index 0000000000..78cb807d85 --- /dev/null +++ b/queue-6.14/ib-mad-check-available-slots-before-posting-receive-.patch @@ -0,0 +1,133 @@ +From 08528db5c62e99be9cfa0cbef9a6b979909e3a29 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 16:20:17 +0200 +Subject: IB/mad: Check available slots before posting receive WRs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Maher Sanalla + +[ Upstream commit 37826f0a8c2f6b6add5179003b8597e32a445362 ] + +The ib_post_receive_mads() function handles posting receive work +requests (WRs) to MAD QPs and is called in two cases: +1) When a MAD port is opened. +2) When a receive WQE is consumed upon receiving a new MAD. + +Whereas, if MADs arrive during the port open phase, a race condition +might cause an extra WR to be posted, exceeding the QP’s capacity. +This leads to failures such as: +infiniband mlx5_0: ib_post_recv failed: -12 +infiniband mlx5_0: Couldn't post receive WRs +infiniband mlx5_0: Couldn't start port +infiniband mlx5_0: Couldn't open port 1 + +Fix this by checking the current receive count before posting a new WR. +If the QP’s receive queue is full, do not post additional WRs. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Maher Sanalla +Link: https://patch.msgid.link/c4984ba3c3a98a5711a558bccefcad789587ecf1.1741875592.git.leon@kernel.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/mad.c | 38 ++++++++++++++++++----------------- + 1 file changed, 20 insertions(+), 18 deletions(-) + +diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c +index 1fd54d5c4dd8b..73f3a0b9a54b5 100644 +--- a/drivers/infiniband/core/mad.c ++++ b/drivers/infiniband/core/mad.c +@@ -2671,11 +2671,11 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, + struct ib_mad_private *mad) + { + unsigned long flags; +- int post, ret; + struct ib_mad_private *mad_priv; + struct ib_sge sg_list; + struct ib_recv_wr recv_wr; + struct ib_mad_queue *recv_queue = &qp_info->recv_queue; ++ int ret = 0; + + /* Initialize common scatter list fields */ + sg_list.lkey = qp_info->port_priv->pd->local_dma_lkey; +@@ -2685,7 +2685,7 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, + recv_wr.sg_list = &sg_list; + recv_wr.num_sge = 1; + +- do { ++ while (true) { + /* Allocate and map receive buffer */ + if (mad) { + mad_priv = mad; +@@ -2693,10 +2693,8 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, + } else { + mad_priv = alloc_mad_private(port_mad_size(qp_info->port_priv), + GFP_ATOMIC); +- if (!mad_priv) { +- ret = -ENOMEM; +- break; +- } ++ if (!mad_priv) ++ return -ENOMEM; + } + sg_list.length = mad_priv_dma_size(mad_priv); + sg_list.addr = ib_dma_map_single(qp_info->port_priv->device, +@@ -2705,37 +2703,41 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, + DMA_FROM_DEVICE); + if (unlikely(ib_dma_mapping_error(qp_info->port_priv->device, + sg_list.addr))) { +- kfree(mad_priv); + ret = -ENOMEM; +- break; ++ goto free_mad_priv; + } + mad_priv->header.mapping = sg_list.addr; + mad_priv->header.mad_list.mad_queue = recv_queue; + mad_priv->header.mad_list.cqe.done = ib_mad_recv_done; + recv_wr.wr_cqe = &mad_priv->header.mad_list.cqe; +- +- /* Post receive WR */ + spin_lock_irqsave(&recv_queue->lock, flags); +- post = (++recv_queue->count < recv_queue->max_active); +- list_add_tail(&mad_priv->header.mad_list.list, &recv_queue->list); ++ if (recv_queue->count >= recv_queue->max_active) { ++ /* Fully populated the receive queue */ ++ spin_unlock_irqrestore(&recv_queue->lock, flags); ++ break; ++ } ++ recv_queue->count++; ++ list_add_tail(&mad_priv->header.mad_list.list, ++ &recv_queue->list); + spin_unlock_irqrestore(&recv_queue->lock, flags); ++ + ret = ib_post_recv(qp_info->qp, &recv_wr, NULL); + if (ret) { + spin_lock_irqsave(&recv_queue->lock, flags); + list_del(&mad_priv->header.mad_list.list); + recv_queue->count--; + spin_unlock_irqrestore(&recv_queue->lock, flags); +- ib_dma_unmap_single(qp_info->port_priv->device, +- mad_priv->header.mapping, +- mad_priv_dma_size(mad_priv), +- DMA_FROM_DEVICE); +- kfree(mad_priv); + dev_err(&qp_info->port_priv->device->dev, + "ib_post_recv failed: %d\n", ret); + break; + } +- } while (post); ++ } + ++ ib_dma_unmap_single(qp_info->port_priv->device, ++ mad_priv->header.mapping, ++ mad_priv_dma_size(mad_priv), DMA_FROM_DEVICE); ++free_mad_priv: ++ kfree(mad_priv); + return ret; + } + +-- +2.39.5 + diff --git a/queue-6.14/ibmvnic-use-kernel-helpers-for-hex-dumps.patch b/queue-6.14/ibmvnic-use-kernel-helpers-for-hex-dumps.patch new file mode 100644 index 0000000000..61899cb6fc --- /dev/null +++ b/queue-6.14/ibmvnic-use-kernel-helpers-for-hex-dumps.patch @@ -0,0 +1,119 @@ +From 3cbedc0461d20a6a49c90d7722db2999b892cacd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Mar 2025 16:29:51 -0500 +Subject: ibmvnic: Use kernel helpers for hex dumps + +From: Nick Child + +[ Upstream commit d93a6caab5d7d9b5ce034d75b1e1e993338e3852 ] + +Previously, when the driver was printing hex dumps, the buffer was cast +to an 8 byte long and printed using string formatters. If the buffer +size was not a multiple of 8 then a read buffer overflow was possible. + +Therefore, create a new ibmvnic function that loops over a buffer and +calls hex_dump_to_buffer instead. + +This patch address KASAN reports like the one below: + ibmvnic 30000003 env3: Login Buffer: + ibmvnic 30000003 env3: 01000000af000000 + <...> + ibmvnic 30000003 env3: 2e6d62692e736261 + ibmvnic 30000003 env3: 65050003006d6f63 + ================================================================== + BUG: KASAN: slab-out-of-bounds in ibmvnic_login+0xacc/0xffc [ibmvnic] + Read of size 8 at addr c0000001331a9aa8 by task ip/17681 + <...> + Allocated by task 17681: + <...> + ibmvnic_login+0x2f0/0xffc [ibmvnic] + ibmvnic_open+0x148/0x308 [ibmvnic] + __dev_open+0x1ac/0x304 + <...> + The buggy address is located 168 bytes inside of + allocated 175-byte region [c0000001331a9a00, c0000001331a9aaf) + <...> + ================================================================= + ibmvnic 30000003 env3: 000000000033766e + +Fixes: 032c5e82847a ("Driver for IBM System i/p VNIC protocol") +Signed-off-by: Nick Child +Reviewed-by: Dave Marquardt +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250320212951.11142-1-nnac123@linux.ibm.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/ibm/ibmvnic.c | 30 ++++++++++++++++++------------ + 1 file changed, 18 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c +index 0676fc547b6f4..480606d1245ea 100644 +--- a/drivers/net/ethernet/ibm/ibmvnic.c ++++ b/drivers/net/ethernet/ibm/ibmvnic.c +@@ -4829,6 +4829,18 @@ static void vnic_add_client_data(struct ibmvnic_adapter *adapter, + strscpy(vlcd->name, adapter->netdev->name, len); + } + ++static void ibmvnic_print_hex_dump(struct net_device *dev, void *buf, ++ size_t len) ++{ ++ unsigned char hex_str[16 * 3]; ++ ++ for (size_t i = 0; i < len; i += 16) { ++ hex_dump_to_buffer((unsigned char *)buf + i, len - i, 16, 8, ++ hex_str, sizeof(hex_str), false); ++ netdev_dbg(dev, "%s\n", hex_str); ++ } ++} ++ + static int send_login(struct ibmvnic_adapter *adapter) + { + struct ibmvnic_login_rsp_buffer *login_rsp_buffer; +@@ -4939,10 +4951,8 @@ static int send_login(struct ibmvnic_adapter *adapter) + vnic_add_client_data(adapter, vlcd); + + netdev_dbg(adapter->netdev, "Login Buffer:\n"); +- for (i = 0; i < (adapter->login_buf_sz - 1) / 8 + 1; i++) { +- netdev_dbg(adapter->netdev, "%016lx\n", +- ((unsigned long *)(adapter->login_buf))[i]); +- } ++ ibmvnic_print_hex_dump(adapter->netdev, adapter->login_buf, ++ adapter->login_buf_sz); + + memset(&crq, 0, sizeof(crq)); + crq.login.first = IBMVNIC_CRQ_CMD; +@@ -5319,15 +5329,13 @@ static void handle_query_ip_offload_rsp(struct ibmvnic_adapter *adapter) + { + struct device *dev = &adapter->vdev->dev; + struct ibmvnic_query_ip_offload_buffer *buf = &adapter->ip_offload_buf; +- int i; + + dma_unmap_single(dev, adapter->ip_offload_tok, + sizeof(adapter->ip_offload_buf), DMA_FROM_DEVICE); + + netdev_dbg(adapter->netdev, "Query IP Offload Buffer:\n"); +- for (i = 0; i < (sizeof(adapter->ip_offload_buf) - 1) / 8 + 1; i++) +- netdev_dbg(adapter->netdev, "%016lx\n", +- ((unsigned long *)(buf))[i]); ++ ibmvnic_print_hex_dump(adapter->netdev, buf, ++ sizeof(adapter->ip_offload_buf)); + + netdev_dbg(adapter->netdev, "ipv4_chksum = %d\n", buf->ipv4_chksum); + netdev_dbg(adapter->netdev, "ipv6_chksum = %d\n", buf->ipv6_chksum); +@@ -5558,10 +5566,8 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq, + netdev->mtu = adapter->req_mtu - ETH_HLEN; + + netdev_dbg(adapter->netdev, "Login Response Buffer:\n"); +- for (i = 0; i < (adapter->login_rsp_buf_sz - 1) / 8 + 1; i++) { +- netdev_dbg(adapter->netdev, "%016lx\n", +- ((unsigned long *)(adapter->login_rsp_buf))[i]); +- } ++ ibmvnic_print_hex_dump(netdev, adapter->login_rsp_buf, ++ adapter->login_rsp_buf_sz); + + /* Sanity checks */ + if (login->num_txcomp_subcrqs != login_rsp->num_txsubm_subcrqs || +-- +2.39.5 + diff --git a/queue-6.14/ice-ensure-periodic-output-start-time-is-in-the-futu.patch b/queue-6.14/ice-ensure-periodic-output-start-time-is-in-the-futu.patch new file mode 100644 index 0000000000..3de248b6fb --- /dev/null +++ b/queue-6.14/ice-ensure-periodic-output-start-time-is-in-the-futu.patch @@ -0,0 +1,101 @@ +From eb2e68a806dccb39d9d85b68465d6fe830abedff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 14:13:27 -0800 +Subject: ice: ensure periodic output start time is in the future + +From: Karol Kolacinski + +[ Upstream commit 53ce7166cbffd2b8f3bd821fd3918be665afd4c6 ] + +On E800 series hardware, if the start time for a periodic output signal is +programmed into GLTSYN_TGT_H and GLTSYN_TGT_L registers, the hardware logic +locks up and the periodic output signal never starts. Any future attempt to +reprogram the clock function is futile as the hardware will not reset until +a power on. + +The ice_ptp_cfg_perout function has logic to prevent this, as it checks if +the requested start time is in the past. If so, a new start time is +calculated by rounding up. + +Since commit d755a7e129a5 ("ice: Cache perout/extts requests and check +flags"), the rounding is done to the nearest multiple of the clock period, +rather than to a full second. This is more accurate, since it ensures the +signal matches the user request precisely. + +Unfortunately, there is a race condition with this rounding logic. If the +current time is close to the multiple of the period, we could calculate a +target time that is extremely soon. It takes time for the software to +program the registers, during which time this requested start time could +become a start time in the past. If that happens, the periodic output +signal will lock up. + +For large enough periods, or for the logic prior to the mentioned commit, +this is unlikely. However, with the new logic rounding to the period and +with a small enough period, this becomes inevitable. + +For example, attempting to enable a 10MHz signal requires a period of 100 +nanoseconds. This means in the *best* case, we have 99 nanoseconds to +program the clock output. This is essentially impossible, and thus such a +small period practically guarantees that the clock output function will +lock up. + +To fix this, add some slop to the clock time used to check if the start +time is in the past. Because it is not critical that output signals start +immediately, but it *is* critical that we do not brick the function, 0.5 +seconds is selected. This does mean that any requested output will be +delayed by at least 0.5 seconds. + +This slop is applied before rounding, so that we always round up to the +nearest multiple of the period that is at least 0.5 seconds in the future, +ensuring a minimum of 0.5 seconds to program the clock output registers. + +Finally, to ensure that the hardware registers programming the clock output +complete in a timely manner, add a write flush to the end of +ice_ptp_write_perout. This ensures we don't risk any issue with PCIe +transaction batching. + +Strictly speaking, this fixes a race condition all the way back at the +initial implementation of periodic output programming, as it is +theoretically possible to trigger this bug even on the old logic when +always rounding to a full second. However, the window is narrow, and the +code has been refactored heavily since then, making a direct backport not +apply cleanly. + +Fixes: d755a7e129a5 ("ice: Cache perout/extts requests and check flags") +Signed-off-by: Karol Kolacinski +Signed-off-by: Jacob Keller +Tested-by: Rinitha S (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index e26320ce52ca1..a99e0fbd0b8b5 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -1783,6 +1783,7 @@ static int ice_ptp_write_perout(struct ice_hw *hw, unsigned int chan, + 8 + chan + (tmr_idx * 4)); + + wr32(hw, GLGEN_GPIO_CTL(gpio_pin), val); ++ ice_flush(hw); + + return 0; + } +@@ -1843,9 +1844,10 @@ static int ice_ptp_cfg_perout(struct ice_pf *pf, struct ptp_perout_request *rq, + div64_u64_rem(start, period, &phase); + + /* If we have only phase or start time is in the past, start the timer +- * at the next multiple of period, maintaining phase. ++ * at the next multiple of period, maintaining phase at least 0.5 second ++ * from now, so we have time to write it to HW. + */ +- clk = ice_ptp_read_src_clk_reg(pf, NULL); ++ clk = ice_ptp_read_src_clk_reg(pf, NULL) + NSEC_PER_MSEC * 500; + if (rq->flags & PTP_PEROUT_PHASE || start <= clk - prop_delay_ns) + start = div64_u64(clk + period - 1, period) * period + phase; + +-- +2.39.5 + diff --git a/queue-6.14/ice-fix-input-validation-for-virtchnl-bw.patch b/queue-6.14/ice-fix-input-validation-for-virtchnl-bw.patch new file mode 100644 index 0000000000..5b9da325c6 --- /dev/null +++ b/queue-6.14/ice-fix-input-validation-for-virtchnl-bw.patch @@ -0,0 +1,73 @@ +From 8319a8c4840a2654ed0ebd53ab44290e527039c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 12:08:34 +0100 +Subject: ice: fix input validation for virtchnl BW + +From: Lukasz Czapnik + +[ Upstream commit c5be6562de5a19c44605b1c1edba8e339f2022c8 ] + +Add missing validation of tc and queue id values sent by a VF in +ice_vc_cfg_q_bw(). +Additionally fixed logged value in the warning message, +where max_tx_rate was incorrectly referenced instead of min_tx_rate. +Also correct error handling in this function by properly exiting +when invalid configuration is detected. + +Fixes: 015307754a19 ("ice: Support VF queue rate limit and quanta size configuration") +Reviewed-by: Jedrzej Jagielski +Reviewed-by: Simon Horman +Signed-off-by: Lukasz Czapnik +Co-developed-by: Martyna Szapar-Mudlaw +Signed-off-by: Martyna Szapar-Mudlaw +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_virtchnl.c | 24 ++++++++++++++++--- + 1 file changed, 21 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c +index df13f5110168d..1af51469f070b 100644 +--- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c ++++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c +@@ -1862,15 +1862,33 @@ static int ice_vc_cfg_q_bw(struct ice_vf *vf, u8 *msg) + + for (i = 0; i < qbw->num_queues; i++) { + if (qbw->cfg[i].shaper.peak != 0 && vf->max_tx_rate != 0 && +- qbw->cfg[i].shaper.peak > vf->max_tx_rate) ++ qbw->cfg[i].shaper.peak > vf->max_tx_rate) { + dev_warn(ice_pf_to_dev(vf->pf), "The maximum queue %d rate limit configuration may not take effect because the maximum TX rate for VF-%d is %d\n", + qbw->cfg[i].queue_id, vf->vf_id, + vf->max_tx_rate); ++ v_ret = VIRTCHNL_STATUS_ERR_PARAM; ++ goto err; ++ } + if (qbw->cfg[i].shaper.committed != 0 && vf->min_tx_rate != 0 && +- qbw->cfg[i].shaper.committed < vf->min_tx_rate) ++ qbw->cfg[i].shaper.committed < vf->min_tx_rate) { + dev_warn(ice_pf_to_dev(vf->pf), "The minimum queue %d rate limit configuration may not take effect because the minimum TX rate for VF-%d is %d\n", + qbw->cfg[i].queue_id, vf->vf_id, +- vf->max_tx_rate); ++ vf->min_tx_rate); ++ v_ret = VIRTCHNL_STATUS_ERR_PARAM; ++ goto err; ++ } ++ if (qbw->cfg[i].queue_id > vf->num_vf_qs) { ++ dev_warn(ice_pf_to_dev(vf->pf), "VF-%d trying to configure invalid queue_id\n", ++ vf->vf_id); ++ v_ret = VIRTCHNL_STATUS_ERR_PARAM; ++ goto err; ++ } ++ if (qbw->cfg[i].tc >= ICE_MAX_TRAFFIC_CLASS) { ++ dev_warn(ice_pf_to_dev(vf->pf), "VF-%d trying to configure a traffic class higher than allowed\n", ++ vf->vf_id); ++ v_ret = VIRTCHNL_STATUS_ERR_PARAM; ++ goto err; ++ } + } + + for (i = 0; i < qbw->num_queues; i++) { +-- +2.39.5 + diff --git a/queue-6.14/ice-fix-reservation-of-resources-for-rdma-when-disab.patch b/queue-6.14/ice-fix-reservation-of-resources-for-rdma-when-disab.patch new file mode 100644 index 0000000000..c328e36bd9 --- /dev/null +++ b/queue-6.14/ice-fix-reservation-of-resources-for-rdma-when-disab.patch @@ -0,0 +1,49 @@ +From 045119b2f143cf5888626d367fcd441649c9021c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 09:56:34 -0800 +Subject: ice: fix reservation of resources for RDMA when disabled + +From: Jesse Brandeburg + +[ Upstream commit 7fd71f317288d5150d353ce9d65b1e2abf99a8e2 ] + +If the CONFIG_INFINIBAND_IRDMA symbol is not enabled as a module or a +built-in, then don't let the driver reserve resources for RDMA. The result +of this change is a large savings in resources for older kernels, and a +cleaner driver configuration for the IRDMA=n case for old and new kernels. + +Implement this by avoiding enabling the RDMA capability when scanning +hardware capabilities. + +Note: Loading the out-of-tree irdma driver in connection to the in-kernel +ice driver, is not supported, and should not be attempted, especially when +disabling IRDMA in the kernel config. + +Fixes: d25a0fc41c1f ("ice: Initialize RDMA support") +Signed-off-by: Jesse Brandeburg +Acked-by: Dave Ertman +Reviewed-by: Aleksandr Loktionov +Tested-by: Rinitha S (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_common.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c +index 7a2a2e8da8fab..1e801300310e9 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -2271,7 +2271,8 @@ ice_parse_common_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps, + caps->nvm_unified_update); + break; + case ICE_AQC_CAPS_RDMA: +- caps->rdma = (number == 1); ++ if (IS_ENABLED(CONFIG_INFINIBAND_IRDMA)) ++ caps->rdma = (number == 1); + ice_debug(hw, ICE_DBG_INIT, "%s: rdma = %d\n", prefix, caps->rdma); + break; + case ICE_AQC_CAPS_MAX_MTU: +-- +2.39.5 + diff --git a/queue-6.14/ice-fix-using-untrusted-value-of-pkt_len-in-ice_vc_f.patch b/queue-6.14/ice-fix-using-untrusted-value-of-pkt_len-in-ice_vc_f.patch new file mode 100644 index 0000000000..1a2ef19cb7 --- /dev/null +++ b/queue-6.14/ice-fix-using-untrusted-value-of-pkt_len-in-ice_vc_f.patch @@ -0,0 +1,92 @@ +From a3ac4ce7b5bee51e8690711c4b57dcec1c129d58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 12:08:36 +0100 +Subject: ice: fix using untrusted value of pkt_len in ice_vc_fdir_parse_raw() + +From: Mateusz Polchlopek + +[ Upstream commit 1388dd564183a5a18ec4a966748037736b5653c5 ] + +Fix using the untrusted value of proto->raw.pkt_len in function +ice_vc_fdir_parse_raw() by verifying if it does not exceed the +VIRTCHNL_MAX_SIZE_RAW_PACKET value. + +Fixes: 99f419df8a5c ("ice: enable FDIR filters from raw binary patterns for VFs") +Reviewed-by: Przemek Kitszel +Signed-off-by: Mateusz Polchlopek +Signed-off-by: Martyna Szapar-Mudlaw +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + .../ethernet/intel/ice/ice_virtchnl_fdir.c | 24 ++++++++++++------- + 1 file changed, 15 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c +index 14e3f0f89c78d..9be4bd717512d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c ++++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c +@@ -832,21 +832,27 @@ ice_vc_fdir_parse_raw(struct ice_vf *vf, + struct virtchnl_proto_hdrs *proto, + struct virtchnl_fdir_fltr_conf *conf) + { +- u8 *pkt_buf, *msk_buf __free(kfree); ++ u8 *pkt_buf, *msk_buf __free(kfree) = NULL; + struct ice_parser_result rslt; + struct ice_pf *pf = vf->pf; ++ u16 pkt_len, udp_port = 0; + struct ice_parser *psr; + int status = -ENOMEM; + struct ice_hw *hw; +- u16 udp_port = 0; + +- pkt_buf = kzalloc(proto->raw.pkt_len, GFP_KERNEL); +- msk_buf = kzalloc(proto->raw.pkt_len, GFP_KERNEL); ++ pkt_len = proto->raw.pkt_len; ++ ++ if (!pkt_len || pkt_len > VIRTCHNL_MAX_SIZE_RAW_PACKET) ++ return -EINVAL; ++ ++ pkt_buf = kzalloc(pkt_len, GFP_KERNEL); ++ msk_buf = kzalloc(pkt_len, GFP_KERNEL); ++ + if (!pkt_buf || !msk_buf) + goto err_mem_alloc; + +- memcpy(pkt_buf, proto->raw.spec, proto->raw.pkt_len); +- memcpy(msk_buf, proto->raw.mask, proto->raw.pkt_len); ++ memcpy(pkt_buf, proto->raw.spec, pkt_len); ++ memcpy(msk_buf, proto->raw.mask, pkt_len); + + hw = &pf->hw; + +@@ -862,7 +868,7 @@ ice_vc_fdir_parse_raw(struct ice_vf *vf, + if (ice_get_open_tunnel_port(hw, &udp_port, TNL_VXLAN)) + ice_parser_vxlan_tunnel_set(psr, udp_port, true); + +- status = ice_parser_run(psr, pkt_buf, proto->raw.pkt_len, &rslt); ++ status = ice_parser_run(psr, pkt_buf, pkt_len, &rslt); + if (status) + goto err_parser_destroy; + +@@ -876,7 +882,7 @@ ice_vc_fdir_parse_raw(struct ice_vf *vf, + } + + status = ice_parser_profile_init(&rslt, pkt_buf, msk_buf, +- proto->raw.pkt_len, ICE_BLK_FD, ++ pkt_len, ICE_BLK_FD, + conf->prof); + if (status) + goto err_parser_profile_init; +@@ -885,7 +891,7 @@ ice_vc_fdir_parse_raw(struct ice_vf *vf, + ice_parser_profile_dump(hw, conf->prof); + + /* Store raw flow info into @conf */ +- conf->pkt_len = proto->raw.pkt_len; ++ conf->pkt_len = pkt_len; + conf->pkt_buf = pkt_buf; + conf->parser_ena = true; + +-- +2.39.5 + diff --git a/queue-6.14/ice-health.c-fix-compilation-on-gcc-7.5.patch b/queue-6.14/ice-health.c-fix-compilation-on-gcc-7.5.patch new file mode 100644 index 0000000000..d9368c4ddd --- /dev/null +++ b/queue-6.14/ice-health.c-fix-compilation-on-gcc-7.5.patch @@ -0,0 +1,69 @@ +From 92c93fdc5485cd1883eef3c936cb0e68d80d64dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 23:30:23 +0100 +Subject: ice: health.c: fix compilation on gcc 7.5 + +From: Przemek Kitszel + +[ Upstream commit fa8eda19015ca9ae625f46d4ecb13df651bb54cc ] + +GCC 7 is not as good as GCC 8+ in telling what is a compile-time +const, and thus could be used for static storage. +Fortunately keeping strings as const arrays is enough to make old +gcc happy. + +Excerpt from the report: +My GCC is: gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0. + + CC [M] drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.o +drivers/net/ethernet/intel/ice/devlink/health.c:35:3: error: initializer element is not constant + ice_common_port_solutions, {ice_port_number_label}}, + ^~~~~~~~~~~~~~~~~~~~~~~~~ +drivers/net/ethernet/intel/ice/devlink/health.c:35:3: note: (near initialization for 'ice_health_status_lookup[0].solution') +drivers/net/ethernet/intel/ice/devlink/health.c:35:31: error: initializer element is not constant + ice_common_port_solutions, {ice_port_number_label}}, + ^~~~~~~~~~~~~~~~~~~~~ +drivers/net/ethernet/intel/ice/devlink/health.c:35:31: note: (near initialization for 'ice_health_status_lookup[0].data_label[0]') +drivers/net/ethernet/intel/ice/devlink/health.c:37:46: error: initializer element is not constant + "Change or replace the module or cable.", {ice_port_number_label}}, + ^~~~~~~~~~~~~~~~~~~~~ +drivers/net/ethernet/intel/ice/devlink/health.c:37:46: note: (near initialization for 'ice_health_status_lookup[1].data_label[0]') +drivers/net/ethernet/intel/ice/devlink/health.c:39:3: error: initializer element is not constant + ice_common_port_solutions, {ice_port_number_label}}, + ^~~~~~~~~~~~~~~~~~~~~~~~~ + +Fixes: 85d6164ec56d ("ice: add fw and port health reporters") +Reported-by: Qiuxu Zhuo +Closes: https://lore.kernel.org/netdev/CY8PR11MB7134BF7A46D71E50D25FA7A989F72@CY8PR11MB7134.namprd11.prod.outlook.com +Reviewed-by: Michal Swiatkowski +Suggested-by: Simon Horman +Signed-off-by: Przemek Kitszel +Reviewed-by: Simon Horman +Tested-by: Sunitha Mekala (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/devlink/health.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/devlink/health.c b/drivers/net/ethernet/intel/ice/devlink/health.c +index ea40f79412590..19c3d37aa768b 100644 +--- a/drivers/net/ethernet/intel/ice/devlink/health.c ++++ b/drivers/net/ethernet/intel/ice/devlink/health.c +@@ -25,10 +25,10 @@ struct ice_health_status { + * The below lookup requires to be sorted by code. + */ + +-static const char *const ice_common_port_solutions = ++static const char ice_common_port_solutions[] = + "Check your cable connection. Change or replace the module or cable. Manually set speed and duplex."; +-static const char *const ice_port_number_label = "Port Number"; +-static const char *const ice_update_nvm_solution = "Update to the latest NVM image."; ++static const char ice_port_number_label[] = "Port Number"; ++static const char ice_update_nvm_solution[] = "Update to the latest NVM image."; + + static const struct ice_health_status ice_health_status_lookup[] = { + {ICE_AQC_HEALTH_STATUS_ERR_UNKNOWN_MOD_STRICT, "An unsupported module was detected.", +-- +2.39.5 + diff --git a/queue-6.14/ice-stop-truncating-queue-ids-when-checking.patch b/queue-6.14/ice-stop-truncating-queue-ids-when-checking.patch new file mode 100644 index 0000000000..e0bee9c03f --- /dev/null +++ b/queue-6.14/ice-stop-truncating-queue-ids-when-checking.patch @@ -0,0 +1,41 @@ +From 4408563cab4b29737ff70658e877232c7cfdaa6b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 12:08:32 +0100 +Subject: ice: stop truncating queue ids when checking + +From: Jan Glaza + +[ Upstream commit f91d0efcc3dd7b341bb370499b99dc02d4fb792f ] + +Queue IDs can be up to 4096, fix invalid check to stop +truncating IDs to 8 bits. + +Fixes: bf93bf791cec8 ("ice: introduce ice_virtchnl.c and ice_virtchnl.h") +Reviewed-by: Aleksandr Loktionov +Reviewed-by: Jedrzej Jagielski +Reviewed-by: Simon Horman +Signed-off-by: Jan Glaza +Signed-off-by: Martyna Szapar-Mudlaw +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_virtchnl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c +index ff4ad788d96ac..346aee373ccd4 100644 +--- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c ++++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c +@@ -562,7 +562,7 @@ bool ice_vc_isvalid_vsi_id(struct ice_vf *vf, u16 vsi_id) + * + * check for the valid queue ID + */ +-static bool ice_vc_isvalid_q_id(struct ice_vsi *vsi, u8 qid) ++static bool ice_vc_isvalid_q_id(struct ice_vsi *vsi, u16 qid) + { + /* allocated Tx and Rx queues should be always equal for VF VSI */ + return qid < vsi->alloc_txq; +-- +2.39.5 + diff --git a/queue-6.14/ice-validate-queue-quanta-parameters-to-prevent-oob-.patch b/queue-6.14/ice-validate-queue-quanta-parameters-to-prevent-oob-.patch new file mode 100644 index 0000000000..b952e3aec1 --- /dev/null +++ b/queue-6.14/ice-validate-queue-quanta-parameters-to-prevent-oob-.patch @@ -0,0 +1,71 @@ +From 340add927f4b564e78b7b1ca7022bfee7b7f6670 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 12:08:33 +0100 +Subject: ice: validate queue quanta parameters to prevent OOB access + +From: Jan Glaza + +[ Upstream commit e2f7d3f7331b92cb820da23e8c45133305da1e63 ] + +Add queue wraparound prevention in quanta configuration. +Ensure end_qid does not overflow by validating start_qid and num_queues. + +Fixes: 015307754a19 ("ice: Support VF queue rate limit and quanta size configuration") +Reviewed-by: Jedrzej Jagielski +Reviewed-by: Simon Horman +Signed-off-by: Jan Glaza +Signed-off-by: Martyna Szapar-Mudlaw +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_virtchnl.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c +index 346aee373ccd4..df13f5110168d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c ++++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c +@@ -1900,13 +1900,21 @@ static int ice_vc_cfg_q_bw(struct ice_vf *vf, u8 *msg) + */ + static int ice_vc_cfg_q_quanta(struct ice_vf *vf, u8 *msg) + { ++ u16 quanta_prof_id, quanta_size, start_qid, num_queues, end_qid, i; + enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; +- u16 quanta_prof_id, quanta_size, start_qid, end_qid, i; + struct virtchnl_quanta_cfg *qquanta = + (struct virtchnl_quanta_cfg *)msg; + struct ice_vsi *vsi; + int ret; + ++ start_qid = qquanta->queue_select.start_queue_id; ++ num_queues = qquanta->queue_select.num_queues; ++ ++ if (check_add_overflow(start_qid, num_queues, &end_qid)) { ++ v_ret = VIRTCHNL_STATUS_ERR_PARAM; ++ goto err; ++ } ++ + if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { + v_ret = VIRTCHNL_STATUS_ERR_PARAM; + goto err; +@@ -1918,8 +1926,6 @@ static int ice_vc_cfg_q_quanta(struct ice_vf *vf, u8 *msg) + goto err; + } + +- end_qid = qquanta->queue_select.start_queue_id + +- qquanta->queue_select.num_queues; + if (end_qid > ICE_MAX_RSS_QS_PER_VF || + end_qid > min_t(u16, vsi->alloc_txq, vsi->alloc_rxq)) { + dev_err(ice_pf_to_dev(vf->pf), "VF-%d trying to configure more than allocated number of queues: %d\n", +@@ -1948,7 +1954,6 @@ static int ice_vc_cfg_q_quanta(struct ice_vf *vf, u8 *msg) + goto err; + } + +- start_qid = qquanta->queue_select.start_queue_id; + for (i = start_qid; i < end_qid; i++) + vsi->tx_rings[i]->quanta_prof_id = quanta_prof_id; + +-- +2.39.5 + diff --git a/queue-6.14/idpf-check-error-for-register_netdev-on-init.patch b/queue-6.14/idpf-check-error-for-register_netdev-on-init.patch new file mode 100644 index 0000000000..9cf0b896f8 --- /dev/null +++ b/queue-6.14/idpf-check-error-for-register_netdev-on-init.patch @@ -0,0 +1,102 @@ +From c511988b2e591381dfe94def5f54aa661b388325 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 09:18:16 -0800 +Subject: idpf: check error for register_netdev() on init + +From: Emil Tantilov + +[ Upstream commit 680811c67906191b237bbafe7dabbbad64649b39 ] + +Current init logic ignores the error code from register_netdev(), +which will cause WARN_ON() on attempt to unregister it, if there was one, +and there is no info for the user that the creation of the netdev failed. + +WARNING: CPU: 89 PID: 6902 at net/core/dev.c:11512 unregister_netdevice_many_notify+0x211/0x1a10 +... +[ 3707.563641] unregister_netdev+0x1c/0x30 +[ 3707.563656] idpf_vport_dealloc+0x5cf/0xce0 [idpf] +[ 3707.563684] idpf_deinit_task+0xef/0x160 [idpf] +[ 3707.563712] idpf_vc_core_deinit+0x84/0x320 [idpf] +[ 3707.563739] idpf_remove+0xbf/0x780 [idpf] +[ 3707.563769] pci_device_remove+0xab/0x1e0 +[ 3707.563786] device_release_driver_internal+0x371/0x530 +[ 3707.563803] driver_detach+0xbf/0x180 +[ 3707.563816] bus_remove_driver+0x11b/0x2a0 +[ 3707.563829] pci_unregister_driver+0x2a/0x250 + +Introduce an error check and log the vport number and error code. +On removal make sure to check VPORT_REG_NETDEV flag prior to calling +unregister and free on the netdev. + +Add local variables for idx, vport_config and netdev for readability. + +Fixes: 0fe45467a104 ("idpf: add create vport and netdev configuration") +Suggested-by: Tony Nguyen +Signed-off-by: Emil Tantilov +Reviewed-by: Simon Horman +Tested-by: Samuel Salin +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/idpf/idpf_lib.c | 31 +++++++++++++++------- + 1 file changed, 22 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c +index a3d6b8f198a86..a055a47449f12 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c ++++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c +@@ -927,15 +927,19 @@ static int idpf_stop(struct net_device *netdev) + static void idpf_decfg_netdev(struct idpf_vport *vport) + { + struct idpf_adapter *adapter = vport->adapter; ++ u16 idx = vport->idx; + + kfree(vport->rx_ptype_lkup); + vport->rx_ptype_lkup = NULL; + +- unregister_netdev(vport->netdev); +- free_netdev(vport->netdev); ++ if (test_and_clear_bit(IDPF_VPORT_REG_NETDEV, ++ adapter->vport_config[idx]->flags)) { ++ unregister_netdev(vport->netdev); ++ free_netdev(vport->netdev); ++ } + vport->netdev = NULL; + +- adapter->netdevs[vport->idx] = NULL; ++ adapter->netdevs[idx] = NULL; + } + + /** +@@ -1536,13 +1540,22 @@ void idpf_init_task(struct work_struct *work) + } + + for (index = 0; index < adapter->max_vports; index++) { +- if (adapter->netdevs[index] && +- !test_bit(IDPF_VPORT_REG_NETDEV, +- adapter->vport_config[index]->flags)) { +- register_netdev(adapter->netdevs[index]); +- set_bit(IDPF_VPORT_REG_NETDEV, +- adapter->vport_config[index]->flags); ++ struct net_device *netdev = adapter->netdevs[index]; ++ struct idpf_vport_config *vport_config; ++ ++ vport_config = adapter->vport_config[index]; ++ ++ if (!netdev || ++ test_bit(IDPF_VPORT_REG_NETDEV, vport_config->flags)) ++ continue; ++ ++ err = register_netdev(netdev); ++ if (err) { ++ dev_err(&pdev->dev, "failed to register netdev for vport %d: %pe\n", ++ index, ERR_PTR(err)); ++ continue; + } ++ set_bit(IDPF_VPORT_REG_NETDEV, vport_config->flags); + } + + /* As all the required vports are created, clear the reset flag +-- +2.39.5 + diff --git a/queue-6.14/idpf-fix-adapter-null-pointer-dereference-on-reboot.patch b/queue-6.14/idpf-fix-adapter-null-pointer-dereference-on-reboot.patch new file mode 100644 index 0000000000..990a51af36 --- /dev/null +++ b/queue-6.14/idpf-fix-adapter-null-pointer-dereference-on-reboot.patch @@ -0,0 +1,77 @@ +From de96bd25a69c0348bc1d53a3e6e0647d90ec0242 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 22:42:02 -0700 +Subject: idpf: fix adapter NULL pointer dereference on reboot + +From: Emil Tantilov + +[ Upstream commit 4c9106f4906a85f6b13542d862e423bcdc118cc3 ] + +With SRIOV enabled, idpf ends up calling into idpf_remove() twice. +First via idpf_shutdown() and then again when idpf_remove() calls into +sriov_disable(), because the VF devices use the idpf driver, hence the +same remove routine. When that happens, it is possible for the adapter +to be NULL from the first call to idpf_remove(), leading to a NULL +pointer dereference. + +echo 1 > /sys/class/net//device/sriov_numvfs +reboot + +BUG: kernel NULL pointer dereference, address: 0000000000000020 +... +RIP: 0010:idpf_remove+0x22/0x1f0 [idpf] +... +? idpf_remove+0x22/0x1f0 [idpf] +? idpf_remove+0x1e4/0x1f0 [idpf] +pci_device_remove+0x3f/0xb0 +device_release_driver_internal+0x19f/0x200 +pci_stop_bus_device+0x6d/0x90 +pci_stop_and_remove_bus_device+0x12/0x20 +pci_iov_remove_virtfn+0xbe/0x120 +sriov_disable+0x34/0xe0 +idpf_sriov_configure+0x58/0x140 [idpf] +idpf_remove+0x1b9/0x1f0 [idpf] +idpf_shutdown+0x12/0x30 [idpf] +pci_device_shutdown+0x35/0x60 +device_shutdown+0x156/0x200 +... + +Replace the direct idpf_remove() call in idpf_shutdown() with +idpf_vc_core_deinit() and idpf_deinit_dflt_mbx(), which perform +the bulk of the cleanup, such as stopping the init task, freeing IRQs, +destroying the vports and freeing the mailbox. This avoids the calls to +sriov_disable() in addition to a small netdev cleanup, and destroying +workqueues, which don't seem to be required on shutdown. + +Reported-by: Yuying Ma +Fixes: e850efed5e15 ("idpf: add module register and probe functionality") +Reviewed-by: Madhu Chittim +Signed-off-by: Emil Tantilov +Reviewed-by: Simon Horman +Tested-by: Samuel Salin +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/idpf/idpf_main.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/idpf/idpf_main.c b/drivers/net/ethernet/intel/idpf/idpf_main.c +index b6c515d14cbf0..bec4a02c53733 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_main.c ++++ b/drivers/net/ethernet/intel/idpf/idpf_main.c +@@ -87,7 +87,11 @@ static void idpf_remove(struct pci_dev *pdev) + */ + static void idpf_shutdown(struct pci_dev *pdev) + { +- idpf_remove(pdev); ++ struct idpf_adapter *adapter = pci_get_drvdata(pdev); ++ ++ cancel_delayed_work_sync(&adapter->vc_event_task); ++ idpf_vc_core_deinit(adapter); ++ idpf_deinit_dflt_mbx(adapter); + + if (system_state == SYSTEM_POWER_OFF) + pci_set_power_state(pdev, PCI_D3hot); +-- +2.39.5 + diff --git a/queue-6.14/igb-reject-invalid-external-timestamp-requests-for-8.patch b/queue-6.14/igb-reject-invalid-external-timestamp-requests-for-8.patch new file mode 100644 index 0000000000..5224875ec9 --- /dev/null +++ b/queue-6.14/igb-reject-invalid-external-timestamp-requests-for-8.patch @@ -0,0 +1,69 @@ +From 3e22a8e9eb75c01be9cd2063ce089dd54d0ba06d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 15:15:50 -0700 +Subject: igb: reject invalid external timestamp requests for 82580-based HW + +From: Jacob Keller + +[ Upstream commit 5eada2aabf13dcc4574b0a281b963b8cc55a52cc ] + +The igb_ptp_feature_enable_82580 function correctly checks that unknown +flags are not passed to the function. However, it does not actually check +PTP_RISING_EDGE or PTP_FALLING_EDGE when configuring the external timestamp +function. + +The data sheet for the 82580 product says: + + Upon a change in the input level of one of the SDP pins that was + configured to detect Time stamp events using the TSSDP register, a time + stamp of the system time is captured into one of the two auxiliary time + stamp registers (AUXSTMPL/H0 or AUXSTMPL/H1). + + For example to define timestamping of events in the AUXSTMPL0 and + AUXSTMPH0 registers, Software should: + + 1. Set the TSSDP.AUX0_SDP_SEL field to select the SDP pin that detects + the level change and set the TSSDP.AUX0_TS_SDP_EN bit to 1. + + 2. Set the TSAUXC.EN_TS0 bit to 1 to enable timestamping + +The same paragraph is in the i350 and i354 data sheets. + +The wording implies that the time stamps are captured at any level change. +There does not appear to be any way to only timestamp one edge of the +signal. + +Reject requests which do not set both PTP_RISING_EDGE and PTP_FALLING_EDGE +when operating under PTP_STRICT_FLAGS mode via PTP_EXTTS_REQUEST2. + +Fixes: 38970eac41db ("igb: support EXTTS on 82580/i354/i350") +Reviewed-by: Michal Swiatkowski +Signed-off-by: Jacob Keller +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250312-jk-net-fixes-supported-extts-flags-v2-1-ea930ba82459@intel.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/igb/igb_ptp.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c +index f945705561200..f323e1c1989f1 100644 +--- a/drivers/net/ethernet/intel/igb/igb_ptp.c ++++ b/drivers/net/ethernet/intel/igb/igb_ptp.c +@@ -509,6 +509,12 @@ static int igb_ptp_feature_enable_82580(struct ptp_clock_info *ptp, + PTP_STRICT_FLAGS)) + return -EOPNOTSUPP; + ++ /* Both the rising and falling edge are timestamped */ ++ if (rq->extts.flags & PTP_STRICT_FLAGS && ++ (rq->extts.flags & PTP_ENABLE_FEATURE) && ++ (rq->extts.flags & PTP_EXTTS_EDGES) != PTP_EXTTS_EDGES) ++ return -EOPNOTSUPP; ++ + if (on) { + pin = ptp_find_pin(igb->ptp_clock, PTP_PF_EXTTS, + rq->extts.index); +-- +2.39.5 + diff --git a/queue-6.14/igc-add-launch-time-support-to-xdp-zc.patch b/queue-6.14/igc-add-launch-time-support-to-xdp-zc.patch new file mode 100644 index 0000000000..c656efa751 --- /dev/null +++ b/queue-6.14/igc-add-launch-time-support-to-xdp-zc.patch @@ -0,0 +1,201 @@ +From 779e244ecc14a115bac09fa0029660315ee48b24 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Feb 2025 17:34:30 +0800 +Subject: igc: Add launch time support to XDP ZC + +From: Song Yoong Siang + +[ Upstream commit d7c3a7ff75028bea9e4879bd3dcd04a6dc3e33c8 ] + +Enable Launch Time Control (LTC) support for XDP zero copy via XDP Tx +metadata framework. + +This patch has been tested with tools/testing/selftests/bpf/xdp_hw_metadata +on Intel I225-LM Ethernet controller. Below are the test steps and result. + +Test 1: Send a single packet with the launch time set to 1 s in the future. + +Test steps: +1. On the DUT, start the xdp_hw_metadata selftest application: + $ sudo ./xdp_hw_metadata enp2s0 -l 1000000000 -L 1 + +2. On the Link Partner, send a UDP packet with VLAN priority 1 to port 9091 + of the DUT. + +Result: +When the launch time is set to 1 s in the future, the delta between the +launch time and the transmit hardware timestamp is 0.016 us, as shown in +printout of the xdp_hw_metadata application below. + 0x562ff5dc8880: rx_desc[4]->addr=84110 addr=84110 comp_addr=84110 EoP + rx_hash: 0xE343384 with RSS type:0x1 + HW RX-time: 1734578015467548904 (sec:1734578015.4675) + delta to User RX-time sec:0.0002 (183.103 usec) + XDP RX-time: 1734578015467651698 (sec:1734578015.4677) + delta to User RX-time sec:0.0001 (80.309 usec) + No rx_vlan_tci or rx_vlan_proto, err=-95 + 0x562ff5dc8880: ping-pong with csum=561c (want c7dd) + csum_start=34 csum_offset=6 + HW RX-time: 1734578015467548904 (sec:1734578015.4675) + delta to HW Launch-time sec:1.0000 (1000000.000 usec) + 0x562ff5dc8880: complete tx idx=4 addr=4018 + HW Launch-time: 1734578016467548904 (sec:1734578016.4675) + delta to HW TX-complete-time sec:0.0000 (0.016 usec) + HW TX-complete-time: 1734578016467548920 (sec:1734578016.4675) + delta to User TX-complete-time sec:0.0000 + (32.546 usec) + XDP RX-time: 1734578015467651698 (sec:1734578015.4677) + delta to User TX-complete-time sec:0.9999 + (999929.768 usec) + HW RX-time: 1734578015467548904 (sec:1734578015.4675) + delta to HW TX-complete-time sec:1.0000 (1000000.016 usec) + 0x562ff5dc8880: complete rx idx=132 addr=84110 + +Test 2: Send 1000 packets with a 10 ms interval and the launch time set to + 500 us in the future. + +Test steps: +1. On the DUT, start the xdp_hw_metadata selftest application: + $ sudo chrt -f 99 ./xdp_hw_metadata enp2s0 -l 500000 -L 1 > \ + /dev/shm/result.log + +2. On the Link Partner, send 1000 UDP packets with a 10 ms interval and + VLAN priority 1 to port 9091 of the DUT. + +Result: +When the launch time is set to 500 us in the future, the average delta +between the launch time and the transmit hardware timestamp is 0.016 us, +as shown in the analysis of /dev/shm/result.log below. The XDP launch time +works correctly in sending 1000 packets continuously. + Min delta: 0.005 us + Avr delta: 0.016 us + Max delta: 0.031 us + Total packets forwarded: 1000 + +Signed-off-by: Song Yoong Siang +Signed-off-by: Martin KaFai Lau +Reviewed-by: Faizal Rahim +Reviewed-by: Maciej Fijalkowski +Link: https://patch.msgid.link/20250216093430.957880-6-yoong.siang.song@intel.com +Stable-dep-of: d931cf9b38da ("igc: Fix TX drops in XDP ZC") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/igc/igc.h | 1 + + drivers/net/ethernet/intel/igc/igc_main.c | 61 ++++++++++++++++++++++- + 2 files changed, 60 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h +index b8111ad9a9a83..cd1d7b6c17823 100644 +--- a/drivers/net/ethernet/intel/igc/igc.h ++++ b/drivers/net/ethernet/intel/igc/igc.h +@@ -579,6 +579,7 @@ struct igc_metadata_request { + struct xsk_tx_metadata *meta; + struct igc_ring *tx_ring; + u32 cmd_type; ++ u16 used_desc; + }; + + struct igc_q_vector { +diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c +index 1bfa71545e371..3044392e8ded8 100644 +--- a/drivers/net/ethernet/intel/igc/igc_main.c ++++ b/drivers/net/ethernet/intel/igc/igc_main.c +@@ -2971,9 +2971,48 @@ static u64 igc_xsk_fill_timestamp(void *_priv) + return *(u64 *)_priv; + } + ++static void igc_xsk_request_launch_time(u64 launch_time, void *_priv) ++{ ++ struct igc_metadata_request *meta_req = _priv; ++ struct igc_ring *tx_ring = meta_req->tx_ring; ++ __le32 launch_time_offset; ++ bool insert_empty = false; ++ bool first_flag = false; ++ u16 used_desc = 0; ++ ++ if (!tx_ring->launchtime_enable) ++ return; ++ ++ launch_time_offset = igc_tx_launchtime(tx_ring, ++ ns_to_ktime(launch_time), ++ &first_flag, &insert_empty); ++ if (insert_empty) { ++ /* Disregard the launch time request if the required empty frame ++ * fails to be inserted. ++ */ ++ if (igc_insert_empty_frame(tx_ring)) ++ return; ++ ++ meta_req->tx_buffer = ++ &tx_ring->tx_buffer_info[tx_ring->next_to_use]; ++ /* Inserting an empty packet requires two descriptors: ++ * one data descriptor and one context descriptor. ++ */ ++ used_desc += 2; ++ } ++ ++ /* Use one context descriptor to specify launch time and first flag. */ ++ igc_tx_ctxtdesc(tx_ring, launch_time_offset, first_flag, 0, 0, 0); ++ used_desc += 1; ++ ++ /* Update the number of used descriptors in this request */ ++ meta_req->used_desc += used_desc; ++} ++ + const struct xsk_tx_metadata_ops igc_xsk_tx_metadata_ops = { + .tmo_request_timestamp = igc_xsk_request_timestamp, + .tmo_fill_timestamp = igc_xsk_fill_timestamp, ++ .tmo_request_launch_time = igc_xsk_request_launch_time, + }; + + static void igc_xdp_xmit_zc(struct igc_ring *ring) +@@ -2996,7 +3035,13 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring) + ntu = ring->next_to_use; + budget = igc_desc_unused(ring); + +- while (xsk_tx_peek_desc(pool, &xdp_desc) && budget--) { ++ /* Packets with launch time require one data descriptor and one context ++ * descriptor. When the launch time falls into the next Qbv cycle, we ++ * may need to insert an empty packet, which requires two more ++ * descriptors. Therefore, to be safe, we always ensure we have at least ++ * 4 descriptors available. ++ */ ++ while (xsk_tx_peek_desc(pool, &xdp_desc) && budget >= 4) { + struct igc_metadata_request meta_req; + struct xsk_tx_metadata *meta = NULL; + struct igc_tx_buffer *bi; +@@ -3017,9 +3062,19 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring) + meta_req.tx_ring = ring; + meta_req.tx_buffer = bi; + meta_req.meta = meta; ++ meta_req.used_desc = 0; + xsk_tx_metadata_request(meta, &igc_xsk_tx_metadata_ops, + &meta_req); + ++ /* xsk_tx_metadata_request() may have updated next_to_use */ ++ ntu = ring->next_to_use; ++ ++ /* xsk_tx_metadata_request() may have updated Tx buffer info */ ++ bi = meta_req.tx_buffer; ++ ++ /* xsk_tx_metadata_request() may use a few descriptors */ ++ budget -= meta_req.used_desc; ++ + tx_desc = IGC_TX_DESC(ring, ntu); + tx_desc->read.cmd_type_len = cpu_to_le32(meta_req.cmd_type); + tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status); +@@ -3037,9 +3092,11 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring) + ntu++; + if (ntu == ring->count) + ntu = 0; ++ ++ ring->next_to_use = ntu; ++ budget--; + } + +- ring->next_to_use = ntu; + if (tx_desc) { + igc_flush_tx_descriptors(ring); + xsk_tx_release(pool); +-- +2.39.5 + diff --git a/queue-6.14/igc-fix-tx-drops-in-xdp-zc.patch b/queue-6.14/igc-fix-tx-drops-in-xdp-zc.patch new file mode 100644 index 0000000000..a4ffeccb29 --- /dev/null +++ b/queue-6.14/igc-fix-tx-drops-in-xdp-zc.patch @@ -0,0 +1,45 @@ +From 928274876bc4146e60394944459cfbb3ee3458bc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 15:18:48 +0100 +Subject: igc: Fix TX drops in XDP ZC + +From: Zdenek Bouska + +[ Upstream commit d931cf9b38da0f533cacfe51c863a9912e67822f ] + +Fixes TX frame drops in AF_XDP zero copy mode when budget < 4. +xsk_tx_peek_desc() consumed TX frame and it was ignored because of +low budget. Not even AF_XDP completion was done for dropped frames. + +It can be reproduced on i226 by sending 100000x 60 B frames with +launch time set to minimal IPG (672 ns between starts of frames) +on 1Gbit/s. Always 1026 frames are not sent and are missing a +completion. + +Fixes: 9acf59a752d4c ("igc: Enable TX via AF_XDP zero-copy") +Signed-off-by: Zdenek Bouska +Reviewed-by: Song Yoong Siang +Reviewed-by: Florian Bezdeka +Tested-by: Mor Bar-Gabay +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/igc/igc_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c +index 3044392e8ded8..706dd26d4dde2 100644 +--- a/drivers/net/ethernet/intel/igc/igc_main.c ++++ b/drivers/net/ethernet/intel/igc/igc_main.c +@@ -3041,7 +3041,7 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring) + * descriptors. Therefore, to be safe, we always ensure we have at least + * 4 descriptors available. + */ +- while (xsk_tx_peek_desc(pool, &xdp_desc) && budget >= 4) { ++ while (budget >= 4 && xsk_tx_peek_desc(pool, &xdp_desc)) { + struct igc_metadata_request meta_req; + struct xsk_tx_metadata *meta = NULL; + struct igc_tx_buffer *bi; +-- +2.39.5 + diff --git a/queue-6.14/igc-refactor-empty-frame-insertion-for-launch-time-s.patch b/queue-6.14/igc-refactor-empty-frame-insertion-for-launch-time-s.patch new file mode 100644 index 0000000000..62216ee3c3 --- /dev/null +++ b/queue-6.14/igc-refactor-empty-frame-insertion-for-launch-time-s.patch @@ -0,0 +1,175 @@ +From a9a4d19bcd879931f3668a3636b156fa0bc7d290 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Feb 2025 17:34:29 +0800 +Subject: igc: Refactor empty frame insertion for launch time support + +From: Song Yoong Siang + +[ Upstream commit f9b53bb13923f0a6ed2e784a35301cfb4c28f4f4 ] + +Refactor the code for inserting an empty frame into a new function +igc_insert_empty_frame(). This change extracts the logic for inserting +an empty packet from igc_xmit_frame_ring() into a separate function, +allowing it to be reused in future implementations, such as the XDP +zero copy transmit function. + +Remove the igc_desc_unused() checking in igc_init_tx_empty_descriptor() +because the number of descriptors needed is guaranteed. + +Ensure that skb allocation and DMA mapping work for the empty frame, +before proceeding to fill in igc_tx_buffer info, context descriptor, +and data descriptor. + +Rate limit the error messages for skb allocation and DMA mapping failures. + +Update the comment to indicate that the 2 descriptors needed by the empty +frame are already taken into consideration in igc_xmit_frame_ring(). + +Handle the case where the insertion of an empty frame fails and explain +the reason behind this handling. + +Signed-off-by: Song Yoong Siang +Signed-off-by: Martin KaFai Lau +Reviewed-by: Faizal Rahim +Reviewed-by: Maciej Fijalkowski +Link: https://patch.msgid.link/20250216093430.957880-5-yoong.siang.song@intel.com +Stable-dep-of: d931cf9b38da ("igc: Fix TX drops in XDP ZC") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/igc/igc_main.c | 82 ++++++++++++++--------- + 1 file changed, 50 insertions(+), 32 deletions(-) + +diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c +index 84307bb7313e0..1bfa71545e371 100644 +--- a/drivers/net/ethernet/intel/igc/igc_main.c ++++ b/drivers/net/ethernet/intel/igc/igc_main.c +@@ -1092,7 +1092,8 @@ static int igc_init_empty_frame(struct igc_ring *ring, + + dma = dma_map_single(ring->dev, skb->data, size, DMA_TO_DEVICE); + if (dma_mapping_error(ring->dev, dma)) { +- netdev_err_once(ring->netdev, "Failed to map DMA for TX\n"); ++ net_err_ratelimited("%s: DMA mapping error for empty frame\n", ++ netdev_name(ring->netdev)); + return -ENOMEM; + } + +@@ -1108,20 +1109,12 @@ static int igc_init_empty_frame(struct igc_ring *ring, + return 0; + } + +-static int igc_init_tx_empty_descriptor(struct igc_ring *ring, +- struct sk_buff *skb, +- struct igc_tx_buffer *first) ++static void igc_init_tx_empty_descriptor(struct igc_ring *ring, ++ struct sk_buff *skb, ++ struct igc_tx_buffer *first) + { + union igc_adv_tx_desc *desc; + u32 cmd_type, olinfo_status; +- int err; +- +- if (!igc_desc_unused(ring)) +- return -EBUSY; +- +- err = igc_init_empty_frame(ring, first, skb); +- if (err) +- return err; + + cmd_type = IGC_ADVTXD_DTYP_DATA | IGC_ADVTXD_DCMD_DEXT | + IGC_ADVTXD_DCMD_IFCS | IGC_TXD_DCMD | +@@ -1140,8 +1133,6 @@ static int igc_init_tx_empty_descriptor(struct igc_ring *ring, + ring->next_to_use++; + if (ring->next_to_use == ring->count) + ring->next_to_use = 0; +- +- return 0; + } + + #define IGC_EMPTY_FRAME_SIZE 60 +@@ -1567,6 +1558,40 @@ static bool igc_request_tx_tstamp(struct igc_adapter *adapter, struct sk_buff *s + return false; + } + ++static int igc_insert_empty_frame(struct igc_ring *tx_ring) ++{ ++ struct igc_tx_buffer *empty_info; ++ struct sk_buff *empty_skb; ++ void *data; ++ int ret; ++ ++ empty_info = &tx_ring->tx_buffer_info[tx_ring->next_to_use]; ++ empty_skb = alloc_skb(IGC_EMPTY_FRAME_SIZE, GFP_ATOMIC); ++ if (unlikely(!empty_skb)) { ++ net_err_ratelimited("%s: skb alloc error for empty frame\n", ++ netdev_name(tx_ring->netdev)); ++ return -ENOMEM; ++ } ++ ++ data = skb_put(empty_skb, IGC_EMPTY_FRAME_SIZE); ++ memset(data, 0, IGC_EMPTY_FRAME_SIZE); ++ ++ /* Prepare DMA mapping and Tx buffer information */ ++ ret = igc_init_empty_frame(tx_ring, empty_info, empty_skb); ++ if (unlikely(ret)) { ++ dev_kfree_skb_any(empty_skb); ++ return ret; ++ } ++ ++ /* Prepare advanced context descriptor for empty packet */ ++ igc_tx_ctxtdesc(tx_ring, 0, false, 0, 0, 0); ++ ++ /* Prepare advanced data descriptor for empty packet */ ++ igc_init_tx_empty_descriptor(tx_ring, empty_skb, empty_info); ++ ++ return 0; ++} ++ + static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb, + struct igc_ring *tx_ring) + { +@@ -1586,6 +1611,7 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb, + * + 1 desc for skb_headlen/IGC_MAX_DATA_PER_TXD, + * + 2 desc gap to keep tail from touching head, + * + 1 desc for context descriptor, ++ * + 2 desc for inserting an empty packet for launch time, + * otherwise try next time + */ + for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) +@@ -1605,24 +1631,16 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb, + launch_time = igc_tx_launchtime(tx_ring, txtime, &first_flag, &insert_empty); + + if (insert_empty) { +- struct igc_tx_buffer *empty_info; +- struct sk_buff *empty; +- void *data; +- +- empty_info = &tx_ring->tx_buffer_info[tx_ring->next_to_use]; +- empty = alloc_skb(IGC_EMPTY_FRAME_SIZE, GFP_ATOMIC); +- if (!empty) +- goto done; +- +- data = skb_put(empty, IGC_EMPTY_FRAME_SIZE); +- memset(data, 0, IGC_EMPTY_FRAME_SIZE); +- +- igc_tx_ctxtdesc(tx_ring, 0, false, 0, 0, 0); +- +- if (igc_init_tx_empty_descriptor(tx_ring, +- empty, +- empty_info) < 0) +- dev_kfree_skb_any(empty); ++ /* Reset the launch time if the required empty frame fails to ++ * be inserted. However, this packet is not dropped, so it ++ * "dirties" the current Qbv cycle. This ensures that the ++ * upcoming packet, which is scheduled in the next Qbv cycle, ++ * does not require an empty frame. This way, the launch time ++ * continues to function correctly despite the current failure ++ * to insert the empty frame. ++ */ ++ if (igc_insert_empty_frame(tx_ring)) ++ launch_time = 0; + } + + done: +-- +2.39.5 + diff --git a/queue-6.14/iio-accel-mma8452-ensure-error-return-on-failure-to-.patch b/queue-6.14/iio-accel-mma8452-ensure-error-return-on-failure-to-.patch new file mode 100644 index 0000000000..2a122f15ce --- /dev/null +++ b/queue-6.14/iio-accel-mma8452-ensure-error-return-on-failure-to-.patch @@ -0,0 +1,61 @@ +From baf6af1e72284e02414b240916319e1ab58fd98b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:01:28 +0000 +Subject: iio: accel: mma8452: Ensure error return on failure to matching + oversampling ratio + +From: Jonathan Cameron + +[ Upstream commit df330c808182a8beab5d0f84a6cbc9cff76c61fc ] + +If a match was not found, then the write_raw() callback would return +the odr index, not an error. Return -EINVAL if this occurs. +To avoid similar issues in future, introduce j, a new indexing variable +rather than using ret for this purpose. + +Fixes: 79de2ee469aa ("iio: accel: mma8452: claim direct mode during write raw") +Reviewed-by: David Lechner +Link: https://patch.msgid.link/20250217140135.896574-2-jic23@kernel.org +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/accel/mma8452.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c +index 962d289065ab7..1b2014c4c4b46 100644 +--- a/drivers/iio/accel/mma8452.c ++++ b/drivers/iio/accel/mma8452.c +@@ -712,7 +712,7 @@ static int mma8452_write_raw(struct iio_dev *indio_dev, + int val, int val2, long mask) + { + struct mma8452_data *data = iio_priv(indio_dev); +- int i, ret; ++ int i, j, ret; + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) +@@ -772,14 +772,18 @@ static int mma8452_write_raw(struct iio_dev *indio_dev, + break; + + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: +- ret = mma8452_get_odr_index(data); ++ j = mma8452_get_odr_index(data); + + for (i = 0; i < ARRAY_SIZE(mma8452_os_ratio); i++) { +- if (mma8452_os_ratio[i][ret] == val) { ++ if (mma8452_os_ratio[i][j] == val) { + ret = mma8452_set_power_mode(data, i); + break; + } + } ++ if (i == ARRAY_SIZE(mma8452_os_ratio)) { ++ ret = -EINVAL; ++ break; ++ } + break; + default: + ret = -EINVAL; +-- +2.39.5 + diff --git a/queue-6.14/iio-accel-msa311-fix-failure-to-release-runtime-pm-i.patch b/queue-6.14/iio-accel-msa311-fix-failure-to-release-runtime-pm-i.patch new file mode 100644 index 0000000000..0e0c8276f6 --- /dev/null +++ b/queue-6.14/iio-accel-msa311-fix-failure-to-release-runtime-pm-i.patch @@ -0,0 +1,100 @@ +From b979021fbbb51e3282b4aafd6df293db73b9e0dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:01:33 +0000 +Subject: iio: accel: msa311: Fix failure to release runtime pm if direct mode + claim fails. + +From: Jonathan Cameron + +[ Upstream commit 60a0cf2ebab92011055ab7db6553c0fc3c546938 ] + +Reorder the claiming of direct mode and runtime pm calls to simplify +handling a little. For correct error handling, after the reorder +iio_device_release_direct_mode() must be claimed in an error occurs +in pm_runtime_resume_and_get() + +Fixes: 1ca2cfbc0c33 ("iio: add MEMSensing MSA311 3-axis accelerometer driver") +Reviewed-by: David Lechner +Link: https://patch.msgid.link/20250217140135.896574-7-jic23@kernel.org +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/accel/msa311.c | 26 +++++++++++++++----------- + 1 file changed, 15 insertions(+), 11 deletions(-) + +diff --git a/drivers/iio/accel/msa311.c b/drivers/iio/accel/msa311.c +index e7fb860f32337..c2b05d1f7239a 100644 +--- a/drivers/iio/accel/msa311.c ++++ b/drivers/iio/accel/msa311.c +@@ -594,23 +594,25 @@ static int msa311_read_raw_data(struct iio_dev *indio_dev, + __le16 axis; + int err; + +- err = pm_runtime_resume_and_get(dev); ++ err = iio_device_claim_direct_mode(indio_dev); + if (err) + return err; + +- err = iio_device_claim_direct_mode(indio_dev); +- if (err) ++ err = pm_runtime_resume_and_get(dev); ++ if (err) { ++ iio_device_release_direct_mode(indio_dev); + return err; ++ } + + mutex_lock(&msa311->lock); + err = msa311_get_axis(msa311, chan, &axis); + mutex_unlock(&msa311->lock); + +- iio_device_release_direct_mode(indio_dev); +- + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + ++ iio_device_release_direct_mode(indio_dev); ++ + if (err) { + dev_err(dev, "can't get axis %s (%pe)\n", + chan->datasheet_name, ERR_PTR(err)); +@@ -756,10 +758,6 @@ static int msa311_write_samp_freq(struct iio_dev *indio_dev, int val, int val2) + unsigned int odr; + int err; + +- err = pm_runtime_resume_and_get(dev); +- if (err) +- return err; +- + /* + * Sampling frequency changing is prohibited when buffer mode is + * enabled, because sometimes MSA311 chip returns outliers during +@@ -769,6 +767,12 @@ static int msa311_write_samp_freq(struct iio_dev *indio_dev, int val, int val2) + if (err) + return err; + ++ err = pm_runtime_resume_and_get(dev); ++ if (err) { ++ iio_device_release_direct_mode(indio_dev); ++ return err; ++ } ++ + err = -EINVAL; + for (odr = 0; odr < ARRAY_SIZE(msa311_odr_table); odr++) + if (val == msa311_odr_table[odr].integral && +@@ -779,11 +783,11 @@ static int msa311_write_samp_freq(struct iio_dev *indio_dev, int val, int val2) + break; + } + +- iio_device_release_direct_mode(indio_dev); +- + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + ++ iio_device_release_direct_mode(indio_dev); ++ + if (err) + dev_err(dev, "can't update frequency (%pe)\n", ERR_PTR(err)); + +-- +2.39.5 + diff --git a/queue-6.14/iio-adc-ad4130-fix-comparison-of-channel-setups.patch b/queue-6.14/iio-adc-ad4130-fix-comparison-of-channel-setups.patch new file mode 100644 index 0000000000..e016bb127f --- /dev/null +++ b/queue-6.14/iio-adc-ad4130-fix-comparison-of-channel-setups.patch @@ -0,0 +1,109 @@ +From 6c242ca8191713f6d36b3d3c3e7966eb534dd461 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 12:47:00 +0100 +Subject: iio: adc: ad4130: Fix comparison of channel setups +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 280acb19824663d55a3f4d09087c76fabe86fa3c ] + +Checking the binary representation of two structs (of the same type) +for equality doesn't have the same semantic as comparing all members for +equality. The former might find a difference where the latter doesn't in +the presence of padding or when ambiguous types like float or bool are +involved. (Floats typically have different representations for single +values, like -0.0 vs +0.0, or 0.5 * 2² vs 0.25 * 2³. The type bool has +at least 8 bits and the raw values 1 and 2 (probably) both evaluate to +true, but memcmp finds a difference.) + +When searching for a channel that already has the configuration we need, +the comparison by member is the one that is needed. + +Convert the comparison accordingly to compare the members one after +another. Also add a static_assert guard to (somewhat) ensure that when +struct ad4130_setup_info is expanded, the comparison is adapted, too. + +This issue is somewhat theoretic, but using memcmp() on a struct is a +bad pattern that is worth fixing. + +Fixes: 62094060cf3a ("iio: adc: ad4130: add AD4130 driver") +Signed-off-by: Uwe Kleine-König +Link: https://patch.msgid.link/20250303114659.1672695-12-u.kleine-koenig@baylibre.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/ad4130.c | 41 ++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 39 insertions(+), 2 deletions(-) + +diff --git a/drivers/iio/adc/ad4130.c b/drivers/iio/adc/ad4130.c +index de32cc9d18c5e..712f95f53c9ec 100644 +--- a/drivers/iio/adc/ad4130.c ++++ b/drivers/iio/adc/ad4130.c +@@ -223,6 +223,10 @@ enum ad4130_pin_function { + AD4130_PIN_FN_VBIAS = BIT(3), + }; + ++/* ++ * If you make adaptations in this struct, you most likely also have to adapt ++ * ad4130_setup_info_eq(), too. ++ */ + struct ad4130_setup_info { + unsigned int iout0_val; + unsigned int iout1_val; +@@ -591,6 +595,40 @@ static irqreturn_t ad4130_irq_handler(int irq, void *private) + return IRQ_HANDLED; + } + ++static bool ad4130_setup_info_eq(struct ad4130_setup_info *a, ++ struct ad4130_setup_info *b) ++{ ++ /* ++ * This is just to make sure that the comparison is adapted after ++ * struct ad4130_setup_info was changed. ++ */ ++ static_assert(sizeof(*a) == ++ sizeof(struct { ++ unsigned int iout0_val; ++ unsigned int iout1_val; ++ unsigned int burnout; ++ unsigned int pga; ++ unsigned int fs; ++ u32 ref_sel; ++ enum ad4130_filter_mode filter_mode; ++ bool ref_bufp; ++ bool ref_bufm; ++ })); ++ ++ if (a->iout0_val != b->iout0_val || ++ a->iout1_val != b->iout1_val || ++ a->burnout != b->burnout || ++ a->pga != b->pga || ++ a->fs != b->fs || ++ a->ref_sel != b->ref_sel || ++ a->filter_mode != b->filter_mode || ++ a->ref_bufp != b->ref_bufp || ++ a->ref_bufm != b->ref_bufm) ++ return false; ++ ++ return true; ++} ++ + static int ad4130_find_slot(struct ad4130_state *st, + struct ad4130_setup_info *target_setup_info, + unsigned int *slot, bool *overwrite) +@@ -604,8 +642,7 @@ static int ad4130_find_slot(struct ad4130_state *st, + struct ad4130_slot_info *slot_info = &st->slots_info[i]; + + /* Immediately accept a matching setup info. */ +- if (!memcmp(target_setup_info, &slot_info->setup, +- sizeof(*target_setup_info))) { ++ if (ad4130_setup_info_eq(target_setup_info, &slot_info->setup)) { + *slot = i; + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/iio-adc-ad7124-fix-comparison-of-channel-configs.patch b/queue-6.14/iio-adc-ad7124-fix-comparison-of-channel-configs.patch new file mode 100644 index 0000000000..c0a50f4598 --- /dev/null +++ b/queue-6.14/iio-adc-ad7124-fix-comparison-of-channel-configs.patch @@ -0,0 +1,103 @@ +From 5c50a9993601d5f6e06d1794956615f78b705ca9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 12:47:01 +0100 +Subject: iio: adc: ad7124: Fix comparison of channel configs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 05a5d874f7327b75e9bc4359618017e047cc129c ] + +Checking the binary representation of two structs (of the same type) +for equality doesn't have the same semantic as comparing all members for +equality. The former might find a difference where the latter doesn't in +the presence of padding or when ambiguous types like float or bool are +involved. (Floats typically have different representations for single +values, like -0.0 vs +0.0, or 0.5 * 2² vs 0.25 * 2³. The type bool has +at least 8 bits and the raw values 1 and 2 (probably) both evaluate to +true, but memcmp finds a difference.) + +When searching for a channel that already has the configuration we need, +the comparison by member is the one that is needed. + +Convert the comparison accordingly to compare the members one after +another. Also add a static_assert guard to (somewhat) ensure that when +struct ad7124_channel_config::config_props is expanded, the comparison +is adapted, too. + +This issue is somewhat theoretic, but using memcmp() on a struct is a +bad pattern that is worth fixing. + +Fixes: 7b8d045e497a ("iio: adc: ad7124: allow more than 8 channels") +Signed-off-by: Uwe Kleine-König +Link: https://patch.msgid.link/20250303114659.1672695-13-u.kleine-koenig@baylibre.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/ad7124.c | 35 +++++++++++++++++++++++++++++++---- + 1 file changed, 31 insertions(+), 4 deletions(-) + +diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c +index 6bc418d388202..de90ecb5f6307 100644 +--- a/drivers/iio/adc/ad7124.c ++++ b/drivers/iio/adc/ad7124.c +@@ -151,7 +151,11 @@ struct ad7124_chip_info { + struct ad7124_channel_config { + bool live; + unsigned int cfg_slot; +- /* Following fields are used to compare equality. */ ++ /* ++ * Following fields are used to compare for equality. If you ++ * make adaptations in it, you most likely also have to adapt ++ * ad7124_find_similar_live_cfg(), too. ++ */ + struct_group(config_props, + enum ad7124_ref_sel refsel; + bool bipolar; +@@ -338,15 +342,38 @@ static struct ad7124_channel_config *ad7124_find_similar_live_cfg(struct ad7124_ + struct ad7124_channel_config *cfg) + { + struct ad7124_channel_config *cfg_aux; +- ptrdiff_t cmp_size; + int i; + +- cmp_size = sizeof_field(struct ad7124_channel_config, config_props); ++ /* ++ * This is just to make sure that the comparison is adapted after ++ * struct ad7124_channel_config was changed. ++ */ ++ static_assert(sizeof_field(struct ad7124_channel_config, config_props) == ++ sizeof(struct { ++ enum ad7124_ref_sel refsel; ++ bool bipolar; ++ bool buf_positive; ++ bool buf_negative; ++ unsigned int vref_mv; ++ unsigned int pga_bits; ++ unsigned int odr; ++ unsigned int odr_sel_bits; ++ unsigned int filter_type; ++ })); ++ + for (i = 0; i < st->num_channels; i++) { + cfg_aux = &st->channels[i].cfg; + + if (cfg_aux->live && +- !memcmp(&cfg->config_props, &cfg_aux->config_props, cmp_size)) ++ cfg->refsel == cfg_aux->refsel && ++ cfg->bipolar == cfg_aux->bipolar && ++ cfg->buf_positive == cfg_aux->buf_positive && ++ cfg->buf_negative == cfg_aux->buf_negative && ++ cfg->vref_mv == cfg_aux->vref_mv && ++ cfg->pga_bits == cfg_aux->pga_bits && ++ cfg->odr == cfg_aux->odr && ++ cfg->odr_sel_bits == cfg_aux->odr_sel_bits && ++ cfg->filter_type == cfg_aux->filter_type) + return cfg_aux; + } + +-- +2.39.5 + diff --git a/queue-6.14/iio-adc-ad7124-micro-optimize-channel-disabling.patch b/queue-6.14/iio-adc-ad7124-micro-optimize-channel-disabling.patch new file mode 100644 index 0000000000..dad3cfd968 --- /dev/null +++ b/queue-6.14/iio-adc-ad7124-micro-optimize-channel-disabling.patch @@ -0,0 +1,78 @@ +From 0a1462729ef7d48616c20a90278147b2ac3ec272 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jan 2025 15:07:09 +0100 +Subject: iio: adc: ad7124: Micro-optimize channel disabling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit cf67879bd4280f6243103e281595f9b523c61481 ] + +The key objective in ad7124_disable_one() is clearing the +AD7124_CHANNEL_EN_MSK bit in the channel register. However there is no +advantage to keep the other bits in that register because when the +channel is used next time, all fields are rewritten anyhow. So instead +of using ad7124_spi_write_mask() (which is a register read plus a +register write) use a simple register write clearing the complete +register. + +Also do the same in the .disable_all() callback by using the +.disable_one() callback there. + +Signed-off-by: Uwe Kleine-König +Reviewed-by: Nuno Sa +Link: https://patch.msgid.link/20250120140708.1093655-2-u.kleine-koenig@baylibre.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: e903868b4ce7 ("iio: adc: ad7124: Really disable all channels at probe time") +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/ad7124.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c +index 6ae27cdd32503..2fdeb32479522 100644 +--- a/drivers/iio/adc/ad7124.c ++++ b/drivers/iio/adc/ad7124.c +@@ -540,6 +540,14 @@ static int ad7124_append_status(struct ad_sigma_delta *sd, bool append) + return 0; + } + ++static int ad7124_disable_one(struct ad_sigma_delta *sd, unsigned int chan) ++{ ++ struct ad7124_state *st = container_of(sd, struct ad7124_state, sd); ++ ++ /* The relevant thing here is that AD7124_CHANNEL_EN_MSK is cleared. */ ++ return ad_sd_write_reg(&st->sd, AD7124_CHANNEL(chan), 2, 0); ++} ++ + static int ad7124_disable_all(struct ad_sigma_delta *sd) + { + struct ad7124_state *st = container_of(sd, struct ad7124_state, sd); +@@ -547,7 +555,7 @@ static int ad7124_disable_all(struct ad_sigma_delta *sd) + int i; + + for (i = 0; i < st->num_channels; i++) { +- ret = ad7124_spi_write_mask(st, AD7124_CHANNEL(i), AD7124_CHANNEL_EN_MSK, 0, 2); ++ ret = ad7124_disable_one(sd, i); + if (ret < 0) + return ret; + } +@@ -555,13 +563,6 @@ static int ad7124_disable_all(struct ad_sigma_delta *sd) + return 0; + } + +-static int ad7124_disable_one(struct ad_sigma_delta *sd, unsigned int chan) +-{ +- struct ad7124_state *st = container_of(sd, struct ad7124_state, sd); +- +- return ad7124_spi_write_mask(st, AD7124_CHANNEL(chan), AD7124_CHANNEL_EN_MSK, 0, 2); +-} +- + static const struct ad_sigma_delta_info ad7124_sigma_delta_info = { + .set_channel = ad7124_set_channel, + .append_status = ad7124_append_status, +-- +2.39.5 + diff --git a/queue-6.14/iio-adc-ad7124-really-disable-all-channels-at-probe-.patch b/queue-6.14/iio-adc-ad7124-really-disable-all-channels-at-probe-.patch new file mode 100644 index 0000000000..ebb3b7ae46 --- /dev/null +++ b/queue-6.14/iio-adc-ad7124-really-disable-all-channels-at-probe-.patch @@ -0,0 +1,66 @@ +From 8b16dee9690074fea48b670689a35e163784b156 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 12:50:23 +0100 +Subject: iio: adc: ad7124: Really disable all channels at probe time +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit e903868b4ce73d1ba3663d5e0718424946cebd99 ] + +If one or more of the 16 channels are enabled and the driver is not +aware of that, unexpected things happen because different channels are +used than intended. To prevent that, all channels should be disabled at +probe time. In Commit 4be339af334c ("iio: adc: ad7124: Disable all +channels at probe time") I intended do that, however only the channels +that are potentially used by the driver and not all channels are +disabled since then. So disable all 16 channels and not only the used +ones. + +Also fix the same issue in the .disable_all() callback. + +Fixes: 4be339af334c ("iio: adc: ad7124: Disable all channels at probe time") +Signed-off-by: Uwe Kleine-König +Link: https://patch.msgid.link/20250204115023.265813-2-u.kleine-koenig@baylibre.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/ad7124.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c +index 2fdeb32479522..6bc418d388202 100644 +--- a/drivers/iio/adc/ad7124.c ++++ b/drivers/iio/adc/ad7124.c +@@ -550,11 +550,10 @@ static int ad7124_disable_one(struct ad_sigma_delta *sd, unsigned int chan) + + static int ad7124_disable_all(struct ad_sigma_delta *sd) + { +- struct ad7124_state *st = container_of(sd, struct ad7124_state, sd); + int ret; + int i; + +- for (i = 0; i < st->num_channels; i++) { ++ for (i = 0; i < 16; i++) { + ret = ad7124_disable_one(sd, i); + if (ret < 0) + return ret; +@@ -1017,11 +1016,10 @@ static int ad7124_setup(struct ad7124_state *st) + * set all channels to this default value. + */ + ad7124_set_channel_odr(st, i, 10); +- +- /* Disable all channels to prevent unintended conversions. */ +- ad_sd_write_reg(&st->sd, AD7124_CHANNEL(i), 2, 0); + } + ++ ad7124_disable_all(&st->sd); ++ + ret = ad_sd_write_reg(&st->sd, AD7124_ADC_CONTROL, 2, st->adc_control); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to setup CONTROL register\n"); +-- +2.39.5 + diff --git a/queue-6.14/iio-adc-ad7173-fix-comparison-of-channel-configs.patch b/queue-6.14/iio-adc-ad7173-fix-comparison-of-channel-configs.patch new file mode 100644 index 0000000000..804bcb1137 --- /dev/null +++ b/queue-6.14/iio-adc-ad7173-fix-comparison-of-channel-configs.patch @@ -0,0 +1,93 @@ +From a7e40a234bdfa2e1b52398b5b77049f20c238175 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 12:47:02 +0100 +Subject: iio: adc: ad7173: Fix comparison of channel configs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 7b6033ed5a9e1a369a9cf58018388ae4c5f17e41 ] + +Checking the binary representation of two structs (of the same type) +for equality doesn't have the same semantic as comparing all members for +equality. The former might find a difference where the latter doesn't in +the presence of padding or when ambiguous types like float or bool are +involved. (Floats typically have different representations for single +values, like -0.0 vs +0.0, or 0.5 * 2² vs 0.25 * 2³. The type bool has +at least 8 bits and the raw values 1 and 2 (probably) both evaluate to +true, but memcmp finds a difference.) + +When searching for a channel that already has the configuration we need, +the comparison by member is the one that is needed. + +Convert the comparison accordingly to compare the members one after +another. Also add a static_assert guard to (somewhat) ensure that when +struct ad7173_channel_config::config_props is expanded, the comparison +is adapted, too. + +This issue is somewhat theoretic, but using memcmp() on a struct is a +bad pattern that is worth fixing. + +Fixes: 76a1e6a42802 ("iio: adc: ad7173: add AD7173 driver") +Signed-off-by: Uwe Kleine-König +Link: https://patch.msgid.link/20250303114659.1672695-14-u.kleine-koenig@baylibre.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/ad7173.c | 25 +++++++++++++++++++++---- + 1 file changed, 21 insertions(+), 4 deletions(-) + +diff --git a/drivers/iio/adc/ad7173.c b/drivers/iio/adc/ad7173.c +index 6645a811764fd..4f8810e35a8d1 100644 +--- a/drivers/iio/adc/ad7173.c ++++ b/drivers/iio/adc/ad7173.c +@@ -189,7 +189,11 @@ struct ad7173_channel_config { + u8 cfg_slot; + bool live; + +- /* Following fields are used to compare equality. */ ++ /* ++ * Following fields are used to compare equality. If you ++ * make adaptations in it, you most likely also have to adapt ++ * ad7173_find_live_config(), too. ++ */ + struct_group(config_props, + bool bipolar; + bool input_buf; +@@ -717,15 +721,28 @@ static struct ad7173_channel_config * + ad7173_find_live_config(struct ad7173_state *st, struct ad7173_channel_config *cfg) + { + struct ad7173_channel_config *cfg_aux; +- ptrdiff_t cmp_size; + int i; + +- cmp_size = sizeof_field(struct ad7173_channel_config, config_props); ++ /* ++ * This is just to make sure that the comparison is adapted after ++ * struct ad7173_channel_config was changed. ++ */ ++ static_assert(sizeof_field(struct ad7173_channel_config, config_props) == ++ sizeof(struct { ++ bool bipolar; ++ bool input_buf; ++ u8 odr; ++ u8 ref_sel; ++ })); ++ + for (i = 0; i < st->num_channels; i++) { + cfg_aux = &st->channels[i].cfg; + + if (cfg_aux->live && +- !memcmp(&cfg->config_props, &cfg_aux->config_props, cmp_size)) ++ cfg->bipolar == cfg_aux->bipolar && ++ cfg->input_buf == cfg_aux->input_buf && ++ cfg->odr == cfg_aux->odr && ++ cfg->ref_sel == cfg_aux->ref_sel) + return cfg_aux; + } + return NULL; +-- +2.39.5 + diff --git a/queue-6.14/iio-adc-ad7173-grab-direct-mode-for-calibration.patch b/queue-6.14/iio-adc-ad7173-grab-direct-mode-for-calibration.patch new file mode 100644 index 0000000000..5857c66ba8 --- /dev/null +++ b/queue-6.14/iio-adc-ad7173-grab-direct-mode-for-calibration.patch @@ -0,0 +1,52 @@ +From de973ee16cde1448747aed42a21bb388391ec966 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 12:35:27 +0100 +Subject: iio: adc: ad7173: Grab direct mode for calibration +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 7021d97fb89b216557561ca8cdf68144c016993b ] + +While a calibration is running, better don't make the device do anything +else. + +To enforce that, grab direct mode during calibration. + +Fixes: 031bdc8aee01 ("iio: adc: ad7173: add calibration support") +Signed-off-by: Uwe Kleine-König +Link: https://patch.msgid.link/8319fa2dc881c9899d60db4eba7fe8e984716617.1740655250.git.u.kleine-koenig@baylibre.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/ad7173.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/iio/adc/ad7173.c b/drivers/iio/adc/ad7173.c +index 6c4ed10ae580d..6645a811764fd 100644 +--- a/drivers/iio/adc/ad7173.c ++++ b/drivers/iio/adc/ad7173.c +@@ -559,6 +559,9 @@ static ssize_t ad7173_write_syscalib(struct iio_dev *indio_dev, + if (ret) + return ret; + ++ if (!iio_device_claim_direct(indio_dev)) ++ return -EBUSY; ++ + mode = st->channels[chan->channel].syscalib_mode; + if (sys_calib) { + if (mode == AD7173_SYSCALIB_ZERO_SCALE) +@@ -569,6 +572,8 @@ static ssize_t ad7173_write_syscalib(struct iio_dev *indio_dev, + chan->address); + } + ++ iio_device_release_direct(indio_dev); ++ + return ret ? : len; + } + +-- +2.39.5 + diff --git a/queue-6.14/iio-adc-ad7192-grab-direct-mode-for-calibration.patch b/queue-6.14/iio-adc-ad7192-grab-direct-mode-for-calibration.patch new file mode 100644 index 0000000000..7e4d290d15 --- /dev/null +++ b/queue-6.14/iio-adc-ad7192-grab-direct-mode-for-calibration.patch @@ -0,0 +1,52 @@ +From 6f2af463884aec45dc12e2d77599684bcd2d79fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 12:35:28 +0100 +Subject: iio: adc: ad7192: Grab direct mode for calibration +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 08808b3ef384974b1eaf4975de707f93f8cda62d ] + +While a calibration is running, better don't make the device do anything +else. + +To enforce that, grab direct mode during calibration. + +Fixes: 42776c14c692 ("staging: iio: adc: ad7192: Add system calibration support") +Signed-off-by: Uwe Kleine-König +Link: https://patch.msgid.link/8aade802afca6a89641e24c1ae1d4b8d82cff58d.1740655250.git.u.kleine-koenig@baylibre.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/ad7192.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c +index cfaf8f7e0a07d..1ebb738d99f57 100644 +--- a/drivers/iio/adc/ad7192.c ++++ b/drivers/iio/adc/ad7192.c +@@ -256,6 +256,9 @@ static ssize_t ad7192_write_syscalib(struct iio_dev *indio_dev, + if (ret) + return ret; + ++ if (!iio_device_claim_direct(indio_dev)) ++ return -EBUSY; ++ + temp = st->syscalib_mode[chan->channel]; + if (sys_calib) { + if (temp == AD7192_SYSCALIB_ZERO_SCALE) +@@ -266,6 +269,8 @@ static ssize_t ad7192_write_syscalib(struct iio_dev *indio_dev, + chan->address); + } + ++ iio_device_release_direct(indio_dev); ++ + return ret ? ret : len; + } + +-- +2.39.5 + diff --git a/queue-6.14/iio-adc-ad7768-1-set-mosi-idle-state-to-prevent-acci.patch b/queue-6.14/iio-adc-ad7768-1-set-mosi-idle-state-to-prevent-acci.patch new file mode 100644 index 0000000000..adb217df24 --- /dev/null +++ b/queue-6.14/iio-adc-ad7768-1-set-mosi-idle-state-to-prevent-acci.patch @@ -0,0 +1,55 @@ +From 91e734326f7edcdcee2b36fc9c26af0b4417b846 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 18:00:43 -0300 +Subject: iio: adc: ad7768-1: set MOSI idle state to prevent accidental reset + +From: Jonathan Santos + +[ Upstream commit 2416cec859299be04d021b4cf98eff814f345af7 ] + +Datasheet recommends Setting the MOSI idle state to high in order to +prevent accidental reset of the device when SCLK is free running. +This happens when the controller clocks out a 1 followed by 63 zeros +while the CS is held low. + +Check if SPI controller supports SPI_MOSI_IDLE_HIGH flag and set it. + +Fixes: a5f8c7da3dbe ("iio: adc: Add AD7768-1 ADC basic support") +Signed-off-by: Jonathan Santos +Reviewed-by: Marcelo Schmitt +Link: https://patch.msgid.link/c2a2b0f3d54829079763a5511359a1fa80516cfb.1741268122.git.Jonathan.Santos@analog.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/ad7768-1.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c +index 113703fb72454..6f8816483f1a0 100644 +--- a/drivers/iio/adc/ad7768-1.c ++++ b/drivers/iio/adc/ad7768-1.c +@@ -574,6 +574,21 @@ static int ad7768_probe(struct spi_device *spi) + return -ENOMEM; + + st = iio_priv(indio_dev); ++ /* ++ * Datasheet recommends SDI line to be kept high when data is not being ++ * clocked out of the controller and the spi clock is free running, ++ * to prevent accidental reset. ++ * Since many controllers do not support the SPI_MOSI_IDLE_HIGH flag ++ * yet, only request the MOSI idle state to enable if the controller ++ * supports it. ++ */ ++ if (spi->controller->mode_bits & SPI_MOSI_IDLE_HIGH) { ++ spi->mode |= SPI_MOSI_IDLE_HIGH; ++ ret = spi_setup(spi); ++ if (ret < 0) ++ return ret; ++ } ++ + st->spi = spi; + + st->vref = devm_regulator_get(&spi->dev, "vref"); +-- +2.39.5 + diff --git a/queue-6.14/iio-adc-ad_sigma_delta-disable-channel-after-calibra.patch b/queue-6.14/iio-adc-ad_sigma_delta-disable-channel-after-calibra.patch new file mode 100644 index 0000000000..865462bac2 --- /dev/null +++ b/queue-6.14/iio-adc-ad_sigma_delta-disable-channel-after-calibra.patch @@ -0,0 +1,48 @@ +From 3dffc6a9036ada018df64061807472a2dd6f32f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 12:46:59 +0100 +Subject: iio: adc: ad_sigma_delta: Disable channel after calibration +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit fb3a0811a7bc12d51cba4b75d6b123ab62e2fe4d ] + +The function ad_sd_calibrate() enables the channel to calibrate at +function entry but doesn't disable it on exit. This is problematic +because if two (or more) channels are calibrated in a row, the second +calibration isn't executed as intended as the first (still enabled) +channel is recalibrated and after the first irq (i.e. when the +calibration of the first channel completed) the calibration is aborted. + +This currently affects ad7173 only, as the other drivers using +ad_sd_calibrate() never have more than one channel enabled at a time. + +To fix this, disable the calibrated channel after calibration. + +Fixes: 031bdc8aee01 ("iio: adc: ad7173: add calibration support") +Signed-off-by: Uwe Kleine-König +Link: https://patch.msgid.link/20250303114659.1672695-11-u.kleine-koenig@baylibre.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/ad_sigma_delta.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c +index d5d81581ab340..77b4e8bc47485 100644 +--- a/drivers/iio/adc/ad_sigma_delta.c ++++ b/drivers/iio/adc/ad_sigma_delta.c +@@ -339,6 +339,7 @@ int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta, + out: + sigma_delta->keep_cs_asserted = false; + ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE); ++ ad_sigma_delta_disable_one(sigma_delta, channel); + sigma_delta->bus_locked = false; + spi_bus_unlock(sigma_delta->spi->controller); + +-- +2.39.5 + diff --git a/queue-6.14/iio-backend-make-sure-to-null-terminate-stack-buffer.patch b/queue-6.14/iio-backend-make-sure-to-null-terminate-stack-buffer.patch new file mode 100644 index 0000000000..02a885604b --- /dev/null +++ b/queue-6.14/iio-backend-make-sure-to-null-terminate-stack-buffer.patch @@ -0,0 +1,47 @@ +From 77965c4d7622c58203fcb5d89d32c926d5b526c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 10:31:25 +0000 +Subject: iio: backend: make sure to NULL terminate stack buffer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Nuno Sá + +[ Upstream commit 035b4989211dc1c8626e186d655ae8ca5141bb73 ] + +Make sure to NULL terminate the buffer in +iio_backend_debugfs_write_reg() before passing it to sscanf(). It is a +stack variable so we should not assume it will 0 initialized. + +Fixes: cdf01e0809a4 ("iio: backend: add debugFs interface") +Signed-off-by: Nuno Sá +Reviewed-by: David Lechner +Link: https://patch.msgid.link/20250218-dev-iio-misc-v1-1-bf72b20a1eb8@analog.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/industrialio-backend.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c +index 3632812720352..aa2b8b38ab587 100644 +--- a/drivers/iio/industrialio-backend.c ++++ b/drivers/iio/industrialio-backend.c +@@ -155,10 +155,12 @@ static ssize_t iio_backend_debugfs_write_reg(struct file *file, + ssize_t rc; + int ret; + +- rc = simple_write_to_buffer(buf, sizeof(buf), ppos, userbuf, count); ++ rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, userbuf, count); + if (rc < 0) + return rc; + ++ buf[count] = '\0'; ++ + ret = sscanf(buf, "%i %i", &back->cached_reg_addr, &val); + + switch (ret) { +-- +2.39.5 + diff --git a/queue-6.14/iio-core-rework-claim-and-release-of-direct-mode-to-.patch b/queue-6.14/iio-core-rework-claim-and-release-of-direct-mode-to-.patch new file mode 100644 index 0000000000..a6518ad71f --- /dev/null +++ b/queue-6.14/iio-core-rework-claim-and-release-of-direct-mode-to-.patch @@ -0,0 +1,94 @@ +From c23006d42aa42b17d9b9d7545a87f64eb3d7df91 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Feb 2025 18:05:58 +0000 +Subject: iio: core: Rework claim and release of direct mode to work with + sparse. + +From: Jonathan Cameron + +[ Upstream commit d795e38df4b7ebac1072bbf7d8a5500c1ea83332 ] + +Initial thought was to do something similar to __cond_lock() + + do_iio_device_claim_direct_mode(iio_dev) ? : ({ __acquire(iio_dev); 0; }) ++ Appropriate static inline iio_device_release_direct_mode() + +However with that, sparse generates false positives. E.g. + +drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c:1811:17: warning: context imbalance in 'st_lsm6dsx_read_raw' - unexpected unlock + +So instead, this patch rethinks the return type and makes it more +'conditional lock like' (which is part of what is going on under the hood +anyway) and return a boolean - true for successfully acquired, false for +did not acquire. + +To allow a migration path given the rework is now non trivial, take a leaf +out of the naming of the conditional guard we currently have for IIO +device direct mode and drop the _mode postfix from the new functions giving +iio_device_claim_direct() and iio_device_release_direct() + +Whilst the kernel supports __cond_acquires() upstream sparse does not +yet do so. Hence rely on sparse expanding a static inline wrapper +to explicitly see whether __acquire() is called. + +Note that even with the solution here, sparse sometimes gives false +positives. However in the few cases seen they were complex code +structures that benefited from simplification anyway. + +Reviewed-by: David Lechner +Reviewed-by: Nuno Sa +Link: https://patch.msgid.link/20250209180624.701140-2-jic23@kernel.org +Signed-off-by: Jonathan Cameron +Stable-dep-of: 7021d97fb89b ("iio: adc: ad7173: Grab direct mode for calibration") +Signed-off-by: Sasha Levin +--- + include/linux/iio/iio.h | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h +index 56161e02f002c..5ed03e36178fc 100644 +--- a/include/linux/iio/iio.h ++++ b/include/linux/iio/iio.h +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + /* IIO TODO LIST */ +@@ -662,6 +663,31 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp); + int iio_device_claim_direct_mode(struct iio_dev *indio_dev); + void iio_device_release_direct_mode(struct iio_dev *indio_dev); + ++/* ++ * Helper functions that allow claim and release of direct mode ++ * in a fashion that doesn't generate many false positives from sparse. ++ * Note this must remain static inline in the header so that sparse ++ * can see the __acquire() marking. Revisit when sparse supports ++ * __cond_acquires() ++ */ ++static inline bool iio_device_claim_direct(struct iio_dev *indio_dev) ++{ ++ int ret = iio_device_claim_direct_mode(indio_dev); ++ ++ if (ret) ++ return false; ++ ++ __acquire(iio_dev); ++ ++ return true; ++} ++ ++static inline void iio_device_release_direct(struct iio_dev *indio_dev) ++{ ++ iio_device_release_direct_mode(indio_dev); ++ __release(indio_dev); ++} ++ + /* + * This autocleanup logic is normally used via + * iio_device_claim_direct_scoped(). +-- +2.39.5 + diff --git a/queue-6.14/iio-dac-adi-axi-dac-modify-stream-enable.patch b/queue-6.14/iio-dac-adi-axi-dac-modify-stream-enable.patch new file mode 100644 index 0000000000..06db19d447 --- /dev/null +++ b/queue-6.14/iio-dac-adi-axi-dac-modify-stream-enable.patch @@ -0,0 +1,45 @@ +From 0637f17c1766845cfff8753a86d549a63cf7e761 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jan 2025 16:30:12 +0100 +Subject: iio: dac: adi-axi-dac: modify stream enable + +From: Angelo Dureghello + +[ Upstream commit 6cc60bc38e8428544f8f4f12ddb6cc05fc83a7da ] + +Change suggested from the AXI HDL team, modify the function +axi_dac_data_stream_enable() to check for interface busy, to avoid +possible issues when starting the stream. + +Fixes: e61d7178429a ("iio: dac: adi-axi-dac: extend features") +Reviewed-by: Nuno Sa +Signed-off-by: Angelo Dureghello +Link: https://patch.msgid.link/20250114-wip-bl-ad3552r-axi-v0-iio-testing-carlos-v4-3-979402e33545@baylibre.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/dac/adi-axi-dac.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c +index b143f7ed68472..ac871deb8063c 100644 +--- a/drivers/iio/dac/adi-axi-dac.c ++++ b/drivers/iio/dac/adi-axi-dac.c +@@ -585,6 +585,14 @@ static int axi_dac_ddr_disable(struct iio_backend *back) + static int axi_dac_data_stream_enable(struct iio_backend *back) + { + struct axi_dac_state *st = iio_backend_get_priv(back); ++ int ret, val; ++ ++ ret = regmap_read_poll_timeout(st->regmap, ++ AXI_DAC_UI_STATUS_REG, val, ++ FIELD_GET(AXI_DAC_UI_STATUS_IF_BUSY, val) == 0, ++ 10, 100 * KILO); ++ if (ret) ++ return ret; + + return regmap_set_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG, + AXI_DAC_CUSTOM_CTRL_STREAM_ENABLE); +-- +2.39.5 + diff --git a/queue-6.14/iio-gts-helper-export-iio_gts_get_total_gain.patch b/queue-6.14/iio-gts-helper-export-iio_gts_get_total_gain.patch new file mode 100644 index 0000000000..53dfb69a3d --- /dev/null +++ b/queue-6.14/iio-gts-helper-export-iio_gts_get_total_gain.patch @@ -0,0 +1,68 @@ +From da1eaaaaac2049adbaa17025eb02ff80b3cab393 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Jan 2025 20:30:22 +0100 +Subject: iio: gts-helper: export iio_gts_get_total_gain() + +From: Javier Carrasco + +[ Upstream commit dbd2e08ff09fd6bd51215b44474899cc1b7b7a16 ] + +Export this function in preparation for the fix in veml6030.c, where the +total gain can be used to ease the calculation of the processed value of +the IIO_LIGHT channel compared to acquiring the scale in NANO. + +Suggested-by: Matti Vaittinen +Signed-off-by: Javier Carrasco +Reviewed-by: Matti Vaittinen +Link: https://patch.msgid.link/20250127-veml6030-scale-v3-1-4f32ba03df94@gmail.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: 22eaca4283b2 ("iio: light: veml6030: fix scale to conform to ABI") +Signed-off-by: Sasha Levin +--- + drivers/iio/industrialio-gts-helper.c | 11 ++++++++++- + include/linux/iio/iio-gts-helper.h | 1 + + 2 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/drivers/iio/industrialio-gts-helper.c b/drivers/iio/industrialio-gts-helper.c +index d70ebe3bf7742..d14f3507f34ea 100644 +--- a/drivers/iio/industrialio-gts-helper.c ++++ b/drivers/iio/industrialio-gts-helper.c +@@ -950,7 +950,15 @@ int iio_gts_find_gain_time_sel_for_scale(struct iio_gts *gts, int scale_int, + } + EXPORT_SYMBOL_NS_GPL(iio_gts_find_gain_time_sel_for_scale, "IIO_GTS_HELPER"); + +-static int iio_gts_get_total_gain(struct iio_gts *gts, int gain, int time) ++/** ++ * iio_gts_get_total_gain - Fetch total gain for given HW-gain and time ++ * @gts: Gain time scale descriptor ++ * @gain: HW-gain for which the total gain is searched for ++ * @time: Integration time for which the total gain is searched for ++ * ++ * Return: total gain on success and -EINVAL on error. ++ */ ++int iio_gts_get_total_gain(struct iio_gts *gts, int gain, int time) + { + const struct iio_itime_sel_mul *itime; + +@@ -966,6 +974,7 @@ static int iio_gts_get_total_gain(struct iio_gts *gts, int gain, int time) + + return gain * itime->mul; + } ++EXPORT_SYMBOL_NS_GPL(iio_gts_get_total_gain, "IIO_GTS_HELPER"); + + static int iio_gts_get_scale_linear(struct iio_gts *gts, int gain, int time, + u64 *scale) +diff --git a/include/linux/iio/iio-gts-helper.h b/include/linux/iio/iio-gts-helper.h +index e5de7a124bad6..66f830ab9b49b 100644 +--- a/include/linux/iio/iio-gts-helper.h ++++ b/include/linux/iio/iio-gts-helper.h +@@ -208,5 +208,6 @@ int iio_gts_all_avail_scales(struct iio_gts *gts, const int **vals, int *type, + int *length); + int iio_gts_avail_scales_for_time(struct iio_gts *gts, int time, + const int **vals, int *type, int *length); ++int iio_gts_get_total_gain(struct iio_gts *gts, int gain, int time); + + #endif +-- +2.39.5 + diff --git a/queue-6.14/iio-light-add-check-for-array-bounds-in-veml6075_rea.patch b/queue-6.14/iio-light-add-check-for-array-bounds-in-veml6075_rea.patch new file mode 100644 index 0000000000..e6bc0c7585 --- /dev/null +++ b/queue-6.14/iio-light-add-check-for-array-bounds-in-veml6075_rea.patch @@ -0,0 +1,59 @@ +From ca74a8a289abbf2124f3fdcd4f25d706d9da9d70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 17:34:36 +0000 +Subject: iio: light: Add check for array bounds in veml6075_read_int_time_ms + +From: Karan Sanghavi + +[ Upstream commit ee735aa33db16c1fb5ebccbaf84ad38f5583f3cc ] + +The array contains only 5 elements, but the index calculated by +veml6075_read_int_time_index can range from 0 to 7, +which could lead to out-of-bounds access. The check prevents this issue. + +Coverity Issue +CID 1574309: (#1 of 1): Out-of-bounds read (OVERRUN) +overrun-local: Overrunning array veml6075_it_ms of 5 4-byte +elements at element index 7 (byte offset 31) using +index int_index (which evaluates to 7) + +This is hardening against potentially broken hardware. Good to have +but not necessary to backport. + +Fixes: 3b82f43238ae ("iio: light: add VEML6075 UVA and UVB light sensor driver") +Signed-off-by: Karan Sanghavi +Reviewed-by: Javier Carrasco +Link: https://patch.msgid.link/Z7dnrEpKQdRZ2qFU@Emma +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/light/veml6075.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/iio/light/veml6075.c b/drivers/iio/light/veml6075.c +index 05d4c0e9015d6..859891e8f1152 100644 +--- a/drivers/iio/light/veml6075.c ++++ b/drivers/iio/light/veml6075.c +@@ -195,13 +195,17 @@ static int veml6075_read_uv_direct(struct veml6075_data *data, int chan, + + static int veml6075_read_int_time_index(struct veml6075_data *data) + { +- int ret, conf; ++ int ret, conf, int_index; + + ret = regmap_read(data->regmap, VEML6075_CMD_CONF, &conf); + if (ret < 0) + return ret; + +- return FIELD_GET(VEML6075_CONF_IT, conf); ++ int_index = FIELD_GET(VEML6075_CONF_IT, conf); ++ if (int_index >= ARRAY_SIZE(veml6075_it_ms)) ++ return -EINVAL; ++ ++ return int_index; + } + + static int veml6075_read_int_time_ms(struct veml6075_data *data, int *val) +-- +2.39.5 + diff --git a/queue-6.14/iio-light-veml6030-extend-regmap-to-support-regfield.patch b/queue-6.14/iio-light-veml6030-extend-regmap-to-support-regfield.patch new file mode 100644 index 0000000000..ced1b6b40d --- /dev/null +++ b/queue-6.14/iio-light-veml6030-extend-regmap-to-support-regfield.patch @@ -0,0 +1,278 @@ +From c1123c84875a67006d18ba19ff05deaa6ce0e701 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 19 Jan 2025 18:31:58 +0100 +Subject: iio: light: veml6030: extend regmap to support regfields + +From: Javier Carrasco + +[ Upstream commit 9c7eb1ab2eec47ad9eaf6e11ce14d3d6fd54e677 ] + +Add support for regfields as well to simplify register operations, +taking into account the different fields for the veml6030/veml7700 and +veml6035. + +Signed-off-by: Javier Carrasco +Link: https://patch.msgid.link/20250119-veml6030-scale-v2-1-6bfc4062a371@gmail.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: 22eaca4283b2 ("iio: light: veml6030: fix scale to conform to ABI") +Signed-off-by: Sasha Levin +--- + drivers/iio/light/veml6030.c | 95 ++++++++++++++++++++++++++---------- + 1 file changed, 70 insertions(+), 25 deletions(-) + +diff --git a/drivers/iio/light/veml6030.c b/drivers/iio/light/veml6030.c +index 9b71825eea9be..8e4eb8b0c1927 100644 +--- a/drivers/iio/light/veml6030.c ++++ b/drivers/iio/light/veml6030.c +@@ -59,18 +59,31 @@ + #define VEML6035_INT_CHAN BIT(3) + #define VEML6035_CHAN_EN BIT(2) + ++/* Regfields */ ++#define VEML6030_GAIN_RF REG_FIELD(VEML6030_REG_ALS_CONF, 11, 12) ++#define VEML6030_IT_RF REG_FIELD(VEML6030_REG_ALS_CONF, 6, 9) ++ ++#define VEML6035_GAIN_RF REG_FIELD(VEML6030_REG_ALS_CONF, 10, 12) ++ + enum veml6030_scan { + VEML6030_SCAN_ALS, + VEML6030_SCAN_WH, + VEML6030_SCAN_TIMESTAMP, + }; + ++struct veml6030_rf { ++ struct regmap_field *it; ++ struct regmap_field *gain; ++}; ++ + struct veml603x_chip { + const char *name; + const int(*scale_vals)[][2]; + const int num_scale_vals; + const struct iio_chan_spec *channels; + const int num_channels; ++ const struct reg_field gain_rf; ++ const struct reg_field it_rf; + int (*hw_init)(struct iio_dev *indio_dev, struct device *dev); + int (*set_info)(struct iio_dev *indio_dev); + int (*set_als_gain)(struct iio_dev *indio_dev, int val, int val2); +@@ -91,6 +104,7 @@ struct veml603x_chip { + struct veml6030_data { + struct i2c_client *client; + struct regmap *regmap; ++ struct veml6030_rf rf; + int cur_resolution; + int cur_gain; + int cur_integration_time; +@@ -330,17 +344,17 @@ static const struct regmap_config veml6030_regmap_config = { + static int veml6030_get_intgrn_tm(struct iio_dev *indio_dev, + int *val, int *val2) + { +- int ret, reg; ++ int it_idx, ret; + struct veml6030_data *data = iio_priv(indio_dev); + +- ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, ®); ++ ret = regmap_field_read(data->rf.it, &it_idx); + if (ret) { + dev_err(&data->client->dev, + "can't read als conf register %d\n", ret); + return ret; + } + +- switch ((reg >> 6) & 0xF) { ++ switch (it_idx) { + case 0: + *val2 = 100000; + break; +@@ -405,8 +419,7 @@ static int veml6030_set_intgrn_tm(struct iio_dev *indio_dev, + return -EINVAL; + } + +- ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF, +- VEML6030_ALS_IT, new_int_time); ++ ret = regmap_field_write(data->rf.it, new_int_time); + if (ret) { + dev_err(&data->client->dev, + "can't update als integration time %d\n", ret); +@@ -510,23 +523,22 @@ static int veml6030_set_als_gain(struct iio_dev *indio_dev, + struct veml6030_data *data = iio_priv(indio_dev); + + if (val == 0 && val2 == 125000) { +- new_gain = 0x1000; /* 0x02 << 11 */ ++ new_gain = 0x01; + gain_idx = 3; + } else if (val == 0 && val2 == 250000) { +- new_gain = 0x1800; ++ new_gain = 0x11; + gain_idx = 2; + } else if (val == 1 && val2 == 0) { + new_gain = 0x00; + gain_idx = 1; + } else if (val == 2 && val2 == 0) { +- new_gain = 0x800; ++ new_gain = 0x01; + gain_idx = 0; + } else { + return -EINVAL; + } + +- ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF, +- VEML6030_ALS_GAIN, new_gain); ++ ret = regmap_field_write(data->rf.gain, new_gain); + if (ret) { + dev_err(&data->client->dev, + "can't set als gain %d\n", ret); +@@ -544,30 +556,31 @@ static int veml6035_set_als_gain(struct iio_dev *indio_dev, int val, int val2) + struct veml6030_data *data = iio_priv(indio_dev); + + if (val == 0 && val2 == 125000) { +- new_gain = VEML6035_SENS; ++ new_gain = FIELD_GET(VEML6035_GAIN_M, VEML6035_SENS); + gain_idx = 5; + } else if (val == 0 && val2 == 250000) { +- new_gain = VEML6035_SENS | VEML6035_GAIN; ++ new_gain = FIELD_GET(VEML6035_GAIN_M, VEML6035_SENS | ++ VEML6035_GAIN); + gain_idx = 4; + } else if (val == 0 && val2 == 500000) { +- new_gain = VEML6035_SENS | VEML6035_GAIN | +- VEML6035_DG; ++ new_gain = FIELD_GET(VEML6035_GAIN_M, VEML6035_SENS | ++ VEML6035_GAIN | VEML6035_DG); + gain_idx = 3; + } else if (val == 1 && val2 == 0) { + new_gain = 0x0000; + gain_idx = 2; + } else if (val == 2 && val2 == 0) { +- new_gain = VEML6035_GAIN; ++ new_gain = FIELD_GET(VEML6035_GAIN_M, VEML6035_GAIN); + gain_idx = 1; + } else if (val == 4 && val2 == 0) { +- new_gain = VEML6035_GAIN | VEML6035_DG; ++ new_gain = FIELD_GET(VEML6035_GAIN_M, VEML6035_GAIN | ++ VEML6035_DG); + gain_idx = 0; + } else { + return -EINVAL; + } + +- ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF, +- VEML6035_GAIN_M, new_gain); ++ ret = regmap_field_write(data->rf.gain, new_gain); + if (ret) { + dev_err(&data->client->dev, "can't set als gain %d\n", ret); + return ret; +@@ -581,17 +594,17 @@ static int veml6035_set_als_gain(struct iio_dev *indio_dev, int val, int val2) + static int veml6030_get_als_gain(struct iio_dev *indio_dev, + int *val, int *val2) + { +- int ret, reg; ++ int gain, ret; + struct veml6030_data *data = iio_priv(indio_dev); + +- ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, ®); ++ ret = regmap_field_read(data->rf.gain, &gain); + if (ret) { + dev_err(&data->client->dev, + "can't read als conf register %d\n", ret); + return ret; + } + +- switch ((reg >> 11) & 0x03) { ++ switch (gain) { + case 0: + *val = 1; + *val2 = 0; +@@ -617,17 +630,17 @@ static int veml6030_get_als_gain(struct iio_dev *indio_dev, + + static int veml6035_get_als_gain(struct iio_dev *indio_dev, int *val, int *val2) + { +- int ret, reg; ++ int gain, ret; + struct veml6030_data *data = iio_priv(indio_dev); + +- ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, ®); ++ ret = regmap_field_read(data->rf.gain, &gain); + if (ret) { + dev_err(&data->client->dev, +- "can't read als conf register %d\n", ret); ++ "can't read als conf register %d\n", ret); + return ret; + } + +- switch (FIELD_GET(VEML6035_GAIN_M, reg)) { ++ switch (gain) { + case 0: + *val = 1; + *val2 = 0; +@@ -990,6 +1003,27 @@ static int veml7700_set_info(struct iio_dev *indio_dev) + return 0; + } + ++static int veml6030_regfield_init(struct iio_dev *indio_dev) ++{ ++ struct veml6030_data *data = iio_priv(indio_dev); ++ struct regmap *regmap = data->regmap; ++ struct device *dev = &data->client->dev; ++ struct regmap_field *rm_field; ++ struct veml6030_rf *rf = &data->rf; ++ ++ rm_field = devm_regmap_field_alloc(dev, regmap, data->chip->it_rf); ++ if (IS_ERR(rm_field)) ++ return PTR_ERR(rm_field); ++ rf->it = rm_field; ++ ++ rm_field = devm_regmap_field_alloc(dev, regmap, data->chip->gain_rf); ++ if (IS_ERR(rm_field)) ++ return PTR_ERR(rm_field); ++ rf->gain = rm_field; ++ ++ return 0; ++} ++ + /* + * Set ALS gain to 1/8, integration time to 100 ms, PSM to mode 2, + * persistence to 1 x integration time and the threshold +@@ -1143,6 +1177,11 @@ static int veml6030_probe(struct i2c_client *client) + if (ret < 0) + return ret; + ++ ret = veml6030_regfield_init(indio_dev); ++ if (ret) ++ return dev_err_probe(&client->dev, ret, ++ "failed to init regfields\n"); ++ + ret = data->chip->hw_init(indio_dev, &client->dev); + if (ret < 0) + return ret; +@@ -1191,6 +1230,8 @@ static const struct veml603x_chip veml6030_chip = { + .num_scale_vals = ARRAY_SIZE(veml6030_scale_vals), + .channels = veml6030_channels, + .num_channels = ARRAY_SIZE(veml6030_channels), ++ .gain_rf = VEML6030_GAIN_RF, ++ .it_rf = VEML6030_IT_RF, + .hw_init = veml6030_hw_init, + .set_info = veml6030_set_info, + .set_als_gain = veml6030_set_als_gain, +@@ -1203,6 +1244,8 @@ static const struct veml603x_chip veml6035_chip = { + .num_scale_vals = ARRAY_SIZE(veml6035_scale_vals), + .channels = veml6030_channels, + .num_channels = ARRAY_SIZE(veml6030_channels), ++ .gain_rf = VEML6035_GAIN_RF, ++ .it_rf = VEML6030_IT_RF, + .hw_init = veml6035_hw_init, + .set_info = veml6030_set_info, + .set_als_gain = veml6035_set_als_gain, +@@ -1215,6 +1258,8 @@ static const struct veml603x_chip veml7700_chip = { + .num_scale_vals = ARRAY_SIZE(veml6030_scale_vals), + .channels = veml7700_channels, + .num_channels = ARRAY_SIZE(veml7700_channels), ++ .gain_rf = VEML6030_GAIN_RF, ++ .it_rf = VEML6030_IT_RF, + .hw_init = veml6030_hw_init, + .set_info = veml7700_set_info, + .set_als_gain = veml6030_set_als_gain, +-- +2.39.5 + diff --git a/queue-6.14/iio-light-veml6030-fix-scale-to-conform-to-abi.patch b/queue-6.14/iio-light-veml6030-fix-scale-to-conform-to-abi.patch new file mode 100644 index 0000000000..5c1d5e9c86 --- /dev/null +++ b/queue-6.14/iio-light-veml6030-fix-scale-to-conform-to-abi.patch @@ -0,0 +1,802 @@ +From 5172b3ca2fe38c990a64de6ecf4c9b1794c5be88 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Jan 2025 20:30:23 +0100 +Subject: iio: light: veml6030: fix scale to conform to ABI + +From: Javier Carrasco + +[ Upstream commit 22eaca4283b216f5e1f7721e4ad0ecb3d23c6774 ] + +The current scale is not ABI-compliant as it is just the sensor gain +instead of the value that acts as a multiplier to be applied to the raw +value (there is no offset). + +Use the iio-gts helpers to obtain the proper scale values according to +the gain and integration time to match the resolution tables from the +datasheet and drop dedicated variables to store the current values of +the integration time, gain and resolution. When at it, use 'scale' +instead of 'gain' consistently for the get/set functions to avoid +misunderstandings. + +Fixes: 7b779f573c48 ("iio: light: add driver for veml6030 ambient light sensor") +Acked-by: Matti Vaittinen +Signed-off-by: Javier Carrasco +Link: https://patch.msgid.link/20250127-veml6030-scale-v3-2-4f32ba03df94@gmail.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/light/Kconfig | 1 + + drivers/iio/light/veml6030.c | 528 ++++++++++++++--------------------- + 2 files changed, 218 insertions(+), 311 deletions(-) + +diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig +index e34e551eef3e8..eb7f56eaeae07 100644 +--- a/drivers/iio/light/Kconfig ++++ b/drivers/iio/light/Kconfig +@@ -683,6 +683,7 @@ config VEML6030 + select REGMAP_I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER ++ select IIO_GTS_HELPER + depends on I2C + help + Say Y here if you want to build a driver for the Vishay VEML6030 +diff --git a/drivers/iio/light/veml6030.c b/drivers/iio/light/veml6030.c +index 8e4eb8b0c1927..750d3c2267a49 100644 +--- a/drivers/iio/light/veml6030.c ++++ b/drivers/iio/light/veml6030.c +@@ -24,10 +24,12 @@ + #include + #include + #include ++#include + #include + #include + #include + #include ++#include + #include + #include + +@@ -65,6 +67,10 @@ + + #define VEML6035_GAIN_RF REG_FIELD(VEML6030_REG_ALS_CONF, 10, 12) + ++/* Maximum scales x 10000 to work with integers */ ++#define VEML6030_MAX_SCALE 21504 ++#define VEML6035_MAX_SCALE 4096 ++ + enum veml6030_scan { + VEML6030_SCAN_ALS, + VEML6030_SCAN_WH, +@@ -78,16 +84,13 @@ struct veml6030_rf { + + struct veml603x_chip { + const char *name; +- const int(*scale_vals)[][2]; +- const int num_scale_vals; + const struct iio_chan_spec *channels; + const int num_channels; + const struct reg_field gain_rf; + const struct reg_field it_rf; ++ const int max_scale; + int (*hw_init)(struct iio_dev *indio_dev, struct device *dev); + int (*set_info)(struct iio_dev *indio_dev); +- int (*set_als_gain)(struct iio_dev *indio_dev, int val, int val2); +- int (*get_als_gain)(struct iio_dev *indio_dev, int *val, int *val2); + }; + + /* +@@ -105,40 +108,55 @@ struct veml6030_data { + struct i2c_client *client; + struct regmap *regmap; + struct veml6030_rf rf; +- int cur_resolution; +- int cur_gain; +- int cur_integration_time; + const struct veml603x_chip *chip; ++ struct iio_gts gts; ++ + }; + +-static const int veml6030_it_times[][2] = { +- { 0, 25000 }, +- { 0, 50000 }, +- { 0, 100000 }, +- { 0, 200000 }, +- { 0, 400000 }, +- { 0, 800000 }, ++#define VEML6030_SEL_IT_25MS 0x0C ++#define VEML6030_SEL_IT_50MS 0x08 ++#define VEML6030_SEL_IT_100MS 0x00 ++#define VEML6030_SEL_IT_200MS 0x01 ++#define VEML6030_SEL_IT_400MS 0x02 ++#define VEML6030_SEL_IT_800MS 0x03 ++static const struct iio_itime_sel_mul veml6030_it_sel[] = { ++ GAIN_SCALE_ITIME_US(25000, VEML6030_SEL_IT_25MS, 1), ++ GAIN_SCALE_ITIME_US(50000, VEML6030_SEL_IT_50MS, 2), ++ GAIN_SCALE_ITIME_US(100000, VEML6030_SEL_IT_100MS, 4), ++ GAIN_SCALE_ITIME_US(200000, VEML6030_SEL_IT_200MS, 8), ++ GAIN_SCALE_ITIME_US(400000, VEML6030_SEL_IT_400MS, 16), ++ GAIN_SCALE_ITIME_US(800000, VEML6030_SEL_IT_800MS, 32), + }; + +-/* +- * Scale is 1/gain. Value 0.125 is ALS gain x (1/8), 0.25 is +- * ALS gain x (1/4), 0.5 is ALS gain x (1/2), 1.0 is ALS gain x 1, +- * 2.0 is ALS gain x2, and 4.0 is ALS gain x 4. ++/* Gains are multiplied by 8 to work with integers. The values in the ++ * iio-gts tables don't need corrections because the maximum value of ++ * the scale refers to GAIN = x1, and the rest of the values are ++ * obtained from the resulting linear function. + */ +-static const int veml6030_scale_vals[][2] = { +- { 0, 125000 }, +- { 0, 250000 }, +- { 1, 0 }, +- { 2, 0 }, ++#define VEML6030_SEL_MILLI_GAIN_X125 2 ++#define VEML6030_SEL_MILLI_GAIN_X250 3 ++#define VEML6030_SEL_MILLI_GAIN_X1000 0 ++#define VEML6030_SEL_MILLI_GAIN_X2000 1 ++static const struct iio_gain_sel_pair veml6030_gain_sel[] = { ++ GAIN_SCALE_GAIN(1, VEML6030_SEL_MILLI_GAIN_X125), ++ GAIN_SCALE_GAIN(2, VEML6030_SEL_MILLI_GAIN_X250), ++ GAIN_SCALE_GAIN(8, VEML6030_SEL_MILLI_GAIN_X1000), ++ GAIN_SCALE_GAIN(16, VEML6030_SEL_MILLI_GAIN_X2000), + }; + +-static const int veml6035_scale_vals[][2] = { +- { 0, 125000 }, +- { 0, 250000 }, +- { 0, 500000 }, +- { 1, 0 }, +- { 2, 0 }, +- { 4, 0 }, ++#define VEML6035_SEL_MILLI_GAIN_X125 4 ++#define VEML6035_SEL_MILLI_GAIN_X250 5 ++#define VEML6035_SEL_MILLI_GAIN_X500 7 ++#define VEML6035_SEL_MILLI_GAIN_X1000 0 ++#define VEML6035_SEL_MILLI_GAIN_X2000 1 ++#define VEML6035_SEL_MILLI_GAIN_X4000 3 ++static const struct iio_gain_sel_pair veml6035_gain_sel[] = { ++ GAIN_SCALE_GAIN(1, VEML6035_SEL_MILLI_GAIN_X125), ++ GAIN_SCALE_GAIN(2, VEML6035_SEL_MILLI_GAIN_X250), ++ GAIN_SCALE_GAIN(4, VEML6035_SEL_MILLI_GAIN_X500), ++ GAIN_SCALE_GAIN(8, VEML6035_SEL_MILLI_GAIN_X1000), ++ GAIN_SCALE_GAIN(16, VEML6035_SEL_MILLI_GAIN_X2000), ++ GAIN_SCALE_GAIN(32, VEML6035_SEL_MILLI_GAIN_X4000), + }; + + /* +@@ -341,104 +359,73 @@ static const struct regmap_config veml6030_regmap_config = { + .val_format_endian = REGMAP_ENDIAN_LITTLE, + }; + +-static int veml6030_get_intgrn_tm(struct iio_dev *indio_dev, +- int *val, int *val2) ++static int veml6030_get_it(struct veml6030_data *data, int *val, int *val2) + { +- int it_idx, ret; +- struct veml6030_data *data = iio_priv(indio_dev); ++ int ret, it_idx; + + ret = regmap_field_read(data->rf.it, &it_idx); +- if (ret) { +- dev_err(&data->client->dev, +- "can't read als conf register %d\n", ret); ++ if (ret) + return ret; +- } + +- switch (it_idx) { +- case 0: +- *val2 = 100000; +- break; +- case 1: +- *val2 = 200000; +- break; +- case 2: +- *val2 = 400000; +- break; +- case 3: +- *val2 = 800000; +- break; +- case 8: +- *val2 = 50000; +- break; +- case 12: +- *val2 = 25000; +- break; +- default: +- return -EINVAL; +- } ++ ret = iio_gts_find_int_time_by_sel(&data->gts, it_idx); ++ if (ret < 0) ++ return ret; + ++ *val2 = ret; + *val = 0; ++ + return IIO_VAL_INT_PLUS_MICRO; + } + +-static int veml6030_set_intgrn_tm(struct iio_dev *indio_dev, +- int val, int val2) ++static int veml6030_set_it(struct iio_dev *indio_dev, int val, int val2) + { +- int ret, new_int_time, int_idx; + struct veml6030_data *data = iio_priv(indio_dev); ++ int ret, gain_idx, it_idx, new_gain, prev_gain, prev_it; ++ bool in_range; + +- if (val) ++ if (val || !iio_gts_valid_time(&data->gts, val2)) + return -EINVAL; + +- switch (val2) { +- case 25000: +- new_int_time = 0x300; +- int_idx = 5; +- break; +- case 50000: +- new_int_time = 0x200; +- int_idx = 4; +- break; +- case 100000: +- new_int_time = 0x00; +- int_idx = 3; +- break; +- case 200000: +- new_int_time = 0x40; +- int_idx = 2; +- break; +- case 400000: +- new_int_time = 0x80; +- int_idx = 1; +- break; +- case 800000: +- new_int_time = 0xC0; +- int_idx = 0; +- break; +- default: +- return -EINVAL; +- } ++ ret = regmap_field_read(data->rf.it, &it_idx); ++ if (ret) ++ return ret; + +- ret = regmap_field_write(data->rf.it, new_int_time); +- if (ret) { +- dev_err(&data->client->dev, +- "can't update als integration time %d\n", ret); ++ ret = regmap_field_read(data->rf.gain, &gain_idx); ++ if (ret) + return ret; +- } + +- /* +- * Cache current integration time and update resolution. For every +- * increase in integration time to next level, resolution is halved +- * and vice-versa. +- */ +- if (data->cur_integration_time < int_idx) +- data->cur_resolution <<= int_idx - data->cur_integration_time; +- else if (data->cur_integration_time > int_idx) +- data->cur_resolution >>= data->cur_integration_time - int_idx; ++ prev_it = iio_gts_find_int_time_by_sel(&data->gts, it_idx); ++ if (prev_it < 0) ++ return prev_it; ++ ++ if (prev_it == val2) ++ return 0; + +- data->cur_integration_time = int_idx; ++ prev_gain = iio_gts_find_gain_by_sel(&data->gts, gain_idx); ++ if (prev_gain < 0) ++ return prev_gain; + +- return ret; ++ ret = iio_gts_find_new_gain_by_gain_time_min(&data->gts, prev_gain, prev_it, ++ val2, &new_gain, &in_range); ++ if (ret) ++ return ret; ++ ++ if (!in_range) ++ dev_dbg(&data->client->dev, "Optimal gain out of range\n"); ++ ++ ret = iio_gts_find_sel_by_int_time(&data->gts, val2); ++ if (ret < 0) ++ return ret; ++ ++ ret = regmap_field_write(data->rf.it, ret); ++ if (ret) ++ return ret; ++ ++ ret = iio_gts_find_sel_by_gain(&data->gts, new_gain); ++ if (ret < 0) ++ return ret; ++ ++ return regmap_field_write(data->rf.gain, ret); + } + + static int veml6030_read_persistence(struct iio_dev *indio_dev, +@@ -447,7 +434,7 @@ static int veml6030_read_persistence(struct iio_dev *indio_dev, + int ret, reg, period, x, y; + struct veml6030_data *data = iio_priv(indio_dev); + +- ret = veml6030_get_intgrn_tm(indio_dev, &x, &y); ++ ret = veml6030_get_it(data, &x, &y); + if (ret < 0) + return ret; + +@@ -472,7 +459,7 @@ static int veml6030_write_persistence(struct iio_dev *indio_dev, + int ret, period, x, y; + struct veml6030_data *data = iio_priv(indio_dev); + +- ret = veml6030_get_intgrn_tm(indio_dev, &x, &y); ++ ret = veml6030_get_it(data, &x, &y); + if (ret < 0) + return ret; + +@@ -501,177 +488,29 @@ static int veml6030_write_persistence(struct iio_dev *indio_dev, + return ret; + } + +-/* +- * Cache currently set gain & update resolution. For every +- * increase in the gain to next level, resolution is halved +- * and vice-versa. +- */ +-static void veml6030_update_gain_res(struct veml6030_data *data, int gain_idx) +-{ +- if (data->cur_gain < gain_idx) +- data->cur_resolution <<= gain_idx - data->cur_gain; +- else if (data->cur_gain > gain_idx) +- data->cur_resolution >>= data->cur_gain - gain_idx; +- +- data->cur_gain = gain_idx; +-} +- +-static int veml6030_set_als_gain(struct iio_dev *indio_dev, +- int val, int val2) ++static int veml6030_set_scale(struct iio_dev *indio_dev, int val, int val2) + { +- int ret, new_gain, gain_idx; ++ int ret, gain_sel, it_idx, it_sel; + struct veml6030_data *data = iio_priv(indio_dev); + +- if (val == 0 && val2 == 125000) { +- new_gain = 0x01; +- gain_idx = 3; +- } else if (val == 0 && val2 == 250000) { +- new_gain = 0x11; +- gain_idx = 2; +- } else if (val == 1 && val2 == 0) { +- new_gain = 0x00; +- gain_idx = 1; +- } else if (val == 2 && val2 == 0) { +- new_gain = 0x01; +- gain_idx = 0; +- } else { +- return -EINVAL; +- } +- +- ret = regmap_field_write(data->rf.gain, new_gain); +- if (ret) { +- dev_err(&data->client->dev, +- "can't set als gain %d\n", ret); ++ ret = regmap_field_read(data->rf.it, &it_idx); ++ if (ret) + return ret; +- } +- +- veml6030_update_gain_res(data, gain_idx); +- +- return 0; +-} +- +-static int veml6035_set_als_gain(struct iio_dev *indio_dev, int val, int val2) +-{ +- int ret, new_gain, gain_idx; +- struct veml6030_data *data = iio_priv(indio_dev); +- +- if (val == 0 && val2 == 125000) { +- new_gain = FIELD_GET(VEML6035_GAIN_M, VEML6035_SENS); +- gain_idx = 5; +- } else if (val == 0 && val2 == 250000) { +- new_gain = FIELD_GET(VEML6035_GAIN_M, VEML6035_SENS | +- VEML6035_GAIN); +- gain_idx = 4; +- } else if (val == 0 && val2 == 500000) { +- new_gain = FIELD_GET(VEML6035_GAIN_M, VEML6035_SENS | +- VEML6035_GAIN | VEML6035_DG); +- gain_idx = 3; +- } else if (val == 1 && val2 == 0) { +- new_gain = 0x0000; +- gain_idx = 2; +- } else if (val == 2 && val2 == 0) { +- new_gain = FIELD_GET(VEML6035_GAIN_M, VEML6035_GAIN); +- gain_idx = 1; +- } else if (val == 4 && val2 == 0) { +- new_gain = FIELD_GET(VEML6035_GAIN_M, VEML6035_GAIN | +- VEML6035_DG); +- gain_idx = 0; +- } else { +- return -EINVAL; +- } + +- ret = regmap_field_write(data->rf.gain, new_gain); +- if (ret) { +- dev_err(&data->client->dev, "can't set als gain %d\n", ret); ++ ret = iio_gts_find_gain_time_sel_for_scale(&data->gts, val, val2, ++ &gain_sel, &it_sel); ++ if (ret) + return ret; +- } +- +- veml6030_update_gain_res(data, gain_idx); +- +- return 0; +-} +- +-static int veml6030_get_als_gain(struct iio_dev *indio_dev, +- int *val, int *val2) +-{ +- int gain, ret; +- struct veml6030_data *data = iio_priv(indio_dev); + +- ret = regmap_field_read(data->rf.gain, &gain); +- if (ret) { +- dev_err(&data->client->dev, +- "can't read als conf register %d\n", ret); ++ ret = regmap_field_write(data->rf.it, it_sel); ++ if (ret) + return ret; +- } + +- switch (gain) { +- case 0: +- *val = 1; +- *val2 = 0; +- break; +- case 1: +- *val = 2; +- *val2 = 0; +- break; +- case 2: +- *val = 0; +- *val2 = 125000; +- break; +- case 3: +- *val = 0; +- *val2 = 250000; +- break; +- default: +- return -EINVAL; +- } +- +- return IIO_VAL_INT_PLUS_MICRO; +-} +- +-static int veml6035_get_als_gain(struct iio_dev *indio_dev, int *val, int *val2) +-{ +- int gain, ret; +- struct veml6030_data *data = iio_priv(indio_dev); +- +- ret = regmap_field_read(data->rf.gain, &gain); +- if (ret) { +- dev_err(&data->client->dev, +- "can't read als conf register %d\n", ret); ++ ret = regmap_field_write(data->rf.gain, gain_sel); ++ if (ret) + return ret; +- } +- +- switch (gain) { +- case 0: +- *val = 1; +- *val2 = 0; +- break; +- case 1: +- case 2: +- *val = 2; +- *val2 = 0; +- break; +- case 3: +- *val = 4; +- *val2 = 0; +- break; +- case 4: +- *val = 0; +- *val2 = 125000; +- break; +- case 5: +- case 6: +- *val = 0; +- *val2 = 250000; +- break; +- case 7: +- *val = 0; +- *val2 = 500000; +- break; +- default: +- return -EINVAL; +- } + +- return IIO_VAL_INT_PLUS_MICRO; ++ return 0; + } + + static int veml6030_read_thresh(struct iio_dev *indio_dev, +@@ -718,6 +557,71 @@ static int veml6030_write_thresh(struct iio_dev *indio_dev, + return ret; + } + ++static int veml6030_get_total_gain(struct veml6030_data *data) ++{ ++ int gain, it, reg, ret; ++ ++ ret = regmap_field_read(data->rf.gain, ®); ++ if (ret) ++ return ret; ++ ++ gain = iio_gts_find_gain_by_sel(&data->gts, reg); ++ if (gain < 0) ++ return gain; ++ ++ ret = regmap_field_read(data->rf.it, ®); ++ if (ret) ++ return ret; ++ ++ it = iio_gts_find_int_time_by_sel(&data->gts, reg); ++ if (it < 0) ++ return it; ++ ++ return iio_gts_get_total_gain(&data->gts, gain, it); ++} ++ ++static int veml6030_get_scale(struct veml6030_data *data, int *val, int *val2) ++{ ++ int gain, it, reg, ret; ++ ++ ret = regmap_field_read(data->rf.gain, ®); ++ if (ret) ++ return ret; ++ ++ gain = iio_gts_find_gain_by_sel(&data->gts, reg); ++ if (gain < 0) ++ return gain; ++ ++ ret = regmap_field_read(data->rf.it, ®); ++ if (ret) ++ return ret; ++ ++ it = iio_gts_find_int_time_by_sel(&data->gts, reg); ++ if (it < 0) ++ return it; ++ ++ ret = iio_gts_get_scale(&data->gts, gain, it, val, val2); ++ if (ret) ++ return ret; ++ ++ return IIO_VAL_INT_PLUS_NANO; ++} ++ ++static int veml6030_process_als(struct veml6030_data *data, int raw, ++ int *val, int *val2) ++{ ++ int total_gain; ++ ++ total_gain = veml6030_get_total_gain(data); ++ if (total_gain < 0) ++ return total_gain; ++ ++ *val = raw * data->chip->max_scale / total_gain / 10000; ++ *val2 = raw * data->chip->max_scale / total_gain % 10000 * 100; ++ ++ return IIO_VAL_INT_PLUS_MICRO; ++} ++ + /* + * Provide both raw as well as light reading in lux. + * light (in lux) = resolution * raw reading +@@ -741,11 +645,9 @@ static int veml6030_read_raw(struct iio_dev *indio_dev, + dev_err(dev, "can't read als data %d\n", ret); + return ret; + } +- if (mask == IIO_CHAN_INFO_PROCESSED) { +- *val = (reg * data->cur_resolution) / 10000; +- *val2 = (reg * data->cur_resolution) % 10000 * 100; +- return IIO_VAL_INT_PLUS_MICRO; +- } ++ if (mask == IIO_CHAN_INFO_PROCESSED) ++ return veml6030_process_als(data, reg, val, val2); ++ + *val = reg; + return IIO_VAL_INT; + case IIO_INTENSITY: +@@ -760,9 +662,9 @@ static int veml6030_read_raw(struct iio_dev *indio_dev, + return -EINVAL; + } + case IIO_CHAN_INFO_INT_TIME: +- return veml6030_get_intgrn_tm(indio_dev, val, val2); ++ return veml6030_get_it(data, val, val2); + case IIO_CHAN_INFO_SCALE: +- return data->chip->get_als_gain(indio_dev, val, val2); ++ return veml6030_get_scale(data, val, val2); + default: + return -EINVAL; + } +@@ -777,15 +679,9 @@ static int veml6030_read_avail(struct iio_dev *indio_dev, + + switch (mask) { + case IIO_CHAN_INFO_INT_TIME: +- *vals = (int *)&veml6030_it_times; +- *length = 2 * ARRAY_SIZE(veml6030_it_times); +- *type = IIO_VAL_INT_PLUS_MICRO; +- return IIO_AVAIL_LIST; ++ return iio_gts_avail_times(&data->gts, vals, type, length); + case IIO_CHAN_INFO_SCALE: +- *vals = (int *)*data->chip->scale_vals; +- *length = 2 * data->chip->num_scale_vals; +- *type = IIO_VAL_INT_PLUS_MICRO; +- return IIO_AVAIL_LIST; ++ return iio_gts_all_avail_scales(&data->gts, vals, type, length); + } + + return -EINVAL; +@@ -795,13 +691,25 @@ static int veml6030_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) + { +- struct veml6030_data *data = iio_priv(indio_dev); +- + switch (mask) { + case IIO_CHAN_INFO_INT_TIME: +- return veml6030_set_intgrn_tm(indio_dev, val, val2); ++ return veml6030_set_it(indio_dev, val, val2); ++ case IIO_CHAN_INFO_SCALE: ++ return veml6030_set_scale(indio_dev, val, val2); ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int veml6030_write_raw_get_fmt(struct iio_dev *indio_dev, ++ struct iio_chan_spec const *chan, ++ long mask) ++{ ++ switch (mask) { + case IIO_CHAN_INFO_SCALE: +- return data->chip->set_als_gain(indio_dev, val, val2); ++ return IIO_VAL_INT_PLUS_NANO; ++ case IIO_CHAN_INFO_INT_TIME: ++ return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +@@ -899,6 +807,7 @@ static const struct iio_info veml6030_info = { + .read_raw = veml6030_read_raw, + .read_avail = veml6030_read_avail, + .write_raw = veml6030_write_raw, ++ .write_raw_get_fmt = veml6030_write_raw_get_fmt, + .read_event_value = veml6030_read_event_val, + .write_event_value = veml6030_write_event_val, + .read_event_config = veml6030_read_interrupt_config, +@@ -910,6 +819,7 @@ static const struct iio_info veml6030_info_no_irq = { + .read_raw = veml6030_read_raw, + .read_avail = veml6030_read_avail, + .write_raw = veml6030_write_raw, ++ .write_raw_get_fmt = veml6030_write_raw_get_fmt, + }; + + static irqreturn_t veml6030_event_handler(int irq, void *private) +@@ -1035,6 +945,13 @@ static int veml6030_hw_init(struct iio_dev *indio_dev, struct device *dev) + int ret, val; + struct veml6030_data *data = iio_priv(indio_dev); + ++ ret = devm_iio_init_iio_gts(dev, 2, 150400000, ++ veml6030_gain_sel, ARRAY_SIZE(veml6030_gain_sel), ++ veml6030_it_sel, ARRAY_SIZE(veml6030_it_sel), ++ &data->gts); ++ if (ret) ++ return dev_err_probe(dev, ret, "failed to init iio gts\n"); ++ + ret = veml6030_als_shut_down(data); + if (ret) + return dev_err_probe(dev, ret, "can't shutdown als\n"); +@@ -1070,11 +987,6 @@ static int veml6030_hw_init(struct iio_dev *indio_dev, struct device *dev) + return dev_err_probe(dev, ret, + "can't clear als interrupt status\n"); + +- /* Cache currently active measurement parameters */ +- data->cur_gain = 3; +- data->cur_resolution = 5376; +- data->cur_integration_time = 3; +- + return ret; + } + +@@ -1090,6 +1002,13 @@ static int veml6035_hw_init(struct iio_dev *indio_dev, struct device *dev) + int ret, val; + struct veml6030_data *data = iio_priv(indio_dev); + ++ ret = devm_iio_init_iio_gts(dev, 0, 409600000, ++ veml6035_gain_sel, ARRAY_SIZE(veml6035_gain_sel), ++ veml6030_it_sel, ARRAY_SIZE(veml6030_it_sel), ++ &data->gts); ++ if (ret) ++ return dev_err_probe(dev, ret, "failed to init iio gts\n"); ++ + ret = veml6030_als_shut_down(data); + if (ret) + return dev_err_probe(dev, ret, "can't shutdown als\n"); +@@ -1126,11 +1045,6 @@ static int veml6035_hw_init(struct iio_dev *indio_dev, struct device *dev) + return dev_err_probe(dev, ret, + "can't clear als interrupt status\n"); + +- /* Cache currently active measurement parameters */ +- data->cur_gain = 5; +- data->cur_resolution = 1024; +- data->cur_integration_time = 3; +- + return 0; + } + +@@ -1226,44 +1140,35 @@ static DEFINE_RUNTIME_DEV_PM_OPS(veml6030_pm_ops, veml6030_runtime_suspend, + + static const struct veml603x_chip veml6030_chip = { + .name = "veml6030", +- .scale_vals = &veml6030_scale_vals, +- .num_scale_vals = ARRAY_SIZE(veml6030_scale_vals), + .channels = veml6030_channels, + .num_channels = ARRAY_SIZE(veml6030_channels), + .gain_rf = VEML6030_GAIN_RF, + .it_rf = VEML6030_IT_RF, ++ .max_scale = VEML6030_MAX_SCALE, + .hw_init = veml6030_hw_init, + .set_info = veml6030_set_info, +- .set_als_gain = veml6030_set_als_gain, +- .get_als_gain = veml6030_get_als_gain, + }; + + static const struct veml603x_chip veml6035_chip = { + .name = "veml6035", +- .scale_vals = &veml6035_scale_vals, +- .num_scale_vals = ARRAY_SIZE(veml6035_scale_vals), + .channels = veml6030_channels, + .num_channels = ARRAY_SIZE(veml6030_channels), + .gain_rf = VEML6035_GAIN_RF, + .it_rf = VEML6030_IT_RF, ++ .max_scale = VEML6035_MAX_SCALE, + .hw_init = veml6035_hw_init, + .set_info = veml6030_set_info, +- .set_als_gain = veml6035_set_als_gain, +- .get_als_gain = veml6035_get_als_gain, + }; + + static const struct veml603x_chip veml7700_chip = { + .name = "veml7700", +- .scale_vals = &veml6030_scale_vals, +- .num_scale_vals = ARRAY_SIZE(veml6030_scale_vals), + .channels = veml7700_channels, + .num_channels = ARRAY_SIZE(veml7700_channels), + .gain_rf = VEML6030_GAIN_RF, + .it_rf = VEML6030_IT_RF, ++ .max_scale = VEML6030_MAX_SCALE, + .hw_init = veml6030_hw_init, + .set_info = veml7700_set_info, +- .set_als_gain = veml6030_set_als_gain, +- .get_als_gain = veml6030_get_als_gain, + }; + + static const struct of_device_id veml6030_of_match[] = { +@@ -1305,3 +1210,4 @@ module_i2c_driver(veml6030_driver); + MODULE_AUTHOR("Rishi Gupta "); + MODULE_DESCRIPTION("VEML6030 Ambient Light Sensor"); + MODULE_LICENSE("GPL v2"); ++MODULE_IMPORT_NS("IIO_GTS_HELPER"); +-- +2.39.5 + diff --git a/queue-6.14/io_uring-check-for-iowq-alloc_workqueue-failure.patch b/queue-6.14/io_uring-check-for-iowq-alloc_workqueue-failure.patch new file mode 100644 index 0000000000..d81b58b67b --- /dev/null +++ b/queue-6.14/io_uring-check-for-iowq-alloc_workqueue-failure.patch @@ -0,0 +1,36 @@ +From 0795165d214b607fd288e5febc014a9181d812ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 17:28:21 +0000 +Subject: io_uring: check for iowq alloc_workqueue failure + +From: Pavel Begunkov + +[ Upstream commit 7215469659cb9751a9bf80e43b24a48749004d26 ] + +alloc_workqueue() can fail even during init in io_uring_init(), check +the result and panic if anything went wrong. + +Fixes: 73eaa2b583493 ("io_uring: use private workqueue for exit work") +Signed-off-by: Pavel Begunkov +Link: https://lore.kernel.org/r/3a046063902f888f66151f89fa42f84063b9727b.1738343083.git.asml.silence@gmail.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/io_uring.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index f7acae5f7e1d0..573b3f542b82a 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -3922,6 +3922,7 @@ static int __init io_uring_init(void) + SLAB_HWCACHE_ALIGN | SLAB_PANIC | SLAB_ACCOUNT); + + iou_wq = alloc_workqueue("iou_exit", WQ_UNBOUND, 64); ++ BUG_ON(!iou_wq); + + #ifdef CONFIG_SYSCTL + register_sysctl_init("kernel", kernel_io_uring_disabled_table); +-- +2.39.5 + diff --git a/queue-6.14/io_uring-fix-retry-handling-off-iowq.patch b/queue-6.14/io_uring-fix-retry-handling-off-iowq.patch new file mode 100644 index 0000000000..fcbdfa120e --- /dev/null +++ b/queue-6.14/io_uring-fix-retry-handling-off-iowq.patch @@ -0,0 +1,38 @@ +From 7b61ac899c110ca07750fe62fb1115bf88dae98c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 15:32:32 +0000 +Subject: io_uring: fix retry handling off iowq + +From: Pavel Begunkov + +[ Upstream commit 3f0cb8de56b9a5c052a9e43fa548856926059810 ] + +io_req_complete_post() doesn't handle reissue and if called with a +REQ_F_REISSUE request it might post extra unexpected completions. Fix it +by pushing into flush_completion via task work. + +Fixes: d803d123948fe ("io_uring/rw: handle -EAGAIN retry at IO completion time") +Signed-off-by: Pavel Begunkov +Link: https://lore.kernel.org/r/badb3d7e462881e7edbfcc2be6301090b07dbe53.1742829388.git.asml.silence@gmail.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/io_uring.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index 99b83487c8158..4910ee7ac18aa 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -899,7 +899,7 @@ static void io_req_complete_post(struct io_kiocb *req, unsigned issue_flags) + * Handle special CQ sync cases via task_work. DEFER_TASKRUN requires + * the submitter task context, IOPOLL protects with uring_lock. + */ +- if (ctx->lockless_cq) { ++ if (ctx->lockless_cq || (req->flags & REQ_F_REISSUE)) { + req->io_task_work.func = io_req_task_complete; + io_req_task_work_add(req); + return; +-- +2.39.5 + diff --git a/queue-6.14/io_uring-io-wq-cache-work-flags-in-variable.patch b/queue-6.14/io_uring-io-wq-cache-work-flags-in-variable.patch new file mode 100644 index 0000000000..84075167da --- /dev/null +++ b/queue-6.14/io_uring-io-wq-cache-work-flags-in-variable.patch @@ -0,0 +1,183 @@ +From e42afeb38a26b057411cb0897732807f1804c4c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jan 2025 14:39:23 +0100 +Subject: io_uring/io-wq: cache work->flags in variable + +From: Max Kellermann + +[ Upstream commit 6ee78354eaa602002448f098b34678396d99043d ] + +This eliminates several redundant atomic reads and therefore reduces +the duration the surrounding spinlocks are held. + +In several io_uring benchmarks, this reduced the CPU time spent in +queued_spin_lock_slowpath() considerably: + +io_uring benchmark with a flood of `IORING_OP_NOP` and `IOSQE_ASYNC`: + + 38.86% -1.49% [kernel.kallsyms] [k] queued_spin_lock_slowpath + 6.75% +0.36% [kernel.kallsyms] [k] io_worker_handle_work + 2.60% +0.19% [kernel.kallsyms] [k] io_nop + 3.92% +0.18% [kernel.kallsyms] [k] io_req_task_complete + 6.34% -0.18% [kernel.kallsyms] [k] io_wq_submit_work + +HTTP server, static file: + + 42.79% -2.77% [kernel.kallsyms] [k] queued_spin_lock_slowpath + 2.08% +0.23% [kernel.kallsyms] [k] io_wq_submit_work + 1.19% +0.20% [kernel.kallsyms] [k] amd_iommu_iotlb_sync_map + 1.46% +0.15% [kernel.kallsyms] [k] ep_poll_callback + 1.80% +0.15% [kernel.kallsyms] [k] io_worker_handle_work + +HTTP server, PHP: + + 35.03% -1.80% [kernel.kallsyms] [k] queued_spin_lock_slowpath + 0.84% +0.21% [kernel.kallsyms] [k] amd_iommu_iotlb_sync_map + 1.39% +0.12% [kernel.kallsyms] [k] _copy_to_iter + 0.21% +0.10% [kernel.kallsyms] [k] update_sd_lb_stats + +Signed-off-by: Max Kellermann +Link: https://lore.kernel.org/r/20250128133927.3989681-5-max.kellermann@ionos.com +Signed-off-by: Jens Axboe +Stable-dep-of: 486ba4d84d62 ("io_uring/io-wq: do not use bogus hash value") +Signed-off-by: Sasha Levin +--- + io_uring/io-wq.c | 33 +++++++++++++++++++++------------ + io_uring/io-wq.h | 7 ++++++- + 2 files changed, 27 insertions(+), 13 deletions(-) + +diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c +index f7d09698e43ce..d1eaa3e39cd5f 100644 +--- a/io_uring/io-wq.c ++++ b/io_uring/io-wq.c +@@ -160,9 +160,9 @@ static inline struct io_wq_acct *io_get_acct(struct io_wq *wq, bool bound) + } + + static inline struct io_wq_acct *io_work_get_acct(struct io_wq *wq, +- struct io_wq_work *work) ++ unsigned int work_flags) + { +- return io_get_acct(wq, !(atomic_read(&work->flags) & IO_WQ_WORK_UNBOUND)); ++ return io_get_acct(wq, !(work_flags & IO_WQ_WORK_UNBOUND)); + } + + static inline struct io_wq_acct *io_wq_get_acct(struct io_worker *worker) +@@ -452,9 +452,14 @@ static void __io_worker_idle(struct io_wq *wq, struct io_worker *worker) + } + } + ++static inline unsigned int __io_get_work_hash(unsigned int work_flags) ++{ ++ return work_flags >> IO_WQ_HASH_SHIFT; ++} ++ + static inline unsigned int io_get_work_hash(struct io_wq_work *work) + { +- return atomic_read(&work->flags) >> IO_WQ_HASH_SHIFT; ++ return __io_get_work_hash(atomic_read(&work->flags)); + } + + static bool io_wait_on_hash(struct io_wq *wq, unsigned int hash) +@@ -484,17 +489,19 @@ static struct io_wq_work *io_get_next_work(struct io_wq_acct *acct, + struct io_wq *wq = worker->wq; + + wq_list_for_each(node, prev, &acct->work_list) { ++ unsigned int work_flags; + unsigned int hash; + + work = container_of(node, struct io_wq_work, list); + + /* not hashed, can run anytime */ +- if (!io_wq_is_hashed(work)) { ++ work_flags = atomic_read(&work->flags); ++ if (!__io_wq_is_hashed(work_flags)) { + wq_list_del(&acct->work_list, node, prev); + return work; + } + +- hash = io_get_work_hash(work); ++ hash = __io_get_work_hash(work_flags); + /* all items with this hash lie in [work, tail] */ + tail = wq->hash_tail[hash]; + +@@ -591,12 +598,13 @@ static void io_worker_handle_work(struct io_wq_acct *acct, + /* handle a whole dependent link */ + do { + struct io_wq_work *next_hashed, *linked; +- unsigned int hash = io_get_work_hash(work); ++ unsigned int work_flags = atomic_read(&work->flags); ++ unsigned int hash = __io_get_work_hash(work_flags); + + next_hashed = wq_next_work(work); + + if (do_kill && +- (atomic_read(&work->flags) & IO_WQ_WORK_UNBOUND)) ++ (work_flags & IO_WQ_WORK_UNBOUND)) + atomic_or(IO_WQ_WORK_CANCEL, &work->flags); + wq->do_work(work); + io_assign_current_work(worker, NULL); +@@ -916,18 +924,19 @@ static void io_run_cancel(struct io_wq_work *work, struct io_wq *wq) + } while (work); + } + +-static void io_wq_insert_work(struct io_wq *wq, struct io_wq_acct *acct, struct io_wq_work *work) ++static void io_wq_insert_work(struct io_wq *wq, struct io_wq_acct *acct, ++ struct io_wq_work *work, unsigned int work_flags) + { + unsigned int hash; + struct io_wq_work *tail; + +- if (!io_wq_is_hashed(work)) { ++ if (!__io_wq_is_hashed(work_flags)) { + append: + wq_list_add_tail(&work->list, &acct->work_list); + return; + } + +- hash = io_get_work_hash(work); ++ hash = __io_get_work_hash(work_flags); + tail = wq->hash_tail[hash]; + wq->hash_tail[hash] = work; + if (!tail) +@@ -943,8 +952,8 @@ static bool io_wq_work_match_item(struct io_wq_work *work, void *data) + + void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work) + { +- struct io_wq_acct *acct = io_work_get_acct(wq, work); + unsigned int work_flags = atomic_read(&work->flags); ++ struct io_wq_acct *acct = io_work_get_acct(wq, work_flags); + struct io_cb_cancel_data match = { + .fn = io_wq_work_match_item, + .data = work, +@@ -963,7 +972,7 @@ void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work) + } + + raw_spin_lock(&acct->lock); +- io_wq_insert_work(wq, acct, work); ++ io_wq_insert_work(wq, acct, work, work_flags); + clear_bit(IO_ACCT_STALLED_BIT, &acct->flags); + raw_spin_unlock(&acct->lock); + +diff --git a/io_uring/io-wq.h b/io_uring/io-wq.h +index b3b004a7b6252..d4fb2940e435f 100644 +--- a/io_uring/io-wq.h ++++ b/io_uring/io-wq.h +@@ -54,9 +54,14 @@ int io_wq_cpu_affinity(struct io_uring_task *tctx, cpumask_var_t mask); + int io_wq_max_workers(struct io_wq *wq, int *new_count); + bool io_wq_worker_stopped(void); + ++static inline bool __io_wq_is_hashed(unsigned int work_flags) ++{ ++ return work_flags & IO_WQ_WORK_HASHED; ++} ++ + static inline bool io_wq_is_hashed(struct io_wq_work *work) + { +- return atomic_read(&work->flags) & IO_WQ_WORK_HASHED; ++ return __io_wq_is_hashed(atomic_read(&work->flags)); + } + + typedef bool (work_cancel_fn)(struct io_wq_work *, void *); +-- +2.39.5 + diff --git a/queue-6.14/io_uring-io-wq-do-not-use-bogus-hash-value.patch b/queue-6.14/io_uring-io-wq-do-not-use-bogus-hash-value.patch new file mode 100644 index 0000000000..dc499aa344 --- /dev/null +++ b/queue-6.14/io_uring-io-wq-do-not-use-bogus-hash-value.patch @@ -0,0 +1,56 @@ +From 7749467c5f9aa433ee66e585741f7c9e04cb203f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jan 2025 14:39:24 +0100 +Subject: io_uring/io-wq: do not use bogus hash value + +From: Max Kellermann + +[ Upstream commit 486ba4d84d62e92716cd395c4b1612b8ce70a257 ] + +Previously, the `hash` variable was initialized with `-1` and only +updated by io_get_next_work() if the current work was hashed. Commit +60cf46ae6054 ("io-wq: hash dependent work") changed this to always +call io_get_work_hash() even if the work was not hashed. This caused +the `hash != -1U` check to always be true, adding some overhead for +the `hash->wait` code. + +This patch fixes the regression by checking the `IO_WQ_WORK_HASHED` +flag. + +Perf diff for a flood of `IORING_OP_NOP` with `IOSQE_ASYNC`: + + 38.55% -1.57% [kernel.kallsyms] [k] queued_spin_lock_slowpath + 6.86% -0.72% [kernel.kallsyms] [k] io_worker_handle_work + 0.10% +0.67% [kernel.kallsyms] [k] put_prev_entity + 1.96% +0.59% [kernel.kallsyms] [k] io_nop_prep + 3.31% -0.51% [kernel.kallsyms] [k] try_to_wake_up + 7.18% -0.47% [kernel.kallsyms] [k] io_wq_free_work + +Fixes: 60cf46ae6054 ("io-wq: hash dependent work") +Cc: Pavel Begunkov +Signed-off-by: Max Kellermann +Link: https://lore.kernel.org/r/20250128133927.3989681-6-max.kellermann@ionos.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/io-wq.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c +index d1eaa3e39cd5f..24f06fba43096 100644 +--- a/io_uring/io-wq.c ++++ b/io_uring/io-wq.c +@@ -599,7 +599,9 @@ static void io_worker_handle_work(struct io_wq_acct *acct, + do { + struct io_wq_work *next_hashed, *linked; + unsigned int work_flags = atomic_read(&work->flags); +- unsigned int hash = __io_get_work_hash(work_flags); ++ unsigned int hash = __io_wq_is_hashed(work_flags) ++ ? __io_get_work_hash(work_flags) ++ : -1U; + + next_hashed = wq_next_work(work); + +-- +2.39.5 + diff --git a/queue-6.14/io_uring-io-wq-eliminate-redundant-io_work_get_acct-.patch b/queue-6.14/io_uring-io-wq-eliminate-redundant-io_work_get_acct-.patch new file mode 100644 index 0000000000..c83da4e399 --- /dev/null +++ b/queue-6.14/io_uring-io-wq-eliminate-redundant-io_work_get_acct-.patch @@ -0,0 +1,72 @@ +From 60788765a619d0a24f7afb2cbbdc82cca878d72b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jan 2025 14:39:20 +0100 +Subject: io_uring/io-wq: eliminate redundant io_work_get_acct() calls + +From: Max Kellermann + +[ Upstream commit 3c75635f8ed482300931327847c50068a865a648 ] + +Instead of calling io_work_get_acct() again, pass acct to +io_wq_insert_work() and io_wq_remove_pending(). + +This atomic access in io_work_get_acct() was done under the +`acct->lock`, and optimizing it away reduces lock contention a bit. + +Signed-off-by: Max Kellermann +Link: https://lore.kernel.org/r/20250128133927.3989681-2-max.kellermann@ionos.com +Signed-off-by: Jens Axboe +Stable-dep-of: 486ba4d84d62 ("io_uring/io-wq: do not use bogus hash value") +Signed-off-by: Sasha Levin +--- + io_uring/io-wq.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c +index 91019b4d03088..f7d09698e43ce 100644 +--- a/io_uring/io-wq.c ++++ b/io_uring/io-wq.c +@@ -916,9 +916,8 @@ static void io_run_cancel(struct io_wq_work *work, struct io_wq *wq) + } while (work); + } + +-static void io_wq_insert_work(struct io_wq *wq, struct io_wq_work *work) ++static void io_wq_insert_work(struct io_wq *wq, struct io_wq_acct *acct, struct io_wq_work *work) + { +- struct io_wq_acct *acct = io_work_get_acct(wq, work); + unsigned int hash; + struct io_wq_work *tail; + +@@ -964,7 +963,7 @@ void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work) + } + + raw_spin_lock(&acct->lock); +- io_wq_insert_work(wq, work); ++ io_wq_insert_work(wq, acct, work); + clear_bit(IO_ACCT_STALLED_BIT, &acct->flags); + raw_spin_unlock(&acct->lock); + +@@ -1034,10 +1033,10 @@ static bool io_wq_worker_cancel(struct io_worker *worker, void *data) + } + + static inline void io_wq_remove_pending(struct io_wq *wq, ++ struct io_wq_acct *acct, + struct io_wq_work *work, + struct io_wq_work_node *prev) + { +- struct io_wq_acct *acct = io_work_get_acct(wq, work); + unsigned int hash = io_get_work_hash(work); + struct io_wq_work *prev_work = NULL; + +@@ -1064,7 +1063,7 @@ static bool io_acct_cancel_pending_work(struct io_wq *wq, + work = container_of(node, struct io_wq_work, list); + if (!match->fn(work, match->data)) + continue; +- io_wq_remove_pending(wq, work, prev); ++ io_wq_remove_pending(wq, acct, work, prev); + raw_spin_unlock(&acct->lock); + io_run_cancel(work, wq); + match->nr_pending++; +-- +2.39.5 + diff --git a/queue-6.14/io_uring-net-improve-recv-bundles.patch b/queue-6.14/io_uring-net-improve-recv-bundles.patch new file mode 100644 index 0000000000..ea48a4a615 --- /dev/null +++ b/queue-6.14/io_uring-net-improve-recv-bundles.patch @@ -0,0 +1,133 @@ +From 22e4a71444dfc6c063a80d3ffe7773416ae25679 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Feb 2025 10:50:34 -0700 +Subject: io_uring/net: improve recv bundles + +From: Jens Axboe + +[ Upstream commit 7c71a0af81ba72de9b2c501065e4e718aba9a271 ] + +Current recv bundles are only supported for multishot receives, and +additionally they also always post at least 2 CQEs if more data is +available than what a buffer will hold. This happens because the initial +bundle recv will do a single buffer, and then do the rest of what is in +the socket as a followup receive. As shown in a test program, if 1k +buffers are available and 32k is available to receive in the socket, +you'd get the following completions: + +bundle=1, mshot=0 +cqe res 1024 +cqe res 1024 +[...] +cqe res 1024 + +bundle=1, mshot=1 +cqe res 1024 +cqe res 31744 + +where bundle=1 && mshot=0 will post 32 1k completions, and bundle=1 && +mshot=1 will post a 1k completion and then a 31k completion. + +To support bundle recv without multishot, it's possible to simply retry +the recv immediately and post a single completion, rather than split it +into two completions. With the below patch, the same test looks as +follows: + +bundle=1, mshot=0 +cqe res 32768 + +bundle=1, mshot=1 +cqe res 32768 + +where mshot=0 works fine for bundles, and both of them post just a +single 32k completion rather than split it into separate completions. +Posting fewer completions is always a nice win, and not needing +multishot for proper bundle efficiency is nice for cases that can't +necessarily use multishot. + +Reported-by: Norman Maurer +Link: https://lore.kernel.org/r/184f9f92-a682-4205-a15d-89e18f664502@kernel.dk +Fixes: 2f9c9515bdfd ("io_uring/net: support bundles for recv") +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/net.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/io_uring/net.c b/io_uring/net.c +index 50e8a3ccc9de9..e9bea0235c130 100644 +--- a/io_uring/net.c ++++ b/io_uring/net.c +@@ -76,6 +76,7 @@ struct io_sr_msg { + /* initialised and used only by !msg send variants */ + u16 buf_group; + u16 buf_index; ++ bool retry; + void __user *msg_control; + /* used only for send zerocopy */ + struct io_kiocb *notif; +@@ -187,6 +188,7 @@ static inline void io_mshot_prep_retry(struct io_kiocb *req, + + req->flags &= ~REQ_F_BL_EMPTY; + sr->done_io = 0; ++ sr->retry = false; + sr->len = 0; /* get from the provided buffer */ + req->buf_index = sr->buf_group; + } +@@ -404,6 +406,7 @@ int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) + struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg); + + sr->done_io = 0; ++ sr->retry = false; + + if (req->opcode != IORING_OP_SEND) { + if (sqe->addr2 || sqe->file_index) +@@ -786,6 +789,7 @@ int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) + struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg); + + sr->done_io = 0; ++ sr->retry = false; + + if (unlikely(sqe->file_index || sqe->addr2)) + return -EINVAL; +@@ -834,6 +838,9 @@ int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) + return io_recvmsg_prep_setup(req); + } + ++/* bits to clear in old and inherit in new cflags on bundle retry */ ++#define CQE_F_MASK (IORING_CQE_F_SOCK_NONEMPTY|IORING_CQE_F_MORE) ++ + /* + * Finishes io_recv and io_recvmsg. + * +@@ -853,9 +860,19 @@ static inline bool io_recv_finish(struct io_kiocb *req, int *ret, + if (sr->flags & IORING_RECVSEND_BUNDLE) { + cflags |= io_put_kbufs(req, *ret, io_bundle_nbufs(kmsg, *ret), + issue_flags); ++ if (sr->retry) ++ cflags = req->cqe.flags | (cflags & CQE_F_MASK); + /* bundle with no more immediate buffers, we're done */ + if (req->flags & REQ_F_BL_EMPTY) + goto finish; ++ /* if more is available, retry and append to this one */ ++ if (!sr->retry && kmsg->msg.msg_inq > 0 && *ret > 0) { ++ req->cqe.flags = cflags & ~CQE_F_MASK; ++ sr->len = kmsg->msg.msg_inq; ++ sr->done_io += *ret; ++ sr->retry = true; ++ return false; ++ } + } else { + cflags |= io_put_kbuf(req, *ret, issue_flags); + } +@@ -1234,6 +1251,7 @@ int io_send_zc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) + struct io_kiocb *notif; + + zc->done_io = 0; ++ zc->retry = false; + req->flags |= REQ_F_POLL_NO_LAZY; + + if (unlikely(READ_ONCE(sqe->__pad2[0]) || READ_ONCE(sqe->addr3))) +-- +2.39.5 + diff --git a/queue-6.14/io_uring-net-only-import-send_zc-buffer-once.patch b/queue-6.14/io_uring-net-only-import-send_zc-buffer-once.patch new file mode 100644 index 0000000000..3e3b752f13 --- /dev/null +++ b/queue-6.14/io_uring-net-only-import-send_zc-buffer-once.patch @@ -0,0 +1,60 @@ +From aedf91129a4b50679b6310ea092dc26631343b8f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 12:48:17 -0600 +Subject: io_uring/net: only import send_zc buffer once + +From: Caleb Sander Mateos + +[ Upstream commit 8e3100fcc5cbba03518b8b5c059624aba5c29d50 ] + +io_send_zc() guards its call to io_send_zc_import() with if (!done_io) +in an attempt to avoid calling it redundantly on the same req. However, +if the initial non-blocking issue returns -EAGAIN, done_io will stay 0. +This causes the subsequent issue to unnecessarily re-import the buffer. + +Add an explicit flag "imported" to io_sr_msg to track if its buffer has +already been imported. Clear the flag in io_send_zc_prep(). Call +io_send_zc_import() and set the flag in io_send_zc() if it is unset. + +Signed-off-by: Caleb Sander Mateos +Fixes: 54cdcca05abd ("io_uring/net: switch io_send() and io_send_zc() to using io_async_msghdr") +Link: https://lore.kernel.org/r/20250321184819.3847386-2-csander@purestorage.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/net.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/io_uring/net.c b/io_uring/net.c +index e9bea0235c130..16d54cd4d53f3 100644 +--- a/io_uring/net.c ++++ b/io_uring/net.c +@@ -77,6 +77,7 @@ struct io_sr_msg { + u16 buf_group; + u16 buf_index; + bool retry; ++ bool imported; /* only for io_send_zc */ + void __user *msg_control; + /* used only for send zerocopy */ + struct io_kiocb *notif; +@@ -1252,6 +1253,7 @@ int io_send_zc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) + + zc->done_io = 0; + zc->retry = false; ++ zc->imported = false; + req->flags |= REQ_F_POLL_NO_LAZY; + + if (unlikely(READ_ONCE(sqe->__pad2[0]) || READ_ONCE(sqe->addr3))) +@@ -1414,7 +1416,8 @@ int io_send_zc(struct io_kiocb *req, unsigned int issue_flags) + (zc->flags & IORING_RECVSEND_POLL_FIRST)) + return -EAGAIN; + +- if (!zc->done_io) { ++ if (!zc->imported) { ++ zc->imported = true; + ret = io_send_zc_import(req, issue_flags); + if (unlikely(ret)) + return ret; +-- +2.39.5 + diff --git a/queue-6.14/io_uring-use-lockless_cq-flag-in-io_req_complete_pos.patch b/queue-6.14/io_uring-use-lockless_cq-flag-in-io_req_complete_pos.patch new file mode 100644 index 0000000000..c732d31340 --- /dev/null +++ b/queue-6.14/io_uring-use-lockless_cq-flag-in-io_req_complete_pos.patch @@ -0,0 +1,40 @@ +From ac8d0697a8246d85e7cd88880f3204fc07688efe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 17:51:18 -0700 +Subject: io_uring: use lockless_cq flag in io_req_complete_post() + +From: Caleb Sander Mateos + +[ Upstream commit 62aa9805d123165102273eb277f776aaca908e0e ] + +io_uring_create() computes ctx->lockless_cq as: +ctx->task_complete || (ctx->flags & IORING_SETUP_IOPOLL) + +So use it to simplify that expression in io_req_complete_post(). + +Signed-off-by: Caleb Sander Mateos +Reviewed-by: Li Zetao +Link: https://lore.kernel.org/r/20250212005119.3433005-1-csander@purestorage.com +Signed-off-by: Jens Axboe +Stable-dep-of: 3f0cb8de56b9 ("io_uring: fix retry handling off iowq") +Signed-off-by: Sasha Levin +--- + io_uring/io_uring.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index 573b3f542b82a..99b83487c8158 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -899,7 +899,7 @@ static void io_req_complete_post(struct io_kiocb *req, unsigned issue_flags) + * Handle special CQ sync cases via task_work. DEFER_TASKRUN requires + * the submitter task context, IOPOLL protects with uring_lock. + */ +- if (ctx->task_complete || (ctx->flags & IORING_SETUP_IOPOLL)) { ++ if (ctx->lockless_cq) { + req->io_task_work.func = io_req_task_complete; + io_req_task_work_add(req); + return; +-- +2.39.5 + diff --git a/queue-6.14/iommu-amd-fix-header-file.patch b/queue-6.14/iommu-amd-fix-header-file.patch new file mode 100644 index 0000000000..c46c673e23 --- /dev/null +++ b/queue-6.14/iommu-amd-fix-header-file.patch @@ -0,0 +1,46 @@ +From 5bf07061ffefdc855be064926ff1b51886dc4628 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 16:23:18 +0000 +Subject: iommu/amd: Fix header file + +From: Vasant Hegde + +[ Upstream commit ee4cf9260afe8e4be6b6d64f56fa7493d051d8de ] + +Move function declaration inside AMD_IOMMU_H defination. + +Fixes: fd5dff9de4be ("iommu/amd: Modify set_dte_entry() to use 256-bit DTE helpers") +Fixes: 457da5764668 ("iommu/amd: Lock DTE before updating the entry with WRITE_ONCE()") +Cc: Suravee Suthikulpanit +Signed-off-by: Vasant Hegde +Reviewed-by: Jason Gunthorpe +Link: https://lore.kernel.org/r/20250227162320.5805-6-vasant.hegde@amd.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/amd_iommu.h | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h +index 68debf5ee2d75..e3bf27da1339e 100644 +--- a/drivers/iommu/amd/amd_iommu.h ++++ b/drivers/iommu/amd/amd_iommu.h +@@ -176,12 +176,11 @@ void amd_iommu_apply_ivrs_quirks(void); + #else + static inline void amd_iommu_apply_ivrs_quirks(void) { } + #endif ++struct dev_table_entry *amd_iommu_get_ivhd_dte_flags(u16 segid, u16 devid); + + void amd_iommu_domain_set_pgtable(struct protection_domain *domain, + u64 *root, int mode); + struct dev_table_entry *get_dev_table(struct amd_iommu *iommu); +- +-#endif +- +-struct dev_table_entry *amd_iommu_get_ivhd_dte_flags(u16 segid, u16 devid); + struct iommu_dev_data *search_dev_data(struct amd_iommu *iommu, u16 devid); ++ ++#endif /* AMD_IOMMU_H */ +-- +2.39.5 + diff --git a/queue-6.14/iommu-handle-race-with-default-domain-setup.patch b/queue-6.14/iommu-handle-race-with-default-domain-setup.patch new file mode 100644 index 0000000000..7ec7107e24 --- /dev/null +++ b/queue-6.14/iommu-handle-race-with-default-domain-setup.patch @@ -0,0 +1,57 @@ +From 03a391950995413b4bddd9c0b4fb8a49469a6435 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 15:46:30 +0000 +Subject: iommu: Handle race with default domain setup + +From: Robin Murphy + +[ Upstream commit b46064a18810bad3aea089a79993ca5ea7a3d2b2 ] + +It turns out that deferred default domain creation leaves a subtle +race window during iommu_device_register() wherein a client driver may +asynchronously probe in parallel and get as far as performing DMA API +operations with dma-direct, only to be switched to iommu-dma underfoot +once the default domain attachment finally happens, with obviously +disastrous consequences. Even the wonky of_iommu_configure() path is at +risk, since iommu_fwspec_init() will no longer defer client probe as the +instance ops are (necessarily) already registered, and the "replay" +iommu_probe_device() call can see dev->iommu_group already set and so +think there's nothing to do either. + +Fortunately we already have the right tool in the right place in the +form of iommu_device_use_default_domain(), which just needs to ensure +that said default domain is actually ready to *be* used. Deferring the +client probe shouldn't have too much impact, given that this only +happens while the IOMMU driver is probing, and thus due to kick the +deferred probe list again once it finishes. + +Reported-by: Charan Teja Kalla +Fixes: 98ac73f99bc4 ("iommu: Require a default_domain for all iommu drivers") +Reviewed-by: Jason Gunthorpe +Signed-off-by: Robin Murphy +Link: https://lore.kernel.org/r/e88b94c9b575034a2c98a48b3d383654cbda7902.1740753261.git.robin.murphy@arm.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/iommu.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c +index 60aed01e54f27..e3df1f06afbeb 100644 +--- a/drivers/iommu/iommu.c ++++ b/drivers/iommu/iommu.c +@@ -3097,6 +3097,11 @@ int iommu_device_use_default_domain(struct device *dev) + return 0; + + mutex_lock(&group->mutex); ++ /* We may race against bus_iommu_probe() finalising groups here */ ++ if (!group->default_domain) { ++ ret = -EPROBE_DEFER; ++ goto unlock_out; ++ } + if (group->owner_cnt) { + if (group->domain != group->default_domain || group->owner || + !xa_empty(&group->pasid_array)) { +-- +2.39.5 + diff --git a/queue-6.14/iommu-io-pgtable-dart-only-set-subpage-protection-di.patch b/queue-6.14/iommu-io-pgtable-dart-only-set-subpage-protection-di.patch new file mode 100644 index 0000000000..58fd4ce83d --- /dev/null +++ b/queue-6.14/iommu-io-pgtable-dart-only-set-subpage-protection-di.patch @@ -0,0 +1,47 @@ +From 9486734923927d3d2704ff9bc58f41608155b59e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 10:13:53 +0100 +Subject: iommu/io-pgtable-dart: Only set subpage protection disable for DART 1 + +From: Asahi Lina + +[ Upstream commit 5276c1e07679c44ee021e88045bbb5190831b328 ] + +Subpage protection can't be disabled on t6000-style darts, +as such the disable flag no longer applies, and probably +even affects something else. + +Fixes: dc09fe1c5edd ("iommu/io-pgtable-dart: Add DART PTE support for t6000") +Signed-off-by: Asahi Lina +Signed-off-by: Sasha Finkelstein +Reviewed-by: Sven Peter +Link: https://lore.kernel.org/r/20250219-dart2-no-sp-disable-v1-1-9f324cfa4e70@gmail.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/io-pgtable-dart.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iommu/io-pgtable-dart.c b/drivers/iommu/io-pgtable-dart.c +index c004640640ee5..06aca9ab52f9a 100644 +--- a/drivers/iommu/io-pgtable-dart.c ++++ b/drivers/iommu/io-pgtable-dart.c +@@ -135,7 +135,6 @@ static int dart_init_pte(struct dart_io_pgtable *data, + pte |= FIELD_PREP(APPLE_DART_PTE_SUBPAGE_START, 0); + pte |= FIELD_PREP(APPLE_DART_PTE_SUBPAGE_END, 0xfff); + +- pte |= APPLE_DART1_PTE_PROT_SP_DIS; + pte |= APPLE_DART_PTE_VALID; + + for (i = 0; i < num_entries; i++) +@@ -211,6 +210,7 @@ static dart_iopte dart_prot_to_pte(struct dart_io_pgtable *data, + dart_iopte pte = 0; + + if (data->iop.fmt == APPLE_DART) { ++ pte |= APPLE_DART1_PTE_PROT_SP_DIS; + if (!(prot & IOMMU_WRITE)) + pte |= APPLE_DART1_PTE_PROT_NO_WRITE; + if (!(prot & IOMMU_READ)) +-- +2.39.5 + diff --git a/queue-6.14/iommu-vt-d-fix-system-hang-on-reboot-f.patch b/queue-6.14/iommu-vt-d-fix-system-hang-on-reboot-f.patch new file mode 100644 index 0000000000..2adb081448 --- /dev/null +++ b/queue-6.14/iommu-vt-d-fix-system-hang-on-reboot-f.patch @@ -0,0 +1,93 @@ +From dd5ec70a60d720099f6adebc4b1b4078b2699c7f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 10:47:44 +0800 +Subject: iommu/vt-d: Fix system hang on reboot -f + +From: Yunhui Cui + +[ Upstream commit 9ce7603ad3cbae64003087de57834e8c5c856a20 ] + +We found that executing the command ./a.out &;reboot -f (where a.out is a +program that only executes a while(1) infinite loop) can probabilistically +cause the system to hang in the intel_iommu_shutdown() function, rendering +it unresponsive. Through analysis, we identified that the factors +contributing to this issue are as follows: + +1. The reboot -f command does not prompt the kernel to notify the +application layer to perform cleanup actions, allowing the application to +continue running. + +2. When the kernel reaches the intel_iommu_shutdown() function, only the +BSP (Bootstrap Processor) CPU is operational in the system. + +3. During the execution of intel_iommu_shutdown(), the function down_write +(&dmar_global_lock) causes the process to sleep and be scheduled out. + +4. At this point, though the processor's interrupt flag is not cleared, + allowing interrupts to be accepted. However, only legacy devices and NMI +(Non-Maskable Interrupt) interrupts could come in, as other interrupts +routing have already been disabled. If no legacy or NMI interrupts occur +at this stage, the scheduler will not be able to run. + +5. If the application got scheduled at this time is executing a while(1)- +type loop, it will be unable to be preempted, leading to an infinite loop +and causing the system to become unresponsive. + +To resolve this issue, the intel_iommu_shutdown() function should not +execute down_write(), which can potentially cause the process to be +scheduled out. Furthermore, since only the BSP is running during the later +stages of the reboot, there is no need for protection against parallel +access to the DMAR (DMA Remapping) unit. Therefore, the following lines +could be removed: + +down_write(&dmar_global_lock); +up_write(&dmar_global_lock); + +After testing, the issue has been resolved. + +Fixes: 6c3a44ed3c55 ("iommu/vt-d: Turn off translations at shutdown") +Co-developed-by: Ethan Zhao +Signed-off-by: Ethan Zhao +Signed-off-by: Yunhui Cui +Link: https://lore.kernel.org/r/20250303062421.17929-1-cuiyunhui@bytedance.com +Signed-off-by: Lu Baolu +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/intel/iommu.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c +index bf1f0c8143483..25d31f8c129a6 100644 +--- a/drivers/iommu/intel/iommu.c ++++ b/drivers/iommu/intel/iommu.c +@@ -2871,16 +2871,19 @@ void intel_iommu_shutdown(void) + if (no_iommu || dmar_disabled) + return; + +- down_write(&dmar_global_lock); ++ /* ++ * All other CPUs were brought down, hotplug interrupts were disabled, ++ * no lock and RCU checking needed anymore ++ */ ++ list_for_each_entry(drhd, &dmar_drhd_units, list) { ++ iommu = drhd->iommu; + +- /* Disable PMRs explicitly here. */ +- for_each_iommu(iommu, drhd) ++ /* Disable PMRs explicitly here. */ + iommu_disable_protect_mem_regions(iommu); + +- /* Make sure the IOMMUs are switched off */ +- intel_disable_iommus(); +- +- up_write(&dmar_global_lock); ++ /* Make sure the IOMMUs are switched off */ ++ iommu_disable_translation(iommu); ++ } + } + + static struct intel_iommu *dev_to_intel_iommu(struct device *dev) +-- +2.39.5 + diff --git a/queue-6.14/ipv6-do-not-consider-link-down-nexthops-in-path-sele.patch b/queue-6.14/ipv6-do-not-consider-link-down-nexthops-in-path-sele.patch new file mode 100644 index 0000000000..244b5eb3ed --- /dev/null +++ b/queue-6.14/ipv6-do-not-consider-link-down-nexthops-in-path-sele.patch @@ -0,0 +1,64 @@ +From 6fb367a2bdb46f5af1e7a9fb578e4ae15688e726 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Apr 2025 14:42:24 +0300 +Subject: ipv6: Do not consider link down nexthops in path selection + +From: Ido Schimmel + +[ Upstream commit 8b8e0dd357165e0258d9f9cdab5366720ed2f619 ] + +Nexthops whose link is down are not supposed to be considered during +path selection when the "ignore_routes_with_linkdown" sysctl is set. +This is done by assigning them a negative region boundary. + +However, when comparing the computed hash (unsigned) with the region +boundary (signed), the negative region boundary is treated as unsigned, +resulting in incorrect nexthop selection. + +Fix by treating the computed hash as signed. Note that the computed hash +is always in range of [0, 2^31 - 1]. + +Fixes: 3d709f69a3e7 ("ipv6: Use hash-threshold instead of modulo-N") +Signed-off-by: Ido Schimmel +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20250402114224.293392-3-idosch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/route.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 07ff19ae263f5..169a7b9bc40ea 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -442,6 +442,7 @@ void fib6_select_path(const struct net *net, struct fib6_result *res, + { + struct fib6_info *first, *match = res->f6i; + struct fib6_info *sibling; ++ int hash; + + if (!match->nh && (!match->fib6_nsiblings || have_oif_match)) + goto out; +@@ -468,7 +469,8 @@ void fib6_select_path(const struct net *net, struct fib6_result *res, + if (!first) + goto out; + +- if (fl6->mp_hash <= atomic_read(&first->fib6_nh->fib_nh_upper_bound) && ++ hash = fl6->mp_hash; ++ if (hash <= atomic_read(&first->fib6_nh->fib_nh_upper_bound) && + rt6_score_route(first->fib6_nh, first->fib6_flags, oif, + strict) >= 0) { + match = first; +@@ -481,7 +483,7 @@ void fib6_select_path(const struct net *net, struct fib6_result *res, + int nh_upper_bound; + + nh_upper_bound = atomic_read(&nh->fib_nh_upper_bound); +- if (fl6->mp_hash > nh_upper_bound) ++ if (hash > nh_upper_bound) + continue; + if (rt6_score_route(nh, sibling->fib6_flags, oif, strict) < 0) + break; +-- +2.39.5 + diff --git a/queue-6.14/ipv6-fix-omitted-netlink-attributes-when-using-rtext.patch b/queue-6.14/ipv6-fix-omitted-netlink-attributes-when-using-rtext.patch new file mode 100644 index 0000000000..424889c04f --- /dev/null +++ b/queue-6.14/ipv6-fix-omitted-netlink-attributes-when-using-rtext.patch @@ -0,0 +1,87 @@ +From bf52317672eaee9039c9103cf725ffae264fbb93 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Apr 2025 14:17:51 +0200 +Subject: ipv6: fix omitted netlink attributes when using + RTEXT_FILTER_SKIP_STATS + +From: Fernando Fernandez Mancera + +[ Upstream commit 7ac6ea4a3e0898db76aecccd68fb2c403eb7d24e ] + +Using RTEXT_FILTER_SKIP_STATS is incorrectly skipping non-stats IPv6 +netlink attributes on link dump. This causes issues on userspace tools, +e.g iproute2 is not rendering address generation mode as it should due +to missing netlink attribute. + +Move the filling of IFLA_INET6_STATS and IFLA_INET6_ICMP6STATS to a +helper function guarded by a flag check to avoid hitting the same +situation in the future. + +Fixes: d5566fd72ec1 ("rtnetlink: RTEXT_FILTER_SKIP_STATS support to avoid dumping inet/inet6 stats") +Signed-off-by: Fernando Fernandez Mancera +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250402121751.3108-1-ffmancera@riseup.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/addrconf.c | 37 +++++++++++++++++++++++++------------ + 1 file changed, 25 insertions(+), 12 deletions(-) + +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c +index ac8cc10765360..54a8ea004da28 100644 +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -5784,6 +5784,27 @@ static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, + } + } + ++static int inet6_fill_ifla6_stats_attrs(struct sk_buff *skb, ++ struct inet6_dev *idev) ++{ ++ struct nlattr *nla; ++ ++ nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64)); ++ if (!nla) ++ goto nla_put_failure; ++ snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla)); ++ ++ nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64)); ++ if (!nla) ++ goto nla_put_failure; ++ snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla)); ++ ++ return 0; ++ ++nla_put_failure: ++ return -EMSGSIZE; ++} ++ + static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev, + u32 ext_filter_mask) + { +@@ -5806,18 +5827,10 @@ static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev, + + /* XXX - MC not implemented */ + +- if (ext_filter_mask & RTEXT_FILTER_SKIP_STATS) +- return 0; +- +- nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64)); +- if (!nla) +- goto nla_put_failure; +- snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla)); +- +- nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64)); +- if (!nla) +- goto nla_put_failure; +- snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla)); ++ if (!(ext_filter_mask & RTEXT_FILTER_SKIP_STATS)) { ++ if (inet6_fill_ifla6_stats_attrs(skb, idev) < 0) ++ goto nla_put_failure; ++ } + + nla = nla_reserve(skb, IFLA_INET6_TOKEN, sizeof(struct in6_addr)); + if (!nla) +-- +2.39.5 + diff --git a/queue-6.14/ipv6-start-path-selection-from-the-first-nexthop.patch b/queue-6.14/ipv6-start-path-selection-from-the-first-nexthop.patch new file mode 100644 index 0000000000..b110fc3c93 --- /dev/null +++ b/queue-6.14/ipv6-start-path-selection-from-the-first-nexthop.patch @@ -0,0 +1,101 @@ +From 7cffaf4157929a0ae26826a6338482ad25518363 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Apr 2025 14:42:23 +0300 +Subject: ipv6: Start path selection from the first nexthop + +From: Ido Schimmel + +[ Upstream commit 4d0ab3a6885e3e9040310a8d8f54503366083626 ] + +Cited commit transitioned IPv6 path selection to use hash-threshold +instead of modulo-N. With hash-threshold, each nexthop is assigned a +region boundary in the multipath hash function's output space and a +nexthop is chosen if the calculated hash is smaller than the nexthop's +region boundary. + +Hash-threshold does not work correctly if path selection does not start +with the first nexthop. For example, if fib6_select_path() is always +passed the last nexthop in the group, then it will always be chosen +because its region boundary covers the entire hash function's output +space. + +Fix this by starting the selection process from the first nexthop and do +not consider nexthops for which rt6_score_route() provided a negative +score. + +Fixes: 3d709f69a3e7 ("ipv6: Use hash-threshold instead of modulo-N") +Reported-by: Stanislav Fomichev +Closes: https://lore.kernel.org/netdev/Z9RIyKZDNoka53EO@mini-arch/ +Signed-off-by: Ido Schimmel +Link: https://patch.msgid.link/20250402114224.293392-2-idosch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/route.c | 38 +++++++++++++++++++++++++++++++++++--- + 1 file changed, 35 insertions(+), 3 deletions(-) + +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 15ce21afc8c62..07ff19ae263f5 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -412,11 +412,35 @@ static bool rt6_check_expired(const struct rt6_info *rt) + return false; + } + ++static struct fib6_info * ++rt6_multipath_first_sibling_rcu(const struct fib6_info *rt) ++{ ++ struct fib6_info *iter; ++ struct fib6_node *fn; ++ ++ fn = rcu_dereference(rt->fib6_node); ++ if (!fn) ++ goto out; ++ iter = rcu_dereference(fn->leaf); ++ if (!iter) ++ goto out; ++ ++ while (iter) { ++ if (iter->fib6_metric == rt->fib6_metric && ++ rt6_qualify_for_ecmp(iter)) ++ return iter; ++ iter = rcu_dereference(iter->fib6_next); ++ } ++ ++out: ++ return NULL; ++} ++ + void fib6_select_path(const struct net *net, struct fib6_result *res, + struct flowi6 *fl6, int oif, bool have_oif_match, + const struct sk_buff *skb, int strict) + { +- struct fib6_info *match = res->f6i; ++ struct fib6_info *first, *match = res->f6i; + struct fib6_info *sibling; + + if (!match->nh && (!match->fib6_nsiblings || have_oif_match)) +@@ -440,10 +464,18 @@ void fib6_select_path(const struct net *net, struct fib6_result *res, + return; + } + +- if (fl6->mp_hash <= atomic_read(&match->fib6_nh->fib_nh_upper_bound)) ++ first = rt6_multipath_first_sibling_rcu(match); ++ if (!first) + goto out; + +- list_for_each_entry_rcu(sibling, &match->fib6_siblings, ++ if (fl6->mp_hash <= atomic_read(&first->fib6_nh->fib_nh_upper_bound) && ++ rt6_score_route(first->fib6_nh, first->fib6_flags, oif, ++ strict) >= 0) { ++ match = first; ++ goto out; ++ } ++ ++ list_for_each_entry_rcu(sibling, &first->fib6_siblings, + fib6_siblings) { + const struct fib6_nh *nh = sibling->fib6_nh; + int nh_upper_bound; +-- +2.39.5 + diff --git a/queue-6.14/isofs-fix-kmsan-uninit-value-bug-in-do_isofs_readdir.patch b/queue-6.14/isofs-fix-kmsan-uninit-value-bug-in-do_isofs_readdir.patch new file mode 100644 index 0000000000..2069245f95 --- /dev/null +++ b/queue-6.14/isofs-fix-kmsan-uninit-value-bug-in-do_isofs_readdir.patch @@ -0,0 +1,89 @@ +From 913a6d2fac1e4b1bb1735149e19cc3886f724ae4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 19:59:00 +0000 +Subject: isofs: fix KMSAN uninit-value bug in do_isofs_readdir() + +From: Qasim Ijaz + +[ Upstream commit 81a82e8f33880793029cd6f8a766fb13b737e6a7 ] + +In do_isofs_readdir() when assigning the variable +"struct iso_directory_record *de" the b_data field of the buffer_head +is accessed and an offset is added to it, the size of b_data is 2048 +and the offset size is 2047, meaning +"de = (struct iso_directory_record *) (bh->b_data + offset);" +yields the final byte of the 2048 sized b_data block. + +The first byte of the directory record (de_len) is then read and +found to be 31, meaning the directory record size is 31 bytes long. +The directory record is defined by the structure: + + struct iso_directory_record { + __u8 length; // 1 byte + __u8 ext_attr_length; // 1 byte + __u8 extent[8]; // 8 bytes + __u8 size[8]; // 8 bytes + __u8 date[7]; // 7 bytes + __u8 flags; // 1 byte + __u8 file_unit_size; // 1 byte + __u8 interleave; // 1 byte + __u8 volume_sequence_number[4]; // 4 bytes + __u8 name_len; // 1 byte + char name[]; // variable size + } __attribute__((packed)); + +The fixed portion of this structure occupies 33 bytes. Therefore, a +valid directory record must be at least 33 bytes long +(even without considering the variable-length name field). +Since de_len is only 31, it is insufficient to contain +the complete fixed header. + +The code later hits the following sanity check that +compares de_len against the sum of de->name_len and +sizeof(struct iso_directory_record): + + if (de_len < de->name_len[0] + sizeof(struct iso_directory_record)) { + ... + } + +Since the fixed portion of the structure is +33 bytes (up to and including name_len member), +a valid record should have de_len of at least 33 bytes; +here, however, de_len is too short, and the field de->name_len +(located at offset 32) is accessed even though it lies beyond +the available 31 bytes. + +This access on the corrupted isofs data triggers a KASAN uninitialized +memory warning. The fix would be to first verify that de_len is at least +sizeof(struct iso_directory_record) before accessing any +fields like de->name_len. + +Reported-by: syzbot +Tested-by: syzbot +Closes: https://syzkaller.appspot.com/bug?extid=812641c6c3d7586a1613 +Fixes: 2deb1acc653c ("isofs: fix access to unallocated memory when reading corrupted filesystem") +Signed-off-by: Qasim Ijaz +Signed-off-by: Jan Kara +Link: https://patch.msgid.link/20250211195900.42406-1-qasdev00@gmail.com +Signed-off-by: Sasha Levin +--- + fs/isofs/dir.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c +index eb2f8273e6f15..09df40b612fbf 100644 +--- a/fs/isofs/dir.c ++++ b/fs/isofs/dir.c +@@ -147,7 +147,8 @@ static int do_isofs_readdir(struct inode *inode, struct file *file, + de = tmpde; + } + /* Basic sanity check, whether name doesn't exceed dir entry */ +- if (de_len < de->name_len[0] + ++ if (de_len < sizeof(struct iso_directory_record) || ++ de_len < de->name_len[0] + + sizeof(struct iso_directory_record)) { + printk(KERN_NOTICE "iso9660: Corrupted directory entry" + " in block %lu of inode %lu\n", block, +-- +2.39.5 + diff --git a/queue-6.14/ixgbe-fix-media-type-detection-for-e610-device.patch b/queue-6.14/ixgbe-fix-media-type-detection-for-e610-device.patch new file mode 100644 index 0000000000..04c976c3d8 --- /dev/null +++ b/queue-6.14/ixgbe-fix-media-type-detection-for-e610-device.patch @@ -0,0 +1,58 @@ +From 10e0957a46558ad9d1aec4653095f54026fbbb13 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 16:49:17 +0100 +Subject: ixgbe: fix media type detection for E610 device + +From: Piotr Kwapulinski + +[ Upstream commit 40206599beec98cfeb01913ee417f015e3f6190c ] + +The commit 23c0e5a16bcc ("ixgbe: Add link management support for E610 +device") introduced incorrect media type detection for E610 device. It +reproduces when advertised speed is modified after driver reload. Clear +the previous outdated PHY type high value. + +Reproduction steps: +modprobe ixgbe +ethtool -s eth0 advertise 0x1000000000000 +modprobe -r ixgbe +modprobe ixgbe +ethtool -s eth0 advertise 0x1000000000000 +Result before the fix: +netlink error: link settings update failed +netlink error: Invalid argument +Result after the fix: +No output error + +Fixes: 23c0e5a16bcc ("ixgbe: Add link management support for E610 device") +Reviewed-by: Przemek Kitszel +Reviewed-by: Paul Menzel +Signed-off-by: Piotr Kwapulinski +Reviewed-by: Simon Horman +Tested-by: Bharath R +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c +index cb07ecd8937d3..00935747c8c55 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c +@@ -1453,9 +1453,11 @@ enum ixgbe_media_type ixgbe_get_media_type_e610(struct ixgbe_hw *hw) + hw->link.link_info.phy_type_low = 0; + } else { + highest_bit = fls64(le64_to_cpu(pcaps.phy_type_low)); +- if (highest_bit) ++ if (highest_bit) { + hw->link.link_info.phy_type_low = + BIT_ULL(highest_bit - 1); ++ hw->link.link_info.phy_type_high = 0; ++ } + } + } + +-- +2.39.5 + diff --git a/queue-6.14/jbd2-add-a-missing-data-flush-during-file-and-fs-syn.patch b/queue-6.14/jbd2-add-a-missing-data-flush-during-file-and-fs-syn.patch new file mode 100644 index 0000000000..7687444e5d --- /dev/null +++ b/queue-6.14/jbd2-add-a-missing-data-flush-during-file-and-fs-syn.patch @@ -0,0 +1,70 @@ +From b585990ec3d5f2f3574b9395b0525dd1e43ea78d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 6 Dec 2024 19:13:27 +0800 +Subject: jbd2: add a missing data flush during file and fs synchronization + +From: Zhang Yi + +[ Upstream commit aac45075f6d79a63ac8dff93b3e1d7053a6ba628 ] + +When the filesystem performs file or filesystem synchronization (e.g., +ext4_sync_file()), it queries the journal to determine whether to flush +the file device through jbd2_trans_will_send_data_barrier(). If the +target transaction has not started committing, it assumes that the +journal will submit the flush command, allowing the filesystem to bypass +a redundant flush command. However, this assumption is not always valid. +If the journal is not located on the filesystem device, the journal +commit thread will not submit the flush command unless the variable +->t_need_data_flush is set to 1. Consequently, the flush may be missed, +and data may be lost following a power failure or system crash, even if +the synchronization appears to succeed. + +Unfortunately, we cannot determine with certainty whether the target +transaction will flush to the filesystem device before it commits. +However, if it has not started committing, it must be the running +transaction. Therefore, fix it by always set its t_need_data_flush to 1, +ensuring that the committing thread will flush the filesystem device. + +Fixes: bbd2be369107 ("jbd2: Add function jbd2_trans_will_send_data_barrier()") +Signed-off-by: Zhang Yi +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20241206111327.4171337-1-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/jbd2/journal.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c +index 49a9e99cbc03d..a10e086a0165b 100644 +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -603,7 +603,7 @@ int jbd2_journal_start_commit(journal_t *journal, tid_t *ptid) + int jbd2_trans_will_send_data_barrier(journal_t *journal, tid_t tid) + { + int ret = 0; +- transaction_t *commit_trans; ++ transaction_t *commit_trans, *running_trans; + + if (!(journal->j_flags & JBD2_BARRIER)) + return 0; +@@ -613,6 +613,16 @@ int jbd2_trans_will_send_data_barrier(journal_t *journal, tid_t tid) + goto out; + commit_trans = journal->j_committing_transaction; + if (!commit_trans || commit_trans->t_tid != tid) { ++ running_trans = journal->j_running_transaction; ++ /* ++ * The query transaction hasn't started committing, ++ * it must still be running. ++ */ ++ if (WARN_ON_ONCE(!running_trans || ++ running_trans->t_tid != tid)) ++ goto out; ++ ++ running_trans->t_need_data_flush = 1; + ret = 1; + goto out; + } +-- +2.39.5 + diff --git a/queue-6.14/jbd2-fix-off-by-one-while-erasing-journal.patch b/queue-6.14/jbd2-fix-off-by-one-while-erasing-journal.patch new file mode 100644 index 0000000000..d5401afde9 --- /dev/null +++ b/queue-6.14/jbd2-fix-off-by-one-while-erasing-journal.patch @@ -0,0 +1,85 @@ +From dc010836281f313cb42f5de07fe82aa458a168f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:59:55 +0800 +Subject: jbd2: fix off-by-one while erasing journal + +From: Zhang Yi + +[ Upstream commit 18aba2adb3e2a676fff0d81e51f5045f3c636666 ] + +In __jbd2_journal_erase(), the block_stop parameter includes the last +block of a contiguous region; however, the calculation of byte_stop is +incorrect, as it does not account for the bytes in that last block. +Consequently, the page cache is not cleared properly, which occasionally +causes the ext4/050 test to fail. + +Since block_stop operates on inclusion semantics, it involves repeated +increments and decrements by 1, significantly increasing the complexity +of the calculations. Optimize the calculation and fix the incorrect +byte_stop by make both block_stop and byte_stop to use exclusion +semantics. + +This fixes a failure in fstests ext4/050. + +Fixes: 01d5d96542fd ("ext4: add discard/zeroout flags to journal flush") +Signed-off-by: Zhang Yi +Reviewed-by: Baokun Li +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20250217065955.3829229-1-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/jbd2/journal.c | 15 ++++++--------- + 1 file changed, 6 insertions(+), 9 deletions(-) + +diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c +index d8084b31b3610..49a9e99cbc03d 100644 +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -1965,17 +1965,15 @@ static int __jbd2_journal_erase(journal_t *journal, unsigned int flags) + return err; + } + +- if (block_start == ~0ULL) { +- block_start = phys_block; +- block_stop = block_start - 1; +- } ++ if (block_start == ~0ULL) ++ block_stop = block_start = phys_block; + + /* + * last block not contiguous with current block, + * process last contiguous region and return to this block on + * next loop + */ +- if (phys_block != block_stop + 1) { ++ if (phys_block != block_stop) { + block--; + } else { + block_stop++; +@@ -1994,11 +1992,10 @@ static int __jbd2_journal_erase(journal_t *journal, unsigned int flags) + */ + byte_start = block_start * journal->j_blocksize; + byte_stop = block_stop * journal->j_blocksize; +- byte_count = (block_stop - block_start + 1) * +- journal->j_blocksize; ++ byte_count = (block_stop - block_start) * journal->j_blocksize; + + truncate_inode_pages_range(journal->j_dev->bd_mapping, +- byte_start, byte_stop); ++ byte_start, byte_stop - 1); + + if (flags & JBD2_JOURNAL_FLUSH_DISCARD) { + err = blkdev_issue_discard(journal->j_dev, +@@ -2013,7 +2010,7 @@ static int __jbd2_journal_erase(journal_t *journal, unsigned int flags) + } + + if (unlikely(err != 0)) { +- pr_err("JBD2: (error %d) unable to wipe journal at physical blocks %llu - %llu", ++ pr_err("JBD2: (error %d) unable to wipe journal at physical blocks [%llu, %llu)", + err, block_start, block_stop); + return err; + } +-- +2.39.5 + diff --git a/queue-6.14/jfs-add-check-read-only-before-truncation-in-jfs_tru.patch b/queue-6.14/jfs-add-check-read-only-before-truncation-in-jfs_tru.patch new file mode 100644 index 0000000000..d410fb94ac --- /dev/null +++ b/queue-6.14/jfs-add-check-read-only-before-truncation-in-jfs_tru.patch @@ -0,0 +1,56 @@ +From 781262b3ddbed7e7d7396caf53b6aac65749a913 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Dec 2024 17:49:14 +0300 +Subject: jfs: add check read-only before truncation in jfs_truncate_nolock() + +From: Vasiliy Kovalev + +[ Upstream commit b5799dd77054c1ec49b0088b006c9908e256843b ] + +Added a check for "read-only" mode in the `jfs_truncate_nolock` +function to avoid errors related to writing to a read-only +filesystem. + +Call stack: + +block_write_begin() { + jfs_write_failed() { + jfs_truncate() { + jfs_truncate_nolock() { + txEnd() { + ... + log = JFS_SBI(tblk->sb)->log; + // (log == NULL) + +If the `isReadOnly(ip)` condition is triggered in +`jfs_truncate_nolock`, the function execution will stop, and no +further data modification will occur. Instead, the `xtTruncate` +function will be called with the "COMMIT_WMAP" flag, preventing +modifications in "read-only" mode. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+4e89b5368baba8324e07@syzkaller.appspotmail.com +Link: https://syzkaller.appspot.com/bug?extid=4e89b5368baba8324e07 +Signed-off-by: Vasiliy Kovalev +Signed-off-by: Dave Kleikamp +Signed-off-by: Sasha Levin +--- + fs/jfs/inode.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c +index 07cfdc4405968..60fc92dee24d2 100644 +--- a/fs/jfs/inode.c ++++ b/fs/jfs/inode.c +@@ -369,7 +369,7 @@ void jfs_truncate_nolock(struct inode *ip, loff_t length) + + ASSERT(length >= 0); + +- if (test_cflag(COMMIT_Nolink, ip)) { ++ if (test_cflag(COMMIT_Nolink, ip) || isReadOnly(ip)) { + xtTruncate(0, ip, length, COMMIT_WMAP); + return; + } +-- +2.39.5 + diff --git a/queue-6.14/jfs-add-check-read-only-before-txbeginanon-call.patch b/queue-6.14/jfs-add-check-read-only-before-txbeginanon-call.patch new file mode 100644 index 0000000000..f71eb258c8 --- /dev/null +++ b/queue-6.14/jfs-add-check-read-only-before-txbeginanon-call.patch @@ -0,0 +1,63 @@ +From 81a70debc4e4a6cf2b53592d64919c07b5563061 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Dec 2024 17:49:13 +0300 +Subject: jfs: add check read-only before txBeginAnon() call + +From: Vasiliy Kovalev + +[ Upstream commit 0176e69743ecc02961f2ae1ea42439cd2bf9ed58 ] + +Added a read-only check before calling `txBeginAnon` in `extAlloc` +and `extRecord`. This prevents modification attempts on a read-only +mounted filesystem, avoiding potential errors or crashes. + +Call trace: + txBeginAnon+0xac/0x154 + extAlloc+0xe8/0xdec fs/jfs/jfs_extent.c:78 + jfs_get_block+0x340/0xb98 fs/jfs/inode.c:248 + __block_write_begin_int+0x580/0x166c fs/buffer.c:2128 + __block_write_begin fs/buffer.c:2177 [inline] + block_write_begin+0x98/0x11c fs/buffer.c:2236 + jfs_write_begin+0x44/0x88 fs/jfs/inode.c:299 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+4e89b5368baba8324e07@syzkaller.appspotmail.com +Link: https://syzkaller.appspot.com/bug?extid=4e89b5368baba8324e07 +Signed-off-by: Vasiliy Kovalev +Signed-off-by: Dave Kleikamp +Signed-off-by: Sasha Levin +--- + fs/jfs/jfs_extent.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c +index 63d21822d309b..46529bcc8297e 100644 +--- a/fs/jfs/jfs_extent.c ++++ b/fs/jfs/jfs_extent.c +@@ -74,6 +74,11 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr) + int rc; + int xflag; + ++ if (isReadOnly(ip)) { ++ jfs_error(ip->i_sb, "read-only filesystem\n"); ++ return -EIO; ++ } ++ + /* This blocks if we are low on resources */ + txBeginAnon(ip->i_sb); + +@@ -253,6 +258,11 @@ int extRecord(struct inode *ip, xad_t * xp) + { + int rc; + ++ if (isReadOnly(ip)) { ++ jfs_error(ip->i_sb, "read-only filesystem\n"); ++ return -EIO; ++ } ++ + txBeginAnon(ip->i_sb); + + mutex_lock(&JFS_IP(ip)->commit_mutex); +-- +2.39.5 + diff --git a/queue-6.14/jfs-reject-on-disk-inodes-of-an-unsupported-type.patch b/queue-6.14/jfs-reject-on-disk-inodes-of-an-unsupported-type.patch new file mode 100644 index 0000000000..b4ac28570b --- /dev/null +++ b/queue-6.14/jfs-reject-on-disk-inodes-of-an-unsupported-type.patch @@ -0,0 +1,116 @@ +From 47c44050d29a3a2e5749b9e17d1b9c4736d6ce89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Nov 2024 08:42:28 +0300 +Subject: jfs: reject on-disk inodes of an unsupported type + +From: Dmitry Antipov + +[ Upstream commit 8c3f9a70d2d4dd6c640afe294b05c6a0a45434d9 ] + +Syzbot has reported the following BUG: + +kernel BUG at fs/inode.c:668! +Oops: invalid opcode: 0000 [#1] PREEMPT SMP KASAN PTI +CPU: 3 UID: 0 PID: 139 Comm: jfsCommit Not tainted 6.12.0-rc4-syzkaller-00085-g4e46774408d9 #0 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-3.fc41 04/01/2014 +RIP: 0010:clear_inode+0x168/0x190 +Code: 4c 89 f7 e8 ba fe e5 ff e9 61 ff ff ff 44 89 f1 80 e1 07 80 c1 03 38 c1 7c c1 4c 89 f7 e8 90 ff e5 ff eb b7 + 0b e8 01 5d 7f ff 90 0f 0b e8 f9 5c 7f ff 90 0f 0b e8 f1 5c 7f +RSP: 0018:ffffc900027dfae8 EFLAGS: 00010093 +RAX: ffffffff82157a87 RBX: 0000000000000001 RCX: ffff888104d4b980 +RDX: 0000000000000000 RSI: 0000000000000001 RDI: 0000000000000000 +RBP: ffffc900027dfc90 R08: ffffffff82157977 R09: fffff520004fbf38 +R10: dffffc0000000000 R11: fffff520004fbf38 R12: dffffc0000000000 +R13: ffff88811315bc00 R14: ffff88811315bda8 R15: ffff88811315bb80 +FS: 0000000000000000(0000) GS:ffff888135f00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00005565222e0578 CR3: 0000000026ef0000 CR4: 00000000000006f0 +Call Trace: + + ? __die_body+0x5f/0xb0 + ? die+0x9e/0xc0 + ? do_trap+0x15a/0x3a0 + ? clear_inode+0x168/0x190 + ? do_error_trap+0x1dc/0x2c0 + ? clear_inode+0x168/0x190 + ? __pfx_do_error_trap+0x10/0x10 + ? report_bug+0x3cd/0x500 + ? handle_invalid_op+0x34/0x40 + ? clear_inode+0x168/0x190 + ? exc_invalid_op+0x38/0x50 + ? asm_exc_invalid_op+0x1a/0x20 + ? clear_inode+0x57/0x190 + ? clear_inode+0x167/0x190 + ? clear_inode+0x168/0x190 + ? clear_inode+0x167/0x190 + jfs_evict_inode+0xb5/0x440 + ? __pfx_jfs_evict_inode+0x10/0x10 + evict+0x4ea/0x9b0 + ? __pfx_evict+0x10/0x10 + ? iput+0x713/0xa50 + txUpdateMap+0x931/0xb10 + ? __pfx_txUpdateMap+0x10/0x10 + jfs_lazycommit+0x49a/0xb80 + ? _raw_spin_unlock_irqrestore+0x8f/0x140 + ? lockdep_hardirqs_on+0x99/0x150 + ? __pfx_jfs_lazycommit+0x10/0x10 + ? __pfx_default_wake_function+0x10/0x10 + ? __kthread_parkme+0x169/0x1d0 + ? __pfx_jfs_lazycommit+0x10/0x10 + kthread+0x2f2/0x390 + ? __pfx_jfs_lazycommit+0x10/0x10 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x4d/0x80 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + +This happens when 'clear_inode()' makes an attempt to finalize an underlying +JFS inode of unknown type. According to JFS layout description from +https://jfs.sourceforge.net/project/pub/jfslayout.pdf, inode types from 5 to +15 are reserved for future extensions and should not be encountered on a valid +filesystem. So add an extra check for valid inode type in 'copy_from_dinode()'. + +Reported-by: syzbot+ac2116e48989e84a2893@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=ac2116e48989e84a2893 +Fixes: 79ac5a46c5c1 ("jfs_lookup(): don't bother with . or ..") +Signed-off-by: Dmitry Antipov +Signed-off-by: Dave Kleikamp +Signed-off-by: Sasha Levin +--- + fs/jfs/jfs_imap.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c +index a360b24ed320c..debfc1389cb3e 100644 +--- a/fs/jfs/jfs_imap.c ++++ b/fs/jfs/jfs_imap.c +@@ -3029,14 +3029,23 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno, + * + * RETURN VALUES: + * 0 - success +- * -ENOMEM - insufficient memory ++ * -EINVAL - unexpected inode type + */ + static int copy_from_dinode(struct dinode * dip, struct inode *ip) + { + struct jfs_inode_info *jfs_ip = JFS_IP(ip); + struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb); ++ int fileset = le32_to_cpu(dip->di_fileset); ++ ++ switch (fileset) { ++ case AGGR_RESERVED_I: case AGGREGATE_I: case BMAP_I: ++ case LOG_I: case BADBLOCK_I: case FILESYSTEM_I: ++ break; ++ default: ++ return -EINVAL; ++ } + +- jfs_ip->fileset = le32_to_cpu(dip->di_fileset); ++ jfs_ip->fileset = fileset; + jfs_ip->mode2 = le32_to_cpu(dip->di_mode); + jfs_set_inode_flags(ip); + +-- +2.39.5 + diff --git a/queue-6.14/kernel-events-uprobes-handle-device-exclusive-entrie.patch b/queue-6.14/kernel-events-uprobes-handle-device-exclusive-entrie.patch new file mode 100644 index 0000000000..79cc112e4d --- /dev/null +++ b/queue-6.14/kernel-events-uprobes-handle-device-exclusive-entrie.patch @@ -0,0 +1,99 @@ +From 4d40a4739778621c30e7e11a265cefe1cfe46fd9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 20:37:50 +0100 +Subject: kernel/events/uprobes: handle device-exclusive entries correctly in + __replace_page() + +From: David Hildenbrand + +[ Upstream commit 096cbb80ab3fd85a9035ec17a1312c2a7db8bc8c ] + +Ever since commit b756a3b5e7ea ("mm: device exclusive memory access") we +can return with a device-exclusive entry from page_vma_mapped_walk(). + +__replace_page() is not prepared for that, so teach it about these PFN +swap PTEs. Note that device-private entries are so far not applicable on +that path, because GUP would never have returned such folios (conversion +to device-private happens by page migration, not in-place conversion of +the PTE). + +There is a race between GUP and us locking the folio to look it up using +page_vma_mapped_walk(), so this is likely a fix (unless something else +could prevent that race, but it doesn't look like). pte_pfn() on +something that is not a present pte could give use garbage, and we'd +wrongly mess up the mapcount because it was already adjusted by calling +folio_remove_rmap_pte() when making the entry device-exclusive. + +Link: https://lkml.kernel.org/r/20250210193801.781278-9-david@redhat.com +Fixes: b756a3b5e7ea ("mm: device exclusive memory access") +Signed-off-by: David Hildenbrand +Tested-by: Alistair Popple +Cc: Alex Shi +Cc: Danilo Krummrich +Cc: Dave Airlie +Cc: Jann Horn +Cc: Jason Gunthorpe +Cc: Jerome Glisse +Cc: John Hubbard +Cc: Jonathan Corbet +Cc: Karol Herbst +Cc: Liam Howlett +Cc: Lorenzo Stoakes +Cc: Lyude +Cc: "Masami Hiramatsu (Google)" +Cc: Oleg Nesterov +Cc: Pasha Tatashin +Cc: Peter Xu +Cc: Peter Zijlstra (Intel) +Cc: SeongJae Park +Cc: Simona Vetter +Cc: Vlastimil Babka +Cc: Yanteng Si +Cc: Barry Song +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + kernel/events/uprobes.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c +index b4ca8898fe178..eac24f39c2c2d 100644 +--- a/kernel/events/uprobes.c ++++ b/kernel/events/uprobes.c +@@ -173,6 +173,7 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr, + DEFINE_FOLIO_VMA_WALK(pvmw, old_folio, vma, addr, 0); + int err; + struct mmu_notifier_range range; ++ pte_t pte; + + mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, mm, addr, + addr + PAGE_SIZE); +@@ -192,6 +193,16 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr, + if (!page_vma_mapped_walk(&pvmw)) + goto unlock; + VM_BUG_ON_PAGE(addr != pvmw.address, old_page); ++ pte = ptep_get(pvmw.pte); ++ ++ /* ++ * Handle PFN swap PTES, such as device-exclusive ones, that actually ++ * map pages: simply trigger GUP again to fix it up. ++ */ ++ if (unlikely(!pte_present(pte))) { ++ page_vma_mapped_walk_done(&pvmw); ++ goto unlock; ++ } + + if (new_page) { + folio_get(new_folio); +@@ -206,7 +217,7 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr, + inc_mm_counter(mm, MM_ANONPAGES); + } + +- flush_cache_page(vma, addr, pte_pfn(ptep_get(pvmw.pte))); ++ flush_cache_page(vma, addr, pte_pfn(pte)); + ptep_clear_flush(vma, addr, pvmw.pte); + if (new_page) + set_pte_at(mm, addr, pvmw.pte, +-- +2.39.5 + diff --git a/queue-6.14/kexec-initialize-elf-lowest-address-to-ulong_max.patch b/queue-6.14/kexec-initialize-elf-lowest-address-to-ulong_max.patch new file mode 100644 index 0000000000..d22592eb87 --- /dev/null +++ b/queue-6.14/kexec-initialize-elf-lowest-address-to-ulong_max.patch @@ -0,0 +1,71 @@ +From fc826c964f336f33b21f8c445c7ecf453bf6a9f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 17:08:24 +0530 +Subject: kexec: initialize ELF lowest address to ULONG_MAX + +From: Sourabh Jain + +[ Upstream commit 9986fb5164c8b21f6439cfd45ba36d8cc80c9710 ] + +Patch series "powerpc/crash: use generic crashkernel reservation", v3. + +Commit 0ab97169aa05 ("crash_core: add generic function to do reservation") +added a generic function to reserve crashkernel memory. So let's use the +same function on powerpc and remove the architecture-specific code that +essentially does the same thing. + +The generic crashkernel reservation also provides a way to split the +crashkernel reservation into high and low memory reservations, which can +be enabled for powerpc in the future. + +Additionally move powerpc to use generic APIs to locate memory hole for +kexec segments while loading kdump kernel. + +This patch (of 7): + +kexec_elf_load() loads an ELF executable and sets the address of the +lowest PT_LOAD section to the address held by the lowest_load_addr +function argument. + +To determine the lowest PT_LOAD address, a local variable lowest_addr +(type unsigned long) is initialized to UINT_MAX. After loading each +PT_LOAD, its address is compared to lowest_addr. If a loaded PT_LOAD +address is lower, lowest_addr is updated. However, setting lowest_addr to +UINT_MAX won't work when the kernel image is loaded above 4G, as the +returned lowest PT_LOAD address would be invalid. This is resolved by +initializing lowest_addr to ULONG_MAX instead. + +This issue was discovered while implementing crashkernel high/low +reservation on the PowerPC architecture. + +Link: https://lkml.kernel.org/r/20250131113830.925179-1-sourabhjain@linux.ibm.com +Link: https://lkml.kernel.org/r/20250131113830.925179-2-sourabhjain@linux.ibm.com +Fixes: a0458284f062 ("powerpc: Add support code for kexec_file_load()") +Signed-off-by: Sourabh Jain +Acked-by: Hari Bathini +Acked-by: Baoquan He +Cc: Madhavan Srinivasan +Cc: Mahesh Salgaonkar +Cc: Michael Ellerman +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + kernel/kexec_elf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/kexec_elf.c b/kernel/kexec_elf.c +index d3689632e8b90..3a5c25b2adc94 100644 +--- a/kernel/kexec_elf.c ++++ b/kernel/kexec_elf.c +@@ -390,7 +390,7 @@ int kexec_elf_load(struct kimage *image, struct elfhdr *ehdr, + struct kexec_buf *kbuf, + unsigned long *lowest_load_addr) + { +- unsigned long lowest_addr = UINT_MAX; ++ unsigned long lowest_addr = ULONG_MAX; + int ret; + size_t i; + +-- +2.39.5 + diff --git a/queue-6.14/ksmbd-fix-multichannel-connection-failure.patch b/queue-6.14/ksmbd-fix-multichannel-connection-failure.patch new file mode 100644 index 0000000000..4a62e64df4 --- /dev/null +++ b/queue-6.14/ksmbd-fix-multichannel-connection-failure.patch @@ -0,0 +1,127 @@ +From 503a2bb079be46e3e1931eedc0bb6036eae60c67 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 20:19:20 +0900 +Subject: ksmbd: fix multichannel connection failure + +From: Namjae Jeon + +[ Upstream commit c1883049aa9b2b7dffd3a68c5fc67fa92c174bd9 ] + +ksmbd check that the session of second channel is in the session list of +first connection. If it is in session list, multichannel connection +should not be allowed. + +Fixes: b95629435b84 ("ksmbd: fix racy issue from session lookup and expire") +Reported-by: Sean Heelan +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/mgmt/user_session.c | 16 ++++++++++++++++ + fs/smb/server/mgmt/user_session.h | 2 ++ + fs/smb/server/smb2pdu.c | 12 ++++-------- + 3 files changed, 22 insertions(+), 8 deletions(-) + +diff --git a/fs/smb/server/mgmt/user_session.c b/fs/smb/server/mgmt/user_session.c +index 71c6939dfbf13..e5c835c8822ca 100644 +--- a/fs/smb/server/mgmt/user_session.c ++++ b/fs/smb/server/mgmt/user_session.c +@@ -256,6 +256,22 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn) + up_write(&sessions_table_lock); + } + ++bool is_ksmbd_session_in_connection(struct ksmbd_conn *conn, ++ unsigned long long id) ++{ ++ struct ksmbd_session *sess; ++ ++ down_read(&conn->session_lock); ++ sess = xa_load(&conn->sessions, id); ++ if (sess) { ++ up_read(&conn->session_lock); ++ return true; ++ } ++ up_read(&conn->session_lock); ++ ++ return false; ++} ++ + struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn, + unsigned long long id) + { +diff --git a/fs/smb/server/mgmt/user_session.h b/fs/smb/server/mgmt/user_session.h +index c1c4b20bd5c6c..f21348381d598 100644 +--- a/fs/smb/server/mgmt/user_session.h ++++ b/fs/smb/server/mgmt/user_session.h +@@ -87,6 +87,8 @@ void ksmbd_session_destroy(struct ksmbd_session *sess); + struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id); + struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn, + unsigned long long id); ++bool is_ksmbd_session_in_connection(struct ksmbd_conn *conn, ++ unsigned long long id); + int ksmbd_session_register(struct ksmbd_conn *conn, + struct ksmbd_session *sess); + void ksmbd_sessions_deregister(struct ksmbd_conn *conn); +diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c +index c53121538990e..ad4754339fa03 100644 +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -1707,44 +1707,38 @@ int smb2_sess_setup(struct ksmbd_work *work) + + if (conn->dialect != sess->dialect) { + rc = -EINVAL; +- ksmbd_user_session_put(sess); + goto out_err; + } + + if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) { + rc = -EINVAL; +- ksmbd_user_session_put(sess); + goto out_err; + } + + if (strncmp(conn->ClientGUID, sess->ClientGUID, + SMB2_CLIENT_GUID_SIZE)) { + rc = -ENOENT; +- ksmbd_user_session_put(sess); + goto out_err; + } + + if (sess->state == SMB2_SESSION_IN_PROGRESS) { + rc = -EACCES; +- ksmbd_user_session_put(sess); + goto out_err; + } + + if (sess->state == SMB2_SESSION_EXPIRED) { + rc = -EFAULT; +- ksmbd_user_session_put(sess); + goto out_err; + } +- ksmbd_user_session_put(sess); + + if (ksmbd_conn_need_reconnect(conn)) { + rc = -EFAULT; ++ ksmbd_user_session_put(sess); + sess = NULL; + goto out_err; + } + +- sess = ksmbd_session_lookup(conn, sess_id); +- if (!sess) { ++ if (is_ksmbd_session_in_connection(conn, sess_id)) { + rc = -EACCES; + goto out_err; + } +@@ -1910,6 +1904,8 @@ int smb2_sess_setup(struct ksmbd_work *work) + + sess->last_active = jiffies; + sess->state = SMB2_SESSION_EXPIRED; ++ ksmbd_user_session_put(sess); ++ work->sess = NULL; + if (try_delay) { + ksmbd_conn_set_need_reconnect(conn); + ssleep(5); +-- +2.39.5 + diff --git a/queue-6.14/ksmbd-fix-r_count-dec-increment-mismatch.patch b/queue-6.14/ksmbd-fix-r_count-dec-increment-mismatch.patch new file mode 100644 index 0000000000..5ded012cbe --- /dev/null +++ b/queue-6.14/ksmbd-fix-r_count-dec-increment-mismatch.patch @@ -0,0 +1,51 @@ +From a934c47e73eb6c32bc578bafd65fb1cbbf9b5c3d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Mar 2025 00:00:24 +0900 +Subject: ksmbd: fix r_count dec/increment mismatch + +From: Namjae Jeon + +[ Upstream commit ddb7ea36ba7129c2ed107e2186591128618864e1 ] + +r_count is only increased when there is an oplock break wait, +so r_count inc/decrement are not paired. This can cause r_count +to become negative, which can lead to a problem where the ksmbd +thread does not terminate. + +Fixes: 3aa660c05924 ("ksmbd: prevent connection release during oplock break notification") +Reported-by: Norbert Szetei +Tested-by: Norbert Szetei +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/oplock.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c +index 28886ff1ee577..8e6d226dc4e0a 100644 +--- a/fs/smb/server/oplock.c ++++ b/fs/smb/server/oplock.c +@@ -724,8 +724,8 @@ static int smb2_oplock_break_noti(struct oplock_info *opinfo) + work->conn = conn; + work->sess = opinfo->sess; + ++ ksmbd_conn_r_count_inc(conn); + if (opinfo->op_state == OPLOCK_ACK_WAIT) { +- ksmbd_conn_r_count_inc(conn); + INIT_WORK(&work->work, __smb2_oplock_break_noti); + ksmbd_queue_work(work); + +@@ -833,8 +833,8 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo) + work->conn = conn; + work->sess = opinfo->sess; + ++ ksmbd_conn_r_count_inc(conn); + if (opinfo->op_state == OPLOCK_ACK_WAIT) { +- ksmbd_conn_r_count_inc(conn); + INIT_WORK(&work->work, __smb2_lease_break_noti); + ksmbd_queue_work(work); + wait_for_break_ack(opinfo); +-- +2.39.5 + diff --git a/queue-6.14/ksmbd-use-aead_request_free-to-match-aead_request_al.patch b/queue-6.14/ksmbd-use-aead_request_free-to-match-aead_request_al.patch new file mode 100644 index 0000000000..8bd21cb89d --- /dev/null +++ b/queue-6.14/ksmbd-use-aead_request_free-to-match-aead_request_al.patch @@ -0,0 +1,38 @@ +From a62acf0706e11ef5b7b8507e346ddd7439e13db8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 20:12:34 +0800 +Subject: ksmbd: use aead_request_free to match aead_request_alloc + +From: Miaoqian Lin + +[ Upstream commit 6171063e9d046ffa46f51579b2ca4a43caef581a ] + +Use aead_request_free() instead of kfree() to properly free memory +allocated by aead_request_alloc(). This ensures sensitive crypto data +is zeroed before being freed. + +Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3") +Signed-off-by: Miaoqian Lin +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/auth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/smb/server/auth.c b/fs/smb/server/auth.c +index 2a5b4a96bf993..00b31cf864627 100644 +--- a/fs/smb/server/auth.c ++++ b/fs/smb/server/auth.c +@@ -1218,7 +1218,7 @@ int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov, + free_sg: + kfree(sg); + free_req: +- kfree(req); ++ aead_request_free(req); + free_ctx: + ksmbd_release_crypto_ctx(ctx); + return rc; +-- +2.39.5 + diff --git a/queue-6.14/kunit-stackinit-use-fill-byte-different-from-clang-i.patch b/queue-6.14/kunit-stackinit-use-fill-byte-different-from-clang-i.patch new file mode 100644 index 0000000000..9fb253f27e --- /dev/null +++ b/queue-6.14/kunit-stackinit-use-fill-byte-different-from-clang-i.patch @@ -0,0 +1,124 @@ +From 33edcc0de149657c2a1e244df967f7f0be8b3068 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 14:56:11 -0800 +Subject: kunit/stackinit: Use fill byte different from Clang i386 pattern + +From: Kees Cook + +[ Upstream commit d985e4399adffb58e10b38dbb5479ef29d53cde6 ] + +The byte initialization values used with -ftrivial-auto-var-init=pattern +(CONFIG_INIT_STACK_ALL_PATTERN=y) depends on the compiler, architecture, +and byte position relative to struct member types. On i386 with Clang, +this includes the 0xFF value, which means it looks like nothing changes +between the leaf byte filling pass and the expected "stack wiping" +pass of the stackinit test. + +Use the byte fill value of 0x99 instead, fixing the test for i386 Clang +builds. + +Reported-by: ernsteiswuerfel +Closes: https://github.com/ClangBuiltLinux/linux/issues/2071 +Fixes: 8c30d32b1a32 ("lib/test_stackinit: Handle Clang auto-initialization pattern") +Tested-by: Nathan Chancellor +Link: https://lore.kernel.org/r/20250304225606.work.030-kees@kernel.org +Signed-off-by: Kees Cook +Signed-off-by: Sasha Levin +--- + lib/stackinit_kunit.c | 30 ++++++++++++++++++++---------- + 1 file changed, 20 insertions(+), 10 deletions(-) + +diff --git a/lib/stackinit_kunit.c b/lib/stackinit_kunit.c +index 135322592faf8..63aa78e6f5c1a 100644 +--- a/lib/stackinit_kunit.c ++++ b/lib/stackinit_kunit.c +@@ -184,6 +184,15 @@ static bool stackinit_range_contains(char *haystack_start, size_t haystack_size, + #define INIT_UNION_assigned_copy(var_type) \ + INIT_STRUCT_assigned_copy(var_type) + ++/* ++ * The "did we actually fill the stack?" check value needs ++ * to be neither 0 nor any of the "pattern" bytes. The ++ * pattern bytes are compiler, architecture, and type based, ++ * so we have to pick a value that never appears for those ++ * combinations. Use 0x99 which is not 0xFF, 0xFE, nor 0xAA. ++ */ ++#define FILL_BYTE 0x99 ++ + /* + * @name: unique string name for the test + * @var_type: type to be tested for zeroing initialization +@@ -206,12 +215,12 @@ static noinline void test_ ## name (struct kunit *test) \ + ZERO_CLONE_ ## which(zero); \ + /* Clear entire check buffer for 0xFF overlap test. */ \ + memset(check_buf, 0x00, sizeof(check_buf)); \ +- /* Fill stack with 0xFF. */ \ ++ /* Fill stack with FILL_BYTE. */ \ + ignored = leaf_ ##name((unsigned long)&ignored, 1, \ + FETCH_ARG_ ## which(zero)); \ +- /* Verify all bytes overwritten with 0xFF. */ \ ++ /* Verify all bytes overwritten with FILL_BYTE. */ \ + for (sum = 0, i = 0; i < target_size; i++) \ +- sum += (check_buf[i] != 0xFF); \ ++ sum += (check_buf[i] != FILL_BYTE); \ + /* Clear entire check buffer for later bit tests. */ \ + memset(check_buf, 0x00, sizeof(check_buf)); \ + /* Extract stack-defined variable contents. */ \ +@@ -222,7 +231,8 @@ static noinline void test_ ## name (struct kunit *test) \ + * possible between the two leaf function calls. \ + */ \ + KUNIT_ASSERT_EQ_MSG(test, sum, 0, \ +- "leaf fill was not 0xFF!?\n"); \ ++ "leaf fill was not 0x%02X!?\n", \ ++ FILL_BYTE); \ + \ + /* Validate that compiler lined up fill and target. */ \ + KUNIT_ASSERT_TRUE_MSG(test, \ +@@ -234,9 +244,9 @@ static noinline void test_ ## name (struct kunit *test) \ + (int)((ssize_t)(uintptr_t)fill_start - \ + (ssize_t)(uintptr_t)target_start)); \ + \ +- /* Look for any bytes still 0xFF in check region. */ \ ++ /* Validate check region has no FILL_BYTE bytes. */ \ + for (sum = 0, i = 0; i < target_size; i++) \ +- sum += (check_buf[i] == 0xFF); \ ++ sum += (check_buf[i] == FILL_BYTE); \ + \ + if (sum != 0 && xfail) \ + kunit_skip(test, \ +@@ -271,12 +281,12 @@ static noinline int leaf_ ## name(unsigned long sp, bool fill, \ + * stack frame of SOME kind... \ + */ \ + memset(buf, (char)(sp & 0xff), sizeof(buf)); \ +- /* Fill variable with 0xFF. */ \ ++ /* Fill variable with FILL_BYTE. */ \ + if (fill) { \ + fill_start = &var; \ + fill_size = sizeof(var); \ + memset(fill_start, \ +- (char)((sp & 0xff) | forced_mask), \ ++ FILL_BYTE & forced_mask, \ + fill_size); \ + } \ + \ +@@ -469,7 +479,7 @@ static int noinline __leaf_switch_none(int path, bool fill) + fill_start = &var; + fill_size = sizeof(var); + +- memset(fill_start, forced_mask | 0x55, fill_size); ++ memset(fill_start, (forced_mask | 0x55) & FILL_BYTE, fill_size); + } + memcpy(check_buf, target_start, target_size); + break; +@@ -480,7 +490,7 @@ static int noinline __leaf_switch_none(int path, bool fill) + fill_start = &var; + fill_size = sizeof(var); + +- memset(fill_start, forced_mask | 0xaa, fill_size); ++ memset(fill_start, (forced_mask | 0xaa) & FILL_BYTE, fill_size); + } + memcpy(check_buf, target_start, target_size); + break; +-- +2.39.5 + diff --git a/queue-6.14/leds-fix-led_off-brightness-race.patch b/queue-6.14/leds-fix-led_off-brightness-race.patch new file mode 100644 index 0000000000..44c4e50cb9 --- /dev/null +++ b/queue-6.14/leds-fix-led_off-brightness-race.patch @@ -0,0 +1,108 @@ +From 82c4e71541d27ea35614de9fb1ffda28d14c5cfc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 12:23:17 +0100 +Subject: leds: Fix LED_OFF brightness race + +From: Remi Pommarel + +[ Upstream commit 2c70953b6f535f7698ccbf22c1f5ba26cb6c2816 ] + +While commit fa15d8c69238 ("leds: Fix set_brightness_delayed() race") +successfully forces led_set_brightness() to be called with LED_OFF at +least once when switching from blinking to LED on state so that +hw-blinking can be disabled, another race remains. Indeed in +led_set_brightness(LED_OFF) followed by led_set_brightness(any) +scenario the following CPU scheduling can happen: + + CPU0 CPU1 + ---- ---- + set_brightness_delayed() { + test_and_clear_bit(BRIGHTNESS_OFF) + led_set_brightness(LED_OFF) { + set_bit(BRIGHTNESS_OFF) + queue_work() + } + led_set_brightness(any) { + set_bit(BRIGHTNESS) + queue_work() //already queued + } + test_and_clear_bit(BRIGHTNESS) + /* LED set with brightness any */ + } + + /* From previous CPU1 queue_work() */ + set_brightness_delayed() { + test_and_clear_bit(BRIGHTNESS_OFF) + /* LED turned off */ + test_and_clear_bit(BRIGHTNESS) + /* Clear from previous run, LED remains off */ + +In that case the led_set_brightness(LED_OFF)/led_set_brightness(any) +sequence will be effectively executed in reverse order and LED will +remain off. + +With the introduction of commit 32360bf6a5d4 ("leds: Introduce ordered +workqueue for LEDs events instead of system_wq") the race is easier to +trigger as sysfs brightness configuration does not wait for +set_brightness_delayed() work to finish (flush_work() removal). + +Use delayed_set_value to optionnally re-configure brightness after a +LED_OFF. That way a LED state could be configured more that once but +final state will always be as expected. Ensure that delayed_set_value +modification is seen before set_bit() using smp_mb__before_atomic(). + +Fixes: fa15d8c69238 ("leds: Fix set_brightness_delayed() race") +Signed-off-by: Remi Pommarel +Reviewed-by: Hans de Goede +Link: https://lore.kernel.org/r/19c81177059dab7b656c42063958011a8e4d1a66.1740050412.git.repk@triplefau.lt +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/leds/led-core.c | 22 ++++++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c +index f6c46d2e5276b..e3d8ddcff5670 100644 +--- a/drivers/leds/led-core.c ++++ b/drivers/leds/led-core.c +@@ -159,8 +159,19 @@ static void set_brightness_delayed(struct work_struct *ws) + * before this work item runs once. To make sure this works properly + * handle LED_SET_BRIGHTNESS_OFF first. + */ +- if (test_and_clear_bit(LED_SET_BRIGHTNESS_OFF, &led_cdev->work_flags)) ++ if (test_and_clear_bit(LED_SET_BRIGHTNESS_OFF, &led_cdev->work_flags)) { + set_brightness_delayed_set_brightness(led_cdev, LED_OFF); ++ /* ++ * The consecutives led_set_brightness(LED_OFF), ++ * led_set_brightness(LED_FULL) could have been executed out of ++ * order (LED_FULL first), if the work_flags has been set ++ * between LED_SET_BRIGHTNESS_OFF and LED_SET_BRIGHTNESS of this ++ * work. To avoid ending with the LED turned off, turn the LED ++ * on again. ++ */ ++ if (led_cdev->delayed_set_value != LED_OFF) ++ set_bit(LED_SET_BRIGHTNESS, &led_cdev->work_flags); ++ } + + if (test_and_clear_bit(LED_SET_BRIGHTNESS, &led_cdev->work_flags)) + set_brightness_delayed_set_brightness(led_cdev, led_cdev->delayed_set_value); +@@ -331,10 +342,13 @@ void led_set_brightness_nopm(struct led_classdev *led_cdev, unsigned int value) + * change is done immediately afterwards (before the work runs), + * it uses a separate work_flag. + */ +- if (value) { +- led_cdev->delayed_set_value = value; ++ led_cdev->delayed_set_value = value; ++ /* Ensure delayed_set_value is seen before work_flags modification */ ++ smp_mb__before_atomic(); ++ ++ if (value) + set_bit(LED_SET_BRIGHTNESS, &led_cdev->work_flags); +- } else { ++ else { + clear_bit(LED_SET_BRIGHTNESS, &led_cdev->work_flags); + clear_bit(LED_SET_BLINK, &led_cdev->work_flags); + set_bit(LED_SET_BRIGHTNESS_OFF, &led_cdev->work_flags); +-- +2.39.5 + diff --git a/queue-6.14/leds-st1202-check-for-error-code-from-devm_mutex_ini.patch b/queue-6.14/leds-st1202-check-for-error-code-from-devm_mutex_ini.patch new file mode 100644 index 0000000000..2823238542 --- /dev/null +++ b/queue-6.14/leds-st1202-check-for-error-code-from-devm_mutex_ini.patch @@ -0,0 +1,44 @@ +From 8cf8349d75defe48386cf4eb7b0226e488b4419e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 07:52:50 +0100 +Subject: leds: st1202: Check for error code from devm_mutex_init() call +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Thomas Weißschuh + +[ Upstream commit 8168906bbb3ba678583422de29e6349407a94bb5 ] + +Even if it's not critical, the avoidance of checking the error code +from devm_mutex_init() call today diminishes the point of using devm +variant of it. Tomorrow it may even leak something. Add the missed +check. + +Fixes: 259230378c65 ("leds: Add LED1202 I2C driver") +Signed-off-by: Thomas Weißschuh +Link: https://lore.kernel.org/r/20250204-must_check-devm_mutex_init-v2-1-7b6271c4b7e6@weissschuh.net +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/leds/leds-st1202.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/leds/leds-st1202.c b/drivers/leds/leds-st1202.c +index e894b3f9a0f46..4cebc0203c227 100644 +--- a/drivers/leds/leds-st1202.c ++++ b/drivers/leds/leds-st1202.c +@@ -345,7 +345,9 @@ static int st1202_probe(struct i2c_client *client) + if (!chip) + return -ENOMEM; + +- devm_mutex_init(&client->dev, &chip->lock); ++ ret = devm_mutex_init(&client->dev, &chip->lock); ++ if (ret < 0) ++ return ret; + chip->client = client; + + ret = st1202_dt_init(chip); +-- +2.39.5 + diff --git a/queue-6.14/lib-842-improve-error-handling-in-sw842_compress.patch b/queue-6.14/lib-842-improve-error-handling-in-sw842_compress.patch new file mode 100644 index 0000000000..0dcdac3004 --- /dev/null +++ b/queue-6.14/lib-842-improve-error-handling-in-sw842_compress.patch @@ -0,0 +1,44 @@ +From b2bf5d1cdd9afa2b7789b6f748ce4dbdd347c03b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jan 2025 19:42:04 +0530 +Subject: lib: 842: Improve error handling in sw842_compress() + +From: Tanya Agarwal + +[ Upstream commit af324dc0e2b558678aec42260cce38be16cc77ca ] + +The static code analysis tool "Coverity Scan" pointed the following +implementation details out for further development considerations: +CID 1309755: Unused value +In sw842_compress: A value assigned to a variable is never used. (CWE-563) +returned_value: Assigning value from add_repeat_template(p, repeat_count) +to ret here, but that stored value is overwritten before it can be used. + +Conclusion: +Add error handling for the return value from an add_repeat_template() +call. + +Fixes: 2da572c959dd ("lib: add software 842 compression/decompression") +Signed-off-by: Tanya Agarwal +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + lib/842/842_compress.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/lib/842/842_compress.c b/lib/842/842_compress.c +index c02baa4168e16..055356508d97c 100644 +--- a/lib/842/842_compress.c ++++ b/lib/842/842_compress.c +@@ -532,6 +532,8 @@ int sw842_compress(const u8 *in, unsigned int ilen, + } + if (repeat_count) { + ret = add_repeat_template(p, repeat_count); ++ if (ret) ++ return ret; + repeat_count = 0; + if (next == last) /* reached max repeat bits */ + goto repeat; +-- +2.39.5 + diff --git a/queue-6.14/libbpf-add-namespace-for-errstr-making-it-libbpf_err.patch b/queue-6.14/libbpf-add-namespace-for-errstr-making-it-libbpf_err.patch new file mode 100644 index 0000000000..2567ef349b --- /dev/null +++ b/queue-6.14/libbpf-add-namespace-for-errstr-making-it-libbpf_err.patch @@ -0,0 +1,62 @@ +From ce046a03e3f3c9aad6f2b43a57c77f60124465b0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Mar 2025 15:24:39 -0700 +Subject: libbpf: Add namespace for errstr making it libbpf_errstr + +From: Ian Rogers + +[ Upstream commit 307ef667e94530c2f2f77797bfe9ea85c22bec7d ] + +When statically linking symbols can be replaced with those from other +statically linked libraries depending on the link order and the hoped +for "multiple definition" error may not appear. To avoid conflicts it +is good practice to namespace symbols, this change renames errstr to +libbpf_errstr. To avoid churn a #define is used to turn use of +errstr(err) to libbpf_errstr(err). + +Fixes: 1633a83bf993 ("libbpf: Introduce errstr() for stringifying errno") +Signed-off-by: Ian Rogers +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20250320222439.1350187-1-irogers@google.com +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/str_error.c | 2 +- + tools/lib/bpf/str_error.h | 7 +++++-- + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/tools/lib/bpf/str_error.c b/tools/lib/bpf/str_error.c +index 8743049e32b7d..9a541762f54c0 100644 +--- a/tools/lib/bpf/str_error.c ++++ b/tools/lib/bpf/str_error.c +@@ -36,7 +36,7 @@ char *libbpf_strerror_r(int err, char *dst, int len) + return dst; + } + +-const char *errstr(int err) ++const char *libbpf_errstr(int err) + { + static __thread char buf[12]; + +diff --git a/tools/lib/bpf/str_error.h b/tools/lib/bpf/str_error.h +index 66ffebde0684a..53e7fbffc13ec 100644 +--- a/tools/lib/bpf/str_error.h ++++ b/tools/lib/bpf/str_error.h +@@ -7,10 +7,13 @@ + char *libbpf_strerror_r(int err, char *dst, int len); + + /** +- * @brief **errstr()** returns string corresponding to numeric errno ++ * @brief **libbpf_errstr()** returns string corresponding to numeric errno + * @param err negative numeric errno + * @return pointer to string representation of the errno, that is invalidated + * upon the next call. + */ +-const char *errstr(int err); ++const char *libbpf_errstr(int err); ++ ++#define errstr(err) libbpf_errstr(err) ++ + #endif /* __LIBBPF_STR_ERROR_H */ +-- +2.39.5 + diff --git a/queue-6.14/libbpf-fix-accessing-btf.ext-core_relo-header.patch b/queue-6.14/libbpf-fix-accessing-btf.ext-core_relo-header.patch new file mode 100644 index 0000000000..c1c631fe23 --- /dev/null +++ b/queue-6.14/libbpf-fix-accessing-btf.ext-core_relo-header.patch @@ -0,0 +1,49 @@ +From fdc0529e04889d45502928a195b145d369307aff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 22:52:36 -0800 +Subject: libbpf: Fix accessing BTF.ext core_relo header + +From: Tony Ambardar + +[ Upstream commit 0a7c2a84359612e54328aa52030eb202093da6e2 ] + +Update btf_ext_parse_info() to ensure the core_relo header is present +before reading its fields. This avoids a potential buffer read overflow +reported by the OSS Fuzz project. + +Fixes: cf579164e9ea ("libbpf: Support BTF.ext loading and output in either endianness") +Signed-off-by: Tony Ambardar +Signed-off-by: Andrii Nakryiko +Link: https://issues.oss-fuzz.com/issues/388905046 +Link: https://lore.kernel.org/bpf/20250125065236.2603346-1-itugrok@yahoo.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/btf.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c +index 48c66f3a92002..560b519f820e2 100644 +--- a/tools/lib/bpf/btf.c ++++ b/tools/lib/bpf/btf.c +@@ -3015,8 +3015,6 @@ static int btf_ext_parse_info(struct btf_ext *btf_ext, bool is_native) + .desc = "line_info", + }; + struct btf_ext_sec_info_param core_relo = { +- .off = btf_ext->hdr->core_relo_off, +- .len = btf_ext->hdr->core_relo_len, + .min_rec_size = sizeof(struct bpf_core_relo), + .ext_info = &btf_ext->core_relo_info, + .desc = "core_relo", +@@ -3034,6 +3032,8 @@ static int btf_ext_parse_info(struct btf_ext *btf_ext, bool is_native) + if (btf_ext->hdr->hdr_len < offsetofend(struct btf_ext_header, core_relo_len)) + return 0; /* skip core relos parsing */ + ++ core_relo.off = btf_ext->hdr->core_relo_off; ++ core_relo.len = btf_ext->hdr->core_relo_len; + err = btf_ext_parse_sec_info(btf_ext, &core_relo, is_native); + if (err) + return err; +-- +2.39.5 + diff --git a/queue-6.14/libbpf-fix-hypothetical-stt_section-extern-null-dere.patch b/queue-6.14/libbpf-fix-hypothetical-stt_section-extern-null-dere.patch new file mode 100644 index 0000000000..56bf2f98d5 --- /dev/null +++ b/queue-6.14/libbpf-fix-hypothetical-stt_section-extern-null-dere.patch @@ -0,0 +1,41 @@ +From 78bd018ce080610f165bf87419e8b884a23579b7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 16:28:21 -0800 +Subject: libbpf: Fix hypothetical STT_SECTION extern NULL deref case + +From: Andrii Nakryiko + +[ Upstream commit e0525cd72b5979d8089fe524a071ea93fd011dc9 ] + +Fix theoretical NULL dereference in linker when resolving *extern* +STT_SECTION symbol against not-yet-existing ELF section. Not sure if +it's possible in practice for valid ELF object files (this would require +embedded assembly manipulations, at which point BTF will be missing), +but fix the s/dst_sym/dst_sec/ typo guarding this condition anyways. + +Fixes: faf6ed321cf6 ("libbpf: Add BPF static linker APIs") +Fixes: a46349227cd8 ("libbpf: Add linker extern resolution support for functions and global variables") +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/r/20250220002821.834400-1-andrii@kernel.org +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/linker.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/lib/bpf/linker.c b/tools/lib/bpf/linker.c +index b52f71c59616f..800e0ef09c378 100644 +--- a/tools/lib/bpf/linker.c ++++ b/tools/lib/bpf/linker.c +@@ -2163,7 +2163,7 @@ static int linker_append_elf_sym(struct bpf_linker *linker, struct src_obj *obj, + + obj->sym_map[src_sym_idx] = dst_sym_idx; + +- if (sym_type == STT_SECTION && dst_sym) { ++ if (sym_type == STT_SECTION && dst_sec) { + dst_sec->sec_sym_idx = dst_sym_idx; + dst_sym->st_value = 0; + } +-- +2.39.5 + diff --git a/queue-6.14/lockdep-don-t-disable-interrupts-on-rt-in-disable_ir.patch b/queue-6.14/lockdep-don-t-disable-interrupts-on-rt-in-disable_ir.patch new file mode 100644 index 0000000000..5c148f914d --- /dev/null +++ b/queue-6.14/lockdep-don-t-disable-interrupts-on-rt-in-disable_ir.patch @@ -0,0 +1,82 @@ +From 5e170c5bf91f7f4fb3e7df04df04c746d2b66e35 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 11:36:18 +0100 +Subject: lockdep: Don't disable interrupts on RT in + disable_irq_nosync_lockdep.*() + +From: Sebastian Andrzej Siewior + +[ Upstream commit 87886b32d669abc11c7be95ef44099215e4f5788 ] + +disable_irq_nosync_lockdep() disables interrupts with lockdep enabled to +avoid false positive reports by lockdep that a certain lock has not been +acquired with disabled interrupts. The user of this macros expects that +a lock can be acquried without disabling interrupts because the IRQ line +triggering the interrupt is disabled. + +This triggers a warning on PREEMPT_RT because after +disable_irq_nosync_lockdep.*() the following spinlock_t now is acquired +with disabled interrupts. + +On PREEMPT_RT there is no difference between spin_lock() and +spin_lock_irq() so avoiding disabling interrupts in this case works for +the two remaining callers as of today. + +Don't disable interrupts on PREEMPT_RT in disable_irq_nosync_lockdep.*(). + +Closes: https://lore.kernel.org/760e34f9-6034-40e0-82a5-ee9becd24438@roeck-us.net +Fixes: e8106b941ceab ("[PATCH] lockdep: core, add enable/disable_irq_irqsave/irqrestore() APIs") +Reported-by: Guenter Roeck +Suggested-by: "Steven Rostedt (Google)" +Signed-off-by: Sebastian Andrzej Siewior +Signed-off-by: Peter Zijlstra (Intel) +Tested-by: Guenter Roeck +Link: https://lore.kernel.org/r/20250212103619.2560503-2-bigeasy@linutronix.de +Signed-off-by: Sasha Levin +--- + include/linux/interrupt.h | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h +index 8cd9327e4e78d..a1b1be9bf73b2 100644 +--- a/include/linux/interrupt.h ++++ b/include/linux/interrupt.h +@@ -448,7 +448,7 @@ irq_calc_affinity_vectors(unsigned int minvec, unsigned int maxvec, + static inline void disable_irq_nosync_lockdep(unsigned int irq) + { + disable_irq_nosync(irq); +-#ifdef CONFIG_LOCKDEP ++#if defined(CONFIG_LOCKDEP) && !defined(CONFIG_PREEMPT_RT) + local_irq_disable(); + #endif + } +@@ -456,7 +456,7 @@ static inline void disable_irq_nosync_lockdep(unsigned int irq) + static inline void disable_irq_nosync_lockdep_irqsave(unsigned int irq, unsigned long *flags) + { + disable_irq_nosync(irq); +-#ifdef CONFIG_LOCKDEP ++#if defined(CONFIG_LOCKDEP) && !defined(CONFIG_PREEMPT_RT) + local_irq_save(*flags); + #endif + } +@@ -471,7 +471,7 @@ static inline void disable_irq_lockdep(unsigned int irq) + + static inline void enable_irq_lockdep(unsigned int irq) + { +-#ifdef CONFIG_LOCKDEP ++#if defined(CONFIG_LOCKDEP) && !defined(CONFIG_PREEMPT_RT) + local_irq_enable(); + #endif + enable_irq(irq); +@@ -479,7 +479,7 @@ static inline void enable_irq_lockdep(unsigned int irq) + + static inline void enable_irq_lockdep_irqrestore(unsigned int irq, unsigned long *flags) + { +-#ifdef CONFIG_LOCKDEP ++#if defined(CONFIG_LOCKDEP) && !defined(CONFIG_PREEMPT_RT) + local_irq_restore(*flags); + #endif + enable_irq(irq); +-- +2.39.5 + diff --git a/queue-6.14/lockdep-mm-fix-might_fault-lockdep-check-of-current-.patch b/queue-6.14/lockdep-mm-fix-might_fault-lockdep-check-of-current-.patch new file mode 100644 index 0000000000..eec33f0af1 --- /dev/null +++ b/queue-6.14/lockdep-mm-fix-might_fault-lockdep-check-of-current-.patch @@ -0,0 +1,52 @@ +From 18188a48f4e56e881ef114f98b95dc55fd079474 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Nov 2024 14:39:10 +0100 +Subject: lockdep/mm: Fix might_fault() lockdep check of current->mm->mmap_lock + +From: Peter Zijlstra + +[ Upstream commit a1b65f3f7c6f7f0a08a7dba8be458c6415236487 ] + +Turns out that this commit, about 10 years ago: + + 9ec23531fd48 ("sched/preempt, mm/fault: Trigger might_sleep() in might_fault() with disabled pagefaults") + +... accidentally (and unnessecarily) put the lockdep part of +__might_fault() under CONFIG_DEBUG_ATOMIC_SLEEP=y. + +This is potentially notable because large distributions such as +Ubuntu are running with !CONFIG_DEBUG_ATOMIC_SLEEP. + +Restore the debug check. + +[ mingo: Update changelog. ] + +Fixes: 9ec23531fd48 ("sched/preempt, mm/fault: Trigger might_sleep() in might_fault() with disabled pagefaults") +Signed-off-by: Peter Zijlstra (Intel) +Signed-off-by: Ingo Molnar +Cc: Linus Torvalds +Cc: Andrew Morton +Link: https://lore.kernel.org/r/20241104135517.536628371@infradead.org +Signed-off-by: Sasha Levin +--- + mm/memory.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/mm/memory.c b/mm/memory.c +index fb7b8dc751679..4f6d9766a0460 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -6834,10 +6834,8 @@ void __might_fault(const char *file, int line) + if (pagefault_disabled()) + return; + __might_sleep(file, line); +-#if defined(CONFIG_DEBUG_ATOMIC_SLEEP) + if (current->mm) + might_lock_read(¤t->mm->mmap_lock); +-#endif + } + EXPORT_SYMBOL(__might_fault); + #endif +-- +2.39.5 + diff --git a/queue-6.14/loongarch-fix-device-node-refcount-leak-in-fdt_cpu_c.patch b/queue-6.14/loongarch-fix-device-node-refcount-leak-in-fdt_cpu_c.patch new file mode 100644 index 0000000000..3916f9c08c --- /dev/null +++ b/queue-6.14/loongarch-fix-device-node-refcount-leak-in-fdt_cpu_c.patch @@ -0,0 +1,36 @@ +From 18735de67374bd06d8782229f2dc15260d7a7389 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 30 Mar 2025 16:31:09 +0800 +Subject: LoongArch: Fix device node refcount leak in fdt_cpu_clk_init() + +From: Miaoqian Lin + +[ Upstream commit 2e3bc71e4f394ecf8f499d21923cf556b4bfa1e7 ] + +Add missing of_node_put() to properly handle the reference count of the +device node obtained from of_get_cpu_node(). + +Fixes: 44a01f1f726a ("LoongArch: Parsing CPU-related information from DTS") +Signed-off-by: Miaoqian Lin +Signed-off-by: Huacai Chen +Signed-off-by: Sasha Levin +--- + arch/loongarch/kernel/env.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/loongarch/kernel/env.c b/arch/loongarch/kernel/env.c +index 2f1f5b08638f8..27144de5c5fe4 100644 +--- a/arch/loongarch/kernel/env.c ++++ b/arch/loongarch/kernel/env.c +@@ -68,6 +68,8 @@ static int __init fdt_cpu_clk_init(void) + return -ENODEV; + + clk = of_clk_get(np, 0); ++ of_node_put(np); ++ + if (IS_ERR(clk)) + return -ENODEV; + +-- +2.39.5 + diff --git a/queue-6.14/loongarch-fix-help-text-of-cmdline_extend-in-kconfig.patch b/queue-6.14/loongarch-fix-help-text-of-cmdline_extend-in-kconfig.patch new file mode 100644 index 0000000000..23e5c77588 --- /dev/null +++ b/queue-6.14/loongarch-fix-help-text-of-cmdline_extend-in-kconfig.patch @@ -0,0 +1,41 @@ +From a1a85be7e4661fd9db01e51f1d76717cbe752874 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 30 Mar 2025 16:31:09 +0800 +Subject: LoongArch: Fix help text of CMDLINE_EXTEND in Kconfig +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: 谢致邦 (XIE Zhibang) + +[ Upstream commit be216cbc1ddf99a51915414ce147311c0dfd50a2 ] + +It is the built-in command line appended to the bootloader command line, +not the bootloader command line appended to the built-in command line. + +Fixes: fa96b57c1490 ("LoongArch: Add build infrastructure") +Signed-off-by: 谢致邦 (XIE Zhibang) +Signed-off-by: Huacai Chen +Signed-off-by: Sasha Levin +--- + arch/loongarch/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig +index 2b8bd27a852fe..bdb989c49c094 100644 +--- a/arch/loongarch/Kconfig ++++ b/arch/loongarch/Kconfig +@@ -382,8 +382,8 @@ config CMDLINE_BOOTLOADER + config CMDLINE_EXTEND + bool "Use built-in to extend bootloader kernel arguments" + help +- The command-line arguments provided during boot will be +- appended to the built-in command line. This is useful in ++ The built-in command line will be appended to the command- ++ line arguments provided during boot. This is useful in + cases where the provided arguments are insufficient and + you don't want to or cannot modify them. + +-- +2.39.5 + diff --git a/queue-6.14/loongarch-rework-the-arch_kgdb_breakpoint-implementa.patch b/queue-6.14/loongarch-rework-the-arch_kgdb_breakpoint-implementa.patch new file mode 100644 index 0000000000..a0b11cd9af --- /dev/null +++ b/queue-6.14/loongarch-rework-the-arch_kgdb_breakpoint-implementa.patch @@ -0,0 +1,74 @@ +From 3ac2c2fefe0edca42ed1531755f7980bed1a1e16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 30 Mar 2025 16:31:09 +0800 +Subject: LoongArch: Rework the arch_kgdb_breakpoint() implementation + +From: Yuli Wang + +[ Upstream commit 29c92a41c6d2879c1f62220fe4758dce191bb38f ] + +The arch_kgdb_breakpoint() function defines the kgdb_breakinst symbol +using inline assembly. + +1. There's a potential issue where the compiler might inline +arch_kgdb_breakpoint(), which would then define the kgdb_breakinst +symbol multiple times, leading to a linker error. + +To prevent this, declare arch_kgdb_breakpoint() as noinline. + +Fix follow error with LLVM-19 *only* when LTO_CLANG_FULL: + LD vmlinux.o + ld.lld-19: error: ld-temp.o :3:1: symbol 'kgdb_breakinst' is already defined + kgdb_breakinst: break 2 + ^ + +2. Remove "nop" in the inline assembly because it's meaningless for +LoongArch here. + +3. Add "STACK_FRAME_NON_STANDARD" for arch_kgdb_breakpoint() to avoid +the objtool warning. + +Fixes: e14dd076964e ("LoongArch: Add basic KGDB & KDB support") +Tested-by: Binbin Zhou +Co-developed-by: Winston Wen +Signed-off-by: Winston Wen +Co-developed-by: Wentao Guan +Signed-off-by: Wentao Guan +Signed-off-by: Yuli Wang +Signed-off-by: Huacai Chen +Signed-off-by: Sasha Levin +--- + arch/loongarch/kernel/kgdb.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/arch/loongarch/kernel/kgdb.c b/arch/loongarch/kernel/kgdb.c +index 445c452d72a79..7be5b4c0c9002 100644 +--- a/arch/loongarch/kernel/kgdb.c ++++ b/arch/loongarch/kernel/kgdb.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -224,13 +225,13 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) + regs->csr_era = pc; + } + +-void arch_kgdb_breakpoint(void) ++noinline void arch_kgdb_breakpoint(void) + { + __asm__ __volatile__ ( \ + ".globl kgdb_breakinst\n\t" \ +- "nop\n" \ + "kgdb_breakinst:\tbreak 2\n\t"); /* BRK_KDB = 2 */ + } ++STACK_FRAME_NON_STANDARD(arch_kgdb_breakpoint); + + /* + * Calls linux_debug_hook before the kernel dies. If KGDB is enabled, +-- +2.39.5 + diff --git a/queue-6.14/m68k-sun3-fix-debug_mmu_emu-build.patch b/queue-6.14/m68k-sun3-fix-debug_mmu_emu-build.patch new file mode 100644 index 0000000000..a04fe77d3d --- /dev/null +++ b/queue-6.14/m68k-sun3-fix-debug_mmu_emu-build.patch @@ -0,0 +1,94 @@ +From ea387c100c88f0581f1ee52e046e4ed18221fa8d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jan 2025 16:40:22 +0100 +Subject: m68k: sun3: Fix DEBUG_MMU_EMU build +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Geert Uytterhoeven + +[ Upstream commit 723be3c6ab31b320afe0075e2eb9b8dd41f3b6d1 ] + +With DEBUG_MMU_EMU enabled: + + arch/m68k/sun3/mmu_emu.c: In function ‘mmu_emu_handle_fault’: + arch/m68k/sun3/mmu_emu.c:420:38: error: implicit declaration of function ‘get_fs’; did you mean ‘sget_fc’? [-Werror=implicit-function-declaration] + 420 | pr_info("seg:%ld crp:%p ->", get_fs().seg, crp); + | ^~~~~~ + + [...] + + arch/m68k/sun3/mmu_emu.c:420:46: error: request for member ‘seg’ in something not a structure or union + 420 | pr_info("seg:%ld crp:%p ->", get_fs().seg, crp); + | ^ + +Fix this by reintroducing and using a helper to retrieve the current +value of the DFC register. + +While at it, replace "%p" by "%px", as there is no point in printing +obfuscated pointers during debugging. + +Fixes: 9fde0348640252c7 ("m68k: Remove set_fs()") +Signed-off-by: Geert Uytterhoeven +Link: https://lore.kernel.org/b1d12a1d24b4aea9f98d905383ba932b2dc382e6.1737387419.git.geert@linux-m68k.org +Signed-off-by: Sasha Levin +--- + arch/m68k/include/asm/processor.h | 14 ++++++++++++++ + arch/m68k/sun3/mmu_emu.c | 4 ++-- + 2 files changed, 16 insertions(+), 2 deletions(-) + +diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h +index 8f2676c3a9882..3c43c09d44894 100644 +--- a/arch/m68k/include/asm/processor.h ++++ b/arch/m68k/include/asm/processor.h +@@ -95,10 +95,24 @@ static inline void set_fc(unsigned long val) + "movec %0,%/dfc\n\t" + : /* no outputs */ : "r" (val) : "memory"); + } ++ ++static inline unsigned long get_fc(void) ++{ ++ unsigned long val; ++ ++ __asm__ ("movec %/dfc,%0" : "=r" (val) : ); ++ ++ return val; ++} + #else + static inline void set_fc(unsigned long val) + { + } ++ ++static inline unsigned long get_fc(void) ++{ ++ return USER_DATA; ++} + #endif /* CONFIG_CPU_HAS_ADDRESS_SPACES */ + + struct thread_struct { +diff --git a/arch/m68k/sun3/mmu_emu.c b/arch/m68k/sun3/mmu_emu.c +index 7b15cc12637bf..b39fc3717d8ea 100644 +--- a/arch/m68k/sun3/mmu_emu.c ++++ b/arch/m68k/sun3/mmu_emu.c +@@ -371,7 +371,7 @@ int mmu_emu_handle_fault (unsigned long vaddr, int read_flag, int kernel_fault) + } + + #ifdef DEBUG_MMU_EMU +- pr_info("%s: vaddr=%lx type=%s crp=%p\n", __func__, vaddr, ++ pr_info("%s: vaddr=%lx type=%s crp=%px\n", __func__, vaddr, + str_read_write(read_flag), crp); + #endif + +@@ -418,7 +418,7 @@ int mmu_emu_handle_fault (unsigned long vaddr, int read_flag, int kernel_fault) + pte_val (*pte) |= SUN3_PAGE_ACCESSED; + + #ifdef DEBUG_MMU_EMU +- pr_info("seg:%ld crp:%p ->", get_fs().seg, crp); ++ pr_info("seg:%ld crp:%px ->", get_fc(), crp); + print_pte_vaddr (vaddr); + pr_cont("\n"); + #endif +-- +2.39.5 + diff --git a/queue-6.14/m68k-sun3-use-str_read_write-helper-in-mmu_emu_handl.patch b/queue-6.14/m68k-sun3-use-str_read_write-helper-in-mmu_emu_handl.patch new file mode 100644 index 0000000000..dfcb38ffd5 --- /dev/null +++ b/queue-6.14/m68k-sun3-use-str_read_write-helper-in-mmu_emu_handl.patch @@ -0,0 +1,45 @@ +From 28f8b4af5e2415be7f060ffc0641458efa27f1a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jan 2025 13:06:05 +0100 +Subject: m68k: sun3: Use str_read_write() helper in mmu_emu_handle_fault() + +From: Thorsten Blum + +[ Upstream commit 751b3d8d886e73ecc24a5426adba228ef7eb39e8 ] + +Remove hard-coded strings by using the str_read_write() helper. + +Signed-off-by: Thorsten Blum +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/20250117120605.126941-2-thorsten.blum@linux.dev +Signed-off-by: Geert Uytterhoeven +Stable-dep-of: 723be3c6ab31 ("m68k: sun3: Fix DEBUG_MMU_EMU build") +Signed-off-by: Sasha Levin +--- + arch/m68k/sun3/mmu_emu.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/m68k/sun3/mmu_emu.c b/arch/m68k/sun3/mmu_emu.c +index 119bd32efcfbc..7b15cc12637bf 100644 +--- a/arch/m68k/sun3/mmu_emu.c ++++ b/arch/m68k/sun3/mmu_emu.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -371,7 +372,7 @@ int mmu_emu_handle_fault (unsigned long vaddr, int read_flag, int kernel_fault) + + #ifdef DEBUG_MMU_EMU + pr_info("%s: vaddr=%lx type=%s crp=%p\n", __func__, vaddr, +- read_flag ? "read" : "write", crp); ++ str_read_write(read_flag), crp); + #endif + + segment = (vaddr >> SUN3_PMEG_SIZE_BITS) & 0x7FF; +-- +2.39.5 + diff --git a/queue-6.14/md-ensure-resync-is-prioritized-over-recovery.patch b/queue-6.14/md-ensure-resync-is-prioritized-over-recovery.patch new file mode 100644 index 0000000000..cd5eb99774 --- /dev/null +++ b/queue-6.14/md-ensure-resync-is-prioritized-over-recovery.patch @@ -0,0 +1,62 @@ +From 3b3d25fa3e7591a5c14807718a92262e11c21aba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 21:15:30 +0800 +Subject: md: ensure resync is prioritized over recovery + +From: Li Nan + +[ Upstream commit 4b10a3bc67c1232f76aa1e04778ca26d6c0ddf7f ] + +If a new disk is added during resync, the resync process is interrupted, +and recovery is triggered, causing the previous resync to be lost. In +reality, disk addition should not terminate resync, fix it. + +Steps to reproduce the issue: + mdadm -CR /dev/md0 -l1 -n3 -x1 /dev/sd[abcd] + mdadm --fail /dev/md0 /dev/sdc + +Fixes: 24dd469d728d ("[PATCH] md: allow a manual resync with md") +Signed-off-by: Li Nan +Reviewed-by: Yu Kuai +Link: https://lore.kernel.org/linux-raid/20250213131530.3698600-1-linan666@huaweicloud.com +Signed-off-by: Yu Kuai +Signed-off-by: Sasha Levin +--- + drivers/md/md.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 30b3dbbce2d2d..827646b3eb594 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -9460,6 +9460,13 @@ static bool md_choose_sync_action(struct mddev *mddev, int *spares) + return true; + } + ++ /* Check if resync is in progress. */ ++ if (mddev->recovery_cp < MaxSector) { ++ set_bit(MD_RECOVERY_SYNC, &mddev->recovery); ++ clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery); ++ return true; ++ } ++ + /* + * Remove any failed drives, then add spares if possible. Spares are + * also removed and re-added, to allow the personality to fail the +@@ -9476,13 +9483,6 @@ static bool md_choose_sync_action(struct mddev *mddev, int *spares) + return true; + } + +- /* Check if recovery is in progress. */ +- if (mddev->recovery_cp < MaxSector) { +- set_bit(MD_RECOVERY_SYNC, &mddev->recovery); +- clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery); +- return true; +- } +- + /* Delay to choose resync/check/repair in md_do_sync(). */ + if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) + return true; +-- +2.39.5 + diff --git a/queue-6.14/md-fix-mddev-uaf-while-iterating-all_mddevs-list.patch b/queue-6.14/md-fix-mddev-uaf-while-iterating-all_mddevs-list.patch new file mode 100644 index 0000000000..958653838a --- /dev/null +++ b/queue-6.14/md-fix-mddev-uaf-while-iterating-all_mddevs-list.patch @@ -0,0 +1,135 @@ +From 7e9bd276b31eb924cd8d1d9005636b90a8970c40 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 20:43:48 +0800 +Subject: md: fix mddev uaf while iterating all_mddevs list + +From: Yu Kuai + +[ Upstream commit 8542870237c3a48ff049b6c5df5f50c8728284fa ] + +While iterating all_mddevs list from md_notify_reboot() and md_exit(), +list_for_each_entry_safe is used, and this can race with deletint the +next mddev, causing UAF: + +t1: +spin_lock +//list_for_each_entry_safe(mddev, n, ...) + mddev_get(mddev1) + // assume mddev2 is the next entry + spin_unlock + t2: + //remove mddev2 + ... + mddev_free + spin_lock + list_del + spin_unlock + kfree(mddev2) + mddev_put(mddev1) + spin_lock + //continue dereference mddev2->all_mddevs + +The old helper for_each_mddev() actually grab the reference of mddev2 +while holding the lock, to prevent from being freed. This problem can be +fixed the same way, however, the code will be complex. + +Hence switch to use list_for_each_entry, in this case mddev_put() can free +the mddev1 and it's not safe as well. Refer to md_seq_show(), also factor +out a helper mddev_put_locked() to fix this problem. + +Cc: Christoph Hellwig +Link: https://lore.kernel.org/linux-raid/20250220124348.845222-1-yukuai1@huaweicloud.com +Fixes: f26514342255 ("md: stop using for_each_mddev in md_notify_reboot") +Fixes: 16648bac862f ("md: stop using for_each_mddev in md_exit") +Reported-and-tested-by: Guillaume Morin +Closes: https://lore.kernel.org/all/Z7Y0SURoA8xwg7vn@bender.morinfr.org/ +Signed-off-by: Yu Kuai +Reviewed-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + drivers/md/md.c | 22 +++++++++++++--------- + 1 file changed, 13 insertions(+), 9 deletions(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 827646b3eb594..f501bc5f68f1a 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -629,6 +629,12 @@ static void __mddev_put(struct mddev *mddev) + queue_work(md_misc_wq, &mddev->del_work); + } + ++static void mddev_put_locked(struct mddev *mddev) ++{ ++ if (atomic_dec_and_test(&mddev->active)) ++ __mddev_put(mddev); ++} ++ + void mddev_put(struct mddev *mddev) + { + if (!atomic_dec_and_lock(&mddev->active, &all_mddevs_lock)) +@@ -8461,9 +8467,7 @@ static int md_seq_show(struct seq_file *seq, void *v) + if (mddev == list_last_entry(&all_mddevs, struct mddev, all_mddevs)) + status_unused(seq); + +- if (atomic_dec_and_test(&mddev->active)) +- __mddev_put(mddev); +- ++ mddev_put_locked(mddev); + return 0; + } + +@@ -9895,11 +9899,11 @@ EXPORT_SYMBOL_GPL(rdev_clear_badblocks); + static int md_notify_reboot(struct notifier_block *this, + unsigned long code, void *x) + { +- struct mddev *mddev, *n; ++ struct mddev *mddev; + int need_delay = 0; + + spin_lock(&all_mddevs_lock); +- list_for_each_entry_safe(mddev, n, &all_mddevs, all_mddevs) { ++ list_for_each_entry(mddev, &all_mddevs, all_mddevs) { + if (!mddev_get(mddev)) + continue; + spin_unlock(&all_mddevs_lock); +@@ -9911,8 +9915,8 @@ static int md_notify_reboot(struct notifier_block *this, + mddev_unlock(mddev); + } + need_delay = 1; +- mddev_put(mddev); + spin_lock(&all_mddevs_lock); ++ mddev_put_locked(mddev); + } + spin_unlock(&all_mddevs_lock); + +@@ -10245,7 +10249,7 @@ void md_autostart_arrays(int part) + + static __exit void md_exit(void) + { +- struct mddev *mddev, *n; ++ struct mddev *mddev; + int delay = 1; + + unregister_blkdev(MD_MAJOR,"md"); +@@ -10266,7 +10270,7 @@ static __exit void md_exit(void) + remove_proc_entry("mdstat", NULL); + + spin_lock(&all_mddevs_lock); +- list_for_each_entry_safe(mddev, n, &all_mddevs, all_mddevs) { ++ list_for_each_entry(mddev, &all_mddevs, all_mddevs) { + if (!mddev_get(mddev)) + continue; + spin_unlock(&all_mddevs_lock); +@@ -10278,8 +10282,8 @@ static __exit void md_exit(void) + * the mddev for destruction by a workqueue, and the + * destroy_workqueue() below will wait for that to complete. + */ +- mddev_put(mddev); + spin_lock(&all_mddevs_lock); ++ mddev_put_locked(mddev); + } + spin_unlock(&all_mddevs_lock); + +-- +2.39.5 + diff --git a/queue-6.14/md-md-bitmap-fix-wrong-bitmap_limit-for-clustermd-wh.patch b/queue-6.14/md-md-bitmap-fix-wrong-bitmap_limit-for-clustermd-wh.patch new file mode 100644 index 0000000000..e101f8612b --- /dev/null +++ b/queue-6.14/md-md-bitmap-fix-wrong-bitmap_limit-for-clustermd-wh.patch @@ -0,0 +1,66 @@ +From fd4c044de51c78315b7dd86a81e927b7eb64a5cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 11:39:18 +0800 +Subject: md/md-bitmap: fix wrong bitmap_limit for clustermd when write sb + +From: Su Yue + +[ Upstream commit 6130825f34d41718c98a9b1504a79a23e379701e ] + +In clustermd, separate write-intent-bitmaps are used for each cluster +node: + +0 4k 8k 12k +------------------------------------------------------------------- +| idle | md super | bm super [0] + bits | +| bm bits[0, contd] | bm super[1] + bits | bm bits[1, contd] | +| bm super[2] + bits | bm bits [2, contd] | bm super[3] + bits | +| bm bits [3, contd] | | | + +So in node 1, pg_index in __write_sb_page() could equal to +bitmap->storage.file_pages. Then bitmap_limit will be calculated to +0. md_super_write() will be called with 0 size. +That means the first 4k sb area of node 1 will never be updated +through filemap_write_page(). +This bug causes hang of mdadm/clustermd_tests/01r1_Grow_resize. + +Here use (pg_index % bitmap->storage.file_pages) to make calculation +of bitmap_limit correct. + +Fixes: ab99a87542f1 ("md/md-bitmap: fix writing non bitmap pages") +Signed-off-by: Su Yue +Reviewed-by: Heming Zhao +Link: https://lore.kernel.org/linux-raid/20250303033918.32136-1-glass.su@suse.com +Signed-off-by: Yu Kuai +Signed-off-by: Sasha Levin +--- + drivers/md/md-bitmap.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c +index 23c09d22fcdbc..9ae6cc8e30cbd 100644 +--- a/drivers/md/md-bitmap.c ++++ b/drivers/md/md-bitmap.c +@@ -426,8 +426,8 @@ static int __write_sb_page(struct md_rdev *rdev, struct bitmap *bitmap, + struct block_device *bdev; + struct mddev *mddev = bitmap->mddev; + struct bitmap_storage *store = &bitmap->storage; +- unsigned int bitmap_limit = (bitmap->storage.file_pages - pg_index) << +- PAGE_SHIFT; ++ unsigned long num_pages = bitmap->storage.file_pages; ++ unsigned int bitmap_limit = (num_pages - pg_index % num_pages) << PAGE_SHIFT; + loff_t sboff, offset = mddev->bitmap_info.offset; + sector_t ps = pg_index * PAGE_SIZE / SECTOR_SIZE; + unsigned int size = PAGE_SIZE; +@@ -436,7 +436,7 @@ static int __write_sb_page(struct md_rdev *rdev, struct bitmap *bitmap, + + bdev = (rdev->meta_bdev) ? rdev->meta_bdev : rdev->bdev; + /* we compare length (page numbers), not page offset. */ +- if ((pg_index - store->sb_index) == store->file_pages - 1) { ++ if ((pg_index - store->sb_index) == num_pages - 1) { + unsigned int last_page_size = store->bytes & (PAGE_SIZE - 1); + + if (last_page_size == 0) +-- +2.39.5 + diff --git a/queue-6.14/md-raid1-fix-memory-leak-in-raid1_run-if-no-active-r.patch b/queue-6.14/md-raid1-fix-memory-leak-in-raid1_run-if-no-active-r.patch new file mode 100644 index 0000000000..ab1787b8d8 --- /dev/null +++ b/queue-6.14/md-raid1-fix-memory-leak-in-raid1_run-if-no-active-r.patch @@ -0,0 +1,60 @@ +From 67dde4fa72498756199c10e15795486fe860bcc8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Feb 2025 10:01:37 +0800 +Subject: md/raid1: fix memory leak in raid1_run() if no active rdev + +From: Zheng Qixing + +[ Upstream commit 5fbcf76e0dfe68578ffa2a8a691cc44cf586ae35 ] + +When `raid1_set_limits()` fails or when the array has no active +`rdev`, the allocated memory for `conf` is not properly freed. + +Add raid1_free() call to properly free the conf in error path. + +Fixes: 799af947ed13 ("md/raid1: don't free conf on raid0_run failure") +Signed-off-by: Zheng Qixing +Link: https://lore.kernel.org/linux-raid/20250215020137.3703757-1-zhengqixing@huaweicloud.com +Singed-off-by: Yu Kuai +Signed-off-by: Sasha Levin +--- + drivers/md/raid1.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 10ea3af40991d..cb108b3e28c4d 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -45,6 +45,7 @@ + + static void allow_barrier(struct r1conf *conf, sector_t sector_nr); + static void lower_barrier(struct r1conf *conf, sector_t sector_nr); ++static void raid1_free(struct mddev *mddev, void *priv); + + #define RAID_1_10_NAME "raid1" + #include "raid1-10.c" +@@ -3256,8 +3257,11 @@ static int raid1_run(struct mddev *mddev) + + if (!mddev_is_dm(mddev)) { + ret = raid1_set_limits(mddev); +- if (ret) ++ if (ret) { ++ if (!mddev->private) ++ raid1_free(mddev, conf); + return ret; ++ } + } + + mddev->degraded = 0; +@@ -3271,6 +3275,8 @@ static int raid1_run(struct mddev *mddev) + */ + if (conf->raid_disks - mddev->degraded < 1) { + md_unregister_thread(mddev, &conf->thread); ++ if (!mddev->private) ++ raid1_free(mddev, conf); + return -EINVAL; + } + +-- +2.39.5 + diff --git a/queue-6.14/md-raid1-raid10-don-t-ignore-io-flags.patch b/queue-6.14/md-raid1-raid10-don-t-ignore-io-flags.patch new file mode 100644 index 0000000000..2377ecd37e --- /dev/null +++ b/queue-6.14/md-raid1-raid10-don-t-ignore-io-flags.patch @@ -0,0 +1,105 @@ +From c6a2ffa0baf01960f769ef65d1318cb38d6fbc23 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 20:16:57 +0800 +Subject: md/raid1,raid10: don't ignore IO flags + +From: Yu Kuai + +[ Upstream commit e879a0d9cb086c8e52ce6c04e5bfa63825a6213c ] + +If blk-wbt is enabled by default, it's found that raid write performance +is quite bad because all IO are throttled by wbt of underlying disks, +due to flag REQ_IDLE is ignored. And turns out this behaviour exist since +blk-wbt is introduced. + +Other than REQ_IDLE, other flags should not be ignored as well, for +example REQ_META can be set for filesystems, clearing it can cause priority +reverse problems; And REQ_NOWAIT should not be cleared as well, because +io will wait instead of failing directly in underlying disks. + +Fix those problems by keep IO flags from master bio. + +Fises: f51d46d0e7cb ("md: add support for REQ_NOWAIT") +Fixes: e34cbd307477 ("blk-wbt: add general throttling mechanism") +Fixes: 5404bc7a87b9 ("[PATCH] Allow file systems to differentiate between data and meta reads") +Link: https://lore.kernel.org/linux-raid/20250227121657.832356-1-yukuai1@huaweicloud.com +Signed-off-by: Yu Kuai +Signed-off-by: Sasha Levin +--- + drivers/md/raid1.c | 5 ----- + drivers/md/raid10.c | 8 -------- + 2 files changed, 13 deletions(-) + +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index cb108b3e28c4d..44dcfebff4f03 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -1316,8 +1316,6 @@ static void raid1_read_request(struct mddev *mddev, struct bio *bio, + struct r1conf *conf = mddev->private; + struct raid1_info *mirror; + struct bio *read_bio; +- const enum req_op op = bio_op(bio); +- const blk_opf_t do_sync = bio->bi_opf & REQ_SYNC; + int max_sectors; + int rdisk, error; + bool r1bio_existed = !!r1_bio; +@@ -1405,7 +1403,6 @@ static void raid1_read_request(struct mddev *mddev, struct bio *bio, + read_bio->bi_iter.bi_sector = r1_bio->sector + + mirror->rdev->data_offset; + read_bio->bi_end_io = raid1_end_read_request; +- read_bio->bi_opf = op | do_sync; + if (test_bit(FailFast, &mirror->rdev->flags) && + test_bit(R1BIO_FailFast, &r1_bio->state)) + read_bio->bi_opf |= MD_FAILFAST; +@@ -1654,8 +1651,6 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, + + mbio->bi_iter.bi_sector = (r1_bio->sector + rdev->data_offset); + mbio->bi_end_io = raid1_end_write_request; +- mbio->bi_opf = bio_op(bio) | +- (bio->bi_opf & (REQ_SYNC | REQ_FUA | REQ_ATOMIC)); + if (test_bit(FailFast, &rdev->flags) && + !test_bit(WriteMostly, &rdev->flags) && + conf->raid_disks - mddev->degraded > 1) +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index 15b9ae5bf84d8..c897b19dc2d53 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -1146,8 +1146,6 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio, + { + struct r10conf *conf = mddev->private; + struct bio *read_bio; +- const enum req_op op = bio_op(bio); +- const blk_opf_t do_sync = bio->bi_opf & REQ_SYNC; + int max_sectors; + struct md_rdev *rdev; + char b[BDEVNAME_SIZE]; +@@ -1228,7 +1226,6 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio, + read_bio->bi_iter.bi_sector = r10_bio->devs[slot].addr + + choose_data_offset(r10_bio, rdev); + read_bio->bi_end_io = raid10_end_read_request; +- read_bio->bi_opf = op | do_sync; + if (test_bit(FailFast, &rdev->flags) && + test_bit(R10BIO_FailFast, &r10_bio->state)) + read_bio->bi_opf |= MD_FAILFAST; +@@ -1247,10 +1244,6 @@ static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio, + struct bio *bio, bool replacement, + int n_copy) + { +- const enum req_op op = bio_op(bio); +- const blk_opf_t do_sync = bio->bi_opf & REQ_SYNC; +- const blk_opf_t do_fua = bio->bi_opf & REQ_FUA; +- const blk_opf_t do_atomic = bio->bi_opf & REQ_ATOMIC; + unsigned long flags; + struct r10conf *conf = mddev->private; + struct md_rdev *rdev; +@@ -1269,7 +1262,6 @@ static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio, + mbio->bi_iter.bi_sector = (r10_bio->devs[n_copy].addr + + choose_data_offset(r10_bio, rdev)); + mbio->bi_end_io = raid10_end_write_request; +- mbio->bi_opf = op | do_sync | do_fua | do_atomic; + if (!replacement && test_bit(FailFast, + &conf->mirrors[devnum].rdev->flags) + && enough(conf, devnum)) +-- +2.39.5 + diff --git a/queue-6.14/md-raid10-wait-barrier-before-returning-discard-requ.patch b/queue-6.14/md-raid10-wait-barrier-before-returning-discard-requ.patch new file mode 100644 index 0000000000..cfba712a67 --- /dev/null +++ b/queue-6.14/md-raid10-wait-barrier-before-returning-discard-requ.patch @@ -0,0 +1,45 @@ +From ea9f0cd98faaeb4335a3c93f74caf36e928cdb0c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 17:49:38 +0800 +Subject: md/raid10: wait barrier before returning discard request with + REQ_NOWAIT + +From: Xiao Ni + +[ Upstream commit 3db4404435397a345431b45f57876a3df133f3b4 ] + +raid10_handle_discard should wait barrier before returning a discard bio +which has REQ_NOWAIT. And there is no need to print warning calltrace +if a discard bio has REQ_NOWAIT flag. Quality engineer usually checks +dmesg and reports error if dmesg has warning/error calltrace. + +Fixes: c9aa889b035f ("md: raid10 add nowait support") +Signed-off-by: Xiao Ni +Acked-by: Coly Li +Link: https://lore.kernel.org/linux-raid/20250306094938.48952-1-xni@redhat.com +Signed-off-by: Yu Kuai +Signed-off-by: Sasha Levin +--- + drivers/md/raid10.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index c897b19dc2d53..918a09f0ddd45 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -1623,11 +1623,10 @@ static int raid10_handle_discard(struct mddev *mddev, struct bio *bio) + if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) + return -EAGAIN; + +- if (WARN_ON_ONCE(bio->bi_opf & REQ_NOWAIT)) { ++ if (!wait_barrier(conf, bio->bi_opf & REQ_NOWAIT)) { + bio_wouldblock_error(bio); + return 0; + } +- wait_barrier(conf, false); + + /* + * Check reshape again to avoid reshape happens after checking +-- +2.39.5 + diff --git a/queue-6.14/mdacon-rework-dependency-list.patch b/queue-6.14/mdacon-rework-dependency-list.patch new file mode 100644 index 0000000000..52c5519526 --- /dev/null +++ b/queue-6.14/mdacon-rework-dependency-list.patch @@ -0,0 +1,47 @@ +From 2d4eec4133b54d956ccc5907acf8f64eb68f9106 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 17:44:23 +0100 +Subject: mdacon: rework dependency list + +From: Arnd Bergmann + +[ Upstream commit 5bbcc7645f4b244ffb5ac6563fbe9d3d42194447 ] + +mdacon has roughly the same dependencies as vgacon but expresses them +as a negative list instead of a positive list, with the only practical +difference being PowerPC/CHRP, which uses vga16fb instead of vgacon. + +The CONFIG_MDA_CONSOLE description advises to only turn it on when vgacon +is also used because MDA/Hercules-only systems should be using vgacon +instead, so just change the list to enforce that directly for simplicity. + +The probing was broken from 2002 to 2008, this improves on the fix +that was added then: If vgacon is a loadable module, then mdacon +cannot be built-in now, and the list of systems that support vgacon +is carried over. + +Fixes: 0b9cf3aa6b1e ("mdacon messing up default vc's - set default to vc13-16 again") +Signed-off-by: Arnd Bergmann +Reviewed-by: Thomas Zimmermann +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + drivers/video/console/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig +index c4a8f74df2493..3e9f2bda67027 100644 +--- a/drivers/video/console/Kconfig ++++ b/drivers/video/console/Kconfig +@@ -24,7 +24,7 @@ config VGA_CONSOLE + Say Y. + + config MDA_CONSOLE +- depends on !M68K && !PARISC && ISA ++ depends on VGA_CONSOLE && ISA + tristate "MDA text console (dual-headed)" + help + Say Y here if you have an old MDA or monochrome Hercules graphics +-- +2.39.5 + diff --git a/queue-6.14/media-platform-allgro-dvt-unregister-v4l2_device-on-.patch b/queue-6.14/media-platform-allgro-dvt-unregister-v4l2_device-on-.patch new file mode 100644 index 0000000000..1932db5a1d --- /dev/null +++ b/queue-6.14/media-platform-allgro-dvt-unregister-v4l2_device-on-.patch @@ -0,0 +1,38 @@ +From f62b1f5dc674fb0e0a9ce9965e124228af317b16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Dec 2024 11:06:21 +0900 +Subject: media: platform: allgro-dvt: unregister v4l2_device on the error path + +From: Joe Hattori + +[ Upstream commit c2b96a6818159fba8a3bcc38262da9e77f9b3ec7 ] + +In allegro_probe(), the v4l2 device is not unregistered in the error +path, which results in a memory leak. Fix it by calling +v4l2_device_unregister() before returning error. + +Fixes: d74d4e2359ec ("media: allegro: move driver out of staging") +Signed-off-by: Joe Hattori +Reviewed-by: Michael Tretter +Signed-off-by: Sebastian Fricke +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/platform/allegro-dvt/allegro-core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/media/platform/allegro-dvt/allegro-core.c b/drivers/media/platform/allegro-dvt/allegro-core.c +index e491399afcc98..eb03df0d86527 100644 +--- a/drivers/media/platform/allegro-dvt/allegro-core.c ++++ b/drivers/media/platform/allegro-dvt/allegro-core.c +@@ -3912,6 +3912,7 @@ static int allegro_probe(struct platform_device *pdev) + if (ret < 0) { + v4l2_err(&dev->v4l2_dev, + "failed to request firmware: %d\n", ret); ++ v4l2_device_unregister(&dev->v4l2_dev); + return ret; + } + +-- +2.39.5 + diff --git a/queue-6.14/media-verisilicon-hevc-initialize-start_bit-field.patch b/queue-6.14/media-verisilicon-hevc-initialize-start_bit-field.patch new file mode 100644 index 0000000000..9240405fad --- /dev/null +++ b/queue-6.14/media-verisilicon-hevc-initialize-start_bit-field.patch @@ -0,0 +1,40 @@ +From 09b1a00f5a7cdd91e8db0350f6a31b18a8284275 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jan 2025 09:10:52 +0100 +Subject: media: verisilicon: HEVC: Initialize start_bit field + +From: Benjamin Gaignard + +[ Upstream commit 7fcb42b3835e90ef18d68555934cf72adaf58402 ] + +The HEVC driver needs to set the start_bit field explicitly to avoid +causing corrupted frames when the VP9 decoder is used in parallel. The +reason for this problem is that the VP9 and the HEVC decoder share this +register. + +Fixes: cb5dd5a0fa51 ("media: hantro: Introduce G2/HEVC decoder") +Signed-off-by: Benjamin Gaignard +Tested-by: Nicolas Dufresne +Reviewed-by: Nicolas Dufresne +Signed-off-by: Sebastian Fricke +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c b/drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c +index 85a44143b3786..0e212198dd65b 100644 +--- a/drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c ++++ b/drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c +@@ -518,6 +518,7 @@ static void set_buffers(struct hantro_ctx *ctx) + hantro_reg_write(vpu, &g2_stream_len, src_len); + hantro_reg_write(vpu, &g2_strm_buffer_len, src_buf_len); + hantro_reg_write(vpu, &g2_strm_start_offset, 0); ++ hantro_reg_write(vpu, &g2_start_bit, 0); + hantro_reg_write(vpu, &g2_write_mvs_e, 1); + + hantro_write_addr(vpu, G2_TILE_SIZES_ADDR, ctx->hevc_dec.tile_sizes.dma); +-- +2.39.5 + diff --git a/queue-6.14/memory-mtk-smi-add-ostd-setting-for-mt8192.patch b/queue-6.14/memory-mtk-smi-add-ostd-setting-for-mt8192.patch new file mode 100644 index 0000000000..258d3107c6 --- /dev/null +++ b/queue-6.14/memory-mtk-smi-add-ostd-setting-for-mt8192.patch @@ -0,0 +1,79 @@ +From ce9a89fa3887becfef24ab0e963c191919bb6344 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Mar 2025 13:45:08 +0800 +Subject: memory: mtk-smi: Add ostd setting for mt8192 + +From: Xueqi Zhang + +[ Upstream commit 90a0fbaac4a588a1116a191521c3c837c25582ee ] + +Add initial ostd setting for mt8192. All the settings come from DE. +These settings help adjust Multimedia HW's bandwidth limits to achieve +a balanced bandwidth requirement. +Without this, the VENC HW work abnormal while stress testing. + +Fixes: 02c02ddce427 ("memory: mtk-smi: Add mt8192 support") +Signed-off-by: Xueqi Zhang +Reviewed-by: Yong Wu +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20250307054515.23455-1-xueqi.zhang@mediatek.com +Signed-off-by: Krzysztof Kozlowski +Signed-off-by: Sasha Levin +--- + drivers/memory/mtk-smi.c | 33 +++++++++++++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c +index 5710348f72f6f..a8f5467d6b31e 100644 +--- a/drivers/memory/mtk-smi.c ++++ b/drivers/memory/mtk-smi.c +@@ -332,6 +332,38 @@ static const u8 mtk_smi_larb_mt8188_ostd[][SMI_LARB_PORT_NR_MAX] = { + [25] = {0x01}, + }; + ++static const u8 mtk_smi_larb_mt8192_ostd[][SMI_LARB_PORT_NR_MAX] = { ++ [0] = {0x2, 0x2, 0x28, 0xa, 0xc, 0x28,}, ++ [1] = {0x2, 0x2, 0x18, 0x18, 0x18, 0xa, 0xc, 0x28,}, ++ [2] = {0x5, 0x5, 0x5, 0x5, 0x1,}, ++ [3] = {}, ++ [4] = {0x28, 0x19, 0xb, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x1,}, ++ [5] = {0x1, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x16,}, ++ [6] = {}, ++ [7] = {0x1, 0x3, 0x2, 0x1, 0x1, 0x5, 0x2, 0x12, 0x13, 0x4, 0x4, 0x1, ++ 0x4, 0x2, 0x1,}, ++ [8] = {}, ++ [9] = {0xa, 0x7, 0xf, 0x8, 0x1, 0x8, 0x9, 0x3, 0x3, 0x6, 0x7, 0x4, ++ 0xa, 0x3, 0x4, 0xe, 0x1, 0x7, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, ++ 0x1, 0x1, 0x1, 0x1, 0x1,}, ++ [10] = {}, ++ [11] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, ++ 0x1, 0x1, 0x1, 0xe, 0x1, 0x7, 0x8, 0x7, 0x7, 0x1, 0x6, 0x2, ++ 0xf, 0x8, 0x1, 0x1, 0x1,}, ++ [12] = {}, ++ [13] = {0x2, 0xc, 0xc, 0xe, 0x6, 0x6, 0x6, 0x6, 0x6, 0x12, 0x6, 0x28, ++ 0x2, 0xc, 0xc, 0x28, 0x12, 0x6,}, ++ [14] = {}, ++ [15] = {0x28, 0x14, 0x2, 0xc, 0x18, 0x4, 0x28, 0x14, 0x4, 0x4, 0x4, 0x2, ++ 0x4, 0x2, 0x8, 0x4, 0x4,}, ++ [16] = {0x28, 0x14, 0x2, 0xc, 0x18, 0x4, 0x28, 0x14, 0x4, 0x4, 0x4, 0x2, ++ 0x4, 0x2, 0x8, 0x4, 0x4,}, ++ [17] = {0x28, 0x14, 0x2, 0xc, 0x18, 0x4, 0x28, 0x14, 0x4, 0x4, 0x4, 0x2, ++ 0x4, 0x2, 0x8, 0x4, 0x4,}, ++ [18] = {0x2, 0x2, 0x4, 0x2,}, ++ [19] = {0x9, 0x9, 0x5, 0x5, 0x1, 0x1,}, ++}; ++ + static const u8 mtk_smi_larb_mt8195_ostd[][SMI_LARB_PORT_NR_MAX] = { + [0] = {0x0a, 0xc, 0x22, 0x22, 0x01, 0x0a,}, /* larb0 */ + [1] = {0x0a, 0xc, 0x22, 0x22, 0x01, 0x0a,}, /* larb1 */ +@@ -427,6 +459,7 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8188 = { + + static const struct mtk_smi_larb_gen mtk_smi_larb_mt8192 = { + .config_port = mtk_smi_larb_config_port_gen2_general, ++ .ostd = mtk_smi_larb_mt8192_ostd, + }; + + static const struct mtk_smi_larb_gen mtk_smi_larb_mt8195 = { +-- +2.39.5 + diff --git a/queue-6.14/mfd-sm501-switch-to-bit-to-mitigate-integer-overflow.patch b/queue-6.14/mfd-sm501-switch-to-bit-to-mitigate-integer-overflow.patch new file mode 100644 index 0000000000..d4461cbeb3 --- /dev/null +++ b/queue-6.14/mfd-sm501-switch-to-bit-to-mitigate-integer-overflow.patch @@ -0,0 +1,63 @@ +From 2842a1c8cc923f3db6ce327c65a4bc3087a952c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jan 2025 09:12:06 -0800 +Subject: mfd: sm501: Switch to BIT() to mitigate integer overflows + +From: Nikita Zhandarovich + +[ Upstream commit 2d8cb9ffe18c2f1e5bd07a19cbce85b26c1d0cf0 ] + +If offset end up being high enough, right hand expression in functions +like sm501_gpio_set() shifted left for that number of bits, may +not fit in int type. + +Just in case, fix that by using BIT() both as an option safe from +overflow issues and to make this step look similar to other gpio +drivers. + +Found by Linux Verification Center (linuxtesting.org) with static +analysis tool SVACE. + +Fixes: f61be273d369 ("sm501: add gpiolib support") +Signed-off-by: Nikita Zhandarovich +Link: https://lore.kernel.org/r/20250115171206.20308-1-n.zhandarovich@fintech.ru +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/mfd/sm501.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c +index 0469e85d72cff..7ee293b09f628 100644 +--- a/drivers/mfd/sm501.c ++++ b/drivers/mfd/sm501.c +@@ -920,7 +920,7 @@ static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value) + { + struct sm501_gpio_chip *smchip = gpiochip_get_data(chip); + struct sm501_gpio *smgpio = smchip->ourgpio; +- unsigned long bit = 1 << offset; ++ unsigned long bit = BIT(offset); + void __iomem *regs = smchip->regbase; + unsigned long save; + unsigned long val; +@@ -946,7 +946,7 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset) + struct sm501_gpio_chip *smchip = gpiochip_get_data(chip); + struct sm501_gpio *smgpio = smchip->ourgpio; + void __iomem *regs = smchip->regbase; +- unsigned long bit = 1 << offset; ++ unsigned long bit = BIT(offset); + unsigned long save; + unsigned long ddr; + +@@ -971,7 +971,7 @@ static int sm501_gpio_output(struct gpio_chip *chip, + { + struct sm501_gpio_chip *smchip = gpiochip_get_data(chip); + struct sm501_gpio *smgpio = smchip->ourgpio; +- unsigned long bit = 1 << offset; ++ unsigned long bit = BIT(offset); + void __iomem *regs = smchip->regbase; + unsigned long save; + unsigned long val; +-- +2.39.5 + diff --git a/queue-6.14/misc-pci_endpoint_test-fix-pci_endpoint_test_bars_re.patch b/queue-6.14/misc-pci_endpoint_test-fix-pci_endpoint_test_bars_re.patch new file mode 100644 index 0000000000..eacb1c9ba6 --- /dev/null +++ b/queue-6.14/misc-pci_endpoint_test-fix-pci_endpoint_test_bars_re.patch @@ -0,0 +1,53 @@ +From 3d5a79b5be531754359323f8ce66ee0db784f457 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 12:06:41 +0100 +Subject: misc: pci_endpoint_test: Fix pci_endpoint_test_bars_read_bar() error + handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Niklas Cassel + +[ Upstream commit 2a93192d2058507b2e39b590fc1efa0e03344136 ] + +Commit f26d37ee9bda ("misc: pci_endpoint_test: Fix IOCTL return value") +changed the return value of pci_endpoint_test_bars_read_bar() from false +to -EINVAL on error, however, it failed to update the error handling. + +Fixes: f26d37ee9bda ("misc: pci_endpoint_test: Fix IOCTL return value") +Signed-off-by: Niklas Cassel +Reviewed-by: Manivannan Sadhasivam +Link: https://lore.kernel.org/r/20250204110640.570823-2-cassel@kernel.org +Signed-off-by: Manivannan Sadhasivam +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/misc/pci_endpoint_test.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c +index d5ac71a493865..7584d18768598 100644 +--- a/drivers/misc/pci_endpoint_test.c ++++ b/drivers/misc/pci_endpoint_test.c +@@ -382,7 +382,7 @@ static int pci_endpoint_test_bars_read_bar(struct pci_endpoint_test *test, + static int pci_endpoint_test_bars(struct pci_endpoint_test *test) + { + enum pci_barno bar; +- bool ret; ++ int ret; + + /* Write all BARs in order (without reading). */ + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) +@@ -398,7 +398,7 @@ static int pci_endpoint_test_bars(struct pci_endpoint_test *test) + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { + if (test->bar[bar]) { + ret = pci_endpoint_test_bars_read_bar(test, bar); +- if (!ret) ++ if (ret) + return ret; + } + } +-- +2.39.5 + diff --git a/queue-6.14/misc-pci_endpoint_test-handle-bar-sizes-larger-than-.patch b/queue-6.14/misc-pci_endpoint_test-handle-bar-sizes-larger-than-.patch new file mode 100644 index 0000000000..434a8c9b9b --- /dev/null +++ b/queue-6.14/misc-pci_endpoint_test-handle-bar-sizes-larger-than-.patch @@ -0,0 +1,93 @@ +From 738c21591c83b668872cc42d117def5da2ba692b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 10:33:01 +0100 +Subject: misc: pci_endpoint_test: Handle BAR sizes larger than INT_MAX +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Niklas Cassel + +[ Upstream commit 7962c82a6e648d07bf0067796e4a0e69ba1fc702 ] + +Running 'pcitest -b 0' fails with "TEST FAILED" when the BAR0 size +is e.g. 8 GB. + +The return value of the pci_resource_len() macro can be larger than that +of a signed integer type. Thus, when using 'pcitest' with an 8 GB BAR, +the bar_size of the integer type will overflow. + +Change bar_size from integer to resource_size_t to prevent integer +overflow for large BAR sizes with 32-bit compilers. + +In order to handle 64-bit resource_type_t on 32-bit platforms, we would +have needed to use a function like div_u64() or similar. Instead, change +the code to use addition instead of division. This avoids the need for +div_u64() or similar, while also simplifying the code. + +Fixes: cda370ec6d1f ("misc: pci_endpoint_test: Avoid using hard-coded BAR sizes") +Co-developed-by: Hans Zhang <18255117159@163.com> +Signed-off-by: Hans Zhang <18255117159@163.com> +Signed-off-by: Niklas Cassel +Reviewed-by: Manivannan Sadhasivam +Tested-by: Jon Hunter +Reviewed-by: Frank Li +Link: https://lore.kernel.org/r/20250124093300.3629624-2-cassel@kernel.org +[mani: added fixes tag] +Signed-off-by: Manivannan Sadhasivam +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/misc/pci_endpoint_test.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c +index 7584d18768598..9dac7cbe8748c 100644 +--- a/drivers/misc/pci_endpoint_test.c ++++ b/drivers/misc/pci_endpoint_test.c +@@ -272,9 +272,9 @@ static const u32 bar_test_pattern[] = { + }; + + static int pci_endpoint_test_bar_memcmp(struct pci_endpoint_test *test, +- enum pci_barno barno, int offset, +- void *write_buf, void *read_buf, +- int size) ++ enum pci_barno barno, ++ resource_size_t offset, void *write_buf, ++ void *read_buf, int size) + { + memset(write_buf, bar_test_pattern[barno], size); + memcpy_toio(test->bar[barno] + offset, write_buf, size); +@@ -287,10 +287,11 @@ static int pci_endpoint_test_bar_memcmp(struct pci_endpoint_test *test, + static int pci_endpoint_test_bar(struct pci_endpoint_test *test, + enum pci_barno barno) + { +- int j, bar_size, buf_size, iters; ++ resource_size_t bar_size, offset = 0; + void *write_buf __free(kfree) = NULL; + void *read_buf __free(kfree) = NULL; + struct pci_dev *pdev = test->pdev; ++ int buf_size; + + if (!test->bar[barno]) + return -ENOMEM; +@@ -314,11 +315,12 @@ static int pci_endpoint_test_bar(struct pci_endpoint_test *test, + if (!read_buf) + return -ENOMEM; + +- iters = bar_size / buf_size; +- for (j = 0; j < iters; j++) +- if (pci_endpoint_test_bar_memcmp(test, barno, buf_size * j, +- write_buf, read_buf, buf_size)) ++ while (offset < bar_size) { ++ if (pci_endpoint_test_bar_memcmp(test, barno, offset, write_buf, ++ read_buf, buf_size)) + return -EIO; ++ offset += buf_size; ++ } + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/mlxsw-spectrum_acl_bloom_filter-workaround-for-some-.patch b/queue-6.14/mlxsw-spectrum_acl_bloom_filter-workaround-for-some-.patch new file mode 100644 index 0000000000..ac897aa570 --- /dev/null +++ b/queue-6.14/mlxsw-spectrum_acl_bloom_filter-workaround-for-some-.patch @@ -0,0 +1,115 @@ +From e7802eeb5e1ecee9ed36317b32751d778c9d45ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 18:36:54 +0800 +Subject: mlxsw: spectrum_acl_bloom_filter: Workaround for some LLVM versions + +From: WangYuli + +[ Upstream commit 4af9939a4977e05ccaaa645848f6208e82e06c61 ] + +This is a workaround to mitigate a compiler anomaly. + +During LLVM toolchain compilation of this driver on s390x architecture, an +unreasonable __write_overflow_field warning occurs. + +Contextually, chunk_index is restricted to 0, 1 or 2. By expanding these +possibilities, the compile warning is suppressed. + +Fix follow error with clang-19 when -Werror: + In file included from drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c:5: + In file included from ./include/linux/gfp.h:7: + In file included from ./include/linux/mmzone.h:8: + In file included from ./include/linux/spinlock.h:63: + In file included from ./include/linux/lockdep.h:14: + In file included from ./include/linux/smp.h:13: + In file included from ./include/linux/cpumask.h:12: + In file included from ./include/linux/bitmap.h:13: + In file included from ./include/linux/string.h:392: + ./include/linux/fortify-string.h:571:4: error: call to '__write_overflow_field' declared with 'warning' attribute: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Werror,-Wattribute-warning] + 571 | __write_overflow_field(p_size_field, size); + | ^ + 1 error generated. + +According to the testing, we can be fairly certain that this is a clang +compiler bug, impacting only clang-19 and below. Clang versions 20 and +21 do not exhibit this behavior. + +Link: https://lore.kernel.org/all/484364B641C901CD+20250311141025.1624528-1-wangyuli@uniontech.com/ +Fixes: 7585cacdb978 ("mlxsw: spectrum_acl: Add Bloom filter handling") +Co-developed-by: Zijian Chen +Signed-off-by: Zijian Chen +Co-developed-by: Wentao Guan +Signed-off-by: Wentao Guan +Suggested-by: Paolo Abeni +Co-developed-by: Ido Schimmel +Signed-off-by: Ido Schimmel +Tested-by: Ido Schimmel +Tested-by: WangYuli +Signed-off-by: WangYuli +Link: https://patch.msgid.link/A1858F1D36E653E0+20250318103654.708077-1-wangyuli@uniontech.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../mlxsw/spectrum_acl_bloom_filter.c | 27 +++++++++++++++---- + 1 file changed, 22 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c +index a54eedb69a3f5..067f0055a55af 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c +@@ -212,7 +212,22 @@ static const u8 mlxsw_sp4_acl_bf_crc6_tab[256] = { + * This array defines key offsets for easy access when copying key blocks from + * entry key to Bloom filter chunk. + */ +-static const u8 chunk_key_offsets[MLXSW_BLOOM_KEY_CHUNKS] = {2, 20, 38}; ++static char * ++mlxsw_sp_acl_bf_enc_key_get(struct mlxsw_sp_acl_atcam_entry *aentry, ++ u8 chunk_index) ++{ ++ switch (chunk_index) { ++ case 0: ++ return &aentry->ht_key.enc_key[2]; ++ case 1: ++ return &aentry->ht_key.enc_key[20]; ++ case 2: ++ return &aentry->ht_key.enc_key[38]; ++ default: ++ WARN_ON_ONCE(1); ++ return &aentry->ht_key.enc_key[0]; ++ } ++} + + static u16 mlxsw_sp2_acl_bf_crc16_byte(u16 crc, u8 c) + { +@@ -235,9 +250,10 @@ __mlxsw_sp_acl_bf_key_encode(struct mlxsw_sp_acl_atcam_region *aregion, + u8 key_offset, u8 chunk_key_len, u8 chunk_len) + { + struct mlxsw_afk_key_info *key_info = aregion->region->key_info; +- u8 chunk_index, chunk_count, block_count; ++ u8 chunk_index, chunk_count; + char *chunk = output; + __be16 erp_region_id; ++ u32 block_count; + + block_count = mlxsw_afk_key_info_blocks_count_get(key_info); + chunk_count = 1 + ((block_count - 1) >> 2); +@@ -245,12 +261,13 @@ __mlxsw_sp_acl_bf_key_encode(struct mlxsw_sp_acl_atcam_region *aregion, + (aregion->region->id << 4)); + for (chunk_index = max_chunks - chunk_count; chunk_index < max_chunks; + chunk_index++) { ++ char *enc_key; ++ + memset(chunk, 0, pad_bytes); + memcpy(chunk + pad_bytes, &erp_region_id, + sizeof(erp_region_id)); +- memcpy(chunk + key_offset, +- &aentry->ht_key.enc_key[chunk_key_offsets[chunk_index]], +- chunk_key_len); ++ enc_key = mlxsw_sp_acl_bf_enc_key_get(aentry, chunk_index); ++ memcpy(chunk + key_offset, enc_key, chunk_key_len); + chunk += chunk_len; + } + *len = chunk_count * chunk_len; +-- +2.39.5 + diff --git a/queue-6.14/net-airoha-fix-ets-priomap-validation.patch b/queue-6.14/net-airoha-fix-ets-priomap-validation.patch new file mode 100644 index 0000000000..3403f9ed0e --- /dev/null +++ b/queue-6.14/net-airoha-fix-ets-priomap-validation.patch @@ -0,0 +1,68 @@ +From 446558b1738138367c2a788227b95773c8083e49 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Mar 2025 18:17:31 +0200 +Subject: net: airoha: Fix ETS priomap validation + +From: Lorenzo Bianconi + +[ Upstream commit 367579274f60cb23c570ae5348966ab51e1509a4 ] + +ETS Qdisc schedules SP bands in a priority order assigning band-0 the +highest priority (band-0 > band-1 > .. > band-n) while EN7581 arranges +SP bands in a priority order assigning band-7 the highest priority +(band-7 > band-6, .. > band-n). +Fix priomap check in airoha_qdma_set_tx_ets_sched routine in order to +align ETS Qdisc and airoha_eth driver SP priority ordering. + +Fixes: b56e4d660a96 ("net: airoha: Enforce ETS Qdisc priomap") +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Reviewed-by: Davide Caratti +Link: https://patch.msgid.link/20250331-airoha-ets-validate-priomap-v1-1-60a524488672@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mediatek/airoha_eth.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/airoha_eth.c b/drivers/net/ethernet/mediatek/airoha_eth.c +index 71975c490822b..0c244ea5244cc 100644 +--- a/drivers/net/ethernet/mediatek/airoha_eth.c ++++ b/drivers/net/ethernet/mediatek/airoha_eth.c +@@ -2793,7 +2793,7 @@ static int airoha_qdma_set_tx_ets_sched(struct airoha_gdm_port *port, + struct tc_ets_qopt_offload_replace_params *p = &opt->replace_params; + enum tx_sched_mode mode = TC_SCH_SP; + u16 w[AIROHA_NUM_QOS_QUEUES] = {}; +- int i, nstrict = 0, nwrr, qidx; ++ int i, nstrict = 0; + + if (p->bands > AIROHA_NUM_QOS_QUEUES) + return -EINVAL; +@@ -2811,17 +2811,17 @@ static int airoha_qdma_set_tx_ets_sched(struct airoha_gdm_port *port, + * lowest priorities with respect to SP ones. + * e.g: WRR0, WRR1, .., WRRm, SP0, SP1, .., SPn + */ +- nwrr = p->bands - nstrict; +- qidx = nstrict && nwrr ? nstrict : 0; +- for (i = 1; i <= p->bands; i++) { +- if (p->priomap[i % AIROHA_NUM_QOS_QUEUES] != qidx) ++ for (i = 0; i < nstrict; i++) { ++ if (p->priomap[p->bands - i - 1] != i) + return -EINVAL; +- +- qidx = i == nwrr ? 0 : qidx + 1; + } + +- for (i = 0; i < nwrr; i++) ++ for (i = 0; i < p->bands - nstrict; i++) { ++ if (p->priomap[i] != nstrict + i) ++ return -EINVAL; ++ + w[i] = p->weights[nstrict + i]; ++ } + + if (!nstrict) + mode = TC_SCH_WRR8; +-- +2.39.5 + diff --git a/queue-6.14/net-airoha-fix-lan4-support-in-airoha_qdma_get_gdm_p.patch b/queue-6.14/net-airoha-fix-lan4-support-in-airoha_qdma_get_gdm_p.patch new file mode 100644 index 0000000000..9f815fdab8 --- /dev/null +++ b/queue-6.14/net-airoha-fix-lan4-support-in-airoha_qdma_get_gdm_p.patch @@ -0,0 +1,38 @@ +From 89136f833925ba92ee114393e8226c8e9616ff8e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 15:38:05 +0100 +Subject: net: airoha: Fix lan4 support in airoha_qdma_get_gdm_port() + +From: Lorenzo Bianconi + +[ Upstream commit 35ea4f06fd33fc32f556a0c26d1d8340497fa7f8 ] + +EN7581 SoC supports lan{1,4} ports on MT7530 DSA switch. Fix lan4 +reported value in airoha_qdma_get_gdm_port routine. + +Fixes: 23020f0493270 ("net: airoha: Introduce ethernet support for EN7581 SoC") +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250304-airoha-eth-fix-lan4-v1-1-832417da4bb5@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mediatek/airoha_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mediatek/airoha_eth.c b/drivers/net/ethernet/mediatek/airoha_eth.c +index 09f448f291240..c1c2ab82a08d8 100644 +--- a/drivers/net/ethernet/mediatek/airoha_eth.c ++++ b/drivers/net/ethernet/mediatek/airoha_eth.c +@@ -1547,7 +1547,7 @@ static int airoha_qdma_get_gdm_port(struct airoha_eth *eth, + + sport = FIELD_GET(QDMA_ETH_RXMSG_SPORT_MASK, msg1); + switch (sport) { +- case 0x10 ... 0x13: ++ case 0x10 ... 0x14: + port = 0; + break; + case 0x2 ... 0x4: +-- +2.39.5 + diff --git a/queue-6.14/net-airoha-fix-qid-report-in-airoha_tc_get_htb_get_l.patch b/queue-6.14/net-airoha-fix-qid-report-in-airoha_tc_get_htb_get_l.patch new file mode 100644 index 0000000000..655b00eb91 --- /dev/null +++ b/queue-6.14/net-airoha-fix-qid-report-in-airoha_tc_get_htb_get_l.patch @@ -0,0 +1,86 @@ +From 9f7b715607deb46570225567057fb12fefb6dc9e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Mar 2025 08:52:53 +0200 +Subject: net: airoha: Fix qid report in airoha_tc_get_htb_get_leaf_queue() + +From: Lorenzo Bianconi + +[ Upstream commit 57b290d97c6150774bf929117ca737a26d8fc33d ] + +Fix the following kernel warning deleting HTB offloaded leafs and/or root +HTB qdisc in airoha_eth driver properly reporting qid in +airoha_tc_get_htb_get_leaf_queue routine. + +$tc qdisc replace dev eth1 root handle 10: htb offload +$tc class add dev eth1 arent 10: classid 10:4 htb rate 100mbit ceil 100mbit +$tc qdisc replace dev eth1 parent 10:4 handle 4: ets bands 8 \ + quanta 1514 3028 4542 6056 7570 9084 10598 12112 +$tc qdisc del dev eth1 root + +[ 55.827864] ------------[ cut here ]------------ +[ 55.832493] WARNING: CPU: 3 PID: 2678 at 0xffffffc0798695a4 +[ 55.956510] CPU: 3 PID: 2678 Comm: tc Tainted: G O 6.6.71 #0 +[ 55.963557] Hardware name: Airoha AN7581 Evaluation Board (DT) +[ 55.969383] pstate: 20400005 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) +[ 55.976344] pc : 0xffffffc0798695a4 +[ 55.979851] lr : 0xffffffc079869a20 +[ 55.983358] sp : ffffffc0850536a0 +[ 55.986665] x29: ffffffc0850536a0 x28: 0000000000000024 x27: 0000000000000001 +[ 55.993800] x26: 0000000000000000 x25: ffffff8008b19000 x24: ffffff800222e800 +[ 56.000935] x23: 0000000000000001 x22: 0000000000000000 x21: ffffff8008b19000 +[ 56.008071] x20: ffffff8002225800 x19: ffffff800379d000 x18: 0000000000000000 +[ 56.015206] x17: ffffffbf9ea59000 x16: ffffffc080018000 x15: 0000000000000000 +[ 56.022342] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000001 +[ 56.029478] x11: ffffffc081471008 x10: ffffffc081575a98 x9 : 0000000000000000 +[ 56.036614] x8 : ffffffc08167fd40 x7 : ffffffc08069e104 x6 : ffffff8007f86000 +[ 56.043748] x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000001 +[ 56.050884] x2 : 0000000000000000 x1 : 0000000000000250 x0 : ffffff800222c000 +[ 56.058020] Call trace: +[ 56.060459] 0xffffffc0798695a4 +[ 56.063618] 0xffffffc079869a20 +[ 56.066777] __qdisc_destroy+0x40/0xa0 +[ 56.070528] qdisc_put+0x54/0x6c +[ 56.073748] qdisc_graft+0x41c/0x648 +[ 56.077324] tc_get_qdisc+0x168/0x2f8 +[ 56.080978] rtnetlink_rcv_msg+0x230/0x330 +[ 56.085076] netlink_rcv_skb+0x5c/0x128 +[ 56.088913] rtnetlink_rcv+0x14/0x1c +[ 56.092490] netlink_unicast+0x1e0/0x2c8 +[ 56.096413] netlink_sendmsg+0x198/0x3c8 +[ 56.100337] ____sys_sendmsg+0x1c4/0x274 +[ 56.104261] ___sys_sendmsg+0x7c/0xc0 +[ 56.107924] __sys_sendmsg+0x44/0x98 +[ 56.111492] __arm64_sys_sendmsg+0x20/0x28 +[ 56.115580] invoke_syscall.constprop.0+0x58/0xfc +[ 56.120285] do_el0_svc+0x3c/0xbc +[ 56.123592] el0_svc+0x18/0x4c +[ 56.126647] el0t_64_sync_handler+0x118/0x124 +[ 56.131005] el0t_64_sync+0x150/0x154 +[ 56.134660] ---[ end trace 0000000000000000 ]--- + +Fixes: ef1ca9271313b ("net: airoha: Add sched HTB offload support") +Signed-off-by: Lorenzo Bianconi +Acked-by: Paolo Abeni +Link: https://patch.msgid.link/20250331-airoha-htb-qdisc-offload-del-fix-v1-1-4ea429c2c968@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mediatek/airoha_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mediatek/airoha_eth.c b/drivers/net/ethernet/mediatek/airoha_eth.c +index c1c2ab82a08d8..71975c490822b 100644 +--- a/drivers/net/ethernet/mediatek/airoha_eth.c ++++ b/drivers/net/ethernet/mediatek/airoha_eth.c +@@ -3082,7 +3082,7 @@ static int airoha_tc_get_htb_get_leaf_queue(struct airoha_gdm_port *port, + return -EINVAL; + } + +- opt->qid = channel; ++ opt->qid = AIROHA_NUM_TX_RING + channel; + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/net-decrease-cached-dst-counters-in-dst_release.patch b/queue-6.14/net-decrease-cached-dst-counters-in-dst_release.patch new file mode 100644 index 0000000000..447538c238 --- /dev/null +++ b/queue-6.14/net-decrease-cached-dst-counters-in-dst_release.patch @@ -0,0 +1,61 @@ +From b64ad2d47b3f0cdb15f682bc76f600148d3cdbce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Mar 2025 18:36:32 +0100 +Subject: net: decrease cached dst counters in dst_release + +From: Antoine Tenart + +[ Upstream commit 3a0a3ff6593d670af2451ec363ccb7b18aec0c0a ] + +Upstream fix ac888d58869b ("net: do not delay dst_entries_add() in +dst_release()") moved decrementing the dst count from dst_destroy to +dst_release to avoid accessing already freed data in case of netns +dismantle. However in case CONFIG_DST_CACHE is enabled and OvS+tunnels +are used, this fix is incomplete as the same issue will be seen for +cached dsts: + + Unable to handle kernel paging request at virtual address ffff5aabf6b5c000 + Call trace: + percpu_counter_add_batch+0x3c/0x160 (P) + dst_release+0xec/0x108 + dst_cache_destroy+0x68/0xd8 + dst_destroy+0x13c/0x168 + dst_destroy_rcu+0x1c/0xb0 + rcu_do_batch+0x18c/0x7d0 + rcu_core+0x174/0x378 + rcu_core_si+0x18/0x30 + +Fix this by invalidating the cache, and thus decrementing cached dst +counters, in dst_release too. + +Fixes: d71785ffc7e7 ("net: add dst_cache to ovs vxlan lwtunnel") +Signed-off-by: Antoine Tenart +Link: https://patch.msgid.link/20250326173634.31096-1-atenart@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/core/dst.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/net/core/dst.c b/net/core/dst.c +index 9552a90d4772d..6d76b799ce645 100644 +--- a/net/core/dst.c ++++ b/net/core/dst.c +@@ -165,6 +165,14 @@ static void dst_count_dec(struct dst_entry *dst) + void dst_release(struct dst_entry *dst) + { + if (dst && rcuref_put(&dst->__rcuref)) { ++#ifdef CONFIG_DST_CACHE ++ if (dst->flags & DST_METADATA) { ++ struct metadata_dst *md_dst = (struct metadata_dst *)dst; ++ ++ if (md_dst->type == METADATA_IP_TUNNEL) ++ dst_cache_reset_now(&md_dst->u.tun_info.dst_cache); ++ } ++#endif + dst_count_dec(dst); + call_rcu_hurry(&dst->rcu_head, dst_destroy_rcu); + } +-- +2.39.5 + diff --git a/queue-6.14/net-dsa-microchip-fix-dcb-apptrust-configuration-on-.patch b/queue-6.14/net-dsa-microchip-fix-dcb-apptrust-configuration-on-.patch new file mode 100644 index 0000000000..e86e8bb931 --- /dev/null +++ b/queue-6.14/net-dsa-microchip-fix-dcb-apptrust-configuration-on-.patch @@ -0,0 +1,350 @@ +From 53a7953258486502a86652ae942e7323176ebef1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 15:10:44 +0100 +Subject: net: dsa: microchip: fix DCB apptrust configuration on KSZ88x3 + +From: Oleksij Rempel + +[ Upstream commit 1ae1d705a1120e8e0ca41698c5a0fff6f5290bc1 ] + +Remove KSZ88x3-specific priority and apptrust configuration logic that was +based on incorrect register access assumptions. Also fix the register +offset for KSZ8_REG_PORT_1_CTRL_0 to align with get_port_addr() logic. + +The KSZ88x3 switch family uses a different register layout compared to +KSZ9477-compatible variants. Specifically, port control registers need +offset adjustment through get_port_addr(), and do not match the datasheet +values directly. + +Commit a1ea57710c9d ("net: dsa: microchip: dcb: add special handling for +KSZ88X3 family") introduced quirks based on datasheet offsets, which do +not work with the driver's internal addressing model. As a result, these +quirks addressed the wrong ports and caused unstable behavior. + +This patch removes all KSZ88x3-specific DCB quirks and corrects the port +control register offset, effectively restoring working and predictable +apptrust configuration. + +Fixes: a1ea57710c9d ("net: dsa: microchip: dcb: add special handling for KSZ88X3 family") +Signed-off-by: Oleksij Rempel +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250321141044.2128973-1-o.rempel@pengutronix.de +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/microchip/ksz8.c | 11 +- + drivers/net/dsa/microchip/ksz_dcb.c | 231 +--------------------------- + 2 files changed, 9 insertions(+), 233 deletions(-) + +diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c +index da7110d675583..be433b4e2b1ca 100644 +--- a/drivers/net/dsa/microchip/ksz8.c ++++ b/drivers/net/dsa/microchip/ksz8.c +@@ -1625,7 +1625,6 @@ void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port) + const u16 *regs = dev->info->regs; + struct dsa_switch *ds = dev->ds; + const u32 *masks; +- int queues; + u8 member; + + masks = dev->info->masks; +@@ -1633,15 +1632,7 @@ void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port) + /* enable broadcast storm limit */ + ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true); + +- /* For KSZ88x3 enable only one queue by default, otherwise we won't +- * be able to get rid of PCP prios on Port 2. +- */ +- if (ksz_is_ksz88x3(dev)) +- queues = 1; +- else +- queues = dev->info->num_tx_queues; +- +- ksz8_port_queue_split(dev, port, queues); ++ ksz8_port_queue_split(dev, port, dev->info->num_tx_queues); + + /* replace priority */ + ksz_port_cfg(dev, port, P_802_1P_CTRL, +diff --git a/drivers/net/dsa/microchip/ksz_dcb.c b/drivers/net/dsa/microchip/ksz_dcb.c +index 30b4a6186e38f..c3b501997ac94 100644 +--- a/drivers/net/dsa/microchip/ksz_dcb.c ++++ b/drivers/net/dsa/microchip/ksz_dcb.c +@@ -10,7 +10,12 @@ + #include "ksz_dcb.h" + #include "ksz8.h" + +-#define KSZ8_REG_PORT_1_CTRL_0 0x10 ++/* Port X Control 0 register. ++ * The datasheet specifies: Port 1 - 0x10, Port 2 - 0x20, Port 3 - 0x30. ++ * However, the driver uses get_port_addr(), which maps Port 1 to offset 0. ++ * Therefore, we define the base offset as 0x00 here to align with that logic. ++ */ ++#define KSZ8_REG_PORT_1_CTRL_0 0x00 + #define KSZ8_PORT_DIFFSERV_ENABLE BIT(6) + #define KSZ8_PORT_802_1P_ENABLE BIT(5) + #define KSZ8_PORT_BASED_PRIO_M GENMASK(4, 3) +@@ -181,49 +186,6 @@ int ksz_port_get_default_prio(struct dsa_switch *ds, int port) + return (data & mask) >> shift; + } + +-/** +- * ksz88x3_port_set_default_prio_quirks - Quirks for default priority +- * @dev: Pointer to the KSZ switch device structure +- * @port: Port number for which to set the default priority +- * @prio: Priority value to set +- * +- * This function implements quirks for setting the default priority on KSZ88x3 +- * devices. On Port 2, no other priority providers are working +- * except of PCP. So, configuring default priority on Port 2 is not possible. +- * On Port 1, it is not possible to configure port priority if PCP +- * apptrust on Port 2 is disabled. Since we disable multiple queues on the +- * switch to disable PCP on Port 2, we need to ensure that the default priority +- * configuration on Port 1 is in agreement with the configuration on Port 2. +- * +- * Return: 0 on success, or a negative error code on failure +- */ +-static int ksz88x3_port_set_default_prio_quirks(struct ksz_device *dev, int port, +- u8 prio) +-{ +- if (!prio) +- return 0; +- +- if (port == KSZ_PORT_2) { +- dev_err(dev->dev, "Port priority configuration is not working on Port 2\n"); +- return -EINVAL; +- } else if (port == KSZ_PORT_1) { +- u8 port2_data; +- int ret; +- +- ret = ksz_pread8(dev, KSZ_PORT_2, KSZ8_REG_PORT_1_CTRL_0, +- &port2_data); +- if (ret) +- return ret; +- +- if (!(port2_data & KSZ8_PORT_802_1P_ENABLE)) { +- dev_err(dev->dev, "Not possible to configure port priority on Port 1 if PCP apptrust on Port 2 is disabled\n"); +- return -EINVAL; +- } +- } +- +- return 0; +-} +- + /** + * ksz_port_set_default_prio - Sets the default priority for a port on a KSZ + * switch +@@ -239,18 +201,12 @@ static int ksz88x3_port_set_default_prio_quirks(struct ksz_device *dev, int port + int ksz_port_set_default_prio(struct dsa_switch *ds, int port, u8 prio) + { + struct ksz_device *dev = ds->priv; +- int reg, shift, ret; ++ int reg, shift; + u8 mask; + + if (prio >= dev->info->num_ipms) + return -EINVAL; + +- if (ksz_is_ksz88x3(dev)) { +- ret = ksz88x3_port_set_default_prio_quirks(dev, port, prio); +- if (ret) +- return ret; +- } +- + ksz_get_default_port_prio_reg(dev, ®, &mask, &shift); + + return ksz_prmw8(dev, port, reg, mask, (prio << shift) & mask); +@@ -518,155 +474,6 @@ static int ksz_port_set_apptrust_validate(struct ksz_device *dev, int port, + return -EINVAL; + } + +-/** +- * ksz88x3_port1_apptrust_quirk - Quirk for apptrust configuration on Port 1 +- * of KSZ88x3 devices +- * @dev: Pointer to the KSZ switch device structure +- * @port: Port number for which to set the apptrust selectors +- * @reg: Register address for the apptrust configuration +- * @port1_data: Data to set for the apptrust configuration +- * +- * This function implements a quirk for apptrust configuration on Port 1 of +- * KSZ88x3 devices. It ensures that apptrust configuration on Port 1 is not +- * possible if PCP apptrust on Port 2 is disabled. This is because the Port 2 +- * seems to be permanently hardwired to PCP classification, so we need to +- * do Port 1 configuration always in agreement with Port 2 configuration. +- * +- * Return: 0 on success, or a negative error code on failure +- */ +-static int ksz88x3_port1_apptrust_quirk(struct ksz_device *dev, int port, +- int reg, u8 port1_data) +-{ +- u8 port2_data; +- int ret; +- +- /* If no apptrust is requested for Port 1, no need to care about Port 2 +- * configuration. +- */ +- if (!(port1_data & (KSZ8_PORT_802_1P_ENABLE | KSZ8_PORT_DIFFSERV_ENABLE))) +- return 0; +- +- /* We got request to enable any apptrust on Port 1. To make it possible, +- * we need to enable multiple queues on the switch. If we enable +- * multiqueue support, PCP classification on Port 2 will be +- * automatically activated by HW. +- */ +- ret = ksz_pread8(dev, KSZ_PORT_2, reg, &port2_data); +- if (ret) +- return ret; +- +- /* If KSZ8_PORT_802_1P_ENABLE bit is set on Port 2, the driver showed +- * the interest in PCP classification on Port 2. In this case, +- * multiqueue support is enabled and we can enable any apptrust on +- * Port 1. +- * If KSZ8_PORT_802_1P_ENABLE bit is not set on Port 2, the PCP +- * classification on Port 2 is still active, but the driver disabled +- * multiqueue support and made frame prioritization inactive for +- * all ports. In this case, we can't enable any apptrust on Port 1. +- */ +- if (!(port2_data & KSZ8_PORT_802_1P_ENABLE)) { +- dev_err(dev->dev, "Not possible to enable any apptrust on Port 1 if PCP apptrust on Port 2 is disabled\n"); +- return -EINVAL; +- } +- +- return 0; +-} +- +-/** +- * ksz88x3_port2_apptrust_quirk - Quirk for apptrust configuration on Port 2 +- * of KSZ88x3 devices +- * @dev: Pointer to the KSZ switch device structure +- * @port: Port number for which to set the apptrust selectors +- * @reg: Register address for the apptrust configuration +- * @port2_data: Data to set for the apptrust configuration +- * +- * This function implements a quirk for apptrust configuration on Port 2 of +- * KSZ88x3 devices. It ensures that DSCP apptrust is not working on Port 2 and +- * that it is not possible to disable PCP on Port 2. The only way to disable PCP +- * on Port 2 is to disable multiple queues on the switch. +- * +- * Return: 0 on success, or a negative error code on failure +- */ +-static int ksz88x3_port2_apptrust_quirk(struct ksz_device *dev, int port, +- int reg, u8 port2_data) +-{ +- struct dsa_switch *ds = dev->ds; +- u8 port1_data; +- int ret; +- +- /* First validate Port 2 configuration. DiffServ/DSCP is not working +- * on this port. +- */ +- if (port2_data & KSZ8_PORT_DIFFSERV_ENABLE) { +- dev_err(dev->dev, "DSCP apptrust is not working on Port 2\n"); +- return -EINVAL; +- } +- +- /* If PCP support is requested, we need to enable all queues on the +- * switch to make PCP priority working on Port 2. +- */ +- if (port2_data & KSZ8_PORT_802_1P_ENABLE) +- return ksz8_all_queues_split(dev, dev->info->num_tx_queues); +- +- /* We got request to disable PCP priority on Port 2. +- * Now, we need to compare Port 2 configuration with Port 1 +- * configuration. +- */ +- ret = ksz_pread8(dev, KSZ_PORT_1, reg, &port1_data); +- if (ret) +- return ret; +- +- /* If Port 1 has any apptrust enabled, we can't disable multiple queues +- * on the switch, so we can't disable PCP on Port 2. +- */ +- if (port1_data & (KSZ8_PORT_802_1P_ENABLE | KSZ8_PORT_DIFFSERV_ENABLE)) { +- dev_err(dev->dev, "Not possible to disable PCP on Port 2 if any apptrust is enabled on Port 1\n"); +- return -EINVAL; +- } +- +- /* Now we need to ensure that default priority on Port 1 is set to 0 +- * otherwise we can't disable multiqueue support on the switch. +- */ +- ret = ksz_port_get_default_prio(ds, KSZ_PORT_1); +- if (ret < 0) { +- return ret; +- } else if (ret) { +- dev_err(dev->dev, "Not possible to disable PCP on Port 2 if non zero default priority is set on Port 1\n"); +- return -EINVAL; +- } +- +- /* Port 1 has no apptrust or default priority set and we got request to +- * disable PCP on Port 2. We can disable multiqueue support to disable +- * PCP on Port 2. +- */ +- return ksz8_all_queues_split(dev, 1); +-} +- +-/** +- * ksz88x3_port_apptrust_quirk - Quirk for apptrust configuration on KSZ88x3 +- * devices +- * @dev: Pointer to the KSZ switch device structure +- * @port: Port number for which to set the apptrust selectors +- * @reg: Register address for the apptrust configuration +- * @data: Data to set for the apptrust configuration +- * +- * This function implements a quirk for apptrust configuration on KSZ88x3 +- * devices. It ensures that apptrust configuration on Port 1 and +- * Port 2 is done in agreement with each other. +- * +- * Return: 0 on success, or a negative error code on failure +- */ +-static int ksz88x3_port_apptrust_quirk(struct ksz_device *dev, int port, +- int reg, u8 data) +-{ +- if (port == KSZ_PORT_1) +- return ksz88x3_port1_apptrust_quirk(dev, port, reg, data); +- else if (port == KSZ_PORT_2) +- return ksz88x3_port2_apptrust_quirk(dev, port, reg, data); +- +- return 0; +-} +- + /** + * ksz_port_set_apptrust - Sets the apptrust selectors for a port on a KSZ + * switch +@@ -707,12 +514,6 @@ int ksz_port_set_apptrust(struct dsa_switch *ds, int port, + } + } + +- if (ksz_is_ksz88x3(dev)) { +- ret = ksz88x3_port_apptrust_quirk(dev, port, reg, data); +- if (ret) +- return ret; +- } +- + return ksz_prmw8(dev, port, reg, mask, data); + } + +@@ -799,21 +600,5 @@ int ksz_dcb_init_port(struct ksz_device *dev, int port) + */ + int ksz_dcb_init(struct ksz_device *dev) + { +- int ret; +- +- ret = ksz_init_global_dscp_map(dev); +- if (ret) +- return ret; +- +- /* Enable 802.1p priority control on Port 2 during switch initialization. +- * This setup is critical for the apptrust functionality on Port 1, which +- * relies on the priority settings of Port 2. Note: Port 1 is naturally +- * configured before Port 2, necessitating this configuration order. +- */ +- if (ksz_is_ksz88x3(dev)) +- return ksz_prmw8(dev, KSZ_PORT_2, KSZ8_REG_PORT_1_CTRL_0, +- KSZ8_PORT_802_1P_ENABLE, +- KSZ8_PORT_802_1P_ENABLE); +- +- return 0; ++ return ksz_init_global_dscp_map(dev); + } +-- +2.39.5 + diff --git a/queue-6.14/net-dsa-mv88e6xxx-enable-.port_set_policy-for-6320-f.patch b/queue-6.14/net-dsa-mv88e6xxx-enable-.port_set_policy-for-6320-f.patch new file mode 100644 index 0000000000..28c61bf135 --- /dev/null +++ b/queue-6.14/net-dsa-mv88e6xxx-enable-.port_set_policy-for-6320-f.patch @@ -0,0 +1,48 @@ +From c9b8afc72b78bcce9f59702142756ee42e50e593 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 18:32:47 +0100 +Subject: net: dsa: mv88e6xxx: enable .port_set_policy() for 6320 family +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Marek Behún + +[ Upstream commit a2ef58e2c4aea4de166fc9832eb2b621e88c98d5 ] + +Commit f3a2cd326e44 ("net: dsa: mv88e6xxx: introduce .port_set_policy") +did not add the .port_set_policy() method for the 6320 family. Fix it. + +Fixes: f3a2cd326e44 ("net: dsa: mv88e6xxx: introduce .port_set_policy") +Signed-off-by: Marek Behún +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250317173250.28780-5-kabel@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/mv88e6xxx/chip.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index d8f037da5e294..b110704a7ee9a 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -5145,6 +5145,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { + .port_set_rgmii_delay = mv88e6320_port_set_rgmii_delay, + .port_set_speed_duplex = mv88e6185_port_set_speed_duplex, + .port_tag_remap = mv88e6095_port_tag_remap, ++ .port_set_policy = mv88e6352_port_set_policy, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, +@@ -5194,6 +5195,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { + .port_set_rgmii_delay = mv88e6320_port_set_rgmii_delay, + .port_set_speed_duplex = mv88e6185_port_set_speed_duplex, + .port_tag_remap = mv88e6095_port_tag_remap, ++ .port_set_policy = mv88e6352_port_set_policy, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, +-- +2.39.5 + diff --git a/queue-6.14/net-dsa-mv88e6xxx-enable-pvt-for-6321-switch.patch b/queue-6.14/net-dsa-mv88e6xxx-enable-pvt-for-6321-switch.patch new file mode 100644 index 0000000000..56a5e4492f --- /dev/null +++ b/queue-6.14/net-dsa-mv88e6xxx-enable-pvt-for-6321-switch.patch @@ -0,0 +1,40 @@ +From 6af543af31c19d15662ff618802e9ef548120b46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 18:32:46 +0100 +Subject: net: dsa: mv88e6xxx: enable PVT for 6321 switch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Marek Behún + +[ Upstream commit f85c69369854a43af2c5d3b3896da0908d713133 ] + +Commit f36456522168 ("net: dsa: mv88e6xxx: move PVT description in +info") did not enable PVT for 6321 switch. Fix it. + +Fixes: f36456522168 ("net: dsa: mv88e6xxx: move PVT description in info") +Signed-off-by: Marek Behún +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250317173250.28780-4-kabel@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/mv88e6xxx/chip.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index 841da8437738c..d8f037da5e294 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -6274,6 +6274,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { + .g2_irqs = 10, + .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1, + .atu_move_port_mask = 0xf, ++ .pvt = true, + .multi_chip = true, + .edsa_support = MV88E6XXX_EDSA_SUPPORTED, + .ptp_support = true, +-- +2.39.5 + diff --git a/queue-6.14/net-dsa-mv88e6xxx-enable-stu-methods-for-6320-family.patch b/queue-6.14/net-dsa-mv88e6xxx-enable-stu-methods-for-6320-family.patch new file mode 100644 index 0000000000..a1257c07a3 --- /dev/null +++ b/queue-6.14/net-dsa-mv88e6xxx-enable-stu-methods-for-6320-family.patch @@ -0,0 +1,67 @@ +From 3311351fe6e7d277417a1159716ab2ed0daa1aec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 18:32:48 +0100 +Subject: net: dsa: mv88e6xxx: enable STU methods for 6320 family +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Marek Behún + +[ Upstream commit 1428a6109b20e356188c3fb027bdb7998cc2fb98 ] + +Commit c050f5e91b47 ("net: dsa: mv88e6xxx: Fill in STU support for all +supported chips") introduced STU methods, but did not add them to the +6320 family. Fix it. + +Fixes: c050f5e91b47 ("net: dsa: mv88e6xxx: Fill in STU support for all supported chips") +Signed-off-by: Marek Behún +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250317173250.28780-6-kabel@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/mv88e6xxx/chip.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index f886a69d7a3ce..74b8bae226e4b 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -5172,6 +5172,8 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { + .reset = mv88e6352_g1_reset, + .vtu_getnext = mv88e6352_g1_vtu_getnext, + .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, ++ .stu_getnext = mv88e6352_g1_stu_getnext, ++ .stu_loadpurge = mv88e6352_g1_stu_loadpurge, + .gpio_ops = &mv88e6352_gpio_ops, + .avb_ops = &mv88e6352_avb_ops, + .ptp_ops = &mv88e6352_ptp_ops, +@@ -5221,6 +5223,8 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { + .reset = mv88e6352_g1_reset, + .vtu_getnext = mv88e6352_g1_vtu_getnext, + .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, ++ .stu_getnext = mv88e6352_g1_stu_getnext, ++ .stu_loadpurge = mv88e6352_g1_stu_loadpurge, + .gpio_ops = &mv88e6352_gpio_ops, + .avb_ops = &mv88e6352_avb_ops, + .ptp_ops = &mv88e6352_ptp_ops, +@@ -6241,6 +6245,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { + .num_internal_phys = 5, + .num_gpio = 15, + .max_vid = 4095, ++ .max_sid = 63, + .port_base_addr = 0x10, + .phy_base_addr = 0x0, + .global1_addr = 0x1b, +@@ -6267,6 +6272,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { + .num_internal_phys = 5, + .num_gpio = 15, + .max_vid = 4095, ++ .max_sid = 63, + .port_base_addr = 0x10, + .phy_base_addr = 0x0, + .global1_addr = 0x1b, +-- +2.39.5 + diff --git a/queue-6.14/net-dsa-mv88e6xxx-fix-atu_move_port_mask-for-6341-fa.patch b/queue-6.14/net-dsa-mv88e6xxx-fix-atu_move_port_mask-for-6341-fa.patch new file mode 100644 index 0000000000..b05585ffe2 --- /dev/null +++ b/queue-6.14/net-dsa-mv88e6xxx-fix-atu_move_port_mask-for-6341-fa.patch @@ -0,0 +1,50 @@ +From 43ada44a88e834e6f983b9d606f0377f2e37ed31 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 18:32:45 +0100 +Subject: net: dsa: mv88e6xxx: fix atu_move_port_mask for 6341 family +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Marek Behún + +[ Upstream commit 4ae01ec007716986e1a20f1285eb013cbf188830 ] + +The atu_move_port_mask for 6341 family (Topaz) is 0xf, not 0x1f. The +PortVec field is 8 bits wide, not 11 as in 6390 family. Fix this. + +Fixes: e606ca36bbf2 ("net: dsa: mv88e6xxx: rework ATU Remove") +Signed-off-by: Marek Behún +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250317173250.28780-3-kabel@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/mv88e6xxx/chip.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index 5db96ca52505a..841da8437738c 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -5818,7 +5818,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { + .global1_addr = 0x1b, + .global2_addr = 0x1c, + .age_time_coeff = 3750, +- .atu_move_port_mask = 0x1f, ++ .atu_move_port_mask = 0xf, + .g1_irqs = 9, + .g2_irqs = 10, + .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1, +@@ -6296,7 +6296,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { + .global1_addr = 0x1b, + .global2_addr = 0x1c, + .age_time_coeff = 3750, +- .atu_move_port_mask = 0x1f, ++ .atu_move_port_mask = 0xf, + .g1_irqs = 9, + .g2_irqs = 10, + .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1, +-- +2.39.5 + diff --git a/queue-6.14/net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch b/queue-6.14/net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch new file mode 100644 index 0000000000..bf61219e14 --- /dev/null +++ b/queue-6.14/net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch @@ -0,0 +1,56 @@ +From 117d552a354513ee07e18e5f582951e6390040d5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 18:32:44 +0100 +Subject: net: dsa: mv88e6xxx: fix VTU methods for 6320 family +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Marek Behún + +[ Upstream commit f9a457722cf5e3534be5ffab549d6b49737fca72 ] + +The VTU registers of the 6320 family use the 6352 semantics, not 6185. +Fix it. + +Fixes: b8fee9571063 ("net: dsa: mv88e6xxx: add VLAN Get Next support") +Signed-off-by: Marek Behún +Cc: # 5.15.x +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250317173250.28780-2-kabel@kernel.org +Signed-off-by: Jakub Kicinski +Stable-dep-of: 1428a6109b20 ("net: dsa: mv88e6xxx: enable STU methods for 6320 family") +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/mv88e6xxx/chip.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index b110704a7ee9a..f886a69d7a3ce 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -5170,8 +5170,8 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { + .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, + .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, + .reset = mv88e6352_g1_reset, +- .vtu_getnext = mv88e6185_g1_vtu_getnext, +- .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, ++ .vtu_getnext = mv88e6352_g1_vtu_getnext, ++ .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, + .gpio_ops = &mv88e6352_gpio_ops, + .avb_ops = &mv88e6352_avb_ops, + .ptp_ops = &mv88e6352_ptp_ops, +@@ -5219,8 +5219,8 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { + .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, + .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, + .reset = mv88e6352_g1_reset, +- .vtu_getnext = mv88e6185_g1_vtu_getnext, +- .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, ++ .vtu_getnext = mv88e6352_g1_vtu_getnext, ++ .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, + .gpio_ops = &mv88e6352_gpio_ops, + .avb_ops = &mv88e6352_avb_ops, + .ptp_ops = &mv88e6352_ptp_ops, +-- +2.39.5 + diff --git a/queue-6.14/net-dsa-mv88e6xxx-propperly-shutdown-ppu-re-enable-t.patch b/queue-6.14/net-dsa-mv88e6xxx-propperly-shutdown-ppu-re-enable-t.patch new file mode 100644 index 0000000000..f3cedb0dc2 --- /dev/null +++ b/queue-6.14/net-dsa-mv88e6xxx-propperly-shutdown-ppu-re-enable-t.patch @@ -0,0 +1,126 @@ +From bb4f685e245692536c6be854a8b3dc316ca67da2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Apr 2025 15:56:37 +0200 +Subject: net: dsa: mv88e6xxx: propperly shutdown PPU re-enable timer on + destroy + +From: David Oberhollenzer + +[ Upstream commit a58d882841a0750da3c482cd3d82432b1c7edb77 ] + +The mv88e6xxx has an internal PPU that polls PHY state. If we want to +access the internal PHYs, we need to disable the PPU first. Because +that is a slow operation, a 10ms timer is used to re-enable it, +canceled with every access, so bulk operations effectively only +disable it once and re-enable it some 10ms after the last access. + +If a PHY is accessed and then the mv88e6xxx module is removed before +the 10ms are up, the PPU re-enable ends up accessing a dangling pointer. + +This especially affects probing during bootup. The MDIO bus and PHY +registration may succeed, but registration with the DSA framework +may fail later on (e.g. because the CPU port depends on another, +very slow device that isn't done probing yet, returning -EPROBE_DEFER). +In this case, probe() fails, but the MDIO subsystem may already have +accessed the MIDO bus or PHYs, arming the timer. + +This is fixed as follows: + - If probe fails after mv88e6xxx_phy_init(), make sure we also call + mv88e6xxx_phy_destroy() before returning + - In mv88e6xxx_remove(), make sure we do the teardown in the correct + order, calling mv88e6xxx_phy_destroy() after unregistering the + switch device. + - In mv88e6xxx_phy_destroy(), destroy both the timer and the work item + that the timer might schedule, synchronously waiting in case one of + the callbacks already fired and destroying the timer first, before + waiting for the work item. + - Access to the PPU is guarded by a mutex, the worker acquires it + with a mutex_trylock(), not proceeding with the expensive shutdown + if that fails. We grab the mutex in mv88e6xxx_phy_destroy() to make + sure the slow PPU shutdown is already done or won't even enter, when + we wait for the work item. + +Fixes: 2e5f032095ff ("dsa: add support for the Marvell 88E6131 switch chip") +Signed-off-by: David Oberhollenzer +Reviewed-by: Vladimir Oltean +Link: https://patch.msgid.link/20250401135705.92760-1-david.oberhollenzer@sigma-star.at +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/mv88e6xxx/chip.c | 11 +++++++---- + drivers/net/dsa/mv88e6xxx/phy.c | 3 +++ + 2 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index 74b8bae226e4b..4a9fbfa8db41a 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -7331,13 +7331,13 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev) + err = mv88e6xxx_switch_reset(chip); + mv88e6xxx_reg_unlock(chip); + if (err) +- goto out; ++ goto out_phy; + + if (np) { + chip->irq = of_irq_get(np, 0); + if (chip->irq == -EPROBE_DEFER) { + err = chip->irq; +- goto out; ++ goto out_phy; + } + } + +@@ -7356,7 +7356,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev) + mv88e6xxx_reg_unlock(chip); + + if (err) +- goto out; ++ goto out_phy; + + if (chip->info->g2_irqs > 0) { + err = mv88e6xxx_g2_irq_setup(chip); +@@ -7390,6 +7390,8 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev) + mv88e6xxx_g1_irq_free(chip); + else + mv88e6xxx_irq_poll_free(chip); ++out_phy: ++ mv88e6xxx_phy_destroy(chip); + out: + if (pdata) + dev_put(pdata->netdev); +@@ -7412,7 +7414,6 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev) + mv88e6xxx_ptp_free(chip); + } + +- mv88e6xxx_phy_destroy(chip); + mv88e6xxx_unregister_switch(chip); + + mv88e6xxx_g1_vtu_prob_irq_free(chip); +@@ -7425,6 +7426,8 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev) + mv88e6xxx_g1_irq_free(chip); + else + mv88e6xxx_irq_poll_free(chip); ++ ++ mv88e6xxx_phy_destroy(chip); + } + + static void mv88e6xxx_shutdown(struct mdio_device *mdiodev) +diff --git a/drivers/net/dsa/mv88e6xxx/phy.c b/drivers/net/dsa/mv88e6xxx/phy.c +index 8bb88b3d900db..ee9e5d7e52770 100644 +--- a/drivers/net/dsa/mv88e6xxx/phy.c ++++ b/drivers/net/dsa/mv88e6xxx/phy.c +@@ -229,7 +229,10 @@ static void mv88e6xxx_phy_ppu_state_init(struct mv88e6xxx_chip *chip) + + static void mv88e6xxx_phy_ppu_state_destroy(struct mv88e6xxx_chip *chip) + { ++ mutex_lock(&chip->ppu_mutex); + del_timer_sync(&chip->ppu_timer); ++ cancel_work_sync(&chip->ppu_work); ++ mutex_unlock(&chip->ppu_mutex); + } + + int mv88e6185_phy_ppu_read(struct mv88e6xxx_chip *chip, struct mii_bus *bus, +-- +2.39.5 + diff --git a/queue-6.14/net-dsa-sja1105-fix-displaced-ethtool-statistics-cou.patch b/queue-6.14/net-dsa-sja1105-fix-displaced-ethtool-statistics-cou.patch new file mode 100644 index 0000000000..b809128eed --- /dev/null +++ b/queue-6.14/net-dsa-sja1105-fix-displaced-ethtool-statistics-cou.patch @@ -0,0 +1,63 @@ +From 64c4af0d938a2a0217c0ed07af970d36d6d7c9d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 13:57:14 +0200 +Subject: net: dsa: sja1105: fix displaced ethtool statistics counters + +From: Vladimir Oltean + +[ Upstream commit 00eb88752f48615ae7b4c1df6f9271cdd62c1d95 ] + +Port counters with no name (aka +sja1105_port_counters[__SJA1105_COUNTER_UNUSED]) are skipped when +reporting sja1105_get_sset_count(), but are not skipped during +sja1105_get_strings() and sja1105_get_ethtool_stats(). + +As a consequence, the first reported counter has an empty name and a +bogus value (reads from area 0, aka MAC, from offset 0, bits start:end +0:0). Also, the last counter (N_NOT_REACH on E/T, N_RX_BCAST on P/Q/R/S) +gets pushed out of the statistics counters that get shown. + +Skip __SJA1105_COUNTER_UNUSED consistently, so that the bogus counter +with an empty name disappears, and in its place appears a valid counter. + +Fixes: 039b167d68a3 ("net: dsa: sja1105: don't use burst SPI reads for port statistics") +Signed-off-by: Vladimir Oltean +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250318115716.2124395-2-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/sja1105/sja1105_ethtool.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/dsa/sja1105/sja1105_ethtool.c b/drivers/net/dsa/sja1105/sja1105_ethtool.c +index 2ea64b1d026d7..84d7d3f66bd03 100644 +--- a/drivers/net/dsa/sja1105/sja1105_ethtool.c ++++ b/drivers/net/dsa/sja1105/sja1105_ethtool.c +@@ -571,6 +571,9 @@ void sja1105_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data) + max_ctr = __MAX_SJA1105PQRS_PORT_COUNTER; + + for (i = 0; i < max_ctr; i++) { ++ if (!strlen(sja1105_port_counters[i].name)) ++ continue; ++ + rc = sja1105_port_counter_read(priv, port, i, &data[k++]); + if (rc) { + dev_err(ds->dev, +@@ -596,8 +599,12 @@ void sja1105_get_strings(struct dsa_switch *ds, int port, + else + max_ctr = __MAX_SJA1105PQRS_PORT_COUNTER; + +- for (i = 0; i < max_ctr; i++) ++ for (i = 0; i < max_ctr; i++) { ++ if (!strlen(sja1105_port_counters[i].name)) ++ continue; ++ + ethtool_puts(&data, sja1105_port_counters[i].name); ++ } + } + + int sja1105_get_sset_count(struct dsa_switch *ds, int port, int sset) +-- +2.39.5 + diff --git a/queue-6.14/net-dsa-sja1105-fix-kasan-out-of-bounds-warning-in-s.patch b/queue-6.14/net-dsa-sja1105-fix-kasan-out-of-bounds-warning-in-s.patch new file mode 100644 index 0000000000..11b5127fbe --- /dev/null +++ b/queue-6.14/net-dsa-sja1105-fix-kasan-out-of-bounds-warning-in-s.patch @@ -0,0 +1,51 @@ +From 64610c2066dc397edc6eaf1bfed6081de1606c18 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 13:57:16 +0200 +Subject: net: dsa: sja1105: fix kasan out-of-bounds warning in + sja1105_table_delete_entry() + +From: Vladimir Oltean + +[ Upstream commit 5f2b28b79d2d1946ee36ad8b3dc0066f73c90481 ] + +There are actually 2 problems: +- deleting the last element doesn't require the memmove of elements + [i + 1, end) over it. Actually, element i+1 is out of bounds. +- The memmove itself should move size - i - 1 elements, because the last + element is out of bounds. + +The out-of-bounds element still remains out of bounds after being +accessed, so the problem is only that we touch it, not that it becomes +in active use. But I suppose it can lead to issues if the out-of-bounds +element is part of an unmapped page. + +Fixes: 6666cebc5e30 ("net: dsa: sja1105: Add support for VLAN operations") +Signed-off-by: Vladimir Oltean +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250318115716.2124395-4-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/sja1105/sja1105_static_config.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/dsa/sja1105/sja1105_static_config.c b/drivers/net/dsa/sja1105/sja1105_static_config.c +index 3d790f8c6f4da..ffece8a400a66 100644 +--- a/drivers/net/dsa/sja1105/sja1105_static_config.c ++++ b/drivers/net/dsa/sja1105/sja1105_static_config.c +@@ -1917,8 +1917,10 @@ int sja1105_table_delete_entry(struct sja1105_table *table, int i) + if (i > table->entry_count) + return -ERANGE; + +- memmove(entries + i * entry_size, entries + (i + 1) * entry_size, +- (table->entry_count - i) * entry_size); ++ if (i + 1 < table->entry_count) { ++ memmove(entries + i * entry_size, entries + (i + 1) * entry_size, ++ (table->entry_count - i - 1) * entry_size); ++ } + + table->entry_count--; + +-- +2.39.5 + diff --git a/queue-6.14/net-dsa-sja1105-reject-other-rx-filters-than-hwtstam.patch b/queue-6.14/net-dsa-sja1105-reject-other-rx-filters-than-hwtstam.patch new file mode 100644 index 0000000000..853ab55160 --- /dev/null +++ b/queue-6.14/net-dsa-sja1105-reject-other-rx-filters-than-hwtstam.patch @@ -0,0 +1,83 @@ +From 2e908e279f595687f383f97c900f0b6e2f42a84d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 13:57:15 +0200 +Subject: net: dsa: sja1105: reject other RX filters than + HWTSTAMP_FILTER_PTP_V2_L2_EVENT + +From: Vladimir Oltean + +[ Upstream commit b6a177b559717b707087114e08537fd47a4d1aca ] + +This is all that we can support timestamping, so we shouldn't accept +anything else. Also see sja1105_hwtstamp_get(). + +To avoid erroring out in an inconsistent state, operate on copies of +priv->hwts_rx_en and priv->hwts_tx_en, and write them back when nothing +else can fail anymore. + +Fixes: a602afd200f5 ("net: dsa: sja1105: Expose PTP timestamping ioctls to userspace") +Signed-off-by: Vladimir Oltean +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250318115716.2124395-3-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/sja1105/sja1105_ptp.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/dsa/sja1105/sja1105_ptp.c b/drivers/net/dsa/sja1105/sja1105_ptp.c +index a1f4ca6ad888f..08b45fdd1d248 100644 +--- a/drivers/net/dsa/sja1105/sja1105_ptp.c ++++ b/drivers/net/dsa/sja1105/sja1105_ptp.c +@@ -61,17 +61,21 @@ enum sja1105_ptp_clk_mode { + int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr) + { + struct sja1105_private *priv = ds->priv; ++ unsigned long hwts_tx_en, hwts_rx_en; + struct hwtstamp_config config; + + if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) + return -EFAULT; + ++ hwts_tx_en = priv->hwts_tx_en; ++ hwts_rx_en = priv->hwts_rx_en; ++ + switch (config.tx_type) { + case HWTSTAMP_TX_OFF: +- priv->hwts_tx_en &= ~BIT(port); ++ hwts_tx_en &= ~BIT(port); + break; + case HWTSTAMP_TX_ON: +- priv->hwts_tx_en |= BIT(port); ++ hwts_tx_en |= BIT(port); + break; + default: + return -ERANGE; +@@ -79,15 +83,21 @@ int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr) + + switch (config.rx_filter) { + case HWTSTAMP_FILTER_NONE: +- priv->hwts_rx_en &= ~BIT(port); ++ hwts_rx_en &= ~BIT(port); + break; +- default: +- priv->hwts_rx_en |= BIT(port); ++ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: ++ hwts_rx_en |= BIT(port); + break; ++ default: ++ return -ERANGE; + } + + if (copy_to_user(ifr->ifr_data, &config, sizeof(config))) + return -EFAULT; ++ ++ priv->hwts_tx_en = hwts_tx_en; ++ priv->hwts_rx_en = hwts_rx_en; ++ + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/net-fix-geneve_opt-length-integer-overflow.patch b/queue-6.14/net-fix-geneve_opt-length-integer-overflow.patch new file mode 100644 index 0000000000..e37181f11f --- /dev/null +++ b/queue-6.14/net-fix-geneve_opt-length-integer-overflow.patch @@ -0,0 +1,134 @@ +From 7dc5d98df94af67f0655d53b08e208079378da72 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 3 Apr 2025 00:56:32 +0800 +Subject: net: fix geneve_opt length integer overflow + +From: Lin Ma + +[ Upstream commit b27055a08ad4b415dcf15b63034f9cb236f7fb40 ] + +struct geneve_opt uses 5 bit length for each single option, which +means every vary size option should be smaller than 128 bytes. + +However, all current related Netlink policies cannot promise this +length condition and the attacker can exploit a exact 128-byte size +option to *fake* a zero length option and confuse the parsing logic, +further achieve heap out-of-bounds read. + +One example crash log is like below: + +[ 3.905425] ================================================================== +[ 3.905925] BUG: KASAN: slab-out-of-bounds in nla_put+0xa9/0xe0 +[ 3.906255] Read of size 124 at addr ffff888005f291cc by task poc/177 +[ 3.906646] +[ 3.906775] CPU: 0 PID: 177 Comm: poc-oob-read Not tainted 6.1.132 #1 +[ 3.907131] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014 +[ 3.907784] Call Trace: +[ 3.907925] +[ 3.908048] dump_stack_lvl+0x44/0x5c +[ 3.908258] print_report+0x184/0x4be +[ 3.909151] kasan_report+0xc5/0x100 +[ 3.909539] kasan_check_range+0xf3/0x1a0 +[ 3.909794] memcpy+0x1f/0x60 +[ 3.909968] nla_put+0xa9/0xe0 +[ 3.910147] tunnel_key_dump+0x945/0xba0 +[ 3.911536] tcf_action_dump_1+0x1c1/0x340 +[ 3.912436] tcf_action_dump+0x101/0x180 +[ 3.912689] tcf_exts_dump+0x164/0x1e0 +[ 3.912905] fw_dump+0x18b/0x2d0 +[ 3.913483] tcf_fill_node+0x2ee/0x460 +[ 3.914778] tfilter_notify+0xf4/0x180 +[ 3.915208] tc_new_tfilter+0xd51/0x10d0 +[ 3.918615] rtnetlink_rcv_msg+0x4a2/0x560 +[ 3.919118] netlink_rcv_skb+0xcd/0x200 +[ 3.919787] netlink_unicast+0x395/0x530 +[ 3.921032] netlink_sendmsg+0x3d0/0x6d0 +[ 3.921987] __sock_sendmsg+0x99/0xa0 +[ 3.922220] __sys_sendto+0x1b7/0x240 +[ 3.922682] __x64_sys_sendto+0x72/0x90 +[ 3.922906] do_syscall_64+0x5e/0x90 +[ 3.923814] entry_SYSCALL_64_after_hwframe+0x6e/0xd8 +[ 3.924122] RIP: 0033:0x7e83eab84407 +[ 3.924331] Code: 48 89 fa 4c 89 df e8 38 aa 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 faf +[ 3.925330] RSP: 002b:00007ffff505e370 EFLAGS: 00000202 ORIG_RAX: 000000000000002c +[ 3.925752] RAX: ffffffffffffffda RBX: 00007e83eaafa740 RCX: 00007e83eab84407 +[ 3.926173] RDX: 00000000000001a8 RSI: 00007ffff505e3c0 RDI: 0000000000000003 +[ 3.926587] RBP: 00007ffff505f460 R08: 00007e83eace1000 R09: 000000000000000c +[ 3.926977] R10: 0000000000000000 R11: 0000000000000202 R12: 00007ffff505f3c0 +[ 3.927367] R13: 00007ffff505f5c8 R14: 00007e83ead1b000 R15: 00005d4fbbe6dcb8 + +Fix these issues by enforing correct length condition in related +policies. + +Fixes: 925d844696d9 ("netfilter: nft_tunnel: add support for geneve opts") +Fixes: 4ece47787077 ("lwtunnel: add options setting and dumping for geneve") +Fixes: 0ed5269f9e41 ("net/sched: add tunnel option support to act_tunnel_key") +Fixes: 0a6e77784f49 ("net/sched: allow flower to match tunnel options") +Signed-off-by: Lin Ma +Reviewed-by: Xin Long +Acked-by: Cong Wang +Link: https://patch.msgid.link/20250402165632.6958-1-linma@zju.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/ip_tunnel_core.c | 2 +- + net/netfilter/nft_tunnel.c | 2 +- + net/sched/act_tunnel_key.c | 2 +- + net/sched/cls_flower.c | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c +index 364ea798511ea..f65d2f7273813 100644 +--- a/net/ipv4/ip_tunnel_core.c ++++ b/net/ipv4/ip_tunnel_core.c +@@ -451,7 +451,7 @@ static const struct nla_policy + geneve_opt_policy[LWTUNNEL_IP_OPT_GENEVE_MAX + 1] = { + [LWTUNNEL_IP_OPT_GENEVE_CLASS] = { .type = NLA_U16 }, + [LWTUNNEL_IP_OPT_GENEVE_TYPE] = { .type = NLA_U8 }, +- [LWTUNNEL_IP_OPT_GENEVE_DATA] = { .type = NLA_BINARY, .len = 128 }, ++ [LWTUNNEL_IP_OPT_GENEVE_DATA] = { .type = NLA_BINARY, .len = 127 }, + }; + + static const struct nla_policy +diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c +index 2e40f575aed9f..0c63d1367cf7a 100644 +--- a/net/netfilter/nft_tunnel.c ++++ b/net/netfilter/nft_tunnel.c +@@ -335,7 +335,7 @@ static int nft_tunnel_obj_erspan_init(const struct nlattr *attr, + static const struct nla_policy nft_tunnel_opts_geneve_policy[NFTA_TUNNEL_KEY_GENEVE_MAX + 1] = { + [NFTA_TUNNEL_KEY_GENEVE_CLASS] = { .type = NLA_U16 }, + [NFTA_TUNNEL_KEY_GENEVE_TYPE] = { .type = NLA_U8 }, +- [NFTA_TUNNEL_KEY_GENEVE_DATA] = { .type = NLA_BINARY, .len = 128 }, ++ [NFTA_TUNNEL_KEY_GENEVE_DATA] = { .type = NLA_BINARY, .len = 127 }, + }; + + static int nft_tunnel_obj_geneve_init(const struct nlattr *attr, +diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c +index af7c998459488..e296714803dc0 100644 +--- a/net/sched/act_tunnel_key.c ++++ b/net/sched/act_tunnel_key.c +@@ -68,7 +68,7 @@ geneve_opt_policy[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX + 1] = { + [TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS] = { .type = NLA_U16 }, + [TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE] = { .type = NLA_U8 }, + [TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA] = { .type = NLA_BINARY, +- .len = 128 }, ++ .len = 127 }, + }; + + static const struct nla_policy +diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c +index 03505673d5234..099ff6a3e1f51 100644 +--- a/net/sched/cls_flower.c ++++ b/net/sched/cls_flower.c +@@ -766,7 +766,7 @@ geneve_opt_policy[TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX + 1] = { + [TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS] = { .type = NLA_U16 }, + [TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE] = { .type = NLA_U8 }, + [TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA] = { .type = NLA_BINARY, +- .len = 128 }, ++ .len = 127 }, + }; + + static const struct nla_policy +-- +2.39.5 + diff --git a/queue-6.14/net-fix-null-pointer-dereference-in-l3mdev_l3_rcv.patch b/queue-6.14/net-fix-null-pointer-dereference-in-l3mdev_l3_rcv.patch new file mode 100644 index 0000000000..6e39e0d910 --- /dev/null +++ b/queue-6.14/net-fix-null-pointer-dereference-in-l3mdev_l3_rcv.patch @@ -0,0 +1,66 @@ +From cdb4d9598aa997b693a176ca3a033ae199e5ad81 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 17:03:53 +0800 +Subject: net: fix NULL pointer dereference in l3mdev_l3_rcv + +From: Wang Liang + +[ Upstream commit 0032c99e83b9ce6d5995d65900aa4b6ffb501cce ] + +When delete l3s ipvlan: + + ip link del link eth0 ipvlan1 type ipvlan mode l3s + +This may cause a null pointer dereference: + + Call trace: + ip_rcv_finish+0x48/0xd0 + ip_rcv+0x5c/0x100 + __netif_receive_skb_one_core+0x64/0xb0 + __netif_receive_skb+0x20/0x80 + process_backlog+0xb4/0x204 + napi_poll+0xe8/0x294 + net_rx_action+0xd8/0x22c + __do_softirq+0x12c/0x354 + +This is because l3mdev_l3_rcv() visit dev->l3mdev_ops after +ipvlan_l3s_unregister() assign the dev->l3mdev_ops to NULL. The process +like this: + + (CPU1) | (CPU2) + l3mdev_l3_rcv() | + check dev->priv_flags: | + master = skb->dev; | + | + | ipvlan_l3s_unregister() + | set dev->priv_flags + | dev->l3mdev_ops = NULL; + | + visit master->l3mdev_ops | + +To avoid this by do not set dev->l3mdev_ops when unregister l3s ipvlan. + +Suggested-by: David Ahern +Fixes: c675e06a98a4 ("ipvlan: decouple l3s mode dependencies from other modes") +Signed-off-by: Wang Liang +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250321090353.1170545-1-wangliang74@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ipvlan/ipvlan_l3s.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/net/ipvlan/ipvlan_l3s.c b/drivers/net/ipvlan/ipvlan_l3s.c +index b4ef386bdb1ba..7c017fe35522a 100644 +--- a/drivers/net/ipvlan/ipvlan_l3s.c ++++ b/drivers/net/ipvlan/ipvlan_l3s.c +@@ -226,5 +226,4 @@ void ipvlan_l3s_unregister(struct ipvl_port *port) + + dev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER; + ipvlan_unregister_nf_hook(read_pnet(&port->pnet)); +- dev->l3mdev_ops = NULL; + } +-- +2.39.5 + diff --git a/queue-6.14/net-fix-the-devmem-sock-opts-and-msgs-for-parisc.patch b/queue-6.14/net-fix-the-devmem-sock-opts-and-msgs-for-parisc.patch new file mode 100644 index 0000000000..c46993e18d --- /dev/null +++ b/queue-6.14/net-fix-the-devmem-sock-opts-and-msgs-for-parisc.patch @@ -0,0 +1,65 @@ +From b261dcf8be84d8261c5fbf5dc110310d5fe3711a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 07:42:27 +0000 +Subject: net: Fix the devmem sock opts and msgs for parisc + +From: Pranjal Shrivastava + +[ Upstream commit fd87b7783802b45cdd261b273e6b2b792823064d ] + +The devmem socket options and socket control message definitions +introduced in the TCP devmem series[1] incorrectly continued the socket +definitions for arch/parisc. + +The UAPI change seems safe as there are currently no drivers that +declare support for devmem TCP RX via PP_FLAG_ALLOW_UNREADABLE_NETMEM. +Hence, fixing this UAPI should be safe. + +Fix the devmem socket options and socket control message definitions to +reflect the series followed by arch/parisc. + +[1] +https://lore.kernel.org/lkml/20240910171458.219195-10-almasrymina@google.com/ + +Fixes: 8f0b3cc9a4c10 ("tcp: RX path for devmem TCP") +Signed-off-by: Pranjal Shrivastava +Reviewed-by: Willem de Bruijn +Reviewed-by: Jason Xing +Reviewed-by: Mina Almasry +Link: https://patch.msgid.link/20250324074228.3139088-1-praan@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + arch/parisc/include/uapi/asm/socket.h | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h +index aa9cd4b951fe5..96831c9886065 100644 +--- a/arch/parisc/include/uapi/asm/socket.h ++++ b/arch/parisc/include/uapi/asm/socket.h +@@ -132,16 +132,16 @@ + #define SO_PASSPIDFD 0x404A + #define SO_PEERPIDFD 0x404B + +-#define SO_DEVMEM_LINEAR 78 +-#define SCM_DEVMEM_LINEAR SO_DEVMEM_LINEAR +-#define SO_DEVMEM_DMABUF 79 +-#define SCM_DEVMEM_DMABUF SO_DEVMEM_DMABUF +-#define SO_DEVMEM_DONTNEED 80 +- + #define SCM_TS_OPT_ID 0x404C + + #define SO_RCVPRIORITY 0x404D + ++#define SO_DEVMEM_LINEAR 0x404E ++#define SCM_DEVMEM_LINEAR SO_DEVMEM_LINEAR ++#define SO_DEVMEM_DMABUF 0x404F ++#define SCM_DEVMEM_DMABUF SO_DEVMEM_DMABUF ++#define SO_DEVMEM_DONTNEED 0x4050 ++ + #if !defined(__KERNEL__) + + #if __BITS_PER_LONG == 64 +-- +2.39.5 + diff --git a/queue-6.14/net-ibmveth-make-veth_pool_store-stop-hanging.patch b/queue-6.14/net-ibmveth-make-veth_pool_store-stop-hanging.patch new file mode 100644 index 0000000000..ec667513db --- /dev/null +++ b/queue-6.14/net-ibmveth-make-veth_pool_store-stop-hanging.patch @@ -0,0 +1,211 @@ +From 20ed1547669d6f5ef0e15dcb1c77a2c4e11afd2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Apr 2025 10:44:03 -0500 +Subject: net: ibmveth: make veth_pool_store stop hanging + +From: Dave Marquardt + +[ Upstream commit 053f3ff67d7feefc75797863f3d84b47ad47086f ] + +v2: +- Created a single error handling unlock and exit in veth_pool_store +- Greatly expanded commit message with previous explanatory-only text + +Summary: Use rtnl_mutex to synchronize veth_pool_store with itself, +ibmveth_close and ibmveth_open, preventing multiple calls in a row to +napi_disable. + +Background: Two (or more) threads could call veth_pool_store through +writing to /sys/devices/vio/30000002/pool*/*. You can do this easily +with a little shell script. This causes a hang. + +I configured LOCKDEP, compiled ibmveth.c with DEBUG, and built a new +kernel. I ran this test again and saw: + + Setting pool0/active to 0 + Setting pool1/active to 1 + [ 73.911067][ T4365] ibmveth 30000002 eth0: close starting + Setting pool1/active to 1 + Setting pool1/active to 0 + [ 73.911367][ T4366] ibmveth 30000002 eth0: close starting + [ 73.916056][ T4365] ibmveth 30000002 eth0: close complete + [ 73.916064][ T4365] ibmveth 30000002 eth0: open starting + [ 110.808564][ T712] systemd-journald[712]: Sent WATCHDOG=1 notification. + [ 230.808495][ T712] systemd-journald[712]: Sent WATCHDOG=1 notification. + [ 243.683786][ T123] INFO: task stress.sh:4365 blocked for more than 122 seconds. + [ 243.683827][ T123] Not tainted 6.14.0-01103-g2df0c02dab82-dirty #8 + [ 243.683833][ T123] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. + [ 243.683838][ T123] task:stress.sh state:D stack:28096 pid:4365 tgid:4365 ppid:4364 task_flags:0x400040 flags:0x00042000 + [ 243.683852][ T123] Call Trace: + [ 243.683857][ T123] [c00000000c38f690] [0000000000000001] 0x1 (unreliable) + [ 243.683868][ T123] [c00000000c38f840] [c00000000001f908] __switch_to+0x318/0x4e0 + [ 243.683878][ T123] [c00000000c38f8a0] [c000000001549a70] __schedule+0x500/0x12a0 + [ 243.683888][ T123] [c00000000c38f9a0] [c00000000154a878] schedule+0x68/0x210 + [ 243.683896][ T123] [c00000000c38f9d0] [c00000000154ac80] schedule_preempt_disabled+0x30/0x50 + [ 243.683904][ T123] [c00000000c38fa00] [c00000000154dbb0] __mutex_lock+0x730/0x10f0 + [ 243.683913][ T123] [c00000000c38fb10] [c000000001154d40] napi_enable+0x30/0x60 + [ 243.683921][ T123] [c00000000c38fb40] [c000000000f4ae94] ibmveth_open+0x68/0x5dc + [ 243.683928][ T123] [c00000000c38fbe0] [c000000000f4aa20] veth_pool_store+0x220/0x270 + [ 243.683936][ T123] [c00000000c38fc70] [c000000000826278] sysfs_kf_write+0x68/0xb0 + [ 243.683944][ T123] [c00000000c38fcb0] [c0000000008240b8] kernfs_fop_write_iter+0x198/0x2d0 + [ 243.683951][ T123] [c00000000c38fd00] [c00000000071b9ac] vfs_write+0x34c/0x650 + [ 243.683958][ T123] [c00000000c38fdc0] [c00000000071bea8] ksys_write+0x88/0x150 + [ 243.683966][ T123] [c00000000c38fe10] [c0000000000317f4] system_call_exception+0x124/0x340 + [ 243.683973][ T123] [c00000000c38fe50] [c00000000000d05c] system_call_vectored_common+0x15c/0x2ec + ... + [ 243.684087][ T123] Showing all locks held in the system: + [ 243.684095][ T123] 1 lock held by khungtaskd/123: + [ 243.684099][ T123] #0: c00000000278e370 (rcu_read_lock){....}-{1:2}, at: debug_show_all_locks+0x50/0x248 + [ 243.684114][ T123] 4 locks held by stress.sh/4365: + [ 243.684119][ T123] #0: c00000003a4cd3f8 (sb_writers#3){.+.+}-{0:0}, at: ksys_write+0x88/0x150 + [ 243.684132][ T123] #1: c000000041aea888 (&of->mutex#2){+.+.}-{3:3}, at: kernfs_fop_write_iter+0x154/0x2d0 + [ 243.684143][ T123] #2: c0000000366fb9a8 (kn->active#64){.+.+}-{0:0}, at: kernfs_fop_write_iter+0x160/0x2d0 + [ 243.684155][ T123] #3: c000000035ff4cb8 (&dev->lock){+.+.}-{3:3}, at: napi_enable+0x30/0x60 + [ 243.684166][ T123] 5 locks held by stress.sh/4366: + [ 243.684170][ T123] #0: c00000003a4cd3f8 (sb_writers#3){.+.+}-{0:0}, at: ksys_write+0x88/0x150 + [ 243.684183][ T123] #1: c00000000aee2288 (&of->mutex#2){+.+.}-{3:3}, at: kernfs_fop_write_iter+0x154/0x2d0 + [ 243.684194][ T123] #2: c0000000366f4ba8 (kn->active#64){.+.+}-{0:0}, at: kernfs_fop_write_iter+0x160/0x2d0 + [ 243.684205][ T123] #3: c000000035ff4cb8 (&dev->lock){+.+.}-{3:3}, at: napi_disable+0x30/0x60 + [ 243.684216][ T123] #4: c0000003ff9bbf18 (&rq->__lock){-.-.}-{2:2}, at: __schedule+0x138/0x12a0 + +From the ibmveth debug, two threads are calling veth_pool_store, which +calls ibmveth_close and ibmveth_open. Here's the sequence: + + T4365 T4366 + ----------------- ----------------- --------- + veth_pool_store veth_pool_store + ibmveth_close + ibmveth_close + napi_disable + napi_disable + ibmveth_open + napi_enable <- HANG + +ibmveth_close calls napi_disable at the top and ibmveth_open calls +napi_enable at the top. + +https://docs.kernel.org/networking/napi.html]] says + + The control APIs are not idempotent. Control API calls are safe + against concurrent use of datapath APIs but an incorrect sequence of + control API calls may result in crashes, deadlocks, or race + conditions. For example, calling napi_disable() multiple times in a + row will deadlock. + +In the normal open and close paths, rtnl_mutex is acquired to prevent +other callers. This is missing from veth_pool_store. Use rtnl_mutex in +veth_pool_store fixes these hangs. + +Signed-off-by: Dave Marquardt +Fixes: 860f242eb534 ("[PATCH] ibmveth change buffer pools dynamically") +Reviewed-by: Nick Child +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250402154403.386744-1-davemarq@linux.ibm.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/ibm/ibmveth.c | 39 +++++++++++++++++++++--------- + 1 file changed, 27 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c +index b619a3ec245b2..04192190bebab 100644 +--- a/drivers/net/ethernet/ibm/ibmveth.c ++++ b/drivers/net/ethernet/ibm/ibmveth.c +@@ -1802,18 +1802,22 @@ static ssize_t veth_pool_store(struct kobject *kobj, struct attribute *attr, + long value = simple_strtol(buf, NULL, 10); + long rc; + ++ rtnl_lock(); ++ + if (attr == &veth_active_attr) { + if (value && !pool->active) { + if (netif_running(netdev)) { + if (ibmveth_alloc_buffer_pool(pool)) { + netdev_err(netdev, + "unable to alloc pool\n"); +- return -ENOMEM; ++ rc = -ENOMEM; ++ goto unlock_err; + } + pool->active = 1; + ibmveth_close(netdev); +- if ((rc = ibmveth_open(netdev))) +- return rc; ++ rc = ibmveth_open(netdev); ++ if (rc) ++ goto unlock_err; + } else { + pool->active = 1; + } +@@ -1833,48 +1837,59 @@ static ssize_t veth_pool_store(struct kobject *kobj, struct attribute *attr, + + if (i == IBMVETH_NUM_BUFF_POOLS) { + netdev_err(netdev, "no active pool >= MTU\n"); +- return -EPERM; ++ rc = -EPERM; ++ goto unlock_err; + } + + if (netif_running(netdev)) { + ibmveth_close(netdev); + pool->active = 0; +- if ((rc = ibmveth_open(netdev))) +- return rc; ++ rc = ibmveth_open(netdev); ++ if (rc) ++ goto unlock_err; + } + pool->active = 0; + } + } else if (attr == &veth_num_attr) { + if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT) { +- return -EINVAL; ++ rc = -EINVAL; ++ goto unlock_err; + } else { + if (netif_running(netdev)) { + ibmveth_close(netdev); + pool->size = value; +- if ((rc = ibmveth_open(netdev))) +- return rc; ++ rc = ibmveth_open(netdev); ++ if (rc) ++ goto unlock_err; + } else { + pool->size = value; + } + } + } else if (attr == &veth_size_attr) { + if (value <= IBMVETH_BUFF_OH || value > IBMVETH_MAX_BUF_SIZE) { +- return -EINVAL; ++ rc = -EINVAL; ++ goto unlock_err; + } else { + if (netif_running(netdev)) { + ibmveth_close(netdev); + pool->buff_size = value; +- if ((rc = ibmveth_open(netdev))) +- return rc; ++ rc = ibmveth_open(netdev); ++ if (rc) ++ goto unlock_err; + } else { + pool->buff_size = value; + } + } + } ++ rtnl_unlock(); + + /* kick the interrupt handler to allocate/deallocate pools */ + ibmveth_interrupt(netdev->irq, netdev); + return count; ++ ++unlock_err: ++ rtnl_unlock(); ++ return rc; + } + + +-- +2.39.5 + diff --git a/queue-6.14/net-lan743x-reject-unsupported-external-timestamp-re.patch b/queue-6.14/net-lan743x-reject-unsupported-external-timestamp-re.patch new file mode 100644 index 0000000000..80976f9f4c --- /dev/null +++ b/queue-6.14/net-lan743x-reject-unsupported-external-timestamp-re.patch @@ -0,0 +1,48 @@ +From 8272f856dff510ace46d78ff923394a9448c85a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 15:15:52 -0700 +Subject: net: lan743x: reject unsupported external timestamp requests + +From: Jacob Keller + +[ Upstream commit c0b4ddd30871c59043ed3592e6abeee55c3bf045 ] + +The lan743x_ptp_io_event_cap_en() function checks that the given request +sets only one of PTP_RISING_EDGE or PTP_FALLING_EDGE, but not both. + +However, this driver does not check whether other flags (such as +PTP_EXT_OFF) are set, nor whether any future unrecognized flags are set. + +Fix this by adding the appropriate check to the lan743x_ptp_io_extts() +function. + +Fixes: 60942c397af6 ("net: lan743x: Add support for PTP-IO Event Input External Timestamp (extts)") +Signed-off-by: Jacob Keller +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250312-jk-net-fixes-supported-extts-flags-v2-3-ea930ba82459@intel.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/microchip/lan743x_ptp.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/ethernet/microchip/lan743x_ptp.c b/drivers/net/ethernet/microchip/lan743x_ptp.c +index 4a777b449ecd0..0be44dcb33938 100644 +--- a/drivers/net/ethernet/microchip/lan743x_ptp.c ++++ b/drivers/net/ethernet/microchip/lan743x_ptp.c +@@ -942,6 +942,12 @@ static int lan743x_ptp_io_extts(struct lan743x_adapter *adapter, int on, + + extts = &ptp->extts[index]; + ++ if (extts_request->flags & ~(PTP_ENABLE_FEATURE | ++ PTP_RISING_EDGE | ++ PTP_FALLING_EDGE | ++ PTP_STRICT_FLAGS)) ++ return -EOPNOTSUPP; ++ + if (on) { + extts_pin = ptp_find_pin(ptp->ptp_clock, PTP_PF_EXTTS, index); + if (extts_pin < 0) +-- +2.39.5 + diff --git a/queue-6.14/net-libwx-fix-tx-descriptor-content-for-some-tunnel-.patch b/queue-6.14/net-libwx-fix-tx-descriptor-content-for-some-tunnel-.patch new file mode 100644 index 0000000000..139207106e --- /dev/null +++ b/queue-6.14/net-libwx-fix-tx-descriptor-content-for-some-tunnel-.patch @@ -0,0 +1,183 @@ +From b5ba6a9512628f0d93eb717625be95e3efacc40d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 18:32:34 +0800 +Subject: net: libwx: fix Tx descriptor content for some tunnel packets + +From: Jiawen Wu + +[ Upstream commit a44940d094afa2e04b5b164b1e136fc18bcb4a2d ] + +The length of skb header was incorrectly calculated when transmit a tunnel +packet with outer IPv6 extension header, or a IP over IP packet which has +inner IPv6 header. Thus the correct Tx context descriptor cannot be +composed, resulting in Tx ring hang. + +Fixes: 3403960cdf86 ("net: wangxun: libwx add tx offload functions") +Signed-off-by: Jiawen Wu +Link: https://patch.msgid.link/20250324103235.823096-1-jiawenwu@trustnetic.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/wangxun/libwx/wx_lib.c | 61 +++++++++++++-------- + 1 file changed, 37 insertions(+), 24 deletions(-) + +diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c +index 2b3d6586f44a5..9294a9d8c5541 100644 +--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c ++++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c +@@ -1082,26 +1082,6 @@ static void wx_tx_ctxtdesc(struct wx_ring *tx_ring, u32 vlan_macip_lens, + context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx); + } + +-static void wx_get_ipv6_proto(struct sk_buff *skb, int offset, u8 *nexthdr) +-{ +- struct ipv6hdr *hdr = (struct ipv6hdr *)(skb->data + offset); +- +- *nexthdr = hdr->nexthdr; +- offset += sizeof(struct ipv6hdr); +- while (ipv6_ext_hdr(*nexthdr)) { +- struct ipv6_opt_hdr _hdr, *hp; +- +- if (*nexthdr == NEXTHDR_NONE) +- return; +- hp = skb_header_pointer(skb, offset, sizeof(_hdr), &_hdr); +- if (!hp) +- return; +- if (*nexthdr == NEXTHDR_FRAGMENT) +- break; +- *nexthdr = hp->nexthdr; +- } +-} +- + union network_header { + struct iphdr *ipv4; + struct ipv6hdr *ipv6; +@@ -1112,6 +1092,8 @@ static u8 wx_encode_tx_desc_ptype(const struct wx_tx_buffer *first) + { + u8 tun_prot = 0, l4_prot = 0, ptype = 0; + struct sk_buff *skb = first->skb; ++ unsigned char *exthdr, *l4_hdr; ++ __be16 frag_off; + + if (skb->encapsulation) { + union network_header hdr; +@@ -1122,14 +1104,18 @@ static u8 wx_encode_tx_desc_ptype(const struct wx_tx_buffer *first) + ptype = WX_PTYPE_TUN_IPV4; + break; + case htons(ETH_P_IPV6): +- wx_get_ipv6_proto(skb, skb_network_offset(skb), &tun_prot); ++ l4_hdr = skb_transport_header(skb); ++ exthdr = skb_network_header(skb) + sizeof(struct ipv6hdr); ++ tun_prot = ipv6_hdr(skb)->nexthdr; ++ if (l4_hdr != exthdr) ++ ipv6_skip_exthdr(skb, exthdr - skb->data, &tun_prot, &frag_off); + ptype = WX_PTYPE_TUN_IPV6; + break; + default: + return ptype; + } + +- if (tun_prot == IPPROTO_IPIP) { ++ if (tun_prot == IPPROTO_IPIP || tun_prot == IPPROTO_IPV6) { + hdr.raw = (void *)inner_ip_hdr(skb); + ptype |= WX_PTYPE_PKT_IPIP; + } else if (tun_prot == IPPROTO_UDP) { +@@ -1166,7 +1152,11 @@ static u8 wx_encode_tx_desc_ptype(const struct wx_tx_buffer *first) + l4_prot = hdr.ipv4->protocol; + break; + case 6: +- wx_get_ipv6_proto(skb, skb_inner_network_offset(skb), &l4_prot); ++ l4_hdr = skb_inner_transport_header(skb); ++ exthdr = skb_inner_network_header(skb) + sizeof(struct ipv6hdr); ++ l4_prot = inner_ipv6_hdr(skb)->nexthdr; ++ if (l4_hdr != exthdr) ++ ipv6_skip_exthdr(skb, exthdr - skb->data, &l4_prot, &frag_off); + ptype |= WX_PTYPE_PKT_IPV6; + break; + default: +@@ -1179,7 +1169,11 @@ static u8 wx_encode_tx_desc_ptype(const struct wx_tx_buffer *first) + ptype = WX_PTYPE_PKT_IP; + break; + case htons(ETH_P_IPV6): +- wx_get_ipv6_proto(skb, skb_network_offset(skb), &l4_prot); ++ l4_hdr = skb_transport_header(skb); ++ exthdr = skb_network_header(skb) + sizeof(struct ipv6hdr); ++ l4_prot = ipv6_hdr(skb)->nexthdr; ++ if (l4_hdr != exthdr) ++ ipv6_skip_exthdr(skb, exthdr - skb->data, &l4_prot, &frag_off); + ptype = WX_PTYPE_PKT_IP | WX_PTYPE_PKT_IPV6; + break; + default: +@@ -1269,13 +1263,20 @@ static int wx_tso(struct wx_ring *tx_ring, struct wx_tx_buffer *first, + + /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */ + if (enc) { ++ unsigned char *exthdr, *l4_hdr; ++ __be16 frag_off; ++ + switch (first->protocol) { + case htons(ETH_P_IP): + tun_prot = ip_hdr(skb)->protocol; + first->tx_flags |= WX_TX_FLAGS_OUTER_IPV4; + break; + case htons(ETH_P_IPV6): ++ l4_hdr = skb_transport_header(skb); ++ exthdr = skb_network_header(skb) + sizeof(struct ipv6hdr); + tun_prot = ipv6_hdr(skb)->nexthdr; ++ if (l4_hdr != exthdr) ++ ipv6_skip_exthdr(skb, exthdr - skb->data, &tun_prot, &frag_off); + break; + default: + break; +@@ -1298,6 +1299,7 @@ static int wx_tso(struct wx_ring *tx_ring, struct wx_tx_buffer *first, + WX_TXD_TUNNEL_LEN_SHIFT); + break; + case IPPROTO_IPIP: ++ case IPPROTO_IPV6: + tunhdr_eiplen_tunlen = (((char *)inner_ip_hdr(skb) - + (char *)ip_hdr(skb)) >> 2) << + WX_TXD_OUTER_IPLEN_SHIFT; +@@ -1341,6 +1343,8 @@ static void wx_tx_csum(struct wx_ring *tx_ring, struct wx_tx_buffer *first, + vlan_macip_lens = skb_network_offset(skb) << + WX_TXD_MACLEN_SHIFT; + } else { ++ unsigned char *exthdr, *l4_hdr; ++ __be16 frag_off; + u8 l4_prot = 0; + union { + struct iphdr *ipv4; +@@ -1362,7 +1366,12 @@ static void wx_tx_csum(struct wx_ring *tx_ring, struct wx_tx_buffer *first, + tun_prot = ip_hdr(skb)->protocol; + break; + case htons(ETH_P_IPV6): ++ l4_hdr = skb_transport_header(skb); ++ exthdr = skb_network_header(skb) + sizeof(struct ipv6hdr); + tun_prot = ipv6_hdr(skb)->nexthdr; ++ if (l4_hdr != exthdr) ++ ipv6_skip_exthdr(skb, exthdr - skb->data, ++ &tun_prot, &frag_off); + break; + default: + return; +@@ -1386,6 +1395,7 @@ static void wx_tx_csum(struct wx_ring *tx_ring, struct wx_tx_buffer *first, + WX_TXD_TUNNEL_LEN_SHIFT); + break; + case IPPROTO_IPIP: ++ case IPPROTO_IPV6: + tunhdr_eiplen_tunlen = (((char *)inner_ip_hdr(skb) - + (char *)ip_hdr(skb)) >> 2) << + WX_TXD_OUTER_IPLEN_SHIFT; +@@ -1408,7 +1418,10 @@ static void wx_tx_csum(struct wx_ring *tx_ring, struct wx_tx_buffer *first, + break; + case 6: + vlan_macip_lens |= (transport_hdr.raw - network_hdr.raw) >> 1; ++ exthdr = network_hdr.raw + sizeof(struct ipv6hdr); + l4_prot = network_hdr.ipv6->nexthdr; ++ if (transport_hdr.raw != exthdr) ++ ipv6_skip_exthdr(skb, exthdr - skb->data, &l4_prot, &frag_off); + break; + default: + break; +-- +2.39.5 + diff --git a/queue-6.14/net-libwx-fix-tx-l4-checksum.patch b/queue-6.14/net-libwx-fix-tx-l4-checksum.patch new file mode 100644 index 0000000000..e0b27434ef --- /dev/null +++ b/queue-6.14/net-libwx-fix-tx-l4-checksum.patch @@ -0,0 +1,47 @@ +From bc72ff4f67cb0b0e876ff20777156bd12dd28888 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 18:32:35 +0800 +Subject: net: libwx: fix Tx L4 checksum + +From: Jiawen Wu + +[ Upstream commit c7d82913d5f9e97860772ee4051eaa66b56a6273 ] + +The hardware only supports L4 checksum offload for TCP/UDP/SCTP protocol. +There was a bug to set Tx checksum flag for the other protocol that results +in Tx ring hang. Fix to compute software checksum for these packets. + +Fixes: 3403960cdf86 ("net: wangxun: libwx add tx offload functions") +Signed-off-by: Jiawen Wu +Link: https://patch.msgid.link/20250324103235.823096-2-jiawenwu@trustnetic.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/wangxun/libwx/wx_lib.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c +index 9294a9d8c5541..497abf2723a5e 100644 +--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c ++++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c +@@ -1337,6 +1337,7 @@ static void wx_tx_csum(struct wx_ring *tx_ring, struct wx_tx_buffer *first, + u8 tun_prot = 0; + + if (skb->ip_summed != CHECKSUM_PARTIAL) { ++csum_failed: + if (!(first->tx_flags & WX_TX_FLAGS_HW_VLAN) && + !(first->tx_flags & WX_TX_FLAGS_CC)) + return; +@@ -1441,7 +1442,8 @@ static void wx_tx_csum(struct wx_ring *tx_ring, struct wx_tx_buffer *first, + WX_TXD_L4LEN_SHIFT; + break; + default: +- break; ++ skb_checksum_help(skb); ++ goto csum_failed; + } + + /* update TX checksum flag */ +-- +2.39.5 + diff --git a/queue-6.14/net-mlx5-lag-reload-representors-on-lag-creation-fai.patch b/queue-6.14/net-mlx5-lag-reload-representors-on-lag-creation-fai.patch new file mode 100644 index 0000000000..9675764409 --- /dev/null +++ b/queue-6.14/net-mlx5-lag-reload-representors-on-lag-creation-fai.patch @@ -0,0 +1,44 @@ +From c59f94be2341e84ce4c76200b9cde9e355e9d45f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 22:51:16 +0200 +Subject: net/mlx5: LAG, reload representors on LAG creation failure + +From: Mark Bloch + +[ Upstream commit bdf549a7a4d738838d50833168881a0b6247446a ] + +When LAG creation fails, the driver reloads the RDMA devices. If RDMA +representors are present, they should also be reloaded. This step was +missed in the cited commit. + +Fixes: 598fe77df855 ("net/mlx5: Lag, Create shared FDB when in switchdev mode") +Signed-off-by: Mark Bloch +Reviewed-by: Shay Drori +Signed-off-by: Tariq Toukan +Reviewed-by: Michal Swiatkowski +Reviewed-by: Kalesh AP +Link: https://patch.msgid.link/1742331077-102038-2-git-send-email-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +index ed2ba272946b9..6c9737c537348 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +@@ -1052,6 +1052,10 @@ static void mlx5_do_bond(struct mlx5_lag *ldev) + if (err) { + if (shared_fdb || roce_lag) + mlx5_lag_add_devices(ldev); ++ if (shared_fdb) { ++ mlx5_ldev_for_each(i, 0, ldev) ++ mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); ++ } + + return; + } else if (roce_lag) { +-- +2.39.5 + diff --git a/queue-6.14/net-mlx5-start-health-poll-after-enable-hca.patch b/queue-6.14/net-mlx5-start-health-poll-after-enable-hca.patch new file mode 100644 index 0000000000..f18b2ccacf --- /dev/null +++ b/queue-6.14/net-mlx5-start-health-poll-after-enable-hca.patch @@ -0,0 +1,87 @@ +From ff275d2935c9e0de5456d8b14da9f23455137b9b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 22:51:17 +0200 +Subject: net/mlx5: Start health poll after enable hca + +From: Moshe Shemesh + +[ Upstream commit 1726ad035cb0c93cc5c3f2227ec71322ccd7c2f8 ] + +The health poll mechanism performs periodic checks to detect firmware +errors. One of the checks verifies the function is still enabled on +firmware side, but the function is enabled only after enable_hca command +completed. Start health poll after enable_hca command to avoid a race +between function enabled and first health polling. + +Fixes: 9b98d395b85d ("net/mlx5: Start health poll at earlier stage of driver load") +Signed-off-by: Moshe Shemesh +Reviewed-by: Shay Drori +Signed-off-by: Tariq Toukan +Reviewed-by: Michal Swiatkowski +Reviewed-by: Kalesh AP +Link: https://patch.msgid.link/1742331077-102038-3-git-send-email-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/main.c | 15 +++++++-------- + 1 file changed, 7 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c +index ec956c4bcebdb..7c3312d6aed9b 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -1205,24 +1205,24 @@ static int mlx5_function_enable(struct mlx5_core_dev *dev, bool boot, u64 timeou + dev->caps.embedded_cpu = mlx5_read_embedded_cpu(dev); + mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_UP); + +- mlx5_start_health_poll(dev); +- + err = mlx5_core_enable_hca(dev, 0); + if (err) { + mlx5_core_err(dev, "enable hca failed\n"); +- goto stop_health_poll; ++ goto err_cmd_cleanup; + } + ++ mlx5_start_health_poll(dev); ++ + err = mlx5_core_set_issi(dev); + if (err) { + mlx5_core_err(dev, "failed to set issi\n"); +- goto err_disable_hca; ++ goto stop_health_poll; + } + + err = mlx5_satisfy_startup_pages(dev, 1); + if (err) { + mlx5_core_err(dev, "failed to allocate boot pages\n"); +- goto err_disable_hca; ++ goto stop_health_poll; + } + + err = mlx5_tout_query_dtor(dev); +@@ -1235,10 +1235,9 @@ static int mlx5_function_enable(struct mlx5_core_dev *dev, bool boot, u64 timeou + + reclaim_boot_pages: + mlx5_reclaim_startup_pages(dev); +-err_disable_hca: +- mlx5_core_disable_hca(dev, 0); + stop_health_poll: + mlx5_stop_health_poll(dev, boot); ++ mlx5_core_disable_hca(dev, 0); + err_cmd_cleanup: + mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN); + mlx5_cmd_disable(dev); +@@ -1249,8 +1248,8 @@ static int mlx5_function_enable(struct mlx5_core_dev *dev, bool boot, u64 timeou + static void mlx5_function_disable(struct mlx5_core_dev *dev, bool boot) + { + mlx5_reclaim_startup_pages(dev); +- mlx5_core_disable_hca(dev, 0); + mlx5_stop_health_poll(dev, boot); ++ mlx5_core_disable_hca(dev, 0); + mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN); + mlx5_cmd_disable(dev); + } +-- +2.39.5 + diff --git a/queue-6.14/net-mlx5e-fix-ethtool-n-flow-type-ip4-to-rss-context.patch b/queue-6.14/net-mlx5e-fix-ethtool-n-flow-type-ip4-to-rss-context.patch new file mode 100644 index 0000000000..bc3261751b --- /dev/null +++ b/queue-6.14/net-mlx5e-fix-ethtool-n-flow-type-ip4-to-rss-context.patch @@ -0,0 +1,71 @@ +From ae678e481c00f2aad3ad6e4fe4ce09860f76c752 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 14:45:08 +0200 +Subject: net/mlx5e: Fix ethtool -N flow-type ip4 to RSS context + +From: Maxim Mikityanskiy + +[ Upstream commit 3865bec60683b86d39a5d8d6c34a1d269adaa84c ] + +There commands can be used to add an RSS context and steer some traffic +into it: + + # ethtool -X eth0 context new + New RSS context is 1 + # ethtool -N eth0 flow-type ip4 dst-ip 1.1.1.1 context 1 + Added rule with ID 1023 + +However, the second command fails with EINVAL on mlx5e: + + # ethtool -N eth0 flow-type ip4 dst-ip 1.1.1.1 context 1 + rmgr: Cannot insert RX class rule: Invalid argument + Cannot insert classification rule + +It happens when flow_get_tirn calls flow_type_to_traffic_type with +flow_type = IP_USER_FLOW or IPV6_USER_FLOW. That function only handles +IPV4_FLOW and IPV6_FLOW cases, but unlike all other cases which are +common for hash and spec, IPv4 and IPv6 defines different contants for +hash and for spec: + + #define TCP_V4_FLOW 0x01 /* hash or spec (tcp_ip4_spec) */ + #define UDP_V4_FLOW 0x02 /* hash or spec (udp_ip4_spec) */ + ... + #define IPV4_USER_FLOW 0x0d /* spec only (usr_ip4_spec) */ + #define IP_USER_FLOW IPV4_USER_FLOW + #define IPV6_USER_FLOW 0x0e /* spec only (usr_ip6_spec; nfc only) */ + #define IPV4_FLOW 0x10 /* hash only */ + #define IPV6_FLOW 0x11 /* hash only */ + +Extend the switch in flow_type_to_traffic_type to support both, which +fixes the failing ethtool -N command with flow-type ip4 or ip6. + +Fixes: 248d3b4c9a39 ("net/mlx5e: Support flow classification into RSS contexts") +Signed-off-by: Maxim Mikityanskiy +Tested-by: Daniel Borkmann +Reviewed-by: Joe Damato +Reviewed-by: Tariq Toukan +Link: https://patch.msgid.link/20250319124508.3979818-1-maxim@isovalent.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c +index 773624bb2c5d5..d68230a7b9f46 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c +@@ -884,8 +884,10 @@ static int flow_type_to_traffic_type(u32 flow_type) + case ESP_V6_FLOW: + return MLX5_TT_IPV6_IPSEC_ESP; + case IPV4_FLOW: ++ case IP_USER_FLOW: + return MLX5_TT_IPV4; + case IPV6_FLOW: ++ case IPV6_USER_FLOW: + return MLX5_TT_IPV6; + default: + return -EINVAL; +-- +2.39.5 + diff --git a/queue-6.14/net-mlx5e-shampo-make-reserved-size-independent-of-p.patch b/queue-6.14/net-mlx5e-shampo-make-reserved-size-independent-of-p.patch new file mode 100644 index 0000000000..bc5c4e0d5c --- /dev/null +++ b/queue-6.14/net-mlx5e-shampo-make-reserved-size-independent-of-p.patch @@ -0,0 +1,77 @@ +From b6d0b42c317e4bc31a3375aa766706dfe574792a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 23 Mar 2025 14:28:26 +0200 +Subject: net/mlx5e: SHAMPO, Make reserved size independent of page size + +From: Lama Kayal + +[ Upstream commit fab05835688526f9de123d1e98e4d1f838da4e22 ] + +When hw-gro is enabled, the maximum number of header entries that are +needed per wqe (hd_per_wqe) is calculated based on the size of the +reservations among other parameters. + +Miscalculation of the size of reservations leads to incorrect +calculation of hd_per_wqe as 0, particularly in the case of large page +size like in aarch64, this prevents the SHAMPO header from being +correctly initialized in the device, ultimately causing the following +cqe err that indicates a violation of PD. + + mlx5_core 0000:00:08.0 eth2: ERR CQE on RQ: 0x1180 + mlx5_core 0000:00:08.0 eth2: Error cqe on cqn 0x510, ci 0x0, qn 0x1180, opcode 0xe, syndrome 0x4, vendor syndrome 0x32 + 00000000: 00 00 00 00 04 4a 00 00 00 00 00 00 20 00 93 32 + 00000010: 55 00 00 00 fb cc 00 00 00 00 00 00 07 18 00 00 + 00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4a + 00000030: 00 00 00 9a 93 00 32 04 00 00 00 00 00 00 da e1 + +Use the correct formula for calculating the size of reservations, +precisely it shouldn't be dependent on page size, instead use the +correct multiply of MLX5E_SHAMPO_WQ_BASE_RESRV_SIZE. + +Fixes: e5ca8fb08ab2 ("net/mlx5e: Add control path for SHAMPO feature") +Signed-off-by: Lama Kayal +Reviewed-by: Dragos Tatulea +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1742732906-166564-1-git-send-email-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en/params.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +index 64b62ed17b07a..31eb99f09c63c 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +@@ -423,7 +423,7 @@ u8 mlx5e_shampo_get_log_pkt_per_rsrv(struct mlx5_core_dev *mdev, + struct mlx5e_params *params) + { + u32 resrv_size = BIT(mlx5e_shampo_get_log_rsrv_size(mdev, params)) * +- PAGE_SIZE; ++ MLX5E_SHAMPO_WQ_BASE_RESRV_SIZE; + + return order_base_2(DIV_ROUND_UP(resrv_size, params->sw_mtu)); + } +@@ -827,7 +827,8 @@ static u32 mlx5e_shampo_get_log_cq_size(struct mlx5_core_dev *mdev, + struct mlx5e_params *params, + struct mlx5e_xsk_param *xsk) + { +- int rsrv_size = BIT(mlx5e_shampo_get_log_rsrv_size(mdev, params)) * PAGE_SIZE; ++ int rsrv_size = BIT(mlx5e_shampo_get_log_rsrv_size(mdev, params)) * ++ MLX5E_SHAMPO_WQ_BASE_RESRV_SIZE; + u16 num_strides = BIT(mlx5e_mpwqe_get_log_num_strides(mdev, params, xsk)); + int pkt_per_rsrv = BIT(mlx5e_shampo_get_log_pkt_per_rsrv(mdev, params)); + u8 log_stride_sz = mlx5e_mpwqe_get_log_stride_size(mdev, params, xsk); +@@ -1036,7 +1037,8 @@ u32 mlx5e_shampo_hd_per_wqe(struct mlx5_core_dev *mdev, + struct mlx5e_params *params, + struct mlx5e_rq_param *rq_param) + { +- int resv_size = BIT(mlx5e_shampo_get_log_rsrv_size(mdev, params)) * PAGE_SIZE; ++ int resv_size = BIT(mlx5e_shampo_get_log_rsrv_size(mdev, params)) * ++ MLX5E_SHAMPO_WQ_BASE_RESRV_SIZE; + u16 num_strides = BIT(mlx5e_mpwqe_get_log_num_strides(mdev, params, NULL)); + int pkt_per_resv = BIT(mlx5e_shampo_get_log_pkt_per_rsrv(mdev, params)); + u8 log_stride_sz = mlx5e_mpwqe_get_log_stride_size(mdev, params, NULL); +-- +2.39.5 + diff --git a/queue-6.14/net-mvpp2-prevent-parser-tcam-memory-corruption.patch b/queue-6.14/net-mvpp2-prevent-parser-tcam-memory-corruption.patch new file mode 100644 index 0000000000..6e1c4fddd4 --- /dev/null +++ b/queue-6.14/net-mvpp2-prevent-parser-tcam-memory-corruption.patch @@ -0,0 +1,659 @@ +From 7f5a28b049a23ef58066a4b1e26c359d2eb007c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Apr 2025 08:58:04 +0200 +Subject: net: mvpp2: Prevent parser TCAM memory corruption + +From: Tobias Waldekranz + +[ Upstream commit 96844075226b49af25a69a1d084b648ec2d9b08d ] + +Protect the parser TCAM/SRAM memory, and the cached (shadow) SRAM +information, from concurrent modifications. + +Both the TCAM and SRAM tables are indirectly accessed by configuring +an index register that selects the row to read or write to. This means +that operations must be atomic in order to, e.g., avoid spreading +writes across multiple rows. Since the shadow SRAM array is used to +find free rows in the hardware table, it must also be protected in +order to avoid TOCTOU errors where multiple cores allocate the same +row. + +This issue was detected in a situation where `mvpp2_set_rx_mode()` ran +concurrently on two CPUs. In this particular case the +MVPP2_PE_MAC_UC_PROMISCUOUS entry was corrupted, causing the +classifier unit to drop all incoming unicast - indicated by the +`rx_classifier_drops` counter. + +Fixes: 3f518509dedc ("ethernet: Add new driver for Marvell Armada 375 network unit") +Signed-off-by: Tobias Waldekranz +Reviewed-by: Maxime Chevallier +Tested-by: Maxime Chevallier +Link: https://patch.msgid.link/20250401065855.3113635-1-tobias@waldekranz.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 3 + + .../net/ethernet/marvell/mvpp2/mvpp2_main.c | 3 +- + .../net/ethernet/marvell/mvpp2/mvpp2_prs.c | 201 ++++++++++++------ + 3 files changed, 140 insertions(+), 67 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +index 44fe9b68d1c22..061fcd444d503 100644 +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +@@ -1113,6 +1113,9 @@ struct mvpp2 { + + /* Spinlocks for CM3 shared memory configuration */ + spinlock_t mss_spinlock; ++ ++ /* Spinlock for shared PRS parser memory and shadow table */ ++ spinlock_t prs_spinlock; + }; + + struct mvpp2_pcpu_stats { +diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +index dd76c1b7ed3a1..c63e5f1b168a9 100644 +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +@@ -7722,8 +7722,9 @@ static int mvpp2_probe(struct platform_device *pdev) + if (mvpp2_read(priv, MVPP2_VER_ID_REG) == MVPP2_VER_PP23) + priv->hw_version = MVPP23; + +- /* Init mss lock */ ++ /* Init locks for shared packet processor resources */ + spin_lock_init(&priv->mss_spinlock); ++ spin_lock_init(&priv->prs_spinlock); + + /* Initialize network controller */ + err = mvpp2_init(pdev, priv); +diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c +index 9af22f497a40f..93e978bdf303c 100644 +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c +@@ -23,6 +23,8 @@ static int mvpp2_prs_hw_write(struct mvpp2 *priv, struct mvpp2_prs_entry *pe) + { + int i; + ++ lockdep_assert_held(&priv->prs_spinlock); ++ + if (pe->index > MVPP2_PRS_TCAM_SRAM_SIZE - 1) + return -EINVAL; + +@@ -43,11 +45,13 @@ static int mvpp2_prs_hw_write(struct mvpp2 *priv, struct mvpp2_prs_entry *pe) + } + + /* Initialize tcam entry from hw */ +-int mvpp2_prs_init_from_hw(struct mvpp2 *priv, struct mvpp2_prs_entry *pe, +- int tid) ++static int __mvpp2_prs_init_from_hw(struct mvpp2 *priv, ++ struct mvpp2_prs_entry *pe, int tid) + { + int i; + ++ lockdep_assert_held(&priv->prs_spinlock); ++ + if (tid > MVPP2_PRS_TCAM_SRAM_SIZE - 1) + return -EINVAL; + +@@ -73,6 +77,18 @@ int mvpp2_prs_init_from_hw(struct mvpp2 *priv, struct mvpp2_prs_entry *pe, + return 0; + } + ++int mvpp2_prs_init_from_hw(struct mvpp2 *priv, struct mvpp2_prs_entry *pe, ++ int tid) ++{ ++ int err; ++ ++ spin_lock_bh(&priv->prs_spinlock); ++ err = __mvpp2_prs_init_from_hw(priv, pe, tid); ++ spin_unlock_bh(&priv->prs_spinlock); ++ ++ return err; ++} ++ + /* Invalidate tcam hw entry */ + static void mvpp2_prs_hw_inv(struct mvpp2 *priv, int index) + { +@@ -374,7 +390,7 @@ static int mvpp2_prs_flow_find(struct mvpp2 *priv, int flow) + priv->prs_shadow[tid].lu != MVPP2_PRS_LU_FLOWS) + continue; + +- mvpp2_prs_init_from_hw(priv, &pe, tid); ++ __mvpp2_prs_init_from_hw(priv, &pe, tid); + bits = mvpp2_prs_sram_ai_get(&pe); + + /* Sram store classification lookup ID in AI bits [5:0] */ +@@ -441,7 +457,7 @@ static void mvpp2_prs_mac_drop_all_set(struct mvpp2 *priv, int port, bool add) + + if (priv->prs_shadow[MVPP2_PE_DROP_ALL].valid) { + /* Entry exist - update port only */ +- mvpp2_prs_init_from_hw(priv, &pe, MVPP2_PE_DROP_ALL); ++ __mvpp2_prs_init_from_hw(priv, &pe, MVPP2_PE_DROP_ALL); + } else { + /* Entry doesn't exist - create new */ + memset(&pe, 0, sizeof(pe)); +@@ -469,14 +485,17 @@ static void mvpp2_prs_mac_drop_all_set(struct mvpp2 *priv, int port, bool add) + } + + /* Set port to unicast or multicast promiscuous mode */ +-void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port, +- enum mvpp2_prs_l2_cast l2_cast, bool add) ++static void __mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port, ++ enum mvpp2_prs_l2_cast l2_cast, ++ bool add) + { + struct mvpp2_prs_entry pe; + unsigned char cast_match; + unsigned int ri; + int tid; + ++ lockdep_assert_held(&priv->prs_spinlock); ++ + if (l2_cast == MVPP2_PRS_L2_UNI_CAST) { + cast_match = MVPP2_PRS_UCAST_VAL; + tid = MVPP2_PE_MAC_UC_PROMISCUOUS; +@@ -489,7 +508,7 @@ void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port, + + /* promiscuous mode - Accept unknown unicast or multicast packets */ + if (priv->prs_shadow[tid].valid) { +- mvpp2_prs_init_from_hw(priv, &pe, tid); ++ __mvpp2_prs_init_from_hw(priv, &pe, tid); + } else { + memset(&pe, 0, sizeof(pe)); + mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC); +@@ -522,6 +541,14 @@ void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port, + mvpp2_prs_hw_write(priv, &pe); + } + ++void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port, ++ enum mvpp2_prs_l2_cast l2_cast, bool add) ++{ ++ spin_lock_bh(&priv->prs_spinlock); ++ __mvpp2_prs_mac_promisc_set(priv, port, l2_cast, add); ++ spin_unlock_bh(&priv->prs_spinlock); ++} ++ + /* Set entry for dsa packets */ + static void mvpp2_prs_dsa_tag_set(struct mvpp2 *priv, int port, bool add, + bool tagged, bool extend) +@@ -539,7 +566,7 @@ static void mvpp2_prs_dsa_tag_set(struct mvpp2 *priv, int port, bool add, + + if (priv->prs_shadow[tid].valid) { + /* Entry exist - update port only */ +- mvpp2_prs_init_from_hw(priv, &pe, tid); ++ __mvpp2_prs_init_from_hw(priv, &pe, tid); + } else { + /* Entry doesn't exist - create new */ + memset(&pe, 0, sizeof(pe)); +@@ -610,7 +637,7 @@ static void mvpp2_prs_dsa_tag_ethertype_set(struct mvpp2 *priv, int port, + + if (priv->prs_shadow[tid].valid) { + /* Entry exist - update port only */ +- mvpp2_prs_init_from_hw(priv, &pe, tid); ++ __mvpp2_prs_init_from_hw(priv, &pe, tid); + } else { + /* Entry doesn't exist - create new */ + memset(&pe, 0, sizeof(pe)); +@@ -673,7 +700,7 @@ static int mvpp2_prs_vlan_find(struct mvpp2 *priv, unsigned short tpid, int ai) + priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN) + continue; + +- mvpp2_prs_init_from_hw(priv, &pe, tid); ++ __mvpp2_prs_init_from_hw(priv, &pe, tid); + match = mvpp2_prs_tcam_data_cmp(&pe, 0, tpid); + if (!match) + continue; +@@ -726,7 +753,7 @@ static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai, + priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN) + continue; + +- mvpp2_prs_init_from_hw(priv, &pe, tid_aux); ++ __mvpp2_prs_init_from_hw(priv, &pe, tid_aux); + ri_bits = mvpp2_prs_sram_ri_get(&pe); + if ((ri_bits & MVPP2_PRS_RI_VLAN_MASK) == + MVPP2_PRS_RI_VLAN_DOUBLE) +@@ -760,7 +787,7 @@ static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai, + + mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VLAN); + } else { +- mvpp2_prs_init_from_hw(priv, &pe, tid); ++ __mvpp2_prs_init_from_hw(priv, &pe, tid); + } + /* Update ports' mask */ + mvpp2_prs_tcam_port_map_set(&pe, port_map); +@@ -800,7 +827,7 @@ static int mvpp2_prs_double_vlan_find(struct mvpp2 *priv, unsigned short tpid1, + priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN) + continue; + +- mvpp2_prs_init_from_hw(priv, &pe, tid); ++ __mvpp2_prs_init_from_hw(priv, &pe, tid); + + match = mvpp2_prs_tcam_data_cmp(&pe, 0, tpid1) && + mvpp2_prs_tcam_data_cmp(&pe, 4, tpid2); +@@ -849,7 +876,7 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1, + priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN) + continue; + +- mvpp2_prs_init_from_hw(priv, &pe, tid_aux); ++ __mvpp2_prs_init_from_hw(priv, &pe, tid_aux); + ri_bits = mvpp2_prs_sram_ri_get(&pe); + ri_bits &= MVPP2_PRS_RI_VLAN_MASK; + if (ri_bits == MVPP2_PRS_RI_VLAN_SINGLE || +@@ -880,7 +907,7 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1, + + mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VLAN); + } else { +- mvpp2_prs_init_from_hw(priv, &pe, tid); ++ __mvpp2_prs_init_from_hw(priv, &pe, tid); + } + + /* Update ports' mask */ +@@ -1213,8 +1240,8 @@ static void mvpp2_prs_mac_init(struct mvpp2 *priv) + /* Create dummy entries for drop all and promiscuous modes */ + mvpp2_prs_drop_fc(priv); + mvpp2_prs_mac_drop_all_set(priv, 0, false); +- mvpp2_prs_mac_promisc_set(priv, 0, MVPP2_PRS_L2_UNI_CAST, false); +- mvpp2_prs_mac_promisc_set(priv, 0, MVPP2_PRS_L2_MULTI_CAST, false); ++ __mvpp2_prs_mac_promisc_set(priv, 0, MVPP2_PRS_L2_UNI_CAST, false); ++ __mvpp2_prs_mac_promisc_set(priv, 0, MVPP2_PRS_L2_MULTI_CAST, false); + } + + /* Set default entries for various types of dsa packets */ +@@ -1533,12 +1560,6 @@ static int mvpp2_prs_vlan_init(struct platform_device *pdev, struct mvpp2 *priv) + struct mvpp2_prs_entry pe; + int err; + +- priv->prs_double_vlans = devm_kcalloc(&pdev->dev, sizeof(bool), +- MVPP2_PRS_DBL_VLANS_MAX, +- GFP_KERNEL); +- if (!priv->prs_double_vlans) +- return -ENOMEM; +- + /* Double VLAN: 0x88A8, 0x8100 */ + err = mvpp2_prs_double_vlan_add(priv, ETH_P_8021AD, ETH_P_8021Q, + MVPP2_PRS_PORT_MASK); +@@ -1941,7 +1962,7 @@ static int mvpp2_prs_vid_range_find(struct mvpp2_port *port, u16 vid, u16 mask) + port->priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VID) + continue; + +- mvpp2_prs_init_from_hw(port->priv, &pe, tid); ++ __mvpp2_prs_init_from_hw(port->priv, &pe, tid); + + mvpp2_prs_tcam_data_byte_get(&pe, 2, &byte[0], &enable[0]); + mvpp2_prs_tcam_data_byte_get(&pe, 3, &byte[1], &enable[1]); +@@ -1970,6 +1991,8 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid) + + memset(&pe, 0, sizeof(pe)); + ++ spin_lock_bh(&priv->prs_spinlock); ++ + /* Scan TCAM and see if entry with this already exist */ + tid = mvpp2_prs_vid_range_find(port, vid, mask); + +@@ -1988,8 +2011,10 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid) + MVPP2_PRS_VLAN_FILT_MAX_ENTRY); + + /* There isn't room for a new VID filter */ +- if (tid < 0) ++ if (tid < 0) { ++ spin_unlock_bh(&priv->prs_spinlock); + return tid; ++ } + + mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VID); + pe.index = tid; +@@ -1997,7 +2022,7 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid) + /* Mask all ports */ + mvpp2_prs_tcam_port_map_set(&pe, 0); + } else { +- mvpp2_prs_init_from_hw(priv, &pe, tid); ++ __mvpp2_prs_init_from_hw(priv, &pe, tid); + } + + /* Enable the current port */ +@@ -2019,6 +2044,7 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid) + mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VID); + mvpp2_prs_hw_write(priv, &pe); + ++ spin_unlock_bh(&priv->prs_spinlock); + return 0; + } + +@@ -2028,15 +2054,16 @@ void mvpp2_prs_vid_entry_remove(struct mvpp2_port *port, u16 vid) + struct mvpp2 *priv = port->priv; + int tid; + +- /* Scan TCAM and see if entry with this already exist */ +- tid = mvpp2_prs_vid_range_find(port, vid, 0xfff); ++ spin_lock_bh(&priv->prs_spinlock); + +- /* No such entry */ +- if (tid < 0) +- return; ++ /* Invalidate TCAM entry with this , if it exists */ ++ tid = mvpp2_prs_vid_range_find(port, vid, 0xfff); ++ if (tid >= 0) { ++ mvpp2_prs_hw_inv(priv, tid); ++ priv->prs_shadow[tid].valid = false; ++ } + +- mvpp2_prs_hw_inv(priv, tid); +- priv->prs_shadow[tid].valid = false; ++ spin_unlock_bh(&priv->prs_spinlock); + } + + /* Remove all existing VID filters on this port */ +@@ -2045,6 +2072,8 @@ void mvpp2_prs_vid_remove_all(struct mvpp2_port *port) + struct mvpp2 *priv = port->priv; + int tid; + ++ spin_lock_bh(&priv->prs_spinlock); ++ + for (tid = MVPP2_PRS_VID_PORT_FIRST(port->id); + tid <= MVPP2_PRS_VID_PORT_LAST(port->id); tid++) { + if (priv->prs_shadow[tid].valid) { +@@ -2052,6 +2081,8 @@ void mvpp2_prs_vid_remove_all(struct mvpp2_port *port) + priv->prs_shadow[tid].valid = false; + } + } ++ ++ spin_unlock_bh(&priv->prs_spinlock); + } + + /* Remove VID filering entry for this port */ +@@ -2060,10 +2091,14 @@ void mvpp2_prs_vid_disable_filtering(struct mvpp2_port *port) + unsigned int tid = MVPP2_PRS_VID_PORT_DFLT(port->id); + struct mvpp2 *priv = port->priv; + ++ spin_lock_bh(&priv->prs_spinlock); ++ + /* Invalidate the guard entry */ + mvpp2_prs_hw_inv(priv, tid); + + priv->prs_shadow[tid].valid = false; ++ ++ spin_unlock_bh(&priv->prs_spinlock); + } + + /* Add guard entry that drops packets when no VID is matched on this port */ +@@ -2079,6 +2114,8 @@ void mvpp2_prs_vid_enable_filtering(struct mvpp2_port *port) + + memset(&pe, 0, sizeof(pe)); + ++ spin_lock_bh(&priv->prs_spinlock); ++ + pe.index = tid; + + reg_val = mvpp2_read(priv, MVPP2_MH_REG(port->id)); +@@ -2111,6 +2148,8 @@ void mvpp2_prs_vid_enable_filtering(struct mvpp2_port *port) + /* Update shadow table */ + mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VID); + mvpp2_prs_hw_write(priv, &pe); ++ ++ spin_unlock_bh(&priv->prs_spinlock); + } + + /* Parser default initialization */ +@@ -2118,6 +2157,20 @@ int mvpp2_prs_default_init(struct platform_device *pdev, struct mvpp2 *priv) + { + int err, index, i; + ++ priv->prs_shadow = devm_kcalloc(&pdev->dev, MVPP2_PRS_TCAM_SRAM_SIZE, ++ sizeof(*priv->prs_shadow), ++ GFP_KERNEL); ++ if (!priv->prs_shadow) ++ return -ENOMEM; ++ ++ priv->prs_double_vlans = devm_kcalloc(&pdev->dev, sizeof(bool), ++ MVPP2_PRS_DBL_VLANS_MAX, ++ GFP_KERNEL); ++ if (!priv->prs_double_vlans) ++ return -ENOMEM; ++ ++ spin_lock_bh(&priv->prs_spinlock); ++ + /* Enable tcam table */ + mvpp2_write(priv, MVPP2_PRS_TCAM_CTRL_REG, MVPP2_PRS_TCAM_EN_MASK); + +@@ -2136,12 +2189,6 @@ int mvpp2_prs_default_init(struct platform_device *pdev, struct mvpp2 *priv) + for (index = 0; index < MVPP2_PRS_TCAM_SRAM_SIZE; index++) + mvpp2_prs_hw_inv(priv, index); + +- priv->prs_shadow = devm_kcalloc(&pdev->dev, MVPP2_PRS_TCAM_SRAM_SIZE, +- sizeof(*priv->prs_shadow), +- GFP_KERNEL); +- if (!priv->prs_shadow) +- return -ENOMEM; +- + /* Always start from lookup = 0 */ + for (index = 0; index < MVPP2_MAX_PORTS; index++) + mvpp2_prs_hw_port_init(priv, index, MVPP2_PRS_LU_MH, +@@ -2158,26 +2205,13 @@ int mvpp2_prs_default_init(struct platform_device *pdev, struct mvpp2 *priv) + mvpp2_prs_vid_init(priv); + + err = mvpp2_prs_etype_init(priv); +- if (err) +- return err; +- +- err = mvpp2_prs_vlan_init(pdev, priv); +- if (err) +- return err; +- +- err = mvpp2_prs_pppoe_init(priv); +- if (err) +- return err; +- +- err = mvpp2_prs_ip6_init(priv); +- if (err) +- return err; +- +- err = mvpp2_prs_ip4_init(priv); +- if (err) +- return err; ++ err = err ? : mvpp2_prs_vlan_init(pdev, priv); ++ err = err ? : mvpp2_prs_pppoe_init(priv); ++ err = err ? : mvpp2_prs_ip6_init(priv); ++ err = err ? : mvpp2_prs_ip4_init(priv); + +- return 0; ++ spin_unlock_bh(&priv->prs_spinlock); ++ return err; + } + + /* Compare MAC DA with tcam entry data */ +@@ -2217,7 +2251,7 @@ mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da, + (priv->prs_shadow[tid].udf != udf_type)) + continue; + +- mvpp2_prs_init_from_hw(priv, &pe, tid); ++ __mvpp2_prs_init_from_hw(priv, &pe, tid); + entry_pmap = mvpp2_prs_tcam_port_map_get(&pe); + + if (mvpp2_prs_mac_range_equals(&pe, da, mask) && +@@ -2229,7 +2263,8 @@ mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da, + } + + /* Update parser's mac da entry */ +-int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da, bool add) ++static int __mvpp2_prs_mac_da_accept(struct mvpp2_port *port, ++ const u8 *da, bool add) + { + unsigned char mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + struct mvpp2 *priv = port->priv; +@@ -2261,7 +2296,7 @@ int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da, bool add) + /* Mask all ports */ + mvpp2_prs_tcam_port_map_set(&pe, 0); + } else { +- mvpp2_prs_init_from_hw(priv, &pe, tid); ++ __mvpp2_prs_init_from_hw(priv, &pe, tid); + } + + mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC); +@@ -2317,6 +2352,17 @@ int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da, bool add) + return 0; + } + ++int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da, bool add) ++{ ++ int err; ++ ++ spin_lock_bh(&port->priv->prs_spinlock); ++ err = __mvpp2_prs_mac_da_accept(port, da, add); ++ spin_unlock_bh(&port->priv->prs_spinlock); ++ ++ return err; ++} ++ + int mvpp2_prs_update_mac_da(struct net_device *dev, const u8 *da) + { + struct mvpp2_port *port = netdev_priv(dev); +@@ -2345,6 +2391,8 @@ void mvpp2_prs_mac_del_all(struct mvpp2_port *port) + unsigned long pmap; + int index, tid; + ++ spin_lock_bh(&priv->prs_spinlock); ++ + for (tid = MVPP2_PE_MAC_RANGE_START; + tid <= MVPP2_PE_MAC_RANGE_END; tid++) { + unsigned char da[ETH_ALEN], da_mask[ETH_ALEN]; +@@ -2354,7 +2402,7 @@ void mvpp2_prs_mac_del_all(struct mvpp2_port *port) + (priv->prs_shadow[tid].udf != MVPP2_PRS_UDF_MAC_DEF)) + continue; + +- mvpp2_prs_init_from_hw(priv, &pe, tid); ++ __mvpp2_prs_init_from_hw(priv, &pe, tid); + + pmap = mvpp2_prs_tcam_port_map_get(&pe); + +@@ -2375,14 +2423,17 @@ void mvpp2_prs_mac_del_all(struct mvpp2_port *port) + continue; + + /* Remove entry from TCAM */ +- mvpp2_prs_mac_da_accept(port, da, false); ++ __mvpp2_prs_mac_da_accept(port, da, false); + } ++ ++ spin_unlock_bh(&priv->prs_spinlock); + } + + int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type) + { + switch (type) { + case MVPP2_TAG_TYPE_EDSA: ++ spin_lock_bh(&priv->prs_spinlock); + /* Add port to EDSA entries */ + mvpp2_prs_dsa_tag_set(priv, port, true, + MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA); +@@ -2393,9 +2444,11 @@ int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type) + MVPP2_PRS_TAGGED, MVPP2_PRS_DSA); + mvpp2_prs_dsa_tag_set(priv, port, false, + MVPP2_PRS_UNTAGGED, MVPP2_PRS_DSA); ++ spin_unlock_bh(&priv->prs_spinlock); + break; + + case MVPP2_TAG_TYPE_DSA: ++ spin_lock_bh(&priv->prs_spinlock); + /* Add port to DSA entries */ + mvpp2_prs_dsa_tag_set(priv, port, true, + MVPP2_PRS_TAGGED, MVPP2_PRS_DSA); +@@ -2406,10 +2459,12 @@ int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type) + MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA); + mvpp2_prs_dsa_tag_set(priv, port, false, + MVPP2_PRS_UNTAGGED, MVPP2_PRS_EDSA); ++ spin_unlock_bh(&priv->prs_spinlock); + break; + + case MVPP2_TAG_TYPE_MH: + case MVPP2_TAG_TYPE_NONE: ++ spin_lock_bh(&priv->prs_spinlock); + /* Remove port form EDSA and DSA entries */ + mvpp2_prs_dsa_tag_set(priv, port, false, + MVPP2_PRS_TAGGED, MVPP2_PRS_DSA); +@@ -2419,6 +2474,7 @@ int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type) + MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA); + mvpp2_prs_dsa_tag_set(priv, port, false, + MVPP2_PRS_UNTAGGED, MVPP2_PRS_EDSA); ++ spin_unlock_bh(&priv->prs_spinlock); + break; + + default: +@@ -2437,11 +2493,15 @@ int mvpp2_prs_add_flow(struct mvpp2 *priv, int flow, u32 ri, u32 ri_mask) + + memset(&pe, 0, sizeof(pe)); + ++ spin_lock_bh(&priv->prs_spinlock); ++ + tid = mvpp2_prs_tcam_first_free(priv, + MVPP2_PE_LAST_FREE_TID, + MVPP2_PE_FIRST_FREE_TID); +- if (tid < 0) ++ if (tid < 0) { ++ spin_unlock_bh(&priv->prs_spinlock); + return tid; ++ } + + pe.index = tid; + +@@ -2461,6 +2521,7 @@ int mvpp2_prs_add_flow(struct mvpp2 *priv, int flow, u32 ri, u32 ri_mask) + mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK); + mvpp2_prs_hw_write(priv, &pe); + ++ spin_unlock_bh(&priv->prs_spinlock); + return 0; + } + +@@ -2472,6 +2533,8 @@ int mvpp2_prs_def_flow(struct mvpp2_port *port) + + memset(&pe, 0, sizeof(pe)); + ++ spin_lock_bh(&port->priv->prs_spinlock); ++ + tid = mvpp2_prs_flow_find(port->priv, port->id); + + /* Such entry not exist */ +@@ -2480,8 +2543,10 @@ int mvpp2_prs_def_flow(struct mvpp2_port *port) + tid = mvpp2_prs_tcam_first_free(port->priv, + MVPP2_PE_LAST_FREE_TID, + MVPP2_PE_FIRST_FREE_TID); +- if (tid < 0) ++ if (tid < 0) { ++ spin_unlock_bh(&port->priv->prs_spinlock); + return tid; ++ } + + pe.index = tid; + +@@ -2492,13 +2557,14 @@ int mvpp2_prs_def_flow(struct mvpp2_port *port) + /* Update shadow table */ + mvpp2_prs_shadow_set(port->priv, pe.index, MVPP2_PRS_LU_FLOWS); + } else { +- mvpp2_prs_init_from_hw(port->priv, &pe, tid); ++ __mvpp2_prs_init_from_hw(port->priv, &pe, tid); + } + + mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_FLOWS); + mvpp2_prs_tcam_port_map_set(&pe, (1 << port->id)); + mvpp2_prs_hw_write(port->priv, &pe); + ++ spin_unlock_bh(&port->priv->prs_spinlock); + return 0; + } + +@@ -2509,11 +2575,14 @@ int mvpp2_prs_hits(struct mvpp2 *priv, int index) + if (index > MVPP2_PRS_TCAM_SRAM_SIZE) + return -EINVAL; + ++ spin_lock_bh(&priv->prs_spinlock); ++ + mvpp2_write(priv, MVPP2_PRS_TCAM_HIT_IDX_REG, index); + + val = mvpp2_read(priv, MVPP2_PRS_TCAM_HIT_CNT_REG); + + val &= MVPP2_PRS_TCAM_HIT_CNT_MASK; + ++ spin_unlock_bh(&priv->prs_spinlock); + return val; + } +-- +2.39.5 + diff --git a/queue-6.14/net-phy-broadcom-correct-bcm5221-phy-model-detection.patch b/queue-6.14/net-phy-broadcom-correct-bcm5221-phy-model-detection.patch new file mode 100644 index 0000000000..63caa844e1 --- /dev/null +++ b/queue-6.14/net-phy-broadcom-correct-bcm5221-phy-model-detection.patch @@ -0,0 +1,55 @@ +From 0354ffe21f51a4fd8eef7d6f58c6d60d0afb9119 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Mar 2025 14:29:42 +0800 +Subject: net: phy: broadcom: Correct BCM5221 PHY model detection + +From: Jim Liu + +[ Upstream commit 4f1eaabb4b66a1f7473f584e14e15b2ac19dfaf3 ] + +Correct detect condition is applied to the entire 5221 family of PHYs. + +Fixes: 3abbd0699b67 ("net: phy: broadcom: add support for BCM5221 phy") +Signed-off-by: Jim Liu +Reviewed-by: Michal Swiatkowski +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/phy/broadcom.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c +index 22edb7e4c1a1f..5a963b2b7ea78 100644 +--- a/drivers/net/phy/broadcom.c ++++ b/drivers/net/phy/broadcom.c +@@ -859,7 +859,7 @@ static int brcm_fet_config_init(struct phy_device *phydev) + return reg; + + /* Unmask events we are interested in and mask interrupts globally. */ +- if (phydev->phy_id == PHY_ID_BCM5221) ++ if (phydev->drv->phy_id == PHY_ID_BCM5221) + reg = MII_BRCM_FET_IR_ENABLE | + MII_BRCM_FET_IR_MASK; + else +@@ -888,7 +888,7 @@ static int brcm_fet_config_init(struct phy_device *phydev) + return err; + } + +- if (phydev->phy_id != PHY_ID_BCM5221) { ++ if (phydev->drv->phy_id != PHY_ID_BCM5221) { + /* Set the LED mode */ + reg = __phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4); + if (reg < 0) { +@@ -1009,7 +1009,7 @@ static int brcm_fet_suspend(struct phy_device *phydev) + return err; + } + +- if (phydev->phy_id == PHY_ID_BCM5221) ++ if (phydev->drv->phy_id == PHY_ID_BCM5221) + /* Force Low Power Mode with clock enabled */ + reg = BCM5221_SHDW_AM4_EN_CLK_LPM | BCM5221_SHDW_AM4_FORCE_LPM; + else +-- +2.39.5 + diff --git a/queue-6.14/net-remove-rtnl-dance-for-siocbraddif-and-siocbrdeli.patch b/queue-6.14/net-remove-rtnl-dance-for-siocbraddif-and-siocbrdeli.patch new file mode 100644 index 0000000000..42924a4696 --- /dev/null +++ b/queue-6.14/net-remove-rtnl-dance-for-siocbraddif-and-siocbrdeli.patch @@ -0,0 +1,311 @@ +From 9e9fa9d0fac08b4795d41b3213c752dbc089df89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Mar 2025 12:28:37 -0700 +Subject: net: Remove RTNL dance for SIOCBRADDIF and SIOCBRDELIF. + +From: Kuniyuki Iwashima + +[ Upstream commit ed3ba9b6e280e14cc3148c1b226ba453f02fa76c ] + +SIOCBRDELIF is passed to dev_ioctl() first and later forwarded to +br_ioctl_call(), which causes unnecessary RTNL dance and the splat +below [0] under RTNL pressure. + +Let's say Thread A is trying to detach a device from a bridge and +Thread B is trying to remove the bridge. + +In dev_ioctl(), Thread A bumps the bridge device's refcnt by +netdev_hold() and releases RTNL because the following br_ioctl_call() +also re-acquires RTNL. + +In the race window, Thread B could acquire RTNL and try to remove +the bridge device. Then, rtnl_unlock() by Thread B will release RTNL +and wait for netdev_put() by Thread A. + +Thread A, however, must hold RTNL after the unlock in dev_ifsioc(), +which may take long under RTNL pressure, resulting in the splat by +Thread B. + + Thread A (SIOCBRDELIF) Thread B (SIOCBRDELBR) + ---------------------- ---------------------- + sock_ioctl sock_ioctl + `- sock_do_ioctl `- br_ioctl_call + `- dev_ioctl `- br_ioctl_stub + |- rtnl_lock | + |- dev_ifsioc ' + ' |- dev = __dev_get_by_name(...) + |- netdev_hold(dev, ...) . + / |- rtnl_unlock ------. | + | |- br_ioctl_call `---> |- rtnl_lock + Race | | `- br_ioctl_stub |- br_del_bridge + Window | | | |- dev = __dev_get_by_name(...) + | | | May take long | `- br_dev_delete(dev, ...) + | | | under RTNL pressure | `- unregister_netdevice_queue(dev, ...) + | | | | `- rtnl_unlock + \ | |- rtnl_lock <-' `- netdev_run_todo + | |- ... `- netdev_run_todo + | `- rtnl_unlock |- __rtnl_unlock + | |- netdev_wait_allrefs_any + |- netdev_put(dev, ...) <----------------' + Wait refcnt decrement + and log splat below + +To avoid blocking SIOCBRDELBR unnecessarily, let's not call +dev_ioctl() for SIOCBRADDIF and SIOCBRDELIF. + +In the dev_ioctl() path, we do the following: + + 1. Copy struct ifreq by get_user_ifreq in sock_do_ioctl() + 2. Check CAP_NET_ADMIN in dev_ioctl() + 3. Call dev_load() in dev_ioctl() + 4. Fetch the master dev from ifr.ifr_name in dev_ifsioc() + +3. can be done by request_module() in br_ioctl_call(), so we move +1., 2., and 4. to br_ioctl_stub(). + +Note that 2. is also checked later in add_del_if(), but it's better +performed before RTNL. + +SIOCBRADDIF and SIOCBRDELIF have been processed in dev_ioctl() since +the pre-git era, and there seems to be no specific reason to process +them there. + +[0]: +unregister_netdevice: waiting for wpan3 to become free. Usage count = 2 +ref_tracker: wpan3@ffff8880662d8608 has 1/1 users at + __netdev_tracker_alloc include/linux/netdevice.h:4282 [inline] + netdev_hold include/linux/netdevice.h:4311 [inline] + dev_ifsioc+0xc6a/0x1160 net/core/dev_ioctl.c:624 + dev_ioctl+0x255/0x10c0 net/core/dev_ioctl.c:826 + sock_do_ioctl+0x1ca/0x260 net/socket.c:1213 + sock_ioctl+0x23a/0x6c0 net/socket.c:1318 + vfs_ioctl fs/ioctl.c:51 [inline] + __do_sys_ioctl fs/ioctl.c:906 [inline] + __se_sys_ioctl fs/ioctl.c:892 [inline] + __x64_sys_ioctl+0x1a4/0x210 fs/ioctl.c:892 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xcb/0x250 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Fixes: 893b19587534 ("net: bridge: fix ioctl locking") +Reported-by: syzkaller +Reported-by: yan kang +Reported-by: yue sun +Closes: https://lore.kernel.org/netdev/SY8P300MB0421225D54EB92762AE8F0F2A1D32@SY8P300MB0421.AUSP300.PROD.OUTLOOK.COM/ +Signed-off-by: Kuniyuki Iwashima +Acked-by: Stanislav Fomichev +Reviewed-by: Ido Schimmel +Acked-by: Nikolay Aleksandrov +Link: https://patch.msgid.link/20250316192851.19781-1-kuniyu@amazon.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + include/linux/if_bridge.h | 6 ++---- + net/bridge/br_ioctl.c | 36 +++++++++++++++++++++++++++++++++--- + net/bridge/br_private.h | 3 +-- + net/core/dev_ioctl.c | 19 ------------------- + net/socket.c | 19 +++++++++---------- + 5 files changed, 45 insertions(+), 38 deletions(-) + +diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h +index 3ff96ae31bf6d..c5fe3b2a53e82 100644 +--- a/include/linux/if_bridge.h ++++ b/include/linux/if_bridge.h +@@ -65,11 +65,9 @@ struct br_ip_list { + #define BR_DEFAULT_AGEING_TIME (300 * HZ) + + struct net_bridge; +-void brioctl_set(int (*hook)(struct net *net, struct net_bridge *br, +- unsigned int cmd, struct ifreq *ifr, ++void brioctl_set(int (*hook)(struct net *net, unsigned int cmd, + void __user *uarg)); +-int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd, +- struct ifreq *ifr, void __user *uarg); ++int br_ioctl_call(struct net *net, unsigned int cmd, void __user *uarg); + + #if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING) + int br_multicast_list_adjacent(struct net_device *dev, +diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c +index f213ed1083618..6bc0a11f2ed3e 100644 +--- a/net/bridge/br_ioctl.c ++++ b/net/bridge/br_ioctl.c +@@ -394,10 +394,26 @@ static int old_deviceless(struct net *net, void __user *data) + return -EOPNOTSUPP; + } + +-int br_ioctl_stub(struct net *net, struct net_bridge *br, unsigned int cmd, +- struct ifreq *ifr, void __user *uarg) ++int br_ioctl_stub(struct net *net, unsigned int cmd, void __user *uarg) + { + int ret = -EOPNOTSUPP; ++ struct ifreq ifr; ++ ++ if (cmd == SIOCBRADDIF || cmd == SIOCBRDELIF) { ++ void __user *data; ++ char *colon; ++ ++ if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) ++ return -EPERM; ++ ++ if (get_user_ifreq(&ifr, &data, uarg)) ++ return -EFAULT; ++ ++ ifr.ifr_name[IFNAMSIZ - 1] = 0; ++ colon = strchr(ifr.ifr_name, ':'); ++ if (colon) ++ *colon = 0; ++ } + + rtnl_lock(); + +@@ -430,7 +446,21 @@ int br_ioctl_stub(struct net *net, struct net_bridge *br, unsigned int cmd, + break; + case SIOCBRADDIF: + case SIOCBRDELIF: +- ret = add_del_if(br, ifr->ifr_ifindex, cmd == SIOCBRADDIF); ++ { ++ struct net_device *dev; ++ ++ dev = __dev_get_by_name(net, ifr.ifr_name); ++ if (!dev || !netif_device_present(dev)) { ++ ret = -ENODEV; ++ break; ++ } ++ if (!netif_is_bridge_master(dev)) { ++ ret = -EOPNOTSUPP; ++ break; ++ } ++ ++ ret = add_del_if(netdev_priv(dev), ifr.ifr_ifindex, cmd == SIOCBRADDIF); ++ } + break; + } + +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index 1054b8a88edc4..d5b3c5936a79e 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -949,8 +949,7 @@ br_port_get_check_rtnl(const struct net_device *dev) + /* br_ioctl.c */ + int br_dev_siocdevprivate(struct net_device *dev, struct ifreq *rq, + void __user *data, int cmd); +-int br_ioctl_stub(struct net *net, struct net_bridge *br, unsigned int cmd, +- struct ifreq *ifr, void __user *uarg); ++int br_ioctl_stub(struct net *net, unsigned int cmd, void __user *uarg); + + /* br_multicast.c */ + #ifdef CONFIG_BRIDGE_IGMP_SNOOPING +diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c +index 4c2098ac9d724..57f79f8e84665 100644 +--- a/net/core/dev_ioctl.c ++++ b/net/core/dev_ioctl.c +@@ -551,7 +551,6 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, void __user *data, + int err; + struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name); + const struct net_device_ops *ops; +- netdevice_tracker dev_tracker; + + if (!dev) + return -ENODEV; +@@ -614,22 +613,6 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, void __user *data, + case SIOCWANDEV: + return dev_siocwandev(dev, &ifr->ifr_settings); + +- case SIOCBRADDIF: +- case SIOCBRDELIF: +- if (!netif_device_present(dev)) +- return -ENODEV; +- if (!netif_is_bridge_master(dev)) +- return -EOPNOTSUPP; +- +- netdev_hold(dev, &dev_tracker, GFP_KERNEL); +- rtnl_net_unlock(net); +- +- err = br_ioctl_call(net, netdev_priv(dev), cmd, ifr, NULL); +- +- netdev_put(dev, &dev_tracker); +- rtnl_net_lock(net); +- return err; +- + case SIOCDEVPRIVATE ... SIOCDEVPRIVATE + 15: + return dev_siocdevprivate(dev, ifr, data, cmd); + +@@ -812,8 +795,6 @@ int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr, + case SIOCBONDRELEASE: + case SIOCBONDSETHWADDR: + case SIOCBONDCHANGEACTIVE: +- case SIOCBRADDIF: +- case SIOCBRDELIF: + case SIOCSHWTSTAMP: + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) + return -EPERM; +diff --git a/net/socket.c b/net/socket.c +index 28bae5a942341..38227d00d1987 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -1145,12 +1145,10 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from) + */ + + static DEFINE_MUTEX(br_ioctl_mutex); +-static int (*br_ioctl_hook)(struct net *net, struct net_bridge *br, +- unsigned int cmd, struct ifreq *ifr, ++static int (*br_ioctl_hook)(struct net *net, unsigned int cmd, + void __user *uarg); + +-void brioctl_set(int (*hook)(struct net *net, struct net_bridge *br, +- unsigned int cmd, struct ifreq *ifr, ++void brioctl_set(int (*hook)(struct net *net, unsigned int cmd, + void __user *uarg)) + { + mutex_lock(&br_ioctl_mutex); +@@ -1159,8 +1157,7 @@ void brioctl_set(int (*hook)(struct net *net, struct net_bridge *br, + } + EXPORT_SYMBOL(brioctl_set); + +-int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd, +- struct ifreq *ifr, void __user *uarg) ++int br_ioctl_call(struct net *net, unsigned int cmd, void __user *uarg) + { + int err = -ENOPKG; + +@@ -1169,7 +1166,7 @@ int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd, + + mutex_lock(&br_ioctl_mutex); + if (br_ioctl_hook) +- err = br_ioctl_hook(net, br, cmd, ifr, uarg); ++ err = br_ioctl_hook(net, cmd, uarg); + mutex_unlock(&br_ioctl_mutex); + + return err; +@@ -1269,7 +1266,9 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) + case SIOCSIFBR: + case SIOCBRADDBR: + case SIOCBRDELBR: +- err = br_ioctl_call(net, NULL, cmd, NULL, argp); ++ case SIOCBRADDIF: ++ case SIOCBRDELIF: ++ err = br_ioctl_call(net, cmd, argp); + break; + case SIOCGIFVLAN: + case SIOCSIFVLAN: +@@ -3429,6 +3428,8 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, + case SIOCGPGRP: + case SIOCBRADDBR: + case SIOCBRDELBR: ++ case SIOCBRADDIF: ++ case SIOCBRDELIF: + case SIOCGIFVLAN: + case SIOCSIFVLAN: + case SIOCGSKNS: +@@ -3468,8 +3469,6 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, + case SIOCGIFPFLAGS: + case SIOCGIFTXQLEN: + case SIOCSIFTXQLEN: +- case SIOCBRADDIF: +- case SIOCBRDELIF: + case SIOCGIFNAME: + case SIOCSIFNAME: + case SIOCGMIIPHY: +-- +2.39.5 + diff --git a/queue-6.14/net_sched-skbprio-remove-overly-strict-queue-asserti.patch b/queue-6.14/net_sched-skbprio-remove-overly-strict-queue-asserti.patch new file mode 100644 index 0000000000..c071b8caca --- /dev/null +++ b/queue-6.14/net_sched-skbprio-remove-overly-strict-queue-asserti.patch @@ -0,0 +1,60 @@ +From f1085a31189fe6111a4bc28ceef7c19fcb388130 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 29 Mar 2025 15:25:35 -0700 +Subject: net_sched: skbprio: Remove overly strict queue assertions + +From: Cong Wang + +[ Upstream commit ce8fe975fd99b49c29c42e50f2441ba53112b2e8 ] + +In the current implementation, skbprio enqueue/dequeue contains an assertion +that fails under certain conditions when SKBPRIO is used as a child qdisc under +TBF with specific parameters. The failure occurs because TBF sometimes peeks at +packets in the child qdisc without actually dequeuing them when tokens are +unavailable. + +This peek operation creates a discrepancy between the parent and child qdisc +queue length counters. When TBF later receives a high-priority packet, +SKBPRIO's queue length may show a different value than what's reflected in its +internal priority queue tracking, triggering the assertion. + +The fix removes this overly strict assertions in SKBPRIO, they are not +necessary at all. + +Reported-by: syzbot+a3422a19b05ea96bee18@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=a3422a19b05ea96bee18 +Fixes: aea5f654e6b7 ("net/sched: add skbprio scheduler") +Cc: Nishanth Devarajan +Signed-off-by: Cong Wang +Acked-by: Paolo Abeni +Link: https://patch.msgid.link/20250329222536.696204-2-xiyou.wangcong@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_skbprio.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/net/sched/sch_skbprio.c b/net/sched/sch_skbprio.c +index 20ff7386b74bd..f485f62ab721a 100644 +--- a/net/sched/sch_skbprio.c ++++ b/net/sched/sch_skbprio.c +@@ -123,8 +123,6 @@ static int skbprio_enqueue(struct sk_buff *skb, struct Qdisc *sch, + /* Check to update highest and lowest priorities. */ + if (skb_queue_empty(lp_qdisc)) { + if (q->lowest_prio == q->highest_prio) { +- /* The incoming packet is the only packet in queue. */ +- BUG_ON(sch->q.qlen != 1); + q->lowest_prio = prio; + q->highest_prio = prio; + } else { +@@ -156,7 +154,6 @@ static struct sk_buff *skbprio_dequeue(struct Qdisc *sch) + /* Update highest priority field. */ + if (skb_queue_empty(hpq)) { + if (q->lowest_prio == q->highest_prio) { +- BUG_ON(sch->q.qlen); + q->highest_prio = 0; + q->lowest_prio = SKBPRIO_MAX_PRIORITY - 1; + } else { +-- +2.39.5 + diff --git a/queue-6.14/netfilter-nf_tables-don-t-unregister-hook-when-table.patch b/queue-6.14/netfilter-nf_tables-don-t-unregister-hook-when-table.patch new file mode 100644 index 0000000000..0615405458 --- /dev/null +++ b/queue-6.14/netfilter-nf_tables-don-t-unregister-hook-when-table.patch @@ -0,0 +1,48 @@ +From 9f16a61be7c5b148885004a6645bc0ca4552a772 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Apr 2025 14:36:47 +0200 +Subject: netfilter: nf_tables: don't unregister hook when table is dormant + +From: Florian Westphal + +[ Upstream commit 688c15017d5cd5aac882400782e7213d40dc3556 ] + +When nf_tables_updchain encounters an error, hook registration needs to +be rolled back. + +This should only be done if the hook has been registered, which won't +happen when the table is flagged as dormant (inactive). + +Just move the assignment into the registration block. + +Reported-by: syzbot+53ed3a6440173ddbf499@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=53ed3a6440173ddbf499 +Fixes: b9703ed44ffb ("netfilter: nf_tables: support for adding new devices to an existing netdev chain") +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_tables_api.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index c2df81b7e9505..a133e1c175ce9 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -2839,11 +2839,11 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy, + err = nft_netdev_register_hooks(ctx->net, &hook.list); + if (err < 0) + goto err_hooks; ++ ++ unregister = true; + } + } + +- unregister = true; +- + if (nla[NFTA_CHAIN_COUNTERS]) { + if (!nft_is_base_chain(chain)) { + err = -EOPNOTSUPP; +-- +2.39.5 + diff --git a/queue-6.14/netfilter-nf_tables-only-use-nf_skip_indirect_calls-.patch b/queue-6.14/netfilter-nf_tables-only-use-nf_skip_indirect_calls-.patch new file mode 100644 index 0000000000..5b0e773662 --- /dev/null +++ b/queue-6.14/netfilter-nf_tables-only-use-nf_skip_indirect_calls-.patch @@ -0,0 +1,77 @@ +From 61f92995d2e0568223f4f7fddb5f44eebe6e6cd6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 22:01:47 +0800 +Subject: netfilter: nf_tables: Only use nf_skip_indirect_calls() when + MITIGATION_RETPOLINE + +From: WangYuli + +[ Upstream commit e3a4182edd1ae60e7e3539ff3b3784af9830d223 ] + +1. MITIGATION_RETPOLINE is x86-only (defined in arch/x86/Kconfig), +so no need to AND with CONFIG_X86 when checking if enabled. + +2. Remove unused declaration of nf_skip_indirect_calls() when +MITIGATION_RETPOLINE is disabled to avoid warnings. + +3. Declare nf_skip_indirect_calls() and nf_skip_indirect_calls_enable() +as inline when MITIGATION_RETPOLINE is enabled, as they are called +only once and have simple logic. + +Fix follow error with clang-21 when W=1e: + net/netfilter/nf_tables_core.c:39:20: error: unused function 'nf_skip_indirect_calls' [-Werror,-Wunused-function] + 39 | static inline bool nf_skip_indirect_calls(void) { return false; } + | ^~~~~~~~~~~~~~~~~~~~~~ + 1 error generated. + make[4]: *** [scripts/Makefile.build:207: net/netfilter/nf_tables_core.o] Error 1 + make[3]: *** [scripts/Makefile.build:465: net/netfilter] Error 2 + make[3]: *** Waiting for unfinished jobs.... + +Fixes: d8d760627855 ("netfilter: nf_tables: add static key to skip retpoline workarounds") +Co-developed-by: Wentao Guan +Signed-off-by: Wentao Guan +Signed-off-by: WangYuli +Acked-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_tables_core.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c +index 75598520b0fa0..6557a4018c099 100644 +--- a/net/netfilter/nf_tables_core.c ++++ b/net/netfilter/nf_tables_core.c +@@ -21,25 +21,22 @@ + #include + #include + +-#if defined(CONFIG_MITIGATION_RETPOLINE) && defined(CONFIG_X86) +- ++#ifdef CONFIG_MITIGATION_RETPOLINE + static struct static_key_false nf_tables_skip_direct_calls; + +-static bool nf_skip_indirect_calls(void) ++static inline bool nf_skip_indirect_calls(void) + { + return static_branch_likely(&nf_tables_skip_direct_calls); + } + +-static void __init nf_skip_indirect_calls_enable(void) ++static inline void __init nf_skip_indirect_calls_enable(void) + { + if (!cpu_feature_enabled(X86_FEATURE_RETPOLINE)) + static_branch_enable(&nf_tables_skip_direct_calls); + } + #else +-static inline bool nf_skip_indirect_calls(void) { return false; } +- + static inline void nf_skip_indirect_calls_enable(void) { } +-#endif ++#endif /* CONFIG_MITIGATION_RETPOLINE */ + + static noinline void __nft_trace_packet(const struct nft_pktinfo *pkt, + const struct nft_verdict *verdict, +-- +2.39.5 + diff --git a/queue-6.14/netfilter-nfnetlink_queue-initialize-ctx-to-avoid-me.patch b/queue-6.14/netfilter-nfnetlink_queue-initialize-ctx-to-avoid-me.patch new file mode 100644 index 0000000000..11196d2613 --- /dev/null +++ b/queue-6.14/netfilter-nfnetlink_queue-initialize-ctx-to-avoid-me.patch @@ -0,0 +1,44 @@ +From 5ca0eab51fc25ecf2a730d0237c3f1cd34d75ab3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 14:54:41 -0500 +Subject: netfilter: nfnetlink_queue: Initialize ctx to avoid memory allocation + error + +From: Chenyuan Yang + +[ Upstream commit 778b09d91baafb13408470c721d034d6515cfa5a ] + +It is possible that ctx in nfqnl_build_packet_message() could be used +before it is properly initialize, which is only initialized +by nfqnl_get_sk_secctx(). + +This patch corrects this problem by initializing the lsmctx to a safe +value when it is declared. + +This is similar to the commit 35fcac7a7c25 +("audit: Initialize lsmctx to avoid memory allocation error"). + +Fixes: 2d470c778120 ("lsm: replace context+len with lsm_context") +Signed-off-by: Chenyuan Yang +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nfnetlink_queue.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c +index 5c913987901ab..8b7b39d8a1091 100644 +--- a/net/netfilter/nfnetlink_queue.c ++++ b/net/netfilter/nfnetlink_queue.c +@@ -567,7 +567,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, + enum ip_conntrack_info ctinfo = 0; + const struct nfnl_ct_hook *nfnl_ct; + bool csum_verify; +- struct lsm_context ctx; ++ struct lsm_context ctx = { NULL, 0, 0 }; + int seclen = 0; + ktime_t tstamp; + +-- +2.39.5 + diff --git a/queue-6.14/netfilter-nft_set_hash-gc-reaps-elements-with-connco.patch b/queue-6.14/netfilter-nft_set_hash-gc-reaps-elements-with-connco.patch new file mode 100644 index 0000000000..79cd3ce473 --- /dev/null +++ b/queue-6.14/netfilter-nft_set_hash-gc-reaps-elements-with-connco.patch @@ -0,0 +1,40 @@ +From e04bba514ca0b87680190ba7b74cfa31c467a881 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 23:24:20 +0100 +Subject: netfilter: nft_set_hash: GC reaps elements with conncount for dynamic + sets only + +From: Pablo Neira Ayuso + +[ Upstream commit 9d74da1177c800eb3d51c13f9821b7b0683845a5 ] + +conncount has its own GC handler which determines when to reap stale +elements, this is convenient for dynamic sets. However, this also reaps +non-dynamic sets with static configurations coming from control plane. +Always run connlimit gc handler but honor feedback to reap element if +this set is dynamic. + +Fixes: 290180e2448c ("netfilter: nf_tables: add connlimit support") +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nft_set_hash.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c +index 8bfac4185ac79..abb0c8ec63719 100644 +--- a/net/netfilter/nft_set_hash.c ++++ b/net/netfilter/nft_set_hash.c +@@ -309,7 +309,8 @@ static bool nft_rhash_expr_needs_gc_run(const struct nft_set *set, + + nft_setelem_expr_foreach(expr, elem_expr, size) { + if (expr->ops->gc && +- expr->ops->gc(read_pnet(&set->net), expr)) ++ expr->ops->gc(read_pnet(&set->net), expr) && ++ set->flags & NFT_SET_EVAL) + return true; + } + +-- +2.39.5 + diff --git a/queue-6.14/netfilter-nft_tunnel-fix-geneve_opt-type-confusion-a.patch b/queue-6.14/netfilter-nft_tunnel-fix-geneve_opt-type-confusion-a.patch new file mode 100644 index 0000000000..593cb836f3 --- /dev/null +++ b/queue-6.14/netfilter-nft_tunnel-fix-geneve_opt-type-confusion-a.patch @@ -0,0 +1,88 @@ +From 66f8fc68e7b330086029913efc8db0532f0cb25f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 3 Apr 2025 01:00:26 +0800 +Subject: netfilter: nft_tunnel: fix geneve_opt type confusion addition + +From: Lin Ma + +[ Upstream commit 1b755d8eb1ace3870789d48fbd94f386ad6e30be ] + +When handling multiple NFTA_TUNNEL_KEY_OPTS_GENEVE attributes, the +parsing logic should place every geneve_opt structure one by one +compactly. Hence, when deciding the next geneve_opt position, the +pointer addition should be in units of char *. + +However, the current implementation erroneously does type conversion +before the addition, which will lead to heap out-of-bounds write. + +[ 6.989857] ================================================================== +[ 6.990293] BUG: KASAN: slab-out-of-bounds in nft_tunnel_obj_init+0x977/0xa70 +[ 6.990725] Write of size 124 at addr ffff888005f18974 by task poc/178 +[ 6.991162] +[ 6.991259] CPU: 0 PID: 178 Comm: poc-oob-write Not tainted 6.1.132 #1 +[ 6.991655] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014 +[ 6.992281] Call Trace: +[ 6.992423] +[ 6.992586] dump_stack_lvl+0x44/0x5c +[ 6.992801] print_report+0x184/0x4be +[ 6.993790] kasan_report+0xc5/0x100 +[ 6.994252] kasan_check_range+0xf3/0x1a0 +[ 6.994486] memcpy+0x38/0x60 +[ 6.994692] nft_tunnel_obj_init+0x977/0xa70 +[ 6.995677] nft_obj_init+0x10c/0x1b0 +[ 6.995891] nf_tables_newobj+0x585/0x950 +[ 6.996922] nfnetlink_rcv_batch+0xdf9/0x1020 +[ 6.998997] nfnetlink_rcv+0x1df/0x220 +[ 6.999537] netlink_unicast+0x395/0x530 +[ 7.000771] netlink_sendmsg+0x3d0/0x6d0 +[ 7.001462] __sock_sendmsg+0x99/0xa0 +[ 7.001707] ____sys_sendmsg+0x409/0x450 +[ 7.002391] ___sys_sendmsg+0xfd/0x170 +[ 7.003145] __sys_sendmsg+0xea/0x170 +[ 7.004359] do_syscall_64+0x5e/0x90 +[ 7.005817] entry_SYSCALL_64_after_hwframe+0x6e/0xd8 +[ 7.006127] RIP: 0033:0x7ec756d4e407 +[ 7.006339] Code: 48 89 fa 4c 89 df e8 38 aa 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 faf +[ 7.007364] RSP: 002b:00007ffed5d46760 EFLAGS: 00000202 ORIG_RAX: 000000000000002e +[ 7.007827] RAX: ffffffffffffffda RBX: 00007ec756cc4740 RCX: 00007ec756d4e407 +[ 7.008223] RDX: 0000000000000000 RSI: 00007ffed5d467f0 RDI: 0000000000000003 +[ 7.008620] RBP: 00007ffed5d468a0 R08: 0000000000000000 R09: 0000000000000000 +[ 7.009039] R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000000 +[ 7.009429] R13: 00007ffed5d478b0 R14: 00007ec756ee5000 R15: 00005cbd4e655cb8 + +Fix this bug with correct pointer addition and conversion in parse +and dump code. + +Fixes: 925d844696d9 ("netfilter: nft_tunnel: add support for geneve opts") +Signed-off-by: Lin Ma +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nft_tunnel.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c +index 681301b46aa40..2e40f575aed9f 100644 +--- a/net/netfilter/nft_tunnel.c ++++ b/net/netfilter/nft_tunnel.c +@@ -341,7 +341,7 @@ static const struct nla_policy nft_tunnel_opts_geneve_policy[NFTA_TUNNEL_KEY_GEN + static int nft_tunnel_obj_geneve_init(const struct nlattr *attr, + struct nft_tunnel_opts *opts) + { +- struct geneve_opt *opt = (struct geneve_opt *)opts->u.data + opts->len; ++ struct geneve_opt *opt = (struct geneve_opt *)(opts->u.data + opts->len); + struct nlattr *tb[NFTA_TUNNEL_KEY_GENEVE_MAX + 1]; + int err, data_len; + +@@ -625,7 +625,7 @@ static int nft_tunnel_opts_dump(struct sk_buff *skb, + if (!inner) + goto failure; + while (opts->len > offset) { +- opt = (struct geneve_opt *)opts->u.data + offset; ++ opt = (struct geneve_opt *)(opts->u.data + offset); + if (nla_put_be16(skb, NFTA_TUNNEL_KEY_GENEVE_CLASS, + opt->opt_class) || + nla_put_u8(skb, NFTA_TUNNEL_KEY_GENEVE_TYPE, +-- +2.39.5 + diff --git a/queue-6.14/netlabel-fix-null-pointer-exception-caused-by-calips.patch b/queue-6.14/netlabel-fix-null-pointer-exception-caused-by-calips.patch new file mode 100644 index 0000000000..6ba6f36bd7 --- /dev/null +++ b/queue-6.14/netlabel-fix-null-pointer-exception-caused-by-calips.patch @@ -0,0 +1,87 @@ +From a82444a72916ca60ee3405034c118ab4306e753d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Apr 2025 20:40:18 +0800 +Subject: netlabel: Fix NULL pointer exception caused by CALIPSO on IPv4 + sockets + +From: Debin Zhu + +[ Upstream commit 078aabd567de3d63d37d7673f714e309d369e6e2 ] + +When calling netlbl_conn_setattr(), addr->sa_family is used +to determine the function behavior. If sk is an IPv4 socket, +but the connect function is called with an IPv6 address, +the function calipso_sock_setattr() is triggered. +Inside this function, the following code is executed: + +sk_fullsock(__sk) ? inet_sk(__sk)->pinet6 : NULL; + +Since sk is an IPv4 socket, pinet6 is NULL, leading to a +null pointer dereference. + +This patch fixes the issue by checking if inet6_sk(sk) +returns a NULL pointer before accessing pinet6. + +Signed-off-by: Debin Zhu +Signed-off-by: Bitao Ouyang <1985755126@qq.com> +Acked-by: Paul Moore +Fixes: ceba1832b1b2 ("calipso: Set the calipso socket label to match the secattr.") +Link: https://patch.msgid.link/20250401124018.4763-1-mowenroot@163.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/calipso.c | 21 ++++++++++++++++++--- + 1 file changed, 18 insertions(+), 3 deletions(-) + +diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c +index dbcea9fee6262..62618a058b8fa 100644 +--- a/net/ipv6/calipso.c ++++ b/net/ipv6/calipso.c +@@ -1072,8 +1072,13 @@ static int calipso_sock_getattr(struct sock *sk, + struct ipv6_opt_hdr *hop; + int opt_len, len, ret_val = -ENOMSG, offset; + unsigned char *opt; +- struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk)); ++ struct ipv6_pinfo *pinfo = inet6_sk(sk); ++ struct ipv6_txoptions *txopts; ++ ++ if (!pinfo) ++ return -EAFNOSUPPORT; + ++ txopts = txopt_get(pinfo); + if (!txopts || !txopts->hopopt) + goto done; + +@@ -1125,8 +1130,13 @@ static int calipso_sock_setattr(struct sock *sk, + { + int ret_val; + struct ipv6_opt_hdr *old, *new; +- struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk)); ++ struct ipv6_pinfo *pinfo = inet6_sk(sk); ++ struct ipv6_txoptions *txopts; ++ ++ if (!pinfo) ++ return -EAFNOSUPPORT; + ++ txopts = txopt_get(pinfo); + old = NULL; + if (txopts) + old = txopts->hopopt; +@@ -1153,8 +1163,13 @@ static int calipso_sock_setattr(struct sock *sk, + static void calipso_sock_delattr(struct sock *sk) + { + struct ipv6_opt_hdr *new_hop; +- struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk)); ++ struct ipv6_pinfo *pinfo = inet6_sk(sk); ++ struct ipv6_txoptions *txopts; ++ ++ if (!pinfo) ++ return; + ++ txopts = txopt_get(pinfo); + if (!txopts || !txopts->hopopt) + goto done; + +-- +2.39.5 + diff --git a/queue-6.14/netlink-specs-rt_route-pull-the-ifa-prefix-out-of-th.patch b/queue-6.14/netlink-specs-rt_route-pull-the-ifa-prefix-out-of-th.patch new file mode 100644 index 0000000000..72b2961586 --- /dev/null +++ b/queue-6.14/netlink-specs-rt_route-pull-the-ifa-prefix-out-of-th.patch @@ -0,0 +1,342 @@ +From 3b4c0e06426e336d139aecf7da324d986009e7e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Apr 2025 18:37:06 -0700 +Subject: netlink: specs: rt_route: pull the ifa- prefix out of the names + +From: Jakub Kicinski + +[ Upstream commit 1a1eba0e9899c286914032c78708c614b016704b ] + +YAML specs don't normally include the C prefix name in the name +of the YAML attr. Remove the ifa- prefix from all attributes +in route-attrs and metrics and specify name-prefix instead. + +This is a bit risky, hopefully there aren't many users out there. + +Fixes: 023289b4f582 ("doc/netlink: Add spec for rt route messages") +Reviewed-by: Donald Hunter +Link: https://patch.msgid.link/20250403013706.2828322-5-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + Documentation/netlink/specs/rt_route.yaml | 180 +++++++++++----------- + 1 file changed, 91 insertions(+), 89 deletions(-) + +diff --git a/Documentation/netlink/specs/rt_route.yaml b/Documentation/netlink/specs/rt_route.yaml +index a674103e5bc4e..292469c7d4b9f 100644 +--- a/Documentation/netlink/specs/rt_route.yaml ++++ b/Documentation/netlink/specs/rt_route.yaml +@@ -80,165 +80,167 @@ definitions: + attribute-sets: + - + name: route-attrs ++ name-prefix: rta- + attributes: + - +- name: rta-dst ++ name: dst + type: binary + display-hint: ipv4 + - +- name: rta-src ++ name: src + type: binary + display-hint: ipv4 + - +- name: rta-iif ++ name: iif + type: u32 + - +- name: rta-oif ++ name: oif + type: u32 + - +- name: rta-gateway ++ name: gateway + type: binary + display-hint: ipv4 + - +- name: rta-priority ++ name: priority + type: u32 + - +- name: rta-prefsrc ++ name: prefsrc + type: binary + display-hint: ipv4 + - +- name: rta-metrics ++ name: metrics + type: nest +- nested-attributes: rta-metrics ++ nested-attributes: metrics + - +- name: rta-multipath ++ name: multipath + type: binary + - +- name: rta-protoinfo # not used ++ name: protoinfo # not used + type: binary + - +- name: rta-flow ++ name: flow + type: u32 + - +- name: rta-cacheinfo ++ name: cacheinfo + type: binary + struct: rta-cacheinfo + - +- name: rta-session # not used ++ name: session # not used + type: binary + - +- name: rta-mp-algo # not used ++ name: mp-algo # not used + type: binary + - +- name: rta-table ++ name: table + type: u32 + - +- name: rta-mark ++ name: mark + type: u32 + - +- name: rta-mfc-stats ++ name: mfc-stats + type: binary + - +- name: rta-via ++ name: via + type: binary + - +- name: rta-newdst ++ name: newdst + type: binary + - +- name: rta-pref ++ name: pref + type: u8 + - +- name: rta-encap-type ++ name: encap-type + type: u16 + - +- name: rta-encap ++ name: encap + type: binary # tunnel specific nest + - +- name: rta-expires ++ name: expires + type: u32 + - +- name: rta-pad ++ name: pad + type: binary + - +- name: rta-uid ++ name: uid + type: u32 + - +- name: rta-ttl-propagate ++ name: ttl-propagate + type: u8 + - +- name: rta-ip-proto ++ name: ip-proto + type: u8 + - +- name: rta-sport ++ name: sport + type: u16 + - +- name: rta-dport ++ name: dport + type: u16 + - +- name: rta-nh-id ++ name: nh-id + type: u32 + - +- name: rta-flowlabel ++ name: flowlabel + type: u32 + byte-order: big-endian + display-hint: hex + - +- name: rta-metrics ++ name: metrics ++ name-prefix: rtax- + attributes: + - +- name: rtax-unspec ++ name: unspec + type: unused + value: 0 + - +- name: rtax-lock ++ name: lock + type: u32 + - +- name: rtax-mtu ++ name: mtu + type: u32 + - +- name: rtax-window ++ name: window + type: u32 + - +- name: rtax-rtt ++ name: rtt + type: u32 + - +- name: rtax-rttvar ++ name: rttvar + type: u32 + - +- name: rtax-ssthresh ++ name: ssthresh + type: u32 + - +- name: rtax-cwnd ++ name: cwnd + type: u32 + - +- name: rtax-advmss ++ name: advmss + type: u32 + - +- name: rtax-reordering ++ name: reordering + type: u32 + - +- name: rtax-hoplimit ++ name: hoplimit + type: u32 + - +- name: rtax-initcwnd ++ name: initcwnd + type: u32 + - +- name: rtax-features ++ name: features + type: u32 + - +- name: rtax-rto-min ++ name: rto-min + type: u32 + - +- name: rtax-initrwnd ++ name: initrwnd + type: u32 + - +- name: rtax-quickack ++ name: quickack + type: u32 + - +- name: rtax-cc-algo ++ name: cc-algo + type: string + - +- name: rtax-fastopen-no-cookie ++ name: fastopen-no-cookie + type: u32 + + operations: +@@ -254,18 +256,18 @@ operations: + value: 26 + attributes: + - rtm-family +- - rta-src ++ - src + - rtm-src-len +- - rta-dst ++ - dst + - rtm-dst-len +- - rta-iif +- - rta-oif +- - rta-ip-proto +- - rta-sport +- - rta-dport +- - rta-mark +- - rta-uid +- - rta-flowlabel ++ - iif ++ - oif ++ - ip-proto ++ - sport ++ - dport ++ - mark ++ - uid ++ - flowlabel + reply: + value: 24 + attributes: &all-route-attrs +@@ -278,34 +280,34 @@ operations: + - rtm-scope + - rtm-type + - rtm-flags +- - rta-dst +- - rta-src +- - rta-iif +- - rta-oif +- - rta-gateway +- - rta-priority +- - rta-prefsrc +- - rta-metrics +- - rta-multipath +- - rta-flow +- - rta-cacheinfo +- - rta-table +- - rta-mark +- - rta-mfc-stats +- - rta-via +- - rta-newdst +- - rta-pref +- - rta-encap-type +- - rta-encap +- - rta-expires +- - rta-pad +- - rta-uid +- - rta-ttl-propagate +- - rta-ip-proto +- - rta-sport +- - rta-dport +- - rta-nh-id +- - rta-flowlabel ++ - dst ++ - src ++ - iif ++ - oif ++ - gateway ++ - priority ++ - prefsrc ++ - metrics ++ - multipath ++ - flow ++ - cacheinfo ++ - table ++ - mark ++ - mfc-stats ++ - via ++ - newdst ++ - pref ++ - encap-type ++ - encap ++ - expires ++ - pad ++ - uid ++ - ttl-propagate ++ - ip-proto ++ - sport ++ - dport ++ - nh-id ++ - flowlabel + dump: + request: + value: 26 +-- +2.39.5 + diff --git a/queue-6.14/nfs-add-missing-release-on-error-in-nfs_lock_and_joi.patch b/queue-6.14/nfs-add-missing-release-on-error-in-nfs_lock_and_joi.patch new file mode 100644 index 0000000000..15b24dae13 --- /dev/null +++ b/queue-6.14/nfs-add-missing-release-on-error-in-nfs_lock_and_joi.patch @@ -0,0 +1,39 @@ +From a7fef49891bb5564300c6f997e7879270fb29bdd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Apr 2025 14:02:40 +0300 +Subject: nfs: Add missing release on error in nfs_lock_and_join_requests() + +From: Dan Carpenter + +[ Upstream commit 8e5419d6542fdf2dca9a0acdef2b8255f0e4ba69 ] + +Call nfs_release_request() on this error path before returning. + +Fixes: c3f2235782c3 ("nfs: fold nfs_folio_find_and_lock_request into nfs_lock_and_join_requests") +Signed-off-by: Dan Carpenter +Link: https://lore.kernel.org/r/3aaaa3d5-1c8a-41e4-98c7-717801ddd171@stanley.mountain +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/write.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/fs/nfs/write.c b/fs/nfs/write.c +index aa3d8bea3ec06..23df8b214474f 100644 +--- a/fs/nfs/write.c ++++ b/fs/nfs/write.c +@@ -579,8 +579,10 @@ static struct nfs_page *nfs_lock_and_join_requests(struct folio *folio) + + while (!nfs_lock_request(head)) { + ret = nfs_wait_on_request(head); +- if (ret < 0) ++ if (ret < 0) { ++ nfs_release_request(head); + return ERR_PTR(ret); ++ } + } + + /* Ensure that nobody removed the request before we locked it */ +-- +2.39.5 + diff --git a/queue-6.14/nfs-fix-open_owner_id_maxsz-and-related-fields.patch b/queue-6.14/nfs-fix-open_owner_id_maxsz-and-related-fields.patch new file mode 100644 index 0000000000..097c0aa809 --- /dev/null +++ b/queue-6.14/nfs-fix-open_owner_id_maxsz-and-related-fields.patch @@ -0,0 +1,100 @@ +From eccd76691bbf571aeaf92519d946d8fd437a63d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Dec 2024 13:53:09 +1100 +Subject: NFS: fix open_owner_id_maxsz and related fields. + +From: NeilBrown + +[ Upstream commit 43502f6e8d1e767d6736ea0676cc784025cf6eeb ] + +A recent change increased the size of an NFSv4 open owner, but didn't +increase the corresponding max_sz defines. This is not know to have +caused failure, but should be fixed. + +This patch also fixes some relates _maxsz fields that are wrong. + +Note that the XXX_owner_id_maxsz values now are only the size of the id +and do NOT include the len field that will always preceed the id in xdr +encoding. I think this is clearer. + +Reported-by: David Disseldorp +Fixes: d98f72272500 ("nfs: simplify and guarantee owner uniqueness.") +Signed-off-by: NeilBrown +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs4xdr.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c +index e8ac3f615f932..71f45cc0ca74d 100644 +--- a/fs/nfs/nfs4xdr.c ++++ b/fs/nfs/nfs4xdr.c +@@ -82,9 +82,8 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, + * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2) + */ + #define pagepad_maxsz (1) +-#define open_owner_id_maxsz (1 + 2 + 1 + 1 + 2) +-#define lock_owner_id_maxsz (1 + 1 + 4) +-#define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) ++#define open_owner_id_maxsz (2 + 1 + 2 + 2) ++#define lock_owner_id_maxsz (2 + 1 + 2) + #define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) + #define compound_decode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) + #define op_encode_hdr_maxsz (1) +@@ -185,7 +184,7 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, + #define encode_claim_null_maxsz (1 + nfs4_name_maxsz) + #define encode_open_maxsz (op_encode_hdr_maxsz + \ + 2 + encode_share_access_maxsz + 2 + \ +- open_owner_id_maxsz + \ ++ 1 + open_owner_id_maxsz + \ + encode_opentype_maxsz + \ + encode_claim_null_maxsz) + #define decode_space_limit_maxsz (3) +@@ -255,13 +254,14 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, + #define encode_link_maxsz (op_encode_hdr_maxsz + \ + nfs4_name_maxsz) + #define decode_link_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz) +-#define encode_lockowner_maxsz (7) ++#define encode_lockowner_maxsz (2 + 1 + lock_owner_id_maxsz) ++ + #define encode_lock_maxsz (op_encode_hdr_maxsz + \ + 7 + \ + 1 + encode_stateid_maxsz + 1 + \ + encode_lockowner_maxsz) + #define decode_lock_denied_maxsz \ +- (8 + decode_lockowner_maxsz) ++ (2 + 2 + 1 + 2 + 1 + lock_owner_id_maxsz) + #define decode_lock_maxsz (op_decode_hdr_maxsz + \ + decode_lock_denied_maxsz) + #define encode_lockt_maxsz (op_encode_hdr_maxsz + 5 + \ +@@ -617,7 +617,7 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, + encode_lockowner_maxsz) + #define NFS4_dec_release_lockowner_sz \ + (compound_decode_hdr_maxsz + \ +- decode_lockowner_maxsz) ++ decode_release_lockowner_maxsz) + #define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ + encode_putfh_maxsz + \ +@@ -1412,7 +1412,7 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena + __be32 *p; + /* + * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4, +- * owner 4 = 32 ++ * owner 28 + */ + encode_nfs4_seqid(xdr, arg->seqid); + encode_share_access(xdr, arg->share_access); +@@ -5077,7 +5077,7 @@ static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) + /* + * We create the owner, so we know a proper owner.id length is 4. + */ +-static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl) ++static int decode_lock_denied(struct xdr_stream *xdr, struct file_lock *fl) + { + uint64_t offset, length, clientid; + __be32 *p; +-- +2.39.5 + diff --git a/queue-6.14/nfs-shut-down-the-nfs_client-only-after-all-the-supe.patch b/queue-6.14/nfs-shut-down-the-nfs_client-only-after-all-the-supe.patch new file mode 100644 index 0000000000..08b3b1fd44 --- /dev/null +++ b/queue-6.14/nfs-shut-down-the-nfs_client-only-after-all-the-supe.patch @@ -0,0 +1,78 @@ +From 098bf8ca8c15b04aef6e92d815ee6f78901e9c2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Mar 2025 17:58:50 -0400 +Subject: NFS: Shut down the nfs_client only after all the superblocks + +From: Trond Myklebust + +[ Upstream commit 2d3e998a0bc7fe26a724f87a8ce217848040520e ] + +The nfs_client manages state for all the superblocks in the +"cl_superblocks" list, so it must not be shut down until all of them are +gone. + +Fixes: 7d3e26a054c8 ("NFS: Cancel all existing RPC tasks when shutdown") +Reviewed-by: Benjamin Coddington +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/sysfs.c | 22 +++++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +diff --git a/fs/nfs/sysfs.c b/fs/nfs/sysfs.c +index 7b59a40d40c06..784f7c1d003bf 100644 +--- a/fs/nfs/sysfs.c ++++ b/fs/nfs/sysfs.c +@@ -14,6 +14,7 @@ + #include + #include + ++#include "internal.h" + #include "nfs4_fs.h" + #include "netns.h" + #include "sysfs.h" +@@ -228,6 +229,25 @@ static void shutdown_client(struct rpc_clnt *clnt) + rpc_cancel_tasks(clnt, -EIO, shutdown_match_client, NULL); + } + ++/* ++ * Shut down the nfs_client only once all the superblocks ++ * have been shut down. ++ */ ++static void shutdown_nfs_client(struct nfs_client *clp) ++{ ++ struct nfs_server *server; ++ rcu_read_lock(); ++ list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { ++ if (!(server->flags & NFS_MOUNT_SHUTDOWN)) { ++ rcu_read_unlock(); ++ return; ++ } ++ } ++ rcu_read_unlock(); ++ nfs_mark_client_ready(clp, -EIO); ++ shutdown_client(clp->cl_rpcclient); ++} ++ + static ssize_t + shutdown_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +@@ -259,7 +279,6 @@ shutdown_store(struct kobject *kobj, struct kobj_attribute *attr, + + server->flags |= NFS_MOUNT_SHUTDOWN; + shutdown_client(server->client); +- shutdown_client(server->nfs_client->cl_rpcclient); + + if (!IS_ERR(server->client_acl)) + shutdown_client(server->client_acl); +@@ -267,6 +286,7 @@ shutdown_store(struct kobject *kobj, struct kobj_attribute *attr, + if (server->nlm_host) + shutdown_client(server->nlm_host->h_rpcclnt); + out: ++ shutdown_nfs_client(server->nfs_client); + return count; + } + +-- +2.39.5 + diff --git a/queue-6.14/nfsd-fix-callback-decoder-status-codes.patch b/queue-6.14/nfsd-fix-callback-decoder-status-codes.patch new file mode 100644 index 0000000000..cc2d0ecafc --- /dev/null +++ b/queue-6.14/nfsd-fix-callback-decoder-status-codes.patch @@ -0,0 +1,82 @@ +From 568d44cb669a6640e09778695184c3b435475c50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 12:03:32 -0500 +Subject: NFSD: Fix callback decoder status codes + +From: Chuck Lever + +[ Upstream commit 8ce35dcaf3aed7113cd692759dc0a26cec8cd0c3 ] + +fs/nfsd/nfs4callback.c implements a callback client. Thus its XDR +decoders are decoding replies, not calls. + +NFS4ERR_BAD_XDR is an on-the-wire status code that reports that the +client sent a corrupted RPC /call/. It's not used as the internal +error code when a /reply/ can't be decoded, since that kind of +failure is never reported to the sender of that RPC message. + +Instead, a reply decoder should return -EIO, as the reply decoders +in the NFS client do. + +Fixes: 6487a13b5c6b ("NFSD: add support for CB_GETATTR callback") +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfsd/nfs4callback.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c +index 484077200c5d7..d649a3d65a3a5 100644 +--- a/fs/nfsd/nfs4callback.c ++++ b/fs/nfsd/nfs4callback.c +@@ -101,15 +101,15 @@ static int decode_cb_fattr4(struct xdr_stream *xdr, uint32_t *bitmap, + + if (bitmap[0] & FATTR4_WORD0_CHANGE) + if (xdr_stream_decode_u64(xdr, &fattr->ncf_cb_change) < 0) +- return -NFSERR_BAD_XDR; ++ return -EIO; + if (bitmap[0] & FATTR4_WORD0_SIZE) + if (xdr_stream_decode_u64(xdr, &fattr->ncf_cb_fsize) < 0) +- return -NFSERR_BAD_XDR; ++ return -EIO; + if (bitmap[2] & FATTR4_WORD2_TIME_DELEG_ACCESS) { + fattr4_time_deleg_access access; + + if (!xdrgen_decode_fattr4_time_deleg_access(xdr, &access)) +- return -NFSERR_BAD_XDR; ++ return -EIO; + fattr->ncf_cb_atime.tv_sec = access.seconds; + fattr->ncf_cb_atime.tv_nsec = access.nseconds; + +@@ -118,7 +118,7 @@ static int decode_cb_fattr4(struct xdr_stream *xdr, uint32_t *bitmap, + fattr4_time_deleg_modify modify; + + if (!xdrgen_decode_fattr4_time_deleg_modify(xdr, &modify)) +- return -NFSERR_BAD_XDR; ++ return -EIO; + fattr->ncf_cb_mtime.tv_sec = modify.seconds; + fattr->ncf_cb_mtime.tv_nsec = modify.nseconds; + +@@ -682,15 +682,15 @@ static int nfs4_xdr_dec_cb_getattr(struct rpc_rqst *rqstp, + if (unlikely(status || cb->cb_status)) + return status; + if (xdr_stream_decode_uint32_array(xdr, bitmap, 3) < 0) +- return -NFSERR_BAD_XDR; ++ return -EIO; + if (xdr_stream_decode_u32(xdr, &attrlen) < 0) +- return -NFSERR_BAD_XDR; ++ return -EIO; + maxlen = sizeof(ncf->ncf_cb_change) + sizeof(ncf->ncf_cb_fsize); + if (bitmap[2] != 0) + maxlen += (sizeof(ncf->ncf_cb_mtime.tv_sec) + + sizeof(ncf->ncf_cb_mtime.tv_nsec)) * 2; + if (attrlen > maxlen) +- return -NFSERR_BAD_XDR; ++ return -EIO; + status = decode_cb_fattr4(xdr, bitmap, ncf); + return status; + } +-- +2.39.5 + diff --git a/queue-6.14/nfsv4-avoid-unnecessary-scans-of-filesystems-for-del.patch b/queue-6.14/nfsv4-avoid-unnecessary-scans-of-filesystems-for-del.patch new file mode 100644 index 0000000000..17720cf120 --- /dev/null +++ b/queue-6.14/nfsv4-avoid-unnecessary-scans-of-filesystems-for-del.patch @@ -0,0 +1,102 @@ +From 7341ed38ac3e8da4d0c19e64f8825f31f9e6f383 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 18:37:51 -0500 +Subject: NFSv4: Avoid unnecessary scans of filesystems for delayed delegations + +From: Trond Myklebust + +[ Upstream commit e767b59e29b8327d25edde65efc743f479f30d0a ] + +The amount of looping through the list of delegations is occasionally +leading to soft lockups. If the state manager was asked to manage the +delayed return of delegations, then only scan those filesystems +containing delegations that were marked as being delayed. + +Fixes: be20037725d1 ("NFSv4: Fix delegation return in cases where we have to retry") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/delegation.c | 18 ++++++++++++------ + include/linux/nfs_fs_sb.h | 1 + + 2 files changed, 13 insertions(+), 6 deletions(-) + +diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c +index abd952cc47e4b..325ba0663a6de 100644 +--- a/fs/nfs/delegation.c ++++ b/fs/nfs/delegation.c +@@ -331,14 +331,16 @@ nfs_start_delegation_return(struct nfs_inode *nfsi) + } + + static void nfs_abort_delegation_return(struct nfs_delegation *delegation, +- struct nfs_client *clp, int err) ++ struct nfs_server *server, int err) + { +- + spin_lock(&delegation->lock); + clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags); + if (err == -EAGAIN) { + set_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags); +- set_bit(NFS4CLNT_DELEGRETURN_DELAYED, &clp->cl_state); ++ set_bit(NFS4SERV_DELEGRETURN_DELAYED, ++ &server->delegation_flags); ++ set_bit(NFS4CLNT_DELEGRETURN_DELAYED, ++ &server->nfs_client->cl_state); + } + spin_unlock(&delegation->lock); + } +@@ -548,7 +550,7 @@ int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred, + */ + static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation *delegation, int issync) + { +- struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; ++ struct nfs_server *server = NFS_SERVER(inode); + unsigned int mode = O_WRONLY | O_RDWR; + int err = 0; + +@@ -570,11 +572,11 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation + /* + * Guard against state recovery + */ +- err = nfs4_wait_clnt_recover(clp); ++ err = nfs4_wait_clnt_recover(server->nfs_client); + } + + if (err) { +- nfs_abort_delegation_return(delegation, clp, err); ++ nfs_abort_delegation_return(delegation, server, err); + goto out; + } + +@@ -678,6 +680,9 @@ static bool nfs_server_clear_delayed_delegations(struct nfs_server *server) + struct nfs_delegation *d; + bool ret = false; + ++ if (!test_and_clear_bit(NFS4SERV_DELEGRETURN_DELAYED, ++ &server->delegation_flags)) ++ goto out; + list_for_each_entry_rcu (d, &server->delegations, super_list) { + if (!test_bit(NFS_DELEGATION_RETURN_DELAYED, &d->flags)) + continue; +@@ -685,6 +690,7 @@ static bool nfs_server_clear_delayed_delegations(struct nfs_server *server) + clear_bit(NFS_DELEGATION_RETURN_DELAYED, &d->flags); + ret = true; + } ++out: + return ret; + } + +diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h +index 7d6f164036fac..108862d81b579 100644 +--- a/include/linux/nfs_fs_sb.h ++++ b/include/linux/nfs_fs_sb.h +@@ -253,6 +253,7 @@ struct nfs_server { + unsigned long delegation_flags; + #define NFS4SERV_DELEGRETURN (1) + #define NFS4SERV_DELEGATION_EXPIRED (2) ++#define NFS4SERV_DELEGRETURN_DELAYED (3) + unsigned long delegation_gen; + unsigned long mig_gen; + unsigned long mig_status; +-- +2.39.5 + diff --git a/queue-6.14/nfsv4-avoid-unnecessary-scans-of-filesystems-for-exp.patch b/queue-6.14/nfsv4-avoid-unnecessary-scans-of-filesystems-for-exp.patch new file mode 100644 index 0000000000..e86b0900b2 --- /dev/null +++ b/queue-6.14/nfsv4-avoid-unnecessary-scans-of-filesystems-for-exp.patch @@ -0,0 +1,69 @@ +From 357e5a298a29879766e42963624041b8c62f5609 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 19:03:21 -0500 +Subject: NFSv4: Avoid unnecessary scans of filesystems for expired delegations + +From: Trond Myklebust + +[ Upstream commit f163aa81a799e2d46d7f8f0b42a0e7770eaa0d06 ] + +The amount of looping through the list of delegations is occasionally +leading to soft lockups. If the state manager was asked to reap the +expired delegations, it should scan only those filesystems that hold +delegations that need to be reaped. + +Fixes: 7f156ef0bf45 ("NFSv4: Clean up nfs_delegation_reap_expired()") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/delegation.c | 7 +++++++ + include/linux/nfs_fs_sb.h | 1 + + 2 files changed, 8 insertions(+) + +diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c +index d1f5e497729c3..abd952cc47e4b 100644 +--- a/fs/nfs/delegation.c ++++ b/fs/nfs/delegation.c +@@ -1284,6 +1284,7 @@ static void nfs_mark_test_expired_delegation(struct nfs_server *server, + return; + clear_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags); + set_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags); ++ set_bit(NFS4SERV_DELEGATION_EXPIRED, &server->delegation_flags); + set_bit(NFS4CLNT_DELEGATION_EXPIRED, &server->nfs_client->cl_state); + } + +@@ -1362,6 +1363,9 @@ static int nfs_server_reap_expired_delegations(struct nfs_server *server, + nfs4_stateid stateid; + unsigned long gen = ++server->delegation_gen; + ++ if (!test_and_clear_bit(NFS4SERV_DELEGATION_EXPIRED, ++ &server->delegation_flags)) ++ return 0; + restart: + rcu_read_lock(); + list_for_each_entry_rcu(delegation, &server->delegations, super_list) { +@@ -1391,6 +1395,9 @@ static int nfs_server_reap_expired_delegations(struct nfs_server *server, + goto restart; + } + nfs_inode_mark_test_expired_delegation(server,inode); ++ set_bit(NFS4SERV_DELEGATION_EXPIRED, &server->delegation_flags); ++ set_bit(NFS4CLNT_DELEGATION_EXPIRED, ++ &server->nfs_client->cl_state); + iput(inode); + return -EAGAIN; + } +diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h +index 4e9ad6f6e9073..7d6f164036fac 100644 +--- a/include/linux/nfs_fs_sb.h ++++ b/include/linux/nfs_fs_sb.h +@@ -252,6 +252,7 @@ struct nfs_server { + + unsigned long delegation_flags; + #define NFS4SERV_DELEGRETURN (1) ++#define NFS4SERV_DELEGATION_EXPIRED (2) + unsigned long delegation_gen; + unsigned long mig_gen; + unsigned long mig_status; +-- +2.39.5 + diff --git a/queue-6.14/nfsv4-avoid-unnecessary-scans-of-filesystems-for-ret.patch b/queue-6.14/nfsv4-avoid-unnecessary-scans-of-filesystems-for-ret.patch new file mode 100644 index 0000000000..f533c13ae3 --- /dev/null +++ b/queue-6.14/nfsv4-avoid-unnecessary-scans-of-filesystems-for-ret.patch @@ -0,0 +1,69 @@ +From a41df55372959244ea27825e4ebb903e0c4c4e36 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 18:14:26 -0500 +Subject: NFSv4: Avoid unnecessary scans of filesystems for returning + delegations + +From: Trond Myklebust + +[ Upstream commit 35a566a24e58f1b5f89737edf60b77de58719ed0 ] + +The amount of looping through the list of delegations is occasionally +leading to soft lockups. If the state manager was asked to return +delegations asynchronously, it should only scan those filesystems that +hold delegations that need to be returned. + +Fixes: af3b61bf6131 ("NFSv4: Clean up nfs_client_return_marked_delegations()") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/delegation.c | 5 +++++ + include/linux/nfs_fs_sb.h | 2 ++ + 2 files changed, 7 insertions(+) + +diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c +index df77d68d9ff99..d1f5e497729c3 100644 +--- a/fs/nfs/delegation.c ++++ b/fs/nfs/delegation.c +@@ -79,6 +79,7 @@ static void nfs_mark_return_delegation(struct nfs_server *server, + struct nfs_delegation *delegation) + { + set_bit(NFS_DELEGATION_RETURN, &delegation->flags); ++ set_bit(NFS4SERV_DELEGRETURN, &server->delegation_flags); + set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state); + } + +@@ -608,6 +609,9 @@ static int nfs_server_return_marked_delegations(struct nfs_server *server, + struct nfs_delegation *place_holder_deleg = NULL; + int err = 0; + ++ if (!test_and_clear_bit(NFS4SERV_DELEGRETURN, ++ &server->delegation_flags)) ++ return 0; + restart: + /* + * To avoid quadratic looping we hold a reference +@@ -659,6 +663,7 @@ static int nfs_server_return_marked_delegations(struct nfs_server *server, + cond_resched(); + if (!err) + goto restart; ++ set_bit(NFS4SERV_DELEGRETURN, &server->delegation_flags); + set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state); + goto out; + } +diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h +index f00bfcee7120e..4e9ad6f6e9073 100644 +--- a/include/linux/nfs_fs_sb.h ++++ b/include/linux/nfs_fs_sb.h +@@ -250,6 +250,8 @@ struct nfs_server { + struct list_head ss_copies; + struct list_head ss_src_copies; + ++ unsigned long delegation_flags; ++#define NFS4SERV_DELEGRETURN (1) + unsigned long delegation_gen; + unsigned long mig_gen; + unsigned long mig_status; +-- +2.39.5 + diff --git a/queue-6.14/nfsv4-don-t-trigger-uneccessary-scans-for-return-on-.patch b/queue-6.14/nfsv4-don-t-trigger-uneccessary-scans-for-return-on-.patch new file mode 100644 index 0000000000..65aa73c580 --- /dev/null +++ b/queue-6.14/nfsv4-don-t-trigger-uneccessary-scans-for-return-on-.patch @@ -0,0 +1,79 @@ +From e4f5cd400257ce90846acd83252b640d87a26ebd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 16:50:30 -0500 +Subject: NFSv4: Don't trigger uneccessary scans for return-on-close + delegations + +From: Trond Myklebust + +[ Upstream commit 47acca884f714f41d95dc654f802845544554784 ] + +The amount of looping through the list of delegations is occasionally +leading to soft lockups. Avoid at least some loops by not requiring the +NFSv4 state manager to scan for delegations that are marked for +return-on-close. Instead, either mark them for immediate return (if +possible) or else leave it up to nfs4_inode_return_delegation_on_close() +to return them once the file is closed by the application. + +Fixes: b757144fd77c ("NFSv4: Be less aggressive about returning delegations for open files") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/delegation.c | 33 ++++++++++++++++++--------------- + 1 file changed, 18 insertions(+), 15 deletions(-) + +diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c +index 4db912f562305..df77d68d9ff99 100644 +--- a/fs/nfs/delegation.c ++++ b/fs/nfs/delegation.c +@@ -590,17 +590,6 @@ static bool nfs_delegation_need_return(struct nfs_delegation *delegation) + + if (test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags)) + ret = true; +- else if (test_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags)) { +- struct inode *inode; +- +- spin_lock(&delegation->lock); +- inode = delegation->inode; +- if (inode && list_empty(&NFS_I(inode)->open_files)) +- ret = true; +- spin_unlock(&delegation->lock); +- } +- if (ret) +- clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags); + if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags) || + test_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags) || + test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) +@@ -878,11 +867,25 @@ int nfs4_inode_make_writeable(struct inode *inode) + return nfs4_inode_return_delegation(inode); + } + +-static void nfs_mark_return_if_closed_delegation(struct nfs_server *server, +- struct nfs_delegation *delegation) ++static void ++nfs_mark_return_if_closed_delegation(struct nfs_server *server, ++ struct nfs_delegation *delegation) + { +- set_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags); +- set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state); ++ struct inode *inode; ++ ++ if (test_bit(NFS_DELEGATION_RETURN, &delegation->flags) || ++ test_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags)) ++ return; ++ spin_lock(&delegation->lock); ++ inode = delegation->inode; ++ if (!inode) ++ goto out; ++ if (list_empty(&NFS_I(inode)->open_files)) ++ nfs_mark_return_delegation(server, delegation); ++ else ++ set_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags); ++out: ++ spin_unlock(&delegation->lock); + } + + static bool nfs_server_mark_return_all_delegations(struct nfs_server *server) +-- +2.39.5 + diff --git a/queue-6.14/ntb-intel-fix-using-link-status-db-s.patch b/queue-6.14/ntb-intel-fix-using-link-status-db-s.patch new file mode 100644 index 0000000000..86a97a40f9 --- /dev/null +++ b/queue-6.14/ntb-intel-fix-using-link-status-db-s.patch @@ -0,0 +1,37 @@ +From e406a898836f2d787ba8861993030ddec41d84bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Jun 2024 11:15:19 +0300 +Subject: ntb: intel: Fix using link status DB's + +From: Nikita Shubin + +[ Upstream commit 8144e9c8f30fb23bb736a5d24d5c9d46965563c4 ] + +Make sure we are not using DB's which were remapped for link status. + +Fixes: f6e51c354b60 ("ntb: intel: split out the gen3 code") +Signed-off-by: Nikita Shubin +Reviewed-by: Dave Jiang +Signed-off-by: Jon Mason +Signed-off-by: Sasha Levin +--- + drivers/ntb/hw/intel/ntb_hw_gen3.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/ntb/hw/intel/ntb_hw_gen3.c b/drivers/ntb/hw/intel/ntb_hw_gen3.c +index ffcfc3e02c353..a5aa96a31f4a6 100644 +--- a/drivers/ntb/hw/intel/ntb_hw_gen3.c ++++ b/drivers/ntb/hw/intel/ntb_hw_gen3.c +@@ -215,6 +215,9 @@ static int gen3_init_ntb(struct intel_ntb_dev *ndev) + } + + ndev->db_valid_mask = BIT_ULL(ndev->db_count) - 1; ++ /* Make sure we are not using DB's used for link status */ ++ if (ndev->hwerr_flags & NTB_HWERR_MSIX_VECTOR32_BAD) ++ ndev->db_valid_mask &= ~ndev->db_link_mask; + + ndev->reg->db_iowrite(ndev->db_valid_mask, + ndev->self_mmio + +-- +2.39.5 + diff --git a/queue-6.14/ntb_hw_switchtec-fix-shift-out-of-bounds-in-switchte.patch b/queue-6.14/ntb_hw_switchtec-fix-shift-out-of-bounds-in-switchte.patch new file mode 100644 index 0000000000..1ecb5e4827 --- /dev/null +++ b/queue-6.14/ntb_hw_switchtec-fix-shift-out-of-bounds-in-switchte.patch @@ -0,0 +1,45 @@ +From 90154437738305da7bb6e4d6ca12300f47d8286d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Aug 2023 16:33:05 +0800 +Subject: ntb_hw_switchtec: Fix shift-out-of-bounds in + switchtec_ntb_mw_set_trans + +From: Yajun Deng + +[ Upstream commit de203da734fae00e75be50220ba5391e7beecdf9 ] + +There is a kernel API ntb_mw_clear_trans() would pass 0 to both addr and +size. This would make xlate_pos negative. + +[ 23.734156] switchtec switchtec0: MW 0: part 0 addr 0x0000000000000000 size 0x0000000000000000 +[ 23.734158] ================================================================================ +[ 23.734172] UBSAN: shift-out-of-bounds in drivers/ntb/hw/mscc/ntb_hw_switchtec.c:293:7 +[ 23.734418] shift exponent -1 is negative + +Ensuring xlate_pos is a positive or zero before BIT. + +Fixes: 1e2fd202f859 ("ntb_hw_switchtec: Check for alignment of the buffer in mw_set_trans()") +Signed-off-by: Yajun Deng +Reviewed-by: Logan Gunthorpe +Signed-off-by: Jon Mason +Signed-off-by: Sasha Levin +--- + drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c +index ad1786be2554b..f851397b65d6e 100644 +--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c ++++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c +@@ -288,7 +288,7 @@ static int switchtec_ntb_mw_set_trans(struct ntb_dev *ntb, int pidx, int widx, + if (size != 0 && xlate_pos < 12) + return -EINVAL; + +- if (!IS_ALIGNED(addr, BIT_ULL(xlate_pos))) { ++ if (xlate_pos >= 0 && !IS_ALIGNED(addr, BIT_ULL(xlate_pos))) { + /* + * In certain circumstances we can get a buffer that is + * not aligned to its size. (Most of the time +-- +2.39.5 + diff --git a/queue-6.14/null_blk-do-partial-io-for-bad-blocks.patch b/queue-6.14/null_blk-do-partial-io-for-bad-blocks.patch new file mode 100644 index 0000000000..a8f6f40e81 --- /dev/null +++ b/queue-6.14/null_blk-do-partial-io-for-bad-blocks.patch @@ -0,0 +1,190 @@ +From 32000fec7c7f3a5b813eb3317e48ebd84d78ed75 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 19:06:13 +0900 +Subject: null_blk: do partial IO for bad blocks + +From: Shin'ichiro Kawasaki + +[ Upstream commit 567abc989e3c74c7f4e245492707208c37d27693 ] + +The current null_blk implementation checks if any bad blocks exist in +the target blocks of each IO. If so, the IO fails and data is not +transferred for all of the IO target blocks. However, when real storage +devices have bad blocks, the devices may transfer data partially up to +the first bad blocks (e.g., SAS drives). Especially, when the IO is a +write operation, such partial IO leaves partially written data on the +device. + +To simulate such partial IO using null_blk, introduce the new parameter +'badblocks_partial_io'. When this parameter is set, +null_handle_badblocks() returns the number of the sectors for the +partial IO as its third pointer argument. Pass the returned number of +sectors to the following calls to null_handle_memory_backend() in +null_process_cmd() and null_zone_write(). + +Reviewed-by: Damien Le Moal +Reviewed-by: Chaitanya Kulkarni +Reviewed-by: Johannes Thumshirn +Signed-off-by: Shin'ichiro Kawasaki +Link: https://lore.kernel.org/r/20250226100613.1622564-6-shinichiro.kawasaki@wdc.com +Signed-off-by: Jens Axboe +Stable-dep-of: d301f164c3fb ("badblocks: use sector_t instead of int to avoid truncation of badblocks length") +Signed-off-by: Sasha Levin +--- + drivers/block/null_blk/main.c | 40 ++++++++++++++++++++++++------- + drivers/block/null_blk/null_blk.h | 4 ++-- + drivers/block/null_blk/zoned.c | 9 ++++--- + 3 files changed, 40 insertions(+), 13 deletions(-) + +diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c +index b0b009b1136d5..cca278f1d2ce7 100644 +--- a/drivers/block/null_blk/main.c ++++ b/drivers/block/null_blk/main.c +@@ -474,6 +474,7 @@ NULLB_DEVICE_ATTR(shared_tag_bitmap, bool, NULL); + NULLB_DEVICE_ATTR(fua, bool, NULL); + NULLB_DEVICE_ATTR(rotational, bool, NULL); + NULLB_DEVICE_ATTR(badblocks_once, bool, NULL); ++NULLB_DEVICE_ATTR(badblocks_partial_io, bool, NULL); + + static ssize_t nullb_device_power_show(struct config_item *item, char *page) + { +@@ -595,6 +596,7 @@ CONFIGFS_ATTR_WO(nullb_device_, zone_offline); + static struct configfs_attribute *nullb_device_attrs[] = { + &nullb_device_attr_badblocks, + &nullb_device_attr_badblocks_once, ++ &nullb_device_attr_badblocks_partial_io, + &nullb_device_attr_blocking, + &nullb_device_attr_blocksize, + &nullb_device_attr_cache_size, +@@ -1309,19 +1311,40 @@ static inline blk_status_t null_handle_throttled(struct nullb_cmd *cmd) + return sts; + } + ++/* ++ * Check if the command should fail for the badblocks. If so, return ++ * BLK_STS_IOERR and return number of partial I/O sectors to be written or read, ++ * which may be less than the requested number of sectors. ++ * ++ * @cmd: The command to handle. ++ * @sector: The start sector for I/O. ++ * @nr_sectors: Specifies number of sectors to write or read, and returns the ++ * number of sectors to be written or read. ++ */ + blk_status_t null_handle_badblocks(struct nullb_cmd *cmd, sector_t sector, +- sector_t nr_sectors) ++ unsigned int *nr_sectors) + { + struct badblocks *bb = &cmd->nq->dev->badblocks; ++ struct nullb_device *dev = cmd->nq->dev; ++ unsigned int block_sectors = dev->blocksize >> SECTOR_SHIFT; + sector_t first_bad; + int bad_sectors; ++ unsigned int partial_io_sectors = 0; + +- if (!badblocks_check(bb, sector, nr_sectors, &first_bad, &bad_sectors)) ++ if (!badblocks_check(bb, sector, *nr_sectors, &first_bad, &bad_sectors)) + return BLK_STS_OK; + + if (cmd->nq->dev->badblocks_once) + badblocks_clear(bb, first_bad, bad_sectors); + ++ if (cmd->nq->dev->badblocks_partial_io) { ++ if (!IS_ALIGNED(first_bad, block_sectors)) ++ first_bad = ALIGN_DOWN(first_bad, block_sectors); ++ if (sector < first_bad) ++ partial_io_sectors = first_bad - sector; ++ } ++ *nr_sectors = partial_io_sectors; ++ + return BLK_STS_IOERR; + } + +@@ -1380,18 +1403,19 @@ blk_status_t null_process_cmd(struct nullb_cmd *cmd, enum req_op op, + sector_t sector, unsigned int nr_sectors) + { + struct nullb_device *dev = cmd->nq->dev; ++ blk_status_t badblocks_ret = BLK_STS_OK; + blk_status_t ret; + +- if (dev->badblocks.shift != -1) { +- ret = null_handle_badblocks(cmd, sector, nr_sectors); ++ if (dev->badblocks.shift != -1) ++ badblocks_ret = null_handle_badblocks(cmd, sector, &nr_sectors); ++ ++ if (dev->memory_backed && nr_sectors) { ++ ret = null_handle_memory_backed(cmd, op, sector, nr_sectors); + if (ret != BLK_STS_OK) + return ret; + } + +- if (dev->memory_backed) +- return null_handle_memory_backed(cmd, op, sector, nr_sectors); +- +- return BLK_STS_OK; ++ return badblocks_ret; + } + + static void null_handle_cmd(struct nullb_cmd *cmd, sector_t sector, +diff --git a/drivers/block/null_blk/null_blk.h b/drivers/block/null_blk/null_blk.h +index ee60f3a887967..7bb6128dbaafb 100644 +--- a/drivers/block/null_blk/null_blk.h ++++ b/drivers/block/null_blk/null_blk.h +@@ -64,6 +64,7 @@ struct nullb_device { + unsigned int curr_cache; + struct badblocks badblocks; + bool badblocks_once; ++ bool badblocks_partial_io; + + unsigned int nr_zones; + unsigned int nr_zones_imp_open; +@@ -133,11 +134,10 @@ blk_status_t null_handle_discard(struct nullb_device *dev, sector_t sector, + blk_status_t null_process_cmd(struct nullb_cmd *cmd, enum req_op op, + sector_t sector, unsigned int nr_sectors); + blk_status_t null_handle_badblocks(struct nullb_cmd *cmd, sector_t sector, +- sector_t nr_sectors); ++ unsigned int *nr_sectors); + blk_status_t null_handle_memory_backed(struct nullb_cmd *cmd, enum req_op op, + sector_t sector, sector_t nr_sectors); + +- + #ifdef CONFIG_BLK_DEV_ZONED + int null_init_zoned_dev(struct nullb_device *dev, struct queue_limits *lim); + int null_register_zoned_dev(struct nullb *nullb); +diff --git a/drivers/block/null_blk/zoned.c b/drivers/block/null_blk/zoned.c +index 7677f6cf23f46..4e5728f459899 100644 +--- a/drivers/block/null_blk/zoned.c ++++ b/drivers/block/null_blk/zoned.c +@@ -353,6 +353,7 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector, + struct nullb_device *dev = cmd->nq->dev; + unsigned int zno = null_zone_no(dev, sector); + struct nullb_zone *zone = &dev->zones[zno]; ++ blk_status_t badblocks_ret = BLK_STS_OK; + blk_status_t ret; + + trace_nullb_zone_op(cmd, zno, zone->cond); +@@ -413,9 +414,11 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector, + } + + if (dev->badblocks.shift != -1) { +- ret = null_handle_badblocks(cmd, sector, nr_sectors); +- if (ret != BLK_STS_OK) ++ badblocks_ret = null_handle_badblocks(cmd, sector, &nr_sectors); ++ if (badblocks_ret != BLK_STS_OK && !nr_sectors) { ++ ret = badblocks_ret; + goto unlock_zone; ++ } + } + + if (dev->memory_backed) { +@@ -438,7 +441,7 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector, + zone->cond = BLK_ZONE_COND_FULL; + } + +- ret = BLK_STS_OK; ++ ret = badblocks_ret; + + unlock_zone: + null_unlock_zone(dev, zone); +-- +2.39.5 + diff --git a/queue-6.14/null_blk-generate-null_blk-configfs-features-string.patch b/queue-6.14/null_blk-generate-null_blk-configfs-features-string.patch new file mode 100644 index 0000000000..dd91c34f7b --- /dev/null +++ b/queue-6.14/null_blk-generate-null_blk-configfs-features-string.patch @@ -0,0 +1,152 @@ +From 1a23a8372e02346183b027cf5a4939d7e19a961c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 19:06:09 +0900 +Subject: null_blk: generate null_blk configfs features string + +From: Shin'ichiro Kawasaki + +[ Upstream commit 2cadb8ef25a6157b5bd3e8fe0d3e23f32defec25 ] + +The null_blk configfs file 'features' provides a string that lists +available null_blk features for userspace programs to reference. +The string is defined as a long constant in the code, which tends to be +forgotten for updates. It also causes checkpatch.pl to report +"WARNING: quoted string split across lines". + +To avoid these drawbacks, generate the feature string on the fly. Refer +to the ca_name field of each element in the nullb_device_attrs table and +concatenate them in the given buffer. Also, sorted nullb_device_attrs +table elements in alphabetical order. + +Of note is that the feature "index" was missing before this commit. +This commit adds it to the generated string. + +Suggested-by: Bart Van Assche +Reviewed-by: Bart Van Assche +Reviewed-by: Damien Le Moal +Reviewed-by: Chaitanya Kulkarni +Reviewed-by: Johannes Thumshirn +Signed-off-by: Shin'ichiro Kawasaki +Link: https://lore.kernel.org/r/20250226100613.1622564-2-shinichiro.kawasaki@wdc.com +Signed-off-by: Jens Axboe +Stable-dep-of: d301f164c3fb ("badblocks: use sector_t instead of int to avoid truncation of badblocks length") +Signed-off-by: Sasha Levin +--- + drivers/block/null_blk/main.c | 86 ++++++++++++++++++++--------------- + 1 file changed, 49 insertions(+), 37 deletions(-) + +diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c +index fdc7a0b2af109..18520d0e38c61 100644 +--- a/drivers/block/null_blk/main.c ++++ b/drivers/block/null_blk/main.c +@@ -592,41 +592,41 @@ static ssize_t nullb_device_zone_offline_store(struct config_item *item, + CONFIGFS_ATTR_WO(nullb_device_, zone_offline); + + static struct configfs_attribute *nullb_device_attrs[] = { +- &nullb_device_attr_size, ++ &nullb_device_attr_badblocks, ++ &nullb_device_attr_blocking, ++ &nullb_device_attr_blocksize, ++ &nullb_device_attr_cache_size, + &nullb_device_attr_completion_nsec, +- &nullb_device_attr_submit_queues, +- &nullb_device_attr_poll_queues, ++ &nullb_device_attr_discard, ++ &nullb_device_attr_fua, + &nullb_device_attr_home_node, +- &nullb_device_attr_queue_mode, +- &nullb_device_attr_blocksize, +- &nullb_device_attr_max_sectors, +- &nullb_device_attr_irqmode, + &nullb_device_attr_hw_queue_depth, + &nullb_device_attr_index, +- &nullb_device_attr_blocking, +- &nullb_device_attr_use_per_node_hctx, +- &nullb_device_attr_power, +- &nullb_device_attr_memory_backed, +- &nullb_device_attr_discard, ++ &nullb_device_attr_irqmode, ++ &nullb_device_attr_max_sectors, + &nullb_device_attr_mbps, +- &nullb_device_attr_cache_size, +- &nullb_device_attr_badblocks, +- &nullb_device_attr_zoned, +- &nullb_device_attr_zone_size, ++ &nullb_device_attr_memory_backed, ++ &nullb_device_attr_no_sched, ++ &nullb_device_attr_poll_queues, ++ &nullb_device_attr_power, ++ &nullb_device_attr_queue_mode, ++ &nullb_device_attr_rotational, ++ &nullb_device_attr_shared_tag_bitmap, ++ &nullb_device_attr_shared_tags, ++ &nullb_device_attr_size, ++ &nullb_device_attr_submit_queues, ++ &nullb_device_attr_use_per_node_hctx, ++ &nullb_device_attr_virt_boundary, ++ &nullb_device_attr_zone_append_max_sectors, + &nullb_device_attr_zone_capacity, +- &nullb_device_attr_zone_nr_conv, +- &nullb_device_attr_zone_max_open, ++ &nullb_device_attr_zone_full, + &nullb_device_attr_zone_max_active, +- &nullb_device_attr_zone_append_max_sectors, +- &nullb_device_attr_zone_readonly, ++ &nullb_device_attr_zone_max_open, ++ &nullb_device_attr_zone_nr_conv, + &nullb_device_attr_zone_offline, +- &nullb_device_attr_zone_full, +- &nullb_device_attr_virt_boundary, +- &nullb_device_attr_no_sched, +- &nullb_device_attr_shared_tags, +- &nullb_device_attr_shared_tag_bitmap, +- &nullb_device_attr_fua, +- &nullb_device_attr_rotational, ++ &nullb_device_attr_zone_readonly, ++ &nullb_device_attr_zone_size, ++ &nullb_device_attr_zoned, + NULL, + }; + +@@ -704,16 +704,28 @@ nullb_group_drop_item(struct config_group *group, struct config_item *item) + + static ssize_t memb_group_features_show(struct config_item *item, char *page) + { +- return snprintf(page, PAGE_SIZE, +- "badblocks,blocking,blocksize,cache_size,fua," +- "completion_nsec,discard,home_node,hw_queue_depth," +- "irqmode,max_sectors,mbps,memory_backed,no_sched," +- "poll_queues,power,queue_mode,shared_tag_bitmap," +- "shared_tags,size,submit_queues,use_per_node_hctx," +- "virt_boundary,zoned,zone_capacity,zone_max_active," +- "zone_max_open,zone_nr_conv,zone_offline,zone_readonly," +- "zone_size,zone_append_max_sectors,zone_full," +- "rotational\n"); ++ ++ struct configfs_attribute **entry; ++ char delimiter = ','; ++ size_t left = PAGE_SIZE; ++ size_t written = 0; ++ int ret; ++ ++ for (entry = &nullb_device_attrs[0]; *entry && left > 0; entry++) { ++ if (!*(entry + 1)) ++ delimiter = '\n'; ++ ret = snprintf(page + written, left, "%s%c", (*entry)->ca_name, ++ delimiter); ++ if (ret >= left) { ++ WARN_ONCE(1, "Too many null_blk features to print\n"); ++ memzero_explicit(page, PAGE_SIZE); ++ return -ENOBUFS; ++ } ++ left -= ret; ++ written += ret; ++ } ++ ++ return written; + } + + CONFIGFS_ATTR_RO(memb_group_, features); +-- +2.39.5 + diff --git a/queue-6.14/null_blk-introduce-badblocks_once-parameter.patch b/queue-6.14/null_blk-introduce-badblocks_once-parameter.patch new file mode 100644 index 0000000000..effc950964 --- /dev/null +++ b/queue-6.14/null_blk-introduce-badblocks_once-parameter.patch @@ -0,0 +1,81 @@ +From 275d2fac17595f39a6998537703606dead1e9481 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 19:06:10 +0900 +Subject: null_blk: introduce badblocks_once parameter + +From: Shin'ichiro Kawasaki + +[ Upstream commit 800c24391676143695d284f70af297b28a809886 ] + +When IO errors happen on real storage devices, the IOs repeated to the +same target range can success by virtue of recovery features by devices, +such as reserved block assignment. To simulate such IO errors and +recoveries, introduce the new parameter badblocks_once parameter. When +this parameter is set to 1, the specified badblocks are cleared after +the first IO error, so that the next IO to the blocks succeed. + +Reviewed-by: Damien Le Moal +Reviewed-by: Chaitanya Kulkarni +Reviewed-by: Johannes Thumshirn +Signed-off-by: Shin'ichiro Kawasaki +Link: https://lore.kernel.org/r/20250226100613.1622564-3-shinichiro.kawasaki@wdc.com +Signed-off-by: Jens Axboe +Stable-dep-of: d301f164c3fb ("badblocks: use sector_t instead of int to avoid truncation of badblocks length") +Signed-off-by: Sasha Levin +--- + drivers/block/null_blk/main.c | 11 ++++++++--- + drivers/block/null_blk/null_blk.h | 1 + + 2 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c +index 18520d0e38c61..164c62f20f109 100644 +--- a/drivers/block/null_blk/main.c ++++ b/drivers/block/null_blk/main.c +@@ -473,6 +473,7 @@ NULLB_DEVICE_ATTR(shared_tags, bool, NULL); + NULLB_DEVICE_ATTR(shared_tag_bitmap, bool, NULL); + NULLB_DEVICE_ATTR(fua, bool, NULL); + NULLB_DEVICE_ATTR(rotational, bool, NULL); ++NULLB_DEVICE_ATTR(badblocks_once, bool, NULL); + + static ssize_t nullb_device_power_show(struct config_item *item, char *page) + { +@@ -593,6 +594,7 @@ CONFIGFS_ATTR_WO(nullb_device_, zone_offline); + + static struct configfs_attribute *nullb_device_attrs[] = { + &nullb_device_attr_badblocks, ++ &nullb_device_attr_badblocks_once, + &nullb_device_attr_blocking, + &nullb_device_attr_blocksize, + &nullb_device_attr_cache_size, +@@ -1315,10 +1317,13 @@ static inline blk_status_t null_handle_badblocks(struct nullb_cmd *cmd, + sector_t first_bad; + int bad_sectors; + +- if (badblocks_check(bb, sector, nr_sectors, &first_bad, &bad_sectors)) +- return BLK_STS_IOERR; ++ if (!badblocks_check(bb, sector, nr_sectors, &first_bad, &bad_sectors)) ++ return BLK_STS_OK; + +- return BLK_STS_OK; ++ if (cmd->nq->dev->badblocks_once) ++ badblocks_clear(bb, first_bad, bad_sectors); ++ ++ return BLK_STS_IOERR; + } + + static inline blk_status_t null_handle_memory_backed(struct nullb_cmd *cmd, +diff --git a/drivers/block/null_blk/null_blk.h b/drivers/block/null_blk/null_blk.h +index 6f9fe61710870..3c4c07f0418b0 100644 +--- a/drivers/block/null_blk/null_blk.h ++++ b/drivers/block/null_blk/null_blk.h +@@ -63,6 +63,7 @@ struct nullb_device { + unsigned long flags; /* device flags */ + unsigned int curr_cache; + struct badblocks badblocks; ++ bool badblocks_once; + + unsigned int nr_zones; + unsigned int nr_zones_imp_open; +-- +2.39.5 + diff --git a/queue-6.14/null_blk-replace-null_process_cmd-call-in-null_zone_.patch b/queue-6.14/null_blk-replace-null_process_cmd-call-in-null_zone_.patch new file mode 100644 index 0000000000..a7c0a6f980 --- /dev/null +++ b/queue-6.14/null_blk-replace-null_process_cmd-call-in-null_zone_.patch @@ -0,0 +1,103 @@ +From 79be7fe7f31f9ae02a9eeb31f6ac2087f256ad78 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 19:06:11 +0900 +Subject: null_blk: replace null_process_cmd() call in null_zone_write() + +From: Shin'ichiro Kawasaki + +[ Upstream commit 4f235000b1e88934d1e6117dc43ed814710ef4e2 ] + +As a preparation to support partial data transfer due to badblocks, +replace the null_process_cmd() call in null_zone_write() with equivalent +calls to null_handle_badblocks() and null_handle_memory_backed(). This +commit does not change behavior. It will enable null_handle_badblocks() +to return the size of partial data transfer in the following commit, +allowing null_zone_write() to move write pointers appropriately. + +Reviewed-by: Damien Le Moal +Reviewed-by: Johannes Thumshirn +Signed-off-by: Shin'ichiro Kawasaki +Link: https://lore.kernel.org/r/20250226100613.1622564-4-shinichiro.kawasaki@wdc.com +Signed-off-by: Jens Axboe +Stable-dep-of: d301f164c3fb ("badblocks: use sector_t instead of int to avoid truncation of badblocks length") +Signed-off-by: Sasha Levin +--- + drivers/block/null_blk/main.c | 11 ++++------- + drivers/block/null_blk/null_blk.h | 5 +++++ + drivers/block/null_blk/zoned.c | 15 ++++++++++++--- + 3 files changed, 21 insertions(+), 10 deletions(-) + +diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c +index 164c62f20f109..b0b009b1136d5 100644 +--- a/drivers/block/null_blk/main.c ++++ b/drivers/block/null_blk/main.c +@@ -1309,9 +1309,8 @@ static inline blk_status_t null_handle_throttled(struct nullb_cmd *cmd) + return sts; + } + +-static inline blk_status_t null_handle_badblocks(struct nullb_cmd *cmd, +- sector_t sector, +- sector_t nr_sectors) ++blk_status_t null_handle_badblocks(struct nullb_cmd *cmd, sector_t sector, ++ sector_t nr_sectors) + { + struct badblocks *bb = &cmd->nq->dev->badblocks; + sector_t first_bad; +@@ -1326,10 +1325,8 @@ static inline blk_status_t null_handle_badblocks(struct nullb_cmd *cmd, + return BLK_STS_IOERR; + } + +-static inline blk_status_t null_handle_memory_backed(struct nullb_cmd *cmd, +- enum req_op op, +- sector_t sector, +- sector_t nr_sectors) ++blk_status_t null_handle_memory_backed(struct nullb_cmd *cmd, enum req_op op, ++ sector_t sector, sector_t nr_sectors) + { + struct nullb_device *dev = cmd->nq->dev; + +diff --git a/drivers/block/null_blk/null_blk.h b/drivers/block/null_blk/null_blk.h +index 3c4c07f0418b0..ee60f3a887967 100644 +--- a/drivers/block/null_blk/null_blk.h ++++ b/drivers/block/null_blk/null_blk.h +@@ -132,6 +132,11 @@ blk_status_t null_handle_discard(struct nullb_device *dev, sector_t sector, + sector_t nr_sectors); + blk_status_t null_process_cmd(struct nullb_cmd *cmd, enum req_op op, + sector_t sector, unsigned int nr_sectors); ++blk_status_t null_handle_badblocks(struct nullb_cmd *cmd, sector_t sector, ++ sector_t nr_sectors); ++blk_status_t null_handle_memory_backed(struct nullb_cmd *cmd, enum req_op op, ++ sector_t sector, sector_t nr_sectors); ++ + + #ifdef CONFIG_BLK_DEV_ZONED + int null_init_zoned_dev(struct nullb_device *dev, struct queue_limits *lim); +diff --git a/drivers/block/null_blk/zoned.c b/drivers/block/null_blk/zoned.c +index 0d5f9bf952292..7677f6cf23f46 100644 +--- a/drivers/block/null_blk/zoned.c ++++ b/drivers/block/null_blk/zoned.c +@@ -412,9 +412,18 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector, + zone->cond = BLK_ZONE_COND_IMP_OPEN; + } + +- ret = null_process_cmd(cmd, REQ_OP_WRITE, sector, nr_sectors); +- if (ret != BLK_STS_OK) +- goto unlock_zone; ++ if (dev->badblocks.shift != -1) { ++ ret = null_handle_badblocks(cmd, sector, nr_sectors); ++ if (ret != BLK_STS_OK) ++ goto unlock_zone; ++ } ++ ++ if (dev->memory_backed) { ++ ret = null_handle_memory_backed(cmd, REQ_OP_WRITE, sector, ++ nr_sectors); ++ if (ret != BLK_STS_OK) ++ goto unlock_zone; ++ } + + zone->wp += nr_sectors; + if (zone->wp == zone->start + zone->capacity) { +-- +2.39.5 + diff --git a/queue-6.14/nvme-ioctl-don-t-warn-on-vectorized-uring_cmd-with-f.patch b/queue-6.14/nvme-ioctl-don-t-warn-on-vectorized-uring_cmd-with-f.patch new file mode 100644 index 0000000000..b68716b75e --- /dev/null +++ b/queue-6.14/nvme-ioctl-don-t-warn-on-vectorized-uring_cmd-with-f.patch @@ -0,0 +1,40 @@ +From 513c59d1806253c6907c9c81c4cf60afd01a61de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Mar 2025 09:46:45 -0600 +Subject: nvme/ioctl: don't warn on vectorized uring_cmd with fixed buffer + +From: Caleb Sander Mateos + +[ Upstream commit eada75467fca0b016b9b22212637c07216135c20 ] + +The vectorized io_uring NVMe passthru opcodes don't yet support fixed +buffers. But since userspace can trigger this condition based on the +io_uring SQE parameters, it shouldn't cause a kernel warning. + +Signed-off-by: Caleb Sander Mateos +Reviewed-by: Jens Axboe +Reviewed-by: Chaitanya Kulkarni +Reviewed-by: Christoph Hellwig +Fixes: 23fd22e55b76 ("nvme: wire up fixed buffer support for nvme passthrough") +Signed-off-by: Keith Busch +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 24e2c702da7a2..fed6b29098ad3 100644 +--- a/drivers/nvme/host/ioctl.c ++++ b/drivers/nvme/host/ioctl.c +@@ -141,7 +141,7 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer, + struct iov_iter iter; + + /* fixedbufs is only for non-vectored io */ +- if (WARN_ON_ONCE(flags & NVME_IOCTL_VEC)) { ++ if (flags & NVME_IOCTL_VEC) { + ret = -EINVAL; + goto out; + } +-- +2.39.5 + diff --git a/queue-6.14/nvme-pci-skip-nvme_write_sq_db-on-empty-rqlist.patch b/queue-6.14/nvme-pci-skip-nvme_write_sq_db-on-empty-rqlist.patch new file mode 100644 index 0000000000..a1665761b5 --- /dev/null +++ b/queue-6.14/nvme-pci-skip-nvme_write_sq_db-on-empty-rqlist.patch @@ -0,0 +1,37 @@ +From e07f23eb7b103eb25132b2a01a2816401132a179 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Mar 2025 18:28:59 +0200 +Subject: nvme-pci: skip nvme_write_sq_db on empty rqlist + +From: Maurizio Lombardi + +[ Upstream commit 288ff0d10beb069355036355d5f7612579dc869c ] + +nvme_submit_cmds() should check the rqlist before calling +nvme_write_sq_db(); if the list is empty, it must return immediately. + +Fixes: beadf0088501 ("nvme-pci: reverse request order in nvme_queue_rqs") +Signed-off-by: Maurizio Lombardi +Signed-off-by: Keith Busch +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 3ad7f197c8087..1dc12784efafc 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -989,6 +989,9 @@ static void nvme_submit_cmds(struct nvme_queue *nvmeq, struct rq_list *rqlist) + { + struct request *req; + ++ if (rq_list_empty(rqlist)) ++ return; ++ + spin_lock(&nvmeq->sq_lock); + while ((req = rq_list_pop(rqlist))) { + struct nvme_iod *iod = blk_mq_rq_to_pdu(req); +-- +2.39.5 + diff --git a/queue-6.14/nvmet-pci-epf-always-configure-bar0-as-64-bit.patch b/queue-6.14/nvmet-pci-epf-always-configure-bar0-as-64-bit.patch new file mode 100644 index 0000000000..e34b27ecb3 --- /dev/null +++ b/queue-6.14/nvmet-pci-epf-always-configure-bar0-as-64-bit.patch @@ -0,0 +1,61 @@ +From 90bd6773db3fc58c1bd4d6ed42ec1eb0382b12c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 10:57:04 +0100 +Subject: nvmet: pci-epf: Always configure BAR0 as 64-bit + +From: Niklas Cassel + +[ Upstream commit 1cf0184c0ac4f1e936bb3b089894bbeb0a9eb2bc ] + +NVMe PCIe Transport Specification 1.1, section 2.1.10, claims that the +BAR0 type is Implementation Specific. + +However, in NVMe 1.1, the type is required to be 64-bit. + +Thus, to make our PCI EPF work on as many host systems as possible, +always configure the BAR0 type to be 64-bit. + +In the rare case that the underlying PCI EPC does not support configuring +BAR0 as 64-bit, the call to pci_epc_set_bar() will fail, and we will +return a failure back to the user. + +This should not be a problem, as most PCI EPCs support configuring a BAR +as 64-bit (and those EPCs with .only_64bit set to true in epc_features +only support configuring the BAR as 64-bit). + +Tested-by: Damien Le Moal +Fixes: 0faa0fe6f90e ("nvmet: New NVMe PCI endpoint function target driver") +Signed-off-by: Niklas Cassel +Reviewed-by: Christoph Hellwig +Reviewed-by: Chaitanya Kulkarni +Signed-off-by: Keith Busch +Signed-off-by: Sasha Levin +--- + drivers/nvme/target/pci-epf.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c +index b1e31483f1574..99563648c318f 100644 +--- a/drivers/nvme/target/pci-epf.c ++++ b/drivers/nvme/target/pci-epf.c +@@ -2129,8 +2129,15 @@ static int nvmet_pci_epf_configure_bar(struct nvmet_pci_epf *nvme_epf) + return -ENODEV; + } + +- if (epc_features->bar[BAR_0].only_64bit) +- epf->bar[BAR_0].flags |= PCI_BASE_ADDRESS_MEM_TYPE_64; ++ /* ++ * While NVMe PCIe Transport Specification 1.1, section 2.1.10, claims ++ * that the BAR0 type is Implementation Specific, in NVMe 1.1, the type ++ * is required to be 64-bit. Thus, for interoperability, always set the ++ * type to 64-bit. In the rare case that the PCI EPC does not support ++ * configuring BAR0 as 64-bit, the call to pci_epc_set_bar() will fail, ++ * and we will return failure back to the user. ++ */ ++ epf->bar[BAR_0].flags |= PCI_BASE_ADDRESS_MEM_TYPE_64; + + /* + * Calculate the size of the register bar: NVMe registers first with +-- +2.39.5 + diff --git a/queue-6.14/objtool-fix-detection-of-consecutive-jump-tables-on-.patch b/queue-6.14/objtool-fix-detection-of-consecutive-jump-tables-on-.patch new file mode 100644 index 0000000000..ba77384878 --- /dev/null +++ b/queue-6.14/objtool-fix-detection-of-consecutive-jump-tables-on-.patch @@ -0,0 +1,188 @@ +From c7329abf977f548041d034092851340b7a102b34 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 14:55:51 -0700 +Subject: objtool: Fix detection of consecutive jump tables on Clang 20 + +From: Josh Poimboeuf + +[ Upstream commit ef753d66051ca03bee1982ce047f9eaf90f81ab4 ] + +The jump table detection code assumes jump tables are in the same order +as their corresponding indirect branches. That's apparently not always +true with Clang 20. + +Fix that by changing how multiple jump tables are detected. In the +first detection pass, mark the beginning of each jump table so the +second pass can tell where one ends and the next one begins. + +Fixes the following warnings: + + vmlinux.o: warning: objtool: SiS_GetCRT2Ptr+0x1ad: stack state mismatch: cfa1=4+8 cfa2=5+16 + sound/core/seq/snd-seq.o: warning: objtool: cc_ev_to_ump_midi2+0x589: return with modified stack frame + +Fixes: be2f0b1e1264 ("objtool: Get rid of reloc->jump_table_start") +Reported-by: kernel test robot +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Cc: Nathan Chancellor +Cc: Nick Desaulniers +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/141752fff614eab962dba6bdfaa54aa67ff03bba.1742852846.git.jpoimboe@kernel.org +Closes: https://lore.kernel.org/oe-kbuild-all/202503171547.LlCTJLQL-lkp@intel.com/ +Closes: https://lore.kernel.org/oe-kbuild-all/202503200535.J3hAvcjw-lkp@intel.com/ +Signed-off-by: Sasha Levin +--- + tools/objtool/check.c | 26 ++++++++------------------ + tools/objtool/elf.c | 6 +++--- + tools/objtool/include/objtool/elf.h | 27 ++++++++++++++++++++++++++- + 3 files changed, 37 insertions(+), 22 deletions(-) + +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index 12bf6c1f5071d..813e708c16499 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -1949,8 +1949,7 @@ __weak unsigned long arch_jump_table_sym_offset(struct reloc *reloc, struct relo + return reloc->sym->offset + reloc_addend(reloc); + } + +-static int add_jump_table(struct objtool_file *file, struct instruction *insn, +- struct reloc *next_table) ++static int add_jump_table(struct objtool_file *file, struct instruction *insn) + { + unsigned long table_size = insn_jump_table_size(insn); + struct symbol *pfunc = insn_func(insn)->pfunc; +@@ -1970,7 +1969,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn, + /* Check for the end of the table: */ + if (table_size && reloc_offset(reloc) - reloc_offset(table) >= table_size) + break; +- if (reloc != table && reloc == next_table) ++ if (reloc != table && is_jump_table(reloc)) + break; + + /* Make sure the table entries are consecutive: */ +@@ -2061,8 +2060,10 @@ static void find_jump_table(struct objtool_file *file, struct symbol *func, + if (!dest_insn || !insn_func(dest_insn) || insn_func(dest_insn)->pfunc != func) + continue; + ++ set_jump_table(table_reloc); + orig_insn->_jump_table = table_reloc; + orig_insn->_jump_table_size = table_size; ++ + break; + } + } +@@ -2104,31 +2105,20 @@ static void mark_func_jump_tables(struct objtool_file *file, + static int add_func_jump_tables(struct objtool_file *file, + struct symbol *func) + { +- struct instruction *insn, *insn_t1 = NULL, *insn_t2; +- int ret = 0; ++ struct instruction *insn; ++ int ret; + + func_for_each_insn(file, func, insn) { + if (!insn_jump_table(insn)) + continue; + +- if (!insn_t1) { +- insn_t1 = insn; +- continue; +- } +- +- insn_t2 = insn; + +- ret = add_jump_table(file, insn_t1, insn_jump_table(insn_t2)); ++ ret = add_jump_table(file, insn); + if (ret) + return ret; +- +- insn_t1 = insn_t2; + } + +- if (insn_t1) +- ret = add_jump_table(file, insn_t1, NULL); +- +- return ret; ++ return 0; + } + + /* +diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c +index 6f64d611faea9..934855be631c0 100644 +--- a/tools/objtool/elf.c ++++ b/tools/objtool/elf.c +@@ -583,7 +583,7 @@ static int elf_update_sym_relocs(struct elf *elf, struct symbol *sym) + { + struct reloc *reloc; + +- for (reloc = sym->relocs; reloc; reloc = reloc->sym_next_reloc) ++ for (reloc = sym->relocs; reloc; reloc = sym_next_reloc(reloc)) + set_reloc_sym(elf, reloc, reloc->sym->idx); + + return 0; +@@ -880,7 +880,7 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec, + set_reloc_addend(elf, reloc, addend); + + elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc)); +- reloc->sym_next_reloc = sym->relocs; ++ set_sym_next_reloc(reloc, sym->relocs); + sym->relocs = reloc; + + return reloc; +@@ -979,7 +979,7 @@ static int read_relocs(struct elf *elf) + } + + elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc)); +- reloc->sym_next_reloc = sym->relocs; ++ set_sym_next_reloc(reloc, sym->relocs); + sym->relocs = reloc; + + nr_reloc++; +diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h +index d7e815c2fd156..764cba535f22e 100644 +--- a/tools/objtool/include/objtool/elf.h ++++ b/tools/objtool/include/objtool/elf.h +@@ -77,7 +77,7 @@ struct reloc { + struct elf_hash_node hash; + struct section *sec; + struct symbol *sym; +- struct reloc *sym_next_reloc; ++ unsigned long _sym_next_reloc; + }; + + struct elf { +@@ -297,6 +297,31 @@ static inline void set_reloc_type(struct elf *elf, struct reloc *reloc, unsigned + mark_sec_changed(elf, reloc->sec, true); + } + ++#define RELOC_JUMP_TABLE_BIT 1UL ++ ++/* Does reloc mark the beginning of a jump table? */ ++static inline bool is_jump_table(struct reloc *reloc) ++{ ++ return reloc->_sym_next_reloc & RELOC_JUMP_TABLE_BIT; ++} ++ ++static inline void set_jump_table(struct reloc *reloc) ++{ ++ reloc->_sym_next_reloc |= RELOC_JUMP_TABLE_BIT; ++} ++ ++static inline struct reloc *sym_next_reloc(struct reloc *reloc) ++{ ++ return (struct reloc *)(reloc->_sym_next_reloc & ~RELOC_JUMP_TABLE_BIT); ++} ++ ++static inline void set_sym_next_reloc(struct reloc *reloc, struct reloc *next) ++{ ++ unsigned long bit = reloc->_sym_next_reloc & RELOC_JUMP_TABLE_BIT; ++ ++ reloc->_sym_next_reloc = (unsigned long)next | bit; ++} ++ + #define for_each_sec(file, sec) \ + list_for_each_entry(sec, &file->elf->sections, list) + +-- +2.39.5 + diff --git a/queue-6.14/objtool-fix-segfault-in-ignore_unreachable_insn.patch b/queue-6.14/objtool-fix-segfault-in-ignore_unreachable_insn.patch new file mode 100644 index 0000000000..9ae552fab4 --- /dev/null +++ b/queue-6.14/objtool-fix-segfault-in-ignore_unreachable_insn.patch @@ -0,0 +1,41 @@ +From fa7361d986866a83ee808332e2f4e76b1bb7b062 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Mar 2025 22:04:21 -0700 +Subject: objtool: Fix segfault in ignore_unreachable_insn() + +From: Josh Poimboeuf + +[ Upstream commit 69d41d6dafff0967565b971d950bd10443e4076c ] + +Check 'prev_insn' before dereferencing it. + +Fixes: bd841d6154f5 ("objtool: Fix CONFIG_UBSAN_TRAP unreachable warnings") +Reported-by: Arnd Bergmann +Reported-by: Ingo Molnar +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Link: https://lore.kernel.org/r/5df4ff89c9e4b9e788b77b0531234ffa7ba03e9e.1743136205.git.jpoimboe@kernel.org + +Closes: https://lore.kernel.org/d86b4cc6-0b97-4095-8793-a7384410b8ab@app.fastmail.com +Closes: https://lore.kernel.org/Z-V_rruKY0-36pqA@gmail.com +Signed-off-by: Sasha Levin +--- + tools/objtool/check.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index 813e708c16499..aa071017c325c 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -4009,7 +4009,7 @@ static bool ignore_unreachable_insn(struct objtool_file *file, struct instructio + * It may also insert a UD2 after calling a __noreturn function. + */ + prev_insn = prev_insn_same_sec(file, insn); +- if (prev_insn->dead_end && ++ if (prev_insn && prev_insn->dead_end && + (insn->type == INSN_BUG || + (insn->type == INSN_JUMP_UNCONDITIONAL && + insn->jump_dest && insn->jump_dest->type == INSN_BUG))) +-- +2.39.5 + diff --git a/queue-6.14/objtool-fix-verbose-disassembly-if-cross_compile-isn.patch b/queue-6.14/objtool-fix-verbose-disassembly-if-cross_compile-isn.patch new file mode 100644 index 0000000000..6e0a60a6df --- /dev/null +++ b/queue-6.14/objtool-fix-verbose-disassembly-if-cross_compile-isn.patch @@ -0,0 +1,46 @@ +From c868f5d2c496c5e00d49eca4279e8edaa40ca874 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Mar 2025 21:26:42 -0700 +Subject: objtool: Fix verbose disassembly if CROSS_COMPILE isn't set + +From: David Laight + +[ Upstream commit e77956e4e5c11218e60a1fe8cdbccd02476f2e56 ] + +In verbose mode, when printing the disassembly of affected functions, if +CROSS_COMPILE isn't set, the objdump command string gets prefixed with +"(null)". + +Somehow this worked before. Maybe some versions of glibc return an +empty string instead of NULL. Fix it regardless. + +[ jpoimboe: Rewrite commit log. ] + +Fixes: ca653464dd097 ("objtool: Add verbose option for disassembling affected functions") +Signed-off-by: David Laight +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/20250215142321.14081-1-david.laight.linux@gmail.com +Link: https://lore.kernel.org/r/b931a4786bc0127aa4c94e8b35ed617dcbd3d3da.1743481539.git.jpoimboe@kernel.org +Signed-off-by: Sasha Levin +--- + tools/objtool/check.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index aa071017c325c..159fb130e2827 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -4489,6 +4489,8 @@ static int disas_funcs(const char *funcs) + char *cmd; + + cross_compile = getenv("CROSS_COMPILE"); ++ if (!cross_compile) ++ cross_compile = ""; + + objdump_str = "%sobjdump -wdr %s | gawk -M -v _funcs='%s' '" + "BEGIN { split(_funcs, funcs); }" +-- +2.39.5 + diff --git a/queue-6.14/objtool-handle-different-entry-size-of-rodata.patch b/queue-6.14/objtool-handle-different-entry-size-of-rodata.patch new file mode 100644 index 0000000000..dd4c4d6d71 --- /dev/null +++ b/queue-6.14/objtool-handle-different-entry-size-of-rodata.patch @@ -0,0 +1,119 @@ +From a5960469e972944f694526a3fc7677cdb480c83f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 19:50:11 +0800 +Subject: objtool: Handle different entry size of rodata + +From: Tiezhu Yang + +[ Upstream commit 091bf313f8a852a7f30c3a8dcef569edfd06f5dc ] + +In the most cases, the entry size of rodata is 8 bytes because the +relocation type is 64 bit. There are also 32 bit relocation types, +the entry size of rodata should be 4 bytes in this case. + +Add an arch-specific function arch_reloc_size() to assign the entry +size of rodata for x86, powerpc and LoongArch. + +Signed-off-by: Tiezhu Yang +Link: https://lore.kernel.org/r/20250211115016.26913-3-yangtiezhu@loongson.cn +Acked-by: Huacai Chen +Signed-off-by: Josh Poimboeuf +Stable-dep-of: ef753d66051c ("objtool: Fix detection of consecutive jump tables on Clang 20") +Signed-off-by: Sasha Levin +--- + tools/objtool/arch/loongarch/decode.c | 11 +++++++++++ + tools/objtool/arch/powerpc/decode.c | 14 ++++++++++++++ + tools/objtool/arch/x86/decode.c | 13 +++++++++++++ + tools/objtool/check.c | 2 +- + tools/objtool/include/objtool/arch.h | 2 ++ + 5 files changed, 41 insertions(+), 1 deletion(-) + +diff --git a/tools/objtool/arch/loongarch/decode.c b/tools/objtool/arch/loongarch/decode.c +index 69b66994f2a15..b64205b89f6b4 100644 +--- a/tools/objtool/arch/loongarch/decode.c ++++ b/tools/objtool/arch/loongarch/decode.c +@@ -363,3 +363,14 @@ void arch_initial_func_cfi_state(struct cfi_init_state *state) + state->cfa.base = CFI_SP; + state->cfa.offset = 0; + } ++ ++unsigned int arch_reloc_size(struct reloc *reloc) ++{ ++ switch (reloc_type(reloc)) { ++ case R_LARCH_32: ++ case R_LARCH_32_PCREL: ++ return 4; ++ default: ++ return 8; ++ } ++} +diff --git a/tools/objtool/arch/powerpc/decode.c b/tools/objtool/arch/powerpc/decode.c +index 53b55690f3204..7c0bf24290675 100644 +--- a/tools/objtool/arch/powerpc/decode.c ++++ b/tools/objtool/arch/powerpc/decode.c +@@ -106,3 +106,17 @@ void arch_initial_func_cfi_state(struct cfi_init_state *state) + state->regs[CFI_RA].base = CFI_CFA; + state->regs[CFI_RA].offset = 0; + } ++ ++unsigned int arch_reloc_size(struct reloc *reloc) ++{ ++ switch (reloc_type(reloc)) { ++ case R_PPC_REL32: ++ case R_PPC_ADDR32: ++ case R_PPC_UADDR32: ++ case R_PPC_PLT32: ++ case R_PPC_PLTREL32: ++ return 4; ++ default: ++ return 8; ++ } ++} +diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c +index fe1362c345647..fb9691a34d926 100644 +--- a/tools/objtool/arch/x86/decode.c ++++ b/tools/objtool/arch/x86/decode.c +@@ -852,3 +852,16 @@ bool arch_is_embedded_insn(struct symbol *sym) + return !strcmp(sym->name, "retbleed_return_thunk") || + !strcmp(sym->name, "srso_safe_ret"); + } ++ ++unsigned int arch_reloc_size(struct reloc *reloc) ++{ ++ switch (reloc_type(reloc)) { ++ case R_X86_64_32: ++ case R_X86_64_32S: ++ case R_X86_64_PC32: ++ case R_X86_64_PLT32: ++ return 4; ++ default: ++ return 8; ++ } ++} +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index 79c49c75b429b..4b9f01a11792f 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -1969,7 +1969,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn, + break; + + /* Make sure the table entries are consecutive: */ +- if (prev_offset && reloc_offset(reloc) != prev_offset + 8) ++ if (prev_offset && reloc_offset(reloc) != prev_offset + arch_reloc_size(reloc)) + break; + + sym_offset = reloc->sym->offset + reloc_addend(reloc); +diff --git a/tools/objtool/include/objtool/arch.h b/tools/objtool/include/objtool/arch.h +index d63b46a19f397..396f7c6c81c0f 100644 +--- a/tools/objtool/include/objtool/arch.h ++++ b/tools/objtool/include/objtool/arch.h +@@ -97,4 +97,6 @@ int arch_rewrite_retpolines(struct objtool_file *file); + + bool arch_pc_relative_reloc(struct reloc *reloc); + ++unsigned int arch_reloc_size(struct reloc *reloc); ++ + #endif /* _ARCH_H */ +-- +2.39.5 + diff --git a/queue-6.14/objtool-handle-pc-relative-relocation-type.patch b/queue-6.14/objtool-handle-pc-relative-relocation-type.patch new file mode 100644 index 0000000000..71a48dbd5c --- /dev/null +++ b/queue-6.14/objtool-handle-pc-relative-relocation-type.patch @@ -0,0 +1,141 @@ +From 7f6b8e0797ef3f276827eedacbf5b0e27e5f63e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 19:50:12 +0800 +Subject: objtool: Handle PC relative relocation type + +From: Tiezhu Yang + +[ Upstream commit c4b93b06230ae49870187189d9f7342f6ad4f14e ] + +For the most part, an absolute relocation type is used for rodata. +In the case of STT_SECTION, reloc->sym->offset is always zero, for +the other symbol types, reloc_addend(reloc) is always zero, thus it +can use a simple statement "reloc->sym->offset + reloc_addend(reloc)" +to obtain the symbol offset for various symbol types. + +When compiling on LoongArch, there exist PC relative relocation types +for rodata, it needs to calculate the symbol offset with "S + A - PC" +according to the spec of "ELF for the LoongArch Architecture". + +If there is only one jump table in the rodata, the "PC" is the entry +address which is equal with the value of reloc_offset(reloc), at this +time, reloc_offset(table) is 0. + +If there are many jump tables in the rodata, the "PC" is the offset +of the jump table's base address which is equal with the value of +reloc_offset(reloc) - reloc_offset(table). + +So for LoongArch, if the relocation type is PC relative, it can use a +statement "reloc_offset(reloc) - reloc_offset(table)" to get the "PC" +value when calculating the symbol offset with "S + A - PC" for one or +many jump tables in the rodata. + +Add an arch-specific function arch_jump_table_sym_offset() to assign +the symbol offset, for the most part that is an absolute relocation, +the default value is "reloc->sym->offset + reloc_addend(reloc)" in +the weak definition, it can be overridden by each architecture that +has different requirements. + +Link: https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc +Signed-off-by: Tiezhu Yang +Link: https://lore.kernel.org/r/20250211115016.26913-4-yangtiezhu@loongson.cn +Acked-by: Huacai Chen +Signed-off-by: Josh Poimboeuf +Stable-dep-of: ef753d66051c ("objtool: Fix detection of consecutive jump tables on Clang 20") +Signed-off-by: Sasha Levin +--- + tools/objtool/arch/loongarch/decode.c | 17 +++++++++++++---- + tools/objtool/arch/loongarch/include/arch/elf.h | 7 +++++++ + tools/objtool/check.c | 7 ++++++- + tools/objtool/include/objtool/arch.h | 1 + + 4 files changed, 27 insertions(+), 5 deletions(-) + +diff --git a/tools/objtool/arch/loongarch/decode.c b/tools/objtool/arch/loongarch/decode.c +index b64205b89f6b4..02e4905559667 100644 +--- a/tools/objtool/arch/loongarch/decode.c ++++ b/tools/objtool/arch/loongarch/decode.c +@@ -5,10 +5,7 @@ + #include + #include + #include +- +-#ifndef EM_LOONGARCH +-#define EM_LOONGARCH 258 +-#endif ++#include + + int arch_ftrace_match(char *name) + { +@@ -374,3 +371,15 @@ unsigned int arch_reloc_size(struct reloc *reloc) + return 8; + } + } ++ ++unsigned long arch_jump_table_sym_offset(struct reloc *reloc, struct reloc *table) ++{ ++ switch (reloc_type(reloc)) { ++ case R_LARCH_32_PCREL: ++ case R_LARCH_64_PCREL: ++ return reloc->sym->offset + reloc_addend(reloc) - ++ (reloc_offset(reloc) - reloc_offset(table)); ++ default: ++ return reloc->sym->offset + reloc_addend(reloc); ++ } ++} +diff --git a/tools/objtool/arch/loongarch/include/arch/elf.h b/tools/objtool/arch/loongarch/include/arch/elf.h +index 9623d663220ef..ec79062c9554d 100644 +--- a/tools/objtool/arch/loongarch/include/arch/elf.h ++++ b/tools/objtool/arch/loongarch/include/arch/elf.h +@@ -18,6 +18,13 @@ + #ifndef R_LARCH_32_PCREL + #define R_LARCH_32_PCREL 99 + #endif ++#ifndef R_LARCH_64_PCREL ++#define R_LARCH_64_PCREL 109 ++#endif ++ ++#ifndef EM_LOONGARCH ++#define EM_LOONGARCH 258 ++#endif + + #define R_NONE R_LARCH_NONE + #define R_ABS32 R_LARCH_32 +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index 4b9f01a11792f..12bf6c1f5071d 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -1944,6 +1944,11 @@ static int add_special_section_alts(struct objtool_file *file) + return ret; + } + ++__weak unsigned long arch_jump_table_sym_offset(struct reloc *reloc, struct reloc *table) ++{ ++ return reloc->sym->offset + reloc_addend(reloc); ++} ++ + static int add_jump_table(struct objtool_file *file, struct instruction *insn, + struct reloc *next_table) + { +@@ -1972,7 +1977,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn, + if (prev_offset && reloc_offset(reloc) != prev_offset + arch_reloc_size(reloc)) + break; + +- sym_offset = reloc->sym->offset + reloc_addend(reloc); ++ sym_offset = arch_jump_table_sym_offset(reloc, table); + + /* Detect function pointers from contiguous objects: */ + if (reloc->sym->sec == pfunc->sec && sym_offset == pfunc->offset) +diff --git a/tools/objtool/include/objtool/arch.h b/tools/objtool/include/objtool/arch.h +index 396f7c6c81c0f..089a1acc48a8d 100644 +--- a/tools/objtool/include/objtool/arch.h ++++ b/tools/objtool/include/objtool/arch.h +@@ -98,5 +98,6 @@ int arch_rewrite_retpolines(struct objtool_file *file); + bool arch_pc_relative_reloc(struct reloc *reloc); + + unsigned int arch_reloc_size(struct reloc *reloc); ++unsigned long arch_jump_table_sym_offset(struct reloc *reloc, struct reloc *table); + + #endif /* _ARCH_H */ +-- +2.39.5 + diff --git a/queue-6.14/objtool-handle-various-symbol-types-of-rodata.patch b/queue-6.14/objtool-handle-various-symbol-types-of-rodata.patch new file mode 100644 index 0000000000..e0c88b10b6 --- /dev/null +++ b/queue-6.14/objtool-handle-various-symbol-types-of-rodata.patch @@ -0,0 +1,92 @@ +From e6efe415670d8d341acd0fd4ee5dc5493a9ba0d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 19:50:10 +0800 +Subject: objtool: Handle various symbol types of rodata + +From: Tiezhu Yang + +[ Upstream commit ab6ce22b789622ca732e91cbb3a5cb5ba370cbd0 ] + +In the relocation section ".rela.rodata" of each .o file compiled with +LoongArch toolchain, there are various symbol types such as STT_NOTYPE, +STT_OBJECT, STT_FUNC in addition to the usual STT_SECTION, it needs to +use reloc symbol offset instead of reloc addend to find the destination +instruction in find_jump_table() and add_jump_table(). + +For the most part, an absolute relocation type is used for rodata. In the +case of STT_SECTION, reloc->sym->offset is always zero, and for the other +symbol types, reloc_addend(reloc) is always zero, thus it can use a simple +statement "reloc->sym->offset + reloc_addend(reloc)" to obtain the symbol +offset for various symbol types. + +Signed-off-by: Tiezhu Yang +Link: https://lore.kernel.org/r/20250211115016.26913-2-yangtiezhu@loongson.cn +Acked-by: Huacai Chen +Signed-off-by: Josh Poimboeuf +Stable-dep-of: ef753d66051c ("objtool: Fix detection of consecutive jump tables on Clang 20") +Signed-off-by: Sasha Levin +--- + tools/objtool/check.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index c1fa0220f33de..79c49c75b429b 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -1954,6 +1954,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn, + unsigned int prev_offset = 0; + struct reloc *reloc = table; + struct alternative *alt; ++ unsigned long sym_offset; + + /* + * Each @reloc is a switch table relocation which points to the target +@@ -1971,9 +1972,10 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn, + if (prev_offset && reloc_offset(reloc) != prev_offset + 8) + break; + ++ sym_offset = reloc->sym->offset + reloc_addend(reloc); ++ + /* Detect function pointers from contiguous objects: */ +- if (reloc->sym->sec == pfunc->sec && +- reloc_addend(reloc) == pfunc->offset) ++ if (reloc->sym->sec == pfunc->sec && sym_offset == pfunc->offset) + break; + + /* +@@ -1981,10 +1983,10 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn, + * which point to the end of the function. Ignore them. + */ + if (reloc->sym->sec == pfunc->sec && +- reloc_addend(reloc) == pfunc->offset + pfunc->len) ++ sym_offset == pfunc->offset + pfunc->len) + goto next; + +- dest_insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc)); ++ dest_insn = find_insn(file, reloc->sym->sec, sym_offset); + if (!dest_insn) + break; + +@@ -2023,6 +2025,7 @@ static void find_jump_table(struct objtool_file *file, struct symbol *func, + struct reloc *table_reloc; + struct instruction *dest_insn, *orig_insn = insn; + unsigned long table_size; ++ unsigned long sym_offset; + + /* + * Backward search using the @first_jump_src links, these help avoid +@@ -2046,7 +2049,10 @@ static void find_jump_table(struct objtool_file *file, struct symbol *func, + table_reloc = arch_find_switch_table(file, insn, &table_size); + if (!table_reloc) + continue; +- dest_insn = find_insn(file, table_reloc->sym->sec, reloc_addend(table_reloc)); ++ ++ sym_offset = table_reloc->sym->offset + reloc_addend(table_reloc); ++ ++ dest_insn = find_insn(file, table_reloc->sym->sec, sym_offset); + if (!dest_insn || !insn_func(dest_insn) || insn_func(dest_insn)->pfunc != func) + continue; + +-- +2.39.5 + diff --git a/queue-6.14/objtool-loongarch-add-unwind-hints-in-prepare_framet.patch b/queue-6.14/objtool-loongarch-add-unwind-hints-in-prepare_framet.patch new file mode 100644 index 0000000000..bde5c76c1d --- /dev/null +++ b/queue-6.14/objtool-loongarch-add-unwind-hints-in-prepare_framet.patch @@ -0,0 +1,86 @@ +From 025debc85eaf79293136822f14707189e9c565a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Mar 2025 21:26:43 -0700 +Subject: objtool/loongarch: Add unwind hints in prepare_frametrace() + +From: Josh Poimboeuf + +[ Upstream commit 7c977393b8277ed319e92e4b598b26598c9d30c0 ] + +If 'regs' points to a local stack variable, prepare_frametrace() stores +all registers to the stack. This confuses objtool as it expects them to +be restored from the stack later. + +The stores don't affect stack tracing, so use unwind hints to hide them +from objtool. + +Fixes the following warnings: + + arch/loongarch/kernel/traps.o: warning: objtool: show_stack+0xe0: stack state mismatch: reg1[22]=-1+0 reg2[22]=-2-160 + arch/loongarch/kernel/traps.o: warning: objtool: show_stack+0xe0: stack state mismatch: reg1[23]=-1+0 reg2[23]=-2-152 + +Fixes: cb8a2ef0848c ("LoongArch: Add ORC stack unwinder support") +Reported-by: kernel test robot +Tested-by: Tiezhu Yang +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/270cadd8040dda74db2307f23497bb68e65db98d.1743481539.git.jpoimboe@kernel.org +Closes: https://lore.kernel.org/oe-kbuild-all/202503280703.OARM8SrY-lkp@intel.com/ +Signed-off-by: Sasha Levin +--- + arch/loongarch/include/asm/stacktrace.h | 3 +++ + arch/loongarch/include/asm/unwind_hints.h | 10 +++++++++- + 2 files changed, 12 insertions(+), 1 deletion(-) + +diff --git a/arch/loongarch/include/asm/stacktrace.h b/arch/loongarch/include/asm/stacktrace.h +index f23adb15f418f..fc8b64773794a 100644 +--- a/arch/loongarch/include/asm/stacktrace.h ++++ b/arch/loongarch/include/asm/stacktrace.h +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + + enum stack_type { +@@ -43,6 +44,7 @@ int get_stack_info(unsigned long stack, struct task_struct *task, struct stack_i + static __always_inline void prepare_frametrace(struct pt_regs *regs) + { + __asm__ __volatile__( ++ UNWIND_HINT_SAVE + /* Save $ra */ + STORE_ONE_REG(1) + /* Use $ra to save PC */ +@@ -80,6 +82,7 @@ static __always_inline void prepare_frametrace(struct pt_regs *regs) + STORE_ONE_REG(29) + STORE_ONE_REG(30) + STORE_ONE_REG(31) ++ UNWIND_HINT_RESTORE + : "=m" (regs->csr_era) + : "r" (regs->regs) + : "memory"); +diff --git a/arch/loongarch/include/asm/unwind_hints.h b/arch/loongarch/include/asm/unwind_hints.h +index a01086ad9ddea..2c68bc72736c9 100644 +--- a/arch/loongarch/include/asm/unwind_hints.h ++++ b/arch/loongarch/include/asm/unwind_hints.h +@@ -23,6 +23,14 @@ + UNWIND_HINT sp_reg=ORC_REG_SP type=UNWIND_HINT_TYPE_CALL + .endm + +-#endif /* __ASSEMBLY__ */ ++#else /* !__ASSEMBLY__ */ ++ ++#define UNWIND_HINT_SAVE \ ++ UNWIND_HINT(UNWIND_HINT_TYPE_SAVE, 0, 0, 0) ++ ++#define UNWIND_HINT_RESTORE \ ++ UNWIND_HINT(UNWIND_HINT_TYPE_RESTORE, 0, 0, 0) ++ ++#endif /* !__ASSEMBLY__ */ + + #endif /* _ASM_LOONGARCH_UNWIND_HINTS_H */ +-- +2.39.5 + diff --git a/queue-6.14/objtool-media-dib8000-prevent-divide-by-zero-in-dib8.patch b/queue-6.14/objtool-media-dib8000-prevent-divide-by-zero-in-dib8.patch new file mode 100644 index 0000000000..b06cedf069 --- /dev/null +++ b/queue-6.14/objtool-media-dib8000-prevent-divide-by-zero-in-dib8.patch @@ -0,0 +1,49 @@ +From c66e2f743e403c69214bba41776a831b01f88226 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 14:56:06 -0700 +Subject: objtool, media: dib8000: Prevent divide-by-zero in dib8000_set_dds() + +From: Josh Poimboeuf + +[ Upstream commit e63d465f59011dede0a0f1d21718b59a64c3ff5c ] + +If dib8000_set_dds()'s call to dib8000_read32() returns zero, the result +is a divide-by-zero. Prevent that from happening. + +Fixes the following warning with an UBSAN kernel: + + drivers/media/dvb-frontends/dib8000.o: warning: objtool: dib8000_tune() falls through to next function dib8096p_cfg_DibRx() + +Fixes: 173a64cb3fcf ("[media] dib8000: enhancement") +Reported-by: kernel test robot +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Cc: Mauro Carvalho Chehab +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/bd1d504d930ae3f073b1e071bcf62cae7708773c.1742852847.git.jpoimboe@kernel.org +Closes: https://lore.kernel.org/r/202503210602.fvH5DO1i-lkp@intel.com/ +Signed-off-by: Sasha Levin +--- + drivers/media/dvb-frontends/dib8000.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c +index 2f5165918163d..cfe59c3255f70 100644 +--- a/drivers/media/dvb-frontends/dib8000.c ++++ b/drivers/media/dvb-frontends/dib8000.c +@@ -2701,8 +2701,11 @@ static void dib8000_set_dds(struct dib8000_state *state, s32 offset_khz) + u8 ratio; + + if (state->revision == 0x8090) { ++ u32 internal = dib8000_read32(state, 23) / 1000; ++ + ratio = 4; +- unit_khz_dds_val = (1<<26) / (dib8000_read32(state, 23) / 1000); ++ ++ unit_khz_dds_val = (1<<26) / (internal ?: 1); + if (offset_khz < 0) + dds = (1 << 26) - (abs_offset_khz * unit_khz_dds_val); + else +-- +2.39.5 + diff --git a/queue-6.14/objtool-nvmet-fix-out-of-bounds-stack-access-in-nvme.patch b/queue-6.14/objtool-nvmet-fix-out-of-bounds-stack-access-in-nvme.patch new file mode 100644 index 0000000000..f2447b193f --- /dev/null +++ b/queue-6.14/objtool-nvmet-fix-out-of-bounds-stack-access-in-nvme.patch @@ -0,0 +1,49 @@ +From 26843688c456c5e6ed7d9e09034adcabfc4d8746 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 14:56:05 -0700 +Subject: objtool, nvmet: Fix out-of-bounds stack access in + nvmet_ctrl_state_show() + +From: Josh Poimboeuf + +[ Upstream commit 107a23185d990e3df6638d9a84c835f963fe30a6 ] + +The csts_state_names[] array only has six sparse entries, but the +iteration code in nvmet_ctrl_state_show() iterates seven, resulting in a +potential out-of-bounds stack read. Fix that. + +Fixes the following warning with an UBSAN kernel: + + vmlinux.o: warning: objtool: .text.nvmet_ctrl_state_show: unexpected end of section + +Fixes: 649fd41420a8 ("nvmet: add debugfs support") +Reported-by: kernel test robot +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Cc: Christoph Hellwig +Cc: Sagi Grimberg +Cc: Chaitanya Kulkarni +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/f1f60858ee7a941863dc7f5506c540cb9f97b5f6.1742852847.git.jpoimboe@kernel.org +Closes: https://lore.kernel.org/oe-kbuild-all/202503171547.LlCTJLQL-lkp@intel.com/ +Signed-off-by: Sasha Levin +--- + drivers/nvme/target/debugfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/nvme/target/debugfs.c b/drivers/nvme/target/debugfs.c +index 220c7391fc19a..c6571fbd35e30 100644 +--- a/drivers/nvme/target/debugfs.c ++++ b/drivers/nvme/target/debugfs.c +@@ -78,7 +78,7 @@ static int nvmet_ctrl_state_show(struct seq_file *m, void *p) + bool sep = false; + int i; + +- for (i = 0; i < 7; i++) { ++ for (i = 0; i < ARRAY_SIZE(csts_state_names); i++) { + int state = BIT(i); + + if (!(ctrl->csts & state)) +-- +2.39.5 + diff --git a/queue-6.14/objtool-spi-amd-fix-out-of-bounds-stack-access-in-am.patch b/queue-6.14/objtool-spi-amd-fix-out-of-bounds-stack-access-in-am.patch new file mode 100644 index 0000000000..a1c0aff50a --- /dev/null +++ b/queue-6.14/objtool-spi-amd-fix-out-of-bounds-stack-access-in-am.patch @@ -0,0 +1,51 @@ +From 13bca3630831efd54ef6bc603888d15acf3d3536 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 14:56:04 -0700 +Subject: objtool, spi: amd: Fix out-of-bounds stack access in + amd_set_spi_freq() + +From: Josh Poimboeuf + +[ Upstream commit 76e51db43fe4aaaebcc5ddda67b0807f7c9bdecc ] + +If speed_hz < AMD_SPI_MIN_HZ, amd_set_spi_freq() iterates over the +entire amd_spi_freq array without breaking out early, causing 'i' to go +beyond the array bounds. + +Fix that by stopping the loop when it gets to the last entry, so the low +speed_hz value gets clamped up to AMD_SPI_MIN_HZ. + +Fixes the following warning with an UBSAN kernel: + + drivers/spi/spi-amd.o: error: objtool: amd_set_spi_freq() falls through to next function amd_spi_set_opcode() + +Fixes: 3fe26121dc3a ("spi: amd: Configure device speed") +Reported-by: kernel test robot +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Acked-by: Mark Brown +Cc: Raju Rangoju +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/78fef0f2434f35be9095bcc9ffa23dd8cab667b9.1742852847.git.jpoimboe@kernel.org +Closes: https://lore.kernel.org/r/202503161828.RUk9EhWx-lkp@intel.com/ +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-amd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-amd.c b/drivers/spi/spi-amd.c +index c85997478b819..17fc0b17e756d 100644 +--- a/drivers/spi/spi-amd.c ++++ b/drivers/spi/spi-amd.c +@@ -302,7 +302,7 @@ static void amd_set_spi_freq(struct amd_spi *amd_spi, u32 speed_hz) + { + unsigned int i, spd7_val, alt_spd; + +- for (i = 0; i < ARRAY_SIZE(amd_spi_freq); i++) ++ for (i = 0; i < ARRAY_SIZE(amd_spi_freq)-1; i++) + if (speed_hz >= amd_spi_freq[i].speed_hz) + break; + +-- +2.39.5 + diff --git a/queue-6.14/ocfs2-validate-l_tree_depth-to-avoid-out-of-bounds-a.patch b/queue-6.14/ocfs2-validate-l_tree_depth-to-avoid-out-of-bounds-a.patch new file mode 100644 index 0000000000..a06623451d --- /dev/null +++ b/queue-6.14/ocfs2-validate-l_tree_depth-to-avoid-out-of-bounds-a.patch @@ -0,0 +1,56 @@ +From d290ad05f2e587a0830ab902c0fdc7d032499264 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 11:49:08 +0300 +Subject: ocfs2: validate l_tree_depth to avoid out-of-bounds access + +From: Vasiliy Kovalev + +[ Upstream commit a406aff8c05115119127c962cbbbbd202e1973ef ] + +The l_tree_depth field is 16-bit (__le16), but the actual maximum depth is +limited to OCFS2_MAX_PATH_DEPTH. + +Add a check to prevent out-of-bounds access if l_tree_depth has an invalid +value, which may occur when reading from a corrupted mounted disk [1]. + +Link: https://lkml.kernel.org/r/20250214084908.736528-1-kovalev@altlinux.org +Fixes: ccd979bdbce9 ("[PATCH] OCFS2: The Second Oracle Cluster Filesystem") +Signed-off-by: Vasiliy Kovalev +Reported-by: syzbot+66c146268dc88f4341fd@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=66c146268dc88f4341fd [1] +Reviewed-by: Joseph Qi +Cc: Joel Becker +Cc: Junxiao Bi +Cc: Changwei Ge +Cc: Jun Piao +Cc: Kurt Hackel +Cc: Mark Fasheh +Cc: Vasiliy Kovalev +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + fs/ocfs2/alloc.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c +index 4414743b638e8..b8ac85b548c7e 100644 +--- a/fs/ocfs2/alloc.c ++++ b/fs/ocfs2/alloc.c +@@ -1803,6 +1803,14 @@ static int __ocfs2_find_path(struct ocfs2_caching_info *ci, + + el = root_el; + while (el->l_tree_depth) { ++ if (unlikely(le16_to_cpu(el->l_tree_depth) >= OCFS2_MAX_PATH_DEPTH)) { ++ ocfs2_error(ocfs2_metadata_cache_get_super(ci), ++ "Owner %llu has invalid tree depth %u in extent list\n", ++ (unsigned long long)ocfs2_metadata_cache_owner(ci), ++ le16_to_cpu(el->l_tree_depth)); ++ ret = -EROFS; ++ goto out; ++ } + if (le16_to_cpu(el->l_next_free_rec) == 0) { + ocfs2_error(ocfs2_metadata_cache_get_super(ci), + "Owner %llu has empty extent list at depth %u\n", +-- +2.39.5 + diff --git a/queue-6.14/octeontx2-af-fix-mbox-intr-handler-when-num-vfs-64.patch b/queue-6.14/octeontx2-af-fix-mbox-intr-handler-when-num-vfs-64.patch new file mode 100644 index 0000000000..852bd6528b --- /dev/null +++ b/queue-6.14/octeontx2-af-fix-mbox-intr-handler-when-num-vfs-64.patch @@ -0,0 +1,39 @@ +From fb6e60c6db2c33ff39b26a36d11adb9f13dd9329 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Mar 2025 14:44:41 +0530 +Subject: octeontx2-af: Fix mbox INTR handler when num VFs > 64 + +From: Geetha sowjanya + +[ Upstream commit 0fdba88a211508984eb5df62008c29688692b134 ] + +When number of RVU VFs > 64, the vfs value passed to "rvu_queue_work" +function is incorrect. Due to which mbox workqueue entries for +VFs 0 to 63 never gets added to workqueue. + +Fixes: 9bdc47a6e328 ("octeontx2-af: Mbox communication support btw AF and it's VFs") +Signed-off-by: Geetha sowjanya +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250327091441.1284-1-gakula@marvell.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +index cd0d7b7774f1a..6575c422635b7 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +@@ -2634,7 +2634,7 @@ static irqreturn_t rvu_mbox_intr_handler(int irq, void *rvu_irq) + rvupf_write64(rvu, RVU_PF_VFPF_MBOX_INTX(1), intr); + + rvu_queue_work(&rvu->afvf_wq_info, 64, vfs, intr); +- vfs -= 64; ++ vfs = 64; + } + + intr = rvupf_read64(rvu, RVU_PF_VFPF_MBOX_INTX(0)); +-- +2.39.5 + diff --git a/queue-6.14/octeontx2-af-free-nix_af_int_vec_gen-irq.patch b/queue-6.14/octeontx2-af-free-nix_af_int_vec_gen-irq.patch new file mode 100644 index 0000000000..d22cf4026f --- /dev/null +++ b/queue-6.14/octeontx2-af-free-nix_af_int_vec_gen-irq.patch @@ -0,0 +1,40 @@ +From cfaba7e83534f97f7ae969fd37b5ffe015c12eb9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Mar 2025 15:10:54 +0530 +Subject: octeontx2-af: Free NIX_AF_INT_VEC_GEN irq + +From: Geetha sowjanya + +[ Upstream commit 323d6db6dc7decb06f2545efb9496259ddacd4f4 ] + +Due to the incorrect initial vector number in +rvu_nix_unregister_interrupts(), NIX_AF_INT_VEC_GEN is not +geeting free. Fix the vector number to include NIX_AF_INT_VEC_GEN +irq. + +Fixes: 5ed66306eab6 ("octeontx2-af: Add devlink health reporters for NIX") +Signed-off-by: Geetha sowjanya +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250327094054.2312-1-gakula@marvell.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c +index dab4deca893f5..27c3a2daaaa95 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c +@@ -207,7 +207,7 @@ static void rvu_nix_unregister_interrupts(struct rvu *rvu) + rvu->irq_allocated[offs + NIX_AF_INT_VEC_RVU] = false; + } + +- for (i = NIX_AF_INT_VEC_AF_ERR; i < NIX_AF_INT_VEC_CNT; i++) ++ for (i = NIX_AF_INT_VEC_GEN; i < NIX_AF_INT_VEC_CNT; i++) + if (rvu->irq_allocated[offs + i]) { + free_irq(pci_irq_vector(rvu->pdev, offs + i), rvu_dl); + rvu->irq_allocated[offs + i] = false; +-- +2.39.5 + diff --git a/queue-6.14/of-property-increase-nr_fwnode_reference_args.patch b/queue-6.14/of-property-increase-nr_fwnode_reference_args.patch new file mode 100644 index 0000000000..6548864534 --- /dev/null +++ b/queue-6.14/of-property-increase-nr_fwnode_reference_args.patch @@ -0,0 +1,52 @@ +From 57c3526427f037857be4a2d03f14ca5b19680052 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 21:58:06 +0800 +Subject: of: property: Increase NR_FWNODE_REFERENCE_ARGS + +From: Zijun Hu + +[ Upstream commit eb50844d728f11e87491f7c7af15a4a737f1159d ] + +Currently, the following two macros have different values: + +// The maximal argument count for firmware node reference + #define NR_FWNODE_REFERENCE_ARGS 8 +// The maximal argument count for DT node reference + #define MAX_PHANDLE_ARGS 16 + +It may cause firmware node reference's argument count out of range if +directly assign DT node reference's argument count to firmware's. + +drivers/of/property.c:of_fwnode_get_reference_args() is doing the direct +assignment, so may cause firmware's argument count @args->nargs got out +of range, namely, in [9, 16]. + +Fix by increasing NR_FWNODE_REFERENCE_ARGS to 16 to meet DT requirement. +Will align both macros later to avoid such inconsistency. + +Fixes: 3e3119d3088f ("device property: Introduce fwnode_property_get_reference_args") +Signed-off-by: Zijun Hu +Acked-by: Sakari Ailus +Link: https://lore.kernel.org/r/20250225-fix_arg_count-v4-1-13cdc519eb31@quicinc.com +Signed-off-by: Rob Herring (Arm) +Signed-off-by: Sasha Levin +--- + include/linux/fwnode.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h +index 0731994b9d7c8..6fa0a268d5382 100644 +--- a/include/linux/fwnode.h ++++ b/include/linux/fwnode.h +@@ -91,7 +91,7 @@ struct fwnode_endpoint { + #define SWNODE_GRAPH_PORT_NAME_FMT "port@%u" + #define SWNODE_GRAPH_ENDPOINT_NAME_FMT "endpoint@%u" + +-#define NR_FWNODE_REFERENCE_ARGS 8 ++#define NR_FWNODE_REFERENCE_ARGS 16 + + /** + * struct fwnode_reference_args - Fwnode reference with additional arguments +-- +2.39.5 + diff --git a/queue-6.14/pci-acs-fix-pci-config_acs-parameter.patch b/queue-6.14/pci-acs-fix-pci-config_acs-parameter.patch new file mode 100644 index 0000000000..edd4340cbd --- /dev/null +++ b/queue-6.14/pci-acs-fix-pci-config_acs-parameter.patch @@ -0,0 +1,143 @@ +From eaf950b03e2755e77cf3019af104d3ba9dbc6fd6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 19:03:38 -0800 +Subject: PCI/ACS: Fix 'pci=config_acs=' parameter + +From: Tushar Dave + +[ Upstream commit 9cf8a952d57b422d3ff8a9a0163f8adf694f4b2b ] + +Commit 47c8846a49ba ("PCI: Extend ACS configurability") introduced bugs +that fail to configure ACS ctrl to the value specified by the kernel +parameter. Essentially there are two bugs: + +1) When ACS is configured for multiple PCI devices using 'config_acs' + kernel parameter, it results into error "PCI: Can't parse ACS command + line parameter". This is due to a bug that doesn't preserve the ACS + mask, but instead overwrites the mask with value 0. + + For example, using 'config_acs' to configure ACS ctrl for multiple BDFs + fails: + + Kernel command line: pci=config_acs=1111011@0020:02:00.0;101xxxx@0039:00:00.0 "dyndbg=file drivers/pci/pci.c +p" + PCI: Can't parse ACS command line parameter + pci 0020:02:00.0: ACS mask = 0x007f + pci 0020:02:00.0: ACS flags = 0x007b + pci 0020:02:00.0: Configured ACS to 0x007b + + After this fix: + + Kernel command line: pci=config_acs=1111011@0020:02:00.0;101xxxx@0039:00:00.0 "dyndbg=file drivers/pci/pci.c +p" + pci 0020:02:00.0: ACS mask = 0x007f + pci 0020:02:00.0: ACS flags = 0x007b + pci 0020:02:00.0: ACS control = 0x005f + pci 0020:02:00.0: ACS fw_ctrl = 0x0053 + pci 0020:02:00.0: Configured ACS to 0x007b + pci 0039:00:00.0: ACS mask = 0x0070 + pci 0039:00:00.0: ACS flags = 0x0050 + pci 0039:00:00.0: ACS control = 0x001d + pci 0039:00:00.0: ACS fw_ctrl = 0x0000 + pci 0039:00:00.0: Configured ACS to 0x0050 + +2) In the bit manipulation logic, we copy the bit from the firmware + settings when mask bit 0. + + For example, 'disable_acs_redir' fails to clear all three ACS P2P redir + bits due to the wrong bit fiddling: + + Kernel command line: pci=disable_acs_redir=0020:02:00.0;0030:02:00.0;0039:00:00.0 "dyndbg=file drivers/pci/pci.c +p" + pci 0020:02:00.0: ACS mask = 0x002c + pci 0020:02:00.0: ACS flags = 0xffd3 + pci 0020:02:00.0: Configured ACS to 0xfffb + pci 0030:02:00.0: ACS mask = 0x002c + pci 0030:02:00.0: ACS flags = 0xffd3 + pci 0030:02:00.0: Configured ACS to 0xffdf + pci 0039:00:00.0: ACS mask = 0x002c + pci 0039:00:00.0: ACS flags = 0xffd3 + pci 0039:00:00.0: Configured ACS to 0xffd3 + + After this fix: + + Kernel command line: pci=disable_acs_redir=0020:02:00.0;0030:02:00.0;0039:00:00.0 "dyndbg=file drivers/pci/pci.c +p" + pci 0020:02:00.0: ACS mask = 0x002c + pci 0020:02:00.0: ACS flags = 0xffd3 + pci 0020:02:00.0: ACS control = 0x007f + pci 0020:02:00.0: ACS fw_ctrl = 0x007b + pci 0020:02:00.0: Configured ACS to 0x0053 + pci 0030:02:00.0: ACS mask = 0x002c + pci 0030:02:00.0: ACS flags = 0xffd3 + pci 0030:02:00.0: ACS control = 0x005f + pci 0030:02:00.0: ACS fw_ctrl = 0x005f + pci 0030:02:00.0: Configured ACS to 0x0053 + pci 0039:00:00.0: ACS mask = 0x002c + pci 0039:00:00.0: ACS flags = 0xffd3 + pci 0039:00:00.0: ACS control = 0x001d + pci 0039:00:00.0: ACS fw_ctrl = 0x0000 + pci 0039:00:00.0: Configured ACS to 0x0000 + +Link: https://lore.kernel.org/r/20250207030338.456887-1-tdave@nvidia.com +Fixes: 47c8846a49ba ("PCI: Extend ACS configurability") +Signed-off-by: Tushar Dave +Signed-off-by: Bjorn Helgaas +Reviewed-by: Jason Gunthorpe +Reviewed-by: Kuppuswamy Sathyanarayanan +Signed-off-by: Sasha Levin +--- + drivers/pci/pci.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c +index 869d204a70a37..23609dd123f95 100644 +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -954,8 +954,10 @@ struct pci_acs { + }; + + static void __pci_config_acs(struct pci_dev *dev, struct pci_acs *caps, +- const char *p, u16 mask, u16 flags) ++ const char *p, const u16 acs_mask, const u16 acs_flags) + { ++ u16 flags = acs_flags; ++ u16 mask = acs_mask; + char *delimit; + int ret = 0; + +@@ -963,7 +965,7 @@ static void __pci_config_acs(struct pci_dev *dev, struct pci_acs *caps, + return; + + while (*p) { +- if (!mask) { ++ if (!acs_mask) { + /* Check for ACS flags */ + delimit = strstr(p, "@"); + if (delimit) { +@@ -971,6 +973,8 @@ static void __pci_config_acs(struct pci_dev *dev, struct pci_acs *caps, + u32 shift = 0; + + end = delimit - p - 1; ++ mask = 0; ++ flags = 0; + + while (end > -1) { + if (*(p + end) == '0') { +@@ -1027,10 +1031,14 @@ static void __pci_config_acs(struct pci_dev *dev, struct pci_acs *caps, + + pci_dbg(dev, "ACS mask = %#06x\n", mask); + pci_dbg(dev, "ACS flags = %#06x\n", flags); ++ pci_dbg(dev, "ACS control = %#06x\n", caps->ctrl); ++ pci_dbg(dev, "ACS fw_ctrl = %#06x\n", caps->fw_ctrl); + +- /* If mask is 0 then we copy the bit from the firmware setting. */ +- caps->ctrl = (caps->ctrl & ~mask) | (caps->fw_ctrl & mask); +- caps->ctrl |= flags; ++ /* ++ * For mask bits that are 0, copy them from the firmware setting ++ * and apply flags for all the mask bits that are 1. ++ */ ++ caps->ctrl = (caps->fw_ctrl & ~mask) | (flags & mask); + + pci_info(dev, "Configured ACS to %#06x\n", caps->ctrl); + } +-- +2.39.5 + diff --git a/queue-6.14/pci-allow-relaxed-bridge-window-tail-sizing-for-opti.patch b/queue-6.14/pci-allow-relaxed-bridge-window-tail-sizing-for-opti.patch new file mode 100644 index 0000000000..219d3cd5e0 --- /dev/null +++ b/queue-6.14/pci-allow-relaxed-bridge-window-tail-sizing-for-opti.patch @@ -0,0 +1,76 @@ +From 836751174dd6f299e1f6c7fba078f97bb41a0119 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Dec 2024 19:56:11 +0200 +Subject: PCI: Allow relaxed bridge window tail sizing for optional resources +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit 67f9085596ee55dd27b540ca6088ba0717ee511c ] + +Commit 566f1dd52816 ("PCI: Relax bridge window tail sizing rules") +relaxed the bridge window requirements for non-optional size (size0) +but pbus_size_mem() also handles optional sizes (IOV resources) using +size1. This can manifest, e.g., as a failure to resize a BAR back to +its original size after it was first shrunk when device has a VF BAR +resource because the bridge window (size1) is enlarged beyond what is +strictly required to fit the downstream resources. + +Allow using relaxed bridge window tail sizing rules also with the optional +resources (size1) so that the remove/realloc cycle during BAR resize +(smaller and back to the original size) does not fail unexpectedly due to +increase in bridge window size demand. + +Also move add_align calculation to more logical place next to size1 +assignment as they are strongly related to each other. + +Link: https://lore.kernel.org/r/20241216175632.4175-5-ilpo.jarvinen@linux.intel.com +Fixes: 566f1dd52816 ("PCI: Relax bridge window tail sizing rules") +Reported-by: Michał Winiarski +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 | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c +index d9f129a7735a5..8707c5b08cf34 100644 +--- a/drivers/pci/setup-bus.c ++++ b/drivers/pci/setup-bus.c +@@ -1146,7 +1146,6 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, + min_align = calculate_mem_align(aligns, max_order); + min_align = max(min_align, win_align); + size0 = calculate_memsize(size, min_size, 0, 0, resource_size(b_res), min_align); +- add_align = max(min_align, add_align); + + if (bus->self && size0 && + !pbus_upstream_space_available(bus, mask | IORESOURCE_PREFETCH, type, +@@ -1159,8 +1158,21 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, + } + + if (realloc_head && (add_size > 0 || children_add_size > 0)) { ++ add_align = max(min_align, add_align); + size1 = calculate_memsize(size, min_size, add_size, children_add_size, + resource_size(b_res), add_align); ++ ++ if (bus->self && size1 && ++ !pbus_upstream_space_available(bus, mask | IORESOURCE_PREFETCH, type, ++ size1, add_align)) { ++ min_align = 1ULL << (max_order + __ffs(SZ_1M)); ++ min_align = max(min_align, win_align); ++ size1 = calculate_memsize(size, min_size, add_size, children_add_size, ++ resource_size(b_res), win_align); ++ pci_info(bus->self, ++ "bridge window %pR to %pR requires relaxed alignment rules\n", ++ b_res, &bus->busn_res); ++ } + } + + if (!size0 && !size1) { +-- +2.39.5 + diff --git a/queue-6.14/pci-aspm-fix-link-state-exit-during-switch-upstream-.patch b/queue-6.14/pci-aspm-fix-link-state-exit-during-switch-upstream-.patch new file mode 100644 index 0000000000..de7a64dedc --- /dev/null +++ b/queue-6.14/pci-aspm-fix-link-state-exit-during-switch-upstream-.patch @@ -0,0 +1,84 @@ +From 5f629cfd9694bd0b95729e8671744d9fa9fec0e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 22 Dec 2024 19:39:08 -0800 +Subject: PCI/ASPM: Fix link state exit during switch upstream function removal +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Daniel Stodden + +[ Upstream commit cbf937dcadfd571a434f8074d057b32cd14fbea5 ] + +Before 456d8aa37d0f ("PCI/ASPM: Disable ASPM on MFD function removal to +avoid use-after-free"), we would free the ASPM link only after the last +function on the bus pertaining to the given link was removed. + +That was too late. If function 0 is removed before sibling function, +link->downstream would point to free'd memory after. + +After above change, we freed the ASPM parent link state upon any function +removal on the bus pertaining to a given link. + +That is too early. If the link is to a PCIe switch with MFD on the upstream +port, then removing functions other than 0 first would free a link which +still remains parent_link to the remaining downstream ports. + +The resulting GPFs are especially frequent during hot-unplug, because +pciehp removes devices on the link bus in reverse order. + +On that switch, function 0 is the virtual P2P bridge to the internal bus. +Free exactly when function 0 is removed -- before the parent link is +obsolete, but after all subordinate links are gone. + +Link: https://lore.kernel.org/r/e12898835f25234561c9d7de4435590d957b85d9.1734924854.git.dns@arista.com +Fixes: 456d8aa37d0f ("PCI/ASPM: Disable ASPM on MFD function removal to avoid use-after-free") +Signed-off-by: Daniel Stodden +Signed-off-by: Bjorn Helgaas +[kwilczynski: commit log] +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/pci/pcie/aspm.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c +index da3e7edcf49d9..29fcb0689a918 100644 +--- a/drivers/pci/pcie/aspm.c ++++ b/drivers/pci/pcie/aspm.c +@@ -1270,16 +1270,16 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) + parent_link = link->parent; + + /* +- * link->downstream is a pointer to the pci_dev of function 0. If +- * we remove that function, the pci_dev is about to be deallocated, +- * so we can't use link->downstream again. Free the link state to +- * avoid this. ++ * Free the parent link state, no later than function 0 (i.e. ++ * link->downstream) being removed. + * +- * If we're removing a non-0 function, it's possible we could +- * retain the link state, but PCIe r6.0, sec 7.5.3.7, recommends +- * programming the same ASPM Control value for all functions of +- * multi-function devices, so disable ASPM for all of them. ++ * Do not free the link state any earlier. If function 0 is a ++ * switch upstream port, this link state is parent_link to all ++ * subordinate ones. + */ ++ if (pdev != link->downstream) ++ goto out; ++ + pcie_config_aspm_link(link, 0); + list_del(&link->sibling); + free_link_state(link); +@@ -1290,6 +1290,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) + pcie_config_aspm_path(parent_link); + } + ++ out: + mutex_unlock(&aspm_lock); + up_read(&pci_bus_sem); + } +-- +2.39.5 + diff --git a/queue-6.14/pci-avoid-reset-when-disabled-via-sysfs.patch b/queue-6.14/pci-avoid-reset-when-disabled-via-sysfs.patch new file mode 100644 index 0000000000..8139065699 --- /dev/null +++ b/queue-6.14/pci-avoid-reset-when-disabled-via-sysfs.patch @@ -0,0 +1,67 @@ +From 7b6100a6efe07d75094632952dd7b5300391d1e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 14:56:00 -0600 +Subject: PCI: Avoid reset when disabled via sysfs + +From: Nishanth Aravamudan + +[ Upstream commit 479380efe1625e251008d24b2810283db60d6fcd ] + +After d88f521da3ef ("PCI: Allow userspace to query and set device reset +mechanism"), userspace can disable reset of specific PCI devices by writing +an empty string to the sysfs reset_method file. + +However, pci_slot_resettable() does not check pci_reset_supported(), which +means that pci_reset_function() will still reset the device even if +userspace has disabled all the reset methods. + +I was able to reproduce this issue with a vfio device passed to a qemu +guest, where I had disabled PCI reset via sysfs. + +Add an explicit check of pci_reset_supported() in both +pci_slot_resettable() and pci_bus_resettable() to ensure both the reset +status and reset execution are bypassed if an administrator disables it for +a device. + +Link: https://lore.kernel.org/r/20250207205600.1846178-1-naravamudan@nvidia.com +Fixes: d88f521da3ef ("PCI: Allow userspace to query and set device reset mechanism") +Signed-off-by: Nishanth Aravamudan +[bhelgaas: commit log] +Signed-off-by: Bjorn Helgaas +Cc: Alex Williamson +Cc: Raphael Norwitz +Cc: Amey Narkhede +Cc: Jason Gunthorpe +Cc: Yishai Hadas +Cc: Shameer Kolothum +Cc: Kevin Tian +Signed-off-by: Sasha Levin +--- + drivers/pci/pci.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c +index 23609dd123f95..3e78cf86ef03b 100644 +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -5413,6 +5413,8 @@ static bool pci_bus_resettable(struct pci_bus *bus) + return false; + + list_for_each_entry(dev, &bus->devices, bus_list) { ++ if (!pci_reset_supported(dev)) ++ return false; + if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET || + (dev->subordinate && !pci_bus_resettable(dev->subordinate))) + return false; +@@ -5489,6 +5491,8 @@ static bool pci_slot_resettable(struct pci_slot *slot) + list_for_each_entry(dev, &slot->bus->devices, bus_list) { + if (!dev->slot || dev->slot != slot) + continue; ++ if (!pci_reset_supported(dev)) ++ return false; + if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET || + (dev->subordinate && !pci_bus_resettable(dev->subordinate))) + return false; +-- +2.39.5 + diff --git a/queue-6.14/pci-brcmstb-fix-error-path-after-a-call-to-regulator.patch b/queue-6.14/pci-brcmstb-fix-error-path-after-a-call-to-regulator.patch new file mode 100644 index 0000000000..ada0278684 --- /dev/null +++ b/queue-6.14/pci-brcmstb-fix-error-path-after-a-call-to-regulator.patch @@ -0,0 +1,50 @@ +From b970ceb339d43fe9be244d1487cb59da6c91db98 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 12:39:32 -0500 +Subject: PCI: brcmstb: Fix error path after a call to regulator_bulk_get() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jim Quinlan + +[ Upstream commit 3651ad5249c51cf7eee078e12612557040a6bdb4 ] + +If the regulator_bulk_get() returns an error and no regulators +are created, we need to set their number to zero. + +If we don't do this and the PCIe link up fails, a call to the +regulator_bulk_free() will result in a kernel panic. + +While at it, print the error value, as we cannot return an error +upwards as the kernel will WARN() on an error from add_bus(). + +Fixes: 9e6be018b263 ("PCI: brcmstb: Enable child bus device regulators from DT") +Signed-off-by: Jim Quinlan +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/20250214173944.47506-5-james.quinlan@broadcom.com +[kwilczynski: commit log, use comma in the message to match style with +other similar messages] +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-brcmstb.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c +index 8b728c0f7f421..1495d770b4c2c 100644 +--- a/drivers/pci/controller/pcie-brcmstb.c ++++ b/drivers/pci/controller/pcie-brcmstb.c +@@ -1368,7 +1368,8 @@ static int brcm_pcie_add_bus(struct pci_bus *bus) + + ret = regulator_bulk_get(dev, sr->num_supplies, sr->supplies); + if (ret) { +- dev_info(dev, "No regulators for downstream device\n"); ++ dev_info(dev, "Did not get regulators, err=%d\n", ret); ++ pcie->sr = NULL; + goto no_regulators; + } + +-- +2.39.5 + diff --git a/queue-6.14/pci-brcmstb-fix-potential-premature-regulator-disabl.patch b/queue-6.14/pci-brcmstb-fix-potential-premature-regulator-disabl.patch new file mode 100644 index 0000000000..bad5e93afa --- /dev/null +++ b/queue-6.14/pci-brcmstb-fix-potential-premature-regulator-disabl.patch @@ -0,0 +1,47 @@ +From 3ab4a3dc24ea2b947f4de002fb38a628c12f78d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 12:39:33 -0500 +Subject: PCI: brcmstb: Fix potential premature regulator disabling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jim Quinlan + +[ Upstream commit b7de1b60ecab2f7b6f05d8116e93228a0bbb8563 ] + +The platform supports enabling and disabling regulators only on +ports below the Root Complex. + +Thus, we need to verify this both when adding and removing the bus, +otherwise regulators may be disabled prematurely when a bus further +down the topology is removed. + +Fixes: 9e6be018b263 ("PCI: brcmstb: Enable child bus device regulators from DT") +Signed-off-by: Jim Quinlan +Reviewed-by: Florian Fainelli +Reviewed-by: Manivannan Sadhasivam +Link: https://lore.kernel.org/r/20250214173944.47506-6-james.quinlan@broadcom.com +[kwilczynski: commit log] +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-brcmstb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c +index 1495d770b4c2c..3d7dbfcd689e3 100644 +--- a/drivers/pci/controller/pcie-brcmstb.c ++++ b/drivers/pci/controller/pcie-brcmstb.c +@@ -1392,7 +1392,7 @@ static void brcm_pcie_remove_bus(struct pci_bus *bus) + struct subdev_regulators *sr = pcie->sr; + struct device *dev = &bus->dev; + +- if (!sr) ++ if (!sr || !bus->parent || !pci_is_root_bus(bus->parent)) + return; + + if (regulator_bulk_disable(sr->num_supplies, sr->supplies)) +-- +2.39.5 + diff --git a/queue-6.14/pci-brcmstb-set-generation-limit-before-pcie-link-up.patch b/queue-6.14/pci-brcmstb-set-generation-limit-before-pcie-link-up.patch new file mode 100644 index 0000000000..2efb2732b9 --- /dev/null +++ b/queue-6.14/pci-brcmstb-set-generation-limit-before-pcie-link-up.patch @@ -0,0 +1,56 @@ +From f47809b0a85128a4716e0127d84aee1667587090 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 12:39:29 -0500 +Subject: PCI: brcmstb: Set generation limit before PCIe link up +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jim Quinlan + +[ Upstream commit 72d36589c6b7bef6b30eb99fcb7082f72faca37f ] + +When the user elects to limit the PCIe generation via the appropriate +devicetree property, apply the settings before the PCIe link up, not +after. + +Fixes: c0452137034b ("PCI: brcmstb: Add Broadcom STB PCIe host controller driver") +Signed-off-by: Jim Quinlan +Reviewed-by: Florian Fainelli +Reviewed-by: Manivannan Sadhasivam +Link: https://lore.kernel.org/r/20250214173944.47506-2-james.quinlan@broadcom.com +[kwilczynski: commit log] +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-brcmstb.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c +index e733a27dc8df8..b2d523e268b3c 100644 +--- a/drivers/pci/controller/pcie-brcmstb.c ++++ b/drivers/pci/controller/pcie-brcmstb.c +@@ -1276,6 +1276,10 @@ static int brcm_pcie_start_link(struct brcm_pcie *pcie) + bool ssc_good = false; + int ret, i; + ++ /* Limit the generation if specified */ ++ if (pcie->gen) ++ brcm_pcie_set_gen(pcie, pcie->gen); ++ + /* Unassert the fundamental reset */ + ret = pcie->perst_set(pcie, 0); + if (ret) +@@ -1302,9 +1306,6 @@ static int brcm_pcie_start_link(struct brcm_pcie *pcie) + + brcm_config_clkreq(pcie); + +- if (pcie->gen) +- brcm_pcie_set_gen(pcie, pcie->gen); +- + if (pcie->ssc) { + ret = brcm_pcie_set_ssc(pcie); + if (ret == 0) +-- +2.39.5 + diff --git a/queue-6.14/pci-brcmstb-use-internal-register-to-change-link-cap.patch b/queue-6.14/pci-brcmstb-use-internal-register-to-change-link-cap.patch new file mode 100644 index 0000000000..beacb6af47 --- /dev/null +++ b/queue-6.14/pci-brcmstb-use-internal-register-to-change-link-cap.patch @@ -0,0 +1,54 @@ +From 424ef1d7f0b3d7ed8b6884400aa4d6f172e09d5b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 12:39:30 -0500 +Subject: PCI: brcmstb: Use internal register to change link capability +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jim Quinlan + +[ Upstream commit 0c97321e11e0e9e18546f828492758f6aaecec59 ] + +The driver has been mistakenly writing to a read-only (RO) +configuration space register (PCI_EXP_LNKCAP) to change the +PCIe link capability. + +Although harmless in this case, the proper write destination +is an internal register that is reflected by PCI_EXP_LNKCAP. + +Thus, fix the brcm_pcie_set_gen() function to correctly update +the link capability. + +Fixes: c0452137034b ("PCI: brcmstb: Add Broadcom STB PCIe host controller driver") +Signed-off-by: Jim Quinlan +Reviewed-by: Florian Fainelli +Reviewed-by: Manivannan Sadhasivam +Link: https://lore.kernel.org/r/20250214173944.47506-3-james.quinlan@broadcom.com +[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 b2d523e268b3c..8b728c0f7f421 100644 +--- a/drivers/pci/controller/pcie-brcmstb.c ++++ b/drivers/pci/controller/pcie-brcmstb.c +@@ -403,10 +403,10 @@ static int brcm_pcie_set_ssc(struct brcm_pcie *pcie) + static void brcm_pcie_set_gen(struct brcm_pcie *pcie, int gen) + { + u16 lnkctl2 = readw(pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2); +- u32 lnkcap = readl(pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP); ++ u32 lnkcap = readl(pcie->base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY); + + lnkcap = (lnkcap & ~PCI_EXP_LNKCAP_SLS) | gen; +- writel(lnkcap, pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP); ++ writel(lnkcap, pcie->base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY); + + lnkctl2 = (lnkctl2 & ~0xf) | gen; + writew(lnkctl2, pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2); +-- +2.39.5 + diff --git a/queue-6.14/pci-bwctrl-fix-pcie_bwctrl_select_speed-return-type.patch b/queue-6.14/pci-bwctrl-fix-pcie_bwctrl_select_speed-return-type.patch new file mode 100644 index 0000000000..52074d044c --- /dev/null +++ b/queue-6.14/pci-bwctrl-fix-pcie_bwctrl_select_speed-return-type.patch @@ -0,0 +1,50 @@ +From 2207118a2333ffc867db92718c82c06808e77407 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 18:31:03 +0200 +Subject: PCI/bwctrl: Fix pcie_bwctrl_select_speed() return type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit 026e4bffb0af9632f5a0bbf8d594f2aace44cf07 ] + +pcie_bwctrl_select_speed() should take __fls() of the speed bit, not return +it as a raw value. Instead of directly returning 2.5GT/s speed bit, simply +assign the fallback speed (2.5GT/s) into supported_speeds variable to share +the normal return path that calls pcie_supported_speeds2target_speed() to +calculate __fls(). + +This code path is not very likely to execute because +pcie_get_supported_speeds() should provide valid ->supported_speeds but a +spec violating device could fail to synthesize any speed in +pcie_get_supported_speeds(). It could also happen in case the +supported_speeds intersection is empty (also a violation of the current +PCIe specs). + +Link: https://lore.kernel.org/r/20250321163103.5145-1-ilpo.jarvinen@linux.intel.com +Fixes: de9a6c8d5dbf ("PCI/bwctrl: Add pcie_set_target_speed() to set PCIe Link Speed") +Signed-off-by: Ilpo Järvinen +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +--- + drivers/pci/pcie/bwctrl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pci/pcie/bwctrl.c b/drivers/pci/pcie/bwctrl.c +index 0a5e7efbce2cc..58ba8142c9a31 100644 +--- a/drivers/pci/pcie/bwctrl.c ++++ b/drivers/pci/pcie/bwctrl.c +@@ -113,7 +113,7 @@ static u16 pcie_bwctrl_select_speed(struct pci_dev *port, enum pci_bus_speed spe + up_read(&pci_bus_sem); + } + if (!supported_speeds) +- return PCI_EXP_LNKCAP2_SLS_2_5GB; ++ supported_speeds = PCI_EXP_LNKCAP2_SLS_2_5GB; + + return pcie_supported_speeds2target_speed(supported_speeds & desired_speeds); + } +-- +2.39.5 + diff --git a/queue-6.14/pci-cadence-ep-fix-the-driver-to-send-msg-tlp-for-in.patch b/queue-6.14/pci-cadence-ep-fix-the-driver-to-send-msg-tlp-for-in.patch new file mode 100644 index 0000000000..c2c0f16b76 --- /dev/null +++ b/queue-6.14/pci-cadence-ep-fix-the-driver-to-send-msg-tlp-for-in.patch @@ -0,0 +1,67 @@ +From 36d48a34d1b1f026bed89c026d58cc43ac050ace Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Feb 2025 00:57:24 +0800 +Subject: PCI: cadence-ep: Fix the driver to send MSG TLP for INTx without data + payload +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Hans Zhang <18255117159@163.com> + +[ Upstream commit 3ac47fbf4f6e8c3a7c3855fac68cc3246f90f850 ] + +Per the Cadence's "PCIe Controller IP for AX14" user guide, Version +1.04, Section 9.1.7.1, "AXI Subordinate to PCIe Address Translation +Registers", Table 9.4, the bit 16 of the AXI Subordinate Address +(axi_s_awaddr) when set corresponds to MSG with data, and when not set, +to MSG without data. + +However, the driver is currently doing the opposite and due to this, +the INTx is never received on the host. + +So, fix the driver to reflect the documentation and also make INTx work. + +Fixes: 37dddf14f1ae ("PCI: cadence: Add EndPoint Controller driver for Cadence PCIe controller") +Signed-off-by: Hans Zhang <18255117159@163.com> +Signed-off-by: Hans Zhang +Reviewed-by: Manivannan Sadhasivam +Link: https://lore.kernel.org/r/20250214165724.184599-1-18255117159@163.com +[kwilczynski: commit log] +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/cadence/pcie-cadence-ep.c | 3 +-- + drivers/pci/controller/cadence/pcie-cadence.h | 2 +- + 2 files changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c b/drivers/pci/controller/cadence/pcie-cadence-ep.c +index e0cc4560dfde7..0bf4cde34f517 100644 +--- a/drivers/pci/controller/cadence/pcie-cadence-ep.c ++++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c +@@ -352,8 +352,7 @@ static void cdns_pcie_ep_assert_intx(struct cdns_pcie_ep *ep, u8 fn, u8 intx, + spin_unlock_irqrestore(&ep->lock, flags); + + offset = CDNS_PCIE_NORMAL_MSG_ROUTING(MSG_ROUTING_LOCAL) | +- CDNS_PCIE_NORMAL_MSG_CODE(msg_code) | +- CDNS_PCIE_MSG_NO_DATA; ++ CDNS_PCIE_NORMAL_MSG_CODE(msg_code); + writel(0, ep->irq_cpu_addr + offset); + } + +diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h +index f5eeff834ec19..39ee9945c903e 100644 +--- a/drivers/pci/controller/cadence/pcie-cadence.h ++++ b/drivers/pci/controller/cadence/pcie-cadence.h +@@ -246,7 +246,7 @@ struct cdns_pcie_rp_ib_bar { + #define CDNS_PCIE_NORMAL_MSG_CODE_MASK GENMASK(15, 8) + #define CDNS_PCIE_NORMAL_MSG_CODE(code) \ + (((code) << 8) & CDNS_PCIE_NORMAL_MSG_CODE_MASK) +-#define CDNS_PCIE_MSG_NO_DATA BIT(16) ++#define CDNS_PCIE_MSG_DATA BIT(16) + + struct cdns_pcie; + +-- +2.39.5 + diff --git a/queue-6.14/pci-dwc-ep-return-enomem-for-allocation-failures.patch b/queue-6.14/pci-dwc-ep-return-enomem-for-allocation-failures.patch new file mode 100644 index 0000000000..ad8a3e3b4f --- /dev/null +++ b/queue-6.14/pci-dwc-ep-return-enomem-for-allocation-failures.patch @@ -0,0 +1,44 @@ +From 59437a80ad7b326c8746391b575bcb1f547a307a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 18:00:07 +0300 +Subject: PCI: dwc: ep: Return -ENOMEM for allocation failures +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Dan Carpenter + +[ Upstream commit 8189aa56dbed0bfb46b7b30d4d231f57ab17b3f4 ] + +If the bitmap or memory allocations fail, then dw_pcie_ep_init_registers() +will incorrectly return a success. + +Return -ENOMEM instead. + +Fixes: 869bc5253406 ("PCI: dwc: ep: Fix DBI access failure for drivers requiring refclk from host") +Signed-off-by: Dan Carpenter +[kwilczynski: commit log] +Signed-off-by: Krzysztof Wilczyński +Reviewed-by: Krzysztof Wilczyński +Reviewed-by: Manivannan Sadhasivam +Link: https://lore.kernel.org/r/36dcb6fc-f292-4dd5-bd45-a8c6f9dc3df7@stanley.mountain +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/dwc/pcie-designware-ep.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c +index 8e07d432e74f2..e41479a9ca027 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-ep.c ++++ b/drivers/pci/controller/dwc/pcie-designware-ep.c +@@ -773,6 +773,7 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep) + if (ret) + return ret; + ++ ret = -ENOMEM; + if (!ep->ib_window_map) { + ep->ib_window_map = devm_bitmap_zalloc(dev, pci->num_ib_windows, + GFP_KERNEL); +-- +2.39.5 + diff --git a/queue-6.14/pci-endpoint-pci-epf-test-handle-endianness-properly.patch b/queue-6.14/pci-endpoint-pci-epf-test-handle-endianness-properly.patch new file mode 100644 index 0000000000..f6b9175d78 --- /dev/null +++ b/queue-6.14/pci-endpoint-pci-epf-test-handle-endianness-properly.patch @@ -0,0 +1,351 @@ +From 0050734e99b6c67017b6f69c5c7a942f5921d9ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Jan 2025 17:12:42 +0100 +Subject: PCI: endpoint: pci-epf-test: Handle endianness properly +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Niklas Cassel + +[ Upstream commit 3c936e0ec0e412a3ce6072883da8682fb723d573 ] + +The struct pci_epf_test_reg is the actual data in pci-epf-test's test_reg +BAR (usually BAR0), which the host uses to send commands (etc.), and which +pci-epf-test uses to send back status codes. + +pci-epf-test currently reads and writes this data without any endianness +conversion functions, which means that pci-epf-test is completely broken +on big-endian endpoint systems. + +PCI devices are inherently little-endian, and the data stored in the PCI +BARs should be in little-endian. + +Use endianness conversion functions when reading and writing data to +struct pci_epf_test_reg so that pci-epf-test will behave correctly on +big-endian endpoint systems. + +Fixes: 349e7a85b25f ("PCI: endpoint: functions: Add an EP function to test PCI") +Reviewed-by: Frank Li +Reviewed-by: Manivannan Sadhasivam +Signed-off-by: Niklas Cassel +Link: https://lore.kernel.org/r/20250127161242.104651-2-cassel@kernel.org +Signed-off-by: Manivannan Sadhasivam +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/pci/endpoint/functions/pci-epf-test.c | 126 ++++++++++-------- + 1 file changed, 73 insertions(+), 53 deletions(-) + +diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c +index b94e205ae10b9..2409787cf56d9 100644 +--- a/drivers/pci/endpoint/functions/pci-epf-test.c ++++ b/drivers/pci/endpoint/functions/pci-epf-test.c +@@ -66,17 +66,17 @@ struct pci_epf_test { + }; + + struct pci_epf_test_reg { +- u32 magic; +- u32 command; +- u32 status; +- u64 src_addr; +- u64 dst_addr; +- u32 size; +- u32 checksum; +- u32 irq_type; +- u32 irq_number; +- u32 flags; +- u32 caps; ++ __le32 magic; ++ __le32 command; ++ __le32 status; ++ __le64 src_addr; ++ __le64 dst_addr; ++ __le32 size; ++ __le32 checksum; ++ __le32 irq_type; ++ __le32 irq_number; ++ __le32 flags; ++ __le32 caps; + } __packed; + + static struct pci_epf_header test_header = { +@@ -324,13 +324,17 @@ static void pci_epf_test_copy(struct pci_epf_test *epf_test, + struct pci_epc *epc = epf->epc; + struct device *dev = &epf->dev; + struct pci_epc_map src_map, dst_map; +- u64 src_addr = reg->src_addr; +- u64 dst_addr = reg->dst_addr; +- size_t copy_size = reg->size; ++ u64 src_addr = le64_to_cpu(reg->src_addr); ++ u64 dst_addr = le64_to_cpu(reg->dst_addr); ++ size_t orig_size, copy_size; + ssize_t map_size = 0; ++ u32 flags = le32_to_cpu(reg->flags); ++ u32 status = 0; + void *copy_buf = NULL, *buf; + +- if (reg->flags & FLAG_USE_DMA) { ++ orig_size = copy_size = le32_to_cpu(reg->size); ++ ++ if (flags & FLAG_USE_DMA) { + if (!dma_has_cap(DMA_MEMCPY, epf_test->dma_chan_tx->device->cap_mask)) { + dev_err(dev, "DMA controller doesn't support MEMCPY\n"); + ret = -EINVAL; +@@ -350,7 +354,7 @@ static void pci_epf_test_copy(struct pci_epf_test *epf_test, + src_addr, copy_size, &src_map); + if (ret) { + dev_err(dev, "Failed to map source address\n"); +- reg->status = STATUS_SRC_ADDR_INVALID; ++ status = STATUS_SRC_ADDR_INVALID; + goto free_buf; + } + +@@ -358,7 +362,7 @@ static void pci_epf_test_copy(struct pci_epf_test *epf_test, + dst_addr, copy_size, &dst_map); + if (ret) { + dev_err(dev, "Failed to map destination address\n"); +- reg->status = STATUS_DST_ADDR_INVALID; ++ status = STATUS_DST_ADDR_INVALID; + pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, + &src_map); + goto free_buf; +@@ -367,7 +371,7 @@ static void pci_epf_test_copy(struct pci_epf_test *epf_test, + map_size = min_t(size_t, dst_map.pci_size, src_map.pci_size); + + ktime_get_ts64(&start); +- if (reg->flags & FLAG_USE_DMA) { ++ if (flags & FLAG_USE_DMA) { + ret = pci_epf_test_data_transfer(epf_test, + dst_map.phys_addr, src_map.phys_addr, + map_size, 0, DMA_MEM_TO_MEM); +@@ -391,8 +395,8 @@ static void pci_epf_test_copy(struct pci_epf_test *epf_test, + map_size = 0; + } + +- pci_epf_test_print_rate(epf_test, "COPY", reg->size, &start, +- &end, reg->flags & FLAG_USE_DMA); ++ pci_epf_test_print_rate(epf_test, "COPY", orig_size, &start, &end, ++ flags & FLAG_USE_DMA); + + unmap: + if (map_size) { +@@ -405,9 +409,10 @@ static void pci_epf_test_copy(struct pci_epf_test *epf_test, + + set_status: + if (!ret) +- reg->status |= STATUS_COPY_SUCCESS; ++ status |= STATUS_COPY_SUCCESS; + else +- reg->status |= STATUS_COPY_FAIL; ++ status |= STATUS_COPY_FAIL; ++ reg->status = cpu_to_le32(status); + } + + static void pci_epf_test_read(struct pci_epf_test *epf_test, +@@ -423,9 +428,14 @@ static void pci_epf_test_read(struct pci_epf_test *epf_test, + struct pci_epc *epc = epf->epc; + struct device *dev = &epf->dev; + struct device *dma_dev = epf->epc->dev.parent; +- u64 src_addr = reg->src_addr; +- size_t src_size = reg->size; ++ u64 src_addr = le64_to_cpu(reg->src_addr); ++ size_t orig_size, src_size; + ssize_t map_size = 0; ++ u32 flags = le32_to_cpu(reg->flags); ++ u32 checksum = le32_to_cpu(reg->checksum); ++ u32 status = 0; ++ ++ orig_size = src_size = le32_to_cpu(reg->size); + + src_buf = kzalloc(src_size, GFP_KERNEL); + if (!src_buf) { +@@ -439,12 +449,12 @@ static void pci_epf_test_read(struct pci_epf_test *epf_test, + src_addr, src_size, &map); + if (ret) { + dev_err(dev, "Failed to map address\n"); +- reg->status = STATUS_SRC_ADDR_INVALID; ++ status = STATUS_SRC_ADDR_INVALID; + goto free_buf; + } + + map_size = map.pci_size; +- if (reg->flags & FLAG_USE_DMA) { ++ if (flags & FLAG_USE_DMA) { + dst_phys_addr = dma_map_single(dma_dev, buf, map_size, + DMA_FROM_DEVICE); + if (dma_mapping_error(dma_dev, dst_phys_addr)) { +@@ -481,11 +491,11 @@ static void pci_epf_test_read(struct pci_epf_test *epf_test, + map_size = 0; + } + +- pci_epf_test_print_rate(epf_test, "READ", reg->size, &start, +- &end, reg->flags & FLAG_USE_DMA); ++ pci_epf_test_print_rate(epf_test, "READ", orig_size, &start, &end, ++ flags & FLAG_USE_DMA); + +- crc32 = crc32_le(~0, src_buf, reg->size); +- if (crc32 != reg->checksum) ++ crc32 = crc32_le(~0, src_buf, orig_size); ++ if (crc32 != checksum) + ret = -EIO; + + unmap: +@@ -497,9 +507,10 @@ static void pci_epf_test_read(struct pci_epf_test *epf_test, + + set_status: + if (!ret) +- reg->status |= STATUS_READ_SUCCESS; ++ status |= STATUS_READ_SUCCESS; + else +- reg->status |= STATUS_READ_FAIL; ++ status |= STATUS_READ_FAIL; ++ reg->status = cpu_to_le32(status); + } + + static void pci_epf_test_write(struct pci_epf_test *epf_test, +@@ -514,9 +525,13 @@ static void pci_epf_test_write(struct pci_epf_test *epf_test, + struct pci_epc *epc = epf->epc; + struct device *dev = &epf->dev; + struct device *dma_dev = epf->epc->dev.parent; +- u64 dst_addr = reg->dst_addr; +- size_t dst_size = reg->size; ++ u64 dst_addr = le64_to_cpu(reg->dst_addr); ++ size_t orig_size, dst_size; + ssize_t map_size = 0; ++ u32 flags = le32_to_cpu(reg->flags); ++ u32 status = 0; ++ ++ orig_size = dst_size = le32_to_cpu(reg->size); + + dst_buf = kzalloc(dst_size, GFP_KERNEL); + if (!dst_buf) { +@@ -524,7 +539,7 @@ static void pci_epf_test_write(struct pci_epf_test *epf_test, + goto set_status; + } + get_random_bytes(dst_buf, dst_size); +- reg->checksum = crc32_le(~0, dst_buf, dst_size); ++ reg->checksum = cpu_to_le32(crc32_le(~0, dst_buf, dst_size)); + buf = dst_buf; + + while (dst_size) { +@@ -532,12 +547,12 @@ static void pci_epf_test_write(struct pci_epf_test *epf_test, + dst_addr, dst_size, &map); + if (ret) { + dev_err(dev, "Failed to map address\n"); +- reg->status = STATUS_DST_ADDR_INVALID; ++ status = STATUS_DST_ADDR_INVALID; + goto free_buf; + } + + map_size = map.pci_size; +- if (reg->flags & FLAG_USE_DMA) { ++ if (flags & FLAG_USE_DMA) { + src_phys_addr = dma_map_single(dma_dev, buf, map_size, + DMA_TO_DEVICE); + if (dma_mapping_error(dma_dev, src_phys_addr)) { +@@ -576,8 +591,8 @@ static void pci_epf_test_write(struct pci_epf_test *epf_test, + map_size = 0; + } + +- pci_epf_test_print_rate(epf_test, "WRITE", reg->size, &start, +- &end, reg->flags & FLAG_USE_DMA); ++ pci_epf_test_print_rate(epf_test, "WRITE", orig_size, &start, &end, ++ flags & FLAG_USE_DMA); + + /* + * wait 1ms inorder for the write to complete. Without this delay L3 +@@ -594,9 +609,10 @@ static void pci_epf_test_write(struct pci_epf_test *epf_test, + + set_status: + if (!ret) +- reg->status |= STATUS_WRITE_SUCCESS; ++ status |= STATUS_WRITE_SUCCESS; + else +- reg->status |= STATUS_WRITE_FAIL; ++ status |= STATUS_WRITE_FAIL; ++ reg->status = cpu_to_le32(status); + } + + static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test, +@@ -605,39 +621,42 @@ static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test, + struct pci_epf *epf = epf_test->epf; + struct device *dev = &epf->dev; + struct pci_epc *epc = epf->epc; +- u32 status = reg->status | STATUS_IRQ_RAISED; ++ u32 status = le32_to_cpu(reg->status); ++ u32 irq_number = le32_to_cpu(reg->irq_number); ++ u32 irq_type = le32_to_cpu(reg->irq_type); + int count; + + /* + * Set the status before raising the IRQ to ensure that the host sees + * the updated value when it gets the IRQ. + */ +- WRITE_ONCE(reg->status, status); ++ status |= STATUS_IRQ_RAISED; ++ WRITE_ONCE(reg->status, cpu_to_le32(status)); + +- switch (reg->irq_type) { ++ switch (irq_type) { + case IRQ_TYPE_INTX: + pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, + PCI_IRQ_INTX, 0); + break; + case IRQ_TYPE_MSI: + count = pci_epc_get_msi(epc, epf->func_no, epf->vfunc_no); +- if (reg->irq_number > count || count <= 0) { ++ if (irq_number > count || count <= 0) { + dev_err(dev, "Invalid MSI IRQ number %d / %d\n", +- reg->irq_number, count); ++ irq_number, count); + return; + } + pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, +- PCI_IRQ_MSI, reg->irq_number); ++ PCI_IRQ_MSI, irq_number); + break; + case IRQ_TYPE_MSIX: + count = pci_epc_get_msix(epc, epf->func_no, epf->vfunc_no); +- if (reg->irq_number > count || count <= 0) { ++ if (irq_number > count || count <= 0) { + dev_err(dev, "Invalid MSIX IRQ number %d / %d\n", +- reg->irq_number, count); ++ irq_number, count); + return; + } + pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, +- PCI_IRQ_MSIX, reg->irq_number); ++ PCI_IRQ_MSIX, irq_number); + break; + default: + dev_err(dev, "Failed to raise IRQ, unknown type\n"); +@@ -654,21 +673,22 @@ static void pci_epf_test_cmd_handler(struct work_struct *work) + struct device *dev = &epf->dev; + enum pci_barno test_reg_bar = epf_test->test_reg_bar; + struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; ++ u32 irq_type = le32_to_cpu(reg->irq_type); + +- command = READ_ONCE(reg->command); ++ command = le32_to_cpu(READ_ONCE(reg->command)); + if (!command) + goto reset_handler; + + WRITE_ONCE(reg->command, 0); + WRITE_ONCE(reg->status, 0); + +- if ((READ_ONCE(reg->flags) & FLAG_USE_DMA) && ++ if ((le32_to_cpu(READ_ONCE(reg->flags)) & FLAG_USE_DMA) && + !epf_test->dma_supported) { + dev_err(dev, "Cannot transfer data using DMA\n"); + goto reset_handler; + } + +- if (reg->irq_type > IRQ_TYPE_MSIX) { ++ if (irq_type > IRQ_TYPE_MSIX) { + dev_err(dev, "Failed to detect IRQ type\n"); + goto reset_handler; + } +-- +2.39.5 + diff --git a/queue-6.14/pci-fix-bar-resizing-when-vf-bars-are-assigned.patch b/queue-6.14/pci-fix-bar-resizing-when-vf-bars-are-assigned.patch new file mode 100644 index 0000000000..126a6ba9e8 --- /dev/null +++ b/queue-6.14/pci-fix-bar-resizing-when-vf-bars-are-assigned.patch @@ -0,0 +1,62 @@ +From 90fc6e30ea79a190c7171a0a331933cb2d3f9c97 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Mar 2025 16:28:37 +0200 +Subject: PCI: Fix BAR resizing when VF BARs are assigned +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit 9ec19bfa78bd788945e2445b09de7b4482dee432 ] + +__resource_resize_store() attempts to release all resources of the device +before attempting the resize. The loop, however, only covers standard BARs +(< PCI_STD_NUM_BARS). If a device has VF BARs that are assigned, +pci_reassign_bridge_resources() finds the bridge window still has some +assigned child resources and returns -NOENT which makes +pci_resize_resource() to detect an error and abort the resize. + +Change the release loop to cover all resources up to VF BARs which allows +the resize operation to release the bridge windows and attempt to assigned +them again with the different size. + +If SR-IOV is enabled, disallow resize as it requires releasing also IOV +resources. + +Link: https://lore.kernel.org/r/20250320142837.8027-1-ilpo.jarvinen@linux.intel.com +Fixes: 91fa127794ac ("PCI: Expose PCIe Resizable BAR support via sysfs") +Reported-by: Michał Winiarski +Signed-off-by: Ilpo Järvinen +Signed-off-by: Bjorn Helgaas +Reviewed-by: Alex Williamson +Signed-off-by: Sasha Levin +--- + drivers/pci/pci-sysfs.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c +index b46ce1a2c5542..0e7eb2a42d88d 100644 +--- a/drivers/pci/pci-sysfs.c ++++ b/drivers/pci/pci-sysfs.c +@@ -1556,7 +1556,7 @@ static ssize_t __resource_resize_store(struct device *dev, int n, + return -EINVAL; + + device_lock(dev); +- if (dev->driver) { ++ if (dev->driver || pci_num_vf(pdev)) { + ret = -EBUSY; + goto unlock; + } +@@ -1578,7 +1578,7 @@ static ssize_t __resource_resize_store(struct device *dev, int n, + + pci_remove_resource_files(pdev); + +- for (i = 0; i < PCI_STD_NUM_BARS; i++) { ++ for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) { + if (pci_resource_len(pdev, i) && + pci_resource_flags(pdev, i) == flags) + pci_release_resource(pdev, i); +-- +2.39.5 + diff --git a/queue-6.14/pci-fix-null-dereference-in-sr-iov-vf-creation-error.patch b/queue-6.14/pci-fix-null-dereference-in-sr-iov-vf-creation-error.patch new file mode 100644 index 0000000000..15f1342a1c --- /dev/null +++ b/queue-6.14/pci-fix-null-dereference-in-sr-iov-vf-creation-error.patch @@ -0,0 +1,112 @@ +From f3fd07228b519149bfd48dc810ad78d54f245ef5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 10:45:24 +0200 +Subject: PCI: Fix NULL dereference in SR-IOV VF creation error path + +From: Shay Drory + +[ Upstream commit 04d50d953ab46d96b0b32d5ad955fceaa28622db ] + +Clean up when virtfn setup fails to prevent NULL pointer dereference +during device removal. The kernel oops below occurred due to incorrect +error handling flow when pci_setup_device() fails. + +Add pci_iov_scan_device(), which handles virtfn allocation and setup and +cleans up if pci_setup_device() fails, so pci_iov_add_virtfn() doesn't need +to call pci_stop_and_remove_bus_device(). This prevents accessing +partially initialized virtfn devices during removal. + + BUG: kernel NULL pointer dereference, address: 00000000000000d0 + RIP: 0010:device_del+0x3d/0x3d0 + Call Trace: + pci_remove_bus_device+0x7c/0x100 + pci_iov_add_virtfn+0xfa/0x200 + sriov_enable+0x208/0x420 + mlx5_core_sriov_configure+0x6a/0x160 [mlx5_core] + sriov_numvfs_store+0xae/0x1a0 + +Link: https://lore.kernel.org/r/20250310084524.599225-1-shayd@nvidia.com +Fixes: e3f30d563a38 ("PCI: Make pci_destroy_dev() concurrent safe") +Signed-off-by: Shay Drory +[bhelgaas: commit log, return ERR_PTR(-ENOMEM) directly] +Signed-off-by: Bjorn Helgaas +Cc: Keith Busch +Signed-off-by: Sasha Levin +--- + drivers/pci/iov.c | 48 +++++++++++++++++++++++++++++++++-------------- + 1 file changed, 34 insertions(+), 14 deletions(-) + +diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c +index 9e4770cdd4d5a..a964c66b42950 100644 +--- a/drivers/pci/iov.c ++++ b/drivers/pci/iov.c +@@ -285,23 +285,16 @@ const struct attribute_group sriov_vf_dev_attr_group = { + .is_visible = sriov_vf_attrs_are_visible, + }; + +-int pci_iov_add_virtfn(struct pci_dev *dev, int id) ++static struct pci_dev *pci_iov_scan_device(struct pci_dev *dev, int id, ++ struct pci_bus *bus) + { +- int i; +- int rc = -ENOMEM; +- u64 size; +- struct pci_dev *virtfn; +- struct resource *res; + struct pci_sriov *iov = dev->sriov; +- struct pci_bus *bus; +- +- bus = virtfn_add_bus(dev->bus, pci_iov_virtfn_bus(dev, id)); +- if (!bus) +- goto failed; ++ struct pci_dev *virtfn; ++ int rc; + + virtfn = pci_alloc_dev(bus); + if (!virtfn) +- goto failed0; ++ return ERR_PTR(-ENOMEM); + + virtfn->devfn = pci_iov_virtfn_devfn(dev, id); + virtfn->vendor = dev->vendor; +@@ -314,8 +307,35 @@ int pci_iov_add_virtfn(struct pci_dev *dev, int id) + pci_read_vf_config_common(virtfn); + + rc = pci_setup_device(virtfn); +- if (rc) +- goto failed1; ++ if (rc) { ++ pci_dev_put(dev); ++ pci_bus_put(virtfn->bus); ++ kfree(virtfn); ++ return ERR_PTR(rc); ++ } ++ ++ return virtfn; ++} ++ ++int pci_iov_add_virtfn(struct pci_dev *dev, int id) ++{ ++ struct pci_bus *bus; ++ struct pci_dev *virtfn; ++ struct resource *res; ++ int rc, i; ++ u64 size; ++ ++ bus = virtfn_add_bus(dev->bus, pci_iov_virtfn_bus(dev, id)); ++ if (!bus) { ++ rc = -ENOMEM; ++ goto failed; ++ } ++ ++ virtfn = pci_iov_scan_device(dev, id, bus); ++ if (IS_ERR(virtfn)) { ++ rc = PTR_ERR(virtfn); ++ goto failed0; ++ } + + virtfn->dev.parent = dev->dev.parent; + virtfn->multifunction = 0; +-- +2.39.5 + diff --git a/queue-6.14/pci-histb-fix-an-error-handling-path-in-histb_pcie_p.patch b/queue-6.14/pci-histb-fix-an-error-handling-path-in-histb_pcie_p.patch new file mode 100644 index 0000000000..b3bc5a1878 --- /dev/null +++ b/queue-6.14/pci-histb-fix-an-error-handling-path-in-histb_pcie_p.patch @@ -0,0 +1,71 @@ +From 36963495a6f647b94f8611a6ca80eaaa1866a304 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Mar 2025 19:42:54 +0100 +Subject: PCI: histb: Fix an error handling path in histb_pcie_probe() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Christophe JAILLET + +[ Upstream commit b36fb50701619efca5f5450b355d42575cf532ed ] + +If an error occurs after a successful phy_init() call, then phy_exit() +should be called. + +Add the missing call, as already done in the remove function. + +Fixes: bbd11bddb398 ("PCI: hisi: Add HiSilicon STB SoC PCIe controller driver") +Signed-off-by: Christophe JAILLET +[kwilczynski: remove unnecessary hipcie->phy NULL check from +histb_pcie_probe() and squash a patch that removes similar NULL +check for hipcie-phy from histb_pcie_remove() from +https://lore.kernel.org/linux-pci/c369b5d25e17a44984ae5a889ccc28a59a0737f7.1742058005.git.christophe.jaillet@wanadoo.fr] +Signed-off-by: Krzysztof Wilczyński +Link: https://lore.kernel.org/r/8301fc15cdea5d2dac21f57613e8e6922fb1ad95.1740854531.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/dwc/pcie-histb.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/pci/controller/dwc/pcie-histb.c b/drivers/pci/controller/dwc/pcie-histb.c +index 615a0e3e6d7eb..1f2f4c28a9495 100644 +--- a/drivers/pci/controller/dwc/pcie-histb.c ++++ b/drivers/pci/controller/dwc/pcie-histb.c +@@ -409,16 +409,21 @@ static int histb_pcie_probe(struct platform_device *pdev) + ret = histb_pcie_host_enable(pp); + if (ret) { + dev_err(dev, "failed to enable host\n"); +- return ret; ++ goto err_exit_phy; + } + + ret = dw_pcie_host_init(pp); + if (ret) { + dev_err(dev, "failed to initialize host\n"); +- return ret; ++ goto err_exit_phy; + } + + return 0; ++ ++err_exit_phy: ++ phy_exit(hipcie->phy); ++ ++ return ret; + } + + static void histb_pcie_remove(struct platform_device *pdev) +@@ -427,8 +432,7 @@ static void histb_pcie_remove(struct platform_device *pdev) + + histb_pcie_host_disable(hipcie); + +- if (hipcie->phy) +- phy_exit(hipcie->phy); ++ phy_exit(hipcie->phy); + } + + static const struct of_device_id histb_pcie_of_match[] = { +-- +2.39.5 + diff --git a/queue-6.14/pci-mediatek-gen3-configure-pbus_csr-registers-for-e.patch b/queue-6.14/pci-mediatek-gen3-configure-pbus_csr-registers-for-e.patch new file mode 100644 index 0000000000..18f4aa270e --- /dev/null +++ b/queue-6.14/pci-mediatek-gen3-configure-pbus_csr-registers-for-e.patch @@ -0,0 +1,90 @@ +From 91bc769b064d6c3c272a6695b67b95e5ac0f2341 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 09:04:07 +0100 +Subject: PCI: mediatek-gen3: Configure PBUS_CSR registers for EN7581 SoC +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Lorenzo Bianconi + +[ Upstream commit 249b78298078448a699c39356d27d8183af4b281 ] + +Configure PBus base address and address mask to allow the hw +to detect if a given address is accessible on PCIe controller. + +Fixes: f6ab898356dd ("PCI: mediatek-gen3: Add Airoha EN7581 support") +Reviewed-by: Manivannan Sadhasivam +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/20250225-en7581-pcie-pbus-csr-v4-2-24324382424a@kernel.org +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-mediatek-gen3.c | 28 ++++++++++++++++++++- + 1 file changed, 27 insertions(+), 1 deletion(-) + +diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c +index aa24ac9aaecc7..d0cc7f3b4b520 100644 +--- a/drivers/pci/controller/pcie-mediatek-gen3.c ++++ b/drivers/pci/controller/pcie-mediatek-gen3.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -24,6 +25,7 @@ + #include + #include + #include ++#include + #include + + #include "../pci.h" +@@ -930,9 +932,13 @@ static int mtk_pcie_parse_port(struct mtk_gen3_pcie *pcie) + + static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie) + { ++ struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); + struct device *dev = pcie->dev; ++ struct resource_entry *entry; ++ struct regmap *pbus_regmap; ++ u32 val, args[2], size; ++ resource_size_t addr; + int err; +- u32 val; + + /* + * The controller may have been left out of reset by the bootloader +@@ -945,6 +951,26 @@ static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie) + /* Wait for the time needed to complete the reset lines assert. */ + msleep(PCIE_EN7581_RESET_TIME_MS); + ++ /* ++ * Configure PBus base address and base address mask to allow the ++ * hw to detect if a given address is accessible on PCIe controller. ++ */ ++ pbus_regmap = syscon_regmap_lookup_by_phandle_args(dev->of_node, ++ "mediatek,pbus-csr", ++ ARRAY_SIZE(args), ++ args); ++ if (IS_ERR(pbus_regmap)) ++ return PTR_ERR(pbus_regmap); ++ ++ entry = resource_list_first_type(&host->windows, IORESOURCE_MEM); ++ if (!entry) ++ return -ENODEV; ++ ++ addr = entry->res->start - entry->offset; ++ regmap_write(pbus_regmap, args[0], lower_32_bits(addr)); ++ size = lower_32_bits(resource_size(entry->res)); ++ regmap_write(pbus_regmap, args[1], GENMASK(31, __fls(size))); ++ + /* + * Unlike the other MediaTek Gen3 controllers, the Airoha EN7581 + * requires PHY initialization and power-on before PHY reset deassert. +-- +2.39.5 + diff --git a/queue-6.14/pci-pciehp-don-t-enable-hpie-when-resuming-in-poll-m.patch b/queue-6.14/pci-pciehp-don-t-enable-hpie-when-resuming-in-poll-m.patch new file mode 100644 index 0000000000..4cecbf1258 --- /dev/null +++ b/queue-6.14/pci-pciehp-don-t-enable-hpie-when-resuming-in-poll-m.patch @@ -0,0 +1,49 @@ +From 70aff1ff2d96bd3c85487c3db4d4e44c876ba7d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 18:21:14 +0200 +Subject: PCI: pciehp: Don't enable HPIE when resuming in poll mode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit 527664f738afb6f2c58022cd35e63801e5dc7aec ] + +PCIe hotplug can operate in poll mode without interrupt handlers using a +polling kthread only. eb34da60edee ("PCI: pciehp: Disable hotplug +interrupt during suspend") failed to consider that and enables HPIE +(Hot-Plug Interrupt Enable) unconditionally when resuming the Port. + +Only set HPIE if non-poll mode is in use. This makes +pcie_enable_interrupt() match how pcie_enable_notification() already +handles HPIE. + +Link: https://lore.kernel.org/r/20250321162114.3939-1-ilpo.jarvinen@linux.intel.com +Fixes: eb34da60edee ("PCI: pciehp: Disable hotplug interrupt during suspend") +Signed-off-by: Ilpo Järvinen +Signed-off-by: Bjorn Helgaas +Reviewed-by: Lukas Wunner +Signed-off-by: Sasha Levin +--- + drivers/pci/hotplug/pciehp_hpc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c +index bb5a8d9f03ad9..28ab393af1c04 100644 +--- a/drivers/pci/hotplug/pciehp_hpc.c ++++ b/drivers/pci/hotplug/pciehp_hpc.c +@@ -842,7 +842,9 @@ void pcie_enable_interrupt(struct controller *ctrl) + { + u16 mask; + +- mask = PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_DLLSCE; ++ mask = PCI_EXP_SLTCTL_DLLSCE; ++ if (!pciehp_poll_mode) ++ mask |= PCI_EXP_SLTCTL_HPIE; + pcie_write_cmd(ctrl, mask, mask); + } + +-- +2.39.5 + diff --git a/queue-6.14/pci-portdrv-only-disable-pciehp-interrupts-early-whe.patch b/queue-6.14/pci-portdrv-only-disable-pciehp-interrupts-early-whe.patch new file mode 100644 index 0000000000..81d1cfc26b --- /dev/null +++ b/queue-6.14/pci-portdrv-only-disable-pciehp-interrupts-early-whe.patch @@ -0,0 +1,60 @@ +From 88fc452ed913cffb7ee8c53422ac581bfbcf08ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 10:36:30 +0800 +Subject: PCI/portdrv: Only disable pciehp interrupts early when needed + +From: Feng Tang + +[ Upstream commit 9d7db4db19827380e225914618c0c1bf435ed2f5 ] + +Firmware developers reported that Linux issues two PCIe hotplug commands in +very short intervals on an ARM server, which doesn't comply with the PCIe +spec. According to PCIe r6.1, sec 6.7.3.2, if the Command Completed event +is supported, software must wait for a command to complete or wait at +least 1 second before sending a new command. + +In the failure case, the first PCIe hotplug command is from +get_port_device_capability(), which sends a command to disable PCIe hotplug +interrupts without waiting for its completion, and the second command comes +from pcie_enable_notification() of pciehp driver, which enables hotplug +interrupts again. + +Fix this by only disabling the hotplug interrupts when the pciehp driver is +not enabled. + +Link: https://lore.kernel.org/r/20250303023630.78397-1-feng.tang@linux.alibaba.com +Fixes: 2bd50dd800b5 ("PCI: PCIe: Disable PCIe port services during port initialization") +Suggested-by: Lukas Wunner +Signed-off-by: Feng Tang +[bhelgaas: commit log] +Signed-off-by: Bjorn Helgaas +Reviewed-by: Lukas Wunner +Reviewed-by: Kuppuswamy Sathyanarayanan +Signed-off-by: Sasha Levin +--- + drivers/pci/pcie/portdrv.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/pci/pcie/portdrv.c b/drivers/pci/pcie/portdrv.c +index 02e73099bad05..e8318fd5f6ed5 100644 +--- a/drivers/pci/pcie/portdrv.c ++++ b/drivers/pci/pcie/portdrv.c +@@ -228,10 +228,12 @@ static int get_port_device_capability(struct pci_dev *dev) + + /* + * Disable hot-plug interrupts in case they have been enabled +- * by the BIOS and the hot-plug service driver is not loaded. ++ * by the BIOS and the hot-plug service driver won't be loaded ++ * to handle them. + */ +- pcie_capability_clear_word(dev, PCI_EXP_SLTCTL, +- PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE); ++ if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE)) ++ pcie_capability_clear_word(dev, PCI_EXP_SLTCTL, ++ PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE); + } + + #ifdef CONFIG_PCIEAER +-- +2.39.5 + diff --git a/queue-6.14/pci-remove-add_align-overwrite-unrelated-to-size0.patch b/queue-6.14/pci-remove-add_align-overwrite-unrelated-to-size0.patch new file mode 100644 index 0000000000..861200131d --- /dev/null +++ b/queue-6.14/pci-remove-add_align-overwrite-unrelated-to-size0.patch @@ -0,0 +1,45 @@ +From b5970add3fe71a1950687f8f69fac5815703be5a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Dec 2024 19:56:08 +0200 +Subject: PCI: Remove add_align overwrite unrelated to size0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit d06cc1e3809040e8250f69a4c656e3717e6b963c ] + +Commit 566f1dd52816 ("PCI: Relax bridge window tail sizing rules") +relaxed bridge window tail alignment rule for the non-optional part +(size0, no add_size/add_align). The change, however, also overwrote +add_align, which is only related to case where optional size1 related +entry is added into realloc head. + +Correct this by removing the add_align overwrite. + +Link: https://lore.kernel.org/r/20241216175632.4175-2-ilpo.jarvinen@linux.intel.com +Fixes: 566f1dd52816 ("PCI: Relax bridge window tail sizing rules") +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 | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c +index 3d876d493faf2..3a1fcaad142a4 100644 +--- a/drivers/pci/setup-bus.c ++++ b/drivers/pci/setup-bus.c +@@ -1149,7 +1149,6 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, + min_align = 1ULL << (max_order + __ffs(SZ_1M)); + min_align = max(min_align, win_align); + size0 = calculate_memsize(size, min_size, 0, 0, resource_size(b_res), win_align); +- add_align = win_align; + pci_info(bus->self, "bridge window %pR to %pR requires relaxed alignment rules\n", + b_res, &bus->busn_res); + } +-- +2.39.5 + diff --git a/queue-6.14/pci-remove-stray-put_device-in-pci_register_host_bri.patch b/queue-6.14/pci-remove-stray-put_device-in-pci_register_host_bri.patch new file mode 100644 index 0000000000..fa19c38df0 --- /dev/null +++ b/queue-6.14/pci-remove-stray-put_device-in-pci_register_host_bri.patch @@ -0,0 +1,41 @@ +From f3b0526a33ac038a6ea908aef08d738bc8582754 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Mar 2025 11:46:34 +0300 +Subject: PCI: Remove stray put_device() in pci_register_host_bridge() + +From: Dan Carpenter + +[ Upstream commit 6e8d06e5096c80cbf41313b4a204f43071ca42be ] + +This put_device() was accidentally left over from when we changed the code +from using device_register() to calling device_add(). Delete it. + +Link: https://lore.kernel.org/r/55b24870-89fb-4c91-b85d-744e35db53c2@stanley.mountain +Fixes: 9885440b16b8 ("PCI: Fix pci_host_bridge struct device release/free handling") +Signed-off-by: Dan Carpenter +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +--- + drivers/pci/probe.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c +index 246744d8d268a..0154b48bfbd7b 100644 +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -996,10 +996,9 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) + /* Temporarily move resources off the list */ + list_splice_init(&bridge->windows, &resources); + err = device_add(&bridge->dev); +- if (err) { +- put_device(&bridge->dev); ++ if (err) + goto free; +- } ++ + bus->bridge = get_device(&bridge->dev); + device_enable_async_suspend(bus->bridge); + pci_set_bus_of_node(bus); +-- +2.39.5 + diff --git a/queue-6.14/pci-simplify-size1-assignment-logic.patch b/queue-6.14/pci-simplify-size1-assignment-logic.patch new file mode 100644 index 0000000000..58c7540cd3 --- /dev/null +++ b/queue-6.14/pci-simplify-size1-assignment-logic.patch @@ -0,0 +1,77 @@ +From 4f9a0f857946025ee0ed8c2006f5774c662ad8de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Dec 2024 19:56:10 +0200 +Subject: PCI: Simplify size1 assignment logic +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit a55bf64b30e4ee04c8f690e2c3d0924beb7fbd62 ] + +In pbus_size_io() and pbus_size_mem(), a complex ?: operation is performed +to set size1. Decompose this so it's easier to read. + +In the case of pbus_size_mem(), simply initializing size1 to zero ensures +the size1 checks work as expected. + +Link: https://lore.kernel.org/r/20241216175632.4175-4-ilpo.jarvinen@linux.intel.com +Signed-off-by: Ilpo Järvinen +Signed-off-by: Bjorn Helgaas +Tested-by: Xiaochun Lee +Stable-dep-of: 67f9085596ee ("PCI: Allow relaxed bridge window tail sizing for optional resources") +Signed-off-by: Sasha Levin +--- + drivers/pci/setup-bus.c | 21 ++++++++++++++------- + 1 file changed, 14 insertions(+), 7 deletions(-) + +diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c +index 3a1fcaad142a4..d9f129a7735a5 100644 +--- a/drivers/pci/setup-bus.c ++++ b/drivers/pci/setup-bus.c +@@ -927,9 +927,14 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, + + size0 = calculate_iosize(size, min_size, size1, 0, 0, + resource_size(b_res), min_align); +- size1 = (!realloc_head || (realloc_head && !add_size && !children_add_size)) ? size0 : +- calculate_iosize(size, min_size, size1, add_size, children_add_size, +- resource_size(b_res), min_align); ++ ++ size1 = size0; ++ if (realloc_head && (add_size > 0 || children_add_size > 0)) { ++ size1 = calculate_iosize(size, min_size, size1, add_size, ++ children_add_size, resource_size(b_res), ++ min_align); ++ } ++ + if (!size0 && !size1) { + if (bus->self && (b_res->start || b_res->end)) + pci_info(bus->self, "disabling bridge window %pR to %pR (unused)\n", +@@ -1058,7 +1063,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, + struct list_head *realloc_head) + { + struct pci_dev *dev; +- resource_size_t min_align, win_align, align, size, size0, size1; ++ resource_size_t min_align, win_align, align, size, size0, size1 = 0; + resource_size_t aligns[24]; /* Alignments from 1MB to 8TB */ + int order, max_order; + struct resource *b_res = find_bus_resource_of_type(bus, +@@ -1153,9 +1158,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, + b_res, &bus->busn_res); + } + +- size1 = (!realloc_head || (realloc_head && !add_size && !children_add_size)) ? size0 : +- calculate_memsize(size, min_size, add_size, children_add_size, +- resource_size(b_res), add_align); ++ if (realloc_head && (add_size > 0 || children_add_size > 0)) { ++ size1 = calculate_memsize(size, min_size, add_size, children_add_size, ++ resource_size(b_res), add_align); ++ } ++ + if (!size0 && !size1) { + if (bus->self && (b_res->start || b_res->end)) + pci_info(bus->self, "disabling bridge window %pR to %pR (unused)\n", +-- +2.39.5 + diff --git a/queue-6.14/pci-use-downstream-bridges-for-distributing-resource.patch b/queue-6.14/pci-use-downstream-bridges-for-distributing-resource.patch new file mode 100644 index 0000000000..105c2e1da3 --- /dev/null +++ b/queue-6.14/pci-use-downstream-bridges-for-distributing-resource.patch @@ -0,0 +1,96 @@ +From 1c7bc6a41e1651f9098c6a9ae249aeb796b05194 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Dec 2024 10:24:57 +0800 +Subject: PCI: Use downstream bridges for distributing resources + +From: Kai-Heng Feng + +[ Upstream commit 1a596ad00ffe9b37fc60a93cbdd4daead3bf95f3 ] + +7180c1d08639 ("PCI: Distribute available resources for root buses, too") +breaks BAR assignment on some devices: + + pci 0006:03:00.0: BAR 0 [mem 0x6300c0000000-0x6300c1ffffff 64bit pref]: assigned + pci 0006:03:00.1: BAR 0 [mem 0x6300c2000000-0x6300c3ffffff 64bit pref]: assigned + pci 0006:03:00.2: BAR 0 [mem size 0x00800000 64bit pref]: can't assign; no space + pci 0006:03:00.0: VF BAR 0 [mem size 0x02000000 64bit pref]: can't assign; no space + pci 0006:03:00.1: VF BAR 0 [mem size 0x02000000 64bit pref]: can't assign; no space + +The apertures of domain 0006 before 7180c1d08639: + + 6300c0000000-63ffffffffff : PCI Bus 0006:00 + 6300c0000000-6300c9ffffff : PCI Bus 0006:01 + 6300c0000000-6300c9ffffff : PCI Bus 0006:02 # 160MB + 6300c0000000-6300c8ffffff : PCI Bus 0006:03 # 144MB + 6300c0000000-6300c1ffffff : 0006:03:00.0 # 32MB + 6300c2000000-6300c3ffffff : 0006:03:00.1 # 32MB + 6300c4000000-6300c47fffff : 0006:03:00.2 # 8MB + 6300c4800000-6300c67fffff : 0006:03:00.0 # 32MB + 6300c6800000-6300c87fffff : 0006:03:00.1 # 32MB + 6300c9000000-6300c9bfffff : PCI Bus 0006:04 # 12MB + 6300c9000000-6300c9bfffff : PCI Bus 0006:05 # 12MB + 6300c9000000-6300c91fffff : PCI Bus 0006:06 # 2MB + 6300c9200000-6300c93fffff : PCI Bus 0006:07 # 2MB + 6300c9400000-6300c95fffff : PCI Bus 0006:08 # 2MB + 6300c9600000-6300c97fffff : PCI Bus 0006:09 # 2MB + +After 7180c1d08639: + + 6300c0000000-63ffffffffff : PCI Bus 0006:00 + 6300c0000000-6300c9ffffff : PCI Bus 0006:01 + 6300c0000000-6300c9ffffff : PCI Bus 0006:02 # 160MB + 6300c0000000-6300c43fffff : PCI Bus 0006:03 # 68MB + 6300c0000000-6300c1ffffff : 0006:03:00.0 # 32MB + 6300c2000000-6300c3ffffff : 0006:03:00.1 # 32MB + --- no space --- : 0006:03:00.2 # 8MB + --- no space --- : 0006:03:00.0 # 32MB + --- no space --- : 0006:03:00.1 # 32MB + 6300c4400000-6300c4dfffff : PCI Bus 0006:04 # 10MB + 6300c4400000-6300c4dfffff : PCI Bus 0006:05 # 10MB + 6300c4400000-6300c45fffff : PCI Bus 0006:06 # 2MB + 6300c4600000-6300c47fffff : PCI Bus 0006:07 # 2MB + 6300c4800000-6300c49fffff : PCI Bus 0006:08 # 2MB + 6300c4a00000-6300c4bfffff : PCI Bus 0006:09 # 2MB + +We can see that the window to 0006:03 gets shrunken too much and 0006:04 +eats away the window for 0006:03:00.2. + +The offending commit distributes the upstream bridge's resources multiple +times to every downstream bridge, hence makes the aperture smaller than +desired because calculation of io_per_b, mmio_per_b and mmio_pref_per_b +becomes incorrect. + +Instead, distribute downstream bridges' own resources to resolve the issue. + +Link: https://lore.kernel.org/r/20241204022457.51322-1-kaihengf@nvidia.com +Fixes: 7180c1d08639 ("PCI: Distribute available resources for root buses, too") +Link: https://bugzilla.kernel.org/show_bug.cgi?id=219540 +Signed-off-by: Kai-Heng Feng +Signed-off-by: Bjorn Helgaas +Tested-by: Chia-Lin Kao (AceLan) +Reviewed-by: Mika Westerberg +Cc: Carol Soto +Cc: Jonathan Cameron +Cc: Chris Chiu +Signed-off-by: Sasha Levin +--- + drivers/pci/setup-bus.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c +index 5e00cecf1f1af..3d876d493faf2 100644 +--- a/drivers/pci/setup-bus.c ++++ b/drivers/pci/setup-bus.c +@@ -2102,8 +2102,7 @@ pci_root_bus_distribute_available_resources(struct pci_bus *bus, + * in case of root bus. + */ + if (bridge && pci_bridge_resources_not_assigned(dev)) +- pci_bridge_distribute_available_resources(bridge, +- add_list); ++ pci_bridge_distribute_available_resources(dev, add_list); + else + pci_root_bus_distribute_available_resources(b, add_list); + } +-- +2.39.5 + diff --git a/queue-6.14/pci-xilinx-cpm-fix-irq-domain-leak-in-error-path-of-.patch b/queue-6.14/pci-xilinx-cpm-fix-irq-domain-leak-in-error-path-of-.patch new file mode 100644 index 0000000000..6670ce1924 --- /dev/null +++ b/queue-6.14/pci-xilinx-cpm-fix-irq-domain-leak-in-error-path-of-.patch @@ -0,0 +1,65 @@ +From 18ffd29ea42f8dd7377e1b2e70b4e28194089ded Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 21:20:22 +0530 +Subject: PCI: xilinx-cpm: Fix IRQ domain leak in error path of probe +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Thippeswamy Havalige + +[ Upstream commit 57b0302240741e73fe51f88404b3866e0d2933ad ] + +The IRQ domain allocated for the PCIe controller is not freed if +resource_list_first_type() returns NULL, leading to a resource leak. + +This fix ensures properly cleaning up the allocated IRQ domain in +the error path. + +Fixes: 49e427e6bdd1 ("Merge branch 'pci/host-probe-refactor'") +Signed-off-by: Thippeswamy Havalige +[kwilczynski: added missing Fixes: tag, refactored to use one of the goto labels] +Signed-off-by: Krzysztof Wilczyński +Link: https://lore.kernel.org/r/20250224155025.782179-2-thippeswamy.havalige@amd.com +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-xilinx-cpm.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/pci/controller/pcie-xilinx-cpm.c b/drivers/pci/controller/pcie-xilinx-cpm.c +index 81e8bfae53d00..dc8ecdbee56c8 100644 +--- a/drivers/pci/controller/pcie-xilinx-cpm.c ++++ b/drivers/pci/controller/pcie-xilinx-cpm.c +@@ -583,15 +583,17 @@ static int xilinx_cpm_pcie_probe(struct platform_device *pdev) + return err; + + bus = resource_list_first_type(&bridge->windows, IORESOURCE_BUS); +- if (!bus) +- return -ENODEV; ++ if (!bus) { ++ err = -ENODEV; ++ goto err_free_irq_domains; ++ } + + port->variant = of_device_get_match_data(dev); + + err = xilinx_cpm_pcie_parse_dt(port, bus->res); + if (err) { + dev_err(dev, "Parsing DT failed\n"); +- goto err_parse_dt; ++ goto err_free_irq_domains; + } + + xilinx_cpm_pcie_init_port(port); +@@ -615,7 +617,7 @@ static int xilinx_cpm_pcie_probe(struct platform_device *pdev) + xilinx_cpm_free_interrupts(port); + err_setup_irq: + pci_ecam_free(port->cfg); +-err_parse_dt: ++err_free_irq_domains: + xilinx_cpm_free_irq_domains(port); + return err; + } +-- +2.39.5 + diff --git a/queue-6.14/perf-always-feature-test-reallocarray.patch b/queue-6.14/perf-always-feature-test-reallocarray.patch new file mode 100644 index 0000000000..8e089fb755 --- /dev/null +++ b/queue-6.14/perf-always-feature-test-reallocarray.patch @@ -0,0 +1,86 @@ +From 9697b5e0996a53e781f29001534c9a3cbd0636af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 15:44:05 +0000 +Subject: perf: Always feature test reallocarray + +From: James Clark + +[ Upstream commit 4c4c0724d6521a8092b7c16f8f210c5869d95b17 ] + +This is also used in util/comm.c now, so instead of selectively doing +the feature test, always do it. If it's ever used anywhere else it's +less likely to cause another build failure. + +This doesn't remove the need to manually include libc_compat.h, and +missing that will still cause an error for glibc < 2.26. There isn't a +way to fix that without poisoning reallocarray like libbpf did, but that +has other downsides like making memory debugging tools less useful. So +for Perf keep it like this and we'll have to fix up any missed includes. + +Fixes the following build error: + + util/comm.c:152:31: error: implicit declaration of function + 'reallocarray' [-Wimplicit-function-declaration] + 152 | tmp = reallocarray(comm_strs->strs, + | ^~~~~~~~~~~~ + +Fixes: 13ca628716c6 ("perf comm: Add reference count checking to 'struct comm_str'") +Reported-by: Ali Utku Selen +Signed-off-by: James Clark +Reviewed-by: Ian Rogers +Link: https://lore.kernel.org/r/20250129154405.777533-1-james.clark@linaro.org +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/Makefile.config | 10 ++++------ + tools/perf/util/comm.c | 2 ++ + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config +index a148ca9efca91..23dbb6bb91cf8 100644 +--- a/tools/perf/Makefile.config ++++ b/tools/perf/Makefile.config +@@ -497,13 +497,14 @@ ifeq ($(feature-setns), 1) + $(call detected,CONFIG_SETNS) + endif + ++ifeq ($(feature-reallocarray), 0) ++ CFLAGS += -DCOMPAT_NEED_REALLOCARRAY ++endif ++ + ifdef CORESIGHT + $(call feature_check,libopencsd) + ifeq ($(feature-libopencsd), 1) + CFLAGS += -DHAVE_CSTRACE_SUPPORT $(LIBOPENCSD_CFLAGS) +- ifeq ($(feature-reallocarray), 0) +- CFLAGS += -DCOMPAT_NEED_REALLOCARRAY +- endif + LDFLAGS += $(LIBOPENCSD_LDFLAGS) + EXTLIBS += $(OPENCSDLIBS) + $(call detected,CONFIG_LIBOPENCSD) +@@ -1103,9 +1104,6 @@ ifndef NO_AUXTRACE + ifndef NO_AUXTRACE + $(call detected,CONFIG_AUXTRACE) + CFLAGS += -DHAVE_AUXTRACE_SUPPORT +- ifeq ($(feature-reallocarray), 0) +- CFLAGS += -DCOMPAT_NEED_REALLOCARRAY +- endif + endif + endif + +diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c +index 49b79cf0c5cc5..8aa456d7c2cd2 100644 +--- a/tools/perf/util/comm.c ++++ b/tools/perf/util/comm.c +@@ -5,6 +5,8 @@ + #include + #include + #include ++#include // reallocarray ++ + #include "rwsem.h" + + DECLARE_RC_STRUCT(comm_str) { +-- +2.39.5 + diff --git a/queue-6.14/perf-arm-spe-fix-load-store-operation-checking.patch b/queue-6.14/perf-arm-spe-fix-load-store-operation-checking.patch new file mode 100644 index 0000000000..e14ffd94b4 --- /dev/null +++ b/queue-6.14/perf-arm-spe-fix-load-store-operation-checking.patch @@ -0,0 +1,64 @@ +From 9229fc8f1b7c158c821917f1812aa33d74e8e271 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 11:12:34 +0000 +Subject: perf arm-spe: Fix load-store operation checking + +From: Leo Yan + +[ Upstream commit e1d47850bbf79a541c9b3bacdd562f5e0112274d ] + +The ARM_SPE_OP_LD and ARM_SPE_OP_ST operations are secondary operation +type, they are overlapping with other second level's operation types +belonging to SVE and branch operations. As a result, a non load-store +operation can be parsed for data source and memory sample. + +To fix the issue, this commit introduces a is_ldst_op() macro for +checking LDST operation, and apply the checking when synthesize data +source and memory samples. + +Fixes: a89dbc9b988f ("perf arm-spe: Set sample's data source field") +Signed-off-by: Leo Yan +Reviewed-by: James Clark +Link: https://lore.kernel.org/r/20250304111240.3378214-7-leo.yan@arm.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/util/arm-spe.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c +index 12761c39788f8..f1365ce69ba08 100644 +--- a/tools/perf/util/arm-spe.c ++++ b/tools/perf/util/arm-spe.c +@@ -37,6 +37,8 @@ + #include "../../arch/arm64/include/asm/cputype.h" + #define MAX_TIMESTAMP (~0ULL) + ++#define is_ldst_op(op) (!!((op) & ARM_SPE_OP_LDST)) ++ + struct arm_spe { + struct auxtrace auxtrace; + struct auxtrace_queues queues; +@@ -669,6 +671,10 @@ static u64 arm_spe__synth_data_source(struct arm_spe_queue *speq, + { + union perf_mem_data_src data_src = { .mem_op = PERF_MEM_OP_NA }; + ++ /* Only synthesize data source for LDST operations */ ++ if (!is_ldst_op(record->op)) ++ return 0; ++ + if (record->op & ARM_SPE_OP_LD) + data_src.mem_op = PERF_MEM_OP_LOAD; + else if (record->op & ARM_SPE_OP_ST) +@@ -767,7 +773,7 @@ static int arm_spe_sample(struct arm_spe_queue *speq) + * When data_src is zero it means the record is not a memory operation, + * skip to synthesize memory sample for this case. + */ +- if (spe->sample_memory && data_src) { ++ if (spe->sample_memory && is_ldst_op(record->op)) { + err = arm_spe__synth_mem_sample(speq, spe->memory_id, data_src); + if (err) + return err; +-- +2.39.5 + diff --git a/queue-6.14/perf-bench-fix-perf-bench-syscall-loop-count.patch b/queue-6.14/perf-bench-fix-perf-bench-syscall-loop-count.patch new file mode 100644 index 0000000000..a728a757a9 --- /dev/null +++ b/queue-6.14/perf-bench-fix-perf-bench-syscall-loop-count.patch @@ -0,0 +1,104 @@ +From 447e5a46663329296a118ac17ea5c54e1309fc8f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 10:23:49 +0100 +Subject: perf bench: Fix perf bench syscall loop count + +From: Thomas Richter + +[ Upstream commit 957d194163bf983da98bf7ec7e4f86caff8cd0eb ] + +Command 'perf bench syscall fork -l 100000' offers option -l to run for +a specified number of iterations. However this option is not always +observed. The number is silently limited to 10000 iterations as can be +seen: + +Output before: + # perf bench syscall fork -l 100000 + # Running 'syscall/fork' benchmark: + # Executed 10,000 fork() calls + Total time: 23.388 [sec] + + 2338.809800 usecs/op + 427 ops/sec + # + +When explicitly specified with option -l or --loops, also observe +higher number of iterations: + +Output after: + # perf bench syscall fork -l 100000 + # Running 'syscall/fork' benchmark: + # Executed 100,000 fork() calls + Total time: 716.982 [sec] + + 7169.829510 usecs/op + 139 ops/sec + # + +This patch fixes the issue for basic execve fork and getpgid. + +Fixes: ece7f7c0507c ("perf bench syscall: Add fork syscall benchmark") +Signed-off-by: Thomas Richter +Acked-by: Sumanth Korikkar +Tested-by: Athira Rajeev +Cc: Tiezhu Yang +Link: https://lore.kernel.org/r/20250304092349.2618082-1-tmricht@linux.ibm.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/bench/syscall.c | 22 +++++++++++++--------- + 1 file changed, 13 insertions(+), 9 deletions(-) + +diff --git a/tools/perf/bench/syscall.c b/tools/perf/bench/syscall.c +index ea4dfc07cbd6b..e7dc216f717f5 100644 +--- a/tools/perf/bench/syscall.c ++++ b/tools/perf/bench/syscall.c +@@ -22,8 +22,7 @@ + #define __NR_fork -1 + #endif + +-#define LOOPS_DEFAULT 10000000 +-static int loops = LOOPS_DEFAULT; ++static int loops; + + static const struct option options[] = { + OPT_INTEGER('l', "loop", &loops, "Specify number of loops"), +@@ -80,6 +79,18 @@ static int bench_syscall_common(int argc, const char **argv, int syscall) + const char *name = NULL; + int i; + ++ switch (syscall) { ++ case __NR_fork: ++ case __NR_execve: ++ /* Limit default loop to 10000 times to save time */ ++ loops = 10000; ++ break; ++ default: ++ loops = 10000000; ++ break; ++ } ++ ++ /* Options -l and --loops override default above */ + argc = parse_options(argc, argv, options, bench_syscall_usage, 0); + + gettimeofday(&start, NULL); +@@ -94,16 +105,9 @@ static int bench_syscall_common(int argc, const char **argv, int syscall) + break; + case __NR_fork: + test_fork(); +- /* Only loop 10000 times to save time */ +- if (i == 10000) +- loops = 10000; + break; + case __NR_execve: + test_execve(); +- /* Only loop 10000 times to save time */ +- if (i == 10000) +- loops = 10000; +- break; + default: + break; + } +-- +2.39.5 + diff --git a/queue-6.14/perf-bpf-filter-fix-a-parsing-error-with-comma.patch b/queue-6.14/perf-bpf-filter-fix-a-parsing-error-with-comma.patch new file mode 100644 index 0000000000..8cce19bf7e --- /dev/null +++ b/queue-6.14/perf-bpf-filter-fix-a-parsing-error-with-comma.patch @@ -0,0 +1,81 @@ +From 79b2ca3bb34c255cfcd72995c4bc8d006caa09c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Mar 2025 14:09:21 -0800 +Subject: perf bpf-filter: Fix a parsing error with comma + +From: Namhyung Kim + +[ Upstream commit 35d13f841a3d8159ef20d5e32a9ed3faa27875bc ] + +The previous change to support cgroup filters introduced a bug that +pathname can include commas. It confused the lexer to treat an item and +the trailing comma as a single token. And it resulted in a parse error: + + $ sudo perf record -e cycles:P --filter 'period > 0, ip > 64' -- true + perf_bpf_filter: Error: Unexpected item: 0, + perf_bpf_filter: syntax error, unexpected BFT_ERROR, expecting BFT_NUM + + Usage: perf record [] [] + or: perf record [] -- [] + + --filter + event filter + +It should get "0" and "," separately. + +An easiest fix would be to remove "," from the possible pathname +characters. As it's for cgroup names, probably ok to assume it won't +have commas in the pathname. + +I found that the existing BPF filtering test didn't have any complex +filter condition with commas. Let's update the group filter test which +is supposed to test filter combinations like this. + +Link: https://lore.kernel.org/r/20250307220922.434319-1-namhyung@kernel.org +Fixes: 91e88437d5156b20 ("perf bpf-filter: Support filtering on cgroups") +Reported-by: Sally Shi +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/tests/shell/record_bpf_filter.sh | 4 ++-- + tools/perf/util/bpf-filter.l | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tools/perf/tests/shell/record_bpf_filter.sh b/tools/perf/tests/shell/record_bpf_filter.sh +index 1b58ccc1fd882..4d6c3c1b7fb92 100755 +--- a/tools/perf/tests/shell/record_bpf_filter.sh ++++ b/tools/perf/tests/shell/record_bpf_filter.sh +@@ -89,7 +89,7 @@ test_bpf_filter_fail() { + test_bpf_filter_group() { + echo "Group bpf-filter test" + +- if ! perf record -e task-clock --filter 'period > 1000 || ip > 0' \ ++ if ! perf record -e task-clock --filter 'period > 1000, ip > 0' \ + -o /dev/null true 2>/dev/null + then + echo "Group bpf-filter test [Failed should succeed]" +@@ -97,7 +97,7 @@ test_bpf_filter_group() { + return + fi + +- if ! perf record -e task-clock --filter 'cpu > 0 || ip > 0' \ ++ if ! perf record -e task-clock --filter 'period > 1000 , cpu > 0 || ip > 0' \ + -o /dev/null true 2>&1 | grep -q PERF_SAMPLE_CPU + then + echo "Group bpf-filter test [Failed forbidden CPU]" +diff --git a/tools/perf/util/bpf-filter.l b/tools/perf/util/bpf-filter.l +index f313404f95a90..6aa65ade33851 100644 +--- a/tools/perf/util/bpf-filter.l ++++ b/tools/perf/util/bpf-filter.l +@@ -76,7 +76,7 @@ static int path_or_error(void) + num_dec [0-9]+ + num_hex 0[Xx][0-9a-fA-F]+ + space [ \t]+ +-path [^ \t\n]+ ++path [^ \t\n,]+ + ident [_a-zA-Z][_a-zA-Z0-9]+ + + %% +-- +2.39.5 + diff --git a/queue-6.14/perf-build-fix-in-tree-build-due-to-symbolic-link.patch b/queue-6.14/perf-build-fix-in-tree-build-due-to-symbolic-link.patch new file mode 100644 index 0000000000..7d7a481340 --- /dev/null +++ b/queue-6.14/perf-build-fix-in-tree-build-due-to-symbolic-link.patch @@ -0,0 +1,80 @@ +From 1f7c527356926c62b491887005ae51635184b6ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 14:06:08 +0100 +Subject: perf build: Fix in-tree build due to symbolic link + +From: Luca Ceresoli + +[ Upstream commit 75100d848ef4b8ca39bb6dd3a21181e37dea27e2 ] + +Building perf in-tree is broken after commit 890a1961c812 ("perf tools: +Create source symlink in perf object dir") which added a 'source' symlink +in the output dir pointing to the source dir. + +With in-tree builds, the added 'SOURCE = ...' line is executed multiple +times (I observed 2 during the build plus 2 during installation). This is a +minor inefficiency, in theory not harmful because symlink creation is +assumed to be idempotent. But it is not. + +Considering with in-tree builds: + + srctree=/absolute/path/to/linux + OUTPUT=/absolute/path/to/linux/tools/perf + +here's what happens: + + 1. ln -sf $(srctree)/tools/perf $(OUTPUT)/source + -> creates /absolute/path/to/linux/tools/perf/source + link to /absolute/path/to/linux/tools/perf + => OK, that's what was intended + 2. ln -sf $(srctree)/tools/perf $(OUTPUT)/source # same command as 1 + -> creates /absolute/path/to/linux/tools/perf/perf + link to /absolute/path/to/linux/tools/perf + => Not what was intended, not idempotent + 3. Now the build _should_ create the 'perf' executable, but it fails + +The reason is the tricky 'ln' command line. At the first invocation 'ln' +uses the 1st form: + + ln [OPTION]... [-T] TARGET LINK_NAME + +and creates a link to TARGET *called LINK_NAME*. + +At the second invocation $(OUTPUT)/source exists, so 'ln' uses the 3rd +form: + + ln [OPTION]... TARGET... DIRECTORY + +and creates a link to TARGET *called TARGET* inside DIRECTORY. + +Fix by adding -n/--no-dereference to "treat LINK_NAME as a normal file +if it is a symbolic link to a directory", as the manpage says. + +Closes: https://lore.kernel.org/all/20241125182506.38af9907@booty/ +Fixes: 890a1961c812 ("perf tools: Create source symlink in perf object dir") +Signed-off-by: Luca Ceresoli +Reviewed-by: Charlie Jenkins +Tested-by: Charlie Jenkins +Link: https://lore.kernel.org/r/20250124-perf-fix-intree-build-v1-1-485dd7a855e4@bootlin.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/Makefile.perf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf +index 05c083bb11220..eea8877c7cba3 100644 +--- a/tools/perf/Makefile.perf ++++ b/tools/perf/Makefile.perf +@@ -158,7 +158,7 @@ ifneq ($(OUTPUT),) + VPATH += $(OUTPUT) + export VPATH + # create symlink to the original source +-SOURCE := $(shell ln -sf $(srctree)/tools/perf $(OUTPUT)/source) ++SOURCE := $(shell ln -sfn $(srctree)/tools/perf $(OUTPUT)/source) + endif + + # Do not use make's built-in rules +-- +2.39.5 + diff --git a/queue-6.14/perf-debug-avoid-stack-overflow-in-recursive-error-m.patch b/queue-6.14/perf-debug-avoid-stack-overflow-in-recursive-error-m.patch new file mode 100644 index 0000000000..43b9f473e8 --- /dev/null +++ b/queue-6.14/perf-debug-avoid-stack-overflow-in-recursive-error-m.patch @@ -0,0 +1,41 @@ +From 088e63bd3546eb886cbc707398b135a7b9e2e955 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 14:22:58 -0800 +Subject: perf debug: Avoid stack overflow in recursive error message + +From: Ian Rogers + +[ Upstream commit bda840191d2aae3b7cadc3ac21835dcf29487191 ] + +In debug_file, pr_warning_once is called on error. As that function +calls debug_file the function will yield a stack overflow. Switch the +location of the call so the recursion is avoided. + +Reviewed-by: Howard Chu +Signed-off-by: Ian Rogers +Reviewed-by: Arnaldo Carvalho de Melo +Link: https://lore.kernel.org/r/20250228222308.626803-2-irogers@google.com +Fixes: ec49230cf6dda704 ("perf debug: Expose debug file") +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/util/debug.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c +index 995f6bb05b5f8..f9ef7d045c92e 100644 +--- a/tools/perf/util/debug.c ++++ b/tools/perf/util/debug.c +@@ -46,8 +46,8 @@ int debug_type_profile; + FILE *debug_file(void) + { + if (!_debug_file) { +- pr_warning_once("debug_file not set"); + debug_set_file(stderr); ++ pr_warning_once("debug_file not set"); + } + return _debug_file; + } +-- +2.39.5 + diff --git a/queue-6.14/perf-dso-fix-dso__is_kallsyms-check.patch b/queue-6.14/perf-dso-fix-dso__is_kallsyms-check.patch new file mode 100644 index 0000000000..e2e4114fc3 --- /dev/null +++ b/queue-6.14/perf-dso-fix-dso__is_kallsyms-check.patch @@ -0,0 +1,63 @@ +From 8d3ba02c275ec9d2725d557d011b8a68ec784343 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 16:00:11 -0700 +Subject: perf dso: fix dso__is_kallsyms() check + +From: Stephen Brennan + +[ Upstream commit ebf0b332732dcc64239119e554faa946562b0b93 ] + +Kernel modules for which we cannot find a file on-disk will have a +dso->long_name that looks like "[module_name]". Prior to the commit +listed in the fixes, the dso->kernel field would be zero (for user +space), so dso__is_kallsyms() would return false. After the commit, +kernel module DSOs are correctly labeled, but the result is that +dso__is_kallsyms() erroneously returns true for those modules without a +filesystem path. + +Later, build_id_cache__add() consults this value of is_kallsyms, and +when true, it copies /proc/kallsyms into the cache. Users with many +kernel modules without a filesystem path (e.g. ksplice or possibly +kernel live patch modules) have reported excessive disk space usage in +the build ID cache directory due to this behavior. + +To reproduce the issue, it's enough to build a trivial out-of-tree hello +world kernel module, load it using insmod, and then use: + + perf record -ag -- sleep 1 + +In the build ID directory, there will be a directory for your module +name containing a kallsyms file. + +Fix this up by changing dso__is_kallsyms() to consult the +dso_binary_type enumeration, which is also symmetric to the above checks +for dso__is_vmlinux() and dso__is_kcore(). With this change, kallsyms is +not cached in the build-id cache for out-of-tree modules. + +Fixes: 02213cec64bbe ("perf maps: Mark module DSOs with kernel type") +Signed-off-by: Stephen Brennan +Link: https://lore.kernel.org/r/20250318230012.2038790-1-stephen.s.brennan@oracle.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/util/dso.h | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h +index bb8e8f444054d..c0472a41147c3 100644 +--- a/tools/perf/util/dso.h ++++ b/tools/perf/util/dso.h +@@ -808,7 +808,9 @@ static inline bool dso__is_kcore(const struct dso *dso) + + static inline bool dso__is_kallsyms(const struct dso *dso) + { +- return RC_CHK_ACCESS(dso)->kernel && RC_CHK_ACCESS(dso)->long_name[0] != '/'; ++ enum dso_binary_type bt = dso__binary_type(dso); ++ ++ return bt == DSO_BINARY_TYPE__KALLSYMS || bt == DSO_BINARY_TYPE__GUEST_KALLSYMS; + } + + bool dso__is_object_file(const struct dso *dso); +-- +2.39.5 + diff --git a/queue-6.14/perf-evlist-add-success-path-to-evlist__create_syswi.patch b/queue-6.14/perf-evlist-add-success-path-to-evlist__create_syswi.patch new file mode 100644 index 0000000000..57143ff803 --- /dev/null +++ b/queue-6.14/perf-evlist-add-success-path-to-evlist__create_syswi.patch @@ -0,0 +1,57 @@ +From 756ecb1c93287330bdec868702c03917a7684e99 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 14:22:59 -0800 +Subject: perf evlist: Add success path to evlist__create_syswide_maps + +From: Ian Rogers + +[ Upstream commit fe0ce8a9d85a48642880c9b78944cb0d23e779c5 ] + +Over various refactorings evlist__create_syswide_maps has been made to +only ever return with -ENOMEM. Fix this so that when +perf_evlist__set_maps is successfully called, 0 is returned. + +Reviewed-by: Howard Chu +Signed-off-by: Ian Rogers +Reviewed-by: Arnaldo Carvalho de Melo +Link: https://lore.kernel.org/r/20250228222308.626803-3-irogers@google.com +Fixes: 8c0498b6891d7ca5 ("perf evlist: Fix create_syswide_maps() not propagating maps") +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/util/evlist.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c +index f0dd174e2debd..633df7d9204c2 100644 +--- a/tools/perf/util/evlist.c ++++ b/tools/perf/util/evlist.c +@@ -1373,19 +1373,18 @@ static int evlist__create_syswide_maps(struct evlist *evlist) + */ + cpus = perf_cpu_map__new_online_cpus(); + if (!cpus) +- goto out; ++ return -ENOMEM; + + threads = perf_thread_map__new_dummy(); +- if (!threads) +- goto out_put; ++ if (!threads) { ++ perf_cpu_map__put(cpus); ++ return -ENOMEM; ++ } + + perf_evlist__set_maps(&evlist->core, cpus, threads); +- + perf_thread_map__put(threads); +-out_put: + perf_cpu_map__put(cpus); +-out: +- return -ENOMEM; ++ return 0; + } + + int evlist__open(struct evlist *evlist) +-- +2.39.5 + diff --git a/queue-6.14/perf-evsel-tp_format-accessing-improvements.patch b/queue-6.14/perf-evsel-tp_format-accessing-improvements.patch new file mode 100644 index 0000000000..e989f14a4d --- /dev/null +++ b/queue-6.14/perf-evsel-tp_format-accessing-improvements.patch @@ -0,0 +1,62 @@ +From 698c69d6eec877f4082eb3f02c7dda65a2ac3cd3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 14:23:00 -0800 +Subject: perf evsel: tp_format accessing improvements + +From: Ian Rogers + +[ Upstream commit eb7e83a7ca2dba01671c711e1711705e1a15626d ] + +Ensure evsel__clone copies the tp_sys and tp_name variables. +In evsel__tp_format, if tp_sys isn't set, use the config value to find +the tp_format. This succeeds in python code where pyrf__tracepoint has +already found the format. + +Reviewed-by: Howard Chu +Signed-off-by: Ian Rogers +Reviewed-by: Arnaldo Carvalho de Melo +Link: https://lore.kernel.org/r/20250228222308.626803-4-irogers@google.com +Fixes: 6c8310e8380d472c ("perf evsel: Allow evsel__newtp without libtraceevent") +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/util/evsel.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c +index bc144388f8929..9cd78cdee6282 100644 +--- a/tools/perf/util/evsel.c ++++ b/tools/perf/util/evsel.c +@@ -511,6 +511,16 @@ struct evsel *evsel__clone(struct evsel *dest, struct evsel *orig) + } + evsel->cgrp = cgroup__get(orig->cgrp); + #ifdef HAVE_LIBTRACEEVENT ++ if (orig->tp_sys) { ++ evsel->tp_sys = strdup(orig->tp_sys); ++ if (evsel->tp_sys == NULL) ++ goto out_err; ++ } ++ if (orig->tp_name) { ++ evsel->tp_name = strdup(orig->tp_name); ++ if (evsel->tp_name == NULL) ++ goto out_err; ++ } + evsel->tp_format = orig->tp_format; + #endif + evsel->handler = orig->handler; +@@ -634,7 +644,11 @@ struct tep_event *evsel__tp_format(struct evsel *evsel) + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) + return NULL; + +- tp_format = trace_event__tp_format(evsel->tp_sys, evsel->tp_name); ++ if (!evsel->tp_sys) ++ tp_format = trace_event__tp_format_id(evsel->core.attr.config); ++ else ++ tp_format = trace_event__tp_format(evsel->tp_sys, evsel->tp_name); ++ + if (IS_ERR(tp_format)) { + int err = -PTR_ERR(evsel->tp_format); + +-- +2.39.5 + diff --git a/queue-6.14/perf-intel-tpebs-fix-incorrect-usage-of-zfree.patch b/queue-6.14/perf-intel-tpebs-fix-incorrect-usage-of-zfree.patch new file mode 100644 index 0000000000..ff5a727a81 --- /dev/null +++ b/queue-6.14/perf-intel-tpebs-fix-incorrect-usage-of-zfree.patch @@ -0,0 +1,39 @@ +From b66199ec3475c25185cd920958ba7edbb4e70f68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 10:16:10 +0000 +Subject: perf: intel-tpebs: Fix incorrect usage of zfree() + +From: James Clark + +[ Upstream commit 6d2dcd635204c023eb5328ad7d38b198a5558c9b ] + +zfree() requires an address otherwise it frees what's in name, rather +than name itself. Pass the address of name to fix it. + +This was the only incorrect occurrence in Perf found using a search. + +Fixes: 8db5cabcf1b6 ("perf stat: Fork and launch 'perf record' when 'perf stat' needs to get retire latency value for a metric.") +Signed-off-by: James Clark +Link: https://lore.kernel.org/r/20250319101614.190922-1-james.clark@linaro.org +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/util/intel-tpebs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/intel-tpebs.c b/tools/perf/util/intel-tpebs.c +index 50a3c3e071606..2c421b475b3b8 100644 +--- a/tools/perf/util/intel-tpebs.c ++++ b/tools/perf/util/intel-tpebs.c +@@ -254,7 +254,7 @@ int tpebs_start(struct evlist *evsel_list) + new = zalloc(sizeof(*new)); + if (!new) { + ret = -1; +- zfree(name); ++ zfree(&name); + goto err; + } + new->name = name; +-- +2.39.5 + diff --git a/queue-6.14/perf-machine-fixup-kernel-maps-ends-after-adding-ext.patch b/queue-6.14/perf-machine-fixup-kernel-maps-ends-after-adding-ext.patch new file mode 100644 index 0000000000..e826fbcbff --- /dev/null +++ b/queue-6.14/perf-machine-fixup-kernel-maps-ends-after-adding-ext.patch @@ -0,0 +1,51 @@ +From 12baa545c8f606621e68677d3088a7ccbe7f24d3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 18:17:31 -0300 +Subject: perf machine: Fixup kernel maps ends after adding extra maps + +From: Namhyung Kim + +[ Upstream commit f7a46e028c394cd422326caa7a2ad6ba0cd87915 ] + +I just noticed it would add extra kernel maps after modules. I think it +should fixup end address of the kernel maps after adding all maps first. + +Fixes: 876e80cf83d10585 ("perf tools: Fixup end address of modules") +Reported-by: Arnaldo Carvalho de Melo +Tested-by: Arnaldo Carvalho de Melo +Reviewed-by: Ian Rogers +Link: https://lore.kernel.org/lkml/Z7TvZGjVix2asYWI@x1 +Link: https://lore.kernel.org/lkml/Z712hzvv22Ni63f1@google.com +Link: https://lore.kernel.org/r/20250228211734.33781-4-acme@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/util/machine.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c +index 2d51badfbf2e2..9c7bf17bcbe86 100644 +--- a/tools/perf/util/machine.c ++++ b/tools/perf/util/machine.c +@@ -1468,8 +1468,6 @@ static int machine__create_modules(struct machine *machine) + if (modules__parse(modules, machine, machine__create_module)) + return -1; + +- maps__fixup_end(machine__kernel_maps(machine)); +- + if (!machine__set_modules_path(machine)) + return 0; + +@@ -1563,6 +1561,8 @@ int machine__create_kernel_maps(struct machine *machine) + } + } + ++ maps__fixup_end(machine__kernel_maps(machine)); ++ + out_put: + dso__put(kernel); + return ret; +-- +2.39.5 + diff --git a/queue-6.14/perf-pmu-don-t-double-count-common-sysfs-and-json-ev.patch b/queue-6.14/perf-pmu-don-t-double-count-common-sysfs-and-json-ev.patch new file mode 100644 index 0000000000..d436289d87 --- /dev/null +++ b/queue-6.14/perf-pmu-don-t-double-count-common-sysfs-and-json-ev.patch @@ -0,0 +1,81 @@ +From c97516c33509a5ad3ddbe5ed796c873d3a1c59f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 10:41:01 +0000 +Subject: perf pmu: Don't double count common sysfs and json events + +From: James Clark + +[ Upstream commit c9d699e10fa6c0cdabcddcf991e7ff42af6b2503 ] + +After pmu_add_cpu_aliases() is called, perf_pmu__num_events() returns an +incorrect value that double counts common events and doesn't match the +actual count of events in the alias list. This is because after +'cpu_aliases_added == true', the number of events returned is +'sysfs_aliases + cpu_json_aliases'. But when adding 'case +EVENT_SRC_SYSFS' events, 'sysfs_aliases' and 'cpu_json_aliases' are both +incremented together, failing to account that these ones overlap and +only add a single item to the list. Fix it by adding another counter for +overlapping events which doesn't influence 'cpu_json_aliases'. + +There doesn't seem to be a current issue because it's used in perf list +before pmu_add_cpu_aliases() so the correct value is returned. Other +uses in tests may also miss it for other reasons like only looking at +uncore events. However it's marked as a fixes commit in case any new fix +with new uses of perf_pmu__num_events() is backported. + +Fixes: d9c5f5f94c2d ("perf pmu: Count sys and cpuid JSON events separately") +Reviewed-by: Ian Rogers +Signed-off-by: James Clark +Link: https://lore.kernel.org/r/20250226104111.564443-3-james.clark@linaro.org +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/util/pmu.c | 7 ++++--- + tools/perf/util/pmu.h | 5 +++++ + 2 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index a8193ac8f2e7d..98cc525dc9ded 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -596,7 +596,7 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, + }; + if (pmu_events_table__find_event(pmu->events_table, pmu, name, + update_alias, &data) == 0) +- pmu->cpu_json_aliases++; ++ pmu->cpu_common_json_aliases++; + } + pmu->sysfs_aliases++; + break; +@@ -1851,9 +1851,10 @@ size_t perf_pmu__num_events(struct perf_pmu *pmu) + if (pmu->cpu_aliases_added) + nr += pmu->cpu_json_aliases; + else if (pmu->events_table) +- nr += pmu_events_table__num_events(pmu->events_table, pmu) - pmu->cpu_json_aliases; ++ nr += pmu_events_table__num_events(pmu->events_table, pmu) - ++ pmu->cpu_common_json_aliases; + else +- assert(pmu->cpu_json_aliases == 0); ++ assert(pmu->cpu_json_aliases == 0 && pmu->cpu_common_json_aliases == 0); + + if (perf_pmu__is_tool(pmu)) + nr -= tool_pmu__num_skip_events(); +diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h +index edd36c20aedc2..deaf9c268ed13 100644 +--- a/tools/perf/util/pmu.h ++++ b/tools/perf/util/pmu.h +@@ -136,6 +136,11 @@ struct perf_pmu { + uint32_t cpu_json_aliases; + /** @sys_json_aliases: Number of json event aliases loaded matching the PMU's identifier. */ + uint32_t sys_json_aliases; ++ /** ++ * @cpu_common_json_aliases: Number of json events that overlapped with sysfs when ++ * loading all sysfs events. ++ */ ++ uint32_t cpu_common_json_aliases; + /** @sysfs_aliases_loaded: Are sysfs aliases loaded from disk? */ + bool sysfs_aliases_loaded; + /** +-- +2.39.5 + diff --git a/queue-6.14/perf-pmu-dynamically-allocate-tool-pmu.patch b/queue-6.14/perf-pmu-dynamically-allocate-tool-pmu.patch new file mode 100644 index 0000000000..76418722bc --- /dev/null +++ b/queue-6.14/perf-pmu-dynamically-allocate-tool-pmu.patch @@ -0,0 +1,101 @@ +From 94ee44495c0084c916d7d11de1bb4b44bd040aa4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 10:41:00 +0000 +Subject: perf pmu: Dynamically allocate tool PMU + +From: James Clark + +[ Upstream commit 72c6f57a4193f2eadceb52261315438719c4c1ad ] + +perf_pmus__destroy() treats all PMUs as allocated and free's them so we +can't have any static PMUs that are added to the PMU lists. Fix it by +allocating the tool PMU in the same way as the others. Current users of +the tool PMU already use find_pmu() and not perf_pmus__tool_pmu(), so +rename the function to add 'new' to avoid it being misused in the +future. + +perf_pmus__fake_pmu() can remain as static as it's not added to the +PMU lists. + +Fixes the following error: + + $ perf bench internals pmu-scan + + # Running 'internals/pmu-scan' benchmark: + Computing performance of sysfs PMU event scan for 100 times + munmap_chunk(): invalid pointer + Aborted (core dumped) + +Fixes: 240505b2d0ad ("perf tool_pmu: Factor tool events into their own PMU") +Reviewed-by: Ian Rogers +Signed-off-by: James Clark +Link: https://lore.kernel.org/r/20250226104111.564443-2-james.clark@linaro.org +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/util/pmus.c | 2 +- + tools/perf/util/tool_pmu.c | 23 +++++++++++------------ + tools/perf/util/tool_pmu.h | 2 +- + 3 files changed, 13 insertions(+), 14 deletions(-) + +diff --git a/tools/perf/util/pmus.c b/tools/perf/util/pmus.c +index 8a0a919415d49..6498021acef01 100644 +--- a/tools/perf/util/pmus.c ++++ b/tools/perf/util/pmus.c +@@ -268,7 +268,7 @@ static void pmu_read_sysfs(unsigned int to_read_types) + + if ((to_read_types & PERF_TOOL_PMU_TYPE_TOOL_MASK) != 0 && + (read_pmu_types & PERF_TOOL_PMU_TYPE_TOOL_MASK) == 0) { +- tool_pmu = perf_pmus__tool_pmu(); ++ tool_pmu = tool_pmu__new(); + list_add_tail(&tool_pmu->list, &other_pmus); + } + if ((to_read_types & PERF_TOOL_PMU_TYPE_HWMON_MASK) != 0 && +diff --git a/tools/perf/util/tool_pmu.c b/tools/perf/util/tool_pmu.c +index 3a68debe71437..9156745ea180d 100644 +--- a/tools/perf/util/tool_pmu.c ++++ b/tools/perf/util/tool_pmu.c +@@ -490,17 +490,16 @@ int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread) + return 0; + } + +-struct perf_pmu *perf_pmus__tool_pmu(void) ++struct perf_pmu *tool_pmu__new(void) + { +- static struct perf_pmu tool = { +- .name = "tool", +- .type = PERF_PMU_TYPE_TOOL, +- .aliases = LIST_HEAD_INIT(tool.aliases), +- .caps = LIST_HEAD_INIT(tool.caps), +- .format = LIST_HEAD_INIT(tool.format), +- }; +- if (!tool.events_table) +- tool.events_table = find_core_events_table("common", "common"); +- +- return &tool; ++ struct perf_pmu *tool = zalloc(sizeof(struct perf_pmu)); ++ ++ tool->name = strdup("tool"); ++ tool->type = PERF_PMU_TYPE_TOOL; ++ INIT_LIST_HEAD(&tool->aliases); ++ INIT_LIST_HEAD(&tool->caps); ++ INIT_LIST_HEAD(&tool->format); ++ tool->events_table = find_core_events_table("common", "common"); ++ ++ return tool; + } +diff --git a/tools/perf/util/tool_pmu.h b/tools/perf/util/tool_pmu.h +index a60184859080f..c6ad1dd90a56d 100644 +--- a/tools/perf/util/tool_pmu.h ++++ b/tools/perf/util/tool_pmu.h +@@ -51,6 +51,6 @@ int evsel__tool_pmu_open(struct evsel *evsel, + int start_cpu_map_idx, int end_cpu_map_idx); + int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread); + +-struct perf_pmu *perf_pmus__tool_pmu(void); ++struct perf_pmu *tool_pmu__new(void); + + #endif /* __TOOL_PMU_H */ +-- +2.39.5 + diff --git a/queue-6.14/perf-pmu-handle-memory-failure-in-tool_pmu__new.patch b/queue-6.14/perf-pmu-handle-memory-failure-in-tool_pmu__new.patch new file mode 100644 index 0000000000..268988c45e --- /dev/null +++ b/queue-6.14/perf-pmu-handle-memory-failure-in-tool_pmu__new.patch @@ -0,0 +1,69 @@ +From f1b1270e1aebda08a2bd3a861d5409463724d8df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 13:28:20 +0100 +Subject: perf pmu: Handle memory failure in tool_pmu__new() + +From: Thomas Richter + +[ Upstream commit 431db90a7303cb394c5a881b4479946f64052727 ] + +On linux-next +commit 72c6f57a4193 ("perf pmu: Dynamically allocate tool PMU") +allocated PMU named "tool" dynamicly. However that allocation +can fail and a NULL pointer is returned. That case is currently +not handled and would result in an invalid address reference. +Add a check for NULL pointer. + +Fixes: 72c6f57a4193 ("perf pmu: Dynamically allocate tool PMU") +Signed-off-by: Thomas Richter +Reviewed-by: James Clark +Link: https://lore.kernel.org/r/20250319122820.2898333-1-tmricht@linux.ibm.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/util/pmus.c | 3 ++- + tools/perf/util/tool_pmu.c | 8 ++++++++ + 2 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/util/pmus.c b/tools/perf/util/pmus.c +index 6498021acef01..7959af59908c2 100644 +--- a/tools/perf/util/pmus.c ++++ b/tools/perf/util/pmus.c +@@ -269,7 +269,8 @@ static void pmu_read_sysfs(unsigned int to_read_types) + if ((to_read_types & PERF_TOOL_PMU_TYPE_TOOL_MASK) != 0 && + (read_pmu_types & PERF_TOOL_PMU_TYPE_TOOL_MASK) == 0) { + tool_pmu = tool_pmu__new(); +- list_add_tail(&tool_pmu->list, &other_pmus); ++ if (tool_pmu) ++ list_add_tail(&tool_pmu->list, &other_pmus); + } + if ((to_read_types & PERF_TOOL_PMU_TYPE_HWMON_MASK) != 0 && + (read_pmu_types & PERF_TOOL_PMU_TYPE_HWMON_MASK) == 0) +diff --git a/tools/perf/util/tool_pmu.c b/tools/perf/util/tool_pmu.c +index 9156745ea180d..d43d6cf6e4a20 100644 +--- a/tools/perf/util/tool_pmu.c ++++ b/tools/perf/util/tool_pmu.c +@@ -494,12 +494,20 @@ struct perf_pmu *tool_pmu__new(void) + { + struct perf_pmu *tool = zalloc(sizeof(struct perf_pmu)); + ++ if (!tool) ++ goto out; + tool->name = strdup("tool"); ++ if (!tool->name) { ++ zfree(&tool); ++ goto out; ++ } ++ + tool->type = PERF_PMU_TYPE_TOOL; + INIT_LIST_HEAD(&tool->aliases); + INIT_LIST_HEAD(&tool->caps); + INIT_LIST_HEAD(&tool->format); + tool->events_table = find_core_events_table("common", "common"); + ++out: + return tool; + } +-- +2.39.5 + diff --git a/queue-6.14/perf-pmus-restructure-pmu_read_sysfs-to-scan-fewer-p.patch b/queue-6.14/perf-pmus-restructure-pmu_read_sysfs-to-scan-fewer-p.patch new file mode 100644 index 0000000000..3dd5653cfa --- /dev/null +++ b/queue-6.14/perf-pmus-restructure-pmu_read_sysfs-to-scan-fewer-p.patch @@ -0,0 +1,302 @@ +From a0b6bb7120284aa209a604059c833a509da21c41 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 23:43:17 -0800 +Subject: perf pmus: Restructure pmu_read_sysfs to scan fewer PMUs + +From: Ian Rogers + +[ Upstream commit 57e13264dcea670d5f42a067562f02aa923219e2 ] + +Rather than scanning core or all PMUs, allow pmu_read_sysfs to read +some combination of core, other, hwmon and tool PMUs. The PMUs that +should be read and are already read are held as bitmaps. It is known +that a "hwmon_" prefix is necessary for a hwmon PMU's name, similarly +with "tool", so only scan those PMUs in situations the PMU name or the +PMU's type number make sense to. + +The number of openat system calls reduces from 276 to 98 for a hwmon +event. The number of openats for regular perf events isn't changed. + +Signed-off-by: Ian Rogers +Reviewed-by: Kan Liang +Link: https://lore.kernel.org/r/20250201074320.746259-3-irogers@google.com +Signed-off-by: Namhyung Kim +Stable-dep-of: 72c6f57a4193 ("perf pmu: Dynamically allocate tool PMU") +Signed-off-by: Sasha Levin +--- + tools/perf/util/pmu.h | 2 + + tools/perf/util/pmus.c | 146 +++++++++++++++++++++++++++-------------- + 2 files changed, 97 insertions(+), 51 deletions(-) + +diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h +index dbed6c243a5ef..edd36c20aedc2 100644 +--- a/tools/perf/util/pmu.h ++++ b/tools/perf/util/pmu.h +@@ -37,6 +37,8 @@ struct perf_pmu_caps { + }; + + enum { ++ PERF_PMU_TYPE_PE_START = 0, ++ PERF_PMU_TYPE_PE_END = 0xFFFEFFFF, + PERF_PMU_TYPE_HWMON_START = 0xFFFF0000, + PERF_PMU_TYPE_HWMON_END = 0xFFFFFFFD, + PERF_PMU_TYPE_TOOL = 0xFFFFFFFE, +diff --git a/tools/perf/util/pmus.c b/tools/perf/util/pmus.c +index 60d81d69503e3..8a0a919415d49 100644 +--- a/tools/perf/util/pmus.c ++++ b/tools/perf/util/pmus.c +@@ -37,10 +37,25 @@ + */ + static LIST_HEAD(core_pmus); + static LIST_HEAD(other_pmus); +-static bool read_sysfs_core_pmus; +-static bool read_sysfs_all_pmus; ++enum perf_tool_pmu_type { ++ PERF_TOOL_PMU_TYPE_PE_CORE, ++ PERF_TOOL_PMU_TYPE_PE_OTHER, ++ PERF_TOOL_PMU_TYPE_TOOL, ++ PERF_TOOL_PMU_TYPE_HWMON, ++ ++#define PERF_TOOL_PMU_TYPE_PE_CORE_MASK (1 << PERF_TOOL_PMU_TYPE_PE_CORE) ++#define PERF_TOOL_PMU_TYPE_PE_OTHER_MASK (1 << PERF_TOOL_PMU_TYPE_PE_OTHER) ++#define PERF_TOOL_PMU_TYPE_TOOL_MASK (1 << PERF_TOOL_PMU_TYPE_TOOL) ++#define PERF_TOOL_PMU_TYPE_HWMON_MASK (1 << PERF_TOOL_PMU_TYPE_HWMON) ++ ++#define PERF_TOOL_PMU_TYPE_ALL_MASK (PERF_TOOL_PMU_TYPE_PE_CORE_MASK | \ ++ PERF_TOOL_PMU_TYPE_PE_OTHER_MASK | \ ++ PERF_TOOL_PMU_TYPE_TOOL_MASK | \ ++ PERF_TOOL_PMU_TYPE_HWMON_MASK) ++}; ++static unsigned int read_pmu_types; + +-static void pmu_read_sysfs(bool core_only); ++static void pmu_read_sysfs(unsigned int to_read_pmus); + + size_t pmu_name_len_no_suffix(const char *str) + { +@@ -102,8 +117,7 @@ void perf_pmus__destroy(void) + + perf_pmu__delete(pmu); + } +- read_sysfs_core_pmus = false; +- read_sysfs_all_pmus = false; ++ read_pmu_types = 0; + } + + static struct perf_pmu *pmu_find(const char *name) +@@ -129,6 +143,7 @@ struct perf_pmu *perf_pmus__find(const char *name) + struct perf_pmu *pmu; + int dirfd; + bool core_pmu; ++ unsigned int to_read_pmus = 0; + + /* + * Once PMU is loaded it stays in the list, +@@ -139,11 +154,11 @@ struct perf_pmu *perf_pmus__find(const char *name) + if (pmu) + return pmu; + +- if (read_sysfs_all_pmus) ++ if (read_pmu_types == PERF_TOOL_PMU_TYPE_ALL_MASK) + return NULL; + + core_pmu = is_pmu_core(name); +- if (core_pmu && read_sysfs_core_pmus) ++ if (core_pmu && (read_pmu_types & PERF_TOOL_PMU_TYPE_PE_CORE_MASK)) + return NULL; + + dirfd = perf_pmu__event_source_devices_fd(); +@@ -151,15 +166,27 @@ struct perf_pmu *perf_pmus__find(const char *name) + /*eager_load=*/false); + close(dirfd); + +- if (!pmu) { +- /* +- * Looking up an inidividual PMU failed. This may mean name is +- * an alias, so read the PMUs from sysfs and try to find again. +- */ +- pmu_read_sysfs(core_pmu); ++ if (pmu) ++ return pmu; ++ ++ /* Looking up an individual perf event PMU failed, check if a tool PMU should be read. */ ++ if (!strncmp(name, "hwmon_", 6)) ++ to_read_pmus |= PERF_TOOL_PMU_TYPE_HWMON_MASK; ++ else if (!strcmp(name, "tool")) ++ to_read_pmus |= PERF_TOOL_PMU_TYPE_TOOL_MASK; ++ ++ if (to_read_pmus) { ++ pmu_read_sysfs(to_read_pmus); + pmu = pmu_find(name); ++ if (pmu) ++ return pmu; + } +- return pmu; ++ /* Read all necessary PMUs from sysfs and see if the PMU is found. */ ++ to_read_pmus = PERF_TOOL_PMU_TYPE_PE_CORE_MASK; ++ if (!core_pmu) ++ to_read_pmus |= PERF_TOOL_PMU_TYPE_PE_OTHER_MASK; ++ pmu_read_sysfs(to_read_pmus); ++ return pmu_find(name); + } + + static struct perf_pmu *perf_pmu__find2(int dirfd, const char *name) +@@ -176,11 +203,11 @@ static struct perf_pmu *perf_pmu__find2(int dirfd, const char *name) + if (pmu) + return pmu; + +- if (read_sysfs_all_pmus) ++ if (read_pmu_types == PERF_TOOL_PMU_TYPE_ALL_MASK) + return NULL; + + core_pmu = is_pmu_core(name); +- if (core_pmu && read_sysfs_core_pmus) ++ if (core_pmu && (read_pmu_types & PERF_TOOL_PMU_TYPE_PE_CORE_MASK)) + return NULL; + + return perf_pmu__lookup(core_pmu ? &core_pmus : &other_pmus, dirfd, name, +@@ -197,52 +224,60 @@ static int pmus_cmp(void *priv __maybe_unused, + } + + /* Add all pmus in sysfs to pmu list: */ +-static void pmu_read_sysfs(bool core_only) ++static void pmu_read_sysfs(unsigned int to_read_types) + { +- int fd; +- DIR *dir; +- struct dirent *dent; + struct perf_pmu *tool_pmu; + +- if (read_sysfs_all_pmus || (core_only && read_sysfs_core_pmus)) ++ if ((read_pmu_types & to_read_types) == to_read_types) { ++ /* All requested PMU types have been read. */ + return; ++ } + +- fd = perf_pmu__event_source_devices_fd(); +- if (fd < 0) +- return; ++ if (to_read_types & (PERF_TOOL_PMU_TYPE_PE_CORE_MASK | PERF_TOOL_PMU_TYPE_PE_OTHER_MASK)) { ++ int fd = perf_pmu__event_source_devices_fd(); ++ DIR *dir; ++ struct dirent *dent; ++ bool core_only = (to_read_types & PERF_TOOL_PMU_TYPE_PE_OTHER_MASK) == 0; + +- dir = fdopendir(fd); +- if (!dir) { +- close(fd); +- return; +- } ++ if (fd < 0) ++ goto skip_pe_pmus; + +- while ((dent = readdir(dir))) { +- if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) +- continue; +- if (core_only && !is_pmu_core(dent->d_name)) +- continue; +- /* add to static LIST_HEAD(core_pmus) or LIST_HEAD(other_pmus): */ +- perf_pmu__find2(fd, dent->d_name); +- } ++ dir = fdopendir(fd); ++ if (!dir) { ++ close(fd); ++ goto skip_pe_pmus; ++ } + +- closedir(dir); +- if (list_empty(&core_pmus)) { ++ while ((dent = readdir(dir))) { ++ if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) ++ continue; ++ if (core_only && !is_pmu_core(dent->d_name)) ++ continue; ++ /* add to static LIST_HEAD(core_pmus) or LIST_HEAD(other_pmus): */ ++ perf_pmu__find2(fd, dent->d_name); ++ } ++ ++ closedir(dir); ++ } ++skip_pe_pmus: ++ if ((to_read_types & PERF_TOOL_PMU_TYPE_PE_CORE_MASK) && list_empty(&core_pmus)) { + if (!perf_pmu__create_placeholder_core_pmu(&core_pmus)) + pr_err("Failure to set up any core PMUs\n"); + } + list_sort(NULL, &core_pmus, pmus_cmp); +- if (!core_only) { ++ ++ if ((to_read_types & PERF_TOOL_PMU_TYPE_TOOL_MASK) != 0 && ++ (read_pmu_types & PERF_TOOL_PMU_TYPE_TOOL_MASK) == 0) { + tool_pmu = perf_pmus__tool_pmu(); + list_add_tail(&tool_pmu->list, &other_pmus); +- perf_pmus__read_hwmon_pmus(&other_pmus); + } ++ if ((to_read_types & PERF_TOOL_PMU_TYPE_HWMON_MASK) != 0 && ++ (read_pmu_types & PERF_TOOL_PMU_TYPE_HWMON_MASK) == 0) ++ perf_pmus__read_hwmon_pmus(&other_pmus); ++ + list_sort(NULL, &other_pmus, pmus_cmp); +- if (!list_empty(&core_pmus)) { +- read_sysfs_core_pmus = true; +- if (!core_only) +- read_sysfs_all_pmus = true; +- } ++ ++ read_pmu_types |= to_read_types; + } + + static struct perf_pmu *__perf_pmus__find_by_type(unsigned int type) +@@ -263,12 +298,21 @@ static struct perf_pmu *__perf_pmus__find_by_type(unsigned int type) + + struct perf_pmu *perf_pmus__find_by_type(unsigned int type) + { ++ unsigned int to_read_pmus; + struct perf_pmu *pmu = __perf_pmus__find_by_type(type); + +- if (pmu || read_sysfs_all_pmus) ++ if (pmu || (read_pmu_types == PERF_TOOL_PMU_TYPE_ALL_MASK)) + return pmu; + +- pmu_read_sysfs(/*core_only=*/false); ++ if (type >= PERF_PMU_TYPE_PE_START && type <= PERF_PMU_TYPE_PE_END) { ++ to_read_pmus = PERF_TOOL_PMU_TYPE_PE_CORE_MASK | ++ PERF_TOOL_PMU_TYPE_PE_OTHER_MASK; ++ } else if (type >= PERF_PMU_TYPE_HWMON_START && type <= PERF_PMU_TYPE_HWMON_END) { ++ to_read_pmus = PERF_TOOL_PMU_TYPE_HWMON_MASK; ++ } else { ++ to_read_pmus = PERF_TOOL_PMU_TYPE_TOOL_MASK; ++ } ++ pmu_read_sysfs(to_read_pmus); + pmu = __perf_pmus__find_by_type(type); + return pmu; + } +@@ -282,7 +326,7 @@ struct perf_pmu *perf_pmus__scan(struct perf_pmu *pmu) + bool use_core_pmus = !pmu || pmu->is_core; + + if (!pmu) { +- pmu_read_sysfs(/*core_only=*/false); ++ pmu_read_sysfs(PERF_TOOL_PMU_TYPE_ALL_MASK); + pmu = list_prepare_entry(pmu, &core_pmus, list); + } + if (use_core_pmus) { +@@ -300,7 +344,7 @@ struct perf_pmu *perf_pmus__scan(struct perf_pmu *pmu) + struct perf_pmu *perf_pmus__scan_core(struct perf_pmu *pmu) + { + if (!pmu) { +- pmu_read_sysfs(/*core_only=*/true); ++ pmu_read_sysfs(PERF_TOOL_PMU_TYPE_PE_CORE_MASK); + return list_first_entry_or_null(&core_pmus, typeof(*pmu), list); + } + list_for_each_entry_continue(pmu, &core_pmus, list) +@@ -316,7 +360,7 @@ static struct perf_pmu *perf_pmus__scan_skip_duplicates(struct perf_pmu *pmu) + const char *last_pmu_name = (pmu && pmu->name) ? pmu->name : ""; + + if (!pmu) { +- pmu_read_sysfs(/*core_only=*/false); ++ pmu_read_sysfs(PERF_TOOL_PMU_TYPE_ALL_MASK); + pmu = list_prepare_entry(pmu, &core_pmus, list); + } else + last_pmu_name_len = pmu_name_len_no_suffix(pmu->name ?: ""); +-- +2.39.5 + diff --git a/queue-6.14/perf-python-check-if-there-is-space-to-copy-all-the-.patch b/queue-6.14/perf-python-check-if-there-is-space-to-copy-all-the-.patch new file mode 100644 index 0000000000..fb7fbddc60 --- /dev/null +++ b/queue-6.14/perf-python-check-if-there-is-space-to-copy-all-the-.patch @@ -0,0 +1,68 @@ +From db475438df7ea70f083e37e8aa558d16929214f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 17:31:41 -0300 +Subject: perf python: Check if there is space to copy all the event + +From: Arnaldo Carvalho de Melo + +[ Upstream commit 89aaeaf84231157288035b366cb6300c1c6cac64 ] + +The pyrf_event__new() method copies the event obtained from the perf +ring buffer to a structure that will then be turned into a python object +for further consumption, so it copies perf_event.header.size bytes to +its 'event' member: + + $ pahole -C pyrf_event /tmp/build/perf-tools-next/python/perf.cpython-312-x86_64-linux-gnu.so + struct pyrf_event { + PyObject ob_base; /* 0 16 */ + struct evsel * evsel; /* 16 8 */ + struct perf_sample sample; /* 24 312 */ + + /* XXX last struct has 7 bytes of padding, 2 holes */ + + /* --- cacheline 5 boundary (320 bytes) was 16 bytes ago --- */ + union perf_event event; /* 336 4168 */ + + /* size: 4504, cachelines: 71, members: 4 */ + /* member types with holes: 1, total: 2 */ + /* paddings: 1, sum paddings: 7 */ + /* last cacheline: 24 bytes */ + }; + + $ + +It was doing so without checking if the event just obtained has more +than that space, fix it. + +This isn't a proper, final solution, as we need to support larger +events, but for the time being we at least bounds check and document it. + +Fixes: 877108e42b1b9ba6 ("perf tools: Initial python binding") +Signed-off-by: Arnaldo Carvalho de Melo +Reviewed-by: Ian Rogers +Link: https://lore.kernel.org/r/20250312203141.285263-7-acme@kernel.org +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/util/python.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c +index 016d7ac956d2e..a23fa5d953943 100644 +--- a/tools/perf/util/python.c ++++ b/tools/perf/util/python.c +@@ -481,6 +481,11 @@ static PyObject *pyrf_event__new(const union perf_event *event) + event->header.type == PERF_RECORD_SWITCH_CPU_WIDE)) + return NULL; + ++ // FIXME this better be dynamic or we need to parse everything ++ // before calling perf_mmap__consume(), including tracepoint fields. ++ if (sizeof(pevent->event) < event->header.size) ++ return NULL; ++ + ptype = pyrf_event__type[event->header.type]; + pevent = PyObject_New(struct pyrf_event, ptype); + if (pevent != NULL) +-- +2.39.5 + diff --git a/queue-6.14/perf-python-decrement-the-refcount-of-just-created-e.patch b/queue-6.14/perf-python-decrement-the-refcount-of-just-created-e.patch new file mode 100644 index 0000000000..cf8f19cf9a --- /dev/null +++ b/queue-6.14/perf-python-decrement-the-refcount-of-just-created-e.patch @@ -0,0 +1,52 @@ +From 35078afe2f0a4fb751b7a855707b753afe963616 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 17:31:39 -0300 +Subject: perf python: Decrement the refcount of just created event on failure + +From: Arnaldo Carvalho de Melo + +[ Upstream commit 3de5a2bf5b4847f7a59a184568f969f8fe05d57f ] + +To avoid a leak if we have the python object but then something happens +and we need to return the operation, decrement the offset of the newly +created object. + +Fixes: 377f698db12150a1 ("perf python: Add struct evsel into struct pyrf_event") +Signed-off-by: Arnaldo Carvalho de Melo +Reviewed-by: Ian Rogers +Link: https://lore.kernel.org/r/20250312203141.285263-5-acme@kernel.org +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/util/python.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c +index ae6bcd39a2001..5370fff2525f5 100644 +--- a/tools/perf/util/python.c ++++ b/tools/perf/util/python.c +@@ -984,6 +984,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, + + evsel = evlist__event2evsel(evlist, event); + if (!evsel) { ++ Py_DECREF(pyevent); + Py_INCREF(Py_None); + return Py_None; + } +@@ -995,9 +996,12 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, + /* Consume the even only after we parsed it out. */ + perf_mmap__consume(&md->core); + +- if (err) ++ if (err) { ++ Py_DECREF(pyevent); + return PyErr_Format(PyExc_OSError, + "perf: can't parse sample, err=%d", err); ++ } ++ + return pyevent; + } + end: +-- +2.39.5 + diff --git a/queue-6.14/perf-python-don-t-keep-a-raw_data-pointer-to-consume.patch b/queue-6.14/perf-python-don-t-keep-a-raw_data-pointer-to-consume.patch new file mode 100644 index 0000000000..a3cbb9ce7c --- /dev/null +++ b/queue-6.14/perf-python-don-t-keep-a-raw_data-pointer-to-consume.patch @@ -0,0 +1,86 @@ +From c4869ce287e96816a05f54517c13a4e7bf0acb5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 17:31:40 -0300 +Subject: perf python: Don't keep a raw_data pointer to consumed ring buffer + space +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Arnaldo Carvalho de Melo + +[ Upstream commit f3fed3ae34d606819d87a63d970cc3092a5be7ab ] + +When processing tracepoints the perf python binding was parsing the +event before calling perf_mmap__consume(&md->core) in +pyrf_evlist__read_on_cpu(). + +But part of this event parsing was to set the perf_sample->raw_data +pointer to the payload of the event, which then could be overwritten by +other event before tracepoint fields were asked for via event.prev_comm +in a python program, for instance. + +This also happened with other fields, but strings were were problems +were surfacing, as there is UTF-8 validation for the potentially garbled +data. + +This ended up showing up as (with some added debugging messages): + + ( field 'prev_comm' ret=0x7f7c31f65110, raw_size=68 ) ( field 'prev_pid' ret=0x7f7c23b1bed0, raw_size=68 ) ( field 'prev_prio' ret=0x7f7c239c0030, raw_size=68 ) ( field 'prev_state' ret=0x7f7c239c0250, raw_size=68 ) time 14771421785867 prev_comm= prev_pid=1919907691 prev_prio=796026219 prev_state=0x303a32313175 ==> + ( XXX '��' len=16, raw_size=68) ( field 'next_comm' ret=(nil), raw_size=68 ) Traceback (most recent call last): + File "/home/acme/git/perf-tools-next/tools/perf/python/tracepoint.py", line 51, in + main() + File "/home/acme/git/perf-tools-next/tools/perf/python/tracepoint.py", line 46, in main + event.next_comm, + ^^^^^^^^^^^^^^^ + AttributeError: 'perf.sample_event' object has no attribute 'next_comm' + +When event.next_comm was asked for, the PyUnicode_FromString() python +API would fail and that tracepoint field wouldn't be available, stopping +the tools/perf/python/tracepoint.py test tool. + +But, since we already do a copy of the whole event in pyrf_event__new, +just use it and while at it remove what was done in in e8968e654191390a +("perf python: Fix pyrf_evlist__read_on_cpu event consuming") because we +don't really need to wait for parsing the sample before declaring the +event as consumed. + +This copy is questionable as is now, as it limits the maximum event + +sample_type and tracepoint payload to sizeof(union perf_event), this all +has been "working" because 'struct perf_event_mmap2', the largest entry +in 'union perf_event' is: + + $ pahole -C perf_event ~/bin/perf | grep mmap2 + struct perf_record_mmap2 mmap2; /* 0 4168 */ + $ + +Fixes: bae57e3825a3dded ("perf python: Add support to resolve tracepoint fields") +Signed-off-by: Arnaldo Carvalho de Melo +Reviewed-by: Ian Rogers +Link: https://lore.kernel.org/r/20250312203141.285263-6-acme@kernel.org +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/util/python.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c +index 5370fff2525f5..016d7ac956d2e 100644 +--- a/tools/perf/util/python.c ++++ b/tools/perf/util/python.c +@@ -991,11 +991,9 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, + + pevent->evsel = evsel; + +- err = evsel__parse_sample(evsel, event, &pevent->sample); +- +- /* Consume the even only after we parsed it out. */ + perf_mmap__consume(&md->core); + ++ err = evsel__parse_sample(evsel, &pevent->event, &pevent->sample); + if (err) { + Py_DECREF(pyevent); + return PyErr_Format(PyExc_OSError, +-- +2.39.5 + diff --git a/queue-6.14/perf-python-fixup-description-of-sample.id-event-mem.patch b/queue-6.14/perf-python-fixup-description-of-sample.id-event-mem.patch new file mode 100644 index 0000000000..12ebdeca05 --- /dev/null +++ b/queue-6.14/perf-python-fixup-description-of-sample.id-event-mem.patch @@ -0,0 +1,38 @@ +From 4a0d8b4d32e256fcbc7414a72b904085b74b7bfd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 17:31:36 -0300 +Subject: perf python: Fixup description of sample.id event member + +From: Arnaldo Carvalho de Melo + +[ Upstream commit 1376c195e8ad327bb9f2d32e0acc5ac39e7cb30a ] + +Some old cut'n'paste error, its "ip", so the description should be +"event ip", not "event type". + +Fixes: 877108e42b1b9ba6 ("perf tools: Initial python binding") +Signed-off-by: Arnaldo Carvalho de Melo +Reviewed-by: Ian Rogers +Link: https://lore.kernel.org/r/20250312203141.285263-2-acme@kernel.org +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/util/python.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c +index b4bc57859f730..ae6bcd39a2001 100644 +--- a/tools/perf/util/python.c ++++ b/tools/perf/util/python.c +@@ -47,7 +47,7 @@ struct pyrf_event { + }; + + #define sample_members \ +- sample_member_def(sample_ip, ip, T_ULONGLONG, "event type"), \ ++ sample_member_def(sample_ip, ip, T_ULONGLONG, "event ip"), \ + sample_member_def(sample_pid, pid, T_INT, "event pid"), \ + sample_member_def(sample_tid, tid, T_INT, "event tid"), \ + sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"), \ +-- +2.39.5 + diff --git a/queue-6.14/perf-report-add-parallelism-sort-key.patch b/queue-6.14/perf-report-add-parallelism-sort-key.patch new file mode 100644 index 0000000000..8cae3081bd --- /dev/null +++ b/queue-6.14/perf-report-add-parallelism-sort-key.patch @@ -0,0 +1,195 @@ +From 57a34683ceced28522efd04a896ac031b1138064 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 10:08:15 +0100 +Subject: perf report: Add parallelism sort key + +From: Dmitry Vyukov + +[ Upstream commit 7ae1972e748863b0aa04983caf847d4dd5b7e136 ] + +Show parallelism level in profiles if requested by user. + +Signed-off-by: Dmitry Vyukov +Reviewed-by: Andi Kleen +Link: https://lore.kernel.org/r/7f7bb87cbaa51bf1fb008a0d68b687423ce4bad4.1739437531.git.dvyukov@google.com +Signed-off-by: Namhyung Kim +Stable-dep-of: 6353255e7cfa ("perf report: Fix input reload/switch with symbol sort key") +Signed-off-by: Sasha Levin +--- + tools/perf/builtin-report.c | 11 +++++++++++ + tools/perf/util/hist.c | 2 ++ + tools/perf/util/hist.h | 3 +++ + tools/perf/util/session.c | 12 ++++++++++++ + tools/perf/util/session.h | 1 + + tools/perf/util/sort.c | 23 +++++++++++++++++++++++ + tools/perf/util/sort.h | 1 + + 7 files changed, 53 insertions(+) + +diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c +index c99b14a852dbd..66b8b1c32e00a 100644 +--- a/tools/perf/builtin-report.c ++++ b/tools/perf/builtin-report.c +@@ -1719,6 +1719,17 @@ int cmd_report(int argc, const char **argv) + symbol_conf.annotate_data_sample = true; + } + ++ if (report.disable_order || !perf_session__has_switch_events(session)) { ++ if ((sort_order && strstr(sort_order, "parallelism")) || ++ (field_order && strstr(field_order, "parallelism"))) { ++ if (report.disable_order) ++ ui__error("Use of parallelism is incompatible with --disable-order.\n"); ++ else ++ ui__error("Use of parallelism requires --switch-events during record.\n"); ++ return -1; ++ } ++ } ++ + if (sort_order && strstr(sort_order, "ipc")) { + parse_options_usage(report_usage, options, "s", 1); + goto error; +diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c +index 0f30f843c566d..cafd693568189 100644 +--- a/tools/perf/util/hist.c ++++ b/tools/perf/util/hist.c +@@ -207,6 +207,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) + + hists__new_col_len(hists, HISTC_CGROUP, 6); + hists__new_col_len(hists, HISTC_CGROUP_ID, 20); ++ hists__new_col_len(hists, HISTC_PARALLELISM, 11); + hists__new_col_len(hists, HISTC_CPU, 3); + hists__new_col_len(hists, HISTC_SOCKET, 6); + hists__new_col_len(hists, HISTC_MEM_LOCKED, 6); +@@ -741,6 +742,7 @@ __hists__add_entry(struct hists *hists, + .ip = al->addr, + .level = al->level, + .code_page_size = sample->code_page_size, ++ .parallelism = al->parallelism, + .stat = { + .nr_events = 1, + .period = sample->period, +diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h +index 46c8373e31465..a6e662d77dc24 100644 +--- a/tools/perf/util/hist.h ++++ b/tools/perf/util/hist.h +@@ -42,6 +42,7 @@ enum hist_column { + HISTC_CGROUP_ID, + HISTC_CGROUP, + HISTC_PARENT, ++ HISTC_PARALLELISM, + HISTC_CPU, + HISTC_SOCKET, + HISTC_SRCLINE, +@@ -228,6 +229,7 @@ struct hist_entry { + u64 transaction; + s32 socket; + s32 cpu; ++ int parallelism; + u64 code_page_size; + u64 weight; + u64 ins_lat; +@@ -580,6 +582,7 @@ bool perf_hpp__is_thread_entry(struct perf_hpp_fmt *fmt); + bool perf_hpp__is_comm_entry(struct perf_hpp_fmt *fmt); + bool perf_hpp__is_dso_entry(struct perf_hpp_fmt *fmt); + bool perf_hpp__is_sym_entry(struct perf_hpp_fmt *fmt); ++bool perf_hpp__is_parallelism_entry(struct perf_hpp_fmt *fmt); + + struct perf_hpp_fmt *perf_hpp_fmt__dup(struct perf_hpp_fmt *fmt); + +diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c +index c06e3020a9769..00fcf8d8ac255 100644 +--- a/tools/perf/util/session.c ++++ b/tools/perf/util/session.c +@@ -2403,6 +2403,18 @@ bool perf_session__has_traces(struct perf_session *session, const char *msg) + return false; + } + ++bool perf_session__has_switch_events(struct perf_session *session) ++{ ++ struct evsel *evsel; ++ ++ evlist__for_each_entry(session->evlist, evsel) { ++ if (evsel->core.attr.context_switch) ++ return true; ++ } ++ ++ return false; ++} ++ + int map__set_kallsyms_ref_reloc_sym(struct map *map, const char *symbol_name, u64 addr) + { + char *bracket; +diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h +index bcf1bcf06959b..db1c120a9e67f 100644 +--- a/tools/perf/util/session.h ++++ b/tools/perf/util/session.h +@@ -141,6 +141,7 @@ int perf_session__resolve_callchain(struct perf_session *session, + struct symbol **parent); + + bool perf_session__has_traces(struct perf_session *session, const char *msg); ++bool perf_session__has_switch_events(struct perf_session *session); + + void perf_event__attr_swap(struct perf_event_attr *attr); + +diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c +index 3dd33721823f3..7eef43f5be360 100644 +--- a/tools/perf/util/sort.c ++++ b/tools/perf/util/sort.c +@@ -892,6 +892,27 @@ struct sort_entry sort_cpu = { + .se_width_idx = HISTC_CPU, + }; + ++/* --sort parallelism */ ++ ++static int64_t ++sort__parallelism_cmp(struct hist_entry *left, struct hist_entry *right) ++{ ++ return right->parallelism - left->parallelism; ++} ++ ++static int hist_entry__parallelism_snprintf(struct hist_entry *he, char *bf, ++ size_t size, unsigned int width) ++{ ++ return repsep_snprintf(bf, size, "%*d", width, he->parallelism); ++} ++ ++struct sort_entry sort_parallelism = { ++ .se_header = "Parallelism", ++ .se_cmp = sort__parallelism_cmp, ++ .se_snprintf = hist_entry__parallelism_snprintf, ++ .se_width_idx = HISTC_PARALLELISM, ++}; ++ + /* --sort cgroup_id */ + + static int64_t _sort__cgroup_dev_cmp(u64 left_dev, u64 right_dev) +@@ -2534,6 +2555,7 @@ static struct sort_dimension common_sort_dimensions[] = { + DIM(SORT_ANNOTATE_DATA_TYPE_OFFSET, "typeoff", sort_type_offset), + DIM(SORT_SYM_OFFSET, "symoff", sort_sym_offset), + DIM(SORT_ANNOTATE_DATA_TYPE_CACHELINE, "typecln", sort_type_cacheline), ++ DIM(SORT_PARALLELISM, "parallelism", sort_parallelism), + }; + + #undef DIM +@@ -2735,6 +2757,7 @@ MK_SORT_ENTRY_CHK(thread) + MK_SORT_ENTRY_CHK(comm) + MK_SORT_ENTRY_CHK(dso) + MK_SORT_ENTRY_CHK(sym) ++MK_SORT_ENTRY_CHK(parallelism) + + + static bool __sort__hpp_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) +diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h +index a8572574e1686..11fb15f914093 100644 +--- a/tools/perf/util/sort.h ++++ b/tools/perf/util/sort.h +@@ -72,6 +72,7 @@ enum sort_type { + SORT_ANNOTATE_DATA_TYPE_OFFSET, + SORT_SYM_OFFSET, + SORT_ANNOTATE_DATA_TYPE_CACHELINE, ++ SORT_PARALLELISM, + + /* branch stack specific sort keys */ + __SORT_BRANCH_STACK, +-- +2.39.5 + diff --git a/queue-6.14/perf-report-fix-input-reload-switch-with-symbol-sort.patch b/queue-6.14/perf-report-fix-input-reload-switch-with-symbol-sort.patch new file mode 100644 index 0000000000..deb195cdc2 --- /dev/null +++ b/queue-6.14/perf-report-fix-input-reload-switch-with-symbol-sort.patch @@ -0,0 +1,69 @@ +From 6f38743deaeb22c04bb2d98f5a9fe105b086ed5f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jan 2025 07:36:23 +0100 +Subject: perf report: Fix input reload/switch with symbol sort key + +From: Dmitry Vyukov + +[ Upstream commit 6353255e7cfab568058580424fa0967bf4504fe5 ] + +Currently the code checks that there is no "ipc" in the sort order +and add an ipc string. This will always error out on the second pass +after input reload/switch, since the sort order already contains "ipc". +Do the ipc check/fixup only on the first pass. + +Signed-off-by: Dmitry Vyukov +Link: https://lore.kernel.org/r/20250108063628.215577-1-dvyukov@google.com +Fixes: ec6ae74fe8f0 ("perf report: Display average IPC and IPC coverage per symbol") +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/builtin-report.c | 30 ++++++++++++++++-------------- + 1 file changed, 16 insertions(+), 14 deletions(-) + +diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c +index 66b8b1c32e00a..e74d8a6cfa5ae 100644 +--- a/tools/perf/builtin-report.c ++++ b/tools/perf/builtin-report.c +@@ -1730,22 +1730,24 @@ int cmd_report(int argc, const char **argv) + } + } + +- if (sort_order && strstr(sort_order, "ipc")) { +- parse_options_usage(report_usage, options, "s", 1); +- goto error; +- } +- +- if (sort_order && strstr(sort_order, "symbol")) { +- if (sort__mode == SORT_MODE__BRANCH) { +- snprintf(sort_tmp, sizeof(sort_tmp), "%s,%s", +- sort_order, "ipc_lbr"); +- report.symbol_ipc = true; +- } else { +- snprintf(sort_tmp, sizeof(sort_tmp), "%s,%s", +- sort_order, "ipc_null"); ++ if (last_key != K_SWITCH_INPUT_DATA) { ++ if (sort_order && strstr(sort_order, "ipc")) { ++ parse_options_usage(report_usage, options, "s", 1); ++ goto error; + } + +- sort_order = sort_tmp; ++ if (sort_order && strstr(sort_order, "symbol")) { ++ if (sort__mode == SORT_MODE__BRANCH) { ++ snprintf(sort_tmp, sizeof(sort_tmp), "%s,%s", ++ sort_order, "ipc_lbr"); ++ report.symbol_ipc = true; ++ } else { ++ snprintf(sort_tmp, sizeof(sort_tmp), "%s,%s", ++ sort_order, "ipc_null"); ++ } ++ ++ sort_order = sort_tmp; ++ } + } + + if ((last_key != K_SWITCH_INPUT_DATA && last_key != K_RELOAD) && +-- +2.39.5 + diff --git a/queue-6.14/perf-report-switch-data-file-correctly-in-tui.patch b/queue-6.14/perf-report-switch-data-file-correctly-in-tui.patch new file mode 100644 index 0000000000..4356950b35 --- /dev/null +++ b/queue-6.14/perf-report-switch-data-file-correctly-in-tui.patch @@ -0,0 +1,48 @@ +From 4d4a4c92e9cbbd5f93bebf4a3dc36c1d0d41cc90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 22:07:44 -0800 +Subject: perf report: Switch data file correctly in TUI + +From: Namhyung Kim + +[ Upstream commit 43c2b6139b188d8a756130147f7efd5ddf99f88d ] + +The 's' key is to switch to a new data file and load the data in the +same window. The switch_data_file() will show a popup menu to select +which data file user wants and update the 'input_name' global variable. + +But in the cmd_report(), it didn't update the data.path using the new +'input_name' and keep usng the old file. This is fairly an old bug and +I assume people don't use this feature much. :) + +Link: https://lore.kernel.org/r/20250211060745.294289-1-namhyung@kernel.org +Closes: https://lore.kernel.org/linux-perf-users/89e678bc-f0af-4929-a8a6-a2666f1294a4@linaro.org +Fixes: f5fc14124c5cefdd ("perf tools: Add data object to handle perf data file") +Reported-by: James Clark +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/builtin-report.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c +index f5fbd670d619a..c99b14a852dbd 100644 +--- a/tools/perf/builtin-report.c ++++ b/tools/perf/builtin-report.c +@@ -1553,12 +1553,12 @@ int cmd_report(int argc, const char **argv) + input_name = "perf.data"; + } + ++repeat: + data.path = input_name; + data.force = symbol_conf.force; + + symbol_conf.skip_empty = report.skip_empty; + +-repeat: + perf_tool__init(&report.tool, ordered_events); + report.tool.sample = process_sample_event; + report.tool.mmap = perf_event__process_mmap; +-- +2.39.5 + diff --git a/queue-6.14/perf-ring_buffer-allow-the-epollrdnorm-flag-for-poll.patch b/queue-6.14/perf-ring_buffer-allow-the-epollrdnorm-flag-for-poll.patch new file mode 100644 index 0000000000..661e49731c --- /dev/null +++ b/queue-6.14/perf-ring_buffer-allow-the-epollrdnorm-flag-for-poll.patch @@ -0,0 +1,43 @@ +From 2671e79f1df562890d6c2769c42575b5ebc5731d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 11:00:36 +0800 +Subject: perf/ring_buffer: Allow the EPOLLRDNORM flag for poll + +From: Tao Chen + +[ Upstream commit c96fff391c095c11dc87dab35be72dee7d217cde ] + +The poll man page says POLLRDNORM is equivalent to POLLIN. For poll(), +it seems that if user sets pollfd with POLLRDNORM in userspace, perf_poll +will not return until timeout even if perf_output_wakeup called, +whereas POLLIN returns. + +Fixes: 76369139ceb9 ("perf: Split up buffer handling from core code") +Signed-off-by: Tao Chen +Signed-off-by: Ingo Molnar +Cc: Peter Zijlstra +Cc: Arnaldo Carvalho de Melo +Cc: "H. Peter Anvin" +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/20250314030036.2543180-1-chen.dylane@linux.dev +Signed-off-by: Sasha Levin +--- + kernel/events/ring_buffer.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c +index 180509132d4b6..09459647cb822 100644 +--- a/kernel/events/ring_buffer.c ++++ b/kernel/events/ring_buffer.c +@@ -19,7 +19,7 @@ + + static void perf_output_wakeup(struct perf_output_handle *handle) + { +- atomic_set(&handle->rb->poll, EPOLLIN); ++ atomic_set(&handle->rb->poll, EPOLLIN | EPOLLRDNORM); + + handle->event->pending_wakeup = 1; + +-- +2.39.5 + diff --git a/queue-6.14/perf-save-pmu-specific-data-in-task_struct.patch b/queue-6.14/perf-save-pmu-specific-data-in-task_struct.patch new file mode 100644 index 0000000000..68b420e3f9 --- /dev/null +++ b/queue-6.14/perf-save-pmu-specific-data-in-task_struct.patch @@ -0,0 +1,170 @@ +From 6ca13247c58250525645a5ec2bb0e2a61b7b16ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 10:26:54 -0700 +Subject: perf: Save PMU specific data in task_struct + +From: Kan Liang + +[ Upstream commit cb4369129339060218baca718a578bb0b826e734 ] + +Some PMU specific data has to be saved/restored during context switch, +e.g. LBR call stack data. Currently, the data is saved in event context +structure, but only for per-process event. For system-wide event, +because of missing the LBR call stack data after context switch, LBR +callstacks are always shorter in comparison to per-process mode. + +For example, + Per-process mode: + $perf record --call-graph lbr -- taskset -c 0 ./tchain_edit + + - 99.90% 99.86% tchain_edit tchain_edit [.] f3 + 99.86% _start + __libc_start_main + generic_start_main + main + f1 + - f2 + f3 + + System-wide mode: + $perf record --call-graph lbr -a -- taskset -c 0 ./tchain_edit + + - 99.88% 99.82% tchain_edit tchain_edit [.] f3 + - 62.02% main + f1 + f2 + f3 + - 28.83% f1 + - f2 + f3 + - 28.83% f1 + - f2 + f3 + - 8.88% generic_start_main + main + f1 + f2 + f3 + +It isn't practical to simply allocate the data for system-wide event in +CPU context structure for all tasks. We have no idea which CPU a task +will be scheduled to. The duplicated LBR data has to be maintained on +every CPU context structure. That's a huge waste. Otherwise, the LBR +data still lost if the task is scheduled to another CPU. + +Save the pmu specific data in task_struct. The size of pmu specific data +is 788 bytes for LBR call stack. Usually, the overall amount of threads +doesn't exceed a few thousands. For 10K threads, keeping LBR data would +consume additional ~8MB. The additional space will only be allocated +during LBR call stack monitoring. It will be released when the +monitoring is finished. + +Furthermore, moving task_ctx_data from perf_event_context to task_struct +can reduce complexity and make things clearer. E.g. perf doesn't need to +swap task_ctx_data on optimized context switch path. +This patch set is just the first step. There could be other +optimization/extension on top of this patch set. E.g. for cgroup +profiling, perf just needs to save/store the LBR call stack information +for tasks in specific cgroup. That could reduce the additional space. +Also, the LBR call stack can be available for software events, or allow +even debugging use cases, like LBRs on crash later. + +Because of the alignment requirement of Intel Arch LBR, the Kmem cache +is used to allocate the PMU specific data. It's required when child task +allocates the space. Save it in struct perf_ctx_data. +The refcount in struct perf_ctx_data is used to track the users of pmu +specific data. + +Signed-off-by: Kan Liang +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Alexey Budankov +Link: https://lore.kernel.org/r/20250314172700.438923-1-kan.liang@linux.intel.com +Stable-dep-of: 3cec9fd03543 ("perf/x86/lbr: Fix shorter LBRs call stacks for the system-wide mode") +Signed-off-by: Sasha Levin +--- + include/linux/perf_event.h | 35 +++++++++++++++++++++++++++++++++++ + include/linux/sched.h | 2 ++ + kernel/events/core.c | 1 + + 3 files changed, 38 insertions(+) + +diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h +index 8333f132f4a96..852ea843bca27 100644 +--- a/include/linux/perf_event.h ++++ b/include/linux/perf_event.h +@@ -1020,6 +1020,41 @@ struct perf_event_context { + local_t nr_no_switch_fast; + }; + ++/** ++ * struct perf_ctx_data - PMU specific data for a task ++ * @rcu_head: To avoid the race on free PMU specific data ++ * @refcount: To track users ++ * @global: To track system-wide users ++ * @ctx_cache: Kmem cache of PMU specific data ++ * @data: PMU specific data ++ * ++ * Currently, the struct is only used in Intel LBR call stack mode to ++ * save/restore the call stack of a task on context switches. ++ * ++ * The rcu_head is used to prevent the race on free the data. ++ * The data only be allocated when Intel LBR call stack mode is enabled. ++ * The data will be freed when the mode is disabled. ++ * The content of the data will only be accessed in context switch, which ++ * should be protected by rcu_read_lock(). ++ * ++ * Because of the alignment requirement of Intel Arch LBR, the Kmem cache ++ * is used to allocate the PMU specific data. The ctx_cache is to track ++ * the Kmem cache. ++ * ++ * Careful: Struct perf_ctx_data is added as a pointer in struct task_struct. ++ * When system-wide Intel LBR call stack mode is enabled, a buffer with ++ * constant size will be allocated for each task. ++ * Also, system memory consumption can further grow when the size of ++ * struct perf_ctx_data enlarges. ++ */ ++struct perf_ctx_data { ++ struct rcu_head rcu_head; ++ refcount_t refcount; ++ int global; ++ struct kmem_cache *ctx_cache; ++ void *data; ++}; ++ + struct perf_cpu_pmu_context { + struct perf_event_pmu_context epc; + struct perf_event_pmu_context *task_epc; +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 9c15365a30c08..b13c9545d5d67 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -65,6 +65,7 @@ struct mempolicy; + struct nameidata; + struct nsproxy; + struct perf_event_context; ++struct perf_ctx_data; + struct pid_namespace; + struct pipe_inode_info; + struct rcu_node; +@@ -1311,6 +1312,7 @@ struct task_struct { + struct perf_event_context *perf_event_ctxp; + struct mutex perf_event_mutex; + struct list_head perf_event_list; ++ struct perf_ctx_data __rcu *perf_ctx_data; + #endif + #ifdef CONFIG_DEBUG_PREEMPT + unsigned long preempt_disable_ip; +diff --git a/kernel/events/core.c b/kernel/events/core.c +index 823aa08249161..eb359be7ec793 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -14002,6 +14002,7 @@ int perf_event_init_task(struct task_struct *child, u64 clone_flags) + child->perf_event_ctxp = NULL; + mutex_init(&child->perf_event_mutex); + INIT_LIST_HEAD(&child->perf_event_list); ++ child->perf_ctx_data = NULL; + + ret = perf_event_init_context(child, clone_flags); + if (ret) { +-- +2.39.5 + diff --git a/queue-6.14/perf-stat-don-t-merge-counters-purely-on-name.patch b/queue-6.14/perf-stat-don-t-merge-counters-purely-on-name.patch new file mode 100644 index 0000000000..f90c08402f --- /dev/null +++ b/queue-6.14/perf-stat-don-t-merge-counters-purely-on-name.patch @@ -0,0 +1,70 @@ +From 4052f6b655c2ae9cb2de448fcc9c0a2a44284577 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 23:43:19 -0800 +Subject: perf stat: Don't merge counters purely on name + +From: Ian Rogers + +[ Upstream commit 2d9961c690d299893735783a2077e866f2d46a56 ] + +Counter merging was added in commit 942c5593393d ("perf stat: Add +perf_stat_merge_counters()"), however, it merges events with the same +name on different PMUs regardless of whether the different PMUs are +actually of the same type (ie they differ only in the suffix on the +PMU). For hwmon events there may be a temp1 event on every PMU, but +the PMU names are all unique and don't differ just by a suffix. The +merging is over eager and will merge all the hwmon counters together +meaning an aggregated and very large temp1 value is shown. The same +would be true for say cache events and memory controller events where +the PMUs differ but the event names are the same. + +Fix the problem by correctly saying two PMUs alias when they differ +only by suffix. + +Note, there is an overlap with evsel's merged_stat with aggregation +and the evsel's metric_leader where aggregation happens for metrics. + +Fixes: 942c5593393d ("perf stat: Add perf_stat_merge_counters()") +Signed-off-by: Ian Rogers +Reviewed-by: Kan Liang +Link: https://lore.kernel.org/r/20250201074320.746259-5-irogers@google.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/util/stat.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c +index 7c2ccdcc3fdba..1f7abd8754c75 100644 +--- a/tools/perf/util/stat.c ++++ b/tools/perf/util/stat.c +@@ -535,7 +535,10 @@ static int evsel__merge_aggr_counters(struct evsel *evsel, struct evsel *alias) + + return 0; + } +-/* events should have the same name, scale, unit, cgroup but on different PMUs */ ++/* ++ * Events should have the same name, scale, unit, cgroup but on different core ++ * PMUs or on different but matching uncore PMUs. ++ */ + static bool evsel__is_alias(struct evsel *evsel_a, struct evsel *evsel_b) + { + if (strcmp(evsel__name(evsel_a), evsel__name(evsel_b))) +@@ -553,7 +556,13 @@ static bool evsel__is_alias(struct evsel *evsel_a, struct evsel *evsel_b) + if (evsel__is_clock(evsel_a) != evsel__is_clock(evsel_b)) + return false; + +- return evsel_a->pmu != evsel_b->pmu; ++ if (evsel_a->pmu == evsel_b->pmu || evsel_a->pmu == NULL || evsel_b->pmu == NULL) ++ return false; ++ ++ if (evsel_a->pmu->is_core) ++ return evsel_b->pmu->is_core; ++ ++ return perf_pmu__name_no_suffix_match(evsel_a->pmu, evsel_b->pmu->name); + } + + static void evsel__merge_aliases(struct evsel *evsel) +-- +2.39.5 + diff --git a/queue-6.14/perf-stat-fix-find_stat-for-mixed-legacy-non-legacy-.patch b/queue-6.14/perf-stat-fix-find_stat-for-mixed-legacy-non-legacy-.patch new file mode 100644 index 0000000000..f22abaad3d --- /dev/null +++ b/queue-6.14/perf-stat-fix-find_stat-for-mixed-legacy-non-legacy-.patch @@ -0,0 +1,107 @@ +From 1845cef5516f3bead678011f532e286602d8db3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jan 2025 14:21:07 -0800 +Subject: perf stat: Fix find_stat for mixed legacy/non-legacy events + +From: Ian Rogers + +[ Upstream commit 8ce0d2da14d3fb62844dd0e95982c194326b1a5f ] + +Legacy events typically don't have a PMU when added leading to +mismatched legacy/non-legacy cases in find_stat. Use evsel__find_pmu +to make sure the evsel PMU is looked up. Update the evsel__find_pmu +code to look for the PMU using the extended config type or, for legacy +hardware/hw_cache events on non-hybrid systems, just use the core PMU. + +Before: +``` +$ perf stat -e cycles,cpu/instructions/ -a sleep 1 + Performance counter stats for 'system wide': + + 215,309,764 cycles + 44,326,491 cpu/instructions/ + + 1.002555314 seconds time elapsed +``` +After: +``` +$ perf stat -e cycles,cpu/instructions/ -a sleep 1 + + Performance counter stats for 'system wide': + + 990,676,332 cycles + 1,235,762,487 cpu/instructions/ # 1.25 insn per cycle + + 1.002667198 seconds time elapsed +``` + +Fixes: 3612ca8e2935 ("perf stat: Fix the hard-coded metrics calculation on the hybrid") +Signed-off-by: Ian Rogers +Tested-by: James Clark +Tested-by: Leo Yan +Tested-by: Atish Patra +Link: https://lore.kernel.org/r/20250109222109.567031-3-irogers@google.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/util/pmus.c | 20 +++++++++++++++++--- + tools/perf/util/stat-shadow.c | 3 ++- + 2 files changed, 19 insertions(+), 4 deletions(-) + +diff --git a/tools/perf/util/pmus.c b/tools/perf/util/pmus.c +index b493da0d22ef7..60d81d69503e3 100644 +--- a/tools/perf/util/pmus.c ++++ b/tools/perf/util/pmus.c +@@ -710,11 +710,25 @@ char *perf_pmus__default_pmu_name(void) + struct perf_pmu *evsel__find_pmu(const struct evsel *evsel) + { + struct perf_pmu *pmu = evsel->pmu; ++ bool legacy_core_type; + +- if (!pmu) { +- pmu = perf_pmus__find_by_type(evsel->core.attr.type); +- ((struct evsel *)evsel)->pmu = pmu; ++ if (pmu) ++ return pmu; ++ ++ pmu = perf_pmus__find_by_type(evsel->core.attr.type); ++ legacy_core_type = ++ evsel->core.attr.type == PERF_TYPE_HARDWARE || ++ evsel->core.attr.type == PERF_TYPE_HW_CACHE; ++ if (!pmu && legacy_core_type) { ++ if (perf_pmus__supports_extended_type()) { ++ u32 type = evsel->core.attr.config >> PERF_PMU_TYPE_SHIFT; ++ ++ pmu = perf_pmus__find_by_type(type); ++ } else { ++ pmu = perf_pmus__find_core_pmu(); ++ } + } ++ ((struct evsel *)evsel)->pmu = pmu; + return pmu; + } + +diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c +index fa8b2a1048ff9..d83bda5824d22 100644 +--- a/tools/perf/util/stat-shadow.c ++++ b/tools/perf/util/stat-shadow.c +@@ -151,6 +151,7 @@ static double find_stat(const struct evsel *evsel, int aggr_idx, enum stat_type + { + struct evsel *cur; + int evsel_ctx = evsel_context(evsel); ++ struct perf_pmu *evsel_pmu = evsel__find_pmu(evsel); + + evlist__for_each_entry(evsel->evlist, cur) { + struct perf_stat_aggr *aggr; +@@ -177,7 +178,7 @@ static double find_stat(const struct evsel *evsel, int aggr_idx, enum stat_type + * Except the SW CLOCK events, + * ignore if not the PMU we're looking for. + */ +- if ((type != STAT_NSECS) && (evsel->pmu != cur->pmu)) ++ if ((type != STAT_NSECS) && (evsel_pmu != evsel__find_pmu(cur))) + continue; + + aggr = &cur->stats->aggr[aggr_idx]; +-- +2.39.5 + diff --git a/queue-6.14/perf-supply-task-information-to-sched_task.patch b/queue-6.14/perf-supply-task-information-to-sched_task.patch new file mode 100644 index 0000000000..ee1888f9da --- /dev/null +++ b/queue-6.14/perf-supply-task-information-to-sched_task.patch @@ -0,0 +1,323 @@ +From 3f9eb283032f1fe38c0cbd41d1083d895ee8d5a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 10:26:57 -0700 +Subject: perf: Supply task information to sched_task() + +From: Kan Liang + +[ Upstream commit d57e94f5b891925e4f2796266eba31edd5a01903 ] + +To save/restore LBR call stack data in system-wide mode, the task_struct +information is required. + +Extend the parameters of sched_task() to supply task_struct information. + +When schedule in, the LBR call stack data for new task will be restored. +When schedule out, the LBR call stack data for old task will be saved. +Only need to pass the required task_struct information. + +Signed-off-by: Kan Liang +Signed-off-by: Peter Zijlstra (Intel) +Link: https://lore.kernel.org/r/20250314172700.438923-4-kan.liang@linux.intel.com +Stable-dep-of: 3cec9fd03543 ("perf/x86/lbr: Fix shorter LBRs call stacks for the system-wide mode") +Signed-off-by: Sasha Levin +--- + arch/powerpc/perf/core-book3s.c | 8 ++++++-- + arch/s390/kernel/perf_pai_crypto.c | 3 ++- + arch/s390/kernel/perf_pai_ext.c | 3 ++- + arch/x86/events/amd/brs.c | 3 ++- + arch/x86/events/amd/lbr.c | 3 ++- + arch/x86/events/core.c | 5 +++-- + arch/x86/events/intel/core.c | 4 ++-- + arch/x86/events/intel/lbr.c | 3 ++- + arch/x86/events/perf_event.h | 14 +++++++++----- + include/linux/perf_event.h | 2 +- + kernel/events/core.c | 20 +++++++++++--------- + 11 files changed, 42 insertions(+), 26 deletions(-) + +diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c +index 2b79171ee185b..f4e03aaabb4c3 100644 +--- a/arch/powerpc/perf/core-book3s.c ++++ b/arch/powerpc/perf/core-book3s.c +@@ -132,7 +132,10 @@ static unsigned long ebb_switch_in(bool ebb, struct cpu_hw_events *cpuhw) + + static inline void power_pmu_bhrb_enable(struct perf_event *event) {} + static inline void power_pmu_bhrb_disable(struct perf_event *event) {} +-static void power_pmu_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in) {} ++static void power_pmu_sched_task(struct perf_event_pmu_context *pmu_ctx, ++ struct task_struct *task, bool sched_in) ++{ ++} + static inline void power_pmu_bhrb_read(struct perf_event *event, struct cpu_hw_events *cpuhw) {} + static void pmao_restore_workaround(bool ebb) { } + #endif /* CONFIG_PPC32 */ +@@ -444,7 +447,8 @@ static void power_pmu_bhrb_disable(struct perf_event *event) + /* Called from ctxsw to prevent one process's branch entries to + * mingle with the other process's entries during context switch. + */ +-static void power_pmu_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in) ++static void power_pmu_sched_task(struct perf_event_pmu_context *pmu_ctx, ++ struct task_struct *task, bool sched_in) + { + if (!ppmu->bhrb_nr) + return; +diff --git a/arch/s390/kernel/perf_pai_crypto.c b/arch/s390/kernel/perf_pai_crypto.c +index 10725f5a6f0fd..63875270941bc 100644 +--- a/arch/s390/kernel/perf_pai_crypto.c ++++ b/arch/s390/kernel/perf_pai_crypto.c +@@ -518,7 +518,8 @@ static void paicrypt_have_samples(void) + /* Called on schedule-in and schedule-out. No access to event structure, + * but for sampling only event CRYPTO_ALL is allowed. + */ +-static void paicrypt_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in) ++static void paicrypt_sched_task(struct perf_event_pmu_context *pmu_ctx, ++ struct task_struct *task, bool sched_in) + { + /* We started with a clean page on event installation. So read out + * results on schedule_out and if page was dirty, save old values. +diff --git a/arch/s390/kernel/perf_pai_ext.c b/arch/s390/kernel/perf_pai_ext.c +index a8f0bad99cf04..fd14d5ebccbca 100644 +--- a/arch/s390/kernel/perf_pai_ext.c ++++ b/arch/s390/kernel/perf_pai_ext.c +@@ -542,7 +542,8 @@ static void paiext_have_samples(void) + /* Called on schedule-in and schedule-out. No access to event structure, + * but for sampling only event NNPA_ALL is allowed. + */ +-static void paiext_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in) ++static void paiext_sched_task(struct perf_event_pmu_context *pmu_ctx, ++ struct task_struct *task, bool sched_in) + { + /* We started with a clean page on event installation. So read out + * results on schedule_out and if page was dirty, save old values. +diff --git a/arch/x86/events/amd/brs.c b/arch/x86/events/amd/brs.c +index 780acd3dff22a..ec34274633824 100644 +--- a/arch/x86/events/amd/brs.c ++++ b/arch/x86/events/amd/brs.c +@@ -381,7 +381,8 @@ static void amd_brs_poison_buffer(void) + * On ctxswin, sched_in = true, called after the PMU has started + * On ctxswout, sched_in = false, called before the PMU is stopped + */ +-void amd_pmu_brs_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in) ++void amd_pmu_brs_sched_task(struct perf_event_pmu_context *pmu_ctx, ++ struct task_struct *task, bool sched_in) + { + struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); + +diff --git a/arch/x86/events/amd/lbr.c b/arch/x86/events/amd/lbr.c +index 19c7b76e21bcb..c06ccca96851f 100644 +--- a/arch/x86/events/amd/lbr.c ++++ b/arch/x86/events/amd/lbr.c +@@ -371,7 +371,8 @@ void amd_pmu_lbr_del(struct perf_event *event) + perf_sched_cb_dec(event->pmu); + } + +-void amd_pmu_lbr_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in) ++void amd_pmu_lbr_sched_task(struct perf_event_pmu_context *pmu_ctx, ++ struct task_struct *task, bool sched_in) + { + struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); + +diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c +index 2092d615333da..3a27c50080f4f 100644 +--- a/arch/x86/events/core.c ++++ b/arch/x86/events/core.c +@@ -2625,9 +2625,10 @@ static const struct attribute_group *x86_pmu_attr_groups[] = { + NULL, + }; + +-static void x86_pmu_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in) ++static void x86_pmu_sched_task(struct perf_event_pmu_context *pmu_ctx, ++ struct task_struct *task, bool sched_in) + { +- static_call_cond(x86_pmu_sched_task)(pmu_ctx, sched_in); ++ static_call_cond(x86_pmu_sched_task)(pmu_ctx, task, sched_in); + } + + static void x86_pmu_swap_task_ctx(struct perf_event_pmu_context *prev_epc, +diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c +index cdb19e3ba3aa3..f5eea63013b9b 100644 +--- a/arch/x86/events/intel/core.c ++++ b/arch/x86/events/intel/core.c +@@ -5244,10 +5244,10 @@ static void intel_pmu_cpu_dead(int cpu) + } + + static void intel_pmu_sched_task(struct perf_event_pmu_context *pmu_ctx, +- bool sched_in) ++ struct task_struct *task, bool sched_in) + { + intel_pmu_pebs_sched_task(pmu_ctx, sched_in); +- intel_pmu_lbr_sched_task(pmu_ctx, sched_in); ++ intel_pmu_lbr_sched_task(pmu_ctx, task, sched_in); + } + + static void intel_pmu_swap_task_ctx(struct perf_event_pmu_context *prev_epc, +diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c +index dc641b50814e2..dafeee216f3b6 100644 +--- a/arch/x86/events/intel/lbr.c ++++ b/arch/x86/events/intel/lbr.c +@@ -539,7 +539,8 @@ void intel_pmu_lbr_swap_task_ctx(struct perf_event_pmu_context *prev_epc, + task_context_opt(next_ctx_data)->lbr_callstack_users); + } + +-void intel_pmu_lbr_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in) ++void intel_pmu_lbr_sched_task(struct perf_event_pmu_context *pmu_ctx, ++ struct task_struct *task, bool sched_in) + { + struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); + void *task_ctx; +diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h +index 31c2771545a6c..ce7c98364d5b6 100644 +--- a/arch/x86/events/perf_event.h ++++ b/arch/x86/events/perf_event.h +@@ -869,7 +869,7 @@ struct x86_pmu { + + void (*check_microcode)(void); + void (*sched_task)(struct perf_event_pmu_context *pmu_ctx, +- bool sched_in); ++ struct task_struct *task, bool sched_in); + + /* + * Intel Arch Perfmon v2+ +@@ -1394,7 +1394,8 @@ void amd_pmu_lbr_reset(void); + void amd_pmu_lbr_read(void); + void amd_pmu_lbr_add(struct perf_event *event); + void amd_pmu_lbr_del(struct perf_event *event); +-void amd_pmu_lbr_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in); ++void amd_pmu_lbr_sched_task(struct perf_event_pmu_context *pmu_ctx, ++ struct task_struct *task, bool sched_in); + void amd_pmu_lbr_enable_all(void); + void amd_pmu_lbr_disable_all(void); + int amd_pmu_lbr_hw_config(struct perf_event *event); +@@ -1448,7 +1449,8 @@ static inline void amd_pmu_brs_del(struct perf_event *event) + perf_sched_cb_dec(event->pmu); + } + +-void amd_pmu_brs_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in); ++void amd_pmu_brs_sched_task(struct perf_event_pmu_context *pmu_ctx, ++ struct task_struct *task, bool sched_in); + #else + static inline int amd_brs_init(void) + { +@@ -1473,7 +1475,8 @@ static inline void amd_pmu_brs_del(struct perf_event *event) + { + } + +-static inline void amd_pmu_brs_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in) ++static inline void amd_pmu_brs_sched_task(struct perf_event_pmu_context *pmu_ctx, ++ struct task_struct *task, bool sched_in) + { + } + +@@ -1656,7 +1659,8 @@ void intel_pmu_lbr_save_brstack(struct perf_sample_data *data, + void intel_pmu_lbr_swap_task_ctx(struct perf_event_pmu_context *prev_epc, + struct perf_event_pmu_context *next_epc); + +-void intel_pmu_lbr_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in); ++void intel_pmu_lbr_sched_task(struct perf_event_pmu_context *pmu_ctx, ++ struct task_struct *task, bool sched_in); + + u64 lbr_from_signext_quirk_wr(u64 val); + +diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h +index 852ea843bca27..bcb764c3a8034 100644 +--- a/include/linux/perf_event.h ++++ b/include/linux/perf_event.h +@@ -495,7 +495,7 @@ struct pmu { + * context-switches callback + */ + void (*sched_task) (struct perf_event_pmu_context *pmu_ctx, +- bool sched_in); ++ struct task_struct *task, bool sched_in); + + /* + * Kmem cache of PMU specific data +diff --git a/kernel/events/core.c b/kernel/events/core.c +index eb359be7ec793..03c27754aef8b 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -3558,7 +3558,8 @@ static void perf_event_swap_task_ctx_data(struct perf_event_context *prev_ctx, + } + } + +-static void perf_ctx_sched_task_cb(struct perf_event_context *ctx, bool sched_in) ++static void perf_ctx_sched_task_cb(struct perf_event_context *ctx, ++ struct task_struct *task, bool sched_in) + { + struct perf_event_pmu_context *pmu_ctx; + struct perf_cpu_pmu_context *cpc; +@@ -3567,7 +3568,7 @@ static void perf_ctx_sched_task_cb(struct perf_event_context *ctx, bool sched_in + cpc = this_cpu_ptr(pmu_ctx->pmu->cpu_pmu_context); + + if (cpc->sched_cb_usage && pmu_ctx->pmu->sched_task) +- pmu_ctx->pmu->sched_task(pmu_ctx, sched_in); ++ pmu_ctx->pmu->sched_task(pmu_ctx, task, sched_in); + } + } + +@@ -3630,7 +3631,7 @@ perf_event_context_sched_out(struct task_struct *task, struct task_struct *next) + WRITE_ONCE(ctx->task, next); + WRITE_ONCE(next_ctx->task, task); + +- perf_ctx_sched_task_cb(ctx, false); ++ perf_ctx_sched_task_cb(ctx, task, false); + perf_event_swap_task_ctx_data(ctx, next_ctx); + + perf_ctx_enable(ctx, false); +@@ -3660,7 +3661,7 @@ perf_event_context_sched_out(struct task_struct *task, struct task_struct *next) + perf_ctx_disable(ctx, false); + + inside_switch: +- perf_ctx_sched_task_cb(ctx, false); ++ perf_ctx_sched_task_cb(ctx, task, false); + task_ctx_sched_out(ctx, NULL, EVENT_ALL); + + perf_ctx_enable(ctx, false); +@@ -3702,7 +3703,8 @@ void perf_sched_cb_inc(struct pmu *pmu) + * PEBS requires this to provide PID/TID information. This requires we flush + * all queued PEBS records before we context switch to a new task. + */ +-static void __perf_pmu_sched_task(struct perf_cpu_pmu_context *cpc, bool sched_in) ++static void __perf_pmu_sched_task(struct perf_cpu_pmu_context *cpc, ++ struct task_struct *task, bool sched_in) + { + struct perf_cpu_context *cpuctx = this_cpu_ptr(&perf_cpu_context); + struct pmu *pmu; +@@ -3716,7 +3718,7 @@ static void __perf_pmu_sched_task(struct perf_cpu_pmu_context *cpc, bool sched_i + perf_ctx_lock(cpuctx, cpuctx->task_ctx); + perf_pmu_disable(pmu); + +- pmu->sched_task(cpc->task_epc, sched_in); ++ pmu->sched_task(cpc->task_epc, task, sched_in); + + perf_pmu_enable(pmu); + perf_ctx_unlock(cpuctx, cpuctx->task_ctx); +@@ -3734,7 +3736,7 @@ static void perf_pmu_sched_task(struct task_struct *prev, + return; + + list_for_each_entry(cpc, this_cpu_ptr(&sched_cb_list), sched_cb_entry) +- __perf_pmu_sched_task(cpc, sched_in); ++ __perf_pmu_sched_task(cpc, sched_in ? next : prev, sched_in); + } + + static void perf_event_switch(struct task_struct *task, +@@ -4029,7 +4031,7 @@ static void perf_event_context_sched_in(struct task_struct *task) + perf_ctx_lock(cpuctx, ctx); + perf_ctx_disable(ctx, false); + +- perf_ctx_sched_task_cb(ctx, true); ++ perf_ctx_sched_task_cb(ctx, task, true); + + perf_ctx_enable(ctx, false); + perf_ctx_unlock(cpuctx, ctx); +@@ -4060,7 +4062,7 @@ static void perf_event_context_sched_in(struct task_struct *task) + + perf_event_sched_in(cpuctx, ctx, NULL); + +- perf_ctx_sched_task_cb(cpuctx->task_ctx, true); ++ perf_ctx_sched_task_cb(cpuctx->task_ctx, task, true); + + if (!RB_EMPTY_ROOT(&ctx->pinned_groups.tree)) + perf_ctx_enable(&cpuctx->ctx, false); +-- +2.39.5 + diff --git a/queue-6.14/perf-test-add-timeout-to-datasym-workload.patch b/queue-6.14/perf-test-add-timeout-to-datasym-workload.patch new file mode 100644 index 0000000000..dfacd68fab --- /dev/null +++ b/queue-6.14/perf-test-add-timeout-to-datasym-workload.patch @@ -0,0 +1,68 @@ +From 48e68512e124afee1472e212da60be36b3fd94c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 18:28:36 -0800 +Subject: perf test: Add timeout to datasym workload + +From: Namhyung Kim + +[ Upstream commit f04c7ef35256beea57a598a7ea06dd2242ae9ae6 ] + +Unlike others it has an infinite loop that make it annoying to call. +Make it finish after 1 second and handle command-line argument to change +the setting. + +Reviewed-by: Leo Yan +Tested-by: Thomas Richter +Tested-by: Thomas Falcon +Cc: Thomas Richter +Cc: Leo Yan +Link: https://lore.kernel.org/r/20250304022837.1877845-6-namhyung@kernel.org +Signed-off-by: Namhyung Kim +Stable-dep-of: 36e7748d33bf ("perf tests: Fix data symbol test with LTO builds") +Signed-off-by: Sasha Levin +--- + tools/perf/tests/workloads/datasym.c | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/tests/workloads/datasym.c b/tools/perf/tests/workloads/datasym.c +index 8e08fc75a973e..8ddb2aa6a049e 100644 +--- a/tools/perf/tests/workloads/datasym.c ++++ b/tools/perf/tests/workloads/datasym.c +@@ -1,3 +1,6 @@ ++#include ++#include ++#include + #include + #include "../tests.h" + +@@ -12,9 +15,25 @@ static buf buf1 = { + .reserved[0] = 1, + }; + +-static int datasym(int argc __maybe_unused, const char **argv __maybe_unused) ++static volatile sig_atomic_t done; ++ ++static void sighandler(int sig __maybe_unused) ++{ ++ done = 1; ++} ++ ++static int datasym(int argc, const char **argv) + { +- for (;;) { ++ int sec = 1; ++ ++ if (argc > 0) ++ sec = atoi(argv[0]); ++ ++ signal(SIGINT, sighandler); ++ signal(SIGALRM, sighandler); ++ alarm(sec); ++ ++ while (!done) { + buf1.data1++; + if (buf1.data1 == 123) { + /* +-- +2.39.5 + diff --git a/queue-6.14/perf-test-fix-hwmon-pmu-test-endianess-issue.patch b/queue-6.14/perf-test-fix-hwmon-pmu-test-endianess-issue.patch new file mode 100644 index 0000000000..2538cd090a --- /dev/null +++ b/queue-6.14/perf-test-fix-hwmon-pmu-test-endianess-issue.patch @@ -0,0 +1,219 @@ +From 9db927aaf94b57a87ce198f6fcf8ba31fe5ae382 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 12:24:00 +0100 +Subject: perf test: Fix Hwmon PMU test endianess issue + +From: Thomas Richter + +[ Upstream commit 888751e4d0e948d0364eee6fb47e21f090b2b5e4 ] + +perf test 11 hwmon fails on s390 with this error + + # ./perf test -Fv 11 + --- start --- + ---- end ---- + 11.1: Basic parsing test : Ok + --- start --- + Testing 'temp_test_hwmon_event1' + Using CPUID IBM,3931,704,A01,3.7,002f + temp_test_hwmon_event1 -> hwmon_a_test_hwmon_pmu/temp_test_hwmon_event1/ + FAILED tests/hwmon_pmu.c:189 Unexpected config for + 'temp_test_hwmon_event1', 292470092988416 != 655361 + ---- end ---- + 11.2: Parsing without PMU name : FAILED! + --- start --- + Testing 'hwmon_a_test_hwmon_pmu/temp_test_hwmon_event1/' + FAILED tests/hwmon_pmu.c:189 Unexpected config for + 'hwmon_a_test_hwmon_pmu/temp_test_hwmon_event1/', + 292470092988416 != 655361 + ---- end ---- + 11.3: Parsing with PMU name : FAILED! + # + +The root cause is in member test_event::config which is initialized +to 0xA0001 or 655361. During event parsing a long list event parsing +functions are called and end up with this gdb call stack: + + #0 hwmon_pmu__config_term (hwm=0x168dfd0, attr=0x3ffffff5ee8, + term=0x168db60, err=0x3ffffff81c8) at util/hwmon_pmu.c:623 + #1 hwmon_pmu__config_terms (pmu=0x168dfd0, attr=0x3ffffff5ee8, + terms=0x3ffffff5ea8, err=0x3ffffff81c8) at util/hwmon_pmu.c:662 + #2 0x00000000012f870c in perf_pmu__config_terms (pmu=0x168dfd0, + attr=0x3ffffff5ee8, terms=0x3ffffff5ea8, zero=false, + apply_hardcoded=false, err=0x3ffffff81c8) at util/pmu.c:1519 + #3 0x00000000012f88a4 in perf_pmu__config (pmu=0x168dfd0, attr=0x3ffffff5ee8, + head_terms=0x3ffffff5ea8, apply_hardcoded=false, err=0x3ffffff81c8) + at util/pmu.c:1545 + #4 0x00000000012680c4 in parse_events_add_pmu (parse_state=0x3ffffff7fb8, + list=0x168dc00, pmu=0x168dfd0, const_parsed_terms=0x3ffffff6090, + auto_merge_stats=true, alternate_hw_config=10) + at util/parse-events.c:1508 + #5 0x00000000012684c6 in parse_events_multi_pmu_add (parse_state=0x3ffffff7fb8, + event_name=0x168ec10 "temp_test_hwmon_event1", hw_config=10, + const_parsed_terms=0x0, listp=0x3ffffff6230, loc_=0x3ffffff70e0) + at util/parse-events.c:1592 + #6 0x00000000012f0e4e in parse_events_parse (_parse_state=0x3ffffff7fb8, + scanner=0x16878c0) at util/parse-events.y:293 + #7 0x00000000012695a0 in parse_events__scanner (str=0x3ffffff81d8 + "temp_test_hwmon_event1", input=0x0, parse_state=0x3ffffff7fb8) + at util/parse-events.c:1867 + #8 0x000000000126a1e8 in __parse_events (evlist=0x168b580, + str=0x3ffffff81d8 "temp_test_hwmon_event1", pmu_filter=0x0, + err=0x3ffffff81c8, fake_pmu=false, warn_if_reordered=true, + fake_tp=false) at util/parse-events.c:2136 + #9 0x00000000011e36aa in parse_events (evlist=0x168b580, + str=0x3ffffff81d8 "temp_test_hwmon_event1", err=0x3ffffff81c8) + at /root/linux/tools/perf/util/parse-events.h:41 + #10 0x00000000011e3e64 in do_test (i=0, with_pmu=false, with_alias=false) + at tests/hwmon_pmu.c:164 + #11 0x00000000011e422c in test__hwmon_pmu (with_pmu=false) + at tests/hwmon_pmu.c:219 + #12 0x00000000011e431c in test__hwmon_pmu_without_pmu (test=0x1610368 + , subtest=1) at tests/hwmon_pmu.c:23 + +where the attr::config is set to value 292470092988416 or 0x10a0000000000 +in line 625 of file ./util/hwmon_pmu.c: + + attr->config = key.type_and_num; + +However member key::type_and_num is defined as union and bit field: + + union hwmon_pmu_event_key { + long type_and_num; + struct { + int num :16; + enum hwmon_type type :8; + }; + }; + +s390 is big endian and Intel is little endian architecture. +The events for the hwmon dummy pmu have num = 1 or num = 2 and +type is set to HWMON_TYPE_TEMP (which is 10). +On s390 this assignes member key::type_and_num the value of +0x10a0000000000 (which is 292470092988416) as shown in above +trace output. + +Fix this and export the structure/union hwmon_pmu_event_key +so the test shares the same implementation as the event parsing +functions for union and bit fields. This should avoid +endianess issues on all platforms. + +Output after: + # ./perf test -F 11 + 11.1: Basic parsing test : Ok + 11.2: Parsing without PMU name : Ok + 11.3: Parsing with PMU name : Ok + # + +Fixes: 531ee0fd4836 ("perf test: Add hwmon "PMU" test") +Signed-off-by: Thomas Richter +Reviewed-by: Ian Rogers +Link: https://lore.kernel.org/r/20250131112400.568975-1-tmricht@linux.ibm.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/tests/hwmon_pmu.c | 16 +++++++++++----- + tools/perf/util/hwmon_pmu.c | 14 -------------- + tools/perf/util/hwmon_pmu.h | 16 ++++++++++++++++ + 3 files changed, 27 insertions(+), 19 deletions(-) + +diff --git a/tools/perf/tests/hwmon_pmu.c b/tools/perf/tests/hwmon_pmu.c +index d2b066a2b557a..0837aca1cdfa7 100644 +--- a/tools/perf/tests/hwmon_pmu.c ++++ b/tools/perf/tests/hwmon_pmu.c +@@ -13,17 +13,23 @@ + static const struct test_event { + const char *name; + const char *alias; +- long config; ++ union hwmon_pmu_event_key key; + } test_events[] = { + { + "temp_test_hwmon_event1", + "temp1", +- 0xA0001, ++ .key = { ++ .num = 1, ++ .type = 10 ++ }, + }, + { + "temp_test_hwmon_event2", + "temp2", +- 0xA0002, ++ .key = { ++ .num = 2, ++ .type = 10 ++ }, + }, + }; + +@@ -183,11 +189,11 @@ static int do_test(size_t i, bool with_pmu, bool with_alias) + strcmp(evsel->pmu->name, "hwmon_a_test_hwmon_pmu")) + continue; + +- if (evsel->core.attr.config != (u64)test_events[i].config) { ++ if (evsel->core.attr.config != (u64)test_events[i].key.type_and_num) { + pr_debug("FAILED %s:%d Unexpected config for '%s', %lld != %ld\n", + __FILE__, __LINE__, str, + evsel->core.attr.config, +- test_events[i].config); ++ test_events[i].key.type_and_num); + ret = TEST_FAIL; + goto out; + } +diff --git a/tools/perf/util/hwmon_pmu.c b/tools/perf/util/hwmon_pmu.c +index 4acb9bb19b846..acd889b2462f6 100644 +--- a/tools/perf/util/hwmon_pmu.c ++++ b/tools/perf/util/hwmon_pmu.c +@@ -107,20 +107,6 @@ struct hwmon_pmu { + int hwmon_dir_fd; + }; + +-/** +- * union hwmon_pmu_event_key: Key for hwmon_pmu->events as such each key +- * represents an event. +- * +- * Related hwmon files start that this key represents. +- */ +-union hwmon_pmu_event_key { +- long type_and_num; +- struct { +- int num :16; +- enum hwmon_type type :8; +- }; +-}; +- + /** + * struct hwmon_pmu_event_value: Value in hwmon_pmu->events. + * +diff --git a/tools/perf/util/hwmon_pmu.h b/tools/perf/util/hwmon_pmu.h +index 882566846df46..b3329774d2b22 100644 +--- a/tools/perf/util/hwmon_pmu.h ++++ b/tools/perf/util/hwmon_pmu.h +@@ -91,6 +91,22 @@ enum hwmon_item { + HWMON_ITEM__MAX, + }; + ++/** ++ * union hwmon_pmu_event_key: Key for hwmon_pmu->events as such each key ++ * represents an event. ++ * union is exposed for testing to ensure problems are avoided on big ++ * endian machines. ++ * ++ * Related hwmon files start that this key represents. ++ */ ++union hwmon_pmu_event_key { ++ long type_and_num; ++ struct { ++ int num :16; ++ enum hwmon_type type :8; ++ }; ++}; ++ + bool perf_pmu__is_hwmon(const struct perf_pmu *pmu); + bool evsel__is_hwmon(const struct evsel *evsel); + +-- +2.39.5 + diff --git a/queue-6.14/perf-test-stat_all_pmu.sh-correctly-check-perf-stat-.patch b/queue-6.14/perf-test-stat_all_pmu.sh-correctly-check-perf-stat-.patch new file mode 100644 index 0000000000..bdee538dbf --- /dev/null +++ b/queue-6.14/perf-test-stat_all_pmu.sh-correctly-check-perf-stat-.patch @@ -0,0 +1,126 @@ +From 945305bcfa9a28a6efd97985826ad7ed746f63d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Nov 2024 00:12:33 +0100 +Subject: perf test stat_all_pmu.sh: Correctly check 'perf stat' result + +From: Veronika Molnarova + +[ Upstream commit 02ba09c8ab9406f30c5c63b7cfd4b300c3c2c32c ] + +Test case "stat_all_pmu.sh" is not correctly checking 'perf stat' output +due to a poor design. Firstly, having the 'set -e' option with a trap +catching the sigexit causes the shell to exit immediately if 'perf stat' ends +with any non-zero value, which is then caught by the trap reporting an +unexpected signal. This causes events that should be parsed by the if-else +statement to be caught by the trap handler and are reported as errors: + + $ perf test -vv "perf all pmu" + Testing i915/actual-frequency/ + Unexpected signal in main + Error: + Access to performance monitoring and observability operations is limited. + +Secondly, the if-else branches are not exclusive as the checking if the +event is present in the output log covers also the "" +events, which should be accepted, and also the "Bad name events", which +should be rejected. + +Remove the "set -e" option from the test case, correctly parse the +"perf stat" output log and check its return value. Add the missing +outputs for the 'perf stat' result and also add logs messages to +report the branch that parsed the event for more info. + +Fixes: 7e73ea40295620e7 ("perf test: Ignore security failures in all PMU test") +Signed-off-by: Veronika Molnarova +Tested-by: Qiao Zhao +Link: https://lore.kernel.org/r/20241122231233.79509-1-vmolnaro@redhat.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/tests/shell/stat_all_pmu.sh | 48 ++++++++++++++++++-------- + 1 file changed, 34 insertions(+), 14 deletions(-) + +diff --git a/tools/perf/tests/shell/stat_all_pmu.sh b/tools/perf/tests/shell/stat_all_pmu.sh +index 8b148b300be11..9c466c0efa857 100755 +--- a/tools/perf/tests/shell/stat_all_pmu.sh ++++ b/tools/perf/tests/shell/stat_all_pmu.sh +@@ -2,7 +2,6 @@ + # perf all PMU test (exclusive) + # SPDX-License-Identifier: GPL-2.0 + +-set -e + err=0 + result="" + +@@ -16,34 +15,55 @@ trap trap_cleanup EXIT TERM INT + # Test all PMU events; however exclude parameterized ones (name contains '?') + for p in $(perf list --raw-dump pmu | sed 's/[[:graph:]]\+?[[:graph:]]\+[[:space:]]//g') + do +- echo "Testing $p" +- result=$(perf stat -e "$p" true 2>&1) +- if echo "$result" | grep -q "$p" ++ echo -n "Testing $p -- " ++ output=$(perf stat -e "$p" true 2>&1) ++ stat_result=$? ++ if echo "$output" | grep -q "$p" + then + # Event seen in output. +- continue +- fi +- if echo "$result" | grep -q "" +- then +- # Event not supported, so ignore. +- continue ++ if [ $stat_result -eq 0 ] && ! echo "$output" | grep -q "" ++ then ++ # Event supported. ++ echo "supported" ++ continue ++ elif echo "$output" | grep -q "" ++ then ++ # Event not supported, so ignore. ++ echo "not supported" ++ continue ++ elif echo "$output" | grep -q "No permission to enable" ++ then ++ # No permissions, so ignore. ++ echo "no permission to enable" ++ continue ++ elif echo "$output" | grep -q "Bad event name" ++ then ++ # Non-existent event. ++ echo "Error: Bad event name" ++ echo "$output" ++ err=1 ++ continue ++ fi + fi +- if echo "$result" | grep -q "Access to performance monitoring and observability operations is limited." ++ ++ if echo "$output" | grep -q "Access to performance monitoring and observability operations is limited." + then + # Access is limited, so ignore. ++ echo "access limited" + continue + fi + + # We failed to see the event and it is supported. Possibly the workload was + # too small so retry with something longer. +- result=$(perf stat -e "$p" perf bench internals synthesize 2>&1) +- if echo "$result" | grep -q "$p" ++ output=$(perf stat -e "$p" perf bench internals synthesize 2>&1) ++ if echo "$output" | grep -q "$p" + then + # Event seen in output. ++ echo "supported" + continue + fi + echo "Error: event '$p' not printed in:" +- echo "$result" ++ echo "$output" + err=1 + done + +-- +2.39.5 + diff --git a/queue-6.14/perf-tests-fix-data-symbol-test-with-lto-builds.patch b/queue-6.14/perf-tests-fix-data-symbol-test-with-lto-builds.patch new file mode 100644 index 0000000000..6d331718bd --- /dev/null +++ b/queue-6.14/perf-tests-fix-data-symbol-test-with-lto-builds.patch @@ -0,0 +1,138 @@ +From 015821a9ad626f6356ac52939ac8f90a776bc2cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 15:01:09 -0800 +Subject: perf tests: Fix data symbol test with LTO builds + +From: Ian Rogers + +[ Upstream commit 36e7748d33bf6a82e558009e03448e9321465e05 ] + +With LTO builds, although regular builds could also see this as +all the code is in one file, the datasym workload can realize the +buf1.reserved data is never accessed. The compiler moves the +variable to bss and only keeps the data1 and data2 parts as +separate variables. This causes the symbol check to fail in the +test. Make the variable volatile to disable the more aggressive +optimization. Rename the variable to make which buf1 in perf is +being referred to. + +Before: + + $ perf test -vv "data symbol" + 126: Test data symbol: + --- start --- + test child forked, pid 299808 + perf does not have symbol 'buf1' + perf is missing symbols - skipping test + ---- end(-2) ---- + 126: Test data symbol : Skip + $ nm perf|grep buf1 + 0000000000a5fa40 b buf1.0 + 0000000000a5fa48 b buf1.1 + +After: + + $ nm perf|grep buf1 + 0000000000a53a00 d buf1 + $ perf test -vv "data symbol"126: Test data symbol: + --- start --- + test child forked, pid 302166 + a53a00-a53a39 l buf1 + perf does have symbol 'buf1' + Recording workload... + Waiting for "perf record has started" message + OK + Cleaning up files... + ---- end(0) ---- + 126: Test data symbol : Ok + +Fixes: 3dfc01fe9d12 ("perf test: Add 'datasym' test workload") +Signed-off-by: Ian Rogers +Link: https://lore.kernel.org/r/20250226230109.314580-1-irogers@google.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/tests/shell/test_data_symbol.sh | 17 +++++++++-------- + tools/perf/tests/workloads/datasym.c | 11 ++++++----- + 2 files changed, 15 insertions(+), 13 deletions(-) + +diff --git a/tools/perf/tests/shell/test_data_symbol.sh b/tools/perf/tests/shell/test_data_symbol.sh +index c86da02350596..7da606db97cb4 100755 +--- a/tools/perf/tests/shell/test_data_symbol.sh ++++ b/tools/perf/tests/shell/test_data_symbol.sh +@@ -18,7 +18,7 @@ skip_if_no_mem_event() { + + skip_if_no_mem_event || exit 2 + +-skip_test_missing_symbol buf1 ++skip_test_missing_symbol workload_datasym_buf1 + + TEST_PROGRAM="perf test -w datasym" + PERF_DATA=$(mktemp /tmp/__perf_test.perf.data.XXXXX) +@@ -26,18 +26,19 @@ ERR_FILE=$(mktemp /tmp/__perf_test.stderr.XXXXX) + + check_result() { + # The memory report format is as below: +- # 99.92% ... [.] buf1+0x38 ++ # 99.92% ... [.] workload_datasym_buf1+0x38 + result=$(perf mem report -i ${PERF_DATA} -s symbol_daddr -q 2>&1 | +- awk '/buf1/ { print $4 }') ++ awk '/workload_datasym_buf1/ { print $4 }') + +- # Testing is failed if has no any sample for "buf1" ++ # Testing is failed if has no any sample for "workload_datasym_buf1" + [ -z "$result" ] && return 1 + + while IFS= read -r line; do +- # The "data1" and "data2" fields in structure "buf1" have +- # offset "0x0" and "0x38", returns failure if detect any +- # other offset value. +- if [ "$line" != "buf1+0x0" ] && [ "$line" != "buf1+0x38" ]; then ++ # The "data1" and "data2" fields in structure ++ # "workload_datasym_buf1" have offset "0x0" and "0x38", returns ++ # failure if detect any other offset value. ++ if [ "$line" != "workload_datasym_buf1+0x0" ] && \ ++ [ "$line" != "workload_datasym_buf1+0x38" ]; then + return 1 + fi + done <<< "$result" +diff --git a/tools/perf/tests/workloads/datasym.c b/tools/perf/tests/workloads/datasym.c +index 8ddb2aa6a049e..1d0b7d64e1ba1 100644 +--- a/tools/perf/tests/workloads/datasym.c ++++ b/tools/perf/tests/workloads/datasym.c +@@ -10,7 +10,8 @@ typedef struct _buf { + char data2; + } buf __attribute__((aligned(64))); + +-static buf buf1 = { ++/* volatile to try to avoid the compiler seeing reserved as unused. */ ++static volatile buf workload_datasym_buf1 = { + /* to have this in the data section */ + .reserved[0] = 1, + }; +@@ -34,8 +35,8 @@ static int datasym(int argc, const char **argv) + alarm(sec); + + while (!done) { +- buf1.data1++; +- if (buf1.data1 == 123) { ++ workload_datasym_buf1.data1++; ++ if (workload_datasym_buf1.data1 == 123) { + /* + * Add some 'noise' in the loop to work around errata + * 1694299 on Arm N1. +@@ -49,9 +50,9 @@ static int datasym(int argc, const char **argv) + * longer a continuous repeating pattern that interacts + * badly with the bias. + */ +- buf1.data1++; ++ workload_datasym_buf1.data1++; + } +- buf1.data2 += buf1.data1; ++ workload_datasym_buf1.data2 += workload_datasym_buf1.data1; + } + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/perf-tests-fix-tool-pmu-test-segfault.patch b/queue-6.14/perf-tests-fix-tool-pmu-test-segfault.patch new file mode 100644 index 0000000000..717773570c --- /dev/null +++ b/queue-6.14/perf-tests-fix-tool-pmu-test-segfault.patch @@ -0,0 +1,58 @@ +From 39b9c8e5d8809d2243411c83b5d34fa907178afa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 16:38:56 +0000 +Subject: perf tests: Fix Tool PMU test segfault + +From: James Clark + +[ Upstream commit 615ec00b06f78912c370b372426190768402a5b9 ] + +tool_pmu__event_to_str() now handles skipped events by returning NULL, +so it's wrong to re-check for a skip on the resulting string. Calling +tool_pmu__skip_event() with a NULL string results in a segfault so +remove the unnecessary skip to fix it: + + $ perf test -vv "parsing with PMU name" + + 12.2: Parsing with PMU name: + ... + ---- unexpected signal (11) ---- + 12.2: Parsing with PMU name : FAILED! + +Fixes: ee8aef2d2321 ("perf tools: Add skip check in tool_pmu__event_to_str()") +Signed-off-by: James Clark +Reported-by: Athira Rajeev +Acked-by: Kan Liang +Tested-by: Ian Rogers +Link: https://lore.kernel.org/r/20250212163859.1489916-1-james.clark@linaro.org +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/tests/tool_pmu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/tests/tool_pmu.c b/tools/perf/tests/tool_pmu.c +index 187942b749b7c..1e900ef92e378 100644 +--- a/tools/perf/tests/tool_pmu.c ++++ b/tools/perf/tests/tool_pmu.c +@@ -27,7 +27,7 @@ static int do_test(enum tool_pmu_event ev, bool with_pmu) + parse_events_error__init(&err); + ret = parse_events(evlist, str, &err); + if (ret) { +- if (tool_pmu__skip_event(tool_pmu__event_to_str(ev))) { ++ if (!tool_pmu__event_to_str(ev)) { + ret = TEST_OK; + goto out; + } +@@ -59,7 +59,7 @@ static int do_test(enum tool_pmu_event ev, bool with_pmu) + } + } + +- if (!found && !tool_pmu__skip_event(tool_pmu__event_to_str(ev))) { ++ if (!found && tool_pmu__event_to_str(ev)) { + pr_debug("FAILED %s:%d Didn't find tool event '%s' in parsed evsels\n", + __FILE__, __LINE__, str); + ret = TEST_FAIL; +-- +2.39.5 + diff --git a/queue-6.14/perf-tools-add-skip-check-in-tool_pmu__event_to_str.patch b/queue-6.14/perf-tools-add-skip-check-in-tool_pmu__event_to_str.patch new file mode 100644 index 0000000000..a2801376be --- /dev/null +++ b/queue-6.14/perf-tools-add-skip-check-in-tool_pmu__event_to_str.patch @@ -0,0 +1,71 @@ +From ff5976feb66fdd33962fbff321a5d85e1e1aa227 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 07:28:44 -0800 +Subject: perf tools: Add skip check in tool_pmu__event_to_str() + +From: Kan Liang + +[ Upstream commit ee8aef2d232142e5fdfed9c16132815969a0bf81 ] + +Some topdown related metrics may fail on hybrid machines. + + $ perf stat -M tma_frontend_bound + Cannot resolve IDs for tma_frontend_bound: + cpu_atom@TOPDOWN_FE_BOUND.ALL@ / (8 * cpu_atom@CPU_CLK_UNHALTED.CORE@) + +In the find_tool_events(), the tool_pmu__event_to_str() is used to +compare the tool_events. It only checks the event name, no PMU or arch. +So the tool_events[TOOL_PMU__EVENT_SLOTS] is set to true, because the +p-core Topdown metrics has "slots" event. +The tool_events is shared. So when parsing the e-core metrics, the +"slots" is automatically added. + +The "slots" event as a tool event should only be available on arm64. It +has a different meaning on X86. The tool_pmu__skip_event() intends +handle the case. Apply it for tool_pmu__event_to_str() as well. + +There is a lack of sanity check in the expr__get_id(). Add the check. + +Closes: https://lore.kernel.org/lkml/608077bc-4139-4a97-8dc4-7997177d95c4@linux.intel.com/ +Fixes: 069057239a67 ("perf tool_pmu: Move expr literals to tool_pmu") +Signed-off-by: Kan Liang +Reviewed-by: Ian Rogers +Cc: thomas.falcon@intel.com +Link: https://lore.kernel.org/r/20250207152844.302167-1-kan.liang@linux.intel.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/util/expr.c | 2 ++ + tools/perf/util/tool_pmu.c | 3 ++- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c +index c221dcce66660..6413537442aa8 100644 +--- a/tools/perf/util/expr.c ++++ b/tools/perf/util/expr.c +@@ -215,6 +215,8 @@ int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref) + int expr__get_id(struct expr_parse_ctx *ctx, const char *id, + struct expr_id_data **data) + { ++ if (!ctx || !id) ++ return -1; + return hashmap__find(ctx->ids, id, data) ? 0 : -1; + } + +diff --git a/tools/perf/util/tool_pmu.c b/tools/perf/util/tool_pmu.c +index 4fb0975784794..3a68debe71437 100644 +--- a/tools/perf/util/tool_pmu.c ++++ b/tools/perf/util/tool_pmu.c +@@ -62,7 +62,8 @@ int tool_pmu__num_skip_events(void) + + const char *tool_pmu__event_to_str(enum tool_pmu_event ev) + { +- if (ev > TOOL_PMU__EVENT_NONE && ev < TOOL_PMU__EVENT_MAX) ++ if ((ev > TOOL_PMU__EVENT_NONE && ev < TOOL_PMU__EVENT_MAX) && ++ !tool_pmu__skip_event(tool_pmu__event_names[ev])) + return tool_pmu__event_names[ev]; + + return NULL; +-- +2.39.5 + diff --git a/queue-6.14/perf-tools-annotate-asm_pure_loop.s.patch b/queue-6.14/perf-tools-annotate-asm_pure_loop.s.patch new file mode 100644 index 0000000000..4dab72e412 --- /dev/null +++ b/queue-6.14/perf-tools-annotate-asm_pure_loop.s.patch @@ -0,0 +1,34 @@ +From 97ab8d398fedd198a7994ff966368f09cfb9a0c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 23 Mar 2025 09:53:45 +0100 +Subject: perf tools: annotate asm_pure_loop.S + +From: Marcus Meissner + +[ Upstream commit 9a352a90e88a041f4b26d359493e12a7f5ae1a6a ] + +Annotate so it is built with non-executable stack. + +Fixes: 8b97519711c3 ("perf test: Add asm pureloop test tool") +Signed-off-by: Marcus Meissner +Reviewed-by: Leo Yan +Link: https://lore.kernel.org/r/20250323085410.23751-1-meissner@suse.de +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/tests/shell/coresight/asm_pure_loop/asm_pure_loop.S | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tools/perf/tests/shell/coresight/asm_pure_loop/asm_pure_loop.S b/tools/perf/tests/shell/coresight/asm_pure_loop/asm_pure_loop.S +index 75cf084a927d3..5777600467723 100644 +--- a/tools/perf/tests/shell/coresight/asm_pure_loop/asm_pure_loop.S ++++ b/tools/perf/tests/shell/coresight/asm_pure_loop/asm_pure_loop.S +@@ -26,3 +26,5 @@ skip: + mov x0, #0 + mov x8, #93 // __NR_exit syscall + svc #0 ++ ++.section .note.GNU-stack, "", @progbits +-- +2.39.5 + diff --git a/queue-6.14/perf-tools-fix-is_compat_mode-build-break-in-ppc64.patch b/queue-6.14/perf-tools-fix-is_compat_mode-build-break-in-ppc64.patch new file mode 100644 index 0000000000..0ec53d6f38 --- /dev/null +++ b/queue-6.14/perf-tools-fix-is_compat_mode-build-break-in-ppc64.patch @@ -0,0 +1,58 @@ +From ff68b1da7dc501e2e6418bc2fe3eb829a8ac70ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 15:37:26 +0530 +Subject: perf tools: Fix is_compat_mode build break in ppc64 + +From: Likhitha Korrapati + +[ Upstream commit 7e442be7015af524d2b5fb84f0ff04a44501542b ] + +Commit 54f9aa1092457 ("tools/perf/powerpc/util: Add support to +handle compatible mode PVR for perf json events") introduced +to select proper JSON events in case of compat mode using +auxiliary vector. But this caused a compilation error in ppc64 +Big Endian. + +arch/powerpc/util/header.c: In function 'is_compat_mode': +arch/powerpc/util/header.c:20:21: error: cast to pointer from +integer of different size [-Werror=int-to-pointer-cast] + 20 | if (!strcmp((char *)platform, (char *)base_platform)) + | ^ +arch/powerpc/util/header.c:20:39: error: cast to pointer from +integer of different size [-Werror=int-to-pointer-cast] + 20 | if (!strcmp((char *)platform, (char *)base_platform)) + | + +Commit saved the getauxval(AT_BASE_PLATFORM) and getauxval(AT_PLATFORM) +return values in u64 which causes the compilation error. + +Patch fixes this issue by changing u64 to "unsigned long". + +Fixes: 54f9aa1092457 ("tools/perf/powerpc/util: Add support to handle compatible mode PVR for perf json events") +Signed-off-by: Likhitha Korrapati +Reviewed-by: Athira Rajeev +Link: https://lore.kernel.org/r/20250321100726.699956-1-likhitha@linux.ibm.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/arch/powerpc/util/header.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/arch/powerpc/util/header.c b/tools/perf/arch/powerpc/util/header.c +index c7df534dbf8f8..0be74f048f964 100644 +--- a/tools/perf/arch/powerpc/util/header.c ++++ b/tools/perf/arch/powerpc/util/header.c +@@ -14,8 +14,8 @@ + + static bool is_compat_mode(void) + { +- u64 base_platform = getauxval(AT_BASE_PLATFORM); +- u64 platform = getauxval(AT_PLATFORM); ++ unsigned long base_platform = getauxval(AT_BASE_PLATFORM); ++ unsigned long platform = getauxval(AT_PLATFORM); + + if (!strcmp((char *)platform, (char *)base_platform)) + return false; +-- +2.39.5 + diff --git a/queue-6.14/perf-units-fix-insufficient-array-space.patch b/queue-6.14/perf-units-fix-insufficient-array-space.patch new file mode 100644 index 0000000000..7108cdd0a9 --- /dev/null +++ b/queue-6.14/perf-units-fix-insufficient-array-space.patch @@ -0,0 +1,46 @@ +From 43e40bf3879ed6547a7f1df6982880534c044cba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 16:45:32 -0300 +Subject: perf units: Fix insufficient array space + +From: Arnaldo Carvalho de Melo + +[ Upstream commit cf67629f7f637fb988228abdb3aae46d0c1748fe ] + +No need to specify the array size, let the compiler figure that out. + +This addresses this compiler warning that was noticed while build +testing on fedora rawhide: + + 31 15.81 fedora:rawhide : FAIL gcc version 15.0.1 20250225 (Red Hat 15.0.1-0) (GCC) + util/units.c: In function 'unit_number__scnprintf': + util/units.c:67:24: error: initializer-string for array of 'char' is too long [-Werror=unterminated-string-initialization] + 67 | char unit[4] = "BKMG"; + | ^~~~~~ + cc1: all warnings being treated as errors + +Fixes: 9808143ba2e54818 ("perf tools: Add unit_number__scnprintf function") +Signed-off-by: Arnaldo Carvalho de Melo +Link: https://lore.kernel.org/r/20250310194534.265487-3-acme@kernel.org +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/util/units.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/units.c b/tools/perf/util/units.c +index 32c39cfe209b3..4c6a86e1cb54b 100644 +--- a/tools/perf/util/units.c ++++ b/tools/perf/util/units.c +@@ -64,7 +64,7 @@ unsigned long convert_unit(unsigned long value, char *unit) + + int unit_number__scnprintf(char *buf, size_t size, u64 n) + { +- char unit[4] = "BKMG"; ++ char unit[] = "BKMG"; + int i = 0; + + while (((n / 1024) > 1) && (i < 3)) { +-- +2.39.5 + diff --git a/queue-6.14/perf-vendor-events-arm64-ampereonex-fix-frontend_bou.patch b/queue-6.14/perf-vendor-events-arm64-ampereonex-fix-frontend_bou.patch new file mode 100644 index 0000000000..ac3a1543ba --- /dev/null +++ b/queue-6.14/perf-vendor-events-arm64-ampereonex-fix-frontend_bou.patch @@ -0,0 +1,63 @@ +From bb62e8214a26c458298e30e9d34ceace780b9c80 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 20:15:59 +0000 +Subject: perf vendor events arm64 AmpereOneX: Fix frontend_bound calculation + +From: Ilkka Koskinen + +[ Upstream commit 182f12f3193341c3400ae719a34c00a8a1204cff ] + +frontend_bound metrics was miscalculated due to different scaling in +a couple of metrics it depends on. Change the scaling to match with +AmpereOne. + +Fixes: 16438b652b46 ("perf vendor events arm64 AmpereOneX: Add core PMU events and metrics") +Signed-off-by: Ilkka Koskinen +Reviewed-by: James Clark +Link: https://lore.kernel.org/r/20250313201559.11332-3-ilkka@os.amperecomputing.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + .../arch/arm64/ampere/ampereonex/metrics.json | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/metrics.json b/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/metrics.json +index c5d1d22bd034b..5228f94a793f9 100644 +--- a/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/metrics.json ++++ b/tools/perf/pmu-events/arch/arm64/ampere/ampereonex/metrics.json +@@ -229,19 +229,19 @@ + }, + { + "MetricName": "slots_lost_misspeculation_fraction", +- "MetricExpr": "(OP_SPEC - OP_RETIRED) / (CPU_CYCLES * #slots)", ++ "MetricExpr": "100 * (OP_SPEC - OP_RETIRED) / (CPU_CYCLES * #slots)", + "BriefDescription": "Fraction of slots lost due to misspeculation", + "DefaultMetricgroupName": "TopdownL1", + "MetricGroup": "Default;TopdownL1", +- "ScaleUnit": "100percent of slots" ++ "ScaleUnit": "1percent of slots" + }, + { + "MetricName": "retired_fraction", +- "MetricExpr": "OP_RETIRED / (CPU_CYCLES * #slots)", ++ "MetricExpr": "100 * OP_RETIRED / (CPU_CYCLES * #slots)", + "BriefDescription": "Fraction of slots retiring, useful work", + "DefaultMetricgroupName": "TopdownL1", + "MetricGroup": "Default;TopdownL1", +- "ScaleUnit": "100percent of slots" ++ "ScaleUnit": "1percent of slots" + }, + { + "MetricName": "backend_core", +@@ -266,7 +266,7 @@ + }, + { + "MetricName": "frontend_bandwidth", +- "MetricExpr": "frontend_bound - frontend_latency", ++ "MetricExpr": "frontend_bound - 100 * frontend_latency", + "BriefDescription": "Fraction of slots the CPU did not dispatch at full bandwidth - able to dispatch partial slots only (1, 2, or 3 uops)", + "MetricGroup": "TopdownL2", + "ScaleUnit": "1percent of slots" +-- +2.39.5 + diff --git a/queue-6.14/perf-x86-lbr-fix-shorter-lbrs-call-stacks-for-the-sy.patch b/queue-6.14/perf-x86-lbr-fix-shorter-lbrs-call-stacks-for-the-sy.patch new file mode 100644 index 0000000000..b2e189233f --- /dev/null +++ b/queue-6.14/perf-x86-lbr-fix-shorter-lbrs-call-stacks-for-the-sy.patch @@ -0,0 +1,155 @@ +From 692127c5b9c2629d7125371b9699ef5805d4ecd6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 10:26:58 -0700 +Subject: perf/x86/lbr: Fix shorter LBRs call stacks for the system-wide mode + +From: Kan Liang + +[ Upstream commit 3cec9fd03543c1e2919f906353e5cba079ae0a7c ] + +In the system-wide mode, LBR callstacks are shorter in comparison to +the per-process mode. + +LBR MSRs are reset during a context switch in the system-wide mode. For +the LBR call stack, the LBRs should be always saved/restored during a +context switch. + +Use the space in task_struct to save/restore the LBR call stack data. + +For a system-wide event, it's unnecessagy to update the +lbr_callstack_users for each threads. Add a variable in x86_pmu to +indicate whether the system-wide event is active. + +Fixes: 76cb2c617f12 ("perf/x86/intel: Save/restore LBR stack during context switch") +Reported-by: Andi Kleen +Reported-by: Alexey Budankov +Debugged-by: Alexey Budankov +Signed-off-by: Kan Liang +Signed-off-by: Peter Zijlstra (Intel) +Link: https://lore.kernel.org/r/20250314172700.438923-5-kan.liang@linux.intel.com +Signed-off-by: Sasha Levin +--- + arch/x86/events/intel/lbr.c | 47 ++++++++++++++++++++++++++++++------ + arch/x86/events/perf_event.h | 1 + + 2 files changed, 40 insertions(+), 8 deletions(-) + +diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c +index dafeee216f3b6..24719adbcd7ea 100644 +--- a/arch/x86/events/intel/lbr.c ++++ b/arch/x86/events/intel/lbr.c +@@ -422,11 +422,17 @@ static __always_inline bool lbr_is_reset_in_cstate(void *ctx) + return !rdlbr_from(((struct x86_perf_task_context *)ctx)->tos, NULL); + } + ++static inline bool has_lbr_callstack_users(void *ctx) ++{ ++ return task_context_opt(ctx)->lbr_callstack_users || ++ x86_pmu.lbr_callstack_users; ++} ++ + static void __intel_pmu_lbr_restore(void *ctx) + { + struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); + +- if (task_context_opt(ctx)->lbr_callstack_users == 0 || ++ if (!has_lbr_callstack_users(ctx) || + task_context_opt(ctx)->lbr_stack_state == LBR_NONE) { + intel_pmu_lbr_reset(); + return; +@@ -503,7 +509,7 @@ static void __intel_pmu_lbr_save(void *ctx) + { + struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); + +- if (task_context_opt(ctx)->lbr_callstack_users == 0) { ++ if (!has_lbr_callstack_users(ctx)) { + task_context_opt(ctx)->lbr_stack_state = LBR_NONE; + return; + } +@@ -543,6 +549,7 @@ void intel_pmu_lbr_sched_task(struct perf_event_pmu_context *pmu_ctx, + struct task_struct *task, bool sched_in) + { + struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); ++ struct perf_ctx_data *ctx_data; + void *task_ctx; + + if (!cpuc->lbr_users) +@@ -553,14 +560,18 @@ void intel_pmu_lbr_sched_task(struct perf_event_pmu_context *pmu_ctx, + * the task was scheduled out, restore the stack. Otherwise flush + * the LBR stack. + */ +- task_ctx = pmu_ctx ? pmu_ctx->task_ctx_data : NULL; ++ rcu_read_lock(); ++ ctx_data = rcu_dereference(task->perf_ctx_data); ++ task_ctx = ctx_data ? ctx_data->data : NULL; + if (task_ctx) { + if (sched_in) + __intel_pmu_lbr_restore(task_ctx); + else + __intel_pmu_lbr_save(task_ctx); ++ rcu_read_unlock(); + return; + } ++ rcu_read_unlock(); + + /* + * Since a context switch can flip the address space and LBR entries +@@ -589,9 +600,19 @@ void intel_pmu_lbr_add(struct perf_event *event) + + cpuc->br_sel = event->hw.branch_reg.reg; + +- if (branch_user_callstack(cpuc->br_sel) && event->pmu_ctx->task_ctx_data) +- task_context_opt(event->pmu_ctx->task_ctx_data)->lbr_callstack_users++; ++ if (branch_user_callstack(cpuc->br_sel)) { ++ if (event->attach_state & PERF_ATTACH_TASK) { ++ struct task_struct *task = event->hw.target; ++ struct perf_ctx_data *ctx_data; + ++ rcu_read_lock(); ++ ctx_data = rcu_dereference(task->perf_ctx_data); ++ if (ctx_data) ++ task_context_opt(ctx_data->data)->lbr_callstack_users++; ++ rcu_read_unlock(); ++ } else ++ x86_pmu.lbr_callstack_users++; ++ } + /* + * Request pmu::sched_task() callback, which will fire inside the + * regular perf event scheduling, so that call will: +@@ -665,9 +686,19 @@ void intel_pmu_lbr_del(struct perf_event *event) + if (!x86_pmu.lbr_nr) + return; + +- if (branch_user_callstack(cpuc->br_sel) && +- event->pmu_ctx->task_ctx_data) +- task_context_opt(event->pmu_ctx->task_ctx_data)->lbr_callstack_users--; ++ if (branch_user_callstack(cpuc->br_sel)) { ++ if (event->attach_state & PERF_ATTACH_TASK) { ++ struct task_struct *task = event->hw.target; ++ struct perf_ctx_data *ctx_data; ++ ++ rcu_read_lock(); ++ ctx_data = rcu_dereference(task->perf_ctx_data); ++ if (ctx_data) ++ task_context_opt(ctx_data->data)->lbr_callstack_users--; ++ rcu_read_unlock(); ++ } else ++ x86_pmu.lbr_callstack_users--; ++ } + + if (event->hw.flags & PERF_X86_EVENT_LBR_SELECT) + cpuc->lbr_select = 0; +diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h +index ce7c98364d5b6..b93b526d6834a 100644 +--- a/arch/x86/events/perf_event.h ++++ b/arch/x86/events/perf_event.h +@@ -914,6 +914,7 @@ struct x86_pmu { + const int *lbr_sel_map; /* lbr_select mappings */ + int *lbr_ctl_map; /* LBR_CTL mappings */ + }; ++ u64 lbr_callstack_users; /* lbr callstack system wide users */ + bool lbr_double_abort; /* duplicated lbr aborts */ + bool lbr_pt_coexist; /* (LBR|BTS) may coexist with PT */ + +-- +2.39.5 + diff --git a/queue-6.14/perf-x86-topdown-fix-topdown-leader-sampling-test-er.patch b/queue-6.14/perf-x86-topdown-fix-topdown-leader-sampling-test-er.patch new file mode 100644 index 0000000000..7ccb484bb7 --- /dev/null +++ b/queue-6.14/perf-x86-topdown-fix-topdown-leader-sampling-test-er.patch @@ -0,0 +1,67 @@ +From a66f487c03c9b51c68fde8791b6413139a6dc337 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 18:39:03 -0800 +Subject: perf x86/topdown: Fix topdown leader sampling test error on hybrid + +From: Dapeng Mi + +[ Upstream commit b74683b3bb224eccb644cf260753dfc82e802d92 ] + +When running topdown leader smapling test on Intel hybrid platforms, +such as LNL/ARL, we see the below error. + +Topdown leader sampling test +Topdown leader sampling [Failed topdown events not reordered correctly] + +It indciates the below command fails. + +perf record -o "${perfdata}" -e "{instructions,slots,topdown-retiring}:S" true + +The root cause is that perf tool creats a perf event for each PMU type +if it can create. + +As for this command, there would be 5 perf events created, +cpu_atom/instructions/,cpu_atom/topdown_retiring/, +cpu_core/slots/,cpu_core/instructions/,cpu_core/topdown-retiring/ + +For these 5 events, the 2 cpu_atom events are in a group and the other 3 +cpu_core events are in another group. + +When arch_topdown_sample_read() traverses all these 5 events, events +cpu_atom/instructions/ and cpu_core/slots/ don't have a same group +leade, and then return false directly and lead to cpu_core/slots/ event +is used to sample and this is not allowed by PMU driver. + +It's a overkill to return false directly if "evsel->core.leader != + leader->core.leader" since there could be multiple groups in the event +list. + +Just "continue" instead of "return false" to fix this issue. + +Fixes: 1e53e9d1787b ("perf x86/topdown: Correct leader selection with sample_read enabled") +Signed-off-by: Dapeng Mi +Tested-by: Thomas Falcon +Tested-by: Ian Rogers +Link: https://lore.kernel.org/r/20250307023906.1135613-2-irogers@google.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/perf/arch/x86/util/topdown.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/arch/x86/util/topdown.c b/tools/perf/arch/x86/util/topdown.c +index f63747d0abdf9..d1c6548390496 100644 +--- a/tools/perf/arch/x86/util/topdown.c ++++ b/tools/perf/arch/x86/util/topdown.c +@@ -81,7 +81,7 @@ bool arch_topdown_sample_read(struct evsel *leader) + */ + evlist__for_each_entry(leader->evlist, evsel) { + if (evsel->core.leader != leader->core.leader) +- return false; ++ continue; + if (evsel != leader && arch_is_topdown_metrics(evsel)) + return true; + } +-- +2.39.5 + diff --git a/queue-6.14/phy-phy-rockchip-samsung-hdptx-don-t-use-dt-aliases-.patch b/queue-6.14/phy-phy-rockchip-samsung-hdptx-don-t-use-dt-aliases-.patch new file mode 100644 index 0000000000..fc8bbaad22 --- /dev/null +++ b/queue-6.14/phy-phy-rockchip-samsung-hdptx-don-t-use-dt-aliases-.patch @@ -0,0 +1,139 @@ +From dabbb791dc54d49db1010f63fd15443122bcbd91 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 6 Dec 2024 11:34:01 +0100 +Subject: phy: phy-rockchip-samsung-hdptx: Don't use dt aliases to determine + phy-id + +From: Heiko Stuebner + +[ Upstream commit f08d1c08563846f9be79a4859e912c8795d690fd ] + +The phy needs to know its identity in the system (phy0 or phy1 on rk3588) +for some actions and the driver currently contains code abusing of_alias +for that. + +Devicetree aliases are always optional and should not be used for core +device functionality, so instead keep a list of phys on a soc in the +of_device_data and find the phy-id by comparing against the mapped +register-base. + +Fixes: c4b09c562086 ("phy: phy-rockchip-samsung-hdptx: Add clock provider support") +Signed-off-by: Heiko Stuebner +Reviewed-by: Cristian Ciocaltea +Reviewed-by: Sebastian Reichel +Link: https://lore.kernel.org/r/20241206103401.1780416-3-heiko@sntech.de +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + .../phy/rockchip/phy-rockchip-samsung-hdptx.c | 50 ++++++++++++++++--- + 1 file changed, 44 insertions(+), 6 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +index 0965b9d4f9cf1..2fb4f297fda3d 100644 +--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c ++++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +@@ -263,11 +263,22 @@ enum rk_hdptx_reset { + RST_MAX + }; + ++#define MAX_HDPTX_PHY_NUM 2 ++ ++struct rk_hdptx_phy_cfg { ++ unsigned int num_phys; ++ unsigned int phy_ids[MAX_HDPTX_PHY_NUM]; ++}; ++ + struct rk_hdptx_phy { + struct device *dev; + struct regmap *regmap; + struct regmap *grf; + ++ /* PHY const config */ ++ const struct rk_hdptx_phy_cfg *cfgs; ++ int phy_id; ++ + struct phy *phy; + struct phy_config *phy_cfg; + struct clk_bulk_data *clks; +@@ -1007,15 +1018,14 @@ static int rk_hdptx_phy_clk_register(struct rk_hdptx_phy *hdptx) + struct device *dev = hdptx->dev; + const char *name, *pname; + struct clk *refclk; +- int ret, id; ++ int ret; + + refclk = devm_clk_get(dev, "ref"); + if (IS_ERR(refclk)) + return dev_err_probe(dev, PTR_ERR(refclk), + "Failed to get ref clock\n"); + +- id = of_alias_get_id(dev->of_node, "hdptxphy"); +- name = id > 0 ? "clk_hdmiphy_pixel1" : "clk_hdmiphy_pixel0"; ++ name = hdptx->phy_id > 0 ? "clk_hdmiphy_pixel1" : "clk_hdmiphy_pixel0"; + pname = __clk_get_name(refclk); + + hdptx->hw.init = CLK_HW_INIT(name, pname, &hdptx_phy_clk_ops, +@@ -1058,8 +1068,9 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev) + struct phy_provider *phy_provider; + struct device *dev = &pdev->dev; + struct rk_hdptx_phy *hdptx; ++ struct resource *res; + void __iomem *regs; +- int ret; ++ int ret, id; + + hdptx = devm_kzalloc(dev, sizeof(*hdptx), GFP_KERNEL); + if (!hdptx) +@@ -1067,11 +1078,27 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev) + + hdptx->dev = dev; + +- regs = devm_platform_ioremap_resource(pdev, 0); ++ regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(regs)) + return dev_err_probe(dev, PTR_ERR(regs), + "Failed to ioremap resource\n"); + ++ hdptx->cfgs = device_get_match_data(dev); ++ if (!hdptx->cfgs) ++ return dev_err_probe(dev, -EINVAL, "missing match data\n"); ++ ++ /* find the phy-id from the io address */ ++ hdptx->phy_id = -ENODEV; ++ for (id = 0; id < hdptx->cfgs->num_phys; id++) { ++ if (res->start == hdptx->cfgs->phy_ids[id]) { ++ hdptx->phy_id = id; ++ break; ++ } ++ } ++ ++ if (hdptx->phy_id < 0) ++ return dev_err_probe(dev, -ENODEV, "no matching device found\n"); ++ + ret = devm_clk_bulk_get_all(dev, &hdptx->clks); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to get clocks\n"); +@@ -1132,8 +1159,19 @@ static const struct dev_pm_ops rk_hdptx_phy_pm_ops = { + rk_hdptx_phy_runtime_resume, NULL) + }; + ++static const struct rk_hdptx_phy_cfg rk3588_hdptx_phy_cfgs = { ++ .num_phys = 2, ++ .phy_ids = { ++ 0xfed60000, ++ 0xfed70000, ++ }, ++}; ++ + static const struct of_device_id rk_hdptx_phy_of_match[] = { +- { .compatible = "rockchip,rk3588-hdptx-phy", }, ++ { ++ .compatible = "rockchip,rk3588-hdptx-phy", ++ .data = &rk3588_hdptx_phy_cfgs ++ }, + {} + }; + MODULE_DEVICE_TABLE(of, rk_hdptx_phy_of_match); +-- +2.39.5 + diff --git a/queue-6.14/pinctrl-bcm2835-don-t-einval-on-alternate-funcs-from.patch b/queue-6.14/pinctrl-bcm2835-don-t-einval-on-alternate-funcs-from.patch new file mode 100644 index 0000000000..42e1344d46 --- /dev/null +++ b/queue-6.14/pinctrl-bcm2835-don-t-einval-on-alternate-funcs-from.patch @@ -0,0 +1,61 @@ +From 224a68176909cb4e8228bcb0c2ab2e0d65ed8df5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 11:27:50 +0100 +Subject: pinctrl: bcm2835: don't -EINVAL on alternate funcs from + get_direction() + +From: Bartosz Golaszewski + +[ Upstream commit 75f87f5d04f73645136d7a603c331d844fc5704a ] + +Since commit 9d846b1aebbe ("gpiolib: check the return value of +gpio_chip::get_direction()") we check the return value of the +get_direction() callback as per its API contract. This driver returns +-EINVAL if the pin in question is set to one of the alternative +(non-GPIO) functions. This isn't really an error that should be +communicated to GPIOLIB so default to returning the "safe" value of +INPUT in this case. The GPIO subsystem does not have the notion of +"unknown" direction. + +Fixes: 9d846b1aebbe ("gpiolib: check the return value of gpio_chip::get_direction()") +Reported-by: Mark Brown +Closes: https://lore.kernel.org/all/Z7VFB1nST6lbmBIo@finisterre.sirena.org.uk/ +Signed-off-by: Bartosz Golaszewski +Tested-by: Marek Szyprowski +Reviewed-by: Stefan Wahren +Link: https://lore.kernel.org/20250219102750.38519-1-brgl@bgdev.pl +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/bcm/pinctrl-bcm2835.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c +index cc1fe0555e196..eaeec096bc9a9 100644 +--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c ++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c +@@ -346,14 +346,14 @@ static int bcm2835_gpio_get_direction(struct gpio_chip *chip, unsigned int offse + struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); + enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset); + +- /* Alternative function doesn't clearly provide a direction */ +- if (fsel > BCM2835_FSEL_GPIO_OUT) +- return -EINVAL; +- +- if (fsel == BCM2835_FSEL_GPIO_IN) +- return GPIO_LINE_DIRECTION_IN; ++ if (fsel == BCM2835_FSEL_GPIO_OUT) ++ return GPIO_LINE_DIRECTION_OUT; + +- return GPIO_LINE_DIRECTION_OUT; ++ /* ++ * Alternative function doesn't clearly provide a direction. Default ++ * to INPUT. ++ */ ++ return GPIO_LINE_DIRECTION_IN; + } + + static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +-- +2.39.5 + diff --git a/queue-6.14/pinctrl-intel-fix-wrong-bypass-assignment-in-intel_p.patch b/queue-6.14/pinctrl-intel-fix-wrong-bypass-assignment-in-intel_p.patch new file mode 100644 index 0000000000..1c535a0c30 --- /dev/null +++ b/queue-6.14/pinctrl-intel-fix-wrong-bypass-assignment-in-intel_p.patch @@ -0,0 +1,39 @@ +From 4d05af4c9d23e52e5469ff58242f5849ce46e43b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 21:44:51 +0200 +Subject: pinctrl: intel: Fix wrong bypass assignment in + intel_pinctrl_probe_pwm() + +From: Andy Shevchenko + +[ Upstream commit 0eee258cdf172763502f142d85e967f27a573be0 ] + +When instantiating PWM, the bypass should be set to false. The field +is used for the selected Intel SoCs that do not have PWM feature enabled +in their pin control IPs. + +Fixes: eb78d3604d6b ("pinctrl: intel: Enumerate PWM device when community has a capability") +Reported-by: Alexis GUILLEMET +Signed-off-by: Andy Shevchenko +Reviewed-by: Mika Westerberg +Tested-by: Alexis GUILLEMET +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/intel/pinctrl-intel.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c +index 527e4b87ae52e..f8b0221055e4a 100644 +--- a/drivers/pinctrl/intel/pinctrl-intel.c ++++ b/drivers/pinctrl/intel/pinctrl-intel.c +@@ -1543,7 +1543,6 @@ static int intel_pinctrl_probe_pwm(struct intel_pinctrl *pctrl, + .clk_rate = 19200000, + .npwm = 1, + .base_unit_bits = 22, +- .bypass = true, + }; + struct pwm_chip *chip; + +-- +2.39.5 + diff --git a/queue-6.14/pinctrl-npcm8xx-fix-incorrect-struct-npcm8xx_pincfg-.patch b/queue-6.14/pinctrl-npcm8xx-fix-incorrect-struct-npcm8xx_pincfg-.patch new file mode 100644 index 0000000000..1917a35ac4 --- /dev/null +++ b/queue-6.14/pinctrl-npcm8xx-fix-incorrect-struct-npcm8xx_pincfg-.patch @@ -0,0 +1,57 @@ +From 953d1178bcd80d1f59f4d348877ff865d599796e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 12:57:14 +0200 +Subject: pinctrl: npcm8xx: Fix incorrect struct npcm8xx_pincfg assignment + +From: Andy Shevchenko + +[ Upstream commit 113ec87b0f26a17b02c58aa2714a9b8f1020eed9 ] + +Sparse is not happy about implementation of the NPCM8XX_PINCFG() + + pinctrl-npcm8xx.c:1314:9: warning: obsolete array initializer, use C99 syntax + pinctrl-npcm8xx.c:1315:9: warning: obsolete array initializer, use C99 syntax + ... + pinctrl-npcm8xx.c:1412:9: warning: obsolete array initializer, use C99 syntax + pinctrl-npcm8xx.c:1413:9: warning: too many warnings + +which uses index-based assignment in a wrong way, i.e. it missed +the equal sign and hence the index is simply ignored, while the +entries are indexed naturally. This is not a problem as the pin +numbering repeats the natural order, but it might be in case of +shuffling the entries. Fix this by adding missed equal sign and +reformat a bit for better readability. + +Fixes: acf4884a5717 ("pinctrl: nuvoton: add NPCM8XX pinctrl and GPIO driver") +Signed-off-by: Andy Shevchenko +Link: https://lore.kernel.org/20250318105932.2090926-2-andriy.shevchenko@linux.intel.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c +index 17825bbe14213..f6a1e684a3864 100644 +--- a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c ++++ b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c +@@ -1290,12 +1290,14 @@ static struct npcm8xx_func npcm8xx_funcs[] = { + }; + + #define NPCM8XX_PINCFG(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) \ +- [a] { .fn0 = fn_ ## b, .reg0 = NPCM8XX_GCR_ ## c, .bit0 = d, \ ++ [a] = { \ ++ .flag = q, \ ++ .fn0 = fn_ ## b, .reg0 = NPCM8XX_GCR_ ## c, .bit0 = d, \ + .fn1 = fn_ ## e, .reg1 = NPCM8XX_GCR_ ## f, .bit1 = g, \ + .fn2 = fn_ ## h, .reg2 = NPCM8XX_GCR_ ## i, .bit2 = j, \ + .fn3 = fn_ ## k, .reg3 = NPCM8XX_GCR_ ## l, .bit3 = m, \ + .fn4 = fn_ ## n, .reg4 = NPCM8XX_GCR_ ## o, .bit4 = p, \ +- .flag = q } ++ } + + /* Drive strength controlled by NPCM8XX_GP_N_ODSC */ + #define DRIVE_STRENGTH_LO_SHIFT 8 +-- +2.39.5 + diff --git a/queue-6.14/pinctrl-nuvoton-npcm8xx-fix-error-handling-in-npcm8x.patch b/queue-6.14/pinctrl-nuvoton-npcm8xx-fix-error-handling-in-npcm8x.patch new file mode 100644 index 0000000000..422aeb4dee --- /dev/null +++ b/queue-6.14/pinctrl-nuvoton-npcm8xx-fix-error-handling-in-npcm8x.patch @@ -0,0 +1,39 @@ +From 31b47361065b2ccc885b59256e97061423ded14a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 18 Jan 2025 11:13:34 +0800 +Subject: pinctrl: nuvoton: npcm8xx: Fix error handling in npcm8xx_gpio_fw() + +From: Yue Haibing + +[ Upstream commit d6c6fd77e5816e3f6689a2767cdd777797506f24 ] + +fwnode_irq_get() was changed to not return 0, fix this by checking +for negative error, also update the error log. + +Fixes: acf4884a5717 ("pinctrl: nuvoton: add NPCM8XX pinctrl and GPIO driver") +Signed-off-by: Yue Haibing +Link: https://lore.kernel.org/20250118031334.243324-1-yuehaibing@huawei.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c +index d09a5e9b2eca5..17825bbe14213 100644 +--- a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c ++++ b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c +@@ -2361,8 +2361,8 @@ static int npcm8xx_gpio_fw(struct npcm8xx_pinctrl *pctrl) + return dev_err_probe(dev, ret, "gpio-ranges fail for GPIO bank %u\n", id); + + ret = fwnode_irq_get(child, 0); +- if (!ret) +- return dev_err_probe(dev, ret, "No IRQ for GPIO bank %u\n", id); ++ if (ret < 0) ++ return dev_err_probe(dev, ret, "Failed to retrieve IRQ for bank %u\n", id); + + pctrl->gpio_bank[id].irq = ret; + pctrl->gpio_bank[id].irq_chip = npcmgpio_irqchip; +-- +2.39.5 + diff --git a/queue-6.14/pinctrl-renesas-rza2-fix-missing-of_node_put-call.patch b/queue-6.14/pinctrl-renesas-rza2-fix-missing-of_node_put-call.patch new file mode 100644 index 0000000000..316935d6ce --- /dev/null +++ b/queue-6.14/pinctrl-renesas-rza2-fix-missing-of_node_put-call.patch @@ -0,0 +1,42 @@ +From df9283bcbb6baf5eedf9c0a4ee6ad379faa76bfc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 16:37:53 +0000 +Subject: pinctrl: renesas: rza2: Fix missing of_node_put() call + +From: Fabrizio Castro + +[ Upstream commit abcdeb4e299a11ecb5a3ea0cce00e68e8f540375 ] + +of_parse_phandle_with_fixed_args() requires its caller to +call into of_node_put() on the node pointer from the output +structure, but such a call is currently missing. + +Call into of_node_put() to rectify that. + +Fixes: b59d0e782706 ("pinctrl: Add RZ/A2 pin and gpio controller") +Signed-off-by: Fabrizio Castro +Reviewed-by: Lad Prabhakar +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/20250305163753.34913-5-fabrizio.castro.jz@renesas.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/renesas/pinctrl-rza2.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/pinctrl/renesas/pinctrl-rza2.c b/drivers/pinctrl/renesas/pinctrl-rza2.c +index dd1f8c29d3e75..8b36161c7c502 100644 +--- a/drivers/pinctrl/renesas/pinctrl-rza2.c ++++ b/drivers/pinctrl/renesas/pinctrl-rza2.c +@@ -256,6 +256,8 @@ static int rza2_gpio_register(struct rza2_pinctrl_priv *priv) + return ret; + } + ++ of_node_put(of_args.np); ++ + if ((of_args.args[0] != 0) || + (of_args.args[1] != 0) || + (of_args.args[2] != priv->npins)) { +-- +2.39.5 + diff --git a/queue-6.14/pinctrl-renesas-rzg2l-fix-missing-of_node_put-call.patch b/queue-6.14/pinctrl-renesas-rzg2l-fix-missing-of_node_put-call.patch new file mode 100644 index 0000000000..479be04b8b --- /dev/null +++ b/queue-6.14/pinctrl-renesas-rzg2l-fix-missing-of_node_put-call.patch @@ -0,0 +1,42 @@ +From 6065eeb07b0354500c7333ba5114f90a3b57c1e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 16:37:51 +0000 +Subject: pinctrl: renesas: rzg2l: Fix missing of_node_put() call + +From: Fabrizio Castro + +[ Upstream commit a5779e625e2b377f16a6675c432aaf299ce5028c ] + +of_parse_phandle_with_fixed_args() requires its caller to +call into of_node_put() on the node pointer from the output +structure, but such a call is currently missing. + +Call into of_node_put() to rectify that. + +Fixes: c4c4637eb57f ("pinctrl: renesas: Add RZ/G2L pin and gpio controller driver") +Signed-off-by: Fabrizio Castro +Reviewed-by: Lad Prabhakar +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/20250305163753.34913-3-fabrizio.castro.jz@renesas.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/renesas/pinctrl-rzg2l.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +index 5f006a059d9c2..d1da7f53fc600 100644 +--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c ++++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +@@ -2756,6 +2756,8 @@ static int rzg2l_gpio_register(struct rzg2l_pinctrl *pctrl) + if (ret) + return dev_err_probe(pctrl->dev, ret, "Unable to parse gpio-ranges\n"); + ++ of_node_put(of_args.np); ++ + if (of_args.args[0] != 0 || of_args.args[1] != 0 || + of_args.args[2] != pctrl->data->n_port_pins) + return dev_err_probe(pctrl->dev, -EINVAL, +-- +2.39.5 + diff --git a/queue-6.14/pinctrl-renesas-rzg2l-suppress-binding-attributes.patch b/queue-6.14/pinctrl-renesas-rzg2l-suppress-binding-attributes.patch new file mode 100644 index 0000000000..9cbcd040b5 --- /dev/null +++ b/queue-6.14/pinctrl-renesas-rzg2l-suppress-binding-attributes.patch @@ -0,0 +1,40 @@ +From 15939d967b711d8033e83418d3b365390c15ebb6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Feb 2025 15:12:35 +0200 +Subject: pinctrl: renesas: rzg2l: Suppress binding attributes + +From: Claudiu Beznea + +[ Upstream commit ea4065345643f3163e812e58ed8add2c75c3ee46 ] + +Suppress binding attributes for the rzg2l pinctrl driver, as it is an +essential block for Renesas SoCs. Unbinding the driver leads to +warnings from __device_links_no_driver() and can eventually render the +system inaccessible. + +Fixes: c4c4637eb57f ("pinctrl: renesas: Add RZ/G2L pin and gpio controller driver") +Signed-off-by: Claudiu Beznea +Reviewed-by: Lad Prabhakar +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/20250215131235.228274-1-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/renesas/pinctrl-rzg2l.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +index ce4a07a3df49a..5f006a059d9c2 100644 +--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c ++++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +@@ -3386,6 +3386,7 @@ static struct platform_driver rzg2l_pinctrl_driver = { + .name = DRV_NAME, + .of_match_table = of_match_ptr(rzg2l_pinctrl_of_table), + .pm = pm_sleep_ptr(&rzg2l_pinctrl_pm_ops), ++ .suppress_bind_attrs = true, + }, + .probe = rzg2l_pinctrl_probe, + }; +-- +2.39.5 + diff --git a/queue-6.14/pinctrl-renesas-rzv2m-fix-missing-of_node_put-call.patch b/queue-6.14/pinctrl-renesas-rzv2m-fix-missing-of_node_put-call.patch new file mode 100644 index 0000000000..be1ec33038 --- /dev/null +++ b/queue-6.14/pinctrl-renesas-rzv2m-fix-missing-of_node_put-call.patch @@ -0,0 +1,42 @@ +From 29756efaee1f9d817bdcbcbbd0d5266f3429317d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 16:37:52 +0000 +Subject: pinctrl: renesas: rzv2m: Fix missing of_node_put() call + +From: Fabrizio Castro + +[ Upstream commit 5a550b00704d3a2cd9d766a9427b0f8166da37df ] + +of_parse_phandle_with_fixed_args() requires its caller to +call into of_node_put() on the node pointer from the output +structure, but such a call is currently missing. + +Call into of_node_put() to rectify that. + +Fixes: 92a9b8252576 ("pinctrl: renesas: Add RZ/V2M pin and gpio controller driver") +Signed-off-by: Fabrizio Castro +Reviewed-by: Lad Prabhakar +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/20250305163753.34913-4-fabrizio.castro.jz@renesas.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/renesas/pinctrl-rzv2m.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/pinctrl/renesas/pinctrl-rzv2m.c b/drivers/pinctrl/renesas/pinctrl-rzv2m.c +index 4062c56619f59..8c7169db4fcce 100644 +--- a/drivers/pinctrl/renesas/pinctrl-rzv2m.c ++++ b/drivers/pinctrl/renesas/pinctrl-rzv2m.c +@@ -940,6 +940,8 @@ static int rzv2m_gpio_register(struct rzv2m_pinctrl *pctrl) + return ret; + } + ++ of_node_put(of_args.np); ++ + if (of_args.args[0] != 0 || of_args.args[1] != 0 || + of_args.args[2] != pctrl->data->n_port_pins) { + dev_err(pctrl->dev, "gpio-ranges does not match selected SOC\n"); +-- +2.39.5 + diff --git a/queue-6.14/pinctrl-tegra-set-sfio-mode-to-mux-register.patch b/queue-6.14/pinctrl-tegra-set-sfio-mode-to-mux-register.patch new file mode 100644 index 0000000000..63505b376f --- /dev/null +++ b/queue-6.14/pinctrl-tegra-set-sfio-mode-to-mux-register.patch @@ -0,0 +1,49 @@ +From 791469d26f64adeef96b9be300fca7a4d46496f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 10:35:42 +0530 +Subject: pinctrl: tegra: Set SFIO mode to Mux Register + +From: Prathamesh Shete + +[ Upstream commit 17013f0acb322e5052ff9b9d0fab0ab5a4bfd828 ] + +Tegra devices have an 'sfsel' bit field that determines whether a pin +operates in SFIO (Special Function I/O) or GPIO mode. Currently, +tegra_pinctrl_gpio_disable_free() sets this bit when releasing a GPIO. + +However, tegra_pinctrl_set_mux() can be called independently in certain +code paths where gpio_disable_free() is not invoked. In such cases, failing +to set the SFIO mode could lead to incorrect pin configurations, resulting +in functional issues for peripherals relying on SFIO. + +This patch ensures that whenever set_mux() is called, the SFIO mode is +correctly set in the Mux Register if the 'sfsel' bit is present. This +prevents situations where the pin remains in GPIO mode despite being +configured for SFIO use. + +Fixes: 971dac7123c7 ("pinctrl: add a driver for NVIDIA Tegra") +Signed-off-by: Prathamesh Shete +Link: https://lore.kernel.org/20250306050542.16335-1-pshete@nvidia.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/tegra/pinctrl-tegra.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c +index c83e5a65e6801..3b046450bd3ff 100644 +--- a/drivers/pinctrl/tegra/pinctrl-tegra.c ++++ b/drivers/pinctrl/tegra/pinctrl-tegra.c +@@ -270,6 +270,9 @@ static int tegra_pinctrl_set_mux(struct pinctrl_dev *pctldev, + val = pmx_readl(pmx, g->mux_bank, g->mux_reg); + val &= ~(0x3 << g->mux_bit); + val |= i << g->mux_bit; ++ /* Set the SFIO/GPIO selection to SFIO when under pinmux control*/ ++ if (pmx->soc->sfsel_in_mux) ++ val |= (1 << g->sfsel_bit); + pmx_writel(pmx, val, g->mux_bank, g->mux_reg); + + return 0; +-- +2.39.5 + diff --git a/queue-6.14/platform-x86-dell-ddv-fix-temperature-calculation.patch b/queue-6.14/platform-x86-dell-ddv-fix-temperature-calculation.patch new file mode 100644 index 0000000000..34a84ec4e4 --- /dev/null +++ b/queue-6.14/platform-x86-dell-ddv-fix-temperature-calculation.patch @@ -0,0 +1,50 @@ +From 27c30ccdc047966851d9fedc2f73a024b418b0b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 06:30:07 +0100 +Subject: platform/x86: dell-ddv: Fix temperature calculation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Armin Wolf + +[ Upstream commit 7a248294a3145bc65eb0d8980a0a8edbb1b92db4 ] + +On the Dell Inspiron 3505 the battery temperature is always +0.1 degrees larger than the temperature show inside the OEM +application. + +Emulate this behaviour to avoid showing strange looking values +like 29.1 degrees. + +Fixes: 0331b1b0ba653 ("platform/x86: dell-ddv: Fix temperature scaling") +Signed-off-by: Armin Wolf +Reviewed-by: Sebastian Reichel +Link: https://lore.kernel.org/r/20250305053009.378609-2-W_Armin@gmx.de +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/dell/dell-wmi-ddv.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/platform/x86/dell/dell-wmi-ddv.c b/drivers/platform/x86/dell/dell-wmi-ddv.c +index e75cd6e1efe6a..ab5f7d3ab8249 100644 +--- a/drivers/platform/x86/dell/dell-wmi-ddv.c ++++ b/drivers/platform/x86/dell/dell-wmi-ddv.c +@@ -665,8 +665,10 @@ static ssize_t temp_show(struct device *dev, struct device_attribute *attr, char + if (ret < 0) + return ret; + +- /* Use 2731 instead of 2731.5 to avoid unnecessary rounding */ +- return sysfs_emit(buf, "%d\n", value - 2731); ++ /* Use 2732 instead of 2731.5 to avoid unnecessary rounding and to emulate ++ * the behaviour of the OEM application which seems to round down the result. ++ */ ++ return sysfs_emit(buf, "%d\n", value - 2732); + } + + static ssize_t eppid_show(struct device *dev, struct device_attribute *attr, char *buf) +-- +2.39.5 + diff --git a/queue-6.14/platform-x86-dell-uart-backlight-make-dell_uart_bl_s.patch b/queue-6.14/platform-x86-dell-uart-backlight-make-dell_uart_bl_s.patch new file mode 100644 index 0000000000..0d823e34a9 --- /dev/null +++ b/queue-6.14/platform-x86-dell-uart-backlight-make-dell_uart_bl_s.patch @@ -0,0 +1,47 @@ +From 6a818e2c31843e5685d357b022ddd2497ee5a34e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 18:06:39 +0200 +Subject: platform/x86: dell-uart-backlight: Make dell_uart_bl_serdev_driver + static +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit 4878e0b14c3e31a87ab147bd2dae443394cb5a2c ] + +Sparse reports: + +dell-uart-backlight.c:328:29: warning: symbol +'dell_uart_bl_serdev_driver' was not declared. Should it be static? + +Fix it by making the symbol static. + +Fixes: 484bae9e4d6ac ("platform/x86: Add new Dell UART backlight driver") +Reviewed-by: Mario Limonciello +Reviewed-by: Hans de Goede +Link: https://lore.kernel.org/r/20250304160639.4295-2-ilpo.jarvinen@linux.intel.com +Signed-off-by: Ilpo Järvinen +Reviewed-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/dell/dell-uart-backlight.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/dell/dell-uart-backlight.c b/drivers/platform/x86/dell/dell-uart-backlight.c +index 50002ef13d5d4..8f868f845350a 100644 +--- a/drivers/platform/x86/dell/dell-uart-backlight.c ++++ b/drivers/platform/x86/dell/dell-uart-backlight.c +@@ -325,7 +325,7 @@ static int dell_uart_bl_serdev_probe(struct serdev_device *serdev) + return PTR_ERR_OR_ZERO(dell_bl->bl); + } + +-struct serdev_device_driver dell_uart_bl_serdev_driver = { ++static struct serdev_device_driver dell_uart_bl_serdev_driver = { + .probe = dell_uart_bl_serdev_probe, + .driver = { + .name = KBUILD_MODNAME, +-- +2.39.5 + diff --git a/queue-6.14/platform-x86-lenovo-yoga-tab2-pro-1380-fastcharger-m.patch b/queue-6.14/platform-x86-lenovo-yoga-tab2-pro-1380-fastcharger-m.patch new file mode 100644 index 0000000000..14ec0fa804 --- /dev/null +++ b/queue-6.14/platform-x86-lenovo-yoga-tab2-pro-1380-fastcharger-m.patch @@ -0,0 +1,47 @@ +From 7af41486776275a0d49a6822ea94c2631b120f62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 18:06:38 +0200 +Subject: platform/x86: lenovo-yoga-tab2-pro-1380-fastcharger: Make symbol + static +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit 886ca11a0c70efe5627a18557062e8a44370d78f ] + +Sparse reports: + +lenovo-yoga-tab2-pro-1380-fastcharger.c:222:29: warning: symbol +'yt2_1380_fc_serdev_driver' was not declared. Should it be static? + +Fix that by making the symbol static. + +Fixes: b2ed33e8d486a ("platform/x86: Add lenovo-yoga-tab2-pro-1380-fastcharger driver") +Reviewed-by: Mario Limonciello +Reviewed-by: Hans de Goede +Link: https://lore.kernel.org/r/20250304160639.4295-1-ilpo.jarvinen@linux.intel.com +Signed-off-by: Ilpo Järvinen +Reviewed-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/lenovo-yoga-tab2-pro-1380-fastcharger.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/lenovo-yoga-tab2-pro-1380-fastcharger.c b/drivers/platform/x86/lenovo-yoga-tab2-pro-1380-fastcharger.c +index a96b215cd2c5e..25933cd018d17 100644 +--- a/drivers/platform/x86/lenovo-yoga-tab2-pro-1380-fastcharger.c ++++ b/drivers/platform/x86/lenovo-yoga-tab2-pro-1380-fastcharger.c +@@ -219,7 +219,7 @@ static int yt2_1380_fc_serdev_probe(struct serdev_device *serdev) + return 0; + } + +-struct serdev_device_driver yt2_1380_fc_serdev_driver = { ++static struct serdev_device_driver yt2_1380_fc_serdev_driver = { + .probe = yt2_1380_fc_serdev_probe, + .driver = { + .name = KBUILD_MODNAME, +-- +2.39.5 + diff --git a/queue-6.14/pm-sleep-adjust-check-before-setting-power.must_resu.patch b/queue-6.14/pm-sleep-adjust-check-before-setting-power.must_resu.patch new file mode 100644 index 0000000000..0bf1283b0b --- /dev/null +++ b/queue-6.14/pm-sleep-adjust-check-before-setting-power.must_resu.patch @@ -0,0 +1,86 @@ +From a64c5e409591be70a98621518124c0e8c15f1b11 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 11:53:50 +0100 +Subject: PM: sleep: Adjust check before setting power.must_resume + +From: Rafael J. Wysocki + +[ Upstream commit eeb87d17aceab7803a5a5bcb6cf2817b745157cf ] + +The check before setting power.must_resume in device_suspend_noirq() +does not take power.child_count into account, but it should do that, so +use pm_runtime_need_not_resume() in it for this purpose and adjust the +comment next to it accordingly. + +Fixes: 107d47b2b95e ("PM: sleep: core: Simplify the SMART_SUSPEND flag handling") +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Ulf Hansson +Link: https://patch.msgid.link/3353728.44csPzL39Z@rjwysocki.net +Signed-off-by: Sasha Levin +--- + drivers/base/power/main.c | 13 ++++++------- + drivers/base/power/runtime.c | 2 +- + include/linux/pm_runtime.h | 2 ++ + 3 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c +index 40e1d8d8a5893..5afafd4e13dff 100644 +--- a/drivers/base/power/main.c ++++ b/drivers/base/power/main.c +@@ -1270,14 +1270,13 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state, bool asy + dev->power.is_noirq_suspended = true; + + /* +- * Skipping the resume of devices that were in use right before the +- * system suspend (as indicated by their PM-runtime usage counters) +- * would be suboptimal. Also resume them if doing that is not allowed +- * to be skipped. ++ * Devices must be resumed unless they are explicitly allowed to be left ++ * in suspend, but even in that case skipping the resume of devices that ++ * were in use right before the system suspend (as indicated by their ++ * runtime PM usage counters and child counters) would be suboptimal. + */ +- if (atomic_read(&dev->power.usage_count) > 1 || +- !(dev_pm_test_driver_flags(dev, DPM_FLAG_MAY_SKIP_RESUME) && +- dev->power.may_skip_resume)) ++ if (!(dev_pm_test_driver_flags(dev, DPM_FLAG_MAY_SKIP_RESUME) && ++ dev->power.may_skip_resume) || !pm_runtime_need_not_resume(dev)) + dev->power.must_resume = true; + + if (dev->power.must_resume) { +diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c +index 2ee45841486bc..04113adb092b5 100644 +--- a/drivers/base/power/runtime.c ++++ b/drivers/base/power/runtime.c +@@ -1874,7 +1874,7 @@ void pm_runtime_drop_link(struct device_link *link) + pm_request_idle(link->supplier); + } + +-static bool pm_runtime_need_not_resume(struct device *dev) ++bool pm_runtime_need_not_resume(struct device *dev) + { + return atomic_read(&dev->power.usage_count) <= 1 && + (atomic_read(&dev->power.child_count) == 0 || +diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h +index d39dc863f612f..d0b29cd1fd204 100644 +--- a/include/linux/pm_runtime.h ++++ b/include/linux/pm_runtime.h +@@ -66,6 +66,7 @@ static inline bool queue_pm_work(struct work_struct *work) + + extern int pm_generic_runtime_suspend(struct device *dev); + extern int pm_generic_runtime_resume(struct device *dev); ++extern bool pm_runtime_need_not_resume(struct device *dev); + extern int pm_runtime_force_suspend(struct device *dev); + extern int pm_runtime_force_resume(struct device *dev); + +@@ -241,6 +242,7 @@ static inline bool queue_pm_work(struct work_struct *work) { return false; } + + static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; } + static inline int pm_generic_runtime_resume(struct device *dev) { return 0; } ++static inline bool pm_runtime_need_not_resume(struct device *dev) {return true; } + static inline int pm_runtime_force_suspend(struct device *dev) { return 0; } + static inline int pm_runtime_force_resume(struct device *dev) { return 0; } + +-- +2.39.5 + diff --git a/queue-6.14/pm-sleep-fix-handling-devices-with-direct_complete-s.patch b/queue-6.14/pm-sleep-fix-handling-devices-with-direct_complete-s.patch new file mode 100644 index 0000000000..6a3301db43 --- /dev/null +++ b/queue-6.14/pm-sleep-fix-handling-devices-with-direct_complete-s.patch @@ -0,0 +1,91 @@ +From 34c9fb2182dbd19c496ba1a0247274f4388480cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 17:00:00 +0100 +Subject: PM: sleep: Fix handling devices with direct_complete set on errors + +From: Rafael J. Wysocki + +[ Upstream commit 03f1444016b71feffa1dfb8a51f15ba592f94b13 ] + +When dpm_suspend() fails, some devices with power.direct_complete set +may not have been handled by device_suspend() yet, so runtime PM has +not been disabled for them yet even though power.direct_complete is set. + +Since device_resume() expects that runtime PM has been disabled for all +devices with power.direct_complete set, it will attempt to reenable +runtime PM for the devices that have not been processed by device_suspend() +which does not make sense. Had those devices had runtime PM disabled +before device_suspend() had run, device_resume() would have inadvertently +enable runtime PM for them, but this is not expected to happen because +it would require ->prepare() callbacks to return positive values for +devices with runtime PM disabled, which would be invalid. + +In practice, this issue is most likely benign because pm_runtime_enable() +will not allow the "disable depth" counter to underflow, but it causes a +warning message to be printed for each affected device. + +To allow device_resume() to distinguish the "direct complete" devices +that have been processed by device_suspend() from those which have not +been handled by it, make device_suspend() set power.is_suspended for +"direct complete" devices. + +Next, move the power.is_suspended check in device_resume() before the +power.direct_complete check in it to make it skip the "direct complete" +devices that have not been handled by device_suspend(). + +This change is based on a preliminary patch from Saravana Kannan. + +Fixes: aae4518b3124 ("PM / sleep: Mechanism to avoid resuming runtime-suspended devices unnecessarily") +Link: https://lore.kernel.org/linux-pm/20241114220921.2529905-2-saravanak@google.com/ +Reported-by: Saravana Kannan +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Saravana Kannan +Link: https://patch.msgid.link/12627587.O9o76ZdvQC@rjwysocki.net +Signed-off-by: Sasha Levin +--- + drivers/base/power/main.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c +index 5afafd4e13dff..23be2d1b04079 100644 +--- a/drivers/base/power/main.c ++++ b/drivers/base/power/main.c +@@ -929,6 +929,9 @@ static void device_resume(struct device *dev, pm_message_t state, bool async) + if (dev->power.syscore) + goto Complete; + ++ if (!dev->power.is_suspended) ++ goto Complete; ++ + if (dev->power.direct_complete) { + /* Match the pm_runtime_disable() in device_suspend(). */ + pm_runtime_enable(dev); +@@ -947,9 +950,6 @@ static void device_resume(struct device *dev, pm_message_t state, bool async) + */ + dev->power.is_prepared = false; + +- if (!dev->power.is_suspended) +- goto Unlock; +- + if (dev->pm_domain) { + info = "power domain "; + callback = pm_op(&dev->pm_domain->ops, state); +@@ -989,7 +989,6 @@ static void device_resume(struct device *dev, pm_message_t state, bool async) + error = dpm_run_callback(callback, dev, state, info); + dev->power.is_suspended = false; + +- Unlock: + device_unlock(dev); + dpm_watchdog_clear(&wd); + +@@ -1649,6 +1648,7 @@ static int device_suspend(struct device *dev, pm_message_t state, bool async) + pm_runtime_disable(dev); + if (pm_runtime_status_suspended(dev)) { + pm_dev_dbg(dev, state, "direct-complete "); ++ dev->power.is_suspended = true; + goto Complete; + } + +-- +2.39.5 + diff --git a/queue-6.14/power-supply-bq27xxx_battery-do-not-update-cached-fl.patch b/queue-6.14/power-supply-bq27xxx_battery-do-not-update-cached-fl.patch new file mode 100644 index 0000000000..4e699ce914 --- /dev/null +++ b/queue-6.14/power-supply-bq27xxx_battery-do-not-update-cached-fl.patch @@ -0,0 +1,40 @@ +From a992418cbebd06ce81c51c47a9a89deeee8c4b5b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Nov 2024 17:29:30 +0200 +Subject: power: supply: bq27xxx_battery: do not update cached flags + prematurely + +From: Sicelo A. Mhlongo + +[ Upstream commit 45291874a762dbb12a619dc2efaf84598859007a ] + +Commit 243f8ffc883a1 ("power: supply: bq27xxx_battery: Notify also about +status changes") intended to notify userspace when the status changes, +based on the flags register. However, the cached state is updated too +early, before the flags are tested for any changes. Remove the premature +update. + +Fixes: 243f8ffc883a1 ("power: supply: bq27xxx_battery: Notify also about status changes") +Signed-off-by: Sicelo A. Mhlongo +Link: https://lore.kernel.org/r/20241125152945.47937-1-absicsz@gmail.com +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + drivers/power/supply/bq27xxx_battery.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c +index 90a5bccfc6b9b..a8d8bcaace2f0 100644 +--- a/drivers/power/supply/bq27xxx_battery.c ++++ b/drivers/power/supply/bq27xxx_battery.c +@@ -1918,7 +1918,6 @@ static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di) + cache.flags = -1; /* read error */ + if (cache.flags >= 0) { + cache.capacity = bq27xxx_battery_read_soc(di); +- di->cache.flags = cache.flags; + + /* + * On gauges with signed current reporting the current must be +-- +2.39.5 + diff --git a/queue-6.14/power-supply-max77693-fix-wrong-conversion-of-charge.patch b/queue-6.14/power-supply-max77693-fix-wrong-conversion-of-charge.patch new file mode 100644 index 0000000000..0ce8dd874b --- /dev/null +++ b/queue-6.14/power-supply-max77693-fix-wrong-conversion-of-charge.patch @@ -0,0 +1,46 @@ +From f23da0295e496ac89aef07543c1258d2ae4ecc72 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Mar 2025 21:11:49 +0100 +Subject: power: supply: max77693: Fix wrong conversion of charge input + threshold value + +From: Artur Weber + +[ Upstream commit 30cc7b0d0e9341d419eb7da15fb5c22406dbe499 ] + +The charge input threshold voltage register on the MAX77693 PMIC accepts +four values: 0x0 for 4.3v, 0x1 for 4.7v, 0x2 for 4.8v and 0x3 for 4.9v. +Due to an oversight, the driver calculated the values for 4.7v and above +starting from 0x0, rather than from 0x1 ([(4700000 - 4700000) / 100000] +gives 0). + +Add 1 to the calculation to ensure that 4.7v is converted to a register +value of 0x1 and that the other two voltages are converted correctly as +well. + +Fixes: 87c2d9067893 ("power: max77693: Add charger driver for Maxim 77693") +Signed-off-by: Artur Weber +Reviewed-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20250316-max77693-charger-input-threshold-fix-v1-1-2b037d0ac722@gmail.com +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + drivers/power/supply/max77693_charger.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/power/supply/max77693_charger.c b/drivers/power/supply/max77693_charger.c +index cdea35c0d1de1..027d6a539b65a 100644 +--- a/drivers/power/supply/max77693_charger.c ++++ b/drivers/power/supply/max77693_charger.c +@@ -608,7 +608,7 @@ static int max77693_set_charge_input_threshold_volt(struct max77693_charger *chg + case 4700000: + case 4800000: + case 4900000: +- data = (uvolt - 4700000) / 100000; ++ data = ((uvolt - 4700000) / 100000) + 1; + break; + default: + dev_err(chg->dev, "Wrong value for charge input voltage regulation threshold\n"); +-- +2.39.5 + diff --git a/queue-6.14/powerpc-kexec-fix-physical-address-calculation-in-cl.patch b/queue-6.14/powerpc-kexec-fix-physical-address-calculation-in-cl.patch new file mode 100644 index 0000000000..73b3ba046a --- /dev/null +++ b/queue-6.14/powerpc-kexec-fix-physical-address-calculation-in-cl.patch @@ -0,0 +1,57 @@ +From 979f84138c447176a33b160396b59361c8dee4db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 11:24:28 +0100 +Subject: powerpc/kexec: fix physical address calculation in clear_utlb_entry() + +From: Christophe Leroy + +[ Upstream commit 861efb8a48ee8b73ae4e8817509cd4e82fd52bc4 ] + +In relocate_32.S, function clear_utlb_entry() goes into real mode. To +do so, it has to calculate the physical address based on the virtual +address. To get the virtual address it uses 'bl' which is problematic +(see commit c974809a26a1 ("powerpc/vdso: Avoid link stack corruption +in __get_datapage()")). In addition, the calculation is done on a +wrong address because 'bl' loads LR with the address of the following +instruction, not the address of the target. So when the target is not +the instruction following the 'bl' instruction, it may lead to +unexpected behaviour. + +Fix it by re-writing the code so that is goes via another path which +is based 'bcl 20,31,.+4' which is the right instruction to use for that. + +Fixes: 683430200315 ("powerpc/47x: Kernel support for KEXEC") +Signed-off-by: Christophe Leroy +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/dc4f9616fba9c05c5dbf9b4b5480eb1c362adc17.1741256651.git.christophe.leroy@csgroup.eu +Signed-off-by: Sasha Levin +--- + arch/powerpc/kexec/relocate_32.S | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/arch/powerpc/kexec/relocate_32.S b/arch/powerpc/kexec/relocate_32.S +index 104c9911f4061..dd86e338307d3 100644 +--- a/arch/powerpc/kexec/relocate_32.S ++++ b/arch/powerpc/kexec/relocate_32.S +@@ -348,16 +348,13 @@ write_utlb: + rlwinm r10, r24, 0, 22, 27 + + cmpwi r10, PPC47x_TLB0_4K +- bne 0f + li r10, 0x1000 /* r10 = 4k */ +- ANNOTATE_INTRA_FUNCTION_CALL +- bl 1f ++ beq 0f + +-0: + /* Defaults to 256M */ + lis r10, 0x1000 + +- bcl 20,31,$+4 ++0: bcl 20,31,$+4 + 1: mflr r4 + addi r4, r4, (2f-1b) /* virtual address of 2f */ + +-- +2.39.5 + diff --git a/queue-6.14/powerpc-perf-fix-ref-counting-on-the-pmu-vpa_pmu.patch b/queue-6.14/powerpc-perf-fix-ref-counting-on-the-pmu-vpa_pmu.patch new file mode 100644 index 0000000000..12ab6e4f5c --- /dev/null +++ b/queue-6.14/powerpc-perf-fix-ref-counting-on-the-pmu-vpa_pmu.patch @@ -0,0 +1,57 @@ +From f3b59f412cb78f06db160ca90d5ef85220c82a99 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 21:05:26 +0530 +Subject: powerpc/perf: Fix ref-counting on the PMU 'vpa_pmu' + +From: Vaibhav Jain + +[ Upstream commit ff99d5b6a246715f2257123cdf6c4a29cb33aa78 ] + +Commit 176cda0619b6 ("powerpc/perf: Add perf interface to expose vpa +counters") introduced 'vpa_pmu' to expose Book3s-HV nested APIv2 provided +L1<->L2 context switch latency counters to L1 user-space via +perf-events. However the newly introduced PMU named 'vpa_pmu' doesn't +assign ownership of the PMU to the module 'vpa_pmu'. Consequently the +module 'vpa_pmu' can be unloaded while one of the perf-events are still +active, which can lead to kernel oops and panic of the form below on a +Pseries-LPAR: + +BUG: Kernel NULL pointer dereference on read at 0x00000058 + + NIP [c000000000506cb8] event_sched_out+0x40/0x258 + LR [c00000000050e8a4] __perf_remove_from_context+0x7c/0x2b0 + Call Trace: + [c00000025fc3fc30] [c00000025f8457a8] 0xc00000025f8457a8 (unreliable) + [c00000025fc3fc80] [fffffffffffffee0] 0xfffffffffffffee0 + [c00000025fc3fcd0] [c000000000501e70] event_function+0xa8/0x120 + + Kernel panic - not syncing: Aiee, killing interrupt handler! + +Fix this by adding the module ownership to 'vpa_pmu' so that the module +'vpa_pmu' is ref-counted and prevented from being unloaded when perf-events +are initialized. + +Fixes: 176cda0619b6 ("powerpc/perf: Add perf interface to expose vpa counters") +Signed-off-by: Vaibhav Jain +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250204153527.125491-1-vaibhav@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/perf/vpa-pmu.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/powerpc/perf/vpa-pmu.c b/arch/powerpc/perf/vpa-pmu.c +index 6a5bfd2a13b5a..8407334689596 100644 +--- a/arch/powerpc/perf/vpa-pmu.c ++++ b/arch/powerpc/perf/vpa-pmu.c +@@ -156,6 +156,7 @@ static void vpa_pmu_del(struct perf_event *event, int flags) + } + + static struct pmu vpa_pmu = { ++ .module = THIS_MODULE, + .task_ctx_nr = perf_sw_context, + .name = "vpa_pmu", + .event_init = vpa_pmu_event_init, +-- +2.39.5 + diff --git a/queue-6.14/ptp-ocp-reject-unsupported-periodic-output-flags.patch b/queue-6.14/ptp-ocp-reject-unsupported-periodic-output-flags.patch new file mode 100644 index 0000000000..f523ae76ba --- /dev/null +++ b/queue-6.14/ptp-ocp-reject-unsupported-periodic-output-flags.patch @@ -0,0 +1,45 @@ +From 431089d4d0c3adc64a74b288fc2f18443309cf33 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 15:15:54 -0700 +Subject: ptp: ocp: reject unsupported periodic output flags + +From: Jacob Keller + +[ Upstream commit 8dcfc910a81d8b53f59f8b23211e81f2a91f84f9 ] + +The ptp_ocp_signal_from_perout() function supports PTP_PEROUT_DUTY_CYCLE +and PTP_PEROUT_PHASE. It does not support PTP_PEROUT_ONE_SHOT, but does not +reject a request with such an unsupported flag. + +Add the appropriate check to ensure that unsupported requests are rejected +both for PTP_PEROUT_ONE_SHOT as well as any future flags. + +Fixes: 1aa66a3a135a ("ptp: ocp: Program the signal generators via PTP_CLK_REQ_PEROUT") +Reviewed-by: Vadim Fedorenko +Signed-off-by: Jacob Keller +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250312-jk-net-fixes-supported-extts-flags-v2-5-ea930ba82459@intel.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/ptp/ptp_ocp.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c +index b651087f426f5..4a87af0980d69 100644 +--- a/drivers/ptp/ptp_ocp.c ++++ b/drivers/ptp/ptp_ocp.c +@@ -2090,6 +2090,10 @@ ptp_ocp_signal_from_perout(struct ptp_ocp *bp, int gen, + { + struct ptp_ocp_signal s = { }; + ++ if (req->flags & ~(PTP_PEROUT_DUTY_CYCLE | ++ PTP_PEROUT_PHASE)) ++ return -EOPNOTSUPP; ++ + s.polarity = bp->signal[gen].polarity; + s.period = ktime_set(req->period.sec, req->period.nsec); + if (!s.period) +-- +2.39.5 + diff --git a/queue-6.14/rcu-tasks-always-inline-rcu_irq_work_resched.patch b/queue-6.14/rcu-tasks-always-inline-rcu_irq_work_resched.patch new file mode 100644 index 0000000000..60009876fd --- /dev/null +++ b/queue-6.14/rcu-tasks-always-inline-rcu_irq_work_resched.patch @@ -0,0 +1,43 @@ +From f2e38fa21e2fbf989fcf8bb48c891ff542489d6b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Mar 2025 21:26:46 -0700 +Subject: rcu-tasks: Always inline rcu_irq_work_resched() + +From: Josh Poimboeuf + +[ Upstream commit 6309a5c43b0dc629851f25b2e5ef8beff61d08e5 ] + +Thanks to CONFIG_DEBUG_SECTION_MISMATCH, empty functions can be +generated out of line. rcu_irq_work_resched() can be called from +noinstr code, so make sure it's always inlined. + +Fixes: 564506495ca9 ("rcu/context-tracking: Move deferred nocb resched to context tracking") +Reported-by: Randy Dunlap +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Cc: Frederic Weisbecker +Cc: Paul E. McKenney +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/e84f15f013c07e4c410d972e75620c53b62c1b3e.1743481539.git.jpoimboe@kernel.org +Closes: https://lore.kernel.org/d1eca076-fdde-484a-b33e-70e0d167c36d@infradead.org +Signed-off-by: Sasha Levin +--- + include/linux/rcupdate.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h +index 48e5c03df1dd8..bd69ddc102fbc 100644 +--- a/include/linux/rcupdate.h ++++ b/include/linux/rcupdate.h +@@ -138,7 +138,7 @@ static inline void rcu_sysrq_end(void) { } + #if defined(CONFIG_NO_HZ_FULL) && (!defined(CONFIG_GENERIC_ENTRY) || !defined(CONFIG_KVM_XFER_TO_GUEST_WORK)) + void rcu_irq_work_resched(void); + #else +-static inline void rcu_irq_work_resched(void) { } ++static __always_inline void rcu_irq_work_resched(void) { } + #endif + + #ifdef CONFIG_RCU_NOCB_CPU +-- +2.39.5 + diff --git a/queue-6.14/rdma-core-don-t-expose-hw_counters-outside-of-init-n.patch b/queue-6.14/rdma-core-don-t-expose-hw_counters-outside-of-init-n.patch new file mode 100644 index 0000000000..58adc3123f --- /dev/null +++ b/queue-6.14/rdma-core-don-t-expose-hw_counters-outside-of-init-n.patch @@ -0,0 +1,150 @@ +From 94cfd22b952acb3a5d82dec13480544310331a46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 16:54:20 +0000 +Subject: RDMA/core: Don't expose hw_counters outside of init net namespace + +From: Roman Gushchin + +[ Upstream commit a1ecb30f90856b0be4168ad51b8875148e285c1f ] + +Commit 467f432a521a ("RDMA/core: Split port and device counter sysfs +attributes") accidentally almost exposed hw counters to non-init net +namespaces. It didn't expose them fully, as an attempt to read any of +those counters leads to a crash like this one: + +[42021.807566] BUG: kernel NULL pointer dereference, address: 0000000000000028 +[42021.814463] #PF: supervisor read access in kernel mode +[42021.819549] #PF: error_code(0x0000) - not-present page +[42021.824636] PGD 0 P4D 0 +[42021.827145] Oops: 0000 [#1] SMP PTI +[42021.830598] CPU: 82 PID: 2843922 Comm: switchto-defaul Kdump: loaded Tainted: G S W I XXX +[42021.841697] Hardware name: XXX +[42021.849619] RIP: 0010:hw_stat_device_show+0x1e/0x40 [ib_core] +[42021.855362] Code: 90 90 90 90 90 90 90 90 90 90 90 90 f3 0f 1e fa 0f 1f 44 00 00 49 89 d0 4c 8b 5e 20 48 8b 8f b8 04 00 00 48 81 c7 f0 fa ff ff <48> 8b 41 28 48 29 ce 48 83 c6 d0 48 c1 ee 04 69 d6 ab aa aa aa 48 +[42021.873931] RSP: 0018:ffff97fe90f03da0 EFLAGS: 00010287 +[42021.879108] RAX: ffff9406988a8c60 RBX: ffff940e1072d438 RCX: 0000000000000000 +[42021.886169] RDX: ffff94085f1aa000 RSI: ffff93c6cbbdbcb0 RDI: ffff940c7517aef0 +[42021.893230] RBP: ffff97fe90f03e70 R08: ffff94085f1aa000 R09: 0000000000000000 +[42021.900294] R10: ffff94085f1aa000 R11: ffffffffc0775680 R12: ffffffff87ca2530 +[42021.907355] R13: ffff940651602840 R14: ffff93c6cbbdbcb0 R15: ffff94085f1aa000 +[42021.914418] FS: 00007fda1a3b9700(0000) GS:ffff94453fb80000(0000) knlGS:0000000000000000 +[42021.922423] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[42021.928130] CR2: 0000000000000028 CR3: 00000042dcfb8003 CR4: 00000000003726f0 +[42021.935194] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[42021.942257] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +[42021.949324] Call Trace: +[42021.951756] +[42021.953842] [] ? show_regs+0x64/0x70 +[42021.959030] [] ? __die+0x78/0xc0 +[42021.963874] [] ? page_fault_oops+0x2b5/0x3b0 +[42021.969749] [] ? exc_page_fault+0x1a2/0x3c0 +[42021.975549] [] ? asm_exc_page_fault+0x26/0x30 +[42021.981517] [] ? __pfx_show_hw_stats+0x10/0x10 [ib_core] +[42021.988482] [] ? hw_stat_device_show+0x1e/0x40 [ib_core] +[42021.995438] [] dev_attr_show+0x1e/0x50 +[42022.000803] [] sysfs_kf_seq_show+0x81/0xe0 +[42022.006508] [] seq_read_iter+0xf4/0x410 +[42022.011954] [] vfs_read+0x16e/0x2f0 +[42022.017058] [] ksys_read+0x6e/0xe0 +[42022.022073] [] do_syscall_64+0x6a/0xa0 +[42022.027441] [] entry_SYSCALL_64_after_hwframe+0x78/0xe2 + +The problem can be reproduced using the following steps: + ip netns add foo + ip netns exec foo bash + cat /sys/class/infiniband/mlx4_0/hw_counters/* + +The panic occurs because of casting the device pointer into an +ib_device pointer using container_of() in hw_stat_device_show() is +wrong and leads to a memory corruption. + +However the real problem is that hw counters should never been exposed +outside of the non-init net namespace. + +Fix this by saving the index of the corresponding attribute group +(it might be 1 or 2 depending on the presence of driver-specific +attributes) and zeroing the pointer to hw_counters group for compat +devices during the initialization. + +With this fix applied hw_counters are not available in a non-init +net namespace: + find /sys/class/infiniband/mlx4_0/ -name hw_counters + /sys/class/infiniband/mlx4_0/ports/1/hw_counters + /sys/class/infiniband/mlx4_0/ports/2/hw_counters + /sys/class/infiniband/mlx4_0/hw_counters + + ip netns add foo + ip netns exec foo bash + find /sys/class/infiniband/mlx4_0/ -name hw_counters + +Fixes: 467f432a521a ("RDMA/core: Split port and device counter sysfs attributes") +Signed-off-by: Roman Gushchin +Cc: Jason Gunthorpe +Cc: Leon Romanovsky +Cc: Maher Sanalla +Cc: linux-rdma@vger.kernel.org +Cc: linux-kernel@vger.kernel.org +Link: https://patch.msgid.link/20250227165420.3430301-1-roman.gushchin@linux.dev +Reviewed-by: Parav Pandit +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/device.c | 9 +++++++++ + drivers/infiniband/core/sysfs.c | 1 + + include/rdma/ib_verbs.h | 1 + + 3 files changed, 11 insertions(+) + +diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c +index 0ded91f056f39..8feb22089cbbd 100644 +--- a/drivers/infiniband/core/device.c ++++ b/drivers/infiniband/core/device.c +@@ -528,6 +528,8 @@ static struct class ib_class = { + static void rdma_init_coredev(struct ib_core_device *coredev, + struct ib_device *dev, struct net *net) + { ++ bool is_full_dev = &dev->coredev == coredev; ++ + /* This BUILD_BUG_ON is intended to catch layout change + * of union of ib_core_device and device. + * dev must be the first element as ib_core and providers +@@ -539,6 +541,13 @@ static void rdma_init_coredev(struct ib_core_device *coredev, + + coredev->dev.class = &ib_class; + coredev->dev.groups = dev->groups; ++ ++ /* ++ * Don't expose hw counters outside of the init namespace. ++ */ ++ if (!is_full_dev && dev->hw_stats_attr_index) ++ coredev->dev.groups[dev->hw_stats_attr_index] = NULL; ++ + device_initialize(&coredev->dev); + coredev->owner = dev; + INIT_LIST_HEAD(&coredev->port_list); +diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c +index 9f97bef021497..210092b9bf17d 100644 +--- a/drivers/infiniband/core/sysfs.c ++++ b/drivers/infiniband/core/sysfs.c +@@ -988,6 +988,7 @@ int ib_setup_device_attrs(struct ib_device *ibdev) + for (i = 0; i != ARRAY_SIZE(ibdev->groups); i++) + if (!ibdev->groups[i]) { + ibdev->groups[i] = &data->group; ++ ibdev->hw_stats_attr_index = i; + return 0; + } + WARN(true, "struct ib_device->groups is too small"); +diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h +index 0ad104dae2539..43954bb0475a7 100644 +--- a/include/rdma/ib_verbs.h ++++ b/include/rdma/ib_verbs.h +@@ -2750,6 +2750,7 @@ struct ib_device { + * It is a NULL terminated array. + */ + const struct attribute_group *groups[4]; ++ u8 hw_stats_attr_index; + + u64 uverbs_cmd_mask; + +-- +2.39.5 + diff --git a/queue-6.14/rdma-core-fix-use-after-free-when-rename-device-name.patch b/queue-6.14/rdma-core-fix-use-after-free-when-rename-device-name.patch new file mode 100644 index 0000000000..a16fb698d3 --- /dev/null +++ b/queue-6.14/rdma-core-fix-use-after-free-when-rename-device-name.patch @@ -0,0 +1,171 @@ +From 2d3c44a14de54530688bc77574ae3d88d73a26c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 17:24:21 +0800 +Subject: RDMA/core: Fix use-after-free when rename device name + +From: Wang Liang + +[ Upstream commit 1d6a9e7449e2a0c1e2934eee7880ba8bd1e464cd ] + +Syzbot reported a slab-use-after-free with the following call trace: + +================================================================== +BUG: KASAN: slab-use-after-free in nla_put+0xd3/0x150 lib/nlattr.c:1099 +Read of size 5 at addr ffff888140ea1c60 by task syz.0.988/10025 + +CPU: 0 UID: 0 PID: 10025 Comm: syz.0.988 +Not tainted 6.14.0-rc4-syzkaller-00859-gf77f12010f67 #0 +Hardware name: Google Compute Engine, BIOS Google 02/12/2025 +Call Trace: + + __dump_stack lib/dump_stack.c:94 [inline] + dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:408 [inline] + print_report+0x16e/0x5b0 mm/kasan/report.c:521 + kasan_report+0x143/0x180 mm/kasan/report.c:634 + kasan_check_range+0x282/0x290 mm/kasan/generic.c:189 + __asan_memcpy+0x29/0x70 mm/kasan/shadow.c:105 + nla_put+0xd3/0x150 lib/nlattr.c:1099 + nla_put_string include/net/netlink.h:1621 [inline] + fill_nldev_handle+0x16e/0x200 drivers/infiniband/core/nldev.c:265 + rdma_nl_notify_event+0x561/0xef0 drivers/infiniband/core/nldev.c:2857 + ib_device_notify_register+0x22/0x230 drivers/infiniband/core/device.c:1344 + ib_register_device+0x1292/0x1460 drivers/infiniband/core/device.c:1460 + rxe_register_device+0x233/0x350 drivers/infiniband/sw/rxe/rxe_verbs.c:1540 + rxe_net_add+0x74/0xf0 drivers/infiniband/sw/rxe/rxe_net.c:550 + rxe_newlink+0xde/0x1a0 drivers/infiniband/sw/rxe/rxe.c:212 + nldev_newlink+0x5ea/0x680 drivers/infiniband/core/nldev.c:1795 + rdma_nl_rcv_skb drivers/infiniband/core/netlink.c:239 [inline] + rdma_nl_rcv+0x6dd/0x9e0 drivers/infiniband/core/netlink.c:259 + netlink_unicast_kernel net/netlink/af_netlink.c:1313 [inline] + netlink_unicast+0x7f6/0x990 net/netlink/af_netlink.c:1339 + netlink_sendmsg+0x8de/0xcb0 net/netlink/af_netlink.c:1883 + sock_sendmsg_nosec net/socket.c:709 [inline] + __sock_sendmsg+0x221/0x270 net/socket.c:724 + ____sys_sendmsg+0x53a/0x860 net/socket.c:2564 + ___sys_sendmsg net/socket.c:2618 [inline] + __sys_sendmsg+0x269/0x350 net/socket.c:2650 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f +RIP: 0033:0x7f42d1b8d169 +Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 ... +RSP: 002b:00007f42d2960038 EFLAGS: 00000246 ORIG_RAX: 000000000000002e +RAX: ffffffffffffffda RBX: 00007f42d1da6320 RCX: 00007f42d1b8d169 +RDX: 0000000000000000 RSI: 00004000000002c0 RDI: 000000000000000c +RBP: 00007f42d1c0e2a0 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 +R13: 0000000000000000 R14: 00007f42d1da6320 R15: 00007ffe399344a8 + + +Allocated by task 10025: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3f/0x80 mm/kasan/common.c:68 + poison_kmalloc_redzone mm/kasan/common.c:377 [inline] + __kasan_kmalloc+0x98/0xb0 mm/kasan/common.c:394 + kasan_kmalloc include/linux/kasan.h:260 [inline] + __do_kmalloc_node mm/slub.c:4294 [inline] + __kmalloc_node_track_caller_noprof+0x28b/0x4c0 mm/slub.c:4313 + __kmemdup_nul mm/util.c:61 [inline] + kstrdup+0x42/0x100 mm/util.c:81 + kobject_set_name_vargs+0x61/0x120 lib/kobject.c:274 + dev_set_name+0xd5/0x120 drivers/base/core.c:3468 + assign_name drivers/infiniband/core/device.c:1202 [inline] + ib_register_device+0x178/0x1460 drivers/infiniband/core/device.c:1384 + rxe_register_device+0x233/0x350 drivers/infiniband/sw/rxe/rxe_verbs.c:1540 + rxe_net_add+0x74/0xf0 drivers/infiniband/sw/rxe/rxe_net.c:550 + rxe_newlink+0xde/0x1a0 drivers/infiniband/sw/rxe/rxe.c:212 + nldev_newlink+0x5ea/0x680 drivers/infiniband/core/nldev.c:1795 + rdma_nl_rcv_skb drivers/infiniband/core/netlink.c:239 [inline] + rdma_nl_rcv+0x6dd/0x9e0 drivers/infiniband/core/netlink.c:259 + netlink_unicast_kernel net/netlink/af_netlink.c:1313 [inline] + netlink_unicast+0x7f6/0x990 net/netlink/af_netlink.c:1339 + netlink_sendmsg+0x8de/0xcb0 net/netlink/af_netlink.c:1883 + sock_sendmsg_nosec net/socket.c:709 [inline] + __sock_sendmsg+0x221/0x270 net/socket.c:724 + ____sys_sendmsg+0x53a/0x860 net/socket.c:2564 + ___sys_sendmsg net/socket.c:2618 [inline] + __sys_sendmsg+0x269/0x350 net/socket.c:2650 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Freed by task 10035: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3f/0x80 mm/kasan/common.c:68 + kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:576 + poison_slab_object mm/kasan/common.c:247 [inline] + __kasan_slab_free+0x59/0x70 mm/kasan/common.c:264 + kasan_slab_free include/linux/kasan.h:233 [inline] + slab_free_hook mm/slub.c:2353 [inline] + slab_free mm/slub.c:4609 [inline] + kfree+0x196/0x430 mm/slub.c:4757 + kobject_rename+0x38f/0x410 lib/kobject.c:524 + device_rename+0x16a/0x200 drivers/base/core.c:4525 + ib_device_rename+0x270/0x710 drivers/infiniband/core/device.c:402 + nldev_set_doit+0x30e/0x4c0 drivers/infiniband/core/nldev.c:1146 + rdma_nl_rcv_skb drivers/infiniband/core/netlink.c:239 [inline] + rdma_nl_rcv+0x6dd/0x9e0 drivers/infiniband/core/netlink.c:259 + netlink_unicast_kernel net/netlink/af_netlink.c:1313 [inline] + netlink_unicast+0x7f6/0x990 net/netlink/af_netlink.c:1339 + netlink_sendmsg+0x8de/0xcb0 net/netlink/af_netlink.c:1883 + sock_sendmsg_nosec net/socket.c:709 [inline] + __sock_sendmsg+0x221/0x270 net/socket.c:724 + ____sys_sendmsg+0x53a/0x860 net/socket.c:2564 + ___sys_sendmsg net/socket.c:2618 [inline] + __sys_sendmsg+0x269/0x350 net/socket.c:2650 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +This is because if rename device happens, the old name is freed in +ib_device_rename() with lock, but ib_device_notify_register() may visit +the dev name locklessly by event RDMA_REGISTER_EVENT or +RDMA_NETDEV_ATTACH_EVENT. + +Fix this by hold devices_rwsem in ib_device_notify_register(). + +Reported-by: syzbot+f60349ba1f9f08df349f@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=25bc6f0ed2b88b9eb9b8 +Fixes: 9cbed5aab5ae ("RDMA/nldev: Add support for RDMA monitoring") +Signed-off-by: Wang Liang +Link: https://patch.msgid.link/20250313092421.944658-1-wangliang74@huawei.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/device.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c +index 8feb22089cbbd..ee75b99f84bcc 100644 +--- a/drivers/infiniband/core/device.c ++++ b/drivers/infiniband/core/device.c +@@ -1350,9 +1350,11 @@ static void ib_device_notify_register(struct ib_device *device) + u32 port; + int ret; + ++ down_read(&devices_rwsem); ++ + ret = rdma_nl_notify_event(device, 0, RDMA_REGISTER_EVENT); + if (ret) +- return; ++ goto out; + + rdma_for_each_port(device, port) { + netdev = ib_device_get_netdev(device, port); +@@ -1363,8 +1365,11 @@ static void ib_device_notify_register(struct ib_device *device) + RDMA_NETDEV_ATTACH_EVENT); + dev_put(netdev); + if (ret) +- return; ++ goto out; + } ++ ++out: ++ up_read(&devices_rwsem); + } + + /** +-- +2.39.5 + diff --git a/queue-6.14/rdma-erdma-prevent-use-after-free-in-erdma_accept_ne.patch b/queue-6.14/rdma-erdma-prevent-use-after-free-in-erdma_accept_ne.patch new file mode 100644 index 0000000000..eb0d21d18e --- /dev/null +++ b/queue-6.14/rdma-erdma-prevent-use-after-free-in-erdma_accept_ne.patch @@ -0,0 +1,36 @@ +From 60fa719d89d296afc562e192d802d48c7f577a19 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 20:04:40 +0800 +Subject: RDMA/erdma: Prevent use-after-free in erdma_accept_newconn() + +From: Cheng Xu + +[ Upstream commit 83437689249e6a17b25e27712fbee292e42e7855 ] + +After the erdma_cep_put(new_cep) being called, new_cep will be freed, +and the following dereference will cause a UAF problem. Fix this issue. + +Fixes: 920d93eac8b9 ("RDMA/erdma: Add connection management (CM) support") +Signed-off-by: Markus Elfring +Signed-off-by: Cheng Xu +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/erdma/erdma_cm.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/infiniband/hw/erdma/erdma_cm.c b/drivers/infiniband/hw/erdma/erdma_cm.c +index 1b23c698ec25c..e0acc185e7193 100644 +--- a/drivers/infiniband/hw/erdma/erdma_cm.c ++++ b/drivers/infiniband/hw/erdma/erdma_cm.c +@@ -709,7 +709,6 @@ static void erdma_accept_newconn(struct erdma_cep *cep) + erdma_cancel_mpatimer(new_cep); + + erdma_cep_put(new_cep); +- new_cep->sock = NULL; + } + + if (new_s) { +-- +2.39.5 + diff --git a/queue-6.14/rdma-mana_ib-ensure-variable-err-is-initialized.patch b/queue-6.14/rdma-mana_ib-ensure-variable-err-is-initialized.patch new file mode 100644 index 0000000000..831590d710 --- /dev/null +++ b/queue-6.14/rdma-mana_ib-ensure-variable-err-is-initialized.patch @@ -0,0 +1,38 @@ +From d67c7e99de965fa823903ca55ba3d0ef99bcd271 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 20:39:03 +0100 +Subject: RDMA/mana_ib: Ensure variable err is initialized + +From: Kees Bakker + +[ Upstream commit be35a3127d60964b338da95c7bfaaf4a01b330d4 ] + +In the function mana_ib_gd_create_dma_region if there are no dma blocks +to process the variable `err` remains uninitialized. + +Fixes: 0266a177631d ("RDMA/mana_ib: Add a driver for Microsoft Azure Network Adapter") +Signed-off-by: Kees Bakker +Link: https://patch.msgid.link/20250221195833.7516C16290A@bout3.ijzerbout.nl +Reviewed-by: Long Li +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/mana/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/mana/main.c b/drivers/infiniband/hw/mana/main.c +index 457cea6d99095..f6bf289041bfe 100644 +--- a/drivers/infiniband/hw/mana/main.c ++++ b/drivers/infiniband/hw/mana/main.c +@@ -358,7 +358,7 @@ static int mana_ib_gd_create_dma_region(struct mana_ib_dev *dev, struct ib_umem + unsigned int tail = 0; + u64 *page_addr_list; + void *request_buf; +- int err; ++ int err = 0; + + gc = mdev_to_gc(dev); + hwc = gc->hwc.driver_data; +-- +2.39.5 + diff --git a/queue-6.14/rdma-mlx5-fix-calculation-of-total-invalidated-pages.patch b/queue-6.14/rdma-mlx5-fix-calculation-of-total-invalidated-pages.patch new file mode 100644 index 0000000000..548935da9f --- /dev/null +++ b/queue-6.14/rdma-mlx5-fix-calculation-of-total-invalidated-pages.patch @@ -0,0 +1,65 @@ +From 36f45d7fc4e04c547505bfdd55c4cb9197d689c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 16:29:54 +0200 +Subject: RDMA/mlx5: Fix calculation of total invalidated pages + +From: Chiara Meiohas + +[ Upstream commit 79195147644653ebffadece31a42181e4c48c07d ] + +When invalidating an address range in mlx5, there is an optimization to +do UMR operations in chunks. +Previously, the invalidation counter was incorrectly updated for the +same indexes within a chunk. Now, the invalidation counter is updated +only when a chunk is complete and mlx5r_umr_update_xlt() is called. +This ensures that the counter accurately represents the number of pages +invalidated using UMR. + +Fixes: a3de94e3d61e ("IB/mlx5: Introduce ODP diagnostic counters") +Signed-off-by: Chiara Meiohas +Reviewed-by: Michael Guralnik +Link: https://patch.msgid.link/560deb2433318e5947282b070c915f3c81fef77f.1741875692.git.leon@kernel.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/mlx5/odp.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/infiniband/hw/mlx5/odp.c b/drivers/infiniband/hw/mlx5/odp.c +index e77c9280c07e4..86d8fa63bf691 100644 +--- a/drivers/infiniband/hw/mlx5/odp.c ++++ b/drivers/infiniband/hw/mlx5/odp.c +@@ -309,9 +309,6 @@ static bool mlx5_ib_invalidate_range(struct mmu_interval_notifier *mni, + blk_start_idx = idx; + in_block = 1; + } +- +- /* Count page invalidations */ +- invalidations += idx - blk_start_idx + 1; + } else { + u64 umr_offset = idx & umr_block_mask; + +@@ -321,14 +318,19 @@ static bool mlx5_ib_invalidate_range(struct mmu_interval_notifier *mni, + MLX5_IB_UPD_XLT_ZAP | + MLX5_IB_UPD_XLT_ATOMIC); + in_block = 0; ++ /* Count page invalidations */ ++ invalidations += idx - blk_start_idx + 1; + } + } + } +- if (in_block) ++ if (in_block) { + mlx5r_umr_update_xlt(mr, blk_start_idx, + idx - blk_start_idx + 1, 0, + MLX5_IB_UPD_XLT_ZAP | + MLX5_IB_UPD_XLT_ATOMIC); ++ /* Count page invalidations */ ++ invalidations += idx - blk_start_idx + 1; ++ } + + mlx5_update_odp_stats_with_handled(mr, invalidations, invalidations); + +-- +2.39.5 + diff --git a/queue-6.14/rdma-mlx5-fix-mlx5_poll_one-cur_qp-update-flow.patch b/queue-6.14/rdma-mlx5-fix-mlx5_poll_one-cur_qp-update-flow.patch new file mode 100644 index 0000000000..17ce8e5154 --- /dev/null +++ b/queue-6.14/rdma-mlx5-fix-mlx5_poll_one-cur_qp-update-flow.patch @@ -0,0 +1,91 @@ +From a6873b8c42c7bb65e8d9a71b5c8cfb0548261a2d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 16:29:53 +0200 +Subject: RDMA/mlx5: Fix mlx5_poll_one() cur_qp update flow + +From: Patrisious Haddad + +[ Upstream commit 5ed3b0cb3f827072e93b4c5b6e2b8106fd7cccbd ] + +When cur_qp isn't NULL, in order to avoid fetching the QP from +the radix tree again we check if the next cqe QP is identical to +the one we already have. + +The bug however is that we are checking if the QP is identical by +checking the QP number inside the CQE against the QP number inside the +mlx5_ib_qp, but that's wrong since the QP number from the CQE is from +FW so it should be matched against mlx5_core_qp which is our FW QP +number. + +Otherwise we could use the wrong QP when handling a CQE which could +cause the kernel trace below. + +This issue is mainly noticeable over QPs 0 & 1, since for now they are +the only QPs in our driver whereas the QP number inside mlx5_ib_qp +doesn't match the QP number inside mlx5_core_qp. + +BUG: kernel NULL pointer dereference, address: 0000000000000012 + #PF: supervisor read access in kernel mode + #PF: error_code(0x0000) - not-present page + PGD 0 P4D 0 + Oops: Oops: 0000 [#1] SMP + CPU: 0 UID: 0 PID: 7927 Comm: kworker/u62:1 Not tainted 6.14.0-rc3+ #189 + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014 + Workqueue: ib-comp-unb-wq ib_cq_poll_work [ib_core] + RIP: 0010:mlx5_ib_poll_cq+0x4c7/0xd90 [mlx5_ib] + Code: 03 00 00 8d 58 ff 21 cb 66 39 d3 74 39 48 c7 c7 3c 89 6e a0 0f b7 db e8 b7 d2 b3 e0 49 8b 86 60 03 00 00 48 c7 c7 4a 89 6e a0 <0f> b7 5c 98 02 e8 9f d2 b3 e0 41 0f b7 86 78 03 00 00 83 e8 01 21 + RSP: 0018:ffff88810511bd60 EFLAGS: 00010046 + RAX: 0000000000000010 RBX: 0000000000000000 RCX: 0000000000000000 + RDX: 0000000000000000 RSI: ffff88885fa1b3c0 RDI: ffffffffa06e894a + RBP: 00000000000000b0 R08: 0000000000000000 R09: ffff88810511bc10 + R10: 0000000000000001 R11: 0000000000000001 R12: ffff88810d593000 + R13: ffff88810e579108 R14: ffff888105146000 R15: 00000000000000b0 + FS: 0000000000000000(0000) GS:ffff88885fa00000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 0000000000000012 CR3: 00000001077e6001 CR4: 0000000000370eb0 + Call Trace: + + ? __die+0x20/0x60 + ? page_fault_oops+0x150/0x3e0 + ? exc_page_fault+0x74/0x130 + ? asm_exc_page_fault+0x22/0x30 + ? mlx5_ib_poll_cq+0x4c7/0xd90 [mlx5_ib] + __ib_process_cq+0x5a/0x150 [ib_core] + ib_cq_poll_work+0x31/0x90 [ib_core] + process_one_work+0x169/0x320 + worker_thread+0x288/0x3a0 + ? work_busy+0xb0/0xb0 + kthread+0xd7/0x1f0 + ? kthreads_online_cpu+0x130/0x130 + ? kthreads_online_cpu+0x130/0x130 + ret_from_fork+0x2d/0x50 + ? kthreads_online_cpu+0x130/0x130 + ret_from_fork_asm+0x11/0x20 + + +Fixes: e126ba97dba9 ("mlx5: Add driver for Mellanox Connect-IB adapters") +Signed-off-by: Patrisious Haddad +Reviewed-by: Edward Srouji +Link: https://patch.msgid.link/4ada09d41f1e36db62c44a9b25c209ea5f054316.1741875692.git.leon@kernel.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/mlx5/cq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/mlx5/cq.c b/drivers/infiniband/hw/mlx5/cq.c +index 4c54dc5780690..1aa5311b03e9f 100644 +--- a/drivers/infiniband/hw/mlx5/cq.c ++++ b/drivers/infiniband/hw/mlx5/cq.c +@@ -490,7 +490,7 @@ static int mlx5_poll_one(struct mlx5_ib_cq *cq, + } + + qpn = ntohl(cqe64->sop_drop_qpn) & 0xffffff; +- if (!*cur_qp || (qpn != (*cur_qp)->ibqp.qp_num)) { ++ if (!*cur_qp || (qpn != (*cur_qp)->trans_qp.base.mqp.qpn)) { + /* We do not have to take the QP table lock here, + * because CQs will be locked while QPs are removed + * from the table. +-- +2.39.5 + diff --git a/queue-6.14/rdma-mlx5-fix-mr-cache-initialization-error-flow.patch b/queue-6.14/rdma-mlx5-fix-mr-cache-initialization-error-flow.patch new file mode 100644 index 0000000000..d88157d089 --- /dev/null +++ b/queue-6.14/rdma-mlx5-fix-mr-cache-initialization-error-flow.patch @@ -0,0 +1,83 @@ +From acb75bc2868ae672dd6a67b469580319a59e591c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 16:29:48 +0200 +Subject: RDMA/mlx5: Fix MR cache initialization error flow + +From: Michael Guralnik + +[ Upstream commit a0130ef84b00c68ba0b79ee974a0f01459741421 ] + +Destroy all previously created cache entries and work queue when rolling +back the MR cache initialization upon an error. + +Fixes: 73d09b2fe833 ("RDMA/mlx5: Introduce mlx5r_cache_rb_key") +Signed-off-by: Michael Guralnik +Reviewed-by: Yishai Hadas +Link: https://patch.msgid.link/c41d525fb3c72e28dd38511bf3aaccb5d584063e.1741875692.git.leon@kernel.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/mlx5/mr.c | 33 ++++++++++++++++++++++----------- + 1 file changed, 22 insertions(+), 11 deletions(-) + +diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c +index eeb94d1ae60d9..068eac3bdb50b 100644 +--- a/drivers/infiniband/hw/mlx5/mr.c ++++ b/drivers/infiniband/hw/mlx5/mr.c +@@ -919,6 +919,25 @@ mlx5r_cache_create_ent_locked(struct mlx5_ib_dev *dev, + return ERR_PTR(ret); + } + ++static void mlx5r_destroy_cache_entries(struct mlx5_ib_dev *dev) ++{ ++ struct rb_root *root = &dev->cache.rb_root; ++ struct mlx5_cache_ent *ent; ++ struct rb_node *node; ++ ++ mutex_lock(&dev->cache.rb_lock); ++ node = rb_first(root); ++ while (node) { ++ ent = rb_entry(node, struct mlx5_cache_ent, node); ++ node = rb_next(node); ++ clean_keys(dev, ent); ++ rb_erase(&ent->node, root); ++ mlx5r_mkeys_uninit(ent); ++ kfree(ent); ++ } ++ mutex_unlock(&dev->cache.rb_lock); ++} ++ + int mlx5_mkey_cache_init(struct mlx5_ib_dev *dev) + { + struct mlx5_mkey_cache *cache = &dev->cache; +@@ -970,6 +989,8 @@ int mlx5_mkey_cache_init(struct mlx5_ib_dev *dev) + err: + mutex_unlock(&cache->rb_lock); + mlx5_mkey_cache_debugfs_cleanup(dev); ++ mlx5r_destroy_cache_entries(dev); ++ destroy_workqueue(cache->wq); + mlx5_ib_warn(dev, "failed to create mkey cache entry\n"); + return ret; + } +@@ -1003,17 +1024,7 @@ void mlx5_mkey_cache_cleanup(struct mlx5_ib_dev *dev) + mlx5_cmd_cleanup_async_ctx(&dev->async_ctx); + + /* At this point all entries are disabled and have no concurrent work. */ +- mutex_lock(&dev->cache.rb_lock); +- node = rb_first(root); +- while (node) { +- ent = rb_entry(node, struct mlx5_cache_ent, node); +- node = rb_next(node); +- clean_keys(dev, ent); +- rb_erase(&ent->node, root); +- mlx5r_mkeys_uninit(ent); +- kfree(ent); +- } +- mutex_unlock(&dev->cache.rb_lock); ++ mlx5r_destroy_cache_entries(dev); + + destroy_workqueue(dev->cache.wq); + del_timer_sync(&dev->delay_timer); +-- +2.39.5 + diff --git a/queue-6.14/rdma-mlx5-fix-page_size-variable-overflow.patch b/queue-6.14/rdma-mlx5-fix-page_size-variable-overflow.patch new file mode 100644 index 0000000000..9db1710c3c --- /dev/null +++ b/queue-6.14/rdma-mlx5-fix-page_size-variable-overflow.patch @@ -0,0 +1,121 @@ +From a3231e474ff9d00eae1c4acb14d126bdde704658 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 16:29:51 +0200 +Subject: RDMA/mlx5: Fix page_size variable overflow + +From: Michael Guralnik + +[ Upstream commit f0c2427412b43cdf1b7b0944749ea17ddb97d5a5 ] + +Change all variables storing mlx5_umem_mkc_find_best_pgsz() result to +unsigned long to support values larger than 31 and avoid overflow. + +For example: If we try to register 4GB of memory that is contiguous in +physical memory, the driver will optimize the page_size and try to use +an mkey with 4GB entity size. The 'unsigned int' page_size variable will +overflow to '0' and we'll hit the WARN_ON() in alloc_cacheable_mr(). + +WARNING: CPU: 2 PID: 1203 at drivers/infiniband/hw/mlx5/mr.c:1124 alloc_cacheable_mr+0x22/0x580 [mlx5_ib] +Modules linked in: mlx5_ib mlx5_core bonding ip6_gre ip6_tunnel tunnel6 ip_gre gre rdma_rxe rdma_ucm ib_uverbs ib_ipoib ib_umad rpcrdma ib_iser libiscsi scsi_transport_iscsi rdma_cm iw_cm ib_cm fuse ib_core [last unloaded: mlx5_core] +CPU: 2 UID: 70878 PID: 1203 Comm: rdma_resource_l Tainted: G W 6.14.0-rc4-dirty #43 +Tainted: [W]=WARN +Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 +RIP: 0010:alloc_cacheable_mr+0x22/0x580 [mlx5_ib] +Code: 90 90 90 90 90 90 90 90 0f 1f 44 00 00 55 48 89 e5 41 57 41 56 41 55 41 54 41 52 53 48 83 ec 30 f6 46 28 04 4c 8b 77 08 75 21 <0f> 0b 49 c7 c2 ea ff ff ff 48 8d 65 d0 4c 89 d0 5b 41 5a 41 5c 41 +RSP: 0018:ffffc900006ffac8 EFLAGS: 00010246 +RAX: 0000000004c0d0d0 RBX: ffff888217a22000 RCX: 0000000000100001 +RDX: 00007fb7ac480000 RSI: ffff8882037b1240 RDI: ffff8882046f0600 +RBP: ffffc900006ffb28 R08: 0000000000000001 R09: 0000000000000000 +R10: 00000000000007e0 R11: ffffea0008011d40 R12: ffff8882037b1240 +R13: ffff8882046f0600 R14: ffff888217a22000 R15: ffffc900006ffe00 +FS: 00007fb7ed013340(0000) GS:ffff88885fd00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007fb7ed1d8000 CR3: 00000001fd8f6006 CR4: 0000000000772eb0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +PKRU: 55555554 +Call Trace: + + ? __warn+0x81/0x130 + ? alloc_cacheable_mr+0x22/0x580 [mlx5_ib] + ? report_bug+0xfc/0x1e0 + ? handle_bug+0x55/0x90 + ? exc_invalid_op+0x17/0x70 + ? asm_exc_invalid_op+0x1a/0x20 + ? alloc_cacheable_mr+0x22/0x580 [mlx5_ib] + create_real_mr+0x54/0x150 [mlx5_ib] + ib_uverbs_reg_mr+0x17f/0x2a0 [ib_uverbs] + ib_uverbs_handler_UVERBS_METHOD_INVOKE_WRITE+0xca/0x140 [ib_uverbs] + ib_uverbs_run_method+0x6d0/0x780 [ib_uverbs] + ? __pfx_ib_uverbs_handler_UVERBS_METHOD_INVOKE_WRITE+0x10/0x10 [ib_uverbs] + ib_uverbs_cmd_verbs+0x19b/0x360 [ib_uverbs] + ? walk_system_ram_range+0x79/0xd0 + ? ___pte_offset_map+0x1b/0x110 + ? __pte_offset_map_lock+0x80/0x100 + ib_uverbs_ioctl+0xac/0x110 [ib_uverbs] + __x64_sys_ioctl+0x94/0xb0 + do_syscall_64+0x50/0x110 + entry_SYSCALL_64_after_hwframe+0x76/0x7e +RIP: 0033:0x7fb7ecf0737b +Code: ff ff ff 85 c0 79 9b 49 c7 c4 ff ff ff ff 5b 5d 4c 89 e0 41 5c c3 66 0f 1f 84 00 00 00 00 00 f3 0f 1e fa b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 7d 2a 0f 00 f7 d8 64 89 01 48 +RSP: 002b:00007ffdbe03ecc8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 +RAX: ffffffffffffffda RBX: 00007ffdbe03edb8 RCX: 00007fb7ecf0737b +RDX: 00007ffdbe03eda0 RSI: 00000000c0181b01 RDI: 0000000000000003 +RBP: 00007ffdbe03ed80 R08: 00007fb7ecc84010 R09: 00007ffdbe03eed4 +R10: 0000000000000009 R11: 0000000000000246 R12: 00007ffdbe03eed4 +R13: 000000000000000c R14: 000000000000000c R15: 00007fb7ecc84150 + + +Fixes: cef7dde8836a ("net/mlx5: Expand mkey page size to support 6 bits") +Signed-off-by: Michael Guralnik +Reviewed-by: Yishai Hadas +Link: https://patch.msgid.link/2479a4a3f6fd9bd032e1b6d396274a89c4c5e22f.1741875692.git.leon@kernel.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/mlx5/mr.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c +index 753faa9ad06a8..eeb94d1ae60d9 100644 +--- a/drivers/infiniband/hw/mlx5/mr.c ++++ b/drivers/infiniband/hw/mlx5/mr.c +@@ -56,7 +56,7 @@ static void + create_mkey_callback(int status, struct mlx5_async_work *context); + static struct mlx5_ib_mr *reg_create(struct ib_pd *pd, struct ib_umem *umem, + u64 iova, int access_flags, +- unsigned int page_size, bool populate, ++ unsigned long page_size, bool populate, + int access_mode); + static int __mlx5_ib_dereg_mr(struct ib_mr *ibmr); + +@@ -1115,7 +1115,7 @@ static struct mlx5_ib_mr *alloc_cacheable_mr(struct ib_pd *pd, + struct mlx5r_cache_rb_key rb_key = {}; + struct mlx5_cache_ent *ent; + struct mlx5_ib_mr *mr; +- unsigned int page_size; ++ unsigned long page_size; + + if (umem->is_dmabuf) + page_size = mlx5_umem_dmabuf_default_pgsz(umem, iova); +@@ -1219,7 +1219,7 @@ reg_create_crossing_vhca_mr(struct ib_pd *pd, u64 iova, u64 length, int access_f + */ + static struct mlx5_ib_mr *reg_create(struct ib_pd *pd, struct ib_umem *umem, + u64 iova, int access_flags, +- unsigned int page_size, bool populate, ++ unsigned long page_size, bool populate, + int access_mode) + { + struct mlx5_ib_dev *dev = to_mdev(pd->device); +@@ -1425,7 +1425,7 @@ static struct ib_mr *create_real_mr(struct ib_pd *pd, struct ib_umem *umem, + mr = alloc_cacheable_mr(pd, umem, iova, access_flags, + MLX5_MKC_ACCESS_MODE_MTT); + } else { +- unsigned int page_size = ++ unsigned long page_size = + mlx5_umem_mkc_find_best_pgsz(dev, umem, iova); + + mutex_lock(&dev->slow_path_mutex); +-- +2.39.5 + diff --git a/queue-6.14/reboot-reboot-not-shutdown-on-hw_protection_reboot-t.patch b/queue-6.14/reboot-reboot-not-shutdown-on-hw_protection_reboot-t.patch new file mode 100644 index 0000000000..7bf7344ede --- /dev/null +++ b/queue-6.14/reboot-reboot-not-shutdown-on-hw_protection_reboot-t.patch @@ -0,0 +1,163 @@ +From e068e7a7e3cf40db47c4a6caac20477ee8f0a06e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 21:39:42 +0100 +Subject: reboot: reboot, not shutdown, on hw_protection_reboot timeout + +From: Ahmad Fatoum + +[ Upstream commit bbf0ec4f57e0a34983ca25f00ec90f4765572d78 ] + +hw_protection_shutdown() will kick off an orderly shutdown and if that +takes longer than a configurable amount of time, an emergency shutdown +will occur. + +Recently, hw_protection_reboot() was added for those systems that don't +implement a proper shutdown and are better served by rebooting and having +the boot firmware worry about doing something about the critical +condition. + +On timeout of the orderly reboot of hw_protection_reboot(), the system +would go into shutdown, instead of reboot. This is not a good idea, as +going into shutdown was explicitly not asked for. + +Fix this by always doing an emergency reboot if hw_protection_reboot() is +called and the orderly reboot takes too long. + +Link: https://lkml.kernel.org/r/20250217-hw_protection-reboot-v3-2-e1c09b090c0c@pengutronix.de +Fixes: 79fa723ba84c ("reboot: Introduce thermal_zone_device_critical_reboot()") +Signed-off-by: Ahmad Fatoum +Reviewed-by: Tzung-Bi Shih +Reviewed-by: Matti Vaittinen +Cc: Benson Leung +Cc: Daniel Lezcano +Cc: Fabio Estevam +Cc: Guenter Roeck +Cc: Jonathan Corbet +Cc: Liam Girdwood +Cc: Lukasz Luba +Cc: Mark Brown +Cc: Matteo Croce +Cc: "Rafael J. Wysocki" +Cc: Rob Herring (Arm) +Cc: Rui Zhang +Cc: Sascha Hauer +Cc: "Serge E. Hallyn" +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + kernel/reboot.c | 70 ++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 49 insertions(+), 21 deletions(-) + +diff --git a/kernel/reboot.c b/kernel/reboot.c +index b20b53f08648d..f348f1ba9e226 100644 +--- a/kernel/reboot.c ++++ b/kernel/reboot.c +@@ -932,48 +932,76 @@ void orderly_reboot(void) + } + EXPORT_SYMBOL_GPL(orderly_reboot); + ++static const char *hw_protection_action_str(enum hw_protection_action action) ++{ ++ switch (action) { ++ case HWPROT_ACT_SHUTDOWN: ++ return "shutdown"; ++ case HWPROT_ACT_REBOOT: ++ return "reboot"; ++ default: ++ return "undefined"; ++ } ++} ++ ++static enum hw_protection_action hw_failure_emergency_action; ++ + /** +- * hw_failure_emergency_poweroff_func - emergency poweroff work after a known delay +- * @work: work_struct associated with the emergency poweroff function ++ * hw_failure_emergency_action_func - emergency action work after a known delay ++ * @work: work_struct associated with the emergency action function + * + * This function is called in very critical situations to force +- * a kernel poweroff after a configurable timeout value. ++ * a kernel poweroff or reboot after a configurable timeout value. + */ +-static void hw_failure_emergency_poweroff_func(struct work_struct *work) ++static void hw_failure_emergency_action_func(struct work_struct *work) + { ++ const char *action_str = hw_protection_action_str(hw_failure_emergency_action); ++ ++ pr_emerg("Hardware protection timed-out. Trying forced %s\n", ++ action_str); ++ + /* +- * We have reached here after the emergency shutdown waiting period has +- * expired. This means orderly_poweroff has not been able to shut off +- * the system for some reason. ++ * We have reached here after the emergency action waiting period has ++ * expired. This means orderly_poweroff/reboot has not been able to ++ * shut off the system for some reason. + * +- * Try to shut down the system immediately using kernel_power_off +- * if populated ++ * Try to shut off the system immediately if possible + */ +- pr_emerg("Hardware protection timed-out. Trying forced poweroff\n"); +- kernel_power_off(); ++ ++ if (hw_failure_emergency_action == HWPROT_ACT_REBOOT) ++ kernel_restart(NULL); ++ else ++ kernel_power_off(); + + /* + * Worst of the worst case trigger emergency restart + */ +- pr_emerg("Hardware protection shutdown failed. Trying emergency restart\n"); ++ pr_emerg("Hardware protection %s failed. Trying emergency restart\n", ++ action_str); + emergency_restart(); + } + +-static DECLARE_DELAYED_WORK(hw_failure_emergency_poweroff_work, +- hw_failure_emergency_poweroff_func); ++static DECLARE_DELAYED_WORK(hw_failure_emergency_action_work, ++ hw_failure_emergency_action_func); + + /** +- * hw_failure_emergency_poweroff - Trigger an emergency system poweroff ++ * hw_failure_emergency_schedule - Schedule an emergency system shutdown or reboot ++ * ++ * @action: The hardware protection action to be taken ++ * @action_delay_ms: Time in milliseconds to elapse before triggering action + * + * This may be called from any critical situation to trigger a system shutdown +- * after a given period of time. If time is negative this is not scheduled. ++ * or reboot after a given period of time. ++ * If time is negative this is not scheduled. + */ +-static void hw_failure_emergency_poweroff(int poweroff_delay_ms) ++static void hw_failure_emergency_schedule(enum hw_protection_action action, ++ int action_delay_ms) + { +- if (poweroff_delay_ms <= 0) ++ if (action_delay_ms <= 0) + return; +- schedule_delayed_work(&hw_failure_emergency_poweroff_work, +- msecs_to_jiffies(poweroff_delay_ms)); ++ hw_failure_emergency_action = action; ++ schedule_delayed_work(&hw_failure_emergency_action_work, ++ msecs_to_jiffies(action_delay_ms)); + } + + /** +@@ -1006,7 +1034,7 @@ void __hw_protection_shutdown(const char *reason, int ms_until_forced, + * Queue a backup emergency shutdown in the event of + * orderly_poweroff failure + */ +- hw_failure_emergency_poweroff(ms_until_forced); ++ hw_failure_emergency_schedule(action, ms_until_forced); + if (action == HWPROT_ACT_REBOOT) + orderly_reboot(); + else +-- +2.39.5 + diff --git a/queue-6.14/reboot-replace-__hw_protection_shutdown-bool-action-.patch b/queue-6.14/reboot-replace-__hw_protection_shutdown-bool-action-.patch new file mode 100644 index 0000000000..11171334b0 --- /dev/null +++ b/queue-6.14/reboot-replace-__hw_protection_shutdown-bool-action-.patch @@ -0,0 +1,163 @@ +From 5fcd3b3a72e0b163e889efa538d1aeb785c97579 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 21:39:41 +0100 +Subject: reboot: replace __hw_protection_shutdown bool action parameter with + an enum + +From: Ahmad Fatoum + +[ Upstream commit 318f05a057157c400a92f17c5f2fa3dd96f57c7e ] + +Patch series "reboot: support runtime configuration of emergency +hw_protection action", v3. + +We currently leave the decision of whether to shutdown or reboot to +protect hardware in an emergency situation to the individual drivers. + +This works out in some cases, where the driver detecting the critical +failure has inside knowledge: It binds to the system management controller +for example or is guided by hardware description that defines what to do. + +This is inadequate in the general case though as a driver reporting e.g. +an imminent power failure can't know whether a shutdown or a reboot would +be more appropriate for a given hardware platform. + +To address this, this series adds a hw_protection kernel parameter and +sysfs toggle that can be used to change the action from the shutdown +default to reboot. A new hw_protection_trigger API then makes use of this +default action. + +My particular use case is unattended embedded systems that don't have +support for shutdown and that power on automatically when power is +supplied: + + - A brief power cycle gets detected by the driver + - The kernel powers down the system and SoC goes into shutdown mode + - Power is restored + - The system remains oblivious to the restored power + - System needs to be manually power cycled for a duration long enough + to drain the capacitors + +With this series, such systems can configure the kernel with +hw_protection=reboot to have the boot firmware worry about critical +conditions. + +This patch (of 12): + +Currently __hw_protection_shutdown() either reboots or shuts down the +system according to its shutdown argument. + +To make the logic easier to follow, both inside __hw_protection_shutdown +and at caller sites, lets replace the bool parameter with an enum. + +This will be extra useful, when in a later commit, a third action is added +to the enumeration. + +No functional change. + +Link: https://lkml.kernel.org/r/20250217-hw_protection-reboot-v3-0-e1c09b090c0c@pengutronix.de +Link: https://lkml.kernel.org/r/20250217-hw_protection-reboot-v3-1-e1c09b090c0c@pengutronix.de +Signed-off-by: Ahmad Fatoum +Reviewed-by: Tzung-Bi Shih +Cc: Benson Leung +Cc: Mark Brown +Cc: Daniel Lezcano +Cc: Fabio Estevam +Cc: Guenter Roeck +Cc: Jonathan Corbet +Cc: Liam Girdwood +Cc: Lukasz Luba +Cc: Matteo Croce +Cc: Matti Vaittinen +Cc: "Rafael J. Wysocki" +Cc: Rob Herring +Cc: Rui Zhang +Cc: Sascha Hauer +Cc: "Serge E. Hallyn" +Signed-off-by: Andrew Morton +Stable-dep-of: bbf0ec4f57e0 ("reboot: reboot, not shutdown, on hw_protection_reboot timeout") +Signed-off-by: Sasha Levin +--- + include/linux/reboot.h | 18 +++++++++++++++--- + kernel/reboot.c | 14 ++++++-------- + 2 files changed, 21 insertions(+), 11 deletions(-) + +diff --git a/include/linux/reboot.h b/include/linux/reboot.h +index abcdde4df6979..e97f6b8e85868 100644 +--- a/include/linux/reboot.h ++++ b/include/linux/reboot.h +@@ -177,16 +177,28 @@ void ctrl_alt_del(void); + + extern void orderly_poweroff(bool force); + extern void orderly_reboot(void); +-void __hw_protection_shutdown(const char *reason, int ms_until_forced, bool shutdown); ++ ++/** ++ * enum hw_protection_action - Hardware protection action ++ * ++ * @HWPROT_ACT_SHUTDOWN: ++ * The system should be shut down (powered off) for HW protection. ++ * @HWPROT_ACT_REBOOT: ++ * The system should be rebooted for HW protection. ++ */ ++enum hw_protection_action { HWPROT_ACT_SHUTDOWN, HWPROT_ACT_REBOOT }; ++ ++void __hw_protection_shutdown(const char *reason, int ms_until_forced, ++ enum hw_protection_action action); + + static inline void hw_protection_reboot(const char *reason, int ms_until_forced) + { +- __hw_protection_shutdown(reason, ms_until_forced, false); ++ __hw_protection_shutdown(reason, ms_until_forced, HWPROT_ACT_REBOOT); + } + + static inline void hw_protection_shutdown(const char *reason, int ms_until_forced) + { +- __hw_protection_shutdown(reason, ms_until_forced, true); ++ __hw_protection_shutdown(reason, ms_until_forced, HWPROT_ACT_SHUTDOWN); + } + + /* +diff --git a/kernel/reboot.c b/kernel/reboot.c +index b5a8569e5d81f..b20b53f08648d 100644 +--- a/kernel/reboot.c ++++ b/kernel/reboot.c +@@ -983,10 +983,7 @@ static void hw_failure_emergency_poweroff(int poweroff_delay_ms) + * @ms_until_forced: Time to wait for orderly shutdown or reboot before + * triggering it. Negative value disables the forced + * shutdown or reboot. +- * @shutdown: If true, indicates that a shutdown will happen +- * after the critical tempeature is reached. +- * If false, indicates that a reboot will happen +- * after the critical tempeature is reached. ++ * @action: The hardware protection action to be taken. + * + * Initiate an emergency system shutdown or reboot in order to protect + * hardware from further damage. Usage examples include a thermal protection. +@@ -994,7 +991,8 @@ static void hw_failure_emergency_poweroff(int poweroff_delay_ms) + * pending even if the previous request has given a large timeout for forced + * shutdown/reboot. + */ +-void __hw_protection_shutdown(const char *reason, int ms_until_forced, bool shutdown) ++void __hw_protection_shutdown(const char *reason, int ms_until_forced, ++ enum hw_protection_action action) + { + static atomic_t allow_proceed = ATOMIC_INIT(1); + +@@ -1009,10 +1007,10 @@ void __hw_protection_shutdown(const char *reason, int ms_until_forced, bool shut + * orderly_poweroff failure + */ + hw_failure_emergency_poweroff(ms_until_forced); +- if (shutdown) +- orderly_poweroff(true); +- else ++ if (action == HWPROT_ACT_REBOOT) + orderly_reboot(); ++ else ++ orderly_poweroff(true); + } + EXPORT_SYMBOL_GPL(__hw_protection_shutdown); + +-- +2.39.5 + diff --git a/queue-6.14/regulator-pca9450-fix-enable-register-for-ldo5.patch b/queue-6.14/regulator-pca9450-fix-enable-register-for-ldo5.patch new file mode 100644 index 0000000000..a8c7499f8c --- /dev/null +++ b/queue-6.14/regulator-pca9450-fix-enable-register-for-ldo5.patch @@ -0,0 +1,56 @@ +From 3ae272dc1e43584b4c8ea413b2a1c066e0ff163b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Dec 2024 16:27:28 +0100 +Subject: regulator: pca9450: Fix enable register for LDO5 + +From: Frieder Schrempf + +[ Upstream commit f5aab0438ef17f01c5ecd25e61ae6a03f82a4586 ] + +The LDO5 regulator has two configuration registers, but only +LDO5CTRL_L contains the bits for enabling/disabling the regulator. + +Fixes: 0935ff5f1f0a ("regulator: pca9450: add pca9450 pmic driver") +Signed-off-by: Frieder Schrempf +Reviewed-by: Marek Vasut +Link: https://patch.msgid.link/20241218152842.97483-6-frieder@fris.de +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/pca9450-regulator.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c +index faa6b79c27d75..dfe1dd93d56f5 100644 +--- a/drivers/regulator/pca9450-regulator.c ++++ b/drivers/regulator/pca9450-regulator.c +@@ -460,7 +460,7 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = { + .n_linear_ranges = ARRAY_SIZE(pca9450_ldo5_volts), + .vsel_reg = PCA9450_REG_LDO5CTRL_H, + .vsel_mask = LDO5HOUT_MASK, +- .enable_reg = PCA9450_REG_LDO5CTRL_H, ++ .enable_reg = PCA9450_REG_LDO5CTRL_L, + .enable_mask = LDO5H_EN_MASK, + .owner = THIS_MODULE, + }, +@@ -674,7 +674,7 @@ static const struct pca9450_regulator_desc pca9450bc_regulators[] = { + .n_linear_ranges = ARRAY_SIZE(pca9450_ldo5_volts), + .vsel_reg = PCA9450_REG_LDO5CTRL_H, + .vsel_mask = LDO5HOUT_MASK, +- .enable_reg = PCA9450_REG_LDO5CTRL_H, ++ .enable_reg = PCA9450_REG_LDO5CTRL_L, + .enable_mask = LDO5H_EN_MASK, + .owner = THIS_MODULE, + }, +@@ -864,7 +864,7 @@ static const struct pca9450_regulator_desc pca9451a_regulators[] = { + .n_linear_ranges = ARRAY_SIZE(pca9450_ldo5_volts), + .vsel_reg = PCA9450_REG_LDO5CTRL_H, + .vsel_mask = LDO5HOUT_MASK, +- .enable_reg = PCA9450_REG_LDO5CTRL_H, ++ .enable_reg = PCA9450_REG_LDO5CTRL_L, + .enable_mask = LDO5H_EN_MASK, + .owner = THIS_MODULE, + }, +-- +2.39.5 + diff --git a/queue-6.14/remoteproc-core-clear-table_sz-when-rproc_shutdown.patch b/queue-6.14/remoteproc-core-clear-table_sz-when-rproc_shutdown.patch new file mode 100644 index 0000000000..352e22d867 --- /dev/null +++ b/queue-6.14/remoteproc-core-clear-table_sz-when-rproc_shutdown.patch @@ -0,0 +1,86 @@ +From 03548ac7dacba2057f32d2bdc2286d855c76328a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 18:01:05 +0800 +Subject: remoteproc: core: Clear table_sz when rproc_shutdown + +From: Peng Fan + +[ Upstream commit efdde3d73ab25cef4ff2d06783b0aad8b093c0e4 ] + +There is case as below could trigger kernel dump: +Use U-Boot to start remote processor(rproc) with resource table +published to a fixed address by rproc. After Kernel boots up, +stop the rproc, load a new firmware which doesn't have resource table +,and start rproc. + +When starting rproc with a firmware not have resource table, +`memcpy(loaded_table, rproc->cached_table, rproc->table_sz)` will +trigger dump, because rproc->cache_table is set to NULL during the last +stop operation, but rproc->table_sz is still valid. + +This issue is found on i.MX8MP and i.MX9. + +Dump as below: +Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 +Mem abort info: + ESR = 0x0000000096000004 + EC = 0x25: DABT (current EL), IL = 32 bits + SET = 0, FnV = 0 + EA = 0, S1PTW = 0 + FSC = 0x04: level 0 translation fault +Data abort info: + ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000 + CM = 0, WnR = 0, TnD = 0, TagAccess = 0 + GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 +user pgtable: 4k pages, 48-bit VAs, pgdp=000000010af63000 +[0000000000000000] pgd=0000000000000000, p4d=0000000000000000 +Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP +Modules linked in: +CPU: 2 UID: 0 PID: 1060 Comm: sh Not tainted 6.14.0-rc7-next-20250317-dirty #38 +Hardware name: NXP i.MX8MPlus EVK board (DT) +pstate: a0000005 (NzCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) +pc : __pi_memcpy_generic+0x110/0x22c +lr : rproc_start+0x88/0x1e0 +Call trace: + __pi_memcpy_generic+0x110/0x22c (P) + rproc_boot+0x198/0x57c + state_store+0x40/0x104 + dev_attr_store+0x18/0x2c + sysfs_kf_write+0x7c/0x94 + kernfs_fop_write_iter+0x120/0x1cc + vfs_write+0x240/0x378 + ksys_write+0x70/0x108 + __arm64_sys_write+0x1c/0x28 + invoke_syscall+0x48/0x10c + el0_svc_common.constprop.0+0xc0/0xe0 + do_el0_svc+0x1c/0x28 + el0_svc+0x30/0xcc + el0t_64_sync_handler+0x10c/0x138 + el0t_64_sync+0x198/0x19c + +Clear rproc->table_sz to address the issue. + +Fixes: 9dc9507f1880 ("remoteproc: Properly deal with the resource table when detaching") +Signed-off-by: Peng Fan +Link: https://lore.kernel.org/r/20250319100106.3622619-1-peng.fan@oss.nxp.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/remoteproc_core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c +index c2cf0d2777296..b21eedefff877 100644 +--- a/drivers/remoteproc/remoteproc_core.c ++++ b/drivers/remoteproc/remoteproc_core.c +@@ -2025,6 +2025,7 @@ int rproc_shutdown(struct rproc *rproc) + kfree(rproc->cached_table); + rproc->cached_table = NULL; + rproc->table_ptr = NULL; ++ rproc->table_sz = 0; + out: + mutex_unlock(&rproc->lock); + return ret; +-- +2.39.5 + diff --git a/queue-6.14/remoteproc-qcom-pas-add-minidump_id-to-sc7280-wpss.patch b/queue-6.14/remoteproc-qcom-pas-add-minidump_id-to-sc7280-wpss.patch new file mode 100644 index 0000000000..4274fa5f43 --- /dev/null +++ b/queue-6.14/remoteproc-qcom-pas-add-minidump_id-to-sc7280-wpss.patch @@ -0,0 +1,35 @@ +From a59243e01971196c157066afd71868e2334badbb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 09:24:31 +0100 +Subject: remoteproc: qcom: pas: add minidump_id to SC7280 WPSS + +From: Luca Weiss + +[ Upstream commit d2909538bff0189d4d038f4e903c70be5f5c2bfc ] + +Add the minidump ID to the wpss resources, based on msm-5.4 devicetree. + +Fixes: 300ed425dfa9 ("remoteproc: qcom_q6v5_pas: Add SC7280 ADSP, CDSP & WPSS") +Signed-off-by: Luca Weiss +Link: https://lore.kernel.org/r/20250314-sc7280-wpss-minidump-v1-1-d869d53fd432@fairphone.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/qcom_q6v5_pas.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c +index 78484ed9b6c85..9f2d9b4be2790 100644 +--- a/drivers/remoteproc/qcom_q6v5_pas.c ++++ b/drivers/remoteproc/qcom_q6v5_pas.c +@@ -1348,6 +1348,7 @@ static const struct adsp_data sc7280_wpss_resource = { + .crash_reason_smem = 626, + .firmware_name = "wpss.mdt", + .pas_id = 6, ++ .minidump_id = 4, + .auto_boot = false, + .proxy_pd_names = (char*[]){ + "cx", +-- +2.39.5 + diff --git a/queue-6.14/remoteproc-qcom_q6v5_mss-handle-platforms-with-one-p.patch b/queue-6.14/remoteproc-qcom_q6v5_mss-handle-platforms-with-one-p.patch new file mode 100644 index 0000000000..0025e72a6a --- /dev/null +++ b/queue-6.14/remoteproc-qcom_q6v5_mss-handle-platforms-with-one-p.patch @@ -0,0 +1,90 @@ +From 9c7e625d24af257cdefc05f4253e62cfd52e44ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 23:05:18 +0100 +Subject: remoteproc: qcom_q6v5_mss: Handle platforms with one power domain +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Luca Weiss + +[ Upstream commit 4641840341f37dc8231e0840ec1514b4061b4322 ] + +For example MSM8974 has mx voltage rail exposed as regulator and only cx +voltage rail is exposed as power domain. This power domain (cx) is +attached internally in power domain and cannot be attached in this driver. + +Fixes: 8750cf392394 ("remoteproc: qcom_q6v5_mss: Allow replacing regulators with power domains") +Co-developed-by: Matti Lehtimäki +Signed-off-by: Matti Lehtimäki +Reviewed-by: Stephan Gerhold +Signed-off-by: Luca Weiss +Link: https://lore.kernel.org/r/20250217-msm8226-modem-v5-4-2bc74b80e0ae@lucaweiss.eu +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/qcom_q6v5_mss.c | 21 +++++++++++++++++---- + 1 file changed, 17 insertions(+), 4 deletions(-) + +diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c +index e78bd986dc3f2..2c80d7fe39f8e 100644 +--- a/drivers/remoteproc/qcom_q6v5_mss.c ++++ b/drivers/remoteproc/qcom_q6v5_mss.c +@@ -1831,6 +1831,13 @@ static int q6v5_pds_attach(struct device *dev, struct device **devs, + while (pd_names[num_pds]) + num_pds++; + ++ /* Handle single power domain */ ++ if (num_pds == 1 && dev->pm_domain) { ++ devs[0] = dev; ++ pm_runtime_enable(dev); ++ return 1; ++ } ++ + for (i = 0; i < num_pds; i++) { + devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]); + if (IS_ERR_OR_NULL(devs[i])) { +@@ -1851,8 +1858,15 @@ static int q6v5_pds_attach(struct device *dev, struct device **devs, + static void q6v5_pds_detach(struct q6v5 *qproc, struct device **pds, + size_t pd_count) + { ++ struct device *dev = qproc->dev; + int i; + ++ /* Handle single power domain */ ++ if (pd_count == 1 && dev->pm_domain) { ++ pm_runtime_disable(dev); ++ return; ++ } ++ + for (i = 0; i < pd_count; i++) + dev_pm_domain_detach(pds[i], false); + } +@@ -2449,13 +2463,13 @@ static const struct rproc_hexagon_res msm8974_mss = { + .supply = "pll", + .uA = 100000, + }, +- {} +- }, +- .fallback_proxy_supply = (struct qcom_mss_reg_res[]) { + { + .supply = "mx", + .uV = 1050000, + }, ++ {} ++ }, ++ .fallback_proxy_supply = (struct qcom_mss_reg_res[]) { + { + .supply = "cx", + .uA = 100000, +@@ -2481,7 +2495,6 @@ static const struct rproc_hexagon_res msm8974_mss = { + NULL + }, + .proxy_pd_names = (char*[]){ +- "mx", + "cx", + NULL + }, +-- +2.39.5 + diff --git a/queue-6.14/remoteproc-qcom_q6v5_pas-make-single-pd-handling-mor.patch b/queue-6.14/remoteproc-qcom_q6v5_pas-make-single-pd-handling-mor.patch new file mode 100644 index 0000000000..d8b3b501bf --- /dev/null +++ b/queue-6.14/remoteproc-qcom_q6v5_pas-make-single-pd-handling-mor.patch @@ -0,0 +1,63 @@ +From 176372e04d484164528fbf61690719e62589158f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jan 2025 22:54:00 +0100 +Subject: remoteproc: qcom_q6v5_pas: Make single-PD handling more robust + +From: Luca Weiss + +[ Upstream commit e917b73234b02aa4966325e7380d2559bf127ba9 ] + +Only go into the if condition for single-PD handling when there's +actually just one power domain specified there. Otherwise it'll be an +issue in the dts and we should fail in the regular code path. + +This also mirrors the latest changes in the qcom_q6v5_mss driver. + +Suggested-by: Stephan Gerhold +Fixes: 17ee2fb4e856 ("remoteproc: qcom: pas: Vote for active/proxy power domains") +Signed-off-by: Luca Weiss +Reviewed-by: Stephan Gerhold +Link: https://lore.kernel.org/r/20250128-pas-singlepd-v1-2-85d9ae4b0093@lucaweiss.eu +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/qcom_q6v5_pas.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c +index 97c4bdd9222a8..78484ed9b6c85 100644 +--- a/drivers/remoteproc/qcom_q6v5_pas.c ++++ b/drivers/remoteproc/qcom_q6v5_pas.c +@@ -501,16 +501,16 @@ static int adsp_pds_attach(struct device *dev, struct device **devs, + if (!pd_names) + return 0; + ++ while (pd_names[num_pds]) ++ num_pds++; ++ + /* Handle single power domain */ +- if (dev->pm_domain) { ++ if (num_pds == 1 && dev->pm_domain) { + devs[0] = dev; + pm_runtime_enable(dev); + return 1; + } + +- while (pd_names[num_pds]) +- num_pds++; +- + for (i = 0; i < num_pds; i++) { + devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]); + if (IS_ERR_OR_NULL(devs[i])) { +@@ -535,7 +535,7 @@ static void adsp_pds_detach(struct qcom_adsp *adsp, struct device **pds, + int i; + + /* Handle single power domain */ +- if (dev->pm_domain && pd_count) { ++ if (pd_count == 1 && dev->pm_domain) { + pm_runtime_disable(dev); + return; + } +-- +2.39.5 + diff --git a/queue-6.14/remoteproc-qcom_q6v5_pas-use-resource-with-cx-pd-for.patch b/queue-6.14/remoteproc-qcom_q6v5_pas-use-resource-with-cx-pd-for.patch new file mode 100644 index 0000000000..36adffbd9f --- /dev/null +++ b/queue-6.14/remoteproc-qcom_q6v5_pas-use-resource-with-cx-pd-for.patch @@ -0,0 +1,39 @@ +From 3d65b5946c2f2b816b51bcae2ff2bdf40812c2ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jan 2025 22:53:59 +0100 +Subject: remoteproc: qcom_q6v5_pas: Use resource with CX PD for MSM8226 + +From: Luca Weiss + +[ Upstream commit ba785ff4162a65f18ed501019637a998b752b5ad ] + +MSM8226 requires the CX power domain, so use the msm8996_adsp_resource +which has cx under proxy_pd_names and is otherwise equivalent. + +Suggested-by: Stephan Gerhold +Fixes: fb4f07cc9399 ("remoteproc: qcom: pas: Add MSM8226 ADSP support") +Signed-off-by: Luca Weiss +Reviewed-by: Stephan Gerhold +Link: https://lore.kernel.org/r/20250128-pas-singlepd-v1-1-85d9ae4b0093@lucaweiss.eu +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/qcom_q6v5_pas.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c +index 9f2d9b4be2790..60923ed129049 100644 +--- a/drivers/remoteproc/qcom_q6v5_pas.c ++++ b/drivers/remoteproc/qcom_q6v5_pas.c +@@ -1411,7 +1411,7 @@ static const struct adsp_data sm8650_mpss_resource = { + }; + + static const struct of_device_id adsp_of_match[] = { +- { .compatible = "qcom,msm8226-adsp-pil", .data = &adsp_resource_init}, ++ { .compatible = "qcom,msm8226-adsp-pil", .data = &msm8996_adsp_resource}, + { .compatible = "qcom,msm8953-adsp-pil", .data = &msm8996_adsp_resource}, + { .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init}, + { .compatible = "qcom,msm8996-adsp-pil", .data = &msm8996_adsp_resource}, +-- +2.39.5 + diff --git a/queue-6.14/renesas-reject-ptp_strict_flags-as-unsupported.patch b/queue-6.14/renesas-reject-ptp_strict_flags-as-unsupported.patch new file mode 100644 index 0000000000..775c2e62e7 --- /dev/null +++ b/queue-6.14/renesas-reject-ptp_strict_flags-as-unsupported.patch @@ -0,0 +1,61 @@ +From 85d54d82083097138a75f3a9a02ce48603107b4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 15:15:51 -0700 +Subject: renesas: reject PTP_STRICT_FLAGS as unsupported +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jacob Keller + +[ Upstream commit 51d58c0c7921d3c93c44099b90dc46720d095bde ] + +The ravb_ptp_extts() function checks the flags coming from the +PTP_EXTTS_REQUEST ioctl, to ensure that future flags are not accepted on +accident. + +This was updated to 'honor' the PTP_STRICT_FLAGS in commit 6138e687c7b6 +("ptp: Introduce strict checking of external time stamp options."). +However, the driver does not *actually* validate the flags. + +I originally fixed this driver to reject future flags in commit +592025a03b34 ("renesas: reject unsupported external timestamp flags"). It +is still unclear whether this hardware timestamps the rising, falling, or +both edges of the input signal. + +Accepting requests with PTP_STRICT_FLAGS is a bug, as this could lead to +users mistakenly assuming a request with PTP_RISING_EDGE actually +timestamps the rising edge only. + +Reject requests with PTP_STRICT_FLAGS (and hence all PTP_EXTTS_REQUEST2 +requests) until someone with access to the datasheet or hardware knowledge +can confirm the timestamping behavior and update this driver. + +Fixes: 6138e687c7b6 ("ptp: Introduce strict checking of external time stamp options.") +Signed-off-by: Jacob Keller +Reviewed-by: Niklas Söderlund +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250312-jk-net-fixes-supported-extts-flags-v2-2-ea930ba82459@intel.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/renesas/ravb_ptp.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/renesas/ravb_ptp.c b/drivers/net/ethernet/renesas/ravb_ptp.c +index 6e4ef7af27bf3..b4365906669f3 100644 +--- a/drivers/net/ethernet/renesas/ravb_ptp.c ++++ b/drivers/net/ethernet/renesas/ravb_ptp.c +@@ -179,8 +179,7 @@ static int ravb_ptp_extts(struct ptp_clock_info *ptp, + /* Reject requests with unsupported flags */ + if (req->flags & ~(PTP_ENABLE_FEATURE | + PTP_RISING_EDGE | +- PTP_FALLING_EDGE | +- PTP_STRICT_FLAGS)) ++ PTP_FALLING_EDGE)) + return -EOPNOTSUPP; + + if (req->index) +-- +2.39.5 + diff --git a/queue-6.14/ring-buffer-fix-bytes_dropped-calculation-issue.patch b/queue-6.14/ring-buffer-fix-bytes_dropped-calculation-issue.patch new file mode 100644 index 0000000000..69669fc3dd --- /dev/null +++ b/queue-6.14/ring-buffer-fix-bytes_dropped-calculation-issue.patch @@ -0,0 +1,41 @@ +From d355f6c8855ef275c89ef2c4e97923a04e2c3b93 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 23 Feb 2025 15:01:06 +0800 +Subject: ring-buffer: Fix bytes_dropped calculation issue + +From: Feng Yang + +[ Upstream commit c73f0b69648501978e8b3e8fa7eef7f4197d0481 ] + +The calculation of bytes-dropped and bytes_dropped_nested is reversed. +Although it does not affect the final calculation of total_dropped, +it should still be modified. + +Link: https://lore.kernel.org/20250223070106.6781-1-yangfeng59949@163.com +Fixes: 6c43e554a2a5 ("ring-buffer: Add ring buffer startup selftest") +Signed-off-by: Feng Yang +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + kernel/trace/ring_buffer.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c +index bb6089c2951e5..510409f979923 100644 +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -7411,9 +7411,9 @@ static __init int rb_write_something(struct rb_test_data *data, bool nested) + /* Ignore dropped events before test starts. */ + if (started) { + if (nested) +- data->bytes_dropped += len; +- else + data->bytes_dropped_nested += len; ++ else ++ data->bytes_dropped += len; + } + return len; + } +-- +2.39.5 + diff --git a/queue-6.14/risc-v-errata-use-medany-for-relocatable-builds.patch b/queue-6.14/risc-v-errata-use-medany-for-relocatable-builds.patch new file mode 100644 index 0000000000..666d4edf0f --- /dev/null +++ b/queue-6.14/risc-v-errata-use-medany-for-relocatable-builds.patch @@ -0,0 +1,42 @@ +From c55c0669a3446ef499b3bb5e0a7531c98e23df59 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Mar 2025 15:45:07 -0700 +Subject: RISC-V: errata: Use medany for relocatable builds + +From: Palmer Dabbelt + +[ Upstream commit bb58e1579f431d42469b6aed0f03eff383ba6db5 ] + +We're trying to mix non-PIC/PIE objects into the otherwise-PIE +relocatable kernels, to avoid GOT/PLT references during early boot +alternative resolution (which happens before the GOT/PLT are set up). + +riscv64-unknown-linux-gnu-ld: arch/riscv/errata/sifive/errata.o: relocation R_RISCV_HI20 against `tlb_flush_all_threshold' can not be used when making a shared object; recompile with -fPIC +riscv64-unknown-linux-gnu-ld: arch/riscv/errata/thead/errata.o: relocation R_RISCV_HI20 against `riscv_cbom_block_size' can not be used when making a shared object; recompile with -fPIC + +Fixes: 8dc2a7e8027f ("riscv: Fix relocatable kernels with early alternatives using -fno-pie") +Link: https://lore.kernel.org/r/20250326224506.27165-2-palmer@rivosinc.com +Signed-off-by: Palmer Dabbelt +Signed-off-by: Sasha Levin +--- + arch/riscv/errata/Makefile | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile +index f0da9d7b39c37..bc6c77ba837d2 100644 +--- a/arch/riscv/errata/Makefile ++++ b/arch/riscv/errata/Makefile +@@ -1,5 +1,9 @@ + ifdef CONFIG_RELOCATABLE +-KBUILD_CFLAGS += -fno-pie ++# We can't use PIC/PIE when handling early-boot errata parsing, as the kernel ++# doesn't have a GOT setup at that point. So instead just use medany: it's ++# usually position-independent, so it should be good enough for the errata ++# handling. ++KBUILD_CFLAGS += -fno-pie -mcmodel=medany + endif + + ifdef CONFIG_RISCV_ALTERNATIVE_EARLY +-- +2.39.5 + diff --git a/queue-6.14/risc-v-kvm-disable-the-kernel-perf-counter-during-co.patch b/queue-6.14/risc-v-kvm-disable-the-kernel-perf-counter-during-co.patch new file mode 100644 index 0000000000..9e7fdc4907 --- /dev/null +++ b/queue-6.14/risc-v-kvm-disable-the-kernel-perf-counter-during-co.patch @@ -0,0 +1,42 @@ +From 2de7c470dea137d40ad48bed7b214deef9bf1395 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 14:53:06 -0800 +Subject: RISC-V: KVM: Disable the kernel perf counter during configure + +From: Atish Patra + +[ Upstream commit bbb622488749478955485765ddff9d56be4a7e4b ] + +The perf event should be marked disabled during the creation as +it is not ready to be scheduled until there is SBI PMU start call +or config matching is called with auto start. Otherwise, event add/start +gets called during perf_event_create_kernel_counter function. +It will be enabled and scheduled to run via perf_event_enable during +either the above mentioned scenario. + +Fixes: 0cb74b65d2e5 ("RISC-V: KVM: Implement perf support without sampling") + +Reviewed-by: Andrew Jones +Signed-off-by: Atish Patra +Link: https://lore.kernel.org/r/20250303-kvm_pmu_improve-v2-1-41d177e45929@rivosinc.com +Signed-off-by: Anup Patel +Signed-off-by: Sasha Levin +--- + arch/riscv/kvm/vcpu_pmu.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/riscv/kvm/vcpu_pmu.c b/arch/riscv/kvm/vcpu_pmu.c +index 2707a51b082ca..78ac3216a54dd 100644 +--- a/arch/riscv/kvm/vcpu_pmu.c ++++ b/arch/riscv/kvm/vcpu_pmu.c +@@ -666,6 +666,7 @@ int kvm_riscv_vcpu_pmu_ctr_cfg_match(struct kvm_vcpu *vcpu, unsigned long ctr_ba + .type = etype, + .size = sizeof(struct perf_event_attr), + .pinned = true, ++ .disabled = true, + /* + * It should never reach here if the platform doesn't support the sscofpmf + * extension as mode filtering won't work without it. +-- +2.39.5 + diff --git a/queue-6.14/risc-v-kvm-teardown-riscv-specific-bits-after-kvm_ex.patch b/queue-6.14/risc-v-kvm-teardown-riscv-specific-bits-after-kvm_ex.patch new file mode 100644 index 0000000000..ef57e73eaa --- /dev/null +++ b/queue-6.14/risc-v-kvm-teardown-riscv-specific-bits-after-kvm_ex.patch @@ -0,0 +1,75 @@ +From e6b7e13d0967d4366aebc279f843d02507004a4c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 00:41:44 -0700 +Subject: RISC-V: KVM: Teardown riscv specific bits after kvm_exit + +From: Atish Patra + +[ Upstream commit 2d117e67f318303f6ab699a5511d1fac3f170545 ] + +During a module removal, kvm_exit invokes arch specific disable +call which disables AIA. However, we invoke aia_exit before kvm_exit +resulting in the following warning. KVM kernel module can't be inserted +afterwards due to inconsistent state of IRQ. + +[25469.031389] percpu IRQ 31 still enabled on CPU0! +[25469.031732] WARNING: CPU: 3 PID: 943 at kernel/irq/manage.c:2476 __free_percpu_irq+0xa2/0x150 +[25469.031804] Modules linked in: kvm(-) +[25469.031848] CPU: 3 UID: 0 PID: 943 Comm: rmmod Not tainted 6.14.0-rc5-06947-g91c763118f47-dirty #2 +[25469.031905] Hardware name: riscv-virtio,qemu (DT) +[25469.031928] epc : __free_percpu_irq+0xa2/0x150 +[25469.031976] ra : __free_percpu_irq+0xa2/0x150 +[25469.032197] epc : ffffffff8007db1e ra : ffffffff8007db1e sp : ff2000000088bd50 +[25469.032241] gp : ffffffff8131cef8 tp : ff60000080b96400 t0 : ff2000000088baf8 +[25469.032285] t1 : fffffffffffffffc t2 : 5249207570637265 s0 : ff2000000088bd90 +[25469.032329] s1 : ff60000098b21080 a0 : 037d527a15eb4f00 a1 : 037d527a15eb4f00 +[25469.032372] a2 : 0000000000000023 a3 : 0000000000000001 a4 : ffffffff8122dbf8 +[25469.032410] a5 : 0000000000000fff a6 : 0000000000000000 a7 : ffffffff8122dc10 +[25469.032448] s2 : ff60000080c22eb0 s3 : 0000000200000022 s4 : 000000000000001f +[25469.032488] s5 : ff60000080c22e00 s6 : ffffffff80c351c0 s7 : 0000000000000000 +[25469.032582] s8 : 0000000000000003 s9 : 000055556b7fb490 s10: 00007ffff0e12fa0 +[25469.032621] s11: 00007ffff0e13e9a t3 : ffffffff81354ac7 t4 : ffffffff81354ac7 +[25469.032664] t5 : ffffffff81354ac8 t6 : ffffffff81354ac7 +[25469.032698] status: 0000000200000100 badaddr: ffffffff8007db1e cause: 0000000000000003 +[25469.032738] [] __free_percpu_irq+0xa2/0x150 +[25469.032797] [] free_percpu_irq+0x30/0x5e +[25469.032856] [] kvm_riscv_aia_exit+0x40/0x42 [kvm] +[25469.033947] [] cleanup_module+0x10/0x32 [kvm] +[25469.035300] [] __riscv_sys_delete_module+0x18e/0x1fc +[25469.035374] [] syscall_handler+0x3a/0x46 +[25469.035456] [] do_trap_ecall_u+0x72/0x134 +[25469.035536] [] handle_exception+0x148/0x156 + +Invoke aia_exit and other arch specific cleanup functions after kvm_exit +so that disable gets a chance to be called first before exit. + +Fixes: 54e43320c2ba ("RISC-V: KVM: Initial skeletal support for AIA") +Fixes: eded6754f398 ("riscv: KVM: add basic support for host vs guest profiling") +Signed-off-by: Atish Patra +Reviewed-by: Anup Patel +Reviewed-by: Sean Christopherson +Link: https://lore.kernel.org/r/20250317-kvm_exit_fix-v1-1-aa5240c5dbd2@rivosinc.com +Signed-off-by: Anup Patel +Signed-off-by: Sasha Levin +--- + arch/riscv/kvm/main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/riscv/kvm/main.c b/arch/riscv/kvm/main.c +index 1fa8be5ee5097..4b24705dc63a9 100644 +--- a/arch/riscv/kvm/main.c ++++ b/arch/riscv/kvm/main.c +@@ -172,8 +172,8 @@ module_init(riscv_kvm_init); + + static void __exit riscv_kvm_exit(void) + { +- kvm_riscv_teardown(); +- + kvm_exit(); ++ ++ kvm_riscv_teardown(); + } + module_exit(riscv_kvm_exit); +-- +2.39.5 + diff --git a/queue-6.14/riscv-annotate-unaligned-access-init-functions.patch b/queue-6.14/riscv-annotate-unaligned-access-init-functions.patch new file mode 100644 index 0000000000..0601dc5f57 --- /dev/null +++ b/queue-6.14/riscv-annotate-unaligned-access-init-functions.patch @@ -0,0 +1,154 @@ +From 79c55833317d09267353df056a2678fb3d6a47c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 13:00:16 +0100 +Subject: riscv: Annotate unaligned access init functions + +From: Andrew Jones + +[ Upstream commit a00e022be5315c5a1f47521a1cc6d3b71c8e9c44 ] + +Several functions used in unaligned access probing are only run at +init time. Annotate them appropriately. + +Fixes: f413aae96cda ("riscv: Set unaligned access speed at compile time") +Reviewed-by: Alexandre Ghiti +Signed-off-by: Andrew Jones +Link: https://lore.kernel.org/r/20250304120014.143628-11-ajones@ventanamicro.com +Signed-off-by: Alexandre Ghiti +Signed-off-by: Sasha Levin +--- + arch/riscv/include/asm/cpufeature.h | 4 ++-- + arch/riscv/kernel/traps_misaligned.c | 8 ++++---- + arch/riscv/kernel/unaligned_access_speed.c | 14 +++++++------- + 3 files changed, 13 insertions(+), 13 deletions(-) + +diff --git a/arch/riscv/include/asm/cpufeature.h b/arch/riscv/include/asm/cpufeature.h +index 569140d6e6399..19defdc2002d8 100644 +--- a/arch/riscv/include/asm/cpufeature.h ++++ b/arch/riscv/include/asm/cpufeature.h +@@ -63,7 +63,7 @@ void __init riscv_user_isa_enable(void); + #define __RISCV_ISA_EXT_SUPERSET_VALIDATE(_name, _id, _sub_exts, _validate) \ + _RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), _validate) + +-bool check_unaligned_access_emulated_all_cpus(void); ++bool __init check_unaligned_access_emulated_all_cpus(void); + #if defined(CONFIG_RISCV_SCALAR_MISALIGNED) + void check_unaligned_access_emulated(struct work_struct *work __always_unused); + void unaligned_emulation_finish(void); +@@ -76,7 +76,7 @@ static inline bool unaligned_ctl_available(void) + } + #endif + +-bool check_vector_unaligned_access_emulated_all_cpus(void); ++bool __init check_vector_unaligned_access_emulated_all_cpus(void); + #if defined(CONFIG_RISCV_VECTOR_MISALIGNED) + void check_vector_unaligned_access_emulated(struct work_struct *work __always_unused); + DECLARE_PER_CPU(long, vector_misaligned_access); +diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c +index 7cc108aed74e8..aacbd9d7196e7 100644 +--- a/arch/riscv/kernel/traps_misaligned.c ++++ b/arch/riscv/kernel/traps_misaligned.c +@@ -605,7 +605,7 @@ void check_vector_unaligned_access_emulated(struct work_struct *work __always_un + kernel_vector_end(); + } + +-bool check_vector_unaligned_access_emulated_all_cpus(void) ++bool __init check_vector_unaligned_access_emulated_all_cpus(void) + { + int cpu; + +@@ -625,7 +625,7 @@ bool check_vector_unaligned_access_emulated_all_cpus(void) + return true; + } + #else +-bool check_vector_unaligned_access_emulated_all_cpus(void) ++bool __init check_vector_unaligned_access_emulated_all_cpus(void) + { + return false; + } +@@ -659,7 +659,7 @@ void check_unaligned_access_emulated(struct work_struct *work __always_unused) + } + } + +-bool check_unaligned_access_emulated_all_cpus(void) ++bool __init check_unaligned_access_emulated_all_cpus(void) + { + int cpu; + +@@ -684,7 +684,7 @@ bool unaligned_ctl_available(void) + return unaligned_ctl; + } + #else +-bool check_unaligned_access_emulated_all_cpus(void) ++bool __init check_unaligned_access_emulated_all_cpus(void) + { + return false; + } +diff --git a/arch/riscv/kernel/unaligned_access_speed.c b/arch/riscv/kernel/unaligned_access_speed.c +index 074ac4abd023e..85c868a8cee63 100644 +--- a/arch/riscv/kernel/unaligned_access_speed.c ++++ b/arch/riscv/kernel/unaligned_access_speed.c +@@ -121,7 +121,7 @@ static int check_unaligned_access(void *param) + return 0; + } + +-static void check_unaligned_access_nonboot_cpu(void *param) ++static void __init check_unaligned_access_nonboot_cpu(void *param) + { + unsigned int cpu = smp_processor_id(); + struct page **pages = param; +@@ -175,7 +175,7 @@ static void set_unaligned_access_static_branches(void) + modify_unaligned_access_branches(&fast_and_online, num_online_cpus()); + } + +-static int lock_and_set_unaligned_access_static_branch(void) ++static int __init lock_and_set_unaligned_access_static_branch(void) + { + cpus_read_lock(); + set_unaligned_access_static_branches(); +@@ -218,7 +218,7 @@ static int riscv_offline_cpu(unsigned int cpu) + } + + /* Measure unaligned access speed on all CPUs present at boot in parallel. */ +-static int check_unaligned_access_speed_all_cpus(void) ++static int __init check_unaligned_access_speed_all_cpus(void) + { + unsigned int cpu; + unsigned int cpu_count = num_possible_cpus(); +@@ -264,7 +264,7 @@ static int check_unaligned_access_speed_all_cpus(void) + return 0; + } + #else /* CONFIG_RISCV_PROBE_UNALIGNED_ACCESS */ +-static int check_unaligned_access_speed_all_cpus(void) ++static int __init check_unaligned_access_speed_all_cpus(void) + { + return 0; + } +@@ -382,7 +382,7 @@ static int riscv_online_cpu_vec(unsigned int cpu) + } + + /* Measure unaligned access speed on all CPUs present at boot in parallel. */ +-static int vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused) ++static int __init vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused) + { + schedule_on_each_cpu(check_vector_unaligned_access); + +@@ -396,13 +396,13 @@ static int vec_check_unaligned_access_speed_all_cpus(void *unused __always_unuse + return 0; + } + #else /* CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS */ +-static int vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused) ++static int __init vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused) + { + return 0; + } + #endif + +-static int check_unaligned_access_all_cpus(void) ++static int __init check_unaligned_access_all_cpus(void) + { + bool all_cpus_emulated, all_cpus_vec_unsupported; + +-- +2.39.5 + diff --git a/queue-6.14/riscv-change-check_unaligned_access_speed_all_cpus-t.patch b/queue-6.14/riscv-change-check_unaligned_access_speed_all_cpus-t.patch new file mode 100644 index 0000000000..ea95f4aecc --- /dev/null +++ b/queue-6.14/riscv-change-check_unaligned_access_speed_all_cpus-t.patch @@ -0,0 +1,90 @@ +From 6b5398627c7e07dd84d8d562643cf7678197eb82 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 13:00:19 +0100 +Subject: riscv: Change check_unaligned_access_speed_all_cpus to void +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Andrew Jones + +[ Upstream commit 813d39baee3229d31420af61460b97f4fafdd352 ] + +The return value of check_unaligned_access_speed_all_cpus() is always +zero, so make the function void so we don't need to concern ourselves +with it. The change also allows us to tidy up +check_unaligned_access_all_cpus() a bit. + +Reviewed-by: Clément Léger +Reviewed-by: Alexandre Ghiti +Signed-off-by: Andrew Jones +Link: https://lore.kernel.org/r/20250304120014.143628-14-ajones@ventanamicro.com +Signed-off-by: Alexandre Ghiti +Stable-dep-of: 05ee21f0fcb8 ("riscv: Fix set up of cpu hotplug callbacks") +Signed-off-by: Sasha Levin +--- + arch/riscv/kernel/unaligned_access_speed.c | 15 +++++---------- + 1 file changed, 5 insertions(+), 10 deletions(-) + +diff --git a/arch/riscv/kernel/unaligned_access_speed.c b/arch/riscv/kernel/unaligned_access_speed.c +index 78ab4cb2ab050..bca798153e37d 100644 +--- a/arch/riscv/kernel/unaligned_access_speed.c ++++ b/arch/riscv/kernel/unaligned_access_speed.c +@@ -218,7 +218,7 @@ static int riscv_offline_cpu(unsigned int cpu) + } + + /* Measure unaligned access speed on all CPUs present at boot in parallel. */ +-static int __init check_unaligned_access_speed_all_cpus(void) ++static void __init check_unaligned_access_speed_all_cpus(void) + { + unsigned int cpu; + unsigned int cpu_count = num_possible_cpus(); +@@ -226,7 +226,7 @@ static int __init check_unaligned_access_speed_all_cpus(void) + + if (!bufs) { + pr_warn("Allocation failure, not measuring misaligned performance\n"); +- return 0; ++ return; + } + + /* +@@ -261,12 +261,10 @@ static int __init check_unaligned_access_speed_all_cpus(void) + } + + kfree(bufs); +- return 0; + } + #else /* CONFIG_RISCV_PROBE_UNALIGNED_ACCESS */ +-static int __init check_unaligned_access_speed_all_cpus(void) ++static void __init check_unaligned_access_speed_all_cpus(void) + { +- return 0; + } + #endif + +@@ -406,10 +404,10 @@ static int __init vec_check_unaligned_access_speed_all_cpus(void *unused __alway + + static int __init check_unaligned_access_all_cpus(void) + { +- bool all_cpus_emulated; + int cpu; + +- all_cpus_emulated = check_unaligned_access_emulated_all_cpus(); ++ if (!check_unaligned_access_emulated_all_cpus()) ++ check_unaligned_access_speed_all_cpus(); + + if (!has_vector()) { + for_each_online_cpu(cpu) +@@ -420,9 +418,6 @@ static int __init check_unaligned_access_all_cpus(void) + NULL, "vec_check_unaligned_access_speed_all_cpus"); + } + +- if (!all_cpus_emulated) +- return check_unaligned_access_speed_all_cpus(); +- + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/riscv-fgraph-fix-stack-layout-to-match-__arch_ftrace.patch b/queue-6.14/riscv-fgraph-fix-stack-layout-to-match-__arch_ftrace.patch new file mode 100644 index 0000000000..e5111c3351 --- /dev/null +++ b/queue-6.14/riscv-fgraph-fix-stack-layout-to-match-__arch_ftrace.patch @@ -0,0 +1,127 @@ +From 87d4b04edf75dfcb0e1d35eb9a4145c370c91814 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 03:12:14 +0000 +Subject: riscv: fgraph: Fix stack layout to match __arch_ftrace_regs argument + of ftrace_return_to_handler +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pu Lehui + +[ Upstream commit 67a5ba8f742f247bc83e46dd2313c142b1383276 ] + +Naresh Kamboju reported a "Bad frame pointer" kernel warning while +running LTP trace ftrace_stress_test.sh in riscv. We can reproduce the +same issue with the following command: + +``` +$ cd /sys/kernel/debug/tracing +$ echo 'f:myprobe do_nanosleep%return args1=$retval' > dynamic_events +$ echo 1 > events/fprobes/enable +$ echo 1 > tracing_on +$ sleep 1 +``` + +And we can get the following kernel warning: + +[ 127.692888] ------------[ cut here ]------------ +[ 127.693755] Bad frame pointer: expected ff2000000065be50, received ba34c141e9594000 +[ 127.693755] from func do_nanosleep return to ffffffff800ccb16 +[ 127.698699] WARNING: CPU: 1 PID: 129 at kernel/trace/fgraph.c:755 ftrace_return_to_handler+0x1b2/0x1be +[ 127.699894] Modules linked in: +[ 127.700908] CPU: 1 UID: 0 PID: 129 Comm: sleep Not tainted 6.14.0-rc3-g0ab191c74642 #32 +[ 127.701453] Hardware name: riscv-virtio,qemu (DT) +[ 127.701859] epc : ftrace_return_to_handler+0x1b2/0x1be +[ 127.702032] ra : ftrace_return_to_handler+0x1b2/0x1be +[ 127.702151] epc : ffffffff8013b5e0 ra : ffffffff8013b5e0 sp : ff2000000065bd10 +[ 127.702221] gp : ffffffff819c12f8 tp : ff60000080853100 t0 : 6e00000000000000 +[ 127.702284] t1 : 0000000000000020 t2 : 6e7566206d6f7266 s0 : ff2000000065bd80 +[ 127.702346] s1 : ff60000081262000 a0 : 000000000000007b a1 : ffffffff81894f20 +[ 127.702408] a2 : 0000000000000010 a3 : fffffffffffffffe a4 : 0000000000000000 +[ 127.702470] a5 : 0000000000000000 a6 : 0000000000000008 a7 : 0000000000000038 +[ 127.702530] s2 : ba34c141e9594000 s3 : 0000000000000000 s4 : ff2000000065bdd0 +[ 127.702591] s5 : 00007fff8adcf400 s6 : 000055556dc1d8c0 s7 : 0000000000000068 +[ 127.702651] s8 : 00007fff8adf5d10 s9 : 000000000000006d s10: 0000000000000001 +[ 127.702710] s11: 00005555737377c8 t3 : ffffffff819d899e t4 : ffffffff819d899e +[ 127.702769] t5 : ffffffff819d89a0 t6 : ff2000000065bb18 +[ 127.702826] status: 0000000200000120 badaddr: 0000000000000000 cause: 0000000000000003 +[ 127.703292] [] ftrace_return_to_handler+0x1b2/0x1be +[ 127.703760] [] return_to_handler+0x16/0x26 +[ 127.704009] [] return_to_handler+0x0/0x26 +[ 127.704057] [] common_nsleep+0x42/0x54 +[ 127.704117] [] __riscv_sys_clock_nanosleep+0xba/0x10a +[ 127.704176] [] do_trap_ecall_u+0x188/0x218 +[ 127.704295] [] handle_exception+0x14a/0x156 +[ 127.705436] ---[ end trace 0000000000000000 ]--- + +The reason is that the stack layout for constructing argument for the +ftrace_return_to_handler in the return_to_handler does not match the +__arch_ftrace_regs structure of riscv, leading to unexpected results. + +Fixes: a3ed4157b7d8 ("fgraph: Replace fgraph_ret_regs with ftrace_regs") +Reported-by: Linux Kernel Functional Testing +Closes: https://lore.kernel.org/all/CA+G9fYvp_oAxeDFj88Tk2rfEZ7jtYKAKSwfYS66=57Db9TBdyA@mail.gmail.com +Signed-off-by: Pu Lehui +Reviewed-by: Alexandre Ghiti +Tested-by: Björn Töpel +Reviewed-by: Masami Hiramatsu (Google) +Link: https://lore.kernel.org/r/20250317031214.4138436-2-pulehui@huaweicloud.com +Signed-off-by: Alexandre Ghiti +Signed-off-by: Sasha Levin +--- + arch/riscv/kernel/mcount.S | 24 +++++++++++------------- + 1 file changed, 11 insertions(+), 13 deletions(-) + +diff --git a/arch/riscv/kernel/mcount.S b/arch/riscv/kernel/mcount.S +index 068168046e0ef..da4a4000e57ea 100644 +--- a/arch/riscv/kernel/mcount.S ++++ b/arch/riscv/kernel/mcount.S +@@ -12,8 +12,6 @@ + #include + #include + +-#define ABI_SIZE_ON_STACK 80 +- + .text + + .macro SAVE_ABI_STATE +@@ -28,12 +26,12 @@ + * register if a0 was not saved. + */ + .macro SAVE_RET_ABI_STATE +- addi sp, sp, -ABI_SIZE_ON_STACK +- REG_S ra, 1*SZREG(sp) +- REG_S s0, 8*SZREG(sp) +- REG_S a0, 10*SZREG(sp) +- REG_S a1, 11*SZREG(sp) +- addi s0, sp, ABI_SIZE_ON_STACK ++ addi sp, sp, -FREGS_SIZE_ON_STACK ++ REG_S ra, FREGS_RA(sp) ++ REG_S s0, FREGS_S0(sp) ++ REG_S a0, FREGS_A0(sp) ++ REG_S a1, FREGS_A1(sp) ++ addi s0, sp, FREGS_SIZE_ON_STACK + .endm + + .macro RESTORE_ABI_STATE +@@ -43,11 +41,11 @@ + .endm + + .macro RESTORE_RET_ABI_STATE +- REG_L ra, 1*SZREG(sp) +- REG_L s0, 8*SZREG(sp) +- REG_L a0, 10*SZREG(sp) +- REG_L a1, 11*SZREG(sp) +- addi sp, sp, ABI_SIZE_ON_STACK ++ REG_L ra, FREGS_RA(sp) ++ REG_L s0, FREGS_S0(sp) ++ REG_L a0, FREGS_A0(sp) ++ REG_L a1, FREGS_A1(sp) ++ addi sp, sp, FREGS_SIZE_ON_STACK + .endm + + SYM_TYPED_FUNC_START(ftrace_stub) +-- +2.39.5 + diff --git a/queue-6.14/riscv-fgraph-select-have_function_graph_tracer-depen.patch b/queue-6.14/riscv-fgraph-select-have_function_graph_tracer-depen.patch new file mode 100644 index 0000000000..a79f72a438 --- /dev/null +++ b/queue-6.14/riscv-fgraph-select-have_function_graph_tracer-depen.patch @@ -0,0 +1,47 @@ +From a5bb6f4efdad4106634c4cc4441b7b8ea3eca9c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 03:12:13 +0000 +Subject: riscv: fgraph: Select HAVE_FUNCTION_GRAPH_TRACER depends on + HAVE_DYNAMIC_FTRACE_WITH_ARGS +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pu Lehui + +[ Upstream commit e8eb8e1bdae94b9e003f5909519fd311d0936890 ] + +Currently, fgraph on riscv relies on the infrastructure of +DYNAMIC_FTRACE_WITH_ARGS. However, DYNAMIC_FTRACE_WITH_ARGS may be +turned off on riscv, which will cause the enabled fgraph to be abnormal. +Therefore, let's select HAVE_FUNCTION_GRAPH_TRACER depends on +HAVE_DYNAMIC_FTRACE_WITH_ARGS. + +Fixes: a3ed4157b7d8 ("fgraph: Replace fgraph_ret_regs with ftrace_regs") +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202503160820.dvqMpH0g-lkp@intel.com/ +Signed-off-by: Pu Lehui +Reviewed-by: Björn Töpel +Link: https://lore.kernel.org/r/20250317031214.4138436-1-pulehui@huaweicloud.com +Signed-off-by: Alexandre Ghiti +Signed-off-by: Sasha Levin +--- + arch/riscv/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig +index 7612c52e9b1e3..5d63abc499ce7 100644 +--- a/arch/riscv/Kconfig ++++ b/arch/riscv/Kconfig +@@ -149,7 +149,7 @@ config RISCV + select HAVE_DYNAMIC_FTRACE_WITH_ARGS if HAVE_DYNAMIC_FTRACE + select HAVE_FTRACE_GRAPH_FUNC + select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL +- select HAVE_FUNCTION_GRAPH_TRACER ++ select HAVE_FUNCTION_GRAPH_TRACER if HAVE_DYNAMIC_FTRACE_WITH_ARGS + select HAVE_FUNCTION_GRAPH_FREGS + select HAVE_FUNCTION_TRACER if !XIP_KERNEL && !PREEMPTION + select HAVE_EBPF_JIT if MMU +-- +2.39.5 + diff --git a/queue-6.14/riscv-fix-check_unaligned_access_all_cpus.patch b/queue-6.14/riscv-fix-check_unaligned_access_all_cpus.patch new file mode 100644 index 0000000000..d1da0e396a --- /dev/null +++ b/queue-6.14/riscv-fix-check_unaligned_access_all_cpus.patch @@ -0,0 +1,77 @@ +From 756818f07a8bba02f7d341feb1cf6f1083ad25ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 13:00:18 +0100 +Subject: riscv: Fix check_unaligned_access_all_cpus + +From: Andrew Jones + +[ Upstream commit e6d0adf2eb5bb3244cb21a7a15899aa058bd384f ] + +check_vector_unaligned_access_emulated_all_cpus(), like its name +suggests, will return true when all cpus emulate unaligned vector +accesses. If the function returned false it may have been because +vector isn't supported at all (!has_vector()) or because at least +one cpu doesn't emulate unaligned vector accesses. Since false may +be returned for two cases, checking for it isn't sufficient when +attempting to determine if we should proceed with the vector speed +check. Move the !has_vector() functionality to +check_unaligned_access_all_cpus() in order for +check_vector_unaligned_access_emulated_all_cpus() to return false +for a single case. + +Fixes: e7c9d66e313b ("RISC-V: Report vector unaligned access speed hwprobe") +Reviewed-by: Alexandre Ghiti +Signed-off-by: Andrew Jones +Link: https://lore.kernel.org/r/20250304120014.143628-13-ajones@ventanamicro.com +Signed-off-by: Alexandre Ghiti +Signed-off-by: Sasha Levin +--- + arch/riscv/kernel/traps_misaligned.c | 6 ------ + arch/riscv/kernel/unaligned_access_speed.c | 11 +++++++---- + 2 files changed, 7 insertions(+), 10 deletions(-) + +diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c +index aacbd9d7196e7..4354c87c0376f 100644 +--- a/arch/riscv/kernel/traps_misaligned.c ++++ b/arch/riscv/kernel/traps_misaligned.c +@@ -609,12 +609,6 @@ bool __init check_vector_unaligned_access_emulated_all_cpus(void) + { + int cpu; + +- if (!has_vector()) { +- for_each_online_cpu(cpu) +- per_cpu(vector_misaligned_access, cpu) = RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED; +- return false; +- } +- + schedule_on_each_cpu(check_vector_unaligned_access_emulated); + + for_each_online_cpu(cpu) +diff --git a/arch/riscv/kernel/unaligned_access_speed.c b/arch/riscv/kernel/unaligned_access_speed.c +index 2e41b42498c76..78ab4cb2ab050 100644 +--- a/arch/riscv/kernel/unaligned_access_speed.c ++++ b/arch/riscv/kernel/unaligned_access_speed.c +@@ -406,13 +406,16 @@ static int __init vec_check_unaligned_access_speed_all_cpus(void *unused __alway + + static int __init check_unaligned_access_all_cpus(void) + { +- bool all_cpus_emulated, all_cpus_vec_unsupported; ++ bool all_cpus_emulated; ++ int cpu; + + all_cpus_emulated = check_unaligned_access_emulated_all_cpus(); +- all_cpus_vec_unsupported = check_vector_unaligned_access_emulated_all_cpus(); + +- if (!all_cpus_vec_unsupported && +- IS_ENABLED(CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS)) { ++ if (!has_vector()) { ++ for_each_online_cpu(cpu) ++ per_cpu(vector_misaligned_access, cpu) = RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED; ++ } else if (!check_vector_unaligned_access_emulated_all_cpus() && ++ IS_ENABLED(CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS)) { + kthread_run(vec_check_unaligned_access_speed_all_cpus, + NULL, "vec_check_unaligned_access_speed_all_cpus"); + } +-- +2.39.5 + diff --git a/queue-6.14/riscv-fix-hugetlb-retrieval-of-number-of-ptes-in-cas.patch b/queue-6.14/riscv-fix-hugetlb-retrieval-of-number-of-ptes-in-cas.patch new file mode 100644 index 0000000000..7d8f3dfd7e --- /dev/null +++ b/queue-6.14/riscv-fix-hugetlb-retrieval-of-number-of-ptes-in-cas.patch @@ -0,0 +1,162 @@ +From 8905ee3a725f2b538a19cb73f00aa46b59989140 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 08:25:51 +0100 +Subject: riscv: Fix hugetlb retrieval of number of ptes in case of !present + pte + +From: Alexandre Ghiti + +[ Upstream commit 83d78ac677b9fdd8ea763507c6fe02d6bf415f3a ] + +Ryan sent a fix [1] for arm64 that applies to riscv too: in some hugetlb +functions, we must not use the pte value to get the size of a mapping +because the pte may not be present. + +So use the already present size parameter for huge_pte_clear() and the +newly introduced size parameter for huge_ptep_get_and_clear(). And make +sure to gather A/D bits only on present ptes. + +Fixes: 82a1a1f3bfb6 ("riscv: mm: support Svnapot in hugetlb page") +Link: https://lore.kernel.org/all/20250217140419.1702389-1-ryan.roberts@arm.com/ [1] +Link: https://lore.kernel.org/r/20250317072551.572169-1-alexghiti@rivosinc.com +Signed-off-by: Alexandre Ghiti +Signed-off-by: Sasha Levin +--- + arch/riscv/mm/hugetlbpage.c | 76 ++++++++++++++++++++++--------------- + 1 file changed, 45 insertions(+), 31 deletions(-) + +diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c +index b4a78a4b35cff..375dd96bb4a0d 100644 +--- a/arch/riscv/mm/hugetlbpage.c ++++ b/arch/riscv/mm/hugetlbpage.c +@@ -148,22 +148,25 @@ unsigned long hugetlb_mask_last_page(struct hstate *h) + static pte_t get_clear_contig(struct mm_struct *mm, + unsigned long addr, + pte_t *ptep, +- unsigned long pte_num) ++ unsigned long ncontig) + { +- pte_t orig_pte = ptep_get(ptep); +- unsigned long i; +- +- for (i = 0; i < pte_num; i++, addr += PAGE_SIZE, ptep++) { +- pte_t pte = ptep_get_and_clear(mm, addr, ptep); +- +- if (pte_dirty(pte)) +- orig_pte = pte_mkdirty(orig_pte); +- +- if (pte_young(pte)) +- orig_pte = pte_mkyoung(orig_pte); ++ pte_t pte, tmp_pte; ++ bool present; ++ ++ pte = ptep_get_and_clear(mm, addr, ptep); ++ present = pte_present(pte); ++ while (--ncontig) { ++ ptep++; ++ addr += PAGE_SIZE; ++ tmp_pte = ptep_get_and_clear(mm, addr, ptep); ++ if (present) { ++ if (pte_dirty(tmp_pte)) ++ pte = pte_mkdirty(pte); ++ if (pte_young(tmp_pte)) ++ pte = pte_mkyoung(pte); ++ } + } +- +- return orig_pte; ++ return pte; + } + + static pte_t get_clear_contig_flush(struct mm_struct *mm, +@@ -212,6 +215,26 @@ static void clear_flush(struct mm_struct *mm, + flush_tlb_range(&vma, saddr, addr); + } + ++static int num_contig_ptes_from_size(unsigned long sz, size_t *pgsize) ++{ ++ unsigned long hugepage_shift; ++ ++ if (sz >= PGDIR_SIZE) ++ hugepage_shift = PGDIR_SHIFT; ++ else if (sz >= P4D_SIZE) ++ hugepage_shift = P4D_SHIFT; ++ else if (sz >= PUD_SIZE) ++ hugepage_shift = PUD_SHIFT; ++ else if (sz >= PMD_SIZE) ++ hugepage_shift = PMD_SHIFT; ++ else ++ hugepage_shift = PAGE_SHIFT; ++ ++ *pgsize = 1 << hugepage_shift; ++ ++ return sz >> hugepage_shift; ++} ++ + /* + * When dealing with NAPOT mappings, the privileged specification indicates that + * "if an update needs to be made, the OS generally should first mark all of the +@@ -226,22 +249,10 @@ void set_huge_pte_at(struct mm_struct *mm, + pte_t pte, + unsigned long sz) + { +- unsigned long hugepage_shift, pgsize; ++ size_t pgsize; + int i, pte_num; + +- if (sz >= PGDIR_SIZE) +- hugepage_shift = PGDIR_SHIFT; +- else if (sz >= P4D_SIZE) +- hugepage_shift = P4D_SHIFT; +- else if (sz >= PUD_SIZE) +- hugepage_shift = PUD_SHIFT; +- else if (sz >= PMD_SIZE) +- hugepage_shift = PMD_SHIFT; +- else +- hugepage_shift = PAGE_SHIFT; +- +- pte_num = sz >> hugepage_shift; +- pgsize = 1 << hugepage_shift; ++ pte_num = num_contig_ptes_from_size(sz, &pgsize); + + if (!pte_present(pte)) { + for (i = 0; i < pte_num; i++, ptep++, addr += pgsize) +@@ -295,13 +306,14 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, + unsigned long addr, + pte_t *ptep, unsigned long sz) + { ++ size_t pgsize; + pte_t orig_pte = ptep_get(ptep); + int pte_num; + + if (!pte_napot(orig_pte)) + return ptep_get_and_clear(mm, addr, ptep); + +- pte_num = napot_pte_num(napot_cont_order(orig_pte)); ++ pte_num = num_contig_ptes_from_size(sz, &pgsize); + + return get_clear_contig(mm, addr, ptep, pte_num); + } +@@ -351,6 +363,7 @@ void huge_pte_clear(struct mm_struct *mm, + pte_t *ptep, + unsigned long sz) + { ++ size_t pgsize; + pte_t pte = ptep_get(ptep); + int i, pte_num; + +@@ -359,8 +372,9 @@ void huge_pte_clear(struct mm_struct *mm, + return; + } + +- pte_num = napot_pte_num(napot_cont_order(pte)); +- for (i = 0; i < pte_num; i++, addr += PAGE_SIZE, ptep++) ++ pte_num = num_contig_ptes_from_size(sz, &pgsize); ++ ++ for (i = 0; i < pte_num; i++, addr += pgsize, ptep++) + pte_clear(mm, addr, ptep); + } + +-- +2.39.5 + diff --git a/queue-6.14/riscv-fix-missing-__free_pages-in-check_vector_unali.patch b/queue-6.14/riscv-fix-missing-__free_pages-in-check_vector_unali.patch new file mode 100644 index 0000000000..6034476fb0 --- /dev/null +++ b/queue-6.14/riscv-fix-missing-__free_pages-in-check_vector_unali.patch @@ -0,0 +1,46 @@ +From 4216e172bf91e72e4f4b9e3a40ea9afa978189c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 10:06:13 +0100 +Subject: riscv: Fix missing __free_pages() in check_vector_unaligned_access() + +From: Alexandre Ghiti + +[ Upstream commit 33981b1c4e499021421686dcfa7b3d23a430d00e ] + +The locally allocated pages are never freed up, so add the corresponding +__free_pages(). + +Fixes: e7c9d66e313b ("RISC-V: Report vector unaligned access speed hwprobe") +Link: https://lore.kernel.org/r/20250228090613.345309-1-alexghiti@rivosinc.com +Signed-off-by: Alexandre Ghiti +Signed-off-by: Sasha Levin +--- + arch/riscv/kernel/unaligned_access_speed.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/arch/riscv/kernel/unaligned_access_speed.c b/arch/riscv/kernel/unaligned_access_speed.c +index 91f189cf16113..074ac4abd023e 100644 +--- a/arch/riscv/kernel/unaligned_access_speed.c ++++ b/arch/riscv/kernel/unaligned_access_speed.c +@@ -349,7 +349,7 @@ static void check_vector_unaligned_access(struct work_struct *work __always_unus + pr_warn("cpu%d: rdtime lacks granularity needed to measure unaligned vector access speed\n", + cpu); + +- return; ++ goto free; + } + + if (word_cycles < byte_cycles) +@@ -363,6 +363,9 @@ static void check_vector_unaligned_access(struct work_struct *work __always_unus + (speed == RISCV_HWPROBE_MISALIGNED_VECTOR_FAST) ? "fast" : "slow"); + + per_cpu(vector_misaligned_access, cpu) = speed; ++ ++free: ++ __free_pages(page, MISALIGNED_BUFFER_ORDER); + } + + static int riscv_online_cpu_vec(unsigned int cpu) +-- +2.39.5 + diff --git a/queue-6.14/riscv-fix-riscv_online_cpu_vec.patch b/queue-6.14/riscv-fix-riscv_online_cpu_vec.patch new file mode 100644 index 0000000000..aa96c9cb54 --- /dev/null +++ b/queue-6.14/riscv-fix-riscv_online_cpu_vec.patch @@ -0,0 +1,46 @@ +From 8483214a8dd409e7edd118c2783aab932b5f2556 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 13:00:17 +0100 +Subject: riscv: Fix riscv_online_cpu_vec + +From: Andrew Jones + +[ Upstream commit 5af72a818612332a11171b16f27a62ec0a0f91d7 ] + +We shouldn't probe when we already know vector is unsupported and +we should probe when we see we don't yet know whether it's supported. +Furthermore, we should ensure we've set the access type to +unsupported when we don't have vector at all. + +Fixes: e7c9d66e313b ("RISC-V: Report vector unaligned access speed hwprobe") +Reviewed-by: Alexandre Ghiti +Signed-off-by: Andrew Jones +Link: https://lore.kernel.org/r/20250304120014.143628-12-ajones@ventanamicro.com +Signed-off-by: Alexandre Ghiti +Signed-off-by: Sasha Levin +--- + arch/riscv/kernel/unaligned_access_speed.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/arch/riscv/kernel/unaligned_access_speed.c b/arch/riscv/kernel/unaligned_access_speed.c +index 85c868a8cee63..2e41b42498c76 100644 +--- a/arch/riscv/kernel/unaligned_access_speed.c ++++ b/arch/riscv/kernel/unaligned_access_speed.c +@@ -370,10 +370,12 @@ static void check_vector_unaligned_access(struct work_struct *work __always_unus + + static int riscv_online_cpu_vec(unsigned int cpu) + { +- if (!has_vector()) ++ if (!has_vector()) { ++ per_cpu(vector_misaligned_access, cpu) = RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED; + return 0; ++ } + +- if (per_cpu(vector_misaligned_access, cpu) != RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED) ++ if (per_cpu(vector_misaligned_access, cpu) != RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN) + return 0; + + check_vector_unaligned_access_emulated(NULL); +-- +2.39.5 + diff --git a/queue-6.14/riscv-fix-set-up-of-cpu-hotplug-callbacks.patch b/queue-6.14/riscv-fix-set-up-of-cpu-hotplug-callbacks.patch new file mode 100644 index 0000000000..2b4b3a7d67 --- /dev/null +++ b/queue-6.14/riscv-fix-set-up-of-cpu-hotplug-callbacks.patch @@ -0,0 +1,83 @@ +From a4f06d506a6e1d4b5f43098a4710857c514e3367 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 13:00:20 +0100 +Subject: riscv: Fix set up of cpu hotplug callbacks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Andrew Jones + +[ Upstream commit 05ee21f0fcb8ca29bf42bd6cbce109f2e49c167f ] + +CPU hotplug callbacks should be set up even if we detected all +current cpus emulate misaligned accesses, since we want to +ensure our expectations of all cpus emulating is maintained. + +Fixes: 6e5ce7f2eae3 ("riscv: Decouple emulated unaligned accesses from access speed") +Fixes: e7c9d66e313b ("RISC-V: Report vector unaligned access speed hwprobe") +Reviewed-by: Clément Léger +Reviewed-by: Alexandre Ghiti +Signed-off-by: Andrew Jones +Link: https://lore.kernel.org/r/20250304120014.143628-15-ajones@ventanamicro.com +Signed-off-by: Alexandre Ghiti +Signed-off-by: Sasha Levin +--- + arch/riscv/kernel/unaligned_access_speed.c | 27 +++++++++++----------- + 1 file changed, 13 insertions(+), 14 deletions(-) + +diff --git a/arch/riscv/kernel/unaligned_access_speed.c b/arch/riscv/kernel/unaligned_access_speed.c +index bca798153e37d..84694a44f3da4 100644 +--- a/arch/riscv/kernel/unaligned_access_speed.c ++++ b/arch/riscv/kernel/unaligned_access_speed.c +@@ -247,13 +247,6 @@ static void __init check_unaligned_access_speed_all_cpus(void) + /* Check core 0. */ + smp_call_on_cpu(0, check_unaligned_access, bufs[0], true); + +- /* +- * Setup hotplug callbacks for any new CPUs that come online or go +- * offline. +- */ +- cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "riscv:online", +- riscv_online_cpu, riscv_offline_cpu); +- + out: + for_each_cpu(cpu, cpu_online_mask) { + if (bufs[cpu]) +@@ -386,13 +379,6 @@ static int __init vec_check_unaligned_access_speed_all_cpus(void *unused __alway + { + schedule_on_each_cpu(check_vector_unaligned_access); + +- /* +- * Setup hotplug callbacks for any new CPUs that come online or go +- * offline. +- */ +- cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "riscv:online", +- riscv_online_cpu_vec, NULL); +- + return 0; + } + #else /* CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS */ +@@ -418,6 +404,19 @@ static int __init check_unaligned_access_all_cpus(void) + NULL, "vec_check_unaligned_access_speed_all_cpus"); + } + ++ /* ++ * Setup hotplug callbacks for any new CPUs that come online or go ++ * offline. ++ */ ++#ifdef CONFIG_RISCV_PROBE_UNALIGNED_ACCESS ++ cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "riscv:online", ++ riscv_online_cpu, riscv_offline_cpu); ++#endif ++#ifdef CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS ++ cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "riscv:online", ++ riscv_online_cpu_vec, NULL); ++#endif ++ + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/riscv-fix-set-up-of-vector-cpu-hotplug-callback.patch b/queue-6.14/riscv-fix-set-up-of-vector-cpu-hotplug-callback.patch new file mode 100644 index 0000000000..571e1fd28b --- /dev/null +++ b/queue-6.14/riscv-fix-set-up-of-vector-cpu-hotplug-callback.patch @@ -0,0 +1,94 @@ +From d0795006384749d350750864f475cf2166235b2c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 13:00:21 +0100 +Subject: riscv: Fix set up of vector cpu hotplug callback + +From: Andrew Jones + +[ Upstream commit 2744ec472de31141ad354907ff98843dd6040917 ] + +Whether or not we have RISCV_PROBE_VECTOR_UNALIGNED_ACCESS we need to +set up a cpu hotplug callback to check if we have vector at all, +since, when we don't have vector, we need to set +vector_misaligned_access to unsupported rather than leave it the +default of unknown. + +Fixes: e7c9d66e313b ("RISC-V: Report vector unaligned access speed hwprobe") +Reviewed-by: Alexandre Ghiti +Signed-off-by: Andrew Jones +Link: https://lore.kernel.org/r/20250304120014.143628-16-ajones@ventanamicro.com +Signed-off-by: Alexandre Ghiti +Signed-off-by: Sasha Levin +--- + arch/riscv/kernel/unaligned_access_speed.c | 31 +++++++++++----------- + 1 file changed, 16 insertions(+), 15 deletions(-) + +diff --git a/arch/riscv/kernel/unaligned_access_speed.c b/arch/riscv/kernel/unaligned_access_speed.c +index 84694a44f3da4..a42115fbdeb89 100644 +--- a/arch/riscv/kernel/unaligned_access_speed.c ++++ b/arch/riscv/kernel/unaligned_access_speed.c +@@ -359,6 +359,20 @@ static void check_vector_unaligned_access(struct work_struct *work __always_unus + __free_pages(page, MISALIGNED_BUFFER_ORDER); + } + ++/* Measure unaligned access speed on all CPUs present at boot in parallel. */ ++static int __init vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused) ++{ ++ schedule_on_each_cpu(check_vector_unaligned_access); ++ ++ return 0; ++} ++#else /* CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS */ ++static int __init vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused) ++{ ++ return 0; ++} ++#endif ++ + static int riscv_online_cpu_vec(unsigned int cpu) + { + if (!has_vector()) { +@@ -366,27 +380,16 @@ static int riscv_online_cpu_vec(unsigned int cpu) + return 0; + } + ++#ifdef CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS + if (per_cpu(vector_misaligned_access, cpu) != RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN) + return 0; + + check_vector_unaligned_access_emulated(NULL); + check_vector_unaligned_access(NULL); +- return 0; +-} +- +-/* Measure unaligned access speed on all CPUs present at boot in parallel. */ +-static int __init vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused) +-{ +- schedule_on_each_cpu(check_vector_unaligned_access); ++#endif + + return 0; + } +-#else /* CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS */ +-static int __init vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused) +-{ +- return 0; +-} +-#endif + + static int __init check_unaligned_access_all_cpus(void) + { +@@ -412,10 +415,8 @@ static int __init check_unaligned_access_all_cpus(void) + cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "riscv:online", + riscv_online_cpu, riscv_offline_cpu); + #endif +-#ifdef CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS + cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "riscv:online", + riscv_online_cpu_vec, NULL); +-#endif + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/riscv-fix-the-__riscv_copy_vec_words_unaligned-imple.patch b/queue-6.14/riscv-fix-the-__riscv_copy_vec_words_unaligned-imple.patch new file mode 100644 index 0000000000..d97124c671 --- /dev/null +++ b/queue-6.14/riscv-fix-the-__riscv_copy_vec_words_unaligned-imple.patch @@ -0,0 +1,38 @@ +From ca8633c42558b48bad67a684f326524a6f5fbe87 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 01:08:01 -0800 +Subject: riscv: Fix the __riscv_copy_vec_words_unaligned implementation + +From: Tingbo Liao + +[ Upstream commit 475afa39b123699e910c61ad9a51cedce4a0d310 ] + +Correct the VEC_S macro definition to fix the implementation +of vector words copy in the case of unalignment in RISC-V. + +Fixes: e7c9d66e313b ("RISC-V: Report vector unaligned access speed hwprobe") +Reviewed-by: Alexandre Ghiti +Signed-off-by: Tingbo Liao +Link: https://lore.kernel.org/r/20250228090801.8334-1-tingbo.liao@starfivetech.com +Signed-off-by: Alexandre Ghiti +Signed-off-by: Sasha Levin +--- + arch/riscv/kernel/vec-copy-unaligned.S | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/riscv/kernel/vec-copy-unaligned.S b/arch/riscv/kernel/vec-copy-unaligned.S +index d16f19f1b3b65..7ce4de6f6e694 100644 +--- a/arch/riscv/kernel/vec-copy-unaligned.S ++++ b/arch/riscv/kernel/vec-copy-unaligned.S +@@ -11,7 +11,7 @@ + + #define WORD_SEW CONCATENATE(e, WORD_EEW) + #define VEC_L CONCATENATE(vle, WORD_EEW).v +-#define VEC_S CONCATENATE(vle, WORD_EEW).v ++#define VEC_S CONCATENATE(vse, WORD_EEW).v + + /* void __riscv_copy_vec_words_unaligned(void *, const void *, size_t) */ + /* Performs a memcpy without aligning buffers, using word loads and stores. */ +-- +2.39.5 + diff --git a/queue-6.14/riscv-ftrace-add-parentheses-in-macro-definitions-of.patch b/queue-6.14/riscv-ftrace-add-parentheses-in-macro-definitions-of.patch new file mode 100644 index 0000000000..237c803fd4 --- /dev/null +++ b/queue-6.14/riscv-ftrace-add-parentheses-in-macro-definitions-of.patch @@ -0,0 +1,63 @@ +From 72856b93c8432eeaa645945f72921751887697d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 13:28:36 -0600 +Subject: riscv: ftrace: Add parentheses in macro definitions of make_call_t0 + and make_call_ra + +From: Juhan Jin + +[ Upstream commit 5f1a58ed91a040d4625d854f9bb3dd4995919202 ] + +This patch adds parentheses to parameters caller and callee of macros +make_call_t0 and make_call_ra. Every existing invocation of these two +macros uses a single variable for each argument, so the absence of the +parentheses seems okay. However, future invocations might use more +complex expressions as arguments. For example, a future invocation might +look like this: make_call_t0(a - b, c, call). Without parentheses in the +macro definition, the macro invocation expands to: + +... +unsigned int offset = (unsigned long) c - (unsigned long) a - b; +... + +which is clearly wrong. + +The use of parentheses ensures arguments are correctly evaluated and +potentially saves future users of make_call_t0 and make_call_ra debugging +trouble. + +Fixes: 6724a76cff85 ("riscv: ftrace: Reduce the detour code size to half") +Signed-off-by: Juhan Jin +Reviewed-by: Alexandre Ghiti +Link: https://lore.kernel.org/r/tencent_AE90AA59903A628E87E9F80E563DA5BA5508@qq.com +Signed-off-by: Alexandre Ghiti +Signed-off-by: Sasha Levin +--- + arch/riscv/include/asm/ftrace.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/riscv/include/asm/ftrace.h b/arch/riscv/include/asm/ftrace.h +index c4721ce44ca47..2636ee00ccf0f 100644 +--- a/arch/riscv/include/asm/ftrace.h ++++ b/arch/riscv/include/asm/ftrace.h +@@ -92,7 +92,7 @@ struct dyn_arch_ftrace { + #define make_call_t0(caller, callee, call) \ + do { \ + unsigned int offset = \ +- (unsigned long) callee - (unsigned long) caller; \ ++ (unsigned long) (callee) - (unsigned long) (caller); \ + call[0] = to_auipc_t0(offset); \ + call[1] = to_jalr_t0(offset); \ + } while (0) +@@ -108,7 +108,7 @@ do { \ + #define make_call_ra(caller, callee, call) \ + do { \ + unsigned int offset = \ +- (unsigned long) callee - (unsigned long) caller; \ ++ (unsigned long) (callee) - (unsigned long) (caller); \ + call[0] = to_auipc_ra(offset); \ + call[1] = to_jalr_ra(offset); \ + } while (0) +-- +2.39.5 + diff --git a/queue-6.14/riscv-kexec_file-handle-r_riscv_64-in-purgatory-relo.patch b/queue-6.14/riscv-kexec_file-handle-r_riscv_64-in-purgatory-relo.patch new file mode 100644 index 0000000000..1c5d36aa19 --- /dev/null +++ b/queue-6.14/riscv-kexec_file-handle-r_riscv_64-in-purgatory-relo.patch @@ -0,0 +1,54 @@ +From 9aba7e22aca1cbc3892de9d623680598be3a9458 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Mar 2025 05:14:46 +0000 +Subject: riscv/kexec_file: Handle R_RISCV_64 in purgatory relocator +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Yao Zi + +[ Upstream commit 28093cfef5dd62f4cbd537f2bdf6f0bf85309c45 ] + +Commit 58ff537109ac ("riscv: Omit optimized string routines when +using KASAN") introduced calls to EXPORT_SYMBOL() in assembly string +routines, which result in R_RISCV_64 relocations against +.export_symbol section. As these rountines are reused by RISC-V +purgatory and our relocator doesn't recognize these relocations, this +fails kexec-file-load with dmesg like + + [ 11.344251] kexec_image: Unknown rela relocation: 2 + [ 11.345972] kexec_image: Error loading purgatory ret=-8 + +Let's support R_RISCV_64 relocation to fix kexec on 64-bit RISC-V. +32-bit variant isn't covered since KEXEC_FILE and KEXEC_PURGATORY isn't +available. + +Fixes: 58ff537109ac ("riscv: Omit optimized string routines when using KASAN") +Signed-off-by: Yao Zi +Tested-by: Björn Töpel +Reviewed-by: Björn Töpel +Link: https://lore.kernel.org/r/20250326051445.55131-2-ziyao@disroot.org +Signed-off-by: Alexandre Ghiti +Signed-off-by: Sasha Levin +--- + arch/riscv/kernel/elf_kexec.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/riscv/kernel/elf_kexec.c b/arch/riscv/kernel/elf_kexec.c +index 3c37661801f95..e783a72d051f4 100644 +--- a/arch/riscv/kernel/elf_kexec.c ++++ b/arch/riscv/kernel/elf_kexec.c +@@ -468,6 +468,9 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi, + case R_RISCV_ALIGN: + case R_RISCV_RELAX: + break; ++ case R_RISCV_64: ++ *(u64 *)loc = val; ++ break; + default: + pr_err("Unknown rela relocation: %d\n", r_type); + return -ENOEXEC; +-- +2.39.5 + diff --git a/queue-6.14/riscv-purgatory-4b-align-purgatory_start.patch b/queue-6.14/riscv-purgatory-4b-align-purgatory_start.patch new file mode 100644 index 0000000000..f23779a09c --- /dev/null +++ b/queue-6.14/riscv-purgatory-4b-align-purgatory_start.patch @@ -0,0 +1,63 @@ +From 374d76691474ee0440c58aac8f9b66f9e34bc91d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Mar 2025 09:53:11 +0100 +Subject: riscv/purgatory: 4B align purgatory_start +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Björn Töpel + +[ Upstream commit 3f7023171df43641a8a8a1c9a12124501e589010 ] + +When a crashkernel is launched on RISC-V, the entry to purgatory is +done by trapping via the stvec CSR. From riscv_kexec_norelocate(): + + | ... + | /* + | * Switch to physical addressing + | * This will also trigger a jump to CSR_STVEC + | * which in this case is the address of the new + | * kernel. + | */ + | csrw CSR_STVEC, a2 + | csrw CSR_SATP, zero + +stvec requires that the address is 4B aligned, which was not the case, +e.g.: + + | Loaded purgatory at 0xffffc000 + | kexec_file: kexec_file_load: type:1, start:0xffffd232 head:0x4 flags:0x6 + +The address 0xffffd232 not 4B aligned. + +Correct by adding proper function alignment. + +With this change, crashkernels loaded with kexec-file will be able to +properly enter the purgatory. + +Fixes: 736e30af583fb ("RISC-V: Add purgatory") +Signed-off-by: Björn Töpel +Reviewed-by: Alexandre Ghiti +Link: https://lore.kernel.org/r/20250328085313.1193815-1-bjorn@kernel.org +Signed-off-by: Alexandre Ghiti +Signed-off-by: Sasha Levin +--- + arch/riscv/purgatory/entry.S | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/riscv/purgatory/entry.S b/arch/riscv/purgatory/entry.S +index 0e6ca6d5ae4b4..c5db2f072c341 100644 +--- a/arch/riscv/purgatory/entry.S ++++ b/arch/riscv/purgatory/entry.S +@@ -12,6 +12,7 @@ + + .text + ++.align 2 + SYM_CODE_START(purgatory_start) + + lla sp, .Lstack +-- +2.39.5 + diff --git a/queue-6.14/rndis_host-flag-rndis-modems-as-wwan-devices.patch b/queue-6.14/rndis_host-flag-rndis-modems-as-wwan-devices.patch new file mode 100644 index 0000000000..121751ff9c --- /dev/null +++ b/queue-6.14/rndis_host-flag-rndis-modems-as-wwan-devices.patch @@ -0,0 +1,70 @@ +From d4b6ac22656526cfed6203880ff42fea855f6212 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Mar 2025 10:58:41 +0100 +Subject: rndis_host: Flag RNDIS modems as WWAN devices + +From: Lubomir Rintel + +[ Upstream commit 67d1a8956d2d62fe6b4c13ebabb57806098511d8 ] + +Set FLAG_WWAN instead of FLAG_ETHERNET for RNDIS interfaces on Mobile +Broadband Modems, as opposed to regular Ethernet adapters. + +Otherwise NetworkManager gets confused, misjudges the device type, +and wouldn't know it should connect a modem to get the device to work. +What would be the result depends on ModemManager version -- older +ModemManager would end up disconnecting a device after an unsuccessful +probe attempt (if it connected without needing to unlock a SIM), while +a newer one might spawn a separate PPP connection over a tty interface +instead, resulting in a general confusion and no end of chaos. + +The only way to get this work reliably is to fix the device type +and have good enough version ModemManager (or equivalent). + +Fixes: 63ba395cd7a5 ("rndis_host: support Novatel Verizon USB730L") +Signed-off-by: Lubomir Rintel +Link: https://patch.msgid.link/20250325095842.1567999-1-lkundrak@v3.sk +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/usb/rndis_host.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c +index 7b3739b29c8f7..bb0bf14158727 100644 +--- a/drivers/net/usb/rndis_host.c ++++ b/drivers/net/usb/rndis_host.c +@@ -630,6 +630,16 @@ static const struct driver_info zte_rndis_info = { + .tx_fixup = rndis_tx_fixup, + }; + ++static const struct driver_info wwan_rndis_info = { ++ .description = "Mobile Broadband RNDIS device", ++ .flags = FLAG_WWAN | FLAG_POINTTOPOINT | FLAG_FRAMING_RN | FLAG_NO_SETINT, ++ .bind = rndis_bind, ++ .unbind = rndis_unbind, ++ .status = rndis_status, ++ .rx_fixup = rndis_rx_fixup, ++ .tx_fixup = rndis_tx_fixup, ++}; ++ + /*-------------------------------------------------------------------------*/ + + static const struct usb_device_id products [] = { +@@ -666,9 +676,11 @@ static const struct usb_device_id products [] = { + USB_INTERFACE_INFO(USB_CLASS_WIRELESS_CONTROLLER, 1, 3), + .driver_info = (unsigned long) &rndis_info, + }, { +- /* Novatel Verizon USB730L */ ++ /* Mobile Broadband Modem, seen in Novatel Verizon USB730L and ++ * Telit FN990A (RNDIS) ++ */ + USB_INTERFACE_INFO(USB_CLASS_MISC, 4, 1), +- .driver_info = (unsigned long) &rndis_info, ++ .driver_info = (unsigned long)&wwan_rndis_info, + }, + { }, // END + }; +-- +2.39.5 + diff --git a/queue-6.14/rseq-update-kernel-fields-in-lockstep-with-config_de.patch b/queue-6.14/rseq-update-kernel-fields-in-lockstep-with-config_de.patch new file mode 100644 index 0000000000..2570070d48 --- /dev/null +++ b/queue-6.14/rseq-update-kernel-fields-in-lockstep-with-config_de.patch @@ -0,0 +1,159 @@ +From c47afbd27f11a7cf6fe070eae86e6fb844a34251 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 15:24:46 -0500 +Subject: rseq: Update kernel fields in lockstep with CONFIG_DEBUG_RSEQ=y + +From: Michael Jeanson + +[ Upstream commit 79e10dad1ce3feac7937bedf911d92f486a9e76a ] + +With CONFIG_DEBUG_RSEQ=y, an in-kernel copy of the read-only fields is +kept synchronized with the user-space fields. Ensure the updates are +done in lockstep in case we error out on a write to user-space. + +Fixes: 7d5265ffcd8b ("rseq: Validate read-only fields under DEBUG_RSEQ config") +Signed-off-by: Michael Jeanson +Signed-off-by: Ingo Molnar +Reviewed-by: Mathieu Desnoyers +Link: https://lore.kernel.org/r/20250225202500.731245-1-mjeanson@efficios.com +Signed-off-by: Sasha Levin +--- + kernel/rseq.c | 80 +++++++++++++++++++++++++-------------------------- + 1 file changed, 40 insertions(+), 40 deletions(-) + +diff --git a/kernel/rseq.c b/kernel/rseq.c +index 2cb16091ec0ae..a7d81229eda04 100644 +--- a/kernel/rseq.c ++++ b/kernel/rseq.c +@@ -78,24 +78,24 @@ static int rseq_validate_ro_fields(struct task_struct *t) + return -EFAULT; + } + +-static void rseq_set_ro_fields(struct task_struct *t, u32 cpu_id_start, u32 cpu_id, +- u32 node_id, u32 mm_cid) +-{ +- rseq_kernel_fields(t)->cpu_id_start = cpu_id; +- rseq_kernel_fields(t)->cpu_id = cpu_id; +- rseq_kernel_fields(t)->node_id = node_id; +- rseq_kernel_fields(t)->mm_cid = mm_cid; +-} ++/* ++ * Update an rseq field and its in-kernel copy in lock-step to keep a coherent ++ * state. ++ */ ++#define rseq_unsafe_put_user(t, value, field, error_label) \ ++ do { \ ++ unsafe_put_user(value, &t->rseq->field, error_label); \ ++ rseq_kernel_fields(t)->field = value; \ ++ } while (0) ++ + #else + static int rseq_validate_ro_fields(struct task_struct *t) + { + return 0; + } + +-static void rseq_set_ro_fields(struct task_struct *t, u32 cpu_id_start, u32 cpu_id, +- u32 node_id, u32 mm_cid) +-{ +-} ++#define rseq_unsafe_put_user(t, value, field, error_label) \ ++ unsafe_put_user(value, &t->rseq->field, error_label) + #endif + + /* +@@ -173,17 +173,18 @@ static int rseq_update_cpu_node_id(struct task_struct *t) + WARN_ON_ONCE((int) mm_cid < 0); + if (!user_write_access_begin(rseq, t->rseq_len)) + goto efault; +- unsafe_put_user(cpu_id, &rseq->cpu_id_start, efault_end); +- unsafe_put_user(cpu_id, &rseq->cpu_id, efault_end); +- unsafe_put_user(node_id, &rseq->node_id, efault_end); +- unsafe_put_user(mm_cid, &rseq->mm_cid, efault_end); ++ ++ rseq_unsafe_put_user(t, cpu_id, cpu_id_start, efault_end); ++ rseq_unsafe_put_user(t, cpu_id, cpu_id, efault_end); ++ rseq_unsafe_put_user(t, node_id, node_id, efault_end); ++ rseq_unsafe_put_user(t, mm_cid, mm_cid, efault_end); ++ + /* + * Additional feature fields added after ORIG_RSEQ_SIZE + * need to be conditionally updated only if + * t->rseq_len != ORIG_RSEQ_SIZE. + */ + user_write_access_end(); +- rseq_set_ro_fields(t, cpu_id, cpu_id, node_id, mm_cid); + trace_rseq_update(t); + return 0; + +@@ -195,6 +196,7 @@ static int rseq_update_cpu_node_id(struct task_struct *t) + + static int rseq_reset_rseq_cpu_node_id(struct task_struct *t) + { ++ struct rseq __user *rseq = t->rseq; + u32 cpu_id_start = 0, cpu_id = RSEQ_CPU_ID_UNINITIALIZED, node_id = 0, + mm_cid = 0; + +@@ -202,38 +204,36 @@ static int rseq_reset_rseq_cpu_node_id(struct task_struct *t) + * Validate read-only rseq fields. + */ + if (rseq_validate_ro_fields(t)) +- return -EFAULT; +- /* +- * Reset cpu_id_start to its initial state (0). +- */ +- if (put_user(cpu_id_start, &t->rseq->cpu_id_start)) +- return -EFAULT; +- /* +- * Reset cpu_id to RSEQ_CPU_ID_UNINITIALIZED, so any user coming +- * in after unregistration can figure out that rseq needs to be +- * registered again. +- */ +- if (put_user(cpu_id, &t->rseq->cpu_id)) +- return -EFAULT; +- /* +- * Reset node_id to its initial state (0). +- */ +- if (put_user(node_id, &t->rseq->node_id)) +- return -EFAULT; ++ goto efault; ++ ++ if (!user_write_access_begin(rseq, t->rseq_len)) ++ goto efault; ++ + /* +- * Reset mm_cid to its initial state (0). ++ * Reset all fields to their initial state. ++ * ++ * All fields have an initial state of 0 except cpu_id which is set to ++ * RSEQ_CPU_ID_UNINITIALIZED, so that any user coming in after ++ * unregistration can figure out that rseq needs to be registered ++ * again. + */ +- if (put_user(mm_cid, &t->rseq->mm_cid)) +- return -EFAULT; +- +- rseq_set_ro_fields(t, cpu_id_start, cpu_id, node_id, mm_cid); ++ rseq_unsafe_put_user(t, cpu_id_start, cpu_id_start, efault_end); ++ rseq_unsafe_put_user(t, cpu_id, cpu_id, efault_end); ++ rseq_unsafe_put_user(t, node_id, node_id, efault_end); ++ rseq_unsafe_put_user(t, mm_cid, mm_cid, efault_end); + + /* + * Additional feature fields added after ORIG_RSEQ_SIZE + * need to be conditionally reset only if + * t->rseq_len != ORIG_RSEQ_SIZE. + */ ++ user_write_access_end(); + return 0; ++ ++efault_end: ++ user_write_access_end(); ++efault: ++ return -EFAULT; + } + + static int rseq_get_rseq_cs(struct task_struct *t, struct rseq_cs *rseq_cs) +-- +2.39.5 + diff --git a/queue-6.14/rtc-renesas-rtca3-disable-interrupts-only-if-the-rtc.patch b/queue-6.14/rtc-renesas-rtca3-disable-interrupts-only-if-the-rtc.patch new file mode 100644 index 0000000000..69fbb0f6bf --- /dev/null +++ b/queue-6.14/rtc-renesas-rtca3-disable-interrupts-only-if-the-rtc.patch @@ -0,0 +1,58 @@ +From 77b7d26de01f80f8d1c0369b9f69cfdf93c7811c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 11:55:19 +0200 +Subject: rtc: renesas-rtca3: Disable interrupts only if the RTC is enabled + +From: Claudiu Beznea + +[ Upstream commit 27b2fcbd6b98204b0dce62e9aa9540ca0a2b70f1 ] + +If the RTC is not enabled and the code attempts to disable the interrupt, +the readb_poll_timeout_atomic() function in the +rtca3_alarm_irq_set_helper() may timeout, leading to probe failures. +This issue is reproducible on some devices because the initial values of +the PIE and AIE bits in the RCR1 register are undefined. + +To prevent probe failures in this scenario, disable RTC interrupts only +when the RTC is actually enabled. + +Fixes: d4488377609e ("rtc: renesas-rtca3: Add driver for RTCA-3 available on Renesas RZ/G3S SoC") +Signed-off-by: Claudiu Beznea +Link: https://lore.kernel.org/r/20250205095519.2031742-1-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-renesas-rtca3.c | 15 ++++++--------- + 1 file changed, 6 insertions(+), 9 deletions(-) + +diff --git a/drivers/rtc/rtc-renesas-rtca3.c b/drivers/rtc/rtc-renesas-rtca3.c +index a056291d38876..ab816bdf0d776 100644 +--- a/drivers/rtc/rtc-renesas-rtca3.c ++++ b/drivers/rtc/rtc-renesas-rtca3.c +@@ -586,17 +586,14 @@ static int rtca3_initial_setup(struct clk *clk, struct rtca3_priv *priv) + */ + usleep_range(sleep_us, sleep_us + 10); + +- /* Disable all interrupts. */ +- mask = RTCA3_RCR1_AIE | RTCA3_RCR1_CIE | RTCA3_RCR1_PIE; +- ret = rtca3_alarm_irq_set_helper(priv, mask, 0); +- if (ret) +- return ret; +- + mask = RTCA3_RCR2_START | RTCA3_RCR2_HR24; + val = readb(priv->base + RTCA3_RCR2); +- /* Nothing to do if already started in 24 hours and calendar count mode. */ +- if ((val & mask) == mask) +- return 0; ++ /* Only disable the interrupts if already started in 24 hours and calendar count mode. */ ++ if ((val & mask) == mask) { ++ /* Disable all interrupts. */ ++ mask = RTCA3_RCR1_AIE | RTCA3_RCR1_CIE | RTCA3_RCR1_PIE; ++ return rtca3_alarm_irq_set_helper(priv, mask, 0); ++ } + + /* Reconfigure the RTC in 24 hours and calendar count mode. */ + mask = RTCA3_RCR2_START | RTCA3_RCR2_CNTMD; +-- +2.39.5 + diff --git a/queue-6.14/rtnetlink-allocate-vfinfo-size-for-vf-guids-when-sup.patch b/queue-6.14/rtnetlink-allocate-vfinfo-size-for-vf-guids-when-sup.patch new file mode 100644 index 0000000000..f7340adf73 --- /dev/null +++ b/queue-6.14/rtnetlink-allocate-vfinfo-size-for-vf-guids-when-sup.patch @@ -0,0 +1,163 @@ +From 7f58e24cc182f84ff282a413ce57f57b9bd68653 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Mar 2025 11:02:26 +0200 +Subject: rtnetlink: Allocate vfinfo size for VF GUIDs when supported + +From: Mark Zhang + +[ Upstream commit 23f00807619d15063d676218f36c5dfeda1eb420 ] + +Commit 30aad41721e0 ("net/core: Add support for getting VF GUIDs") +added support for getting VF port and node GUIDs in netlink ifinfo +messages, but their size was not taken into consideration in the +function that allocates the netlink message, causing the following +warning when a netlink message is filled with many VF port and node +GUIDs: + # echo 64 > /sys/bus/pci/devices/0000\:08\:00.0/sriov_numvfs + # ip link show dev ib0 + RTNETLINK answers: Message too long + Cannot send link get request: Message too long + +Kernel warning: + + ------------[ cut here ]------------ + WARNING: CPU: 2 PID: 1930 at net/core/rtnetlink.c:4151 rtnl_getlink+0x586/0x5a0 + Modules linked in: xt_conntrack xt_MASQUERADE nfnetlink xt_addrtype iptable_nat nf_nat br_netfilter overlay mlx5_ib macsec mlx5_core tls rpcrdma rdma_ucm ib_uverbs ib_iser libiscsi scsi_transport_iscsi ib_umad rdma_cm iw_cm ib_ipoib fuse ib_cm ib_core + CPU: 2 UID: 0 PID: 1930 Comm: ip Not tainted 6.14.0-rc2+ #1 + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 + RIP: 0010:rtnl_getlink+0x586/0x5a0 + Code: cb 82 e8 3d af 0a 00 4d 85 ff 0f 84 08 ff ff ff 4c 89 ff 41 be ea ff ff ff e8 66 63 5b ff 49 c7 07 80 4f cb 82 e9 36 fc ff ff <0f> 0b e9 16 fe ff ff e8 de a0 56 00 66 66 2e 0f 1f 84 00 00 00 00 + RSP: 0018:ffff888113557348 EFLAGS: 00010246 + RAX: 00000000ffffffa6 RBX: ffff88817e87aa34 RCX: dffffc0000000000 + RDX: 0000000000000003 RSI: 0000000000000000 RDI: ffff88817e87afb8 + RBP: 0000000000000009 R08: ffffffff821f44aa R09: 0000000000000000 + R10: ffff8881260f79a8 R11: ffff88817e87af00 R12: ffff88817e87aa00 + R13: ffffffff8563d300 R14: 00000000ffffffa6 R15: 00000000ffffffff + FS: 00007f63a5dbf280(0000) GS:ffff88881ee00000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007f63a5ba4493 CR3: 00000001700fe002 CR4: 0000000000772eb0 + DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 + DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 + PKRU: 55555554 + Call Trace: + + ? __warn+0xa5/0x230 + ? rtnl_getlink+0x586/0x5a0 + ? report_bug+0x22d/0x240 + ? handle_bug+0x53/0xa0 + ? exc_invalid_op+0x14/0x50 + ? asm_exc_invalid_op+0x16/0x20 + ? skb_trim+0x6a/0x80 + ? rtnl_getlink+0x586/0x5a0 + ? __pfx_rtnl_getlink+0x10/0x10 + ? rtnetlink_rcv_msg+0x1e5/0x860 + ? __pfx___mutex_lock+0x10/0x10 + ? rcu_is_watching+0x34/0x60 + ? __pfx_lock_acquire+0x10/0x10 + ? stack_trace_save+0x90/0xd0 + ? filter_irq_stacks+0x1d/0x70 + ? kasan_save_stack+0x30/0x40 + ? kasan_save_stack+0x20/0x40 + ? kasan_save_track+0x10/0x30 + rtnetlink_rcv_msg+0x21c/0x860 + ? entry_SYSCALL_64_after_hwframe+0x76/0x7e + ? __pfx_rtnetlink_rcv_msg+0x10/0x10 + ? arch_stack_walk+0x9e/0xf0 + ? rcu_is_watching+0x34/0x60 + ? lock_acquire+0xd5/0x410 + ? rcu_is_watching+0x34/0x60 + netlink_rcv_skb+0xe0/0x210 + ? __pfx_rtnetlink_rcv_msg+0x10/0x10 + ? __pfx_netlink_rcv_skb+0x10/0x10 + ? rcu_is_watching+0x34/0x60 + ? __pfx___netlink_lookup+0x10/0x10 + ? lock_release+0x62/0x200 + ? netlink_deliver_tap+0xfd/0x290 + ? rcu_is_watching+0x34/0x60 + ? lock_release+0x62/0x200 + ? netlink_deliver_tap+0x95/0x290 + netlink_unicast+0x31f/0x480 + ? __pfx_netlink_unicast+0x10/0x10 + ? rcu_is_watching+0x34/0x60 + ? lock_acquire+0xd5/0x410 + netlink_sendmsg+0x369/0x660 + ? lock_release+0x62/0x200 + ? __pfx_netlink_sendmsg+0x10/0x10 + ? import_ubuf+0xb9/0xf0 + ? __import_iovec+0x254/0x2b0 + ? lock_release+0x62/0x200 + ? __pfx_netlink_sendmsg+0x10/0x10 + ____sys_sendmsg+0x559/0x5a0 + ? __pfx_____sys_sendmsg+0x10/0x10 + ? __pfx_copy_msghdr_from_user+0x10/0x10 + ? rcu_is_watching+0x34/0x60 + ? do_read_fault+0x213/0x4a0 + ? rcu_is_watching+0x34/0x60 + ___sys_sendmsg+0xe4/0x150 + ? __pfx____sys_sendmsg+0x10/0x10 + ? do_fault+0x2cc/0x6f0 + ? handle_pte_fault+0x2e3/0x3d0 + ? __pfx_handle_pte_fault+0x10/0x10 + ? preempt_count_sub+0x14/0xc0 + ? __down_read_trylock+0x150/0x270 + ? __handle_mm_fault+0x404/0x8e0 + ? __pfx___handle_mm_fault+0x10/0x10 + ? lock_release+0x62/0x200 + ? __rcu_read_unlock+0x65/0x90 + ? rcu_is_watching+0x34/0x60 + __sys_sendmsg+0xd5/0x150 + ? __pfx___sys_sendmsg+0x10/0x10 + ? __up_read+0x192/0x480 + ? lock_release+0x62/0x200 + ? __rcu_read_unlock+0x65/0x90 + ? rcu_is_watching+0x34/0x60 + do_syscall_64+0x6d/0x140 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + RIP: 0033:0x7f63a5b13367 + Code: 0e 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b9 0f 1f 00 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 51 c3 48 83 ec 28 89 54 24 1c 48 89 74 24 10 + RSP: 002b:00007fff8c726bc8 EFLAGS: 00000246 ORIG_RAX: 000000000000002e + RAX: ffffffffffffffda RBX: 0000000067b687c2 RCX: 00007f63a5b13367 + RDX: 0000000000000000 RSI: 00007fff8c726c30 RDI: 0000000000000004 + RBP: 00007fff8c726cb8 R08: 0000000000000000 R09: 0000000000000034 + R10: 00007fff8c726c7c R11: 0000000000000246 R12: 0000000000000001 + R13: 0000000000000000 R14: 00007fff8c726cd0 R15: 00007fff8c726cd0 + + irq event stamp: 0 + hardirqs last enabled at (0): [<0000000000000000>] 0x0 + hardirqs last disabled at (0): [] copy_process+0xd08/0x2830 + softirqs last enabled at (0): [] copy_process+0xd08/0x2830 + softirqs last disabled at (0): [<0000000000000000>] 0x0 + ---[ end trace 0000000000000000 ]--- + +Thus, when calculating ifinfo message size, take VF GUIDs sizes into +account when supported. + +Fixes: 30aad41721e0 ("net/core: Add support for getting VF GUIDs") +Signed-off-by: Mark Zhang +Reviewed-by: Maher Sanalla +Signed-off-by: Mark Bloch +Reviewed-by: Sabrina Dubroca +Link: https://patch.msgid.link/20250325090226.749730-1-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/rtnetlink.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index d1e559fce918d..80e006940f51a 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -1171,6 +1171,9 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev, + /* IFLA_VF_STATS_TX_DROPPED */ + nla_total_size_64bit(sizeof(__u64))); + } ++ if (dev->netdev_ops->ndo_get_vf_guid) ++ size += num_vfs * 2 * ++ nla_total_size(sizeof(struct ifla_vf_guid)); + return size; + } else + return 0; +-- +2.39.5 + diff --git a/queue-6.14/rtnetlink-use-register_pernet_subsys-in-rtnl_net_deb.patch b/queue-6.14/rtnetlink-use-register_pernet_subsys-in-rtnl_net_deb.patch new file mode 100644 index 0000000000..f5d2852019 --- /dev/null +++ b/queue-6.14/rtnetlink-use-register_pernet_subsys-in-rtnl_net_deb.patch @@ -0,0 +1,48 @@ +From 4ae5168dc4f76ff9aaa6b9ffceaed5ee45471327 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Apr 2025 12:07:08 -0700 +Subject: rtnetlink: Use register_pernet_subsys() in rtnl_net_debug_init(). + +From: Kuniyuki Iwashima + +[ Upstream commit 1b7fdc702c031134c619b74c4f311c590e50ca3d ] + +rtnl_net_debug_init() registers rtnl_net_debug_net_ops by +register_pernet_device() but calls unregister_pernet_subsys() +in case register_netdevice_notifier() fails. + +It corrupts pernet_list because first_device is updated in +register_pernet_device() but not unregister_pernet_subsys(). + +Let's fix it by calling register_pernet_subsys() instead. + +The _subsys() one fits better for the use case because it keeps +the notifier alive until default_device_exit_net(), giving it +more chance to test NETDEV_UNREGISTER. + +Fixes: 03fa53485659 ("rtnetlink: Add ASSERT_RTNL_NET() placeholder for netdev notifier.") +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250401190716.70437-1-kuniyu@amazon.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/rtnl_net_debug.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/core/rtnl_net_debug.c b/net/core/rtnl_net_debug.c +index 7ecd28cc1c225..f3272b09c2556 100644 +--- a/net/core/rtnl_net_debug.c ++++ b/net/core/rtnl_net_debug.c +@@ -102,7 +102,7 @@ static int __init rtnl_net_debug_init(void) + { + int ret; + +- ret = register_pernet_device(&rtnl_net_debug_net_ops); ++ ret = register_pernet_subsys(&rtnl_net_debug_net_ops); + if (ret) + return ret; + +-- +2.39.5 + diff --git a/queue-6.14/rust-fix-signature-of-rust_fmt_argument.patch b/queue-6.14/rust-fix-signature-of-rust_fmt_argument.patch new file mode 100644 index 0000000000..73908b1daa --- /dev/null +++ b/queue-6.14/rust-fix-signature-of-rust_fmt_argument.patch @@ -0,0 +1,78 @@ +From dcac389c75d05930a6ba09a1f8f2cb0b1d3d1850 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 08:45:12 +0000 +Subject: rust: fix signature of rust_fmt_argument + +From: Alice Ryhl + +[ Upstream commit 901b3290bd4dc35e613d13abd03c129e754dd3dd ] + +Without this change, the rest of this series will emit the following +error message: + +error[E0308]: `if` and `else` have incompatible types + --> /rust/kernel/print.rs:22:22 + | +21 | #[export] + | --------- expected because of this +22 | unsafe extern "C" fn rust_fmt_argument( + | ^^^^^^^^^^^^^^^^^ expected `u8`, found `i8` + | + = note: expected fn item `unsafe extern "C" fn(*mut u8, *mut u8, *mut c_void) -> *mut u8 {bindings::rust_fmt_argument}` + found fn item `unsafe extern "C" fn(*mut i8, *mut i8, *const c_void) -> *mut i8 {print::rust_fmt_argument}` + +The error may be different depending on the architecture. + +To fix this, change the void pointer argument to use a const pointer, +and change the imports to use crate::ffi instead of core::ffi for +integer types. + +Fixes: 787983da7718 ("vsprintf: add new `%pA` format specifier") +Reviewed-by: Tamir Duberstein +Acked-by: Greg Kroah-Hartman +Signed-off-by: Alice Ryhl +Acked-by: Petr Mladek +Link: https://lore.kernel.org/r/20250303-export-macro-v3-1-41fbad85a27f@google.com +Signed-off-by: Miguel Ojeda +Signed-off-by: Sasha Levin +--- + lib/vsprintf.c | 2 +- + rust/kernel/print.rs | 7 +++---- + 2 files changed, 4 insertions(+), 5 deletions(-) + +diff --git a/lib/vsprintf.c b/lib/vsprintf.c +index 56fe963192926..a8ac4c4fffcf2 100644 +--- a/lib/vsprintf.c ++++ b/lib/vsprintf.c +@@ -2285,7 +2285,7 @@ int __init no_hash_pointers_enable(char *str) + early_param("no_hash_pointers", no_hash_pointers_enable); + + /* Used for Rust formatting ('%pA'). */ +-char *rust_fmt_argument(char *buf, char *end, void *ptr); ++char *rust_fmt_argument(char *buf, char *end, const void *ptr); + + /* + * Show a '%p' thing. A kernel extension is that the '%p' is followed +diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs +index b19ee490be58f..61ee36c5e5f5d 100644 +--- a/rust/kernel/print.rs ++++ b/rust/kernel/print.rs +@@ -6,12 +6,11 @@ + //! + //! Reference: + +-use core::{ ++use crate::{ + ffi::{c_char, c_void}, +- fmt, ++ str::RawFormatter, + }; +- +-use crate::str::RawFormatter; ++use core::fmt; + + // Called from `vsprintf` with format specifier `%pA`. + #[expect(clippy::missing_safety_doc)] +-- +2.39.5 + diff --git a/queue-6.14/rust-pci-fix-unrestricted-mut-pci-device.patch b/queue-6.14/rust-pci-fix-unrestricted-mut-pci-device.patch new file mode 100644 index 0000000000..e871cd12a1 --- /dev/null +++ b/queue-6.14/rust-pci-fix-unrestricted-mut-pci-device.patch @@ -0,0 +1,334 @@ +From 59cba79ebad5ec8c5936a4e0941da198ff414d77 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 17:09:06 +0100 +Subject: rust: pci: fix unrestricted &mut pci::Device + +From: Danilo Krummrich + +[ Upstream commit 7b948a2af6b5d64a25c14da8f63d8084ea527cd9 ] + +As by now, pci::Device is implemented as: + + #[derive(Clone)] + pub struct Device(ARef); + +This may be convenient, but has the implication that drivers can call +device methods that require a mutable reference concurrently at any +point of time. + +Instead define pci::Device as + + pub struct Device( + Opaque, + PhantomData, + ); + +and manually implement the AlwaysRefCounted trait. + +With this we can implement methods that should only be called from +bus callbacks (such as probe()) for pci::Device. Consequently, we +make this type accessible in bus callbacks only. + +Arbitrary references taken by the driver are still of type +ARef and hence don't provide access to methods that are +reserved for bus callbacks. + +Fixes: 1bd8b6b2c5d3 ("rust: pci: add basic PCI device / driver abstractions") +Reviewed-by: Benno Lossin +Signed-off-by: Danilo Krummrich +Acked-by: Boqun Feng +Link: https://lore.kernel.org/r/20250314160932.100165-4-dakr@kernel.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + rust/kernel/pci.rs | 132 ++++++++++++++++++++------------ + samples/rust/rust_driver_pci.rs | 8 +- + 2 files changed, 89 insertions(+), 51 deletions(-) + +diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs +index 386484dcf36eb..0ac6cef74f815 100644 +--- a/rust/kernel/pci.rs ++++ b/rust/kernel/pci.rs +@@ -6,7 +6,7 @@ + + use crate::{ + alloc::flags::*, +- bindings, container_of, device, ++ bindings, device, + device_id::RawDeviceId, + devres::Devres, + driver, +@@ -17,7 +17,11 @@ use crate::{ + types::{ARef, ForeignOwnable, Opaque}, + ThisModule, + }; +-use core::{ops::Deref, ptr::addr_of_mut}; ++use core::{ ++ marker::PhantomData, ++ ops::Deref, ++ ptr::{addr_of_mut, NonNull}, ++}; + use kernel::prelude::*; + + /// An adapter for the registration of PCI drivers. +@@ -60,17 +64,16 @@ impl Adapter { + ) -> kernel::ffi::c_int { + // SAFETY: The PCI bus only ever calls the probe callback with a valid pointer to a + // `struct pci_dev`. +- let dev = unsafe { device::Device::get_device(addr_of_mut!((*pdev).dev)) }; +- // SAFETY: `dev` is guaranteed to be embedded in a valid `struct pci_dev` by the call +- // above. +- let mut pdev = unsafe { Device::from_dev(dev) }; ++ // ++ // INVARIANT: `pdev` is valid for the duration of `probe_callback()`. ++ let pdev = unsafe { &*pdev.cast::>() }; + + // SAFETY: `DeviceId` is a `#[repr(transparent)` wrapper of `struct pci_device_id` and + // does not add additional invariants, so it's safe to transmute. + let id = unsafe { &*id.cast::() }; + let info = T::ID_TABLE.info(id.index()); + +- match T::probe(&mut pdev, info) { ++ match T::probe(pdev, info) { + Ok(data) => { + // Let the `struct pci_dev` own a reference of the driver's private data. + // SAFETY: By the type invariant `pdev.as_raw` returns a valid pointer to a +@@ -192,7 +195,7 @@ macro_rules! pci_device_table { + /// # Example + /// + ///``` +-/// # use kernel::{bindings, pci}; ++/// # use kernel::{bindings, device::Core, pci}; + /// + /// struct MyDriver; + /// +@@ -210,7 +213,7 @@ macro_rules! pci_device_table { + /// const ID_TABLE: pci::IdTable = &PCI_TABLE; + /// + /// fn probe( +-/// _pdev: &mut pci::Device, ++/// _pdev: &pci::Device, + /// _id_info: &Self::IdInfo, + /// ) -> Result>> { + /// Err(ENODEV) +@@ -234,20 +237,23 @@ pub trait Driver { + /// + /// Called when a new platform device is added or discovered. + /// Implementers should attempt to initialize the device here. +- fn probe(dev: &mut Device, id_info: &Self::IdInfo) -> Result>>; ++ fn probe(dev: &Device, id_info: &Self::IdInfo) -> Result>>; + } + + /// The PCI device representation. + /// +-/// A PCI device is based on an always reference counted `device:Device` instance. Cloning a PCI +-/// device, hence, also increments the base device' reference count. ++/// This structure represents the Rust abstraction for a C `struct pci_dev`. The implementation ++/// abstracts the usage of an already existing C `struct pci_dev` within Rust code that we get ++/// passed from the C side. + /// + /// # Invariants + /// +-/// `Device` hold a valid reference of `ARef` whose underlying `struct device` is a +-/// member of a `struct pci_dev`. +-#[derive(Clone)] +-pub struct Device(ARef); ++/// A [`Device`] instance represents a valid `struct device` created by the C portion of the kernel. ++#[repr(transparent)] ++pub struct Device( ++ Opaque, ++ PhantomData, ++); + + /// A PCI BAR to perform I/O-Operations on. + /// +@@ -256,13 +262,13 @@ pub struct Device(ARef); + /// `Bar` always holds an `IoRaw` inststance that holds a valid pointer to the start of the I/O + /// memory mapped PCI bar and its size. + pub struct Bar { +- pdev: Device, ++ pdev: ARef, + io: IoRaw, + num: i32, + } + + impl Bar { +- fn new(pdev: Device, num: u32, name: &CStr) -> Result { ++ fn new(pdev: &Device, num: u32, name: &CStr) -> Result { + let len = pdev.resource_len(num)?; + if len == 0 { + return Err(ENOMEM); +@@ -300,12 +306,16 @@ impl Bar { + // `pdev` is valid by the invariants of `Device`. + // `ioptr` is guaranteed to be the start of a valid I/O mapped memory region. + // `num` is checked for validity by a previous call to `Device::resource_len`. +- unsafe { Self::do_release(&pdev, ioptr, num) }; ++ unsafe { Self::do_release(pdev, ioptr, num) }; + return Err(err); + } + }; + +- Ok(Bar { pdev, io, num }) ++ Ok(Bar { ++ pdev: pdev.into(), ++ io, ++ num, ++ }) + } + + /// # Safety +@@ -351,20 +361,8 @@ impl Deref for Bar { + } + + impl Device { +- /// Create a PCI Device instance from an existing `device::Device`. +- /// +- /// # Safety +- /// +- /// `dev` must be an `ARef` whose underlying `bindings::device` is a member of +- /// a `bindings::pci_dev`. +- pub unsafe fn from_dev(dev: ARef) -> Self { +- Self(dev) +- } +- + fn as_raw(&self) -> *mut bindings::pci_dev { +- // SAFETY: By the type invariant `self.0.as_raw` is a pointer to the `struct device` +- // embedded in `struct pci_dev`. +- unsafe { container_of!(self.0.as_raw(), bindings::pci_dev, dev) as _ } ++ self.0.get() + } + + /// Returns the PCI vendor ID. +@@ -379,18 +377,6 @@ impl Device { + unsafe { (*self.as_raw()).device } + } + +- /// Enable memory resources for this device. +- pub fn enable_device_mem(&self) -> Result { +- // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid `struct pci_dev`. +- to_result(unsafe { bindings::pci_enable_device_mem(self.as_raw()) }) +- } +- +- /// Enable bus-mastering for this device. +- pub fn set_master(&self) { +- // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid `struct pci_dev`. +- unsafe { bindings::pci_set_master(self.as_raw()) }; +- } +- + /// Returns the size of the given PCI bar resource. + pub fn resource_len(&self, bar: u32) -> Result { + if !Bar::index_is_valid(bar) { +@@ -410,7 +396,7 @@ impl Device { + bar: u32, + name: &CStr, + ) -> Result>> { +- let bar = Bar::::new(self.clone(), bar, name)?; ++ let bar = Bar::::new(self, bar, name)?; + let devres = Devres::new(self.as_ref(), bar, GFP_KERNEL)?; + + Ok(devres) +@@ -422,8 +408,60 @@ impl Device { + } + } + ++impl Device { ++ /// Enable memory resources for this device. ++ pub fn enable_device_mem(&self) -> Result { ++ // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid `struct pci_dev`. ++ to_result(unsafe { bindings::pci_enable_device_mem(self.as_raw()) }) ++ } ++ ++ /// Enable bus-mastering for this device. ++ pub fn set_master(&self) { ++ // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid `struct pci_dev`. ++ unsafe { bindings::pci_set_master(self.as_raw()) }; ++ } ++} ++ ++impl Deref for Device { ++ type Target = Device; ++ ++ fn deref(&self) -> &Self::Target { ++ let ptr: *const Self = self; ++ ++ // CAST: `Device` is a transparent wrapper of `Opaque`. ++ let ptr = ptr.cast::(); ++ ++ // SAFETY: `ptr` was derived from `&self`. ++ unsafe { &*ptr } ++ } ++} ++ ++impl From<&Device> for ARef { ++ fn from(dev: &Device) -> Self { ++ (&**dev).into() ++ } ++} ++ ++// SAFETY: Instances of `Device` are always reference-counted. ++unsafe impl crate::types::AlwaysRefCounted for Device { ++ fn inc_ref(&self) { ++ // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero. ++ unsafe { bindings::pci_dev_get(self.as_raw()) }; ++ } ++ ++ unsafe fn dec_ref(obj: NonNull) { ++ // SAFETY: The safety requirements guarantee that the refcount is non-zero. ++ unsafe { bindings::pci_dev_put(obj.cast().as_ptr()) } ++ } ++} ++ + impl AsRef for Device { + fn as_ref(&self) -> &device::Device { +- &self.0 ++ // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid ++ // `struct pci_dev`. ++ let dev = unsafe { addr_of_mut!((*self.as_raw()).dev) }; ++ ++ // SAFETY: `dev` points to a valid `struct device`. ++ unsafe { device::Device::as_ref(dev) } + } + } +diff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci.rs +index 1fb6e44f33951..4f14e63f323e9 100644 +--- a/samples/rust/rust_driver_pci.rs ++++ b/samples/rust/rust_driver_pci.rs +@@ -4,7 +4,7 @@ + //! + //! To make this driver probe, QEMU must be run with `-device pci-testdev`. + +-use kernel::{bindings, c_str, devres::Devres, pci, prelude::*}; ++use kernel::{bindings, c_str, device::Core, devres::Devres, pci, prelude::*, types::ARef}; + + struct Regs; + +@@ -26,7 +26,7 @@ impl TestIndex { + } + + struct SampleDriver { +- pdev: pci::Device, ++ pdev: ARef, + bar: Devres, + } + +@@ -62,7 +62,7 @@ impl pci::Driver for SampleDriver { + + const ID_TABLE: pci::IdTable = &PCI_TABLE; + +- fn probe(pdev: &mut pci::Device, info: &Self::IdInfo) -> Result>> { ++ fn probe(pdev: &pci::Device, info: &Self::IdInfo) -> Result>> { + dev_dbg!( + pdev.as_ref(), + "Probe Rust PCI driver sample (PCI ID: 0x{:x}, 0x{:x}).\n", +@@ -77,7 +77,7 @@ impl pci::Driver for SampleDriver { + + let drvdata = KBox::new( + Self { +- pdev: pdev.clone(), ++ pdev: pdev.into(), + bar, + }, + GFP_KERNEL, +-- +2.39.5 + diff --git a/queue-6.14/rust-pci-use-to_result-in-enable_device_mem.patch b/queue-6.14/rust-pci-use-to_result-in-enable_device_mem.patch new file mode 100644 index 0000000000..37febc1a5e --- /dev/null +++ b/queue-6.14/rust-pci-use-to_result-in-enable_device_mem.patch @@ -0,0 +1,44 @@ +From f6a539ed57d190c8990587d7db7b3ec06ec6bb0e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 17:09:04 +0100 +Subject: rust: pci: use to_result() in enable_device_mem() + +From: Danilo Krummrich + +[ Upstream commit d1f6d6c537d488b1a8f04091c7751124985a0ab9 ] + +Simplify enable_device_mem() by using to_result() to handle the return +value of the corresponding FFI call. + +Reviewed-by: Benno Lossin +Signed-off-by: Danilo Krummrich +Acked-by: Boqun Feng +Link: https://lore.kernel.org/r/20250314160932.100165-2-dakr@kernel.org +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 7b948a2af6b5 ("rust: pci: fix unrestricted &mut pci::Device") +Signed-off-by: Sasha Levin +--- + rust/kernel/pci.rs | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs +index 4c98b5b9aa1e9..386484dcf36eb 100644 +--- a/rust/kernel/pci.rs ++++ b/rust/kernel/pci.rs +@@ -382,12 +382,7 @@ impl Device { + /// Enable memory resources for this device. + pub fn enable_device_mem(&self) -> Result { + // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid `struct pci_dev`. +- let ret = unsafe { bindings::pci_enable_device_mem(self.as_raw()) }; +- if ret != 0 { +- Err(Error::from_errno(ret)) +- } else { +- Ok(()) +- } ++ to_result(unsafe { bindings::pci_enable_device_mem(self.as_raw()) }) + } + + /// Enable bus-mastering for this device. +-- +2.39.5 + diff --git a/queue-6.14/rust-platform-fix-unrestricted-mut-platform-device.patch b/queue-6.14/rust-platform-fix-unrestricted-mut-platform-device.patch new file mode 100644 index 0000000000..3b009cd7d6 --- /dev/null +++ b/queue-6.14/rust-platform-fix-unrestricted-mut-platform-device.patch @@ -0,0 +1,245 @@ +From 818139a93eb0e8f6bc0f874ae474ab674e419b6a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 17:09:07 +0100 +Subject: rust: platform: fix unrestricted &mut platform::Device + +From: Danilo Krummrich + +[ Upstream commit 4d320e30ee04c25c660eca2bb33e846ebb71a79a ] + +As by now, platform::Device is implemented as: + + #[derive(Clone)] + pub struct Device(ARef); + +This may be convenient, but has the implication that drivers can call +device methods that require a mutable reference concurrently at any +point of time. + +Instead define platform::Device as + + pub struct Device( + Opaque, + PhantomData, + ); + +and manually implement the AlwaysRefCounted trait. + +With this we can implement methods that should only be called from +bus callbacks (such as probe()) for platform::Device. Consequently, +we make this type accessible in bus callbacks only. + +Arbitrary references taken by the driver are still of type +ARef and hence don't provide access to methods that are +reserved for bus callbacks. + +Fixes: 683a63befc73 ("rust: platform: add basic platform device / driver abstractions") +Reviewed-by: Benno Lossin +Signed-off-by: Danilo Krummrich +Acked-by: Boqun Feng +Link: https://lore.kernel.org/r/20250314160932.100165-5-dakr@kernel.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + rust/kernel/platform.rs | 95 +++++++++++++++++++--------- + samples/rust/rust_driver_platform.rs | 11 ++-- + 2 files changed, 72 insertions(+), 34 deletions(-) + +diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs +index 50e6b04218132..c77c9f2e9aea1 100644 +--- a/rust/kernel/platform.rs ++++ b/rust/kernel/platform.rs +@@ -5,7 +5,7 @@ + //! C header: [`include/linux/platform_device.h`](srctree/include/linux/platform_device.h) + + use crate::{ +- bindings, container_of, device, driver, ++ bindings, device, driver, + error::{to_result, Result}, + of, + prelude::*, +@@ -14,7 +14,11 @@ use crate::{ + ThisModule, + }; + +-use core::ptr::addr_of_mut; ++use core::{ ++ marker::PhantomData, ++ ops::Deref, ++ ptr::{addr_of_mut, NonNull}, ++}; + + /// An adapter for the registration of platform drivers. + pub struct Adapter(T); +@@ -54,14 +58,14 @@ unsafe impl driver::RegistrationOps for Adapter { + + impl Adapter { + extern "C" fn probe_callback(pdev: *mut bindings::platform_device) -> kernel::ffi::c_int { +- // SAFETY: The platform bus only ever calls the probe callback with a valid `pdev`. +- let dev = unsafe { device::Device::get_device(addr_of_mut!((*pdev).dev)) }; +- // SAFETY: `dev` is guaranteed to be embedded in a valid `struct platform_device` by the +- // call above. +- let mut pdev = unsafe { Device::from_dev(dev) }; ++ // SAFETY: The platform bus only ever calls the probe callback with a valid pointer to a ++ // `struct platform_device`. ++ // ++ // INVARIANT: `pdev` is valid for the duration of `probe_callback()`. ++ let pdev = unsafe { &*pdev.cast::>() }; + + let info = ::id_info(pdev.as_ref()); +- match T::probe(&mut pdev, info) { ++ match T::probe(pdev, info) { + Ok(data) => { + // Let the `struct platform_device` own a reference of the driver's private data. + // SAFETY: By the type invariant `pdev.as_raw` returns a valid pointer to a +@@ -120,7 +124,7 @@ macro_rules! module_platform_driver { + /// # Example + /// + ///``` +-/// # use kernel::{bindings, c_str, of, platform}; ++/// # use kernel::{bindings, c_str, device::Core, of, platform}; + /// + /// struct MyDriver; + /// +@@ -138,7 +142,7 @@ macro_rules! module_platform_driver { + /// const OF_ID_TABLE: Option> = Some(&OF_TABLE); + /// + /// fn probe( +-/// _pdev: &mut platform::Device, ++/// _pdev: &platform::Device, + /// _id_info: Option<&Self::IdInfo>, + /// ) -> Result>> { + /// Err(ENODEV) +@@ -160,41 +164,72 @@ pub trait Driver { + /// + /// Called when a new platform device is added or discovered. + /// Implementers should attempt to initialize the device here. +- fn probe(dev: &mut Device, id_info: Option<&Self::IdInfo>) -> Result>>; ++ fn probe(dev: &Device, id_info: Option<&Self::IdInfo>) ++ -> Result>>; + } + + /// The platform device representation. + /// +-/// A platform device is based on an always reference counted `device:Device` instance. Cloning a +-/// platform device, hence, also increments the base device' reference count. ++/// This structure represents the Rust abstraction for a C `struct platform_device`. The ++/// implementation abstracts the usage of an already existing C `struct platform_device` within Rust ++/// code that we get passed from the C side. + /// + /// # Invariants + /// +-/// `Device` holds a valid reference of `ARef` whose underlying `struct device` is a +-/// member of a `struct platform_device`. +-#[derive(Clone)] +-pub struct Device(ARef); ++/// A [`Device`] instance represents a valid `struct platform_device` created by the C portion of ++/// the kernel. ++#[repr(transparent)] ++pub struct Device( ++ Opaque, ++ PhantomData, ++); + + impl Device { +- /// Convert a raw kernel device into a `Device` +- /// +- /// # Safety +- /// +- /// `dev` must be an `Aref` whose underlying `bindings::device` is a member of a +- /// `bindings::platform_device`. +- unsafe fn from_dev(dev: ARef) -> Self { +- Self(dev) ++ fn as_raw(&self) -> *mut bindings::platform_device { ++ self.0.get() + } ++} + +- fn as_raw(&self) -> *mut bindings::platform_device { +- // SAFETY: By the type invariant `self.0.as_raw` is a pointer to the `struct device` +- // embedded in `struct platform_device`. +- unsafe { container_of!(self.0.as_raw(), bindings::platform_device, dev) }.cast_mut() ++impl Deref for Device { ++ type Target = Device; ++ ++ fn deref(&self) -> &Self::Target { ++ let ptr: *const Self = self; ++ ++ // CAST: `Device` is a transparent wrapper of `Opaque`. ++ let ptr = ptr.cast::(); ++ ++ // SAFETY: `ptr` was derived from `&self`. ++ unsafe { &*ptr } ++ } ++} ++ ++impl From<&Device> for ARef { ++ fn from(dev: &Device) -> Self { ++ (&**dev).into() ++ } ++} ++ ++// SAFETY: Instances of `Device` are always reference-counted. ++unsafe impl crate::types::AlwaysRefCounted for Device { ++ fn inc_ref(&self) { ++ // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero. ++ unsafe { bindings::get_device(self.as_ref().as_raw()) }; ++ } ++ ++ unsafe fn dec_ref(obj: NonNull) { ++ // SAFETY: The safety requirements guarantee that the refcount is non-zero. ++ unsafe { bindings::platform_device_put(obj.cast().as_ptr()) } + } + } + + impl AsRef for Device { + fn as_ref(&self) -> &device::Device { +- &self.0 ++ // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid ++ // `struct platform_device`. ++ let dev = unsafe { addr_of_mut!((*self.as_raw()).dev) }; ++ ++ // SAFETY: `dev` points to a valid `struct device`. ++ unsafe { device::Device::as_ref(dev) } + } + } +diff --git a/samples/rust/rust_driver_platform.rs b/samples/rust/rust_driver_platform.rs +index 8120609e29402..9bb66db0a4f43 100644 +--- a/samples/rust/rust_driver_platform.rs ++++ b/samples/rust/rust_driver_platform.rs +@@ -2,10 +2,10 @@ + + //! Rust Platform driver sample. + +-use kernel::{c_str, of, platform, prelude::*}; ++use kernel::{c_str, device::Core, of, platform, prelude::*, types::ARef}; + + struct SampleDriver { +- pdev: platform::Device, ++ pdev: ARef, + } + + struct Info(u32); +@@ -21,14 +21,17 @@ impl platform::Driver for SampleDriver { + type IdInfo = Info; + const OF_ID_TABLE: Option> = Some(&OF_TABLE); + +- fn probe(pdev: &mut platform::Device, info: Option<&Self::IdInfo>) -> Result>> { ++ fn probe( ++ pdev: &platform::Device, ++ info: Option<&Self::IdInfo>, ++ ) -> Result>> { + dev_dbg!(pdev.as_ref(), "Probe Rust Platform driver sample.\n"); + + if let Some(info) = info { + dev_info!(pdev.as_ref(), "Probed with info: '{}'.\n", info.0); + } + +- let drvdata = KBox::new(Self { pdev: pdev.clone() }, GFP_KERNEL)?; ++ let drvdata = KBox::new(Self { pdev: pdev.into() }, GFP_KERNEL)?; + + Ok(drvdata.into()) + } +-- +2.39.5 + diff --git a/queue-6.14/rwonce-fix-crash-by-removing-read_once-for-unaligned.patch b/queue-6.14/rwonce-fix-crash-by-removing-read_once-for-unaligned.patch new file mode 100644 index 0000000000..539aa6d044 --- /dev/null +++ b/queue-6.14/rwonce-fix-crash-by-removing-read_once-for-unaligned.patch @@ -0,0 +1,50 @@ +From 465750d3aab3a885afbbe5cbd7150bd52ae7ea3a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Mar 2025 22:04:36 +0100 +Subject: rwonce: fix crash by removing READ_ONCE() for unaligned read + +From: Jann Horn + +[ Upstream commit 47a60391ae0ed04ffbb9bd8dcd94ad9d08b41288 ] + +When arm64 is built with LTO, it upgrades READ_ONCE() to ldar / ldapr +(load-acquire) to avoid issues that can be caused by the compiler +optimizing away implicit address dependencies. + +Unlike plain loads, these load-acquire instructions actually require an +aligned address. + +For now, fix it by removing the READ_ONCE() that the buggy commit +introduced. + +Fixes: ece69af2ede1 ("rwonce: handle KCSAN like KASAN in read_word_at_a_time()") +Reported-by: Nathan Chancellor +Closes: https://lore.kernel.org/r/20250326203926.GA10484@ax162 +Signed-off-by: Jann Horn +Signed-off-by: Arnd Bergmann +Signed-off-by: Sasha Levin +--- + include/asm-generic/rwonce.h | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/include/asm-generic/rwonce.h b/include/asm-generic/rwonce.h +index e9f2b84d2338c..52b969c7cef93 100644 +--- a/include/asm-generic/rwonce.h ++++ b/include/asm-generic/rwonce.h +@@ -86,7 +86,12 @@ unsigned long read_word_at_a_time(const void *addr) + kasan_check_read(addr, 1); + kcsan_check_read(addr, 1); + +- return READ_ONCE(*(unsigned long *)addr); ++ /* ++ * This load can race with concurrent stores to out-of-bounds memory, ++ * but READ_ONCE() can't be used because it requires higher alignment ++ * than plain loads in arm64 builds with LTO. ++ */ ++ return *(unsigned long *)addr; + } + + #endif /* __ASSEMBLY__ */ +-- +2.39.5 + diff --git a/queue-6.14/rwonce-handle-kcsan-like-kasan-in-read_word_at_a_tim.patch b/queue-6.14/rwonce-handle-kcsan-like-kasan-in-read_word_at_a_tim.patch new file mode 100644 index 0000000000..219eff8932 --- /dev/null +++ b/queue-6.14/rwonce-handle-kcsan-like-kasan-in-read_word_at_a_tim.patch @@ -0,0 +1,64 @@ +From b5c082982b69836ef3951ad22ce59abd18edcbf9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Mar 2025 17:01:34 +0100 +Subject: rwonce: handle KCSAN like KASAN in read_word_at_a_time() + +From: Jann Horn + +[ Upstream commit ece69af2ede103e190ffdfccd9f9ec850606ab5e ] + +read_word_at_a_time() is allowed to read out of bounds by straddling the +end of an allocation (and the caller is expected to then mask off +out-of-bounds data). This works as long as the caller guarantees that the +access won't hit a pagefault (either by ensuring that addr is aligned or by +explicitly checking where the next page boundary is). + +Such out-of-bounds data could include things like KASAN redzones, adjacent +allocations that are concurrently written to, or simply an adjacent struct +field that is concurrently updated. KCSAN should ignore racy reads of OOB +data that is not actually used, just like KASAN, so (similar to the code +above) change read_word_at_a_time() to use __no_sanitize_or_inline instead +of __no_kasan_or_inline, and explicitly inform KCSAN that we're reading +the first byte. + +We do have an instrument_read() helper that calls into both KASAN and +KCSAN, but I'm instead open-coding that here to avoid having to pull the +entire instrumented.h header into rwonce.h. + +Also, since this read can be racy by design, we should technically do +READ_ONCE(), so add that. + +Fixes: dfd402a4c4ba ("kcsan: Add Kernel Concurrency Sanitizer infrastructure") +Signed-off-by: Jann Horn +Acked-by: Arnd Bergmann +Acked-by: Marco Elver +Signed-off-by: Arnd Bergmann +Signed-off-by: Sasha Levin +--- + include/asm-generic/rwonce.h | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/include/asm-generic/rwonce.h b/include/asm-generic/rwonce.h +index 8d0a6280e9824..e9f2b84d2338c 100644 +--- a/include/asm-generic/rwonce.h ++++ b/include/asm-generic/rwonce.h +@@ -79,11 +79,14 @@ unsigned long __read_once_word_nocheck(const void *addr) + (typeof(x))__read_once_word_nocheck(&(x)); \ + }) + +-static __no_kasan_or_inline ++static __no_sanitize_or_inline + unsigned long read_word_at_a_time(const void *addr) + { ++ /* open-coded instrument_read(addr, 1) */ + kasan_check_read(addr, 1); +- return *(unsigned long *)addr; ++ kcsan_check_read(addr, 1); ++ ++ return READ_ONCE(*(unsigned long *)addr); + } + + #endif /* __ASSEMBLY__ */ +-- +2.39.5 + diff --git a/queue-6.14/s390-entry-fix-setting-_cif_mcck_guest-with-lowcore-.patch b/queue-6.14/s390-entry-fix-setting-_cif_mcck_guest-with-lowcore-.patch new file mode 100644 index 0000000000..57c8285056 --- /dev/null +++ b/queue-6.14/s390-entry-fix-setting-_cif_mcck_guest-with-lowcore-.patch @@ -0,0 +1,39 @@ +From e78432cc22292c4b182d0e4873259364a7a97d37 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Mar 2025 13:25:38 +0100 +Subject: s390/entry: Fix setting _CIF_MCCK_GUEST with lowcore relocation + +From: Sven Schnelle + +[ Upstream commit 121df45b37a1016ee6828c2ca3ba825f3e18a8c1 ] + +When lowcore relocation is enabled, the machine check handler doesn't +use the lowcore address when setting _CIF_MCCK_GUEST. Fix this by +adding the missing base register. + +Fixes: 0001b7bbc53a ("s390/entry: Make mchk_int_handler() ready for lowcore relocation") +Reported-by: Heiko Carstens +Reviewed-by: Heiko Carstens +Signed-off-by: Sven Schnelle +Signed-off-by: Vasily Gorbik +Signed-off-by: Sasha Levin +--- + arch/s390/kernel/entry.S | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S +index 4cc3408c4dacf..88e09a650d2df 100644 +--- a/arch/s390/kernel/entry.S ++++ b/arch/s390/kernel/entry.S +@@ -467,7 +467,7 @@ SYM_CODE_START(mcck_int_handler) + clgrjl %r9,%r14, 4f + larl %r14,.Lsie_leave + clgrjhe %r9,%r14, 4f +- lg %r10,__LC_PCPU ++ lg %r10,__LC_PCPU(%r13) + oi __PCPU_FLAGS+7(%r10), _CIF_MCCK_GUEST + 4: BPENTER __SF_SIE_FLAGS(%r15),_TIF_ISOLATE_BP_GUEST + SIEEXIT __SF_SIE_CONTROL(%r15),%r13 +-- +2.39.5 + diff --git a/queue-6.14/s390-remove-ioremap_wt-and-pgprot_writethrough.patch b/queue-6.14/s390-remove-ioremap_wt-and-pgprot_writethrough.patch new file mode 100644 index 0000000000..34f47ef406 --- /dev/null +++ b/queue-6.14/s390-remove-ioremap_wt-and-pgprot_writethrough.patch @@ -0,0 +1,89 @@ +From 5404ece582ee25065fbbd6bbb6003807e2a14854 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 12:51:48 +0100 +Subject: s390: Remove ioremap_wt() and pgprot_writethrough() + +From: Niklas Schnelle + +[ Upstream commit c94bff63e49302d4ce36502a85a2710a67332a4f ] + +It turns out that while s390 architecture calls its memory-I/O mapping +variants write-through and write-back the implementation of ioremap_wt() +and pgprot_writethrough() does not match Linux notion of ioremap_wt(). + +In particular Linux expects ioremap_wt() to be weaker still than +ioremap_wc(), allowing not just gathering and re-ordering but also reads +to be served from cache. Instead s390's implementation is equivalent to +normal ioremap() while its ioremap_wc() allows re-ordering. + +Note that there are no known users of ioremap_wt() on s390 and the +resulting behavior is in line with asm-generic defining ioremap_wt() as +ioremap(), if undefined, so no breakage is expected. + +As s390 does not have a mapping type matching the Linux notion of +ioremap_wt() and pgprot_writethrough(), simply drop them and rely on the +asm-generic fallbacks instead. + +Fixes: b02002cc4c0f ("s390/pci: Implement ioremap_wc/prot() with MIO") +Fixes: b43b3fff042d ("s390: mm: convert to GENERIC_IOREMAP") +Acked-by: Heiko Carstens +Signed-off-by: Niklas Schnelle +Signed-off-by: Vasily Gorbik +Signed-off-by: Sasha Levin +--- + arch/s390/include/asm/io.h | 2 -- + arch/s390/include/asm/pgtable.h | 3 --- + arch/s390/mm/pgtable.c | 10 ---------- + 3 files changed, 15 deletions(-) + +diff --git a/arch/s390/include/asm/io.h b/arch/s390/include/asm/io.h +index fc9933a743d69..251e0372ccbd0 100644 +--- a/arch/s390/include/asm/io.h ++++ b/arch/s390/include/asm/io.h +@@ -34,8 +34,6 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr); + + #define ioremap_wc(addr, size) \ + ioremap_prot((addr), (size), pgprot_val(pgprot_writecombine(PAGE_KERNEL))) +-#define ioremap_wt(addr, size) \ +- ioremap_prot((addr), (size), pgprot_val(pgprot_writethrough(PAGE_KERNEL))) + + static inline void __iomem *ioport_map(unsigned long port, unsigned int nr) + { +diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h +index 3ca5af4cfe432..2467e521e1c0f 100644 +--- a/arch/s390/include/asm/pgtable.h ++++ b/arch/s390/include/asm/pgtable.h +@@ -1402,9 +1402,6 @@ void gmap_pmdp_idte_global(struct mm_struct *mm, unsigned long vmaddr); + #define pgprot_writecombine pgprot_writecombine + pgprot_t pgprot_writecombine(pgprot_t prot); + +-#define pgprot_writethrough pgprot_writethrough +-pgprot_t pgprot_writethrough(pgprot_t prot); +- + #define PFN_PTE_SHIFT PAGE_SHIFT + + /* +diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c +index f05e62e037c28..a248764ad9586 100644 +--- a/arch/s390/mm/pgtable.c ++++ b/arch/s390/mm/pgtable.c +@@ -34,16 +34,6 @@ pgprot_t pgprot_writecombine(pgprot_t prot) + } + EXPORT_SYMBOL_GPL(pgprot_writecombine); + +-pgprot_t pgprot_writethrough(pgprot_t prot) +-{ +- /* +- * mio_wb_bit_mask may be set on a different CPU, but it is only set +- * once at init and only read afterwards. +- */ +- return __pgprot(pgprot_val(prot) & ~mio_wb_bit_mask); +-} +-EXPORT_SYMBOL_GPL(pgprot_writethrough); +- + static inline void ptep_ipte_local(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, int nodat) + { +-- +2.39.5 + diff --git a/queue-6.14/samples-bpf-fix-broken-vmlinux-path-for-vmlinux_btf.patch b/queue-6.14/samples-bpf-fix-broken-vmlinux-path-for-vmlinux_btf.patch new file mode 100644 index 0000000000..c5b3849733 --- /dev/null +++ b/queue-6.14/samples-bpf-fix-broken-vmlinux-path-for-vmlinux_btf.patch @@ -0,0 +1,45 @@ +From 482fb096daffe338832010c3126f7785936e238b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 02:55:05 -0600 +Subject: samples/bpf: Fix broken vmlinux path for VMLINUX_BTF + +From: Jinghao Jia + +[ Upstream commit 94f53edc64e19640b5245721cd6d0c4a84f52587 ] + +Commit 13b25489b6f8 ("kbuild: change working directory to external +module directory with M=") changed kbuild working directory of bpf +sample programs to samples/bpf, which broke the vmlinux path for +VMLINUX_BTF, as the Makefiles assume the current work directory to be +the kernel output directory and use a relative path (i.e., ./vmlinux): + + Makefile:316: *** Cannot find a vmlinux for VMLINUX_BTF at any of " /path/to/linux/samples/bpf/vmlinux", build the kernel or set VMLINUX_BTF like "VMLINUX_BTF=/sys/kernel/btf/vmlinux" or VMLINUX_H variable. Stop. + +Correctly refer to the kernel output directory using $(objtree). + +Fixes: 13b25489b6f8 ("kbuild: change working directory to external module directory with M=") +Signed-off-by: Jinghao Jia +Signed-off-by: Andrii Nakryiko +Tested-by: Ruowen Qin +Link: https://lore.kernel.org/bpf/20250203085506.220297-3-jinghao7@illinois.edu +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 dd9944a97b7e6..5b632635e00dd 100644 +--- a/samples/bpf/Makefile ++++ b/samples/bpf/Makefile +@@ -307,7 +307,7 @@ $(obj)/$(TRACE_HELPERS): TPROGS_CFLAGS := $(TPROGS_CFLAGS) -D__must_check= + + VMLINUX_BTF_PATHS ?= $(abspath $(if $(O),$(O)/vmlinux)) \ + $(abspath $(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux)) \ +- $(abspath ./vmlinux) ++ $(abspath $(objtree)/vmlinux) + VMLINUX_BTF ?= $(abspath $(firstword $(wildcard $(VMLINUX_BTF_PATHS)))) + + $(obj)/vmlinux.h: $(VMLINUX_BTF) $(BPFTOOL) +-- +2.39.5 + diff --git a/queue-6.14/sched-cancel-the-slice-protection-of-the-idle-entity.patch b/queue-6.14/sched-cancel-the-slice-protection-of-the-idle-entity.patch new file mode 100644 index 0000000000..105af89c17 --- /dev/null +++ b/queue-6.14/sched-cancel-the-slice-protection-of-the-idle-entity.patch @@ -0,0 +1,122 @@ +From fac3662d5fac40de36333ecf9874d63686a82da6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Feb 2025 16:08:52 +0800 +Subject: sched: Cancel the slice protection of the idle entity + +From: zihan zhou <15645113830zzh@gmail.com> + +[ Upstream commit f553741ac8c0e467a3b873e305f34b902e50b86d ] + +A wakeup non-idle entity should preempt idle entity at any time, +but because of the slice protection of the idle entity, the non-idle +entity has to wait, so just cancel it. + +This patch is aimed at minimizing the impact of SCHED_IDLE on +SCHED_NORMAL. For example, a task with SCHED_IDLE policy that sleeps for +1s and then runs for 3 ms, running cyclictest on the same cpu, has a +maximum latency of 3 ms, which is caused by the slice protection of the +idle entity. It is unreasonable. With this patch, the cyclictest latency +under the same conditions is basically the same on the cpu with idle +processes and on empty cpu. + +[peterz: add helpers] +Fixes: 63304558ba5d ("sched/eevdf: Curb wakeup-preemption") +Signed-off-by: zihan zhou <15645113830zzh@gmail.com> +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Vincent Guittot +Tested-by: Vincent Guittot +Link: https://lkml.kernel.org/r/20250208080850.16300-1-15645113830zzh@gmail.com +Signed-off-by: Sasha Levin +--- + kernel/sched/fair.c | 46 ++++++++++++++++++++++++++++++++------------- + 1 file changed, 33 insertions(+), 13 deletions(-) + +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index c798d27952431..61a5d08ac3324 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -883,6 +883,26 @@ struct sched_entity *__pick_first_entity(struct cfs_rq *cfs_rq) + return __node_2_se(left); + } + ++/* ++ * HACK, stash a copy of deadline at the point of pick in vlag, ++ * which isn't used until dequeue. ++ */ ++static inline void set_protect_slice(struct sched_entity *se) ++{ ++ se->vlag = se->deadline; ++} ++ ++static inline bool protect_slice(struct sched_entity *se) ++{ ++ return se->vlag == se->deadline; ++} ++ ++static inline void cancel_protect_slice(struct sched_entity *se) ++{ ++ if (protect_slice(se)) ++ se->vlag = se->deadline + 1; ++} ++ + /* + * Earliest Eligible Virtual Deadline First + * +@@ -919,11 +939,7 @@ static struct sched_entity *pick_eevdf(struct cfs_rq *cfs_rq) + if (curr && (!curr->on_rq || !entity_eligible(cfs_rq, curr))) + curr = NULL; + +- /* +- * Once selected, run a task until it either becomes non-eligible or +- * until it gets a new slice. See the HACK in set_next_entity(). +- */ +- if (sched_feat(RUN_TO_PARITY) && curr && curr->vlag == curr->deadline) ++ if (sched_feat(RUN_TO_PARITY) && curr && protect_slice(curr)) + return curr; + + /* Pick the leftmost entity if it's eligible */ +@@ -5530,11 +5546,8 @@ set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se) + update_stats_wait_end_fair(cfs_rq, se); + __dequeue_entity(cfs_rq, se); + update_load_avg(cfs_rq, se, UPDATE_TG); +- /* +- * HACK, stash a copy of deadline at the point of pick in vlag, +- * which isn't used until dequeue. +- */ +- se->vlag = se->deadline; ++ ++ set_protect_slice(se); + } + + update_stats_curr_start(cfs_rq, se); +@@ -8783,8 +8796,15 @@ static void check_preempt_wakeup_fair(struct rq *rq, struct task_struct *p, int + * Preempt an idle entity in favor of a non-idle entity (and don't preempt + * in the inverse case). + */ +- if (cse_is_idle && !pse_is_idle) ++ if (cse_is_idle && !pse_is_idle) { ++ /* ++ * When non-idle entity preempt an idle entity, ++ * don't give idle entity slice protection. ++ */ ++ cancel_protect_slice(se); + goto preempt; ++ } ++ + if (cse_is_idle != pse_is_idle) + return; + +@@ -8803,8 +8823,8 @@ static void check_preempt_wakeup_fair(struct rq *rq, struct task_struct *p, int + * Note that even if @p does not turn out to be the most eligible + * task at this moment, current's slice protection will be lost. + */ +- if (do_preempt_short(cfs_rq, pse, se) && se->vlag == se->deadline) +- se->vlag = se->deadline + 1; ++ if (do_preempt_short(cfs_rq, pse, se)) ++ cancel_protect_slice(se); + + /* + * If @p has become the most eligible task, force preemption. +-- +2.39.5 + diff --git a/queue-6.14/sched-deadline-generalize-unique-visiting-of-root-do.patch b/queue-6.14/sched-deadline-generalize-unique-visiting-of-root-do.patch new file mode 100644 index 0000000000..32fa11b12e --- /dev/null +++ b/queue-6.14/sched-deadline-generalize-unique-visiting-of-root-do.patch @@ -0,0 +1,178 @@ +From 7be559207be61d4a61078dffcde5dcb68135cfd3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 18:05:46 +0100 +Subject: sched/deadline: Generalize unique visiting of root domains + +From: Juri Lelli + +[ Upstream commit 45007c6fb5860cf63556a9cadc87c8984927e23d ] + +Bandwidth checks and updates that work on root domains currently employ +a cookie mechanism for efficiency. This mechanism is very much tied to +when root domains are first created and initialized. + +Generalize the cookie mechanism so that it can be used also later at +runtime while updating root domains. Also, additionally guard it with +sched_domains_mutex, since domains need to be stable while updating them +(and it will be required for further dynamic changes). + +Fixes: 53916d5fd3c0 ("sched/deadline: Check bandwidth overflow earlier for hotplug") +Reported-by: Jon Hunter +Signed-off-by: Juri Lelli +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Valentin Schneider +Reviewed-by: Dietmar Eggemann +Tested-by: Waiman Long +Tested-by: Jon Hunter +Tested-by: Dietmar Eggemann +Link: https://lore.kernel.org/r/Z9MQaiXPvEeW_v7x@jlelli-thinkpadt14gen4.remote.csb +Signed-off-by: Sasha Levin +--- + include/linux/sched/deadline.h | 3 +++ + kernel/sched/deadline.c | 23 +++++++++++++---------- + kernel/sched/rt.c | 2 ++ + kernel/sched/sched.h | 2 +- + kernel/sched/topology.c | 2 +- + 5 files changed, 20 insertions(+), 12 deletions(-) + +diff --git a/include/linux/sched/deadline.h b/include/linux/sched/deadline.h +index 3a912ab42bb55..6ec578600b24c 100644 +--- a/include/linux/sched/deadline.h ++++ b/include/linux/sched/deadline.h +@@ -37,4 +37,7 @@ extern void dl_clear_root_domain(struct root_domain *rd); + + #endif /* CONFIG_SMP */ + ++extern u64 dl_cookie; ++extern bool dl_bw_visited(int cpu, u64 cookie); ++ + #endif /* _LINUX_SCHED_DEADLINE_H */ +diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c +index 1a041c1fc0d1e..3e05032e9e0eb 100644 +--- a/kernel/sched/deadline.c ++++ b/kernel/sched/deadline.c +@@ -166,14 +166,14 @@ static inline unsigned long dl_bw_capacity(int i) + } + } + +-static inline bool dl_bw_visited(int cpu, u64 gen) ++static inline bool dl_bw_visited(int cpu, u64 cookie) + { + struct root_domain *rd = cpu_rq(cpu)->rd; + +- if (rd->visit_gen == gen) ++ if (rd->visit_cookie == cookie) + return true; + +- rd->visit_gen = gen; ++ rd->visit_cookie = cookie; + return false; + } + +@@ -207,7 +207,7 @@ static inline unsigned long dl_bw_capacity(int i) + return SCHED_CAPACITY_SCALE; + } + +-static inline bool dl_bw_visited(int cpu, u64 gen) ++static inline bool dl_bw_visited(int cpu, u64 cookie) + { + return false; + } +@@ -3171,15 +3171,18 @@ DEFINE_SCHED_CLASS(dl) = { + #endif + }; + +-/* Used for dl_bw check and update, used under sched_rt_handler()::mutex */ +-static u64 dl_generation; ++/* ++ * Used for dl_bw check and update, used under sched_rt_handler()::mutex and ++ * sched_domains_mutex. ++ */ ++u64 dl_cookie; + + int sched_dl_global_validate(void) + { + u64 runtime = global_rt_runtime(); + u64 period = global_rt_period(); + u64 new_bw = to_ratio(period, runtime); +- u64 gen = ++dl_generation; ++ u64 cookie = ++dl_cookie; + struct dl_bw *dl_b; + int cpu, cpus, ret = 0; + unsigned long flags; +@@ -3192,7 +3195,7 @@ int sched_dl_global_validate(void) + for_each_online_cpu(cpu) { + rcu_read_lock_sched(); + +- if (dl_bw_visited(cpu, gen)) ++ if (dl_bw_visited(cpu, cookie)) + goto next; + + dl_b = dl_bw_of(cpu); +@@ -3229,7 +3232,7 @@ static void init_dl_rq_bw_ratio(struct dl_rq *dl_rq) + void sched_dl_do_global(void) + { + u64 new_bw = -1; +- u64 gen = ++dl_generation; ++ u64 cookie = ++dl_cookie; + struct dl_bw *dl_b; + int cpu; + unsigned long flags; +@@ -3240,7 +3243,7 @@ void sched_dl_do_global(void) + for_each_possible_cpu(cpu) { + rcu_read_lock_sched(); + +- if (dl_bw_visited(cpu, gen)) { ++ if (dl_bw_visited(cpu, cookie)) { + rcu_read_unlock_sched(); + continue; + } +diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c +index 4b8e33c615b12..8cebe71d2bb16 100644 +--- a/kernel/sched/rt.c ++++ b/kernel/sched/rt.c +@@ -2910,6 +2910,7 @@ static int sched_rt_handler(const struct ctl_table *table, int write, void *buff + int ret; + + mutex_lock(&mutex); ++ sched_domains_mutex_lock(); + old_period = sysctl_sched_rt_period; + old_runtime = sysctl_sched_rt_runtime; + +@@ -2936,6 +2937,7 @@ static int sched_rt_handler(const struct ctl_table *table, int write, void *buff + sysctl_sched_rt_period = old_period; + sysctl_sched_rt_runtime = old_runtime; + } ++ sched_domains_mutex_unlock(); + mutex_unlock(&mutex); + + return ret; +diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h +index 023b844159c94..1aa65a0ac5864 100644 +--- a/kernel/sched/sched.h ++++ b/kernel/sched/sched.h +@@ -998,7 +998,7 @@ struct root_domain { + * Also, some corner cases, like 'wrap around' is dangerous, but given + * that u64 is 'big enough'. So that shouldn't be a concern. + */ +- u64 visit_gen; ++ u64 visit_cookie; + + #ifdef HAVE_RT_PUSH_IPI + /* +diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c +index 296ff2acfd321..44093339761c9 100644 +--- a/kernel/sched/topology.c ++++ b/kernel/sched/topology.c +@@ -568,7 +568,7 @@ static int init_rootdomain(struct root_domain *rd) + rd->rto_push_work = IRQ_WORK_INIT_HARD(rto_push_irq_work_func); + #endif + +- rd->visit_gen = 0; ++ rd->visit_cookie = 0; + init_dl_bw(&rd->dl_bw); + if (cpudl_init(&rd->cpudl) != 0) + goto free_rto_mask; +-- +2.39.5 + diff --git a/queue-6.14/sched-deadline-ignore-special-tasks-when-rebuilding-.patch b/queue-6.14/sched-deadline-ignore-special-tasks-when-rebuilding-.patch new file mode 100644 index 0000000000..6fbd2c0659 --- /dev/null +++ b/queue-6.14/sched-deadline-ignore-special-tasks-when-rebuilding-.patch @@ -0,0 +1,46 @@ +From 9d244e2638d26f426e9628839e421a02108119d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 18:00:04 +0100 +Subject: sched/deadline: Ignore special tasks when rebuilding domains + +From: Juri Lelli + +[ Upstream commit f6147af176eaa4027b692fdbb1a0a60dfaa1e9b6 ] + +SCHED_DEADLINE special tasks get a fake bandwidth that is only used to +make sure sleeping and priority inheritance 'work', but it is ignored +for runtime enforcement and admission control. + +Be consistent with it also when rebuilding root domains. + +Fixes: 53916d5fd3c0 ("sched/deadline: Check bandwidth overflow earlier for hotplug") +Reported-by: Jon Hunter +Signed-off-by: Juri Lelli +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Valentin Schneider +Reviewed-by: Dietmar Eggemann +Tested-by: Waiman Long +Tested-by: Jon Hunter +Tested-by: Dietmar Eggemann +Link: https://lore.kernel.org/r/20250313170011.357208-2-juri.lelli@redhat.com +Signed-off-by: Sasha Levin +--- + kernel/sched/deadline.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c +index ff4df16b5186d..1a041c1fc0d1e 100644 +--- a/kernel/sched/deadline.c ++++ b/kernel/sched/deadline.c +@@ -2956,7 +2956,7 @@ void dl_add_task_root_domain(struct task_struct *p) + struct dl_bw *dl_b; + + raw_spin_lock_irqsave(&p->pi_lock, rf.flags); +- if (!dl_task(p)) { ++ if (!dl_task(p) || dl_entity_is_special(&p->dl)) { + raw_spin_unlock_irqrestore(&p->pi_lock, rf.flags); + return; + } +-- +2.39.5 + diff --git a/queue-6.14/sched-deadline-rebuild-root-domain-accounting-after-.patch b/queue-6.14/sched-deadline-rebuild-root-domain-accounting-after-.patch new file mode 100644 index 0000000000..b5d079ffde --- /dev/null +++ b/queue-6.14/sched-deadline-rebuild-root-domain-accounting-after-.patch @@ -0,0 +1,234 @@ +From 5c8caaa13f60a2e10b381b6490882b573c07b9ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 18:10:21 +0100 +Subject: sched/deadline: Rebuild root domain accounting after every update + +From: Juri Lelli + +[ Upstream commit 2ff899e3516437354204423ef0a94994717b8e6a ] + +Rebuilding of root domains accounting information (total_bw) is +currently broken on some cases, e.g. suspend/resume on aarch64. Problem +is that the way we keep track of domain changes and try to add bandwidth +back is convoluted and fragile. + +Fix it by simplify things by making sure bandwidth accounting is cleared +and completely restored after root domains changes (after root domains +are again stable). + +To be sure we always call dl_rebuild_rd_accounting while holding +cpuset_mutex we also add cpuset_reset_sched_domains() wrapper. + +Fixes: 53916d5fd3c0 ("sched/deadline: Check bandwidth overflow earlier for hotplug") +Reported-by: Jon Hunter +Co-developed-by: Waiman Long +Signed-off-by: Waiman Long +Signed-off-by: Juri Lelli +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Dietmar Eggemann +Tested-by: Dietmar Eggemann +Link: https://lore.kernel.org/r/Z9MRfeJKJUOyUSto@jlelli-thinkpadt14gen4.remote.csb +Signed-off-by: Sasha Levin +--- + include/linux/cpuset.h | 6 ++++++ + include/linux/sched/deadline.h | 1 + + include/linux/sched/topology.h | 2 ++ + kernel/cgroup/cpuset.c | 23 ++++++++++++++++------- + kernel/sched/core.c | 4 ++-- + kernel/sched/deadline.c | 16 ++++++++++------ + kernel/sched/topology.c | 1 + + 7 files changed, 38 insertions(+), 15 deletions(-) + +diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h +index 835e7b793f6a3..17cc90d900f96 100644 +--- a/include/linux/cpuset.h ++++ b/include/linux/cpuset.h +@@ -128,6 +128,7 @@ extern bool current_cpuset_is_being_rebound(void); + extern void rebuild_sched_domains(void); + + extern void cpuset_print_current_mems_allowed(void); ++extern void cpuset_reset_sched_domains(void); + + /* + * read_mems_allowed_begin is required when making decisions involving +@@ -264,6 +265,11 @@ static inline void rebuild_sched_domains(void) + partition_sched_domains(1, NULL, NULL); + } + ++static inline void cpuset_reset_sched_domains(void) ++{ ++ partition_sched_domains(1, NULL, NULL); ++} ++ + static inline void cpuset_print_current_mems_allowed(void) + { + } +diff --git a/include/linux/sched/deadline.h b/include/linux/sched/deadline.h +index 6ec578600b24c..f9aabbc9d22ef 100644 +--- a/include/linux/sched/deadline.h ++++ b/include/linux/sched/deadline.h +@@ -34,6 +34,7 @@ static inline bool dl_time_before(u64 a, u64 b) + struct root_domain; + extern void dl_add_task_root_domain(struct task_struct *p); + extern void dl_clear_root_domain(struct root_domain *rd); ++extern void dl_clear_root_domain_cpu(int cpu); + + #endif /* CONFIG_SMP */ + +diff --git a/include/linux/sched/topology.h b/include/linux/sched/topology.h +index 7f3dbafe18177..1622232bd08b9 100644 +--- a/include/linux/sched/topology.h ++++ b/include/linux/sched/topology.h +@@ -166,6 +166,8 @@ static inline struct cpumask *sched_domain_span(struct sched_domain *sd) + return to_cpumask(sd->span); + } + ++extern void dl_rebuild_rd_accounting(void); ++ + extern void partition_sched_domains_locked(int ndoms_new, + cpumask_var_t doms_new[], + struct sched_domain_attr *dattr_new); +diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c +index f87526edb2a46..1892dc8cd2119 100644 +--- a/kernel/cgroup/cpuset.c ++++ b/kernel/cgroup/cpuset.c +@@ -954,10 +954,12 @@ static void dl_update_tasks_root_domain(struct cpuset *cs) + css_task_iter_end(&it); + } + +-static void dl_rebuild_rd_accounting(void) ++void dl_rebuild_rd_accounting(void) + { + struct cpuset *cs = NULL; + struct cgroup_subsys_state *pos_css; ++ int cpu; ++ u64 cookie = ++dl_cookie; + + lockdep_assert_held(&cpuset_mutex); + lockdep_assert_cpus_held(); +@@ -965,11 +967,12 @@ static void dl_rebuild_rd_accounting(void) + + rcu_read_lock(); + +- /* +- * Clear default root domain DL accounting, it will be computed again +- * if a task belongs to it. +- */ +- dl_clear_root_domain(&def_root_domain); ++ for_each_possible_cpu(cpu) { ++ if (dl_bw_visited(cpu, cookie)) ++ continue; ++ ++ dl_clear_root_domain_cpu(cpu); ++ } + + cpuset_for_each_descendant_pre(cs, pos_css, &top_cpuset) { + +@@ -996,7 +999,6 @@ partition_and_rebuild_sched_domains(int ndoms_new, cpumask_var_t doms_new[], + { + sched_domains_mutex_lock(); + partition_sched_domains_locked(ndoms_new, doms_new, dattr_new); +- dl_rebuild_rd_accounting(); + sched_domains_mutex_unlock(); + } + +@@ -1083,6 +1085,13 @@ void rebuild_sched_domains(void) + cpus_read_unlock(); + } + ++void cpuset_reset_sched_domains(void) ++{ ++ mutex_lock(&cpuset_mutex); ++ partition_sched_domains(1, NULL, NULL); ++ mutex_unlock(&cpuset_mutex); ++} ++ + /** + * cpuset_update_tasks_cpumask - Update the cpumasks of tasks in the cpuset. + * @cs: the cpuset in which each task's cpus_allowed mask needs to be changed +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index 8adf495491179..3c7c942c7c429 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -8183,7 +8183,7 @@ static void cpuset_cpu_active(void) + * operation in the resume sequence, just build a single sched + * domain, ignoring cpusets. + */ +- partition_sched_domains(1, NULL, NULL); ++ cpuset_reset_sched_domains(); + if (--num_cpus_frozen) + return; + /* +@@ -8202,7 +8202,7 @@ static void cpuset_cpu_inactive(unsigned int cpu) + cpuset_update_active_cpus(); + } else { + num_cpus_frozen++; +- partition_sched_domains(1, NULL, NULL); ++ cpuset_reset_sched_domains(); + } + } + +diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c +index 3e05032e9e0eb..5dca336cdd7ca 100644 +--- a/kernel/sched/deadline.c ++++ b/kernel/sched/deadline.c +@@ -166,7 +166,7 @@ static inline unsigned long dl_bw_capacity(int i) + } + } + +-static inline bool dl_bw_visited(int cpu, u64 cookie) ++bool dl_bw_visited(int cpu, u64 cookie) + { + struct root_domain *rd = cpu_rq(cpu)->rd; + +@@ -207,7 +207,7 @@ static inline unsigned long dl_bw_capacity(int i) + return SCHED_CAPACITY_SCALE; + } + +-static inline bool dl_bw_visited(int cpu, u64 cookie) ++bool dl_bw_visited(int cpu, u64 cookie) + { + return false; + } +@@ -2981,18 +2981,22 @@ void dl_clear_root_domain(struct root_domain *rd) + rd->dl_bw.total_bw = 0; + + /* +- * dl_server bandwidth is only restored when CPUs are attached to root +- * domains (after domains are created or CPUs moved back to the +- * default root doamin). ++ * dl_servers are not tasks. Since dl_add_task_root_domain ignores ++ * them, we need to account for them here explicitly. + */ + for_each_cpu(i, rd->span) { + struct sched_dl_entity *dl_se = &cpu_rq(i)->fair_server; + + if (dl_server(dl_se) && cpu_active(i)) +- rd->dl_bw.total_bw += dl_se->dl_bw; ++ __dl_add(&rd->dl_bw, dl_se->dl_bw, dl_bw_cpus(i)); + } + } + ++void dl_clear_root_domain_cpu(int cpu) ++{ ++ dl_clear_root_domain(cpu_rq(cpu)->rd); ++} ++ + #endif /* CONFIG_SMP */ + + static void switched_from_dl(struct rq *rq, struct task_struct *p) +diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c +index 44093339761c9..363ad268a25b0 100644 +--- a/kernel/sched/topology.c ++++ b/kernel/sched/topology.c +@@ -2791,6 +2791,7 @@ void partition_sched_domains_locked(int ndoms_new, cpumask_var_t doms_new[], + ndoms_cur = ndoms_new; + + update_sched_domain_debugfs(); ++ dl_rebuild_rd_accounting(); + } + + /* +-- +2.39.5 + diff --git a/queue-6.14/sched-eevdf-force-propagating-min_slice-of-cfs_rq-wh.patch b/queue-6.14/sched-eevdf-force-propagating-min_slice-of-cfs_rq-wh.patch new file mode 100644 index 0000000000..6d642c28d7 --- /dev/null +++ b/queue-6.14/sched-eevdf-force-propagating-min_slice-of-cfs_rq-wh.patch @@ -0,0 +1,53 @@ +From 337aaaf9918909dcfe54fa9376be74b91a073f72 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 14:36:59 +0800 +Subject: sched/eevdf: Force propagating min_slice of cfs_rq when {en,de}queue + tasks + +From: Tianchen Ding + +[ Upstream commit 563bc2161b94571ea425bbe2cf69fd38e24cdedf ] + +When a task is enqueued and its parent cgroup se is already on_rq, this +parent cgroup se will not be enqueued again, and hence the root->min_slice +leaves unchanged. The same issue happens when a task is dequeued and its +parent cgroup se has other runnable entities, and the parent cgroup se +will not be dequeued. + +Force propagating min_slice when se doesn't need to be enqueued or +dequeued. Ensure the se hierarchy always get the latest min_slice. + +Fixes: aef6987d8954 ("sched/eevdf: Propagate min_slice up the cgroup hierarchy") +Signed-off-by: Tianchen Ding +Signed-off-by: Peter Zijlstra (Intel) +Link: https://lkml.kernel.org/r/20250211063659.7180-1-dtcccc@linux.alibaba.com +Signed-off-by: Sasha Levin +--- + kernel/sched/fair.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index 61a5d08ac3324..89c7260103e18 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -7004,6 +7004,8 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags) + update_cfs_group(se); + + se->slice = slice; ++ if (se != cfs_rq->curr) ++ min_vruntime_cb_propagate(&se->run_node, NULL); + slice = cfs_rq_min_slice(cfs_rq); + + cfs_rq->h_nr_runnable += h_nr_runnable; +@@ -7133,6 +7135,8 @@ static int dequeue_entities(struct rq *rq, struct sched_entity *se, int flags) + update_cfs_group(se); + + se->slice = slice; ++ if (se != cfs_rq->curr) ++ min_vruntime_cb_propagate(&se->run_node, NULL); + slice = cfs_rq_min_slice(cfs_rq); + + cfs_rq->h_nr_runnable -= h_nr_runnable; +-- +2.39.5 + diff --git a/queue-6.14/sched-smt-always-inline-sched_smt_active.patch b/queue-6.14/sched-smt-always-inline-sched_smt_active.patch new file mode 100644 index 0000000000..cc8d6dab34 --- /dev/null +++ b/queue-6.14/sched-smt-always-inline-sched_smt_active.patch @@ -0,0 +1,45 @@ +From b5ff0bfab76f41e654998f3b4caf98e757aeb617 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Mar 2025 21:26:44 -0700 +Subject: sched/smt: Always inline sched_smt_active() + +From: Josh Poimboeuf + +[ Upstream commit 09f37f2d7b21ff35b8b533f9ab8cfad2fe8f72f6 ] + +sched_smt_active() can be called from noinstr code, so it should always +be inlined. The CONFIG_SCHED_SMT version already has __always_inline. +Do the same for its !CONFIG_SCHED_SMT counterpart. + +Fixes the following warning: + + vmlinux.o: error: objtool: intel_idle_ibrs+0x13: call to sched_smt_active() leaves .noinstr.text section + +Fixes: 321a874a7ef8 ("sched/smt: Expose sched_smt_present static key") +Reported-by: kernel test robot +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/1d03907b0a247cf7fb5c1d518de378864f603060.1743481539.git.jpoimboe@kernel.org +Closes: https://lore.kernel.org/r/202503311434.lyw2Tveh-lkp@intel.com/ +Signed-off-by: Sasha Levin +--- + include/linux/sched/smt.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/sched/smt.h b/include/linux/sched/smt.h +index fb1e295e7e63e..166b19af956f8 100644 +--- a/include/linux/sched/smt.h ++++ b/include/linux/sched/smt.h +@@ -12,7 +12,7 @@ static __always_inline bool sched_smt_active(void) + return static_branch_likely(&sched_smt_present); + } + #else +-static inline bool sched_smt_active(void) { return false; } ++static __always_inline bool sched_smt_active(void) { return false; } + #endif + + void arch_smt_update(void); +-- +2.39.5 + diff --git a/queue-6.14/sched-topology-wrappers-for-sched_domains_mutex.patch b/queue-6.14/sched-topology-wrappers-for-sched_domains_mutex.patch new file mode 100644 index 0000000000..fe94dfdd1e --- /dev/null +++ b/queue-6.14/sched-topology-wrappers-for-sched_domains_mutex.patch @@ -0,0 +1,147 @@ +From 4f582264c66c2b62705ee4bf376c4226718dd3bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 18:03:32 +0100 +Subject: sched/topology: Wrappers for sched_domains_mutex + +From: Juri Lelli + +[ Upstream commit 56209334dda1832c0a919e1d74768c6d0f3b2ca9 ] + +Create wrappers for sched_domains_mutex so that it can transparently be +used on both CONFIG_SMP and !CONFIG_SMP, as some function will need to +do. + +Fixes: 53916d5fd3c0 ("sched/deadline: Check bandwidth overflow earlier for hotplug") +Reported-by: Jon Hunter +Signed-off-by: Juri Lelli +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Valentin Schneider +Reviewed-by: Dietmar Eggemann +Tested-by: Waiman Long +Tested-by: Jon Hunter +Tested-by: Dietmar Eggemann +Link: https://lore.kernel.org/r/Z9MP5Oq9RB8jBs3y@jlelli-thinkpadt14gen4.remote.csb +Signed-off-by: Sasha Levin +--- + include/linux/sched.h | 5 +++++ + kernel/cgroup/cpuset.c | 4 ++-- + kernel/sched/core.c | 4 ++-- + kernel/sched/debug.c | 8 ++++---- + kernel/sched/topology.c | 12 ++++++++++-- + 5 files changed, 23 insertions(+), 10 deletions(-) + +diff --git a/include/linux/sched.h b/include/linux/sched.h +index b13c9545d5d67..6e5c38718ff56 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -383,6 +383,11 @@ enum uclamp_id { + #ifdef CONFIG_SMP + extern struct root_domain def_root_domain; + extern struct mutex sched_domains_mutex; ++extern void sched_domains_mutex_lock(void); ++extern void sched_domains_mutex_unlock(void); ++#else ++static inline void sched_domains_mutex_lock(void) { } ++static inline void sched_domains_mutex_unlock(void) { } + #endif + + struct sched_param { +diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c +index 0f910c828973a..f87526edb2a46 100644 +--- a/kernel/cgroup/cpuset.c ++++ b/kernel/cgroup/cpuset.c +@@ -994,10 +994,10 @@ static void + partition_and_rebuild_sched_domains(int ndoms_new, cpumask_var_t doms_new[], + struct sched_domain_attr *dattr_new) + { +- mutex_lock(&sched_domains_mutex); ++ sched_domains_mutex_lock(); + partition_sched_domains_locked(ndoms_new, doms_new, dattr_new); + dl_rebuild_rd_accounting(); +- mutex_unlock(&sched_domains_mutex); ++ sched_domains_mutex_unlock(); + } + + /* +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index 042351c7afce7..8adf495491179 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -8424,9 +8424,9 @@ void __init sched_init_smp(void) + * CPU masks are stable and all blatant races in the below code cannot + * happen. + */ +- mutex_lock(&sched_domains_mutex); ++ sched_domains_mutex_lock(); + sched_init_domains(cpu_active_mask); +- mutex_unlock(&sched_domains_mutex); ++ sched_domains_mutex_unlock(); + + /* Move init over to a non-isolated CPU */ + if (set_cpus_allowed_ptr(current, housekeeping_cpumask(HK_TYPE_DOMAIN)) < 0) +diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c +index ef047add7f9e6..a0893a483d35d 100644 +--- a/kernel/sched/debug.c ++++ b/kernel/sched/debug.c +@@ -292,7 +292,7 @@ static ssize_t sched_verbose_write(struct file *filp, const char __user *ubuf, + bool orig; + + cpus_read_lock(); +- mutex_lock(&sched_domains_mutex); ++ sched_domains_mutex_lock(); + + orig = sched_debug_verbose; + result = debugfs_write_file_bool(filp, ubuf, cnt, ppos); +@@ -304,7 +304,7 @@ static ssize_t sched_verbose_write(struct file *filp, const char __user *ubuf, + sd_dentry = NULL; + } + +- mutex_unlock(&sched_domains_mutex); ++ sched_domains_mutex_unlock(); + cpus_read_unlock(); + + return result; +@@ -515,9 +515,9 @@ static __init int sched_init_debug(void) + debugfs_create_u32("migration_cost_ns", 0644, debugfs_sched, &sysctl_sched_migration_cost); + debugfs_create_u32("nr_migrate", 0644, debugfs_sched, &sysctl_sched_nr_migrate); + +- mutex_lock(&sched_domains_mutex); ++ sched_domains_mutex_lock(); + update_sched_domain_debugfs(); +- mutex_unlock(&sched_domains_mutex); ++ sched_domains_mutex_unlock(); + #endif + + #ifdef CONFIG_NUMA_BALANCING +diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c +index c49aea8c10254..296ff2acfd321 100644 +--- a/kernel/sched/topology.c ++++ b/kernel/sched/topology.c +@@ -6,6 +6,14 @@ + #include + + DEFINE_MUTEX(sched_domains_mutex); ++void sched_domains_mutex_lock(void) ++{ ++ mutex_lock(&sched_domains_mutex); ++} ++void sched_domains_mutex_unlock(void) ++{ ++ mutex_unlock(&sched_domains_mutex); ++} + + /* Protected by sched_domains_mutex: */ + static cpumask_var_t sched_domains_tmpmask; +@@ -2791,7 +2799,7 @@ void partition_sched_domains_locked(int ndoms_new, cpumask_var_t doms_new[], + void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[], + struct sched_domain_attr *dattr_new) + { +- mutex_lock(&sched_domains_mutex); ++ sched_domains_mutex_lock(); + partition_sched_domains_locked(ndoms_new, doms_new, dattr_new); +- mutex_unlock(&sched_domains_mutex); ++ sched_domains_mutex_unlock(); + } +-- +2.39.5 + diff --git a/queue-6.14/scripts-gdb-linux-symbols.py-address-changes-to-modu.patch b/queue-6.14/scripts-gdb-linux-symbols.py-address-changes-to-modu.patch new file mode 100644 index 0000000000..295dc1c943 --- /dev/null +++ b/queue-6.14/scripts-gdb-linux-symbols.py-address-changes-to-modu.patch @@ -0,0 +1,76 @@ +From 8221cb6460dce0253cba437e959f740a01775ce0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 21:40:34 +0100 +Subject: scripts/gdb/linux/symbols.py: address changes to module_sect_attrs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Antonio Quartulli + +[ Upstream commit e0349c46cb4fbbb507fa34476bd70f9c82bad359 ] + +When loading symbols from kernel modules we used to iterate +from 0 to module_sect_attrs::nsections, in order to +retrieve their name and address. + +However module_sect_attrs::nsections has been removed from +the struct by a previous commit. + +Re-arrange the iteration by accessing all items in +module_sect_attrs::grp::bin_attrs[] until NULL is found +(it's a NULL terminated array). + +At the same time the symbol address cannot be extracted +from module_sect_attrs::attrs[]::address anymore because +it has also been deleted. Fetch it from +module_sect_attrs::grp::bin_attrs[]::private as described +in 4b2c11e4aaf7. + +Link: https://lkml.kernel.org/r/20250221204034.4430-1-antonio@mandelbit.com +Fixes: d8959b947a8d ("module: sysfs: Drop member 'module_sect_attrs::nsections'") +Fixes: 4b2c11e4aaf7 ("module: sysfs: Drop member 'module_sect_attr::address'") +Signed-off-by: Antonio Quartulli +Reviewed-by: Jan Kiszka +Cc: Thomas Weißschuh +Cc: Kieran Bingham +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + scripts/gdb/linux/symbols.py | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py +index f6c1b063775a7..15d76f7d8ebce 100644 +--- a/scripts/gdb/linux/symbols.py ++++ b/scripts/gdb/linux/symbols.py +@@ -15,6 +15,7 @@ import gdb + import os + import re + ++from itertools import count + from linux import modules, utils, constants + + +@@ -95,10 +96,14 @@ lx-symbols command.""" + except gdb.error: + return str(module_addr) + +- attrs = sect_attrs['attrs'] +- section_name_to_address = { +- attrs[n]['battr']['attr']['name'].string(): attrs[n]['address'] +- for n in range(int(sect_attrs['nsections']))} ++ section_name_to_address = {} ++ for i in count(): ++ # this is a NULL terminated array ++ if sect_attrs['grp']['bin_attrs'][i] == 0x0: ++ break ++ ++ attr = sect_attrs['grp']['bin_attrs'][i].dereference() ++ section_name_to_address[attr['attr']['name'].string()] = attr['private'] + + textaddr = section_name_to_address.get(".text", module_addr) + args = [] +-- +2.39.5 + diff --git a/queue-6.14/scsi-hisi_sas-fixed-failure-to-issue-vendor-specific.patch b/queue-6.14/scsi-hisi_sas-fixed-failure-to-issue-vendor-specific.patch new file mode 100644 index 0000000000..884d07ceb1 --- /dev/null +++ b/queue-6.14/scsi-hisi_sas-fixed-failure-to-issue-vendor-specific.patch @@ -0,0 +1,122 @@ +From ee438a3ecbec53b6bc4e1d6f9bdc5c14f951b6e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 17:00:11 +0800 +Subject: scsi: hisi_sas: Fixed failure to issue vendor specific commands + +From: Xingui Yang + +[ Upstream commit 750d4fbe2c20e65d764c70afe2c9e6cfa874b044 ] + +At present, we determine the protocol through the cmd type, but other cmd +types, such as vendor-specific commands, default to the PIO protocol. This +strategy often causes the execution of different vendor-specific commands +to fail. In fact, for these commands, a better way is to use the protocol +configured by the command's tf to determine its protocol. + +Fixes: 6f2ff1a1311e ("hisi_sas: add v2 path to send ATA command") +Signed-off-by: Xingui Yang +Link: https://lore.kernel.org/r/20250220090011.313848-1-liyihang9@huawei.com +Reviewed-by: Yihang Li +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/hisi_sas/hisi_sas.h | 3 +-- + drivers/scsi/hisi_sas/hisi_sas_main.c | 28 ++++++++++++++++++++++++-- + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 +--- + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 +--- + 4 files changed, 29 insertions(+), 10 deletions(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 2d438d722d0b4..e17f5d8226bf2 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -633,8 +633,7 @@ extern struct dentry *hisi_sas_debugfs_dir; + extern void hisi_sas_stop_phys(struct hisi_hba *hisi_hba); + extern int hisi_sas_alloc(struct hisi_hba *hisi_hba); + extern void hisi_sas_free(struct hisi_hba *hisi_hba); +-extern u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, +- int direction); ++extern u8 hisi_sas_get_ata_protocol(struct sas_task *task); + extern struct hisi_sas_port *to_hisi_sas_port(struct asd_sas_port *sas_port); + extern void hisi_sas_sata_done(struct sas_task *task, + struct hisi_sas_slot *slot); +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index da4a2ed8ee863..3596414d970b2 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -21,8 +21,32 @@ struct hisi_sas_internal_abort_data { + bool rst_ha_timeout; /* reset the HA for timeout */ + }; + +-u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction) ++static u8 hisi_sas_get_ata_protocol_from_tf(struct ata_queued_cmd *qc) + { ++ if (!qc) ++ return HISI_SAS_SATA_PROTOCOL_PIO; ++ ++ switch (qc->tf.protocol) { ++ case ATA_PROT_NODATA: ++ return HISI_SAS_SATA_PROTOCOL_NONDATA; ++ case ATA_PROT_PIO: ++ return HISI_SAS_SATA_PROTOCOL_PIO; ++ case ATA_PROT_DMA: ++ return HISI_SAS_SATA_PROTOCOL_DMA; ++ case ATA_PROT_NCQ_NODATA: ++ case ATA_PROT_NCQ: ++ return HISI_SAS_SATA_PROTOCOL_FPDMA; ++ default: ++ return HISI_SAS_SATA_PROTOCOL_PIO; ++ } ++} ++ ++u8 hisi_sas_get_ata_protocol(struct sas_task *task) ++{ ++ struct host_to_dev_fis *fis = &task->ata_task.fis; ++ struct ata_queued_cmd *qc = task->uldd_task; ++ int direction = task->data_dir; ++ + switch (fis->command) { + case ATA_CMD_FPDMA_WRITE: + case ATA_CMD_FPDMA_READ: +@@ -93,7 +117,7 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction) + { + if (direction == DMA_NONE) + return HISI_SAS_SATA_PROTOCOL_NONDATA; +- return HISI_SAS_SATA_PROTOCOL_PIO; ++ return hisi_sas_get_ata_protocol_from_tf(qc); + } + } + } +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +index 71cd5b4450c2b..6e7f99fcc8247 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +@@ -2538,9 +2538,7 @@ static void prep_ata_v2_hw(struct hisi_hba *hisi_hba, + (task->ata_task.fis.control & ATA_SRST)) + dw1 |= 1 << CMD_HDR_RESET_OFF; + +- dw1 |= (hisi_sas_get_ata_protocol( +- &task->ata_task.fis, task->data_dir)) +- << CMD_HDR_FRAME_TYPE_OFF; ++ dw1 |= (hisi_sas_get_ata_protocol(task)) << CMD_HDR_FRAME_TYPE_OFF; + dw1 |= sas_dev->device_id << CMD_HDR_DEV_ID_OFF; + hdr->dw1 = cpu_to_le32(dw1); + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 48b95d9a79275..095bbf80c34ef 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -1456,9 +1456,7 @@ static void prep_ata_v3_hw(struct hisi_hba *hisi_hba, + (task->ata_task.fis.control & ATA_SRST)) + dw1 |= 1 << CMD_HDR_RESET_OFF; + +- dw1 |= (hisi_sas_get_ata_protocol( +- &task->ata_task.fis, task->data_dir)) +- << CMD_HDR_FRAME_TYPE_OFF; ++ dw1 |= (hisi_sas_get_ata_protocol(task)) << CMD_HDR_FRAME_TYPE_OFF; + dw1 |= sas_dev->device_id << CMD_HDR_DEV_ID_OFF; + + if (FIS_CMD_IS_UNCONSTRAINED(task->ata_task.fis)) +-- +2.39.5 + diff --git a/queue-6.14/scsi-mpi3mr-fix-locking-in-an-error-path.patch b/queue-6.14/scsi-mpi3mr-fix-locking-in-an-error-path.patch new file mode 100644 index 0000000000..5023afbb84 --- /dev/null +++ b/queue-6.14/scsi-mpi3mr-fix-locking-in-an-error-path.patch @@ -0,0 +1,48 @@ +From 70a9505c919497cfbe7342b507b298a6ac34207b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 12:39:35 -0800 +Subject: scsi: mpi3mr: Fix locking in an error path + +From: Bart Van Assche + +[ Upstream commit c733741ae1c3a5927f72664b0d760d5f4c14f96b ] + +Make all error paths unlock rioc->bsg_cmds.mutex. + +This patch fixes the following Clang -Wthread-safety errors: + +drivers/scsi/mpi3mr/mpi3mr_app.c:2835:1: error: mutex 'mrioc->bsg_cmds.mutex' is not held on every path through here [-Werror,-Wthread-safety-analysis] + 2835 | } + | ^ +drivers/scsi/mpi3mr/mpi3mr_app.c:2332:6: note: mutex acquired here + 2332 | if (mutex_lock_interruptible(&mrioc->bsg_cmds.mutex)) + | ^ +./include/linux/mutex.h:172:40: note: expanded from macro 'mutex_lock_interruptible' + 172 | #define mutex_lock_interruptible(lock) mutex_lock_interruptible_nested(lock, 0) + | ^ + +Cc: Sathya Prakash +Fixes: fb231d7deffb ("scsi: mpi3mr: Support for preallocation of SGL BSG data buffers part-2") +Signed-off-by: Bart Van Assche +Link: https://lore.kernel.org/r/20250210203936.2946494-2-bvanassche@acm.org +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/mpi3mr/mpi3mr_app.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c +index 7589f48aebc80..f4b5813e6fc4c 100644 +--- a/drivers/scsi/mpi3mr/mpi3mr_app.c ++++ b/drivers/scsi/mpi3mr/mpi3mr_app.c +@@ -2339,6 +2339,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job) + } + + if (!mrioc->ioctl_sges_allocated) { ++ mutex_unlock(&mrioc->bsg_cmds.mutex); + dprint_bsg_err(mrioc, "%s: DMA memory was not allocated\n", + __func__); + return -ENOMEM; +-- +2.39.5 + diff --git a/queue-6.14/scsi-mpt3sas-fix-a-locking-bug-in-an-error-path.patch b/queue-6.14/scsi-mpt3sas-fix-a-locking-bug-in-an-error-path.patch new file mode 100644 index 0000000000..e650d1955d --- /dev/null +++ b/queue-6.14/scsi-mpt3sas-fix-a-locking-bug-in-an-error-path.patch @@ -0,0 +1,94 @@ +From 43aa1bad7ca5aec22139a1d2c158dc9c984d417b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 12:39:36 -0800 +Subject: scsi: mpt3sas: Fix a locking bug in an error path + +From: Bart Van Assche + +[ Upstream commit 38afcf0660f5c408ba6c2f0ba3a9729e0102fe2e ] + +Call mutex_unlock(&ioc->hostdiag_unlock_mutex) once from error paths +instead of twice. + +This patch fixes the following Clang -Wthread-safety errors: + +drivers/scsi/mpt3sas/mpt3sas_base.c:8085:2: error: mutex 'ioc->hostdiag_unlock_mutex' is not held on every path through here [-Werror,-Wthread-safety-analysis] + 8085 | pci_cfg_access_unlock(ioc->pdev); + | ^ +drivers/scsi/mpt3sas/mpt3sas_base.c:8019:2: note: mutex acquired here + 8019 | mutex_lock(&ioc->hostdiag_unlock_mutex); + | ^ +./include/linux/mutex.h:171:26: note: expanded from macro 'mutex_lock' + 171 | #define mutex_lock(lock) mutex_lock_nested(lock, 0) + | ^ +drivers/scsi/mpt3sas/mpt3sas_base.c:8085:2: error: mutex 'ioc->hostdiag_unlock_mutex' is not held on every path through here [-Werror,-Wthread-safety-analysis] + 8085 | pci_cfg_access_unlock(ioc->pdev); + | ^ +drivers/scsi/mpt3sas/mpt3sas_base.c:8019:2: note: mutex acquired here + 8019 | mutex_lock(&ioc->hostdiag_unlock_mutex); + | ^ +./include/linux/mutex.h:171:26: note: expanded from macro 'mutex_lock' + 171 | #define mutex_lock(lock) mutex_lock_nested(lock, 0) + | ^ +drivers/scsi/mpt3sas/mpt3sas_base.c:8087:2: error: releasing mutex 'ioc->hostdiag_unlock_mutex' that was not held [-Werror,-Wthread-safety-analysis] + 8087 | mutex_unlock(&ioc->hostdiag_unlock_mutex); + | ^ + +Cc: Ranjan Kumar +Fixes: c0767560b012 ("scsi: mpt3sas: Reload SBR without rebooting HBA") +Signed-off-by: Bart Van Assche +Link: https://lore.kernel.org/r/20250210203936.2946494-3-bvanassche@acm.org +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/mpt3sas/mpt3sas_base.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c +index dc43cfa83088b..212e3b86bb817 100644 +--- a/drivers/scsi/mpt3sas/mpt3sas_base.c ++++ b/drivers/scsi/mpt3sas/mpt3sas_base.c +@@ -8018,7 +8018,7 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc) + + mutex_lock(&ioc->hostdiag_unlock_mutex); + if (mpt3sas_base_unlock_and_get_host_diagnostic(ioc, &host_diagnostic)) +- goto out; ++ goto unlock; + + hcb_size = ioc->base_readl(&ioc->chip->HCBSize); + drsprintk(ioc, ioc_info(ioc, "diag reset: issued\n")); +@@ -8038,7 +8038,7 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc) + ioc_info(ioc, + "Invalid host diagnostic register value\n"); + _base_dump_reg_set(ioc); +- goto out; ++ goto unlock; + } + if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER)) + break; +@@ -8074,17 +8074,19 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc) + ioc_err(ioc, "%s: failed going to ready state (ioc_state=0x%x)\n", + __func__, ioc_state); + _base_dump_reg_set(ioc); +- goto out; ++ goto fail; + } + + pci_cfg_access_unlock(ioc->pdev); + ioc_info(ioc, "diag reset: SUCCESS\n"); + return 0; + +- out: ++unlock: ++ mutex_unlock(&ioc->hostdiag_unlock_mutex); ++ ++fail: + pci_cfg_access_unlock(ioc->pdev); + ioc_err(ioc, "diag reset: FAILED\n"); +- mutex_unlock(&ioc->hostdiag_unlock_mutex); + return -EFAULT; + } + +-- +2.39.5 + diff --git a/queue-6.14/scsi-mpt3sas-reduce-log-level-of-ignore_delay_remove.patch b/queue-6.14/scsi-mpt3sas-reduce-log-level-of-ignore_delay_remove.patch new file mode 100644 index 0000000000..b122487345 --- /dev/null +++ b/queue-6.14/scsi-mpt3sas-reduce-log-level-of-ignore_delay_remove.patch @@ -0,0 +1,67 @@ +From 61cfed482212d298fbdd3ecfd0569fe2415d79b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 18:16:40 +0100 +Subject: scsi: mpt3sas: Reduce log level of ignore_delay_remove message to + KERN_INFO + +From: Paul Menzel + +[ Upstream commit fb27da6e06a0869d2e36255bb7e0b6102daf712f ] + +On several systems with Dell HBA controller Linux prints the warning below: + + $ dmesg | grep -e "Linux version" -e "DMI: Dell" -e "ignore_delay_remove" + [ 0.000000] Linux version 6.12.11.mx64.479 (root@lucy.molgen.mpg.de) (gcc (GCC) 12.3.0, GNU ld (GNU Binutils) 2.41) #1 SMP PREEMPT_DYNAMIC Fri Jan 24 13:30:47 CET 2025 + [ 0.000000] DMI: Dell Inc. PowerEdge R7625/0M7YXP, BIOS 1.10.6 12/06/2024 + [ 9.386551] scsi 0:0:4:0: set ignore_delay_remove for handle(0x0012) + +A user does not know, what to do about it, and everything seems to work as +expected. Therefore, remove the log level from warning to info. + +Device information: + + $ dmesg | grep -e 0:4:0 -e '12)' + [ 8.857606] mpt3sas_cm0: config page(0x00000000db0e4179) - dma(0xfd5f6000): size(512) + [ 9.133856] scsi 0:0:0:0: SATA: handle(0x0017), sas_addr(0x3c0470e0d40cc20c), phy(12), device_name(0x5000039db8d2284b) + [ 9.366341] mpt3sas_cm0: handle(0x12) sas_address(0x3c0570e0d40cc208) port_type(0x0) + [ 9.378867] scsi 0:0:4:0: Enclosure DP BP_PSV 7.10 PQ: 0 ANSI: 7 + [ 9.386551] scsi 0:0:4:0: set ignore_delay_remove for handle(0x0012) + [ 9.387465] scsi 0:0:4:0: SES: handle(0x0012), sas_addr(0x3c0570e0d40cc208), phy(17), device_name(0x3c0570e0d40cc208) + [ 9.387465] scsi 0:0:4:0: enclosure logical id (0x3c0470e0d4092108), slot(8) + [ 9.387465] scsi 0:0:4:0: enclosure level(0x0001), connector name( C0 ) + [ 9.390495] scsi 0:0:4:0: qdepth(1), tagged(0), scsi_level(8), cmd_que(0) + [ 9.401700] end_device-0:4: add: handle(0x0012), sas_addr(0x3c0570e0d40cc208) + [ 9.471916] ses 0:0:4:0: Attached Enclosure device + [ 9.480088] ses 0:0:4:0: Attached scsi generic sg4 type 13 + $ lspci -nn -k -s 41: + 41:00.0 Serial Attached SCSI controller [0107]: Broadcom / LSI Fusion-MPT 12GSAS/PCIe Secure SAS38xx [1000:00e6] + DeviceName: SL3 NonRAID + Subsystem: Dell HBA355i Front [1028:200c] + Kernel driver in use: mpt3sas + +Fixes: 30158dc9bbc9 ("mpt3sas: Never block the Enclosure device") +Cc: Tomas Henzl +Signed-off-by: Paul Menzel +Link: https://lore.kernel.org/r/20250131171640.30721-1-pmenzel@molgen.mpg.de +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/mpt3sas/mpt3sas_scsih.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c +index a456e5ec74d88..9c2d3178f3844 100644 +--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c ++++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c +@@ -2703,7 +2703,7 @@ scsih_sdev_configure(struct scsi_device *sdev, struct queue_limits *lim) + ssp_target = 1; + if (sas_device->device_info & + MPI2_SAS_DEVICE_INFO_SEP) { +- sdev_printk(KERN_WARNING, sdev, ++ sdev_printk(KERN_INFO, sdev, + "set ignore_delay_remove for handle(0x%04x)\n", + sas_device_priv_data->sas_target->handle); + sas_device_priv_data->ignore_delay_remove = 1; +-- +2.39.5 + diff --git a/queue-6.14/scsi-target-tcm_loop-fix-wrong-abort-tag.patch b/queue-6.14/scsi-target-tcm_loop-fix-wrong-abort-tag.patch new file mode 100644 index 0000000000..a3900726a4 --- /dev/null +++ b/queue-6.14/scsi-target-tcm_loop-fix-wrong-abort-tag.patch @@ -0,0 +1,50 @@ +From 8143e7517ed5442b9fbcca0c4e5e063b157e0ae9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 09:47:27 +0800 +Subject: scsi: target: tcm_loop: Fix wrong abort tag + +From: Guixin Liu + +[ Upstream commit 1909b643034ef741af9f24a57ab735440c4b5d1a ] + +When the tcm_loop_nr_hw_queues is set to a value greater than 1, the +tags of requests in the block layer are no longer unique. This may lead +to erroneous aborting of commands with the same tag. The issue can be +resolved by using blk_mq_unique_tag to generate globally unique +identifiers by combining the hardware queue index and per-queue tags. + +Fixes: 6375f8908255 ("tcm_loop: Fixup tag handling") +Signed-off-by: Guixin Liu +Link: https://lore.kernel.org/r/20250313014728.105849-1-kanie@linux.alibaba.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/target/loopback/tcm_loop.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c +index 761c511aea07c..c7b7da6297418 100644 +--- a/drivers/target/loopback/tcm_loop.c ++++ b/drivers/target/loopback/tcm_loop.c +@@ -176,7 +176,7 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc) + + memset(tl_cmd, 0, sizeof(*tl_cmd)); + tl_cmd->sc = sc; +- tl_cmd->sc_cmd_tag = scsi_cmd_to_rq(sc)->tag; ++ tl_cmd->sc_cmd_tag = blk_mq_unique_tag(scsi_cmd_to_rq(sc)); + + tcm_loop_target_queue_cmd(tl_cmd); + return 0; +@@ -242,7 +242,8 @@ static int tcm_loop_abort_task(struct scsi_cmnd *sc) + tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); + tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; + ret = tcm_loop_issue_tmr(tl_tpg, sc->device->lun, +- scsi_cmd_to_rq(sc)->tag, TMR_ABORT_TASK); ++ blk_mq_unique_tag(scsi_cmd_to_rq(sc)), ++ TMR_ABORT_TASK); + return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED; + } + +-- +2.39.5 + diff --git a/queue-6.14/sctp-add-mutual-exclusion-in-proc_sctp_do_udp_port.patch b/queue-6.14/sctp-add-mutual-exclusion-in-proc_sctp_do_udp_port.patch new file mode 100644 index 0000000000..ae5440a0be --- /dev/null +++ b/queue-6.14/sctp-add-mutual-exclusion-in-proc_sctp_do_udp_port.patch @@ -0,0 +1,80 @@ +From 438213eef0357721df99417477018c248293cf20 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Mar 2025 09:15:32 +0000 +Subject: sctp: add mutual exclusion in proc_sctp_do_udp_port() + +From: Eric Dumazet + +[ Upstream commit 10206302af856791fbcc27a33ed3c3eb09b2793d ] + +We must serialize calls to sctp_udp_sock_stop() and sctp_udp_sock_start() +or risk a crash as syzbot reported: + +Oops: general protection fault, probably for non-canonical address 0xdffffc000000000d: 0000 [#1] SMP KASAN PTI +KASAN: null-ptr-deref in range [0x0000000000000068-0x000000000000006f] +CPU: 1 UID: 0 PID: 6551 Comm: syz.1.44 Not tainted 6.14.0-syzkaller-g7f2ff7b62617 #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/12/2025 + RIP: 0010:kernel_sock_shutdown+0x47/0x70 net/socket.c:3653 +Call Trace: + + udp_tunnel_sock_release+0x68/0x80 net/ipv4/udp_tunnel_core.c:181 + sctp_udp_sock_stop+0x71/0x160 net/sctp/protocol.c:930 + proc_sctp_do_udp_port+0x264/0x450 net/sctp/sysctl.c:553 + proc_sys_call_handler+0x3d0/0x5b0 fs/proc/proc_sysctl.c:601 + iter_file_splice_write+0x91c/0x1150 fs/splice.c:738 + do_splice_from fs/splice.c:935 [inline] + direct_splice_actor+0x18f/0x6c0 fs/splice.c:1158 + splice_direct_to_actor+0x342/0xa30 fs/splice.c:1102 + do_splice_direct_actor fs/splice.c:1201 [inline] + do_splice_direct+0x174/0x240 fs/splice.c:1227 + do_sendfile+0xafd/0xe50 fs/read_write.c:1368 + __do_sys_sendfile64 fs/read_write.c:1429 [inline] + __se_sys_sendfile64 fs/read_write.c:1415 [inline] + __x64_sys_sendfile64+0x1d8/0x220 fs/read_write.c:1415 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + +Fixes: 046c052b475e ("sctp: enable udp tunneling socks") +Reported-by: syzbot+fae49d997eb56fa7c74d@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/67ea5c01.050a0220.1547ec.012b.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Marcelo Ricardo Leitner +Acked-by: Xin Long +Link: https://patch.msgid.link/20250331091532.224982-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/sysctl.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c +index 8e1e97be4df79..ee3eac338a9de 100644 +--- a/net/sctp/sysctl.c ++++ b/net/sctp/sysctl.c +@@ -525,6 +525,8 @@ static int proc_sctp_do_auth(const struct ctl_table *ctl, int write, + return ret; + } + ++static DEFINE_MUTEX(sctp_sysctl_mutex); ++ + static int proc_sctp_do_udp_port(const struct ctl_table *ctl, int write, + void *buffer, size_t *lenp, loff_t *ppos) + { +@@ -549,6 +551,7 @@ static int proc_sctp_do_udp_port(const struct ctl_table *ctl, int write, + if (new_value > max || new_value < min) + return -EINVAL; + ++ mutex_lock(&sctp_sysctl_mutex); + net->sctp.udp_port = new_value; + sctp_udp_sock_stop(net); + if (new_value) { +@@ -561,6 +564,7 @@ static int proc_sctp_do_udp_port(const struct ctl_table *ctl, int write, + lock_sock(sk); + sctp_sk(sk)->udp_port = htons(net->sctp.udp_port); + release_sock(sk); ++ mutex_unlock(&sctp_sysctl_mutex); + } + + return ret; +-- +2.39.5 + diff --git a/queue-6.14/seccomp-fix-the-__secure_computing-stub-for-have_arc.patch b/queue-6.14/seccomp-fix-the-__secure_computing-stub-for-have_arc.patch new file mode 100644 index 0000000000..5cfc09a2c0 --- /dev/null +++ b/queue-6.14/seccomp-fix-the-__secure_computing-stub-for-have_arc.patch @@ -0,0 +1,98 @@ +From 37d91ef961b9373cb069e6e91ceb27d8366a4825 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jan 2025 16:03:07 +0100 +Subject: seccomp: fix the __secure_computing() stub for + !HAVE_ARCH_SECCOMP_FILTER + +From: Oleg Nesterov + +[ Upstream commit b37778bec82ba82058912ca069881397197cd3d5 ] + +Depending on CONFIG_HAVE_ARCH_SECCOMP_FILTER, __secure_computing(NULL) +will crash or not. This is not consistent/safe, especially considering +that after the previous change __secure_computing(sd) is always called +with sd == NULL. + +Fortunately, if CONFIG_HAVE_ARCH_SECCOMP_FILTER=n, __secure_computing() +has no callers, these architectures use secure_computing_strict(). Yet +it make sense make __secure_computing(NULL) safe in this case. + +Note also that with this change we can unexport secure_computing_strict() +and change the current callers to use __secure_computing(NULL). + +Fixes: 8cf8dfceebda ("seccomp: Stub for !HAVE_ARCH_SECCOMP_FILTER") +Signed-off-by: Oleg Nesterov +Reviewed-by: Linus Walleij +Link: https://lore.kernel.org/r/20250128150307.GA15325@redhat.com +Signed-off-by: Kees Cook +Signed-off-by: Sasha Levin +--- + include/linux/seccomp.h | 8 ++------ + kernel/seccomp.c | 14 ++++++++++---- + 2 files changed, 12 insertions(+), 10 deletions(-) + +diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h +index e45531455d3bb..d55949071c30e 100644 +--- a/include/linux/seccomp.h ++++ b/include/linux/seccomp.h +@@ -22,8 +22,9 @@ + #include + #include + +-#ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER + extern int __secure_computing(const struct seccomp_data *sd); ++ ++#ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER + static inline int secure_computing(void) + { + if (unlikely(test_syscall_work(SECCOMP))) +@@ -32,11 +33,6 @@ static inline int secure_computing(void) + } + #else + extern void secure_computing_strict(int this_syscall); +-static inline int __secure_computing(const struct seccomp_data *sd) +-{ +- secure_computing_strict(sd->nr); +- return 0; +-} + #endif + + extern long prctl_get_seccomp(void); +diff --git a/kernel/seccomp.c b/kernel/seccomp.c +index 7bbb408431ebc..3231f63d93d89 100644 +--- a/kernel/seccomp.c ++++ b/kernel/seccomp.c +@@ -29,13 +29,11 @@ + #include + #include + ++#include ++ + /* Not exposed in headers: strictly internal use only. */ + #define SECCOMP_MODE_DEAD (SECCOMP_MODE_FILTER + 1) + +-#ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER +-#include +-#endif +- + #ifdef CONFIG_SECCOMP_FILTER + #include + #include +@@ -1074,6 +1072,14 @@ void secure_computing_strict(int this_syscall) + else + BUG(); + } ++int __secure_computing(const struct seccomp_data *sd) ++{ ++ int this_syscall = sd ? sd->nr : ++ syscall_get_nr(current, current_pt_regs()); ++ ++ secure_computing_strict(this_syscall); ++ return 0; ++} + #else + + #ifdef CONFIG_SECCOMP_FILTER +-- +2.39.5 + diff --git a/queue-6.14/selftests-bpf-fix-freplace_link-segfault-in-tailcall.patch b/queue-6.14/selftests-bpf-fix-freplace_link-segfault-in-tailcall.patch new file mode 100644 index 0000000000..606bb21073 --- /dev/null +++ b/queue-6.14/selftests-bpf-fix-freplace_link-segfault-in-tailcall.patch @@ -0,0 +1,44 @@ +From dcf0d3a771635db202cfc27fcc4c0c7ed5b81573 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 10:28:38 +0800 +Subject: selftests/bpf: Fix freplace_link segfault in tailcalls prog test + +From: Tengda Wu + +[ Upstream commit a63a631c9b5cb25a1c17dd2cb18c63df91e978b1 ] + +There are two bpf_link__destroy(freplace_link) calls in +test_tailcall_bpf2bpf_freplace(). After the first bpf_link__destroy() +is called, if the following bpf_map_{update,delete}_elem() throws an +exception, it will jump to the "out" label and call bpf_link__destroy() +again, causing double free and eventually leading to a segfault. + +Fix it by directly resetting freplace_link to NULL after the first +bpf_link__destroy() call. + +Fixes: 021611d33e78 ("selftests/bpf: Add test to verify tailcall and freplace restrictions") +Signed-off-by: Tengda Wu +Signed-off-by: Andrii Nakryiko +Reviewed-by: Leon Hwang +Link: https://lore.kernel.org/bpf/20250122022838.1079157-1-wutengda@huaweicloud.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/bpf/prog_tests/tailcalls.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/testing/selftests/bpf/prog_tests/tailcalls.c b/tools/testing/selftests/bpf/prog_tests/tailcalls.c +index 544144620ca61..66a900327f912 100644 +--- a/tools/testing/selftests/bpf/prog_tests/tailcalls.c ++++ b/tools/testing/selftests/bpf/prog_tests/tailcalls.c +@@ -1600,6 +1600,7 @@ static void test_tailcall_bpf2bpf_freplace(void) + goto out; + + err = bpf_link__destroy(freplace_link); ++ freplace_link = NULL; + if (!ASSERT_OK(err, "destroy link")) + goto out; + +-- +2.39.5 + diff --git a/queue-6.14/selftests-bpf-fix-runqslower-cross-endian-build.patch b/queue-6.14/selftests-bpf-fix-runqslower-cross-endian-build.patch new file mode 100644 index 0000000000..639534ee80 --- /dev/null +++ b/queue-6.14/selftests-bpf-fix-runqslower-cross-endian-build.patch @@ -0,0 +1,60 @@ +From 266e8b101b75a2cd38286c278a99b116923e5b03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 23:14:23 -0800 +Subject: selftests/bpf: Fix runqslower cross-endian build + +From: Tony Ambardar + +[ Upstream commit cb3ade567816a03d1ac1c33bf86073574efcfcaf ] + +The runqslower binary from a cross-endian build currently fails to run +because the included skeleton has host endianness. Fix this by passing the +target BPF endianness to the runqslower sub-make. + +Fixes: 5a63c33d6f00 ("selftests/bpf: Support cross-endian building") +Signed-off-by: Tony Ambardar +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20250125071423.2603588-1-itugrok@yahoo.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + tools/bpf/runqslower/Makefile | 3 ++- + tools/testing/selftests/bpf/Makefile | 1 + + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/tools/bpf/runqslower/Makefile b/tools/bpf/runqslower/Makefile +index e49203ebd48c1..78a436c4072e3 100644 +--- a/tools/bpf/runqslower/Makefile ++++ b/tools/bpf/runqslower/Makefile +@@ -6,6 +6,7 @@ OUTPUT ?= $(abspath .output)/ + BPFTOOL_OUTPUT := $(OUTPUT)bpftool/ + DEFAULT_BPFTOOL := $(BPFTOOL_OUTPUT)bootstrap/bpftool + BPFTOOL ?= $(DEFAULT_BPFTOOL) ++BPF_TARGET_ENDIAN ?= --target=bpf + LIBBPF_SRC := $(abspath ../../lib/bpf) + BPFOBJ_OUTPUT := $(OUTPUT)libbpf/ + BPFOBJ := $(BPFOBJ_OUTPUT)libbpf.a +@@ -60,7 +61,7 @@ $(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o | $(BPFTOOL) + $(QUIET_GEN)$(BPFTOOL) gen skeleton $< > $@ + + $(OUTPUT)/%.bpf.o: %.bpf.c $(BPFOBJ) | $(OUTPUT) +- $(QUIET_GEN)$(CLANG) -g -O2 --target=bpf $(INCLUDES) \ ++ $(QUIET_GEN)$(CLANG) -g -O2 $(BPF_TARGET_ENDIAN) $(INCLUDES) \ + -c $(filter %.c,$^) -o $@ && \ + $(LLVM_STRIP) -g $@ + +diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile +index 87551628e1129..6722080b2107a 100644 +--- a/tools/testing/selftests/bpf/Makefile ++++ b/tools/testing/selftests/bpf/Makefile +@@ -306,6 +306,7 @@ $(OUTPUT)/runqslower: $(BPFOBJ) | $(DEFAULT_BPFTOOL) $(RUNQSLOWER_OUTPUT) + BPFTOOL_OUTPUT=$(HOST_BUILD_DIR)/bpftool/ \ + BPFOBJ_OUTPUT=$(BUILD_DIR)/libbpf/ \ + BPFOBJ=$(BPFOBJ) BPF_INCLUDE=$(INCLUDE_DIR) \ ++ BPF_TARGET_ENDIAN=$(BPF_TARGET_ENDIAN) \ + EXTRA_CFLAGS='-g $(OPT_FLAGS) $(SAN_CFLAGS) $(EXTRA_CFLAGS)' \ + EXTRA_LDFLAGS='$(SAN_LDFLAGS) $(EXTRA_LDFLAGS)' && \ + cp $(RUNQSLOWER_OUTPUT)runqslower $@ +-- +2.39.5 + diff --git a/queue-6.14/selftests-bpf-fix-string-read-in-strncmp-benchmark.patch b/queue-6.14/selftests-bpf-fix-string-read-in-strncmp-benchmark.patch new file mode 100644 index 0000000000..1207d31122 --- /dev/null +++ b/queue-6.14/selftests-bpf-fix-string-read-in-strncmp-benchmark.patch @@ -0,0 +1,83 @@ +From a5901ce10ccad4fa9282ef1be5ae177cc64c4adf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 13:28:52 +0100 +Subject: selftests/bpf: Fix string read in strncmp benchmark +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Viktor Malik + +[ Upstream commit de07b182899227d5fd1ca7a1a7d495ecd453d49c ] + +The strncmp benchmark uses the bpf_strncmp helper and a hand-written +loop to compare two strings. The values of the strings are filled from +userspace. One of the strings is non-const (in .bss) while the other is +const (in .rodata) since that is the requirement of bpf_strncmp. + +The problem is that in the hand-written loop, Clang optimizes the reads +from the const string to always return 0 which breaks the benchmark. + +Use barrier_var to prevent the optimization. + +The effect can be seen on the strncmp-no-helper variant. + +Before this change: + + # ./bench strncmp-no-helper + Setting up benchmark 'strncmp-no-helper'... + Benchmark 'strncmp-no-helper' started. + Iter 0 (112.309us): hits 0.000M/s ( 0.000M/prod), drops 0.000M/s, total operations 0.000M/s + Iter 1 (-23.238us): hits 0.000M/s ( 0.000M/prod), drops 0.000M/s, total operations 0.000M/s + Iter 2 ( 58.994us): hits 0.000M/s ( 0.000M/prod), drops 0.000M/s, total operations 0.000M/s + Iter 3 (-30.466us): hits 0.000M/s ( 0.000M/prod), drops 0.000M/s, total operations 0.000M/s + Iter 4 ( 29.996us): hits 0.000M/s ( 0.000M/prod), drops 0.000M/s, total operations 0.000M/s + Iter 5 ( 16.949us): hits 0.000M/s ( 0.000M/prod), drops 0.000M/s, total operations 0.000M/s + Iter 6 (-60.035us): hits 0.000M/s ( 0.000M/prod), drops 0.000M/s, total operations 0.000M/s + Summary: hits 0.000 ± 0.000M/s ( 0.000M/prod), drops 0.000 ± 0.000M/s, total operations 0.000 ± 0.000M/s + +After this change: + + # ./bench strncmp-no-helper + Setting up benchmark 'strncmp-no-helper'... + Benchmark 'strncmp-no-helper' started. + Iter 0 ( 77.711us): hits 5.534M/s ( 5.534M/prod), drops 0.000M/s, total operations 5.534M/s + Iter 1 ( 11.215us): hits 6.006M/s ( 6.006M/prod), drops 0.000M/s, total operations 6.006M/s + Iter 2 (-14.253us): hits 5.931M/s ( 5.931M/prod), drops 0.000M/s, total operations 5.931M/s + Iter 3 ( 59.087us): hits 6.005M/s ( 6.005M/prod), drops 0.000M/s, total operations 6.005M/s + Iter 4 (-21.379us): hits 6.010M/s ( 6.010M/prod), drops 0.000M/s, total operations 6.010M/s + Iter 5 (-20.310us): hits 5.861M/s ( 5.861M/prod), drops 0.000M/s, total operations 5.861M/s + Iter 6 ( 53.937us): hits 6.004M/s ( 6.004M/prod), drops 0.000M/s, total operations 6.004M/s + Summary: hits 5.969 ± 0.061M/s ( 5.969M/prod), drops 0.000 ± 0.000M/s, total operations 5.969 ± 0.061M/s + +Fixes: 9c42652f8be3 ("selftests/bpf: Add benchmark for bpf_strncmp() helper") +Suggested-by: Andrii Nakryiko +Signed-off-by: Viktor Malik +Signed-off-by: Andrii Nakryiko +Acked-by: Hou Tao +Link: https://lore.kernel.org/bpf/20250313122852.1365202-1-vmalik@redhat.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/bpf/progs/strncmp_bench.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/bpf/progs/strncmp_bench.c b/tools/testing/selftests/bpf/progs/strncmp_bench.c +index 18373a7df76e6..f47bf88f8d2a7 100644 +--- a/tools/testing/selftests/bpf/progs/strncmp_bench.c ++++ b/tools/testing/selftests/bpf/progs/strncmp_bench.c +@@ -35,7 +35,10 @@ static __always_inline int local_strncmp(const char *s1, unsigned int sz, + SEC("tp/syscalls/sys_enter_getpgid") + int strncmp_no_helper(void *ctx) + { +- if (local_strncmp(str, cmp_str_len + 1, target) < 0) ++ const char *target_str = target; ++ ++ barrier_var(target_str); ++ if (local_strncmp(str, cmp_str_len + 1, target_str) < 0) + __sync_add_and_fetch(&hits, 1); + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/selftests-bpf-select-numa_no_node-to-create-map.patch b/queue-6.14/selftests-bpf-select-numa_no_node-to-create-map.patch new file mode 100644 index 0000000000..cba6d8358b --- /dev/null +++ b/queue-6.14/selftests-bpf-select-numa_no_node-to-create-map.patch @@ -0,0 +1,55 @@ +From 4e754e976e73947dcaf8e37f1d01dc0d04eb4997 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 12:35:22 +0530 +Subject: selftests/bpf: Select NUMA_NO_NODE to create map + +From: Saket Kumar Bhaskar + +[ Upstream commit 4107a1aeb20ed4cdad6a0d49de92ea0f933c71b7 ] + +On powerpc, a CPU does not necessarily originate from NUMA node 0. +This contrasts with architectures like x86, where CPU 0 is not +hot-pluggable, making NUMA node 0 a consistently valid node. +This discrepancy can lead to failures when creating a map on NUMA +node 0, which is initialized by default, if no CPUs are allocated +from NUMA node 0. + +This patch fixes the issue by setting NUMA_NO_NODE (-1) for map +creation for this selftest. + +Fixes: 96eabe7a40aa ("bpf: Allow selecting numa node during map creation") +Signed-off-by: Saket Kumar Bhaskar +Signed-off-by: Andrii Nakryiko +Acked-by: Yonghong Song +Link: https://lore.kernel.org/bpf/cf1f61468b47425ecf3728689bc9636ddd1d910e.1738302337.git.skb99@linux.ibm.com +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/bpf/prog_tests/bloom_filter_map.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/tools/testing/selftests/bpf/prog_tests/bloom_filter_map.c b/tools/testing/selftests/bpf/prog_tests/bloom_filter_map.c +index cc184e4420f6e..67557cda22083 100644 +--- a/tools/testing/selftests/bpf/prog_tests/bloom_filter_map.c ++++ b/tools/testing/selftests/bpf/prog_tests/bloom_filter_map.c +@@ -6,6 +6,10 @@ + #include + #include "bloom_filter_map.skel.h" + ++#ifndef NUMA_NO_NODE ++#define NUMA_NO_NODE (-1) ++#endif ++ + static void test_fail_cases(void) + { + LIBBPF_OPTS(bpf_map_create_opts, opts); +@@ -69,6 +73,7 @@ static void test_success_cases(void) + + /* Create a map */ + opts.map_flags = BPF_F_ZERO_SEED | BPF_F_NUMA_NODE; ++ opts.numa_node = NUMA_NO_NODE; + fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 0, sizeof(value), 100, &opts); + if (!ASSERT_GE(fd, 0, "bpf_map_create bloom filter success case")) + return; +-- +2.39.5 + diff --git a/queue-6.14/selftests-mm-cow-fix-the-incorrect-error-handling.patch b/queue-6.14/selftests-mm-cow-fix-the-incorrect-error-handling.patch new file mode 100644 index 0000000000..b797e4e6ba --- /dev/null +++ b/queue-6.14/selftests-mm-cow-fix-the-incorrect-error-handling.patch @@ -0,0 +1,41 @@ +From 9168b43f383494a231dffca960306e0a7a9d023a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 12:38:40 +0800 +Subject: selftests/mm/cow: fix the incorrect error handling + +From: Cyan Yang + +[ Upstream commit f841ad9ca5007167c02de143980c9dc703f90b3d ] + +Error handling doesn't check the correct return value. This patch will +fix it. + +Link: https://lkml.kernel.org/r/20250312043840.71799-1-cyan.yang@sifive.com +Fixes: f4b5fd6946e2 ("selftests/vm: anon_cow: THP tests") +Signed-off-by: Cyan Yang +Reviewed-by: Dev Jain +Reviewed-by: Muhammad Usama Anjum +Cc: David Hildenbrand +Cc: Shuah Khan +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/mm/cow.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/mm/cow.c b/tools/testing/selftests/mm/cow.c +index 9446673645eba..f0cb14ea86084 100644 +--- a/tools/testing/selftests/mm/cow.c ++++ b/tools/testing/selftests/mm/cow.c +@@ -876,7 +876,7 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize) + mremap_size = thpsize / 2; + mremap_mem = mmap(NULL, mremap_size, PROT_NONE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +- if (mem == MAP_FAILED) { ++ if (mremap_mem == MAP_FAILED) { + ksft_test_result_fail("mmap() failed\n"); + goto munmap; + } +-- +2.39.5 + diff --git a/queue-6.14/selftests-pcie_bwctrl-add-set_pcie_speed.sh-to-test_.patch b/queue-6.14/selftests-pcie_bwctrl-add-set_pcie_speed.sh-to-test_.patch new file mode 100644 index 0000000000..1318d365c0 --- /dev/null +++ b/queue-6.14/selftests-pcie_bwctrl-add-set_pcie_speed.sh-to-test_.patch @@ -0,0 +1,36 @@ +From dee123bf970d85449f6784121f444e4d8b139bff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 15:00:59 +0800 +Subject: selftests/pcie_bwctrl: Add 'set_pcie_speed.sh' to TEST_PROGS + +From: Yi Lai + +[ Upstream commit df6f8c4d72aebaf66aaa8658c723fd360c272e59 ] + +The test shell script "set_pcie_speed.sh" is not installed in INSTALL_PATH. +Attempting to execute set_pcie_cooling_state.sh shows warning: + + ./set_pcie_cooling_state.sh: line 119: ./set_pcie_speed.sh: No such file or directory + +Add "set_pcie_speed.sh" to TEST_PROGS. + +Link: https://lore.kernel.org/r/Z8FfK8rN30lKzvVV@ly-workstation +Fixes: 838f12c3d551 ("selftests/pcie_bwctrl: Create selftests") +Signed-off-by: Yi Lai +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/pcie_bwctrl/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/pcie_bwctrl/Makefile b/tools/testing/selftests/pcie_bwctrl/Makefile +index 3e84e26341d1c..48ec048f47afd 100644 +--- a/tools/testing/selftests/pcie_bwctrl/Makefile ++++ b/tools/testing/selftests/pcie_bwctrl/Makefile +@@ -1,2 +1,2 @@ +-TEST_PROGS = set_pcie_cooling_state.sh ++TEST_PROGS = set_pcie_cooling_state.sh set_pcie_speed.sh + include ../lib.mk +-- +2.39.5 + diff --git a/queue-6.14/selinux-chain-up-tool-resolving-errors-in-install_po.patch b/queue-6.14/selinux-chain-up-tool-resolving-errors-in-install_po.patch new file mode 100644 index 0000000000..34dfd15d29 --- /dev/null +++ b/queue-6.14/selinux-chain-up-tool-resolving-errors-in-install_po.patch @@ -0,0 +1,66 @@ +From dff19f3035f357f79c2747127b3853346d92c7a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Mar 2025 10:56:43 +0100 +Subject: selinux: Chain up tool resolving errors in install_policy.sh + +From: Tim Schumacher + +[ Upstream commit 6ae0042f4d3f331e841495eb0a3d51598e593ec2 ] + +Subshell evaluations are not exempt from errexit, so if a command is +not available, `which` will fail and exit the script as a whole. +This causes the helpful error messages to not be printed if they are +tacked on using a `$?` comparison. + +Resolve the issue by using chains of logical operators, which are not +subject to the effects of errexit. + +Fixes: e37c1877ba5b1 ("scripts/selinux: modernize mdp") +Signed-off-by: Tim Schumacher +Signed-off-by: Paul Moore +Signed-off-by: Sasha Levin +--- + scripts/selinux/install_policy.sh | 15 ++++++--------- + 1 file changed, 6 insertions(+), 9 deletions(-) + +diff --git a/scripts/selinux/install_policy.sh b/scripts/selinux/install_policy.sh +index 24086793b0d8d..db40237e60ce7 100755 +--- a/scripts/selinux/install_policy.sh ++++ b/scripts/selinux/install_policy.sh +@@ -6,27 +6,24 @@ if [ `id -u` -ne 0 ]; then + exit 1 + fi + +-SF=`which setfiles` +-if [ $? -eq 1 ]; then ++SF=`which setfiles` || { + echo "Could not find setfiles" + echo "Do you have policycoreutils installed?" + exit 1 +-fi ++} + +-CP=`which checkpolicy` +-if [ $? -eq 1 ]; then ++CP=`which checkpolicy` || { + echo "Could not find checkpolicy" + echo "Do you have checkpolicy installed?" + exit 1 +-fi ++} + VERS=`$CP -V | awk '{print $1}'` + +-ENABLED=`which selinuxenabled` +-if [ $? -eq 1 ]; then ++ENABLED=`which selinuxenabled` || { + echo "Could not find selinuxenabled" + echo "Do you have libselinux-utils installed?" + exit 1 +-fi ++} + + if selinuxenabled; then + echo "SELinux is already enabled" +-- +2.39.5 + diff --git a/queue-6.14/series b/queue-6.14/series new file mode 100644 index 0000000000..f67715a7ba --- /dev/null +++ b/queue-6.14/series @@ -0,0 +1,644 @@ +fs-support-o_path-fds-with-fsconfig_set_fd.patch +watch_queue-fix-pipe-accounting-mismatch.patch +x86-mm-pat-cpa-test-fix-length-for-cpa_array-test.patch +m68k-sun3-use-str_read_write-helper-in-mmu_emu_handl.patch +m68k-sun3-fix-debug_mmu_emu-build.patch +cpufreq-scpi-compare-khz-instead-of-hz.patch +seccomp-fix-the-__secure_computing-stub-for-have_arc.patch +smack-dont-compile-ipv6-code-unless-ipv6-is-configur.patch +smack-ipv4-ipv6-tcp-dccp-sctp-fix-incorrect-child-so.patch +sched-cancel-the-slice-protection-of-the-idle-entity.patch +sched-eevdf-force-propagating-min_slice-of-cfs_rq-wh.patch +cpufreq-governor-fix-negative-idle_time-handling-in-.patch +edac-igen6-fix-the-flood-of-invalid-error-reports.patch +edac-skx_common-i10nm-fix-some-missing-error-reports.patch +x86-vdso-fix-latent-bug-in-vclock_pages-calculation.patch +x86-fpu-fix-guest-fpu-state-buffer-allocation-size.patch +cpufreq-amd-pstate-modify-the-min_perf-calculation-i.patch +cpufreq-amd-pstate-pass-min-max_limit_perf-as-min-ma.patch +cpufreq-amd-pstate-convert-all-perf-values-to-u8.patch +cpufreq-amd-pstate-add-missing-null-ptr-check-in-amd.patch +x86-fpu-avoid-copying-dynamic-fp-state-from-init_tas.patch +rseq-update-kernel-fields-in-lockstep-with-config_de.patch +x86-platform-only-allow-config_eisa-for-32-bit.patch +x86-sev-add-missing-rip_rel_ref-invocations-during-s.patch +lockdep-mm-fix-might_fault-lockdep-check-of-current-.patch +pm-sleep-adjust-check-before-setting-power.must_resu.patch +cpufreq-tegra194-allow-building-for-tegra234.patch +risc-v-kvm-disable-the-kernel-perf-counter-during-co.patch +kunit-stackinit-use-fill-byte-different-from-clang-i.patch +watchdog-hardlockup-perf-fix-perf_event-memory-leak.patch +x86-split_lock-fix-the-delayed-detection-logic.patch +selinux-chain-up-tool-resolving-errors-in-install_po.patch +edac-ie31200-fix-the-size-of-edac_mc_layer_chip_sele.patch +edac-ie31200-fix-the-dimm-size-mask-for-several-socs.patch +edac-ie31200-fix-the-error-path-order-of-ie31200_ini.patch +dma-fix-encryption-bit-clearing-for-dma_to_phys.patch +dma-introduce-generic-dma_addr_-crypted-helpers.patch +arm64-realm-use-aliased-addresses-for-device-dma-to-.patch +x86-resctrl-fix-allocation-of-cleanest-closid-on-pla.patch +cpuidle-init-cpuidle-only-for-present-cpus.patch +thermal-int340x-add-null-check-for-adev.patch +pm-sleep-fix-handling-devices-with-direct_complete-s.patch +lockdep-don-t-disable-interrupts-on-rt-in-disable_ir.patch +cpufreq-init-cpufreq-only-for-present-cpus.patch +perf-ring_buffer-allow-the-epollrdnorm-flag-for-poll.patch +perf-save-pmu-specific-data-in-task_struct.patch +perf-supply-task-information-to-sched_task.patch +perf-x86-lbr-fix-shorter-lbrs-call-stacks-for-the-sy.patch +sched-deadline-ignore-special-tasks-when-rebuilding-.patch +sched-topology-wrappers-for-sched_domains_mutex.patch +sched-deadline-generalize-unique-visiting-of-root-do.patch +sched-deadline-rebuild-root-domain-accounting-after-.patch +x86-traps-make-exc_double_fault-consistently-noretur.patch +x86-fpu-xstate-fix-inconsistencies-in-guest-fpu-xfea.patch +x86-entry-add-__init-to-ia32_emulation_override_cmdl.patch +risc-v-kvm-teardown-riscv-specific-bits-after-kvm_ex.patch +timekeeping-fix-possible-inconsistencies-in-_coarse-.patch +regulator-pca9450-fix-enable-register-for-ldo5.patch +auxdisplay-max6959-should-select-bitreverse.patch +media-verisilicon-hevc-initialize-start_bit-field.patch +media-platform-allgro-dvt-unregister-v4l2_device-on-.patch +auxdisplay-panel-fix-an-api-misuse-in-panel.c.patch +platform-x86-lenovo-yoga-tab2-pro-1380-fastcharger-m.patch +platform-x86-dell-uart-backlight-make-dell_uart_bl_s.patch +platform-x86-dell-ddv-fix-temperature-calculation.patch +asoc-cs35l41-check-the-return-value-from-spi_setup.patch +asoc-amd-acp-fix-for-enabling-dmic-on-acp-platforms-.patch +hid-remove-superfluous-and-wrong-makefile-entry-for-.patch +asoc-simple-card-utils-don-t-use-__free-device_node-.patch +dt-bindings-vendor-prefixes-add-gocontroll.patch +alsa-hda-realtek-always-honor-no_shutup_pins.patch +asoc-tegra-use-non-atomic-timeout-for-adx-status-reg.patch +asoc-ti-j721e-evm-fix-clock-configuration-for-ti-j72.patch +alsa-usb-audio-separate-djm-a9-cap-lvl-options.patch +alsa-timer-don-t-take-register_mutex-with-copy_from-.patch +alsa-hda-realtek-fix-built-in-mic-assignment-on-asus.patch +wifi-rtw89-correct-immediate-cfg_len-calculation-for.patch +wifi-ath12k-fix-skb_ext_desc-leak-in-ath12k_dp_tx-er.patch +wifi-ath12k-encode-max-tx-power-in-scan-channel-list.patch +wifi-ath12k-fix-pdev-lookup-in-wbm-error-processing.patch +wifi-ath9k-do-not-submit-zero-bytes-to-the-entropy-p.patch +wifi-ath11k-fix-wrong-overriding-for-vht-beamformee-.patch +arm64-dts-mediatek-mt8173-elm-drop-pmic-s-address-ce.patch +arm64-dts-mediatek-mt8173-fix-some-node-names.patch +wifi-ath11k-update-channel-list-in-reg-notifier-inst.patch +arm-dts-omap4-panda-a4-add-missing-model-and-compati.patch +f2fs-quota-fix-to-avoid-warning-in-dquot_writeback_d.patch +dlm-prevent-npd-when-writing-a-positive-value-to-eve.patch +wifi-ath11k-fix-rcu-stall-while-reaping-monitor-dest.patch +wifi-ath11k-add-srng-lock-for-ath11k_hal_srng_-in-mo.patch +wifi-ath12k-fix-locking-in-qmi-firmware-ready-error-.patch +f2fs-fix-to-avoid-panic-once-fallocation-fails-for-p.patch +scsi-mpt3sas-reduce-log-level-of-ignore_delay_remove.patch +md-ensure-resync-is-prioritized-over-recovery.patch +md-raid1-fix-memory-leak-in-raid1_run-if-no-active-r.patch +coredump-fixes-core_pipe_limit-sysctl-proc_handler.patch +io_uring-io-wq-eliminate-redundant-io_work_get_acct-.patch +io_uring-io-wq-cache-work-flags-in-variable.patch +io_uring-io-wq-do-not-use-bogus-hash-value.patch +io_uring-check-for-iowq-alloc_workqueue-failure.patch +io_uring-net-improve-recv-bundles.patch +firmware-arm_ffa-refactor-addition-of-partition-info.patch +firmware-arm_ffa-unregister-the-ff-a-devices-when-cl.patch +arm64-dts-mediatek-mt6359-fix-dtbs_check-error-for-a.patch +scsi-mpi3mr-fix-locking-in-an-error-path.patch +scsi-mpt3sas-fix-a-locking-bug-in-an-error-path.patch +can-rockchip_canfd-rkcanfd_chip_fifo_setup-remove-du.patch +jfs-reject-on-disk-inodes-of-an-unsupported-type.patch +jfs-add-check-read-only-before-txbeginanon-call.patch +jfs-add-check-read-only-before-truncation-in-jfs_tru.patch +wifi-ath12k-add-missing-htt_metadata-flag-in-ath12k_.patch +wifi-rtw89-rtw8852b-t-fix-tssi-debug-timestamps.patch +xfrm-delay-initialization-of-offload-path-till-its-a.patch +iommu-io-pgtable-dart-only-set-subpage-protection-di.patch +firmware-arm_ffa-explicitly-cast-return-value-from-f.patch +firmware-arm_ffa-explicitly-cast-return-value-from-n.patch +arm64-dts-renesas-r8a774c0-re-add-voltages-to-opp-ta.patch +arm64-dts-renesas-r8a77990-re-add-voltages-to-opp-ta.patch +firmware-arm_ffa-skip-the-first-partition-id-when-pa.patch +arm64-dts-ti-k3-j722s-evm-fix-usb2.0_mux_sel-to-sele.patch +wifi-ath12k-use-link-specific-bss_conf-as-well-in-at.patch +arm64-dts-imx8mp-skov-correct-pmic-board-limits.patch +arm64-dts-imx8mp-skov-operate-cpu-at-850-mv-by-defau.patch +arm64-dts-mediatek-mt8390-genio-700-evk-move-common-.patch +arm64-dts-mediatek-mt8390-genio-common-fix-duplicate.patch +wifi-ath11k-clear-affinity-hint-before-calling-ath11.patch +wifi-ath12k-clear-affinity-hint-before-calling-ath12.patch +f2fs-fix-to-set-.discard_granularity-correctly.patch +f2fs-add-check-for-deleted-inode.patch +arm64-dts-ti-k3-am62-verdin-dahlia-add-microphone-ja.patch +f2fs-fix-potential-deadloop-in-prepare_compress_over.patch +f2fs-fix-to-call-f2fs_recover_quota_end-correctly.patch +md-fix-mddev-uaf-while-iterating-all_mddevs-list.patch +md-raid1-raid10-don-t-ignore-io-flags.patch +md-md-bitmap-fix-wrong-bitmap_limit-for-clustermd-wh.patch +tracing-fix-declare_trace_condition.patch +tools-rv-keep-user-ldflags-in-build.patch +arm64-dts-ti-k3-am62p-enable-audio_refclkx.patch +arm64-dts-ti-k3-am62p-fix-pinctrl-settings.patch +arm64-dts-ti-k3-j722s-fix-pinctrl-settings.patch +wifi-rtw89-fw-correct-debug-message-format-in-rtw89_.patch +wifi-rtw89-pci-correct-isr-rdu-bit-for-8922ae.patch +blk-throttle-fix-lower-bps-rate-by-throtl_trim_slice.patch +soc-mediatek-mtk-mmsys-fix-mt8188-vdo1-dpi1-output-s.patch +soc-mediatek-mt8167-mmsys-fix-missing-regval-in-all-.patch +soc-mediatek-mt8365-mmsys-fix-routing-table-masks-an.patch +md-raid10-wait-barrier-before-returning-discard-requ.patch +block-ensure-correct-integrity-capability-propagatio.patch +block-correctly-initialize-blk_integrity_nogenerate-.patch +badblocks-fix-error-shitf-ops.patch +badblocks-factor-out-a-helper-try_adjacent_combine.patch +badblocks-attempt-to-merge-adjacent-badblocks-during.patch +badblocks-return-error-directly-when-setting-badbloc.patch +badblocks-return-error-if-any-badblock-set-fails.patch +badblocks-fix-the-using-of-max_badblocks.patch +badblocks-fix-merge-issue-when-new-badblocks-align-w.patch +badblocks-fix-missing-bad-blocks-on-retry-in-_badblo.patch +null_blk-generate-null_blk-configfs-features-string.patch +null_blk-introduce-badblocks_once-parameter.patch +null_blk-replace-null_process_cmd-call-in-null_zone_.patch +null_blk-do-partial-io-for-bad-blocks.patch +badblocks-return-boolean-from-badblocks_set-and-badb.patch +badblocks-use-sector_t-instead-of-int-to-avoid-trunc.patch +firmware-arm_scmi-use-ioread64-instead-of-ioread64_h.patch +net-airoha-fix-lan4-support-in-airoha_qdma_get_gdm_p.patch +iommu-amd-fix-header-file.patch +iommu-vt-d-fix-system-hang-on-reboot-f.patch +memory-mtk-smi-add-ostd-setting-for-mt8192.patch +gfs2-minor-evict-fix.patch +gfs2-skip-if-we-cannot-defer-delete.patch +arm-dts-imx6ul-tqma6ul1-change-include-order-to-disa.patch +arm64-dts-imx8mp-add-audio_axi_clk_root-to-audiomix-.patch +arm64-dts-imx8mp-change-audio_axi_clk_root-freq.-to-.patch +f2fs-fix-to-avoid-accessing-uninitialized-curseg.patch +iommu-handle-race-with-default-domain-setup.patch +wifi-mac80211-remove-ssid-from-ml-reconf.patch +f2fs-fix-to-avoid-running-out-of-free-segments.patch +block-fix-adding-folio-to-bio.patch +ext4-fix-potential-null-dereference-in-ext4-kunit-te.patch +ext4-convert-ext4_flags_-defines-to-enum.patch +ext4-add-ext4_flags_emergency_ro-bit.patch +ext4-correct-behavior-under-errors-remount-ro-mode.patch +ext4-show-emergency_ro-when-ext4_flags_emergency_ro-.patch +arm64-dts-rockchip-move-rk356x-scmi-shmem-to-reserve.patch +arm64-dts-rockchip-remove-bluetooth-node-from-rock-3.patch +bus-qcom-ssc-block-bus-remove-some-duplicated-iounma.patch +bus-qcom-ssc-block-bus-fix-the-error-handling-path-o.patch +arm64-dts-rockchip-fix-pcie-reset-gpio-on-orange-pi-.patch +arm64-dts-rockchip-fix-pwm-pinctrl-names.patch +arm64-dts-rockchip-remove-ethm0_clk0_25m_out-from-si.patch +erofs-allow-16-byte-volume-name-again.patch +ext4-add-missing-brelse-for-bh2-in-ext4_dx_add_entry.patch +ext4-verify-fast-symlink-length.patch +f2fs-fix-missing-discard-for-active-segments.patch +scsi-hisi_sas-fixed-failure-to-issue-vendor-specific.patch +scsi-target-tcm_loop-fix-wrong-abort-tag.patch +ext4-introduce-itail-helper.patch +ext4-fix-out-of-bound-read-in-ext4_xattr_inode_dec_r.patch +ext4-goto-right-label-out_mmap_sem-in-ext4_setattr.patch +jbd2-fix-off-by-one-while-erasing-journal.patch +ata-libata-fix-ncq-non-data-log-not-supported-print.patch +wifi-nl80211-store-chandef-on-the-correct-link-when-.patch +wifi-mac80211-check-basic-rates-validity-in-sta_link.patch +wifi-cfg80211-init-wiphy_work-before-allocating-rfki.patch +wifi-mwifiex-fix-premature-release-of-rf-calibration.patch +wifi-mwifiex-fix-rf-calibration-data-download-from-f.patch +ice-health.c-fix-compilation-on-gcc-7.5.patch +ice-ensure-periodic-output-start-time-is-in-the-futu.patch +ice-fix-reservation-of-resources-for-rdma-when-disab.patch +virtchnl-make-proto-and-filter-action-count-unsigned.patch +ice-stop-truncating-queue-ids-when-checking.patch +ice-validate-queue-quanta-parameters-to-prevent-oob-.patch +ice-fix-input-validation-for-virtchnl-bw.patch +ice-fix-using-untrusted-value-of-pkt_len-in-ice_vc_f.patch +idpf-check-error-for-register_netdev-on-init.patch +btrfs-get-used-bytes-while-holding-lock-at-btrfs_rec.patch +btrfs-fix-reclaimed-bytes-accounting-after-automatic.patch +btrfs-fix-block-group-refcount-race-in-btrfs_create_.patch +btrfs-don-t-clobber-ret-in-btrfs_validate_super.patch +wifi-mt76-mt7915-fix-possible-integer-overflows-in-m.patch +igb-reject-invalid-external-timestamp-requests-for-8.patch +renesas-reject-ptp_strict_flags-as-unsupported.patch +net-lan743x-reject-unsupported-external-timestamp-re.patch +broadcom-fix-supported-flag-check-in-periodic-output.patch +ptp-ocp-reject-unsupported-periodic-output-flags.patch +nvmet-pci-epf-always-configure-bar0-as-64-bit.patch +jbd2-add-a-missing-data-flush-during-file-and-fs-syn.patch +ext4-define-ext4_journal_destroy-wrapper.patch +ext4-avoid-journaling-sb-update-on-error-if-journal-.patch +eth-bnxt-fix-out-of-range-access-of-vnic_info-array.patch +net-remove-rtnl-dance-for-siocbraddif-and-siocbrdeli.patch +netfilter-nfnetlink_queue-initialize-ctx-to-avoid-me.patch +netfilter-nf_tables-only-use-nf_skip_indirect_calls-.patch +ax25-remove-broken-autobind.patch +net-mlx5e-fix-ethtool-n-flow-type-ip4-to-rss-context.patch +bnxt_en-mask-the-bd_cnt-field-in-the-tx-bd-properly.patch +bnxt_en-linearize-tx-skb-if-the-fragments-exceed-the.patch +net-dsa-mv88e6xxx-fix-atu_move_port_mask-for-6341-fa.patch +net-dsa-mv88e6xxx-enable-pvt-for-6321-switch.patch +net-dsa-mv88e6xxx-enable-.port_set_policy-for-6320-f.patch +net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch +net-dsa-mv88e6xxx-enable-stu-methods-for-6320-family.patch +mlxsw-spectrum_acl_bloom_filter-workaround-for-some-.patch +net-dsa-sja1105-fix-displaced-ethtool-statistics-cou.patch +net-dsa-sja1105-reject-other-rx-filters-than-hwtstam.patch +net-dsa-sja1105-fix-kasan-out-of-bounds-warning-in-s.patch +net-mlx5-lag-reload-representors-on-lag-creation-fai.patch +net-mlx5-start-health-poll-after-enable-hca.patch +vmxnet3-unregister-xdp-rxq-info-in-the-reset-path.patch +bonding-check-xdp-prog-when-set-bond-mode.patch +ibmvnic-use-kernel-helpers-for-hex-dumps.patch +net-fix-null-pointer-dereference-in-l3mdev_l3_rcv.patch +virtio_net-fix-endian-with-virtio_net_ctrl_rss.patch +bluetooth-add-quirk-for-broken-read_voice_setting.patch +bluetooth-add-quirk-for-broken-read_page_scan_type.patch +bluetooth-btusb-fix-regression-in-the-initialization.patch +bluetooth-hci_core-enable-buffer-flow-control-for-sc.patch +bluetooth-hci-add-definition-of-hci_rp_remote_name_r.patch +rwonce-handle-kcsan-like-kasan-in-read_word_at_a_tim.patch +net-dsa-microchip-fix-dcb-apptrust-configuration-on-.patch +bluetooth-btnxpuart-fix-kernel-panic-during-fw-relea.patch +bluetooth-hci_event-fix-handling-of-hci_ev_le_direct.patch +net-fix-the-devmem-sock-opts-and-msgs-for-parisc.patch +net-libwx-fix-tx-descriptor-content-for-some-tunnel-.patch +net-libwx-fix-tx-l4-checksum.patch +rwonce-fix-crash-by-removing-read_once-for-unaligned.patch +drm-bridge-ti-sn65dsi86-fix-multiple-instances.patch +drm-ssd130x-set-spi-.id_table-to-prevent-an-spi-core.patch +accel-amdxdna-return-error-when-setting-clock-failed.patch +drm-panthor-fix-a-race-between-the-reset-and-suspend.patch +drm-ssd130x-fix-ssd132x-encoding.patch +drm-ssd130x-ensure-ssd132x-pitch-is-correct.patch +drm-dp_mst-fix-drm-rad-print.patch +drm-bridge-it6505-fix-hdcp-v-match-check-is-not-perf.patch +drm-panthor-fix-race-condition-when-gathering-fdinfo.patch +drm-xlnx-zynqmp-fix-max-dma-segment-size.patch +drm-xlnx-zynqmp_dpsub-add-null-check-in-zynqmp_audio.patch +drm-zynqmp_dp-fix-a-deadlock-in-zynqmp_dp_ignore_hpd.patch +drm-vkms-fix-use-after-free-and-double-free-on-init-.patch +gpu-cdns-mhdp8546-fix-call-balance-of-mhdp-clk-handl.patch +drm-amdgpu-refine-smu-send-msg-debug-log-format.patch +drm-amdgpu-umsch-remove-vpe-test-from-umsch.patch +drm-amdgpu-umsch-declare-umsch-firmware.patch +drm-amdgpu-umsch-fix-ucode-check.patch +drm-amdgpu-vcn5.0.1-use-correct-dpm-helper.patch +pci-use-downstream-bridges-for-distributing-resource.patch +pci-remove-add_align-overwrite-unrelated-to-size0.patch +pci-simplify-size1-assignment-logic.patch +pci-allow-relaxed-bridge-window-tail-sizing-for-opti.patch +drm-mediatek-mtk_hdmi-unregister-audio-platform-devi.patch +drm-mediatek-mtk_hdmi-fix-typo-for-aud_sampe_size-me.patch +drm-amdgpu-replace-mutex-with-spinlock-for-rlcg-regi.patch +pci-aspm-fix-link-state-exit-during-switch-upstream-.patch +drm-panel-ilitek-ili9882t-fix-gpio-name-in-error-mes.patch +pci-acs-fix-pci-config_acs-parameter.patch +drm-amd-display-fix-an-indent-issue-in-dml21.patch +drm-msm-dpu-don-t-use-active-in-atomic_check.patch +drm-msm-dsi-phy-program-clock-inverters-in-correct-r.patch +drm-msm-dsi-use-existing-per-interface-slice-count-i.patch +drm-msm-dsi-set-phy-usescase-and-mode-before-registe.patch +drm-msm-dpu-fall-back-to-a-single-dsc-encoder-1-1-1-.patch +drm-msm-dpu-remove-arbitrary-limit-of-1-interface-in.patch +drm-msm-gem-fix-error-code-msm_parse_deps.patch +drm-amdkfd-fix-circular-locking-dependency-in-svm_ra.patch +pci-mediatek-gen3-configure-pbus_csr-registers-for-e.patch +pci-cadence-ep-fix-the-driver-to-send-msg-tlp-for-in.patch +pci-brcmstb-set-generation-limit-before-pcie-link-up.patch +pci-brcmstb-use-internal-register-to-change-link-cap.patch +pci-brcmstb-fix-error-path-after-a-call-to-regulator.patch +pci-brcmstb-fix-potential-premature-regulator-disabl.patch +selftests-pcie_bwctrl-add-set_pcie_speed.sh-to-test_.patch +pci-portdrv-only-disable-pciehp-interrupts-early-whe.patch +pci-avoid-reset-when-disabled-via-sysfs.patch +drm-msm-dpu-move-needs_cdm-setting-to-dpu_encoder_ge.patch +drm-msm-dpu-simplify-dpu_encoder_get_topology-interf.patch +drm-msm-dpu-don-t-set-crtc_state-mode_changed-from-a.patch +drm-panthor-update-cs_status_-defines-to-correct-val.patch +drm-file-add-fdinfo-helper-for-printing-regions-with.patch +drm-panthor-expose-size-of-driver-internal-bo-s-over.patch +drm-panthor-replace-sleep-locks-with-spinlocks-in-fd.patch +drm-panthor-avoid-sleep-locking-in-the-internal-bo-s.patch +drm-panthor-clean-up-fw-version-information-display.patch +drm-amd-display-fix-type-mismatch-in-calculatedynami.patch +drm-msm-a6xx-fix-a6xx-indexed-regs-in-devcoreduump.patch +powerpc-perf-fix-ref-counting-on-the-pmu-vpa_pmu.patch +misc-pci_endpoint_test-fix-pci_endpoint_test_bars_re.patch +misc-pci_endpoint_test-handle-bar-sizes-larger-than-.patch +pci-endpoint-pci-epf-test-handle-endianness-properly.patch +crypto-powerpc-mark-ghashp8-ppc.o-as-an-object_files.patch +powerpc-kexec-fix-physical-address-calculation-in-cl.patch +pci-remove-stray-put_device-in-pci_register_host_bri.patch +pci-xilinx-cpm-fix-irq-domain-leak-in-error-path-of-.patch +drm-mediatek-fix-config_updating-flag-never-false-wh.patch +drm-mediatek-dp-drm_err-dev_err-in-hpd-path-to-avoid.patch +drm-mediatek-dsi-fix-error-codes-in-mtk_dsi_host_tra.patch +drm-amd-display-avoid-npd-when-asic-does-not-support.patch +pci-dwc-ep-return-enomem-for-allocation-failures.patch +pci-histb-fix-an-error-handling-path-in-histb_pcie_p.patch +pci-fix-bar-resizing-when-vf-bars-are-assigned.patch +drm-amdgpu-mes-optimize-compute-loop-handling.patch +drm-amdgpu-mes-enable-compute-pipes-across-all-mec.patch +pci-pciehp-don-t-enable-hpie-when-resuming-in-poll-m.patch +pci-bwctrl-fix-pcie_bwctrl_select_speed-return-type.patch +io_uring-net-only-import-send_zc-buffer-once.patch +pci-fix-null-dereference-in-sr-iov-vf-creation-error.patch +io_uring-use-lockless_cq-flag-in-io_req_complete_pos.patch +io_uring-fix-retry-handling-off-iowq.patch +fbdev-au1100fb-move-a-variable-assignment-behind-a-n.patch +dummycon-fix-default-rows-cols.patch +mdacon-rework-dependency-list.patch +fbdev-sm501fb-add-some-geometry-checks.patch +crypto-iaa-test-the-correct-request-flag.patch +crypto-qat-set-parity-error-mask-for-qat_420xx.patch +crypto-tegra-use-separate-buffer-for-setkey.patch +crypto-tegra-do-not-use-fixed-size-buffers.patch +crypto-tegra-check-return-value-for-hash-do_one_req.patch +crypto-tegra-transfer-hash-init-function-to-crypto-e.patch +crypto-tegra-fix-hash-intermediate-result-handling.patch +crypto-bpf-add-module_description-for-skcipher.patch +crypto-tegra-use-hmac-fallback-when-keyslots-are-ful.patch +clk-amlogic-gxbb-drop-incorrect-flag-on-32k-clock.patch +crypto-hisilicon-sec2-fix-for-aead-authsize-alignmen.patch +crypto-hisilicon-sec2-fix-for-sec-spec-check.patch +rdma-mlx5-fix-page_size-variable-overflow.patch +remoteproc-core-clear-table_sz-when-rproc_shutdown.patch +of-property-increase-nr_fwnode_reference_args.patch +pinctrl-renesas-rzg2l-suppress-binding-attributes.patch +remoteproc-qcom_q6v5_pas-make-single-pd-handling-mor.patch +libbpf-fix-hypothetical-stt_section-extern-null-dere.patch +drivers-clk-qcom-ipq5424-fix-the-freq-table-of-sdcc1.patch +selftests-bpf-fix-string-read-in-strncmp-benchmark.patch +x86-mm-pat-fix-vm_pat-handling-when-fork-fails-in-co.patch +clk-renesas-r8a08g045-check-the-source-of-the-cpu-pl.patch +remoteproc-qcom-pas-add-minidump_id-to-sc7280-wpss.patch +clk-samsung-fix-ubsan-panic-in-samsung_clk_init.patch +pinctrl-nuvoton-npcm8xx-fix-error-handling-in-npcm8x.patch +crypto-tegra-fix-cmac-intermediate-result-handling.patch +clk-qcom-gcc-msm8953-fix-stuck-venus0_core0-clock.patch +selftests-bpf-fix-runqslower-cross-endian-build.patch +s390-remove-ioremap_wt-and-pgprot_writethrough.patch +rdma-mana_ib-ensure-variable-err-is-initialized.patch +crypto-tegra-set-iv-to-null-explicitly-for-aes-ecb.patch +remoteproc-qcom_q6v5_pas-use-resource-with-cx-pd-for.patch +clk-qcom-gcc-x1e80100-unregister-gcc_gpu_cfg_ahb_clk.patch +crypto-tegra-finalize-crypto-req-on-error.patch +crypto-tegra-reserve-keyslots-to-allocate-dynamicall.patch +bpf-use-preempt_count-directly-in-bpf_send_signal_co.patch +lib-842-improve-error-handling-in-sw842_compress.patch +pinctrl-renesas-rza2-fix-missing-of_node_put-call.patch +pinctrl-renesas-rzg2l-fix-missing-of_node_put-call.patch +rdma-mlx5-fix-mr-cache-initialization-error-flow.patch +selftests-bpf-fix-freplace_link-segfault-in-tailcall.patch +clk-rockchip-rk3328-fix-wrong-clk_ref_usb3otg-parent.patch +rdma-core-don-t-expose-hw_counters-outside-of-init-n.patch +rdma-mlx5-fix-calculation-of-total-invalidated-pages.patch +rdma-erdma-prevent-use-after-free-in-erdma_accept_ne.patch +remoteproc-qcom_q6v5_mss-handle-platforms-with-one-p.patch +power-supply-bq27xxx_battery-do-not-update-cached-fl.patch +leds-st1202-check-for-error-code-from-devm_mutex_ini.patch +crypto-api-fix-larval-relookup-type-and-mask.patch +ib-mad-check-available-slots-before-posting-receive-.patch +pinctrl-tegra-set-sfio-mode-to-mux-register.patch +clk-amlogic-g12b-fix-cluster-a-parent-data.patch +clk-amlogic-gxbb-drop-non-existing-32k-clock-parent.patch +selftests-bpf-select-numa_no_node-to-create-map.patch +rust-fix-signature-of-rust_fmt_argument.patch +crypto-tegra-fix-format-specifier-in-tegra_sha_prep_.patch +libbpf-add-namespace-for-errstr-making-it-libbpf_err.patch +clk-mmp-fix-null-vs-is_err-check.patch +pinctrl-npcm8xx-fix-incorrect-struct-npcm8xx_pincfg-.patch +samples-bpf-fix-broken-vmlinux-path-for-vmlinux_btf.patch +crypto-qat-remove-access-to-parity-register-for-qat-.patch +clk-clk-imx8mp-audiomix-fix-dsp-ocram_a-clock-parent.patch +clk-amlogic-g12a-fix-mmc-a-peripheral-clock.patch +pinctrl-bcm2835-don-t-einval-on-alternate-funcs-from.patch +x86-entry-fix-orc-unwinder-for-push_regs-with-save_r.patch +power-supply-max77693-fix-wrong-conversion-of-charge.patch +crypto-api-call-crypto_alg_put-in-crypto_unregister_.patch +clk-stm32f4-fix-an-uninitialized-variable.patch +crypto-nx-fix-uninitialised-hv_nxc-on-error.patch +clk-qcom-gcc-sm8650-do-not-turn-off-usb-gdscs-during.patch +bpf-fix-array-bounds-error-with-may_goto.patch +rdma-mlx5-fix-mlx5_poll_one-cur_qp-update-flow.patch +pinctrl-renesas-rzv2m-fix-missing-of_node_put-call.patch +clk-qcom-ipq5424-fix-software-and-hardware-flow-cont.patch +mfd-sm501-switch-to-bit-to-mitigate-integer-overflow.patch +leds-fix-led_off-brightness-race.patch +x86-dumpstack-fix-inaccurate-unwinding-from-exceptio.patch +rdma-core-fix-use-after-free-when-rename-device-name.patch +crypto-hisilicon-sec2-fix-for-aead-auth-key-length.patch +pinctrl-intel-fix-wrong-bypass-assignment-in-intel_p.patch +clk-qcom-mmcc-sdm660-fix-stuck-video_subcore0-clock.patch +libbpf-fix-accessing-btf.ext-core_relo-header.patch +perf-stat-fix-find_stat-for-mixed-legacy-non-legacy-.patch +perf-always-feature-test-reallocarray.patch +w1-fix-null-pointer-dereference-in-probe.patch +staging-gpib-add-missing-interface-entry-point.patch +staging-gpib-fix-pr_err-format-warning.patch +usb-typec-thunderbolt-fix-loops-that-iterate-typec_p.patch +usb-typec-thunderbolt-remove-is_err-check-for-plug.patch +iio-dac-adi-axi-dac-modify-stream-enable.patch +perf-test-fix-hwmon-pmu-test-endianess-issue.patch +perf-stat-don-t-merge-counters-purely-on-name.patch +fs-ntfs3-factor-out-ntfs_-create-remove-_procdir.patch +fs-ntfs3-factor-out-ntfs_-create-remove-_proc_root.patch +fs-ntfs3-fix-proc_info_root-leak-when-init-ntfs-fail.patch +fs-ntfs3-update-inode-i_mapping-a_ops-on-compression.patch +iio-light-veml6030-extend-regmap-to-support-regfield.patch +iio-gts-helper-export-iio_gts_get_total_gain.patch +iio-light-veml6030-fix-scale-to-conform-to-abi.patch +iio-adc-ad7124-micro-optimize-channel-disabling.patch +iio-adc-ad7124-really-disable-all-channels-at-probe-.patch +phy-phy-rockchip-samsung-hdptx-don-t-use-dt-aliases-.patch +perf-tools-add-skip-check-in-tool_pmu__event_to_str.patch +isofs-fix-kmsan-uninit-value-bug-in-do_isofs_readdir.patch +perf-tests-fix-tool-pmu-test-segfault.patch +soundwire-slave-fix-an-of-node-reference-leak-in-sou.patch +staging-gpib-fix-cb7210-pcmcia-oops.patch +perf-report-switch-data-file-correctly-in-tui.patch +perf-report-add-parallelism-sort-key.patch +perf-report-fix-input-reload-switch-with-symbol-sort.patch +greybus-gb-beagleplay-add-error-handling-for-gb_grey.patch +coresight-catu-fix-number-of-pages-while-using-64k-p.patch +vhost-scsi-fix-handling-of-multiple-calls-to-vhost_s.patch +coresight-etm4x-add-isb-before-reading-the-trcstatr.patch +perf-pmus-restructure-pmu_read_sysfs-to-scan-fewer-p.patch +perf-pmu-dynamically-allocate-tool-pmu.patch +perf-pmu-don-t-double-count-common-sysfs-and-json-ev.patch +tools-x86-fix-linux-unaligned.h-include-path-in-lib-.patch +perf-build-fix-in-tree-build-due-to-symbolic-link.patch +ucsi_ccg-don-t-show-failed-to-get-fw-build-informati.patch +iio-accel-mma8452-ensure-error-return-on-failure-to-.patch +iio-accel-msa311-fix-failure-to-release-runtime-pm-i.patch +iio-backend-make-sure-to-null-terminate-stack-buffer.patch +iio-core-rework-claim-and-release-of-direct-mode-to-.patch +iio-adc-ad7173-grab-direct-mode-for-calibration.patch +iio-adc-ad7192-grab-direct-mode-for-calibration.patch +perf-arm-spe-fix-load-store-operation-checking.patch +perf-bench-fix-perf-bench-syscall-loop-count.patch +perf-machine-fixup-kernel-maps-ends-after-adding-ext.patch +usb-xhci-correct-debug-message-page-size-calculation.patch +fs-ntfs3-fix-a-couple-integer-overflows-on-32bit-sys.patch +fs-ntfs3-prevent-integer-overflow-in-hdr_first_de.patch +perf-test-add-timeout-to-datasym-workload.patch +perf-tests-fix-data-symbol-test-with-lto-builds.patch +nfsd-fix-callback-decoder-status-codes.patch +soundwire-take-in-count-the-bandwidth-of-a-prepared-.patch +dmaengine-fsl-edma-cleanup-chan-after-dma_async_devi.patch +dmaengine-fsl-edma-free-irq-correctly-in-remove-path.patch +dmaengine-ae4dma-use-the-msi-count-and-its-correspon.patch +dmaengine-ptdma-utilize-the-ae4dma-engine-s-multi-qu.patch +iio-adc-ad_sigma_delta-disable-channel-after-calibra.patch +iio-adc-ad4130-fix-comparison-of-channel-setups.patch +iio-adc-ad7124-fix-comparison-of-channel-configs.patch +iio-adc-ad7173-fix-comparison-of-channel-configs.patch +iio-adc-ad7768-1-set-mosi-idle-state-to-prevent-acci.patch +iio-light-add-check-for-array-bounds-in-veml6075_rea.patch +perf-debug-avoid-stack-overflow-in-recursive-error-m.patch +perf-evlist-add-success-path-to-evlist__create_syswi.patch +perf-evsel-tp_format-accessing-improvements.patch +perf-x86-topdown-fix-topdown-leader-sampling-test-er.patch +perf-units-fix-insufficient-array-space.patch +perf-test-stat_all_pmu.sh-correctly-check-perf-stat-.patch +kernel-events-uprobes-handle-device-exclusive-entrie.patch +kexec-initialize-elf-lowest-address-to-ulong_max.patch +ocfs2-validate-l_tree_depth-to-avoid-out-of-bounds-a.patch +reboot-replace-__hw_protection_shutdown-bool-action-.patch +reboot-reboot-not-shutdown-on-hw_protection_reboot-t.patch +rust-pci-use-to_result-in-enable_device_mem.patch +rust-pci-fix-unrestricted-mut-pci-device.patch +rust-platform-fix-unrestricted-mut-platform-device.patch +arch-powerpc-drop-generic_ptdump-from-mpc885_ads_def.patch +writeback-let-trace_balance_dirty_pages-take-struct-.patch +writeback-fix-calculations-in-trace_balance_dirty_pa.patch +scripts-gdb-linux-symbols.py-address-changes-to-modu.patch +nfsv4-don-t-trigger-uneccessary-scans-for-return-on-.patch +nfsv4-avoid-unnecessary-scans-of-filesystems-for-ret.patch +nfsv4-avoid-unnecessary-scans-of-filesystems-for-exp.patch +nfsv4-avoid-unnecessary-scans-of-filesystems-for-del.patch +nfs-fix-open_owner_id_maxsz-and-related-fields.patch +fuse-fix-dax-truncate-punch_hole-fault-path.patch +selftests-mm-cow-fix-the-incorrect-error-handling.patch +um-pass-the-correct-rust-target-and-options-with-gcc.patch +um-remove-copy_from_kernel_nofault_allowed.patch +um-hostfs-avoid-issues-on-inode-number-reuse-by-host.patch +i3c-master-svc-fix-missing-the-ibi-rules.patch +perf-python-fixup-description-of-sample.id-event-mem.patch +perf-python-decrement-the-refcount-of-just-created-e.patch +perf-python-don-t-keep-a-raw_data-pointer-to-consume.patch +perf-python-check-if-there-is-space-to-copy-all-the-.patch +perf-dso-fix-dso__is_kallsyms-check.patch +perf-intel-tpebs-fix-incorrect-usage-of-zfree.patch +perf-pmu-handle-memory-failure-in-tool_pmu__new.patch +staging-rtl8723bs-select-config_crypto_lib_aes.patch +staging-vchiq_arm-register-debugfs-after-cdev.patch +staging-vchiq_arm-fix-possible-npr-of-keep-alive-thr.patch +staging-vchiq_arm-stop-kthreads-if-vchiq-cdev-regist.patch +tty-n_tty-use-uint-for-space-returned-by-tty_write_r.patch +perf-vendor-events-arm64-ampereonex-fix-frontend_bou.patch +fs-procfs-fix-the-comment-above-proc_pid_wchan.patch +perf-tools-fix-is_compat_mode-build-break-in-ppc64.patch +perf-tools-annotate-asm_pure_loop.s.patch +perf-bpf-filter-fix-a-parsing-error-with-comma.patch +objtool-handle-various-symbol-types-of-rodata.patch +objtool-handle-different-entry-size-of-rodata.patch +objtool-handle-pc-relative-relocation-type.patch +objtool-fix-detection-of-consecutive-jump-tables-on-.patch +thermal-core-remove-duplicate-struct-declaration.patch +objtool-spi-amd-fix-out-of-bounds-stack-access-in-am.patch +objtool-nvmet-fix-out-of-bounds-stack-access-in-nvme.patch +objtool-media-dib8000-prevent-divide-by-zero-in-dib8.patch +nfs-shut-down-the-nfs_client-only-after-all-the-supe.patch +smb-client-fix-netns-refcount-imbalance-causing-leak.patch +exfat-fix-the-infinite-loop-in-exfat_find_last_clust.patch +exfat-fix-missing-shutdown-check.patch +rtnetlink-allocate-vfinfo-size-for-vf-guids-when-sup.patch +rndis_host-flag-rndis-modems-as-wwan-devices.patch +ksmbd-use-aead_request_free-to-match-aead_request_al.patch +ksmbd-fix-multichannel-connection-failure.patch +ksmbd-fix-r_count-dec-increment-mismatch.patch +net-mlx5e-shampo-make-reserved-size-independent-of-p.patch +ring-buffer-fix-bytes_dropped-calculation-issue.patch +objtool-fix-segfault-in-ignore_unreachable_insn.patch +loongarch-fix-help-text-of-cmdline_extend-in-kconfig.patch +loongarch-fix-device-node-refcount-leak-in-fdt_cpu_c.patch +loongarch-rework-the-arch_kgdb_breakpoint-implementa.patch +acpi-processor-idle-return-an-error-if-both-p_lvl-2-.patch +net-phy-broadcom-correct-bcm5221-phy-model-detection.patch +octeontx2-af-fix-mbox-intr-handler-when-num-vfs-64.patch +octeontx2-af-free-nix_af_int_vec_gen-irq.patch +objtool-fix-verbose-disassembly-if-cross_compile-isn.patch +sched-smt-always-inline-sched_smt_active.patch +context_tracking-always-inline-ct_-nmi-irq-_-enter-e.patch +rcu-tasks-always-inline-rcu_irq_work_resched.patch +objtool-loongarch-add-unwind-hints-in-prepare_framet.patch +nfs-add-missing-release-on-error-in-nfs_lock_and_joi.patch +rtc-renesas-rtca3-disable-interrupts-only-if-the-rtc.patch +spufs-fix-a-leak-on-spufs_new_file-failure.patch +spufs-fix-gang-directory-lifetimes.patch +spufs-fix-a-leak-in-spufs_create_context.patch +fs-9p-fix-null-pointer-dereference-on-mkdir.patch +riscv-ftrace-add-parentheses-in-macro-definitions-of.patch +riscv-fix-the-__riscv_copy_vec_words_unaligned-imple.patch +riscv-fix-missing-__free_pages-in-check_vector_unali.patch +riscv-fgraph-select-have_function_graph_tracer-depen.patch +ntb_hw_switchtec-fix-shift-out-of-bounds-in-switchte.patch +ntb-intel-fix-using-link-status-db-s.patch +riscv-fgraph-fix-stack-layout-to-match-__arch_ftrace.patch +riscv-annotate-unaligned-access-init-functions.patch +riscv-fix-riscv_online_cpu_vec.patch +riscv-fix-check_unaligned_access_all_cpus.patch +riscv-change-check_unaligned_access_speed_all_cpus-t.patch +riscv-fix-set-up-of-cpu-hotplug-callbacks.patch +riscv-fix-set-up-of-vector-cpu-hotplug-callback.patch +firmware-cs_dsp-ensure-cs_dsp_load-_coeff-returns-0-.patch +alsa-hda-realtek-fix-built-in-mic-breakage-on-asus-v.patch +risc-v-errata-use-medany-for-relocatable-builds.patch +x86-uaccess-improve-performance-by-aligning-writes-t.patch +ublk-make-sure-ubq-canceling-is-set-when-queue-is-fr.patch +s390-entry-fix-setting-_cif_mcck_guest-with-lowcore-.patch +asoc-codecs-rt5665-fix-some-error-handling-paths-in-.patch +spi-cadence-fix-out-of-bounds-array-access-in-cdns_m.patch +riscv-fix-hugetlb-retrieval-of-number-of-ptes-in-cas.patch +riscv-kexec_file-handle-r_riscv_64-in-purgatory-relo.patch +riscv-purgatory-4b-align-purgatory_start.patch +nvme-ioctl-don-t-warn-on-vectorized-uring_cmd-with-f.patch +nvme-pci-skip-nvme_write_sq_db-on-empty-rqlist.patch +asoc-imx-card-add-null-check-in-imx_card_probe.patch +spi-bcm2835-do-not-call-gpiod_put-on-invalid-descrip.patch +alsa-hda-realtek-fix-built-in-mic-on-another-asus-vi.patch +spi-bcm2835-restore-native-cs-probing-when-pinctrl-b.patch +xsk-add-launch-time-hardware-offload-support-to-xdp-.patch +igc-refactor-empty-frame-insertion-for-launch-time-s.patch +igc-add-launch-time-support-to-xdp-zc.patch +igc-fix-tx-drops-in-xdp-zc.patch +e1000e-change-k1-configuration-on-mtp-and-later-plat.patch +ixgbe-fix-media-type-detection-for-e610-device.patch +idpf-fix-adapter-null-pointer-dereference-on-reboot.patch +netfilter-nft_set_hash-gc-reaps-elements-with-connco.patch +netfilter-nf_tables-don-t-unregister-hook-when-table.patch +netlabel-fix-null-pointer-exception-caused-by-calips.patch +net_sched-skbprio-remove-overly-strict-queue-asserti.patch +sctp-add-mutual-exclusion-in-proc_sctp_do_udp_port.patch +net-airoha-fix-qid-report-in-airoha_tc_get_htb_get_l.patch +net-airoha-fix-ets-priomap-validation.patch +net-mvpp2-prevent-parser-tcam-memory-corruption.patch +rtnetlink-use-register_pernet_subsys-in-rtnl_net_deb.patch +udp-fix-multiple-wraparounds-of-sk-sk_rmem_alloc.patch +udp-fix-memory-accounting-leak.patch +vsock-avoid-timeout-during-connect-if-the-socket-is-.patch +tunnels-accept-packet_host-in-skb_tunnel_check_pmtu.patch +xsk-fix-__xsk_generic_xmit-error-code-when-cq-is-ful.patch +net-decrease-cached-dst-counters-in-dst_release.patch +netfilter-nft_tunnel-fix-geneve_opt-type-confusion-a.patch +sfc-rip-out-mdio-support.patch +sfc-fix-null-dereferences-in-ef100_process_design_pa.patch +ipv6-fix-omitted-netlink-attributes-when-using-rtext.patch +net-dsa-mv88e6xxx-propperly-shutdown-ppu-re-enable-t.patch +net-fix-geneve_opt-length-integer-overflow.patch +ipv6-start-path-selection-from-the-first-nexthop.patch +ipv6-do-not-consider-link-down-nexthops-in-path-sele.patch +arcnet-add-null-check-in-com20020pci_probe.patch +net-ibmveth-make-veth_pool_store-stop-hanging.patch +netlink-specs-rt_route-pull-the-ifa-prefix-out-of-th.patch diff --git a/queue-6.14/sfc-fix-null-dereferences-in-ef100_process_design_pa.patch b/queue-6.14/sfc-fix-null-dereferences-in-ef100_process_design_pa.patch new file mode 100644 index 0000000000..08aec8e8c4 --- /dev/null +++ b/queue-6.14/sfc-fix-null-dereferences-in-ef100_process_design_pa.patch @@ -0,0 +1,157 @@ +From 76562363602df8f06a4e2489547657642c030762 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Apr 2025 23:54:39 +0100 +Subject: sfc: fix NULL dereferences in ef100_process_design_param() + +From: Edward Cree + +[ Upstream commit 8241ecec1cdc6699ae197d52d58e76bddd995fa5 ] + +Since cited commit, ef100_probe_main() and hence also + ef100_check_design_params() run before efx->net_dev is created; + consequently, we cannot netif_set_tso_max_size() or _segs() at this + point. +Move those netif calls to ef100_probe_netdev(), and also replace + netif_err within the design params code with pci_err. + +Reported-by: Kyungwook Boo +Fixes: 98ff4c7c8ac7 ("sfc: Separate netdev probe/remove from PCI probe/remove") +Signed-off-by: Edward Cree +Reviewed-by: Michal Swiatkowski +Link: https://patch.msgid.link/20250401225439.2401047-1-edward.cree@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/sfc/ef100_netdev.c | 6 ++-- + drivers/net/ethernet/sfc/ef100_nic.c | 47 +++++++++++-------------- + 2 files changed, 24 insertions(+), 29 deletions(-) + +diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c +index d941f073f1ebf..3a06e3b1bd6bf 100644 +--- a/drivers/net/ethernet/sfc/ef100_netdev.c ++++ b/drivers/net/ethernet/sfc/ef100_netdev.c +@@ -450,8 +450,9 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data) + net_dev->hw_enc_features |= efx->type->offload_features; + net_dev->vlan_features |= NETIF_F_HW_CSUM | NETIF_F_SG | + NETIF_F_HIGHDMA | NETIF_F_ALL_TSO; +- netif_set_tso_max_segs(net_dev, +- ESE_EF100_DP_GZ_TSO_MAX_HDR_NUM_SEGS_DEFAULT); ++ nic_data = efx->nic_data; ++ netif_set_tso_max_size(efx->net_dev, nic_data->tso_max_payload_len); ++ netif_set_tso_max_segs(efx->net_dev, nic_data->tso_max_payload_num_segs); + + rc = efx_ef100_init_datapath_caps(efx); + if (rc < 0) +@@ -477,7 +478,6 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data) + /* Don't fail init if RSS setup doesn't work. */ + efx_mcdi_push_default_indir_table(efx, efx->n_rx_channels); + +- nic_data = efx->nic_data; + rc = ef100_get_mac_address(efx, net_dev->perm_addr, CLIENT_HANDLE_SELF, + efx->type->is_vf); + if (rc) +diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c +index 62e674d6ff60c..3ad95a4c8af2d 100644 +--- a/drivers/net/ethernet/sfc/ef100_nic.c ++++ b/drivers/net/ethernet/sfc/ef100_nic.c +@@ -887,8 +887,7 @@ static int ef100_process_design_param(struct efx_nic *efx, + case ESE_EF100_DP_GZ_TSO_MAX_HDR_NUM_SEGS: + /* We always put HDR_NUM_SEGS=1 in our TSO descriptors */ + if (!reader->value) { +- netif_err(efx, probe, efx->net_dev, +- "TSO_MAX_HDR_NUM_SEGS < 1\n"); ++ pci_err(efx->pci_dev, "TSO_MAX_HDR_NUM_SEGS < 1\n"); + return -EOPNOTSUPP; + } + return 0; +@@ -901,32 +900,28 @@ static int ef100_process_design_param(struct efx_nic *efx, + */ + if (!reader->value || reader->value > EFX_MIN_DMAQ_SIZE || + EFX_MIN_DMAQ_SIZE % (u32)reader->value) { +- netif_err(efx, probe, efx->net_dev, +- "%s size granularity is %llu, can't guarantee safety\n", +- reader->type == ESE_EF100_DP_GZ_RXQ_SIZE_GRANULARITY ? "RXQ" : "TXQ", +- reader->value); ++ pci_err(efx->pci_dev, ++ "%s size granularity is %llu, can't guarantee safety\n", ++ reader->type == ESE_EF100_DP_GZ_RXQ_SIZE_GRANULARITY ? "RXQ" : "TXQ", ++ reader->value); + return -EOPNOTSUPP; + } + return 0; + case ESE_EF100_DP_GZ_TSO_MAX_PAYLOAD_LEN: + nic_data->tso_max_payload_len = min_t(u64, reader->value, + GSO_LEGACY_MAX_SIZE); +- netif_set_tso_max_size(efx->net_dev, +- nic_data->tso_max_payload_len); + return 0; + case ESE_EF100_DP_GZ_TSO_MAX_PAYLOAD_NUM_SEGS: + nic_data->tso_max_payload_num_segs = min_t(u64, reader->value, 0xffff); +- netif_set_tso_max_segs(efx->net_dev, +- nic_data->tso_max_payload_num_segs); + return 0; + case ESE_EF100_DP_GZ_TSO_MAX_NUM_FRAMES: + nic_data->tso_max_frames = min_t(u64, reader->value, 0xffff); + return 0; + case ESE_EF100_DP_GZ_COMPAT: + if (reader->value) { +- netif_err(efx, probe, efx->net_dev, +- "DP_COMPAT has unknown bits %#llx, driver not compatible with this hw\n", +- reader->value); ++ pci_err(efx->pci_dev, ++ "DP_COMPAT has unknown bits %#llx, driver not compatible with this hw\n", ++ reader->value); + return -EOPNOTSUPP; + } + return 0; +@@ -946,10 +941,10 @@ static int ef100_process_design_param(struct efx_nic *efx, + * So the value of this shouldn't matter. + */ + if (reader->value != ESE_EF100_DP_GZ_VI_STRIDES_DEFAULT) +- netif_dbg(efx, probe, efx->net_dev, +- "NIC has other than default VI_STRIDES (mask " +- "%#llx), early probing might use wrong one\n", +- reader->value); ++ pci_dbg(efx->pci_dev, ++ "NIC has other than default VI_STRIDES (mask " ++ "%#llx), early probing might use wrong one\n", ++ reader->value); + return 0; + case ESE_EF100_DP_GZ_RX_MAX_RUNT: + /* Driver doesn't look at L2_STATUS:LEN_ERR bit, so we don't +@@ -961,9 +956,9 @@ static int ef100_process_design_param(struct efx_nic *efx, + /* Host interface says "Drivers should ignore design parameters + * that they do not recognise." + */ +- netif_dbg(efx, probe, efx->net_dev, +- "Ignoring unrecognised design parameter %u\n", +- reader->type); ++ pci_dbg(efx->pci_dev, ++ "Ignoring unrecognised design parameter %u\n", ++ reader->type); + return 0; + } + } +@@ -999,13 +994,13 @@ static int ef100_check_design_params(struct efx_nic *efx) + */ + if (reader.state != EF100_TLV_TYPE) { + if (reader.state == EF100_TLV_TYPE_CONT) +- netif_err(efx, probe, efx->net_dev, +- "truncated design parameter (incomplete type %u)\n", +- reader.type); ++ pci_err(efx->pci_dev, ++ "truncated design parameter (incomplete type %u)\n", ++ reader.type); + else +- netif_err(efx, probe, efx->net_dev, +- "truncated design parameter %u\n", +- reader.type); ++ pci_err(efx->pci_dev, ++ "truncated design parameter %u\n", ++ reader.type); + rc = -EIO; + } + out: +-- +2.39.5 + diff --git a/queue-6.14/sfc-rip-out-mdio-support.patch b/queue-6.14/sfc-rip-out-mdio-support.patch new file mode 100644 index 0000000000..c4f7af1c20 --- /dev/null +++ b/queue-6.14/sfc-rip-out-mdio-support.patch @@ -0,0 +1,228 @@ +From 1feeb1552aaf3242d2259df5f7268a86152fadc5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Mar 2025 17:57:10 +0000 +Subject: sfc: rip out MDIO support + +From: Edward Cree + +[ Upstream commit c339fcdd738be78c540407ae78fef5601ba5092a ] + +Unlike Siena, no EF10 board ever had an external PHY, and consequently + MDIO handling isn't even built into the firmware. Since Siena has + been split out into its own driver, the MDIO code can be deleted from + the sfc driver. + +Signed-off-by: Edward Cree +Link: https://patch.msgid.link/aa689d192ddaef7abe82709316c2be648a7bd66e.1742493017.git.ecree.xilinx@gmail.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 8241ecec1cdc ("sfc: fix NULL dereferences in ef100_process_design_param()") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/sfc/ef100_netdev.c | 1 - + drivers/net/ethernet/sfc/efx.c | 24 --------- + drivers/net/ethernet/sfc/mcdi_port.c | 59 +-------------------- + drivers/net/ethernet/sfc/mcdi_port_common.c | 11 ---- + drivers/net/ethernet/sfc/net_driver.h | 6 +-- + 5 files changed, 2 insertions(+), 99 deletions(-) + +diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c +index 7f7d560cb2b4c..d941f073f1ebf 100644 +--- a/drivers/net/ethernet/sfc/ef100_netdev.c ++++ b/drivers/net/ethernet/sfc/ef100_netdev.c +@@ -452,7 +452,6 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data) + NETIF_F_HIGHDMA | NETIF_F_ALL_TSO; + netif_set_tso_max_segs(net_dev, + ESE_EF100_DP_GZ_TSO_MAX_HDR_NUM_SEGS_DEFAULT); +- efx->mdio.dev = net_dev; + + rc = efx_ef100_init_datapath_caps(efx); + if (rc < 0) +diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c +index 650136dfc642f..112e55b98ed3b 100644 +--- a/drivers/net/ethernet/sfc/efx.c ++++ b/drivers/net/ethernet/sfc/efx.c +@@ -474,28 +474,6 @@ void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs, + } + } + +-/************************************************************************** +- * +- * ioctls +- * +- *************************************************************************/ +- +-/* Net device ioctl +- * Context: process, rtnl_lock() held. +- */ +-static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd) +-{ +- struct efx_nic *efx = efx_netdev_priv(net_dev); +- struct mii_ioctl_data *data = if_mii(ifr); +- +- /* Convert phy_id from older PRTAD/DEVAD format */ +- if ((cmd == SIOCGMIIREG || cmd == SIOCSMIIREG) && +- (data->phy_id & 0xfc00) == 0x0400) +- data->phy_id ^= MDIO_PHY_ID_C45 | 0x0400; +- +- return mdio_mii_ioctl(&efx->mdio, data, cmd); +-} +- + /************************************************************************** + * + * Kernel net device interface +@@ -593,7 +571,6 @@ static const struct net_device_ops efx_netdev_ops = { + .ndo_tx_timeout = efx_watchdog, + .ndo_start_xmit = efx_hard_start_xmit, + .ndo_validate_addr = eth_validate_addr, +- .ndo_eth_ioctl = efx_ioctl, + .ndo_change_mtu = efx_change_mtu, + .ndo_set_mac_address = efx_set_mac_address, + .ndo_set_rx_mode = efx_set_rx_mode, +@@ -1201,7 +1178,6 @@ static int efx_pci_probe(struct pci_dev *pci_dev, + rc = efx_init_struct(efx, pci_dev); + if (rc) + goto fail1; +- efx->mdio.dev = net_dev; + + pci_info(pci_dev, "Solarflare NIC detected\n"); + +diff --git a/drivers/net/ethernet/sfc/mcdi_port.c b/drivers/net/ethernet/sfc/mcdi_port.c +index ad4694fa3ddae..7b236d291d8c2 100644 +--- a/drivers/net/ethernet/sfc/mcdi_port.c ++++ b/drivers/net/ethernet/sfc/mcdi_port.c +@@ -17,58 +17,6 @@ + #include "selftest.h" + #include "mcdi_port_common.h" + +-static int efx_mcdi_mdio_read(struct net_device *net_dev, +- int prtad, int devad, u16 addr) +-{ +- struct efx_nic *efx = efx_netdev_priv(net_dev); +- MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_READ_IN_LEN); +- MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_READ_OUT_LEN); +- size_t outlen; +- int rc; +- +- MCDI_SET_DWORD(inbuf, MDIO_READ_IN_BUS, efx->mdio_bus); +- MCDI_SET_DWORD(inbuf, MDIO_READ_IN_PRTAD, prtad); +- MCDI_SET_DWORD(inbuf, MDIO_READ_IN_DEVAD, devad); +- MCDI_SET_DWORD(inbuf, MDIO_READ_IN_ADDR, addr); +- +- rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_READ, inbuf, sizeof(inbuf), +- outbuf, sizeof(outbuf), &outlen); +- if (rc) +- return rc; +- +- if (MCDI_DWORD(outbuf, MDIO_READ_OUT_STATUS) != +- MC_CMD_MDIO_STATUS_GOOD) +- return -EIO; +- +- return (u16)MCDI_DWORD(outbuf, MDIO_READ_OUT_VALUE); +-} +- +-static int efx_mcdi_mdio_write(struct net_device *net_dev, +- int prtad, int devad, u16 addr, u16 value) +-{ +- struct efx_nic *efx = efx_netdev_priv(net_dev); +- MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_WRITE_IN_LEN); +- MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_WRITE_OUT_LEN); +- size_t outlen; +- int rc; +- +- MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_BUS, efx->mdio_bus); +- MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_PRTAD, prtad); +- MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_DEVAD, devad); +- MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_ADDR, addr); +- MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_VALUE, value); +- +- rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_WRITE, inbuf, sizeof(inbuf), +- outbuf, sizeof(outbuf), &outlen); +- if (rc) +- return rc; +- +- if (MCDI_DWORD(outbuf, MDIO_WRITE_OUT_STATUS) != +- MC_CMD_MDIO_STATUS_GOOD) +- return -EIO; +- +- return 0; +-} + + u32 efx_mcdi_phy_get_caps(struct efx_nic *efx) + { +@@ -97,12 +45,7 @@ int efx_mcdi_port_probe(struct efx_nic *efx) + { + int rc; + +- /* Set up MDIO structure for PHY */ +- efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; +- efx->mdio.mdio_read = efx_mcdi_mdio_read; +- efx->mdio.mdio_write = efx_mcdi_mdio_write; +- +- /* Fill out MDIO structure, loopback modes, and initial link state */ ++ /* Fill out loopback modes and initial link state */ + rc = efx_mcdi_phy_probe(efx); + if (rc != 0) + return rc; +diff --git a/drivers/net/ethernet/sfc/mcdi_port_common.c b/drivers/net/ethernet/sfc/mcdi_port_common.c +index 76ea26722ca46..dae684194ac8c 100644 +--- a/drivers/net/ethernet/sfc/mcdi_port_common.c ++++ b/drivers/net/ethernet/sfc/mcdi_port_common.c +@@ -448,15 +448,6 @@ int efx_mcdi_phy_probe(struct efx_nic *efx) + efx->phy_data = phy_data; + efx->phy_type = phy_data->type; + +- efx->mdio_bus = phy_data->channel; +- efx->mdio.prtad = phy_data->port; +- efx->mdio.mmds = phy_data->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22); +- efx->mdio.mode_support = 0; +- if (phy_data->mmd_mask & (1 << MC_CMD_MMD_CLAUSE22)) +- efx->mdio.mode_support |= MDIO_SUPPORTS_C22; +- if (phy_data->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22)) +- efx->mdio.mode_support |= MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; +- + caps = MCDI_DWORD(outbuf, GET_LINK_OUT_CAP); + if (caps & (1 << MC_CMD_PHY_CAP_AN_LBN)) + mcdi_to_ethtool_linkset(phy_data->media, caps, +@@ -546,8 +537,6 @@ void efx_mcdi_phy_get_link_ksettings(struct efx_nic *efx, struct ethtool_link_ks + cmd->base.port = mcdi_to_ethtool_media(phy_cfg->media); + cmd->base.phy_address = phy_cfg->port; + cmd->base.autoneg = !!(efx->link_advertising[0] & ADVERTISED_Autoneg); +- cmd->base.mdio_support = (efx->mdio.mode_support & +- (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22)); + + mcdi_to_ethtool_linkset(phy_cfg->media, phy_cfg->supported_cap, + cmd->link_modes.supported); +diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h +index f70a7b7d6345c..1d3e0f3101d4f 100644 +--- a/drivers/net/ethernet/sfc/net_driver.h ++++ b/drivers/net/ethernet/sfc/net_driver.h +@@ -15,7 +15,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +@@ -956,8 +956,6 @@ struct efx_mae; + * @stats_buffer: DMA buffer for statistics + * @phy_type: PHY type + * @phy_data: PHY private data (including PHY-specific stats) +- * @mdio: PHY MDIO interface +- * @mdio_bus: PHY MDIO bus ID (only used by Siena) + * @phy_mode: PHY operating mode. Serialised by @mac_lock. + * @link_advertising: Autonegotiation advertising flags + * @fec_config: Forward Error Correction configuration flags. For bit positions +@@ -1131,8 +1129,6 @@ struct efx_nic { + + unsigned int phy_type; + void *phy_data; +- struct mdio_if_info mdio; +- unsigned int mdio_bus; + enum efx_phy_mode phy_mode; + + __ETHTOOL_DECLARE_LINK_MODE_MASK(link_advertising); +-- +2.39.5 + diff --git a/queue-6.14/smack-dont-compile-ipv6-code-unless-ipv6-is-configur.patch b/queue-6.14/smack-dont-compile-ipv6-code-unless-ipv6-is-configur.patch new file mode 100644 index 0000000000..5e12091851 --- /dev/null +++ b/queue-6.14/smack-dont-compile-ipv6-code-unless-ipv6-is-configur.patch @@ -0,0 +1,133 @@ +From b856c7eeffb4b44c33c40fc8db7252297354d22f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jan 2025 19:36:42 +0300 +Subject: smack: dont compile ipv6 code unless ipv6 is configured + +From: Konstantin Andreev + +[ Upstream commit bfcf4004bcbce2cb674b4e8dbd31ce0891766bac ] + +I want to be sure that ipv6-specific code +is not compiled in kernel binaries +if ipv6 is not configured. + +[1] was getting rid of "unused variable" warning, but, +with that, it also mandated compilation of a handful ipv6- +specific functions in ipv4-only kernel configurations: + +smk_ipv6_localhost, smack_ipv6host_label, smk_ipv6_check. + +Their compiled bodies are likely to be removed by compiler +from the resulting binary, but, to be on the safe side, +I remove them from the compiler view. + +[1] +Fixes: 00720f0e7f28 ("smack: avoid unused 'sip' variable warning") + +Signed-off-by: Konstantin Andreev +Signed-off-by: Casey Schaufler +Signed-off-by: Sasha Levin +--- + security/smack/smack.h | 6 ++++++ + security/smack/smack_lsm.c | 10 +++++++++- + 2 files changed, 15 insertions(+), 1 deletion(-) + +diff --git a/security/smack/smack.h b/security/smack/smack.h +index 4608b07607a3d..c4d998972ba56 100644 +--- a/security/smack/smack.h ++++ b/security/smack/smack.h +@@ -152,6 +152,7 @@ struct smk_net4addr { + struct smack_known *smk_label; /* label */ + }; + ++#if IS_ENABLED(CONFIG_IPV6) + /* + * An entry in the table identifying IPv6 hosts. + */ +@@ -162,7 +163,9 @@ struct smk_net6addr { + int smk_masks; /* mask size */ + struct smack_known *smk_label; /* label */ + }; ++#endif /* CONFIG_IPV6 */ + ++#ifdef SMACK_IPV6_PORT_LABELING + /* + * An entry in the table identifying ports. + */ +@@ -175,6 +178,7 @@ struct smk_port_label { + short smk_sock_type; /* Socket type */ + short smk_can_reuse; + }; ++#endif /* SMACK_IPV6_PORT_LABELING */ + + struct smack_known_list_elem { + struct list_head list; +@@ -315,7 +319,9 @@ extern struct smack_known smack_known_web; + extern struct mutex smack_known_lock; + extern struct list_head smack_known_list; + extern struct list_head smk_net4addr_list; ++#if IS_ENABLED(CONFIG_IPV6) + extern struct list_head smk_net6addr_list; ++#endif /* CONFIG_IPV6 */ + + extern struct mutex smack_onlycap_lock; + extern struct list_head smack_onlycap_list; +diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c +index 239773cdcdcf4..85f3d4337ca19 100644 +--- a/security/smack/smack_lsm.c ++++ b/security/smack/smack_lsm.c +@@ -2492,6 +2492,7 @@ static struct smack_known *smack_ipv4host_label(struct sockaddr_in *sip) + return NULL; + } + ++#if IS_ENABLED(CONFIG_IPV6) + /* + * smk_ipv6_localhost - Check for local ipv6 host address + * @sip: the address +@@ -2559,6 +2560,7 @@ static struct smack_known *smack_ipv6host_label(struct sockaddr_in6 *sip) + + return NULL; + } ++#endif /* CONFIG_IPV6 */ + + /** + * smack_netlbl_add - Set the secattr on a socket +@@ -2663,6 +2665,7 @@ static int smk_ipv4_check(struct sock *sk, struct sockaddr_in *sap) + return rc; + } + ++#if IS_ENABLED(CONFIG_IPV6) + /** + * smk_ipv6_check - check Smack access + * @subject: subject Smack label +@@ -2695,6 +2698,7 @@ static int smk_ipv6_check(struct smack_known *subject, + rc = smk_bu_note("IPv6 check", subject, object, MAY_WRITE, rc); + return rc; + } ++#endif /* CONFIG_IPV6 */ + + #ifdef SMACK_IPV6_PORT_LABELING + /** +@@ -3027,7 +3031,9 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, + return 0; + if (addrlen < offsetofend(struct sockaddr, sa_family)) + return 0; +- if (IS_ENABLED(CONFIG_IPV6) && sap->sa_family == AF_INET6) { ++ ++#if IS_ENABLED(CONFIG_IPV6) ++ if (sap->sa_family == AF_INET6) { + struct sockaddr_in6 *sip = (struct sockaddr_in6 *)sap; + struct smack_known *rsp = NULL; + +@@ -3047,6 +3053,8 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, + + return rc; + } ++#endif /* CONFIG_IPV6 */ ++ + if (sap->sa_family != AF_INET || addrlen < sizeof(struct sockaddr_in)) + return 0; + rc = smk_ipv4_check(sock->sk, (struct sockaddr_in *)sap); +-- +2.39.5 + diff --git a/queue-6.14/smack-ipv4-ipv6-tcp-dccp-sctp-fix-incorrect-child-so.patch b/queue-6.14/smack-ipv4-ipv6-tcp-dccp-sctp-fix-incorrect-child-so.patch new file mode 100644 index 0000000000..f9e587259d --- /dev/null +++ b/queue-6.14/smack-ipv4-ipv6-tcp-dccp-sctp-fix-incorrect-child-so.patch @@ -0,0 +1,181 @@ +From 68480fcbb91b7474332696173b40b6c1b055fafb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 26 Jan 2025 17:07:27 +0300 +Subject: smack: ipv4/ipv6: tcp/dccp/sctp: fix incorrect child socket label +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Konstantin Andreev + +[ Upstream commit 6cce0cc3861337b3ad8d4ac131d6e47efa0954ec ] + +Since inception [1], SMACK initializes ipv* child socket security +for connection-oriented communications (tcp/sctp/dccp) +during accept() syscall, in the security_sock_graft() hook: + +| void smack_sock_graft(struct sock *sk, ...) +| { +| // only ipv4 and ipv6 are eligible here +| // ... +| ssp = sk->sk_security; // socket security +| ssp->smk_in = skp; // process label: smk_of_current() +| ssp->smk_out = skp; // process label: smk_of_current() +| } + +This approach is incorrect for two reasons: + +A) initialization occurs too late for child socket security: + + The child socket is created by the kernel once the handshake + completes (e.g., for tcp: after receiving ack for syn+ack). + + Data can legitimately start arriving to the child socket + immediately, long before the application calls accept() + on the socket. + + Those data are (currently — were) processed by SMACK using + incorrect child socket security attributes. + +B) Incoming connection requests are handled using the listening + socket's security, hence, the child socket must inherit the + listening socket's security attributes. + + smack_sock_graft() initilizes the child socket's security with + a process label, as is done for a new socket() + + But ... the process label is not necessarily the same as the + listening socket label. A privileged application may legitimately + set other in/out labels for a listening socket. + + When this happens, SMACK processes incoming packets using + incorrect socket security attributes. + +In [2] Michael Lontke noticed (A) and fixed it in [3] by adding +socket initialization into security_sk_clone_security() hook like + +| void smack_sk_clone_security(struct sock *oldsk, struct sock *newsk) +| { +| *(struct socket_smack *)newsk->sk_security = +| *(struct socket_smack *)oldsk->sk_security; +| } + +This initializes the child socket security with the parent (listening) +socket security at the appropriate time. + +I was forced to revisit this old story because + +smack_sock_graft() was left in place by [3] and continues overwriting +the child socket's labels with the process label, +and there might be a reason for this, so I undertook a study. + +If the process label differs from the listening socket's labels, +the following occurs for ipv4: + +assigning the smk_out is not accompanied by netlbl_sock_setattr, +so the outgoing packet's cipso label does not change. + +So, the only effect of this assignment for interhost communications +is a divergence between the program-visible “out” socket label and +the cipso network label. For intrahost communications this label, +however, becomes visible via secmark netfilter marking, and is +checked for access rights by the client, receiving side. + +Assigning the smk_in affects both interhost and intrahost +communications: the server begins to check access rights against +an wrong label. + +Access check against wrong label (smk_in or smk_out), +unsurprisingly fails, breaking the connection. + +The above affects protocols that calls security_sock_graft() +during accept(), namely: {tcp,dccp,sctp}/{ipv4,ipv6} +One extra security_sock_graft() caller, crypto/af_alg.c`af_alg_accept +is not affected, because smack_sock_graft() does nothing for PF_ALG. + +To reproduce, assign non-default in/out labels to a listening socket, +setup rules between these labels and client label, attempt to connect +and send some data. + +Ipv6 specific: ipv6 packets do not convey SMACK labels. To reproduce +the issue in interhost communications set opposite labels in +/smack/ipv6host on both hosts. +Ipv6 intrahost communications do not require tricking, because SMACK +labels are conveyed via secmark netfilter marking. + +So, currently smack_sock_graft() is not useful, but harmful, +therefore, I have removed it. + +This fixes the issue for {tcp,dccp}/{ipv4,ipv6}, +but not sctp/{ipv4,ipv6}. + +Although this change is necessary for sctp+smack to function +correctly, it is not sufficient because: +sctp/ipv4 does not call security_sk_clone() and +sctp/ipv6 ignores SMACK completely. + +These are separate issues, belong to other subsystem, +and should be addressed separately. + +[1] 2008-02-04, +Fixes: e114e473771c ("Smack: Simplified Mandatory Access Control Kernel") + +[2] Michael Lontke, 2022-08-31, SMACK LSM checks wrong object label + during ingress network traffic +Link: https://lore.kernel.org/linux-security-module/6324997ce4fc092c5020a4add075257f9c5f6442.camel@elektrobit.com/ + +[3] 2022-08-31, michael.lontke, + commit 4ca165fc6c49 ("SMACK: Add sk_clone_security LSM hook") + +Signed-off-by: Konstantin Andreev +Signed-off-by: Casey Schaufler +Signed-off-by: Sasha Levin +--- + security/smack/smack_lsm.c | 24 ------------------------ + 1 file changed, 24 deletions(-) + +diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c +index 85f3d4337ca19..e68c982e499eb 100644 +--- a/security/smack/smack_lsm.c ++++ b/security/smack/smack_lsm.c +@@ -4350,29 +4350,6 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, + return 0; + } + +-/** +- * smack_sock_graft - Initialize a newly created socket with an existing sock +- * @sk: child sock +- * @parent: parent socket +- * +- * Set the smk_{in,out} state of an existing sock based on the process that +- * is creating the new socket. +- */ +-static void smack_sock_graft(struct sock *sk, struct socket *parent) +-{ +- struct socket_smack *ssp; +- struct smack_known *skp = smk_of_current(); +- +- if (sk == NULL || +- (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)) +- return; +- +- ssp = smack_sock(sk); +- ssp->smk_in = skp; +- ssp->smk_out = skp; +- /* cssp->smk_packet is already set in smack_inet_csk_clone() */ +-} +- + /** + * smack_inet_conn_request - Smack access check on connect + * @sk: socket involved +@@ -5187,7 +5164,6 @@ static struct security_hook_list smack_hooks[] __ro_after_init = { + LSM_HOOK_INIT(sk_free_security, smack_sk_free_security), + #endif + LSM_HOOK_INIT(sk_clone_security, smack_sk_clone_security), +- LSM_HOOK_INIT(sock_graft, smack_sock_graft), + LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request), + LSM_HOOK_INIT(inet_csk_clone, smack_inet_csk_clone), + +-- +2.39.5 + diff --git a/queue-6.14/smb-client-fix-netns-refcount-imbalance-causing-leak.patch b/queue-6.14/smb-client-fix-netns-refcount-imbalance-causing-leak.patch new file mode 100644 index 0000000000..94df939a88 --- /dev/null +++ b/queue-6.14/smb-client-fix-netns-refcount-imbalance-causing-leak.patch @@ -0,0 +1,175 @@ +From 1804af0a24ba4e230e76db0e2867e500182c325c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 22:30:05 +0800 +Subject: smb: client: Fix netns refcount imbalance causing leaks and + use-after-free + +From: Wang Zhaolong + +[ Upstream commit 4e7f1644f2ac6d01dc584f6301c3b1d5aac4eaef ] + +Commit ef7134c7fc48 ("smb: client: Fix use-after-free of network +namespace.") attempted to fix a netns use-after-free issue by manually +adjusting reference counts via sk->sk_net_refcnt and sock_inuse_add(). + +However, a later commit e9f2517a3e18 ("smb: client: fix TCP timers deadlock +after rmmod") pointed out that the approach of manually setting +sk->sk_net_refcnt in the first commit was technically incorrect, as +sk->sk_net_refcnt should only be set for user sockets. It led to issues +like TCP timers not being cleared properly on close. The second commit +moved to a model of just holding an extra netns reference for +server->ssocket using get_net(), and dropping it when the server is torn +down. + +But there remain some gaps in the get_net()/put_net() balancing added by +these commits. The incomplete reference handling in these fixes results +in two issues: + +1. Netns refcount leaks[1] + +The problem process is as follows: + +``` +mount.cifs cifsd + +cifs_do_mount + cifs_mount + cifs_mount_get_session + cifs_get_tcp_session + get_net() /* First get net. */ + ip_connect + generic_ip_connect /* Try port 445 */ + get_net() + ->connect() /* Failed */ + put_net() + generic_ip_connect /* Try port 139 */ + get_net() /* Missing matching put_net() for this get_net().*/ + cifs_get_smb_ses + cifs_negotiate_protocol + smb2_negotiate + SMB2_negotiate + cifs_send_recv + wait_for_response + cifs_demultiplex_thread + cifs_read_from_socket + cifs_readv_from_socket + cifs_reconnect + cifs_abort_connection + sock_release(); + server->ssocket = NULL; + /* Missing put_net() here. */ + generic_ip_connect + get_net() + ->connect() /* Failed */ + put_net() + sock_release(); + server->ssocket = NULL; + free_rsp_buf + ... + clean_demultiplex_info + /* It's only called once here. */ + put_net() +``` + +When cifs_reconnect() is triggered, the server->ssocket is released +without a corresponding put_net() for the reference acquired in +generic_ip_connect() before. it ends up calling generic_ip_connect() +again to retry get_net(). After that, server->ssocket is set to NULL +in the error path of generic_ip_connect(), and the net count cannot be +released in the final clean_demultiplex_info() function. + +2. Potential use-after-free + +The current refcounting scheme can lead to a potential use-after-free issue +in the following scenario: + +``` + cifs_do_mount + cifs_mount + cifs_mount_get_session + cifs_get_tcp_session + get_net() /* First get net */ + ip_connect + generic_ip_connect + get_net() + bind_socket + kernel_bind /* failed */ + put_net() + /* after out_err_crypto_release label */ + put_net() + /* after out_err label */ + put_net() +``` + +In the exception handling process where binding the socket fails, the +get_net() and put_net() calls are unbalanced, which may cause the +server->net reference count to drop to zero and be prematurely released. + +To address both issues, this patch ties the netns reference counting to +the server->ssocket and server lifecycles. The extra reference is now +acquired when the server or socket is created, and released when the +socket is destroyed or the server is torn down. + +[1]: https://bugzilla.kernel.org/show_bug.cgi?id=219792 + +Fixes: ef7134c7fc48 ("smb: client: Fix use-after-free of network namespace.") +Fixes: e9f2517a3e18 ("smb: client: fix TCP timers deadlock after rmmod") +Signed-off-by: Wang Zhaolong +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/connect.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c +index 73f93a35eeddb..cb14a6828c501 100644 +--- a/fs/smb/client/connect.c ++++ b/fs/smb/client/connect.c +@@ -300,6 +300,7 @@ cifs_abort_connection(struct TCP_Server_Info *server) + server->ssocket->flags); + sock_release(server->ssocket); + server->ssocket = NULL; ++ put_net(cifs_net_ns(server)); + } + server->sequence_number = 0; + server->session_estab = false; +@@ -3123,8 +3124,12 @@ generic_ip_connect(struct TCP_Server_Info *server) + /* + * Grab netns reference for the socket. + * +- * It'll be released here, on error, or in clean_demultiplex_info() upon server +- * teardown. ++ * This reference will be released in several situations: ++ * - In the failure path before the cifsd thread is started. ++ * - In the all place where server->socket is released, it is ++ * also set to NULL. ++ * - Ultimately in clean_demultiplex_info(), during the final ++ * teardown. + */ + get_net(net); + +@@ -3140,10 +3145,8 @@ generic_ip_connect(struct TCP_Server_Info *server) + } + + rc = bind_socket(server); +- if (rc < 0) { +- put_net(cifs_net_ns(server)); ++ if (rc < 0) + return rc; +- } + + /* + * Eventually check for other socket options to change from +@@ -3189,9 +3192,6 @@ generic_ip_connect(struct TCP_Server_Info *server) + if (sport == htons(RFC1001_PORT)) + rc = ip_rfc1001_connect(server); + +- if (rc < 0) +- put_net(cifs_net_ns(server)); +- + return rc; + } + +-- +2.39.5 + diff --git a/queue-6.14/soc-mediatek-mt8167-mmsys-fix-missing-regval-in-all-.patch b/queue-6.14/soc-mediatek-mt8167-mmsys-fix-missing-regval-in-all-.patch new file mode 100644 index 0000000000..25dcf84d13 --- /dev/null +++ b/queue-6.14/soc-mediatek-mt8167-mmsys-fix-missing-regval-in-all-.patch @@ -0,0 +1,60 @@ +From 3359dfeaad6be3e4bd62ee14437b1b31ce4535b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 11:00:09 +0100 +Subject: soc: mediatek: mt8167-mmsys: Fix missing regval in all entries + +From: AngeloGioacchino Del Regno + +[ Upstream commit 5424793452d134ec1a173bd748c757144f25b1e2 ] + +The mmsys routing table for this SoC was effectively missing +initialization of the val variable of struct mtk_mmsys_routes: +this means that `val` was incorrectly initialized to zero, +hence the registers were wrongly initialized. + +Add the required regval to all of the entries of the routing +table for this SoC to fix display controller functionality. + +Fixes: 060f7875bd23 ("soc: mediatek: mmsys: Add support for MT8167 SoC") +Link: https://lore.kernel.org/r/20250212100012.33001-6-angelogioacchino.delregno@collabora.com +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + drivers/soc/mediatek/mt8167-mmsys.h | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/drivers/soc/mediatek/mt8167-mmsys.h b/drivers/soc/mediatek/mt8167-mmsys.h +index f7a35b3656bb1..655ef962abe9f 100644 +--- a/drivers/soc/mediatek/mt8167-mmsys.h ++++ b/drivers/soc/mediatek/mt8167-mmsys.h +@@ -17,18 +17,23 @@ static const struct mtk_mmsys_routes mt8167_mmsys_routing_table[] = { + { + DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0, + MT8167_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN, OVL0_MOUT_EN_COLOR0, ++ OVL0_MOUT_EN_COLOR0 + }, { + DDP_COMPONENT_DITHER0, DDP_COMPONENT_RDMA0, +- MT8167_DISP_REG_CONFIG_DISP_DITHER_MOUT_EN, MT8167_DITHER_MOUT_EN_RDMA0 ++ MT8167_DISP_REG_CONFIG_DISP_DITHER_MOUT_EN, MT8167_DITHER_MOUT_EN_RDMA0, ++ MT8167_DITHER_MOUT_EN_RDMA0 + }, { + DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0, +- MT8167_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN, COLOR0_SEL_IN_OVL0 ++ MT8167_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN, COLOR0_SEL_IN_OVL0, ++ COLOR0_SEL_IN_OVL0 + }, { + DDP_COMPONENT_RDMA0, DDP_COMPONENT_DSI0, +- MT8167_DISP_REG_CONFIG_DISP_DSI0_SEL_IN, MT8167_DSI0_SEL_IN_RDMA0 ++ MT8167_DISP_REG_CONFIG_DISP_DSI0_SEL_IN, MT8167_DSI0_SEL_IN_RDMA0, ++ MT8167_DSI0_SEL_IN_RDMA0 + }, { + DDP_COMPONENT_RDMA0, DDP_COMPONENT_DSI0, +- MT8167_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN, MT8167_RDMA0_SOUT_DSI0 ++ MT8167_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN, MT8167_RDMA0_SOUT_DSI0, ++ MT8167_RDMA0_SOUT_DSI0 + }, + }; + +-- +2.39.5 + diff --git a/queue-6.14/soc-mediatek-mt8365-mmsys-fix-routing-table-masks-an.patch b/queue-6.14/soc-mediatek-mt8365-mmsys-fix-routing-table-masks-an.patch new file mode 100644 index 0000000000..5ba18608c9 --- /dev/null +++ b/queue-6.14/soc-mediatek-mt8365-mmsys-fix-routing-table-masks-an.patch @@ -0,0 +1,127 @@ +From f7a34c8b1f18ef8df86a3243011a3941e7970c77 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 11:00:10 +0100 +Subject: soc: mediatek: mt8365-mmsys: Fix routing table masks and values + +From: AngeloGioacchino Del Regno + +[ Upstream commit d294d56cb9462e918421fe2bbe5f52a8da82603a ] + +The mmsys driver reads the routing table and writes to the +hardware `val & mask`, but multiple entries in the mmsys +routing table for the MT8365 SoC are setting a 0x0 mask: +this effectively writes .. nothing .. to the hardware. + +That would never work, and if the display controller was +actually working with the mmsys doing no routing at all, +that was only because the bootloader was correctly setting +the display controller routing registers before booting the +kernel, and the mmsys was never reset. + +Make this table to actually set the routing by adding the +correct register masks to it. + +While at it, also change MOUT val definitions to BIT(x), as +the MOUT registers are effectively checking for each bit to +enable output to the corresponding HW. +Please note that, for this SoC, only the MOUT registers are +checking bits (as those can enable multiple outputs), while +the others are purely reading a number to select an input. + +Fixes: bc3fc5c05100 ("soc: mediatek: mmsys: add MT8365 support") +Link: https://lore.kernel.org/r/20250212100012.33001-7-angelogioacchino.delregno@collabora.com +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + drivers/soc/mediatek/mt8365-mmsys.h | 48 ++++++++++++----------------- + 1 file changed, 20 insertions(+), 28 deletions(-) + +diff --git a/drivers/soc/mediatek/mt8365-mmsys.h b/drivers/soc/mediatek/mt8365-mmsys.h +index 7abaf048d91e8..ae37945e6c67c 100644 +--- a/drivers/soc/mediatek/mt8365-mmsys.h ++++ b/drivers/soc/mediatek/mt8365-mmsys.h +@@ -14,8 +14,9 @@ + #define MT8365_DISP_REG_CONFIG_DISP_DPI0_SEL_IN 0xfd8 + #define MT8365_DISP_REG_CONFIG_DISP_LVDS_SYS_CFG_00 0xfdc + ++#define MT8365_DISP_MS_IN_OUT_MASK GENMASK(3, 0) + #define MT8365_RDMA0_SOUT_COLOR0 0x1 +-#define MT8365_DITHER_MOUT_EN_DSI0 0x1 ++#define MT8365_DITHER_MOUT_EN_DSI0 BIT(0) + #define MT8365_DSI0_SEL_IN_DITHER 0x1 + #define MT8365_RDMA0_SEL_IN_OVL0 0x0 + #define MT8365_RDMA0_RSZ0_SEL_IN_RDMA0 0x0 +@@ -30,52 +31,43 @@ static const struct mtk_mmsys_routes mt8365_mmsys_routing_table[] = { + { + DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0, + MT8365_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN, +- MT8365_OVL0_MOUT_PATH0_SEL, MT8365_OVL0_MOUT_PATH0_SEL +- }, +- { ++ MT8365_DISP_MS_IN_OUT_MASK, MT8365_OVL0_MOUT_PATH0_SEL ++ }, { + DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0, + MT8365_DISP_REG_CONFIG_DISP_RDMA0_SEL_IN, +- MT8365_RDMA0_SEL_IN_OVL0, MT8365_RDMA0_SEL_IN_OVL0 +- }, +- { ++ MT8365_DISP_MS_IN_OUT_MASK, MT8365_RDMA0_SEL_IN_OVL0 ++ }, { + DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0, + MT8365_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL, +- MT8365_RDMA0_SOUT_COLOR0, MT8365_RDMA0_SOUT_COLOR0 +- }, +- { ++ MT8365_DISP_MS_IN_OUT_MASK, MT8365_RDMA0_SOUT_COLOR0 ++ }, { + DDP_COMPONENT_COLOR0, DDP_COMPONENT_CCORR, + MT8365_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN, +- MT8365_DISP_COLOR_SEL_IN_COLOR0,MT8365_DISP_COLOR_SEL_IN_COLOR0 +- }, +- { ++ MT8365_DISP_MS_IN_OUT_MASK, MT8365_DISP_COLOR_SEL_IN_COLOR0 ++ }, { + DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSI0, + MT8365_DISP_REG_CONFIG_DISP_DITHER0_MOUT_EN, +- MT8365_DITHER_MOUT_EN_DSI0, MT8365_DITHER_MOUT_EN_DSI0 +- }, +- { ++ MT8365_DISP_MS_IN_OUT_MASK, MT8365_DITHER_MOUT_EN_DSI0 ++ }, { + DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSI0, + MT8365_DISP_REG_CONFIG_DISP_DSI0_SEL_IN, +- MT8365_DSI0_SEL_IN_DITHER, MT8365_DSI0_SEL_IN_DITHER +- }, +- { ++ MT8365_DISP_MS_IN_OUT_MASK, MT8365_DSI0_SEL_IN_DITHER ++ }, { + DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0, + MT8365_DISP_REG_CONFIG_DISP_RDMA0_RSZ0_SEL_IN, +- MT8365_RDMA0_RSZ0_SEL_IN_RDMA0, MT8365_RDMA0_RSZ0_SEL_IN_RDMA0 +- }, +- { ++ MT8365_DISP_MS_IN_OUT_MASK, MT8365_RDMA0_RSZ0_SEL_IN_RDMA0 ++ }, { + DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0, + MT8365_DISP_REG_CONFIG_DISP_LVDS_SYS_CFG_00, + MT8365_LVDS_SYS_CFG_00_SEL_LVDS_PXL_CLK, MT8365_LVDS_SYS_CFG_00_SEL_LVDS_PXL_CLK +- }, +- { ++ }, { + DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0, + MT8365_DISP_REG_CONFIG_DISP_DPI0_SEL_IN, +- MT8365_DPI0_SEL_IN_RDMA1, MT8365_DPI0_SEL_IN_RDMA1 +- }, +- { ++ MT8365_DISP_MS_IN_OUT_MASK, MT8365_DPI0_SEL_IN_RDMA1 ++ }, { + DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0, + MT8365_DISP_REG_CONFIG_DISP_RDMA1_SOUT_SEL, +- MT8365_RDMA1_SOUT_DPI0, MT8365_RDMA1_SOUT_DPI0 ++ MT8365_DISP_MS_IN_OUT_MASK, MT8365_RDMA1_SOUT_DPI0 + }, + }; + +-- +2.39.5 + diff --git a/queue-6.14/soc-mediatek-mtk-mmsys-fix-mt8188-vdo1-dpi1-output-s.patch b/queue-6.14/soc-mediatek-mtk-mmsys-fix-mt8188-vdo1-dpi1-output-s.patch new file mode 100644 index 0000000000..7b733eb0b6 --- /dev/null +++ b/queue-6.14/soc-mediatek-mtk-mmsys-fix-mt8188-vdo1-dpi1-output-s.patch @@ -0,0 +1,43 @@ +From 337f09dcb6b3b3d299f601cd916f2554343f4f84 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 11:00:06 +0100 +Subject: soc: mediatek: mtk-mmsys: Fix MT8188 VDO1 DPI1 output selection + +From: AngeloGioacchino Del Regno + +[ Upstream commit 881d5094b138d002aab14922d41ec2058b9570c7 ] + +The VDO1_MERGE4 hardware (merge5 software component) should be +set to enable output to DPI1_SEL by setting BIT(2) but, despite +the intention being exactly that, this won't work because the +declared register mask is wrong as it is set as GENMASK(1, 0). + +Register MERGE4_MOUT_EN in VDO1 has four used bits [3, 0] so +fix the mask to reflect that. +That, in turn, allows the mmsys driver to actually set BIT(2) +in this register, fixing the MERGE4 output to DPI1 selection. + +Fixes: c0349314d5a0 ("soc: mediatek: Support MT8188 VDOSYS1 in mtk-mmsys") +Link: https://lore.kernel.org/r/20250212100012.33001-3-angelogioacchino.delregno@collabora.com +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + drivers/soc/mediatek/mt8188-mmsys.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/soc/mediatek/mt8188-mmsys.h b/drivers/soc/mediatek/mt8188-mmsys.h +index 6bebf1a69fc07..a1d63be0a73dc 100644 +--- a/drivers/soc/mediatek/mt8188-mmsys.h ++++ b/drivers/soc/mediatek/mt8188-mmsys.h +@@ -343,7 +343,7 @@ static const struct mtk_mmsys_routes mmsys_mt8188_vdo1_routing_table[] = { + MT8188_DISP_DPI1_SEL_IN_FROM_VPP_MERGE4_MOUT + }, { + DDP_COMPONENT_MERGE5, DDP_COMPONENT_DPI1, +- MT8188_VDO1_MERGE4_SOUT_SEL, GENMASK(1, 0), ++ MT8188_VDO1_MERGE4_SOUT_SEL, GENMASK(3, 0), + MT8188_MERGE4_SOUT_TO_DPI1_SEL + }, { + DDP_COMPONENT_MERGE5, DDP_COMPONENT_DP_INTF1, +-- +2.39.5 + diff --git a/queue-6.14/soundwire-slave-fix-an-of-node-reference-leak-in-sou.patch b/queue-6.14/soundwire-slave-fix-an-of-node-reference-leak-in-sou.patch new file mode 100644 index 0000000000..96e41d1436 --- /dev/null +++ b/queue-6.14/soundwire-slave-fix-an-of-node-reference-leak-in-sou.patch @@ -0,0 +1,40 @@ +From d9a327274d4d4ddba87fdb7c9f170dd65c482f11 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Dec 2024 12:48:44 +0900 +Subject: soundwire: slave: fix an OF node reference leak in soundwire slave + device + +From: Joe Hattori + +[ Upstream commit aac2f8363f773ae1f65aab140e06e2084ac6b787 ] + +When initializing a soundwire slave device, an OF node is stored to the +device with refcount incremented. However, the refcount is not +decremented in .release(), thus call of_node_put() in +sdw_slave_release(). + +Fixes: a2e484585ad3 ("soundwire: core: add device tree support for slave devices") +Signed-off-by: Joe Hattori +Reviewed-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20241205034844.2784964-1-joe@pf.is.s.u-tokyo.ac.jp +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/soundwire/slave.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/soundwire/slave.c b/drivers/soundwire/slave.c +index 4869b073b11c2..d2d99555ec5a5 100644 +--- a/drivers/soundwire/slave.c ++++ b/drivers/soundwire/slave.c +@@ -13,6 +13,7 @@ static void sdw_slave_release(struct device *dev) + { + struct sdw_slave *slave = dev_to_sdw_dev(dev); + ++ of_node_put(slave->dev.of_node); + mutex_destroy(&slave->sdw_dev_lock); + kfree(slave); + } +-- +2.39.5 + diff --git a/queue-6.14/soundwire-take-in-count-the-bandwidth-of-a-prepared-.patch b/queue-6.14/soundwire-take-in-count-the-bandwidth-of-a-prepared-.patch new file mode 100644 index 0000000000..25f2f91c55 --- /dev/null +++ b/queue-6.14/soundwire-take-in-count-the-bandwidth-of-a-prepared-.patch @@ -0,0 +1,46 @@ +From 456ce3d1ce56ee009c1a06ada3103458df90a241 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 15:36:53 +0800 +Subject: soundwire: take in count the bandwidth of a prepared stream + +From: Bard Liao + +[ Upstream commit 08ae0d61c3d79bb5d52ae30ad4fc12442e966a23 ] + +When a stream's state is marked as prepared, it is ready for +playback/capture. Therefore, we need to include the stream's bandwidth +when we calculate the required bandwidth of a bus. + +Fixes: 25befdf32aa40 ("soundwire: generic_bandwidth_allocation: count the bandwidth of active streams only") +Signed-off-by: Bard Liao +Link: https://github.com/thesofproject/linux/issues/5334 +Reviewed-by: Richard Fitzgerald +Reviewed-by: Ranjani Sridharan +Link: https://lore.kernel.org/r/20250310073653.56476-1-yung-chuan.liao@linux.intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/soundwire/generic_bandwidth_allocation.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/soundwire/generic_bandwidth_allocation.c b/drivers/soundwire/generic_bandwidth_allocation.c +index 59965f43c2fb0..f78a2a16581a7 100644 +--- a/drivers/soundwire/generic_bandwidth_allocation.c ++++ b/drivers/soundwire/generic_bandwidth_allocation.c +@@ -194,10 +194,11 @@ static int sdw_compute_group_params(struct sdw_bus *bus, + continue; + } else { + /* +- * Include runtimes with running (ENABLED state) and paused (DISABLED state) +- * streams ++ * Include runtimes with running (ENABLED/PREPARED state) and ++ * paused (DISABLED state) streams + */ + if (m_rt->stream->state != SDW_STREAM_ENABLED && ++ m_rt->stream->state != SDW_STREAM_PREPARED && + m_rt->stream->state != SDW_STREAM_DISABLED) + continue; + } +-- +2.39.5 + diff --git a/queue-6.14/spi-bcm2835-do-not-call-gpiod_put-on-invalid-descrip.patch b/queue-6.14/spi-bcm2835-do-not-call-gpiod_put-on-invalid-descrip.patch new file mode 100644 index 0000000000..cbef891a2c --- /dev/null +++ b/queue-6.14/spi-bcm2835-do-not-call-gpiod_put-on-invalid-descrip.patch @@ -0,0 +1,39 @@ +From 8e969a73a07d07d13f4a4cd9436d8ea712adf201 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Apr 2025 15:42:38 -0700 +Subject: spi: bcm2835: Do not call gpiod_put() on invalid descriptor + +From: Florian Fainelli + +[ Upstream commit d6691010523fe1016f482a1e1defcc6289eeea48 ] + +If we are unable to lookup the chip-select GPIO, the error path will +call bcm2835_spi_cleanup() which unconditionally calls gpiod_put() on +the cs->gpio variable which we just determined was invalid. + +Fixes: 21f252cd29f0 ("spi: bcm2835: reduce the abuse of the GPIO API") +Signed-off-by: Florian Fainelli +Link: https://patch.msgid.link/20250401224238.2854256-1-florian.fainelli@broadcom.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-bcm2835.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c +index 0d1aa65924846..06a81727d74dd 100644 +--- a/drivers/spi/spi-bcm2835.c ++++ b/drivers/spi/spi-bcm2835.c +@@ -1162,7 +1162,8 @@ static void bcm2835_spi_cleanup(struct spi_device *spi) + sizeof(u32), + DMA_TO_DEVICE); + +- gpiod_put(bs->cs_gpio); ++ if (!IS_ERR(bs->cs_gpio)) ++ gpiod_put(bs->cs_gpio); + spi_set_csgpiod(spi, 0, NULL); + + kfree(target); +-- +2.39.5 + diff --git a/queue-6.14/spi-bcm2835-restore-native-cs-probing-when-pinctrl-b.patch b/queue-6.14/spi-bcm2835-restore-native-cs-probing-when-pinctrl-b.patch new file mode 100644 index 0000000000..e3b9ca86ea --- /dev/null +++ b/queue-6.14/spi-bcm2835-restore-native-cs-probing-when-pinctrl-b.patch @@ -0,0 +1,76 @@ +From bb1c94f7f3806f05dec0046d27d142920a4ff61f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Apr 2025 16:36:03 -0700 +Subject: spi: bcm2835: Restore native CS probing when pinctrl-bcm2835 is + absent + +From: Florian Fainelli + +[ Upstream commit e19c1272c80a5ecce387c1b0c3b995f4edf9c525 ] + +The lookup table forces the use of the "pinctrl-bcm2835" GPIO chip +provider and essentially assumes that there is going to be such a +provider, and if not, we will fail to set-up the SPI device. + +While this is true on Raspberry Pi based systems (2835/36/37, 2711, +2712), this is not true on 7712/77122 Broadcom STB systems which use the +SPI driver, but not the GPIO driver. + +There used to be an early check: + + chip = gpiochip_find("pinctrl-bcm2835", chip_match_name); + if (!chip) + return 0; + +which would accomplish that nicely, bring something similar back by +checking for the compatible strings matched by the pinctrl-bcm2835.c +driver, if there is no Device Tree node matching those compatible +strings, then we won't find any GPIO provider registered by the +"pinctrl-bcm2835" driver. + +Fixes: 21f252cd29f0 ("spi: bcm2835: reduce the abuse of the GPIO API") +Signed-off-by: Florian Fainelli +Link: https://patch.msgid.link/20250401233603.2938955-1-florian.fainelli@broadcom.com +Acked-by: Bartosz Golaszewski +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-bcm2835.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c +index 06a81727d74dd..77de5a07639af 100644 +--- a/drivers/spi/spi-bcm2835.c ++++ b/drivers/spi/spi-bcm2835.c +@@ -1226,7 +1226,12 @@ static int bcm2835_spi_setup(struct spi_device *spi) + struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); + struct bcm2835_spidev *target = spi_get_ctldata(spi); + struct gpiod_lookup_table *lookup __free(kfree) = NULL; +- int ret; ++ const char *pinctrl_compats[] = { ++ "brcm,bcm2835-gpio", ++ "brcm,bcm2711-gpio", ++ "brcm,bcm7211-gpio", ++ }; ++ int ret, i; + u32 cs; + + if (!target) { +@@ -1291,6 +1296,14 @@ static int bcm2835_spi_setup(struct spi_device *spi) + goto err_cleanup; + } + ++ for (i = 0; i < ARRAY_SIZE(pinctrl_compats); i++) { ++ if (of_find_compatible_node(NULL, NULL, pinctrl_compats[i])) ++ break; ++ } ++ ++ if (i == ARRAY_SIZE(pinctrl_compats)) ++ return 0; ++ + /* + * TODO: The code below is a slightly better alternative to the utter + * abuse of the GPIO API that I found here before. It creates a +-- +2.39.5 + diff --git a/queue-6.14/spi-cadence-fix-out-of-bounds-array-access-in-cdns_m.patch b/queue-6.14/spi-cadence-fix-out-of-bounds-array-access-in-cdns_m.patch new file mode 100644 index 0000000000..7d47e7b104 --- /dev/null +++ b/queue-6.14/spi-cadence-fix-out-of-bounds-array-access-in-cdns_m.patch @@ -0,0 +1,49 @@ +From 2179f4325e554f6c2dd360dbf872510c0e60a185 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Mar 2025 08:33:32 -0700 +Subject: spi: cadence: Fix out-of-bounds array access in + cdns_mrvl_xspi_setup_clock() + +From: Josh Poimboeuf + +[ Upstream commit 7ba0847fa1c22e7801cebfe5f7b75aee4fae317e ] + +If requested_clk > 128, cdns_mrvl_xspi_setup_clock() iterates over the +entire cdns_mrvl_xspi_clk_div_list array without breaking out early, +causing 'i' to go beyond the array bounds. + +Fix that by stopping the loop when it gets to the last entry, clamping +the clock to the minimum 6.25 MHz. + +Fixes the following warning with an UBSAN kernel: + + vmlinux.o: warning: objtool: cdns_mrvl_xspi_setup_clock: unexpected end of section .text.cdns_mrvl_xspi_setup_clock + +Fixes: 26d34fdc4971 ("spi: cadence: Add clock configuration for Marvell xSPI overlay") +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202503282236.UhfRsF3B-lkp@intel.com/ +Link: https://lore.kernel.org/r/gs2ooxfkblnee6cc5yfcxh7nu4wvoqnuv4lrllkhccxgcac2jg@7snmwd73jkhs +Signed-off-by: Josh Poimboeuf +Link: https://patch.msgid.link/h6bef6wof6zpjfp3jbhrkigqsnykdfy6j4qmmvb6gsabhianhj@k57a7hwpa3bj +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-cadence-xspi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-cadence-xspi.c b/drivers/spi/spi-cadence-xspi.c +index aed98ab143346..6dcba0e0ddaa3 100644 +--- a/drivers/spi/spi-cadence-xspi.c ++++ b/drivers/spi/spi-cadence-xspi.c +@@ -432,7 +432,7 @@ static bool cdns_mrvl_xspi_setup_clock(struct cdns_xspi_dev *cdns_xspi, + u32 clk_reg; + bool update_clk = false; + +- while (i < ARRAY_SIZE(cdns_mrvl_xspi_clk_div_list)) { ++ while (i < (ARRAY_SIZE(cdns_mrvl_xspi_clk_div_list) - 1)) { + clk_val = MRVL_XSPI_CLOCK_DIVIDED( + cdns_mrvl_xspi_clk_div_list[i]); + if (clk_val <= requested_clk) +-- +2.39.5 + diff --git a/queue-6.14/spufs-fix-a-leak-in-spufs_create_context.patch b/queue-6.14/spufs-fix-a-leak-in-spufs_create_context.patch new file mode 100644 index 0000000000..e7b22d271b --- /dev/null +++ b/queue-6.14/spufs-fix-a-leak-in-spufs_create_context.patch @@ -0,0 +1,39 @@ +From 61c62a81da3f68150692440fe99a48e8af0d64a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 19:38:28 -0400 +Subject: spufs: fix a leak in spufs_create_context() + +From: Al Viro + +[ Upstream commit 0f5cce3fc55b08ee4da3372baccf4bcd36a98396 ] + +Leak fixes back in 2008 missed one case - if we are trying to set affinity +and spufs_mkdir() fails, we need to drop the reference to neighbor. + +Fixes: 58119068cb27 "[POWERPC] spufs: Fix memory leak on SPU affinity" +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/cell/spufs/inode.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c +index c566e7997f2c1..9f9e4b8716278 100644 +--- a/arch/powerpc/platforms/cell/spufs/inode.c ++++ b/arch/powerpc/platforms/cell/spufs/inode.c +@@ -460,8 +460,11 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, + } + + ret = spufs_mkdir(inode, dentry, flags, mode & 0777); +- if (ret) ++ if (ret) { ++ if (neighbor) ++ put_spu_context(neighbor); + goto out_aff_unlock; ++ } + + if (affinity) { + spufs_set_affinity(flags, SPUFS_I(d_inode(dentry))->i_ctx, +-- +2.39.5 + diff --git a/queue-6.14/spufs-fix-a-leak-on-spufs_new_file-failure.patch b/queue-6.14/spufs-fix-a-leak-on-spufs_new_file-failure.patch new file mode 100644 index 0000000000..408c62a0f4 --- /dev/null +++ b/queue-6.14/spufs-fix-a-leak-on-spufs_new_file-failure.patch @@ -0,0 +1,40 @@ +From d673f2c311897cde5d354cbb57928d175ed9b92e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 19:26:31 -0500 +Subject: spufs: fix a leak on spufs_new_file() failure + +From: Al Viro + +[ Upstream commit d1ca8698ca1332625d83ea0d753747be66f9906d ] + +It's called from spufs_fill_dir(), and caller of that will do +spufs_rmdir() in case of failure. That does remove everything +we'd managed to create, but... the problem dentry is still +negative. IOW, it needs to be explicitly dropped. + +Fixes: 3f51dd91c807 "[PATCH] spufs: fix spufs_fill_dir error path" +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/cell/spufs/inode.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c +index 70236d1df3d3e..793c005607cf0 100644 +--- a/arch/powerpc/platforms/cell/spufs/inode.c ++++ b/arch/powerpc/platforms/cell/spufs/inode.c +@@ -192,8 +192,10 @@ static int spufs_fill_dir(struct dentry *dir, + return -ENOMEM; + ret = spufs_new_file(dir->d_sb, dentry, files->ops, + files->mode & mode, files->size, ctx); +- if (ret) ++ if (ret) { ++ dput(dentry); + return ret; ++ } + files++; + } + return 0; +-- +2.39.5 + diff --git a/queue-6.14/spufs-fix-gang-directory-lifetimes.patch b/queue-6.14/spufs-fix-gang-directory-lifetimes.patch new file mode 100644 index 0000000000..e260c96d42 --- /dev/null +++ b/queue-6.14/spufs-fix-gang-directory-lifetimes.patch @@ -0,0 +1,195 @@ +From 6dc1c5f87051adc8cc7fcfbcef387da465a58fe2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 19:18:39 -0400 +Subject: spufs: fix gang directory lifetimes + +From: Al Viro + +[ Upstream commit c134deabf4784e155d360744d4a6a835b9de4dd4 ] + +prior to "[POWERPC] spufs: Fix gang destroy leaks" we used to have +a problem with gang lifetimes - creation of a gang returns opened +gang directory, which normally gets removed when that gets closed, +but if somebody has created a context belonging to that gang and +kept it alive until the gang got closed, removal failed and we +ended up with a leak. + +Unfortunately, it had been fixed the wrong way. Dentry of gang +directory was no longer pinned, and rmdir on close was gone. +One problem was that failure of open kept calling simple_rmdir() +as cleanup, which meant an unbalanced dput(). Another bug was +in the success case - gang creation incremented link count on +root directory, but that was no longer undone when gang got +destroyed. + +Fix consists of + * reverting the commit in question + * adding a counter to gang, protected by ->i_rwsem +of gang directory inode. + * having it set to 1 at creation time, dropped +in both spufs_dir_close() and spufs_gang_close() and bumped +in spufs_create_context(), provided that it's not 0. + * using simple_recursive_removal() to take the gang +directory out when counter reaches zero. + +Fixes: 877907d37da9 "[POWERPC] spufs: Fix gang destroy leaks" +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/cell/spufs/gang.c | 1 + + arch/powerpc/platforms/cell/spufs/inode.c | 54 +++++++++++++++++++---- + arch/powerpc/platforms/cell/spufs/spufs.h | 2 + + 3 files changed, 49 insertions(+), 8 deletions(-) + +diff --git a/arch/powerpc/platforms/cell/spufs/gang.c b/arch/powerpc/platforms/cell/spufs/gang.c +index 827d338deaf4c..2c2999de6bfa2 100644 +--- a/arch/powerpc/platforms/cell/spufs/gang.c ++++ b/arch/powerpc/platforms/cell/spufs/gang.c +@@ -25,6 +25,7 @@ struct spu_gang *alloc_spu_gang(void) + mutex_init(&gang->aff_mutex); + INIT_LIST_HEAD(&gang->list); + INIT_LIST_HEAD(&gang->aff_list_head); ++ gang->alive = 1; + + out: + return gang; +diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c +index 793c005607cf0..c566e7997f2c1 100644 +--- a/arch/powerpc/platforms/cell/spufs/inode.c ++++ b/arch/powerpc/platforms/cell/spufs/inode.c +@@ -201,6 +201,23 @@ static int spufs_fill_dir(struct dentry *dir, + return 0; + } + ++static void unuse_gang(struct dentry *dir) ++{ ++ struct inode *inode = dir->d_inode; ++ struct spu_gang *gang = SPUFS_I(inode)->i_gang; ++ ++ if (gang) { ++ bool dead; ++ ++ inode_lock(inode); // exclusion with spufs_create_context() ++ dead = !--gang->alive; ++ inode_unlock(inode); ++ ++ if (dead) ++ simple_recursive_removal(dir, NULL); ++ } ++} ++ + static int spufs_dir_close(struct inode *inode, struct file *file) + { + struct inode *parent; +@@ -215,6 +232,7 @@ static int spufs_dir_close(struct inode *inode, struct file *file) + inode_unlock(parent); + WARN_ON(ret); + ++ unuse_gang(dir->d_parent); + return dcache_dir_close(inode, file); + } + +@@ -407,7 +425,7 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, + { + int ret; + int affinity; +- struct spu_gang *gang; ++ struct spu_gang *gang = SPUFS_I(inode)->i_gang; + struct spu_context *neighbor; + struct path path = {.mnt = mnt, .dentry = dentry}; + +@@ -422,11 +440,15 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, + if ((flags & SPU_CREATE_ISOLATE) && !isolated_loader) + return -ENODEV; + +- gang = NULL; ++ if (gang) { ++ if (!gang->alive) ++ return -ENOENT; ++ gang->alive++; ++ } ++ + neighbor = NULL; + affinity = flags & (SPU_CREATE_AFFINITY_MEM | SPU_CREATE_AFFINITY_SPU); + if (affinity) { +- gang = SPUFS_I(inode)->i_gang; + if (!gang) + return -EINVAL; + mutex_lock(&gang->aff_mutex); +@@ -455,6 +477,8 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, + out_aff_unlock: + if (affinity) + mutex_unlock(&gang->aff_mutex); ++ if (ret && gang) ++ gang->alive--; // can't reach 0 + return ret; + } + +@@ -484,6 +508,7 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, umode_t mode) + inode->i_fop = &simple_dir_operations; + + d_instantiate(dentry, inode); ++ dget(dentry); + inc_nlink(dir); + inc_nlink(d_inode(dentry)); + return ret; +@@ -494,6 +519,21 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, umode_t mode) + return ret; + } + ++static int spufs_gang_close(struct inode *inode, struct file *file) ++{ ++ unuse_gang(file->f_path.dentry); ++ return dcache_dir_close(inode, file); ++} ++ ++static const struct file_operations spufs_gang_fops = { ++ .open = dcache_dir_open, ++ .release = spufs_gang_close, ++ .llseek = dcache_dir_lseek, ++ .read = generic_read_dir, ++ .iterate_shared = dcache_readdir, ++ .fsync = noop_fsync, ++}; ++ + static int spufs_gang_open(const struct path *path) + { + int ret; +@@ -513,7 +553,7 @@ static int spufs_gang_open(const struct path *path) + return PTR_ERR(filp); + } + +- filp->f_op = &simple_dir_operations; ++ filp->f_op = &spufs_gang_fops; + fd_install(ret, filp); + return ret; + } +@@ -528,10 +568,8 @@ static int spufs_create_gang(struct inode *inode, + ret = spufs_mkgang(inode, dentry, mode & 0777); + if (!ret) { + ret = spufs_gang_open(&path); +- if (ret < 0) { +- int err = simple_rmdir(inode, dentry); +- WARN_ON(err); +- } ++ if (ret < 0) ++ unuse_gang(dentry); + } + return ret; + } +diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h +index 84958487f696a..d33787c57c39a 100644 +--- a/arch/powerpc/platforms/cell/spufs/spufs.h ++++ b/arch/powerpc/platforms/cell/spufs/spufs.h +@@ -151,6 +151,8 @@ struct spu_gang { + int aff_flags; + struct spu *aff_ref_spu; + atomic_t aff_sched_count; ++ ++ int alive; + }; + + /* Flag bits for spu_gang aff_flags */ +-- +2.39.5 + diff --git a/queue-6.14/staging-gpib-add-missing-interface-entry-point.patch b/queue-6.14/staging-gpib-add-missing-interface-entry-point.patch new file mode 100644 index 0000000000..867496129f --- /dev/null +++ b/queue-6.14/staging-gpib-add-missing-interface-entry-point.patch @@ -0,0 +1,49 @@ +From 0b44ed6cb829054e42e9d6d2f404d01cef9d8a4b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 11:38:58 +0100 +Subject: staging: gpib: Add missing interface entry point + +From: Dave Penkler + +[ Upstream commit 2f548210a5a5d4cb5f20af39b684a9f6de58cd0e ] + +Declaring the driver entry points as static caused a warning +that the serial_poll_status function of the agilent_82350b driver +was unused. + +Add the entry point to the corresponding interface structure +initializations where it was missing. + +Fixes: 09a4655ee1eb ("staging: gpib: Add HP/Agilent/Keysight 8235xx PCI GPIB driver") +Signed-off-by: Dave Penkler +Reviewed-by: Dan Carpenter +Link: https://lore.kernel.org/r/20250122103859.25499-2-dpenkler@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/staging/gpib/agilent_82350b/agilent_82350b.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/staging/gpib/agilent_82350b/agilent_82350b.c b/drivers/staging/gpib/agilent_82350b/agilent_82350b.c +index 3f4f95b7fe34a..c62407077d37f 100644 +--- a/drivers/staging/gpib/agilent_82350b/agilent_82350b.c ++++ b/drivers/staging/gpib/agilent_82350b/agilent_82350b.c +@@ -848,6 +848,7 @@ static gpib_interface_t agilent_82350b_unaccel_interface = { + .primary_address = agilent_82350b_primary_address, + .secondary_address = agilent_82350b_secondary_address, + .serial_poll_response = agilent_82350b_serial_poll_response, ++ .serial_poll_status = agilent_82350b_serial_poll_status, + .t1_delay = agilent_82350b_t1_delay, + .return_to_local = agilent_82350b_return_to_local, + }; +@@ -875,6 +876,7 @@ static gpib_interface_t agilent_82350b_interface = { + .primary_address = agilent_82350b_primary_address, + .secondary_address = agilent_82350b_secondary_address, + .serial_poll_response = agilent_82350b_serial_poll_response, ++ .serial_poll_status = agilent_82350b_serial_poll_status, + .t1_delay = agilent_82350b_t1_delay, + .return_to_local = agilent_82350b_return_to_local, + }; +-- +2.39.5 + diff --git a/queue-6.14/staging-gpib-fix-cb7210-pcmcia-oops.patch b/queue-6.14/staging-gpib-fix-cb7210-pcmcia-oops.patch new file mode 100644 index 0000000000..cc47ee6b7f --- /dev/null +++ b/queue-6.14/staging-gpib-fix-cb7210-pcmcia-oops.patch @@ -0,0 +1,43 @@ +From de8c0eb0bf6dd048ead7270e9b169ab08d9c8d64 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 11:31:12 +0100 +Subject: staging: gpib: Fix cb7210 pcmcia Oops + +From: Dave Penkler + +[ Upstream commit c1baf6528bcfd6a86842093ff3f8ff8caf309c12 ] + +The pcmcia_driver struct was still only using the old .name +initialization in the drv field. This led to a NULL pointer +deref Oops in strcmp called from pcmcia_register_driver. + +Initialize the pcmcia_driver struct name field. + +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-lkp/202502131453.cb6d2e4a-lkp@intel.com +Fixes: e9dc69956d4d ("staging: gpib: Add Computer Boards GPIB driver") +Signed-off-by: Dave Penkler +Link: https://lore.kernel.org/r/20250213103112.4415-1-dpenkler@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/staging/gpib/cb7210/cb7210.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/gpib/cb7210/cb7210.c b/drivers/staging/gpib/cb7210/cb7210.c +index 4d22f647a453f..ab93061263bfe 100644 +--- a/drivers/staging/gpib/cb7210/cb7210.c ++++ b/drivers/staging/gpib/cb7210/cb7210.c +@@ -1342,8 +1342,8 @@ static struct pcmcia_device_id cb_pcmcia_ids[] = { + MODULE_DEVICE_TABLE(pcmcia, cb_pcmcia_ids); + + static struct pcmcia_driver cb_gpib_cs_driver = { ++ .name = "cb_gpib_cs", + .owner = THIS_MODULE, +- .drv = { .name = "cb_gpib_cs", }, + .id_table = cb_pcmcia_ids, + .probe = cb_gpib_probe, + .remove = cb_gpib_remove, +-- +2.39.5 + diff --git a/queue-6.14/staging-gpib-fix-pr_err-format-warning.patch b/queue-6.14/staging-gpib-fix-pr_err-format-warning.patch new file mode 100644 index 0000000000..12bcd07f55 --- /dev/null +++ b/queue-6.14/staging-gpib-fix-pr_err-format-warning.patch @@ -0,0 +1,45 @@ +From 88d4826eb47bf41daaa31ad3bb74617952a1f49e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 11:58:58 +0100 +Subject: staging: gpib: Fix pr_err format warning + +From: Dave Penkler + +[ Upstream commit 03ec050c437bb4e7c5d215bbeedaa93932f13b35 ] + +This patch fixes the following compile warning: + +drivers/staging/gpib/hp_82341/hp_82341.c: In function 'hp_82341_attach': +./include/linux/kern_levels.h:5:25: warning: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'u32' {aka 'unsigned int'} [-Wformat=] + +It was introduced in + +commit baf8855c9160 ("staging: gpib: fix address space mixup") + +but was not detected as the build of the driver depended on BROKEN. + +Fixes: baf8855c9160 ("staging: gpib: fix address space mixup") +Signed-off-by: Dave Penkler +Link: https://lore.kernel.org/r/20250124105900.27592-2-dpenkler@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/staging/gpib/hp_82341/hp_82341.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/gpib/hp_82341/hp_82341.c b/drivers/staging/gpib/hp_82341/hp_82341.c +index 0ddae295912fa..589c4fee1d562 100644 +--- a/drivers/staging/gpib/hp_82341/hp_82341.c ++++ b/drivers/staging/gpib/hp_82341/hp_82341.c +@@ -718,7 +718,7 @@ int hp_82341_attach(gpib_board_t *board, const gpib_board_config_t *config) + for (i = 0; i < hp_82341_num_io_regions; ++i) { + start_addr = iobase + i * hp_priv->io_region_offset; + if (!request_region(start_addr, hp_82341_region_iosize, "hp_82341")) { +- pr_err("hp_82341: failed to allocate io ports 0x%lx-0x%lx\n", ++ pr_err("hp_82341: failed to allocate io ports 0x%x-0x%x\n", + start_addr, + start_addr + hp_82341_region_iosize - 1); + return -EIO; +-- +2.39.5 + diff --git a/queue-6.14/staging-rtl8723bs-select-config_crypto_lib_aes.patch b/queue-6.14/staging-rtl8723bs-select-config_crypto_lib_aes.patch new file mode 100644 index 0000000000..46892a3e72 --- /dev/null +++ b/queue-6.14/staging-rtl8723bs-select-config_crypto_lib_aes.patch @@ -0,0 +1,44 @@ +From 308288efa4218c7346d2ca4f098450420e64ad41 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Feb 2025 19:36:17 +0000 +Subject: staging: rtl8723bs: select CONFIG_CRYPTO_LIB_AES +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: 谢致邦 (XIE Zhibang) + +[ Upstream commit b2a9a6a26b7e954297e51822e396572026480bad ] + +This fixes the following issue: +ERROR: modpost: "aes_expandkey" [drivers/staging/rtl8723bs/r8723bs.ko] +undefined! +ERROR: modpost: "aes_encrypt" [drivers/staging/rtl8723bs/r8723bs.ko] +undefined! + +Fixes: 7d40753d8820 ("staging: rtl8723bs: use in-kernel aes encryption in OMAC1 routines") +Fixes: 3d3a170f6d80 ("staging: rtl8723bs: use in-kernel aes encryption") +Signed-off-by: 谢致邦 (XIE Zhibang) +Reviewed-by: Hans de Goede +Link: https://lore.kernel.org/r/tencent_0BDDF3A721708D16A2E7C3DAFF0FEC79A105@qq.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/staging/rtl8723bs/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/staging/rtl8723bs/Kconfig b/drivers/staging/rtl8723bs/Kconfig +index 8d48c61961a6b..353e6ee2c1450 100644 +--- a/drivers/staging/rtl8723bs/Kconfig ++++ b/drivers/staging/rtl8723bs/Kconfig +@@ -4,6 +4,7 @@ config RTL8723BS + depends on WLAN && MMC && CFG80211 + depends on m + select CRYPTO ++ select CRYPTO_LIB_AES + select CRYPTO_LIB_ARC4 + help + This option enables support for RTL8723BS SDIO drivers, such as +-- +2.39.5 + diff --git a/queue-6.14/staging-vchiq_arm-fix-possible-npr-of-keep-alive-thr.patch b/queue-6.14/staging-vchiq_arm-fix-possible-npr-of-keep-alive-thr.patch new file mode 100644 index 0000000000..1270ea4a28 --- /dev/null +++ b/queue-6.14/staging-vchiq_arm-fix-possible-npr-of-keep-alive-thr.patch @@ -0,0 +1,39 @@ +From 3468fdebebf0a7eeae5db2957519e99e09c0b723 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Mar 2025 13:50:11 +0100 +Subject: staging: vchiq_arm: Fix possible NPR of keep-alive thread + +From: Stefan Wahren + +[ Upstream commit 3db89bc6d973e2bcaa852f6409c98c228f39a926 ] + +In case vchiq_platform_conn_state_changed() is never called or fails before +driver removal, ka_thread won't be a valid pointer to a task_struct. So +do the necessary checks before calling kthread_stop to avoid a crash. + +Fixes: 863a756aaf49 ("staging: vc04_services: vchiq_core: Stop kthreads on vchiq module unload") +Signed-off-by: Stefan Wahren +Link: https://lore.kernel.org/r/20250309125014.37166-3-wahrenst@gmx.net +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +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 e2e80e90b555b..d3b7d1227d7d6 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -1422,7 +1422,8 @@ static void vchiq_remove(struct platform_device *pdev) + kthread_stop(mgmt->state.slot_handler_thread); + + arm_state = vchiq_platform_get_arm_state(&mgmt->state); +- kthread_stop(arm_state->ka_thread); ++ if (!IS_ERR_OR_NULL(arm_state->ka_thread)) ++ kthread_stop(arm_state->ka_thread); + } + + static struct platform_driver vchiq_driver = { +-- +2.39.5 + diff --git a/queue-6.14/staging-vchiq_arm-register-debugfs-after-cdev.patch b/queue-6.14/staging-vchiq_arm-register-debugfs-after-cdev.patch new file mode 100644 index 0000000000..dedf6a7ffd --- /dev/null +++ b/queue-6.14/staging-vchiq_arm-register-debugfs-after-cdev.patch @@ -0,0 +1,48 @@ +From f338f3283d47f25510eff930e75e804b277fe191 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Mar 2025 13:50:10 +0100 +Subject: staging: vchiq_arm: Register debugfs after cdev + +From: Stefan Wahren + +[ Upstream commit 63f4dbb196db60a8536ba3d1b835d597a83f6cbb ] + +The commit 2a4d15a4ae98 ("staging: vchiq: Refactor vchiq cdev code") +moved the debugfs directory creation before vchiq character device +registration. In case the latter fails, the debugfs directory won't +be cleaned up. + +Fixes: 2a4d15a4ae98 ("staging: vchiq: Refactor vchiq cdev code") +Signed-off-by: Stefan Wahren +Link: https://lore.kernel.org/r/20250309125014.37166-2-wahrenst@gmx.net +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 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 a4e83e5d619bc..e2e80e90b555b 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -1386,8 +1386,6 @@ static int vchiq_probe(struct platform_device *pdev) + return ret; + } + +- vchiq_debugfs_init(&mgmt->state); +- + dev_dbg(&pdev->dev, "arm: platform initialised - version %d (min %d)\n", + VCHIQ_VERSION, VCHIQ_VERSION_MIN); + +@@ -1401,6 +1399,8 @@ static int vchiq_probe(struct platform_device *pdev) + return ret; + } + ++ vchiq_debugfs_init(&mgmt->state); ++ + bcm2835_audio = vchiq_device_register(&pdev->dev, "bcm2835-audio"); + bcm2835_camera = vchiq_device_register(&pdev->dev, "bcm2835-camera"); + +-- +2.39.5 + diff --git a/queue-6.14/staging-vchiq_arm-stop-kthreads-if-vchiq-cdev-regist.patch b/queue-6.14/staging-vchiq_arm-stop-kthreads-if-vchiq-cdev-regist.patch new file mode 100644 index 0000000000..26c4b2906e --- /dev/null +++ b/queue-6.14/staging-vchiq_arm-stop-kthreads-if-vchiq-cdev-regist.patch @@ -0,0 +1,79 @@ +From e9519c498dcb8a9bdd9fe1b33d56ba4134513f3d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Mar 2025 13:50:12 +0100 +Subject: staging: vchiq_arm: Stop kthreads if vchiq cdev register fails + +From: Stefan Wahren + +[ Upstream commit cfb320d990919836b49bd090c6c232c6c4d90b41 ] + +In case the vchiq character device cannot be registered during probe, +all kthreads needs to be stopped to avoid resource leaks. + +Fixes: 863a756aaf49 ("staging: vc04_services: vchiq_core: Stop kthreads on vchiq module unload") +Signed-off-by: Stefan Wahren +Link: https://lore.kernel.org/r/20250309125014.37166-4-wahrenst@gmx.net +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + .../interface/vchiq_arm/vchiq_arm.c | 25 ++++++++++++------- + 1 file changed, 16 insertions(+), 9 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 d3b7d1227d7d6..0c7ea2d0ee85e 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -308,6 +308,20 @@ static struct vchiq_arm_state *vchiq_platform_get_arm_state(struct vchiq_state * + return (struct vchiq_arm_state *)state->platform_state; + } + ++static void ++vchiq_platform_uninit(struct vchiq_drv_mgmt *mgmt) ++{ ++ struct vchiq_arm_state *arm_state; ++ ++ kthread_stop(mgmt->state.sync_thread); ++ kthread_stop(mgmt->state.recycle_thread); ++ kthread_stop(mgmt->state.slot_handler_thread); ++ ++ arm_state = vchiq_platform_get_arm_state(&mgmt->state); ++ if (!IS_ERR_OR_NULL(arm_state->ka_thread)) ++ kthread_stop(arm_state->ka_thread); ++} ++ + void vchiq_dump_platform_state(struct seq_file *f) + { + seq_puts(f, " Platform: 2835 (VC master)\n"); +@@ -1396,6 +1410,7 @@ static int vchiq_probe(struct platform_device *pdev) + ret = vchiq_register_chrdev(&pdev->dev); + if (ret) { + dev_err(&pdev->dev, "arm: Failed to initialize vchiq cdev\n"); ++ vchiq_platform_uninit(mgmt); + return ret; + } + +@@ -1410,20 +1425,12 @@ static int vchiq_probe(struct platform_device *pdev) + static void vchiq_remove(struct platform_device *pdev) + { + struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(&pdev->dev); +- struct vchiq_arm_state *arm_state; + + vchiq_device_unregister(bcm2835_audio); + vchiq_device_unregister(bcm2835_camera); + vchiq_debugfs_deinit(); + vchiq_deregister_chrdev(); +- +- kthread_stop(mgmt->state.sync_thread); +- kthread_stop(mgmt->state.recycle_thread); +- kthread_stop(mgmt->state.slot_handler_thread); +- +- arm_state = vchiq_platform_get_arm_state(&mgmt->state); +- if (!IS_ERR_OR_NULL(arm_state->ka_thread)) +- kthread_stop(arm_state->ka_thread); ++ vchiq_platform_uninit(mgmt); + } + + static struct platform_driver vchiq_driver = { +-- +2.39.5 + diff --git a/queue-6.14/thermal-core-remove-duplicate-struct-declaration.patch b/queue-6.14/thermal-core-remove-duplicate-struct-declaration.patch new file mode 100644 index 0000000000..867e2a34ee --- /dev/null +++ b/queue-6.14/thermal-core-remove-duplicate-struct-declaration.patch @@ -0,0 +1,37 @@ +From ac01b360172bdc26b975e93b6715cf0aa9571d33 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 16:14:36 +0800 +Subject: thermal: core: Remove duplicate struct declaration + +From: xueqin Luo + +[ Upstream commit 9e6ec8cf64e2973f0ec74f09023988cabd218426 ] + +The struct thermal_zone_device is already declared on line 32, so the +duplicate declaration has been removed. + +Fixes: b1ae92dcfa8e ("thermal: core: Make struct thermal_zone_device definition internal") +Signed-off-by: xueqin Luo +Link: https://lore.kernel.org/r/20250206081436.51785-1-luoxueqin@kylinos.cn +Signed-off-by: Daniel Lezcano +Signed-off-by: Sasha Levin +--- + include/linux/thermal.h | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/include/linux/thermal.h b/include/linux/thermal.h +index 69f9bedd0ee88..0b5ed68210807 100644 +--- a/include/linux/thermal.h ++++ b/include/linux/thermal.h +@@ -86,8 +86,6 @@ struct thermal_trip { + #define THERMAL_TRIP_PRIV_TO_INT(_val_) (uintptr_t)(_val_) + #define THERMAL_INT_TO_TRIP_PRIV(_val_) (void *)(uintptr_t)(_val_) + +-struct thermal_zone_device; +- + struct cooling_spec { + unsigned long upper; /* Highest cooling state */ + unsigned long lower; /* Lowest cooling state */ +-- +2.39.5 + diff --git a/queue-6.14/thermal-int340x-add-null-check-for-adev.patch b/queue-6.14/thermal-int340x-add-null-check-for-adev.patch new file mode 100644 index 0000000000..d620abd3c7 --- /dev/null +++ b/queue-6.14/thermal-int340x-add-null-check-for-adev.patch @@ -0,0 +1,50 @@ +From 34c9849f7670046d8b667eb69f6091e7a3d7d2da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 23:36:11 -0500 +Subject: thermal: int340x: Add NULL check for adev +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Chenyuan Yang + +[ Upstream commit 2542a3f70e563a9e70e7ded314286535a3321bdb ] + +Not all devices have an ACPI companion fwnode, so adev might be NULL. +This is similar to the commit cd2fd6eab480 +("platform/x86: int3472: Check for adev == NULL"). + +Add a check for adev not being set and return -ENODEV in that case to +avoid a possible NULL pointer deref in int3402_thermal_probe(). + +Note, under the same directory, int3400_thermal_probe() has such a +check. + +Fixes: 77e337c6e23e ("Thermal: introduce INT3402 thermal driver") +Signed-off-by: Chenyuan Yang +Acked-by: Uwe Kleine-König +Link: https://patch.msgid.link/20250313043611.1212116-1-chenyuan0y@gmail.com +[ rjw: Subject edit, added Fixes: ] +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/thermal/intel/int340x_thermal/int3402_thermal.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/thermal/intel/int340x_thermal/int3402_thermal.c b/drivers/thermal/intel/int340x_thermal/int3402_thermal.c +index 543b03960e992..57b90005888a3 100644 +--- a/drivers/thermal/intel/int340x_thermal/int3402_thermal.c ++++ b/drivers/thermal/intel/int340x_thermal/int3402_thermal.c +@@ -45,6 +45,9 @@ static int int3402_thermal_probe(struct platform_device *pdev) + struct int3402_thermal_data *d; + int ret; + ++ if (!adev) ++ return -ENODEV; ++ + if (!acpi_has_method(adev->handle, "_TMP")) + return -ENODEV; + +-- +2.39.5 + diff --git a/queue-6.14/timekeeping-fix-possible-inconsistencies-in-_coarse-.patch b/queue-6.14/timekeeping-fix-possible-inconsistencies-in-_coarse-.patch new file mode 100644 index 0000000000..7a2676966e --- /dev/null +++ b/queue-6.14/timekeeping-fix-possible-inconsistencies-in-_coarse-.patch @@ -0,0 +1,219 @@ +From cb6ae383145403c779d9dd8dc6fdfc2bcdc42d32 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Mar 2025 13:03:00 -0700 +Subject: timekeeping: Fix possible inconsistencies in _COARSE clockids + +From: John Stultz + +[ Upstream commit 757b000f7b936edf79311ab0971fe465bbda75ea ] + +Lei Chen raised an issue with CLOCK_MONOTONIC_COARSE seeing time +inconsistencies. + +Lei tracked down that this was being caused by the adjustment + + tk->tkr_mono.xtime_nsec -= offset; + +which is made to compensate for the unaccumulated cycles in offset when the +multiplicator is adjusted forward, so that the non-_COARSE clockids don't +see inconsistencies. + +However, the _COARSE clockid getter functions use the adjusted xtime_nsec +value directly and do not compensate the negative offset via the +clocksource delta multiplied with the new multiplicator. In that case the +caller can observe time going backwards in consecutive calls. + +By design, this negative adjustment should be fine, because the logic run +from timekeeping_adjust() is done after it accumulated approximately + + multiplicator * interval_cycles + +into xtime_nsec. The accumulated value is always larger then the + + mult_adj * offset + +value, which is subtracted from xtime_nsec. Both operations are done +together under the tk_core.lock, so the net change to xtime_nsec is always +always be positive. + +However, do_adjtimex() calls into timekeeping_advance() as well, to to +apply the NTP frequency adjustment immediately. In this case, +timekeeping_advance() does not return early when the offset is smaller then +interval_cycles. In that case there is no time accumulated into +xtime_nsec. But the subsequent call into timekeeping_adjust(), which +modifies the multiplicator, subtracts from xtime_nsec to correct +for the new multiplicator. + +Here because there was no accumulation, xtime_nsec becomes smaller than +before, which opens a window up to the next accumulation, where the _COARSE +clockid getters, which don't compensate for the offset, can observe the +inconsistency. + +To fix this, rework the timekeeping_advance() logic so that when invoked +from do_adjtimex(), the time is immediately forwarded to accumulate also +the sub-interval portion into xtime. That means the remaining offset +becomes zero and the subsequent multiplier adjustment therefore does not +modify xtime_nsec. + +There is another related inconsistency. If xtime is forwarded due to the +instantaneous multiplier adjustment, the NTP error, which was accumulated +with the previous setting, becomes meaningless. + +Therefore clear the NTP error as well, after forwarding the clock for the +instantaneous multiplier update. + +Fixes: da15cfdae033 ("time: Introduce CLOCK_REALTIME_COARSE") +Reported-by: Lei Chen +Signed-off-by: John Stultz +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/all/20250320200306.1712599-1-jstultz@google.com +Closes: https://lore.kernel.org/lkml/20250310030004.3705801-1-lei.chen@smartx.com/ +Signed-off-by: Sasha Levin +--- + kernel/time/timekeeping.c | 94 ++++++++++++++++++++++++++++----------- + 1 file changed, 69 insertions(+), 25 deletions(-) + +diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c +index 1e67d076f1955..929846b8b45ab 100644 +--- a/kernel/time/timekeeping.c ++++ b/kernel/time/timekeeping.c +@@ -682,20 +682,19 @@ static void timekeeping_update_from_shadow(struct tk_data *tkd, unsigned int act + } + + /** +- * timekeeping_forward_now - update clock to the current time ++ * timekeeping_forward - update clock to given cycle now value + * @tk: Pointer to the timekeeper to update ++ * @cycle_now: Current clocksource read value + * + * Forward the current clock to update its state since the last call to + * update_wall_time(). This is useful before significant clock changes, + * as it avoids having to deal with this time offset explicitly. + */ +-static void timekeeping_forward_now(struct timekeeper *tk) ++static void timekeeping_forward(struct timekeeper *tk, u64 cycle_now) + { +- u64 cycle_now, delta; ++ u64 delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last, tk->tkr_mono.mask, ++ tk->tkr_mono.clock->max_raw_delta); + +- cycle_now = tk_clock_read(&tk->tkr_mono); +- delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last, tk->tkr_mono.mask, +- tk->tkr_mono.clock->max_raw_delta); + tk->tkr_mono.cycle_last = cycle_now; + tk->tkr_raw.cycle_last = cycle_now; + +@@ -710,6 +709,21 @@ static void timekeeping_forward_now(struct timekeeper *tk) + } + } + ++/** ++ * timekeeping_forward_now - update clock to the current time ++ * @tk: Pointer to the timekeeper to update ++ * ++ * Forward the current clock to update its state since the last call to ++ * update_wall_time(). This is useful before significant clock changes, ++ * as it avoids having to deal with this time offset explicitly. ++ */ ++static void timekeeping_forward_now(struct timekeeper *tk) ++{ ++ u64 cycle_now = tk_clock_read(&tk->tkr_mono); ++ ++ timekeeping_forward(tk, cycle_now); ++} ++ + /** + * ktime_get_real_ts64 - Returns the time of day in a timespec64. + * @ts: pointer to the timespec to be set +@@ -2151,6 +2165,54 @@ static u64 logarithmic_accumulation(struct timekeeper *tk, u64 offset, + return offset; + } + ++static u64 timekeeping_accumulate(struct timekeeper *tk, u64 offset, ++ enum timekeeping_adv_mode mode, ++ unsigned int *clock_set) ++{ ++ int shift = 0, maxshift; ++ ++ /* ++ * TK_ADV_FREQ indicates that adjtimex(2) directly set the ++ * frequency or the tick length. ++ * ++ * Accumulate the offset, so that the new multiplier starts from ++ * now. This is required as otherwise for offsets, which are ++ * smaller than tk::cycle_interval, timekeeping_adjust() could set ++ * xtime_nsec backwards, which subsequently causes time going ++ * backwards in the coarse time getters. But even for the case ++ * where offset is greater than tk::cycle_interval the periodic ++ * accumulation does not have much value. ++ * ++ * Also reset tk::ntp_error as it does not make sense to keep the ++ * old accumulated error around in this case. ++ */ ++ if (mode == TK_ADV_FREQ) { ++ timekeeping_forward(tk, tk->tkr_mono.cycle_last + offset); ++ tk->ntp_error = 0; ++ return 0; ++ } ++ ++ /* ++ * With NO_HZ we may have to accumulate many cycle_intervals ++ * (think "ticks") worth of time at once. To do this efficiently, ++ * we calculate the largest doubling multiple of cycle_intervals ++ * that is smaller than the offset. We then accumulate that ++ * chunk in one go, and then try to consume the next smaller ++ * doubled multiple. ++ */ ++ shift = ilog2(offset) - ilog2(tk->cycle_interval); ++ shift = max(0, shift); ++ /* Bound shift to one less than what overflows tick_length */ ++ maxshift = (64 - (ilog2(ntp_tick_length()) + 1)) - 1; ++ shift = min(shift, maxshift); ++ while (offset >= tk->cycle_interval) { ++ offset = logarithmic_accumulation(tk, offset, shift, clock_set); ++ if (offset < tk->cycle_interval << shift) ++ shift--; ++ } ++ return offset; ++} ++ + /* + * timekeeping_advance - Updates the timekeeper to the current time and + * current NTP tick length +@@ -2160,7 +2222,6 @@ static bool timekeeping_advance(enum timekeeping_adv_mode mode) + struct timekeeper *tk = &tk_core.shadow_timekeeper; + struct timekeeper *real_tk = &tk_core.timekeeper; + unsigned int clock_set = 0; +- int shift = 0, maxshift; + u64 offset; + + guard(raw_spinlock_irqsave)(&tk_core.lock); +@@ -2177,24 +2238,7 @@ static bool timekeeping_advance(enum timekeeping_adv_mode mode) + if (offset < real_tk->cycle_interval && mode == TK_ADV_TICK) + return false; + +- /* +- * With NO_HZ we may have to accumulate many cycle_intervals +- * (think "ticks") worth of time at once. To do this efficiently, +- * we calculate the largest doubling multiple of cycle_intervals +- * that is smaller than the offset. We then accumulate that +- * chunk in one go, and then try to consume the next smaller +- * doubled multiple. +- */ +- shift = ilog2(offset) - ilog2(tk->cycle_interval); +- shift = max(0, shift); +- /* Bound shift to one less than what overflows tick_length */ +- maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1; +- shift = min(shift, maxshift); +- while (offset >= tk->cycle_interval) { +- offset = logarithmic_accumulation(tk, offset, shift, &clock_set); +- if (offset < tk->cycle_interval< +Date: Tue, 4 Mar 2025 15:22:28 +0100 +Subject: tools/rv: Keep user LDFLAGS in build + +From: Tomas Glozar + +[ Upstream commit e82c78afa3d48f6512570e7d39258cd68e7bae0a ] + +rv, unlike rtla and perf, drops LDFLAGS supplied by the user and honors +only EXTRA_LDFLAGS. This is inconsistent with both perf and rtla and +can lead to all kinds of unexpected behavior. + +For example, on Fedora and RHEL, it causes rv to be build without +PIE, unlike the aforementioned perf and rtla: + +$ file /usr/bin/{rv,rtla,perf} +/usr/bin/rv: ELF 64-bit LSB executable, ... +/usr/bin/rtla: ELF 64-bit LSB pie executable, ... +/usr/bin/perf: ELF 64-bit LSB pie executable, ... + +Keep both LDFLAGS and EXTRA_LDFLAGS for the build. + +Cc: John Kacur +Cc: Luis Goncalves +Cc: Gabriele Monaco +Link: https://lore.kernel.org/20250304142228.767658-1-tglozar@redhat.com +Fixes: 012e4e77df73 ("tools/verification: Use tools/build makefiles on rv") +Signed-off-by: Tomas Glozar +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + tools/verification/rv/Makefile.rv | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/verification/rv/Makefile.rv b/tools/verification/rv/Makefile.rv +index 161baa29eb86c..2497fb96c83d2 100644 +--- a/tools/verification/rv/Makefile.rv ++++ b/tools/verification/rv/Makefile.rv +@@ -27,7 +27,7 @@ endif + + INCLUDE := -Iinclude/ + CFLAGS := -g -DVERSION=\"$(VERSION)\" $(FOPTS) $(WOPTS) $(EXTRA_CFLAGS) $(INCLUDE) +-LDFLAGS := -ggdb $(EXTRA_LDFLAGS) ++LDFLAGS := -ggdb $(LDFLAGS) $(EXTRA_LDFLAGS) + + INSTALL := install + MKDIR := mkdir +-- +2.39.5 + diff --git a/queue-6.14/tools-x86-fix-linux-unaligned.h-include-path-in-lib-.patch b/queue-6.14/tools-x86-fix-linux-unaligned.h-include-path-in-lib-.patch new file mode 100644 index 0000000000..c8e6b1d1b9 --- /dev/null +++ b/queue-6.14/tools-x86-fix-linux-unaligned.h-include-path-in-lib-.patch @@ -0,0 +1,40 @@ +From dbf31150669296d59072e7f1ce19979dba760b6e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 11:36:00 -0800 +Subject: tools/x86: Fix linux/unaligned.h include path in lib/insn.c + +From: Ian Rogers + +[ Upstream commit fad07a5c0f07ad0884e1cb4362fe28c083b5b811 ] + +tools/arch/x86/include/linux doesn't exist but building is working by +virtue of a -I. Building using bazel this fails. Use angle brackets to +include unaligned.h so there isn't an invalid relative include. + +Fixes: 5f60d5f6bbc1 ("move asm/unaligned.h to linux/unaligned.h") +Signed-off-by: Ian Rogers +Acked-by: Josh Poimboeuf +Cc: Al Viro +Link: https://lore.kernel.org/r/20250225193600.90037-1-irogers@google.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/arch/x86/lib/insn.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/arch/x86/lib/insn.c b/tools/arch/x86/lib/insn.c +index ab5cdc3337dac..e91d4c4e1c162 100644 +--- a/tools/arch/x86/lib/insn.c ++++ b/tools/arch/x86/lib/insn.c +@@ -13,7 +13,7 @@ + #endif + #include "../include/asm/inat.h" /* __ignore_sync_check__ */ + #include "../include/asm/insn.h" /* __ignore_sync_check__ */ +-#include "../include/linux/unaligned.h" /* __ignore_sync_check__ */ ++#include /* __ignore_sync_check__ */ + + #include + #include +-- +2.39.5 + diff --git a/queue-6.14/tracing-fix-declare_trace_condition.patch b/queue-6.14/tracing-fix-declare_trace_condition.patch new file mode 100644 index 0000000000..6113df16ac --- /dev/null +++ b/queue-6.14/tracing-fix-declare_trace_condition.patch @@ -0,0 +1,68 @@ +From fe78bc87aa35f40b6e00a7c7d9ec3f0a0138ff42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 13:31:06 +0100 +Subject: tracing: Fix DECLARE_TRACE_CONDITION + +From: Gabriele Monaco + +[ Upstream commit 486df3466daf7b185f534a7408fa6f9dbb16dbeb ] + +Commit 287050d39026 ("tracing: Add TRACE_EVENT_CONDITIONAL()") adds +macros to define conditional trace events (TRACE_EVENT_CONDITIONAL) and +tracepoints (DECLARE_TRACE_CONDITION), but sets up functionality for +direct use only for the former. + +Add preprocessor bits in define_trace.h to allow usage of +DECLARE_TRACE_CONDITION just like DECLARE_TRACE. + +Cc: Mathieu Desnoyers +Cc: Frederic Weisbecker +Cc: Ingo Molnar +Cc: Peter Zijlstra +Cc: Juri Lelli +Link: https://lore.kernel.org/20250218123121.253551-2-gmonaco@redhat.com +Fixes: 287050d39026 ("tracing: Add TRACE_EVENT_CONDITIONAL()") +Link: https://lore.kernel.org/linux-trace-kernel/20250128111926.303093-1-gmonaco@redhat.com +Reviewed-by: Masami Hiramatsu (Google) +Signed-off-by: Gabriele Monaco +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + include/trace/define_trace.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/include/trace/define_trace.h b/include/trace/define_trace.h +index e1c1079f8c8db..ed52d0506c69f 100644 +--- a/include/trace/define_trace.h ++++ b/include/trace/define_trace.h +@@ -76,6 +76,10 @@ + #define DECLARE_TRACE(name, proto, args) \ + DEFINE_TRACE(name, PARAMS(proto), PARAMS(args)) + ++#undef DECLARE_TRACE_CONDITION ++#define DECLARE_TRACE_CONDITION(name, proto, args, cond) \ ++ DEFINE_TRACE(name, PARAMS(proto), PARAMS(args)) ++ + /* If requested, create helpers for calling these tracepoints from Rust. */ + #ifdef CREATE_RUST_TRACE_POINTS + #undef DEFINE_RUST_DO_TRACE +@@ -108,6 +112,8 @@ + /* Make all open coded DECLARE_TRACE nops */ + #undef DECLARE_TRACE + #define DECLARE_TRACE(name, proto, args) ++#undef DECLARE_TRACE_CONDITION ++#define DECLARE_TRACE_CONDITION(name, proto, args, cond) + + #ifdef TRACEPOINTS_ENABLED + #include +@@ -129,6 +135,7 @@ + #undef DEFINE_EVENT_CONDITION + #undef TRACE_HEADER_MULTI_READ + #undef DECLARE_TRACE ++#undef DECLARE_TRACE_CONDITION + + /* Only undef what we defined in this file */ + #ifdef UNDEF_TRACE_INCLUDE_FILE +-- +2.39.5 + diff --git a/queue-6.14/tty-n_tty-use-uint-for-space-returned-by-tty_write_r.patch b/queue-6.14/tty-n_tty-use-uint-for-space-returned-by-tty_write_r.patch new file mode 100644 index 0000000000..9d27a69368 --- /dev/null +++ b/queue-6.14/tty-n_tty-use-uint-for-space-returned-by-tty_write_r.patch @@ -0,0 +1,85 @@ +From 3fdbc0e5b910331099e0fe19f6baafa19f16c4f6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 08:00:20 +0100 +Subject: tty: n_tty: use uint for space returned by tty_write_room() + +From: Jiri Slaby (SUSE) + +[ Upstream commit d97aa066678bd1e2951ee93db9690835dfe57ab6 ] + +tty_write_room() returns an "unsigned int". So in case some insane +driver (like my tty test driver) returns (legitimate) UINT_MAX from its +tty_operations::write_room(), n_tty is confused on several places. + +For example, in process_output_block(), the result of tty_write_room() +is stored into (signed) "int". So this UINT_MAX suddenly becomes -1. And +that is extended to ssize_t and returned from process_output_block(). +This causes a write() to such a node to receive -EPERM (which is -1). + +Fix that by using proper "unsigned int" and proper "== 0" test. And +return 0 constant directly in that "if", so that it is immediately clear +what is returned ("space" equals to 0 at that point). + +Similarly for process_output() and __process_echoes(). + +Note this does not fix any in-tree driver as of now. + +If you want "Fixes: something", it would be commit 03b3b1a2405c ("tty: +make tty_operations::write_room return uint"). I intentionally do not +mark this patch by a real tag below. + +Signed-off-by: Jiri Slaby (SUSE) +Link: https://lore.kernel.org/r/20250317070046.24386-6-jirislaby@kernel.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/n_tty.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c +index 5e9ca4376d686..94fa981081fdb 100644 +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -486,7 +486,8 @@ static int do_output_char(u8 c, struct tty_struct *tty, int space) + static int process_output(u8 c, struct tty_struct *tty) + { + struct n_tty_data *ldata = tty->disc_data; +- int space, retval; ++ unsigned int space; ++ int retval; + + mutex_lock(&ldata->output_lock); + +@@ -522,16 +523,16 @@ static ssize_t process_output_block(struct tty_struct *tty, + const u8 *buf, unsigned int nr) + { + struct n_tty_data *ldata = tty->disc_data; +- int space; +- int i; ++ unsigned int space; ++ int i; + const u8 *cp; + + mutex_lock(&ldata->output_lock); + + space = tty_write_room(tty); +- if (space <= 0) { ++ if (space == 0) { + mutex_unlock(&ldata->output_lock); +- return space; ++ return 0; + } + if (nr > space) + nr = space; +@@ -696,7 +697,7 @@ static int n_tty_process_echo_ops(struct tty_struct *tty, size_t *tail, + static size_t __process_echoes(struct tty_struct *tty) + { + struct n_tty_data *ldata = tty->disc_data; +- int space, old_space; ++ unsigned int space, old_space; + size_t tail; + u8 c; + +-- +2.39.5 + diff --git a/queue-6.14/tunnels-accept-packet_host-in-skb_tunnel_check_pmtu.patch b/queue-6.14/tunnels-accept-packet_host-in-skb_tunnel_check_pmtu.patch new file mode 100644 index 0000000000..1d3a569e3c --- /dev/null +++ b/queue-6.14/tunnels-accept-packet_host-in-skb_tunnel_check_pmtu.patch @@ -0,0 +1,83 @@ +From 76beeead62dad30cc36b8a21be779fb021b4539f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 29 Mar 2025 01:33:44 +0100 +Subject: tunnels: Accept PACKET_HOST in skb_tunnel_check_pmtu(). + +From: Guillaume Nault + +[ Upstream commit 8930424777e43257f5bf6f0f0f53defd0d30415c ] + +Because skb_tunnel_check_pmtu() doesn't handle PACKET_HOST packets, +commit 30a92c9e3d6b ("openvswitch: Set the skbuff pkt_type for proper +pmtud support.") forced skb->pkt_type to PACKET_OUTGOING for +openvswitch packets that are sent using the OVS_ACTION_ATTR_OUTPUT +action. This allowed such packets to invoke the +iptunnel_pmtud_check_icmp() or iptunnel_pmtud_check_icmpv6() helpers +and thus trigger PMTU update on the input device. + +However, this also broke other parts of PMTU discovery. Since these +packets don't have the PACKET_HOST type anymore, they won't trigger the +sending of ICMP Fragmentation Needed or Packet Too Big messages to +remote hosts when oversized (see the skb_in->pkt_type condition in +__icmp_send() for example). + +These two skb->pkt_type checks are therefore incompatible as one +requires skb->pkt_type to be PACKET_HOST, while the other requires it +to be anything but PACKET_HOST. + +It makes sense to not trigger ICMP messages for non-PACKET_HOST packets +as these messages should be generated only for incoming l2-unicast +packets. However there doesn't seem to be any reason for +skb_tunnel_check_pmtu() to ignore PACKET_HOST packets. + +Allow both cases to work by allowing skb_tunnel_check_pmtu() to work on +PACKET_HOST packets and not overriding skb->pkt_type in openvswitch +anymore. + +Fixes: 30a92c9e3d6b ("openvswitch: Set the skbuff pkt_type for proper pmtud support.") +Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets") +Signed-off-by: Guillaume Nault +Reviewed-by: Stefano Brivio +Reviewed-by: Aaron Conole +Tested-by: Aaron Conole +Link: https://patch.msgid.link/eac941652b86fddf8909df9b3bf0d97bc9444793.1743208264.git.gnault@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/ip_tunnel_core.c | 2 +- + net/openvswitch/actions.c | 6 ------ + 2 files changed, 1 insertion(+), 7 deletions(-) + +diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c +index a3676155be78b..364ea798511ea 100644 +--- a/net/ipv4/ip_tunnel_core.c ++++ b/net/ipv4/ip_tunnel_core.c +@@ -416,7 +416,7 @@ int skb_tunnel_check_pmtu(struct sk_buff *skb, struct dst_entry *encap_dst, + + skb_dst_update_pmtu_no_confirm(skb, mtu); + +- if (!reply || skb->pkt_type == PACKET_HOST) ++ if (!reply) + return 0; + + if (skb->protocol == htons(ETH_P_IP)) +diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c +index 704c858cf2093..61fea7baae5d5 100644 +--- a/net/openvswitch/actions.c ++++ b/net/openvswitch/actions.c +@@ -947,12 +947,6 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port, + pskb_trim(skb, ovs_mac_header_len(key)); + } + +- /* Need to set the pkt_type to involve the routing layer. The +- * packet movement through the OVS datapath doesn't generally +- * use routing, but this is needed for tunnel cases. +- */ +- skb->pkt_type = PACKET_OUTGOING; +- + if (likely(!mru || + (skb->len <= mru + vport->dev->hard_header_len))) { + ovs_vport_send(vport, skb, ovs_key_mac_proto(key)); +-- +2.39.5 + diff --git a/queue-6.14/ublk-make-sure-ubq-canceling-is-set-when-queue-is-fr.patch b/queue-6.14/ublk-make-sure-ubq-canceling-is-set-when-queue-is-fr.patch new file mode 100644 index 0000000000..68d72ac6f6 --- /dev/null +++ b/queue-6.14/ublk-make-sure-ubq-canceling-is-set-when-queue-is-fr.patch @@ -0,0 +1,97 @@ +From 96a654dd9bb5a688f20c7122a897c3b91f780bb2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Mar 2025 17:51:10 +0800 +Subject: ublk: make sure ubq->canceling is set when queue is frozen + +From: Ming Lei + +[ Upstream commit 8741d0737921ec1c03cf59aebf4d01400c2b461a ] + +Now ublk driver depends on `ubq->canceling` for deciding if the request +can be dispatched via uring_cmd & io_uring_cmd_complete_in_task(). + +Once ubq->canceling is set, the uring_cmd can be done via ublk_cancel_cmd() +and io_uring_cmd_done(). + +So set ubq->canceling when queue is frozen, this way makes sure that the +flag can be observed from ublk_queue_rq() reliably, and avoids +use-after-free on uring_cmd. + +Fixes: 216c8f5ef0f2 ("ublk: replace monitor with cancelable uring_cmd") +Signed-off-by: Ming Lei +Link: https://lore.kernel.org/r/20250327095123.179113-2-ming.lei@redhat.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/block/ublk_drv.c | 39 +++++++++++++++++++++++++++++---------- + 1 file changed, 29 insertions(+), 10 deletions(-) + +diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c +index ca9a67b5b537a..b7adfaddc3abb 100644 +--- a/drivers/block/ublk_drv.c ++++ b/drivers/block/ublk_drv.c +@@ -1452,17 +1452,27 @@ static void ublk_abort_queue(struct ublk_device *ub, struct ublk_queue *ubq) + } + } + ++/* Must be called when queue is frozen */ ++static bool ublk_mark_queue_canceling(struct ublk_queue *ubq) ++{ ++ bool canceled; ++ ++ spin_lock(&ubq->cancel_lock); ++ canceled = ubq->canceling; ++ if (!canceled) ++ ubq->canceling = true; ++ spin_unlock(&ubq->cancel_lock); ++ ++ return canceled; ++} ++ + static bool ublk_abort_requests(struct ublk_device *ub, struct ublk_queue *ubq) + { ++ bool was_canceled = ubq->canceling; + struct gendisk *disk; + +- spin_lock(&ubq->cancel_lock); +- if (ubq->canceling) { +- spin_unlock(&ubq->cancel_lock); ++ if (was_canceled) + return false; +- } +- ubq->canceling = true; +- spin_unlock(&ubq->cancel_lock); + + spin_lock(&ub->lock); + disk = ub->ub_disk; +@@ -1474,14 +1484,23 @@ static bool ublk_abort_requests(struct ublk_device *ub, struct ublk_queue *ubq) + if (!disk) + return false; + +- /* Now we are serialized with ublk_queue_rq() */ ++ /* ++ * Now we are serialized with ublk_queue_rq() ++ * ++ * Make sure that ubq->canceling is set when queue is frozen, ++ * because ublk_queue_rq() has to rely on this flag for avoiding to ++ * touch completed uring_cmd ++ */ + blk_mq_quiesce_queue(disk->queue); +- /* abort queue is for making forward progress */ +- ublk_abort_queue(ub, ubq); ++ was_canceled = ublk_mark_queue_canceling(ubq); ++ if (!was_canceled) { ++ /* abort queue is for making forward progress */ ++ ublk_abort_queue(ub, ubq); ++ } + blk_mq_unquiesce_queue(disk->queue); + put_device(disk_to_dev(disk)); + +- return true; ++ return !was_canceled; + } + + static void ublk_cancel_cmd(struct ublk_queue *ubq, struct ublk_io *io, +-- +2.39.5 + diff --git a/queue-6.14/ucsi_ccg-don-t-show-failed-to-get-fw-build-informati.patch b/queue-6.14/ucsi_ccg-don-t-show-failed-to-get-fw-build-informati.patch new file mode 100644 index 0000000000..cf3aa1f5a5 --- /dev/null +++ b/queue-6.14/ucsi_ccg-don-t-show-failed-to-get-fw-build-informati.patch @@ -0,0 +1,47 @@ +From d2b2da74e868bb8ccdede6be6e82146999923fc3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 23:40:03 -0600 +Subject: ucsi_ccg: Don't show failed to get FW build information error + +From: Mario Limonciello + +[ Upstream commit c16006852732dc4fe37c14b81f9b4458df05b832 ] + +The error `failed to get FW build information` is added for what looks +to be for misdetection of the device property firmware-name. + +If the property is missing (such as on non-nvidia HW) this error shows up. +Move the error into the scope of the property parser for "firmware-name" +to avoid showing errors on systems without the firmware-name property. + +Fixes: 5c9ae5a87573d ("usb: typec: ucsi: ccg: add firmware flashing support") +Signed-off-by: Mario Limonciello +Reviewed-by: Heikki Krogerus +Link: https://lore.kernel.org/r/20250221054137.1631765-2-superm1@kernel.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/typec/ucsi/ucsi_ccg.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c +index 4b1668733a4be..511dd1b224ae5 100644 +--- a/drivers/usb/typec/ucsi/ucsi_ccg.c ++++ b/drivers/usb/typec/ucsi/ucsi_ccg.c +@@ -1433,11 +1433,10 @@ static int ucsi_ccg_probe(struct i2c_client *client) + uc->fw_build = CCG_FW_BUILD_NVIDIA_TEGRA; + else if (!strcmp(fw_name, "nvidia,gpu")) + uc->fw_build = CCG_FW_BUILD_NVIDIA; ++ if (!uc->fw_build) ++ dev_err(uc->dev, "failed to get FW build information\n"); + } + +- if (!uc->fw_build) +- dev_err(uc->dev, "failed to get FW build information\n"); +- + /* reset ccg device and initialize ucsi */ + status = ucsi_ccg_init(uc); + if (status < 0) { +-- +2.39.5 + diff --git a/queue-6.14/udp-fix-memory-accounting-leak.patch b/queue-6.14/udp-fix-memory-accounting-leak.patch new file mode 100644 index 0000000000..e4fd9451ed --- /dev/null +++ b/queue-6.14/udp-fix-memory-accounting-leak.patch @@ -0,0 +1,171 @@ +From 602205618f23aecfbd0b8b789546cb53e80f2d5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Apr 2025 11:44:43 -0700 +Subject: udp: Fix memory accounting leak. + +From: Kuniyuki Iwashima + +[ Upstream commit df207de9d9e7a4d92f8567e2c539d9c8c12fd99d ] + +Matt Dowling reported a weird UDP memory usage issue. + +Under normal operation, the UDP memory usage reported in /proc/net/sockstat +remains close to zero. However, it occasionally spiked to 524,288 pages +and never dropped. Moreover, the value doubled when the application was +terminated. Finally, it caused intermittent packet drops. + +We can reproduce the issue with the script below [0]: + + 1. /proc/net/sockstat reports 0 pages + + # cat /proc/net/sockstat | grep UDP: + UDP: inuse 1 mem 0 + + 2. Run the script till the report reaches 524,288 + + # python3 test.py & sleep 5 + # cat /proc/net/sockstat | grep UDP: + UDP: inuse 3 mem 524288 <-- (INT_MAX + 1) >> PAGE_SHIFT + + 3. Kill the socket and confirm the number never drops + + # pkill python3 && sleep 5 + # cat /proc/net/sockstat | grep UDP: + UDP: inuse 1 mem 524288 + + 4. (necessary since v6.0) Trigger proto_memory_pcpu_drain() + + # python3 test.py & sleep 1 && pkill python3 + + 5. The number doubles + + # cat /proc/net/sockstat | grep UDP: + UDP: inuse 1 mem 1048577 + +The application set INT_MAX to SO_RCVBUF, which triggered an integer +overflow in udp_rmem_release(). + +When a socket is close()d, udp_destruct_common() purges its receive +queue and sums up skb->truesize in the queue. This total is calculated +and stored in a local unsigned integer variable. + +The total size is then passed to udp_rmem_release() to adjust memory +accounting. However, because the function takes a signed integer +argument, the total size can wrap around, causing an overflow. + +Then, the released amount is calculated as follows: + + 1) Add size to sk->sk_forward_alloc. + 2) Round down sk->sk_forward_alloc to the nearest lower multiple of + PAGE_SIZE and assign it to amount. + 3) Subtract amount from sk->sk_forward_alloc. + 4) Pass amount >> PAGE_SHIFT to __sk_mem_reduce_allocated(). + +When the issue occurred, the total in udp_destruct_common() was 2147484480 +(INT_MAX + 833), which was cast to -2147482816 in udp_rmem_release(). + +At 1) sk->sk_forward_alloc is changed from 3264 to -2147479552, and +2) sets -2147479552 to amount. 3) reverts the wraparound, so we don't +see a warning in inet_sock_destruct(). However, udp_memory_allocated +ends up doubling at 4). + +Since commit 3cd3399dd7a8 ("net: implement per-cpu reserves for +memory_allocated"), memory usage no longer doubles immediately after +a socket is close()d because __sk_mem_reduce_allocated() caches the +amount in udp_memory_per_cpu_fw_alloc. However, the next time a UDP +socket receives a packet, the subtraction takes effect, causing UDP +memory usage to double. + +This issue makes further memory allocation fail once the socket's +sk->sk_rmem_alloc exceeds net.ipv4.udp_rmem_min, resulting in packet +drops. + +To prevent this issue, let's use unsigned int for the calculation and +call sk_forward_alloc_add() only once for the small delta. + +Note that first_packet_length() also potentially has the same problem. + +[0]: +from socket import * + +SO_RCVBUFFORCE = 33 +INT_MAX = (2 ** 31) - 1 + +s = socket(AF_INET, SOCK_DGRAM) +s.bind(('', 0)) +s.setsockopt(SOL_SOCKET, SO_RCVBUFFORCE, INT_MAX) + +c = socket(AF_INET, SOCK_DGRAM) +c.connect(s.getsockname()) + +data = b'a' * 100 + +while True: + c.send(data) + +Fixes: f970bd9e3a06 ("udp: implement memory accounting helpers") +Reported-by: Matt Dowling +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20250401184501.67377-3-kuniyu@amazon.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/udp.c | 16 +++++++--------- + 1 file changed, 7 insertions(+), 9 deletions(-) + +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index 31f7bfec23590..3fe85ecec2361 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1626,12 +1626,12 @@ static bool udp_skb_has_head_state(struct sk_buff *skb) + } + + /* fully reclaim rmem/fwd memory allocated for skb */ +-static void udp_rmem_release(struct sock *sk, int size, int partial, +- bool rx_queue_lock_held) ++static void udp_rmem_release(struct sock *sk, unsigned int size, ++ int partial, bool rx_queue_lock_held) + { + struct udp_sock *up = udp_sk(sk); + struct sk_buff_head *sk_queue; +- int amt; ++ unsigned int amt; + + if (likely(partial)) { + up->forward_deficit += size; +@@ -1651,10 +1651,8 @@ static void udp_rmem_release(struct sock *sk, int size, int partial, + if (!rx_queue_lock_held) + spin_lock(&sk_queue->lock); + +- +- sk_forward_alloc_add(sk, size); +- amt = (sk->sk_forward_alloc - partial) & ~(PAGE_SIZE - 1); +- sk_forward_alloc_add(sk, -amt); ++ amt = (size + sk->sk_forward_alloc - partial) & ~(PAGE_SIZE - 1); ++ sk_forward_alloc_add(sk, size - amt); + + if (amt) + __sk_mem_reduce_allocated(sk, amt >> PAGE_SHIFT); +@@ -1844,7 +1842,7 @@ EXPORT_SYMBOL_GPL(skb_consume_udp); + + static struct sk_buff *__first_packet_length(struct sock *sk, + struct sk_buff_head *rcvq, +- int *total) ++ unsigned int *total) + { + struct sk_buff *skb; + +@@ -1877,8 +1875,8 @@ static int first_packet_length(struct sock *sk) + { + struct sk_buff_head *rcvq = &udp_sk(sk)->reader_queue; + struct sk_buff_head *sk_queue = &sk->sk_receive_queue; ++ unsigned int total = 0; + struct sk_buff *skb; +- int total = 0; + int res; + + spin_lock_bh(&rcvq->lock); +-- +2.39.5 + diff --git a/queue-6.14/udp-fix-multiple-wraparounds-of-sk-sk_rmem_alloc.patch b/queue-6.14/udp-fix-multiple-wraparounds-of-sk-sk_rmem_alloc.patch new file mode 100644 index 0000000000..d2a9fdb318 --- /dev/null +++ b/queue-6.14/udp-fix-multiple-wraparounds-of-sk-sk_rmem_alloc.patch @@ -0,0 +1,138 @@ +From 937ff7aa0714714869c32d0e329eab955964e562 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Apr 2025 11:44:42 -0700 +Subject: udp: Fix multiple wraparounds of sk->sk_rmem_alloc. + +From: Kuniyuki Iwashima + +[ Upstream commit 5a465a0da13ee9fbd7d3cd0b2893309b0fe4b7e3 ] + +__udp_enqueue_schedule_skb() has the following condition: + + if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf) + goto drop; + +sk->sk_rcvbuf is initialised by net.core.rmem_default and later can +be configured by SO_RCVBUF, which is limited by net.core.rmem_max, +or SO_RCVBUFFORCE. + +If we set INT_MAX to sk->sk_rcvbuf, the condition is always false +as sk->sk_rmem_alloc is also signed int. + +Then, the size of the incoming skb is added to sk->sk_rmem_alloc +unconditionally. + +This results in integer overflow (possibly multiple times) on +sk->sk_rmem_alloc and allows a single socket to have skb up to +net.core.udp_mem[1]. + +For example, if we set a large value to udp_mem[1] and INT_MAX to +sk->sk_rcvbuf and flood packets to the socket, we can see multiple +overflows: + + # cat /proc/net/sockstat | grep UDP: + UDP: inuse 3 mem 7956736 <-- (7956736 << 12) bytes > INT_MAX * 15 + ^- PAGE_SHIFT + # ss -uam + State Recv-Q ... + UNCONN -1757018048 ... <-- flipping the sign repeatedly + skmem:(r2537949248,rb2147483646,t0,tb212992,f1984,w0,o0,bl0,d0) + +Previously, we had a boundary check for INT_MAX, which was removed by +commit 6a1f12dd85a8 ("udp: relax atomic operation on sk->sk_rmem_alloc"). + +A complete fix would be to revert it and cap the right operand by +INT_MAX: + + rmem = atomic_add_return(size, &sk->sk_rmem_alloc); + if (rmem > min(size + (unsigned int)sk->sk_rcvbuf, INT_MAX)) + goto uncharge_drop; + +but we do not want to add the expensive atomic_add_return() back just +for the corner case. + +Casting rmem to unsigned int prevents multiple wraparounds, but we still +allow a single wraparound. + + # cat /proc/net/sockstat | grep UDP: + UDP: inuse 3 mem 524288 <-- (INT_MAX + 1) >> 12 + + # ss -uam + State Recv-Q ... + UNCONN -2147482816 ... <-- INT_MAX + 831 bytes + skmem:(r2147484480,rb2147483646,t0,tb212992,f3264,w0,o0,bl0,d14468947) + +So, let's define rmem and rcvbuf as unsigned int and check skb->truesize +only when rcvbuf is large enough to lower the overflow possibility. + +Note that we still have a small chance to see overflow if multiple skbs +to the same socket are processed on different core at the same time and +each size does not exceed the limit but the total size does. + +Note also that we must ignore skb->truesize for a small buffer as +explained in commit 363dc73acacb ("udp: be less conservative with +sock rmem accounting"). + +Fixes: 6a1f12dd85a8 ("udp: relax atomic operation on sk->sk_rmem_alloc") +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20250401184501.67377-2-kuniyu@amazon.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/udp.c | 26 +++++++++++++++++--------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index a9bb9ce5438ea..31f7bfec23590 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1726,17 +1726,25 @@ static int udp_rmem_schedule(struct sock *sk, int size) + int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb) + { + struct sk_buff_head *list = &sk->sk_receive_queue; +- int rmem, err = -ENOMEM; ++ unsigned int rmem, rcvbuf; + spinlock_t *busy = NULL; +- int size, rcvbuf; ++ int size, err = -ENOMEM; + +- /* Immediately drop when the receive queue is full. +- * Always allow at least one packet. +- */ + rmem = atomic_read(&sk->sk_rmem_alloc); + rcvbuf = READ_ONCE(sk->sk_rcvbuf); +- if (rmem > rcvbuf) +- goto drop; ++ size = skb->truesize; ++ ++ /* Immediately drop when the receive queue is full. ++ * Cast to unsigned int performs the boundary check for INT_MAX. ++ */ ++ if (rmem + size > rcvbuf) { ++ if (rcvbuf > INT_MAX >> 1) ++ goto drop; ++ ++ /* Always allow at least one packet for small buffer. */ ++ if (rmem > rcvbuf) ++ goto drop; ++ } + + /* Under mem pressure, it might be helpful to help udp_recvmsg() + * having linear skbs : +@@ -1746,10 +1754,10 @@ int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb) + */ + if (rmem > (rcvbuf >> 1)) { + skb_condense(skb); +- ++ size = skb->truesize; + busy = busylock_acquire(sk); + } +- size = skb->truesize; ++ + udp_set_dev_scratch(skb); + + atomic_add(size, &sk->sk_rmem_alloc); +-- +2.39.5 + diff --git a/queue-6.14/um-hostfs-avoid-issues-on-inode-number-reuse-by-host.patch b/queue-6.14/um-hostfs-avoid-issues-on-inode-number-reuse-by-host.patch new file mode 100644 index 0000000000..7dcfdbbd78 --- /dev/null +++ b/queue-6.14/um-hostfs-avoid-issues-on-inode-number-reuse-by-host.patch @@ -0,0 +1,172 @@ +From bec083e14d8780df43f6f350e0aed23135a9879f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 10:28:22 +0100 +Subject: um: hostfs: avoid issues on inode number reuse by host +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Benjamin Berg + +[ Upstream commit 0bc754d1e31f40f4a343b692096d9e092ccc0370 ] + +Some file systems (e.g. ext4) may reuse inode numbers once the inode is +not in use anymore. Usually hostfs will keep an FD open for each inode, +but this is not always the case. In the case of sockets, this cannot +even be done properly. + +As such, the following sequence of events was possible: + * application creates and deletes a socket + * hostfs creates/deletes the socket on the host + * inode is still in the hostfs cache + * hostfs creates a new file + * ext4 on the outside reuses the inode number + * hostfs finds the socket inode for the newly created file + * application receives -ENXIO when opening the file + +As mentioned, this can only happen if the deleted file is a special file +that is never opened on the host (i.e. no .open fop). + +As such, to prevent issues, it is sufficient to check that the inode +has the expected type. That said, also add a check for the inode birth +time, just to be on the safe side. + +Fixes: 74ce793bcbde ("hostfs: Fix ephemeral inodes") +Signed-off-by: Benjamin Berg +Reviewed-by: Mickaël Salaün +Tested-by: Mickaël Salaün +Link: https://patch.msgid.link/20250214092822.1241575-1-benjamin@sipsolutions.net +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + fs/hostfs/hostfs.h | 2 +- + fs/hostfs/hostfs_kern.c | 7 ++++- + fs/hostfs/hostfs_user.c | 59 ++++++++++++++++++++++++----------------- + 3 files changed, 41 insertions(+), 27 deletions(-) + +diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h +index 8b39c15c408cc..15b2f094d36ef 100644 +--- a/fs/hostfs/hostfs.h ++++ b/fs/hostfs/hostfs.h +@@ -60,7 +60,7 @@ struct hostfs_stat { + unsigned int uid; + unsigned int gid; + unsigned long long size; +- struct hostfs_timespec atime, mtime, ctime; ++ struct hostfs_timespec atime, mtime, ctime, btime; + unsigned int blksize; + unsigned long long blocks; + struct { +diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c +index e0741e468956d..e6e2472357282 100644 +--- a/fs/hostfs/hostfs_kern.c ++++ b/fs/hostfs/hostfs_kern.c +@@ -33,6 +33,7 @@ struct hostfs_inode_info { + struct inode vfs_inode; + struct mutex open_mutex; + dev_t dev; ++ struct hostfs_timespec btime; + }; + + static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode) +@@ -547,6 +548,7 @@ static int hostfs_inode_set(struct inode *ino, void *data) + } + + HOSTFS_I(ino)->dev = dev; ++ HOSTFS_I(ino)->btime = st->btime; + ino->i_ino = st->ino; + ino->i_mode = st->mode; + return hostfs_inode_update(ino, st); +@@ -557,7 +559,10 @@ static int hostfs_inode_test(struct inode *inode, void *data) + const struct hostfs_stat *st = data; + dev_t dev = MKDEV(st->dev.maj, st->dev.min); + +- return inode->i_ino == st->ino && HOSTFS_I(inode)->dev == dev; ++ return inode->i_ino == st->ino && HOSTFS_I(inode)->dev == dev && ++ (inode->i_mode & S_IFMT) == (st->mode & S_IFMT) && ++ HOSTFS_I(inode)->btime.tv_sec == st->btime.tv_sec && ++ HOSTFS_I(inode)->btime.tv_nsec == st->btime.tv_nsec; + } + + static struct inode *hostfs_iget(struct super_block *sb, char *name) +diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c +index 97e9c40a94488..3bcd9f35e70b2 100644 +--- a/fs/hostfs/hostfs_user.c ++++ b/fs/hostfs/hostfs_user.c +@@ -18,39 +18,48 @@ + #include "hostfs.h" + #include + +-static void stat64_to_hostfs(const struct stat64 *buf, struct hostfs_stat *p) ++static void statx_to_hostfs(const struct statx *buf, struct hostfs_stat *p) + { +- p->ino = buf->st_ino; +- p->mode = buf->st_mode; +- p->nlink = buf->st_nlink; +- p->uid = buf->st_uid; +- p->gid = buf->st_gid; +- p->size = buf->st_size; +- p->atime.tv_sec = buf->st_atime; +- p->atime.tv_nsec = 0; +- p->ctime.tv_sec = buf->st_ctime; +- p->ctime.tv_nsec = 0; +- p->mtime.tv_sec = buf->st_mtime; +- p->mtime.tv_nsec = 0; +- p->blksize = buf->st_blksize; +- p->blocks = buf->st_blocks; +- p->rdev.maj = os_major(buf->st_rdev); +- p->rdev.min = os_minor(buf->st_rdev); +- p->dev.maj = os_major(buf->st_dev); +- p->dev.min = os_minor(buf->st_dev); ++ p->ino = buf->stx_ino; ++ p->mode = buf->stx_mode; ++ p->nlink = buf->stx_nlink; ++ p->uid = buf->stx_uid; ++ p->gid = buf->stx_gid; ++ p->size = buf->stx_size; ++ p->atime.tv_sec = buf->stx_atime.tv_sec; ++ p->atime.tv_nsec = buf->stx_atime.tv_nsec; ++ p->ctime.tv_sec = buf->stx_ctime.tv_sec; ++ p->ctime.tv_nsec = buf->stx_ctime.tv_nsec; ++ p->mtime.tv_sec = buf->stx_mtime.tv_sec; ++ p->mtime.tv_nsec = buf->stx_mtime.tv_nsec; ++ if (buf->stx_mask & STATX_BTIME) { ++ p->btime.tv_sec = buf->stx_btime.tv_sec; ++ p->btime.tv_nsec = buf->stx_btime.tv_nsec; ++ } else { ++ memset(&p->btime, 0, sizeof(p->btime)); ++ } ++ p->blksize = buf->stx_blksize; ++ p->blocks = buf->stx_blocks; ++ p->rdev.maj = buf->stx_rdev_major; ++ p->rdev.min = buf->stx_rdev_minor; ++ p->dev.maj = buf->stx_dev_major; ++ p->dev.min = buf->stx_dev_minor; + } + + int stat_file(const char *path, struct hostfs_stat *p, int fd) + { +- struct stat64 buf; ++ struct statx buf; ++ int flags = AT_SYMLINK_NOFOLLOW; + + if (fd >= 0) { +- if (fstat64(fd, &buf) < 0) +- return -errno; +- } else if (lstat64(path, &buf) < 0) { +- return -errno; ++ flags |= AT_EMPTY_PATH; ++ path = ""; + } +- stat64_to_hostfs(&buf, p); ++ ++ if ((statx(fd, path, flags, STATX_BASIC_STATS | STATX_BTIME, &buf)) < 0) ++ return -errno; ++ ++ statx_to_hostfs(&buf, p); + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/um-pass-the-correct-rust-target-and-options-with-gcc.patch b/queue-6.14/um-pass-the-correct-rust-target-and-options-with-gcc.patch new file mode 100644 index 0000000000..fc8dffd46e --- /dev/null +++ b/queue-6.14/um-pass-the-correct-rust-target-and-options-with-gcc.patch @@ -0,0 +1,57 @@ +From f8d8be0357d81998d9b7d5e358819bb09ffd7a34 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 18:53:51 +0800 +Subject: um: Pass the correct Rust target and options with gcc + +From: David Gow + +[ Upstream commit 5550187c4c21740942c32a9ae56f9f472a104cb4 ] + +In order to work around some issues with disabling SSE on older versions +of gcc (compilation would fail upon seeing a function declaration +containing a float, even if it was never called or defined), the +corresponding CFLAGS and RUSTFLAGS were only set when using clang. + +However, this led to two problems: +- Newer gcc versions also wouldn't get the correct flags, despite not + having the bug. +- The RUSTFLAGS for setting the rust target definition were not set, + despite being unrelated. This works by chance for x86_64, as the + built-in default target is close enough, but not for 32-bit x86. + +Move the target definition outside the conditional block, and update the +condition to take into account the gcc version. + +Fixes: a3046a618a28 ("um: Only disable SSE on clang to work around old GCC bugs") +Signed-off-by: David Gow +Link: https://patch.msgid.link/20250210105353.2238769-2-davidgow@google.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + arch/x86/Makefile.um | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/Makefile.um b/arch/x86/Makefile.um +index a46b1397ad01c..c86cbd9cbba38 100644 +--- a/arch/x86/Makefile.um ++++ b/arch/x86/Makefile.um +@@ -7,12 +7,13 @@ core-y += arch/x86/crypto/ + # GCC versions < 11. See: + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99652 + # +-ifeq ($(CONFIG_CC_IS_CLANG),y) +-KBUILD_CFLAGS += -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx +-KBUILD_RUSTFLAGS += --target=$(objtree)/scripts/target.json ++ifeq ($(call gcc-min-version, 110000)$(CONFIG_CC_IS_CLANG),y) ++KBUILD_CFLAGS += -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx + KBUILD_RUSTFLAGS += -Ctarget-feature=-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2 + endif + ++KBUILD_RUSTFLAGS += --target=$(objtree)/scripts/target.json ++ + ifeq ($(CONFIG_X86_32),y) + START := 0x8048000 + +-- +2.39.5 + diff --git a/queue-6.14/um-remove-copy_from_kernel_nofault_allowed.patch b/queue-6.14/um-remove-copy_from_kernel_nofault_allowed.patch new file mode 100644 index 0000000000..eb881e7737 --- /dev/null +++ b/queue-6.14/um-remove-copy_from_kernel_nofault_allowed.patch @@ -0,0 +1,144 @@ +From 0924236862703fa63f527aeceb8ea374f1b81d25 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 17:09:26 +0100 +Subject: um: remove copy_from_kernel_nofault_allowed + +From: Benjamin Berg + +[ Upstream commit 84a6fc378471fbeaf48f8604566a5a33a3d63c18 ] + +There is no need to override the default version of this function +anymore as UML now has proper _nofault memory access functions. + +Doing this also fixes the fact that the implementation was incorrect as +using mincore() will incorrectly flag pages as inaccessible if they were +swapped out by the host. + +Fixes: f75b1b1bedfb ("um: Implement probe_kernel_read()") +Signed-off-by: Benjamin Berg +Link: https://patch.msgid.link/20250210160926.420133-3-benjamin@sipsolutions.net +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + arch/um/include/shared/os.h | 1 - + arch/um/kernel/Makefile | 2 +- + arch/um/kernel/maccess.c | 19 -------------- + arch/um/os-Linux/process.c | 51 ------------------------------------- + 4 files changed, 1 insertion(+), 72 deletions(-) + delete mode 100644 arch/um/kernel/maccess.c + +diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h +index 5babad8c5f75e..bc02767f06397 100644 +--- a/arch/um/include/shared/os.h ++++ b/arch/um/include/shared/os.h +@@ -213,7 +213,6 @@ extern int os_protect_memory(void *addr, unsigned long len, + extern int os_unmap_memory(void *addr, int len); + extern int os_drop_memory(void *addr, int length); + extern int can_drop_memory(void); +-extern int os_mincore(void *addr, unsigned long len); + + void os_set_pdeathsig(void); + +diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile +index f8567b933ffaa..4df1cd0d20179 100644 +--- a/arch/um/kernel/Makefile ++++ b/arch/um/kernel/Makefile +@@ -17,7 +17,7 @@ extra-y := vmlinux.lds + obj-y = config.o exec.o exitcode.o irq.o ksyms.o mem.o \ + physmem.o process.o ptrace.o reboot.o sigio.o \ + signal.o sysrq.o time.o tlb.o trap.o \ +- um_arch.o umid.o maccess.o kmsg_dump.o capflags.o skas/ ++ um_arch.o umid.o kmsg_dump.o capflags.o skas/ + obj-y += load_file.o + + obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o +diff --git a/arch/um/kernel/maccess.c b/arch/um/kernel/maccess.c +deleted file mode 100644 +index 8ccd56813f684..0000000000000 +--- a/arch/um/kernel/maccess.c ++++ /dev/null +@@ -1,19 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-only +-/* +- * Copyright (C) 2013 Richard Weinberger +- */ +- +-#include +-#include +-#include +- +-bool copy_from_kernel_nofault_allowed(const void *src, size_t size) +-{ +- void *psrc = (void *)rounddown((unsigned long)src, PAGE_SIZE); +- +- if ((unsigned long)src < PAGE_SIZE || size <= 0) +- return false; +- if (os_mincore(psrc, size + src - psrc) <= 0) +- return false; +- return true; +-} +diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c +index 9f086f9394202..184566edeee99 100644 +--- a/arch/um/os-Linux/process.c ++++ b/arch/um/os-Linux/process.c +@@ -142,57 +142,6 @@ int __init can_drop_memory(void) + return ok; + } + +-static int os_page_mincore(void *addr) +-{ +- char vec[2]; +- int ret; +- +- ret = mincore(addr, UM_KERN_PAGE_SIZE, vec); +- if (ret < 0) { +- if (errno == ENOMEM || errno == EINVAL) +- return 0; +- else +- return -errno; +- } +- +- return vec[0] & 1; +-} +- +-int os_mincore(void *addr, unsigned long len) +-{ +- char *vec; +- int ret, i; +- +- if (len <= UM_KERN_PAGE_SIZE) +- return os_page_mincore(addr); +- +- vec = calloc(1, (len + UM_KERN_PAGE_SIZE - 1) / UM_KERN_PAGE_SIZE); +- if (!vec) +- return -ENOMEM; +- +- ret = mincore(addr, UM_KERN_PAGE_SIZE, vec); +- if (ret < 0) { +- if (errno == ENOMEM || errno == EINVAL) +- ret = 0; +- else +- ret = -errno; +- +- goto out; +- } +- +- for (i = 0; i < ((len + UM_KERN_PAGE_SIZE - 1) / UM_KERN_PAGE_SIZE); i++) { +- if (!(vec[i] & 1)) { +- ret = 0; +- goto out; +- } +- } +- +- ret = 1; +-out: +- free(vec); +- return ret; +-} +- + void init_new_thread_signals(void) + { + set_handler(SIGSEGV); +-- +2.39.5 + diff --git a/queue-6.14/usb-typec-thunderbolt-fix-loops-that-iterate-typec_p.patch b/queue-6.14/usb-typec-thunderbolt-fix-loops-that-iterate-typec_p.patch new file mode 100644 index 0000000000..21b1fad120 --- /dev/null +++ b/queue-6.14/usb-typec-thunderbolt-fix-loops-that-iterate-typec_p.patch @@ -0,0 +1,60 @@ +From 97e2aa7a98097fde3fe6075934281458eebf7ecf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 19:40:23 +0000 +Subject: usb: typec: thunderbolt: Fix loops that iterate TYPEC_PLUG_SOP_P and + TYPEC_PLUG_SOP_PP + +From: Benson Leung + +[ Upstream commit b51c1e8d2f49342b2087338c72511326fdb7b172 ] + +Fixes these Smatch static checker warnings: +drivers/usb/typec/altmodes/thunderbolt.c:116 tbt_altmode_work() warn: why is zero skipped 'i' +drivers/usb/typec/altmodes/thunderbolt.c:147 tbt_enter_modes_ordered() warn: why is zero skipped 'i' +drivers/usb/typec/altmodes/thunderbolt.c:328 tbt_altmode_remove() warn: why is zero skipped 'i' + +Fixes: 100e25738659 ("usb: typec: Add driver for Thunderbolt 3 Alternate Mode") +Signed-off-by: Benson Leung +Reported-by: Dan Carpenter +Reviewed-by: Heikki Krogerus +Link: https://lore.kernel.org/r/Z5Psp615abaaId6J@google.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/typec/altmodes/thunderbolt.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/usb/typec/altmodes/thunderbolt.c b/drivers/usb/typec/altmodes/thunderbolt.c +index 1b475b1d98e78..94e47d30e5989 100644 +--- a/drivers/usb/typec/altmodes/thunderbolt.c ++++ b/drivers/usb/typec/altmodes/thunderbolt.c +@@ -112,7 +112,7 @@ static void tbt_altmode_work(struct work_struct *work) + return; + + disable_plugs: +- for (int i = TYPEC_PLUG_SOP_PP; i > 0; --i) { ++ for (int i = TYPEC_PLUG_SOP_PP; i >= 0; --i) { + if (tbt->plug[i]) + typec_altmode_put_plug(tbt->plug[i]); + +@@ -143,7 +143,7 @@ static int tbt_enter_modes_ordered(struct typec_altmode *alt) + if (tbt->plug[TYPEC_PLUG_SOP_P]) { + ret = typec_cable_altmode_enter(alt, TYPEC_PLUG_SOP_P, NULL); + if (ret < 0) { +- for (int i = TYPEC_PLUG_SOP_PP; i > 0; --i) { ++ for (int i = TYPEC_PLUG_SOP_PP; i >= 0; --i) { + if (tbt->plug[i]) + typec_altmode_put_plug(tbt->plug[i]); + +@@ -324,7 +324,7 @@ static void tbt_altmode_remove(struct typec_altmode *alt) + { + struct tbt_altmode *tbt = typec_altmode_get_drvdata(alt); + +- for (int i = TYPEC_PLUG_SOP_PP; i > 0; --i) { ++ for (int i = TYPEC_PLUG_SOP_PP; i >= 0; --i) { + if (tbt->plug[i]) + typec_altmode_put_plug(tbt->plug[i]); + } +-- +2.39.5 + diff --git a/queue-6.14/usb-typec-thunderbolt-remove-is_err-check-for-plug.patch b/queue-6.14/usb-typec-thunderbolt-remove-is_err-check-for-plug.patch new file mode 100644 index 0000000000..c9c8169276 --- /dev/null +++ b/queue-6.14/usb-typec-thunderbolt-remove-is_err-check-for-plug.patch @@ -0,0 +1,43 @@ +From adc1c8868f522ad28ede942e4c7189dfbe074e29 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 19:40:38 +0000 +Subject: usb: typec: thunderbolt: Remove IS_ERR check for plug + +From: Benson Leung + +[ Upstream commit 9682c35ff6ecd76d9462d4749b8b413d3e8e605e ] + +Fixes these Smatch static checker warnings: +drivers/usb/typec/altmodes/thunderbolt.c:354 tbt_ready() warn: 'plug' is not an error pointer + +Fixes: 100e25738659 ("usb: typec: Add driver for Thunderbolt 3 Alternate Mode") +Signed-off-by: Benson Leung +Reported-by: Dan Carpenter +Reviewed-by: Heikki Krogerus +Link: https://lore.kernel.org/r/Z5PstnlA52Z1F2SU@google.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/typec/altmodes/thunderbolt.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/typec/altmodes/thunderbolt.c b/drivers/usb/typec/altmodes/thunderbolt.c +index 94e47d30e5989..6eadf7835f8f6 100644 +--- a/drivers/usb/typec/altmodes/thunderbolt.c ++++ b/drivers/usb/typec/altmodes/thunderbolt.c +@@ -351,10 +351,10 @@ static bool tbt_ready(struct typec_altmode *alt) + */ + for (int i = 0; i < TYPEC_PLUG_SOP_PP + 1; i++) { + plug = typec_altmode_get_plug(tbt->alt, i); +- if (IS_ERR(plug)) ++ if (!plug) + continue; + +- if (!plug || plug->svid != USB_TYPEC_TBT_SID) ++ if (plug->svid != USB_TYPEC_TBT_SID) + break; + + plug->desc = "Thunderbolt3"; +-- +2.39.5 + diff --git a/queue-6.14/usb-xhci-correct-debug-message-page-size-calculation.patch b/queue-6.14/usb-xhci-correct-debug-message-page-size-calculation.patch new file mode 100644 index 0000000000..6da504cd24 --- /dev/null +++ b/queue-6.14/usb-xhci-correct-debug-message-page-size-calculation.patch @@ -0,0 +1,52 @@ +From 5e51f431e8946c1e89e34b4c2cc78444295676aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 16:49:47 +0200 +Subject: usb: xhci: correct debug message page size calculation + +From: Niklas Neronin + +[ Upstream commit 55741c723318905e6d5161bf1e12749020b161e3 ] + +The ffs() function returns the index of the first set bit, starting from 1. +If no bits are set, it returns zero. This behavior causes an off-by-one +page size in the debug message, as the page size calculation [1] +is zero-based, while ffs() is one-based. + +Fix this by subtracting one from the result of ffs(). Note that since +variable 'val' is unsigned, subtracting one from zero will result in the +maximum unsigned integer value. Consequently, the condition 'if (val < 16)' +will still function correctly. + +[1], Page size: (2^(n+12)), where 'n' is the set page size bit. + +Fixes: 81720ec5320c ("usb: host: xhci: use ffs() in xhci_mem_init()") +Signed-off-by: Niklas Neronin +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20250306144954.3507700-9-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-mem.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index fdf0c1008225a..9aa7e2a876ec1 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -2391,10 +2391,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) + page_size = readl(&xhci->op_regs->page_size); + xhci_dbg_trace(xhci, trace_xhci_dbg_init, + "Supported page size register = 0x%x", page_size); +- i = ffs(page_size); +- if (i < 16) ++ val = ffs(page_size) - 1; ++ if (val < 16) + xhci_dbg_trace(xhci, trace_xhci_dbg_init, +- "Supported page size of %iK", (1 << (i+12)) / 1024); ++ "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 */ +-- +2.39.5 + diff --git a/queue-6.14/vhost-scsi-fix-handling-of-multiple-calls-to-vhost_s.patch b/queue-6.14/vhost-scsi-fix-handling-of-multiple-calls-to-vhost_s.patch new file mode 100644 index 0000000000..c0a71920ce --- /dev/null +++ b/queue-6.14/vhost-scsi-fix-handling-of-multiple-calls-to-vhost_s.patch @@ -0,0 +1,176 @@ +From e5b3522c692c8c2a5df548e911b538f804e841fd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 15:09:22 -0600 +Subject: vhost-scsi: Fix handling of multiple calls to vhost_scsi_set_endpoint + +From: Mike Christie + +[ Upstream commit 5dd639a1646ef5fe8f4bf270fad47c5c3755b9b6 ] + +If vhost_scsi_set_endpoint is called multiple times without a +vhost_scsi_clear_endpoint between them, we can hit multiple bugs +found by Haoran Zhang: + +1. Use-after-free when no tpgs are found: + +This fixes a use after free that occurs when vhost_scsi_set_endpoint is +called more than once and calls after the first call do not find any +tpgs to add to the vs_tpg. When vhost_scsi_set_endpoint first finds +tpgs to add to the vs_tpg array match=true, so we will do: + +vhost_vq_set_backend(vq, vs_tpg); +... + +kfree(vs->vs_tpg); +vs->vs_tpg = vs_tpg; + +If vhost_scsi_set_endpoint is called again and no tpgs are found +match=false so we skip the vhost_vq_set_backend call leaving the +pointer to the vs_tpg we then free via: + +kfree(vs->vs_tpg); +vs->vs_tpg = vs_tpg; + +If a scsi request is then sent we do: + +vhost_scsi_handle_vq -> vhost_scsi_get_req -> vhost_vq_get_backend + +which sees the vs_tpg we just did a kfree on. + +2. Tpg dir removal hang: + +This patch fixes an issue where we cannot remove a LIO/target layer +tpg (and structs above it like the target) dir due to the refcount +dropping to -1. + +The problem is that if vhost_scsi_set_endpoint detects a tpg is already +in the vs->vs_tpg array or if the tpg has been removed so +target_depend_item fails, the undepend goto handler will do +target_undepend_item on all tpgs in the vs_tpg array dropping their +refcount to 0. At this time vs_tpg contains both the tpgs we have added +in the current vhost_scsi_set_endpoint call as well as tpgs we added in +previous calls which are also in vs->vs_tpg. + +Later, when vhost_scsi_clear_endpoint runs it will do +target_undepend_item on all the tpgs in the vs->vs_tpg which will drop +their refcount to -1. Userspace will then not be able to remove the tpg +and will hang when it tries to do rmdir on the tpg dir. + +3. Tpg leak: + +This fixes a bug where we can leak tpgs and cause them to be +un-removable because the target name is overwritten when +vhost_scsi_set_endpoint is called multiple times but with different +target names. + +The bug occurs if a user has called VHOST_SCSI_SET_ENDPOINT and setup +a vhost-scsi device to target/tpg mapping, then calls +VHOST_SCSI_SET_ENDPOINT again with a new target name that has tpgs we +haven't seen before (target1 has tpg1 but target2 has tpg2). When this +happens we don't teardown the old target tpg mapping and just overwrite +the target name and the vs->vs_tpg array. Later when we do +vhost_scsi_clear_endpoint, we are passed in either target1 or target2's +name and we will only match that target's tpgs when we loop over the +vs->vs_tpg. We will then return from the function without doing +target_undepend_item on the tpgs. + +Because of all these bugs, it looks like being able to call +vhost_scsi_set_endpoint multiple times was never supported. The major +user, QEMU, already has checks to prevent this use case. So to fix the +issues, this patch prevents vhost_scsi_set_endpoint from being called +if it's already successfully added tpgs. To add, remove or change the +tpg config or target name, you must do a vhost_scsi_clear_endpoint +first. + +Fixes: 25b98b64e284 ("vhost scsi: alloc cmds per vq instead of session") +Fixes: 4f7f46d32c98 ("tcm_vhost: Use vq->private_data to indicate if the endpoint is setup") +Reported-by: Haoran Zhang +Closes: https://lore.kernel.org/virtualization/e418a5ee-45ca-4d18-9b5d-6f8b6b1add8e@oracle.com/T/#me6c0041ce376677419b9b2563494172a01487ecb +Signed-off-by: Mike Christie +Reviewed-by: Stefan Hajnoczi +Message-Id: <20250129210922.121533-1-michael.christie@oracle.com> +Signed-off-by: Michael S. Tsirkin +Acked-by: Stefano Garzarella +Signed-off-by: Sasha Levin +--- + drivers/vhost/scsi.c | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + +diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c +index 718fa4e0b31ec..7aeff435c1d87 100644 +--- a/drivers/vhost/scsi.c ++++ b/drivers/vhost/scsi.c +@@ -1699,14 +1699,19 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs, + } + } + ++ if (vs->vs_tpg) { ++ pr_err("vhost-scsi endpoint already set for %s.\n", ++ vs->vs_vhost_wwpn); ++ ret = -EEXIST; ++ goto out; ++ } ++ + len = sizeof(vs_tpg[0]) * VHOST_SCSI_MAX_TARGET; + vs_tpg = kzalloc(len, GFP_KERNEL); + if (!vs_tpg) { + ret = -ENOMEM; + goto out; + } +- if (vs->vs_tpg) +- memcpy(vs_tpg, vs->vs_tpg, len); + + mutex_lock(&vhost_scsi_mutex); + list_for_each_entry(tpg, &vhost_scsi_list, tv_tpg_list) { +@@ -1722,12 +1727,6 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs, + tv_tport = tpg->tport; + + if (!strcmp(tv_tport->tport_name, t->vhost_wwpn)) { +- if (vs->vs_tpg && vs->vs_tpg[tpg->tport_tpgt]) { +- mutex_unlock(&tpg->tv_tpg_mutex); +- mutex_unlock(&vhost_scsi_mutex); +- ret = -EEXIST; +- goto undepend; +- } + /* + * In order to ensure individual vhost-scsi configfs + * groups cannot be removed while in use by vhost ioctl, +@@ -1774,15 +1773,15 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs, + } + ret = 0; + } else { +- ret = -EEXIST; ++ ret = -ENODEV; ++ goto free_tpg; + } + + /* +- * Act as synchronize_rcu to make sure access to +- * old vs->vs_tpg is finished. ++ * Act as synchronize_rcu to make sure requests after this point ++ * see a fully setup device. + */ + vhost_scsi_flush(vs); +- kfree(vs->vs_tpg); + vs->vs_tpg = vs_tpg; + goto out; + +@@ -1802,6 +1801,7 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs, + target_undepend_item(&tpg->se_tpg.tpg_group.cg_item); + } + } ++free_tpg: + kfree(vs_tpg); + out: + mutex_unlock(&vs->dev.mutex); +@@ -1904,6 +1904,7 @@ vhost_scsi_clear_endpoint(struct vhost_scsi *vs, + vhost_scsi_flush(vs); + kfree(vs->vs_tpg); + vs->vs_tpg = NULL; ++ memset(vs->vs_vhost_wwpn, 0, sizeof(vs->vs_vhost_wwpn)); + WARN_ON(vs->vs_events_nr); + mutex_unlock(&vs->dev.mutex); + return 0; +-- +2.39.5 + diff --git a/queue-6.14/virtchnl-make-proto-and-filter-action-count-unsigned.patch b/queue-6.14/virtchnl-make-proto-and-filter-action-count-unsigned.patch new file mode 100644 index 0000000000..bfacc6e5d3 --- /dev/null +++ b/queue-6.14/virtchnl-make-proto-and-filter-action-count-unsigned.patch @@ -0,0 +1,56 @@ +From 3959a94a4f4011c7a04a82502ba0cf81a6fcbcad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 12:08:31 +0100 +Subject: virtchnl: make proto and filter action count unsigned + +From: Jan Glaza + +[ Upstream commit db5e8ea155fc1d89c87cb81f0e4a681a77b9b03f ] + +The count field in virtchnl_proto_hdrs and virtchnl_filter_action_set +should never be negative while still being valid. Changing it from +int to u32 ensures proper handling of values in virtchnl messages in +driverrs and prevents unintended behavior. +In its current signed form, a negative count does not trigger +an error in ice driver but instead results in it being treated as 0. +This can lead to unexpected outcomes when processing messages. +By using u32, any invalid values will correctly trigger -EINVAL, +making error detection more robust. + +Fixes: 1f7ea1cd6a374 ("ice: Enable FDIR Configure for AVF") +Reviewed-by: Jedrzej Jagielski +Reviewed-by: Simon Horman +Signed-off-by: Jan Glaza +Signed-off-by: Martyna Szapar-Mudlaw +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + include/linux/avf/virtchnl.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/avf/virtchnl.h b/include/linux/avf/virtchnl.h +index 13a11f3c09b87..aca06f300f833 100644 +--- a/include/linux/avf/virtchnl.h ++++ b/include/linux/avf/virtchnl.h +@@ -1283,7 +1283,7 @@ struct virtchnl_proto_hdrs { + * 2 - from the second inner layer + * .... + **/ +- int count; /* the proto layers must < VIRTCHNL_MAX_NUM_PROTO_HDRS */ ++ u32 count; /* the proto layers must < VIRTCHNL_MAX_NUM_PROTO_HDRS */ + union { + struct virtchnl_proto_hdr + proto_hdr[VIRTCHNL_MAX_NUM_PROTO_HDRS]; +@@ -1335,7 +1335,7 @@ VIRTCHNL_CHECK_STRUCT_LEN(36, virtchnl_filter_action); + + struct virtchnl_filter_action_set { + /* action number must be less then VIRTCHNL_MAX_NUM_ACTIONS */ +- int count; ++ u32 count; + struct virtchnl_filter_action actions[VIRTCHNL_MAX_NUM_ACTIONS]; + }; + +-- +2.39.5 + diff --git a/queue-6.14/virtio_net-fix-endian-with-virtio_net_ctrl_rss.patch b/queue-6.14/virtio_net-fix-endian-with-virtio_net_ctrl_rss.patch new file mode 100644 index 0000000000..e0636c8fc7 --- /dev/null +++ b/queue-6.14/virtio_net-fix-endian-with-virtio_net_ctrl_rss.patch @@ -0,0 +1,118 @@ +From daab4cb50b8189c0264de5b310134f2a615c54b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 15:48:33 +0900 +Subject: virtio_net: Fix endian with virtio_net_ctrl_rss + +From: Akihiko Odaki + +[ Upstream commit 97841341e302eac13d54eb5e968570b5626196a7 ] + +Mark the fields of struct virtio_net_ctrl_rss as little endian as +they are in struct virtio_net_rss_config, which it follows. + +Fixes: c7114b1249fa ("drivers/net/virtio_net: Added basic RSS support.") +Signed-off-by: Akihiko Odaki +Acked-by: Jason Wang +Reviewed-by: Xuan Zhuo +Acked-by: Michael S. Tsirkin +Tested-by: Lei Yang +Link: https://patch.msgid.link/20250321-virtio-v2-2-33afb8f4640b@daynix.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/virtio_net.c | 30 +++++++++++++++--------------- + 1 file changed, 15 insertions(+), 15 deletions(-) + +diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c +index 7646ddd9bef70..d1ed544ba03ac 100644 +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -368,15 +368,15 @@ struct receive_queue { + */ + #define VIRTIO_NET_RSS_MAX_KEY_SIZE 40 + struct virtio_net_ctrl_rss { +- u32 hash_types; +- u16 indirection_table_mask; +- u16 unclassified_queue; +- u16 hash_cfg_reserved; /* for HASH_CONFIG (see virtio_net_hash_config for details) */ +- u16 max_tx_vq; ++ __le32 hash_types; ++ __le16 indirection_table_mask; ++ __le16 unclassified_queue; ++ __le16 hash_cfg_reserved; /* for HASH_CONFIG (see virtio_net_hash_config for details) */ ++ __le16 max_tx_vq; + u8 hash_key_length; + u8 key[VIRTIO_NET_RSS_MAX_KEY_SIZE]; + +- u16 *indirection_table; ++ __le16 *indirection_table; + }; + + /* Control VQ buffers: protected by the rtnl lock */ +@@ -3576,9 +3576,9 @@ static void virtnet_rss_update_by_qpairs(struct virtnet_info *vi, u16 queue_pair + + for (; i < vi->rss_indir_table_size; ++i) { + indir_val = ethtool_rxfh_indir_default(i, queue_pairs); +- vi->rss.indirection_table[i] = indir_val; ++ vi->rss.indirection_table[i] = cpu_to_le16(indir_val); + } +- vi->rss.max_tx_vq = queue_pairs; ++ vi->rss.max_tx_vq = cpu_to_le16(queue_pairs); + } + + static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs) +@@ -4097,10 +4097,10 @@ static bool virtnet_commit_rss_command(struct virtnet_info *vi) + + static void virtnet_init_default_rss(struct virtnet_info *vi) + { +- vi->rss.hash_types = vi->rss_hash_types_supported; ++ vi->rss.hash_types = cpu_to_le32(vi->rss_hash_types_supported); + vi->rss_hash_types_saved = vi->rss_hash_types_supported; + vi->rss.indirection_table_mask = vi->rss_indir_table_size +- ? vi->rss_indir_table_size - 1 : 0; ++ ? cpu_to_le16(vi->rss_indir_table_size - 1) : 0; + vi->rss.unclassified_queue = 0; + + virtnet_rss_update_by_qpairs(vi, vi->curr_queue_pairs); +@@ -4218,7 +4218,7 @@ static bool virtnet_set_hashflow(struct virtnet_info *vi, struct ethtool_rxnfc * + + if (new_hashtypes != vi->rss_hash_types_saved) { + vi->rss_hash_types_saved = new_hashtypes; +- vi->rss.hash_types = vi->rss_hash_types_saved; ++ vi->rss.hash_types = cpu_to_le32(vi->rss_hash_types_saved); + if (vi->dev->features & NETIF_F_RXHASH) + return virtnet_commit_rss_command(vi); + } +@@ -5398,7 +5398,7 @@ static int virtnet_get_rxfh(struct net_device *dev, + + if (rxfh->indir) { + for (i = 0; i < vi->rss_indir_table_size; ++i) +- rxfh->indir[i] = vi->rss.indirection_table[i]; ++ rxfh->indir[i] = le16_to_cpu(vi->rss.indirection_table[i]); + } + + if (rxfh->key) +@@ -5426,7 +5426,7 @@ static int virtnet_set_rxfh(struct net_device *dev, + return -EOPNOTSUPP; + + for (i = 0; i < vi->rss_indir_table_size; ++i) +- vi->rss.indirection_table[i] = rxfh->indir[i]; ++ vi->rss.indirection_table[i] = cpu_to_le16(rxfh->indir[i]); + update = true; + } + +@@ -6044,9 +6044,9 @@ static int virtnet_set_features(struct net_device *dev, + + if ((dev->features ^ features) & NETIF_F_RXHASH) { + if (features & NETIF_F_RXHASH) +- vi->rss.hash_types = vi->rss_hash_types_saved; ++ vi->rss.hash_types = cpu_to_le32(vi->rss_hash_types_saved); + else +- vi->rss.hash_types = VIRTIO_NET_HASH_REPORT_NONE; ++ vi->rss.hash_types = cpu_to_le32(VIRTIO_NET_HASH_REPORT_NONE); + + if (!virtnet_commit_rss_command(vi)) + return -EINVAL; +-- +2.39.5 + diff --git a/queue-6.14/vmxnet3-unregister-xdp-rxq-info-in-the-reset-path.patch b/queue-6.14/vmxnet3-unregister-xdp-rxq-info-in-the-reset-path.patch new file mode 100644 index 0000000000..1e6eee90ef --- /dev/null +++ b/queue-6.14/vmxnet3-unregister-xdp-rxq-info-in-the-reset-path.patch @@ -0,0 +1,62 @@ +From 666a1e2c6c3f3f2ea6db0eee9999acff71ad9850 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Mar 2025 10:25:22 +0530 +Subject: vmxnet3: unregister xdp rxq info in the reset path + +From: Sankararaman Jayaraman + +[ Upstream commit 0dd765fae295832934bf28e45dd5a355e0891ed4 ] + +vmxnet3 does not unregister xdp rxq info in the +vmxnet3_reset_work() code path as vmxnet3_rq_destroy() +is not invoked in this code path. So, we get below message with a +backtrace. + +Missing unregister, handled but fix driver +WARNING: CPU:48 PID: 500 at net/core/xdp.c:182 +__xdp_rxq_info_reg+0x93/0xf0 + +This patch fixes the problem by moving the unregister +code of XDP from vmxnet3_rq_destroy() to vmxnet3_rq_cleanup(). + +Fixes: 54f00cce1178 ("vmxnet3: Add XDP support.") +Signed-off-by: Sankararaman Jayaraman +Signed-off-by: Ronak Doshi +Link: https://patch.msgid.link/20250320045522.57892-1-sankararaman.jayaraman@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/vmxnet3/vmxnet3_drv.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c +index 6793fa09f9d1a..3df6aabc7e339 100644 +--- a/drivers/net/vmxnet3/vmxnet3_drv.c ++++ b/drivers/net/vmxnet3/vmxnet3_drv.c +@@ -2033,6 +2033,11 @@ vmxnet3_rq_cleanup(struct vmxnet3_rx_queue *rq, + + rq->comp_ring.gen = VMXNET3_INIT_GEN; + rq->comp_ring.next2proc = 0; ++ ++ if (xdp_rxq_info_is_reg(&rq->xdp_rxq)) ++ xdp_rxq_info_unreg(&rq->xdp_rxq); ++ page_pool_destroy(rq->page_pool); ++ rq->page_pool = NULL; + } + + +@@ -2073,11 +2078,6 @@ static void vmxnet3_rq_destroy(struct vmxnet3_rx_queue *rq, + } + } + +- if (xdp_rxq_info_is_reg(&rq->xdp_rxq)) +- xdp_rxq_info_unreg(&rq->xdp_rxq); +- page_pool_destroy(rq->page_pool); +- rq->page_pool = NULL; +- + if (rq->data_ring.base) { + dma_free_coherent(&adapter->pdev->dev, + rq->rx_ring[0].size * rq->data_ring.desc_size, +-- +2.39.5 + diff --git a/queue-6.14/vsock-avoid-timeout-during-connect-if-the-socket-is-.patch b/queue-6.14/vsock-avoid-timeout-during-connect-if-the-socket-is-.patch new file mode 100644 index 0000000000..4af8e4c01f --- /dev/null +++ b/queue-6.14/vsock-avoid-timeout-during-connect-if-the-socket-is-.patch @@ -0,0 +1,62 @@ +From 2f13422603abd895f97349fc021a64003be9d19c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Mar 2025 15:15:28 +0100 +Subject: vsock: avoid timeout during connect() if the socket is closing + +From: Stefano Garzarella + +[ Upstream commit fccd2b711d9628c7ce0111d5e4938652101ee30a ] + +When a peer attempts to establish a connection, vsock_connect() contains +a loop that waits for the state to be TCP_ESTABLISHED. However, the +other peer can be fast enough to accept the connection and close it +immediately, thus moving the state to TCP_CLOSING. + +When this happens, the peer in the vsock_connect() is properly woken up, +but since the state is not TCP_ESTABLISHED, it goes back to sleep +until the timeout expires, returning -ETIMEDOUT. + +If the socket state is TCP_CLOSING, waiting for the timeout is pointless. +vsock_connect() can return immediately without errors or delay since the +connection actually happened. The socket will be in a closing state, +but this is not an issue, and subsequent calls will fail as expected. + +We discovered this issue while developing a test that accepts and +immediately closes connections to stress the transport switch between +two connect() calls, where the first one was interrupted by a signal +(see Closes link). + +Reported-by: Luigi Leonardi +Closes: https://lore.kernel.org/virtualization/bq6hxrolno2vmtqwcvb5bljfpb7mvwb3kohrvaed6auz5vxrfv@ijmd2f3grobn/ +Fixes: d021c344051a ("VSOCK: Introduce VM Sockets") +Signed-off-by: Stefano Garzarella +Acked-by: Paolo Abeni +Tested-by: Luigi Leonardi +Reviewed-by: Luigi Leonardi +Link: https://patch.msgid.link/20250328141528.420719-1-sgarzare@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/vmw_vsock/af_vsock.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c +index 7e3db87ae4333..fc6afbc8d6806 100644 +--- a/net/vmw_vsock/af_vsock.c ++++ b/net/vmw_vsock/af_vsock.c +@@ -1551,7 +1551,11 @@ static int vsock_connect(struct socket *sock, struct sockaddr *addr, + timeout = vsk->connect_timeout; + prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); + +- while (sk->sk_state != TCP_ESTABLISHED && sk->sk_err == 0) { ++ /* If the socket is already closing or it is in an error state, there ++ * is no point in waiting. ++ */ ++ while (sk->sk_state != TCP_ESTABLISHED && ++ sk->sk_state != TCP_CLOSING && sk->sk_err == 0) { + if (flags & O_NONBLOCK) { + /* If we're not going to block, we schedule a timeout + * function to generate a timeout on the connection +-- +2.39.5 + diff --git a/queue-6.14/w1-fix-null-pointer-dereference-in-probe.patch b/queue-6.14/w1-fix-null-pointer-dereference-in-probe.patch new file mode 100644 index 0000000000..b14f5a9a71 --- /dev/null +++ b/queue-6.14/w1-fix-null-pointer-dereference-in-probe.patch @@ -0,0 +1,54 @@ +From 0b8090141ecb2c6a11fca92867bb473bb4a7976f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jan 2025 12:18:03 -0600 +Subject: w1: fix NULL pointer dereference in probe + +From: Chenyuan Yang + +[ Upstream commit 0dd6770a72f138dabea9eae87f3da6ffa68f0d06 ] + +The w1_uart_probe() function calls w1_uart_serdev_open() (which includes +devm_serdev_device_open()) before setting the client ops via +serdev_device_set_client_ops(). This ordering can trigger a NULL pointer +dereference in the serdev controller's receive_buf handler, as it assumes +serdev->ops is valid when SERPORT_ACTIVE is set. + +This is similar to the issue fixed in commit 5e700b384ec1 +("platform/chrome: cros_ec_uart: properly fix race condition") where +devm_serdev_device_open() was called before fully initializing the +device. + +Fix the race by ensuring client ops are set before enabling the port via +w1_uart_serdev_open(). + +Fixes: a3c08804364e ("w1: add UART w1 bus driver") +Signed-off-by: Chenyuan Yang +Acked-by: Christoph Winklhofer +Link: https://lore.kernel.org/r/20250111181803.2283611-1-chenyuan0y@gmail.com +Signed-off-by: Krzysztof Kozlowski +Signed-off-by: Sasha Levin +--- + drivers/w1/masters/w1-uart.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/w1/masters/w1-uart.c b/drivers/w1/masters/w1-uart.c +index a31782e56ba75..c87eea3478067 100644 +--- a/drivers/w1/masters/w1-uart.c ++++ b/drivers/w1/masters/w1-uart.c +@@ -372,11 +372,11 @@ static int w1_uart_probe(struct serdev_device *serdev) + init_completion(&w1dev->rx_byte_received); + mutex_init(&w1dev->rx_mutex); + ++ serdev_device_set_drvdata(serdev, w1dev); ++ serdev_device_set_client_ops(serdev, &w1_uart_serdev_ops); + ret = w1_uart_serdev_open(w1dev); + if (ret < 0) + return ret; +- serdev_device_set_drvdata(serdev, w1dev); +- serdev_device_set_client_ops(serdev, &w1_uart_serdev_ops); + + return w1_add_master_device(&w1dev->bus); + } +-- +2.39.5 + diff --git a/queue-6.14/watch_queue-fix-pipe-accounting-mismatch.patch b/queue-6.14/watch_queue-fix-pipe-accounting-mismatch.patch new file mode 100644 index 0000000000..6571a81187 --- /dev/null +++ b/queue-6.14/watch_queue-fix-pipe-accounting-mismatch.patch @@ -0,0 +1,55 @@ +From 743efdc6a0626ad9365b7a6226d5db4ab0122da2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 11:41:08 -0600 +Subject: watch_queue: fix pipe accounting mismatch + +From: Eric Sandeen + +[ Upstream commit f13abc1e8e1a3b7455511c4e122750127f6bc9b0 ] + +Currently, watch_queue_set_size() modifies the pipe buffers charged to +user->pipe_bufs without updating the pipe->nr_accounted on the pipe +itself, due to the if (!pipe_has_watch_queue()) test in +pipe_resize_ring(). This means that when the pipe is ultimately freed, +we decrement user->pipe_bufs by something other than what than we had +charged to it, potentially leading to an underflow. This in turn can +cause subsequent too_many_pipe_buffers_soft() tests to fail with -EPERM. + +To remedy this, explicitly account for the pipe usage in +watch_queue_set_size() to match the number set via account_pipe_buffers() + +(It's unclear why watch_queue_set_size() does not update nr_accounted; +it may be due to intentional overprovisioning in watch_queue_set_size()?) + +Fixes: e95aada4cb93d ("pipe: wakeup wr_wait after setting max_usage") +Signed-off-by: Eric Sandeen +Link: https://lore.kernel.org/r/206682a8-0604-49e5-8224-fdbe0c12b460@redhat.com +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + kernel/watch_queue.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/kernel/watch_queue.c b/kernel/watch_queue.c +index 5267adeaa4034..41e4e8070923a 100644 +--- a/kernel/watch_queue.c ++++ b/kernel/watch_queue.c +@@ -269,6 +269,15 @@ long watch_queue_set_size(struct pipe_inode_info *pipe, unsigned int nr_notes) + if (ret < 0) + goto error; + ++ /* ++ * pipe_resize_ring() does not update nr_accounted for watch_queue ++ * pipes, because the above vastly overprovisions. Set nr_accounted on ++ * and max_usage this pipe to the number that was actually charged to ++ * the user above via account_pipe_buffers. ++ */ ++ pipe->max_usage = nr_pages; ++ pipe->nr_accounted = nr_pages; ++ + ret = -ENOMEM; + pages = kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL); + if (!pages) +-- +2.39.5 + diff --git a/queue-6.14/watchdog-hardlockup-perf-fix-perf_event-memory-leak.patch b/queue-6.14/watchdog-hardlockup-perf-fix-perf_event-memory-leak.patch new file mode 100644 index 0000000000..b784e27551 --- /dev/null +++ b/queue-6.14/watchdog-hardlockup-perf-fix-perf_event-memory-leak.patch @@ -0,0 +1,288 @@ +From 601bb99e52a9462a6f873f07b224467629d790af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Oct 2024 03:30:03 +0800 +Subject: watchdog/hardlockup/perf: Fix perf_event memory leak + +From: Li Huafei + +[ Upstream commit d6834d9c990333bfa433bc1816e2417f268eebbe ] + +During stress-testing, we found a kmemleak report for perf_event: + + unreferenced object 0xff110001410a33e0 (size 1328): + comm "kworker/4:11", pid 288, jiffies 4294916004 + hex dump (first 32 bytes): + b8 be c2 3b 02 00 11 ff 22 01 00 00 00 00 ad de ...;...."....... + f0 33 0a 41 01 00 11 ff f0 33 0a 41 01 00 11 ff .3.A.....3.A.... + backtrace (crc 24eb7b3a): + [<00000000e211b653>] kmem_cache_alloc_node_noprof+0x269/0x2e0 + [<000000009d0985fa>] perf_event_alloc+0x5f/0xcf0 + [<00000000084ad4a2>] perf_event_create_kernel_counter+0x38/0x1b0 + [<00000000fde96401>] hardlockup_detector_event_create+0x50/0xe0 + [<0000000051183158>] watchdog_hardlockup_enable+0x17/0x70 + [<00000000ac89727f>] softlockup_start_fn+0x15/0x40 + ... + +Our stress test includes CPU online and offline cycles, and updating the +watchdog configuration. + +After reading the code, I found that there may be a race between cleaning up +perf_event after updating watchdog and disabling event when the CPU goes offline: + + CPU0 CPU1 CPU2 + (update watchdog) (hotplug offline CPU1) + + ... _cpu_down(CPU1) + cpus_read_lock() // waiting for cpu lock + softlockup_start_all + smp_call_on_cpu(CPU1) + softlockup_start_fn + ... + watchdog_hardlockup_enable(CPU1) + perf create E1 + watchdog_ev[CPU1] = E1 + cpus_read_unlock() + cpus_write_lock() + cpuhp_kick_ap_work(CPU1) + cpuhp_thread_fun + ... + watchdog_hardlockup_disable(CPU1) + watchdog_ev[CPU1] = NULL + dead_event[CPU1] = E1 + __lockup_detector_cleanup + for each dead_events_mask + release each dead_event + /* + * CPU1 has not been added to + * dead_events_mask, then E1 + * will not be released + */ + CPU1 -> dead_events_mask + cpumask_clear(&dead_events_mask) + // dead_events_mask is cleared, E1 is leaked + +In this case, the leaked perf_event E1 matches the perf_event leak +reported by kmemleak. Due to the low probability of problem recurrence +(only reported once), I added some hack delays in the code: + + static void __lockup_detector_reconfigure(void) + { + ... + watchdog_hardlockup_start(); + cpus_read_unlock(); + + mdelay(100); + /* + * Must be called outside the cpus locked section to prevent + * recursive locking in the perf code. + ... + } + + void watchdog_hardlockup_disable(unsigned int cpu) + { + ... + perf_event_disable(event); + this_cpu_write(watchdog_ev, NULL); + this_cpu_write(dead_event, event); + + mdelay(100); + cpumask_set_cpu(smp_processor_id(), &dead_events_mask); + atomic_dec(&watchdog_cpus); + ... + } + + void hardlockup_detector_perf_cleanup(void) + { + ... + perf_event_release_kernel(event); + per_cpu(dead_event, cpu) = NULL; + } + + mdelay(100); + cpumask_clear(&dead_events_mask); + } + +Then, simultaneously performing CPU on/off and switching watchdog, it is +almost certain to reproduce this leak. + +The problem here is that releasing perf_event is not within the CPU +hotplug read-write lock. Commit: + + 941154bd6937 ("watchdog/hardlockup/perf: Prevent CPU hotplug deadlock") + +introduced deferred release to solve the deadlock caused by calling +get_online_cpus() when releasing perf_event. Later, commit: + + efe951d3de91 ("perf/x86: Fix perf,x86,cpuhp deadlock") + +removed the get_online_cpus() call on the perf_event release path to solve +another deadlock problem. + +Therefore, it is now possible to move the release of perf_event back +into the CPU hotplug read-write lock, and release the event immediately +after disabling it. + +Fixes: 941154bd6937 ("watchdog/hardlockup/perf: Prevent CPU hotplug deadlock") +Signed-off-by: Li Huafei +Signed-off-by: Ingo Molnar +Cc: Thomas Gleixner +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20241021193004.308303-1-lihuafei1@huawei.com +Signed-off-by: Sasha Levin +--- + include/linux/nmi.h | 4 ---- + kernel/cpu.c | 5 ----- + kernel/watchdog.c | 25 ------------------------- + kernel/watchdog_perf.c | 28 +--------------------------- + 4 files changed, 1 insertion(+), 61 deletions(-) + +diff --git a/include/linux/nmi.h b/include/linux/nmi.h +index a8dfb38c9bb6f..e78fa535f61dd 100644 +--- a/include/linux/nmi.h ++++ b/include/linux/nmi.h +@@ -17,7 +17,6 @@ + void lockup_detector_init(void); + void lockup_detector_retry_init(void); + void lockup_detector_soft_poweroff(void); +-void lockup_detector_cleanup(void); + + extern int watchdog_user_enabled; + extern int watchdog_thresh; +@@ -37,7 +36,6 @@ extern int sysctl_hardlockup_all_cpu_backtrace; + static inline void lockup_detector_init(void) { } + static inline void lockup_detector_retry_init(void) { } + static inline void lockup_detector_soft_poweroff(void) { } +-static inline void lockup_detector_cleanup(void) { } + #endif /* !CONFIG_LOCKUP_DETECTOR */ + + #ifdef CONFIG_SOFTLOCKUP_DETECTOR +@@ -104,12 +102,10 @@ void watchdog_hardlockup_check(unsigned int cpu, struct pt_regs *regs); + #if defined(CONFIG_HARDLOCKUP_DETECTOR_PERF) + extern void hardlockup_detector_perf_stop(void); + extern void hardlockup_detector_perf_restart(void); +-extern void hardlockup_detector_perf_cleanup(void); + extern void hardlockup_config_perf_event(const char *str); + #else + static inline void hardlockup_detector_perf_stop(void) { } + static inline void hardlockup_detector_perf_restart(void) { } +-static inline void hardlockup_detector_perf_cleanup(void) { } + static inline void hardlockup_config_perf_event(const char *str) { } + #endif + +diff --git a/kernel/cpu.c b/kernel/cpu.c +index 07455d25329c9..ad755db29efd4 100644 +--- a/kernel/cpu.c ++++ b/kernel/cpu.c +@@ -1453,11 +1453,6 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen, + + out: + cpus_write_unlock(); +- /* +- * Do post unplug cleanup. This is still protected against +- * concurrent CPU hotplug via cpu_add_remove_lock. +- */ +- lockup_detector_cleanup(); + arch_smt_update(); + return ret; + } +diff --git a/kernel/watchdog.c b/kernel/watchdog.c +index b2da7de39d06d..18156023e4614 100644 +--- a/kernel/watchdog.c ++++ b/kernel/watchdog.c +@@ -347,8 +347,6 @@ static int __init watchdog_thresh_setup(char *str) + } + __setup("watchdog_thresh=", watchdog_thresh_setup); + +-static void __lockup_detector_cleanup(void); +- + #ifdef CONFIG_SOFTLOCKUP_DETECTOR_INTR_STORM + enum stats_per_group { + STATS_SYSTEM, +@@ -886,11 +884,6 @@ static void __lockup_detector_reconfigure(void) + + watchdog_hardlockup_start(); + cpus_read_unlock(); +- /* +- * Must be called outside the cpus locked section to prevent +- * recursive locking in the perf code. +- */ +- __lockup_detector_cleanup(); + } + + void lockup_detector_reconfigure(void) +@@ -940,24 +933,6 @@ static inline void lockup_detector_setup(void) + } + #endif /* !CONFIG_SOFTLOCKUP_DETECTOR */ + +-static void __lockup_detector_cleanup(void) +-{ +- lockdep_assert_held(&watchdog_mutex); +- hardlockup_detector_perf_cleanup(); +-} +- +-/** +- * lockup_detector_cleanup - Cleanup after cpu hotplug or sysctl changes +- * +- * Caller must not hold the cpu hotplug rwsem. +- */ +-void lockup_detector_cleanup(void) +-{ +- mutex_lock(&watchdog_mutex); +- __lockup_detector_cleanup(); +- mutex_unlock(&watchdog_mutex); +-} +- + /** + * lockup_detector_soft_poweroff - Interface to stop lockup detector(s) + * +diff --git a/kernel/watchdog_perf.c b/kernel/watchdog_perf.c +index 59c1d86a73a24..2fdb96eaf4933 100644 +--- a/kernel/watchdog_perf.c ++++ b/kernel/watchdog_perf.c +@@ -21,8 +21,6 @@ + #include + + static DEFINE_PER_CPU(struct perf_event *, watchdog_ev); +-static DEFINE_PER_CPU(struct perf_event *, dead_event); +-static struct cpumask dead_events_mask; + + static atomic_t watchdog_cpus = ATOMIC_INIT(0); + +@@ -181,36 +179,12 @@ void watchdog_hardlockup_disable(unsigned int cpu) + + if (event) { + perf_event_disable(event); ++ perf_event_release_kernel(event); + this_cpu_write(watchdog_ev, NULL); +- this_cpu_write(dead_event, event); +- cpumask_set_cpu(smp_processor_id(), &dead_events_mask); + atomic_dec(&watchdog_cpus); + } + } + +-/** +- * hardlockup_detector_perf_cleanup - Cleanup disabled events and destroy them +- * +- * Called from lockup_detector_cleanup(). Serialized by the caller. +- */ +-void hardlockup_detector_perf_cleanup(void) +-{ +- int cpu; +- +- for_each_cpu(cpu, &dead_events_mask) { +- struct perf_event *event = per_cpu(dead_event, cpu); +- +- /* +- * Required because for_each_cpu() reports unconditionally +- * CPU0 as set on UP kernels. Sigh. +- */ +- if (event) +- perf_event_release_kernel(event); +- per_cpu(dead_event, cpu) = NULL; +- } +- cpumask_clear(&dead_events_mask); +-} +- + /** + * hardlockup_detector_perf_stop - Globally stop watchdog events + * +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath11k-add-srng-lock-for-ath11k_hal_srng_-in-mo.patch b/queue-6.14/wifi-ath11k-add-srng-lock-for-ath11k_hal_srng_-in-mo.patch new file mode 100644 index 0000000000..52a78a2f4f --- /dev/null +++ b/queue-6.14/wifi-ath11k-add-srng-lock-for-ath11k_hal_srng_-in-mo.patch @@ -0,0 +1,106 @@ +From dcb00c3fd6f68b9034abaefff042c138435ceb66 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Dec 2024 19:05:31 +0800 +Subject: wifi: ath11k: add srng->lock for ath11k_hal_srng_* in monitor mode + +From: Kang Yang + +[ Upstream commit 63b7af49496d0e32f7a748b6af3361ec138b1bd3 ] + +ath11k_hal_srng_* should be used with srng->lock to protect srng data. + +For ath11k_dp_rx_mon_dest_process() and ath11k_dp_full_mon_process_rx(), +they use ath11k_hal_srng_* for many times but never call srng->lock. + +So when running (full) monitor mode, warning will occur: +RIP: 0010:ath11k_hal_srng_dst_peek+0x18/0x30 [ath11k] +Call Trace: + ? ath11k_hal_srng_dst_peek+0x18/0x30 [ath11k] + ath11k_dp_rx_process_mon_status+0xc45/0x1190 [ath11k] + ? idr_alloc_u32+0x97/0xd0 + ath11k_dp_rx_process_mon_rings+0x32a/0x550 [ath11k] + ath11k_dp_service_srng+0x289/0x5a0 [ath11k] + ath11k_pcic_ext_grp_napi_poll+0x30/0xd0 [ath11k] + __napi_poll+0x30/0x1f0 + net_rx_action+0x198/0x320 + __do_softirq+0xdd/0x319 + +So add srng->lock for them to avoid such warnings. + +Inorder to fetch the srng->lock, should change srng's definition from +'void' to 'struct hal_srng'. And initialize them elsewhere to prevent +one line of code from being too long. This is consistent with other ring +process functions, such as ath11k_dp_process_rx(). + +Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.30 +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Signed-off-by: Kang Yang +Acked-by: Jeff Johnson +Link: https://patch.msgid.link/20241219110531.2096-3-quic_kangyang@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index 07cd336ee01b1..b8b3dce9cdb53 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -5148,7 +5148,7 @@ static void ath11k_dp_rx_mon_dest_process(struct ath11k *ar, int mac_id, + struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data; + const struct ath11k_hw_hal_params *hal_params; + void *ring_entry; +- void *mon_dst_srng; ++ struct hal_srng *mon_dst_srng; + u32 ppdu_id; + u32 rx_bufs_used; + u32 ring_id; +@@ -5165,6 +5165,7 @@ static void ath11k_dp_rx_mon_dest_process(struct ath11k *ar, int mac_id, + + spin_lock_bh(&pmon->mon_lock); + ++ spin_lock_bh(&mon_dst_srng->lock); + ath11k_hal_srng_access_begin(ar->ab, mon_dst_srng); + + ppdu_id = pmon->mon_ppdu_info.ppdu_id; +@@ -5223,6 +5224,7 @@ static void ath11k_dp_rx_mon_dest_process(struct ath11k *ar, int mac_id, + mon_dst_srng); + } + ath11k_hal_srng_access_end(ar->ab, mon_dst_srng); ++ spin_unlock_bh(&mon_dst_srng->lock); + + spin_unlock_bh(&pmon->mon_lock); + +@@ -5612,7 +5614,7 @@ static int ath11k_dp_full_mon_process_rx(struct ath11k_base *ab, int mac_id, + struct hal_sw_mon_ring_entries *sw_mon_entries; + struct ath11k_pdev_mon_stats *rx_mon_stats; + struct sk_buff *head_msdu, *tail_msdu; +- void *mon_dst_srng = &ar->ab->hal.srng_list[dp->rxdma_mon_dst_ring.ring_id]; ++ struct hal_srng *mon_dst_srng; + void *ring_entry; + u32 rx_bufs_used = 0, mpdu_rx_bufs_used; + int quota = 0, ret; +@@ -5628,6 +5630,9 @@ static int ath11k_dp_full_mon_process_rx(struct ath11k_base *ab, int mac_id, + goto reap_status_ring; + } + ++ mon_dst_srng = &ar->ab->hal.srng_list[dp->rxdma_mon_dst_ring.ring_id]; ++ spin_lock_bh(&mon_dst_srng->lock); ++ + ath11k_hal_srng_access_begin(ar->ab, mon_dst_srng); + while ((ring_entry = ath11k_hal_srng_dst_peek(ar->ab, mon_dst_srng))) { + head_msdu = NULL; +@@ -5671,6 +5676,7 @@ static int ath11k_dp_full_mon_process_rx(struct ath11k_base *ab, int mac_id, + } + + ath11k_hal_srng_access_end(ar->ab, mon_dst_srng); ++ spin_unlock_bh(&mon_dst_srng->lock); + spin_unlock_bh(&pmon->mon_lock); + + if (rx_bufs_used) { +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath11k-clear-affinity-hint-before-calling-ath11.patch b/queue-6.14/wifi-ath11k-clear-affinity-hint-before-calling-ath11.patch new file mode 100644 index 0000000000..ce9ed58922 --- /dev/null +++ b/queue-6.14/wifi-ath11k-clear-affinity-hint-before-calling-ath11.patch @@ -0,0 +1,60 @@ +From 0b3826c8a21a4f184221fc1b74d03bdb93105e76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 11:04:45 +0530 +Subject: wifi: ath11k: Clear affinity hint before calling + ath11k_pcic_free_irq() in error path + +From: Manivannan Sadhasivam + +[ Upstream commit 68410c5bd381a81bcc92b808e7dc4e6b9ed25d11 ] + +If a shared IRQ is used by the driver due to platform limitation, then the +IRQ affinity hint is set right after the allocation of IRQ vectors in +ath11k_pci_alloc_msi(). This does no harm unless one of the functions +requesting the IRQ fails and attempt to free the IRQ. This results in the +below warning: + +WARNING: CPU: 7 PID: 349 at kernel/irq/manage.c:1929 free_irq+0x278/0x29c +Call trace: + free_irq+0x278/0x29c + ath11k_pcic_free_irq+0x70/0x10c [ath11k] + ath11k_pci_probe+0x800/0x820 [ath11k_pci] + local_pci_probe+0x40/0xbc + +The warning is due to not clearing the affinity hint before freeing the +IRQs. + +So to fix this issue, clear the IRQ affinity hint before calling +ath11k_pcic_free_irq() in the error path. The affinity will be cleared once +again further down the error path due to code organization, but that does +no harm. + +Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-05266-QCAHSTSWPLZ_V2_TO_X86-1 + +Cc: Baochen Qiang +Fixes: 39564b475ac5 ("wifi: ath11k: fix boot failure with one MSI vector") +Signed-off-by: Manivannan Sadhasivam +Reviewed-by: Baochen Qiang +Link: https://patch.msgid.link/20250225053447.16824-2-manivannan.sadhasivam@linaro.org +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/pci.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c +index b93f04973ad79..eaac9eabcc70a 100644 +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -939,6 +939,8 @@ static int ath11k_pci_probe(struct pci_dev *pdev, + return 0; + + err_free_irq: ++ /* __free_irq() expects the caller to have cleared the affinity hint */ ++ ath11k_pci_set_irq_affinity_hint(ab_pci, NULL); + ath11k_pcic_free_irq(ab); + + err_ce_free: +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath11k-fix-rcu-stall-while-reaping-monitor-dest.patch b/queue-6.14/wifi-ath11k-fix-rcu-stall-while-reaping-monitor-dest.patch new file mode 100644 index 0000000000..42fcfe79ff --- /dev/null +++ b/queue-6.14/wifi-ath11k-fix-rcu-stall-while-reaping-monitor-dest.patch @@ -0,0 +1,65 @@ +From b8e77986c47107bdf3df7b9a8ceb38cfd47229ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Dec 2024 19:05:30 +0800 +Subject: wifi: ath11k: fix RCU stall while reaping monitor destination ring + +From: P Praneesh + +[ Upstream commit 16c6c35c03ea73054a1f6d3302a4ce4a331b427d ] + +While processing the monitor destination ring, MSDUs are reaped from the +link descriptor based on the corresponding buf_id. + +However, sometimes the driver cannot obtain a valid buffer corresponding +to the buf_id received from the hardware. This causes an infinite loop +in the destination processing, resulting in a kernel crash. + +kernel log: +ath11k_pci 0000:58:00.0: data msdu_pop: invalid buf_id 309 +ath11k_pci 0000:58:00.0: data dp_rx_monitor_link_desc_return failed +ath11k_pci 0000:58:00.0: data msdu_pop: invalid buf_id 309 +ath11k_pci 0000:58:00.0: data dp_rx_monitor_link_desc_return failed + +Fix this by skipping the problematic buf_id and reaping the next entry, +replacing the break with the next MSDU processing. + +Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.30 +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Signed-off-by: P Praneesh +Signed-off-by: Kang Yang +Acked-by: Kalle Valo +Acked-by: Jeff Johnson +Link: https://patch.msgid.link/20241219110531.2096-2-quic_kangyang@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index 029ecf51c9efd..07cd336ee01b1 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -4783,7 +4783,7 @@ u32 ath11k_dp_rx_mon_mpdu_pop(struct ath11k *ar, int mac_id, + if (!msdu) { + ath11k_dbg(ar->ab, ATH11K_DBG_DATA, + "msdu_pop: invalid buf_id %d\n", buf_id); +- break; ++ goto next_msdu; + } + rxcb = ATH11K_SKB_RXCB(msdu); + if (!rxcb->unmapped) { +@@ -5410,7 +5410,7 @@ ath11k_dp_rx_full_mon_mpdu_pop(struct ath11k *ar, + "full mon msdu_pop: invalid buf_id %d\n", + buf_id); + spin_unlock_bh(&rx_ring->idr_lock); +- break; ++ goto next_msdu; + } + idr_remove(&rx_ring->bufs_idr, buf_id); + spin_unlock_bh(&rx_ring->idr_lock); +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath11k-fix-wrong-overriding-for-vht-beamformee-.patch b/queue-6.14/wifi-ath11k-fix-wrong-overriding-for-vht-beamformee-.patch new file mode 100644 index 0000000000..4cbb8294e9 --- /dev/null +++ b/queue-6.14/wifi-ath11k-fix-wrong-overriding-for-vht-beamformee-.patch @@ -0,0 +1,67 @@ +From 6ae5b5a7bbaf4b55c9471b89a4a3c08035e79de1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 15:59:53 +0800 +Subject: wifi: ath11k: fix wrong overriding for VHT Beamformee STS Capability +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Yu Zhang(Yuriy) + +[ Upstream commit 9d13950acb2a51342c93c69f1a5bf285adb90d88 ] + +Current code in ath11k_mac_set_txbf_conf overrides nsts, which is +incorrect as it confuses nss and nsts. nss is Number of Spatial +Streams,nsts is Number of Space-Time Streams. + +As mentioned in Fixes: 55b5ee3357d7, the nss used when acting as a +beamformee in VHT mode should be reported by the firmware and should not +be greater than the number of receiving antennas - 1. The num_rx_chains +related nss rather than nsts. + +If STBC is enabled, nsts is greater than nss. About nss are mapped to +nsts, refer to IEEE Std 802.11-2020: 19.3.11.9.2 Space-time block coding +(STBC), Table 19-18—Constellation mapper output to spatial mapper input +for STBC. + +Remove wrong overriding for nsts of VHT Beamformee STS Capability, +acting DL MU-MIMO in VHT mode is working properly. + +Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-04479-QCAHSPSWPL_V1_V2_SILICONZ_IOE-1 + +Fixes: 55b5ee3357d7 ("wifi: ath11k: fix number of VHT beamformee spatial streams") +Signed-off-by: Yu Zhang (Yuriy) +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20250124075953.2282354-1-quic_yuzha@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/mac.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index 1556392f7ad48..1298a3190a3c5 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -5336,8 +5336,6 @@ static int ath11k_mac_set_txbf_conf(struct ath11k_vif *arvif) + if (vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)) { + nsts = vht_cap & IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; + nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; +- if (nsts > (ar->num_rx_chains - 1)) +- nsts = ar->num_rx_chains - 1; + value |= SM(nsts, WMI_TXBF_STS_CAP_OFFSET); + } + +@@ -5421,9 +5419,6 @@ static void ath11k_set_vht_txbf_cap(struct ath11k *ar, u32 *vht_cap) + + /* Enable Beamformee STS Field only if SU BF is enabled */ + if (subfee) { +- if (nsts > (ar->num_rx_chains - 1)) +- nsts = ar->num_rx_chains - 1; +- + nsts <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; + nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; + *vht_cap |= nsts; +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath11k-update-channel-list-in-reg-notifier-inst.patch b/queue-6.14/wifi-ath11k-update-channel-list-in-reg-notifier-inst.patch new file mode 100644 index 0000000000..35270d7a3d --- /dev/null +++ b/queue-6.14/wifi-ath11k-update-channel-list-in-reg-notifier-inst.patch @@ -0,0 +1,108 @@ +From b9b7e8f7609d0f5cd3807565d18feb8ccebe67a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jan 2025 14:17:36 +0800 +Subject: wifi: ath11k: update channel list in reg notifier instead reg worker + +From: Wen Gong + +[ Upstream commit 933ab187e679e6fbdeea1835ae39efcc59c022d2 ] + +Currently when ath11k gets a new channel list, it will be processed +according to the following steps: +1. update new channel list to cfg80211 and queue reg_work. +2. cfg80211 handles new channel list during reg_work. +3. update cfg80211's handled channel list to firmware by +ath11k_reg_update_chan_list(). + +But ath11k will immediately execute step 3 after reg_work is just +queued. Since step 2 is asynchronous, cfg80211 may not have completed +handling the new channel list, which may leading to an out-of-bounds +write error: +BUG: KASAN: slab-out-of-bounds in ath11k_reg_update_chan_list +Call Trace: + ath11k_reg_update_chan_list+0xbfe/0xfe0 [ath11k] + kfree+0x109/0x3a0 + ath11k_regd_update+0x1cf/0x350 [ath11k] + ath11k_regd_update_work+0x14/0x20 [ath11k] + process_one_work+0xe35/0x14c0 + +Should ensure step 2 is completely done before executing step 3. Thus +Wen raised patch[1]. When flag NL80211_REGDOM_SET_BY_DRIVER is set, +cfg80211 will notify ath11k after step 2 is done. + +So enable the flag NL80211_REGDOM_SET_BY_DRIVER then cfg80211 will +notify ath11k after step 2 is done. At this time, there will be no +KASAN bug during the execution of the step 3. + +[1] https://patchwork.kernel.org/project/linux-wireless/patch/20230201065313.27203-1-quic_wgong@quicinc.com/ + +Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3 + +Fixes: f45cb6b29cd3 ("wifi: ath11k: avoid deadlock during regulatory update in ath11k_regd_update()") +Signed-off-by: Wen Gong +Signed-off-by: Kang Yang +Reviewed-by: Aditya Kumar Singh +Link: https://patch.msgid.link/20250117061737.1921-2-quic_kangyang@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/reg.c | 22 +++++++++++++++------- + 1 file changed, 15 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c +index b0f289784dd3a..7bfe47ad62a07 100644 +--- a/drivers/net/wireless/ath/ath11k/reg.c ++++ b/drivers/net/wireless/ath/ath11k/reg.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 + +@@ -55,6 +55,19 @@ ath11k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) + ath11k_dbg(ar->ab, ATH11K_DBG_REG, + "Regulatory Notification received for %s\n", wiphy_name(wiphy)); + ++ if (request->initiator == NL80211_REGDOM_SET_BY_DRIVER) { ++ ath11k_dbg(ar->ab, ATH11K_DBG_REG, ++ "driver initiated regd update\n"); ++ if (ar->state != ATH11K_STATE_ON) ++ return; ++ ++ ret = ath11k_reg_update_chan_list(ar, true); ++ if (ret) ++ ath11k_warn(ar->ab, "failed to update channel list: %d\n", ret); ++ ++ return; ++ } ++ + /* Currently supporting only General User Hints. Cell base user + * hints to be handled later. + * Hints from other sources like Core, Beacons are not expected for +@@ -293,12 +306,6 @@ int ath11k_regd_update(struct ath11k *ar) + if (ret) + goto err; + +- if (ar->state == ATH11K_STATE_ON) { +- ret = ath11k_reg_update_chan_list(ar, true); +- if (ret) +- goto err; +- } +- + return 0; + err: + ath11k_warn(ab, "failed to perform regd update : %d\n", ret); +@@ -977,6 +984,7 @@ void ath11k_regd_update_work(struct work_struct *work) + void ath11k_reg_init(struct ath11k *ar) + { + ar->hw->wiphy->regulatory_flags = REGULATORY_WIPHY_SELF_MANAGED; ++ ar->hw->wiphy->flags |= WIPHY_FLAG_NOTIFY_REGDOM_BY_DRIVER; + ar->hw->wiphy->reg_notifier = ath11k_reg_notifier; + } + +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-add-missing-htt_metadata-flag-in-ath12k_.patch b/queue-6.14/wifi-ath12k-add-missing-htt_metadata-flag-in-ath12k_.patch new file mode 100644 index 0000000000..a254141b19 --- /dev/null +++ b/queue-6.14/wifi-ath12k-add-missing-htt_metadata-flag-in-ath12k_.patch @@ -0,0 +1,41 @@ +From b5880ca972956aa1a3415c5f7988178df27182cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 12:33:31 +0100 +Subject: wifi: ath12k: Add missing htt_metadata flag in ath12k_dp_tx() + +From: Nicolas Escande + +[ Upstream commit af1c6007a64e78b729eb5a8d149637a820077bee ] + +When AP-VLAN support was added, the HTT_TCL_META_DATA_VALID_HTT flag +was not added to the tx_info's meta_data_flags. Without this flag the +firmware seems to reject all the broadcast (ap-vlan) frames. So add +the flag, just as ath11k did it in the downstream QSDK project[1]. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1 + +Fixes: 26dd8ccdba4d ("wifi: ath12k: dynamic VLAN support") +Signed-off-by: Nicolas Escande +Link: https://git.codelinaro.org/clo/qsdk/oss/system/feeds/wlan-open/-/blob/win.wlan_host_opensource.3.0.r24/patches/ath11k/207-ath11k-Add-support-for-dynamic-vlan.patch # [1] +Link: https://patch.msgid.link/20250124113331.93476-1-nico.escande@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index e0b85f959cd4a..1fffabaca527a 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -368,6 +368,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, + add_htt_metadata = true; + msdu_ext_desc = true; + ti.flags0 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TO_FW); ++ ti.meta_data_flags |= HTT_TCL_META_DATA_VALID_HTT; + ti.encap_type = HAL_TCL_ENCAP_TYPE_RAW; + ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN; + } +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-clear-affinity-hint-before-calling-ath12.patch b/queue-6.14/wifi-ath12k-clear-affinity-hint-before-calling-ath12.patch new file mode 100644 index 0000000000..4aed7731f8 --- /dev/null +++ b/queue-6.14/wifi-ath12k-clear-affinity-hint-before-calling-ath12.patch @@ -0,0 +1,55 @@ +From d95fb4eb0cc825851b9b046968b7444ad1c5e9f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 11:04:46 +0530 +Subject: wifi: ath12k: Clear affinity hint before calling + ath12k_pci_free_irq() in error path + +From: Manivannan Sadhasivam + +[ Upstream commit b43b1e2c52db77c872bd60d30cdcc72c47df70c7 ] + +If a shared IRQ is used by the driver due to platform limitation, then the +IRQ affinity hint is set right after the allocation of IRQ vectors in +ath12k_pci_msi_alloc(). This does no harm unless one of the functions +requesting the IRQ fails and attempt to free the IRQ. + +This may end up with a warning from the IRQ core that is expecting the +affinity hint to be cleared before freeing the IRQ: + +kernel/irq/manage.c: + + /* make sure affinity_hint is cleaned up */ + if (WARN_ON_ONCE(desc->affinity_hint)) + desc->affinity_hint = NULL; + +So to fix this issue, clear the IRQ affinity hint before calling +ath12k_pci_free_irq() in the error path. The affinity will be cleared once +again further down the error path due to code organization, but that does +no harm. + +Fixes: a3012f206d07 ("wifi: ath12k: set IRQ affinity to CPU0 in case of one MSI vector") +Signed-off-by: Manivannan Sadhasivam +Reviewed-by: Baochen Qiang +Link: https://patch.msgid.link/20250225053447.16824-3-manivannan.sadhasivam@linaro.org +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/pci.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c +index 06cff3849ab8d..2851f6944b864 100644 +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -1689,6 +1689,8 @@ static int ath12k_pci_probe(struct pci_dev *pdev, + return 0; + + err_free_irq: ++ /* __free_irq() expects the caller to have cleared the affinity hint */ ++ ath12k_pci_set_irq_affinity_hint(ab_pci, NULL); + ath12k_pci_free_irq(ab); + + err_ce_free: +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-encode-max-tx-power-in-scan-channel-list.patch b/queue-6.14/wifi-ath12k-encode-max-tx-power-in-scan-channel-list.patch new file mode 100644 index 0000000000..4d66632435 --- /dev/null +++ b/queue-6.14/wifi-ath12k-encode-max-tx-power-in-scan-channel-list.patch @@ -0,0 +1,47 @@ +From 0883f642fde5db41a4f19fe29895858ff5acad19 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jan 2025 09:31:39 +0530 +Subject: wifi: ath12k: encode max Tx power in scan channel list command + +From: Sathishkumar Muruganandam + +[ Upstream commit 07c34cad10ab0ac8b06ede8a7fbc55ecf2efa3e6 ] + +Currently, when sending the scan channel list command to the firmware, the +maximum Tx power is not encoded in the reg2 member. This omission causes +the firmware to be unaware of the host's maximum Tx power, leading to +incorrect Tx power derivation at firmware level. + +To resolve this issue, encode the maximum Tx power in the scan channel list +command before sending it to firmware. + +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 + +Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices") +Signed-off-by: Sathishkumar Muruganandam +Signed-off-by: Aditya Kumar Singh +Tested-by: Nicolas Escande +Link: https://patch.msgid.link/20250107-add_max_reg_pwr_in_scan_ch_list_cmd-v1-1-70d9963a21e4@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/wmi.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index abb510d235a52..7a87777e0a047 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -2794,6 +2794,8 @@ int ath12k_wmi_send_scan_chan_list_cmd(struct ath12k *ar, + WMI_CHAN_REG_INFO1_REG_CLS); + *reg2 |= le32_encode_bits(channel_arg->antennamax, + WMI_CHAN_REG_INFO2_ANT_MAX); ++ *reg2 |= le32_encode_bits(channel_arg->maxregpower, ++ WMI_CHAN_REG_INFO2_MAX_TX_PWR); + + ath12k_dbg(ar->ab, ATH12K_DBG_WMI, + "WMI chan scan list chan[%d] = %u, chan_info->info %8x\n", +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-fix-locking-in-qmi-firmware-ready-error-.patch b/queue-6.14/wifi-ath12k-fix-locking-in-qmi-firmware-ready-error-.patch new file mode 100644 index 0000000000..58e25b7a6a --- /dev/null +++ b/queue-6.14/wifi-ath12k-fix-locking-in-qmi-firmware-ready-error-.patch @@ -0,0 +1,52 @@ +From 70bcf4f613ce834610c3f810ec237ce1786007e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 14:13:17 -0800 +Subject: wifi: ath12k: Fix locking in "QMI firmware ready" error paths + +From: Bart Van Assche + +[ Upstream commit b9c7299a3341a737622e4de45b9c27e60ad01e3b ] + +If ag->mutex has been locked, unlock it before returning. If it has not +been locked, do not unlock it before returning. These bugs have been +detected by the Clang thread-safety analyzer. + +Cc: Karthikeyan Periyasamy +Cc: Jeff Johnson +Fixes: ee146e11b4d9 ("wifi: ath12k: refactor core start based on hardware group") +Signed-off-by: Bart Van Assche +Reviewed-by: Aditya Kumar Singh +Link: https://patch.msgid.link/20250206221317.3845663-1-bvanassche@acm.org +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/core.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c +index 0606116d6b9c4..212cd935e60a0 100644 +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1122,16 +1122,18 @@ int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab) + ath12k_core_stop(ab); + mutex_unlock(&ab->core_lock); + } ++ mutex_unlock(&ag->mutex); + goto exit; + + err_dp_free: + ath12k_dp_free(ab); + mutex_unlock(&ab->core_lock); ++ mutex_unlock(&ag->mutex); ++ + err_firmware_stop: + ath12k_qmi_firmware_stop(ab); + + exit: +- mutex_unlock(&ag->mutex); + return ret; + } + +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-fix-pdev-lookup-in-wbm-error-processing.patch b/queue-6.14/wifi-ath12k-fix-pdev-lookup-in-wbm-error-processing.patch new file mode 100644 index 0000000000..5adec3359c --- /dev/null +++ b/queue-6.14/wifi-ath12k-fix-pdev-lookup-in-wbm-error-processing.patch @@ -0,0 +1,49 @@ +From 1b252edaf1105466e88f4c75bd0ab709d0d71e27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Jan 2025 10:00:48 +0530 +Subject: wifi: ath12k: Fix pdev lookup in WBM error processing + +From: Rameshkumar Sundaram + +[ Upstream commit 4e635b81db9d69bbb836afae8cb402978ff966a4 ] + +Currently in ath12k_dp_rx_process_wbm_err(), when processing packets +received on the WBM error ring, pdev validation is done based upon the +hw_link_id. But hw_link_id corresponds to link id of a given partner pdev +in a MLO hardware group, and is not the correct index to use to lookup a +pdev in an SoC(ab). As a result, pdev validation fails, and the reaped +packets are dropped instead of being processed. + +The correct index to use is the pdev_id, which is already derived in the +function. So update the logic to validate the pdev based upon the pdev_id +instead of the hw_link_id. This matches the logic used in other Rx ring +processing functions. + +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 + +Fixes: 1a73acb5fba4 ("wifi: ath12k: move to HW link id based receive handling") +Signed-off-by: Rameshkumar Sundaram +Link: https://patch.msgid.link/20250102043048.2596791-1-quic_ramess@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c +index dad35bfd83f62..68d609f2ac60e 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -4032,7 +4032,7 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab, + hw_links[hw_link_id].pdev_idx); + ar = partner_ab->pdevs[pdev_id].ar; + +- if (!ar || !rcu_dereference(ar->ab->pdevs_active[hw_link_id])) { ++ if (!ar || !rcu_dereference(ar->ab->pdevs_active[pdev_id])) { + dev_kfree_skb_any(msdu); + continue; + } +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-fix-skb_ext_desc-leak-in-ath12k_dp_tx-er.patch b/queue-6.14/wifi-ath12k-fix-skb_ext_desc-leak-in-ath12k_dp_tx-er.patch new file mode 100644 index 0000000000..8db8a466f5 --- /dev/null +++ b/queue-6.14/wifi-ath12k-fix-skb_ext_desc-leak-in-ath12k_dp_tx-er.patch @@ -0,0 +1,40 @@ +From 8f8eee6dcf2544224744ab627ef564717690f889 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 17:01:12 +0100 +Subject: wifi: ath12k: fix skb_ext_desc leak in ath12k_dp_tx() error path + +From: Nicolas Escande + +[ Upstream commit 28a9972e0f0693cd4d08f431c992fa6be39c788c ] + +When vlan support was added, we missed that when +ath12k_dp_prepare_htt_metadata() returns an error we also need to free +the skb holding the metadata before going on with the cleanup process. + +Compile tested only. + +Fixes: 26dd8ccdba4d ("wifi: ath12k: dynamic VLAN support") +Signed-off-by: Nicolas Escande +Reviewed-by: Aditya Kumar Singh +Link: https://patch.msgid.link/20250122160112.3234558-1-nico.escande@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index a8d341a6df01e..e0b85f959cd4a 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -398,6 +398,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, + if (ret < 0) { + ath12k_dbg(ab, ATH12K_DBG_DP_TX, + "Failed to add HTT meta data, dropping packet\n"); ++ kfree_skb(skb_ext_desc); + goto fail_unmap_dma; + } + } +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-use-link-specific-bss_conf-as-well-in-at.patch b/queue-6.14/wifi-ath12k-use-link-specific-bss_conf-as-well-in-at.patch new file mode 100644 index 0000000000..00b1335dba --- /dev/null +++ b/queue-6.14/wifi-ath12k-use-link-specific-bss_conf-as-well-in-at.patch @@ -0,0 +1,60 @@ +From ef21a8caf67a87bfb5ab7ae583a6e1dee4a63ce7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Dec 2024 10:41:46 +0800 +Subject: wifi: ath12k: use link specific bss_conf as well in + ath12k_mac_vif_cache_flush() + +From: Baochen Qiang + +[ Upstream commit 11d963d44c77261d6a948f3745bbd678eef4b83b ] + +Commit 3952657848c0 ("wifi: ath12k: Use mac80211 vif's link_conf instead of +bss_conf") aims at, where applicable, replacing all usage of vif's bss_conf +with link specific bss_conff, but missed one instance in +ath12k_mac_vif_cache_flush(). This results in wrong configurations passed +to ath12k_mac_bss_info_changed() when the link in question is not the default +link. + +Change to use the link specific bss_conf to fix this issue. + +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 + +Fixes: 3952657848c0 ("wifi: ath12k: Use mac80211 vif's link_conf instead of bss_conf") +Signed-off-by: Baochen Qiang +Link: https://patch.msgid.link/20241209024146.3282-1-quic_bqiang@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/mac.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 2d062b5904a8e..9c3e66dbe0c3b 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -8066,6 +8066,7 @@ static void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ath12k_link_vif + struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif); + struct ath12k_vif_cache *cache = ahvif->cache[arvif->link_id]; + struct ath12k_base *ab = ar->ab; ++ struct ieee80211_bss_conf *link_conf; + + int ret; + +@@ -8084,7 +8085,13 @@ static void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ath12k_link_vif + } + + if (cache->bss_conf_changed) { +- ath12k_mac_bss_info_changed(ar, arvif, &vif->bss_conf, ++ link_conf = ath12k_mac_get_link_bss_conf(arvif); ++ if (!link_conf) { ++ ath12k_warn(ar->ab, "unable to access bss link conf in cache flush for vif %pM link %u\n", ++ vif->addr, arvif->link_id); ++ return; ++ } ++ ath12k_mac_bss_info_changed(ar, arvif, link_conf, + cache->bss_conf_changed); + } + +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath9k-do-not-submit-zero-bytes-to-the-entropy-p.patch b/queue-6.14/wifi-ath9k-do-not-submit-zero-bytes-to-the-entropy-p.patch new file mode 100644 index 0000000000..b7f86af888 --- /dev/null +++ b/queue-6.14/wifi-ath9k-do-not-submit-zero-bytes-to-the-entropy-p.patch @@ -0,0 +1,49 @@ +From 39dff6eb61c5e9e53d1350b55aad78795453d6cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 17:10:58 +0300 +Subject: wifi: ath9k: do not submit zero bytes to the entropy pool +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Dmitry Antipov + +[ Upstream commit 0f2b59a98027a781eee1cbd48c7c8fdf87cb73f6 ] + +In 'ath_cmn_process_fft()', it doesn't make too much sense to +add zero bytes in attempt to improve randomness. So swap calls +to 'memset()' and 'add_device_randomness()' to feed the pool +with actual FFT results rather than zeroes. Compile tested only. + +Signed-off-by: Dmitry Antipov +Fixes: 2aa56cca3571 ("ath9k: Mix the received FFT bins to the random pool") +Acked-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20250123141058.1696502-1-dmantipov@yandex.ru +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/common-spectral.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c +index 628eeec4b82fe..300d178830adf 100644 +--- a/drivers/net/wireless/ath/ath9k/common-spectral.c ++++ b/drivers/net/wireless/ath/ath9k/common-spectral.c +@@ -628,12 +628,12 @@ int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_h + else + RX_STAT_INC(sc, rx_spectral_sample_err); + +- memset(sample_buf, 0, SPECTRAL_SAMPLE_MAX_LEN); +- + /* Mix the received bins to the /dev/random + * pool + */ + add_device_randomness(sample_buf, num_bins); ++ ++ memset(sample_buf, 0, SPECTRAL_SAMPLE_MAX_LEN); + } + + /* Process a normal frame */ +-- +2.39.5 + diff --git a/queue-6.14/wifi-cfg80211-init-wiphy_work-before-allocating-rfki.patch b/queue-6.14/wifi-cfg80211-init-wiphy_work-before-allocating-rfki.patch new file mode 100644 index 0000000000..4afb1908e9 --- /dev/null +++ b/queue-6.14/wifi-cfg80211-init-wiphy_work-before-allocating-rfki.patch @@ -0,0 +1,102 @@ +From 8a233cc96129532631e35584068ec464fe470c0f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 11:13:45 +0800 +Subject: wifi: cfg80211: init wiphy_work before allocating rfkill fails + +From: Edward Adam Davis + +[ Upstream commit fc88dee89d7b63eeb17699393eb659aadf9d9b7c ] + +syzbort reported a uninitialize wiphy_work_lock in cfg80211_dev_free. [1] + +After rfkill allocation fails, the wiphy release process will be performed, +which will cause cfg80211_dev_free to access the uninitialized wiphy_work +related data. + +Move the initialization of wiphy_work to before rfkill initialization to +avoid this issue. + +[1] +INFO: trying to register non-static key. +The code is fine but needs lockdep annotation, or maybe +you didn't initialize this object before use? +turning off the locking correctness validator. +CPU: 0 UID: 0 PID: 5935 Comm: syz-executor550 Not tainted 6.14.0-rc6-syzkaller-00103-g4003c9e78778 #0 +Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 +Call Trace: + + __dump_stack lib/dump_stack.c:94 [inline] + dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120 + assign_lock_key kernel/locking/lockdep.c:983 [inline] + register_lock_class+0xc39/0x1240 kernel/locking/lockdep.c:1297 + __lock_acquire+0x135/0x3c40 kernel/locking/lockdep.c:5103 + lock_acquire.part.0+0x11b/0x380 kernel/locking/lockdep.c:5851 + __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline] + _raw_spin_lock_irqsave+0x3a/0x60 kernel/locking/spinlock.c:162 + cfg80211_dev_free+0x30/0x3d0 net/wireless/core.c:1196 + device_release+0xa1/0x240 drivers/base/core.c:2568 + kobject_cleanup lib/kobject.c:689 [inline] + kobject_release lib/kobject.c:720 [inline] + kref_put include/linux/kref.h:65 [inline] + kobject_put+0x1e4/0x5a0 lib/kobject.c:737 + put_device+0x1f/0x30 drivers/base/core.c:3774 + wiphy_free net/wireless/core.c:1224 [inline] + wiphy_new_nm+0x1c1f/0x2160 net/wireless/core.c:562 + ieee80211_alloc_hw_nm+0x1b7a/0x2260 net/mac80211/main.c:835 + mac80211_hwsim_new_radio+0x1d6/0x54e0 drivers/net/wireless/virtual/mac80211_hwsim.c:5185 + hwsim_new_radio_nl+0xb42/0x12b0 drivers/net/wireless/virtual/mac80211_hwsim.c:6242 + genl_family_rcv_msg_doit+0x202/0x2f0 net/netlink/genetlink.c:1115 + genl_family_rcv_msg net/netlink/genetlink.c:1195 [inline] + genl_rcv_msg+0x565/0x800 net/netlink/genetlink.c:1210 + netlink_rcv_skb+0x16b/0x440 net/netlink/af_netlink.c:2533 + genl_rcv+0x28/0x40 net/netlink/genetlink.c:1219 + netlink_unicast_kernel net/netlink/af_netlink.c:1312 [inline] + netlink_unicast+0x53c/0x7f0 net/netlink/af_netlink.c:1338 + netlink_sendmsg+0x8b8/0xd70 net/netlink/af_netlink.c:1882 + sock_sendmsg_nosec net/socket.c:718 [inline] + __sock_sendmsg net/socket.c:733 [inline] + ____sys_sendmsg+0xaaf/0xc90 net/socket.c:2573 + ___sys_sendmsg+0x135/0x1e0 net/socket.c:2627 + __sys_sendmsg+0x16e/0x220 net/socket.c:2659 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xcd/0x250 arch/x86/entry/common.c:83 + +Fixes: 72d520476a2f ("wifi: cfg80211: cancel wiphy_work before freeing wiphy") +Reported-by: syzbot+aaf0488c83d1d5f4f029@syzkaller.appspotmail.com +Close: https://syzkaller.appspot.com/bug?extid=aaf0488c83d1d5f4f029 +Tested-by: syzbot+aaf0488c83d1d5f4f029@syzkaller.appspotmail.com +Signed-off-by: Edward Adam Davis +Link: https://patch.msgid.link/tencent_258DD9121DDDB9DD9A1939CFAA0D8625B107@qq.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/core.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 828e298726335..ceb768925b850 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -546,6 +546,9 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, + INIT_WORK(&rdev->mgmt_registrations_update_wk, + cfg80211_mgmt_registrations_update_wk); + spin_lock_init(&rdev->mgmt_registrations_lock); ++ INIT_WORK(&rdev->wiphy_work, cfg80211_wiphy_work); ++ INIT_LIST_HEAD(&rdev->wiphy_work_list); ++ spin_lock_init(&rdev->wiphy_work_lock); + + #ifdef CONFIG_CFG80211_DEFAULT_PS + rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; +@@ -563,9 +566,6 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, + return NULL; + } + +- INIT_WORK(&rdev->wiphy_work, cfg80211_wiphy_work); +- INIT_LIST_HEAD(&rdev->wiphy_work_list); +- spin_lock_init(&rdev->wiphy_work_lock); + INIT_WORK(&rdev->rfkill_block, cfg80211_rfkill_block_work); + INIT_WORK(&rdev->conn_work, cfg80211_conn_work); + INIT_WORK(&rdev->event_work, cfg80211_event_work); +-- +2.39.5 + diff --git a/queue-6.14/wifi-mac80211-check-basic-rates-validity-in-sta_link.patch b/queue-6.14/wifi-mac80211-check-basic-rates-validity-in-sta_link.patch new file mode 100644 index 0000000000..a8016bac74 --- /dev/null +++ b/queue-6.14/wifi-mac80211-check-basic-rates-validity-in-sta_link.patch @@ -0,0 +1,59 @@ +From c9d92e4dcd0ba66d604e635bc21c4efb5d0e20c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 13:31:37 +0300 +Subject: wifi: mac80211: check basic rates validity in + sta_link_apply_parameters + +From: Mikhail Lobanov + +[ Upstream commit 16ee3ea8faef8ff042acc15867a6c458c573de61 ] + +When userspace sets supported rates for a new station via +NL80211_CMD_NEW_STATION, it might send a list that's empty +or contains only invalid values. Currently, we process these +values in sta_link_apply_parameters() without checking the result of +ieee80211_parse_bitrates(), which can lead to an empty rates bitmap. + +A similar issue was addressed for NL80211_CMD_SET_BSS in commit +ce04abc3fcc6 ("wifi: mac80211: check basic rates validity"). +This patch applies the same approach in sta_link_apply_parameters() +for NL80211_CMD_NEW_STATION, ensuring there is at least one valid +rate by inspecting the result of ieee80211_parse_bitrates(). + +Found by Linux Verification Center (linuxtesting.org) with Syzkaller. + +Fixes: b95eb7f0eee4 ("wifi: cfg80211/mac80211: separate link params from station params") +Signed-off-by: Mikhail Lobanov +Link: https://patch.msgid.link/20250317103139.17625-1-m.lobanov@rosa.ru +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/cfg.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index 9351c64608a99..b766472703b12 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1908,12 +1908,12 @@ static int sta_link_apply_parameters(struct ieee80211_local *local, + } + + if (params->supported_rates && +- params->supported_rates_len) { +- ieee80211_parse_bitrates(link->conf->chanreq.oper.width, +- sband, params->supported_rates, +- params->supported_rates_len, +- &link_sta->pub->supp_rates[sband->band]); +- } ++ params->supported_rates_len && ++ !ieee80211_parse_bitrates(link->conf->chanreq.oper.width, ++ sband, params->supported_rates, ++ params->supported_rates_len, ++ &link_sta->pub->supp_rates[sband->band])) ++ return -EINVAL; + + if (params->ht_capa) + ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, +-- +2.39.5 + diff --git a/queue-6.14/wifi-mac80211-remove-ssid-from-ml-reconf.patch b/queue-6.14/wifi-mac80211-remove-ssid-from-ml-reconf.patch new file mode 100644 index 0000000000..e7aabd8682 --- /dev/null +++ b/queue-6.14/wifi-mac80211-remove-ssid-from-ml-reconf.patch @@ -0,0 +1,51 @@ +From 0348083224d2b2ae529cc2013e570f7245eeb89d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 12:10:03 +0100 +Subject: wifi: mac80211: remove SSID from ML reconf + +From: Johannes Berg + +[ Upstream commit 899da1830db112e6bd54ed4573ace753eae6ef22 ] + +The ML reconfiguration frame shouldn't contain an SSID, +remove it. + +Fixes: 36e05b0b8390 ("wifi: mac80211: Support dynamic link addition and removal") +Reviewed-by: Ilan Peer +Link: https://patch.msgid.link/20250311121004.fdf08f90bc30.I07f88d3a6f592a0df65d48f55d65c46a4d261007@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/mlme.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 36a9be9a66c8e..da2c2e6035be8 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -9946,8 +9946,8 @@ ieee80211_build_ml_reconf_req(struct ieee80211_sub_if_data *sdata, + size += 2 + sizeof(struct ieee80211_mle_per_sta_profile) + + ETH_ALEN; + +- /* SSID element + WMM */ +- size += 2 + sdata->vif.cfg.ssid_len + 9; ++ /* WMM */ ++ size += 9; + size += ieee80211_link_common_elems_size(sdata, iftype, cbss, + elems_len); + } +@@ -10053,11 +10053,6 @@ ieee80211_build_ml_reconf_req(struct ieee80211_sub_if_data *sdata, + + capab_pos = skb_put(skb, 2); + +- skb_put_u8(skb, WLAN_EID_SSID); +- skb_put_u8(skb, sdata->vif.cfg.ssid_len); +- skb_put_data(skb, sdata->vif.cfg.ssid, +- sdata->vif.cfg.ssid_len); +- + extra_used = + ieee80211_add_link_elems(sdata, skb, &capab, NULL, + add_links_data->link[link_id].elems, +-- +2.39.5 + diff --git a/queue-6.14/wifi-mt76-mt7915-fix-possible-integer-overflows-in-m.patch b/queue-6.14/wifi-mt76-mt7915-fix-possible-integer-overflows-in-m.patch new file mode 100644 index 0000000000..aff1d5d3a8 --- /dev/null +++ b/queue-6.14/wifi-mt76-mt7915-fix-possible-integer-overflows-in-m.patch @@ -0,0 +1,118 @@ +From 5b0e3976f3482ab322e45f57b6ae1e8ba02a06d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jan 2025 07:44:41 -0800 +Subject: wifi: mt76: mt7915: fix possible integer overflows in + mt7915_muru_stats_show() + +From: Nikita Zhandarovich + +[ Upstream commit 77b749520cac06d000d9923f79ffa632cdea6113 ] + +Assuming sums of values stored in variables such as sub_total_cnt +and total_ppdu_cnt are big enough to warrant their u64 type, it +makes sense to ensure that their calculation takes into account +possible integer overflow issues. + +Play it safe and fix the problem by casting right hand expressions +to u64 as well. Also, slightly adjust tabulation. + +Found by Linux Verification Center (linuxtesting.org) with static +analysis tool SVACE. + +Fixes: 1966a5078f2d ("mt76: mt7915: add mu-mimo and ofdma debugfs knobs") +Signed-off-by: Nikita Zhandarovich +Link: https://patch.msgid.link/20250114154441.16920-1-n.zhandarovich@fintech.ru +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + .../wireless/mediatek/mt76/mt7915/debugfs.c | 45 ++++++++++--------- + 1 file changed, 23 insertions(+), 22 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +index 578013884e438..4fec7d000a631 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +@@ -303,9 +303,9 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) + phy->mib.dl_vht_3mu_cnt, + phy->mib.dl_vht_4mu_cnt); + +- sub_total_cnt = phy->mib.dl_vht_2mu_cnt + +- phy->mib.dl_vht_3mu_cnt + +- phy->mib.dl_vht_4mu_cnt; ++ sub_total_cnt = (u64)phy->mib.dl_vht_2mu_cnt + ++ phy->mib.dl_vht_3mu_cnt + ++ phy->mib.dl_vht_4mu_cnt; + + seq_printf(file, "\nTotal non-HE MU-MIMO DL PPDU count: %lld", + sub_total_cnt); +@@ -353,26 +353,27 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) + phy->mib.dl_he_9to16ru_cnt, + phy->mib.dl_he_gtr16ru_cnt); + +- sub_total_cnt = phy->mib.dl_he_2mu_cnt + +- phy->mib.dl_he_3mu_cnt + +- phy->mib.dl_he_4mu_cnt; ++ sub_total_cnt = (u64)phy->mib.dl_he_2mu_cnt + ++ phy->mib.dl_he_3mu_cnt + ++ phy->mib.dl_he_4mu_cnt; + total_ppdu_cnt = sub_total_cnt; + + seq_printf(file, "\nTotal HE MU-MIMO DL PPDU count: %lld", + sub_total_cnt); + +- sub_total_cnt = phy->mib.dl_he_2ru_cnt + +- phy->mib.dl_he_3ru_cnt + +- phy->mib.dl_he_4ru_cnt + +- phy->mib.dl_he_5to8ru_cnt + +- phy->mib.dl_he_9to16ru_cnt + +- phy->mib.dl_he_gtr16ru_cnt; ++ sub_total_cnt = (u64)phy->mib.dl_he_2ru_cnt + ++ phy->mib.dl_he_3ru_cnt + ++ phy->mib.dl_he_4ru_cnt + ++ phy->mib.dl_he_5to8ru_cnt + ++ phy->mib.dl_he_9to16ru_cnt + ++ phy->mib.dl_he_gtr16ru_cnt; + total_ppdu_cnt += sub_total_cnt; + + seq_printf(file, "\nTotal HE OFDMA DL PPDU count: %lld", + sub_total_cnt); + +- total_ppdu_cnt += phy->mib.dl_he_su_cnt + phy->mib.dl_he_ext_su_cnt; ++ total_ppdu_cnt += (u64)phy->mib.dl_he_su_cnt + ++ phy->mib.dl_he_ext_su_cnt; + + seq_printf(file, "\nAll HE DL PPDU count: %lld", total_ppdu_cnt); + +@@ -404,20 +405,20 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) + phy->mib.ul_hetrig_9to16ru_cnt, + phy->mib.ul_hetrig_gtr16ru_cnt); + +- sub_total_cnt = phy->mib.ul_hetrig_2mu_cnt + +- phy->mib.ul_hetrig_3mu_cnt + +- phy->mib.ul_hetrig_4mu_cnt; ++ sub_total_cnt = (u64)phy->mib.ul_hetrig_2mu_cnt + ++ phy->mib.ul_hetrig_3mu_cnt + ++ phy->mib.ul_hetrig_4mu_cnt; + total_ppdu_cnt = sub_total_cnt; + + seq_printf(file, "\nTotal HE MU-MIMO UL TB PPDU count: %lld", + sub_total_cnt); + +- sub_total_cnt = phy->mib.ul_hetrig_2ru_cnt + +- phy->mib.ul_hetrig_3ru_cnt + +- phy->mib.ul_hetrig_4ru_cnt + +- phy->mib.ul_hetrig_5to8ru_cnt + +- phy->mib.ul_hetrig_9to16ru_cnt + +- phy->mib.ul_hetrig_gtr16ru_cnt; ++ sub_total_cnt = (u64)phy->mib.ul_hetrig_2ru_cnt + ++ phy->mib.ul_hetrig_3ru_cnt + ++ phy->mib.ul_hetrig_4ru_cnt + ++ phy->mib.ul_hetrig_5to8ru_cnt + ++ phy->mib.ul_hetrig_9to16ru_cnt + ++ phy->mib.ul_hetrig_gtr16ru_cnt; + total_ppdu_cnt += sub_total_cnt; + + seq_printf(file, "\nTotal HE OFDMA UL TB PPDU count: %lld", +-- +2.39.5 + diff --git a/queue-6.14/wifi-mwifiex-fix-premature-release-of-rf-calibration.patch b/queue-6.14/wifi-mwifiex-fix-premature-release-of-rf-calibration.patch new file mode 100644 index 0000000000..0c182951e9 --- /dev/null +++ b/queue-6.14/wifi-mwifiex-fix-premature-release-of-rf-calibration.patch @@ -0,0 +1,61 @@ +From 70898ff8c56b71e9a755fec89b063c70e2f4bb22 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 13:07:38 +0800 +Subject: wifi: mwifiex: Fix premature release of RF calibration data. + +From: Jeff Chen + +[ Upstream commit 69ae7e1f73abae20f26e3536ca4a980b90eafeb7 ] + +This patch resolves an issue where RF calibration data was being +released before the download process. Without this fix, the +external calibration data file would not be downloaded +at all. + +Fixes: d39fbc88956e ("mwifiex: remove cfg_data construction") +Signed-off-by: Jeff Chen +Link: https://patch.msgid.link/20250318050739.2239376-2-jeff.chen_1@nxp.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/marvell/mwifiex/main.c | 4 ---- + drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 6 +++++- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c +index 855019fe54858..80fc6d5afe860 100644 +--- a/drivers/net/wireless/marvell/mwifiex/main.c ++++ b/drivers/net/wireless/marvell/mwifiex/main.c +@@ -691,10 +691,6 @@ static int _mwifiex_fw_dpc(const struct firmware *firmware, void *context) + + init_failed = true; + done: +- if (adapter->cal_data) { +- release_firmware(adapter->cal_data); +- adapter->cal_data = NULL; +- } + if (adapter->firmware) { + release_firmware(adapter->firmware); + adapter->firmware = NULL; +diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c +index e2800a831c8ed..c0e6ce1a82fed 100644 +--- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c ++++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c +@@ -2293,9 +2293,13 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) + "marvell,caldata"); + } + +- if (adapter->cal_data) ++ if (adapter->cal_data) { + mwifiex_send_cmd(priv, HostCmd_CMD_CFG_DATA, + HostCmd_ACT_GEN_SET, 0, NULL, true); ++ release_firmware(adapter->cal_data); ++ adapter->cal_data = NULL; ++ } ++ + + /* Read MAC address from HW */ + ret = mwifiex_send_cmd(priv, HostCmd_CMD_GET_HW_SPEC, +-- +2.39.5 + diff --git a/queue-6.14/wifi-mwifiex-fix-rf-calibration-data-download-from-f.patch b/queue-6.14/wifi-mwifiex-fix-rf-calibration-data-download-from-f.patch new file mode 100644 index 0000000000..121493f140 --- /dev/null +++ b/queue-6.14/wifi-mwifiex-fix-rf-calibration-data-download-from-f.patch @@ -0,0 +1,118 @@ +From ca074d2592a8a84711dd313ff53f6d65ba9d3734 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 13:07:39 +0800 +Subject: wifi: mwifiex: Fix RF calibration data download from file + +From: Jeff Chen + +[ Upstream commit 9868c4ce9481043d6c11f7421fe2b9637aa0feee ] + +This patch resolves an issue where RF calibration data from a +file could not be downloaded to the firmware. The feature to +download calibration data from a file was broken by the commit: +d39fbc88956e. + +The issue arose because the function `mwifiex_cmd_cfg_data()` +was modified in a way that prevented proper handling of +file-based calibration data. While this patch restores the ability +to download RF calibration data from a file, it may inadvertently +break the feature to download calibration data from the device +tree. This is because the function `mwifiex_dnld_dt_cfgdata()`, +which also relies on `mwifiex_cmd_cfg_data()`, is still used for +device tree-based calibration data downloads. + +Fixes: d39fbc88956e ("mwifiex: remove cfg_data construction") +Signed-off-by: Jeff Chen +Link: https://patch.msgid.link/20250318050739.2239376-3-jeff.chen_1@nxp.com +[add newline for shorter lines] +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/marvell/mwifiex/fw.h | 14 ++++++++++++++ + drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 12 ++++++++++-- + 2 files changed, 24 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h +index 4a96281792cc1..91458f3bd14a5 100644 +--- a/drivers/net/wireless/marvell/mwifiex/fw.h ++++ b/drivers/net/wireless/marvell/mwifiex/fw.h +@@ -454,6 +454,11 @@ enum mwifiex_channel_flags { + #define HostCmd_RET_BIT 0x8000 + #define HostCmd_ACT_GEN_GET 0x0000 + #define HostCmd_ACT_GEN_SET 0x0001 ++#define HOST_CMD_ACT_GEN_SET 0x0001 ++/* Add this non-CamelCase-style macro to comply with checkpatch requirements. ++ * This macro will eventually replace all existing CamelCase-style macros in ++ * the future for consistency. ++ */ + #define HostCmd_ACT_GEN_REMOVE 0x0004 + #define HostCmd_ACT_BITWISE_SET 0x0002 + #define HostCmd_ACT_BITWISE_CLR 0x0003 +@@ -2352,6 +2357,14 @@ struct host_cmd_ds_add_station { + u8 tlv[]; + } __packed; + ++#define MWIFIEX_CFG_TYPE_CAL 0x2 ++ ++struct host_cmd_ds_802_11_cfg_data { ++ __le16 action; ++ __le16 type; ++ __le16 data_len; ++} __packed; ++ + struct host_cmd_ds_command { + __le16 command; + __le16 size; +@@ -2431,6 +2444,7 @@ struct host_cmd_ds_command { + struct host_cmd_ds_pkt_aggr_ctrl pkt_aggr_ctrl; + struct host_cmd_ds_sta_configure sta_cfg; + struct host_cmd_ds_add_station sta_info; ++ struct host_cmd_ds_802_11_cfg_data cfg_data; + } params; + } __packed; + +diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c +index c0e6ce1a82fed..c4689f5a1acc8 100644 +--- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c ++++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c +@@ -1507,6 +1507,7 @@ static int mwifiex_cmd_cfg_data(struct mwifiex_private *priv, + u32 len; + u8 *data = (u8 *)cmd + S_DS_GEN; + int ret; ++ struct host_cmd_ds_802_11_cfg_data *pcfg_data; + + if (prop) { + len = prop->length; +@@ -1514,12 +1515,20 @@ static int mwifiex_cmd_cfg_data(struct mwifiex_private *priv, + data, len); + if (ret) + return ret; ++ ++ cmd->size = cpu_to_le16(S_DS_GEN + len); + mwifiex_dbg(adapter, INFO, + "download cfg_data from device tree: %s\n", + prop->name); + } else if (adapter->cal_data->data && adapter->cal_data->size > 0) { + len = mwifiex_parse_cal_cfg((u8 *)adapter->cal_data->data, +- adapter->cal_data->size, data); ++ adapter->cal_data->size, ++ data + sizeof(*pcfg_data)); ++ pcfg_data = &cmd->params.cfg_data; ++ pcfg_data->action = cpu_to_le16(HOST_CMD_ACT_GEN_SET); ++ pcfg_data->type = cpu_to_le16(MWIFIEX_CFG_TYPE_CAL); ++ pcfg_data->data_len = cpu_to_le16(len); ++ cmd->size = cpu_to_le16(S_DS_GEN + sizeof(*pcfg_data) + len); + mwifiex_dbg(adapter, INFO, + "download cfg_data from config file\n"); + } else { +@@ -1527,7 +1536,6 @@ static int mwifiex_cmd_cfg_data(struct mwifiex_private *priv, + } + + cmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA); +- cmd->size = cpu_to_le16(S_DS_GEN + len); + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/wifi-nl80211-store-chandef-on-the-correct-link-when-.patch b/queue-6.14/wifi-nl80211-store-chandef-on-the-correct-link-when-.patch new file mode 100644 index 0000000000..e32ae8338e --- /dev/null +++ b/queue-6.14/wifi-nl80211-store-chandef-on-the-correct-link-when-.patch @@ -0,0 +1,38 @@ +From d37109b307a1c98b57af7fb79e75c0865bff45ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 09:38:53 +0530 +Subject: wifi: nl80211: store chandef on the correct link when starting CAC + +From: Aditya Kumar Singh + +[ Upstream commit ea841520c50f5f7c72c8070e3b79e1927b94fabf ] + +Link ID to store chandef is still being used as 0 even in case of MLO which +is incorrect. This leads to issue during CAC completion where link 0 as well +gets stopped. + +Fixes: 0b7798232eee ("wifi: cfg80211/mac80211: use proper link ID for DFS") +Signed-off-by: Aditya Kumar Singh +Link: https://patch.msgid.link/20250314-fix_starting_cac_during_mlo-v1-1-3b51617d7ea5@oss.qualcomm.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index aac0e7298dc7a..b457fe78672b7 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -10172,7 +10172,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, + switch (wdev->iftype) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: +- wdev->links[0].ap.chandef = chandef; ++ wdev->links[link_id].ap.chandef = chandef; + break; + case NL80211_IFTYPE_ADHOC: + wdev->u.ibss.chandef = chandef; +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw89-correct-immediate-cfg_len-calculation-for.patch b/queue-6.14/wifi-rtw89-correct-immediate-cfg_len-calculation-for.patch new file mode 100644 index 0000000000..94cf47b7c1 --- /dev/null +++ b/queue-6.14/wifi-rtw89-correct-immediate-cfg_len-calculation-for.patch @@ -0,0 +1,73 @@ +From 5eaab707646c8ebda061147694c8ca50a6ff31ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jan 2025 18:51:44 +0800 +Subject: wifi: rtw89: Correct immediate cfg_len calculation for + scan_offload_be + +From: Liang Jie + +[ Upstream commit 361cb056e2468be534f47c1a6745f96581a721e3 ] + +Ensures the correct calculation of `cfg_len` prior to the allocation of +the skb in the `rtw89_fw_h2c_scan_offload_be` function, particularly when +the `SCAN_OFFLOAD_BE_V0` firmware feature is enabled. It addresses an +issue where an incorrect skb size might be allocated due to a delayed +setting of `cfg_len`, potentially leading to memory inefficiencies. + +By moving the conditional check and assignment of `cfg_len` before skb +allocation, the patch guarantees that `len`, which depends on `cfg_len`, +is accurately computed, ensuring proper skb size and preventing any +unnecessary memory reservation for firmware operations not supporting +beyond the `w8` member of the command data structure. + +This correction helps to optimize memory usage and maintain consistent +behavior across different firmware versions. + +Fixes: 6ca6b918f280 ("wifi: rtw89: 8922a: Add new fields for scan offload H2C command") +Signed-off-by: Liang Jie +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250112105144.615474-1-buaajxlj@163.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/fw.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index 5d4ad23cc3bd4..5cc9ab78c09f7 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -5311,6 +5311,7 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, + u8 macc_role_size = sizeof(*macc_role) * option->num_macc_role; + u8 opch_size = sizeof(*opch) * option->num_opch; + u8 probe_id[NUM_NL80211_BANDS]; ++ u8 scan_offload_ver = U8_MAX; + u8 cfg_len = sizeof(*h2c); + unsigned int cond; + u8 ver = U8_MAX; +@@ -5321,6 +5322,11 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, + + rtw89_scan_get_6g_disabled_chan(rtwdev, option); + ++ if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD_BE_V0, &rtwdev->fw)) { ++ cfg_len = offsetofend(typeof(*h2c), w8); ++ scan_offload_ver = 0; ++ } ++ + len = cfg_len + macc_role_size + opch_size; + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { +@@ -5392,10 +5398,8 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, + RTW89_H2C_SCANOFLD_BE_W8_PROBE_RATE_6GHZ); + } + +- if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD_BE_V0, &rtwdev->fw)) { +- cfg_len = offsetofend(typeof(*h2c), w8); ++ if (scan_offload_ver == 0) + goto flex_member; +- } + + h2c->w9 = le32_encode_bits(sizeof(*h2c) / sizeof(h2c->w0), + RTW89_H2C_SCANOFLD_BE_W9_SIZE_CFG) | +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw89-fw-correct-debug-message-format-in-rtw89_.patch b/queue-6.14/wifi-rtw89-fw-correct-debug-message-format-in-rtw89_.patch new file mode 100644 index 0000000000..b05610ab03 --- /dev/null +++ b/queue-6.14/wifi-rtw89-fw-correct-debug-message-format-in-rtw89_.patch @@ -0,0 +1,36 @@ +From 104122dc111f10adbbb4984c5569721c062ae9c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 21:12:27 +0800 +Subject: wifi: rtw89: fw: correct debug message format in + rtw89_build_txpwr_trk_tbl_from_elm() + +From: Ping-Ke Shih + +[ Upstream commit 88b46320fc9d915aa0c1c765db5ccd2db12fe92e ] + +The format should be "%08x". Fix the mistakes. + +Fixes: d60e73e5dd70 ("wifi: rtw89: fw: load TX power track tables from fw_element") +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250227131228.8457-4-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 5cc9ab78c09f7..2f3869c700696 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -988,7 +988,7 @@ int rtw89_build_txpwr_trk_tbl_from_elm(struct rtw89_dev *rtwdev, + bitmap = le32_to_cpu(elm->u.txpwr_trk.bitmap); + + if ((bitmap & needed_bitmap) != needed_bitmap) { +- rtw89_warn(rtwdev, "needed txpwr trk bitmap %08x but %0x8x\n", ++ rtw89_warn(rtwdev, "needed txpwr trk bitmap %08x but %08x\n", + needed_bitmap, bitmap); + return -ENOENT; + } +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw89-pci-correct-isr-rdu-bit-for-8922ae.patch b/queue-6.14/wifi-rtw89-pci-correct-isr-rdu-bit-for-8922ae.patch new file mode 100644 index 0000000000..7d78db938a --- /dev/null +++ b/queue-6.14/wifi-rtw89-pci-correct-isr-rdu-bit-for-8922ae.patch @@ -0,0 +1,107 @@ +From 8161ad377ca715d39b8f70b65fb2e812399bbcd7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 21:19:07 +0800 +Subject: wifi: rtw89: pci: correct ISR RDU bit for 8922AE + +From: Ping-Ke Shih + +[ Upstream commit 3218f5bd8e2e4abc156493f8121b8db53b49ee9e ] + +The interrupt status (ISR) bits of RX desc unavailable (RDU) for 8922AE +are B_BE_RDU_CH1_INT_V1 and B_BE_RDU_CH0_INT_V1. With wrong bits, if it +happens, driver can't recognize the situation and prompt a message. +Fix the definition accordingly. + +Fixes: aa70f76120ee ("wifi: rtw89: pci: generalize interrupt status bits of interrupt handlers") +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250227131907.9864-1-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/pci.h | 56 +++++++++++---------- + drivers/net/wireless/realtek/rtw89/pci_be.c | 2 +- + 2 files changed, 30 insertions(+), 28 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h +index 4d11c3dd60a5d..79fef5f901408 100644 +--- a/drivers/net/wireless/realtek/rtw89/pci.h ++++ b/drivers/net/wireless/realtek/rtw89/pci.h +@@ -455,34 +455,36 @@ + #define B_BE_RX0DMA_INT_EN BIT(0) + + #define R_BE_HAXI_HISR00 0xB0B4 +-#define B_BE_RDU_CH6_INT BIT(28) +-#define B_BE_RDU_CH5_INT BIT(27) +-#define B_BE_RDU_CH4_INT BIT(26) +-#define B_BE_RDU_CH2_INT BIT(25) +-#define B_BE_RDU_CH1_INT BIT(24) +-#define B_BE_RDU_CH0_INT BIT(23) +-#define B_BE_RXDMA_STUCK_INT BIT(22) +-#define B_BE_TXDMA_STUCK_INT BIT(21) +-#define B_BE_TXDMA_CH14_INT BIT(20) +-#define B_BE_TXDMA_CH13_INT BIT(19) +-#define B_BE_TXDMA_CH12_INT BIT(18) +-#define B_BE_TXDMA_CH11_INT BIT(17) +-#define B_BE_TXDMA_CH10_INT BIT(16) +-#define B_BE_TXDMA_CH9_INT BIT(15) +-#define B_BE_TXDMA_CH8_INT BIT(14) +-#define B_BE_TXDMA_CH7_INT BIT(13) +-#define B_BE_TXDMA_CH6_INT BIT(12) +-#define B_BE_TXDMA_CH5_INT BIT(11) +-#define B_BE_TXDMA_CH4_INT BIT(10) +-#define B_BE_TXDMA_CH3_INT BIT(9) +-#define B_BE_TXDMA_CH2_INT BIT(8) +-#define B_BE_TXDMA_CH1_INT BIT(7) +-#define B_BE_TXDMA_CH0_INT BIT(6) +-#define B_BE_RPQ1DMA_INT BIT(5) +-#define B_BE_RX1P1DMA_INT BIT(4) ++#define B_BE_RDU_CH5_INT_V1 BIT(30) ++#define B_BE_RDU_CH4_INT_V1 BIT(29) ++#define B_BE_RDU_CH3_INT_V1 BIT(28) ++#define B_BE_RDU_CH2_INT_V1 BIT(27) ++#define B_BE_RDU_CH1_INT_V1 BIT(26) ++#define B_BE_RDU_CH0_INT_V1 BIT(25) ++#define B_BE_RXDMA_STUCK_INT_V1 BIT(24) ++#define B_BE_TXDMA_STUCK_INT_V1 BIT(23) ++#define B_BE_TXDMA_CH14_INT_V1 BIT(22) ++#define B_BE_TXDMA_CH13_INT_V1 BIT(21) ++#define B_BE_TXDMA_CH12_INT_V1 BIT(20) ++#define B_BE_TXDMA_CH11_INT_V1 BIT(19) ++#define B_BE_TXDMA_CH10_INT_V1 BIT(18) ++#define B_BE_TXDMA_CH9_INT_V1 BIT(17) ++#define B_BE_TXDMA_CH8_INT_V1 BIT(16) ++#define B_BE_TXDMA_CH7_INT_V1 BIT(15) ++#define B_BE_TXDMA_CH6_INT_V1 BIT(14) ++#define B_BE_TXDMA_CH5_INT_V1 BIT(13) ++#define B_BE_TXDMA_CH4_INT_V1 BIT(12) ++#define B_BE_TXDMA_CH3_INT_V1 BIT(11) ++#define B_BE_TXDMA_CH2_INT_V1 BIT(10) ++#define B_BE_TXDMA_CH1_INT_V1 BIT(9) ++#define B_BE_TXDMA_CH0_INT_V1 BIT(8) ++#define B_BE_RX1P1DMA_INT_V1 BIT(7) ++#define B_BE_RX0P1DMA_INT_V1 BIT(6) ++#define B_BE_RO1DMA_INT BIT(5) ++#define B_BE_RP1DMA_INT BIT(4) + #define B_BE_RX1DMA_INT BIT(3) +-#define B_BE_RPQ0DMA_INT BIT(2) +-#define B_BE_RX0P1DMA_INT BIT(1) ++#define B_BE_RO0DMA_INT BIT(2) ++#define B_BE_RP0DMA_INT BIT(1) + #define B_BE_RX0DMA_INT BIT(0) + + /* TX/RX */ +diff --git a/drivers/net/wireless/realtek/rtw89/pci_be.c b/drivers/net/wireless/realtek/rtw89/pci_be.c +index cd39eebe81861..12e6a0cbb889b 100644 +--- a/drivers/net/wireless/realtek/rtw89/pci_be.c ++++ b/drivers/net/wireless/realtek/rtw89/pci_be.c +@@ -666,7 +666,7 @@ SIMPLE_DEV_PM_OPS(rtw89_pm_ops_be, rtw89_pci_suspend_be, rtw89_pci_resume_be); + EXPORT_SYMBOL(rtw89_pm_ops_be); + + const struct rtw89_pci_gen_def rtw89_pci_gen_be = { +- .isr_rdu = B_BE_RDU_CH1_INT | B_BE_RDU_CH0_INT, ++ .isr_rdu = B_BE_RDU_CH1_INT_V1 | B_BE_RDU_CH0_INT_V1, + .isr_halt_c2h = B_BE_HALT_C2H_INT, + .isr_wdt_timeout = B_BE_WDT_TIMEOUT_INT, + .isr_clear_rpq = {R_BE_PCIE_DMA_ISR, B_BE_PCIE_RX_RPQ0_ISR_V1}, +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw89-rtw8852b-t-fix-tssi-debug-timestamps.patch b/queue-6.14/wifi-rtw89-rtw8852b-t-fix-tssi-debug-timestamps.patch new file mode 100644 index 0000000000..e1d326fd25 --- /dev/null +++ b/queue-6.14/wifi-rtw89-rtw8852b-t-fix-tssi-debug-timestamps.patch @@ -0,0 +1,125 @@ +From fa2b24dc9ce9d0c06fe2a30c3f85af78e5ebeb50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 12:50:06 +0300 +Subject: wifi: rtw89: rtw8852b{t}: fix TSSI debug timestamps + +From: Dmitry Antipov + +[ Upstream commit bfc8e71ef6b7913f0129aff47951cab73a175259 ] + +Since the vendor driver is claimed to measure 'tssi_alimk_time' of +'struct rtw89_tssi_info' in microseconds, adjust rtw8852b{t}-specific +'_tssi_alimentk()' to not mess the former with nanoseconds and print +both per-call and accumulated times. Compile tested only. + +Fixes: 7f18a70d7b4d ("wifi: rtw89: 8852b: rfk: add TSSI") +Signed-off-by: Dmitry Antipov +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250213095006.1308810-1-dmantipov@yandex.ru +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/core.h | 2 +- + drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c | 13 +++++++------ + drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.c | 13 +++++++------ + 3 files changed, 15 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h +index ff4894c7fa8a5..93e41def81b40 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.h ++++ b/drivers/net/wireless/realtek/rtw89/core.h +@@ -5135,7 +5135,7 @@ struct rtw89_tssi_info { + u32 alignment_backup_by_ch[RF_PATH_MAX][TSSI_MAX_CH_NUM][TSSI_ALIMK_VALUE_NUM]; + u32 alignment_value[RF_PATH_MAX][TSSI_ALIMK_MAX][TSSI_ALIMK_VALUE_NUM]; + bool alignment_done[RF_PATH_MAX][TSSI_ALIMK_MAX]; +- u32 tssi_alimk_time; ++ u64 tssi_alimk_time; + }; + + struct rtw89_power_trim_info { +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c +index ef47a5facc836..fbf82d42687ba 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c +@@ -3585,9 +3585,10 @@ static void _tssi_alimentk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + u8 ch_idx = _tssi_ch_to_idx(rtwdev, channel); + struct rtw8852bx_bb_tssi_bak tssi_bak; + s32 aliment_diff, tssi_cw_default; +- u32 start_time, finish_time; + u32 bb_reg_backup[8] = {0}; ++ ktime_t start_time; + const s16 *power; ++ s64 this_time; + u8 band; + bool ok; + u32 tmp; +@@ -3613,7 +3614,7 @@ static void _tssi_alimentk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + return; + } + +- start_time = ktime_get_ns(); ++ start_time = ktime_get(); + + if (chan->band_type == RTW89_BAND_2G) + power = power_2g; +@@ -3738,12 +3739,12 @@ static void _tssi_alimentk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + rtw8852bx_bb_restore_tssi(rtwdev, phy, &tssi_bak); + rtw8852bx_bb_tx_mode_switch(rtwdev, phy, 0); + +- finish_time = ktime_get_ns(); +- tssi_info->tssi_alimk_time += finish_time - start_time; ++ this_time = ktime_us_delta(ktime_get(), start_time); ++ tssi_info->tssi_alimk_time += this_time; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, +- "[TSSI PA K] %s processing time = %d ms\n", __func__, +- tssi_info->tssi_alimk_time); ++ "[TSSI PA K] %s processing time = %lld us (acc = %llu us)\n", ++ __func__, this_time, tssi_info->tssi_alimk_time); + } + + void rtw8852b_dpk_init(struct rtw89_dev *rtwdev) +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.c +index 336a83e1d46be..6e6889eea9a0d 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.c +@@ -3663,9 +3663,10 @@ static void _tssi_alimentk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + u8 ch_idx = _tssi_ch_to_idx(rtwdev, channel); + struct rtw8852bx_bb_tssi_bak tssi_bak; + s32 aliment_diff, tssi_cw_default; +- u32 start_time, finish_time; + u32 bb_reg_backup[8] = {}; ++ ktime_t start_time; + const s16 *power; ++ s64 this_time; + u8 band; + bool ok; + u32 tmp; +@@ -3675,7 +3676,7 @@ static void _tssi_alimentk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + "======> %s channel=%d path=%d\n", __func__, channel, + path); + +- start_time = ktime_get_ns(); ++ start_time = ktime_get(); + + if (chan->band_type == RTW89_BAND_2G) + power = power_2g; +@@ -3802,12 +3803,12 @@ static void _tssi_alimentk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + rtw8852bx_bb_restore_tssi(rtwdev, phy, &tssi_bak); + rtw8852bx_bb_tx_mode_switch(rtwdev, phy, 0); + +- finish_time = ktime_get_ns(); +- tssi_info->tssi_alimk_time += finish_time - start_time; ++ this_time = ktime_us_delta(ktime_get(), start_time); ++ tssi_info->tssi_alimk_time += this_time; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, +- "[TSSI PA K] %s processing time = %d ms\n", __func__, +- tssi_info->tssi_alimk_time); ++ "[TSSI PA K] %s processing time = %lld us (acc = %llu us)\n", ++ __func__, this_time, tssi_info->tssi_alimk_time); + } + + void rtw8852bt_dpk_init(struct rtw89_dev *rtwdev) +-- +2.39.5 + diff --git a/queue-6.14/writeback-fix-calculations-in-trace_balance_dirty_pa.patch b/queue-6.14/writeback-fix-calculations-in-trace_balance_dirty_pa.patch new file mode 100644 index 0000000000..709678f99b --- /dev/null +++ b/queue-6.14/writeback-fix-calculations-in-trace_balance_dirty_pa.patch @@ -0,0 +1,88 @@ +From b805e90575d4f8ef8c7a1c7b5d6f427c1f19810e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 19:03:18 +0800 +Subject: writeback: fix calculations in trace_balance_dirty_pages() for cgwb + +From: Tang Yizhou + +[ Upstream commit 6cc4c3aa714bc58ec5d20f3054ca5f23534984d1 ] + +In the commit dcc25ae76eb7 ("writeback: move global_dirty_limit into +wb_domain") of the cgroup writeback backpressure propagation patchset, +Tejun made some adaptations to trace_balance_dirty_pages() for cgroup +writeback. However, this adaptation was incomplete and Tejun missed +further adaptation in the subsequent patches. + +In the cgroup writeback scenario, if sdtc in balance_dirty_pages() is +assigned to mdtc, then upon entering trace_balance_dirty_pages(), +__entry->limit should be assigned based on the dirty_limit of the +corresponding memcg's wb_domain, rather than global_wb_domain. + +To address this issue and simplify the implementation, introduce a 'limit' +field in struct dirty_throttle_control to store the hard_limit value +computed in wb_position_ratio() by calling hard_dirty_limit(). This field +will then be used in trace_balance_dirty_pages() to assign the value to +__entry->limit. + +Link: https://lkml.kernel.org/r/20250304110318.159567-4-yizhou.tang@shopee.com +Fixes: dcc25ae76eb7 ("writeback: move global_dirty_limit into wb_domain") +Signed-off-by: Tang Yizhou +Acked-by: Tejun Heo +Cc: Alexei Starovoitov +Cc: Christian Brauner +Cc: Jan Kara +Cc: "Masami Hiramatsu (Google)" +Cc: Matthew Wilcow (Oracle) +Cc: Steven Rostedt +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + include/linux/writeback.h | 1 + + include/trace/events/writeback.h | 5 ++--- + mm/page-writeback.c | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/include/linux/writeback.h b/include/linux/writeback.h +index 32095928365ce..58bda33479146 100644 +--- a/include/linux/writeback.h ++++ b/include/linux/writeback.h +@@ -326,6 +326,7 @@ struct dirty_throttle_control { + unsigned long dirty; /* file_dirty + write + nfs */ + unsigned long thresh; /* dirty threshold */ + unsigned long bg_thresh; /* dirty background threshold */ ++ unsigned long limit; /* hard dirty limit */ + + unsigned long wb_dirty; /* per-wb counterparts */ + unsigned long wb_thresh; +diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h +index 3213b90237944..5755c2a569e16 100644 +--- a/include/trace/events/writeback.h ++++ b/include/trace/events/writeback.h +@@ -663,9 +663,8 @@ TRACE_EVENT(balance_dirty_pages, + unsigned long freerun = (dtc->thresh + dtc->bg_thresh) / 2; + strscpy_pad(__entry->bdi, bdi_dev_name(wb->bdi), 32); + +- __entry->limit = global_wb_domain.dirty_limit; +- __entry->setpoint = (global_wb_domain.dirty_limit + +- freerun) / 2; ++ __entry->limit = dtc->limit; ++ __entry->setpoint = (dtc->limit + freerun) / 2; + __entry->dirty = dtc->dirty; + __entry->bdi_setpoint = __entry->setpoint * + dtc->wb_thresh / (dtc->thresh + 1); +diff --git a/mm/page-writeback.c b/mm/page-writeback.c +index e980b2aec3529..3147119a9a042 100644 +--- a/mm/page-writeback.c ++++ b/mm/page-writeback.c +@@ -1072,7 +1072,7 @@ static void wb_position_ratio(struct dirty_throttle_control *dtc) + struct bdi_writeback *wb = dtc->wb; + unsigned long write_bw = READ_ONCE(wb->avg_write_bandwidth); + unsigned long freerun = dirty_freerun_ceiling(dtc->thresh, dtc->bg_thresh); +- unsigned long limit = hard_dirty_limit(dtc_dom(dtc), dtc->thresh); ++ unsigned long limit = dtc->limit = hard_dirty_limit(dtc_dom(dtc), dtc->thresh); + unsigned long wb_thresh = dtc->wb_thresh; + unsigned long x_intercept; + unsigned long setpoint; /* dirty pages' target balance point */ +-- +2.39.5 + diff --git a/queue-6.14/writeback-let-trace_balance_dirty_pages-take-struct-.patch b/queue-6.14/writeback-let-trace_balance_dirty_pages-take-struct-.patch new file mode 100644 index 0000000000..4789acf669 --- /dev/null +++ b/queue-6.14/writeback-let-trace_balance_dirty_pages-take-struct-.patch @@ -0,0 +1,199 @@ +From 839e5561590ffd665de5b5319f5b57f42c802a95 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 19:03:16 +0800 +Subject: writeback: let trace_balance_dirty_pages() take struct dtc as + parameter + +From: Tang Yizhou + +[ Upstream commit f1ab2831e2a4312046bca79256b2efc41d373eaf ] + +Patch series "Fix calculations in trace_balance_dirty_pages() for cgwb", v2. + +In my experiment, I found that the output of trace_balance_dirty_pages() +in the cgroup writeback scenario was strange because +trace_balance_dirty_pages() always uses global_wb_domain.dirty_limit for +related calculations instead of the dirty_limit of the corresponding +memcg's wb_domain. + +The basic idea of the fix is to store the hard dirty limit value computed +in wb_position_ratio() into struct dirty_throttle_control and use it for +calculations in trace_balance_dirty_pages(). + +This patch (of 3): + +Currently, trace_balance_dirty_pages() already has 12 parameters. In the +patch #3, I initially attempted to introduce an additional parameter. +However, in include/linux/trace_events.h, bpf_trace_run12() only supports +up to 12 parameters and bpf_trace_run13() does not exist. + +To reduce the number of parameters in trace_balance_dirty_pages(), we can +make it accept a pointer to struct dirty_throttle_control as a parameter. +To achieve this, we need to move the definition of struct +dirty_throttle_control from mm/page-writeback.c to +include/linux/writeback.h. + +Link: https://lkml.kernel.org/r/20250304110318.159567-1-yizhou.tang@shopee.com +Link: https://lkml.kernel.org/r/20250304110318.159567-2-yizhou.tang@shopee.com +Signed-off-by: Tang Yizhou +Cc: Alexei Starovoitov +Cc: Christian Brauner +Cc: Steven Rostedt +Cc: Jan Kara +Cc: "Masami Hiramatsu (Google)" +Cc: Matthew Wilcow (Oracle) +Cc: Tang Yizhou +Cc: Tejun Heo +Signed-off-by: Andrew Morton +Stable-dep-of: 6cc4c3aa714b ("writeback: fix calculations in trace_balance_dirty_pages() for cgwb") +Signed-off-by: Sasha Levin +--- + include/linux/writeback.h | 23 +++++++++++++++++++++ + include/trace/events/writeback.h | 16 ++++++--------- + mm/page-writeback.c | 35 ++------------------------------ + 3 files changed, 31 insertions(+), 43 deletions(-) + +diff --git a/include/linux/writeback.h b/include/linux/writeback.h +index d11b903c2edb8..32095928365ce 100644 +--- a/include/linux/writeback.h ++++ b/include/linux/writeback.h +@@ -313,6 +313,29 @@ static inline void cgroup_writeback_umount(struct super_block *sb) + /* + * mm/page-writeback.c + */ ++/* consolidated parameters for balance_dirty_pages() and its subroutines */ ++struct dirty_throttle_control { ++#ifdef CONFIG_CGROUP_WRITEBACK ++ struct wb_domain *dom; ++ struct dirty_throttle_control *gdtc; /* only set in memcg dtc's */ ++#endif ++ struct bdi_writeback *wb; ++ struct fprop_local_percpu *wb_completions; ++ ++ unsigned long avail; /* dirtyable */ ++ unsigned long dirty; /* file_dirty + write + nfs */ ++ unsigned long thresh; /* dirty threshold */ ++ unsigned long bg_thresh; /* dirty background threshold */ ++ ++ unsigned long wb_dirty; /* per-wb counterparts */ ++ unsigned long wb_thresh; ++ unsigned long wb_bg_thresh; ++ ++ unsigned long pos_ratio; ++ bool freerun; ++ bool dirty_exceeded; ++}; ++ + void laptop_io_completion(struct backing_dev_info *info); + void laptop_sync_completion(void); + void laptop_mode_timer_fn(struct timer_list *t); +diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h +index a261e86e61fac..3213b90237944 100644 +--- a/include/trace/events/writeback.h ++++ b/include/trace/events/writeback.h +@@ -629,11 +629,7 @@ TRACE_EVENT(bdi_dirty_ratelimit, + TRACE_EVENT(balance_dirty_pages, + + TP_PROTO(struct bdi_writeback *wb, +- unsigned long thresh, +- unsigned long bg_thresh, +- unsigned long dirty, +- unsigned long bdi_thresh, +- unsigned long bdi_dirty, ++ struct dirty_throttle_control *dtc, + unsigned long dirty_ratelimit, + unsigned long task_ratelimit, + unsigned long dirtied, +@@ -641,7 +637,7 @@ TRACE_EVENT(balance_dirty_pages, + long pause, + unsigned long start_time), + +- TP_ARGS(wb, thresh, bg_thresh, dirty, bdi_thresh, bdi_dirty, ++ TP_ARGS(wb, dtc, + dirty_ratelimit, task_ratelimit, + dirtied, period, pause, start_time), + +@@ -664,16 +660,16 @@ TRACE_EVENT(balance_dirty_pages, + ), + + TP_fast_assign( +- unsigned long freerun = (thresh + bg_thresh) / 2; ++ unsigned long freerun = (dtc->thresh + dtc->bg_thresh) / 2; + strscpy_pad(__entry->bdi, bdi_dev_name(wb->bdi), 32); + + __entry->limit = global_wb_domain.dirty_limit; + __entry->setpoint = (global_wb_domain.dirty_limit + + freerun) / 2; +- __entry->dirty = dirty; ++ __entry->dirty = dtc->dirty; + __entry->bdi_setpoint = __entry->setpoint * +- bdi_thresh / (thresh + 1); +- __entry->bdi_dirty = bdi_dirty; ++ dtc->wb_thresh / (dtc->thresh + 1); ++ __entry->bdi_dirty = dtc->wb_dirty; + __entry->dirty_ratelimit = KBps(dirty_ratelimit); + __entry->task_ratelimit = KBps(task_ratelimit); + __entry->dirtied = dirtied; +diff --git a/mm/page-writeback.c b/mm/page-writeback.c +index eb55ece39c565..e980b2aec3529 100644 +--- a/mm/page-writeback.c ++++ b/mm/page-writeback.c +@@ -120,29 +120,6 @@ EXPORT_SYMBOL(laptop_mode); + + struct wb_domain global_wb_domain; + +-/* consolidated parameters for balance_dirty_pages() and its subroutines */ +-struct dirty_throttle_control { +-#ifdef CONFIG_CGROUP_WRITEBACK +- struct wb_domain *dom; +- struct dirty_throttle_control *gdtc; /* only set in memcg dtc's */ +-#endif +- struct bdi_writeback *wb; +- struct fprop_local_percpu *wb_completions; +- +- unsigned long avail; /* dirtyable */ +- unsigned long dirty; /* file_dirty + write + nfs */ +- unsigned long thresh; /* dirty threshold */ +- unsigned long bg_thresh; /* dirty background threshold */ +- +- unsigned long wb_dirty; /* per-wb counterparts */ +- unsigned long wb_thresh; +- unsigned long wb_bg_thresh; +- +- unsigned long pos_ratio; +- bool freerun; +- bool dirty_exceeded; +-}; +- + /* + * Length of period for aging writeout fractions of bdis. This is an + * arbitrarily chosen number. The longer the period, the slower fractions will +@@ -1962,11 +1939,7 @@ static int balance_dirty_pages(struct bdi_writeback *wb, + */ + if (pause < min_pause) { + trace_balance_dirty_pages(wb, +- sdtc->thresh, +- sdtc->bg_thresh, +- sdtc->dirty, +- sdtc->wb_thresh, +- sdtc->wb_dirty, ++ sdtc, + dirty_ratelimit, + task_ratelimit, + pages_dirtied, +@@ -1991,11 +1964,7 @@ static int balance_dirty_pages(struct bdi_writeback *wb, + + pause: + trace_balance_dirty_pages(wb, +- sdtc->thresh, +- sdtc->bg_thresh, +- sdtc->dirty, +- sdtc->wb_thresh, +- sdtc->wb_dirty, ++ sdtc, + dirty_ratelimit, + task_ratelimit, + pages_dirtied, +-- +2.39.5 + diff --git a/queue-6.14/x86-dumpstack-fix-inaccurate-unwinding-from-exceptio.patch b/queue-6.14/x86-dumpstack-fix-inaccurate-unwinding-from-exceptio.patch new file mode 100644 index 0000000000..99bfbd1809 --- /dev/null +++ b/queue-6.14/x86-dumpstack-fix-inaccurate-unwinding-from-exceptio.patch @@ -0,0 +1,69 @@ +From 8c4f87a7f68c12a77fadfd8781cbb7aca116ef5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Mar 2025 03:01:23 +0100 +Subject: x86/dumpstack: Fix inaccurate unwinding from exception stacks due to + misplaced assignment + +From: Jann Horn + +[ Upstream commit 2c118f50d7fd4d9aefc4533a26f83338b2906b7a ] + +Commit: + + 2e4be0d011f2 ("x86/show_trace_log_lvl: Ensure stack pointer is aligned, again") + +was intended to ensure alignment of the stack pointer; but it also moved +the initialization of the "stack" variable down into the loop header. + +This was likely intended as a no-op cleanup, since the commit +message does not mention it; however, this caused a behavioral change +because the value of "regs" is different between the two places. + +Originally, get_stack_pointer() used the regs provided by the caller; after +that commit, get_stack_pointer() instead uses the regs at the top of the +stack frame the unwinder is looking at. Often, there are no such regs at +all, and "regs" is NULL, causing get_stack_pointer() to fall back to the +task's current stack pointer, which is not what we want here, but probably +happens to mostly work. Other times, the original regs will point to +another regs frame - in that case, the linear guess unwind logic in +show_trace_log_lvl() will start unwinding too far up the stack, causing the +first frame found by the proper unwinder to never be visited, resulting in +a stack trace consisting purely of guess lines. + +Fix it by moving the "stack = " assignment back where it belongs. + +Fixes: 2e4be0d011f2 ("x86/show_trace_log_lvl: Ensure stack pointer is aligned, again") +Signed-off-by: Jann Horn +Signed-off-by: Ingo Molnar +Link: https://lore.kernel.org/r/20250325-2025-03-unwind-fixes-v1-2-acd774364768@google.com +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/dumpstack.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c +index a7d562697e50e..b2b118a8c09be 100644 +--- a/arch/x86/kernel/dumpstack.c ++++ b/arch/x86/kernel/dumpstack.c +@@ -195,6 +195,7 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, + printk("%sCall Trace:\n", log_lvl); + + unwind_start(&state, task, regs, stack); ++ stack = stack ?: get_stack_pointer(task, regs); + regs = unwind_get_entry_regs(&state, &partial); + + /* +@@ -213,9 +214,7 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, + * - hardirq stack + * - entry stack + */ +- for (stack = stack ?: get_stack_pointer(task, regs); +- stack; +- stack = stack_info.next_sp) { ++ for (; stack; stack = stack_info.next_sp) { + const char *stack_name; + + stack = PTR_ALIGN(stack, sizeof(long)); +-- +2.39.5 + diff --git a/queue-6.14/x86-entry-add-__init-to-ia32_emulation_override_cmdl.patch b/queue-6.14/x86-entry-add-__init-to-ia32_emulation_override_cmdl.patch new file mode 100644 index 0000000000..d2ead3db40 --- /dev/null +++ b/queue-6.14/x86-entry-add-__init-to-ia32_emulation_override_cmdl.patch @@ -0,0 +1,41 @@ +From 95cae8252a1326a1dfe8ca217ddad13bca30fcb8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Dec 2024 16:16:50 +0100 +Subject: x86/entry: Add __init to ia32_emulation_override_cmdline() + +From: Vitaly Kuznetsov + +[ Upstream commit d55f31e29047f2f987286d55928ae75775111fe7 ] + +ia32_emulation_override_cmdline() is an early_param() arg and these +are only needed at boot time. In fact, all other early_param() functions +in arch/x86 seem to have '__init' annotation and +ia32_emulation_override_cmdline() is the only exception. + +Fixes: a11e097504ac ("x86: Make IA32_EMULATION boot time configurable") +Signed-off-by: Vitaly Kuznetsov +Signed-off-by: Dave Hansen +Signed-off-by: Ingo Molnar +Reviewed-by: Nikolay Borisov +Link: https://lore.kernel.org/all/20241210151650.1746022-1-vkuznets%40redhat.com +Signed-off-by: Sasha Levin +--- + arch/x86/entry/common.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c +index 14db5b85114c1..3514bf2978eed 100644 +--- a/arch/x86/entry/common.c ++++ b/arch/x86/entry/common.c +@@ -142,7 +142,7 @@ static __always_inline int syscall_32_enter(struct pt_regs *regs) + #ifdef CONFIG_IA32_EMULATION + bool __ia32_enabled __ro_after_init = !IS_ENABLED(CONFIG_IA32_EMULATION_DEFAULT_DISABLED); + +-static int ia32_emulation_override_cmdline(char *arg) ++static int __init ia32_emulation_override_cmdline(char *arg) + { + return kstrtobool(arg, &__ia32_enabled); + } +-- +2.39.5 + diff --git a/queue-6.14/x86-entry-fix-orc-unwinder-for-push_regs-with-save_r.patch b/queue-6.14/x86-entry-fix-orc-unwinder-for-push_regs-with-save_r.patch new file mode 100644 index 0000000000..1e6ce70b5f --- /dev/null +++ b/queue-6.14/x86-entry-fix-orc-unwinder-for-push_regs-with-save_r.patch @@ -0,0 +1,55 @@ +From b8eabdcd88fa3bdc1fc24286174cd7575840086d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Mar 2025 03:01:22 +0100 +Subject: x86/entry: Fix ORC unwinder for PUSH_REGS with save_ret=1 + +From: Jann Horn + +[ Upstream commit 57e2428f8df8263275344566e02c277648a4b7f1 ] + +PUSH_REGS with save_ret=1 is used by interrupt entry helper functions that +initially start with a UNWIND_HINT_FUNC ORC state. + +However, save_ret=1 means that we clobber the helper function's return +address (and then later restore the return address further down on the +stack); after that point, the only thing on the stack we can unwind through +is the IRET frame, so use UNWIND_HINT_IRET_REGS until we have a full +pt_regs frame. + +( An alternate approach would be to move the pt_regs->di overwrite down + such that it is the final step of pt_regs setup; but I don't want to + rearrange entry code just to make unwinding a tiny bit more elegant. ) + +Fixes: 9e809d15d6b6 ("x86/entry: Reduce the code footprint of the 'idtentry' macro") +Signed-off-by: Jann Horn +Signed-off-by: Ingo Molnar +Cc: Andy Lutomirski +Cc: Brian Gerst +Cc: Juergen Gross +Cc: H. Peter Anvin +Cc: Linus Torvalds +Cc: Kees Cook +Cc: Peter Zijlstra +Cc: Josh Poimboeuf +Link: https://lore.kernel.org/r/20250325-2025-03-unwind-fixes-v1-1-acd774364768@google.com +Signed-off-by: Sasha Levin +--- + arch/x86/entry/calling.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h +index ea81770629eea..626a81c6015bd 100644 +--- a/arch/x86/entry/calling.h ++++ b/arch/x86/entry/calling.h +@@ -70,6 +70,8 @@ For 32-bit we have the following conventions - kernel is built with + pushq %rsi /* pt_regs->si */ + movq 8(%rsp), %rsi /* temporarily store the return address in %rsi */ + movq %rdi, 8(%rsp) /* pt_regs->di (overwriting original return address) */ ++ /* We just clobbered the return address - use the IRET frame for unwinding: */ ++ UNWIND_HINT_IRET_REGS offset=3*8 + .else + pushq %rdi /* pt_regs->di */ + pushq %rsi /* pt_regs->si */ +-- +2.39.5 + diff --git a/queue-6.14/x86-fpu-avoid-copying-dynamic-fp-state-from-init_tas.patch b/queue-6.14/x86-fpu-avoid-copying-dynamic-fp-state-from-init_tas.patch new file mode 100644 index 0000000000..74af3034d1 --- /dev/null +++ b/queue-6.14/x86-fpu-avoid-copying-dynamic-fp-state-from-init_tas.patch @@ -0,0 +1,57 @@ +From 2f682ea754482b5ff6156a830eb68791f78e9711 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 14:31:36 +0100 +Subject: x86/fpu: Avoid copying dynamic FP state from init_task in + arch_dup_task_struct() + +From: Benjamin Berg + +[ Upstream commit 5d3b81d4d8520efe888536b6906dc10fd1a228a8 ] + +The init_task instance of struct task_struct is statically allocated and +may not contain the full FP state for userspace. As such, limit the copy +to the valid area of both init_task and 'dst' and ensure all memory is +initialized. + +Note that the FP state is only needed for userspace, and as such it is +entirely reasonable for init_task to not contain parts of it. + +Fixes: 5aaeb5c01c5b ("x86/fpu, sched: Introduce CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT and use it on x86") +Signed-off-by: Benjamin Berg +Signed-off-by: Ingo Molnar +Cc: Andy Lutomirski +Cc: H. Peter Anvin +Cc: Oleg Nesterov +Link: https://lore.kernel.org/r/20250226133136.816901-1-benjamin@sipsolutions.net +---- + +v2: +- Fix code if arch_task_struct_size < sizeof(init_task) by using + memcpy_and_pad. + +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/process.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c +index 6da6769d7254a..7cb52f84cb0c2 100644 +--- a/arch/x86/kernel/process.c ++++ b/arch/x86/kernel/process.c +@@ -93,7 +93,12 @@ EXPORT_PER_CPU_SYMBOL_GPL(__tss_limit_invalid); + */ + int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) + { +- memcpy(dst, src, arch_task_struct_size); ++ /* init_task is not dynamically sized (incomplete FPU state) */ ++ if (unlikely(src == &init_task)) ++ memcpy_and_pad(dst, arch_task_struct_size, src, sizeof(init_task), 0); ++ else ++ memcpy(dst, src, arch_task_struct_size); ++ + #ifdef CONFIG_VM86 + dst->thread.vm86 = NULL; + #endif +-- +2.39.5 + diff --git a/queue-6.14/x86-fpu-fix-guest-fpu-state-buffer-allocation-size.patch b/queue-6.14/x86-fpu-fix-guest-fpu-state-buffer-allocation-size.patch new file mode 100644 index 0000000000..9ff7cbdca2 --- /dev/null +++ b/queue-6.14/x86-fpu-fix-guest-fpu-state-buffer-allocation-size.patch @@ -0,0 +1,49 @@ +From 8c254852164c228803ce7a79b140a4e4de692fc8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 14:10:45 +0000 +Subject: x86/fpu: Fix guest FPU state buffer allocation size + +From: Stanislav Spassov + +[ Upstream commit 1937e18cc3cf27e2b3ef70e8c161437051ab7608 ] + +Ongoing work on an optimization to batch-preallocate vCPU state buffers +for KVM revealed a mismatch between the allocation sizes used in +fpu_alloc_guest_fpstate() and fpstate_realloc(). While the former +allocates a buffer sized to fit the default set of XSAVE features +in UABI form (as per fpu_user_cfg), the latter uses its ksize argument +derived (for the requested set of features) in the same way as the sizes +found in fpu_kernel_cfg, i.e. using the compacted in-kernel +representation. + +The correct size to use for guest FPU state should indeed be the +kernel one as seen in fpstate_realloc(). The original issue likely +went unnoticed through a combination of UABI size typically being +larger than or equal to kernel size, and/or both amounting to the +same number of allocated 4K pages. + +Fixes: 69f6ed1d14c6 ("x86/fpu: Provide infrastructure for KVM FPU cleanup") +Signed-off-by: Stanislav Spassov +Signed-off-by: Ingo Molnar +Link: https://lore.kernel.org/r/20250218141045.85201-1-stanspas@amazon.de +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/fpu/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c +index 1209c7aebb211..36df548acc403 100644 +--- a/arch/x86/kernel/fpu/core.c ++++ b/arch/x86/kernel/fpu/core.c +@@ -220,7 +220,7 @@ bool fpu_alloc_guest_fpstate(struct fpu_guest *gfpu) + struct fpstate *fpstate; + unsigned int size; + +- size = fpu_user_cfg.default_size + ALIGN(offsetof(struct fpstate, regs), 64); ++ size = fpu_kernel_cfg.default_size + ALIGN(offsetof(struct fpstate, regs), 64); + fpstate = vzalloc(size); + if (!fpstate) + return false; +-- +2.39.5 + diff --git a/queue-6.14/x86-fpu-xstate-fix-inconsistencies-in-guest-fpu-xfea.patch b/queue-6.14/x86-fpu-xstate-fix-inconsistencies-in-guest-fpu-xfea.patch new file mode 100644 index 0000000000..2a7fd74253 --- /dev/null +++ b/queue-6.14/x86-fpu-xstate-fix-inconsistencies-in-guest-fpu-xfea.patch @@ -0,0 +1,86 @@ +From fcefc7b385a241178b73f5b839ddb8eda9e3fcc5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 22:06:11 +0800 +Subject: x86/fpu/xstate: Fix inconsistencies in guest FPU xfeatures + +From: Chao Gao + +[ Upstream commit dda366083e5ff307a4a728757db874bbfe7550be ] + +Guest FPUs manage vCPU FPU states. They are allocated via +fpu_alloc_guest_fpstate() and are resized in fpstate_realloc() when XFD +features are enabled. + +Since the introduction of guest FPUs, there have been inconsistencies in +the kernel buffer size and xfeatures: + + 1. fpu_alloc_guest_fpstate() uses fpu_user_cfg since its introduction. See: + + 69f6ed1d14c6 ("x86/fpu: Provide infrastructure for KVM FPU cleanup") + 36487e6228c4 ("x86/fpu: Prepare guest FPU for dynamically enabled FPU features") + + 2. __fpstate_reset() references fpu_kernel_cfg to set storage attributes. + + 3. fpu->guest_perm uses fpu_kernel_cfg, affecting fpstate_realloc(). + +A recent commit in the tip:x86/fpu tree partially addressed the inconsistency +between (1) and (3) by using fpu_kernel_cfg for size calculation in (1), +but left fpu_guest->xfeatures and fpu_guest->perm still referencing +fpu_user_cfg: + + https://lore.kernel.org/all/20250218141045.85201-1-stanspas@amazon.de/ + + 1937e18cc3cf ("x86/fpu: Fix guest FPU state buffer allocation size") + +The inconsistencies within fpu_alloc_guest_fpstate() and across the +mentioned functions cause confusion. + +Fix them by using fpu_kernel_cfg consistently in fpu_alloc_guest_fpstate(), +except for fields related to the UABI buffer. Referencing fpu_kernel_cfg +won't impact functionalities, as: + + 1. fpu_guest->perm is overwritten shortly in fpu_init_guest_permissions() + with fpstate->guest_perm, which already uses fpu_kernel_cfg. + + 2. fpu_guest->xfeatures is solely used to check if XFD features are enabled. + Including supervisor xfeatures doesn't affect the check. + +Fixes: 36487e6228c4 ("x86/fpu: Prepare guest FPU for dynamically enabled FPU features") +Suggested-by: Chang S. Bae +Signed-off-by: Chao Gao +Signed-off-by: Ingo Molnar +Cc: Andy Lutomirski +Cc: H. Peter Anvin +Cc: Linus Torvalds +Cc: Oleg Nesterov +Cc: Dave Hansen +Cc: Juergen Gross +Cc: Stefano Stabellini +Cc: Paolo Bonzini +Cc: Vitaly Kuznetsov +Cc: Sean Christopherson +Cc: David Woodhouse +Link: https://lore.kernel.org/r/20250317140613.1761633-1-chao.gao@intel.com +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/fpu/core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c +index 36df548acc403..dcac3c058fb76 100644 +--- a/arch/x86/kernel/fpu/core.c ++++ b/arch/x86/kernel/fpu/core.c +@@ -232,8 +232,8 @@ bool fpu_alloc_guest_fpstate(struct fpu_guest *gfpu) + fpstate->is_guest = true; + + gfpu->fpstate = fpstate; +- gfpu->xfeatures = fpu_user_cfg.default_features; +- gfpu->perm = fpu_user_cfg.default_features; ++ gfpu->xfeatures = fpu_kernel_cfg.default_features; ++ gfpu->perm = fpu_kernel_cfg.default_features; + + /* + * KVM sets the FP+SSE bits in the XSAVE header when copying FPU state +-- +2.39.5 + diff --git a/queue-6.14/x86-mm-pat-cpa-test-fix-length-for-cpa_array-test.patch b/queue-6.14/x86-mm-pat-cpa-test-fix-length-for-cpa_array-test.patch new file mode 100644 index 0000000000..392d84faf0 --- /dev/null +++ b/queue-6.14/x86-mm-pat-cpa-test-fix-length-for-cpa_array-test.patch @@ -0,0 +1,40 @@ +From 5b4f6b8d95d806633b7fd0fcdaafd355c689a289 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 26 Jan 2025 09:47:25 +0200 +Subject: x86/mm/pat: cpa-test: fix length for CPA_ARRAY test + +From: Mike Rapoport (Microsoft) + +[ Upstream commit 33ea120582a638b2f2e380a50686c2b1d7cce795 ] + +The CPA_ARRAY test always uses len[1] as numpages argument to +change_page_attr_set() although the addresses array is different each +iteration of the test loop. + +Replace len[1] with len[i] to have numpages matching the addresses array. + +Fixes: ecc729f1f471 ("x86/mm/cpa: Add ARRAY and PAGES_ARRAY selftests") +Signed-off-by: "Mike Rapoport (Microsoft)" +Signed-off-by: Peter Zijlstra (Intel) +Link: https://lore.kernel.org/r/20250126074733.1384926-2-rppt@kernel.org +Signed-off-by: Sasha Levin +--- + arch/x86/mm/pat/cpa-test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/x86/mm/pat/cpa-test.c b/arch/x86/mm/pat/cpa-test.c +index 3d2f7f0a6ed14..ad3c1feec990d 100644 +--- a/arch/x86/mm/pat/cpa-test.c ++++ b/arch/x86/mm/pat/cpa-test.c +@@ -183,7 +183,7 @@ static int pageattr_test(void) + break; + + case 1: +- err = change_page_attr_set(addrs, len[1], PAGE_CPA_TEST, 1); ++ err = change_page_attr_set(addrs, len[i], PAGE_CPA_TEST, 1); + break; + + case 2: +-- +2.39.5 + diff --git a/queue-6.14/x86-mm-pat-fix-vm_pat-handling-when-fork-fails-in-co.patch b/queue-6.14/x86-mm-pat-fix-vm_pat-handling-when-fork-fails-in-co.patch new file mode 100644 index 0000000000..f41f1bf292 --- /dev/null +++ b/queue-6.14/x86-mm-pat-fix-vm_pat-handling-when-fork-fails-in-co.patch @@ -0,0 +1,297 @@ +From ff71cd468634374f6f9de93277bce237f353fa0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 12:23:23 +0100 +Subject: x86/mm/pat: Fix VM_PAT handling when fork() fails in + copy_page_range() + +From: David Hildenbrand + +[ Upstream commit dc84bc2aba85a1508f04a936f9f9a15f64ebfb31 ] + +If track_pfn_copy() fails, we already added the dst VMA to the maple +tree. As fork() fails, we'll cleanup the maple tree, and stumble over +the dst VMA for which we neither performed any reservation nor copied +any page tables. + +Consequently untrack_pfn() will see VM_PAT and try obtaining the +PAT information from the page table -- which fails because the page +table was not copied. + +The easiest fix would be to simply clear the VM_PAT flag of the dst VMA +if track_pfn_copy() fails. However, the whole thing is about "simply" +clearing the VM_PAT flag is shaky as well: if we passed track_pfn_copy() +and performed a reservation, but copying the page tables fails, we'll +simply clear the VM_PAT flag, not properly undoing the reservation ... +which is also wrong. + +So let's fix it properly: set the VM_PAT flag only if the reservation +succeeded (leaving it clear initially), and undo the reservation if +anything goes wrong while copying the page tables: clearing the VM_PAT +flag after undoing the reservation. + +Note that any copied page table entries will get zapped when the VMA will +get removed later, after copy_page_range() succeeded; as VM_PAT is not set +then, we won't try cleaning VM_PAT up once more and untrack_pfn() will be +happy. Note that leaving these page tables in place without a reservation +is not a problem, as we are aborting fork(); this process will never run. + +A reproducer can trigger this usually at the first try: + + https://gitlab.com/davidhildenbrand/scratchspace/-/raw/main/reproducers/pat_fork.c + + WARNING: CPU: 26 PID: 11650 at arch/x86/mm/pat/memtype.c:983 get_pat_info+0xf6/0x110 + Modules linked in: ... + CPU: 26 UID: 0 PID: 11650 Comm: repro3 Not tainted 6.12.0-rc5+ #92 + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-2.fc40 04/01/2014 + RIP: 0010:get_pat_info+0xf6/0x110 + ... + Call Trace: + + ... + untrack_pfn+0x52/0x110 + unmap_single_vma+0xa6/0xe0 + unmap_vmas+0x105/0x1f0 + exit_mmap+0xf6/0x460 + __mmput+0x4b/0x120 + copy_process+0x1bf6/0x2aa0 + kernel_clone+0xab/0x440 + __do_sys_clone+0x66/0x90 + do_syscall_64+0x95/0x180 + +Likely this case was missed in: + + d155df53f310 ("x86/mm/pat: clear VM_PAT if copy_p4d_range failed") + +... and instead of undoing the reservation we simply cleared the VM_PAT flag. + +Keep the documentation of these functions in include/linux/pgtable.h, +one place is more than sufficient -- we should clean that up for the other +functions like track_pfn_remap/untrack_pfn separately. + +Fixes: d155df53f310 ("x86/mm/pat: clear VM_PAT if copy_p4d_range failed") +Fixes: 2ab640379a0a ("x86: PAT: hooks in generic vm code to help archs to track pfnmap regions - v3") +Reported-by: xingwei lee +Reported-by: yuxin wang +Reported-by: Marius Fleischer +Signed-off-by: David Hildenbrand +Signed-off-by: Ingo Molnar +Cc: Andy Lutomirski +Cc: Peter Zijlstra +Cc: Rik van Riel +Cc: "H. Peter Anvin" +Cc: Linus Torvalds +Cc: Andrew Morton +Cc: linux-mm@kvack.org +Link: https://lore.kernel.org/r/20250321112323.153741-1-david@redhat.com +Closes: https://lore.kernel.org/lkml/CABOYnLx_dnqzpCW99G81DmOr+2UzdmZMk=T3uxwNxwz+R1RAwg@mail.gmail.com/ +Closes: https://lore.kernel.org/lkml/CAJg=8jwijTP5fre8woS4JVJQ8iUA6v+iNcsOgtj9Zfpc3obDOQ@mail.gmail.com/ +Signed-off-by: Sasha Levin +--- + arch/x86/mm/pat/memtype.c | 52 +++++++++++++++++++++------------------ + include/linux/pgtable.h | 28 ++++++++++++++++----- + kernel/fork.c | 4 +++ + mm/memory.c | 11 +++------ + 4 files changed, 58 insertions(+), 37 deletions(-) + +diff --git a/arch/x86/mm/pat/memtype.c b/arch/x86/mm/pat/memtype.c +index feb8cc6a12bf2..d721cc19addbd 100644 +--- a/arch/x86/mm/pat/memtype.c ++++ b/arch/x86/mm/pat/memtype.c +@@ -984,29 +984,42 @@ static int get_pat_info(struct vm_area_struct *vma, resource_size_t *paddr, + return -EINVAL; + } + +-/* +- * track_pfn_copy is called when vma that is covering the pfnmap gets +- * copied through copy_page_range(). +- * +- * If the vma has a linear pfn mapping for the entire range, we get the prot +- * from pte and reserve the entire vma range with single reserve_pfn_range call. +- */ +-int track_pfn_copy(struct vm_area_struct *vma) ++int track_pfn_copy(struct vm_area_struct *dst_vma, ++ struct vm_area_struct *src_vma, unsigned long *pfn) + { ++ const unsigned long vma_size = src_vma->vm_end - src_vma->vm_start; + resource_size_t paddr; +- unsigned long vma_size = vma->vm_end - vma->vm_start; + pgprot_t pgprot; ++ int rc; + +- if (vma->vm_flags & VM_PAT) { +- if (get_pat_info(vma, &paddr, &pgprot)) +- return -EINVAL; +- /* reserve the whole chunk covered by vma. */ +- return reserve_pfn_range(paddr, vma_size, &pgprot, 1); +- } ++ if (!(src_vma->vm_flags & VM_PAT)) ++ return 0; ++ ++ /* ++ * Duplicate the PAT information for the dst VMA based on the src ++ * VMA. ++ */ ++ if (get_pat_info(src_vma, &paddr, &pgprot)) ++ return -EINVAL; ++ rc = reserve_pfn_range(paddr, vma_size, &pgprot, 1); ++ if (rc) ++ return rc; + ++ /* Reservation for the destination VMA succeeded. */ ++ vm_flags_set(dst_vma, VM_PAT); ++ *pfn = PHYS_PFN(paddr); + return 0; + } + ++void untrack_pfn_copy(struct vm_area_struct *dst_vma, unsigned long pfn) ++{ ++ untrack_pfn(dst_vma, pfn, dst_vma->vm_end - dst_vma->vm_start, true); ++ /* ++ * Reservation was freed, any copied page tables will get cleaned ++ * up later, but without getting PAT involved again. ++ */ ++} ++ + /* + * prot is passed in as a parameter for the new mapping. If the vma has + * a linear pfn mapping for the entire range, or no vma is provided, +@@ -1095,15 +1108,6 @@ void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn, + } + } + +-/* +- * untrack_pfn_clear is called if the following situation fits: +- * +- * 1) while mremapping a pfnmap for a new region, with the old vma after +- * its pfnmap page table has been removed. The new vma has a new pfnmap +- * to the same pfn & cache type with VM_PAT set. +- * 2) while duplicating vm area, the new vma fails to copy the pgtable from +- * old vma. +- */ + void untrack_pfn_clear(struct vm_area_struct *vma) + { + vm_flags_clear(vma, VM_PAT); +diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h +index 94d267d02372e..4c107e17c547e 100644 +--- a/include/linux/pgtable.h ++++ b/include/linux/pgtable.h +@@ -1508,14 +1508,25 @@ static inline void track_pfn_insert(struct vm_area_struct *vma, pgprot_t *prot, + } + + /* +- * track_pfn_copy is called when vma that is covering the pfnmap gets +- * copied through copy_page_range(). ++ * track_pfn_copy is called when a VM_PFNMAP VMA is about to get the page ++ * tables copied during copy_page_range(). On success, stores the pfn to be ++ * passed to untrack_pfn_copy(). + */ +-static inline int track_pfn_copy(struct vm_area_struct *vma) ++static inline int track_pfn_copy(struct vm_area_struct *dst_vma, ++ struct vm_area_struct *src_vma, unsigned long *pfn) + { + return 0; + } + ++/* ++ * untrack_pfn_copy is called when a VM_PFNMAP VMA failed to copy during ++ * copy_page_range(), but after track_pfn_copy() was already called. ++ */ ++static inline void untrack_pfn_copy(struct vm_area_struct *dst_vma, ++ unsigned long pfn) ++{ ++} ++ + /* + * untrack_pfn is called while unmapping a pfnmap for a region. + * untrack can be called for a specific region indicated by pfn and size or +@@ -1528,8 +1539,10 @@ static inline void untrack_pfn(struct vm_area_struct *vma, + } + + /* +- * untrack_pfn_clear is called while mremapping a pfnmap for a new region +- * or fails to copy pgtable during duplicate vm area. ++ * untrack_pfn_clear is called in the following cases on a VM_PFNMAP VMA: ++ * ++ * 1) During mremap() on the src VMA after the page tables were moved. ++ * 2) During fork() on the dst VMA, immediately after duplicating the src VMA. + */ + static inline void untrack_pfn_clear(struct vm_area_struct *vma) + { +@@ -1540,7 +1553,10 @@ extern int track_pfn_remap(struct vm_area_struct *vma, pgprot_t *prot, + unsigned long size); + extern void track_pfn_insert(struct vm_area_struct *vma, pgprot_t *prot, + pfn_t pfn); +-extern int track_pfn_copy(struct vm_area_struct *vma); ++extern int track_pfn_copy(struct vm_area_struct *dst_vma, ++ struct vm_area_struct *src_vma, unsigned long *pfn); ++extern void untrack_pfn_copy(struct vm_area_struct *dst_vma, ++ unsigned long pfn); + extern void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn, + unsigned long size, bool mm_wr_locked); + extern void untrack_pfn_clear(struct vm_area_struct *vma); +diff --git a/kernel/fork.c b/kernel/fork.c +index 735405a9c5f32..ca2ca3884f763 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -504,6 +504,10 @@ struct vm_area_struct *vm_area_dup(struct vm_area_struct *orig) + vma_numab_state_init(new); + dup_anon_vma_name(orig, new); + ++ /* track_pfn_copy() will later take care of copying internal state. */ ++ if (unlikely(new->vm_flags & VM_PFNMAP)) ++ untrack_pfn_clear(new); ++ + return new; + } + +diff --git a/mm/memory.c b/mm/memory.c +index 4f6d9766a0460..53f7b0aaf2a33 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -1362,12 +1362,12 @@ int + copy_page_range(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma) + { + pgd_t *src_pgd, *dst_pgd; +- unsigned long next; + unsigned long addr = src_vma->vm_start; + unsigned long end = src_vma->vm_end; + struct mm_struct *dst_mm = dst_vma->vm_mm; + struct mm_struct *src_mm = src_vma->vm_mm; + struct mmu_notifier_range range; ++ unsigned long next, pfn; + bool is_cow; + int ret; + +@@ -1378,11 +1378,7 @@ copy_page_range(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma) + return copy_hugetlb_page_range(dst_mm, src_mm, dst_vma, src_vma); + + if (unlikely(src_vma->vm_flags & VM_PFNMAP)) { +- /* +- * We do not free on error cases below as remove_vma +- * gets called on error from higher level routine +- */ +- ret = track_pfn_copy(src_vma); ++ ret = track_pfn_copy(dst_vma, src_vma, &pfn); + if (ret) + return ret; + } +@@ -1419,7 +1415,6 @@ copy_page_range(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma) + continue; + if (unlikely(copy_p4d_range(dst_vma, src_vma, dst_pgd, src_pgd, + addr, next))) { +- untrack_pfn_clear(dst_vma); + ret = -ENOMEM; + break; + } +@@ -1429,6 +1424,8 @@ copy_page_range(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma) + raw_write_seqcount_end(&src_mm->write_protect_seq); + mmu_notifier_invalidate_range_end(&range); + } ++ if (ret && unlikely(src_vma->vm_flags & VM_PFNMAP)) ++ untrack_pfn_copy(dst_vma, pfn); + return ret; + } + +-- +2.39.5 + diff --git a/queue-6.14/x86-platform-only-allow-config_eisa-for-32-bit.patch b/queue-6.14/x86-platform-only-allow-config_eisa-for-32-bit.patch new file mode 100644 index 0000000000..5d5ee3e4fe --- /dev/null +++ b/queue-6.14/x86-platform-only-allow-config_eisa-for-32-bit.patch @@ -0,0 +1,43 @@ +From 1d98659d75e6e285ceab4b01020d3a5e8dd3ff4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 22:37:14 +0100 +Subject: x86/platform: Only allow CONFIG_EISA for 32-bit + +From: Arnd Bergmann + +[ Upstream commit 976ba8da2f3c2f1e997f4f620da83ae65c0e3728 ] + +The CONFIG_EISA menu was cleaned up in 2018, but this inadvertently +brought the option back on 64-bit machines: ISA remains guarded by +a CONFIG_X86_32 check, but EISA no longer depends on ISA. + +The last Intel machines ith EISA support used a 82375EB PCI/EISA bridge +from 1993 that could be paired with the 440FX chipset on early Pentium-II +CPUs, long before the first x86-64 products. + +Fixes: 6630a8e50105 ("eisa: consolidate EISA Kconfig entry in drivers/eisa") +Signed-off-by: Arnd Bergmann +Signed-off-by: Ingo Molnar +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/20250226213714.4040853-11-arnd@kernel.org +Signed-off-by: Sasha Levin +--- + arch/x86/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index 0e27ebd7e36a9..cf79f973023f1 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -232,7 +232,7 @@ config X86 + select HAVE_SAMPLE_FTRACE_DIRECT_MULTI if X86_64 + select HAVE_EBPF_JIT + select HAVE_EFFICIENT_UNALIGNED_ACCESS +- select HAVE_EISA ++ select HAVE_EISA if X86_32 + select HAVE_EXIT_THREAD + select HAVE_GUP_FAST + select HAVE_FENTRY if X86_64 || DYNAMIC_FTRACE +-- +2.39.5 + diff --git a/queue-6.14/x86-resctrl-fix-allocation-of-cleanest-closid-on-pla.patch b/queue-6.14/x86-resctrl-fix-allocation-of-cleanest-closid-on-pla.patch new file mode 100644 index 0000000000..89c7585653 --- /dev/null +++ b/queue-6.14/x86-resctrl-fix-allocation-of-cleanest-closid-on-pla.patch @@ -0,0 +1,67 @@ +From 5c8b87d5317571159872b4315996206bf807b271 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 18:36:46 +0000 +Subject: x86/resctrl: Fix allocation of cleanest CLOSID on platforms with no + monitors + +From: James Morse + +[ Upstream commit a121798ae669351ec0697c94f71c3a692b2a755b ] + +Commit + + 6eac36bb9eb0 ("x86/resctrl: Allocate the cleanest CLOSID by searching closid_num_dirty_rmid") + +added logic that causes resctrl to search for the CLOSID with the fewest dirty +cache lines when creating a new control group, if requested by the arch code. +This depends on the values read from the llc_occupancy counters. The logic is +applicable to architectures where the CLOSID effectively forms part of the +monitoring identifier and so do not allow complete freedom to choose an unused +monitoring identifier for a given CLOSID. + +This support missed that some platforms may not have these counters. This +causes a NULL pointer dereference when creating a new control group as the +array was not allocated by dom_data_init(). + +As this feature isn't necessary on platforms that don't have cache occupancy +monitors, add this to the check that occurs when a new control group is +allocated. + +Fixes: 6eac36bb9eb0 ("x86/resctrl: Allocate the cleanest CLOSID by searching closid_num_dirty_rmid") +Signed-off-by: James Morse +Signed-off-by: Borislav Petkov (AMD) +Reviewed-by: Shaopeng Tan +Reviewed-by: David Hildenbrand +Reviewed-by: Reinette Chatre +Reviewed-by: Tony Luck +Reviewed-by: Fenghua Yu +Reviewed-by: Babu Moger +Tested-by: Carl Worth # arm64 +Tested-by: Shaopeng Tan +Tested-by: Peter Newman +Tested-by: Amit Singh Tomar # arm64 +Tested-by: Shanker Donthineni # arm64 +Tested-by: Babu Moger +Link: https://lore.kernel.org/r/20250311183715.16445-2-james.morse@arm.com +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/cpu/resctrl/rdtgroup.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c +index 6419e04d8a7b2..04b653d613e88 100644 +--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c ++++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c +@@ -157,7 +157,8 @@ static int closid_alloc(void) + + lockdep_assert_held(&rdtgroup_mutex); + +- if (IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID)) { ++ if (IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID) && ++ is_llc_occupancy_enabled()) { + cleanest_closid = resctrl_find_cleanest_closid(); + if (cleanest_closid < 0) + return cleanest_closid; +-- +2.39.5 + diff --git a/queue-6.14/x86-sev-add-missing-rip_rel_ref-invocations-during-s.patch b/queue-6.14/x86-sev-add-missing-rip_rel_ref-invocations-during-s.patch new file mode 100644 index 0000000000..eed5b56abb --- /dev/null +++ b/queue-6.14/x86-sev-add-missing-rip_rel_ref-invocations-during-s.patch @@ -0,0 +1,52 @@ +From c1a8403bb7e98c7e05818dd490d31fa61fe7c183 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Nov 2024 20:23:22 +0000 +Subject: x86/sev: Add missing RIP_REL_REF() invocations during sme_enable() + +From: Kevin Loughlin + +[ Upstream commit 72dafb567760320f2de7447cd6e979bf9d4e5d17 ] + +The following commit: + + 1c811d403afd ("x86/sev: Fix position dependent variable references in startup code") + +introduced RIP_REL_REF() to force RIP-relative accesses to global variables, +as needed to prevent crashes during early SEV/SME startup code. + +For completeness, RIP_REL_REF() should be used with additional variables during +sme_enable(): + + https://lore.kernel.org/all/CAMj1kXHnA0fJu6zh634=fbJswp59kSRAbhW+ubDGj1+NYwZJ-Q@mail.gmail.com/ + +Access these vars with RIP_REL_REF() to prevent problem reoccurence. + +Fixes: 1c811d403afd ("x86/sev: Fix position dependent variable references in startup code") +Signed-off-by: Kevin Loughlin +Signed-off-by: Ingo Molnar +Reviewed-by: Ard Biesheuvel +Reviewed-by: Tom Lendacky +Cc: Dave Hansen +Link: https://lore.kernel.org/r/20241122202322.977678-1-kevinloughlin@google.com +Signed-off-by: Sasha Levin +--- + arch/x86/mm/mem_encrypt_identity.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c +index e6c7686f443a0..9fce5b87b8c50 100644 +--- a/arch/x86/mm/mem_encrypt_identity.c ++++ b/arch/x86/mm/mem_encrypt_identity.c +@@ -565,7 +565,7 @@ void __head sme_enable(struct boot_params *bp) + } + + RIP_REL_REF(sme_me_mask) = me_mask; +- physical_mask &= ~me_mask; +- cc_vendor = CC_VENDOR_AMD; ++ RIP_REL_REF(physical_mask) &= ~me_mask; ++ RIP_REL_REF(cc_vendor) = CC_VENDOR_AMD; + cc_set_mask(me_mask); + } +-- +2.39.5 + diff --git a/queue-6.14/x86-split_lock-fix-the-delayed-detection-logic.patch b/queue-6.14/x86-split_lock-fix-the-delayed-detection-logic.patch new file mode 100644 index 0000000000..e4e292093f --- /dev/null +++ b/queue-6.14/x86-split_lock-fix-the-delayed-detection-logic.patch @@ -0,0 +1,161 @@ +From 0f37747df0229dffbd0a837fcf76e6a1ee89d935 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jan 2025 16:17:04 +0300 +Subject: x86/split_lock: Fix the delayed detection logic + +From: Maksim Davydov + +[ Upstream commit c929d08df8bee855528b9d15b853c892c54e1eee ] + +If the warning mode with disabled mitigation mode is used, then on each +CPU where the split lock occurred detection will be disabled in order to +make progress and delayed work will be scheduled, which then will enable +detection back. + +Now it turns out that all CPUs use one global delayed work structure. +This leads to the fact that if a split lock occurs on several CPUs +at the same time (within 2 jiffies), only one CPU will schedule delayed +work, but the rest will not. + +The return value of schedule_delayed_work_on() would have shown this, +but it is not checked in the code. + +A diagram that can help to understand the bug reproduction: + + - sld_update_msr() enables/disables SLD on both CPUs on the same core + + - schedule_delayed_work_on() internally checks WORK_STRUCT_PENDING_BIT. + If a work has the 'pending' status, then schedule_delayed_work_on() + will return an error code and, most importantly, the work will not + be placed in the workqueue. + +Let's say we have a multicore system on which split_lock_mitigate=0 and +a multithreaded application is running that calls splitlock in multiple +threads. Due to the fact that sld_update_msr() affects the entire core +(both CPUs), we will consider 2 CPUs from different cores. Let the 2 +threads of this application schedule to CPU0 (core 0) and to CPU 2 +(core 1), then: + +| || | +| CPU 0 (core 0) || CPU 2 (core 1) | +|_________________________________||___________________________________| +| || | +| 1) SPLIT LOCK occured || | +| || | +| 2) split_lock_warn() || | +| || | +| 3) sysctl_sld_mitigate == 0 || | +| (work = &sl_reenable) || | +| || | +| 4) schedule_delayed_work_on() || | +| (reenable will be called || | +| after 2 jiffies on CPU 0) || | +| || | +| 5) disable SLD for core 0 || | +| || | +| ------------------------- || | +| || | +| || 6) SPLIT LOCK occured | +| || | +| || 7) split_lock_warn() | +| || | +| || 8) sysctl_sld_mitigate == 0 | +| || (work = &sl_reenable, | +| || the same address as in 3) ) | +| || | +| 2 jiffies || 9) schedule_delayed_work_on() | +| || fials because the work is in | +| || the pending state since 4). | +| || The work wasn't placed to the | +| || workqueue. reenable won't be | +| || called on CPU 2 | +| || | +| || 10) disable SLD for core 0 | +| || | +| || From now on SLD will | +| || never be reenabled on core 1 | +| || | +| ------------------------- || | +| || | +| 11) enable SLD for core 0 by || | +| __split_lock_reenable || | +| || | + +If the application threads can be scheduled to all processor cores, +then over time there will be only one core left, on which SLD will be +enabled and split lock will be able to be detected; and on all other +cores SLD will be disabled all the time. + +Most likely, this bug has not been noticed for so long because +sysctl_sld_mitigate default value is 1, and in this case a semaphore +is used that does not allow 2 different cores to have SLD disabled at +the same time, that is, strictly only one work is placed in the +workqueue. + +In order to fix the warning mode with disabled mitigation mode, +delayed work has to be per-CPU. Implement it. + +Fixes: 727209376f49 ("x86/split_lock: Add sysctl to control the misery mode") +Signed-off-by: Maksim Davydov +Signed-off-by: Ingo Molnar +Tested-by: Guilherme G. Piccoli +Cc: Thomas Gleixner +Cc: Ravi Bangoria +Cc: Tom Lendacky +Link: https://lore.kernel.org/r/20250115131704.132609-1-davydov-max@yandex-team.ru +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/cpu/bus_lock.c | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +diff --git a/arch/x86/kernel/cpu/bus_lock.c b/arch/x86/kernel/cpu/bus_lock.c +index 6cba85c79d42d..97222efb4d2a6 100644 +--- a/arch/x86/kernel/cpu/bus_lock.c ++++ b/arch/x86/kernel/cpu/bus_lock.c +@@ -192,7 +192,13 @@ static void __split_lock_reenable(struct work_struct *work) + { + sld_update_msr(true); + } +-static DECLARE_DELAYED_WORK(sl_reenable, __split_lock_reenable); ++/* ++ * In order for each CPU to schedule its delayed work independently of the ++ * others, delayed work struct must be per-CPU. This is not required when ++ * sysctl_sld_mitigate is enabled because of the semaphore that limits ++ * the number of simultaneously scheduled delayed works to 1. ++ */ ++static DEFINE_PER_CPU(struct delayed_work, sl_reenable); + + /* + * If a CPU goes offline with pending delayed work to re-enable split lock +@@ -213,7 +219,7 @@ static int splitlock_cpu_offline(unsigned int cpu) + + static void split_lock_warn(unsigned long ip) + { +- struct delayed_work *work; ++ struct delayed_work *work = NULL; + int cpu; + + if (!current->reported_split_lock) +@@ -235,11 +241,17 @@ static void split_lock_warn(unsigned long ip) + if (down_interruptible(&buslock_sem) == -EINTR) + return; + work = &sl_reenable_unlock; +- } else { +- work = &sl_reenable; + } + + cpu = get_cpu(); ++ ++ if (!work) { ++ work = this_cpu_ptr(&sl_reenable); ++ /* Deferred initialization of per-CPU struct */ ++ if (!work->work.func) ++ INIT_DELAYED_WORK(work, __split_lock_reenable); ++ } ++ + schedule_delayed_work_on(cpu, work, 2); + + /* Disable split lock detection on this CPU to make progress */ +-- +2.39.5 + diff --git a/queue-6.14/x86-traps-make-exc_double_fault-consistently-noretur.patch b/queue-6.14/x86-traps-make-exc_double_fault-consistently-noretur.patch new file mode 100644 index 0000000000..c639c8f3eb --- /dev/null +++ b/queue-6.14/x86-traps-make-exc_double_fault-consistently-noretur.patch @@ -0,0 +1,127 @@ +From c78c9a37a59b47ffe3c2e5d446ef927ed7ba2f6b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 12:28:59 -0700 +Subject: x86/traps: Make exc_double_fault() consistently noreturn + +From: Josh Poimboeuf + +[ Upstream commit 8085fcd78c1a3dbdf2278732579009d41ce0bc4e ] + +The CONFIG_X86_ESPFIX64 version of exc_double_fault() can return to its +caller, but the !CONFIG_X86_ESPFIX64 version never does. In the latter +case the compiler and/or objtool may consider it to be implicitly +noreturn. + +However, due to the currently inflexible way objtool detects noreturns, +a function's noreturn status needs to be consistent across configs. + +The current workaround for this issue is to suppress unreachable +warnings for exc_double_fault()'s callers. Unfortunately that can +result in ORC coverage gaps and potentially worse issues like inert +static calls and silently disabled CPU mitigations. + +Instead, prevent exc_double_fault() from ever being implicitly marked +noreturn by forcing a return behind a never-taken conditional. + +Until a more integrated noreturn detection method exists, this is likely +the least objectionable workaround. + +Fixes: 55eeab2a8a11 ("objtool: Ignore exc_double_fault() __noreturn warnings") +Signed-off-by: Josh Poimboeuf +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Brendan Jackman +Link: https://lore.kernel.org/r/d1f4026f8dc35d0de6cc61f2684e0cb6484009d1.1741975349.git.jpoimboe@kernel.org +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/traps.c | 18 +++++++++++++++++- + tools/objtool/check.c | 31 +------------------------------ + 2 files changed, 18 insertions(+), 31 deletions(-) + +diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c +index 2dbadf347b5f4..5e3e036e6e537 100644 +--- a/arch/x86/kernel/traps.c ++++ b/arch/x86/kernel/traps.c +@@ -379,6 +379,21 @@ __visible void __noreturn handle_stack_overflow(struct pt_regs *regs, + } + #endif + ++/* ++ * Prevent the compiler and/or objtool from marking the !CONFIG_X86_ESPFIX64 ++ * version of exc_double_fault() as noreturn. Otherwise the noreturn mismatch ++ * between configs triggers objtool warnings. ++ * ++ * This is a temporary hack until we have compiler or plugin support for ++ * annotating noreturns. ++ */ ++#ifdef CONFIG_X86_ESPFIX64 ++#define always_true() true ++#else ++bool always_true(void); ++bool __weak always_true(void) { return true; } ++#endif ++ + /* + * Runs on an IST stack for x86_64 and on a special task stack for x86_32. + * +@@ -514,7 +529,8 @@ DEFINE_IDTENTRY_DF(exc_double_fault) + + pr_emerg("PANIC: double fault, error_code: 0x%lx\n", error_code); + die("double fault", regs, error_code); +- panic("Machine halted."); ++ if (always_true()) ++ panic("Machine halted."); + instrumentation_end(); + } + +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index ce973d9d8e6d8..c1fa0220f33de 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -4449,35 +4449,6 @@ static int validate_sls(struct objtool_file *file) + return warnings; + } + +-static bool ignore_noreturn_call(struct instruction *insn) +-{ +- struct symbol *call_dest = insn_call_dest(insn); +- +- /* +- * FIXME: hack, we need a real noreturn solution +- * +- * Problem is, exc_double_fault() may or may not return, depending on +- * whether CONFIG_X86_ESPFIX64 is set. But objtool has no visibility +- * to the kernel config. +- * +- * Other potential ways to fix it: +- * +- * - have compiler communicate __noreturn functions somehow +- * - remove CONFIG_X86_ESPFIX64 +- * - read the .config file +- * - add a cmdline option +- * - create a generic objtool annotation format (vs a bunch of custom +- * formats) and annotate it +- */ +- if (!strcmp(call_dest->name, "exc_double_fault")) { +- /* prevent further unreachable warnings for the caller */ +- insn->sym->warned = 1; +- return true; +- } +- +- return false; +-} +- + static int validate_reachable_instructions(struct objtool_file *file) + { + struct instruction *insn, *prev_insn; +@@ -4494,7 +4465,7 @@ static int validate_reachable_instructions(struct objtool_file *file) + prev_insn = prev_insn_same_sec(file, insn); + if (prev_insn && prev_insn->dead_end) { + call_dest = insn_call_dest(prev_insn); +- if (call_dest && !ignore_noreturn_call(prev_insn)) { ++ if (call_dest) { + WARN_INSN(insn, "%s() is missing a __noreturn annotation", + call_dest->name); + warnings++; +-- +2.39.5 + diff --git a/queue-6.14/x86-uaccess-improve-performance-by-aligning-writes-t.patch b/queue-6.14/x86-uaccess-improve-performance-by-aligning-writes-t.patch new file mode 100644 index 0000000000..c845cdca0c --- /dev/null +++ b/queue-6.14/x86-uaccess-improve-performance-by-aligning-writes-t.patch @@ -0,0 +1,190 @@ +From de70e543d840bd87c2abdfdbbb81f9f3c8b07790 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Mar 2025 11:22:13 -0300 +Subject: x86/uaccess: Improve performance by aligning writes to 8 bytes in + copy_user_generic(), on non-FSRM/ERMS CPUs + +From: Herton R. Krzesinski + +[ Upstream commit b5322b6ec06a6c58650f52abcd2492000396363b ] + +History of the performance regression: +====================================== + +Since the following series of user copy updates were merged upstream +~2 years ago via: + + a5624566431d ("Merge branch 'x86-rep-insns': x86 user copy clarifications") + +.. copy_user_generic() on x86_64 stopped doing alignment of the +writes to the destination to a 8 byte boundary for the non FSRM case. + +Previously, this was done through the ALIGN_DESTINATION macro that +was used in the now removed copy_user_generic_unrolled function. + +Turns out this change causes some loss of performance/throughput on +some use cases and specific CPU/platforms without FSRM and ERMS. + +Lately I got two reports of performance/throughput issues after a +RHEL 9 kernel pulled the same upstream series with updates to user +copy functions. Both reports consisted of running specific +networking/TCP related testing using iperf3. + +Partial upstream fix +==================== + +The first report was related to a Linux Bridge testing using VMs on a +specific machine with an AMD CPU (EPYC 7402), and after a brief +investigation it turned out that the later change via: + + ca96b162bfd2 ("x86: bring back rep movsq for user access on CPUs without ERMS") + +... helped/fixed the performance issue. + +However, after the later commit/fix was applied, then I got another +regression reported in a multistream TCP test on a 100Gbit mlx5 nic, also +running on an AMD based platform (AMD EPYC 7302 CPU), again that was using +iperf3 to run the test. That regression was after applying the later +fix/commit, but only this didn't help in telling the whole history. + +Testing performed to pinpoint residual regression +================================================= + +So I narrowed down the second regression use case, but running it +without traffic through a NIC, on localhost, in trying to narrow down +CPU usage and not being limited by other factor like network bandwidth. +I used another system also with an AMD CPU (AMD EPYC 7742). Basically, +I run iperf3 in server and client mode in the same system, for example: + + - Start the server binding it to CPU core/thread 19: + $ taskset -c 19 iperf3 -D -s -B 127.0.0.1 -p 12000 + + - Start the client always binding/running on CPU core/thread 17, using + perf to get statistics: + $ perf stat -o stat.txt taskset -c 17 iperf3 -c 127.0.0.1 -b 0/1000 -V \ + -n 50G --repeating-payload -l 16384 -p 12000 --cport 12001 2>&1 \ + > stat-19.txt + +For the client, always running/pinned to CPU 17. But for the iperf3 in +server mode, I did test runs using CPUs 19, 21, 23 or not pinned to any +specific CPU. So it basically consisted with four runs of the same +commands, just changing the CPU which the server is pinned, or without +pinning by removing the taskset call before the server command. The CPUs +were chosen based on NUMA node they were on, this is the relevant output +of lscpu on the system: + + $ lscpu + ... + Model name: AMD EPYC 7742 64-Core Processor + ... + Caches (sum of all): + L1d: 2 MiB (64 instances) + L1i: 2 MiB (64 instances) + L2: 32 MiB (64 instances) + L3: 256 MiB (16 instances) + NUMA: + NUMA node(s): 4 + NUMA node0 CPU(s): 0,1,8,9,16,17,24,25,32,33,40,41,48,49,56,57,64,65,72,73,80,81,88,89,96,97,104,105,112,113,120,121 + NUMA node1 CPU(s): 2,3,10,11,18,19,26,27,34,35,42,43,50,51,58,59,66,67,74,75,82,83,90,91,98,99,106,107,114,115,122,123 + NUMA node2 CPU(s): 4,5,12,13,20,21,28,29,36,37,44,45,52,53,60,61,68,69,76,77,84,85,92,93,100,101,108,109,116,117,124,125 + NUMA node3 CPU(s): 6,7,14,15,22,23,30,31,38,39,46,47,54,55,62,63,70,71,78,79,86,87,94,95,102,103,110,111,118,119,126,127 + ... + +So for the server run, when picking a CPU, I chose CPUs to be not on the same +node. The reason is with that I was able to get/measure relevant +performance differences when changing the alignment of the writes to the +destination in copy_user_generic. + +Testing shows up to +81% performance improvement under iperf3 +============================================================= + +Here's a summary of the iperf3 runs: + + # Vanilla upstream alignment: + + CPU RATE SYS TIME sender-receiver + Server bind 19: 13.0Gbits/sec 28.371851000 33.233499566 86.9%-70.8% + Server bind 21: 12.9Gbits/sec 28.283381000 33.586486621 85.8%-69.9% + Server bind 23: 11.1Gbits/sec 33.660190000 39.012243176 87.7%-64.5% + Server bind none: 18.9Gbits/sec 19.215339000 22.875117865 86.0%-80.5% + + # With the attached patch (aligning writes in non ERMS/FSRM case): + + CPU RATE SYS TIME sender-receiver + Server bind 19: 20.8Gbits/sec 14.897284000 20.811101382 75.7%-89.0% + Server bind 21: 20.4Gbits/sec 15.205055000 21.263165909 75.4%-89.7% + Server bind 23: 20.2Gbits/sec 15.433801000 21.456175000 75.5%-89.8% + Server bind none: 26.1Gbits/sec 12.534022000 16.632447315 79.8%-89.6% + +So I consistently got better results when aligning the write. The +results above were run on 6.14.0-rc6/rc7 based kernels. The sys is sys +time and then the total time to run/transfer 50G of data. The last +field is the CPU usage of sender/receiver iperf3 process. It's also +worth to note that each pair of iperf3 runs may get slightly different +results on each run, but I always got consistent higher results with +the write alignment for this specific test of running the processes +on CPUs in different NUMA nodes. + +Linus Torvalds helped/provided this version of the patch. Initially I +proposed a version which aligned writes for all cases in +rep_movs_alternative, however it used two extra registers and thus +Linus provided an enhanced version that only aligns the write on the +large_movsq case, which is sufficient since the problem happens only +on those AMD CPUs like ones mentioned above without ERMS/FSRM, and +also doesn't require using extra registers. Also, I validated that +aligning only on large_movsq case is really enough for getting the +performance back. + +I also tested this patch on an old Intel based non-ERMS/FRMS system +(with Xeon E5-2667 - Sandy Bridge based) and didn't get any problems: +no performance enhancement but also no regression either, using the +same iperf3 based benchmark. Also newer Intel processors after +Sandy Bridge usually have ERMS and should not be affected by this change. + +[ mingo: Updated the changelog. ] + +Fixes: ca96b162bfd2 ("x86: bring back rep movsq for user access on CPUs without ERMS") +Fixes: 034ff37d3407 ("x86: rewrite '__copy_user_nocache' function") +Reported-by: Ondrej Lichtner +Co-developed-by: Linus Torvalds +Signed-off-by: Linus Torvalds +Signed-off-by: Herton R. Krzesinski +Signed-off-by: Ingo Molnar +Link: https://lore.kernel.org/r/20250320142213.2623518-1-herton@redhat.com +Signed-off-by: Sasha Levin +--- + arch/x86/lib/copy_user_64.S | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S +index fc9fb5d061744..b8f74d80f35c6 100644 +--- a/arch/x86/lib/copy_user_64.S ++++ b/arch/x86/lib/copy_user_64.S +@@ -74,6 +74,24 @@ SYM_FUNC_START(rep_movs_alternative) + _ASM_EXTABLE_UA( 0b, 1b) + + .Llarge_movsq: ++ /* Do the first possibly unaligned word */ ++0: movq (%rsi),%rax ++1: movq %rax,(%rdi) ++ ++ _ASM_EXTABLE_UA( 0b, .Lcopy_user_tail) ++ _ASM_EXTABLE_UA( 1b, .Lcopy_user_tail) ++ ++ /* What would be the offset to the aligned destination? */ ++ leaq 8(%rdi),%rax ++ andq $-8,%rax ++ subq %rdi,%rax ++ ++ /* .. and update pointers and count to match */ ++ addq %rax,%rdi ++ addq %rax,%rsi ++ subq %rax,%rcx ++ ++ /* make %rcx contain the number of words, %rax the remainder */ + movq %rcx,%rax + shrq $3,%rcx + andl $7,%eax +-- +2.39.5 + diff --git a/queue-6.14/x86-vdso-fix-latent-bug-in-vclock_pages-calculation.patch b/queue-6.14/x86-vdso-fix-latent-bug-in-vclock_pages-calculation.patch new file mode 100644 index 0000000000..d72220abae --- /dev/null +++ b/queue-6.14/x86-vdso-fix-latent-bug-in-vclock_pages-calculation.patch @@ -0,0 +1,73 @@ +From 701d8e123ed4a266653cbb14a8b1d2abcc63b5be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 13:05:33 +0100 +Subject: x86/vdso: Fix latent bug in vclock_pages calculation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Thomas Weißschuh + +[ Upstream commit 3ef32d90cdaa0cfa6c4ffd18f8d646a658163e3d ] + +The vclock pages are *after* the non-vclock pages. Currently there are both +two vclock and two non-vclock pages so the existing logic works by +accident. As soon as the number of pages changes it will break however. +This will be the case with the introduction of the generic vDSO data +storage. + +Use a macro to keep the calculation understandable and in sync between +the linker script and mapping code. + +Fixes: e93d2521b27f ("x86/vdso: Split virtual clock pages into dedicated mapping") +Signed-off-by: Thomas Weißschuh +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/all/20250204-vdso-store-rng-v3-1-13a4669dfc8c@linutronix.de +Signed-off-by: Sasha Levin +--- + arch/x86/entry/vdso/vdso-layout.lds.S | 2 +- + arch/x86/entry/vdso/vma.c | 2 +- + arch/x86/include/asm/vdso/vsyscall.h | 1 + + 3 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/entry/vdso/vdso-layout.lds.S b/arch/x86/entry/vdso/vdso-layout.lds.S +index 872947c1004c3..918606ff92a98 100644 +--- a/arch/x86/entry/vdso/vdso-layout.lds.S ++++ b/arch/x86/entry/vdso/vdso-layout.lds.S +@@ -24,7 +24,7 @@ SECTIONS + + timens_page = vvar_start + PAGE_SIZE; + +- vclock_pages = vvar_start + VDSO_NR_VCLOCK_PAGES * PAGE_SIZE; ++ vclock_pages = VDSO_VCLOCK_PAGES_START(vvar_start); + pvclock_page = vclock_pages + VDSO_PAGE_PVCLOCK_OFFSET * PAGE_SIZE; + hvclock_page = vclock_pages + VDSO_PAGE_HVCLOCK_OFFSET * PAGE_SIZE; + +diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c +index 39e6efc1a9cab..aa62949335ece 100644 +--- a/arch/x86/entry/vdso/vma.c ++++ b/arch/x86/entry/vdso/vma.c +@@ -290,7 +290,7 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr) + } + + vma = _install_special_mapping(mm, +- addr + (__VVAR_PAGES - VDSO_NR_VCLOCK_PAGES) * PAGE_SIZE, ++ VDSO_VCLOCK_PAGES_START(addr), + VDSO_NR_VCLOCK_PAGES * PAGE_SIZE, + VM_READ|VM_MAYREAD|VM_IO|VM_DONTDUMP| + VM_PFNMAP, +diff --git a/arch/x86/include/asm/vdso/vsyscall.h b/arch/x86/include/asm/vdso/vsyscall.h +index 37b4a70559a82..88b31d4cdfaf3 100644 +--- a/arch/x86/include/asm/vdso/vsyscall.h ++++ b/arch/x86/include/asm/vdso/vsyscall.h +@@ -6,6 +6,7 @@ + #define __VVAR_PAGES 4 + + #define VDSO_NR_VCLOCK_PAGES 2 ++#define VDSO_VCLOCK_PAGES_START(_b) ((_b) + (__VVAR_PAGES - VDSO_NR_VCLOCK_PAGES) * PAGE_SIZE) + #define VDSO_PAGE_PVCLOCK_OFFSET 0 + #define VDSO_PAGE_HVCLOCK_OFFSET 1 + +-- +2.39.5 + diff --git a/queue-6.14/xfrm-delay-initialization-of-offload-path-till-its-a.patch b/queue-6.14/xfrm-delay-initialization-of-offload-path-till-its-a.patch new file mode 100644 index 0000000000..acbb0740d3 --- /dev/null +++ b/queue-6.14/xfrm-delay-initialization-of-offload-path-till-its-a.patch @@ -0,0 +1,205 @@ +From 16b6be5eea74dfb291653ad3b16187f1cafde7ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 15:50:57 +0200 +Subject: xfrm: delay initialization of offload path till its actually + requested + +From: Leon Romanovsky + +[ Upstream commit 585b64f5a62089ef42889b106b063d089feb6599 ] + +XFRM offload path is probed even if offload isn't needed at all. Let's +make sure that x->type_offload pointer stays NULL for such path to +reduce ambiguity. + +Fixes: 9d389d7f84bb ("xfrm: Add a xfrm type offload.") +Signed-off-by: Leon Romanovsky +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + include/net/xfrm.h | 11 ++++++++++- + net/xfrm/xfrm_device.c | 13 ++++++++----- + net/xfrm/xfrm_state.c | 32 ++++++++++++++------------------ + net/xfrm/xfrm_user.c | 2 +- + 4 files changed, 33 insertions(+), 25 deletions(-) + +diff --git a/include/net/xfrm.h b/include/net/xfrm.h +index ed4b83696c77f..e1eed5d47d072 100644 +--- a/include/net/xfrm.h ++++ b/include/net/xfrm.h +@@ -464,6 +464,15 @@ struct xfrm_type_offload { + + int xfrm_register_type_offload(const struct xfrm_type_offload *type, unsigned short family); + void xfrm_unregister_type_offload(const struct xfrm_type_offload *type, unsigned short family); ++void xfrm_set_type_offload(struct xfrm_state *x); ++static inline void xfrm_unset_type_offload(struct xfrm_state *x) ++{ ++ if (!x->type_offload) ++ return; ++ ++ module_put(x->type_offload->owner); ++ x->type_offload = NULL; ++} + + /** + * struct xfrm_mode_cbs - XFRM mode callbacks +@@ -1760,7 +1769,7 @@ void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si); + u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq); + int xfrm_init_replay(struct xfrm_state *x, struct netlink_ext_ack *extack); + u32 xfrm_state_mtu(struct xfrm_state *x, int mtu); +-int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload, ++int __xfrm_init_state(struct xfrm_state *x, bool init_replay, + struct netlink_ext_ack *extack); + int xfrm_init_state(struct xfrm_state *x); + int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type); +diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c +index d1fa94e52ceae..97c8030cc4173 100644 +--- a/net/xfrm/xfrm_device.c ++++ b/net/xfrm/xfrm_device.c +@@ -244,11 +244,6 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, + xfrm_address_t *daddr; + bool is_packet_offload; + +- if (!x->type_offload) { +- NL_SET_ERR_MSG(extack, "Type doesn't support offload"); +- return -EINVAL; +- } +- + if (xuo->flags & + ~(XFRM_OFFLOAD_IPV6 | XFRM_OFFLOAD_INBOUND | XFRM_OFFLOAD_PACKET)) { + NL_SET_ERR_MSG(extack, "Unrecognized flags in offload request"); +@@ -310,6 +305,13 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, + return -EINVAL; + } + ++ xfrm_set_type_offload(x); ++ if (!x->type_offload) { ++ NL_SET_ERR_MSG(extack, "Type doesn't support offload"); ++ dev_put(dev); ++ return -EINVAL; ++ } ++ + xso->dev = dev; + netdev_tracker_alloc(dev, &xso->dev_tracker, GFP_ATOMIC); + xso->real_dev = dev; +@@ -332,6 +334,7 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, + netdev_put(dev, &xso->dev_tracker); + xso->type = XFRM_DEV_OFFLOAD_UNSPECIFIED; + ++ xfrm_unset_type_offload(x); + /* User explicitly requested packet offload mode and configured + * policy in addition to the XFRM state. So be civil to users, + * and return an error instead of taking fallback path. +diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c +index ad2202fa82f34..69af5964c886c 100644 +--- a/net/xfrm/xfrm_state.c ++++ b/net/xfrm/xfrm_state.c +@@ -424,18 +424,18 @@ void xfrm_unregister_type_offload(const struct xfrm_type_offload *type, + } + EXPORT_SYMBOL(xfrm_unregister_type_offload); + +-static const struct xfrm_type_offload * +-xfrm_get_type_offload(u8 proto, unsigned short family, bool try_load) ++void xfrm_set_type_offload(struct xfrm_state *x) + { + const struct xfrm_type_offload *type = NULL; + struct xfrm_state_afinfo *afinfo; ++ bool try_load = true; + + retry: +- afinfo = xfrm_state_get_afinfo(family); ++ afinfo = xfrm_state_get_afinfo(x->props.family); + if (unlikely(afinfo == NULL)) +- return NULL; ++ goto out; + +- switch (proto) { ++ switch (x->id.proto) { + case IPPROTO_ESP: + type = afinfo->type_offload_esp; + break; +@@ -449,18 +449,16 @@ xfrm_get_type_offload(u8 proto, unsigned short family, bool try_load) + rcu_read_unlock(); + + if (!type && try_load) { +- request_module("xfrm-offload-%d-%d", family, proto); ++ request_module("xfrm-offload-%d-%d", x->props.family, ++ x->id.proto); + try_load = false; + goto retry; + } + +- return type; +-} +- +-static void xfrm_put_type_offload(const struct xfrm_type_offload *type) +-{ +- module_put(type->owner); ++out: ++ x->type_offload = type; + } ++EXPORT_SYMBOL(xfrm_set_type_offload); + + static const struct xfrm_mode xfrm4_mode_map[XFRM_MODE_MAX] = { + [XFRM_MODE_BEET] = { +@@ -609,8 +607,6 @@ static void ___xfrm_state_destroy(struct xfrm_state *x) + kfree(x->coaddr); + kfree(x->replay_esn); + kfree(x->preplay_esn); +- if (x->type_offload) +- xfrm_put_type_offload(x->type_offload); + if (x->type) { + x->type->destructor(x); + xfrm_put_type(x->type); +@@ -784,6 +780,8 @@ void xfrm_dev_state_free(struct xfrm_state *x) + struct xfrm_dev_offload *xso = &x->xso; + struct net_device *dev = READ_ONCE(xso->dev); + ++ xfrm_unset_type_offload(x); ++ + if (dev && dev->xfrmdev_ops) { + spin_lock_bh(&xfrm_state_dev_gc_lock); + if (!hlist_unhashed(&x->dev_gclist)) +@@ -3122,7 +3120,7 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu) + } + EXPORT_SYMBOL_GPL(xfrm_state_mtu); + +-int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload, ++int __xfrm_init_state(struct xfrm_state *x, bool init_replay, + struct netlink_ext_ack *extack) + { + const struct xfrm_mode *inner_mode; +@@ -3178,8 +3176,6 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload, + goto error; + } + +- x->type_offload = xfrm_get_type_offload(x->id.proto, family, offload); +- + err = x->type->init_state(x, extack); + if (err) + goto error; +@@ -3229,7 +3225,7 @@ int xfrm_init_state(struct xfrm_state *x) + { + int err; + +- err = __xfrm_init_state(x, true, false, NULL); ++ err = __xfrm_init_state(x, true, NULL); + if (!err) + x->km.state = XFRM_STATE_VALID; + +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index 08c6d6f0179fb..82a768500999b 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -907,7 +907,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, + goto error; + } + +- err = __xfrm_init_state(x, false, attrs[XFRMA_OFFLOAD_DEV], extack); ++ err = __xfrm_init_state(x, false, extack); + if (err) + goto error; + +-- +2.39.5 + diff --git a/queue-6.14/xsk-add-launch-time-hardware-offload-support-to-xdp-.patch b/queue-6.14/xsk-add-launch-time-hardware-offload-support-to-xdp-.patch new file mode 100644 index 0000000000..016b15d5d1 --- /dev/null +++ b/queue-6.14/xsk-add-launch-time-hardware-offload-support-to-xdp-.patch @@ -0,0 +1,305 @@ +From be8f0ca04a18729531cabc24b350ba33e1d4f507 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Feb 2025 17:34:26 +0800 +Subject: xsk: Add launch time hardware offload support to XDP Tx metadata + +From: Song Yoong Siang + +[ Upstream commit ca4419f15abd19ba8be1e109661b60f9f5b6c9f0 ] + +Extend the XDP Tx metadata framework so that user can requests launch time +hardware offload, where the Ethernet device will schedule the packet for +transmission at a pre-determined time called launch time. The value of +launch time is communicated from user space to Ethernet driver via +launch_time field of struct xsk_tx_metadata. + +Suggested-by: Stanislav Fomichev +Signed-off-by: Song Yoong Siang +Signed-off-by: Martin KaFai Lau +Acked-by: Stanislav Fomichev +Acked-by: Jakub Kicinski +Link: https://patch.msgid.link/20250216093430.957880-2-yoong.siang.song@intel.com +Stable-dep-of: d931cf9b38da ("igc: Fix TX drops in XDP ZC") +Signed-off-by: Sasha Levin +--- + Documentation/netlink/specs/netdev.yaml | 4 ++ + Documentation/networking/xsk-tx-metadata.rst | 62 ++++++++++++++++++++ + include/net/xdp_sock.h | 10 ++++ + include/net/xdp_sock_drv.h | 1 + + include/uapi/linux/if_xdp.h | 10 ++++ + include/uapi/linux/netdev.h | 3 + + net/core/netdev-genl.c | 2 + + net/xdp/xsk.c | 3 + + tools/include/uapi/linux/if_xdp.h | 10 ++++ + tools/include/uapi/linux/netdev.h | 3 + + 10 files changed, 108 insertions(+) + +diff --git a/Documentation/netlink/specs/netdev.yaml b/Documentation/netlink/specs/netdev.yaml +index cbb544bd6c848..901b5afb3df0d 100644 +--- a/Documentation/netlink/specs/netdev.yaml ++++ b/Documentation/netlink/specs/netdev.yaml +@@ -70,6 +70,10 @@ definitions: + name: tx-checksum + doc: + L3 checksum HW offload is supported by the driver. ++ - ++ name: tx-launch-time-fifo ++ doc: ++ Launch time HW offload is supported by the driver. + - + name: queue-type + type: enum +diff --git a/Documentation/networking/xsk-tx-metadata.rst b/Documentation/networking/xsk-tx-metadata.rst +index e76b0cfc32f7d..df53a10ccac34 100644 +--- a/Documentation/networking/xsk-tx-metadata.rst ++++ b/Documentation/networking/xsk-tx-metadata.rst +@@ -50,6 +50,10 @@ The flags field enables the particular offload: + checksum. ``csum_start`` specifies byte offset of where the checksumming + should start and ``csum_offset`` specifies byte offset where the + device should store the computed checksum. ++- ``XDP_TXMD_FLAGS_LAUNCH_TIME``: requests the device to schedule the ++ packet for transmission at a pre-determined time called launch time. The ++ value of launch time is indicated by ``launch_time`` field of ++ ``union xsk_tx_metadata``. + + Besides the flags above, in order to trigger the offloads, the first + packet's ``struct xdp_desc`` descriptor should set ``XDP_TX_METADATA`` +@@ -65,6 +69,63 @@ In this case, when running in ``XDK_COPY`` mode, the TX checksum + is calculated on the CPU. Do not enable this option in production because + it will negatively affect performance. + ++Launch Time ++=========== ++ ++The value of the requested launch time should be based on the device's PTP ++Hardware Clock (PHC) to ensure accuracy. AF_XDP takes a different data path ++compared to the ETF queuing discipline, which organizes packets and delays ++their transmission. Instead, AF_XDP immediately hands off the packets to ++the device driver without rearranging their order or holding them prior to ++transmission. Since the driver maintains FIFO behavior and does not perform ++packet reordering, a packet with a launch time request will block other ++packets in the same Tx Queue until it is sent. Therefore, it is recommended ++to allocate separate queue for scheduling traffic that is intended for ++future transmission. ++ ++In scenarios where the launch time offload feature is disabled, the device ++driver is expected to disregard the launch time request. For correct ++interpretation and meaningful operation, the launch time should never be ++set to a value larger than the farthest programmable time in the future ++(the horizon). Different devices have different hardware limitations on the ++launch time offload feature. ++ ++stmmac driver ++------------- ++ ++For stmmac, TSO and launch time (TBS) features are mutually exclusive for ++each individual Tx Queue. By default, the driver configures Tx Queue 0 to ++support TSO and the rest of the Tx Queues to support TBS. The launch time ++hardware offload feature can be enabled or disabled by using the tc-etf ++command to call the driver's ndo_setup_tc() callback. ++ ++The value of the launch time that is programmed in the Enhanced Normal ++Transmit Descriptors is a 32-bit value, where the most significant 8 bits ++represent the time in seconds and the remaining 24 bits represent the time ++in 256 ns increments. The programmed launch time is compared against the ++PTP time (bits[39:8]) and rolls over after 256 seconds. Therefore, the ++horizon of the launch time for dwmac4 and dwxlgmac2 is 128 seconds in the ++future. ++ ++igc driver ++---------- ++ ++For igc, all four Tx Queues support the launch time feature. The launch ++time hardware offload feature can be enabled or disabled by using the ++tc-etf command to call the driver's ndo_setup_tc() callback. When entering ++TSN mode, the igc driver will reset the device and create a default Qbv ++schedule with a 1-second cycle time, with all Tx Queues open at all times. ++ ++The value of the launch time that is programmed in the Advanced Transmit ++Context Descriptor is a relative offset to the starting time of the Qbv ++transmission window of the queue. The Frst flag of the descriptor can be ++set to schedule the packet for the next Qbv cycle. Therefore, the horizon ++of the launch time for i225 and i226 is the ending time of the next cycle ++of the Qbv transmission window of the queue. For example, when the Qbv ++cycle time is set to 1 second, the horizon of the launch time ranges ++from 1 second to 2 seconds, depending on where the Qbv cycle is currently ++running. ++ + Querying Device Capabilities + ============================ + +@@ -74,6 +135,7 @@ Refer to ``xsk-flags`` features bitmask in + + - ``tx-timestamp``: device supports ``XDP_TXMD_FLAGS_TIMESTAMP`` + - ``tx-checksum``: device supports ``XDP_TXMD_FLAGS_CHECKSUM`` ++- ``tx-launch-time-fifo``: device supports ``XDP_TXMD_FLAGS_LAUNCH_TIME`` + + See ``tools/net/ynl/samples/netdev.c`` on how to query this information. + +diff --git a/include/net/xdp_sock.h b/include/net/xdp_sock.h +index bfe625b55d55d..a58ae7589d121 100644 +--- a/include/net/xdp_sock.h ++++ b/include/net/xdp_sock.h +@@ -110,11 +110,16 @@ struct xdp_sock { + * indicates position where checksumming should start. + * csum_offset indicates position where checksum should be stored. + * ++ * void (*tmo_request_launch_time)(u64 launch_time, void *priv) ++ * Called when AF_XDP frame requested launch time HW offload support. ++ * launch_time indicates the PTP time at which the device can schedule the ++ * packet for transmission. + */ + struct xsk_tx_metadata_ops { + void (*tmo_request_timestamp)(void *priv); + u64 (*tmo_fill_timestamp)(void *priv); + void (*tmo_request_checksum)(u16 csum_start, u16 csum_offset, void *priv); ++ void (*tmo_request_launch_time)(u64 launch_time, void *priv); + }; + + #ifdef CONFIG_XDP_SOCKETS +@@ -162,6 +167,11 @@ static inline void xsk_tx_metadata_request(const struct xsk_tx_metadata *meta, + if (!meta) + return; + ++ if (ops->tmo_request_launch_time) ++ if (meta->flags & XDP_TXMD_FLAGS_LAUNCH_TIME) ++ ops->tmo_request_launch_time(meta->request.launch_time, ++ priv); ++ + if (ops->tmo_request_timestamp) + if (meta->flags & XDP_TXMD_FLAGS_TIMESTAMP) + ops->tmo_request_timestamp(priv); +diff --git a/include/net/xdp_sock_drv.h b/include/net/xdp_sock_drv.h +index 784cd34f5bba5..fe4afb2517197 100644 +--- a/include/net/xdp_sock_drv.h ++++ b/include/net/xdp_sock_drv.h +@@ -199,6 +199,7 @@ static inline void *xsk_buff_raw_get_data(struct xsk_buff_pool *pool, u64 addr) + #define XDP_TXMD_FLAGS_VALID ( \ + XDP_TXMD_FLAGS_TIMESTAMP | \ + XDP_TXMD_FLAGS_CHECKSUM | \ ++ XDP_TXMD_FLAGS_LAUNCH_TIME | \ + 0) + + static inline bool +diff --git a/include/uapi/linux/if_xdp.h b/include/uapi/linux/if_xdp.h +index 42ec5ddaab8dc..42869770776ec 100644 +--- a/include/uapi/linux/if_xdp.h ++++ b/include/uapi/linux/if_xdp.h +@@ -127,6 +127,12 @@ struct xdp_options { + */ + #define XDP_TXMD_FLAGS_CHECKSUM (1 << 1) + ++/* Request launch time hardware offload. The device will schedule the packet for ++ * transmission at a pre-determined time called launch time. The value of ++ * launch time is communicated via launch_time field of struct xsk_tx_metadata. ++ */ ++#define XDP_TXMD_FLAGS_LAUNCH_TIME (1 << 2) ++ + /* AF_XDP offloads request. 'request' union member is consumed by the driver + * when the packet is being transmitted. 'completion' union member is + * filled by the driver when the transmit completion arrives. +@@ -142,6 +148,10 @@ struct xsk_tx_metadata { + __u16 csum_start; + /* Offset from csum_start where checksum should be stored. */ + __u16 csum_offset; ++ ++ /* XDP_TXMD_FLAGS_LAUNCH_TIME */ ++ /* Launch time in nanosecond against the PTP HW Clock */ ++ __u64 launch_time; + } request; + + struct { +diff --git a/include/uapi/linux/netdev.h b/include/uapi/linux/netdev.h +index e4be227d3ad64..4324e89a80261 100644 +--- a/include/uapi/linux/netdev.h ++++ b/include/uapi/linux/netdev.h +@@ -59,10 +59,13 @@ enum netdev_xdp_rx_metadata { + * by the driver. + * @NETDEV_XSK_FLAGS_TX_CHECKSUM: L3 checksum HW offload is supported by the + * driver. ++ * @NETDEV_XSK_FLAGS_TX_LAUNCH_TIME_FIFO: Launch time HW offload is supported ++ * by the driver. + */ + enum netdev_xsk_flags { + NETDEV_XSK_FLAGS_TX_TIMESTAMP = 1, + NETDEV_XSK_FLAGS_TX_CHECKSUM = 2, ++ NETDEV_XSK_FLAGS_TX_LAUNCH_TIME_FIFO = 4, + }; + + enum netdev_queue_type { +diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c +index 715f85c6b62ea..7832abc5ca6e2 100644 +--- a/net/core/netdev-genl.c ++++ b/net/core/netdev-genl.c +@@ -52,6 +52,8 @@ XDP_METADATA_KFUNC_xxx + xsk_features |= NETDEV_XSK_FLAGS_TX_TIMESTAMP; + if (netdev->xsk_tx_metadata_ops->tmo_request_checksum) + xsk_features |= NETDEV_XSK_FLAGS_TX_CHECKSUM; ++ if (netdev->xsk_tx_metadata_ops->tmo_request_launch_time) ++ xsk_features |= NETDEV_XSK_FLAGS_TX_LAUNCH_TIME_FIFO; + } + + if (nla_put_u32(rsp, NETDEV_A_DEV_IFINDEX, netdev->ifindex) || +diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c +index 89d2bef964698..41093ea63700c 100644 +--- a/net/xdp/xsk.c ++++ b/net/xdp/xsk.c +@@ -742,6 +742,9 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs, + goto free_err; + } + } ++ ++ if (meta->flags & XDP_TXMD_FLAGS_LAUNCH_TIME) ++ skb->skb_mstamp_ns = meta->request.launch_time; + } + } + +diff --git a/tools/include/uapi/linux/if_xdp.h b/tools/include/uapi/linux/if_xdp.h +index 42ec5ddaab8dc..42869770776ec 100644 +--- a/tools/include/uapi/linux/if_xdp.h ++++ b/tools/include/uapi/linux/if_xdp.h +@@ -127,6 +127,12 @@ struct xdp_options { + */ + #define XDP_TXMD_FLAGS_CHECKSUM (1 << 1) + ++/* Request launch time hardware offload. The device will schedule the packet for ++ * transmission at a pre-determined time called launch time. The value of ++ * launch time is communicated via launch_time field of struct xsk_tx_metadata. ++ */ ++#define XDP_TXMD_FLAGS_LAUNCH_TIME (1 << 2) ++ + /* AF_XDP offloads request. 'request' union member is consumed by the driver + * when the packet is being transmitted. 'completion' union member is + * filled by the driver when the transmit completion arrives. +@@ -142,6 +148,10 @@ struct xsk_tx_metadata { + __u16 csum_start; + /* Offset from csum_start where checksum should be stored. */ + __u16 csum_offset; ++ ++ /* XDP_TXMD_FLAGS_LAUNCH_TIME */ ++ /* Launch time in nanosecond against the PTP HW Clock */ ++ __u64 launch_time; + } request; + + struct { +diff --git a/tools/include/uapi/linux/netdev.h b/tools/include/uapi/linux/netdev.h +index e4be227d3ad64..4324e89a80261 100644 +--- a/tools/include/uapi/linux/netdev.h ++++ b/tools/include/uapi/linux/netdev.h +@@ -59,10 +59,13 @@ enum netdev_xdp_rx_metadata { + * by the driver. + * @NETDEV_XSK_FLAGS_TX_CHECKSUM: L3 checksum HW offload is supported by the + * driver. ++ * @NETDEV_XSK_FLAGS_TX_LAUNCH_TIME_FIFO: Launch time HW offload is supported ++ * by the driver. + */ + enum netdev_xsk_flags { + NETDEV_XSK_FLAGS_TX_TIMESTAMP = 1, + NETDEV_XSK_FLAGS_TX_CHECKSUM = 2, ++ NETDEV_XSK_FLAGS_TX_LAUNCH_TIME_FIFO = 4, + }; + + enum netdev_queue_type { +-- +2.39.5 + diff --git a/queue-6.14/xsk-fix-__xsk_generic_xmit-error-code-when-cq-is-ful.patch b/queue-6.14/xsk-fix-__xsk_generic_xmit-error-code-when-cq-is-ful.patch new file mode 100644 index 0000000000..f4d64df63d --- /dev/null +++ b/queue-6.14/xsk-fix-__xsk_generic_xmit-error-code-when-cq-is-ful.patch @@ -0,0 +1,53 @@ +From 39a40bdb93b989324d0c79be82059b141f5d5987 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 16:10:52 +0800 +Subject: xsk: Fix __xsk_generic_xmit() error code when cq is full + +From: Wang Liang + +[ Upstream commit 5d0b204654de25615cf712be86c3192eca68ed80 ] + +When the cq reservation is failed, the error code is not set which is +initialized to zero in __xsk_generic_xmit(). That means the packet is not +send successfully but sendto() return ok. + +Considering the impact on uapi, return -EAGAIN is a good idea. The cq is +full usually because it is not released in time, try to send msg again is +appropriate. + +The bug was at the very early implementation of xsk, so the Fixes tag +targets the commit that introduced the changes in +xsk_cq_reserve_addr_locked where this fix depends on. + +Fixes: e6c4047f5122 ("xsk: Use xsk_buff_pool directly for cq functions") +Suggested-by: Magnus Karlsson +Signed-off-by: Wang Liang +Signed-off-by: Martin KaFai Lau +Acked-by: Stanislav Fomichev +Link: https://patch.msgid.link/20250227081052.4096337-1-wangliang74@huawei.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + net/xdp/xsk.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c +index 41093ea63700c..a373a7130d757 100644 +--- a/net/xdp/xsk.c ++++ b/net/xdp/xsk.c +@@ -805,8 +805,11 @@ static int __xsk_generic_xmit(struct sock *sk) + * if there is space in it. This avoids having to implement + * any buffering in the Tx path. + */ +- if (xsk_cq_reserve_addr_locked(xs->pool, desc.addr)) ++ err = xsk_cq_reserve_addr_locked(xs->pool, desc.addr); ++ if (err) { ++ err = -EAGAIN; + goto out; ++ } + + skb = xsk_build_skb(xs, &desc); + if (IS_ERR(skb)) { +-- +2.39.5 +