ixgbe: Allow tx itr specific settings
Allow the user to set Tx specific itr values. This only makes sense when there are separate vectors for Tx and Rx. When the queues are doubled up RxTx on the vectors, we still only use the rx itr value. Signed-off-by: Shannon Nelson <shannon.nelson@intel.com> Acked-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
0a1f87cbdb
commit
f7554a2bf2
3 changed files with 83 additions and 29 deletions
|
@ -267,7 +267,8 @@ struct ixgbe_adapter {
|
||||||
enum ixgbe_fc_mode last_lfc_mode;
|
enum ixgbe_fc_mode last_lfc_mode;
|
||||||
|
|
||||||
/* Interrupt Throttle Rate */
|
/* Interrupt Throttle Rate */
|
||||||
u32 itr_setting;
|
u32 rx_itr_setting;
|
||||||
|
u32 tx_itr_setting;
|
||||||
u16 eitr_low;
|
u16 eitr_low;
|
||||||
u16 eitr_high;
|
u16 eitr_high;
|
||||||
|
|
||||||
|
@ -351,7 +352,8 @@ struct ixgbe_adapter {
|
||||||
struct ixgbe_hw_stats stats;
|
struct ixgbe_hw_stats stats;
|
||||||
|
|
||||||
/* Interrupt Throttle Rate */
|
/* Interrupt Throttle Rate */
|
||||||
u32 eitr_param;
|
u32 rx_eitr_param;
|
||||||
|
u32 tx_eitr_param;
|
||||||
|
|
||||||
unsigned long state;
|
unsigned long state;
|
||||||
u64 tx_busy;
|
u64 tx_busy;
|
||||||
|
|
|
@ -1929,7 +1929,7 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
|
||||||
ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0].work_limit;
|
ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0].work_limit;
|
||||||
|
|
||||||
/* only valid if in constant ITR mode */
|
/* only valid if in constant ITR mode */
|
||||||
switch (adapter->itr_setting) {
|
switch (adapter->rx_itr_setting) {
|
||||||
case 0:
|
case 0:
|
||||||
/* throttling disabled */
|
/* throttling disabled */
|
||||||
ec->rx_coalesce_usecs = 0;
|
ec->rx_coalesce_usecs = 0;
|
||||||
|
@ -1940,9 +1940,25 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* fixed interrupt rate mode */
|
/* fixed interrupt rate mode */
|
||||||
ec->rx_coalesce_usecs = 1000000/adapter->eitr_param;
|
ec->rx_coalesce_usecs = 1000000/adapter->rx_eitr_param;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* only valid if in constant ITR mode */
|
||||||
|
switch (adapter->tx_itr_setting) {
|
||||||
|
case 0:
|
||||||
|
/* throttling disabled */
|
||||||
|
ec->tx_coalesce_usecs = 0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
/* dynamic ITR mode */
|
||||||
|
ec->tx_coalesce_usecs = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ec->tx_coalesce_usecs = 1000000/adapter->tx_eitr_param;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1953,6 +1969,14 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
|
||||||
struct ixgbe_q_vector *q_vector;
|
struct ixgbe_q_vector *q_vector;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* don't accept tx specific changes if we've got mixed RxTx vectors
|
||||||
|
* test and jump out here if needed before changing the rx numbers
|
||||||
|
*/
|
||||||
|
if ((1000000/ec->tx_coalesce_usecs) != adapter->tx_eitr_param &&
|
||||||
|
adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
if (ec->tx_max_coalesced_frames_irq)
|
if (ec->tx_max_coalesced_frames_irq)
|
||||||
adapter->tx_ring[0].work_limit = ec->tx_max_coalesced_frames_irq;
|
adapter->tx_ring[0].work_limit = ec->tx_max_coalesced_frames_irq;
|
||||||
|
|
||||||
|
@ -1963,26 +1987,49 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* store the value in ints/second */
|
/* store the value in ints/second */
|
||||||
adapter->eitr_param = 1000000/ec->rx_coalesce_usecs;
|
adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
|
||||||
|
|
||||||
/* static value of interrupt rate */
|
/* static value of interrupt rate */
|
||||||
adapter->itr_setting = adapter->eitr_param;
|
adapter->rx_itr_setting = adapter->rx_eitr_param;
|
||||||
/* clear the lower bit as its used for dynamic state */
|
/* clear the lower bit as its used for dynamic state */
|
||||||
adapter->itr_setting &= ~1;
|
adapter->rx_itr_setting &= ~1;
|
||||||
} else if (ec->rx_coalesce_usecs == 1) {
|
} else if (ec->rx_coalesce_usecs == 1) {
|
||||||
/* 1 means dynamic mode */
|
/* 1 means dynamic mode */
|
||||||
adapter->eitr_param = 20000;
|
adapter->rx_eitr_param = 20000;
|
||||||
adapter->itr_setting = 1;
|
adapter->rx_itr_setting = 1;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* any other value means disable eitr, which is best
|
* any other value means disable eitr, which is best
|
||||||
* served by setting the interrupt rate very high
|
* served by setting the interrupt rate very high
|
||||||
*/
|
*/
|
||||||
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
|
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
|
||||||
adapter->eitr_param = IXGBE_MAX_RSC_INT_RATE;
|
adapter->rx_eitr_param = IXGBE_MAX_RSC_INT_RATE;
|
||||||
else
|
else
|
||||||
adapter->eitr_param = IXGBE_MAX_INT_RATE;
|
adapter->rx_eitr_param = IXGBE_MAX_INT_RATE;
|
||||||
adapter->itr_setting = 0;
|
adapter->rx_itr_setting = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ec->tx_coalesce_usecs > 1) {
|
||||||
|
/* check the limits */
|
||||||
|
if ((1000000/ec->tx_coalesce_usecs > IXGBE_MAX_INT_RATE) ||
|
||||||
|
(1000000/ec->tx_coalesce_usecs < IXGBE_MIN_INT_RATE))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* store the value in ints/second */
|
||||||
|
adapter->tx_eitr_param = 1000000/ec->tx_coalesce_usecs;
|
||||||
|
|
||||||
|
/* static value of interrupt rate */
|
||||||
|
adapter->tx_itr_setting = adapter->tx_eitr_param;
|
||||||
|
|
||||||
|
/* clear the lower bit as its used for dynamic state */
|
||||||
|
adapter->tx_itr_setting &= ~1;
|
||||||
|
} else if (ec->tx_coalesce_usecs == 1) {
|
||||||
|
/* 1 means dynamic mode */
|
||||||
|
adapter->tx_eitr_param = 10000;
|
||||||
|
adapter->tx_itr_setting = 1;
|
||||||
|
} else {
|
||||||
|
adapter->tx_eitr_param = IXGBE_MAX_INT_RATE;
|
||||||
|
adapter->tx_itr_setting = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MSI/MSIx Interrupt Mode */
|
/* MSI/MSIx Interrupt Mode */
|
||||||
|
@ -1992,17 +2039,17 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
|
||||||
for (i = 0; i < num_vectors; i++) {
|
for (i = 0; i < num_vectors; i++) {
|
||||||
q_vector = adapter->q_vector[i];
|
q_vector = adapter->q_vector[i];
|
||||||
if (q_vector->txr_count && !q_vector->rxr_count)
|
if (q_vector->txr_count && !q_vector->rxr_count)
|
||||||
/* tx vector gets half the rate */
|
/* tx only */
|
||||||
q_vector->eitr = (adapter->eitr_param >> 1);
|
q_vector->eitr = adapter->tx_eitr_param;
|
||||||
else
|
else
|
||||||
/* rx only or mixed */
|
/* rx only or mixed */
|
||||||
q_vector->eitr = adapter->eitr_param;
|
q_vector->eitr = adapter->rx_eitr_param;
|
||||||
ixgbe_write_eitr(q_vector);
|
ixgbe_write_eitr(q_vector);
|
||||||
}
|
}
|
||||||
/* Legacy Interrupt Mode */
|
/* Legacy Interrupt Mode */
|
||||||
} else {
|
} else {
|
||||||
q_vector = adapter->q_vector[0];
|
q_vector = adapter->q_vector[0];
|
||||||
q_vector->eitr = adapter->eitr_param;
|
q_vector->eitr = adapter->rx_eitr_param;
|
||||||
ixgbe_write_eitr(q_vector);
|
ixgbe_write_eitr(q_vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -926,12 +926,12 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
|
||||||
r_idx + 1);
|
r_idx + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if this is a tx only vector halve the interrupt rate */
|
|
||||||
if (q_vector->txr_count && !q_vector->rxr_count)
|
if (q_vector->txr_count && !q_vector->rxr_count)
|
||||||
q_vector->eitr = (adapter->eitr_param >> 1);
|
/* tx only */
|
||||||
|
q_vector->eitr = adapter->tx_eitr_param;
|
||||||
else if (q_vector->rxr_count)
|
else if (q_vector->rxr_count)
|
||||||
/* rx only */
|
/* rx or mixed */
|
||||||
q_vector->eitr = adapter->eitr_param;
|
q_vector->eitr = adapter->rx_eitr_param;
|
||||||
|
|
||||||
ixgbe_write_eitr(q_vector);
|
ixgbe_write_eitr(q_vector);
|
||||||
}
|
}
|
||||||
|
@ -1359,7 +1359,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
|
||||||
/* If all Rx work done, exit the polling mode */
|
/* If all Rx work done, exit the polling mode */
|
||||||
if (work_done < budget) {
|
if (work_done < budget) {
|
||||||
napi_complete(napi);
|
napi_complete(napi);
|
||||||
if (adapter->itr_setting & 1)
|
if (adapter->rx_itr_setting & 1)
|
||||||
ixgbe_set_itr_msix(q_vector);
|
ixgbe_set_itr_msix(q_vector);
|
||||||
if (!test_bit(__IXGBE_DOWN, &adapter->state))
|
if (!test_bit(__IXGBE_DOWN, &adapter->state))
|
||||||
ixgbe_irq_enable_queues(adapter,
|
ixgbe_irq_enable_queues(adapter,
|
||||||
|
@ -1420,7 +1420,7 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
|
||||||
/* If all Rx work done, exit the polling mode */
|
/* If all Rx work done, exit the polling mode */
|
||||||
if (work_done < budget) {
|
if (work_done < budget) {
|
||||||
napi_complete(napi);
|
napi_complete(napi);
|
||||||
if (adapter->itr_setting & 1)
|
if (adapter->rx_itr_setting & 1)
|
||||||
ixgbe_set_itr_msix(q_vector);
|
ixgbe_set_itr_msix(q_vector);
|
||||||
if (!test_bit(__IXGBE_DOWN, &adapter->state))
|
if (!test_bit(__IXGBE_DOWN, &adapter->state))
|
||||||
ixgbe_irq_enable_queues(adapter,
|
ixgbe_irq_enable_queues(adapter,
|
||||||
|
@ -1458,10 +1458,10 @@ static int ixgbe_clean_txonly(struct napi_struct *napi, int budget)
|
||||||
if (!ixgbe_clean_tx_irq(q_vector, tx_ring))
|
if (!ixgbe_clean_tx_irq(q_vector, tx_ring))
|
||||||
work_done = budget;
|
work_done = budget;
|
||||||
|
|
||||||
/* If all Rx work done, exit the polling mode */
|
/* If all Tx work done, exit the polling mode */
|
||||||
if (work_done < budget) {
|
if (work_done < budget) {
|
||||||
napi_complete(napi);
|
napi_complete(napi);
|
||||||
if (adapter->itr_setting & 1)
|
if (adapter->tx_itr_setting & 1)
|
||||||
ixgbe_set_itr_msix(q_vector);
|
ixgbe_set_itr_msix(q_vector);
|
||||||
if (!test_bit(__IXGBE_DOWN, &adapter->state))
|
if (!test_bit(__IXGBE_DOWN, &adapter->state))
|
||||||
ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx));
|
ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx));
|
||||||
|
@ -1848,7 +1848,7 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
|
||||||
struct ixgbe_hw *hw = &adapter->hw;
|
struct ixgbe_hw *hw = &adapter->hw;
|
||||||
|
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_EITR(0),
|
IXGBE_WRITE_REG(hw, IXGBE_EITR(0),
|
||||||
EITR_INTS_PER_SEC_TO_REG(adapter->eitr_param));
|
EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr_param));
|
||||||
|
|
||||||
ixgbe_set_ivar(adapter, 0, 0, 0);
|
ixgbe_set_ivar(adapter, 0, 0, 0);
|
||||||
ixgbe_set_ivar(adapter, 1, 0, 0);
|
ixgbe_set_ivar(adapter, 1, 0, 0);
|
||||||
|
@ -2991,7 +2991,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget)
|
||||||
/* If budget not fully consumed, exit the polling mode */
|
/* If budget not fully consumed, exit the polling mode */
|
||||||
if (work_done < budget) {
|
if (work_done < budget) {
|
||||||
napi_complete(napi);
|
napi_complete(napi);
|
||||||
if (adapter->itr_setting & 1)
|
if (adapter->rx_itr_setting & 1)
|
||||||
ixgbe_set_itr(adapter);
|
ixgbe_set_itr(adapter);
|
||||||
if (!test_bit(__IXGBE_DOWN, &adapter->state))
|
if (!test_bit(__IXGBE_DOWN, &adapter->state))
|
||||||
ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE);
|
ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE);
|
||||||
|
@ -3601,7 +3601,10 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
|
||||||
if (!q_vector)
|
if (!q_vector)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
q_vector->adapter = adapter;
|
q_vector->adapter = adapter;
|
||||||
q_vector->eitr = adapter->eitr_param;
|
if (q_vector->txr_count && !q_vector->rxr_count)
|
||||||
|
q_vector->eitr = adapter->tx_eitr_param;
|
||||||
|
else
|
||||||
|
q_vector->eitr = adapter->rx_eitr_param;
|
||||||
q_vector->v_idx = q_idx;
|
q_vector->v_idx = q_idx;
|
||||||
netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64);
|
netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64);
|
||||||
adapter->q_vector[q_idx] = q_vector;
|
adapter->q_vector[q_idx] = q_vector;
|
||||||
|
@ -3870,8 +3873,10 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
|
||||||
hw->fc.disable_fc_autoneg = false;
|
hw->fc.disable_fc_autoneg = false;
|
||||||
|
|
||||||
/* enable itr by default in dynamic mode */
|
/* enable itr by default in dynamic mode */
|
||||||
adapter->itr_setting = 1;
|
adapter->rx_itr_setting = 1;
|
||||||
adapter->eitr_param = 20000;
|
adapter->rx_eitr_param = 20000;
|
||||||
|
adapter->tx_itr_setting = 1;
|
||||||
|
adapter->tx_eitr_param = 10000;
|
||||||
|
|
||||||
/* set defaults for eitr in MegaBytes */
|
/* set defaults for eitr in MegaBytes */
|
||||||
adapter->eitr_low = 10;
|
adapter->eitr_low = 10;
|
||||||
|
|
Reference in a new issue