--- /dev/null
+From 6f349e33ce2921776a4a4305397d74ab05a2bfcb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jan 2022 20:11:38 +0100
+Subject: ARM: dts: switch timer config to common devkit8000 devicetree
+
+From: Anthoine Bourgeois <anthoine.bourgeois@gmail.com>
+
+[ Upstream commit 64324ef337d0caa5798fa8fa3f6bbfbd3245868a ]
+
+This patch allow lcd43 and lcd70 flavors to benefit from timer
+evolution.
+
+Fixes: e428e250fde6 ("ARM: dts: Configure system timers for omap3")
+Signed-off-by: Anthoine Bourgeois <anthoine.bourgeois@gmail.com>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../arm/boot/dts/omap3-devkit8000-common.dtsi | 33 +++++++++++++++++++
+ arch/arm/boot/dts/omap3-devkit8000.dts | 33 -------------------
+ 2 files changed, 33 insertions(+), 33 deletions(-)
+
+diff --git a/arch/arm/boot/dts/omap3-devkit8000-common.dtsi b/arch/arm/boot/dts/omap3-devkit8000-common.dtsi
+index 5e55198e4576..f5197bb31ed8 100644
+--- a/arch/arm/boot/dts/omap3-devkit8000-common.dtsi
++++ b/arch/arm/boot/dts/omap3-devkit8000-common.dtsi
+@@ -158,6 +158,39 @@
+ status = "disabled";
+ };
+
++/* Unusable as clocksource because of unreliable oscillator */
++&counter32k {
++ status = "disabled";
++};
++
++/* Unusable as clockevent because if unreliable oscillator, allow to idle */
++&timer1_target {
++ /delete-property/ti,no-reset-on-init;
++ /delete-property/ti,no-idle;
++ timer@0 {
++ /delete-property/ti,timer-alwon;
++ };
++};
++
++/* Preferred always-on timer for clocksource */
++&timer12_target {
++ ti,no-reset-on-init;
++ ti,no-idle;
++ timer@0 {
++ /* Always clocked by secure_32k_fck */
++ };
++};
++
++/* Preferred timer for clockevent */
++&timer2_target {
++ ti,no-reset-on-init;
++ ti,no-idle;
++ timer@0 {
++ assigned-clocks = <&gpt2_fck>;
++ assigned-clock-parents = <&sys_ck>;
++ };
++};
++
+ &twl_gpio {
+ ti,use-leds;
+ /*
+diff --git a/arch/arm/boot/dts/omap3-devkit8000.dts b/arch/arm/boot/dts/omap3-devkit8000.dts
+index c2995a280729..162d0726b008 100644
+--- a/arch/arm/boot/dts/omap3-devkit8000.dts
++++ b/arch/arm/boot/dts/omap3-devkit8000.dts
+@@ -14,36 +14,3 @@
+ display2 = &tv0;
+ };
+ };
+-
+-/* Unusable as clocksource because of unreliable oscillator */
+-&counter32k {
+- status = "disabled";
+-};
+-
+-/* Unusable as clockevent because if unreliable oscillator, allow to idle */
+-&timer1_target {
+- /delete-property/ti,no-reset-on-init;
+- /delete-property/ti,no-idle;
+- timer@0 {
+- /delete-property/ti,timer-alwon;
+- };
+-};
+-
+-/* Preferred always-on timer for clocksource */
+-&timer12_target {
+- ti,no-reset-on-init;
+- ti,no-idle;
+- timer@0 {
+- /* Always clocked by secure_32k_fck */
+- };
+-};
+-
+-/* Preferred timer for clockevent */
+-&timer2_target {
+- ti,no-reset-on-init;
+- ti,no-idle;
+- timer@0 {
+- assigned-clocks = <&gpt2_fck>;
+- assigned-clock-parents = <&sys_ck>;
+- };
+-};
+--
+2.34.1
+
--- /dev/null
+From 61077c5b779d97f87bb7479bfb12974d305e8bc9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jan 2022 20:11:39 +0100
+Subject: ARM: dts: Use 32KiHz oscillator on devkit8000
+
+From: Anthoine Bourgeois <anthoine.bourgeois@gmail.com>
+
+[ Upstream commit 8840f5460a23759403f1f2860429dcbcc2f04a65 ]
+
+Devkit8000 board seems to always used 32k_counter as clocksource.
+Restore this behavior.
+
+If clocksource is back to 32k_counter, timer12 is now the clockevent
+source (as before) and timer2 is not longer needed here.
+
+This commit fixes the same issue observed with commit 23885389dbbb
+("ARM: dts: Fix timer regression for beagleboard revision c") when sleep
+is blocked until hitting keys over serial console.
+
+Fixes: aba1ad05da08 ("clocksource/drivers/timer-ti-dm: Add clockevent and clocksource support")
+Fixes: e428e250fde6 ("ARM: dts: Configure system timers for omap3")
+Signed-off-by: Anthoine Bourgeois <anthoine.bourgeois@gmail.com>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/omap3-devkit8000-common.dtsi | 17 +----------------
+ drivers/clocksource/timer-ti-dm-systimer.c | 3 +--
+ 2 files changed, 2 insertions(+), 18 deletions(-)
+
+diff --git a/arch/arm/boot/dts/omap3-devkit8000-common.dtsi b/arch/arm/boot/dts/omap3-devkit8000-common.dtsi
+index f5197bb31ed8..54cd37336be7 100644
+--- a/arch/arm/boot/dts/omap3-devkit8000-common.dtsi
++++ b/arch/arm/boot/dts/omap3-devkit8000-common.dtsi
+@@ -158,11 +158,6 @@
+ status = "disabled";
+ };
+
+-/* Unusable as clocksource because of unreliable oscillator */
+-&counter32k {
+- status = "disabled";
+-};
+-
+ /* Unusable as clockevent because if unreliable oscillator, allow to idle */
+ &timer1_target {
+ /delete-property/ti,no-reset-on-init;
+@@ -172,7 +167,7 @@
+ };
+ };
+
+-/* Preferred always-on timer for clocksource */
++/* Preferred timer for clockevent */
+ &timer12_target {
+ ti,no-reset-on-init;
+ ti,no-idle;
+@@ -181,16 +176,6 @@
+ };
+ };
+
+-/* Preferred timer for clockevent */
+-&timer2_target {
+- ti,no-reset-on-init;
+- ti,no-idle;
+- timer@0 {
+- assigned-clocks = <&gpt2_fck>;
+- assigned-clock-parents = <&sys_ck>;
+- };
+-};
+-
+ &twl_gpio {
+ ti,use-leds;
+ /*
+diff --git a/drivers/clocksource/timer-ti-dm-systimer.c b/drivers/clocksource/timer-ti-dm-systimer.c
+index 5c40ca1d4740..1fccb457fcc5 100644
+--- a/drivers/clocksource/timer-ti-dm-systimer.c
++++ b/drivers/clocksource/timer-ti-dm-systimer.c
+@@ -241,8 +241,7 @@ static void __init dmtimer_systimer_assign_alwon(void)
+ bool quirk_unreliable_oscillator = false;
+
+ /* Quirk unreliable 32 KiHz oscillator with incomplete dts */
+- if (of_machine_is_compatible("ti,omap3-beagle-ab4") ||
+- of_machine_is_compatible("timll,omap3-devkit8000")) {
++ if (of_machine_is_compatible("ti,omap3-beagle-ab4")) {
+ quirk_unreliable_oscillator = true;
+ counter_32k = -ENODEV;
+ }
+--
+2.34.1
+
--- /dev/null
+From 2fb2e0a2be5a86af006852750ecfdcb65cac5cb0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Dec 2021 11:32:39 +0100
+Subject: ARM: tegra: Move panels to AUX bus
+
+From: Thierry Reding <treding@nvidia.com>
+
+[ Upstream commit 8d3b01e0d4bb54368d73d0984466d72c2eeeac74 ]
+
+Move the eDP panel on Venice 2 and Nyan boards into the corresponding
+AUX bus device tree node. This allows us to avoid a nasty circular
+dependency that would otherwise be created between the DPAUX and panel
+nodes via the DDC/I2C phandle.
+
+Fixes: eb481f9ac95c ("ARM: tegra: add Acer Chromebook 13 device tree")
+Fixes: 59fe02cb079f ("ARM: tegra: Add DTS for the nyan-blaze board")
+Fixes: 40e231c770a4 ("ARM: tegra: Enable eDP for Venice2")
+Signed-off-by: Thierry Reding <treding@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/tegra124-nyan-big.dts | 15 +++++++++------
+ arch/arm/boot/dts/tegra124-nyan-blaze.dts | 15 +++++++++------
+ arch/arm/boot/dts/tegra124-venice2.dts | 14 +++++++-------
+ 3 files changed, 25 insertions(+), 19 deletions(-)
+
+diff --git a/arch/arm/boot/dts/tegra124-nyan-big.dts b/arch/arm/boot/dts/tegra124-nyan-big.dts
+index 1d2aac2cb6d0..fdc1d64dfff9 100644
+--- a/arch/arm/boot/dts/tegra124-nyan-big.dts
++++ b/arch/arm/boot/dts/tegra124-nyan-big.dts
+@@ -13,12 +13,15 @@
+ "google,nyan-big-rev1", "google,nyan-big-rev0",
+ "google,nyan-big", "google,nyan", "nvidia,tegra124";
+
+- panel: panel {
+- compatible = "auo,b133xtn01";
+-
+- power-supply = <&vdd_3v3_panel>;
+- backlight = <&backlight>;
+- ddc-i2c-bus = <&dpaux>;
++ host1x@50000000 {
++ dpaux@545c0000 {
++ aux-bus {
++ panel: panel {
++ compatible = "auo,b133xtn01";
++ backlight = <&backlight>;
++ };
++ };
++ };
+ };
+
+ mmc@700b0400 { /* SD Card on this bus */
+diff --git a/arch/arm/boot/dts/tegra124-nyan-blaze.dts b/arch/arm/boot/dts/tegra124-nyan-blaze.dts
+index 677babde6460..abdf4456826f 100644
+--- a/arch/arm/boot/dts/tegra124-nyan-blaze.dts
++++ b/arch/arm/boot/dts/tegra124-nyan-blaze.dts
+@@ -15,12 +15,15 @@
+ "google,nyan-blaze-rev0", "google,nyan-blaze",
+ "google,nyan", "nvidia,tegra124";
+
+- panel: panel {
+- compatible = "samsung,ltn140at29-301";
+-
+- power-supply = <&vdd_3v3_panel>;
+- backlight = <&backlight>;
+- ddc-i2c-bus = <&dpaux>;
++ host1x@50000000 {
++ dpaux@545c0000 {
++ aux-bus {
++ panel: panel {
++ compatible = "samsung,ltn140at29-301";
++ backlight = <&backlight>;
++ };
++ };
++ };
+ };
+
+ sound {
+diff --git a/arch/arm/boot/dts/tegra124-venice2.dts b/arch/arm/boot/dts/tegra124-venice2.dts
+index e6b54ac1ebd1..84e2d24065e9 100644
+--- a/arch/arm/boot/dts/tegra124-venice2.dts
++++ b/arch/arm/boot/dts/tegra124-venice2.dts
+@@ -48,6 +48,13 @@
+ dpaux@545c0000 {
+ vdd-supply = <&vdd_3v3_panel>;
+ status = "okay";
++
++ aux-bus {
++ panel: panel {
++ compatible = "lg,lp129qe";
++ backlight = <&backlight>;
++ };
++ };
+ };
+ };
+
+@@ -1079,13 +1086,6 @@
+ };
+ };
+
+- panel: panel {
+- compatible = "lg,lp129qe";
+- power-supply = <&vdd_3v3_panel>;
+- backlight = <&backlight>;
+- ddc-i2c-bus = <&dpaux>;
+- };
+-
+ vdd_mux: regulator@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "+VDD_MUX";
+--
+2.34.1
+
--- /dev/null
+From f234fb54ef2de87445571761d231af85c6c06807 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jan 2022 11:11:25 -0600
+Subject: arm64: dts: imx8mm: Fix VPU Hanging
+
+From: Adam Ford <aford173@gmail.com>
+
+[ Upstream commit ef3075d6638d3d5353a97fcc7bb0338fc85675f5 ]
+
+The vpumix power domain has a reset assigned to it, however
+when used, it causes a system hang. Testing has shown that
+it does not appear to be needed anywhere.
+
+Fixes: d39d4bb15310 ("arm64: dts: imx8mm: add GPC node")
+Signed-off-by: Adam Ford <aford173@gmail.com>
+Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
+Signed-off-by: Shawn Guo <shawnguo@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/freescale/imx8mm.dtsi | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+index c2f3f118f82e..f13d31ebfcbd 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+@@ -681,7 +681,6 @@
+ clocks = <&clk IMX8MM_CLK_VPU_DEC_ROOT>;
+ assigned-clocks = <&clk IMX8MM_CLK_VPU_BUS>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_800M>;
+- resets = <&src IMX8MQ_RESET_VPU_RESET>;
+ };
+
+ pgc_vpu_g1: power-domain@7 {
+--
+2.34.1
+
--- /dev/null
+From 06e1c23b052f352842554a016c55db9a1737bbe8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Jan 2022 17:57:01 +0000
+Subject: arm64: dts: juno: Remove GICv2m dma-range
+
+From: Robin Murphy <robin.murphy@arm.com>
+
+[ Upstream commit 31eeb6b09f4053f32a30ce9fbcdfca31f713028d ]
+
+Although it is painstakingly honest to describe all 3 PCI windows in
+"dma-ranges", it misses the the subtle distinction that the window for
+the GICv2m range is normally programmed for Device memory attributes
+rather than Normal Cacheable like the DRAM windows. Since MMU-401 only
+offers stage 2 translation, this means that when the PCI SMMU is
+enabled, accesses through that IPA range unexpectedly lose coherency if
+mapped as cacheable at the SMMU, due to the attribute combining rules.
+Since an extra 256KB is neither here nor there when we still have 10GB
+worth of usable address space, rather than attempting to describe and
+cope with this detail let's just remove the offending range. If the SMMU
+is not used then it makes no difference anyway.
+
+Link: https://lore.kernel.org/r/856c3f7192c6c3ce545ba67462f2ce9c86ed6b0c.1643046936.git.robin.murphy@arm.com
+Fixes: 4ac4d146cb63 ("arm64: dts: juno: Describe PCI dma-ranges")
+Reported-by: Anders Roxell <anders.roxell@linaro.org>
+Acked-by: Liviu Dudau <liviu.dudau@arm.com>
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/arm/juno-base.dtsi | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi
+index 6288e104a089..a2635b14da30 100644
+--- a/arch/arm64/boot/dts/arm/juno-base.dtsi
++++ b/arch/arm64/boot/dts/arm/juno-base.dtsi
+@@ -543,8 +543,7 @@
+ <0x02000000 0x00 0x50000000 0x00 0x50000000 0x0 0x08000000>,
+ <0x42000000 0x40 0x00000000 0x40 0x00000000 0x1 0x00000000>;
+ /* Standard AXI Translation entries as programmed by EDK2 */
+- dma-ranges = <0x02000000 0x0 0x2c1c0000 0x0 0x2c1c0000 0x0 0x00040000>,
+- <0x02000000 0x0 0x80000000 0x0 0x80000000 0x0 0x80000000>,
++ dma-ranges = <0x02000000 0x0 0x80000000 0x0 0x80000000 0x0 0x80000000>,
+ <0x43000000 0x8 0x00000000 0x8 0x00000000 0x2 0x00000000>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+--
+2.34.1
+
--- /dev/null
+From 4458a534ef37cb25041df6bdd34201e39e8b678f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 23 Jan 2022 14:35:10 +0100
+Subject: arm64: dts: rockchip: drop pclk_xpcs from gmac0 on rk3568
+
+From: Frank Wunderlich <frank-w@public-files.de>
+
+[ Upstream commit 85a8bccfa945680dc561f06b65ea01341d2033fc ]
+
+pclk_xpcs is not supported by mainline driver and breaks dtbs_check
+
+following warnings occour, and many more
+
+rk3568-evb1-v10.dt.yaml: ethernet@fe2a0000: clocks:
+ [[15, 386], [15, 389], [15, 389], [15, 184], [15, 180], [15, 181],
+ [15, 389], [15, 185], [15, 172]] is too long
+ From schema: Documentation/devicetree/bindings/net/snps,dwmac.yaml
+rk3568-evb1-v10.dt.yaml: ethernet@fe2a0000: clock-names:
+ ['stmmaceth', 'mac_clk_rx', 'mac_clk_tx', 'clk_mac_refout', 'aclk_mac',
+ 'pclk_mac', 'clk_mac_speed', 'ptp_ref', 'pclk_xpcs'] is too long
+ From schema: Documentation/devicetree/bindings/net/snps,dwmac.yaml
+
+after removing it, the clock and other warnings are gone.
+
+pclk_xpcs on gmac is used to support QSGMII, but this requires a driver
+supporting it.
+Once xpcs support is introduced, the clock can be added to the
+documentation and both controllers.
+
+Fixes: b8d41e5053cd ("arm64: dts: rockchip: add gmac0 node to rk3568")
+Co-developed-by: Peter Geis <pgwipeout@gmail.com>
+Signed-off-by: Peter Geis <pgwipeout@gmail.com>
+Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
+Acked-by: Michael Riesch <michael.riesch@wolfvision.net>
+Link: https://lore.kernel.org/r/20220123133510.135651-1-linux@fw-web.de
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/rockchip/rk3568.dtsi | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3568.dtsi b/arch/arm64/boot/dts/rockchip/rk3568.dtsi
+index 2fd313a295f8..d91df1cde736 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi
++++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi
+@@ -32,13 +32,11 @@
+ clocks = <&cru SCLK_GMAC0>, <&cru SCLK_GMAC0_RX_TX>,
+ <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_MAC0_REFOUT>,
+ <&cru ACLK_GMAC0>, <&cru PCLK_GMAC0>,
+- <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_GMAC0_PTP_REF>,
+- <&cru PCLK_XPCS>;
++ <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_GMAC0_PTP_REF>;
+ clock-names = "stmmaceth", "mac_clk_rx",
+ "mac_clk_tx", "clk_mac_refout",
+ "aclk_mac", "pclk_mac",
+- "clk_mac_speed", "ptp_ref",
+- "pclk_xpcs";
++ "clk_mac_speed", "ptp_ref";
+ resets = <&cru SRST_A_GMAC0>;
+ reset-names = "stmmaceth";
+ rockchip,grf = <&grf>;
+--
+2.34.1
+
--- /dev/null
+From 79a124d5500cb9b3a89c99b7d5794e140a68ac70 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Jan 2022 19:38:05 -0500
+Subject: arm64: dts: rockchip: fix Quartz64-A ddr regulator voltage
+
+From: Peter Geis <pgwipeout@gmail.com>
+
+[ Upstream commit ad02776cf8d083e28b1ca4d93d8b1949668c27cc ]
+
+The Quartz64 Model A uses a voltage divider to ensure ddr voltage is
+within specification from the default regulator configuration.
+Adjusting this voltage is detrimental, and currently causes the ddr
+voltage to be about 0.8v.
+
+Remove the min and max voltage setpoints for the ddr regulator.
+
+Fixes: b33a22a1e7c4 ("arm64: dts: rockchip: add basic dts for Pine64 Quartz64-A")
+Signed-off-by: Peter Geis <pgwipeout@gmail.com>
+Link: https://lore.kernel.org/r/20220128003809.3291407-2-pgwipeout@gmail.com
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
+index 4d4b2a301b1a..f6290538c8a4 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
+@@ -285,8 +285,6 @@
+ vcc_ddr: DCDC_REG3 {
+ regulator-always-on;
+ regulator-boot-on;
+- regulator-min-microvolt = <1100000>;
+- regulator-max-microvolt = <1100000>;
+ regulator-initial-mode = <0x2>;
+ regulator-name = "vcc_ddr";
+ regulator-state-mem {
+--
+2.34.1
+
--- /dev/null
+From 976b37e2a5885863e25eb71ebf8f67bf272a3b0f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Feb 2022 17:59:38 -0800
+Subject: Bluetooth: Fix bt_skb_sendmmsg not allocating partial chunks
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 29fb608396d6a62c1b85acc421ad7a4399085b9f ]
+
+Since bt_skb_sendmmsg can be used with the likes of SOCK_STREAM it
+shall return the partial chunks it could allocate instead of freeing
+everything as otherwise it can cause problems like bellow.
+
+Fixes: 81be03e026dc ("Bluetooth: RFCOMM: Replace use of memcpy_from_msg with bt_skb_sendmmsg")
+Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
+Link: https://lore.kernel.org/r/d7206e12-1b99-c3be-84f4-df22af427ef5@molgen.mpg.de
+BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=215594
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Tested-by: Paul Menzel <pmenzel@molgen.mpg.de> (Nokia N9 (MeeGo/Harmattan)
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/bluetooth/bluetooth.h | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
+index 3271870fd85e..a1093994e5e4 100644
+--- a/include/net/bluetooth/bluetooth.h
++++ b/include/net/bluetooth/bluetooth.h
+@@ -497,8 +497,7 @@ static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk,
+
+ tmp = bt_skb_sendmsg(sk, msg, len, mtu, headroom, tailroom);
+ if (IS_ERR(tmp)) {
+- kfree_skb(skb);
+- return tmp;
++ return skb;
+ }
+
+ len -= tmp->len;
+--
+2.34.1
+
--- /dev/null
+From 1885746ec2ea63d5ee6970657c878610417c8531 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 12 Feb 2022 20:27:13 +0900
+Subject: can: etas_es58x: change opened_channel_cnt's type from atomic_t to u8
+
+From: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
+
+[ Upstream commit f4896248e9025ff744b4147e6758274a1cb8cbae ]
+
+The driver uses an atomic_t variable: struct
+es58x_device::opened_channel_cnt to keep track of the number of opened
+channels in order to only allocate memory for the URBs when this count
+changes from zero to one.
+
+While the intent was to prevent race conditions, the choice of an
+atomic_t turns out to be a bad idea for several reasons:
+
+- implementation is incorrect and fails to decrement
+ opened_channel_cnt when the URB allocation fails as reported in
+ [1].
+
+- even if opened_channel_cnt were to be correctly decremented,
+ atomic_t is insufficient to cover edge cases: there can be a race
+ condition in which 1/ a first process fails to allocate URBs
+ memory 2/ a second process enters es58x_open() before the first
+ process does its cleanup and decrements opened_channed_cnt. In
+ which case, the second process would successfully return despite
+ the URBs memory not being allocated.
+
+- actually, any kind of locking mechanism was useless here because
+ it is redundant with the network stack big kernel lock
+ (a.k.a. rtnl_lock) which is being hold by all the callers of
+ net_device_ops:ndo_open() and net_device_ops:ndo_close(). c.f. the
+ ASSERST_RTNL() calls in __dev_open() [2] and __dev_close_many()
+ [3].
+
+The atmomic_t is thus replaced by a simple u8 type and the logic to
+increment and decrement es58x_device:opened_channel_cnt is simplified
+accordingly fixing the bug reported in [1]. We do not check again for
+ASSERST_RTNL() as this is already done by the callers.
+
+[1] https://lore.kernel.org/linux-can/20220201140351.GA2548@kili/T/#u
+[2] https://elixir.bootlin.com/linux/v5.16/source/net/core/dev.c#L1463
+[3] https://elixir.bootlin.com/linux/v5.16/source/net/core/dev.c#L1541
+
+Fixes: 8537257874e9 ("can: etas_es58x: add core support for ETAS ES58X CAN USB interfaces")
+Link: https://lore.kernel.org/all/20220212112713.577957-1-mailhol.vincent@wanadoo.fr
+Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/usb/etas_es58x/es58x_core.c | 9 +++++----
+ drivers/net/can/usb/etas_es58x/es58x_core.h | 8 +++++---
+ 2 files changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.c b/drivers/net/can/usb/etas_es58x/es58x_core.c
+index fb07c33ba0c3..78d0a5947ba1 100644
+--- a/drivers/net/can/usb/etas_es58x/es58x_core.c
++++ b/drivers/net/can/usb/etas_es58x/es58x_core.c
+@@ -1787,7 +1787,7 @@ static int es58x_open(struct net_device *netdev)
+ struct es58x_device *es58x_dev = es58x_priv(netdev)->es58x_dev;
+ int ret;
+
+- if (atomic_inc_return(&es58x_dev->opened_channel_cnt) == 1) {
++ if (!es58x_dev->opened_channel_cnt) {
+ ret = es58x_alloc_rx_urbs(es58x_dev);
+ if (ret)
+ return ret;
+@@ -1805,12 +1805,13 @@ static int es58x_open(struct net_device *netdev)
+ if (ret)
+ goto free_urbs;
+
++ es58x_dev->opened_channel_cnt++;
+ netif_start_queue(netdev);
+
+ return ret;
+
+ free_urbs:
+- if (atomic_dec_and_test(&es58x_dev->opened_channel_cnt))
++ if (!es58x_dev->opened_channel_cnt)
+ es58x_free_urbs(es58x_dev);
+ netdev_err(netdev, "%s: Could not open the network device: %pe\n",
+ __func__, ERR_PTR(ret));
+@@ -1845,7 +1846,8 @@ static int es58x_stop(struct net_device *netdev)
+
+ es58x_flush_pending_tx_msg(netdev);
+
+- if (atomic_dec_and_test(&es58x_dev->opened_channel_cnt))
++ es58x_dev->opened_channel_cnt--;
++ if (!es58x_dev->opened_channel_cnt)
+ es58x_free_urbs(es58x_dev);
+
+ return 0;
+@@ -2214,7 +2216,6 @@ static struct es58x_device *es58x_init_es58x_dev(struct usb_interface *intf,
+ init_usb_anchor(&es58x_dev->tx_urbs_idle);
+ init_usb_anchor(&es58x_dev->tx_urbs_busy);
+ atomic_set(&es58x_dev->tx_urbs_idle_cnt, 0);
+- atomic_set(&es58x_dev->opened_channel_cnt, 0);
+ usb_set_intfdata(intf, es58x_dev);
+
+ es58x_dev->rx_pipe = usb_rcvbulkpipe(es58x_dev->udev,
+diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.h b/drivers/net/can/usb/etas_es58x/es58x_core.h
+index 826a15871573..e5033cb5e695 100644
+--- a/drivers/net/can/usb/etas_es58x/es58x_core.h
++++ b/drivers/net/can/usb/etas_es58x/es58x_core.h
+@@ -373,8 +373,6 @@ struct es58x_operators {
+ * queue wake/stop logic should prevent this URB from getting
+ * empty. Please refer to es58x_get_tx_urb() for more details.
+ * @tx_urbs_idle_cnt: number of urbs in @tx_urbs_idle.
+- * @opened_channel_cnt: number of channels opened (c.f. es58x_open()
+- * and es58x_stop()).
+ * @ktime_req_ns: kernel timestamp when es58x_set_realtime_diff_ns()
+ * was called.
+ * @realtime_diff_ns: difference in nanoseconds between the clocks of
+@@ -384,6 +382,10 @@ struct es58x_operators {
+ * in RX branches.
+ * @rx_max_packet_size: Maximum length of bulk-in URB.
+ * @num_can_ch: Number of CAN channel (i.e. number of elements of @netdev).
++ * @opened_channel_cnt: number of channels opened. Free of race
++ * conditions because its two users (net_device_ops:ndo_open()
++ * and net_device_ops:ndo_close()) guarantee that the network
++ * stack big kernel lock (a.k.a. rtnl_mutex) is being hold.
+ * @rx_cmd_buf_len: Length of @rx_cmd_buf.
+ * @rx_cmd_buf: The device might split the URB commands in an
+ * arbitrary amount of pieces. This buffer is used to concatenate
+@@ -406,7 +408,6 @@ struct es58x_device {
+ struct usb_anchor tx_urbs_busy;
+ struct usb_anchor tx_urbs_idle;
+ atomic_t tx_urbs_idle_cnt;
+- atomic_t opened_channel_cnt;
+
+ u64 ktime_req_ns;
+ s64 realtime_diff_ns;
+@@ -415,6 +416,7 @@ struct es58x_device {
+
+ u16 rx_max_packet_size;
+ u8 num_can_ch;
++ u8 opened_channel_cnt;
+
+ u16 rx_cmd_buf_len;
+ union es58x_urb_cmd rx_cmd_buf;
+--
+2.34.1
+
--- /dev/null
+From 5bb330da4ac107341315142178a975fc3953f3ca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Mar 2022 14:11:59 +0800
+Subject: drm/amdgpu: fix suspend/resume hang regression
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Qiang Yu <qiang.yu@amd.com>
+
+[ Upstream commit f1ef17011c765495c876fa75435e59eecfdc1ee4 ]
+
+Regression has been reported that suspend/resume may hang with
+the previous vm ready check commit.
+
+So bring back the evicted list check as a temp fix.
+
+Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1922
+Fixes: c1a66c3bc425 ("drm/amdgpu: check vm ready by amdgpu_vm->evicting flag")
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Qiang Yu <qiang.yu@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+index bc8d83698880..e73c09d05b6e 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+@@ -777,7 +777,8 @@ bool amdgpu_vm_ready(struct amdgpu_vm *vm)
+ amdgpu_vm_eviction_lock(vm);
+ ret = !vm->evicting;
+ amdgpu_vm_eviction_unlock(vm);
+- return ret;
++
++ return ret && list_empty(&vm->evicted);
+ }
+
+ /**
+--
+2.34.1
+
--- /dev/null
+From 7b75869723751933faead20e628c433346bcef41 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Feb 2022 14:18:43 -0800
+Subject: drm/bridge: ti-sn65dsi86: Properly undo autosuspend
+
+From: Douglas Anderson <dianders@chromium.org>
+
+[ Upstream commit 26d3474348293dc752c55fe6d41282199f73714c ]
+
+The PM Runtime docs say:
+ Drivers in ->remove() callback should undo the runtime PM changes done
+ in ->probe(). Usually this means calling pm_runtime_disable(),
+ pm_runtime_dont_use_autosuspend() etc.
+
+We weren't doing that for autosuspend. Let's do it.
+
+Fixes: 9bede63127c6 ("drm/bridge: ti-sn65dsi86: Use pm_runtime autosuspend")
+Signed-off-by: Douglas Anderson <dianders@chromium.org>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220222141838.1.If784ba19e875e8ded4ec4931601ce6d255845245@changeid
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/ti-sn65dsi86.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+index 83d06c16d4d7..b7f74c146dee 100644
+--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
++++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+@@ -1474,6 +1474,7 @@ static inline void ti_sn_gpio_unregister(void) {}
+
+ static void ti_sn65dsi86_runtime_disable(void *data)
+ {
++ pm_runtime_dont_use_autosuspend(data);
+ pm_runtime_disable(data);
+ }
+
+@@ -1533,11 +1534,11 @@ static int ti_sn65dsi86_probe(struct i2c_client *client,
+ "failed to get reference clock\n");
+
+ pm_runtime_enable(dev);
++ pm_runtime_set_autosuspend_delay(pdata->dev, 500);
++ pm_runtime_use_autosuspend(pdata->dev);
+ ret = devm_add_action_or_reset(dev, ti_sn65dsi86_runtime_disable, dev);
+ if (ret)
+ return ret;
+- pm_runtime_set_autosuspend_delay(pdata->dev, 500);
+- pm_runtime_use_autosuspend(pdata->dev);
+
+ ti_sn65dsi86_debugfs_init(pdata);
+
+--
+2.34.1
+
--- /dev/null
+From e7c44e365b06eb6dc329bc235a5c92f729d284d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Feb 2022 10:15:04 -0800
+Subject: drm/i915/guc/slpc: Correct the param count for unset param
+
+From: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
+
+[ Upstream commit 1b279f6ad467535c3b8a66b4edefaca2cdd5bdc3 ]
+
+SLPC unset param H2G only needs one parameter - the id of the
+param.
+
+Fixes: 025cb07bebfa ("drm/i915/guc/slpc: Cache platform frequency limits")
+
+Suggested-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
+Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
+Reviewed-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
+Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220216181504.7155-1-vinay.belgaumkar@intel.com
+(cherry picked from commit 9648f1c3739505557d94ff749a4f32192ea81fe3)
+Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+index 65a3e7fdb2b2..95ff630157b9 100644
+--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
++++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+@@ -133,7 +133,7 @@ static int guc_action_slpc_unset_param(struct intel_guc *guc, u8 id)
+ {
+ u32 request[] = {
+ GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST,
+- SLPC_EVENT(SLPC_EVENT_PARAMETER_UNSET, 2),
++ SLPC_EVENT(SLPC_EVENT_PARAMETER_UNSET, 1),
+ id,
+ };
+
+--
+2.34.1
+
--- /dev/null
+From 4c3a8889de12355d19058fc38b0067b81f1bdee3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jan 2022 19:31:23 +0200
+Subject: e1000e: Fix possible HW unit hang after an s0ix exit
+
+From: Sasha Neftin <sasha.neftin@intel.com>
+
+[ Upstream commit 1866aa0d0d6492bc2f8d22d0df49abaccf50cddd ]
+
+Disable the OEM bit/Gig Disable/restart AN impact and disable the PHY
+LAN connected device (LCD) reset during power management flows. This
+fixes possible HW unit hangs on the s0ix exit on some corporate ADL
+platforms.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=214821
+Fixes: 3e55d231716e ("e1000e: Add handshake with the CSME to support S0ix")
+Suggested-by: Dima Ruinskiy <dima.ruinskiy@intel.com>
+Suggested-by: Nir Efrati <nir.efrati@intel.com>
+Signed-off-by: Sasha Neftin <sasha.neftin@intel.com>
+Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/e1000e/hw.h | 1 +
+ drivers/net/ethernet/intel/e1000e/ich8lan.c | 4 ++++
+ drivers/net/ethernet/intel/e1000e/ich8lan.h | 1 +
+ drivers/net/ethernet/intel/e1000e/netdev.c | 26 +++++++++++++++++++++
+ 4 files changed, 32 insertions(+)
+
+diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h
+index bcf680e83811..13382df2f2ef 100644
+--- a/drivers/net/ethernet/intel/e1000e/hw.h
++++ b/drivers/net/ethernet/intel/e1000e/hw.h
+@@ -630,6 +630,7 @@ struct e1000_phy_info {
+ bool disable_polarity_correction;
+ bool is_mdix;
+ bool polarity_correction;
++ bool reset_disable;
+ bool speed_downgraded;
+ bool autoneg_wait_to_complete;
+ };
+diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
+index a3e42d06c63e..d60e2016d03c 100644
+--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
++++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
+@@ -2050,6 +2050,10 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw)
+ bool blocked = false;
+ int i = 0;
+
++ /* Check the PHY (LCD) reset flag */
++ if (hw->phy.reset_disable)
++ return true;
++
+ while ((blocked = !(er32(FWSM) & E1000_ICH_FWSM_RSPCIPHY)) &&
+ (i++ < 30))
+ usleep_range(10000, 11000);
+diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.h b/drivers/net/ethernet/intel/e1000e/ich8lan.h
+index 2504b11c3169..638a3ddd7ada 100644
+--- a/drivers/net/ethernet/intel/e1000e/ich8lan.h
++++ b/drivers/net/ethernet/intel/e1000e/ich8lan.h
+@@ -271,6 +271,7 @@
+ #define I217_CGFREG_ENABLE_MTA_RESET 0x0002
+ #define I217_MEMPWR PHY_REG(772, 26)
+ #define I217_MEMPWR_DISABLE_SMB_RELEASE 0x0010
++#define I217_MEMPWR_MOEM 0x1000
+
+ /* Receive Address Initial CRC Calculation */
+ #define E1000_PCH_RAICC(_n) (0x05F50 + ((_n) * 4))
+diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
+index c063128ed1df..f2db4ff0003f 100644
+--- a/drivers/net/ethernet/intel/e1000e/netdev.c
++++ b/drivers/net/ethernet/intel/e1000e/netdev.c
+@@ -6991,8 +6991,21 @@ static __maybe_unused int e1000e_pm_suspend(struct device *dev)
+ struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct pci_dev *pdev = to_pci_dev(dev);
++ struct e1000_hw *hw = &adapter->hw;
++ u16 phy_data;
+ int rc;
+
++ if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID &&
++ hw->mac.type >= e1000_pch_adp) {
++ /* Mask OEM Bits / Gig Disable / Restart AN (772_26[12] = 1) */
++ e1e_rphy(hw, I217_MEMPWR, &phy_data);
++ phy_data |= I217_MEMPWR_MOEM;
++ e1e_wphy(hw, I217_MEMPWR, phy_data);
++
++ /* Disable LCD reset */
++ hw->phy.reset_disable = true;
++ }
++
+ e1000e_flush_lpic(pdev);
+
+ e1000e_pm_freeze(dev);
+@@ -7014,6 +7027,8 @@ static __maybe_unused int e1000e_pm_resume(struct device *dev)
+ struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct pci_dev *pdev = to_pci_dev(dev);
++ struct e1000_hw *hw = &adapter->hw;
++ u16 phy_data;
+ int rc;
+
+ /* Introduce S0ix implementation */
+@@ -7024,6 +7039,17 @@ static __maybe_unused int e1000e_pm_resume(struct device *dev)
+ if (rc)
+ return rc;
+
++ if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID &&
++ hw->mac.type >= e1000_pch_adp) {
++ /* Unmask OEM Bits / Gig Disable / Restart AN 772_26[12] = 0 */
++ e1e_rphy(hw, I217_MEMPWR, &phy_data);
++ phy_data &= ~I217_MEMPWR_MOEM;
++ e1e_wphy(hw, I217_MEMPWR, phy_data);
++
++ /* Enable LCD reset */
++ hw->phy.reset_disable = false;
++ }
++
+ return e1000e_pm_thaw(dev);
+ }
+
+--
+2.34.1
+
--- /dev/null
+From 31531faa59684b9869ef5b39c00dd9730e0d1f2f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Jun 2021 15:43:48 +0200
+Subject: iavf: Add trace while removing device
+
+From: Jedrzej Jagielski <jedrzej.jagielski@intel.com>
+
+[ Upstream commit bdb9e5c7aec73a7b8b5acab37587b6de1203e68d ]
+
+Add kernel trace that device was removed.
+Currently there is no such information.
+I.e. Host admin removes a PCI device from a VM,
+than on VM shall be info about the event.
+
+This patch adds info log to iavf_remove function.
+
+Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
+Signed-off-by: Jedrzej Jagielski <jedrzej.jagielski@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf_main.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
+index 5ff6d0de654e..fff9e9c7f76e 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
+@@ -4005,6 +4005,7 @@ static void iavf_remove(struct pci_dev *pdev)
+ if (iavf_lock_timeout(&adapter->crit_lock, 5000))
+ dev_warn(&adapter->pdev->dev, "failed to acquire crit_lock in %s\n", __FUNCTION__);
+
++ dev_info(&adapter->pdev->dev, "Removing device\n");
+ /* Shut down all the garbage mashers on the detention level */
+ iavf_change_state(adapter, __IAVF_REMOVE);
+ adapter->aq_required = 0;
+--
+2.34.1
+
--- /dev/null
+From 9ccd78004b57c3dede3fc56df9ca14144c4a5c24 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Feb 2022 13:36:56 +0100
+Subject: iavf: Add waiting so the port is initialized in remove
+
+From: Slawomir Laba <slawomirx.laba@intel.com>
+
+[ Upstream commit 974578017fc1fdd06cea8afb9dfa32602e8529ed ]
+
+There exist races when port is being configured and remove is
+triggered.
+
+unregister_netdev is not and can't be called under crit_lock
+mutex since it is calling ndo_stop -> iavf_close which requires
+this lock. Depending on init state the netdev could be still
+unregistered so unregister_netdev never cleans up, when shortly
+after that the device could become registered.
+
+Make iavf_remove wait until port finishes initialization.
+All critical state changes are atomic (under crit_lock).
+Crashes that come from iavf_reset_interrupt_capability and
+iavf_free_traffic_irqs should now be solved in a graceful
+manner.
+
+Fixes: 605ca7c5c6707 ("iavf: Fix kernel BUG in free_msi_irqs")
+Signed-off-by: Slawomir Laba <slawomirx.laba@intel.com>
+Signed-off-by: Phani Burra <phani.r.burra@intel.com>
+Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf_main.c | 27 ++++++++++++---------
+ 1 file changed, 16 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
+index ab7cce78988a..d5055a49ae12 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
+@@ -3981,7 +3981,6 @@ static int __maybe_unused iavf_resume(struct device *dev_d)
+ static void iavf_remove(struct pci_dev *pdev)
+ {
+ struct iavf_adapter *adapter = iavf_pdev_to_adapter(pdev);
+- enum iavf_state_t prev_state = adapter->last_state;
+ struct net_device *netdev = adapter->netdev;
+ struct iavf_fdir_fltr *fdir, *fdirtmp;
+ struct iavf_vlan_filter *vlf, *vlftmp;
+@@ -3991,6 +3990,22 @@ static void iavf_remove(struct pci_dev *pdev)
+ struct iavf_hw *hw = &adapter->hw;
+ int err;
+
++ /* Wait until port initialization is complete.
++ * There are flows where register/unregister netdev may race.
++ */
++ while (1) {
++ mutex_lock(&adapter->crit_lock);
++ if (adapter->state == __IAVF_RUNNING ||
++ adapter->state == __IAVF_DOWN) {
++ mutex_unlock(&adapter->crit_lock);
++ break;
++ }
++
++ mutex_unlock(&adapter->crit_lock);
++ usleep_range(500, 1000);
++ }
++ cancel_delayed_work_sync(&adapter->watchdog_task);
++
+ if (adapter->netdev_registered) {
+ unregister_netdev(netdev);
+ adapter->netdev_registered = false;
+@@ -4028,16 +4043,6 @@ static void iavf_remove(struct pci_dev *pdev)
+ iavf_free_all_rx_resources(adapter);
+ iavf_free_misc_irq(adapter);
+
+- /* In case we enter iavf_remove from erroneous state, free traffic irqs
+- * here, so as to not cause a kernel crash, when calling
+- * iavf_reset_interrupt_capability.
+- */
+- if ((adapter->last_state == __IAVF_RESETTING &&
+- prev_state != __IAVF_DOWN) ||
+- (adapter->last_state == __IAVF_RUNNING &&
+- !(netdev->flags & IFF_UP)))
+- iavf_free_traffic_irqs(adapter);
+-
+ iavf_reset_interrupt_capability(adapter);
+ iavf_free_q_vectors(adapter);
+
+--
+2.34.1
+
--- /dev/null
+From 99370296907366839eaca8f96dff68d036a1df4f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Feb 2022 13:38:55 +0100
+Subject: iavf: Fix __IAVF_RESETTING state usage
+
+From: Slawomir Laba <slawomirx.laba@intel.com>
+
+[ Upstream commit 14756b2ae265d526b8356e86729090b01778fdf6 ]
+
+The setup of __IAVF_RESETTING state in watchdog task had no
+effect and could lead to slow resets in the driver as
+the task for __IAVF_RESETTING state only requeues watchdog.
+Till now the __IAVF_RESETTING was interpreted by reset task
+as running state which could lead to errors with allocating
+and resources disposal.
+
+Make watchdog_task queue the reset task when it's necessary.
+Do not update the state to __IAVF_RESETTING so the reset task
+knows exactly what is the current state of the adapter.
+
+Fixes: 898ef1cb1cb2 ("iavf: Combine init and watchdog state machines")
+Signed-off-by: Slawomir Laba <slawomirx.laba@intel.com>
+Signed-off-by: Phani Burra <phani.r.burra@intel.com>
+Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf_main.c | 13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
+index 9ed02a8ca7a3..138db07bdfa8 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
+@@ -1073,8 +1073,7 @@ void iavf_down(struct iavf_adapter *adapter)
+ rss->state = IAVF_ADV_RSS_DEL_REQUEST;
+ spin_unlock_bh(&adapter->adv_rss_lock);
+
+- if (!(adapter->flags & IAVF_FLAG_PF_COMMS_FAILED) &&
+- adapter->state != __IAVF_RESETTING) {
++ if (!(adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)) {
+ /* cancel any current operation */
+ adapter->current_op = VIRTCHNL_OP_UNKNOWN;
+ /* Schedule operations to close down the HW. Don't wait
+@@ -1992,11 +1991,12 @@ static void iavf_watchdog_task(struct work_struct *work)
+ if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
+ iavf_change_state(adapter, __IAVF_COMM_FAILED);
+
+- if (adapter->flags & IAVF_FLAG_RESET_NEEDED &&
+- adapter->state != __IAVF_RESETTING) {
+- iavf_change_state(adapter, __IAVF_RESETTING);
++ if (adapter->flags & IAVF_FLAG_RESET_NEEDED) {
+ adapter->aq_required = 0;
+ adapter->current_op = VIRTCHNL_OP_UNKNOWN;
++ mutex_unlock(&adapter->crit_lock);
++ queue_work(iavf_wq, &adapter->reset_task);
++ return;
+ }
+
+ switch (adapter->state) {
+@@ -2289,8 +2289,7 @@ static void iavf_reset_task(struct work_struct *work)
+ * ndo_open() returning, so we can't assume it means all our open
+ * tasks have finished, since we're not holding the rtnl_lock here.
+ */
+- running = ((adapter->state == __IAVF_RUNNING) ||
+- (adapter->state == __IAVF_RESETTING));
++ running = adapter->state == __IAVF_RUNNING;
+
+ if (running) {
+ netdev->flags &= ~IFF_UP;
+--
+2.34.1
+
--- /dev/null
+From b5ee8c62e24fc6ddbec4fbbe5e7964968d6fc37c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Feb 2022 13:37:10 +0100
+Subject: iavf: Fix init state closure on remove
+
+From: Slawomir Laba <slawomirx.laba@intel.com>
+
+[ Upstream commit 3ccd54ef44ebfa0792c5441b6d9c86618f3378d1 ]
+
+When init states of the adapter work, the errors like lack
+of communication with the PF might hop in. If such events
+occur the driver restores previous states in order to retry
+initialization in a proper way. When remove task kicks in,
+this situation could lead to races with unregistering the
+netdevice as well as resources cleanup. With the commit
+introducing the waiting in remove for init to complete,
+this problem turns into an endless waiting if init never
+recovers from errors.
+
+Introduce __IAVF_IN_REMOVE_TASK bit to indicate that the
+remove thread has started.
+
+Make __IAVF_COMM_FAILED adapter state respect the
+__IAVF_IN_REMOVE_TASK bit and set the __IAVF_INIT_FAILED
+state and return without any action instead of trying to
+recover.
+
+Make __IAVF_INIT_FAILED adapter state respect the
+__IAVF_IN_REMOVE_TASK bit and return without any further
+actions.
+
+Make the loop in the remove handler break when adapter has
+__IAVF_INIT_FAILED state set.
+
+Fixes: 898ef1cb1cb2 ("iavf: Combine init and watchdog state machines")
+Signed-off-by: Slawomir Laba <slawomirx.laba@intel.com>
+Signed-off-by: Phani Burra <phani.r.burra@intel.com>
+Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf.h | 4 ++++
+ drivers/net/ethernet/intel/iavf/iavf_main.c | 24 ++++++++++++++++++++-
+ 2 files changed, 27 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h
+index 21e0f3361560..ffc61993019b 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf.h
++++ b/drivers/net/ethernet/intel/iavf/iavf.h
+@@ -188,6 +188,10 @@ enum iavf_state_t {
+ __IAVF_RUNNING, /* opened, working */
+ };
+
++enum iavf_critical_section_t {
++ __IAVF_IN_REMOVE_TASK, /* device being removed */
++};
++
+ #define IAVF_CLOUD_FIELD_OMAC 0x01
+ #define IAVF_CLOUD_FIELD_IMAC 0x02
+ #define IAVF_CLOUD_FIELD_IVLAN 0x04
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
+index d5055a49ae12..2a9044c8396f 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
+@@ -2019,6 +2019,15 @@ static void iavf_watchdog_task(struct work_struct *work)
+ msecs_to_jiffies(1));
+ return;
+ case __IAVF_INIT_FAILED:
++ if (test_bit(__IAVF_IN_REMOVE_TASK,
++ &adapter->crit_section)) {
++ /* Do not update the state and do not reschedule
++ * watchdog task, iavf_remove should handle this state
++ * as it can loop forever
++ */
++ mutex_unlock(&adapter->crit_lock);
++ return;
++ }
+ if (++adapter->aq_wait_count > IAVF_AQ_MAX_ERR) {
+ dev_err(&adapter->pdev->dev,
+ "Failed to communicate with PF; waiting before retry\n");
+@@ -2035,6 +2044,17 @@ static void iavf_watchdog_task(struct work_struct *work)
+ queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ);
+ return;
+ case __IAVF_COMM_FAILED:
++ if (test_bit(__IAVF_IN_REMOVE_TASK,
++ &adapter->crit_section)) {
++ /* Set state to __IAVF_INIT_FAILED and perform remove
++ * steps. Remove IAVF_FLAG_PF_COMMS_FAILED so the task
++ * doesn't bring the state back to __IAVF_COMM_FAILED.
++ */
++ iavf_change_state(adapter, __IAVF_INIT_FAILED);
++ adapter->flags &= ~IAVF_FLAG_PF_COMMS_FAILED;
++ mutex_unlock(&adapter->crit_lock);
++ return;
++ }
+ reg_val = rd32(hw, IAVF_VFGEN_RSTAT) &
+ IAVF_VFGEN_RSTAT_VFR_STATE_MASK;
+ if (reg_val == VIRTCHNL_VFR_VFACTIVE ||
+@@ -3990,13 +4010,15 @@ static void iavf_remove(struct pci_dev *pdev)
+ struct iavf_hw *hw = &adapter->hw;
+ int err;
+
++ set_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section);
+ /* Wait until port initialization is complete.
+ * There are flows where register/unregister netdev may race.
+ */
+ while (1) {
+ mutex_lock(&adapter->crit_lock);
+ if (adapter->state == __IAVF_RUNNING ||
+- adapter->state == __IAVF_DOWN) {
++ adapter->state == __IAVF_DOWN ||
++ adapter->state == __IAVF_INIT_FAILED) {
+ mutex_unlock(&adapter->crit_lock);
+ break;
+ }
+--
+2.34.1
+
--- /dev/null
+From 4ed13bc6fb5640e254709a62b47d3bc20a2ed796 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Feb 2022 13:37:50 +0100
+Subject: iavf: Fix locking for VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS
+
+From: Slawomir Laba <slawomirx.laba@intel.com>
+
+[ Upstream commit 0579fafd37fb7efe091f0e6c8ccf968864f40f3e ]
+
+iavf_virtchnl_completion is called under crit_lock but when
+the code for VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS is called,
+this lock is released in order to obtain rtnl_lock to avoid
+ABBA deadlock with unregister_netdev.
+
+Along with the new way iavf_remove behaves, there exist
+many risks related to the lock release and attmepts to regrab
+it. The driver faces crashes related to races between
+unregister_netdev and netdev_update_features. Yet another
+risk is that the driver could already obtain the crit_lock
+in order to destroy it and iavf_virtchnl_completion could
+crash or block forever.
+
+Make iavf_virtchnl_completion never relock crit_lock in it's
+call paths.
+
+Extract rtnl_lock locking logic to the driver for
+unregister_netdev in order to set the netdev_registered flag
+inside the lock.
+
+Introduce a new flag that will inform adminq_task to perform
+the code from VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS right after
+it finishes processing messages. Guard this code with remove
+flags so it's never called when the driver is in remove state.
+
+Fixes: 5951a2b9812d ("iavf: Fix VLAN feature flags after VFR")
+Signed-off-by: Slawomir Laba <slawomirx.laba@intel.com>
+Signed-off-by: Phani Burra <phani.r.burra@intel.com>
+Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf.h | 1 +
+ drivers/net/ethernet/intel/iavf/iavf_main.c | 16 +++++++++++++++-
+ drivers/net/ethernet/intel/iavf/iavf_virtchnl.c | 14 +-------------
+ 3 files changed, 17 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h
+index ffc61993019b..9a122aea6979 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf.h
++++ b/drivers/net/ethernet/intel/iavf/iavf.h
+@@ -274,6 +274,7 @@ struct iavf_adapter {
+ #define IAVF_FLAG_LEGACY_RX BIT(15)
+ #define IAVF_FLAG_REINIT_ITR_NEEDED BIT(16)
+ #define IAVF_FLAG_QUEUES_DISABLED BIT(17)
++#define IAVF_FLAG_SETUP_NETDEV_FEATURES BIT(18)
+ /* duplicates for common code */
+ #define IAVF_FLAG_DCB_ENABLED 0
+ /* flags for admin queue service task */
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
+index 2a9044c8396f..1af3fe427543 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
+@@ -2465,6 +2465,18 @@ static void iavf_adminq_task(struct work_struct *work)
+ } while (pending);
+ mutex_unlock(&adapter->crit_lock);
+
++ if ((adapter->flags & IAVF_FLAG_SETUP_NETDEV_FEATURES)) {
++ if (adapter->netdev_registered ||
++ !test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section)) {
++ struct net_device *netdev = adapter->netdev;
++
++ rtnl_lock();
++ netdev_update_features(netdev);
++ rtnl_unlock();
++ }
++
++ adapter->flags &= ~IAVF_FLAG_SETUP_NETDEV_FEATURES;
++ }
+ if ((adapter->flags &
+ (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED)) ||
+ adapter->state == __IAVF_RESETTING)
+@@ -4029,8 +4041,10 @@ static void iavf_remove(struct pci_dev *pdev)
+ cancel_delayed_work_sync(&adapter->watchdog_task);
+
+ if (adapter->netdev_registered) {
+- unregister_netdev(netdev);
++ rtnl_lock();
++ unregister_netdevice(netdev);
+ adapter->netdev_registered = false;
++ rtnl_unlock();
+ }
+ if (CLIENT_ALLOWED(adapter)) {
+ err = iavf_lan_del_device(adapter);
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
+index d60bf7c21200..d3da65d24bd6 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
++++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
+@@ -1752,19 +1752,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
+
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+ iavf_process_config(adapter);
+-
+- /* unlock crit_lock before acquiring rtnl_lock as other
+- * processes holding rtnl_lock could be waiting for the same
+- * crit_lock
+- */
+- mutex_unlock(&adapter->crit_lock);
+- rtnl_lock();
+- netdev_update_features(adapter->netdev);
+- rtnl_unlock();
+- if (iavf_lock_timeout(&adapter->crit_lock, 10000))
+- dev_warn(&adapter->pdev->dev, "failed to acquire crit_lock in %s\n",
+- __FUNCTION__);
+-
++ adapter->flags |= IAVF_FLAG_SETUP_NETDEV_FEATURES;
+ }
+ break;
+ case VIRTCHNL_OP_ENABLE_QUEUES:
+--
+2.34.1
+
--- /dev/null
+From e890ce16df6f8ce37e95dc56b74ff4da0c1aaaaf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Feb 2022 13:38:01 +0100
+Subject: iavf: Fix race in init state
+
+From: Slawomir Laba <slawomirx.laba@intel.com>
+
+[ Upstream commit a472eb5cbaebb5774672c565e024336c039e9128 ]
+
+When iavf_init_version_check sends VIRTCHNL_OP_GET_VF_RESOURCES
+message, the driver will wait for the response after requeueing
+the watchdog task in iavf_init_get_resources call stack. The
+logic is implemented this way that iavf_init_get_resources has
+to be called in order to allocate adapter->vf_res. It is polling
+for the AQ response in iavf_get_vf_config function. Expect a
+call trace from kernel when adminq_task worker handles this
+message first. adapter->vf_res will be NULL in
+iavf_virtchnl_completion.
+
+Make the watchdog task not queue the adminq_task if the init
+process is not finished yet.
+
+Fixes: 898ef1cb1cb2 ("iavf: Combine init and watchdog state machines")
+Signed-off-by: Slawomir Laba <slawomirx.laba@intel.com>
+Signed-off-by: Phani Burra <phani.r.burra@intel.com>
+Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf_main.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
+index 1af3fe427543..9ed02a8ca7a3 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
+@@ -2124,7 +2124,8 @@ static void iavf_watchdog_task(struct work_struct *work)
+ schedule_delayed_work(&adapter->client_task, msecs_to_jiffies(5));
+ mutex_unlock(&adapter->crit_lock);
+ restart_watchdog:
+- queue_work(iavf_wq, &adapter->adminq_task);
++ if (adapter->state >= __IAVF_DOWN)
++ queue_work(iavf_wq, &adapter->adminq_task);
+ if (adapter->aq_required)
+ queue_delayed_work(iavf_wq, &adapter->watchdog_task,
+ msecs_to_jiffies(20));
+--
+2.34.1
+
--- /dev/null
+From aa8fabb6d326832ab5aebcc9186aa22245552065 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Feb 2022 13:35:49 +0100
+Subject: iavf: Rework mutexes for better synchronisation
+
+From: Slawomir Laba <slawomirx.laba@intel.com>
+
+[ Upstream commit fc2e6b3b132a907378f6af08356b105a4139c4fb ]
+
+The driver used to crash in multiple spots when put to stress testing
+of the init, reset and remove paths.
+
+The user would experience call traces or hangs when creating,
+resetting, removing VFs. Depending on the machines, the call traces
+are happening in random spots, like reset restoring resources racing
+with driver remove.
+
+Make adapter->crit_lock mutex a mandatory lock for guarding the
+operations performed on all workqueues and functions dealing with
+resource allocation and disposal.
+
+Make __IAVF_REMOVE a final state of the driver respected by
+workqueues that shall not requeue, when they fail to obtain the
+crit_lock.
+
+Make the IRQ handler not to queue the new work for adminq_task
+when the __IAVF_REMOVE state is set.
+
+Fixes: 5ac49f3c2702 ("iavf: use mutexes for locking of critical sections")
+Signed-off-by: Slawomir Laba <slawomirx.laba@intel.com>
+Signed-off-by: Phani Burra <phani.r.burra@intel.com>
+Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf.h | 1 -
+ drivers/net/ethernet/intel/iavf/iavf_main.c | 66 +++++++++++----------
+ 2 files changed, 36 insertions(+), 31 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h
+index 3789269ce741..21e0f3361560 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf.h
++++ b/drivers/net/ethernet/intel/iavf/iavf.h
+@@ -233,7 +233,6 @@ struct iavf_adapter {
+ struct list_head mac_filter_list;
+ struct mutex crit_lock;
+ struct mutex client_lock;
+- struct mutex remove_lock;
+ /* Lock to protect accesses to MAC and VLAN lists */
+ spinlock_t mac_vlan_list_lock;
+ char misc_vector_name[IFNAMSIZ + 9];
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
+index fff9e9c7f76e..ab7cce78988a 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
+@@ -302,8 +302,9 @@ static irqreturn_t iavf_msix_aq(int irq, void *data)
+ rd32(hw, IAVF_VFINT_ICR01);
+ rd32(hw, IAVF_VFINT_ICR0_ENA1);
+
+- /* schedule work on the private workqueue */
+- queue_work(iavf_wq, &adapter->adminq_task);
++ if (adapter->state != __IAVF_REMOVE)
++ /* schedule work on the private workqueue */
++ queue_work(iavf_wq, &adapter->adminq_task);
+
+ return IRQ_HANDLED;
+ }
+@@ -1981,8 +1982,12 @@ static void iavf_watchdog_task(struct work_struct *work)
+ struct iavf_hw *hw = &adapter->hw;
+ u32 reg_val;
+
+- if (!mutex_trylock(&adapter->crit_lock))
++ if (!mutex_trylock(&adapter->crit_lock)) {
++ if (adapter->state == __IAVF_REMOVE)
++ return;
++
+ goto restart_watchdog;
++ }
+
+ if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
+ iavf_change_state(adapter, __IAVF_COMM_FAILED);
+@@ -2193,13 +2198,13 @@ static void iavf_reset_task(struct work_struct *work)
+ /* When device is being removed it doesn't make sense to run the reset
+ * task, just return in such a case.
+ */
+- if (mutex_is_locked(&adapter->remove_lock))
+- return;
++ if (!mutex_trylock(&adapter->crit_lock)) {
++ if (adapter->state != __IAVF_REMOVE)
++ queue_work(iavf_wq, &adapter->reset_task);
+
+- if (iavf_lock_timeout(&adapter->crit_lock, 200)) {
+- schedule_work(&adapter->reset_task);
+ return;
+ }
++
+ while (!mutex_trylock(&adapter->client_lock))
+ usleep_range(500, 1000);
+ if (CLIENT_ENABLED(adapter)) {
+@@ -2412,13 +2417,19 @@ static void iavf_adminq_task(struct work_struct *work)
+ if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
+ goto out;
+
++ if (!mutex_trylock(&adapter->crit_lock)) {
++ if (adapter->state == __IAVF_REMOVE)
++ return;
++
++ queue_work(iavf_wq, &adapter->adminq_task);
++ goto out;
++ }
++
+ event.buf_len = IAVF_MAX_AQ_BUF_SIZE;
+ event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL);
+ if (!event.msg_buf)
+ goto out;
+
+- if (iavf_lock_timeout(&adapter->crit_lock, 200))
+- goto freedom;
+ do {
+ ret = iavf_clean_arq_element(hw, &event, &pending);
+ v_op = (enum virtchnl_ops)le32_to_cpu(event.desc.cookie_high);
+@@ -3386,11 +3397,12 @@ static int iavf_close(struct net_device *netdev)
+ struct iavf_adapter *adapter = netdev_priv(netdev);
+ int status;
+
+- if (adapter->state <= __IAVF_DOWN_PENDING)
+- return 0;
++ mutex_lock(&adapter->crit_lock);
+
+- while (!mutex_trylock(&adapter->crit_lock))
+- usleep_range(500, 1000);
++ if (adapter->state <= __IAVF_DOWN_PENDING) {
++ mutex_unlock(&adapter->crit_lock);
++ return 0;
++ }
+
+ set_bit(__IAVF_VSI_DOWN, adapter->vsi.state);
+ if (CLIENT_ENABLED(adapter))
+@@ -3854,7 +3866,6 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ */
+ mutex_init(&adapter->crit_lock);
+ mutex_init(&adapter->client_lock);
+- mutex_init(&adapter->remove_lock);
+ mutex_init(&hw->aq.asq_mutex);
+ mutex_init(&hw->aq.arq_mutex);
+
+@@ -3979,11 +3990,7 @@ static void iavf_remove(struct pci_dev *pdev)
+ struct iavf_cloud_filter *cf, *cftmp;
+ struct iavf_hw *hw = &adapter->hw;
+ int err;
+- /* Indicate we are in remove and not to run reset_task */
+- mutex_lock(&adapter->remove_lock);
+- cancel_work_sync(&adapter->reset_task);
+- cancel_delayed_work_sync(&adapter->watchdog_task);
+- cancel_delayed_work_sync(&adapter->client_task);
++
+ if (adapter->netdev_registered) {
+ unregister_netdev(netdev);
+ adapter->netdev_registered = false;
+@@ -3995,6 +4002,10 @@ static void iavf_remove(struct pci_dev *pdev)
+ err);
+ }
+
++ mutex_lock(&adapter->crit_lock);
++ dev_info(&adapter->pdev->dev, "Remove device\n");
++ iavf_change_state(adapter, __IAVF_REMOVE);
++
+ iavf_request_reset(adapter);
+ msleep(50);
+ /* If the FW isn't responding, kick it once, but only once. */
+@@ -4002,18 +4013,19 @@ static void iavf_remove(struct pci_dev *pdev)
+ iavf_request_reset(adapter);
+ msleep(50);
+ }
+- if (iavf_lock_timeout(&adapter->crit_lock, 5000))
+- dev_warn(&adapter->pdev->dev, "failed to acquire crit_lock in %s\n", __FUNCTION__);
+
+- dev_info(&adapter->pdev->dev, "Removing device\n");
++ iavf_misc_irq_disable(adapter);
+ /* Shut down all the garbage mashers on the detention level */
+- iavf_change_state(adapter, __IAVF_REMOVE);
++ cancel_work_sync(&adapter->reset_task);
++ cancel_delayed_work_sync(&adapter->watchdog_task);
++ cancel_work_sync(&adapter->adminq_task);
++ cancel_delayed_work_sync(&adapter->client_task);
++
+ adapter->aq_required = 0;
+ adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
+
+ iavf_free_all_tx_resources(adapter);
+ iavf_free_all_rx_resources(adapter);
+- iavf_misc_irq_disable(adapter);
+ iavf_free_misc_irq(adapter);
+
+ /* In case we enter iavf_remove from erroneous state, free traffic irqs
+@@ -4029,10 +4041,6 @@ static void iavf_remove(struct pci_dev *pdev)
+ iavf_reset_interrupt_capability(adapter);
+ iavf_free_q_vectors(adapter);
+
+- cancel_delayed_work_sync(&adapter->watchdog_task);
+-
+- cancel_work_sync(&adapter->adminq_task);
+-
+ iavf_free_rss(adapter);
+
+ if (hw->aq.asq.count)
+@@ -4044,8 +4052,6 @@ static void iavf_remove(struct pci_dev *pdev)
+ mutex_destroy(&adapter->client_lock);
+ mutex_unlock(&adapter->crit_lock);
+ mutex_destroy(&adapter->crit_lock);
+- mutex_unlock(&adapter->remove_lock);
+- mutex_destroy(&adapter->remove_lock);
+
+ iounmap(hw->hw_addr);
+ pci_release_regions(pdev);
+--
+2.34.1
+
--- /dev/null
+From 8dda9af1e93ced0c920755ad32d2e6c93ea00be8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Feb 2022 22:23:58 -0800
+Subject: ibmvnic: Allow queueing resets during probe
+
+From: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+
+[ Upstream commit fd98693cb0721317f27341951593712c580c36a1 ]
+
+We currently don't allow queuing resets when adapter is in VNIC_PROBING
+state - instead we throw away the reset and return EBUSY. The reasoning
+is probably that during ibmvnic_probe() the ibmvnic_adapter itself is
+being initialized so performing a reset during this time can lead us to
+accessing fields in the ibmvnic_adapter that are not fully initialized.
+A review of the code shows that all the adapter state neede to process a
+reset is initialized before registering the CRQ so that should no longer
+be a concern.
+
+Further the expectation is that if we do get a reset (transport event)
+during probe, the do..while() loop in ibmvnic_probe() will handle this
+by reinitializing the CRQ.
+
+While that is true to some extent, it is possible that the reset might
+occur _after_ the CRQ is registered and CRQ_INIT message was exchanged
+but _before_ the adapter state is set to VNIC_PROBED. As mentioned above,
+such a reset will be thrown away. While the client assumes that the
+adapter is functional, the vnic server will wait for the client to reinit
+the adapter. This disconnect between the two leaves the adapter down
+needing manual intervention.
+
+Because ibmvnic_probe() has other work to do after initializing the CRQ
+(such as registering the netdev at a minimum) and because the reset event
+can occur at any instant after the CRQ is initialized, there will always
+be a window between initializing the CRQ and considering the adapter
+ready for resets (ie state == PROBED).
+
+So rather than discarding resets during this window, allow queueing them
+- but only process them after the adapter is fully initialized.
+
+To do this, introduce a new completion state ->probe_done and have the
+reset worker thread wait on this before processing resets.
+
+This change brings up two new situations in or just after ibmvnic_probe().
+First after one or more resets were queued, we encounter an error and
+decide to retry the initialization. At that point the queued resets are
+no longer relevant since we could be talking to a new vnic server. So we
+must purge/flush the queued resets before restarting the initialization.
+As a side note, since we are still in the probing stage and we have not
+registered the netdev, it will not be CHANGE_PARAM reset.
+
+Second this change opens up a potential race between the worker thread
+in __ibmvnic_reset(), the tasklet and the ibmvnic_open() due to the
+following sequence of events:
+
+ 1. Register CRQ
+ 2. Get transport event before CRQ_INIT completes.
+ 3. Tasklet schedules reset:
+ a) add rwi to list
+ b) schedule_work() to start worker thread which runs
+ and waits for ->probe_done.
+ 4. ibmvnic_probe() decides to retry, purges rwi_list
+ 5. Re-register crq and this time rest of probe succeeds - register
+ netdev and complete(->probe_done).
+ 6. Worker thread resumes in __ibmvnic_reset() from 3b.
+ 7. Worker thread sets ->resetting bit
+ 8. ibmvnic_open() comes in, notices ->resetting bit, sets state
+ to IBMVNIC_OPEN and returns early expecting worker thread to
+ finish the open.
+ 9. Worker thread finds rwi_list empty and returns without
+ opening the interface.
+
+If this happens, the ->ndo_open() call is effectively lost and the
+interface remains down. To address this, ensure that ->rwi_list is
+not empty before setting the ->resetting bit. See also comments in
+__ibmvnic_reset().
+
+Fixes: 6a2fb0e99f9c ("ibmvnic: driver initialization for kdump/kexec")
+Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c | 107 ++++++++++++++++++++++++++---
+ drivers/net/ethernet/ibm/ibmvnic.h | 1 +
+ 2 files changed, 98 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index 679257d3a3c6..a8b65c072f64 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -2618,23 +2618,82 @@ static int do_passive_init(struct ibmvnic_adapter *adapter)
+ static void __ibmvnic_reset(struct work_struct *work)
+ {
+ struct ibmvnic_adapter *adapter;
+- bool saved_state = false;
++ unsigned int timeout = 5000;
+ struct ibmvnic_rwi *tmprwi;
++ bool saved_state = false;
+ struct ibmvnic_rwi *rwi;
+ unsigned long flags;
+- u32 reset_state;
++ struct device *dev;
++ bool need_reset;
+ int num_fails = 0;
++ u32 reset_state;
+ int rc = 0;
+
+ adapter = container_of(work, struct ibmvnic_adapter, ibmvnic_reset);
++ dev = &adapter->vdev->dev;
+
+- if (test_and_set_bit_lock(0, &adapter->resetting)) {
++ /* Wait for ibmvnic_probe() to complete. If probe is taking too long
++ * or if another reset is in progress, defer work for now. If probe
++ * eventually fails it will flush and terminate our work.
++ *
++ * Three possibilities here:
++ * 1. Adpater being removed - just return
++ * 2. Timed out on probe or another reset in progress - delay the work
++ * 3. Completed probe - perform any resets in queue
++ */
++ if (adapter->state == VNIC_PROBING &&
++ !wait_for_completion_timeout(&adapter->probe_done, timeout)) {
++ dev_err(dev, "Reset thread timed out on probe");
+ queue_delayed_work(system_long_wq,
+ &adapter->ibmvnic_delayed_reset,
+ IBMVNIC_RESET_DELAY);
+ return;
+ }
+
++ /* adapter is done with probe (i.e state is never VNIC_PROBING now) */
++ if (adapter->state == VNIC_REMOVING)
++ return;
++
++ /* ->rwi_list is stable now (no one else is removing entries) */
++
++ /* ibmvnic_probe() may have purged the reset queue after we were
++ * scheduled to process a reset so there maybe no resets to process.
++ * Before setting the ->resetting bit though, we have to make sure
++ * that there is infact a reset to process. Otherwise we may race
++ * with ibmvnic_open() and end up leaving the vnic down:
++ *
++ * __ibmvnic_reset() ibmvnic_open()
++ * ----------------- --------------
++ *
++ * set ->resetting bit
++ * find ->resetting bit is set
++ * set ->state to IBMVNIC_OPEN (i.e
++ * assume reset will open device)
++ * return
++ * find reset queue empty
++ * return
++ *
++ * Neither performed vnic login/open and vnic stays down
++ *
++ * If we hold the lock and conditionally set the bit, either we
++ * or ibmvnic_open() will complete the open.
++ */
++ need_reset = false;
++ spin_lock(&adapter->rwi_lock);
++ if (!list_empty(&adapter->rwi_list)) {
++ if (test_and_set_bit_lock(0, &adapter->resetting)) {
++ queue_delayed_work(system_long_wq,
++ &adapter->ibmvnic_delayed_reset,
++ IBMVNIC_RESET_DELAY);
++ } else {
++ need_reset = true;
++ }
++ }
++ spin_unlock(&adapter->rwi_lock);
++
++ if (!need_reset)
++ return;
++
+ rwi = get_next_rwi(adapter);
+ while (rwi) {
+ spin_lock_irqsave(&adapter->state_lock, flags);
+@@ -2786,13 +2845,6 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
+ goto err;
+ }
+
+- if (adapter->state == VNIC_PROBING) {
+- netdev_warn(netdev, "Adapter reset during probe\n");
+- adapter->init_done_rc = -EAGAIN;
+- ret = EAGAIN;
+- goto err;
+- }
+-
+ list_for_each_entry(tmp, &adapter->rwi_list, list) {
+ if (tmp->reset_reason == reason) {
+ netdev_dbg(netdev, "Skipping matching reset, reason=%s\n",
+@@ -5761,6 +5813,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
+ struct ibmvnic_adapter *adapter;
+ struct net_device *netdev;
+ unsigned char *mac_addr_p;
++ unsigned long flags;
+ bool init_success;
+ int rc;
+
+@@ -5805,6 +5858,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
+ spin_lock_init(&adapter->rwi_lock);
+ spin_lock_init(&adapter->state_lock);
+ mutex_init(&adapter->fw_lock);
++ init_completion(&adapter->probe_done);
+ init_completion(&adapter->init_done);
+ init_completion(&adapter->fw_done);
+ init_completion(&adapter->reset_done);
+@@ -5822,6 +5876,26 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
+ */
+ adapter->failover_pending = false;
+
++ /* If we had already initialized CRQ, we may have one or
++ * more resets queued already. Discard those and release
++ * the CRQ before initializing the CRQ again.
++ */
++ release_crq_queue(adapter);
++
++ /* Since we are still in PROBING state, __ibmvnic_reset()
++ * will not access the ->rwi_list and since we released CRQ,
++ * we won't get _new_ transport events. But there maybe an
++ * ongoing ibmvnic_reset() call. So serialize access to
++ * rwi_list. If we win the race, ibvmnic_reset() could add
++ * a reset after we purged but thats ok - we just may end
++ * up with an extra reset (i.e similar to having two or more
++ * resets in the queue at once).
++ * CHECK.
++ */
++ spin_lock_irqsave(&adapter->rwi_lock, flags);
++ flush_reset_queue(adapter);
++ spin_unlock_irqrestore(&adapter->rwi_lock, flags);
++
+ rc = init_crq_queue(adapter);
+ if (rc) {
+ dev_err(&dev->dev, "Couldn't initialize crq. rc=%d\n",
+@@ -5873,6 +5947,8 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
+ }
+ dev_info(&dev->dev, "ibmvnic registered\n");
+
++ complete(&adapter->probe_done);
++
+ return 0;
+
+ ibmvnic_register_fail:
+@@ -5887,6 +5963,17 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
+ ibmvnic_init_fail:
+ release_sub_crqs(adapter, 1);
+ release_crq_queue(adapter);
++
++ /* cleanup worker thread after releasing CRQ so we don't get
++ * transport events (i.e new work items for the worker thread).
++ */
++ adapter->state = VNIC_REMOVING;
++ complete(&adapter->probe_done);
++ flush_work(&adapter->ibmvnic_reset);
++ flush_delayed_work(&adapter->ibmvnic_delayed_reset);
++
++ flush_reset_queue(adapter);
++
+ mutex_destroy(&adapter->fw_lock);
+ free_netdev(netdev);
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h
+index b8e42f67d897..549a9b7b1a70 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.h
++++ b/drivers/net/ethernet/ibm/ibmvnic.h
+@@ -933,6 +933,7 @@ struct ibmvnic_adapter {
+
+ struct ibmvnic_tx_pool *tx_pool;
+ struct ibmvnic_tx_pool *tso_pool;
++ struct completion probe_done;
+ struct completion init_done;
+ int init_done_rc;
+
+--
+2.34.1
+
--- /dev/null
+From 2451f3416710e850ea0b6de71393b7a7cba2f02e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Feb 2022 22:23:57 -0800
+Subject: ibmvnic: clear fop when retrying probe
+
+From: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+
+[ Upstream commit f628ad531b4f34fdba0984255b4a2850dd369513 ]
+
+Clear ->failover_pending flag that may have been set in the previous
+pass of registering CRQ. If we don't clear, a subsequent ibmvnic_open()
+call would be misled into thinking a failover is pending and assuming
+that the reset worker thread would open the adapter. If this pass of
+registering the CRQ succeeds (i.e there is no transport event), there
+wouldn't be a reset worker thread.
+
+This would leave the adapter unconfigured and require manual intervention
+to bring it up during boot.
+
+Fixes: 5a18e1e0c193 ("ibmvnic: Fix failover case for non-redundant configuration")
+Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index 26ea1f32281f..679257d3a3c6 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -5817,6 +5817,11 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
+ do {
+ reinit_init_done(adapter);
+
++ /* clear any failovers we got in the previous pass
++ * since we are reinitializing the CRQ
++ */
++ adapter->failover_pending = false;
++
+ rc = init_crq_queue(adapter);
+ if (rc) {
+ dev_err(&dev->dev, "Couldn't initialize crq. rc=%d\n",
+--
+2.34.1
+
--- /dev/null
+From a4db48354e5a7a137f12185261d3caf27e0da6c9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Feb 2022 22:23:54 -0800
+Subject: ibmvnic: complete init_done on transport events
+
+From: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+
+[ Upstream commit 36491f2df9ad2501e5a4ec25d3d95d72bafd2781 ]
+
+If we get a transport event, set the error and mark the init as
+complete so the attempt to send crq-init or login fail sooner
+rather than wait for the timeout.
+
+Fixes: bbd669a868bb ("ibmvnic: Fix completion structure initialization")
+Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index 5c8264e3979a..16e772f80ec5 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -5352,6 +5352,13 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
+ adapter->fw_done_rc = -EIO;
+ complete(&adapter->fw_done);
+ }
++
++ /* if we got here during crq-init, retry crq-init */
++ if (!completion_done(&adapter->init_done)) {
++ adapter->init_done_rc = -EAGAIN;
++ complete(&adapter->init_done);
++ }
++
+ if (!completion_done(&adapter->stats_done))
+ complete(&adapter->stats_done);
+ if (test_bit(0, &adapter->resetting))
+--
+2.34.1
+
--- /dev/null
+From 46cbdf8227c219ca051270e873f38443f974e17a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Feb 2022 22:23:53 -0800
+Subject: ibmvnic: define flush_reset_queue helper
+
+From: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+
+[ Upstream commit 83da53f7e4bd86dca4b2edc1e2bb324fb3c033a1 ]
+
+Define and use a helper to flush the reset queue.
+
+Fixes: 2770a7984db5 ("ibmvnic: Introduce hard reset recovery")
+Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c | 24 ++++++++++++++++--------
+ 1 file changed, 16 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index 945a84c2134f..5c8264e3979a 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -2731,12 +2731,23 @@ static void __ibmvnic_delayed_reset(struct work_struct *work)
+ __ibmvnic_reset(&adapter->ibmvnic_reset);
+ }
+
++static void flush_reset_queue(struct ibmvnic_adapter *adapter)
++{
++ struct list_head *entry, *tmp_entry;
++
++ if (!list_empty(&adapter->rwi_list)) {
++ list_for_each_safe(entry, tmp_entry, &adapter->rwi_list) {
++ list_del(entry);
++ kfree(list_entry(entry, struct ibmvnic_rwi, list));
++ }
++ }
++}
++
+ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
+ enum ibmvnic_reset_reason reason)
+ {
+- struct list_head *entry, *tmp_entry;
+- struct ibmvnic_rwi *rwi, *tmp;
+ struct net_device *netdev = adapter->netdev;
++ struct ibmvnic_rwi *rwi, *tmp;
+ unsigned long flags;
+ int ret;
+
+@@ -2779,12 +2790,9 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
+ /* if we just received a transport event,
+ * flush reset queue and process this reset
+ */
+- if (adapter->force_reset_recovery && !list_empty(&adapter->rwi_list)) {
+- list_for_each_safe(entry, tmp_entry, &adapter->rwi_list) {
+- list_del(entry);
+- kfree(list_entry(entry, struct ibmvnic_rwi, list));
+- }
+- }
++ if (adapter->force_reset_recovery)
++ flush_reset_queue(adapter);
++
+ rwi->reset_reason = reason;
+ list_add_tail(&rwi->list, &adapter->rwi_list);
+ netdev_dbg(adapter->netdev, "Scheduling reset (reason %s)\n",
+--
+2.34.1
+
--- /dev/null
+From c6d999a4962f162f0de1b18f7f35c1be5b86fdb5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Feb 2022 22:23:56 -0800
+Subject: ibmvnic: init init_done_rc earlier
+
+From: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+
+[ Upstream commit ae16bf15374d8b055e040ac6f3f1147ab1c9bb7d ]
+
+We currently initialize the ->init_done completion/return code fields
+before issuing a CRQ_INIT command. But if we get a transport event soon
+after registering the CRQ the taskslet may already have recorded the
+completion and error code. If we initialize here, we might overwrite/
+lose that and end up issuing the CRQ_INIT only to timeout later.
+
+If that timeout happens during probe, we will leave the adapter in the
+DOWN state rather than retrying to register/init the CRQ.
+
+Initialize the completion before registering the CRQ so we don't lose
+the notification.
+
+Fixes: 032c5e82847a ("Driver for IBM System i/p VNIC protocol")
+Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c | 26 +++++++++++++++++++++-----
+ 1 file changed, 21 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index 7bd0ad590898..26ea1f32281f 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -2212,6 +2212,19 @@ static const char *reset_reason_to_string(enum ibmvnic_reset_reason reason)
+ return "UNKNOWN";
+ }
+
++/*
++ * Initialize the init_done completion and return code values. We
++ * can get a transport event just after registering the CRQ and the
++ * tasklet will use this to communicate the transport event. To ensure
++ * we don't miss the notification/error, initialize these _before_
++ * regisering the CRQ.
++ */
++static inline void reinit_init_done(struct ibmvnic_adapter *adapter)
++{
++ reinit_completion(&adapter->init_done);
++ adapter->init_done_rc = 0;
++}
++
+ /*
+ * do_reset returns zero if we are able to keep processing reset events, or
+ * non-zero if we hit a fatal error and must halt.
+@@ -2318,6 +2331,8 @@ static int do_reset(struct ibmvnic_adapter *adapter,
+ */
+ adapter->state = VNIC_PROBED;
+
++ reinit_init_done(adapter);
++
+ if (adapter->reset_reason == VNIC_RESET_CHANGE_PARAM) {
+ rc = init_crq_queue(adapter);
+ } else if (adapter->reset_reason == VNIC_RESET_MOBILITY) {
+@@ -2461,7 +2476,8 @@ static int do_hard_reset(struct ibmvnic_adapter *adapter,
+ */
+ adapter->state = VNIC_PROBED;
+
+- reinit_completion(&adapter->init_done);
++ reinit_init_done(adapter);
++
+ rc = init_crq_queue(adapter);
+ if (rc) {
+ netdev_err(adapter->netdev,
+@@ -5685,10 +5701,6 @@ static int ibmvnic_reset_init(struct ibmvnic_adapter *adapter, bool reset)
+
+ adapter->from_passive_init = false;
+
+- if (reset)
+- reinit_completion(&adapter->init_done);
+-
+- adapter->init_done_rc = 0;
+ rc = ibmvnic_send_crq_init(adapter);
+ if (rc) {
+ dev_err(dev, "Send crq init failed with error %d\n", rc);
+@@ -5702,12 +5714,14 @@ static int ibmvnic_reset_init(struct ibmvnic_adapter *adapter, bool reset)
+
+ if (adapter->init_done_rc) {
+ release_crq_queue(adapter);
++ dev_err(dev, "CRQ-init failed, %d\n", adapter->init_done_rc);
+ return adapter->init_done_rc;
+ }
+
+ if (adapter->from_passive_init) {
+ adapter->state = VNIC_OPEN;
+ adapter->from_passive_init = false;
++ dev_err(dev, "CRQ-init failed, passive-init\n");
+ return -EINVAL;
+ }
+
+@@ -5801,6 +5815,8 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
+
+ init_success = false;
+ do {
++ reinit_init_done(adapter);
++
+ rc = init_crq_queue(adapter);
+ if (rc) {
+ dev_err(&dev->dev, "Couldn't initialize crq. rc=%d\n",
+--
+2.34.1
+
--- /dev/null
+From 54950130f768f2d2a0977e6f4f4b0257580ebbb6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Feb 2022 22:23:52 -0800
+Subject: ibmvnic: initialize rc before completing wait
+
+From: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+
+[ Upstream commit 765559b10ce514eb1576595834f23cdc92125fee ]
+
+We should initialize ->init_done_rc before calling complete(). Otherwise
+the waiting thread may see ->init_done_rc as 0 before we have updated it
+and may assume that the CRQ was successful.
+
+Fixes: 6b278c0cb378 ("ibmvnic delay complete()")
+Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index 996da870dafe..945a84c2134f 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -5319,9 +5319,9 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
+ }
+
+ if (!completion_done(&adapter->init_done)) {
+- complete(&adapter->init_done);
+ if (!adapter->init_done_rc)
+ adapter->init_done_rc = -EAGAIN;
++ complete(&adapter->init_done);
+ }
+
+ break;
+--
+2.34.1
+
--- /dev/null
+From 0bc96584ee434c4a72e533f64309a5ffebbef2d1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Dec 2021 00:17:47 -0500
+Subject: ibmvnic: Update driver return codes
+
+From: Dany Madden <drt@linux.ibm.com>
+
+[ Upstream commit b6ee566cf3940883d67c0d142fae8d410e975f47 ]
+
+Update return codes to be more informative.
+
+Signed-off-by: Jacob Root <otis@otisroot.com>
+Signed-off-by: Dany Madden <drt@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c | 64 ++++++++++++++++--------------
+ 1 file changed, 34 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index 16e772f80ec5..7bd0ad590898 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -309,7 +309,7 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,
+ if (adapter->fw_done_rc) {
+ dev_err(dev, "Couldn't map LTB, rc = %d\n",
+ adapter->fw_done_rc);
+- rc = -1;
++ rc = -EIO;
+ goto out;
+ }
+ rc = 0;
+@@ -541,13 +541,15 @@ static int init_stats_token(struct ibmvnic_adapter *adapter)
+ {
+ struct device *dev = &adapter->vdev->dev;
+ dma_addr_t stok;
++ int rc;
+
+ stok = dma_map_single(dev, &adapter->stats,
+ sizeof(struct ibmvnic_statistics),
+ DMA_FROM_DEVICE);
+- if (dma_mapping_error(dev, stok)) {
+- dev_err(dev, "Couldn't map stats buffer\n");
+- return -1;
++ rc = dma_mapping_error(dev, stok);
++ if (rc) {
++ dev_err(dev, "Couldn't map stats buffer, rc = %d\n", rc);
++ return rc;
+ }
+
+ adapter->stats_token = stok;
+@@ -656,7 +658,7 @@ static int init_rx_pools(struct net_device *netdev)
+ u64 num_pools;
+ u64 pool_size; /* # of buffers in one pool */
+ u64 buff_size;
+- int i, j;
++ int i, j, rc;
+
+ pool_size = adapter->req_rx_add_entries_per_subcrq;
+ num_pools = adapter->req_rx_queues;
+@@ -675,7 +677,7 @@ static int init_rx_pools(struct net_device *netdev)
+ GFP_KERNEL);
+ if (!adapter->rx_pool) {
+ dev_err(dev, "Failed to allocate rx pools\n");
+- return -1;
++ return -ENOMEM;
+ }
+
+ /* Set num_active_rx_pools early. If we fail below after partial
+@@ -698,6 +700,7 @@ static int init_rx_pools(struct net_device *netdev)
+ GFP_KERNEL);
+ if (!rx_pool->free_map) {
+ dev_err(dev, "Couldn't alloc free_map %d\n", i);
++ rc = -ENOMEM;
+ goto out_release;
+ }
+
+@@ -706,6 +709,7 @@ static int init_rx_pools(struct net_device *netdev)
+ GFP_KERNEL);
+ if (!rx_pool->rx_buff) {
+ dev_err(dev, "Couldn't alloc rx buffers\n");
++ rc = -ENOMEM;
+ goto out_release;
+ }
+ }
+@@ -719,8 +723,9 @@ static int init_rx_pools(struct net_device *netdev)
+ dev_dbg(dev, "Updating LTB for rx pool %d [%d, %d]\n",
+ i, rx_pool->size, rx_pool->buff_size);
+
+- if (alloc_long_term_buff(adapter, &rx_pool->long_term_buff,
+- rx_pool->size * rx_pool->buff_size))
++ rc = alloc_long_term_buff(adapter, &rx_pool->long_term_buff,
++ rx_pool->size * rx_pool->buff_size);
++ if (rc)
+ goto out;
+
+ for (j = 0; j < rx_pool->size; ++j) {
+@@ -757,7 +762,7 @@ static int init_rx_pools(struct net_device *netdev)
+ /* We failed to allocate one or more LTBs or map them on the VIOS.
+ * Hold onto the pools and any LTBs that we did allocate/map.
+ */
+- return -1;
++ return rc;
+ }
+
+ static void release_vpd_data(struct ibmvnic_adapter *adapter)
+@@ -818,13 +823,13 @@ static int init_one_tx_pool(struct net_device *netdev,
+ sizeof(struct ibmvnic_tx_buff),
+ GFP_KERNEL);
+ if (!tx_pool->tx_buff)
+- return -1;
++ return -ENOMEM;
+
+ tx_pool->free_map = kcalloc(pool_size, sizeof(int), GFP_KERNEL);
+ if (!tx_pool->free_map) {
+ kfree(tx_pool->tx_buff);
+ tx_pool->tx_buff = NULL;
+- return -1;
++ return -ENOMEM;
+ }
+
+ for (i = 0; i < pool_size; i++)
+@@ -915,7 +920,7 @@ static int init_tx_pools(struct net_device *netdev)
+ adapter->tx_pool = kcalloc(num_pools,
+ sizeof(struct ibmvnic_tx_pool), GFP_KERNEL);
+ if (!adapter->tx_pool)
+- return -1;
++ return -ENOMEM;
+
+ adapter->tso_pool = kcalloc(num_pools,
+ sizeof(struct ibmvnic_tx_pool), GFP_KERNEL);
+@@ -925,7 +930,7 @@ static int init_tx_pools(struct net_device *netdev)
+ if (!adapter->tso_pool) {
+ kfree(adapter->tx_pool);
+ adapter->tx_pool = NULL;
+- return -1;
++ return -ENOMEM;
+ }
+
+ /* Set num_active_tx_pools early. If we fail below after partial
+@@ -1114,7 +1119,7 @@ static int ibmvnic_login(struct net_device *netdev)
+ retry = false;
+ if (retry_count > retries) {
+ netdev_warn(netdev, "Login attempts exceeded\n");
+- return -1;
++ return -EACCES;
+ }
+
+ adapter->init_done_rc = 0;
+@@ -1155,25 +1160,26 @@ static int ibmvnic_login(struct net_device *netdev)
+ timeout)) {
+ netdev_warn(netdev,
+ "Capabilities query timed out\n");
+- return -1;
++ return -ETIMEDOUT;
+ }
+
+ rc = init_sub_crqs(adapter);
+ if (rc) {
+ netdev_warn(netdev,
+ "SCRQ initialization failed\n");
+- return -1;
++ return rc;
+ }
+
+ rc = init_sub_crq_irqs(adapter);
+ if (rc) {
+ netdev_warn(netdev,
+ "SCRQ irq initialization failed\n");
+- return -1;
++ return rc;
+ }
+ } else if (adapter->init_done_rc) {
+- netdev_warn(netdev, "Adapter login failed\n");
+- return -1;
++ netdev_warn(netdev, "Adapter login failed, init_done_rc = %d\n",
++ adapter->init_done_rc);
++ return -EIO;
+ }
+ } while (retry);
+
+@@ -1232,7 +1238,7 @@ static int set_link_state(struct ibmvnic_adapter *adapter, u8 link_state)
+ if (!wait_for_completion_timeout(&adapter->init_done,
+ timeout)) {
+ netdev_err(netdev, "timeout setting link state\n");
+- return -1;
++ return -ETIMEDOUT;
+ }
+
+ if (adapter->init_done_rc == PARTIALSUCCESS) {
+@@ -2293,7 +2299,7 @@ static int do_reset(struct ibmvnic_adapter *adapter,
+ /* If someone else changed the adapter state
+ * when we dropped the rtnl, fail the reset
+ */
+- rc = -1;
++ rc = -EAGAIN;
+ goto out;
+ }
+ adapter->state = VNIC_CLOSED;
+@@ -2335,10 +2341,8 @@ static int do_reset(struct ibmvnic_adapter *adapter,
+ }
+
+ rc = ibmvnic_reset_init(adapter, true);
+- if (rc) {
+- rc = IBMVNIC_INIT_FAILED;
++ if (rc)
+ goto out;
+- }
+
+ /* If the adapter was in PROBE or DOWN state prior to the reset,
+ * exit here.
+@@ -3787,7 +3791,7 @@ static int init_sub_crqs(struct ibmvnic_adapter *adapter)
+
+ allqueues = kcalloc(total_queues, sizeof(*allqueues), GFP_KERNEL);
+ if (!allqueues)
+- return -1;
++ return -ENOMEM;
+
+ for (i = 0; i < total_queues; i++) {
+ allqueues[i] = init_sub_crq_queue(adapter);
+@@ -3856,7 +3860,7 @@ static int init_sub_crqs(struct ibmvnic_adapter *adapter)
+ for (i = 0; i < registered_queues; i++)
+ release_sub_crq_queue(adapter, allqueues[i], 1);
+ kfree(allqueues);
+- return -1;
++ return -ENOMEM;
+ }
+
+ static void send_request_cap(struct ibmvnic_adapter *adapter, int retry)
+@@ -4235,7 +4239,7 @@ static int send_login(struct ibmvnic_adapter *adapter)
+ if (!adapter->tx_scrq || !adapter->rx_scrq) {
+ netdev_err(adapter->netdev,
+ "RX or TX queues are not allocated, device login failed\n");
+- return -1;
++ return -ENOMEM;
+ }
+
+ release_login_buffer(adapter);
+@@ -4355,7 +4359,7 @@ static int send_login(struct ibmvnic_adapter *adapter)
+ kfree(login_buffer);
+ adapter->login_buf = NULL;
+ buf_alloc_failed:
+- return -1;
++ return -ENOMEM;
+ }
+
+ static int send_request_map(struct ibmvnic_adapter *adapter, dma_addr_t addr,
+@@ -5693,7 +5697,7 @@ static int ibmvnic_reset_init(struct ibmvnic_adapter *adapter, bool reset)
+
+ if (!wait_for_completion_timeout(&adapter->init_done, timeout)) {
+ dev_err(dev, "Initialization sequence timed out\n");
+- return -1;
++ return -ETIMEDOUT;
+ }
+
+ if (adapter->init_done_rc) {
+@@ -5704,7 +5708,7 @@ static int ibmvnic_reset_init(struct ibmvnic_adapter *adapter, bool reset)
+ if (adapter->from_passive_init) {
+ adapter->state = VNIC_OPEN;
+ adapter->from_passive_init = false;
+- return -1;
++ return -EINVAL;
+ }
+
+ if (reset &&
+--
+2.34.1
+
--- /dev/null
+From 17bba395b5754c254a6fda3a6973b2f35f6e4a46 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 10 Feb 2022 09:47:45 -0600
+Subject: iommu/amd: Fix I/O page table memory leak
+
+From: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
+
+[ Upstream commit 6b0b2d9a6a308bcd9300c2d83000a82812c56cea ]
+
+The current logic updates the I/O page table mode for the domain
+before calling the logic to free memory used for the page table.
+This results in IOMMU page table memory leak, and can be observed
+when launching VM w/ pass-through devices.
+
+Fix by freeing the memory used for page table before updating the mode.
+
+Cc: Joerg Roedel <joro@8bytes.org>
+Reported-by: Daniel Jordan <daniel.m.jordan@oracle.com>
+Tested-by: Daniel Jordan <daniel.m.jordan@oracle.com>
+Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
+Fixes: e42ba0633064 ("iommu/amd: Restructure code for freeing page table")
+Link: https://lore.kernel.org/all/20220118194720.urjgi73b7c3tq2o6@oracle.com/
+Link: https://lore.kernel.org/r/20220210154745.11524-1-suravee.suthikulpanit@amd.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/amd/io_pgtable.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c
+index b1bf4125b0f7..6608d1717574 100644
+--- a/drivers/iommu/amd/io_pgtable.c
++++ b/drivers/iommu/amd/io_pgtable.c
+@@ -492,18 +492,18 @@ static void v1_free_pgtable(struct io_pgtable *iop)
+
+ dom = container_of(pgtable, struct protection_domain, iop);
+
+- /* Update data structure */
+- amd_iommu_domain_clr_pt_root(dom);
+-
+- /* Make changes visible to IOMMUs */
+- amd_iommu_domain_update(dom);
+-
+ /* Page-table is not visible to IOMMU anymore, so free it */
+ BUG_ON(pgtable->mode < PAGE_MODE_NONE ||
+ pgtable->mode > PAGE_MODE_6_LEVEL);
+
+ free_sub_pt(pgtable->root, pgtable->mode, &freelist);
+
++ /* Update data structure */
++ amd_iommu_domain_clr_pt_root(dom);
++
++ /* Make changes visible to IOMMUs */
++ amd_iommu_domain_update(dom);
++
+ put_pages_list(&freelist);
+ }
+
+--
+2.34.1
+
--- /dev/null
+From da8f8eb5547bbcc236d36afd7cd01f49ad5d2c42 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Dec 2021 15:30:58 +0000
+Subject: iommu/amd: Simplify pagetable freeing
+
+From: Robin Murphy <robin.murphy@arm.com>
+
+[ Upstream commit 6b3106e9ba2de7320a71291cedcefdcf1195ad58 ]
+
+For reasons unclear, pagetable freeing is an effectively recursive
+method implemented via an elaborate system of templated functions that
+turns out to account for 25% of the object file size. Implementing it
+using regular straightforward recursion makes the code simpler, and
+seems like a good thing to do before we work on it further. As part of
+that, also fix the types to avoid all the needless casting back and
+forth which just gets in the way.
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/d3d00c9f3fa0df4756b867072c201e6e82f9ce39.1639753638.git.robin.murphy@arm.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/amd/io_pgtable.c | 82 ++++++++++++++--------------------
+ 1 file changed, 34 insertions(+), 48 deletions(-)
+
+diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c
+index 182c93a43efd..4165e1372b6e 100644
+--- a/drivers/iommu/amd/io_pgtable.c
++++ b/drivers/iommu/amd/io_pgtable.c
+@@ -84,49 +84,45 @@ static void free_page_list(struct page *freelist)
+ }
+ }
+
+-static struct page *free_pt_page(unsigned long pt, struct page *freelist)
++static struct page *free_pt_page(u64 *pt, struct page *freelist)
+ {
+- struct page *p = virt_to_page((void *)pt);
++ struct page *p = virt_to_page(pt);
+
+ p->freelist = freelist;
+
+ return p;
+ }
+
+-#define DEFINE_FREE_PT_FN(LVL, FN) \
+-static struct page *free_pt_##LVL (unsigned long __pt, struct page *freelist) \
+-{ \
+- unsigned long p; \
+- u64 *pt; \
+- int i; \
+- \
+- pt = (u64 *)__pt; \
+- \
+- for (i = 0; i < 512; ++i) { \
+- /* PTE present? */ \
+- if (!IOMMU_PTE_PRESENT(pt[i])) \
+- continue; \
+- \
+- /* Large PTE? */ \
+- if (PM_PTE_LEVEL(pt[i]) == 0 || \
+- PM_PTE_LEVEL(pt[i]) == 7) \
+- continue; \
+- \
+- p = (unsigned long)IOMMU_PTE_PAGE(pt[i]); \
+- freelist = FN(p, freelist); \
+- } \
+- \
+- return free_pt_page((unsigned long)pt, freelist); \
+-}
++static struct page *free_pt_lvl(u64 *pt, struct page *freelist, int lvl)
++{
++ u64 *p;
++ int i;
++
++ for (i = 0; i < 512; ++i) {
++ /* PTE present? */
++ if (!IOMMU_PTE_PRESENT(pt[i]))
++ continue;
+
+-DEFINE_FREE_PT_FN(l2, free_pt_page)
+-DEFINE_FREE_PT_FN(l3, free_pt_l2)
+-DEFINE_FREE_PT_FN(l4, free_pt_l3)
+-DEFINE_FREE_PT_FN(l5, free_pt_l4)
+-DEFINE_FREE_PT_FN(l6, free_pt_l5)
++ /* Large PTE? */
++ if (PM_PTE_LEVEL(pt[i]) == 0 ||
++ PM_PTE_LEVEL(pt[i]) == 7)
++ continue;
+
+-static struct page *free_sub_pt(unsigned long root, int mode,
+- struct page *freelist)
++ /*
++ * Free the next level. No need to look at l1 tables here since
++ * they can only contain leaf PTEs; just free them directly.
++ */
++ p = IOMMU_PTE_PAGE(pt[i]);
++ if (lvl > 2)
++ freelist = free_pt_lvl(p, freelist, lvl - 1);
++ else
++ freelist = free_pt_page(p, freelist);
++ }
++
++ return free_pt_page(pt, freelist);
++}
++
++static struct page *free_sub_pt(u64 *root, int mode, struct page *freelist)
+ {
+ switch (mode) {
+ case PAGE_MODE_NONE:
+@@ -136,19 +132,11 @@ static struct page *free_sub_pt(unsigned long root, int mode,
+ freelist = free_pt_page(root, freelist);
+ break;
+ case PAGE_MODE_2_LEVEL:
+- freelist = free_pt_l2(root, freelist);
+- break;
+ case PAGE_MODE_3_LEVEL:
+- freelist = free_pt_l3(root, freelist);
+- break;
+ case PAGE_MODE_4_LEVEL:
+- freelist = free_pt_l4(root, freelist);
+- break;
+ case PAGE_MODE_5_LEVEL:
+- freelist = free_pt_l5(root, freelist);
+- break;
+ case PAGE_MODE_6_LEVEL:
+- freelist = free_pt_l6(root, freelist);
++ free_pt_lvl(root, freelist, mode);
+ break;
+ default:
+ BUG();
+@@ -364,7 +352,7 @@ static u64 *fetch_pte(struct amd_io_pgtable *pgtable,
+
+ static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist)
+ {
+- unsigned long pt;
++ u64 *pt;
+ int mode;
+
+ while (cmpxchg64(pte, pteval, 0) != pteval) {
+@@ -375,7 +363,7 @@ static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist)
+ if (!IOMMU_PTE_PRESENT(pteval))
+ return freelist;
+
+- pt = (unsigned long)IOMMU_PTE_PAGE(pteval);
++ pt = IOMMU_PTE_PAGE(pteval);
+ mode = IOMMU_PTE_MODE(pteval);
+
+ return free_sub_pt(pt, mode, freelist);
+@@ -512,7 +500,6 @@ static void v1_free_pgtable(struct io_pgtable *iop)
+ struct amd_io_pgtable *pgtable = container_of(iop, struct amd_io_pgtable, iop);
+ struct protection_domain *dom;
+ struct page *freelist = NULL;
+- unsigned long root;
+
+ if (pgtable->mode == PAGE_MODE_NONE)
+ return;
+@@ -529,8 +516,7 @@ static void v1_free_pgtable(struct io_pgtable *iop)
+ BUG_ON(pgtable->mode < PAGE_MODE_NONE ||
+ pgtable->mode > PAGE_MODE_6_LEVEL);
+
+- root = (unsigned long)pgtable->root;
+- freelist = free_sub_pt(root, pgtable->mode, freelist);
++ freelist = free_sub_pt(pgtable->root, pgtable->mode, freelist);
+
+ free_page_list(freelist);
+ }
+--
+2.34.1
+
--- /dev/null
+From 42cf2683550e58b3529f00d834e1a700c8962994 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Dec 2021 15:30:59 +0000
+Subject: iommu/amd: Use put_pages_list
+
+From: Matthew Wilcox (Oracle) <willy@infradead.org>
+
+[ Upstream commit ce00eece6909c266da123fd147172d745a4f14a0 ]
+
+page->freelist is for the use of slab. We already have the ability
+to free a list of pages in the core mm, but it requires the use of a
+list_head and for the pages to be chained together through page->lru.
+Switch the AMD IOMMU code over to using free_pages_list().
+
+Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
+[rm: split from original patch, cosmetic tweaks]
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/73af128f651aaa1f38f69e586c66765a88ad2de0.1639753638.git.robin.murphy@arm.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/amd/io_pgtable.c | 50 ++++++++++++----------------------
+ 1 file changed, 18 insertions(+), 32 deletions(-)
+
+diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c
+index 4165e1372b6e..b1bf4125b0f7 100644
+--- a/drivers/iommu/amd/io_pgtable.c
++++ b/drivers/iommu/amd/io_pgtable.c
+@@ -74,26 +74,14 @@ static u64 *first_pte_l7(u64 *pte, unsigned long *page_size,
+ *
+ ****************************************************************************/
+
+-static void free_page_list(struct page *freelist)
+-{
+- while (freelist != NULL) {
+- unsigned long p = (unsigned long)page_address(freelist);
+-
+- freelist = freelist->freelist;
+- free_page(p);
+- }
+-}
+-
+-static struct page *free_pt_page(u64 *pt, struct page *freelist)
++static void free_pt_page(u64 *pt, struct list_head *freelist)
+ {
+ struct page *p = virt_to_page(pt);
+
+- p->freelist = freelist;
+-
+- return p;
++ list_add_tail(&p->lru, freelist);
+ }
+
+-static struct page *free_pt_lvl(u64 *pt, struct page *freelist, int lvl)
++static void free_pt_lvl(u64 *pt, struct list_head *freelist, int lvl)
+ {
+ u64 *p;
+ int i;
+@@ -114,22 +102,22 @@ static struct page *free_pt_lvl(u64 *pt, struct page *freelist, int lvl)
+ */
+ p = IOMMU_PTE_PAGE(pt[i]);
+ if (lvl > 2)
+- freelist = free_pt_lvl(p, freelist, lvl - 1);
++ free_pt_lvl(p, freelist, lvl - 1);
+ else
+- freelist = free_pt_page(p, freelist);
++ free_pt_page(p, freelist);
+ }
+
+- return free_pt_page(pt, freelist);
++ free_pt_page(pt, freelist);
+ }
+
+-static struct page *free_sub_pt(u64 *root, int mode, struct page *freelist)
++static void free_sub_pt(u64 *root, int mode, struct list_head *freelist)
+ {
+ switch (mode) {
+ case PAGE_MODE_NONE:
+ case PAGE_MODE_7_LEVEL:
+ break;
+ case PAGE_MODE_1_LEVEL:
+- freelist = free_pt_page(root, freelist);
++ free_pt_page(root, freelist);
+ break;
+ case PAGE_MODE_2_LEVEL:
+ case PAGE_MODE_3_LEVEL:
+@@ -141,8 +129,6 @@ static struct page *free_sub_pt(u64 *root, int mode, struct page *freelist)
+ default:
+ BUG();
+ }
+-
+- return freelist;
+ }
+
+ void amd_iommu_domain_set_pgtable(struct protection_domain *domain,
+@@ -350,7 +336,7 @@ static u64 *fetch_pte(struct amd_io_pgtable *pgtable,
+ return pte;
+ }
+
+-static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist)
++static void free_clear_pte(u64 *pte, u64 pteval, struct list_head *freelist)
+ {
+ u64 *pt;
+ int mode;
+@@ -361,12 +347,12 @@ static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist)
+ }
+
+ if (!IOMMU_PTE_PRESENT(pteval))
+- return freelist;
++ return;
+
+ pt = IOMMU_PTE_PAGE(pteval);
+ mode = IOMMU_PTE_MODE(pteval);
+
+- return free_sub_pt(pt, mode, freelist);
++ free_sub_pt(pt, mode, freelist);
+ }
+
+ /*
+@@ -380,7 +366,7 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova,
+ phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
+ {
+ struct protection_domain *dom = io_pgtable_ops_to_domain(ops);
+- struct page *freelist = NULL;
++ LIST_HEAD(freelist);
+ bool updated = false;
+ u64 __pte, *pte;
+ int ret, i, count;
+@@ -400,9 +386,9 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova,
+ goto out;
+
+ for (i = 0; i < count; ++i)
+- freelist = free_clear_pte(&pte[i], pte[i], freelist);
++ free_clear_pte(&pte[i], pte[i], &freelist);
+
+- if (freelist != NULL)
++ if (!list_empty(&freelist))
+ updated = true;
+
+ if (count > 1) {
+@@ -437,7 +423,7 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova,
+ }
+
+ /* Everything flushed out, free pages now */
+- free_page_list(freelist);
++ put_pages_list(&freelist);
+
+ return ret;
+ }
+@@ -499,7 +485,7 @@ static void v1_free_pgtable(struct io_pgtable *iop)
+ {
+ struct amd_io_pgtable *pgtable = container_of(iop, struct amd_io_pgtable, iop);
+ struct protection_domain *dom;
+- struct page *freelist = NULL;
++ LIST_HEAD(freelist);
+
+ if (pgtable->mode == PAGE_MODE_NONE)
+ return;
+@@ -516,9 +502,9 @@ static void v1_free_pgtable(struct io_pgtable *iop)
+ BUG_ON(pgtable->mode < PAGE_MODE_NONE ||
+ pgtable->mode > PAGE_MODE_6_LEVEL);
+
+- freelist = free_sub_pt(pgtable->root, pgtable->mode, freelist);
++ free_sub_pt(pgtable->root, pgtable->mode, &freelist);
+
+- free_page_list(freelist);
++ put_pages_list(&freelist);
+ }
+
+ static struct io_pgtable *v1_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
+--
+2.34.1
+
--- /dev/null
+From 916192e06e8e114c5173b101cf321101d81fa8a9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Feb 2022 08:13:44 +0800
+Subject: MIPS: ralink: mt7621: do memory detection on KSEG1
+
+From: Chuanhong Guo <gch981213@gmail.com>
+
+[ Upstream commit cc19db8b312a6c75645645f5cc1b45166b109006 ]
+
+It's reported that current memory detection code occasionally detects
+larger memory under some bootloaders.
+Current memory detection code tests whether address space wraps around
+on KSEG0, which is unreliable because it's cached.
+
+Rewrite memory size detection to perform the same test on KSEG1 instead.
+While at it, this patch also does the following two things:
+1. use a fixed pattern instead of a random function pointer as the magic
+ value.
+2. add an additional memory write and a second comparison as part of the
+ test to prevent possible smaller memory detection result due to
+ leftover values in memory.
+
+Fixes: 139c949f7f0a MIPS: ("ralink: mt7621: add memory detection support")
+Reported-by: Rui Salvaterra <rsalvaterra@gmail.com>
+Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
+Tested-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
+Tested-by: Rui Salvaterra <rsalvaterra@gmail.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/ralink/mt7621.c | 36 +++++++++++++++++++++++-------------
+ 1 file changed, 23 insertions(+), 13 deletions(-)
+
+diff --git a/arch/mips/ralink/mt7621.c b/arch/mips/ralink/mt7621.c
+index bd71f5b14238..fd9a872d5713 100644
+--- a/arch/mips/ralink/mt7621.c
++++ b/arch/mips/ralink/mt7621.c
+@@ -20,31 +20,41 @@
+
+ #include "common.h"
+
+-static void *detect_magic __initdata = detect_memory_region;
++#define MT7621_MEM_TEST_PATTERN 0xaa5555aa
++
++static u32 detect_magic __initdata;
+
+ phys_addr_t mips_cpc_default_phys_base(void)
+ {
+ panic("Cannot detect cpc address");
+ }
+
++static bool __init mt7621_addr_wraparound_test(phys_addr_t size)
++{
++ void *dm = (void *)KSEG1ADDR(&detect_magic);
++
++ if (CPHYSADDR(dm + size) >= MT7621_LOWMEM_MAX_SIZE)
++ return true;
++ __raw_writel(MT7621_MEM_TEST_PATTERN, dm);
++ if (__raw_readl(dm) != __raw_readl(dm + size))
++ return false;
++ __raw_writel(!MT7621_MEM_TEST_PATTERN, dm);
++ return __raw_readl(dm) == __raw_readl(dm + size);
++}
++
+ static void __init mt7621_memory_detect(void)
+ {
+- void *dm = &detect_magic;
+ phys_addr_t size;
+
+- for (size = 32 * SZ_1M; size < 256 * SZ_1M; size <<= 1) {
+- if (!__builtin_memcmp(dm, dm + size, sizeof(detect_magic)))
+- break;
++ for (size = 32 * SZ_1M; size <= 256 * SZ_1M; size <<= 1) {
++ if (mt7621_addr_wraparound_test(size)) {
++ memblock_add(MT7621_LOWMEM_BASE, size);
++ return;
++ }
+ }
+
+- if ((size == 256 * SZ_1M) &&
+- (CPHYSADDR(dm + size) < MT7621_LOWMEM_MAX_SIZE) &&
+- __builtin_memcmp(dm, dm + size, sizeof(detect_magic))) {
+- memblock_add(MT7621_LOWMEM_BASE, MT7621_LOWMEM_MAX_SIZE);
+- memblock_add(MT7621_HIGHMEM_BASE, MT7621_HIGHMEM_SIZE);
+- } else {
+- memblock_add(MT7621_LOWMEM_BASE, size);
+- }
++ memblock_add(MT7621_LOWMEM_BASE, MT7621_LOWMEM_MAX_SIZE);
++ memblock_add(MT7621_HIGHMEM_BASE, MT7621_HIGHMEM_SIZE);
+ }
+
+ void __init ralink_of_remap(void)
+--
+2.34.1
+
--- /dev/null
+From 9d933ab70e2c0d56f1d4ccf3317453642c8cc784 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Feb 2022 17:15:07 -0800
+Subject: MIPS: ralink: mt7621: use bitwise NOT instead of logical
+
+From: Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
+
+[ Upstream commit 5d8965704fe5662e2e4a7e4424a2cbe53e182670 ]
+
+It was the intention to reverse the bits, not make them all zero by
+using logical NOT operator.
+
+Fixes: cc19db8b312a ("MIPS: ralink: mt7621: do memory detection on KSEG1")
+Suggested-by: Chuanhong Guo <gch981213@gmail.com>
+Signed-off-by: Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
+Reviewed-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/ralink/mt7621.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/mips/ralink/mt7621.c b/arch/mips/ralink/mt7621.c
+index fd9a872d5713..4c8378661219 100644
+--- a/arch/mips/ralink/mt7621.c
++++ b/arch/mips/ralink/mt7621.c
+@@ -38,7 +38,7 @@ static bool __init mt7621_addr_wraparound_test(phys_addr_t size)
+ __raw_writel(MT7621_MEM_TEST_PATTERN, dm);
+ if (__raw_readl(dm) != __raw_readl(dm + size))
+ return false;
+- __raw_writel(!MT7621_MEM_TEST_PATTERN, dm);
++ __raw_writel(~MT7621_MEM_TEST_PATTERN, dm);
+ return __raw_readl(dm) == __raw_readl(dm + size);
+ }
+
+--
+2.34.1
+
--- /dev/null
+From 2f521aadaaaca07cd1143861d0ae29b3efaa0144 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Feb 2022 04:37:27 -0800
+Subject: net: chelsio: cxgb3: check the return value of pci_find_capability()
+
+From: Jia-Ju Bai <baijiaju1990@gmail.com>
+
+[ Upstream commit 767b9825ed1765894e569a3d698749d40d83762a ]
+
+The function pci_find_capability() in t3_prep_adapter() can fail, so its
+return value should be checked.
+
+Fixes: 4d22de3e6cc4 ("Add support for the latest 1G/10G Chelsio adapter, T3")
+Reported-by: TOTE Robot <oslab@tsinghua.edu.cn>
+Signed-off-by: Jia-Ju Bai <baijiaju1990@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/chelsio/cxgb3/t3_hw.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
+index da41eee2f25c..a06003bfa04b 100644
+--- a/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
++++ b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
+@@ -3613,6 +3613,8 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
+ MAC_STATS_ACCUM_SECS : (MAC_STATS_ACCUM_SECS * 10);
+ adapter->params.pci.vpd_cap_addr =
+ pci_find_capability(adapter->pdev, PCI_CAP_ID_VPD);
++ if (!adapter->params.pci.vpd_cap_addr)
++ return -ENODEV;
+ ret = get_vpd_params(adapter, &adapter->params.vpd);
+ if (ret < 0)
+ return ret;
+--
+2.34.1
+
--- /dev/null
+From c18d886459e3b77da5a853535c93ab7500f58124 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Mar 2022 21:39:39 +0200
+Subject: net: dcb: disable softirqs in dcbnl_flush_dev()
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit 10b6bb62ae1a49ee818fc479cf57b8900176773e ]
+
+Ido Schimmel points out that since commit 52cff74eef5d ("dcbnl : Disable
+software interrupts before taking dcb_lock"), the DCB API can be called
+by drivers from softirq context.
+
+One such in-tree example is the chelsio cxgb4 driver:
+dcb_rpl
+-> cxgb4_dcb_handle_fw_update
+ -> dcb_ieee_setapp
+
+If the firmware for this driver happened to send an event which resulted
+in a call to dcb_ieee_setapp() at the exact same time as another
+DCB-enabled interface was unregistering on the same CPU, the softirq
+would deadlock, because the interrupted process was already holding the
+dcb_lock in dcbnl_flush_dev().
+
+Fix this unlikely event by using spin_lock_bh() in dcbnl_flush_dev() as
+in the rest of the dcbnl code.
+
+Fixes: 91b0383fef06 ("net: dcb: flush lingering app table entries for unregistered devices")
+Reported-by: Ido Schimmel <idosch@idosch.org>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Link: https://lore.kernel.org/r/20220302193939.1368823-1-vladimir.oltean@nxp.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/dcb/dcbnl.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
+index 36c91273daac..dc4fb699b56c 100644
+--- a/net/dcb/dcbnl.c
++++ b/net/dcb/dcbnl.c
+@@ -2077,7 +2077,7 @@ static void dcbnl_flush_dev(struct net_device *dev)
+ {
+ struct dcb_app_type *itr, *tmp;
+
+- spin_lock(&dcb_lock);
++ spin_lock_bh(&dcb_lock);
+
+ list_for_each_entry_safe(itr, tmp, &dcb_app_list, list) {
+ if (itr->ifindex == dev->ifindex) {
+@@ -2086,7 +2086,7 @@ static void dcbnl_flush_dev(struct net_device *dev)
+ }
+ }
+
+- spin_unlock(&dcb_lock);
++ spin_unlock_bh(&dcb_lock);
+ }
+
+ static int dcbnl_netdevice_event(struct notifier_block *nb,
+--
+2.34.1
+
--- /dev/null
+From 114e9646f14fb5067363c0a83daf8314e103ee84 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Feb 2022 11:15:16 +0100
+Subject: net: sparx5: Fix add vlan when invalid operation
+
+From: Casper Andersson <casper.casan@gmail.com>
+
+[ Upstream commit b3a34dc362c03215031b268fcc0b988e69490231 ]
+
+Check if operation is valid before changing any
+settings in hardware. Otherwise it results in
+changes being made despite it not being a valid
+operation.
+
+Fixes: 78eab33bb68b ("net: sparx5: add vlan support")
+
+Signed-off-by: Casper Andersson <casper.casan@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/microchip/sparx5/sparx5_vlan.c | 20 +++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c b/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c
+index 4ce490a25f33..8e56ffa1c4f7 100644
+--- a/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c
++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c
+@@ -58,16 +58,6 @@ int sparx5_vlan_vid_add(struct sparx5_port *port, u16 vid, bool pvid,
+ struct sparx5 *sparx5 = port->sparx5;
+ int ret;
+
+- /* Make the port a member of the VLAN */
+- set_bit(port->portno, sparx5->vlan_mask[vid]);
+- ret = sparx5_vlant_set_mask(sparx5, vid);
+- if (ret)
+- return ret;
+-
+- /* Default ingress vlan classification */
+- if (pvid)
+- port->pvid = vid;
+-
+ /* Untagged egress vlan classification */
+ if (untagged && port->vid != vid) {
+ if (port->vid) {
+@@ -79,6 +69,16 @@ int sparx5_vlan_vid_add(struct sparx5_port *port, u16 vid, bool pvid,
+ port->vid = vid;
+ }
+
++ /* Make the port a member of the VLAN */
++ set_bit(port->portno, sparx5->vlan_mask[vid]);
++ ret = sparx5_vlant_set_mask(sparx5, vid);
++ if (ret)
++ return ret;
++
++ /* Default ingress vlan classification */
++ if (pvid)
++ port->pvid = vid;
++
+ sparx5_vlan_port_apply(sparx5, port);
+
+ return 0;
+--
+2.34.1
+
--- /dev/null
+From 721322b751f39f2843d35dec7a80001d5cc446b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 11 Nov 2021 22:39:49 +0800
+Subject: net: stmmac: enhance XDP ZC driver level switching performance
+
+From: Ong Boon Leong <boon.leong.ong@intel.com>
+
+[ Upstream commit ac746c8520d9d056b6963ecca8ff1da9929d02f1 ]
+
+The previous stmmac_xdp_set_prog() implementation uses stmmac_release()
+and stmmac_open() which tear down the PHY device and causes undesirable
+autonegotiation which causes a delay whenever AFXDP ZC is setup.
+
+This patch introduces two new functions that just sufficiently tear
+down DMA descriptors, buffer, NAPI process, and IRQs and reestablish
+them accordingly in both stmmac_xdp_release() and stammac_xdp_open().
+
+As the results of this enhancement, we get rid of transient state
+introduced by the link auto-negotiation:
+
+$ ./xdpsock -i eth0 -t -z
+
+ sock0@eth0:0 txonly xdp-drv
+ pps pkts 1.00
+rx 0 0
+tx 634444 634560
+
+ sock0@eth0:0 txonly xdp-drv
+ pps pkts 1.00
+rx 0 0
+tx 632330 1267072
+
+ sock0@eth0:0 txonly xdp-drv
+ pps pkts 1.00
+rx 0 0
+tx 632438 1899584
+
+ sock0@eth0:0 txonly xdp-drv
+ pps pkts 1.00
+rx 0 0
+tx 632502 2532160
+
+Reported-by: Kurt Kanzenbach <kurt@linutronix.de>
+Signed-off-by: Ong Boon Leong <boon.leong.ong@intel.com>
+Tested-by: Kurt Kanzenbach <kurt@linutronix.de>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 4 +-
+ .../net/ethernet/stmicro/stmmac/stmmac_main.c | 137 +++++++++++++++++-
+ .../net/ethernet/stmicro/stmmac/stmmac_xdp.c | 4 +-
+ 3 files changed, 139 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+index 873b9e3e5da2..05b5371ca036 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+@@ -334,8 +334,8 @@ void stmmac_set_ethtool_ops(struct net_device *netdev);
+ int stmmac_init_tstamp_counter(struct stmmac_priv *priv, u32 systime_flags);
+ void stmmac_ptp_register(struct stmmac_priv *priv);
+ void stmmac_ptp_unregister(struct stmmac_priv *priv);
+-int stmmac_open(struct net_device *dev);
+-int stmmac_release(struct net_device *dev);
++int stmmac_xdp_open(struct net_device *dev);
++void stmmac_xdp_release(struct net_device *dev);
+ int stmmac_resume(struct device *dev);
+ int stmmac_suspend(struct device *dev);
+ int stmmac_dvr_remove(struct device *dev);
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 240dffe20fc3..2b3752bd1ac9 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -3679,7 +3679,7 @@ static int stmmac_request_irq(struct net_device *dev)
+ * 0 on success and an appropriate (-)ve integer as defined in errno.h
+ * file on failure.
+ */
+-int stmmac_open(struct net_device *dev)
++static int stmmac_open(struct net_device *dev)
+ {
+ struct stmmac_priv *priv = netdev_priv(dev);
+ int mode = priv->plat->phy_interface;
+@@ -3803,7 +3803,7 @@ static void stmmac_fpe_stop_wq(struct stmmac_priv *priv)
+ * Description:
+ * This is the stop entry point of the driver.
+ */
+-int stmmac_release(struct net_device *dev)
++static int stmmac_release(struct net_device *dev)
+ {
+ struct stmmac_priv *priv = netdev_priv(dev);
+ u32 chan;
+@@ -6473,6 +6473,139 @@ void stmmac_enable_tx_queue(struct stmmac_priv *priv, u32 queue)
+ spin_unlock_irqrestore(&ch->lock, flags);
+ }
+
++void stmmac_xdp_release(struct net_device *dev)
++{
++ struct stmmac_priv *priv = netdev_priv(dev);
++ u32 chan;
++
++ /* Disable NAPI process */
++ stmmac_disable_all_queues(priv);
++
++ for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
++ hrtimer_cancel(&priv->tx_queue[chan].txtimer);
++
++ /* Free the IRQ lines */
++ stmmac_free_irq(dev, REQ_IRQ_ERR_ALL, 0);
++
++ /* Stop TX/RX DMA channels */
++ stmmac_stop_all_dma(priv);
++
++ /* Release and free the Rx/Tx resources */
++ free_dma_desc_resources(priv);
++
++ /* Disable the MAC Rx/Tx */
++ stmmac_mac_set(priv, priv->ioaddr, false);
++
++ /* set trans_start so we don't get spurious
++ * watchdogs during reset
++ */
++ netif_trans_update(dev);
++ netif_carrier_off(dev);
++}
++
++int stmmac_xdp_open(struct net_device *dev)
++{
++ struct stmmac_priv *priv = netdev_priv(dev);
++ u32 rx_cnt = priv->plat->rx_queues_to_use;
++ u32 tx_cnt = priv->plat->tx_queues_to_use;
++ u32 dma_csr_ch = max(rx_cnt, tx_cnt);
++ struct stmmac_rx_queue *rx_q;
++ struct stmmac_tx_queue *tx_q;
++ u32 buf_size;
++ bool sph_en;
++ u32 chan;
++ int ret;
++
++ ret = alloc_dma_desc_resources(priv);
++ if (ret < 0) {
++ netdev_err(dev, "%s: DMA descriptors allocation failed\n",
++ __func__);
++ goto dma_desc_error;
++ }
++
++ ret = init_dma_desc_rings(dev, GFP_KERNEL);
++ if (ret < 0) {
++ netdev_err(dev, "%s: DMA descriptors initialization failed\n",
++ __func__);
++ goto init_error;
++ }
++
++ /* DMA CSR Channel configuration */
++ for (chan = 0; chan < dma_csr_ch; chan++)
++ stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
++
++ /* Adjust Split header */
++ sph_en = (priv->hw->rx_csum > 0) && priv->sph;
++
++ /* DMA RX Channel Configuration */
++ for (chan = 0; chan < rx_cnt; chan++) {
++ rx_q = &priv->rx_queue[chan];
++
++ stmmac_init_rx_chan(priv, priv->ioaddr, priv->plat->dma_cfg,
++ rx_q->dma_rx_phy, chan);
++
++ rx_q->rx_tail_addr = rx_q->dma_rx_phy +
++ (rx_q->buf_alloc_num *
++ sizeof(struct dma_desc));
++ stmmac_set_rx_tail_ptr(priv, priv->ioaddr,
++ rx_q->rx_tail_addr, chan);
++
++ if (rx_q->xsk_pool && rx_q->buf_alloc_num) {
++ buf_size = xsk_pool_get_rx_frame_size(rx_q->xsk_pool);
++ stmmac_set_dma_bfsize(priv, priv->ioaddr,
++ buf_size,
++ rx_q->queue_index);
++ } else {
++ stmmac_set_dma_bfsize(priv, priv->ioaddr,
++ priv->dma_buf_sz,
++ rx_q->queue_index);
++ }
++
++ stmmac_enable_sph(priv, priv->ioaddr, sph_en, chan);
++ }
++
++ /* DMA TX Channel Configuration */
++ for (chan = 0; chan < tx_cnt; chan++) {
++ tx_q = &priv->tx_queue[chan];
++
++ stmmac_init_tx_chan(priv, priv->ioaddr, priv->plat->dma_cfg,
++ tx_q->dma_tx_phy, chan);
++
++ tx_q->tx_tail_addr = tx_q->dma_tx_phy;
++ stmmac_set_tx_tail_ptr(priv, priv->ioaddr,
++ tx_q->tx_tail_addr, chan);
++ }
++
++ /* Enable the MAC Rx/Tx */
++ stmmac_mac_set(priv, priv->ioaddr, true);
++
++ /* Start Rx & Tx DMA Channels */
++ stmmac_start_all_dma(priv);
++
++ stmmac_init_coalesce(priv);
++
++ ret = stmmac_request_irq(dev);
++ if (ret)
++ goto irq_error;
++
++ /* Enable NAPI process*/
++ stmmac_enable_all_queues(priv);
++ netif_carrier_on(dev);
++ netif_tx_start_all_queues(dev);
++
++ return 0;
++
++irq_error:
++ for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
++ hrtimer_cancel(&priv->tx_queue[chan].txtimer);
++
++ stmmac_hw_teardown(dev);
++init_error:
++ free_dma_desc_resources(priv);
++dma_desc_error:
++ return ret;
++}
++
+ int stmmac_xsk_wakeup(struct net_device *dev, u32 queue, u32 flags)
+ {
+ struct stmmac_priv *priv = netdev_priv(dev);
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c
+index 2a616c6f7cd0..9d4d8c3dad0a 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c
+@@ -119,7 +119,7 @@ int stmmac_xdp_set_prog(struct stmmac_priv *priv, struct bpf_prog *prog,
+
+ need_update = !!priv->xdp_prog != !!prog;
+ if (if_running && need_update)
+- stmmac_release(dev);
++ stmmac_xdp_release(dev);
+
+ old_prog = xchg(&priv->xdp_prog, prog);
+ if (old_prog)
+@@ -129,7 +129,7 @@ int stmmac_xdp_set_prog(struct stmmac_priv *priv, struct bpf_prog *prog,
+ priv->sph = priv->sph_cap && !stmmac_xdp_is_enabled(priv);
+
+ if (if_running && need_update)
+- stmmac_open(dev);
++ stmmac_xdp_open(dev);
+
+ return 0;
+ }
+--
+2.34.1
+
--- /dev/null
+From d18a70db2c7ba7da108f9c33b9b11d7cbb195bd2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Feb 2022 12:38:29 +0100
+Subject: net: stmmac: only enable DMA interrupts when ready
+
+From: Vincent Whitchurch <vincent.whitchurch@axis.com>
+
+[ Upstream commit 087a7b944c5db409f7c1a68bf4896c56ba54eaff ]
+
+In this driver's ->ndo_open() callback, it enables DMA interrupts,
+starts the DMA channels, then requests interrupts with request_irq(),
+and then finally enables napi.
+
+If RX DMA interrupts are received before napi is enabled, no processing
+is done because napi_schedule_prep() will return false. If the network
+has a lot of broadcast/multicast traffic, then the RX ring could fill up
+completely before napi is enabled. When this happens, no further RX
+interrupts will be delivered, and the driver will fail to receive any
+packets.
+
+Fix this by only enabling DMA interrupts after all other initialization
+is complete.
+
+Fixes: 523f11b5d4fd72efb ("net: stmmac: move hardware setup for stmmac_open to new function")
+Reported-by: Lars Persson <larper@axis.com>
+Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/stmicro/stmmac/stmmac_main.c | 28 +++++++++++++++++--
+ 1 file changed, 26 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 2b3752bd1ac9..8610e4d28e85 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -2272,6 +2272,23 @@ static void stmmac_stop_tx_dma(struct stmmac_priv *priv, u32 chan)
+ stmmac_stop_tx(priv, priv->ioaddr, chan);
+ }
+
++static void stmmac_enable_all_dma_irq(struct stmmac_priv *priv)
++{
++ u32 rx_channels_count = priv->plat->rx_queues_to_use;
++ u32 tx_channels_count = priv->plat->tx_queues_to_use;
++ u32 dma_csr_ch = max(rx_channels_count, tx_channels_count);
++ u32 chan;
++
++ for (chan = 0; chan < dma_csr_ch; chan++) {
++ struct stmmac_channel *ch = &priv->channel[chan];
++ unsigned long flags;
++
++ spin_lock_irqsave(&ch->lock, flags);
++ stmmac_enable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
++ spin_unlock_irqrestore(&ch->lock, flags);
++ }
++}
++
+ /**
+ * stmmac_start_all_dma - start all RX and TX DMA channels
+ * @priv: driver private structure
+@@ -2911,8 +2928,10 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
+ stmmac_axi(priv, priv->ioaddr, priv->plat->axi);
+
+ /* DMA CSR Channel configuration */
+- for (chan = 0; chan < dma_csr_ch; chan++)
++ for (chan = 0; chan < dma_csr_ch; chan++) {
+ stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
++ stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
++ }
+
+ /* DMA RX Channel Configuration */
+ for (chan = 0; chan < rx_channels_count; chan++) {
+@@ -3768,6 +3787,7 @@ static int stmmac_open(struct net_device *dev)
+
+ stmmac_enable_all_queues(priv);
+ netif_tx_start_all_queues(priv->dev);
++ stmmac_enable_all_dma_irq(priv);
+
+ return 0;
+
+@@ -6531,8 +6551,10 @@ int stmmac_xdp_open(struct net_device *dev)
+ }
+
+ /* DMA CSR Channel configuration */
+- for (chan = 0; chan < dma_csr_ch; chan++)
++ for (chan = 0; chan < dma_csr_ch; chan++) {
+ stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
++ stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
++ }
+
+ /* Adjust Split header */
+ sph_en = (priv->hw->rx_csum > 0) && priv->sph;
+@@ -6592,6 +6614,7 @@ int stmmac_xdp_open(struct net_device *dev)
+ stmmac_enable_all_queues(priv);
+ netif_carrier_on(dev);
+ netif_tx_start_all_queues(dev);
++ stmmac_enable_all_dma_irq(priv);
+
+ return 0;
+
+@@ -7470,6 +7493,7 @@ int stmmac_resume(struct device *dev)
+ stmmac_restore_hw_vlan_rx_fltr(priv, ndev, priv->hw);
+
+ stmmac_enable_all_queues(priv);
++ stmmac_enable_all_dma_irq(priv);
+
+ mutex_unlock(&priv->lock);
+ rtnl_unlock();
+--
+2.34.1
+
--- /dev/null
+From 733f87d56b9a367d15a7d964b23dbe840d01c1c7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Feb 2022 10:13:31 -0800
+Subject: netfilter: nf_tables: prefer kfree_rcu(ptr, rcu) variant
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit ae089831ff28a115908b8d796f667c2dadef1637 ]
+
+While kfree_rcu(ptr) _is_ supported, it has some limitations.
+
+Given that 99.99% of kfree_rcu() users [1] use the legacy
+two parameters variant, and @catchall objects do have an rcu head,
+simply use it.
+
+Choice of kfree_rcu(ptr) variant was probably not intentional.
+
+[1] including calls from net/netfilter/nf_tables_api.c
+
+Fixes: aaa31047a6d2 ("netfilter: nftables: add catch-all set element support")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_tables_api.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index a65b530975f5..2b2e0210a7f9 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -4486,7 +4486,7 @@ static void nft_set_catchall_destroy(const struct nft_ctx *ctx,
+ list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
+ list_del_rcu(&catchall->list);
+ nft_set_elem_destroy(set, catchall->elem, true);
+- kfree_rcu(catchall);
++ kfree_rcu(catchall, rcu);
+ }
+ }
+
+@@ -5653,7 +5653,7 @@ static void nft_setelem_catchall_remove(const struct net *net,
+ list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
+ if (catchall->elem == elem->priv) {
+ list_del_rcu(&catchall->list);
+- kfree_rcu(catchall);
++ kfree_rcu(catchall, rcu);
+ break;
+ }
+ }
+--
+2.34.1
+
--- /dev/null
+From 44331e751c3907fe89f2c201f5ea59a56acd9f3f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Mar 2022 18:00:20 +0800
+Subject: nl80211: Handle nla_memdup failures in handle_nan_filter
+
+From: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+
+[ Upstream commit 6ad27f522cb3b210476daf63ce6ddb6568c0508b ]
+
+As there's potential for failure of the nla_memdup(),
+check the return value.
+
+Fixes: a442b761b24b ("cfg80211: add add_nan_func / del_nan_func")
+Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+Link: https://lore.kernel.org/r/20220301100020.3801187-1-jiasheng@iscas.ac.cn
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/wireless/nl80211.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index a27b3b5fa210..f73251828782 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -13379,6 +13379,9 @@ static int handle_nan_filter(struct nlattr *attr_filter,
+ i = 0;
+ nla_for_each_nested(attr, attr_filter, rem) {
+ filter[i].filter = nla_memdup(attr, GFP_KERNEL);
++ if (!filter[i].filter)
++ goto err;
++
+ filter[i].len = nla_len(attr);
+ i++;
+ }
+@@ -13391,6 +13394,15 @@ static int handle_nan_filter(struct nlattr *attr_filter,
+ }
+
+ return 0;
++
++err:
++ i = 0;
++ nla_for_each_nested(attr, attr_filter, rem) {
++ kfree(filter[i].filter);
++ i++;
++ }
++ kfree(filter);
++ return -ENOMEM;
+ }
+
+ static int nl80211_nan_add_func(struct sk_buff *skb,
+--
+2.34.1
+
--- /dev/null
+From ff38defe5e96242ec919416054973ec803a864dd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Feb 2022 12:39:57 -0800
+Subject: ptp: ocp: Add ptp_ocp_adjtime_coarse for large adjustments
+
+From: Jonathan Lemon <jonathan.lemon@gmail.com>
+
+[ Upstream commit 90f8f4c0e3cebd541deaa45cf0e470bb9810dd4f ]
+
+In ("ptp: ocp: Have FPGA fold in ns adjustment for adjtime."), the
+ns adjustment was written to the FPGA register, so the clock could
+accurately perform adjustments.
+
+However, the adjtime() call passes in a s64, while the clock adjustment
+registers use a s32. When trying to perform adjustments with a large
+value (37 sec), things fail.
+
+Examine the incoming delta, and if larger than 1 sec, use the original
+(coarse) adjustment method. If smaller than 1 sec, then allow the
+FPGA to fold in the changes over a 1 second window.
+
+Fixes: 6d59d4fa1789 ("ptp: ocp: Have FPGA fold in ns adjustment for adjtime.")
+Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
+Acked-by: Richard Cochran <richardcochran@gmail.com>
+Link: https://lore.kernel.org/r/20220228203957.367371-1-jonathan.lemon@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ptp/ptp_ocp.c | 25 +++++++++++++++++++++++--
+ 1 file changed, 23 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
+index 0f1b5a7d2a89..17ad5f0d13b2 100644
+--- a/drivers/ptp/ptp_ocp.c
++++ b/drivers/ptp/ptp_ocp.c
+@@ -607,7 +607,7 @@ ptp_ocp_settime(struct ptp_clock_info *ptp_info, const struct timespec64 *ts)
+ }
+
+ static void
+-__ptp_ocp_adjtime_locked(struct ptp_ocp *bp, u64 adj_val)
++__ptp_ocp_adjtime_locked(struct ptp_ocp *bp, u32 adj_val)
+ {
+ u32 select, ctrl;
+
+@@ -615,7 +615,7 @@ __ptp_ocp_adjtime_locked(struct ptp_ocp *bp, u64 adj_val)
+ iowrite32(OCP_SELECT_CLK_REG, &bp->reg->select);
+
+ iowrite32(adj_val, &bp->reg->offset_ns);
+- iowrite32(adj_val & 0x7f, &bp->reg->offset_window_ns);
++ iowrite32(NSEC_PER_SEC, &bp->reg->offset_window_ns);
+
+ ctrl = OCP_CTRL_ADJUST_OFFSET | OCP_CTRL_ENABLE;
+ iowrite32(ctrl, &bp->reg->ctrl);
+@@ -624,6 +624,22 @@ __ptp_ocp_adjtime_locked(struct ptp_ocp *bp, u64 adj_val)
+ iowrite32(select >> 16, &bp->reg->select);
+ }
+
++static void
++ptp_ocp_adjtime_coarse(struct ptp_ocp *bp, u64 delta_ns)
++{
++ struct timespec64 ts;
++ unsigned long flags;
++ int err;
++
++ spin_lock_irqsave(&bp->lock, flags);
++ err = __ptp_ocp_gettime_locked(bp, &ts, NULL);
++ if (likely(!err)) {
++ timespec64_add_ns(&ts, delta_ns);
++ __ptp_ocp_settime_locked(bp, &ts);
++ }
++ spin_unlock_irqrestore(&bp->lock, flags);
++}
++
+ static int
+ ptp_ocp_adjtime(struct ptp_clock_info *ptp_info, s64 delta_ns)
+ {
+@@ -631,6 +647,11 @@ ptp_ocp_adjtime(struct ptp_clock_info *ptp_info, s64 delta_ns)
+ unsigned long flags;
+ u32 adj_ns, sign;
+
++ if (delta_ns > NSEC_PER_SEC || -delta_ns > NSEC_PER_SEC) {
++ ptp_ocp_adjtime_coarse(bp, delta_ns);
++ return 0;
++ }
++
+ sign = delta_ns < 0 ? BIT(31) : 0;
+ adj_ns = sign ? -delta_ns : delta_ns;
+
+--
+2.34.1
+
--- /dev/null
+From 5457c795f1823dbffe1a4a9321a33d6761b4b4b7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Mar 2022 18:14:47 +0200
+Subject: selftests: mlxsw: resource_scale: Fix return value
+
+From: Amit Cohen <amcohen@nvidia.com>
+
+[ Upstream commit 196f9bc050cbc5085b4cbb61cce2efe380bc66d0 ]
+
+The test runs several test cases and is supposed to return an error in
+case at least one of them failed.
+
+Currently, the check of the return value of each test case is in the
+wrong place, which can result in the wrong return value. For example:
+
+ # TESTS='tc_police' ./resource_scale.sh
+ TEST: 'tc_police' [default] 968 [FAIL]
+ tc police offload count failed
+ Error: mlxsw_spectrum: Failed to allocate policer index.
+ We have an error talking to the kernel
+ Command failed /tmp/tmp.i7Oc5HwmXY:969
+ TEST: 'tc_police' [default] overflow 969 [ OK ]
+ ...
+ TEST: 'tc_police' [ipv4_max] overflow 969 [ OK ]
+
+ $ echo $?
+ 0
+
+Fix this by moving the check to be done after each test case.
+
+Fixes: 059b18e21c63 ("selftests: mlxsw: Return correct error code in resource scale test")
+Signed-off-by: Amit Cohen <amcohen@nvidia.com>
+Reviewed-by: Petr Machata <petrm@nvidia.com>
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/drivers/net/mlxsw/spectrum/resource_scale.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh
+index bcb110e830ce..dea33dc93790 100755
+--- a/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh
++++ b/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh
+@@ -50,8 +50,8 @@ for current_test in ${TESTS:-$ALL_TESTS}; do
+ else
+ log_test "'$current_test' [$profile] overflow $target"
+ fi
++ RET_FIN=$(( RET_FIN || RET ))
+ done
+- RET_FIN=$(( RET_FIN || RET ))
+ done
+ done
+ current_test=""
+--
+2.34.1
+
memfd-fix-f_seal_write-after-shmem-huge-page-allocated.patch
s390-setup-preserve-memory-at-oldmem_base-and-oldmem_size.patch
s390-extable-fix-exception-table-sorting.patch
+arm64-dts-rockchip-drop-pclk_xpcs-from-gmac0-on-rk35.patch
+arm64-dts-juno-remove-gicv2m-dma-range.patch
+arm64-dts-rockchip-fix-quartz64-a-ddr-regulator-volt.patch
+arm64-dts-imx8mm-fix-vpu-hanging.patch
+iommu-amd-simplify-pagetable-freeing.patch
+iommu-amd-use-put_pages_list.patch
+iommu-amd-fix-i-o-page-table-memory-leak.patch
+mips-ralink-mt7621-do-memory-detection-on-kseg1.patch
+arm-dts-switch-timer-config-to-common-devkit8000-dev.patch
+arm-dts-use-32kihz-oscillator-on-devkit8000.patch
+soc-fsl-guts-revert-commit-3c0d64e867ed.patch
+soc-fsl-guts-add-a-missing-memory-allocation-failure.patch
+soc-fsl-qe-check-of-ioremap-return-value.patch
+soc-imx-gpcv2-fix-clock-disabling-imbalance-in-error.patch
+netfilter-nf_tables-prefer-kfree_rcu-ptr-rcu-variant.patch
+arm-tegra-move-panels-to-aux-bus.patch
+bluetooth-fix-bt_skb_sendmmsg-not-allocating-partial.patch
+can-etas_es58x-change-opened_channel_cnt-s-type-from.patch
+net-stmmac-enhance-xdp-zc-driver-level-switching-per.patch
+net-stmmac-only-enable-dma-interrupts-when-ready.patch
+ibmvnic-initialize-rc-before-completing-wait.patch
+ibmvnic-define-flush_reset_queue-helper.patch
+ibmvnic-complete-init_done-on-transport-events.patch
+ibmvnic-update-driver-return-codes.patch
+ibmvnic-init-init_done_rc-earlier.patch
+ibmvnic-clear-fop-when-retrying-probe.patch
+ibmvnic-allow-queueing-resets-during-probe.patch
+net-chelsio-cxgb3-check-the-return-value-of-pci_find.patch
+net-sparx5-fix-add-vlan-when-invalid-operation.patch
+iavf-add-trace-while-removing-device.patch
+iavf-rework-mutexes-for-better-synchronisation.patch
+iavf-add-waiting-so-the-port-is-initialized-in-remov.patch
+iavf-fix-init-state-closure-on-remove.patch
+iavf-fix-locking-for-virtchnl_op_get_offload_vlan_v2.patch
+iavf-fix-race-in-init-state.patch
+iavf-fix-__iavf_resetting-state-usage.patch
+drm-i915-guc-slpc-correct-the-param-count-for-unset-.patch
+drm-bridge-ti-sn65dsi86-properly-undo-autosuspend.patch
+e1000e-fix-possible-hw-unit-hang-after-an-s0ix-exit.patch
+mips-ralink-mt7621-use-bitwise-not-instead-of-logica.patch
+nl80211-handle-nla_memdup-failures-in-handle_nan_fil.patch
+ptp-ocp-add-ptp_ocp_adjtime_coarse-for-large-adjustm.patch
+drm-amdgpu-fix-suspend-resume-hang-regression.patch
+net-dcb-disable-softirqs-in-dcbnl_flush_dev.patch
+selftests-mlxsw-resource_scale-fix-return-value.patch
--- /dev/null
+From 4693252150fc3c82d81c55a99788e49835c1743b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Nov 2021 21:00:33 +0100
+Subject: soc: fsl: guts: Add a missing memory allocation failure check
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit b9abe942cda43a1d46a0fd96efb54f1aa909f757 ]
+
+If 'devm_kstrdup()' fails, we should return -ENOMEM.
+
+While at it, move the 'of_node_put()' call in the error handling path and
+after the 'machine' has been copied.
+Better safe than sorry.
+
+Fixes: a6fc3b698130 ("soc: fsl: add GUTS driver for QorIQ platforms")
+Depends-on: fddacc7ff4dd ("soc: fsl: guts: Revert commit 3c0d64e867ed")
+Suggested-by: Tyrel Datwyler <tyreld@linux.ibm.com>
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Signed-off-by: Li Yang <leoyang.li@nxp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/fsl/guts.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c
+index af7741eafc57..5ed2fc1c53a0 100644
+--- a/drivers/soc/fsl/guts.c
++++ b/drivers/soc/fsl/guts.c
+@@ -158,9 +158,14 @@ static int fsl_guts_probe(struct platform_device *pdev)
+ root = of_find_node_by_path("/");
+ if (of_property_read_string(root, "model", &machine))
+ of_property_read_string_index(root, "compatible", 0, &machine);
+- of_node_put(root);
+- if (machine)
++ if (machine) {
+ soc_dev_attr.machine = devm_kstrdup(dev, machine, GFP_KERNEL);
++ if (!soc_dev_attr.machine) {
++ of_node_put(root);
++ return -ENOMEM;
++ }
++ }
++ of_node_put(root);
+
+ svr = fsl_guts_get_svr();
+ soc_die = fsl_soc_die_match(svr, fsl_soc_die);
+--
+2.34.1
+
--- /dev/null
+From 899a1d20a75fb5d0791c36baae3b7636339e90dd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Nov 2021 21:00:17 +0100
+Subject: soc: fsl: guts: Revert commit 3c0d64e867ed
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit b113737cf12964a20cc3ba1ddabe6229099661c6 ]
+
+This reverts commit 3c0d64e867ed
+("soc: fsl: guts: reuse machine name from device tree").
+
+A following patch will fix the missing memory allocation failure check
+instead.
+
+Suggested-by: Tyrel Datwyler <tyreld@linux.ibm.com>
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Signed-off-by: Li Yang <leoyang.li@nxp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/fsl/guts.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c
+index 072473a16f4d..af7741eafc57 100644
+--- a/drivers/soc/fsl/guts.c
++++ b/drivers/soc/fsl/guts.c
+@@ -28,7 +28,6 @@ struct fsl_soc_die_attr {
+ static struct guts *guts;
+ static struct soc_device_attribute soc_dev_attr;
+ static struct soc_device *soc_dev;
+-static struct device_node *root;
+
+
+ /* SoC die attribute definition for QorIQ platform */
+@@ -138,7 +137,7 @@ static u32 fsl_guts_get_svr(void)
+
+ static int fsl_guts_probe(struct platform_device *pdev)
+ {
+- struct device_node *np = pdev->dev.of_node;
++ struct device_node *root, *np = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
+ const struct fsl_soc_die_attr *soc_die;
+ const char *machine;
+@@ -159,8 +158,9 @@ static int fsl_guts_probe(struct platform_device *pdev)
+ root = of_find_node_by_path("/");
+ if (of_property_read_string(root, "model", &machine))
+ of_property_read_string_index(root, "compatible", 0, &machine);
++ of_node_put(root);
+ if (machine)
+- soc_dev_attr.machine = machine;
++ soc_dev_attr.machine = devm_kstrdup(dev, machine, GFP_KERNEL);
+
+ svr = fsl_guts_get_svr();
+ soc_die = fsl_soc_die_match(svr, fsl_soc_die);
+@@ -195,7 +195,6 @@ static int fsl_guts_probe(struct platform_device *pdev)
+ static int fsl_guts_remove(struct platform_device *dev)
+ {
+ soc_device_unregister(soc_dev);
+- of_node_put(root);
+ return 0;
+ }
+
+--
+2.34.1
+
--- /dev/null
+From 7bb0e835e01e327a37d1f46cf24095b8a97518ab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Dec 2021 09:45:43 +0800
+Subject: soc: fsl: qe: Check of ioremap return value
+
+From: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+
+[ Upstream commit a222fd8541394b36b13c89d1698d9530afd59a9c ]
+
+As the possible failure of the ioremap(), the par_io could be NULL.
+Therefore it should be better to check it and return error in order to
+guarantee the success of the initiation.
+But, I also notice that all the caller like mpc85xx_qe_par_io_init() in
+`arch/powerpc/platforms/85xx/common.c` don't check the return value of
+the par_io_init().
+Actually, par_io_init() needs to check to handle the potential error.
+I will submit another patch to fix that.
+Anyway, par_io_init() itsely should be fixed.
+
+Fixes: 7aa1aa6ecec2 ("QE: Move QE from arch/powerpc to drivers/soc")
+Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+Signed-off-by: Li Yang <leoyang.li@nxp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/fsl/qe/qe_io.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/soc/fsl/qe/qe_io.c b/drivers/soc/fsl/qe/qe_io.c
+index e277c827bdf3..a5e2d0e5ab51 100644
+--- a/drivers/soc/fsl/qe/qe_io.c
++++ b/drivers/soc/fsl/qe/qe_io.c
+@@ -35,6 +35,8 @@ int par_io_init(struct device_node *np)
+ if (ret)
+ return ret;
+ par_io = ioremap(res.start, resource_size(&res));
++ if (!par_io)
++ return -ENOMEM;
+
+ if (!of_property_read_u32(np, "num-ports", &num_ports))
+ num_par_io_ports = num_ports;
+--
+2.34.1
+
--- /dev/null
+From 851466a38cf93dd073dfe79b166fb7e3249843a3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Feb 2022 23:57:20 +0200
+Subject: soc: imx: gpcv2: Fix clock disabling imbalance in error path
+
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+[ Upstream commit fa231bef3b34f1670b240409c11e59a3ce095e6d ]
+
+The imx_pgc_power_down() starts by enabling the domain clocks, and thus
+disables them in the error path. Commit 18c98573a4cf ("soc: imx: gpcv2:
+add domain option to keep domain clocks enabled") made the clock enable
+conditional, but forgot to add the same condition to the error path.
+This can result in a clock enable/disable imbalance. Fix it.
+
+Fixes: 18c98573a4cf ("soc: imx: gpcv2: add domain option to keep domain clocks enabled")
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
+Signed-off-by: Shawn Guo <shawnguo@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/imx/gpcv2.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
+index 8176380b02e6..4415f07e1fa9 100644
+--- a/drivers/soc/imx/gpcv2.c
++++ b/drivers/soc/imx/gpcv2.c
+@@ -382,7 +382,8 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd)
+ return 0;
+
+ out_clk_disable:
+- clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
++ if (!domain->keep_clocks)
++ clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
+
+ return ret;
+ }
+--
+2.34.1
+