aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-04-23 09:35:26 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-04-23 09:35:26 -0700
commit30574c54eb734d785455c43be188b79b6c6bd940 (patch)
treefb845f3dea29a94d4a34e53b7da3e6726cfb1af7
parent971ea24b9a143d19114aba224fcd550e7981f403 (diff)
downloadstable-queue-30574c54eb734d785455c43be188b79b6c6bd940.tar.gz
6.6-stable patches
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
-rw-r--r--queue-6.6/net-dsa-mt7530-fix-enabling-eee-on-mt7531-switch-on-all-boards.patch101
-rw-r--r--queue-6.6/net-dsa-mt7530-fix-improper-frames-on-all-25mhz-and-40mhz-xtal-mt7530.patch79
-rw-r--r--queue-6.6/powerpc-ftrace-ignore-ftrace-locations-in-exit-text-sections.patch157
-rw-r--r--queue-6.6/series4
-rw-r--r--queue-6.6/virtio_net-do-not-send-rss-key-if-it-is-not-supported.patch130
5 files changed, 471 insertions, 0 deletions
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
index 0000000000..c7644570a7
--- /dev/null
+++ b/queue-6.6/net-dsa-mt7530-fix-enabling-eee-on-mt7531-switch-on-all-boards.patch
@@ -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
index 0000000000..5327d2732b
--- /dev/null
+++ b/queue-6.6/net-dsa-mt7530-fix-improper-frames-on-all-25mhz-and-40mhz-xtal-mt7530.patch
@@ -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
index 0000000000..0d274ae721
--- /dev/null
+++ b/queue-6.6/powerpc-ftrace-ignore-ftrace-locations-in-exit-text-sections.patch
@@ -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);
diff --git a/queue-6.6/series b/queue-6.6/series
index ec14f47b82..257aea7212 100644
--- a/queue-6.6/series
+++ b/queue-6.6/series
@@ -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
index 0000000000..a1f0477d6c
--- /dev/null
+++ b/queue-6.6/virtio_net-do-not-send-rss-key-if-it-is-not-supported.patch
@@ -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));
+