From 6d9e5130b96daa1656966f7271e8a0928b3906c4 Mon Sep 17 00:00:00 2001 From: Nicolas Schichan Date: Sat, 9 Jul 2011 00:24:18 +0000 Subject: e1000: always call e1000_check_for_link() on e1000_ce4100 MACs. Interrupts about link lost or rx sequence errors are not reported by the ce4100 hardware, leading to transitions from link UP to link DOWN never being reported. Signed-off-by: Nicolas Schichan Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/e1000/e1000_main.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index acaebecf0ca7..f97afda941d7 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2402,13 +2402,16 @@ bool e1000_has_link(struct e1000_adapter *adapter) struct e1000_hw *hw = &adapter->hw; bool link_active = false; - /* get_link_status is set on LSC (link status) interrupt or - * rx sequence error interrupt. get_link_status will stay - * false until the e1000_check_for_link establishes link - * for copper adapters ONLY + /* get_link_status is set on LSC (link status) interrupt or rx + * sequence error interrupt (except on intel ce4100). + * get_link_status will stay false until the + * e1000_check_for_link establishes link for copper adapters + * ONLY */ switch (hw->media_type) { case e1000_media_type_copper: + if (hw->mac_type == e1000_ce4100) + hw->get_link_status = 1; if (hw->get_link_status) { e1000_check_for_link(hw); link_active = !hw->get_link_status; -- cgit v1.2.3-58-ga151 From a14bc2bb7075e59be635a2470dc0a32c5a0e8e21 Mon Sep 17 00:00:00 2001 From: Robert Healy Date: Tue, 12 Jul 2011 08:46:20 +0000 Subject: igb: Fix for DH89xxCC near end loopback test On this chipset it is required to configure the MPHY block for loopback tests. If MPHY is not configured then all loopback tests will report failures. Signed-off-by: Robert Healy Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/igb/e1000_defines.h | 10 ++++++++++ drivers/net/igb/igb_ethtool.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 2cd4082c86ca..7b8ddd830f19 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -512,6 +512,16 @@ #define E1000_GCR_CMPL_TMOUT_RESEND 0x00010000 #define E1000_GCR_CAP_VER2 0x00040000 +/* mPHY Address Control and Data Registers */ +#define E1000_MPHY_ADDR_CTL 0x0024 /* mPHY Address Control Register */ +#define E1000_MPHY_ADDR_CTL_OFFSET_MASK 0xFFFF0000 +#define E1000_MPHY_DATA 0x0E10 /* mPHY Data Register */ + +/* mPHY PCS CLK Register */ +#define E1000_MPHY_PCS_CLK_REG_OFFSET 0x0004 /* mPHY PCS CLK AFE CSR Offset */ +/* mPHY Near End Digital Loopback Override Bit */ +#define E1000_MPHY_PCS_CLK_REG_DIGINELBEN 0x10 + /* PHY Control Register */ #define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ #define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index ed63ff4cf6d6..ff244ce803ce 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -1461,6 +1461,22 @@ static int igb_setup_loopback_test(struct igb_adapter *adapter) /* use CTRL_EXT to identify link type as SGMII can appear as copper */ if (reg & E1000_CTRL_EXT_LINK_MODE_MASK) { + if ((hw->device_id == E1000_DEV_ID_DH89XXCC_SGMII) || + (hw->device_id == E1000_DEV_ID_DH89XXCC_SERDES) || + (hw->device_id == E1000_DEV_ID_DH89XXCC_BACKPLANE) || + (hw->device_id == E1000_DEV_ID_DH89XXCC_SFP)) { + + /* Enable DH89xxCC MPHY for near end loopback */ + reg = rd32(E1000_MPHY_ADDR_CTL); + reg = (reg & E1000_MPHY_ADDR_CTL_OFFSET_MASK) | + E1000_MPHY_PCS_CLK_REG_OFFSET; + wr32(E1000_MPHY_ADDR_CTL, reg); + + reg = rd32(E1000_MPHY_DATA); + reg |= E1000_MPHY_PCS_CLK_REG_DIGINELBEN; + wr32(E1000_MPHY_DATA, reg); + } + reg = rd32(E1000_RCTL); reg |= E1000_RCTL_LBM_TCVR; wr32(E1000_RCTL, reg); @@ -1502,6 +1518,23 @@ static void igb_loopback_cleanup(struct igb_adapter *adapter) u32 rctl; u16 phy_reg; + if ((hw->device_id == E1000_DEV_ID_DH89XXCC_SGMII) || + (hw->device_id == E1000_DEV_ID_DH89XXCC_SERDES) || + (hw->device_id == E1000_DEV_ID_DH89XXCC_BACKPLANE) || + (hw->device_id == E1000_DEV_ID_DH89XXCC_SFP)) { + u32 reg; + + /* Disable near end loopback on DH89xxCC */ + reg = rd32(E1000_MPHY_ADDR_CTL); + reg = (reg & E1000_MPHY_ADDR_CTL_OFFSET_MASK) | + E1000_MPHY_PCS_CLK_REG_OFFSET; + wr32(E1000_MPHY_ADDR_CTL, reg); + + reg = rd32(E1000_MPHY_DATA); + reg &= ~E1000_MPHY_PCS_CLK_REG_DIGINELBEN; + wr32(E1000_MPHY_DATA, reg); + } + rctl = rd32(E1000_RCTL); rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); wr32(E1000_RCTL, rctl); -- cgit v1.2.3-58-ga151 From 6440752c872e418452a2cbbf5e73d546affe2b28 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sat, 11 Jun 2011 01:44:53 +0000 Subject: ixgbe: Update ATR to use recorded TX queues instead of CPU for routing This change is meant to update ATR so that it will use the recorded RX queue instead of the CPU in the case of routing. This change is meant to help ixgbe default behavior to more closely match that of the kernel. Signed-off-by: Alexander Duyck Tested-by: Ross Brattain Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index de307965dfee..f05ddf31a19f 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -6795,11 +6795,10 @@ static int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size) static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb) { struct ixgbe_adapter *adapter = netdev_priv(dev); - int txq = smp_processor_id(); + int txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : + smp_processor_id(); #ifdef IXGBE_FCOE - __be16 protocol; - - protocol = vlan_get_protocol(skb); + __be16 protocol = vlan_get_protocol(skb); if (((protocol == htons(ETH_P_FCOE)) || (protocol == htons(ETH_P_FIP))) && -- cgit v1.2.3-58-ga151 From 82d4e46e2a398154273044dd9813206f0d85bc09 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sat, 11 Jun 2011 01:44:58 +0000 Subject: ixgbe: inline the ixgbe_maybe_stop_tx function The ixgbe_maybe_stop_tx function is only a few lines long and is called multiple times through the xmit hotpath. In order to streamline things it makes sense to just inline it. Signed-off-by: Alexander Duyck Tested-by: Ross Brattain Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index f05ddf31a19f..7275c5cc09b2 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -6785,7 +6785,7 @@ static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size) return 0; } -static int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size) +static inline int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size) { if (likely(ixgbe_desc_unused(tx_ring) >= size)) return 0; -- cgit v1.2.3-58-ga151 From 08c8833b29cfa4343ff132eebc5648b234eb3f85 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sat, 11 Jun 2011 01:45:03 +0000 Subject: ixgbe: add structure for containing RX/TX rings to q_vector This patch adds support for a ring container structure to be used within the q_vector. The basic idea is to provide a means of separating the RX and TX rings while maintaining a common structure for their containment. The advantage to this is that later we should be able to pass this structure to the update_itr functions without needing to pass individual rings. Signed-off-by: Alexander Duyck Tested-by: Ross Brattain Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe.h | 16 ++-- drivers/net/ixgbe/ixgbe_ethtool.c | 6 +- drivers/net/ixgbe/ixgbe_main.c | 150 +++++++++++++++++++------------------- 3 files changed, 88 insertions(+), 84 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 744b64108130..a5ed9fd69fdd 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -277,6 +277,15 @@ struct ixgbe_ring_feature { int mask; } ____cacheline_internodealigned_in_smp; +struct ixgbe_ring_container { +#if MAX_RX_QUEUES > MAX_TX_QUEUES + DECLARE_BITMAP(idx, MAX_RX_QUEUES); +#else + DECLARE_BITMAP(idx, MAX_TX_QUEUES); +#endif + u8 count; /* total number of rings in vector */ + u8 itr; /* current ITR setting for ring */ +}; #define MAX_RX_PACKET_BUFFERS ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) \ ? 8 : 1) @@ -294,12 +303,7 @@ struct ixgbe_q_vector { int cpu; /* CPU for DCA */ #endif struct napi_struct napi; - DECLARE_BITMAP(rxr_idx, MAX_RX_QUEUES); /* Rx ring indices */ - DECLARE_BITMAP(txr_idx, MAX_TX_QUEUES); /* Tx ring indices */ - u8 rxr_count; /* Rx ring count assigned to this vector */ - u8 txr_count; /* Tx ring count assigned to this vector */ - u8 tx_itr; - u8 rx_itr; + struct ixgbe_ring_container rx, tx; u32 eitr; cpumask_var_t affinity_mask; char name[IFNAMSIZ + 9]; diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 074e9baf069a..cd842f9dcae5 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -2122,7 +2122,7 @@ static int ixgbe_get_coalesce(struct net_device *netdev, } /* if in mixed tx/rx queues per vector mode, report only rx settings */ - if (adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count) + if (adapter->q_vector[0]->tx.count && adapter->q_vector[0]->rx.count) return 0; /* only valid if in constant ITR mode */ @@ -2187,7 +2187,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev, bool need_reset = false; /* don't accept tx specific changes if we've got mixed RxTx vectors */ - if (adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count + if (adapter->q_vector[0]->tx.count && adapter->q_vector[0]->rx.count && ec->tx_coalesce_usecs) return -EINVAL; @@ -2261,7 +2261,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev, int 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->txr_count && !q_vector->rxr_count) + if (q_vector->tx.count && !q_vector->rx.count) /* tx only */ q_vector->eitr = adapter->tx_eitr_param; else diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 7275c5cc09b2..bd1fd8f422dc 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -959,17 +959,17 @@ static void ixgbe_update_dca(struct ixgbe_q_vector *q_vector) if (q_vector->cpu == cpu) goto out_no_update; - r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); - for (i = 0; i < q_vector->txr_count; i++) { + r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues); + for (i = 0; i < q_vector->tx.count; i++) { ixgbe_update_tx_dca(adapter, adapter->tx_ring[r_idx], cpu); - r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, + r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues, r_idx + 1); } - r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); - for (i = 0; i < q_vector->rxr_count; i++) { + r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues); + for (i = 0; i < q_vector->rx.count; i++) { ixgbe_update_rx_dca(adapter, adapter->rx_ring[r_idx], cpu); - r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, + r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues, r_idx + 1); } @@ -1517,31 +1517,31 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) for (v_idx = 0; v_idx < q_vectors; v_idx++) { q_vector = adapter->q_vector[v_idx]; /* XXX for_each_set_bit(...) */ - r_idx = find_first_bit(q_vector->rxr_idx, + r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues); - for (i = 0; i < q_vector->rxr_count; i++) { + for (i = 0; i < q_vector->rx.count; i++) { u8 reg_idx = adapter->rx_ring[r_idx]->reg_idx; ixgbe_set_ivar(adapter, 0, reg_idx, v_idx); - r_idx = find_next_bit(q_vector->rxr_idx, + r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues, r_idx + 1); } - r_idx = find_first_bit(q_vector->txr_idx, + r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues); - for (i = 0; i < q_vector->txr_count; i++) { + for (i = 0; i < q_vector->tx.count; i++) { u8 reg_idx = adapter->tx_ring[r_idx]->reg_idx; ixgbe_set_ivar(adapter, 1, reg_idx, v_idx); - r_idx = find_next_bit(q_vector->txr_idx, + r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues, r_idx + 1); } - if (q_vector->txr_count && !q_vector->rxr_count) + if (q_vector->tx.count && !q_vector->rx.count) /* tx only */ q_vector->eitr = adapter->tx_eitr_param; - else if (q_vector->rxr_count) + else if (q_vector->rx.count) /* rx or mixed */ q_vector->eitr = adapter->rx_eitr_param; @@ -1705,37 +1705,37 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) u32 new_itr; u8 current_itr, ret_itr; - r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); - for (i = 0; i < q_vector->txr_count; i++) { + r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues); + for (i = 0; i < q_vector->tx.count; i++) { struct ixgbe_ring *tx_ring = adapter->tx_ring[r_idx]; ret_itr = ixgbe_update_itr(adapter, q_vector->eitr, - q_vector->tx_itr, + q_vector->tx.itr, tx_ring->total_packets, tx_ring->total_bytes); /* if the result for this queue would decrease interrupt * rate for this vector then use that result */ - q_vector->tx_itr = ((q_vector->tx_itr > ret_itr) ? - q_vector->tx_itr - 1 : ret_itr); - r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, + q_vector->tx.itr = ((q_vector->tx.itr > ret_itr) ? + q_vector->tx.itr - 1 : ret_itr); + r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues, r_idx + 1); } - r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); - for (i = 0; i < q_vector->rxr_count; i++) { + r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues); + for (i = 0; i < q_vector->rx.count; i++) { struct ixgbe_ring *rx_ring = adapter->rx_ring[r_idx]; ret_itr = ixgbe_update_itr(adapter, q_vector->eitr, - q_vector->rx_itr, + q_vector->rx.itr, rx_ring->total_packets, rx_ring->total_bytes); /* if the result for this queue would decrease interrupt * rate for this vector then use that result */ - q_vector->rx_itr = ((q_vector->rx_itr > ret_itr) ? - q_vector->rx_itr - 1 : ret_itr); - r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, + q_vector->rx.itr = ((q_vector->rx.itr > ret_itr) ? + q_vector->rx.itr - 1 : ret_itr); + r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues, r_idx + 1); } - current_itr = max(q_vector->rx_itr, q_vector->tx_itr); + current_itr = max(q_vector->rx.itr, q_vector->tx.itr); switch (current_itr) { /* counts and packets in update_itr are dependent on these numbers */ @@ -1995,15 +1995,15 @@ static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data) struct ixgbe_ring *tx_ring; int i, r_idx; - if (!q_vector->txr_count) + if (!q_vector->tx.count) return IRQ_HANDLED; - r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); - for (i = 0; i < q_vector->txr_count; i++) { + r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues); + for (i = 0; i < q_vector->tx.count; i++) { tx_ring = adapter->tx_ring[r_idx]; tx_ring->total_bytes = 0; tx_ring->total_packets = 0; - r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, + r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues, r_idx + 1); } @@ -2031,16 +2031,16 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data) ixgbe_update_dca(q_vector); #endif - r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); - for (i = 0; i < q_vector->rxr_count; i++) { + r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues); + for (i = 0; i < q_vector->rx.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 = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues, r_idx + 1); } - if (!q_vector->rxr_count) + if (!q_vector->rx.count) return IRQ_HANDLED; /* EIAM disabled interrupts (on this vector) for us */ @@ -2057,24 +2057,24 @@ static irqreturn_t ixgbe_msix_clean_many(int irq, void *data) int r_idx; int i; - if (!q_vector->txr_count && !q_vector->rxr_count) + if (!q_vector->tx.count && !q_vector->rx.count) return IRQ_HANDLED; - r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); - for (i = 0; i < q_vector->txr_count; i++) { + r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues); + for (i = 0; i < q_vector->tx.count; i++) { ring = adapter->tx_ring[r_idx]; ring->total_bytes = 0; ring->total_packets = 0; - r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, + r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues, r_idx + 1); } - r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); - for (i = 0; i < q_vector->rxr_count; i++) { + r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues); + for (i = 0; i < q_vector->rx.count; i++) { ring = adapter->rx_ring[r_idx]; ring->total_bytes = 0; ring->total_packets = 0; - r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, + r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues, r_idx + 1); } @@ -2106,7 +2106,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget) ixgbe_update_dca(q_vector); #endif - r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues); rx_ring = adapter->rx_ring[r_idx]; ixgbe_clean_rx_irq(q_vector, rx_ring, &work_done, budget); @@ -2147,27 +2147,27 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget) ixgbe_update_dca(q_vector); #endif - r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); - for (i = 0; i < q_vector->txr_count; i++) { + r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues); + for (i = 0; i < q_vector->tx.count; i++) { ring = adapter->tx_ring[r_idx]; tx_clean_complete &= ixgbe_clean_tx_irq(q_vector, ring); - r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, + r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues, r_idx + 1); } /* attempt to distribute budget to each queue fairly, but don't allow * the budget to go below 1 because we'll exit polling */ - budget /= (q_vector->rxr_count ?: 1); + budget /= (q_vector->rx.count ?: 1); budget = max(budget, 1); - r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); - for (i = 0; i < q_vector->rxr_count; i++) { + r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues); + for (i = 0; i < q_vector->rx.count; i++) { ring = adapter->rx_ring[r_idx]; ixgbe_clean_rx_irq(q_vector, ring, &work_done, budget); - r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, + r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues, r_idx + 1); } - r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues); ring = adapter->rx_ring[r_idx]; /* If all Rx work done, exit the polling mode */ if (work_done < budget) { @@ -2205,7 +2205,7 @@ static int ixgbe_clean_txonly(struct napi_struct *napi, int budget) ixgbe_update_dca(q_vector); #endif - r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); + r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues); tx_ring = adapter->tx_ring[r_idx]; if (!ixgbe_clean_tx_irq(q_vector, tx_ring)) @@ -2230,8 +2230,8 @@ static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx, struct ixgbe_q_vector *q_vector = a->q_vector[v_idx]; struct ixgbe_ring *rx_ring = a->rx_ring[r_idx]; - set_bit(r_idx, q_vector->rxr_idx); - q_vector->rxr_count++; + set_bit(r_idx, q_vector->rx.idx); + q_vector->rx.count++; rx_ring->q_vector = q_vector; } @@ -2241,8 +2241,8 @@ static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx, struct ixgbe_q_vector *q_vector = a->q_vector[v_idx]; struct ixgbe_ring *tx_ring = a->tx_ring[t_idx]; - set_bit(t_idx, q_vector->txr_idx); - q_vector->txr_count++; + set_bit(t_idx, q_vector->tx.idx); + q_vector->tx.count++; tx_ring->q_vector = q_vector; } @@ -2332,10 +2332,10 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) if (err) return err; -#define SET_HANDLER(_v) (((_v)->rxr_count && (_v)->txr_count) \ +#define SET_HANDLER(_v) (((_v)->rx.count && (_v)->tx.count) \ ? &ixgbe_msix_clean_many : \ - (_v)->rxr_count ? &ixgbe_msix_clean_rx : \ - (_v)->txr_count ? &ixgbe_msix_clean_tx : \ + (_v)->rx.count ? &ixgbe_msix_clean_rx : \ + (_v)->tx.count ? &ixgbe_msix_clean_tx : \ NULL) for (vector = 0; vector < q_vectors; vector++) { struct ixgbe_q_vector *q_vector = adapter->q_vector[vector]; @@ -2394,16 +2394,16 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter) u32 new_itr = q_vector->eitr; u8 current_itr; - q_vector->tx_itr = ixgbe_update_itr(adapter, new_itr, - q_vector->tx_itr, + q_vector->tx.itr = ixgbe_update_itr(adapter, new_itr, + q_vector->tx.itr, tx_ring->total_packets, tx_ring->total_bytes); - q_vector->rx_itr = ixgbe_update_itr(adapter, new_itr, - q_vector->rx_itr, + q_vector->rx.itr = ixgbe_update_itr(adapter, new_itr, + q_vector->rx.itr, rx_ring->total_packets, rx_ring->total_bytes); - current_itr = max(q_vector->rx_itr, q_vector->tx_itr); + current_itr = max(q_vector->rx.itr, q_vector->tx.itr); switch (current_itr) { /* counts and packets in update_itr are dependent on these numbers */ @@ -2553,10 +2553,10 @@ static inline void ixgbe_reset_q_vectors(struct ixgbe_adapter *adapter) for (i = 0; i < q_vectors; i++) { struct ixgbe_q_vector *q_vector = adapter->q_vector[i]; - bitmap_zero(q_vector->rxr_idx, MAX_RX_QUEUES); - bitmap_zero(q_vector->txr_idx, MAX_TX_QUEUES); - q_vector->rxr_count = 0; - q_vector->txr_count = 0; + bitmap_zero(q_vector->rx.idx, MAX_RX_QUEUES); + bitmap_zero(q_vector->tx.idx, MAX_TX_QUEUES); + q_vector->rx.count = 0; + q_vector->tx.count = 0; } } @@ -2601,8 +2601,8 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter) i--; for (; i >= 0; i--) { /* free only the irqs that were actually requested */ - if (!adapter->q_vector[i]->rxr_count && - !adapter->q_vector[i]->txr_count) + if (!adapter->q_vector[i]->rx.count && + !adapter->q_vector[i]->tx.count) continue; free_irq(adapter->msix_entries[i].vector, @@ -3616,10 +3616,10 @@ static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter) q_vector = adapter->q_vector[q_idx]; napi = &q_vector->napi; if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { - if (!q_vector->rxr_count || !q_vector->txr_count) { - if (q_vector->txr_count == 1) + if (!q_vector->rx.count || !q_vector->tx.count) { + if (q_vector->tx.count == 1) napi->poll = &ixgbe_clean_txonly; - else if (q_vector->rxr_count == 1) + else if (q_vector->rx.count == 1) napi->poll = &ixgbe_clean_rxonly; } } @@ -4965,7 +4965,7 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter) if (!q_vector) goto err_out; q_vector->adapter = adapter; - if (q_vector->txr_count && !q_vector->rxr_count) + if (q_vector->tx.count && !q_vector->rx.count) q_vector->eitr = adapter->tx_eitr_param; else q_vector->eitr = adapter->rx_eitr_param; @@ -5979,7 +5979,7 @@ static void ixgbe_check_hang_subtask(struct ixgbe_adapter *adapter) /* 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) + if (qv->rx.count || qv->tx.count) eics |= ((u64)1 << i); } } -- cgit v1.2.3-58-ga151 From bd19805803a954415ec36a559fd3b8a0a3647d7c Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sat, 11 Jun 2011 01:45:08 +0000 Subject: ixgbe: Move interrupt related values out of ring and into q_vector This change moves work_limit, total_packets, and total_bytes into the ring container struct of the q_vector. The advantage of this is that it should reduce the size of memory used in the event of multiple rings being assigned to a single q_vector. In addition it should help to reduce the total workload for calculating itr since now total_packets and total_bytes will be the total work done of the interrupt instead of for the ring. Signed-off-by: Alexander Duyck Tested-by: Ross Brattain Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe.h | 24 +++--- drivers/net/ixgbe/ixgbe_ethtool.c | 6 +- drivers/net/ixgbe/ixgbe_main.c | 170 ++++++++++---------------------------- 3 files changed, 62 insertions(+), 138 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index a5ed9fd69fdd..fbae7352b036 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -214,12 +214,10 @@ struct ixgbe_ring { struct ixgbe_rx_buffer *rx_buffer_info; }; unsigned long state; - u8 atr_sample_rate; - u8 atr_count; + u8 __iomem *tail; + u16 count; /* amount of descriptors */ u16 rx_buf_len; - u16 next_to_use; - u16 next_to_clean; u8 queue_index; /* needed for multiqueue queue management */ u8 reg_idx; /* holds the special value that gets @@ -227,15 +225,13 @@ struct ixgbe_ring { * associated with this ring, which is * different for DCB and RSS modes */ - u8 dcb_tc; - - u16 work_limit; /* max work per interrupt */ - - u8 __iomem *tail; + u8 atr_sample_rate; + u8 atr_count; - unsigned int total_bytes; - unsigned int total_packets; + u16 next_to_use; + u16 next_to_clean; + u8 dcb_tc; struct ixgbe_queue_stats stats; struct u64_stats_sync syncp; union { @@ -283,6 +279,9 @@ struct ixgbe_ring_container { #else DECLARE_BITMAP(idx, MAX_TX_QUEUES); #endif + unsigned int total_bytes; /* total bytes processed this int */ + unsigned int total_packets; /* total packets processed this int */ + u16 work_limit; /* total work allowed per interrupt */ u8 count; /* total number of rings in vector */ u8 itr; /* current ITR setting for ring */ }; @@ -417,6 +416,9 @@ struct ixgbe_adapter { u16 eitr_low; u16 eitr_high; + /* Work limits */ + u16 tx_work_limit; + /* TX */ struct ixgbe_ring *tx_ring[MAX_TX_QUEUES] ____cacheline_aligned_in_smp; int num_tx_queues; diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index cd842f9dcae5..6035cfa1b4c7 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -2103,7 +2103,7 @@ static int ixgbe_get_coalesce(struct net_device *netdev, { struct ixgbe_adapter *adapter = netdev_priv(netdev); - ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0]->work_limit; + ec->tx_max_coalesced_frames_irq = adapter->tx_work_limit; /* only valid if in constant ITR mode */ switch (adapter->rx_itr_setting) { @@ -2192,7 +2192,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev, return -EINVAL; if (ec->tx_max_coalesced_frames_irq) - adapter->tx_ring[0]->work_limit = ec->tx_max_coalesced_frames_irq; + adapter->tx_work_limit = ec->tx_max_coalesced_frames_irq; if (ec->rx_coalesce_usecs > 1) { /* check the limits */ @@ -2267,12 +2267,14 @@ static int ixgbe_set_coalesce(struct net_device *netdev, else /* rx only or mixed */ q_vector->eitr = adapter->rx_eitr_param; + q_vector->tx.work_limit = adapter->tx_work_limit; ixgbe_write_eitr(q_vector); } /* Legacy Interrupt Mode */ } else { q_vector = adapter->q_vector[0]; q_vector->eitr = adapter->rx_eitr_param; + q_vector->tx.work_limit = adapter->tx_work_limit; ixgbe_write_eitr(q_vector); } diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index bd1fd8f422dc..298c95b1480f 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -805,7 +805,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop); while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) && - (count < tx_ring->work_limit)) { + (count < q_vector->tx.work_limit)) { bool cleaned = false; rmb(); /* read buffer_info after eop_desc */ for ( ; !cleaned; count++) { @@ -834,11 +834,11 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, } tx_ring->next_to_clean = i; - tx_ring->total_bytes += total_bytes; - tx_ring->total_packets += total_packets; - u64_stats_update_begin(&tx_ring->syncp); - tx_ring->stats.packets += total_packets; tx_ring->stats.bytes += total_bytes; + tx_ring->stats.packets += total_packets; + u64_stats_update_begin(&tx_ring->syncp); + q_vector->tx.total_bytes += total_bytes; + q_vector->tx.total_packets += total_packets; u64_stats_update_end(&tx_ring->syncp); if (check_for_tx_hang(tx_ring) && ixgbe_check_tx_hang(tx_ring)) { @@ -886,7 +886,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, } } - return count < tx_ring->work_limit; + return count < q_vector->tx.work_limit; } #ifdef CONFIG_IXGBE_DCA @@ -1486,12 +1486,12 @@ next_desc: } #endif /* IXGBE_FCOE */ - rx_ring->total_packets += total_rx_packets; - rx_ring->total_bytes += total_rx_bytes; u64_stats_update_begin(&rx_ring->syncp); rx_ring->stats.packets += total_rx_packets; rx_ring->stats.bytes += total_rx_bytes; u64_stats_update_end(&rx_ring->syncp); + q_vector->rx.total_packets += total_rx_packets; + q_vector->rx.total_bytes += total_rx_bytes; } static int ixgbe_clean_rxonly(struct napi_struct *, int); @@ -1597,11 +1597,8 @@ enum latency_range { /** * ixgbe_update_itr - update the dynamic ITR value based on statistics - * @adapter: pointer to adapter - * @eitr: eitr setting (ints per sec) to give last timeslice - * @itr_setting: current throttle rate in ints/second - * @packets: the number of packets during this measurement interval - * @bytes: the number of bytes during this measurement interval + * @q_vector: structure containing interrupt and ring information + * @ring_container: structure containing ring performance data * * Stores a new ITR value based on packets and byte * counts during the last interrupt. The advantage of per interrupt @@ -1613,17 +1610,18 @@ enum latency_range { * this functionality is controlled by the InterruptThrottleRate module * parameter (see ixgbe_param.c) **/ -static u8 ixgbe_update_itr(struct ixgbe_adapter *adapter, - u32 eitr, u8 itr_setting, - int packets, int bytes) +static void ixgbe_update_itr(struct ixgbe_q_vector *q_vector, + struct ixgbe_ring_container *ring_container) { - unsigned int retval = itr_setting; - u32 timepassed_us; u64 bytes_perint; + struct ixgbe_adapter *adapter = q_vector->adapter; + int bytes = ring_container->total_bytes; + int packets = ring_container->total_packets; + u32 timepassed_us; + u8 itr_setting = ring_container->itr; if (packets == 0) - goto update_itr_done; - + return; /* simple throttlerate management * 0-20MB/s lowest (100000 ints/s) @@ -1631,28 +1629,32 @@ static u8 ixgbe_update_itr(struct ixgbe_adapter *adapter, * 100-1249MB/s bulk (8000 ints/s) */ /* what was last interrupt timeslice? */ - timepassed_us = 1000000/eitr; + timepassed_us = 1000000/q_vector->eitr; bytes_perint = bytes / timepassed_us; /* bytes/usec */ switch (itr_setting) { case lowest_latency: if (bytes_perint > adapter->eitr_low) - retval = low_latency; + itr_setting = low_latency; break; case low_latency: if (bytes_perint > adapter->eitr_high) - retval = bulk_latency; + itr_setting = bulk_latency; else if (bytes_perint <= adapter->eitr_low) - retval = lowest_latency; + itr_setting = lowest_latency; break; case bulk_latency: if (bytes_perint <= adapter->eitr_high) - retval = low_latency; + itr_setting = low_latency; break; } -update_itr_done: - return retval; + /* clear work counters since we have the values we need */ + ring_container->total_bytes = 0; + ring_container->total_packets = 0; + + /* write updated itr to ring container */ + ring_container->itr = itr_setting; } /** @@ -1698,42 +1700,13 @@ void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector) IXGBE_WRITE_REG(hw, IXGBE_EITR(v_idx), itr_reg); } -static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) +static void ixgbe_set_itr(struct ixgbe_q_vector *q_vector) { - struct ixgbe_adapter *adapter = q_vector->adapter; - int i, r_idx; - u32 new_itr; - u8 current_itr, ret_itr; - - r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues); - for (i = 0; i < q_vector->tx.count; i++) { - struct ixgbe_ring *tx_ring = adapter->tx_ring[r_idx]; - ret_itr = ixgbe_update_itr(adapter, q_vector->eitr, - q_vector->tx.itr, - tx_ring->total_packets, - tx_ring->total_bytes); - /* if the result for this queue would decrease interrupt - * rate for this vector then use that result */ - q_vector->tx.itr = ((q_vector->tx.itr > ret_itr) ? - q_vector->tx.itr - 1 : ret_itr); - r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues, - r_idx + 1); - } + u32 new_itr = q_vector->eitr; + u8 current_itr; - r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues); - for (i = 0; i < q_vector->rx.count; i++) { - struct ixgbe_ring *rx_ring = adapter->rx_ring[r_idx]; - ret_itr = ixgbe_update_itr(adapter, q_vector->eitr, - q_vector->rx.itr, - rx_ring->total_packets, - rx_ring->total_bytes); - /* if the result for this queue would decrease interrupt - * rate for this vector then use that result */ - q_vector->rx.itr = ((q_vector->rx.itr > ret_itr) ? - q_vector->rx.itr - 1 : ret_itr); - r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues, - r_idx + 1); - } + ixgbe_update_itr(q_vector, &q_vector->tx); + ixgbe_update_itr(q_vector, &q_vector->rx); current_itr = max(q_vector->rx.itr, q_vector->tx.itr); @@ -1746,16 +1719,17 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) new_itr = 20000; /* aka hwitr = ~200 */ break; case bulk_latency: - default: new_itr = 8000; break; + default: + break; } if (new_itr != q_vector->eitr) { /* do an exponential smoothing */ new_itr = ((q_vector->eitr * 9) + new_itr)/10; - /* save the algorithm value here, not the smoothed one */ + /* save the algorithm value here */ q_vector->eitr = new_itr; ixgbe_write_eitr(q_vector); @@ -2001,8 +1975,6 @@ static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data) r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues); for (i = 0; i < q_vector->tx.count; i++) { tx_ring = adapter->tx_ring[r_idx]; - tx_ring->total_bytes = 0; - tx_ring->total_packets = 0; r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues, r_idx + 1); } @@ -2034,8 +2006,6 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data) r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues); for (i = 0; i < q_vector->rx.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->rx.idx, adapter->num_rx_queues, r_idx + 1); } @@ -2063,8 +2033,6 @@ static irqreturn_t ixgbe_msix_clean_many(int irq, void *data) r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues); for (i = 0; i < q_vector->tx.count; i++) { ring = adapter->tx_ring[r_idx]; - ring->total_bytes = 0; - ring->total_packets = 0; r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues, r_idx + 1); } @@ -2072,8 +2040,6 @@ static irqreturn_t ixgbe_msix_clean_many(int irq, void *data) r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues); for (i = 0; i < q_vector->rx.count; i++) { ring = adapter->rx_ring[r_idx]; - ring->total_bytes = 0; - ring->total_packets = 0; r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues, r_idx + 1); } @@ -2115,7 +2081,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget) if (work_done < budget) { napi_complete(napi); if (adapter->rx_itr_setting & 1) - ixgbe_set_itr_msix(q_vector); + ixgbe_set_itr(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx)); @@ -2173,7 +2139,7 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget) if (work_done < budget) { napi_complete(napi); if (adapter->rx_itr_setting & 1) - ixgbe_set_itr_msix(q_vector); + ixgbe_set_itr(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx)); @@ -2215,7 +2181,7 @@ static int ixgbe_clean_txonly(struct napi_struct *napi, int budget) if (work_done < budget) { napi_complete(napi); if (adapter->tx_itr_setting & 1) - ixgbe_set_itr_msix(q_vector); + ixgbe_set_itr(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx)); @@ -2244,6 +2210,7 @@ static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx, set_bit(t_idx, q_vector->tx.idx); q_vector->tx.count++; tx_ring->q_vector = q_vector; + q_vector->tx.work_limit = a->tx_work_limit; } /** @@ -2386,51 +2353,6 @@ free_queue_irqs: return err; } -static void ixgbe_set_itr(struct ixgbe_adapter *adapter) -{ - struct ixgbe_q_vector *q_vector = adapter->q_vector[0]; - struct ixgbe_ring *rx_ring = adapter->rx_ring[0]; - struct ixgbe_ring *tx_ring = adapter->tx_ring[0]; - u32 new_itr = q_vector->eitr; - u8 current_itr; - - q_vector->tx.itr = ixgbe_update_itr(adapter, new_itr, - q_vector->tx.itr, - tx_ring->total_packets, - tx_ring->total_bytes); - q_vector->rx.itr = ixgbe_update_itr(adapter, new_itr, - q_vector->rx.itr, - rx_ring->total_packets, - rx_ring->total_bytes); - - current_itr = max(q_vector->rx.itr, q_vector->tx.itr); - - switch (current_itr) { - /* counts and packets in update_itr are dependent on these numbers */ - case lowest_latency: - new_itr = 100000; - break; - case low_latency: - new_itr = 20000; /* aka hwitr = ~200 */ - break; - case bulk_latency: - new_itr = 8000; - break; - default: - break; - } - - if (new_itr != q_vector->eitr) { - /* do an exponential smoothing */ - new_itr = ((q_vector->eitr * 9) + new_itr)/10; - - /* save the algorithm value here */ - q_vector->eitr = new_itr; - - ixgbe_write_eitr(q_vector); - } -} - /** * ixgbe_irq_enable - Enable default interrupt generation settings * @adapter: board private structure @@ -2528,10 +2450,6 @@ static irqreturn_t ixgbe_intr(int irq, void *data) ixgbe_check_fan_failure(adapter, eicr); if (napi_schedule_prep(&(q_vector->napi))) { - adapter->tx_ring[0]->total_packets = 0; - adapter->tx_ring[0]->total_bytes = 0; - adapter->rx_ring[0]->total_packets = 0; - adapter->rx_ring[0]->total_bytes = 0; /* would disable interrupts here but EIAM disabled it */ __napi_schedule(&(q_vector->napi)); } @@ -4299,7 +4217,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) if (work_done < budget) { napi_complete(napi); if (adapter->rx_itr_setting & 1) - ixgbe_set_itr(adapter); + ixgbe_set_itr(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE); } @@ -5224,6 +5142,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) adapter->tx_ring_count = IXGBE_DEFAULT_TXD; adapter->rx_ring_count = IXGBE_DEFAULT_RXD; + /* set default work limits */ + adapter->tx_work_limit = adapter->tx_ring_count; + /* initialize eeprom parameters */ if (ixgbe_init_eeprom_params_generic(hw)) { e_dev_err("EEPROM initialization failed\n"); @@ -5270,7 +5191,6 @@ int ixgbe_setup_tx_resources(struct ixgbe_ring *tx_ring) tx_ring->next_to_use = 0; tx_ring->next_to_clean = 0; - tx_ring->work_limit = tx_ring->count; return 0; err: -- cgit v1.2.3-58-ga151 From ff886dfce2bdacbe71583ec973cec117973d8859 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sat, 11 Jun 2011 01:45:13 +0000 Subject: ixgbe: Pass staterr instead of re-reading status and error bits from descriptor This change is meant to address possible race conditions from the status and error bits on the RX descriptors being re-read by multiple functions in the RX cleanup path. To resolve this I have added code that will pass the staterr value to those functions. Signed-off-by: Alexander Duyck Tested-by: Ross Brattain Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe.h | 5 +++-- drivers/net/ixgbe/ixgbe_fcoe.c | 35 ++++++----------------------------- drivers/net/ixgbe/ixgbe_main.c | 39 ++++++++++++++++++++++++++++----------- 3 files changed, 37 insertions(+), 42 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index fbae7352b036..0d610c73164d 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -600,8 +600,9 @@ extern int ixgbe_fso(struct ixgbe_ring *tx_ring, struct sk_buff *skb, u32 tx_flags, u8 *hdr_len); extern void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter); extern int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter, - union ixgbe_adv_rx_desc *rx_desc, - struct sk_buff *skb); + union ixgbe_adv_rx_desc *rx_desc, + struct sk_buff *skb, + u32 staterr); extern int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, struct scatterlist *sgl, unsigned int sgc); extern int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid, diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c index f0c1018bbf31..824edae77865 100644 --- a/drivers/net/ixgbe/ixgbe_fcoe.c +++ b/drivers/net/ixgbe/ixgbe_fcoe.c @@ -36,25 +36,6 @@ #include #include -/** - * ixgbe_rx_is_fcoe - check the rx desc for incoming pkt type - * @rx_desc: advanced rx descriptor - * - * Returns : true if it is FCoE pkt - */ -static inline bool ixgbe_rx_is_fcoe(union ixgbe_adv_rx_desc *rx_desc) -{ - u16 p; - - p = le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info); - if (p & IXGBE_RXDADV_PKTTYPE_ETQF) { - p &= IXGBE_RXDADV_PKTTYPE_ETQF_MASK; - p >>= IXGBE_RXDADV_PKTTYPE_ETQF_SHIFT; - return p == IXGBE_ETQF_FILTER_FCOE; - } - return false; -} - /** * ixgbe_fcoe_clear_ddp - clear the given ddp context * @ddp - ptr to the ixgbe_fcoe_ddp @@ -136,7 +117,6 @@ out_ddp_put: return len; } - /** * ixgbe_fcoe_ddp_setup - called to set up ddp context * @netdev: the corresponding net_device @@ -380,23 +360,20 @@ int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid, */ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter, union ixgbe_adv_rx_desc *rx_desc, - struct sk_buff *skb) + struct sk_buff *skb, + u32 staterr) { u16 xid; u32 fctl; - u32 sterr, fceofe, fcerr, fcstat; + u32 fceofe, fcerr, fcstat; int rc = -EINVAL; struct ixgbe_fcoe *fcoe; struct ixgbe_fcoe_ddp *ddp; struct fc_frame_header *fh; struct fcoe_crc_eof *crc; - if (!ixgbe_rx_is_fcoe(rx_desc)) - goto ddp_out; - - sterr = le32_to_cpu(rx_desc->wb.upper.status_error); - fcerr = (sterr & IXGBE_RXDADV_ERR_FCERR); - fceofe = (sterr & IXGBE_RXDADV_ERR_FCEOFE); + fcerr = (staterr & IXGBE_RXDADV_ERR_FCERR); + fceofe = (staterr & IXGBE_RXDADV_ERR_FCEOFE); if (fcerr == IXGBE_FCERR_BADCRC) skb_checksum_none_assert(skb); else @@ -425,7 +402,7 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter, if (fcerr | fceofe) goto ddp_out; - fcstat = (sterr & IXGBE_RXDADV_STAT_FCSTAT); + fcstat = (staterr & IXGBE_RXDADV_STAT_FCSTAT); if (fcstat) { /* update length of DDPed data */ ddp->len = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss); diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 298c95b1480f..a222af378a32 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1038,6 +1038,24 @@ static inline void ixgbe_rx_hash(union ixgbe_adv_rx_desc *rx_desc, skb->rxhash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss); } +/** + * ixgbe_rx_is_fcoe - check the rx desc for incoming pkt type + * @adapter: address of board private structure + * @rx_desc: advanced rx descriptor + * + * Returns : true if it is FCoE pkt + */ +static inline bool ixgbe_rx_is_fcoe(struct ixgbe_adapter *adapter, + union ixgbe_adv_rx_desc *rx_desc) +{ + __le16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info; + + return (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) && + ((pkt_info & cpu_to_le16(IXGBE_RXDADV_PKTTYPE_ETQF_MASK)) == + (cpu_to_le16(IXGBE_ETQF_FILTER_FCOE << + IXGBE_RXDADV_PKTTYPE_ETQF_SHIFT))); +} + /** * ixgbe_receive_skb - Send a completed packet up the stack * @adapter: board private structure @@ -1070,14 +1088,14 @@ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector, * @adapter: address of board private structure * @status_err: hardware indication of status of receive * @skb: skb currently being received and modified + * @status_err: status error value of last descriptor in packet **/ static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter, union ixgbe_adv_rx_desc *rx_desc, - struct sk_buff *skb) + struct sk_buff *skb, + u32 status_err) { - u32 status_err = le32_to_cpu(rx_desc->wb.upper.status_error); - - skb_checksum_none_assert(skb); + skb->ip_summed = CHECKSUM_NONE; /* Rx csum disabled */ if (!(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED)) @@ -1421,14 +1439,12 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, } /* ERR_MASK will only have valid bits if EOP set */ - if (staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) { - /* trim packet back to size 0 and recycle it */ - __pskb_trim(skb, 0); - rx_buffer_info->skb = skb; + if (unlikely(staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK)) { + dev_kfree_skb_any(skb); goto next_desc; } - ixgbe_rx_checksum(adapter, rx_desc, skb); + ixgbe_rx_checksum(adapter, rx_desc, skb, staterr); if (adapter->netdev->features & NETIF_F_RXHASH) ixgbe_rx_hash(rx_desc, skb); @@ -1439,8 +1455,9 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, skb->protocol = eth_type_trans(skb, rx_ring->netdev); #ifdef IXGBE_FCOE /* if ddp, not passing to ULD unless for FCP_RSP or error */ - if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { - ddp_bytes = ixgbe_fcoe_ddp(adapter, rx_desc, skb); + if (ixgbe_rx_is_fcoe(adapter, rx_desc)) { + ddp_bytes = ixgbe_fcoe_ddp(adapter, rx_desc, skb, + staterr); if (!ddp_bytes) goto next_desc; } -- cgit v1.2.3-58-ga151 From 34c6ee8181d6ec1ed761ed2fdac4f1b0358e5447 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Tue, 12 Jul 2011 08:13:41 +0000 Subject: ixgbe: remove ifdef check for non-existent define Signed-off-by: Emil Tantilov Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_main.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index a222af378a32..358f6c9dafe7 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -6021,9 +6021,7 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter) (flow_tx ? "TX" : "None")))); netif_carrier_on(netdev); -#ifdef HAVE_IPLINK_VF_CONFIG ixgbe_check_vf_rate_limit(adapter); -#endif /* HAVE_IPLINK_VF_CONFIG */ } /** -- cgit v1.2.3-58-ga151 From 9417c464ba834ae29982fcd71bc59dc8e734327c Mon Sep 17 00:00:00 2001 From: Andy Gospodarek Date: Sat, 16 Jul 2011 07:31:33 +0000 Subject: ixgbe: only enable WoL for magic packet by default Martin Wilck reported that systems using the ixgbe-driver that were capable of WoL were rebooting almost as soon as they were shut down. This is because the default WoL settings enabled magic packet, broadcast, unicast, and multicast. Other Intel devices seem to use the stored eeprom value for initial WoL capabilities. The 82578DM (e1000e) and 82576 (igb) the devices I looked at had only the magic packet enabled in the eeprom, so that seems appropriate on ixgbe-based devices as well. I set the WoL options on my 82578DM to be the same default as the ixgbe devices (umbg) and saw the same as Martin -- almost as soon as my box shutdown, it booted again. This patch changes the default to only be the magic packet. This is the same as the default for most Intel and non-Intel hardware currently upstream. Signed-off-by: Andy Gospodarek CC: Martin Wilck Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_main.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 358f6c9dafe7..c6fa9c7eb738 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -7515,18 +7515,15 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, case IXGBE_DEV_ID_82599_SFP: /* Only this subdevice supports WOL */ if (pdev->subsystem_device == IXGBE_SUBDEV_ID_82599_SFP) - adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX | - IXGBE_WUFC_MC | IXGBE_WUFC_BC); + adapter->wol = IXGBE_WUFC_MAG; break; case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: /* All except this subdevice support WOL */ if (pdev->subsystem_device != IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ) - adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX | - IXGBE_WUFC_MC | IXGBE_WUFC_BC); + adapter->wol = IXGBE_WUFC_MAG; break; case IXGBE_DEV_ID_82599_KX4: - adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX | - IXGBE_WUFC_MC | IXGBE_WUFC_BC); + adapter->wol = IXGBE_WUFC_MAG; break; default: adapter->wol = 0; -- cgit v1.2.3-58-ga151 From 082757afcf7d6e44b24c4927ce5b158196d63e84 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Thu, 21 Jul 2011 05:55:00 +0000 Subject: ixgbe: convert to ndo_fix_features Private rx_csum flags are now duplicate of netdev->features & NETIF_F_RXCSUM. We remove those duplicates and now use the net_device_ops ndo_set_features. This was based on the original patch submitted by Michal Miroslaw . I also removed the special case not requiring a reset for X540 hardware. It is needed just as it is in 82599 hardware. Signed-off-by: Don Skidmore Cc: Michal Miroslaw Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe.h | 5 +- drivers/net/ixgbe/ixgbe_ethtool.c | 188 -------------------------------------- drivers/net/ixgbe/ixgbe_main.c | 135 ++++++++++++++++++++++----- 3 files changed, 111 insertions(+), 217 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 0d610c73164d..e04a8e49e6dc 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -587,13 +587,10 @@ extern s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw, u16 soft_id); extern void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input, union ixgbe_atr_input *mask); -extern void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, - struct ixgbe_ring *ring); -extern void ixgbe_clear_rscctl(struct ixgbe_adapter *adapter, - struct ixgbe_ring *ring); extern void ixgbe_set_rx_mode(struct net_device *netdev); extern int ixgbe_setup_tc(struct net_device *dev, u8 tc); extern void ixgbe_tx_ctxtdesc(struct ixgbe_ring *, u32, u32, u32, u32); +extern void ixgbe_do_reset(struct net_device *netdev); #ifdef IXGBE_FCOE extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter); extern int ixgbe_fso(struct ixgbe_ring *tx_ring, struct sk_buff *skb, diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 6035cfa1b4c7..dc649553a0a6 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -442,109 +442,6 @@ static int ixgbe_set_pauseparam(struct net_device *netdev, return 0; } -static void ixgbe_do_reset(struct net_device *netdev) -{ - struct ixgbe_adapter *adapter = netdev_priv(netdev); - - if (netif_running(netdev)) - ixgbe_reinit_locked(adapter); - else - ixgbe_reset(adapter); -} - -static u32 ixgbe_get_rx_csum(struct net_device *netdev) -{ - struct ixgbe_adapter *adapter = netdev_priv(netdev); - return adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED; -} - -static void ixgbe_set_rsc(struct ixgbe_adapter *adapter) -{ - int i; - - for (i = 0; i < adapter->num_rx_queues; i++) { - struct ixgbe_ring *ring = adapter->rx_ring[i]; - if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { - set_ring_rsc_enabled(ring); - ixgbe_configure_rscctl(adapter, ring); - } else { - ixgbe_clear_rscctl(adapter, ring); - } - } -} - -static int ixgbe_set_rx_csum(struct net_device *netdev, u32 data) -{ - struct ixgbe_adapter *adapter = netdev_priv(netdev); - bool need_reset = false; - - if (data) { - adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED; - } else { - adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED; - - if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) { - adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED; - netdev->features &= ~NETIF_F_LRO; - } - - switch (adapter->hw.mac.type) { - case ixgbe_mac_X540: - ixgbe_set_rsc(adapter); - break; - case ixgbe_mac_82599EB: - need_reset = true; - break; - default: - break; - } - } - - if (need_reset) - ixgbe_do_reset(netdev); - - return 0; -} - -static u32 ixgbe_get_tx_csum(struct net_device *netdev) -{ - return (netdev->features & NETIF_F_IP_CSUM) != 0; -} - -static int ixgbe_set_tx_csum(struct net_device *netdev, u32 data) -{ - struct ixgbe_adapter *adapter = netdev_priv(netdev); - u32 feature_list; - - feature_list = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - switch (adapter->hw.mac.type) { - case ixgbe_mac_82599EB: - case ixgbe_mac_X540: - feature_list |= NETIF_F_SCTP_CSUM; - break; - default: - break; - } - if (data) - netdev->features |= feature_list; - else - netdev->features &= ~feature_list; - - return 0; -} - -static int ixgbe_set_tso(struct net_device *netdev, u32 data) -{ - if (data) { - netdev->features |= NETIF_F_TSO; - netdev->features |= NETIF_F_TSO6; - } else { - netdev->features &= ~NETIF_F_TSO; - netdev->features &= ~NETIF_F_TSO6; - } - return 0; -} - static u32 ixgbe_get_msglevel(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); @@ -2289,81 +2186,6 @@ static int ixgbe_set_coalesce(struct net_device *netdev, return 0; } -static int ixgbe_set_flags(struct net_device *netdev, u32 data) -{ - struct ixgbe_adapter *adapter = netdev_priv(netdev); - bool need_reset = false; - int rc; - -#ifdef CONFIG_IXGBE_DCB - if ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) && - !(data & ETH_FLAG_RXVLAN)) - return -EINVAL; -#endif - - need_reset = (data & ETH_FLAG_RXVLAN) != - (netdev->features & NETIF_F_HW_VLAN_RX); - - if ((data & ETH_FLAG_RXHASH) && - !(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) - return -EOPNOTSUPP; - - rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_LRO | ETH_FLAG_NTUPLE | - ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN | - ETH_FLAG_RXHASH); - if (rc) - return rc; - - /* if state changes we need to update adapter->flags and reset */ - if ((adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) && - (!!(data & ETH_FLAG_LRO) != - !!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) { - if ((data & ETH_FLAG_LRO) && - (!adapter->rx_itr_setting || - (adapter->rx_itr_setting > IXGBE_MAX_RSC_INT_RATE))) { - e_info(probe, "rx-usecs set too low, " - "not enabling RSC.\n"); - } else { - adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED; - switch (adapter->hw.mac.type) { - case ixgbe_mac_X540: - ixgbe_set_rsc(adapter); - break; - case ixgbe_mac_82599EB: - need_reset = true; - break; - default: - break; - } - } - } - - /* - * Check if Flow Director n-tuple support was enabled or disabled. If - * the state changed, we need to reset. - */ - if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) { - /* turn off ATR, enable perfect filters and reset */ - if (data & ETH_FLAG_NTUPLE) { - adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; - adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE; - need_reset = true; - } - } else if (!(data & ETH_FLAG_NTUPLE)) { - /* turn off Flow Director, set ATR and reset */ - adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE; - if ((adapter->flags & IXGBE_FLAG_RSS_ENABLED) && - !(adapter->flags & IXGBE_FLAG_DCB_ENABLED)) - adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; - need_reset = true; - } - - if (need_reset) - ixgbe_do_reset(netdev); - - return 0; -} - static int ixgbe_get_ethtool_fdir_entry(struct ixgbe_adapter *adapter, struct ethtool_rxnfc *cmd) { @@ -2746,16 +2568,8 @@ static const struct ethtool_ops ixgbe_ethtool_ops = { .set_ringparam = ixgbe_set_ringparam, .get_pauseparam = ixgbe_get_pauseparam, .set_pauseparam = ixgbe_set_pauseparam, - .get_rx_csum = ixgbe_get_rx_csum, - .set_rx_csum = ixgbe_set_rx_csum, - .get_tx_csum = ixgbe_get_tx_csum, - .set_tx_csum = ixgbe_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, .get_msglevel = ixgbe_get_msglevel, .set_msglevel = ixgbe_set_msglevel, - .get_tso = ethtool_op_get_tso, - .set_tso = ixgbe_set_tso, .self_test = ixgbe_diag_test, .get_strings = ixgbe_get_strings, .set_phys_id = ixgbe_set_phys_id, @@ -2763,8 +2577,6 @@ static const struct ethtool_ops ixgbe_ethtool_ops = { .get_ethtool_stats = ixgbe_get_ethtool_stats, .get_coalesce = ixgbe_get_coalesce, .set_coalesce = ixgbe_set_coalesce, - .get_flags = ethtool_op_get_flags, - .set_flags = ixgbe_set_flags, .get_rxnfc = ixgbe_get_rxnfc, .set_rxnfc = ixgbe_set_rxnfc, }; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index c6fa9c7eb738..1be617545dc9 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2861,29 +2861,12 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); } -/** - * ixgbe_clear_rscctl - disable RSC for the indicated ring - * @adapter: address of board private structure - * @ring: structure containing ring specific data - **/ -void ixgbe_clear_rscctl(struct ixgbe_adapter *adapter, - struct ixgbe_ring *ring) -{ - struct ixgbe_hw *hw = &adapter->hw; - u32 rscctrl; - u8 reg_idx = ring->reg_idx; - - rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(reg_idx)); - rscctrl &= ~IXGBE_RSCCTL_RSCEN; - IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(reg_idx), rscctrl); -} - /** * ixgbe_configure_rscctl - enable RSC for the indicated ring * @adapter: address of board private structure * @index: index of ring to set **/ -void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, +static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, struct ixgbe_ring *ring) { struct ixgbe_hw *hw = &adapter->hw; @@ -7122,6 +7105,98 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc) return 0; } +void ixgbe_do_reset(struct net_device *netdev) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + + if (netif_running(netdev)) + ixgbe_reinit_locked(adapter); + else + ixgbe_reset(adapter); +} + +static u32 ixgbe_fix_features(struct net_device *netdev, u32 data) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + +#ifdef CONFIG_DCB + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) + data &= ~NETIF_F_HW_VLAN_RX; +#endif + + /* return error if RXHASH is being enabled when RSS is not supported */ + if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) + data &= ~NETIF_F_RXHASH; + + /* If Rx checksum is disabled, then RSC/LRO should also be disabled */ + if (!(data & NETIF_F_RXCSUM)) + data &= ~NETIF_F_LRO; + + /* Turn off LRO if not RSC capable or invalid ITR settings */ + if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) { + data &= ~NETIF_F_LRO; + } else if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) && + (adapter->rx_itr_setting != 1 && + adapter->rx_itr_setting > IXGBE_MAX_RSC_INT_RATE)) { + data &= ~NETIF_F_LRO; + e_info(probe, "rx-usecs set too low, not enabling RSC\n"); + } + + return data; +} + +static int ixgbe_set_features(struct net_device *netdev, u32 data) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + bool need_reset = false; + + /* If Rx checksum is disabled, then RSC/LRO should also be disabled */ + if (!(data & NETIF_F_RXCSUM)) + adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED; + else + adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED; + + /* Make sure RSC matches LRO, reset if change */ + if (!!(data & NETIF_F_LRO) != + !!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)) { + adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED; + switch (adapter->hw.mac.type) { + case ixgbe_mac_X540: + case ixgbe_mac_82599EB: + need_reset = true; + break; + default: + break; + } + } + + /* + * Check if Flow Director n-tuple support was enabled or disabled. If + * the state changed, we need to reset. + */ + if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) { + /* turn off ATR, enable perfect filters and reset */ + if (data & NETIF_F_NTUPLE) { + adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; + adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE; + need_reset = true; + } + } else if (!(data & NETIF_F_NTUPLE)) { + /* turn off Flow Director, set ATR and reset */ + adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE; + if ((adapter->flags & IXGBE_FLAG_RSS_ENABLED) && + !(adapter->flags & IXGBE_FLAG_DCB_ENABLED)) + adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; + need_reset = true; + } + + if (need_reset) + ixgbe_do_reset(netdev); + + return 0; + +} + static const struct net_device_ops ixgbe_netdev_ops = { .ndo_open = ixgbe_open, .ndo_stop = ixgbe_close, @@ -7153,6 +7228,8 @@ static const struct net_device_ops ixgbe_netdev_ops = { .ndo_fcoe_disable = ixgbe_fcoe_disable, .ndo_fcoe_get_wwn = ixgbe_fcoe_get_wwn, #endif /* IXGBE_FCOE */ + .ndo_set_features = ixgbe_set_features, + .ndo_fix_features = ixgbe_fix_features, }; static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter, @@ -7420,20 +7497,24 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, netdev->features = NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | - NETIF_F_HW_VLAN_FILTER; + NETIF_F_HW_VLAN_FILTER | + NETIF_F_TSO | + NETIF_F_TSO6 | + NETIF_F_GRO | + NETIF_F_RXHASH | + NETIF_F_RXCSUM; - netdev->features |= NETIF_F_IPV6_CSUM; - netdev->features |= NETIF_F_TSO; - netdev->features |= NETIF_F_TSO6; - netdev->features |= NETIF_F_GRO; - netdev->features |= NETIF_F_RXHASH; + netdev->hw_features = netdev->features; switch (adapter->hw.mac.type) { case ixgbe_mac_82599EB: case ixgbe_mac_X540: netdev->features |= NETIF_F_SCTP_CSUM; + netdev->hw_features |= NETIF_F_SCTP_CSUM | + NETIF_F_NTUPLE; break; default: break; @@ -7472,6 +7553,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, netdev->vlan_features |= NETIF_F_HIGHDMA; } + if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) + netdev->hw_features |= NETIF_F_LRO; if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) netdev->features |= NETIF_F_LRO; @@ -7508,8 +7591,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, if (err) goto err_sw_init; - if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) + if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) { + netdev->hw_features &= ~NETIF_F_RXHASH; netdev->features &= ~NETIF_F_RXHASH; + } switch (pdev->device) { case IXGBE_DEV_ID_82599_SFP: -- cgit v1.2.3-58-ga151