]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.15
authorSasha Levin <sashal@kernel.org>
Sat, 5 Mar 2022 20:55:48 +0000 (15:55 -0500)
committerSasha Levin <sashal@kernel.org>
Sat, 5 Mar 2022 20:55:48 +0000 (15:55 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
41 files changed:
queue-5.15/arm-dts-switch-timer-config-to-common-devkit8000-dev.patch [new file with mode: 0644]
queue-5.15/arm-dts-use-32kihz-oscillator-on-devkit8000.patch [new file with mode: 0644]
queue-5.15/arm-tegra-move-panels-to-aux-bus.patch [new file with mode: 0644]
queue-5.15/arm64-dts-juno-remove-gicv2m-dma-range.patch [new file with mode: 0644]
queue-5.15/can-etas_es58x-change-opened_channel_cnt-s-type-from.patch [new file with mode: 0644]
queue-5.15/drm-amdgpu-fix-suspend-resume-hang-regression.patch [new file with mode: 0644]
queue-5.15/drm-bridge-ti-sn65dsi86-properly-undo-autosuspend.patch [new file with mode: 0644]
queue-5.15/drm-i915-guc-slpc-correct-the-param-count-for-unset-.patch [new file with mode: 0644]
queue-5.15/e1000e-fix-possible-hw-unit-hang-after-an-s0ix-exit.patch [new file with mode: 0644]
queue-5.15/iavf-add-__iavf_init_failed-state.patch [new file with mode: 0644]
queue-5.15/iavf-add-helper-function-to-go-from-pci_dev-to-adapt.patch [new file with mode: 0644]
queue-5.15/iavf-add-trace-while-removing-device.patch [new file with mode: 0644]
queue-5.15/iavf-add-waiting-so-the-port-is-initialized-in-remov.patch [new file with mode: 0644]
queue-5.15/iavf-combine-init-and-watchdog-state-machines.patch [new file with mode: 0644]
queue-5.15/iavf-fix-__iavf_resetting-state-usage.patch [new file with mode: 0644]
queue-5.15/iavf-fix-init-state-closure-on-remove.patch [new file with mode: 0644]
queue-5.15/iavf-fix-kernel-bug-in-free_msi_irqs.patch [new file with mode: 0644]
queue-5.15/iavf-fix-locking-for-virtchnl_op_get_offload_vlan_v2.patch [new file with mode: 0644]
queue-5.15/iavf-fix-race-in-init-state.patch [new file with mode: 0644]
queue-5.15/iavf-refactor-iavf-state-machine-tracking.patch [new file with mode: 0644]
queue-5.15/iavf-rework-mutexes-for-better-synchronisation.patch [new file with mode: 0644]
queue-5.15/ibmvnic-complete-init_done-on-transport-events.patch [new file with mode: 0644]
queue-5.15/ibmvnic-define-flush_reset_queue-helper.patch [new file with mode: 0644]
queue-5.15/ibmvnic-initialize-rc-before-completing-wait.patch [new file with mode: 0644]
queue-5.15/iommu-amd-fix-i-o-page-table-memory-leak.patch [new file with mode: 0644]
queue-5.15/iommu-amd-simplify-pagetable-freeing.patch [new file with mode: 0644]
queue-5.15/iommu-amd-use-put_pages_list.patch [new file with mode: 0644]
queue-5.15/mips-ralink-mt7621-do-memory-detection-on-kseg1.patch [new file with mode: 0644]
queue-5.15/mips-ralink-mt7621-use-bitwise-not-instead-of-logica.patch [new file with mode: 0644]
queue-5.15/net-chelsio-cxgb3-check-the-return-value-of-pci_find.patch [new file with mode: 0644]
queue-5.15/net-dcb-disable-softirqs-in-dcbnl_flush_dev.patch [new file with mode: 0644]
queue-5.15/net-sparx5-fix-add-vlan-when-invalid-operation.patch [new file with mode: 0644]
queue-5.15/net-stmmac-enhance-xdp-zc-driver-level-switching-per.patch [new file with mode: 0644]
queue-5.15/net-stmmac-only-enable-dma-interrupts-when-ready.patch [new file with mode: 0644]
queue-5.15/netfilter-nf_tables-prefer-kfree_rcu-ptr-rcu-variant.patch [new file with mode: 0644]
queue-5.15/nl80211-handle-nla_memdup-failures-in-handle_nan_fil.patch [new file with mode: 0644]
queue-5.15/selftests-mlxsw-resource_scale-fix-return-value.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/soc-fsl-guts-add-a-missing-memory-allocation-failure.patch [new file with mode: 0644]
queue-5.15/soc-fsl-guts-revert-commit-3c0d64e867ed.patch [new file with mode: 0644]
queue-5.15/soc-fsl-qe-check-of-ioremap-return-value.patch [new file with mode: 0644]

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 (file)
index 0000000..46b8641
--- /dev/null
@@ -0,0 +1,109 @@
+From 574a0aa6ee459fc336cce7e765118cda090dcac3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jan 2022 20:11:38 +0100
+Subject: ARM: dts: switch timer config to common devkit8000 devicetree
+
+From: Anthoine Bourgeois <anthoine.bourgeois@gmail.com>
+
+[ Upstream commit 64324ef337d0caa5798fa8fa3f6bbfbd3245868a ]
+
+This patch allow lcd43 and lcd70 flavors to benefit from timer
+evolution.
+
+Fixes: e428e250fde6 ("ARM: dts: Configure system timers for omap3")
+Signed-off-by: Anthoine Bourgeois <anthoine.bourgeois@gmail.com>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../arm/boot/dts/omap3-devkit8000-common.dtsi | 33 +++++++++++++++++++
+ arch/arm/boot/dts/omap3-devkit8000.dts        | 33 -------------------
+ 2 files changed, 33 insertions(+), 33 deletions(-)
+
+diff --git a/arch/arm/boot/dts/omap3-devkit8000-common.dtsi b/arch/arm/boot/dts/omap3-devkit8000-common.dtsi
+index 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 (file)
index 0000000..e54a075
--- /dev/null
@@ -0,0 +1,88 @@
+From eed594e56910b074825c354af6d235de4eea6737 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jan 2022 20:11:39 +0100
+Subject: ARM: dts: Use 32KiHz oscillator on devkit8000
+
+From: Anthoine Bourgeois <anthoine.bourgeois@gmail.com>
+
+[ Upstream commit 8840f5460a23759403f1f2860429dcbcc2f04a65 ]
+
+Devkit8000 board seems to always used 32k_counter as clocksource.
+Restore this behavior.
+
+If clocksource is back to 32k_counter, timer12 is now the clockevent
+source (as before) and timer2 is not longer needed here.
+
+This commit fixes the same issue observed with commit 23885389dbbb
+("ARM: dts: Fix timer regression for beagleboard revision c") when sleep
+is blocked until hitting keys over serial console.
+
+Fixes: aba1ad05da08 ("clocksource/drivers/timer-ti-dm: Add clockevent and clocksource support")
+Fixes: e428e250fde6 ("ARM: dts: Configure system timers for omap3")
+Signed-off-by: Anthoine Bourgeois <anthoine.bourgeois@gmail.com>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/omap3-devkit8000-common.dtsi | 17 +----------------
+ drivers/clocksource/timer-ti-dm-systimer.c     |  3 +--
+ 2 files changed, 2 insertions(+), 18 deletions(-)
+
+diff --git a/arch/arm/boot/dts/omap3-devkit8000-common.dtsi b/arch/arm/boot/dts/omap3-devkit8000-common.dtsi
+index 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 (file)
index 0000000..f38d0f6
--- /dev/null
@@ -0,0 +1,112 @@
+From 10bbe62faf7b11c9bb932b40ad53f99d5da178d2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Dec 2021 11:32:39 +0100
+Subject: ARM: tegra: Move panels to AUX bus
+
+From: Thierry Reding <treding@nvidia.com>
+
+[ Upstream commit 8d3b01e0d4bb54368d73d0984466d72c2eeeac74 ]
+
+Move the eDP panel on Venice 2 and Nyan boards into the corresponding
+AUX bus device tree node. This allows us to avoid a nasty circular
+dependency that would otherwise be created between the DPAUX and panel
+nodes via the DDC/I2C phandle.
+
+Fixes: eb481f9ac95c ("ARM: tegra: add Acer Chromebook 13 device tree")
+Fixes: 59fe02cb079f ("ARM: tegra: Add DTS for the nyan-blaze board")
+Fixes: 40e231c770a4 ("ARM: tegra: Enable eDP for Venice2")
+Signed-off-by: Thierry Reding <treding@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/tegra124-nyan-big.dts   | 15 +++++++++------
+ arch/arm/boot/dts/tegra124-nyan-blaze.dts | 15 +++++++++------
+ arch/arm/boot/dts/tegra124-venice2.dts    | 14 +++++++-------
+ 3 files changed, 25 insertions(+), 19 deletions(-)
+
+diff --git a/arch/arm/boot/dts/tegra124-nyan-big.dts b/arch/arm/boot/dts/tegra124-nyan-big.dts
+index 1d2aac2cb6d0..fdc1d64dfff9 100644
+--- a/arch/arm/boot/dts/tegra124-nyan-big.dts
++++ b/arch/arm/boot/dts/tegra124-nyan-big.dts
+@@ -13,12 +13,15 @@
+                    "google,nyan-big-rev1", "google,nyan-big-rev0",
+                    "google,nyan-big", "google,nyan", "nvidia,tegra124";
+-      panel: panel {
+-              compatible = "auo,b133xtn01";
+-
+-              power-supply = <&vdd_3v3_panel>;
+-              backlight = <&backlight>;
+-              ddc-i2c-bus = <&dpaux>;
++      host1x@50000000 {
++              dpaux@545c0000 {
++                      aux-bus {
++                              panel: panel {
++                                      compatible = "auo,b133xtn01";
++                                      backlight = <&backlight>;
++                              };
++                      };
++              };
+       };
+       mmc@700b0400 { /* SD Card on this bus */
+diff --git a/arch/arm/boot/dts/tegra124-nyan-blaze.dts b/arch/arm/boot/dts/tegra124-nyan-blaze.dts
+index 677babde6460..abdf4456826f 100644
+--- a/arch/arm/boot/dts/tegra124-nyan-blaze.dts
++++ b/arch/arm/boot/dts/tegra124-nyan-blaze.dts
+@@ -15,12 +15,15 @@
+                    "google,nyan-blaze-rev0", "google,nyan-blaze",
+                    "google,nyan", "nvidia,tegra124";
+-      panel: panel {
+-              compatible = "samsung,ltn140at29-301";
+-
+-              power-supply = <&vdd_3v3_panel>;
+-              backlight = <&backlight>;
+-              ddc-i2c-bus = <&dpaux>;
++      host1x@50000000 {
++              dpaux@545c0000 {
++                      aux-bus {
++                              panel: panel {
++                                      compatible = "samsung,ltn140at29-301";
++                                      backlight = <&backlight>;
++                              };
++                      };
++              };
+       };
+       sound {
+diff --git a/arch/arm/boot/dts/tegra124-venice2.dts b/arch/arm/boot/dts/tegra124-venice2.dts
+index e6b54ac1ebd1..84e2d24065e9 100644
+--- a/arch/arm/boot/dts/tegra124-venice2.dts
++++ b/arch/arm/boot/dts/tegra124-venice2.dts
+@@ -48,6 +48,13 @@
+               dpaux@545c0000 {
+                       vdd-supply = <&vdd_3v3_panel>;
+                       status = "okay";
++
++                      aux-bus {
++                              panel: panel {
++                                      compatible = "lg,lp129qe";
++                                      backlight = <&backlight>;
++                              };
++                      };
+               };
+       };
+@@ -1079,13 +1086,6 @@
+               };
+       };
+-      panel: panel {
+-              compatible = "lg,lp129qe";
+-              power-supply = <&vdd_3v3_panel>;
+-              backlight = <&backlight>;
+-              ddc-i2c-bus = <&dpaux>;
+-      };
+-
+       vdd_mux: regulator@0 {
+               compatible = "regulator-fixed";
+               regulator-name = "+VDD_MUX";
+-- 
+2.34.1
+
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 (file)
index 0000000..0e79358
--- /dev/null
@@ -0,0 +1,49 @@
+From ea202775357b1f16e9fdfa759d539c243b159368 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Jan 2022 17:57:01 +0000
+Subject: arm64: dts: juno: Remove GICv2m dma-range
+
+From: Robin Murphy <robin.murphy@arm.com>
+
+[ Upstream commit 31eeb6b09f4053f32a30ce9fbcdfca31f713028d ]
+
+Although it is painstakingly honest to describe all 3 PCI windows in
+"dma-ranges", it misses the the subtle distinction that the window for
+the GICv2m range is normally programmed for Device memory attributes
+rather than Normal Cacheable like the DRAM windows. Since MMU-401 only
+offers stage 2 translation, this means that when the PCI SMMU is
+enabled, accesses through that IPA range unexpectedly lose coherency if
+mapped as cacheable at the SMMU, due to the attribute combining rules.
+Since an extra 256KB is neither here nor there when we still have 10GB
+worth of usable address space, rather than attempting to describe and
+cope with this detail let's just remove the offending range. If the SMMU
+is not used then it makes no difference anyway.
+
+Link: https://lore.kernel.org/r/856c3f7192c6c3ce545ba67462f2ce9c86ed6b0c.1643046936.git.robin.murphy@arm.com
+Fixes: 4ac4d146cb63 ("arm64: dts: juno: Describe PCI dma-ranges")
+Reported-by: Anders Roxell <anders.roxell@linaro.org>
+Acked-by: Liviu Dudau <liviu.dudau@arm.com>
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/arm/juno-base.dtsi | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi
+index 6288e104a089..a2635b14da30 100644
+--- a/arch/arm64/boot/dts/arm/juno-base.dtsi
++++ b/arch/arm64/boot/dts/arm/juno-base.dtsi
+@@ -543,8 +543,7 @@
+                        <0x02000000 0x00 0x50000000 0x00 0x50000000 0x0 0x08000000>,
+                        <0x42000000 0x40 0x00000000 0x40 0x00000000 0x1 0x00000000>;
+               /* Standard AXI Translation entries as programmed by EDK2 */
+-              dma-ranges = <0x02000000 0x0 0x2c1c0000 0x0 0x2c1c0000 0x0 0x00040000>,
+-                           <0x02000000 0x0 0x80000000 0x0 0x80000000 0x0 0x80000000>,
++              dma-ranges = <0x02000000 0x0 0x80000000 0x0 0x80000000 0x0 0x80000000>,
+                            <0x43000000 0x8 0x00000000 0x8 0x00000000 0x2 0x00000000>;
+               #interrupt-cells = <1>;
+               interrupt-map-mask = <0 0 0 7>;
+-- 
+2.34.1
+
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 (file)
index 0000000..eda2ac7
--- /dev/null
@@ -0,0 +1,145 @@
+From ce8b5f15f7bfda11ec44de2e67b5dba428452ffc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 12 Feb 2022 20:27:13 +0900
+Subject: can: etas_es58x: change opened_channel_cnt's type from atomic_t to u8
+
+From: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
+
+[ Upstream commit f4896248e9025ff744b4147e6758274a1cb8cbae ]
+
+The driver uses an atomic_t variable: struct
+es58x_device::opened_channel_cnt to keep track of the number of opened
+channels in order to only allocate memory for the URBs when this count
+changes from zero to one.
+
+While the intent was to prevent race conditions, the choice of an
+atomic_t turns out to be a bad idea for several reasons:
+
+- implementation is incorrect and fails to decrement
+  opened_channel_cnt when the URB allocation fails as reported in
+  [1].
+
+- even if opened_channel_cnt were to be correctly decremented,
+  atomic_t is insufficient to cover edge cases: there can be a race
+  condition in which 1/ a first process fails to allocate URBs
+  memory 2/ a second process enters es58x_open() before the first
+  process does its cleanup and decrements opened_channed_cnt. In
+  which case, the second process would successfully return despite
+  the URBs memory not being allocated.
+
+- actually, any kind of locking mechanism was useless here because
+  it is redundant with the network stack big kernel lock
+  (a.k.a. rtnl_lock) which is being hold by all the callers of
+  net_device_ops:ndo_open() and net_device_ops:ndo_close(). c.f. the
+  ASSERST_RTNL() calls in __dev_open() [2] and __dev_close_many()
+  [3].
+
+The atmomic_t is thus replaced by a simple u8 type and the logic to
+increment and decrement es58x_device:opened_channel_cnt is simplified
+accordingly fixing the bug reported in [1]. We do not check again for
+ASSERST_RTNL() as this is already done by the callers.
+
+[1] https://lore.kernel.org/linux-can/20220201140351.GA2548@kili/T/#u
+[2] https://elixir.bootlin.com/linux/v5.16/source/net/core/dev.c#L1463
+[3] https://elixir.bootlin.com/linux/v5.16/source/net/core/dev.c#L1541
+
+Fixes: 8537257874e9 ("can: etas_es58x: add core support for ETAS ES58X CAN USB interfaces")
+Link: https://lore.kernel.org/all/20220212112713.577957-1-mailhol.vincent@wanadoo.fr
+Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/usb/etas_es58x/es58x_core.c | 9 +++++----
+ drivers/net/can/usb/etas_es58x/es58x_core.h | 8 +++++---
+ 2 files changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.c b/drivers/net/can/usb/etas_es58x/es58x_core.c
+index 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 (file)
index 0000000..a01f77e
--- /dev/null
@@ -0,0 +1,44 @@
+From 264c35048fc1d42f6e7abfa5c47b255b8d4709bd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Mar 2022 14:11:59 +0800
+Subject: drm/amdgpu: fix suspend/resume hang regression
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Qiang Yu <qiang.yu@amd.com>
+
+[ Upstream commit f1ef17011c765495c876fa75435e59eecfdc1ee4 ]
+
+Regression has been reported that suspend/resume may hang with
+the previous vm ready check commit.
+
+So bring back the evicted list check as a temp fix.
+
+Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1922
+Fixes: c1a66c3bc425 ("drm/amdgpu: check vm ready by amdgpu_vm->evicting flag")
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Qiang Yu <qiang.yu@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+index 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 (file)
index 0000000..880e55d
--- /dev/null
@@ -0,0 +1,54 @@
+From 0f77fd637bf0ed205f85c047cfee269bb2f9b95c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Feb 2022 14:18:43 -0800
+Subject: drm/bridge: ti-sn65dsi86: Properly undo autosuspend
+
+From: Douglas Anderson <dianders@chromium.org>
+
+[ Upstream commit 26d3474348293dc752c55fe6d41282199f73714c ]
+
+The PM Runtime docs say:
+  Drivers in ->remove() callback should undo the runtime PM changes done
+  in ->probe(). Usually this means calling pm_runtime_disable(),
+  pm_runtime_dont_use_autosuspend() etc.
+
+We weren't doing that for autosuspend. Let's do it.
+
+Fixes: 9bede63127c6 ("drm/bridge: ti-sn65dsi86: Use pm_runtime autosuspend")
+Signed-off-by: Douglas Anderson <dianders@chromium.org>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220222141838.1.If784ba19e875e8ded4ec4931601ce6d255845245@changeid
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/ti-sn65dsi86.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+index 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 (file)
index 0000000..e0a3875
--- /dev/null
@@ -0,0 +1,42 @@
+From b1c1647ea710b5c1791c61979eef4ec26cecb399 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Feb 2022 10:15:04 -0800
+Subject: drm/i915/guc/slpc: Correct the param count for unset param
+
+From: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
+
+[ Upstream commit 1b279f6ad467535c3b8a66b4edefaca2cdd5bdc3 ]
+
+SLPC unset param H2G only needs one parameter - the id of the
+param.
+
+Fixes: 025cb07bebfa ("drm/i915/guc/slpc: Cache platform frequency limits")
+
+Suggested-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
+Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
+Reviewed-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
+Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220216181504.7155-1-vinay.belgaumkar@intel.com
+(cherry picked from commit 9648f1c3739505557d94ff749a4f32192ea81fe3)
+Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+index 65a3e7fdb2b2..95ff630157b9 100644
+--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
++++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+@@ -133,7 +133,7 @@ static int guc_action_slpc_unset_param(struct intel_guc *guc, u8 id)
+ {
+       u32 request[] = {
+               GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST,
+-              SLPC_EVENT(SLPC_EVENT_PARAMETER_UNSET, 2),
++              SLPC_EVENT(SLPC_EVENT_PARAMETER_UNSET, 1),
+               id,
+       };
+-- 
+2.34.1
+
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 (file)
index 0000000..9866d19
--- /dev/null
@@ -0,0 +1,124 @@
+From f4b307e070d435058fa0b4f451e1e34e684abe36 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jan 2022 19:31:23 +0200
+Subject: e1000e: Fix possible HW unit hang after an s0ix exit
+
+From: Sasha Neftin <sasha.neftin@intel.com>
+
+[ Upstream commit 1866aa0d0d6492bc2f8d22d0df49abaccf50cddd ]
+
+Disable the OEM bit/Gig Disable/restart AN impact and disable the PHY
+LAN connected device (LCD) reset during power management flows. This
+fixes possible HW unit hangs on the s0ix exit on some corporate ADL
+platforms.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=214821
+Fixes: 3e55d231716e ("e1000e: Add handshake with the CSME to support S0ix")
+Suggested-by: Dima Ruinskiy <dima.ruinskiy@intel.com>
+Suggested-by: Nir Efrati <nir.efrati@intel.com>
+Signed-off-by: Sasha Neftin <sasha.neftin@intel.com>
+Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/e1000e/hw.h      |  1 +
+ drivers/net/ethernet/intel/e1000e/ich8lan.c |  4 ++++
+ drivers/net/ethernet/intel/e1000e/ich8lan.h |  1 +
+ drivers/net/ethernet/intel/e1000e/netdev.c  | 26 +++++++++++++++++++++
+ 4 files changed, 32 insertions(+)
+
+diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h
+index bcf680e83811..13382df2f2ef 100644
+--- a/drivers/net/ethernet/intel/e1000e/hw.h
++++ b/drivers/net/ethernet/intel/e1000e/hw.h
+@@ -630,6 +630,7 @@ struct e1000_phy_info {
+       bool disable_polarity_correction;
+       bool is_mdix;
+       bool polarity_correction;
++      bool reset_disable;
+       bool speed_downgraded;
+       bool autoneg_wait_to_complete;
+ };
+diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
+index a3e42d06c63e..d60e2016d03c 100644
+--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
++++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
+@@ -2050,6 +2050,10 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw)
+       bool blocked = false;
+       int i = 0;
++      /* Check the PHY (LCD) reset flag */
++      if (hw->phy.reset_disable)
++              return true;
++
+       while ((blocked = !(er32(FWSM) & E1000_ICH_FWSM_RSPCIPHY)) &&
+              (i++ < 30))
+               usleep_range(10000, 11000);
+diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.h b/drivers/net/ethernet/intel/e1000e/ich8lan.h
+index 2504b11c3169..638a3ddd7ada 100644
+--- a/drivers/net/ethernet/intel/e1000e/ich8lan.h
++++ b/drivers/net/ethernet/intel/e1000e/ich8lan.h
+@@ -271,6 +271,7 @@
+ #define I217_CGFREG_ENABLE_MTA_RESET  0x0002
+ #define I217_MEMPWR                   PHY_REG(772, 26)
+ #define I217_MEMPWR_DISABLE_SMB_RELEASE       0x0010
++#define I217_MEMPWR_MOEM              0x1000
+ /* Receive Address Initial CRC Calculation */
+ #define E1000_PCH_RAICC(_n)   (0x05F50 + ((_n) * 4))
+diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
+index 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 (file)
index 0000000..69e8c99
--- /dev/null
@@ -0,0 +1,160 @@
+From 4d78bbefe42416b6fddd0ee94431c91e152eeb19 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Aug 2021 08:47:49 +0000
+Subject: iavf: Add __IAVF_INIT_FAILED state
+
+From: Mateusz Palczewski <mateusz.palczewski@intel.com>
+
+[ 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 <jakub.pawlak@intel.com>
+Signed-off-by: Jan Sokolowski <jan.sokolowski@intel.com>
+Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf.h      |  1 +
+ drivers/net/ethernet/intel/iavf/iavf_main.c | 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 (file)
index 0000000..c8280b5
--- /dev/null
@@ -0,0 +1,90 @@
+From 4ec871ca764acf3e43e44815885546ec42333d00 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Sep 2021 08:41:23 +0200
+Subject: iavf: Add helper function to go from pci_dev to adapter
+
+From: Karen Sornek <karen.sornek@intel.com>
+
+[ 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 <brett.creeley@intel.com>
+Signed-off-by: Karen Sornek <karen.sornek@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf_main.c | 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 (file)
index 0000000..555a189
--- /dev/null
@@ -0,0 +1,40 @@
+From 359da61e4686555ad78467d19b5c7f9fa78cf15b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Jun 2021 15:43:48 +0200
+Subject: iavf: Add trace while removing device
+
+From: Jedrzej Jagielski <jedrzej.jagielski@intel.com>
+
+[ Upstream commit bdb9e5c7aec73a7b8b5acab37587b6de1203e68d ]
+
+Add kernel trace that device was removed.
+Currently there is no such information.
+I.e. Host admin removes a PCI device from a VM,
+than on VM shall be info about the event.
+
+This patch adds info log to iavf_remove function.
+
+Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
+Signed-off-by: Jedrzej Jagielski <jedrzej.jagielski@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf_main.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
+index 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 (file)
index 0000000..26b7910
--- /dev/null
@@ -0,0 +1,91 @@
+From f1c2cece1a86bc8d7c23daeffaa1448b64eb7f59 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Feb 2022 13:36:56 +0100
+Subject: iavf: Add waiting so the port is initialized in remove
+
+From: Slawomir Laba <slawomirx.laba@intel.com>
+
+[ Upstream commit 974578017fc1fdd06cea8afb9dfa32602e8529ed ]
+
+There exist races when port is being configured and remove is
+triggered.
+
+unregister_netdev is not and can't be called under crit_lock
+mutex since it is calling ndo_stop -> iavf_close which requires
+this lock. Depending on init state the netdev could be still
+unregistered so unregister_netdev never cleans up, when shortly
+after that the device could become registered.
+
+Make iavf_remove wait until port finishes initialization.
+All critical state changes are atomic (under crit_lock).
+Crashes that come from iavf_reset_interrupt_capability and
+iavf_free_traffic_irqs should now be solved in a graceful
+manner.
+
+Fixes: 605ca7c5c6707 ("iavf: Fix kernel BUG in free_msi_irqs")
+Signed-off-by: Slawomir Laba <slawomirx.laba@intel.com>
+Signed-off-by: Phani Burra <phani.r.burra@intel.com>
+Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf_main.c | 27 ++++++++++++---------
+ 1 file changed, 16 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
+index 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 (file)
index 0000000..102c3fe
--- /dev/null
@@ -0,0 +1,262 @@
+From 66e8366ede742f4857607296d9454b7670223a66 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Aug 2021 08:47:58 +0000
+Subject: iavf: Combine init and watchdog state machines
+
+From: Mateusz Palczewski <mateusz.palczewski@intel.com>
+
+[ 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 <jakub.pawlak@intel.com>
+Signed-off-by: Jan Sokolowski <jan.sokolowski@intel.com>
+Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf.h      |   1 -
+ drivers/net/ethernet/intel/iavf/iavf_main.c | 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 (file)
index 0000000..688fca1
--- /dev/null
@@ -0,0 +1,75 @@
+From 0483197111c0b2fed7c949ebfed82c4ac2feef1b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Feb 2022 13:38:55 +0100
+Subject: iavf: Fix __IAVF_RESETTING state usage
+
+From: Slawomir Laba <slawomirx.laba@intel.com>
+
+[ Upstream commit 14756b2ae265d526b8356e86729090b01778fdf6 ]
+
+The setup of __IAVF_RESETTING state in watchdog task had no
+effect and could lead to slow resets in the driver as
+the task for __IAVF_RESETTING state only requeues watchdog.
+Till now the __IAVF_RESETTING was interpreted by reset task
+as running state which could lead to errors with allocating
+and resources disposal.
+
+Make watchdog_task queue the reset task when it's necessary.
+Do not update the state to __IAVF_RESETTING so the reset task
+knows exactly what is the current state of the adapter.
+
+Fixes: 898ef1cb1cb2 ("iavf: Combine init and watchdog state machines")
+Signed-off-by: Slawomir Laba <slawomirx.laba@intel.com>
+Signed-off-by: Phani Burra <phani.r.burra@intel.com>
+Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf_main.c | 13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
+index 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 (file)
index 0000000..a78fefd
--- /dev/null
@@ -0,0 +1,120 @@
+From 790378f852c366075d30217b4dd06e201a886008 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Feb 2022 13:37:10 +0100
+Subject: iavf: Fix init state closure on remove
+
+From: Slawomir Laba <slawomirx.laba@intel.com>
+
+[ Upstream commit 3ccd54ef44ebfa0792c5441b6d9c86618f3378d1 ]
+
+When init states of the adapter work, the errors like lack
+of communication with the PF might hop in. If such events
+occur the driver restores previous states in order to retry
+initialization in a proper way. When remove task kicks in,
+this situation could lead to races with unregistering the
+netdevice as well as resources cleanup. With the commit
+introducing the waiting in remove for init to complete,
+this problem turns into an endless waiting if init never
+recovers from errors.
+
+Introduce __IAVF_IN_REMOVE_TASK bit to indicate that the
+remove thread has started.
+
+Make __IAVF_COMM_FAILED adapter state respect the
+__IAVF_IN_REMOVE_TASK bit and set the __IAVF_INIT_FAILED
+state and return without any action instead of trying to
+recover.
+
+Make __IAVF_INIT_FAILED adapter state respect the
+__IAVF_IN_REMOVE_TASK bit and return without any further
+actions.
+
+Make the loop in the remove handler break when adapter has
+__IAVF_INIT_FAILED state set.
+
+Fixes: 898ef1cb1cb2 ("iavf: Combine init and watchdog state machines")
+Signed-off-by: Slawomir Laba <slawomirx.laba@intel.com>
+Signed-off-by: Phani Burra <phani.r.burra@intel.com>
+Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf.h      |  4 ++++
+ drivers/net/ethernet/intel/iavf/iavf_main.c | 24 ++++++++++++++++++++-
+ 2 files changed, 27 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h
+index 21e0f3361560..ffc61993019b 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf.h
++++ b/drivers/net/ethernet/intel/iavf/iavf.h
+@@ -188,6 +188,10 @@ enum iavf_state_t {
+       __IAVF_RUNNING,         /* opened, working */
+ };
++enum iavf_critical_section_t {
++      __IAVF_IN_REMOVE_TASK,  /* device being removed */
++};
++
+ #define IAVF_CLOUD_FIELD_OMAC         0x01
+ #define IAVF_CLOUD_FIELD_IMAC         0x02
+ #define IAVF_CLOUD_FIELD_IVLAN        0x04
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
+index 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 (file)
index 0000000..dd6438e
--- /dev/null
@@ -0,0 +1,166 @@
+From c921be40859f3feb324c0dc6cc21740bdd73ce87 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Oct 2021 10:30:14 +0200
+Subject: iavf: Fix kernel BUG in free_msi_irqs
+
+From: Przemyslaw Patynowski <przemyslawx.patynowski@intel.com>
+
+[ 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 <przemyslawx.patynowski@intel.com>
+Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf.h      | 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 (file)
index 0000000..d7055e0
--- /dev/null
@@ -0,0 +1,123 @@
+From b36169a9af44c73b062f68498b056fec6cb8ee9f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Feb 2022 13:37:50 +0100
+Subject: iavf: Fix locking for VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS
+
+From: Slawomir Laba <slawomirx.laba@intel.com>
+
+[ Upstream commit 0579fafd37fb7efe091f0e6c8ccf968864f40f3e ]
+
+iavf_virtchnl_completion is called under crit_lock but when
+the code for VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS is called,
+this lock is released in order to obtain rtnl_lock to avoid
+ABBA deadlock with unregister_netdev.
+
+Along with the new way iavf_remove behaves, there exist
+many risks related to the lock release and attmepts to regrab
+it. The driver faces crashes related to races between
+unregister_netdev and netdev_update_features. Yet another
+risk is that the driver could already obtain the crit_lock
+in order to destroy it and iavf_virtchnl_completion could
+crash or block forever.
+
+Make iavf_virtchnl_completion never relock crit_lock in it's
+call paths.
+
+Extract rtnl_lock locking logic to the driver for
+unregister_netdev in order to set the netdev_registered flag
+inside the lock.
+
+Introduce a new flag that will inform adminq_task to perform
+the code from VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS right after
+it finishes processing messages. Guard this code with remove
+flags so it's never called when the driver is in remove state.
+
+Fixes: 5951a2b9812d ("iavf: Fix VLAN feature flags after VFR")
+Signed-off-by: Slawomir Laba <slawomirx.laba@intel.com>
+Signed-off-by: Phani Burra <phani.r.burra@intel.com>
+Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf.h          |  1 +
+ drivers/net/ethernet/intel/iavf/iavf_main.c     | 16 +++++++++++++++-
+ drivers/net/ethernet/intel/iavf/iavf_virtchnl.c | 14 +-------------
+ 3 files changed, 17 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h
+index ffc61993019b..9a122aea6979 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf.h
++++ b/drivers/net/ethernet/intel/iavf/iavf.h
+@@ -274,6 +274,7 @@ struct iavf_adapter {
+ #define IAVF_FLAG_LEGACY_RX                   BIT(15)
+ #define IAVF_FLAG_REINIT_ITR_NEEDED           BIT(16)
+ #define IAVF_FLAG_QUEUES_DISABLED             BIT(17)
++#define IAVF_FLAG_SETUP_NETDEV_FEATURES               BIT(18)
+ /* duplicates for common code */
+ #define IAVF_FLAG_DCB_ENABLED                 0
+       /* flags for admin queue service task */
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
+index 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 (file)
index 0000000..dfcb932
--- /dev/null
@@ -0,0 +1,51 @@
+From 02e7c0894901fbaea41b72ab85c52b58e299099b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Feb 2022 13:38:01 +0100
+Subject: iavf: Fix race in init state
+
+From: Slawomir Laba <slawomirx.laba@intel.com>
+
+[ Upstream commit a472eb5cbaebb5774672c565e024336c039e9128 ]
+
+When iavf_init_version_check sends VIRTCHNL_OP_GET_VF_RESOURCES
+message, the driver will wait for the response after requeueing
+the watchdog task in iavf_init_get_resources call stack. The
+logic is implemented this way that iavf_init_get_resources has
+to be called in order to allocate adapter->vf_res. It is polling
+for the AQ response in iavf_get_vf_config function. Expect a
+call trace from kernel when adminq_task worker handles this
+message first. adapter->vf_res will be NULL in
+iavf_virtchnl_completion.
+
+Make the watchdog task not queue the adminq_task if the init
+process is not finished yet.
+
+Fixes: 898ef1cb1cb2 ("iavf: Combine init and watchdog state machines")
+Signed-off-by: Slawomir Laba <slawomirx.laba@intel.com>
+Signed-off-by: Phani Burra <phani.r.burra@intel.com>
+Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf_main.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
+index 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 (file)
index 0000000..9f8a358
--- /dev/null
@@ -0,0 +1,234 @@
+From 2e835ccfc0315c5328a11cf6e91a93fe53f8537f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Aug 2021 08:47:40 +0000
+Subject: iavf: Refactor iavf state machine tracking
+
+From: Mateusz Palczewski <mateusz.palczewski@intel.com>
+
+[ 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 <jakub.pawlak@intel.com>
+Signed-off-by: Jan Sokolowski <jan.sokolowski@intel.com>
+Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf.h        | 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 (file)
index 0000000..d140f51
--- /dev/null
@@ -0,0 +1,216 @@
+From 549a40f97169b5d19e76b085277b1d82730fb64c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Feb 2022 13:35:49 +0100
+Subject: iavf: Rework mutexes for better synchronisation
+
+From: Slawomir Laba <slawomirx.laba@intel.com>
+
+[ Upstream commit fc2e6b3b132a907378f6af08356b105a4139c4fb ]
+
+The driver used to crash in multiple spots when put to stress testing
+of the init, reset and remove paths.
+
+The user would experience call traces or hangs when creating,
+resetting, removing VFs. Depending on the machines, the call traces
+are happening in random spots, like reset restoring resources racing
+with driver remove.
+
+Make adapter->crit_lock mutex a mandatory lock for guarding the
+operations performed on all workqueues and functions dealing with
+resource allocation and disposal.
+
+Make __IAVF_REMOVE a final state of the driver respected by
+workqueues that shall not requeue, when they fail to obtain the
+crit_lock.
+
+Make the IRQ handler not to queue the new work for adminq_task
+when the __IAVF_REMOVE state is set.
+
+Fixes: 5ac49f3c2702 ("iavf: use mutexes for locking of critical sections")
+Signed-off-by: Slawomir Laba <slawomirx.laba@intel.com>
+Signed-off-by: Phani Burra <phani.r.burra@intel.com>
+Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
+Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf.h      |  1 -
+ drivers/net/ethernet/intel/iavf/iavf_main.c | 66 +++++++++++----------
+ 2 files changed, 36 insertions(+), 31 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h
+index 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 (file)
index 0000000..60351a9
--- /dev/null
@@ -0,0 +1,42 @@
+From 139c3c07dd51d87c2e8107da620d3d04f3c311d4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Feb 2022 22:23:54 -0800
+Subject: ibmvnic: complete init_done on transport events
+
+From: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+
+[ Upstream commit 36491f2df9ad2501e5a4ec25d3d95d72bafd2781 ]
+
+If we get a transport event, set the error and mark the init as
+complete so the attempt to send crq-init or login fail sooner
+rather than wait for the timeout.
+
+Fixes: bbd669a868bb ("ibmvnic: Fix completion structure initialization")
+Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index 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 (file)
index 0000000..f77b6df
--- /dev/null
@@ -0,0 +1,68 @@
+From d6b0a4973f68876e4122c5c7e9c250bb8e3084b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Feb 2022 22:23:53 -0800
+Subject: ibmvnic: define flush_reset_queue helper
+
+From: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+
+[ Upstream commit 83da53f7e4bd86dca4b2edc1e2bb324fb3c033a1 ]
+
+Define and use a helper to flush the reset queue.
+
+Fixes: 2770a7984db5 ("ibmvnic: Introduce hard reset recovery")
+Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c | 24 ++++++++++++++++--------
+ 1 file changed, 16 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index 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 (file)
index 0000000..ce8d00e
--- /dev/null
@@ -0,0 +1,39 @@
+From 76b12c922ec1e8f98d732bb471a2929864ab5533 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Feb 2022 22:23:52 -0800
+Subject: ibmvnic: initialize rc before completing wait
+
+From: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+
+[ Upstream commit 765559b10ce514eb1576595834f23cdc92125fee ]
+
+We should initialize ->init_done_rc before calling complete(). Otherwise
+the waiting thread may see ->init_done_rc as 0 before we have updated it
+and may assume that the CRQ was successful.
+
+Fixes: 6b278c0cb378 ("ibmvnic delay complete()")
+Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index 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 (file)
index 0000000..849f21f
--- /dev/null
@@ -0,0 +1,61 @@
+From 7656e2f87a4d5b925445c4ede4ceae460151c4bc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 10 Feb 2022 09:47:45 -0600
+Subject: iommu/amd: Fix I/O page table memory leak
+
+From: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
+
+[ Upstream commit 6b0b2d9a6a308bcd9300c2d83000a82812c56cea ]
+
+The current logic updates the I/O page table mode for the domain
+before calling the logic to free memory used for the page table.
+This results in IOMMU page table memory leak, and can be observed
+when launching VM w/ pass-through devices.
+
+Fix by freeing the memory used for page table before updating the mode.
+
+Cc: Joerg Roedel <joro@8bytes.org>
+Reported-by: Daniel Jordan <daniel.m.jordan@oracle.com>
+Tested-by: Daniel Jordan <daniel.m.jordan@oracle.com>
+Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
+Fixes: e42ba0633064 ("iommu/amd: Restructure code for freeing page table")
+Link: https://lore.kernel.org/all/20220118194720.urjgi73b7c3tq2o6@oracle.com/
+Link: https://lore.kernel.org/r/20220210154745.11524-1-suravee.suthikulpanit@amd.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/amd/io_pgtable.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c
+index b1bf4125b0f7..6608d1717574 100644
+--- a/drivers/iommu/amd/io_pgtable.c
++++ b/drivers/iommu/amd/io_pgtable.c
+@@ -492,18 +492,18 @@ static void v1_free_pgtable(struct io_pgtable *iop)
+       dom = container_of(pgtable, struct protection_domain, iop);
+-      /* Update data structure */
+-      amd_iommu_domain_clr_pt_root(dom);
+-
+-      /* Make changes visible to IOMMUs */
+-      amd_iommu_domain_update(dom);
+-
+       /* Page-table is not visible to IOMMU anymore, so free it */
+       BUG_ON(pgtable->mode < PAGE_MODE_NONE ||
+              pgtable->mode > PAGE_MODE_6_LEVEL);
+       free_sub_pt(pgtable->root, pgtable->mode, &freelist);
++      /* Update data structure */
++      amd_iommu_domain_clr_pt_root(dom);
++
++      /* Make changes visible to IOMMUs */
++      amd_iommu_domain_update(dom);
++
+       put_pages_list(&freelist);
+ }
+-- 
+2.34.1
+
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 (file)
index 0000000..31c087a
--- /dev/null
@@ -0,0 +1,169 @@
+From 3ccd31a933e9a08a64a803d7fda5cb64a48e5229 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Dec 2021 15:30:58 +0000
+Subject: iommu/amd: Simplify pagetable freeing
+
+From: Robin Murphy <robin.murphy@arm.com>
+
+[ Upstream commit 6b3106e9ba2de7320a71291cedcefdcf1195ad58 ]
+
+For reasons unclear, pagetable freeing is an effectively recursive
+method implemented via an elaborate system of templated functions that
+turns out to account for 25% of the object file size. Implementing it
+using regular straightforward recursion makes the code simpler, and
+seems like a good thing to do before we work on it further. As part of
+that, also fix the types to avoid all the needless casting back and
+forth which just gets in the way.
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/d3d00c9f3fa0df4756b867072c201e6e82f9ce39.1639753638.git.robin.murphy@arm.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/amd/io_pgtable.c | 82 ++++++++++++++--------------------
+ 1 file changed, 34 insertions(+), 48 deletions(-)
+
+diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c
+index 182c93a43efd..4165e1372b6e 100644
+--- a/drivers/iommu/amd/io_pgtable.c
++++ b/drivers/iommu/amd/io_pgtable.c
+@@ -84,49 +84,45 @@ static void free_page_list(struct page *freelist)
+       }
+ }
+-static struct page *free_pt_page(unsigned long pt, struct page *freelist)
++static struct page *free_pt_page(u64 *pt, struct page *freelist)
+ {
+-      struct page *p = virt_to_page((void *)pt);
++      struct page *p = virt_to_page(pt);
+       p->freelist = freelist;
+       return p;
+ }
+-#define DEFINE_FREE_PT_FN(LVL, FN)                                            \
+-static struct page *free_pt_##LVL (unsigned long __pt, struct page *freelist) \
+-{                                                                             \
+-      unsigned long p;                                                        \
+-      u64 *pt;                                                                \
+-      int i;                                                                  \
+-                                                                              \
+-      pt = (u64 *)__pt;                                                       \
+-                                                                              \
+-      for (i = 0; i < 512; ++i) {                                             \
+-              /* PTE present? */                                              \
+-              if (!IOMMU_PTE_PRESENT(pt[i]))                                  \
+-                      continue;                                               \
+-                                                                              \
+-              /* Large PTE? */                                                \
+-              if (PM_PTE_LEVEL(pt[i]) == 0 ||                                 \
+-                  PM_PTE_LEVEL(pt[i]) == 7)                                   \
+-                      continue;                                               \
+-                                                                              \
+-              p = (unsigned long)IOMMU_PTE_PAGE(pt[i]);                       \
+-              freelist = FN(p, freelist);                                     \
+-      }                                                                       \
+-                                                                              \
+-      return free_pt_page((unsigned long)pt, freelist);                       \
+-}
++static struct page *free_pt_lvl(u64 *pt, struct page *freelist, int lvl)
++{
++      u64 *p;
++      int i;
++
++      for (i = 0; i < 512; ++i) {
++              /* PTE present? */
++              if (!IOMMU_PTE_PRESENT(pt[i]))
++                      continue;
+-DEFINE_FREE_PT_FN(l2, free_pt_page)
+-DEFINE_FREE_PT_FN(l3, free_pt_l2)
+-DEFINE_FREE_PT_FN(l4, free_pt_l3)
+-DEFINE_FREE_PT_FN(l5, free_pt_l4)
+-DEFINE_FREE_PT_FN(l6, free_pt_l5)
++              /* Large PTE? */
++              if (PM_PTE_LEVEL(pt[i]) == 0 ||
++                  PM_PTE_LEVEL(pt[i]) == 7)
++                      continue;
+-static struct page *free_sub_pt(unsigned long root, int mode,
+-                              struct page *freelist)
++              /*
++               * Free the next level. No need to look at l1 tables here since
++               * they can only contain leaf PTEs; just free them directly.
++               */
++              p = IOMMU_PTE_PAGE(pt[i]);
++              if (lvl > 2)
++                      freelist = free_pt_lvl(p, freelist, lvl - 1);
++              else
++                      freelist = free_pt_page(p, freelist);
++      }
++
++      return free_pt_page(pt, freelist);
++}
++
++static struct page *free_sub_pt(u64 *root, int mode, struct page *freelist)
+ {
+       switch (mode) {
+       case PAGE_MODE_NONE:
+@@ -136,19 +132,11 @@ static struct page *free_sub_pt(unsigned long root, int mode,
+               freelist = free_pt_page(root, freelist);
+               break;
+       case PAGE_MODE_2_LEVEL:
+-              freelist = free_pt_l2(root, freelist);
+-              break;
+       case PAGE_MODE_3_LEVEL:
+-              freelist = free_pt_l3(root, freelist);
+-              break;
+       case PAGE_MODE_4_LEVEL:
+-              freelist = free_pt_l4(root, freelist);
+-              break;
+       case PAGE_MODE_5_LEVEL:
+-              freelist = free_pt_l5(root, freelist);
+-              break;
+       case PAGE_MODE_6_LEVEL:
+-              freelist = free_pt_l6(root, freelist);
++              free_pt_lvl(root, freelist, mode);
+               break;
+       default:
+               BUG();
+@@ -364,7 +352,7 @@ static u64 *fetch_pte(struct amd_io_pgtable *pgtable,
+ static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist)
+ {
+-      unsigned long pt;
++      u64 *pt;
+       int mode;
+       while (cmpxchg64(pte, pteval, 0) != pteval) {
+@@ -375,7 +363,7 @@ static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist)
+       if (!IOMMU_PTE_PRESENT(pteval))
+               return freelist;
+-      pt   = (unsigned long)IOMMU_PTE_PAGE(pteval);
++      pt   = IOMMU_PTE_PAGE(pteval);
+       mode = IOMMU_PTE_MODE(pteval);
+       return free_sub_pt(pt, mode, freelist);
+@@ -512,7 +500,6 @@ static void v1_free_pgtable(struct io_pgtable *iop)
+       struct amd_io_pgtable *pgtable = container_of(iop, struct amd_io_pgtable, iop);
+       struct protection_domain *dom;
+       struct page *freelist = NULL;
+-      unsigned long root;
+       if (pgtable->mode == PAGE_MODE_NONE)
+               return;
+@@ -529,8 +516,7 @@ static void v1_free_pgtable(struct io_pgtable *iop)
+       BUG_ON(pgtable->mode < PAGE_MODE_NONE ||
+              pgtable->mode > PAGE_MODE_6_LEVEL);
+-      root = (unsigned long)pgtable->root;
+-      freelist = free_sub_pt(root, pgtable->mode, freelist);
++      freelist = free_sub_pt(pgtable->root, pgtable->mode, freelist);
+       free_page_list(freelist);
+ }
+-- 
+2.34.1
+
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 (file)
index 0000000..db20222
--- /dev/null
@@ -0,0 +1,173 @@
+From 9b97aa7b7e805cb43fde64554473bfd458dad907 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Dec 2021 15:30:59 +0000
+Subject: iommu/amd: Use put_pages_list
+
+From: Matthew Wilcox (Oracle) <willy@infradead.org>
+
+[ Upstream commit ce00eece6909c266da123fd147172d745a4f14a0 ]
+
+page->freelist is for the use of slab.  We already have the ability
+to free a list of pages in the core mm, but it requires the use of a
+list_head and for the pages to be chained together through page->lru.
+Switch the AMD IOMMU code over to using free_pages_list().
+
+Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
+[rm: split from original patch, cosmetic tweaks]
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/73af128f651aaa1f38f69e586c66765a88ad2de0.1639753638.git.robin.murphy@arm.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/amd/io_pgtable.c | 50 ++++++++++++----------------------
+ 1 file changed, 18 insertions(+), 32 deletions(-)
+
+diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c
+index 4165e1372b6e..b1bf4125b0f7 100644
+--- a/drivers/iommu/amd/io_pgtable.c
++++ b/drivers/iommu/amd/io_pgtable.c
+@@ -74,26 +74,14 @@ static u64 *first_pte_l7(u64 *pte, unsigned long *page_size,
+  *
+  ****************************************************************************/
+-static void free_page_list(struct page *freelist)
+-{
+-      while (freelist != NULL) {
+-              unsigned long p = (unsigned long)page_address(freelist);
+-
+-              freelist = freelist->freelist;
+-              free_page(p);
+-      }
+-}
+-
+-static struct page *free_pt_page(u64 *pt, struct page *freelist)
++static void free_pt_page(u64 *pt, struct list_head *freelist)
+ {
+       struct page *p = virt_to_page(pt);
+-      p->freelist = freelist;
+-
+-      return p;
++      list_add_tail(&p->lru, freelist);
+ }
+-static struct page *free_pt_lvl(u64 *pt, struct page *freelist, int lvl)
++static void free_pt_lvl(u64 *pt, struct list_head *freelist, int lvl)
+ {
+       u64 *p;
+       int i;
+@@ -114,22 +102,22 @@ static struct page *free_pt_lvl(u64 *pt, struct page *freelist, int lvl)
+                */
+               p = IOMMU_PTE_PAGE(pt[i]);
+               if (lvl > 2)
+-                      freelist = free_pt_lvl(p, freelist, lvl - 1);
++                      free_pt_lvl(p, freelist, lvl - 1);
+               else
+-                      freelist = free_pt_page(p, freelist);
++                      free_pt_page(p, freelist);
+       }
+-      return free_pt_page(pt, freelist);
++      free_pt_page(pt, freelist);
+ }
+-static struct page *free_sub_pt(u64 *root, int mode, struct page *freelist)
++static void free_sub_pt(u64 *root, int mode, struct list_head *freelist)
+ {
+       switch (mode) {
+       case PAGE_MODE_NONE:
+       case PAGE_MODE_7_LEVEL:
+               break;
+       case PAGE_MODE_1_LEVEL:
+-              freelist = free_pt_page(root, freelist);
++              free_pt_page(root, freelist);
+               break;
+       case PAGE_MODE_2_LEVEL:
+       case PAGE_MODE_3_LEVEL:
+@@ -141,8 +129,6 @@ static struct page *free_sub_pt(u64 *root, int mode, struct page *freelist)
+       default:
+               BUG();
+       }
+-
+-      return freelist;
+ }
+ void amd_iommu_domain_set_pgtable(struct protection_domain *domain,
+@@ -350,7 +336,7 @@ static u64 *fetch_pte(struct amd_io_pgtable *pgtable,
+       return pte;
+ }
+-static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist)
++static void free_clear_pte(u64 *pte, u64 pteval, struct list_head *freelist)
+ {
+       u64 *pt;
+       int mode;
+@@ -361,12 +347,12 @@ static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist)
+       }
+       if (!IOMMU_PTE_PRESENT(pteval))
+-              return freelist;
++              return;
+       pt   = IOMMU_PTE_PAGE(pteval);
+       mode = IOMMU_PTE_MODE(pteval);
+-      return free_sub_pt(pt, mode, freelist);
++      free_sub_pt(pt, mode, freelist);
+ }
+ /*
+@@ -380,7 +366,7 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova,
+                         phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
+ {
+       struct protection_domain *dom = io_pgtable_ops_to_domain(ops);
+-      struct page *freelist = NULL;
++      LIST_HEAD(freelist);
+       bool updated = false;
+       u64 __pte, *pte;
+       int ret, i, count;
+@@ -400,9 +386,9 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova,
+               goto out;
+       for (i = 0; i < count; ++i)
+-              freelist = free_clear_pte(&pte[i], pte[i], freelist);
++              free_clear_pte(&pte[i], pte[i], &freelist);
+-      if (freelist != NULL)
++      if (!list_empty(&freelist))
+               updated = true;
+       if (count > 1) {
+@@ -437,7 +423,7 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova,
+       }
+       /* Everything flushed out, free pages now */
+-      free_page_list(freelist);
++      put_pages_list(&freelist);
+       return ret;
+ }
+@@ -499,7 +485,7 @@ static void v1_free_pgtable(struct io_pgtable *iop)
+ {
+       struct amd_io_pgtable *pgtable = container_of(iop, struct amd_io_pgtable, iop);
+       struct protection_domain *dom;
+-      struct page *freelist = NULL;
++      LIST_HEAD(freelist);
+       if (pgtable->mode == PAGE_MODE_NONE)
+               return;
+@@ -516,9 +502,9 @@ static void v1_free_pgtable(struct io_pgtable *iop)
+       BUG_ON(pgtable->mode < PAGE_MODE_NONE ||
+              pgtable->mode > PAGE_MODE_6_LEVEL);
+-      freelist = free_sub_pt(pgtable->root, pgtable->mode, freelist);
++      free_sub_pt(pgtable->root, pgtable->mode, &freelist);
+-      free_page_list(freelist);
++      put_pages_list(&freelist);
+ }
+ static struct io_pgtable *v1_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
+-- 
+2.34.1
+
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 (file)
index 0000000..7cabd2b
--- /dev/null
@@ -0,0 +1,95 @@
+From 90d2cd4918401b6fdee1b6886399d4dbbed4429c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Feb 2022 08:13:44 +0800
+Subject: MIPS: ralink: mt7621: do memory detection on KSEG1
+
+From: Chuanhong Guo <gch981213@gmail.com>
+
+[ Upstream commit cc19db8b312a6c75645645f5cc1b45166b109006 ]
+
+It's reported that current memory detection code occasionally detects
+larger memory under some bootloaders.
+Current memory detection code tests whether address space wraps around
+on KSEG0, which is unreliable because it's cached.
+
+Rewrite memory size detection to perform the same test on KSEG1 instead.
+While at it, this patch also does the following two things:
+1. use a fixed pattern instead of a random function pointer as the magic
+   value.
+2. add an additional memory write and a second comparison as part of the
+   test to prevent possible smaller memory detection result due to
+   leftover values in memory.
+
+Fixes: 139c949f7f0a MIPS: ("ralink: mt7621: add memory detection support")
+Reported-by: Rui Salvaterra <rsalvaterra@gmail.com>
+Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
+Tested-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
+Tested-by: Rui Salvaterra <rsalvaterra@gmail.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/ralink/mt7621.c | 36 +++++++++++++++++++++++-------------
+ 1 file changed, 23 insertions(+), 13 deletions(-)
+
+diff --git a/arch/mips/ralink/mt7621.c b/arch/mips/ralink/mt7621.c
+index bd71f5b14238..fd9a872d5713 100644
+--- a/arch/mips/ralink/mt7621.c
++++ b/arch/mips/ralink/mt7621.c
+@@ -20,31 +20,41 @@
+ #include "common.h"
+-static void *detect_magic __initdata = detect_memory_region;
++#define MT7621_MEM_TEST_PATTERN         0xaa5555aa
++
++static u32 detect_magic __initdata;
+ phys_addr_t mips_cpc_default_phys_base(void)
+ {
+       panic("Cannot detect cpc address");
+ }
++static bool __init mt7621_addr_wraparound_test(phys_addr_t size)
++{
++      void *dm = (void *)KSEG1ADDR(&detect_magic);
++
++      if (CPHYSADDR(dm + size) >= MT7621_LOWMEM_MAX_SIZE)
++              return true;
++      __raw_writel(MT7621_MEM_TEST_PATTERN, dm);
++      if (__raw_readl(dm) != __raw_readl(dm + size))
++              return false;
++      __raw_writel(!MT7621_MEM_TEST_PATTERN, dm);
++      return __raw_readl(dm) == __raw_readl(dm + size);
++}
++
+ static void __init mt7621_memory_detect(void)
+ {
+-      void *dm = &detect_magic;
+       phys_addr_t size;
+-      for (size = 32 * SZ_1M; size < 256 * SZ_1M; size <<= 1) {
+-              if (!__builtin_memcmp(dm, dm + size, sizeof(detect_magic)))
+-                      break;
++      for (size = 32 * SZ_1M; size <= 256 * SZ_1M; size <<= 1) {
++              if (mt7621_addr_wraparound_test(size)) {
++                      memblock_add(MT7621_LOWMEM_BASE, size);
++                      return;
++              }
+       }
+-      if ((size == 256 * SZ_1M) &&
+-          (CPHYSADDR(dm + size) < MT7621_LOWMEM_MAX_SIZE) &&
+-          __builtin_memcmp(dm, dm + size, sizeof(detect_magic))) {
+-              memblock_add(MT7621_LOWMEM_BASE, MT7621_LOWMEM_MAX_SIZE);
+-              memblock_add(MT7621_HIGHMEM_BASE, MT7621_HIGHMEM_SIZE);
+-      } else {
+-              memblock_add(MT7621_LOWMEM_BASE, size);
+-      }
++      memblock_add(MT7621_LOWMEM_BASE, MT7621_LOWMEM_MAX_SIZE);
++      memblock_add(MT7621_HIGHMEM_BASE, MT7621_HIGHMEM_SIZE);
+ }
+ void __init ralink_of_remap(void)
+-- 
+2.34.1
+
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 (file)
index 0000000..0288155
--- /dev/null
@@ -0,0 +1,38 @@
+From 279cbb489e2ac9bf7d70563b73f6efc939ccf4be Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Feb 2022 17:15:07 -0800
+Subject: MIPS: ralink: mt7621: use bitwise NOT instead of logical
+
+From: Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
+
+[ Upstream commit 5d8965704fe5662e2e4a7e4424a2cbe53e182670 ]
+
+It was the intention to reverse the bits, not make them all zero by
+using logical NOT operator.
+
+Fixes: cc19db8b312a ("MIPS: ralink: mt7621: do memory detection on KSEG1")
+Suggested-by: Chuanhong Guo <gch981213@gmail.com>
+Signed-off-by: Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
+Reviewed-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/ralink/mt7621.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/mips/ralink/mt7621.c b/arch/mips/ralink/mt7621.c
+index fd9a872d5713..4c8378661219 100644
+--- a/arch/mips/ralink/mt7621.c
++++ b/arch/mips/ralink/mt7621.c
+@@ -38,7 +38,7 @@ static bool __init mt7621_addr_wraparound_test(phys_addr_t size)
+       __raw_writel(MT7621_MEM_TEST_PATTERN, dm);
+       if (__raw_readl(dm) != __raw_readl(dm + size))
+               return false;
+-      __raw_writel(!MT7621_MEM_TEST_PATTERN, dm);
++      __raw_writel(~MT7621_MEM_TEST_PATTERN, dm);
+       return __raw_readl(dm) == __raw_readl(dm + size);
+ }
+-- 
+2.34.1
+
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 (file)
index 0000000..8fd5e20
--- /dev/null
@@ -0,0 +1,37 @@
+From 696a45300c2778081637ac3f1e1b1c21bd21d6ca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Feb 2022 04:37:27 -0800
+Subject: net: chelsio: cxgb3: check the return value of pci_find_capability()
+
+From: Jia-Ju Bai <baijiaju1990@gmail.com>
+
+[ Upstream commit 767b9825ed1765894e569a3d698749d40d83762a ]
+
+The function pci_find_capability() in t3_prep_adapter() can fail, so its
+return value should be checked.
+
+Fixes: 4d22de3e6cc4 ("Add support for the latest 1G/10G Chelsio adapter, T3")
+Reported-by: TOTE Robot <oslab@tsinghua.edu.cn>
+Signed-off-by: Jia-Ju Bai <baijiaju1990@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/chelsio/cxgb3/t3_hw.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
+index 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 (file)
index 0000000..ceea55b
--- /dev/null
@@ -0,0 +1,62 @@
+From a6b4965c98b3db02b009b1102ac8333f7a020dcc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Mar 2022 21:39:39 +0200
+Subject: net: dcb: disable softirqs in dcbnl_flush_dev()
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit 10b6bb62ae1a49ee818fc479cf57b8900176773e ]
+
+Ido Schimmel points out that since commit 52cff74eef5d ("dcbnl : Disable
+software interrupts before taking dcb_lock"), the DCB API can be called
+by drivers from softirq context.
+
+One such in-tree example is the chelsio cxgb4 driver:
+dcb_rpl
+-> cxgb4_dcb_handle_fw_update
+   -> dcb_ieee_setapp
+
+If the firmware for this driver happened to send an event which resulted
+in a call to dcb_ieee_setapp() at the exact same time as another
+DCB-enabled interface was unregistering on the same CPU, the softirq
+would deadlock, because the interrupted process was already holding the
+dcb_lock in dcbnl_flush_dev().
+
+Fix this unlikely event by using spin_lock_bh() in dcbnl_flush_dev() as
+in the rest of the dcbnl code.
+
+Fixes: 91b0383fef06 ("net: dcb: flush lingering app table entries for unregistered devices")
+Reported-by: Ido Schimmel <idosch@idosch.org>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Link: https://lore.kernel.org/r/20220302193939.1368823-1-vladimir.oltean@nxp.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/dcb/dcbnl.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
+index 36c91273daac..dc4fb699b56c 100644
+--- a/net/dcb/dcbnl.c
++++ b/net/dcb/dcbnl.c
+@@ -2077,7 +2077,7 @@ static void dcbnl_flush_dev(struct net_device *dev)
+ {
+       struct dcb_app_type *itr, *tmp;
+-      spin_lock(&dcb_lock);
++      spin_lock_bh(&dcb_lock);
+       list_for_each_entry_safe(itr, tmp, &dcb_app_list, list) {
+               if (itr->ifindex == dev->ifindex) {
+@@ -2086,7 +2086,7 @@ static void dcbnl_flush_dev(struct net_device *dev)
+               }
+       }
+-      spin_unlock(&dcb_lock);
++      spin_unlock_bh(&dcb_lock);
+ }
+ static int dcbnl_netdevice_event(struct notifier_block *nb,
+-- 
+2.34.1
+
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 (file)
index 0000000..ea48faf
--- /dev/null
@@ -0,0 +1,64 @@
+From 21949ec920470d43decf8bd3bfd61cabaf8b6921 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Feb 2022 11:15:16 +0100
+Subject: net: sparx5: Fix add vlan when invalid operation
+
+From: Casper Andersson <casper.casan@gmail.com>
+
+[ Upstream commit b3a34dc362c03215031b268fcc0b988e69490231 ]
+
+Check if operation is valid before changing any
+settings in hardware. Otherwise it results in
+changes being made despite it not being a valid
+operation.
+
+Fixes: 78eab33bb68b ("net: sparx5: add vlan support")
+
+Signed-off-by: Casper Andersson <casper.casan@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/microchip/sparx5/sparx5_vlan.c   | 20 +++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c b/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c
+index 4ce490a25f33..8e56ffa1c4f7 100644
+--- a/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c
++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c
+@@ -58,16 +58,6 @@ int sparx5_vlan_vid_add(struct sparx5_port *port, u16 vid, bool pvid,
+       struct sparx5 *sparx5 = port->sparx5;
+       int ret;
+-      /* Make the port a member of the VLAN */
+-      set_bit(port->portno, sparx5->vlan_mask[vid]);
+-      ret = sparx5_vlant_set_mask(sparx5, vid);
+-      if (ret)
+-              return ret;
+-
+-      /* Default ingress vlan classification */
+-      if (pvid)
+-              port->pvid = vid;
+-
+       /* Untagged egress vlan classification */
+       if (untagged && port->vid != vid) {
+               if (port->vid) {
+@@ -79,6 +69,16 @@ int sparx5_vlan_vid_add(struct sparx5_port *port, u16 vid, bool pvid,
+               port->vid = vid;
+       }
++      /* Make the port a member of the VLAN */
++      set_bit(port->portno, sparx5->vlan_mask[vid]);
++      ret = sparx5_vlant_set_mask(sparx5, vid);
++      if (ret)
++              return ret;
++
++      /* Default ingress vlan classification */
++      if (pvid)
++              port->pvid = vid;
++
+       sparx5_vlan_port_apply(sparx5, port);
+       return 0;
+-- 
+2.34.1
+
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 (file)
index 0000000..7eb742b
--- /dev/null
@@ -0,0 +1,255 @@
+From 8ea5f75e7f58ea847eda2afe6529f06b9f1b617a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 11 Nov 2021 22:39:49 +0800
+Subject: net: stmmac: enhance XDP ZC driver level switching performance
+
+From: Ong Boon Leong <boon.leong.ong@intel.com>
+
+[ Upstream commit ac746c8520d9d056b6963ecca8ff1da9929d02f1 ]
+
+The previous stmmac_xdp_set_prog() implementation uses stmmac_release()
+and stmmac_open() which tear down the PHY device and causes undesirable
+autonegotiation which causes a delay whenever AFXDP ZC is setup.
+
+This patch introduces two new functions that just sufficiently tear
+down DMA descriptors, buffer, NAPI process, and IRQs and reestablish
+them accordingly in both stmmac_xdp_release() and stammac_xdp_open().
+
+As the results of this enhancement, we get rid of transient state
+introduced by the link auto-negotiation:
+
+$ ./xdpsock -i eth0 -t -z
+
+ sock0@eth0:0 txonly xdp-drv
+                   pps            pkts           1.00
+rx                 0              0
+tx                 634444         634560
+
+ sock0@eth0:0 txonly xdp-drv
+                   pps            pkts           1.00
+rx                 0              0
+tx                 632330         1267072
+
+ sock0@eth0:0 txonly xdp-drv
+                   pps            pkts           1.00
+rx                 0              0
+tx                 632438         1899584
+
+ sock0@eth0:0 txonly xdp-drv
+                   pps            pkts           1.00
+rx                 0              0
+tx                 632502         2532160
+
+Reported-by: Kurt Kanzenbach <kurt@linutronix.de>
+Signed-off-by: Ong Boon Leong <boon.leong.ong@intel.com>
+Tested-by: Kurt Kanzenbach <kurt@linutronix.de>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac.h  |   4 +-
+ .../net/ethernet/stmicro/stmmac/stmmac_main.c | 137 +++++++++++++++++-
+ .../net/ethernet/stmicro/stmmac/stmmac_xdp.c  |   4 +-
+ 3 files changed, 139 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+index 873b9e3e5da2..05b5371ca036 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+@@ -334,8 +334,8 @@ void stmmac_set_ethtool_ops(struct net_device *netdev);
+ int stmmac_init_tstamp_counter(struct stmmac_priv *priv, u32 systime_flags);
+ void stmmac_ptp_register(struct stmmac_priv *priv);
+ void stmmac_ptp_unregister(struct stmmac_priv *priv);
+-int stmmac_open(struct net_device *dev);
+-int stmmac_release(struct net_device *dev);
++int stmmac_xdp_open(struct net_device *dev);
++void stmmac_xdp_release(struct net_device *dev);
+ int stmmac_resume(struct device *dev);
+ int stmmac_suspend(struct device *dev);
+ int stmmac_dvr_remove(struct device *dev);
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 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 (file)
index 0000000..0f75ec9
--- /dev/null
@@ -0,0 +1,111 @@
+From a70594c1daf30392e0ca9f667f9e52da57e89cd3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Feb 2022 12:38:29 +0100
+Subject: net: stmmac: only enable DMA interrupts when ready
+
+From: Vincent Whitchurch <vincent.whitchurch@axis.com>
+
+[ Upstream commit 087a7b944c5db409f7c1a68bf4896c56ba54eaff ]
+
+In this driver's ->ndo_open() callback, it enables DMA interrupts,
+starts the DMA channels, then requests interrupts with request_irq(),
+and then finally enables napi.
+
+If RX DMA interrupts are received before napi is enabled, no processing
+is done because napi_schedule_prep() will return false.  If the network
+has a lot of broadcast/multicast traffic, then the RX ring could fill up
+completely before napi is enabled.  When this happens, no further RX
+interrupts will be delivered, and the driver will fail to receive any
+packets.
+
+Fix this by only enabling DMA interrupts after all other initialization
+is complete.
+
+Fixes: 523f11b5d4fd72efb ("net: stmmac: move hardware setup for stmmac_open to new function")
+Reported-by: Lars Persson <larper@axis.com>
+Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/stmicro/stmmac/stmmac_main.c | 28 +++++++++++++++++--
+ 1 file changed, 26 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 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 (file)
index 0000000..eaf8827
--- /dev/null
@@ -0,0 +1,53 @@
+From dcc32a297a6e5a2285ef4a2da88575aa9126c51f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Feb 2022 10:13:31 -0800
+Subject: netfilter: nf_tables: prefer kfree_rcu(ptr, rcu) variant
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit ae089831ff28a115908b8d796f667c2dadef1637 ]
+
+While kfree_rcu(ptr) _is_ supported, it has some limitations.
+
+Given that 99.99% of kfree_rcu() users [1] use the legacy
+two parameters variant, and @catchall objects do have an rcu head,
+simply use it.
+
+Choice of kfree_rcu(ptr) variant was probably not intentional.
+
+[1] including calls from net/netfilter/nf_tables_api.c
+
+Fixes: aaa31047a6d2 ("netfilter: nftables: add catch-all set element support")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_tables_api.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index a65b530975f5..2b2e0210a7f9 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -4486,7 +4486,7 @@ static void nft_set_catchall_destroy(const struct nft_ctx *ctx,
+       list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
+               list_del_rcu(&catchall->list);
+               nft_set_elem_destroy(set, catchall->elem, true);
+-              kfree_rcu(catchall);
++              kfree_rcu(catchall, rcu);
+       }
+ }
+@@ -5653,7 +5653,7 @@ static void nft_setelem_catchall_remove(const struct net *net,
+       list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
+               if (catchall->elem == elem->priv) {
+                       list_del_rcu(&catchall->list);
+-                      kfree_rcu(catchall);
++                      kfree_rcu(catchall, rcu);
+                       break;
+               }
+       }
+-- 
+2.34.1
+
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 (file)
index 0000000..dad9b8f
--- /dev/null
@@ -0,0 +1,54 @@
+From 9f3a11cfeed63bf0efc3ef4a0c06480ceb44158b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Mar 2022 18:00:20 +0800
+Subject: nl80211: Handle nla_memdup failures in handle_nan_filter
+
+From: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+
+[ Upstream commit 6ad27f522cb3b210476daf63ce6ddb6568c0508b ]
+
+As there's potential for failure of the nla_memdup(),
+check the return value.
+
+Fixes: a442b761b24b ("cfg80211: add add_nan_func / del_nan_func")
+Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+Link: https://lore.kernel.org/r/20220301100020.3801187-1-jiasheng@iscas.ac.cn
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/wireless/nl80211.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index 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 (file)
index 0000000..4e6b1e3
--- /dev/null
@@ -0,0 +1,57 @@
+From 06fac660a8d74c994c2987c358710ca2e0e1b396 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Mar 2022 18:14:47 +0200
+Subject: selftests: mlxsw: resource_scale: Fix return value
+
+From: Amit Cohen <amcohen@nvidia.com>
+
+[ Upstream commit 196f9bc050cbc5085b4cbb61cce2efe380bc66d0 ]
+
+The test runs several test cases and is supposed to return an error in
+case at least one of them failed.
+
+Currently, the check of the return value of each test case is in the
+wrong place, which can result in the wrong return value. For example:
+
+ # TESTS='tc_police' ./resource_scale.sh
+ TEST: 'tc_police' [default] 968                                     [FAIL]
+         tc police offload count failed
+ Error: mlxsw_spectrum: Failed to allocate policer index.
+ We have an error talking to the kernel
+ Command failed /tmp/tmp.i7Oc5HwmXY:969
+ TEST: 'tc_police' [default] overflow 969                            [ OK ]
+ ...
+ TEST: 'tc_police' [ipv4_max] overflow 969                           [ OK ]
+
+ $ echo $?
+ 0
+
+Fix this by moving the check to be done after each test case.
+
+Fixes: 059b18e21c63 ("selftests: mlxsw: Return correct error code in resource scale test")
+Signed-off-by: Amit Cohen <amcohen@nvidia.com>
+Reviewed-by: Petr Machata <petrm@nvidia.com>
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/drivers/net/mlxsw/spectrum/resource_scale.sh      | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh
+index 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
+
index 832c658a26d12841b65ce22532b95b58f5caf491..542d736b5334a0b419de00eee5634497d92b82d1 100644 (file)
@@ -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 (file)
index 0000000..591284d
--- /dev/null
@@ -0,0 +1,49 @@
+From c014bf6ee7c6da9a72a63c028da917216074ee39 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Nov 2021 21:00:33 +0100
+Subject: soc: fsl: guts: Add a missing memory allocation failure check
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit b9abe942cda43a1d46a0fd96efb54f1aa909f757 ]
+
+If 'devm_kstrdup()' fails, we should return -ENOMEM.
+
+While at it, move the 'of_node_put()' call in the error handling path and
+after the 'machine' has been copied.
+Better safe than sorry.
+
+Fixes: a6fc3b698130 ("soc: fsl: add GUTS driver for QorIQ platforms")
+Depends-on: fddacc7ff4dd ("soc: fsl: guts: Revert commit 3c0d64e867ed")
+Suggested-by: Tyrel Datwyler <tyreld@linux.ibm.com>
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Signed-off-by: Li Yang <leoyang.li@nxp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/fsl/guts.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c
+index 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 (file)
index 0000000..ffc358f
--- /dev/null
@@ -0,0 +1,66 @@
+From a20b918f6b4aa4ed5ed658693b71d2dba4825d41 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Nov 2021 21:00:17 +0100
+Subject: soc: fsl: guts: Revert commit 3c0d64e867ed
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit b113737cf12964a20cc3ba1ddabe6229099661c6 ]
+
+This reverts commit 3c0d64e867ed
+("soc: fsl: guts: reuse machine name from device tree").
+
+A following patch will fix the missing memory allocation failure check
+instead.
+
+Suggested-by: Tyrel Datwyler <tyreld@linux.ibm.com>
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Signed-off-by: Li Yang <leoyang.li@nxp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/fsl/guts.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c
+index 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 (file)
index 0000000..7d63f6e
--- /dev/null
@@ -0,0 +1,43 @@
+From 6d48e5679e0c32f8640ecbe10d46bb400557f282 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Dec 2021 09:45:43 +0800
+Subject: soc: fsl: qe: Check of ioremap return value
+
+From: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+
+[ Upstream commit a222fd8541394b36b13c89d1698d9530afd59a9c ]
+
+As the possible failure of the ioremap(), the par_io could be NULL.
+Therefore it should be better to check it and return error in order to
+guarantee the success of the initiation.
+But, I also notice that all the caller like mpc85xx_qe_par_io_init() in
+`arch/powerpc/platforms/85xx/common.c` don't check the return value of
+the par_io_init().
+Actually, par_io_init() needs to check to handle the potential error.
+I will submit another patch to fix that.
+Anyway, par_io_init() itsely should be fixed.
+
+Fixes: 7aa1aa6ecec2 ("QE: Move QE from arch/powerpc to drivers/soc")
+Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+Signed-off-by: Li Yang <leoyang.li@nxp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/fsl/qe/qe_io.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/soc/fsl/qe/qe_io.c b/drivers/soc/fsl/qe/qe_io.c
+index e277c827bdf3..a5e2d0e5ab51 100644
+--- a/drivers/soc/fsl/qe/qe_io.c
++++ b/drivers/soc/fsl/qe/qe_io.c
+@@ -35,6 +35,8 @@ int par_io_init(struct device_node *np)
+       if (ret)
+               return ret;
+       par_io = ioremap(res.start, resource_size(&res));
++      if (!par_io)
++              return -ENOMEM;
+       if (!of_property_read_u32(np, "num-ports", &num_ports))
+               num_par_io_ports = num_ports;
+-- 
+2.34.1
+