Commit 65e87c03 authored by Jacob Keller's avatar Jacob Keller Committed by Jeff Kirsher

i40evf: support queue-specific settings for interrupt moderation

In commit a75e8005 ("i40e: queue-specific settings for interrupt
moderation") the i40e driver gained support for setting interrupt
moderation values per queue. This patch adds support for this feature
to the i40evf driver as well. In addition, a few changes are made to
the i40e implementation to add function header documentation comments,
as well.

This behaves in a similar fashion to the implementation in i40e. Thus,
requesting the moderation value when no queue is provided will report
queue 0 value, while setting the value without a queue will set all
queues at once.

Change-ID: I1f310a57c8e6c84a8524c178d44d1b7a6d3a848e
Signed-off-by: default avatarJacob Keller <jacob.e.keller@intel.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent a4fa59cc
...@@ -1970,11 +1970,22 @@ static int i40e_set_phys_id(struct net_device *netdev, ...@@ -1970,11 +1970,22 @@ static int i40e_set_phys_id(struct net_device *netdev,
* 125us (8000 interrupts per second) == ITR(62) * 125us (8000 interrupts per second) == ITR(62)
*/ */
/**
* __i40e_get_coalesce - get per-queue coalesce settings
* @netdev: the netdev to check
* @ec: ethtool coalesce data structure
* @queue: which queue to pick
*
* Gets the per-queue settings for coalescence. Specifically Rx and Tx usecs
* are per queue. If queue is <0 then we default to queue 0 as the
* representative value.
**/
static int __i40e_get_coalesce(struct net_device *netdev, static int __i40e_get_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec, struct ethtool_coalesce *ec,
int queue) int queue)
{ {
struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_ring *rx_ring, *tx_ring;
struct i40e_vsi *vsi = np->vsi; struct i40e_vsi *vsi = np->vsi;
ec->tx_max_coalesced_frames_irq = vsi->work_limit; ec->tx_max_coalesced_frames_irq = vsi->work_limit;
...@@ -1989,14 +2000,18 @@ static int __i40e_get_coalesce(struct net_device *netdev, ...@@ -1989,14 +2000,18 @@ static int __i40e_get_coalesce(struct net_device *netdev,
return -EINVAL; return -EINVAL;
} }
if (ITR_IS_DYNAMIC(vsi->rx_rings[queue]->rx_itr_setting)) rx_ring = vsi->rx_rings[queue];
tx_ring = vsi->tx_rings[queue];
if (ITR_IS_DYNAMIC(rx_ring->rx_itr_setting))
ec->use_adaptive_rx_coalesce = 1; ec->use_adaptive_rx_coalesce = 1;
if (ITR_IS_DYNAMIC(vsi->tx_rings[queue]->tx_itr_setting)) if (ITR_IS_DYNAMIC(tx_ring->tx_itr_setting))
ec->use_adaptive_tx_coalesce = 1; ec->use_adaptive_tx_coalesce = 1;
ec->rx_coalesce_usecs = vsi->rx_rings[queue]->rx_itr_setting & ~I40E_ITR_DYNAMIC; ec->rx_coalesce_usecs = rx_ring->rx_itr_setting & ~I40E_ITR_DYNAMIC;
ec->tx_coalesce_usecs = vsi->tx_rings[queue]->tx_itr_setting & ~I40E_ITR_DYNAMIC; ec->tx_coalesce_usecs = tx_ring->tx_itr_setting & ~I40E_ITR_DYNAMIC;
/* we use the _usecs_high to store/set the interrupt rate limit /* we use the _usecs_high to store/set the interrupt rate limit
* that the hardware supports, that almost but not quite * that the hardware supports, that almost but not quite
...@@ -2010,18 +2025,44 @@ static int __i40e_get_coalesce(struct net_device *netdev, ...@@ -2010,18 +2025,44 @@ static int __i40e_get_coalesce(struct net_device *netdev,
return 0; return 0;
} }
/**
* i40e_get_coalesce - get a netdev's coalesce settings
* @netdev: the netdev to check
* @ec: ethtool coalesce data structure
*
* Gets the coalesce settings for a particular netdev. Note that if user has
* modified per-queue settings, this only guarantees to represent queue 0. See
* __i40e_get_coalesce for more details.
**/
static int i40e_get_coalesce(struct net_device *netdev, static int i40e_get_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec) struct ethtool_coalesce *ec)
{ {
return __i40e_get_coalesce(netdev, ec, -1); return __i40e_get_coalesce(netdev, ec, -1);
} }
/**
* i40e_get_per_queue_coalesce - gets coalesce settings for particular queue
* @netdev: netdev structure
* @ec: ethtool's coalesce settings
* @queue: the particular queue to read
*
* Will read a specific queue's coalesce settings
**/
static int i40e_get_per_queue_coalesce(struct net_device *netdev, u32 queue, static int i40e_get_per_queue_coalesce(struct net_device *netdev, u32 queue,
struct ethtool_coalesce *ec) struct ethtool_coalesce *ec)
{ {
return __i40e_get_coalesce(netdev, ec, queue); return __i40e_get_coalesce(netdev, ec, queue);
} }
/**
* i40e_set_itr_per_queue - set ITR values for specific queue
* @vsi: the VSI to set values for
* @ec: coalesce settings from ethtool
* @queue: the queue to modify
*
* Change the ITR settings for a specific queue.
**/
static void i40e_set_itr_per_queue(struct i40e_vsi *vsi, static void i40e_set_itr_per_queue(struct i40e_vsi *vsi,
struct ethtool_coalesce *ec, struct ethtool_coalesce *ec,
int queue) int queue)
...@@ -2060,6 +2101,14 @@ static void i40e_set_itr_per_queue(struct i40e_vsi *vsi, ...@@ -2060,6 +2101,14 @@ static void i40e_set_itr_per_queue(struct i40e_vsi *vsi,
i40e_flush(hw); i40e_flush(hw);
} }
/**
* __i40e_set_coalesce - set coalesce settings for particular queue
* @netdev: the netdev to change
* @ec: ethtool coalesce settings
* @queue: the queue to change
*
* Sets the coalesce settings for a particular queue.
**/
static int __i40e_set_coalesce(struct net_device *netdev, static int __i40e_set_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec, struct ethtool_coalesce *ec,
int queue) int queue)
...@@ -2120,12 +2169,27 @@ static int __i40e_set_coalesce(struct net_device *netdev, ...@@ -2120,12 +2169,27 @@ static int __i40e_set_coalesce(struct net_device *netdev,
return 0; return 0;
} }
/**
* i40e_set_coalesce - set coalesce settings for every queue on the netdev
* @netdev: the netdev to change
* @ec: ethtool coalesce settings
*
* This will set each queue to the same coalesce settings.
**/
static int i40e_set_coalesce(struct net_device *netdev, static int i40e_set_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec) struct ethtool_coalesce *ec)
{ {
return __i40e_set_coalesce(netdev, ec, -1); return __i40e_set_coalesce(netdev, ec, -1);
} }
/**
* i40e_set_per_queue_coalesce - set specific queue's coalesce settings
* @netdev: the netdev to change
* @ec: ethtool's coalesce settings
* @queue: the queue to change
*
* Sets the specified queue's coalesce settings.
**/
static int i40e_set_per_queue_coalesce(struct net_device *netdev, u32 queue, static int i40e_set_per_queue_coalesce(struct net_device *netdev, u32 queue,
struct ethtool_coalesce *ec) struct ethtool_coalesce *ec)
{ {
......
...@@ -1877,6 +1877,15 @@ static u32 i40e_buildreg_itr(const int type, const u16 itr) ...@@ -1877,6 +1877,15 @@ static u32 i40e_buildreg_itr(const int type, const u16 itr)
/* a small macro to shorten up some long lines */ /* a small macro to shorten up some long lines */
#define INTREG I40E_PFINT_DYN_CTLN #define INTREG I40E_PFINT_DYN_CTLN
static inline int get_rx_itr_enabled(struct i40e_vsi *vsi, int idx)
{
return !!(vsi->rx_rings[idx]->rx_itr_setting);
}
static inline int get_tx_itr_enabled(struct i40e_vsi *vsi, int idx)
{
return !!(vsi->tx_rings[idx]->tx_itr_setting);
}
/** /**
* i40e_update_enable_itr - Update itr and re-enable MSIX interrupt * i40e_update_enable_itr - Update itr and re-enable MSIX interrupt
...@@ -1892,6 +1901,7 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi, ...@@ -1892,6 +1901,7 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
u32 rxval, txval; u32 rxval, txval;
int vector; int vector;
int idx = q_vector->v_idx; int idx = q_vector->v_idx;
int rx_itr_setting, tx_itr_setting;
vector = (q_vector->v_idx + vsi->base_vector); vector = (q_vector->v_idx + vsi->base_vector);
...@@ -1900,18 +1910,21 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi, ...@@ -1900,18 +1910,21 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
*/ */
rxval = txval = i40e_buildreg_itr(I40E_ITR_NONE, 0); rxval = txval = i40e_buildreg_itr(I40E_ITR_NONE, 0);
rx_itr_setting = get_rx_itr_enabled(vsi, idx);
tx_itr_setting = get_tx_itr_enabled(vsi, idx);
if (q_vector->itr_countdown > 0 || if (q_vector->itr_countdown > 0 ||
(!ITR_IS_DYNAMIC(vsi->rx_rings[idx]->rx_itr_setting) && (!ITR_IS_DYNAMIC(rx_itr_setting) &&
!ITR_IS_DYNAMIC(vsi->tx_rings[idx]->tx_itr_setting))) { !ITR_IS_DYNAMIC(tx_itr_setting))) {
goto enable_int; goto enable_int;
} }
if (ITR_IS_DYNAMIC(vsi->rx_rings[idx]->rx_itr_setting)) { if (ITR_IS_DYNAMIC(tx_itr_setting)) {
rx = i40e_set_new_dynamic_itr(&q_vector->rx); rx = i40e_set_new_dynamic_itr(&q_vector->rx);
rxval = i40e_buildreg_itr(I40E_RX_ITR, q_vector->rx.itr); rxval = i40e_buildreg_itr(I40E_RX_ITR, q_vector->rx.itr);
} }
if (ITR_IS_DYNAMIC(vsi->tx_rings[idx]->tx_itr_setting)) { if (ITR_IS_DYNAMIC(tx_itr_setting)) {
tx = i40e_set_new_dynamic_itr(&q_vector->tx); tx = i40e_set_new_dynamic_itr(&q_vector->tx);
txval = i40e_buildreg_itr(I40E_TX_ITR, q_vector->tx.itr); txval = i40e_buildreg_itr(I40E_TX_ITR, q_vector->tx.itr);
} }
......
...@@ -1311,6 +1311,19 @@ static u32 i40e_buildreg_itr(const int type, const u16 itr) ...@@ -1311,6 +1311,19 @@ static u32 i40e_buildreg_itr(const int type, const u16 itr)
/* a small macro to shorten up some long lines */ /* a small macro to shorten up some long lines */
#define INTREG I40E_VFINT_DYN_CTLN1 #define INTREG I40E_VFINT_DYN_CTLN1
static inline int get_rx_itr_enabled(struct i40e_vsi *vsi, int idx)
{
struct i40evf_adapter *adapter = vsi->back;
return !!(adapter->rx_rings[idx].rx_itr_setting);
}
static inline int get_tx_itr_enabled(struct i40e_vsi *vsi, int idx)
{
struct i40evf_adapter *adapter = vsi->back;
return !!(adapter->tx_rings[idx].tx_itr_setting);
}
/** /**
* i40e_update_enable_itr - Update itr and re-enable MSIX interrupt * i40e_update_enable_itr - Update itr and re-enable MSIX interrupt
...@@ -1325,6 +1338,8 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi, ...@@ -1325,6 +1338,8 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
bool rx = false, tx = false; bool rx = false, tx = false;
u32 rxval, txval; u32 rxval, txval;
int vector; int vector;
int idx = q_vector->v_idx;
int rx_itr_setting, tx_itr_setting;
vector = (q_vector->v_idx + vsi->base_vector); vector = (q_vector->v_idx + vsi->base_vector);
...@@ -1333,18 +1348,21 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi, ...@@ -1333,18 +1348,21 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
*/ */
rxval = txval = i40e_buildreg_itr(I40E_ITR_NONE, 0); rxval = txval = i40e_buildreg_itr(I40E_ITR_NONE, 0);
rx_itr_setting = get_rx_itr_enabled(vsi, idx);
tx_itr_setting = get_tx_itr_enabled(vsi, idx);
if (q_vector->itr_countdown > 0 || if (q_vector->itr_countdown > 0 ||
(!ITR_IS_DYNAMIC(vsi->rx_itr_setting) && (!ITR_IS_DYNAMIC(rx_itr_setting) &&
!ITR_IS_DYNAMIC(vsi->tx_itr_setting))) { !ITR_IS_DYNAMIC(tx_itr_setting))) {
goto enable_int; goto enable_int;
} }
if (ITR_IS_DYNAMIC(vsi->rx_itr_setting)) { if (ITR_IS_DYNAMIC(rx_itr_setting)) {
rx = i40e_set_new_dynamic_itr(&q_vector->rx); rx = i40e_set_new_dynamic_itr(&q_vector->rx);
rxval = i40e_buildreg_itr(I40E_RX_ITR, q_vector->rx.itr); rxval = i40e_buildreg_itr(I40E_RX_ITR, q_vector->rx.itr);
} }
if (ITR_IS_DYNAMIC(vsi->tx_itr_setting)) { if (ITR_IS_DYNAMIC(tx_itr_setting)) {
tx = i40e_set_new_dynamic_itr(&q_vector->tx); tx = i40e_set_new_dynamic_itr(&q_vector->tx);
txval = i40e_buildreg_itr(I40E_TX_ITR, q_vector->tx.itr); txval = i40e_buildreg_itr(I40E_TX_ITR, q_vector->tx.itr);
} }
......
...@@ -287,6 +287,14 @@ struct i40e_ring { ...@@ -287,6 +287,14 @@ struct i40e_ring {
u8 dcb_tc; /* Traffic class of ring */ u8 dcb_tc; /* Traffic class of ring */
u8 __iomem *tail; u8 __iomem *tail;
/* high bit set means dynamic, use accessors routines to read/write.
* hardware only supports 2us resolution for the ITR registers.
* these values always store the USER setting, and must be converted
* before programming to a register.
*/
u16 rx_itr_setting;
u16 tx_itr_setting;
u16 count; /* Number of descriptors */ u16 count; /* Number of descriptors */
u16 reg_idx; /* HW register index of the ring */ u16 reg_idx; /* HW register index of the ring */
u16 rx_buf_len; u16 rx_buf_len;
......
...@@ -59,13 +59,6 @@ struct i40e_vsi { ...@@ -59,13 +59,6 @@ struct i40e_vsi {
unsigned long state; unsigned long state;
int base_vector; int base_vector;
u16 work_limit; u16 work_limit;
/* high bit set means dynamic, use accessor routines to read/write.
* hardware only supports 2us resolution for the ITR registers.
* these values always store the USER setting, and must be converted
* before programming to a register.
*/
u16 rx_itr_setting;
u16 tx_itr_setting;
u16 qs_handle; u16 qs_handle;
}; };
......
...@@ -296,92 +296,206 @@ static int i40evf_set_ringparam(struct net_device *netdev, ...@@ -296,92 +296,206 @@ static int i40evf_set_ringparam(struct net_device *netdev,
} }
/** /**
* i40evf_get_coalesce - Get interrupt coalescing settings * __i40evf_get_coalesce - get per-queue coalesce settings
* @netdev: network interface device structure * @netdev: the netdev to check
* @ec: ethtool coalesce structure * @ec: ethtool coalesce data structure
* @queue: which queue to pick
* *
* Returns current coalescing settings. This is referred to elsewhere in the * Gets the per-queue settings for coalescence. Specifically Rx and Tx usecs
* driver as Interrupt Throttle Rate, as this is how the hardware describes * are per queue. If queue is <0 then we default to queue 0 as the
* this functionality. * representative value.
**/ **/
static int i40evf_get_coalesce(struct net_device *netdev, static int __i40evf_get_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec) struct ethtool_coalesce *ec,
int queue)
{ {
struct i40evf_adapter *adapter = netdev_priv(netdev); struct i40evf_adapter *adapter = netdev_priv(netdev);
struct i40e_vsi *vsi = &adapter->vsi; struct i40e_vsi *vsi = &adapter->vsi;
struct i40e_ring *rx_ring, *tx_ring;
ec->tx_max_coalesced_frames = vsi->work_limit; ec->tx_max_coalesced_frames = vsi->work_limit;
ec->rx_max_coalesced_frames = vsi->work_limit; ec->rx_max_coalesced_frames = vsi->work_limit;
if (ITR_IS_DYNAMIC(vsi->rx_itr_setting)) /* Rx and Tx usecs per queue value. If user doesn't specify the
* queue, return queue 0's value to represent.
*/
if (queue < 0)
queue = 0;
else if (queue >= adapter->num_active_queues)
return -EINVAL;
rx_ring = &adapter->rx_rings[queue];
tx_ring = &adapter->tx_rings[queue];
if (ITR_IS_DYNAMIC(rx_ring->rx_itr_setting))
ec->use_adaptive_rx_coalesce = 1; ec->use_adaptive_rx_coalesce = 1;
if (ITR_IS_DYNAMIC(vsi->tx_itr_setting)) if (ITR_IS_DYNAMIC(tx_ring->tx_itr_setting))
ec->use_adaptive_tx_coalesce = 1; ec->use_adaptive_tx_coalesce = 1;
ec->rx_coalesce_usecs = vsi->rx_itr_setting & ~I40E_ITR_DYNAMIC; ec->rx_coalesce_usecs = rx_ring->rx_itr_setting & ~I40E_ITR_DYNAMIC;
ec->tx_coalesce_usecs = vsi->tx_itr_setting & ~I40E_ITR_DYNAMIC; ec->tx_coalesce_usecs = tx_ring->tx_itr_setting & ~I40E_ITR_DYNAMIC;
return 0; return 0;
} }
/** /**
* i40evf_set_coalesce - Set interrupt coalescing settings * i40evf_get_coalesce - Get interrupt coalescing settings
* @netdev: network interface device structure * @netdev: network interface device structure
* @ec: ethtool coalesce structure * @ec: ethtool coalesce structure
* *
* Change current coalescing settings. * Returns current coalescing settings. This is referred to elsewhere in the
* driver as Interrupt Throttle Rate, as this is how the hardware describes
* this functionality. Note that if per-queue settings have been modified this
* only represents the settings of queue 0.
**/ **/
static int i40evf_set_coalesce(struct net_device *netdev, static int i40evf_get_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec) struct ethtool_coalesce *ec)
{ {
struct i40evf_adapter *adapter = netdev_priv(netdev); return __i40evf_get_coalesce(netdev, ec, -1);
struct i40e_hw *hw = &adapter->hw; }
/**
* i40evf_get_per_queue_coalesce - get coalesce values for specific queue
* @netdev: netdev to read
* @ec: coalesce settings from ethtool
* @queue: the queue to read
*
* Read specific queue's coalesce settings.
**/
static int i40evf_get_per_queue_coalesce(struct net_device *netdev,
u32 queue,
struct ethtool_coalesce *ec)
{
return __i40evf_get_coalesce(netdev, ec, queue);
}
/**
* i40evf_set_itr_per_queue - set ITR values for specific queue
* @vsi: the VSI to set values for
* @ec: coalesce settings from ethtool
* @queue: the queue to modify
*
* Change the ITR settings for a specific queue.
**/
static void i40evf_set_itr_per_queue(struct i40evf_adapter *adapter,
struct ethtool_coalesce *ec,
int queue)
{
struct i40e_vsi *vsi = &adapter->vsi; struct i40e_vsi *vsi = &adapter->vsi;
struct i40e_hw *hw = &adapter->hw;
struct i40e_q_vector *q_vector; struct i40e_q_vector *q_vector;
u16 vector;
adapter->rx_rings[queue].rx_itr_setting = ec->rx_coalesce_usecs;
adapter->tx_rings[queue].tx_itr_setting = ec->tx_coalesce_usecs;
if (ec->use_adaptive_rx_coalesce)
adapter->rx_rings[queue].rx_itr_setting |= I40E_ITR_DYNAMIC;
else
adapter->rx_rings[queue].rx_itr_setting &= ~I40E_ITR_DYNAMIC;
if (ec->use_adaptive_tx_coalesce)
adapter->tx_rings[queue].tx_itr_setting |= I40E_ITR_DYNAMIC;
else
adapter->tx_rings[queue].tx_itr_setting &= ~I40E_ITR_DYNAMIC;
q_vector = adapter->rx_rings[queue].q_vector;
q_vector->rx.itr = ITR_TO_REG(adapter->rx_rings[queue].rx_itr_setting);
vector = vsi->base_vector + q_vector->v_idx;
wr32(hw, I40E_VFINT_ITRN1(I40E_RX_ITR, vector - 1), q_vector->rx.itr);
q_vector = adapter->tx_rings[queue].q_vector;
q_vector->tx.itr = ITR_TO_REG(adapter->tx_rings[queue].tx_itr_setting);
vector = vsi->base_vector + q_vector->v_idx;
wr32(hw, I40E_VFINT_ITRN1(I40E_TX_ITR, vector - 1), q_vector->tx.itr);
i40e_flush(hw);
}
/**
* __i40evf_set_coalesce - set coalesce settings for particular queue
* @netdev: the netdev to change
* @ec: ethtool coalesce settings
* @queue: the queue to change
*
* Sets the coalesce settings for a particular queue.
**/
static int __i40evf_set_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec,
int queue)
{
struct i40evf_adapter *adapter = netdev_priv(netdev);
struct i40e_vsi *vsi = &adapter->vsi;
int i; int i;
if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq) if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq)
vsi->work_limit = ec->tx_max_coalesced_frames_irq; vsi->work_limit = ec->tx_max_coalesced_frames_irq;
if ((ec->rx_coalesce_usecs >= (I40E_MIN_ITR << 1)) && if (ec->rx_coalesce_usecs == 0) {
(ec->rx_coalesce_usecs <= (I40E_MAX_ITR << 1))) if (ec->use_adaptive_rx_coalesce)
vsi->rx_itr_setting = ec->rx_coalesce_usecs; netif_info(adapter, drv, netdev, "rx-usecs=0, need to disable adaptive-rx for a complete disable\n");
} else if ((ec->rx_coalesce_usecs < (I40E_MIN_ITR << 1)) ||
else (ec->rx_coalesce_usecs > (I40E_MAX_ITR << 1))) {
netif_info(adapter, drv, netdev, "Invalid value, rx-usecs range is 0-8160\n");
return -EINVAL; return -EINVAL;
}
if ((ec->tx_coalesce_usecs >= (I40E_MIN_ITR << 1)) &&
(ec->tx_coalesce_usecs <= (I40E_MAX_ITR << 1)))
vsi->tx_itr_setting = ec->tx_coalesce_usecs;
else if (ec->use_adaptive_tx_coalesce)
vsi->tx_itr_setting = (I40E_ITR_DYNAMIC |
ITR_REG_TO_USEC(I40E_ITR_RX_DEF));
else else
if (ec->tx_coalesce_usecs == 0) {
if (ec->use_adaptive_tx_coalesce)
netif_info(adapter, drv, netdev, "tx-usecs=0, need to disable adaptive-tx for a complete disable\n");
} else if ((ec->tx_coalesce_usecs < (I40E_MIN_ITR << 1)) ||
(ec->tx_coalesce_usecs > (I40E_MAX_ITR << 1))) {
netif_info(adapter, drv, netdev, "Invalid value, tx-usecs range is 0-8160\n");
return -EINVAL; return -EINVAL;
}
if (ec->use_adaptive_rx_coalesce) /* Rx and Tx usecs has per queue value. If user doesn't specify the
vsi->rx_itr_setting |= I40E_ITR_DYNAMIC; * queue, apply to all queues.
else */
vsi->rx_itr_setting &= ~I40E_ITR_DYNAMIC; if (queue < 0) {
for (i = 0; i < adapter->num_active_queues; i++)
if (ec->use_adaptive_tx_coalesce) i40evf_set_itr_per_queue(adapter, ec, i);
vsi->tx_itr_setting |= I40E_ITR_DYNAMIC; } else if (queue < adapter->num_active_queues) {
else i40evf_set_itr_per_queue(adapter, ec, queue);
vsi->tx_itr_setting &= ~I40E_ITR_DYNAMIC; } else {
netif_info(adapter, drv, netdev, "Invalid queue value, queue range is 0 - %d\n",
for (i = 0; i < adapter->num_msix_vectors - NONQ_VECS; i++) { adapter->num_active_queues - 1);
q_vector = &adapter->q_vectors[i]; return -EINVAL;
q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting);
wr32(hw, I40E_VFINT_ITRN1(0, i), q_vector->rx.itr);
q_vector->tx.itr = ITR_TO_REG(vsi->tx_itr_setting);
wr32(hw, I40E_VFINT_ITRN1(1, i), q_vector->tx.itr);
i40e_flush(hw);
} }
return 0; return 0;
} }
/**
* i40evf_set_coalesce - Set interrupt coalescing settings
* @netdev: network interface device structure
* @ec: ethtool coalesce structure
*
* Change current coalescing settings for every queue.
**/
static int i40evf_set_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec)
{
return __i40evf_set_coalesce(netdev, ec, -1);
}
/**
* i40evf_set_per_queue_coalesce - set specific queue's coalesce settings
* @netdev: the netdev to change
* @ec: ethtool's coalesce settings
* @queue: the queue to modify
*
* Modifies a specific queue's coalesce settings.
*/
static int i40evf_set_per_queue_coalesce(struct net_device *netdev,
u32 queue,
struct ethtool_coalesce *ec)
{
return __i40evf_set_coalesce(netdev, ec, queue);
}
/** /**
* i40evf_get_rxnfc - command to get RX flow classification rules * i40evf_get_rxnfc - command to get RX flow classification rules
* @netdev: network interface device structure * @netdev: network interface device structure
...@@ -533,6 +647,8 @@ static const struct ethtool_ops i40evf_ethtool_ops = { ...@@ -533,6 +647,8 @@ static const struct ethtool_ops i40evf_ethtool_ops = {
.set_msglevel = i40evf_set_msglevel, .set_msglevel = i40evf_set_msglevel,
.get_coalesce = i40evf_get_coalesce, .get_coalesce = i40evf_get_coalesce,
.set_coalesce = i40evf_set_coalesce, .set_coalesce = i40evf_set_coalesce,
.get_per_queue_coalesce = i40evf_get_per_queue_coalesce,
.set_per_queue_coalesce = i40evf_set_per_queue_coalesce,
.get_rxnfc = i40evf_get_rxnfc, .get_rxnfc = i40evf_get_rxnfc,
.get_rxfh_indir_size = i40evf_get_rxfh_indir_size, .get_rxfh_indir_size = i40evf_get_rxfh_indir_size,
.get_rxfh = i40evf_get_rxfh, .get_rxfh = i40evf_get_rxfh,
......
...@@ -370,7 +370,6 @@ i40evf_map_vector_to_rxq(struct i40evf_adapter *adapter, int v_idx, int r_idx) ...@@ -370,7 +370,6 @@ i40evf_map_vector_to_rxq(struct i40evf_adapter *adapter, int v_idx, int r_idx)
{ {
struct i40e_q_vector *q_vector = &adapter->q_vectors[v_idx]; struct i40e_q_vector *q_vector = &adapter->q_vectors[v_idx];
struct i40e_ring *rx_ring = &adapter->rx_rings[r_idx]; struct i40e_ring *rx_ring = &adapter->rx_rings[r_idx];
struct i40e_vsi *vsi = &adapter->vsi;
struct i40e_hw *hw = &adapter->hw; struct i40e_hw *hw = &adapter->hw;
rx_ring->q_vector = q_vector; rx_ring->q_vector = q_vector;
...@@ -379,7 +378,7 @@ i40evf_map_vector_to_rxq(struct i40evf_adapter *adapter, int v_idx, int r_idx) ...@@ -379,7 +378,7 @@ i40evf_map_vector_to_rxq(struct i40evf_adapter *adapter, int v_idx, int r_idx)
q_vector->rx.ring = rx_ring; q_vector->rx.ring = rx_ring;
q_vector->rx.count++; q_vector->rx.count++;
q_vector->rx.latency_range = I40E_LOW_LATENCY; q_vector->rx.latency_range = I40E_LOW_LATENCY;
q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting); q_vector->rx.itr = ITR_TO_REG(rx_ring->rx_itr_setting);
q_vector->ring_mask |= BIT(r_idx); q_vector->ring_mask |= BIT(r_idx);
q_vector->itr_countdown = ITR_COUNTDOWN_START; q_vector->itr_countdown = ITR_COUNTDOWN_START;
wr32(hw, I40E_VFINT_ITRN1(I40E_RX_ITR, v_idx - 1), q_vector->rx.itr); wr32(hw, I40E_VFINT_ITRN1(I40E_RX_ITR, v_idx - 1), q_vector->rx.itr);
...@@ -396,7 +395,6 @@ i40evf_map_vector_to_txq(struct i40evf_adapter *adapter, int v_idx, int t_idx) ...@@ -396,7 +395,6 @@ i40evf_map_vector_to_txq(struct i40evf_adapter *adapter, int v_idx, int t_idx)
{ {
struct i40e_q_vector *q_vector = &adapter->q_vectors[v_idx]; struct i40e_q_vector *q_vector = &adapter->q_vectors[v_idx];
struct i40e_ring *tx_ring = &adapter->tx_rings[t_idx]; struct i40e_ring *tx_ring = &adapter->tx_rings[t_idx];
struct i40e_vsi *vsi = &adapter->vsi;
struct i40e_hw *hw = &adapter->hw; struct i40e_hw *hw = &adapter->hw;
tx_ring->q_vector = q_vector; tx_ring->q_vector = q_vector;
...@@ -405,7 +403,7 @@ i40evf_map_vector_to_txq(struct i40evf_adapter *adapter, int v_idx, int t_idx) ...@@ -405,7 +403,7 @@ i40evf_map_vector_to_txq(struct i40evf_adapter *adapter, int v_idx, int t_idx)
q_vector->tx.ring = tx_ring; q_vector->tx.ring = tx_ring;
q_vector->tx.count++; q_vector->tx.count++;
q_vector->tx.latency_range = I40E_LOW_LATENCY; q_vector->tx.latency_range = I40E_LOW_LATENCY;
q_vector->tx.itr = ITR_TO_REG(vsi->tx_itr_setting); q_vector->tx.itr = ITR_TO_REG(tx_ring->tx_itr_setting);
q_vector->itr_countdown = ITR_COUNTDOWN_START; q_vector->itr_countdown = ITR_COUNTDOWN_START;
q_vector->num_ringpairs++; q_vector->num_ringpairs++;
wr32(hw, I40E_VFINT_ITRN1(I40E_TX_ITR, v_idx - 1), q_vector->tx.itr); wr32(hw, I40E_VFINT_ITRN1(I40E_TX_ITR, v_idx - 1), q_vector->tx.itr);
...@@ -1162,6 +1160,7 @@ static int i40evf_alloc_queues(struct i40evf_adapter *adapter) ...@@ -1162,6 +1160,7 @@ static int i40evf_alloc_queues(struct i40evf_adapter *adapter)
tx_ring->netdev = adapter->netdev; tx_ring->netdev = adapter->netdev;
tx_ring->dev = &adapter->pdev->dev; tx_ring->dev = &adapter->pdev->dev;
tx_ring->count = adapter->tx_desc_count; tx_ring->count = adapter->tx_desc_count;
tx_ring->tx_itr_setting = (I40E_ITR_DYNAMIC | I40E_ITR_TX_DEF);
if (adapter->flags & I40E_FLAG_WB_ON_ITR_CAPABLE) if (adapter->flags & I40E_FLAG_WB_ON_ITR_CAPABLE)
tx_ring->flags |= I40E_TXR_FLAGS_WB_ON_ITR; tx_ring->flags |= I40E_TXR_FLAGS_WB_ON_ITR;
...@@ -1170,6 +1169,7 @@ static int i40evf_alloc_queues(struct i40evf_adapter *adapter) ...@@ -1170,6 +1169,7 @@ static int i40evf_alloc_queues(struct i40evf_adapter *adapter)
rx_ring->netdev = adapter->netdev; rx_ring->netdev = adapter->netdev;
rx_ring->dev = &adapter->pdev->dev; rx_ring->dev = &adapter->pdev->dev;
rx_ring->count = adapter->rx_desc_count; rx_ring->count = adapter->rx_desc_count;
rx_ring->rx_itr_setting = (I40E_ITR_DYNAMIC | I40E_ITR_RX_DEF);
} }
return 0; return 0;
...@@ -2277,8 +2277,6 @@ int i40evf_process_config(struct i40evf_adapter *adapter) ...@@ -2277,8 +2277,6 @@ int i40evf_process_config(struct i40evf_adapter *adapter)
adapter->vsi.back = adapter; adapter->vsi.back = adapter;
adapter->vsi.base_vector = 1; adapter->vsi.base_vector = 1;
adapter->vsi.work_limit = I40E_DEFAULT_IRQ_WORK; adapter->vsi.work_limit = I40E_DEFAULT_IRQ_WORK;
adapter->vsi.rx_itr_setting = (I40E_ITR_DYNAMIC | I40E_ITR_RX_DEF);
adapter->vsi.tx_itr_setting = (I40E_ITR_DYNAMIC | I40E_ITR_TX_DEF);
vsi->netdev = adapter->netdev; vsi->netdev = adapter->netdev;
vsi->qs_handle = adapter->vsi_res->qset_handle; vsi->qs_handle = adapter->vsi_res->qset_handle;
if (vfres->vf_offload_flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF) { if (vfres->vf_offload_flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment