ethtool: add infrastructure for centralized checking of coalescing parameters
Linux supports 22 different interrupt coalescing parameters. No driver implements them all. Some drivers just ignore the ones they don't support, while others have to carry a long list of checks to reject unsupported settings. To simplify the drivers add the ability to specify inside ethtool_ops which parameters are supported and let the core reject attempts to set any other one. This commit makes the mechanism an opt-in, only drivers which set ethtool_opts->coalesce_types to a non-zero value will have the checks enforced. The same mask is used for global and per queue settings. v3: - move the (temporary) check if driver defines types earlier (Michal) - rename used_types -> nonzero_params, and coalesce_types -> supported_coalesce_params (Alex) - use EOPNOTSUPP instead of EINVAL (Andrew, Michal) Leaving the long series of ifs for now, it seems nice to be able to grep for the field and flag names. This will probably have to be revisited once netlink support lands. Signed-off-by: Jakub Kicinski <kuba@kernel.org> Reviewed-by: Jacob Keller <jacob.e.keller@intel.com> Reviewed-by: Michal Kubecek <mkubecek@suse.cz> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Reviewed-by: Alexander Duyck <alexander.h.duyck@linux.intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
56dc0a0eac
commit
95cddcb5cc
@@ -1544,6 +1544,64 @@ static noinline_for_stack int ethtool_get_coalesce(struct net_device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
ethtool_set_coalesce_supported(struct net_device *dev,
|
||||
struct ethtool_coalesce *coalesce)
|
||||
{
|
||||
u32 supported_params = dev->ethtool_ops->supported_coalesce_params;
|
||||
u32 nonzero_params = 0;
|
||||
|
||||
if (!supported_params)
|
||||
return true;
|
||||
|
||||
if (coalesce->rx_coalesce_usecs)
|
||||
nonzero_params |= ETHTOOL_COALESCE_RX_USECS;
|
||||
if (coalesce->rx_max_coalesced_frames)
|
||||
nonzero_params |= ETHTOOL_COALESCE_RX_MAX_FRAMES;
|
||||
if (coalesce->rx_coalesce_usecs_irq)
|
||||
nonzero_params |= ETHTOOL_COALESCE_RX_USECS_IRQ;
|
||||
if (coalesce->rx_max_coalesced_frames_irq)
|
||||
nonzero_params |= ETHTOOL_COALESCE_RX_MAX_FRAMES_IRQ;
|
||||
if (coalesce->tx_coalesce_usecs)
|
||||
nonzero_params |= ETHTOOL_COALESCE_TX_USECS;
|
||||
if (coalesce->tx_max_coalesced_frames)
|
||||
nonzero_params |= ETHTOOL_COALESCE_TX_MAX_FRAMES;
|
||||
if (coalesce->tx_coalesce_usecs_irq)
|
||||
nonzero_params |= ETHTOOL_COALESCE_TX_USECS_IRQ;
|
||||
if (coalesce->tx_max_coalesced_frames_irq)
|
||||
nonzero_params |= ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ;
|
||||
if (coalesce->stats_block_coalesce_usecs)
|
||||
nonzero_params |= ETHTOOL_COALESCE_STATS_BLOCK_USECS;
|
||||
if (coalesce->use_adaptive_rx_coalesce)
|
||||
nonzero_params |= ETHTOOL_COALESCE_USE_ADAPTIVE_RX;
|
||||
if (coalesce->use_adaptive_tx_coalesce)
|
||||
nonzero_params |= ETHTOOL_COALESCE_USE_ADAPTIVE_TX;
|
||||
if (coalesce->pkt_rate_low)
|
||||
nonzero_params |= ETHTOOL_COALESCE_PKT_RATE_LOW;
|
||||
if (coalesce->rx_coalesce_usecs_low)
|
||||
nonzero_params |= ETHTOOL_COALESCE_RX_USECS_LOW;
|
||||
if (coalesce->rx_max_coalesced_frames_low)
|
||||
nonzero_params |= ETHTOOL_COALESCE_RX_MAX_FRAMES_LOW;
|
||||
if (coalesce->tx_coalesce_usecs_low)
|
||||
nonzero_params |= ETHTOOL_COALESCE_TX_USECS_LOW;
|
||||
if (coalesce->tx_max_coalesced_frames_low)
|
||||
nonzero_params |= ETHTOOL_COALESCE_TX_MAX_FRAMES_LOW;
|
||||
if (coalesce->pkt_rate_high)
|
||||
nonzero_params |= ETHTOOL_COALESCE_PKT_RATE_HIGH;
|
||||
if (coalesce->rx_coalesce_usecs_high)
|
||||
nonzero_params |= ETHTOOL_COALESCE_RX_USECS_HIGH;
|
||||
if (coalesce->rx_max_coalesced_frames_high)
|
||||
nonzero_params |= ETHTOOL_COALESCE_RX_MAX_FRAMES_HIGH;
|
||||
if (coalesce->tx_coalesce_usecs_high)
|
||||
nonzero_params |= ETHTOOL_COALESCE_TX_USECS_HIGH;
|
||||
if (coalesce->tx_max_coalesced_frames_high)
|
||||
nonzero_params |= ETHTOOL_COALESCE_TX_MAX_FRAMES_HIGH;
|
||||
if (coalesce->rate_sample_interval)
|
||||
nonzero_params |= ETHTOOL_COALESCE_RATE_SAMPLE_INTERVAL;
|
||||
|
||||
return (supported_params & nonzero_params) == nonzero_params;
|
||||
}
|
||||
|
||||
static noinline_for_stack int ethtool_set_coalesce(struct net_device *dev,
|
||||
void __user *useraddr)
|
||||
{
|
||||
@@ -1555,6 +1613,9 @@ static noinline_for_stack int ethtool_set_coalesce(struct net_device *dev,
|
||||
if (copy_from_user(&coalesce, useraddr, sizeof(coalesce)))
|
||||
return -EFAULT;
|
||||
|
||||
if (!ethtool_set_coalesce_supported(dev, &coalesce))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return dev->ethtool_ops->set_coalesce(dev, &coalesce);
|
||||
}
|
||||
|
||||
@@ -2336,6 +2397,11 @@ ethtool_set_per_queue_coalesce(struct net_device *dev,
|
||||
goto roll_back;
|
||||
}
|
||||
|
||||
if (!ethtool_set_coalesce_supported(dev, &coalesce)) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto roll_back;
|
||||
}
|
||||
|
||||
ret = dev->ethtool_ops->set_per_queue_coalesce(dev, bit, &coalesce);
|
||||
if (ret != 0)
|
||||
goto roll_back;
|
||||
|
Reference in New Issue
Block a user