diff options
author | Auke Kok <auke-jan.h.kok@intel.com> | 2007-09-15 14:07:45 -0700 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 16:51:02 -0700 |
commit | 9a799d71034c4e2b168740c8a8530591011313d5 (patch) | |
tree | ce2dedefe2b101e1e81105a7ca8e3e61321193b6 /drivers/net | |
parent | dc029ad97f267cbd1c2e978a443eb5ae93a55328 (diff) |
ixgbe: driver for Intel(R) 82598 PCI-Express 10GbE adapters (v4)
This patch adds support for the Intel 82598 PCI-Express 10GbE
chipset. Devices will be available on the market soon.
This version of the driver is largely the same as the last release:
* Driver uses a single RX and single TX queue, each using 1 MSI-X
irq vector.
* Driver runs in NAPI mode only
* Driver is largely multiqueue-ready (TM)
Changes since 20070803:
* removed wrappers for hardware functions
* incorporated e1000e-style HW api reorganization code
* sparse/checkpatch cleanups, namespace cleanups
* driver prints out extra debugging information at load time
identifying adapter board number, mac, phy types
* removed ixgbe_api.c, ixgbe_api.h, ixgbe_osdep.h
* driver update to 1.1.18
* removed ixgbe.txt which contained no useful info anymore
[ Integrated napi_struct changes from Auke as well... -DaveM ]
Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com>
Signed-off-by: Ayyappan Veeraiyan <ayyappan.veeraiyan@intel.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/Kconfig | 27 | ||||
-rw-r--r-- | drivers/net/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/ixgbe/Makefile | 36 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe.h | 259 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_82598.c | 589 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_common.c | 1175 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_common.h | 86 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_ethtool.c | 943 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_main.c | 2873 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_phy.c | 494 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_phy.h | 50 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_type.h | 1332 |
12 files changed, 7863 insertions, 2 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index eeac2f49aae..76db0bc9452 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2518,12 +2518,35 @@ config EHEA To compile the driver as a module, choose M here. The module will be called ehea. +config IXGBE + tristate "Intel(R) 10GbE PCI Express adapters support" + depends on PCI + ---help--- + This driver supports Intel(R) 10GbE PCI Express family of + adapters. For more information on how to identify your adapter, go + to the Adapter & Driver ID Guide at: + + <http://support.intel.com/support/network/adapter/pro100/21397.htm> + + For general information and support, go to the Intel support + website at: + + <http://support.intel.com> + + More specific information on configuring the driver is in + <file:Documentation/networking/ixgbe.txt>. + + To compile this driver as a module, choose M here and read + <file:Documentation/networking/net-modules.txt>. The module + will be called ixgbe. + config IXGB tristate "Intel(R) PRO/10GbE support" depends on PCI ---help--- - This driver supports Intel(R) PRO/10GbE family of - adapters. For more information on how to identify your adapter, go + This driver supports Intel(R) PRO/10GbE family of adapters for + PCI-X type cards. For PCI-E type cards, use the "ixgbe" driver + instead. For more information on how to identify your adapter, go to the Adapter & Driver ID Guide at: <http://support.intel.com/support/network/adapter/pro100/21397.htm> diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 0d2b4bee587..c23ffdbe259 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_E1000) += e1000/ obj-$(CONFIG_E1000E) += e1000e/ obj-$(CONFIG_IBM_EMAC) += ibm_emac/ +obj-$(CONFIG_IXGBE) += ixgbe/ obj-$(CONFIG_IXGB) += ixgb/ obj-$(CONFIG_CHELSIO_T1) += chelsio/ obj-$(CONFIG_CHELSIO_T3) += cxgb3/ diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile new file mode 100644 index 00000000000..ccd83d9f579 --- /dev/null +++ b/drivers/net/ixgbe/Makefile @@ -0,0 +1,36 @@ +################################################################################ +# +# Intel 10 Gigabit PCI Express Linux driver +# Copyright(c) 1999 - 2007 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, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +# +# The full GNU General Public License is included in this distribution in +# the file called "COPYING". +# +# Contact Information: +# Linux NICS <linux.nics@intel.com> +# e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> +# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +# +################################################################################ + +# +# Makefile for the Intel(R) 10GbE PCI Express ethernet driver +# + +obj-$(CONFIG_IXGBE) += ixgbe.o + +ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \ + ixgbe_82598.o ixgbe_phy.o diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h new file mode 100644 index 00000000000..c160a7d91e2 --- /dev/null +++ b/drivers/net/ixgbe/ixgbe.h @@ -0,0 +1,259 @@ +/******************************************************************************* + + Intel 10 Gigabit PCI Express Linux driver + Copyright(c) 1999 - 2007 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, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS <linux.nics@intel.com> + e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _IXGBE_H_ +#define _IXGBE_H_ + +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/netdevice.h> + +#include "ixgbe_type.h" +#include "ixgbe_common.h" + + +#define IXGBE_ERR(args...) printk(KERN_ERR "ixgbe: " args) + +#define PFX "ixgbe: " +#define DPRINTK(nlevel, klevel, fmt, args...) \ + ((void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \ + printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \ + __FUNCTION__ , ## args))) + +/* TX/RX descriptor defines */ +#define IXGBE_DEFAULT_TXD 1024 +#define IXGBE_MAX_TXD 4096 +#define IXGBE_MIN_TXD 64 + +#define IXGBE_DEFAULT_RXD 1024 +#define IXGBE_MAX_RXD 4096 +#define IXGBE_MIN_RXD 64 + +#define IXGBE_DEFAULT_RXQ 1 +#define IXGBE_MAX_RXQ 1 +#define IXGBE_MIN_RXQ 1 + +#define IXGBE_DEFAULT_ITR_RX_USECS 125 /* 8k irqs/sec */ +#define IXGBE_DEFAULT_ITR_TX_USECS 250 /* 4k irqs/sec */ +#define IXGBE_MIN_ITR_USECS 100 /* 500k irqs/sec */ +#define IXGBE_MAX_ITR_USECS 10000 /* 100 irqs/sec */ + +/* flow control */ +#define IXGBE_DEFAULT_FCRTL 0x10000 +#define IXGBE_MIN_FCRTL 0 +#define IXGBE_MAX_FCRTL 0x7FF80 +#define IXGBE_DEFAULT_FCRTH 0x20000 +#define IXGBE_MIN_FCRTH 0 +#define IXGBE_MAX_FCRTH 0x7FFF0 +#define IXGBE_DEFAULT_FCPAUSE 0x6800 /* may be too long */ +#define IXGBE_MIN_FCPAUSE 0 +#define IXGBE_MAX_FCPAUSE 0xFFFF + +/* Supported Rx Buffer Sizes */ +#define IXGBE_RXBUFFER_64 64 /* Used for packet split */ +#define IXGBE_RXBUFFER_128 128 /* Used for packet split */ +#define IXGBE_RXBUFFER_256 256 /* Used for packet split */ +#define IXGBE_RXBUFFER_2048 2048 + +#define IXGBE_RX_HDR_SIZE IXGBE_RXBUFFER_256 + +#define MAXIMUM_ETHERNET_VLAN_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN) + +/* How many Tx Descriptors do we need to call netif_wake_queue? */ +#define IXGBE_TX_QUEUE_WAKE 16 + +/* How many Rx Buffers do we bundle into one write to the hardware ? */ +#define IXGBE_RX_BUFFER_WRITE 16 /* Must be power of 2 */ + +#define IXGBE_TX_FLAGS_CSUM (u32)(1) +#define IXGBE_TX_FLAGS_VLAN (u32)(1 << 1) +#define IXGBE_TX_FLAGS_TSO (u32)(1 << 2) +#define IXGBE_TX_FLAGS_IPV4 (u32)(1 << 3) +#define IXGBE_TX_FLAGS_VLAN_MASK 0xffff0000 +#define IXGBE_TX_FLAGS_VLAN_SHIFT 16 + +/* wrapper around a pointer to a socket buffer, + * so a DMA handle can be stored along with the buffer */ +struct ixgbe_tx_buffer { + struct sk_buff *skb; + dma_addr_t dma; + unsigned long time_stamp; + u16 length; + u16 next_to_watch; +}; + +struct ixgbe_rx_buffer { + struct sk_buff *skb; + dma_addr_t dma; + struct page *page; + dma_addr_t page_dma; +}; + +struct ixgbe_queue_stats { + u64 packets; + u64 bytes; +}; + +struct ixgbe_ring { + struct ixgbe_adapter *adapter; /* backlink */ + void *desc; /* descriptor ring memory */ + dma_addr_t dma; /* phys. address of descriptor ring */ + unsigned int size; /* length in bytes */ + unsigned int count; /* amount of descriptors */ + unsigned int next_to_use; + unsigned int next_to_clean; + + union { + struct ixgbe_tx_buffer *tx_buffer_info; + struct ixgbe_rx_buffer *rx_buffer_info; + }; + + u16 head; + u16 tail; + + /* To protect race between sender and clean_tx_irq */ + spinlock_t tx_lock; + + struct ixgbe_queue_stats stats; + + u32 eims_value; + u16 itr_register; + + char name[IFNAMSIZ + 5]; + u16 work_limit; /* max work per interrupt */ +}; + +/* Helper macros to switch between ints/sec and what the register uses. + * And yes, it's the same math going both ways. + */ +#define EITR_INTS_PER_SEC_TO_REG(_eitr) \ + ((_eitr) ? (1000000000 / ((_eitr) * 256)) : 0) +#define EITR_REG_TO_INTS_PER_SEC EITR_INTS_PER_SEC_TO_REG + +#define IXGBE_DESC_UNUSED(R) \ + ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \ + (R)->next_to_clean - (R)->next_to_use - 1) + +#define IXGBE_RX_DESC_ADV(R, i) \ + (&(((union ixgbe_adv_rx_desc *)((R).desc))[i])) +#define IXGBE_TX_DESC_ADV(R, i) \ + (&(((union ixgbe_adv_tx_desc *)((R).desc))[i])) +#define IXGBE_TX_CTXTDESC_ADV(R, i) \ + (&(((struct ixgbe_adv_tx_context_desc *)((R).desc))[i])) + +#define IXGBE_MAX_JUMBO_FRAME_SIZE 16128 + +/* board specific private data structure */ +struct ixgbe_adapter { + struct timer_list watchdog_timer; + struct vlan_group *vlgrp; + u16 bd_number; + u16 rx_buf_len; + atomic_t irq_sem; + struct work_struct reset_task; + + /* TX */ + struct ixgbe_ring *tx_ring; /* One per active queue */ + struct napi_struct napi; + u64 restart_queue; + u64 lsc_int; + u64 hw_tso_ctxt; + u64 hw_tso6_ctxt; + u32 tx_timeout_count; + bool detect_tx_hung; + + /* RX */ + struct ixgbe_ring *rx_ring; /* One per active queue */ + u64 hw_csum_tx_good; + u64 hw_csum_rx_error; + u64 hw_csum_rx_good; + u64 non_eop_descs; + int num_tx_queues; + int num_rx_queues; + struct msix_entry *msix_entries; + + u64 rx_hdr_split; + u32 alloc_rx_page_failed; + u32 alloc_rx_buff_failed; + + u32 flags; +#define IXGBE_FLAG_RX_CSUM_ENABLED (u32)(1) +#define IXGBE_FLAG_MSI_ENABLED (u32)(1 << 1) +#define IXGBE_FLAG_MSIX_ENABLED (u32)(1 << 2) +#define IXGBE_FLAG_RX_PS_ENABLED (u32)(1 << 3) +#define IXGBE_FLAG_IN_NETPOLL (u32)(1 << 4) + + /* Interrupt Throttle Rate */ + u32 rx_eitr; + u32 tx_eitr; + + /* OS defined structs */ + struct net_device *netdev; + struct pci_dev *pdev; + struct net_device_stats net_stats; + + /* structs defined in ixgbe_hw.h */ + struct ixgbe_hw hw; + u16 msg_enable; + struct ixgbe_hw_stats stats; + char lsc_name[IFNAMSIZ + 5]; + + unsigned long state; + u64 tx_busy; +}; + +enum ixbge_state_t { + __IXGBE_TESTING, + __IXGBE_RESETTING, + __IXGBE_DOWN +}; + +enum ixgbe_boards { + board_82598AF, + board_82598EB, + board_82598AT, +}; + +extern struct ixgbe_info ixgbe_82598AF_info; +extern struct ixgbe_info ixgbe_82598EB_info; +extern struct ixgbe_info ixgbe_82598AT_info; + +extern char ixgbe_driver_name[]; +extern char ixgbe_driver_version[]; + +extern int ixgbe_up(struct ixgbe_adapter *adapter); +extern void ixgbe_down(struct ixgbe_adapter *adapter); +extern void ixgbe_reset(struct ixgbe_adapter *adapter); +extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); +extern void ixgbe_set_ethtool_ops(struct net_device *netdev); +extern int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter, + struct ixgbe_ring *rxdr); +extern int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter, + struct ixgbe_ring *txdr); + +#endif /* _IXGBE_H_ */ diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c new file mode 100644 index 00000000000..00ee20125ca --- /dev/null +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -0,0 +1,589 @@ +/******************************************************************************* + + Intel 10 Gigabit PCI Express Linux driver + Copyright(c) 1999 - 2007 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, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS <linux.nics@intel.com> + e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include <linux/pci.h> +#include <linux/delay.h> +#include <linux/sched.h> + +#include "ixgbe_type.h" +#include "ixgbe_common.h" +#include "ixgbe_phy.h" + +#define IXGBE_82598_MAX_TX_QUEUES 32 +#define IXGBE_82598_MAX_RX_QUEUES 64 +#define IXGBE_82598_RAR_ENTRIES 16 + +static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw); +static s32 ixgbe_get_link_settings_82598(struct ixgbe_hw *hw, u32 *speed, + bool *autoneg); +static s32 ixgbe_get_copper_link_settings_82598(struct ixgbe_hw *hw, + u32 *speed, bool *autoneg); +static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw); +static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw); +static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, u32 *speed, + bool *link_up); +static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, u32 speed, + bool autoneg, + bool autoneg_wait_to_complete); +static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw); +static s32 ixgbe_check_copper_link_82598(struct ixgbe_hw *hw, u32 *speed, + bool *link_up); +static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, u32 speed, + bool autoneg, + bool autoneg_wait_to_complete); +static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw); + + +static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw) +{ + hw->mac.num_rx_queues = IXGBE_82598_MAX_TX_QUEUES; + hw->mac.num_tx_queues = IXGBE_82598_MAX_RX_QUEUES; + hw->mac.num_rx_addrs = IXGBE_82598_RAR_ENTRIES; + + return 0; +} + +/** + * ixgbe_get_link_settings_82598 - Determines default link settings + * @hw: pointer to hardware structure + * @speed: pointer to link speed + * @autoneg: boolean auto-negotiation value + * + * Determines the default link settings by reading the AUTOC register. + **/ +static s32 ixgbe_get_link_settings_82598(struct ixgbe_hw *hw, u32 *speed, + bool *autoneg) +{ + s32 status = 0; + s32 autoc_reg; + + autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); + + if (hw->mac.link_settings_loaded) { + autoc_reg &= ~IXGBE_AUTOC_LMS_ATTACH_TYPE; + autoc_reg &= ~IXGBE_AUTOC_LMS_MASK; + autoc_reg |= hw->mac.link_attach_type; + autoc_reg |= hw->mac.link_mode_select; + } + + switch (autoc_reg & IXGBE_AUTOC_LMS_MASK) { + case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: + *speed = IXGBE_LINK_SPEED_1GB_FULL; + *autoneg = false; + break; + + case IXGBE_AUTOC_LMS_10G_LINK_NO_AN: + *speed = IXGBE_LINK_SPEED_10GB_FULL; + *autoneg = false; + break; + + case IXGBE_AUTOC_LMS_1G_AN: + *speed = IXGBE_LINK_SPEED_1GB_FULL; + *autoneg = true; + break; + + case IXGBE_AUTOC_LMS_KX4_AN: + case IXGBE_AUTOC_LMS_KX4_AN_1G_AN: + *speed = IXGBE_LINK_SPEED_UNKNOWN; + if (autoc_reg & IXGBE_AUTOC_KX4_SUPP) + *speed |= IXGBE_LINK_SPEED_10GB_FULL; + if (autoc_reg & IXGBE_AUTOC_KX_SUPP) + *speed |= IXGBE_LINK_SPEED_1GB_FULL; + *autoneg = true; + break; + + default: + status = IXGBE_ERR_LINK_SETUP; + break; + } + + return status; +} + +/** + * ixgbe_get_copper_link_settings_82598 - Determines default link settings + * @hw: pointer to hardware structure + * @speed: pointer to link speed + * @autoneg: boolean auto-negotiation value + * + * Determines the default link settings by reading the AUTOC register. + **/ +static s32 ixgbe_get_copper_link_settings_82598(struct ixgbe_hw *hw, + u32 *speed, bool *autoneg) +{ + s32 status = IXGBE_ERR_LINK_SETUP; + u16 speed_ability; + + *speed = 0; + *autoneg = true; + + status = ixgbe_read_phy_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY, + IXGBE_MDIO_PMA_PMD_DEV_TYPE, + &speed_ability); + + if (status == 0) { + if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G) + *speed |= IXGBE_LINK_SPEED_10GB_FULL; + if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G) + *speed |= IXGBE_LINK_SPEED_1GB_FULL; + } + + return status; +} + +/** + * ixgbe_get_media_type_82598 - Determines media type + * @hw: pointer to hardware structure + * + * Returns the media type (fiber, copper, backplane) + **/ +static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) +{ + enum ixgbe_media_type media_type; + + /* Media type for I82598 is based on device ID */ + switch (hw->device_id) { + case IXGBE_DEV_ID_82598AF_DUAL_PORT: + case IXGBE_DEV_ID_82598AF_SINGLE_PORT: + case IXGBE_DEV_ID_82598EB_CX4: + media_type = ixgbe_media_type_fiber; + break; + case IXGBE_DEV_ID_82598AT_DUAL_PORT: + media_type = ixgbe_media_type_copper; + break; + default: + media_type = ixgbe_media_type_unknown; + break; + } + + return media_type; +} + +/** + * ixgbe_setup_mac_link_82598 - Configures MAC link settings + * @hw: pointer to hardware structure + * + * Configures link settings based on values in the ixgbe_hw struct. + * Restarts the link. Performs autonegotiation if needed. + **/ +static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw) +{ + u32 autoc_reg; + u32 links_reg; + u32 i; + s32 status = 0; + + autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); + + if (hw->mac.link_settings_loaded) { + autoc_reg &= ~IXGBE_AUTOC_LMS_ATTACH_TYPE; + autoc_reg &= ~IXGBE_AUTOC_LMS_MASK; + autoc_reg |= hw->mac.link_attach_type; + autoc_reg |= hw->mac.link_mode_select; + + IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); + msleep(50); + } + + /* Restart link */ + autoc_reg |= IXGBE_AUTOC_AN_RESTART; + IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); + + /* Only poll for autoneg to complete if specified to do so */ + if (hw->phy.autoneg_wait_to_complete) { + if (hw->mac.link_mode_select == IXGBE_AUTOC_LMS_KX4_AN || + hw->mac.link_mode_select == IXGBE_AUTOC_LMS_KX4_AN_1G_AN) { + links_reg = 0; /* Just in case Autoneg time = 0 */ + for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) { + links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); + if (links_reg & IXGBE_LINKS_KX_AN_COMP) + break; + msleep(100); + } + if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) { + status = IXGBE_ERR_AUTONEG_NOT_COMPLETE; + hw_dbg(hw, + "Autonegotiation did not complete.\n"); + } + } + } + + /* + * We want to save off the original Flow Control configuration just in + * case we get disconnected and then reconnected into a different hub + * or switch with different Flow Control capabilities. + */ + hw->fc.type = hw->fc.original_type; + ixgbe_setup_fc(hw, 0); + + /* Add delay to filter out noises during initial link setup */ + msleep(50); + + return status; +} + +/** + * ixgbe_check_mac_link_82598 - Get link/speed status + * @hw: pointer to hardware structure + * @speed: pointer to link speed + * @link_up: true is link is up, false otherwise + * + * Reads the links register to determine if link is up and the current speed + **/ +static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, u32 *speed, + bool *link_up) +{ + u32 links_reg; + + links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); + + if (links_reg & IXGBE_LINKS_UP) + *link_up = true; + else + *link_up = false; + + if (links_reg & IXGBE_LINKS_SPEED) + *speed = IXGBE_LINK_SPEED_10GB_FULL; + else + *speed = IXGBE_LINK_SPEED_1GB_FULL; + + return 0; +} + +/** + * ixgbe_setup_mac_link_speed_82598 - Set MAC link speed + * @hw: pointer to hardware structure + * @speed: new link speed + * @autoneg: true if auto-negotiation enabled + * @autoneg_wait_to_complete: true if waiting is needed to complete + * + * Set the link speed in the AUTOC register and restarts link. + **/ +static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, + u32 speed, bool autoneg, + bool autoneg_wait_to_complete) +{ + s32 status = 0; + + /* If speed is 10G, then check for CX4 or XAUI. */ + if ((speed == IXGBE_LINK_SPEED_10GB_FULL) && + (!(hw->mac.link_attach_type & IXGBE_AUTOC_10G_KX4))) + hw->mac.link_mode_select = IXGBE_AUTOC_LMS_10G_LINK_NO_AN; + else if ((speed == IXGBE_LINK_SPEED_1GB_FULL) && (!autoneg)) + hw->mac.link_mode_select = IXGBE_AUTOC_LMS_1G_LINK_NO_AN; + else if (autoneg) { + /* BX mode - Autonegotiate 1G */ + if (!(hw->mac.link_attach_type & IXGBE_AUTOC_1G_PMA_PMD)) + hw->mac.link_mode_select = IXGBE_AUTOC_LMS_1G_AN; + else /* KX/KX4 mode */ + hw->mac.link_mode_select = IXGBE_AUTOC_LMS_KX4_AN_1G_AN; + } else { + status = IXGBE_ERR_LINK_SETUP; + } + + if (status == 0) { + hw->phy.autoneg_wait_to_complete = autoneg_wait_to_complete; + + hw->mac.link_settings_loaded = true; + /* + * Setup and restart the link based on the new values in + * ixgbe_hw This will write the AUTOC register based on the new + * stored values + */ + hw->phy.ops.setup(hw); + } + + return status; +} + + +/** + * ixgbe_setup_copper_link_82598 - Setup copper link settings + * @hw: pointer to hardware structure + * + * Configures link settings based on values in the ixgbe_hw struct. + * Restarts the link. Performs autonegotiation if needed. Restart + * phy and wait for autonegotiate to finish. Then synchronize the + * MAC and PHY. + **/ +static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw) +{ + s32 status; + u32 speed = 0; + bool link_up = false; + + /* Set up MAC */ + hw->phy.ops.setup(hw); + + /* Restart autonegotiation on PHY */ + status = hw->phy.ops.setup(hw); + + /* Synchronize MAC to PHY speed */ + if (status == 0) + status = hw->phy.ops.check(hw, &speed, &link_up); + + return status; +} + +/** + * ixgbe_check_copper_link_82598 - Syncs MAC & PHY link settings + * @hw: pointer to hardware structure + * @speed: pointer to link speed + * @link_up: true if link is up, false otherwise + * + * Reads the mac link, phy link, and synchronizes the MAC to PHY. + **/ +static s32 ixgbe_check_copper_link_82598(struct ixgbe_hw *hw, u32 *speed, + bool *link_up) +{ + s32 status; + u32 phy_speed = 0; + bool phy_link = false; + + /* This is the speed and link the MAC is set at */ + hw->phy.ops.check(hw, speed, link_up); + + /* + * Check current speed and link status of the PHY register. + * This is a vendor specific register and may have to + * be changed for other copper PHYs. + */ + status = hw->phy.ops.check(hw, &phy_speed, &phy_link); + + if ((status == 0) && (phy_link)) { + /* + * Check current link status of the MACs link's register + * matches that of the speed in the PHY register + */ + if (*speed != phy_speed) { + /* + * The copper PHY requires 82598 attach type to be XAUI + * for 10G and BX for 1G + */ + hw->mac.link_attach_type = + (IXGBE_AUTOC_10G_XAUI | IXGBE_AUTOC_1G_BX); + + /* Synchronize the MAC speed to the PHY speed */ + status = hw->phy.ops.setup_speed(hw, phy_speed, false, + false); + if (status == 0) + hw->phy.ops.check(hw, speed, link_up); + else + status = IXGBE_ERR_LINK_SETUP; + } + } else { + *link_up = phy_link; + } + + return status; +} + +/** + * ixgbe_setup_copper_link_speed_82598 - Set the PHY autoneg advertised field + * @hw: pointer to hardware structure + * @speed: new link speed + * @autoneg: true if autonegotiation enabled + * @autoneg_wait_to_complete: true if waiting is needed to complete + * + * Sets the link speed in the AUTOC register in the MAC and restarts link. + **/ +static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, u32 speed, + bool autoneg, + bool autoneg_wait_to_complete) +{ + s32 status; + bool link_up = 0; + + /* Setup the PHY according to input speed */ + status = hw->phy.ops.setup_speed(hw, speed, autoneg, + autoneg_wait_to_complete); + + /* Synchronize MAC to PHY speed */ + if (status == 0) + status = hw->phy.ops.check(hw, &speed, &link_up); + + return status; +} + +/** + * ixgbe_reset_hw_82598 - Performs hardware reset + * @hw: pointer to hardware structure + * + * Resets the hardware by reseting the transmit and receive units, masks and + * clears all interrupts, performing a PHY reset, and performing a link (MAC) + * reset. + **/ +static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) +{ + s32 status = 0; + u32 ctrl; + u32 gheccr; + u32 i; + u32 autoc; + u8 analog_val; + + /* Call adapter stop to disable tx/rx and clear interrupts */ + ixgbe_stop_adapter(hw); + + /* + * Power up the Atlas TX lanes if they are currently powered down. + * Atlas TX lanes are powered down for MAC loopback tests, but + * they are not automatically restored on reset. + */ + ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val); + if (analog_val & IXGBE_ATLAS_PDN_TX_REG_EN) { + /* Enable TX Atlas so packets can be transmitted again */ + ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val); + analog_val &= ~IXGBE_ATLAS_PDN_TX_REG_EN; + ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, analog_val); + + ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, &analog_val); + analog_val &= ~IXGBE_ATLAS_PDN_TX_10G_QL_ALL; + ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, analog_val); + + ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, &analog_val); + analog_val &= ~IXGBE_ATLAS_PDN_TX_1G_QL_ALL; + ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, analog_val); + + ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, &analog_val); + analog_val &= ~IXGBE_ATLAS_PDN_TX_AN_QL_ALL; + ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, analog_val); + } + + /* Reset PHY */ + ixgbe_reset_phy(hw); + + /* + * Prevent the PCI-E bus from from hanging by disabling PCI-E master + * access and verify no pending requests before reset + */ + if (ixgbe_disable_pcie_master(hw) != 0) { + status = IXGBE_ERR_MASTER_REQUESTS_PENDING; + hw_dbg(hw, "PCI-E Master disable polling has failed.\n"); + } + + /* + * Issue global reset to the MAC. This needs to be a SW reset. + * If link reset is used, it might reset the MAC when mng is using it + */ + ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); + IXGBE_WRITE_REG(hw, IXGBE_CTRL, (ctrl | IXGBE_CTRL_RST)); + IXGBE_WRITE_FLUSH(hw); + + /* Poll for reset bit to self-clear indicating reset is complete */ + for (i = 0; i < 10; i++) { + udelay(1); + ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); + if (!(ctrl & IXGBE_CTRL_RST)) + break; + } + if (ctrl & IXGBE_CTRL_RST) { + status = IXGBE_ERR_RESET_FAILED; + hw_dbg(hw, "Reset polling failed to complete.\n"); + } + + msleep(50); + + gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR); + gheccr &= ~((1 << 21) | (1 << 18) | (1 << 9) | (1 << 6)); + IXGBE_WRITE_REG(hw, IXGBE_GHECCR, gheccr); + + /* + * AUTOC register which stores link settings gets cleared + * and reloaded from EEPROM after reset. We need to restore + * our stored value from init in case SW changed the attach + * type or speed. If this is the first time and link settings + * have not been stored, store default settings from AUTOC. + */ + autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); + if (hw->mac.link_settings_loaded) { + autoc &= ~(IXGBE_AUTOC_LMS_ATTACH_TYPE); + autoc &= ~(IXGBE_AUTOC_LMS_MASK); + autoc |= hw->mac.link_attach_type; + autoc |= hw->mac.link_mode_select; + IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc); + } else { + hw->mac.link_attach_type = + (autoc & IXGBE_AUTOC_LMS_ATTACH_TYPE); + hw->mac.link_mode_select = (autoc & IXGBE_AUTOC_LMS_MASK); + hw->mac.link_settings_loaded = true; + } + + /* Store the permanent mac address */ + ixgbe_get_mac_addr(hw, hw->mac.perm_addr); + + return status; +} + +static struct ixgbe_mac_operations mac_ops_82598 = { + .reset = &ixgbe_reset_hw_82598, + .get_media_type = &ixgbe_get_media_type_82598, +}; + +static struct ixgbe_phy_operations phy_ops_82598EB = { + .setup = &ixgbe_setup_copper_link_82598, + .check = &ixgbe_check_copper_link_82598, + .setup_speed = &ixgbe_setup_copper_link_speed_82598, + .get_settings = &ixgbe_get_copper_link_settings_82598, +}; + +struct ixgbe_info ixgbe_82598EB_info = { + .mac = ixgbe_mac_82598EB, + .get_invariants = &ixgbe_get_invariants_82598, + .mac_ops = &mac_ops_82598, + .phy_ops = &phy_ops_82598EB, +}; + +static struct ixgbe_phy_operations phy_ops_82598AT = { + .setup = &ixgbe_setup_tnx_phy_link, + .check = &ixgbe_check_tnx_phy_link, + .setup_speed = &ixgbe_setup_tnx_phy_link_speed, + .get_settings = &ixgbe_get_copper_link_settings_82598, +}; + +struct ixgbe_info ixgbe_82598AT_info = { + .mac = ixgbe_mac_82598EB, + .get_invariants = &ixgbe_get_invariants_82598, + .mac_ops = &mac_ops_82598, + .phy_ops = &phy_ops_82598AT, +}; + +static struct ixgbe_phy_operations phy_ops_82598AF = { + .setup = &ixgbe_setup_mac_link_82598, + .check = &ixgbe_check_mac_link_82598, + .setup_speed = &ixgbe_setup_mac_link_speed_82598, + .get_settings = &ixgbe_get_link_settings_82598, +}; + +struct ixgbe_info ixgbe_82598AF_info = { + .mac = ixgbe_mac_82598EB, + .get_invariants = &ixgbe_get_invariants_82598, + .mac_ops = &mac_ops_82598, + .phy_ops = &phy_ops_82598AF, +}; + diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c new file mode 100644 index 00000000000..512e3b22ed0 --- /dev/null +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -0,0 +1,1175 @@ +/******************************************************************************* + + Intel 10 Gigabit PCI Express Linux driver + Copyright(c) 1999 - 2007 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, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 U |