diff options
author | Michal Kubecek <mkubecek@suse.cz> | 2020-03-12 21:08:43 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-03-12 23:32:33 +0100 |
commit | e19c591eafad4d723a2eed385e253eca0506cc25 (patch) | |
tree | 1450733e460f65eb9eb6a0b88a1dd96bc061fcc2 /net/ethtool/common.c | |
parent | ethtool: provide channel counts with CHANNELS_GET request (diff) | |
download | linux-e19c591eafad4d723a2eed385e253eca0506cc25.tar.xz linux-e19c591eafad4d723a2eed385e253eca0506cc25.zip |
ethtool: set device channel counts with CHANNELS_SET request
Implement CHANNELS_SET netlink request to set channel counts of a network
device. These are traditionally set with ETHTOOL_SCHANNELS ioctl request.
Like the ioctl implementation, the generic ethtool code checks if supplied
values do not exceed driver defined limits; if they do, first offending
attribute is reported using extack. Checks preventing removing channels
used for RX indirection table or zerocopy AF_XDP socket are also
implemented.
Move ethtool_get_max_rxfh_channel() helper into common.c so that it can be
used by both ioctl and netlink code.
v2:
- fix netdev reference leak in error path (found by Jakub Kicinsky)
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
Reviewed-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ethtool/common.c')
-rw-r--r-- | net/ethtool/common.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/net/ethtool/common.c b/net/ethtool/common.c index 7b6969af5ae7..0b22741b2f8f 100644 --- a/net/ethtool/common.c +++ b/net/ethtool/common.c @@ -258,3 +258,34 @@ int __ethtool_get_link(struct net_device *dev) return netif_running(dev) && dev->ethtool_ops->get_link(dev); } + +int ethtool_get_max_rxfh_channel(struct net_device *dev, u32 *max) +{ + u32 dev_size, current_max = 0; + u32 *indir; + int ret; + + if (!dev->ethtool_ops->get_rxfh_indir_size || + !dev->ethtool_ops->get_rxfh) + return -EOPNOTSUPP; + dev_size = dev->ethtool_ops->get_rxfh_indir_size(dev); + if (dev_size == 0) + return -EOPNOTSUPP; + + indir = kcalloc(dev_size, sizeof(indir[0]), GFP_USER); + if (!indir) + return -ENOMEM; + + ret = dev->ethtool_ops->get_rxfh(dev, indir, NULL, NULL); + if (ret) + goto out; + + while (dev_size--) + current_max = max(current_max, indir[dev_size]); + + *max = current_max; + +out: + kfree(indir); + return ret; +} |