summaryrefslogtreecommitdiffstats
path: root/drivers/net/ixgbe/ixgbe_ethtool.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_ethtool.c')
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c90
1 files changed, 53 insertions, 37 deletions
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index c19594a4e8f..561d47895d8 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -1975,6 +1975,41 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
return 0;
}
+/*
+ * this function must be called before setting the new value of
+ * rx_itr_setting
+ */
+static bool ixgbe_update_rsc(struct ixgbe_adapter *adapter,
+ struct ethtool_coalesce *ec)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE))
+ return false;
+
+ /* if interrupt rate is too high then disable RSC */
+ if (ec->rx_coalesce_usecs != 1 &&
+ ec->rx_coalesce_usecs <= 1000000/IXGBE_MAX_RSC_INT_RATE) {
+ if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
+ e_info(probe, "rx-usecs set too low, "
+ "disabling RSC\n");
+ adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
+ return true;
+ }
+ } else {
+ /* check the feature flag value and enable RSC if necessary */
+ if ((netdev->features & NETIF_F_LRO) &&
+ !(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)) {
+ e_info(probe, "rx-usecs set to %d, "
+ "re-enabling RSC\n",
+ ec->rx_coalesce_usecs);
+ adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
+ return true;
+ }
+ }
+ return false;
+}
+
static int ixgbe_set_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec)
{
@@ -1992,17 +2027,14 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
adapter->tx_ring[0]->work_limit = ec->tx_max_coalesced_frames_irq;
if (ec->rx_coalesce_usecs > 1) {
- u32 max_int;
- if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
- max_int = IXGBE_MAX_RSC_INT_RATE;
- else
- max_int = IXGBE_MAX_INT_RATE;
-
/* check the limits */
- if ((1000000/ec->rx_coalesce_usecs > max_int) ||
+ if ((1000000/ec->rx_coalesce_usecs > IXGBE_MAX_INT_RATE) ||
(1000000/ec->rx_coalesce_usecs < IXGBE_MIN_INT_RATE))
return -EINVAL;
+ /* check the old value and enable RSC if necessary */
+ need_reset = ixgbe_update_rsc(adapter, ec);
+
/* store the value in ints/second */
adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
@@ -2011,32 +2043,21 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
/* clear the lower bit as its used for dynamic state */
adapter->rx_itr_setting &= ~1;
} else if (ec->rx_coalesce_usecs == 1) {
+ /* check the old value and enable RSC if necessary */
+ need_reset = ixgbe_update_rsc(adapter, ec);
+
/* 1 means dynamic mode */
adapter->rx_eitr_param = 20000;
adapter->rx_itr_setting = 1;
} else {
+ /* check the old value and enable RSC if necessary */
+ need_reset = ixgbe_update_rsc(adapter, ec);
/*
* any other value means disable eitr, which is best
* served by setting the interrupt rate very high
*/
adapter->rx_eitr_param = IXGBE_MAX_INT_RATE;
adapter->rx_itr_setting = 0;
-
- /*
- * if hardware RSC is enabled, disable it when
- * setting low latency mode, to avoid errata, assuming
- * that when the user set low latency mode they want
- * it at the cost of anything else
- */
- if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
- adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
- if (netdev->features & NETIF_F_LRO) {
- netdev->features &= ~NETIF_F_LRO;
- e_info(probe, "rx-usecs set to 0, "
- "disabling RSC\n");
- }
- need_reset = true;
- }
}
if (ec->tx_coalesce_usecs > 1) {
@@ -2123,15 +2144,15 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
return rc;
/* if state changes we need to update adapter->flags and reset */
- if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) {
- /*
- * cast both to bool and verify if they are set the same
- * but only enable RSC if itr is non-zero, as
- * itr=0 and RSC are mutually exclusive
- */
- if (((!!(data & ETH_FLAG_LRO)) !=
- (!!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) &&
- adapter->rx_itr_setting) {
+ if ((adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) &&
+ (!!(data & ETH_FLAG_LRO) !=
+ !!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) {
+ if ((data & ETH_FLAG_LRO) &&
+ (!adapter->rx_itr_setting ||
+ (adapter->rx_itr_setting > IXGBE_MAX_RSC_INT_RATE))) {
+ e_info(probe, "rx-usecs set too low, "
+ "not enabling RSC.\n");
+ } else {
adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED;
switch (adapter->hw.mac.type) {
case ixgbe_mac_82599EB:
@@ -2140,11 +2161,6 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
default:
break;
}
- } else if (!adapter->rx_itr_setting) {
- netdev->features &= ~NETIF_F_LRO;
- if (data & ETH_FLAG_LRO)
- e_info(probe, "rx-usecs set to 0, "
- "LRO/RSC cannot be enabled.\n");
}
}