diff options
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_main.c')
| -rw-r--r-- | drivers/net/ixgbe/ixgbe_main.c | 1400 |
1 files changed, 956 insertions, 444 deletions
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index d2f4d5f508b..79aa811c403 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2008 Intel Corporation. + Copyright(c) 1999 - 2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -47,12 +47,13 @@ char ixgbe_driver_name[] = "ixgbe"; static const char ixgbe_driver_string[] = "Intel(R) 10 Gigabit PCI Express Network Driver"; -#define DRV_VERSION "1.3.30-k2" +#define DRV_VERSION "2.0.8-k2" const char ixgbe_driver_version[] = DRV_VERSION; -static char ixgbe_copyright[] = "Copyright (c) 1999-2007 Intel Corporation."; +static char ixgbe_copyright[] = "Copyright (c) 1999-2009 Intel Corporation."; static const struct ixgbe_info *ixgbe_info_tbl[] = { [board_82598] = &ixgbe_82598_info, + [board_82599] = &ixgbe_82599_info, }; /* ixgbe_pci_tbl - PCI Device ID Table @@ -64,6 +65,8 @@ static const struct ixgbe_info *ixgbe_info_tbl[] = { * Class, Class Mask, private data (not used) } */ static struct pci_device_id ixgbe_pci_tbl[] = { + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598), + board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_DUAL_PORT), board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_SINGLE_PORT), @@ -82,6 +85,12 @@ static struct pci_device_id ixgbe_pci_tbl[] = { board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_SFP_LOM), board_82598 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_BX), + board_82598 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KX4), + board_82599 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP), + board_82599 }, /* required last entry */ {0, } @@ -125,17 +134,53 @@ static void ixgbe_get_hw_control(struct ixgbe_adapter *adapter) ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD); } -static void ixgbe_set_ivar(struct ixgbe_adapter *adapter, u16 int_alloc_entry, - u8 msix_vector) +/* + * ixgbe_set_ivar - set the IVAR registers, mapping interrupt causes to vectors + * @adapter: pointer to adapter struct + * @direction: 0 for Rx, 1 for Tx, -1 for other causes + * @queue: queue to map the corresponding interrupt to + * @msix_vector: the vector to map to the corresponding queue + * + */ +static void ixgbe_set_ivar(struct ixgbe_adapter *adapter, s8 direction, + u8 queue, u8 msix_vector) { u32 ivar, index; - - msix_vector |= IXGBE_IVAR_ALLOC_VAL; - index = (int_alloc_entry >> 2) & 0x1F; - ivar = IXGBE_READ_REG(&adapter->hw, IXGBE_IVAR(index)); - ivar &= ~(0xFF << (8 * (int_alloc_entry & 0x3))); - ivar |= (msix_vector << (8 * (int_alloc_entry & 0x3))); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_IVAR(index), ivar); + struct ixgbe_hw *hw = &adapter->hw; + switch (hw->mac.type) { + case ixgbe_mac_82598EB: + msix_vector |= IXGBE_IVAR_ALLOC_VAL; + if (direction == -1) + direction = 0; + index = (((direction * 64) + queue) >> 2) & 0x1F; + ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index)); + ivar &= ~(0xFF << (8 * (queue & 0x3))); + ivar |= (msix_vector << (8 * (queue & 0x3))); + IXGBE_WRITE_REG(hw, IXGBE_IVAR(index), ivar); + break; + case ixgbe_mac_82599EB: + if (direction == -1) { + /* other causes */ + msix_vector |= IXGBE_IVAR_ALLOC_VAL; + index = ((queue & 1) * 8); + ivar = IXGBE_READ_REG(&adapter->hw, IXGBE_IVAR_MISC); + ivar &= ~(0xFF << index); + ivar |= (msix_vector << index); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_IVAR_MISC, ivar); + break; + } else { + /* tx or rx causes */ + msix_vector |= IXGBE_IVAR_ALLOC_VAL; + index = ((16 * (queue & 1)) + (8 * direction)); + ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(queue >> 1)); + ivar &= ~(0xFF << index); + ivar |= (msix_vector << index); + IXGBE_WRITE_REG(hw, IXGBE_IVAR(queue >> 1), ivar); + break; + } + default: + break; + } } static void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter, @@ -200,39 +245,39 @@ static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter, #define DESC_NEEDED (TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) /* skb->data */ + \ MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1) /* for context */ -#define GET_TX_HEAD_FROM_RING(ring) (\ - *(volatile u32 *) \ - ((union ixgbe_adv_tx_desc *)(ring)->desc + (ring)->count)) static void ixgbe_tx_timeout(struct net_device *netdev); /** * ixgbe_clean_tx_irq - Reclaim resources after transmit completes * @adapter: board private structure * @tx_ring: tx ring to clean + * + * returns true if transmit work is done **/ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, struct ixgbe_ring *tx_ring) { - union ixgbe_adv_tx_desc *tx_desc; - struct ixgbe_tx_buffer *tx_buffer_info; struct net_device *netdev = adapter->netdev; - struct sk_buff *skb; - unsigned int i; - u32 head, oldhead; - unsigned int count = 0; + union ixgbe_adv_tx_desc *tx_desc, *eop_desc; + struct ixgbe_tx_buffer *tx_buffer_info; + unsigned int i, eop, count = 0; unsigned int total_bytes = 0, total_packets = 0; - rmb(); - head = GET_TX_HEAD_FROM_RING(tx_ring); - head = le32_to_cpu(head); i = tx_ring->next_to_clean; - while (1) { - while (i != head) { + eop = tx_ring->tx_buffer_info[i].next_to_watch; + 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)) { + bool cleaned = false; + for ( ; !cleaned; count++) { + struct sk_buff *skb; tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); tx_buffer_info = &tx_ring->tx_buffer_info[i]; + cleaned = (i == eop); skb = tx_buffer_info->skb; - if (skb) { + if (cleaned && skb) { unsigned int segs, bytecount; /* gso_segs is currently only valid for tcp */ @@ -247,23 +292,17 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info); + tx_desc->wb.status = 0; + i++; if (i == tx_ring->count) i = 0; - - count++; - if (count == tx_ring->count) - goto done_cleaning; } - oldhead = head; - rmb(); - head = GET_TX_HEAD_FROM_RING(tx_ring); - head = le32_to_cpu(head); - if (head == oldhead) - goto done_cleaning; - } /* while (1) */ - -done_cleaning: + + eop = tx_ring->tx_buffer_info[i].next_to_watch; + eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); + } + tx_ring->next_to_clean = i; #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) @@ -291,17 +330,16 @@ done_cleaning: } /* re-arm the interrupt */ - if ((total_packets >= tx_ring->work_limit) || - (count == tx_ring->count)) + if (count >= tx_ring->work_limit) IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->v_idx); tx_ring->total_bytes += total_bytes; tx_ring->total_packets += total_packets; - tx_ring->stats.bytes += total_bytes; tx_ring->stats.packets += total_packets; + tx_ring->stats.bytes += total_bytes; adapter->net_stats.tx_bytes += total_bytes; adapter->net_stats.tx_packets += total_packets; - return (total_packets ? true : false); + return (count < tx_ring->work_limit); } #ifdef CONFIG_IXGBE_DCA @@ -314,13 +352,19 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter, if (rx_ring->cpu != cpu) { rxctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q)); - rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK; - rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); + if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK; + rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); + } else if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK_82599; + rxctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) << + IXGBE_DCA_RXCTRL_CPUID_SHIFT_82599); + } rxctrl |= IXGBE_DCA_RXCTRL_DESC_DCA_EN; rxctrl |= IXGBE_DCA_RXCTRL_HEAD_DCA_EN; rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_RRO_EN); rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN | - IXGBE_DCA_RXCTRL_DESC_HSRO_EN); + IXGBE_DCA_RXCTRL_DESC_HSRO_EN); IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q), rxctrl); rx_ring->cpu = cpu; } @@ -336,8 +380,14 @@ static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter, if (tx_ring->cpu != cpu) { txctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_DCA_TXCTRL(q)); - txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK; - txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); + if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK; + txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); + } else if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK_82599; + txctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) << + IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599); + } txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN; IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_TXCTRL(q), txctrl); tx_ring->cpu = cpu; @@ -403,23 +453,21 @@ static int __ixgbe_notify_dca(struct device *dev, void *data) * @rx_ring: rx descriptor ring (for a specific queue) to setup * @rx_desc: rx descriptor **/ -static void ixgbe_receive_skb(struct ixgbe_adapter *adapter, +static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector, struct sk_buff *skb, u8 status, - struct ixgbe_ring *ring, union ixgbe_adv_rx_desc *rx_desc) { + struct ixgbe_adapter *adapter = q_vector->adapter; + struct napi_struct *napi = &q_vector->napi; bool is_vlan = (status & IXGBE_RXD_STAT_VP); u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan); - if (adapter->netdev->features & NETIF_F_LRO && - skb->ip_summed == CHECKSUM_UNNECESSARY) { + skb_record_rx_queue(skb, q_vector - &adapter->q_vector[0]); + if (skb->ip_summed == CHECKSUM_UNNECESSARY) { if (adapter->vlgrp && is_vlan && (tag != 0)) - lro_vlan_hwaccel_receive_skb(&ring->lro_mgr, skb, - adapter->vlgrp, tag, - rx_desc); + vlan_gro_receive(napi, adapter->vlgrp, tag, skb); else - lro_receive_skb(&ring->lro_mgr, skb, rx_desc); - ring->lro_used = true; + napi_gro_receive(napi, skb); } else { if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) { if (adapter->vlgrp && is_vlan && (tag != 0)) @@ -470,6 +518,19 @@ static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter, adapter->hw_csum_rx_good++; } +static inline void ixgbe_release_rx_desc(struct ixgbe_hw *hw, + struct ixgbe_ring *rx_ring, u32 val) +{ + /* + * Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + IXGBE_WRITE_REG(hw, IXGBE_RDT(rx_ring->reg_idx), val); +} + /** * ixgbe_alloc_rx_buffers - Replace used receive buffers; packet split * @adapter: address of board private structure @@ -482,6 +543,7 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, union ixgbe_adv_rx_desc *rx_desc; struct ixgbe_rx_buffer *bi; unsigned int i; + unsigned int bufsz = rx_ring->rx_buf_len + NET_IP_ALIGN; i = rx_ring->next_to_use; bi = &rx_ring->rx_buffer_info[i]; @@ -511,9 +573,7 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, if (!bi->skb) { struct sk_buff *skb; - skb = netdev_alloc_skb(adapter->netdev, - (rx_ring->rx_buf_len + - NET_IP_ALIGN)); + skb = netdev_alloc_skb(adapter->netdev, bufsz); if (!skb) { adapter->alloc_rx_buff_failed++; @@ -528,8 +588,7 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, skb_reserve(skb, NET_IP_ALIGN); bi->skb = skb; - bi->dma = pci_map_single(pdev, skb->data, - rx_ring->rx_buf_len, + bi->dma = pci_map_single(pdev, skb->data, bufsz, PCI_DMA_FROMDEVICE); } /* Refresh the desc even if buffer_addrs didn't change because @@ -553,14 +612,7 @@ no_buffers: if (i-- == 0) i = (rx_ring->count - 1); - /* - * Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - writel(i, adapter->hw.hw_addr + rx_ring->tail); + ixgbe_release_rx_desc(&adapter->hw, rx_ring, i); } } @@ -574,10 +626,11 @@ static inline u16 ixgbe_get_pkt_info(union ixgbe_adv_rx_desc *rx_desc) return rx_desc->wb.lower.lo_dword.hs_rss.pkt_info; } -static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter, +static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, struct ixgbe_ring *rx_ring, int *work_done, int work_to_do) { + struct ixgbe_adapter *adapter = q_vector->adapter; struct pci_dev *pdev = adapter->pdev; union ixgbe_adv_rx_desc *rx_desc, *next_rxd; struct ixgbe_rx_buffer *rx_buffer_info, *next_buffer; @@ -678,7 +731,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter, total_rx_packets++; skb->protocol = eth_type_trans(skb, adapter->netdev); - ixgbe_receive_skb(adapter, skb, staterr, rx_ring, rx_desc); + ixgbe_receive_skb(q_vector, skb, staterr, rx_desc); next_desc: rx_desc->wb.upper.status_error = 0; @@ -696,11 +749,6 @@ next_desc: staterr = le32_to_cpu(rx_desc->wb.upper.status_error); } - if (rx_ring->lro_used) { - lro_flush_all(&rx_ring->lro_mgr); - rx_ring->lro_used = false; - } - rx_ring->next_to_clean = i; cleaned_count = IXGBE_DESC_UNUSED(rx_ring); @@ -731,7 +779,8 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; - /* Populate the IVAR table and set the ITR values to the + /* + * Populate the IVAR table and set the ITR values to the * corresponding register. */ for (v_idx = 0; v_idx < q_vectors; v_idx++) { @@ -742,7 +791,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) for (i = 0; i < q_vector->rxr_count; i++) { j = adapter->rx_ring[r_idx].reg_idx; - ixgbe_set_ivar(adapter, IXGBE_IVAR_RX_QUEUE(j), v_idx); + ixgbe_set_ivar(adapter, 0, j, v_idx); r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, r_idx + 1); @@ -752,7 +801,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) for (i = 0; i < q_vector->txr_count; i++) { j = adapter->tx_ring[r_idx].reg_idx; - ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(j), v_idx); + ixgbe_set_ivar(adapter, 1, j, v_idx); r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, r_idx + 1); @@ -761,15 +810,23 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) /* if this is a tx only vector halve the interrupt rate */ if (q_vector->txr_count && !q_vector->rxr_count) q_vector->eitr = (adapter->eitr_param >> 1); - else + else if (q_vector->rxr_count) /* rx only */ q_vector->eitr = adapter->eitr_param; + /* + * 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)); } - ixgbe_set_ivar(adapter, IXGBE_IVAR_OTHER_CAUSES_INDEX, v_idx); + if (adapter->hw.mac.type == ixgbe_mac_82598EB) + ixgbe_set_ivar(adapter, -1, IXGBE_IVAR_OTHER_CAUSES_INDEX, + v_idx); + else if (adapter->hw.mac.type == ixgbe_mac_82599EB) + ixgbe_set_ivar(adapter, -1, 1, v_idx); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx), 1950); /* set up to autoclear timer, and the vectors */ @@ -845,10 +902,35 @@ update_itr_done: return retval; } +/** + * ixgbe_write_eitr - write EITR register in hardware specific way + * @adapter: pointer to adapter struct + * @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 + * when it needs to update EITR registers at runtime. Hardware + * specific quirks/differences are taken care of here. + */ +void ixgbe_write_eitr(struct ixgbe_adapter *adapter, int v_idx, u32 itr_reg) +{ + struct ixgbe_hw *hw = &adapter->hw; + if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + /* must write high and low 16 bits to reset counter */ + itr_reg |= (itr_reg << 16); + } else if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + /* + * set the WDIS bit to not clear the timer bits and cause an + * immediate assertion of the interrupt + */ + itr_reg |= IXGBE_EITR_CNT_WDIS; + } + IXGBE_WRITE_REG(hw, IXGBE_EITR(v_idx), itr_reg); +} + static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) { struct ixgbe_adapter *adapter = q_vector->adapter; - struct ixgbe_hw *hw = &adapter->hw; u32 new_itr; u8 current_itr, ret_itr; int i, r_idx, v_idx = ((void *)q_vector - (void *)(adapter->q_vector)) / @@ -903,14 +985,13 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) if (new_itr != q_vector->eitr) { u32 itr_reg; + + /* save the algorithm value here, not the smoothed one */ + q_vector->eitr = new_itr; /* do an exponential smoothing */ new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100); - q_vector->eitr = new_itr; itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr); - /* must write high and low 16 bits to reset counter */ - DPRINTK(TX_ERR, DEBUG, "writing eitr(%d): %08X\n", v_idx, - itr_reg); - IXGBE_WRITE_REG(hw, IXGBE_EITR(v_idx), itr_reg | (itr_reg)<<16); + ixgbe_write_eitr(adapter, v_idx, itr_reg); } return; @@ -928,6 +1009,24 @@ static void ixgbe_check_fan_failure(struct ixgbe_adapter *adapter, u32 eicr) } } +static void ixgbe_check_sfp_event(struct ixgbe_adapter *adapter, u32 eicr) +{ + struct ixgbe_hw *hw = &adapter->hw; + + if (eicr & IXGBE_EICR_GPI_SDP1) { + /* Clear the interrupt */ + IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1); + schedule_work(&adapter->multispeed_fiber_task); + } else if (eicr & IXGBE_EICR_GPI_SDP2) { + /* Clear the interrupt */ + IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2); + schedule_work(&adapter->sfp_config_module_task); + } else { + /* Interrupt isn't for us... */ + return; + } +} + static void ixgbe_check_lsc(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; @@ -946,13 +1045,25 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) struct net_device *netdev = data; struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; - u32 eicr = IXGBE_READ_REG(hw, IXGBE_EICR); + u32 eicr; + + /* + * Workaround for Silicon errata. Use clear-by-write instead + * of clear-by-read. Reading with EICS will return the + * interrupt causes without clearing, which later be done + * with the write to EICR. + */ + eicr = IXGBE_READ_REG(hw, IXGBE_EICS); + IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr); if (eicr & IXGBE_EICR_LSC) ixgbe_check_lsc(adapter); - ixgbe_check_fan_failure(adapter, eicr); + if (hw->mac.type == ixgbe_mac_82598EB) + ixgbe_check_fan_failure(adapter, eicr); + if (hw->mac.type == ixgbe_mac_82599EB) + ixgbe_check_sfp_event(adapter, eicr); if (!test_bit(__IXGBE_DOWN, &adapter->state)) IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER); @@ -1015,7 +1126,7 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data) rx_ring = &(adapter->rx_ring[r_idx]); /* disable interrupts on this vector only */ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rx_ring->v_idx); - netif_rx_schedule(&q_vector->napi); + napi_schedule(&q_vector->napi); return IRQ_HANDLED; } @@ -1052,12 +1163,12 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget) ixgbe_update_rx_dca(adapter, rx_ring); #endif - ixgbe_clean_rx_irq(adapter, rx_ring, &work_done, budget); + ixgbe_clean_rx_irq(q_vector, rx_ring, &work_done, budget); /* If all Rx work done, exit the polling mode */ if (work_done < budget) { - netif_rx_complete(napi); - if (adapter->itr_setting & 3) + napi_complete(napi); + if (adapter->itr_setting & 1) ixgbe_set_itr_msix(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, rx_ring->v_idx); @@ -1095,7 +1206,7 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget) if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) ixgbe_update_rx_dca(adapter, rx_ring); #endif - ixgbe_clean_rx_irq(adapter, 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 + 1); @@ -1105,8 +1216,8 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget) rx_ring = &(adapter->rx_ring[r_idx]); /* If all Rx work done, exit the polling mode */ if (work_done < budget) { - netif_rx_complete(napi); - if (adapter->itr_setting & 3) + napi_complete(napi); + if (adapter->itr_setting & 1) ixgbe_set_itr_msix(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, enable_mask); @@ -1276,7 +1387,6 @@ out: static void ixgbe_set_itr(struct ixgbe_adapter *adapter) { - struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_q_vector *q_vector = adapter->q_vector; u8 current_itr; u32 new_itr = q_vector->eitr; @@ -1311,35 +1421,19 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter) if (new_itr != q_vector->eitr) { u32 itr_reg; + + /* save the algorithm value here, not the smoothed one */ + q_vector->eitr = new_itr; /* do an exponential smoothing */ new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100); - q_vector->eitr = new_itr; itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr); - /* must write high and low 16 bits to reset counter */ - IXGBE_WRITE_REG(hw, IXGBE_EITR(0), itr_reg | (itr_reg)<<16); + ixgbe_write_eitr(adapter, 0, itr_reg); } return; } /** - * ixgbe_irq_disable - Mask off interrupt generation on the NIC - * @adapter: board private structure - **/ -static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) -{ - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); - IXGBE_WRITE_FLUSH(&adapter->hw); - if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { - int i; - for (i = 0; i < adapter->num_msix_vectors; i++) - synchronize_irq(adapter->msix_entries[i].vector); - } else { - synchronize_irq(adapter->pdev->irq); - } -} - -/** * ixgbe_irq_enable - Enable default interrupt generation settings * @adapter: board private structure **/ @@ -1349,7 +1443,21 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) mask = IXGBE_EIMS_ENABLE_MASK; if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) mask |= IXGBE_EIMS_GPI_SDP1; + if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + mask |= IXGBE_EIMS_ECC; + mask |= IXGBE_EIMS_GPI_SDP1; + mask |= IXGBE_EIMS_GPI_SDP2; + } + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); + if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + /* enable the rest of the queue vectors */ + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(1), + (IXGBE_EIMS_RTX_QUEUE << 16)); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(2), + ((IXGBE_EIMS_RTX_QUEUE << 16) | + IXGBE_EIMS_RTX_QUEUE)); + } IXGBE_WRITE_FLUSH(&adapter->hw); } @@ -1365,6 +1473,12 @@ static irqreturn_t ixgbe_intr(int irq, void *data) struct ixgbe_hw *hw = &adapter->hw; u32 eicr; + /* + * Workaround for silicon errata. Mask the interrupts + * before the read of EICR. + */ + IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); + /* for NAPI, using EIAM to auto-mask tx/rx interrupt bits on read * therefore no explict interrupt disable is necessary */ eicr = IXGBE_READ_REG(hw, IXGBE_EICR); @@ -1379,15 +1493,18 @@ static irqreturn_t ixgbe_intr(int irq, void *data) if (eicr & IXGBE_EICR_LSC) ixgbe_check_lsc(adapter); + if (hw->mac.type == ixgbe_mac_82599EB) + ixgbe_check_sfp_event(adapter, eicr); + ixgbe_check_fan_failure(adapter, eicr); - if (netif_rx_schedule_prep(&adapter->q_vector[0].napi)) { + if (napi_schedule_prep(&adapter->q_vector[0].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 */ - __netif_rx_schedule(&adapter->q_vector[0].napi); + __napi_schedule(&adapter->q_vector[0].napi); } return IRQ_HANDLED; @@ -1459,6 +1576,39 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter) } /** + * ixgbe_irq_disable - Mask off interrupt generation on the NIC + * @adapter: board private structure + **/ +static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) +{ + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); + if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(2), ~0); + } + IXGBE_WRITE_FLUSH(&adapter->hw); + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { + int i; + for (i = 0; i < adapter->num_msix_vectors; i++) + synchronize_irq(adapter->msix_entries[i].vector); + } else { + synchronize_irq(adapter->pdev->irq); + } +} + +static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter) +{ + u32 mask = IXGBE_EIMS_RTX_QUEUE; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); + if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(1), mask << 16); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(2), + (mask << 16 | mask)); + } + /* skip the flush */ +} + +/** * ixgbe_configure_msi_and_legacy - Initialize PIN (INTA...) and MSI interrupts * **/ @@ -1469,8 +1619,8 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_EITR(0), 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_TX_QUEUE(0), 0); + ixgbe_set_ivar(adapter, 0, 0, 0); + ixgbe_set_ivar(adapter, 1, 0, 0); map_vector_to_rxq(adapter, 0, 0); map_vector_to_txq(adapter, 0, 0); @@ -1486,7 +1636,7 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter) **/ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter) { - u64 tdba, tdwba; + u64 tdba; struct ixgbe_hw *hw = &adapter->hw; u32 i, j, tdlen, txctrl; @@ -1499,11 +1649,6 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j), (tdba & DMA_32BIT_MASK)); IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32)); - tdwba = ring->dma + - (ring->count * sizeof(union ixgbe_adv_tx_desc)); - tdwba |= IXGBE_TDWBAL_HEAD_WB_ENABLE; - IXGBE_WRITE_REG(hw, IXGBE_TDWBAL(j), tdwba & DMA_32BIT_MASK); - IXGBE_WRITE_REG(hw, IXGBE_TDWBAH(j), (tdwba >> 32)); IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j), tdlen); IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0); IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0); @@ -1516,26 +1661,25 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter) txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN; IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl); } + if (hw->mac.type == ixgbe_mac_82599EB) { + /* We enable 8 traffic classes, DCB only */ + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) + IXGBE_WRITE_REG(hw, IXGBE_MTQC, (IXGBE_MTQC_RT_ENA | + IXGBE_MTQC_8TC_8TQ)); + } } -#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2 +#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2 static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index) { struct ixgbe_ring *rx_ring; u32 srrctl; - int queue0; + int queue0 = 0; unsigned long mask; - /* program one srrctl register per VMDq index */ - if (adapter->flags & IXGBE_FLAG_VMDQ_ENABLED) { - long shift, len; - mask = (unsigned long) adapter->ring_feature[RING_F_RSS].mask; - len = sizeof(adapter->ring_feature[RING_F_VMDQ].mask) * 8; - shift = find_first_bit(&mask, len); - queue0 = index & mask; - index = (index & mask) >> shift; - /* program one srrctl per RSS queue since RDRXCTL.MVMEN is enabled */ + if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + queue0 = index; } else { mask = (unsigned long) adapter->ring_feature[RING_F_RSS].mask; queue0 = index & mask; @@ -1550,7 +1694,14 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index) srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK; if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { - srrctl |= IXGBE_RXBUFFER_2048 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; + u16 bufsz = IXGBE_RXBUFFER_2048; + /* grow the amount we can receive on large page machines */ + if (bufsz < (PAGE_SIZE / 2)) + bufsz = (PAGE_SIZE / 2); + /* cap the bufsz at our largest descriptor size */ + bufsz = min((u16)IXGBE_MAX_RXBUFFER, bufsz); + + srrctl |= bufsz >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; srrctl |= IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS; srrctl |= ((IXGBE_RX_HDR_SIZE << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) & @@ -1565,39 +1716,10 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index) srrctl |= rx_ring->rx_buf_len >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; } - IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(index), srrctl); -} -/** - * ixgbe_get_skb_hdr - helper function for LRO header processing - * @skb: pointer to sk_buff to be added to LRO packet - * @iphdr: pointer to ip header structure - * @tcph: pointer to tcp header structure - * @hdr_flags: pointer to header flags - * @priv: private data - **/ -static int ixgbe_get_skb_hdr(struct sk_buff *skb, void **iphdr, void **tcph, - u64 *hdr_flags, void *priv) -{ - union ixgbe_adv_rx_desc *rx_desc = priv; - - /* Verify that this is a valid IPv4 TCP packet */ - if (!((ixgbe_get_pkt_info(rx_desc) & IXGBE_RXDADV_PKTTYPE_IPV4) && - (ixgbe_get_pkt_info(rx_desc) & IXGBE_RXDADV_PKTTYPE_TCP))) - return -1; - - /* Set network headers */ - skb_reset_network_header(skb); - skb_set_transport_header(skb, ip_hdrlen(skb)); - *iphdr = ip_hdr(skb); - *tcph = tcp_hdr(skb); - *hdr_flags = LRO_IPV4 | LRO_TCP; - return 0; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(index), srrctl); } -#define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \ - (((S) & (PAGE_SIZE - 1)) ? 1 : 0)) - /** * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset * @adapter: board private structure @@ -1616,8 +1738,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) 0xA54F2BEC, 0xEA49AF7C, 0xE214AD3D, 0xB855AABE, 0x6A3E67EA, 0x14364D17, 0x3BED200D}; u32 fctrl, hlreg0; - u32 pages; - u32 reta = 0, mrqc; + u32 reta = 0, mrqc = 0; u32 rdrxctl; int rx_buf_len; @@ -1627,6 +1748,14 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) /* Set the RX buffer length according to the mode */ if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { rx_buf_len = IXGBE_RX_HDR_SIZE; + if (hw->mac.type == ixgbe_mac_82599EB) { + /* PSRTYPE must be initialized in 82599 */ + u32 psrtype = IXGBE_PSRTYPE_TCPHDR | + IXGBE_PSRTYPE_UDPHDR | + IXGBE_PSRTYPE_IPV4HDR | + IXGBE_PSRTYPE_IPV6HDR; + IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype); + } } else { if (netdev->mtu <= ETH_DATA_LEN) rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE; @@ -1637,6 +1766,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); fctrl |= IXGBE_FCTRL_BAM; fctrl |= IXGBE_FCTRL_DPF; /* discard pause frames when FC enabled */ + fctrl |= IXGBE_FCTRL_PMCF; IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl); hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); @@ -1646,8 +1776,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) hlreg0 |= IXGBE_HLREG0_JUMBOEN; IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); - pages = PAGE_USE_COUNT(adapter->netdev->mtu); - rdlen = adapter->rx_ring[0].count * sizeof(union ixgbe_adv_rx_desc); /* disable receives while setting up the descriptors */ rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); @@ -1666,37 +1794,44 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) adapter->rx_ring[i].head = IXGBE_RDH(j); adapter->rx_ring[i].tail = IXGBE_RDT(j); adapter->rx_ring[i].rx_buf_len = rx_buf_len; - /* Intitial LRO Settings */ - adapter->rx_ring[i].lro_mgr.max_aggr = IXGBE_MAX_LRO_AGGREGATE; - adapter->rx_ring[i].lro_mgr.max_desc = IXGBE_MAX_LRO_DESCRIPTORS; - adapter->rx_ring[i].lro_mgr.get_skb_header = ixgbe_get_skb_hdr; - adapter->rx_ring[i].lro_mgr.features = LRO_F_EXTRACT_VLAN_ID; - if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) - adapter->rx_ring[i].lro_mgr.features |= LRO_F_NAPI; - adapter->rx_ring[i].lro_mgr.dev = adapter->netdev; - adapter->rx_ring[i].lro_mgr.ip_summed = CHECKSUM_UNNECESSARY; - adapter->rx_ring[i].lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; ixgbe_configure_srrctl(adapter, j); } - /* - * For VMDq support of different descriptor types or - * buffer sizes through the use of multiple SRRCTL - * registers, RDRXCTL.MVMEN must be set to 1 - * - * also, the manual doesn't mention it clearly but DCA hints - * will only use queue 0's tags unless this bit is set. Side - * effects of setting this bit are only that SRRCTL must be - * fully programmed [0..15] - */ - if (adapter->flags & - (IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_VMDQ_ENABLED)) { + if (hw->mac.type == ixgbe_mac_82598EB) { + /* + * For VMDq support of different descriptor types or + * buffer sizes through the use of multiple SRRCTL + * registers, RDRXCTL.MVMEN must be set to 1 + * + * also, the manual doesn't mention it clearly but DCA hints + * will only use queue 0's tags unless this bit is set. Side + * effects of setting this bit are only that SRRCTL must be + * fully programmed [0..15] + */ rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); rdrxctl |= IXGBE_RDRXCTL_MVMEN; IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl); } + /* Program MRQC for the distribution of queues */ + if (hw->mac.type == ixgbe_mac_82599EB) { + int mask = adapter->flags & ( + IXGBE_FLAG_RSS_ENABLED + | IXGBE_FLAG_DCB_ENABLED + ); + + switch (mask) { + case (IXGBE_FLAG_RSS_ENABLED): + mrqc = IXGBE_MRQC_RSSEN; + break; + case (IXGBE_FLAG_DCB_ENABLED): + mrqc = IXGBE_MRQC_RT8TCEN; + break; + default: + break; + } + } if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { /* Fill out redirection table */ for (i = 0, j = 0; i < 128; i++, j++) { @@ -1713,19 +1848,17 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) for (i = 0; i < 10; i++) IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), seed[i]); - mrqc = IXGBE_MRQC_RSSEN + if (hw->mac.type == ixgbe_mac_82598EB) + mrqc |= IXGBE_MRQC_RSSEN; /* Perform hash on these packet types */ - | IXGBE_MRQC_RSS_FIELD_IPV4 - | IXGBE_MRQC_RSS_FIELD_IPV4_TCP - | IXGBE_MRQC_RSS_FIELD_IPV4_UDP - | IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP - | IXGBE_MRQC_RSS_FIELD_IPV6_EX - | IXGBE_MRQC_RSS_FIELD_IPV6 - | IXGBE_MRQC_RSS_FIELD_IPV6_TCP - | IXGBE_MRQC_RSS_FIELD_IPV6_UDP - | IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP; - IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); + mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4 + | IXGBE_MRQC_RSS_FIELD_IPV4_TCP + | IXGBE_MRQC_RSS_FIELD_IPV4_UDP + | IXGBE_MRQC_RSS_FIELD_IPV6 + | IXGBE_MRQC_RSS_FIELD_IPV6_TCP + | IXGBE_MRQC_RSS_FIELD_IPV6_UDP; } + IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); |
