Add a new optional get_rx_ring_count callback in ethtool_ops to allow drivers to provide the number of RX rings directly without going through the full get_rxnfc flow classification interface. Modify ethtool_get_rxrings() to use .get_rx_ring_count if available, falling back to get_rxnfc() otherwise. Signed-off-by: Breno Leitao --- include/linux/ethtool.h | 2 ++ net/ethtool/ioctl.c | 23 +++++++++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index de5bd76a400ca..2d91fd3102c14 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -968,6 +968,7 @@ struct kernel_ethtool_ts_info { * @reset: Reset (part of) the device, as specified by a bitmask of * flags from &enum ethtool_reset_flags. Returns a negative * error code or zero. + * @get_rx_ring_count: Return the number of RX rings * @get_rxfh_key_size: Get the size of the RX flow hash key. * Returns zero if not supported for this specific device. * @get_rxfh_indir_size: Get the size of the RX flow hash indirection table. @@ -1162,6 +1163,7 @@ struct ethtool_ops { int (*set_rxnfc)(struct net_device *, struct ethtool_rxnfc *); int (*flash_device)(struct net_device *, struct ethtool_flash *); int (*reset)(struct net_device *, u32 *); + u32 (*get_rx_ring_count)(struct net_device *dev); u32 (*get_rxfh_key_size)(struct net_device *); u32 (*get_rxfh_indir_size)(struct net_device *); int (*get_rxfh)(struct net_device *, struct ethtool_rxfh_param *); diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index a0f3de76cea03..4981db3e285d8 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -1208,6 +1208,23 @@ static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, return 0; } +static int ethtool_get_rx_ring_count(struct net_device *dev) +{ + const struct ethtool_ops *ops = dev->ethtool_ops; + struct ethtool_rxnfc rx_rings = {}; + int ret; + + if (ops->get_rx_ring_count) + return ops->get_rx_ring_count(dev); + + rx_rings.cmd = ETHTOOL_GRXRINGS; + ret = ops->get_rxnfc(dev, &rx_rings, NULL); + if (ret < 0) + return ret; + + return rx_rings.data; +} + static noinline_for_stack int ethtool_get_rxrings(struct net_device *dev, u32 cmd, void __user *useraddr) @@ -1217,7 +1234,7 @@ static noinline_for_stack int ethtool_get_rxrings(struct net_device *dev, size_t info_size; int ret; - if (!ops->get_rxnfc) + if (!ops->get_rxnfc && !ops->get_rx_ring_count) return -EOPNOTSUPP; info_size = sizeof(info); @@ -1225,9 +1242,7 @@ static noinline_for_stack int ethtool_get_rxrings(struct net_device *dev, if (ret) return ret; - ret = ops->get_rxnfc(dev, &info, NULL); - if (ret < 0) - return ret; + info.data = ethtool_get_rx_ring_count(dev); return ethtool_rxnfc_copy_to_user(useraddr, &info, info_size, NULL); } -- 2.47.3