Commit 30efa5a3 authored by Jesse Brandeburg's avatar Jesse Brandeburg Committed by Jeff Garzik

ixgbe: fix initial interrupt throttle settings

ixgbe was incorrectly setting the throttle rate setting for all tx
queues and the driver has been refreshed to better handle a dynamic
interrupt mode as well as multiple queues.
Signed-off-by: default avatarJesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent 3d3d6d3c
...@@ -62,11 +62,6 @@ ...@@ -62,11 +62,6 @@
#define IXGBE_MAX_RXQ 1 #define IXGBE_MAX_RXQ 1
#define IXGBE_MIN_RXQ 1 #define IXGBE_MIN_RXQ 1
#define IXGBE_DEFAULT_ITR_RX_USECS 125 /* 8k irqs/sec */
#define IXGBE_DEFAULT_ITR_TX_USECS 250 /* 4k irqs/sec */
#define IXGBE_MIN_ITR_USECS 100 /* 500k irqs/sec */
#define IXGBE_MAX_ITR_USECS 10000 /* 100 irqs/sec */
/* flow control */ /* flow control */
#define IXGBE_DEFAULT_FCRTL 0x10000 #define IXGBE_DEFAULT_FCRTL 0x10000
#define IXGBE_MIN_FCRTL 0x40 #define IXGBE_MIN_FCRTL 0x40
...@@ -161,10 +156,7 @@ struct ixgbe_ring { ...@@ -161,10 +156,7 @@ struct ixgbe_ring {
* vector array, can also be used for finding the bit in EICR * vector array, can also be used for finding the bit in EICR
* and friends that represents the vector for this ring */ * and friends that represents the vector for this ring */
u32 eims_value;
u16 itr_register;
char name[IFNAMSIZ + 5];
u16 work_limit; /* max work per interrupt */ u16 work_limit; /* max work per interrupt */
u16 rx_buf_len; u16 rx_buf_len;
}; };
...@@ -191,8 +183,8 @@ struct ixgbe_q_vector { ...@@ -191,8 +183,8 @@ struct ixgbe_q_vector {
DECLARE_BITMAP(txr_idx, MAX_TX_QUEUES); /* Tx ring indices */ DECLARE_BITMAP(txr_idx, MAX_TX_QUEUES); /* Tx ring indices */
u8 rxr_count; /* Rx ring count assigned to this vector */ u8 rxr_count; /* Rx ring count assigned to this vector */
u8 txr_count; /* Tx ring count assigned to this vector */ u8 txr_count; /* Tx ring count assigned to this vector */
u8 tx_eitr; u8 tx_itr;
u8 rx_eitr; u8 rx_itr;
u32 eitr; u32 eitr;
}; };
...@@ -240,7 +232,9 @@ struct ixgbe_adapter { ...@@ -240,7 +232,9 @@ struct ixgbe_adapter {
/* TX */ /* TX */
struct ixgbe_ring *tx_ring; /* One per active queue */ struct ixgbe_ring *tx_ring; /* One per active queue */
int num_tx_queues;
u64 restart_queue; u64 restart_queue;
u64 hw_csum_tx_good;
u64 lsc_int; u64 lsc_int;
u64 hw_tso_ctxt; u64 hw_tso_ctxt;
u64 hw_tso6_ctxt; u64 hw_tso6_ctxt;
...@@ -249,12 +243,10 @@ struct ixgbe_adapter { ...@@ -249,12 +243,10 @@ struct ixgbe_adapter {
/* RX */ /* RX */
struct ixgbe_ring *rx_ring; /* One per active queue */ struct ixgbe_ring *rx_ring; /* One per active queue */
u64 hw_csum_tx_good; int num_rx_queues;
u64 hw_csum_rx_error; u64 hw_csum_rx_error;
u64 hw_csum_rx_good; u64 hw_csum_rx_good;
u64 non_eop_descs; u64 non_eop_descs;
int num_tx_queues;
int num_rx_queues;
int num_msix_vectors; int num_msix_vectors;
struct ixgbe_ring_feature ring_feature[3]; struct ixgbe_ring_feature ring_feature[3];
struct msix_entry *msix_entries; struct msix_entry *msix_entries;
...@@ -301,14 +293,15 @@ struct ixgbe_adapter { ...@@ -301,14 +293,15 @@ struct ixgbe_adapter {
struct ixgbe_hw_stats stats; struct ixgbe_hw_stats stats;
/* Interrupt Throttle Rate */ /* Interrupt Throttle Rate */
u32 rx_eitr; u32 eitr_param;
u32 tx_eitr;
unsigned long state; unsigned long state;
u64 tx_busy; u64 tx_busy;
u64 lro_aggregated; u64 lro_aggregated;
u64 lro_flushed; u64 lro_flushed;
u64 lro_no_desc; u64 lro_no_desc;
unsigned int tx_ring_count;
unsigned int rx_ring_count;
u32 link_speed; u32 link_speed;
bool link_up; bool link_up;
......
...@@ -880,17 +880,23 @@ static int ixgbe_get_coalesce(struct net_device *netdev, ...@@ -880,17 +880,23 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
{ {
struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_adapter *adapter = netdev_priv(netdev);
if (adapter->rx_eitr < IXGBE_MIN_ITR_USECS)
ec->rx_coalesce_usecs = adapter->rx_eitr;
else
ec->rx_coalesce_usecs = 1000000 / adapter->rx_eitr;
if (adapter->tx_eitr < IXGBE_MIN_ITR_USECS)
ec->tx_coalesce_usecs = adapter->tx_eitr;
else
ec->tx_coalesce_usecs = 1000000 / adapter->tx_eitr;
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 */
switch (adapter->itr_setting) {
case 0:
/* throttling disabled */
ec->rx_coalesce_usecs = 0;
break;
case 1:
/* dynamic ITR mode */
ec->rx_coalesce_usecs = 1;
break;
default:
/* fixed interrupt rate mode */
ec->rx_coalesce_usecs = 1000000/adapter->eitr_param;
break;
}
return 0; return 0;
} }
...@@ -898,38 +904,40 @@ static int ixgbe_set_coalesce(struct net_device *netdev, ...@@ -898,38 +904,40 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec) struct ethtool_coalesce *ec)
{ {
struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
if ((ec->rx_coalesce_usecs > IXGBE_MAX_ITR_USECS) || int i;
((ec->rx_coalesce_usecs != 0) &&
(ec->rx_coalesce_usecs != 1) &&
(ec->rx_coalesce_usecs != 3) &&
(ec->rx_coalesce_usecs < IXGBE_MIN_ITR_USECS)))
return -EINVAL;
if ((ec->tx_coalesce_usecs > IXGBE_MAX_ITR_USECS) ||
((ec->tx_coalesce_usecs != 0) &&
(ec->tx_coalesce_usecs != 1) &&
(ec->tx_coalesce_usecs != 3) &&
(ec->tx_coalesce_usecs < IXGBE_MIN_ITR_USECS)))
return -EINVAL;
/* convert to rate of irq's per second */
if (ec->rx_coalesce_usecs < IXGBE_MIN_ITR_USECS)
adapter->rx_eitr = ec->rx_coalesce_usecs;
else
adapter->rx_eitr = (1000000 / ec->rx_coalesce_usecs);
if (ec->tx_coalesce_usecs < IXGBE_MIN_ITR_USECS)
adapter->tx_eitr = ec->rx_coalesce_usecs;
else
adapter->tx_eitr = (1000000 / ec->tx_coalesce_usecs);
if (ec->tx_max_coalesced_frames_irq) if (ec->tx_max_coalesced_frames_irq)
adapter->tx_ring[0].work_limit = adapter->tx_ring[0].work_limit = ec->tx_max_coalesced_frames_irq;
ec->tx_max_coalesced_frames_irq;
if (ec->rx_coalesce_usecs > 1) {
/* store the value in ints/second */
adapter->eitr_param = 1000000/ec->rx_coalesce_usecs;
/* static value of interrupt rate */
adapter->itr_setting = adapter->eitr_param;
/* clear the lower bit */
adapter->itr_setting &= ~1;
} else if (ec->rx_coalesce_usecs == 1) {
/* 1 means dynamic mode */
adapter->eitr_param = 20000;
adapter->itr_setting = 1;
} else {
/* any other value means disable eitr, which is best
* served by setting the interrupt rate very high */
adapter->eitr_param = 3000000;
adapter->itr_setting = 0;
}
if (netif_running(netdev)) { for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) {
ixgbe_down(adapter); struct ixgbe_q_vector *q_vector = &adapter->q_vector[i];
ixgbe_up(adapter); if (q_vector->txr_count && !q_vector->rxr_count)
q_vector->eitr = (adapter->eitr_param >> 1);
else
/* rx only or mixed */
q_vector->eitr = adapter->eitr_param;
IXGBE_WRITE_REG(hw, IXGBE_EITR(i),
EITR_INTS_PER_SEC_TO_REG(q_vector->eitr));
} }
return 0; return 0;
......
...@@ -744,12 +744,12 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) ...@@ -744,12 +744,12 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
r_idx + 1); r_idx + 1);
} }
/* if this is a tx only vector use half the irq (tx) rate */ /* 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->tx_eitr; q_vector->eitr = (adapter->eitr_param >> 1);
else else
/* rx only or mixed */ /* rx only */
q_vector->eitr = adapter->rx_eitr; q_vector->eitr = adapter->eitr_param;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx), IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx),
EITR_INTS_PER_SEC_TO_REG(q_vector->eitr)); EITR_INTS_PER_SEC_TO_REG(q_vector->eitr));
...@@ -845,13 +845,13 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) ...@@ -845,13 +845,13 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
for (i = 0; i < q_vector->txr_count; i++) { for (i = 0; i < q_vector->txr_count; i++) {
tx_ring = &(adapter->tx_ring[r_idx]); tx_ring = &(adapter->tx_ring[r_idx]);
ret_itr = ixgbe_update_itr(adapter, q_vector->eitr, ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
q_vector->tx_eitr, q_vector->tx_itr,
tx_ring->total_packets, tx_ring->total_packets,
tx_ring->total_bytes); tx_ring->total_bytes);
/* if the result for this queue would decrease interrupt /* if the result for this queue would decrease interrupt
* rate for this vector then use that result */ * rate for this vector then use that result */
q_vector->tx_eitr = ((q_vector->tx_eitr > ret_itr) ? q_vector->tx_itr = ((q_vector->tx_itr > ret_itr) ?
q_vector->tx_eitr - 1 : ret_itr); q_vector->tx_itr - 1 : ret_itr);
r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
r_idx + 1); r_idx + 1);
} }
...@@ -860,18 +860,18 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) ...@@ -860,18 +860,18 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
for (i = 0; i < q_vector->rxr_count; i++) { for (i = 0; i < q_vector->rxr_count; i++) {
rx_ring = &(adapter->rx_ring[r_idx]); rx_ring = &(adapter->rx_ring[r_idx]);
ret_itr = ixgbe_update_itr(adapter, q_vector->eitr, ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
q_vector->rx_eitr, q_vector->rx_itr,
rx_ring->total_packets, rx_ring->total_packets,
rx_ring->total_bytes); rx_ring->total_bytes);
/* if the result for this queue would decrease interrupt /* if the result for this queue would decrease interrupt
* rate for this vector then use that result */ * rate for this vector then use that result */
q_vector->rx_eitr = ((q_vector->rx_eitr > ret_itr) ? q_vector->rx_itr = ((q_vector->rx_itr > ret_itr) ?
q_vector->rx_eitr - 1 : ret_itr); q_vector->rx_itr - 1 : ret_itr);
r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
r_idx + 1); r_idx + 1);
} }
current_itr = max(q_vector->rx_eitr, q_vector->tx_eitr); current_itr = max(q_vector->rx_itr, q_vector->tx_itr);
switch (current_itr) { switch (current_itr) {
/* counts and packets in update_itr are dependent on these numbers */ /* counts and packets in update_itr are dependent on these numbers */
...@@ -970,16 +970,24 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data) ...@@ -970,16 +970,24 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data)
struct ixgbe_adapter *adapter = q_vector->adapter; struct ixgbe_adapter *adapter = q_vector->adapter;
struct ixgbe_ring *rx_ring; struct ixgbe_ring *rx_ring;
int r_idx; int r_idx;
int i;
r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
for (i = 0; i < q_vector->rxr_count; i++) {
rx_ring = &(adapter->rx_ring[r_idx]);
rx_ring->total_bytes = 0;
rx_ring->total_packets = 0;
r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
r_idx + 1);
}
if (!q_vector->rxr_count) if (!q_vector->rxr_count)
return IRQ_HANDLED; return IRQ_HANDLED;
r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
rx_ring = &(adapter->rx_ring[r_idx]); rx_ring = &(adapter->rx_ring[r_idx]);
/* disable interrupts on this vector only */ /* disable interrupts on this vector only */
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rx_ring->v_idx); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rx_ring->v_idx);
rx_ring->total_bytes = 0;
rx_ring->total_packets = 0;
netif_rx_schedule(adapter->netdev, &q_vector->napi); netif_rx_schedule(adapter->netdev, &q_vector->napi);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -1020,7 +1028,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget) ...@@ -1020,7 +1028,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) {
netif_rx_complete(adapter->netdev, napi); netif_rx_complete(adapter->netdev, napi);
if (adapter->rx_eitr < IXGBE_MIN_ITR_USECS) if (adapter->itr_setting & 3)
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_WRITE_REG(&adapter->hw, IXGBE_EIMS, rx_ring->v_idx); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, rx_ring->v_idx);
...@@ -1187,16 +1195,16 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter) ...@@ -1187,16 +1195,16 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter)
struct ixgbe_ring *rx_ring = &adapter->rx_ring[0]; struct ixgbe_ring *rx_ring = &adapter->rx_ring[0];
struct ixgbe_ring *tx_ring = &adapter->tx_ring[0]; struct ixgbe_ring *tx_ring = &adapter->tx_ring[0];
q_vector->tx_eitr = ixgbe_update_itr(adapter, new_itr, q_vector->tx_itr = ixgbe_update_itr(adapter, new_itr,
q_vector->tx_eitr, q_vector->tx_itr,
tx_ring->total_packets, tx_ring->total_packets,
tx_ring->total_bytes); tx_ring->total_bytes);
q_vector->rx_eitr = ixgbe_update_itr(adapter, new_itr, q_vector->rx_itr = ixgbe_update_itr(adapter, new_itr,
q_vector->rx_eitr, q_vector->rx_itr,
rx_ring->total_packets, rx_ring->total_packets,
rx_ring->total_bytes); rx_ring->total_bytes);
current_itr = max(q_vector->rx_eitr, q_vector->tx_eitr); current_itr = max(q_vector->rx_itr, q_vector->tx_itr);
switch (current_itr) { switch (current_itr) {
/* counts and packets in update_itr are dependent on these numbers */ /* counts and packets in update_itr are dependent on these numbers */
...@@ -1371,7 +1379,7 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter) ...@@ -1371,7 +1379,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->rx_eitr)); EITR_INTS_PER_SEC_TO_REG(adapter->eitr_param));
ixgbe_set_ivar(adapter, IXGBE_IVAR_RX_QUEUE(0), 0); ixgbe_set_ivar(adapter, IXGBE_IVAR_RX_QUEUE(0), 0);
ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(0), 0); ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(0), 0);
...@@ -2209,7 +2217,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) ...@@ -2209,7 +2217,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) {
netif_rx_complete(adapter->netdev, napi); netif_rx_complete(adapter->netdev, napi);
if (adapter->rx_eitr < IXGBE_MIN_ITR_USECS) if (adapter->itr_setting & 3)
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(adapter); ixgbe_irq_enable(adapter);
...@@ -2420,12 +2428,6 @@ static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter ...@@ -2420,12 +2428,6 @@ static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter
int err = 0; int err = 0;
int vector, v_budget; int vector, v_budget;
/*
* Set the default interrupt throttle rate.
*/
adapter->rx_eitr = (1000000 / IXGBE_DEFAULT_ITR_RX_USECS);
adapter->tx_eitr = (1000000 / IXGBE_DEFAULT_ITR_TX_USECS);
/* /*
* It's easy to be greedy for MSI-X vectors, but it really * It's easy to be greedy for MSI-X vectors, but it really
* doesn't do us much good if we have a lot more vectors * doesn't do us much good if we have a lot more vectors
...@@ -2567,10 +2569,6 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) ...@@ -2567,10 +2569,6 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
adapter->ring_feature[RING_F_RSS].indices = rss; adapter->ring_feature[RING_F_RSS].indices = rss;
adapter->flags |= IXGBE_FLAG_RSS_ENABLED; adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
/* Enable Dynamic interrupt throttling by default */
adapter->rx_eitr = 1;
adapter->tx_eitr = 1;
/* default flow control settings */ /* default flow control settings */
hw->fc.original_type = ixgbe_fc_none; hw->fc.original_type = ixgbe_fc_none;
hw->fc.type = ixgbe_fc_none; hw->fc.type = ixgbe_fc_none;
...@@ -2591,6 +2589,18 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) ...@@ -2591,6 +2589,18 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
return -EIO; return -EIO;
} }
/* enable itr by default in dynamic mode */
adapter->itr_setting = 1;
adapter->eitr_param = 20000;
/* set defaults for eitr in MegaBytes */
adapter->eitr_low = 10;
adapter->eitr_high = 20;
/* set default ring sizes */
adapter->tx_ring_count = IXGBE_DEFAULT_TXD;
adapter->rx_ring_count = IXGBE_DEFAULT_RXD;
/* initialize eeprom parameters */ /* initialize eeprom parameters */
if (ixgbe_init_eeprom(hw)) { if (ixgbe_init_eeprom(hw)) {
dev_err(&pdev->dev, "EEPROM initialization failed\n"); dev_err(&pdev->dev, "EEPROM initialization failed\n");
......
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