From: Jakub Kicinski Date: Wed, 18 Jun 2025 20:38:23 +0000 (-0700) Subject: net: ethtool: don't mux RXFH via rxnfc callbacks X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=72792461c8e8d19b3fe8d62a1b3ea6a2e3135182;p=thirdparty%2Fkernel%2Fstable.git net: ethtool: don't mux RXFH via rxnfc callbacks All drivers have been converted. Stop using the rxnfc fallbacks for Rx Flow Hashing configuration. Joe pointed out in earlier review that in ethtool_set_rxfh() we need both .get_rxnfc and .get_rxfh_fields, because we need both the ring count and flow hashing (because we call ethtool_check_flow_types()). IOW the existing check added for transitioning drivers was buggy. Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250618203823.1336156-11-kuba@kernel.org Signed-off-by: Jakub Kicinski --- diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index a14cf901c32d..82cde640aa87 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -1037,33 +1037,21 @@ static int ethtool_check_xfrm_rxfh(u32 input_xfrm, u64 rxfh) static int ethtool_check_flow_types(struct net_device *dev, u32 input_xfrm) { const struct ethtool_ops *ops = dev->ethtool_ops; - struct ethtool_rxnfc info = { - .cmd = ETHTOOL_GRXFH, - }; int err; u32 i; for (i = 0; i < __FLOW_TYPE_COUNT; i++) { + struct ethtool_rxfh_fields fields = { + .flow_type = i, + }; + if (!flow_type_hashable(i)) continue; - info.flow_type = i; - - if (ops->get_rxfh_fields) { - struct ethtool_rxfh_fields fields = { - .flow_type = info.flow_type, - }; - - if (ops->get_rxfh_fields(dev, &fields)) - continue; - - info.data = fields.data; - } else { - if (ops->get_rxnfc(dev, &info, NULL)) - continue; - } + if (ops->get_rxfh_fields(dev, &fields)) + continue; - err = ethtool_check_xfrm_rxfh(input_xfrm, info.data); + err = ethtool_check_xfrm_rxfh(input_xfrm, fields.data); if (err) return err; } @@ -1080,7 +1068,7 @@ ethtool_set_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) size_t info_size = sizeof(info); int rc; - if (!ops->set_rxnfc && !ops->set_rxfh_fields) + if (!ops->set_rxfh_fields) return -EOPNOTSUPP; rc = ethtool_rxnfc_copy_struct(cmd, &info, &info_size, useraddr); @@ -1103,9 +1091,6 @@ ethtool_set_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) return rc; } - if (!ops->set_rxfh_fields) - return ops->set_rxnfc(dev, &info); - fields.data = info.data; fields.flow_type = info.flow_type & ~FLOW_RSS; if (info.flow_type & FLOW_RSS) @@ -1120,9 +1105,10 @@ ethtool_get_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) struct ethtool_rxnfc info; size_t info_size = sizeof(info); const struct ethtool_ops *ops = dev->ethtool_ops; + struct ethtool_rxfh_fields fields = {}; int ret; - if (!ops->get_rxnfc && !ops->get_rxfh_fields) + if (!ops->get_rxfh_fields) return -EOPNOTSUPP; ret = ethtool_rxnfc_copy_struct(cmd, &info, &info_size, useraddr); @@ -1133,24 +1119,15 @@ ethtool_get_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) !ops->rxfh_per_ctx_fields) return -EINVAL; - if (ops->get_rxfh_fields) { - struct ethtool_rxfh_fields fields = { - .flow_type = info.flow_type & ~FLOW_RSS, - }; - - if (info.flow_type & FLOW_RSS) - fields.rss_context = info.rss_context; + fields.flow_type = info.flow_type & ~FLOW_RSS; + if (info.flow_type & FLOW_RSS) + fields.rss_context = info.rss_context; - ret = ops->get_rxfh_fields(dev, &fields); - if (ret < 0) - return ret; + ret = ops->get_rxfh_fields(dev, &fields); + if (ret < 0) + return ret; - info.data = fields.data; - } else { - ret = ops->get_rxnfc(dev, &info, NULL); - if (ret < 0) - return ret; - } + info.data = fields.data; return ethtool_rxnfc_copy_to_user(useraddr, &info, info_size, NULL); } @@ -1528,7 +1505,7 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev, u8 *rss_config; int ret; - if ((!ops->get_rxnfc && !ops->get_rxfh_fields) || !ops->set_rxfh) + if (!ops->get_rxnfc || !ops->get_rxfh_fields || !ops->set_rxfh) return -EOPNOTSUPP; if (ops->get_rxfh_indir_size)