From: Sasha Levin Date: Sat, 5 Mar 2022 20:55:47 +0000 (-0500) Subject: Fixes for 5.16 X-Git-Tag: v4.9.305~41^2~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c7073dfbfb86af2ac0fdba59d2a52cc7327f1e65;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.16 Signed-off-by: Sasha Levin --- diff --git a/queue-5.16/arm-dts-switch-timer-config-to-common-devkit8000-dev.patch b/queue-5.16/arm-dts-switch-timer-config-to-common-devkit8000-dev.patch new file mode 100644 index 00000000000..485ffd223b3 --- /dev/null +++ b/queue-5.16/arm-dts-switch-timer-config-to-common-devkit8000-dev.patch @@ -0,0 +1,109 @@ +From 6f349e33ce2921776a4a4305397d74ab05a2bfcb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Jan 2022 20:11:38 +0100 +Subject: ARM: dts: switch timer config to common devkit8000 devicetree + +From: Anthoine Bourgeois + +[ 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 +Signed-off-by: Tony Lindgren +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-5.16/arm-dts-use-32kihz-oscillator-on-devkit8000.patch b/queue-5.16/arm-dts-use-32kihz-oscillator-on-devkit8000.patch new file mode 100644 index 00000000000..45a863bf5fe --- /dev/null +++ b/queue-5.16/arm-dts-use-32kihz-oscillator-on-devkit8000.patch @@ -0,0 +1,88 @@ +From 61077c5b779d97f87bb7479bfb12974d305e8bc9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Jan 2022 20:11:39 +0100 +Subject: ARM: dts: Use 32KiHz oscillator on devkit8000 + +From: Anthoine Bourgeois + +[ 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 +Signed-off-by: Tony Lindgren +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/arm-tegra-move-panels-to-aux-bus.patch b/queue-5.16/arm-tegra-move-panels-to-aux-bus.patch new file mode 100644 index 00000000000..d22bce44732 --- /dev/null +++ b/queue-5.16/arm-tegra-move-panels-to-aux-bus.patch @@ -0,0 +1,112 @@ +From 2fb2e0a2be5a86af006852750ecfdcb65cac5cb0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Dec 2021 11:32:39 +0100 +Subject: ARM: tegra: Move panels to AUX bus + +From: Thierry Reding + +[ 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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/arm64-dts-imx8mm-fix-vpu-hanging.patch b/queue-5.16/arm64-dts-imx8mm-fix-vpu-hanging.patch new file mode 100644 index 00000000000..8a538f8450b --- /dev/null +++ b/queue-5.16/arm64-dts-imx8mm-fix-vpu-hanging.patch @@ -0,0 +1,37 @@ +From f234fb54ef2de87445571761d231af85c6c06807 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Jan 2022 11:11:25 -0600 +Subject: arm64: dts: imx8mm: Fix VPU Hanging + +From: Adam Ford + +[ 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 +Reviewed-by: Lucas Stach +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/arm64-dts-juno-remove-gicv2m-dma-range.patch b/queue-5.16/arm64-dts-juno-remove-gicv2m-dma-range.patch new file mode 100644 index 00000000000..2067299db38 --- /dev/null +++ b/queue-5.16/arm64-dts-juno-remove-gicv2m-dma-range.patch @@ -0,0 +1,49 @@ +From 06e1c23b052f352842554a016c55db9a1737bbe8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Jan 2022 17:57:01 +0000 +Subject: arm64: dts: juno: Remove GICv2m dma-range + +From: Robin Murphy + +[ 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 +Acked-by: Liviu Dudau +Signed-off-by: Robin Murphy +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/arm64-dts-rockchip-drop-pclk_xpcs-from-gmac0-on-rk35.patch b/queue-5.16/arm64-dts-rockchip-drop-pclk_xpcs-from-gmac0-on-rk35.patch new file mode 100644 index 00000000000..b5a7e0db232 --- /dev/null +++ b/queue-5.16/arm64-dts-rockchip-drop-pclk_xpcs-from-gmac0-on-rk35.patch @@ -0,0 +1,64 @@ +From 4458a534ef37cb25041df6bdd34201e39e8b678f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 23 Jan 2022 14:35:10 +0100 +Subject: arm64: dts: rockchip: drop pclk_xpcs from gmac0 on rk3568 + +From: Frank Wunderlich + +[ 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 +Signed-off-by: Peter Geis +Signed-off-by: Frank Wunderlich +Acked-by: Michael Riesch +Link: https://lore.kernel.org/r/20220123133510.135651-1-linux@fw-web.de +Signed-off-by: Heiko Stuebner +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/arm64-dts-rockchip-fix-quartz64-a-ddr-regulator-volt.patch b/queue-5.16/arm64-dts-rockchip-fix-quartz64-a-ddr-regulator-volt.patch new file mode 100644 index 00000000000..d044e8cb52b --- /dev/null +++ b/queue-5.16/arm64-dts-rockchip-fix-quartz64-a-ddr-regulator-volt.patch @@ -0,0 +1,41 @@ +From 79a124d5500cb9b3a89c99b7d5794e140a68ac70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Jan 2022 19:38:05 -0500 +Subject: arm64: dts: rockchip: fix Quartz64-A ddr regulator voltage + +From: Peter Geis + +[ 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 +Link: https://lore.kernel.org/r/20220128003809.3291407-2-pgwipeout@gmail.com +Signed-off-by: Heiko Stuebner +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/bluetooth-fix-bt_skb_sendmmsg-not-allocating-partial.patch b/queue-5.16/bluetooth-fix-bt_skb_sendmmsg-not-allocating-partial.patch new file mode 100644 index 00000000000..5865140e947 --- /dev/null +++ b/queue-5.16/bluetooth-fix-bt_skb_sendmmsg-not-allocating-partial.patch @@ -0,0 +1,42 @@ +From 976b37e2a5885863e25eb71ebf8f67bf272a3b0f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Feb 2022 17:59:38 -0800 +Subject: Bluetooth: Fix bt_skb_sendmmsg not allocating partial chunks + +From: Luiz Augusto von Dentz + +[ 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 +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 +Tested-by: Paul Menzel (Nokia N9 (MeeGo/Harmattan) +Signed-off-by: Marcel Holtmann +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/can-etas_es58x-change-opened_channel_cnt-s-type-from.patch b/queue-5.16/can-etas_es58x-change-opened_channel_cnt-s-type-from.patch new file mode 100644 index 00000000000..8384e2052fd --- /dev/null +++ b/queue-5.16/can-etas_es58x-change-opened_channel_cnt-s-type-from.patch @@ -0,0 +1,145 @@ +From 1885746ec2ea63d5ee6970657c878610417c8531 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Vincent Mailhol +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/drm-amdgpu-fix-suspend-resume-hang-regression.patch b/queue-5.16/drm-amdgpu-fix-suspend-resume-hang-regression.patch new file mode 100644 index 00000000000..63c2d129482 --- /dev/null +++ b/queue-5.16/drm-amdgpu-fix-suspend-resume-hang-regression.patch @@ -0,0 +1,44 @@ +From 5bb330da4ac107341315142178a975fc3953f3ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Qiang Yu +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/drm-bridge-ti-sn65dsi86-properly-undo-autosuspend.patch b/queue-5.16/drm-bridge-ti-sn65dsi86-properly-undo-autosuspend.patch new file mode 100644 index 00000000000..ada39a3c37e --- /dev/null +++ b/queue-5.16/drm-bridge-ti-sn65dsi86-properly-undo-autosuspend.patch @@ -0,0 +1,54 @@ +From 7b75869723751933faead20e628c433346bcef41 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Feb 2022 14:18:43 -0800 +Subject: drm/bridge: ti-sn65dsi86: Properly undo autosuspend + +From: Douglas Anderson + +[ 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 +Reviewed-by: Linus Walleij +Link: https://patchwork.freedesktop.org/patch/msgid/20220222141838.1.If784ba19e875e8ded4ec4931601ce6d255845245@changeid +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/drm-i915-guc-slpc-correct-the-param-count-for-unset-.patch b/queue-5.16/drm-i915-guc-slpc-correct-the-param-count-for-unset-.patch new file mode 100644 index 00000000000..5ae7305cca4 --- /dev/null +++ b/queue-5.16/drm-i915-guc-slpc-correct-the-param-count-for-unset-.patch @@ -0,0 +1,42 @@ +From e7c44e365b06eb6dc329bc235a5c92f729d284d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Feb 2022 10:15:04 -0800 +Subject: drm/i915/guc/slpc: Correct the param count for unset param + +From: Vinay Belgaumkar + +[ 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 +Signed-off-by: Vinay Belgaumkar +Reviewed-by: Umesh Nerlige Ramappa +Signed-off-by: Ramalingam C +Link: https://patchwork.freedesktop.org/patch/msgid/20220216181504.7155-1-vinay.belgaumkar@intel.com +(cherry picked from commit 9648f1c3739505557d94ff749a4f32192ea81fe3) +Signed-off-by: Tvrtko Ursulin +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/e1000e-fix-possible-hw-unit-hang-after-an-s0ix-exit.patch b/queue-5.16/e1000e-fix-possible-hw-unit-hang-after-an-s0ix-exit.patch new file mode 100644 index 00000000000..2dba1e45fbc --- /dev/null +++ b/queue-5.16/e1000e-fix-possible-hw-unit-hang-after-an-s0ix-exit.patch @@ -0,0 +1,124 @@ +From 4c3a8889de12355d19058fc38b0067b81f1bdee3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Jan 2022 19:31:23 +0200 +Subject: e1000e: Fix possible HW unit hang after an s0ix exit + +From: Sasha Neftin + +[ 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 +Suggested-by: Nir Efrati +Signed-off-by: Sasha Neftin +Tested-by: Kai-Heng Feng +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/iavf-add-trace-while-removing-device.patch b/queue-5.16/iavf-add-trace-while-removing-device.patch new file mode 100644 index 00000000000..4934f53d28c --- /dev/null +++ b/queue-5.16/iavf-add-trace-while-removing-device.patch @@ -0,0 +1,40 @@ +From 31531faa59684b9869ef5b39c00dd9730e0d1f2f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Jun 2021 15:43:48 +0200 +Subject: iavf: Add trace while removing device + +From: Jedrzej Jagielski + +[ 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 +Signed-off-by: Jedrzej Jagielski +Tested-by: Konrad Jankowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/iavf-add-waiting-so-the-port-is-initialized-in-remov.patch b/queue-5.16/iavf-add-waiting-so-the-port-is-initialized-in-remov.patch new file mode 100644 index 00000000000..252e507ba74 --- /dev/null +++ b/queue-5.16/iavf-add-waiting-so-the-port-is-initialized-in-remov.patch @@ -0,0 +1,91 @@ +From 9ccd78004b57c3dede3fc56df9ca14144c4a5c24 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Feb 2022 13:36:56 +0100 +Subject: iavf: Add waiting so the port is initialized in remove + +From: Slawomir Laba + +[ 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 +Signed-off-by: Phani Burra +Signed-off-by: Jacob Keller +Signed-off-by: Mateusz Palczewski +Tested-by: Konrad Jankowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/iavf-fix-__iavf_resetting-state-usage.patch b/queue-5.16/iavf-fix-__iavf_resetting-state-usage.patch new file mode 100644 index 00000000000..41e0e3187be --- /dev/null +++ b/queue-5.16/iavf-fix-__iavf_resetting-state-usage.patch @@ -0,0 +1,75 @@ +From 99370296907366839eaca8f96dff68d036a1df4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Feb 2022 13:38:55 +0100 +Subject: iavf: Fix __IAVF_RESETTING state usage + +From: Slawomir Laba + +[ 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 +Signed-off-by: Phani Burra +Signed-off-by: Jacob Keller +Signed-off-by: Mateusz Palczewski +Tested-by: Konrad Jankowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/iavf-fix-init-state-closure-on-remove.patch b/queue-5.16/iavf-fix-init-state-closure-on-remove.patch new file mode 100644 index 00000000000..28139c9cd5f --- /dev/null +++ b/queue-5.16/iavf-fix-init-state-closure-on-remove.patch @@ -0,0 +1,120 @@ +From b5ee8c62e24fc6ddbec4fbbe5e7964968d6fc37c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Feb 2022 13:37:10 +0100 +Subject: iavf: Fix init state closure on remove + +From: Slawomir Laba + +[ 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 +Signed-off-by: Phani Burra +Signed-off-by: Jacob Keller +Signed-off-by: Mateusz Palczewski +Tested-by: Konrad Jankowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/iavf-fix-locking-for-virtchnl_op_get_offload_vlan_v2.patch b/queue-5.16/iavf-fix-locking-for-virtchnl_op_get_offload_vlan_v2.patch new file mode 100644 index 00000000000..468184497fa --- /dev/null +++ b/queue-5.16/iavf-fix-locking-for-virtchnl_op_get_offload_vlan_v2.patch @@ -0,0 +1,123 @@ +From 4ed13bc6fb5640e254709a62b47d3bc20a2ed796 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Feb 2022 13:37:50 +0100 +Subject: iavf: Fix locking for VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS + +From: Slawomir Laba + +[ 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 +Signed-off-by: Phani Burra +Signed-off-by: Jacob Keller +Signed-off-by: Mateusz Palczewski +Tested-by: Konrad Jankowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/iavf-fix-race-in-init-state.patch b/queue-5.16/iavf-fix-race-in-init-state.patch new file mode 100644 index 00000000000..348a0739340 --- /dev/null +++ b/queue-5.16/iavf-fix-race-in-init-state.patch @@ -0,0 +1,51 @@ +From e890ce16df6f8ce37e95dc56b74ff4da0c1aaaaf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Feb 2022 13:38:01 +0100 +Subject: iavf: Fix race in init state + +From: Slawomir Laba + +[ 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 +Signed-off-by: Phani Burra +Signed-off-by: Jacob Keller +Signed-off-by: Mateusz Palczewski +Tested-by: Konrad Jankowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/iavf-rework-mutexes-for-better-synchronisation.patch b/queue-5.16/iavf-rework-mutexes-for-better-synchronisation.patch new file mode 100644 index 00000000000..d7b68755f31 --- /dev/null +++ b/queue-5.16/iavf-rework-mutexes-for-better-synchronisation.patch @@ -0,0 +1,220 @@ +From aa8fabb6d326832ab5aebcc9186aa22245552065 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Feb 2022 13:35:49 +0100 +Subject: iavf: Rework mutexes for better synchronisation + +From: Slawomir Laba + +[ 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 +Signed-off-by: Phani Burra +Signed-off-by: Jacob Keller +Signed-off-by: Mateusz Palczewski +Tested-by: Konrad Jankowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/ibmvnic-allow-queueing-resets-during-probe.patch b/queue-5.16/ibmvnic-allow-queueing-resets-during-probe.patch new file mode 100644 index 00000000000..0c5138f88ed --- /dev/null +++ b/queue-5.16/ibmvnic-allow-queueing-resets-during-probe.patch @@ -0,0 +1,274 @@ +From 8dda9af1e93ced0c920755ad32d2e6c93ea00be8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Feb 2022 22:23:58 -0800 +Subject: ibmvnic: Allow queueing resets during probe + +From: Sukadev Bhattiprolu + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/ibmvnic-clear-fop-when-retrying-probe.patch b/queue-5.16/ibmvnic-clear-fop-when-retrying-probe.patch new file mode 100644 index 00000000000..a41c44db425 --- /dev/null +++ b/queue-5.16/ibmvnic-clear-fop-when-retrying-probe.patch @@ -0,0 +1,46 @@ +From 2451f3416710e850ea0b6de71393b7a7cba2f02e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Feb 2022 22:23:57 -0800 +Subject: ibmvnic: clear fop when retrying probe + +From: Sukadev Bhattiprolu + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/ibmvnic-complete-init_done-on-transport-events.patch b/queue-5.16/ibmvnic-complete-init_done-on-transport-events.patch new file mode 100644 index 00000000000..b2dc06f174a --- /dev/null +++ b/queue-5.16/ibmvnic-complete-init_done-on-transport-events.patch @@ -0,0 +1,42 @@ +From a4db48354e5a7a137f12185261d3caf27e0da6c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Feb 2022 22:23:54 -0800 +Subject: ibmvnic: complete init_done on transport events + +From: Sukadev Bhattiprolu + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/ibmvnic-define-flush_reset_queue-helper.patch b/queue-5.16/ibmvnic-define-flush_reset_queue-helper.patch new file mode 100644 index 00000000000..784e54fbe67 --- /dev/null +++ b/queue-5.16/ibmvnic-define-flush_reset_queue-helper.patch @@ -0,0 +1,68 @@ +From 46cbdf8227c219ca051270e873f38443f974e17a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Feb 2022 22:23:53 -0800 +Subject: ibmvnic: define flush_reset_queue helper + +From: Sukadev Bhattiprolu + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/ibmvnic-init-init_done_rc-earlier.patch b/queue-5.16/ibmvnic-init-init_done_rc-earlier.patch new file mode 100644 index 00000000000..626ef882b1c --- /dev/null +++ b/queue-5.16/ibmvnic-init-init_done_rc-earlier.patch @@ -0,0 +1,110 @@ +From c6d999a4962f162f0de1b18f7f35c1be5b86fdb5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Feb 2022 22:23:56 -0800 +Subject: ibmvnic: init init_done_rc earlier + +From: Sukadev Bhattiprolu + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/ibmvnic-initialize-rc-before-completing-wait.patch b/queue-5.16/ibmvnic-initialize-rc-before-completing-wait.patch new file mode 100644 index 00000000000..ecf2f3dbb09 --- /dev/null +++ b/queue-5.16/ibmvnic-initialize-rc-before-completing-wait.patch @@ -0,0 +1,39 @@ +From 54950130f768f2d2a0977e6f4f4b0257580ebbb6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Feb 2022 22:23:52 -0800 +Subject: ibmvnic: initialize rc before completing wait + +From: Sukadev Bhattiprolu + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/ibmvnic-update-driver-return-codes.patch b/queue-5.16/ibmvnic-update-driver-return-codes.patch new file mode 100644 index 00000000000..5ed4500f600 --- /dev/null +++ b/queue-5.16/ibmvnic-update-driver-return-codes.patch @@ -0,0 +1,268 @@ +From 0bc96584ee434c4a72e533f64309a5ffebbef2d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Dec 2021 00:17:47 -0500 +Subject: ibmvnic: Update driver return codes + +From: Dany Madden + +[ Upstream commit b6ee566cf3940883d67c0d142fae8d410e975f47 ] + +Update return codes to be more informative. + +Signed-off-by: Jacob Root +Signed-off-by: Dany Madden +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/iommu-amd-fix-i-o-page-table-memory-leak.patch b/queue-5.16/iommu-amd-fix-i-o-page-table-memory-leak.patch new file mode 100644 index 00000000000..ab29f79ada0 --- /dev/null +++ b/queue-5.16/iommu-amd-fix-i-o-page-table-memory-leak.patch @@ -0,0 +1,61 @@ +From 17bba395b5754c254a6fda3a6973b2f35f6e4a46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Feb 2022 09:47:45 -0600 +Subject: iommu/amd: Fix I/O page table memory leak + +From: Suravee Suthikulpanit + +[ 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 +Reported-by: Daniel Jordan +Tested-by: Daniel Jordan +Signed-off-by: Suravee Suthikulpanit +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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/iommu-amd-simplify-pagetable-freeing.patch b/queue-5.16/iommu-amd-simplify-pagetable-freeing.patch new file mode 100644 index 00000000000..20deda433b9 --- /dev/null +++ b/queue-5.16/iommu-amd-simplify-pagetable-freeing.patch @@ -0,0 +1,169 @@ +From da8f8eb5547bbcc236d36afd7cd01f49ad5d2c42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Dec 2021 15:30:58 +0000 +Subject: iommu/amd: Simplify pagetable freeing + +From: Robin Murphy + +[ 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 +Link: https://lore.kernel.org/r/d3d00c9f3fa0df4756b867072c201e6e82f9ce39.1639753638.git.robin.murphy@arm.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/iommu-amd-use-put_pages_list.patch b/queue-5.16/iommu-amd-use-put_pages_list.patch new file mode 100644 index 00000000000..cd226f65034 --- /dev/null +++ b/queue-5.16/iommu-amd-use-put_pages_list.patch @@ -0,0 +1,173 @@ +From 42cf2683550e58b3529f00d834e1a700c8962994 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Dec 2021 15:30:59 +0000 +Subject: iommu/amd: Use put_pages_list + +From: Matthew Wilcox (Oracle) + +[ 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) +[rm: split from original patch, cosmetic tweaks] +Signed-off-by: Robin Murphy +Link: https://lore.kernel.org/r/73af128f651aaa1f38f69e586c66765a88ad2de0.1639753638.git.robin.murphy@arm.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/mips-ralink-mt7621-do-memory-detection-on-kseg1.patch b/queue-5.16/mips-ralink-mt7621-do-memory-detection-on-kseg1.patch new file mode 100644 index 00000000000..08aef2d170e --- /dev/null +++ b/queue-5.16/mips-ralink-mt7621-do-memory-detection-on-kseg1.patch @@ -0,0 +1,95 @@ +From 916192e06e8e114c5173b101cf321101d81fa8a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Feb 2022 08:13:44 +0800 +Subject: MIPS: ralink: mt7621: do memory detection on KSEG1 + +From: Chuanhong Guo + +[ 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 +Signed-off-by: Chuanhong Guo +Tested-by: Sergio Paracuellos +Tested-by: Rui Salvaterra +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/mips-ralink-mt7621-use-bitwise-not-instead-of-logica.patch b/queue-5.16/mips-ralink-mt7621-use-bitwise-not-instead-of-logica.patch new file mode 100644 index 00000000000..5601d85d5d8 --- /dev/null +++ b/queue-5.16/mips-ralink-mt7621-use-bitwise-not-instead-of-logica.patch @@ -0,0 +1,38 @@ +From 9d933ab70e2c0d56f1d4ccf3317453642c8cc784 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Feb 2022 17:15:07 -0800 +Subject: MIPS: ralink: mt7621: use bitwise NOT instead of logical + +From: Ilya Lipnitskiy + +[ 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 +Signed-off-by: Ilya Lipnitskiy +Reviewed-by: Sergio Paracuellos +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/net-chelsio-cxgb3-check-the-return-value-of-pci_find.patch b/queue-5.16/net-chelsio-cxgb3-check-the-return-value-of-pci_find.patch new file mode 100644 index 00000000000..9f1916cae78 --- /dev/null +++ b/queue-5.16/net-chelsio-cxgb3-check-the-return-value-of-pci_find.patch @@ -0,0 +1,37 @@ +From 2f521aadaaaca07cd1143861d0ae29b3efaa0144 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Jia-Ju Bai +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/net-dcb-disable-softirqs-in-dcbnl_flush_dev.patch b/queue-5.16/net-dcb-disable-softirqs-in-dcbnl_flush_dev.patch new file mode 100644 index 00000000000..f94cae3f242 --- /dev/null +++ b/queue-5.16/net-dcb-disable-softirqs-in-dcbnl_flush_dev.patch @@ -0,0 +1,62 @@ +From c18d886459e3b77da5a853535c93ab7500f58124 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Mar 2022 21:39:39 +0200 +Subject: net: dcb: disable softirqs in dcbnl_flush_dev() + +From: Vladimir Oltean + +[ 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 +Signed-off-by: Vladimir Oltean +Link: https://lore.kernel.org/r/20220302193939.1368823-1-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/net-sparx5-fix-add-vlan-when-invalid-operation.patch b/queue-5.16/net-sparx5-fix-add-vlan-when-invalid-operation.patch new file mode 100644 index 00000000000..36e41e6e379 --- /dev/null +++ b/queue-5.16/net-sparx5-fix-add-vlan-when-invalid-operation.patch @@ -0,0 +1,64 @@ +From 114e9646f14fb5067363c0a83daf8314e103ee84 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Feb 2022 11:15:16 +0100 +Subject: net: sparx5: Fix add vlan when invalid operation + +From: Casper Andersson + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-5.16/net-stmmac-enhance-xdp-zc-driver-level-switching-per.patch b/queue-5.16/net-stmmac-enhance-xdp-zc-driver-level-switching-per.patch new file mode 100644 index 00000000000..67f735e0ef5 --- /dev/null +++ b/queue-5.16/net-stmmac-enhance-xdp-zc-driver-level-switching-per.patch @@ -0,0 +1,255 @@ +From 721322b751f39f2843d35dec7a80001d5cc446b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Nov 2021 22:39:49 +0800 +Subject: net: stmmac: enhance XDP ZC driver level switching performance + +From: Ong Boon Leong + +[ 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 +Signed-off-by: Ong Boon Leong +Tested-by: Kurt Kanzenbach +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/net-stmmac-only-enable-dma-interrupts-when-ready.patch b/queue-5.16/net-stmmac-only-enable-dma-interrupts-when-ready.patch new file mode 100644 index 00000000000..ff23140fe37 --- /dev/null +++ b/queue-5.16/net-stmmac-only-enable-dma-interrupts-when-ready.patch @@ -0,0 +1,111 @@ +From d18a70db2c7ba7da108f9c33b9b11d7cbb195bd2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Feb 2022 12:38:29 +0100 +Subject: net: stmmac: only enable DMA interrupts when ready + +From: Vincent Whitchurch + +[ 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 +Signed-off-by: Vincent Whitchurch +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-5.16/netfilter-nf_tables-prefer-kfree_rcu-ptr-rcu-variant.patch b/queue-5.16/netfilter-nf_tables-prefer-kfree_rcu-ptr-rcu-variant.patch new file mode 100644 index 00000000000..2fa0c8dbab8 --- /dev/null +++ b/queue-5.16/netfilter-nf_tables-prefer-kfree_rcu-ptr-rcu-variant.patch @@ -0,0 +1,53 @@ +From 733f87d56b9a367d15a7d964b23dbe840d01c1c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Feb 2022 10:13:31 -0800 +Subject: netfilter: nf_tables: prefer kfree_rcu(ptr, rcu) variant + +From: Eric Dumazet + +[ 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 +Reviewed-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_tables_api.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 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 + diff --git a/queue-5.16/nl80211-handle-nla_memdup-failures-in-handle_nan_fil.patch b/queue-5.16/nl80211-handle-nla_memdup-failures-in-handle_nan_fil.patch new file mode 100644 index 00000000000..c7fe08de461 --- /dev/null +++ b/queue-5.16/nl80211-handle-nla_memdup-failures-in-handle_nan_fil.patch @@ -0,0 +1,54 @@ +From 44331e751c3907fe89f2c201f5ea59a56acd9f3f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Mar 2022 18:00:20 +0800 +Subject: nl80211: Handle nla_memdup failures in handle_nan_filter + +From: Jiasheng Jiang + +[ 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 +Link: https://lore.kernel.org/r/20220301100020.3801187-1-jiasheng@iscas.ac.cn +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/ptp-ocp-add-ptp_ocp_adjtime_coarse-for-large-adjustm.patch b/queue-5.16/ptp-ocp-add-ptp_ocp_adjtime_coarse-for-large-adjustm.patch new file mode 100644 index 00000000000..f057eb75e44 --- /dev/null +++ b/queue-5.16/ptp-ocp-add-ptp_ocp_adjtime_coarse-for-large-adjustm.patch @@ -0,0 +1,91 @@ +From ff38defe5e96242ec919416054973ec803a864dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Feb 2022 12:39:57 -0800 +Subject: ptp: ocp: Add ptp_ocp_adjtime_coarse for large adjustments + +From: Jonathan Lemon + +[ 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 +Acked-by: Richard Cochran +Link: https://lore.kernel.org/r/20220228203957.367371-1-jonathan.lemon@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/selftests-mlxsw-resource_scale-fix-return-value.patch b/queue-5.16/selftests-mlxsw-resource_scale-fix-return-value.patch new file mode 100644 index 00000000000..70a6fcc4028 --- /dev/null +++ b/queue-5.16/selftests-mlxsw-resource_scale-fix-return-value.patch @@ -0,0 +1,57 @@ +From 5457c795f1823dbffe1a4a9321a33d6761b4b4b7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Mar 2022 18:14:47 +0200 +Subject: selftests: mlxsw: resource_scale: Fix return value + +From: Amit Cohen + +[ 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 +Reviewed-by: Petr Machata +Signed-off-by: Ido Schimmel +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-5.16/series b/queue-5.16/series index fa3909a987f..adf1eff10fc 100644 --- a/queue-5.16/series +++ b/queue-5.16/series @@ -116,3 +116,48 @@ ibmvnic-free-reset-work-item-when-flushing.patch 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 diff --git a/queue-5.16/soc-fsl-guts-add-a-missing-memory-allocation-failure.patch b/queue-5.16/soc-fsl-guts-add-a-missing-memory-allocation-failure.patch new file mode 100644 index 00000000000..5b46ecc306f --- /dev/null +++ b/queue-5.16/soc-fsl-guts-add-a-missing-memory-allocation-failure.patch @@ -0,0 +1,49 @@ +From 4693252150fc3c82d81c55a99788e49835c1743b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Nov 2021 21:00:33 +0100 +Subject: soc: fsl: guts: Add a missing memory allocation failure check + +From: Christophe JAILLET + +[ 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 +Signed-off-by: Christophe JAILLET +Signed-off-by: Li Yang +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/soc-fsl-guts-revert-commit-3c0d64e867ed.patch b/queue-5.16/soc-fsl-guts-revert-commit-3c0d64e867ed.patch new file mode 100644 index 00000000000..74afe390406 --- /dev/null +++ b/queue-5.16/soc-fsl-guts-revert-commit-3c0d64e867ed.patch @@ -0,0 +1,66 @@ +From 899a1d20a75fb5d0791c36baae3b7636339e90dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Nov 2021 21:00:17 +0100 +Subject: soc: fsl: guts: Revert commit 3c0d64e867ed + +From: Christophe JAILLET + +[ 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 +Signed-off-by: Christophe JAILLET +Signed-off-by: Li Yang +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/soc-fsl-qe-check-of-ioremap-return-value.patch b/queue-5.16/soc-fsl-qe-check-of-ioremap-return-value.patch new file mode 100644 index 00000000000..39c5461cb29 --- /dev/null +++ b/queue-5.16/soc-fsl-qe-check-of-ioremap-return-value.patch @@ -0,0 +1,43 @@ +From 7bb0e835e01e327a37d1f46cf24095b8a97518ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Dec 2021 09:45:43 +0800 +Subject: soc: fsl: qe: Check of ioremap return value + +From: Jiasheng Jiang + +[ 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 +Signed-off-by: Li Yang +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.16/soc-imx-gpcv2-fix-clock-disabling-imbalance-in-error.patch b/queue-5.16/soc-imx-gpcv2-fix-clock-disabling-imbalance-in-error.patch new file mode 100644 index 00000000000..c26da41abee --- /dev/null +++ b/queue-5.16/soc-imx-gpcv2-fix-clock-disabling-imbalance-in-error.patch @@ -0,0 +1,41 @@ +From 851466a38cf93dd073dfe79b166fb7e3249843a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Feb 2022 23:57:20 +0200 +Subject: soc: imx: gpcv2: Fix clock disabling imbalance in error path + +From: Laurent Pinchart + +[ 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 +Reviewed-by: Lucas Stach +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + 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 +