From 2e45cb8f53a1bbb59d7828a1b503d3c0291d3b15 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sat, 5 Mar 2022 15:55:48 -0500 Subject: [PATCH] Fixes for 5.15 Signed-off-by: Sasha Levin --- ...imer-config-to-common-devkit8000-dev.patch | 109 ++++++++ ...-use-32kihz-oscillator-on-devkit8000.patch | 88 ++++++ .../arm-tegra-move-panels-to-aux-bus.patch | 112 ++++++++ ...m64-dts-juno-remove-gicv2m-dma-range.patch | 49 ++++ ...hange-opened_channel_cnt-s-type-from.patch | 145 ++++++++++ ...u-fix-suspend-resume-hang-regression.patch | 44 +++ ...-sn65dsi86-properly-undo-autosuspend.patch | 54 ++++ ...c-correct-the-param-count-for-unset-.patch | 42 +++ ...ible-hw-unit-hang-after-an-s0ix-exit.patch | 124 +++++++++ .../iavf-add-__iavf_init_failed-state.patch | 160 +++++++++++ ...function-to-go-from-pci_dev-to-adapt.patch | 90 ++++++ ...iavf-add-trace-while-removing-device.patch | 40 +++ ...-so-the-port-is-initialized-in-remov.patch | 91 ++++++ ...ine-init-and-watchdog-state-machines.patch | 262 ++++++++++++++++++ ...avf-fix-__iavf_resetting-state-usage.patch | 75 +++++ ...avf-fix-init-state-closure-on-remove.patch | 120 ++++++++ ...iavf-fix-kernel-bug-in-free_msi_irqs.patch | 166 +++++++++++ ...-for-virtchnl_op_get_offload_vlan_v2.patch | 123 ++++++++ queue-5.15/iavf-fix-race-in-init-state.patch | 51 ++++ ...refactor-iavf-state-machine-tracking.patch | 234 ++++++++++++++++ ...k-mutexes-for-better-synchronisation.patch | 216 +++++++++++++++ ...mplete-init_done-on-transport-events.patch | 42 +++ ...vnic-define-flush_reset_queue-helper.patch | 68 +++++ ...initialize-rc-before-completing-wait.patch | 39 +++ ...u-amd-fix-i-o-page-table-memory-leak.patch | 61 ++++ ...iommu-amd-simplify-pagetable-freeing.patch | 169 +++++++++++ queue-5.15/iommu-amd-use-put_pages_list.patch | 173 ++++++++++++ ...-mt7621-do-memory-detection-on-kseg1.patch | 95 +++++++ ...21-use-bitwise-not-instead-of-logica.patch | 38 +++ ...3-check-the-return-value-of-pci_find.patch | 37 +++ ...-disable-softirqs-in-dcbnl_flush_dev.patch | 62 +++++ ...-fix-add-vlan-when-invalid-operation.patch | 64 +++++ ...ce-xdp-zc-driver-level-switching-per.patch | 255 +++++++++++++++++ ...nly-enable-dma-interrupts-when-ready.patch | 111 ++++++++ ...les-prefer-kfree_rcu-ptr-rcu-variant.patch | 53 ++++ ...la_memdup-failures-in-handle_nan_fil.patch | 54 ++++ ...lxsw-resource_scale-fix-return-value.patch | 57 ++++ queue-5.15/series | 40 +++ ...-a-missing-memory-allocation-failure.patch | 49 ++++ ...-fsl-guts-revert-commit-3c0d64e867ed.patch | 66 +++++ ...fsl-qe-check-of-ioremap-return-value.patch | 43 +++ 41 files changed, 3971 insertions(+) create mode 100644 queue-5.15/arm-dts-switch-timer-config-to-common-devkit8000-dev.patch create mode 100644 queue-5.15/arm-dts-use-32kihz-oscillator-on-devkit8000.patch create mode 100644 queue-5.15/arm-tegra-move-panels-to-aux-bus.patch create mode 100644 queue-5.15/arm64-dts-juno-remove-gicv2m-dma-range.patch create mode 100644 queue-5.15/can-etas_es58x-change-opened_channel_cnt-s-type-from.patch create mode 100644 queue-5.15/drm-amdgpu-fix-suspend-resume-hang-regression.patch create mode 100644 queue-5.15/drm-bridge-ti-sn65dsi86-properly-undo-autosuspend.patch create mode 100644 queue-5.15/drm-i915-guc-slpc-correct-the-param-count-for-unset-.patch create mode 100644 queue-5.15/e1000e-fix-possible-hw-unit-hang-after-an-s0ix-exit.patch create mode 100644 queue-5.15/iavf-add-__iavf_init_failed-state.patch create mode 100644 queue-5.15/iavf-add-helper-function-to-go-from-pci_dev-to-adapt.patch create mode 100644 queue-5.15/iavf-add-trace-while-removing-device.patch create mode 100644 queue-5.15/iavf-add-waiting-so-the-port-is-initialized-in-remov.patch create mode 100644 queue-5.15/iavf-combine-init-and-watchdog-state-machines.patch create mode 100644 queue-5.15/iavf-fix-__iavf_resetting-state-usage.patch create mode 100644 queue-5.15/iavf-fix-init-state-closure-on-remove.patch create mode 100644 queue-5.15/iavf-fix-kernel-bug-in-free_msi_irqs.patch create mode 100644 queue-5.15/iavf-fix-locking-for-virtchnl_op_get_offload_vlan_v2.patch create mode 100644 queue-5.15/iavf-fix-race-in-init-state.patch create mode 100644 queue-5.15/iavf-refactor-iavf-state-machine-tracking.patch create mode 100644 queue-5.15/iavf-rework-mutexes-for-better-synchronisation.patch create mode 100644 queue-5.15/ibmvnic-complete-init_done-on-transport-events.patch create mode 100644 queue-5.15/ibmvnic-define-flush_reset_queue-helper.patch create mode 100644 queue-5.15/ibmvnic-initialize-rc-before-completing-wait.patch create mode 100644 queue-5.15/iommu-amd-fix-i-o-page-table-memory-leak.patch create mode 100644 queue-5.15/iommu-amd-simplify-pagetable-freeing.patch create mode 100644 queue-5.15/iommu-amd-use-put_pages_list.patch create mode 100644 queue-5.15/mips-ralink-mt7621-do-memory-detection-on-kseg1.patch create mode 100644 queue-5.15/mips-ralink-mt7621-use-bitwise-not-instead-of-logica.patch create mode 100644 queue-5.15/net-chelsio-cxgb3-check-the-return-value-of-pci_find.patch create mode 100644 queue-5.15/net-dcb-disable-softirqs-in-dcbnl_flush_dev.patch create mode 100644 queue-5.15/net-sparx5-fix-add-vlan-when-invalid-operation.patch create mode 100644 queue-5.15/net-stmmac-enhance-xdp-zc-driver-level-switching-per.patch create mode 100644 queue-5.15/net-stmmac-only-enable-dma-interrupts-when-ready.patch create mode 100644 queue-5.15/netfilter-nf_tables-prefer-kfree_rcu-ptr-rcu-variant.patch create mode 100644 queue-5.15/nl80211-handle-nla_memdup-failures-in-handle_nan_fil.patch create mode 100644 queue-5.15/selftests-mlxsw-resource_scale-fix-return-value.patch create mode 100644 queue-5.15/soc-fsl-guts-add-a-missing-memory-allocation-failure.patch create mode 100644 queue-5.15/soc-fsl-guts-revert-commit-3c0d64e867ed.patch create mode 100644 queue-5.15/soc-fsl-qe-check-of-ioremap-return-value.patch diff --git a/queue-5.15/arm-dts-switch-timer-config-to-common-devkit8000-dev.patch b/queue-5.15/arm-dts-switch-timer-config-to-common-devkit8000-dev.patch new file mode 100644 index 00000000000..46b8641d08f --- /dev/null +++ b/queue-5.15/arm-dts-switch-timer-config-to-common-devkit8000-dev.patch @@ -0,0 +1,109 @@ +From 574a0aa6ee459fc336cce7e765118cda090dcac3 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 2c19d6e255bd..0df2b1dd07f6 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.15/arm-dts-use-32kihz-oscillator-on-devkit8000.patch b/queue-5.15/arm-dts-use-32kihz-oscillator-on-devkit8000.patch new file mode 100644 index 00000000000..e54a0757c82 --- /dev/null +++ b/queue-5.15/arm-dts-use-32kihz-oscillator-on-devkit8000.patch @@ -0,0 +1,88 @@ +From eed594e56910b074825c354af6d235de4eea6737 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 0df2b1dd07f6..6883ccb45600 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.15/arm-tegra-move-panels-to-aux-bus.patch b/queue-5.15/arm-tegra-move-panels-to-aux-bus.patch new file mode 100644 index 00000000000..f38d0f67556 --- /dev/null +++ b/queue-5.15/arm-tegra-move-panels-to-aux-bus.patch @@ -0,0 +1,112 @@ +From 10bbe62faf7b11c9bb932b40ad53f99d5da178d2 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.15/arm64-dts-juno-remove-gicv2m-dma-range.patch b/queue-5.15/arm64-dts-juno-remove-gicv2m-dma-range.patch new file mode 100644 index 00000000000..0e79358685f --- /dev/null +++ b/queue-5.15/arm64-dts-juno-remove-gicv2m-dma-range.patch @@ -0,0 +1,49 @@ +From ea202775357b1f16e9fdfa759d539c243b159368 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.15/can-etas_es58x-change-opened_channel_cnt-s-type-from.patch b/queue-5.15/can-etas_es58x-change-opened_channel_cnt-s-type-from.patch new file mode 100644 index 00000000000..eda2ac718e7 --- /dev/null +++ b/queue-5.15/can-etas_es58x-change-opened_channel_cnt-s-type-from.patch @@ -0,0 +1,145 @@ +From ce8b5f15f7bfda11ec44de2e67b5dba428452ffc 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 24627ab14626..cd4e7f356e48 100644 +--- a/drivers/net/can/usb/etas_es58x/es58x_core.c ++++ b/drivers/net/can/usb/etas_es58x/es58x_core.c +@@ -1794,7 +1794,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; +@@ -1812,12 +1812,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)); +@@ -1852,7 +1853,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; +@@ -2221,7 +2223,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.15/drm-amdgpu-fix-suspend-resume-hang-regression.patch b/queue-5.15/drm-amdgpu-fix-suspend-resume-hang-regression.patch new file mode 100644 index 00000000000..a01f77e6196 --- /dev/null +++ b/queue-5.15/drm-amdgpu-fix-suspend-resume-hang-regression.patch @@ -0,0 +1,44 @@ +From 264c35048fc1d42f6e7abfa5c47b255b8d4709bd 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 a33cb2f4d744..fd37bb39774c 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.15/drm-bridge-ti-sn65dsi86-properly-undo-autosuspend.patch b/queue-5.15/drm-bridge-ti-sn65dsi86-properly-undo-autosuspend.patch new file mode 100644 index 00000000000..880e55d31c2 --- /dev/null +++ b/queue-5.15/drm-bridge-ti-sn65dsi86-properly-undo-autosuspend.patch @@ -0,0 +1,54 @@ +From 0f77fd637bf0ed205f85c047cfee269bb2f9b95c 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 4d08246f930c..45a5f1e48f0e 100644 +--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c ++++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c +@@ -1473,6 +1473,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); + } + +@@ -1532,11 +1533,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.15/drm-i915-guc-slpc-correct-the-param-count-for-unset-.patch b/queue-5.15/drm-i915-guc-slpc-correct-the-param-count-for-unset-.patch new file mode 100644 index 00000000000..e0a3875cc70 --- /dev/null +++ b/queue-5.15/drm-i915-guc-slpc-correct-the-param-count-for-unset-.patch @@ -0,0 +1,42 @@ +From b1c1647ea710b5c1791c61979eef4ec26cecb399 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.15/e1000e-fix-possible-hw-unit-hang-after-an-s0ix-exit.patch b/queue-5.15/e1000e-fix-possible-hw-unit-hang-after-an-s0ix-exit.patch new file mode 100644 index 00000000000..9866d19bef1 --- /dev/null +++ b/queue-5.15/e1000e-fix-possible-hw-unit-hang-after-an-s0ix-exit.patch @@ -0,0 +1,124 @@ +From f4b307e070d435058fa0b4f451e1e34e684abe36 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 af2029bb43e3..ce48e630fe55 100644 +--- a/drivers/net/ethernet/intel/e1000e/netdev.c ++++ b/drivers/net/ethernet/intel/e1000e/netdev.c +@@ -6992,8 +6992,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); +@@ -7015,6 +7028,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 */ +@@ -7025,6 +7040,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.15/iavf-add-__iavf_init_failed-state.patch b/queue-5.15/iavf-add-__iavf_init_failed-state.patch new file mode 100644 index 00000000000..69e8c994c82 --- /dev/null +++ b/queue-5.15/iavf-add-__iavf_init_failed-state.patch @@ -0,0 +1,160 @@ +From 4d78bbefe42416b6fddd0ee94431c91e152eeb19 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Aug 2021 08:47:49 +0000 +Subject: iavf: Add __IAVF_INIT_FAILED state + +From: Mateusz Palczewski + +[ Upstream commit 59756ad6948be91d66867ce458083b820c59b8ba ] + +This commit adds a new state, __IAVF_INIT_FAILED to the state machine. +From now on initialization functions report errors not by returning an +error value, but by changing the state to indicate that something went +wrong. + +Signed-off-by: Jakub Pawlak +Signed-off-by: Jan Sokolowski +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 | 35 ++++++++++++--------- + 2 files changed, 21 insertions(+), 15 deletions(-) + +diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h +index 20d6c157bcb2..9eb86c86f454 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf.h ++++ b/drivers/net/ethernet/intel/iavf/iavf.h +@@ -178,6 +178,7 @@ enum iavf_state_t { + __IAVF_INIT_VERSION_CHECK, /* aq msg sent, awaiting reply */ + __IAVF_INIT_GET_RESOURCES, /* aq msg sent, awaiting reply */ + __IAVF_INIT_SW, /* got resources, setting up structs */ ++ __IAVF_INIT_FAILED, /* init failed, restarting procedure */ + __IAVF_RESETTING, /* in reset */ + __IAVF_COMM_FAILED, /* communication with PF failed */ + /* Below here, watchdog is running */ +diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c +index 3e60eb9045c3..181d17945bbe 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -14,7 +14,7 @@ + static int iavf_setup_all_tx_resources(struct iavf_adapter *adapter); + static int iavf_setup_all_rx_resources(struct iavf_adapter *adapter); + static int iavf_close(struct net_device *netdev); +-static int iavf_init_get_resources(struct iavf_adapter *adapter); ++static void iavf_init_get_resources(struct iavf_adapter *adapter); + static int iavf_check_reset_complete(struct iavf_hw *hw); + + char iavf_driver_name[] = "iavf"; +@@ -1722,9 +1722,9 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter) + * + * Function process __IAVF_STARTUP driver state. + * When success the state is changed to __IAVF_INIT_VERSION_CHECK +- * when fails it returns -EAGAIN ++ * when fails the state is changed to __IAVF_INIT_FAILED + **/ +-static int iavf_startup(struct iavf_adapter *adapter) ++static void iavf_startup(struct iavf_adapter *adapter) + { + struct pci_dev *pdev = adapter->pdev; + struct iavf_hw *hw = &adapter->hw; +@@ -1764,8 +1764,9 @@ static int iavf_startup(struct iavf_adapter *adapter) + goto err; + } + iavf_change_state(adapter, __IAVF_INIT_VERSION_CHECK); ++ return; + err: +- return err; ++ iavf_change_state(adapter, __IAVF_INIT_FAILED); + } + + /** +@@ -1774,9 +1775,9 @@ static int iavf_startup(struct iavf_adapter *adapter) + * + * Function process __IAVF_INIT_VERSION_CHECK driver state. + * When success the state is changed to __IAVF_INIT_GET_RESOURCES +- * when fails it returns -EAGAIN ++ * when fails the state is changed to __IAVF_INIT_FAILED + **/ +-static int iavf_init_version_check(struct iavf_adapter *adapter) ++static void iavf_init_version_check(struct iavf_adapter *adapter) + { + struct pci_dev *pdev = adapter->pdev; + struct iavf_hw *hw = &adapter->hw; +@@ -1811,8 +1812,9 @@ static int iavf_init_version_check(struct iavf_adapter *adapter) + goto err; + } + iavf_change_state(adapter, __IAVF_INIT_GET_RESOURCES); ++ return; + err: +- return err; ++ iavf_change_state(adapter, __IAVF_INIT_FAILED); + } + + /** +@@ -1822,9 +1824,9 @@ static int iavf_init_version_check(struct iavf_adapter *adapter) + * Function process __IAVF_INIT_GET_RESOURCES driver state and + * finishes driver initialization procedure. + * When success the state is changed to __IAVF_DOWN +- * when fails it returns -EAGAIN ++ * when fails the state is changed to __IAVF_INIT_FAILED + **/ +-static int iavf_init_get_resources(struct iavf_adapter *adapter) ++static void iavf_init_get_resources(struct iavf_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; +@@ -1852,7 +1854,7 @@ static int iavf_init_get_resources(struct iavf_adapter *adapter) + */ + iavf_shutdown_adminq(hw); + dev_err(&pdev->dev, "Unable to get VF config due to PF error condition, not retrying\n"); +- return 0; ++ return; + } + if (err) { + dev_err(&pdev->dev, "Unable to get VF config (%d)\n", err); +@@ -1944,7 +1946,7 @@ static int iavf_init_get_resources(struct iavf_adapter *adapter) + else + iavf_init_rss(adapter); + +- return err; ++ return; + err_mem: + iavf_free_rss(adapter); + err_register: +@@ -1955,7 +1957,7 @@ static int iavf_init_get_resources(struct iavf_adapter *adapter) + kfree(adapter->vf_res); + adapter->vf_res = NULL; + err: +- return err; ++ iavf_change_state(adapter, __IAVF_INIT_FAILED); + } + + /** +@@ -3704,15 +3706,18 @@ static void iavf_init_task(struct work_struct *work) + } + switch (adapter->state) { + case __IAVF_STARTUP: +- if (iavf_startup(adapter) < 0) ++ iavf_startup(adapter); ++ if (adapter->state == __IAVF_INIT_FAILED) + goto init_failed; + break; + case __IAVF_INIT_VERSION_CHECK: +- if (iavf_init_version_check(adapter) < 0) ++ iavf_init_version_check(adapter); ++ if (adapter->state == __IAVF_INIT_FAILED) + goto init_failed; + break; + case __IAVF_INIT_GET_RESOURCES: +- if (iavf_init_get_resources(adapter) < 0) ++ iavf_init_get_resources(adapter); ++ if (adapter->state == __IAVF_INIT_FAILED) + goto init_failed; + goto out; + default: +-- +2.34.1 + diff --git a/queue-5.15/iavf-add-helper-function-to-go-from-pci_dev-to-adapt.patch b/queue-5.15/iavf-add-helper-function-to-go-from-pci_dev-to-adapt.patch new file mode 100644 index 00000000000..c8280b549fa --- /dev/null +++ b/queue-5.15/iavf-add-helper-function-to-go-from-pci_dev-to-adapt.patch @@ -0,0 +1,90 @@ +From 4ec871ca764acf3e43e44815885546ec42333d00 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Sep 2021 08:41:23 +0200 +Subject: iavf: Add helper function to go from pci_dev to adapter + +From: Karen Sornek + +[ Upstream commit 247aa001b72b6c8a89df9d108a2ec6f274a6b64d ] + +Add helper function to go from pci_dev to adapter to make work simple - +to go from a pci_dev to the adapter structure and make netdev assignment +instead of having to go to the net_device then the adapter. + +Signed-off-by: Brett Creeley +Signed-off-by: Karen Sornek +Tested-by: Konrad Jankowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/iavf/iavf_main.c | 24 +++++++++++++++------ + 1 file changed, 17 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c +index 3aa21568686d..33a3dbcf8f2d 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -51,6 +51,15 @@ MODULE_LICENSE("GPL v2"); + static const struct net_device_ops iavf_netdev_ops; + struct workqueue_struct *iavf_wq; + ++/** ++ * iavf_pdev_to_adapter - go from pci_dev to adapter ++ * @pdev: pci_dev pointer ++ */ ++static struct iavf_adapter *iavf_pdev_to_adapter(struct pci_dev *pdev) ++{ ++ return netdev_priv(pci_get_drvdata(pdev)); ++} ++ + /** + * iavf_allocate_dma_mem_d - OS specific memory alloc for shared code + * @hw: pointer to the HW structure +@@ -3739,8 +3748,8 @@ int iavf_process_config(struct iavf_adapter *adapter) + **/ + static void iavf_shutdown(struct pci_dev *pdev) + { +- struct net_device *netdev = pci_get_drvdata(pdev); +- struct iavf_adapter *adapter = netdev_priv(netdev); ++ struct iavf_adapter *adapter = iavf_pdev_to_adapter(pdev); ++ struct net_device *netdev = adapter->netdev; + + netif_device_detach(netdev); + +@@ -3923,10 +3932,11 @@ static int __maybe_unused iavf_suspend(struct device *dev_d) + static int __maybe_unused iavf_resume(struct device *dev_d) + { + struct pci_dev *pdev = to_pci_dev(dev_d); +- struct net_device *netdev = pci_get_drvdata(pdev); +- struct iavf_adapter *adapter = netdev_priv(netdev); ++ struct iavf_adapter *adapter; + u32 err; + ++ adapter = iavf_pdev_to_adapter(pdev); ++ + pci_set_master(pdev); + + rtnl_lock(); +@@ -3945,7 +3955,7 @@ static int __maybe_unused iavf_resume(struct device *dev_d) + + queue_work(iavf_wq, &adapter->reset_task); + +- netif_device_attach(netdev); ++ netif_device_attach(adapter->netdev); + + return err; + } +@@ -3961,8 +3971,8 @@ static int __maybe_unused iavf_resume(struct device *dev_d) + **/ + static void iavf_remove(struct pci_dev *pdev) + { +- struct net_device *netdev = pci_get_drvdata(pdev); +- struct iavf_adapter *adapter = netdev_priv(netdev); ++ struct iavf_adapter *adapter = iavf_pdev_to_adapter(pdev); ++ struct net_device *netdev = adapter->netdev; + struct iavf_fdir_fltr *fdir, *fdirtmp; + struct iavf_vlan_filter *vlf, *vlftmp; + struct iavf_adv_rss *rss, *rsstmp; +-- +2.34.1 + diff --git a/queue-5.15/iavf-add-trace-while-removing-device.patch b/queue-5.15/iavf-add-trace-while-removing-device.patch new file mode 100644 index 00000000000..555a1895e98 --- /dev/null +++ b/queue-5.15/iavf-add-trace-while-removing-device.patch @@ -0,0 +1,40 @@ +From 359da61e4686555ad78467d19b5c7f9fa78cf15b 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 7bc8b646e37c..75fab4ea42b6 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -3985,6 +3985,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.15/iavf-add-waiting-so-the-port-is-initialized-in-remov.patch b/queue-5.15/iavf-add-waiting-so-the-port-is-initialized-in-remov.patch new file mode 100644 index 00000000000..26b791054b6 --- /dev/null +++ b/queue-5.15/iavf-add-waiting-so-the-port-is-initialized-in-remov.patch @@ -0,0 +1,91 @@ +From f1c2cece1a86bc8d7c23daeffaa1448b64eb7f59 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 e97a8dbbbc89..60e6f55c6dc5 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -3979,7 +3979,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; +@@ -3989,6 +3988,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; +@@ -4026,16 +4041,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.15/iavf-combine-init-and-watchdog-state-machines.patch b/queue-5.15/iavf-combine-init-and-watchdog-state-machines.patch new file mode 100644 index 00000000000..102c3fe99d9 --- /dev/null +++ b/queue-5.15/iavf-combine-init-and-watchdog-state-machines.patch @@ -0,0 +1,262 @@ +From 66e8366ede742f4857607296d9454b7670223a66 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Aug 2021 08:47:58 +0000 +Subject: iavf: Combine init and watchdog state machines + +From: Mateusz Palczewski + +[ Upstream commit 898ef1cb1cb24040c3e89263e02c605af70c776a ] + +Use single state machine for driver initialization and for service +initialized driver. The init state machine implemented in init_task() +is merged into the watchdog_task(). The init_task() function is +removed. + +Signed-off-by: Jakub Pawlak +Signed-off-by: Jan Sokolowski +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 | 136 ++++++++------------ + 2 files changed, 57 insertions(+), 80 deletions(-) + +diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h +index 9eb86c86f454..00d1ea313918 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf.h ++++ b/drivers/net/ethernet/intel/iavf/iavf.h +@@ -227,7 +227,6 @@ struct iavf_adapter { + struct work_struct reset_task; + struct work_struct adminq_task; + struct delayed_work client_task; +- struct delayed_work init_task; + wait_queue_head_t down_waitqueue; + struct iavf_q_vector *q_vectors; + struct list_head vlan_filter_list; +diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c +index 181d17945bbe..7bc8b646e37c 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -1978,7 +1978,48 @@ 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); ++ adapter->aq_required = 0; ++ adapter->current_op = VIRTCHNL_OP_UNKNOWN; ++ } ++ + switch (adapter->state) { ++ case __IAVF_STARTUP: ++ iavf_startup(adapter); ++ mutex_unlock(&adapter->crit_lock); ++ queue_delayed_work(iavf_wq, &adapter->watchdog_task, ++ msecs_to_jiffies(30)); ++ return; ++ case __IAVF_INIT_VERSION_CHECK: ++ iavf_init_version_check(adapter); ++ mutex_unlock(&adapter->crit_lock); ++ queue_delayed_work(iavf_wq, &adapter->watchdog_task, ++ msecs_to_jiffies(30)); ++ return; ++ case __IAVF_INIT_GET_RESOURCES: ++ iavf_init_get_resources(adapter); ++ mutex_unlock(&adapter->crit_lock); ++ queue_delayed_work(iavf_wq, &adapter->watchdog_task, ++ msecs_to_jiffies(1)); ++ return; ++ case __IAVF_INIT_FAILED: ++ if (++adapter->aq_wait_count > IAVF_AQ_MAX_ERR) { ++ dev_err(&adapter->pdev->dev, ++ "Failed to communicate with PF; waiting before retry\n"); ++ adapter->flags |= IAVF_FLAG_PF_COMMS_FAILED; ++ iavf_shutdown_adminq(hw); ++ mutex_unlock(&adapter->crit_lock); ++ queue_delayed_work(iavf_wq, ++ &adapter->watchdog_task, (5 * HZ)); ++ return; ++ } ++ /* Try again from failed step*/ ++ iavf_change_state(adapter, adapter->last_state); ++ mutex_unlock(&adapter->crit_lock); ++ queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ); ++ return; + case __IAVF_COMM_FAILED: + reg_val = rd32(hw, IAVF_VFGEN_RSTAT) & + IAVF_VFGEN_RSTAT_VFR_STATE_MASK; +@@ -1987,23 +2028,19 @@ static void iavf_watchdog_task(struct work_struct *work) + /* A chance for redemption! */ + dev_err(&adapter->pdev->dev, + "Hardware came out of reset. Attempting reinit.\n"); +- iavf_change_state(adapter, __IAVF_STARTUP); +- adapter->flags &= ~IAVF_FLAG_PF_COMMS_FAILED; +- queue_delayed_work(iavf_wq, &adapter->init_task, 10); +- mutex_unlock(&adapter->crit_lock); +- /* Don't reschedule the watchdog, since we've restarted +- * the init task. When init_task contacts the PF and ++ /* When init task contacts the PF and + * gets everything set up again, it'll restart the + * watchdog for us. Down, boy. Sit. Stay. Woof. + */ +- return; ++ iavf_change_state(adapter, __IAVF_STARTUP); ++ adapter->flags &= ~IAVF_FLAG_PF_COMMS_FAILED; + } + adapter->aq_required = 0; + adapter->current_op = VIRTCHNL_OP_UNKNOWN; + queue_delayed_work(iavf_wq, + &adapter->watchdog_task, + msecs_to_jiffies(10)); +- goto watchdog_done; ++ return; + case __IAVF_RESETTING: + mutex_unlock(&adapter->crit_lock); + queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ * 2); +@@ -2026,12 +2063,14 @@ static void iavf_watchdog_task(struct work_struct *work) + adapter->state == __IAVF_RUNNING) + iavf_request_stats(adapter); + } ++ if (adapter->state == __IAVF_RUNNING) ++ iavf_detect_recover_hung(&adapter->vsi); + break; + case __IAVF_REMOVE: + mutex_unlock(&adapter->crit_lock); + return; + default: +- goto restart_watchdog; ++ return; + } + + /* check for hw reset */ +@@ -2043,22 +2082,21 @@ static void iavf_watchdog_task(struct work_struct *work) + adapter->current_op = VIRTCHNL_OP_UNKNOWN; + dev_err(&adapter->pdev->dev, "Hardware reset detected\n"); + queue_work(iavf_wq, &adapter->reset_task); +- goto watchdog_done; ++ mutex_unlock(&adapter->crit_lock); ++ queue_delayed_work(iavf_wq, ++ &adapter->watchdog_task, HZ * 2); ++ return; + } + + schedule_delayed_work(&adapter->client_task, msecs_to_jiffies(5)); +-watchdog_done: +- if (adapter->state == __IAVF_RUNNING || +- adapter->state == __IAVF_COMM_FAILED) +- iavf_detect_recover_hung(&adapter->vsi); + mutex_unlock(&adapter->crit_lock); + restart_watchdog: ++ queue_work(iavf_wq, &adapter->adminq_task); + if (adapter->aq_required) + queue_delayed_work(iavf_wq, &adapter->watchdog_task, + msecs_to_jiffies(20)); + else + queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ * 2); +- queue_work(iavf_wq, &adapter->adminq_task); + } + + static void iavf_disable_vf(struct iavf_adapter *adapter) +@@ -2339,6 +2377,8 @@ static void iavf_reset_task(struct work_struct *work) + reset_err: + mutex_unlock(&adapter->client_lock); + mutex_unlock(&adapter->crit_lock); ++ if (running) ++ iavf_change_state(adapter, __IAVF_RUNNING); + dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n"); + iavf_close(netdev); + } +@@ -3681,67 +3721,6 @@ int iavf_process_config(struct iavf_adapter *adapter) + return 0; + } + +-/** +- * iavf_init_task - worker thread to perform delayed initialization +- * @work: pointer to work_struct containing our data +- * +- * This task completes the work that was begun in probe. Due to the nature +- * of VF-PF communications, we may need to wait tens of milliseconds to get +- * responses back from the PF. Rather than busy-wait in probe and bog down the +- * whole system, we'll do it in a task so we can sleep. +- * This task only runs during driver init. Once we've established +- * communications with the PF driver and set up our netdev, the watchdog +- * takes over. +- **/ +-static void iavf_init_task(struct work_struct *work) +-{ +- struct iavf_adapter *adapter = container_of(work, +- struct iavf_adapter, +- init_task.work); +- struct iavf_hw *hw = &adapter->hw; +- +- if (iavf_lock_timeout(&adapter->crit_lock, 5000)) { +- dev_warn(&adapter->pdev->dev, "failed to acquire crit_lock in %s\n", __FUNCTION__); +- return; +- } +- switch (adapter->state) { +- case __IAVF_STARTUP: +- iavf_startup(adapter); +- if (adapter->state == __IAVF_INIT_FAILED) +- goto init_failed; +- break; +- case __IAVF_INIT_VERSION_CHECK: +- iavf_init_version_check(adapter); +- if (adapter->state == __IAVF_INIT_FAILED) +- goto init_failed; +- break; +- case __IAVF_INIT_GET_RESOURCES: +- iavf_init_get_resources(adapter); +- if (adapter->state == __IAVF_INIT_FAILED) +- goto init_failed; +- goto out; +- default: +- goto init_failed; +- } +- +- queue_delayed_work(iavf_wq, &adapter->init_task, +- msecs_to_jiffies(30)); +- goto out; +-init_failed: +- if (++adapter->aq_wait_count > IAVF_AQ_MAX_ERR) { +- dev_err(&adapter->pdev->dev, +- "Failed to communicate with PF; waiting before retry\n"); +- adapter->flags |= IAVF_FLAG_PF_COMMS_FAILED; +- iavf_shutdown_adminq(hw); +- iavf_change_state(adapter, __IAVF_STARTUP); +- queue_delayed_work(iavf_wq, &adapter->init_task, HZ * 5); +- goto out; +- } +- queue_delayed_work(iavf_wq, &adapter->init_task, HZ); +-out: +- mutex_unlock(&adapter->crit_lock); +-} +- + /** + * iavf_shutdown - Shutdown the device in preparation for a reboot + * @pdev: pci device structure +@@ -3876,8 +3855,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + INIT_WORK(&adapter->adminq_task, iavf_adminq_task); + INIT_DELAYED_WORK(&adapter->watchdog_task, iavf_watchdog_task); + INIT_DELAYED_WORK(&adapter->client_task, iavf_client_task); +- INIT_DELAYED_WORK(&adapter->init_task, iavf_init_task); +- queue_delayed_work(iavf_wq, &adapter->init_task, ++ queue_delayed_work(iavf_wq, &adapter->watchdog_task, + msecs_to_jiffies(5 * (pdev->devfn & 0x07))); + + /* Setup the wait queue for indicating transition to down status */ +@@ -3983,8 +3961,8 @@ static void iavf_remove(struct pci_dev *pdev) + int err; + /* Indicate we are in remove and not to run reset_task */ + mutex_lock(&adapter->remove_lock); +- cancel_delayed_work_sync(&adapter->init_task); + 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); +-- +2.34.1 + diff --git a/queue-5.15/iavf-fix-__iavf_resetting-state-usage.patch b/queue-5.15/iavf-fix-__iavf_resetting-state-usage.patch new file mode 100644 index 00000000000..688fca124ab --- /dev/null +++ b/queue-5.15/iavf-fix-__iavf_resetting-state-usage.patch @@ -0,0 +1,75 @@ +From 0483197111c0b2fed7c949ebfed82c4ac2feef1b 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 e23a062dc39c..50ecfb1faf61 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) { +@@ -2290,8 +2290,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) { + netif_carrier_off(netdev); +-- +2.34.1 + diff --git a/queue-5.15/iavf-fix-init-state-closure-on-remove.patch b/queue-5.15/iavf-fix-init-state-closure-on-remove.patch new file mode 100644 index 00000000000..a78fefd802a --- /dev/null +++ b/queue-5.15/iavf-fix-init-state-closure-on-remove.patch @@ -0,0 +1,120 @@ +From 790378f852c366075d30217b4dd06e201a886008 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 60e6f55c6dc5..57ecdff870a1 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 || +@@ -3988,13 +4008,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.15/iavf-fix-kernel-bug-in-free_msi_irqs.patch b/queue-5.15/iavf-fix-kernel-bug-in-free_msi_irqs.patch new file mode 100644 index 00000000000..dd6438eeef9 --- /dev/null +++ b/queue-5.15/iavf-fix-kernel-bug-in-free_msi_irqs.patch @@ -0,0 +1,166 @@ +From c921be40859f3feb324c0dc6cc21740bdd73ce87 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Oct 2021 10:30:14 +0200 +Subject: iavf: Fix kernel BUG in free_msi_irqs + +From: Przemyslaw Patynowski + +[ Upstream commit 605ca7c5c670762e36ccb475cfa089d7ad0698e0 ] + +Fix driver not freeing VF's traffic irqs, prior to calling +pci_disable_msix in iavf_remove. +There were possible 2 erroneous states in which, iavf_close would +not be called. +One erroneous state is fixed by allowing netdev to register, when state +is already running. It was possible for VF adapter to enter state loop +from running to resetting, where iavf_open would subsequently fail. +If user would then unload driver/remove VF pci, iavf_close would not be +called, as the netdev was not registered, leaving traffic pcis still +allocated. +Fixed this by breaking loop, allowing netdev to open device when adapter +state is __IAVF_RUNNING and it is not explicitily downed. +Other possiblity is entering to iavf_remove from __IAVF_RESETTING state, +where iavf_close would not free irqs, but just return 0. +Fixed this by checking for last adapter state and then removing irqs. + +Kernel panic: +[ 2773.628585] kernel BUG at drivers/pci/msi.c:375! +... +[ 2773.631567] RIP: 0010:free_msi_irqs+0x180/0x1b0 +... +[ 2773.640939] Call Trace: +[ 2773.641572] pci_disable_msix+0xf7/0x120 +[ 2773.642224] iavf_reset_interrupt_capability.part.41+0x15/0x30 [iavf] +[ 2773.642897] iavf_remove+0x12e/0x500 [iavf] +[ 2773.643578] pci_device_remove+0x3b/0xc0 +[ 2773.644266] device_release_driver_internal+0x103/0x1f0 +[ 2773.644948] pci_stop_bus_device+0x69/0x90 +[ 2773.645576] pci_stop_and_remove_bus_device+0xe/0x20 +[ 2773.646215] pci_iov_remove_virtfn+0xba/0x120 +[ 2773.646862] sriov_disable+0x2f/0xe0 +[ 2773.647531] ice_free_vfs+0x2f8/0x350 [ice] +[ 2773.648207] ice_sriov_configure+0x94/0x960 [ice] +[ 2773.648883] ? _kstrtoull+0x3b/0x90 +[ 2773.649560] sriov_numvfs_store+0x10a/0x190 +[ 2773.650249] kernfs_fop_write+0x116/0x190 +[ 2773.650948] vfs_write+0xa5/0x1a0 +[ 2773.651651] ksys_write+0x4f/0xb0 +[ 2773.652358] do_syscall_64+0x5b/0x1a0 +[ 2773.653075] entry_SYSCALL_64_after_hwframe+0x65/0xca + +Fixes: 22ead37f8af8 ("i40evf: Add longer wait after remove module") +Signed-off-by: Przemyslaw Patynowski +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 | 36 +++++++++++++++++++++ + drivers/net/ethernet/intel/iavf/iavf_main.c | 20 ++++++++++++ + 2 files changed, 56 insertions(+) + +diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h +index 997c45f2c542..21e0f3361560 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf.h ++++ b/drivers/net/ethernet/intel/iavf/iavf.h +@@ -395,6 +395,38 @@ struct iavf_device { + extern char iavf_driver_name[]; + extern struct workqueue_struct *iavf_wq; + ++static inline const char *iavf_state_str(enum iavf_state_t state) ++{ ++ switch (state) { ++ case __IAVF_STARTUP: ++ return "__IAVF_STARTUP"; ++ case __IAVF_REMOVE: ++ return "__IAVF_REMOVE"; ++ case __IAVF_INIT_VERSION_CHECK: ++ return "__IAVF_INIT_VERSION_CHECK"; ++ case __IAVF_INIT_GET_RESOURCES: ++ return "__IAVF_INIT_GET_RESOURCES"; ++ case __IAVF_INIT_SW: ++ return "__IAVF_INIT_SW"; ++ case __IAVF_INIT_FAILED: ++ return "__IAVF_INIT_FAILED"; ++ case __IAVF_RESETTING: ++ return "__IAVF_RESETTING"; ++ case __IAVF_COMM_FAILED: ++ return "__IAVF_COMM_FAILED"; ++ case __IAVF_DOWN: ++ return "__IAVF_DOWN"; ++ case __IAVF_DOWN_PENDING: ++ return "__IAVF_DOWN_PENDING"; ++ case __IAVF_TESTING: ++ return "__IAVF_TESTING"; ++ case __IAVF_RUNNING: ++ return "__IAVF_RUNNING"; ++ default: ++ return "__IAVF_UNKNOWN_STATE"; ++ } ++} ++ + static inline void iavf_change_state(struct iavf_adapter *adapter, + enum iavf_state_t state) + { +@@ -402,6 +434,10 @@ static inline void iavf_change_state(struct iavf_adapter *adapter, + adapter->last_state = adapter->state; + adapter->state = state; + } ++ dev_dbg(&adapter->pdev->dev, ++ "state transition from:%s to:%s\n", ++ iavf_state_str(adapter->last_state), ++ iavf_state_str(adapter->state)); + } + + int iavf_up(struct iavf_adapter *adapter); +diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c +index 33a3dbcf8f2d..e97a8dbbbc89 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -3325,6 +3325,13 @@ static int iavf_open(struct net_device *netdev) + goto err_unlock; + } + ++ if (adapter->state == __IAVF_RUNNING && ++ !test_bit(__IAVF_VSI_DOWN, adapter->vsi.state)) { ++ dev_dbg(&adapter->pdev->dev, "VF is already open.\n"); ++ err = 0; ++ goto err_unlock; ++ } ++ + /* allocate transmit descriptors */ + err = iavf_setup_all_tx_resources(adapter); + if (err) +@@ -3972,6 +3979,7 @@ 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; +@@ -4013,9 +4021,21 @@ static void iavf_remove(struct pci_dev *pdev) + + adapter->aq_required = 0; + adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED; ++ + iavf_free_all_tx_resources(adapter); + 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.15/iavf-fix-locking-for-virtchnl_op_get_offload_vlan_v2.patch b/queue-5.15/iavf-fix-locking-for-virtchnl_op_get_offload_vlan_v2.patch new file mode 100644 index 00000000000..d7055e09365 --- /dev/null +++ b/queue-5.15/iavf-fix-locking-for-virtchnl_op_get_offload_vlan_v2.patch @@ -0,0 +1,123 @@ +From b36169a9af44c73b062f68498b056fec6cb8ee9f 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 57ecdff870a1..d11e172252b4 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -2463,6 +2463,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) +@@ -4027,8 +4039,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 845976a9ec5f..8a1c293b8c7a 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.15/iavf-fix-race-in-init-state.patch b/queue-5.15/iavf-fix-race-in-init-state.patch new file mode 100644 index 00000000000..dfcb932c3b2 --- /dev/null +++ b/queue-5.15/iavf-fix-race-in-init-state.patch @@ -0,0 +1,51 @@ +From 02e7c0894901fbaea41b72ab85c52b58e299099b 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 d11e172252b4..e23a062dc39c 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -2125,7 +2125,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.15/iavf-refactor-iavf-state-machine-tracking.patch b/queue-5.15/iavf-refactor-iavf-state-machine-tracking.patch new file mode 100644 index 00000000000..9f8a35887b6 --- /dev/null +++ b/queue-5.15/iavf-refactor-iavf-state-machine-tracking.patch @@ -0,0 +1,234 @@ +From 2e835ccfc0315c5328a11cf6e91a93fe53f8537f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Aug 2021 08:47:40 +0000 +Subject: iavf: Refactor iavf state machine tracking + +From: Mateusz Palczewski + +[ Upstream commit 45eebd62999d37d13568723524b99d828e0ce22c ] + +Replace state changes of iavf state machine +with a method that also tracks the previous +state the machine was on. + +This change is required for further work with +refactoring init and watchdog state machines. + +Tracking of previous state would help us +recover iavf after failure has occurred. + +Signed-off-by: Jakub Pawlak +Signed-off-by: Jan Sokolowski +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 | 10 +++++ + drivers/net/ethernet/intel/iavf/iavf_main.c | 37 ++++++++++--------- + .../net/ethernet/intel/iavf/iavf_virtchnl.c | 2 +- + 3 files changed, 31 insertions(+), 18 deletions(-) + +diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h +index 0ae6da2992d0..20d6c157bcb2 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf.h ++++ b/drivers/net/ethernet/intel/iavf/iavf.h +@@ -314,6 +314,7 @@ struct iavf_adapter { + struct iavf_hw hw; /* defined in iavf_type.h */ + + enum iavf_state_t state; ++ enum iavf_state_t last_state; + unsigned long crit_section; + + struct delayed_work watchdog_task; +@@ -395,6 +396,15 @@ struct iavf_device { + extern char iavf_driver_name[]; + extern struct workqueue_struct *iavf_wq; + ++static inline void iavf_change_state(struct iavf_adapter *adapter, ++ enum iavf_state_t state) ++{ ++ if (adapter->state != state) { ++ adapter->last_state = adapter->state; ++ adapter->state = state; ++ } ++} ++ + int iavf_up(struct iavf_adapter *adapter); + void iavf_down(struct iavf_adapter *adapter); + int iavf_process_config(struct iavf_adapter *adapter); +diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c +index 62f66f9aa722..3e60eb9045c3 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -990,7 +990,7 @@ static void iavf_configure(struct iavf_adapter *adapter) + **/ + static void iavf_up_complete(struct iavf_adapter *adapter) + { +- adapter->state = __IAVF_RUNNING; ++ iavf_change_state(adapter, __IAVF_RUNNING); + clear_bit(__IAVF_VSI_DOWN, adapter->vsi.state); + + iavf_napi_enable_all(adapter); +@@ -1763,7 +1763,7 @@ static int iavf_startup(struct iavf_adapter *adapter) + iavf_shutdown_adminq(hw); + goto err; + } +- adapter->state = __IAVF_INIT_VERSION_CHECK; ++ iavf_change_state(adapter, __IAVF_INIT_VERSION_CHECK); + err: + return err; + } +@@ -1787,7 +1787,7 @@ static int iavf_init_version_check(struct iavf_adapter *adapter) + if (!iavf_asq_done(hw)) { + dev_err(&pdev->dev, "Admin queue command never completed\n"); + iavf_shutdown_adminq(hw); +- adapter->state = __IAVF_STARTUP; ++ iavf_change_state(adapter, __IAVF_STARTUP); + goto err; + } + +@@ -1810,8 +1810,7 @@ static int iavf_init_version_check(struct iavf_adapter *adapter) + err); + goto err; + } +- adapter->state = __IAVF_INIT_GET_RESOURCES; +- ++ iavf_change_state(adapter, __IAVF_INIT_GET_RESOURCES); + err: + return err; + } +@@ -1927,7 +1926,7 @@ static int iavf_init_get_resources(struct iavf_adapter *adapter) + if (netdev->features & NETIF_F_GRO) + dev_info(&pdev->dev, "GRO is enabled\n"); + +- adapter->state = __IAVF_DOWN; ++ iavf_change_state(adapter, __IAVF_DOWN); + set_bit(__IAVF_VSI_DOWN, adapter->vsi.state); + rtnl_unlock(); + +@@ -1975,7 +1974,7 @@ static void iavf_watchdog_task(struct work_struct *work) + goto restart_watchdog; + + if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED) +- adapter->state = __IAVF_COMM_FAILED; ++ iavf_change_state(adapter, __IAVF_COMM_FAILED); + + switch (adapter->state) { + case __IAVF_COMM_FAILED: +@@ -1986,7 +1985,7 @@ static void iavf_watchdog_task(struct work_struct *work) + /* A chance for redemption! */ + dev_err(&adapter->pdev->dev, + "Hardware came out of reset. Attempting reinit.\n"); +- adapter->state = __IAVF_STARTUP; ++ iavf_change_state(adapter, __IAVF_STARTUP); + adapter->flags &= ~IAVF_FLAG_PF_COMMS_FAILED; + queue_delayed_work(iavf_wq, &adapter->init_task, 10); + mutex_unlock(&adapter->crit_lock); +@@ -2033,9 +2032,10 @@ static void iavf_watchdog_task(struct work_struct *work) + goto restart_watchdog; + } + +- /* check for hw reset */ ++ /* check for hw reset */ + reg_val = rd32(hw, IAVF_VF_ARQLEN1) & IAVF_VF_ARQLEN1_ARQENABLE_MASK; + if (!reg_val) { ++ iavf_change_state(adapter, __IAVF_RESETTING); + adapter->flags |= IAVF_FLAG_RESET_PENDING; + adapter->aq_required = 0; + adapter->current_op = VIRTCHNL_OP_UNKNOWN; +@@ -2115,7 +2115,7 @@ static void iavf_disable_vf(struct iavf_adapter *adapter) + adapter->netdev->flags &= ~IFF_UP; + mutex_unlock(&adapter->crit_lock); + adapter->flags &= ~IAVF_FLAG_RESET_PENDING; +- adapter->state = __IAVF_DOWN; ++ iavf_change_state(adapter, __IAVF_DOWN); + wake_up(&adapter->down_waitqueue); + dev_info(&adapter->pdev->dev, "Reset task did not complete, VF disabled\n"); + } +@@ -2226,7 +2226,7 @@ static void iavf_reset_task(struct work_struct *work) + } + iavf_irq_disable(adapter); + +- adapter->state = __IAVF_RESETTING; ++ iavf_change_state(adapter, __IAVF_RESETTING); + adapter->flags &= ~IAVF_FLAG_RESET_PENDING; + + /* free the Tx/Rx rings and descriptors, might be better to just +@@ -2320,11 +2320,14 @@ static void iavf_reset_task(struct work_struct *work) + + iavf_configure(adapter); + ++ /* iavf_up_complete() will switch device back ++ * to __IAVF_RUNNING ++ */ + iavf_up_complete(adapter); + + iavf_irq_enable(adapter, true); + } else { +- adapter->state = __IAVF_DOWN; ++ iavf_change_state(adapter, __IAVF_DOWN); + wake_up(&adapter->down_waitqueue); + } + mutex_unlock(&adapter->client_lock); +@@ -3334,7 +3337,7 @@ static int iavf_close(struct net_device *netdev) + adapter->flags |= IAVF_FLAG_CLIENT_NEEDS_CLOSE; + + iavf_down(adapter); +- adapter->state = __IAVF_DOWN_PENDING; ++ iavf_change_state(adapter, __IAVF_DOWN_PENDING); + iavf_free_traffic_irqs(adapter); + + mutex_unlock(&adapter->crit_lock); +@@ -3725,7 +3728,7 @@ static void iavf_init_task(struct work_struct *work) + "Failed to communicate with PF; waiting before retry\n"); + adapter->flags |= IAVF_FLAG_PF_COMMS_FAILED; + iavf_shutdown_adminq(hw); +- adapter->state = __IAVF_STARTUP; ++ iavf_change_state(adapter, __IAVF_STARTUP); + queue_delayed_work(iavf_wq, &adapter->init_task, HZ * 5); + goto out; + } +@@ -3751,7 +3754,7 @@ static void iavf_shutdown(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__); + /* Prevent the watchdog from running. */ +- adapter->state = __IAVF_REMOVE; ++ iavf_change_state(adapter, __IAVF_REMOVE); + adapter->aq_required = 0; + mutex_unlock(&adapter->crit_lock); + +@@ -3824,7 +3827,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + hw->back = adapter; + + adapter->msg_enable = BIT(DEFAULT_DEBUG_LEVEL_SHIFT) - 1; +- adapter->state = __IAVF_STARTUP; ++ iavf_change_state(adapter, __IAVF_STARTUP); + + /* Call save state here because it relies on the adapter struct. */ + pci_save_state(pdev); +@@ -4000,7 +4003,7 @@ static void iavf_remove(struct pci_dev *pdev) + dev_warn(&adapter->pdev->dev, "failed to acquire crit_lock in %s\n", __FUNCTION__); + + /* Shut down all the garbage mashers on the detention level */ +- adapter->state = __IAVF_REMOVE; ++ iavf_change_state(adapter, __IAVF_REMOVE); + adapter->aq_required = 0; + adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED; + iavf_free_all_tx_resources(adapter); +diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c +index 08302ab35d68..845976a9ec5f 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c +@@ -1776,7 +1776,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, + iavf_free_all_tx_resources(adapter); + iavf_free_all_rx_resources(adapter); + if (adapter->state == __IAVF_DOWN_PENDING) { +- adapter->state = __IAVF_DOWN; ++ iavf_change_state(adapter, __IAVF_DOWN); + wake_up(&adapter->down_waitqueue); + } + break; +-- +2.34.1 + diff --git a/queue-5.15/iavf-rework-mutexes-for-better-synchronisation.patch b/queue-5.15/iavf-rework-mutexes-for-better-synchronisation.patch new file mode 100644 index 00000000000..d140f51d247 --- /dev/null +++ b/queue-5.15/iavf-rework-mutexes-for-better-synchronisation.patch @@ -0,0 +1,216 @@ +From 549a40f97169b5d19e76b085277b1d82730fb64c 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 00d1ea313918..997c45f2c542 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 75fab4ea42b6..3aa21568686d 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -293,8 +293,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; + } +@@ -1972,8 +1973,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); +@@ -2185,13 +2190,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)) { +@@ -2401,13 +2406,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); +@@ -3368,11 +3379,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)) +@@ -3836,7 +3848,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); + +@@ -3959,11 +3970,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; +@@ -3975,6 +3982,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. */ +@@ -3982,25 +3993,22 @@ 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); + 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) +@@ -4012,8 +4020,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.15/ibmvnic-complete-init_done-on-transport-events.patch b/queue-5.15/ibmvnic-complete-init_done-on-transport-events.patch new file mode 100644 index 00000000000..60351a9b5f6 --- /dev/null +++ b/queue-5.15/ibmvnic-complete-init_done-on-transport-events.patch @@ -0,0 +1,42 @@ +From 139c3c07dd51d87c2e8107da620d3d04f3c311d4 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 088c764fe3cd..404921418f42 100644 +--- a/drivers/net/ethernet/ibm/ibmvnic.c ++++ b/drivers/net/ethernet/ibm/ibmvnic.c +@@ -5178,6 +5178,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.15/ibmvnic-define-flush_reset_queue-helper.patch b/queue-5.15/ibmvnic-define-flush_reset_queue-helper.patch new file mode 100644 index 00000000000..f77b6dfb6d7 --- /dev/null +++ b/queue-5.15/ibmvnic-define-flush_reset_queue-helper.patch @@ -0,0 +1,68 @@ +From d6b0a4973f68876e4122c5c7e9c250bb8e3084b3 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 e98f7d3f935d..088c764fe3cd 100644 +--- a/drivers/net/ethernet/ibm/ibmvnic.c ++++ b/drivers/net/ethernet/ibm/ibmvnic.c +@@ -2557,12 +2557,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; + +@@ -2605,12 +2616,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.15/ibmvnic-initialize-rc-before-completing-wait.patch b/queue-5.15/ibmvnic-initialize-rc-before-completing-wait.patch new file mode 100644 index 00000000000..ce8d00e74b7 --- /dev/null +++ b/queue-5.15/ibmvnic-initialize-rc-before-completing-wait.patch @@ -0,0 +1,39 @@ +From 76b12c922ec1e8f98d732bb471a2929864ab5533 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 52eb6629328c..e98f7d3f935d 100644 +--- a/drivers/net/ethernet/ibm/ibmvnic.c ++++ b/drivers/net/ethernet/ibm/ibmvnic.c +@@ -5145,9 +5145,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.15/iommu-amd-fix-i-o-page-table-memory-leak.patch b/queue-5.15/iommu-amd-fix-i-o-page-table-memory-leak.patch new file mode 100644 index 00000000000..849f21fec31 --- /dev/null +++ b/queue-5.15/iommu-amd-fix-i-o-page-table-memory-leak.patch @@ -0,0 +1,61 @@ +From 7656e2f87a4d5b925445c4ede4ceae460151c4bc 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.15/iommu-amd-simplify-pagetable-freeing.patch b/queue-5.15/iommu-amd-simplify-pagetable-freeing.patch new file mode 100644 index 00000000000..31c087acd29 --- /dev/null +++ b/queue-5.15/iommu-amd-simplify-pagetable-freeing.patch @@ -0,0 +1,169 @@ +From 3ccd31a933e9a08a64a803d7fda5cb64a48e5229 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.15/iommu-amd-use-put_pages_list.patch b/queue-5.15/iommu-amd-use-put_pages_list.patch new file mode 100644 index 00000000000..db2022279b9 --- /dev/null +++ b/queue-5.15/iommu-amd-use-put_pages_list.patch @@ -0,0 +1,173 @@ +From 9b97aa7b7e805cb43fde64554473bfd458dad907 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.15/mips-ralink-mt7621-do-memory-detection-on-kseg1.patch b/queue-5.15/mips-ralink-mt7621-do-memory-detection-on-kseg1.patch new file mode 100644 index 00000000000..7cabd2b063f --- /dev/null +++ b/queue-5.15/mips-ralink-mt7621-do-memory-detection-on-kseg1.patch @@ -0,0 +1,95 @@ +From 90d2cd4918401b6fdee1b6886399d4dbbed4429c 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.15/mips-ralink-mt7621-use-bitwise-not-instead-of-logica.patch b/queue-5.15/mips-ralink-mt7621-use-bitwise-not-instead-of-logica.patch new file mode 100644 index 00000000000..0288155ae4b --- /dev/null +++ b/queue-5.15/mips-ralink-mt7621-use-bitwise-not-instead-of-logica.patch @@ -0,0 +1,38 @@ +From 279cbb489e2ac9bf7d70563b73f6efc939ccf4be 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.15/net-chelsio-cxgb3-check-the-return-value-of-pci_find.patch b/queue-5.15/net-chelsio-cxgb3-check-the-return-value-of-pci_find.patch new file mode 100644 index 00000000000..8fd5e20da5e --- /dev/null +++ b/queue-5.15/net-chelsio-cxgb3-check-the-return-value-of-pci_find.patch @@ -0,0 +1,37 @@ +From 696a45300c2778081637ac3f1e1b1c21bd21d6ca 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 7ff31d1026fb..e0d34e64fc6c 100644 +--- a/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c ++++ b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c +@@ -3678,6 +3678,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.15/net-dcb-disable-softirqs-in-dcbnl_flush_dev.patch b/queue-5.15/net-dcb-disable-softirqs-in-dcbnl_flush_dev.patch new file mode 100644 index 00000000000..ceea55b3159 --- /dev/null +++ b/queue-5.15/net-dcb-disable-softirqs-in-dcbnl_flush_dev.patch @@ -0,0 +1,62 @@ +From a6b4965c98b3db02b009b1102ac8333f7a020dcc 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.15/net-sparx5-fix-add-vlan-when-invalid-operation.patch b/queue-5.15/net-sparx5-fix-add-vlan-when-invalid-operation.patch new file mode 100644 index 00000000000..ea48faf92ad --- /dev/null +++ b/queue-5.15/net-sparx5-fix-add-vlan-when-invalid-operation.patch @@ -0,0 +1,64 @@ +From 21949ec920470d43decf8bd3bfd61cabaf8b6921 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.15/net-stmmac-enhance-xdp-zc-driver-level-switching-per.patch b/queue-5.15/net-stmmac-enhance-xdp-zc-driver-level-switching-per.patch new file mode 100644 index 00000000000..7eb742b8d57 --- /dev/null +++ b/queue-5.15/net-stmmac-enhance-xdp-zc-driver-level-switching-per.patch @@ -0,0 +1,255 @@ +From 8ea5f75e7f58ea847eda2afe6529f06b9f1b617a 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 c6e3b0c1f1e8..4595282a9790 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -3667,7 +3667,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; +@@ -3791,7 +3791,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; +@@ -6456,6 +6456,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.15/net-stmmac-only-enable-dma-interrupts-when-ready.patch b/queue-5.15/net-stmmac-only-enable-dma-interrupts-when-ready.patch new file mode 100644 index 00000000000..0f75ec949d8 --- /dev/null +++ b/queue-5.15/net-stmmac-only-enable-dma-interrupts-when-ready.patch @@ -0,0 +1,111 @@ +From a70594c1daf30392e0ca9f667f9e52da57e89cd3 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 4595282a9790..73f66170829a 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -2268,6 +2268,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 +@@ -2903,8 +2920,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++) { +@@ -3756,6 +3775,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; + +@@ -6514,8 +6534,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; +@@ -6575,6 +6597,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; + +@@ -7453,6 +7476,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.15/netfilter-nf_tables-prefer-kfree_rcu-ptr-rcu-variant.patch b/queue-5.15/netfilter-nf_tables-prefer-kfree_rcu-ptr-rcu-variant.patch new file mode 100644 index 00000000000..eaf8827b75c --- /dev/null +++ b/queue-5.15/netfilter-nf_tables-prefer-kfree_rcu-ptr-rcu-variant.patch @@ -0,0 +1,53 @@ +From dcc32a297a6e5a2285ef4a2da88575aa9126c51f 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.15/nl80211-handle-nla_memdup-failures-in-handle_nan_fil.patch b/queue-5.15/nl80211-handle-nla_memdup-failures-in-handle_nan_fil.patch new file mode 100644 index 00000000000..dad9b8f07f1 --- /dev/null +++ b/queue-5.15/nl80211-handle-nla_memdup-failures-in-handle_nan_fil.patch @@ -0,0 +1,54 @@ +From 9f3a11cfeed63bf0efc3ef4a0c06480ceb44158b 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 16b3d0cc0bdb..99564db14aa1 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -13177,6 +13177,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++; + } +@@ -13189,6 +13192,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.15/selftests-mlxsw-resource_scale-fix-return-value.patch b/queue-5.15/selftests-mlxsw-resource_scale-fix-return-value.patch new file mode 100644 index 00000000000..4e6b1e3396d --- /dev/null +++ b/queue-5.15/selftests-mlxsw-resource_scale-fix-return-value.patch @@ -0,0 +1,57 @@ +From 06fac660a8d74c994c2987c358710ca2e0e1b396 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 685dfb3478b3..b9b8274643de 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.15/series b/queue-5.15/series index 832c658a26d..542d736b533 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -199,3 +199,43 @@ igc-igc_write_phy_reg_gpy-drop-premature-return.patch ibmvnic-free-reset-work-item-when-flushing.patch memfd-fix-f_seal_write-after-shmem-huge-page-allocated.patch s390-extable-fix-exception-table-sorting.patch +arm64-dts-juno-remove-gicv2m-dma-range.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 +netfilter-nf_tables-prefer-kfree_rcu-ptr-rcu-variant.patch +arm-tegra-move-panels-to-aux-bus.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 +net-chelsio-cxgb3-check-the-return-value-of-pci_find.patch +net-sparx5-fix-add-vlan-when-invalid-operation.patch +iavf-refactor-iavf-state-machine-tracking.patch +iavf-add-__iavf_init_failed-state.patch +iavf-combine-init-and-watchdog-state-machines.patch +iavf-add-trace-while-removing-device.patch +iavf-rework-mutexes-for-better-synchronisation.patch +iavf-add-helper-function-to-go-from-pci_dev-to-adapt.patch +iavf-fix-kernel-bug-in-free_msi_irqs.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 +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.15/soc-fsl-guts-add-a-missing-memory-allocation-failure.patch b/queue-5.15/soc-fsl-guts-add-a-missing-memory-allocation-failure.patch new file mode 100644 index 00000000000..591284d1ed8 --- /dev/null +++ b/queue-5.15/soc-fsl-guts-add-a-missing-memory-allocation-failure.patch @@ -0,0 +1,49 @@ +From c014bf6ee7c6da9a72a63c028da917216074ee39 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 67b079fc0c8e..75eabfb916cb 100644 +--- a/drivers/soc/fsl/guts.c ++++ b/drivers/soc/fsl/guts.c +@@ -160,9 +160,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.15/soc-fsl-guts-revert-commit-3c0d64e867ed.patch b/queue-5.15/soc-fsl-guts-revert-commit-3c0d64e867ed.patch new file mode 100644 index 00000000000..ffc358f5b7c --- /dev/null +++ b/queue-5.15/soc-fsl-guts-revert-commit-3c0d64e867ed.patch @@ -0,0 +1,66 @@ +From a20b918f6b4aa4ed5ed658693b71d2dba4825d41 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 d5e9a5f2c087..67b079fc0c8e 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; + struct resource *res; + const struct fsl_soc_die_attr *soc_die; +@@ -161,8 +160,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); +@@ -197,7 +197,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.15/soc-fsl-qe-check-of-ioremap-return-value.patch b/queue-5.15/soc-fsl-qe-check-of-ioremap-return-value.patch new file mode 100644 index 00000000000..7d63f6e1bfc --- /dev/null +++ b/queue-5.15/soc-fsl-qe-check-of-ioremap-return-value.patch @@ -0,0 +1,43 @@ +From 6d48e5679e0c32f8640ecbe10d46bb400557f282 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 + -- 2.47.2