]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 23 Apr 2024 16:35:26 +0000 (09:35 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 23 Apr 2024 16:35:26 +0000 (09:35 -0700)
added patches:
net-dsa-mt7530-fix-enabling-eee-on-mt7531-switch-on-all-boards.patch
net-dsa-mt7530-fix-improper-frames-on-all-25mhz-and-40mhz-xtal-mt7530.patch
powerpc-ftrace-ignore-ftrace-locations-in-exit-text-sections.patch
virtio_net-do-not-send-rss-key-if-it-is-not-supported.patch

queue-6.6/net-dsa-mt7530-fix-enabling-eee-on-mt7531-switch-on-all-boards.patch [new file with mode: 0644]
queue-6.6/net-dsa-mt7530-fix-improper-frames-on-all-25mhz-and-40mhz-xtal-mt7530.patch [new file with mode: 0644]
queue-6.6/powerpc-ftrace-ignore-ftrace-locations-in-exit-text-sections.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/virtio_net-do-not-send-rss-key-if-it-is-not-supported.patch [new file with mode: 0644]

diff --git a/queue-6.6/net-dsa-mt7530-fix-enabling-eee-on-mt7531-switch-on-all-boards.patch b/queue-6.6/net-dsa-mt7530-fix-enabling-eee-on-mt7531-switch-on-all-boards.patch
new file mode 100644 (file)
index 0000000..c764457
--- /dev/null
@@ -0,0 +1,101 @@
+From 06dfcd4098cfdc4d4577d94793a4f9125386da8b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Mon, 8 Apr 2024 10:08:53 +0300
+Subject: net: dsa: mt7530: fix enabling EEE on MT7531 switch on all boards
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Arınç ÜNAL <arinc.unal@arinc9.com>
+
+commit 06dfcd4098cfdc4d4577d94793a4f9125386da8b upstream.
+
+The commit 40b5d2f15c09 ("net: dsa: mt7530: Add support for EEE features")
+brought EEE support but did not enable EEE on MT7531 switch MACs. EEE is
+enabled on MT7531 switch MACs by pulling the LAN2LED0 pin low on the board
+(bootstrapping), unsetting the EEE_DIS bit on the trap register, or setting
+the internal EEE switch bit on the CORE_PLL_GROUP4 register. Thanks to
+SkyLake Huang (黃啟澤) from MediaTek for providing information on the
+internal EEE switch bit.
+
+There are existing boards that were not designed to pull the pin low.
+Because of that, the EEE status currently depends on the board design.
+
+The EEE_DIS bit on the trap pertains to the LAN2LED0 pin which is usually
+used to control an LED. Once the bit is unset, the pin will be low. That
+will make the active low LED turn on. The pin is controlled by the switch
+PHY. It seems that the PHY controls the pin in the way that it inverts the
+pin state. That means depending on the wiring of the LED connected to
+LAN2LED0 on the board, the LED may be on without an active link.
+
+To not cause this unwanted behaviour whilst enabling EEE on all boards, set
+the internal EEE switch bit on the CORE_PLL_GROUP4 register.
+
+My testing on MT7531 shows a certain amount of traffic loss when EEE is
+enabled. That said, I haven't come across a board that enables EEE. So
+enable EEE on the switch MACs but disable EEE advertisement on the switch
+PHYs. This way, we don't change the behaviour of the majority of the boards
+that have this switch. The mediatek-ge PHY driver already disables EEE
+advertisement on the switch PHYs but my testing shows that it is somehow
+enabled afterwards. Disabling EEE advertisement before the PHY driver
+initialises keeps it off.
+
+With this change, EEE can now be enabled using ethtool.
+
+Fixes: 40b5d2f15c09 ("net: dsa: mt7530: Add support for EEE features")
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Tested-by: Daniel Golle <daniel@makrotopia.org>
+Reviewed-by: Daniel Golle <daniel@makrotopia.org>
+Link: https://lore.kernel.org/r/20240408-for-net-mt7530-fix-eee-for-mt7531-mt7988-v3-1-84fdef1f008b@arinc9.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/dsa/mt7530.c |   17 ++++++++++++-----
+ drivers/net/dsa/mt7530.h |    1 +
+ 2 files changed, 13 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2713,18 +2713,25 @@ mt7531_setup(struct dsa_switch *ds)
+       priv->p5_interface = PHY_INTERFACE_MODE_NA;
+       priv->p6_interface = PHY_INTERFACE_MODE_NA;
+-      /* Enable PHY core PLL, since phy_device has not yet been created
+-       * provided for phy_[read,write]_mmd_indirect is called, we provide
+-       * our own mt7531_ind_mmd_phy_[read,write] to complete this
+-       * function.
++      /* Enable Energy-Efficient Ethernet (EEE) and PHY core PLL, since
++       * phy_device has not yet been created provided for
++       * phy_[read,write]_mmd_indirect is called, we provide our own
++       * mt7531_ind_mmd_phy_[read,write] to complete this function.
+        */
+       val = mt7531_ind_c45_phy_read(priv, MT753X_CTRL_PHY_ADDR,
+                                     MDIO_MMD_VEND2, CORE_PLL_GROUP4);
+-      val |= MT7531_PHY_PLL_BYPASS_MODE;
++      val |= MT7531_RG_SYSPLL_DMY2 | MT7531_PHY_PLL_BYPASS_MODE;
+       val &= ~MT7531_PHY_PLL_OFF;
+       mt7531_ind_c45_phy_write(priv, MT753X_CTRL_PHY_ADDR, MDIO_MMD_VEND2,
+                                CORE_PLL_GROUP4, val);
++      /* Disable EEE advertisement on the switch PHYs. */
++      for (i = MT753X_CTRL_PHY_ADDR;
++           i < MT753X_CTRL_PHY_ADDR + MT7530_NUM_PHYS; i++) {
++              mt7531_ind_c45_phy_write(priv, i, MDIO_MMD_AN, MDIO_AN_EEE_ADV,
++                                       0);
++      }
++
+       mt7531_setup_common(ds);
+       /* Setup VLAN ID 0 for VLAN-unaware bridges */
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -634,6 +634,7 @@ enum mt7531_clk_skew {
+ #define  RG_SYSPLL_DDSFBK_EN          BIT(12)
+ #define  RG_SYSPLL_BIAS_EN            BIT(11)
+ #define  RG_SYSPLL_BIAS_LPF_EN                BIT(10)
++#define  MT7531_RG_SYSPLL_DMY2                BIT(6)
+ #define  MT7531_PHY_PLL_OFF           BIT(5)
+ #define  MT7531_PHY_PLL_BYPASS_MODE   BIT(4)
diff --git a/queue-6.6/net-dsa-mt7530-fix-improper-frames-on-all-25mhz-and-40mhz-xtal-mt7530.patch b/queue-6.6/net-dsa-mt7530-fix-improper-frames-on-all-25mhz-and-40mhz-xtal-mt7530.patch
new file mode 100644 (file)
index 0000000..5327d27
--- /dev/null
@@ -0,0 +1,79 @@
+From 5f563c31ff0c40ce395d0bae7daa94c7950dac97 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Wed, 20 Mar 2024 23:45:30 +0300
+Subject: net: dsa: mt7530: fix improper frames on all 25MHz and 40MHz XTAL MT7530
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Arınç ÜNAL <arinc.unal@arinc9.com>
+
+commit 5f563c31ff0c40ce395d0bae7daa94c7950dac97 upstream.
+
+The MT7530 switch after reset initialises with a core clock frequency that
+works with a 25MHz XTAL connected to it. For 40MHz XTAL, the core clock
+frequency must be set to 500MHz.
+
+The mt7530_pll_setup() function is responsible of setting the core clock
+frequency. Currently, it runs on MT7530 with 25MHz and 40MHz XTAL. This
+causes MT7530 switch with 25MHz XTAL to egress and ingress frames
+improperly.
+
+Introduce a check to run it only on MT7530 with 40MHz XTAL.
+
+The core clock frequency is set by writing to a switch PHY's register.
+Access to the PHY's register is done via the MDIO bus the switch is also
+on. Therefore, it works only when the switch makes switch PHYs listen on
+the MDIO bus the switch is on. This is controlled either by the state of
+the ESW_P1_LED_1 pin after reset deassertion or modifying bit 5 of the
+modifiable trap register.
+
+When ESW_P1_LED_1 is pulled high, PHY indirect access is used. That means
+accessing PHY registers via the PHY indirect access control register of the
+switch.
+
+When ESW_P1_LED_1 is pulled low, PHY direct access is used. That means
+accessing PHY registers via the MDIO bus the switch is on.
+
+For MT7530 switch with 40MHz XTAL on a board with ESW_P1_LED_1 pulled high,
+the core clock frequency won't be set to 500MHz, causing the switch to
+egress and ingress frames improperly.
+
+Run mt7530_pll_setup() after PHY direct access is set on the modifiable
+trap register.
+
+With these two changes, all MT7530 switches with 25MHz and 40MHz, and
+P1_LED_1 pulled high or low, will egress and ingress frames properly.
+
+Link: https://github.com/BPI-SINOVOIP/BPI-R2-bsp/blob/4a5dd143f2172ec97a2872fa29c7c4cd520f45b5/linux-mt/drivers/net/ethernet/mediatek/gsw_mt7623.c#L1039
+Fixes: b8f126a8d543 ("net-next: dsa: add dsa support for Mediatek MT7530 switch")
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Link: https://lore.kernel.org/r/20240320-for-net-mt7530-fix-25mhz-xtal-with-direct-phy-access-v1-1-d92f605f1160@arinc9.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/dsa/mt7530.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2472,8 +2472,6 @@ mt7530_setup(struct dsa_switch *ds)
+                    SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST |
+                    SYS_CTRL_REG_RST);
+-      mt7530_pll_setup(priv);
+-
+       /* Lower Tx driving for TRGMII path */
+       for (i = 0; i < NUM_TRGMII_CTRL; i++)
+               mt7530_write(priv, MT7530_TRGMII_TD_ODT(i),
+@@ -2491,6 +2489,9 @@ mt7530_setup(struct dsa_switch *ds)
+       priv->p6_interface = PHY_INTERFACE_MODE_NA;
++      if ((val & HWTRAP_XTAL_MASK) == HWTRAP_XTAL_40MHZ)
++              mt7530_pll_setup(priv);
++
+       mt753x_trap_frames(priv);
+       /* Enable and reset MIB counters */
diff --git a/queue-6.6/powerpc-ftrace-ignore-ftrace-locations-in-exit-text-sections.patch b/queue-6.6/powerpc-ftrace-ignore-ftrace-locations-in-exit-text-sections.patch
new file mode 100644 (file)
index 0000000..0d274ae
--- /dev/null
@@ -0,0 +1,157 @@
+From ea73179e64131bcd29ba6defd33732abdf8ca14b Mon Sep 17 00:00:00 2001
+From: Naveen N Rao <naveen@kernel.org>
+Date: Tue, 13 Feb 2024 23:24:10 +0530
+Subject: powerpc/ftrace: Ignore ftrace locations in exit text sections
+
+From: Naveen N Rao <naveen@kernel.org>
+
+commit ea73179e64131bcd29ba6defd33732abdf8ca14b upstream.
+
+Michael reported that we are seeing an ftrace bug on bootup when KASAN
+is enabled and we are using -fpatchable-function-entry:
+
+  ftrace: allocating 47780 entries in 18 pages
+  ftrace-powerpc: 0xc0000000020b3d5c: No module provided for non-kernel address
+  ------------[ ftrace bug ]------------
+  ftrace faulted on modifying
+  [<c0000000020b3d5c>] 0xc0000000020b3d5c
+  Initializing ftrace call sites
+  ftrace record flags: 0
+   (0)
+   expected tramp: c00000000008cef4
+  ------------[ cut here ]------------
+  WARNING: CPU: 0 PID: 0 at kernel/trace/ftrace.c:2180 ftrace_bug+0x3c0/0x424
+  Modules linked in:
+  CPU: 0 PID: 0 Comm: swapper Not tainted 6.5.0-rc3-00120-g0f71dcfb4aef #860
+  Hardware name: IBM pSeries (emulated by qemu) POWER9 (raw) 0x4e1202 0xf000005 of:SLOF,HEAD hv:linux,kvm pSeries
+  NIP:  c0000000003aa81c LR: c0000000003aa818 CTR: 0000000000000000
+  REGS: c0000000033cfab0 TRAP: 0700   Not tainted  (6.5.0-rc3-00120-g0f71dcfb4aef)
+  MSR:  8000000002021033 <SF,VEC,ME,IR,DR,RI,LE>  CR: 28028240  XER: 00000000
+  CFAR: c0000000002781a8 IRQMASK: 3
+  ...
+  NIP [c0000000003aa81c] ftrace_bug+0x3c0/0x424
+  LR [c0000000003aa818] ftrace_bug+0x3bc/0x424
+  Call Trace:
+   ftrace_bug+0x3bc/0x424 (unreliable)
+   ftrace_process_locs+0x5f4/0x8a0
+   ftrace_init+0xc0/0x1d0
+   start_kernel+0x1d8/0x484
+
+With CONFIG_FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY=y and
+CONFIG_KASAN=y, compiler emits nops in functions that it generates for
+registering and unregistering global variables (unlike with -pg and
+-mprofile-kernel where calls to _mcount() are not generated in those
+functions). Those functions then end up in INIT_TEXT and EXIT_TEXT
+respectively. We don't expect to see any profiled functions in
+EXIT_TEXT, so ftrace_init_nop() assumes that all addresses that aren't
+in the core kernel text belongs to a module. Since these functions do
+not match that criteria, we see the above bug.
+
+Address this by having ftrace ignore all locations in the text exit
+sections of vmlinux.
+
+Fixes: 0f71dcfb4aef ("powerpc/ftrace: Add support for -fpatchable-function-entry")
+Cc: stable@vger.kernel.org # v6.6+
+Reported-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Naveen N Rao <naveen@kernel.org>
+Reviewed-by: Benjamin Gray <bgray@linux.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://msgid.link/20240213175410.1091313-1-naveen@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/powerpc/include/asm/ftrace.h        |   10 ++--------
+ arch/powerpc/include/asm/sections.h      |    1 +
+ arch/powerpc/kernel/trace/ftrace.c       |   12 ++++++++++++
+ arch/powerpc/kernel/trace/ftrace_64_pg.c |    5 +++++
+ arch/powerpc/kernel/vmlinux.lds.S        |    2 ++
+ 5 files changed, 22 insertions(+), 8 deletions(-)
+
+--- a/arch/powerpc/include/asm/ftrace.h
++++ b/arch/powerpc/include/asm/ftrace.h
+@@ -20,14 +20,6 @@
+ #ifndef __ASSEMBLY__
+ extern void _mcount(void);
+-static inline unsigned long ftrace_call_adjust(unsigned long addr)
+-{
+-      if (IS_ENABLED(CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY))
+-              addr += MCOUNT_INSN_SIZE;
+-
+-       return addr;
+-}
+-
+ unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip,
+                                   unsigned long sp);
+@@ -142,8 +134,10 @@ static inline u8 this_cpu_get_ftrace_ena
+ #ifdef CONFIG_FUNCTION_TRACER
+ extern unsigned int ftrace_tramp_text[], ftrace_tramp_init[];
+ void ftrace_free_init_tramp(void);
++unsigned long ftrace_call_adjust(unsigned long addr);
+ #else
+ static inline void ftrace_free_init_tramp(void) { }
++static inline unsigned long ftrace_call_adjust(unsigned long addr) { return addr; }
+ #endif
+ #endif /* !__ASSEMBLY__ */
+--- a/arch/powerpc/include/asm/sections.h
++++ b/arch/powerpc/include/asm/sections.h
+@@ -14,6 +14,7 @@ typedef struct func_desc func_desc_t;
+ extern char __head_end[];
+ extern char __srwx_boundary[];
++extern char __exittext_begin[], __exittext_end[];
+ /* Patch sites */
+ extern s32 patch__call_flush_branch_caches1;
+--- a/arch/powerpc/kernel/trace/ftrace.c
++++ b/arch/powerpc/kernel/trace/ftrace.c
+@@ -27,10 +27,22 @@
+ #include <asm/ftrace.h>
+ #include <asm/syscall.h>
+ #include <asm/inst.h>
++#include <asm/sections.h>
+ #define       NUM_FTRACE_TRAMPS       2
+ static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS];
++unsigned long ftrace_call_adjust(unsigned long addr)
++{
++      if (addr >= (unsigned long)__exittext_begin && addr < (unsigned long)__exittext_end)
++              return 0;
++
++      if (IS_ENABLED(CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY))
++              addr += MCOUNT_INSN_SIZE;
++
++      return addr;
++}
++
+ static ppc_inst_t ftrace_create_branch_inst(unsigned long ip, unsigned long addr, int link)
+ {
+       ppc_inst_t op;
+--- a/arch/powerpc/kernel/trace/ftrace_64_pg.c
++++ b/arch/powerpc/kernel/trace/ftrace_64_pg.c
+@@ -37,6 +37,11 @@
+ #define       NUM_FTRACE_TRAMPS       8
+ static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS];
++unsigned long ftrace_call_adjust(unsigned long addr)
++{
++      return addr;
++}
++
+ static ppc_inst_t
+ ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
+ {
+--- a/arch/powerpc/kernel/vmlinux.lds.S
++++ b/arch/powerpc/kernel/vmlinux.lds.S
+@@ -281,7 +281,9 @@ SECTIONS
+        * to deal with references from __bug_table
+        */
+       .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) {
++              __exittext_begin = .;
+               EXIT_TEXT
++              __exittext_end = .;
+       }
+       . = ALIGN(PAGE_SIZE);
index ec14f47b829aa58df4b7f2098b9fcbf29d1bf79c..257aea72128d600edab0c1e9db91a4b27c4c618b 100644 (file)
@@ -145,3 +145,7 @@ drm-vmwgfx-fix-crtc-s-atomic-check-conditional.patch
 nouveau-fix-instmem-race-condition-around-ptr-stores.patch
 bootconfig-use-memblock_free_late-to-free-xbc-memory-to-buddy.patch
 nilfs2-fix-oob-in-nilfs_set_de_type.patch
+net-dsa-mt7530-fix-improper-frames-on-all-25mhz-and-40mhz-xtal-mt7530.patch
+net-dsa-mt7530-fix-enabling-eee-on-mt7531-switch-on-all-boards.patch
+virtio_net-do-not-send-rss-key-if-it-is-not-supported.patch
+powerpc-ftrace-ignore-ftrace-locations-in-exit-text-sections.patch
diff --git a/queue-6.6/virtio_net-do-not-send-rss-key-if-it-is-not-supported.patch b/queue-6.6/virtio_net-do-not-send-rss-key-if-it-is-not-supported.patch
new file mode 100644 (file)
index 0000000..a1f0477
--- /dev/null
@@ -0,0 +1,130 @@
+From 059a49aa2e25c58f90b50151f109dd3c4cdb3a47 Mon Sep 17 00:00:00 2001
+From: Breno Leitao <leitao@debian.org>
+Date: Wed, 3 Apr 2024 08:43:12 -0700
+Subject: virtio_net: Do not send RSS key if it is not supported
+
+From: Breno Leitao <leitao@debian.org>
+
+commit 059a49aa2e25c58f90b50151f109dd3c4cdb3a47 upstream.
+
+There is a bug when setting the RSS options in virtio_net that can break
+the whole machine, getting the kernel into an infinite loop.
+
+Running the following command in any QEMU virtual machine with virtionet
+will reproduce this problem:
+
+    # ethtool -X eth0  hfunc toeplitz
+
+This is how the problem happens:
+
+1) ethtool_set_rxfh() calls virtnet_set_rxfh()
+
+2) virtnet_set_rxfh() calls virtnet_commit_rss_command()
+
+3) virtnet_commit_rss_command() populates 4 entries for the rss
+scatter-gather
+
+4) Since the command above does not have a key, then the last
+scatter-gatter entry will be zeroed, since rss_key_size == 0.
+sg_buf_size = vi->rss_key_size;
+
+5) This buffer is passed to qemu, but qemu is not happy with a buffer
+with zero length, and do the following in virtqueue_map_desc() (QEMU
+function):
+
+  if (!sz) {
+      virtio_error(vdev, "virtio: zero sized buffers are not allowed");
+
+6) virtio_error() (also QEMU function) set the device as broken
+
+    vdev->broken = true;
+
+7) Qemu bails out, and do not repond this crazy kernel.
+
+8) The kernel is waiting for the response to come back (function
+virtnet_send_command())
+
+9) The kernel is waiting doing the following :
+
+      while (!virtqueue_get_buf(vi->cvq, &tmp) &&
+            !virtqueue_is_broken(vi->cvq))
+             cpu_relax();
+
+10) None of the following functions above is true, thus, the kernel
+loops here forever. Keeping in mind that virtqueue_is_broken() does
+not look at the qemu `vdev->broken`, so, it never realizes that the
+vitio is broken at QEMU side.
+
+Fix it by not sending RSS commands if the feature is not available in
+the device.
+
+Fixes: c7114b1249fa ("drivers/net/virtio_net: Added basic RSS support.")
+Cc: stable@vger.kernel.org
+Cc: qemu-devel@nongnu.org
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Reviewed-by: Heng Qi <hengqi@linux.alibaba.com>
+Reviewed-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Vlad Poenaru <vlad.wing@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/virtio_net.c |   25 +++++++++++++++++++++----
+ 1 file changed, 21 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -3570,19 +3570,34 @@ static int virtnet_get_rxfh(struct net_d
+ static int virtnet_set_rxfh(struct net_device *dev, const u32 *indir, const u8 *key, const u8 hfunc)
+ {
+       struct virtnet_info *vi = netdev_priv(dev);
++      bool update = false;
+       int i;
+       if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
+               return -EOPNOTSUPP;
+       if (indir) {
++              if (!vi->has_rss)
++                      return -EOPNOTSUPP;
++
+               for (i = 0; i < vi->rss_indir_table_size; ++i)
+                       vi->ctrl->rss.indirection_table[i] = indir[i];
++              update = true;
+       }
+-      if (key)
++      if (key) {
++              /* If either _F_HASH_REPORT or _F_RSS are negotiated, the
++               * device provides hash calculation capabilities, that is,
++               * hash_key is configured.
++               */
++              if (!vi->has_rss && !vi->has_rss_hash_report)
++                      return -EOPNOTSUPP;
++
+               memcpy(vi->ctrl->rss.key, key, vi->rss_key_size);
++              update = true;
++      }
+-      virtnet_commit_rss_command(vi);
++      if (update)
++              virtnet_commit_rss_command(vi);
+       return 0;
+ }
+@@ -4491,13 +4506,15 @@ static int virtnet_probe(struct virtio_d
+       if (virtio_has_feature(vdev, VIRTIO_NET_F_HASH_REPORT))
+               vi->has_rss_hash_report = true;
+-      if (virtio_has_feature(vdev, VIRTIO_NET_F_RSS))
++      if (virtio_has_feature(vdev, VIRTIO_NET_F_RSS)) {
+               vi->has_rss = true;
+-      if (vi->has_rss || vi->has_rss_hash_report) {
+               vi->rss_indir_table_size =
+                       virtio_cread16(vdev, offsetof(struct virtio_net_config,
+                               rss_max_indirection_table_length));
++      }
++
++      if (vi->has_rss || vi->has_rss_hash_report) {
+               vi->rss_key_size =
+                       virtio_cread8(vdev, offsetof(struct virtio_net_config, rss_max_key_size));