diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-04-23 09:35:26 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-04-23 09:35:26 -0700 |
commit | 30574c54eb734d785455c43be188b79b6c6bd940 (patch) | |
tree | fb845f3dea29a94d4a34e53b7da3e6726cfb1af7 | |
parent | 971ea24b9a143d19114aba224fcd550e7981f403 (diff) | |
download | stable-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
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)); + |