diff options
author | Jakub Kicinski <kuba@kernel.org> | 2025-06-11 07:59:44 -0700 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2025-06-12 17:16:20 -0700 |
commit | 9bb00786fc61e865e121aa20dd12aa4d1311a990 (patch) | |
tree | 8b10a3834b071f8549bc6165aacf7776f16f4c7b /net/ethtool/ioctl.c | |
parent | fac4b41741b5cd0826cf0fa5b14e177f70a6b509 (diff) |
net: ethtool: add dedicated callbacks for getting and setting rxfh fields
We mux multiple calls to the drivers via the .get_nfc and .set_nfc
callbacks. This is slightly inconvenient to the drivers as they
have to de-mux them back. It will also be awkward for netlink code
to construct struct ethtool_rxnfc when it wants to get info about
RX Flow Hash, from the RSS module.
Add dedicated driver callbacks. Create struct ethtool_rxfh_fields
which contains only data relevant to RXFH. Maintain the names of
the fields to avoid having to heavily modify the drivers.
For now support both callbacks, once all drivers are converted
ethtool_*et_rxfh_fields() will stop using the rxnfc callbacks.
Link: https://patch.msgid.link/20250611145949.2674086-5-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/ethtool/ioctl.c')
-rw-r--r-- | net/ethtool/ioctl.c | 55 |
1 files changed, 45 insertions, 10 deletions
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 1a1705e900b3..a14cf901c32d 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -1048,9 +1048,20 @@ static int ethtool_check_flow_types(struct net_device *dev, u32 input_xfrm) continue; info.flow_type = i; - err = ops->get_rxnfc(dev, &info, NULL); - if (err) - continue; + + 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; + } err = ethtool_check_xfrm_rxfh(input_xfrm, info.data); if (err) @@ -1064,11 +1075,12 @@ static noinline_for_stack int ethtool_set_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) { const struct ethtool_ops *ops = dev->ethtool_ops; + struct ethtool_rxfh_fields fields = {}; struct ethtool_rxnfc info; size_t info_size = sizeof(info); int rc; - if (!ops->set_rxnfc) + if (!ops->set_rxnfc && !ops->set_rxfh_fields) return -EOPNOTSUPP; rc = ethtool_rxnfc_copy_struct(cmd, &info, &info_size, useraddr); @@ -1091,7 +1103,15 @@ ethtool_set_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) return rc; } - return ops->set_rxnfc(dev, &info); + 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) + fields.rss_context = info.rss_context; + + return ops->set_rxfh_fields(dev, &fields, NULL); } static noinline_for_stack int @@ -1102,7 +1122,7 @@ ethtool_get_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) const struct ethtool_ops *ops = dev->ethtool_ops; int ret; - if (!ops->get_rxnfc) + if (!ops->get_rxnfc && !ops->get_rxfh_fields) return -EOPNOTSUPP; ret = ethtool_rxnfc_copy_struct(cmd, &info, &info_size, useraddr); @@ -1113,9 +1133,24 @@ ethtool_get_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) !ops->rxfh_per_ctx_fields) return -EINVAL; - ret = ops->get_rxnfc(dev, &info, NULL); - if (ret < 0) - return ret; + 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; + + 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; + } return ethtool_rxnfc_copy_to_user(useraddr, &info, info_size, NULL); } @@ -1493,7 +1528,7 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev, u8 *rss_config; int ret; - if (!ops->get_rxnfc || !ops->set_rxfh) + if ((!ops->get_rxnfc && !ops->get_rxfh_fields) || !ops->set_rxfh) return -EOPNOTSUPP; if (ops->get_rxfh_indir_size) |