diff options
Diffstat (limited to 'drivers/net/ethernet/sfc/ethtool.c')
-rw-r--r-- | drivers/net/ethernet/sfc/ethtool.c | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 98b363bb4a75..93f1fb99432d 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -595,6 +595,20 @@ static int efx_ethtool_nway_reset(struct net_device *net_dev) * automatically changed too, but otherwise we fail if the two values * are requested to be different. * + * The hardware does not support a limit on the number of completions + * before an IRQ, so we do not use the max_frames fields. We should + * report and require that max_frames == (usecs != 0), but this would + * invalidate existing user documentation. + * + * The hardware does not have distinct settings for interrupt + * moderation while the previous IRQ is being handled, so we should + * not use the 'irq' fields. However, an earlier developer + * misunderstood the meaning of the 'irq' fields and the driver did + * not support the standard fields. To avoid invalidating existing + * user documentation, we report and accept changes through either the + * standard or 'irq' fields. If both are changed at the same time, we + * prefer the standard field. + * * We implement adaptive IRQ moderation, but use a different algorithm * from that assumed in the definition of struct ethtool_coalesce. * Therefore we do not use any of the adaptive moderation parameters @@ -610,7 +624,9 @@ static int efx_ethtool_get_coalesce(struct net_device *net_dev, efx_get_irq_moderation(efx, &tx_usecs, &rx_usecs, &rx_adaptive); + coalesce->tx_coalesce_usecs = tx_usecs; coalesce->tx_coalesce_usecs_irq = tx_usecs; + coalesce->rx_coalesce_usecs = rx_usecs; coalesce->rx_coalesce_usecs_irq = rx_usecs; coalesce->use_adaptive_rx_coalesce = rx_adaptive; @@ -629,22 +645,24 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev, if (coalesce->use_adaptive_tx_coalesce) return -EINVAL; - if (coalesce->rx_coalesce_usecs || coalesce->tx_coalesce_usecs) { - netif_err(efx, drv, efx->net_dev, "invalid coalescing setting. " - "Only rx/tx_coalesce_usecs_irq are supported\n"); - return -EINVAL; - } - efx_get_irq_moderation(efx, &tx_usecs, &rx_usecs, &adaptive); - rx_usecs = coalesce->rx_coalesce_usecs_irq; + if (coalesce->rx_coalesce_usecs != rx_usecs) + rx_usecs = coalesce->rx_coalesce_usecs; + else + rx_usecs = coalesce->rx_coalesce_usecs_irq; + adaptive = coalesce->use_adaptive_rx_coalesce; /* If channels are shared, TX IRQ moderation can be quietly * overridden unless it is changed from its old value. */ - rx_may_override_tx = coalesce->tx_coalesce_usecs_irq == tx_usecs; - tx_usecs = coalesce->tx_coalesce_usecs_irq; + rx_may_override_tx = (coalesce->tx_coalesce_usecs == tx_usecs && + coalesce->tx_coalesce_usecs_irq == tx_usecs); + if (coalesce->tx_coalesce_usecs != tx_usecs) + tx_usecs = coalesce->tx_coalesce_usecs; + else + tx_usecs = coalesce->tx_coalesce_usecs_irq; rc = efx_init_irq_moderation(efx, tx_usecs, rx_usecs, adaptive, rx_may_override_tx); |