--- /dev/null
+From ac6b4d29a34de7f7c66d77d242c1df41c07b9373 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Mar 2024 22:46:50 +0100
+Subject: ahci: asm1064: asm1166: don't limit reported ports
+
+From: Conrad Kostecki <conikost@gentoo.org>
+
+[ 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 <cryptearth@googlemail.com>
+Signed-off-by: Conrad Kostecki <conikost@gentoo.org>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+[cassel: rewrote commit message]
+Signed-off-by: Niklas Cassel <cassel@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/ahci.c | 13 -------------
+ 1 file changed, 13 deletions(-)
+
+diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
+index 6b1562fed85ed..ab3ea47ecce3a 100644
+--- a/drivers/ata/ahci.c
++++ b/drivers/ata/ahci.c
+@@ -634,19 +634,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
+
--- /dev/null
+From 26bcc6f3f9548334f78f32199864a897b547a668 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 14 Feb 2024 17:57:57 +0100
+Subject: ahci: asm1064: correct count of reported ports
+
+From: Andrey Jr. Melnikov <temnota.am@gmail.com>
+
+[ 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" <temnota.am@gmail.com>
+Signed-off-by: Niklas Cassel <cassel@kernel.org>
+Stable-dep-of: 6cd8adc3e189 ("ahci: asm1064: asm1166: don't limit reported ports")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 abdfd440987b4..6b1562fed85ed 100644
+--- a/drivers/ata/ahci.c
++++ b/drivers/ata/ahci.c
+@@ -634,9 +634,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
+
--- /dev/null
+From eac6e50536430d612ac3e1b7e967459c7acb8972 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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ć <duje.mihanovic@skole.hr>
+
+[ 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: <stable@vger.kernel.org>
+Signed-off-by: Duje Mihanović <duje.mihanovic@skole.hr>
+Reported-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Closes: https://lore.kernel.org/linux-devicetree/1410884282-18041-1-git-send-email-k.kozlowski@samsung.com/
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+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 <krzysztof.kozlowski@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 0fdcc2edcf4b6..f12d5aa773f30 100644
+--- a/arch/arm/boot/dts/mmp2-brownstone.dts
++++ b/arch/arm/boot/dts/mmp2-brownstone.dts
+@@ -30,7 +30,7 @@ &uart3 {
+ &twsi1 {
+ status = "okay";
+ pmic: max8925@3c {
+- compatible = "maxium,max8925";
++ compatible = "maxim,max8925";
+ reg = <0x3c>;
+ interrupts = <1>;
+ interrupt-parent = <&intcmux4>;
+--
+2.43.0
+
--- /dev/null
+From 87a0058ac3794889406cbed55db219139cafb7d1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Mar 2020 18:41:01 +0100
+Subject: ARM: dts: mmp2-brownstone: Don't redeclare phandle references
+
+From: Lubomir Rintel <lkundrak@v3.sk>
+
+[ 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 <lkundrak@v3.sk>
+Reviewed-by: Rob Herring <robh@kernel.org>
+Link: https://lore.kernel.org/r/20200320174107.29406-5-lkundrak@v3.sk
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 831e0cd4f9ee ("arm: dts: marvell: Fix maxium->maxim typo in brownstone dts")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 350208c5e1ed2..0fdcc2edcf4b6 100644
+--- a/arch/arm/boot/dts/mmp2-brownstone.dts
++++ b/arch/arm/boot/dts/mmp2-brownstone.dts
+@@ -21,176 +21,174 @@ chosen {
+ 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
+
--- /dev/null
+From 569e0074a68509876455eb78047a732f53960ba3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Feb 2024 19:07:48 +0100
+Subject: clk: qcom: gcc-ipq8074: fix terminating of frequency table arrays
+
+From: Gabor Juhos <j4g8y7@gmail.com>
+
+[ 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 <j4g8y7@gmail.com>
+Reviewed-by: Stephen Boyd <sboyd@kernel.org>
+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 <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 eff38d22738c4..e38a1f87263b8 100644
+--- a/drivers/clk/qcom/gcc-ipq8074.c
++++ b/drivers/clk/qcom/gcc-ipq8074.c
+@@ -980,6 +980,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 = {
+@@ -1085,6 +1086,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
+
--- /dev/null
+From 3a1b427ff627f15e2d837ead93fd11715fd40b8a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Feb 2024 19:07:51 +0100
+Subject: clk: qcom: mmcc-apq8084: fix terminating of frequency table arrays
+
+From: Gabor Juhos <j4g8y7@gmail.com>
+
+[ 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 <j4g8y7@gmail.com>
+Reviewed-by: Stephen Boyd <sboyd@kernel.org>
+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 <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 4ce1d7c88377f..36a40b0ddfa1f 100644
+--- a/drivers/clk/qcom/mmcc-apq8084.c
++++ b/drivers/clk/qcom/mmcc-apq8084.c
+@@ -341,6 +341,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 = {
+@@ -365,6 +366,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
+
--- /dev/null
+From 7acfd3e5c473591e5b1a6ec2a358d31c26d6a358 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Feb 2024 19:07:52 +0100
+Subject: clk: qcom: mmcc-msm8974: fix terminating of frequency table arrays
+
+From: Gabor Juhos <j4g8y7@gmail.com>
+
+[ 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 <j4g8y7@gmail.com>
+Reviewed-by: Stephen Boyd <sboyd@kernel.org>
+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 <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 91818516c3e0c..124d21f19e2c7 100644
+--- a/drivers/clk/qcom/mmcc-msm8974.c
++++ b/drivers/clk/qcom/mmcc-msm8974.c
+@@ -291,6 +291,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 = {
+@@ -315,6 +316,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
+
--- /dev/null
+From 1cf8737b7847080156bbd3e3b86fe54b49a7bf27 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Oct 2023 13:27:19 +0100
+Subject: crypto: qat - fix double free during reset
+
+From: Svyatoslav Pankratov <svyatoslav.pankratov@intel.com>
+
+[ 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 <svyatoslav.pankratov@intel.com>
+Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Stable-dep-of: 7d42e097607c ("crypto: qat - resolve race condition during AER recovery")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 9225d060e18f4..44b91cb73dd19 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
+
--- /dev/null
+From d4c80f722a31411015c24be063f690885d0c33d5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 9 Feb 2024 13:43:42 +0100
+Subject: crypto: qat - resolve race condition during AER recovery
+
+From: Damian Muszynski <damian.muszynski@intel.com>
+
+[ 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: <stable@vger.kernel.org>
+Signed-off-by: Damian Muszynski <damian.muszynski@intel.com>
+Reviewed-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 44b91cb73dd19..7242a1ee86de7 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
+
--- /dev/null
+From 1b3818962a987bdc835b4603c3028f209b754aa5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Mar 2024 15:23:06 +0800
+Subject: dm-raid: fix lockdep waring in "pers->hot_add_disk"
+
+From: Yu Kuai <yukuai3@huawei.com>
+
+[ 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 <yukuai3@huawei.com>
+Signed-off-by: Xiao Ni <xni@redhat.com>
+Acked-by: Mike Snitzer <snitzer@kernel.org>
+Signed-off-by: Song Liu <song@kernel.org>
+Link: https://lore.kernel.org/r/20240305072306.2562024-10-yukuai1@huaweicloud.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 1759134fce824..2a8746f9c6d87 100644
+--- a/drivers/md/dm-raid.c
++++ b/drivers/md/dm-raid.c
+@@ -4023,7 +4023,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
+
--- /dev/null
+From daebe5010bd15ac347ac995a4f66777fa72d664f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Mar 2024 18:03:43 +0200
+Subject: drm/imx/ipuv3: do not return negative values from .get_modes()
+
+From: Jani Nikula <jani.nikula@intel.com>
+
+[ 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 <p.zabel@pengutronix.de>
+Cc: stable@vger.kernel.org
+Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
+Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/311f6eec96d47949b16a670529f4d89fcd97aefa.1709913674.git.jani.nikula@intel.com
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 a96d99cbec4d0..290f68b9adfea 100644
+--- a/drivers/gpu/drm/imx/parallel-display.c
++++ b/drivers/gpu/drm/imx/parallel-display.c
+@@ -78,14 +78,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
+
--- /dev/null
+From 1da708797a30d20a5033729bd6afc7f1da7a68a1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jan 2020 14:55:09 +0100
+Subject: drm/imx: pd: Use bus format/flags provided by the bridge when
+ available
+
+From: Boris Brezillon <boris.brezillon@collabora.com>
+
+[ Upstream commit fe141cedc4333e3b76307f096e02b2c1e60f65d5 ]
+
+Now that bridges can expose the bus format/flags they expect, we can
+use those instead of the relying on the display_info provided by the
+connector (which is only valid if the encoder is directly connected
+to bridge element driving the panel/display).
+
+We also explicitly expose the bus formats supported by our encoder by
+filling encoder->output_bus_caps with proper info.
+
+v10:
+* Add changelog to the commit message
+* Use kmalloc() instead of kcalloc()
+* Add a dev_warn() when unsupported flags are requested
+
+v8 -> v9:
+* No changes
+
+v7:
+* Add an imx_pd_format_supported() helper (suggested by Philipp)
+* Simplify imx_pd_bridge_atomic_get_output_bus_fmts() (suggested by Philipp)
+* Simplify imx_pd_bridge_atomic_get_input_bus_fmts()
+* Explicitly set the duplicate/destro_state() and reset() hooks
+
+v4 -> v6:
+* Patch was not part of the series
+
+v3 (all suggested by Philipp):
+* Adjust to match core changes
+* Propagate output format to input format
+* Pick a default value when output_fmt = _FIXED
+* Add missing BGR888 and GBR888 fmts to imx_pd_bus_fmts[]
+
+v2:
+* Adjust things to match the new bus-format negotiation infra
+
+Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
+Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20200128135514.108171-8-boris.brezillon@collabora.com
+Stable-dep-of: c2da9ada6496 ("drm/imx/ipuv3: do not return negative values from .get_modes()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/imx/parallel-display.c | 176 +++++++++++++++++++++----
+ 1 file changed, 151 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
+index e9dff31b377c4..a96d99cbec4d0 100644
+--- a/drivers/gpu/drm/imx/parallel-display.c
++++ b/drivers/gpu/drm/imx/parallel-display.c
+@@ -29,6 +29,7 @@
+ struct imx_parallel_display {
+ struct drm_connector connector;
+ struct drm_encoder encoder;
++ struct drm_bridge bridge;
+ struct device *dev;
+ void *edid;
+ int edid_len;
+@@ -36,7 +37,7 @@ struct imx_parallel_display {
+ u32 bus_flags;
+ struct drm_display_mode mode;
+ struct drm_panel *panel;
+- struct drm_bridge *bridge;
++ struct drm_bridge *next_bridge;
+ };
+
+ static inline struct imx_parallel_display *con_to_imxpd(struct drm_connector *c)
+@@ -49,6 +50,11 @@ static inline struct imx_parallel_display *enc_to_imxpd(struct drm_encoder *e)
+ return container_of(e, struct imx_parallel_display, encoder);
+ }
+
++static inline struct imx_parallel_display *bridge_to_imxpd(struct drm_bridge *b)
++{
++ return container_of(b, struct imx_parallel_display, bridge);
++}
++
+ static int imx_pd_connector_get_modes(struct drm_connector *connector)
+ {
+ struct imx_parallel_display *imxpd = con_to_imxpd(connector);
+@@ -99,37 +105,148 @@ static struct drm_encoder *imx_pd_connector_best_encoder(
+ return &imxpd->encoder;
+ }
+
+-static void imx_pd_encoder_enable(struct drm_encoder *encoder)
++static void imx_pd_bridge_enable(struct drm_bridge *bridge)
+ {
+- struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
++ struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
+
+ drm_panel_prepare(imxpd->panel);
+ drm_panel_enable(imxpd->panel);
+ }
+
+-static void imx_pd_encoder_disable(struct drm_encoder *encoder)
++static void imx_pd_bridge_disable(struct drm_bridge *bridge)
+ {
+- struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
++ struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
+
+ drm_panel_disable(imxpd->panel);
+ drm_panel_unprepare(imxpd->panel);
+ }
+
+-static int imx_pd_encoder_atomic_check(struct drm_encoder *encoder,
+- struct drm_crtc_state *crtc_state,
+- struct drm_connector_state *conn_state)
++static const u32 imx_pd_bus_fmts[] = {
++ MEDIA_BUS_FMT_RGB888_1X24,
++ MEDIA_BUS_FMT_BGR888_1X24,
++ MEDIA_BUS_FMT_GBR888_1X24,
++ MEDIA_BUS_FMT_RGB666_1X18,
++ MEDIA_BUS_FMT_RGB666_1X24_CPADHI,
++ MEDIA_BUS_FMT_RGB565_1X16,
++};
++
++static u32 *
++imx_pd_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
++ struct drm_bridge_state *bridge_state,
++ struct drm_crtc_state *crtc_state,
++ struct drm_connector_state *conn_state,
++ unsigned int *num_output_fmts)
+ {
+- struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc_state);
+ struct drm_display_info *di = &conn_state->connector->display_info;
+- struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
++ struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
++ u32 *output_fmts;
+
+- if (!imxpd->bus_format && di->num_bus_formats) {
+- imx_crtc_state->bus_flags = di->bus_flags;
+- imx_crtc_state->bus_format = di->bus_formats[0];
+- } else {
+- imx_crtc_state->bus_flags = imxpd->bus_flags;
+- imx_crtc_state->bus_format = imxpd->bus_format;
++ if (!imxpd->bus_format && !di->num_bus_formats) {
++ *num_output_fmts = ARRAY_SIZE(imx_pd_bus_fmts);
++ return kmemdup(imx_pd_bus_fmts, sizeof(imx_pd_bus_fmts),
++ GFP_KERNEL);
++ }
++
++ *num_output_fmts = 1;
++ output_fmts = kmalloc(sizeof(*output_fmts), GFP_KERNEL);
++ if (!output_fmts)
++ return NULL;
++
++ if (!imxpd->bus_format && di->num_bus_formats)
++ output_fmts[0] = di->bus_formats[0];
++ else
++ output_fmts[0] = imxpd->bus_format;
++
++ return output_fmts;
++}
++
++static bool imx_pd_format_supported(u32 output_fmt)
++{
++ unsigned int i;
++
++ for (i = 0; i < ARRAY_SIZE(imx_pd_bus_fmts); i++) {
++ if (imx_pd_bus_fmts[i] == output_fmt)
++ return true;
++ }
++
++ return false;
++}
++
++static u32 *
++imx_pd_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
++ struct drm_bridge_state *bridge_state,
++ struct drm_crtc_state *crtc_state,
++ struct drm_connector_state *conn_state,
++ u32 output_fmt,
++ unsigned int *num_input_fmts)
++{
++ struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
++ u32 *input_fmts;
++
++ /*
++ * If the next bridge does not support bus format negotiation, let's
++ * use the static bus format definition (imxpd->bus_format) if it's
++ * specified, RGB888 when it's not.
++ */
++ if (output_fmt == MEDIA_BUS_FMT_FIXED)
++ output_fmt = imxpd->bus_format ? : MEDIA_BUS_FMT_RGB888_1X24;
++
++ /* Now make sure the requested output format is supported. */
++ if ((imxpd->bus_format && imxpd->bus_format != output_fmt) ||
++ !imx_pd_format_supported(output_fmt)) {
++ *num_input_fmts = 0;
++ return NULL;
++ }
++
++ *num_input_fmts = 1;
++ input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL);
++ if (!input_fmts)
++ return NULL;
++
++ input_fmts[0] = output_fmt;
++ return input_fmts;
++}
++
++static int imx_pd_bridge_atomic_check(struct drm_bridge *bridge,
++ struct drm_bridge_state *bridge_state,
++ struct drm_crtc_state *crtc_state,
++ struct drm_connector_state *conn_state)
++{
++ struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc_state);
++ struct drm_display_info *di = &conn_state->connector->display_info;
++ struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
++ struct drm_bridge_state *next_bridge_state = NULL;
++ struct drm_bridge *next_bridge;
++ u32 bus_flags, bus_fmt;
++
++ next_bridge = drm_bridge_get_next_bridge(bridge);
++ if (next_bridge)
++ next_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
++ next_bridge);
++
++ if (next_bridge_state)
++ bus_flags = next_bridge_state->input_bus_cfg.flags;
++ else if (!imxpd->bus_format && di->num_bus_formats)
++ bus_flags = di->bus_flags;
++ else
++ bus_flags = imxpd->bus_flags;
++
++ bus_fmt = bridge_state->input_bus_cfg.format;
++ if (!imx_pd_format_supported(bus_fmt))
++ return -EINVAL;
++
++ if (bus_flags &
++ ~(DRM_BUS_FLAG_DE_LOW | DRM_BUS_FLAG_DE_HIGH |
++ DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE |
++ DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)) {
++ dev_warn(imxpd->dev, "invalid bus_flags (%x)\n", bus_flags);
++ return -EINVAL;
+ }
++
++ bridge_state->output_bus_cfg.flags = bus_flags;
++ bridge_state->input_bus_cfg.flags = bus_flags;
++ imx_crtc_state->bus_flags = bus_flags;
++ imx_crtc_state->bus_format = bridge_state->input_bus_cfg.format;
+ imx_crtc_state->di_hsync_pin = 2;
+ imx_crtc_state->di_vsync_pin = 3;
+
+@@ -153,10 +270,15 @@ static const struct drm_encoder_funcs imx_pd_encoder_funcs = {
+ .destroy = imx_drm_encoder_destroy,
+ };
+
+-static const struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = {
+- .enable = imx_pd_encoder_enable,
+- .disable = imx_pd_encoder_disable,
+- .atomic_check = imx_pd_encoder_atomic_check,
++static const struct drm_bridge_funcs imx_pd_bridge_funcs = {
++ .enable = imx_pd_bridge_enable,
++ .disable = imx_pd_bridge_disable,
++ .atomic_reset = drm_atomic_helper_bridge_reset,
++ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
++ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
++ .atomic_check = imx_pd_bridge_atomic_check,
++ .atomic_get_input_bus_fmts = imx_pd_bridge_atomic_get_input_bus_fmts,
++ .atomic_get_output_bus_fmts = imx_pd_bridge_atomic_get_output_bus_fmts,
+ };
+
+ static int imx_pd_register(struct drm_device *drm,
+@@ -176,11 +298,13 @@ static int imx_pd_register(struct drm_device *drm,
+ */
+ imxpd->connector.dpms = DRM_MODE_DPMS_OFF;
+
+- drm_encoder_helper_add(encoder, &imx_pd_encoder_helper_funcs);
+ drm_encoder_init(drm, encoder, &imx_pd_encoder_funcs,
+ DRM_MODE_ENCODER_NONE, NULL);
+
+- if (!imxpd->bridge) {
++ imxpd->bridge.funcs = &imx_pd_bridge_funcs;
++ drm_bridge_attach(encoder, &imxpd->bridge, NULL);
++
++ if (!imxpd->next_bridge) {
+ drm_connector_helper_add(&imxpd->connector,
+ &imx_pd_connector_helper_funcs);
+ drm_connector_init(drm, &imxpd->connector,
+@@ -191,8 +315,9 @@ static int imx_pd_register(struct drm_device *drm,
+ if (imxpd->panel)
+ drm_panel_attach(imxpd->panel, &imxpd->connector);
+
+- if (imxpd->bridge) {
+- ret = drm_bridge_attach(encoder, imxpd->bridge, NULL);
++ if (imxpd->next_bridge) {
++ ret = drm_bridge_attach(encoder, imxpd->next_bridge,
++ &imxpd->bridge);
+ if (ret < 0) {
+ dev_err(imxpd->dev, "failed to attach bridge: %d\n",
+ ret);
+@@ -237,7 +362,8 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
+ imxpd->bus_format = bus_format;
+
+ /* port@1 is the output port */
+- ret = drm_of_find_panel_or_bridge(np, 1, 0, &imxpd->panel, &imxpd->bridge);
++ ret = drm_of_find_panel_or_bridge(np, 1, 0, &imxpd->panel,
++ &imxpd->next_bridge);
+ if (ret && ret != -ENODEV)
+ return ret;
+
+--
+2.43.0
+
--- /dev/null
+From 7cf20b631a75a18b2e20d7a3b5936ad5ba341d63 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Mar 2024 18:03:44 +0200
+Subject: drm/vc4: hdmi: do not return negative values from .get_modes()
+
+From: Jani Nikula <jani.nikula@intel.com>
+
+[ 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 <mripard@kernel.org>
+Cc: stable@vger.kernel.org
+Acked-by: Maxime Ripard <mripard@kernel.org>
+Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/dcda6d4003e2c6192987916b35c7304732800e08.1709913674.git.jani.nikula@intel.com
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 1161662664577..013dfc63c824e 100644
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -276,7 +276,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
+
--- /dev/null
+From c2f26e7ce51958bc1eb98f1e35ab0043a418c273 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Feb 2024 15:50:09 +0000
+Subject: ext4: fix corruption during on-line resize
+
+From: Maximilian Heyne <mheyne@amazon.de>
+
+[ 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/<some_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: <stable@vger.kernel.org>
+Signed-off-by: Maximilian Heyne <mheyne@amazon.de>
+Tested-by: Srivathsa Dara <srivathsa.d.dara@oracle.com>
+Reviewed-by: Srivathsa Dara <srivathsa.d.dara@oracle.com>
+Link: https://lore.kernel.org/r/20240215155009.94493-1-mheyne@amazon.de
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 97af09d6e7e6c..7d615c00b632b 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
+
--- /dev/null
+From d75c3e07af2e7db054a9e2483c4e48a3dbdb8965 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Feb 2024 13:26:26 +0100
+Subject: fat: fix uninitialized field in nostale filehandles
+
+From: Jan Kara <jack@suse.cz>
+
+[ 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 <jack@suse.cz>
+Acked-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
+Cc: Amir Goldstein <amir73il@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/fat/nfs.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/fs/fat/nfs.c b/fs/fat/nfs.c
+index eb192656fba27..f442a8d2f114b 100644
+--- a/fs/fat/nfs.c
++++ b/fs/fat/nfs.c
+@@ -139,6 +139,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
+
--- /dev/null
+From dcee3958857991a5564ecac25fe6e7490f65eb1e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Feb 2024 16:50:49 +0100
+Subject: fuse: don't unhash root
+
+From: Miklos Szeredi <mszeredi@redhat.com>
+
+[ 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: <stable@vger.kernel.org> # v5.11
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 1c754a02fb06b..aa0a5e3960909 100644
+--- a/fs/fuse/fuse_i.h
++++ b/fs/fuse/fuse_i.h
+@@ -706,7 +706,6 @@ static inline u64 get_node_id(struct inode *inode)
+
+ 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 3b51c881baf8c..a67769c357b2d 100644
+--- a/fs/fuse/inode.c
++++ b/fs/fuse/inode.c
+@@ -324,8 +324,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
+
--- /dev/null
+From 8bf3e0e5bbeb59a2c6ba4c79106fcf960b12769c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Mar 2024 12:06:58 +0100
+Subject: hwmon: (amc6821) add of_match table
+
+From: Josua Mayer <josua@solid-run.com>
+
+[ 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 <josua@solid-run.com>
+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 <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/amc6821.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c
+index 46b4e35fd5555..b562337df7b3c 100644
+--- a/drivers/hwmon/amc6821.c
++++ b/drivers/hwmon/amc6821.c
+@@ -1003,10 +1003,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
+
--- /dev/null
+From 82f7b316fe1ee30f4a71e5657a67c323fde9cc8c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Mar 2024 15:12:47 -0700
+Subject: kbuild: Move -Wenum-{compare-conditional,enum-conversion} into W=1
+
+From: Nathan Chancellor <nathan@kernel.org>
+
+[ 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 <yonghong.song@linux.dev>
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ scripts/Makefile.extrawarn | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn
+index e15cd63428ba7..c2e41daf373f8 100644
+--- a/scripts/Makefile.extrawarn
++++ b/scripts/Makefile.extrawarn
+@@ -75,5 +75,7 @@ KBUILD_CFLAGS += $(call cc-disable-warning, uninitialized)
+ 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
+
--- /dev/null
+From 58d41c9ae61c4309315ff6e9e3817d85beb11350 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 Jan 2024 17:15:30 -0800
+Subject: KVM: Always flush async #PF workqueue when vCPU is being destroyed
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ 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:
+ <TASK>
+ 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
+ </TASK>
+ ---[ 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:
+ <TASK>
+ __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
+ </TASK>
+
+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 <dmatlack@google.com>
+Reviewed-by: Xu Yilun <yilun.xu@intel.com>
+Reviewed-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+Link: https://lore.kernel.org/r/20240110011533.503302-2-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 c9861c2315e8e..3e17f8c7432c1 100644
+--- a/virt/kvm/async_pf.c
++++ b/virt/kvm/async_pf.c
+@@ -110,7 +110,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)
+@@ -137,7 +157,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
+@@ -149,7 +168,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);
+
+@@ -173,7 +195,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);
+ }
+ }
+
+@@ -202,7 +224,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
+
--- /dev/null
+From 4dad784985406e39c7f0262747c2e38be3f49fa4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <bass@buaa.edu.cn>
+Signed-off-by: Gui-Dong Han <2045gemini@gmail.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 0ef8f054a7950..6017602aead62 100644
+--- a/drivers/media/tuners/xc4000.c
++++ b/drivers/media/tuners/xc4000.c
+@@ -1527,10 +1527,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;
+@@ -1541,8 +1541,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
+
--- /dev/null
+From ba55d8ed17c95d28e74e5228778900e2c19ddfd0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Mar 2024 16:04:23 +0800
+Subject: memtest: use {READ,WRITE}_ONCE in memory scanning
+
+From: Qiang Zhang <qiang4.zhang@intel.com>
+
+[ 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 <qiang4.zhang@intel.com>
+Cc: Bill Wendling <morbo@google.com>
+Cc: Justin Stitt <justinstitt@google.com>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nick Desaulniers <ndesaulniers@google.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From d47ba4aa9b89095f85eb19a33a50cffd55da8dd8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Mar 2024 10:44:38 +0900
+Subject: mmc: core: Fix switch on gp3 partition
+
+From: Dominique Martinet <dominique.martinet@atmark-techno.com>
+
+[ 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 <jorge@foundries.io>
+Signed-off-by: Dominique Martinet <dominique.martinet@atmark-techno.com>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Link: https://lore.kernel.org/r/20240306-mmc-partswitch-v1-1-bf116985d950@codewreck.org
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 ef9422917e1ca..c3b329946429c 100644
+--- a/drivers/mmc/core/block.c
++++ b/drivers/mmc/core/block.c
+@@ -851,10 +851,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)
+@@ -869,10 +870,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
+
--- /dev/null
+From 79316ff6e0f07a610c1fb471b40244900023e8c8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Mar 2024 11:42:56 +0100
+Subject: mmc: tmio: avoid concurrent runs of mmc_request_done()
+
+From: Wolfram Sang <wsa+renesas@sang-engineering.com>
+
+[ 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 <dirk.behme@de.bosch.com>
+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 <wsa+renesas@sang-engineering.com>
+Tested-by: Dirk Behme <dirk.behme@de.bosch.com>
+Reviewed-by: Dirk Behme <dirk.behme@de.bosch.com>
+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 <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 f819757e125e0..ae8913e5adc70 100644
+--- a/drivers/mmc/host/tmio_mmc_core.c
++++ b/drivers/mmc/host/tmio_mmc_core.c
+@@ -213,6 +213,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
+
--- /dev/null
+From dd86ad28d5435456f39cb57a8bc3953119b80b66 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <konishi.ryusuke@gmail.com>
+
+[ 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 <konishi.ryusuke@gmail.com>
+Reported-by: syzbot+cfed5b56649bddf80d6e@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=cfed5b56649bddf80d6e
+Tested-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 8b0aab043fdb946b11ae8d864f2ba2ea72b576e9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Mar 2024 19:58:27 +0900
+Subject: nilfs2: prevent kernel bug at submit_bh_wbc()
+
+From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+
+[ 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 <konishi.ryusuke@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 99bf688a2f7d846e7e7c3ab0a7b120dadbb46aef Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Aug 2020 18:35:49 -0700
+Subject: nilfs2: use a more common logging style
+
+From: Joe Perches <joe@perches.com>
+
+[ Upstream commit a1d0747a393a079631130d61faa2a61027d1c789 ]
+
+Add macros for nilfs_<level>(sb, fmt, ...) and convert the uses of
+'nilfs_msg(sb, KERN_<LEVEL>, ...)' to 'nilfs_<level>(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 <joe@perches.com>
+Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Link: http://lkml.kernel.org/r/1595860111-3920-4-git-send-email-konishi.ryusuke@gmail.com
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Stable-dep-of: 269cdf353b5b ("nilfs2: prevent kernel bug at submit_bh_wbc()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 dfb2083b8ce1c..ecb5e4cf058b5 100644
+--- a/fs/nilfs2/ioctl.c
++++ b/fs/nilfs2/ioctl.c
+@@ -574,25 +574,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;
+ }
+@@ -842,8 +842,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;
+ }
+
+@@ -952,7 +951,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 cca30f0f965c5..d8dc6e546febe 100644
+--- a/fs/nilfs2/nilfs.h
++++ b/fs/nilfs2/nilfs.h
+@@ -321,6 +321,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 e5fee7fac9154..762dd277099eb 100644
+--- a/fs/nilfs2/page.c
++++ b/fs/nilfs2/page.c
+@@ -401,9 +401,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);
+@@ -419,9 +418,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 99bcb4ab47a61..6d33eecff2619 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.
+ */
+@@ -186,8 +186,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],
+@@ -257,7 +256,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] &&
+@@ -367,9 +366,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;
+ }
+@@ -563,7 +562,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;
+@@ -661,8 +660,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
+@@ -794,7 +792,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;
+@@ -810,8 +808,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;
+ }
+ }
+@@ -847,10 +844,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)
+@@ -913,7 +910,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;
+@@ -921,7 +918,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;
+@@ -940,12 +937,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;
+ }
+@@ -973,7 +970,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;
+ }
+
+@@ -993,7 +990,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;
+@@ -1002,7 +999,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;
+@@ -1099,7 +1096,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;
+@@ -1162,8 +1159,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;
+ }
+
+@@ -1193,9 +1190,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;
+ }
+@@ -1254,7 +1251,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;
+ }
+
+@@ -1357,7 +1354,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
+
--- /dev/null
+From 83b44a145746d0c0cc73bbd6c2e9bd5b7533797a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 29 Sep 2019 21:00:42 +0200
+Subject: parisc: Do not hardcode registers in checksum functions
+
+From: Helge Deller <deller@gmx.de>
+
+[ 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 <deller@gmx.de>
+Stable-dep-of: a2abae8f0b63 ("parisc: Fix ip_fast_csum")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From f3fc09f38ebd520863b2ab0f2ae02c4454541b16 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 10 Feb 2024 11:15:56 -0800
+Subject: parisc: Fix csum_ipv6_magic on 32-bit systems
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ 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 <palmer@rivosinc.com>
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Tested-by: Charlie Jenkins <charlie@rivosinc.com>
+Reviewed-by: Charlie Jenkins <charlie@rivosinc.com>
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 0cc85c467f723a50c503d8bdf3e2e9604c9a7b52 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Feb 2024 15:46:31 -0800
+Subject: parisc: Fix csum_ipv6_magic on 64-bit systems
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ 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 <palmer@rivosinc.com>
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Reviewed-by: Charlie Jenkins <charlie@rivosinc.com>
+Tested-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From da648d10829e55e3062bef8085c9e4ce3e5b6d37 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 10 Feb 2024 09:55:26 -0800
+Subject: parisc: Fix ip_fast_csum
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ 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 <palmer@rivosinc.com>
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Tested-by: Charlie Jenkins <charlie@rivosinc.com>
+Reviewed-by: Charlie Jenkins <charlie@rivosinc.com>
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From a0e80f9c8e7c7c3408ee851834b0230a5cf593fd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <linux@roeck-us.net>
+
+[ 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 <deller@gmx.de>
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 6fd80a9071ad5ea0e7d945db22bdf1e8f8140a68 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <u.kleine-koenig@pengutronix.de>
+
+[ 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 <u.kleine-koenig@pengutronix.de>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Stable-dep-of: 9d5286d4e7f6 ("PCI/PM: Drain runtime-idle callbacks before driver removal")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 78ae1cab9af70..2e5402b09c1ad 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
+
--- /dev/null
+From b9d80cd02698d039f45414aced21fa8e3291b981 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Mar 2024 11:45:38 +0100
+Subject: PCI/PM: Drain runtime-idle callbacks before driver removal
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+[ 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 <kai.heng.feng@canonical.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Tested-by: Ricky Wu <ricky_wu@realtek.com>
+Acked-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 2e5402b09c1ad..031908e42fb54 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
+
--- /dev/null
+From e1ff83dbd2ba5445062363fbe0319ff4a382ff23 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Mar 2024 17:26:57 +0800
+Subject: PM: sleep: wakeirq: fix wake irq warning in system suspend
+
+From: Qingliang Li <qingliang.li@mediatek.com>
+
+[ 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 <d-gole@ti.com>
+Signed-off-by: Qingliang Li <qingliang.li@mediatek.com>
+Reviewed-by: Johan Hovold <johan+linaro@kernel.org>
+Cc: 5.16+ <stable@vger.kernel.org> # 5.16+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 e7ba514999163..bc3637b45cbf7 100644
+--- a/drivers/base/power/wakeirq.c
++++ b/drivers/base/power/wakeirq.c
+@@ -376,8 +376,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
+
--- /dev/null
+From 0c3fe9b38f44f9d7512e69f915715297a20d0900 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Feb 2024 12:14:59 +0530
+Subject: PM: suspend: Set mem_sleep_current during kernel command line setup
+
+From: Maulik Shah <quic_mkshah@quicinc.com>
+
+[ 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 <quic_mkshah@quicinc.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/power/suspend.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
+index 0bd595a0b6103..7a080015a1b3c 100644
+--- a/kernel/power/suspend.c
++++ b/kernel/power/suspend.c
+@@ -202,6 +202,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
+
--- /dev/null
+From c6cfea0aa39a4a2af3e5ff374ea17d5bca9af03f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Feb 2024 23:25:19 +1100
+Subject: powerpc/fsl: Fix mfpmr build errors with newer binutils
+
+From: Michael Ellerman <mpe@ellerman.id.au>
+
+[ 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 <jbglaw@lug-owl.de>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://msgid.link/20240229122521.762431-3-mpe@ellerman.id.au
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 19975ad2eaf6c29185953381f42722e7d03e0562 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <song@kernel.org>
+
+[ 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 <dan@danm.net>
+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 <junxiao.bi@oracle.com>
+Cc: Yu Kuai <yukuai3@huawei.com>
+Signed-off-by: Song Liu <song@kernel.org>
+Reviewed-by: Yu Kuai <yukuai3@huawei.com>
+Link: https://lore.kernel.org/r/20240125082131.788600-1-song@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/raid5.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index e2fcc09a18cdb..b98abe927d06b 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -44,6 +44,7 @@
+ */
+
+ #include <linux/blkdev.h>
++#include <linux/delay.h>
+ #include <linux/kthread.h>
+ #include <linux/raid/pq.h>
+ #include <linux/async_tx.h>
+@@ -6329,7 +6330,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
+
--- /dev/null
+From 6d76aed2af33d6785e991ce06f5fbc168c0bb689 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Feb 2024 15:20:09 +0100
+Subject: s390/zcrypt: fix reference counting on zcrypt card objects
+
+From: Harald Freudenberger <freude@linux.ibm.com>
+
+[ 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 <freude@linux.ibm.com>
+Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 b7cb897cd83e0..3a47e622db10e 100644
+--- a/drivers/s390/crypto/zcrypt_api.c
++++ b/drivers/s390/crypto/zcrypt_api.c
+@@ -158,6 +158,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);
+@@ -177,6 +178,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
+
documentation-hw-vuln-update-spectre-doc.patch
x86-cpu-support-amd-automatic-ibrs.patch
x86-bugs-use-sysfs_emit.patch
+timer-trace-replace-deprecated-vsprintf-pointer-exte.patch
+timer-trace-improve-timer-tracing.patch
+timers-prepare-support-for-preempt_rt.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
+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
+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
+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
+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-don-t-unhash-root.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
+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
+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-imx-pd-use-bus-format-flags-provided-by-the-brid.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
--- /dev/null
+From 6b6875cd79f55185122131aa69114bbfa73fca04 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 24 Feb 2024 11:41:37 +0000
+Subject: slimbus: core: Remove usage of the deprecated ida_simple_xx() API
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ 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 <christophe.jaillet@wanadoo.fr>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20240224114137.85781-2-srinivas.kandagatla@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 3e63e4ce45b04..6270b4165644b 100644
+--- a/drivers/slimbus/core.c
++++ b/drivers/slimbus/core.c
+@@ -409,8 +409,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
+
--- /dev/null
+From d2465efe6d8e2d2bad644e9d2b940add3d439278 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Nov 2023 10:01:22 +0100
+Subject: smack: Handle SMACK64TRANSMUTE in smack_inode_setsecurity()
+
+From: Roberto Sassu <roberto.sassu@huawei.com>
+
+[ 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 <roberto.sassu@huawei.com>
+Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 2f2dc49f53dff..d9bff4ba7f2e8 100644
+--- a/security/smack/smack_lsm.c
++++ b/security/smack/smack_lsm.c
+@@ -2802,6 +2802,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
+
--- /dev/null
+From 9ff6961c77f4e1814ce5a4fa70c000245030c8e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Nov 2023 10:01:21 +0100
+Subject: smack: Set SMACK64TRANSMUTE only for dirs in smack_inode_setxattr()
+
+From: Roberto Sassu <roberto.sassu@huawei.com>
+
+[ 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 <roberto.sassu@huawei.com>
+Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 128a5f464740e..2f2dc49f53dff 100644
+--- a/security/smack/smack_lsm.c
++++ b/security/smack/smack_lsm.c
+@@ -1341,7 +1341,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
+
--- /dev/null
+From 2b6496ce7b74b3e04b8c3ea3b35cc613ae043b48 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Sep 2022 17:57:35 -0400
+Subject: soc: fsl: qbman: Add CGR update function
+
+From: Sean Anderson <sean.anderson@seco.com>
+
+[ 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 <sean.anderson@seco.com>
+Acked-by: Camelia Groza <camelia.groza@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: fbec4e7fed89 ("soc: fsl: qbman: Use raw spinlock for cgr_lock")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 24ca4bedcaa6e..4d0853ead7ddf 100644
+--- a/drivers/soc/fsl/qbman/qman.c
++++ b/drivers/soc/fsl/qbman/qman.c
+@@ -2474,6 +2474,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 597783b8a3a07..b67f2e83bbef9 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
+
--- /dev/null
+From cb2aa347c344e691a57955456f3578ad6bd4736f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Sep 2022 17:57:34 -0400
+Subject: soc: fsl: qbman: Add helper for sanity checking cgr ops
+
+From: Sean Anderson <sean.anderson@seco.com>
+
+[ 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 <sean.anderson@seco.com>
+Acked-by: Camelia Groza <camelia.groza@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: fbec4e7fed89 ("soc: fsl: qbman: Use raw spinlock for cgr_lock")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 17f72d7ed3103..24ca4bedcaa6e 100644
+--- a/drivers/soc/fsl/qbman/qman.c
++++ b/drivers/soc/fsl/qbman/qman.c
+@@ -2389,13 +2389,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) {
+@@ -2403,10 +2398,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);
+@@ -2434,7 +2444,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
+
--- /dev/null
+From e9a20c13617c202253aee022c4eba6e65b9da50c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Mar 2024 12:38:29 -0400
+Subject: soc: fsl: qbman: Always disable interrupts when taking cgr_lock
+
+From: Sean Anderson <sean.anderson@linux.dev>
+
+[ 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 <sean.anderson@linux.dev>
+Reviewed-by: Camelia Groza <camelia.groza@nxp.com>
+Tested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 d7bf456fd10e4..17f72d7ed3103 100644
+--- a/drivers/soc/fsl/qbman/qman.c
++++ b/drivers/soc/fsl/qbman/qman.c
+@@ -1369,11 +1369,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;
+@@ -1389,7 +1389,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);
+ }
+
+@@ -2346,7 +2346,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;
+@@ -2383,7 +2383,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
+
--- /dev/null
+From a3c99cd0f065054849feb567330867ed84ae3021 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Mar 2024 12:38:30 -0400
+Subject: soc: fsl: qbman: Use raw spinlock for cgr_lock
+
+From: Sean Anderson <sean.anderson@linux.dev>
+
+[ 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 <vladimir.oltean@nxp.com>
+Closes: https://lore.kernel.org/all/20230323153935.nofnjucqjqnz34ej@skbuf/
+Reported-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+Closes: https://lore.kernel.org/linux-arm-kernel/87wmsyvclu.fsf@pengutronix.de/
+Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
+Reviewed-by: Camelia Groza <camelia.groza@nxp.com>
+Tested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 4d0853ead7ddf..ce08ce98142da 100644
+--- a/drivers/soc/fsl/qbman/qman.c
++++ b/drivers/soc/fsl/qbman/qman.c
+@@ -976,7 +976,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];
+@@ -1194,7 +1194,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;
+@@ -1369,11 +1369,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;
+@@ -1389,7 +1392,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);
+ }
+
+@@ -2346,7 +2349,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;
+@@ -2383,7 +2386,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;
+ }
+@@ -2418,7 +2421,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,
+@@ -2443,7 +2446,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;
+ }
+@@ -2483,9 +2486,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
+
--- /dev/null
+From b886f27b61cda081bda03280525d260e7c630402 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 10 Feb 2024 21:28:08 -0800
+Subject: sparc: vDSO: fix return value of __setup handler
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+[ 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 <rdunlap@infradead.org>
+Reported-by: Igor Zhbanov <izh1979@gmail.com>
+Link: lore.kernel.org/r/64644a2f-4a20-bab3-1e15-3b2cdd0defe3@omprussia.ru
+Cc: "David S. Miller" <davem@davemloft.net>
+Cc: sparclinux@vger.kernel.org
+Cc: Dan Carpenter <dan.carpenter@oracle.com>
+Cc: Nick Alcock <nick.alcock@oracle.com>
+Cc: Sam Ravnborg <sam@ravnborg.org>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: stable@vger.kernel.org
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Andreas Larsson <andreas@gaisler.com>
+Signed-off-by: Andreas Larsson <andreas@gaisler.com>
+Link: https://lore.kernel.org/r/20240211052808.22635-1-rdunlap@infradead.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 5eaff3c1aa0c7..1869e4b36db21 100644
+--- a/arch/sparc/vdso/vma.c
++++ b/arch/sparc/vdso/vma.c
+@@ -262,9 +262,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
+
--- /dev/null
+From 6613e411ca811ece6336f148cbf3901cabac1b5a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 10 Feb 2024 21:28:02 -0800
+Subject: sparc64: NMI watchdog: fix return value of __setup handler
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+[ 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 <rdunlap@infradead.org>
+Reported-by: Igor Zhbanov <izh1979@gmail.com>
+Link: lore.kernel.org/r/64644a2f-4a20-bab3-1e15-3b2cdd0defe3@omprussia.ru
+Cc: "David S. Miller" <davem@davemloft.net>
+Cc: sparclinux@vger.kernel.org
+Cc: Sam Ravnborg <sam@ravnborg.org>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: stable@vger.kernel.org
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Andreas Larsson <andreas@gaisler.com>
+Signed-off-by: Andreas Larsson <andreas@gaisler.com>
+Link: https://lore.kernel.org/r/20240211052802.22612-1-rdunlap@infradead.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 8babbeb30adf9..1f356928a06d5 100644
+--- a/arch/sparc/kernel/nmi.c
++++ b/arch/sparc/kernel/nmi.c
+@@ -273,7 +273,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
+
--- /dev/null
+From 845a40f8fe3a542bd9e03e0c28133f3eafef38e5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 4 Feb 2024 16:57:36 +0100
+Subject: speakup: Fix 8bit characters from direct synth
+
+From: Samuel Thibault <samuel.thibault@ens-lyon.org>
+
+[ 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 <samuel.thibault@ens-lyon.org>
+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 <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 8f8cbd582e9415845042fec6cb69b310fd4aebf8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Mar 2019 13:09:21 +0100
+Subject: timer/trace: Improve timer tracing
+
+From: Anna-Maria Gleixner <anna-maria@linutronix.de>
+
+[ Upstream commit f28d3d5346e97e60c81f933ac89ccf015430e5cf ]
+
+Timers are added to the timer wheel off by one. This is required in
+case a timer is queued directly before incrementing jiffies to prevent
+early timer expiry.
+
+When reading a timer trace and relying only on the expiry time of the timer
+in the timer_start trace point and on the now in the timer_expiry_entry
+trace point, it seems that the timer fires late. With the current
+timer_expiry_entry trace point information only now=jiffies is printed but
+not the value of base->clk. This makes it impossible to draw a conclusion
+to the index of base->clk and makes it impossible to examine timer problems
+without additional trace points.
+
+Therefore add the base->clk value to the timer_expire_entry trace
+point, to be able to calculate the index the timer base is located at
+during collecting expired timers.
+
+Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: fweisbec@gmail.com
+Cc: peterz@infradead.org
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Link: https://lkml.kernel.org/r/20190321120921.16463-5-anna-maria@linutronix.de
+Stable-dep-of: 0f7352557a35 ("wifi: brcmfmac: Fix use-after-free bug in brcmf_cfg80211_detach")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/trace/events/timer.h | 11 +++++++----
+ kernel/time/timer.c | 17 +++++++++++++----
+ 2 files changed, 20 insertions(+), 8 deletions(-)
+
+diff --git a/include/trace/events/timer.h b/include/trace/events/timer.h
+index 8f6240854e28f..295517f109d71 100644
+--- a/include/trace/events/timer.h
++++ b/include/trace/events/timer.h
+@@ -89,24 +89,27 @@ TRACE_EVENT(timer_start,
+ */
+ TRACE_EVENT(timer_expire_entry,
+
+- TP_PROTO(struct timer_list *timer),
++ TP_PROTO(struct timer_list *timer, unsigned long baseclk),
+
+- TP_ARGS(timer),
++ TP_ARGS(timer, baseclk),
+
+ TP_STRUCT__entry(
+ __field( void *, timer )
+ __field( unsigned long, now )
+ __field( void *, function)
++ __field( unsigned long, baseclk )
+ ),
+
+ TP_fast_assign(
+ __entry->timer = timer;
+ __entry->now = jiffies;
+ __entry->function = timer->function;
++ __entry->baseclk = baseclk;
+ ),
+
+- TP_printk("timer=%p function=%ps now=%lu",
+- __entry->timer, __entry->function, __entry->now)
++ TP_printk("timer=%p function=%ps now=%lu baseclk=%lu",
++ __entry->timer, __entry->function, __entry->now,
++ __entry->baseclk)
+ );
+
+ /**
+diff --git a/kernel/time/timer.c b/kernel/time/timer.c
+index a6e88d9bb931c..140662c2b41e1 100644
+--- a/kernel/time/timer.c
++++ b/kernel/time/timer.c
+@@ -1311,7 +1311,9 @@ int del_timer_sync(struct timer_list *timer)
+ EXPORT_SYMBOL(del_timer_sync);
+ #endif
+
+-static void call_timer_fn(struct timer_list *timer, void (*fn)(struct timer_list *))
++static void call_timer_fn(struct timer_list *timer,
++ void (*fn)(struct timer_list *),
++ unsigned long baseclk)
+ {
+ int count = preempt_count();
+
+@@ -1334,7 +1336,7 @@ static void call_timer_fn(struct timer_list *timer, void (*fn)(struct timer_list
+ */
+ lock_map_acquire(&lockdep_map);
+
+- trace_timer_expire_entry(timer);
++ trace_timer_expire_entry(timer, baseclk);
+ fn(timer);
+ trace_timer_expire_exit(timer);
+
+@@ -1355,6 +1357,13 @@ static void call_timer_fn(struct timer_list *timer, void (*fn)(struct timer_list
+
+ static void expire_timers(struct timer_base *base, struct hlist_head *head)
+ {
++ /*
++ * This value is required only for tracing. base->clk was
++ * incremented directly before expire_timers was called. But expiry
++ * is related to the old base->clk value.
++ */
++ unsigned long baseclk = base->clk - 1;
++
+ while (!hlist_empty(head)) {
+ struct timer_list *timer;
+ void (*fn)(struct timer_list *);
+@@ -1368,11 +1377,11 @@ static void expire_timers(struct timer_base *base, struct hlist_head *head)
+
+ if (timer->flags & TIMER_IRQSAFE) {
+ raw_spin_unlock(&base->lock);
+- call_timer_fn(timer, fn);
++ call_timer_fn(timer, fn, baseclk);
+ raw_spin_lock(&base->lock);
+ } else {
+ raw_spin_unlock_irq(&base->lock);
+- call_timer_fn(timer, fn);
++ call_timer_fn(timer, fn, baseclk);
+ raw_spin_lock_irq(&base->lock);
+ }
+ }
+--
+2.43.0
+
--- /dev/null
+From 8bb580146d09a5d90cc57d0a5a3e7e4739a93ab6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Mar 2019 13:09:20 +0100
+Subject: timer/trace: Replace deprecated vsprintf pointer extension %pf by %ps
+
+From: Anna-Maria Gleixner <anna-maria@linutronix.de>
+
+[ Upstream commit 6849cbb0f9a8dbc1ba56e9abc6955613103e01e3 ]
+
+Since commit 04b8eb7a4ccd ("symbol lookup: introduce
+dereference_symbol_descriptor()") %pf is deprecated, because %ps is smart
+enough to handle function pointer dereference on platforms where such a
+dereference is required.
+
+While at it add proper line breaks to stay in the 80 character limit.
+
+Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: fweisbec@gmail.com
+Cc: peterz@infradead.org
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Link: https://lkml.kernel.org/r/20190321120921.16463-4-anna-maria@linutronix.de
+Stable-dep-of: 0f7352557a35 ("wifi: brcmfmac: Fix use-after-free bug in brcmf_cfg80211_detach")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/trace/events/timer.h | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/include/trace/events/timer.h b/include/trace/events/timer.h
+index 350b046e7576c..8f6240854e28f 100644
+--- a/include/trace/events/timer.h
++++ b/include/trace/events/timer.h
+@@ -73,7 +73,7 @@ TRACE_EVENT(timer_start,
+ __entry->flags = flags;
+ ),
+
+- TP_printk("timer=%p function=%pf expires=%lu [timeout=%ld] cpu=%u idx=%u flags=%s",
++ TP_printk("timer=%p function=%ps expires=%lu [timeout=%ld] cpu=%u idx=%u flags=%s",
+ __entry->timer, __entry->function, __entry->expires,
+ (long)__entry->expires - __entry->now,
+ __entry->flags & TIMER_CPUMASK,
+@@ -105,7 +105,8 @@ TRACE_EVENT(timer_expire_entry,
+ __entry->function = timer->function;
+ ),
+
+- TP_printk("timer=%p function=%pf now=%lu", __entry->timer, __entry->function,__entry->now)
++ TP_printk("timer=%p function=%ps now=%lu",
++ __entry->timer, __entry->function, __entry->now)
+ );
+
+ /**
+@@ -210,7 +211,7 @@ TRACE_EVENT(hrtimer_start,
+ __entry->mode = mode;
+ ),
+
+- TP_printk("hrtimer=%p function=%pf expires=%llu softexpires=%llu "
++ TP_printk("hrtimer=%p function=%ps expires=%llu softexpires=%llu "
+ "mode=%s", __entry->hrtimer, __entry->function,
+ (unsigned long long) __entry->expires,
+ (unsigned long long) __entry->softexpires,
+@@ -243,7 +244,8 @@ TRACE_EVENT(hrtimer_expire_entry,
+ __entry->function = hrtimer->function;
+ ),
+
+- TP_printk("hrtimer=%p function=%pf now=%llu", __entry->hrtimer, __entry->function,
++ TP_printk("hrtimer=%p function=%ps now=%llu",
++ __entry->hrtimer, __entry->function,
+ (unsigned long long) __entry->now)
+ );
+
+--
+2.43.0
+
--- /dev/null
+From bdddfba9b9710fbafeec23b4aa82c368d05b2099 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jul 2019 20:31:00 +0200
+Subject: timers: Prepare support for PREEMPT_RT
+
+From: Anna-Maria Gleixner <anna-maria@linutronix.de>
+
+[ Upstream commit 030dcdd197d77374879bb5603d091eee7d8aba80 ]
+
+When PREEMPT_RT is enabled, the soft interrupt thread can be preempted. If
+the soft interrupt thread is preempted in the middle of a timer callback,
+then calling del_timer_sync() can lead to two issues:
+
+ - If the caller is on a remote CPU then it has to spin wait for the timer
+ handler to complete. This can result in unbound priority inversion.
+
+ - If the caller originates from the task which preempted the timer
+ handler on the same CPU, then spin waiting for the timer handler to
+ complete is never going to end.
+
+To avoid these issues, add a new lock to the timer base which is held
+around the execution of the timer callbacks. If del_timer_sync() detects
+that the timer callback is currently running, it blocks on the expiry
+lock. When the callback is finished, the expiry lock is dropped by the
+softirq thread which wakes up the waiter and the system makes progress.
+
+This addresses both the priority inversion and the life lock issues.
+
+This mechanism is not used for timers which are marked IRQSAFE as for those
+preemption is disabled accross the callback and therefore this situation
+cannot happen. The callbacks for such timers need to be individually
+audited for RT compliance.
+
+The same issue can happen in virtual machines when the vCPU which runs a
+timer callback is scheduled out. If a second vCPU of the same guest calls
+del_timer_sync() it will spin wait for the other vCPU to be scheduled back
+in. The expiry lock mechanism would avoid that. It'd be trivial to enable
+this when paravirt spinlocks are enabled in a guest, but it's not clear
+whether this is an actual problem in the wild, so for now it's an RT only
+mechanism.
+
+As the softirq thread can be preempted with PREEMPT_RT=y, the SMP variant
+of del_timer_sync() needs to be used on UP as well.
+
+[ tglx: Refactored it for mainline ]
+
+Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lkml.kernel.org/r/20190726185753.832418500@linutronix.de
+Stable-dep-of: 0f7352557a35 ("wifi: brcmfmac: Fix use-after-free bug in brcmf_cfg80211_detach")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/timer.h | 2 +-
+ kernel/time/timer.c | 103 ++++++++++++++++++++++++++++++++++++++----
+ 2 files changed, 96 insertions(+), 9 deletions(-)
+
+diff --git a/include/linux/timer.h b/include/linux/timer.h
+index 7b066fd38248b..8e027cb10df01 100644
+--- a/include/linux/timer.h
++++ b/include/linux/timer.h
+@@ -172,7 +172,7 @@ extern void add_timer(struct timer_list *timer);
+
+ extern int try_to_del_timer_sync(struct timer_list *timer);
+
+-#ifdef CONFIG_SMP
++#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)
+diff --git a/kernel/time/timer.c b/kernel/time/timer.c
+index 140662c2b41e1..2f5565ed27063 100644
+--- a/kernel/time/timer.c
++++ b/kernel/time/timer.c
+@@ -198,6 +198,10 @@ EXPORT_SYMBOL(jiffies_64);
+ struct timer_base {
+ raw_spinlock_t lock;
+ struct timer_list *running_timer;
++#ifdef CONFIG_PREEMPT_RT
++ spinlock_t expiry_lock;
++ atomic_t timer_waiters;
++#endif
+ unsigned long clk;
+ unsigned long next_expiry;
+ unsigned int cpu;
+@@ -1245,7 +1249,78 @@ int try_to_del_timer_sync(struct timer_list *timer)
+ }
+ EXPORT_SYMBOL(try_to_del_timer_sync);
+
+-#ifdef CONFIG_SMP
++#ifdef CONFIG_PREEMPT_RT
++static __init void timer_base_init_expiry_lock(struct timer_base *base)
++{
++ spin_lock_init(&base->expiry_lock);
++}
++
++static inline void timer_base_lock_expiry(struct timer_base *base)
++{
++ spin_lock(&base->expiry_lock);
++}
++
++static inline void timer_base_unlock_expiry(struct timer_base *base)
++{
++ spin_unlock(&base->expiry_lock);
++}
++
++/*
++ * The counterpart to del_timer_wait_running().
++ *
++ * If there is a waiter for base->expiry_lock, then it was waiting for the
++ * timer callback to finish. Drop expiry_lock and reaquire it. That allows
++ * the waiter to acquire the lock and make progress.
++ */
++static void timer_sync_wait_running(struct timer_base *base)
++{
++ if (atomic_read(&base->timer_waiters)) {
++ spin_unlock(&base->expiry_lock);
++ spin_lock(&base->expiry_lock);
++ }
++}
++
++/*
++ * This function is called on PREEMPT_RT kernels when the fast path
++ * deletion of a timer failed because the timer callback function was
++ * running.
++ *
++ * This prevents priority inversion, if the softirq thread on a remote CPU
++ * got preempted, and it prevents a life lock when the task which tries to
++ * delete a timer preempted the softirq thread running the timer callback
++ * function.
++ */
++static void del_timer_wait_running(struct timer_list *timer)
++{
++ u32 tf;
++
++ tf = READ_ONCE(timer->flags);
++ if (!(tf & TIMER_MIGRATING)) {
++ struct timer_base *base = get_timer_base(tf);
++
++ /*
++ * Mark the base as contended and grab the expiry lock,
++ * which is held by the softirq across the timer
++ * callback. Drop the lock immediately so the softirq can
++ * expire the next timer. In theory the timer could already
++ * be running again, but that's more than unlikely and just
++ * causes another wait loop.
++ */
++ atomic_inc(&base->timer_waiters);
++ spin_lock_bh(&base->expiry_lock);
++ atomic_dec(&base->timer_waiters);
++ spin_unlock_bh(&base->expiry_lock);
++ }
++}
++#else
++static inline void timer_base_init_expiry_lock(struct timer_base *base) { }
++static inline void timer_base_lock_expiry(struct timer_base *base) { }
++static inline void timer_base_unlock_expiry(struct timer_base *base) { }
++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
+@@ -1284,6 +1359,8 @@ EXPORT_SYMBOL(try_to_del_timer_sync);
+ */
+ int del_timer_sync(struct timer_list *timer)
+ {
++ int ret;
++
+ #ifdef CONFIG_LOCKDEP
+ unsigned long flags;
+
+@@ -1301,12 +1378,17 @@ int del_timer_sync(struct timer_list *timer)
+ * could lead to deadlock.
+ */
+ WARN_ON(in_irq() && !(timer->flags & TIMER_IRQSAFE));
+- for (;;) {
+- int ret = try_to_del_timer_sync(timer);
+- if (ret >= 0)
+- return ret;
+- cpu_relax();
+- }
++
++ do {
++ ret = try_to_del_timer_sync(timer);
++
++ if (unlikely(ret < 0)) {
++ del_timer_wait_running(timer);
++ cpu_relax();
++ }
++ } while (ret < 0);
++
++ return ret;
+ }
+ EXPORT_SYMBOL(del_timer_sync);
+ #endif
+@@ -1378,10 +1460,13 @@ static void expire_timers(struct timer_base *base, struct hlist_head *head)
+ if (timer->flags & TIMER_IRQSAFE) {
+ raw_spin_unlock(&base->lock);
+ call_timer_fn(timer, fn, baseclk);
++ base->running_timer = NULL;
+ raw_spin_lock(&base->lock);
+ } else {
+ raw_spin_unlock_irq(&base->lock);
+ call_timer_fn(timer, fn, baseclk);
++ base->running_timer = NULL;
++ timer_sync_wait_running(base);
+ raw_spin_lock_irq(&base->lock);
+ }
+ }
+@@ -1678,6 +1763,7 @@ static inline void __run_timers(struct timer_base *base)
+ if (!time_after_eq(jiffies, base->clk))
+ return;
+
++ timer_base_lock_expiry(base);
+ raw_spin_lock_irq(&base->lock);
+
+ /*
+@@ -1704,8 +1790,8 @@ static inline void __run_timers(struct timer_base *base)
+ while (levels--)
+ expire_timers(base, heads + levels);
+ }
+- base->running_timer = NULL;
+ raw_spin_unlock_irq(&base->lock);
++ timer_base_unlock_expiry(base);
+ }
+
+ /*
+@@ -1950,6 +2036,7 @@ static void __init init_timer_cpu(int cpu)
+ base->cpu = cpu;
+ raw_spin_lock_init(&base->lock);
+ base->clk = jiffies;
++ timer_base_init_expiry_lock(base);
+ }
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 49bede6456956e527a3245a9f3a3a32c320de5c1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Nov 2022 21:18:44 +0100
+Subject: timers: Rename del_timer_sync() to timer_delete_sync()
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ 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 <tglx@linutronix.de>
+Tested-by: Guenter Roeck <linux@roeck-us.net>
+Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Reviewed-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
+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 <sashal@kernel.org>
+---
+ 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 a9c20a7ead305..aef40cac2add8 100644
+--- a/include/linux/timer.h
++++ b/include/linux/timer.h
+@@ -171,7 +171,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 489bb01796de4..e3120af29f533 100644
+--- a/kernel/time/timer.c
++++ b/kernel/time/timer.c
+@@ -1037,7 +1037,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.
+ */
+@@ -1216,7 +1216,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.
+@@ -1350,7 +1350,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,
+@@ -1372,10 +1372,10 @@ static inline void del_timer_wait_running(struct timer_list *timer) { }
+ * spin_lock_irq(somelock);
+ * <IRQ>
+ * 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.
+ *
+@@ -1388,7 +1388,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;
+
+@@ -1421,7 +1421,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 *),
+@@ -1443,8 +1443,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
+
--- /dev/null
+From 150c0fe68b670faeaf13c632c944b265c5274d17 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Nov 2022 21:18:40 +0100
+Subject: timers: Update kernel-doc for various functions
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ 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 <tglx@linutronix.de>
+Tested-by: Guenter Roeck <linux@roeck-us.net>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Reviewed-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
+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 <sashal@kernel.org>
+---
+ 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 2f5565ed27063..f63efe259ae46 100644
+--- a/kernel/time/timer.c
++++ b/kernel/time/timer.c
+@@ -1078,14 +1078,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)
+ {
+@@ -1094,24 +1096,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)
+ {
+@@ -1122,11 +1127,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)
+ {
+@@ -1135,18 +1147,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)
+ {
+@@ -1156,11 +1171,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)
+ {
+@@ -1195,15 +1212,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)
+ {
+@@ -1225,10 +1245,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)
+ {
+@@ -1322,23 +1351,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
+ * ---- ----
+@@ -1352,10 +1377,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
+
--- /dev/null
+From c861b9222b285721ebb64c9c091cd65383823e4c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Nov 2022 21:18:42 +0100
+Subject: timers: Use del_timer_sync() even on UP
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ 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 <rostedt@goodmis.org>
+Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Tested-by: Guenter Roeck <linux@roeck-us.net>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Reviewed-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
+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 <sashal@kernel.org>
+---
+ 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 8e027cb10df01..a9c20a7ead305 100644
+--- a/include/linux/timer.h
++++ b/include/linux/timer.h
+@@ -171,12 +171,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 f63efe259ae46..489bb01796de4 100644
+--- a/kernel/time/timer.c
++++ b/kernel/time/timer.c
+@@ -1349,7 +1349,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
+@@ -1423,7 +1422,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
+
--- /dev/null
+From a1e1d5f3dd021fa82f49c9b5f6308929d60e313a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jan 2024 07:37:02 +0100
+Subject: ubi: Check for too small LEB size in VTBL code
+
+From: Richard Weinberger <richard@nod.at>
+
+[ 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 <cy54@illinois.edu>
+Cc: stable@vger.kernel.org
+Fixes: 801c135ce73d ("UBI: Unsorted Block Images")
+Reported-by: Chenyuan Yang <cy54@illinois.edu>
+Closes: https://lore.kernel.org/linux-mtd/1433EB7A-FC89-47D6-8F47-23BE41B263B3@illinois.edu/
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 1bc82154bb18f..634ec95a1e71a 100644
+--- a/drivers/mtd/ubi/vtbl.c
++++ b/drivers/mtd/ubi/vtbl.c
+@@ -804,6 +804,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
+
--- /dev/null
+From 88143158954daa536cabbc156ecd22458635903b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Feb 2024 10:49:03 +0800
+Subject: ubi: correct the calculation of fastmap size
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+[ 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 <yi.zhang@huawei.com>
+Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com>
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 d45c1d6587d18..e24fc0131d794 100644
+--- a/drivers/mtd/ubi/fastmap.c
++++ b/drivers/mtd/ubi/fastmap.c
+@@ -95,9 +95,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
+
--- /dev/null
+From 705b47602ccec54ef4283d0b596ff02d3c0f264a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jan 2024 17:52:44 +0000
+Subject: ubifs: Set page uptodate in the correct place
+
+From: Matthew Wilcox (Oracle) <willy@infradead.org>
+
+[ 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) <willy@infradead.org>
+Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com>
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 fca3b7f483c79..e373e5d057fd4 100644
+--- a/fs/ubifs/file.c
++++ b/fs/ubifs/file.c
+@@ -274,9 +274,6 @@ static int write_begin_slow(struct address_space *mapping,
+ return err;
+ }
+ }
+-
+- SetPageUptodate(page);
+- ClearPageError(page);
+ }
+
+ if (PagePrivate(page))
+@@ -475,9 +472,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);
+@@ -487,10 +481,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
+@@ -581,6 +573,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
+
--- /dev/null
+From eef55cc6d97d29cd1a98f69ee391635980209bc3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Feb 2024 21:53:29 +0000
+Subject: USB: serial: add device ID for VeriFone adapter
+
+From: Cameron Williams <cang1@live.co.uk>
+
+[ 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 <cang1@live.co.uk>
+Cc: stable@vger.kernel.org
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 b58ca66dc3aed..9901fd79b8a21 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
+
--- /dev/null
+From 8a71affce8f58ec9dfd5274749015d557bf697e0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <christian.haggstrom@orexplore.com>
+
+[ 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 <christian.haggstrom@orexplore.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 9901fd79b8a21..4bebe0f3c201a 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
+
--- /dev/null
+From bf78acd4bfed2f8390d612a0f7e7e260504a8608 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Mar 2024 08:46:14 +0900
+Subject: USB: serial: cp210x: add pid/vid for TDK NC0110013M and MM0110113M
+
+From: Toru Katagiri <Toru.Katagiri@tdk.com>
+
+[ 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 <Toru.Katagiri@tdk.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 4bebe0f3c201a..4686cf7c6b0a6 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
+
--- /dev/null
+From 8dbd79ae1abdaa2ef1a3757fc065ed3cda7631e6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <daniel@chaospixel.com>
+
+[ 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 <daniel@chaospixel.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 6d4c572807a41..755cbc9525a1b 100644
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -1045,6 +1045,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
+
--- /dev/null
+From 133b87fab349501bc1e4932160a9c23d4bcf9af2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <aurel@gnuage.org>
+
+[ 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 <aurel@gnuage.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 5014f45c7c6a0..7f4baceb540cd 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
+
--- /dev/null
+From 11a2a088bb035db043ab94456c89310282ce5fdc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Mar 2024 16:05:26 -0700
+Subject: vfio/platform: Disable virqfds on cleanup
+
+From: Alex Williamson <alex.williamson@redhat.com>
+
+[ 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 <eric.auger@redhat.com>
+Cc: <stable@vger.kernel.org>
+Fixes: a7fa7c77cf15 ("vfio/platform: implement IRQ masking/unmasking via an eventfd")
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Reviewed-by: Eric Auger <eric.auger@redhat.com>
+Link: https://lore.kernel.org/r/20240308230557.805580-6-alex.williamson@redhat.com
+Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 46d4750f43a8d..c53a9b4438733 100644
+--- a/drivers/vfio/platform/vfio_platform_irq.c
++++ b/drivers/vfio/platform/vfio_platform_irq.c
+@@ -329,8 +329,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
+
--- /dev/null
+From 8cacbaf24bcd5d4002ea2ee857ab86f37a984196 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 7 Jan 2024 08:25:04 +0100
+Subject: wifi: brcmfmac: Fix use-after-free bug in brcmf_cfg80211_detach
+
+From: Zheng Wang <zyytlz.wz@163.com>
+
+[ 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 <zyytlz.wz@163.com>
+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 <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://msgid.link/20240107072504.392713-1-arend.vanspriel@broadcom.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 1827be85f115f..fe8f1134a5f3e 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -690,8 +690,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 */
+@@ -7093,6 +7092,7 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
+ wiphy_unregister(cfg->wiphy);
+ kfree(cfg->ops);
+ wl_deinit_priv(cfg);
++ cancel_work_sync(&cfg->escan_timeout_work);
+ brcmf_free_wiphy(cfg->wiphy);
+ kfree(cfg);
+ }
+--
+2.43.0
+
--- /dev/null
+From c4fcc0fe81415022653261226c8a2f6e3566a054 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Mar 2024 22:42:27 +0100
+Subject: x86/CPU/AMD: Update the Zenbleed microcode revisions
+
+From: Borislav Petkov (AMD) <bp@alien8.de>
+
+[ 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) <bp@alien8.de>
+Cc: <stable@kernel.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 5b75a4ff6802c..3f6188477e014 100644
+--- a/arch/x86/kernel/cpu/amd.c
++++ b/arch/x86/kernel/cpu/amd.c
+@@ -988,11 +988,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
+