ixgbe: move v_idx into q_vector and use as index only
The v_idx value was being used as both a bitmask and an index. This change makes it so that the q_vector contains the index and allows for much of the code to be simplified since disabling a q_vector involves only clearing one bit in the interrupt bitmask. Signed-off-by: Alexander Duyck <alexander.h.duyck@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
21fa4e66bd
commit
fe49f04aa8
3 changed files with 117 additions and 126 deletions
|
@ -148,10 +148,6 @@ struct ixgbe_ring {
|
||||||
int cpu;
|
int cpu;
|
||||||
#endif
|
#endif
|
||||||
struct ixgbe_queue_stats stats;
|
struct ixgbe_queue_stats stats;
|
||||||
u64 v_idx; /* maps directly to the index for this ring in the hardware
|
|
||||||
* vector array, can also be used for finding the bit in EICR
|
|
||||||
* and friends that represents the vector for this ring */
|
|
||||||
|
|
||||||
|
|
||||||
u16 work_limit; /* max work per interrupt */
|
u16 work_limit; /* max work per interrupt */
|
||||||
u16 rx_buf_len;
|
u16 rx_buf_len;
|
||||||
|
@ -193,6 +189,9 @@ struct ixgbe_ring_feature {
|
||||||
*/
|
*/
|
||||||
struct ixgbe_q_vector {
|
struct ixgbe_q_vector {
|
||||||
struct ixgbe_adapter *adapter;
|
struct ixgbe_adapter *adapter;
|
||||||
|
unsigned int v_idx; /* index of q_vector within array, also used for
|
||||||
|
* finding the bit in EICR and friends that
|
||||||
|
* represents the vector for this ring */
|
||||||
struct napi_struct napi;
|
struct napi_struct napi;
|
||||||
DECLARE_BITMAP(rxr_idx, MAX_RX_QUEUES); /* Rx ring indices */
|
DECLARE_BITMAP(rxr_idx, MAX_RX_QUEUES); /* Rx ring indices */
|
||||||
DECLARE_BITMAP(txr_idx, MAX_TX_QUEUES); /* Tx ring indices */
|
DECLARE_BITMAP(txr_idx, MAX_TX_QUEUES); /* Tx ring indices */
|
||||||
|
@ -201,7 +200,6 @@ struct ixgbe_q_vector {
|
||||||
u8 tx_itr;
|
u8 tx_itr;
|
||||||
u8 rx_itr;
|
u8 rx_itr;
|
||||||
u32 eitr;
|
u32 eitr;
|
||||||
u32 v_idx; /* vector index in list */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Helper macros to switch between ints/sec and what the register uses.
|
/* Helper macros to switch between ints/sec and what the register uses.
|
||||||
|
@ -401,7 +399,8 @@ extern void ixgbe_free_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *)
|
||||||
extern void ixgbe_update_stats(struct ixgbe_adapter *adapter);
|
extern void ixgbe_update_stats(struct ixgbe_adapter *adapter);
|
||||||
extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter);
|
extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter);
|
||||||
extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter);
|
extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter);
|
||||||
extern void ixgbe_write_eitr(struct ixgbe_adapter *, int, u32);
|
extern void ixgbe_write_eitr(struct ixgbe_q_vector *);
|
||||||
|
extern int ethtool_ioctl(struct ifreq *ifr);
|
||||||
#ifdef IXGBE_FCOE
|
#ifdef IXGBE_FCOE
|
||||||
extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter);
|
extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter);
|
||||||
extern int ixgbe_fso(struct ixgbe_adapter *adapter,
|
extern int ixgbe_fso(struct ixgbe_adapter *adapter,
|
||||||
|
|
|
@ -840,7 +840,6 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
|
||||||
}
|
}
|
||||||
goto err_setup;
|
goto err_setup;
|
||||||
}
|
}
|
||||||
temp_tx_ring[i].v_idx = adapter->tx_ring[i].v_idx;
|
|
||||||
}
|
}
|
||||||
need_update = true;
|
need_update = true;
|
||||||
}
|
}
|
||||||
|
@ -870,7 +869,6 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
|
||||||
}
|
}
|
||||||
goto err_setup;
|
goto err_setup;
|
||||||
}
|
}
|
||||||
temp_rx_ring[i].v_idx = adapter->rx_ring[i].v_idx;
|
|
||||||
}
|
}
|
||||||
need_update = true;
|
need_update = true;
|
||||||
}
|
}
|
||||||
|
@ -1987,8 +1985,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
|
||||||
else
|
else
|
||||||
/* rx only or mixed */
|
/* rx only or mixed */
|
||||||
q_vector->eitr = adapter->eitr_param;
|
q_vector->eitr = adapter->eitr_param;
|
||||||
ixgbe_write_eitr(adapter, i,
|
ixgbe_write_eitr(q_vector);
|
||||||
EITR_INTS_PER_SEC_TO_REG(q_vector->eitr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -186,6 +186,22 @@ static void ixgbe_set_ivar(struct ixgbe_adapter *adapter, s8 direction,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void ixgbe_irq_rearm_queues(struct ixgbe_adapter *adapter,
|
||||||
|
u64 qmask)
|
||||||
|
{
|
||||||
|
u32 mask;
|
||||||
|
|
||||||
|
if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
|
||||||
|
mask = (IXGBE_EIMS_RTX_QUEUE & qmask);
|
||||||
|
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask);
|
||||||
|
} else {
|
||||||
|
mask = (qmask & 0xFFFFFFFF);
|
||||||
|
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0), mask);
|
||||||
|
mask = (qmask >> 32);
|
||||||
|
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(1), mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter,
|
static void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter,
|
||||||
struct ixgbe_tx_buffer
|
struct ixgbe_tx_buffer
|
||||||
*tx_buffer_info)
|
*tx_buffer_info)
|
||||||
|
@ -248,14 +264,13 @@ static void ixgbe_tx_timeout(struct net_device *netdev);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ixgbe_clean_tx_irq - Reclaim resources after transmit completes
|
* ixgbe_clean_tx_irq - Reclaim resources after transmit completes
|
||||||
* @adapter: board private structure
|
* @q_vector: structure containing interrupt and ring information
|
||||||
* @tx_ring: tx ring to clean
|
* @tx_ring: tx ring to clean
|
||||||
*
|
|
||||||
* returns true if transmit work is done
|
|
||||||
**/
|
**/
|
||||||
static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter,
|
static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
|
||||||
struct ixgbe_ring *tx_ring)
|
struct ixgbe_ring *tx_ring)
|
||||||
{
|
{
|
||||||
|
struct ixgbe_adapter *adapter = q_vector->adapter;
|
||||||
struct net_device *netdev = adapter->netdev;
|
struct net_device *netdev = adapter->netdev;
|
||||||
union ixgbe_adv_tx_desc *tx_desc, *eop_desc;
|
union ixgbe_adv_tx_desc *tx_desc, *eop_desc;
|
||||||
struct ixgbe_tx_buffer *tx_buffer_info;
|
struct ixgbe_tx_buffer *tx_buffer_info;
|
||||||
|
@ -329,18 +344,8 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* re-arm the interrupt */
|
/* re-arm the interrupt */
|
||||||
if (count >= tx_ring->work_limit) {
|
if (count >= tx_ring->work_limit)
|
||||||
if (adapter->hw.mac.type == ixgbe_mac_82598EB)
|
ixgbe_irq_rearm_queues(adapter, ((u64)1 << q_vector->v_idx));
|
||||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS,
|
|
||||||
tx_ring->v_idx);
|
|
||||||
else if (tx_ring->v_idx & 0xFFFFFFFF)
|
|
||||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0),
|
|
||||||
tx_ring->v_idx);
|
|
||||||
else
|
|
||||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(1),
|
|
||||||
(tx_ring->v_idx >> 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
tx_ring->total_bytes += total_bytes;
|
tx_ring->total_bytes += total_bytes;
|
||||||
tx_ring->total_packets += total_packets;
|
tx_ring->total_packets += total_packets;
|
||||||
|
@ -875,12 +880,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
|
||||||
/* rx only */
|
/* rx only */
|
||||||
q_vector->eitr = adapter->eitr_param;
|
q_vector->eitr = adapter->eitr_param;
|
||||||
|
|
||||||
/*
|
ixgbe_write_eitr(q_vector);
|
||||||
* since this is initial set up don't need to call
|
|
||||||
* ixgbe_write_eitr helper
|
|
||||||
*/
|
|
||||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx),
|
|
||||||
EITR_INTS_PER_SEC_TO_REG(q_vector->eitr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adapter->hw.mac.type == ixgbe_mac_82598EB)
|
if (adapter->hw.mac.type == ixgbe_mac_82598EB)
|
||||||
|
@ -965,17 +965,19 @@ static u8 ixgbe_update_itr(struct ixgbe_adapter *adapter,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ixgbe_write_eitr - write EITR register in hardware specific way
|
* ixgbe_write_eitr - write EITR register in hardware specific way
|
||||||
* @adapter: pointer to adapter struct
|
* @q_vector: structure containing interrupt and ring information
|
||||||
* @v_idx: vector index into q_vector array
|
|
||||||
* @itr_reg: new value to be written in *register* format, not ints/s
|
|
||||||
*
|
*
|
||||||
* This function is made to be called by ethtool and by the driver
|
* This function is made to be called by ethtool and by the driver
|
||||||
* when it needs to update EITR registers at runtime. Hardware
|
* when it needs to update EITR registers at runtime. Hardware
|
||||||
* specific quirks/differences are taken care of here.
|
* specific quirks/differences are taken care of here.
|
||||||
*/
|
*/
|
||||||
void ixgbe_write_eitr(struct ixgbe_adapter *adapter, int v_idx, u32 itr_reg)
|
void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector)
|
||||||
{
|
{
|
||||||
|
struct ixgbe_adapter *adapter = q_vector->adapter;
|
||||||
struct ixgbe_hw *hw = &adapter->hw;
|
struct ixgbe_hw *hw = &adapter->hw;
|
||||||
|
int v_idx = q_vector->v_idx;
|
||||||
|
u32 itr_reg = EITR_INTS_PER_SEC_TO_REG(q_vector->eitr);
|
||||||
|
|
||||||
if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
|
if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
|
||||||
/* must write high and low 16 bits to reset counter */
|
/* must write high and low 16 bits to reset counter */
|
||||||
itr_reg |= (itr_reg << 16);
|
itr_reg |= (itr_reg << 16);
|
||||||
|
@ -994,7 +996,7 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
|
||||||
struct ixgbe_adapter *adapter = q_vector->adapter;
|
struct ixgbe_adapter *adapter = q_vector->adapter;
|
||||||
u32 new_itr;
|
u32 new_itr;
|
||||||
u8 current_itr, ret_itr;
|
u8 current_itr, ret_itr;
|
||||||
int i, r_idx, v_idx = q_vector->v_idx;
|
int i, r_idx;
|
||||||
struct ixgbe_ring *rx_ring, *tx_ring;
|
struct ixgbe_ring *rx_ring, *tx_ring;
|
||||||
|
|
||||||
r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
|
r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
|
||||||
|
@ -1044,14 +1046,13 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_itr != q_vector->eitr) {
|
if (new_itr != q_vector->eitr) {
|
||||||
u32 itr_reg;
|
/* do an exponential smoothing */
|
||||||
|
new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100);
|
||||||
|
|
||||||
/* save the algorithm value here, not the smoothed one */
|
/* save the algorithm value here, not the smoothed one */
|
||||||
q_vector->eitr = new_itr;
|
q_vector->eitr = new_itr;
|
||||||
/* do an exponential smoothing */
|
|
||||||
new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100);
|
ixgbe_write_eitr(q_vector);
|
||||||
itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr);
|
|
||||||
ixgbe_write_eitr(adapter, v_idx, itr_reg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -1130,6 +1131,40 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter,
|
||||||
|
u64 qmask)
|
||||||
|
{
|
||||||
|
u32 mask;
|
||||||
|
|
||||||
|
if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
|
||||||
|
mask = (IXGBE_EIMS_RTX_QUEUE & qmask);
|
||||||
|
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
|
||||||
|
} else {
|
||||||
|
mask = (qmask & 0xFFFFFFFF);
|
||||||
|
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(0), mask);
|
||||||
|
mask = (qmask >> 32);
|
||||||
|
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(1), mask);
|
||||||
|
}
|
||||||
|
/* skip the flush */
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter,
|
||||||
|
u64 qmask)
|
||||||
|
{
|
||||||
|
u32 mask;
|
||||||
|
|
||||||
|
if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
|
||||||
|
mask = (IXGBE_EIMS_RTX_QUEUE & qmask);
|
||||||
|
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, mask);
|
||||||
|
} else {
|
||||||
|
mask = (qmask & 0xFFFFFFFF);
|
||||||
|
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), mask);
|
||||||
|
mask = (qmask >> 32);
|
||||||
|
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), mask);
|
||||||
|
}
|
||||||
|
/* skip the flush */
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
|
static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
|
||||||
{
|
{
|
||||||
struct ixgbe_q_vector *q_vector = data;
|
struct ixgbe_q_vector *q_vector = data;
|
||||||
|
@ -1149,7 +1184,7 @@ static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
|
||||||
#endif
|
#endif
|
||||||
tx_ring->total_bytes = 0;
|
tx_ring->total_bytes = 0;
|
||||||
tx_ring->total_packets = 0;
|
tx_ring->total_packets = 0;
|
||||||
ixgbe_clean_tx_irq(adapter, tx_ring);
|
ixgbe_clean_tx_irq(q_vector, tx_ring);
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -1185,13 +1220,7 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data)
|
||||||
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);
|
||||||
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 */
|
||||||
if (adapter->hw.mac.type == ixgbe_mac_82598EB)
|
ixgbe_irq_disable_queues(adapter, ((u64)1 << q_vector->v_idx));
|
||||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rx_ring->v_idx);
|
|
||||||
else if (rx_ring->v_idx & 0xFFFFFFFF)
|
|
||||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), rx_ring->v_idx);
|
|
||||||
else
|
|
||||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1),
|
|
||||||
(rx_ring->v_idx >> 32));
|
|
||||||
napi_schedule(&q_vector->napi);
|
napi_schedule(&q_vector->napi);
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
|
@ -1205,23 +1234,6 @@ static irqreturn_t ixgbe_msix_clean_many(int irq, void *data)
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter,
|
|
||||||
u64 qmask)
|
|
||||||
{
|
|
||||||
u32 mask;
|
|
||||||
|
|
||||||
if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
|
|
||||||
mask = (IXGBE_EIMS_RTX_QUEUE & qmask);
|
|
||||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
|
|
||||||
} else {
|
|
||||||
mask = (qmask & 0xFFFFFFFF);
|
|
||||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(0), mask);
|
|
||||||
mask = (qmask >> 32);
|
|
||||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(1), mask);
|
|
||||||
}
|
|
||||||
/* skip the flush */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ixgbe_clean_rxonly - msix (aka one shot) rx clean routine
|
* ixgbe_clean_rxonly - msix (aka one shot) rx clean routine
|
||||||
* @napi: napi struct with our devices info in it
|
* @napi: napi struct with our devices info in it
|
||||||
|
@ -1254,7 +1266,8 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
|
||||||
if (adapter->itr_setting & 1)
|
if (adapter->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, rx_ring->v_idx);
|
ixgbe_irq_enable_queues(adapter,
|
||||||
|
((u64)1 << q_vector->v_idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
return work_done;
|
return work_done;
|
||||||
|
@ -1276,7 +1289,6 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget)
|
||||||
struct ixgbe_ring *rx_ring = NULL;
|
struct ixgbe_ring *rx_ring = NULL;
|
||||||
int work_done = 0, i;
|
int work_done = 0, i;
|
||||||
long r_idx;
|
long r_idx;
|
||||||
u64 enable_mask = 0;
|
|
||||||
|
|
||||||
/* attempt to distribute budget to each queue fairly, but don't allow
|
/* attempt to distribute budget to each queue fairly, but don't allow
|
||||||
* the budget to go below 1 because we'll exit polling */
|
* the budget to go below 1 because we'll exit polling */
|
||||||
|
@ -1290,7 +1302,6 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget)
|
||||||
ixgbe_update_rx_dca(adapter, rx_ring);
|
ixgbe_update_rx_dca(adapter, rx_ring);
|
||||||
#endif
|
#endif
|
||||||
ixgbe_clean_rx_irq(q_vector, rx_ring, &work_done, budget);
|
ixgbe_clean_rx_irq(q_vector, rx_ring, &work_done, budget);
|
||||||
enable_mask |= rx_ring->v_idx;
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -1303,7 +1314,8 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget)
|
||||||
if (adapter->itr_setting & 1)
|
if (adapter->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, enable_mask);
|
ixgbe_irq_enable_queues(adapter,
|
||||||
|
((u64)1 << q_vector->v_idx));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1316,7 +1328,6 @@ static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx,
|
||||||
|
|
||||||
set_bit(r_idx, q_vector->rxr_idx);
|
set_bit(r_idx, q_vector->rxr_idx);
|
||||||
q_vector->rxr_count++;
|
q_vector->rxr_count++;
|
||||||
a->rx_ring[r_idx].v_idx = (u64)1 << v_idx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
|
static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
|
||||||
|
@ -1326,7 +1337,6 @@ static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
|
||||||
|
|
||||||
set_bit(t_idx, q_vector->txr_idx);
|
set_bit(t_idx, q_vector->txr_idx);
|
||||||
q_vector->txr_count++;
|
q_vector->txr_count++;
|
||||||
a->tx_ring[t_idx].v_idx = (u64)1 << v_idx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1505,14 +1515,13 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_itr != q_vector->eitr) {
|
if (new_itr != q_vector->eitr) {
|
||||||
u32 itr_reg;
|
/* do an exponential smoothing */
|
||||||
|
new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100);
|
||||||
|
|
||||||
/* save the algorithm value here, not the smoothed one */
|
/* save the algorithm value here, not the smoothed one */
|
||||||
q_vector->eitr = new_itr;
|
q_vector->eitr = new_itr;
|
||||||
/* do an exponential smoothing */
|
|
||||||
new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100);
|
ixgbe_write_eitr(q_vector);
|
||||||
itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr);
|
|
||||||
ixgbe_write_eitr(adapter, 0, itr_reg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -2805,7 +2814,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tx_clean_complete = ixgbe_clean_tx_irq(adapter, adapter->tx_ring);
|
tx_clean_complete = ixgbe_clean_tx_irq(q_vector, adapter->tx_ring);
|
||||||
ixgbe_clean_rx_irq(q_vector, adapter->rx_ring, &work_done, budget);
|
ixgbe_clean_rx_irq(q_vector, adapter->rx_ring, &work_done, budget);
|
||||||
|
|
||||||
if (!tx_clean_complete)
|
if (!tx_clean_complete)
|
||||||
|
@ -3324,8 +3333,8 @@ 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->v_idx = q_idx;
|
|
||||||
q_vector->eitr = adapter->eitr_param;
|
q_vector->eitr = adapter->eitr_param;
|
||||||
|
q_vector->v_idx = q_idx;
|
||||||
if (q_idx < napi_vectors)
|
if (q_idx < napi_vectors)
|
||||||
netif_napi_add(adapter->netdev, &q_vector->napi,
|
netif_napi_add(adapter->netdev, &q_vector->napi,
|
||||||
(*poll), 64);
|
(*poll), 64);
|
||||||
|
@ -4216,57 +4225,43 @@ static void ixgbe_watchdog(unsigned long data)
|
||||||
{
|
{
|
||||||
struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data;
|
struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data;
|
||||||
struct ixgbe_hw *hw = &adapter->hw;
|
struct ixgbe_hw *hw = &adapter->hw;
|
||||||
|
u64 eics = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
/* Do the watchdog outside of interrupt context due to the lovely
|
/*
|
||||||
* delays that some of the newer hardware requires */
|
* Do the watchdog outside of interrupt context due to the lovely
|
||||||
if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
|
* delays that some of the newer hardware requires
|
||||||
u64 eics = 0;
|
*/
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++)
|
if (test_bit(__IXGBE_DOWN, &adapter->state))
|
||||||
eics |= ((u64)1 << i);
|
goto watchdog_short_circuit;
|
||||||
|
|
||||||
/* Cause software interrupt to ensure rx rings are cleaned */
|
if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
|
||||||
switch (hw->mac.type) {
|
/*
|
||||||
case ixgbe_mac_82598EB:
|
* for legacy and MSI interrupts don't set any bits
|
||||||
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
|
* that are enabled for EIAM, because this operation
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_EICS, (u32)eics);
|
* would set *both* EIMS and EICS for any bit in EIAM
|
||||||
} else {
|
*/
|
||||||
/*
|
IXGBE_WRITE_REG(hw, IXGBE_EICS,
|
||||||
* for legacy and MSI interrupts don't set any
|
(IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER));
|
||||||
* bits that are enabled for EIAM, because this
|
goto watchdog_reschedule;
|
||||||
* operation would set *both* EIMS and EICS for
|
|
||||||
* any bit in EIAM
|
|
||||||
*/
|
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_EICS,
|
|
||||||
(IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ixgbe_mac_82599EB:
|
|
||||||
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
|
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_EICS_EX(0),
|
|
||||||
(u32)(eics & 0xFFFFFFFF));
|
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_EICS_EX(1),
|
|
||||||
(u32)(eics >> 32));
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* for legacy and MSI interrupts don't set any
|
|
||||||
* bits that are enabled for EIAM, because this
|
|
||||||
* operation would set *both* EIMS and EICS for
|
|
||||||
* any bit in EIAM
|
|
||||||
*/
|
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_EICS,
|
|
||||||
(IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* Reset the timer */
|
|
||||||
mod_timer(&adapter->watchdog_timer,
|
|
||||||
round_jiffies(jiffies + 2 * HZ));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get one bit for every active tx/rx interrupt vector */
|
||||||
|
for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) {
|
||||||
|
struct ixgbe_q_vector *qv = adapter->q_vector[i];
|
||||||
|
if (qv->rxr_count || qv->txr_count)
|
||||||
|
eics |= ((u64)1 << i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cause software interrupt to ensure rx rings are cleaned */
|
||||||
|
ixgbe_irq_rearm_queues(adapter, eics);
|
||||||
|
|
||||||
|
watchdog_reschedule:
|
||||||
|
/* Reset the timer */
|
||||||
|
mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 2 * HZ));
|
||||||
|
|
||||||
|
watchdog_short_circuit:
|
||||||
schedule_work(&adapter->watchdog_task);
|
schedule_work(&adapter->watchdog_task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue