diff options
| author | Jacob Keller <jacob.e.keller@intel.com> | 2013-10-22 06:19:18 +0000 | 
|---|---|---|
| committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2013-10-24 07:27:10 -0700 | 
| commit | 3849623e03662babfdb82a6192e2f23b3f157119 (patch) | |
| tree | bac43c9478712fcef727b0be41c99e46c7def000 /drivers/net/ethernet/intel/ixgbevf | |
| parent | 1bb9c6390e0f6df355576b48514b393a2579c3b9 (diff) | |
ixgbevf: implement ethtool get/set coalesce
This patch adds support for ethtool's get_coalesce and set_coalesce command for
the ixgbevf driver. This enables dynamically updating the minimum time between
interrupts.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/ixgbevf')
| -rw-r--r-- | drivers/net/ethernet/intel/ixgbevf/ethtool.c | 81 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/ixgbevf/ixgbevf.h | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 2 | 
3 files changed, 84 insertions, 1 deletions
| diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c index 84329b0d567a..21adb1bc1706 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c +++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c @@ -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) diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h index 64a2b912e73c..d7837dcc9897 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h @@ -293,6 +293,8 @@ void ixgbevf_free_tx_resources(struct ixgbevf_adapter *, struct ixgbevf_ring *);  void ixgbevf_update_stats(struct ixgbevf_adapter *adapter);  int ethtool_ioctl(struct ifreq *ifr); +extern void ixgbevf_write_eitr(struct ixgbevf_q_vector *q_vector); +  void ixgbe_napi_add_all(struct ixgbevf_adapter *adapter);  void ixgbe_napi_del_all(struct ixgbevf_adapter *adapter); diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index c0f9aad2cda3..8407fd274810 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -580,7 +580,7 @@ static int ixgbevf_poll(struct napi_struct *napi, int budget)   * ixgbevf_write_eitr - write VTEITR register in hardware specific way   * @q_vector: structure containing interrupt and ring information   */ -static void ixgbevf_write_eitr(struct ixgbevf_q_vector *q_vector) +void ixgbevf_write_eitr(struct ixgbevf_q_vector *q_vector)  {  	struct ixgbevf_adapter *adapter = q_vector->adapter;  	struct ixgbe_hw *hw = &adapter->hw; | 
