summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAuke Kok <auke-jan.h.kok@intel.com>2007-09-15 14:07:45 -0700
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 16:51:02 -0700
commit9a799d71034c4e2b168740c8a8530591011313d5 (patch)
treece2dedefe2b101e1e81105a7ca8e3e61321193b6 /drivers
parentdc029ad97f267cbd1c2e978a443eb5ae93a55328 (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')
-rw-r--r--drivers/net/Kconfig27
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/ixgbe/Makefile36
-rw-r--r--drivers/net/ixgbe/ixgbe.h259
-rw-r--r--drivers/net/ixgbe/ixgbe_82598.c589
-rw-r--r--drivers/net/ixgbe/ixgbe_common.c1175
-rw-r--r--drivers/net/ixgbe/ixgbe_common.h86
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c943
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c2873
-rw-r--r--drivers/net/ixgbe/ixgbe_phy.c494
-rw-r--r--drivers/net/ixgbe/ixgbe_phy.h50
-rw-r--r--drivers/net/ixgbe/ixgbe_type.h1332
12 files changed, 7863 insertions, 2 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index eeac2f49aae3..76db0bc9452d 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 0d2b4bee587c..c23ffdbe2599 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 000000000000..ccd83d9f579e
--- /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 000000000000..c160a7d91e21
--- /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 000000000000..00ee20125ca9
--- /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 000000000000..512e3b22ed08
--- /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 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
+
<