|
@@ -634,6 +634,85 @@ static int ixgbevf_nway_reset(struct net_device *netdev)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int ixgbevf_get_coalesce(struct net_device *netdev,
|
|
|
+ struct ethtool_coalesce *ec)
|
|
|
+{
|
|
|
+ struct ixgbevf_adapter *adapter = netdev_priv(netdev);
|
|
|
+
|
|
|
+ /* only valid if in constant ITR mode */
|
|
|
+ if (adapter->rx_itr_setting <= 1)
|
|
|
+ ec->rx_coalesce_usecs = adapter->rx_itr_setting;
|
|
|
+ else
|
|
|
+ ec->rx_coalesce_usecs = adapter->rx_itr_setting >> 2;
|
|
|
+
|
|
|
+ /* if in mixed tx/rx queues per vector mode, report only rx settings */
|
|
|
+ if (adapter->q_vector[0]->tx.count && adapter->q_vector[0]->rx.count)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /* only valid if in constant ITR mode */
|
|
|
+ if (adapter->tx_itr_setting <= 1)
|
|
|
+ ec->tx_coalesce_usecs = adapter->tx_itr_setting;
|
|
|
+ else
|
|
|
+ ec->tx_coalesce_usecs = adapter->tx_itr_setting >> 2;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int ixgbevf_set_coalesce(struct net_device *netdev,
|
|
|
+ struct ethtool_coalesce *ec)
|
|
|
+{
|
|
|
+ struct ixgbevf_adapter *adapter = netdev_priv(netdev);
|
|
|
+ struct ixgbevf_q_vector *q_vector;
|
|
|
+ int num_vectors, i;
|
|
|
+ u16 tx_itr_param, rx_itr_param;
|
|
|
+
|
|
|
+ /* don't accept tx specific changes if we've got mixed RxTx vectors */
|
|
|
+ if (adapter->q_vector[0]->tx.count && adapter->q_vector[0]->rx.count
|
|
|
+ && ec->tx_coalesce_usecs)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+
|
|
|
+ if ((ec->rx_coalesce_usecs > (IXGBE_MAX_EITR >> 2)) ||
|
|
|
+ (ec->tx_coalesce_usecs > (IXGBE_MAX_EITR >> 2)))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (ec->rx_coalesce_usecs > 1)
|
|
|
+ adapter->rx_itr_setting = ec->rx_coalesce_usecs << 2;
|
|
|
+ else
|
|
|
+ adapter->rx_itr_setting = ec->rx_coalesce_usecs;
|
|
|
+
|
|
|
+ if (adapter->rx_itr_setting == 1)
|
|
|
+ rx_itr_param = IXGBE_20K_ITR;
|
|
|
+ else
|
|
|
+ rx_itr_param = adapter->rx_itr_setting;
|
|
|
+
|
|
|
+
|
|
|
+ if (ec->tx_coalesce_usecs > 1)
|
|
|
+ adapter->tx_itr_setting = ec->tx_coalesce_usecs << 2;
|
|
|
+ else
|
|
|
+ adapter->tx_itr_setting = ec->tx_coalesce_usecs;
|
|
|
+
|
|
|
+ if (adapter->tx_itr_setting == 1)
|
|
|
+ tx_itr_param = IXGBE_10K_ITR;
|
|
|
+ else
|
|
|
+ tx_itr_param = adapter->tx_itr_setting;
|
|
|
+
|
|
|
+ num_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
|
|
|
+
|
|
|
+ for (i = 0; i < num_vectors; i++) {
|
|
|
+ q_vector = adapter->q_vector[i];
|
|
|
+ if (q_vector->tx.count && !q_vector->rx.count)
|
|
|
+ /* tx only */
|
|
|
+ q_vector->itr = tx_itr_param;
|
|
|
+ else
|
|
|
+ /* rx only or mixed */
|
|
|
+ q_vector->itr = rx_itr_param;
|
|
|
+ ixgbevf_write_eitr(q_vector);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static const struct ethtool_ops ixgbevf_ethtool_ops = {
|
|
|
.get_settings = ixgbevf_get_settings,
|
|
|
.get_drvinfo = ixgbevf_get_drvinfo,
|
|
@@ -649,6 +728,8 @@ static const struct ethtool_ops ixgbevf_ethtool_ops = {
|
|
|
.get_sset_count = ixgbevf_get_sset_count,
|
|
|
.get_strings = ixgbevf_get_strings,
|
|
|
.get_ethtool_stats = ixgbevf_get_ethtool_stats,
|
|
|
+ .get_coalesce = ixgbevf_get_coalesce,
|
|
|
+ .set_coalesce = ixgbevf_set_coalesce,
|
|
|
};
|
|
|
|
|
|
void ixgbevf_set_ethtool_ops(struct net_device *netdev)
|