From: Sasha Levin Date: Wed, 27 Mar 2024 11:08:43 +0000 (-0400) Subject: Fixes for 5.4 X-Git-Tag: v6.7.12~220 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d5afabcb75c3e3cb27f9ad2e7a5a76ffe859bea8;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.4 Signed-off-by: Sasha Levin --- diff --git a/queue-5.4/ahci-asm1064-asm1166-don-t-limit-reported-ports.patch b/queue-5.4/ahci-asm1064-asm1166-don-t-limit-reported-ports.patch new file mode 100644 index 00000000000..20629101c2d --- /dev/null +++ b/queue-5.4/ahci-asm1064-asm1166-don-t-limit-reported-ports.patch @@ -0,0 +1,89 @@ +From 2f22e2811f1efdbf9914f99db01fa4e6125d199c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Mar 2024 22:46:50 +0100 +Subject: ahci: asm1064: asm1166: don't limit reported ports + +From: Conrad Kostecki + +[ Upstream commit 6cd8adc3e18960f6e59d797285ed34ef473cc896 ] + +Previously, patches have been added to limit the reported count of SATA +ports for asm1064 and asm1166 SATA controllers, as those controllers do +report more ports than physically having. + +While it is allowed to report more ports than physically having in CAP.NP, +it is not allowed to report more ports than physically having in the PI +(Ports Implemented) register, which is what these HBAs do. +(This is a AHCI spec violation.) + +Unfortunately, it seems that the PMP implementation in these ASMedia HBAs +is also violating the AHCI and SATA-IO PMP specification. + +What these HBAs do is that they do not report that they support PMP +(CAP.SPM (Supports Port Multiplier) is not set). + +Instead, they have decided to add extra "virtual" ports in the PI register +that is used if a port multiplier is connected to any of the physical +ports of the HBA. + +Enumerating the devices behind the PMP as specified in the AHCI and +SATA-IO specifications, by using PMP READ and PMP WRITE commands to the +physical ports of the HBA is not possible, you have to use the "virtual" +ports. + +This is of course bad, because this gives us no way to detect the device +and vendor ID of the PMP actually connected to the HBA, which means that +we can not apply the proper PMP quirks for the PMP that is connected to +the HBA. + +Limiting the port map will thus stop these controllers from working with +SATA Port Multipliers. + +This patch reverts both patches for asm1064 and asm1166, so old behavior +is restored and SATA PMP will work again, but it will also reintroduce the +(minutes long) extra boot time for the ASMedia controllers that do not +have a PMP connected (either on the PCIe card itself, or an external PMP). + +However, a longer boot time for some, is the lesser evil compared to some +other users not being able to detect their drives at all. + +Fixes: 0077a504e1a4 ("ahci: asm1166: correct count of reported ports") +Fixes: 9815e3961754 ("ahci: asm1064: correct count of reported ports") +Cc: stable@vger.kernel.org +Reported-by: Matt +Signed-off-by: Conrad Kostecki +Reviewed-by: Hans de Goede +[cassel: rewrote commit message] +Signed-off-by: Niklas Cassel +Signed-off-by: Sasha Levin +--- + drivers/ata/ahci.c | 13 ------------- + 1 file changed, 13 deletions(-) + +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index d446830ba4b85..2d2a070c1efcb 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -626,19 +626,6 @@ MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets"); + static void ahci_pci_save_initial_config(struct pci_dev *pdev, + struct ahci_host_priv *hpriv) + { +- if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA) { +- switch (pdev->device) { +- case 0x1166: +- dev_info(&pdev->dev, "ASM1166 has only six ports\n"); +- hpriv->saved_port_map = 0x3f; +- break; +- case 0x1064: +- dev_info(&pdev->dev, "ASM1064 has only four ports\n"); +- hpriv->saved_port_map = 0xf; +- break; +- } +- } +- + if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { + dev_info(&pdev->dev, "JMB361 has only one port\n"); + hpriv->force_port_map = 1; +-- +2.43.0 + diff --git a/queue-5.4/ahci-asm1064-correct-count-of-reported-ports.patch b/queue-5.4/ahci-asm1064-correct-count-of-reported-ports.patch new file mode 100644 index 00000000000..cf86fe742e8 --- /dev/null +++ b/queue-5.4/ahci-asm1064-correct-count-of-reported-ports.patch @@ -0,0 +1,60 @@ +From 462c0ee155de082d0f7ef090b73f76f62d6d5626 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Feb 2024 17:57:57 +0100 +Subject: ahci: asm1064: correct count of reported ports + +From: Andrey Jr. Melnikov + +[ Upstream commit 9815e39617541ef52d0dfac4be274ad378c6dc09 ] + +The ASM1064 SATA host controller always reports wrongly, +that it has 24 ports. But in reality, it only has four ports. + +before: +ahci 0000:04:00.0: SSS flag set, parallel bus scan disabled +ahci 0000:04:00.0: AHCI 0001.0301 32 slots 24 ports 6 Gbps 0xffff0f impl SATA mode +ahci 0000:04:00.0: flags: 64bit ncq sntf stag pm led only pio sxs deso sadm sds apst + +after: +ahci 0000:04:00.0: ASM1064 has only four ports +ahci 0000:04:00.0: forcing port_map 0xffff0f -> 0xf +ahci 0000:04:00.0: SSS flag set, parallel bus scan disabled +ahci 0000:04:00.0: AHCI 0001.0301 32 slots 24 ports 6 Gbps 0xf impl SATA mode +ahci 0000:04:00.0: flags: 64bit ncq sntf stag pm led only pio sxs deso sadm sds apst + +Signed-off-by: "Andrey Jr. Melnikov" +Signed-off-by: Niklas Cassel +Stable-dep-of: 6cd8adc3e189 ("ahci: asm1064: asm1166: don't limit reported ports") +Signed-off-by: Sasha Levin +--- + drivers/ata/ahci.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index 84c7519dddb19..d446830ba4b85 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -626,9 +626,17 @@ MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets"); + static void ahci_pci_save_initial_config(struct pci_dev *pdev, + struct ahci_host_priv *hpriv) + { +- if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && pdev->device == 0x1166) { +- dev_info(&pdev->dev, "ASM1166 has only six ports\n"); +- hpriv->saved_port_map = 0x3f; ++ if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA) { ++ switch (pdev->device) { ++ case 0x1166: ++ dev_info(&pdev->dev, "ASM1166 has only six ports\n"); ++ hpriv->saved_port_map = 0x3f; ++ break; ++ case 0x1064: ++ dev_info(&pdev->dev, "ASM1064 has only four ports\n"); ++ hpriv->saved_port_map = 0xf; ++ break; ++ } + } + + if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { +-- +2.43.0 + diff --git a/queue-5.4/arm-dts-marvell-fix-maxium-maxim-typo-in-brownstone-.patch b/queue-5.4/arm-dts-marvell-fix-maxium-maxim-typo-in-brownstone-.patch new file mode 100644 index 00000000000..a675b3794de --- /dev/null +++ b/queue-5.4/arm-dts-marvell-fix-maxium-maxim-typo-in-brownstone-.patch @@ -0,0 +1,46 @@ +From 30851949f89edb6068a6bbf442a956d673d3fe6a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Jan 2024 19:39:32 +0100 +Subject: arm: dts: marvell: Fix maxium->maxim typo in brownstone dts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Duje Mihanović + +[ Upstream commit 831e0cd4f9ee15a4f02ae10b67e7fdc10eb2b4fc ] + +Fix an obvious spelling error in the PMIC compatible in the MMP2 +Brownstone DTS file. + +Fixes: 58f1193e6210 ("mfd: max8925: Add dts") +Cc: +Signed-off-by: Duje Mihanović +Reported-by: Krzysztof Kozlowski +Closes: https://lore.kernel.org/linux-devicetree/1410884282-18041-1-git-send-email-k.kozlowski@samsung.com/ +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240125-brownstone-typo-fix-v2-1-45bc48a0c81c@skole.hr +[krzysztof: Just 10 years to take a patch, not bad! Rephrased commit + msg] +Signed-off-by: Krzysztof Kozlowski +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/mmp2-brownstone.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/mmp2-brownstone.dts b/arch/arm/boot/dts/mmp2-brownstone.dts +index 04f1ae1382e7a..bc64348b82185 100644 +--- a/arch/arm/boot/dts/mmp2-brownstone.dts ++++ b/arch/arm/boot/dts/mmp2-brownstone.dts +@@ -28,7 +28,7 @@ &uart3 { + &twsi1 { + status = "okay"; + pmic: max8925@3c { +- compatible = "maxium,max8925"; ++ compatible = "maxim,max8925"; + reg = <0x3c>; + interrupts = <1>; + interrupt-parent = <&intcmux4>; +-- +2.43.0 + diff --git a/queue-5.4/arm-dts-mmp2-brownstone-don-t-redeclare-phandle-refe.patch b/queue-5.4/arm-dts-mmp2-brownstone-don-t-redeclare-phandle-refe.patch new file mode 100644 index 00000000000..9f22c2a436e --- /dev/null +++ b/queue-5.4/arm-dts-mmp2-brownstone-don-t-redeclare-phandle-refe.patch @@ -0,0 +1,371 @@ +From f09bf20057f84fc9644d62661f1dff8a0f6bc3ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2020 18:41:01 +0100 +Subject: ARM: dts: mmp2-brownstone: Don't redeclare phandle references + +From: Lubomir Rintel + +[ Upstream commit 5a56cf3e8738f5d31d8c024d0c62a4c2bfe76fb2 ] + +Extend the nodes by their phandle references instead of recreating the +tree and declaring references of the same names. + +Signed-off-by: Lubomir Rintel +Reviewed-by: Rob Herring +Link: https://lore.kernel.org/r/20200320174107.29406-5-lkundrak@v3.sk +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 831e0cd4f9ee ("arm: dts: marvell: Fix maxium->maxim typo in brownstone dts") +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/mmp2-brownstone.dts | 332 +++++++++++++------------- + 1 file changed, 165 insertions(+), 167 deletions(-) + +diff --git a/arch/arm/boot/dts/mmp2-brownstone.dts b/arch/arm/boot/dts/mmp2-brownstone.dts +index aaedc4c742ea5..04f1ae1382e7a 100644 +--- a/arch/arm/boot/dts/mmp2-brownstone.dts ++++ b/arch/arm/boot/dts/mmp2-brownstone.dts +@@ -19,176 +19,174 @@ memory { + device_type = "memory"; + reg = <0x00000000 0x08000000>; + }; ++}; ++ ++&uart3 { ++ status = "okay"; ++}; + +- soc { +- apb@d4000000 { +- uart3: uart@d4018000 { +- status = "okay"; +- }; +- twsi1: i2c@d4011000 { +- status = "okay"; +- pmic: max8925@3c { +- compatible = "maxium,max8925"; +- reg = <0x3c>; +- interrupts = <1>; +- interrupt-parent = <&intcmux4>; +- interrupt-controller; +- #interrupt-cells = <1>; +- maxim,tsc-irq = <0>; ++&twsi1 { ++ status = "okay"; ++ pmic: max8925@3c { ++ compatible = "maxium,max8925"; ++ reg = <0x3c>; ++ interrupts = <1>; ++ interrupt-parent = <&intcmux4>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ maxim,tsc-irq = <0>; + +- regulators { +- SDV1 { +- regulator-min-microvolt = <637500>; +- regulator-max-microvolt = <1425000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- SDV2 { +- regulator-min-microvolt = <650000>; +- regulator-max-microvolt = <2225000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- SDV3 { +- regulator-min-microvolt = <750000>; +- regulator-max-microvolt = <3900000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO1 { +- regulator-min-microvolt = <750000>; +- regulator-max-microvolt = <3900000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO2 { +- regulator-min-microvolt = <650000>; +- regulator-max-microvolt = <2250000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO3 { +- regulator-min-microvolt = <650000>; +- regulator-max-microvolt = <2250000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO4 { +- regulator-min-microvolt = <750000>; +- regulator-max-microvolt = <3900000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO5 { +- regulator-min-microvolt = <750000>; +- regulator-max-microvolt = <3900000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO6 { +- regulator-min-microvolt = <750000>; +- regulator-max-microvolt = <3900000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO7 { +- regulator-min-microvolt = <750000>; +- regulator-max-microvolt = <3900000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO8 { +- regulator-min-microvolt = <750000>; +- regulator-max-microvolt = <3900000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO9 { +- regulator-min-microvolt = <750000>; +- regulator-max-microvolt = <3900000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO10 { +- regulator-min-microvolt = <750000>; +- regulator-max-microvolt = <3900000>; +- }; +- LDO11 { +- regulator-min-microvolt = <750000>; +- regulator-max-microvolt = <3900000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO12 { +- regulator-min-microvolt = <750000>; +- regulator-max-microvolt = <3900000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO13 { +- regulator-min-microvolt = <750000>; +- regulator-max-microvolt = <3900000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO14 { +- regulator-min-microvolt = <750000>; +- regulator-max-microvolt = <3900000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO15 { +- regulator-min-microvolt = <750000>; +- regulator-max-microvolt = <3900000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO16 { +- regulator-min-microvolt = <750000>; +- regulator-max-microvolt = <3900000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO17 { +- regulator-min-microvolt = <650000>; +- regulator-max-microvolt = <2250000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO18 { +- regulator-min-microvolt = <650000>; +- regulator-max-microvolt = <2250000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO19 { +- regulator-min-microvolt = <750000>; +- regulator-max-microvolt = <3900000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- LDO20 { +- regulator-min-microvolt = <750000>; +- regulator-max-microvolt = <3900000>; +- regulator-boot-on; +- regulator-always-on; +- }; +- }; +- backlight { +- maxim,max8925-dual-string = <0>; +- }; +- charger { +- batt-detect = <0>; +- topoff-threshold = <1>; +- fast-charge = <7>; +- no-temp-support = <0>; +- no-insert-detect = <0>; +- }; +- }; +- }; +- rtc: rtc@d4010000 { +- status = "okay"; ++ regulators { ++ SDV1 { ++ regulator-min-microvolt = <637500>; ++ regulator-max-microvolt = <1425000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ SDV2 { ++ regulator-min-microvolt = <650000>; ++ regulator-max-microvolt = <2225000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ SDV3 { ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <3900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO1 { ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <3900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO2 { ++ regulator-min-microvolt = <650000>; ++ regulator-max-microvolt = <2250000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO3 { ++ regulator-min-microvolt = <650000>; ++ regulator-max-microvolt = <2250000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO4 { ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <3900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO5 { ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <3900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO6 { ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <3900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO7 { ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <3900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO8 { ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <3900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO9 { ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <3900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO10 { ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <3900000>; + }; ++ LDO11 { ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <3900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO12 { ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <3900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO13 { ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <3900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO14 { ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <3900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO15 { ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <3900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO16 { ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <3900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO17 { ++ regulator-min-microvolt = <650000>; ++ regulator-max-microvolt = <2250000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO18 { ++ regulator-min-microvolt = <650000>; ++ regulator-max-microvolt = <2250000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO19 { ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <3900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ LDO20 { ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <3900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ }; ++ backlight { ++ maxim,max8925-dual-string = <0>; ++ }; ++ charger { ++ batt-detect = <0>; ++ topoff-threshold = <1>; ++ fast-charge = <7>; ++ no-temp-support = <0>; ++ no-insert-detect = <0>; + }; + }; + }; ++ ++&rtc { ++ status = "okay"; ++}; +-- +2.43.0 + diff --git a/queue-5.4/btrfs-fix-off-by-one-chunk-length-calculation-at-con.patch b/queue-5.4/btrfs-fix-off-by-one-chunk-length-calculation-at-con.patch new file mode 100644 index 00000000000..f0ce05bfdfd --- /dev/null +++ b/queue-5.4/btrfs-fix-off-by-one-chunk-length-calculation-at-con.patch @@ -0,0 +1,48 @@ +From ee3aecc3453220b3120356ed2e39242e02613b00 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Feb 2024 10:37:04 +0000 +Subject: btrfs: fix off-by-one chunk length calculation at + contains_pending_extent() + +From: Filipe Manana + +[ Upstream commit ae6bd7f9b46a29af52ebfac25d395757e2031d0d ] + +At contains_pending_extent() the value of the end offset of a chunk we +found in the device's allocation state io tree is inclusive, so when +we calculate the length we pass to the in_range() macro, we must sum +1 to the expression "physical_end - physical_offset". + +In practice the wrong calculation should be harmless as chunks sizes +are never 1 byte and we should never have 1 byte ranges of unallocated +space. Nevertheless fix the wrong calculation. + +Reported-by: Alex Lyakas +Link: https://lore.kernel.org/linux-btrfs/CAOcd+r30e-f4R-5x-S7sV22RJPe7+pgwherA6xqN2_qe7o4XTg@mail.gmail.com/ +Fixes: 1c11b63eff2a ("btrfs: replace pending/pinned chunks lists with io tree") +CC: stable@vger.kernel.org # 6.1+ +Reviewed-by: Josef Bacik +Reviewed-by: Qu Wenruo +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/volumes.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c +index e11c8da9a5605..5539e672d70a3 100644 +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -1638,7 +1638,7 @@ static bool contains_pending_extent(struct btrfs_device *device, u64 *start, + + if (in_range(physical_start, *start, len) || + in_range(*start, physical_start, +- physical_end - physical_start)) { ++ physical_end + 1 - physical_start)) { + *start = physical_end + 1; + return true; + } +-- +2.43.0 + diff --git a/queue-5.4/clk-qcom-gcc-ipq8074-fix-terminating-of-frequency-ta.patch b/queue-5.4/clk-qcom-gcc-ipq8074-fix-terminating-of-frequency-ta.patch new file mode 100644 index 00000000000..8464f92ea6d --- /dev/null +++ b/queue-5.4/clk-qcom-gcc-ipq8074-fix-terminating-of-frequency-ta.patch @@ -0,0 +1,51 @@ +From ac3c54a9b71cd909da60a9091a6fc50bdca0b091 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Feb 2024 19:07:48 +0100 +Subject: clk: qcom: gcc-ipq8074: fix terminating of frequency table arrays + +From: Gabor Juhos + +[ Upstream commit 1040ef5ed95d6fd2628bad387d78a61633e09429 ] + +The frequency table arrays are supposed to be terminated with an +empty element. Add such entry to the end of the arrays where it +is missing in order to avoid possible out-of-bound access when +the table is traversed by functions like qcom_find_freq() or +qcom_find_freq_floor(). + +Only compile tested. + +Fixes: 9607f6224b39 ("clk: qcom: ipq8074: add PCIE, USB and SDCC clocks") +Signed-off-by: Gabor Juhos +Reviewed-by: Stephen Boyd +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20240229-freq-table-terminator-v1-3-074334f0905c@gmail.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/gcc-ipq8074.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/clk/qcom/gcc-ipq8074.c b/drivers/clk/qcom/gcc-ipq8074.c +index 052e168d2a2ac..b10ecfde21c87 100644 +--- a/drivers/clk/qcom/gcc-ipq8074.c ++++ b/drivers/clk/qcom/gcc-ipq8074.c +@@ -972,6 +972,7 @@ static struct clk_rcg2 pcie0_axi_clk_src = { + + static const struct freq_tbl ftbl_pcie_aux_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), ++ { } + }; + + static struct clk_rcg2 pcie0_aux_clk_src = { +@@ -1077,6 +1078,7 @@ static const struct freq_tbl ftbl_sdcc_ice_core_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(160000000, P_GPLL0, 5, 0, 0), + F(308570000, P_GPLL6, 3.5, 0, 0), ++ { } + }; + + static struct clk_rcg2 sdcc1_ice_core_clk_src = { +-- +2.43.0 + diff --git a/queue-5.4/clk-qcom-gcc-sdm845-add-soft-dependency-on-rpmhpd.patch b/queue-5.4/clk-qcom-gcc-sdm845-add-soft-dependency-on-rpmhpd.patch new file mode 100644 index 00000000000..70bac133240 --- /dev/null +++ b/queue-5.4/clk-qcom-gcc-sdm845-add-soft-dependency-on-rpmhpd.patch @@ -0,0 +1,40 @@ +From 92cb14ccc6871835151b79ea1f6f731d456d83f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jan 2024 11:58:14 +0530 +Subject: clk: qcom: gcc-sdm845: Add soft dependency on rpmhpd + +From: Amit Pundir + +[ Upstream commit 1d9054e3a4fd36e2949e616f7360bdb81bcc1921 ] + +With the addition of RPMh power domain to the GCC node in +device tree, we noticed a significant delay in getting the +UFS driver probed on AOSP which futher led to mount failures +because Android do not support rootwait. So adding a soft +dependency on RPMh power domain which informs modprobe to +load rpmhpd module before gcc-sdm845. + +Cc: stable@vger.kernel.org # v5.4+ +Fixes: 4b6ea15c0a11 ("arm64: dts: qcom: sdm845: Add missing RPMh power domain to GCC") +Suggested-by: Manivannan Sadhasivam +Signed-off-by: Amit Pundir +Reviewed-by: Manivannan Sadhasivam +Link: https://lore.kernel.org/r/20240123062814.2555649-1-amit.pundir@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/gcc-sdm845.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/clk/qcom/gcc-sdm845.c b/drivers/clk/qcom/gcc-sdm845.c +index 56d22dd225c9d..a8810a628e710 100644 +--- a/drivers/clk/qcom/gcc-sdm845.c ++++ b/drivers/clk/qcom/gcc-sdm845.c +@@ -3646,3 +3646,4 @@ module_exit(gcc_sdm845_exit); + MODULE_DESCRIPTION("QTI GCC SDM845 Driver"); + MODULE_LICENSE("GPL v2"); + MODULE_ALIAS("platform:gcc-sdm845"); ++MODULE_SOFTDEP("pre: rpmhpd"); +-- +2.43.0 + diff --git a/queue-5.4/clk-qcom-mmcc-apq8084-fix-terminating-of-frequency-t.patch b/queue-5.4/clk-qcom-mmcc-apq8084-fix-terminating-of-frequency-t.patch new file mode 100644 index 00000000000..05cc81d6114 --- /dev/null +++ b/queue-5.4/clk-qcom-mmcc-apq8084-fix-terminating-of-frequency-t.patch @@ -0,0 +1,51 @@ +From 37767219c909a2eccb4a66475eea0990dbb345cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Feb 2024 19:07:51 +0100 +Subject: clk: qcom: mmcc-apq8084: fix terminating of frequency table arrays + +From: Gabor Juhos + +[ Upstream commit a903cfd38d8dee7e754fb89fd1bebed99e28003d ] + +The frequency table arrays are supposed to be terminated with an +empty element. Add such entry to the end of the arrays where it +is missing in order to avoid possible out-of-bound access when +the table is traversed by functions like qcom_find_freq() or +qcom_find_freq_floor(). + +Only compile tested. + +Fixes: 2b46cd23a5a2 ("clk: qcom: Add APQ8084 Multimedia Clock Controller (MMCC) support") +Signed-off-by: Gabor Juhos +Reviewed-by: Stephen Boyd +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20240229-freq-table-terminator-v1-6-074334f0905c@gmail.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/mmcc-apq8084.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/clk/qcom/mmcc-apq8084.c b/drivers/clk/qcom/mmcc-apq8084.c +index fbfcf00067394..c2fd0e8f4bc09 100644 +--- a/drivers/clk/qcom/mmcc-apq8084.c ++++ b/drivers/clk/qcom/mmcc-apq8084.c +@@ -333,6 +333,7 @@ static struct freq_tbl ftbl_mmss_axi_clk[] = { + F(333430000, P_MMPLL1, 3.5, 0, 0), + F(400000000, P_MMPLL0, 2, 0, 0), + F(466800000, P_MMPLL1, 2.5, 0, 0), ++ { } + }; + + static struct clk_rcg2 mmss_axi_clk_src = { +@@ -357,6 +358,7 @@ static struct freq_tbl ftbl_ocmemnoc_clk[] = { + F(150000000, P_GPLL0, 4, 0, 0), + F(228570000, P_MMPLL0, 3.5, 0, 0), + F(320000000, P_MMPLL0, 2.5, 0, 0), ++ { } + }; + + static struct clk_rcg2 ocmemnoc_clk_src = { +-- +2.43.0 + diff --git a/queue-5.4/clk-qcom-mmcc-msm8974-fix-terminating-of-frequency-t.patch b/queue-5.4/clk-qcom-mmcc-msm8974-fix-terminating-of-frequency-t.patch new file mode 100644 index 00000000000..8fea95c6adb --- /dev/null +++ b/queue-5.4/clk-qcom-mmcc-msm8974-fix-terminating-of-frequency-t.patch @@ -0,0 +1,51 @@ +From 900e38be6bb1759b2fbddbc286715ce86009ac11 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Feb 2024 19:07:52 +0100 +Subject: clk: qcom: mmcc-msm8974: fix terminating of frequency table arrays + +From: Gabor Juhos + +[ Upstream commit e2c02a85bf53ae86d79b5fccf0a75ac0b78e0c96 ] + +The frequency table arrays are supposed to be terminated with an +empty element. Add such entry to the end of the arrays where it +is missing in order to avoid possible out-of-bound access when +the table is traversed by functions like qcom_find_freq() or +qcom_find_freq_floor(). + +Only compile tested. + +Fixes: d8b212014e69 ("clk: qcom: Add support for MSM8974's multimedia clock controller (MMCC)") +Signed-off-by: Gabor Juhos +Reviewed-by: Stephen Boyd +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20240229-freq-table-terminator-v1-7-074334f0905c@gmail.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/mmcc-msm8974.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c +index bcb0a397ef918..8ce1826aea140 100644 +--- a/drivers/clk/qcom/mmcc-msm8974.c ++++ b/drivers/clk/qcom/mmcc-msm8974.c +@@ -283,6 +283,7 @@ static struct freq_tbl ftbl_mmss_axi_clk[] = { + F(291750000, P_MMPLL1, 4, 0, 0), + F(400000000, P_MMPLL0, 2, 0, 0), + F(466800000, P_MMPLL1, 2.5, 0, 0), ++ { } + }; + + static struct clk_rcg2 mmss_axi_clk_src = { +@@ -307,6 +308,7 @@ static struct freq_tbl ftbl_ocmemnoc_clk[] = { + F(150000000, P_GPLL0, 4, 0, 0), + F(291750000, P_MMPLL1, 4, 0, 0), + F(400000000, P_MMPLL0, 2, 0, 0), ++ { } + }; + + static struct clk_rcg2 ocmemnoc_clk_src = { +-- +2.43.0 + diff --git a/queue-5.4/crypto-qat-fix-double-free-during-reset.patch b/queue-5.4/crypto-qat-fix-double-free-during-reset.patch new file mode 100644 index 00000000000..336b1b89b16 --- /dev/null +++ b/queue-5.4/crypto-qat-fix-double-free-during-reset.patch @@ -0,0 +1,42 @@ +From 5aa4f15b9804c4684b5e11bfddf360780561b35c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Oct 2023 13:27:19 +0100 +Subject: crypto: qat - fix double free during reset + +From: Svyatoslav Pankratov + +[ Upstream commit 01aed663e6c421aeafc9c330bda630976b50a764 ] + +There is no need to free the reset_data structure if the recovery is +unsuccessful and the reset is synchronous. The function +adf_dev_aer_schedule_reset() handles the cleanup properly. Only +asynchronous resets require such structure to be freed inside the reset +worker. + +Fixes: d8cba25d2c68 ("crypto: qat - Intel(R) QAT driver framework") +Signed-off-by: Svyatoslav Pankratov +Signed-off-by: Giovanni Cabiddu +Signed-off-by: Herbert Xu +Stable-dep-of: 7d42e097607c ("crypto: qat - resolve race condition during AER recovery") +Signed-off-by: Sasha Levin +--- + drivers/crypto/qat/qat_common/adf_aer.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/crypto/qat/qat_common/adf_aer.c b/drivers/crypto/qat/qat_common/adf_aer.c +index f5e960d23a7a7..20f983b830065 100644 +--- a/drivers/crypto/qat/qat_common/adf_aer.c ++++ b/drivers/crypto/qat/qat_common/adf_aer.c +@@ -139,7 +139,8 @@ static void adf_device_reset_worker(struct work_struct *work) + if (adf_dev_init(accel_dev) || adf_dev_start(accel_dev)) { + /* The device hanged and we can't restart it so stop here */ + dev_err(&GET_DEV(accel_dev), "Restart device failed\n"); +- kfree(reset_data); ++ if (reset_data->mode == ADF_DEV_RESET_ASYNC) ++ kfree(reset_data); + WARN(1, "QAT: device restart failed. Device is unusable\n"); + return; + } +-- +2.43.0 + diff --git a/queue-5.4/crypto-qat-resolve-race-condition-during-aer-recover.patch b/queue-5.4/crypto-qat-resolve-race-condition-during-aer-recover.patch new file mode 100644 index 00000000000..c15feda042e --- /dev/null +++ b/queue-5.4/crypto-qat-resolve-race-condition-during-aer-recover.patch @@ -0,0 +1,92 @@ +From 5451aa18ecfed58331298d88f6a6944d090a9fa4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Feb 2024 13:43:42 +0100 +Subject: crypto: qat - resolve race condition during AER recovery + +From: Damian Muszynski + +[ Upstream commit 7d42e097607c4d246d99225bf2b195b6167a210c ] + +During the PCI AER system's error recovery process, the kernel driver +may encounter a race condition with freeing the reset_data structure's +memory. If the device restart will take more than 10 seconds the function +scheduling that restart will exit due to a timeout, and the reset_data +structure will be freed. However, this data structure is used for +completion notification after the restart is completed, which leads +to a UAF bug. + +This results in a KFENCE bug notice. + + BUG: KFENCE: use-after-free read in adf_device_reset_worker+0x38/0xa0 [intel_qat] + Use-after-free read at 0x00000000bc56fddf (in kfence-#142): + adf_device_reset_worker+0x38/0xa0 [intel_qat] + process_one_work+0x173/0x340 + +To resolve this race condition, the memory associated to the container +of the work_struct is freed on the worker if the timeout expired, +otherwise on the function that schedules the worker. +The timeout detection can be done by checking if the caller is +still waiting for completion or not by using completion_done() function. + +Fixes: d8cba25d2c68 ("crypto: qat - Intel(R) QAT driver framework") +Cc: +Signed-off-by: Damian Muszynski +Reviewed-by: Giovanni Cabiddu +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/qat/qat_common/adf_aer.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/drivers/crypto/qat/qat_common/adf_aer.c b/drivers/crypto/qat/qat_common/adf_aer.c +index 20f983b830065..a2989f0188cad 100644 +--- a/drivers/crypto/qat/qat_common/adf_aer.c ++++ b/drivers/crypto/qat/qat_common/adf_aer.c +@@ -139,7 +139,8 @@ static void adf_device_reset_worker(struct work_struct *work) + if (adf_dev_init(accel_dev) || adf_dev_start(accel_dev)) { + /* The device hanged and we can't restart it so stop here */ + dev_err(&GET_DEV(accel_dev), "Restart device failed\n"); +- if (reset_data->mode == ADF_DEV_RESET_ASYNC) ++ if (reset_data->mode == ADF_DEV_RESET_ASYNC || ++ completion_done(&reset_data->compl)) + kfree(reset_data); + WARN(1, "QAT: device restart failed. Device is unusable\n"); + return; +@@ -147,11 +148,19 @@ static void adf_device_reset_worker(struct work_struct *work) + adf_dev_restarted_notify(accel_dev); + clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status); + +- /* The dev is back alive. Notify the caller if in sync mode */ +- if (reset_data->mode == ADF_DEV_RESET_SYNC) +- complete(&reset_data->compl); +- else ++ /* ++ * The dev is back alive. Notify the caller if in sync mode ++ * ++ * If device restart will take a more time than expected, ++ * the schedule_reset() function can timeout and exit. This can be ++ * detected by calling the completion_done() function. In this case ++ * the reset_data structure needs to be freed here. ++ */ ++ if (reset_data->mode == ADF_DEV_RESET_ASYNC || ++ completion_done(&reset_data->compl)) + kfree(reset_data); ++ else ++ complete(&reset_data->compl); + } + + static int adf_dev_aer_schedule_reset(struct adf_accel_dev *accel_dev, +@@ -184,8 +193,9 @@ static int adf_dev_aer_schedule_reset(struct adf_accel_dev *accel_dev, + dev_err(&GET_DEV(accel_dev), + "Reset device timeout expired\n"); + ret = -EFAULT; ++ } else { ++ kfree(reset_data); + } +- kfree(reset_data); + return ret; + } + return 0; +-- +2.43.0 + diff --git a/queue-5.4/dm-raid-fix-lockdep-waring-in-pers-hot_add_disk.patch b/queue-5.4/dm-raid-fix-lockdep-waring-in-pers-hot_add_disk.patch new file mode 100644 index 00000000000..3b3702d33b3 --- /dev/null +++ b/queue-5.4/dm-raid-fix-lockdep-waring-in-pers-hot_add_disk.patch @@ -0,0 +1,49 @@ +From e326ab70723f47af48a50805b544d29f691bd0f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Mar 2024 15:23:06 +0800 +Subject: dm-raid: fix lockdep waring in "pers->hot_add_disk" + +From: Yu Kuai + +[ Upstream commit 95009ae904b1e9dca8db6f649f2d7c18a6e42c75 ] + +The lockdep assert is added by commit a448af25becf ("md/raid10: remove +rcu protection to access rdev from conf") in print_conf(). And I didn't +notice that dm-raid is calling "pers->hot_add_disk" without holding +'reconfig_mutex'. + +"pers->hot_add_disk" read and write many fields that is protected by +'reconfig_mutex', and raid_resume() already grab the lock in other +contex. Hence fix this problem by protecting "pers->host_add_disk" +with the lock. + +Fixes: 9092c02d9435 ("DM RAID: Add ability to restore transiently failed devices on resume") +Fixes: a448af25becf ("md/raid10: remove rcu protection to access rdev from conf") +Cc: stable@vger.kernel.org # v6.7+ +Signed-off-by: Yu Kuai +Signed-off-by: Xiao Ni +Acked-by: Mike Snitzer +Signed-off-by: Song Liu +Link: https://lore.kernel.org/r/20240305072306.2562024-10-yukuai1@huaweicloud.com +Signed-off-by: Sasha Levin +--- + drivers/md/dm-raid.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c +index 1ccd765fad938..25eecb92f5f38 100644 +--- a/drivers/md/dm-raid.c ++++ b/drivers/md/dm-raid.c +@@ -4027,7 +4027,9 @@ static void raid_resume(struct dm_target *ti) + * Take this opportunity to check whether any failed + * devices are reachable again. + */ ++ mddev_lock_nointr(mddev); + attempt_restore_of_faulty_devices(rs); ++ mddev_unlock(mddev); + } + + if (test_and_clear_bit(RT_FLAG_RS_SUSPENDED, &rs->runtime_flags)) { +-- +2.43.0 + diff --git a/queue-5.4/dm-snapshot-fix-lockup-in-dm_exception_table_exit.patch b/queue-5.4/dm-snapshot-fix-lockup-in-dm_exception_table_exit.patch new file mode 100644 index 00000000000..796dd60895b --- /dev/null +++ b/queue-5.4/dm-snapshot-fix-lockup-in-dm_exception_table_exit.patch @@ -0,0 +1,40 @@ +From 101f87a83c2afb4bffda0905079ba6250f134db7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Mar 2024 18:43:11 +0100 +Subject: dm snapshot: fix lockup in dm_exception_table_exit + +From: Mikulas Patocka + +[ Upstream commit 6e7132ed3c07bd8a6ce3db4bb307ef2852b322dc ] + +There was reported lockup when we exit a snapshot with many exceptions. +Fix this by adding "cond_resched" to the loop that frees the exceptions. + +Reported-by: John Pittman +Cc: stable@vger.kernel.org +Signed-off-by: Mikulas Patocka +Signed-off-by: Mike Snitzer +Signed-off-by: Sasha Levin +--- + drivers/md/dm-snap.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c +index e902aae685af9..d8902d2b6aa66 100644 +--- a/drivers/md/dm-snap.c ++++ b/drivers/md/dm-snap.c +@@ -685,8 +685,10 @@ static void dm_exception_table_exit(struct dm_exception_table *et, + for (i = 0; i < size; i++) { + slot = et->table + i; + +- hlist_bl_for_each_entry_safe(ex, pos, n, slot, hash_list) ++ hlist_bl_for_each_entry_safe(ex, pos, n, slot, hash_list) { + kmem_cache_free(mem, ex); ++ cond_resched(); ++ } + } + + vfree(et->table); +-- +2.43.0 + diff --git a/queue-5.4/drm-exynos-do-not-return-negative-values-from-.get_m.patch b/queue-5.4/drm-exynos-do-not-return-negative-values-from-.get_m.patch new file mode 100644 index 00000000000..7e4c652d110 --- /dev/null +++ b/queue-5.4/drm-exynos-do-not-return-negative-values-from-.get_m.patch @@ -0,0 +1,67 @@ +From ad1cebc6eee7b89a489a73caa05cb44c1536823d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Mar 2024 18:03:41 +0200 +Subject: drm/exynos: do not return negative values from .get_modes() + +From: Jani Nikula + +[ Upstream commit 13d5b040363c7ec0ac29c2de9cf661a24a8aa531 ] + +The .get_modes() hooks aren't supposed to return negative error +codes. Return 0 for no modes, whatever the reason. + +Cc: Inki Dae +Cc: Seung-Woo Kim +Cc: Kyungmin Park +Cc: stable@vger.kernel.org +Acked-by: Thomas Zimmermann +Link: https://patchwork.freedesktop.org/patch/msgid/d8665f620d9c252aa7d5a4811ff6b16e773903a2.1709913674.git.jani.nikula@intel.com +Signed-off-by: Jani Nikula +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/exynos/exynos_drm_vidi.c | 4 ++-- + drivers/gpu/drm/exynos/exynos_hdmi.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c +index d882a22dfd6e6..46fc472be3068 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c +@@ -308,14 +308,14 @@ static int vidi_get_modes(struct drm_connector *connector) + */ + if (!ctx->raw_edid) { + DRM_DEV_DEBUG_KMS(ctx->dev, "raw_edid is null.\n"); +- return -EFAULT; ++ return 0; + } + + edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH; + edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL); + if (!edid) { + DRM_DEV_DEBUG_KMS(ctx->dev, "failed to allocate edid\n"); +- return -ENOMEM; ++ return 0; + } + + drm_connector_update_edid_property(connector, edid); +diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c +index 93b2af4936d0e..0e2e1dfcd9ce5 100644 +--- a/drivers/gpu/drm/exynos/exynos_hdmi.c ++++ b/drivers/gpu/drm/exynos/exynos_hdmi.c +@@ -876,11 +876,11 @@ static int hdmi_get_modes(struct drm_connector *connector) + int ret; + + if (!hdata->ddc_adpt) +- return -ENODEV; ++ return 0; + + edid = drm_get_edid(connector, hdata->ddc_adpt); + if (!edid) +- return -ENODEV; ++ return 0; + + hdata->dvi_mode = !drm_detect_hdmi_monitor(edid); + DRM_DEV_DEBUG_KMS(hdata->dev, "%s : width[%d] x height[%d]\n", +-- +2.43.0 + diff --git a/queue-5.4/drm-imx-ipuv3-do-not-return-negative-values-from-.ge.patch b/queue-5.4/drm-imx-ipuv3-do-not-return-negative-values-from-.ge.patch new file mode 100644 index 00000000000..f82c3fb44ea --- /dev/null +++ b/queue-5.4/drm-imx-ipuv3-do-not-return-negative-values-from-.ge.patch @@ -0,0 +1,47 @@ +From a75274a4104014cccb27d98fbc0d99770ed5b5aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Mar 2024 18:03:43 +0200 +Subject: drm/imx/ipuv3: do not return negative values from .get_modes() + +From: Jani Nikula + +[ Upstream commit c2da9ada64962fcd2e6395ed9987b9874ea032d3 ] + +The .get_modes() hooks aren't supposed to return negative error +codes. Return 0 for no modes, whatever the reason. + +Cc: Philipp Zabel +Cc: stable@vger.kernel.org +Acked-by: Philipp Zabel +Acked-by: Thomas Zimmermann +Link: https://patchwork.freedesktop.org/patch/msgid/311f6eec96d47949b16a670529f4d89fcd97aefa.1709913674.git.jani.nikula@intel.com +Signed-off-by: Jani Nikula +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/imx/parallel-display.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c +index e24272428744c..2165ad545a382 100644 +--- a/drivers/gpu/drm/imx/parallel-display.c ++++ b/drivers/gpu/drm/imx/parallel-display.c +@@ -63,14 +63,14 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector) + int ret; + + if (!mode) +- return -EINVAL; ++ return 0; + + ret = of_get_drm_display_mode(np, &imxpd->mode, + &imxpd->bus_flags, + OF_USE_NATIVE_MODE); + if (ret) { + drm_mode_destroy(connector->dev, mode); +- return ret; ++ return 0; + } + + drm_mode_copy(mode, &imxpd->mode); +-- +2.43.0 + diff --git a/queue-5.4/drm-vc4-hdmi-do-not-return-negative-values-from-.get.patch b/queue-5.4/drm-vc4-hdmi-do-not-return-negative-values-from-.get.patch new file mode 100644 index 00000000000..14bcd78d411 --- /dev/null +++ b/queue-5.4/drm-vc4-hdmi-do-not-return-negative-values-from-.get.patch @@ -0,0 +1,39 @@ +From f6612d3221f416bc30017423994dfbfd900e4bf9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Mar 2024 18:03:44 +0200 +Subject: drm/vc4: hdmi: do not return negative values from .get_modes() + +From: Jani Nikula + +[ Upstream commit abf493988e380f25242c1023275c68bd3579c9ce ] + +The .get_modes() hooks aren't supposed to return negative error +codes. Return 0 for no modes, whatever the reason. + +Cc: Maxime Ripard +Cc: stable@vger.kernel.org +Acked-by: Maxime Ripard +Acked-by: Thomas Zimmermann +Link: https://patchwork.freedesktop.org/patch/msgid/dcda6d4003e2c6192987916b35c7304732800e08.1709913674.git.jani.nikula@intel.com +Signed-off-by: Jani Nikula +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c +index 54435b72b7611..ba71200169866 100644 +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -236,7 +236,7 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) + edid = drm_get_edid(connector, vc4->hdmi->ddc); + cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid); + if (!edid) +- return -ENODEV; ++ return 0; + + vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid); + +-- +2.43.0 + diff --git a/queue-5.4/ext4-correct-best-extent-lstart-adjustment-logic.patch b/queue-5.4/ext4-correct-best-extent-lstart-adjustment-logic.patch new file mode 100644 index 00000000000..8da6e5cef0e --- /dev/null +++ b/queue-5.4/ext4-correct-best-extent-lstart-adjustment-logic.patch @@ -0,0 +1,95 @@ +From e6705a0254e5189dee1166d8707962d98e427c40 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Feb 2024 22:18:45 +0800 +Subject: ext4: correct best extent lstart adjustment logic + +From: Baokun Li + +[ Upstream commit 4fbf8bc733d14bceb16dda46a3f5e19c6a9621c5 ] + +When yangerkun review commit 93cdf49f6eca ("ext4: Fix best extent lstart +adjustment logic in ext4_mb_new_inode_pa()"), it was found that the best +extent did not completely cover the original request after adjusting the +best extent lstart in ext4_mb_new_inode_pa() as follows: + + original request: 2/10(8) + normalized request: 0/64(64) + best extent: 0/9(9) + +When we check if best ex can be kept at start of goal, ac_o_ex.fe_logical +is 2 less than the adjusted best extent logical end 9, so we think the +adjustment is done. But obviously 0/9(9) doesn't cover 2/10(8), so we +should determine here if the original request logical end is less than or +equal to the adjusted best extent logical end. + +In addition, add a comment stating when adjusted best_ex will not cover +the original request, and remove the duplicate assertion because adjusting +lstart makes no change to b_ex.fe_len. + +Link: https://lore.kernel.org/r/3630fa7f-b432-7afd-5f79-781bc3b2c5ea@huawei.com +Fixes: 93cdf49f6eca ("ext4: Fix best extent lstart adjustment logic in ext4_mb_new_inode_pa()") +Cc: +Signed-off-by: yangerkun +Signed-off-by: Baokun Li +Reviewed-by: Jan Kara +Reviewed-by: Ojaswin Mujoo +Link: https://lore.kernel.org/r/20240201141845.1879253-1-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/mballoc.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index e823731110e3e..b2e7b1907d410 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -3692,10 +3692,16 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac) + .fe_len = ac->ac_g_ex.fe_len, + }; + loff_t orig_goal_end = extent_logical_end(sbi, &ex); ++ loff_t o_ex_end = extent_logical_end(sbi, &ac->ac_o_ex); + +- /* we can't allocate as much as normalizer wants. +- * so, found space must get proper lstart +- * to cover original request */ ++ /* ++ * We can't allocate as much as normalizer wants, so we try ++ * to get proper lstart to cover the original request, except ++ * when the goal doesn't cover the original request as below: ++ * ++ * orig_ex:2045/2055(10), isize:8417280 -> normalized:0/2048 ++ * best_ex:0/200(200) -> adjusted: 1848/2048(200) ++ */ + BUG_ON(ac->ac_g_ex.fe_logical > ac->ac_o_ex.fe_logical); + BUG_ON(ac->ac_g_ex.fe_len < ac->ac_o_ex.fe_len); + +@@ -3707,7 +3713,7 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac) + * 1. Check if best ex can be kept at end of goal and still + * cover original start + * 2. Else, check if best ex can be kept at start of goal and +- * still cover original start ++ * still cover original end + * 3. Else, keep the best ex at start of original request. + */ + ex.fe_len = ac->ac_b_ex.fe_len; +@@ -3717,7 +3723,7 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac) + goto adjust_bex; + + ex.fe_logical = ac->ac_g_ex.fe_logical; +- if (ac->ac_o_ex.fe_logical < extent_logical_end(sbi, &ex)) ++ if (o_ex_end <= extent_logical_end(sbi, &ex)) + goto adjust_bex; + + ex.fe_logical = ac->ac_o_ex.fe_logical; +@@ -3725,7 +3731,6 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac) + ac->ac_b_ex.fe_logical = ex.fe_logical; + + BUG_ON(ac->ac_o_ex.fe_logical < ac->ac_b_ex.fe_logical); +- BUG_ON(ac->ac_o_ex.fe_len > ac->ac_b_ex.fe_len); + BUG_ON(extent_logical_end(sbi, &ex) > orig_goal_end); + } + +-- +2.43.0 + diff --git a/queue-5.4/ext4-fix-corruption-during-on-line-resize.patch b/queue-5.4/ext4-fix-corruption-during-on-line-resize.patch new file mode 100644 index 00000000000..55db21177f7 --- /dev/null +++ b/queue-5.4/ext4-fix-corruption-during-on-line-resize.patch @@ -0,0 +1,79 @@ +From 04972897ee2f8e26842c6c00ac34332524176aff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Feb 2024 15:50:09 +0000 +Subject: ext4: fix corruption during on-line resize + +From: Maximilian Heyne + +[ Upstream commit a6b3bfe176e8a5b05ec4447404e412c2a3fc92cc ] + +We observed a corruption during on-line resize of a file system that is +larger than 16 TiB with 4k block size. With having more then 2^32 blocks +resize_inode is turned off by default by mke2fs. The issue can be +reproduced on a smaller file system for convenience by explicitly +turning off resize_inode. An on-line resize across an 8 GiB boundary (the +size of a meta block group in this setup) then leads to a corruption: + + dev=/dev/ # should be >= 16 GiB + mkdir -p /corruption + /sbin/mke2fs -t ext4 -b 4096 -O ^resize_inode $dev $((2 * 2**21 - 2**15)) + mount -t ext4 $dev /corruption + + dd if=/dev/zero bs=4096 of=/corruption/test count=$((2*2**21 - 4*2**15)) + sha1sum /corruption/test + # 79d2658b39dcfd77274e435b0934028adafaab11 /corruption/test + + /sbin/resize2fs $dev $((2*2**21)) + # drop page cache to force reload the block from disk + echo 1 > /proc/sys/vm/drop_caches + + sha1sum /corruption/test + # 3c2abc63cbf1a94c9e6977e0fbd72cd832c4d5c3 /corruption/test + +2^21 = 2^15*2^6 equals 8 GiB whereof 2^15 is the number of blocks per +block group and 2^6 are the number of block groups that make a meta +block group. + +The last checksum might be different depending on how the file is laid +out across the physical blocks. The actual corruption occurs at physical +block 63*2^15 = 2064384 which would be the location of the backup of the +meta block group's block descriptor. During the on-line resize the file +system will be converted to meta_bg starting at s_first_meta_bg which is +2 in the example - meaning all block groups after 16 GiB. However, in +ext4_flex_group_add we might add block groups that are not part of the +first meta block group yet. In the reproducer we achieved this by +substracting the size of a whole block group from the point where the +meta block group would start. This must be considered when updating the +backup block group descriptors to follow the non-meta_bg layout. The fix +is to add a test whether the group to add is already part of the meta +block group or not. + +Fixes: 01f795f9e0d67 ("ext4: add online resizing support for meta_bg and 64-bit file systems") +Cc: +Signed-off-by: Maximilian Heyne +Tested-by: Srivathsa Dara +Reviewed-by: Srivathsa Dara +Link: https://lore.kernel.org/r/20240215155009.94493-1-mheyne@amazon.de +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/resize.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c +index 409b4ad28e718..d4431ca0c10e3 100644 +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -1567,7 +1567,8 @@ static int ext4_flex_group_add(struct super_block *sb, + int gdb_num = group / EXT4_DESC_PER_BLOCK(sb); + int gdb_num_end = ((group + flex_gd->count - 1) / + EXT4_DESC_PER_BLOCK(sb)); +- int meta_bg = ext4_has_feature_meta_bg(sb); ++ int meta_bg = ext4_has_feature_meta_bg(sb) && ++ gdb_num >= le32_to_cpu(es->s_first_meta_bg); + sector_t padding_blocks = meta_bg ? 0 : sbi->s_sbh->b_blocknr - + ext4_group_first_block_no(sb, 0); + sector_t old_gdb = 0; +-- +2.43.0 + diff --git a/queue-5.4/fat-fix-uninitialized-field-in-nostale-filehandles.patch b/queue-5.4/fat-fix-uninitialized-field-in-nostale-filehandles.patch new file mode 100644 index 00000000000..634060f0057 --- /dev/null +++ b/queue-5.4/fat-fix-uninitialized-field-in-nostale-filehandles.patch @@ -0,0 +1,49 @@ +From b31b138105b9b15d2a4a8cee6f56fad8bd90540a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Feb 2024 13:26:26 +0100 +Subject: fat: fix uninitialized field in nostale filehandles + +From: Jan Kara + +[ Upstream commit fde2497d2bc3a063d8af88b258dbadc86bd7b57c ] + +When fat_encode_fh_nostale() encodes file handle without a parent it +stores only first 10 bytes of the file handle. However the length of the +file handle must be a multiple of 4 so the file handle is actually 12 +bytes long and the last two bytes remain uninitialized. This is not +great at we potentially leak uninitialized information with the handle +to userspace. Properly initialize the full handle length. + +Link: https://lkml.kernel.org/r/20240205122626.13701-1-jack@suse.cz +Reported-by: syzbot+3ce5dea5b1539ff36769@syzkaller.appspotmail.com +Fixes: ea3983ace6b7 ("fat: restructure export_operations") +Signed-off-by: Jan Kara +Acked-by: OGAWA Hirofumi +Cc: Amir Goldstein +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + fs/fat/nfs.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/fs/fat/nfs.c b/fs/fat/nfs.c +index af191371c3529..bab63eeaf9cbc 100644 +--- a/fs/fat/nfs.c ++++ b/fs/fat/nfs.c +@@ -130,6 +130,12 @@ fat_encode_fh_nostale(struct inode *inode, __u32 *fh, int *lenp, + fid->parent_i_gen = parent->i_generation; + type = FILEID_FAT_WITH_PARENT; + *lenp = FAT_FID_SIZE_WITH_PARENT; ++ } else { ++ /* ++ * We need to initialize this field because the fh is actually ++ * 12 bytes long ++ */ ++ fid->parent_i_pos_hi = 0; + } + + return type; +-- +2.43.0 + diff --git a/queue-5.4/firmware-meson_sm-rework-driver-as-a-proper-platform.patch b/queue-5.4/firmware-meson_sm-rework-driver-as-a-proper-platform.patch new file mode 100644 index 00000000000..4ee2f9a8b32 --- /dev/null +++ b/queue-5.4/firmware-meson_sm-rework-driver-as-a-proper-platform.patch @@ -0,0 +1,353 @@ +From 00f77340d3c1ac58aee9c6a5b97773b77e4bc0fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Jul 2019 09:23:39 +0100 +Subject: firmware: meson_sm: Rework driver as a proper platform driver + +From: Carlo Caione + +[ Upstream commit 8cde3c2153e8f57be884c0e73f18bc4de150e870 ] + +The secure monitor driver is currently a frankenstein driver which is +registered as a platform driver but its functionality goes through a +global struct accessed by the consumer drivers using exported helper +functions. + +Try to tidy up the driver moving the firmware struct into the driver +data and make the consumer drivers referencing the secure-monitor using +a new property in the DT. + +Currently only the nvmem driver is using this API so we can fix it in +the same commit. + +Reviewed-by: Jerome Brunet +Signed-off-by: Carlo Caione +Signed-off-by: Kevin Hilman +Stable-dep-of: cbd38332c140 ("nvmem: meson-efuse: fix function pointer type mismatch") +Signed-off-by: Sasha Levin +--- + drivers/firmware/meson/meson_sm.c | 94 +++++++++++++++++-------- + drivers/nvmem/meson-efuse.c | 24 ++++++- + include/linux/firmware/meson/meson_sm.h | 15 ++-- + 3 files changed, 94 insertions(+), 39 deletions(-) + +diff --git a/drivers/firmware/meson/meson_sm.c b/drivers/firmware/meson/meson_sm.c +index 8d908a8e0d20f..7608704512054 100644 +--- a/drivers/firmware/meson/meson_sm.c ++++ b/drivers/firmware/meson/meson_sm.c +@@ -54,8 +54,6 @@ struct meson_sm_firmware { + void __iomem *sm_shmem_out_base; + }; + +-static struct meson_sm_firmware fw; +- + static u32 meson_sm_get_cmd(const struct meson_sm_chip *chip, + unsigned int cmd_index) + { +@@ -90,6 +88,7 @@ static void __iomem *meson_sm_map_shmem(u32 cmd_shmem, unsigned int size) + /** + * meson_sm_call - generic SMC32 call to the secure-monitor + * ++ * @fw: Pointer to secure-monitor firmware + * @cmd_index: Index of the SMC32 function ID + * @ret: Returned value + * @arg0: SMC32 Argument 0 +@@ -100,15 +99,15 @@ static void __iomem *meson_sm_map_shmem(u32 cmd_shmem, unsigned int size) + * + * Return: 0 on success, a negative value on error + */ +-int meson_sm_call(unsigned int cmd_index, u32 *ret, u32 arg0, +- u32 arg1, u32 arg2, u32 arg3, u32 arg4) ++int meson_sm_call(struct meson_sm_firmware *fw, unsigned int cmd_index, ++ u32 *ret, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4) + { + u32 cmd, lret; + +- if (!fw.chip) ++ if (!fw->chip) + return -ENOENT; + +- cmd = meson_sm_get_cmd(fw.chip, cmd_index); ++ cmd = meson_sm_get_cmd(fw->chip, cmd_index); + if (!cmd) + return -EINVAL; + +@@ -124,6 +123,7 @@ EXPORT_SYMBOL(meson_sm_call); + /** + * meson_sm_call_read - retrieve data from secure-monitor + * ++ * @fw: Pointer to secure-monitor firmware + * @buffer: Buffer to store the retrieved data + * @bsize: Size of the buffer + * @cmd_index: Index of the SMC32 function ID +@@ -137,22 +137,23 @@ EXPORT_SYMBOL(meson_sm_call); + * When 0 is returned there is no guarantee about the amount of + * data read and bsize bytes are copied in buffer. + */ +-int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index, +- u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4) ++int meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer, ++ unsigned int bsize, unsigned int cmd_index, u32 arg0, ++ u32 arg1, u32 arg2, u32 arg3, u32 arg4) + { + u32 size; + int ret; + +- if (!fw.chip) ++ if (!fw->chip) + return -ENOENT; + +- if (!fw.chip->cmd_shmem_out_base) ++ if (!fw->chip->cmd_shmem_out_base) + return -EINVAL; + +- if (bsize > fw.chip->shmem_size) ++ if (bsize > fw->chip->shmem_size) + return -EINVAL; + +- if (meson_sm_call(cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0) ++ if (meson_sm_call(fw, cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0) + return -EINVAL; + + if (size > bsize) +@@ -164,7 +165,7 @@ int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index, + size = bsize; + + if (buffer) +- memcpy(buffer, fw.sm_shmem_out_base, size); ++ memcpy(buffer, fw->sm_shmem_out_base, size); + + return ret; + } +@@ -173,6 +174,7 @@ EXPORT_SYMBOL(meson_sm_call_read); + /** + * meson_sm_call_write - send data to secure-monitor + * ++ * @fw: Pointer to secure-monitor firmware + * @buffer: Buffer containing data to send + * @size: Size of the data to send + * @cmd_index: Index of the SMC32 function ID +@@ -184,23 +186,24 @@ EXPORT_SYMBOL(meson_sm_call_read); + * + * Return: size of sent data on success, a negative value on error + */ +-int meson_sm_call_write(void *buffer, unsigned int size, unsigned int cmd_index, +- u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4) ++int meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer, ++ unsigned int size, unsigned int cmd_index, u32 arg0, ++ u32 arg1, u32 arg2, u32 arg3, u32 arg4) + { + u32 written; + +- if (!fw.chip) ++ if (!fw->chip) + return -ENOENT; + +- if (size > fw.chip->shmem_size) ++ if (size > fw->chip->shmem_size) + return -EINVAL; + +- if (!fw.chip->cmd_shmem_in_base) ++ if (!fw->chip->cmd_shmem_in_base) + return -EINVAL; + +- memcpy(fw.sm_shmem_in_base, buffer, size); ++ memcpy(fw->sm_shmem_in_base, buffer, size); + +- if (meson_sm_call(cmd_index, &written, arg0, arg1, arg2, arg3, arg4) < 0) ++ if (meson_sm_call(fw, cmd_index, &written, arg0, arg1, arg2, arg3, arg4) < 0) + return -EINVAL; + + if (!written) +@@ -210,6 +213,24 @@ int meson_sm_call_write(void *buffer, unsigned int size, unsigned int cmd_index, + } + EXPORT_SYMBOL(meson_sm_call_write); + ++/** ++ * meson_sm_get - get pointer to meson_sm_firmware structure. ++ * ++ * @sm_node: Pointer to the secure-monitor Device Tree node. ++ * ++ * Return: NULL is the secure-monitor device is not ready. ++ */ ++struct meson_sm_firmware *meson_sm_get(struct device_node *sm_node) ++{ ++ struct platform_device *pdev = of_find_device_by_node(sm_node); ++ ++ if (!pdev) ++ return NULL; ++ ++ return platform_get_drvdata(pdev); ++} ++EXPORT_SYMBOL_GPL(meson_sm_get); ++ + #define SM_CHIP_ID_LENGTH 119 + #define SM_CHIP_ID_OFFSET 4 + #define SM_CHIP_ID_SIZE 12 +@@ -217,14 +238,18 @@ EXPORT_SYMBOL(meson_sm_call_write); + static ssize_t serial_show(struct device *dev, struct device_attribute *attr, + char *buf) + { ++ struct platform_device *pdev = to_platform_device(dev); ++ struct meson_sm_firmware *fw; + uint8_t *id_buf; + int ret; + ++ fw = platform_get_drvdata(pdev); ++ + id_buf = kmalloc(SM_CHIP_ID_LENGTH, GFP_KERNEL); + if (!id_buf) + return -ENOMEM; + +- ret = meson_sm_call_read(id_buf, SM_CHIP_ID_LENGTH, SM_GET_CHIP_ID, ++ ret = meson_sm_call_read(fw, id_buf, SM_CHIP_ID_LENGTH, SM_GET_CHIP_ID, + 0, 0, 0, 0, 0); + if (ret < 0) { + kfree(id_buf); +@@ -268,25 +293,34 @@ static const struct of_device_id meson_sm_ids[] = { + + static int __init meson_sm_probe(struct platform_device *pdev) + { ++ struct device *dev = &pdev->dev; + const struct meson_sm_chip *chip; ++ struct meson_sm_firmware *fw; ++ ++ fw = devm_kzalloc(dev, sizeof(*fw), GFP_KERNEL); ++ if (!fw) ++ return -ENOMEM; + +- chip = of_match_device(meson_sm_ids, &pdev->dev)->data; ++ chip = of_match_device(meson_sm_ids, dev)->data; + + if (chip->cmd_shmem_in_base) { +- fw.sm_shmem_in_base = meson_sm_map_shmem(chip->cmd_shmem_in_base, +- chip->shmem_size); +- if (WARN_ON(!fw.sm_shmem_in_base)) ++ fw->sm_shmem_in_base = meson_sm_map_shmem(chip->cmd_shmem_in_base, ++ chip->shmem_size); ++ if (WARN_ON(!fw->sm_shmem_in_base)) + goto out; + } + + if (chip->cmd_shmem_out_base) { +- fw.sm_shmem_out_base = meson_sm_map_shmem(chip->cmd_shmem_out_base, +- chip->shmem_size); +- if (WARN_ON(!fw.sm_shmem_out_base)) ++ fw->sm_shmem_out_base = meson_sm_map_shmem(chip->cmd_shmem_out_base, ++ chip->shmem_size); ++ if (WARN_ON(!fw->sm_shmem_out_base)) + goto out_in_base; + } + +- fw.chip = chip; ++ fw->chip = chip; ++ ++ platform_set_drvdata(pdev, fw); ++ + pr_info("secure-monitor enabled\n"); + + if (sysfs_create_group(&pdev->dev.kobj, &meson_sm_sysfs_attr_group)) +@@ -295,7 +329,7 @@ static int __init meson_sm_probe(struct platform_device *pdev) + return 0; + + out_in_base: +- iounmap(fw.sm_shmem_in_base); ++ iounmap(fw->sm_shmem_in_base); + out: + return -EINVAL; + } +diff --git a/drivers/nvmem/meson-efuse.c b/drivers/nvmem/meson-efuse.c +index 39bd76306033f..d6b533497ce1a 100644 +--- a/drivers/nvmem/meson-efuse.c ++++ b/drivers/nvmem/meson-efuse.c +@@ -17,14 +17,18 @@ + static int meson_efuse_read(void *context, unsigned int offset, + void *val, size_t bytes) + { +- return meson_sm_call_read((u8 *)val, bytes, SM_EFUSE_READ, offset, ++ struct meson_sm_firmware *fw = context; ++ ++ return meson_sm_call_read(fw, (u8 *)val, bytes, SM_EFUSE_READ, offset, + bytes, 0, 0, 0); + } + + static int meson_efuse_write(void *context, unsigned int offset, + void *val, size_t bytes) + { +- return meson_sm_call_write((u8 *)val, bytes, SM_EFUSE_WRITE, offset, ++ struct meson_sm_firmware *fw = context; ++ ++ return meson_sm_call_write(fw, (u8 *)val, bytes, SM_EFUSE_WRITE, offset, + bytes, 0, 0, 0); + } + +@@ -37,12 +41,25 @@ MODULE_DEVICE_TABLE(of, meson_efuse_match); + static int meson_efuse_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; ++ struct meson_sm_firmware *fw; ++ struct device_node *sm_np; + struct nvmem_device *nvmem; + struct nvmem_config *econfig; + struct clk *clk; + unsigned int size; + int ret; + ++ sm_np = of_parse_phandle(pdev->dev.of_node, "secure-monitor", 0); ++ if (!sm_np) { ++ dev_err(&pdev->dev, "no secure-monitor node\n"); ++ return -ENODEV; ++ } ++ ++ fw = meson_sm_get(sm_np); ++ of_node_put(sm_np); ++ if (!fw) ++ return -EPROBE_DEFER; ++ + clk = devm_clk_get(dev, NULL); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); +@@ -65,7 +82,7 @@ static int meson_efuse_probe(struct platform_device *pdev) + return ret; + } + +- if (meson_sm_call(SM_EFUSE_USER_MAX, &size, 0, 0, 0, 0, 0) < 0) { ++ if (meson_sm_call(fw, SM_EFUSE_USER_MAX, &size, 0, 0, 0, 0, 0) < 0) { + dev_err(dev, "failed to get max user"); + return -EINVAL; + } +@@ -81,6 +98,7 @@ static int meson_efuse_probe(struct platform_device *pdev) + econfig->reg_read = meson_efuse_read; + econfig->reg_write = meson_efuse_write; + econfig->size = size; ++ econfig->priv = fw; + + nvmem = devm_nvmem_register(&pdev->dev, econfig); + +diff --git a/include/linux/firmware/meson/meson_sm.h b/include/linux/firmware/meson/meson_sm.h +index 7613bf7c94428..6669e2a1d5fdc 100644 +--- a/include/linux/firmware/meson/meson_sm.h ++++ b/include/linux/firmware/meson/meson_sm.h +@@ -16,11 +16,14 @@ enum { + + struct meson_sm_firmware; + +-int meson_sm_call(unsigned int cmd_index, u32 *ret, u32 arg0, u32 arg1, +- u32 arg2, u32 arg3, u32 arg4); +-int meson_sm_call_write(void *buffer, unsigned int b_size, unsigned int cmd_index, +- u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4); +-int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index, +- u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4); ++int meson_sm_call(struct meson_sm_firmware *fw, unsigned int cmd_index, ++ u32 *ret, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4); ++int meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer, ++ unsigned int b_size, unsigned int cmd_index, u32 arg0, ++ u32 arg1, u32 arg2, u32 arg3, u32 arg4); ++int meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer, ++ unsigned int bsize, unsigned int cmd_index, u32 arg0, ++ u32 arg1, u32 arg2, u32 arg3, u32 arg4); ++struct meson_sm_firmware *meson_sm_get(struct device_node *firmware_node); + + #endif /* _MESON_SM_FW_H_ */ +-- +2.43.0 + diff --git a/queue-5.4/fuse-don-t-unhash-root.patch b/queue-5.4/fuse-don-t-unhash-root.patch new file mode 100644 index 00000000000..25b1dfc63e9 --- /dev/null +++ b/queue-5.4/fuse-don-t-unhash-root.patch @@ -0,0 +1,54 @@ +From 82dc6b1c14b9413bda118a23192fc0cc56c57e3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Feb 2024 16:50:49 +0100 +Subject: fuse: don't unhash root + +From: Miklos Szeredi + +[ Upstream commit b1fe686a765e6c0d71811d825b5a1585a202b777 ] + +The root inode is assumed to be always hashed. Do not unhash the root +inode even if it is marked BAD. + +Fixes: 5d069dbe8aaf ("fuse: fix bad inode") +Cc: # v5.11 +Signed-off-by: Miklos Szeredi +Signed-off-by: Sasha Levin +--- + fs/fuse/fuse_i.h | 1 - + fs/fuse/inode.c | 7 +++++-- + 2 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h +index b7bd2e623c3f3..676bc4a191afb 100644 +--- a/fs/fuse/fuse_i.h ++++ b/fs/fuse/fuse_i.h +@@ -795,7 +795,6 @@ static inline u64 fuse_get_attr_version(struct fuse_conn *fc) + + static inline void fuse_make_bad(struct inode *inode) + { +- remove_inode_hash(inode); + set_bit(FUSE_I_BAD, &get_fuse_inode(inode)->state); + } + +diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c +index f3d712decb57c..287e850fbd644 100644 +--- a/fs/fuse/inode.c ++++ b/fs/fuse/inode.c +@@ -313,8 +313,11 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid, + } else if ((inode->i_mode ^ attr->mode) & S_IFMT) { + /* Inode has changed type, any I/O on the old should fail */ + fuse_make_bad(inode); +- iput(inode); +- goto retry; ++ if (inode != d_inode(sb->s_root)) { ++ remove_inode_hash(inode); ++ iput(inode); ++ goto retry; ++ } + } + + fi = get_fuse_inode(inode); +-- +2.43.0 + diff --git a/queue-5.4/fuse-drop-fuse_conn-parameter-where-possible.patch b/queue-5.4/fuse-drop-fuse_conn-parameter-where-possible.patch new file mode 100644 index 00000000000..c838bcbfafe --- /dev/null +++ b/queue-5.4/fuse-drop-fuse_conn-parameter-where-possible.patch @@ -0,0 +1,342 @@ +From 58e9060ef80221da9887c99a190f06486930f7ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Apr 2020 17:59:34 +0200 +Subject: fuse: drop fuse_conn parameter where possible + +From: Max Reitz + +[ Upstream commit 8f622e9497bbbd5df4675edf782500cd9fe961ba ] + +With the last commit, all functions that handle some existing fuse_req +no longer need to be given the associated fuse_conn, because they can +get it from the fuse_req object. + +Signed-off-by: Max Reitz +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Miklos Szeredi +Stable-dep-of: b1fe686a765e ("fuse: don't unhash root") +Signed-off-by: Sasha Levin +--- + fs/fuse/dev.c | 70 +++++++++++++++++++++++++-------------------- + fs/fuse/fuse_i.h | 2 +- + fs/fuse/virtio_fs.c | 8 ++---- + 3 files changed, 43 insertions(+), 37 deletions(-) + +diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c +index 185cae8a7ce11..96fcb004190e2 100644 +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -101,7 +101,7 @@ static void fuse_drop_waiting(struct fuse_conn *fc) + } + } + +-static void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req); ++static void fuse_put_request(struct fuse_req *req); + + static struct fuse_req *fuse_get_req(struct fuse_conn *fc, bool for_background) + { +@@ -144,7 +144,7 @@ static struct fuse_req *fuse_get_req(struct fuse_conn *fc, bool for_background) + + if (unlikely(req->in.h.uid == ((uid_t)-1) || + req->in.h.gid == ((gid_t)-1))) { +- fuse_put_request(fc, req); ++ fuse_put_request(req); + return ERR_PTR(-EOVERFLOW); + } + return req; +@@ -154,8 +154,10 @@ static struct fuse_req *fuse_get_req(struct fuse_conn *fc, bool for_background) + return ERR_PTR(err); + } + +-static void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) ++static void fuse_put_request(struct fuse_req *req) + { ++ struct fuse_conn *fc = req->fc; ++ + if (refcount_dec_and_test(&req->count)) { + if (test_bit(FR_BACKGROUND, &req->flags)) { + /* +@@ -274,8 +276,9 @@ static void flush_bg_queue(struct fuse_conn *fc) + * the 'end' callback is called if given, else the reference to the + * request is released + */ +-void fuse_request_end(struct fuse_conn *fc, struct fuse_req *req) ++void fuse_request_end(struct fuse_req *req) + { ++ struct fuse_conn *fc = req->fc; + struct fuse_iqueue *fiq = &fc->iq; + + if (test_and_set_bit(FR_FINISHED, &req->flags)) +@@ -326,12 +329,14 @@ void fuse_request_end(struct fuse_conn *fc, struct fuse_req *req) + if (test_bit(FR_ASYNC, &req->flags)) + req->args->end(fc, req->args, req->out.h.error); + put_request: +- fuse_put_request(fc, req); ++ fuse_put_request(req); + } + EXPORT_SYMBOL_GPL(fuse_request_end); + +-static int queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req) ++static int queue_interrupt(struct fuse_req *req) + { ++ struct fuse_iqueue *fiq = &req->fc->iq; ++ + spin_lock(&fiq->lock); + /* Check for we've sent request to interrupt this req */ + if (unlikely(!test_bit(FR_INTERRUPTED, &req->flags))) { +@@ -358,8 +363,9 @@ static int queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req) + return 0; + } + +-static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) ++static void request_wait_answer(struct fuse_req *req) + { ++ struct fuse_conn *fc = req->fc; + struct fuse_iqueue *fiq = &fc->iq; + int err; + +@@ -374,7 +380,7 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) + /* matches barrier in fuse_dev_do_read() */ + smp_mb__after_atomic(); + if (test_bit(FR_SENT, &req->flags)) +- queue_interrupt(fiq, req); ++ queue_interrupt(req); + } + + if (!test_bit(FR_FORCE, &req->flags)) { +@@ -403,9 +409,9 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) + wait_event(req->waitq, test_bit(FR_FINISHED, &req->flags)); + } + +-static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) ++static void __fuse_request_send(struct fuse_req *req) + { +- struct fuse_iqueue *fiq = &fc->iq; ++ struct fuse_iqueue *fiq = &req->fc->iq; + + BUG_ON(test_bit(FR_BACKGROUND, &req->flags)); + spin_lock(&fiq->lock); +@@ -419,7 +425,7 @@ static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) + __fuse_get_request(req); + queue_request_and_unlock(fiq, req); + +- request_wait_answer(fc, req); ++ request_wait_answer(req); + /* Pairs with smp_wmb() in fuse_request_end() */ + smp_rmb(); + } +@@ -458,8 +464,10 @@ static void fuse_adjust_compat(struct fuse_conn *fc, struct fuse_args *args) + } + } + +-static void fuse_force_creds(struct fuse_conn *fc, struct fuse_req *req) ++static void fuse_force_creds(struct fuse_req *req) + { ++ struct fuse_conn *fc = req->fc; ++ + req->in.h.uid = from_kuid_munged(fc->user_ns, current_fsuid()); + req->in.h.gid = from_kgid_munged(fc->user_ns, current_fsgid()); + req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns); +@@ -484,7 +492,7 @@ ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args) + req = fuse_request_alloc(fc, GFP_KERNEL | __GFP_NOFAIL); + + if (!args->nocreds) +- fuse_force_creds(fc, req); ++ fuse_force_creds(req); + + __set_bit(FR_WAITING, &req->flags); + __set_bit(FR_FORCE, &req->flags); +@@ -501,20 +509,20 @@ ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args) + + if (!args->noreply) + __set_bit(FR_ISREPLY, &req->flags); +- __fuse_request_send(fc, req); ++ __fuse_request_send(req); + ret = req->out.h.error; + if (!ret && args->out_argvar) { + BUG_ON(args->out_numargs == 0); + ret = args->out_args[args->out_numargs - 1].size; + } +- fuse_put_request(fc, req); ++ fuse_put_request(req); + + return ret; + } + +-static bool fuse_request_queue_background(struct fuse_conn *fc, +- struct fuse_req *req) ++static bool fuse_request_queue_background(struct fuse_req *req) + { ++ struct fuse_conn *fc = req->fc; + bool queued = false; + + WARN_ON(!test_bit(FR_BACKGROUND, &req->flags)); +@@ -561,8 +569,8 @@ int fuse_simple_background(struct fuse_conn *fc, struct fuse_args *args, + + fuse_args_to_req(req, args); + +- if (!fuse_request_queue_background(fc, req)) { +- fuse_put_request(fc, req); ++ if (!fuse_request_queue_background(req)) { ++ fuse_put_request(req); + return -ENOTCONN; + } + +@@ -592,7 +600,7 @@ static int fuse_simple_notify_reply(struct fuse_conn *fc, + } else { + err = -ENODEV; + spin_unlock(&fiq->lock); +- fuse_put_request(fc, req); ++ fuse_put_request(req); + } + + return err; +@@ -1277,7 +1285,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, + /* SETXATTR is special, since it may contain too large data */ + if (args->opcode == FUSE_SETXATTR) + req->out.h.error = -E2BIG; +- fuse_request_end(fc, req); ++ fuse_request_end(req); + goto restart; + } + spin_lock(&fpq->lock); +@@ -1320,8 +1328,8 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, + /* matches barrier in request_wait_answer() */ + smp_mb__after_atomic(); + if (test_bit(FR_INTERRUPTED, &req->flags)) +- queue_interrupt(fiq, req); +- fuse_put_request(fc, req); ++ queue_interrupt(req); ++ fuse_put_request(req); + + return reqsize; + +@@ -1329,7 +1337,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, + if (!test_bit(FR_PRIVATE, &req->flags)) + list_del_init(&req->list); + spin_unlock(&fpq->lock); +- fuse_request_end(fc, req); ++ fuse_request_end(req); + return err; + + err_unlock: +@@ -1911,9 +1919,9 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud, + else if (oh.error == -ENOSYS) + fc->no_interrupt = 1; + else if (oh.error == -EAGAIN) +- err = queue_interrupt(&fc->iq, req); ++ err = queue_interrupt(req); + +- fuse_put_request(fc, req); ++ fuse_put_request(req); + + goto copy_finish; + } +@@ -1943,7 +1951,7 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud, + list_del_init(&req->list); + spin_unlock(&fpq->lock); + +- fuse_request_end(fc, req); ++ fuse_request_end(req); + out: + return err ? err : nbytes; + +@@ -2079,7 +2087,7 @@ static __poll_t fuse_dev_poll(struct file *file, poll_table *wait) + } + + /* Abort all requests on the given list (pending or processing) */ +-static void end_requests(struct fuse_conn *fc, struct list_head *head) ++static void end_requests(struct list_head *head) + { + while (!list_empty(head)) { + struct fuse_req *req; +@@ -2087,7 +2095,7 @@ static void end_requests(struct fuse_conn *fc, struct list_head *head) + req->out.h.error = -ECONNABORTED; + clear_bit(FR_SENT, &req->flags); + list_del_init(&req->list); +- fuse_request_end(fc, req); ++ fuse_request_end(req); + } + } + +@@ -2182,7 +2190,7 @@ void fuse_abort_conn(struct fuse_conn *fc) + wake_up_all(&fc->blocked_waitq); + spin_unlock(&fc->lock); + +- end_requests(fc, &to_end); ++ end_requests(&to_end); + } else { + spin_unlock(&fc->lock); + } +@@ -2212,7 +2220,7 @@ int fuse_dev_release(struct inode *inode, struct file *file) + list_splice_init(&fpq->processing[i], &to_end); + spin_unlock(&fpq->lock); + +- end_requests(fc, &to_end); ++ end_requests(&to_end); + + /* Are we the last open device? */ + if (atomic_dec_and_test(&fc->dev_count)) { +diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h +index 7138b780c9abd..b7bd2e623c3f3 100644 +--- a/fs/fuse/fuse_i.h ++++ b/fs/fuse/fuse_i.h +@@ -941,7 +941,7 @@ int fuse_simple_background(struct fuse_conn *fc, struct fuse_args *args, + /** + * End a finished request + */ +-void fuse_request_end(struct fuse_conn *fc, struct fuse_req *req); ++void fuse_request_end(struct fuse_req *req); + + /* Abort all requests */ + void fuse_abort_conn(struct fuse_conn *fc); +diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c +index fadf6fb90fe22..8865ab961abfe 100644 +--- a/fs/fuse/virtio_fs.c ++++ b/fs/fuse/virtio_fs.c +@@ -268,7 +268,6 @@ static void virtio_fs_request_dispatch_work(struct work_struct *work) + struct fuse_req *req; + struct virtio_fs_vq *fsvq = container_of(work, struct virtio_fs_vq, + dispatch_work.work); +- struct fuse_conn *fc = fsvq->fud->fc; + int ret; + + pr_debug("virtio-fs: worker %s called.\n", __func__); +@@ -283,7 +282,7 @@ static void virtio_fs_request_dispatch_work(struct work_struct *work) + + list_del_init(&req->list); + spin_unlock(&fsvq->lock); +- fuse_request_end(fc, req); ++ fuse_request_end(req); + } + + /* Dispatch pending requests */ +@@ -314,7 +313,7 @@ static void virtio_fs_request_dispatch_work(struct work_struct *work) + spin_unlock(&fsvq->lock); + pr_err("virtio-fs: virtio_fs_enqueue_req() failed %d\n", + ret); +- fuse_request_end(fc, req); ++ fuse_request_end(req); + } + } + } +@@ -453,7 +452,6 @@ static void virtio_fs_request_complete(struct fuse_req *req, + struct virtio_fs_vq *fsvq) + { + struct fuse_pqueue *fpq = &fsvq->fud->pq; +- struct fuse_conn *fc = fsvq->fud->fc; + struct fuse_args *args; + struct fuse_args_pages *ap; + unsigned int len, i, thislen; +@@ -486,7 +484,7 @@ static void virtio_fs_request_complete(struct fuse_req *req, + clear_bit(FR_SENT, &req->flags); + spin_unlock(&fpq->lock); + +- fuse_request_end(fc, req); ++ fuse_request_end(req); + spin_lock(&fsvq->lock); + dec_in_flight_req(fsvq); + spin_unlock(&fsvq->lock); +-- +2.43.0 + diff --git a/queue-5.4/fuse-store-fuse_conn-in-fuse_req.patch b/queue-5.4/fuse-store-fuse_conn-in-fuse_req.patch new file mode 100644 index 00000000000..bcf6d9a227c --- /dev/null +++ b/queue-5.4/fuse-store-fuse_conn-in-fuse_req.patch @@ -0,0 +1,101 @@ +From 437aa1e2b0ce897e451b5a41c9a5a3db6aa9f7e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Apr 2020 17:54:38 +0200 +Subject: fuse: store fuse_conn in fuse_req + +From: Max Reitz + +[ Upstream commit 24754db2728a87c513cc480c70c09072a7a40ba6 ] + +Every fuse_req belongs to a fuse_conn. Right now, we always know which +fuse_conn that is based on the respective device, but we want to allow +multiple (sub)mounts per single connection, and then the corresponding +filesystem is not going to be so trivial to obtain. + +Storing a pointer to the associated fuse_conn in every fuse_req will +allow us to trivially find any request's superblock (and thus +filesystem) even then. + +Signed-off-by: Max Reitz +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Miklos Szeredi +Stable-dep-of: b1fe686a765e ("fuse: don't unhash root") +Signed-off-by: Sasha Levin +--- + fs/fuse/dev.c | 13 +++++++------ + fs/fuse/fuse_i.h | 3 +++ + 2 files changed, 10 insertions(+), 6 deletions(-) + +diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c +index ac6a8da340139..185cae8a7ce11 100644 +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -40,20 +40,21 @@ static struct fuse_dev *fuse_get_dev(struct file *file) + return READ_ONCE(file->private_data); + } + +-static void fuse_request_init(struct fuse_req *req) ++static void fuse_request_init(struct fuse_conn *fc, struct fuse_req *req) + { + INIT_LIST_HEAD(&req->list); + INIT_LIST_HEAD(&req->intr_entry); + init_waitqueue_head(&req->waitq); + refcount_set(&req->count, 1); + __set_bit(FR_PENDING, &req->flags); ++ req->fc = fc; + } + +-static struct fuse_req *fuse_request_alloc(gfp_t flags) ++static struct fuse_req *fuse_request_alloc(struct fuse_conn *fc, gfp_t flags) + { + struct fuse_req *req = kmem_cache_zalloc(fuse_req_cachep, flags); + if (req) +- fuse_request_init(req); ++ fuse_request_init(fc, req); + + return req; + } +@@ -125,7 +126,7 @@ static struct fuse_req *fuse_get_req(struct fuse_conn *fc, bool for_background) + if (fc->conn_error) + goto out; + +- req = fuse_request_alloc(GFP_KERNEL); ++ req = fuse_request_alloc(fc, GFP_KERNEL); + err = -ENOMEM; + if (!req) { + if (for_background) +@@ -480,7 +481,7 @@ ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args) + + if (args->force) { + atomic_inc(&fc->num_waiting); +- req = fuse_request_alloc(GFP_KERNEL | __GFP_NOFAIL); ++ req = fuse_request_alloc(fc, GFP_KERNEL | __GFP_NOFAIL); + + if (!args->nocreds) + fuse_force_creds(fc, req); +@@ -547,7 +548,7 @@ int fuse_simple_background(struct fuse_conn *fc, struct fuse_args *args, + + if (args->force) { + WARN_ON(!args->nocreds); +- req = fuse_request_alloc(gfp_flags); ++ req = fuse_request_alloc(fc, gfp_flags); + if (!req) + return -ENOMEM; + __set_bit(FR_BACKGROUND, &req->flags); +diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h +index 83c2855bc7406..7138b780c9abd 100644 +--- a/fs/fuse/fuse_i.h ++++ b/fs/fuse/fuse_i.h +@@ -363,6 +363,9 @@ struct fuse_req { + /** virtio-fs's physically contiguous buffer for in and out args */ + void *argbuf; + #endif ++ ++ /** fuse_conn this request belongs to */ ++ struct fuse_conn *fc; + }; + + struct fuse_iqueue; +-- +2.43.0 + diff --git a/queue-5.4/hwmon-amc6821-add-of_match-table.patch b/queue-5.4/hwmon-amc6821-add-of_match-table.patch new file mode 100644 index 00000000000..403758294ca --- /dev/null +++ b/queue-5.4/hwmon-amc6821-add-of_match-table.patch @@ -0,0 +1,56 @@ +From 08f28a0fc60fac7c2f52a77b10a98b149ff28891 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Mar 2024 12:06:58 +0100 +Subject: hwmon: (amc6821) add of_match table + +From: Josua Mayer + +[ Upstream commit 3f003fda98a7a8d5f399057d92e6ed56b468657c ] + +Add of_match table for "ti,amc6821" compatible string. +This fixes automatic driver loading by userspace when using device-tree, +and if built as a module like major linux distributions do. + +While devices probe just fine with i2c_device_id table, userspace can't +match the "ti,amc6821" compatible string from dt with the plain +"amc6821" device id. As a result, the kernel module can not be loaded. + +Cc: stable@vger.kernel.org +Signed-off-by: Josua Mayer +Link: https://lore.kernel.org/r/20240307-amc6821-of-match-v1-1-5f40464a3110@solid-run.com +[groeck: Cleaned up patch description] +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/amc6821.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c +index 013fb056b1d02..a8e94d73eaa04 100644 +--- a/drivers/hwmon/amc6821.c ++++ b/drivers/hwmon/amc6821.c +@@ -935,10 +935,21 @@ static const struct i2c_device_id amc6821_id[] = { + + MODULE_DEVICE_TABLE(i2c, amc6821_id); + ++static const struct of_device_id __maybe_unused amc6821_of_match[] = { ++ { ++ .compatible = "ti,amc6821", ++ .data = (void *)amc6821, ++ }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(of, amc6821_of_match); ++ + static struct i2c_driver amc6821_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "amc6821", ++ .of_match_table = of_match_ptr(amc6821_of_match), + }, + .probe = amc6821_probe, + .id_table = amc6821_id, +-- +2.43.0 + diff --git a/queue-5.4/kbuild-move-wenum-compare-conditional-enum-conversio.patch b/queue-5.4/kbuild-move-wenum-compare-conditional-enum-conversio.patch new file mode 100644 index 00000000000..9396417cd43 --- /dev/null +++ b/queue-5.4/kbuild-move-wenum-compare-conditional-enum-conversio.patch @@ -0,0 +1,72 @@ +From 5e354914ef3da9fe773c833469be40f0efdd559c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Mar 2024 15:12:47 -0700 +Subject: kbuild: Move -Wenum-{compare-conditional,enum-conversion} into W=1 + +From: Nathan Chancellor + +[ Upstream commit 75b5ab134bb5f657ef7979a59106dce0657e8d87 ] + +Clang enables -Wenum-enum-conversion and -Wenum-compare-conditional +under -Wenum-conversion. A recent change in Clang strengthened these +warnings and they appear frequently in common builds, primarily due to +several instances in common headers but there are quite a few drivers +that have individual instances as well. + + include/linux/vmstat.h:508:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion] + 508 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS + + | ~~~~~~~~~~~~~~~~~~~~~ ^ + 509 | item]; + | ~~~~ + + drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c:955:24: warning: conditional expression between different enumeration types ('enum iwl_mac_beacon_flags' and 'enum iwl_mac_beacon_flags_v1') [-Wenum-compare-conditional] + 955 | flags |= is_new_rate ? IWL_MAC_BEACON_CCK + | ^ ~~~~~~~~~~~~~~~~~~ + 956 | : IWL_MAC_BEACON_CCK_V1; + | ~~~~~~~~~~~~~~~~~~~~~ + drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c:1120:21: warning: conditional expression between different enumeration types ('enum iwl_mac_beacon_flags' and 'enum iwl_mac_beacon_flags_v1') [-Wenum-compare-conditional] + 1120 | 0) > 10 ? + | ^ + 1121 | IWL_MAC_BEACON_FILS : + | ~~~~~~~~~~~~~~~~~~~ + 1122 | IWL_MAC_BEACON_FILS_V1; + | ~~~~~~~~~~~~~~~~~~~~~~ + +Doing arithmetic between or returning two different types of enums could +be a bug, so each of the instance of the warning needs to be evaluated. +Unfortunately, as mentioned above, there are many instances of this +warning in many different configurations, which can break the build when +CONFIG_WERROR is enabled. + +To avoid introducing new instances of the warnings while cleaning up the +disruption for the majority of users, disable these warnings for the +default build while leaving them on for W=1 builds. + +Cc: stable@vger.kernel.org +Closes: https://github.com/ClangBuiltLinux/linux/issues/2002 +Link: https://github.com/llvm/llvm-project/commit/8c2ae42b3e1c6aa7c18f873edcebff7c0b45a37e +Acked-by: Yonghong Song +Signed-off-by: Nathan Chancellor +Acked-by: Arnd Bergmann +Signed-off-by: Masahiro Yamada +Signed-off-by: Sasha Levin +--- + scripts/Makefile.extrawarn | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn +index 6a78afc6f13b4..a51193485c50f 100644 +--- a/scripts/Makefile.extrawarn ++++ b/scripts/Makefile.extrawarn +@@ -51,6 +51,8 @@ KBUILD_CFLAGS += -Wno-format-zero-length + KBUILD_CFLAGS += $(call cc-disable-warning, pointer-to-enum-cast) + KBUILD_CFLAGS += $(call cc-disable-warning, unaligned-access) + KBUILD_CFLAGS += $(call cc-disable-warning, cast-function-type-strict) ++KBUILD_CFLAGS += -Wno-enum-compare-conditional ++KBUILD_CFLAGS += -Wno-enum-enum-conversion + endif + + endif +-- +2.43.0 + diff --git a/queue-5.4/kvm-always-flush-async-pf-workqueue-when-vcpu-is-bei.patch b/queue-5.4/kvm-always-flush-async-pf-workqueue-when-vcpu-is-bei.patch new file mode 100644 index 00000000000..ecab60e80fb --- /dev/null +++ b/queue-5.4/kvm-always-flush-async-pf-workqueue-when-vcpu-is-bei.patch @@ -0,0 +1,183 @@ +From 31e45bfb63b6a2b735bd32e1d6b0092063375d2d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Jan 2024 17:15:30 -0800 +Subject: KVM: Always flush async #PF workqueue when vCPU is being destroyed + +From: Sean Christopherson + +[ Upstream commit 3d75b8aa5c29058a512db29da7cbee8052724157 ] + +Always flush the per-vCPU async #PF workqueue when a vCPU is clearing its +completion queue, e.g. when a VM and all its vCPUs is being destroyed. +KVM must ensure that none of its workqueue callbacks is running when the +last reference to the KVM _module_ is put. Gifting a reference to the +associated VM prevents the workqueue callback from dereferencing freed +vCPU/VM memory, but does not prevent the KVM module from being unloaded +before the callback completes. + +Drop the misguided VM refcount gifting, as calling kvm_put_kvm() from +async_pf_execute() if kvm_put_kvm() flushes the async #PF workqueue will +result in deadlock. async_pf_execute() can't return until kvm_put_kvm() +finishes, and kvm_put_kvm() can't return until async_pf_execute() finishes: + + WARNING: CPU: 8 PID: 251 at virt/kvm/kvm_main.c:1435 kvm_put_kvm+0x2d/0x320 [kvm] + Modules linked in: vhost_net vhost vhost_iotlb tap kvm_intel kvm irqbypass + CPU: 8 PID: 251 Comm: kworker/8:1 Tainted: G W 6.6.0-rc1-e7af8d17224a-x86/gmem-vm #119 + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 + Workqueue: events async_pf_execute [kvm] + RIP: 0010:kvm_put_kvm+0x2d/0x320 [kvm] + Call Trace: + + async_pf_execute+0x198/0x260 [kvm] + process_one_work+0x145/0x2d0 + worker_thread+0x27e/0x3a0 + kthread+0xba/0xe0 + ret_from_fork+0x2d/0x50 + ret_from_fork_asm+0x11/0x20 + + ---[ end trace 0000000000000000 ]--- + INFO: task kworker/8:1:251 blocked for more than 120 seconds. + Tainted: G W 6.6.0-rc1-e7af8d17224a-x86/gmem-vm #119 + "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. + task:kworker/8:1 state:D stack:0 pid:251 ppid:2 flags:0x00004000 + Workqueue: events async_pf_execute [kvm] + Call Trace: + + __schedule+0x33f/0xa40 + schedule+0x53/0xc0 + schedule_timeout+0x12a/0x140 + __wait_for_common+0x8d/0x1d0 + __flush_work.isra.0+0x19f/0x2c0 + kvm_clear_async_pf_completion_queue+0x129/0x190 [kvm] + kvm_arch_destroy_vm+0x78/0x1b0 [kvm] + kvm_put_kvm+0x1c1/0x320 [kvm] + async_pf_execute+0x198/0x260 [kvm] + process_one_work+0x145/0x2d0 + worker_thread+0x27e/0x3a0 + kthread+0xba/0xe0 + ret_from_fork+0x2d/0x50 + ret_from_fork_asm+0x11/0x20 + + +If kvm_clear_async_pf_completion_queue() actually flushes the workqueue, +then there's no need to gift async_pf_execute() a reference because all +invocations of async_pf_execute() will be forced to complete before the +vCPU and its VM are destroyed/freed. And that in turn fixes the module +unloading bug as __fput() won't do module_put() on the last vCPU reference +until the vCPU has been freed, e.g. if closing the vCPU file also puts the +last reference to the KVM module. + +Note that kvm_check_async_pf_completion() may also take the work item off +the completion queue and so also needs to flush the work queue, as the +work will not be seen by kvm_clear_async_pf_completion_queue(). Waiting +on the workqueue could theoretically delay a vCPU due to waiting for the +work to complete, but that's a very, very small chance, and likely a very +small delay. kvm_arch_async_page_present_queued() unconditionally makes a +new request, i.e. will effectively delay entering the guest, so the +remaining work is really just: + + trace_kvm_async_pf_completed(addr, cr2_or_gpa); + + __kvm_vcpu_wake_up(vcpu); + + mmput(mm); + +and mmput() can't drop the last reference to the page tables if the vCPU is +still alive, i.e. the vCPU won't get stuck tearing down page tables. + +Add a helper to do the flushing, specifically to deal with "wakeup all" +work items, as they aren't actually work items, i.e. are never placed in a +workqueue. Trying to flush a bogus workqueue entry rightly makes +__flush_work() complain (kudos to whoever added that sanity check). + +Note, commit 5f6de5cbebee ("KVM: Prevent module exit until all VMs are +freed") *tried* to fix the module refcounting issue by having VMs grab a +reference to the module, but that only made the bug slightly harder to hit +as it gave async_pf_execute() a bit more time to complete before the KVM +module could be unloaded. + +Fixes: af585b921e5d ("KVM: Halt vcpu if page it tries to access is swapped out") +Cc: stable@vger.kernel.org +Cc: David Matlack +Reviewed-by: Xu Yilun +Reviewed-by: Vitaly Kuznetsov +Link: https://lore.kernel.org/r/20240110011533.503302-2-seanjc@google.com +Signed-off-by: Sean Christopherson +Signed-off-by: Sasha Levin +--- + virt/kvm/async_pf.c | 31 ++++++++++++++++++++++++++----- + 1 file changed, 26 insertions(+), 5 deletions(-) + +diff --git a/virt/kvm/async_pf.c b/virt/kvm/async_pf.c +index d8ef708a2ef67..d0a1113b0e55c 100644 +--- a/virt/kvm/async_pf.c ++++ b/virt/kvm/async_pf.c +@@ -98,7 +98,27 @@ static void async_pf_execute(struct work_struct *work) + swake_up_one(&vcpu->wq); + + mmput(mm); +- kvm_put_kvm(vcpu->kvm); ++} ++ ++static void kvm_flush_and_free_async_pf_work(struct kvm_async_pf *work) ++{ ++ /* ++ * The async #PF is "done", but KVM must wait for the work item itself, ++ * i.e. async_pf_execute(), to run to completion. If KVM is a module, ++ * KVM must ensure *no* code owned by the KVM (the module) can be run ++ * after the last call to module_put(). Note, flushing the work item ++ * is always required when the item is taken off the completion queue. ++ * E.g. even if the vCPU handles the item in the "normal" path, the VM ++ * could be terminated before async_pf_execute() completes. ++ * ++ * Wake all events skip the queue and go straight done, i.e. don't ++ * need to be flushed (but sanity check that the work wasn't queued). ++ */ ++ if (work->wakeup_all) ++ WARN_ON_ONCE(work->work.func); ++ else ++ flush_work(&work->work); ++ kmem_cache_free(async_pf_cache, work); + } + + void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu) +@@ -125,7 +145,6 @@ void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu) + #else + if (cancel_work_sync(&work->work)) { + mmput(work->mm); +- kvm_put_kvm(vcpu->kvm); /* == work->vcpu->kvm */ + kmem_cache_free(async_pf_cache, work); + } + #endif +@@ -137,7 +156,10 @@ void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu) + list_first_entry(&vcpu->async_pf.done, + typeof(*work), link); + list_del(&work->link); +- kmem_cache_free(async_pf_cache, work); ++ ++ spin_unlock(&vcpu->async_pf.lock); ++ kvm_flush_and_free_async_pf_work(work); ++ spin_lock(&vcpu->async_pf.lock); + } + spin_unlock(&vcpu->async_pf.lock); + +@@ -161,7 +183,7 @@ void kvm_check_async_pf_completion(struct kvm_vcpu *vcpu) + + list_del(&work->queue); + vcpu->async_pf.queued--; +- kmem_cache_free(async_pf_cache, work); ++ kvm_flush_and_free_async_pf_work(work); + } + } + +@@ -190,7 +212,6 @@ int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, + work->arch = *arch; + work->mm = current->mm; + mmget(work->mm); +- kvm_get_kvm(work->vcpu->kvm); + + /* this can't really happen otherwise gfn_to_pfn_async + would succeed */ +-- +2.43.0 + diff --git a/queue-5.4/media-staging-ipu3-imgu-set-fields-before-media_enti.patch b/queue-5.4/media-staging-ipu3-imgu-set-fields-before-media_enti.patch new file mode 100644 index 00000000000..459d9c04a44 --- /dev/null +++ b/queue-5.4/media-staging-ipu3-imgu-set-fields-before-media_enti.patch @@ -0,0 +1,81 @@ +From a2f1dfa244689b068b46c0f5accf458ff15bed02 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Jan 2024 17:09:09 +0900 +Subject: media: staging: ipu3-imgu: Set fields before media_entity_pads_init() + +From: Hidenori Kobayashi + +[ Upstream commit 87318b7092670d4086bfec115a0280a60c51c2dd ] + +The imgu driver fails to probe with the following message because it +does not set the pad's flags before calling media_entity_pads_init(). + +[ 14.596315] ipu3-imgu 0000:00:05.0: failed initialize subdev media entity (-22) +[ 14.596322] ipu3-imgu 0000:00:05.0: failed to register subdev0 ret (-22) +[ 14.596327] ipu3-imgu 0000:00:05.0: failed to register pipes (-22) +[ 14.596331] ipu3-imgu 0000:00:05.0: failed to create V4L2 devices (-22) + +Fix the initialization order so that the driver probe succeeds. The ops +initialization is also moved together for readability. + +Fixes: a0ca1627b450 ("media: staging/intel-ipu3: Add v4l2 driver based on media framework") +Cc: # 6.7 +Cc: Dan Carpenter +Signed-off-by: Hidenori Kobayashi +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/staging/media/ipu3/ipu3-v4l2.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/staging/media/ipu3/ipu3-v4l2.c b/drivers/staging/media/ipu3/ipu3-v4l2.c +index 53239ea67fe48..ee9fed6fc67e9 100644 +--- a/drivers/staging/media/ipu3/ipu3-v4l2.c ++++ b/drivers/staging/media/ipu3/ipu3-v4l2.c +@@ -1115,6 +1115,11 @@ static int imgu_v4l2_subdev_register(struct imgu_device *imgu, + struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe]; + + /* Initialize subdev media entity */ ++ imgu_sd->subdev.entity.ops = &imgu_media_ops; ++ for (i = 0; i < IMGU_NODE_NUM; i++) { ++ imgu_sd->subdev_pads[i].flags = imgu_pipe->nodes[i].output ? ++ MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; ++ } + r = media_entity_pads_init(&imgu_sd->subdev.entity, IMGU_NODE_NUM, + imgu_sd->subdev_pads); + if (r) { +@@ -1122,11 +1127,6 @@ static int imgu_v4l2_subdev_register(struct imgu_device *imgu, + "failed initialize subdev media entity (%d)\n", r); + return r; + } +- imgu_sd->subdev.entity.ops = &imgu_media_ops; +- for (i = 0; i < IMGU_NODE_NUM; i++) { +- imgu_sd->subdev_pads[i].flags = imgu_pipe->nodes[i].output ? +- MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; +- } + + /* Initialize subdev */ + v4l2_subdev_init(&imgu_sd->subdev, &imgu_subdev_ops); +@@ -1221,15 +1221,15 @@ static int imgu_v4l2_node_setup(struct imgu_device *imgu, unsigned int pipe, + } + + /* Initialize media entities */ ++ node->vdev_pad.flags = node->output ? ++ MEDIA_PAD_FL_SOURCE : MEDIA_PAD_FL_SINK; ++ vdev->entity.ops = NULL; + r = media_entity_pads_init(&vdev->entity, 1, &node->vdev_pad); + if (r) { + dev_err(dev, "failed initialize media entity (%d)\n", r); + mutex_destroy(&node->lock); + return r; + } +- node->vdev_pad.flags = node->output ? +- MEDIA_PAD_FL_SOURCE : MEDIA_PAD_FL_SINK; +- vdev->entity.ops = NULL; + + /* Initialize vbq */ + vbq->type = node->vdev_fmt.type; +-- +2.43.0 + diff --git a/queue-5.4/media-xc4000-fix-atomicity-violation-in-xc4000_get_f.patch b/queue-5.4/media-xc4000-fix-atomicity-violation-in-xc4000_get_f.patch new file mode 100644 index 00000000000..4c39e588ff2 --- /dev/null +++ b/queue-5.4/media-xc4000-fix-atomicity-violation-in-xc4000_get_f.patch @@ -0,0 +1,79 @@ +From 0c88ec0ac6041bc08c8d293c554441b64d39eb7d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Dec 2023 13:50:30 +0800 +Subject: media: xc4000: Fix atomicity violation in xc4000_get_frequency + +From: Gui-Dong Han <2045gemini@gmail.com> + +[ Upstream commit 36d503ad547d1c75758a6fcdbec2806f1b6aeb41 ] + +In xc4000_get_frequency(): + *freq = priv->freq_hz + priv->freq_offset; +The code accesses priv->freq_hz and priv->freq_offset without holding any +lock. + +In xc4000_set_params(): + // Code that updates priv->freq_hz and priv->freq_offset + ... + +xc4000_get_frequency() and xc4000_set_params() may execute concurrently, +risking inconsistent reads of priv->freq_hz and priv->freq_offset. Since +these related data may update during reading, it can result in incorrect +frequency calculation, leading to atomicity violations. + +This possible bug is found by an experimental static analysis tool +developed by our team, BassCheck[1]. This tool analyzes the locking APIs +to extract function pairs that can be concurrently executed, and then +analyzes the instructions in the paired functions to identify possible +concurrency bugs including data races and atomicity violations. The above +possible bug is reported when our tool analyzes the source code of +Linux 6.2. + +To address this issue, it is proposed to add a mutex lock pair in +xc4000_get_frequency() to ensure atomicity. With this patch applied, our +tool no longer reports the possible bug, with the kernel configuration +allyesconfig for x86_64. Due to the lack of associated hardware, we cannot +test the patch in runtime testing, and just verify it according to the +code logic. + +[1] https://sites.google.com/view/basscheck/ + +Fixes: 4c07e32884ab ("[media] xc4000: Fix get_frequency()") +Cc: stable@vger.kernel.org +Reported-by: BassCheck +Signed-off-by: Gui-Dong Han <2045gemini@gmail.com> +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/tuners/xc4000.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/tuners/xc4000.c b/drivers/media/tuners/xc4000.c +index ef9af052007cb..849df4d1c573c 100644 +--- a/drivers/media/tuners/xc4000.c ++++ b/drivers/media/tuners/xc4000.c +@@ -1517,10 +1517,10 @@ static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq) + { + struct xc4000_priv *priv = fe->tuner_priv; + ++ mutex_lock(&priv->lock); + *freq = priv->freq_hz + priv->freq_offset; + + if (debug) { +- mutex_lock(&priv->lock); + if ((priv->cur_fw.type + & (BASE | FM | DTV6 | DTV7 | DTV78 | DTV8)) == BASE) { + u16 snr = 0; +@@ -1531,8 +1531,8 @@ static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq) + return 0; + } + } +- mutex_unlock(&priv->lock); + } ++ mutex_unlock(&priv->lock); + + dprintk(1, "%s()\n", __func__); + +-- +2.43.0 + diff --git a/queue-5.4/memtest-use-read-write-_once-in-memory-scanning.patch b/queue-5.4/memtest-use-read-write-_once-in-memory-scanning.patch new file mode 100644 index 00000000000..43ded8c2d35 --- /dev/null +++ b/queue-5.4/memtest-use-read-write-_once-in-memory-scanning.patch @@ -0,0 +1,45 @@ +From ccf953f57b1fe9b58efd8a8e3713ba3928c410d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Mar 2024 16:04:23 +0800 +Subject: memtest: use {READ,WRITE}_ONCE in memory scanning + +From: Qiang Zhang + +[ Upstream commit 82634d7e24271698e50a3ec811e5f50de790a65f ] + +memtest failed to find bad memory when compiled with clang. So use +{WRITE,READ}_ONCE to access memory to avoid compiler over optimization. + +Link: https://lkml.kernel.org/r/20240312080422.691222-1-qiang4.zhang@intel.com +Signed-off-by: Qiang Zhang +Cc: Bill Wendling +Cc: Justin Stitt +Cc: Nathan Chancellor +Cc: Nick Desaulniers +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + mm/memtest.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/mm/memtest.c b/mm/memtest.c +index f53ace709ccd8..d407373f225b4 100644 +--- a/mm/memtest.c ++++ b/mm/memtest.c +@@ -46,10 +46,10 @@ static void __init memtest(u64 pattern, phys_addr_t start_phys, phys_addr_t size + last_bad = 0; + + for (p = start; p < end; p++) +- *p = pattern; ++ WRITE_ONCE(*p, pattern); + + for (p = start; p < end; p++, start_phys_aligned += incr) { +- if (*p == pattern) ++ if (READ_ONCE(*p) == pattern) + continue; + if (start_phys_aligned == last_bad + incr) { + last_bad += incr; +-- +2.43.0 + diff --git a/queue-5.4/mmc-core-fix-switch-on-gp3-partition.patch b/queue-5.4/mmc-core-fix-switch-on-gp3-partition.patch new file mode 100644 index 00000000000..2df63653acd --- /dev/null +++ b/queue-5.4/mmc-core-fix-switch-on-gp3-partition.patch @@ -0,0 +1,86 @@ +From f5db3108a2ca65dcfeff70e362b62f06b3306d84 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Mar 2024 10:44:38 +0900 +Subject: mmc: core: Fix switch on gp3 partition + +From: Dominique Martinet + +[ Upstream commit 4af59a8df5ea930038cd3355e822f5eedf4accc1 ] + +Commit e7794c14fd73 ("mmc: rpmb: fixes pause retune on all RPMB +partitions.") added a mask check for 'part_type', but the mask used was +wrong leading to the code intended for rpmb also being executed for GP3. + +On some MMCs (but not all) this would make gp3 partition inaccessible: +armadillo:~# head -c 1 < /dev/mmcblk2gp3 +head: standard input: I/O error +armadillo:~# dmesg -c +[ 422.976583] mmc2: running CQE recovery +[ 423.058182] mmc2: running CQE recovery +[ 423.137607] mmc2: running CQE recovery +[ 423.137802] blk_update_request: I/O error, dev mmcblk2gp3, sector 0 op 0x0:(READ) flags 0x80700 phys_seg 4 prio class 0 +[ 423.237125] mmc2: running CQE recovery +[ 423.318206] mmc2: running CQE recovery +[ 423.397680] mmc2: running CQE recovery +[ 423.397837] blk_update_request: I/O error, dev mmcblk2gp3, sector 0 op 0x0:(READ) flags 0x0 phys_seg 1 prio class 0 +[ 423.408287] Buffer I/O error on dev mmcblk2gp3, logical block 0, async page read + +the part_type values of interest here are defined as follow: +main 0 +boot0 1 +boot1 2 +rpmb 3 +gp0 4 +gp1 5 +gp2 6 +gp3 7 + +so mask with EXT_CSD_PART_CONFIG_ACC_MASK (7) to correctly identify rpmb + +Fixes: e7794c14fd73 ("mmc: rpmb: fixes pause retune on all RPMB partitions.") +Cc: stable@vger.kernel.org +Cc: Jorge Ramirez-Ortiz +Signed-off-by: Dominique Martinet +Reviewed-by: Linus Walleij +Link: https://lore.kernel.org/r/20240306-mmc-partswitch-v1-1-bf116985d950@codewreck.org +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/core/block.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c +index 554dba0a06f5b..32369b120f02c 100644 +--- a/drivers/mmc/core/block.c ++++ b/drivers/mmc/core/block.c +@@ -873,10 +873,11 @@ static const struct block_device_operations mmc_bdops = { + static int mmc_blk_part_switch_pre(struct mmc_card *card, + unsigned int part_type) + { +- const unsigned int mask = EXT_CSD_PART_CONFIG_ACC_RPMB; ++ const unsigned int mask = EXT_CSD_PART_CONFIG_ACC_MASK; ++ const unsigned int rpmb = EXT_CSD_PART_CONFIG_ACC_RPMB; + int ret = 0; + +- if ((part_type & mask) == mask) { ++ if ((part_type & mask) == rpmb) { + if (card->ext_csd.cmdq_en) { + ret = mmc_cmdq_disable(card); + if (ret) +@@ -891,10 +892,11 @@ static int mmc_blk_part_switch_pre(struct mmc_card *card, + static int mmc_blk_part_switch_post(struct mmc_card *card, + unsigned int part_type) + { +- const unsigned int mask = EXT_CSD_PART_CONFIG_ACC_RPMB; ++ const unsigned int mask = EXT_CSD_PART_CONFIG_ACC_MASK; ++ const unsigned int rpmb = EXT_CSD_PART_CONFIG_ACC_RPMB; + int ret = 0; + +- if ((part_type & mask) == mask) { ++ if ((part_type & mask) == rpmb) { + mmc_retune_unpause(card->host); + if (card->reenable_cmdq && !card->ext_csd.cmdq_en) + ret = mmc_cmdq_enable(card); +-- +2.43.0 + diff --git a/queue-5.4/mmc-tmio-avoid-concurrent-runs-of-mmc_request_done.patch b/queue-5.4/mmc-tmio-avoid-concurrent-runs-of-mmc_request_done.patch new file mode 100644 index 00000000000..7969c1c538b --- /dev/null +++ b/queue-5.4/mmc-tmio-avoid-concurrent-runs-of-mmc_request_done.patch @@ -0,0 +1,51 @@ +From 75485efdd73b2ada183e77dc3d428b3315fd0fe0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Mar 2024 11:42:56 +0100 +Subject: mmc: tmio: avoid concurrent runs of mmc_request_done() + +From: Wolfram Sang + +[ Upstream commit e8d1b41e69d72c62865bebe8f441163ec00b3d44 ] + +With the to-be-fixed commit, the reset_work handler cleared 'host->mrq' +outside of the spinlock protected critical section. That leaves a small +race window during execution of 'tmio_mmc_reset()' where the done_work +handler could grab a pointer to the now invalid 'host->mrq'. Both would +use it to call mmc_request_done() causing problems (see link below). + +However, 'host->mrq' cannot simply be cleared earlier inside the +critical section. That would allow new mrqs to come in asynchronously +while the actual reset of the controller still needs to be done. So, +like 'tmio_mmc_set_ios()', an ERR_PTR is used to prevent new mrqs from +coming in but still avoiding concurrency between work handlers. + +Reported-by: Dirk Behme +Closes: https://lore.kernel.org/all/20240220061356.3001761-1-dirk.behme@de.bosch.com/ +Fixes: df3ef2d3c92c ("mmc: protect the tmio_mmc driver against a theoretical race") +Signed-off-by: Wolfram Sang +Tested-by: Dirk Behme +Reviewed-by: Dirk Behme +Cc: stable@vger.kernel.org # 3.0+ +Link: https://lore.kernel.org/r/20240305104423.3177-2-wsa+renesas@sang-engineering.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/tmio_mmc_core.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c +index 25083f010a7ad..e21907b92cf11 100644 +--- a/drivers/mmc/host/tmio_mmc_core.c ++++ b/drivers/mmc/host/tmio_mmc_core.c +@@ -217,6 +217,8 @@ static void tmio_mmc_reset_work(struct work_struct *work) + else + mrq->cmd->error = -ETIMEDOUT; + ++ /* No new calls yet, but disallow concurrent tmio_mmc_done_work() */ ++ host->mrq = ERR_PTR(-EBUSY); + host->cmd = NULL; + host->data = NULL; + +-- +2.43.0 + diff --git a/queue-5.4/mtd-rawnand-meson-fix-scrambling-mode-value-in-comma.patch b/queue-5.4/mtd-rawnand-meson-fix-scrambling-mode-value-in-comma.patch new file mode 100644 index 00000000000..09cd38b55fd --- /dev/null +++ b/queue-5.4/mtd-rawnand-meson-fix-scrambling-mode-value-in-comma.patch @@ -0,0 +1,39 @@ +From 067a8169209a2ca5e037b19eafdfc5fe195da7af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 11 Feb 2024 00:45:51 +0300 +Subject: mtd: rawnand: meson: fix scrambling mode value in command macro + +From: Arseniy Krasnov + +[ Upstream commit ef6f463599e16924cdd02ce5056ab52879dc008c ] + +Scrambling mode is enabled by value (1 << 19). NFC_CMD_SCRAMBLER_ENABLE +is already (1 << 19), so there is no need to shift it again in CMDRWGEN +macro. + +Signed-off-by: Arseniy Krasnov +Cc: +Fixes: 8fae856c5350 ("mtd: rawnand: meson: add support for Amlogic NAND flash controller") +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20240210214551.441610-1-avkrasnov@salutedevices.com +Signed-off-by: Sasha Levin +--- + drivers/mtd/nand/raw/meson_nand.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c +index 29f3d39138e84..794c85cf22fa9 100644 +--- a/drivers/mtd/nand/raw/meson_nand.c ++++ b/drivers/mtd/nand/raw/meson_nand.c +@@ -59,7 +59,7 @@ + #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages) \ + ( \ + (cmd_dir) | \ +- ((ran) << 19) | \ ++ (ran) | \ + ((bch) << 14) | \ + ((short_mode) << 13) | \ + (((page_size) & 0x7f) << 6) | \ +-- +2.43.0 + diff --git a/queue-5.4/nilfs2-fix-failure-to-detect-dat-corruption-in-btree.patch b/queue-5.4/nilfs2-fix-failure-to-detect-dat-corruption-in-btree.patch new file mode 100644 index 00000000000..a9ceaef54ef --- /dev/null +++ b/queue-5.4/nilfs2-fix-failure-to-detect-dat-corruption-in-btree.patch @@ -0,0 +1,131 @@ +From 7d462f1ebda9c4988ce2f4f610ca51de714d29ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Mar 2024 19:58:26 +0900 +Subject: nilfs2: fix failure to detect DAT corruption in btree and direct + mappings + +From: Ryusuke Konishi + +[ Upstream commit f2f26b4a84a0ef41791bd2d70861c8eac748f4ba ] + +Patch series "nilfs2: fix kernel bug at submit_bh_wbc()". + +This resolves a kernel BUG reported by syzbot. Since there are two +flaws involved, I've made each one a separate patch. + +The first patch alone resolves the syzbot-reported bug, but I think +both fixes should be sent to stable, so I've tagged them as such. + +This patch (of 2): + +Syzbot has reported a kernel bug in submit_bh_wbc() when writing file data +to a nilfs2 file system whose metadata is corrupted. + +There are two flaws involved in this issue. + +The first flaw is that when nilfs_get_block() locates a data block using +btree or direct mapping, if the disk address translation routine +nilfs_dat_translate() fails with internal code -ENOENT due to DAT metadata +corruption, it can be passed back to nilfs_get_block(). This causes +nilfs_get_block() to misidentify an existing block as non-existent, +causing both data block lookup and insertion to fail inconsistently. + +The second flaw is that nilfs_get_block() returns a successful status in +this inconsistent state. This causes the caller __block_write_begin_int() +or others to request a read even though the buffer is not mapped, +resulting in a BUG_ON check for the BH_Mapped flag in submit_bh_wbc() +failing. + +This fixes the first issue by changing the return value to code -EINVAL +when a conversion using DAT fails with code -ENOENT, avoiding the +conflicting condition that leads to the kernel bug described above. Here, +code -EINVAL indicates that metadata corruption was detected during the +block lookup, which will be properly handled as a file system error and +converted to -EIO when passing through the nilfs2 bmap layer. + +Link: https://lkml.kernel.org/r/20240313105827.5296-1-konishi.ryusuke@gmail.com +Link: https://lkml.kernel.org/r/20240313105827.5296-2-konishi.ryusuke@gmail.com +Fixes: c3a7abf06ce7 ("nilfs2: support contiguous lookup of blocks") +Signed-off-by: Ryusuke Konishi +Reported-by: syzbot+cfed5b56649bddf80d6e@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=cfed5b56649bddf80d6e +Tested-by: Ryusuke Konishi +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + fs/nilfs2/btree.c | 9 +++++++-- + fs/nilfs2/direct.c | 9 +++++++-- + 2 files changed, 14 insertions(+), 4 deletions(-) + +diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c +index a0e37530dcf30..1ab5db17e8248 100644 +--- a/fs/nilfs2/btree.c ++++ b/fs/nilfs2/btree.c +@@ -724,7 +724,7 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *btree, + dat = nilfs_bmap_get_dat(btree); + ret = nilfs_dat_translate(dat, ptr, &blocknr); + if (ret < 0) +- goto out; ++ goto dat_error; + ptr = blocknr; + } + cnt = 1; +@@ -743,7 +743,7 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *btree, + if (dat) { + ret = nilfs_dat_translate(dat, ptr2, &blocknr); + if (ret < 0) +- goto out; ++ goto dat_error; + ptr2 = blocknr; + } + if (ptr2 != ptr + cnt || ++cnt == maxblocks) +@@ -782,6 +782,11 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *btree, + out: + nilfs_btree_free_path(path); + return ret; ++ ++ dat_error: ++ if (ret == -ENOENT) ++ ret = -EINVAL; /* Notify bmap layer of metadata corruption */ ++ goto out; + } + + static void nilfs_btree_promote_key(struct nilfs_bmap *btree, +diff --git a/fs/nilfs2/direct.c b/fs/nilfs2/direct.c +index 533e24ea3a88d..8d769c5dd5dc6 100644 +--- a/fs/nilfs2/direct.c ++++ b/fs/nilfs2/direct.c +@@ -66,7 +66,7 @@ static int nilfs_direct_lookup_contig(const struct nilfs_bmap *direct, + dat = nilfs_bmap_get_dat(direct); + ret = nilfs_dat_translate(dat, ptr, &blocknr); + if (ret < 0) +- return ret; ++ goto dat_error; + ptr = blocknr; + } + +@@ -79,7 +79,7 @@ static int nilfs_direct_lookup_contig(const struct nilfs_bmap *direct, + if (dat) { + ret = nilfs_dat_translate(dat, ptr2, &blocknr); + if (ret < 0) +- return ret; ++ goto dat_error; + ptr2 = blocknr; + } + if (ptr2 != ptr + cnt) +@@ -87,6 +87,11 @@ static int nilfs_direct_lookup_contig(const struct nilfs_bmap *direct, + } + *ptrp = ptr; + return cnt; ++ ++ dat_error: ++ if (ret == -ENOENT) ++ ret = -EINVAL; /* Notify bmap layer of metadata corruption */ ++ return ret; + } + + static __u64 +-- +2.43.0 + diff --git a/queue-5.4/nilfs2-prevent-kernel-bug-at-submit_bh_wbc.patch b/queue-5.4/nilfs2-prevent-kernel-bug-at-submit_bh_wbc.patch new file mode 100644 index 00000000000..52b0e28360c --- /dev/null +++ b/queue-5.4/nilfs2-prevent-kernel-bug-at-submit_bh_wbc.patch @@ -0,0 +1,44 @@ +From 1f3b327beb694b246665b1ff2f2c62038ae04843 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Mar 2024 19:58:27 +0900 +Subject: nilfs2: prevent kernel bug at submit_bh_wbc() + +From: Ryusuke Konishi + +[ Upstream commit 269cdf353b5bdd15f1a079671b0f889113865f20 ] + +Fix a bug where nilfs_get_block() returns a successful status when +searching and inserting the specified block both fail inconsistently. If +this inconsistent behavior is not due to a previously fixed bug, then an +unexpected race is occurring, so return a temporary error -EAGAIN instead. + +This prevents callers such as __block_write_begin_int() from requesting a +read into a buffer that is not mapped, which would cause the BUG_ON check +for the BH_Mapped flag in submit_bh_wbc() to fail. + +Link: https://lkml.kernel.org/r/20240313105827.5296-3-konishi.ryusuke@gmail.com +Fixes: 1f5abe7e7dbc ("nilfs2: replace BUG_ON and BUG calls triggerable from ioctl") +Signed-off-by: Ryusuke Konishi +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + fs/nilfs2/inode.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c +index 83dbfd9d25323..530edb813add8 100644 +--- a/fs/nilfs2/inode.c ++++ b/fs/nilfs2/inode.c +@@ -111,7 +111,7 @@ int nilfs_get_block(struct inode *inode, sector_t blkoff, + "%s (ino=%lu): a race condition while inserting a data block at offset=%llu", + __func__, inode->i_ino, + (unsigned long long)blkoff); +- err = 0; ++ err = -EAGAIN; + } + nilfs_transaction_abort(inode->i_sb); + goto out; +-- +2.43.0 + diff --git a/queue-5.4/nilfs2-use-a-more-common-logging-style.patch b/queue-5.4/nilfs2-use-a-more-common-logging-style.patch new file mode 100644 index 00000000000..11655690af9 --- /dev/null +++ b/queue-5.4/nilfs2-use-a-more-common-logging-style.patch @@ -0,0 +1,1376 @@ +From 52a357f45d469d6c516573386d4b44ad1b857c3a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Aug 2020 18:35:49 -0700 +Subject: nilfs2: use a more common logging style + +From: Joe Perches + +[ Upstream commit a1d0747a393a079631130d61faa2a61027d1c789 ] + +Add macros for nilfs_(sb, fmt, ...) and convert the uses of +'nilfs_msg(sb, KERN_, ...)' to 'nilfs_(sb, ...)' so nilfs2 +uses a logging style more like the typical kernel logging style. + +Miscellanea: + +o Realign arguments for these uses + +Signed-off-by: Joe Perches +Signed-off-by: Ryusuke Konishi +Signed-off-by: Andrew Morton +Link: http://lkml.kernel.org/r/1595860111-3920-4-git-send-email-konishi.ryusuke@gmail.com +Signed-off-by: Linus Torvalds +Stable-dep-of: 269cdf353b5b ("nilfs2: prevent kernel bug at submit_bh_wbc()") +Signed-off-by: Sasha Levin +--- + fs/nilfs2/alloc.c | 38 +++++++++---------- + fs/nilfs2/btree.c | 42 ++++++++++----------- + fs/nilfs2/cpfile.c | 10 ++--- + fs/nilfs2/dat.c | 14 +++---- + fs/nilfs2/direct.c | 14 ++++--- + fs/nilfs2/gcinode.c | 2 +- + fs/nilfs2/ifile.c | 4 +- + fs/nilfs2/inode.c | 29 +++++++-------- + fs/nilfs2/ioctl.c | 37 +++++++++---------- + fs/nilfs2/mdt.c | 2 +- + fs/nilfs2/namei.c | 6 +-- + fs/nilfs2/nilfs.h | 9 +++++ + fs/nilfs2/page.c | 11 +++--- + fs/nilfs2/recovery.c | 32 +++++++--------- + fs/nilfs2/segbuf.c | 2 +- + fs/nilfs2/segment.c | 38 +++++++++---------- + fs/nilfs2/sufile.c | 29 +++++++-------- + fs/nilfs2/super.c | 57 ++++++++++++++--------------- + fs/nilfs2/sysfs.c | 29 +++++++-------- + fs/nilfs2/the_nilfs.c | 85 ++++++++++++++++++++----------------------- + 20 files changed, 239 insertions(+), 251 deletions(-) + +diff --git a/fs/nilfs2/alloc.c b/fs/nilfs2/alloc.c +index bbd82f650e93e..279d945d4ebee 100644 +--- a/fs/nilfs2/alloc.c ++++ b/fs/nilfs2/alloc.c +@@ -614,10 +614,10 @@ void nilfs_palloc_commit_free_entry(struct inode *inode, + lock = nilfs_mdt_bgl_lock(inode, group); + + if (!nilfs_clear_bit_atomic(lock, group_offset, bitmap)) +- nilfs_msg(inode->i_sb, KERN_WARNING, +- "%s (ino=%lu): entry number %llu already freed", +- __func__, inode->i_ino, +- (unsigned long long)req->pr_entry_nr); ++ nilfs_warn(inode->i_sb, ++ "%s (ino=%lu): entry number %llu already freed", ++ __func__, inode->i_ino, ++ (unsigned long long)req->pr_entry_nr); + else + nilfs_palloc_group_desc_add_entries(desc, lock, 1); + +@@ -655,10 +655,10 @@ void nilfs_palloc_abort_alloc_entry(struct inode *inode, + lock = nilfs_mdt_bgl_lock(inode, group); + + if (!nilfs_clear_bit_atomic(lock, group_offset, bitmap)) +- nilfs_msg(inode->i_sb, KERN_WARNING, +- "%s (ino=%lu): entry number %llu already freed", +- __func__, inode->i_ino, +- (unsigned long long)req->pr_entry_nr); ++ nilfs_warn(inode->i_sb, ++ "%s (ino=%lu): entry number %llu already freed", ++ __func__, inode->i_ino, ++ (unsigned long long)req->pr_entry_nr); + else + nilfs_palloc_group_desc_add_entries(desc, lock, 1); + +@@ -764,10 +764,10 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems) + do { + if (!nilfs_clear_bit_atomic(lock, group_offset, + bitmap)) { +- nilfs_msg(inode->i_sb, KERN_WARNING, +- "%s (ino=%lu): entry number %llu already freed", +- __func__, inode->i_ino, +- (unsigned long long)entry_nrs[j]); ++ nilfs_warn(inode->i_sb, ++ "%s (ino=%lu): entry number %llu already freed", ++ __func__, inode->i_ino, ++ (unsigned long long)entry_nrs[j]); + } else { + n++; + } +@@ -809,10 +809,10 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems) + ret = nilfs_palloc_delete_entry_block(inode, + last_nrs[k]); + if (ret && ret != -ENOENT) +- nilfs_msg(inode->i_sb, KERN_WARNING, +- "error %d deleting block that object (entry=%llu, ino=%lu) belongs to", +- ret, (unsigned long long)last_nrs[k], +- inode->i_ino); ++ nilfs_warn(inode->i_sb, ++ "error %d deleting block that object (entry=%llu, ino=%lu) belongs to", ++ ret, (unsigned long long)last_nrs[k], ++ inode->i_ino); + } + + desc_kaddr = kmap_atomic(desc_bh->b_page); +@@ -827,9 +827,9 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems) + if (nfree == nilfs_palloc_entries_per_group(inode)) { + ret = nilfs_palloc_delete_bitmap_block(inode, group); + if (ret && ret != -ENOENT) +- nilfs_msg(inode->i_sb, KERN_WARNING, +- "error %d deleting bitmap block of group=%lu, ino=%lu", +- ret, group, inode->i_ino); ++ nilfs_warn(inode->i_sb, ++ "error %d deleting bitmap block of group=%lu, ino=%lu", ++ ret, group, inode->i_ino); + } + } + return 0; +diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c +index 1ab5db17e8248..4905b7cd7bf33 100644 +--- a/fs/nilfs2/btree.c ++++ b/fs/nilfs2/btree.c +@@ -352,10 +352,10 @@ static int nilfs_btree_node_broken(const struct nilfs_btree_node *node, + (flags & NILFS_BTREE_NODE_ROOT) || + nchildren < 0 || + nchildren > NILFS_BTREE_NODE_NCHILDREN_MAX(size))) { +- nilfs_msg(inode->i_sb, KERN_CRIT, +- "bad btree node (ino=%lu, blocknr=%llu): level = %d, flags = 0x%x, nchildren = %d", +- inode->i_ino, (unsigned long long)blocknr, level, +- flags, nchildren); ++ nilfs_crit(inode->i_sb, ++ "bad btree node (ino=%lu, blocknr=%llu): level = %d, flags = 0x%x, nchildren = %d", ++ inode->i_ino, (unsigned long long)blocknr, level, ++ flags, nchildren); + ret = 1; + } + return ret; +@@ -382,9 +382,9 @@ static int nilfs_btree_root_broken(const struct nilfs_btree_node *node, + level >= NILFS_BTREE_LEVEL_MAX || + nchildren < 0 || + nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX)) { +- nilfs_msg(inode->i_sb, KERN_CRIT, +- "bad btree root (ino=%lu): level = %d, flags = 0x%x, nchildren = %d", +- inode->i_ino, level, flags, nchildren); ++ nilfs_crit(inode->i_sb, ++ "bad btree root (ino=%lu): level = %d, flags = 0x%x, nchildren = %d", ++ inode->i_ino, level, flags, nchildren); + ret = 1; + } + return ret; +@@ -451,10 +451,10 @@ static int nilfs_btree_bad_node(const struct nilfs_bmap *btree, + { + if (unlikely(nilfs_btree_node_get_level(node) != level)) { + dump_stack(); +- nilfs_msg(btree->b_inode->i_sb, KERN_CRIT, +- "btree level mismatch (ino=%lu): %d != %d", +- btree->b_inode->i_ino, +- nilfs_btree_node_get_level(node), level); ++ nilfs_crit(btree->b_inode->i_sb, ++ "btree level mismatch (ino=%lu): %d != %d", ++ btree->b_inode->i_ino, ++ nilfs_btree_node_get_level(node), level); + return 1; + } + return 0; +@@ -519,7 +519,7 @@ static int __nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr, + + out_no_wait: + if (!buffer_uptodate(bh)) { +- nilfs_msg(btree->b_inode->i_sb, KERN_ERR, ++ nilfs_err(btree->b_inode->i_sb, + "I/O error reading b-tree node block (ino=%lu, blocknr=%llu)", + btree->b_inode->i_ino, (unsigned long long)ptr); + brelse(bh); +@@ -2094,10 +2094,10 @@ static int nilfs_btree_propagate(struct nilfs_bmap *btree, + ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1, 0); + if (ret < 0) { + if (unlikely(ret == -ENOENT)) +- nilfs_msg(btree->b_inode->i_sb, KERN_CRIT, +- "writing node/leaf block does not appear in b-tree (ino=%lu) at key=%llu, level=%d", +- btree->b_inode->i_ino, +- (unsigned long long)key, level); ++ nilfs_crit(btree->b_inode->i_sb, ++ "writing node/leaf block does not appear in b-tree (ino=%lu) at key=%llu, level=%d", ++ btree->b_inode->i_ino, ++ (unsigned long long)key, level); + goto out; + } + +@@ -2134,11 +2134,11 @@ static void nilfs_btree_add_dirty_buffer(struct nilfs_bmap *btree, + if (level < NILFS_BTREE_LEVEL_NODE_MIN || + level >= NILFS_BTREE_LEVEL_MAX) { + dump_stack(); +- nilfs_msg(btree->b_inode->i_sb, KERN_WARNING, +- "invalid btree level: %d (key=%llu, ino=%lu, blocknr=%llu)", +- level, (unsigned long long)key, +- btree->b_inode->i_ino, +- (unsigned long long)bh->b_blocknr); ++ nilfs_warn(btree->b_inode->i_sb, ++ "invalid btree level: %d (key=%llu, ino=%lu, blocknr=%llu)", ++ level, (unsigned long long)key, ++ btree->b_inode->i_ino, ++ (unsigned long long)bh->b_blocknr); + return; + } + +diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c +index 8d41311b5db4b..86d4d850d1305 100644 +--- a/fs/nilfs2/cpfile.c ++++ b/fs/nilfs2/cpfile.c +@@ -322,7 +322,7 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, + int ret, ncps, nicps, nss, count, i; + + if (unlikely(start == 0 || start > end)) { +- nilfs_msg(cpfile->i_sb, KERN_ERR, ++ nilfs_err(cpfile->i_sb, + "cannot delete checkpoints: invalid range [%llu, %llu)", + (unsigned long long)start, (unsigned long long)end); + return -EINVAL; +@@ -376,7 +376,7 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, + cpfile, cno); + if (ret == 0) + continue; +- nilfs_msg(cpfile->i_sb, KERN_ERR, ++ nilfs_err(cpfile->i_sb, + "error %d deleting checkpoint block", + ret); + break; +@@ -981,12 +981,10 @@ int nilfs_cpfile_read(struct super_block *sb, size_t cpsize, + int err; + + if (cpsize > sb->s_blocksize) { +- nilfs_msg(sb, KERN_ERR, +- "too large checkpoint size: %zu bytes", cpsize); ++ nilfs_err(sb, "too large checkpoint size: %zu bytes", cpsize); + return -EINVAL; + } else if (cpsize < NILFS_MIN_CHECKPOINT_SIZE) { +- nilfs_msg(sb, KERN_ERR, +- "too small checkpoint size: %zu bytes", cpsize); ++ nilfs_err(sb, "too small checkpoint size: %zu bytes", cpsize); + return -EINVAL; + } + +diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c +index b9c759addd50e..c47e1f6f23a82 100644 +--- a/fs/nilfs2/dat.c ++++ b/fs/nilfs2/dat.c +@@ -354,11 +354,11 @@ int nilfs_dat_move(struct inode *dat, __u64 vblocknr, sector_t blocknr) + kaddr = kmap_atomic(entry_bh->b_page); + entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr); + if (unlikely(entry->de_blocknr == cpu_to_le64(0))) { +- nilfs_msg(dat->i_sb, KERN_CRIT, +- "%s: invalid vblocknr = %llu, [%llu, %llu)", +- __func__, (unsigned long long)vblocknr, +- (unsigned long long)le64_to_cpu(entry->de_start), +- (unsigned long long)le64_to_cpu(entry->de_end)); ++ nilfs_crit(dat->i_sb, ++ "%s: invalid vblocknr = %llu, [%llu, %llu)", ++ __func__, (unsigned long long)vblocknr, ++ (unsigned long long)le64_to_cpu(entry->de_start), ++ (unsigned long long)le64_to_cpu(entry->de_end)); + kunmap_atomic(kaddr); + brelse(entry_bh); + return -EINVAL; +@@ -485,11 +485,11 @@ int nilfs_dat_read(struct super_block *sb, size_t entry_size, + int err; + + if (entry_size > sb->s_blocksize) { +- nilfs_msg(sb, KERN_ERR, "too large DAT entry size: %zu bytes", ++ nilfs_err(sb, "too large DAT entry size: %zu bytes", + entry_size); + return -EINVAL; + } else if (entry_size < NILFS_MIN_DAT_ENTRY_SIZE) { +- nilfs_msg(sb, KERN_ERR, "too small DAT entry size: %zu bytes", ++ nilfs_err(sb, "too small DAT entry size: %zu bytes", + entry_size); + return -EINVAL; + } +diff --git a/fs/nilfs2/direct.c b/fs/nilfs2/direct.c +index 8d769c5dd5dc6..7faf8c285d6c9 100644 +--- a/fs/nilfs2/direct.c ++++ b/fs/nilfs2/direct.c +@@ -333,16 +333,18 @@ static int nilfs_direct_assign(struct nilfs_bmap *bmap, + + key = nilfs_bmap_data_get_key(bmap, *bh); + if (unlikely(key > NILFS_DIRECT_KEY_MAX)) { +- nilfs_msg(bmap->b_inode->i_sb, KERN_CRIT, +- "%s (ino=%lu): invalid key: %llu", __func__, +- bmap->b_inode->i_ino, (unsigned long long)key); ++ nilfs_crit(bmap->b_inode->i_sb, ++ "%s (ino=%lu): invalid key: %llu", ++ __func__, ++ bmap->b_inode->i_ino, (unsigned long long)key); + return -EINVAL; + } + ptr = nilfs_direct_get_ptr(bmap, key); + if (unlikely(ptr == NILFS_BMAP_INVALID_PTR)) { +- nilfs_msg(bmap->b_inode->i_sb, KERN_CRIT, +- "%s (ino=%lu): invalid pointer: %llu", __func__, +- bmap->b_inode->i_ino, (unsigned long long)ptr); ++ nilfs_crit(bmap->b_inode->i_sb, ++ "%s (ino=%lu): invalid pointer: %llu", ++ __func__, ++ bmap->b_inode->i_ino, (unsigned long long)ptr); + return -EINVAL; + } + +diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c +index cef46650102e7..b0077f5f71124 100644 +--- a/fs/nilfs2/gcinode.c ++++ b/fs/nilfs2/gcinode.c +@@ -143,7 +143,7 @@ int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *bh) + if (!buffer_uptodate(bh)) { + struct inode *inode = bh->b_page->mapping->host; + +- nilfs_msg(inode->i_sb, KERN_ERR, ++ nilfs_err(inode->i_sb, + "I/O error reading %s block for GC (ino=%lu, vblocknr=%llu)", + buffer_nilfs_node(bh) ? "node" : "data", + inode->i_ino, (unsigned long long)bh->b_blocknr); +diff --git a/fs/nilfs2/ifile.c b/fs/nilfs2/ifile.c +index 4140d232cadc0..02727ed3a7c6a 100644 +--- a/fs/nilfs2/ifile.c ++++ b/fs/nilfs2/ifile.c +@@ -142,8 +142,8 @@ int nilfs_ifile_get_inode_block(struct inode *ifile, ino_t ino, + + err = nilfs_palloc_get_entry_block(ifile, ino, 0, out_bh); + if (unlikely(err)) +- nilfs_msg(sb, KERN_WARNING, "error %d reading inode: ino=%lu", +- err, (unsigned long)ino); ++ nilfs_warn(sb, "error %d reading inode: ino=%lu", ++ err, (unsigned long)ino); + return err; + } + +diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c +index ea94dc21af0c9..83dbfd9d25323 100644 +--- a/fs/nilfs2/inode.c ++++ b/fs/nilfs2/inode.c +@@ -107,10 +107,10 @@ int nilfs_get_block(struct inode *inode, sector_t blkoff, + * However, the page having this block must + * be locked in this case. + */ +- nilfs_msg(inode->i_sb, KERN_WARNING, +- "%s (ino=%lu): a race condition while inserting a data block at offset=%llu", +- __func__, inode->i_ino, +- (unsigned long long)blkoff); ++ nilfs_warn(inode->i_sb, ++ "%s (ino=%lu): a race condition while inserting a data block at offset=%llu", ++ __func__, inode->i_ino, ++ (unsigned long long)blkoff); + err = 0; + } + nilfs_transaction_abort(inode->i_sb); +@@ -862,9 +862,8 @@ static void nilfs_truncate_bmap(struct nilfs_inode_info *ii, + goto repeat; + + failed: +- nilfs_msg(ii->vfs_inode.i_sb, KERN_WARNING, +- "error %d truncating bmap (ino=%lu)", ret, +- ii->vfs_inode.i_ino); ++ nilfs_warn(ii->vfs_inode.i_sb, "error %d truncating bmap (ino=%lu)", ++ ret, ii->vfs_inode.i_ino); + } + + void nilfs_truncate(struct inode *inode) +@@ -1097,9 +1096,9 @@ int nilfs_set_file_dirty(struct inode *inode, unsigned int nr_dirty) + * This will happen when somebody is freeing + * this inode. + */ +- nilfs_msg(inode->i_sb, KERN_WARNING, +- "cannot set file dirty (ino=%lu): the file is being freed", +- inode->i_ino); ++ nilfs_warn(inode->i_sb, ++ "cannot set file dirty (ino=%lu): the file is being freed", ++ inode->i_ino); + spin_unlock(&nilfs->ns_inode_lock); + return -EINVAL; /* + * NILFS_I_DIRTY may remain for +@@ -1128,9 +1127,9 @@ int __nilfs_mark_inode_dirty(struct inode *inode, int flags) + + err = nilfs_load_inode_block(inode, &ibh); + if (unlikely(err)) { +- nilfs_msg(inode->i_sb, KERN_WARNING, +- "cannot mark inode dirty (ino=%lu): error %d loading inode block", +- inode->i_ino, err); ++ nilfs_warn(inode->i_sb, ++ "cannot mark inode dirty (ino=%lu): error %d loading inode block", ++ inode->i_ino, err); + return err; + } + nilfs_update_inode(inode, ibh, flags); +@@ -1156,8 +1155,8 @@ void nilfs_dirty_inode(struct inode *inode, int flags) + struct nilfs_mdt_info *mdi = NILFS_MDT(inode); + + if (is_bad_inode(inode)) { +- nilfs_msg(inode->i_sb, KERN_WARNING, +- "tried to mark bad_inode dirty. ignored."); ++ nilfs_warn(inode->i_sb, ++ "tried to mark bad_inode dirty. ignored."); + dump_stack(); + return; + } +diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c +index 83926b9ab4b59..1a266a10d4cf3 100644 +--- a/fs/nilfs2/ioctl.c ++++ b/fs/nilfs2/ioctl.c +@@ -569,25 +569,25 @@ static int nilfs_ioctl_move_inode_block(struct inode *inode, + + if (unlikely(ret < 0)) { + if (ret == -ENOENT) +- nilfs_msg(inode->i_sb, KERN_CRIT, +- "%s: invalid virtual block address (%s): ino=%llu, cno=%llu, offset=%llu, blocknr=%llu, vblocknr=%llu", +- __func__, vdesc->vd_flags ? "node" : "data", +- (unsigned long long)vdesc->vd_ino, +- (unsigned long long)vdesc->vd_cno, +- (unsigned long long)vdesc->vd_offset, +- (unsigned long long)vdesc->vd_blocknr, +- (unsigned long long)vdesc->vd_vblocknr); ++ nilfs_crit(inode->i_sb, ++ "%s: invalid virtual block address (%s): ino=%llu, cno=%llu, offset=%llu, blocknr=%llu, vblocknr=%llu", ++ __func__, vdesc->vd_flags ? "node" : "data", ++ (unsigned long long)vdesc->vd_ino, ++ (unsigned long long)vdesc->vd_cno, ++ (unsigned long long)vdesc->vd_offset, ++ (unsigned long long)vdesc->vd_blocknr, ++ (unsigned long long)vdesc->vd_vblocknr); + return ret; + } + if (unlikely(!list_empty(&bh->b_assoc_buffers))) { +- nilfs_msg(inode->i_sb, KERN_CRIT, +- "%s: conflicting %s buffer: ino=%llu, cno=%llu, offset=%llu, blocknr=%llu, vblocknr=%llu", +- __func__, vdesc->vd_flags ? "node" : "data", +- (unsigned long long)vdesc->vd_ino, +- (unsigned long long)vdesc->vd_cno, +- (unsigned long long)vdesc->vd_offset, +- (unsigned long long)vdesc->vd_blocknr, +- (unsigned long long)vdesc->vd_vblocknr); ++ nilfs_crit(inode->i_sb, ++ "%s: conflicting %s buffer: ino=%llu, cno=%llu, offset=%llu, blocknr=%llu, vblocknr=%llu", ++ __func__, vdesc->vd_flags ? "node" : "data", ++ (unsigned long long)vdesc->vd_ino, ++ (unsigned long long)vdesc->vd_cno, ++ (unsigned long long)vdesc->vd_offset, ++ (unsigned long long)vdesc->vd_blocknr, ++ (unsigned long long)vdesc->vd_vblocknr); + brelse(bh); + return -EEXIST; + } +@@ -837,8 +837,7 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs, + return 0; + + failed: +- nilfs_msg(nilfs->ns_sb, KERN_ERR, "error %d preparing GC: %s", ret, +- msg); ++ nilfs_err(nilfs->ns_sb, "error %d preparing GC: %s", ret, msg); + return ret; + } + +@@ -947,7 +946,7 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, + + ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]); + if (ret < 0) { +- nilfs_msg(inode->i_sb, KERN_ERR, ++ nilfs_err(inode->i_sb, + "error %d preparing GC: cannot read source blocks", + ret); + } else { +diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c +index 7c9055d767d16..e80ef2c0a785c 100644 +--- a/fs/nilfs2/mdt.c ++++ b/fs/nilfs2/mdt.c +@@ -199,7 +199,7 @@ static int nilfs_mdt_read_block(struct inode *inode, unsigned long block, + out_no_wait: + err = -EIO; + if (!buffer_uptodate(first_bh)) { +- nilfs_msg(inode->i_sb, KERN_ERR, ++ nilfs_err(inode->i_sb, + "I/O error reading meta-data file (ino=%lu, block-offset=%lu)", + inode->i_ino, block); + goto failed_bh; +diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c +index 9fe6d4ab74f01..a6ec7961d4f5a 100644 +--- a/fs/nilfs2/namei.c ++++ b/fs/nilfs2/namei.c +@@ -272,9 +272,9 @@ static int nilfs_do_unlink(struct inode *dir, struct dentry *dentry) + goto out; + + if (!inode->i_nlink) { +- nilfs_msg(inode->i_sb, KERN_WARNING, +- "deleting nonexistent file (ino=%lu), %d", +- inode->i_ino, inode->i_nlink); ++ nilfs_warn(inode->i_sb, ++ "deleting nonexistent file (ino=%lu), %d", ++ inode->i_ino, inode->i_nlink); + set_nlink(inode, 1); + } + err = nilfs_delete_entry(de, page); +diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h +index dc772eaa13cf1..6b9383ba0049d 100644 +--- a/fs/nilfs2/nilfs.h ++++ b/fs/nilfs2/nilfs.h +@@ -319,6 +319,15 @@ void __nilfs_error(struct super_block *sb, const char *function, + + #endif /* CONFIG_PRINTK */ + ++#define nilfs_crit(sb, fmt, ...) \ ++ nilfs_msg(sb, KERN_CRIT, fmt, ##__VA_ARGS__) ++#define nilfs_err(sb, fmt, ...) \ ++ nilfs_msg(sb, KERN_ERR, fmt, ##__VA_ARGS__) ++#define nilfs_warn(sb, fmt, ...) \ ++ nilfs_msg(sb, KERN_WARNING, fmt, ##__VA_ARGS__) ++#define nilfs_info(sb, fmt, ...) \ ++ nilfs_msg(sb, KERN_INFO, fmt, ##__VA_ARGS__) ++ + extern struct nilfs_super_block * + nilfs_read_super_block(struct super_block *, u64, int, struct buffer_head **); + extern int nilfs_store_magic_and_option(struct super_block *, +diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c +index 108e4528fccd0..fc86cc7a26d72 100644 +--- a/fs/nilfs2/page.c ++++ b/fs/nilfs2/page.c +@@ -399,9 +399,8 @@ void nilfs_clear_dirty_page(struct page *page, bool silent) + BUG_ON(!PageLocked(page)); + + if (!silent) +- nilfs_msg(sb, KERN_WARNING, +- "discard dirty page: offset=%lld, ino=%lu", +- page_offset(page), inode->i_ino); ++ nilfs_warn(sb, "discard dirty page: offset=%lld, ino=%lu", ++ page_offset(page), inode->i_ino); + + ClearPageUptodate(page); + ClearPageMappedToDisk(page); +@@ -417,9 +416,9 @@ void nilfs_clear_dirty_page(struct page *page, bool silent) + do { + lock_buffer(bh); + if (!silent) +- nilfs_msg(sb, KERN_WARNING, +- "discard dirty block: blocknr=%llu, size=%zu", +- (u64)bh->b_blocknr, bh->b_size); ++ nilfs_warn(sb, ++ "discard dirty block: blocknr=%llu, size=%zu", ++ (u64)bh->b_blocknr, bh->b_size); + + set_mask_bits(&bh->b_state, clear_bits, 0); + unlock_buffer(bh); +diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c +index 18feb9c7c7066..0923231e9e605 100644 +--- a/fs/nilfs2/recovery.c ++++ b/fs/nilfs2/recovery.c +@@ -51,7 +51,7 @@ static int nilfs_warn_segment_error(struct super_block *sb, int err) + + switch (err) { + case NILFS_SEG_FAIL_IO: +- nilfs_msg(sb, KERN_ERR, "I/O error reading segment"); ++ nilfs_err(sb, "I/O error reading segment"); + return -EIO; + case NILFS_SEG_FAIL_MAGIC: + msg = "Magic number mismatch"; +@@ -72,10 +72,10 @@ static int nilfs_warn_segment_error(struct super_block *sb, int err) + msg = "No super root in the last segment"; + break; + default: +- nilfs_msg(sb, KERN_ERR, "unrecognized segment error %d", err); ++ nilfs_err(sb, "unrecognized segment error %d", err); + return -EINVAL; + } +- nilfs_msg(sb, KERN_WARNING, "invalid segment: %s", msg); ++ nilfs_warn(sb, "invalid segment: %s", msg); + return -EINVAL; + } + +@@ -544,10 +544,10 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, + put_page(page); + + failed_inode: +- nilfs_msg(sb, KERN_WARNING, +- "error %d recovering data block (ino=%lu, block-offset=%llu)", +- err, (unsigned long)rb->ino, +- (unsigned long long)rb->blkoff); ++ nilfs_warn(sb, ++ "error %d recovering data block (ino=%lu, block-offset=%llu)", ++ err, (unsigned long)rb->ino, ++ (unsigned long long)rb->blkoff); + if (!err2) + err2 = err; + next: +@@ -670,8 +670,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, + } + + if (nsalvaged_blocks) { +- nilfs_msg(sb, KERN_INFO, "salvaged %lu blocks", +- nsalvaged_blocks); ++ nilfs_info(sb, "salvaged %lu blocks", nsalvaged_blocks); + ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE; + } + out: +@@ -682,7 +681,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, + confused: + err = -EINVAL; + failed: +- nilfs_msg(sb, KERN_ERR, ++ nilfs_err(sb, + "error %d roll-forwarding partial segment at blocknr = %llu", + err, (unsigned long long)pseg_start); + goto out; +@@ -704,8 +703,8 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, + set_buffer_dirty(bh); + err = sync_dirty_buffer(bh); + if (unlikely(err)) +- nilfs_msg(nilfs->ns_sb, KERN_WARNING, +- "buffer sync write failed during post-cleaning of recovery."); ++ nilfs_warn(nilfs->ns_sb, ++ "buffer sync write failed during post-cleaning of recovery."); + brelse(bh); + } + +@@ -740,8 +739,7 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, + + err = nilfs_attach_checkpoint(sb, ri->ri_cno, true, &root); + if (unlikely(err)) { +- nilfs_msg(sb, KERN_ERR, +- "error %d loading the latest checkpoint", err); ++ nilfs_err(sb, "error %d loading the latest checkpoint", err); + return err; + } + +@@ -752,8 +750,7 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, + if (ri->ri_need_recovery == NILFS_RECOVERY_ROLLFORWARD_DONE) { + err = nilfs_prepare_segment_for_recovery(nilfs, sb, ri); + if (unlikely(err)) { +- nilfs_msg(sb, KERN_ERR, +- "error %d preparing segment for recovery", ++ nilfs_err(sb, "error %d preparing segment for recovery", + err); + goto failed; + } +@@ -767,8 +764,7 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, + nilfs_detach_log_writer(sb); + + if (unlikely(err)) { +- nilfs_msg(sb, KERN_ERR, +- "error %d writing segment for recovery", ++ nilfs_err(sb, "error %d writing segment for recovery", + err); + goto failed; + } +diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c +index e72466fc8ca93..9f435879a0487 100644 +--- a/fs/nilfs2/segbuf.c ++++ b/fs/nilfs2/segbuf.c +@@ -511,7 +511,7 @@ static int nilfs_segbuf_wait(struct nilfs_segment_buffer *segbuf) + } while (--segbuf->sb_nbio > 0); + + if (unlikely(atomic_read(&segbuf->sb_err) > 0)) { +- nilfs_msg(segbuf->sb_super, KERN_ERR, ++ nilfs_err(segbuf->sb_super, + "I/O error writing log (start-blocknr=%llu, block-count=%lu) in segment %llu", + (unsigned long long)segbuf->sb_pseg_start, + segbuf->sb_sum.nblocks, +diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c +index 7d1860d33723e..d4610f71d21b7 100644 +--- a/fs/nilfs2/segment.c ++++ b/fs/nilfs2/segment.c +@@ -158,7 +158,7 @@ static int nilfs_prepare_segment_lock(struct super_block *sb, + * it is saved and will be restored on + * nilfs_transaction_commit(). + */ +- nilfs_msg(sb, KERN_WARNING, "journal info from a different FS"); ++ nilfs_warn(sb, "journal info from a different FS"); + save = current->journal_info; + } + if (!ti) { +@@ -1983,9 +1983,9 @@ static int nilfs_segctor_collect_dirty_files(struct nilfs_sc_info *sci, + err = nilfs_ifile_get_inode_block( + ifile, ii->vfs_inode.i_ino, &ibh); + if (unlikely(err)) { +- nilfs_msg(sci->sc_super, KERN_WARNING, +- "log writer: error %d getting inode block (ino=%lu)", +- err, ii->vfs_inode.i_ino); ++ nilfs_warn(sci->sc_super, ++ "log writer: error %d getting inode block (ino=%lu)", ++ err, ii->vfs_inode.i_ino); + return err; + } + spin_lock(&nilfs->ns_inode_lock); +@@ -2495,7 +2495,7 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, + if (likely(!err)) + break; + +- nilfs_msg(sb, KERN_WARNING, "error %d cleaning segments", err); ++ nilfs_warn(sb, "error %d cleaning segments", err); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(sci->sc_interval); + } +@@ -2503,9 +2503,9 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, + int ret = nilfs_discard_segments(nilfs, sci->sc_freesegs, + sci->sc_nfreesegs); + if (ret) { +- nilfs_msg(sb, KERN_WARNING, +- "error %d on discard request, turning discards off for the device", +- ret); ++ nilfs_warn(sb, ++ "error %d on discard request, turning discards off for the device", ++ ret); + nilfs_clear_opt(nilfs, DISCARD); + } + } +@@ -2586,9 +2586,9 @@ static int nilfs_segctor_thread(void *arg) + /* start sync. */ + sci->sc_task = current; + wake_up(&sci->sc_wait_task); /* for nilfs_segctor_start_thread() */ +- nilfs_msg(sci->sc_super, KERN_INFO, +- "segctord starting. Construction interval = %lu seconds, CP frequency < %lu seconds", +- sci->sc_interval / HZ, sci->sc_mjcp_freq / HZ); ++ nilfs_info(sci->sc_super, ++ "segctord starting. Construction interval = %lu seconds, CP frequency < %lu seconds", ++ sci->sc_interval / HZ, sci->sc_mjcp_freq / HZ); + + spin_lock(&sci->sc_state_lock); + loop: +@@ -2661,8 +2661,8 @@ static int nilfs_segctor_start_thread(struct nilfs_sc_info *sci) + if (IS_ERR(t)) { + int err = PTR_ERR(t); + +- nilfs_msg(sci->sc_super, KERN_ERR, +- "error %d creating segctord thread", err); ++ nilfs_err(sci->sc_super, "error %d creating segctord thread", ++ err); + return err; + } + wait_event(sci->sc_wait_task, sci->sc_task != NULL); +@@ -2772,14 +2772,14 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) + nilfs_segctor_write_out(sci); + + if (!list_empty(&sci->sc_dirty_files)) { +- nilfs_msg(sci->sc_super, KERN_WARNING, +- "disposed unprocessed dirty file(s) when stopping log writer"); ++ nilfs_warn(sci->sc_super, ++ "disposed unprocessed dirty file(s) when stopping log writer"); + nilfs_dispose_list(nilfs, &sci->sc_dirty_files, 1); + } + + if (!list_empty(&sci->sc_iput_queue)) { +- nilfs_msg(sci->sc_super, KERN_WARNING, +- "disposed unprocessed inode(s) in iput queue when stopping log writer"); ++ nilfs_warn(sci->sc_super, ++ "disposed unprocessed inode(s) in iput queue when stopping log writer"); + nilfs_dispose_list(nilfs, &sci->sc_iput_queue, 1); + } + +@@ -2858,8 +2858,8 @@ void nilfs_detach_log_writer(struct super_block *sb) + spin_lock(&nilfs->ns_inode_lock); + if (!list_empty(&nilfs->ns_dirty_files)) { + list_splice_init(&nilfs->ns_dirty_files, &garbage_list); +- nilfs_msg(sb, KERN_WARNING, +- "disposed unprocessed dirty file(s) when detaching log writer"); ++ nilfs_warn(sb, ++ "disposed unprocessed dirty file(s) when detaching log writer"); + } + spin_unlock(&nilfs->ns_inode_lock); + up_write(&nilfs->ns_segctor_sem); +diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c +index 4626540008c13..379db0c54227f 100644 +--- a/fs/nilfs2/sufile.c ++++ b/fs/nilfs2/sufile.c +@@ -171,9 +171,9 @@ int nilfs_sufile_updatev(struct inode *sufile, __u64 *segnumv, size_t nsegs, + down_write(&NILFS_MDT(sufile)->mi_sem); + for (seg = segnumv; seg < segnumv + nsegs; seg++) { + if (unlikely(*seg >= nilfs_sufile_get_nsegments(sufile))) { +- nilfs_msg(sufile->i_sb, KERN_WARNING, +- "%s: invalid segment number: %llu", +- __func__, (unsigned long long)*seg); ++ nilfs_warn(sufile->i_sb, ++ "%s: invalid segment number: %llu", ++ __func__, (unsigned long long)*seg); + nerr++; + } + } +@@ -230,9 +230,8 @@ int nilfs_sufile_update(struct inode *sufile, __u64 segnum, int create, + int ret; + + if (unlikely(segnum >= nilfs_sufile_get_nsegments(sufile))) { +- nilfs_msg(sufile->i_sb, KERN_WARNING, +- "%s: invalid segment number: %llu", +- __func__, (unsigned long long)segnum); ++ nilfs_warn(sufile->i_sb, "%s: invalid segment number: %llu", ++ __func__, (unsigned long long)segnum); + return -EINVAL; + } + down_write(&NILFS_MDT(sufile)->mi_sem); +@@ -410,9 +409,8 @@ void nilfs_sufile_do_cancel_free(struct inode *sufile, __u64 segnum, + kaddr = kmap_atomic(su_bh->b_page); + su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr); + if (unlikely(!nilfs_segment_usage_clean(su))) { +- nilfs_msg(sufile->i_sb, KERN_WARNING, +- "%s: segment %llu must be clean", __func__, +- (unsigned long long)segnum); ++ nilfs_warn(sufile->i_sb, "%s: segment %llu must be clean", ++ __func__, (unsigned long long)segnum); + kunmap_atomic(kaddr); + return; + } +@@ -468,9 +466,8 @@ void nilfs_sufile_do_free(struct inode *sufile, __u64 segnum, + kaddr = kmap_atomic(su_bh->b_page); + su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr); + if (nilfs_segment_usage_clean(su)) { +- nilfs_msg(sufile->i_sb, KERN_WARNING, +- "%s: segment %llu is already clean", +- __func__, (unsigned long long)segnum); ++ nilfs_warn(sufile->i_sb, "%s: segment %llu is already clean", ++ __func__, (unsigned long long)segnum); + kunmap_atomic(kaddr); + return; + } +@@ -1213,12 +1210,12 @@ int nilfs_sufile_read(struct super_block *sb, size_t susize, + int err; + + if (susize > sb->s_blocksize) { +- nilfs_msg(sb, KERN_ERR, +- "too large segment usage size: %zu bytes", susize); ++ nilfs_err(sb, "too large segment usage size: %zu bytes", ++ susize); + return -EINVAL; + } else if (susize < NILFS_MIN_SEGMENT_USAGE_SIZE) { +- nilfs_msg(sb, KERN_ERR, +- "too small segment usage size: %zu bytes", susize); ++ nilfs_err(sb, "too small segment usage size: %zu bytes", ++ susize); + return -EINVAL; + } + +diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c +index 2263ebedf9d58..59e74e764cd27 100644 +--- a/fs/nilfs2/super.c ++++ b/fs/nilfs2/super.c +@@ -106,7 +106,7 @@ static void nilfs_set_error(struct super_block *sb) + * + * This implements the body of nilfs_error() macro. Normally, + * nilfs_error() should be used. As for sustainable errors such as a +- * single-shot I/O error, nilfs_msg() should be used instead. ++ * single-shot I/O error, nilfs_err() should be used instead. + * + * Callers should not add a trailing newline since this will do it. + */ +@@ -179,8 +179,7 @@ static int nilfs_sync_super(struct super_block *sb, int flag) + } + + if (unlikely(err)) { +- nilfs_msg(sb, KERN_ERR, "unable to write superblock: err=%d", +- err); ++ nilfs_err(sb, "unable to write superblock: err=%d", err); + if (err == -EIO && nilfs->ns_sbh[1]) { + /* + * sbp[0] points to newer log than sbp[1], +@@ -250,7 +249,7 @@ struct nilfs_super_block **nilfs_prepare_super(struct super_block *sb, + sbp[1]->s_magic == cpu_to_le16(NILFS_SUPER_MAGIC)) { + memcpy(sbp[0], sbp[1], nilfs->ns_sbsize); + } else { +- nilfs_msg(sb, KERN_CRIT, "superblock broke"); ++ nilfs_crit(sb, "superblock broke"); + return NULL; + } + } else if (sbp[1] && +@@ -360,9 +359,9 @@ static int nilfs_move_2nd_super(struct super_block *sb, loff_t sb2off) + offset = sb2off & (nilfs->ns_blocksize - 1); + nsbh = sb_getblk(sb, newblocknr); + if (!nsbh) { +- nilfs_msg(sb, KERN_WARNING, +- "unable to move secondary superblock to block %llu", +- (unsigned long long)newblocknr); ++ nilfs_warn(sb, ++ "unable to move secondary superblock to block %llu", ++ (unsigned long long)newblocknr); + ret = -EIO; + goto out; + } +@@ -556,7 +555,7 @@ int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt, + up_read(&nilfs->ns_segctor_sem); + if (unlikely(err)) { + if (err == -ENOENT || err == -EINVAL) { +- nilfs_msg(sb, KERN_ERR, ++ nilfs_err(sb, + "Invalid checkpoint (checkpoint number=%llu)", + (unsigned long long)cno); + err = -EINVAL; +@@ -654,8 +653,7 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) + err = nilfs_ifile_count_free_inodes(root->ifile, + &nmaxinodes, &nfreeinodes); + if (unlikely(err)) { +- nilfs_msg(sb, KERN_WARNING, +- "failed to count free inodes: err=%d", err); ++ nilfs_warn(sb, "failed to count free inodes: err=%d", err); + if (err == -ERANGE) { + /* + * If nilfs_palloc_count_max_entries() returns +@@ -787,7 +785,7 @@ static int parse_options(char *options, struct super_block *sb, int is_remount) + break; + case Opt_snapshot: + if (is_remount) { +- nilfs_msg(sb, KERN_ERR, ++ nilfs_err(sb, + "\"%s\" option is invalid for remount", + p); + return 0; +@@ -803,8 +801,7 @@ static int parse_options(char *options, struct super_block *sb, int is_remount) + nilfs_clear_opt(nilfs, DISCARD); + break; + default: +- nilfs_msg(sb, KERN_ERR, +- "unrecognized mount option \"%s\"", p); ++ nilfs_err(sb, "unrecognized mount option \"%s\"", p); + return 0; + } + } +@@ -840,10 +837,10 @@ static int nilfs_setup_super(struct super_block *sb, int is_mount) + mnt_count = le16_to_cpu(sbp[0]->s_mnt_count); + + if (nilfs->ns_mount_state & NILFS_ERROR_FS) { +- nilfs_msg(sb, KERN_WARNING, "mounting fs with errors"); ++ nilfs_warn(sb, "mounting fs with errors"); + #if 0 + } else if (max_mnt_count >= 0 && mnt_count >= max_mnt_count) { +- nilfs_msg(sb, KERN_WARNING, "maximal mount count reached"); ++ nilfs_warn(sb, "maximal mount count reached"); + #endif + } + if (!max_mnt_count) +@@ -906,7 +903,7 @@ int nilfs_check_feature_compatibility(struct super_block *sb, + features = le64_to_cpu(sbp->s_feature_incompat) & + ~NILFS_FEATURE_INCOMPAT_SUPP; + if (features) { +- nilfs_msg(sb, KERN_ERR, ++ nilfs_err(sb, + "couldn't mount because of unsupported optional features (%llx)", + (unsigned long long)features); + return -EINVAL; +@@ -914,7 +911,7 @@ int nilfs_check_feature_compatibility(struct super_block *sb, + features = le64_to_cpu(sbp->s_feature_compat_ro) & + ~NILFS_FEATURE_COMPAT_RO_SUPP; + if (!sb_rdonly(sb) && features) { +- nilfs_msg(sb, KERN_ERR, ++ nilfs_err(sb, + "couldn't mount RDWR because of unsupported optional features (%llx)", + (unsigned long long)features); + return -EINVAL; +@@ -933,12 +930,12 @@ static int nilfs_get_root_dentry(struct super_block *sb, + inode = nilfs_iget(sb, root, NILFS_ROOT_INO); + if (IS_ERR(inode)) { + ret = PTR_ERR(inode); +- nilfs_msg(sb, KERN_ERR, "error %d getting root inode", ret); ++ nilfs_err(sb, "error %d getting root inode", ret); + goto out; + } + if (!S_ISDIR(inode->i_mode) || !inode->i_blocks || !inode->i_size) { + iput(inode); +- nilfs_msg(sb, KERN_ERR, "corrupt root inode"); ++ nilfs_err(sb, "corrupt root inode"); + ret = -EINVAL; + goto out; + } +@@ -966,7 +963,7 @@ static int nilfs_get_root_dentry(struct super_block *sb, + return ret; + + failed_dentry: +- nilfs_msg(sb, KERN_ERR, "error %d getting root dentry", ret); ++ nilfs_err(sb, "error %d getting root dentry", ret); + goto out; + } + +@@ -986,7 +983,7 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, + ret = (ret == -ENOENT) ? -EINVAL : ret; + goto out; + } else if (!ret) { +- nilfs_msg(s, KERN_ERR, ++ nilfs_err(s, + "The specified checkpoint is not a snapshot (checkpoint number=%llu)", + (unsigned long long)cno); + ret = -EINVAL; +@@ -995,7 +992,7 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, + + ret = nilfs_attach_checkpoint(s, cno, false, &root); + if (ret) { +- nilfs_msg(s, KERN_ERR, ++ nilfs_err(s, + "error %d while loading snapshot (checkpoint number=%llu)", + ret, (unsigned long long)cno); + goto out; +@@ -1092,7 +1089,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) + cno = nilfs_last_cno(nilfs); + err = nilfs_attach_checkpoint(sb, cno, true, &fsroot); + if (err) { +- nilfs_msg(sb, KERN_ERR, ++ nilfs_err(sb, + "error %d while loading last checkpoint (checkpoint number=%llu)", + err, (unsigned long long)cno); + goto failed_unload; +@@ -1155,8 +1152,8 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) + err = -EINVAL; + + if (!nilfs_valid_fs(nilfs)) { +- nilfs_msg(sb, KERN_WARNING, +- "couldn't remount because the filesystem is in an incomplete recovery state"); ++ nilfs_warn(sb, ++ "couldn't remount because the filesystem is in an incomplete recovery state"); + goto restore_opts; + } + +@@ -1186,9 +1183,9 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) + ~NILFS_FEATURE_COMPAT_RO_SUPP; + up_read(&nilfs->ns_sem); + if (features) { +- nilfs_msg(sb, KERN_WARNING, +- "couldn't remount RDWR because of unsupported optional features (%llx)", +- (unsigned long long)features); ++ nilfs_warn(sb, ++ "couldn't remount RDWR because of unsupported optional features (%llx)", ++ (unsigned long long)features); + err = -EROFS; + goto restore_opts; + } +@@ -1247,7 +1244,7 @@ static int nilfs_parse_snapshot_option(const char *option, + return 0; + + parse_error: +- nilfs_msg(NULL, KERN_ERR, "invalid option \"%s\": %s", option, msg); ++ nilfs_err(NULL, "invalid option \"%s\": %s", option, msg); + return 1; + } + +@@ -1350,7 +1347,7 @@ nilfs_mount(struct file_system_type *fs_type, int flags, + } else if (!sd.cno) { + if (nilfs_tree_is_busy(s->s_root)) { + if ((flags ^ s->s_flags) & SB_RDONLY) { +- nilfs_msg(s, KERN_ERR, ++ nilfs_err(s, + "the device already has a %s mount.", + sb_rdonly(s) ? "read-only" : "read/write"); + err = -EBUSY; +diff --git a/fs/nilfs2/sysfs.c b/fs/nilfs2/sysfs.c +index 28a2db3b1787f..57afd06db62de 100644 +--- a/fs/nilfs2/sysfs.c ++++ b/fs/nilfs2/sysfs.c +@@ -261,8 +261,8 @@ nilfs_checkpoints_checkpoints_number_show(struct nilfs_checkpoints_attr *attr, + err = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat); + up_read(&nilfs->ns_segctor_sem); + if (err < 0) { +- nilfs_msg(nilfs->ns_sb, KERN_ERR, +- "unable to get checkpoint stat: err=%d", err); ++ nilfs_err(nilfs->ns_sb, "unable to get checkpoint stat: err=%d", ++ err); + return err; + } + +@@ -284,8 +284,8 @@ nilfs_checkpoints_snapshots_number_show(struct nilfs_checkpoints_attr *attr, + err = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat); + up_read(&nilfs->ns_segctor_sem); + if (err < 0) { +- nilfs_msg(nilfs->ns_sb, KERN_ERR, +- "unable to get checkpoint stat: err=%d", err); ++ nilfs_err(nilfs->ns_sb, "unable to get checkpoint stat: err=%d", ++ err); + return err; + } + +@@ -403,8 +403,8 @@ nilfs_segments_dirty_segments_show(struct nilfs_segments_attr *attr, + err = nilfs_sufile_get_stat(nilfs->ns_sufile, &sustat); + up_read(&nilfs->ns_segctor_sem); + if (err < 0) { +- nilfs_msg(nilfs->ns_sb, KERN_ERR, +- "unable to get segment stat: err=%d", err); ++ nilfs_err(nilfs->ns_sb, "unable to get segment stat: err=%d", ++ err); + return err; + } + +@@ -777,15 +777,15 @@ nilfs_superblock_sb_update_frequency_store(struct nilfs_superblock_attr *attr, + + err = kstrtouint(skip_spaces(buf), 0, &val); + if (err) { +- nilfs_msg(nilfs->ns_sb, KERN_ERR, +- "unable to convert string: err=%d", err); ++ nilfs_err(nilfs->ns_sb, "unable to convert string: err=%d", ++ err); + return err; + } + + if (val < NILFS_SB_FREQ) { + val = NILFS_SB_FREQ; +- nilfs_msg(nilfs->ns_sb, KERN_WARNING, +- "superblock update frequency cannot be lesser than 10 seconds"); ++ nilfs_warn(nilfs->ns_sb, ++ "superblock update frequency cannot be lesser than 10 seconds"); + } + + down_write(&nilfs->ns_sem); +@@ -988,8 +988,7 @@ int nilfs_sysfs_create_device_group(struct super_block *sb) + nilfs->ns_dev_subgroups = kzalloc(devgrp_size, GFP_KERNEL); + if (unlikely(!nilfs->ns_dev_subgroups)) { + err = -ENOMEM; +- nilfs_msg(sb, KERN_ERR, +- "unable to allocate memory for device group"); ++ nilfs_err(sb, "unable to allocate memory for device group"); + goto failed_create_device_group; + } + +@@ -1098,15 +1097,13 @@ int __init nilfs_sysfs_init(void) + nilfs_kset = kset_create_and_add(NILFS_ROOT_GROUP_NAME, NULL, fs_kobj); + if (!nilfs_kset) { + err = -ENOMEM; +- nilfs_msg(NULL, KERN_ERR, +- "unable to create sysfs entry: err=%d", err); ++ nilfs_err(NULL, "unable to create sysfs entry: err=%d", err); + goto failed_sysfs_init; + } + + err = sysfs_create_group(&nilfs_kset->kobj, &nilfs_feature_attr_group); + if (unlikely(err)) { +- nilfs_msg(NULL, KERN_ERR, +- "unable to create feature group: err=%d", err); ++ nilfs_err(NULL, "unable to create feature group: err=%d", err); + goto cleanup_sysfs_init; + } + +diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c +index c8d869bc25b0c..0480034644aa7 100644 +--- a/fs/nilfs2/the_nilfs.c ++++ b/fs/nilfs2/the_nilfs.c +@@ -183,7 +183,7 @@ static int nilfs_store_log_cursor(struct the_nilfs *nilfs, + nilfs_get_segnum_of_block(nilfs, nilfs->ns_last_pseg); + nilfs->ns_cno = nilfs->ns_last_cno + 1; + if (nilfs->ns_segnum >= nilfs->ns_nsegments) { +- nilfs_msg(nilfs->ns_sb, KERN_ERR, ++ nilfs_err(nilfs->ns_sb, + "pointed segment number is out of range: segnum=%llu, nsegments=%lu", + (unsigned long long)nilfs->ns_segnum, + nilfs->ns_nsegments); +@@ -210,12 +210,12 @@ int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb) + int err; + + if (!valid_fs) { +- nilfs_msg(sb, KERN_WARNING, "mounting unchecked fs"); ++ nilfs_warn(sb, "mounting unchecked fs"); + if (s_flags & SB_RDONLY) { +- nilfs_msg(sb, KERN_INFO, +- "recovery required for readonly filesystem"); +- nilfs_msg(sb, KERN_INFO, +- "write access will be enabled during recovery"); ++ nilfs_info(sb, ++ "recovery required for readonly filesystem"); ++ nilfs_info(sb, ++ "write access will be enabled during recovery"); + } + } + +@@ -230,12 +230,11 @@ int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb) + goto scan_error; + + if (!nilfs_valid_sb(sbp[1])) { +- nilfs_msg(sb, KERN_WARNING, +- "unable to fall back to spare super block"); ++ nilfs_warn(sb, ++ "unable to fall back to spare super block"); + goto scan_error; + } +- nilfs_msg(sb, KERN_INFO, +- "trying rollback from an earlier position"); ++ nilfs_info(sb, "trying rollback from an earlier position"); + + /* + * restore super block with its spare and reconfigure +@@ -248,9 +247,9 @@ int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb) + /* verify consistency between two super blocks */ + blocksize = BLOCK_SIZE << le32_to_cpu(sbp[0]->s_log_block_size); + if (blocksize != nilfs->ns_blocksize) { +- nilfs_msg(sb, KERN_WARNING, +- "blocksize differs between two super blocks (%d != %d)", +- blocksize, nilfs->ns_blocksize); ++ nilfs_warn(sb, ++ "blocksize differs between two super blocks (%d != %d)", ++ blocksize, nilfs->ns_blocksize); + goto scan_error; + } + +@@ -269,8 +268,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb) + + err = nilfs_load_super_root(nilfs, sb, ri.ri_super_root); + if (unlikely(err)) { +- nilfs_msg(sb, KERN_ERR, "error %d while loading super root", +- err); ++ nilfs_err(sb, "error %d while loading super root", err); + goto failed; + } + +@@ -285,28 +283,28 @@ int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb) + __u64 features; + + if (nilfs_test_opt(nilfs, NORECOVERY)) { +- nilfs_msg(sb, KERN_INFO, +- "norecovery option specified, skipping roll-forward recovery"); ++ nilfs_info(sb, ++ "norecovery option specified, skipping roll-forward recovery"); + goto skip_recovery; + } + features = le64_to_cpu(nilfs->ns_sbp[0]->s_feature_compat_ro) & + ~NILFS_FEATURE_COMPAT_RO_SUPP; + if (features) { +- nilfs_msg(sb, KERN_ERR, ++ nilfs_err(sb, + "couldn't proceed with recovery because of unsupported optional features (%llx)", + (unsigned long long)features); + err = -EROFS; + goto failed_unload; + } + if (really_read_only) { +- nilfs_msg(sb, KERN_ERR, ++ nilfs_err(sb, + "write access unavailable, cannot proceed"); + err = -EROFS; + goto failed_unload; + } + sb->s_flags &= ~SB_RDONLY; + } else if (nilfs_test_opt(nilfs, NORECOVERY)) { +- nilfs_msg(sb, KERN_ERR, ++ nilfs_err(sb, + "recovery cancelled because norecovery option was specified for a read/write mount"); + err = -EINVAL; + goto failed_unload; +@@ -322,12 +320,12 @@ int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb) + up_write(&nilfs->ns_sem); + + if (err) { +- nilfs_msg(sb, KERN_ERR, ++ nilfs_err(sb, + "error %d updating super block. recovery unfinished.", + err); + goto failed_unload; + } +- nilfs_msg(sb, KERN_INFO, "recovery complete"); ++ nilfs_info(sb, "recovery complete"); + + skip_recovery: + nilfs_clear_recovery_info(&ri); +@@ -335,7 +333,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb) + return 0; + + scan_error: +- nilfs_msg(sb, KERN_ERR, "error %d while searching super root", err); ++ nilfs_err(sb, "error %d while searching super root", err); + goto failed; + + failed_unload: +@@ -399,7 +397,7 @@ static int nilfs_store_disk_layout(struct the_nilfs *nilfs, + u64 nsegments, nblocks; + + if (le32_to_cpu(sbp->s_rev_level) < NILFS_MIN_SUPP_REV) { +- nilfs_msg(nilfs->ns_sb, KERN_ERR, ++ nilfs_err(nilfs->ns_sb, + "unsupported revision (superblock rev.=%d.%d, current rev.=%d.%d). Please check the version of mkfs.nilfs(2).", + le32_to_cpu(sbp->s_rev_level), + le16_to_cpu(sbp->s_minor_rev_level), +@@ -412,13 +410,11 @@ static int nilfs_store_disk_layout(struct the_nilfs *nilfs, + + nilfs->ns_inode_size = le16_to_cpu(sbp->s_inode_size); + if (nilfs->ns_inode_size > nilfs->ns_blocksize) { +- nilfs_msg(nilfs->ns_sb, KERN_ERR, +- "too large inode size: %d bytes", ++ nilfs_err(nilfs->ns_sb, "too large inode size: %d bytes", + nilfs->ns_inode_size); + return -EINVAL; + } else if (nilfs->ns_inode_size < NILFS_MIN_INODE_SIZE) { +- nilfs_msg(nilfs->ns_sb, KERN_ERR, +- "too small inode size: %d bytes", ++ nilfs_err(nilfs->ns_sb, "too small inode size: %d bytes", + nilfs->ns_inode_size); + return -EINVAL; + } +@@ -427,8 +423,7 @@ static int nilfs_store_disk_layout(struct the_nilfs *nilfs, + + nilfs->ns_blocks_per_segment = le32_to_cpu(sbp->s_blocks_per_segment); + if (nilfs->ns_blocks_per_segment < NILFS_SEG_MIN_BLOCKS) { +- nilfs_msg(nilfs->ns_sb, KERN_ERR, +- "too short segment: %lu blocks", ++ nilfs_err(nilfs->ns_sb, "too short segment: %lu blocks", + nilfs->ns_blocks_per_segment); + return -EINVAL; + } +@@ -438,7 +433,7 @@ static int nilfs_store_disk_layout(struct the_nilfs *nilfs, + le32_to_cpu(sbp->s_r_segments_percentage); + if (nilfs->ns_r_segments_percentage < 1 || + nilfs->ns_r_segments_percentage > 99) { +- nilfs_msg(nilfs->ns_sb, KERN_ERR, ++ nilfs_err(nilfs->ns_sb, + "invalid reserved segments percentage: %lu", + nilfs->ns_r_segments_percentage); + return -EINVAL; +@@ -580,16 +575,16 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, + + if (!sbp[0]) { + if (!sbp[1]) { +- nilfs_msg(sb, KERN_ERR, "unable to read superblock"); ++ nilfs_err(sb, "unable to read superblock"); + return -EIO; + } +- nilfs_msg(sb, KERN_WARNING, +- "unable to read primary superblock (blocksize = %d)", +- blocksize); ++ nilfs_warn(sb, ++ "unable to read primary superblock (blocksize = %d)", ++ blocksize); + } else if (!sbp[1]) { +- nilfs_msg(sb, KERN_WARNING, +- "unable to read secondary superblock (blocksize = %d)", +- blocksize); ++ nilfs_warn(sb, ++ "unable to read secondary superblock (blocksize = %d)", ++ blocksize); + } + + /* +@@ -611,14 +606,14 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, + } + if (!valid[swp]) { + nilfs_release_super_block(nilfs); +- nilfs_msg(sb, KERN_ERR, "couldn't find nilfs on the device"); ++ nilfs_err(sb, "couldn't find nilfs on the device"); + return -EINVAL; + } + + if (!valid[!swp]) +- nilfs_msg(sb, KERN_WARNING, +- "broken superblock, retrying with spare superblock (blocksize = %d)", +- blocksize); ++ nilfs_warn(sb, ++ "broken superblock, retrying with spare superblock (blocksize = %d)", ++ blocksize); + if (swp) + nilfs_swap_super_block(nilfs); + +@@ -652,7 +647,7 @@ int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data) + + blocksize = sb_min_blocksize(sb, NILFS_MIN_BLOCK_SIZE); + if (!blocksize) { +- nilfs_msg(sb, KERN_ERR, "unable to set blocksize"); ++ nilfs_err(sb, "unable to set blocksize"); + err = -EINVAL; + goto out; + } +@@ -671,7 +666,7 @@ int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data) + blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); + if (blocksize < NILFS_MIN_BLOCK_SIZE || + blocksize > NILFS_MAX_BLOCK_SIZE) { +- nilfs_msg(sb, KERN_ERR, ++ nilfs_err(sb, + "couldn't mount because of unsupported filesystem blocksize %d", + blocksize); + err = -EINVAL; +@@ -681,7 +676,7 @@ int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data) + int hw_blocksize = bdev_logical_block_size(sb->s_bdev); + + if (blocksize < hw_blocksize) { +- nilfs_msg(sb, KERN_ERR, ++ nilfs_err(sb, + "blocksize %d too small for device (sector-size = %d)", + blocksize, hw_blocksize); + err = -EINVAL; +-- +2.43.0 + diff --git a/queue-5.4/nvmem-meson-efuse-fix-function-pointer-type-mismatch.patch b/queue-5.4/nvmem-meson-efuse-fix-function-pointer-type-mismatch.patch new file mode 100644 index 00000000000..0a964c764a2 --- /dev/null +++ b/queue-5.4/nvmem-meson-efuse-fix-function-pointer-type-mismatch.patch @@ -0,0 +1,80 @@ +From 8ee2e43b6cbe233d3e9d5b32b48198a812cf13f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 24 Feb 2024 11:40:23 +0000 +Subject: nvmem: meson-efuse: fix function pointer type mismatch + +From: Jerome Brunet + +[ Upstream commit cbd38332c140829ab752ba4e727f98be5c257f18 ] + +clang-16 warns about casting functions to incompatible types, as is done +here to call clk_disable_unprepare: + +drivers/nvmem/meson-efuse.c:78:12: error: cast from 'void (*)(struct clk *)' to 'void (*)(void *)' converts to incompatible function type [-Werror,-Wcast-function-type-strict] + 78 | (void(*)(void *))clk_disable_unprepare, + +The pattern of getting, enabling and setting a disable callback for a +clock can be replaced with devm_clk_get_enabled(), which also fixes +this warning. + +Fixes: 611fbca1c861 ("nvmem: meson-efuse: add peripheral clock") +Cc: Stable@vger.kernel.org +Reported-by: Arnd Bergmann +Signed-off-by: Jerome Brunet +Reviewed-by: Martin Blumenstingl +Acked-by: Arnd Bergmann +Reviewed-by: Justin Stitt +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240224114023.85535-2-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/nvmem/meson-efuse.c | 25 +++---------------------- + 1 file changed, 3 insertions(+), 22 deletions(-) + +diff --git a/drivers/nvmem/meson-efuse.c b/drivers/nvmem/meson-efuse.c +index d6b533497ce1a..ba2714bef8d0e 100644 +--- a/drivers/nvmem/meson-efuse.c ++++ b/drivers/nvmem/meson-efuse.c +@@ -47,7 +47,6 @@ static int meson_efuse_probe(struct platform_device *pdev) + struct nvmem_config *econfig; + struct clk *clk; + unsigned int size; +- int ret; + + sm_np = of_parse_phandle(pdev->dev.of_node, "secure-monitor", 0); + if (!sm_np) { +@@ -60,27 +59,9 @@ static int meson_efuse_probe(struct platform_device *pdev) + if (!fw) + return -EPROBE_DEFER; + +- clk = devm_clk_get(dev, NULL); +- if (IS_ERR(clk)) { +- ret = PTR_ERR(clk); +- if (ret != -EPROBE_DEFER) +- dev_err(dev, "failed to get efuse gate"); +- return ret; +- } +- +- ret = clk_prepare_enable(clk); +- if (ret) { +- dev_err(dev, "failed to enable gate"); +- return ret; +- } +- +- ret = devm_add_action_or_reset(dev, +- (void(*)(void *))clk_disable_unprepare, +- clk); +- if (ret) { +- dev_err(dev, "failed to add disable callback"); +- return ret; +- } ++ clk = devm_clk_get_enabled(dev, NULL); ++ if (IS_ERR(clk)) ++ return dev_err_probe(dev, PTR_ERR(clk), "failed to get efuse gate"); + + if (meson_sm_call(fw, SM_EFUSE_USER_MAX, &size, 0, 0, 0, 0, 0) < 0) { + dev_err(dev, "failed to get max user"); +-- +2.43.0 + diff --git a/queue-5.4/parisc-do-not-hardcode-registers-in-checksum-functio.patch b/queue-5.4/parisc-do-not-hardcode-registers-in-checksum-functio.patch new file mode 100644 index 00000000000..230f0d956ad --- /dev/null +++ b/queue-5.4/parisc-do-not-hardcode-registers-in-checksum-functio.patch @@ -0,0 +1,170 @@ +From 2c1119eb82ffed6d94489a4c80e4b776615fb2f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 29 Sep 2019 21:00:42 +0200 +Subject: parisc: Do not hardcode registers in checksum functions + +From: Helge Deller + +[ Upstream commit 52b2d91752a82d9350981eb3b3ffc4b325c84ba9 ] + +Do not hardcode processor registers r19 to r22 as scratch registers. +Instead let the compiler decide, which may give better optimization +results when the functions get inlined. + +Signed-off-by: Helge Deller +Stable-dep-of: a2abae8f0b63 ("parisc: Fix ip_fast_csum") +Signed-off-by: Sasha Levin +--- + arch/parisc/include/asm/checksum.h | 101 +++++++++++++++-------------- + 1 file changed, 52 insertions(+), 49 deletions(-) + +diff --git a/arch/parisc/include/asm/checksum.h b/arch/parisc/include/asm/checksum.h +index 3cbf1f1c1188e..c1c22819a04d1 100644 +--- a/arch/parisc/include/asm/checksum.h ++++ b/arch/parisc/include/asm/checksum.h +@@ -42,31 +42,32 @@ extern __wsum csum_partial_copy_from_user(const void __user *src, + static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) + { + unsigned int sum; ++ unsigned long t0, t1, t2; + + __asm__ __volatile__ ( + " ldws,ma 4(%1), %0\n" + " addib,<= -4, %2, 2f\n" + "\n" +-" ldws 4(%1), %%r20\n" +-" ldws 8(%1), %%r21\n" +-" add %0, %%r20, %0\n" +-" ldws,ma 12(%1), %%r19\n" +-" addc %0, %%r21, %0\n" +-" addc %0, %%r19, %0\n" +-"1: ldws,ma 4(%1), %%r19\n" ++" ldws 4(%1), %4\n" ++" ldws 8(%1), %5\n" ++" add %0, %4, %0\n" ++" ldws,ma 12(%1), %3\n" ++" addc %0, %5, %0\n" ++" addc %0, %3, %0\n" ++"1: ldws,ma 4(%1), %3\n" + " addib,< 0, %2, 1b\n" +-" addc %0, %%r19, %0\n" ++" addc %0, %3, %0\n" + "\n" +-" extru %0, 31, 16, %%r20\n" +-" extru %0, 15, 16, %%r21\n" +-" addc %%r20, %%r21, %0\n" +-" extru %0, 15, 16, %%r21\n" +-" add %0, %%r21, %0\n" ++" extru %0, 31, 16, %4\n" ++" extru %0, 15, 16, %5\n" ++" addc %4, %5, %0\n" ++" extru %0, 15, 16, %5\n" ++" add %0, %5, %0\n" + " subi -1, %0, %0\n" + "2:\n" +- : "=r" (sum), "=r" (iph), "=r" (ihl) ++ : "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (t0), "=r" (t1), "=r" (t2) + : "1" (iph), "2" (ihl) +- : "r19", "r20", "r21", "memory"); ++ : "memory"); + + return (__force __sum16)sum; + } +@@ -126,6 +127,10 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, + __u32 len, __u8 proto, + __wsum sum) + { ++ unsigned long t0, t1, t2, t3; ++ ++ len += proto; /* add 16-bit proto + len */ ++ + __asm__ __volatile__ ( + + #if BITS_PER_LONG > 32 +@@ -136,20 +141,19 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, + ** Try to keep 4 registers with "live" values ahead of the ALU. + */ + +-" ldd,ma 8(%1), %%r19\n" /* get 1st saddr word */ +-" ldd,ma 8(%2), %%r20\n" /* get 1st daddr word */ +-" add %8, %3, %3\n"/* add 16-bit proto + len */ +-" add %%r19, %0, %0\n" +-" ldd,ma 8(%1), %%r21\n" /* 2cd saddr */ +-" ldd,ma 8(%2), %%r22\n" /* 2cd daddr */ +-" add,dc %%r20, %0, %0\n" +-" add,dc %%r21, %0, %0\n" +-" add,dc %%r22, %0, %0\n" ++" ldd,ma 8(%1), %4\n" /* get 1st saddr word */ ++" ldd,ma 8(%2), %5\n" /* get 1st daddr word */ ++" add %4, %0, %0\n" ++" ldd,ma 8(%1), %6\n" /* 2nd saddr */ ++" ldd,ma 8(%2), %7\n" /* 2nd daddr */ ++" add,dc %5, %0, %0\n" ++" add,dc %6, %0, %0\n" ++" add,dc %7, %0, %0\n" + " add,dc %3, %0, %0\n" /* fold in proto+len | carry bit */ +-" extrd,u %0, 31, 32, %%r19\n" /* copy upper half down */ +-" depdi 0, 31, 32, %0\n" /* clear upper half */ +-" add %%r19, %0, %0\n" /* fold into 32-bits */ +-" addc 0, %0, %0\n" /* add carry */ ++" extrd,u %0, 31, 32, %4\n"/* copy upper half down */ ++" depdi 0, 31, 32, %0\n"/* clear upper half */ ++" add %4, %0, %0\n" /* fold into 32-bits */ ++" addc 0, %0, %0\n" /* add carry */ + + #else + +@@ -158,30 +162,29 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, + ** Insn stream is serialized on the carry bit here too. + ** result from the previous operation (eg r0 + x) + */ +- +-" ldw,ma 4(%1), %%r19\n" /* get 1st saddr word */ +-" ldw,ma 4(%2), %%r20\n" /* get 1st daddr word */ +-" add %8, %3, %3\n" /* add 16-bit proto + len */ +-" add %%r19, %0, %0\n" +-" ldw,ma 4(%1), %%r21\n" /* 2cd saddr */ +-" addc %%r20, %0, %0\n" +-" ldw,ma 4(%2), %%r22\n" /* 2cd daddr */ +-" addc %%r21, %0, %0\n" +-" ldw,ma 4(%1), %%r19\n" /* 3rd saddr */ +-" addc %%r22, %0, %0\n" +-" ldw,ma 4(%2), %%r20\n" /* 3rd daddr */ +-" addc %%r19, %0, %0\n" +-" ldw,ma 4(%1), %%r21\n" /* 4th saddr */ +-" addc %%r20, %0, %0\n" +-" ldw,ma 4(%2), %%r22\n" /* 4th daddr */ +-" addc %%r21, %0, %0\n" +-" addc %%r22, %0, %0\n" ++" ldw,ma 4(%1), %4\n" /* get 1st saddr word */ ++" ldw,ma 4(%2), %5\n" /* get 1st daddr word */ ++" add %4, %0, %0\n" ++" ldw,ma 4(%1), %6\n" /* 2nd saddr */ ++" addc %5, %0, %0\n" ++" ldw,ma 4(%2), %7\n" /* 2nd daddr */ ++" addc %6, %0, %0\n" ++" ldw,ma 4(%1), %4\n" /* 3rd saddr */ ++" addc %7, %0, %0\n" ++" ldw,ma 4(%2), %5\n" /* 3rd daddr */ ++" addc %4, %0, %0\n" ++" ldw,ma 4(%1), %6\n" /* 4th saddr */ ++" addc %5, %0, %0\n" ++" ldw,ma 4(%2), %7\n" /* 4th daddr */ ++" addc %6, %0, %0\n" ++" addc %7, %0, %0\n" + " addc %3, %0, %0\n" /* fold in proto+len, catch carry */ + + #endif +- : "=r" (sum), "=r" (saddr), "=r" (daddr), "=r" (len) +- : "0" (sum), "1" (saddr), "2" (daddr), "3" (len), "r" (proto) +- : "r19", "r20", "r21", "r22", "memory"); ++ : "=r" (sum), "=r" (saddr), "=r" (daddr), "=r" (len), ++ "=r" (t0), "=r" (t1), "=r" (t2), "=r" (t3) ++ : "0" (sum), "1" (saddr), "2" (daddr), "3" (len) ++ : "memory"); + return csum_fold(sum); + } + +-- +2.43.0 + diff --git a/queue-5.4/parisc-fix-csum_ipv6_magic-on-32-bit-systems.patch b/queue-5.4/parisc-fix-csum_ipv6_magic-on-32-bit-systems.patch new file mode 100644 index 00000000000..b5c330ee923 --- /dev/null +++ b/queue-5.4/parisc-fix-csum_ipv6_magic-on-32-bit-systems.patch @@ -0,0 +1,55 @@ +From a7b8b9bafd54330c4b0e62fd81531609ccd8e9a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 10 Feb 2024 11:15:56 -0800 +Subject: parisc: Fix csum_ipv6_magic on 32-bit systems + +From: Guenter Roeck + +[ Upstream commit 4408ba75e4ba80c91fde7e10bccccf388f5c09be ] + +Calculating the IPv6 checksum on 32-bit systems missed overflows when +adding the proto+len fields into the checksum. This results in the +following unit test failure. + + # test_csum_ipv6_magic: ASSERTION FAILED at lib/checksum_kunit.c:506 + Expected ( u64)csum_result == ( u64)expected, but + ( u64)csum_result == 46722 (0xb682) + ( u64)expected == 46721 (0xb681) + not ok 5 test_csum_ipv6_magic + +This is probably rarely seen in the real world because proto+len are +usually small values which will rarely result in overflows when calculating +the checksum. However, the unit test code uses large values for the length +field, causing the test to fail. + +Fix the problem by adding the missing carry into the final checksum. + +Cc: Palmer Dabbelt +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org +Signed-off-by: Guenter Roeck +Tested-by: Charlie Jenkins +Reviewed-by: Charlie Jenkins +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + arch/parisc/include/asm/checksum.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/parisc/include/asm/checksum.h b/arch/parisc/include/asm/checksum.h +index 7efcd901b9656..0a02639514505 100644 +--- a/arch/parisc/include/asm/checksum.h ++++ b/arch/parisc/include/asm/checksum.h +@@ -178,7 +178,8 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, + " ldw,ma 4(%2), %7\n" /* 4th daddr */ + " addc %6, %0, %0\n" + " addc %7, %0, %0\n" +-" addc %3, %0, %0\n" /* fold in proto+len, catch carry */ ++" addc %3, %0, %0\n" /* fold in proto+len */ ++" addc 0, %0, %0\n" /* add carry */ + + #endif + : "=r" (sum), "=r" (saddr), "=r" (daddr), "=r" (len), +-- +2.43.0 + diff --git a/queue-5.4/parisc-fix-csum_ipv6_magic-on-64-bit-systems.patch b/queue-5.4/parisc-fix-csum_ipv6_magic-on-64-bit-systems.patch new file mode 100644 index 00000000000..298dea6d937 --- /dev/null +++ b/queue-5.4/parisc-fix-csum_ipv6_magic-on-64-bit-systems.patch @@ -0,0 +1,55 @@ +From 14d25bfed6981c007d368d36574d5646e7dcd989 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Feb 2024 15:46:31 -0800 +Subject: parisc: Fix csum_ipv6_magic on 64-bit systems + +From: Guenter Roeck + +[ Upstream commit 4b75b12d70506e31fc02356bbca60f8d5ca012d0 ] + +hppa 64-bit systems calculates the IPv6 checksum using 64-bit add +operations. The last add folds protocol and length fields into the 64-bit +result. While unlikely, this operation can overflow. The overflow can be +triggered with a code sequence such as the following. + + /* try to trigger massive overflows */ + memset(tmp_buf, 0xff, sizeof(struct in6_addr)); + csum_result = csum_ipv6_magic((struct in6_addr *)tmp_buf, + (struct in6_addr *)tmp_buf, + 0xffff, 0xff, 0xffffffff); + +Fix the problem by adding any overflows from the final add operation into +the calculated checksum. Fortunately, we can do this without additional +cost by replacing the add operation used to fold the checksum into 32 bit +with "add,dc" to add in the missing carry. + +Cc: Palmer Dabbelt +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org +Signed-off-by: Guenter Roeck +Reviewed-by: Charlie Jenkins +Tested-by: Guenter Roeck +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + arch/parisc/include/asm/checksum.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/parisc/include/asm/checksum.h b/arch/parisc/include/asm/checksum.h +index 0a02639514505..7861d365ba1e2 100644 +--- a/arch/parisc/include/asm/checksum.h ++++ b/arch/parisc/include/asm/checksum.h +@@ -152,8 +152,8 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, + " add,dc %3, %0, %0\n" /* fold in proto+len | carry bit */ + " extrd,u %0, 31, 32, %4\n"/* copy upper half down */ + " depdi 0, 31, 32, %0\n"/* clear upper half */ +-" add %4, %0, %0\n" /* fold into 32-bits */ +-" addc 0, %0, %0\n" /* add carry */ ++" add,dc %4, %0, %0\n" /* fold into 32-bits, plus carry */ ++" addc 0, %0, %0\n" /* add final carry */ + + #else + +-- +2.43.0 + diff --git a/queue-5.4/parisc-fix-ip_fast_csum.patch b/queue-5.4/parisc-fix-ip_fast_csum.patch new file mode 100644 index 00000000000..973ffa566a4 --- /dev/null +++ b/queue-5.4/parisc-fix-ip_fast_csum.patch @@ -0,0 +1,66 @@ +From 050a4dfc2ed005a701be7d175bc394559633debe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 10 Feb 2024 09:55:26 -0800 +Subject: parisc: Fix ip_fast_csum + +From: Guenter Roeck + +[ Upstream commit a2abae8f0b638c31bb9799d9dd847306e0d005bd ] + +IP checksum unit tests report the following error when run on hppa/hppa64. + + # test_ip_fast_csum: ASSERTION FAILED at lib/checksum_kunit.c:463 + Expected ( u64)csum_result == ( u64)expected, but + ( u64)csum_result == 33754 (0x83da) + ( u64)expected == 10946 (0x2ac2) + not ok 4 test_ip_fast_csum + +0x83da is the expected result if the IP header length is 20 bytes. 0x2ac2 +is the expected result if the IP header length is 24 bytes. The test fails +with an IP header length of 24 bytes. It appears that ip_fast_csum() +always returns the checksum for a 20-byte header, no matter how long +the header actually is. + +Code analysis shows a suspicious assembler sequence in ip_fast_csum(). + + " addc %0, %3, %0\n" + "1: ldws,ma 4(%1), %3\n" + " addib,< 0, %2, 1b\n" <--- + +While my understanding of HPPA assembler is limited, it does not seem +to make much sense to subtract 0 from a register and to expect the result +to ever be negative. Subtracting 1 from the length parameter makes more +sense. On top of that, the operation should be repeated if and only if +the result is still > 0, so change the suspicious instruction to + " addib,> -1, %2, 1b\n" + +The IP checksum unit test passes after this change. + +Cc: Palmer Dabbelt +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org +Signed-off-by: Guenter Roeck +Tested-by: Charlie Jenkins +Reviewed-by: Charlie Jenkins +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + arch/parisc/include/asm/checksum.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/parisc/include/asm/checksum.h b/arch/parisc/include/asm/checksum.h +index c1c22819a04d1..7efcd901b9656 100644 +--- a/arch/parisc/include/asm/checksum.h ++++ b/arch/parisc/include/asm/checksum.h +@@ -55,7 +55,7 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) + " addc %0, %5, %0\n" + " addc %0, %3, %0\n" + "1: ldws,ma 4(%1), %3\n" +-" addib,< 0, %2, 1b\n" ++" addib,> -1, %2, 1b\n" + " addc %0, %3, %0\n" + "\n" + " extru %0, 31, 16, %4\n" +-- +2.43.0 + diff --git a/queue-5.4/parisc-strip-upper-32-bit-of-sum-in-csum_ipv6_magic-.patch b/queue-5.4/parisc-strip-upper-32-bit-of-sum-in-csum_ipv6_magic-.patch new file mode 100644 index 00000000000..73fde9e47a3 --- /dev/null +++ b/queue-5.4/parisc-strip-upper-32-bit-of-sum-in-csum_ipv6_magic-.patch @@ -0,0 +1,55 @@ +From 9f97fcdfbca270cade377b9fa50a81ef923ddbb6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Feb 2024 12:33:51 -0800 +Subject: parisc: Strip upper 32 bit of sum in csum_ipv6_magic for 64-bit + builds + +From: Guenter Roeck + +[ Upstream commit 0568b6f0d863643db2edcc7be31165740c89fa82 ] + +IPv6 checksum tests with unaligned addresses on 64-bit builds result +in unexpected failures. + +Expected expected == csum_result, but + expected == 46591 (0xb5ff) + csum_result == 46381 (0xb52d) +with alignment offset 1 + +Oddly enough, the problem disappeared after adding test code into +the beginning of csum_ipv6_magic(). + +As it turns out, the 'sum' parameter of csum_ipv6_magic() is declared as +__wsum, which is a 32-bit variable. However, it is treated as 64-bit +variable in the 64-bit assembler code. Tests showed that the upper 32 bit +of the register used to pass the variable are _not_ cleared when entering +the function. This can result in checksum calculation errors. + +Clearing the upper 32 bit of 'sum' as first operation in the assembler +code fixes the problem. + +Acked-by: Helge Deller +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org +Signed-off-by: Guenter Roeck +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + arch/parisc/include/asm/checksum.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/parisc/include/asm/checksum.h b/arch/parisc/include/asm/checksum.h +index 7861d365ba1e2..ef34e8f839d55 100644 +--- a/arch/parisc/include/asm/checksum.h ++++ b/arch/parisc/include/asm/checksum.h +@@ -141,6 +141,7 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, + ** Try to keep 4 registers with "live" values ahead of the ALU. + */ + ++" depdi 0, 31, 32, %0\n"/* clear upper half of incoming checksum */ + " ldd,ma 8(%1), %4\n" /* get 1st saddr word */ + " ldd,ma 8(%2), %5\n" /* get 1st daddr word */ + " add %4, %0, %0\n" +-- +2.43.0 + diff --git a/queue-5.4/pci-drop-pci_device_remove-test-of-pci_dev-driver.patch b/queue-5.4/pci-drop-pci_device_remove-test-of-pci_dev-driver.patch new file mode 100644 index 00000000000..c704f2cb077 --- /dev/null +++ b/queue-5.4/pci-drop-pci_device_remove-test-of-pci_dev-driver.patch @@ -0,0 +1,58 @@ +From 5ecd6ea79d068313aacbc6465cfe1be3d59540e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Oct 2021 14:59:25 +0200 +Subject: PCI: Drop pci_device_remove() test of pci_dev->driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 097d9d414433315122f759ee6c2d8a7417a8ff0f ] + +When the driver core calls pci_device_remove(), there is a driver bound +to the device, so pci_dev->driver is never NULL. + +Remove the unnecessary test of pci_dev->driver. + +Link: https://lore.kernel.org/r/20211004125935.2300113-2-u.kleine-koenig@pengutronix.de +Signed-off-by: Uwe Kleine-König +Signed-off-by: Bjorn Helgaas +Reviewed-by: Christoph Hellwig +Stable-dep-of: 9d5286d4e7f6 ("PCI/PM: Drain runtime-idle callbacks before driver removal") +Signed-off-by: Sasha Levin +--- + drivers/pci/pci-driver.c | 16 +++++++--------- + 1 file changed, 7 insertions(+), 9 deletions(-) + +diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c +index 70c8584b3ffcc..7644a282bfdb8 100644 +--- a/drivers/pci/pci-driver.c ++++ b/drivers/pci/pci-driver.c +@@ -439,16 +439,14 @@ static int pci_device_remove(struct device *dev) + struct pci_dev *pci_dev = to_pci_dev(dev); + struct pci_driver *drv = pci_dev->driver; + +- if (drv) { +- if (drv->remove) { +- pm_runtime_get_sync(dev); +- drv->remove(pci_dev); +- pm_runtime_put_noidle(dev); +- } +- pcibios_free_irq(pci_dev); +- pci_dev->driver = NULL; +- pci_iov_remove(pci_dev); ++ if (drv->remove) { ++ pm_runtime_get_sync(dev); ++ drv->remove(pci_dev); ++ pm_runtime_put_noidle(dev); + } ++ pcibios_free_irq(pci_dev); ++ pci_dev->driver = NULL; ++ pci_iov_remove(pci_dev); + + /* Undo the runtime PM settings in local_pci_probe() */ + pm_runtime_put_sync(dev); +-- +2.43.0 + diff --git a/queue-5.4/pci-pm-drain-runtime-idle-callbacks-before-driver-re.patch b/queue-5.4/pci-pm-drain-runtime-idle-callbacks-before-driver-re.patch new file mode 100644 index 00000000000..f84e20c0294 --- /dev/null +++ b/queue-5.4/pci-pm-drain-runtime-idle-callbacks-before-driver-re.patch @@ -0,0 +1,76 @@ +From afe96e755f1efe5384755121c4133672853933a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Mar 2024 11:45:38 +0100 +Subject: PCI/PM: Drain runtime-idle callbacks before driver removal + +From: Rafael J. Wysocki + +[ Upstream commit 9d5286d4e7f68beab450deddbb6a32edd5ecf4bf ] + +A race condition between the .runtime_idle() callback and the .remove() +callback in the rtsx_pcr PCI driver leads to a kernel crash due to an +unhandled page fault [1]. + +The problem is that rtsx_pci_runtime_idle() is not expected to be running +after pm_runtime_get_sync() has been called, but the latter doesn't really +guarantee that. It only guarantees that the suspend and resume callbacks +will not be running when it returns. + +However, if a .runtime_idle() callback is already running when +pm_runtime_get_sync() is called, the latter will notice that the runtime PM +status of the device is RPM_ACTIVE and it will return right away without +waiting for the former to complete. In fact, it cannot wait for +.runtime_idle() to complete because it may be called from that callback (it +arguably does not make much sense to do that, but it is not strictly +prohibited). + +Thus in general, whoever is providing a .runtime_idle() callback needs +to protect it from running in parallel with whatever code runs after +pm_runtime_get_sync(). [Note that .runtime_idle() will not start after +pm_runtime_get_sync() has returned, but it may continue running then if it +has started earlier.] + +One way to address that race condition is to call pm_runtime_barrier() +after pm_runtime_get_sync() (not before it, because a nonzero value of the +runtime PM usage counter is necessary to prevent runtime PM callbacks from +being invoked) to wait for the .runtime_idle() callback to complete should +it be running at that point. A suitable place for doing that is in +pci_device_remove() which calls pm_runtime_get_sync() before removing the +driver, so it may as well call pm_runtime_barrier() subsequently, which +will prevent the race in question from occurring, not just in the rtsx_pcr +driver, but in any PCI drivers providing .runtime_idle() callbacks. + +Link: https://lore.kernel.org/lkml/20240229062201.49500-1-kai.heng.feng@canonical.com/ # [1] +Link: https://lore.kernel.org/r/5761426.DvuYhMxLoT@kreacher +Reported-by: Kai-Heng Feng +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Bjorn Helgaas +Tested-by: Ricky Wu +Acked-by: Kai-Heng Feng +Cc: +Signed-off-by: Sasha Levin +--- + drivers/pci/pci-driver.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c +index 7644a282bfdb8..617b13c94b390 100644 +--- a/drivers/pci/pci-driver.c ++++ b/drivers/pci/pci-driver.c +@@ -441,6 +441,13 @@ static int pci_device_remove(struct device *dev) + + if (drv->remove) { + pm_runtime_get_sync(dev); ++ /* ++ * If the driver provides a .runtime_idle() callback and it has ++ * started to run already, it may continue to run in parallel ++ * with the code below, so wait until all of the runtime PM ++ * activity has completed. ++ */ ++ pm_runtime_barrier(dev); + drv->remove(pci_dev); + pm_runtime_put_noidle(dev); + } +-- +2.43.0 + diff --git a/queue-5.4/pm-sleep-wakeirq-fix-wake-irq-warning-in-system-susp.patch b/queue-5.4/pm-sleep-wakeirq-fix-wake-irq-warning-in-system-susp.patch new file mode 100644 index 00000000000..09828909fb4 --- /dev/null +++ b/queue-5.4/pm-sleep-wakeirq-fix-wake-irq-warning-in-system-susp.patch @@ -0,0 +1,59 @@ +From 1d213ef8f90c8bf0e35990f26001d4af1a4d01b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Mar 2024 17:26:57 +0800 +Subject: PM: sleep: wakeirq: fix wake irq warning in system suspend + +From: Qingliang Li + +[ Upstream commit e7a7681c859643f3f2476b2a28a494877fd89442 ] + +When driver uses pm_runtime_force_suspend() as the system suspend callback +function and registers the wake irq with reverse enable ordering, the wake +irq will be re-enabled when entering system suspend, triggering an +'Unbalanced enable for IRQ xxx' warning. In this scenario, the call +sequence during system suspend is as follows: + suspend_devices_and_enter() + -> dpm_suspend_start() + -> dpm_run_callback() + -> pm_runtime_force_suspend() + -> dev_pm_enable_wake_irq_check() + -> dev_pm_enable_wake_irq_complete() + + -> suspend_enter() + -> dpm_suspend_noirq() + -> device_wakeup_arm_wake_irqs() + -> dev_pm_arm_wake_irq() + +To fix this issue, complete the setting of WAKE_IRQ_DEDICATED_ENABLED flag +in dev_pm_enable_wake_irq_complete() to avoid redundant irq enablement. + +Fixes: 8527beb12087 ("PM: sleep: wakeirq: fix wake irq arming") +Reviewed-by: Dhruva Gole +Signed-off-by: Qingliang Li +Reviewed-by: Johan Hovold +Cc: 5.16+ # 5.16+ +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/base/power/wakeirq.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c +index 46654adf00a10..20b07fa2792ba 100644 +--- a/drivers/base/power/wakeirq.c ++++ b/drivers/base/power/wakeirq.c +@@ -365,8 +365,10 @@ void dev_pm_enable_wake_irq_complete(struct device *dev) + return; + + if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED && +- wirq->status & WAKE_IRQ_DEDICATED_REVERSE) ++ wirq->status & WAKE_IRQ_DEDICATED_REVERSE) { + enable_irq(wirq->irq); ++ wirq->status |= WAKE_IRQ_DEDICATED_ENABLED; ++ } + } + + /** +-- +2.43.0 + diff --git a/queue-5.4/pm-suspend-set-mem_sleep_current-during-kernel-comma.patch b/queue-5.4/pm-suspend-set-mem_sleep_current-during-kernel-comma.patch new file mode 100644 index 00000000000..8dafac33bfb --- /dev/null +++ b/queue-5.4/pm-suspend-set-mem_sleep_current-during-kernel-comma.patch @@ -0,0 +1,42 @@ +From 48969729d4e23b856564e7c8e434cdcce1575d3e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Feb 2024 12:14:59 +0530 +Subject: PM: suspend: Set mem_sleep_current during kernel command line setup + +From: Maulik Shah + +[ Upstream commit 9bc4ffd32ef8943f5c5a42c9637cfd04771d021b ] + +psci_init_system_suspend() invokes suspend_set_ops() very early during +bootup even before kernel command line for mem_sleep_default is setup. +This leads to kernel command line mem_sleep_default=s2idle not working +as mem_sleep_current gets changed to deep via suspend_set_ops() and never +changes back to s2idle. + +Set mem_sleep_current along with mem_sleep_default during kernel command +line setup as default suspend mode. + +Fixes: faf7ec4a92c0 ("drivers: firmware: psci: add system suspend support") +CC: stable@vger.kernel.org # 5.4+ +Signed-off-by: Maulik Shah +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + kernel/power/suspend.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c +index 5dea2778a3dbb..c6433d3c04a0e 100644 +--- a/kernel/power/suspend.c ++++ b/kernel/power/suspend.c +@@ -187,6 +187,7 @@ static int __init mem_sleep_default_setup(char *str) + if (mem_sleep_labels[state] && + !strcmp(str, mem_sleep_labels[state])) { + mem_sleep_default = state; ++ mem_sleep_current = state; + break; + } + +-- +2.43.0 + diff --git a/queue-5.4/powerpc-fsl-fix-mfpmr-build-errors-with-newer-binuti.patch b/queue-5.4/powerpc-fsl-fix-mfpmr-build-errors-with-newer-binuti.patch new file mode 100644 index 00000000000..e36f065d470 --- /dev/null +++ b/queue-5.4/powerpc-fsl-fix-mfpmr-build-errors-with-newer-binuti.patch @@ -0,0 +1,61 @@ +From c4c34fdff7c5346b072f068a60c7769dc75dd682 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Feb 2024 23:25:19 +1100 +Subject: powerpc/fsl: Fix mfpmr build errors with newer binutils + +From: Michael Ellerman + +[ Upstream commit 5f491356b7149564ab22323ccce79c8d595bfd0c ] + +Binutils 2.38 complains about the use of mfpmr when building +ppc6xx_defconfig: + + CC arch/powerpc/kernel/pmc.o + {standard input}: Assembler messages: + {standard input}:45: Error: unrecognized opcode: `mfpmr' + {standard input}:56: Error: unrecognized opcode: `mtpmr' + +This is because by default the kernel is built with -mcpu=powerpc, and +the mt/mfpmr instructions are not defined. + +It can be avoided by enabling CONFIG_E300C3_CPU, but just adding that to +the defconfig will leave open the possibility of randconfig failures. + +So add machine directives around the mt/mfpmr instructions to tell +binutils how to assemble them. + +Cc: stable@vger.kernel.org +Reported-by: Jan-Benedict Glaw +Signed-off-by: Michael Ellerman +Link: https://msgid.link/20240229122521.762431-3-mpe@ellerman.id.au +Signed-off-by: Sasha Levin +--- + arch/powerpc/include/asm/reg_fsl_emb.h | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/arch/powerpc/include/asm/reg_fsl_emb.h b/arch/powerpc/include/asm/reg_fsl_emb.h +index a21f529c43d96..8359c06d92d9f 100644 +--- a/arch/powerpc/include/asm/reg_fsl_emb.h ++++ b/arch/powerpc/include/asm/reg_fsl_emb.h +@@ -12,9 +12,16 @@ + #ifndef __ASSEMBLY__ + /* Performance Monitor Registers */ + #define mfpmr(rn) ({unsigned int rval; \ +- asm volatile("mfpmr %0," __stringify(rn) \ ++ asm volatile(".machine push; " \ ++ ".machine e300; " \ ++ "mfpmr %0," __stringify(rn) ";" \ ++ ".machine pop; " \ + : "=r" (rval)); rval;}) +-#define mtpmr(rn, v) asm volatile("mtpmr " __stringify(rn) ",%0" : : "r" (v)) ++#define mtpmr(rn, v) asm volatile(".machine push; " \ ++ ".machine e300; " \ ++ "mtpmr " __stringify(rn) ",%0; " \ ++ ".machine pop; " \ ++ : : "r" (v)) + #endif /* __ASSEMBLY__ */ + + /* Freescale Book E Performance Monitor APU Registers */ +-- +2.43.0 + diff --git a/queue-5.4/revert-revert-md-raid5-wait-for-md_sb_change_pending.patch b/queue-5.4/revert-revert-md-raid5-wait-for-md_sb_change_pending.patch new file mode 100644 index 00000000000..ff6c14c8ae7 --- /dev/null +++ b/queue-5.4/revert-revert-md-raid5-wait-for-md_sb_change_pending.patch @@ -0,0 +1,72 @@ +From 080d45a57be6a9ea8789b2615297a36ee59402d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Jan 2024 00:21:31 -0800 +Subject: Revert "Revert "md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d"" + +From: Song Liu + +[ Upstream commit 3445139e3a594be77eff48bc17eff67cf983daed ] + +This reverts commit bed9e27baf52a09b7ba2a3714f1e24e17ced386d. + +The original set [1][2] was expected to undo a suboptimal fix in [2], and +replace it with a better fix [1]. However, as reported by Dan Moulding [2] +causes an issue with raid5 with journal device. + +Revert [2] for now to close the issue. We will follow up on another issue +reported by Juxiao Bi, as [2] is expected to fix it. We believe this is a +good trade-off, because the latter issue happens less freqently. + +In the meanwhile, we will NOT revert [1], as it contains the right logic. + +[1] commit d6e035aad6c0 ("md: bypass block throttle for superblock update") +[2] commit bed9e27baf52 ("Revert "md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d"") + +Reported-by: Dan Moulding +Closes: https://lore.kernel.org/linux-raid/20240123005700.9302-1-dan@danm.net/ +Fixes: bed9e27baf52 ("Revert "md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d"") +Cc: stable@vger.kernel.org # v5.19+ +Cc: Junxiao Bi +Cc: Yu Kuai +Signed-off-by: Song Liu +Reviewed-by: Yu Kuai +Link: https://lore.kernel.org/r/20240125082131.788600-1-song@kernel.org +Signed-off-by: Sasha Levin +--- + drivers/md/raid5.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 0bea103f63d55..f3d60c4b34b8c 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -36,6 +36,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -6334,7 +6335,18 @@ static void raid5d(struct md_thread *thread) + spin_unlock_irq(&conf->device_lock); + md_check_recovery(mddev); + spin_lock_irq(&conf->device_lock); ++ ++ /* ++ * Waiting on MD_SB_CHANGE_PENDING below may deadlock ++ * seeing md_check_recovery() is needed to clear ++ * the flag when using mdmon. ++ */ ++ continue; + } ++ ++ wait_event_lock_irq(mddev->sb_wait, ++ !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags), ++ conf->device_lock); + } + pr_debug("%d stripes handled\n", handled); + +-- +2.43.0 + diff --git a/queue-5.4/ring-buffer-fix-full_waiters_pending-in-poll.patch b/queue-5.4/ring-buffer-fix-full_waiters_pending-in-poll.patch new file mode 100644 index 00000000000..b0cca7fc539 --- /dev/null +++ b/queue-5.4/ring-buffer-fix-full_waiters_pending-in-poll.patch @@ -0,0 +1,138 @@ +From f86962b17c8a108cc4a462ea57b5f55b945e4ca9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Mar 2024 09:19:20 -0400 +Subject: ring-buffer: Fix full_waiters_pending in poll + +From: Steven Rostedt (Google) + +[ Upstream commit 8145f1c35fa648da662078efab299c4467b85ad5 ] + +If a reader of the ring buffer is doing a poll, and waiting for the ring +buffer to hit a specific watermark, there could be a case where it gets +into an infinite ping-pong loop. + +The poll code has: + + rbwork->full_waiters_pending = true; + if (!cpu_buffer->shortest_full || + cpu_buffer->shortest_full > full) + cpu_buffer->shortest_full = full; + +The writer will see full_waiters_pending and check if the ring buffer is +filled over the percentage of the shortest_full value. If it is, it calls +an irq_work to wake up all the waiters. + +But the code could get into a circular loop: + + CPU 0 CPU 1 + ----- ----- + [ Poll ] + [ shortest_full = 0 ] + rbwork->full_waiters_pending = true; + if (rbwork->full_waiters_pending && + [ buffer percent ] > shortest_full) { + rbwork->wakeup_full = true; + [ queue_irqwork ] + + cpu_buffer->shortest_full = full; + + [ IRQ work ] + if (rbwork->wakeup_full) { + cpu_buffer->shortest_full = 0; + wakeup poll waiters; + [woken] + if ([ buffer percent ] > full) + break; + rbwork->full_waiters_pending = true; + if (rbwork->full_waiters_pending && + [ buffer percent ] > shortest_full) { + rbwork->wakeup_full = true; + [ queue_irqwork ] + + cpu_buffer->shortest_full = full; + + [ IRQ work ] + if (rbwork->wakeup_full) { + cpu_buffer->shortest_full = 0; + wakeup poll waiters; + [woken] + + [ Wash, rinse, repeat! ] + +In the poll, the shortest_full needs to be set before the +full_pending_waiters, as once that is set, the writer will compare the +current shortest_full (which is incorrect) to decide to call the irq_work, +which will reset the shortest_full (expecting the readers to update it). + +Also move the setting of full_waiters_pending after the check if the ring +buffer has the required percentage filled. There's no reason to tell the +writer to wake up waiters if there are no waiters. + +Link: https://lore.kernel.org/linux-trace-kernel/20240312131952.630922155@goodmis.org + +Cc: stable@vger.kernel.org +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Fixes: 42fb0a1e84ff5 ("tracing/ring-buffer: Have polling block on watermark") +Reviewed-by: Masami Hiramatsu (Google) +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + kernel/trace/ring_buffer.c | 27 ++++++++++++++++++++------- + 1 file changed, 20 insertions(+), 7 deletions(-) + +diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c +index a9c90088af780..d2dba546fbbe1 100644 +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -761,16 +761,32 @@ __poll_t ring_buffer_poll_wait(struct ring_buffer *buffer, int cpu, + poll_wait(filp, &rbwork->full_waiters, poll_table); + + raw_spin_lock_irqsave(&cpu_buffer->reader_lock, flags); +- rbwork->full_waiters_pending = true; + if (!cpu_buffer->shortest_full || + cpu_buffer->shortest_full > full) + cpu_buffer->shortest_full = full; + raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); +- } else { +- poll_wait(filp, &rbwork->waiters, poll_table); +- rbwork->waiters_pending = true; ++ if (full_hit(buffer, cpu, full)) ++ return EPOLLIN | EPOLLRDNORM; ++ /* ++ * Only allow full_waiters_pending update to be seen after ++ * the shortest_full is set. If the writer sees the ++ * full_waiters_pending flag set, it will compare the ++ * amount in the ring buffer to shortest_full. If the amount ++ * in the ring buffer is greater than the shortest_full ++ * percent, it will call the irq_work handler to wake up ++ * this list. The irq_handler will reset shortest_full ++ * back to zero. That's done under the reader_lock, but ++ * the below smp_mb() makes sure that the update to ++ * full_waiters_pending doesn't leak up into the above. ++ */ ++ smp_mb(); ++ rbwork->full_waiters_pending = true; ++ return 0; + } + ++ poll_wait(filp, &rbwork->waiters, poll_table); ++ rbwork->waiters_pending = true; ++ + /* + * There's a tight race between setting the waiters_pending and + * checking if the ring buffer is empty. Once the waiters_pending bit +@@ -786,9 +802,6 @@ __poll_t ring_buffer_poll_wait(struct ring_buffer *buffer, int cpu, + */ + smp_mb(); + +- if (full) +- return full_hit(buffer, cpu, full) ? EPOLLIN | EPOLLRDNORM : 0; +- + if ((cpu == RING_BUFFER_ALL_CPUS && !ring_buffer_empty(buffer)) || + (cpu != RING_BUFFER_ALL_CPUS && !ring_buffer_empty_cpu(buffer, cpu))) + return EPOLLIN | EPOLLRDNORM; +-- +2.43.0 + diff --git a/queue-5.4/ring-buffer-fix-resetting-of-shortest_full.patch b/queue-5.4/ring-buffer-fix-resetting-of-shortest_full.patch new file mode 100644 index 00000000000..3ad0669f82e --- /dev/null +++ b/queue-5.4/ring-buffer-fix-resetting-of-shortest_full.patch @@ -0,0 +1,117 @@ +From 159f0b83e44933572f784ad80af38d0c39fee546 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Mar 2024 15:24:04 -0500 +Subject: ring-buffer: Fix resetting of shortest_full + +From: Steven Rostedt (Google) + +[ Upstream commit 68282dd930ea38b068ce2c109d12405f40df3f93 ] + +The "shortest_full" variable is used to keep track of the waiter that is +waiting for the smallest amount on the ring buffer before being woken up. +When a tasks waits on the ring buffer, it passes in a "full" value that is +a percentage. 0 means wake up on any data. 1-100 means wake up from 1% to +100% full buffer. + +As all waiters are on the same wait queue, the wake up happens for the +waiter with the smallest percentage. + +The problem is that the smallest_full on the cpu_buffer that stores the +smallest amount doesn't get reset when all the waiters are woken up. It +does get reset when the ring buffer is reset (echo > /sys/kernel/tracing/trace). + +This means that tasks may be woken up more often then when they want to +be. Instead, have the shortest_full field get reset just before waking up +all the tasks. If the tasks wait again, they will update the shortest_full +before sleeping. + +Also add locking around setting of shortest_full in the poll logic, and +change "work" to "rbwork" to match the variable name for rb_irq_work +structures that are used in other places. + +Link: https://lore.kernel.org/linux-trace-kernel/20240308202431.948914369@goodmis.org + +Cc: stable@vger.kernel.org +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Linus Torvalds +Cc: linke li +Cc: Rabin Vincent +Fixes: 2c2b0a78b3739 ("ring-buffer: Add percentage of ring buffer full to wake up reader") +Signed-off-by: Steven Rostedt (Google) +Stable-dep-of: 8145f1c35fa6 ("ring-buffer: Fix full_waiters_pending in poll") +Signed-off-by: Sasha Levin +--- + kernel/trace/ring_buffer.c | 30 +++++++++++++++++++++++------- + 1 file changed, 23 insertions(+), 7 deletions(-) + +diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c +index ed505c6de7cae..a9c90088af780 100644 +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -601,8 +601,19 @@ static void rb_wake_up_waiters(struct irq_work *work) + + wake_up_all(&rbwork->waiters); + if (rbwork->full_waiters_pending || rbwork->wakeup_full) { ++ /* Only cpu_buffer sets the above flags */ ++ struct ring_buffer_per_cpu *cpu_buffer = ++ container_of(rbwork, struct ring_buffer_per_cpu, irq_work); ++ ++ /* Called from interrupt context */ ++ raw_spin_lock(&cpu_buffer->reader_lock); + rbwork->wakeup_full = false; + rbwork->full_waiters_pending = false; ++ ++ /* Waking up all waiters, they will reset the shortest full */ ++ cpu_buffer->shortest_full = 0; ++ raw_spin_unlock(&cpu_buffer->reader_lock); ++ + wake_up_all(&rbwork->full_waiters); + } + } +@@ -731,28 +742,33 @@ __poll_t ring_buffer_poll_wait(struct ring_buffer *buffer, int cpu, + struct file *filp, poll_table *poll_table, int full) + { + struct ring_buffer_per_cpu *cpu_buffer; +- struct rb_irq_work *work; ++ struct rb_irq_work *rbwork; + + if (cpu == RING_BUFFER_ALL_CPUS) { +- work = &buffer->irq_work; ++ rbwork = &buffer->irq_work; + full = 0; + } else { + if (!cpumask_test_cpu(cpu, buffer->cpumask)) + return EPOLLERR; + + cpu_buffer = buffer->buffers[cpu]; +- work = &cpu_buffer->irq_work; ++ rbwork = &cpu_buffer->irq_work; + } + + if (full) { +- poll_wait(filp, &work->full_waiters, poll_table); +- work->full_waiters_pending = true; ++ unsigned long flags; ++ ++ poll_wait(filp, &rbwork->full_waiters, poll_table); ++ ++ raw_spin_lock_irqsave(&cpu_buffer->reader_lock, flags); ++ rbwork->full_waiters_pending = true; + if (!cpu_buffer->shortest_full || + cpu_buffer->shortest_full > full) + cpu_buffer->shortest_full = full; ++ raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); + } else { +- poll_wait(filp, &work->waiters, poll_table); +- work->waiters_pending = true; ++ poll_wait(filp, &rbwork->waiters, poll_table); ++ rbwork->waiters_pending = true; + } + + /* +-- +2.43.0 + diff --git a/queue-5.4/s390-zcrypt-fix-reference-counting-on-zcrypt-card-ob.patch b/queue-5.4/s390-zcrypt-fix-reference-counting-on-zcrypt-card-ob.patch new file mode 100644 index 00000000000..33426139c0e --- /dev/null +++ b/queue-5.4/s390-zcrypt-fix-reference-counting-on-zcrypt-card-ob.patch @@ -0,0 +1,124 @@ +From cee319a8380ca8519cdb409461b3c353856b566d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Feb 2024 15:20:09 +0100 +Subject: s390/zcrypt: fix reference counting on zcrypt card objects + +From: Harald Freudenberger + +[ Upstream commit 50ed48c80fecbe17218afed4f8bed005c802976c ] + +Tests with hot-plugging crytpo cards on KVM guests with debug +kernel build revealed an use after free for the load field of +the struct zcrypt_card. The reason was an incorrect reference +handling of the zcrypt card object which could lead to a free +of the zcrypt card object while it was still in use. + +This is an example of the slab message: + + kernel: 0x00000000885a7512-0x00000000885a7513 @offset=1298. First byte 0x68 instead of 0x6b + kernel: Allocated in zcrypt_card_alloc+0x36/0x70 [zcrypt] age=18046 cpu=3 pid=43 + kernel: kmalloc_trace+0x3f2/0x470 + kernel: zcrypt_card_alloc+0x36/0x70 [zcrypt] + kernel: zcrypt_cex4_card_probe+0x26/0x380 [zcrypt_cex4] + kernel: ap_device_probe+0x15c/0x290 + kernel: really_probe+0xd2/0x468 + kernel: driver_probe_device+0x40/0xf0 + kernel: __device_attach_driver+0xc0/0x140 + kernel: bus_for_each_drv+0x8c/0xd0 + kernel: __device_attach+0x114/0x198 + kernel: bus_probe_device+0xb4/0xc8 + kernel: device_add+0x4d2/0x6e0 + kernel: ap_scan_adapter+0x3d0/0x7c0 + kernel: ap_scan_bus+0x5a/0x3b0 + kernel: ap_scan_bus_wq_callback+0x40/0x60 + kernel: process_one_work+0x26e/0x620 + kernel: worker_thread+0x21c/0x440 + kernel: Freed in zcrypt_card_put+0x54/0x80 [zcrypt] age=9024 cpu=3 pid=43 + kernel: kfree+0x37e/0x418 + kernel: zcrypt_card_put+0x54/0x80 [zcrypt] + kernel: ap_device_remove+0x4c/0xe0 + kernel: device_release_driver_internal+0x1c4/0x270 + kernel: bus_remove_device+0x100/0x188 + kernel: device_del+0x164/0x3c0 + kernel: device_unregister+0x30/0x90 + kernel: ap_scan_adapter+0xc8/0x7c0 + kernel: ap_scan_bus+0x5a/0x3b0 + kernel: ap_scan_bus_wq_callback+0x40/0x60 + kernel: process_one_work+0x26e/0x620 + kernel: worker_thread+0x21c/0x440 + kernel: kthread+0x150/0x168 + kernel: __ret_from_fork+0x3c/0x58 + kernel: ret_from_fork+0xa/0x30 + kernel: Slab 0x00000372022169c0 objects=20 used=18 fp=0x00000000885a7c88 flags=0x3ffff00000000a00(workingset|slab|node=0|zone=1|lastcpupid=0x1ffff) + kernel: Object 0x00000000885a74b8 @offset=1208 fp=0x00000000885a7c88 + kernel: Redzone 00000000885a74b0: bb bb bb bb bb bb bb bb ........ + kernel: Object 00000000885a74b8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk + kernel: Object 00000000885a74c8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk + kernel: Object 00000000885a74d8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk + kernel: Object 00000000885a74e8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk + kernel: Object 00000000885a74f8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk + kernel: Object 00000000885a7508: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 68 4b 6b 6b 6b a5 kkkkkkkkkkhKkkk. + kernel: Redzone 00000000885a7518: bb bb bb bb bb bb bb bb ........ + kernel: Padding 00000000885a756c: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZ + kernel: CPU: 0 PID: 387 Comm: systemd-udevd Not tainted 6.8.0-HF #2 + kernel: Hardware name: IBM 3931 A01 704 (KVM/Linux) + kernel: Call Trace: + kernel: [<00000000ca5ab5b8>] dump_stack_lvl+0x90/0x120 + kernel: [<00000000c99d78bc>] check_bytes_and_report+0x114/0x140 + kernel: [<00000000c99d53cc>] check_object+0x334/0x3f8 + kernel: [<00000000c99d820c>] alloc_debug_processing+0xc4/0x1f8 + kernel: [<00000000c99d852e>] get_partial_node.part.0+0x1ee/0x3e0 + kernel: [<00000000c99d94ec>] ___slab_alloc+0xaf4/0x13c8 + kernel: [<00000000c99d9e38>] __slab_alloc.constprop.0+0x78/0xb8 + kernel: [<00000000c99dc8dc>] __kmalloc+0x434/0x590 + kernel: [<00000000c9b4c0ce>] ext4_htree_store_dirent+0x4e/0x1c0 + kernel: [<00000000c9b908a2>] htree_dirblock_to_tree+0x17a/0x3f0 + kernel: [<00000000c9b919dc>] ext4_htree_fill_tree+0x134/0x400 + kernel: [<00000000c9b4b3d0>] ext4_dx_readdir+0x160/0x2f0 + kernel: [<00000000c9b4bedc>] ext4_readdir+0x5f4/0x760 + kernel: [<00000000c9a7efc4>] iterate_dir+0xb4/0x280 + kernel: [<00000000c9a7f1ea>] __do_sys_getdents64+0x5a/0x120 + kernel: [<00000000ca5d6946>] __do_syscall+0x256/0x310 + kernel: [<00000000ca5eea10>] system_call+0x70/0x98 + kernel: INFO: lockdep is turned off. + kernel: FIX kmalloc-96: Restoring Poison 0x00000000885a7512-0x00000000885a7513=0x6b + kernel: FIX kmalloc-96: Marking all objects used + +The fix is simple: Before use of the queue not only the queue object +but also the card object needs to increase it's reference count +with a call to zcrypt_card_get(). Similar after use of the queue +not only the queue but also the card object's reference count is +decreased with zcrypt_card_put(). + +Signed-off-by: Harald Freudenberger +Reviewed-by: Holger Dengler +Cc: stable@vger.kernel.org +Signed-off-by: Heiko Carstens +Signed-off-by: Sasha Levin +--- + drivers/s390/crypto/zcrypt_api.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c +index f376dfcd7dbeb..69c1df560e2f1 100644 +--- a/drivers/s390/crypto/zcrypt_api.c ++++ b/drivers/s390/crypto/zcrypt_api.c +@@ -574,6 +574,7 @@ static inline struct zcrypt_queue *zcrypt_pick_queue(struct zcrypt_card *zc, + { + if (!zq || !try_module_get(zq->queue->ap_dev.drv->driver.owner)) + return NULL; ++ zcrypt_card_get(zc); + zcrypt_queue_get(zq); + get_device(&zq->queue->ap_dev.device); + atomic_add(weight, &zc->load); +@@ -593,6 +594,7 @@ static inline void zcrypt_drop_queue(struct zcrypt_card *zc, + atomic_sub(weight, &zq->load); + put_device(&zq->queue->ap_dev.device); + zcrypt_queue_put(zq); ++ zcrypt_card_put(zc); + module_put(mod); + } + +-- +2.43.0 + diff --git a/queue-5.4/selftests-mqueue-set-timeout-to-180-seconds.patch b/queue-5.4/selftests-mqueue-set-timeout-to-180-seconds.patch new file mode 100644 index 00000000000..e269b8ee8e1 --- /dev/null +++ b/queue-5.4/selftests-mqueue-set-timeout-to-180-seconds.patch @@ -0,0 +1,35 @@ +From 1342ff7226d2b289e5f43c7619c2a8a25bcddaed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Feb 2024 16:08:02 -0800 +Subject: selftests/mqueue: Set timeout to 180 seconds + +From: SeongJae Park + +[ Upstream commit 85506aca2eb4ea41223c91c5fe25125953c19b13 ] + +While mq_perf_tests runs with the default kselftest timeout limit, which +is 45 seconds, the test takes about 60 seconds to complete on i3.metal +AWS instances. Hence, the test always times out. Increase the timeout +to 180 seconds. + +Fixes: 852c8cbf34d3 ("selftests/kselftest/runner.sh: Add 45 second timeout per test") +Cc: # 5.4.x +Signed-off-by: SeongJae Park +Reviewed-by: Kees Cook +Signed-off-by: Shuah Khan +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/mqueue/setting | 1 + + 1 file changed, 1 insertion(+) + create mode 100644 tools/testing/selftests/mqueue/setting + +diff --git a/tools/testing/selftests/mqueue/setting b/tools/testing/selftests/mqueue/setting +new file mode 100644 +index 0000000000000..a953c96aa16e1 +--- /dev/null ++++ b/tools/testing/selftests/mqueue/setting +@@ -0,0 +1 @@ ++timeout=180 +-- +2.43.0 + diff --git a/queue-5.4/serial-max310x-fix-null-pointer-dereference-in-i2c-i.patch b/queue-5.4/serial-max310x-fix-null-pointer-dereference-in-i2c-i.patch new file mode 100644 index 00000000000..e24d851dae1 --- /dev/null +++ b/queue-5.4/serial-max310x-fix-null-pointer-dereference-in-i2c-i.patch @@ -0,0 +1,62 @@ +From 6cbdbcb97347d63b9c5f862e0578e77070493500 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Jan 2024 10:21:57 -0500 +Subject: serial: max310x: fix NULL pointer dereference in I2C instantiation + +From: Hugo Villeneuve + +[ Upstream commit 0d27056c24efd3d63a03f3edfbcfc4827086b110 ] + +When trying to instantiate a max14830 device from userspace: + + echo max14830 0x60 > /sys/bus/i2c/devices/i2c-2/new_device + +we get the following error: + + Unable to handle kernel NULL pointer dereference at virtual address... + ... + Call trace: + max310x_i2c_probe+0x48/0x170 [max310x] + i2c_device_probe+0x150/0x2a0 + ... + +Add check for validity of devtype to prevent the error, and abort probe +with a meaningful error message. + +Fixes: 2e1f2d9a9bdb ("serial: max310x: implement I2C support") +Cc: stable@vger.kernel.org +Reviewed-by: Andy Shevchenko +Signed-off-by: Hugo Villeneuve +Link: https://lore.kernel.org/r/20240118152213.2644269-2-hugo@hugovil.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/max310x.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c +index 5570fd3b84e15..363b68555fe62 100644 +--- a/drivers/tty/serial/max310x.c ++++ b/drivers/tty/serial/max310x.c +@@ -1636,13 +1636,16 @@ static unsigned short max310x_i2c_slave_addr(unsigned short addr, + + static int max310x_i2c_probe(struct i2c_client *client) + { +- const struct max310x_devtype *devtype = +- device_get_match_data(&client->dev); ++ const struct max310x_devtype *devtype; + struct i2c_client *port_client; + struct regmap *regmaps[4]; + unsigned int i; + u8 port_addr; + ++ devtype = device_get_match_data(&client->dev); ++ if (!devtype) ++ return dev_err_probe(&client->dev, -ENODEV, "Failed to match device\n"); ++ + if (client->addr < devtype->slave_addr.min || + client->addr > devtype->slave_addr.max) + return dev_err_probe(&client->dev, -EINVAL, +-- +2.43.0 + diff --git a/queue-5.4/series b/queue-5.4/series index aca95c98c55..4b0260389f6 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -1,3 +1,79 @@ documentation-hw-vuln-update-spectre-doc.patch x86-cpu-support-amd-automatic-ibrs.patch x86-bugs-use-sysfs_emit.patch +timers-update-kernel-doc-for-various-functions.patch +timers-use-del_timer_sync-even-on-up.patch +timers-rename-del_timer_sync-to-timer_delete_sync.patch +wifi-brcmfmac-fix-use-after-free-bug-in-brcmf_cfg802.patch +media-staging-ipu3-imgu-set-fields-before-media_enti.patch +clk-qcom-gcc-sdm845-add-soft-dependency-on-rpmhpd.patch +smack-set-smack64transmute-only-for-dirs-in-smack_in.patch +smack-handle-smack64transmute-in-smack_inode_setsecu.patch +arm-dts-mmp2-brownstone-don-t-redeclare-phandle-refe.patch +arm-dts-marvell-fix-maxium-maxim-typo-in-brownstone-.patch +serial-max310x-fix-null-pointer-dereference-in-i2c-i.patch +media-xc4000-fix-atomicity-violation-in-xc4000_get_f.patch +kvm-always-flush-async-pf-workqueue-when-vcpu-is-bei.patch +sparc64-nmi-watchdog-fix-return-value-of-__setup-han.patch +sparc-vdso-fix-return-value-of-__setup-handler.patch +crypto-qat-fix-double-free-during-reset.patch +crypto-qat-resolve-race-condition-during-aer-recover.patch +selftests-mqueue-set-timeout-to-180-seconds.patch +ext4-correct-best-extent-lstart-adjustment-logic.patch +fat-fix-uninitialized-field-in-nostale-filehandles.patch +ubifs-set-page-uptodate-in-the-correct-place.patch +ubi-check-for-too-small-leb-size-in-vtbl-code.patch +ubi-correct-the-calculation-of-fastmap-size.patch +mtd-rawnand-meson-fix-scrambling-mode-value-in-comma.patch +parisc-do-not-hardcode-registers-in-checksum-functio.patch +parisc-fix-ip_fast_csum.patch +parisc-fix-csum_ipv6_magic-on-32-bit-systems.patch +parisc-fix-csum_ipv6_magic-on-64-bit-systems.patch +parisc-strip-upper-32-bit-of-sum-in-csum_ipv6_magic-.patch +pm-suspend-set-mem_sleep_current-during-kernel-comma.patch +clk-qcom-gcc-ipq8074-fix-terminating-of-frequency-ta.patch +clk-qcom-mmcc-apq8084-fix-terminating-of-frequency-t.patch +clk-qcom-mmcc-msm8974-fix-terminating-of-frequency-t.patch +powerpc-fsl-fix-mfpmr-build-errors-with-newer-binuti.patch +usb-serial-ftdi_sio-add-support-for-gmc-z216c-adapte.patch +usb-serial-add-device-id-for-verifone-adapter.patch +usb-serial-cp210x-add-id-for-mgp-instruments-pds100.patch +usb-serial-option-add-meig-smart-slm320-product.patch +usb-serial-cp210x-add-pid-vid-for-tdk-nc0110013m-and.patch +pm-sleep-wakeirq-fix-wake-irq-warning-in-system-susp.patch +mmc-tmio-avoid-concurrent-runs-of-mmc_request_done.patch +fuse-store-fuse_conn-in-fuse_req.patch +fuse-drop-fuse_conn-parameter-where-possible.patch +fuse-don-t-unhash-root.patch +btrfs-fix-off-by-one-chunk-length-calculation-at-con.patch +pci-drop-pci_device_remove-test-of-pci_dev-driver.patch +pci-pm-drain-runtime-idle-callbacks-before-driver-re.patch +revert-revert-md-raid5-wait-for-md_sb_change_pending.patch +dm-raid-fix-lockdep-waring-in-pers-hot_add_disk.patch +mmc-core-fix-switch-on-gp3-partition.patch +hwmon-amc6821-add-of_match-table.patch +ext4-fix-corruption-during-on-line-resize.patch +firmware-meson_sm-rework-driver-as-a-proper-platform.patch +nvmem-meson-efuse-fix-function-pointer-type-mismatch.patch +slimbus-core-remove-usage-of-the-deprecated-ida_simp.patch +speakup-fix-8bit-characters-from-direct-synth.patch +kbuild-move-wenum-compare-conditional-enum-conversio.patch +vfio-platform-disable-virqfds-on-cleanup.patch +ring-buffer-fix-resetting-of-shortest_full.patch +ring-buffer-fix-full_waiters_pending-in-poll.patch +soc-fsl-qbman-always-disable-interrupts-when-taking-.patch +soc-fsl-qbman-add-helper-for-sanity-checking-cgr-ops.patch +soc-fsl-qbman-add-cgr-update-function.patch +soc-fsl-qbman-use-raw-spinlock-for-cgr_lock.patch +s390-zcrypt-fix-reference-counting-on-zcrypt-card-ob.patch +drm-exynos-do-not-return-negative-values-from-.get_m.patch +drm-imx-ipuv3-do-not-return-negative-values-from-.ge.patch +drm-vc4-hdmi-do-not-return-negative-values-from-.get.patch +memtest-use-read-write-_once-in-memory-scanning.patch +nilfs2-fix-failure-to-detect-dat-corruption-in-btree.patch +nilfs2-use-a-more-common-logging-style.patch +nilfs2-prevent-kernel-bug-at-submit_bh_wbc.patch +x86-cpu-amd-update-the-zenbleed-microcode-revisions.patch +ahci-asm1064-correct-count-of-reported-ports.patch +ahci-asm1064-asm1166-don-t-limit-reported-ports.patch +dm-snapshot-fix-lockup-in-dm_exception_table_exit.patch diff --git a/queue-5.4/slimbus-core-remove-usage-of-the-deprecated-ida_simp.patch b/queue-5.4/slimbus-core-remove-usage-of-the-deprecated-ida_simp.patch new file mode 100644 index 00000000000..781d73bc208 --- /dev/null +++ b/queue-5.4/slimbus-core-remove-usage-of-the-deprecated-ida_simp.patch @@ -0,0 +1,45 @@ +From 25a714379a4f2db9b08e8f2def20f07d2105a37e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 24 Feb 2024 11:41:37 +0000 +Subject: slimbus: core: Remove usage of the deprecated ida_simple_xx() API + +From: Christophe JAILLET + +[ Upstream commit 89ffa4cccec54467446f141a79b9e36893079fb8 ] + +ida_alloc() and ida_free() should be preferred to the deprecated +ida_simple_get() and ida_simple_remove(). + +Note that the upper limit of ida_simple_get() is exclusive, but the one of +ida_alloc_range() is inclusive. So change this change allows one more +device. Previously address 0xFE was never used. + +Fixes: 46a2bb5a7f7e ("slimbus: core: Add slim controllers support") +Cc: Stable@vger.kernel.org +Signed-off-by: Christophe JAILLET +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240224114137.85781-2-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/slimbus/core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/slimbus/core.c b/drivers/slimbus/core.c +index 130c798921b5d..e3f3ce6dc7e74 100644 +--- a/drivers/slimbus/core.c ++++ b/drivers/slimbus/core.c +@@ -439,8 +439,8 @@ static int slim_device_alloc_laddr(struct slim_device *sbdev, + if (ret < 0) + goto err; + } else if (report_present) { +- ret = ida_simple_get(&ctrl->laddr_ida, +- 0, SLIM_LA_MANAGER - 1, GFP_KERNEL); ++ ret = ida_alloc_max(&ctrl->laddr_ida, ++ SLIM_LA_MANAGER - 1, GFP_KERNEL); + if (ret < 0) + goto err; + +-- +2.43.0 + diff --git a/queue-5.4/smack-handle-smack64transmute-in-smack_inode_setsecu.patch b/queue-5.4/smack-handle-smack64transmute-in-smack_inode_setsecu.patch new file mode 100644 index 00000000000..82bf8be35b2 --- /dev/null +++ b/queue-5.4/smack-handle-smack64transmute-in-smack_inode_setsecu.patch @@ -0,0 +1,44 @@ +From 1f65e09d10b7acbfdc2a827677532b0bde616b2c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Nov 2023 10:01:22 +0100 +Subject: smack: Handle SMACK64TRANSMUTE in smack_inode_setsecurity() + +From: Roberto Sassu + +[ Upstream commit ac02f007d64eb2769d0bde742aac4d7a5fc6e8a5 ] + +If the SMACK64TRANSMUTE xattr is provided, and the inode is a directory, +update the in-memory inode flags by setting SMK_INODE_TRANSMUTE. + +Cc: stable@vger.kernel.org +Fixes: 5c6d1125f8db ("Smack: Transmute labels on specified directories") # v2.6.38.x +Signed-off-by: Roberto Sassu +Signed-off-by: Casey Schaufler +Signed-off-by: Sasha Levin +--- + security/smack/smack_lsm.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c +index 65743be5b30f5..072ce1ef6efb7 100644 +--- a/security/smack/smack_lsm.c ++++ b/security/smack/smack_lsm.c +@@ -2717,6 +2717,15 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, + if (value == NULL || size > SMK_LONGLABEL || size == 0) + return -EINVAL; + ++ if (strcmp(name, XATTR_SMACK_TRANSMUTE) == 0) { ++ if (!S_ISDIR(inode->i_mode) || size != TRANS_TRUE_SIZE || ++ strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0) ++ return -EINVAL; ++ ++ nsp->smk_flags |= SMK_INODE_TRANSMUTE; ++ return 0; ++ } ++ + skp = smk_import_entry(value, size); + if (IS_ERR(skp)) + return PTR_ERR(skp); +-- +2.43.0 + diff --git a/queue-5.4/smack-set-smack64transmute-only-for-dirs-in-smack_in.patch b/queue-5.4/smack-set-smack64transmute-only-for-dirs-in-smack_in.patch new file mode 100644 index 00000000000..c22637b79a8 --- /dev/null +++ b/queue-5.4/smack-set-smack64transmute-only-for-dirs-in-smack_in.patch @@ -0,0 +1,38 @@ +From 6181e4fddf0626f3326dd7c2c29fbfd8d805e162 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Nov 2023 10:01:21 +0100 +Subject: smack: Set SMACK64TRANSMUTE only for dirs in smack_inode_setxattr() + +From: Roberto Sassu + +[ Upstream commit 9c82169208dde516510aaba6bbd8b13976690c5d ] + +Since the SMACK64TRANSMUTE xattr makes sense only for directories, enforce +this restriction in smack_inode_setxattr(). + +Cc: stable@vger.kernel.org +Fixes: 5c6d1125f8db ("Smack: Transmute labels on specified directories") # v2.6.38.x +Signed-off-by: Roberto Sassu +Signed-off-by: Casey Schaufler +Signed-off-by: Sasha Levin +--- + security/smack/smack_lsm.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c +index 6f2613f874fa9..65743be5b30f5 100644 +--- a/security/smack/smack_lsm.c ++++ b/security/smack/smack_lsm.c +@@ -1290,7 +1290,8 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, + check_star = 1; + } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { + check_priv = 1; +- if (size != TRANS_TRUE_SIZE || ++ if (!S_ISDIR(d_backing_inode(dentry)->i_mode) || ++ size != TRANS_TRUE_SIZE || + strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0) + rc = -EINVAL; + } else +-- +2.43.0 + diff --git a/queue-5.4/soc-fsl-qbman-add-cgr-update-function.patch b/queue-5.4/soc-fsl-qbman-add-cgr-update-function.patch new file mode 100644 index 00000000000..55c8b9a5a4f --- /dev/null +++ b/queue-5.4/soc-fsl-qbman-add-cgr-update-function.patch @@ -0,0 +1,107 @@ +From f7b06ebac72817826ed8775116e7504d0ea57fb0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Sep 2022 17:57:35 -0400 +Subject: soc: fsl: qbman: Add CGR update function + +From: Sean Anderson + +[ Upstream commit 914f8b228ede709274b8c80514b352248ec9da00 ] + +This adds a function to update a CGR with new parameters. qman_create_cgr +can almost be used for this (with flags=0), but it's not suitable because +it also registers the callback function. The _safe variant was modeled off +of qman_cgr_delete_safe. However, we handle multiple arguments and a return +value. + +Signed-off-by: Sean Anderson +Acked-by: Camelia Groza +Signed-off-by: David S. Miller +Stable-dep-of: fbec4e7fed89 ("soc: fsl: qbman: Use raw spinlock for cgr_lock") +Signed-off-by: Sasha Levin +--- + drivers/soc/fsl/qbman/qman.c | 48 ++++++++++++++++++++++++++++++++++++ + include/soc/fsl/qman.h | 9 +++++++ + 2 files changed, 57 insertions(+) + +diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c +index e31d33d000526..52327f0dab986 100644 +--- a/drivers/soc/fsl/qbman/qman.c ++++ b/drivers/soc/fsl/qbman/qman.c +@@ -2566,6 +2566,54 @@ void qman_delete_cgr_safe(struct qman_cgr *cgr) + } + EXPORT_SYMBOL(qman_delete_cgr_safe); + ++static int qman_update_cgr(struct qman_cgr *cgr, struct qm_mcc_initcgr *opts) ++{ ++ int ret; ++ unsigned long irqflags; ++ struct qman_portal *p = qman_cgr_get_affine_portal(cgr); ++ ++ if (!p) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&p->cgr_lock, irqflags); ++ ret = qm_modify_cgr(cgr, 0, opts); ++ spin_unlock_irqrestore(&p->cgr_lock, irqflags); ++ put_affine_portal(); ++ return ret; ++} ++ ++struct update_cgr_params { ++ struct qman_cgr *cgr; ++ struct qm_mcc_initcgr *opts; ++ int ret; ++}; ++ ++static void qman_update_cgr_smp_call(void *p) ++{ ++ struct update_cgr_params *params = p; ++ ++ params->ret = qman_update_cgr(params->cgr, params->opts); ++} ++ ++int qman_update_cgr_safe(struct qman_cgr *cgr, struct qm_mcc_initcgr *opts) ++{ ++ struct update_cgr_params params = { ++ .cgr = cgr, ++ .opts = opts, ++ }; ++ ++ preempt_disable(); ++ if (qman_cgr_cpus[cgr->cgrid] != smp_processor_id()) ++ smp_call_function_single(qman_cgr_cpus[cgr->cgrid], ++ qman_update_cgr_smp_call, ¶ms, ++ true); ++ else ++ params.ret = qman_update_cgr(cgr, opts); ++ preempt_enable(); ++ return params.ret; ++} ++EXPORT_SYMBOL(qman_update_cgr_safe); ++ + /* Cleanup FQs */ + + static int _qm_mr_consume_and_match_verb(struct qm_portal *p, int v) +diff --git a/include/soc/fsl/qman.h b/include/soc/fsl/qman.h +index aa31c05a103ad..f9c622027d852 100644 +--- a/include/soc/fsl/qman.h ++++ b/include/soc/fsl/qman.h +@@ -1159,6 +1159,15 @@ int qman_delete_cgr(struct qman_cgr *cgr); + */ + void qman_delete_cgr_safe(struct qman_cgr *cgr); + ++/** ++ * qman_update_cgr_safe - Modifies a congestion group object from any CPU ++ * @cgr: the 'cgr' object to modify ++ * @opts: state of the CGR settings ++ * ++ * This will select the proper CPU and modify the CGR settings. ++ */ ++int qman_update_cgr_safe(struct qman_cgr *cgr, struct qm_mcc_initcgr *opts); ++ + /** + * qman_query_cgr_congested - Queries CGR's congestion status + * @cgr: the 'cgr' object to query +-- +2.43.0 + diff --git a/queue-5.4/soc-fsl-qbman-add-helper-for-sanity-checking-cgr-ops.patch b/queue-5.4/soc-fsl-qbman-add-helper-for-sanity-checking-cgr-ops.patch new file mode 100644 index 00000000000..5e14e295f1b --- /dev/null +++ b/queue-5.4/soc-fsl-qbman-add-helper-for-sanity-checking-cgr-ops.patch @@ -0,0 +1,80 @@ +From 36f2b30bda2babe5670512ab26e4afbdd420c7e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Sep 2022 17:57:34 -0400 +Subject: soc: fsl: qbman: Add helper for sanity checking cgr ops + +From: Sean Anderson + +[ Upstream commit d0e17a4653cebc2c8a20251c837dd1fcec5014d9 ] + +This breaks out/combines get_affine_portal and the cgr sanity check in +preparation for the next commit. No functional change intended. + +Signed-off-by: Sean Anderson +Acked-by: Camelia Groza +Signed-off-by: David S. Miller +Stable-dep-of: fbec4e7fed89 ("soc: fsl: qbman: Use raw spinlock for cgr_lock") +Signed-off-by: Sasha Levin +--- + drivers/soc/fsl/qbman/qman.c | 29 +++++++++++++++++++---------- + 1 file changed, 19 insertions(+), 10 deletions(-) + +diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c +index 53b4cd0fb662d..e31d33d000526 100644 +--- a/drivers/soc/fsl/qbman/qman.c ++++ b/drivers/soc/fsl/qbman/qman.c +@@ -2481,13 +2481,8 @@ int qman_create_cgr(struct qman_cgr *cgr, u32 flags, + } + EXPORT_SYMBOL(qman_create_cgr); + +-int qman_delete_cgr(struct qman_cgr *cgr) ++static struct qman_portal *qman_cgr_get_affine_portal(struct qman_cgr *cgr) + { +- unsigned long irqflags; +- struct qm_mcr_querycgr cgr_state; +- struct qm_mcc_initcgr local_opts; +- int ret = 0; +- struct qman_cgr *i; + struct qman_portal *p = get_affine_portal(); + + if (cgr->chan != p->config->channel) { +@@ -2495,10 +2490,25 @@ int qman_delete_cgr(struct qman_cgr *cgr) + dev_err(p->config->dev, "CGR not owned by current portal"); + dev_dbg(p->config->dev, " create 0x%x, delete 0x%x\n", + cgr->chan, p->config->channel); +- +- ret = -EINVAL; +- goto put_portal; ++ put_affine_portal(); ++ return NULL; + } ++ ++ return p; ++} ++ ++int qman_delete_cgr(struct qman_cgr *cgr) ++{ ++ unsigned long irqflags; ++ struct qm_mcr_querycgr cgr_state; ++ struct qm_mcc_initcgr local_opts; ++ int ret = 0; ++ struct qman_cgr *i; ++ struct qman_portal *p = qman_cgr_get_affine_portal(cgr); ++ ++ if (!p) ++ return -EINVAL; ++ + memset(&local_opts, 0, sizeof(struct qm_mcc_initcgr)); + spin_lock_irqsave(&p->cgr_lock, irqflags); + list_del(&cgr->node); +@@ -2526,7 +2536,6 @@ int qman_delete_cgr(struct qman_cgr *cgr) + list_add(&cgr->node, &p->cgr_cbs); + release_lock: + spin_unlock_irqrestore(&p->cgr_lock, irqflags); +-put_portal: + put_affine_portal(); + return ret; + } +-- +2.43.0 + diff --git a/queue-5.4/soc-fsl-qbman-always-disable-interrupts-when-taking-.patch b/queue-5.4/soc-fsl-qbman-always-disable-interrupts-when-taking-.patch new file mode 100644 index 00000000000..69e6ef29618 --- /dev/null +++ b/queue-5.4/soc-fsl-qbman-always-disable-interrupts-when-taking-.patch @@ -0,0 +1,73 @@ +From 1c17f923ba1446a1d07b8191aac3d4b73103f2fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Mar 2024 12:38:29 -0400 +Subject: soc: fsl: qbman: Always disable interrupts when taking cgr_lock + +From: Sean Anderson + +[ Upstream commit 584c2a9184a33a40fceee838f856de3cffa19be3 ] + +smp_call_function_single disables IRQs when executing the callback. To +prevent deadlocks, we must disable IRQs when taking cgr_lock elsewhere. +This is already done by qman_update_cgr and qman_delete_cgr; fix the +other lockers. + +Fixes: 96f413f47677 ("soc/fsl/qbman: fix issue in qman_delete_cgr_safe()") +CC: stable@vger.kernel.org +Signed-off-by: Sean Anderson +Reviewed-by: Camelia Groza +Tested-by: Vladimir Oltean +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/soc/fsl/qbman/qman.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c +index 95f9e48052452..53b4cd0fb662d 100644 +--- a/drivers/soc/fsl/qbman/qman.c ++++ b/drivers/soc/fsl/qbman/qman.c +@@ -1461,11 +1461,11 @@ static void qm_congestion_task(struct work_struct *work) + union qm_mc_result *mcr; + struct qman_cgr *cgr; + +- spin_lock(&p->cgr_lock); ++ spin_lock_irq(&p->cgr_lock); + qm_mc_start(&p->p); + qm_mc_commit(&p->p, QM_MCC_VERB_QUERYCONGESTION); + if (!qm_mc_result_timeout(&p->p, &mcr)) { +- spin_unlock(&p->cgr_lock); ++ spin_unlock_irq(&p->cgr_lock); + dev_crit(p->config->dev, "QUERYCONGESTION timeout\n"); + qman_p_irqsource_add(p, QM_PIRQ_CSCI); + return; +@@ -1481,7 +1481,7 @@ static void qm_congestion_task(struct work_struct *work) + list_for_each_entry(cgr, &p->cgr_cbs, node) + if (cgr->cb && qman_cgrs_get(&c, cgr->cgrid)) + cgr->cb(p, cgr, qman_cgrs_get(&rr, cgr->cgrid)); +- spin_unlock(&p->cgr_lock); ++ spin_unlock_irq(&p->cgr_lock); + qman_p_irqsource_add(p, QM_PIRQ_CSCI); + } + +@@ -2438,7 +2438,7 @@ int qman_create_cgr(struct qman_cgr *cgr, u32 flags, + preempt_enable(); + + cgr->chan = p->config->channel; +- spin_lock(&p->cgr_lock); ++ spin_lock_irq(&p->cgr_lock); + + if (opts) { + struct qm_mcc_initcgr local_opts = *opts; +@@ -2475,7 +2475,7 @@ int qman_create_cgr(struct qman_cgr *cgr, u32 flags, + qman_cgrs_get(&p->cgrs[1], cgr->cgrid)) + cgr->cb(p, cgr, 1); + out: +- spin_unlock(&p->cgr_lock); ++ spin_unlock_irq(&p->cgr_lock); + put_affine_portal(); + return ret; + } +-- +2.43.0 + diff --git a/queue-5.4/soc-fsl-qbman-use-raw-spinlock-for-cgr_lock.patch b/queue-5.4/soc-fsl-qbman-use-raw-spinlock-for-cgr_lock.patch new file mode 100644 index 00000000000..7a748c03220 --- /dev/null +++ b/queue-5.4/soc-fsl-qbman-use-raw-spinlock-for-cgr_lock.patch @@ -0,0 +1,132 @@ +From 5416903522a8e4d81bafa69e3848ad9823618da1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Mar 2024 12:38:30 -0400 +Subject: soc: fsl: qbman: Use raw spinlock for cgr_lock + +From: Sean Anderson + +[ Upstream commit fbec4e7fed89b579f2483041fabf9650fb0dd6bc ] + +smp_call_function always runs its callback in hard IRQ context, even on +PREEMPT_RT, where spinlocks can sleep. So we need to use a raw spinlock +for cgr_lock to ensure we aren't waiting on a sleeping task. + +Although this bug has existed for a while, it was not apparent until +commit ef2a8d5478b9 ("net: dpaa: Adjust queue depth on rate change") +which invokes smp_call_function_single via qman_update_cgr_safe every +time a link goes up or down. + +Fixes: 96f413f47677 ("soc/fsl/qbman: fix issue in qman_delete_cgr_safe()") +CC: stable@vger.kernel.org +Reported-by: Vladimir Oltean +Closes: https://lore.kernel.org/all/20230323153935.nofnjucqjqnz34ej@skbuf/ +Reported-by: Steffen Trumtrar +Closes: https://lore.kernel.org/linux-arm-kernel/87wmsyvclu.fsf@pengutronix.de/ +Signed-off-by: Sean Anderson +Reviewed-by: Camelia Groza +Tested-by: Vladimir Oltean +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/soc/fsl/qbman/qman.c | 25 ++++++++++++++----------- + 1 file changed, 14 insertions(+), 11 deletions(-) + +diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c +index 52327f0dab986..5144b8c66ac46 100644 +--- a/drivers/soc/fsl/qbman/qman.c ++++ b/drivers/soc/fsl/qbman/qman.c +@@ -996,7 +996,7 @@ struct qman_portal { + /* linked-list of CSCN handlers. */ + struct list_head cgr_cbs; + /* list lock */ +- spinlock_t cgr_lock; ++ raw_spinlock_t cgr_lock; + struct work_struct congestion_work; + struct work_struct mr_work; + char irqname[MAX_IRQNAME]; +@@ -1286,7 +1286,7 @@ static int qman_create_portal(struct qman_portal *portal, + /* if the given mask is NULL, assume all CGRs can be seen */ + qman_cgrs_fill(&portal->cgrs[0]); + INIT_LIST_HEAD(&portal->cgr_cbs); +- spin_lock_init(&portal->cgr_lock); ++ raw_spin_lock_init(&portal->cgr_lock); + INIT_WORK(&portal->congestion_work, qm_congestion_task); + INIT_WORK(&portal->mr_work, qm_mr_process_task); + portal->bits = 0; +@@ -1461,11 +1461,14 @@ static void qm_congestion_task(struct work_struct *work) + union qm_mc_result *mcr; + struct qman_cgr *cgr; + +- spin_lock_irq(&p->cgr_lock); ++ /* ++ * FIXME: QM_MCR_TIMEOUT is 10ms, which is too long for a raw spinlock! ++ */ ++ raw_spin_lock_irq(&p->cgr_lock); + qm_mc_start(&p->p); + qm_mc_commit(&p->p, QM_MCC_VERB_QUERYCONGESTION); + if (!qm_mc_result_timeout(&p->p, &mcr)) { +- spin_unlock_irq(&p->cgr_lock); ++ raw_spin_unlock_irq(&p->cgr_lock); + dev_crit(p->config->dev, "QUERYCONGESTION timeout\n"); + qman_p_irqsource_add(p, QM_PIRQ_CSCI); + return; +@@ -1481,7 +1484,7 @@ static void qm_congestion_task(struct work_struct *work) + list_for_each_entry(cgr, &p->cgr_cbs, node) + if (cgr->cb && qman_cgrs_get(&c, cgr->cgrid)) + cgr->cb(p, cgr, qman_cgrs_get(&rr, cgr->cgrid)); +- spin_unlock_irq(&p->cgr_lock); ++ raw_spin_unlock_irq(&p->cgr_lock); + qman_p_irqsource_add(p, QM_PIRQ_CSCI); + } + +@@ -2438,7 +2441,7 @@ int qman_create_cgr(struct qman_cgr *cgr, u32 flags, + preempt_enable(); + + cgr->chan = p->config->channel; +- spin_lock_irq(&p->cgr_lock); ++ raw_spin_lock_irq(&p->cgr_lock); + + if (opts) { + struct qm_mcc_initcgr local_opts = *opts; +@@ -2475,7 +2478,7 @@ int qman_create_cgr(struct qman_cgr *cgr, u32 flags, + qman_cgrs_get(&p->cgrs[1], cgr->cgrid)) + cgr->cb(p, cgr, 1); + out: +- spin_unlock_irq(&p->cgr_lock); ++ raw_spin_unlock_irq(&p->cgr_lock); + put_affine_portal(); + return ret; + } +@@ -2510,7 +2513,7 @@ int qman_delete_cgr(struct qman_cgr *cgr) + return -EINVAL; + + memset(&local_opts, 0, sizeof(struct qm_mcc_initcgr)); +- spin_lock_irqsave(&p->cgr_lock, irqflags); ++ raw_spin_lock_irqsave(&p->cgr_lock, irqflags); + list_del(&cgr->node); + /* + * If there are no other CGR objects for this CGRID in the list, +@@ -2535,7 +2538,7 @@ int qman_delete_cgr(struct qman_cgr *cgr) + /* add back to the list */ + list_add(&cgr->node, &p->cgr_cbs); + release_lock: +- spin_unlock_irqrestore(&p->cgr_lock, irqflags); ++ raw_spin_unlock_irqrestore(&p->cgr_lock, irqflags); + put_affine_portal(); + return ret; + } +@@ -2575,9 +2578,9 @@ static int qman_update_cgr(struct qman_cgr *cgr, struct qm_mcc_initcgr *opts) + if (!p) + return -EINVAL; + +- spin_lock_irqsave(&p->cgr_lock, irqflags); ++ raw_spin_lock_irqsave(&p->cgr_lock, irqflags); + ret = qm_modify_cgr(cgr, 0, opts); +- spin_unlock_irqrestore(&p->cgr_lock, irqflags); ++ raw_spin_unlock_irqrestore(&p->cgr_lock, irqflags); + put_affine_portal(); + return ret; + } +-- +2.43.0 + diff --git a/queue-5.4/sparc-vdso-fix-return-value-of-__setup-handler.patch b/queue-5.4/sparc-vdso-fix-return-value-of-__setup-handler.patch new file mode 100644 index 00000000000..3e55d282e73 --- /dev/null +++ b/queue-5.4/sparc-vdso-fix-return-value-of-__setup-handler.patch @@ -0,0 +1,57 @@ +From 6e73b9c1ea4246a99b1dc6744f644971b218fad2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 10 Feb 2024 21:28:08 -0800 +Subject: sparc: vDSO: fix return value of __setup handler + +From: Randy Dunlap + +[ Upstream commit 5378f00c935bebb846b1fdb0e79cb76c137c56b5 ] + +__setup() handlers should return 1 to obsolete_checksetup() in +init/main.c to indicate that the boot option has been handled. +A return of 0 causes the boot option/value to be listed as an Unknown +kernel parameter and added to init's (limited) argument or environment +strings. Also, error return codes don't mean anything to +obsolete_checksetup() -- only non-zero (usually 1) or zero. +So return 1 from vdso_setup(). + +Fixes: 9a08862a5d2e ("vDSO for sparc") +Signed-off-by: Randy Dunlap +Reported-by: Igor Zhbanov +Link: lore.kernel.org/r/64644a2f-4a20-bab3-1e15-3b2cdd0defe3@omprussia.ru +Cc: "David S. Miller" +Cc: sparclinux@vger.kernel.org +Cc: Dan Carpenter +Cc: Nick Alcock +Cc: Sam Ravnborg +Cc: Andrew Morton +Cc: stable@vger.kernel.org +Cc: Arnd Bergmann +Cc: Andreas Larsson +Signed-off-by: Andreas Larsson +Link: https://lore.kernel.org/r/20240211052808.22635-1-rdunlap@infradead.org +Signed-off-by: Sasha Levin +--- + arch/sparc/vdso/vma.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/arch/sparc/vdso/vma.c b/arch/sparc/vdso/vma.c +index 9961b0f816939..3a30a086f0feb 100644 +--- a/arch/sparc/vdso/vma.c ++++ b/arch/sparc/vdso/vma.c +@@ -449,9 +449,8 @@ static __init int vdso_setup(char *s) + unsigned long val; + + err = kstrtoul(s, 10, &val); +- if (err) +- return err; +- vdso_enabled = val; +- return 0; ++ if (!err) ++ vdso_enabled = val; ++ return 1; + } + __setup("vdso=", vdso_setup); +-- +2.43.0 + diff --git a/queue-5.4/sparc64-nmi-watchdog-fix-return-value-of-__setup-han.patch b/queue-5.4/sparc64-nmi-watchdog-fix-return-value-of-__setup-han.patch new file mode 100644 index 00000000000..9dee6f5ddef --- /dev/null +++ b/queue-5.4/sparc64-nmi-watchdog-fix-return-value-of-__setup-han.patch @@ -0,0 +1,51 @@ +From 8d0f8fd50a80723f82586df4d14cae56de5f2ccc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 10 Feb 2024 21:28:02 -0800 +Subject: sparc64: NMI watchdog: fix return value of __setup handler + +From: Randy Dunlap + +[ Upstream commit 3ed7c61e49d65dacb96db798c0ab6fcd55a1f20f ] + +__setup() handlers should return 1 to obsolete_checksetup() in +init/main.c to indicate that the boot option has been handled. +A return of 0 causes the boot option/value to be listed as an Unknown +kernel parameter and added to init's (limited) argument or environment +strings. Also, error return codes don't mean anything to +obsolete_checksetup() -- only non-zero (usually 1) or zero. +So return 1 from setup_nmi_watchdog(). + +Fixes: e5553a6d0442 ("sparc64: Implement NMI watchdog on capable cpus.") +Signed-off-by: Randy Dunlap +Reported-by: Igor Zhbanov +Link: lore.kernel.org/r/64644a2f-4a20-bab3-1e15-3b2cdd0defe3@omprussia.ru +Cc: "David S. Miller" +Cc: sparclinux@vger.kernel.org +Cc: Sam Ravnborg +Cc: Andrew Morton +Cc: stable@vger.kernel.org +Cc: Arnd Bergmann +Cc: Andreas Larsson +Signed-off-by: Andreas Larsson +Link: https://lore.kernel.org/r/20240211052802.22612-1-rdunlap@infradead.org +Signed-off-by: Sasha Levin +--- + arch/sparc/kernel/nmi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c +index 060fff95a305c..fbf25e926f67c 100644 +--- a/arch/sparc/kernel/nmi.c ++++ b/arch/sparc/kernel/nmi.c +@@ -274,7 +274,7 @@ static int __init setup_nmi_watchdog(char *str) + if (!strncmp(str, "panic", 5)) + panic_on_timeout = 1; + +- return 0; ++ return 1; + } + __setup("nmi_watchdog=", setup_nmi_watchdog); + +-- +2.43.0 + diff --git a/queue-5.4/speakup-fix-8bit-characters-from-direct-synth.patch b/queue-5.4/speakup-fix-8bit-characters-from-direct-synth.patch new file mode 100644 index 00000000000..c2ed6b3936b --- /dev/null +++ b/queue-5.4/speakup-fix-8bit-characters-from-direct-synth.patch @@ -0,0 +1,49 @@ +From 27e7aa172d013063ed9e54f39dd942990f121bcc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 4 Feb 2024 16:57:36 +0100 +Subject: speakup: Fix 8bit characters from direct synth + +From: Samuel Thibault + +[ Upstream commit b6c8dafc9d86eb77e502bb018ec4105e8d2fbf78 ] + +When userland echoes 8bit characters to /dev/synth with e.g. + +echo -e '\xe9' > /dev/synth + +synth_write would get characters beyond 0x7f, and thus negative when +char is signed. When given to synth_buffer_add which takes a u16, this +would sign-extend and produce a U+ffxy character rather than U+xy. +Users thus get garbled text instead of accents in their output. + +Let's fix this by making sure that we read unsigned characters. + +Signed-off-by: Samuel Thibault +Fixes: 89fc2ae80bb1 ("speakup: extend synth buffer to 16bit unicode characters") +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20240204155736.2oh4ot7tiaa2wpbh@begin +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/staging/speakup/synth.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c +index 3568bfb89912c..b5944e7bdbf67 100644 +--- a/drivers/staging/speakup/synth.c ++++ b/drivers/staging/speakup/synth.c +@@ -208,8 +208,10 @@ void spk_do_flush(void) + wake_up_process(speakup_task); + } + +-void synth_write(const char *buf, size_t count) ++void synth_write(const char *_buf, size_t count) + { ++ const unsigned char *buf = (const unsigned char *) _buf; ++ + while (count--) + synth_buffer_add(*buf++); + synth_start(); +-- +2.43.0 + diff --git a/queue-5.4/timers-rename-del_timer_sync-to-timer_delete_sync.patch b/queue-5.4/timers-rename-del_timer_sync-to-timer_delete_sync.patch new file mode 100644 index 00000000000..38a9022828b --- /dev/null +++ b/queue-5.4/timers-rename-del_timer_sync-to-timer_delete_sync.patch @@ -0,0 +1,130 @@ +From f11327fe09afd2f77c6c2590491b7ab1bd9f7a78 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 21:18:44 +0100 +Subject: timers: Rename del_timer_sync() to timer_delete_sync() + +From: Thomas Gleixner + +[ Upstream commit 9b13df3fb64ee95e2397585404e442afee2c7d4f ] + +The timer related functions do not have a strict timer_ prefixed namespace +which is really annoying. + +Rename del_timer_sync() to timer_delete_sync() and provide del_timer_sync() +as a wrapper. Document that del_timer_sync() is not for new code. + +Signed-off-by: Thomas Gleixner +Tested-by: Guenter Roeck +Reviewed-by: Steven Rostedt (Google) +Reviewed-by: Jacob Keller +Reviewed-by: Anna-Maria Behnsen +Link: https://lore.kernel.org/r/20221123201624.954785441@linutronix.de +Stable-dep-of: 0f7352557a35 ("wifi: brcmfmac: Fix use-after-free bug in brcmf_cfg80211_detach") +Signed-off-by: Sasha Levin +--- + include/linux/timer.h | 15 ++++++++++++++- + kernel/time/timer.c | 18 +++++++++--------- + 2 files changed, 23 insertions(+), 10 deletions(-) + +diff --git a/include/linux/timer.h b/include/linux/timer.h +index 4de865f516154..cadb23acd229e 100644 +--- a/include/linux/timer.h ++++ b/include/linux/timer.h +@@ -182,7 +182,20 @@ extern int timer_reduce(struct timer_list *timer, unsigned long expires); + extern void add_timer(struct timer_list *timer); + + extern int try_to_del_timer_sync(struct timer_list *timer); +-extern int del_timer_sync(struct timer_list *timer); ++extern int timer_delete_sync(struct timer_list *timer); ++ ++/** ++ * del_timer_sync - Delete a pending timer and wait for a running callback ++ * @timer: The timer to be deleted ++ * ++ * See timer_delete_sync() for detailed explanation. ++ * ++ * Do not use in new code. Use timer_delete_sync() instead. ++ */ ++static inline int del_timer_sync(struct timer_list *timer) ++{ ++ return timer_delete_sync(timer); ++} + + #define del_singleshot_timer_sync(t) del_timer_sync(t) + +diff --git a/kernel/time/timer.c b/kernel/time/timer.c +index 0dfd1cacc4a00..6e2dd83a93afd 100644 +--- a/kernel/time/timer.c ++++ b/kernel/time/timer.c +@@ -1031,7 +1031,7 @@ __mod_timer(struct timer_list *timer, unsigned long expires, unsigned int option + /* + * We are trying to schedule the timer on the new base. + * However we can't change timer's base while it is running, +- * otherwise del_timer_sync() can't detect that the timer's ++ * otherwise timer_delete_sync() can't detect that the timer's + * handler yet has not finished. This also guarantees that the + * timer is serialized wrt itself. + */ +@@ -1210,7 +1210,7 @@ EXPORT_SYMBOL_GPL(add_timer_on); + * @timer: The timer to be deactivated + * + * The function only deactivates a pending timer, but contrary to +- * del_timer_sync() it does not take into account whether the timer's ++ * timer_delete_sync() it does not take into account whether the timer's + * callback function is concurrently executed on a different CPU or not. + * It neither prevents rearming of the timer. If @timer can be rearmed + * concurrently then the return value of this function is meaningless. +@@ -1346,7 +1346,7 @@ static inline void del_timer_wait_running(struct timer_list *timer) { } + #endif + + /** +- * del_timer_sync - Deactivate a timer and wait for the handler to finish. ++ * timer_delete_sync - Deactivate a timer and wait for the handler to finish. + * @timer: The timer to be deactivated + * + * Synchronization rules: Callers must prevent restarting of the timer, +@@ -1368,10 +1368,10 @@ static inline void del_timer_wait_running(struct timer_list *timer) { } + * spin_lock_irq(somelock); + * + * spin_lock(somelock); +- * del_timer_sync(mytimer); ++ * timer_delete_sync(mytimer); + * while (base->running_timer == mytimer); + * +- * Now del_timer_sync() will never return and never release somelock. ++ * Now timer_delete_sync() will never return and never release somelock. + * The interrupt on the other CPU is waiting to grab somelock but it has + * interrupted the softirq that CPU0 is waiting to finish. + * +@@ -1384,7 +1384,7 @@ static inline void del_timer_wait_running(struct timer_list *timer) { } + * * %0 - The timer was not pending + * * %1 - The timer was pending and deactivated + */ +-int del_timer_sync(struct timer_list *timer) ++int timer_delete_sync(struct timer_list *timer) + { + int ret; + +@@ -1417,7 +1417,7 @@ int del_timer_sync(struct timer_list *timer) + + return ret; + } +-EXPORT_SYMBOL(del_timer_sync); ++EXPORT_SYMBOL(timer_delete_sync); + + static void call_timer_fn(struct timer_list *timer, + void (*fn)(struct timer_list *), +@@ -1439,8 +1439,8 @@ static void call_timer_fn(struct timer_list *timer, + #endif + /* + * Couple the lock chain with the lock chain at +- * del_timer_sync() by acquiring the lock_map around the fn() +- * call here and in del_timer_sync(). ++ * timer_delete_sync() by acquiring the lock_map around the fn() ++ * call here and in timer_delete_sync(). + */ + lock_map_acquire(&lockdep_map); + +-- +2.43.0 + diff --git a/queue-5.4/timers-update-kernel-doc-for-various-functions.patch b/queue-5.4/timers-update-kernel-doc-for-various-functions.patch new file mode 100644 index 00000000000..1725eb2d03b --- /dev/null +++ b/queue-5.4/timers-update-kernel-doc-for-various-functions.patch @@ -0,0 +1,265 @@ +From 237136958798e092e09ee7c8f61fd89f7744d3b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 21:18:40 +0100 +Subject: timers: Update kernel-doc for various functions + +From: Thomas Gleixner + +[ Upstream commit 14f043f1340bf30bc60af127bff39f55889fef26 ] + +The kernel-doc of timer related functions is partially uncomprehensible +word salad. Rewrite it to make it useful. + +Signed-off-by: Thomas Gleixner +Tested-by: Guenter Roeck +Reviewed-by: Jacob Keller +Reviewed-by: Anna-Maria Behnsen +Link: https://lore.kernel.org/r/20221123201624.828703870@linutronix.de +Stable-dep-of: 0f7352557a35 ("wifi: brcmfmac: Fix use-after-free bug in brcmf_cfg80211_detach") +Signed-off-by: Sasha Levin +--- + kernel/time/timer.c | 148 +++++++++++++++++++++++++++----------------- + 1 file changed, 90 insertions(+), 58 deletions(-) + +diff --git a/kernel/time/timer.c b/kernel/time/timer.c +index 16a2b62f5f74c..973c66d9b3f90 100644 +--- a/kernel/time/timer.c ++++ b/kernel/time/timer.c +@@ -1072,14 +1072,16 @@ __mod_timer(struct timer_list *timer, unsigned long expires, unsigned int option + } + + /** +- * mod_timer_pending - modify a pending timer's timeout +- * @timer: the pending timer to be modified +- * @expires: new timeout in jiffies ++ * mod_timer_pending - Modify a pending timer's timeout ++ * @timer: The pending timer to be modified ++ * @expires: New absolute timeout in jiffies + * +- * mod_timer_pending() is the same for pending timers as mod_timer(), +- * but will not re-activate and modify already deleted timers. ++ * mod_timer_pending() is the same for pending timers as mod_timer(), but ++ * will not activate inactive timers. + * +- * It is useful for unserialized use of timers. ++ * Return: ++ * * %0 - The timer was inactive and not modified ++ * * %1 - The timer was active and requeued to expire at @expires + */ + int mod_timer_pending(struct timer_list *timer, unsigned long expires) + { +@@ -1088,24 +1090,27 @@ int mod_timer_pending(struct timer_list *timer, unsigned long expires) + EXPORT_SYMBOL(mod_timer_pending); + + /** +- * mod_timer - modify a timer's timeout +- * @timer: the timer to be modified +- * @expires: new timeout in jiffies +- * +- * mod_timer() is a more efficient way to update the expire field of an +- * active timer (if the timer is inactive it will be activated) ++ * mod_timer - Modify a timer's timeout ++ * @timer: The timer to be modified ++ * @expires: New absolute timeout in jiffies + * + * mod_timer(timer, expires) is equivalent to: + * + * del_timer(timer); timer->expires = expires; add_timer(timer); + * ++ * mod_timer() is more efficient than the above open coded sequence. In ++ * case that the timer is inactive, the del_timer() part is a NOP. The ++ * timer is in any case activated with the new expiry time @expires. ++ * + * Note that if there are multiple unserialized concurrent users of the + * same timer, then mod_timer() is the only safe way to modify the timeout, + * since add_timer() cannot modify an already running timer. + * +- * The function returns whether it has modified a pending timer or not. +- * (ie. mod_timer() of an inactive timer returns 0, mod_timer() of an +- * active timer returns 1.) ++ * Return: ++ * * %0 - The timer was inactive and started ++ * * %1 - The timer was active and requeued to expire at @expires or ++ * the timer was active and not modified because @expires did ++ * not change the effective expiry time + */ + int mod_timer(struct timer_list *timer, unsigned long expires) + { +@@ -1116,11 +1121,18 @@ EXPORT_SYMBOL(mod_timer); + /** + * timer_reduce - Modify a timer's timeout if it would reduce the timeout + * @timer: The timer to be modified +- * @expires: New timeout in jiffies ++ * @expires: New absolute timeout in jiffies + * + * timer_reduce() is very similar to mod_timer(), except that it will only +- * modify a running timer if that would reduce the expiration time (it will +- * start a timer that isn't running). ++ * modify an enqueued timer if that would reduce the expiration time. If ++ * @timer is not enqueued it starts the timer. ++ * ++ * Return: ++ * * %0 - The timer was inactive and started ++ * * %1 - The timer was active and requeued to expire at @expires or ++ * the timer was active and not modified because @expires ++ * did not change the effective expiry time such that the ++ * timer would expire earlier than already scheduled + */ + int timer_reduce(struct timer_list *timer, unsigned long expires) + { +@@ -1129,18 +1141,21 @@ int timer_reduce(struct timer_list *timer, unsigned long expires) + EXPORT_SYMBOL(timer_reduce); + + /** +- * add_timer - start a timer +- * @timer: the timer to be added ++ * add_timer - Start a timer ++ * @timer: The timer to be started + * +- * The kernel will do a ->function(@timer) callback from the +- * timer interrupt at the ->expires point in the future. The +- * current time is 'jiffies'. ++ * Start @timer to expire at @timer->expires in the future. @timer->expires ++ * is the absolute expiry time measured in 'jiffies'. When the timer expires ++ * timer->function(timer) will be invoked from soft interrupt context. + * +- * The timer's ->expires, ->function fields must be set prior calling this +- * function. ++ * The @timer->expires and @timer->function fields must be set prior ++ * to calling this function. ++ * ++ * If @timer->expires is already in the past @timer will be queued to ++ * expire at the next timer tick. + * +- * Timers with an ->expires field in the past will be executed in the next +- * timer tick. ++ * This can only operate on an inactive timer. Attempts to invoke this on ++ * an active timer are rejected with a warning. + */ + void add_timer(struct timer_list *timer) + { +@@ -1150,11 +1165,13 @@ void add_timer(struct timer_list *timer) + EXPORT_SYMBOL(add_timer); + + /** +- * add_timer_on - start a timer on a particular CPU +- * @timer: the timer to be added +- * @cpu: the CPU to start it on ++ * add_timer_on - Start a timer on a particular CPU ++ * @timer: The timer to be started ++ * @cpu: The CPU to start it on ++ * ++ * Same as add_timer() except that it starts the timer on the given CPU. + * +- * This is not very scalable on SMP. Double adds are not possible. ++ * See add_timer() for further details. + */ + void add_timer_on(struct timer_list *timer, int cpu) + { +@@ -1189,15 +1206,18 @@ void add_timer_on(struct timer_list *timer, int cpu) + EXPORT_SYMBOL_GPL(add_timer_on); + + /** +- * del_timer - deactivate a timer. +- * @timer: the timer to be deactivated +- * +- * del_timer() deactivates a timer - this works on both active and inactive +- * timers. +- * +- * The function returns whether it has deactivated a pending timer or not. +- * (ie. del_timer() of an inactive timer returns 0, del_timer() of an +- * active timer returns 1.) ++ * del_timer - Deactivate a timer. ++ * @timer: The timer to be deactivated ++ * ++ * The function only deactivates a pending timer, but contrary to ++ * del_timer_sync() it does not take into account whether the timer's ++ * callback function is concurrently executed on a different CPU or not. ++ * It neither prevents rearming of the timer. If @timer can be rearmed ++ * concurrently then the return value of this function is meaningless. ++ * ++ * Return: ++ * * %0 - The timer was not pending ++ * * %1 - The timer was pending and deactivated + */ + int del_timer(struct timer_list *timer) + { +@@ -1219,10 +1239,19 @@ EXPORT_SYMBOL(del_timer); + + /** + * try_to_del_timer_sync - Try to deactivate a timer +- * @timer: timer to delete ++ * @timer: Timer to deactivate ++ * ++ * This function tries to deactivate a timer. On success the timer is not ++ * queued and the timer callback function is not running on any CPU. + * +- * This function tries to deactivate a timer. Upon successful (ret >= 0) +- * exit the timer is not queued and the handler is not running on any CPU. ++ * This function does not guarantee that the timer cannot be rearmed right ++ * after dropping the base lock. That needs to be prevented by the calling ++ * code if necessary. ++ * ++ * Return: ++ * * %0 - The timer was not pending ++ * * %1 - The timer was pending and deactivated ++ * * %-1 - The timer callback function is running on a different CPU + */ + int try_to_del_timer_sync(struct timer_list *timer) + { +@@ -1318,23 +1347,19 @@ static inline void del_timer_wait_running(struct timer_list *timer) { } + + #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT) + /** +- * del_timer_sync - deactivate a timer and wait for the handler to finish. +- * @timer: the timer to be deactivated +- * +- * This function only differs from del_timer() on SMP: besides deactivating +- * the timer it also makes sure the handler has finished executing on other +- * CPUs. ++ * del_timer_sync - Deactivate a timer and wait for the handler to finish. ++ * @timer: The timer to be deactivated + * + * Synchronization rules: Callers must prevent restarting of the timer, + * otherwise this function is meaningless. It must not be called from + * interrupt contexts unless the timer is an irqsafe one. The caller must +- * not hold locks which would prevent completion of the timer's +- * handler. The timer's handler must not call add_timer_on(). Upon exit the +- * timer is not queued and the handler is not running on any CPU. ++ * not hold locks which would prevent completion of the timer's callback ++ * function. The timer's handler must not call add_timer_on(). Upon exit ++ * the timer is not queued and the handler is not running on any CPU. + * +- * Note: For !irqsafe timers, you must not hold locks that are held in +- * interrupt context while calling this function. Even if the lock has +- * nothing to do with the timer in question. Here's why:: ++ * For !irqsafe timers, the caller must not hold locks that are held in ++ * interrupt context. Even if the lock has nothing to do with the timer in ++ * question. Here's why:: + * + * CPU0 CPU1 + * ---- ---- +@@ -1348,10 +1373,17 @@ static inline void del_timer_wait_running(struct timer_list *timer) { } + * while (base->running_timer == mytimer); + * + * Now del_timer_sync() will never return and never release somelock. +- * The interrupt on the other CPU is waiting to grab somelock but +- * it has interrupted the softirq that CPU0 is waiting to finish. ++ * The interrupt on the other CPU is waiting to grab somelock but it has ++ * interrupted the softirq that CPU0 is waiting to finish. ++ * ++ * This function cannot guarantee that the timer is not rearmed again by ++ * some concurrent or preempting code, right after it dropped the base ++ * lock. If there is the possibility of a concurrent rearm then the return ++ * value of the function is meaningless. + * +- * The function returns whether it has deactivated a pending timer or not. ++ * Return: ++ * * %0 - The timer was not pending ++ * * %1 - The timer was pending and deactivated + */ + int del_timer_sync(struct timer_list *timer) + { +-- +2.43.0 + diff --git a/queue-5.4/timers-use-del_timer_sync-even-on-up.patch b/queue-5.4/timers-use-del_timer_sync-even-on-up.patch new file mode 100644 index 00000000000..baa7391a233 --- /dev/null +++ b/queue-5.4/timers-use-del_timer_sync-even-on-up.patch @@ -0,0 +1,80 @@ +From 3563faca31c6088cad3205a04c50be541bb30916 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 21:18:42 +0100 +Subject: timers: Use del_timer_sync() even on UP + +From: Thomas Gleixner + +[ Upstream commit 168f6b6ffbeec0b9333f3582e4cf637300858db5 ] + +del_timer_sync() is assumed to be pointless on uniprocessor systems and can +be mapped to del_timer() because in theory del_timer() can never be invoked +while the timer callback function is executed. + +This is not entirely true because del_timer() can be invoked from interrupt +context and therefore hit in the middle of a running timer callback. + +Contrary to that del_timer_sync() is not allowed to be invoked from +interrupt context unless the affected timer is marked with TIMER_IRQSAFE. +del_timer_sync() has proper checks in place to detect such a situation. + +Give up on the UP optimization and make del_timer_sync() unconditionally +available. + +Co-developed-by: Steven Rostedt +Signed-off-by: Steven Rostedt +Signed-off-by: Thomas Gleixner +Tested-by: Guenter Roeck +Reviewed-by: Jacob Keller +Reviewed-by: Anna-Maria Behnsen +Link: https://lore.kernel.org/all/20220407161745.7d6754b3@gandalf.local.home +Link: https://lore.kernel.org/all/20221110064101.429013735@goodmis.org +Link: https://lore.kernel.org/r/20221123201624.888306160@linutronix.de +Stable-dep-of: 0f7352557a35 ("wifi: brcmfmac: Fix use-after-free bug in brcmf_cfg80211_detach") +Signed-off-by: Sasha Levin +--- + include/linux/timer.h | 7 +------ + kernel/time/timer.c | 2 -- + 2 files changed, 1 insertion(+), 8 deletions(-) + +diff --git a/include/linux/timer.h b/include/linux/timer.h +index 1e6650ed066d5..4de865f516154 100644 +--- a/include/linux/timer.h ++++ b/include/linux/timer.h +@@ -182,12 +182,7 @@ extern int timer_reduce(struct timer_list *timer, unsigned long expires); + extern void add_timer(struct timer_list *timer); + + extern int try_to_del_timer_sync(struct timer_list *timer); +- +-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT) +- extern int del_timer_sync(struct timer_list *timer); +-#else +-# define del_timer_sync(t) del_timer(t) +-#endif ++extern int del_timer_sync(struct timer_list *timer); + + #define del_singleshot_timer_sync(t) del_timer_sync(t) + +diff --git a/kernel/time/timer.c b/kernel/time/timer.c +index 973c66d9b3f90..0dfd1cacc4a00 100644 +--- a/kernel/time/timer.c ++++ b/kernel/time/timer.c +@@ -1345,7 +1345,6 @@ static inline void timer_sync_wait_running(struct timer_base *base) { } + static inline void del_timer_wait_running(struct timer_list *timer) { } + #endif + +-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT) + /** + * del_timer_sync - Deactivate a timer and wait for the handler to finish. + * @timer: The timer to be deactivated +@@ -1419,7 +1418,6 @@ int del_timer_sync(struct timer_list *timer) + return ret; + } + EXPORT_SYMBOL(del_timer_sync); +-#endif + + static void call_timer_fn(struct timer_list *timer, + void (*fn)(struct timer_list *), +-- +2.43.0 + diff --git a/queue-5.4/ubi-check-for-too-small-leb-size-in-vtbl-code.patch b/queue-5.4/ubi-check-for-too-small-leb-size-in-vtbl-code.patch new file mode 100644 index 00000000000..373f24820c4 --- /dev/null +++ b/queue-5.4/ubi-check-for-too-small-leb-size-in-vtbl-code.patch @@ -0,0 +1,45 @@ +From 55d50d73a93c2057ec399d06f8ef78492b3a58ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jan 2024 07:37:02 +0100 +Subject: ubi: Check for too small LEB size in VTBL code + +From: Richard Weinberger + +[ Upstream commit 68a24aba7c593eafa8fd00f2f76407b9b32b47a9 ] + +If the LEB size is smaller than a volume table record we cannot +have volumes. +In this case abort attaching. + +Cc: Chenyuan Yang +Cc: stable@vger.kernel.org +Fixes: 801c135ce73d ("UBI: Unsorted Block Images") +Reported-by: Chenyuan Yang +Closes: https://lore.kernel.org/linux-mtd/1433EB7A-FC89-47D6-8F47-23BE41B263B3@illinois.edu/ +Signed-off-by: Richard Weinberger +Reviewed-by: Zhihao Cheng +Signed-off-by: Sasha Levin +--- + drivers/mtd/ubi/vtbl.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c +index 53d8ab54e1811..c891ee100dec4 100644 +--- a/drivers/mtd/ubi/vtbl.c ++++ b/drivers/mtd/ubi/vtbl.c +@@ -791,6 +791,12 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai) + * The number of supported volumes is limited by the eraseblock size + * and by the UBI_MAX_VOLUMES constant. + */ ++ ++ if (ubi->leb_size < UBI_VTBL_RECORD_SIZE) { ++ ubi_err(ubi, "LEB size too small for a volume record"); ++ return -EINVAL; ++ } ++ + ubi->vtbl_slots = ubi->leb_size / UBI_VTBL_RECORD_SIZE; + if (ubi->vtbl_slots > UBI_MAX_VOLUMES) + ubi->vtbl_slots = UBI_MAX_VOLUMES; +-- +2.43.0 + diff --git a/queue-5.4/ubi-correct-the-calculation-of-fastmap-size.patch b/queue-5.4/ubi-correct-the-calculation-of-fastmap-size.patch new file mode 100644 index 00000000000..b46ad074726 --- /dev/null +++ b/queue-5.4/ubi-correct-the-calculation-of-fastmap-size.patch @@ -0,0 +1,43 @@ +From a9c278c72ea7a7be518a43f3b4b4cd9692348490 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Feb 2024 10:49:03 +0800 +Subject: ubi: correct the calculation of fastmap size + +From: Zhang Yi + +[ Upstream commit 7f174ae4f39e8475adcc09d26c5a43394689ad6c ] + +Now that the calculation of fastmap size in ubi_calc_fm_size() is +incorrect since it miss each user volume's ubi_fm_eba structure and the +Internal UBI volume info. Let's correct the calculation. + +Cc: stable@vger.kernel.org +Signed-off-by: Zhang Yi +Reviewed-by: Zhihao Cheng +Signed-off-by: Richard Weinberger +Signed-off-by: Sasha Levin +--- + drivers/mtd/ubi/fastmap.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c +index 6e95c4b1473e6..8081fc760d34f 100644 +--- a/drivers/mtd/ubi/fastmap.c ++++ b/drivers/mtd/ubi/fastmap.c +@@ -86,9 +86,10 @@ size_t ubi_calc_fm_size(struct ubi_device *ubi) + sizeof(struct ubi_fm_scan_pool) + + sizeof(struct ubi_fm_scan_pool) + + (ubi->peb_count * sizeof(struct ubi_fm_ec)) + +- (sizeof(struct ubi_fm_eba) + +- (ubi->peb_count * sizeof(__be32))) + +- sizeof(struct ubi_fm_volhdr) * UBI_MAX_VOLUMES; ++ ((sizeof(struct ubi_fm_eba) + ++ sizeof(struct ubi_fm_volhdr)) * ++ (UBI_MAX_VOLUMES + UBI_INT_VOL_COUNT)) + ++ (ubi->peb_count * sizeof(__be32)); + return roundup(size, ubi->leb_size); + } + +-- +2.43.0 + diff --git a/queue-5.4/ubifs-set-page-uptodate-in-the-correct-place.patch b/queue-5.4/ubifs-set-page-uptodate-in-the-correct-place.patch new file mode 100644 index 00000000000..dfec09c5a9b --- /dev/null +++ b/queue-5.4/ubifs-set-page-uptodate-in-the-correct-place.patch @@ -0,0 +1,74 @@ +From 045fbd81ef3f2f279e03d8beebe98a02d6166485 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jan 2024 17:52:44 +0000 +Subject: ubifs: Set page uptodate in the correct place + +From: Matthew Wilcox (Oracle) + +[ Upstream commit 723012cab779eee8228376754e22c6594229bf8f ] + +Page cache reads are lockless, so setting the freshly allocated page +uptodate before we've overwritten it with the data it's supposed to have +in it will allow a simultaneous reader to see old data. Move the call +to SetPageUptodate into ubifs_write_end(), which is after we copied the +new data into the page. + +Fixes: 1e51764a3c2a ("UBIFS: add new flash file system") +Cc: stable@vger.kernel.org +Signed-off-by: Matthew Wilcox (Oracle) +Reviewed-by: Zhihao Cheng +Signed-off-by: Richard Weinberger +Signed-off-by: Sasha Levin +--- + fs/ubifs/file.c | 13 ++++--------- + 1 file changed, 4 insertions(+), 9 deletions(-) + +diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c +index 4d3a5cb6e9b03..ebad140f8d056 100644 +--- a/fs/ubifs/file.c ++++ b/fs/ubifs/file.c +@@ -262,9 +262,6 @@ static int write_begin_slow(struct address_space *mapping, + return err; + } + } +- +- SetPageUptodate(page); +- ClearPageError(page); + } + + if (PagePrivate(page)) +@@ -463,9 +460,6 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping, + return err; + } + } +- +- SetPageUptodate(page); +- ClearPageError(page); + } + + err = allocate_budget(c, page, ui, appending); +@@ -475,10 +469,8 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping, + * If we skipped reading the page because we were going to + * write all of it, then it is not up to date. + */ +- if (skipped_read) { ++ if (skipped_read) + ClearPageChecked(page); +- ClearPageUptodate(page); +- } + /* + * Budgeting failed which means it would have to force + * write-back but didn't, because we set the @fast flag in the +@@ -569,6 +561,9 @@ static int ubifs_write_end(struct file *file, struct address_space *mapping, + goto out; + } + ++ if (len == PAGE_SIZE) ++ SetPageUptodate(page); ++ + if (!PagePrivate(page)) { + SetPagePrivate(page); + atomic_long_inc(&c->dirty_pg_cnt); +-- +2.43.0 + diff --git a/queue-5.4/usb-serial-add-device-id-for-verifone-adapter.patch b/queue-5.4/usb-serial-add-device-id-for-verifone-adapter.patch new file mode 100644 index 00000000000..e81f4ddece6 --- /dev/null +++ b/queue-5.4/usb-serial-add-device-id-for-verifone-adapter.patch @@ -0,0 +1,94 @@ +From 2beb4f71b19ed8d4c9c875ff46e41339d238e40f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Feb 2024 21:53:29 +0000 +Subject: USB: serial: add device ID for VeriFone adapter + +From: Cameron Williams + +[ Upstream commit cda704809797a8a86284f9df3eef5e62ec8a3175 ] + +Add device ID for a (probably fake) CP2102 UART device. + +lsusb -v output: + +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.10 + bDeviceClass 0 [unknown] + bDeviceSubClass 0 [unknown] + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x11ca VeriFone Inc + idProduct 0x0212 Verifone USB to Printer + bcdDevice 1.00 + iManufacturer 1 Silicon Labs + iProduct 2 Verifone USB to Printer + iSerial 3 0001 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 0x0020 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 255 Vendor Specific Class + bInterfaceSubClass 0 [unknown] + bInterfaceProtocol 0 + iInterface 2 Verifone USB to Printer + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 0 +Device Status: 0x0000 + (Bus Powered) + +Signed-off-by: Cameron Williams +Cc: stable@vger.kernel.org +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/cp210x.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index 1724cade102e1..015dcaf58047c 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -178,6 +178,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x10C4, 0xF004) }, /* Elan Digital Systems USBcount50 */ + { USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */ + { USB_DEVICE(0x10CE, 0xEA6A) }, /* Silicon Labs MobiData GPRS USB Modem 100EU */ ++ { USB_DEVICE(0x11CA, 0x0212) }, /* Verifone USB to Printer (UART, CP2102) */ + { USB_DEVICE(0x12B8, 0xEC60) }, /* Link G4 ECU */ + { USB_DEVICE(0x12B8, 0xEC62) }, /* Link G4+ ECU */ + { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */ +-- +2.43.0 + diff --git a/queue-5.4/usb-serial-cp210x-add-id-for-mgp-instruments-pds100.patch b/queue-5.4/usb-serial-cp210x-add-id-for-mgp-instruments-pds100.patch new file mode 100644 index 00000000000..0bdbd1a8300 --- /dev/null +++ b/queue-5.4/usb-serial-cp210x-add-id-for-mgp-instruments-pds100.patch @@ -0,0 +1,44 @@ +From 8144c53c10b4dfcc73f3cf0aa598e9699b38b4a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Feb 2024 11:47:29 +0100 +Subject: USB: serial: cp210x: add ID for MGP Instruments PDS100 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Christian Häggström + +[ Upstream commit a0d9d868491a362d421521499d98308c8e3a0398 ] + +The radiation meter has the text MGP Instruments PDS-100G or PDS-100GN +produced by Mirion Technologies. Tested by forcing the driver +association with + + echo 10c4 863c > /sys/bus/usb-serial/drivers/cp210x/new_id + +and then setting the serial port in 115200 8N1 mode. The device +announces ID_USB_VENDOR_ENC=Silicon\x20Labs and ID_USB_MODEL_ENC=PDS100 + +Signed-off-by: Christian Häggström +Cc: stable@vger.kernel.org +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/cp210x.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index 015dcaf58047c..88659a75f30f9 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -145,6 +145,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */ + { USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */ + { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */ ++ { USB_DEVICE(0x10C4, 0x863C) }, /* MGP Instruments PDS100 */ + { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */ + { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ + { USB_DEVICE(0x10C4, 0x87ED) }, /* IMST USB-Stick for Smart Meter */ +-- +2.43.0 + diff --git a/queue-5.4/usb-serial-cp210x-add-pid-vid-for-tdk-nc0110013m-and.patch b/queue-5.4/usb-serial-cp210x-add-pid-vid-for-tdk-nc0110013m-and.patch new file mode 100644 index 00000000000..d29076b6684 --- /dev/null +++ b/queue-5.4/usb-serial-cp210x-add-pid-vid-for-tdk-nc0110013m-and.patch @@ -0,0 +1,36 @@ +From ff8fc7cda24e8f4affe141aacde2fb3cf4657d56 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Mar 2024 08:46:14 +0900 +Subject: USB: serial: cp210x: add pid/vid for TDK NC0110013M and MM0110113M + +From: Toru Katagiri + +[ Upstream commit b1a8da9ff1395c4879b4bd41e55733d944f3d613 ] + +TDK NC0110013M and MM0110113M have custom USB IDs for CP210x, +so we need to add them to the driver. + +Signed-off-by: Toru Katagiri +Cc: stable@vger.kernel.org +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/cp210x.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index 88659a75f30f9..5353fa7e59696 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -57,6 +57,8 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ + { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ + { USB_DEVICE(0x0489, 0xE003) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ ++ { USB_DEVICE(0x04BF, 0x1301) }, /* TDK Corporation NC0110013M - Network Controller */ ++ { USB_DEVICE(0x04BF, 0x1303) }, /* TDK Corporation MM0110113M - i3 Micro Module */ + { USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */ + { USB_DEVICE(0x0846, 0x1100) }, /* NetGear Managed Switch M4100 series, M5300 series, M7100 series */ + { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ +-- +2.43.0 + diff --git a/queue-5.4/usb-serial-ftdi_sio-add-support-for-gmc-z216c-adapte.patch b/queue-5.4/usb-serial-ftdi_sio-add-support-for-gmc-z216c-adapte.patch new file mode 100644 index 00000000000..03579f1212e --- /dev/null +++ b/queue-5.4/usb-serial-ftdi_sio-add-support-for-gmc-z216c-adapte.patch @@ -0,0 +1,53 @@ +From 78d6e0623c617b7032cb52fd29ae76d920bdac1b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 11 Feb 2024 15:42:46 +0100 +Subject: USB: serial: ftdi_sio: add support for GMC Z216C Adapter IR-USB + +From: Daniel Vogelbacher + +[ Upstream commit 3fb7bc4f3a98c48981318b87cf553c5f115fd5ca ] + +The GMC IR-USB adapter cable utilizes a FTDI FT232R chip. + +Add VID/PID for this adapter so it can be used as serial device via +ftdi_sio. + +Signed-off-by: Daniel Vogelbacher +Cc: stable@vger.kernel.org +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/ftdi_sio.c | 2 ++ + drivers/usb/serial/ftdi_sio_ids.h | 6 ++++++ + 2 files changed, 8 insertions(+) + +diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c +index c97923858fce6..bfb0be4e70d5e 100644 +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -1055,6 +1055,8 @@ static const struct usb_device_id id_table_combined[] = { + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(FTDI_VID, FTDI_FALCONIA_JTAG_UNBUF_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, ++ /* GMC devices */ ++ { USB_DEVICE(GMC_VID, GMC_Z216C_PID) }, + { } /* Terminating entry */ + }; + +diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h +index 9a0f9fc991246..b2aec1106678a 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -1599,3 +1599,9 @@ + #define UBLOX_VID 0x1546 + #define UBLOX_C099F9P_ZED_PID 0x0502 + #define UBLOX_C099F9P_ODIN_PID 0x0503 ++ ++/* ++ * GMC devices ++ */ ++#define GMC_VID 0x1cd7 ++#define GMC_Z216C_PID 0x0217 /* GMC Z216C Adapter IR-USB */ +-- +2.43.0 + diff --git a/queue-5.4/usb-serial-option-add-meig-smart-slm320-product.patch b/queue-5.4/usb-serial-option-add-meig-smart-slm320-product.patch new file mode 100644 index 00000000000..a6a59b4d248 --- /dev/null +++ b/queue-5.4/usb-serial-option-add-meig-smart-slm320-product.patch @@ -0,0 +1,85 @@ +From d052ea1549170db9de28018e5f9c18c65a452d3a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Jan 2024 18:49:17 +0100 +Subject: USB: serial: option: add MeiG Smart SLM320 product +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Aurélien Jacobs + +[ Upstream commit 46809c51565b83881aede6cdf3b0d25254966a41 ] + +Update the USB serial option driver to support MeiG Smart SLM320. + +ID 2dee:4d41 UNISOC UNISOC-8910 + +T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 9 Spd=480 MxCh= 0 +D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 +P: Vendor=2dee ProdID=4d41 Rev=00.00 +S: Manufacturer=UNISOC +S: Product=UNISOC-8910 +C: #Ifs= 8 Cfg#= 1 Atr=e0 MxPwr=400mA +I: If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option +E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms +E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms +I: If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option +E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms +E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms +I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option +E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms +E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms +I: If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option +E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms +E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms +I: If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option +E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms +E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms +I: If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option +E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms +E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms +I: If#= 6 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option +E: Ad=07(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms +E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms +I: If#= 7 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option +E: Ad=08(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms +E: Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms + +Tested successfully a PPP LTE connection using If#= 0. +Not sure of the purpose of every other serial interfaces. + +Signed-off-by: Aurélien Jacobs +Cc: stable@vger.kernel.org +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/option.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c +index 406cfd5ad9f48..17c3044c2d26a 100644 +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -613,6 +613,11 @@ static void option_instat_callback(struct urb *urb); + /* Luat Air72*U series based on UNISOC UIS8910 uses UNISOC's vendor ID */ + #define LUAT_PRODUCT_AIR720U 0x4e00 + ++/* MeiG Smart Technology products */ ++#define MEIGSMART_VENDOR_ID 0x2dee ++/* MeiG Smart SLM320 based on UNISOC UIS8910 */ ++#define MEIGSMART_PRODUCT_SLM320 0x4d41 ++ + /* Device flags */ + + /* Highest interface number which can be used with NCTRL() and RSVD() */ +@@ -2282,6 +2287,7 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM320, 0xff, 0, 0) }, + { } /* Terminating entry */ + }; + MODULE_DEVICE_TABLE(usb, option_ids); +-- +2.43.0 + diff --git a/queue-5.4/vfio-platform-disable-virqfds-on-cleanup.patch b/queue-5.4/vfio-platform-disable-virqfds-on-cleanup.patch new file mode 100644 index 00000000000..c3f0dcdd174 --- /dev/null +++ b/queue-5.4/vfio-platform-disable-virqfds-on-cleanup.patch @@ -0,0 +1,44 @@ +From e5ea57bd9d759bb9bdd1fceb8cbd54cba0320bfd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Mar 2024 16:05:26 -0700 +Subject: vfio/platform: Disable virqfds on cleanup + +From: Alex Williamson + +[ Upstream commit fcdc0d3d40bc26c105acf8467f7d9018970944ae ] + +irqfds for mask and unmask that are not specifically disabled by the +user are leaked. Remove any irqfds during cleanup + +Cc: Eric Auger +Cc: +Fixes: a7fa7c77cf15 ("vfio/platform: implement IRQ masking/unmasking via an eventfd") +Reviewed-by: Kevin Tian +Reviewed-by: Eric Auger +Link: https://lore.kernel.org/r/20240308230557.805580-6-alex.williamson@redhat.com +Signed-off-by: Alex Williamson +Signed-off-by: Sasha Levin +--- + drivers/vfio/platform/vfio_platform_irq.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/vfio/platform/vfio_platform_irq.c b/drivers/vfio/platform/vfio_platform_irq.c +index c5b09ec0a3c98..f2893f2fcaabd 100644 +--- a/drivers/vfio/platform/vfio_platform_irq.c ++++ b/drivers/vfio/platform/vfio_platform_irq.c +@@ -321,8 +321,11 @@ void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev) + { + int i; + +- for (i = 0; i < vdev->num_irqs; i++) ++ for (i = 0; i < vdev->num_irqs; i++) { ++ vfio_virqfd_disable(&vdev->irqs[i].mask); ++ vfio_virqfd_disable(&vdev->irqs[i].unmask); + vfio_set_trigger(vdev, i, -1, NULL); ++ } + + vdev->num_irqs = 0; + kfree(vdev->irqs); +-- +2.43.0 + diff --git a/queue-5.4/wifi-brcmfmac-fix-use-after-free-bug-in-brcmf_cfg802.patch b/queue-5.4/wifi-brcmfmac-fix-use-after-free-bug-in-brcmf_cfg802.patch new file mode 100644 index 00000000000..85d2b1c5cc5 --- /dev/null +++ b/queue-5.4/wifi-brcmfmac-fix-use-after-free-bug-in-brcmf_cfg802.patch @@ -0,0 +1,77 @@ +From 0ae8d3f3edc36b02b54ff1ca83077e8d790fd287 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 7 Jan 2024 08:25:04 +0100 +Subject: wifi: brcmfmac: Fix use-after-free bug in brcmf_cfg80211_detach + +From: Zheng Wang + +[ Upstream commit 0f7352557a35ab7888bc7831411ec8a3cbe20d78 ] + +This is the candidate patch of CVE-2023-47233 : +https://nvd.nist.gov/vuln/detail/CVE-2023-47233 + +In brcm80211 driver,it starts with the following invoking chain +to start init a timeout worker: + +->brcmf_usb_probe + ->brcmf_usb_probe_cb + ->brcmf_attach + ->brcmf_bus_started + ->brcmf_cfg80211_attach + ->wl_init_priv + ->brcmf_init_escan + ->INIT_WORK(&cfg->escan_timeout_work, + brcmf_cfg80211_escan_timeout_worker); + +If we disconnect the USB by hotplug, it will call +brcmf_usb_disconnect to make cleanup. The invoking chain is : + +brcmf_usb_disconnect + ->brcmf_usb_disconnect_cb + ->brcmf_detach + ->brcmf_cfg80211_detach + ->kfree(cfg); + +While the timeout woker may still be running. This will cause +a use-after-free bug on cfg in brcmf_cfg80211_escan_timeout_worker. + +Fix it by deleting the timer and canceling the worker in +brcmf_cfg80211_detach. + +Fixes: e756af5b30b0 ("brcmfmac: add e-scan support.") +Signed-off-by: Zheng Wang +Cc: stable@vger.kernel.org +[arend.vanspriel@broadcom.com: keep timer delete as is and cancel work just before free] +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +Link: https://msgid.link/20240107072504.392713-1-arend.vanspriel@broadcom.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index b7ceea0b3204d..668c8897c1095 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -710,8 +710,7 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, + scan_request = cfg->scan_request; + cfg->scan_request = NULL; + +- if (timer_pending(&cfg->escan_timeout)) +- del_timer_sync(&cfg->escan_timeout); ++ timer_delete_sync(&cfg->escan_timeout); + + if (fw_abort) { + /* Do a scan abort to stop the driver's scan engine */ +@@ -7240,6 +7239,7 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) + brcmf_btcoex_detach(cfg); + wiphy_unregister(cfg->wiphy); + wl_deinit_priv(cfg); ++ cancel_work_sync(&cfg->escan_timeout_work); + brcmf_free_wiphy(cfg->wiphy); + kfree(cfg); + } +-- +2.43.0 + diff --git a/queue-5.4/x86-cpu-amd-update-the-zenbleed-microcode-revisions.patch b/queue-5.4/x86-cpu-amd-update-the-zenbleed-microcode-revisions.patch new file mode 100644 index 00000000000..001c457d430 --- /dev/null +++ b/queue-5.4/x86-cpu-amd-update-the-zenbleed-microcode-revisions.patch @@ -0,0 +1,44 @@ +From bbe48e9f7d1a9ae4b8ebf7bb04e9370f2b7aeea4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Mar 2024 22:42:27 +0100 +Subject: x86/CPU/AMD: Update the Zenbleed microcode revisions + +From: Borislav Petkov (AMD) + +[ Upstream commit 5c84b051bd4e777cf37aaff983277e58c99618d5 ] + +Update them to the correct revision numbers. + +Fixes: 522b1d69219d ("x86/cpu/amd: Add a Zenbleed fix") +Signed-off-by: Borislav Petkov (AMD) +Cc: +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/cpu/amd.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c +index 4e84203fc067d..533451498c8f8 100644 +--- a/arch/x86/kernel/cpu/amd.c ++++ b/arch/x86/kernel/cpu/amd.c +@@ -998,11 +998,11 @@ static bool cpu_has_zenbleed_microcode(void) + u32 good_rev = 0; + + switch (boot_cpu_data.x86_model) { +- case 0x30 ... 0x3f: good_rev = 0x0830107a; break; +- case 0x60 ... 0x67: good_rev = 0x0860010b; break; +- case 0x68 ... 0x6f: good_rev = 0x08608105; break; +- case 0x70 ... 0x7f: good_rev = 0x08701032; break; +- case 0xa0 ... 0xaf: good_rev = 0x08a00008; break; ++ case 0x30 ... 0x3f: good_rev = 0x0830107b; break; ++ case 0x60 ... 0x67: good_rev = 0x0860010c; break; ++ case 0x68 ... 0x6f: good_rev = 0x08608107; break; ++ case 0x70 ... 0x7f: good_rev = 0x08701033; break; ++ case 0xa0 ... 0xaf: good_rev = 0x08a00009; break; + + default: + return false; +-- +2.43.0 +