From aad89561d0278918e619d121756e65324ee9e38a Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=2E=C3=87a=C4=9Flar=20Onur?= Date: Tue, 22 Dec 2009 22:21:06 +0000 Subject: [PATCH] merge igb driver related changes --- kernel-2.6.spec | 4 +- ...gb-driver.patch => linux-2.6-015-igb.patch | 27857 +++++++--------- 2 files changed, 12678 insertions(+), 15183 deletions(-) rename linux-2.6-730-igb-driver.patch => linux-2.6-015-igb.patch (67%) diff --git a/kernel-2.6.spec b/kernel-2.6.spec index 6fbdb1e09..2458481ea 100644 --- a/kernel-2.6.spec +++ b/kernel-2.6.spec @@ -146,6 +146,7 @@ Patch000: ftp://ftp.kernel.org/pub/linux/kernel/v2.6/patch-%{rpmversion}.bz2 %endif Patch010: linux-2.6-010-e1000e.patch +Patch015: linux-2.6-015-igb.patch Patch020: linux-2.6-020-build-id.patch Patch030: linux-2.6-030-netns.patch Patch040: linux-2.6-040-i_mutex-check.patch @@ -190,7 +191,6 @@ Patch670: linux-2.6-670-gcc43.patch Patch680: linux-2.6-680-htb-hysteresis-tso.patch #Patch690: linux-2.6-690-web100.patch Patch710: linux-2.6-710-avoid-64bits-addr-pcmcia.patch -Patch730: linux-2.6-730-igb-driver.patch # See also the file named 'sources' here for the related checksums # NOTE. iwlwifi should be in-kernel starting from 2.6.24 @@ -363,6 +363,7 @@ KERNEL_PREVIOUS=vanilla %endif %ApplyPatch 10 +%ApplyPatch 15 %ApplyPatch 20 # NetNS patch for VINI @@ -409,7 +410,6 @@ KERNEL_PREVIOUS=vanilla %endif %ApplyPatch 680 %ApplyPatch 710 -%ApplyPatch 730 # NetNS conflict-resolving patch for VINI. Will work with patch vini_pl_patch-1 but may diff --git a/linux-2.6-730-igb-driver.patch b/linux-2.6-015-igb.patch similarity index 67% rename from linux-2.6-730-igb-driver.patch rename to linux-2.6-015-igb.patch index 2de367056..7e54c15f3 100644 --- a/linux-2.6-730-igb-driver.patch +++ b/linux-2.6-015-igb.patch @@ -1,11 +1,99 @@ -diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/igb/e1000_82575.c ---- vanilla/drivers/net/igb/e1000_82575.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/e1000_82575.c 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,1663 @@ +Index: linux-2.6.22/drivers/net/Kconfig +=================================================================== +--- linux-2.6.22.orig/drivers/net/Kconfig 2009-12-18 12:37:55.000000000 -0500 ++++ linux-2.6.22/drivers/net/Kconfig 2009-12-18 12:39:22.000000000 -0500 +@@ -2016,6 +2016,28 @@ + . The module + will be called e1000e. + ++config IGB ++ tristate "Intel(R) 82575 Gigabit Ethernet support" ++ depends on PCI ++ ---help--- ++ This driver supports Intel(R) 82575 gigabit ethernet adapters. ++ For more information on how to identify your adapter, go to the ++ Adapter & Driver ID Guide at: ++ ++ ++ ++ For general information and support, go to the Intel support ++ website at: ++ ++ ++ ++ More specific information on configuring the driver is in ++ . ++ ++ To compile this driver as a module, choose M here and read ++ . The module ++ will be called igb. ++ + source "drivers/net/ixp2000/Kconfig" + + config MYRI_SBUS +Index: linux-2.6.22/drivers/net/Makefile +=================================================================== +--- linux-2.6.22.orig/drivers/net/Makefile 2009-12-18 12:38:07.000000000 -0500 ++++ linux-2.6.22/drivers/net/Makefile 2009-12-18 12:39:22.000000000 -0500 +@@ -12,6 +12,7 @@ + obj-$(CONFIG_BONDING) += bonding/ + obj-$(CONFIG_ATL1) += atl1/ + obj-$(CONFIG_GIANFAR) += gianfar_driver.o ++obj-$(CONFIG_IGB) += igb/ + + gianfar_driver-objs := gianfar.o \ + gianfar_ethtool.o \ +Index: linux-2.6.22/drivers/net/igb/Makefile +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/Makefile 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,37 @@ ++################################################################################ ++# ++# Intel 82575 PCI-Express Ethernet Linux driver ++# 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, ++# 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 ++# e1000-devel Mailing List ++# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++# ++################################################################################ ++ ++# ++# Makefile for the Intel(R) 82575 PCI-Express ethernet driver ++# ++ ++obj-$(CONFIG_IGB) += igb.o ++ ++igb-objs := igb_main.o igb_ethtool.o igb_param.o kcompat.o e1000_api.o e1000_manage.o e1000_82575.o \ ++ e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o ++ +Index: linux-2.6.22/drivers/net/igb/e1000_82575.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/e1000_82575.c 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,1580 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ Copyright(c) 2007-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, @@ -34,6 +122,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + * 82575EB Gigabit Backplane Connection + * 82575GB Gigabit Network Connection + * 82576 Gigabit Network Connection ++ * 82576 Quad Port Gigabit Mezzanine Adapter + */ + +#include "e1000_api.h" @@ -57,13 +146,12 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig +static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, + bool active); +static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw); -+static s32 e1000_setup_fiber_serdes_link_82575(struct e1000_hw *hw); ++static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw); +static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data); +static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, + u32 offset, u16 data); +static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw); +static s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask); -+static s32 e1000_configure_pcs_link_82575(struct e1000_hw *hw); +static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, + u16 *speed, u16 *duplex); +static s32 e1000_get_phy_id_82575(struct e1000_hw *hw); @@ -72,12 +160,8 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig +static s32 e1000_reset_init_script_82575(struct e1000_hw *hw); +static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw); +static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw); -+ -+static void e1000_init_rx_addrs_82575(struct e1000_hw *hw, u16 rar_count); -+static void e1000_update_mc_addr_list_82575(struct e1000_hw *hw, -+ u8 *mc_addr_list, u32 mc_addr_count, -+ u32 rar_used_count, u32 rar_count); -+void e1000_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw); ++static void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw); ++static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw); + +/** + * e1000_init_phy_params_82575 - Init PHY func ptrs. @@ -93,11 +177,11 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + if (hw->phy.media_type != e1000_media_type_copper) { + phy->type = e1000_phy_none; + goto out; -+ } else { -+ phy->ops.power_up = e1000_power_up_phy_copper; -+ phy->ops.power_down = e1000_power_down_phy_copper_82575; + } + ++ phy->ops.power_up = e1000_power_up_phy_copper; ++ phy->ops.power_down = e1000_power_down_phy_copper_82575; ++ + phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; + phy->reset_delay_us = 100; + @@ -191,7 +275,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + /* EEPROM access above 16k is unsupported */ + if (size > 14) + size = 14; -+ nvm->word_size = 1 << size; ++ nvm->word_size = 1 << size; + + /* Function Pointers */ + nvm->ops.acquire = e1000_acquire_nvm_82575; @@ -229,20 +313,26 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + dev_spec->sgmii_active = false; + + ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); -+ if ((ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) == -+ E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES) { -+ hw->phy.media_type = e1000_media_type_internal_serdes; -+ ctrl_ext |= E1000_CTRL_I2C_ENA; -+ } else if (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_SGMII) { ++ switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) { ++ case E1000_CTRL_EXT_LINK_MODE_SGMII: + dev_spec->sgmii_active = true; + ctrl_ext |= E1000_CTRL_I2C_ENA; -+ } else { ++ break; ++ case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES: ++ hw->phy.media_type = e1000_media_type_internal_serdes; ++ ctrl_ext |= E1000_CTRL_I2C_ENA; ++ break; ++ default: + ctrl_ext &= ~E1000_CTRL_I2C_ENA; ++ break; + } ++ + E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); + + /* Set mta register count */ + mac->mta_reg_count = 128; ++ /* Set uta register count */ ++ mac->uta_reg_count = (hw->mac.type == e1000_82575) ? 0 : 128; + /* Set rar entry count */ + mac->rar_entry_count = E1000_RAR_ENTRIES_82575; + if (mac->type == e1000_82576) @@ -268,9 +358,9 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + mac->ops.setup_physical_interface = + (hw->phy.media_type == e1000_media_type_copper) + ? e1000_setup_copper_link_82575 -+ : e1000_setup_fiber_serdes_link_82575; ++ : e1000_setup_serdes_link_82575; + /* physical interface shutdown */ -+ mac->ops.shutdown_serdes = e1000_shutdown_fiber_serdes_link_82575; ++ mac->ops.shutdown_serdes = e1000_shutdown_serdes_link_82575; + /* check for link */ + mac->ops.check_for_link = e1000_check_for_link_82575; + /* receive address register setting */ @@ -278,13 +368,15 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + /* read mac address */ + mac->ops.read_mac_addr = e1000_read_mac_addr_82575; + /* multicast address update */ -+ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_82575; ++ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; + /* writing VFTA */ + mac->ops.write_vfta = e1000_write_vfta_generic; + /* clearing VFTA */ + mac->ops.clear_vfta = e1000_clear_vfta_generic; + /* setting MTA */ + mac->ops.mta_set = e1000_mta_set_generic; ++ /* ID LED init */ ++ mac->ops.id_led_init = e1000_id_led_init_generic; + /* blink LED */ + mac->ops.blink_led = e1000_blink_led_generic; + /* setup LED */ @@ -299,6 +391,9 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + /* link info */ + mac->ops.get_link_up_info = e1000_get_link_up_info_82575; + ++ /* set lan id for port to determine which phy lock to use */ ++ hw->mac.ops.set_lan_id(hw); ++ + return E1000_SUCCESS; +} + @@ -315,6 +410,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + hw->mac.ops.init_params = e1000_init_mac_params_82575; + hw->nvm.ops.init_params = e1000_init_nvm_params_82575; + hw->phy.ops.init_params = e1000_init_phy_params_82575; ++ hw->mbx.ops.init_params = e1000_init_mbx_params_pf; +} + +/** @@ -325,11 +421,12 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + **/ +static s32 e1000_acquire_phy_82575(struct e1000_hw *hw) +{ -+ u16 mask; ++ u16 mask = E1000_SWFW_PHY0_SM; + + DEBUGFUNC("e1000_acquire_phy_82575"); + -+ mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; ++ if (hw->bus.func == E1000_FUNC_1) ++ mask = E1000_SWFW_PHY1_SM; + + return e1000_acquire_swfw_sync_82575(hw, mask); +} @@ -342,11 +439,13 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + **/ +static void e1000_release_phy_82575(struct e1000_hw *hw) +{ -+ u16 mask; ++ u16 mask = E1000_SWFW_PHY0_SM; + + DEBUGFUNC("e1000_release_phy_82575"); + -+ mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; ++ if (hw->bus.func == E1000_FUNC_1) ++ mask = E1000_SWFW_PHY1_SM; ++ + e1000_release_swfw_sync_82575(hw, mask); +} + @@ -362,47 +461,25 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig +static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, + u16 *data) +{ -+ struct e1000_phy_info *phy = &hw->phy; -+ u32 i, i2ccmd = 0; ++ s32 ret_val = -E1000_ERR_PARAM; + + DEBUGFUNC("e1000_read_phy_reg_sgmii_82575"); + + if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { + DEBUGOUT1("PHY Address %u is out of range\n", offset); -+ return -E1000_ERR_PARAM; ++ goto out; + } + -+ /* -+ * Set up Op-code, Phy Address, and register address in the I2CCMD -+ * register. The MAC will take care of interfacing with the -+ * PHY to retrieve the desired data. -+ */ -+ i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | -+ (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | -+ (E1000_I2CCMD_OPCODE_READ)); -+ -+ E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) ++ goto out; + -+ /* Poll the ready bit to see if the I2C read completed */ -+ for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { -+ usec_delay(50); -+ i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD); -+ if (i2ccmd & E1000_I2CCMD_READY) -+ break; -+ } -+ if (!(i2ccmd & E1000_I2CCMD_READY)) { -+ DEBUGOUT("I2CCMD Read did not complete\n"); -+ return -E1000_ERR_PHY; -+ } -+ if (i2ccmd & E1000_I2CCMD_ERROR) { -+ DEBUGOUT("I2CCMD Error bit set\n"); -+ return -E1000_ERR_PHY; -+ } ++ ret_val = e1000_read_phy_reg_i2c(hw, offset, data); + -+ /* Need to byte-swap the 16-bit value. */ -+ *data = ((i2ccmd >> 8) & 0x00FF) | ((i2ccmd << 8) & 0xFF00); ++ hw->phy.ops.release(hw); + -+ return E1000_SUCCESS; ++out: ++ return ret_val; +} + +/** @@ -417,49 +494,25 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig +static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, + u16 data) +{ -+ struct e1000_phy_info *phy = &hw->phy; -+ u32 i, i2ccmd = 0; -+ u16 phy_data_swapped; ++ s32 ret_val = -E1000_ERR_PARAM; + + DEBUGFUNC("e1000_write_phy_reg_sgmii_82575"); + + if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { + DEBUGOUT1("PHY Address %d is out of range\n", offset); -+ return -E1000_ERR_PARAM; ++ goto out; + } + -+ /* Swap the data bytes for the I2C interface */ -+ phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00); -+ -+ /* -+ * Set up Op-code, Phy Address, and register address in the I2CCMD -+ * register. The MAC will take care of interfacing with the -+ * PHY to retrieve the desired data. -+ */ -+ i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | -+ (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | -+ E1000_I2CCMD_OPCODE_WRITE | -+ phy_data_swapped); ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) ++ goto out; + -+ E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); ++ ret_val = e1000_write_phy_reg_i2c(hw, offset, data); + -+ /* Poll the ready bit to see if the I2C read completed */ -+ for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { -+ usec_delay(50); -+ i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD); -+ if (i2ccmd & E1000_I2CCMD_READY) -+ break; -+ } -+ if (!(i2ccmd & E1000_I2CCMD_READY)) { -+ DEBUGOUT("I2CCMD Write did not complete\n"); -+ return -E1000_ERR_PHY; -+ } -+ if (i2ccmd & E1000_I2CCMD_ERROR) { -+ DEBUGOUT("I2CCMD Error bit set\n"); -+ return -E1000_ERR_PHY; -+ } ++ hw->phy.ops.release(hw); + -+ return E1000_SUCCESS; ++out: ++ return ret_val; +} + +/** @@ -474,6 +527,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + u16 phy_id; ++ u32 ctrl_ext; + + DEBUGFUNC("e1000_get_phy_id_82575"); + @@ -484,12 +538,19 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + * work. The result of this function should mean phy->phy_addr + * and phy->id are set correctly. + */ -+ if (!(e1000_sgmii_active_82575(hw))) { ++ if (!e1000_sgmii_active_82575(hw)) { + phy->addr = 1; + ret_val = e1000_get_phy_id(hw); + goto out; + } + ++ /* Power on sgmii phy if it is disabled */ ++ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ++ E1000_WRITE_REG(hw, E1000_CTRL_EXT, ++ ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA); ++ E1000_WRITE_FLUSH(hw); ++ msec_delay(300); ++ + /* + * The address field in the I2CCMD register is 3 bits and 0 is invalid. + * Therefore, we need to test 1-7 @@ -516,10 +577,12 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + if (phy->addr == 8) { + phy->addr = 0; + ret_val = -E1000_ERR_PHY; -+ goto out; ++ } else { ++ ret_val = e1000_get_phy_id(hw); + } + -+ ret_val = e1000_get_phy_id(hw); ++ /* restore previous sfp cage power state */ ++ E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); + +out: + return ret_val; @@ -784,24 +847,21 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + + DEBUGFUNC("e1000_get_cfg_done_82575"); + -+ if (hw->bus.func == 1) ++ if (hw->bus.func == E1000_FUNC_1) + mask = E1000_NVM_CFG_DONE_PORT_1; -+ + while (timeout) { + if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask) + break; + msec_delay(1); + timeout--; + } -+ if (!timeout) { ++ if (!timeout) + DEBUGOUT("MNG configuration cycle has not completed.\n"); -+ } + + /* If EEPROM is not marked present, init the PHY manually */ + if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) && -+ (hw->phy.type == e1000_phy_igp_3)) { ++ (hw->phy.type == e1000_phy_igp_3)) + e1000_phy_init_script_igp3(hw); -+ } + + return ret_val; +} @@ -823,14 +883,12 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + + DEBUGFUNC("e1000_get_link_up_info_82575"); + -+ if (hw->phy.media_type != e1000_media_type_copper || -+ e1000_sgmii_active_82575(hw)) { ++ if (hw->phy.media_type != e1000_media_type_copper) + ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, speed, + duplex); -+ } else { ++ else + ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, + duplex); -+ } + + return ret_val; +} @@ -849,13 +907,18 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + + DEBUGFUNC("e1000_check_for_link_82575"); + -+ /* SGMII link check is done through the PCS register. */ -+ if ((hw->phy.media_type != e1000_media_type_copper) || -+ (e1000_sgmii_active_82575(hw))) ++ if (hw->phy.media_type != e1000_media_type_copper) { + ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, &speed, + &duplex); -+ else ++ /* ++ * Use this flag to determine if link needs to be checked or ++ * not. If we have link clear the flag so that we do not ++ * continue to check for link. ++ */ ++ hw->mac.get_link_status = !hw->mac.serdes_has_link; ++ } else { + ret_val = e1000_check_for_copper_link_generic(hw); ++ } + + return ret_val; +} @@ -918,119 +981,25 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig +} + +/** -+ * e1000_init_rx_addrs_82575 - Initialize receive address's -+ * @hw: pointer to the HW structure -+ * @rar_count: receive address registers -+ * -+ * Setups the receive address registers by setting the base receive address -+ * register to the devices MAC address and clearing all the other receive -+ * address registers to 0. -+ **/ -+static void e1000_init_rx_addrs_82575(struct e1000_hw *hw, u16 rar_count) -+{ -+ u32 i; -+ u8 addr[6] = {0,0,0,0,0,0}; -+ /* -+ * This function is essentially the same as that of -+ * e1000_init_rx_addrs_generic. However it also takes care -+ * of the special case where the register offset of the -+ * second set of RARs begins elsewhere. This is implicitly taken care by -+ * function e1000_rar_set_generic. -+ */ -+ -+ DEBUGFUNC("e1000_init_rx_addrs_82575"); -+ -+ /* Setup the receive address */ -+ DEBUGOUT("Programming MAC Address into RAR[0]\n"); -+ hw->mac.ops.rar_set(hw, hw->mac.addr, 0); -+ -+ /* Zero out the other (rar_entry_count - 1) receive addresses */ -+ DEBUGOUT1("Clearing RAR[1-%u]\n", rar_count-1); -+ for (i = 1; i < rar_count; i++) { -+ hw->mac.ops.rar_set(hw, addr, i); -+ } -+} -+ -+/** -+ * e1000_update_mc_addr_list_82575 - Update Multicast addresses -+ * @hw: pointer to the HW structure -+ * @mc_addr_list: array of multicast addresses to program -+ * @mc_addr_count: number of multicast addresses to program -+ * @rar_used_count: the first RAR register free to program -+ * @rar_count: total number of supported Receive Address Registers -+ * -+ * Updates the Receive Address Registers and Multicast Table Array. -+ * The caller must have a packed mc_addr_list of multicast addresses. -+ * The parameter rar_count will usually be hw->mac.rar_entry_count -+ * unless there are workarounds that change this. -+ **/ -+static void e1000_update_mc_addr_list_82575(struct e1000_hw *hw, -+ u8 *mc_addr_list, u32 mc_addr_count, -+ u32 rar_used_count, u32 rar_count) -+{ -+ u32 hash_value; -+ u32 i; -+ u8 addr[6] = {0,0,0,0,0,0}; -+ /* -+ * This function is essentially the same as that of -+ * e1000_update_mc_addr_list_generic. However it also takes care -+ * of the special case where the register offset of the -+ * second set of RARs begins elsewhere. This is implicitly taken care by -+ * function e1000_rar_set_generic. -+ */ -+ -+ DEBUGFUNC("e1000_update_mc_addr_list_82575"); -+ -+ /* -+ * Load the first set of multicast addresses into the exact -+ * filters (RAR). If there are not enough to fill the RAR -+ * array, clear the filters. -+ */ -+ for (i = rar_used_count; i < rar_count; i++) { -+ if (mc_addr_count) { -+ e1000_rar_set_generic(hw, mc_addr_list, i); -+ mc_addr_count--; -+ mc_addr_list += ETH_ADDR_LEN; -+ } else { -+ e1000_rar_set_generic(hw, addr, i); -+ } -+ } -+ -+ /* Clear the old settings from the MTA */ -+ DEBUGOUT("Clearing MTA\n"); -+ for (i = 0; i < hw->mac.mta_reg_count; i++) { -+ E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); -+ E1000_WRITE_FLUSH(hw); -+ } -+ -+ /* Load any remaining multicast addresses into the hash table. */ -+ for (; mc_addr_count > 0; mc_addr_count--) { -+ hash_value = e1000_hash_mc_addr(hw, mc_addr_list); -+ DEBUGOUT1("Hash value = 0x%03X\n", hash_value); -+ hw->mac.ops.mta_set(hw, hash_value); -+ mc_addr_list += ETH_ADDR_LEN; -+ } -+} -+ -+/** -+ * e1000_shutdown_fiber_serdes_link_82575 - Remove link during power down ++ * e1000_shutdown_serdes_link_82575 - Remove link during power down + * @hw: pointer to the HW structure + * -+ * In the case of fiber serdes shut down optics and PCS on driver unload ++ * In the case of serdes shut down sfp and PCS on driver unload + * when management pass thru is not enabled. + **/ -+void e1000_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw) ++void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw) +{ + u32 reg; + u16 eeprom_data = 0; + -+ if (hw->mac.type != e1000_82576 || -+ (hw->phy.media_type != e1000_media_type_fiber && -+ hw->phy.media_type != e1000_media_type_internal_serdes)) ++ if ((hw->phy.media_type != e1000_media_type_internal_serdes) && ++ !e1000_sgmii_active_82575(hw)) + return; + -+ if (hw->bus.func == 0) ++ if (hw->bus.func == E1000_FUNC_0) + hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); ++ else if (hw->bus.func == E1000_FUNC_1) ++ hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); + + /* + * If APM is not enabled in the EEPROM and management interface is @@ -1045,10 +1014,10 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + + /* shutdown the laser */ + reg = E1000_READ_REG(hw, E1000_CTRL_EXT); -+ reg |= E1000_CTRL_EXT_SDP7_DATA; ++ reg |= E1000_CTRL_EXT_SDP3_DATA; + E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); + -+ /* flush the write to verfiy completion */ ++ /* flush the write to verify completion */ + E1000_WRITE_FLUSH(hw); + msec_delay(1); + } @@ -1078,6 +1047,12 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + DEBUGOUT("PCI-E Master disable polling has failed.\n"); + } + ++ /* set the completion timeout for interface */ ++ ret_val = e1000_set_pcie_completion_timeout(hw); ++ if (ret_val) { ++ DEBUGOUT("PCI-E Set completion timeout has failed.\n"); ++ } ++ + DEBUGOUT("Masking off all interrupts\n"); + E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); + @@ -1110,7 +1085,8 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); + icr = E1000_READ_REG(hw, E1000_ICR); + -+ e1000_check_alt_mac_addr_generic(hw); ++ /* Install any alternate MAC address into RAR0 */ ++ ret_val = e1000_check_alt_mac_addr_generic(hw); + + return ret_val; +} @@ -1130,7 +1106,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + DEBUGFUNC("e1000_init_hw_82575"); + + /* Initialize identification LED */ -+ ret_val = e1000_id_led_init_generic(hw); ++ ret_val = mac->ops.id_led_init(hw); + if (ret_val) { + DEBUGOUT("Error initializing identification LED\n"); + /* This is not fatal and we should not stop init due to this */ @@ -1141,12 +1117,18 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + mac->ops.clear_vfta(hw); + + /* Setup the receive address */ -+ e1000_init_rx_addrs_82575(hw, rar_count); ++ e1000_init_rx_addrs_generic(hw, rar_count); ++ + /* Zero out the Multicast HASH table */ + DEBUGOUT("Zeroing the MTA\n"); + for (i = 0; i < mac->mta_reg_count; i++) + E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); + ++ /* Zero out the Unicast HASH table */ ++ DEBUGOUT("Zeroing the UTA\n"); ++ for (i = 0; i < mac->uta_reg_count; i++) ++ E1000_WRITE_REG_ARRAY(hw, E1000_UTA, i, 0); ++ + /* Setup link and flow control */ + ret_val = mac->ops.setup_link(hw); + @@ -1171,9 +1153,8 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + **/ +static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw) +{ -+ u32 ctrl, led_ctrl; ++ u32 ctrl; + s32 ret_val; -+ bool link; + + DEBUGFUNC("e1000_setup_copper_link_82575"); + @@ -1182,17 +1163,23 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + ++ ret_val = e1000_setup_serdes_link_82575(hw); ++ if (ret_val) ++ goto out; ++ ++ if (e1000_sgmii_active_82575(hw) && !hw->phy.reset_disable) { ++ ret_val = hw->phy.ops.reset(hw); ++ if (ret_val) { ++ DEBUGOUT("Error resetting the PHY.\n"); ++ goto out; ++ } ++ } + switch (hw->phy.type) { + case e1000_phy_m88: + ret_val = e1000_copper_link_setup_m88(hw); + break; + case e1000_phy_igp_3: + ret_val = e1000_copper_link_setup_igp(hw); -+ /* Setup activity LED */ -+ led_ctrl = E1000_READ_REG(hw, E1000_LEDCTL); -+ led_ctrl &= IGP_ACTIVITY_LED_MASK; -+ led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); -+ E1000_WRITE_REG(hw, E1000_LEDCTL, led_ctrl); + break; + default: + ret_val = -E1000_ERR_PHY; @@ -1202,66 +1189,29 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + if (ret_val) + goto out; + -+ if (hw->mac.autoneg) { -+ /* -+ * Setup autoneg and flow control advertisement -+ * and perform autonegotiation. -+ */ -+ ret_val = e1000_copper_link_autoneg(hw); -+ if (ret_val) -+ goto out; -+ } else { -+ /* -+ * PHY will be set to 10H, 10F, 100H or 100F -+ * depending on user settings. -+ */ -+ DEBUGOUT("Forcing Speed and Duplex\n"); -+ ret_val = hw->phy.ops.force_speed_duplex(hw); -+ if (ret_val) { -+ DEBUGOUT("Error Forcing Speed and Duplex\n"); -+ goto out; -+ } -+ } ++ ret_val = e1000_setup_copper_link_generic(hw); ++out: ++ return ret_val; ++} + -+ ret_val = e1000_configure_pcs_link_82575(hw); -+ if (ret_val) -+ goto out; ++/** ++ * e1000_setup_serdes_link_82575 - Setup link for serdes ++ * @hw: pointer to the HW structure ++ * ++ * Configure the physical coding sub-layer (PCS) link. The PCS link is ++ * used on copper connections where the serialized gigabit media independent ++ * interface (sgmii), or serdes fiber is being used. Configures the link ++ * for auto-negotiation or forces speed/duplex. ++ **/ ++static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw) ++{ ++ u32 ctrl_reg, reg; + -+ /* -+ * Check link status. Wait up to 100 microseconds for link to become -+ * valid. -+ */ -+ ret_val = e1000_phy_has_link_generic(hw, -+ COPPER_LINK_UP_LIMIT, -+ 10, -+ &link); -+ if (ret_val) -+ goto out; -+ -+ if (link) { -+ DEBUGOUT("Valid link established!!!\n"); -+ /* Config the MAC and PHY after link is up */ -+ e1000_config_collision_dist_generic(hw); -+ ret_val = e1000_config_fc_after_link_up_generic(hw); -+ } else { -+ DEBUGOUT("Unable to establish link!!!\n"); -+ } -+ -+out: -+ return ret_val; -+} -+ -+/** -+ * e1000_setup_fiber_serdes_link_82575 - Setup link for fiber/serdes -+ * @hw: pointer to the HW structure -+ * -+ * Configures speed and duplex for fiber and serdes links. -+ **/ -+static s32 e1000_setup_fiber_serdes_link_82575(struct e1000_hw *hw) -+{ -+ u32 reg; ++ DEBUGFUNC("e1000_setup_serdes_link_82575"); + -+ DEBUGFUNC("e1000_setup_fiber_serdes_link_82575"); ++ if ((hw->phy.media_type != e1000_media_type_internal_serdes) && ++ !e1000_sgmii_active_82575(hw)) ++ return E1000_SUCCESS; + + /* + * On the 82575, SerDes loopback mode persists until it is @@ -1271,26 +1221,38 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + */ + E1000_WRITE_REG(hw, E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); + -+ /* Force link up, set 1gb, set both sw defined pins */ -+ reg = E1000_READ_REG(hw, E1000_CTRL); -+ reg |= E1000_CTRL_SLU | -+ E1000_CTRL_SPD_1000 | -+ E1000_CTRL_FRCSPD | -+ E1000_CTRL_SWDPIN0 | -+ E1000_CTRL_SWDPIN1; -+ E1000_WRITE_REG(hw, E1000_CTRL, reg); ++ /* power on the sfp cage if present */ ++ reg = E1000_READ_REG(hw, E1000_CTRL_EXT); ++ reg &= ~E1000_CTRL_EXT_SDP3_DATA; ++ E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); + -+ /* Power on phy for 82576 fiber adapters */ -+ if (hw->mac.type == e1000_82576) { -+ reg = E1000_READ_REG(hw, E1000_CTRL_EXT); -+ reg &= ~E1000_CTRL_EXT_SDP7_DATA; -+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); ++ ctrl_reg = E1000_READ_REG(hw, E1000_CTRL); ++ ctrl_reg |= E1000_CTRL_SLU; ++ ++ if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576) { ++ /* set both sw defined pins */ ++ ctrl_reg |= E1000_CTRL_SWDPIN0 | E1000_CTRL_SWDPIN1; ++ ++ /* Set switch control to serdes energy detect */ ++ reg = E1000_READ_REG(hw, E1000_CONNSW); ++ reg |= E1000_CONNSW_ENRGSRC; ++ E1000_WRITE_REG(hw, E1000_CONNSW, reg); ++ } ++ ++ reg = E1000_READ_REG(hw, E1000_PCS_LCTL); ++ ++ if (e1000_sgmii_active_82575(hw)) { ++ /* allow time for SFP cage to power up phy */ ++ msec_delay(300); ++ ++ /* AN time out should be disabled for SGMII mode */ ++ reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT); ++ } else { ++ ctrl_reg |= E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD | ++ E1000_CTRL_FD | E1000_CTRL_FRCDPX; + } + -+ /* Set switch control to serdes energy detect */ -+ reg = E1000_READ_REG(hw, E1000_CONNSW); -+ reg |= E1000_CONNSW_ENRGSRC; -+ E1000_WRITE_REG(hw, E1000_CONNSW, reg); ++ E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg); + + /* + * New SerDes mode allows for forcing speed or autonegotiating speed @@ -1298,35 +1260,51 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + * mode that will be compatible with older link partners and switches. + * However, both are supported by the hardware and some drivers/tools. + */ -+ reg = E1000_READ_REG(hw, E1000_PCS_LCTL); + + reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP | -+ E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); ++ E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); + -+ if (hw->mac.autoneg) { ++ /* ++ * We force flow control to prevent the CTRL register values from being ++ * overwritten by the autonegotiated flow control values ++ */ ++ reg |= E1000_PCS_LCTL_FORCE_FCTRL; ++ ++ /* ++ * we always set sgmii to autoneg since it is the phy that will be ++ * forcing the link and the serdes is just a go-between ++ */ ++ if (hw->mac.autoneg || e1000_sgmii_active_82575(hw)) { + /* Set PCS register for autoneg */ -+ reg |= E1000_PCS_LCTL_FSV_1000 | /* Force 1000 */ -+ E1000_PCS_LCTL_FDV_FULL | /* SerDes Full duplex */ -+ E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */ -+ E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */ -+ DEBUGOUT1("Configuring Autoneg; PCS_LCTL = 0x%08X\n", reg); ++ reg |= E1000_PCS_LCTL_FSV_1000 | /* Force 1000 */ ++ E1000_PCS_LCTL_FDV_FULL | /* SerDes Full dplx */ ++ E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */ ++ E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */ ++ DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg); + } else { -+ /* Set PCS register for forced speed */ -+ reg |= E1000_PCS_LCTL_FLV_LINK_UP | /* Force link up */ -+ E1000_PCS_LCTL_FSV_1000 | /* Force 1000 */ -+ E1000_PCS_LCTL_FDV_FULL | /* SerDes Full duplex */ -+ E1000_PCS_LCTL_FSD | /* Force Speed */ -+ E1000_PCS_LCTL_FORCE_LINK; /* Force Link */ -+ DEBUGOUT1("Configuring Forced Link; PCS_LCTL = 0x%08X\n", reg); -+ } ++ /* Check for duplex first */ ++ if (hw->mac.forced_speed_duplex & E1000_ALL_FULL_DUPLEX) ++ reg |= E1000_PCS_LCTL_FDV_FULL; + -+ if (hw->mac.type == e1000_82576) { -+ reg |= E1000_PCS_LCTL_FORCE_FCTRL; -+ e1000_force_mac_fc_generic(hw); ++ /* No need to check for 1000/full since the spec states that ++ * it requires autoneg to be enabled */ ++ /* Now set speed */ ++ if (hw->mac.forced_speed_duplex & E1000_ALL_100_SPEED) ++ reg |= E1000_PCS_LCTL_FSV_100; ++ ++ /* Force speed and force link */ ++ reg |= E1000_PCS_LCTL_FSD | ++ E1000_PCS_LCTL_FORCE_LINK | ++ E1000_PCS_LCTL_FLV_LINK_UP; ++ ++ DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg); + } + + E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg); + ++ if (!e1000_sgmii_active_82575(hw)) ++ e1000_force_mac_fc_generic(hw); ++ + return E1000_SUCCESS; +} + @@ -1352,7 +1330,6 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + + if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) { + switch(hw->phy.media_type) { -+ case e1000_media_type_fiber: + case e1000_media_type_internal_serdes: + *data = ID_LED_DEFAULT_82575_SERDES; + break; @@ -1367,72 +1344,6 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig +} + +/** -+ * e1000_configure_pcs_link_82575 - Configure PCS link -+ * @hw: pointer to the HW structure -+ * -+ * Configure the physical coding sub-layer (PCS) link. The PCS link is -+ * only used on copper connections where the serialized gigabit media -+ * independent interface (sgmii) is being used. Configures the link -+ * for auto-negotiation or forces speed/duplex. -+ **/ -+static s32 e1000_configure_pcs_link_82575(struct e1000_hw *hw) -+{ -+ struct e1000_mac_info *mac = &hw->mac; -+ u32 reg = 0; -+ -+ DEBUGFUNC("e1000_configure_pcs_link_82575"); -+ -+ if (hw->phy.media_type != e1000_media_type_copper || -+ !(e1000_sgmii_active_82575(hw))) -+ goto out; -+ -+ /* For SGMII, we need to issue a PCS autoneg restart */ -+ reg = E1000_READ_REG(hw, E1000_PCS_LCTL); -+ -+ /* AN time out should be disabled for SGMII mode */ -+ reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT); -+ -+ if (mac->autoneg) { -+ /* Make sure forced speed and force link are not set */ -+ reg &= ~(E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); -+ -+ /* -+ * The PHY should be setup prior to calling this function. -+ * All we need to do is restart autoneg and enable autoneg. -+ */ -+ reg |= E1000_PCS_LCTL_AN_RESTART | E1000_PCS_LCTL_AN_ENABLE; -+ } else { -+ /* Set PCS register for forced speed */ -+ -+ /* Turn off bits for full duplex, speed, and autoneg */ -+ reg &= ~(E1000_PCS_LCTL_FSV_1000 | -+ E1000_PCS_LCTL_FSV_100 | -+ E1000_PCS_LCTL_FDV_FULL | -+ E1000_PCS_LCTL_AN_ENABLE); -+ -+ /* Check for duplex first */ -+ if (mac->forced_speed_duplex & E1000_ALL_FULL_DUPLEX) -+ reg |= E1000_PCS_LCTL_FDV_FULL; -+ -+ /* Now set speed */ -+ if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) -+ reg |= E1000_PCS_LCTL_FSV_100; -+ -+ /* Force speed and force link */ -+ reg |= E1000_PCS_LCTL_FSD | -+ E1000_PCS_LCTL_FORCE_LINK | -+ E1000_PCS_LCTL_FLV_LINK_UP; -+ -+ DEBUGOUT1("Wrote 0x%08X to PCS_LCTL to configure forced link\n", -+ reg); -+ } -+ E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg); -+ -+out: -+ return E1000_SUCCESS; -+} -+ -+/** + * e1000_sgmii_active_82575 - Return sgmii state + * @hw: pointer to the HW structure + * @@ -1443,12 +1354,6 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig +static bool e1000_sgmii_active_82575(struct e1000_hw *hw) +{ + struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; -+ -+ DEBUGFUNC("e1000_sgmii_active_82575"); -+ -+ if (hw->mac.type != e1000_82575 && hw->mac.type != e1000_82576) -+ return false; -+ + return dev_spec->sgmii_active; +} + @@ -1499,9 +1404,19 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_read_mac_addr_82575"); -+ if (e1000_check_alt_mac_addr_generic(hw)) -+ ret_val = e1000_read_mac_addr_generic(hw); + ++ /* ++ * If there's an alternate MAC address place it in RAR0 ++ * so that it will override the Si installed default perm ++ * address. ++ */ ++ ret_val = e1000_check_alt_mac_addr_generic(hw); ++ if (ret_val) ++ goto out; ++ ++ ret_val = e1000_read_mac_addr_generic(hw); ++ ++out: + return ret_val; +} + @@ -1535,63 +1450,63 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + **/ +static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw) +{ -+ volatile u32 temp; -+ + DEBUGFUNC("e1000_clear_hw_cntrs_82575"); + + e1000_clear_hw_cntrs_base_generic(hw); + -+ temp = E1000_READ_REG(hw, E1000_PRC64); -+ temp = E1000_READ_REG(hw, E1000_PRC127); -+ temp = E1000_READ_REG(hw, E1000_PRC255); -+ temp = E1000_READ_REG(hw, E1000_PRC511); -+ temp = E1000_READ_REG(hw, E1000_PRC1023); -+ temp = E1000_READ_REG(hw, E1000_PRC1522); -+ temp = E1000_READ_REG(hw, E1000_PTC64); -+ temp = E1000_READ_REG(hw, E1000_PTC127); -+ temp = E1000_READ_REG(hw, E1000_PTC255); -+ temp = E1000_READ_REG(hw, E1000_PTC511); -+ temp = E1000_READ_REG(hw, E1000_PTC1023); -+ temp = E1000_READ_REG(hw, E1000_PTC1522); -+ -+ temp = E1000_READ_REG(hw, E1000_ALGNERRC); -+ temp = E1000_READ_REG(hw, E1000_RXERRC); -+ temp = E1000_READ_REG(hw, E1000_TNCRS); -+ temp = E1000_READ_REG(hw, E1000_CEXTERR); -+ temp = E1000_READ_REG(hw, E1000_TSCTC); -+ temp = E1000_READ_REG(hw, E1000_TSCTFC); -+ -+ temp = E1000_READ_REG(hw, E1000_MGTPRC); -+ temp = E1000_READ_REG(hw, E1000_MGTPDC); -+ temp = E1000_READ_REG(hw, E1000_MGTPTC); -+ -+ temp = E1000_READ_REG(hw, E1000_IAC); -+ temp = E1000_READ_REG(hw, E1000_ICRXOC); -+ -+ temp = E1000_READ_REG(hw, E1000_ICRXPTC); -+ temp = E1000_READ_REG(hw, E1000_ICRXATC); -+ temp = E1000_READ_REG(hw, E1000_ICTXPTC); -+ temp = E1000_READ_REG(hw, E1000_ICTXATC); -+ temp = E1000_READ_REG(hw, E1000_ICTXQEC); -+ temp = E1000_READ_REG(hw, E1000_ICTXQMTC); -+ temp = E1000_READ_REG(hw, E1000_ICRXDMTC); -+ -+ temp = E1000_READ_REG(hw, E1000_CBTMPC); -+ temp = E1000_READ_REG(hw, E1000_HTDPMC); -+ temp = E1000_READ_REG(hw, E1000_CBRMPC); -+ temp = E1000_READ_REG(hw, E1000_RPTHC); -+ temp = E1000_READ_REG(hw, E1000_HGPTC); -+ temp = E1000_READ_REG(hw, E1000_HTCBDPC); -+ temp = E1000_READ_REG(hw, E1000_HGORCL); -+ temp = E1000_READ_REG(hw, E1000_HGORCH); -+ temp = E1000_READ_REG(hw, E1000_HGOTCL); -+ temp = E1000_READ_REG(hw, E1000_HGOTCH); -+ temp = E1000_READ_REG(hw, E1000_LENERRS); ++ E1000_READ_REG(hw, E1000_PRC64); ++ E1000_READ_REG(hw, E1000_PRC127); ++ E1000_READ_REG(hw, E1000_PRC255); ++ E1000_READ_REG(hw, E1000_PRC511); ++ E1000_READ_REG(hw, E1000_PRC1023); ++ E1000_READ_REG(hw, E1000_PRC1522); ++ E1000_READ_REG(hw, E1000_PTC64); ++ E1000_READ_REG(hw, E1000_PTC127); ++ E1000_READ_REG(hw, E1000_PTC255); ++ E1000_READ_REG(hw, E1000_PTC511); ++ E1000_READ_REG(hw, E1000_PTC1023); ++ E1000_READ_REG(hw, E1000_PTC1522); ++ ++ E1000_READ_REG(hw, E1000_ALGNERRC); ++ E1000_READ_REG(hw, E1000_RXERRC); ++ E1000_READ_REG(hw, E1000_TNCRS); ++ E1000_READ_REG(hw, E1000_CEXTERR); ++ E1000_READ_REG(hw, E1000_TSCTC); ++ E1000_READ_REG(hw, E1000_TSCTFC); ++ ++ E1000_READ_REG(hw, E1000_MGTPRC); ++ E1000_READ_REG(hw, E1000_MGTPDC); ++ E1000_READ_REG(hw, E1000_MGTPTC); ++ ++ E1000_READ_REG(hw, E1000_IAC); ++ E1000_READ_REG(hw, E1000_ICRXOC); ++ ++ E1000_READ_REG(hw, E1000_ICRXPTC); ++ E1000_READ_REG(hw, E1000_ICRXATC); ++ E1000_READ_REG(hw, E1000_ICTXPTC); ++ E1000_READ_REG(hw, E1000_ICTXATC); ++ E1000_READ_REG(hw, E1000_ICTXQEC); ++ E1000_READ_REG(hw, E1000_ICTXQMTC); ++ E1000_READ_REG(hw, E1000_ICRXDMTC); ++ ++ E1000_READ_REG(hw, E1000_CBTMPC); ++ E1000_READ_REG(hw, E1000_HTDPMC); ++ E1000_READ_REG(hw, E1000_CBRMPC); ++ E1000_READ_REG(hw, E1000_RPTHC); ++ E1000_READ_REG(hw, E1000_HGPTC); ++ E1000_READ_REG(hw, E1000_HTCBDPC); ++ E1000_READ_REG(hw, E1000_HGORCL); ++ E1000_READ_REG(hw, E1000_HGORCH); ++ E1000_READ_REG(hw, E1000_HGOTCL); ++ E1000_READ_REG(hw, E1000_HGOTCH); ++ E1000_READ_REG(hw, E1000_LENERRS); + + /* This register should not be read in copper configurations */ -+ if (hw->phy.media_type == e1000_media_type_internal_serdes) -+ temp = E1000_READ_REG(hw, E1000_SCVPC); ++ if ((hw->phy.media_type == e1000_media_type_internal_serdes) || ++ e1000_sgmii_active_82575(hw)) ++ E1000_READ_REG(hw, E1000_SCVPC); +} ++ +/** + * e1000_rx_fifo_flush_82575 - Clean rx fifo after RX enable + * @hw: pointer to the HW structure @@ -1665,14 +1580,105 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.c linux-i686-2.6.22/drivers/net/ig + E1000_READ_REG(hw, E1000_RNBC); + E1000_READ_REG(hw, E1000_MPC); +} -diff -Nru vanilla/drivers/net/igb/e1000_82575.h linux-i686-2.6.22/drivers/net/igb/e1000_82575.h ---- vanilla/drivers/net/igb/e1000_82575.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/e1000_82575.h 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,452 @@ ++ ++/** ++ * e1000_set_pcie_completion_timeout - set pci-e completion timeout ++ * @hw: pointer to the HW structure ++ * ++ * The defaults for 82575 and 82576 should be in the range of 50us to 50ms, ++ * however the hardware default for these parts is 500us to 1ms which is less ++ * than the 10ms recommended by the pci-e spec. To address this we need to ++ * increase the value to either 10ms to 200ms for capability version 1 config, ++ * or 16ms to 55ms for version 2. ++ **/ ++static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw) ++{ ++ u32 gcr = E1000_READ_REG(hw, E1000_GCR); ++ s32 ret_val = E1000_SUCCESS; ++ u16 pcie_devctl2; ++ ++ /* only take action if timeout value is defaulted to 0 */ ++ if (gcr & E1000_GCR_CMPL_TMOUT_MASK) ++ goto out; ++ ++ /* ++ * if capababilities version is type 1 we can write the ++ * timeout of 10ms to 200ms through the GCR register ++ */ ++ if (!(gcr & E1000_GCR_CAP_VER2)) { ++ gcr |= E1000_GCR_CMPL_TMOUT_10ms; ++ goto out; ++ } ++ ++ /* ++ * for version 2 capabilities we need to write the config space ++ * directly in order to set the completion timeout value for ++ * 16ms to 55ms ++ */ ++ ret_val = e1000_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, ++ &pcie_devctl2); ++ if (ret_val) ++ goto out; ++ ++ pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms; ++ ++ ret_val = e1000_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, ++ &pcie_devctl2); ++out: ++ /* disable completion timeout resend */ ++ gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND; ++ ++ E1000_WRITE_REG(hw, E1000_GCR, gcr); ++ return ret_val; ++} ++ ++/** ++ * e1000_vmdq_set_loopback_pf - enable or disable vmdq loopback ++ * @hw: pointer to the hardware struct ++ * @enable: state to enter, either enabled or disabled ++ * ++ * enables/disables L2 switch loopback functionality. ++ **/ ++void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable) ++{ ++ u32 dtxswc = E1000_READ_REG(hw, E1000_DTXSWC); ++ ++ if (enable) ++ dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN; ++ else ++ dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN; ++ ++ E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc); ++} ++ ++/** ++ * e1000_vmdq_set_replication_pf - enable or disable vmdq replication ++ * @hw: pointer to the hardware struct ++ * @enable: state to enter, either enabled or disabled ++ * ++ * enables/disables replication of packets across multiple pools. ++ **/ ++void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable) ++{ ++ u32 vt_ctl = E1000_READ_REG(hw, E1000_VT_CTL); ++ ++ if (enable) ++ vt_ctl |= E1000_VT_CTL_VM_REPL_EN; ++ else ++ vt_ctl &= ~E1000_VT_CTL_VM_REPL_EN; ++ ++ E1000_WRITE_REG(hw, E1000_VT_CTL, vt_ctl); ++} ++ +Index: linux-2.6.22/drivers/net/igb/e1000_82575.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/e1000_82575.h 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,439 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ Copyright(c) 2007-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, @@ -1717,7 +1723,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.h linux-i686-2.6.22/drivers/net/ig +#define E1000_RAR_ENTRIES_82576 24 + +struct e1000_adv_data_desc { -+ u64 buffer_addr; /* Address of the descriptor's data buffer */ ++ __le64 buffer_addr; /* Address of the descriptor's data buffer */ + union { + u32 data; + struct { @@ -1790,6 +1796,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.h linux-i686-2.6.22/drivers/net/ig +#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION 0x06000000 +#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000 +#define E1000_SRRCTL_DESCTYPE_MASK 0x0E000000 ++#define E1000_SRRCTL_DROP_EN 0x80000000 + +#define E1000_SRRCTL_BSIZEPKT_MASK 0x0000007F +#define E1000_SRRCTL_BSIZEHDR_MASK 0x00003F00 @@ -1799,6 +1806,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.h linux-i686-2.6.22/drivers/net/ig + +#define E1000_MRQC_ENABLE_RSS_4Q 0x00000002 +#define E1000_MRQC_ENABLE_VMDQ 0x00000003 ++#define E1000_MRQC_ENABLE_VMDQ_RSS_2Q 0x00000005 +#define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000 +#define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000 +#define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000 @@ -1845,41 +1853,42 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.h linux-i686-2.6.22/drivers/net/ig +/* Receive Descriptor - Advanced */ +union e1000_adv_rx_desc { + struct { -+ u64 pkt_addr; /* Packet buffer address */ -+ u64 hdr_addr; /* Header buffer address */ ++ __le64 pkt_addr; /* Packet buffer address */ ++ __le64 hdr_addr; /* Header buffer address */ + } read; + struct { + struct { + union { -+ u32 data; ++ __le32 data; + struct { -+ u16 pkt_info; /* RSS type, Packet type */ -+ u16 hdr_info; /* Split Header, -+ * header buffer length */ ++ __le16 pkt_info; /*RSS type, Pkt type*/ ++ __le16 hdr_info; /* Split Header, ++ * header buffer len*/ + } hs_rss; + } lo_dword; + union { -+ u32 rss; /* RSS Hash */ ++ __le32 rss; /* RSS Hash */ + struct { -+ u16 ip_id; /* IP id */ -+ u16 csum; /* Packet Checksum */ ++ __le16 ip_id; /* IP id */ ++ __le16 csum; /* Packet Checksum */ + } csum_ip; + } hi_dword; + } lower; + struct { -+ u32 status_error; /* ext status/error */ -+ u16 length; /* Packet length */ -+ u16 vlan; /* VLAN tag */ ++ __le32 status_error; /* ext status/error */ ++ __le16 length; /* Packet length */ ++ __le16 vlan; /* VLAN tag */ + } upper; + } wb; /* writeback */ +}; + -+#define E1000_RXDADV_RSSTYPE_MASK 0x0000F000 ++#define E1000_RXDADV_RSSTYPE_MASK 0x0000000F +#define E1000_RXDADV_RSSTYPE_SHIFT 12 +#define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0 +#define E1000_RXDADV_HDRBUFLEN_SHIFT 5 +#define E1000_RXDADV_SPLITHEADER_EN 0x00001000 +#define E1000_RXDADV_SPH 0x8000 ++#define E1000_RXDADV_STAT_TS 0x10000 /* Pkt was time stamped */ +#define E1000_RXDADV_ERR_HBO 0x00800000 + +/* RSS Hash results */ @@ -1929,14 +1938,14 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.h linux-i686-2.6.22/drivers/net/ig +/* Transmit Descriptor - Advanced */ +union e1000_adv_tx_desc { + struct { -+ u64 buffer_addr; /* Address of descriptor's data buf */ -+ u32 cmd_type_len; -+ u32 olinfo_status; ++ __le64 buffer_addr; /* Address of descriptor's data buf */ ++ __le32 cmd_type_len; ++ __le32 olinfo_status; + } read; + struct { -+ u64 rsvd; /* Reserved */ -+ u32 nxtseq_seed; -+ u32 status; ++ __le64 rsvd; /* Reserved */ ++ __le32 nxtseq_seed; ++ __le32 status; + } wb; +}; + @@ -1963,10 +1972,10 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.h linux-i686-2.6.22/drivers/net/ig + +/* Context descriptors */ +struct e1000_adv_tx_context_desc { -+ u32 vlan_macip_lens; -+ u32 seqnum_seed; -+ u32 type_tucmd_mlhl; -+ u32 mss_l4len_idx; ++ __le32 vlan_macip_lens; ++ __le32 seqnum_seed; ++ __le32 type_tucmd_mlhl; ++ __le32 mss_l4len_idx; +}; + +#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ @@ -1975,6 +1984,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.h linux-i686-2.6.22/drivers/net/ig +#define E1000_ADVTXD_TUCMD_IPV6 0x00000000 /* IP Packet Type: 0=IPv6 */ +#define E1000_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */ +#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */ ++#define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 Packet TYPE of SCTP */ +#define E1000_ADVTXD_TUCMD_IPSEC_TYPE_ESP 0x00002000 /* IPSec Type ESP */ +/* IPSec Encrypt Enable for ESP */ +#define E1000_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN 0x00004000 @@ -2012,11 +2022,10 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.h linux-i686-2.6.22/drivers/net/ig +#define E1000_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */ +#define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */ + -+/* Additional DCA related definitions, note change in position of CPUID */ +#define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */ +#define E1000_DCA_RXCTRL_CPUID_MASK_82576 0xFF000000 /* Rx CPUID Mask */ -+#define E1000_DCA_TXCTRL_CPUID_SHIFT 24 /* Tx CPUID now in the last byte */ -+#define E1000_DCA_RXCTRL_CPUID_SHIFT 24 /* Rx CPUID now in the last byte */ ++#define E1000_DCA_TXCTRL_CPUID_SHIFT_82576 24 /* Tx CPUID */ ++#define E1000_DCA_RXCTRL_CPUID_SHIFT_82576 24 /* Rx CPUID */ + +/* Additional interrupt register bit definitions */ +#define E1000_ICR_LSECPNS 0x00000020 /* PN threshold - server */ @@ -2026,6 +2035,8 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.h linux-i686-2.6.22/drivers/net/ig +/* ETQF register bit definitions */ +#define E1000_ETQF_FILTER_ENABLE (1 << 26) +#define E1000_ETQF_IMM_INT (1 << 29) ++#define E1000_ETQF_1588 (1 << 30) ++#define E1000_ETQF_QUEUE_ENABLE (1 << 31) +/* + * ETQF filter list: one static filter per filter consumer. This is + * to avoid filter collisions later. Add new filters @@ -2036,12 +2047,22 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.h linux-i686-2.6.22/drivers/net/ig + */ +#define E1000_ETQF_FILTER_EAPOL 0 + ++#define E1000_FTQF_VF_BP 0x00008000 ++#define E1000_FTQF_1588_TIME_STAMP 0x08000000 ++#define E1000_FTQF_MASK 0xF0000000 ++#define E1000_FTQF_MASK_PROTO_BP 0x10000000 ++#define E1000_FTQF_MASK_SOURCE_ADDR_BP 0x20000000 ++#define E1000_FTQF_MASK_DEST_ADDR_BP 0x40000000 ++#define E1000_FTQF_MASK_SOURCE_PORT_BP 0x80000000 ++ +#define E1000_NVM_APME_82575 0x0400 +#define MAX_NUM_VFS 8 + +#define E1000_DTXSWC_MAC_SPOOF_MASK 0x000000FF /* Per VF MAC spoof control */ +#define E1000_DTXSWC_VLAN_SPOOF_MASK 0x0000FF00 /* Per VF VLAN spoof control */ +#define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */ ++#define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8 ++#define E1000_DTXSWC_LLE_SHIFT 16 +#define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31) /* global VF LB enable */ + +/* Easy defines for setting default pool, would normally be left a zero */ @@ -2054,635 +2075,54 @@ diff -Nru vanilla/drivers/net/igb/e1000_82575.h linux-i686-2.6.22/drivers/net/ig +#define E1000_VT_CTL_VM_REPL_EN (1 << 30) + +/* Per VM Offload register setup */ ++#define E1000_VMOLR_RLPML_MASK 0x00003FFF /* Long Packet Maximum Length mask */ +#define E1000_VMOLR_LPE 0x00010000 /* Accept Long packet */ ++#define E1000_VMOLR_RSSE 0x00020000 /* Enable RSS */ +#define E1000_VMOLR_AUPE 0x01000000 /* Accept untagged packets */ ++#define E1000_VMOLR_ROMPE 0x02000000 /* Accept overflow multicast */ ++#define E1000_VMOLR_ROPE 0x04000000 /* Accept overflow unicast */ +#define E1000_VMOLR_BAM 0x08000000 /* Accept Broadcast packets */ +#define E1000_VMOLR_MPME 0x10000000 /* Multicast promiscuous mode */ +#define E1000_VMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */ -+ -+#define E1000_V2PMAILBOX_REQ 0x00000001 /* Request for PF Ready bit */ -+#define E1000_V2PMAILBOX_ACK 0x00000002 /* Ack PF message received */ -+#define E1000_V2PMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ -+#define E1000_V2PMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ -+#define E1000_V2PMAILBOX_PFSTS 0x00000010 /* PF wrote a message in the MB */ -+#define E1000_V2PMAILBOX_PFACK 0x00000020 /* PF ack the previous VF msg */ -+#define E1000_V2PMAILBOX_RSTI 0x00000040 /* PF has reset indication */ -+ -+#define E1000_P2VMAILBOX_STS 0x00000001 /* Initiate message send to VF */ -+#define E1000_P2VMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */ -+#define E1000_P2VMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ -+#define E1000_P2VMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ -+#define E1000_P2VMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */ -+ -+#define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */ -+ -+/* If it's a E1000_VF_* msg then it originates in the VF and is sent to the -+ * PF. The reverse is true if it is E1000_PF_*. -+ * Message ACK's are the value or'd with 0xF0000000 -+ */ -+#define E1000_VT_MSGTYPE_ACK 0xF0000000 /* Messages below or'd with -+ * this are the ACK */ -+#define E1000_VT_MSGTYPE_NACK 0xFF000000 /* Messages below or'd with -+ * this are the NACK */ -+#define E1000_VT_MSGINFO_SHIFT 16 -+/* bits 23:16 are used for exra info for certain messages */ -+#define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT) -+ -+#define E1000_VF_MSGTYPE_REQ_MAC 1 /* VF needs to know its MAC */ -+#define E1000_VF_MSGTYPE_VFLR 2 /* VF notifies VFLR to PF */ -+#define E1000_VF_SET_MULTICAST 3 /* VF requests PF to set MC addr */ -+#define E1000_VF_SET_VLAN 4 /* VF requests PF to set VLAN */ -+ -+/* Add 100h to all PF msgs, leaves room for up to 255 discrete message types -+ * from VF to PF - way more than we'll ever need */ -+#define E1000_PF_MSGTYPE_RESET (1 + 0x100) /* PF notifies global reset -+ * imminent to VF */ -+#define E1000_PF_MSGTYPE_LSC (2 + 0x100) /* PF notifies VF of LSC... VF -+ * will see extra msg info for -+ * status */ -+ -+#define E1000_PF_MSG_LSCDOWN (1 << E1000_VT_MSGINFO_SHIFT) -+#define E1000_PF_MSG_LSCUP (2 << E1000_VT_MSGINFO_SHIFT) -+ -+s32 e1000_send_mail_to_pf_vf(struct e1000_hw *hw, u32 *msg, -+ s16 size); -+s32 e1000_receive_mail_from_pf_vf(struct e1000_hw *hw, -+ u32 *msg, s16 size); -+s32 e1000_send_mail_to_vf(struct e1000_hw *hw, u32 *msg, -+ u32 vf_number, s16 size); -+s32 e1000_receive_mail_from_vf(struct e1000_hw *hw, u32 *msg, -+ u32 vf_number, s16 size); -+void e1000_vmdq_loopback_enable_vf(struct e1000_hw *hw); -+void e1000_vmdq_loopback_disable_vf(struct e1000_hw *hw); -+void e1000_vmdq_replication_enable_vf(struct e1000_hw *hw, u32 enables); -+void e1000_vmdq_replication_disable_vf(struct e1000_hw *hw); -+bool e1000_check_for_pf_ack_vf(struct e1000_hw *hw); -+bool e1000_check_for_pf_mail_vf(struct e1000_hw *hw, u32*); -+ -+ -+#endif -Binary files vanilla/drivers/net/igb/e1000_82575.o and linux-i686-2.6.22/drivers/net/igb/e1000_82575.o differ -diff -Nru vanilla/drivers/net/igb/.e1000_82575.o.cmd linux-i686-2.6.22/drivers/net/igb/.e1000_82575.o.cmd ---- vanilla/drivers/net/igb/.e1000_82575.o.cmd 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/.e1000_82575.o.cmd 2009-07-16 19:52:19.000000000 -0400 -@@ -0,0 +1,549 @@ -+cmd_drivers/net/igb/e1000_82575.o := gcc -m32 -Wp,-MD,drivers/net/igb/.e1000_82575.o.d -nostdinc -isystem /usr/lib/gcc/i386-redhat-linux/4.1.2/include -D__KERNEL__ -Iinclude -include include/linux/autoconf.h -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Os -pipe -msoft-float -mregparm=3 -freg-struct-return -mpreferred-stack-boundary=2 -march=i686 -mtune=generic -ffreestanding -maccumulate-outgoing-args -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -Iinclude/asm-i386/mach-generic -Iinclude/asm-i386/mach-default -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -DMODULE -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(e1000_82575)" -D"KBUILD_MODNAME=KBUILD_STR(igb)" -c -o drivers/net/igb/.tmp_e1000_82575.o drivers/net/igb/e1000_82575.c -+ -+deps_drivers/net/igb/e1000_82575.o := \ -+ drivers/net/igb/e1000_82575.c \ -+ drivers/net/igb/e1000_api.h \ -+ drivers/net/igb/e1000_hw.h \ -+ drivers/net/igb/e1000_osdep.h \ -+ include/linux/pci.h \ -+ $(wildcard include/config/pci/msi.h) \ -+ $(wildcard include/config/pci.h) \ -+ $(wildcard include/config/ht/irq.h) \ -+ $(wildcard include/config/pci/domains.h) \ -+ include/linux/pci_regs.h \ -+ include/linux/mod_devicetable.h \ -+ include/linux/types.h \ -+ $(wildcard include/config/uid16.h) \ -+ $(wildcard include/config/lbd.h) \ -+ $(wildcard include/config/lsf.h) \ -+ $(wildcard include/config/resources/64bit.h) \ -+ include/linux/posix_types.h \ -+ include/linux/stddef.h \ -+ include/linux/compiler.h \ -+ $(wildcard include/config/enable/must/check.h) \ -+ include/linux/compiler-gcc4.h \ -+ $(wildcard include/config/forced/inlining.h) \ -+ include/linux/compiler-gcc.h \ -+ include/asm/posix_types.h \ -+ include/asm/types.h \ -+ $(wildcard include/config/highmem64g.h) \ -+ include/linux/ioport.h \ -+ include/linux/list.h \ -+ $(wildcard include/config/debug/list.h) \ -+ include/linux/poison.h \ -+ include/linux/prefetch.h \ -+ include/asm/processor.h \ -+ $(wildcard include/config/smp.h) \ -+ $(wildcard include/config/x86/ht.h) \ -+ $(wildcard include/config/paravirt.h) \ -+ $(wildcard include/config/mk8.h) \ -+ $(wildcard include/config/mk7.h) \ -+ include/asm/vm86.h \ -+ $(wildcard include/config/vm86.h) \ -+ include/asm/ptrace.h \ -+ include/asm/ptrace-abi.h \ -+ include/asm/segment.h \ -+ include/asm/math_emu.h \ -+ include/asm/sigcontext.h \ -+ include/asm/page.h \ -+ $(wildcard include/config/x86/use/3dnow.h) \ -+ $(wildcard include/config/x86/pae.h) \ -+ $(wildcard include/config/hugetlb/page.h) \ -+ $(wildcard include/config/highmem4g.h) \ -+ $(wildcard include/config/page/offset.h) \ -+ $(wildcard include/config/flatmem.h) \ -+ include/asm-generic/pgtable-nopmd.h \ -+ include/asm-generic/pgtable-nopud.h \ -+ include/asm-generic/memory_model.h \ -+ $(wildcard include/config/discontigmem.h) \ -+ $(wildcard include/config/sparsemem.h) \ -+ $(wildcard include/config/out/of/line/pfn/to/page.h) \ -+ include/asm-generic/page.h \ -+ include/asm/cpufeature.h \ -+ include/linux/bitops.h \ -+ include/asm/bitops.h \ -+ include/asm/alternative.h \ -+ include/asm-generic/bitops/sched.h \ -+ include/asm-generic/bitops/hweight.h \ -+ include/asm-generic/bitops/fls64.h \ -+ include/asm-generic/bitops/ext2-non-atomic.h \ -+ include/asm-generic/bitops/le.h \ -+ include/asm/byteorder.h \ -+ $(wildcard include/config/x86/bswap.h) \ -+ include/linux/byteorder/little_endian.h \ -+ include/linux/byteorder/swab.h \ -+ include/linux/byteorder/generic.h \ -+ include/asm-generic/bitops/minix.h \ -+ include/asm/required-features.h \ -+ $(wildcard include/config/x86/minimum/cpu.h) \ -+ $(wildcard include/config/x86/cmov.h) \ -+ $(wildcard include/config/x86/cmpxchg64.h) \ -+ include/asm/msr.h \ -+ include/asm/msr-index.h \ -+ include/asm/errno.h \ -+ include/asm-generic/errno.h \ -+ include/asm-generic/errno-base.h \ -+ include/linux/errno.h \ -+ include/asm/system.h \ -+ $(wildcard include/config/x86/oostore.h) \ -+ include/linux/kernel.h \ -+ $(wildcard include/config/preempt/voluntary.h) \ -+ $(wildcard include/config/debug/spinlock/sleep.h) \ -+ $(wildcard include/config/printk.h) \ -+ $(wildcard include/config/numa.h) \ -+ /usr/lib/gcc/i386-redhat-linux/4.1.2/include/stdarg.h \ -+ include/linux/linkage.h \ -+ include/asm/linkage.h \ -+ $(wildcard include/config/x86/alignment/16.h) \ -+ include/linux/log2.h \ -+ $(wildcard include/config/arch/has/ilog2/u32.h) \ -+ $(wildcard include/config/arch/has/ilog2/u64.h) \ -+ include/asm/bug.h \ -+ $(wildcard include/config/bug.h) \ -+ $(wildcard include/config/debug/bugverbose.h) \ -+ include/asm-generic/bug.h \ -+ $(wildcard include/config/generic/bug.h) \ -+ include/asm/cmpxchg.h \ -+ $(wildcard include/config/x86/cmpxchg.h) \ -+ include/linux/irqflags.h \ -+ $(wildcard include/config/trace/irqflags.h) \ -+ $(wildcard include/config/trace/irqflags/support.h) \ -+ $(wildcard include/config/x86.h) \ -+ include/asm/irqflags.h \ -+ include/asm/processor-flags.h \ -+ include/linux/cache.h \ -+ include/asm/cache.h \ -+ $(wildcard include/config/x86/l1/cache/shift.h) \ -+ include/linux/threads.h \ -+ $(wildcard include/config/nr/cpus.h) \ -+ $(wildcard include/config/base/small.h) \ -+ include/asm/percpu.h \ -+ include/linux/cpumask.h \ -+ $(wildcard include/config/hotplug/cpu.h) \ -+ include/linux/bitmap.h \ -+ include/linux/string.h \ -+ include/asm/string.h \ -+ include/linux/init.h \ -+ $(wildcard include/config/modules.h) \ -+ $(wildcard include/config/hotplug.h) \ -+ $(wildcard include/config/memory/hotplug.h) \ -+ $(wildcard include/config/acpi/hotplug/memory.h) \ -+ include/asm/atomic.h \ -+ $(wildcard include/config/m386.h) \ -+ include/asm-generic/atomic.h \ -+ include/linux/device.h \ -+ $(wildcard include/config/debug/devres.h) \ -+ include/linux/kobject.h \ -+ include/linux/sysfs.h \ -+ $(wildcard include/config/sysfs.h) \ -+ include/linux/spinlock.h \ -+ $(wildcard include/config/debug/spinlock.h) \ -+ $(wildcard include/config/preempt.h) \ -+ $(wildcard include/config/debug/lock/alloc.h) \ -+ include/linux/preempt.h \ -+ $(wildcard include/config/debug/preempt.h) \ -+ include/linux/thread_info.h \ -+ include/asm/thread_info.h \ -+ $(wildcard include/config/4kstacks.h) \ -+ $(wildcard include/config/debug/stack/usage.h) \ -+ include/linux/stringify.h \ -+ include/linux/bottom_half.h \ -+ include/linux/spinlock_types.h \ -+ include/linux/lockdep.h \ -+ $(wildcard include/config/lockdep.h) \ -+ $(wildcard include/config/generic/hardirqs.h) \ -+ $(wildcard include/config/prove/locking.h) \ -+ include/asm/spinlock_types.h \ -+ include/asm/spinlock.h \ -+ $(wildcard include/config/x86/ppro/fence.h) \ -+ include/asm/rwlock.h \ -+ include/linux/spinlock_api_smp.h \ -+ include/linux/kref.h \ -+ include/linux/wait.h \ -+ include/asm/current.h \ -+ include/linux/klist.h \ -+ include/linux/completion.h \ -+ include/linux/module.h \ -+ $(wildcard include/config/modversions.h) \ -+ $(wildcard include/config/unused/symbols.h) \ -+ $(wildcard include/config/module/unload.h) \ -+ $(wildcard include/config/kallsyms.h) \ -+ include/linux/stat.h \ -+ include/asm/stat.h \ -+ include/linux/time.h \ -+ include/linux/seqlock.h \ -+ include/linux/vs_time.h \ -+ $(wildcard include/config/vserver/vtime.h) \ -+ include/linux/kmod.h \ -+ $(wildcard include/config/kmod.h) \ -+ include/linux/elf.h \ -+ include/linux/auxvec.h \ -+ include/asm/auxvec.h \ -+ include/linux/elf-em.h \ -+ include/asm/elf.h \ -+ include/asm/user.h \ -+ include/asm/desc.h \ -+ include/asm/ldt.h \ -+ include/linux/smp.h \ -+ include/asm/smp.h \ -+ $(wildcard include/config/x86/local/apic.h) \ -+ $(wildcard include/config/x86/io/apic.h) \ -+ include/asm/mpspec.h \ -+ $(wildcard include/config/acpi.h) \ -+ include/asm/mpspec_def.h \ -+ include/asm-i386/mach-generic/mach_mpspec.h \ -+ include/asm/apic.h \ -+ $(wildcard include/config/x86/good/apic.h) \ -+ include/linux/pm.h \ -+ $(wildcard include/config/pm.h) \ -+ include/linux/delay.h \ -+ include/asm/delay.h \ -+ include/asm/fixmap.h \ -+ $(wildcard include/config/highmem.h) \ -+ $(wildcard include/config/x86/visws/apic.h) \ -+ $(wildcard include/config/x86/f00f/bug.h) \ -+ $(wildcard include/config/x86/cyclone/timer.h) \ -+ $(wildcard include/config/pci/mmconfig.h) \ -+ include/asm/acpi.h \ -+ $(wildcard include/config/acpi/sleep.h) \ -+ include/acpi/pdc_intel.h \ -+ include/asm/apicdef.h \ -+ include/asm/kmap_types.h \ -+ $(wildcard include/config/debug/highmem.h) \ -+ include/asm/io_apic.h \ -+ include/asm-i386/mach-generic/mach_apicdef.h \ -+ include/asm/genapic.h \ -+ include/linux/percpu.h \ -+ include/linux/slab.h \ -+ $(wildcard include/config/slab/debug.h) \ -+ $(wildcard include/config/slab.h) \ -+ $(wildcard include/config/slub.h) \ -+ $(wildcard include/config/debug/slab.h) \ -+ include/linux/gfp.h \ -+ $(wildcard include/config/zone/dma.h) \ -+ $(wildcard include/config/zone/dma32.h) \ -+ include/linux/mmzone.h \ -+ $(wildcard include/config/force/max/zoneorder.h) \ -+ $(wildcard include/config/arch/populates/node/map.h) \ -+ $(wildcard include/config/flat/node/mem/map.h) \ -+ $(wildcard include/config/have/memory/present.h) \ -+ $(wildcard include/config/need/node/memmap/size.h) \ -+ $(wildcard include/config/need/multiple/nodes.h) \ -+ $(wildcard include/config/have/arch/early/pfn/to/nid.h) \ -+ $(wildcard include/config/sparsemem/extreme.h) \ -+ $(wildcard include/config/nodes/span/other/nodes.h) \ -+ $(wildcard include/config/holes/in/zone.h) \ -+ include/linux/numa.h \ -+ $(wildcard include/config/nodes/shift.h) \ -+ include/linux/nodemask.h \ -+ include/linux/memory_hotplug.h \ -+ $(wildcard include/config/have/arch/nodedata/extension.h) \ -+ include/linux/notifier.h \ -+ include/linux/mutex.h \ -+ $(wildcard include/config/debug/mutexes.h) \ -+ $(wildcard include/config/chopstix.h) \ -+ include/linux/rwsem.h \ -+ $(wildcard include/config/rwsem/generic/spinlock.h) \ -+ include/asm/rwsem.h \ -+ include/linux/srcu.h \ -+ include/linux/topology.h \ -+ $(wildcard include/config/sched/smt.h) \ -+ $(wildcard include/config/sched/mc.h) \ -+ include/asm/topology.h \ -+ include/asm-generic/topology.h \ -+ include/linux/slab_def.h \ -+ include/linux/kmalloc_sizes.h \ -+ include/asm/mmu.h \ -+ include/asm/semaphore.h \ -+ include/linux/moduleparam.h \ -+ include/asm/local.h \ -+ include/asm/module.h \ -+ $(wildcard include/config/m486.h) \ -+ $(wildcard include/config/m586.h) \ -+ $(wildcard include/config/m586tsc.h) \ -+ $(wildcard include/config/m586mmx.h) \ -+ $(wildcard include/config/mcore2.h) \ -+ $(wildcard include/config/m686.h) \ -+ $(wildcard include/config/mpentiumii.h) \ -+ $(wildcard include/config/mpentiumiii.h) \ -+ $(wildcard include/config/mpentiumm.h) \ -+ $(wildcard include/config/mpentium4.h) \ -+ $(wildcard include/config/mk6.h) \ -+ $(wildcard include/config/x86/elan.h) \ -+ $(wildcard include/config/mcrusoe.h) \ -+ $(wildcard include/config/mefficeon.h) \ -+ $(wildcard include/config/mwinchipc6.h) \ -+ $(wildcard include/config/mwinchip2.h) \ -+ $(wildcard include/config/mwinchip3d.h) \ -+ $(wildcard include/config/mcyrixiii.h) \ -+ $(wildcard include/config/mviac3/2.h) \ -+ $(wildcard include/config/mviac7.h) \ -+ $(wildcard include/config/mgeodegx1.h) \ -+ $(wildcard include/config/mgeode/lx.h) \ -+ include/asm/device.h \ -+ include/linux/pci_ids.h \ -+ include/linux/dmapool.h \ -+ include/asm/io.h \ -+ $(wildcard include/config/x86/numaq.h) \ -+ include/asm-generic/iomap.h \ -+ include/linux/vmalloc.h \ -+ include/asm/scatterlist.h \ -+ include/asm/pci.h \ -+ include/linux/mm.h \ -+ $(wildcard include/config/sysctl.h) \ -+ $(wildcard include/config/mmu.h) \ -+ $(wildcard include/config/stack/growsup.h) \ -+ $(wildcard include/config/debug/vm.h) \ -+ $(wildcard include/config/shmem.h) \ -+ $(wildcard include/config/split/ptlock/cpus.h) \ -+ $(wildcard include/config/ia64.h) \ -+ $(wildcard include/config/proc/fs.h) \ -+ $(wildcard include/config/debug/pagealloc.h) \ -+ include/linux/capability.h \ -+ include/linux/rbtree.h \ -+ include/linux/prio_tree.h \ -+ include/linux/fs.h \ -+ $(wildcard include/config/dnotify.h) \ -+ $(wildcard include/config/vserver/cowbl.h) \ -+ $(wildcard include/config/quota.h) \ -+ $(wildcard include/config/inotify.h) \ -+ $(wildcard include/config/security.h) \ -+ $(wildcard include/config/epoll.h) \ -+ $(wildcard include/config/auditsyscall.h) \ -+ $(wildcard include/config/block.h) \ -+ $(wildcard include/config/fs/xip.h) \ -+ $(wildcard include/config/migration.h) \ -+ include/linux/limits.h \ -+ include/linux/ioctl.h \ -+ include/asm/ioctl.h \ -+ include/asm-generic/ioctl.h \ -+ include/linux/kdev_t.h \ -+ include/linux/dcache.h \ -+ $(wildcard include/config/profiling.h) \ -+ include/linux/rcupdate.h \ -+ include/linux/namei.h \ -+ include/linux/radix-tree.h \ -+ include/linux/pid.h \ -+ include/linux/quota.h \ -+ include/linux/dqblk_xfs.h \ -+ include/linux/dqblk_v1.h \ -+ include/linux/dqblk_v2.h \ -+ include/linux/nfs_fs_i.h \ -+ include/linux/nfs.h \ -+ include/linux/sunrpc/msg_prot.h \ -+ include/linux/fcntl.h \ -+ include/asm/fcntl.h \ -+ include/asm-generic/fcntl.h \ -+ $(wildcard include/config/64bit.h) \ -+ include/linux/err.h \ -+ include/linux/debug_locks.h \ -+ $(wildcard include/config/debug/locking/api/selftests.h) \ -+ include/linux/backing-dev.h \ -+ include/linux/mm_types.h \ -+ include/asm/pgtable.h \ -+ $(wildcard include/config/highpte.h) \ -+ include/asm/paravirt.h \ -+ include/asm/pgtable-2level-defs.h \ -+ include/asm/pgtable-2level.h \ -+ include/asm-generic/pgtable.h \ -+ include/linux/page-flags.h \ -+ $(wildcard include/config/s390.h) \ -+ $(wildcard include/config/swap.h) \ -+ include/linux/vmstat.h \ -+ $(wildcard include/config/vm/event/counters.h) \ -+ include/asm-generic/pci-dma-compat.h \ -+ include/linux/dma-mapping.h \ -+ include/asm/dma-mapping.h \ -+ include/asm-generic/pci.h \ -+ include/linux/interrupt.h \ -+ $(wildcard include/config/high/res/timers.h) \ -+ $(wildcard include/config/generic/irq/probe.h) \ -+ include/linux/irqreturn.h \ -+ include/linux/hardirq.h \ -+ $(wildcard include/config/preempt/bkl.h) \ -+ $(wildcard include/config/virt/cpu/accounting.h) \ -+ include/linux/smp_lock.h \ -+ $(wildcard include/config/lock/kernel.h) \ -+ include/linux/sched.h \ -+ $(wildcard include/config/no/hz.h) \ -+ $(wildcard include/config/detect/softlockup.h) \ -+ $(wildcard include/config/keys.h) \ -+ $(wildcard include/config/bsd/process/acct.h) \ -+ $(wildcard include/config/taskstats.h) \ -+ $(wildcard include/config/inotify/user.h) \ -+ $(wildcard include/config/schedstats.h) \ -+ $(wildcard include/config/task/delay/acct.h) \ -+ $(wildcard include/config/blk/dev/io/trace.h) \ -+ $(wildcard include/config/cc/stackprotector.h) \ -+ $(wildcard include/config/sysvipc.h) \ -+ $(wildcard include/config/rt/mutexes.h) \ -+ $(wildcard include/config/task/xacct.h) \ -+ $(wildcard include/config/cpusets.h) \ -+ $(wildcard include/config/compat.h) \ -+ $(wildcard include/config/fault/injection.h) \ -+ include/asm/param.h \ -+ $(wildcard include/config/hz.h) \ -+ include/linux/timex.h \ -+ $(wildcard include/config/time/interpolation.h) \ -+ include/asm/timex.h \ -+ include/asm/tsc.h \ -+ $(wildcard include/config/x86/tsc.h) \ -+ $(wildcard include/config/x86/generic.h) \ -+ include/linux/jiffies.h \ -+ include/linux/calc64.h \ -+ include/asm/div64.h \ -+ include/asm/cputime.h \ -+ include/asm-generic/cputime.h \ -+ include/linux/sem.h \ -+ include/linux/ipc.h \ -+ $(wildcard include/config/ipc/ns.h) \ -+ include/asm/ipcbuf.h \ -+ include/asm/sembuf.h \ -+ include/linux/signal.h \ -+ include/asm/signal.h \ -+ include/asm-generic/signal.h \ -+ include/asm/siginfo.h \ -+ include/asm-generic/siginfo.h \ -+ include/linux/securebits.h \ -+ include/linux/fs_struct.h \ -+ include/linux/seccomp.h \ -+ $(wildcard include/config/seccomp.h) \ -+ include/linux/futex.h \ -+ $(wildcard include/config/futex.h) \ -+ include/linux/rtmutex.h \ -+ $(wildcard include/config/debug/rt/mutexes.h) \ -+ include/linux/plist.h \ -+ $(wildcard include/config/debug/pi/list.h) \ -+ include/linux/param.h \ -+ include/linux/resource.h \ -+ include/asm/resource.h \ -+ include/asm-generic/resource.h \ -+ include/linux/timer.h \ -+ $(wildcard include/config/timer/stats.h) \ -+ include/linux/ktime.h \ -+ $(wildcard include/config/ktime/scalar.h) \ -+ include/linux/hrtimer.h \ -+ include/linux/task_io_accounting.h \ -+ $(wildcard include/config/task/io/accounting.h) \ -+ include/linux/aio.h \ -+ include/linux/workqueue.h \ -+ include/linux/aio_abi.h \ -+ include/linux/uio.h \ -+ include/asm/hardirq.h \ -+ include/linux/irq.h \ -+ $(wildcard include/config/irq/per/cpu.h) \ -+ $(wildcard include/config/irq/release/method.h) \ -+ $(wildcard include/config/generic/pending/irq.h) \ -+ $(wildcard include/config/irqbalance.h) \ -+ $(wildcard include/config/auto/irq/affinity.h) \ -+ $(wildcard include/config/generic/hardirqs/no//do/irq.h) \ -+ include/asm/irq.h \ -+ include/asm-i386/mach-default/irq_vectors.h \ -+ include/asm-i386/mach-default/irq_vectors_limits.h \ -+ include/asm/irq_regs.h \ -+ include/asm/hw_irq.h \ -+ include/linux/profile.h \ -+ include/asm/sections.h \ -+ include/asm-generic/sections.h \ -+ include/linux/irq_cpustat.h \ -+ include/linux/if_ether.h \ -+ include/linux/skbuff.h \ -+ $(wildcard include/config/nf/conntrack.h) \ -+ $(wildcard include/config/bridge/netfilter.h) \ -+ $(wildcard include/config/vlan/8021q.h) \ -+ $(wildcard include/config/net/sched.h) \ -+ $(wildcard include/config/net/cls/act.h) \ -+ $(wildcard include/config/net/dma.h) \ -+ $(wildcard include/config/network/secmark.h) \ -+ include/linux/net.h \ -+ include/asm/socket.h \ -+ include/asm/sockios.h \ -+ include/linux/random.h \ -+ include/linux/sysctl.h \ -+ $(wildcard include/config/icmp/ipod.h) \ -+ $(wildcard include/config/web100/net100.h) \ -+ $(wildcard include/config/web100/stats.h) \ -+ include/linux/textsearch.h \ -+ include/net/checksum.h \ -+ include/asm/uaccess.h \ -+ $(wildcard include/config/x86/intel/usercopy.h) \ -+ $(wildcard include/config/x86/wp/works/ok.h) \ -+ include/asm/checksum.h \ -+ include/linux/in6.h \ -+ include/linux/dmaengine.h \ -+ $(wildcard include/config/dma/engine.h) \ -+ drivers/net/igb/kcompat.h \ -+ $(wildcard include/config/e1000/napi.h) \ -+ $(wildcard include/config/e1000e/napi.h) \ -+ $(wildcard include/config/ixgb/napi.h) \ -+ $(wildcard include/config/e1000/disable/packet/split.h) \ -+ $(wildcard include/config/igb/disable/packet/split.h) \ -+ $(wildcard include/config/net/poll/controller.h) \ -+ $(wildcard include/config/space/len.h) \ -+ $(wildcard include/config/netpoll.h) \ -+ $(wildcard include/config/netdevices/multiqueue.h) \ -+ include/linux/version.h \ -+ include/linux/netdevice.h \ -+ $(wildcard include/config/ax25.h) \ -+ $(wildcard include/config/tr.h) \ -+ $(wildcard include/config/net/ipip.h) \ -+ $(wildcard include/config/net/ipgre.h) \ -+ $(wildcard include/config/ipv6/sit.h) \ -+ $(wildcard include/config/ipv6/tunnel.h) \ -+ $(wildcard include/config/wireless/ext.h) \ -+ $(wildcard include/config/netpoll/trap.h) \ -+ include/linux/if.h \ -+ include/linux/socket.h \ -+ include/linux/sockios.h \ -+ include/linux/hdlc/ioctl.h \ -+ include/linux/if_packet.h \ -+ include/linux/etherdevice.h \ -+ include/linux/in.h \ -+ include/linux/ip.h \ -+ include/linux/udp.h \ -+ include/net/inet_sock.h \ -+ $(wildcard include/config/ipv6.h) \ -+ include/linux/jhash.h \ -+ include/net/flow.h \ -+ $(wildcard include/config/ipv6/mip6.h) \ -+ include/net/sock.h \ -+ $(wildcard include/config/security/network.h) \ -+ include/linux/security.h \ -+ $(wildcard include/config/security/network/xfrm.h) \ -+ include/linux/binfmts.h \ -+ include/linux/shm.h \ -+ include/asm/shmparam.h \ -+ include/asm/shmbuf.h \ -+ include/linux/msg.h \ -+ include/asm/msgbuf.h \ -+ include/linux/key.h \ -+ include/linux/xfrm.h \ -+ include/linux/filter.h \ -+ include/net/dst.h \ -+ $(wildcard include/config/net/cls/route.h) \ -+ $(wildcard include/config/xfrm.h) \ -+ include/linux/rtnetlink.h \ -+ include/linux/netlink.h \ -+ include/linux/if_link.h \ -+ include/linux/if_addr.h \ -+ include/linux/neighbour.h \ -+ include/net/neighbour.h \ -+ include/linux/seq_file.h \ -+ include/net/rtnetlink.h \ -+ include/net/netlink.h \ -+ include/net/request_sock.h \ -+ include/linux/mii.h \ -+ include/linux/latency.h \ -+ drivers/net/igb/e1000_regs.h \ -+ drivers/net/igb/e1000_defines.h \ -+ $(wildcard include/config/res.h) \ -+ $(wildcard include/config/fault.h) \ -+ drivers/net/igb/e1000_mac.h \ -+ drivers/net/igb/e1000_phy.h \ -+ drivers/net/igb/e1000_nvm.h \ -+ drivers/net/igb/e1000_manage.h \ -+ drivers/net/igb/e1000_82575.h \ -+ -+drivers/net/igb/e1000_82575.o: $(deps_drivers/net/igb/e1000_82575.o) -+ -+$(deps_drivers/net/igb/e1000_82575.o): -diff -Nru vanilla/drivers/net/igb/e1000_api.c linux-i686-2.6.22/drivers/net/igb/e1000_api.c ---- vanilla/drivers/net/igb/e1000_api.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/e1000_api.c 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,1057 @@ ++#define E1000_VMOLR_STRCRC 0x80000000 /* CRC stripping enable */ ++ ++#define E1000_VLVF_ARRAY_SIZE 32 ++#define E1000_VLVF_VLANID_MASK 0x00000FFF ++#define E1000_VLVF_POOLSEL_SHIFT 12 ++#define E1000_VLVF_POOLSEL_MASK (0xFF << E1000_VLVF_POOLSEL_SHIFT) ++#define E1000_VLVF_LVLAN 0x00100000 ++#define E1000_VLVF_VLANID_ENABLE 0x80000000 ++ ++#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */ ++ ++#define E1000_IOVCTL 0x05BBC ++#define E1000_IOVCTL_REUSE_VFQ 0x00000001 ++ ++#define E1000_RPLOLR_STRVLAN 0x40000000 ++#define E1000_RPLOLR_STRCRC 0x80000000 ++ ++#define E1000_DTXCTL_8023LL 0x0004 ++#define E1000_DTXCTL_VLAN_ADDED 0x0008 ++#define E1000_DTXCTL_OOS_ENABLE 0x0010 ++#define E1000_DTXCTL_MDP_EN 0x0020 ++#define E1000_DTXCTL_SPOOF_INT 0x0040 ++ ++#define ALL_QUEUES 0xFFFF ++ ++/* RX packet buffer size defines */ ++#define E1000_RXPBS_SIZE_MASK_82576 0x0000007F ++void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable); ++void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable); ++#endif /* _E1000_82575_H_ */ +Index: linux-2.6.22/drivers/net/igb/e1000_api.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/e1000_api.c 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,1096 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ Copyright(c) 2007-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, @@ -2787,6 +2227,32 @@ diff -Nru vanilla/drivers/net/igb/e1000_api.c linux-i686-2.6.22/drivers/net/igb/ +} + +/** ++ * e1000_init_mbx_params - Initialize mailbox function pointers ++ * @hw: pointer to the HW structure ++ * ++ * This function initializes the function pointers for the PHY ++ * set of functions. Called by drivers or by e1000_setup_init_funcs. ++ **/ ++s32 e1000_init_mbx_params(struct e1000_hw *hw) ++{ ++ s32 ret_val = E1000_SUCCESS; ++ ++ if (hw->mbx.ops.init_params) { ++ ret_val = hw->mbx.ops.init_params(hw); ++ if (ret_val) { ++ DEBUGOUT("Mailbox Initialization Error\n"); ++ goto out; ++ } ++ } else { ++ DEBUGOUT("mbx.init_mbx_params was NULL\n"); ++ ret_val = -E1000_ERR_CONFIG; ++ } ++ ++out: ++ return ret_val; ++} ++ ++/** + * e1000_set_mac_type - Sets MAC type + * @hw: pointer to the HW structure + * @@ -2811,6 +2277,10 @@ diff -Nru vanilla/drivers/net/igb/e1000_api.c linux-i686-2.6.22/drivers/net/igb/ + case E1000_DEV_ID_82576: + case E1000_DEV_ID_82576_FIBER: + case E1000_DEV_ID_82576_SERDES: ++ case E1000_DEV_ID_82576_QUAD_COPPER: ++ case E1000_DEV_ID_82576_NS: ++ case E1000_DEV_ID_82576_NS_SERDES: ++ case E1000_DEV_ID_82576_SERDES_QUAD: + mac->type = e1000_82576; + break; + default: @@ -2857,6 +2327,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_api.c linux-i686-2.6.22/drivers/net/igb/ + */ + e1000_init_mac_ops_generic(hw); + e1000_init_nvm_ops_generic(hw); ++ e1000_init_mbx_ops_generic(hw); + + /* + * Set up the init function pointers. These are functions within the @@ -2891,6 +2362,9 @@ diff -Nru vanilla/drivers/net/igb/e1000_api.c linux-i686-2.6.22/drivers/net/igb/ + if (ret_val) + goto out; + ++ ret_val = e1000_init_mbx_params(hw); ++ if (ret_val) ++ goto out; + } + +out: @@ -2946,26 +2420,16 @@ diff -Nru vanilla/drivers/net/igb/e1000_api.c linux-i686-2.6.22/drivers/net/igb/ + * @hw: pointer to the HW structure + * @mc_addr_list: array of multicast addresses to program + * @mc_addr_count: number of multicast addresses to program -+ * @rar_used_count: the first RAR register free to program -+ * @rar_count: total number of supported Receive Address Registers + * -+ * Updates the Receive Address Registers and Multicast Table Array. ++ * Updates the Multicast Table Array. + * The caller must have a packed mc_addr_list of multicast addresses. -+ * The parameter rar_count will usually be hw->mac.rar_entry_count -+ * unless there are workarounds that change this. Currently no func pointer -+ * exists and all implementations are handled in the generic version of this -+ * function. + **/ +void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list, -+ u32 mc_addr_count, u32 rar_used_count, -+ u32 rar_count) ++ u32 mc_addr_count) +{ + if (hw->mac.ops.update_mc_addr_list) -+ hw->mac.ops.update_mc_addr_list(hw, -+ mc_addr_list, -+ mc_addr_count, -+ rar_used_count, -+ rar_count); ++ hw->mac.ops.update_mc_addr_list(hw, mc_addr_list, ++ mc_addr_count); +} + +/** @@ -3137,6 +2601,21 @@ diff -Nru vanilla/drivers/net/igb/e1000_api.c linux-i686-2.6.22/drivers/net/igb/ +} + +/** ++ * e1000_id_led_init - store LED configurations in SW ++ * @hw: pointer to the HW structure ++ * ++ * Initializes the LED config in SW. This is a function pointer entry point ++ * called by drivers. ++ **/ ++s32 e1000_id_led_init(struct e1000_hw *hw) ++{ ++ if (hw->mac.ops.id_led_init) ++ return hw->mac.ops.id_led_init(hw); ++ ++ return E1000_SUCCESS; ++} ++ ++/** + * e1000_led_on - Turn on SW controllable LED + * @hw: pointer to the HW structure + * @@ -3736,14 +3215,15 @@ diff -Nru vanilla/drivers/net/igb/e1000_api.c linux-i686-2.6.22/drivers/net/igb/ + hw->mac.ops.shutdown_serdes(hw); +} + -diff -Nru vanilla/drivers/net/igb/e1000_api.h linux-i686-2.6.22/drivers/net/igb/e1000_api.h ---- vanilla/drivers/net/igb/e1000_api.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/e1000_api.h 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,146 @@ +Index: linux-2.6.22/drivers/net/igb/e1000_api.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/e1000_api.h 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,147 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ Copyright(c) 2007-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, @@ -3782,6 +3262,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_api.h linux-i686-2.6.22/drivers/net/igb/ +s32 e1000_init_mac_params(struct e1000_hw *hw); +s32 e1000_init_nvm_params(struct e1000_hw *hw); +s32 e1000_init_phy_params(struct e1000_hw *hw); ++s32 e1000_init_mbx_params(struct e1000_hw *hw); +s32 e1000_get_bus_info(struct e1000_hw *hw); +void e1000_clear_vfta(struct e1000_hw *hw); +void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value); @@ -3798,14 +3279,14 @@ diff -Nru vanilla/drivers/net/igb/e1000_api.h linux-i686-2.6.22/drivers/net/igb/ +void e1000_mta_set(struct e1000_hw *hw, u32 hash_value); +u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr); +void e1000_update_mc_addr_list(struct e1000_hw *hw, -+ u8 *mc_addr_list, u32 mc_addr_count, -+ u32 rar_used_count, u32 rar_count); ++ u8 *mc_addr_list, u32 mc_addr_count); +s32 e1000_setup_led(struct e1000_hw *hw); +s32 e1000_cleanup_led(struct e1000_hw *hw); +s32 e1000_check_reset_block(struct e1000_hw *hw); +s32 e1000_blink_led(struct e1000_hw *hw); +s32 e1000_led_on(struct e1000_hw *hw); +s32 e1000_led_off(struct e1000_hw *hw); ++s32 e1000_id_led_init(struct e1000_hw *hw); +void e1000_reset_adaptive(struct e1000_hw *hw); +void e1000_update_adaptive(struct e1000_hw *hw); +s32 e1000_get_cable_length(struct e1000_hw *hw); @@ -3886,568 +3367,15 @@ diff -Nru vanilla/drivers/net/igb/e1000_api.h linux-i686-2.6.22/drivers/net/igb/ + ((length) <= (max_frame_size + VLAN_TAG_SIZE + 1))))) + +#endif -Binary files vanilla/drivers/net/igb/e1000_api.o and linux-i686-2.6.22/drivers/net/igb/e1000_api.o differ -diff -Nru vanilla/drivers/net/igb/.e1000_api.o.cmd linux-i686-2.6.22/drivers/net/igb/.e1000_api.o.cmd ---- vanilla/drivers/net/igb/.e1000_api.o.cmd 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/.e1000_api.o.cmd 2009-07-16 19:53:45.000000000 -0400 -@@ -0,0 +1,549 @@ -+cmd_drivers/net/igb/e1000_api.o := gcc -m32 -Wp,-MD,drivers/net/igb/.e1000_api.o.d -nostdinc -isystem /usr/lib/gcc/i386-redhat-linux/4.1.2/include -D__KERNEL__ -Iinclude -include include/linux/autoconf.h -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Os -pipe -msoft-float -mregparm=3 -freg-struct-return -mpreferred-stack-boundary=2 -march=i686 -mtune=generic -ffreestanding -maccumulate-outgoing-args -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -Iinclude/asm-i386/mach-generic -Iinclude/asm-i386/mach-default -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -DMODULE -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(e1000_api)" -D"KBUILD_MODNAME=KBUILD_STR(igb)" -c -o drivers/net/igb/.tmp_e1000_api.o drivers/net/igb/e1000_api.c -+ -+deps_drivers/net/igb/e1000_api.o := \ -+ drivers/net/igb/e1000_api.c \ -+ drivers/net/igb/e1000_api.h \ -+ drivers/net/igb/e1000_hw.h \ -+ drivers/net/igb/e1000_osdep.h \ -+ include/linux/pci.h \ -+ $(wildcard include/config/pci/msi.h) \ -+ $(wildcard include/config/pci.h) \ -+ $(wildcard include/config/ht/irq.h) \ -+ $(wildcard include/config/pci/domains.h) \ -+ include/linux/pci_regs.h \ -+ include/linux/mod_devicetable.h \ -+ include/linux/types.h \ -+ $(wildcard include/config/uid16.h) \ -+ $(wildcard include/config/lbd.h) \ -+ $(wildcard include/config/lsf.h) \ -+ $(wildcard include/config/resources/64bit.h) \ -+ include/linux/posix_types.h \ -+ include/linux/stddef.h \ -+ include/linux/compiler.h \ -+ $(wildcard include/config/enable/must/check.h) \ -+ include/linux/compiler-gcc4.h \ -+ $(wildcard include/config/forced/inlining.h) \ -+ include/linux/compiler-gcc.h \ -+ include/asm/posix_types.h \ -+ include/asm/types.h \ -+ $(wildcard include/config/highmem64g.h) \ -+ include/linux/ioport.h \ -+ include/linux/list.h \ -+ $(wildcard include/config/debug/list.h) \ -+ include/linux/poison.h \ -+ include/linux/prefetch.h \ -+ include/asm/processor.h \ -+ $(wildcard include/config/smp.h) \ -+ $(wildcard include/config/x86/ht.h) \ -+ $(wildcard include/config/paravirt.h) \ -+ $(wildcard include/config/mk8.h) \ -+ $(wildcard include/config/mk7.h) \ -+ include/asm/vm86.h \ -+ $(wildcard include/config/vm86.h) \ -+ include/asm/ptrace.h \ -+ include/asm/ptrace-abi.h \ -+ include/asm/segment.h \ -+ include/asm/math_emu.h \ -+ include/asm/sigcontext.h \ -+ include/asm/page.h \ -+ $(wildcard include/config/x86/use/3dnow.h) \ -+ $(wildcard include/config/x86/pae.h) \ -+ $(wildcard include/config/hugetlb/page.h) \ -+ $(wildcard include/config/highmem4g.h) \ -+ $(wildcard include/config/page/offset.h) \ -+ $(wildcard include/config/flatmem.h) \ -+ include/asm-generic/pgtable-nopmd.h \ -+ include/asm-generic/pgtable-nopud.h \ -+ include/asm-generic/memory_model.h \ -+ $(wildcard include/config/discontigmem.h) \ -+ $(wildcard include/config/sparsemem.h) \ -+ $(wildcard include/config/out/of/line/pfn/to/page.h) \ -+ include/asm-generic/page.h \ -+ include/asm/cpufeature.h \ -+ include/linux/bitops.h \ -+ include/asm/bitops.h \ -+ include/asm/alternative.h \ -+ include/asm-generic/bitops/sched.h \ -+ include/asm-generic/bitops/hweight.h \ -+ include/asm-generic/bitops/fls64.h \ -+ include/asm-generic/bitops/ext2-non-atomic.h \ -+ include/asm-generic/bitops/le.h \ -+ include/asm/byteorder.h \ -+ $(wildcard include/config/x86/bswap.h) \ -+ include/linux/byteorder/little_endian.h \ -+ include/linux/byteorder/swab.h \ -+ include/linux/byteorder/generic.h \ -+ include/asm-generic/bitops/minix.h \ -+ include/asm/required-features.h \ -+ $(wildcard include/config/x86/minimum/cpu.h) \ -+ $(wildcard include/config/x86/cmov.h) \ -+ $(wildcard include/config/x86/cmpxchg64.h) \ -+ include/asm/msr.h \ -+ include/asm/msr-index.h \ -+ include/asm/errno.h \ -+ include/asm-generic/errno.h \ -+ include/asm-generic/errno-base.h \ -+ include/linux/errno.h \ -+ include/asm/system.h \ -+ $(wildcard include/config/x86/oostore.h) \ -+ include/linux/kernel.h \ -+ $(wildcard include/config/preempt/voluntary.h) \ -+ $(wildcard include/config/debug/spinlock/sleep.h) \ -+ $(wildcard include/config/printk.h) \ -+ $(wildcard include/config/numa.h) \ -+ /usr/lib/gcc/i386-redhat-linux/4.1.2/include/stdarg.h \ -+ include/linux/linkage.h \ -+ include/asm/linkage.h \ -+ $(wildcard include/config/x86/alignment/16.h) \ -+ include/linux/log2.h \ -+ $(wildcard include/config/arch/has/ilog2/u32.h) \ -+ $(wildcard include/config/arch/has/ilog2/u64.h) \ -+ include/asm/bug.h \ -+ $(wildcard include/config/bug.h) \ -+ $(wildcard include/config/debug/bugverbose.h) \ -+ include/asm-generic/bug.h \ -+ $(wildcard include/config/generic/bug.h) \ -+ include/asm/cmpxchg.h \ -+ $(wildcard include/config/x86/cmpxchg.h) \ -+ include/linux/irqflags.h \ -+ $(wildcard include/config/trace/irqflags.h) \ -+ $(wildcard include/config/trace/irqflags/support.h) \ -+ $(wildcard include/config/x86.h) \ -+ include/asm/irqflags.h \ -+ include/asm/processor-flags.h \ -+ include/linux/cache.h \ -+ include/asm/cache.h \ -+ $(wildcard include/config/x86/l1/cache/shift.h) \ -+ include/linux/threads.h \ -+ $(wildcard include/config/nr/cpus.h) \ -+ $(wildcard include/config/base/small.h) \ -+ include/asm/percpu.h \ -+ include/linux/cpumask.h \ -+ $(wildcard include/config/hotplug/cpu.h) \ -+ include/linux/bitmap.h \ -+ include/linux/string.h \ -+ include/asm/string.h \ -+ include/linux/init.h \ -+ $(wildcard include/config/modules.h) \ -+ $(wildcard include/config/hotplug.h) \ -+ $(wildcard include/config/memory/hotplug.h) \ -+ $(wildcard include/config/acpi/hotplug/memory.h) \ -+ include/asm/atomic.h \ -+ $(wildcard include/config/m386.h) \ -+ include/asm-generic/atomic.h \ -+ include/linux/device.h \ -+ $(wildcard include/config/debug/devres.h) \ -+ include/linux/kobject.h \ -+ include/linux/sysfs.h \ -+ $(wildcard include/config/sysfs.h) \ -+ include/linux/spinlock.h \ -+ $(wildcard include/config/debug/spinlock.h) \ -+ $(wildcard include/config/preempt.h) \ -+ $(wildcard include/config/debug/lock/alloc.h) \ -+ include/linux/preempt.h \ -+ $(wildcard include/config/debug/preempt.h) \ -+ include/linux/thread_info.h \ -+ include/asm/thread_info.h \ -+ $(wildcard include/config/4kstacks.h) \ -+ $(wildcard include/config/debug/stack/usage.h) \ -+ include/linux/stringify.h \ -+ include/linux/bottom_half.h \ -+ include/linux/spinlock_types.h \ -+ include/linux/lockdep.h \ -+ $(wildcard include/config/lockdep.h) \ -+ $(wildcard include/config/generic/hardirqs.h) \ -+ $(wildcard include/config/prove/locking.h) \ -+ include/asm/spinlock_types.h \ -+ include/asm/spinlock.h \ -+ $(wildcard include/config/x86/ppro/fence.h) \ -+ include/asm/rwlock.h \ -+ include/linux/spinlock_api_smp.h \ -+ include/linux/kref.h \ -+ include/linux/wait.h \ -+ include/asm/current.h \ -+ include/linux/klist.h \ -+ include/linux/completion.h \ -+ include/linux/module.h \ -+ $(wildcard include/config/modversions.h) \ -+ $(wildcard include/config/unused/symbols.h) \ -+ $(wildcard include/config/module/unload.h) \ -+ $(wildcard include/config/kallsyms.h) \ -+ include/linux/stat.h \ -+ include/asm/stat.h \ -+ include/linux/time.h \ -+ include/linux/seqlock.h \ -+ include/linux/vs_time.h \ -+ $(wildcard include/config/vserver/vtime.h) \ -+ include/linux/kmod.h \ -+ $(wildcard include/config/kmod.h) \ -+ include/linux/elf.h \ -+ include/linux/auxvec.h \ -+ include/asm/auxvec.h \ -+ include/linux/elf-em.h \ -+ include/asm/elf.h \ -+ include/asm/user.h \ -+ include/asm/desc.h \ -+ include/asm/ldt.h \ -+ include/linux/smp.h \ -+ include/asm/smp.h \ -+ $(wildcard include/config/x86/local/apic.h) \ -+ $(wildcard include/config/x86/io/apic.h) \ -+ include/asm/mpspec.h \ -+ $(wildcard include/config/acpi.h) \ -+ include/asm/mpspec_def.h \ -+ include/asm-i386/mach-generic/mach_mpspec.h \ -+ include/asm/apic.h \ -+ $(wildcard include/config/x86/good/apic.h) \ -+ include/linux/pm.h \ -+ $(wildcard include/config/pm.h) \ -+ include/linux/delay.h \ -+ include/asm/delay.h \ -+ include/asm/fixmap.h \ -+ $(wildcard include/config/highmem.h) \ -+ $(wildcard include/config/x86/visws/apic.h) \ -+ $(wildcard include/config/x86/f00f/bug.h) \ -+ $(wildcard include/config/x86/cyclone/timer.h) \ -+ $(wildcard include/config/pci/mmconfig.h) \ -+ include/asm/acpi.h \ -+ $(wildcard include/config/acpi/sleep.h) \ -+ include/acpi/pdc_intel.h \ -+ include/asm/apicdef.h \ -+ include/asm/kmap_types.h \ -+ $(wildcard include/config/debug/highmem.h) \ -+ include/asm/io_apic.h \ -+ include/asm-i386/mach-generic/mach_apicdef.h \ -+ include/asm/genapic.h \ -+ include/linux/percpu.h \ -+ include/linux/slab.h \ -+ $(wildcard include/config/slab/debug.h) \ -+ $(wildcard include/config/slab.h) \ -+ $(wildcard include/config/slub.h) \ -+ $(wildcard include/config/debug/slab.h) \ -+ include/linux/gfp.h \ -+ $(wildcard include/config/zone/dma.h) \ -+ $(wildcard include/config/zone/dma32.h) \ -+ include/linux/mmzone.h \ -+ $(wildcard include/config/force/max/zoneorder.h) \ -+ $(wildcard include/config/arch/populates/node/map.h) \ -+ $(wildcard include/config/flat/node/mem/map.h) \ -+ $(wildcard include/config/have/memory/present.h) \ -+ $(wildcard include/config/need/node/memmap/size.h) \ -+ $(wildcard include/config/need/multiple/nodes.h) \ -+ $(wildcard include/config/have/arch/early/pfn/to/nid.h) \ -+ $(wildcard include/config/sparsemem/extreme.h) \ -+ $(wildcard include/config/nodes/span/other/nodes.h) \ -+ $(wildcard include/config/holes/in/zone.h) \ -+ include/linux/numa.h \ -+ $(wildcard include/config/nodes/shift.h) \ -+ include/linux/nodemask.h \ -+ include/linux/memory_hotplug.h \ -+ $(wildcard include/config/have/arch/nodedata/extension.h) \ -+ include/linux/notifier.h \ -+ include/linux/mutex.h \ -+ $(wildcard include/config/debug/mutexes.h) \ -+ $(wildcard include/config/chopstix.h) \ -+ include/linux/rwsem.h \ -+ $(wildcard include/config/rwsem/generic/spinlock.h) \ -+ include/asm/rwsem.h \ -+ include/linux/srcu.h \ -+ include/linux/topology.h \ -+ $(wildcard include/config/sched/smt.h) \ -+ $(wildcard include/config/sched/mc.h) \ -+ include/asm/topology.h \ -+ include/asm-generic/topology.h \ -+ include/linux/slab_def.h \ -+ include/linux/kmalloc_sizes.h \ -+ include/asm/mmu.h \ -+ include/asm/semaphore.h \ -+ include/linux/moduleparam.h \ -+ include/asm/local.h \ -+ include/asm/module.h \ -+ $(wildcard include/config/m486.h) \ -+ $(wildcard include/config/m586.h) \ -+ $(wildcard include/config/m586tsc.h) \ -+ $(wildcard include/config/m586mmx.h) \ -+ $(wildcard include/config/mcore2.h) \ -+ $(wildcard include/config/m686.h) \ -+ $(wildcard include/config/mpentiumii.h) \ -+ $(wildcard include/config/mpentiumiii.h) \ -+ $(wildcard include/config/mpentiumm.h) \ -+ $(wildcard include/config/mpentium4.h) \ -+ $(wildcard include/config/mk6.h) \ -+ $(wildcard include/config/x86/elan.h) \ -+ $(wildcard include/config/mcrusoe.h) \ -+ $(wildcard include/config/mefficeon.h) \ -+ $(wildcard include/config/mwinchipc6.h) \ -+ $(wildcard include/config/mwinchip2.h) \ -+ $(wildcard include/config/mwinchip3d.h) \ -+ $(wildcard include/config/mcyrixiii.h) \ -+ $(wildcard include/config/mviac3/2.h) \ -+ $(wildcard include/config/mviac7.h) \ -+ $(wildcard include/config/mgeodegx1.h) \ -+ $(wildcard include/config/mgeode/lx.h) \ -+ include/asm/device.h \ -+ include/linux/pci_ids.h \ -+ include/linux/dmapool.h \ -+ include/asm/io.h \ -+ $(wildcard include/config/x86/numaq.h) \ -+ include/asm-generic/iomap.h \ -+ include/linux/vmalloc.h \ -+ include/asm/scatterlist.h \ -+ include/asm/pci.h \ -+ include/linux/mm.h \ -+ $(wildcard include/config/sysctl.h) \ -+ $(wildcard include/config/mmu.h) \ -+ $(wildcard include/config/stack/growsup.h) \ -+ $(wildcard include/config/debug/vm.h) \ -+ $(wildcard include/config/shmem.h) \ -+ $(wildcard include/config/split/ptlock/cpus.h) \ -+ $(wildcard include/config/ia64.h) \ -+ $(wildcard include/config/proc/fs.h) \ -+ $(wildcard include/config/debug/pagealloc.h) \ -+ include/linux/capability.h \ -+ include/linux/rbtree.h \ -+ include/linux/prio_tree.h \ -+ include/linux/fs.h \ -+ $(wildcard include/config/dnotify.h) \ -+ $(wildcard include/config/vserver/cowbl.h) \ -+ $(wildcard include/config/quota.h) \ -+ $(wildcard include/config/inotify.h) \ -+ $(wildcard include/config/security.h) \ -+ $(wildcard include/config/epoll.h) \ -+ $(wildcard include/config/auditsyscall.h) \ -+ $(wildcard include/config/block.h) \ -+ $(wildcard include/config/fs/xip.h) \ -+ $(wildcard include/config/migration.h) \ -+ include/linux/limits.h \ -+ include/linux/ioctl.h \ -+ include/asm/ioctl.h \ -+ include/asm-generic/ioctl.h \ -+ include/linux/kdev_t.h \ -+ include/linux/dcache.h \ -+ $(wildcard include/config/profiling.h) \ -+ include/linux/rcupdate.h \ -+ include/linux/namei.h \ -+ include/linux/radix-tree.h \ -+ include/linux/pid.h \ -+ include/linux/quota.h \ -+ include/linux/dqblk_xfs.h \ -+ include/linux/dqblk_v1.h \ -+ include/linux/dqblk_v2.h \ -+ include/linux/nfs_fs_i.h \ -+ include/linux/nfs.h \ -+ include/linux/sunrpc/msg_prot.h \ -+ include/linux/fcntl.h \ -+ include/asm/fcntl.h \ -+ include/asm-generic/fcntl.h \ -+ $(wildcard include/config/64bit.h) \ -+ include/linux/err.h \ -+ include/linux/debug_locks.h \ -+ $(wildcard include/config/debug/locking/api/selftests.h) \ -+ include/linux/backing-dev.h \ -+ include/linux/mm_types.h \ -+ include/asm/pgtable.h \ -+ $(wildcard include/config/highpte.h) \ -+ include/asm/paravirt.h \ -+ include/asm/pgtable-2level-defs.h \ -+ include/asm/pgtable-2level.h \ -+ include/asm-generic/pgtable.h \ -+ include/linux/page-flags.h \ -+ $(wildcard include/config/s390.h) \ -+ $(wildcard include/config/swap.h) \ -+ include/linux/vmstat.h \ -+ $(wildcard include/config/vm/event/counters.h) \ -+ include/asm-generic/pci-dma-compat.h \ -+ include/linux/dma-mapping.h \ -+ include/asm/dma-mapping.h \ -+ include/asm-generic/pci.h \ -+ include/linux/interrupt.h \ -+ $(wildcard include/config/high/res/timers.h) \ -+ $(wildcard include/config/generic/irq/probe.h) \ -+ include/linux/irqreturn.h \ -+ include/linux/hardirq.h \ -+ $(wildcard include/config/preempt/bkl.h) \ -+ $(wildcard include/config/virt/cpu/accounting.h) \ -+ include/linux/smp_lock.h \ -+ $(wildcard include/config/lock/kernel.h) \ -+ include/linux/sched.h \ -+ $(wildcard include/config/no/hz.h) \ -+ $(wildcard include/config/detect/softlockup.h) \ -+ $(wildcard include/config/keys.h) \ -+ $(wildcard include/config/bsd/process/acct.h) \ -+ $(wildcard include/config/taskstats.h) \ -+ $(wildcard include/config/inotify/user.h) \ -+ $(wildcard include/config/schedstats.h) \ -+ $(wildcard include/config/task/delay/acct.h) \ -+ $(wildcard include/config/blk/dev/io/trace.h) \ -+ $(wildcard include/config/cc/stackprotector.h) \ -+ $(wildcard include/config/sysvipc.h) \ -+ $(wildcard include/config/rt/mutexes.h) \ -+ $(wildcard include/config/task/xacct.h) \ -+ $(wildcard include/config/cpusets.h) \ -+ $(wildcard include/config/compat.h) \ -+ $(wildcard include/config/fault/injection.h) \ -+ include/asm/param.h \ -+ $(wildcard include/config/hz.h) \ -+ include/linux/timex.h \ -+ $(wildcard include/config/time/interpolation.h) \ -+ include/asm/timex.h \ -+ include/asm/tsc.h \ -+ $(wildcard include/config/x86/tsc.h) \ -+ $(wildcard include/config/x86/generic.h) \ -+ include/linux/jiffies.h \ -+ include/linux/calc64.h \ -+ include/asm/div64.h \ -+ include/asm/cputime.h \ -+ include/asm-generic/cputime.h \ -+ include/linux/sem.h \ -+ include/linux/ipc.h \ -+ $(wildcard include/config/ipc/ns.h) \ -+ include/asm/ipcbuf.h \ -+ include/asm/sembuf.h \ -+ include/linux/signal.h \ -+ include/asm/signal.h \ -+ include/asm-generic/signal.h \ -+ include/asm/siginfo.h \ -+ include/asm-generic/siginfo.h \ -+ include/linux/securebits.h \ -+ include/linux/fs_struct.h \ -+ include/linux/seccomp.h \ -+ $(wildcard include/config/seccomp.h) \ -+ include/linux/futex.h \ -+ $(wildcard include/config/futex.h) \ -+ include/linux/rtmutex.h \ -+ $(wildcard include/config/debug/rt/mutexes.h) \ -+ include/linux/plist.h \ -+ $(wildcard include/config/debug/pi/list.h) \ -+ include/linux/param.h \ -+ include/linux/resource.h \ -+ include/asm/resource.h \ -+ include/asm-generic/resource.h \ -+ include/linux/timer.h \ -+ $(wildcard include/config/timer/stats.h) \ -+ include/linux/ktime.h \ -+ $(wildcard include/config/ktime/scalar.h) \ -+ include/linux/hrtimer.h \ -+ include/linux/task_io_accounting.h \ -+ $(wildcard include/config/task/io/accounting.h) \ -+ include/linux/aio.h \ -+ include/linux/workqueue.h \ -+ include/linux/aio_abi.h \ -+ include/linux/uio.h \ -+ include/asm/hardirq.h \ -+ include/linux/irq.h \ -+ $(wildcard include/config/irq/per/cpu.h) \ -+ $(wildcard include/config/irq/release/method.h) \ -+ $(wildcard include/config/generic/pending/irq.h) \ -+ $(wildcard include/config/irqbalance.h) \ -+ $(wildcard include/config/auto/irq/affinity.h) \ -+ $(wildcard include/config/generic/hardirqs/no//do/irq.h) \ -+ include/asm/irq.h \ -+ include/asm-i386/mach-default/irq_vectors.h \ -+ include/asm-i386/mach-default/irq_vectors_limits.h \ -+ include/asm/irq_regs.h \ -+ include/asm/hw_irq.h \ -+ include/linux/profile.h \ -+ include/asm/sections.h \ -+ include/asm-generic/sections.h \ -+ include/linux/irq_cpustat.h \ -+ include/linux/if_ether.h \ -+ include/linux/skbuff.h \ -+ $(wildcard include/config/nf/conntrack.h) \ -+ $(wildcard include/config/bridge/netfilter.h) \ -+ $(wildcard include/config/vlan/8021q.h) \ -+ $(wildcard include/config/net/sched.h) \ -+ $(wildcard include/config/net/cls/act.h) \ -+ $(wildcard include/config/net/dma.h) \ -+ $(wildcard include/config/network/secmark.h) \ -+ include/linux/net.h \ -+ include/asm/socket.h \ -+ include/asm/sockios.h \ -+ include/linux/random.h \ -+ include/linux/sysctl.h \ -+ $(wildcard include/config/icmp/ipod.h) \ -+ $(wildcard include/config/web100/net100.h) \ -+ $(wildcard include/config/web100/stats.h) \ -+ include/linux/textsearch.h \ -+ include/net/checksum.h \ -+ include/asm/uaccess.h \ -+ $(wildcard include/config/x86/intel/usercopy.h) \ -+ $(wildcard include/config/x86/wp/works/ok.h) \ -+ include/asm/checksum.h \ -+ include/linux/in6.h \ -+ include/linux/dmaengine.h \ -+ $(wildcard include/config/dma/engine.h) \ -+ drivers/net/igb/kcompat.h \ -+ $(wildcard include/config/e1000/napi.h) \ -+ $(wildcard include/config/e1000e/napi.h) \ -+ $(wildcard include/config/ixgb/napi.h) \ -+ $(wildcard include/config/e1000/disable/packet/split.h) \ -+ $(wildcard include/config/igb/disable/packet/split.h) \ -+ $(wildcard include/config/net/poll/controller.h) \ -+ $(wildcard include/config/space/len.h) \ -+ $(wildcard include/config/netpoll.h) \ -+ $(wildcard include/config/netdevices/multiqueue.h) \ -+ include/linux/version.h \ -+ include/linux/netdevice.h \ -+ $(wildcard include/config/ax25.h) \ -+ $(wildcard include/config/tr.h) \ -+ $(wildcard include/config/net/ipip.h) \ -+ $(wildcard include/config/net/ipgre.h) \ -+ $(wildcard include/config/ipv6/sit.h) \ -+ $(wildcard include/config/ipv6/tunnel.h) \ -+ $(wildcard include/config/wireless/ext.h) \ -+ $(wildcard include/config/netpoll/trap.h) \ -+ include/linux/if.h \ -+ include/linux/socket.h \ -+ include/linux/sockios.h \ -+ include/linux/hdlc/ioctl.h \ -+ include/linux/if_packet.h \ -+ include/linux/etherdevice.h \ -+ include/linux/in.h \ -+ include/linux/ip.h \ -+ include/linux/udp.h \ -+ include/net/inet_sock.h \ -+ $(wildcard include/config/ipv6.h) \ -+ include/linux/jhash.h \ -+ include/net/flow.h \ -+ $(wildcard include/config/ipv6/mip6.h) \ -+ include/net/sock.h \ -+ $(wildcard include/config/security/network.h) \ -+ include/linux/security.h \ -+ $(wildcard include/config/security/network/xfrm.h) \ -+ include/linux/binfmts.h \ -+ include/linux/shm.h \ -+ include/asm/shmparam.h \ -+ include/asm/shmbuf.h \ -+ include/linux/msg.h \ -+ include/asm/msgbuf.h \ -+ include/linux/key.h \ -+ include/linux/xfrm.h \ -+ include/linux/filter.h \ -+ include/net/dst.h \ -+ $(wildcard include/config/net/cls/route.h) \ -+ $(wildcard include/config/xfrm.h) \ -+ include/linux/rtnetlink.h \ -+ include/linux/netlink.h \ -+ include/linux/if_link.h \ -+ include/linux/if_addr.h \ -+ include/linux/neighbour.h \ -+ include/net/neighbour.h \ -+ include/linux/seq_file.h \ -+ include/net/rtnetlink.h \ -+ include/net/netlink.h \ -+ include/net/request_sock.h \ -+ include/linux/mii.h \ -+ include/linux/latency.h \ -+ drivers/net/igb/e1000_regs.h \ -+ drivers/net/igb/e1000_defines.h \ -+ $(wildcard include/config/res.h) \ -+ $(wildcard include/config/fault.h) \ -+ drivers/net/igb/e1000_mac.h \ -+ drivers/net/igb/e1000_phy.h \ -+ drivers/net/igb/e1000_nvm.h \ -+ drivers/net/igb/e1000_manage.h \ -+ drivers/net/igb/e1000_82575.h \ -+ -+drivers/net/igb/e1000_api.o: $(deps_drivers/net/igb/e1000_api.o) -+ -+$(deps_drivers/net/igb/e1000_api.o): -diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/igb/e1000_defines.h ---- vanilla/drivers/net/igb/e1000_defines.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/e1000_defines.h 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,1426 @@ +Index: linux-2.6.22/drivers/net/igb/e1000_defines.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/e1000_defines.h 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,1513 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ Copyright(c) 2007-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, @@ -4507,7 +3435,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_WUFC_FLX5 0x00200000 /* Flexible Filter 5 Enable */ +#define E1000_WUFC_ALL_FILTERS 0x000F00FF /* Mask for all wakeup filters */ +#define E1000_WUFC_FLX_OFFSET 16 /* Offset to the Flexible Filters bits */ -+#define E1000_WUFC_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */ ++#define E1000_WUFC_FLX_FILTERS 0x000F0000 /*Mask for the 4 flexible filters */ +/* + * For 82576 to utilize Extended filter masks in addition to + * existing (filter) masks @@ -4557,12 +3485,12 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Definable Pin 5 */ +#define E1000_CTRL_EXT_PHY_INT E1000_CTRL_EXT_SDP5_DATA +#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Definable Pin 6 */ -+#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */ ++#define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* Value of SW Definable Pin 3 */ +/* SDP 4/5 (bits 8,9) are reserved in >= 82575 */ +#define E1000_CTRL_EXT_SDP4_DIR 0x00000100 /* Direction of SDP4 0=in 1=out */ +#define E1000_CTRL_EXT_SDP5_DIR 0x00000200 /* Direction of SDP5 0=in 1=out */ +#define E1000_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 0=in 1=out */ -+#define E1000_CTRL_EXT_SDP7_DIR 0x00000800 /* Direction of SDP7 0=in 1=out */ ++#define E1000_CTRL_EXT_SDP3_DIR 0x00000800 /* Direction of SDP3 0=in 1=out */ +#define E1000_CTRL_EXT_ASDCHK 0x00001000 /* Initiate an ASD sequence */ +#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ +#define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */ @@ -4570,6 +3498,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_CTRL_EXT_PFRSTD 0x00004000 +#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ +#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ ++#define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */ +#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 +#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000 +#define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000 @@ -4584,13 +3513,14 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_CTRL_EXT_WR_WMARK_320 0x01000000 +#define E1000_CTRL_EXT_WR_WMARK_384 0x02000000 +#define E1000_CTRL_EXT_WR_WMARK_448 0x03000000 -+#define E1000_CTRL_EXT_CANC 0x04000000 /* Interrupt delay cancellation */ ++#define E1000_CTRL_EXT_CANC 0x04000000 /* Int delay cancellation */ +#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */ +/* IAME enable bit (27) was removed in >= 82575 */ -+#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */ -+#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */ -+#define E1000_CRTL_EXT_PB_PAREN 0x01000000 /* packet buffer parity error detection enabled */ -+#define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity error detection enable */ ++#define E1000_CTRL_EXT_IAME 0x08000000 /* Int acknowledge Auto-mask */ ++#define E1000_CRTL_EXT_PB_PAREN 0x01000000 /* packet buffer parity error ++ * detection enabled */ ++#define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity ++ * error detection enable */ +#define E1000_CTRL_EXT_GHOST_PAREN 0x40000000 +#define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */ +#define E1000_I2CCMD_REG_ADDR_SHIFT 16 @@ -4716,8 +3646,8 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_RCTL_RST 0x00000001 /* Software reset */ +#define E1000_RCTL_EN 0x00000002 /* enable */ +#define E1000_RCTL_SBP 0x00000004 /* store bad packet */ -+#define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */ -+#define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enab */ ++#define E1000_RCTL_UPE 0x00000008 /* unicast promisc enable */ ++#define E1000_RCTL_MPE 0x00000010 /* multicast promisc enable */ +#define E1000_RCTL_LPE 0x00000020 /* long packet enable */ +#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */ +#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ @@ -4725,9 +3655,9 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ +#define E1000_RCTL_DTYP_MASK 0x00000C00 /* Descriptor type mask */ +#define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */ -+#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */ -+#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */ -+#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */ ++#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min thresh size */ ++#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min thresh size */ ++#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min thresh size */ +#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ +#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */ +#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */ @@ -4782,10 +3712,10 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */ + +/* SWFW_SYNC Definitions */ -+#define E1000_SWFW_EEP_SM 0x1 -+#define E1000_SWFW_PHY0_SM 0x2 -+#define E1000_SWFW_PHY1_SM 0x4 -+#define E1000_SWFW_CSR_SM 0x8 ++#define E1000_SWFW_EEP_SM 0x01 ++#define E1000_SWFW_PHY0_SM 0x02 ++#define E1000_SWFW_PHY1_SM 0x04 ++#define E1000_SWFW_CSR_SM 0x08 + +/* FACTPS Definitions */ +#define E1000_FACTPS_LFS 0x40000000 /* LAN Function Select */ @@ -4793,7 +3723,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */ +#define E1000_CTRL_BEM 0x00000002 /* Endian Mode.0=little,1=big */ +#define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */ -+#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master requests */ ++#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master reqs */ +#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */ +#define E1000_CTRL_TME 0x00000010 /* Test mode. 0=normal,1=test */ +#define E1000_CTRL_SLE 0x00000020 /* Serial Link on 0=dis,1=en */ @@ -4808,12 +3738,16 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */ +#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ +#define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */ -+#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */ -+#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through PHYRST_N pin */ -+#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external LINK_0 and LINK_1 pins */ ++#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock ++ * indication in SDP[0] */ ++#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through ++ * PHYRST_N pin */ ++#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external ++ * LINK_0 and LINK_1 pins */ +#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ +#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ +#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */ ++#define E1000_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */ +#define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */ +#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ +#define E1000_CTRL_SWDPIO1 0x00800000 /* SWDPIN 1 input or output */ @@ -4825,7 +3759,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_CTRL_RTE 0x20000000 /* Routing tag enable */ +#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */ +#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */ -+#define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to manageability engine */ ++#define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to ME */ +#define E1000_CTRL_I2C_ENA 0x02000000 /* I2C enable */ + +/* @@ -4887,10 +3821,12 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */ +#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ +#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ -+#define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion by NVM */ ++#define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion by NVM */ +#define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */ -+#define E1000_STATUS_DOCK_CI 0x00000800 /* Change in Dock/Undock state. Clear on write '0'. */ -+#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */ ++#define E1000_STATUS_PHYRA 0x00000400 /* PHY Reset Asserted */ ++#define E1000_STATUS_DOCK_CI 0x00000800 /* Change in Dock/Undock state. ++ * Clear on write '0'. */ ++#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Master request status */ +#define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */ +#define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */ +#define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */ @@ -4900,7 +3836,8 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_STATUS_BMC_SKU_1 0x00200000 /* BMC SRAM disabled */ +#define E1000_STATUS_BMC_SKU_2 0x00400000 /* BMC SDRAM disabled */ +#define E1000_STATUS_BMC_CRYPTO 0x00800000 /* BMC crypto disabled */ -+#define E1000_STATUS_BMC_LITE 0x01000000 /* BMC external code execution disabled */ ++#define E1000_STATUS_BMC_LITE 0x01000000 /* BMC external code execution ++ * disabled */ +#define E1000_STATUS_RGMII_ENABLE 0x02000000 /* RGMII disabled */ +#define E1000_STATUS_FUSE_8 0x04000000 +#define E1000_STATUS_FUSE_9 0x08000000 @@ -4908,9 +3845,9 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_STATUS_SERDES1_DIS 0x20000000 /* SERDES disabled on port 1 */ + +/* Constants used to interpret the masked PCI-X bus speed. */ -+#define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus speed 50-66 MHz */ -+#define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed 66-100 MHz */ -+#define E1000_STATUS_PCIX_SPEED_133 0x00008000 /* PCI-X bus speed 100-133 MHz */ ++#define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus speed 50-66 MHz */ ++#define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed 66-100 MHz */ ++#define E1000_STATUS_PCIX_SPEED_133 0x00008000 /*PCI-X bus speed 100-133 MHz*/ + +#define SPEED_10 10 +#define SPEED_100 100 @@ -4928,10 +3865,10 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define ADVERTISE_1000_FULL 0x0020 + +/* 1000/H is not supported, nor spec-compliant. */ -+#define E1000_ALL_SPEED_DUPLEX ( ADVERTISE_10_HALF | ADVERTISE_10_FULL | \ ++#define E1000_ALL_SPEED_DUPLEX (ADVERTISE_10_HALF | ADVERTISE_10_FULL | \ + ADVERTISE_100_HALF | ADVERTISE_100_FULL | \ + ADVERTISE_1000_FULL) -+#define E1000_ALL_NOT_GIG ( ADVERTISE_10_HALF | ADVERTISE_10_FULL | \ ++#define E1000_ALL_NOT_GIG (ADVERTISE_10_HALF | ADVERTISE_10_FULL | \ + ADVERTISE_100_HALF | ADVERTISE_100_FULL) +#define E1000_ALL_100_SPEED (ADVERTISE_100_HALF | ADVERTISE_100_FULL) +#define E1000_ALL_10_SPEED (ADVERTISE_10_HALF | ADVERTISE_10_FULL) @@ -5080,6 +4017,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +/* Extended Configuration Control and Size */ +#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020 +#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001 ++#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008 +#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020 +#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000 +#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16 @@ -5095,16 +4033,21 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_KABGTXD_BGSQLBIAS 0x00050000 + +/* PBA constants */ -+#define E1000_PBA_6K 0x0006 /* 6KB */ ++#define E1000_PBA_6K 0x0006 /* 6KB */ +#define E1000_PBA_8K 0x0008 /* 8KB */ ++#define E1000_PBA_10K 0x000A /* 10KB */ +#define E1000_PBA_12K 0x000C /* 12KB */ ++#define E1000_PBA_14K 0x000E /* 14KB */ +#define E1000_PBA_16K 0x0010 /* 16KB */ ++#define E1000_PBA_18K 0x0012 +#define E1000_PBA_20K 0x0014 +#define E1000_PBA_22K 0x0016 +#define E1000_PBA_24K 0x0018 ++#define E1000_PBA_26K 0x001A +#define E1000_PBA_30K 0x001E +#define E1000_PBA_32K 0x0020 +#define E1000_PBA_34K 0x0022 ++#define E1000_PBA_35K 0x0023 +#define E1000_PBA_38K 0x0026 +#define E1000_PBA_40K 0x0028 +#define E1000_PBA_48K 0x0030 /* 48KB */ @@ -5125,6 +4068,8 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_SWSM_WMNG 0x00000004 /* Wake MNG Clock */ +#define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */ + ++#define E1000_SWSM2_LOCK 0x00000002 /* Secondary driver semaphore bit */ ++ +/* Interrupt Cause Read */ +#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */ +#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */ @@ -5145,18 +4090,23 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */ +#define E1000_ICR_MNG 0x00040000 /* Manageability event */ +#define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */ -+#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */ -+#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* queue 0 Rx descriptor FIFO parity error */ -+#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* queue 0 Tx descriptor FIFO parity error */ -+#define E1000_ICR_HOST_ARB_PAR 0x00400000 /* host arb read buffer parity error */ ++#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver ++ * should claim the interrupt */ ++#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* Q0 Rx desc FIFO parity error */ ++#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* Q0 Tx desc FIFO parity error */ ++#define E1000_ICR_HOST_ARB_PAR 0x00400000 /* host arb read buffer parity err */ +#define E1000_ICR_PB_PAR 0x00800000 /* packet buffer parity error */ -+#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* queue 1 Rx descriptor FIFO parity error */ -+#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* queue 1 Tx descriptor FIFO parity error */ ++#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* Q1 Rx desc FIFO parity error */ ++#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* Q1 Tx desc FIFO parity error */ +#define E1000_ICR_ALL_PARITY 0x03F00000 /* all parity error bits */ -+#define E1000_ICR_DSW 0x00000020 /* FW changed the status of DISSW bit in the FWSM */ -+#define E1000_ICR_PHYINT 0x00001000 /* LAN connected device generates an interrupt */ ++#define E1000_ICR_DSW 0x00000020 /* FW changed the status of DISSW ++ * bit in the FWSM */ ++#define E1000_ICR_PHYINT 0x00001000 /* LAN connected device generates ++ * an interrupt */ ++#define E1000_ICR_DOUTSYNC 0x10000000 /* NIC DMA out of sync */ +#define E1000_ICR_EPRST 0x00100000 /* ME hardware reset occurs */ + ++ +/* Extended Interrupt Cause Read */ +#define E1000_EICR_RX_QUEUE0 0x00000001 /* Rx Queue 0 Interrupt */ +#define E1000_EICR_RX_QUEUE1 0x00000002 /* Rx Queue 1 Interrupt */ @@ -5201,7 +4151,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ + E1000_IMS_LSC) + +/* Interrupt Mask Set */ -+#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ ++#define E1000_IMS_TXDW E1000_ICR_TXDW /* Tx desc written back */ +#define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ +#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ +#define E1000_IMS_VMMB E1000_ICR_VMMB /* Mail box activity */ @@ -5220,14 +4170,21 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */ +#define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */ +#define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */ -+#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ -+#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ -+#define E1000_IMS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ -+#define E1000_IMS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ -+#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ -+#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ ++#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* Q0 Rx desc FIFO ++ * parity error */ ++#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* Q0 Tx desc FIFO ++ * parity error */ ++#define E1000_IMS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer ++ * parity error */ ++#define E1000_IMS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity ++ * error */ ++#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* Q1 Rx desc FIFO ++ * parity error */ ++#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* Q1 Tx desc FIFO ++ * parity error */ +#define E1000_IMS_DSW E1000_ICR_DSW +#define E1000_IMS_PHYINT E1000_ICR_PHYINT ++#define E1000_IMS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */ +#define E1000_IMS_EPRST E1000_ICR_EPRST + +/* Extended Interrupt Mask Set */ @@ -5243,7 +4200,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_EIMS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */ + +/* Interrupt Cause Set */ -+#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ ++#define E1000_ICS_TXDW E1000_ICR_TXDW /* Tx desc written back */ +#define E1000_ICS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ +#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ +#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ @@ -5261,13 +4218,20 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_ICS_ACK E1000_ICR_ACK /* Receive Ack frame */ +#define E1000_ICS_MNG E1000_ICR_MNG /* Manageability event */ +#define E1000_ICS_DOCK E1000_ICR_DOCK /* Dock/Undock */ -+#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ -+#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ -+#define E1000_ICS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ -+#define E1000_ICS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ -+#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ -+#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ ++#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* Q0 Rx desc FIFO ++ * parity error */ ++#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* Q0 Tx desc FIFO ++ * parity error */ ++#define E1000_ICS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer ++ * parity error */ ++#define E1000_ICS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity ++ * error */ ++#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* Q1 Rx desc FIFO ++ * parity error */ ++#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* Q1 Tx desc FIFO ++ * parity error */ +#define E1000_ICS_DSW E1000_ICR_DSW ++#define E1000_ICS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */ +#define E1000_ICS_PHYINT E1000_ICR_PHYINT +#define E1000_ICS_EPRST E1000_ICR_EPRST + @@ -5283,6 +4247,8 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_EICS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */ +#define E1000_EICS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */ + ++#define E1000_EITR_ITR_INT_MASK 0x0000FFFF ++ +/* Transmit Descriptor Control */ +#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */ +#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */ @@ -5313,6 +4279,10 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ + */ +#define E1000_RAR_ENTRIES 15 +#define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */ ++#define E1000_RAL_MAC_ADDR_LEN 4 ++#define E1000_RAH_MAC_ADDR_LEN 2 ++#define E1000_RAH_POOL_MASK 0x03FC0000 ++#define E1000_RAH_POOL_1 0x00040000 + +/* Error Codes */ +#define E1000_SUCCESS 0 @@ -5328,6 +4298,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_BLK_PHY_RESET 12 +#define E1000_ERR_SWFW_SYNC 13 +#define E1000_NOT_IMPLEMENTED 14 ++#define E1000_ERR_MBX 15 + +/* Loop limit on how long we wait for auto-negotiation to complete */ +#define FIBER_LINK_UP_LIMIT 50 @@ -5370,6 +4341,39 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */ +#define E1000_RXCW_ANC 0x80000000 /* Auto-neg complete */ + ++#define E1000_TSYNCTXCTL_VALID 0x00000001 /* tx timestamp valid */ ++#define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable tx timestampping */ ++ ++#define E1000_TSYNCRXCTL_VALID 0x00000001 /* rx timestamp valid */ ++#define E1000_TSYNCRXCTL_TYPE_MASK 0x0000000E /* rx type mask */ ++#define E1000_TSYNCRXCTL_TYPE_L2_V2 0x00 ++#define E1000_TSYNCRXCTL_TYPE_L4_V1 0x02 ++#define E1000_TSYNCRXCTL_TYPE_L2_L4_V2 0x04 ++#define E1000_TSYNCRXCTL_TYPE_ALL 0x08 ++#define E1000_TSYNCRXCTL_TYPE_EVENT_V2 0x0A ++#define E1000_TSYNCRXCTL_ENABLED 0x00000010 /* enable rx timestampping */ ++ ++#define E1000_TSYNCRXCFG_PTP_V1_CTRLT_MASK 0x000000FF ++#define E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE 0x00 ++#define E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE 0x01 ++#define E1000_TSYNCRXCFG_PTP_V1_FOLLOWUP_MESSAGE 0x02 ++#define E1000_TSYNCRXCFG_PTP_V1_DELAY_RESP_MESSAGE 0x03 ++#define E1000_TSYNCRXCFG_PTP_V1_MANAGEMENT_MESSAGE 0x04 ++ ++#define E1000_TSYNCRXCFG_PTP_V2_MSGID_MASK 0x00000F00 ++#define E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE 0x0000 ++#define E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE 0x0100 ++#define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_REQ_MESSAGE 0x0200 ++#define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_RESP_MESSAGE 0x0300 ++#define E1000_TSYNCRXCFG_PTP_V2_FOLLOWUP_MESSAGE 0x0800 ++#define E1000_TSYNCRXCFG_PTP_V2_DELAY_RESP_MESSAGE 0x0900 ++#define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_FOLLOWUP_MESSAGE 0x0A00 ++#define E1000_TSYNCRXCFG_PTP_V2_ANNOUNCE_MESSAGE 0x0B00 ++#define E1000_TSYNCRXCFG_PTP_V2_SIGNALLING_MESSAGE 0x0C00 ++#define E1000_TSYNCRXCFG_PTP_V2_MANAGEMENT_MESSAGE 0x0D00 ++ ++#define E1000_TIMINCA_16NS_SHIFT 24 ++ +/* PCI Express Control */ +#define E1000_GCR_RXD_NO_SNOOP 0x00000001 +#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 @@ -5377,6 +4381,10 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_GCR_TXD_NO_SNOOP 0x00000008 +#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010 +#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020 ++#define E1000_GCR_CMPL_TMOUT_MASK 0x0000F000 ++#define E1000_GCR_CMPL_TMOUT_10ms 0x00001000 ++#define E1000_GCR_CMPL_TMOUT_RESEND 0x00010000 ++#define E1000_GCR_CAP_VER2 0x00040000 + +#define PCIE_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \ + E1000_GCR_RXDSCW_NO_SNOOP | \ @@ -5457,7 +4465,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ + /* 0=DTE device */ +#define CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */ + /* 0=Configure PHY as Slave */ -+#define CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */ ++#define CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */ + /* 0=Automatic Master/Slave config */ +#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */ +#define CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */ @@ -5467,7 +4475,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ + +/* 1000BASE-T Status Register */ +#define SR_1000T_IDLE_ERROR_CNT 0x00FF /* Num idle errors since last read */ -+#define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asymmetric pause direction bit */ ++#define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asymmetric pause direction bit */ +#define SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */ +#define SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */ +#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */ @@ -5492,6 +4500,8 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ +#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ + ++#define PHY_CONTROL_LB 0x4000 /* PHY Loopback bit */ ++ +/* NVM Control */ +#define E1000_EECD_SK 0x00000001 /* NVM Clock */ +#define E1000_EECD_CS 0x00000002 /* NVM Chip Select */ @@ -5520,10 +4530,11 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */ +#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */ +#define E1000_EECD_SECVAL_SHIFT 22 ++#define E1000_EECD_SEC1VAL_VALID_MASK (E1000_EECD_AUTO_RD | E1000_EECD_PRES) + +#define E1000_NVM_SWDPIN0 0x0001 /* SWDPIN 0 NVM Value */ +#define E1000_NVM_LED_LOGIC 0x0020 /* Led Logic Word */ -+#define E1000_NVM_RW_REG_DATA 16 /* Offset to data in NVM read/write registers */ ++#define E1000_NVM_RW_REG_DATA 16 /* Offset to data in NVM read/write regs */ +#define E1000_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */ +#define E1000_NVM_RW_REG_START 1 /* Start operation */ +#define E1000_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ @@ -5535,7 +4546,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define NVM_COMPAT 0x0003 +#define NVM_ID_LED_SETTINGS 0x0004 +#define NVM_VERSION 0x0005 -+#define NVM_SERDES_AMPLITUDE 0x0006 /* For SERDES output amplitude adjustment. */ ++#define NVM_SERDES_AMPLITUDE 0x0006 /* SERDES output amplitude */ +#define NVM_PHY_CLASS_WORD 0x0007 +#define NVM_INIT_CONTROL1_REG 0x000A +#define NVM_INIT_CONTROL2_REG 0x000F @@ -5549,8 +4560,8 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define NVM_ALT_MAC_ADDR_PTR 0x0037 +#define NVM_CHECKSUM_REG 0x003F + -+#define E1000_NVM_CFG_DONE_PORT_0 0x40000 /* MNG config cycle done */ -+#define E1000_NVM_CFG_DONE_PORT_1 0x80000 /* ...for second port */ ++#define E1000_NVM_CFG_DONE_PORT_0 0x040000 /* MNG config cycle done */ ++#define E1000_NVM_CFG_DONE_PORT_1 0x080000 /* ...for second port */ + +/* Mask bits for fields in Word 0x0f of the NVM */ +#define NVM_WORD0F_PAUSE_MASK 0x3000 @@ -5618,10 +4629,12 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +/* PCI/PCI-X/PCI-EX Config space */ +#define PCI_HEADER_TYPE_REGISTER 0x0E +#define PCIE_LINK_STATUS 0x12 ++#define PCIE_DEVICE_CONTROL2 0x28 + +#define PCI_HEADER_TYPE_MULTIFUNC 0x80 +#define PCIE_LINK_WIDTH_MASK 0x3F0 +#define PCIE_LINK_WIDTH_SHIFT 4 ++#define PCIE_DEVICE_CONTROL2_16ms 0x0005 + +#ifndef ETH_ADDR_LEN +#define ETH_ADDR_LEN 6 @@ -5666,11 +4679,11 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ + +/* M88E1000 PHY Specific Control Register */ +#define M88E1000_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */ -+#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */ ++#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reverse enabled */ +#define M88E1000_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */ +/* 1=CLK125 low, 0=CLK125 toggling */ +#define M88E1000_PSCR_CLK125_DISABLE 0x0010 -+#define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */ ++#define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */ + /* Manual MDI configuration */ +#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */ +/* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */ @@ -5686,7 +4699,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define M88E1000_PSCR_MII_5BIT_ENABLE 0x0100 +#define M88E1000_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */ +#define M88E1000_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */ -+#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */ ++#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Tx */ + +/* M88E1000 PHY Specific Status Register */ +#define M88E1000_PSSR_JABBER 0x0001 /* 1=Jabber */ @@ -5869,15 +4882,18 @@ diff -Nru vanilla/drivers/net/igb/e1000_defines.h linux-i686-2.6.22/drivers/net/ +#define E1000_LSECRXCTRL_RP 0x00000080 +#define E1000_LSECRXCTRL_RSV_MASK 0xFFFFFF33 + ++ ++ +#endif /* _E1000_DEFINES_H_ */ -diff -Nru vanilla/drivers/net/igb/e1000_hw.h linux-i686-2.6.22/drivers/net/igb/e1000_hw.h ---- vanilla/drivers/net/igb/e1000_hw.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/e1000_hw.h 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,633 @@ +Index: linux-2.6.22/drivers/net/igb/e1000_hw.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/e1000_hw.h 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,692 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ Copyright(c) 2007-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, @@ -5913,6 +4929,10 @@ diff -Nru vanilla/drivers/net/igb/e1000_hw.h linux-i686-2.6.22/drivers/net/igb/e +#define E1000_DEV_ID_82576 0x10C9 +#define E1000_DEV_ID_82576_FIBER 0x10E6 +#define E1000_DEV_ID_82576_SERDES 0x10E7 ++#define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8 ++#define E1000_DEV_ID_82576_NS 0x150A ++#define E1000_DEV_ID_82576_NS_SERDES 0x1518 ++#define E1000_DEV_ID_82576_SERDES_QUAD 0x150D +#define E1000_DEV_ID_82575EB_COPPER 0x10A7 +#define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9 +#define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6 @@ -5925,6 +4945,9 @@ diff -Nru vanilla/drivers/net/igb/e1000_hw.h linux-i686-2.6.22/drivers/net/igb/e +#define E1000_FUNC_0 0 +#define E1000_FUNC_1 1 + ++#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0 ++#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3 ++ +enum e1000_mac_type { + e1000_undefined = 0, + e1000_82575, @@ -6009,7 +5032,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_hw.h linux-i686-2.6.22/drivers/net/igb/e + e1000_rev_polarity_undefined = 0xFF +}; + -+enum e1000_fc_type { ++enum e1000_fc_mode { + e1000_fc_none = 0, + e1000_fc_rx_pause, + e1000_fc_tx_pause, @@ -6030,6 +5053,13 @@ diff -Nru vanilla/drivers/net/igb/e1000_hw.h linux-i686-2.6.22/drivers/net/igb/e + e1000_smart_speed_off +}; + ++enum e1000_serdes_link_state { ++ e1000_serdes_link_down = 0, ++ e1000_serdes_link_autoneg_progress, ++ e1000_serdes_link_autoneg_complete, ++ e1000_serdes_link_forced_up ++}; ++ +/* Receive Descriptor */ +struct e1000_rx_desc { + __le64 buffer_addr; /* Address of the descriptor's data buffer */ @@ -6244,8 +5274,10 @@ diff -Nru vanilla/drivers/net/igb/e1000_hw.h linux-i686-2.6.22/drivers/net/igb/e + u64 lenerrs; + u64 scvpc; + u64 hrmpc; ++ u64 doosync; +}; + ++ +struct e1000_phy_stats { + u32 idle_errors; + u32 receive_errors; @@ -6295,10 +5327,12 @@ diff -Nru vanilla/drivers/net/igb/e1000_hw.h linux-i686-2.6.22/drivers/net/igb/e +#include "e1000_phy.h" +#include "e1000_nvm.h" +#include "e1000_manage.h" ++#include "e1000_mbx.h" + +struct e1000_mac_operations { + /* Function pointers for the MAC. */ + s32 (*init_params)(struct e1000_hw *); ++ s32 (*id_led_init)(struct e1000_hw *); + s32 (*blink_led)(struct e1000_hw *); + s32 (*check_for_link)(struct e1000_hw *); + bool (*check_mng_mode)(struct e1000_hw *hw); @@ -6306,10 +5340,11 @@ diff -Nru vanilla/drivers/net/igb/e1000_hw.h linux-i686-2.6.22/drivers/net/igb/e + void (*clear_hw_cntrs)(struct e1000_hw *); + void (*clear_vfta)(struct e1000_hw *); + s32 (*get_bus_info)(struct e1000_hw *); ++ void (*set_lan_id)(struct e1000_hw *); + s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *); + s32 (*led_on)(struct e1000_hw *); + s32 (*led_off)(struct e1000_hw *); -+ void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32, u32, u32); ++ void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32); + s32 (*reset_hw)(struct e1000_hw *); + s32 (*init_hw)(struct e1000_hw *); + void (*shutdown_serdes)(struct e1000_hw *); @@ -6318,15 +5353,15 @@ diff -Nru vanilla/drivers/net/igb/e1000_hw.h linux-i686-2.6.22/drivers/net/igb/e + s32 (*setup_led)(struct e1000_hw *); + void (*write_vfta)(struct e1000_hw *, u32, u32); + void (*mta_set)(struct e1000_hw *, u32); -+ void (*config_collision_dist)(struct e1000_hw*); -+ void (*rar_set)(struct e1000_hw*, u8*, u32); -+ s32 (*read_mac_addr)(struct e1000_hw*); -+ s32 (*validate_mdi_setting)(struct e1000_hw*); -+ s32 (*mng_host_if_write)(struct e1000_hw*, u8*, u16, u16, u8*); ++ void (*config_collision_dist)(struct e1000_hw *); ++ void (*rar_set)(struct e1000_hw *, u8*, u32); ++ s32 (*read_mac_addr)(struct e1000_hw *); ++ s32 (*validate_mdi_setting)(struct e1000_hw *); ++ s32 (*mng_host_if_write)(struct e1000_hw *, u8*, u16, u16, u8*); + s32 (*mng_write_cmd_header)(struct e1000_hw *hw, + struct e1000_host_mng_command_header*); -+ s32 (*mng_enable_host_if)(struct e1000_hw*); -+ s32 (*wait_autoneg)(struct e1000_hw*); ++ s32 (*mng_enable_host_if)(struct e1000_hw *); ++ s32 (*wait_autoneg)(struct e1000_hw *); +}; + +struct e1000_phy_operations { @@ -6340,11 +5375,13 @@ diff -Nru vanilla/drivers/net/igb/e1000_hw.h linux-i686-2.6.22/drivers/net/igb/e + s32 (*get_cable_length)(struct e1000_hw *); + s32 (*get_info)(struct e1000_hw *); + s32 (*read_reg)(struct e1000_hw *, u32, u16 *); ++ s32 (*read_reg_locked)(struct e1000_hw *, u32, u16 *); + void (*release)(struct e1000_hw *); + s32 (*reset)(struct e1000_hw *); + s32 (*set_d0_lplu_state)(struct e1000_hw *, bool); + s32 (*set_d3_lplu_state)(struct e1000_hw *, bool); + s32 (*write_reg)(struct e1000_hw *, u32, u16); ++ s32 (*write_reg_locked)(struct e1000_hw *, u32, u16); + void (*power_up)(struct e1000_hw *); + void (*power_down)(struct e1000_hw *); +}; @@ -6382,6 +5419,11 @@ diff -Nru vanilla/drivers/net/igb/e1000_hw.h linux-i686-2.6.22/drivers/net/igb/e + u16 ifs_ratio; + u16 ifs_step_size; + u16 mta_reg_count; ++ u16 uta_reg_count; ++ ++ /* Maximum size of the MTA register table in all supported adapters */ ++ #define MAX_MTA_REG 128 ++ u32 mta_shadow[MAX_MTA_REG]; + u16 rar_entry_count; + + u8 forced_speed_duplex; @@ -6393,6 +5435,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_hw.h linux-i686-2.6.22/drivers/net/igb/e + bool autoneg_failed; + bool get_link_status; + bool in_ifs_mode; ++ enum e1000_serdes_link_state serdes_link_state; + bool serdes_has_link; + bool tx_pkt_filtering; +}; @@ -6461,18 +5504,49 @@ diff -Nru vanilla/drivers/net/igb/e1000_hw.h linux-i686-2.6.22/drivers/net/igb/e + u16 pause_time; /* Flow control pause timer */ + bool send_xon; /* Flow control send XON */ + bool strict_ieee; /* Strict IEEE mode */ -+ enum e1000_fc_type type; /* Type of flow control */ -+ enum e1000_fc_type original_type; ++ enum e1000_fc_mode current_mode; /* FC mode in effect */ ++ enum e1000_fc_mode requested_mode; /* FC mode requested by caller */ ++}; ++ ++struct e1000_mbx_operations { ++ s32 (*init_params)(struct e1000_hw *hw); ++ s32 (*read)(struct e1000_hw *, u32 *, u16, u16); ++ s32 (*write)(struct e1000_hw *, u32 *, u16, u16); ++ s32 (*read_posted)(struct e1000_hw *, u32 *, u16, u16); ++ s32 (*write_posted)(struct e1000_hw *, u32 *, u16, u16); ++ s32 (*check_for_msg)(struct e1000_hw *, u16); ++ s32 (*check_for_ack)(struct e1000_hw *, u16); ++ s32 (*check_for_rst)(struct e1000_hw *, u16); ++}; ++ ++struct e1000_mbx_stats { ++ u32 msgs_tx; ++ u32 msgs_rx; ++ ++ u32 acks; ++ u32 reqs; ++ u32 rsts; ++}; ++ ++struct e1000_mbx_info { ++ struct e1000_mbx_operations ops; ++ struct e1000_mbx_stats stats; ++ u32 timeout; ++ u32 usec_delay; ++ u16 size; +}; + +struct e1000_dev_spec_82575 { + bool sgmii_active; ++ bool global_device_reset; +}; + +struct e1000_dev_spec_vf { + u32 vf_number; ++ u32 v2p_mailbox; +}; + ++ +struct e1000_hw { + void *back; + @@ -6485,6 +5559,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_hw.h linux-i686-2.6.22/drivers/net/igb/e + struct e1000_phy_info phy; + struct e1000_nvm_info nvm; + struct e1000_bus_info bus; ++ struct e1000_mbx_info mbx; + struct e1000_host_mng_dhcp_cookie mng_cookie; + + union { @@ -6504,17 +5579,18 @@ diff -Nru vanilla/drivers/net/igb/e1000_hw.h linux-i686-2.6.22/drivers/net/igb/e + +/* These functions must be implemented by drivers */ +s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); -+void e1000_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value); ++s32 e1000_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); + +#endif -diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/e1000_mac.c ---- vanilla/drivers/net/igb/e1000_mac.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/e1000_mac.c 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,1971 @@ +Index: linux-2.6.22/drivers/net/igb/e1000_mac.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/e1000_mac.c 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,1985 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ Copyright(c) 2007-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, @@ -6544,6 +5620,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ +static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw); +static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw); +static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw); ++static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw); + +/** + * e1000_init_mac_ops_generic - Initialize MAC function pointers @@ -6557,6 +5634,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + DEBUGFUNC("e1000_init_mac_ops_generic"); + + /* General Setup */ ++ mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pcie; + mac->ops.read_mac_addr = e1000_read_mac_addr_generic; + mac->ops.config_collision_dist = e1000_config_collision_dist_generic; + /* LINK */ @@ -6580,10 +5658,11 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + **/ +s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw) +{ ++ struct e1000_mac_info *mac = &hw->mac; + struct e1000_bus_info *bus = &hw->bus; ++ + s32 ret_val; -+ u32 status; -+ u16 pcie_link_status, pci_header_type; ++ u16 pcie_link_status; + + DEBUGFUNC("e1000_get_bus_info_pcie_generic"); + @@ -6600,20 +5679,47 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + PCIE_LINK_WIDTH_MASK) >> + PCIE_LINK_WIDTH_SHIFT); + -+ e1000_read_pci_cfg(hw, PCI_HEADER_TYPE_REGISTER, &pci_header_type); -+ if (pci_header_type & PCI_HEADER_TYPE_MULTIFUNC) { -+ status = E1000_READ_REG(hw, E1000_STATUS); -+ bus->func = (status & E1000_STATUS_FUNC_MASK) -+ >> E1000_STATUS_FUNC_SHIFT; -+ } else { -+ bus->func = 0; -+ } ++ mac->ops.set_lan_id(hw); + + return E1000_SUCCESS; +} + +/** -+ * e1000_clear_vfta_generic - Clear VLAN filter table ++ * e1000_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices ++ * ++ * @hw: pointer to the HW structure ++ * ++ * Determines the LAN function id by reading memory-mapped registers ++ * and swaps the port value if requested. ++ **/ ++static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw) ++{ ++ struct e1000_bus_info *bus = &hw->bus; ++ u32 reg; ++ ++ /* ++ * The status register reports the correct function number ++ * for the device regardless of function swap state. ++ */ ++ reg = E1000_READ_REG(hw, E1000_STATUS); ++ bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT; ++} ++ ++/** ++ * e1000_set_lan_id_single_port - Set LAN id for a single port device ++ * @hw: pointer to the HW structure ++ * ++ * Sets the LAN function id to zero for a single port device. ++ **/ ++void e1000_set_lan_id_single_port(struct e1000_hw *hw) ++{ ++ struct e1000_bus_info *bus = &hw->bus; ++ ++ bus->func = 0; ++} ++ ++/** ++ * e1000_clear_vfta_generic - Clear VLAN filter table + * @hw: pointer to the HW structure + * + * Clears the register array which contains the VLAN filter table by @@ -6660,6 +5766,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ +void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count) +{ + u32 i; ++ u8 mac_addr[ETH_ADDR_LEN] = {0}; + + DEBUGFUNC("e1000_init_rx_addrs_generic"); + @@ -6670,12 +5777,8 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + + /* Zero out the other (rar_entry_count - 1) receive addresses */ + DEBUGOUT1("Clearing RAR[1-%u]\n", rar_count-1); -+ for (i = 1; i < rar_count; i++) { -+ E1000_WRITE_REG_ARRAY(hw, E1000_RA, (i << 1), 0); -+ E1000_WRITE_FLUSH(hw); -+ E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((i << 1) + 1), 0); -+ E1000_WRITE_FLUSH(hw); -+ } ++ for (i = 1; i < rar_count; i++) ++ hw->mac.ops.rar_set(hw, mac_addr, i); +} + +/** @@ -6684,10 +5787,11 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + * + * Checks the nvm for an alternate MAC address. An alternate MAC address + * can be setup by pre-boot software and must be treated like a permanent -+ * address and must override the actual permanent MAC address. If an -+ * alternate MAC address is found it is saved in the hw struct and -+ * programmed into RAR0 and the function returns success, otherwise the -+ * function returns an error. ++ * address and must override the actual permanent MAC address. If an ++ * alternate MAC address is found it is programmed into RAR0, replacing ++ * the permanent address that was installed into RAR0 by the Si on reset. ++ * This function will return SUCCESS unless it encounters an error while ++ * reading the EEPROM. + **/ +s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) +{ @@ -6706,13 +5810,12 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + } + + if (nvm_alt_mac_addr_offset == 0xFFFF) { -+ ret_val = -(E1000_NOT_IMPLEMENTED); ++ /* There is no Alternate MAC Address */ + goto out; + } + + if (hw->bus.func == E1000_FUNC_1) -+ nvm_alt_mac_addr_offset += ETH_ADDR_LEN/sizeof(u16); -+ ++ nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1; + for (i = 0; i < ETH_ADDR_LEN; i += 2) { + offset = nvm_alt_mac_addr_offset + (i >> 1); + ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data); @@ -6727,14 +5830,16 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + + /* if multicast bit is set, the alternate address will not be used */ + if (alt_mac_addr[0] & 0x01) { -+ ret_val = -(E1000_NOT_IMPLEMENTED); ++ DEBUGOUT("Ignoring Alternate Mac Address with MC bit set\n"); + goto out; + } + -+ for (i = 0; i < ETH_ADDR_LEN; i++) -+ hw->mac.addr[i] = hw->mac.perm_addr[i] = alt_mac_addr[i]; -+ -+ hw->mac.ops.rar_set(hw, hw->mac.perm_addr, 0); ++ /* ++ * We have a valid alternate MAC address, and we want to treat it the ++ * same as the normal permanent MAC address stored by the HW into the ++ * RAR. Do this by mapping this address into RAR0. ++ */ ++ hw->mac.ops.rar_set(hw, alt_mac_addr, 0); + +out: + return ret_val; @@ -6769,8 +5874,15 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + if (rar_low || rar_high) + rar_high |= E1000_RAH_AV; + ++ /* ++ * Some bridges will combine consecutive 32-bit writes into ++ * a single burst write, which will malfunction on some parts. ++ * The flushes avoid this. ++ */ + E1000_WRITE_REG(hw, E1000_RAL(index), rar_low); ++ E1000_WRITE_FLUSH(hw); + E1000_WRITE_REG(hw, E1000_RAH(index), rar_high); ++ E1000_WRITE_FLUSH(hw); +} + +/** @@ -6814,55 +5926,36 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + * @hw: pointer to the HW structure + * @mc_addr_list: array of multicast addresses to program + * @mc_addr_count: number of multicast addresses to program -+ * @rar_used_count: the first RAR register free to program -+ * @rar_count: total number of supported Receive Address Registers + * -+ * Updates the Receive Address Registers and Multicast Table Array. ++ * Updates entire Multicast Table Array. + * The caller must have a packed mc_addr_list of multicast addresses. -+ * The parameter rar_count will usually be hw->mac.rar_entry_count -+ * unless there are workarounds that change this. + **/ +void e1000_update_mc_addr_list_generic(struct e1000_hw *hw, -+ u8 *mc_addr_list, u32 mc_addr_count, -+ u32 rar_used_count, u32 rar_count) ++ u8 *mc_addr_list, u32 mc_addr_count) +{ -+ u32 hash_value; -+ u32 i; ++ u32 hash_value, hash_bit, hash_reg; ++ int i; + + DEBUGFUNC("e1000_update_mc_addr_list_generic"); + -+ /* -+ * Load the first set of multicast addresses into the exact -+ * filters (RAR). If there are not enough to fill the RAR -+ * array, clear the filters. -+ */ -+ for (i = rar_used_count; i < rar_count; i++) { -+ if (mc_addr_count) { -+ hw->mac.ops.rar_set(hw, mc_addr_list, i); -+ mc_addr_count--; -+ mc_addr_list += ETH_ADDR_LEN; -+ } else { -+ E1000_WRITE_REG_ARRAY(hw, E1000_RA, i << 1, 0); -+ E1000_WRITE_FLUSH(hw); -+ E1000_WRITE_REG_ARRAY(hw, E1000_RA, (i << 1) + 1, 0); -+ E1000_WRITE_FLUSH(hw); -+ } -+ } -+ -+ /* Clear the old settings from the MTA */ -+ DEBUGOUT("Clearing MTA\n"); -+ for (i = 0; i < hw->mac.mta_reg_count; i++) { -+ E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); -+ E1000_WRITE_FLUSH(hw); -+ } ++ /* clear mta_shadow */ ++ memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); + -+ /* Load any remaining multicast addresses into the hash table. */ -+ for (; mc_addr_count > 0; mc_addr_count--) { ++ /* update mta_shadow from mc_addr_list */ ++ for (i = 0; (u32) i < mc_addr_count; i++) { + hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list); -+ DEBUGOUT1("Hash value = 0x%03X\n", hash_value); -+ hw->mac.ops.mta_set(hw, hash_value); -+ mc_addr_list += ETH_ADDR_LEN; ++ ++ hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); ++ hash_bit = hash_value & 0x1F; ++ ++ hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit); ++ mc_addr_list += (ETH_ADDR_LEN); + } ++ ++ /* replace the entire MTA table */ ++ for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) ++ E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]); ++ E1000_WRITE_FLUSH(hw); +} + +/** @@ -6918,18 +6011,18 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634 + */ + switch (hw->mac.mc_filter_type) { -+ default: -+ case 0: -+ break; -+ case 1: -+ bit_shift += 1; -+ break; -+ case 2: -+ bit_shift += 2; -+ break; -+ case 3: -+ bit_shift += 4; -+ break; ++ default: ++ case 0: ++ break; ++ case 1: ++ bit_shift += 1; ++ break; ++ case 2: ++ bit_shift += 2; ++ break; ++ case 3: ++ bit_shift += 4; ++ break; + } + + hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) | @@ -6946,47 +6039,45 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + **/ +void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw) +{ -+ volatile u32 temp; -+ + DEBUGFUNC("e1000_clear_hw_cntrs_base_generic"); + -+ temp = E1000_READ_REG(hw, E1000_CRCERRS); -+ temp = E1000_READ_REG(hw, E1000_SYMERRS); -+ temp = E1000_READ_REG(hw, E1000_MPC); -+ temp = E1000_READ_REG(hw, E1000_SCC); -+ temp = E1000_READ_REG(hw, E1000_ECOL); -+ temp = E1000_READ_REG(hw, E1000_MCC); -+ temp = E1000_READ_REG(hw, E1000_LATECOL); -+ temp = E1000_READ_REG(hw, E1000_COLC); -+ temp = E1000_READ_REG(hw, E1000_DC); -+ temp = E1000_READ_REG(hw, E1000_SEC); -+ temp = E1000_READ_REG(hw, E1000_RLEC); -+ temp = E1000_READ_REG(hw, E1000_XONRXC); -+ temp = E1000_READ_REG(hw, E1000_XONTXC); -+ temp = E1000_READ_REG(hw, E1000_XOFFRXC); -+ temp = E1000_READ_REG(hw, E1000_XOFFTXC); -+ temp = E1000_READ_REG(hw, E1000_FCRUC); -+ temp = E1000_READ_REG(hw, E1000_GPRC); -+ temp = E1000_READ_REG(hw, E1000_BPRC); -+ temp = E1000_READ_REG(hw, E1000_MPRC); -+ temp = E1000_READ_REG(hw, E1000_GPTC); -+ temp = E1000_READ_REG(hw, E1000_GORCL); -+ temp = E1000_READ_REG(hw, E1000_GORCH); -+ temp = E1000_READ_REG(hw, E1000_GOTCL); -+ temp = E1000_READ_REG(hw, E1000_GOTCH); -+ temp = E1000_READ_REG(hw, E1000_RNBC); -+ temp = E1000_READ_REG(hw, E1000_RUC); -+ temp = E1000_READ_REG(hw, E1000_RFC); -+ temp = E1000_READ_REG(hw, E1000_ROC); -+ temp = E1000_READ_REG(hw, E1000_RJC); -+ temp = E1000_READ_REG(hw, E1000_TORL); -+ temp = E1000_READ_REG(hw, E1000_TORH); -+ temp = E1000_READ_REG(hw, E1000_TOTL); -+ temp = E1000_READ_REG(hw, E1000_TOTH); -+ temp = E1000_READ_REG(hw, E1000_TPR); -+ temp = E1000_READ_REG(hw, E1000_TPT); -+ temp = E1000_READ_REG(hw, E1000_MPTC); -+ temp = E1000_READ_REG(hw, E1000_BPTC); ++ E1000_READ_REG(hw, E1000_CRCERRS); ++ E1000_READ_REG(hw, E1000_SYMERRS); ++ E1000_READ_REG(hw, E1000_MPC); ++ E1000_READ_REG(hw, E1000_SCC); ++ E1000_READ_REG(hw, E1000_ECOL); ++ E1000_READ_REG(hw, E1000_MCC); ++ E1000_READ_REG(hw, E1000_LATECOL); ++ E1000_READ_REG(hw, E1000_COLC); ++ E1000_READ_REG(hw, E1000_DC); ++ E1000_READ_REG(hw, E1000_SEC); ++ E1000_READ_REG(hw, E1000_RLEC); ++ E1000_READ_REG(hw, E1000_XONRXC); ++ E1000_READ_REG(hw, E1000_XONTXC); ++ E1000_READ_REG(hw, E1000_XOFFRXC); ++ E1000_READ_REG(hw, E1000_XOFFTXC); ++ E1000_READ_REG(hw, E1000_FCRUC); ++ E1000_READ_REG(hw, E1000_GPRC); ++ E1000_READ_REG(hw, E1000_BPRC); ++ E1000_READ_REG(hw, E1000_MPRC); ++ E1000_READ_REG(hw, E1000_GPTC); ++ E1000_READ_REG(hw, E1000_GORCL); ++ E1000_READ_REG(hw, E1000_GORCH); ++ E1000_READ_REG(hw, E1000_GOTCL); ++ E1000_READ_REG(hw, E1000_GOTCH); ++ E1000_READ_REG(hw, E1000_RNBC); ++ E1000_READ_REG(hw, E1000_RUC); ++ E1000_READ_REG(hw, E1000_RFC); ++ E1000_READ_REG(hw, E1000_ROC); ++ E1000_READ_REG(hw, E1000_RJC); ++ E1000_READ_REG(hw, E1000_TORL); ++ E1000_READ_REG(hw, E1000_TORH); ++ E1000_READ_REG(hw, E1000_TOTL); ++ E1000_READ_REG(hw, E1000_TOTH); ++ E1000_READ_REG(hw, E1000_TPR); ++ E1000_READ_REG(hw, E1000_TPT); ++ E1000_READ_REG(hw, E1000_MPTC); ++ E1000_READ_REG(hw, E1000_BPTC); +} + +/** @@ -7059,9 +6150,8 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + * different link partner. + */ + ret_val = e1000_config_fc_after_link_up_generic(hw); -+ if (ret_val) { ++ if (ret_val) + DEBUGOUT("Error configuring flow control\n"); -+ } + +out: + return ret_val; @@ -7274,23 +6364,23 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + goto out; + + /* -+ * If flow control is set to default, set flow control based on -+ * the EEPROM flow control settings. ++ * If requested flow control is set to default, set flow control ++ * based on the EEPROM flow control settings. + */ -+ if (hw->fc.type == e1000_fc_default) { ++ if (hw->fc.requested_mode == e1000_fc_default) { + ret_val = e1000_set_default_fc_generic(hw); + if (ret_val) + goto out; + } + + /* -+ * 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. ++ * Save off the requested flow control mode for use later. Depending ++ * on the link partner's capabilities, we may or may not use this mode. + */ -+ hw->fc.original_type = hw->fc.type; ++ hw->fc.current_mode = hw->fc.requested_mode; + -+ DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc.type); ++ DEBUGOUT1("After fix-ups FlowControl is now = %x\n", ++ hw->fc.current_mode); + + /* Call the necessary media_type subroutine to configure the link. */ + ret_val = hw->mac.ops.setup_physical_interface(hw); @@ -7400,7 +6490,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + * Polls for link up by reading the status register, if link fails to come + * up with auto-negotiation, then the link is forced if a signal is detected. + **/ -+s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) ++static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + u32 i, status; @@ -7477,7 +6567,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + * do not support receiving pause frames). + * 3: Both Rx and Tx flow control (symmetric) are enabled. + */ -+ switch (hw->fc.type) { ++ switch (hw->fc.current_mode) { + case e1000_fc_none: + /* Flow control completely disabled by a software over-ride. */ + txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); @@ -7543,7 +6633,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + * ability to transmit pause frames is not enabled, then these + * registers will be set to 0. + */ -+ if (hw->fc.type & e1000_fc_tx_pause) { ++ if (hw->fc.current_mode & e1000_fc_tx_pause) { + /* + * We need to set up the Receive Threshold high and low water + * marks as well as (optionally) enabling the transmission of @@ -7592,12 +6682,12 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + } + + if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0) -+ hw->fc.type = e1000_fc_none; ++ hw->fc.requested_mode = e1000_fc_none; + else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == + NVM_WORD0F_ASM_DIR) -+ hw->fc.type = e1000_fc_tx_pause; ++ hw->fc.requested_mode = e1000_fc_tx_pause; + else -+ hw->fc.type = e1000_fc_full; ++ hw->fc.requested_mode = e1000_fc_full; + +out: + return ret_val; @@ -7629,7 +6719,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + * receive flow control. + * + * The "Case" statement below enables/disable flow control -+ * according to the "hw->fc.type" parameter. ++ * according to the "hw->fc.current_mode" parameter. + * + * The possible values of the "fc" parameter are: + * 0: Flow control is completely disabled @@ -7640,9 +6730,9 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + * 3: Both Rx and Tx flow control (symmetric) is enabled. + * other: No other values should be possible at this point. + */ -+ DEBUGOUT1("hw->fc.type = %u\n", hw->fc.type); ++ DEBUGOUT1("hw->fc.current_mode = %u\n", hw->fc.current_mode); + -+ switch (hw->fc.type) { ++ switch (hw->fc.current_mode) { + case e1000_fc_none: + ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); + break; @@ -7791,11 +6881,11 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + * ONLY. Hence, we must now check to see if we need to + * turn OFF the TRANSMISSION of PAUSE frames. + */ -+ if (hw->fc.original_type == e1000_fc_full) { -+ hw->fc.type = e1000_fc_full; ++ if (hw->fc.requested_mode == e1000_fc_full) { ++ hw->fc.current_mode = e1000_fc_full; + DEBUGOUT("Flow Control = FULL.\r\n"); + } else { -+ hw->fc.type = e1000_fc_rx_pause; ++ hw->fc.current_mode = e1000_fc_rx_pause; + DEBUGOUT("Flow Control = " + "RX PAUSE frames only.\r\n"); + } @@ -7812,7 +6902,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && + (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && + (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { -+ hw->fc.type = e1000_fc_tx_pause; ++ hw->fc.current_mode = e1000_fc_tx_pause; + DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n"); + } + /* @@ -7827,14 +6917,14 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && + !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && + (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { -+ hw->fc.type = e1000_fc_rx_pause; ++ hw->fc.current_mode = e1000_fc_rx_pause; + DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); + } else { + /* + * Per the IEEE spec, at this point flow control + * should be disabled. + */ -+ hw->fc.type = e1000_fc_none; ++ hw->fc.current_mode = e1000_fc_none; + DEBUGOUT("Flow Control = NONE.\r\n"); + } + @@ -7850,7 +6940,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + } + + if (duplex == HALF_DUPLEX) -+ hw->fc.type = e1000_fc_none; ++ hw->fc.current_mode = e1000_fc_none; + + /* + * Now we call a subroutine to actually force the MAC @@ -8062,7 +7152,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + * @hw: pointer to the HW structure + * + **/ -+s32 e1000_id_led_init_generic(struct e1000_hw * hw) ++s32 e1000_id_led_init_generic(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + s32 ret_val; @@ -8426,7 +7516,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ + * Verify that when not using auto-negotiation that MDI/MDIx is correctly + * set, which is forced to MDI mode only. + **/ -+s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw) ++static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + @@ -8482,14 +7572,15 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.c linux-i686-2.6.22/drivers/net/igb/ +out: + return ret_val; +} -diff -Nru vanilla/drivers/net/igb/e1000_mac.h linux-i686-2.6.22/drivers/net/igb/e1000_mac.h ---- vanilla/drivers/net/igb/e1000_mac.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/e1000_mac.h 2009-07-16 19:25:22.000000000 -0400 +Index: linux-2.6.22/drivers/net/igb/e1000_mac.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/e1000_mac.h 2009-12-18 12:39:22.000000000 -0500 @@ -0,0 +1,80 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ Copyright(c) 2007-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, @@ -8531,6 +7622,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.h linux-i686-2.6.22/drivers/net/igb/ +s32 e1000_force_mac_fc_generic(struct e1000_hw *hw); +s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw); +s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw); ++void e1000_set_lan_id_single_port(struct e1000_hw *hw); +s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw); +s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed, + u16 *duplex); @@ -8540,8 +7632,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.h linux-i686-2.6.22/drivers/net/igb/ +s32 e1000_led_on_generic(struct e1000_hw *hw); +s32 e1000_led_off_generic(struct e1000_hw *hw); +void e1000_update_mc_addr_list_generic(struct e1000_hw *hw, -+ u8 *mc_addr_list, u32 mc_addr_count, -+ u32 rar_used_count, u32 rar_count); ++ u8 *mc_addr_list, u32 mc_addr_count); +s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw); +s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw); +s32 e1000_setup_led_generic(struct e1000_hw *hw); @@ -8566,568 +7657,15 @@ diff -Nru vanilla/drivers/net/igb/e1000_mac.h linux-i686-2.6.22/drivers/net/igb/ +void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); + +#endif -Binary files vanilla/drivers/net/igb/e1000_mac.o and linux-i686-2.6.22/drivers/net/igb/e1000_mac.o differ -diff -Nru vanilla/drivers/net/igb/.e1000_mac.o.cmd linux-i686-2.6.22/drivers/net/igb/.e1000_mac.o.cmd ---- vanilla/drivers/net/igb/.e1000_mac.o.cmd 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/.e1000_mac.o.cmd 2009-07-16 19:53:41.000000000 -0400 -@@ -0,0 +1,549 @@ -+cmd_drivers/net/igb/e1000_mac.o := gcc -m32 -Wp,-MD,drivers/net/igb/.e1000_mac.o.d -nostdinc -isystem /usr/lib/gcc/i386-redhat-linux/4.1.2/include -D__KERNEL__ -Iinclude -include include/linux/autoconf.h -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Os -pipe -msoft-float -mregparm=3 -freg-struct-return -mpreferred-stack-boundary=2 -march=i686 -mtune=generic -ffreestanding -maccumulate-outgoing-args -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -Iinclude/asm-i386/mach-generic -Iinclude/asm-i386/mach-default -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -DMODULE -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(e1000_mac)" -D"KBUILD_MODNAME=KBUILD_STR(igb)" -c -o drivers/net/igb/.tmp_e1000_mac.o drivers/net/igb/e1000_mac.c -+ -+deps_drivers/net/igb/e1000_mac.o := \ -+ drivers/net/igb/e1000_mac.c \ -+ drivers/net/igb/e1000_api.h \ -+ drivers/net/igb/e1000_hw.h \ -+ drivers/net/igb/e1000_osdep.h \ -+ include/linux/pci.h \ -+ $(wildcard include/config/pci/msi.h) \ -+ $(wildcard include/config/pci.h) \ -+ $(wildcard include/config/ht/irq.h) \ -+ $(wildcard include/config/pci/domains.h) \ -+ include/linux/pci_regs.h \ -+ include/linux/mod_devicetable.h \ -+ include/linux/types.h \ -+ $(wildcard include/config/uid16.h) \ -+ $(wildcard include/config/lbd.h) \ -+ $(wildcard include/config/lsf.h) \ -+ $(wildcard include/config/resources/64bit.h) \ -+ include/linux/posix_types.h \ -+ include/linux/stddef.h \ -+ include/linux/compiler.h \ -+ $(wildcard include/config/enable/must/check.h) \ -+ include/linux/compiler-gcc4.h \ -+ $(wildcard include/config/forced/inlining.h) \ -+ include/linux/compiler-gcc.h \ -+ include/asm/posix_types.h \ -+ include/asm/types.h \ -+ $(wildcard include/config/highmem64g.h) \ -+ include/linux/ioport.h \ -+ include/linux/list.h \ -+ $(wildcard include/config/debug/list.h) \ -+ include/linux/poison.h \ -+ include/linux/prefetch.h \ -+ include/asm/processor.h \ -+ $(wildcard include/config/smp.h) \ -+ $(wildcard include/config/x86/ht.h) \ -+ $(wildcard include/config/paravirt.h) \ -+ $(wildcard include/config/mk8.h) \ -+ $(wildcard include/config/mk7.h) \ -+ include/asm/vm86.h \ -+ $(wildcard include/config/vm86.h) \ -+ include/asm/ptrace.h \ -+ include/asm/ptrace-abi.h \ -+ include/asm/segment.h \ -+ include/asm/math_emu.h \ -+ include/asm/sigcontext.h \ -+ include/asm/page.h \ -+ $(wildcard include/config/x86/use/3dnow.h) \ -+ $(wildcard include/config/x86/pae.h) \ -+ $(wildcard include/config/hugetlb/page.h) \ -+ $(wildcard include/config/highmem4g.h) \ -+ $(wildcard include/config/page/offset.h) \ -+ $(wildcard include/config/flatmem.h) \ -+ include/asm-generic/pgtable-nopmd.h \ -+ include/asm-generic/pgtable-nopud.h \ -+ include/asm-generic/memory_model.h \ -+ $(wildcard include/config/discontigmem.h) \ -+ $(wildcard include/config/sparsemem.h) \ -+ $(wildcard include/config/out/of/line/pfn/to/page.h) \ -+ include/asm-generic/page.h \ -+ include/asm/cpufeature.h \ -+ include/linux/bitops.h \ -+ include/asm/bitops.h \ -+ include/asm/alternative.h \ -+ include/asm-generic/bitops/sched.h \ -+ include/asm-generic/bitops/hweight.h \ -+ include/asm-generic/bitops/fls64.h \ -+ include/asm-generic/bitops/ext2-non-atomic.h \ -+ include/asm-generic/bitops/le.h \ -+ include/asm/byteorder.h \ -+ $(wildcard include/config/x86/bswap.h) \ -+ include/linux/byteorder/little_endian.h \ -+ include/linux/byteorder/swab.h \ -+ include/linux/byteorder/generic.h \ -+ include/asm-generic/bitops/minix.h \ -+ include/asm/required-features.h \ -+ $(wildcard include/config/x86/minimum/cpu.h) \ -+ $(wildcard include/config/x86/cmov.h) \ -+ $(wildcard include/config/x86/cmpxchg64.h) \ -+ include/asm/msr.h \ -+ include/asm/msr-index.h \ -+ include/asm/errno.h \ -+ include/asm-generic/errno.h \ -+ include/asm-generic/errno-base.h \ -+ include/linux/errno.h \ -+ include/asm/system.h \ -+ $(wildcard include/config/x86/oostore.h) \ -+ include/linux/kernel.h \ -+ $(wildcard include/config/preempt/voluntary.h) \ -+ $(wildcard include/config/debug/spinlock/sleep.h) \ -+ $(wildcard include/config/printk.h) \ -+ $(wildcard include/config/numa.h) \ -+ /usr/lib/gcc/i386-redhat-linux/4.1.2/include/stdarg.h \ -+ include/linux/linkage.h \ -+ include/asm/linkage.h \ -+ $(wildcard include/config/x86/alignment/16.h) \ -+ include/linux/log2.h \ -+ $(wildcard include/config/arch/has/ilog2/u32.h) \ -+ $(wildcard include/config/arch/has/ilog2/u64.h) \ -+ include/asm/bug.h \ -+ $(wildcard include/config/bug.h) \ -+ $(wildcard include/config/debug/bugverbose.h) \ -+ include/asm-generic/bug.h \ -+ $(wildcard include/config/generic/bug.h) \ -+ include/asm/cmpxchg.h \ -+ $(wildcard include/config/x86/cmpxchg.h) \ -+ include/linux/irqflags.h \ -+ $(wildcard include/config/trace/irqflags.h) \ -+ $(wildcard include/config/trace/irqflags/support.h) \ -+ $(wildcard include/config/x86.h) \ -+ include/asm/irqflags.h \ -+ include/asm/processor-flags.h \ -+ include/linux/cache.h \ -+ include/asm/cache.h \ -+ $(wildcard include/config/x86/l1/cache/shift.h) \ -+ include/linux/threads.h \ -+ $(wildcard include/config/nr/cpus.h) \ -+ $(wildcard include/config/base/small.h) \ -+ include/asm/percpu.h \ -+ include/linux/cpumask.h \ -+ $(wildcard include/config/hotplug/cpu.h) \ -+ include/linux/bitmap.h \ -+ include/linux/string.h \ -+ include/asm/string.h \ -+ include/linux/init.h \ -+ $(wildcard include/config/modules.h) \ -+ $(wildcard include/config/hotplug.h) \ -+ $(wildcard include/config/memory/hotplug.h) \ -+ $(wildcard include/config/acpi/hotplug/memory.h) \ -+ include/asm/atomic.h \ -+ $(wildcard include/config/m386.h) \ -+ include/asm-generic/atomic.h \ -+ include/linux/device.h \ -+ $(wildcard include/config/debug/devres.h) \ -+ include/linux/kobject.h \ -+ include/linux/sysfs.h \ -+ $(wildcard include/config/sysfs.h) \ -+ include/linux/spinlock.h \ -+ $(wildcard include/config/debug/spinlock.h) \ -+ $(wildcard include/config/preempt.h) \ -+ $(wildcard include/config/debug/lock/alloc.h) \ -+ include/linux/preempt.h \ -+ $(wildcard include/config/debug/preempt.h) \ -+ include/linux/thread_info.h \ -+ include/asm/thread_info.h \ -+ $(wildcard include/config/4kstacks.h) \ -+ $(wildcard include/config/debug/stack/usage.h) \ -+ include/linux/stringify.h \ -+ include/linux/bottom_half.h \ -+ include/linux/spinlock_types.h \ -+ include/linux/lockdep.h \ -+ $(wildcard include/config/lockdep.h) \ -+ $(wildcard include/config/generic/hardirqs.h) \ -+ $(wildcard include/config/prove/locking.h) \ -+ include/asm/spinlock_types.h \ -+ include/asm/spinlock.h \ -+ $(wildcard include/config/x86/ppro/fence.h) \ -+ include/asm/rwlock.h \ -+ include/linux/spinlock_api_smp.h \ -+ include/linux/kref.h \ -+ include/linux/wait.h \ -+ include/asm/current.h \ -+ include/linux/klist.h \ -+ include/linux/completion.h \ -+ include/linux/module.h \ -+ $(wildcard include/config/modversions.h) \ -+ $(wildcard include/config/unused/symbols.h) \ -+ $(wildcard include/config/module/unload.h) \ -+ $(wildcard include/config/kallsyms.h) \ -+ include/linux/stat.h \ -+ include/asm/stat.h \ -+ include/linux/time.h \ -+ include/linux/seqlock.h \ -+ include/linux/vs_time.h \ -+ $(wildcard include/config/vserver/vtime.h) \ -+ include/linux/kmod.h \ -+ $(wildcard include/config/kmod.h) \ -+ include/linux/elf.h \ -+ include/linux/auxvec.h \ -+ include/asm/auxvec.h \ -+ include/linux/elf-em.h \ -+ include/asm/elf.h \ -+ include/asm/user.h \ -+ include/asm/desc.h \ -+ include/asm/ldt.h \ -+ include/linux/smp.h \ -+ include/asm/smp.h \ -+ $(wildcard include/config/x86/local/apic.h) \ -+ $(wildcard include/config/x86/io/apic.h) \ -+ include/asm/mpspec.h \ -+ $(wildcard include/config/acpi.h) \ -+ include/asm/mpspec_def.h \ -+ include/asm-i386/mach-generic/mach_mpspec.h \ -+ include/asm/apic.h \ -+ $(wildcard include/config/x86/good/apic.h) \ -+ include/linux/pm.h \ -+ $(wildcard include/config/pm.h) \ -+ include/linux/delay.h \ -+ include/asm/delay.h \ -+ include/asm/fixmap.h \ -+ $(wildcard include/config/highmem.h) \ -+ $(wildcard include/config/x86/visws/apic.h) \ -+ $(wildcard include/config/x86/f00f/bug.h) \ -+ $(wildcard include/config/x86/cyclone/timer.h) \ -+ $(wildcard include/config/pci/mmconfig.h) \ -+ include/asm/acpi.h \ -+ $(wildcard include/config/acpi/sleep.h) \ -+ include/acpi/pdc_intel.h \ -+ include/asm/apicdef.h \ -+ include/asm/kmap_types.h \ -+ $(wildcard include/config/debug/highmem.h) \ -+ include/asm/io_apic.h \ -+ include/asm-i386/mach-generic/mach_apicdef.h \ -+ include/asm/genapic.h \ -+ include/linux/percpu.h \ -+ include/linux/slab.h \ -+ $(wildcard include/config/slab/debug.h) \ -+ $(wildcard include/config/slab.h) \ -+ $(wildcard include/config/slub.h) \ -+ $(wildcard include/config/debug/slab.h) \ -+ include/linux/gfp.h \ -+ $(wildcard include/config/zone/dma.h) \ -+ $(wildcard include/config/zone/dma32.h) \ -+ include/linux/mmzone.h \ -+ $(wildcard include/config/force/max/zoneorder.h) \ -+ $(wildcard include/config/arch/populates/node/map.h) \ -+ $(wildcard include/config/flat/node/mem/map.h) \ -+ $(wildcard include/config/have/memory/present.h) \ -+ $(wildcard include/config/need/node/memmap/size.h) \ -+ $(wildcard include/config/need/multiple/nodes.h) \ -+ $(wildcard include/config/have/arch/early/pfn/to/nid.h) \ -+ $(wildcard include/config/sparsemem/extreme.h) \ -+ $(wildcard include/config/nodes/span/other/nodes.h) \ -+ $(wildcard include/config/holes/in/zone.h) \ -+ include/linux/numa.h \ -+ $(wildcard include/config/nodes/shift.h) \ -+ include/linux/nodemask.h \ -+ include/linux/memory_hotplug.h \ -+ $(wildcard include/config/have/arch/nodedata/extension.h) \ -+ include/linux/notifier.h \ -+ include/linux/mutex.h \ -+ $(wildcard include/config/debug/mutexes.h) \ -+ $(wildcard include/config/chopstix.h) \ -+ include/linux/rwsem.h \ -+ $(wildcard include/config/rwsem/generic/spinlock.h) \ -+ include/asm/rwsem.h \ -+ include/linux/srcu.h \ -+ include/linux/topology.h \ -+ $(wildcard include/config/sched/smt.h) \ -+ $(wildcard include/config/sched/mc.h) \ -+ include/asm/topology.h \ -+ include/asm-generic/topology.h \ -+ include/linux/slab_def.h \ -+ include/linux/kmalloc_sizes.h \ -+ include/asm/mmu.h \ -+ include/asm/semaphore.h \ -+ include/linux/moduleparam.h \ -+ include/asm/local.h \ -+ include/asm/module.h \ -+ $(wildcard include/config/m486.h) \ -+ $(wildcard include/config/m586.h) \ -+ $(wildcard include/config/m586tsc.h) \ -+ $(wildcard include/config/m586mmx.h) \ -+ $(wildcard include/config/mcore2.h) \ -+ $(wildcard include/config/m686.h) \ -+ $(wildcard include/config/mpentiumii.h) \ -+ $(wildcard include/config/mpentiumiii.h) \ -+ $(wildcard include/config/mpentiumm.h) \ -+ $(wildcard include/config/mpentium4.h) \ -+ $(wildcard include/config/mk6.h) \ -+ $(wildcard include/config/x86/elan.h) \ -+ $(wildcard include/config/mcrusoe.h) \ -+ $(wildcard include/config/mefficeon.h) \ -+ $(wildcard include/config/mwinchipc6.h) \ -+ $(wildcard include/config/mwinchip2.h) \ -+ $(wildcard include/config/mwinchip3d.h) \ -+ $(wildcard include/config/mcyrixiii.h) \ -+ $(wildcard include/config/mviac3/2.h) \ -+ $(wildcard include/config/mviac7.h) \ -+ $(wildcard include/config/mgeodegx1.h) \ -+ $(wildcard include/config/mgeode/lx.h) \ -+ include/asm/device.h \ -+ include/linux/pci_ids.h \ -+ include/linux/dmapool.h \ -+ include/asm/io.h \ -+ $(wildcard include/config/x86/numaq.h) \ -+ include/asm-generic/iomap.h \ -+ include/linux/vmalloc.h \ -+ include/asm/scatterlist.h \ -+ include/asm/pci.h \ -+ include/linux/mm.h \ -+ $(wildcard include/config/sysctl.h) \ -+ $(wildcard include/config/mmu.h) \ -+ $(wildcard include/config/stack/growsup.h) \ -+ $(wildcard include/config/debug/vm.h) \ -+ $(wildcard include/config/shmem.h) \ -+ $(wildcard include/config/split/ptlock/cpus.h) \ -+ $(wildcard include/config/ia64.h) \ -+ $(wildcard include/config/proc/fs.h) \ -+ $(wildcard include/config/debug/pagealloc.h) \ -+ include/linux/capability.h \ -+ include/linux/rbtree.h \ -+ include/linux/prio_tree.h \ -+ include/linux/fs.h \ -+ $(wildcard include/config/dnotify.h) \ -+ $(wildcard include/config/vserver/cowbl.h) \ -+ $(wildcard include/config/quota.h) \ -+ $(wildcard include/config/inotify.h) \ -+ $(wildcard include/config/security.h) \ -+ $(wildcard include/config/epoll.h) \ -+ $(wildcard include/config/auditsyscall.h) \ -+ $(wildcard include/config/block.h) \ -+ $(wildcard include/config/fs/xip.h) \ -+ $(wildcard include/config/migration.h) \ -+ include/linux/limits.h \ -+ include/linux/ioctl.h \ -+ include/asm/ioctl.h \ -+ include/asm-generic/ioctl.h \ -+ include/linux/kdev_t.h \ -+ include/linux/dcache.h \ -+ $(wildcard include/config/profiling.h) \ -+ include/linux/rcupdate.h \ -+ include/linux/namei.h \ -+ include/linux/radix-tree.h \ -+ include/linux/pid.h \ -+ include/linux/quota.h \ -+ include/linux/dqblk_xfs.h \ -+ include/linux/dqblk_v1.h \ -+ include/linux/dqblk_v2.h \ -+ include/linux/nfs_fs_i.h \ -+ include/linux/nfs.h \ -+ include/linux/sunrpc/msg_prot.h \ -+ include/linux/fcntl.h \ -+ include/asm/fcntl.h \ -+ include/asm-generic/fcntl.h \ -+ $(wildcard include/config/64bit.h) \ -+ include/linux/err.h \ -+ include/linux/debug_locks.h \ -+ $(wildcard include/config/debug/locking/api/selftests.h) \ -+ include/linux/backing-dev.h \ -+ include/linux/mm_types.h \ -+ include/asm/pgtable.h \ -+ $(wildcard include/config/highpte.h) \ -+ include/asm/paravirt.h \ -+ include/asm/pgtable-2level-defs.h \ -+ include/asm/pgtable-2level.h \ -+ include/asm-generic/pgtable.h \ -+ include/linux/page-flags.h \ -+ $(wildcard include/config/s390.h) \ -+ $(wildcard include/config/swap.h) \ -+ include/linux/vmstat.h \ -+ $(wildcard include/config/vm/event/counters.h) \ -+ include/asm-generic/pci-dma-compat.h \ -+ include/linux/dma-mapping.h \ -+ include/asm/dma-mapping.h \ -+ include/asm-generic/pci.h \ -+ include/linux/interrupt.h \ -+ $(wildcard include/config/high/res/timers.h) \ -+ $(wildcard include/config/generic/irq/probe.h) \ -+ include/linux/irqreturn.h \ -+ include/linux/hardirq.h \ -+ $(wildcard include/config/preempt/bkl.h) \ -+ $(wildcard include/config/virt/cpu/accounting.h) \ -+ include/linux/smp_lock.h \ -+ $(wildcard include/config/lock/kernel.h) \ -+ include/linux/sched.h \ -+ $(wildcard include/config/no/hz.h) \ -+ $(wildcard include/config/detect/softlockup.h) \ -+ $(wildcard include/config/keys.h) \ -+ $(wildcard include/config/bsd/process/acct.h) \ -+ $(wildcard include/config/taskstats.h) \ -+ $(wildcard include/config/inotify/user.h) \ -+ $(wildcard include/config/schedstats.h) \ -+ $(wildcard include/config/task/delay/acct.h) \ -+ $(wildcard include/config/blk/dev/io/trace.h) \ -+ $(wildcard include/config/cc/stackprotector.h) \ -+ $(wildcard include/config/sysvipc.h) \ -+ $(wildcard include/config/rt/mutexes.h) \ -+ $(wildcard include/config/task/xacct.h) \ -+ $(wildcard include/config/cpusets.h) \ -+ $(wildcard include/config/compat.h) \ -+ $(wildcard include/config/fault/injection.h) \ -+ include/asm/param.h \ -+ $(wildcard include/config/hz.h) \ -+ include/linux/timex.h \ -+ $(wildcard include/config/time/interpolation.h) \ -+ include/asm/timex.h \ -+ include/asm/tsc.h \ -+ $(wildcard include/config/x86/tsc.h) \ -+ $(wildcard include/config/x86/generic.h) \ -+ include/linux/jiffies.h \ -+ include/linux/calc64.h \ -+ include/asm/div64.h \ -+ include/asm/cputime.h \ -+ include/asm-generic/cputime.h \ -+ include/linux/sem.h \ -+ include/linux/ipc.h \ -+ $(wildcard include/config/ipc/ns.h) \ -+ include/asm/ipcbuf.h \ -+ include/asm/sembuf.h \ -+ include/linux/signal.h \ -+ include/asm/signal.h \ -+ include/asm-generic/signal.h \ -+ include/asm/siginfo.h \ -+ include/asm-generic/siginfo.h \ -+ include/linux/securebits.h \ -+ include/linux/fs_struct.h \ -+ include/linux/seccomp.h \ -+ $(wildcard include/config/seccomp.h) \ -+ include/linux/futex.h \ -+ $(wildcard include/config/futex.h) \ -+ include/linux/rtmutex.h \ -+ $(wildcard include/config/debug/rt/mutexes.h) \ -+ include/linux/plist.h \ -+ $(wildcard include/config/debug/pi/list.h) \ -+ include/linux/param.h \ -+ include/linux/resource.h \ -+ include/asm/resource.h \ -+ include/asm-generic/resource.h \ -+ include/linux/timer.h \ -+ $(wildcard include/config/timer/stats.h) \ -+ include/linux/ktime.h \ -+ $(wildcard include/config/ktime/scalar.h) \ -+ include/linux/hrtimer.h \ -+ include/linux/task_io_accounting.h \ -+ $(wildcard include/config/task/io/accounting.h) \ -+ include/linux/aio.h \ -+ include/linux/workqueue.h \ -+ include/linux/aio_abi.h \ -+ include/linux/uio.h \ -+ include/asm/hardirq.h \ -+ include/linux/irq.h \ -+ $(wildcard include/config/irq/per/cpu.h) \ -+ $(wildcard include/config/irq/release/method.h) \ -+ $(wildcard include/config/generic/pending/irq.h) \ -+ $(wildcard include/config/irqbalance.h) \ -+ $(wildcard include/config/auto/irq/affinity.h) \ -+ $(wildcard include/config/generic/hardirqs/no//do/irq.h) \ -+ include/asm/irq.h \ -+ include/asm-i386/mach-default/irq_vectors.h \ -+ include/asm-i386/mach-default/irq_vectors_limits.h \ -+ include/asm/irq_regs.h \ -+ include/asm/hw_irq.h \ -+ include/linux/profile.h \ -+ include/asm/sections.h \ -+ include/asm-generic/sections.h \ -+ include/linux/irq_cpustat.h \ -+ include/linux/if_ether.h \ -+ include/linux/skbuff.h \ -+ $(wildcard include/config/nf/conntrack.h) \ -+ $(wildcard include/config/bridge/netfilter.h) \ -+ $(wildcard include/config/vlan/8021q.h) \ -+ $(wildcard include/config/net/sched.h) \ -+ $(wildcard include/config/net/cls/act.h) \ -+ $(wildcard include/config/net/dma.h) \ -+ $(wildcard include/config/network/secmark.h) \ -+ include/linux/net.h \ -+ include/asm/socket.h \ -+ include/asm/sockios.h \ -+ include/linux/random.h \ -+ include/linux/sysctl.h \ -+ $(wildcard include/config/icmp/ipod.h) \ -+ $(wildcard include/config/web100/net100.h) \ -+ $(wildcard include/config/web100/stats.h) \ -+ include/linux/textsearch.h \ -+ include/net/checksum.h \ -+ include/asm/uaccess.h \ -+ $(wildcard include/config/x86/intel/usercopy.h) \ -+ $(wildcard include/config/x86/wp/works/ok.h) \ -+ include/asm/checksum.h \ -+ include/linux/in6.h \ -+ include/linux/dmaengine.h \ -+ $(wildcard include/config/dma/engine.h) \ -+ drivers/net/igb/kcompat.h \ -+ $(wildcard include/config/e1000/napi.h) \ -+ $(wildcard include/config/e1000e/napi.h) \ -+ $(wildcard include/config/ixgb/napi.h) \ -+ $(wildcard include/config/e1000/disable/packet/split.h) \ -+ $(wildcard include/config/igb/disable/packet/split.h) \ -+ $(wildcard include/config/net/poll/controller.h) \ -+ $(wildcard include/config/space/len.h) \ -+ $(wildcard include/config/netpoll.h) \ -+ $(wildcard include/config/netdevices/multiqueue.h) \ -+ include/linux/version.h \ -+ include/linux/netdevice.h \ -+ $(wildcard include/config/ax25.h) \ -+ $(wildcard include/config/tr.h) \ -+ $(wildcard include/config/net/ipip.h) \ -+ $(wildcard include/config/net/ipgre.h) \ -+ $(wildcard include/config/ipv6/sit.h) \ -+ $(wildcard include/config/ipv6/tunnel.h) \ -+ $(wildcard include/config/wireless/ext.h) \ -+ $(wildcard include/config/netpoll/trap.h) \ -+ include/linux/if.h \ -+ include/linux/socket.h \ -+ include/linux/sockios.h \ -+ include/linux/hdlc/ioctl.h \ -+ include/linux/if_packet.h \ -+ include/linux/etherdevice.h \ -+ include/linux/in.h \ -+ include/linux/ip.h \ -+ include/linux/udp.h \ -+ include/net/inet_sock.h \ -+ $(wildcard include/config/ipv6.h) \ -+ include/linux/jhash.h \ -+ include/net/flow.h \ -+ $(wildcard include/config/ipv6/mip6.h) \ -+ include/net/sock.h \ -+ $(wildcard include/config/security/network.h) \ -+ include/linux/security.h \ -+ $(wildcard include/config/security/network/xfrm.h) \ -+ include/linux/binfmts.h \ -+ include/linux/shm.h \ -+ include/asm/shmparam.h \ -+ include/asm/shmbuf.h \ -+ include/linux/msg.h \ -+ include/asm/msgbuf.h \ -+ include/linux/key.h \ -+ include/linux/xfrm.h \ -+ include/linux/filter.h \ -+ include/net/dst.h \ -+ $(wildcard include/config/net/cls/route.h) \ -+ $(wildcard include/config/xfrm.h) \ -+ include/linux/rtnetlink.h \ -+ include/linux/netlink.h \ -+ include/linux/if_link.h \ -+ include/linux/if_addr.h \ -+ include/linux/neighbour.h \ -+ include/net/neighbour.h \ -+ include/linux/seq_file.h \ -+ include/net/rtnetlink.h \ -+ include/net/netlink.h \ -+ include/net/request_sock.h \ -+ include/linux/mii.h \ -+ include/linux/latency.h \ -+ drivers/net/igb/e1000_regs.h \ -+ drivers/net/igb/e1000_defines.h \ -+ $(wildcard include/config/res.h) \ -+ $(wildcard include/config/fault.h) \ -+ drivers/net/igb/e1000_mac.h \ -+ drivers/net/igb/e1000_phy.h \ -+ drivers/net/igb/e1000_nvm.h \ -+ drivers/net/igb/e1000_manage.h \ -+ drivers/net/igb/e1000_82575.h \ -+ -+drivers/net/igb/e1000_mac.o: $(deps_drivers/net/igb/e1000_mac.o) -+ -+$(deps_drivers/net/igb/e1000_mac.o): -diff -Nru vanilla/drivers/net/igb/e1000_manage.c linux-i686-2.6.22/drivers/net/igb/e1000_manage.c ---- vanilla/drivers/net/igb/e1000_manage.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/e1000_manage.c 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,382 @@ +Index: linux-2.6.22/drivers/net/igb/e1000_manage.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/e1000_manage.c 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,383 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ Copyright(c) 2007-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, @@ -9189,7 +7727,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_manage.c linux-i686-2.6.22/drivers/net/i + * and also checks whether the previous command is completed. It busy waits + * in case of previous command is not completed. + **/ -+s32 e1000_mng_enable_host_if_generic(struct e1000_hw * hw) ++s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw) +{ + u32 hicr; + s32 ret_val = E1000_SUCCESS; @@ -9314,7 +7852,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_manage.c linux-i686-2.6.22/drivers/net/i + * + * Writes the DHCP information to the host interface. + **/ -+s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw * hw, u8 *buffer, ++s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, + u16 length) +{ + struct e1000_host_mng_command_header hdr; @@ -9360,8 +7898,8 @@ diff -Nru vanilla/drivers/net/igb/e1000_manage.c linux-i686-2.6.22/drivers/net/i + * + * Writes the command header after does the checksum calculation. + **/ -+s32 e1000_mng_write_cmd_header_generic(struct e1000_hw * hw, -+ struct e1000_host_mng_command_header * hdr) ++s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, ++ struct e1000_host_mng_command_header *hdr) +{ + u16 i, length = sizeof(struct e1000_host_mng_command_header); + @@ -9394,7 +7932,7 @@ diff -Nru vanilla/drivers/net/igb/e1000_manage.c linux-i686-2.6.22/drivers/net/i + * It also does alignment considerations to do the writes in most efficient + * way. Also fills up the sum of the buffer in *buffer parameter. + **/ -+s32 e1000_mng_host_if_write_generic(struct e1000_hw * hw, u8 *buffer, ++s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, + u16 length, u16 offset, u8 *sum) +{ + u8 *tmp; @@ -9443,7 +7981,8 @@ diff -Nru vanilla/drivers/net/igb/e1000_manage.c linux-i686-2.6.22/drivers/net/i + *sum += *(tmp + j); + } + -+ E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data); ++ E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, ++ data); + } + if (remaining) { + for (j = 0; j < sizeof(u32); j++) { @@ -9506,14 +8045,15 @@ diff -Nru vanilla/drivers/net/igb/e1000_manage.c linux-i686-2.6.22/drivers/net/i + return ret_val; +} + -diff -Nru vanilla/drivers/net/igb/e1000_manage.h linux-i686-2.6.22/drivers/net/igb/e1000_manage.h ---- vanilla/drivers/net/igb/e1000_manage.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/e1000_manage.h 2009-07-16 19:25:22.000000000 -0400 +Index: linux-2.6.22/drivers/net/igb/e1000_manage.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/e1000_manage.h 2009-12-18 12:39:22.000000000 -0500 @@ -0,0 +1,81 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ Copyright(c) 2007-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, @@ -9591,568 +8131,15 @@ diff -Nru vanilla/drivers/net/igb/e1000_manage.h linux-i686-2.6.22/drivers/net/i +#define E1000_IAMT_SIGNATURE 0x544D4149 + +#endif -Binary files vanilla/drivers/net/igb/e1000_manage.o and linux-i686-2.6.22/drivers/net/igb/e1000_manage.o differ -diff -Nru vanilla/drivers/net/igb/.e1000_manage.o.cmd linux-i686-2.6.22/drivers/net/igb/.e1000_manage.o.cmd ---- vanilla/drivers/net/igb/.e1000_manage.o.cmd 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/.e1000_manage.o.cmd 2009-07-16 19:53:43.000000000 -0400 -@@ -0,0 +1,549 @@ -+cmd_drivers/net/igb/e1000_manage.o := gcc -m32 -Wp,-MD,drivers/net/igb/.e1000_manage.o.d -nostdinc -isystem /usr/lib/gcc/i386-redhat-linux/4.1.2/include -D__KERNEL__ -Iinclude -include include/linux/autoconf.h -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Os -pipe -msoft-float -mregparm=3 -freg-struct-return -mpreferred-stack-boundary=2 -march=i686 -mtune=generic -ffreestanding -maccumulate-outgoing-args -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -Iinclude/asm-i386/mach-generic -Iinclude/asm-i386/mach-default -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -DMODULE -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(e1000_manage)" -D"KBUILD_MODNAME=KBUILD_STR(igb)" -c -o drivers/net/igb/.tmp_e1000_manage.o drivers/net/igb/e1000_manage.c -+ -+deps_drivers/net/igb/e1000_manage.o := \ -+ drivers/net/igb/e1000_manage.c \ -+ drivers/net/igb/e1000_api.h \ -+ drivers/net/igb/e1000_hw.h \ -+ drivers/net/igb/e1000_osdep.h \ -+ include/linux/pci.h \ -+ $(wildcard include/config/pci/msi.h) \ -+ $(wildcard include/config/pci.h) \ -+ $(wildcard include/config/ht/irq.h) \ -+ $(wildcard include/config/pci/domains.h) \ -+ include/linux/pci_regs.h \ -+ include/linux/mod_devicetable.h \ -+ include/linux/types.h \ -+ $(wildcard include/config/uid16.h) \ -+ $(wildcard include/config/lbd.h) \ -+ $(wildcard include/config/lsf.h) \ -+ $(wildcard include/config/resources/64bit.h) \ -+ include/linux/posix_types.h \ -+ include/linux/stddef.h \ -+ include/linux/compiler.h \ -+ $(wildcard include/config/enable/must/check.h) \ -+ include/linux/compiler-gcc4.h \ -+ $(wildcard include/config/forced/inlining.h) \ -+ include/linux/compiler-gcc.h \ -+ include/asm/posix_types.h \ -+ include/asm/types.h \ -+ $(wildcard include/config/highmem64g.h) \ -+ include/linux/ioport.h \ -+ include/linux/list.h \ -+ $(wildcard include/config/debug/list.h) \ -+ include/linux/poison.h \ -+ include/linux/prefetch.h \ -+ include/asm/processor.h \ -+ $(wildcard include/config/smp.h) \ -+ $(wildcard include/config/x86/ht.h) \ -+ $(wildcard include/config/paravirt.h) \ -+ $(wildcard include/config/mk8.h) \ -+ $(wildcard include/config/mk7.h) \ -+ include/asm/vm86.h \ -+ $(wildcard include/config/vm86.h) \ -+ include/asm/ptrace.h \ -+ include/asm/ptrace-abi.h \ -+ include/asm/segment.h \ -+ include/asm/math_emu.h \ -+ include/asm/sigcontext.h \ -+ include/asm/page.h \ -+ $(wildcard include/config/x86/use/3dnow.h) \ -+ $(wildcard include/config/x86/pae.h) \ -+ $(wildcard include/config/hugetlb/page.h) \ -+ $(wildcard include/config/highmem4g.h) \ -+ $(wildcard include/config/page/offset.h) \ -+ $(wildcard include/config/flatmem.h) \ -+ include/asm-generic/pgtable-nopmd.h \ -+ include/asm-generic/pgtable-nopud.h \ -+ include/asm-generic/memory_model.h \ -+ $(wildcard include/config/discontigmem.h) \ -+ $(wildcard include/config/sparsemem.h) \ -+ $(wildcard include/config/out/of/line/pfn/to/page.h) \ -+ include/asm-generic/page.h \ -+ include/asm/cpufeature.h \ -+ include/linux/bitops.h \ -+ include/asm/bitops.h \ -+ include/asm/alternative.h \ -+ include/asm-generic/bitops/sched.h \ -+ include/asm-generic/bitops/hweight.h \ -+ include/asm-generic/bitops/fls64.h \ -+ include/asm-generic/bitops/ext2-non-atomic.h \ -+ include/asm-generic/bitops/le.h \ -+ include/asm/byteorder.h \ -+ $(wildcard include/config/x86/bswap.h) \ -+ include/linux/byteorder/little_endian.h \ -+ include/linux/byteorder/swab.h \ -+ include/linux/byteorder/generic.h \ -+ include/asm-generic/bitops/minix.h \ -+ include/asm/required-features.h \ -+ $(wildcard include/config/x86/minimum/cpu.h) \ -+ $(wildcard include/config/x86/cmov.h) \ -+ $(wildcard include/config/x86/cmpxchg64.h) \ -+ include/asm/msr.h \ -+ include/asm/msr-index.h \ -+ include/asm/errno.h \ -+ include/asm-generic/errno.h \ -+ include/asm-generic/errno-base.h \ -+ include/linux/errno.h \ -+ include/asm/system.h \ -+ $(wildcard include/config/x86/oostore.h) \ -+ include/linux/kernel.h \ -+ $(wildcard include/config/preempt/voluntary.h) \ -+ $(wildcard include/config/debug/spinlock/sleep.h) \ -+ $(wildcard include/config/printk.h) \ -+ $(wildcard include/config/numa.h) \ -+ /usr/lib/gcc/i386-redhat-linux/4.1.2/include/stdarg.h \ -+ include/linux/linkage.h \ -+ include/asm/linkage.h \ -+ $(wildcard include/config/x86/alignment/16.h) \ -+ include/linux/log2.h \ -+ $(wildcard include/config/arch/has/ilog2/u32.h) \ -+ $(wildcard include/config/arch/has/ilog2/u64.h) \ -+ include/asm/bug.h \ -+ $(wildcard include/config/bug.h) \ -+ $(wildcard include/config/debug/bugverbose.h) \ -+ include/asm-generic/bug.h \ -+ $(wildcard include/config/generic/bug.h) \ -+ include/asm/cmpxchg.h \ -+ $(wildcard include/config/x86/cmpxchg.h) \ -+ include/linux/irqflags.h \ -+ $(wildcard include/config/trace/irqflags.h) \ -+ $(wildcard include/config/trace/irqflags/support.h) \ -+ $(wildcard include/config/x86.h) \ -+ include/asm/irqflags.h \ -+ include/asm/processor-flags.h \ -+ include/linux/cache.h \ -+ include/asm/cache.h \ -+ $(wildcard include/config/x86/l1/cache/shift.h) \ -+ include/linux/threads.h \ -+ $(wildcard include/config/nr/cpus.h) \ -+ $(wildcard include/config/base/small.h) \ -+ include/asm/percpu.h \ -+ include/linux/cpumask.h \ -+ $(wildcard include/config/hotplug/cpu.h) \ -+ include/linux/bitmap.h \ -+ include/linux/string.h \ -+ include/asm/string.h \ -+ include/linux/init.h \ -+ $(wildcard include/config/modules.h) \ -+ $(wildcard include/config/hotplug.h) \ -+ $(wildcard include/config/memory/hotplug.h) \ -+ $(wildcard include/config/acpi/hotplug/memory.h) \ -+ include/asm/atomic.h \ -+ $(wildcard include/config/m386.h) \ -+ include/asm-generic/atomic.h \ -+ include/linux/device.h \ -+ $(wildcard include/config/debug/devres.h) \ -+ include/linux/kobject.h \ -+ include/linux/sysfs.h \ -+ $(wildcard include/config/sysfs.h) \ -+ include/linux/spinlock.h \ -+ $(wildcard include/config/debug/spinlock.h) \ -+ $(wildcard include/config/preempt.h) \ -+ $(wildcard include/config/debug/lock/alloc.h) \ -+ include/linux/preempt.h \ -+ $(wildcard include/config/debug/preempt.h) \ -+ include/linux/thread_info.h \ -+ include/asm/thread_info.h \ -+ $(wildcard include/config/4kstacks.h) \ -+ $(wildcard include/config/debug/stack/usage.h) \ -+ include/linux/stringify.h \ -+ include/linux/bottom_half.h \ -+ include/linux/spinlock_types.h \ -+ include/linux/lockdep.h \ -+ $(wildcard include/config/lockdep.h) \ -+ $(wildcard include/config/generic/hardirqs.h) \ -+ $(wildcard include/config/prove/locking.h) \ -+ include/asm/spinlock_types.h \ -+ include/asm/spinlock.h \ -+ $(wildcard include/config/x86/ppro/fence.h) \ -+ include/asm/rwlock.h \ -+ include/linux/spinlock_api_smp.h \ -+ include/linux/kref.h \ -+ include/linux/wait.h \ -+ include/asm/current.h \ -+ include/linux/klist.h \ -+ include/linux/completion.h \ -+ include/linux/module.h \ -+ $(wildcard include/config/modversions.h) \ -+ $(wildcard include/config/unused/symbols.h) \ -+ $(wildcard include/config/module/unload.h) \ -+ $(wildcard include/config/kallsyms.h) \ -+ include/linux/stat.h \ -+ include/asm/stat.h \ -+ include/linux/time.h \ -+ include/linux/seqlock.h \ -+ include/linux/vs_time.h \ -+ $(wildcard include/config/vserver/vtime.h) \ -+ include/linux/kmod.h \ -+ $(wildcard include/config/kmod.h) \ -+ include/linux/elf.h \ -+ include/linux/auxvec.h \ -+ include/asm/auxvec.h \ -+ include/linux/elf-em.h \ -+ include/asm/elf.h \ -+ include/asm/user.h \ -+ include/asm/desc.h \ -+ include/asm/ldt.h \ -+ include/linux/smp.h \ -+ include/asm/smp.h \ -+ $(wildcard include/config/x86/local/apic.h) \ -+ $(wildcard include/config/x86/io/apic.h) \ -+ include/asm/mpspec.h \ -+ $(wildcard include/config/acpi.h) \ -+ include/asm/mpspec_def.h \ -+ include/asm-i386/mach-generic/mach_mpspec.h \ -+ include/asm/apic.h \ -+ $(wildcard include/config/x86/good/apic.h) \ -+ include/linux/pm.h \ -+ $(wildcard include/config/pm.h) \ -+ include/linux/delay.h \ -+ include/asm/delay.h \ -+ include/asm/fixmap.h \ -+ $(wildcard include/config/highmem.h) \ -+ $(wildcard include/config/x86/visws/apic.h) \ -+ $(wildcard include/config/x86/f00f/bug.h) \ -+ $(wildcard include/config/x86/cyclone/timer.h) \ -+ $(wildcard include/config/pci/mmconfig.h) \ -+ include/asm/acpi.h \ -+ $(wildcard include/config/acpi/sleep.h) \ -+ include/acpi/pdc_intel.h \ -+ include/asm/apicdef.h \ -+ include/asm/kmap_types.h \ -+ $(wildcard include/config/debug/highmem.h) \ -+ include/asm/io_apic.h \ -+ include/asm-i386/mach-generic/mach_apicdef.h \ -+ include/asm/genapic.h \ -+ include/linux/percpu.h \ -+ include/linux/slab.h \ -+ $(wildcard include/config/slab/debug.h) \ -+ $(wildcard include/config/slab.h) \ -+ $(wildcard include/config/slub.h) \ -+ $(wildcard include/config/debug/slab.h) \ -+ include/linux/gfp.h \ -+ $(wildcard include/config/zone/dma.h) \ -+ $(wildcard include/config/zone/dma32.h) \ -+ include/linux/mmzone.h \ -+ $(wildcard include/config/force/max/zoneorder.h) \ -+ $(wildcard include/config/arch/populates/node/map.h) \ -+ $(wildcard include/config/flat/node/mem/map.h) \ -+ $(wildcard include/config/have/memory/present.h) \ -+ $(wildcard include/config/need/node/memmap/size.h) \ -+ $(wildcard include/config/need/multiple/nodes.h) \ -+ $(wildcard include/config/have/arch/early/pfn/to/nid.h) \ -+ $(wildcard include/config/sparsemem/extreme.h) \ -+ $(wildcard include/config/nodes/span/other/nodes.h) \ -+ $(wildcard include/config/holes/in/zone.h) \ -+ include/linux/numa.h \ -+ $(wildcard include/config/nodes/shift.h) \ -+ include/linux/nodemask.h \ -+ include/linux/memory_hotplug.h \ -+ $(wildcard include/config/have/arch/nodedata/extension.h) \ -+ include/linux/notifier.h \ -+ include/linux/mutex.h \ -+ $(wildcard include/config/debug/mutexes.h) \ -+ $(wildcard include/config/chopstix.h) \ -+ include/linux/rwsem.h \ -+ $(wildcard include/config/rwsem/generic/spinlock.h) \ -+ include/asm/rwsem.h \ -+ include/linux/srcu.h \ -+ include/linux/topology.h \ -+ $(wildcard include/config/sched/smt.h) \ -+ $(wildcard include/config/sched/mc.h) \ -+ include/asm/topology.h \ -+ include/asm-generic/topology.h \ -+ include/linux/slab_def.h \ -+ include/linux/kmalloc_sizes.h \ -+ include/asm/mmu.h \ -+ include/asm/semaphore.h \ -+ include/linux/moduleparam.h \ -+ include/asm/local.h \ -+ include/asm/module.h \ -+ $(wildcard include/config/m486.h) \ -+ $(wildcard include/config/m586.h) \ -+ $(wildcard include/config/m586tsc.h) \ -+ $(wildcard include/config/m586mmx.h) \ -+ $(wildcard include/config/mcore2.h) \ -+ $(wildcard include/config/m686.h) \ -+ $(wildcard include/config/mpentiumii.h) \ -+ $(wildcard include/config/mpentiumiii.h) \ -+ $(wildcard include/config/mpentiumm.h) \ -+ $(wildcard include/config/mpentium4.h) \ -+ $(wildcard include/config/mk6.h) \ -+ $(wildcard include/config/x86/elan.h) \ -+ $(wildcard include/config/mcrusoe.h) \ -+ $(wildcard include/config/mefficeon.h) \ -+ $(wildcard include/config/mwinchipc6.h) \ -+ $(wildcard include/config/mwinchip2.h) \ -+ $(wildcard include/config/mwinchip3d.h) \ -+ $(wildcard include/config/mcyrixiii.h) \ -+ $(wildcard include/config/mviac3/2.h) \ -+ $(wildcard include/config/mviac7.h) \ -+ $(wildcard include/config/mgeodegx1.h) \ -+ $(wildcard include/config/mgeode/lx.h) \ -+ include/asm/device.h \ -+ include/linux/pci_ids.h \ -+ include/linux/dmapool.h \ -+ include/asm/io.h \ -+ $(wildcard include/config/x86/numaq.h) \ -+ include/asm-generic/iomap.h \ -+ include/linux/vmalloc.h \ -+ include/asm/scatterlist.h \ -+ include/asm/pci.h \ -+ include/linux/mm.h \ -+ $(wildcard include/config/sysctl.h) \ -+ $(wildcard include/config/mmu.h) \ -+ $(wildcard include/config/stack/growsup.h) \ -+ $(wildcard include/config/debug/vm.h) \ -+ $(wildcard include/config/shmem.h) \ -+ $(wildcard include/config/split/ptlock/cpus.h) \ -+ $(wildcard include/config/ia64.h) \ -+ $(wildcard include/config/proc/fs.h) \ -+ $(wildcard include/config/debug/pagealloc.h) \ -+ include/linux/capability.h \ -+ include/linux/rbtree.h \ -+ include/linux/prio_tree.h \ -+ include/linux/fs.h \ -+ $(wildcard include/config/dnotify.h) \ -+ $(wildcard include/config/vserver/cowbl.h) \ -+ $(wildcard include/config/quota.h) \ -+ $(wildcard include/config/inotify.h) \ -+ $(wildcard include/config/security.h) \ -+ $(wildcard include/config/epoll.h) \ -+ $(wildcard include/config/auditsyscall.h) \ -+ $(wildcard include/config/block.h) \ -+ $(wildcard include/config/fs/xip.h) \ -+ $(wildcard include/config/migration.h) \ -+ include/linux/limits.h \ -+ include/linux/ioctl.h \ -+ include/asm/ioctl.h \ -+ include/asm-generic/ioctl.h \ -+ include/linux/kdev_t.h \ -+ include/linux/dcache.h \ -+ $(wildcard include/config/profiling.h) \ -+ include/linux/rcupdate.h \ -+ include/linux/namei.h \ -+ include/linux/radix-tree.h \ -+ include/linux/pid.h \ -+ include/linux/quota.h \ -+ include/linux/dqblk_xfs.h \ -+ include/linux/dqblk_v1.h \ -+ include/linux/dqblk_v2.h \ -+ include/linux/nfs_fs_i.h \ -+ include/linux/nfs.h \ -+ include/linux/sunrpc/msg_prot.h \ -+ include/linux/fcntl.h \ -+ include/asm/fcntl.h \ -+ include/asm-generic/fcntl.h \ -+ $(wildcard include/config/64bit.h) \ -+ include/linux/err.h \ -+ include/linux/debug_locks.h \ -+ $(wildcard include/config/debug/locking/api/selftests.h) \ -+ include/linux/backing-dev.h \ -+ include/linux/mm_types.h \ -+ include/asm/pgtable.h \ -+ $(wildcard include/config/highpte.h) \ -+ include/asm/paravirt.h \ -+ include/asm/pgtable-2level-defs.h \ -+ include/asm/pgtable-2level.h \ -+ include/asm-generic/pgtable.h \ -+ include/linux/page-flags.h \ -+ $(wildcard include/config/s390.h) \ -+ $(wildcard include/config/swap.h) \ -+ include/linux/vmstat.h \ -+ $(wildcard include/config/vm/event/counters.h) \ -+ include/asm-generic/pci-dma-compat.h \ -+ include/linux/dma-mapping.h \ -+ include/asm/dma-mapping.h \ -+ include/asm-generic/pci.h \ -+ include/linux/interrupt.h \ -+ $(wildcard include/config/high/res/timers.h) \ -+ $(wildcard include/config/generic/irq/probe.h) \ -+ include/linux/irqreturn.h \ -+ include/linux/hardirq.h \ -+ $(wildcard include/config/preempt/bkl.h) \ -+ $(wildcard include/config/virt/cpu/accounting.h) \ -+ include/linux/smp_lock.h \ -+ $(wildcard include/config/lock/kernel.h) \ -+ include/linux/sched.h \ -+ $(wildcard include/config/no/hz.h) \ -+ $(wildcard include/config/detect/softlockup.h) \ -+ $(wildcard include/config/keys.h) \ -+ $(wildcard include/config/bsd/process/acct.h) \ -+ $(wildcard include/config/taskstats.h) \ -+ $(wildcard include/config/inotify/user.h) \ -+ $(wildcard include/config/schedstats.h) \ -+ $(wildcard include/config/task/delay/acct.h) \ -+ $(wildcard include/config/blk/dev/io/trace.h) \ -+ $(wildcard include/config/cc/stackprotector.h) \ -+ $(wildcard include/config/sysvipc.h) \ -+ $(wildcard include/config/rt/mutexes.h) \ -+ $(wildcard include/config/task/xacct.h) \ -+ $(wildcard include/config/cpusets.h) \ -+ $(wildcard include/config/compat.h) \ -+ $(wildcard include/config/fault/injection.h) \ -+ include/asm/param.h \ -+ $(wildcard include/config/hz.h) \ -+ include/linux/timex.h \ -+ $(wildcard include/config/time/interpolation.h) \ -+ include/asm/timex.h \ -+ include/asm/tsc.h \ -+ $(wildcard include/config/x86/tsc.h) \ -+ $(wildcard include/config/x86/generic.h) \ -+ include/linux/jiffies.h \ -+ include/linux/calc64.h \ -+ include/asm/div64.h \ -+ include/asm/cputime.h \ -+ include/asm-generic/cputime.h \ -+ include/linux/sem.h \ -+ include/linux/ipc.h \ -+ $(wildcard include/config/ipc/ns.h) \ -+ include/asm/ipcbuf.h \ -+ include/asm/sembuf.h \ -+ include/linux/signal.h \ -+ include/asm/signal.h \ -+ include/asm-generic/signal.h \ -+ include/asm/siginfo.h \ -+ include/asm-generic/siginfo.h \ -+ include/linux/securebits.h \ -+ include/linux/fs_struct.h \ -+ include/linux/seccomp.h \ -+ $(wildcard include/config/seccomp.h) \ -+ include/linux/futex.h \ -+ $(wildcard include/config/futex.h) \ -+ include/linux/rtmutex.h \ -+ $(wildcard include/config/debug/rt/mutexes.h) \ -+ include/linux/plist.h \ -+ $(wildcard include/config/debug/pi/list.h) \ -+ include/linux/param.h \ -+ include/linux/resource.h \ -+ include/asm/resource.h \ -+ include/asm-generic/resource.h \ -+ include/linux/timer.h \ -+ $(wildcard include/config/timer/stats.h) \ -+ include/linux/ktime.h \ -+ $(wildcard include/config/ktime/scalar.h) \ -+ include/linux/hrtimer.h \ -+ include/linux/task_io_accounting.h \ -+ $(wildcard include/config/task/io/accounting.h) \ -+ include/linux/aio.h \ -+ include/linux/workqueue.h \ -+ include/linux/aio_abi.h \ -+ include/linux/uio.h \ -+ include/asm/hardirq.h \ -+ include/linux/irq.h \ -+ $(wildcard include/config/irq/per/cpu.h) \ -+ $(wildcard include/config/irq/release/method.h) \ -+ $(wildcard include/config/generic/pending/irq.h) \ -+ $(wildcard include/config/irqbalance.h) \ -+ $(wildcard include/config/auto/irq/affinity.h) \ -+ $(wildcard include/config/generic/hardirqs/no//do/irq.h) \ -+ include/asm/irq.h \ -+ include/asm-i386/mach-default/irq_vectors.h \ -+ include/asm-i386/mach-default/irq_vectors_limits.h \ -+ include/asm/irq_regs.h \ -+ include/asm/hw_irq.h \ -+ include/linux/profile.h \ -+ include/asm/sections.h \ -+ include/asm-generic/sections.h \ -+ include/linux/irq_cpustat.h \ -+ include/linux/if_ether.h \ -+ include/linux/skbuff.h \ -+ $(wildcard include/config/nf/conntrack.h) \ -+ $(wildcard include/config/bridge/netfilter.h) \ -+ $(wildcard include/config/vlan/8021q.h) \ -+ $(wildcard include/config/net/sched.h) \ -+ $(wildcard include/config/net/cls/act.h) \ -+ $(wildcard include/config/net/dma.h) \ -+ $(wildcard include/config/network/secmark.h) \ -+ include/linux/net.h \ -+ include/asm/socket.h \ -+ include/asm/sockios.h \ -+ include/linux/random.h \ -+ include/linux/sysctl.h \ -+ $(wildcard include/config/icmp/ipod.h) \ -+ $(wildcard include/config/web100/net100.h) \ -+ $(wildcard include/config/web100/stats.h) \ -+ include/linux/textsearch.h \ -+ include/net/checksum.h \ -+ include/asm/uaccess.h \ -+ $(wildcard include/config/x86/intel/usercopy.h) \ -+ $(wildcard include/config/x86/wp/works/ok.h) \ -+ include/asm/checksum.h \ -+ include/linux/in6.h \ -+ include/linux/dmaengine.h \ -+ $(wildcard include/config/dma/engine.h) \ -+ drivers/net/igb/kcompat.h \ -+ $(wildcard include/config/e1000/napi.h) \ -+ $(wildcard include/config/e1000e/napi.h) \ -+ $(wildcard include/config/ixgb/napi.h) \ -+ $(wildcard include/config/e1000/disable/packet/split.h) \ -+ $(wildcard include/config/igb/disable/packet/split.h) \ -+ $(wildcard include/config/net/poll/controller.h) \ -+ $(wildcard include/config/space/len.h) \ -+ $(wildcard include/config/netpoll.h) \ -+ $(wildcard include/config/netdevices/multiqueue.h) \ -+ include/linux/version.h \ -+ include/linux/netdevice.h \ -+ $(wildcard include/config/ax25.h) \ -+ $(wildcard include/config/tr.h) \ -+ $(wildcard include/config/net/ipip.h) \ -+ $(wildcard include/config/net/ipgre.h) \ -+ $(wildcard include/config/ipv6/sit.h) \ -+ $(wildcard include/config/ipv6/tunnel.h) \ -+ $(wildcard include/config/wireless/ext.h) \ -+ $(wildcard include/config/netpoll/trap.h) \ -+ include/linux/if.h \ -+ include/linux/socket.h \ -+ include/linux/sockios.h \ -+ include/linux/hdlc/ioctl.h \ -+ include/linux/if_packet.h \ -+ include/linux/etherdevice.h \ -+ include/linux/in.h \ -+ include/linux/ip.h \ -+ include/linux/udp.h \ -+ include/net/inet_sock.h \ -+ $(wildcard include/config/ipv6.h) \ -+ include/linux/jhash.h \ -+ include/net/flow.h \ -+ $(wildcard include/config/ipv6/mip6.h) \ -+ include/net/sock.h \ -+ $(wildcard include/config/security/network.h) \ -+ include/linux/security.h \ -+ $(wildcard include/config/security/network/xfrm.h) \ -+ include/linux/binfmts.h \ -+ include/linux/shm.h \ -+ include/asm/shmparam.h \ -+ include/asm/shmbuf.h \ -+ include/linux/msg.h \ -+ include/asm/msgbuf.h \ -+ include/linux/key.h \ -+ include/linux/xfrm.h \ -+ include/linux/filter.h \ -+ include/net/dst.h \ -+ $(wildcard include/config/net/cls/route.h) \ -+ $(wildcard include/config/xfrm.h) \ -+ include/linux/rtnetlink.h \ -+ include/linux/netlink.h \ -+ include/linux/if_link.h \ -+ include/linux/if_addr.h \ -+ include/linux/neighbour.h \ -+ include/net/neighbour.h \ -+ include/linux/seq_file.h \ -+ include/net/rtnetlink.h \ -+ include/net/netlink.h \ -+ include/net/request_sock.h \ -+ include/linux/mii.h \ -+ include/linux/latency.h \ -+ drivers/net/igb/e1000_regs.h \ -+ drivers/net/igb/e1000_defines.h \ -+ $(wildcard include/config/res.h) \ -+ $(wildcard include/config/fault.h) \ -+ drivers/net/igb/e1000_mac.h \ -+ drivers/net/igb/e1000_phy.h \ -+ drivers/net/igb/e1000_nvm.h \ -+ drivers/net/igb/e1000_manage.h \ -+ drivers/net/igb/e1000_82575.h \ -+ -+drivers/net/igb/e1000_manage.o: $(deps_drivers/net/igb/e1000_manage.o) -+ -+$(deps_drivers/net/igb/e1000_manage.o): -diff -Nru vanilla/drivers/net/igb/e1000_nvm.c linux-i686-2.6.22/drivers/net/igb/e1000_nvm.c ---- vanilla/drivers/net/igb/e1000_nvm.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/e1000_nvm.c 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,634 @@ +Index: linux-2.6.22/drivers/net/igb/e1000_mbx.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/e1000_mbx.c 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,491 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ Copyright(c) 2007-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, @@ -10176,621 +8163,479 @@ diff -Nru vanilla/drivers/net/igb/e1000_nvm.c linux-i686-2.6.22/drivers/net/igb/ + +*******************************************************************************/ + -+#include "e1000_api.h" -+ -+static void e1000_stop_nvm(struct e1000_hw *hw); -+static void e1000_reload_nvm_generic(struct e1000_hw *hw); ++#include "e1000_mbx.h" + +/** -+ * e1000_init_nvm_ops_generic - Initialize NVM function pointers ++ * e1000_read_mbx - Reads a message from the mailbox + * @hw: pointer to the HW structure ++ * @msg: The message buffer ++ * @size: Length of buffer ++ * @mbx_id: id of mailbox to read + * -+ * Setups up the function pointers to no-op functions ++ * returns SUCCESS if it successfuly read message from buffer + **/ -+void e1000_init_nvm_ops_generic(struct e1000_hw *hw) ++s32 e1000_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) +{ -+ struct e1000_nvm_info *nvm = &hw->nvm; -+ DEBUGFUNC("e1000_init_nvm_ops_generic"); ++ struct e1000_mbx_info *mbx = &hw->mbx; ++ s32 ret_val = -E1000_ERR_MBX; + -+ /* Initialize function pointers */ -+ nvm->ops.reload = e1000_reload_nvm_generic; ++ DEBUGFUNC("e1000_read_mbx"); ++ ++ /* limit read to size of mailbox */ ++ if (size > mbx->size) ++ size = mbx->size; ++ ++ if (mbx->ops.read) ++ ret_val = mbx->ops.read(hw, msg, size, mbx_id); ++ ++ return ret_val; +} + +/** -+ * e1000_raise_eec_clk - Raise EEPROM clock ++ * e1000_write_mbx - Write a message to the mailbox + * @hw: pointer to the HW structure -+ * @eecd: pointer to the EEPROM ++ * @msg: The message buffer ++ * @size: Length of buffer ++ * @mbx_id: id of mailbox to write + * -+ * Enable/Raise the EEPROM clock bit. ++ * returns SUCCESS if it successfully copied message into the buffer + **/ -+static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd) ++s32 e1000_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) +{ -+ *eecd = *eecd | E1000_EECD_SK; -+ E1000_WRITE_REG(hw, E1000_EECD, *eecd); -+ E1000_WRITE_FLUSH(hw); -+ usec_delay(hw->nvm.delay_usec); ++ struct e1000_mbx_info *mbx = &hw->mbx; ++ s32 ret_val = E1000_SUCCESS; ++ ++ DEBUGFUNC("e1000_write_mbx"); ++ ++ if (size > mbx->size) ++ ret_val = -E1000_ERR_MBX; ++ ++ else if (mbx->ops.write) ++ ret_val = mbx->ops.write(hw, msg, size, mbx_id); ++ ++ return ret_val; +} + +/** -+ * e1000_lower_eec_clk - Lower EEPROM clock ++ * e1000_check_for_msg - checks to see if someone sent us mail + * @hw: pointer to the HW structure -+ * @eecd: pointer to the EEPROM ++ * @mbx_id: id of mailbox to check + * -+ * Clear/Lower the EEPROM clock bit. ++ * returns SUCCESS if the Status bit was found or else ERR_MBX + **/ -+static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd) ++s32 e1000_check_for_msg(struct e1000_hw *hw, u16 mbx_id) +{ -+ *eecd = *eecd & ~E1000_EECD_SK; -+ E1000_WRITE_REG(hw, E1000_EECD, *eecd); -+ E1000_WRITE_FLUSH(hw); -+ usec_delay(hw->nvm.delay_usec); ++ struct e1000_mbx_info *mbx = &hw->mbx; ++ s32 ret_val = -E1000_ERR_MBX; ++ ++ DEBUGFUNC("e1000_check_for_msg"); ++ ++ if (mbx->ops.check_for_msg) ++ ret_val = mbx->ops.check_for_msg(hw, mbx_id); ++ ++ return ret_val; +} + +/** -+ * e1000_shift_out_eec_bits - Shift data bits our to the EEPROM ++ * e1000_check_for_ack - checks to see if someone sent us ACK + * @hw: pointer to the HW structure -+ * @data: data to send to the EEPROM -+ * @count: number of bits to shift out ++ * @mbx_id: id of mailbox to check + * -+ * We need to shift 'count' bits out to the EEPROM. So, the value in the -+ * "data" parameter will be shifted out to the EEPROM one bit at a time. -+ * In order to do this, "data" must be broken down into bits. ++ * returns SUCCESS if the Status bit was found or else ERR_MBX + **/ -+static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count) ++s32 e1000_check_for_ack(struct e1000_hw *hw, u16 mbx_id) +{ -+ struct e1000_nvm_info *nvm = &hw->nvm; -+ u32 eecd = E1000_READ_REG(hw, E1000_EECD); -+ u32 mask; -+ -+ DEBUGFUNC("e1000_shift_out_eec_bits"); -+ -+ mask = 0x01 << (count - 1); -+ if (nvm->type == e1000_nvm_eeprom_spi) -+ eecd |= E1000_EECD_DO; -+ -+ do { -+ eecd &= ~E1000_EECD_DI; -+ -+ if (data & mask) -+ eecd |= E1000_EECD_DI; -+ -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); -+ E1000_WRITE_FLUSH(hw); -+ -+ usec_delay(nvm->delay_usec); ++ struct e1000_mbx_info *mbx = &hw->mbx; ++ s32 ret_val = -E1000_ERR_MBX; + -+ e1000_raise_eec_clk(hw, &eecd); -+ e1000_lower_eec_clk(hw, &eecd); ++ DEBUGFUNC("e1000_check_for_ack"); + -+ mask >>= 1; -+ } while (mask); ++ if (mbx->ops.check_for_ack) ++ ret_val = mbx->ops.check_for_ack(hw, mbx_id); + -+ eecd &= ~E1000_EECD_DI; -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); ++ return ret_val; +} + +/** -+ * e1000_shift_in_eec_bits - Shift data bits in from the EEPROM ++ * e1000_check_for_rst - checks to see if other side has reset + * @hw: pointer to the HW structure -+ * @count: number of bits to shift in ++ * @mbx_id: id of mailbox to check + * -+ * In order to read a register from the EEPROM, we need to shift 'count' bits -+ * in from the EEPROM. Bits are "shifted in" by raising the clock input to -+ * the EEPROM (setting the SK bit), and then reading the value of the data out -+ * "DO" bit. During this "shifting in" process the data in "DI" bit should -+ * always be clear. ++ * returns SUCCESS if the Status bit was found or else ERR_MBX + **/ -+static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count) ++s32 e1000_check_for_rst(struct e1000_hw *hw, u16 mbx_id) +{ -+ u32 eecd; -+ u32 i; -+ u16 data; ++ struct e1000_mbx_info *mbx = &hw->mbx; ++ s32 ret_val = -E1000_ERR_MBX; + -+ DEBUGFUNC("e1000_shift_in_eec_bits"); ++ DEBUGFUNC("e1000_check_for_rst"); + -+ eecd = E1000_READ_REG(hw, E1000_EECD); ++ if (mbx->ops.check_for_rst) ++ ret_val = mbx->ops.check_for_rst(hw, mbx_id); + -+ eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); -+ data = 0; ++ return ret_val; ++} + -+ for (i = 0; i < count; i++) { -+ data <<= 1; -+ e1000_raise_eec_clk(hw, &eecd); ++/** ++ * e1000_poll_for_msg - Wait for message notification ++ * @hw: pointer to the HW structure ++ * @mbx_id: id of mailbox to write ++ * ++ * returns SUCCESS if it successfully received a message notification ++ **/ ++static s32 e1000_poll_for_msg(struct e1000_hw *hw, u16 mbx_id) ++{ ++ struct e1000_mbx_info *mbx = &hw->mbx; ++ int countdown = mbx->timeout; + -+ eecd = E1000_READ_REG(hw, E1000_EECD); ++ DEBUGFUNC("e1000_poll_for_msg"); + -+ eecd &= ~E1000_EECD_DI; -+ if (eecd & E1000_EECD_DO) -+ data |= 1; ++ if (!countdown || !mbx->ops.check_for_msg) ++ goto out; + -+ e1000_lower_eec_clk(hw, &eecd); ++ while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) { ++ countdown--; ++ if (!countdown) ++ break; ++ usec_delay(mbx->usec_delay); + } + -+ return data; ++ /* if we failed, all future posted messages fail until reset */ ++ if (!countdown) ++ mbx->timeout = 0; ++out: ++ return countdown ? E1000_SUCCESS : -E1000_ERR_MBX; +} + +/** -+ * e1000_poll_eerd_eewr_done - Poll for EEPROM read/write completion ++ * e1000_poll_for_ack - Wait for message acknowledgement + * @hw: pointer to the HW structure -+ * @ee_reg: EEPROM flag for polling ++ * @mbx_id: id of mailbox to write + * -+ * Polls the EEPROM status bit for either read or write completion based -+ * upon the value of 'ee_reg'. ++ * returns SUCCESS if it successfully received a message acknowledgement + **/ -+s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg) ++static s32 e1000_poll_for_ack(struct e1000_hw *hw, u16 mbx_id) +{ -+ u32 attempts = 100000; -+ u32 i, reg = 0; -+ s32 ret_val = -E1000_ERR_NVM; ++ struct e1000_mbx_info *mbx = &hw->mbx; ++ int countdown = mbx->timeout; + -+ DEBUGFUNC("e1000_poll_eerd_eewr_done"); ++ DEBUGFUNC("e1000_poll_for_ack"); + -+ for (i = 0; i < attempts; i++) { -+ if (ee_reg == E1000_NVM_POLL_READ) -+ reg = E1000_READ_REG(hw, E1000_EERD); -+ else -+ reg = E1000_READ_REG(hw, E1000_EEWR); ++ if (!countdown || !mbx->ops.check_for_ack) ++ goto out; + -+ if (reg & E1000_NVM_RW_REG_DONE) { -+ ret_val = E1000_SUCCESS; ++ while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) { ++ countdown--; ++ if (!countdown) + break; -+ } -+ -+ usec_delay(5); ++ usec_delay(mbx->usec_delay); + } + -+ return ret_val; ++ /* if we failed, all future posted messages fail until reset */ ++ if (!countdown) ++ mbx->timeout = 0; ++out: ++ return countdown ? E1000_SUCCESS : -E1000_ERR_MBX; +} + +/** -+ * e1000_acquire_nvm_generic - Generic request for access to EEPROM ++ * e1000_read_posted_mbx - Wait for message notification and receive message + * @hw: pointer to the HW structure ++ * @msg: The message buffer ++ * @size: Length of buffer ++ * @mbx_id: id of mailbox to write + * -+ * Set the EEPROM access request bit and wait for EEPROM access grant bit. -+ * Return successful if access grant bit set, else clear the request for -+ * EEPROM access and return -E1000_ERR_NVM (-1). ++ * returns SUCCESS if it successfully received a message notification and ++ * copied it into the receive buffer. + **/ -+s32 e1000_acquire_nvm_generic(struct e1000_hw *hw) ++s32 e1000_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) +{ -+ u32 eecd = E1000_READ_REG(hw, E1000_EECD); -+ s32 timeout = E1000_NVM_GRANT_ATTEMPTS; -+ s32 ret_val = E1000_SUCCESS; -+ -+ DEBUGFUNC("e1000_acquire_nvm_generic"); ++ struct e1000_mbx_info *mbx = &hw->mbx; ++ s32 ret_val = -E1000_ERR_MBX; + -+ E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_REQ); -+ eecd = E1000_READ_REG(hw, E1000_EECD); ++ DEBUGFUNC("e1000_read_posted_mbx"); + -+ while (timeout) { -+ if (eecd & E1000_EECD_GNT) -+ break; -+ usec_delay(5); -+ eecd = E1000_READ_REG(hw, E1000_EECD); -+ timeout--; -+ } ++ if (!mbx->ops.read) ++ goto out; + -+ if (!timeout) { -+ eecd &= ~E1000_EECD_REQ; -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); -+ DEBUGOUT("Could not acquire NVM grant\n"); -+ ret_val = -E1000_ERR_NVM; -+ } ++ ret_val = e1000_poll_for_msg(hw, mbx_id); + ++ /* if ack received read message, otherwise we timed out */ ++ if (!ret_val) ++ ret_val = mbx->ops.read(hw, msg, size, mbx_id); ++out: + return ret_val; +} + +/** -+ * e1000_standby_nvm - Return EEPROM to standby state ++ * e1000_write_posted_mbx - Write a message to the mailbox, wait for ack + * @hw: pointer to the HW structure ++ * @msg: The message buffer ++ * @size: Length of buffer ++ * @mbx_id: id of mailbox to write + * -+ * Return the EEPROM to a standby state. ++ * returns SUCCESS if it successfully copied message into the buffer and ++ * received an ack to that message within delay * timeout period + **/ -+static void e1000_standby_nvm(struct e1000_hw *hw) ++s32 e1000_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) +{ -+ struct e1000_nvm_info *nvm = &hw->nvm; -+ u32 eecd = E1000_READ_REG(hw, E1000_EECD); ++ struct e1000_mbx_info *mbx = &hw->mbx; ++ s32 ret_val = -E1000_ERR_MBX; + -+ DEBUGFUNC("e1000_standby_nvm"); ++ DEBUGFUNC("e1000_write_posted_mbx"); + -+ if (nvm->type == e1000_nvm_eeprom_spi) { -+ /* Toggle CS to flush commands */ -+ eecd |= E1000_EECD_CS; -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); -+ E1000_WRITE_FLUSH(hw); -+ usec_delay(nvm->delay_usec); -+ eecd &= ~E1000_EECD_CS; -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); -+ E1000_WRITE_FLUSH(hw); -+ usec_delay(nvm->delay_usec); -+ } ++ /* exit if either we can't write or there isn't a defined timeout */ ++ if (!mbx->ops.write || !mbx->timeout) ++ goto out; ++ ++ /* send msg */ ++ ret_val = mbx->ops.write(hw, msg, size, mbx_id); ++ ++ /* if msg sent wait until we receive an ack */ ++ if (!ret_val) ++ ret_val = e1000_poll_for_ack(hw, mbx_id); ++out: ++ return ret_val; +} + +/** -+ * e1000_stop_nvm - Terminate EEPROM command ++ * e1000_init_mbx_ops_generic - Initialize NVM function pointers + * @hw: pointer to the HW structure + * -+ * Terminates the current command by inverting the EEPROM's chip select pin. ++ * Setups up the function pointers to no-op functions + **/ -+static void e1000_stop_nvm(struct e1000_hw *hw) ++void e1000_init_mbx_ops_generic(struct e1000_hw *hw) +{ -+ u32 eecd; ++ struct e1000_mbx_info *mbx = &hw->mbx; ++ mbx->ops.read_posted = e1000_read_posted_mbx; ++ mbx->ops.write_posted = e1000_write_posted_mbx; ++} + -+ DEBUGFUNC("e1000_stop_nvm"); ++static s32 e1000_check_for_bit_pf(struct e1000_hw *hw, u32 mask) ++{ ++ u32 mbvficr = E1000_READ_REG(hw, E1000_MBVFICR); ++ s32 ret_val = -E1000_ERR_MBX; + -+ eecd = E1000_READ_REG(hw, E1000_EECD); -+ if (hw->nvm.type == e1000_nvm_eeprom_spi) { -+ /* Pull CS high */ -+ eecd |= E1000_EECD_CS; -+ e1000_lower_eec_clk(hw, &eecd); ++ if (mbvficr & mask) { ++ ret_val = E1000_SUCCESS; ++ E1000_WRITE_REG(hw, E1000_MBVFICR, mask); + } ++ ++ return ret_val; +} + +/** -+ * e1000_release_nvm_generic - Release exclusive access to EEPROM ++ * e1000_check_for_msg_pf - checks to see if the VF has sent mail + * @hw: pointer to the HW structure ++ * @vf_number: the VF index + * -+ * Stop any current commands to the EEPROM and clear the EEPROM request bit. ++ * returns SUCCESS if the VF has set the Status bit or else ERR_MBX + **/ -+void e1000_release_nvm_generic(struct e1000_hw *hw) ++static s32 e1000_check_for_msg_pf(struct e1000_hw *hw, u16 vf_number) +{ -+ u32 eecd; ++ s32 ret_val = -E1000_ERR_MBX; + -+ DEBUGFUNC("e1000_release_nvm_generic"); ++ DEBUGFUNC("e1000_check_for_msg_pf"); + -+ e1000_stop_nvm(hw); ++ if (!e1000_check_for_bit_pf(hw, E1000_MBVFICR_VFREQ_VF1 << vf_number)) { ++ ret_val = E1000_SUCCESS; ++ hw->mbx.stats.reqs++; ++ } + -+ eecd = E1000_READ_REG(hw, E1000_EECD); -+ eecd &= ~E1000_EECD_REQ; -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); ++ return ret_val; +} + +/** -+ * e1000_ready_nvm_eeprom - Prepares EEPROM for read/write ++ * e1000_check_for_ack_pf - checks to see if the VF has ACKed + * @hw: pointer to the HW structure ++ * @vf_number: the VF index + * -+ * Setups the EEPROM for reading and writing. ++ * returns SUCCESS if the VF has set the Status bit or else ERR_MBX + **/ -+static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw) ++static s32 e1000_check_for_ack_pf(struct e1000_hw *hw, u16 vf_number) +{ -+ struct e1000_nvm_info *nvm = &hw->nvm; -+ u32 eecd = E1000_READ_REG(hw, E1000_EECD); -+ s32 ret_val = E1000_SUCCESS; -+ u16 timeout = 0; -+ u8 spi_stat_reg; -+ -+ DEBUGFUNC("e1000_ready_nvm_eeprom"); -+ -+ if (nvm->type == e1000_nvm_eeprom_spi) { -+ /* Clear SK and CS */ -+ eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); -+ usec_delay(1); -+ timeout = NVM_MAX_RETRY_SPI; -+ -+ /* -+ * Read "Status Register" repeatedly until the LSB is cleared. -+ * The EEPROM will signal that the command has been completed -+ * by clearing bit 0 of the internal status register. If it's -+ * not cleared within 'timeout', then error out. -+ */ -+ while (timeout) { -+ e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI, -+ hw->nvm.opcode_bits); -+ spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8); -+ if (!(spi_stat_reg & NVM_STATUS_RDY_SPI)) -+ break; ++ s32 ret_val = -E1000_ERR_MBX; + -+ usec_delay(5); -+ e1000_standby_nvm(hw); -+ timeout--; -+ } ++ DEBUGFUNC("e1000_check_for_ack_pf"); + -+ if (!timeout) { -+ DEBUGOUT("SPI NVM Status error\n"); -+ ret_val = -E1000_ERR_NVM; -+ goto out; -+ } ++ if (!e1000_check_for_bit_pf(hw, E1000_MBVFICR_VFACK_VF1 << vf_number)) { ++ ret_val = E1000_SUCCESS; ++ hw->mbx.stats.acks++; + } + -+out: + return ret_val; +} + +/** -+ * e1000_read_nvm_eerd - Reads EEPROM using EERD register ++ * e1000_check_for_rst_pf - checks to see if the VF has reset + * @hw: pointer to the HW structure -+ * @offset: offset of word in the EEPROM to read -+ * @words: number of words to read -+ * @data: word read from the EEPROM ++ * @vf_number: the VF index + * -+ * Reads a 16 bit word from the EEPROM using the EERD register. ++ * returns SUCCESS if the VF has set the Status bit or else ERR_MBX + **/ -+s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) ++static s32 e1000_check_for_rst_pf(struct e1000_hw *hw, u16 vf_number) +{ -+ struct e1000_nvm_info *nvm = &hw->nvm; -+ u32 i, eerd = 0; -+ s32 ret_val = E1000_SUCCESS; -+ -+ DEBUGFUNC("e1000_read_nvm_eerd"); -+ -+ /* -+ * A check for invalid values: offset too large, too many words, -+ * too many words for the offset, and not enough words. -+ */ -+ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || -+ (words == 0)) { -+ DEBUGOUT("nvm parameter(s) out of bounds\n"); -+ ret_val = -E1000_ERR_NVM; -+ goto out; -+ } -+ -+ for (i = 0; i < words; i++) { -+ eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) + -+ E1000_NVM_RW_REG_START; ++ u32 vflre = E1000_READ_REG(hw, E1000_VFLRE); ++ s32 ret_val = -E1000_ERR_MBX; + -+ E1000_WRITE_REG(hw, E1000_EERD, eerd); -+ ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); -+ if (ret_val) -+ break; ++ DEBUGFUNC("e1000_check_for_rst_pf"); + -+ data[i] = (E1000_READ_REG(hw, E1000_EERD) >> -+ E1000_NVM_RW_REG_DATA); ++ if (vflre & (1 << vf_number)) { ++ ret_val = E1000_SUCCESS; ++ E1000_WRITE_REG(hw, E1000_VFLRE, (1 << vf_number)); ++ hw->mbx.stats.rsts++; + } + -+out: + return ret_val; +} + +/** -+ * e1000_write_nvm_spi - Write to EEPROM using SPI ++ * e1000_obtain_mbx_lock_pf - obtain mailbox lock + * @hw: pointer to the HW structure -+ * @offset: offset within the EEPROM to be written to -+ * @words: number of words to write -+ * @data: 16 bit word(s) to be written to the EEPROM -+ * -+ * Writes data to EEPROM at offset using SPI interface. ++ * @vf_number: the VF index + * -+ * If e1000_update_nvm_checksum is not called after this function , the -+ * EEPROM will most likely contain an invalid checksum. ++ * return SUCCESS if we obtained the mailbox lock + **/ -+s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) ++static s32 e1000_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number) +{ -+ struct e1000_nvm_info *nvm = &hw->nvm; -+ s32 ret_val; -+ u16 widx = 0; -+ -+ DEBUGFUNC("e1000_write_nvm_spi"); -+ -+ /* -+ * A check for invalid values: offset too large, too many words, -+ * and not enough words. -+ */ -+ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || -+ (words == 0)) { -+ DEBUGOUT("nvm parameter(s) out of bounds\n"); -+ ret_val = -E1000_ERR_NVM; -+ goto out; -+ } -+ -+ ret_val = nvm->ops.acquire(hw); -+ if (ret_val) -+ goto out; -+ -+ while (widx < words) { -+ u8 write_opcode = NVM_WRITE_OPCODE_SPI; -+ -+ ret_val = e1000_ready_nvm_eeprom(hw); -+ if (ret_val) -+ goto release; -+ -+ e1000_standby_nvm(hw); -+ -+ /* Send the WRITE ENABLE command (8 bit opcode) */ -+ e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI, -+ nvm->opcode_bits); -+ -+ e1000_standby_nvm(hw); -+ -+ /* -+ * Some SPI eeproms use the 8th address bit embedded in the -+ * opcode -+ */ -+ if ((nvm->address_bits == 8) && (offset >= 128)) -+ write_opcode |= NVM_A8_OPCODE_SPI; ++ s32 ret_val = -E1000_ERR_MBX; ++ u32 p2v_mailbox; + -+ /* Send the Write command (8-bit opcode + addr) */ -+ e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits); -+ e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2), -+ nvm->address_bits); -+ -+ /* Loop to allow for up to whole page write of eeprom */ -+ while (widx < words) { -+ u16 word_out = data[widx]; -+ word_out = (word_out >> 8) | (word_out << 8); -+ e1000_shift_out_eec_bits(hw, word_out, 16); -+ widx++; ++ DEBUGFUNC("e1000_obtain_mbx_lock_pf"); + -+ if ((((offset + widx) * 2) % nvm->page_size) == 0) { -+ e1000_standby_nvm(hw); -+ break; -+ } -+ } -+ } ++ /* Take ownership of the buffer */ ++ E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU); + -+ msec_delay(10); -+release: -+ nvm->ops.release(hw); ++ /* reserve mailbox for vf use */ ++ p2v_mailbox = E1000_READ_REG(hw, E1000_P2VMAILBOX(vf_number)); ++ if (p2v_mailbox & E1000_P2VMAILBOX_PFU) ++ ret_val = E1000_SUCCESS; + -+out: + return ret_val; +} + +/** -+ * e1000_read_pba_num_generic - Read device part number ++ * e1000_write_mbx_pf - Places a message in the mailbox + * @hw: pointer to the HW structure -+ * @pba_num: pointer to device part number ++ * @msg: The message buffer ++ * @size: Length of buffer ++ * @vf_number: the VF index + * -+ * Reads the product board assembly (PBA) number from the EEPROM and stores -+ * the value in pba_num. ++ * returns SUCCESS if it successfully copied message into the buffer + **/ -+s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num) ++static s32 e1000_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, ++ u16 vf_number) +{ -+ s32 ret_val; -+ u16 nvm_data; ++ s32 ret_val; ++ u16 i; + -+ DEBUGFUNC("e1000_read_pba_num_generic"); ++ DEBUGFUNC("e1000_write_mbx_pf"); + -+ ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); -+ if (ret_val) { -+ DEBUGOUT("NVM Read Error\n"); -+ goto out; -+ } -+ *pba_num = (u32)(nvm_data << 16); ++ /* lock the mailbox to prevent pf/vf race condition */ ++ ret_val = e1000_obtain_mbx_lock_pf(hw, vf_number); ++ if (ret_val) ++ goto out_no_write; + -+ ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data); -+ if (ret_val) { -+ DEBUGOUT("NVM Read Error\n"); -+ goto out; -+ } -+ *pba_num |= nvm_data; ++ /* flush msg and acks as we are overwriting the message buffer */ ++ e1000_check_for_msg_pf(hw, vf_number); ++ e1000_check_for_ack_pf(hw, vf_number); + -+out: ++ /* copy the caller specified message to the mailbox memory buffer */ ++ for (i = 0; i < size; i++) ++ E1000_WRITE_REG_ARRAY(hw, E1000_VMBMEM(vf_number), i, msg[i]); ++ ++ /* Interrupt VF to tell it a message has been sent and release buffer*/ ++ E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_STS); ++ ++ /* update stats */ ++ hw->mbx.stats.msgs_tx++; ++ ++out_no_write: + return ret_val; ++ +} + +/** -+ * e1000_read_mac_addr_generic - Read device MAC address ++ * e1000_read_mbx_pf - Read a message from the mailbox + * @hw: pointer to the HW structure ++ * @msg: The message buffer ++ * @size: Length of buffer ++ * @vf_number: the VF index + * -+ * Reads the device MAC address from the EEPROM and stores the value. -+ * Since devices with two ports use the same EEPROM, we increment the -+ * last bit in the MAC address for the second port. ++ * This function copies a message from the mailbox buffer to the caller's ++ * memory buffer. The presumption is that the caller knows that there was ++ * a message due to a VF request so no polling for message is needed. + **/ -+s32 e1000_read_mac_addr_generic(struct e1000_hw *hw) ++static s32 e1000_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, ++ u16 vf_number) +{ -+ s32 ret_val = E1000_SUCCESS; -+ u16 offset, nvm_data, i; ++ s32 ret_val; ++ u16 i; + -+ DEBUGFUNC("e1000_read_mac_addr"); ++ DEBUGFUNC("e1000_read_mbx_pf"); + -+ for (i = 0; i < ETH_ADDR_LEN; i += 2) { -+ offset = i >> 1; -+ ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data); -+ if (ret_val) { -+ DEBUGOUT("NVM Read Error\n"); -+ goto out; -+ } -+ hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF); -+ hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8); -+ } ++ /* lock the mailbox to prevent pf/vf race condition */ ++ ret_val = e1000_obtain_mbx_lock_pf(hw, vf_number); ++ if (ret_val) ++ goto out_no_read; + -+ /* Flip last bit of mac address if we're on second port */ -+ if (hw->bus.func == E1000_FUNC_1) -+ hw->mac.perm_addr[5] ^= 1; ++ /* copy the message to the mailbox memory buffer */ ++ for (i = 0; i < size; i++) ++ msg[i] = E1000_READ_REG_ARRAY(hw, E1000_VMBMEM(vf_number), i); + -+ for (i = 0; i < ETH_ADDR_LEN; i++) -+ hw->mac.addr[i] = hw->mac.perm_addr[i]; ++ /* Acknowledge the message and release buffer */ ++ E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK); + -+out: ++ /* update stats */ ++ hw->mbx.stats.msgs_rx++; ++ ++out_no_read: + return ret_val; +} + +/** -+ * e1000_validate_nvm_checksum_generic - Validate EEPROM checksum ++ * e1000_init_mbx_params_pf - set initial values for pf mailbox + * @hw: pointer to the HW structure + * -+ * Calculates the EEPROM checksum by reading/adding each word of the EEPROM -+ * and then verifies that the sum of the EEPROM is equal to 0xBABA. -+ **/ -+s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw) ++ * Initializes the hw->mbx struct to correct values for pf mailbox ++ */ ++s32 e1000_init_mbx_params_pf(struct e1000_hw *hw) +{ -+ s32 ret_val = E1000_SUCCESS; -+ u16 checksum = 0; -+ u16 i, nvm_data; ++ struct e1000_mbx_info *mbx = &hw->mbx; + -+ DEBUGFUNC("e1000_validate_nvm_checksum_generic"); ++ if (hw->mac.type == e1000_82576) { ++ mbx->timeout = 0; ++ mbx->usec_delay = 0; + -+ for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { -+ ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); -+ if (ret_val) { -+ DEBUGOUT("NVM Read Error\n"); -+ goto out; -+ } -+ checksum += nvm_data; -+ } ++ mbx->size = E1000_VFMAILBOX_SIZE; + -+ if (checksum != (u16) NVM_SUM) { -+ DEBUGOUT("NVM Checksum Invalid\n"); -+ ret_val = -E1000_ERR_NVM; -+ goto out; ++ mbx->ops.read = e1000_read_mbx_pf; ++ mbx->ops.write = e1000_write_mbx_pf; ++ mbx->ops.read_posted = e1000_read_posted_mbx; ++ mbx->ops.write_posted = e1000_write_posted_mbx; ++ mbx->ops.check_for_msg = e1000_check_for_msg_pf; ++ mbx->ops.check_for_ack = e1000_check_for_ack_pf; ++ mbx->ops.check_for_rst = e1000_check_for_rst_pf; ++ ++ mbx->stats.msgs_tx = 0; ++ mbx->stats.msgs_rx = 0; ++ mbx->stats.reqs = 0; ++ mbx->stats.acks = 0; ++ mbx->stats.rsts = 0; + } + -+out: -+ return ret_val; ++ return E1000_SUCCESS; +} + -+/** -+ * e1000_update_nvm_checksum_generic - Update EEPROM checksum -+ * @hw: pointer to the HW structure -+ * -+ * Updates the EEPROM checksum by reading/adding each word of the EEPROM -+ * up to the checksum. Then calculates the EEPROM checksum and writes the -+ * value to the EEPROM. -+ **/ -+s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw) -+{ -+ s32 ret_val; -+ u16 checksum = 0; -+ u16 i, nvm_data; -+ -+ DEBUGFUNC("e1000_update_nvm_checksum"); -+ -+ for (i = 0; i < NVM_CHECKSUM_REG; i++) { -+ ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); -+ if (ret_val) { -+ DEBUGOUT("NVM Read Error while updating checksum.\n"); -+ goto out; -+ } -+ checksum += nvm_data; -+ } -+ checksum = (u16) NVM_SUM - checksum; -+ ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum); -+ if (ret_val) { -+ DEBUGOUT("NVM Write Error while updating checksum.\n"); -+ } -+ -+out: -+ return ret_val; -+} -+ -+/** -+ * e1000_reload_nvm_generic - Reloads EEPROM -+ * @hw: pointer to the HW structure -+ * -+ * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the -+ * extended control register. -+ **/ -+static void e1000_reload_nvm_generic(struct e1000_hw *hw) -+{ -+ u32 ctrl_ext; -+ -+ DEBUGFUNC("e1000_reload_nvm_generic"); -+ -+ usec_delay(10); -+ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); -+ ctrl_ext |= E1000_CTRL_EXT_EE_RST; -+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); -+ E1000_WRITE_FLUSH(hw); -+} -+ -diff -Nru vanilla/drivers/net/igb/e1000_nvm.h linux-i686-2.6.22/drivers/net/igb/e1000_nvm.h ---- vanilla/drivers/net/igb/e1000_nvm.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/e1000_nvm.h 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,50 @@ +Index: linux-2.6.22/drivers/net/igb/e1000_mbx.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/e1000_mbx.h 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,87 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ Copyright(c) 2007-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, @@ -10814,591 +8659,75 @@ diff -Nru vanilla/drivers/net/igb/e1000_nvm.h linux-i686-2.6.22/drivers/net/igb/ + +*******************************************************************************/ + -+#ifndef _E1000_NVM_H_ -+#define _E1000_NVM_H_ ++#ifndef _E1000_MBX_H_ ++#define _E1000_MBX_H_ + -+void e1000_init_nvm_ops_generic(struct e1000_hw *hw); -+s32 e1000_acquire_nvm_generic(struct e1000_hw *hw); ++#include "e1000_api.h" + -+s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg); -+s32 e1000_read_mac_addr_generic(struct e1000_hw *hw); -+s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num); -+s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, -+ u16 *data); -+s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data); -+s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw); -+s32 e1000_write_nvm_eewr(struct e1000_hw *hw, u16 offset, -+ u16 words, u16 *data); -+s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, -+ u16 *data); -+s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw); -+void e1000_release_nvm_generic(struct e1000_hw *hw); ++#define E1000_P2VMAILBOX_STS 0x00000001 /* Initiate message send to VF */ ++#define E1000_P2VMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */ ++#define E1000_P2VMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ ++#define E1000_P2VMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ ++#define E1000_P2VMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */ + -+#define E1000_STM_OPCODE 0xDB00 ++#define E1000_MBVFICR_VFREQ_MASK 0x000000FF /* bits for VF messages */ ++#define E1000_MBVFICR_VFREQ_VF1 0x00000001 /* bit for VF 1 message */ ++#define E1000_MBVFICR_VFACK_MASK 0x00FF0000 /* bits for VF acks */ ++#define E1000_MBVFICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */ + -+#endif -Binary files vanilla/drivers/net/igb/e1000_nvm.o and linux-i686-2.6.22/drivers/net/igb/e1000_nvm.o differ -diff -Nru vanilla/drivers/net/igb/.e1000_nvm.o.cmd linux-i686-2.6.22/drivers/net/igb/.e1000_nvm.o.cmd ---- vanilla/drivers/net/igb/.e1000_nvm.o.cmd 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/.e1000_nvm.o.cmd 2009-07-16 19:53:42.000000000 -0400 -@@ -0,0 +1,549 @@ -+cmd_drivers/net/igb/e1000_nvm.o := gcc -m32 -Wp,-MD,drivers/net/igb/.e1000_nvm.o.d -nostdinc -isystem /usr/lib/gcc/i386-redhat-linux/4.1.2/include -D__KERNEL__ -Iinclude -include include/linux/autoconf.h -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Os -pipe -msoft-float -mregparm=3 -freg-struct-return -mpreferred-stack-boundary=2 -march=i686 -mtune=generic -ffreestanding -maccumulate-outgoing-args -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -Iinclude/asm-i386/mach-generic -Iinclude/asm-i386/mach-default -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -DMODULE -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(e1000_nvm)" -D"KBUILD_MODNAME=KBUILD_STR(igb)" -c -o drivers/net/igb/.tmp_e1000_nvm.o drivers/net/igb/e1000_nvm.c -+ -+deps_drivers/net/igb/e1000_nvm.o := \ -+ drivers/net/igb/e1000_nvm.c \ -+ drivers/net/igb/e1000_api.h \ -+ drivers/net/igb/e1000_hw.h \ -+ drivers/net/igb/e1000_osdep.h \ -+ include/linux/pci.h \ -+ $(wildcard include/config/pci/msi.h) \ -+ $(wildcard include/config/pci.h) \ -+ $(wildcard include/config/ht/irq.h) \ -+ $(wildcard include/config/pci/domains.h) \ -+ include/linux/pci_regs.h \ -+ include/linux/mod_devicetable.h \ -+ include/linux/types.h \ -+ $(wildcard include/config/uid16.h) \ -+ $(wildcard include/config/lbd.h) \ -+ $(wildcard include/config/lsf.h) \ -+ $(wildcard include/config/resources/64bit.h) \ -+ include/linux/posix_types.h \ -+ include/linux/stddef.h \ -+ include/linux/compiler.h \ -+ $(wildcard include/config/enable/must/check.h) \ -+ include/linux/compiler-gcc4.h \ -+ $(wildcard include/config/forced/inlining.h) \ -+ include/linux/compiler-gcc.h \ -+ include/asm/posix_types.h \ -+ include/asm/types.h \ -+ $(wildcard include/config/highmem64g.h) \ -+ include/linux/ioport.h \ -+ include/linux/list.h \ -+ $(wildcard include/config/debug/list.h) \ -+ include/linux/poison.h \ -+ include/linux/prefetch.h \ -+ include/asm/processor.h \ -+ $(wildcard include/config/smp.h) \ -+ $(wildcard include/config/x86/ht.h) \ -+ $(wildcard include/config/paravirt.h) \ -+ $(wildcard include/config/mk8.h) \ -+ $(wildcard include/config/mk7.h) \ -+ include/asm/vm86.h \ -+ $(wildcard include/config/vm86.h) \ -+ include/asm/ptrace.h \ -+ include/asm/ptrace-abi.h \ -+ include/asm/segment.h \ -+ include/asm/math_emu.h \ -+ include/asm/sigcontext.h \ -+ include/asm/page.h \ -+ $(wildcard include/config/x86/use/3dnow.h) \ -+ $(wildcard include/config/x86/pae.h) \ -+ $(wildcard include/config/hugetlb/page.h) \ -+ $(wildcard include/config/highmem4g.h) \ -+ $(wildcard include/config/page/offset.h) \ -+ $(wildcard include/config/flatmem.h) \ -+ include/asm-generic/pgtable-nopmd.h \ -+ include/asm-generic/pgtable-nopud.h \ -+ include/asm-generic/memory_model.h \ -+ $(wildcard include/config/discontigmem.h) \ -+ $(wildcard include/config/sparsemem.h) \ -+ $(wildcard include/config/out/of/line/pfn/to/page.h) \ -+ include/asm-generic/page.h \ -+ include/asm/cpufeature.h \ -+ include/linux/bitops.h \ -+ include/asm/bitops.h \ -+ include/asm/alternative.h \ -+ include/asm-generic/bitops/sched.h \ -+ include/asm-generic/bitops/hweight.h \ -+ include/asm-generic/bitops/fls64.h \ -+ include/asm-generic/bitops/ext2-non-atomic.h \ -+ include/asm-generic/bitops/le.h \ -+ include/asm/byteorder.h \ -+ $(wildcard include/config/x86/bswap.h) \ -+ include/linux/byteorder/little_endian.h \ -+ include/linux/byteorder/swab.h \ -+ include/linux/byteorder/generic.h \ -+ include/asm-generic/bitops/minix.h \ -+ include/asm/required-features.h \ -+ $(wildcard include/config/x86/minimum/cpu.h) \ -+ $(wildcard include/config/x86/cmov.h) \ -+ $(wildcard include/config/x86/cmpxchg64.h) \ -+ include/asm/msr.h \ -+ include/asm/msr-index.h \ -+ include/asm/errno.h \ -+ include/asm-generic/errno.h \ -+ include/asm-generic/errno-base.h \ -+ include/linux/errno.h \ -+ include/asm/system.h \ -+ $(wildcard include/config/x86/oostore.h) \ -+ include/linux/kernel.h \ -+ $(wildcard include/config/preempt/voluntary.h) \ -+ $(wildcard include/config/debug/spinlock/sleep.h) \ -+ $(wildcard include/config/printk.h) \ -+ $(wildcard include/config/numa.h) \ -+ /usr/lib/gcc/i386-redhat-linux/4.1.2/include/stdarg.h \ -+ include/linux/linkage.h \ -+ include/asm/linkage.h \ -+ $(wildcard include/config/x86/alignment/16.h) \ -+ include/linux/log2.h \ -+ $(wildcard include/config/arch/has/ilog2/u32.h) \ -+ $(wildcard include/config/arch/has/ilog2/u64.h) \ -+ include/asm/bug.h \ -+ $(wildcard include/config/bug.h) \ -+ $(wildcard include/config/debug/bugverbose.h) \ -+ include/asm-generic/bug.h \ -+ $(wildcard include/config/generic/bug.h) \ -+ include/asm/cmpxchg.h \ -+ $(wildcard include/config/x86/cmpxchg.h) \ -+ include/linux/irqflags.h \ -+ $(wildcard include/config/trace/irqflags.h) \ -+ $(wildcard include/config/trace/irqflags/support.h) \ -+ $(wildcard include/config/x86.h) \ -+ include/asm/irqflags.h \ -+ include/asm/processor-flags.h \ -+ include/linux/cache.h \ -+ include/asm/cache.h \ -+ $(wildcard include/config/x86/l1/cache/shift.h) \ -+ include/linux/threads.h \ -+ $(wildcard include/config/nr/cpus.h) \ -+ $(wildcard include/config/base/small.h) \ -+ include/asm/percpu.h \ -+ include/linux/cpumask.h \ -+ $(wildcard include/config/hotplug/cpu.h) \ -+ include/linux/bitmap.h \ -+ include/linux/string.h \ -+ include/asm/string.h \ -+ include/linux/init.h \ -+ $(wildcard include/config/modules.h) \ -+ $(wildcard include/config/hotplug.h) \ -+ $(wildcard include/config/memory/hotplug.h) \ -+ $(wildcard include/config/acpi/hotplug/memory.h) \ -+ include/asm/atomic.h \ -+ $(wildcard include/config/m386.h) \ -+ include/asm-generic/atomic.h \ -+ include/linux/device.h \ -+ $(wildcard include/config/debug/devres.h) \ -+ include/linux/kobject.h \ -+ include/linux/sysfs.h \ -+ $(wildcard include/config/sysfs.h) \ -+ include/linux/spinlock.h \ -+ $(wildcard include/config/debug/spinlock.h) \ -+ $(wildcard include/config/preempt.h) \ -+ $(wildcard include/config/debug/lock/alloc.h) \ -+ include/linux/preempt.h \ -+ $(wildcard include/config/debug/preempt.h) \ -+ include/linux/thread_info.h \ -+ include/asm/thread_info.h \ -+ $(wildcard include/config/4kstacks.h) \ -+ $(wildcard include/config/debug/stack/usage.h) \ -+ include/linux/stringify.h \ -+ include/linux/bottom_half.h \ -+ include/linux/spinlock_types.h \ -+ include/linux/lockdep.h \ -+ $(wildcard include/config/lockdep.h) \ -+ $(wildcard include/config/generic/hardirqs.h) \ -+ $(wildcard include/config/prove/locking.h) \ -+ include/asm/spinlock_types.h \ -+ include/asm/spinlock.h \ -+ $(wildcard include/config/x86/ppro/fence.h) \ -+ include/asm/rwlock.h \ -+ include/linux/spinlock_api_smp.h \ -+ include/linux/kref.h \ -+ include/linux/wait.h \ -+ include/asm/current.h \ -+ include/linux/klist.h \ -+ include/linux/completion.h \ -+ include/linux/module.h \ -+ $(wildcard include/config/modversions.h) \ -+ $(wildcard include/config/unused/symbols.h) \ -+ $(wildcard include/config/module/unload.h) \ -+ $(wildcard include/config/kallsyms.h) \ -+ include/linux/stat.h \ -+ include/asm/stat.h \ -+ include/linux/time.h \ -+ include/linux/seqlock.h \ -+ include/linux/vs_time.h \ -+ $(wildcard include/config/vserver/vtime.h) \ -+ include/linux/kmod.h \ -+ $(wildcard include/config/kmod.h) \ -+ include/linux/elf.h \ -+ include/linux/auxvec.h \ -+ include/asm/auxvec.h \ -+ include/linux/elf-em.h \ -+ include/asm/elf.h \ -+ include/asm/user.h \ -+ include/asm/desc.h \ -+ include/asm/ldt.h \ -+ include/linux/smp.h \ -+ include/asm/smp.h \ -+ $(wildcard include/config/x86/local/apic.h) \ -+ $(wildcard include/config/x86/io/apic.h) \ -+ include/asm/mpspec.h \ -+ $(wildcard include/config/acpi.h) \ -+ include/asm/mpspec_def.h \ -+ include/asm-i386/mach-generic/mach_mpspec.h \ -+ include/asm/apic.h \ -+ $(wildcard include/config/x86/good/apic.h) \ -+ include/linux/pm.h \ -+ $(wildcard include/config/pm.h) \ -+ include/linux/delay.h \ -+ include/asm/delay.h \ -+ include/asm/fixmap.h \ -+ $(wildcard include/config/highmem.h) \ -+ $(wildcard include/config/x86/visws/apic.h) \ -+ $(wildcard include/config/x86/f00f/bug.h) \ -+ $(wildcard include/config/x86/cyclone/timer.h) \ -+ $(wildcard include/config/pci/mmconfig.h) \ -+ include/asm/acpi.h \ -+ $(wildcard include/config/acpi/sleep.h) \ -+ include/acpi/pdc_intel.h \ -+ include/asm/apicdef.h \ -+ include/asm/kmap_types.h \ -+ $(wildcard include/config/debug/highmem.h) \ -+ include/asm/io_apic.h \ -+ include/asm-i386/mach-generic/mach_apicdef.h \ -+ include/asm/genapic.h \ -+ include/linux/percpu.h \ -+ include/linux/slab.h \ -+ $(wildcard include/config/slab/debug.h) \ -+ $(wildcard include/config/slab.h) \ -+ $(wildcard include/config/slub.h) \ -+ $(wildcard include/config/debug/slab.h) \ -+ include/linux/gfp.h \ -+ $(wildcard include/config/zone/dma.h) \ -+ $(wildcard include/config/zone/dma32.h) \ -+ include/linux/mmzone.h \ -+ $(wildcard include/config/force/max/zoneorder.h) \ -+ $(wildcard include/config/arch/populates/node/map.h) \ -+ $(wildcard include/config/flat/node/mem/map.h) \ -+ $(wildcard include/config/have/memory/present.h) \ -+ $(wildcard include/config/need/node/memmap/size.h) \ -+ $(wildcard include/config/need/multiple/nodes.h) \ -+ $(wildcard include/config/have/arch/early/pfn/to/nid.h) \ -+ $(wildcard include/config/sparsemem/extreme.h) \ -+ $(wildcard include/config/nodes/span/other/nodes.h) \ -+ $(wildcard include/config/holes/in/zone.h) \ -+ include/linux/numa.h \ -+ $(wildcard include/config/nodes/shift.h) \ -+ include/linux/nodemask.h \ -+ include/linux/memory_hotplug.h \ -+ $(wildcard include/config/have/arch/nodedata/extension.h) \ -+ include/linux/notifier.h \ -+ include/linux/mutex.h \ -+ $(wildcard include/config/debug/mutexes.h) \ -+ $(wildcard include/config/chopstix.h) \ -+ include/linux/rwsem.h \ -+ $(wildcard include/config/rwsem/generic/spinlock.h) \ -+ include/asm/rwsem.h \ -+ include/linux/srcu.h \ -+ include/linux/topology.h \ -+ $(wildcard include/config/sched/smt.h) \ -+ $(wildcard include/config/sched/mc.h) \ -+ include/asm/topology.h \ -+ include/asm-generic/topology.h \ -+ include/linux/slab_def.h \ -+ include/linux/kmalloc_sizes.h \ -+ include/asm/mmu.h \ -+ include/asm/semaphore.h \ -+ include/linux/moduleparam.h \ -+ include/asm/local.h \ -+ include/asm/module.h \ -+ $(wildcard include/config/m486.h) \ -+ $(wildcard include/config/m586.h) \ -+ $(wildcard include/config/m586tsc.h) \ -+ $(wildcard include/config/m586mmx.h) \ -+ $(wildcard include/config/mcore2.h) \ -+ $(wildcard include/config/m686.h) \ -+ $(wildcard include/config/mpentiumii.h) \ -+ $(wildcard include/config/mpentiumiii.h) \ -+ $(wildcard include/config/mpentiumm.h) \ -+ $(wildcard include/config/mpentium4.h) \ -+ $(wildcard include/config/mk6.h) \ -+ $(wildcard include/config/x86/elan.h) \ -+ $(wildcard include/config/mcrusoe.h) \ -+ $(wildcard include/config/mefficeon.h) \ -+ $(wildcard include/config/mwinchipc6.h) \ -+ $(wildcard include/config/mwinchip2.h) \ -+ $(wildcard include/config/mwinchip3d.h) \ -+ $(wildcard include/config/mcyrixiii.h) \ -+ $(wildcard include/config/mviac3/2.h) \ -+ $(wildcard include/config/mviac7.h) \ -+ $(wildcard include/config/mgeodegx1.h) \ -+ $(wildcard include/config/mgeode/lx.h) \ -+ include/asm/device.h \ -+ include/linux/pci_ids.h \ -+ include/linux/dmapool.h \ -+ include/asm/io.h \ -+ $(wildcard include/config/x86/numaq.h) \ -+ include/asm-generic/iomap.h \ -+ include/linux/vmalloc.h \ -+ include/asm/scatterlist.h \ -+ include/asm/pci.h \ -+ include/linux/mm.h \ -+ $(wildcard include/config/sysctl.h) \ -+ $(wildcard include/config/mmu.h) \ -+ $(wildcard include/config/stack/growsup.h) \ -+ $(wildcard include/config/debug/vm.h) \ -+ $(wildcard include/config/shmem.h) \ -+ $(wildcard include/config/split/ptlock/cpus.h) \ -+ $(wildcard include/config/ia64.h) \ -+ $(wildcard include/config/proc/fs.h) \ -+ $(wildcard include/config/debug/pagealloc.h) \ -+ include/linux/capability.h \ -+ include/linux/rbtree.h \ -+ include/linux/prio_tree.h \ -+ include/linux/fs.h \ -+ $(wildcard include/config/dnotify.h) \ -+ $(wildcard include/config/vserver/cowbl.h) \ -+ $(wildcard include/config/quota.h) \ -+ $(wildcard include/config/inotify.h) \ -+ $(wildcard include/config/security.h) \ -+ $(wildcard include/config/epoll.h) \ -+ $(wildcard include/config/auditsyscall.h) \ -+ $(wildcard include/config/block.h) \ -+ $(wildcard include/config/fs/xip.h) \ -+ $(wildcard include/config/migration.h) \ -+ include/linux/limits.h \ -+ include/linux/ioctl.h \ -+ include/asm/ioctl.h \ -+ include/asm-generic/ioctl.h \ -+ include/linux/kdev_t.h \ -+ include/linux/dcache.h \ -+ $(wildcard include/config/profiling.h) \ -+ include/linux/rcupdate.h \ -+ include/linux/namei.h \ -+ include/linux/radix-tree.h \ -+ include/linux/pid.h \ -+ include/linux/quota.h \ -+ include/linux/dqblk_xfs.h \ -+ include/linux/dqblk_v1.h \ -+ include/linux/dqblk_v2.h \ -+ include/linux/nfs_fs_i.h \ -+ include/linux/nfs.h \ -+ include/linux/sunrpc/msg_prot.h \ -+ include/linux/fcntl.h \ -+ include/asm/fcntl.h \ -+ include/asm-generic/fcntl.h \ -+ $(wildcard include/config/64bit.h) \ -+ include/linux/err.h \ -+ include/linux/debug_locks.h \ -+ $(wildcard include/config/debug/locking/api/selftests.h) \ -+ include/linux/backing-dev.h \ -+ include/linux/mm_types.h \ -+ include/asm/pgtable.h \ -+ $(wildcard include/config/highpte.h) \ -+ include/asm/paravirt.h \ -+ include/asm/pgtable-2level-defs.h \ -+ include/asm/pgtable-2level.h \ -+ include/asm-generic/pgtable.h \ -+ include/linux/page-flags.h \ -+ $(wildcard include/config/s390.h) \ -+ $(wildcard include/config/swap.h) \ -+ include/linux/vmstat.h \ -+ $(wildcard include/config/vm/event/counters.h) \ -+ include/asm-generic/pci-dma-compat.h \ -+ include/linux/dma-mapping.h \ -+ include/asm/dma-mapping.h \ -+ include/asm-generic/pci.h \ -+ include/linux/interrupt.h \ -+ $(wildcard include/config/high/res/timers.h) \ -+ $(wildcard include/config/generic/irq/probe.h) \ -+ include/linux/irqreturn.h \ -+ include/linux/hardirq.h \ -+ $(wildcard include/config/preempt/bkl.h) \ -+ $(wildcard include/config/virt/cpu/accounting.h) \ -+ include/linux/smp_lock.h \ -+ $(wildcard include/config/lock/kernel.h) \ -+ include/linux/sched.h \ -+ $(wildcard include/config/no/hz.h) \ -+ $(wildcard include/config/detect/softlockup.h) \ -+ $(wildcard include/config/keys.h) \ -+ $(wildcard include/config/bsd/process/acct.h) \ -+ $(wildcard include/config/taskstats.h) \ -+ $(wildcard include/config/inotify/user.h) \ -+ $(wildcard include/config/schedstats.h) \ -+ $(wildcard include/config/task/delay/acct.h) \ -+ $(wildcard include/config/blk/dev/io/trace.h) \ -+ $(wildcard include/config/cc/stackprotector.h) \ -+ $(wildcard include/config/sysvipc.h) \ -+ $(wildcard include/config/rt/mutexes.h) \ -+ $(wildcard include/config/task/xacct.h) \ -+ $(wildcard include/config/cpusets.h) \ -+ $(wildcard include/config/compat.h) \ -+ $(wildcard include/config/fault/injection.h) \ -+ include/asm/param.h \ -+ $(wildcard include/config/hz.h) \ -+ include/linux/timex.h \ -+ $(wildcard include/config/time/interpolation.h) \ -+ include/asm/timex.h \ -+ include/asm/tsc.h \ -+ $(wildcard include/config/x86/tsc.h) \ -+ $(wildcard include/config/x86/generic.h) \ -+ include/linux/jiffies.h \ -+ include/linux/calc64.h \ -+ include/asm/div64.h \ -+ include/asm/cputime.h \ -+ include/asm-generic/cputime.h \ -+ include/linux/sem.h \ -+ include/linux/ipc.h \ -+ $(wildcard include/config/ipc/ns.h) \ -+ include/asm/ipcbuf.h \ -+ include/asm/sembuf.h \ -+ include/linux/signal.h \ -+ include/asm/signal.h \ -+ include/asm-generic/signal.h \ -+ include/asm/siginfo.h \ -+ include/asm-generic/siginfo.h \ -+ include/linux/securebits.h \ -+ include/linux/fs_struct.h \ -+ include/linux/seccomp.h \ -+ $(wildcard include/config/seccomp.h) \ -+ include/linux/futex.h \ -+ $(wildcard include/config/futex.h) \ -+ include/linux/rtmutex.h \ -+ $(wildcard include/config/debug/rt/mutexes.h) \ -+ include/linux/plist.h \ -+ $(wildcard include/config/debug/pi/list.h) \ -+ include/linux/param.h \ -+ include/linux/resource.h \ -+ include/asm/resource.h \ -+ include/asm-generic/resource.h \ -+ include/linux/timer.h \ -+ $(wildcard include/config/timer/stats.h) \ -+ include/linux/ktime.h \ -+ $(wildcard include/config/ktime/scalar.h) \ -+ include/linux/hrtimer.h \ -+ include/linux/task_io_accounting.h \ -+ $(wildcard include/config/task/io/accounting.h) \ -+ include/linux/aio.h \ -+ include/linux/workqueue.h \ -+ include/linux/aio_abi.h \ -+ include/linux/uio.h \ -+ include/asm/hardirq.h \ -+ include/linux/irq.h \ -+ $(wildcard include/config/irq/per/cpu.h) \ -+ $(wildcard include/config/irq/release/method.h) \ -+ $(wildcard include/config/generic/pending/irq.h) \ -+ $(wildcard include/config/irqbalance.h) \ -+ $(wildcard include/config/auto/irq/affinity.h) \ -+ $(wildcard include/config/generic/hardirqs/no//do/irq.h) \ -+ include/asm/irq.h \ -+ include/asm-i386/mach-default/irq_vectors.h \ -+ include/asm-i386/mach-default/irq_vectors_limits.h \ -+ include/asm/irq_regs.h \ -+ include/asm/hw_irq.h \ -+ include/linux/profile.h \ -+ include/asm/sections.h \ -+ include/asm-generic/sections.h \ -+ include/linux/irq_cpustat.h \ -+ include/linux/if_ether.h \ -+ include/linux/skbuff.h \ -+ $(wildcard include/config/nf/conntrack.h) \ -+ $(wildcard include/config/bridge/netfilter.h) \ -+ $(wildcard include/config/vlan/8021q.h) \ -+ $(wildcard include/config/net/sched.h) \ -+ $(wildcard include/config/net/cls/act.h) \ -+ $(wildcard include/config/net/dma.h) \ -+ $(wildcard include/config/network/secmark.h) \ -+ include/linux/net.h \ -+ include/asm/socket.h \ -+ include/asm/sockios.h \ -+ include/linux/random.h \ -+ include/linux/sysctl.h \ -+ $(wildcard include/config/icmp/ipod.h) \ -+ $(wildcard include/config/web100/net100.h) \ -+ $(wildcard include/config/web100/stats.h) \ -+ include/linux/textsearch.h \ -+ include/net/checksum.h \ -+ include/asm/uaccess.h \ -+ $(wildcard include/config/x86/intel/usercopy.h) \ -+ $(wildcard include/config/x86/wp/works/ok.h) \ -+ include/asm/checksum.h \ -+ include/linux/in6.h \ -+ include/linux/dmaengine.h \ -+ $(wildcard include/config/dma/engine.h) \ -+ drivers/net/igb/kcompat.h \ -+ $(wildcard include/config/e1000/napi.h) \ -+ $(wildcard include/config/e1000e/napi.h) \ -+ $(wildcard include/config/ixgb/napi.h) \ -+ $(wildcard include/config/e1000/disable/packet/split.h) \ -+ $(wildcard include/config/igb/disable/packet/split.h) \ -+ $(wildcard include/config/net/poll/controller.h) \ -+ $(wildcard include/config/space/len.h) \ -+ $(wildcard include/config/netpoll.h) \ -+ $(wildcard include/config/netdevices/multiqueue.h) \ -+ include/linux/version.h \ -+ include/linux/netdevice.h \ -+ $(wildcard include/config/ax25.h) \ -+ $(wildcard include/config/tr.h) \ -+ $(wildcard include/config/net/ipip.h) \ -+ $(wildcard include/config/net/ipgre.h) \ -+ $(wildcard include/config/ipv6/sit.h) \ -+ $(wildcard include/config/ipv6/tunnel.h) \ -+ $(wildcard include/config/wireless/ext.h) \ -+ $(wildcard include/config/netpoll/trap.h) \ -+ include/linux/if.h \ -+ include/linux/socket.h \ -+ include/linux/sockios.h \ -+ include/linux/hdlc/ioctl.h \ -+ include/linux/if_packet.h \ -+ include/linux/etherdevice.h \ -+ include/linux/in.h \ -+ include/linux/ip.h \ -+ include/linux/udp.h \ -+ include/net/inet_sock.h \ -+ $(wildcard include/config/ipv6.h) \ -+ include/linux/jhash.h \ -+ include/net/flow.h \ -+ $(wildcard include/config/ipv6/mip6.h) \ -+ include/net/sock.h \ -+ $(wildcard include/config/security/network.h) \ -+ include/linux/security.h \ -+ $(wildcard include/config/security/network/xfrm.h) \ -+ include/linux/binfmts.h \ -+ include/linux/shm.h \ -+ include/asm/shmparam.h \ -+ include/asm/shmbuf.h \ -+ include/linux/msg.h \ -+ include/asm/msgbuf.h \ -+ include/linux/key.h \ -+ include/linux/xfrm.h \ -+ include/linux/filter.h \ -+ include/net/dst.h \ -+ $(wildcard include/config/net/cls/route.h) \ -+ $(wildcard include/config/xfrm.h) \ -+ include/linux/rtnetlink.h \ -+ include/linux/netlink.h \ -+ include/linux/if_link.h \ -+ include/linux/if_addr.h \ -+ include/linux/neighbour.h \ -+ include/net/neighbour.h \ -+ include/linux/seq_file.h \ -+ include/net/rtnetlink.h \ -+ include/net/netlink.h \ -+ include/net/request_sock.h \ -+ include/linux/mii.h \ -+ include/linux/latency.h \ -+ drivers/net/igb/e1000_regs.h \ -+ drivers/net/igb/e1000_defines.h \ -+ $(wildcard include/config/res.h) \ -+ $(wildcard include/config/fault.h) \ -+ drivers/net/igb/e1000_mac.h \ -+ drivers/net/igb/e1000_phy.h \ -+ drivers/net/igb/e1000_nvm.h \ -+ drivers/net/igb/e1000_manage.h \ -+ drivers/net/igb/e1000_82575.h \ -+ -+drivers/net/igb/e1000_nvm.o: $(deps_drivers/net/igb/e1000_nvm.o) -+ -+$(deps_drivers/net/igb/e1000_nvm.o): -diff -Nru vanilla/drivers/net/igb/e1000_osdep.h linux-i686-2.6.22/drivers/net/igb/e1000_osdep.h ---- vanilla/drivers/net/igb/e1000_osdep.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/e1000_osdep.h 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,121 @@ ++#define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */ ++ ++/* If it's a E1000_VF_* msg then it originates in the VF and is sent to the ++ * PF. The reverse is true if it is E1000_PF_*. ++ * Message ACK's are the value or'd with 0xF0000000 ++ */ ++#define E1000_VT_MSGTYPE_ACK 0x80000000 /* Messages below or'd with ++ * this are the ACK */ ++#define E1000_VT_MSGTYPE_NACK 0x40000000 /* Messages below or'd with ++ * this are the NACK */ ++#define E1000_VT_MSGTYPE_CTS 0x20000000 /* Indicates that VF is still ++ clear to send requests */ ++#define E1000_VT_MSGINFO_SHIFT 16 ++/* bits 23:16 are used for exra info for certain messages */ ++#define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT) ++ ++#define E1000_VF_RESET 0x01 /* VF requests reset */ ++#define E1000_VF_SET_MAC_ADDR 0x02 /* VF requests to set MAC addr */ ++#define E1000_VF_SET_MULTICAST 0x03 /* VF requests to set MC addr */ ++#define E1000_VF_SET_MULTICAST_COUNT_MASK (0x1F << E1000_VT_MSGINFO_SHIFT) ++#define E1000_VF_SET_MULTICAST_OVERFLOW (0x80 << E1000_VT_MSGINFO_SHIFT) ++#define E1000_VF_SET_VLAN 0x04 /* VF requests to set VLAN */ ++#define E1000_VF_SET_VLAN_ADD (0x01 << E1000_VT_MSGINFO_SHIFT) ++#define E1000_VF_SET_LPE 0x05 /* VF requests to set VMOLR.LPE */ ++#define E1000_VF_SET_PROMISC 0x06 /*VF requests to clear VMOLR.ROPE/MPME*/ ++#define E1000_VF_SET_PROMISC_UNICAST (0x01 << E1000_VT_MSGINFO_SHIFT) ++#define E1000_VF_SET_PROMISC_MULTICAST (0x02 << E1000_VT_MSGINFO_SHIFT) ++ ++#define E1000_PF_CONTROL_MSG 0x0100 /* PF control message */ ++ ++#define E1000_VF_MBX_INIT_TIMEOUT 2000 /* number of retries on mailbox */ ++#define E1000_VF_MBX_INIT_DELAY 500 /* microseconds between retries */ ++ ++s32 e1000_read_mbx(struct e1000_hw *, u32 *, u16, u16); ++s32 e1000_write_mbx(struct e1000_hw *, u32 *, u16, u16); ++s32 e1000_read_posted_mbx(struct e1000_hw *, u32 *, u16, u16); ++s32 e1000_write_posted_mbx(struct e1000_hw *, u32 *, u16, u16); ++s32 e1000_check_for_msg(struct e1000_hw *, u16); ++s32 e1000_check_for_ack(struct e1000_hw *, u16); ++s32 e1000_check_for_rst(struct e1000_hw *, u16); ++void e1000_init_mbx_ops_generic(struct e1000_hw *hw); ++s32 e1000_init_mbx_params_pf(struct e1000_hw *); ++ ++#endif /* _E1000_MBX_H_ */ +Index: linux-2.6.22/drivers/net/igb/e1000_nvm.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/e1000_nvm.c 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,625 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ Copyright(c) 2007-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, @@ -11422,1830 +8751,1584 @@ diff -Nru vanilla/drivers/net/igb/e1000_osdep.h linux-i686-2.6.22/drivers/net/ig + +*******************************************************************************/ + ++#include "e1000_api.h" + -+/* glue for the OS independent part of e1000 -+ * includes register access macros -+ */ -+ -+#ifndef _E1000_OSDEP_H_ -+#define _E1000_OSDEP_H_ -+ -+#include -+#include -+#include -+#include -+#include -+#include "kcompat.h" ++static void e1000_stop_nvm(struct e1000_hw *hw); ++static void e1000_reload_nvm_generic(struct e1000_hw *hw); + -+#define usec_delay(x) udelay(x) -+#ifndef msec_delay -+#define msec_delay(x) do { if (in_interrupt()) { \ -+ /* Don't mdelay in interrupt context! */ \ -+ BUG(); \ -+ } else { \ -+ msleep(x); \ -+ } } while (0) ++/** ++ * e1000_init_nvm_ops_generic - Initialize NVM function pointers ++ * @hw: pointer to the HW structure ++ * ++ * Setups up the function pointers to no-op functions ++ **/ ++void e1000_init_nvm_ops_generic(struct e1000_hw *hw) ++{ ++ struct e1000_nvm_info *nvm = &hw->nvm; ++ DEBUGFUNC("e1000_init_nvm_ops_generic"); + -+/* Some workarounds require millisecond delays and are run during interrupt -+ * context. Most notably, when establishing link, the phy may need tweaking -+ * but cannot process phy register reads/writes faster than millisecond -+ * intervals...and we establish link due to a "link status change" interrupt. -+ */ -+#define msec_delay_irq(x) mdelay(x) -+#endif ++ /* Initialize function pointers */ ++ nvm->ops.reload = e1000_reload_nvm_generic; ++} + -+#define PCI_COMMAND_REGISTER PCI_COMMAND -+#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE -+#define ETH_ADDR_LEN ETH_ALEN ++/** ++ * e1000_raise_eec_clk - Raise EEPROM clock ++ * @hw: pointer to the HW structure ++ * @eecd: pointer to the EEPROM ++ * ++ * Enable/Raise the EEPROM clock bit. ++ **/ ++static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd) ++{ ++ *eecd = *eecd | E1000_EECD_SK; ++ E1000_WRITE_REG(hw, E1000_EECD, *eecd); ++ E1000_WRITE_FLUSH(hw); ++ usec_delay(hw->nvm.delay_usec); ++} + -+#ifdef __BIG_ENDIAN -+#define E1000_BIG_ENDIAN __BIG_ENDIAN -+#endif ++/** ++ * e1000_lower_eec_clk - Lower EEPROM clock ++ * @hw: pointer to the HW structure ++ * @eecd: pointer to the EEPROM ++ * ++ * Clear/Lower the EEPROM clock bit. ++ **/ ++static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd) ++{ ++ *eecd = *eecd & ~E1000_EECD_SK; ++ E1000_WRITE_REG(hw, E1000_EECD, *eecd); ++ E1000_WRITE_FLUSH(hw); ++ usec_delay(hw->nvm.delay_usec); ++} + ++/** ++ * e1000_shift_out_eec_bits - Shift data bits our to the EEPROM ++ * @hw: pointer to the HW structure ++ * @data: data to send to the EEPROM ++ * @count: number of bits to shift out ++ * ++ * We need to shift 'count' bits out to the EEPROM. So, the value in the ++ * "data" parameter will be shifted out to the EEPROM one bit at a time. ++ * In order to do this, "data" must be broken down into bits. ++ **/ ++static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count) ++{ ++ struct e1000_nvm_info *nvm = &hw->nvm; ++ u32 eecd = E1000_READ_REG(hw, E1000_EECD); ++ u32 mask; + -+#define DEBUGOUT(S) -+#define DEBUGOUT1(S, A...) ++ DEBUGFUNC("e1000_shift_out_eec_bits"); + -+#define DEBUGFUNC(F) DEBUGOUT(F "\n") -+#define DEBUGOUT2 DEBUGOUT1 -+#define DEBUGOUT3 DEBUGOUT2 -+#define DEBUGOUT7 DEBUGOUT3 ++ mask = 0x01 << (count - 1); ++ if (nvm->type == e1000_nvm_eeprom_spi) ++ eecd |= E1000_EECD_DO; + -+#define E1000_REGISTER(a, reg) reg ++ do { ++ eecd &= ~E1000_EECD_DI; + -+#define E1000_WRITE_REG(a, reg, value) ( \ -+ writel((value), ((a)->hw_addr + E1000_REGISTER(a, reg)))) ++ if (data & mask) ++ eecd |= E1000_EECD_DI; + -+#define E1000_READ_REG(a, reg) (readl((a)->hw_addr + E1000_REGISTER(a, reg))) ++ E1000_WRITE_REG(hw, E1000_EECD, eecd); ++ E1000_WRITE_FLUSH(hw); + -+#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \ -+ writel((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 2)))) ++ usec_delay(nvm->delay_usec); + -+#define E1000_READ_REG_ARRAY(a, reg, offset) ( \ -+ readl((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 2))) ++ e1000_raise_eec_clk(hw, &eecd); ++ e1000_lower_eec_clk(hw, &eecd); + -+#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY -+#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY ++ mask >>= 1; ++ } while (mask); + -+#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \ -+ writew((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 1)))) ++ eecd &= ~E1000_EECD_DI; ++ E1000_WRITE_REG(hw, E1000_EECD, eecd); ++} + -+#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \ -+ readw((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 1))) ++/** ++ * e1000_shift_in_eec_bits - Shift data bits in from the EEPROM ++ * @hw: pointer to the HW structure ++ * @count: number of bits to shift in ++ * ++ * In order to read a register from the EEPROM, we need to shift 'count' bits ++ * in from the EEPROM. Bits are "shifted in" by raising the clock input to ++ * the EEPROM (setting the SK bit), and then reading the value of the data out ++ * "DO" bit. During this "shifting in" process the data in "DI" bit should ++ * always be clear. ++ **/ ++static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count) ++{ ++ u32 eecd; ++ u32 i; ++ u16 data; + -+#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \ -+ writeb((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + (offset)))) ++ DEBUGFUNC("e1000_shift_in_eec_bits"); + -+#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \ -+ readb((a)->hw_addr + E1000_REGISTER(a, reg) + (offset))) ++ eecd = E1000_READ_REG(hw, E1000_EECD); + -+#define E1000_WRITE_REG_IO(a, reg, offset) do { \ -+ outl(reg, ((a)->io_base)); \ -+ outl(offset, ((a)->io_base + 4)); } while (0) ++ eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); ++ data = 0; + -+#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, E1000_STATUS) ++ for (i = 0; i < count; i++) { ++ data <<= 1; ++ e1000_raise_eec_clk(hw, &eecd); + -+#define E1000_WRITE_FLASH_REG(a, reg, value) ( \ -+ writel((value), ((a)->flash_address + reg))) ++ eecd = E1000_READ_REG(hw, E1000_EECD); + -+#define E1000_WRITE_FLASH_REG16(a, reg, value) ( \ -+ writew((value), ((a)->flash_address + reg))) ++ eecd &= ~E1000_EECD_DI; ++ if (eecd & E1000_EECD_DO) ++ data |= 1; + -+#define E1000_READ_FLASH_REG(a, reg) (readl((a)->flash_address + reg)) ++ e1000_lower_eec_clk(hw, &eecd); ++ } + -+#define E1000_READ_FLASH_REG16(a, reg) (readw((a)->flash_address + reg)) ++ return data; ++} + -+#endif /* _E1000_OSDEP_H_ */ -diff -Nru vanilla/drivers/net/igb/e1000_phy.c linux-i686-2.6.22/drivers/net/igb/e1000_phy.c ---- vanilla/drivers/net/igb/e1000_phy.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/e1000_phy.c 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,2052 @@ -+/******************************************************************************* ++/** ++ * e1000_poll_eerd_eewr_done - Poll for EEPROM read/write completion ++ * @hw: pointer to the HW structure ++ * @ee_reg: EEPROM flag for polling ++ * ++ * Polls the EEPROM status bit for either read or write completion based ++ * upon the value of 'ee_reg'. ++ **/ ++s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg) ++{ ++ u32 attempts = 100000; ++ u32 i, reg = 0; ++ s32 ret_val = -E1000_ERR_NVM; + -+ Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ DEBUGFUNC("e1000_poll_eerd_eewr_done"); + -+ 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. ++ for (i = 0; i < attempts; i++) { ++ if (ee_reg == E1000_NVM_POLL_READ) ++ reg = E1000_READ_REG(hw, E1000_EERD); ++ else ++ reg = E1000_READ_REG(hw, E1000_EEWR); + -+ 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. ++ if (reg & E1000_NVM_RW_REG_DONE) { ++ ret_val = E1000_SUCCESS; ++ break; ++ } + -+ 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. ++ usec_delay(5); ++ } + -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". ++ return ret_val; ++} + -+ Contact Information: -+ e1000-devel Mailing List -+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++/** ++ * e1000_acquire_nvm_generic - Generic request for access to EEPROM ++ * @hw: pointer to the HW structure ++ * ++ * Set the EEPROM access request bit and wait for EEPROM access grant bit. ++ * Return successful if access grant bit set, else clear the request for ++ * EEPROM access and return -E1000_ERR_NVM (-1). ++ **/ ++s32 e1000_acquire_nvm_generic(struct e1000_hw *hw) ++{ ++ u32 eecd = E1000_READ_REG(hw, E1000_EECD); ++ s32 timeout = E1000_NVM_GRANT_ATTEMPTS; ++ s32 ret_val = E1000_SUCCESS; + -+*******************************************************************************/ ++ DEBUGFUNC("e1000_acquire_nvm_generic"); + -+#include "e1000_api.h" ++ E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_REQ); ++ eecd = E1000_READ_REG(hw, E1000_EECD); + -+static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw); -+/* Cable length tables */ -+static const u16 e1000_m88_cable_length_table[] = -+ { 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED }; -+#define M88E1000_CABLE_LENGTH_TABLE_SIZE \ -+ (sizeof(e1000_m88_cable_length_table) / \ -+ sizeof(e1000_m88_cable_length_table[0])) ++ while (timeout) { ++ if (eecd & E1000_EECD_GNT) ++ break; ++ usec_delay(5); ++ eecd = E1000_READ_REG(hw, E1000_EECD); ++ timeout--; ++ } + -+static const u16 e1000_igp_2_cable_length_table[] = -+ { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, -+ 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, -+ 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, -+ 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, -+ 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, -+ 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, -+ 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124, -+ 104, 109, 114, 118, 121, 124}; -+#define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \ -+ (sizeof(e1000_igp_2_cable_length_table) / \ -+ sizeof(e1000_igp_2_cable_length_table[0])) ++ if (!timeout) { ++ eecd &= ~E1000_EECD_REQ; ++ E1000_WRITE_REG(hw, E1000_EECD, eecd); ++ DEBUGOUT("Could not acquire NVM grant\n"); ++ ret_val = -E1000_ERR_NVM; ++ } ++ ++ return ret_val; ++} + +/** -+ * e1000_check_reset_block_generic - Check if PHY reset is blocked ++ * e1000_standby_nvm - Return EEPROM to standby state + * @hw: pointer to the HW structure + * -+ * Read the PHY management control register and check whether a PHY reset -+ * is blocked. If a reset is not blocked return E1000_SUCCESS, otherwise -+ * return E1000_BLK_PHY_RESET (12). ++ * Return the EEPROM to a standby state. + **/ -+s32 e1000_check_reset_block_generic(struct e1000_hw *hw) ++static void e1000_standby_nvm(struct e1000_hw *hw) +{ -+ u32 manc; -+ -+ DEBUGFUNC("e1000_check_reset_block"); ++ struct e1000_nvm_info *nvm = &hw->nvm; ++ u32 eecd = E1000_READ_REG(hw, E1000_EECD); + -+ manc = E1000_READ_REG(hw, E1000_MANC); ++ DEBUGFUNC("e1000_standby_nvm"); + -+ return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? -+ E1000_BLK_PHY_RESET : E1000_SUCCESS; ++ if (nvm->type == e1000_nvm_eeprom_spi) { ++ /* Toggle CS to flush commands */ ++ eecd |= E1000_EECD_CS; ++ E1000_WRITE_REG(hw, E1000_EECD, eecd); ++ E1000_WRITE_FLUSH(hw); ++ usec_delay(nvm->delay_usec); ++ eecd &= ~E1000_EECD_CS; ++ E1000_WRITE_REG(hw, E1000_EECD, eecd); ++ E1000_WRITE_FLUSH(hw); ++ usec_delay(nvm->delay_usec); ++ } +} + +/** -+ * e1000_get_phy_id - Retrieve the PHY ID and revision ++ * e1000_stop_nvm - Terminate EEPROM command + * @hw: pointer to the HW structure + * -+ * Reads the PHY registers and stores the PHY ID and possibly the PHY -+ * revision in the hardware structure. ++ * Terminates the current command by inverting the EEPROM's chip select pin. + **/ -+s32 e1000_get_phy_id(struct e1000_hw *hw) ++static void e1000_stop_nvm(struct e1000_hw *hw) +{ -+ struct e1000_phy_info *phy = &hw->phy; -+ s32 ret_val = E1000_SUCCESS; -+ u16 phy_id; ++ u32 eecd; + -+ DEBUGFUNC("e1000_get_phy_id"); ++ DEBUGFUNC("e1000_stop_nvm"); + -+ if (!(phy->ops.read_reg)) -+ goto out; ++ eecd = E1000_READ_REG(hw, E1000_EECD); ++ if (hw->nvm.type == e1000_nvm_eeprom_spi) { ++ /* Pull CS high */ ++ eecd |= E1000_EECD_CS; ++ e1000_lower_eec_clk(hw, &eecd); ++ } ++} + -+ ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); -+ if (ret_val) -+ goto out; ++/** ++ * e1000_release_nvm_generic - Release exclusive access to EEPROM ++ * @hw: pointer to the HW structure ++ * ++ * Stop any current commands to the EEPROM and clear the EEPROM request bit. ++ **/ ++void e1000_release_nvm_generic(struct e1000_hw *hw) ++{ ++ u32 eecd; + -+ phy->id = (u32)(phy_id << 16); -+ usec_delay(20); -+ ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id); -+ if (ret_val) -+ goto out; ++ DEBUGFUNC("e1000_release_nvm_generic"); + -+ phy->id |= (u32)(phy_id & PHY_REVISION_MASK); -+ phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); ++ e1000_stop_nvm(hw); + -+out: -+ return ret_val; ++ eecd = E1000_READ_REG(hw, E1000_EECD); ++ eecd &= ~E1000_EECD_REQ; ++ E1000_WRITE_REG(hw, E1000_EECD, eecd); +} + +/** -+ * e1000_phy_reset_dsp_generic - Reset PHY DSP ++ * e1000_ready_nvm_eeprom - Prepares EEPROM for read/write + * @hw: pointer to the HW structure + * -+ * Reset the digital signal processor. ++ * Setups the EEPROM for reading and writing. + **/ -+s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw) ++static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw) +{ ++ struct e1000_nvm_info *nvm = &hw->nvm; ++ u32 eecd = E1000_READ_REG(hw, E1000_EECD); + s32 ret_val = E1000_SUCCESS; ++ u16 timeout = 0; ++ u8 spi_stat_reg; + -+ DEBUGFUNC("e1000_phy_reset_dsp_generic"); ++ DEBUGFUNC("e1000_ready_nvm_eeprom"); + -+ if (!(hw->phy.ops.write_reg)) -+ goto out; ++ if (nvm->type == e1000_nvm_eeprom_spi) { ++ /* Clear SK and CS */ ++ eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); ++ E1000_WRITE_REG(hw, E1000_EECD, eecd); ++ usec_delay(1); ++ timeout = NVM_MAX_RETRY_SPI; + -+ ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); -+ if (ret_val) -+ goto out; ++ /* ++ * Read "Status Register" repeatedly until the LSB is cleared. ++ * The EEPROM will signal that the command has been completed ++ * by clearing bit 0 of the internal status register. If it's ++ * not cleared within 'timeout', then error out. ++ */ ++ while (timeout) { ++ e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI, ++ hw->nvm.opcode_bits); ++ spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8); ++ if (!(spi_stat_reg & NVM_STATUS_RDY_SPI)) ++ break; + -+ ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0); ++ usec_delay(5); ++ e1000_standby_nvm(hw); ++ timeout--; ++ } ++ ++ if (!timeout) { ++ DEBUGOUT("SPI NVM Status error\n"); ++ ret_val = -E1000_ERR_NVM; ++ goto out; ++ } ++ } + +out: + return ret_val; +} + +/** -+ * e1000_read_phy_reg_mdic - Read MDI control register ++ * e1000_read_nvm_eerd - Reads EEPROM using EERD register + * @hw: pointer to the HW structure -+ * @offset: register offset to be read -+ * @data: pointer to the read data ++ * @offset: offset of word in the EEPROM to read ++ * @words: number of words to read ++ * @data: word read from the EEPROM + * -+ * Reads the MDI control register in the PHY at offset and stores the -+ * information read to data. ++ * Reads a 16 bit word from the EEPROM using the EERD register. + **/ -+s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) ++s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) +{ -+ struct e1000_phy_info *phy = &hw->phy; -+ u32 i, mdic = 0; ++ struct e1000_nvm_info *nvm = &hw->nvm; ++ u32 i, eerd = 0; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_read_phy_reg_mdic"); ++ DEBUGFUNC("e1000_read_nvm_eerd"); + + /* -+ * Set up Op-code, Phy Address, and register offset in the MDI -+ * Control register. The MAC will take care of interfacing with the -+ * PHY to retrieve the desired data. ++ * A check for invalid values: offset too large, too many words, ++ * too many words for the offset, and not enough words. + */ -+ mdic = ((offset << E1000_MDIC_REG_SHIFT) | -+ (phy->addr << E1000_MDIC_PHY_SHIFT) | -+ (E1000_MDIC_OP_READ)); ++ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || ++ (words == 0)) { ++ DEBUGOUT("nvm parameter(s) out of bounds\n"); ++ ret_val = -E1000_ERR_NVM; ++ goto out; ++ } + -+ E1000_WRITE_REG(hw, E1000_MDIC, mdic); ++ for (i = 0; i < words; i++) { ++ eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) + ++ E1000_NVM_RW_REG_START; + -+ /* -+ * Poll the ready bit to see if the MDI read completed -+ * Increasing the time out as testing showed failures with -+ * the lower time out -+ */ -+ for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { -+ usec_delay(50); -+ mdic = E1000_READ_REG(hw, E1000_MDIC); -+ if (mdic & E1000_MDIC_READY) ++ E1000_WRITE_REG(hw, E1000_EERD, eerd); ++ ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); ++ if (ret_val) + break; ++ ++ data[i] = (E1000_READ_REG(hw, E1000_EERD) >> ++ E1000_NVM_RW_REG_DATA); + } -+ if (!(mdic & E1000_MDIC_READY)) { -+ DEBUGOUT("MDI Read did not complete\n"); -+ ret_val = -E1000_ERR_PHY; -+ goto out; -+ } -+ if (mdic & E1000_MDIC_ERROR) { -+ DEBUGOUT("MDI Error\n"); -+ ret_val = -E1000_ERR_PHY; -+ goto out; -+ } -+ *data = (u16) mdic; + +out: + return ret_val; +} + +/** -+ * e1000_write_phy_reg_mdic - Write MDI control register ++ * e1000_write_nvm_spi - Write to EEPROM using SPI + * @hw: pointer to the HW structure -+ * @offset: register offset to write to -+ * @data: data to write to register at offset ++ * @offset: offset within the EEPROM to be written to ++ * @words: number of words to write ++ * @data: 16 bit word(s) to be written to the EEPROM + * -+ * Writes data to MDI control register in the PHY at offset. ++ * Writes data to EEPROM at offset using SPI interface. ++ * ++ * If e1000_update_nvm_checksum is not called after this function , the ++ * EEPROM will most likely contain an invalid checksum. + **/ -+s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) ++s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) +{ -+ struct e1000_phy_info *phy = &hw->phy; -+ u32 i, mdic = 0; -+ s32 ret_val = E1000_SUCCESS; -+ -+ DEBUGFUNC("e1000_write_phy_reg_mdic"); -+ -+ /* -+ * Set up Op-code, Phy Address, and register offset in the MDI -+ * Control register. The MAC will take care of interfacing with the -+ * PHY to retrieve the desired data. -+ */ -+ mdic = (((u32)data) | -+ (offset << E1000_MDIC_REG_SHIFT) | -+ (phy->addr << E1000_MDIC_PHY_SHIFT) | -+ (E1000_MDIC_OP_WRITE)); ++ struct e1000_nvm_info *nvm = &hw->nvm; ++ s32 ret_val; ++ u16 widx = 0; + -+ E1000_WRITE_REG(hw, E1000_MDIC, mdic); ++ DEBUGFUNC("e1000_write_nvm_spi"); + + /* -+ * Poll the ready bit to see if the MDI read completed -+ * Increasing the time out as testing showed failures with -+ * the lower time out ++ * A check for invalid values: offset too large, too many words, ++ * and not enough words. + */ -+ for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { -+ usec_delay(50); -+ mdic = E1000_READ_REG(hw, E1000_MDIC); -+ if (mdic & E1000_MDIC_READY) -+ break; -+ } -+ if (!(mdic & E1000_MDIC_READY)) { -+ DEBUGOUT("MDI Write did not complete\n"); -+ ret_val = -E1000_ERR_PHY; ++ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || ++ (words == 0)) { ++ DEBUGOUT("nvm parameter(s) out of bounds\n"); ++ ret_val = -E1000_ERR_NVM; + goto out; + } -+ if (mdic & E1000_MDIC_ERROR) { -+ DEBUGOUT("MDI Error\n"); -+ ret_val = -E1000_ERR_PHY; ++ ++ ret_val = nvm->ops.acquire(hw); ++ if (ret_val) + goto out; ++ ++ while (widx < words) { ++ u8 write_opcode = NVM_WRITE_OPCODE_SPI; ++ ++ ret_val = e1000_ready_nvm_eeprom(hw); ++ if (ret_val) ++ goto release; ++ ++ e1000_standby_nvm(hw); ++ ++ /* Send the WRITE ENABLE command (8 bit opcode) */ ++ e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI, ++ nvm->opcode_bits); ++ ++ e1000_standby_nvm(hw); ++ ++ /* ++ * Some SPI eeproms use the 8th address bit embedded in the ++ * opcode ++ */ ++ if ((nvm->address_bits == 8) && (offset >= 128)) ++ write_opcode |= NVM_A8_OPCODE_SPI; ++ ++ /* Send the Write command (8-bit opcode + addr) */ ++ e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits); ++ e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2), ++ nvm->address_bits); ++ ++ /* Loop to allow for up to whole page write of eeprom */ ++ while (widx < words) { ++ u16 word_out = data[widx]; ++ word_out = (word_out >> 8) | (word_out << 8); ++ e1000_shift_out_eec_bits(hw, word_out, 16); ++ widx++; ++ ++ if ((((offset + widx) * 2) % nvm->page_size) == 0) { ++ e1000_standby_nvm(hw); ++ break; ++ } ++ } + } + ++ msec_delay(10); ++release: ++ nvm->ops.release(hw); ++ +out: + return ret_val; +} + +/** -+ * e1000_read_phy_reg_m88 - Read m88 PHY register ++ * e1000_read_pba_num_generic - Read device part number + * @hw: pointer to the HW structure -+ * @offset: register offset to be read -+ * @data: pointer to the read data ++ * @pba_num: pointer to device part number + * -+ * Acquires semaphore, if necessary, then reads the PHY register at offset -+ * and storing the retrieved information in data. Release any acquired -+ * semaphores before exiting. ++ * Reads the product board assembly (PBA) number from the EEPROM and stores ++ * the value in pba_num. + **/ -+s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data) ++s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num) +{ -+ s32 ret_val = E1000_SUCCESS; ++ s32 ret_val; ++ u16 nvm_data; + -+ DEBUGFUNC("e1000_read_phy_reg_m88"); ++ DEBUGFUNC("e1000_read_pba_num_generic"); + -+ if (!(hw->phy.ops.acquire)) ++ ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); ++ if (ret_val) { ++ DEBUGOUT("NVM Read Error\n"); + goto out; ++ } ++ *pba_num = (u32)(nvm_data << 16); + -+ ret_val = hw->phy.ops.acquire(hw); -+ if (ret_val) ++ ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data); ++ if (ret_val) { ++ DEBUGOUT("NVM Read Error\n"); + goto out; -+ -+ ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, -+ data); -+ -+ hw->phy.ops.release(hw); ++ } ++ *pba_num |= nvm_data; + +out: + return ret_val; +} + +/** -+ * e1000_write_phy_reg_m88 - Write m88 PHY register ++ * e1000_read_mac_addr_generic - Read device MAC address + * @hw: pointer to the HW structure -+ * @offset: register offset to write to -+ * @data: data to write at register offset + * -+ * Acquires semaphore, if necessary, then writes the data to PHY register -+ * at the offset. Release any acquired semaphores before exiting. ++ * Reads the device MAC address from the EEPROM and stores the value. ++ * Since devices with two ports use the same EEPROM, we increment the ++ * last bit in the MAC address for the second port. + **/ -+s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) ++s32 e1000_read_mac_addr_generic(struct e1000_hw *hw) +{ -+ s32 ret_val = E1000_SUCCESS; -+ -+ DEBUGFUNC("e1000_write_phy_reg_m88"); ++ u32 rar_high; ++ u32 rar_low; ++ u16 i; + -+ if (!(hw->phy.ops.acquire)) -+ goto out; ++ rar_high = E1000_READ_REG(hw, E1000_RAH(0)); ++ rar_low = E1000_READ_REG(hw, E1000_RAL(0)); + -+ ret_val = hw->phy.ops.acquire(hw); -+ if (ret_val) -+ goto out; ++ for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++) ++ hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8)); + -+ ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, -+ data); ++ for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++) ++ hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8)); + -+ hw->phy.ops.release(hw); ++ for (i = 0; i < ETH_ADDR_LEN; i++) ++ hw->mac.addr[i] = hw->mac.perm_addr[i]; + -+out: -+ return ret_val; ++ return E1000_SUCCESS; +} + +/** -+ * e1000_read_phy_reg_igp - Read igp PHY register ++ * e1000_validate_nvm_checksum_generic - Validate EEPROM checksum + * @hw: pointer to the HW structure -+ * @offset: register offset to be read -+ * @data: pointer to the read data + * -+ * Acquires semaphore, if necessary, then reads the PHY register at offset -+ * and storing the retrieved information in data. Release any acquired -+ * semaphores before exiting. ++ * Calculates the EEPROM checksum by reading/adding each word of the EEPROM ++ * and then verifies that the sum of the EEPROM is equal to 0xBABA. + **/ -+s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) ++s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; ++ u16 checksum = 0; ++ u16 i, nvm_data; + -+ DEBUGFUNC("e1000_read_phy_reg_igp"); -+ -+ if (!(hw->phy.ops.acquire)) -+ goto out; -+ -+ ret_val = hw->phy.ops.acquire(hw); -+ if (ret_val) -+ goto out; ++ DEBUGFUNC("e1000_validate_nvm_checksum_generic"); + -+ if (offset > MAX_PHY_MULTI_PAGE_REG) { -+ ret_val = e1000_write_phy_reg_mdic(hw, -+ IGP01E1000_PHY_PAGE_SELECT, -+ (u16)offset); ++ for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { ++ ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); + if (ret_val) { -+ hw->phy.ops.release(hw); ++ DEBUGOUT("NVM Read Error\n"); + goto out; + } ++ checksum += nvm_data; + } + -+ ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, -+ data); -+ -+ hw->phy.ops.release(hw); ++ if (checksum != (u16) NVM_SUM) { ++ DEBUGOUT("NVM Checksum Invalid\n"); ++ ret_val = -E1000_ERR_NVM; ++ goto out; ++ } + +out: + return ret_val; +} + +/** -+ * e1000_write_phy_reg_igp - Write igp PHY register ++ * e1000_update_nvm_checksum_generic - Update EEPROM checksum + * @hw: pointer to the HW structure -+ * @offset: register offset to write to -+ * @data: data to write at register offset + * -+ * Acquires semaphore, if necessary, then writes the data to PHY register -+ * at the offset. Release any acquired semaphores before exiting. ++ * Updates the EEPROM checksum by reading/adding each word of the EEPROM ++ * up to the checksum. Then calculates the EEPROM checksum and writes the ++ * value to the EEPROM. + **/ -+s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) ++s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw) +{ -+ s32 ret_val = E1000_SUCCESS; -+ -+ DEBUGFUNC("e1000_write_phy_reg_igp"); -+ -+ if (!(hw->phy.ops.acquire)) -+ goto out; ++ s32 ret_val; ++ u16 checksum = 0; ++ u16 i, nvm_data; + -+ ret_val = hw->phy.ops.acquire(hw); -+ if (ret_val) -+ goto out; ++ DEBUGFUNC("e1000_update_nvm_checksum"); + -+ if (offset > MAX_PHY_MULTI_PAGE_REG) { -+ ret_val = e1000_write_phy_reg_mdic(hw, -+ IGP01E1000_PHY_PAGE_SELECT, -+ (u16)offset); ++ for (i = 0; i < NVM_CHECKSUM_REG; i++) { ++ ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); + if (ret_val) { -+ hw->phy.ops.release(hw); ++ DEBUGOUT("NVM Read Error while updating checksum.\n"); + goto out; + } ++ checksum += nvm_data; + } -+ -+ ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, -+ data); -+ -+ hw->phy.ops.release(hw); ++ checksum = (u16) NVM_SUM - checksum; ++ ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum); ++ if (ret_val) ++ DEBUGOUT("NVM Write Error while updating checksum.\n"); + +out: + return ret_val; +} + +/** -+ * e1000_read_kmrn_reg_generic - Read kumeran register ++ * e1000_reload_nvm_generic - Reloads EEPROM + * @hw: pointer to the HW structure -+ * @offset: register offset to be read -+ * @data: pointer to the read data + * -+ * Acquires semaphore, if necessary. Then reads the PHY register at offset -+ * using the kumeran interface. The information retrieved is stored in data. -+ * Release any acquired semaphores before exiting. ++ * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the ++ * extended control register. + **/ -+s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data) ++static void e1000_reload_nvm_generic(struct e1000_hw *hw) +{ -+ u32 kmrnctrlsta; -+ s32 ret_val = E1000_SUCCESS; ++ u32 ctrl_ext; + -+ DEBUGFUNC("e1000_read_kmrn_reg_generic"); ++ DEBUGFUNC("e1000_reload_nvm_generic"); + -+ if (!(hw->phy.ops.acquire)) -+ goto out; ++ usec_delay(10); ++ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ++ ctrl_ext |= E1000_CTRL_EXT_EE_RST; ++ E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); ++ E1000_WRITE_FLUSH(hw); ++} + -+ ret_val = hw->phy.ops.acquire(hw); -+ if (ret_val) -+ goto out; +Index: linux-2.6.22/drivers/net/igb/e1000_nvm.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/e1000_nvm.h 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,50 @@ ++/******************************************************************************* + -+ kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & -+ E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; -+ E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); ++ Intel(R) Gigabit Ethernet Linux driver ++ Copyright(c) 2007-2009 Intel Corporation. + -+ usec_delay(2); ++ 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. + -+ kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA); -+ *data = (u16)kmrnctrlsta; ++ 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. + -+ hw->phy.ops.release(hw); ++ 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. + -+out: -+ return ret_val; -+} ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". + -+/** -+ * e1000_write_kmrn_reg_generic - Write kumeran register -+ * @hw: pointer to the HW structure -+ * @offset: register offset to write to -+ * @data: data to write at register offset -+ * -+ * Acquires semaphore, if necessary. Then write the data to PHY register -+ * at the offset using the kumeran interface. Release any acquired semaphores -+ * before exiting. -+ **/ -+s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data) -+{ -+ u32 kmrnctrlsta; -+ s32 ret_val = E1000_SUCCESS; ++ Contact Information: ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + -+ DEBUGFUNC("e1000_write_kmrn_reg_generic"); ++*******************************************************************************/ + -+ if (!(hw->phy.ops.acquire)) -+ goto out; ++#ifndef _E1000_NVM_H_ ++#define _E1000_NVM_H_ + -+ ret_val = hw->phy.ops.acquire(hw); -+ if (ret_val) -+ goto out; ++void e1000_init_nvm_ops_generic(struct e1000_hw *hw); ++s32 e1000_acquire_nvm_generic(struct e1000_hw *hw); + -+ kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & -+ E1000_KMRNCTRLSTA_OFFSET) | data; -+ E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); ++s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg); ++s32 e1000_read_mac_addr_generic(struct e1000_hw *hw); ++s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num); ++s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, ++ u16 *data); ++s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data); ++s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw); ++s32 e1000_write_nvm_eewr(struct e1000_hw *hw, u16 offset, ++ u16 words, u16 *data); ++s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, ++ u16 *data); ++s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw); ++void e1000_release_nvm_generic(struct e1000_hw *hw); + -+ usec_delay(2); -+ hw->phy.ops.release(hw); ++#define E1000_STM_OPCODE 0xDB00 + -+out: -+ return ret_val; -+} ++#endif +Index: linux-2.6.22/drivers/net/igb/e1000_osdep.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/e1000_osdep.h 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,122 @@ ++/******************************************************************************* + -+/** -+ * e1000_copper_link_setup_m88 - Setup m88 PHY's for copper link -+ * @hw: pointer to the HW structure -+ * -+ * Sets up MDI/MDI-X and polarity for m88 PHY's. If necessary, transmit clock -+ * and downshift values are set also. -+ **/ -+s32 e1000_copper_link_setup_m88(struct e1000_hw *hw) -+{ -+ struct e1000_phy_info *phy = &hw->phy; -+ s32 ret_val; -+ u16 phy_data; ++ Intel(R) Gigabit Ethernet Linux driver ++ Copyright(c) 2007-2009 Intel Corporation. + -+ DEBUGFUNC("e1000_copper_link_setup_m88"); ++ 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. + -+ if (phy->reset_disable) { -+ ret_val = E1000_SUCCESS; -+ goto out; -+ } ++ 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. + -+ /* Enable CRS on TX. This must be set for half-duplex operation. */ -+ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); -+ if (ret_val) -+ goto out; ++ 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. + -+ phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". + -+ /* -+ * Options: -+ * MDI/MDI-X = 0 (default) -+ * 0 - Auto for all speeds -+ * 1 - MDI mode -+ * 2 - MDI-X mode -+ * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) -+ */ -+ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; ++ Contact Information: ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + -+ switch (phy->mdix) { -+ case 1: -+ phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; -+ break; -+ case 2: -+ phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; -+ break; -+ case 3: -+ phy_data |= M88E1000_PSCR_AUTO_X_1000T; -+ break; -+ case 0: -+ default: -+ phy_data |= M88E1000_PSCR_AUTO_X_MODE; -+ break; -+ } ++*******************************************************************************/ + -+ /* -+ * Options: -+ * disable_polarity_correction = 0 (default) -+ * Automatic Correction for Reversed Cable Polarity -+ * 0 - Disabled -+ * 1 - Enabled -+ */ -+ phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; -+ if (phy->disable_polarity_correction == 1) -+ phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; + -+ ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); -+ if (ret_val) -+ goto out; ++/* glue for the OS independent part of e1000 ++ * includes register access macros ++ */ + -+ if (phy->revision < E1000_REVISION_4) { -+ /* -+ * Force TX_CLK in the Extended PHY Specific Control Register -+ * to 25MHz clock. -+ */ -+ ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, -+ &phy_data); -+ if (ret_val) -+ goto out; ++#ifndef _E1000_OSDEP_H_ ++#define _E1000_OSDEP_H_ + -+ phy_data |= M88E1000_EPSCR_TX_CLK_25; ++#include ++#include ++#include ++#include ++#include ++#include "kcompat.h" + -+ if ((phy->revision == E1000_REVISION_2) && -+ (phy->id == M88E1111_I_PHY_ID)) { -+ /* 82573L PHY - set the downshift counter to 5x. */ -+ phy_data &= ~M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK; -+ phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X; -+ } else { -+ /* Configure Master and Slave downshift values */ -+ phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | -+ M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); -+ phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | -+ M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); -+ } -+ ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, -+ phy_data); -+ if (ret_val) -+ goto out; -+ } ++#define usec_delay(x) udelay(x) ++#ifndef msec_delay ++#define msec_delay(x) do { \ ++ /* Don't mdelay in interrupt context! */ \ ++ if (in_interrupt()) \ ++ BUG(); \ ++ else \ ++ msleep(x); \ ++} while (0) + -+ /* Commit the changes. */ -+ ret_val = phy->ops.commit(hw); -+ if (ret_val) { -+ DEBUGOUT("Error committing the PHY changes\n"); -+ goto out; -+ } ++/* Some workarounds require millisecond delays and are run during interrupt ++ * context. Most notably, when establishing link, the phy may need tweaking ++ * but cannot process phy register reads/writes faster than millisecond ++ * intervals...and we establish link due to a "link status change" interrupt. ++ */ ++#define msec_delay_irq(x) mdelay(x) ++#endif + -+out: -+ return ret_val; -+} ++#define PCI_COMMAND_REGISTER PCI_COMMAND ++#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE ++#define ETH_ADDR_LEN ETH_ALEN + -+/** -+ * e1000_copper_link_setup_igp - Setup igp PHY's for copper link -+ * @hw: pointer to the HW structure -+ * -+ * Sets up LPLU, MDI/MDI-X, polarity, Smartspeed and Master/Slave config for -+ * igp PHY's. -+ **/ -+s32 e1000_copper_link_setup_igp(struct e1000_hw *hw) -+{ -+ struct e1000_phy_info *phy = &hw->phy; -+ s32 ret_val; -+ u16 data; ++#ifdef __BIG_ENDIAN ++#define E1000_BIG_ENDIAN __BIG_ENDIAN ++#endif + -+ DEBUGFUNC("e1000_copper_link_setup_igp"); + -+ if (phy->reset_disable) { -+ ret_val = E1000_SUCCESS; -+ goto out; -+ } ++#define DEBUGOUT(S) ++#define DEBUGOUT1(S, A...) + -+ ret_val = hw->phy.ops.reset(hw); -+ if (ret_val) { -+ DEBUGOUT("Error resetting the PHY.\n"); -+ goto out; -+ } ++#define DEBUGFUNC(F) DEBUGOUT(F "\n") ++#define DEBUGOUT2 DEBUGOUT1 ++#define DEBUGOUT3 DEBUGOUT2 ++#define DEBUGOUT7 DEBUGOUT3 + -+ /* -+ * Wait 100ms for MAC to configure PHY from NVM settings, to avoid -+ * timeout issues when LFS is enabled. -+ */ -+ msec_delay(100); ++#define E1000_REGISTER(a, reg) reg + -+ /* -+ * The NVM settings will configure LPLU in D3 for -+ * non-IGP1 PHYs. -+ */ -+ if (phy->type == e1000_phy_igp) { -+ /* disable lplu d3 during driver init */ -+ ret_val = hw->phy.ops.set_d3_lplu_state(hw, false); -+ if (ret_val) { -+ DEBUGOUT("Error Disabling LPLU D3\n"); -+ goto out; -+ } -+ } ++#define E1000_WRITE_REG(a, reg, value) ( \ ++ writel((value), ((a)->hw_addr + E1000_REGISTER(a, reg)))) + -+ /* disable lplu d0 during driver init */ -+ if (hw->phy.ops.set_d0_lplu_state) { -+ ret_val = hw->phy.ops.set_d0_lplu_state(hw, false); -+ if (ret_val) { -+ DEBUGOUT("Error Disabling LPLU D0\n"); -+ goto out; -+ } -+ } -+ /* Configure mdi-mdix settings */ -+ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data); -+ if (ret_val) -+ goto out; ++#define E1000_READ_REG(a, reg) (readl((a)->hw_addr + E1000_REGISTER(a, reg))) + -+ data &= ~IGP01E1000_PSCR_AUTO_MDIX; ++#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \ ++ writel((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 2)))) + -+ switch (phy->mdix) { -+ case 1: -+ data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; -+ break; -+ case 2: -+ data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; -+ break; -+ case 0: -+ default: -+ data |= IGP01E1000_PSCR_AUTO_MDIX; -+ break; -+ } -+ ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data); -+ if (ret_val) -+ goto out; ++#define E1000_READ_REG_ARRAY(a, reg, offset) ( \ ++ readl((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 2))) + -+ /* set auto-master slave resolution settings */ -+ if (hw->mac.autoneg) { -+ /* -+ * when autonegotiation advertisement is only 1000Mbps then we -+ * should disable SmartSpeed and enable Auto MasterSlave -+ * resolution as hardware default. -+ */ -+ if (phy->autoneg_advertised == ADVERTISE_1000_FULL) { -+ /* Disable SmartSpeed */ -+ ret_val = phy->ops.read_reg(hw, -+ IGP01E1000_PHY_PORT_CONFIG, -+ &data); -+ if (ret_val) -+ goto out; ++#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY ++#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY + -+ data &= ~IGP01E1000_PSCFR_SMART_SPEED; -+ ret_val = phy->ops.write_reg(hw, -+ IGP01E1000_PHY_PORT_CONFIG, -+ data); -+ if (ret_val) -+ goto out; ++#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \ ++ writew((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 1)))) + -+ /* Set auto Master/Slave resolution process */ -+ ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); -+ if (ret_val) -+ goto out; ++#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \ ++ readw((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 1))) + -+ data &= ~CR_1000T_MS_ENABLE; -+ ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); -+ if (ret_val) -+ goto out; -+ } ++#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \ ++ writeb((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + (offset)))) + -+ ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); -+ if (ret_val) -+ goto out; ++#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \ ++ readb((a)->hw_addr + E1000_REGISTER(a, reg) + (offset))) + -+ /* load defaults for future use */ -+ phy->original_ms_type = (data & CR_1000T_MS_ENABLE) ? -+ ((data & CR_1000T_MS_VALUE) ? -+ e1000_ms_force_master : -+ e1000_ms_force_slave) : -+ e1000_ms_auto; ++#define E1000_WRITE_REG_IO(a, reg, offset) do { \ ++ outl(reg, ((a)->io_base)); \ ++ outl(offset, ((a)->io_base + 4)); } while (0) + -+ switch (phy->ms_type) { -+ case e1000_ms_force_master: -+ data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); -+ break; -+ case e1000_ms_force_slave: -+ data |= CR_1000T_MS_ENABLE; -+ data &= ~(CR_1000T_MS_VALUE); -+ break; -+ case e1000_ms_auto: -+ data &= ~CR_1000T_MS_ENABLE; -+ default: -+ break; -+ } -+ ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); -+ if (ret_val) -+ goto out; -+ } ++#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, E1000_STATUS) + -+out: -+ return ret_val; -+} ++#define E1000_WRITE_FLASH_REG(a, reg, value) ( \ ++ writel((value), ((a)->flash_address + reg))) + -+/** -+ * e1000_copper_link_autoneg - Setup/Enable autoneg for copper link -+ * @hw: pointer to the HW structure -+ * -+ * Performs initial bounds checking on autoneg advertisement parameter, then -+ * configure to advertise the full capability. Setup the PHY to autoneg -+ * and restart the negotiation process between the link partner. If -+ * autoneg_wait_to_complete, then wait for autoneg to complete before exiting. -+ **/ -+s32 e1000_copper_link_autoneg(struct e1000_hw *hw) -+{ -+ struct e1000_phy_info *phy = &hw->phy; -+ s32 ret_val; -+ u16 phy_ctrl; ++#define E1000_WRITE_FLASH_REG16(a, reg, value) ( \ ++ writew((value), ((a)->flash_address + reg))) + -+ DEBUGFUNC("e1000_copper_link_autoneg"); ++#define E1000_READ_FLASH_REG(a, reg) (readl((a)->flash_address + reg)) + -+ /* -+ * Perform some bounds checking on the autoneg advertisement -+ * parameter. -+ */ -+ phy->autoneg_advertised &= phy->autoneg_mask; ++#define E1000_READ_FLASH_REG16(a, reg) (readw((a)->flash_address + reg)) + -+ /* -+ * If autoneg_advertised is zero, we assume it was not defaulted -+ * by the calling code so we set to advertise full capability. -+ */ -+ if (phy->autoneg_advertised == 0) -+ phy->autoneg_advertised = phy->autoneg_mask; ++#endif /* _E1000_OSDEP_H_ */ +Index: linux-2.6.22/drivers/net/igb/e1000_phy.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/e1000_phy.c 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,2445 @@ ++/******************************************************************************* + -+ DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); -+ ret_val = e1000_phy_setup_autoneg(hw); -+ if (ret_val) { -+ DEBUGOUT("Error Setting up Auto-Negotiation\n"); -+ goto out; -+ } -+ DEBUGOUT("Restarting Auto-Neg\n"); ++ Intel(R) Gigabit Ethernet Linux driver ++ Copyright(c) 2007-2009 Intel Corporation. + -+ /* -+ * Restart auto-negotiation by setting the Auto Neg Enable bit and -+ * the Auto Neg Restart bit in the PHY control register. -+ */ -+ ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); -+ if (ret_val) -+ goto out; ++ 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. + -+ phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); -+ ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl); -+ if (ret_val) -+ goto out; ++ 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. + -+ /* -+ * Does the user want to wait for Auto-Neg to complete here, or -+ * check at a later time (for example, callback routine). -+ */ -+ if (phy->autoneg_wait_to_complete) { -+ ret_val = hw->mac.ops.wait_autoneg(hw); -+ if (ret_val) { -+ DEBUGOUT("Error while waiting for " -+ "autoneg to complete\n"); -+ goto out; -+ } -+ } ++ 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. + -+ hw->mac.get_link_status = true; ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". + -+out: -+ return ret_val; -+} ++ Contact Information: ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + -+/** -+ * e1000_phy_setup_autoneg - Configure PHY for auto-negotiation -+ * @hw: pointer to the HW structure -+ * -+ * Reads the MII auto-neg advertisement register and/or the 1000T control -+ * register and if the PHY is already setup for auto-negotiation, then -+ * return successful. Otherwise, setup advertisement and flow control to -+ * the appropriate values for the wanted auto-negotiation. -+ **/ -+static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) -+{ -+ struct e1000_phy_info *phy = &hw->phy; -+ s32 ret_val; -+ u16 mii_autoneg_adv_reg; -+ u16 mii_1000t_ctrl_reg = 0; ++*******************************************************************************/ + -+ DEBUGFUNC("e1000_phy_setup_autoneg"); ++#include "e1000_api.h" + -+ phy->autoneg_advertised &= phy->autoneg_mask; ++static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw); ++/* Cable length tables */ ++static const u16 e1000_m88_cable_length_table[] = ++ { 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED }; ++#define M88E1000_CABLE_LENGTH_TABLE_SIZE \ ++ (sizeof(e1000_m88_cable_length_table) / \ ++ sizeof(e1000_m88_cable_length_table[0])) + -+ /* Read the MII Auto-Neg Advertisement Register (Address 4). */ -+ ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); -+ if (ret_val) -+ goto out; -+ -+ if (phy->autoneg_mask & ADVERTISE_1000_FULL) { -+ /* Read the MII 1000Base-T Control Register (Address 9). */ -+ ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, -+ &mii_1000t_ctrl_reg); -+ if (ret_val) -+ goto out; -+ } -+ -+ /* -+ * Need to parse both autoneg_advertised and fc and set up -+ * the appropriate PHY registers. First we will parse for -+ * autoneg_advertised software override. Since we can advertise -+ * a plethora of combinations, we need to check each bit -+ * individually. -+ */ -+ -+ /* -+ * First we clear all the 10/100 mb speed bits in the Auto-Neg -+ * Advertisement Register (Address 4) and the 1000 mb speed bits in -+ * the 1000Base-T Control Register (Address 9). -+ */ -+ mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS | -+ NWAY_AR_100TX_HD_CAPS | -+ NWAY_AR_10T_FD_CAPS | -+ NWAY_AR_10T_HD_CAPS); -+ mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS); -+ -+ DEBUGOUT1("autoneg_advertised %x\n", phy->autoneg_advertised); -+ -+ /* Do we want to advertise 10 Mb Half Duplex? */ -+ if (phy->autoneg_advertised & ADVERTISE_10_HALF) { -+ DEBUGOUT("Advertise 10mb Half duplex\n"); -+ mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; -+ } ++static const u16 e1000_igp_2_cable_length_table[] = ++ { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, ++ 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, ++ 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, ++ 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, ++ 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, ++ 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, ++ 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124, ++ 104, 109, 114, 118, 121, 124}; ++#define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \ ++ (sizeof(e1000_igp_2_cable_length_table) / \ ++ sizeof(e1000_igp_2_cable_length_table[0])) + -+ /* Do we want to advertise 10 Mb Full Duplex? */ -+ if (phy->autoneg_advertised & ADVERTISE_10_FULL) { -+ DEBUGOUT("Advertise 10mb Full duplex\n"); -+ mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; -+ } ++/** ++ * e1000_check_reset_block_generic - Check if PHY reset is blocked ++ * @hw: pointer to the HW structure ++ * ++ * Read the PHY management control register and check whether a PHY reset ++ * is blocked. If a reset is not blocked return E1000_SUCCESS, otherwise ++ * return E1000_BLK_PHY_RESET (12). ++ **/ ++s32 e1000_check_reset_block_generic(struct e1000_hw *hw) ++{ ++ u32 manc; + -+ /* Do we want to advertise 100 Mb Half Duplex? */ -+ if (phy->autoneg_advertised & ADVERTISE_100_HALF) { -+ DEBUGOUT("Advertise 100mb Half duplex\n"); -+ mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; -+ } ++ DEBUGFUNC("e1000_check_reset_block"); + -+ /* Do we want to advertise 100 Mb Full Duplex? */ -+ if (phy->autoneg_advertised & ADVERTISE_100_FULL) { -+ DEBUGOUT("Advertise 100mb Full duplex\n"); -+ mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; -+ } ++ manc = E1000_READ_REG(hw, E1000_MANC); + -+ /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ -+ if (phy->autoneg_advertised & ADVERTISE_1000_HALF) -+ DEBUGOUT("Advertise 1000mb Half duplex request denied!\n"); ++ return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? ++ E1000_BLK_PHY_RESET : E1000_SUCCESS; ++} + -+ /* Do we want to advertise 1000 Mb Full Duplex? */ -+ if (phy->autoneg_advertised & ADVERTISE_1000_FULL) { -+ DEBUGOUT("Advertise 1000mb Full duplex\n"); -+ mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; -+ } ++/** ++ * e1000_get_phy_id - Retrieve the PHY ID and revision ++ * @hw: pointer to the HW structure ++ * ++ * Reads the PHY registers and stores the PHY ID and possibly the PHY ++ * revision in the hardware structure. ++ **/ ++s32 e1000_get_phy_id(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val = E1000_SUCCESS; ++ u16 phy_id; + -+ /* -+ * Check for a software override of the flow control settings, and -+ * setup the PHY advertisement registers accordingly. If -+ * auto-negotiation is enabled, then software will have to set the -+ * "PAUSE" bits to the correct value in the Auto-Negotiation -+ * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto- -+ * negotiation. -+ * -+ * The possible values of the "fc" parameter are: -+ * 0: Flow control is completely disabled -+ * 1: Rx flow control is enabled (we can receive pause frames -+ * but not send pause frames). -+ * 2: Tx flow control is enabled (we can send pause frames -+ * but we do not support receiving pause frames). -+ * 3: Both Rx and Tx flow control (symmetric) are enabled. -+ * other: No software override. The flow control configuration -+ * in the EEPROM is used. -+ */ -+ switch (hw->fc.type) { -+ case e1000_fc_none: -+ /* -+ * Flow control (Rx & Tx) is completely disabled by a -+ * software over-ride. -+ */ -+ mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); -+ break; -+ case e1000_fc_rx_pause: -+ /* -+ * Rx Flow control is enabled, and Tx Flow control is -+ * disabled, by a software over-ride. -+ * -+ * Since there really isn't a way to advertise that we are -+ * capable of Rx Pause ONLY, we will advertise that we -+ * support both symmetric and asymmetric Rx PAUSE. Later -+ * (in e1000_config_fc_after_link_up) we will disable the -+ * hw's ability to send PAUSE frames. -+ */ -+ mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); -+ break; -+ case e1000_fc_tx_pause: -+ /* -+ * Tx Flow control is enabled, and Rx Flow control is -+ * disabled, by a software over-ride. -+ */ -+ mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; -+ mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; -+ break; -+ case e1000_fc_full: -+ /* -+ * Flow control (both Rx and Tx) is enabled by a software -+ * over-ride. -+ */ -+ mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); -+ break; -+ default: -+ DEBUGOUT("Flow control param set incorrectly\n"); -+ ret_val = -E1000_ERR_CONFIG; -+ goto out; -+ } ++ DEBUGFUNC("e1000_get_phy_id"); + -+ ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); -+ if (ret_val) ++ if (!(phy->ops.read_reg)) + goto out; + -+ DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); ++ ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); ++ if (ret_val) ++ goto out; + -+ if (phy->autoneg_mask & ADVERTISE_1000_FULL) { -+ ret_val = phy->ops.write_reg(hw, -+ PHY_1000T_CTRL, -+ mii_1000t_ctrl_reg); ++ phy->id = (u32)(phy_id << 16); ++ usec_delay(20); ++ ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id); + if (ret_val) + goto out; -+ } ++ ++ phy->id |= (u32)(phy_id & PHY_REVISION_MASK); ++ phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); + +out: + return ret_val; +} + +/** -+ * e1000_setup_copper_link_generic - Configure copper link settings ++ * e1000_phy_reset_dsp_generic - Reset PHY DSP + * @hw: pointer to the HW structure + * -+ * Calls the appropriate function to configure the link for auto-neg or forced -+ * speed and duplex. Then we check for link, once link is established calls -+ * to configure collision distance and flow control are called. If link is -+ * not established, we return -E1000_ERR_PHY (-2). ++ * Reset the digital signal processor. + **/ -+s32 e1000_setup_copper_link_generic(struct e1000_hw *hw) ++s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw) +{ -+ s32 ret_val; -+ bool link; ++ s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_setup_copper_link_generic"); ++ DEBUGFUNC("e1000_phy_reset_dsp_generic"); + -+ if (hw->mac.autoneg) { -+ /* -+ * Setup autoneg and flow control advertisement and perform -+ * autonegotiation. -+ */ -+ ret_val = e1000_copper_link_autoneg(hw); -+ if (ret_val) -+ goto out; -+ } else { -+ /* -+ * PHY will be set to 10H, 10F, 100H or 100F -+ * depending on user settings. -+ */ -+ DEBUGOUT("Forcing Speed and Duplex\n"); -+ ret_val = hw->phy.ops.force_speed_duplex(hw); -+ if (ret_val) { -+ DEBUGOUT("Error Forcing Speed and Duplex\n"); -+ goto out; -+ } -+ } ++ if (!(hw->phy.ops.write_reg)) ++ goto out; + -+ /* -+ * Check link status. Wait up to 100 microseconds for link to become -+ * valid. -+ */ -+ ret_val = e1000_phy_has_link_generic(hw, -+ COPPER_LINK_UP_LIMIT, -+ 10, -+ &link); ++ ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); + if (ret_val) + goto out; + -+ if (link) { -+ DEBUGOUT("Valid link established!!!\n"); -+ e1000_config_collision_dist_generic(hw); -+ ret_val = e1000_config_fc_after_link_up_generic(hw); -+ } else { -+ DEBUGOUT("Unable to establish link!!!\n"); -+ } ++ ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0); + +out: + return ret_val; +} + +/** -+ * e1000_phy_force_speed_duplex_igp - Force speed/duplex for igp PHY ++ * e1000_read_phy_reg_mdic - Read MDI control register + * @hw: pointer to the HW structure ++ * @offset: register offset to be read ++ * @data: pointer to the read data + * -+ * Calls the PHY setup function to force speed and duplex. Clears the -+ * auto-crossover to force MDI manually. Waits for link and returns -+ * successful if link up is successful, else -E1000_ERR_PHY (-2). ++ * Reads the MDI control register in the PHY at offset and stores the ++ * information read to data. + **/ -+s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw) ++s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) +{ + struct e1000_phy_info *phy = &hw->phy; -+ s32 ret_val; -+ u16 phy_data; -+ bool link; -+ -+ DEBUGFUNC("e1000_phy_force_speed_duplex_igp"); -+ -+ ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); -+ if (ret_val) -+ goto out; -+ -+ e1000_phy_force_speed_duplex_setup(hw, &phy_data); ++ u32 i, mdic = 0; ++ s32 ret_val = E1000_SUCCESS; + -+ ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); -+ if (ret_val) -+ goto out; ++ DEBUGFUNC("e1000_read_phy_reg_mdic"); + + /* -+ * Clear Auto-Crossover to force MDI manually. IGP requires MDI -+ * forced whenever speed and duplex are forced. ++ * Set up Op-code, Phy Address, and register offset in the MDI ++ * Control register. The MAC will take care of interfacing with the ++ * PHY to retrieve the desired data. + */ -+ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); -+ if (ret_val) -+ goto out; ++ mdic = ((offset << E1000_MDIC_REG_SHIFT) | ++ (phy->addr << E1000_MDIC_PHY_SHIFT) | ++ (E1000_MDIC_OP_READ)); + -+ phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; -+ phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; ++ E1000_WRITE_REG(hw, E1000_MDIC, mdic); + -+ ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); -+ if (ret_val) ++ /* ++ * Poll the ready bit to see if the MDI read completed ++ * Increasing the time out as testing showed failures with ++ * the lower time out ++ */ ++ for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { ++ usec_delay(50); ++ mdic = E1000_READ_REG(hw, E1000_MDIC); ++ if (mdic & E1000_MDIC_READY) ++ break; ++ } ++ if (!(mdic & E1000_MDIC_READY)) { ++ DEBUGOUT("MDI Read did not complete\n"); ++ ret_val = -E1000_ERR_PHY; ++ goto out; ++ } ++ if (mdic & E1000_MDIC_ERROR) { ++ DEBUGOUT("MDI Error\n"); ++ ret_val = -E1000_ERR_PHY; + goto out; -+ -+ DEBUGOUT1("IGP PSCR: %X\n", phy_data); -+ -+ usec_delay(1); -+ -+ if (phy->autoneg_wait_to_complete) { -+ DEBUGOUT("Waiting for forced speed/duplex link on IGP phy.\n"); -+ -+ ret_val = e1000_phy_has_link_generic(hw, -+ PHY_FORCE_LIMIT, -+ 100000, -+ &link); -+ if (ret_val) -+ goto out; -+ -+ if (!link) -+ DEBUGOUT("Link taking longer than expected.\n"); -+ -+ /* Try once more */ -+ ret_val = e1000_phy_has_link_generic(hw, -+ PHY_FORCE_LIMIT, -+ 100000, -+ &link); -+ if (ret_val) -+ goto out; + } ++ *data = (u16) mdic; + +out: + return ret_val; +} + +/** -+ * e1000_phy_force_speed_duplex_m88 - Force speed/duplex for m88 PHY ++ * e1000_write_phy_reg_mdic - Write MDI control register + * @hw: pointer to the HW structure ++ * @offset: register offset to write to ++ * @data: data to write to register at offset + * -+ * Calls the PHY setup function to force speed and duplex. Clears the -+ * auto-crossover to force MDI manually. Resets the PHY to commit the -+ * changes. If time expires while waiting for link up, we reset the DSP. -+ * After reset, TX_CLK and CRS on Tx must be set. Return successful upon -+ * successful completion, else return corresponding error code. ++ * Writes data to MDI control register in the PHY at offset. + **/ -+s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) ++s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) +{ + struct e1000_phy_info *phy = &hw->phy; -+ s32 ret_val; -+ u16 phy_data; -+ bool link; ++ u32 i, mdic = 0; ++ s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_phy_force_speed_duplex_m88"); ++ DEBUGFUNC("e1000_write_phy_reg_mdic"); + + /* -+ * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI -+ * forced whenever speed and duplex are forced. ++ * Set up Op-code, Phy Address, and register offset in the MDI ++ * Control register. The MAC will take care of interfacing with the ++ * PHY to retrieve the desired data. + */ -+ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); -+ if (ret_val) -+ goto out; -+ -+ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; -+ ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); -+ if (ret_val) -+ goto out; -+ -+ DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data); -+ -+ ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); -+ if (ret_val) -+ goto out; -+ -+ e1000_phy_force_speed_duplex_setup(hw, &phy_data); -+ -+ ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); -+ if (ret_val) -+ goto out; -+ -+ /* Reset the phy to commit changes. */ -+ ret_val = hw->phy.ops.commit(hw); -+ if (ret_val) -+ goto out; -+ -+ if (phy->autoneg_wait_to_complete) { -+ DEBUGOUT("Waiting for forced speed/duplex link on M88 phy.\n"); -+ -+ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, -+ 100000, &link); -+ if (ret_val) -+ goto out; -+ -+ if (!link) { -+ /* -+ * We didn't get link. -+ * Reset the DSP and cross our fingers. -+ */ -+ ret_val = phy->ops.write_reg(hw, -+ M88E1000_PHY_PAGE_SELECT, -+ 0x001d); -+ if (ret_val) -+ goto out; -+ ret_val = e1000_phy_reset_dsp_generic(hw); -+ if (ret_val) -+ goto out; -+ } -+ -+ /* Try once more */ -+ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, -+ 100000, &link); -+ if (ret_val) -+ goto out; -+ } ++ mdic = (((u32)data) | ++ (offset << E1000_MDIC_REG_SHIFT) | ++ (phy->addr << E1000_MDIC_PHY_SHIFT) | ++ (E1000_MDIC_OP_WRITE)); + -+ ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); -+ if (ret_val) -+ goto out; ++ E1000_WRITE_REG(hw, E1000_MDIC, mdic); + + /* -+ * Resetting the phy means we need to re-force TX_CLK in the -+ * Extended PHY Specific Control Register to 25MHz clock from -+ * the reset value of 2.5MHz. ++ * Poll the ready bit to see if the MDI read completed ++ * Increasing the time out as testing showed failures with ++ * the lower time out + */ -+ phy_data |= M88E1000_EPSCR_TX_CLK_25; -+ ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); -+ if (ret_val) ++ for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { ++ usec_delay(50); ++ mdic = E1000_READ_REG(hw, E1000_MDIC); ++ if (mdic & E1000_MDIC_READY) ++ break; ++ } ++ if (!(mdic & E1000_MDIC_READY)) { ++ DEBUGOUT("MDI Write did not complete\n"); ++ ret_val = -E1000_ERR_PHY; + goto out; -+ -+ /* -+ * In addition, we must re-enable CRS on Tx for both half and full -+ * duplex. -+ */ -+ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); -+ if (ret_val) ++ } ++ if (mdic & E1000_MDIC_ERROR) { ++ DEBUGOUT("MDI Error\n"); ++ ret_val = -E1000_ERR_PHY; + goto out; -+ -+ phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; -+ ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); ++ } + +out: + return ret_val; +} + +/** -+ * e1000_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex ++ * e1000_read_phy_reg_i2c - Read PHY register using i2c + * @hw: pointer to the HW structure -+ * @phy_ctrl: pointer to current value of PHY_CONTROL ++ * @offset: register offset to be read ++ * @data: pointer to the read data + * -+ * Forces speed and duplex on the PHY by doing the following: disable flow -+ * control, force speed/duplex on the MAC, disable auto speed detection, -+ * disable auto-negotiation, configure duplex, configure speed, configure -+ * the collision distance, write configuration to CTRL register. The -+ * caller must write to the PHY_CONTROL register for these settings to -+ * take affect. ++ * Reads the PHY register at offset using the i2c interface and stores the ++ * retrieved information in data. + **/ -+void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl) ++s32 e1000_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data) +{ -+ struct e1000_mac_info *mac = &hw->mac; -+ u32 ctrl; -+ -+ DEBUGFUNC("e1000_phy_force_speed_duplex_setup"); -+ -+ /* Turn off flow control when forcing speed/duplex */ -+ hw->fc.type = e1000_fc_none; ++ struct e1000_phy_info *phy = &hw->phy; ++ u32 i, i2ccmd = 0; + -+ /* Force speed/duplex on the mac */ -+ ctrl = E1000_READ_REG(hw, E1000_CTRL); -+ ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); -+ ctrl &= ~E1000_CTRL_SPD_SEL; ++ DEBUGFUNC("e1000_read_phy_reg_i2c"); + -+ /* Disable Auto Speed Detection */ -+ ctrl &= ~E1000_CTRL_ASDE; ++ /* ++ * Set up Op-code, Phy Address, and register address in the I2CCMD ++ * register. The MAC will take care of interfacing with the ++ * PHY to retrieve the desired data. ++ */ ++ i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | ++ (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | ++ (E1000_I2CCMD_OPCODE_READ)); + -+ /* Disable autoneg on the phy */ -+ *phy_ctrl &= ~MII_CR_AUTO_NEG_EN; ++ E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); + -+ /* Forcing Full or Half Duplex? */ -+ if (mac->forced_speed_duplex & E1000_ALL_HALF_DUPLEX) { -+ ctrl &= ~E1000_CTRL_FD; -+ *phy_ctrl &= ~MII_CR_FULL_DUPLEX; -+ DEBUGOUT("Half Duplex\n"); -+ } else { -+ ctrl |= E1000_CTRL_FD; -+ *phy_ctrl |= MII_CR_FULL_DUPLEX; -+ DEBUGOUT("Full Duplex\n"); ++ /* Poll the ready bit to see if the I2C read completed */ ++ for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { ++ usec_delay(50); ++ i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD); ++ if (i2ccmd & E1000_I2CCMD_READY) ++ break; + } -+ -+ /* Forcing 10mb or 100mb? */ -+ if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) { -+ ctrl |= E1000_CTRL_SPD_100; -+ *phy_ctrl |= MII_CR_SPEED_100; -+ *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10); -+ DEBUGOUT("Forcing 100mb\n"); -+ } else { -+ ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); -+ *phy_ctrl |= MII_CR_SPEED_10; -+ *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100); -+ DEBUGOUT("Forcing 10mb\n"); ++ if (!(i2ccmd & E1000_I2CCMD_READY)) { ++ DEBUGOUT("I2CCMD Read did not complete\n"); ++ return -E1000_ERR_PHY; ++ } ++ if (i2ccmd & E1000_I2CCMD_ERROR) { ++ DEBUGOUT("I2CCMD Error bit set\n"); ++ return -E1000_ERR_PHY; + } + -+ e1000_config_collision_dist_generic(hw); ++ /* Need to byte-swap the 16-bit value. */ ++ *data = ((i2ccmd >> 8) & 0x00FF) | ((i2ccmd << 8) & 0xFF00); + -+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ++ return E1000_SUCCESS; +} + +/** -+ * e1000_set_d3_lplu_state_generic - Sets low power link up state for D3 ++ * e1000_write_phy_reg_i2c - Write PHY register using i2c + * @hw: pointer to the HW structure -+ * @active: boolean used to enable/disable lplu -+ * -+ * Success returns 0, Failure returns 1 ++ * @offset: register offset to write to ++ * @data: data to write at register offset + * -+ * The low power link up (lplu) state is set to the power management level D3 -+ * and SmartSpeed is disabled when active is true, else clear lplu for D3 -+ * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU -+ * is used during Dx states where the power conservation is most important. -+ * During driver activity, SmartSpeed should be enabled so performance is -+ * maintained. ++ * Writes the data to PHY register at the offset using the i2c interface. + **/ -+s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active) ++s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data) +{ + struct e1000_phy_info *phy = &hw->phy; -+ s32 ret_val = E1000_SUCCESS; -+ u16 data; -+ -+ DEBUGFUNC("e1000_set_d3_lplu_state_generic"); -+ -+ if (!(hw->phy.ops.read_reg)) -+ goto out; -+ -+ ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); -+ if (ret_val) -+ goto out; ++ u32 i, i2ccmd = 0; ++ u16 phy_data_swapped; + -+ if (!active) { -+ data &= ~IGP02E1000_PM_D3_LPLU; -+ ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, -+ data); -+ if (ret_val) -+ goto out; -+ /* -+ * LPLU and SmartSpeed are mutually exclusive. LPLU is used -+ * during Dx states where the power conservation is most -+ * important. During driver activity we should enable -+ * SmartSpeed, so performance is maintained. -+ */ -+ if (phy->smart_speed == e1000_smart_speed_on) { -+ ret_val = phy->ops.read_reg(hw, -+ IGP01E1000_PHY_PORT_CONFIG, -+ &data); -+ if (ret_val) -+ goto out; ++ DEBUGFUNC("e1000_write_phy_reg_i2c"); + -+ data |= IGP01E1000_PSCFR_SMART_SPEED; -+ ret_val = phy->ops.write_reg(hw, -+ IGP01E1000_PHY_PORT_CONFIG, -+ data); -+ if (ret_val) -+ goto out; -+ } else if (phy->smart_speed == e1000_smart_speed_off) { -+ ret_val = phy->ops.read_reg(hw, -+ IGP01E1000_PHY_PORT_CONFIG, -+ &data); -+ if (ret_val) -+ goto out; ++ /* Swap the data bytes for the I2C interface */ ++ phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00); + -+ data &= ~IGP01E1000_PSCFR_SMART_SPEED; -+ ret_val = phy->ops.write_reg(hw, -+ IGP01E1000_PHY_PORT_CONFIG, -+ data); -+ if (ret_val) -+ goto out; -+ } -+ } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || -+ (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || -+ (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { -+ data |= IGP02E1000_PM_D3_LPLU; -+ ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, -+ data); -+ if (ret_val) -+ goto out; ++ /* ++ * Set up Op-code, Phy Address, and register address in the I2CCMD ++ * register. The MAC will take care of interfacing with the ++ * PHY to retrieve the desired data. ++ */ ++ i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | ++ (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | ++ E1000_I2CCMD_OPCODE_WRITE | ++ phy_data_swapped); + -+ /* When LPLU is enabled, we should disable SmartSpeed */ -+ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, -+ &data); -+ if (ret_val) -+ goto out; ++ E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); + -+ data &= ~IGP01E1000_PSCFR_SMART_SPEED; -+ ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, -+ data); ++ /* Poll the ready bit to see if the I2C read completed */ ++ for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { ++ usec_delay(50); ++ i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD); ++ if (i2ccmd & E1000_I2CCMD_READY) ++ break; ++ } ++ if (!(i2ccmd & E1000_I2CCMD_READY)) { ++ DEBUGOUT("I2CCMD Write did not complete\n"); ++ return -E1000_ERR_PHY; ++ } ++ if (i2ccmd & E1000_I2CCMD_ERROR) { ++ DEBUGOUT("I2CCMD Error bit set\n"); ++ return -E1000_ERR_PHY; + } + -+out: -+ return ret_val; ++ return E1000_SUCCESS; +} + +/** -+ * e1000_check_downshift_generic - Checks whether a downshift in speed occurred ++ * e1000_read_phy_reg_m88 - Read m88 PHY register + * @hw: pointer to the HW structure ++ * @offset: register offset to be read ++ * @data: pointer to the read data + * -+ * Success returns 0, Failure returns 1 -+ * -+ * A downshift is detected by querying the PHY link health. ++ * Acquires semaphore, if necessary, then reads the PHY register at offset ++ * and storing the retrieved information in data. Release any acquired ++ * semaphores before exiting. + **/ -+s32 e1000_check_downshift_generic(struct e1000_hw *hw) ++s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data) +{ -+ struct e1000_phy_info *phy = &hw->phy; -+ s32 ret_val; -+ u16 phy_data, offset, mask; ++ s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_check_downshift_generic"); ++ DEBUGFUNC("e1000_read_phy_reg_m88"); + -+ switch (phy->type) { -+ case e1000_phy_m88: -+ case e1000_phy_gg82563: -+ offset = M88E1000_PHY_SPEC_STATUS; -+ mask = M88E1000_PSSR_DOWNSHIFT; -+ break; -+ case e1000_phy_igp_2: -+ case e1000_phy_igp: -+ case e1000_phy_igp_3: -+ offset = IGP01E1000_PHY_LINK_HEALTH; -+ mask = IGP01E1000_PLHR_SS_DOWNGRADE; -+ break; -+ default: -+ /* speed downshift not supported */ -+ phy->speed_downgraded = false; -+ ret_val = E1000_SUCCESS; ++ if (!(hw->phy.ops.acquire)) + goto out; -+ } + -+ ret_val = phy->ops.read_reg(hw, offset, &phy_data); ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) ++ goto out; + -+ if (!ret_val) -+ phy->speed_downgraded = (phy_data & mask) ? true : false; ++ ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, ++ data); ++ ++ hw->phy.ops.release(hw); + +out: + return ret_val; +} + +/** -+ * e1000_check_polarity_m88 - Checks the polarity. ++ * e1000_write_phy_reg_m88 - Write m88 PHY register + * @hw: pointer to the HW structure ++ * @offset: register offset to write to ++ * @data: data to write at register offset + * -+ * Success returns 0, Failure returns -E1000_ERR_PHY (-2) -+ * -+ * Polarity is determined based on the PHY specific status register. ++ * Acquires semaphore, if necessary, then writes the data to PHY register ++ * at the offset. Release any acquired semaphores before exiting. + **/ -+s32 e1000_check_polarity_m88(struct e1000_hw *hw) ++s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) +{ -+ struct e1000_phy_info *phy = &hw->phy; -+ s32 ret_val; -+ u16 data; ++ s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_check_polarity_m88"); ++ DEBUGFUNC("e1000_write_phy_reg_m88"); + -+ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &data); ++ if (!(hw->phy.ops.acquire)) ++ goto out; + -+ if (!ret_val) -+ phy->cable_polarity = (data & M88E1000_PSSR_REV_POLARITY) -+ ? e1000_rev_polarity_reversed -+ : e1000_rev_polarity_normal; ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) ++ goto out; ++ ++ ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, ++ data); ++ ++ hw->phy.ops.release(hw); + ++out: + return ret_val; +} + +/** -+ * e1000_check_polarity_igp - Checks the polarity. ++ * __e1000_read_phy_reg_igp - Read igp PHY register + * @hw: pointer to the HW structure ++ * @offset: register offset to be read ++ * @data: pointer to the read data ++ * @locked: semaphore has already been acquired or not + * -+ * Success returns 0, Failure returns -E1000_ERR_PHY (-2) -+ * -+ * Polarity is determined based on the PHY port status register, and the -+ * current speed (since there is no polarity at 100Mbps). ++ * Acquires semaphore, if necessary, then reads the PHY register at offset ++ * and stores the retrieved information in data. Release any acquired ++ * semaphores before exiting. + **/ -+s32 e1000_check_polarity_igp(struct e1000_hw *hw) ++static s32 __e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data, ++ bool locked) +{ -+ struct e1000_phy_info *phy = &hw->phy; -+ s32 ret_val; -+ u16 data, offset, mask; ++ s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_check_polarity_igp"); ++ DEBUGFUNC("__e1000_read_phy_reg_igp"); + -+ /* -+ * Polarity is determined based on the speed of -+ * our connection. -+ */ -+ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); -+ if (ret_val) -+ goto out; ++ if (!locked) { ++ if (!(hw->phy.ops.acquire)) ++ goto out; + -+ if ((data & IGP01E1000_PSSR_SPEED_MASK) == -+ IGP01E1000_PSSR_SPEED_1000MBPS) { -+ offset = IGP01E1000_PHY_PCS_INIT_REG; -+ mask = IGP01E1000_PHY_POLARITY_MASK; -+ } else { -+ /* -+ * This really only applies to 10Mbps since -+ * there is no polarity for 100Mbps (always 0). -+ */ -+ offset = IGP01E1000_PHY_PORT_STATUS; -+ mask = IGP01E1000_PSSR_POLARITY_REVERSED; ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) ++ goto out; + } + -+ ret_val = phy->ops.read_reg(hw, offset, &data); ++ if (offset > MAX_PHY_MULTI_PAGE_REG) { ++ ret_val = e1000_write_phy_reg_mdic(hw, ++ IGP01E1000_PHY_PAGE_SELECT, ++ (u16)offset); ++ if (ret_val) ++ goto release; ++ } + -+ if (!ret_val) -+ phy->cable_polarity = (data & mask) -+ ? e1000_rev_polarity_reversed -+ : e1000_rev_polarity_normal; ++ ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, ++ data); + ++release: ++ if (!locked) ++ hw->phy.ops.release(hw); +out: + return ret_val; +} ++/** ++ * e1000_read_phy_reg_igp - Read igp PHY register ++ * @hw: pointer to the HW structure ++ * @offset: register offset to be read ++ * @data: pointer to the read data ++ * ++ * Acquires semaphore then reads the PHY register at offset and stores the ++ * retrieved information in data. ++ * Release the acquired semaphore before exiting. ++ **/ ++s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) ++{ ++ return __e1000_read_phy_reg_igp(hw, offset, data, false); ++} + +/** -+ * e1000_wait_autoneg_generic - Wait for auto-neg completion ++ * e1000_read_phy_reg_igp_locked - Read igp PHY register + * @hw: pointer to the HW structure ++ * @offset: register offset to be read ++ * @data: pointer to the read data + * -+ * Waits for auto-negotiation to complete or for the auto-negotiation time -+ * limit to expire, which ever happens first. ++ * Reads the PHY register at offset and stores the retrieved information ++ * in data. Assumes semaphore already acquired. + **/ -+s32 e1000_wait_autoneg_generic(struct e1000_hw *hw) ++s32 e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data) +{ -+ s32 ret_val = E1000_SUCCESS; -+ u16 i, phy_status; ++ return __e1000_read_phy_reg_igp(hw, offset, data, true); ++} + -+ DEBUGFUNC("e1000_wait_autoneg_generic"); ++/** ++ * e1000_write_phy_reg_igp - Write igp PHY register ++ * @hw: pointer to the HW structure ++ * @offset: register offset to write to ++ * @data: data to write at register offset ++ * @locked: semaphore has already been acquired or not ++ * ++ * Acquires semaphore, if necessary, then writes the data to PHY register ++ * at the offset. Release any acquired semaphores before exiting. ++ **/ ++static s32 __e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data, ++ bool locked) ++{ ++ s32 ret_val = E1000_SUCCESS; + -+ if (!(hw->phy.ops.read_reg)) -+ return E1000_SUCCESS; ++ DEBUGFUNC("e1000_write_phy_reg_igp"); + -+ /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */ -+ for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) { -+ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); ++ if (!locked) { ++ if (!(hw->phy.ops.acquire)) ++ goto out; ++ ++ ret_val = hw->phy.ops.acquire(hw); + if (ret_val) -+ break; -+ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); ++ goto out; ++ } ++ ++ if (offset > MAX_PHY_MULTI_PAGE_REG) { ++ ret_val = e1000_write_phy_reg_mdic(hw, ++ IGP01E1000_PHY_PAGE_SELECT, ++ (u16)offset); + if (ret_val) -+ break; -+ if (phy_status & MII_SR_AUTONEG_COMPLETE) -+ break; -+ msec_delay(100); ++ goto release; + } + -+ /* -+ * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation -+ * has completed. -+ */ ++ ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, ++ data); ++ ++release: ++ if (!locked) ++ hw->phy.ops.release(hw); ++ ++out: + return ret_val; +} + +/** -+ * e1000_phy_has_link_generic - Polls PHY for link ++ * e1000_write_phy_reg_igp - Write igp PHY register + * @hw: pointer to the HW structure -+ * @iterations: number of times to poll for link -+ * @usec_interval: delay between polling attempts -+ * @success: pointer to whether polling was successful or not ++ * @offset: register offset to write to ++ * @data: data to write at register offset + * -+ * Polls the PHY status register for link, 'iterations' number of times. ++ * Acquires semaphore then writes the data to PHY register ++ * at the offset. Release any acquired semaphores before exiting. + **/ -+s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, -+ u32 usec_interval, bool *success) ++s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) ++{ ++ return __e1000_write_phy_reg_igp(hw, offset, data, false); ++} ++ ++/** ++ * e1000_write_phy_reg_igp_locked - Write igp PHY register ++ * @hw: pointer to the HW structure ++ * @offset: register offset to write to ++ * @data: data to write at register offset ++ * ++ * Writes the data to PHY register at the offset. ++ * Assumes semaphore already acquired. ++ **/ ++s32 e1000_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data) ++{ ++ return __e1000_write_phy_reg_igp(hw, offset, data, true); ++} ++ ++/** ++ * __e1000_read_kmrn_reg - Read kumeran register ++ * @hw: pointer to the HW structure ++ * @offset: register offset to be read ++ * @data: pointer to the read data ++ * @locked: semaphore has already been acquired or not ++ * ++ * Acquires semaphore, if necessary. Then reads the PHY register at offset ++ * using the kumeran interface. The information retrieved is stored in data. ++ * Release any acquired semaphores before exiting. ++ **/ ++static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data, ++ bool locked) +{ ++ u32 kmrnctrlsta; + s32 ret_val = E1000_SUCCESS; -+ u16 i, phy_status; + -+ DEBUGFUNC("e1000_phy_has_link_generic"); ++ DEBUGFUNC("__e1000_read_kmrn_reg"); + -+ if (!(hw->phy.ops.read_reg)) -+ return E1000_SUCCESS; ++ if (!locked) { ++ if (!(hw->phy.ops.acquire)) ++ goto out; + -+ for (i = 0; i < iterations; i++) { -+ /* -+ * Some PHYs require the PHY_STATUS register to be read -+ * twice due to the link bit being sticky. No harm doing -+ * it across the board. -+ */ -+ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); -+ if (ret_val) -+ break; -+ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); ++ ret_val = hw->phy.ops.acquire(hw); + if (ret_val) -+ break; -+ if (phy_status & MII_SR_LINK_STATUS) -+ break; -+ if (usec_interval >= 1000) -+ msec_delay_irq(usec_interval/1000); -+ else -+ usec_delay(usec_interval); ++ goto out; + } + -+ *success = (i < iterations) ? true : false; ++ kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & ++ E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; ++ E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); ++ ++ usec_delay(2); ++ ++ kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA); ++ *data = (u16)kmrnctrlsta; ++ ++ if (!locked) ++ hw->phy.ops.release(hw); + ++out: + return ret_val; +} + +/** -+ * e1000_get_cable_length_m88 - Determine cable length for m88 PHY ++ * e1000_read_kmrn_reg_generic - Read kumeran register + * @hw: pointer to the HW structure ++ * @offset: register offset to be read ++ * @data: pointer to the read data + * -+ * Reads the PHY specific status register to retrieve the cable length -+ * information. The cable length is determined by averaging the minimum and -+ * maximum values to get the "average" cable length. The m88 PHY has four -+ * possible cable length values, which are: -+ * Register Value Cable Length -+ * 0 < 50 meters -+ * 1 50 - 80 meters -+ * 2 80 - 110 meters -+ * 3 110 - 140 meters -+ * 4 > 140 meters ++ * Acquires semaphore then reads the PHY register at offset using the ++ * kumeran interface. The information retrieved is stored in data. ++ * Release the acquired semaphore before exiting. + **/ -+s32 e1000_get_cable_length_m88(struct e1000_hw *hw) ++s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data) +{ -+ struct e1000_phy_info *phy = &hw->phy; -+ s32 ret_val; -+ u16 phy_data, index; -+ -+ DEBUGFUNC("e1000_get_cable_length_m88"); -+ -+ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); -+ if (ret_val) -+ goto out; -+ -+ index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> -+ M88E1000_PSSR_CABLE_LENGTH_SHIFT; -+ phy->min_cable_length = e1000_m88_cable_length_table[index]; -+ phy->max_cable_length = e1000_m88_cable_length_table[index+1]; -+ -+ phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; ++ return __e1000_read_kmrn_reg(hw, offset, data, false); ++} + -+out: -+ return ret_val; ++/** ++ * e1000_read_kmrn_reg_locked - Read kumeran register ++ * @hw: pointer to the HW structure ++ * @offset: register offset to be read ++ * @data: pointer to the read data ++ * ++ * Reads the PHY register at offset using the kumeran interface. The ++ * information retrieved is stored in data. ++ * Assumes semaphore already acquired. ++ **/ ++s32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data) ++{ ++ return __e1000_read_kmrn_reg(hw, offset, data, true); +} + +/** -+ * e1000_get_cable_length_igp_2 - Determine cable length for igp2 PHY ++ * __e1000_write_kmrn_reg - Write kumeran register + * @hw: pointer to the HW structure ++ * @offset: register offset to write to ++ * @data: data to write at register offset ++ * @locked: semaphore has already been acquired or not + * -+ * The automatic gain control (agc) normalizes the amplitude of the -+ * received signal, adjusting for the attenuation produced by the -+ * cable. By reading the AGC registers, which represent the -+ * combination of coarse and fine gain value, the value can be put -+ * into a lookup table to obtain the approximate cable length -+ * for each channel. ++ * Acquires semaphore, if necessary. Then write the data to PHY register ++ * at the offset using the kumeran interface. Release any acquired semaphores ++ * before exiting. + **/ -+s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw) ++static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data, ++ bool locked) +{ -+ struct e1000_phy_info *phy = &hw->phy; ++ u32 kmrnctrlsta; + s32 ret_val = E1000_SUCCESS; -+ u16 phy_data, i, agc_value = 0; -+ u16 cur_agc_index, max_agc_index = 0; -+ u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1; -+ u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = -+ {IGP02E1000_PHY_AGC_A, -+ IGP02E1000_PHY_AGC_B, -+ IGP02E1000_PHY_AGC_C, -+ IGP02E1000_PHY_AGC_D}; + -+ DEBUGFUNC("e1000_get_cable_length_igp_2"); ++ DEBUGFUNC("e1000_write_kmrn_reg_generic"); + -+ /* Read the AGC registers for all channels */ -+ for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) { -+ ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &phy_data); -+ if (ret_val) ++ if (!locked) { ++ if (!(hw->phy.ops.acquire)) + goto out; + -+ /* -+ * Getting bits 15:9, which represent the combination of -+ * coarse and fine gain values. The result is a number -+ * that can be put into the lookup table to obtain the -+ * approximate cable length. -+ */ -+ cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) & -+ IGP02E1000_AGC_LENGTH_MASK; -+ -+ /* Array index bound check. */ -+ if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) || -+ (cur_agc_index == 0)) { -+ ret_val = -E1000_ERR_PHY; ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) + goto out; -+ } -+ -+ /* Remove min & max AGC values from calculation. */ -+ if (e1000_igp_2_cable_length_table[min_agc_index] > -+ e1000_igp_2_cable_length_table[cur_agc_index]) -+ min_agc_index = cur_agc_index; -+ if (e1000_igp_2_cable_length_table[max_agc_index] < -+ e1000_igp_2_cable_length_table[cur_agc_index]) -+ max_agc_index = cur_agc_index; -+ -+ agc_value += e1000_igp_2_cable_length_table[cur_agc_index]; + } + -+ agc_value -= (e1000_igp_2_cable_length_table[min_agc_index] + -+ e1000_igp_2_cable_length_table[max_agc_index]); -+ agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2); ++ kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & ++ E1000_KMRNCTRLSTA_OFFSET) | data; ++ E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); + -+ /* Calculate cable length with the error range of +/- 10 meters. */ -+ phy->min_cable_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ? -+ (agc_value - IGP02E1000_AGC_RANGE) : 0; -+ phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE; ++ usec_delay(2); + -+ phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; ++ if (!locked) ++ hw->phy.ops.release(hw); + +out: + return ret_val; +} + +/** -+ * e1000_get_phy_info_m88 - Retrieve PHY information ++ * e1000_write_kmrn_reg_generic - Write kumeran register ++ * @hw: pointer to the HW structure ++ * @offset: register offset to write to ++ * @data: data to write at register offset ++ * ++ * Acquires semaphore then writes the data to the PHY register at the offset ++ * using the kumeran interface. Release the acquired semaphore before exiting. ++ **/ ++s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data) ++{ ++ return __e1000_write_kmrn_reg(hw, offset, data, false); ++} ++ ++/** ++ * e1000_write_kmrn_reg_locked - Write kumeran register + * @hw: pointer to the HW structure ++ * @offset: register offset to write to ++ * @data: data to write at register offset + * -+ * Valid for only copper links. Read the PHY status register (sticky read) -+ * to verify that link is up. Read the PHY special control register to -+ * determine the polarity and 10base-T extended distance. Read the PHY -+ * special status register to determine MDI/MDIx and current speed. If -+ * speed is 1000, then determine cable length, local and remote receiver. ++ * Write the data to PHY register at the offset using the kumeran interface. ++ * Assumes semaphore already acquired. + **/ -+s32 e1000_get_phy_info_m88(struct e1000_hw *hw) ++s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data) ++{ ++ return __e1000_write_kmrn_reg(hw, offset, data, true); ++} ++ ++/** ++ * e1000_copper_link_setup_m88 - Setup m88 PHY's for copper link ++ * @hw: pointer to the HW structure ++ * ++ * Sets up MDI/MDI-X and polarity for m88 PHY's. If necessary, transmit clock ++ * and downshift values are set also. ++ **/ ++s32 e1000_copper_link_setup_m88(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; -+ s32 ret_val; ++ s32 ret_val; + u16 phy_data; -+ bool link; + -+ DEBUGFUNC("e1000_get_phy_info_m88"); ++ DEBUGFUNC("e1000_copper_link_setup_m88"); + -+ if (hw->phy.media_type != e1000_media_type_copper) { -+ DEBUGOUT("Phy info is only valid for copper media\n"); -+ ret_val = -E1000_ERR_CONFIG; ++ if (phy->reset_disable) { ++ ret_val = E1000_SUCCESS; + goto out; + } + -+ ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); ++ /* Enable CRS on TX. This must be set for half-duplex operation. */ ++ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + if (ret_val) + goto out; + -+ if (!link) { -+ DEBUGOUT("Phy info is only valid if link is up\n"); -+ ret_val = -E1000_ERR_CONFIG; -+ goto out; -+ } ++ phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; + -+ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); -+ if (ret_val) -+ goto out; ++ /* ++ * Options: ++ * MDI/MDI-X = 0 (default) ++ * 0 - Auto for all speeds ++ * 1 - MDI mode ++ * 2 - MDI-X mode ++ * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) ++ */ ++ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; + -+ phy->polarity_correction = (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) -+ ? true : false; ++ switch (phy->mdix) { ++ case 1: ++ phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; ++ break; ++ case 2: ++ phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; ++ break; ++ case 3: ++ phy_data |= M88E1000_PSCR_AUTO_X_1000T; ++ break; ++ case 0: ++ default: ++ phy_data |= M88E1000_PSCR_AUTO_X_MODE; ++ break; ++ } + -+ ret_val = e1000_check_polarity_m88(hw); -+ if (ret_val) -+ goto out; ++ /* ++ * Options: ++ * disable_polarity_correction = 0 (default) ++ * Automatic Correction for Reversed Cable Polarity ++ * 0 - Disabled ++ * 1 - Enabled ++ */ ++ phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; ++ if (phy->disable_polarity_correction == 1) ++ phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; + -+ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); ++ ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + if (ret_val) + goto out; + -+ phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX) ? true : false; -+ -+ if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { -+ ret_val = hw->phy.ops.get_cable_length(hw); ++ if (phy->revision < E1000_REVISION_4) { ++ /* ++ * Force TX_CLK in the Extended PHY Specific Control Register ++ * to 25MHz clock. ++ */ ++ ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, ++ &phy_data); + if (ret_val) + goto out; + -+ ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); ++ phy_data |= M88E1000_EPSCR_TX_CLK_25; ++ ++ if ((phy->revision == E1000_REVISION_2) && ++ (phy->id == M88E1111_I_PHY_ID)) { ++ /* 82573L PHY - set the downshift counter to 5x. */ ++ phy_data &= ~M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK; ++ phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X; ++ } else { ++ /* Configure Master and Slave downshift values */ ++ phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | ++ M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); ++ phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | ++ M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); ++ } ++ ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, ++ phy_data); + if (ret_val) + goto out; ++ } + -+ phy->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) -+ ? e1000_1000t_rx_status_ok -+ : e1000_1000t_rx_status_not_ok; -+ -+ phy->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) -+ ? e1000_1000t_rx_status_ok -+ : e1000_1000t_rx_status_not_ok; -+ } else { -+ /* Set values to "undefined" */ -+ phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; -+ phy->local_rx = e1000_1000t_rx_status_undefined; -+ phy->remote_rx = e1000_1000t_rx_status_undefined; ++ /* Commit the changes. */ ++ ret_val = phy->ops.commit(hw); ++ if (ret_val) { ++ DEBUGOUT("Error committing the PHY changes\n"); ++ goto out; + } + +out: @@ -13253,66 +10336,141 @@ diff -Nru vanilla/drivers/net/igb/e1000_phy.c linux-i686-2.6.22/drivers/net/igb/ +} + +/** -+ * e1000_get_phy_info_igp - Retrieve igp PHY information ++ * e1000_copper_link_setup_igp - Setup igp PHY's for copper link + * @hw: pointer to the HW structure + * -+ * Read PHY status to determine if link is up. If link is up, then -+ * set/determine 10base-T extended distance and polarity correction. Read -+ * PHY port status to determine MDI/MDIx and speed. Based on the speed, -+ * determine on the cable length, local and remote receiver. ++ * Sets up LPLU, MDI/MDI-X, polarity, Smartspeed and Master/Slave config for ++ * igp PHY's. + **/ -+s32 e1000_get_phy_info_igp(struct e1000_hw *hw) ++s32 e1000_copper_link_setup_igp(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 data; -+ bool link; + -+ DEBUGFUNC("e1000_get_phy_info_igp"); ++ DEBUGFUNC("e1000_copper_link_setup_igp"); + -+ ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); -+ if (ret_val) ++ if (phy->reset_disable) { ++ ret_val = E1000_SUCCESS; + goto out; ++ } + -+ if (!link) { -+ DEBUGOUT("Phy info is only valid if link is up\n"); -+ ret_val = -E1000_ERR_CONFIG; ++ ret_val = hw->phy.ops.reset(hw); ++ if (ret_val) { ++ DEBUGOUT("Error resetting the PHY.\n"); + goto out; + } + -+ phy->polarity_correction = true; ++ /* ++ * Wait 100ms for MAC to configure PHY from NVM settings, to avoid ++ * timeout issues when LFS is enabled. ++ */ ++ msec_delay(100); + -+ ret_val = e1000_check_polarity_igp(hw); ++ /* ++ * The NVM settings will configure LPLU in D3 for ++ * non-IGP1 PHYs. ++ */ ++ if (phy->type == e1000_phy_igp) { ++ /* disable lplu d3 during driver init */ ++ ret_val = hw->phy.ops.set_d3_lplu_state(hw, false); ++ if (ret_val) { ++ DEBUGOUT("Error Disabling LPLU D3\n"); ++ goto out; ++ } ++ } ++ ++ /* disable lplu d0 during driver init */ ++ if (hw->phy.ops.set_d0_lplu_state) { ++ ret_val = hw->phy.ops.set_d0_lplu_state(hw, false); ++ if (ret_val) { ++ DEBUGOUT("Error Disabling LPLU D0\n"); ++ goto out; ++ } ++ } ++ /* Configure mdi-mdix settings */ ++ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data); + if (ret_val) + goto out; + -+ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); ++ data &= ~IGP01E1000_PSCR_AUTO_MDIX; ++ ++ switch (phy->mdix) { ++ case 1: ++ data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; ++ break; ++ case 2: ++ data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; ++ break; ++ case 0: ++ default: ++ data |= IGP01E1000_PSCR_AUTO_MDIX; ++ break; ++ } ++ ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data); + if (ret_val) + goto out; + -+ phy->is_mdix = (data & IGP01E1000_PSSR_MDIX) ? true : false; ++ /* set auto-master slave resolution settings */ ++ if (hw->mac.autoneg) { ++ /* ++ * when autonegotiation advertisement is only 1000Mbps then we ++ * should disable SmartSpeed and enable Auto MasterSlave ++ * resolution as hardware default. ++ */ ++ if (phy->autoneg_advertised == ADVERTISE_1000_FULL) { ++ /* Disable SmartSpeed */ ++ ret_val = phy->ops.read_reg(hw, ++ IGP01E1000_PHY_PORT_CONFIG, ++ &data); ++ if (ret_val) ++ goto out; + -+ if ((data & IGP01E1000_PSSR_SPEED_MASK) == -+ IGP01E1000_PSSR_SPEED_1000MBPS) { -+ ret_val = hw->phy.ops.get_cable_length(hw); -+ if (ret_val) -+ goto out; ++ data &= ~IGP01E1000_PSCFR_SMART_SPEED; ++ ret_val = phy->ops.write_reg(hw, ++ IGP01E1000_PHY_PORT_CONFIG, ++ data); ++ if (ret_val) ++ goto out; + -+ ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data); ++ /* Set auto Master/Slave resolution process */ ++ ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); ++ if (ret_val) ++ goto out; ++ ++ data &= ~CR_1000T_MS_ENABLE; ++ ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); ++ if (ret_val) ++ goto out; ++ } ++ ++ ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); + if (ret_val) + goto out; + -+ phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS) -+ ? e1000_1000t_rx_status_ok -+ : e1000_1000t_rx_status_not_ok; ++ /* load defaults for future use */ ++ phy->original_ms_type = (data & CR_1000T_MS_ENABLE) ? ++ ((data & CR_1000T_MS_VALUE) ? ++ e1000_ms_force_master : ++ e1000_ms_force_slave) : ++ e1000_ms_auto; + -+ phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS) -+ ? e1000_1000t_rx_status_ok -+ : e1000_1000t_rx_status_not_ok; -+ } else { -+ phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; -+ phy->local_rx = e1000_1000t_rx_status_undefined; -+ phy->remote_rx = e1000_1000t_rx_status_undefined; ++ switch (phy->ms_type) { ++ case e1000_ms_force_master: ++ data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); ++ break; ++ case e1000_ms_force_slave: ++ data |= CR_1000T_MS_ENABLE; ++ data &= ~(CR_1000T_MS_VALUE); ++ break; ++ case e1000_ms_auto: ++ data &= ~CR_1000T_MS_ENABLE; ++ default: ++ break; ++ } ++ ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); ++ if (ret_val) ++ goto out; + } + +out: @@ -13320,1421 +10478,2624 @@ diff -Nru vanilla/drivers/net/igb/e1000_phy.c linux-i686-2.6.22/drivers/net/igb/ +} + +/** -+ * e1000_phy_sw_reset_generic - PHY software reset ++ * e1000_copper_link_autoneg - Setup/Enable autoneg for copper link + * @hw: pointer to the HW structure + * -+ * Does a software reset of the PHY by reading the PHY control register and -+ * setting/write the control register reset bit to the PHY. ++ * Performs initial bounds checking on autoneg advertisement parameter, then ++ * configure to advertise the full capability. Setup the PHY to autoneg ++ * and restart the negotiation process between the link partner. If ++ * autoneg_wait_to_complete, then wait for autoneg to complete before exiting. + **/ -+s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw) ++s32 e1000_copper_link_autoneg(struct e1000_hw *hw) +{ -+ s32 ret_val = E1000_SUCCESS; ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; + u16 phy_ctrl; + -+ DEBUGFUNC("e1000_phy_sw_reset_generic"); ++ DEBUGFUNC("e1000_copper_link_autoneg"); + -+ if (!(hw->phy.ops.read_reg)) ++ /* ++ * Perform some bounds checking on the autoneg advertisement ++ * parameter. ++ */ ++ phy->autoneg_advertised &= phy->autoneg_mask; ++ ++ /* ++ * If autoneg_advertised is zero, we assume it was not defaulted ++ * by the calling code so we set to advertise full capability. ++ */ ++ if (phy->autoneg_advertised == 0) ++ phy->autoneg_advertised = phy->autoneg_mask; ++ ++ DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); ++ ret_val = e1000_phy_setup_autoneg(hw); ++ if (ret_val) { ++ DEBUGOUT("Error Setting up Auto-Negotiation\n"); + goto out; ++ } ++ DEBUGOUT("Restarting Auto-Neg\n"); + -+ ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); ++ /* ++ * Restart auto-negotiation by setting the Auto Neg Enable bit and ++ * the Auto Neg Restart bit in the PHY control register. ++ */ ++ ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); + if (ret_val) + goto out; + -+ phy_ctrl |= MII_CR_RESET; -+ ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl); ++ phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); ++ ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl); + if (ret_val) + goto out; + -+ usec_delay(1); ++ /* ++ * Does the user want to wait for Auto-Neg to complete here, or ++ * check at a later time (for example, callback routine). ++ */ ++ if (phy->autoneg_wait_to_complete) { ++ ret_val = hw->mac.ops.wait_autoneg(hw); ++ if (ret_val) { ++ DEBUGOUT("Error while waiting for " ++ "autoneg to complete\n"); ++ goto out; ++ } ++ } ++ ++ hw->mac.get_link_status = true; + +out: + return ret_val; +} + +/** -+ * e1000_phy_hw_reset_generic - PHY hardware reset ++ * e1000_phy_setup_autoneg - Configure PHY for auto-negotiation + * @hw: pointer to the HW structure + * -+ * Verify the reset block is not blocking us from resetting. Acquire -+ * semaphore (if necessary) and read/set/write the device control reset -+ * bit in the PHY. Wait the appropriate delay time for the device to -+ * reset and release the semaphore (if necessary). ++ * Reads the MII auto-neg advertisement register and/or the 1000T control ++ * register and if the PHY is already setup for auto-negotiation, then ++ * return successful. Otherwise, setup advertisement and flow control to ++ * the appropriate values for the wanted auto-negotiation. + **/ -+s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw) ++static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; -+ s32 ret_val = E1000_SUCCESS; -+ u32 ctrl; ++ s32 ret_val; ++ u16 mii_autoneg_adv_reg; ++ u16 mii_1000t_ctrl_reg = 0; + -+ DEBUGFUNC("e1000_phy_hw_reset_generic"); ++ DEBUGFUNC("e1000_phy_setup_autoneg"); + -+ ret_val = phy->ops.check_reset_block(hw); -+ if (ret_val) { -+ ret_val = E1000_SUCCESS; -+ goto out; -+ } ++ phy->autoneg_advertised &= phy->autoneg_mask; + -+ ret_val = phy->ops.acquire(hw); ++ /* Read the MII Auto-Neg Advertisement Register (Address 4). */ ++ ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); + if (ret_val) + goto out; + -+ ctrl = E1000_READ_REG(hw, E1000_CTRL); -+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PHY_RST); -+ E1000_WRITE_FLUSH(hw); ++ if (phy->autoneg_mask & ADVERTISE_1000_FULL) { ++ /* Read the MII 1000Base-T Control Register (Address 9). */ ++ ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, ++ &mii_1000t_ctrl_reg); ++ if (ret_val) ++ goto out; ++ } + -+ usec_delay(phy->reset_delay_us); ++ /* ++ * Need to parse both autoneg_advertised and fc and set up ++ * the appropriate PHY registers. First we will parse for ++ * autoneg_advertised software override. Since we can advertise ++ * a plethora of combinations, we need to check each bit ++ * individually. ++ */ + -+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl); -+ E1000_WRITE_FLUSH(hw); ++ /* ++ * First we clear all the 10/100 mb speed bits in the Auto-Neg ++ * Advertisement Register (Address 4) and the 1000 mb speed bits in ++ * the 1000Base-T Control Register (Address 9). ++ */ ++ mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS | ++ NWAY_AR_100TX_HD_CAPS | ++ NWAY_AR_10T_FD_CAPS | ++ NWAY_AR_10T_HD_CAPS); ++ mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS); + -+ usec_delay(150); ++ DEBUGOUT1("autoneg_advertised %x\n", phy->autoneg_advertised); + -+ phy->ops.release(hw); ++ /* Do we want to advertise 10 Mb Half Duplex? */ ++ if (phy->autoneg_advertised & ADVERTISE_10_HALF) { ++ DEBUGOUT("Advertise 10mb Half duplex\n"); ++ mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; ++ } + -+ ret_val = phy->ops.get_cfg_done(hw); ++ /* Do we want to advertise 10 Mb Full Duplex? */ ++ if (phy->autoneg_advertised & ADVERTISE_10_FULL) { ++ DEBUGOUT("Advertise 10mb Full duplex\n"); ++ mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; ++ } ++ ++ /* Do we want to advertise 100 Mb Half Duplex? */ ++ if (phy->autoneg_advertised & ADVERTISE_100_HALF) { ++ DEBUGOUT("Advertise 100mb Half duplex\n"); ++ mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; ++ } ++ ++ /* Do we want to advertise 100 Mb Full Duplex? */ ++ if (phy->autoneg_advertised & ADVERTISE_100_FULL) { ++ DEBUGOUT("Advertise 100mb Full duplex\n"); ++ mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; ++ } ++ ++ /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ ++ if (phy->autoneg_advertised & ADVERTISE_1000_HALF) ++ DEBUGOUT("Advertise 1000mb Half duplex request denied!\n"); ++ ++ /* Do we want to advertise 1000 Mb Full Duplex? */ ++ if (phy->autoneg_advertised & ADVERTISE_1000_FULL) { ++ DEBUGOUT("Advertise 1000mb Full duplex\n"); ++ mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; ++ } ++ ++ /* ++ * Check for a software override of the flow control settings, and ++ * setup the PHY advertisement registers accordingly. If ++ * auto-negotiation is enabled, then software will have to set the ++ * "PAUSE" bits to the correct value in the Auto-Negotiation ++ * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto- ++ * negotiation. ++ * ++ * The possible values of the "fc" parameter are: ++ * 0: Flow control is completely disabled ++ * 1: Rx flow control is enabled (we can receive pause frames ++ * but not send pause frames). ++ * 2: Tx flow control is enabled (we can send pause frames ++ * but we do not support receiving pause frames). ++ * 3: Both Rx and Tx flow control (symmetric) are enabled. ++ * other: No software override. The flow control configuration ++ * in the EEPROM is used. ++ */ ++ switch (hw->fc.current_mode) { ++ case e1000_fc_none: ++ /* ++ * Flow control (Rx & Tx) is completely disabled by a ++ * software over-ride. ++ */ ++ mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); ++ break; ++ case e1000_fc_rx_pause: ++ /* ++ * Rx Flow control is enabled, and Tx Flow control is ++ * disabled, by a software over-ride. ++ * ++ * Since there really isn't a way to advertise that we are ++ * capable of Rx Pause ONLY, we will advertise that we ++ * support both symmetric and asymmetric Rx PAUSE. Later ++ * (in e1000_config_fc_after_link_up) we will disable the ++ * hw's ability to send PAUSE frames. ++ */ ++ mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); ++ break; ++ case e1000_fc_tx_pause: ++ /* ++ * Tx Flow control is enabled, and Rx Flow control is ++ * disabled, by a software over-ride. ++ */ ++ mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; ++ mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; ++ break; ++ case e1000_fc_full: ++ /* ++ * Flow control (both Rx and Tx) is enabled by a software ++ * over-ride. ++ */ ++ mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); ++ break; ++ default: ++ DEBUGOUT("Flow control param set incorrectly\n"); ++ ret_val = -E1000_ERR_CONFIG; ++ goto out; ++ } ++ ++ ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); ++ if (ret_val) ++ goto out; ++ ++ DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); ++ ++ if (phy->autoneg_mask & ADVERTISE_1000_FULL) { ++ ret_val = phy->ops.write_reg(hw, ++ PHY_1000T_CTRL, ++ mii_1000t_ctrl_reg); ++ if (ret_val) ++ goto out; ++ } + +out: + return ret_val; +} + +/** -+ * e1000_get_cfg_done_generic - Generic configuration done ++ * e1000_setup_copper_link_generic - Configure copper link settings + * @hw: pointer to the HW structure + * -+ * Generic function to wait 10 milli-seconds for configuration to complete -+ * and return success. ++ * Calls the appropriate function to configure the link for auto-neg or forced ++ * speed and duplex. Then we check for link, once link is established calls ++ * to configure collision distance and flow control are called. If link is ++ * not established, we return -E1000_ERR_PHY (-2). + **/ -+s32 e1000_get_cfg_done_generic(struct e1000_hw *hw) ++s32 e1000_setup_copper_link_generic(struct e1000_hw *hw) +{ -+ DEBUGFUNC("e1000_get_cfg_done_generic"); ++ s32 ret_val; ++ bool link; + -+ msec_delay_irq(10); ++ DEBUGFUNC("e1000_setup_copper_link_generic"); + -+ return E1000_SUCCESS; -+} ++ if (hw->mac.autoneg) { ++ /* ++ * Setup autoneg and flow control advertisement and perform ++ * autonegotiation. ++ */ ++ ret_val = e1000_copper_link_autoneg(hw); ++ if (ret_val) ++ goto out; ++ } else { ++ /* ++ * PHY will be set to 10H, 10F, 100H or 100F ++ * depending on user settings. ++ */ ++ DEBUGOUT("Forcing Speed and Duplex\n"); ++ ret_val = hw->phy.ops.force_speed_duplex(hw); ++ if (ret_val) { ++ DEBUGOUT("Error Forcing Speed and Duplex\n"); ++ goto out; ++ } ++ } + -+/** -+ * e1000_phy_init_script_igp3 - Inits the IGP3 PHY -+ * @hw: pointer to the HW structure -+ * -+ * Initializes a Intel Gigabit PHY3 when an EEPROM is not present. -+ **/ -+s32 e1000_phy_init_script_igp3(struct e1000_hw *hw) -+{ -+ DEBUGOUT("Running IGP 3 PHY init script\n"); -+ -+ /* PHY init IGP 3 */ -+ /* Enable rise/fall, 10-mode work in class-A */ -+ hw->phy.ops.write_reg(hw, 0x2F5B, 0x9018); -+ /* Remove all caps from Replica path filter */ -+ hw->phy.ops.write_reg(hw, 0x2F52, 0x0000); -+ /* Bias trimming for ADC, AFE and Driver (Default) */ -+ hw->phy.ops.write_reg(hw, 0x2FB1, 0x8B24); -+ /* Increase Hybrid poly bias */ -+ hw->phy.ops.write_reg(hw, 0x2FB2, 0xF8F0); -+ /* Add 4% to Tx amplitude in Gig mode */ -+ hw->phy.ops.write_reg(hw, 0x2010, 0x10B0); -+ /* Disable trimming (TTT) */ -+ hw->phy.ops.write_reg(hw, 0x2011, 0x0000); -+ /* Poly DC correction to 94.6% + 2% for all channels */ -+ hw->phy.ops.write_reg(hw, 0x20DD, 0x249A); -+ /* ABS DC correction to 95.9% */ -+ hw->phy.ops.write_reg(hw, 0x20DE, 0x00D3); -+ /* BG temp curve trim */ -+ hw->phy.ops.write_reg(hw, 0x28B4, 0x04CE); -+ /* Increasing ADC OPAMP stage 1 currents to max */ -+ hw->phy.ops.write_reg(hw, 0x2F70, 0x29E4); -+ /* Force 1000 ( required for enabling PHY regs configuration) */ -+ hw->phy.ops.write_reg(hw, 0x0000, 0x0140); -+ /* Set upd_freq to 6 */ -+ hw->phy.ops.write_reg(hw, 0x1F30, 0x1606); -+ /* Disable NPDFE */ -+ hw->phy.ops.write_reg(hw, 0x1F31, 0xB814); -+ /* Disable adaptive fixed FFE (Default) */ -+ hw->phy.ops.write_reg(hw, 0x1F35, 0x002A); -+ /* Enable FFE hysteresis */ -+ hw->phy.ops.write_reg(hw, 0x1F3E, 0x0067); -+ /* Fixed FFE for short cable lengths */ -+ hw->phy.ops.write_reg(hw, 0x1F54, 0x0065); -+ /* Fixed FFE for medium cable lengths */ -+ hw->phy.ops.write_reg(hw, 0x1F55, 0x002A); -+ /* Fixed FFE for long cable lengths */ -+ hw->phy.ops.write_reg(hw, 0x1F56, 0x002A); -+ /* Enable Adaptive Clip Threshold */ -+ hw->phy.ops.write_reg(hw, 0x1F72, 0x3FB0); -+ /* AHT reset limit to 1 */ -+ hw->phy.ops.write_reg(hw, 0x1F76, 0xC0FF); -+ /* Set AHT master delay to 127 msec */ -+ hw->phy.ops.write_reg(hw, 0x1F77, 0x1DEC); -+ /* Set scan bits for AHT */ -+ hw->phy.ops.write_reg(hw, 0x1F78, 0xF9EF); -+ /* Set AHT Preset bits */ -+ hw->phy.ops.write_reg(hw, 0x1F79, 0x0210); -+ /* Change integ_factor of channel A to 3 */ -+ hw->phy.ops.write_reg(hw, 0x1895, 0x0003); -+ /* Change prop_factor of channels BCD to 8 */ -+ hw->phy.ops.write_reg(hw, 0x1796, 0x0008); -+ /* Change cg_icount + enable integbp for channels BCD */ -+ hw->phy.ops.write_reg(hw, 0x1798, 0xD008); -+ /* -+ * Change cg_icount + enable integbp + change prop_factor_master -+ * to 8 for channel A -+ */ -+ hw->phy.ops.write_reg(hw, 0x1898, 0xD918); -+ /* Disable AHT in Slave mode on channel A */ -+ hw->phy.ops.write_reg(hw, 0x187A, 0x0800); + /* -+ * Enable LPLU and disable AN to 1000 in non-D0a states, -+ * Enable SPD+B2B ++ * Check link status. Wait up to 100 microseconds for link to become ++ * valid. + */ -+ hw->phy.ops.write_reg(hw, 0x0019, 0x008D); -+ /* Enable restart AN on an1000_dis change */ -+ hw->phy.ops.write_reg(hw, 0x001B, 0x2080); -+ /* Enable wh_fifo read clock in 10/100 modes */ -+ hw->phy.ops.write_reg(hw, 0x0014, 0x0045); -+ /* Restart AN, Speed selection is 1000 */ -+ hw->phy.ops.write_reg(hw, 0x0000, 0x1340); ++ ret_val = e1000_phy_has_link_generic(hw, ++ COPPER_LINK_UP_LIMIT, ++ 10, ++ &link); ++ if (ret_val) ++ goto out; + -+ return E1000_SUCCESS; ++ if (link) { ++ DEBUGOUT("Valid link established!!!\n"); ++ e1000_config_collision_dist_generic(hw); ++ ret_val = e1000_config_fc_after_link_up_generic(hw); ++ } else { ++ DEBUGOUT("Unable to establish link!!!\n"); ++ } ++ ++out: ++ return ret_val; +} + +/** -+ * e1000_get_phy_type_from_id - Get PHY type from id -+ * @phy_id: phy_id read from the phy ++ * e1000_phy_force_speed_duplex_igp - Force speed/duplex for igp PHY ++ * @hw: pointer to the HW structure + * -+ * Returns the phy type from the id. ++ * Calls the PHY setup function to force speed and duplex. Clears the ++ * auto-crossover to force MDI manually. Waits for link and returns ++ * successful if link up is successful, else -E1000_ERR_PHY (-2). + **/ -+enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id) ++s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw) +{ -+ enum e1000_phy_type phy_type = e1000_phy_unknown; ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ u16 phy_data; ++ bool link; + -+ switch (phy_id) { -+ case M88E1000_I_PHY_ID: -+ case M88E1000_E_PHY_ID: -+ case M88E1111_I_PHY_ID: -+ case M88E1011_I_PHY_ID: -+ phy_type = e1000_phy_m88; -+ break; -+ case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */ -+ phy_type = e1000_phy_igp_2; -+ break; -+ case GG82563_E_PHY_ID: -+ phy_type = e1000_phy_gg82563; -+ break; -+ case IGP03E1000_E_PHY_ID: -+ phy_type = e1000_phy_igp_3; -+ break; -+ case IFE_E_PHY_ID: -+ case IFE_PLUS_E_PHY_ID: -+ case IFE_C_E_PHY_ID: -+ phy_type = e1000_phy_ife; -+ break; -+ default: -+ phy_type = e1000_phy_unknown; -+ break; ++ DEBUGFUNC("e1000_phy_force_speed_duplex_igp"); ++ ++ ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); ++ if (ret_val) ++ goto out; ++ ++ e1000_phy_force_speed_duplex_setup(hw, &phy_data); ++ ++ ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); ++ if (ret_val) ++ goto out; ++ ++ /* ++ * Clear Auto-Crossover to force MDI manually. IGP requires MDI ++ * forced whenever speed and duplex are forced. ++ */ ++ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); ++ if (ret_val) ++ goto out; ++ ++ phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; ++ phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; ++ ++ ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); ++ if (ret_val) ++ goto out; ++ ++ DEBUGOUT1("IGP PSCR: %X\n", phy_data); ++ ++ usec_delay(1); ++ ++ if (phy->autoneg_wait_to_complete) { ++ DEBUGOUT("Waiting for forced speed/duplex link on IGP phy.\n"); ++ ++ ret_val = e1000_phy_has_link_generic(hw, ++ PHY_FORCE_LIMIT, ++ 100000, ++ &link); ++ if (ret_val) ++ goto out; ++ ++ if (!link) ++ DEBUGOUT("Link taking longer than expected.\n"); ++ ++ /* Try once more */ ++ ret_val = e1000_phy_has_link_generic(hw, ++ PHY_FORCE_LIMIT, ++ 100000, ++ &link); ++ if (ret_val) ++ goto out; + } -+ return phy_type; ++ ++out: ++ return ret_val; +} + +/** -+ * e1000_power_up_phy_copper - Restore copper link in case of PHY power down -+ * @hw: pointer to the HW structure ++ * e1000_phy_force_speed_duplex_m88 - Force speed/duplex for m88 PHY ++ * @hw: pointer to the HW structure + * -+ * In the case of a PHY power down to save power, or to turn off link during a -+ * driver unload, or wake on lan is not enabled, restore the link to previous -+ * settings. ++ * Calls the PHY setup function to force speed and duplex. Clears the ++ * auto-crossover to force MDI manually. Resets the PHY to commit the ++ * changes. If time expires while waiting for link up, we reset the DSP. ++ * After reset, TX_CLK and CRS on Tx must be set. Return successful upon ++ * successful completion, else return corresponding error code. + **/ -+void e1000_power_up_phy_copper(struct e1000_hw *hw) ++s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) +{ -+ u16 mii_reg = 0; ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ u16 phy_data; ++ bool link; + -+ /* The PHY will retain its settings across a power down/up cycle */ -+ hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); -+ mii_reg &= ~MII_CR_POWER_DOWN; -+ hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); -+} ++ DEBUGFUNC("e1000_phy_force_speed_duplex_m88"); + -+/** -+ * e1000_power_down_phy_copper - Restore copper link in case of PHY power down -+ * @hw: pointer to the HW structure -+ * -+ * In the case of a PHY power down to save power, or to turn off link during a -+ * driver unload, or wake on lan is not enabled, restore the link to previous -+ * settings. -+ **/ -+void e1000_power_down_phy_copper(struct e1000_hw *hw) -+{ -+ u16 mii_reg = 0; ++ /* ++ * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI ++ * forced whenever speed and duplex are forced. ++ */ ++ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); ++ if (ret_val) ++ goto out; + -+ /* The PHY will retain its settings across a power down/up cycle */ -+ hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); -+ mii_reg |= MII_CR_POWER_DOWN; -+ hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); -+ msec_delay(1); -+} -diff -Nru vanilla/drivers/net/igb/e1000_phy.h linux-i686-2.6.22/drivers/net/igb/e1000_phy.h ---- vanilla/drivers/net/igb/e1000_phy.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/e1000_phy.h 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,152 @@ -+/******************************************************************************* ++ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; ++ ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); ++ if (ret_val) ++ goto out; + -+ Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data); + -+ 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. ++ ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); ++ if (ret_val) ++ goto out; + -+ 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. ++ e1000_phy_force_speed_duplex_setup(hw, &phy_data); + -+ 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". ++ ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); ++ if (ret_val) ++ goto out; + -+ Contact Information: -+ e1000-devel Mailing List -+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ /* Reset the phy to commit changes. */ ++ ret_val = hw->phy.ops.commit(hw); ++ if (ret_val) ++ goto out; + -+*******************************************************************************/ ++ if (phy->autoneg_wait_to_complete) { ++ DEBUGOUT("Waiting for forced speed/duplex link on M88 phy.\n"); + -+#ifndef _E1000_PHY_H_ -+#define _E1000_PHY_H_ ++ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, ++ 100000, &link); ++ if (ret_val) ++ goto out; + -+void e1000_init_phy_ops_generic(struct e1000_hw *hw); -+s32 e1000_check_downshift_generic(struct e1000_hw *hw); -+s32 e1000_check_polarity_m88(struct e1000_hw *hw); -+s32 e1000_check_polarity_igp(struct e1000_hw *hw); -+s32 e1000_check_reset_block_generic(struct e1000_hw *hw); -+s32 e1000_copper_link_autoneg(struct e1000_hw *hw); -+s32 e1000_copper_link_setup_igp(struct e1000_hw *hw); -+s32 e1000_copper_link_setup_m88(struct e1000_hw *hw); -+s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw); -+s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw); -+s32 e1000_get_cable_length_m88(struct e1000_hw *hw); -+s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw); -+s32 e1000_get_cfg_done_generic(struct e1000_hw *hw); -+s32 e1000_get_phy_id(struct e1000_hw *hw); -+s32 e1000_get_phy_info_igp(struct e1000_hw *hw); -+s32 e1000_get_phy_info_m88(struct e1000_hw *hw); -+s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw); -+void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); -+s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw); -+s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw); -+s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data); -+s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); -+s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data); -+s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active); -+s32 e1000_setup_copper_link_generic(struct e1000_hw *hw); -+s32 e1000_wait_autoneg_generic(struct e1000_hw *hw); -+s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data); -+s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); -+s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data); -+s32 e1000_phy_reset_dsp(struct e1000_hw *hw); -+s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, -+ u32 usec_interval, bool *success); -+s32 e1000_phy_init_script_igp3(struct e1000_hw *hw); -+enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id); -+void e1000_power_up_phy_copper(struct e1000_hw *hw); -+void e1000_power_down_phy_copper(struct e1000_hw *hw); -+s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); -+s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); ++ if (!link) { ++ /* ++ * We didn't get link. ++ * Reset the DSP and cross our fingers. ++ */ ++ ret_val = phy->ops.write_reg(hw, ++ M88E1000_PHY_PAGE_SELECT, ++ 0x001d); ++ if (ret_val) ++ goto out; ++ ret_val = e1000_phy_reset_dsp_generic(hw); ++ if (ret_val) ++ goto out; ++ } + -+#define E1000_MAX_PHY_ADDR 4 ++ /* Try once more */ ++ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, ++ 100000, &link); ++ if (ret_val) ++ goto out; ++ } + -+/* IGP01E1000 Specific Registers */ -+#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */ -+#define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */ -+#define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */ -+#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */ -+#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO */ -+#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality */ -+#define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */ -+#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */ -+#define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */ -+#define IGP_PAGE_SHIFT 5 -+#define PHY_REG_MASK 0x1F ++ ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); ++ if (ret_val) ++ goto out; + -+#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 -+#define IGP01E1000_PHY_POLARITY_MASK 0x0078 ++ /* ++ * Resetting the phy means we need to re-force TX_CLK in the ++ * Extended PHY Specific Control Register to 25MHz clock from ++ * the reset value of 2.5MHz. ++ */ ++ phy_data |= M88E1000_EPSCR_TX_CLK_25; ++ ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); ++ if (ret_val) ++ goto out; + -+#define IGP01E1000_PSCR_AUTO_MDIX 0x1000 -+#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */ ++ /* ++ * In addition, we must re-enable CRS on Tx for both half and full ++ * duplex. ++ */ ++ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); ++ if (ret_val) ++ goto out; + -+#define IGP01E1000_PSCFR_SMART_SPEED 0x0080 ++ phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; ++ ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + -+/* Enable flexible speed on link-up */ -+#define IGP01E1000_GMII_FLEX_SPD 0x0010 -+#define IGP01E1000_GMII_SPD 0x0020 /* Enable SPD */ ++out: ++ return ret_val; ++} + -+#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */ -+#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */ -+#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */ ++/** ++ * e1000_phy_force_speed_duplex_ife - Force PHY speed & duplex ++ * @hw: pointer to the HW structure ++ * ++ * Forces the speed and duplex settings of the PHY. ++ * This is a function pointer entry point only called by ++ * PHY setup routines. ++ **/ ++s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ u16 data; ++ bool link; + -+#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 ++ DEBUGFUNC("e1000_phy_force_speed_duplex_ife"); + -+#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 -+#define IGP01E1000_PSSR_MDIX 0x0008 -+#define IGP01E1000_PSSR_SPEED_MASK 0xC000 -+#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 ++ if (phy->type != e1000_phy_ife) { ++ ret_val = e1000_phy_force_speed_duplex_igp(hw); ++ goto out; ++ } + -+#define IGP02E1000_PHY_CHANNEL_NUM 4 -+#define IGP02E1000_PHY_AGC_A 0x11B1 -+#define IGP02E1000_PHY_AGC_B 0x12B1 -+#define IGP02E1000_PHY_AGC_C 0x14B1 -+#define IGP02E1000_PHY_AGC_D 0x18B1 ++ ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &data); ++ if (ret_val) ++ goto out; + -+#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course - 15:13, Fine - 12:9 */ -+#define IGP02E1000_AGC_LENGTH_MASK 0x7F -+#define IGP02E1000_AGC_RANGE 15 ++ e1000_phy_force_speed_duplex_setup(hw, &data); + -+#define IGP03E1000_PHY_MISC_CTRL 0x1B -+#define IGP03E1000_PHY_MISC_DUPLEX_MANUAL_SET 0x1000 /* Manually Set Duplex */ ++ ret_val = phy->ops.write_reg(hw, PHY_CONTROL, data); ++ if (ret_val) ++ goto out; + -+#define E1000_CABLE_LENGTH_UNDEFINED 0xFF ++ /* Disable MDI-X support for 10/100 */ ++ ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data); ++ if (ret_val) ++ goto out; + -+#define E1000_KMRNCTRLSTA_OFFSET 0x001F0000 -+#define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16 -+#define E1000_KMRNCTRLSTA_REN 0x00200000 -+#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ -+#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ ++ data &= ~IFE_PMC_AUTO_MDIX; ++ data &= ~IFE_PMC_FORCE_MDIX; + -+#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 -+#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */ -+#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Control */ -+#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */ ++ ret_val = phy->ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, data); ++ if (ret_val) ++ goto out; + -+/* IFE PHY Extended Status Control */ -+#define IFE_PESC_POLARITY_REVERSED 0x0100 ++ DEBUGOUT1("IFE PMC: %X\n", data); + -+/* IFE PHY Special Control */ -+#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 -+#define IFE_PSC_FORCE_POLARITY 0x0020 -+#define IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN 0x0100 ++ usec_delay(1); + -+/* IFE PHY Special Control and LED Control */ -+#define IFE_PSCL_PROBE_MODE 0x0020 -+#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */ -+#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */ ++ if (phy->autoneg_wait_to_complete) { ++ DEBUGOUT("Waiting for forced speed/duplex link on IFE phy.\n"); + -+/* IFE PHY MDIX Control */ -+#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */ -+#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDI-X, 0=force MDI */ -+#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable auto MDI/MDI-X, 0=disable */ ++ ret_val = e1000_phy_has_link_generic(hw, ++ PHY_FORCE_LIMIT, ++ 100000, ++ &link); ++ if (ret_val) ++ goto out; + -+#endif -Binary files vanilla/drivers/net/igb/e1000_phy.o and linux-i686-2.6.22/drivers/net/igb/e1000_phy.o differ -diff -Nru vanilla/drivers/net/igb/.e1000_phy.o.cmd linux-i686-2.6.22/drivers/net/igb/.e1000_phy.o.cmd ---- vanilla/drivers/net/igb/.e1000_phy.o.cmd 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/.e1000_phy.o.cmd 2009-07-16 19:53:43.000000000 -0400 -@@ -0,0 +1,549 @@ -+cmd_drivers/net/igb/e1000_phy.o := gcc -m32 -Wp,-MD,drivers/net/igb/.e1000_phy.o.d -nostdinc -isystem /usr/lib/gcc/i386-redhat-linux/4.1.2/include -D__KERNEL__ -Iinclude -include include/linux/autoconf.h -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Os -pipe -msoft-float -mregparm=3 -freg-struct-return -mpreferred-stack-boundary=2 -march=i686 -mtune=generic -ffreestanding -maccumulate-outgoing-args -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -Iinclude/asm-i386/mach-generic -Iinclude/asm-i386/mach-default -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -DMODULE -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(e1000_phy)" -D"KBUILD_MODNAME=KBUILD_STR(igb)" -c -o drivers/net/igb/.tmp_e1000_phy.o drivers/net/igb/e1000_phy.c -+ -+deps_drivers/net/igb/e1000_phy.o := \ -+ drivers/net/igb/e1000_phy.c \ -+ drivers/net/igb/e1000_api.h \ -+ drivers/net/igb/e1000_hw.h \ -+ drivers/net/igb/e1000_osdep.h \ -+ include/linux/pci.h \ -+ $(wildcard include/config/pci/msi.h) \ -+ $(wildcard include/config/pci.h) \ -+ $(wildcard include/config/ht/irq.h) \ -+ $(wildcard include/config/pci/domains.h) \ -+ include/linux/pci_regs.h \ -+ include/linux/mod_devicetable.h \ -+ include/linux/types.h \ -+ $(wildcard include/config/uid16.h) \ -+ $(wildcard include/config/lbd.h) \ -+ $(wildcard include/config/lsf.h) \ -+ $(wildcard include/config/resources/64bit.h) \ -+ include/linux/posix_types.h \ -+ include/linux/stddef.h \ -+ include/linux/compiler.h \ -+ $(wildcard include/config/enable/must/check.h) \ -+ include/linux/compiler-gcc4.h \ -+ $(wildcard include/config/forced/inlining.h) \ -+ include/linux/compiler-gcc.h \ -+ include/asm/posix_types.h \ -+ include/asm/types.h \ -+ $(wildcard include/config/highmem64g.h) \ -+ include/linux/ioport.h \ -+ include/linux/list.h \ -+ $(wildcard include/config/debug/list.h) \ -+ include/linux/poison.h \ -+ include/linux/prefetch.h \ -+ include/asm/processor.h \ -+ $(wildcard include/config/smp.h) \ -+ $(wildcard include/config/x86/ht.h) \ -+ $(wildcard include/config/paravirt.h) \ -+ $(wildcard include/config/mk8.h) \ -+ $(wildcard include/config/mk7.h) \ -+ include/asm/vm86.h \ -+ $(wildcard include/config/vm86.h) \ -+ include/asm/ptrace.h \ -+ include/asm/ptrace-abi.h \ -+ include/asm/segment.h \ -+ include/asm/math_emu.h \ -+ include/asm/sigcontext.h \ -+ include/asm/page.h \ -+ $(wildcard include/config/x86/use/3dnow.h) \ -+ $(wildcard include/config/x86/pae.h) \ -+ $(wildcard include/config/hugetlb/page.h) \ -+ $(wildcard include/config/highmem4g.h) \ -+ $(wildcard include/config/page/offset.h) \ -+ $(wildcard include/config/flatmem.h) \ -+ include/asm-generic/pgtable-nopmd.h \ -+ include/asm-generic/pgtable-nopud.h \ -+ include/asm-generic/memory_model.h \ -+ $(wildcard include/config/discontigmem.h) \ -+ $(wildcard include/config/sparsemem.h) \ -+ $(wildcard include/config/out/of/line/pfn/to/page.h) \ -+ include/asm-generic/page.h \ -+ include/asm/cpufeature.h \ -+ include/linux/bitops.h \ -+ include/asm/bitops.h \ -+ include/asm/alternative.h \ -+ include/asm-generic/bitops/sched.h \ -+ include/asm-generic/bitops/hweight.h \ -+ include/asm-generic/bitops/fls64.h \ -+ include/asm-generic/bitops/ext2-non-atomic.h \ -+ include/asm-generic/bitops/le.h \ -+ include/asm/byteorder.h \ -+ $(wildcard include/config/x86/bswap.h) \ -+ include/linux/byteorder/little_endian.h \ -+ include/linux/byteorder/swab.h \ -+ include/linux/byteorder/generic.h \ -+ include/asm-generic/bitops/minix.h \ -+ include/asm/required-features.h \ -+ $(wildcard include/config/x86/minimum/cpu.h) \ -+ $(wildcard include/config/x86/cmov.h) \ -+ $(wildcard include/config/x86/cmpxchg64.h) \ -+ include/asm/msr.h \ -+ include/asm/msr-index.h \ -+ include/asm/errno.h \ -+ include/asm-generic/errno.h \ -+ include/asm-generic/errno-base.h \ -+ include/linux/errno.h \ -+ include/asm/system.h \ -+ $(wildcard include/config/x86/oostore.h) \ -+ include/linux/kernel.h \ -+ $(wildcard include/config/preempt/voluntary.h) \ -+ $(wildcard include/config/debug/spinlock/sleep.h) \ -+ $(wildcard include/config/printk.h) \ -+ $(wildcard include/config/numa.h) \ -+ /usr/lib/gcc/i386-redhat-linux/4.1.2/include/stdarg.h \ -+ include/linux/linkage.h \ -+ include/asm/linkage.h \ -+ $(wildcard include/config/x86/alignment/16.h) \ -+ include/linux/log2.h \ -+ $(wildcard include/config/arch/has/ilog2/u32.h) \ -+ $(wildcard include/config/arch/has/ilog2/u64.h) \ -+ include/asm/bug.h \ -+ $(wildcard include/config/bug.h) \ -+ $(wildcard include/config/debug/bugverbose.h) \ -+ include/asm-generic/bug.h \ -+ $(wildcard include/config/generic/bug.h) \ -+ include/asm/cmpxchg.h \ -+ $(wildcard include/config/x86/cmpxchg.h) \ -+ include/linux/irqflags.h \ -+ $(wildcard include/config/trace/irqflags.h) \ -+ $(wildcard include/config/trace/irqflags/support.h) \ -+ $(wildcard include/config/x86.h) \ -+ include/asm/irqflags.h \ -+ include/asm/processor-flags.h \ -+ include/linux/cache.h \ -+ include/asm/cache.h \ -+ $(wildcard include/config/x86/l1/cache/shift.h) \ -+ include/linux/threads.h \ -+ $(wildcard include/config/nr/cpus.h) \ -+ $(wildcard include/config/base/small.h) \ -+ include/asm/percpu.h \ -+ include/linux/cpumask.h \ -+ $(wildcard include/config/hotplug/cpu.h) \ -+ include/linux/bitmap.h \ -+ include/linux/string.h \ -+ include/asm/string.h \ -+ include/linux/init.h \ -+ $(wildcard include/config/modules.h) \ -+ $(wildcard include/config/hotplug.h) \ -+ $(wildcard include/config/memory/hotplug.h) \ -+ $(wildcard include/config/acpi/hotplug/memory.h) \ -+ include/asm/atomic.h \ -+ $(wildcard include/config/m386.h) \ -+ include/asm-generic/atomic.h \ -+ include/linux/device.h \ -+ $(wildcard include/config/debug/devres.h) \ -+ include/linux/kobject.h \ -+ include/linux/sysfs.h \ -+ $(wildcard include/config/sysfs.h) \ -+ include/linux/spinlock.h \ -+ $(wildcard include/config/debug/spinlock.h) \ -+ $(wildcard include/config/preempt.h) \ -+ $(wildcard include/config/debug/lock/alloc.h) \ -+ include/linux/preempt.h \ -+ $(wildcard include/config/debug/preempt.h) \ -+ include/linux/thread_info.h \ -+ include/asm/thread_info.h \ -+ $(wildcard include/config/4kstacks.h) \ -+ $(wildcard include/config/debug/stack/usage.h) \ -+ include/linux/stringify.h \ -+ include/linux/bottom_half.h \ -+ include/linux/spinlock_types.h \ -+ include/linux/lockdep.h \ -+ $(wildcard include/config/lockdep.h) \ -+ $(wildcard include/config/generic/hardirqs.h) \ -+ $(wildcard include/config/prove/locking.h) \ -+ include/asm/spinlock_types.h \ -+ include/asm/spinlock.h \ -+ $(wildcard include/config/x86/ppro/fence.h) \ -+ include/asm/rwlock.h \ -+ include/linux/spinlock_api_smp.h \ -+ include/linux/kref.h \ -+ include/linux/wait.h \ -+ include/asm/current.h \ -+ include/linux/klist.h \ -+ include/linux/completion.h \ -+ include/linux/module.h \ -+ $(wildcard include/config/modversions.h) \ -+ $(wildcard include/config/unused/symbols.h) \ -+ $(wildcard include/config/module/unload.h) \ -+ $(wildcard include/config/kallsyms.h) \ -+ include/linux/stat.h \ -+ include/asm/stat.h \ -+ include/linux/time.h \ -+ include/linux/seqlock.h \ -+ include/linux/vs_time.h \ -+ $(wildcard include/config/vserver/vtime.h) \ -+ include/linux/kmod.h \ -+ $(wildcard include/config/kmod.h) \ -+ include/linux/elf.h \ -+ include/linux/auxvec.h \ -+ include/asm/auxvec.h \ -+ include/linux/elf-em.h \ -+ include/asm/elf.h \ -+ include/asm/user.h \ -+ include/asm/desc.h \ -+ include/asm/ldt.h \ -+ include/linux/smp.h \ -+ include/asm/smp.h \ -+ $(wildcard include/config/x86/local/apic.h) \ -+ $(wildcard include/config/x86/io/apic.h) \ -+ include/asm/mpspec.h \ -+ $(wildcard include/config/acpi.h) \ -+ include/asm/mpspec_def.h \ -+ include/asm-i386/mach-generic/mach_mpspec.h \ -+ include/asm/apic.h \ -+ $(wildcard include/config/x86/good/apic.h) \ -+ include/linux/pm.h \ -+ $(wildcard include/config/pm.h) \ -+ include/linux/delay.h \ -+ include/asm/delay.h \ -+ include/asm/fixmap.h \ -+ $(wildcard include/config/highmem.h) \ -+ $(wildcard include/config/x86/visws/apic.h) \ -+ $(wildcard include/config/x86/f00f/bug.h) \ -+ $(wildcard include/config/x86/cyclone/timer.h) \ -+ $(wildcard include/config/pci/mmconfig.h) \ -+ include/asm/acpi.h \ -+ $(wildcard include/config/acpi/sleep.h) \ -+ include/acpi/pdc_intel.h \ -+ include/asm/apicdef.h \ -+ include/asm/kmap_types.h \ -+ $(wildcard include/config/debug/highmem.h) \ -+ include/asm/io_apic.h \ -+ include/asm-i386/mach-generic/mach_apicdef.h \ -+ include/asm/genapic.h \ -+ include/linux/percpu.h \ -+ include/linux/slab.h \ -+ $(wildcard include/config/slab/debug.h) \ -+ $(wildcard include/config/slab.h) \ -+ $(wildcard include/config/slub.h) \ -+ $(wildcard include/config/debug/slab.h) \ -+ include/linux/gfp.h \ -+ $(wildcard include/config/zone/dma.h) \ -+ $(wildcard include/config/zone/dma32.h) \ -+ include/linux/mmzone.h \ -+ $(wildcard include/config/force/max/zoneorder.h) \ -+ $(wildcard include/config/arch/populates/node/map.h) \ -+ $(wildcard include/config/flat/node/mem/map.h) \ -+ $(wildcard include/config/have/memory/present.h) \ -+ $(wildcard include/config/need/node/memmap/size.h) \ -+ $(wildcard include/config/need/multiple/nodes.h) \ -+ $(wildcard include/config/have/arch/early/pfn/to/nid.h) \ -+ $(wildcard include/config/sparsemem/extreme.h) \ -+ $(wildcard include/config/nodes/span/other/nodes.h) \ -+ $(wildcard include/config/holes/in/zone.h) \ -+ include/linux/numa.h \ -+ $(wildcard include/config/nodes/shift.h) \ -+ include/linux/nodemask.h \ -+ include/linux/memory_hotplug.h \ -+ $(wildcard include/config/have/arch/nodedata/extension.h) \ -+ include/linux/notifier.h \ -+ include/linux/mutex.h \ -+ $(wildcard include/config/debug/mutexes.h) \ -+ $(wildcard include/config/chopstix.h) \ -+ include/linux/rwsem.h \ -+ $(wildcard include/config/rwsem/generic/spinlock.h) \ -+ include/asm/rwsem.h \ -+ include/linux/srcu.h \ -+ include/linux/topology.h \ -+ $(wildcard include/config/sched/smt.h) \ -+ $(wildcard include/config/sched/mc.h) \ -+ include/asm/topology.h \ -+ include/asm-generic/topology.h \ -+ include/linux/slab_def.h \ -+ include/linux/kmalloc_sizes.h \ -+ include/asm/mmu.h \ -+ include/asm/semaphore.h \ -+ include/linux/moduleparam.h \ -+ include/asm/local.h \ -+ include/asm/module.h \ -+ $(wildcard include/config/m486.h) \ -+ $(wildcard include/config/m586.h) \ -+ $(wildcard include/config/m586tsc.h) \ -+ $(wildcard include/config/m586mmx.h) \ -+ $(wildcard include/config/mcore2.h) \ -+ $(wildcard include/config/m686.h) \ -+ $(wildcard include/config/mpentiumii.h) \ -+ $(wildcard include/config/mpentiumiii.h) \ -+ $(wildcard include/config/mpentiumm.h) \ -+ $(wildcard include/config/mpentium4.h) \ -+ $(wildcard include/config/mk6.h) \ -+ $(wildcard include/config/x86/elan.h) \ -+ $(wildcard include/config/mcrusoe.h) \ -+ $(wildcard include/config/mefficeon.h) \ -+ $(wildcard include/config/mwinchipc6.h) \ -+ $(wildcard include/config/mwinchip2.h) \ -+ $(wildcard include/config/mwinchip3d.h) \ -+ $(wildcard include/config/mcyrixiii.h) \ -+ $(wildcard include/config/mviac3/2.h) \ -+ $(wildcard include/config/mviac7.h) \ -+ $(wildcard include/config/mgeodegx1.h) \ -+ $(wildcard include/config/mgeode/lx.h) \ -+ include/asm/device.h \ -+ include/linux/pci_ids.h \ -+ include/linux/dmapool.h \ -+ include/asm/io.h \ -+ $(wildcard include/config/x86/numaq.h) \ -+ include/asm-generic/iomap.h \ -+ include/linux/vmalloc.h \ -+ include/asm/scatterlist.h \ -+ include/asm/pci.h \ -+ include/linux/mm.h \ -+ $(wildcard include/config/sysctl.h) \ -+ $(wildcard include/config/mmu.h) \ -+ $(wildcard include/config/stack/growsup.h) \ -+ $(wildcard include/config/debug/vm.h) \ -+ $(wildcard include/config/shmem.h) \ -+ $(wildcard include/config/split/ptlock/cpus.h) \ -+ $(wildcard include/config/ia64.h) \ -+ $(wildcard include/config/proc/fs.h) \ -+ $(wildcard include/config/debug/pagealloc.h) \ -+ include/linux/capability.h \ -+ include/linux/rbtree.h \ -+ include/linux/prio_tree.h \ -+ include/linux/fs.h \ -+ $(wildcard include/config/dnotify.h) \ -+ $(wildcard include/config/vserver/cowbl.h) \ -+ $(wildcard include/config/quota.h) \ -+ $(wildcard include/config/inotify.h) \ -+ $(wildcard include/config/security.h) \ -+ $(wildcard include/config/epoll.h) \ -+ $(wildcard include/config/auditsyscall.h) \ -+ $(wildcard include/config/block.h) \ -+ $(wildcard include/config/fs/xip.h) \ -+ $(wildcard include/config/migration.h) \ -+ include/linux/limits.h \ -+ include/linux/ioctl.h \ -+ include/asm/ioctl.h \ -+ include/asm-generic/ioctl.h \ -+ include/linux/kdev_t.h \ -+ include/linux/dcache.h \ -+ $(wildcard include/config/profiling.h) \ -+ include/linux/rcupdate.h \ -+ include/linux/namei.h \ -+ include/linux/radix-tree.h \ -+ include/linux/pid.h \ -+ include/linux/quota.h \ -+ include/linux/dqblk_xfs.h \ -+ include/linux/dqblk_v1.h \ -+ include/linux/dqblk_v2.h \ -+ include/linux/nfs_fs_i.h \ -+ include/linux/nfs.h \ -+ include/linux/sunrpc/msg_prot.h \ -+ include/linux/fcntl.h \ -+ include/asm/fcntl.h \ -+ include/asm-generic/fcntl.h \ -+ $(wildcard include/config/64bit.h) \ -+ include/linux/err.h \ -+ include/linux/debug_locks.h \ -+ $(wildcard include/config/debug/locking/api/selftests.h) \ -+ include/linux/backing-dev.h \ -+ include/linux/mm_types.h \ -+ include/asm/pgtable.h \ -+ $(wildcard include/config/highpte.h) \ -+ include/asm/paravirt.h \ -+ include/asm/pgtable-2level-defs.h \ -+ include/asm/pgtable-2level.h \ -+ include/asm-generic/pgtable.h \ -+ include/linux/page-flags.h \ -+ $(wildcard include/config/s390.h) \ -+ $(wildcard include/config/swap.h) \ -+ include/linux/vmstat.h \ -+ $(wildcard include/config/vm/event/counters.h) \ -+ include/asm-generic/pci-dma-compat.h \ -+ include/linux/dma-mapping.h \ -+ include/asm/dma-mapping.h \ -+ include/asm-generic/pci.h \ -+ include/linux/interrupt.h \ -+ $(wildcard include/config/high/res/timers.h) \ -+ $(wildcard include/config/generic/irq/probe.h) \ -+ include/linux/irqreturn.h \ -+ include/linux/hardirq.h \ -+ $(wildcard include/config/preempt/bkl.h) \ -+ $(wildcard include/config/virt/cpu/accounting.h) \ -+ include/linux/smp_lock.h \ -+ $(wildcard include/config/lock/kernel.h) \ -+ include/linux/sched.h \ -+ $(wildcard include/config/no/hz.h) \ -+ $(wildcard include/config/detect/softlockup.h) \ -+ $(wildcard include/config/keys.h) \ -+ $(wildcard include/config/bsd/process/acct.h) \ -+ $(wildcard include/config/taskstats.h) \ -+ $(wildcard include/config/inotify/user.h) \ -+ $(wildcard include/config/schedstats.h) \ -+ $(wildcard include/config/task/delay/acct.h) \ -+ $(wildcard include/config/blk/dev/io/trace.h) \ -+ $(wildcard include/config/cc/stackprotector.h) \ -+ $(wildcard include/config/sysvipc.h) \ -+ $(wildcard include/config/rt/mutexes.h) \ -+ $(wildcard include/config/task/xacct.h) \ -+ $(wildcard include/config/cpusets.h) \ -+ $(wildcard include/config/compat.h) \ -+ $(wildcard include/config/fault/injection.h) \ -+ include/asm/param.h \ -+ $(wildcard include/config/hz.h) \ -+ include/linux/timex.h \ -+ $(wildcard include/config/time/interpolation.h) \ -+ include/asm/timex.h \ -+ include/asm/tsc.h \ -+ $(wildcard include/config/x86/tsc.h) \ -+ $(wildcard include/config/x86/generic.h) \ -+ include/linux/jiffies.h \ -+ include/linux/calc64.h \ -+ include/asm/div64.h \ -+ include/asm/cputime.h \ -+ include/asm-generic/cputime.h \ -+ include/linux/sem.h \ -+ include/linux/ipc.h \ -+ $(wildcard include/config/ipc/ns.h) \ -+ include/asm/ipcbuf.h \ -+ include/asm/sembuf.h \ -+ include/linux/signal.h \ -+ include/asm/signal.h \ -+ include/asm-generic/signal.h \ -+ include/asm/siginfo.h \ -+ include/asm-generic/siginfo.h \ -+ include/linux/securebits.h \ -+ include/linux/fs_struct.h \ -+ include/linux/seccomp.h \ -+ $(wildcard include/config/seccomp.h) \ -+ include/linux/futex.h \ -+ $(wildcard include/config/futex.h) \ -+ include/linux/rtmutex.h \ -+ $(wildcard include/config/debug/rt/mutexes.h) \ -+ include/linux/plist.h \ -+ $(wildcard include/config/debug/pi/list.h) \ -+ include/linux/param.h \ -+ include/linux/resource.h \ -+ include/asm/resource.h \ -+ include/asm-generic/resource.h \ -+ include/linux/timer.h \ -+ $(wildcard include/config/timer/stats.h) \ -+ include/linux/ktime.h \ -+ $(wildcard include/config/ktime/scalar.h) \ -+ include/linux/hrtimer.h \ -+ include/linux/task_io_accounting.h \ -+ $(wildcard include/config/task/io/accounting.h) \ -+ include/linux/aio.h \ -+ include/linux/workqueue.h \ -+ include/linux/aio_abi.h \ -+ include/linux/uio.h \ -+ include/asm/hardirq.h \ -+ include/linux/irq.h \ -+ $(wildcard include/config/irq/per/cpu.h) \ -+ $(wildcard include/config/irq/release/method.h) \ -+ $(wildcard include/config/generic/pending/irq.h) \ -+ $(wildcard include/config/irqbalance.h) \ -+ $(wildcard include/config/auto/irq/affinity.h) \ -+ $(wildcard include/config/generic/hardirqs/no//do/irq.h) \ -+ include/asm/irq.h \ -+ include/asm-i386/mach-default/irq_vectors.h \ -+ include/asm-i386/mach-default/irq_vectors_limits.h \ -+ include/asm/irq_regs.h \ -+ include/asm/hw_irq.h \ -+ include/linux/profile.h \ -+ include/asm/sections.h \ -+ include/asm-generic/sections.h \ -+ include/linux/irq_cpustat.h \ -+ include/linux/if_ether.h \ -+ include/linux/skbuff.h \ -+ $(wildcard include/config/nf/conntrack.h) \ -+ $(wildcard include/config/bridge/netfilter.h) \ -+ $(wildcard include/config/vlan/8021q.h) \ -+ $(wildcard include/config/net/sched.h) \ -+ $(wildcard include/config/net/cls/act.h) \ -+ $(wildcard include/config/net/dma.h) \ -+ $(wildcard include/config/network/secmark.h) \ -+ include/linux/net.h \ -+ include/asm/socket.h \ -+ include/asm/sockios.h \ -+ include/linux/random.h \ -+ include/linux/sysctl.h \ -+ $(wildcard include/config/icmp/ipod.h) \ -+ $(wildcard include/config/web100/net100.h) \ -+ $(wildcard include/config/web100/stats.h) \ -+ include/linux/textsearch.h \ -+ include/net/checksum.h \ -+ include/asm/uaccess.h \ -+ $(wildcard include/config/x86/intel/usercopy.h) \ -+ $(wildcard include/config/x86/wp/works/ok.h) \ -+ include/asm/checksum.h \ -+ include/linux/in6.h \ -+ include/linux/dmaengine.h \ -+ $(wildcard include/config/dma/engine.h) \ -+ drivers/net/igb/kcompat.h \ -+ $(wildcard include/config/e1000/napi.h) \ -+ $(wildcard include/config/e1000e/napi.h) \ -+ $(wildcard include/config/ixgb/napi.h) \ -+ $(wildcard include/config/e1000/disable/packet/split.h) \ -+ $(wildcard include/config/igb/disable/packet/split.h) \ -+ $(wildcard include/config/net/poll/controller.h) \ -+ $(wildcard include/config/space/len.h) \ -+ $(wildcard include/config/netpoll.h) \ -+ $(wildcard include/config/netdevices/multiqueue.h) \ -+ include/linux/version.h \ -+ include/linux/netdevice.h \ -+ $(wildcard include/config/ax25.h) \ -+ $(wildcard include/config/tr.h) \ -+ $(wildcard include/config/net/ipip.h) \ -+ $(wildcard include/config/net/ipgre.h) \ -+ $(wildcard include/config/ipv6/sit.h) \ -+ $(wildcard include/config/ipv6/tunnel.h) \ -+ $(wildcard include/config/wireless/ext.h) \ -+ $(wildcard include/config/netpoll/trap.h) \ -+ include/linux/if.h \ -+ include/linux/socket.h \ -+ include/linux/sockios.h \ -+ include/linux/hdlc/ioctl.h \ -+ include/linux/if_packet.h \ -+ include/linux/etherdevice.h \ -+ include/linux/in.h \ -+ include/linux/ip.h \ -+ include/linux/udp.h \ -+ include/net/inet_sock.h \ -+ $(wildcard include/config/ipv6.h) \ -+ include/linux/jhash.h \ -+ include/net/flow.h \ -+ $(wildcard include/config/ipv6/mip6.h) \ -+ include/net/sock.h \ -+ $(wildcard include/config/security/network.h) \ -+ include/linux/security.h \ -+ $(wildcard include/config/security/network/xfrm.h) \ -+ include/linux/binfmts.h \ -+ include/linux/shm.h \ -+ include/asm/shmparam.h \ -+ include/asm/shmbuf.h \ -+ include/linux/msg.h \ -+ include/asm/msgbuf.h \ -+ include/linux/key.h \ -+ include/linux/xfrm.h \ -+ include/linux/filter.h \ -+ include/net/dst.h \ -+ $(wildcard include/config/net/cls/route.h) \ -+ $(wildcard include/config/xfrm.h) \ -+ include/linux/rtnetlink.h \ -+ include/linux/netlink.h \ -+ include/linux/if_link.h \ -+ include/linux/if_addr.h \ -+ include/linux/neighbour.h \ -+ include/net/neighbour.h \ -+ include/linux/seq_file.h \ -+ include/net/rtnetlink.h \ -+ include/net/netlink.h \ -+ include/net/request_sock.h \ -+ include/linux/mii.h \ -+ include/linux/latency.h \ -+ drivers/net/igb/e1000_regs.h \ -+ drivers/net/igb/e1000_defines.h \ -+ $(wildcard include/config/res.h) \ -+ $(wildcard include/config/fault.h) \ -+ drivers/net/igb/e1000_mac.h \ -+ drivers/net/igb/e1000_phy.h \ -+ drivers/net/igb/e1000_nvm.h \ -+ drivers/net/igb/e1000_manage.h \ -+ drivers/net/igb/e1000_82575.h \ -+ -+drivers/net/igb/e1000_phy.o: $(deps_drivers/net/igb/e1000_phy.o) -+ -+$(deps_drivers/net/igb/e1000_phy.o): -diff -Nru vanilla/drivers/net/igb/e1000_regs.h linux-i686-2.6.22/drivers/net/igb/e1000_regs.h ---- vanilla/drivers/net/igb/e1000_regs.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/e1000_regs.h 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,441 @@ -+/******************************************************************************* ++ if (!link) ++ DEBUGOUT("Link taking longer than expected.\n"); + -+ Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ /* Try once more */ ++ ret_val = e1000_phy_has_link_generic(hw, ++ PHY_FORCE_LIMIT, ++ 100000, ++ &link); ++ if (ret_val) ++ goto out; ++ } + -+ 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. ++out: ++ return ret_val; ++} + -+ 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. ++/** ++ * e1000_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex ++ * @hw: pointer to the HW structure ++ * @phy_ctrl: pointer to current value of PHY_CONTROL ++ * ++ * Forces speed and duplex on the PHY by doing the following: disable flow ++ * control, force speed/duplex on the MAC, disable auto speed detection, ++ * disable auto-negotiation, configure duplex, configure speed, configure ++ * the collision distance, write configuration to CTRL register. The ++ * caller must write to the PHY_CONTROL register for these settings to ++ * take affect. ++ **/ ++void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl) ++{ ++ struct e1000_mac_info *mac = &hw->mac; ++ u32 ctrl; + -+ 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. ++ DEBUGFUNC("e1000_phy_force_speed_duplex_setup"); + -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". ++ /* Turn off flow control when forcing speed/duplex */ ++ hw->fc.current_mode = e1000_fc_none; + -+ Contact Information: -+ e1000-devel Mailing List -+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ /* Force speed/duplex on the mac */ ++ ctrl = E1000_READ_REG(hw, E1000_CTRL); ++ ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); ++ ctrl &= ~E1000_CTRL_SPD_SEL; + -+*******************************************************************************/ ++ /* Disable Auto Speed Detection */ ++ ctrl &= ~E1000_CTRL_ASDE; + -+#ifndef _E1000_REGS_H_ -+#define _E1000_REGS_H_ ++ /* Disable autoneg on the phy */ ++ *phy_ctrl &= ~MII_CR_AUTO_NEG_EN; + -+#define E1000_CTRL 0x00000 /* Device Control - RW */ -+#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */ -+#define E1000_STATUS 0x00008 /* Device Status - RO */ -+#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ -+#define E1000_EERD 0x00014 /* EEPROM Read - RW */ -+#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ -+#define E1000_FLA 0x0001C /* Flash Access - RW */ -+#define E1000_MDIC 0x00020 /* MDI Control - RW */ -+#define E1000_SCTL 0x00024 /* SerDes Control - RW */ -+#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ -+#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ -+#define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */ -+#define E1000_FCT 0x00030 /* Flow Control Type - RW */ -+#define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */ -+#define E1000_VET 0x00038 /* VLAN Ether Type - RW */ -+#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */ -+#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */ -+#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */ -+#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */ -+#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */ -+#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */ -+#define E1000_RCTL 0x00100 /* Rx Control - RW */ -+#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ -+#define E1000_TXCW 0x00178 /* Tx Configuration Word - RW */ -+#define E1000_RXCW 0x00180 /* Rx Configuration Word - RO */ -+#define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */ -+#define E1000_EITR(_n) (0x01680 + (0x4 * (_n))) -+#define E1000_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */ -+#define E1000_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */ -+#define E1000_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */ -+#define E1000_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */ -+#define E1000_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */ -+#define E1000_GPIE 0x01514 /* General Purpose Interrupt Enable - RW */ -+#define E1000_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */ -+#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */ -+#define E1000_TCTL 0x00400 /* Tx Control - RW */ -+#define E1000_TCTL_EXT 0x00404 /* Extended Tx Control - RW */ -+#define E1000_TIPG 0x00410 /* Tx Inter-packet gap -RW */ -+#define E1000_TBT 0x00448 /* Tx Burst Timer - RW */ -+#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */ -+#define E1000_LEDCTL 0x00E00 /* LED Control - RW */ -+#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */ -+#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */ -+#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */ -+#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ -+#define E1000_PBS 0x01008 /* Packet Buffer Size */ -+#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ -+#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */ -+#define E1000_FLASHT 0x01028 /* FLASH Timer Register */ -+#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */ -+#define E1000_FLSWCTL 0x01030 /* FLASH control register */ -+#define E1000_FLSWDATA 0x01034 /* FLASH data register */ -+#define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */ -+#define E1000_FLOP 0x0103C /* FLASH Opcode Register */ -+#define E1000_I2CCMD 0x01028 /* SFPI2C Command Register - RW */ -+#define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */ -+#define E1000_WDSTP 0x01040 /* Watchdog Setup - RW */ -+#define E1000_SWDSTS 0x01044 /* SW Device Status - RW */ -+#define E1000_FRTIMER 0x01048 /* Free Running Timer - RW */ -+#define E1000_TCPTIMER 0x0104C /* TCP Timer - RW */ -+#define E1000_VPDDIAG 0x01060 /* VPD Diagnostic - RO */ -+#define E1000_ICR_V2 0x01500 /* Interrupt Cause - new location - RC */ -+#define E1000_ICS_V2 0x01504 /* Interrupt Cause Set - new location - WO */ -+#define E1000_IMS_V2 0x01508 /* Interrupt Mask Set/Read - new location - RW */ -+#define E1000_IMC_V2 0x0150C /* Interrupt Mask Clear - new location - WO */ -+#define E1000_IAM_V2 0x01510 /* Interrupt Ack Auto Mask - new location - RW */ -+#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */ -+#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ -+#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ -+#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */ -+#define E1000_RDFPCQ(_n) (0x02430 + (0x4 * (_n))) -+#define E1000_PBRTH 0x02458 /* PB Rx Arbitration Threshold - RW */ -+#define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */ -+/* Split and Replication Rx Control - RW */ -+#define E1000_RDPUMB 0x025CC /* DMA Rx Descriptor uC Mailbox - RW */ -+#define E1000_RDPUAD 0x025D0 /* DMA Rx Descriptor uC Addr Command - RW */ -+#define E1000_RDPUWD 0x025D4 /* DMA Rx Descriptor uC Data Write - RW */ -+#define E1000_RDPURD 0x025D8 /* DMA Rx Descriptor uC Data Read - RW */ -+#define E1000_RDPUCTL 0x025DC /* DMA Rx Descriptor uC Control - RW */ -+#define E1000_PBDIAG 0x02458 /* Packet Buffer Diagnostic - RW */ -+#define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */ -+#define E1000_RXCTL(_n) (0x0C014 + (0x40 * (_n))) -+#define E1000_RQDPC(_n) (0x0C030 + (0x40 * (_n))) -+#define E1000_TXCTL(_n) (0x0E014 + (0x40 * (_n))) -+#define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */ -+#define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */ -+/* -+ * Convenience macros ++ /* Forcing Full or Half Duplex? */ ++ if (mac->forced_speed_duplex & E1000_ALL_HALF_DUPLEX) { ++ ctrl &= ~E1000_CTRL_FD; ++ *phy_ctrl &= ~MII_CR_FULL_DUPLEX; ++ DEBUGOUT("Half Duplex\n"); ++ } else { ++ ctrl |= E1000_CTRL_FD; ++ *phy_ctrl |= MII_CR_FULL_DUPLEX; ++ DEBUGOUT("Full Duplex\n"); ++ } ++ ++ /* Forcing 10mb or 100mb? */ ++ if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) { ++ ctrl |= E1000_CTRL_SPD_100; ++ *phy_ctrl |= MII_CR_SPEED_100; ++ *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10); ++ DEBUGOUT("Forcing 100mb\n"); ++ } else { ++ ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); ++ *phy_ctrl |= MII_CR_SPEED_10; ++ *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100); ++ DEBUGOUT("Forcing 10mb\n"); ++ } ++ ++ e1000_config_collision_dist_generic(hw); ++ ++ E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ++} ++ ++/** ++ * e1000_set_d3_lplu_state_generic - Sets low power link up state for D3 ++ * @hw: pointer to the HW structure ++ * @active: boolean used to enable/disable lplu + * -+ * Note: "_n" is the queue number of the register to be written to. ++ * Success returns 0, Failure returns 1 + * -+ * Example usage: -+ * E1000_RDBAL_REG(current_rx_queue) -+ */ -+#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : (0x0C000 + ((_n) * 0x40))) -+#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : (0x0C004 + ((_n) * 0x40))) -+#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : (0x0C008 + ((_n) * 0x40))) -+#define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : (0x0C00C + ((_n) * 0x40))) -+#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : (0x0C010 + ((_n) * 0x40))) -+#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : (0x0C018 + ((_n) * 0x40))) -+#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : (0x0C028 + ((_n) * 0x40))) -+#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : (0x0E000 + ((_n) * 0x40))) -+#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : (0x0E004 + ((_n) * 0x40))) -+#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : (0x0E008 + ((_n) * 0x40))) -+#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : (0x0E010 + ((_n) * 0x40))) -+#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : (0x0E018 + ((_n) * 0x40))) -+#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : (0x0E028 + ((_n) * 0x40))) -+#define E1000_TARC(_n) (0x03840 + (_n << 8)) -+#define E1000_DCA_TXCTRL(_n) (0x03814 + (_n << 8)) -+#define E1000_DCA_RXCTRL(_n) (0x02814 + (_n << 8)) -+#define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) : (0x0E038 + ((_n) * 0x40))) -+#define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) : (0x0E03C + ((_n) * 0x40))) -+#define E1000_RSRPD 0x02C00 /* Rx Small Packet Detect - RW */ -+#define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */ -+#define E1000_TXDMAC 0x03000 /* Tx DMA Control - RW */ -+#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */ -+#define E1000_PSRTYPE(_i) (0x05480 + ((_i) * 4)) -+#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : (0x054E0 + ((_i - 16) * 8))) -+#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : (0x054E4 + ((_i - 16) * 8))) -+#define E1000_IP4AT_REG(_i) (0x05840 + ((_i) * 8)) -+#define E1000_IP6AT_REG(_i) (0x05880 + ((_i) * 4)) -+#define E1000_WUPM_REG(_i) (0x05A00 + ((_i) * 4)) -+#define E1000_FFMT_REG(_i) (0x09000 + ((_i) * 8)) -+#define E1000_FFVT_REG(_i) (0x09800 + ((_i) * 8)) -+#define E1000_FFLT_REG(_i) (0x05F00 + ((_i) * 8)) -+#define E1000_PBSLAC 0x03100 /* Packet Buffer Slave Access Control */ -+#define E1000_PBSLAD(_n) (0x03110 + (0x4 * (_n))) /* Packet Buffer DWORD (_n) */ -+#define E1000_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */ -+#define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */ -+#define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */ -+#define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */ -+#define E1000_TDFTS 0x03428 /* Tx Data FIFO Tail Saved - RW */ -+#define E1000_TDFPC 0x03430 /* Tx Data FIFO Packet Count - RW */ -+#define E1000_TDPUMB 0x0357C /* DMA Tx Descriptor uC Mail Box - RW */ -+#define E1000_TDPUAD 0x03580 /* DMA Tx Descriptor uC Addr Command - RW */ -+#define E1000_TDPUWD 0x03584 /* DMA Tx Descriptor uC Data Write - RW */ -+#define E1000_TDPURD 0x03588 /* DMA Tx Descriptor uC Data Read - RW */ -+#define E1000_TDPUCTL 0x0358C /* DMA Tx Descriptor uC Control - RW */ -+#define E1000_DTXCTL 0x03590 /* DMA Tx Control - RW */ -+#define E1000_DTXTCPFLGL 0x0359C /* DMA Tx Control flag low - RW */ -+#define E1000_DTXTCPFLGH 0x035A0 /* DMA Tx Control flag high - RW */ -+#define E1000_DTXMXSZRQ 0x03540 /* DMA Tx Max Total Allow Size Requests - RW */ -+#define E1000_TIDV 0x03820 /* Tx Interrupt Delay Value - RW */ -+#define E1000_TADV 0x0382C /* Tx Interrupt Absolute Delay Val - RW */ -+#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */ -+#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */ -+#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ -+#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */ -+#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */ -+#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */ -+#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */ -+#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */ -+#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */ -+#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */ -+#define E1000_COLC 0x04028 /* Collision Count - R/clr */ -+#define E1000_DC 0x04030 /* Defer Count - R/clr */ -+#define E1000_TNCRS 0x04034 /* Tx-No CRS - R/clr */ -+#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */ -+#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */ -+#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */ -+#define E1000_XONRXC 0x04048 /* XON Rx Count - R/clr */ -+#define E1000_XONTXC 0x0404C /* XON Tx Count - R/clr */ -+#define E1000_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */ -+#define E1000_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */ -+#define E1000_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */ -+#define E1000_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */ -+#define E1000_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */ -+#define E1000_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */ -+#define E1000_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */ -+#define E1000_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */ -+#define E1000_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */ -+#define E1000_GPRC 0x04074 /* Good Packets Rx Count - R/clr */ -+#define E1000_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */ -+#define E1000_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */ -+#define E1000_GPTC 0x04080 /* Good Packets Tx Count - R/clr */ -+#define E1000_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */ -+#define E1000_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */ -+#define E1000_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */ -+#define E1000_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */ -+#define E1000_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */ -+#define E1000_RUC 0x040A4 /* Rx Undersize Count - R/clr */ -+#define E1000_RFC 0x040A8 /* Rx Fragment Count - R/clr */ -+#define E1000_ROC 0x040AC /* Rx Oversize Count - R/clr */ -+#define E1000_RJC 0x040B0 /* Rx Jabber Count - R/clr */ -+#define E1000_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */ -+#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */ -+#define E1000_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */ -+#define E1000_TORL 0x040C0 /* Total Octets Rx Low - R/clr */ -+#define E1000_TORH 0x040C4 /* Total Octets Rx High - R/clr */ -+#define E1000_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */ -+#define E1000_TOTH 0x040CC /* Total Octets Tx High - R/clr */ -+#define E1000_TPR 0x040D0 /* Total Packets Rx - R/clr */ -+#define E1000_TPT 0x040D4 /* Total Packets Tx - R/clr */ -+#define E1000_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */ -+#define E1000_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */ -+#define E1000_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */ -+#define E1000_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */ -+#define E1000_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */ -+#define E1000_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */ -+#define E1000_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */ -+#define E1000_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */ -+#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */ -+#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context Tx Fail - R/clr */ -+#define E1000_IAC 0x04100 /* Interrupt Assertion Count */ -+#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Packet Timer Expire Count */ -+#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Absolute Timer Expire Count */ -+#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Packet Timer Expire Count */ -+#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Absolute Timer Expire Count */ -+#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */ -+#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Minimum Threshold Count */ -+#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Descriptor Minimum Threshold Count */ -+#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */ ++ * The low power link up (lplu) state is set to the power management level D3 ++ * and SmartSpeed is disabled when active is true, else clear lplu for D3 ++ * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU ++ * is used during Dx states where the power conservation is most important. ++ * During driver activity, SmartSpeed should be enabled so performance is ++ * maintained. ++ **/ ++s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val = E1000_SUCCESS; ++ u16 data; ++ ++ DEBUGFUNC("e1000_set_d3_lplu_state_generic"); ++ ++ if (!(hw->phy.ops.read_reg)) ++ goto out; ++ ++ ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); ++ if (ret_val) ++ goto out; ++ ++ if (!active) { ++ data &= ~IGP02E1000_PM_D3_LPLU; ++ ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, ++ data); ++ if (ret_val) ++ goto out; ++ /* ++ * LPLU and SmartSpeed are mutually exclusive. LPLU is used ++ * during Dx states where the power conservation is most ++ * important. During driver activity we should enable ++ * SmartSpeed, so performance is maintained. ++ */ ++ if (phy->smart_speed == e1000_smart_speed_on) { ++ ret_val = phy->ops.read_reg(hw, ++ IGP01E1000_PHY_PORT_CONFIG, ++ &data); ++ if (ret_val) ++ goto out; ++ ++ data |= IGP01E1000_PSCFR_SMART_SPEED; ++ ret_val = phy->ops.write_reg(hw, ++ IGP01E1000_PHY_PORT_CONFIG, ++ data); ++ if (ret_val) ++ goto out; ++ } else if (phy->smart_speed == e1000_smart_speed_off) { ++ ret_val = phy->ops.read_reg(hw, ++ IGP01E1000_PHY_PORT_CONFIG, ++ &data); ++ if (ret_val) ++ goto out; ++ ++ data &= ~IGP01E1000_PSCFR_SMART_SPEED; ++ ret_val = phy->ops.write_reg(hw, ++ IGP01E1000_PHY_PORT_CONFIG, ++ data); ++ if (ret_val) ++ goto out; ++ } ++ } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || ++ (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || ++ (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { ++ data |= IGP02E1000_PM_D3_LPLU; ++ ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, ++ data); ++ if (ret_val) ++ goto out; ++ ++ /* When LPLU is enabled, we should disable SmartSpeed */ ++ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, ++ &data); ++ if (ret_val) ++ goto out; ++ ++ data &= ~IGP01E1000_PSCFR_SMART_SPEED; ++ ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, ++ data); ++ } ++ ++out: ++ return ret_val; ++} ++ ++/** ++ * e1000_check_downshift_generic - Checks whether a downshift in speed occurred ++ * @hw: pointer to the HW structure ++ * ++ * Success returns 0, Failure returns 1 ++ * ++ * A downshift is detected by querying the PHY link health. ++ **/ ++s32 e1000_check_downshift_generic(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ u16 phy_data, offset, mask; ++ ++ DEBUGFUNC("e1000_check_downshift_generic"); ++ ++ switch (phy->type) { ++ case e1000_phy_m88: ++ case e1000_phy_gg82563: ++ offset = M88E1000_PHY_SPEC_STATUS; ++ mask = M88E1000_PSSR_DOWNSHIFT; ++ break; ++ case e1000_phy_igp_2: ++ case e1000_phy_igp: ++ case e1000_phy_igp_3: ++ offset = IGP01E1000_PHY_LINK_HEALTH; ++ mask = IGP01E1000_PLHR_SS_DOWNGRADE; ++ break; ++ default: ++ /* speed downshift not supported */ ++ phy->speed_downgraded = false; ++ ret_val = E1000_SUCCESS; ++ goto out; ++ } ++ ++ ret_val = phy->ops.read_reg(hw, offset, &phy_data); ++ ++ if (!ret_val) ++ phy->speed_downgraded = (phy_data & mask) ? true : false; ++ ++out: ++ return ret_val; ++} ++ ++/** ++ * e1000_check_polarity_m88 - Checks the polarity. ++ * @hw: pointer to the HW structure ++ * ++ * Success returns 0, Failure returns -E1000_ERR_PHY (-2) ++ * ++ * Polarity is determined based on the PHY specific status register. ++ **/ ++s32 e1000_check_polarity_m88(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ u16 data; ++ ++ DEBUGFUNC("e1000_check_polarity_m88"); ++ ++ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &data); ++ ++ if (!ret_val) ++ phy->cable_polarity = (data & M88E1000_PSSR_REV_POLARITY) ++ ? e1000_rev_polarity_reversed ++ : e1000_rev_polarity_normal; ++ ++ return ret_val; ++} ++ ++/** ++ * e1000_check_polarity_igp - Checks the polarity. ++ * @hw: pointer to the HW structure ++ * ++ * Success returns 0, Failure returns -E1000_ERR_PHY (-2) ++ * ++ * Polarity is determined based on the PHY port status register, and the ++ * current speed (since there is no polarity at 100Mbps). ++ **/ ++s32 e1000_check_polarity_igp(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ u16 data, offset, mask; ++ ++ DEBUGFUNC("e1000_check_polarity_igp"); ++ ++ /* ++ * Polarity is determined based on the speed of ++ * our connection. ++ */ ++ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); ++ if (ret_val) ++ goto out; ++ ++ if ((data & IGP01E1000_PSSR_SPEED_MASK) == ++ IGP01E1000_PSSR_SPEED_1000MBPS) { ++ offset = IGP01E1000_PHY_PCS_INIT_REG; ++ mask = IGP01E1000_PHY_POLARITY_MASK; ++ } else { ++ /* ++ * This really only applies to 10Mbps since ++ * there is no polarity for 100Mbps (always 0). ++ */ ++ offset = IGP01E1000_PHY_PORT_STATUS; ++ mask = IGP01E1000_PSSR_POLARITY_REVERSED; ++ } ++ ++ ret_val = phy->ops.read_reg(hw, offset, &data); ++ ++ if (!ret_val) ++ phy->cable_polarity = (data & mask) ++ ? e1000_rev_polarity_reversed ++ : e1000_rev_polarity_normal; ++ ++out: ++ return ret_val; ++} ++ ++/** ++ * e1000_check_polarity_ife - Check cable polarity for IFE PHY ++ * @hw: pointer to the HW structure ++ * ++ * Polarity is determined on the polarity reversal feature being enabled. ++ **/ ++s32 e1000_check_polarity_ife(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ u16 phy_data, offset, mask; ++ ++ DEBUGFUNC("e1000_check_polarity_ife"); ++ ++ /* ++ * Polarity is determined based on the reversal feature being enabled. ++ */ ++ if (phy->polarity_correction) { ++ offset = IFE_PHY_EXTENDED_STATUS_CONTROL; ++ mask = IFE_PESC_POLARITY_REVERSED; ++ } else { ++ offset = IFE_PHY_SPECIAL_CONTROL; ++ mask = IFE_PSC_FORCE_POLARITY; ++ } ++ ++ ret_val = phy->ops.read_reg(hw, offset, &phy_data); ++ ++ if (!ret_val) ++ phy->cable_polarity = (phy_data & mask) ++ ? e1000_rev_polarity_reversed ++ : e1000_rev_polarity_normal; ++ ++ return ret_val; ++} ++ ++/** ++ * e1000_wait_autoneg_generic - Wait for auto-neg completion ++ * @hw: pointer to the HW structure ++ * ++ * Waits for auto-negotiation to complete or for the auto-negotiation time ++ * limit to expire, which ever happens first. ++ **/ ++s32 e1000_wait_autoneg_generic(struct e1000_hw *hw) ++{ ++ s32 ret_val = E1000_SUCCESS; ++ u16 i, phy_status; ++ ++ DEBUGFUNC("e1000_wait_autoneg_generic"); ++ ++ if (!(hw->phy.ops.read_reg)) ++ return E1000_SUCCESS; ++ ++ /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */ ++ for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) { ++ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); ++ if (ret_val) ++ break; ++ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); ++ if (ret_val) ++ break; ++ if (phy_status & MII_SR_AUTONEG_COMPLETE) ++ break; ++ msec_delay(100); ++ } ++ ++ /* ++ * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation ++ * has completed. ++ */ ++ return ret_val; ++} ++ ++/** ++ * e1000_phy_has_link_generic - Polls PHY for link ++ * @hw: pointer to the HW structure ++ * @iterations: number of times to poll for link ++ * @usec_interval: delay between polling attempts ++ * @success: pointer to whether polling was successful or not ++ * ++ * Polls the PHY status register for link, 'iterations' number of times. ++ **/ ++s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, ++ u32 usec_interval, bool *success) ++{ ++ s32 ret_val = E1000_SUCCESS; ++ u16 i, phy_status; ++ ++ DEBUGFUNC("e1000_phy_has_link_generic"); ++ ++ if (!(hw->phy.ops.read_reg)) ++ return E1000_SUCCESS; ++ ++ for (i = 0; i < iterations; i++) { ++ /* ++ * Some PHYs require the PHY_STATUS register to be read ++ * twice due to the link bit being sticky. No harm doing ++ * it across the board. ++ */ ++ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); ++ if (ret_val) { ++ /* ++ * If the first read fails, another entity may have ++ * ownership of the resources, wait and try again to ++ * see if they have relinquished the resources yet. ++ */ ++ usec_delay(usec_interval); ++ } ++ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); ++ if (ret_val) ++ break; ++ if (phy_status & MII_SR_LINK_STATUS) ++ break; ++ if (usec_interval >= 1000) ++ msec_delay_irq(usec_interval/1000); ++ else ++ usec_delay(usec_interval); ++ } ++ ++ *success = (i < iterations) ? true : false; ++ ++ return ret_val; ++} ++ ++/** ++ * e1000_get_cable_length_m88 - Determine cable length for m88 PHY ++ * @hw: pointer to the HW structure ++ * ++ * Reads the PHY specific status register to retrieve the cable length ++ * information. The cable length is determined by averaging the minimum and ++ * maximum values to get the "average" cable length. The m88 PHY has four ++ * possible cable length values, which are: ++ * Register Value Cable Length ++ * 0 < 50 meters ++ * 1 50 - 80 meters ++ * 2 80 - 110 meters ++ * 3 110 - 140 meters ++ * 4 > 140 meters ++ **/ ++s32 e1000_get_cable_length_m88(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ u16 phy_data, index; ++ ++ DEBUGFUNC("e1000_get_cable_length_m88"); ++ ++ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); ++ if (ret_val) ++ goto out; ++ ++ index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> ++ M88E1000_PSSR_CABLE_LENGTH_SHIFT; ++ if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) { ++ ret_val = -E1000_ERR_PHY; ++ goto out; ++ } ++ ++ phy->min_cable_length = e1000_m88_cable_length_table[index]; ++ phy->max_cable_length = e1000_m88_cable_length_table[index + 1]; ++ ++ phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; ++ ++out: ++ return ret_val; ++} ++ ++/** ++ * e1000_get_cable_length_igp_2 - Determine cable length for igp2 PHY ++ * @hw: pointer to the HW structure ++ * ++ * The automatic gain control (agc) normalizes the amplitude of the ++ * received signal, adjusting for the attenuation produced by the ++ * cable. By reading the AGC registers, which represent the ++ * combination of coarse and fine gain value, the value can be put ++ * into a lookup table to obtain the approximate cable length ++ * for each channel. ++ **/ ++s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val = E1000_SUCCESS; ++ u16 phy_data, i, agc_value = 0; ++ u16 cur_agc_index, max_agc_index = 0; ++ u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1; ++ u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = ++ {IGP02E1000_PHY_AGC_A, ++ IGP02E1000_PHY_AGC_B, ++ IGP02E1000_PHY_AGC_C, ++ IGP02E1000_PHY_AGC_D}; ++ ++ DEBUGFUNC("e1000_get_cable_length_igp_2"); ++ ++ /* Read the AGC registers for all channels */ ++ for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) { ++ ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &phy_data); ++ if (ret_val) ++ goto out; ++ ++ /* ++ * Getting bits 15:9, which represent the combination of ++ * coarse and fine gain values. The result is a number ++ * that can be put into the lookup table to obtain the ++ * approximate cable length. ++ */ ++ cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) & ++ IGP02E1000_AGC_LENGTH_MASK; ++ ++ /* Array index bound check. */ ++ if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) || ++ (cur_agc_index == 0)) { ++ ret_val = -E1000_ERR_PHY; ++ goto out; ++ } ++ ++ /* Remove min & max AGC values from calculation. */ ++ if (e1000_igp_2_cable_length_table[min_agc_index] > ++ e1000_igp_2_cable_length_table[cur_agc_index]) ++ min_agc_index = cur_agc_index; ++ if (e1000_igp_2_cable_length_table[max_agc_index] < ++ e1000_igp_2_cable_length_table[cur_agc_index]) ++ max_agc_index = cur_agc_index; ++ ++ agc_value += e1000_igp_2_cable_length_table[cur_agc_index]; ++ } ++ ++ agc_value -= (e1000_igp_2_cable_length_table[min_agc_index] + ++ e1000_igp_2_cable_length_table[max_agc_index]); ++ agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2); ++ ++ /* Calculate cable length with the error range of +/- 10 meters. */ ++ phy->min_cable_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ? ++ (agc_value - IGP02E1000_AGC_RANGE) : 0; ++ phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE; ++ ++ phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; ++ ++out: ++ return ret_val; ++} ++ ++/** ++ * e1000_get_phy_info_m88 - Retrieve PHY information ++ * @hw: pointer to the HW structure ++ * ++ * Valid for only copper links. Read the PHY status register (sticky read) ++ * to verify that link is up. Read the PHY special control register to ++ * determine the polarity and 10base-T extended distance. Read the PHY ++ * special status register to determine MDI/MDIx and current speed. If ++ * speed is 1000, then determine cable length, local and remote receiver. ++ **/ ++s32 e1000_get_phy_info_m88(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ u16 phy_data; ++ bool link; ++ ++ DEBUGFUNC("e1000_get_phy_info_m88"); ++ ++ if (phy->media_type != e1000_media_type_copper) { ++ DEBUGOUT("Phy info is only valid for copper media\n"); ++ ret_val = -E1000_ERR_CONFIG; ++ goto out; ++ } ++ ++ ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); ++ if (ret_val) ++ goto out; ++ ++ if (!link) { ++ DEBUGOUT("Phy info is only valid if link is up\n"); ++ ret_val = -E1000_ERR_CONFIG; ++ goto out; ++ } ++ ++ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); ++ if (ret_val) ++ goto out; ++ ++ phy->polarity_correction = (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) ++ ? true : false; ++ ++ ret_val = e1000_check_polarity_m88(hw); ++ if (ret_val) ++ goto out; ++ ++ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); ++ if (ret_val) ++ goto out; ++ ++ phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX) ? true : false; ++ ++ if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { ++ ret_val = hw->phy.ops.get_cable_length(hw); ++ if (ret_val) ++ goto out; ++ ++ ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); ++ if (ret_val) ++ goto out; ++ ++ phy->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) ++ ? e1000_1000t_rx_status_ok ++ : e1000_1000t_rx_status_not_ok; ++ ++ phy->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) ++ ? e1000_1000t_rx_status_ok ++ : e1000_1000t_rx_status_not_ok; ++ } else { ++ /* Set values to "undefined" */ ++ phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; ++ phy->local_rx = e1000_1000t_rx_status_undefined; ++ phy->remote_rx = e1000_1000t_rx_status_undefined; ++ } ++ ++out: ++ return ret_val; ++} ++ ++/** ++ * e1000_get_phy_info_igp - Retrieve igp PHY information ++ * @hw: pointer to the HW structure ++ * ++ * Read PHY status to determine if link is up. If link is up, then ++ * set/determine 10base-T extended distance and polarity correction. Read ++ * PHY port status to determine MDI/MDIx and speed. Based on the speed, ++ * determine on the cable length, local and remote receiver. ++ **/ ++s32 e1000_get_phy_info_igp(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ u16 data; ++ bool link; ++ ++ DEBUGFUNC("e1000_get_phy_info_igp"); ++ ++ ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); ++ if (ret_val) ++ goto out; ++ ++ if (!link) { ++ DEBUGOUT("Phy info is only valid if link is up\n"); ++ ret_val = -E1000_ERR_CONFIG; ++ goto out; ++ } ++ ++ phy->polarity_correction = true; ++ ++ ret_val = e1000_check_polarity_igp(hw); ++ if (ret_val) ++ goto out; ++ ++ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); ++ if (ret_val) ++ goto out; ++ ++ phy->is_mdix = (data & IGP01E1000_PSSR_MDIX) ? true : false; ++ ++ if ((data & IGP01E1000_PSSR_SPEED_MASK) == ++ IGP01E1000_PSSR_SPEED_1000MBPS) { ++ ret_val = phy->ops.get_cable_length(hw); ++ if (ret_val) ++ goto out; ++ ++ ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data); ++ if (ret_val) ++ goto out; ++ ++ phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS) ++ ? e1000_1000t_rx_status_ok ++ : e1000_1000t_rx_status_not_ok; ++ ++ phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS) ++ ? e1000_1000t_rx_status_ok ++ : e1000_1000t_rx_status_not_ok; ++ } else { ++ phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; ++ phy->local_rx = e1000_1000t_rx_status_undefined; ++ phy->remote_rx = e1000_1000t_rx_status_undefined; ++ } ++ ++out: ++ return ret_val; ++} ++ ++/** ++ * e1000_phy_sw_reset_generic - PHY software reset ++ * @hw: pointer to the HW structure ++ * ++ * Does a software reset of the PHY by reading the PHY control register and ++ * setting/write the control register reset bit to the PHY. ++ **/ ++s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw) ++{ ++ s32 ret_val = E1000_SUCCESS; ++ u16 phy_ctrl; ++ ++ DEBUGFUNC("e1000_phy_sw_reset_generic"); ++ ++ if (!(hw->phy.ops.read_reg)) ++ goto out; ++ ++ ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); ++ if (ret_val) ++ goto out; ++ ++ phy_ctrl |= MII_CR_RESET; ++ ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl); ++ if (ret_val) ++ goto out; ++ ++ usec_delay(1); ++ ++out: ++ return ret_val; ++} ++ ++/** ++ * e1000_phy_hw_reset_generic - PHY hardware reset ++ * @hw: pointer to the HW structure ++ * ++ * Verify the reset block is not blocking us from resetting. Acquire ++ * semaphore (if necessary) and read/set/write the device control reset ++ * bit in the PHY. Wait the appropriate delay time for the device to ++ * reset and release the semaphore (if necessary). ++ **/ ++s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val = E1000_SUCCESS; ++ u32 ctrl; ++ ++ DEBUGFUNC("e1000_phy_hw_reset_generic"); ++ ++ ret_val = phy->ops.check_reset_block(hw); ++ if (ret_val) { ++ ret_val = E1000_SUCCESS; ++ goto out; ++ } ++ ++ ret_val = phy->ops.acquire(hw); ++ if (ret_val) ++ goto out; ++ ++ ctrl = E1000_READ_REG(hw, E1000_CTRL); ++ E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PHY_RST); ++ E1000_WRITE_FLUSH(hw); ++ ++ usec_delay(phy->reset_delay_us); ++ ++ E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ++ E1000_WRITE_FLUSH(hw); ++ ++ usec_delay(150); ++ ++ phy->ops.release(hw); ++ ++ ret_val = phy->ops.get_cfg_done(hw); ++ ++out: ++ return ret_val; ++} ++ ++/** ++ * e1000_get_cfg_done_generic - Generic configuration done ++ * @hw: pointer to the HW structure ++ * ++ * Generic function to wait 10 milli-seconds for configuration to complete ++ * and return success. ++ **/ ++s32 e1000_get_cfg_done_generic(struct e1000_hw *hw) ++{ ++ DEBUGFUNC("e1000_get_cfg_done_generic"); ++ ++ msec_delay_irq(10); ++ ++ return E1000_SUCCESS; ++} ++ ++/** ++ * e1000_phy_init_script_igp3 - Inits the IGP3 PHY ++ * @hw: pointer to the HW structure ++ * ++ * Initializes a Intel Gigabit PHY3 when an EEPROM is not present. ++ **/ ++s32 e1000_phy_init_script_igp3(struct e1000_hw *hw) ++{ ++ DEBUGOUT("Running IGP 3 PHY init script\n"); ++ ++ /* PHY init IGP 3 */ ++ /* Enable rise/fall, 10-mode work in class-A */ ++ hw->phy.ops.write_reg(hw, 0x2F5B, 0x9018); ++ /* Remove all caps from Replica path filter */ ++ hw->phy.ops.write_reg(hw, 0x2F52, 0x0000); ++ /* Bias trimming for ADC, AFE and Driver (Default) */ ++ hw->phy.ops.write_reg(hw, 0x2FB1, 0x8B24); ++ /* Increase Hybrid poly bias */ ++ hw->phy.ops.write_reg(hw, 0x2FB2, 0xF8F0); ++ /* Add 4% to Tx amplitude in Gig mode */ ++ hw->phy.ops.write_reg(hw, 0x2010, 0x10B0); ++ /* Disable trimming (TTT) */ ++ hw->phy.ops.write_reg(hw, 0x2011, 0x0000); ++ /* Poly DC correction to 94.6% + 2% for all channels */ ++ hw->phy.ops.write_reg(hw, 0x20DD, 0x249A); ++ /* ABS DC correction to 95.9% */ ++ hw->phy.ops.write_reg(hw, 0x20DE, 0x00D3); ++ /* BG temp curve trim */ ++ hw->phy.ops.write_reg(hw, 0x28B4, 0x04CE); ++ /* Increasing ADC OPAMP stage 1 currents to max */ ++ hw->phy.ops.write_reg(hw, 0x2F70, 0x29E4); ++ /* Force 1000 ( required for enabling PHY regs configuration) */ ++ hw->phy.ops.write_reg(hw, 0x0000, 0x0140); ++ /* Set upd_freq to 6 */ ++ hw->phy.ops.write_reg(hw, 0x1F30, 0x1606); ++ /* Disable NPDFE */ ++ hw->phy.ops.write_reg(hw, 0x1F31, 0xB814); ++ /* Disable adaptive fixed FFE (Default) */ ++ hw->phy.ops.write_reg(hw, 0x1F35, 0x002A); ++ /* Enable FFE hysteresis */ ++ hw->phy.ops.write_reg(hw, 0x1F3E, 0x0067); ++ /* Fixed FFE for short cable lengths */ ++ hw->phy.ops.write_reg(hw, 0x1F54, 0x0065); ++ /* Fixed FFE for medium cable lengths */ ++ hw->phy.ops.write_reg(hw, 0x1F55, 0x002A); ++ /* Fixed FFE for long cable lengths */ ++ hw->phy.ops.write_reg(hw, 0x1F56, 0x002A); ++ /* Enable Adaptive Clip Threshold */ ++ hw->phy.ops.write_reg(hw, 0x1F72, 0x3FB0); ++ /* AHT reset limit to 1 */ ++ hw->phy.ops.write_reg(hw, 0x1F76, 0xC0FF); ++ /* Set AHT master delay to 127 msec */ ++ hw->phy.ops.write_reg(hw, 0x1F77, 0x1DEC); ++ /* Set scan bits for AHT */ ++ hw->phy.ops.write_reg(hw, 0x1F78, 0xF9EF); ++ /* Set AHT Preset bits */ ++ hw->phy.ops.write_reg(hw, 0x1F79, 0x0210); ++ /* Change integ_factor of channel A to 3 */ ++ hw->phy.ops.write_reg(hw, 0x1895, 0x0003); ++ /* Change prop_factor of channels BCD to 8 */ ++ hw->phy.ops.write_reg(hw, 0x1796, 0x0008); ++ /* Change cg_icount + enable integbp for channels BCD */ ++ hw->phy.ops.write_reg(hw, 0x1798, 0xD008); ++ /* ++ * Change cg_icount + enable integbp + change prop_factor_master ++ * to 8 for channel A ++ */ ++ hw->phy.ops.write_reg(hw, 0x1898, 0xD918); ++ /* Disable AHT in Slave mode on channel A */ ++ hw->phy.ops.write_reg(hw, 0x187A, 0x0800); ++ /* ++ * Enable LPLU and disable AN to 1000 in non-D0a states, ++ * Enable SPD+B2B ++ */ ++ hw->phy.ops.write_reg(hw, 0x0019, 0x008D); ++ /* Enable restart AN on an1000_dis change */ ++ hw->phy.ops.write_reg(hw, 0x001B, 0x2080); ++ /* Enable wh_fifo read clock in 10/100 modes */ ++ hw->phy.ops.write_reg(hw, 0x0014, 0x0045); ++ /* Restart AN, Speed selection is 1000 */ ++ hw->phy.ops.write_reg(hw, 0x0000, 0x1340); ++ ++ return E1000_SUCCESS; ++} ++ ++/** ++ * e1000_get_phy_type_from_id - Get PHY type from id ++ * @phy_id: phy_id read from the phy ++ * ++ * Returns the phy type from the id. ++ **/ ++enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id) ++{ ++ enum e1000_phy_type phy_type = e1000_phy_unknown; ++ ++ switch (phy_id) { ++ case M88E1000_I_PHY_ID: ++ case M88E1000_E_PHY_ID: ++ case M88E1111_I_PHY_ID: ++ case M88E1011_I_PHY_ID: ++ phy_type = e1000_phy_m88; ++ break; ++ case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */ ++ phy_type = e1000_phy_igp_2; ++ break; ++ case GG82563_E_PHY_ID: ++ phy_type = e1000_phy_gg82563; ++ break; ++ case IGP03E1000_E_PHY_ID: ++ phy_type = e1000_phy_igp_3; ++ break; ++ case IFE_E_PHY_ID: ++ case IFE_PLUS_E_PHY_ID: ++ case IFE_C_E_PHY_ID: ++ phy_type = e1000_phy_ife; ++ break; ++ default: ++ phy_type = e1000_phy_unknown; ++ break; ++ } ++ return phy_type; ++} ++ ++/** ++ * e1000_determine_phy_address - Determines PHY address. ++ * @hw: pointer to the HW structure ++ * ++ * This uses a trial and error method to loop through possible PHY ++ * addresses. It tests each by reading the PHY ID registers and ++ * checking for a match. ++ **/ ++s32 e1000_determine_phy_address(struct e1000_hw *hw) ++{ ++ s32 ret_val = -E1000_ERR_PHY_TYPE; ++ u32 phy_addr = 0; ++ u32 i; ++ enum e1000_phy_type phy_type = e1000_phy_unknown; ++ ++ hw->phy.id = phy_type; ++ ++ for (phy_addr = 0; phy_addr < E1000_MAX_PHY_ADDR; phy_addr++) { ++ hw->phy.addr = phy_addr; ++ i = 0; ++ ++ do { ++ e1000_get_phy_id(hw); ++ phy_type = e1000_get_phy_type_from_id(hw->phy.id); ++ ++ /* ++ * If phy_type is valid, break - we found our ++ * PHY address ++ */ ++ if (phy_type != e1000_phy_unknown) { ++ ret_val = E1000_SUCCESS; ++ goto out; ++ } ++ msec_delay(1); ++ i++; ++ } while (i < 10); ++ } ++ ++out: ++ return ret_val; ++} ++ ++/** ++ * e1000_power_up_phy_copper - Restore copper link in case of PHY power down ++ * @hw: pointer to the HW structure ++ * ++ * In the case of a PHY power down to save power, or to turn off link during a ++ * driver unload, or wake on lan is not enabled, restore the link to previous ++ * settings. ++ **/ ++void e1000_power_up_phy_copper(struct e1000_hw *hw) ++{ ++ u16 mii_reg = 0; ++ ++ /* The PHY will retain its settings across a power down/up cycle */ ++ hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); ++ mii_reg &= ~MII_CR_POWER_DOWN; ++ hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); ++} ++ ++/** ++ * e1000_power_down_phy_copper - Restore copper link in case of PHY power down ++ * @hw: pointer to the HW structure ++ * ++ * In the case of a PHY power down to save power, or to turn off link during a ++ * driver unload, or wake on lan is not enabled, restore the link to previous ++ * settings. ++ **/ ++void e1000_power_down_phy_copper(struct e1000_hw *hw) ++{ ++ u16 mii_reg = 0; ++ ++ /* The PHY will retain its settings across a power down/up cycle */ ++ hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); ++ mii_reg |= MII_CR_POWER_DOWN; ++ hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); ++ msec_delay(1); ++} +Index: linux-2.6.22/drivers/net/igb/e1000_phy.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/e1000_phy.h 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,163 @@ ++/******************************************************************************* ++ ++ Intel(R) Gigabit Ethernet Linux driver ++ Copyright(c) 2007-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, ++ 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: ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ ++ ++#ifndef _E1000_PHY_H_ ++#define _E1000_PHY_H_ ++ ++void e1000_init_phy_ops_generic(struct e1000_hw *hw); ++s32 e1000_check_downshift_generic(struct e1000_hw *hw); ++s32 e1000_check_polarity_m88(struct e1000_hw *hw); ++s32 e1000_check_polarity_igp(struct e1000_hw *hw); ++s32 e1000_check_polarity_ife(struct e1000_hw *hw); ++s32 e1000_check_reset_block_generic(struct e1000_hw *hw); ++s32 e1000_copper_link_autoneg(struct e1000_hw *hw); ++s32 e1000_copper_link_setup_igp(struct e1000_hw *hw); ++s32 e1000_copper_link_setup_m88(struct e1000_hw *hw); ++s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw); ++s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw); ++s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw); ++s32 e1000_get_cable_length_m88(struct e1000_hw *hw); ++s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw); ++s32 e1000_get_cfg_done_generic(struct e1000_hw *hw); ++s32 e1000_get_phy_id(struct e1000_hw *hw); ++s32 e1000_get_phy_info_igp(struct e1000_hw *hw); ++s32 e1000_get_phy_info_m88(struct e1000_hw *hw); ++s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw); ++void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); ++s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw); ++s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw); ++s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active); ++s32 e1000_setup_copper_link_generic(struct e1000_hw *hw); ++s32 e1000_wait_autoneg_generic(struct e1000_hw *hw); ++s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000_phy_reset_dsp(struct e1000_hw *hw); ++s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, ++ u32 usec_interval, bool *success); ++s32 e1000_phy_init_script_igp3(struct e1000_hw *hw); ++enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id); ++s32 e1000_determine_phy_address(struct e1000_hw *hw); ++void e1000_power_up_phy_copper(struct e1000_hw *hw); ++void e1000_power_down_phy_copper(struct e1000_hw *hw); ++s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data); ++ ++#define E1000_MAX_PHY_ADDR 4 ++ ++/* IGP01E1000 Specific Registers */ ++#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */ ++#define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */ ++#define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */ ++#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */ ++#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO */ ++#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality */ ++#define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */ ++#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */ ++#define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */ ++#define IGP_PAGE_SHIFT 5 ++#define PHY_REG_MASK 0x1F ++ ++#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 ++#define IGP01E1000_PHY_POLARITY_MASK 0x0078 ++ ++#define IGP01E1000_PSCR_AUTO_MDIX 0x1000 ++#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */ ++ ++#define IGP01E1000_PSCFR_SMART_SPEED 0x0080 ++ ++/* Enable flexible speed on link-up */ ++#define IGP01E1000_GMII_FLEX_SPD 0x0010 ++#define IGP01E1000_GMII_SPD 0x0020 /* Enable SPD */ ++ ++#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */ ++#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */ ++#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */ ++ ++#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 ++ ++#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 ++#define IGP01E1000_PSSR_MDIX 0x0800 ++#define IGP01E1000_PSSR_SPEED_MASK 0xC000 ++#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 ++ ++#define IGP02E1000_PHY_CHANNEL_NUM 4 ++#define IGP02E1000_PHY_AGC_A 0x11B1 ++#define IGP02E1000_PHY_AGC_B 0x12B1 ++#define IGP02E1000_PHY_AGC_C 0x14B1 ++#define IGP02E1000_PHY_AGC_D 0x18B1 ++ ++#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course - 15:13, Fine - 12:9 */ ++#define IGP02E1000_AGC_LENGTH_MASK 0x7F ++#define IGP02E1000_AGC_RANGE 15 ++ ++#define IGP03E1000_PHY_MISC_CTRL 0x1B ++#define IGP03E1000_PHY_MISC_DUPLEX_MANUAL_SET 0x1000 /* Manually Set Duplex */ ++ ++#define E1000_CABLE_LENGTH_UNDEFINED 0xFF ++ ++#define E1000_KMRNCTRLSTA_OFFSET 0x001F0000 ++#define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16 ++#define E1000_KMRNCTRLSTA_REN 0x00200000 ++#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ ++#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */ ++#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */ ++#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ ++ ++#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 ++#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */ ++#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Control */ ++#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */ ++ ++/* IFE PHY Extended Status Control */ ++#define IFE_PESC_POLARITY_REVERSED 0x0100 ++ ++/* IFE PHY Special Control */ ++#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 ++#define IFE_PSC_FORCE_POLARITY 0x0020 ++#define IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN 0x0100 ++ ++/* IFE PHY Special Control and LED Control */ ++#define IFE_PSCL_PROBE_MODE 0x0020 ++#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */ ++#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */ ++ ++/* IFE PHY MDIX Control */ ++#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */ ++#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDI-X, 0=force MDI */ ++#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable auto MDI/MDI-X, 0=disable */ ++ ++#endif +Index: linux-2.6.22/drivers/net/igb/e1000_regs.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/e1000_regs.h 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,484 @@ ++/******************************************************************************* ++ ++ Intel(R) Gigabit Ethernet Linux driver ++ Copyright(c) 2007-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, ++ 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: ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ ++ ++#ifndef _E1000_REGS_H_ ++#define _E1000_REGS_H_ ++ ++#define E1000_CTRL 0x00000 /* Device Control - RW */ ++#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */ ++#define E1000_STATUS 0x00008 /* Device Status - RO */ ++#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ ++#define E1000_EERD 0x00014 /* EEPROM Read - RW */ ++#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ ++#define E1000_FLA 0x0001C /* Flash Access - RW */ ++#define E1000_MDIC 0x00020 /* MDI Control - RW */ ++#define E1000_SCTL 0x00024 /* SerDes Control - RW */ ++#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ ++#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ ++#define E1000_FEXT 0x0002C /* Future Extended - RW */ ++#define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */ ++#define E1000_FCT 0x00030 /* Flow Control Type - RW */ ++#define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */ ++#define E1000_VET 0x00038 /* VLAN Ether Type - RW */ ++#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */ ++#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */ ++#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */ ++#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */ ++#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */ ++#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */ ++#define E1000_RCTL 0x00100 /* Rx Control - RW */ ++#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ ++#define E1000_TXCW 0x00178 /* Tx Configuration Word - RW */ ++#define E1000_RXCW 0x00180 /* Rx Configuration Word - RO */ ++#define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */ ++#define E1000_EITR(_n) (0x01680 + (0x4 * (_n))) ++#define E1000_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */ ++#define E1000_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */ ++#define E1000_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */ ++#define E1000_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */ ++#define E1000_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */ ++#define E1000_GPIE 0x01514 /* General Purpose Interrupt Enable - RW */ ++#define E1000_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */ ++#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */ ++#define E1000_TCTL 0x00400 /* Tx Control - RW */ ++#define E1000_TCTL_EXT 0x00404 /* Extended Tx Control - RW */ ++#define E1000_TIPG 0x00410 /* Tx Inter-packet gap -RW */ ++#define E1000_TBT 0x00448 /* Tx Burst Timer - RW */ ++#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */ ++#define E1000_LEDCTL 0x00E00 /* LED Control - RW */ ++#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */ ++#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */ ++#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */ ++#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ ++#define E1000_PBS 0x01008 /* Packet Buffer Size */ ++#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ ++#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */ ++#define E1000_FLASHT 0x01028 /* FLASH Timer Register */ ++#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */ ++#define E1000_FLSWCTL 0x01030 /* FLASH control register */ ++#define E1000_FLSWDATA 0x01034 /* FLASH data register */ ++#define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */ ++#define E1000_FLOP 0x0103C /* FLASH Opcode Register */ ++#define E1000_I2CCMD 0x01028 /* SFPI2C Command Register - RW */ ++#define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */ ++#define E1000_WDSTP 0x01040 /* Watchdog Setup - RW */ ++#define E1000_SWDSTS 0x01044 /* SW Device Status - RW */ ++#define E1000_FRTIMER 0x01048 /* Free Running Timer - RW */ ++#define E1000_TCPTIMER 0x0104C /* TCP Timer - RW */ ++#define E1000_VPDDIAG 0x01060 /* VPD Diagnostic - RO */ ++#define E1000_ICR_V2 0x01500 /* Interrupt Cause - new location - RC */ ++#define E1000_ICS_V2 0x01504 /* Interrupt Cause Set - new location - WO */ ++#define E1000_IMS_V2 0x01508 /* Interrupt Mask Set/Read - new location - RW */ ++#define E1000_IMC_V2 0x0150C /* Interrupt Mask Clear - new location - WO */ ++#define E1000_IAM_V2 0x01510 /* Interrupt Ack Auto Mask - new location - RW */ ++#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */ ++#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ ++#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ ++#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */ ++#define E1000_RDFPCQ(_n) (0x02430 + (0x4 * (_n))) ++#define E1000_PBRTH 0x02458 /* PB Rx Arbitration Threshold - RW */ ++#define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */ ++/* Split and Replication Rx Control - RW */ ++#define E1000_RDPUMB 0x025CC /* DMA Rx Descriptor uC Mailbox - RW */ ++#define E1000_RDPUAD 0x025D0 /* DMA Rx Descriptor uC Addr Command - RW */ ++#define E1000_RDPUWD 0x025D4 /* DMA Rx Descriptor uC Data Write - RW */ ++#define E1000_RDPURD 0x025D8 /* DMA Rx Descriptor uC Data Read - RW */ ++#define E1000_RDPUCTL 0x025DC /* DMA Rx Descriptor uC Control - RW */ ++#define E1000_PBDIAG 0x02458 /* Packet Buffer Diagnostic - RW */ ++#define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */ ++#define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */ ++#define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */ ++/* ++ * Convenience macros ++ * ++ * Note: "_n" is the queue number of the register to be written to. ++ * ++ * Example usage: ++ * E1000_RDBAL_REG(current_rx_queue) ++ */ ++#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \ ++ (0x0C000 + ((_n) * 0x40))) ++#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \ ++ (0x0C004 + ((_n) * 0x40))) ++#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \ ++ (0x0C008 + ((_n) * 0x40))) ++#define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : \ ++ (0x0C00C + ((_n) * 0x40))) ++#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \ ++ (0x0C010 + ((_n) * 0x40))) ++#define E1000_RXCTL(_n) ((_n) < 4 ? (0x02814 + ((_n) * 0x100)) : \ ++ (0x0C014 + ((_n) * 0x40))) ++#define E1000_DCA_RXCTRL(_n) E1000_RXCTL(_n) ++#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \ ++ (0x0C018 + ((_n) * 0x40))) ++#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \ ++ (0x0C028 + ((_n) * 0x40))) ++#define E1000_RQDPC(_n) ((_n) < 4 ? (0x02830 + ((_n) * 0x100)) : \ ++ (0x0C030 + ((_n) * 0x40))) ++#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \ ++ (0x0E000 + ((_n) * 0x40))) ++#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \ ++ (0x0E004 + ((_n) * 0x40))) ++#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \ ++ (0x0E008 + ((_n) * 0x40))) ++#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \ ++ (0x0E010 + ((_n) * 0x40))) ++#define E1000_TXCTL(_n) ((_n) < 4 ? (0x03814 + ((_n) * 0x100)) : \ ++ (0x0E014 + ((_n) * 0x40))) ++#define E1000_DCA_TXCTRL(_n) E1000_TXCTL(_n) ++#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \ ++ (0x0E018 + ((_n) * 0x40))) ++#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \ ++ (0x0E028 + ((_n) * 0x40))) ++#define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) : \ ++ (0x0E038 + ((_n) * 0x40))) ++#define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) : \ ++ (0x0E03C + ((_n) * 0x40))) ++#define E1000_TARC(_n) (0x03840 + ((_n) * 0x100)) ++#define E1000_RSRPD 0x02C00 /* Rx Small Packet Detect - RW */ ++#define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */ ++#define E1000_TXDMAC 0x03000 /* Tx DMA Control - RW */ ++#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */ ++#define E1000_PSRTYPE(_i) (0x05480 + ((_i) * 4)) ++#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \ ++ (0x054E0 + ((_i - 16) * 8))) ++#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \ ++ (0x054E4 + ((_i - 16) * 8))) ++#define E1000_IP4AT_REG(_i) (0x05840 + ((_i) * 8)) ++#define E1000_IP6AT_REG(_i) (0x05880 + ((_i) * 4)) ++#define E1000_WUPM_REG(_i) (0x05A00 + ((_i) * 4)) ++#define E1000_FFMT_REG(_i) (0x09000 + ((_i) * 8)) ++#define E1000_FFVT_REG(_i) (0x09800 + ((_i) * 8)) ++#define E1000_FFLT_REG(_i) (0x05F00 + ((_i) * 8)) ++#define E1000_PBSLAC 0x03100 /* Packet Buffer Slave Access Control */ ++#define E1000_PBSLAD(_n) (0x03110 + (0x4 * (_n))) /* Packet Buffer DWORD (_n) */ ++#define E1000_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */ ++#define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */ ++#define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */ ++#define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */ ++#define E1000_TDFTS 0x03428 /* Tx Data FIFO Tail Saved - RW */ ++#define E1000_TDFPC 0x03430 /* Tx Data FIFO Packet Count - RW */ ++#define E1000_TDPUMB 0x0357C /* DMA Tx Descriptor uC Mail Box - RW */ ++#define E1000_TDPUAD 0x03580 /* DMA Tx Descriptor uC Addr Command - RW */ ++#define E1000_TDPUWD 0x03584 /* DMA Tx Descriptor uC Data Write - RW */ ++#define E1000_TDPURD 0x03588 /* DMA Tx Descriptor uC Data Read - RW */ ++#define E1000_TDPUCTL 0x0358C /* DMA Tx Descriptor uC Control - RW */ ++#define E1000_DTXCTL 0x03590 /* DMA Tx Control - RW */ ++#define E1000_DTXTCPFLGL 0x0359C /* DMA Tx Control flag low - RW */ ++#define E1000_DTXTCPFLGH 0x035A0 /* DMA Tx Control flag high - RW */ ++#define E1000_DTXMXSZRQ 0x03540 /* DMA Tx Max Total Allow Size Requests - RW */ ++#define E1000_TIDV 0x03820 /* Tx Interrupt Delay Value - RW */ ++#define E1000_TADV 0x0382C /* Tx Interrupt Absolute Delay Val - RW */ ++#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */ ++#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */ ++#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ ++#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */ ++#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */ ++#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */ ++#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */ ++#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */ ++#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */ ++#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */ ++#define E1000_COLC 0x04028 /* Collision Count - R/clr */ ++#define E1000_DC 0x04030 /* Defer Count - R/clr */ ++#define E1000_TNCRS 0x04034 /* Tx-No CRS - R/clr */ ++#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */ ++#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */ ++#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */ ++#define E1000_XONRXC 0x04048 /* XON Rx Count - R/clr */ ++#define E1000_XONTXC 0x0404C /* XON Tx Count - R/clr */ ++#define E1000_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */ ++#define E1000_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */ ++#define E1000_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */ ++#define E1000_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */ ++#define E1000_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */ ++#define E1000_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */ ++#define E1000_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */ ++#define E1000_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */ ++#define E1000_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */ ++#define E1000_GPRC 0x04074 /* Good Packets Rx Count - R/clr */ ++#define E1000_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */ ++#define E1000_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */ ++#define E1000_GPTC 0x04080 /* Good Packets Tx Count - R/clr */ ++#define E1000_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */ ++#define E1000_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */ ++#define E1000_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */ ++#define E1000_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */ ++#define E1000_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */ ++#define E1000_RUC 0x040A4 /* Rx Undersize Count - R/clr */ ++#define E1000_RFC 0x040A8 /* Rx Fragment Count - R/clr */ ++#define E1000_ROC 0x040AC /* Rx Oversize Count - R/clr */ ++#define E1000_RJC 0x040B0 /* Rx Jabber Count - R/clr */ ++#define E1000_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */ ++#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */ ++#define E1000_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */ ++#define E1000_TORL 0x040C0 /* Total Octets Rx Low - R/clr */ ++#define E1000_TORH 0x040C4 /* Total Octets Rx High - R/clr */ ++#define E1000_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */ ++#define E1000_TOTH 0x040CC /* Total Octets Tx High - R/clr */ ++#define E1000_TPR 0x040D0 /* Total Packets Rx - R/clr */ ++#define E1000_TPT 0x040D4 /* Total Packets Tx - R/clr */ ++#define E1000_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */ ++#define E1000_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */ ++#define E1000_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */ ++#define E1000_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */ ++#define E1000_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */ ++#define E1000_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */ ++#define E1000_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */ ++#define E1000_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */ ++#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */ ++#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context Tx Fail - R/clr */ ++#define E1000_IAC 0x04100 /* Interrupt Assertion Count */ ++#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Pkt Timer Expire Count */ ++#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Abs Timer Expire Count */ ++#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Pkt Timer Expire Count */ ++#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Abs Timer Expire Count */ ++#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */ ++#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Min Thresh Count */ ++#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Desc Min Thresh Count */ ++#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */ ++ ++#define E1000_LSECTXUT 0x04300 /* LinkSec Tx Untagged Packet Count - OutPktsUntagged */ ++#define E1000_LSECTXPKTE 0x04304 /* LinkSec Encrypted Tx Packets Count - OutPktsEncrypted */ ++#define E1000_LSECTXPKTP 0x04308 /* LinkSec Protected Tx Packet Count - OutPktsProtected */ ++#define E1000_LSECTXOCTE 0x0430C /* LinkSec Encrypted Tx Octets Count - OutOctetsEncrypted */ ++#define E1000_LSECTXOCTP 0x04310 /* LinkSec Protected Tx Octets Count - OutOctetsProtected */ ++#define E1000_LSECRXUT 0x04314 /* LinkSec Untagged non-Strict Rx Packet Count - InPktsUntagged/InPktsNoTag */ ++#define E1000_LSECRXOCTD 0x0431C /* LinkSec Rx Octets Decrypted Count - InOctetsDecrypted */ ++#define E1000_LSECRXOCTV 0x04320 /* LinkSec Rx Octets Validated - InOctetsValidated */ ++#define E1000_LSECRXBAD 0x04324 /* LinkSec Rx Bad Tag - InPktsBadTag */ ++#define E1000_LSECRXNOSCI 0x04328 /* LinkSec Rx Packet No SCI Count - InPktsNoSci */ ++#define E1000_LSECRXUNSCI 0x0432C /* LinkSec Rx Packet Unknown SCI Count - InPktsUnknownSci */ ++#define E1000_LSECRXUNCH 0x04330 /* LinkSec Rx Unchecked Packets Count - InPktsUnchecked */ ++#define E1000_LSECRXDELAY 0x04340 /* LinkSec Rx Delayed Packet Count - InPktsDelayed */ ++#define E1000_LSECRXLATE 0x04350 /* LinkSec Rx Late Packets Count - InPktsLate */ ++#define E1000_LSECRXOK(_n) (0x04360 + (0x04 * (_n))) /* LinkSec Rx Packet OK Count - InPktsOk */ ++#define E1000_LSECRXINV(_n) (0x04380 + (0x04 * (_n))) /* LinkSec Rx Invalid Count - InPktsInvalid */ ++#define E1000_LSECRXNV(_n) (0x043A0 + (0x04 * (_n))) /* LinkSec Rx Not Valid Count - InPktsNotValid */ ++#define E1000_LSECRXUNSA 0x043C0 /* LinkSec Rx Unused SA Count - InPktsUnusedSa */ ++#define E1000_LSECRXNUSA 0x043D0 /* LinkSec Rx Not Using SA Count - InPktsNotUsingSa */ ++#define E1000_LSECTXCAP 0x0B000 /* LinkSec Tx Capabilities Register - RO */ ++#define E1000_LSECRXCAP 0x0B300 /* LinkSec Rx Capabilities Register - RO */ ++#define E1000_LSECTXCTRL 0x0B004 /* LinkSec Tx Control - RW */ ++#define E1000_LSECRXCTRL 0x0B304 /* LinkSec Rx Control - RW */ ++#define E1000_LSECTXSCL 0x0B008 /* LinkSec Tx SCI Low - RW */ ++#define E1000_LSECTXSCH 0x0B00C /* LinkSec Tx SCI High - RW */ ++#define E1000_LSECTXSA 0x0B010 /* LinkSec Tx SA0 - RW */ ++#define E1000_LSECTXPN0 0x0B018 /* LinkSec Tx SA PN 0 - RW */ ++#define E1000_LSECTXPN1 0x0B01C /* LinkSec Tx SA PN 1 - RW */ ++#define E1000_LSECRXSCL 0x0B3D0 /* LinkSec Rx SCI Low - RW */ ++#define E1000_LSECRXSCH 0x0B3E0 /* LinkSec Rx SCI High - RW */ ++#define E1000_LSECTXKEY0(_n) (0x0B020 + (0x04 * (_n))) /* LinkSec Tx 128-bit Key 0 - WO */ ++#define E1000_LSECTXKEY1(_n) (0x0B030 + (0x04 * (_n))) /* LinkSec Tx 128-bit Key 1 - WO */ ++#define E1000_LSECRXSA(_n) (0x0B310 + (0x04 * (_n))) /* LinkSec Rx SAs - RW */ ++#define E1000_LSECRXPN(_n) (0x0B330 + (0x04 * (_n))) /* LinkSec Rx SAs - RW */ ++/* ++ * LinkSec Rx Keys - where _n is the SA no. and _m the 4 dwords of the 128 bit ++ * key - RW. ++ */ ++#define E1000_LSECRXKEY(_n, _m) (0x0B350 + (0x10 * (_n)) + (0x04 * (_m))) ++ ++#define E1000_SSVPC 0x041A0 /* Switch Security Violation Packet Count */ ++#define E1000_IPSCTRL 0xB430 /* IpSec Control Register */ ++#define E1000_IPSRXCMD 0x0B408 /* IPSec Rx Command Register - RW */ ++#define E1000_IPSRXIDX 0x0B400 /* IPSec Rx Index - RW */ ++#define E1000_IPSRXIPADDR(_n) (0x0B420+ (0x04 * (_n))) /* IPSec Rx IPv4/v6 Address - RW */ ++#define E1000_IPSRXKEY(_n) (0x0B410 + (0x04 * (_n))) /* IPSec Rx 128-bit Key - RW */ ++#define E1000_IPSRXSALT 0x0B404 /* IPSec Rx Salt - RW */ ++#define E1000_IPSRXSPI 0x0B40C /* IPSec Rx SPI - RW */ ++#define E1000_IPSTXKEY(_n) (0x0B460 + (0x04 * (_n))) /* IPSec Tx 128-bit Key - RW */ ++#define E1000_IPSTXSALT 0x0B454 /* IPSec Tx Salt - RW */ ++#define E1000_IPSTXIDX 0x0B450 /* IPSec Tx SA IDX - RW */ ++#define E1000_PCS_CFG0 0x04200 /* PCS Configuration 0 - RW */ ++#define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */ ++#define E1000_PCS_LSTAT 0x0420C /* PCS Link Status - RO */ ++#define E1000_CBTMPC 0x0402C /* Circuit Breaker Tx Packet Count */ ++#define E1000_HTDPMC 0x0403C /* Host Transmit Discarded Packets */ ++#define E1000_CBRDPC 0x04044 /* Circuit Breaker Rx Dropped Count */ ++#define E1000_CBRMPC 0x040FC /* Circuit Breaker Rx Packet Count */ ++#define E1000_RPTHC 0x04104 /* Rx Packets To Host */ ++#define E1000_HGPTC 0x04118 /* Host Good Packets Tx Count */ ++#define E1000_HTCBDPC 0x04124 /* Host Tx Circuit Breaker Dropped Count */ ++#define E1000_HGORCL 0x04128 /* Host Good Octets Received Count Low */ ++#define E1000_HGORCH 0x0412C /* Host Good Octets Received Count High */ ++#define E1000_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */ ++#define E1000_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */ ++#define E1000_LENERRS 0x04138 /* Length Errors Count */ ++#define E1000_SCVPC 0x04228 /* SerDes/SGMII Code Violation Pkt Count */ ++#define E1000_HRMPC 0x0A018 /* Header Redirection Missed Packet Count */ ++#define E1000_PCS_ANADV 0x04218 /* AN advertisement - RW */ ++#define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */ ++#define E1000_PCS_NPTX 0x04220 /* AN Next Page Transmit - RW */ ++#define E1000_PCS_LPABNP 0x04224 /* Link Partner Ability Next Page - RW */ ++#define E1000_1GSTAT_RCV 0x04228 /* 1GSTAT Code Violation Packet Count - RW */ ++#define E1000_RXCSUM 0x05000 /* Rx Checksum Control - RW */ ++#define E1000_RLPML 0x05004 /* Rx Long Packet Max Length */ ++#define E1000_RFCTL 0x05008 /* Receive Filter Control*/ ++#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */ ++#define E1000_RA 0x05400 /* Receive Address - RW Array */ ++#define E1000_RA2 0x054E0 /* 2nd half of receive address array - RW Array */ ++#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */ ++#define E1000_VT_CTL 0x0581C /* VMDq Control - RW */ ++#define E1000_VFQA0 0x0B000 /* VLAN Filter Queue Array 0 - RW Array */ ++#define E1000_VFQA1 0x0B200 /* VLAN Filter Queue Array 1 - RW Array */ ++#define E1000_WUC 0x05800 /* Wakeup Control - RW */ ++#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */ ++#define E1000_WUS 0x05810 /* Wakeup Status - RO */ ++#define E1000_MANC 0x05820 /* Management Control - RW */ ++#define E1000_IPAV 0x05838 /* IP Address Valid - RW */ ++#define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */ ++#define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */ ++#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */ ++#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */ ++#define E1000_PBACL 0x05B68 /* MSIx PBA Clear - Read/Write 1's to clear */ ++#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */ ++#define E1000_HOST_IF 0x08800 /* Host Interface */ ++#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */ ++#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */ ++#define E1000_FHFT(_n) (0x09000 + (_n * 0x100)) /* Flexible Host Filter Table */ ++#define E1000_FHFT_EXT(_n) (0x09A00 + (_n * 0x100)) /* Ext Flexible Host Filter Table */ ++ ++ ++#define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */ ++#define E1000_MDPHYA 0x0003C /* PHY address - RW */ ++#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */ ++#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */ ++#define E1000_CCMCTL 0x05B48 /* CCM Control Register */ ++#define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */ ++#define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */ ++#define E1000_GCR 0x05B00 /* PCI-Ex Control */ ++#define E1000_GCR2 0x05B64 /* PCI-Ex Control #2 */ ++#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */ ++#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */ ++#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */ ++#define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */ ++#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */ ++#define E1000_SWSM 0x05B50 /* SW Semaphore */ ++#define E1000_FWSM 0x05B54 /* FW Semaphore */ ++#define E1000_SWSM2 0x05B58 /* Driver-only SW semaphore (not used by BOOT agents) */ ++#define E1000_DCA_ID 0x05B70 /* DCA Requester ID Information - RO */ ++#define E1000_DCA_CTRL 0x05B74 /* DCA Control - RW */ ++#define E1000_FFLT_DBG 0x05F04 /* Debug Register */ ++#define E1000_HICR 0x08F00 /* Host Interface Control */ ++ ++/* RSS registers */ ++#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */ ++#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */ ++#define E1000_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */ ++#define E1000_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate Interrupt Ext*/ ++#define E1000_IMIRVP 0x05AC0 /* Immediate Interrupt Rx VLAN Priority - RW */ ++#define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4)) /* MSI-X Allocation Register ++ * (_i) - RW */ ++#define E1000_MSIXTADD(_i) (0x0C000 + ((_i) * 0x10)) /* MSI-X Table entry addr ++ * low reg - RW */ ++#define E1000_MSIXTUADD(_i) (0x0C004 + ((_i) * 0x10)) /* MSI-X Table entry addr ++ * upper reg - RW */ ++#define E1000_MSIXTMSG(_i) (0x0C008 + ((_i) * 0x10)) /* MSI-X Table entry ++ * message reg - RW */ ++#define E1000_MSIXVCTRL(_i) (0x0C00C + ((_i) * 0x10)) /* MSI-X Table entry ++ * vector ctrl reg - RW */ ++#define E1000_MSIXPBA 0x0E000 /* MSI-X Pending bit array */ ++#define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW */ ++#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW */ ++#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */ ++#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */ ++/* VT Registers */ ++#define E1000_SWPBS 0x03004 /* Switch Packet Buffer Size - RW */ ++#define E1000_MBVFICR 0x00C80 /* Mailbox VF Cause - RWC */ ++#define E1000_MBVFIMR 0x00C84 /* Mailbox VF int Mask - RW */ ++#define E1000_VFLRE 0x00C88 /* VF Register Events - RWC */ ++#define E1000_VFRE 0x00C8C /* VF Receive Enables */ ++#define E1000_VFTE 0x00C90 /* VF Transmit Enables */ ++#define E1000_QDE 0x02408 /* Queue Drop Enable - RW */ ++#define E1000_DTXSWC 0x03500 /* DMA Tx Switch Control - RW */ ++#define E1000_RPLOLR 0x05AF0 /* Replication Offload - RW */ ++#define E1000_UTA 0x0A000 /* Unicast Table Array - RW */ ++#define E1000_IOVTCL 0x05BBC /* IOV Control Register */ ++#define E1000_VMRCTL 0X05D80 /* Virtual Mirror Rule Control */ ++/* These act per VF so an array friendly macro is used */ ++#define E1000_V2PMAILBOX(_n) (0x00C40 + (4 * (_n))) ++#define E1000_P2VMAILBOX(_n) (0x00C00 + (4 * (_n))) ++#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n))) ++#define E1000_VFVMBMEM(_n) (0x00800 + (_n)) ++#define E1000_VMOLR(_n) (0x05AD0 + (4 * (_n))) ++#define E1000_VLVF(_n) (0x05D00 + (4 * (_n))) /* VLAN Virtual Machine ++ * Filter - RW */ ++/* Time Sync */ ++#define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */ ++#define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */ ++#define E1000_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */ ++#define E1000_RXSTMPL 0x0B624 /* Rx timestamp Low - RO */ ++#define E1000_RXSTMPH 0x0B628 /* Rx timestamp High - RO */ ++#define E1000_RXSATRL 0x0B62C /* Rx timestamp attribute low - RO */ ++#define E1000_RXSATRH 0x0B630 /* Rx timestamp attribute high - RO */ ++#define E1000_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */ ++#define E1000_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */ ++#define E1000_SYSTIML 0x0B600 /* System time register Low - RO */ ++#define E1000_SYSTIMH 0x0B604 /* System time register High - RO */ ++#define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */ ++ ++/* Filtering Registers */ ++#define E1000_SAQF(_n) (0x05980 + (4 * (_n))) /* Source Address Queue Fltr */ ++#define E1000_DAQF(_n) (0x059A0 + (4 * (_n))) /* Dest Address Queue Fltr */ ++#define E1000_SPQF(_n) (0x059C0 + (4 * (_n))) /* Source Port Queue Fltr */ ++#define E1000_FTQF(_n) (0x059E0 + (4 * (_n))) /* 5-tuple Queue Fltr */ ++#define E1000_TTQF(_n) (0x059E0 + (4 * (_n))) /* 2-tuple Queue Fltr */ ++#define E1000_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */ ++#define E1000_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */ ++ ++#define E1000_RTTDCS 0x3600 /* Reedtown Tx Desc plane control and status */ ++#define E1000_RTTPCS 0x3474 /* Reedtown Tx Packet Plane control and status */ ++#define E1000_RTRPCS 0x2474 /* Rx packet plane control and status */ ++#define E1000_RTRUP2TC 0x05AC4 /* Rx User Priority to Traffic Class */ ++#define E1000_RTTUP2TC 0x0418 /* Transmit User Priority to Traffic Class */ ++#define E1000_RTTDTCRC(_n) (0x3610 + ((_n) * 4)) /* Tx Desc plane TC Rate-scheduler config */ ++#define E1000_RTTPTCRC(_n) (0x3480 + ((_n) * 4)) /* Tx Packet plane TC Rate-Scheduler Config */ ++#define E1000_RTRPTCRC(_n) (0x2480 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler Config */ ++#define E1000_RTTDTCRS(_n) (0x3630 + ((_n) * 4)) /* Tx Desc Plane TC Rate-Scheduler Status */ ++#define E1000_RTTDTCRM(_n) (0x3650 + ((_n) * 4)) /* Tx Desc Plane TC Rate-Scheduler MMW */ ++#define E1000_RTTPTCRS(_n) (0x34A0 + ((_n) * 4)) /* Tx Packet plane TC Rate-Scheduler Status */ ++#define E1000_RTTPTCRM(_n) (0x34C0 + ((_n) * 4)) /* Tx Packet plane TC Rate-scheduler MMW */ ++#define E1000_RTRPTCRS(_n) (0x24A0 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler Status */ ++#define E1000_RTRPTCRM(_n) (0x24C0 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler MMW */ ++#define E1000_RTTDVMRM(_n) (0x3670 + ((_n) * 4)) /* Tx Desc plane VM Rate-Scheduler MMW*/ ++#define E1000_RTTBCNRM(_n) (0x3690 + ((_n) * 4)) /* Tx BCN Rate-Scheduler MMW */ ++#define E1000_RTTDQSEL 0x3604 /* Tx Desc Plane Queue Select */ ++#define E1000_RTTDVMRC 0x3608 /* Tx Desc Plane VM Rate-Scheduler Config */ ++#define E1000_RTTDVMRS 0x360C /* Tx Desc Plane VM Rate-Scheduler Status */ ++#define E1000_RTTBCNRC 0x36B0 /* Tx BCN Rate-Scheduler Config */ ++#define E1000_RTTBCNRS 0x36B4 /* Tx BCN Rate-Scheduler Status */ ++#define E1000_RTTBCNCR 0xB200 /* Tx BCN Control Register */ ++#define E1000_RTTBCNTG 0x35A4 /* Tx BCN Tagging */ ++#define E1000_RTTBCNCP 0xB208 /* Tx BCN Congestion point */ ++#define E1000_RTRBCNCR 0xB20C /* Rx BCN Control Register */ ++#define E1000_RTTBCNRD 0x36B8 /* Tx BCN Rate Drift */ ++#define E1000_PFCTOP 0x1080 /* Priority Flow Control Type and Opcode */ ++#define E1000_RTTBCNIDX 0xB204 /* Tx BCN Congestion Point */ ++#define E1000_RTTBCNACH 0x0B214 /* Tx BCN Control High */ ++#define E1000_RTTBCNACL 0x0B210 /* Tx BCN Control Low */ ++ ++#endif +Index: linux-2.6.22/drivers/net/igb/igb.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/igb.h 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,444 @@ ++/******************************************************************************* ++ ++ Intel(R) Gigabit Ethernet Linux driver ++ Copyright(c) 2007-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, ++ 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: ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ ++ ++ ++/* Linux PRO/1000 Ethernet Driver main header file */ ++ ++#ifndef _IGB_H_ ++#define _IGB_H_ ++ ++#include ++#include ++#include ++ ++#ifdef SIOCETHTOOL ++#include ++#endif ++ ++#ifdef SIOCSHWTSTAMP ++#include ++#include ++#include ++#endif ++struct igb_adapter; ++ ++#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) ++#define IGB_DCA ++#endif ++#ifdef IGB_DCA ++#include ++#endif ++ ++ ++#ifdef IGB_LRO ++#undef IGB_LRO ++#ifdef NETIF_F_LRO ++#if defined(CONFIG_INET_LRO) || defined(CONFIG_INET_LRO_MODULE) ++#include ++#define MAX_LRO_DESCRIPTORS 8 ++#define IGB_LRO ++#endif ++#endif ++#endif /* IGB_LRO */ ++ ++#include "kcompat.h" ++ ++#include "e1000_api.h" ++#include "e1000_82575.h" ++ ++#define IGB_ERR(args...) printk(KERN_ERR "igb: " args) ++ ++#define PFX "igb: " ++#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)) ++ ++/* Interrupt defines */ ++#define IGB_START_ITR 648 /* ~6000 ints/sec */ ++ ++/* Interrupt modes, as used by the IntMode paramter */ ++#define IGB_INT_MODE_LEGACY 0 ++#define IGB_INT_MODE_MSI 1 ++#define IGB_INT_MODE_MSIX 2 ++ ++#define HW_PERF ++/* TX/RX descriptor defines */ ++#define IGB_DEFAULT_TXD 256 ++#define IGB_MIN_TXD 80 ++#define IGB_MAX_TXD 4096 ++ ++#define IGB_DEFAULT_RXD 256 ++#define IGB_MIN_RXD 80 ++#define IGB_MAX_RXD 4096 ++ ++#define IGB_MIN_ITR_USECS 10 /* 100k irq/sec */ ++#define IGB_MAX_ITR_USECS 8191 /* 120 irq/sec */ ++ ++#define NON_Q_VECTORS 1 ++#define MAX_Q_VECTORS 8 ++ ++/* Transmit and receive queues */ ++#define IGB_MAX_RX_QUEUES (adapter->vfs_allocated_count ? 2 : \ ++ (hw->mac.type > e1000_82575 ? 8 : 4)) ++#define IGB_ABS_MAX_TX_QUEUES 8 ++#define IGB_MAX_TX_QUEUES IGB_MAX_RX_QUEUES ++ ++#define IGB_MAX_VF_MC_ENTRIES 30 ++#define IGB_MAX_VF_FUNCTIONS 8 ++#define IGB_MAX_VFTA_ENTRIES 128 ++#define IGB_MAX_UTA_ENTRIES 128 ++#define MAX_EMULATION_MAC_ADDRS 16 ++#define OUI_LEN 3 ++ ++struct vf_data_storage { ++ unsigned char vf_mac_addresses[ETH_ALEN]; ++ u16 vf_mc_hashes[IGB_MAX_VF_MC_ENTRIES]; ++ u16 num_vf_mc_hashes; ++ u16 default_vf_vlan_id; ++ u16 vlans_enabled; ++ unsigned char em_mac_addresses[MAX_EMULATION_MAC_ADDRS * ETH_ALEN]; ++ u32 uta_table_copy[IGB_MAX_UTA_ENTRIES]; ++ u32 flags; ++ unsigned long last_nack; ++}; ++ ++#define IGB_VF_FLAG_CTS 0x00000001 /* VF is clear to send data */ ++#define IGB_VF_FLAG_UNI_PROMISC 0x00000002 /* VF has unicast promisc */ ++#define IGB_VF_FLAG_MULTI_PROMISC 0x00000004 /* VF has multicast promisc */ ++ ++/* RX descriptor control thresholds. ++ * PTHRESH - MAC will consider prefetch if it has fewer than this number of ++ * descriptors available in its onboard memory. ++ * Setting this to 0 disables RX descriptor prefetch. ++ * HTHRESH - MAC will only prefetch if there are at least this many descriptors ++ * available in host memory. ++ * If PTHRESH is 0, this should also be 0. ++ * WTHRESH - RX descriptor writeback threshold - MAC will delay writing back ++ * descriptors until either it has this many to write back, or the ++ * ITR timer expires. ++ */ ++#define IGB_RX_PTHRESH (hw->mac.type <= e1000_82576 ? 16 : 8) ++#define IGB_RX_HTHRESH 8 ++#define IGB_RX_WTHRESH 1 ++#define IGB_TX_PTHRESH 8 ++#define IGB_TX_HTHRESH 1 ++#define IGB_TX_WTHRESH ((hw->mac.type == e1000_82576 && \ ++ adapter->msix_entries) ? 0 : 16) ++ ++/* this is the size past which hardware will drop packets when setting LPE=0 */ ++#define MAXIMUM_ETHERNET_VLAN_SIZE 1522 ++ ++/* Supported Rx Buffer Sizes */ ++#define IGB_RXBUFFER_128 128 /* Used for packet split */ ++#define IGB_RXBUFFER_256 256 /* Used for packet split */ ++#define IGB_RXBUFFER_512 512 ++#define IGB_RXBUFFER_1024 1024 ++#define IGB_RXBUFFER_2048 2048 ++#define IGB_RXBUFFER_4096 4096 ++#define IGB_RXBUFFER_8192 8192 ++#define IGB_RXBUFFER_16384 16384 ++ ++/* Packet Buffer allocations */ ++#define IGB_PBA_BYTES_SHIFT 0xA ++#define IGB_TX_HEAD_ADDR_SHIFT 7 ++#define IGB_PBA_TX_MASK 0xFFFF0000 ++ ++#define IGB_FC_PAUSE_TIME 0x0680 /* 858 usec */ ++ ++/* How many Tx Descriptors do we need to call netif_wake_queue ? */ ++#define IGB_TX_QUEUE_WAKE 32 ++/* How many Rx Buffers do we bundle into one write to the hardware ? */ ++#define IGB_RX_BUFFER_WRITE 16 /* Must be power of 2 */ ++ ++#define AUTO_ALL_MODES 0 ++#define IGB_EEPROM_APME 0x0400 ++ ++#ifndef IGB_MASTER_SLAVE ++/* Switch to override PHY master/slave setting */ ++#define IGB_MASTER_SLAVE e1000_ms_hw_default ++#endif ++ ++#define IGB_MNG_VLAN_NONE -1 ++ ++/* wrapper around a pointer to a socket buffer, ++ * so a DMA handle can be stored along with the buffer */ ++struct igb_buffer { ++ struct sk_buff *skb; ++ dma_addr_t dma; ++ dma_addr_t page_dma; ++ union { ++ /* TX */ ++ struct { ++ unsigned long time_stamp; ++ u16 length; ++ u16 next_to_watch; ++ }; ++ ++#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT ++ /* RX */ ++ struct { ++ unsigned long page_offset; ++ struct page *page; ++ }; ++#endif ++ }; ++}; ++ ++struct igb_queue_stats { ++ u64 packets; ++ u64 bytes; ++}; ++ ++struct igb_q_vector { ++ struct igb_adapter *adapter; /* backlink */ ++ struct igb_ring *rx_ring; ++ struct igb_ring *tx_ring; ++ struct napi_struct napi; ++ ++ u32 eims_value; ++ u16 cpu; ++ ++ u16 itr_val; ++ u8 set_itr; ++ u8 itr_shift; ++ void __iomem *itr_register; ++ ++ char name[IFNAMSIZ + 9]; ++#ifndef HAVE_NETDEV_NAPI_LIST ++ struct net_device poll_dev; ++#endif ++}; ++ ++struct igb_ring { ++ struct igb_q_vector *q_vector; /* backlink to q_vector */ ++ struct pci_dev *pdev; /* pci device for dma mapping */ ++ dma_addr_t dma; /* phys address of the ring */ ++ void *desc; /* descriptor ring memory */ ++ unsigned int size; /* length of desc. ring in bytes */ ++ u16 count; /* number of desc. in the ring */ ++ u16 next_to_use; ++ u16 next_to_clean; ++ u8 queue_index; ++ u8 reg_idx; ++ void __iomem *head; ++ void __iomem *tail; ++ struct igb_buffer *buffer_info; /* array of buffer info structs */ ++ ++ unsigned int total_bytes; ++ unsigned int total_packets; ++ ++ struct igb_queue_stats stats; ++ ++ union { ++ /* TX */ ++ struct { ++ unsigned int restart_queue; ++ u32 ctx_idx; ++ bool detect_tx_hung; ++ }; ++ /* RX */ ++ struct { ++ u64 hw_csum_err; ++ u64 hw_csum_good; ++ u32 rx_buffer_len; ++ u16 rx_ps_hdr_size; ++ bool rx_csum; ++#ifdef IGB_LRO ++ struct net_lro_mgr lro_mgr; ++ bool lro_used; ++#endif ++ }; ++ }; ++}; ++ ++ ++#define IGB_ADVTXD_DCMD (E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_RS) ++ ++#define IGB_DESC_UNUSED(R) \ ++ ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \ ++ (R)->next_to_clean - (R)->next_to_use - 1) ++ ++#define E1000_RX_DESC_ADV(R, i) \ ++ (&(((union e1000_adv_rx_desc *)((R).desc))[i])) ++#define E1000_TX_DESC_ADV(R, i) \ ++ (&(((union e1000_adv_tx_desc *)((R).desc))[i])) ++#define E1000_TX_CTXTDESC_ADV(R, i) \ ++ (&(((struct e1000_adv_tx_context_desc *)((R).desc))[i])) ++#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) ++#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc) ++#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc) ++ ++#define MAX_MSIX_COUNT 10 ++/* board specific private data structure */ ++ ++struct igb_adapter { ++ struct timer_list watchdog_timer; ++ struct timer_list phy_info_timer; ++ struct vlan_group *vlgrp; ++ u16 mng_vlan_id; ++ u32 bd_number; ++ u32 wol; ++ u32 en_mng_pt; ++ u16 link_speed; ++ u16 link_duplex; ++ ++ unsigned int total_tx_bytes; ++ unsigned int total_tx_packets; ++ unsigned int total_rx_bytes; ++ unsigned int total_rx_packets; ++ /* Interrupt Throttle Rate */ ++ u32 itr; ++ u32 itr_setting; ++ u16 tx_itr; ++ u16 rx_itr; + -+#define E1000_LSECTXUT 0x04300 /* LinkSec Tx Untagged Packet Count - OutPktsUntagged */ -+#define E1000_LSECTXPKTE 0x04304 /* LinkSec Encrypted Tx Packets Count - OutPktsEncrypted */ -+#define E1000_LSECTXPKTP 0x04308 /* LinkSec Protected Tx Packet Count - OutPktsProtected */ -+#define E1000_LSECTXOCTE 0x0430C /* LinkSec Encrypted Tx Octets Count - OutOctetsEncrypted */ -+#define E1000_LSECTXOCTP 0x04310 /* LinkSec Protected Tx Octets Count - OutOctetsProtected */ -+#define E1000_LSECRXUT 0x04314 /* LinkSec Untagged non-Strict Rx Packet Count - InPktsUntagged/InPktsNoTag */ -+#define E1000_LSECRXOCTD 0x0431C /* LinkSec Rx Octets Decrypted Count - InOctetsDecrypted */ -+#define E1000_LSECRXOCTV 0x04320 /* LinkSec Rx Octets Validated - InOctetsValidated */ -+#define E1000_LSECRXBAD 0x04324 /* LinkSec Rx Bad Tag - InPktsBadTag */ -+#define E1000_LSECRXNOSCI 0x04328 /* LinkSec Rx Packet No SCI Count - InPktsNoSci */ -+#define E1000_LSECRXUNSCI 0x0432C /* LinkSec Rx Packet Unknown SCI Count - InPktsUnknownSci */ -+#define E1000_LSECRXUNCH 0x04330 /* LinkSec Rx Unchecked Packets Count - InPktsUnchecked */ -+#define E1000_LSECRXDELAY 0x04340 /* LinkSec Rx Delayed Packet Count - InPktsDelayed */ -+#define E1000_LSECRXLATE 0x04350 /* LinkSec Rx Late Packets Count - InPktsLate */ -+#define E1000_LSECRXOK(_n) (0x04360 + (0x04 * (_n))) /* LinkSec Rx Packet OK Count - InPktsOk */ -+#define E1000_LSECRXINV(_n) (0x04380 + (0x04 * (_n))) /* LinkSec Rx Invalid Count - InPktsInvalid */ -+#define E1000_LSECRXNV(_n) (0x043A0 + (0x04 * (_n))) /* LinkSec Rx Not Valid Count - InPktsNotValid */ -+#define E1000_LSECRXUNSA 0x043C0 /* LinkSec Rx Unused SA Count - InPktsUnusedSa */ -+#define E1000_LSECRXNUSA 0x043D0 /* LinkSec Rx Not Using SA Count - InPktsNotUsingSa */ -+#define E1000_LSECTXCAP 0x0B000 /* LinkSec Tx Capabilities Register - RO */ -+#define E1000_LSECRXCAP 0x0B300 /* LinkSec Rx Capabilities Register - RO */ -+#define E1000_LSECTXCTRL 0x0B004 /* LinkSec Tx Control - RW */ -+#define E1000_LSECRXCTRL 0x0B304 /* LinkSec Rx Control - RW */ -+#define E1000_LSECTXSCL 0x0B008 /* LinkSec Tx SCI Low - RW */ -+#define E1000_LSECTXSCH 0x0B00C /* LinkSec Tx SCI High - RW */ -+#define E1000_LSECTXSA 0x0B010 /* LinkSec Tx SA0 - RW */ -+#define E1000_LSECTXPN0 0x0B018 /* LinkSec Tx SA PN 0 - RW */ -+#define E1000_LSECTXPN1 0x0B01C /* LinkSec Tx SA PN 1 - RW */ -+#define E1000_LSECRXSCL 0x0B3D0 /* LinkSec Rx SCI Low - RW */ -+#define E1000_LSECRXSCH 0x0B3E0 /* LinkSec Rx SCI High - RW */ -+#define E1000_LSECTXKEY0(_n) (0x0B020 + (0x04 * (_n))) /* LinkSec Tx 128-bit Key 0 - WO */ -+#define E1000_LSECTXKEY1(_n) (0x0B030 + (0x04 * (_n))) /* LinkSec Tx 128-bit Key 1 - WO */ -+#define E1000_LSECRXSA(_n) (0x0B310 + (0x04 * (_n))) /* LinkSec Rx SAs - RW */ -+#define E1000_LSECRXPN(_n) (0x0B330 + (0x04 * (_n))) /* LinkSec Rx SAs - RW */ -+/* -+ * LinkSec Rx Keys - where _n is the SA no. and _m the 4 dwords of the 128 bit -+ * key - RW. -+ */ -+#define E1000_LSECRXKEY(_n, _m) (0x0B350 + (0x10 * (_n)) + (0x04 * (_m))) ++ struct work_struct reset_task; ++ struct work_struct watchdog_task; ++ bool fc_autoneg; ++ u8 tx_timeout_factor; ++#ifdef ETHTOOL_PHYS_ID ++ struct timer_list blink_timer; ++ unsigned long led_status; ++#endif + -+#define E1000_SSVPC 0x041A0 /* Switch Security Violation Packet Count */ -+#define E1000_IPSCTRL 0xB430 /* IpSec Control Register */ -+#define E1000_IPSRXCMD 0x0B408 /* IPSec Rx Command Register - RW */ -+#define E1000_IPSRXIDX 0x0B400 /* IPSec Rx Index - RW */ -+#define E1000_IPSRXIPADDR(_n) (0x0B420+ (0x04 * (_n))) /* IPSec Rx IPv4/v6 Address - RW */ -+#define E1000_IPSRXKEY(_n) (0x0B410 + (0x04 * (_n))) /* IPSec Rx 128-bit Key - RW */ -+#define E1000_IPSRXSALT 0x0B404 /* IPSec Rx Salt - RW */ -+#define E1000_IPSRXSPI 0x0B40C /* IPSec Rx SPI - RW */ -+#define E1000_IPSTXKEY(_n) (0x0B460 + (0x04 * (_n))) /* IPSec Tx 128-bit Key - RW */ -+#define E1000_IPSTXSALT 0x0B454 /* IPSec Tx Salt - RW */ -+#define E1000_IPSTXIDX 0x0B450 /* IPSec Tx SA IDX - RW */ -+#define E1000_PCS_CFG0 0x04200 /* PCS Configuration 0 - RW */ -+#define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */ -+#define E1000_PCS_LSTAT 0x0420C /* PCS Link Status - RO */ -+#define E1000_CBTMPC 0x0402C /* Circuit Breaker Tx Packet Count */ -+#define E1000_HTDPMC 0x0403C /* Host Transmit Discarded Packets */ -+#define E1000_CBRDPC 0x04044 /* Circuit Breaker Rx Dropped Count */ -+#define E1000_CBRMPC 0x040FC /* Circuit Breaker Rx Packet Count */ -+#define E1000_RPTHC 0x04104 /* Rx Packets To Host */ -+#define E1000_HGPTC 0x04118 /* Host Good Packets Tx Count */ -+#define E1000_HTCBDPC 0x04124 /* Host Tx Circuit Breaker Dropped Count */ -+#define E1000_HGORCL 0x04128 /* Host Good Octets Received Count Low */ -+#define E1000_HGORCH 0x0412C /* Host Good Octets Received Count High */ -+#define E1000_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */ -+#define E1000_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */ -+#define E1000_LENERRS 0x04138 /* Length Errors Count */ -+#define E1000_SCVPC 0x04228 /* SerDes/SGMII Code Violation Pkt Count */ -+#define E1000_HRMPC 0x0A018 /* Header Redirection Missed Packet Count */ -+#define E1000_PCS_ANADV 0x04218 /* AN advertisement - RW */ -+#define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */ -+#define E1000_PCS_NPTX 0x04220 /* AN Next Page Transmit - RW */ -+#define E1000_PCS_LPABNP 0x04224 /* Link Partner Ability Next Page - RW */ -+#define E1000_1GSTAT_RCV 0x04228 /* 1GSTAT Code Violation Packet Count - RW */ -+#define E1000_RXCSUM 0x05000 /* Rx Checksum Control - RW */ -+#define E1000_RLPML 0x05004 /* Rx Long Packet Max Length */ -+#define E1000_RFCTL 0x05008 /* Receive Filter Control*/ -+#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */ -+#define E1000_RA 0x05400 /* Receive Address - RW Array */ -+#define E1000_RA2 0x054E0 /* 2nd half of receive address array - RW Array */ -+#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */ -+#define E1000_VT_CTL 0x0581C /* VMDq Control - RW */ -+#define E1000_VFQA0 0x0B000 /* VLAN Filter Queue Array 0 - RW Array */ -+#define E1000_VFQA1 0x0B200 /* VLAN Filter Queue Array 1 - RW Array */ -+#define E1000_WUC 0x05800 /* Wakeup Control - RW */ -+#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */ -+#define E1000_WUS 0x05810 /* Wakeup Status - RO */ -+#define E1000_MANC 0x05820 /* Management Control - RW */ -+#define E1000_IPAV 0x05838 /* IP Address Valid - RW */ -+#define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */ -+#define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */ -+#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */ -+#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */ -+#define E1000_PBACL 0x05B68 /* MSIx PBA Clear - Read/Write 1's to clear */ -+#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */ -+#define E1000_HOST_IF 0x08800 /* Host Interface */ -+#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */ -+#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */ -+#define E1000_FHFT(_n) (0x09000 + (_n * 0x100)) /* Flexible Host Filter Table */ -+#define E1000_FHFT_EXT(_n) (0x09A00 + (_n * 0x100)) /* Ext Flexible Host Filter Table */ ++ /* TX */ ++ struct igb_ring *tx_ring; /* One per active queue */ ++ unsigned int restart_queue; ++ unsigned long tx_queue_len; ++ u32 tx_timeout_count; + ++ /* RX */ ++ struct igb_ring *rx_ring; /* One per active queue */ ++ int num_tx_queues; ++ int num_rx_queues; + -+#define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */ -+#define E1000_MDPHYA 0x0003C /* PHY address - RW */ -+#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */ -+#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */ -+#define E1000_CCMCTL 0x05B48 /* CCM Control Register */ -+#define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */ -+#define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */ -+#define E1000_GCR 0x05B00 /* PCI-Ex Control */ -+#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */ -+#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */ -+#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */ -+#define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */ -+#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */ -+#define E1000_SWSM 0x05B50 /* SW Semaphore */ -+#define E1000_FWSM 0x05B54 /* FW Semaphore */ -+#define E1000_DCA_ID 0x05B70 /* DCA Requester ID Information - RO */ -+#define E1000_DCA_CTRL 0x05B74 /* DCA Control - RW */ -+#define E1000_FFLT_DBG 0x05F04 /* Debug Register */ -+#define E1000_HICR 0x08F00 /* Host Interface Control */ ++ u64 hw_csum_err; ++ u64 hw_csum_good; ++ u32 alloc_rx_buff_failed; ++ u32 max_frame_size; ++ u32 min_frame_size; + -+/* RSS registers */ -+#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */ -+#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */ -+#define E1000_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */ -+#define E1000_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate Interrupt Ext*/ -+#define E1000_IMIRVP 0x05AC0 /* Immediate Interrupt Rx VLAN Priority - RW */ -+#define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4)) /* MSI-X Allocation Register (_i) - RW */ -+#define E1000_MSIXTADD(_i) (0x0C000 + ((_i) * 0x10)) /* MSI-X Table entry addr low reg 0 - RW */ -+#define E1000_MSIXTUADD(_i) (0x0C004 + ((_i) * 0x10)) /* MSI-X Table entry addr upper reg 0 - RW */ -+#define E1000_MSIXTMSG(_i) (0x0C008 + ((_i) * 0x10)) /* MSI-X Table entry message reg 0 - RW */ -+#define E1000_MSIXVCTRL(_i) (0x0C00C + ((_i) * 0x10)) /* MSI-X Table entry vector ctrl reg 0 - RW */ -+#define E1000_MSIXPBA 0x0E000 /* MSI-X Pending bit array */ -+#define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW Array */ -+#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW Array */ -+#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */ -+#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */ -+/* VT Registers */ -+#define E1000_SWPBS 0x03004 /* Switch Packet Buffer Size - RW */ -+#define E1000_MBVFICR 0x00C80 /* Mailbox VF Cause - RWC */ -+#define E1000_MBVFIMR 0x00C84 /* Mailbox VF int Mask - RW */ -+#define E1000_VFLRE 0x00C88 /* VF Register Events - RWC */ -+#define E1000_VFRE 0x00C8C /* VF Receive Enables */ -+#define E1000_VFTE 0x00C90 /* VF Transmit Enables */ -+#define E1000_QDE 0x02408 /* Queue Drop Enable - RW */ -+#define E1000_DTXSWC 0x03500 /* DMA Tx Switch Control - RW */ -+#define E1000_VLVF 0x05D00 /* VLAN Virtual Machine Filter - RW */ -+#define E1000_RPLOLR 0x05AF0 /* Replication Offload - RW */ -+#define E1000_UTA 0x0A000 /* Unicast Table Array - RW */ -+#define E1000_IOVTCL 0x05BBC /* IOV Control Register */ -+#define E1000_VMRCTL 0X05D80 /* Virtual Mirror Rule Control */ -+/* These act per VF so an array friendly macro is used */ -+#define E1000_V2PMAILBOX(_n) (0x00C40 + (4 * (_n))) -+#define E1000_P2VMAILBOX(_n) (0x00C00 + (4 * (_n))) -+#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n))) -+#define E1000_VFVMBMEM(_n) (0x00800 + (_n)) -+#define E1000_VMOLR(_n) (0x05AD0 + (4 * (_n))) ++ /* OS defined structs */ ++ struct net_device *netdev; ++ struct pci_dev *pdev; ++ struct net_device_stats net_stats; ++#ifdef SIOCSHWTSTAMP ++ struct cyclecounter cycles; ++ struct timecounter clock; ++ struct timecompare compare; ++ struct hwtstamp_config hwtstamp_config; ++#endif + -+/* Filtering Registers */ -+#define E1000_SAQF(_n) (0x05980 + (4 * (_n))) /* Source Address Queue Fltr */ -+#define E1000_DAQF(_n) (0x059A0 + (4 * (_n))) /* Dest Address Queue Fltr */ -+#define E1000_SPQF(_n) (0x059C0 + (4 * (_n))) /* Source Port Queue Fltr */ -+#define E1000_FTQF(_n) (0x059E0 + (4 * (_n))) /* 5-tuple Queue Fltr */ -+#define E1000_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */ -+#define E1000_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */ ++ /* structs defined in e1000_hw.h */ ++ struct e1000_hw hw; ++ struct e1000_hw_stats stats; ++ struct e1000_phy_info phy_info; ++ struct e1000_phy_stats phy_stats; + -+#define E1000_RTTDCS 0x3600 /* Reedtown Tx Desc plane control and status */ -+#define E1000_RTTPCS 0x3474 /* Reedtown Tx Packet Plane control and status */ -+#define E1000_RTRPCS 0x2474 /* Rx packet plane control and status */ -+#define E1000_RTRUP2TC 0x05AC4 /* Rx User Priority to Traffic Class */ -+#define E1000_RTTUP2TC 0x0418 /* Transmit User Priority to Traffic Class */ -+#define E1000_RTTDTCRC(_n) (0x3610 + ((_n) * 4)) /* Tx Desc plane TC Rate-scheduler config */ -+#define E1000_RTTPTCRC(_n) (0x3480 + ((_n) * 4)) /* Tx Packet plane TC Rate-Scheduler Config */ -+#define E1000_RTRPTCRC(_n) (0x2480 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler Config */ -+#define E1000_RTTDTCRS(_n) (0x3630 + ((_n) * 4)) /* Tx Desc Plane TC Rate-Scheduler Status */ -+#define E1000_RTTDTCRM(_n) (0x3650 + ((_n) * 4)) /* Tx Desc Plane TC Rate-Scheduler MMW */ -+#define E1000_RTTPTCRS(_n) (0x34A0 + ((_n) * 4)) /* Tx Packet plane TC Rate-Scheduler Status */ -+#define E1000_RTTPTCRM(_n) (0x34C0 + ((_n) * 4)) /* Tx Packet plane TC Rate-scheduler MMW */ -+#define E1000_RTRPTCRS(_n) (0x24A0 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler Status */ -+#define E1000_RTRPTCRM(_n) (0x24C0 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler MMW */ -+#define E1000_RTTDVMRM(_n) (0x3670 + ((_n) * 4)) /* Tx Desc plane VM Rate-Scheduler MMW*/ -+#define E1000_RTTBCNRM(_n) (0x3690 + ((_n) * 4)) /* Tx BCN Rate-Scheduler MMW */ -+#define E1000_RTTDQSEL 0x3604 /* Tx Desc Plane Queue Select */ -+#define E1000_RTTDVMRC 0x3608 /* Tx Desc Plane VM Rate-Scheduler Config */ -+#define E1000_RTTDVMRS 0x360C /* Tx Desc Plane VM Rate-Scheduler Status */ -+#define E1000_RTTBCNRC 0x36B0 /* Tx BCN Rate-Scheduler Config */ -+#define E1000_RTTBCNRS 0x36B4 /* Tx BCN Rate-Scheduler Status */ -+#define E1000_RTTBCNCR 0xB200 /* Tx BCN Control Register */ -+#define E1000_RTTBCNTG 0x35A4 /* Tx BCN Tagging */ -+#define E1000_RTTBCNCP 0xB208 /* Tx BCN Congestion point */ -+#define E1000_RTRBCNCR 0xB20C /* Rx BCN Control Register */ -+#define E1000_RTTBCNRD 0x36B8 /* Tx BCN Rate Drift */ -+#define E1000_PFCTOP 0x1080 /* Priority Flow Control Type and Opcode */ -+#define E1000_RTTBCNIDX 0xB204 /* Tx BCN Congestion Point */ -+#define E1000_RTTBCNACH 0x0B214 /* Tx BCN Control High */ -+#define E1000_RTTBCNACL 0x0B210 /* Tx BCN Control Low */ ++#ifdef ETHTOOL_TEST ++ u32 test_icr; ++ struct igb_ring test_tx_ring; ++ struct igb_ring test_rx_ring; ++#endif ++ ++ ++ int msg_enable; ++ struct msix_entry *msix_entries; ++ int int_mode; ++ u32 eims_enable_mask; ++ u32 eims_other; ++ u32 lli_port; ++ u32 lli_size; ++ unsigned long state; ++ unsigned int flags; ++ u32 eeprom_wol; ++ u32 *config_space; ++#ifdef HAVE_TX_MQ ++ struct igb_ring *multi_tx_table[IGB_ABS_MAX_TX_QUEUES]; ++#endif /* HAVE_TX_MQ */ ++#ifdef IGB_LRO ++ unsigned int lro_max_aggr; ++ unsigned int lro_aggregated; ++ unsigned int lro_flushed; ++ unsigned int lro_no_desc; ++#endif ++ u16 tx_ring_count; ++ u16 rx_ring_count; ++ unsigned int vfs_allocated_count; ++ struct vf_data_storage *vf_data; ++ u32 RSS_queues; ++ u32 VMDQ_queues; ++ unsigned int num_q_vectors; ++ struct igb_q_vector *q_vector[MAX_Q_VECTORS]; ++}; ++ ++ ++#define IGB_FLAG_HAS_MSI (1 << 0) ++#define IGB_FLAG_MSI_ENABLE (1 << 1) ++#define IGB_FLAG_DCA_ENABLED (1 << 3) ++#define IGB_FLAG_LLI_PUSH (1 << 4) ++#define IGB_FLAG_IN_NETPOLL (1 << 5) ++#define IGB_FLAG_QUAD_PORT_A (1 << 6) ++#define IGB_FLAG_QUEUE_PAIRS (1 << 7) + ++#define IGB_82576_TSYNC_SHIFT 19 ++enum e1000_state_t { ++ __IGB_TESTING, ++ __IGB_RESETTING, ++ __IGB_DOWN ++}; ++ ++extern char igb_driver_name[]; ++extern char igb_driver_version[]; ++ ++extern int igb_up(struct igb_adapter *); ++extern void igb_down(struct igb_adapter *); ++extern void igb_reinit_locked(struct igb_adapter *); ++extern void igb_reset(struct igb_adapter *); ++extern int igb_set_spd_dplx(struct igb_adapter *, u16); ++extern int igb_setup_tx_resources(struct igb_ring *); ++extern int igb_setup_rx_resources(struct igb_ring *); ++extern void igb_free_tx_resources(struct igb_ring *); ++extern void igb_free_rx_resources(struct igb_ring *); ++extern void igb_configure_tx_ring(struct igb_adapter *, struct igb_ring *); ++extern void igb_configure_rx_ring(struct igb_adapter *, struct igb_ring *); ++extern void igb_setup_tctl(struct igb_adapter *); ++extern void igb_setup_rctl(struct igb_adapter *); ++extern int igb_alloc_rx_buffers_adv(struct igb_ring *, int); ++extern void igb_update_stats(struct igb_adapter *); ++extern void igb_set_ethtool_ops(struct net_device *); ++extern void igb_check_options(struct igb_adapter *); ++#ifdef ETHTOOL_OPS_COMPAT ++extern int ethtool_ioctl(struct ifreq *); +#endif -diff -Nru vanilla/drivers/net/igb/igb_ethtool.c linux-i686-2.6.22/drivers/net/igb/igb_ethtool.c ---- vanilla/drivers/net/igb/igb_ethtool.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/igb_ethtool.c 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,1965 @@ ++extern int igb_set_vf_mac(struct igb_adapter *adapter, ++ int vf, unsigned char *mac_addr); ++extern s32 igb_vlvf_set(struct igb_adapter *, u32, bool, u32); ++extern void igb_configure_vt_default_pool(struct igb_adapter *adapter); ++ ++#endif /* _IGB_H_ */ +Index: linux-2.6.22/drivers/net/igb/igb_ethtool.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/igb_ethtool.c 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,1953 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ Copyright(c) 2007-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, @@ -14826,8 +13187,7 @@ diff -Nru vanilla/drivers/net/igb/igb_ethtool.c linux-i686-2.6.22/drivers/net/ig + { "rx_long_byte_count", IGB_STAT(stats.gorc) }, + { "rx_csum_offload_good", IGB_STAT(hw_csum_good) }, + { "rx_csum_offload_errors", IGB_STAT(hw_csum_err) }, -+ { "rx_header_split", IGB_STAT(rx_hdr_split) }, -+ { "low_latency_interrupt", IGB_STAT(lli_int)}, ++ { "tx_dma_out_of_sync", IGB_STAT(stats.doosync) }, + { "alloc_rx_buff_failed", IGB_STAT(alloc_rx_buff_failed) }, + { "tx_smbus", IGB_STAT(stats.mgptc) }, + { "rx_smbus", IGB_STAT(stats.mgprc) }, @@ -14840,11 +13200,11 @@ diff -Nru vanilla/drivers/net/igb/igb_ethtool.c linux-i686-2.6.22/drivers/net/ig +}; + +#define IGB_QUEUE_STATS_LEN \ -+ ((((struct igb_adapter *)netdev->priv)->num_rx_queues + \ -+ ((struct igb_adapter *)netdev->priv)->num_tx_queues) * \ ++ ((((struct igb_adapter *)netdev_priv(netdev))->num_rx_queues + \ ++ ((struct igb_adapter *)netdev_priv(netdev))->num_tx_queues) * \ + (sizeof(struct igb_queue_stats) / sizeof(u64))) +#define IGB_GLOBAL_STATS_LEN \ -+ sizeof(igb_gstrings_stats) / sizeof(struct igb_stats) ++ (sizeof(igb_gstrings_stats) / sizeof(struct igb_stats)) +#define IGB_STATS_LEN (IGB_GLOBAL_STATS_LEN + IGB_QUEUE_STATS_LEN) +#endif /* ETHTOOL_GSTATS */ +#ifdef ETHTOOL_TEST @@ -14853,2799 +13213,1847 @@ diff -Nru vanilla/drivers/net/igb/igb_ethtool.c linux-i686-2.6.22/drivers/net/ig + "Interrupt test (offline)", "Loopback test (offline)", + "Link test (on/offline)" +}; -+#define IGB_TEST_LEN sizeof(igb_gstrings_test) / ETH_GSTRING_LEN -+#endif /* ETHTOOL_TEST */ -+ -+static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) -+{ -+ struct igb_adapter *adapter = netdev_priv(netdev); -+ struct e1000_hw *hw = &adapter->hw; -+ u32 status; -+ -+ if (hw->phy.media_type == e1000_media_type_copper) { -+ -+ ecmd->supported = (SUPPORTED_10baseT_Half | -+ SUPPORTED_10baseT_Full | -+ SUPPORTED_100baseT_Half | -+ SUPPORTED_100baseT_Full | -+ SUPPORTED_1000baseT_Full| -+ SUPPORTED_Autoneg | -+ SUPPORTED_TP); -+ ecmd->advertising = ADVERTISED_TP; -+ -+ if (hw->mac.autoneg == 1) { -+ ecmd->advertising |= ADVERTISED_Autoneg; -+ /* the e1000 autoneg seems to match ethtool nicely */ -+ ecmd->advertising |= hw->phy.autoneg_advertised; -+ } -+ -+ ecmd->port = PORT_TP; -+ ecmd->phy_address = hw->phy.addr; -+ } else { -+ ecmd->supported = (SUPPORTED_1000baseT_Full | -+ SUPPORTED_FIBRE | -+ SUPPORTED_Autoneg); -+ -+ ecmd->advertising = (ADVERTISED_1000baseT_Full | -+ ADVERTISED_FIBRE | -+ ADVERTISED_Autoneg); -+ -+ ecmd->port = PORT_FIBRE; -+ } -+ -+ ecmd->transceiver = XCVR_INTERNAL; -+ -+ status = E1000_READ_REG(hw, E1000_STATUS); -+ -+ if (status & E1000_STATUS_LU) { -+ -+ if ((status & E1000_STATUS_SPEED_1000) || -+ hw->phy.media_type != e1000_media_type_copper) -+ ecmd->speed = SPEED_1000; -+ else if (status & E1000_STATUS_SPEED_100) -+ ecmd->speed = SPEED_100; -+ else -+ ecmd->speed = SPEED_10; -+ -+ if ((status & E1000_STATUS_FD) || -+ hw->phy.media_type != e1000_media_type_copper) -+ ecmd->duplex = DUPLEX_FULL; -+ else -+ ecmd->duplex = DUPLEX_HALF; -+ } else { -+ ecmd->speed = -1; -+ ecmd->duplex = -1; -+ } -+ -+ ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) || -+ hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE; -+ return 0; -+} -+ -+static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) -+{ -+ struct igb_adapter *adapter = netdev_priv(netdev); -+ struct e1000_hw *hw = &adapter->hw; -+ -+ /* When SoL/IDER sessions are active, autoneg/speed/duplex -+ * cannot be changed */ -+ if (e1000_check_reset_block(hw)) { -+ DPRINTK(DRV, ERR, "Cannot change link characteristics " -+ "when SoL/IDER is active.\n"); -+ return -EINVAL; -+ } -+ -+ while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) -+ msleep(1); -+ -+ if (ecmd->autoneg == AUTONEG_ENABLE) { -+ hw->mac.autoneg = 1; -+ if (hw->phy.media_type == e1000_media_type_fiber) -+ hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full | -+ ADVERTISED_FIBRE | -+ ADVERTISED_Autoneg; -+ else -+ hw->phy.autoneg_advertised = ecmd->advertising | -+ ADVERTISED_TP | -+ ADVERTISED_Autoneg; -+ ecmd->advertising = hw->phy.autoneg_advertised; -+ if (adapter->fc_autoneg) -+ hw->fc.original_type = e1000_fc_default; -+ } else { -+ if (igb_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) { -+ clear_bit(__IGB_RESETTING, &adapter->state); -+ return -EINVAL; -+ } -+ } -+ -+ /* reset the link */ -+ if (netif_running(adapter->netdev)) { -+ igb_down(adapter); -+ igb_up(adapter); -+ } else -+ igb_reset(adapter); -+ -+ clear_bit(__IGB_RESETTING, &adapter->state); -+ return 0; -+} -+ -+static void igb_get_pauseparam(struct net_device *netdev, -+ struct ethtool_pauseparam *pause) -+{ -+ struct igb_adapter *adapter = netdev_priv(netdev); -+ struct e1000_hw *hw = &adapter->hw; -+ -+ pause->autoneg = -+ (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); -+ -+ if (hw->fc.type == e1000_fc_rx_pause) -+ pause->rx_pause = 1; -+ else if (hw->fc.type == e1000_fc_tx_pause) -+ pause->tx_pause = 1; -+ else if (hw->fc.type == e1000_fc_full) { -+ pause->rx_pause = 1; -+ pause->tx_pause = 1; -+ } -+} -+ -+static int igb_set_pauseparam(struct net_device *netdev, -+ struct ethtool_pauseparam *pause) -+{ -+ struct igb_adapter *adapter = netdev_priv(netdev); -+ struct e1000_hw *hw = &adapter->hw; -+ int retval = 0; -+ -+ adapter->fc_autoneg = pause->autoneg; -+ -+ while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) -+ msleep(1); -+ -+ if (pause->rx_pause && pause->tx_pause) -+ hw->fc.type = e1000_fc_full; -+ else if (pause->rx_pause && !pause->tx_pause) -+ hw->fc.type = e1000_fc_rx_pause; -+ else if (!pause->rx_pause && pause->tx_pause) -+ hw->fc.type = e1000_fc_tx_pause; -+ else if (!pause->rx_pause && !pause->tx_pause) -+ hw->fc.type = e1000_fc_none; -+ -+ hw->fc.original_type = hw->fc.type; -+ -+ /* reset the adapter/link to have settings take effect immediately and -+ * let our link partner know as well */ -+ if (netif_running(adapter->netdev)) { -+ igb_down(adapter); -+ igb_up(adapter); -+ } else { -+ igb_reset(adapter); -+ } -+ -+ clear_bit(__IGB_RESETTING, &adapter->state); -+ return retval; -+} -+ -+static u32 igb_get_rx_csum(struct net_device *netdev) -+{ -+ struct igb_adapter *adapter = netdev_priv(netdev); -+ return adapter->rx_csum; -+} -+ -+static int igb_set_rx_csum(struct net_device *netdev, u32 data) -+{ -+ struct igb_adapter *adapter = netdev_priv(netdev); -+ adapter->rx_csum = data; -+ -+ return 0; -+} -+ -+static u32 igb_get_tx_csum(struct net_device *netdev) -+{ -+ return (netdev->features & NETIF_F_IP_CSUM) != 0; -+} -+ -+static int igb_set_tx_csum(struct net_device *netdev, u32 data) -+{ -+ if (data) -+#ifdef NETIF_F_IPV6_CSUM -+ netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); -+ else -+ netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); -+#else -+ netdev->features |= NETIF_F_IP_CSUM; -+ else -+ netdev->features &= ~NETIF_F_IP_CSUM; -+#endif -+ -+ return 0; -+} -+ -+#ifdef NETIF_F_TSO -+static int igb_set_tso(struct net_device *netdev, u32 data) -+{ -+ struct igb_adapter *adapter = netdev_priv(netdev); -+ int i; -+ struct net_device *v_netdev; -+ -+ if (data) { -+ netdev->features |= NETIF_F_TSO; -+#ifdef NETIF_F_TSO6 -+ netdev->features |= NETIF_F_TSO6; -+#endif -+ } else { -+ netdev->features &= ~NETIF_F_TSO; -+#ifdef NETIF_F_TSO6 -+ netdev->features &= ~NETIF_F_TSO6; -+#endif -+ /* disable TSO on all VLANs if they're present */ -+ if (!adapter->vlgrp) -+ goto tso_out; -+ for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { -+ v_netdev = vlan_group_get_device(adapter->vlgrp, i); -+ if (!v_netdev) -+ continue; -+ -+ v_netdev->features &= ~NETIF_F_TSO; -+#ifdef NETIF_F_TSO6 -+ v_netdev->features &= ~NETIF_F_TSO6; -+#endif -+ vlan_group_set_device(adapter->vlgrp, i, v_netdev); -+ } -+ } -+ -+tso_out: -+ DPRINTK(PROBE, INFO, "TSO is %s\n", data ? "Enabled" : "Disabled"); -+ return 0; -+} -+#endif /* NETIF_F_TSO */ -+ -+static u32 igb_get_msglevel(struct net_device *netdev) -+{ -+ struct igb_adapter *adapter = netdev_priv(netdev); -+ return adapter->msg_enable; -+} -+ -+static void igb_set_msglevel(struct net_device *netdev, u32 data) -+{ -+ struct igb_adapter *adapter = netdev_priv(netdev); -+ adapter->msg_enable = data; -+} -+ -+static int igb_get_regs_len(struct net_device *netdev) -+{ -+#define IGB_REGS_LEN 551 -+ return IGB_REGS_LEN * sizeof(u32); -+} ++#define IGB_TEST_LEN (sizeof(igb_gstrings_test) / ETH_GSTRING_LEN) ++#endif /* ETHTOOL_TEST */ + -+static void igb_get_regs(struct net_device *netdev, -+ struct ethtool_regs *regs, void *p) ++static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) +{ + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; -+ u32 *regs_buff = p; -+ u8 i; -+ -+ memset(p, 0, IGB_REGS_LEN * sizeof(u32)); -+ -+ regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; -+ -+ /* General Registers */ -+ regs_buff[0] = E1000_READ_REG(hw, E1000_CTRL); -+ regs_buff[1] = E1000_READ_REG(hw, E1000_STATUS); -+ regs_buff[2] = E1000_READ_REG(hw, E1000_CTRL_EXT); -+ regs_buff[3] = E1000_READ_REG(hw, E1000_MDIC); -+ regs_buff[4] = E1000_READ_REG(hw, E1000_SCTL); -+ regs_buff[5] = E1000_READ_REG(hw, E1000_CONNSW); -+ regs_buff[6] = E1000_READ_REG(hw, E1000_VET); -+ regs_buff[7] = E1000_READ_REG(hw, E1000_LEDCTL); -+ regs_buff[8] = E1000_READ_REG(hw, E1000_PBA); -+ regs_buff[9] = E1000_READ_REG(hw, E1000_PBS); -+ regs_buff[10] = E1000_READ_REG(hw, E1000_FRTIMER); -+ regs_buff[11] = E1000_READ_REG(hw, E1000_TCPTIMER); -+ -+ /* NVM Register */ -+ regs_buff[12] = E1000_READ_REG(hw, E1000_EECD); -+ -+ /* Interrupt */ -+ /* Reading EICS for EICR because they read the -+ * same but EICS does not clear on read */ -+ regs_buff[13] = E1000_READ_REG(hw, E1000_EICS); -+ regs_buff[14] = E1000_READ_REG(hw, E1000_EICS); -+ regs_buff[15] = E1000_READ_REG(hw, E1000_EIMS); -+ regs_buff[16] = E1000_READ_REG(hw, E1000_EIMC); -+ regs_buff[17] = E1000_READ_REG(hw, E1000_EIAC); -+ regs_buff[18] = E1000_READ_REG(hw, E1000_EIAM); -+ /* Reading ICS for ICR because they read the -+ * same but ICS does not clear on read */ -+ regs_buff[19] = E1000_READ_REG(hw, E1000_ICS); -+ regs_buff[20] = E1000_READ_REG(hw, E1000_ICS); -+ regs_buff[21] = E1000_READ_REG(hw, E1000_IMS); -+ regs_buff[22] = E1000_READ_REG(hw, E1000_IMC); -+ regs_buff[23] = E1000_READ_REG(hw, E1000_IAC); -+ regs_buff[24] = E1000_READ_REG(hw, E1000_IAM); -+ regs_buff[25] = E1000_READ_REG(hw, E1000_IMIRVP); -+ -+ /* Flow Control */ -+ regs_buff[26] = E1000_READ_REG(hw, E1000_FCAL); -+ regs_buff[27] = E1000_READ_REG(hw, E1000_FCAH); -+ regs_buff[28] = E1000_READ_REG(hw, E1000_FCTTV); -+ regs_buff[29] = E1000_READ_REG(hw, E1000_FCRTL); -+ regs_buff[30] = E1000_READ_REG(hw, E1000_FCRTH); -+ regs_buff[31] = E1000_READ_REG(hw, E1000_FCRTV); ++ u32 status; + -+ /* Receive */ -+ regs_buff[32] = E1000_READ_REG(hw, E1000_RCTL); -+ regs_buff[33] = E1000_READ_REG(hw, E1000_RXCSUM); -+ regs_buff[34] = E1000_READ_REG(hw, E1000_RLPML); -+ regs_buff[35] = E1000_READ_REG(hw, E1000_RFCTL); -+ regs_buff[36] = E1000_READ_REG(hw, E1000_MRQC); -+ regs_buff[37] = E1000_READ_REG(hw, E1000_VT_CTL); ++ if (hw->phy.media_type == e1000_media_type_copper) { + -+ /* Transmit */ -+ regs_buff[38] = E1000_READ_REG(hw, E1000_TCTL); -+ regs_buff[39] = E1000_READ_REG(hw, E1000_TCTL_EXT); -+ regs_buff[40] = E1000_READ_REG(hw, E1000_TIPG); -+ regs_buff[41] = E1000_READ_REG(hw, E1000_DTXCTL); ++ ecmd->supported = (SUPPORTED_10baseT_Half | ++ SUPPORTED_10baseT_Full | ++ SUPPORTED_100baseT_Half | ++ SUPPORTED_100baseT_Full | ++ SUPPORTED_1000baseT_Full| ++ SUPPORTED_Autoneg | ++ SUPPORTED_TP); ++ ecmd->advertising = ADVERTISED_TP; + -+ /* Wake Up */ -+ regs_buff[42] = E1000_READ_REG(hw, E1000_WUC); -+ regs_buff[43] = E1000_READ_REG(hw, E1000_WUFC); -+ regs_buff[44] = E1000_READ_REG(hw, E1000_WUS); -+ regs_buff[45] = E1000_READ_REG(hw, E1000_IPAV); -+ regs_buff[46] = E1000_READ_REG(hw, E1000_WUPL); ++ if (hw->mac.autoneg == 1) { ++ ecmd->advertising |= ADVERTISED_Autoneg; ++ /* the e1000 autoneg seems to match ethtool nicely */ ++ ecmd->advertising |= hw->phy.autoneg_advertised; ++ } + -+ /* MAC */ -+ regs_buff[47] = E1000_READ_REG(hw, E1000_PCS_CFG0); -+ regs_buff[48] = E1000_READ_REG(hw, E1000_PCS_LCTL); -+ regs_buff[49] = E1000_READ_REG(hw, E1000_PCS_LSTAT); -+ regs_buff[50] = E1000_READ_REG(hw, E1000_PCS_ANADV); -+ regs_buff[51] = E1000_READ_REG(hw, E1000_PCS_LPAB); -+ regs_buff[52] = E1000_READ_REG(hw, E1000_PCS_NPTX); -+ regs_buff[53] = E1000_READ_REG(hw, E1000_PCS_LPABNP); ++ ecmd->port = PORT_TP; ++ ecmd->phy_address = hw->phy.addr; ++ } else { ++ ecmd->supported = (SUPPORTED_1000baseT_Full | ++ SUPPORTED_FIBRE | ++ SUPPORTED_Autoneg); + -+ /* Statistics */ -+ regs_buff[54] = adapter->stats.crcerrs; -+ regs_buff[55] = adapter->stats.algnerrc; -+ regs_buff[56] = adapter->stats.symerrs; -+ regs_buff[57] = adapter->stats.rxerrc; -+ regs_buff[58] = adapter->stats.mpc; -+ regs_buff[59] = adapter->stats.scc; -+ regs_buff[60] = adapter->stats.ecol; -+ regs_buff[61] = adapter->stats.mcc; -+ regs_buff[62] = adapter->stats.latecol; -+ regs_buff[63] = adapter->stats.colc; -+ regs_buff[64] = adapter->stats.dc; -+ regs_buff[65] = adapter->stats.tncrs; -+ regs_buff[66] = adapter->stats.sec; -+ regs_buff[67] = adapter->stats.htdpmc; -+ regs_buff[68] = adapter->stats.rlec; -+ regs_buff[69] = adapter->stats.xonrxc; -+ regs_buff[70] = adapter->stats.xontxc; -+ regs_buff[71] = adapter->stats.xoffrxc; -+ regs_buff[72] = adapter->stats.xofftxc; -+ regs_buff[73] = adapter->stats.fcruc; -+ regs_buff[74] = adapter->stats.prc64; -+ regs_buff[75] = adapter->stats.prc127; -+ regs_buff[76] = adapter->stats.prc255; -+ regs_buff[77] = adapter->stats.prc511; -+ regs_buff[78] = adapter->stats.prc1023; -+ regs_buff[79] = adapter->stats.prc1522; -+ regs_buff[80] = adapter->stats.gprc; -+ regs_buff[81] = adapter->stats.bprc; -+ regs_buff[82] = adapter->stats.mprc; -+ regs_buff[83] = adapter->stats.gptc; -+ regs_buff[84] = adapter->stats.gorc; -+ regs_buff[86] = adapter->stats.gotc; -+ regs_buff[88] = adapter->stats.rnbc; -+ regs_buff[89] = adapter->stats.ruc; -+ regs_buff[90] = adapter->stats.rfc; -+ regs_buff[91] = adapter->stats.roc; -+ regs_buff[92] = adapter->stats.rjc; -+ regs_buff[93] = adapter->stats.mgprc; -+ regs_buff[94] = adapter->stats.mgpdc; -+ regs_buff[95] = adapter->stats.mgptc; -+ regs_buff[96] = adapter->stats.tor; -+ regs_buff[98] = adapter->stats.tot; -+ regs_buff[100] = adapter->stats.tpr; -+ regs_buff[101] = adapter->stats.tpt; -+ regs_buff[102] = adapter->stats.ptc64; -+ regs_buff[103] = adapter->stats.ptc127; -+ regs_buff[104] = adapter->stats.ptc255; -+ regs_buff[105] = adapter->stats.ptc511; -+ regs_buff[106] = adapter->stats.ptc1023; -+ regs_buff[107] = adapter->stats.ptc1522; -+ regs_buff[108] = adapter->stats.mptc; -+ regs_buff[109] = adapter->stats.bptc; -+ regs_buff[110] = adapter->stats.tsctc; -+ regs_buff[111] = adapter->stats.iac; -+ regs_buff[112] = adapter->stats.rpthc; -+ regs_buff[113] = adapter->stats.hgptc; -+ regs_buff[114] = adapter->stats.hgorc; -+ regs_buff[116] = adapter->stats.hgotc; -+ regs_buff[118] = adapter->stats.lenerrs; -+ regs_buff[119] = adapter->stats.scvpc; -+ regs_buff[120] = adapter->stats.hrmpc; ++ ecmd->advertising = (ADVERTISED_1000baseT_Full | ++ ADVERTISED_FIBRE | ++ ADVERTISED_Autoneg); + -+ for (i = 0; i < 4; i++) -+ regs_buff[121 + i] = E1000_READ_REG(hw, E1000_SRRCTL(i)); -+ for (i = 0; i < 4; i++) -+ regs_buff[125 + i] = E1000_READ_REG(hw, E1000_PSRTYPE(i)); -+ for (i = 0; i < 4; i++) -+ regs_buff[129 + i] = E1000_READ_REG(hw, E1000_RDBAL(i)); -+ for (i = 0; i < 4; i++) -+ regs_buff[133 + i] = E1000_READ_REG(hw, E1000_RDBAH(i)); -+ for (i = 0; i < 4; i++) -+ regs_buff[137 + i] = E1000_READ_REG(hw, E1000_RDLEN(i)); -+ for (i = 0; i < 4; i++) -+ regs_buff[141 + i] = E1000_READ_REG(hw, E1000_RDH(i)); -+ for (i = 0; i < 4; i++) -+ regs_buff[145 + i] = E1000_READ_REG(hw, E1000_RDT(i)); -+ for (i = 0; i < 4; i++) -+ regs_buff[149 + i] = E1000_READ_REG(hw, E1000_RXDCTL(i)); ++ ecmd->port = PORT_FIBRE; ++ } + -+ for (i = 0; i < 10; i++) -+ regs_buff[153 + i] = E1000_READ_REG(hw, E1000_EITR(i)); -+ for (i = 0; i < 8; i++) -+ regs_buff[163 + i] = E1000_READ_REG(hw, E1000_IMIR(i)); -+ for (i = 0; i < 8; i++) -+ regs_buff[171 + i] = E1000_READ_REG(hw, E1000_IMIREXT(i)); -+ for (i = 0; i < 16; i++) -+ regs_buff[179 + i] = E1000_READ_REG(hw, E1000_RAL(i)); -+ for (i = 0; i < 16; i++) -+ regs_buff[195 + i] = E1000_READ_REG(hw, E1000_RAH(i)); ++ ecmd->transceiver = XCVR_INTERNAL; + -+ for (i = 0; i < 4; i++) -+ regs_buff[211 + i] = E1000_READ_REG(hw, E1000_TDBAL(i)); -+ for (i = 0; i < 4; i++) -+ regs_buff[215 + i] = E1000_READ_REG(hw, E1000_TDBAH(i)); -+ for (i = 0; i < 4; i++) -+ regs_buff[219 + i] = E1000_READ_REG(hw, E1000_TDLEN(i)); -+ for (i = 0; i < 4; i++) -+ regs_buff[223 + i] = E1000_READ_REG(hw, E1000_TDH(i)); -+ for (i = 0; i < 4; i++) -+ regs_buff[227 + i] = E1000_READ_REG(hw, E1000_TDT(i)); -+ for (i = 0; i < 4; i++) -+ regs_buff[231 + i] = E1000_READ_REG(hw, E1000_TXDCTL(i)); -+ for (i = 0; i < 4; i++) -+ regs_buff[235 + i] = E1000_READ_REG(hw, E1000_TDWBAL(i)); -+ for (i = 0; i < 4; i++) -+ regs_buff[239 + i] = E1000_READ_REG(hw, E1000_TDWBAH(i)); -+ for (i = 0; i < 4; i++) -+ regs_buff[243 + i] = E1000_READ_REG(hw, E1000_DCA_TXCTRL(i)); ++ status = E1000_READ_REG(hw, E1000_STATUS); + -+ for (i = 0; i < 4; i++) -+ regs_buff[247 + i] = E1000_READ_REG(hw, E1000_IP4AT_REG(i)); -+ for (i = 0; i < 4; i++) -+ regs_buff[251 + i] = E1000_READ_REG(hw, E1000_IP6AT_REG(i)); -+ for (i = 0; i < 32; i++) -+ regs_buff[255 + i] = E1000_READ_REG(hw, E1000_WUPM_REG(i)); -+ for (i = 0; i < 128; i++) -+ regs_buff[287 + i] = E1000_READ_REG(hw, E1000_FFMT_REG(i)); -+ for (i = 0; i < 128; i++) -+ regs_buff[415 + i] = E1000_READ_REG(hw, E1000_FFVT_REG(i)); -+ for (i = 0; i < 4; i++) -+ regs_buff[543 + i] = E1000_READ_REG(hw, E1000_FFLT_REG(i)); ++ if (status & E1000_STATUS_LU) { + -+ regs_buff[547] = E1000_READ_REG(hw, E1000_TDFH); -+ regs_buff[548] = E1000_READ_REG(hw, E1000_TDFT); -+ regs_buff[549] = E1000_READ_REG(hw, E1000_TDFHS); -+ regs_buff[550] = E1000_READ_REG(hw, E1000_TDFPC); ++ if ((status & E1000_STATUS_SPEED_1000) || ++ hw->phy.media_type != e1000_media_type_copper) ++ ecmd->speed = SPEED_1000; ++ else if (status & E1000_STATUS_SPEED_100) ++ ecmd->speed = SPEED_100; ++ else ++ ecmd->speed = SPEED_10; + -+} ++ if ((status & E1000_STATUS_FD) || ++ hw->phy.media_type != e1000_media_type_copper) ++ ecmd->duplex = DUPLEX_FULL; ++ else ++ ecmd->duplex = DUPLEX_HALF; ++ } else { ++ ecmd->speed = -1; ++ ecmd->duplex = -1; ++ } + -+static int igb_get_eeprom_len(struct net_device *netdev) -+{ -+ struct igb_adapter *adapter = netdev_priv(netdev); -+ return adapter->hw.nvm.word_size * 2; ++ ecmd->autoneg = hw->mac.autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; ++ return 0; +} + -+static int igb_get_eeprom(struct net_device *netdev, -+ struct ethtool_eeprom *eeprom, u8 *bytes) ++static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) +{ + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; -+ u16 *eeprom_buff; -+ int first_word, last_word; -+ int ret_val = 0; -+ u16 i; + -+ if (eeprom->len == 0) ++ /* When SoL/IDER sessions are active, autoneg/speed/duplex ++ * cannot be changed */ ++ if (e1000_check_reset_block(hw)) { ++ DPRINTK(DRV, ERR, "Cannot change link characteristics " ++ "when SoL/IDER is active.\n"); + return -EINVAL; ++ } + -+ eeprom->magic = hw->vendor_id | (hw->device_id << 16); -+ -+ first_word = eeprom->offset >> 1; -+ last_word = (eeprom->offset + eeprom->len - 1) >> 1; -+ -+ eeprom_buff = kmalloc(sizeof(u16) * -+ (last_word - first_word + 1), GFP_KERNEL); -+ if (!eeprom_buff) -+ return -ENOMEM; ++ while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) ++ msleep(1); + -+ if (hw->nvm.type == e1000_nvm_eeprom_spi) -+ ret_val = e1000_read_nvm(hw, first_word, -+ last_word - first_word + 1, -+ eeprom_buff); -+ else { -+ for (i = 0; i < last_word - first_word + 1; i++) { -+ ret_val = e1000_read_nvm(hw, first_word + i, 1, -+ &eeprom_buff[i]); -+ if (ret_val) -+ break; ++ if (ecmd->autoneg == AUTONEG_ENABLE) { ++ hw->mac.autoneg = 1; ++ hw->phy.autoneg_advertised = ecmd->advertising | ++ ADVERTISED_TP | ++ ADVERTISED_Autoneg; ++ ecmd->advertising = hw->phy.autoneg_advertised; ++ if (adapter->fc_autoneg) ++ hw->fc.requested_mode = e1000_fc_default; ++ } else { ++ if (igb_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) { ++ clear_bit(__IGB_RESETTING, &adapter->state); ++ return -EINVAL; + } + } + -+ /* Device's eeprom is always little-endian, word addressable */ -+ for (i = 0; i < last_word - first_word + 1; i++) -+ le16_to_cpus(&eeprom_buff[i]); -+ -+ memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), -+ eeprom->len); -+ kfree(eeprom_buff); ++ /* reset the link */ ++ if (netif_running(adapter->netdev)) { ++ igb_down(adapter); ++ igb_up(adapter); ++ } else ++ igb_reset(adapter); + -+ return ret_val; ++ clear_bit(__IGB_RESETTING, &adapter->state); ++ return 0; +} + -+static int igb_set_eeprom(struct net_device *netdev, -+ struct ethtool_eeprom *eeprom, u8 *bytes) ++static void igb_get_pauseparam(struct net_device *netdev, ++ struct ethtool_pauseparam *pause) +{ + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; -+ u16 *eeprom_buff; -+ void *ptr; -+ int max_len, first_word, last_word, ret_val = 0; -+ u16 i; + -+ if (eeprom->len == 0) -+ return -EOPNOTSUPP; -+ -+ if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) -+ return -EFAULT; -+ -+ max_len = hw->nvm.word_size * 2; -+ -+ first_word = eeprom->offset >> 1; -+ last_word = (eeprom->offset + eeprom->len - 1) >> 1; -+ eeprom_buff = kmalloc(max_len, GFP_KERNEL); -+ if (!eeprom_buff) -+ return -ENOMEM; -+ -+ ptr = (void *)eeprom_buff; ++ pause->autoneg = ++ (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); + -+ if (eeprom->offset & 1) { -+ /* need read/modify/write of first changed EEPROM word */ -+ /* only the second byte of the word is being modified */ -+ ret_val = e1000_read_nvm(hw, first_word, 1, -+ &eeprom_buff[0]); -+ ptr++; -+ } -+ if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) { -+ /* need read/modify/write of last changed EEPROM word */ -+ /* only the first byte of the word is being modified */ -+ ret_val = e1000_read_nvm(hw, last_word, 1, -+ &eeprom_buff[last_word - first_word]); ++ if (hw->fc.current_mode == e1000_fc_rx_pause) ++ pause->rx_pause = 1; ++ else if (hw->fc.current_mode == e1000_fc_tx_pause) ++ pause->tx_pause = 1; ++ else if (hw->fc.current_mode == e1000_fc_full) { ++ pause->rx_pause = 1; ++ pause->tx_pause = 1; + } ++} + -+ /* Device's eeprom is always little-endian, word addressable */ -+ for (i = 0; i < last_word - first_word + 1; i++) -+ le16_to_cpus(&eeprom_buff[i]); ++static int igb_set_pauseparam(struct net_device *netdev, ++ struct ethtool_pauseparam *pause) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ struct e1000_hw *hw = &adapter->hw; ++ int retval = 0; + -+ memcpy(ptr, bytes, eeprom->len); ++ adapter->fc_autoneg = pause->autoneg; + -+ for (i = 0; i < last_word - first_word + 1; i++) -+ eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]); ++ while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) ++ msleep(1); + -+ ret_val = e1000_write_nvm(hw, first_word, -+ last_word - first_word + 1, eeprom_buff); ++ if (adapter->fc_autoneg == AUTONEG_ENABLE) { ++ hw->fc.requested_mode = e1000_fc_default; ++ if (netif_running(adapter->netdev)) { ++ igb_down(adapter); ++ igb_up(adapter); ++ } else { ++ igb_reset(adapter); ++ } ++ } else { ++ if (pause->rx_pause && pause->tx_pause) ++ hw->fc.requested_mode = e1000_fc_full; ++ else if (pause->rx_pause && !pause->tx_pause) ++ hw->fc.requested_mode = e1000_fc_rx_pause; ++ else if (!pause->rx_pause && pause->tx_pause) ++ hw->fc.requested_mode = e1000_fc_tx_pause; ++ else if (!pause->rx_pause && !pause->tx_pause) ++ hw->fc.requested_mode = e1000_fc_none; + -+ /* Update the checksum over the first part of the EEPROM if needed -+ * and flush shadow RAM for 82573 controllers */ -+ if ((ret_val == 0) && ((first_word <= NVM_CHECKSUM_REG))) -+ e1000_update_nvm_checksum(hw); ++ hw->fc.current_mode = hw->fc.requested_mode; + -+ kfree(eeprom_buff); -+ return ret_val; ++ retval = ((hw->phy.media_type == e1000_media_type_copper) ? ++ e1000_force_mac_fc(hw) : hw->mac.ops.setup_link(hw)); ++ } ++ ++ clear_bit(__IGB_RESETTING, &adapter->state); ++ return retval; +} + -+static void igb_get_drvinfo(struct net_device *netdev, -+ struct ethtool_drvinfo *drvinfo) ++static u32 igb_get_rx_csum(struct net_device *netdev) +{ + struct igb_adapter *adapter = netdev_priv(netdev); -+ char firmware_version[32]; -+ u16 eeprom_data; ++ return adapter->rx_ring[0].rx_csum; ++} + -+ strncpy(drvinfo->driver, igb_driver_name, 32); -+ strncpy(drvinfo->version, igb_driver_version, 32); ++static int igb_set_rx_csum(struct net_device *netdev, u32 data) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ int i; + -+ /* EEPROM image version # is reported as firmware version # for -+ * 82575 controllers */ -+ e1000_read_nvm(&adapter->hw, 5, 1, &eeprom_data); -+ sprintf(firmware_version, "%d.%d-%d", -+ (eeprom_data & 0xF000) >> 12, -+ (eeprom_data & 0x0FF0) >> 4, -+ eeprom_data & 0x000F); ++ for (i = 0; i < adapter->num_rx_queues; i++) ++ adapter->rx_ring[i].rx_csum = !!data; + -+ strncpy(drvinfo->fw_version, firmware_version, 32); -+ strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); -+ drvinfo->n_stats = IGB_STATS_LEN; -+ drvinfo->testinfo_len = IGB_TEST_LEN; -+ drvinfo->regdump_len = igb_get_regs_len(netdev); -+ drvinfo->eedump_len = igb_get_eeprom_len(netdev); ++ return 0; +} + -+static void igb_get_ringparam(struct net_device *netdev, -+ struct ethtool_ringparam *ring) ++static u32 igb_get_tx_csum(struct net_device *netdev) +{ -+ struct igb_adapter *adapter = netdev_priv(netdev); -+ struct igb_ring *tx_ring = adapter->tx_ring; -+ struct igb_ring *rx_ring = adapter->rx_ring; -+ -+ ring->rx_max_pending = IGB_MAX_RXD; -+ ring->tx_max_pending = IGB_MAX_TXD; -+ ring->rx_mini_max_pending = 0; -+ ring->rx_jumbo_max_pending = 0; -+ ring->rx_pending = rx_ring->count; -+ ring->tx_pending = tx_ring->count; -+ ring->rx_mini_pending = 0; -+ ring->rx_jumbo_pending = 0; ++ return (netdev->features & NETIF_F_IP_CSUM) != 0; +} + -+static int igb_set_ringparam(struct net_device *netdev, -+ struct ethtool_ringparam *ring) ++static int igb_set_tx_csum(struct net_device *netdev, u32 data) +{ + struct igb_adapter *adapter = netdev_priv(netdev); -+ struct igb_ring *temp_ring; -+ int i, err; -+ u32 new_rx_count, new_tx_count; -+ -+ if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) -+ return -EINVAL; -+ -+ new_rx_count = max(ring->rx_pending, (u32)IGB_MIN_RXD); -+ new_rx_count = min(new_rx_count, (u32)IGB_MAX_RXD); -+ new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE); + -+ new_tx_count = max(ring->tx_pending, (u32)IGB_MIN_TXD); -+ new_tx_count = min(new_tx_count, (u32)IGB_MAX_TXD); -+ new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE); -+ -+ if ((new_tx_count == adapter->tx_ring_count) && -+ (new_rx_count == adapter->rx_ring_count)) { -+ /* nothing to do */ -+ return 0; ++ if (data) { ++#ifdef NETIF_F_IPV6_CSUM ++ netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); ++ if (adapter->hw.mac.type >= e1000_82576) ++ netdev->features |= NETIF_F_SCTP_CSUM; ++ } else { ++ netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | ++ NETIF_F_SCTP_CSUM); ++#else ++ netdev->features |= NETIF_F_IP_CSUM; ++ if (adapter->hw.mac.type == e1000_82576) ++ netdev->features |= NETIF_F_SCTP_CSUM; ++ } else { ++ netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_SCTP_CSUM); ++#endif + } + -+ if (adapter->num_tx_queues > adapter->num_rx_queues) -+ temp_ring = vmalloc(adapter->num_tx_queues * sizeof(struct igb_ring)); -+ else -+ temp_ring = vmalloc(adapter->num_rx_queues * sizeof(struct igb_ring)); -+ if (!temp_ring) -+ return -ENOMEM; -+ -+ while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) -+ msleep(1); -+ -+ if (netif_running(adapter->netdev)) -+ igb_down(adapter); -+ -+ /* -+ * We can't just free everything and then setup again, -+ * because the ISRs in MSI-X mode get passed pointers -+ * to the tx and rx ring structs. -+ */ -+ if (new_tx_count != adapter->tx_ring_count) { -+ memcpy(temp_ring, adapter->tx_ring, -+ adapter->num_tx_queues * sizeof(struct igb_ring)); -+ -+ for (i = 0; i < adapter->num_tx_queues; i++) { -+ temp_ring[i].count = new_tx_count; -+ err = igb_setup_tx_resources(adapter, &temp_ring[i]); -+ if (err) { -+ while (i) { -+ i--; -+ igb_free_tx_resources(&temp_ring[i]); -+ } -+ goto err_setup; -+ } -+ } -+ -+ for (i = 0; i < adapter->num_tx_queues; i++) -+ igb_free_tx_resources(&adapter->tx_ring[i]); -+ -+ memcpy(adapter->tx_ring, temp_ring, -+ adapter->num_tx_queues * sizeof(struct igb_ring)); -+ -+ adapter->tx_ring_count = new_tx_count; -+ } ++ return 0; ++} + -+ if (new_rx_count != adapter->rx_ring->count) { -+ memcpy(temp_ring, adapter->rx_ring, -+ adapter->num_rx_queues * sizeof(struct igb_ring)); ++#ifdef NETIF_F_TSO ++static int igb_set_tso(struct net_device *netdev, u32 data) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ int i; ++ struct net_device *v_netdev; + -+ for (i = 0; i < adapter->num_rx_queues; i++) { -+ temp_ring[i].count = new_rx_count; -+ err = igb_setup_rx_resources(adapter, &temp_ring[i]); -+ if (err) { -+ while (i) { -+ i--; -+ igb_free_rx_resources(&temp_ring[i]); -+ } -+ goto err_setup; -+ } ++ if (data) { ++ netdev->features |= NETIF_F_TSO; ++#ifdef NETIF_F_TSO6 ++ netdev->features |= NETIF_F_TSO6; ++#endif ++ } else { ++ netdev->features &= ~NETIF_F_TSO; ++#ifdef NETIF_F_TSO6 ++ netdev->features &= ~NETIF_F_TSO6; ++#endif ++ /* disable TSO on all VLANs if they're present */ ++ if (!adapter->vlgrp) ++ goto tso_out; ++ for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { ++ v_netdev = vlan_group_get_device(adapter->vlgrp, i); ++ if (!v_netdev) ++ continue; + ++ v_netdev->features &= ~NETIF_F_TSO; ++#ifdef NETIF_F_TSO6 ++ v_netdev->features &= ~NETIF_F_TSO6; ++#endif ++ vlan_group_set_device(adapter->vlgrp, i, v_netdev); + } -+ -+ for (i = 0; i < adapter->num_rx_queues; i++) -+ igb_free_rx_resources(&adapter->rx_ring[i]); -+ -+ memcpy(adapter->rx_ring, temp_ring, -+ adapter->num_rx_queues * sizeof(struct igb_ring)); -+ -+ adapter->rx_ring_count = new_rx_count; + } + -+ err = 0; -+err_setup: -+ if (netif_running(adapter->netdev)) -+ igb_up(adapter); ++tso_out: ++ DPRINTK(PROBE, INFO, "TSO is %s\n", data ? "Enabled" : "Disabled"); ++ return 0; ++} ++#endif /* NETIF_F_TSO */ + -+ clear_bit(__IGB_RESETTING, &adapter->state); -+ vfree(temp_ring); -+ return err; ++static u32 igb_get_msglevel(struct net_device *netdev) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ return adapter->msg_enable; +} + -+static bool reg_pattern_test(struct igb_adapter *adapter, u64 *data, -+ int reg, u32 mask, u32 write) ++static void igb_set_msglevel(struct net_device *netdev, u32 data) +{ -+ struct e1000_hw *hw = &adapter->hw; -+ u32 pat, val; -+ static const u32 _test[] = -+ {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; -+ for (pat = 0; pat < ARRAY_SIZE(_test); pat++) { -+ E1000_WRITE_REG(hw, reg, (_test[pat] & write)); -+ val = E1000_READ_REG(hw, reg); -+ if (val != (_test[pat] & write & mask)) { -+ DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " -+ "0x%08X expected 0x%08X\n", -+ E1000_REGISTER(hw, reg), val, -+ (_test[pat] & write & mask)); -+ *data = E1000_REGISTER(hw, reg); -+ return 1; -+ } -+ } ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ adapter->msg_enable = data; ++} + -+ return 0; ++static int igb_get_regs_len(struct net_device *netdev) ++{ ++#define IGB_REGS_LEN 551 ++ return IGB_REGS_LEN * sizeof(u32); +} + -+static bool reg_set_and_check(struct igb_adapter *adapter, u64 *data, -+ int reg, u32 mask, u32 write) ++static void igb_get_regs(struct net_device *netdev, ++ struct ethtool_regs *regs, void *p) +{ ++ struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; -+ u32 val; -+ E1000_WRITE_REG(hw, reg, write & mask); -+ val = E1000_READ_REG(hw, reg); -+ if ((write & mask) != (val & mask)) { -+ DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X " -+ "expected 0x%08X\n", reg, (val & mask), (write & mask)); -+ *data = E1000_REGISTER(hw, reg); -+ return 1; -+ } ++ u32 *regs_buff = p; ++ u8 i; + -+ return 0; -+} ++ memset(p, 0, IGB_REGS_LEN * sizeof(u32)); + -+#define REG_PATTERN_TEST(reg, mask, write) \ -+ do { \ -+ if (reg_pattern_test(adapter, data, reg, mask, write)) \ -+ return 1; \ -+ } while (0) ++ regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; + -+#define REG_SET_AND_CHECK(reg, mask, write) \ -+ do { \ -+ if (reg_set_and_check(adapter, data, reg, mask, write)) \ -+ return 1; \ -+ } while (0) ++ /* General Registers */ ++ regs_buff[0] = E1000_READ_REG(hw, E1000_CTRL); ++ regs_buff[1] = E1000_READ_REG(hw, E1000_STATUS); ++ regs_buff[2] = E1000_READ_REG(hw, E1000_CTRL_EXT); ++ regs_buff[3] = E1000_READ_REG(hw, E1000_MDIC); ++ regs_buff[4] = E1000_READ_REG(hw, E1000_SCTL); ++ regs_buff[5] = E1000_READ_REG(hw, E1000_CONNSW); ++ regs_buff[6] = E1000_READ_REG(hw, E1000_VET); ++ regs_buff[7] = E1000_READ_REG(hw, E1000_LEDCTL); ++ regs_buff[8] = E1000_READ_REG(hw, E1000_PBA); ++ regs_buff[9] = E1000_READ_REG(hw, E1000_PBS); ++ regs_buff[10] = E1000_READ_REG(hw, E1000_FRTIMER); ++ regs_buff[11] = E1000_READ_REG(hw, E1000_TCPTIMER); + -+static int igb_reg_test(struct igb_adapter *adapter, u64 *data) -+{ -+ struct e1000_hw *hw = &adapter->hw; -+ struct igb_reg_test *test; -+ u32 value, before, after; -+ u32 i, toggle; ++ /* NVM Register */ ++ regs_buff[12] = E1000_READ_REG(hw, E1000_EECD); ++ ++ /* Interrupt */ ++ /* Reading EICS for EICR because they read the ++ * same but EICS does not clear on read */ ++ regs_buff[13] = E1000_READ_REG(hw, E1000_EICS); ++ regs_buff[14] = E1000_READ_REG(hw, E1000_EICS); ++ regs_buff[15] = E1000_READ_REG(hw, E1000_EIMS); ++ regs_buff[16] = E1000_READ_REG(hw, E1000_EIMC); ++ regs_buff[17] = E1000_READ_REG(hw, E1000_EIAC); ++ regs_buff[18] = E1000_READ_REG(hw, E1000_EIAM); ++ /* Reading ICS for ICR because they read the ++ * same but ICS does not clear on read */ ++ regs_buff[19] = E1000_READ_REG(hw, E1000_ICS); ++ regs_buff[20] = E1000_READ_REG(hw, E1000_ICS); ++ regs_buff[21] = E1000_READ_REG(hw, E1000_IMS); ++ regs_buff[22] = E1000_READ_REG(hw, E1000_IMC); ++ regs_buff[23] = E1000_READ_REG(hw, E1000_IAC); ++ regs_buff[24] = E1000_READ_REG(hw, E1000_IAM); ++ regs_buff[25] = E1000_READ_REG(hw, E1000_IMIRVP); + -+ toggle = 0x7FFFF3FF; ++ /* Flow Control */ ++ regs_buff[26] = E1000_READ_REG(hw, E1000_FCAL); ++ regs_buff[27] = E1000_READ_REG(hw, E1000_FCAH); ++ regs_buff[28] = E1000_READ_REG(hw, E1000_FCTTV); ++ regs_buff[29] = E1000_READ_REG(hw, E1000_FCRTL); ++ regs_buff[30] = E1000_READ_REG(hw, E1000_FCRTH); ++ regs_buff[31] = E1000_READ_REG(hw, E1000_FCRTV); + -+ switch (adapter->hw.mac.type) { -+ case e1000_82576: -+ test = reg_test_82576; -+ break; -+ default: -+ test = reg_test_82575; -+ break; -+ } ++ /* Receive */ ++ regs_buff[32] = E1000_READ_REG(hw, E1000_RCTL); ++ regs_buff[33] = E1000_READ_REG(hw, E1000_RXCSUM); ++ regs_buff[34] = E1000_READ_REG(hw, E1000_RLPML); ++ regs_buff[35] = E1000_READ_REG(hw, E1000_RFCTL); ++ regs_buff[36] = E1000_READ_REG(hw, E1000_MRQC); ++ regs_buff[37] = E1000_READ_REG(hw, E1000_VT_CTL); + -+ /* Because the status register is such a special case, -+ * we handle it separately from the rest of the register -+ * tests. Some bits are read-only, some toggle, and some -+ * are writable on newer MACs. -+ */ -+ before = E1000_READ_REG(hw, E1000_STATUS); -+ value = (E1000_READ_REG(hw, E1000_STATUS) & toggle); -+ E1000_WRITE_REG(hw, E1000_STATUS, toggle); -+ after = E1000_READ_REG(hw, E1000_STATUS) & toggle; -+ if (value != after) { -+ DPRINTK(DRV, ERR, "failed STATUS register test got: " -+ "0x%08X expected: 0x%08X\n", after, value); -+ *data = 1; -+ return 1; -+ } -+ /* restore previous status */ -+ E1000_WRITE_REG(hw, E1000_STATUS, before); ++ /* Transmit */ ++ regs_buff[38] = E1000_READ_REG(hw, E1000_TCTL); ++ regs_buff[39] = E1000_READ_REG(hw, E1000_TCTL_EXT); ++ regs_buff[40] = E1000_READ_REG(hw, E1000_TIPG); ++ regs_buff[41] = E1000_READ_REG(hw, E1000_DTXCTL); ++ ++ /* Wake Up */ ++ regs_buff[42] = E1000_READ_REG(hw, E1000_WUC); ++ regs_buff[43] = E1000_READ_REG(hw, E1000_WUFC); ++ regs_buff[44] = E1000_READ_REG(hw, E1000_WUS); ++ regs_buff[45] = E1000_READ_REG(hw, E1000_IPAV); ++ regs_buff[46] = E1000_READ_REG(hw, E1000_WUPL); ++ ++ /* MAC */ ++ regs_buff[47] = E1000_READ_REG(hw, E1000_PCS_CFG0); ++ regs_buff[48] = E1000_READ_REG(hw, E1000_PCS_LCTL); ++ regs_buff[49] = E1000_READ_REG(hw, E1000_PCS_LSTAT); ++ regs_buff[50] = E1000_READ_REG(hw, E1000_PCS_ANADV); ++ regs_buff[51] = E1000_READ_REG(hw, E1000_PCS_LPAB); ++ regs_buff[52] = E1000_READ_REG(hw, E1000_PCS_NPTX); ++ regs_buff[53] = E1000_READ_REG(hw, E1000_PCS_LPABNP); ++ ++ /* Statistics */ ++ regs_buff[54] = adapter->stats.crcerrs; ++ regs_buff[55] = adapter->stats.algnerrc; ++ regs_buff[56] = adapter->stats.symerrs; ++ regs_buff[57] = adapter->stats.rxerrc; ++ regs_buff[58] = adapter->stats.mpc; ++ regs_buff[59] = adapter->stats.scc; ++ regs_buff[60] = adapter->stats.ecol; ++ regs_buff[61] = adapter->stats.mcc; ++ regs_buff[62] = adapter->stats.latecol; ++ regs_buff[63] = adapter->stats.colc; ++ regs_buff[64] = adapter->stats.dc; ++ regs_buff[65] = adapter->stats.tncrs; ++ regs_buff[66] = adapter->stats.sec; ++ regs_buff[67] = adapter->stats.htdpmc; ++ regs_buff[68] = adapter->stats.rlec; ++ regs_buff[69] = adapter->stats.xonrxc; ++ regs_buff[70] = adapter->stats.xontxc; ++ regs_buff[71] = adapter->stats.xoffrxc; ++ regs_buff[72] = adapter->stats.xofftxc; ++ regs_buff[73] = adapter->stats.fcruc; ++ regs_buff[74] = adapter->stats.prc64; ++ regs_buff[75] = adapter->stats.prc127; ++ regs_buff[76] = adapter->stats.prc255; ++ regs_buff[77] = adapter->stats.prc511; ++ regs_buff[78] = adapter->stats.prc1023; ++ regs_buff[79] = adapter->stats.prc1522; ++ regs_buff[80] = adapter->stats.gprc; ++ regs_buff[81] = adapter->stats.bprc; ++ regs_buff[82] = adapter->stats.mprc; ++ regs_buff[83] = adapter->stats.gptc; ++ regs_buff[84] = adapter->stats.gorc; ++ regs_buff[86] = adapter->stats.gotc; ++ regs_buff[88] = adapter->stats.rnbc; ++ regs_buff[89] = adapter->stats.ruc; ++ regs_buff[90] = adapter->stats.rfc; ++ regs_buff[91] = adapter->stats.roc; ++ regs_buff[92] = adapter->stats.rjc; ++ regs_buff[93] = adapter->stats.mgprc; ++ regs_buff[94] = adapter->stats.mgpdc; ++ regs_buff[95] = adapter->stats.mgptc; ++ regs_buff[96] = adapter->stats.tor; ++ regs_buff[98] = adapter->stats.tot; ++ regs_buff[100] = adapter->stats.tpr; ++ regs_buff[101] = adapter->stats.tpt; ++ regs_buff[102] = adapter->stats.ptc64; ++ regs_buff[103] = adapter->stats.ptc127; ++ regs_buff[104] = adapter->stats.ptc255; ++ regs_buff[105] = adapter->stats.ptc511; ++ regs_buff[106] = adapter->stats.ptc1023; ++ regs_buff[107] = adapter->stats.ptc1522; ++ regs_buff[108] = adapter->stats.mptc; ++ regs_buff[109] = adapter->stats.bptc; ++ regs_buff[110] = adapter->stats.tsctc; ++ regs_buff[111] = adapter->stats.iac; ++ regs_buff[112] = adapter->stats.rpthc; ++ regs_buff[113] = adapter->stats.hgptc; ++ regs_buff[114] = adapter->stats.hgorc; ++ regs_buff[116] = adapter->stats.hgotc; ++ regs_buff[118] = adapter->stats.lenerrs; ++ regs_buff[119] = adapter->stats.scvpc; ++ regs_buff[120] = adapter->stats.hrmpc; + -+ /* Perform the remainder of the register test, looping through -+ * the test table until we either fail or reach the null entry. -+ */ -+ while (test->reg) { -+ for (i = 0; i < test->array_len; i++) { -+ switch (test->test_type) { -+ case PATTERN_TEST: -+ REG_PATTERN_TEST(test->reg + -+ (i * test->reg_offset), -+ test->mask, -+ test->write); -+ break; -+ case SET_READ_TEST: -+ REG_SET_AND_CHECK(test->reg + -+ (i * test->reg_offset), -+ test->mask, -+ test->write); -+ break; -+ case WRITE_NO_TEST: -+ writel(test->write, -+ (adapter->hw.hw_addr + test->reg) -+ + (i * test->reg_offset)); -+ break; -+ case TABLE32_TEST: -+ REG_PATTERN_TEST(test->reg + (i * 4), -+ test->mask, -+ test->write); -+ break; -+ case TABLE64_TEST_LO: -+ REG_PATTERN_TEST(test->reg + (i * 8), -+ test->mask, -+ test->write); -+ break; -+ case TABLE64_TEST_HI: -+ REG_PATTERN_TEST((test->reg + 4) + (i * 8), -+ test->mask, -+ test->write); -+ break; -+ } -+ } -+ test++; -+ } ++ for (i = 0; i < 4; i++) ++ regs_buff[121 + i] = E1000_READ_REG(hw, E1000_SRRCTL(i)); ++ for (i = 0; i < 4; i++) ++ regs_buff[125 + i] = E1000_READ_REG(hw, E1000_PSRTYPE(i)); ++ for (i = 0; i < 4; i++) ++ regs_buff[129 + i] = E1000_READ_REG(hw, E1000_RDBAL(i)); ++ for (i = 0; i < 4; i++) ++ regs_buff[133 + i] = E1000_READ_REG(hw, E1000_RDBAH(i)); ++ for (i = 0; i < 4; i++) ++ regs_buff[137 + i] = E1000_READ_REG(hw, E1000_RDLEN(i)); ++ for (i = 0; i < 4; i++) ++ regs_buff[141 + i] = E1000_READ_REG(hw, E1000_RDH(i)); ++ for (i = 0; i < 4; i++) ++ regs_buff[145 + i] = E1000_READ_REG(hw, E1000_RDT(i)); ++ for (i = 0; i < 4; i++) ++ regs_buff[149 + i] = E1000_READ_REG(hw, E1000_RXDCTL(i)); + -+ *data = 0; -+ return 0; -+} ++ for (i = 0; i < 10; i++) ++ regs_buff[153 + i] = E1000_READ_REG(hw, E1000_EITR(i)); ++ for (i = 0; i < 8; i++) ++ regs_buff[163 + i] = E1000_READ_REG(hw, E1000_IMIR(i)); ++ for (i = 0; i < 8; i++) ++ regs_buff[171 + i] = E1000_READ_REG(hw, E1000_IMIREXT(i)); ++ for (i = 0; i < 16; i++) ++ regs_buff[179 + i] = E1000_READ_REG(hw, E1000_RAL(i)); ++ for (i = 0; i < 16; i++) ++ regs_buff[195 + i] = E1000_READ_REG(hw, E1000_RAH(i)); + -+static int igb_eeprom_test(struct igb_adapter *adapter, u64 *data) -+{ -+ u16 temp; -+ u16 checksum = 0; -+ u16 i; ++ for (i = 0; i < 4; i++) ++ regs_buff[211 + i] = E1000_READ_REG(hw, E1000_TDBAL(i)); ++ for (i = 0; i < 4; i++) ++ regs_buff[215 + i] = E1000_READ_REG(hw, E1000_TDBAH(i)); ++ for (i = 0; i < 4; i++) ++ regs_buff[219 + i] = E1000_READ_REG(hw, E1000_TDLEN(i)); ++ for (i = 0; i < 4; i++) ++ regs_buff[223 + i] = E1000_READ_REG(hw, E1000_TDH(i)); ++ for (i = 0; i < 4; i++) ++ regs_buff[227 + i] = E1000_READ_REG(hw, E1000_TDT(i)); ++ for (i = 0; i < 4; i++) ++ regs_buff[231 + i] = E1000_READ_REG(hw, E1000_TXDCTL(i)); ++ for (i = 0; i < 4; i++) ++ regs_buff[235 + i] = E1000_READ_REG(hw, E1000_TDWBAL(i)); ++ for (i = 0; i < 4; i++) ++ regs_buff[239 + i] = E1000_READ_REG(hw, E1000_TDWBAH(i)); ++ for (i = 0; i < 4; i++) ++ regs_buff[243 + i] = E1000_READ_REG(hw, E1000_DCA_TXCTRL(i)); + -+ *data = 0; -+ /* Read and add up the contents of the EEPROM */ -+ for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { -+ if ((e1000_read_nvm(&adapter->hw, i, 1, &temp)) < 0) { -+ *data = 1; -+ break; -+ } -+ checksum += temp; -+ } ++ for (i = 0; i < 4; i++) ++ regs_buff[247 + i] = E1000_READ_REG(hw, E1000_IP4AT_REG(i)); ++ for (i = 0; i < 4; i++) ++ regs_buff[251 + i] = E1000_READ_REG(hw, E1000_IP6AT_REG(i)); ++ for (i = 0; i < 32; i++) ++ regs_buff[255 + i] = E1000_READ_REG(hw, E1000_WUPM_REG(i)); ++ for (i = 0; i < 128; i++) ++ regs_buff[287 + i] = E1000_READ_REG(hw, E1000_FFMT_REG(i)); ++ for (i = 0; i < 128; i++) ++ regs_buff[415 + i] = E1000_READ_REG(hw, E1000_FFVT_REG(i)); ++ for (i = 0; i < 4; i++) ++ regs_buff[543 + i] = E1000_READ_REG(hw, E1000_FFLT_REG(i)); + -+ /* If Checksum is not Correct return error else test passed */ -+ if ((checksum != (u16) NVM_SUM) && !(*data)) -+ *data = 2; ++ regs_buff[547] = E1000_READ_REG(hw, E1000_TDFH); ++ regs_buff[548] = E1000_READ_REG(hw, E1000_TDFT); ++ regs_buff[549] = E1000_READ_REG(hw, E1000_TDFHS); ++ regs_buff[550] = E1000_READ_REG(hw, E1000_TDFPC); + -+ return *data; +} + -+static irqreturn_t igb_test_intr(int irq, void *data) ++static int igb_get_eeprom_len(struct net_device *netdev) +{ -+ struct net_device *netdev = (struct net_device *) data; + struct igb_adapter *adapter = netdev_priv(netdev); -+ struct e1000_hw *hw = &adapter->hw; -+ -+ adapter->test_icr |= E1000_READ_REG(hw, E1000_ICR); -+ -+ return IRQ_HANDLED; ++ return adapter->hw.nvm.word_size * 2; +} + -+static int igb_intr_test(struct igb_adapter *adapter, u64 *data) ++static int igb_get_eeprom(struct net_device *netdev, ++ struct ethtool_eeprom *eeprom, u8 *bytes) +{ ++ struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; -+ struct net_device *netdev = adapter->netdev; -+ u32 mask, i=0, shared_int = TRUE; -+ u32 irq = adapter->pdev->irq; -+ -+ *data = 0; -+ -+ /* Hook up test interrupt handler just for this test */ -+ if (adapter->msix_entries) { -+ /* NOTE: we don't test MSI-X interrupts here, yet */ -+ return 0; -+ } else if (adapter->flags & IGB_FLAG_HAS_MSI) { -+ shared_int = FALSE; -+ if (request_irq(irq, &igb_test_intr, 0, netdev->name, netdev)) { -+ *data = 1; -+ return -1; -+ } -+ } else if (!request_irq(irq, &igb_test_intr, IRQF_PROBE_SHARED, -+ netdev->name, netdev)) { -+ shared_int = FALSE; -+ } -+ else if (request_irq(irq, &igb_test_intr, IRQF_SHARED, -+ netdev->name, netdev)) { -+ *data = 1; -+ return -1; -+ } -+ DPRINTK(HW, INFO, "testing %s interrupt\n", -+ (shared_int ? "shared" : "unshared")); -+ -+ /* Disable all the interrupts */ -+ E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); -+ msleep(10); -+ -+ /* Test each interrupt */ -+ for (; i < 10; i++) { -+ /* Interrupt to test */ -+ mask = 1 << i; -+ -+ if (!shared_int) { -+ /* Disable the interrupt to be reported in -+ * the cause register and then force the same -+ * interrupt and see if one gets posted. If -+ * an interrupt was posted to the bus, the -+ * test failed. -+ */ -+ adapter->test_icr = 0; -+ E1000_WRITE_REG(hw, E1000_IMC, ~mask & 0x00007FFF); -+ E1000_WRITE_REG(hw, E1000_ICS, ~mask & 0x00007FFF); -+ msleep(10); ++ u16 *eeprom_buff; ++ int first_word, last_word; ++ int ret_val = 0; ++ u16 i; + -+ if (adapter->test_icr & mask) { -+ *data = 3; -+ break; -+ } -+ } ++ if (eeprom->len == 0) ++ return -EINVAL; + -+ /* Enable the interrupt to be reported in -+ * the cause register and then force the same -+ * interrupt and see if one gets posted. If -+ * an interrupt was not posted to the bus, the -+ * test failed. -+ */ -+ adapter->test_icr = 0; -+ E1000_WRITE_REG(hw, E1000_IMS, mask); -+ E1000_WRITE_REG(hw, E1000_ICS, mask); -+ msleep(10); ++ eeprom->magic = hw->vendor_id | (hw->device_id << 16); + -+ if (!(adapter->test_icr & mask)) { -+ *data = 4; -+ break; -+ } ++ first_word = eeprom->offset >> 1; ++ last_word = (eeprom->offset + eeprom->len - 1) >> 1; + -+ if (!shared_int) { -+ /* Disable the other interrupts to be reported in -+ * the cause register and then force the other -+ * interrupts and see if any get posted. If -+ * an interrupt was posted to the bus, the -+ * test failed. -+ */ -+ adapter->test_icr = 0; -+ E1000_WRITE_REG(hw, E1000_IMC, ~mask & 0x00007FFF); -+ E1000_WRITE_REG(hw, E1000_ICS, ~mask & 0x00007FFF); -+ msleep(10); ++ eeprom_buff = kmalloc(sizeof(u16) * ++ (last_word - first_word + 1), GFP_KERNEL); ++ if (!eeprom_buff) ++ return -ENOMEM; + -+ if (adapter->test_icr) { -+ *data = 5; ++ if (hw->nvm.type == e1000_nvm_eeprom_spi) ++ ret_val = e1000_read_nvm(hw, first_word, ++ last_word - first_word + 1, ++ eeprom_buff); ++ else { ++ for (i = 0; i < last_word - first_word + 1; i++) { ++ ret_val = e1000_read_nvm(hw, first_word + i, 1, ++ &eeprom_buff[i]); ++ if (ret_val) + break; -+ } -+ } -+ } -+ -+ /* Disable all the interrupts */ -+ E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); -+ msleep(10); -+ -+ /* Unhook test interrupt handler */ -+ free_irq(irq, netdev); -+ -+ return *data; -+} -+ -+static void igb_free_desc_rings(struct igb_adapter *adapter) -+{ -+ struct igb_ring *tx_ring = &adapter->test_tx_ring; -+ struct igb_ring *rx_ring = &adapter->test_rx_ring; -+ struct pci_dev *pdev = adapter->pdev; -+ int i; -+ -+ if (tx_ring->desc && tx_ring->buffer_info) { -+ for (i = 0; i < tx_ring->count; i++) { -+ struct igb_buffer *buf = &(tx_ring->buffer_info[i]); -+ if (buf->dma) -+ pci_unmap_single(pdev, buf->dma, buf->length, -+ PCI_DMA_TODEVICE); -+ if (buf->skb) -+ dev_kfree_skb(buf->skb); -+ } -+ } -+ -+ if (rx_ring->desc && rx_ring->buffer_info) { -+ for (i = 0; i < rx_ring->count; i++) { -+ struct igb_buffer *buf = &(rx_ring->buffer_info[i]); -+ if (buf->dma) -+ pci_unmap_single(pdev, buf->dma, -+ IGB_RXBUFFER_2048, -+ PCI_DMA_FROMDEVICE); -+ if (buf->skb) -+ dev_kfree_skb(buf->skb); + } + } + -+ if (tx_ring->desc) { -+ pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, -+ tx_ring->dma); -+ tx_ring->desc = NULL; -+ } -+ if (rx_ring->desc) { -+ pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, -+ rx_ring->dma); -+ rx_ring->desc = NULL; -+ } -+ -+ kfree(tx_ring->buffer_info); -+ tx_ring->buffer_info = NULL; -+ kfree(rx_ring->buffer_info); -+ rx_ring->buffer_info = NULL; ++ /* Device's eeprom is always little-endian, word addressable */ ++ for (i = 0; i < last_word - first_word + 1; i++) ++ le16_to_cpus(&eeprom_buff[i]); + -+ return; ++ memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), ++ eeprom->len); ++ kfree(eeprom_buff); ++ ++ return ret_val; +} + -+static int igb_setup_desc_rings(struct igb_adapter *adapter) ++static int igb_set_eeprom(struct net_device *netdev, ++ struct ethtool_eeprom *eeprom, u8 *bytes) +{ ++ struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; -+ struct igb_ring *tx_ring = &adapter->test_tx_ring; -+ struct igb_ring *rx_ring = &adapter->test_rx_ring; -+ struct pci_dev *pdev = adapter->pdev; -+ u32 rctl; -+ int i, ret_val; -+ -+ /* Setup Tx descriptor ring and Tx buffers */ ++ u16 *eeprom_buff; ++ void *ptr; ++ int max_len, first_word, last_word, ret_val = 0; ++ u16 i; + -+ if (!tx_ring->count) -+ tx_ring->count = IGB_DEFAULT_TXD; ++ if (eeprom->len == 0) ++ return -EOPNOTSUPP; + -+ if (!(tx_ring->buffer_info = kcalloc(tx_ring->count, -+ sizeof(struct igb_buffer), -+ GFP_KERNEL))) { -+ ret_val = 1; -+ goto err_nomem; -+ } ++ if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) ++ return -EFAULT; + -+ tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc); -+ tx_ring->size = ALIGN(tx_ring->size, 4096); -+ if (!(tx_ring->desc = pci_alloc_consistent(pdev, tx_ring->size, -+ &tx_ring->dma))) { -+ ret_val = 2; -+ goto err_nomem; -+ } -+ tx_ring->next_to_use = tx_ring->next_to_clean = 0; ++ max_len = hw->nvm.word_size * 2; + -+ E1000_WRITE_REG(hw, E1000_TDBAL(0), -+ ((u64) tx_ring->dma & 0x00000000FFFFFFFF)); -+ E1000_WRITE_REG(hw, E1000_TDBAH(0), ((u64) tx_ring->dma >> 32)); -+ E1000_WRITE_REG(hw, E1000_TDLEN(0), -+ tx_ring->count * sizeof(struct e1000_tx_desc)); -+ E1000_WRITE_REG(hw, E1000_TDH(0), 0); -+ E1000_WRITE_REG(hw, E1000_TDT(0), 0); -+ E1000_WRITE_REG(hw, E1000_TCTL, -+ E1000_TCTL_PSP | E1000_TCTL_EN | -+ E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT | -+ E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT); ++ first_word = eeprom->offset >> 1; ++ last_word = (eeprom->offset + eeprom->len - 1) >> 1; ++ eeprom_buff = kmalloc(max_len, GFP_KERNEL); ++ if (!eeprom_buff) ++ return -ENOMEM; + -+ for (i = 0; i < tx_ring->count; i++) { -+ struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i); -+ struct sk_buff *skb; -+ unsigned int size = 1024; ++ ptr = (void *)eeprom_buff; + -+ if (!(skb = alloc_skb(size, GFP_KERNEL))) { -+ ret_val = 3; -+ goto err_nomem; -+ } -+ skb_put(skb, size); -+ tx_ring->buffer_info[i].skb = skb; -+ tx_ring->buffer_info[i].length = skb->len; -+ tx_ring->buffer_info[i].dma = -+ pci_map_single(pdev, skb->data, skb->len, -+ PCI_DMA_TODEVICE); -+ tx_desc->buffer_addr = cpu_to_le64(tx_ring->buffer_info[i].dma); -+ tx_desc->lower.data = cpu_to_le32(skb->len); -+ tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP | -+ E1000_TXD_CMD_IFCS | -+ E1000_TXD_CMD_RS); -+ tx_desc->upper.data = 0; ++ if (eeprom->offset & 1) { ++ /* need read/modify/write of first changed EEPROM word */ ++ /* only the second byte of the word is being modified */ ++ ret_val = e1000_read_nvm(hw, first_word, 1, ++ &eeprom_buff[0]); ++ ptr++; + } -+ -+ /* Setup Rx descriptor ring and Rx buffers */ -+ -+ if (!rx_ring->count) -+ rx_ring->count = IGB_DEFAULT_RXD; -+ -+ if (!(rx_ring->buffer_info = kcalloc(rx_ring->count, -+ sizeof(struct igb_buffer), -+ GFP_KERNEL))) { -+ ret_val = 4; -+ goto err_nomem; ++ if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) { ++ /* need read/modify/write of last changed EEPROM word */ ++ /* only the first byte of the word is being modified */ ++ ret_val = e1000_read_nvm(hw, last_word, 1, ++ &eeprom_buff[last_word - first_word]); + } + -+ rx_ring->size = rx_ring->count * sizeof(struct e1000_rx_desc); -+ if (!(rx_ring->desc = pci_alloc_consistent(pdev, rx_ring->size, -+ &rx_ring->dma))) { -+ ret_val = 5; -+ goto err_nomem; -+ } -+ rx_ring->next_to_use = rx_ring->next_to_clean = 0; ++ /* Device's eeprom is always little-endian, word addressable */ ++ for (i = 0; i < last_word - first_word + 1; i++) ++ le16_to_cpus(&eeprom_buff[i]); + -+ rctl = E1000_READ_REG(hw, E1000_RCTL); -+ E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); -+ E1000_WRITE_REG(hw, E1000_RDBAL(0), -+ ((u64) rx_ring->dma & 0xFFFFFFFF)); -+ E1000_WRITE_REG(hw, E1000_RDBAH(0), ((u64) rx_ring->dma >> 32)); -+ E1000_WRITE_REG(hw, E1000_RDLEN(0), rx_ring->size); -+ E1000_WRITE_REG(hw, E1000_RDH(0), 0); -+ E1000_WRITE_REG(hw, E1000_RDT(0), 0); -+ rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 | -+ E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | -+ (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT); -+ E1000_WRITE_REG(hw, E1000_RCTL, rctl); -+ E1000_WRITE_REG(hw, E1000_SRRCTL(0), 0); ++ memcpy(ptr, bytes, eeprom->len); + -+ for (i = 0; i < rx_ring->count; i++) { -+ struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rx_ring, i); -+ struct sk_buff *skb; ++ for (i = 0; i < last_word - first_word + 1; i++) ++ cpu_to_le16s(&eeprom_buff[i]); + -+ skb = alloc_skb(IGB_RXBUFFER_2048 + NET_IP_ALIGN, -+ GFP_KERNEL); -+ if (!skb) { -+ ret_val = 6; -+ goto err_nomem; -+ } -+ skb_reserve(skb, NET_IP_ALIGN); -+ rx_ring->buffer_info[i].skb = skb; -+ rx_ring->buffer_info[i].dma = -+ pci_map_single(pdev, skb->data, IGB_RXBUFFER_2048, -+ PCI_DMA_FROMDEVICE); -+ rx_desc->buffer_addr = cpu_to_le64(rx_ring->buffer_info[i].dma); -+ memset(skb->data, 0x00, skb->len); -+ } ++ ret_val = e1000_write_nvm(hw, first_word, ++ last_word - first_word + 1, eeprom_buff); + -+ return 0; ++ /* Update the checksum over the first part of the EEPROM if needed ++ * and flush shadow RAM for 82573 controllers */ ++ if ((ret_val == 0) && ((first_word <= NVM_CHECKSUM_REG))) ++ e1000_update_nvm_checksum(hw); + -+err_nomem: -+ igb_free_desc_rings(adapter); ++ kfree(eeprom_buff); + return ret_val; +} + -+static void igb_phy_disable_receiver(struct igb_adapter *adapter) ++static void igb_get_drvinfo(struct net_device *netdev, ++ struct ethtool_drvinfo *drvinfo) +{ -+ /* Write out to PHY registers 29 and 30 to disable the Receiver. */ -+ e1000_write_phy_reg(&adapter->hw, 29, 0x001F); -+ e1000_write_phy_reg(&adapter->hw, 30, 0x8FFC); -+ e1000_write_phy_reg(&adapter->hw, 29, 0x001A); -+ e1000_write_phy_reg(&adapter->hw, 30, 0x8FF0); ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ u16 eeprom_data; ++ ++ strncpy(drvinfo->driver, igb_driver_name, 32); ++ strncpy(drvinfo->version, igb_driver_version, 32); ++ ++ /* EEPROM image version # is reported as firmware version # for ++ * 82575 controllers */ ++ e1000_read_nvm(&adapter->hw, 5, 1, &eeprom_data); ++ snprintf(drvinfo->fw_version, 32, "%d.%d-%d", ++ (eeprom_data & 0xF000) >> 12, ++ (eeprom_data & 0x0FF0) >> 4, ++ eeprom_data & 0x000F); ++ ++ strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); ++ drvinfo->n_stats = IGB_STATS_LEN; ++ drvinfo->testinfo_len = IGB_TEST_LEN; ++ drvinfo->regdump_len = igb_get_regs_len(netdev); ++ drvinfo->eedump_len = igb_get_eeprom_len(netdev); +} + -+static int igb_integrated_phy_loopback(struct igb_adapter *adapter) ++static void igb_get_ringparam(struct net_device *netdev, ++ struct ethtool_ringparam *ring) +{ -+ struct e1000_hw *hw = &adapter->hw; -+ u32 ctrl_reg = 0; -+ u32 stat_reg = 0; ++ struct igb_adapter *adapter = netdev_priv(netdev); + -+ hw->mac.autoneg = FALSE; ++ ring->rx_max_pending = IGB_MAX_RXD; ++ ring->tx_max_pending = IGB_MAX_TXD; ++ ring->rx_mini_max_pending = 0; ++ ring->rx_jumbo_max_pending = 0; ++ ring->rx_pending = adapter->rx_ring_count; ++ ring->tx_pending = adapter->tx_ring_count; ++ ring->rx_mini_pending = 0; ++ ring->rx_jumbo_pending = 0; ++} + -+ if (hw->phy.type == e1000_phy_m88) { -+ /* Auto-MDI/MDIX Off */ -+ e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); -+ /* reset to update Auto-MDI/MDIX */ -+ e1000_write_phy_reg(hw, PHY_CONTROL, 0x9140); -+ /* autoneg off */ -+ e1000_write_phy_reg(hw, PHY_CONTROL, 0x8140); -+ } ++static int igb_set_ringparam(struct net_device *netdev, ++ struct ethtool_ringparam *ring) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ struct igb_ring *temp_ring; ++ int i, err; ++ u16 new_rx_count, new_tx_count; + -+ ctrl_reg = E1000_READ_REG(hw, E1000_CTRL); ++ if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) ++ return -EINVAL; + -+ /* force 1000, set loopback */ -+ e1000_write_phy_reg(hw, PHY_CONTROL, 0x4140); ++ new_rx_count = min(ring->rx_pending, (u32)IGB_MAX_RXD); ++ new_rx_count = max(new_rx_count, (u16)IGB_MIN_RXD); ++ new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE); + -+ /* Now set up the MAC to the same speed/duplex as the PHY. */ -+ ctrl_reg = E1000_READ_REG(hw, E1000_CTRL); -+ ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ -+ ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ -+ E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ -+ E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */ -+ E1000_CTRL_FD); /* Force Duplex to FULL */ ++ new_tx_count = min(ring->tx_pending, (u32)IGB_MAX_TXD); ++ new_tx_count = max(new_tx_count, (u16)IGB_MIN_TXD); ++ new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE); + -+ if (hw->phy.media_type == e1000_media_type_copper && -+ hw->phy.type == e1000_phy_m88) -+ ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ -+ else { -+ /* Set the ILOS bit on the fiber Nic if half duplex link is -+ * detected. */ -+ stat_reg = E1000_READ_REG(hw, E1000_STATUS); -+ if ((stat_reg & E1000_STATUS_FD) == 0) -+ ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU); ++ if ((new_tx_count == adapter->tx_ring_count) && ++ (new_rx_count == adapter->rx_ring_count)) { ++ /* nothing to do */ ++ return 0; + } + -+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg); ++ if (adapter->num_tx_queues > adapter->num_rx_queues) ++ temp_ring = vmalloc(adapter->num_tx_queues * sizeof(struct igb_ring)); ++ else ++ temp_ring = vmalloc(adapter->num_rx_queues * sizeof(struct igb_ring)); ++ if (!temp_ring) ++ return -ENOMEM; + -+ /* Disable the receiver on the PHY so when a cable is plugged in, the -+ * PHY does not begin to autoneg when a cable is reconnected to the NIC. -+ */ -+ if (hw->phy.type == e1000_phy_m88) -+ igb_phy_disable_receiver(adapter); ++ while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) ++ msleep(1); + -+ udelay(500); ++ if (netif_running(adapter->netdev)) ++ igb_down(adapter); + -+ return 0; -+} ++ /* ++ * We can't just free everything and then setup again, ++ * because the ISRs in MSI-X mode get passed pointers ++ * to the tx and rx ring structs. ++ */ ++ if (new_tx_count != adapter->tx_ring_count) { ++ memcpy(temp_ring, adapter->tx_ring, ++ adapter->num_tx_queues * sizeof(struct igb_ring)); + -+static int igb_set_phy_loopback(struct igb_adapter *adapter) -+{ -+ return igb_integrated_phy_loopback(adapter); -+} ++ for (i = 0; i < adapter->num_tx_queues; i++) { ++ temp_ring[i].count = new_tx_count; ++ err = igb_setup_tx_resources(&temp_ring[i]); ++ if (err) { ++ while (i) { ++ i--; ++ igb_free_tx_resources(&temp_ring[i]); ++ } ++ goto err_setup; ++ } ++ } + -+static int igb_setup_loopback_test(struct igb_adapter *adapter) -+{ -+ struct e1000_hw *hw = &adapter->hw; -+ u32 reg; ++ for (i = 0; i < adapter->num_tx_queues; i++) ++ igb_free_tx_resources(&adapter->tx_ring[i]); + -+ if (hw->phy.media_type == e1000_media_type_fiber || -+ hw->phy.media_type == e1000_media_type_internal_serdes) { ++ memcpy(adapter->tx_ring, temp_ring, ++ adapter->num_tx_queues * sizeof(struct igb_ring)); + -+ reg = E1000_READ_REG(hw, E1000_RCTL); -+ reg |= E1000_RCTL_LBM_TCVR; -+ E1000_WRITE_REG(hw, E1000_RCTL, reg); ++ adapter->tx_ring_count = new_tx_count; ++ } + -+ E1000_WRITE_REG(hw, E1000_SCTL, E1000_ENABLE_SERDES_LOOPBACK); ++ if (new_rx_count != adapter->rx_ring->count) { ++ memcpy(temp_ring, adapter->rx_ring, ++ adapter->num_rx_queues * sizeof(struct igb_ring)); + -+ reg = E1000_READ_REG(hw, E1000_CTRL); -+ reg &= ~(E1000_CTRL_RFCE | -+ E1000_CTRL_TFCE | -+ E1000_CTRL_LRST); -+ reg |= E1000_CTRL_SLU | -+ E1000_CTRL_FD; -+ E1000_WRITE_REG(hw, E1000_CTRL, reg); ++ for (i = 0; i < adapter->num_rx_queues; i++) { ++ temp_ring[i].count = new_rx_count; ++ err = igb_setup_rx_resources(&temp_ring[i]); ++ if (err) { ++ while (i) { ++ i--; ++ igb_free_rx_resources(&temp_ring[i]); ++ } ++ goto err_setup; ++ } + -+ /* Unset switch control to serdes energy detect */ -+ reg = E1000_READ_REG(hw, E1000_CONNSW); -+ reg &= ~E1000_CONNSW_ENRGSRC; -+ E1000_WRITE_REG(hw, E1000_CONNSW, reg); ++ } + -+ /* Set PCS register for forced speed */ -+ reg = E1000_READ_REG(hw, E1000_PCS_LCTL); -+ reg &= ~E1000_PCS_LCTL_AN_ENABLE; /* Disable Autoneg*/ -+ reg |= E1000_PCS_LCTL_FLV_LINK_UP | /* Force link up */ -+ E1000_PCS_LCTL_FSV_1000 | /* Force 1000 */ -+ E1000_PCS_LCTL_FDV_FULL | /* SerDes Full duplex */ -+ E1000_PCS_LCTL_FSD | /* Force Speed */ -+ E1000_PCS_LCTL_FORCE_LINK; /* Force Link */ -+ E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg); ++ for (i = 0; i < adapter->num_rx_queues; i++) ++ igb_free_rx_resources(&adapter->rx_ring[i]); + -+ return 0; -+ } else if (hw->phy.media_type == e1000_media_type_copper) { -+ return igb_set_phy_loopback(adapter); ++ memcpy(adapter->rx_ring, temp_ring, ++ adapter->num_rx_queues * sizeof(struct igb_ring)); ++ ++ adapter->rx_ring_count = new_rx_count; + } + -+ return 7; ++ err = 0; ++err_setup: ++ if (netif_running(adapter->netdev)) ++ igb_up(adapter); ++ ++ clear_bit(__IGB_RESETTING, &adapter->state); ++ vfree(temp_ring); ++ return err; +} + -+static void igb_loopback_cleanup(struct igb_adapter *adapter) ++static bool reg_pattern_test(struct igb_adapter *adapter, u64 *data, ++ int reg, u32 mask, u32 write) +{ + struct e1000_hw *hw = &adapter->hw; -+ u32 rctl; -+ u16 phy_reg; -+ -+ rctl = E1000_READ_REG(hw, E1000_RCTL); -+ rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); -+ E1000_WRITE_REG(hw, E1000_RCTL, rctl); -+ -+ hw->mac.autoneg = TRUE; -+ e1000_read_phy_reg(hw, PHY_CONTROL, &phy_reg); -+ if (phy_reg & MII_CR_LOOPBACK) { -+ phy_reg &= ~MII_CR_LOOPBACK; -+ e1000_write_phy_reg(hw, PHY_CONTROL, phy_reg); -+ e1000_phy_commit(hw); ++ u32 pat, val; ++ static const u32 _test[] = ++ {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; ++ for (pat = 0; pat < ARRAY_SIZE(_test); pat++) { ++ E1000_WRITE_REG(hw, reg, (_test[pat] & write)); ++ val = E1000_READ_REG(hw, reg); ++ if (val != (_test[pat] & write & mask)) { ++ DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " ++ "0x%08X expected 0x%08X\n", ++ E1000_REGISTER(hw, reg), val, ++ (_test[pat] & write & mask)); ++ *data = E1000_REGISTER(hw, reg); ++ return 1; ++ } + } -+} + -+static void igb_create_lbtest_frame(struct sk_buff *skb, -+ unsigned int frame_size) -+{ -+ memset(skb->data, 0xFF, frame_size); -+ frame_size &= ~1; -+ memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1); -+ memset(&skb->data[frame_size / 2 + 10], 0xBE, 1); -+ memset(&skb->data[frame_size / 2 + 12], 0xAF, 1); ++ return 0; +} + -+static int igb_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size) ++static bool reg_set_and_check(struct igb_adapter *adapter, u64 *data, ++ int reg, u32 mask, u32 write) +{ -+ frame_size &= ~1; -+ if (*(skb->data + 3) == 0xFF) { -+ if ((*(skb->data + frame_size / 2 + 10) == 0xBE) && -+ (*(skb->data + frame_size / 2 + 12) == 0xAF)) { -+ return 0; -+ } ++ struct e1000_hw *hw = &adapter->hw; ++ u32 val; ++ E1000_WRITE_REG(hw, reg, write & mask); ++ val = E1000_READ_REG(hw, reg); ++ if ((write & mask) != (val & mask)) { ++ DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X " ++ "expected 0x%08X\n", reg, (val & mask), (write & mask)); ++ *data = E1000_REGISTER(hw, reg); ++ return 1; + } -+ return 13; ++ ++ return 0; +} + -+static int igb_run_loopback_test(struct igb_adapter *adapter) ++#define REG_PATTERN_TEST(reg, mask, write) \ ++ do { \ ++ if (reg_pattern_test(adapter, data, reg, mask, write)) \ ++ return 1; \ ++ } while (0) ++ ++#define REG_SET_AND_CHECK(reg, mask, write) \ ++ do { \ ++ if (reg_set_and_check(adapter, data, reg, mask, write)) \ ++ return 1; \ ++ } while (0) ++ ++static int igb_reg_test(struct igb_adapter *adapter, u64 *data) +{ + struct e1000_hw *hw = &adapter->hw; -+ struct igb_ring *tx_ring = &adapter->test_tx_ring; -+ struct igb_ring *rx_ring = &adapter->test_rx_ring; -+ struct pci_dev *pdev = adapter->pdev; -+ int i, j, k, l, lc, good_cnt, ret_val=0; -+ unsigned long time; ++ struct igb_reg_test *test; ++ u32 value, before, after; ++ u32 i, toggle; + -+ E1000_WRITE_REG(hw, E1000_RDT(0), rx_ring->count - 1); ++ switch (adapter->hw.mac.type) { ++ case e1000_82576: ++ test = reg_test_82576; ++ toggle = 0x7FFFF3FF; ++ break; ++ default: ++ test = reg_test_82575; ++ toggle = 0x7FFFF3FF; ++ break; ++ } + -+ /* Calculate the loop count based on the largest descriptor ring -+ * The idea is to wrap the largest ring a number of times using 64 -+ * send/receive pairs during each loop ++ /* Because the status register is such a special case, ++ * we handle it separately from the rest of the register ++ * tests. Some bits are read-only, some toggle, and some ++ * are writable on newer MACs. + */ ++ before = E1000_READ_REG(hw, E1000_STATUS); ++ value = (E1000_READ_REG(hw, E1000_STATUS) & toggle); ++ E1000_WRITE_REG(hw, E1000_STATUS, toggle); ++ after = E1000_READ_REG(hw, E1000_STATUS) & toggle; ++ if (value != after) { ++ DPRINTK(DRV, ERR, "failed STATUS register test got: " ++ "0x%08X expected: 0x%08X\n", after, value); ++ *data = 1; ++ return 1; ++ } ++ /* restore previous status */ ++ E1000_WRITE_REG(hw, E1000_STATUS, before); + -+ if (rx_ring->count <= tx_ring->count) -+ lc = ((tx_ring->count / 64) * 2) + 1; -+ else -+ lc = ((rx_ring->count / 64) * 2) + 1; -+ -+ k = l = 0; -+ for (j = 0; j <= lc; j++) { /* loop count loop */ -+ for (i = 0; i < 64; i++) { /* send the packets */ -+ igb_create_lbtest_frame(tx_ring->buffer_info[k].skb, -+ 1024); -+ pci_dma_sync_single_for_device(pdev, -+ tx_ring->buffer_info[k].dma, -+ tx_ring->buffer_info[k].length, -+ PCI_DMA_TODEVICE); -+ if (unlikely(++k == tx_ring->count)) k = 0; ++ /* Perform the remainder of the register test, looping through ++ * the test table until we either fail or reach the null entry. ++ */ ++ while (test->reg) { ++ for (i = 0; i < test->array_len; i++) { ++ switch (test->test_type) { ++ case PATTERN_TEST: ++ REG_PATTERN_TEST(test->reg + ++ (i * test->reg_offset), ++ test->mask, ++ test->write); ++ break; ++ case SET_READ_TEST: ++ REG_SET_AND_CHECK(test->reg + ++ (i * test->reg_offset), ++ test->mask, ++ test->write); ++ break; ++ case WRITE_NO_TEST: ++ writel(test->write, ++ (adapter->hw.hw_addr + test->reg) ++ + (i * test->reg_offset)); ++ break; ++ case TABLE32_TEST: ++ REG_PATTERN_TEST(test->reg + (i * 4), ++ test->mask, ++ test->write); ++ break; ++ case TABLE64_TEST_LO: ++ REG_PATTERN_TEST(test->reg + (i * 8), ++ test->mask, ++ test->write); ++ break; ++ case TABLE64_TEST_HI: ++ REG_PATTERN_TEST((test->reg + 4) + (i * 8), ++ test->mask, ++ test->write); ++ break; ++ } + } -+ E1000_WRITE_REG(hw, E1000_TDT(0), k); -+ msleep(200); -+ -+ time = jiffies; /* set the start time for the receive */ -+ good_cnt = 0; -+ do { /* receive the sent packets */ -+ pci_dma_sync_single_for_cpu(pdev, -+ rx_ring->buffer_info[l].dma, -+ IGB_RXBUFFER_2048, -+ PCI_DMA_FROMDEVICE); ++ test++; ++ } + -+ ret_val = igb_check_lbtest_frame( -+ rx_ring->buffer_info[l].skb, 1024); -+ if (!ret_val) -+ good_cnt++; -+ if (unlikely(++l == rx_ring->count)) l = 0; -+ /* time + 20 msecs (200 msecs on 2.4) is more than -+ * enough time to complete the receives, if it's -+ * exceeded, break and error off -+ */ -+ } while (good_cnt < 64 && jiffies < (time + 20)); -+ if (good_cnt != 64) { -+ ret_val = 13; /* ret_val is the same as mis-compare */ -+ break; -+ } -+ if (jiffies >= (time + 20)) { -+ ret_val = 14; /* error code for time out error */ -+ break; -+ } -+ } /* end loop count loop */ -+ return ret_val; ++ *data = 0; ++ return 0; +} + -+static int igb_loopback_test(struct igb_adapter *adapter, u64 *data) ++static int igb_eeprom_test(struct igb_adapter *adapter, u64 *data) +{ -+ /* PHY loopback cannot be performed if SoL/IDER -+ * sessions are active */ -+ if (e1000_check_reset_block(&adapter->hw)) { -+ DPRINTK(DRV, ERR, "Cannot do PHY loopback test " -+ "when SoL/IDER is active.\n"); -+ *data = 0; -+ goto out; ++ u16 temp; ++ u16 checksum = 0; ++ u16 i; ++ ++ *data = 0; ++ /* Read and add up the contents of the EEPROM */ ++ for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { ++ if ((e1000_read_nvm(&adapter->hw, i, 1, &temp)) < 0) { ++ *data = 1; ++ break; ++ } ++ checksum += temp; + } -+ *data = igb_setup_desc_rings(adapter); -+ if (*data) -+ goto out; -+ *data = igb_setup_loopback_test(adapter); -+ if (*data) -+ goto err_loopback; -+ *data = igb_run_loopback_test(adapter); -+ igb_loopback_cleanup(adapter); + -+err_loopback: -+ igb_free_desc_rings(adapter); -+out: ++ /* If Checksum is not Correct return error else test passed */ ++ if ((checksum != (u16) NVM_SUM) && !(*data)) ++ *data = 2; ++ + return *data; +} + -+static int igb_link_test(struct igb_adapter *adapter, u64 *data) ++static irqreturn_t igb_test_intr(int irq, void *data) +{ ++ struct igb_adapter *adapter = (struct igb_adapter *) data; + struct e1000_hw *hw = &adapter->hw; -+ *data = 0; -+ if (adapter->hw.phy.media_type == e1000_media_type_internal_serdes) { -+ int i = 0; -+ adapter->hw.mac.serdes_has_link = FALSE; + -+ /* On some blade server designs, link establishment -+ * could take as long as 2-3 minutes */ -+ do { -+ e1000_check_for_link(&adapter->hw); -+ if (adapter->hw.mac.serdes_has_link) -+ return *data; -+ msleep(20); -+ } while (i++ < 3750); ++ adapter->test_icr |= E1000_READ_REG(hw, E1000_ICR); ++ ++ return IRQ_HANDLED; ++} ++ ++static int igb_intr_test(struct igb_adapter *adapter, u64 *data) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ u32 mask, ics_mask, i = 0, shared_int = TRUE; ++ u32 irq = adapter->pdev->irq; + -+ *data = 1; -+ } else { -+ e1000_check_for_link(&adapter->hw); -+ if (adapter->hw.mac.autoneg) -+ msleep(4000); ++ *data = 0; + -+ if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) ++ /* Hook up test interrupt handler just for this test */ ++ if (adapter->msix_entries) { ++ if (request_irq(adapter->msix_entries[0].vector, ++ &igb_test_intr, 0, netdev->name, adapter)) { ++ *data = 1; ++ return -1; ++ } ++ } else if (adapter->flags & IGB_FLAG_HAS_MSI) { ++ shared_int = FALSE; ++ if (request_irq(irq, &igb_test_intr, 0, netdev->name, adapter)) { + *data = 1; ++ return -1; ++ } ++ } else if (!request_irq(irq, &igb_test_intr, IRQF_PROBE_SHARED, ++ netdev->name, adapter)) { ++ shared_int = FALSE; ++ } else if (request_irq(irq, &igb_test_intr, IRQF_SHARED, ++ netdev->name, adapter)) { ++ *data = 1; ++ return -1; + } -+ return *data; -+} ++ DPRINTK(HW, INFO, "testing %s interrupt\n", ++ (shared_int ? "shared" : "unshared")); + -+static int igb_diag_test_count(struct net_device *netdev) -+{ -+ return IGB_TEST_LEN; -+} ++ /* Disable all the interrupts */ ++ E1000_WRITE_REG(hw, E1000_IMC, ~0); ++ msleep(10); + -+static void igb_diag_test(struct net_device *netdev, -+ struct ethtool_test *eth_test, u64 *data) -+{ -+ struct igb_adapter *adapter = netdev_priv(netdev); -+ u16 autoneg_advertised; -+ u8 forced_speed_duplex, autoneg; -+ bool if_running = netif_running(netdev); ++ /* Define all writable bits for ICS */ ++ switch (hw->mac.type) { ++ case e1000_82575: ++ ics_mask = 0x37F47EDD; ++ break; ++ case e1000_82576: ++ ics_mask = 0x77D4FBFD; ++ break; ++ default: ++ ics_mask = 0x7FFFFFFF; ++ break; ++ } + -+ set_bit(__IGB_TESTING, &adapter->state); -+ if (eth_test->flags == ETH_TEST_FL_OFFLINE) { -+ /* Offline tests */ ++ /* Test each interrupt */ ++ for (; i < 31; i++) { ++ /* Interrupt to test */ ++ mask = 1 << i; + -+ /* save speed, duplex, autoneg settings */ -+ autoneg_advertised = adapter->hw.phy.autoneg_advertised; -+ forced_speed_duplex = adapter->hw.mac.forced_speed_duplex; -+ autoneg = adapter->hw.mac.autoneg; ++ if (!(mask & ics_mask)) ++ continue; + -+ DPRINTK(HW, INFO, "offline testing starting\n"); ++ if (!shared_int) { ++ /* Disable the interrupt to be reported in ++ * the cause register and then force the same ++ * interrupt and see if one gets posted. If ++ * an interrupt was posted to the bus, the ++ * test failed. ++ */ ++ adapter->test_icr = 0; + -+ /* Link test performed before hardware reset so autoneg doesn't -+ * interfere with test result */ -+ if (igb_link_test(adapter, &data[4])) -+ eth_test->flags |= ETH_TEST_FL_FAILED; ++ /* Flush any pending interrupts */ ++ E1000_WRITE_REG(hw, E1000_ICR, ~0); + -+ if (if_running) -+ /* indicate we're in test mode */ -+ dev_close(netdev); -+ else -+ igb_reset(adapter); ++ E1000_WRITE_REG(hw, E1000_IMC, mask); ++ E1000_WRITE_REG(hw, E1000_ICS, mask); ++ msleep(10); + -+ if (igb_reg_test(adapter, &data[0])) -+ eth_test->flags |= ETH_TEST_FL_FAILED; ++ if (adapter->test_icr & mask) { ++ *data = 3; ++ break; ++ } ++ } + -+ igb_reset(adapter); -+ if (igb_eeprom_test(adapter, &data[1])) -+ eth_test->flags |= ETH_TEST_FL_FAILED; ++ /* Enable the interrupt to be reported in ++ * the cause register and then force the same ++ * interrupt and see if one gets posted. If ++ * an interrupt was not posted to the bus, the ++ * test failed. ++ */ ++ adapter->test_icr = 0; + -+ igb_reset(adapter); -+ if (igb_intr_test(adapter, &data[2])) -+ eth_test->flags |= ETH_TEST_FL_FAILED; ++ /* Flush any pending interrupts */ ++ E1000_WRITE_REG(hw, E1000_ICR, ~0); + -+ igb_reset(adapter); -+ if (igb_loopback_test(adapter, &data[3])) -+ eth_test->flags |= ETH_TEST_FL_FAILED; ++ E1000_WRITE_REG(hw, E1000_IMS, mask); ++ E1000_WRITE_REG(hw, E1000_ICS, mask); ++ msleep(10); + -+ /* restore speed, duplex, autoneg settings */ -+ adapter->hw.phy.autoneg_advertised = autoneg_advertised; -+ adapter->hw.mac.forced_speed_duplex = forced_speed_duplex; -+ adapter->hw.mac.autoneg = autoneg; ++ if (!(adapter->test_icr & mask)) { ++ *data = 4; ++ break; ++ } + -+ /* force this routine to wait until autoneg complete/timeout */ -+ adapter->hw.phy.autoneg_wait_to_complete = TRUE; -+ igb_reset(adapter); -+ adapter->hw.phy.autoneg_wait_to_complete = FALSE; ++ if (!shared_int) { ++ /* Disable the other interrupts to be reported in ++ * the cause register and then force the other ++ * interrupts and see if any get posted. If ++ * an interrupt was posted to the bus, the ++ * test failed. ++ */ ++ adapter->test_icr = 0; + -+ clear_bit(__IGB_TESTING, &adapter->state); -+ if (if_running) -+ dev_open(netdev); -+ } else { -+ DPRINTK(HW, INFO, "online testing starting\n"); -+ /* Online tests */ -+ if (igb_link_test(adapter, &data[4])) -+ eth_test->flags |= ETH_TEST_FL_FAILED; ++ /* Flush any pending interrupts */ ++ E1000_WRITE_REG(hw, E1000_ICR, ~0); + -+ /* Online tests aren't run; pass by default */ -+ data[0] = 0; -+ data[1] = 0; -+ data[2] = 0; -+ data[3] = 0; ++ E1000_WRITE_REG(hw, E1000_IMC, ~mask); ++ E1000_WRITE_REG(hw, E1000_ICS, ~mask); ++ msleep(10); + -+ clear_bit(__IGB_TESTING, &adapter->state); ++ if (adapter->test_icr & mask) { ++ *data = 5; ++ break; ++ } ++ } + } -+ msleep_interruptible(4 * 1000); ++ ++ /* Disable all the interrupts */ ++ E1000_WRITE_REG(hw, E1000_IMC, ~0); ++ msleep(10); ++ ++ /* Unhook test interrupt handler */ ++ if (adapter->msix_entries) ++ free_irq(adapter->msix_entries[0].vector, adapter); ++ else ++ free_irq(irq, adapter); ++ ++ return *data; +} + -+static int igb_wol_exclusion(struct igb_adapter *adapter, -+ struct ethtool_wolinfo *wol) ++static void igb_free_desc_rings(struct igb_adapter *adapter) +{ -+ struct e1000_hw *hw = &adapter->hw; -+ int retval = 1; /* fail by default */ ++ igb_free_tx_resources(&adapter->test_tx_ring); ++ igb_free_rx_resources(&adapter->test_rx_ring); ++} + -+ switch (hw->device_id) { -+ case E1000_DEV_ID_82575GB_QUAD_COPPER: -+ /* WoL not supported */ -+ wol->supported = 0; -+ break; -+ case E1000_DEV_ID_82575EB_FIBER_SERDES: -+ case E1000_DEV_ID_82576_FIBER: -+ case E1000_DEV_ID_82576_SERDES: -+ /* Wake events not supported on port B */ -+ if (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_FUNC_1) { -+ wol->supported = 0; -+ break; -+ } -+ /* return success for non excluded adapter ports */ -+ retval = 0; -+ break; -+ default: -+ /* dual port cards only support WoL on port A from now on -+ * unless it was enabled in the eeprom for port B -+ * so exclude FUNC_1 ports from having WoL enabled */ -+ if (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_FUNC_1 && -+ !adapter->eeprom_wol) { -+ wol->supported = 0; -+ break; -+ } ++static int igb_setup_desc_rings(struct igb_adapter *adapter) ++{ ++ struct igb_ring *tx_ring = &adapter->test_tx_ring; ++ struct igb_ring *rx_ring = &adapter->test_rx_ring; ++ int i, ret_val; + -+ retval = 0; ++ /* Setup Tx descriptor ring and Tx buffers */ ++ tx_ring->count = IGB_DEFAULT_TXD; ++ tx_ring->pdev = adapter->pdev; ++ tx_ring->reg_idx = adapter->vfs_allocated_count; ++ ++ if (igb_setup_tx_resources(tx_ring)) { ++ ret_val = 1; ++ goto err_nomem; + } + -+ return retval; -+} ++ igb_setup_tctl(adapter); ++ igb_configure_tx_ring(adapter, tx_ring); + -+static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -+{ -+ struct igb_adapter *adapter = netdev_priv(netdev); ++ for (i = 0; i < tx_ring->count; i++) { ++ union e1000_adv_tx_desc *tx_desc; ++ unsigned int size = 1024; ++ struct sk_buff *skb = alloc_skb(size, GFP_KERNEL); + -+ wol->supported = WAKE_UCAST | WAKE_MCAST | -+ WAKE_BCAST | WAKE_MAGIC; -+ wol->wolopts = 0; ++ if (!skb) { ++ ret_val = 2; ++ goto err_nomem; ++ } ++ skb_put(skb, size); ++ tx_ring->buffer_info[i].skb = skb; ++ tx_ring->buffer_info[i].length = skb->len; ++ tx_ring->buffer_info[i].dma = ++ pci_map_single(tx_ring->pdev, skb->data, skb->len, ++ PCI_DMA_TODEVICE); ++ tx_desc = E1000_TX_DESC_ADV(*tx_ring, i); ++ tx_desc->read.buffer_addr = ++ cpu_to_le64(tx_ring->buffer_info[i].dma); ++ tx_desc->read.olinfo_status = ++ cpu_to_le32(skb->len << E1000_ADVTXD_PAYLEN_SHIFT); ++ tx_desc->read.cmd_type_len = cpu_to_le32(skb->len); ++ tx_desc->read.cmd_type_len |= ++ cpu_to_le32(E1000_ADVTXD_DTYP_DATA | ++ E1000_ADVTXD_DCMD_DEXT); ++ tx_desc->read.cmd_type_len |= ++ cpu_to_le32(IGB_ADVTXD_DCMD | ++ E1000_ADVTXD_DTYP_DATA | ++ E1000_ADVTXD_DCMD_IFCS | ++ E1000_ADVTXD_DCMD_DEXT); ++ } + -+ /* this function will set ->supported = 0 and return 1 if wol is not -+ * supported by this hardware */ -+ if (igb_wol_exclusion(adapter, wol)) -+ return; ++ /* Setup Rx descriptor ring and Rx buffers */ ++ rx_ring->count = IGB_DEFAULT_RXD; ++ rx_ring->pdev = adapter->pdev; ++ rx_ring->rx_buffer_len = IGB_RXBUFFER_2048; ++ rx_ring->reg_idx = adapter->vfs_allocated_count; + -+ /* apply any specific unsupported masks here */ -+ switch (adapter->hw.device_id) { -+ default: -+ break; ++ if (igb_setup_rx_resources(rx_ring)) { ++ ret_val = 3; ++ goto err_nomem; + } + -+ if (adapter->wol & E1000_WUFC_EX) -+ wol->wolopts |= WAKE_UCAST; -+ if (adapter->wol & E1000_WUFC_MC) -+ wol->wolopts |= WAKE_MCAST; -+ if (adapter->wol & E1000_WUFC_BC) -+ wol->wolopts |= WAKE_BCAST; -+ if (adapter->wol & E1000_WUFC_MAG) -+ wol->wolopts |= WAKE_MAGIC; ++ /* set the default queue to queue 0 of PF */ ++ E1000_WRITE_REG(&adapter->hw, E1000_MRQC, ++ adapter->vfs_allocated_count << 3); + -+ return; ++ /* enable receive ring */ ++ igb_setup_rctl(adapter); ++ igb_configure_rx_ring(adapter, rx_ring); ++ ++ if (igb_alloc_rx_buffers_adv(rx_ring, rx_ring->count)) { ++ ret_val = 4; ++ goto err_nomem; ++ } ++ ++ ++ return 0; ++ ++err_nomem: ++ igb_free_desc_rings(adapter); ++ return ret_val; ++} ++ ++static void igb_phy_disable_receiver(struct igb_adapter *adapter) ++{ ++ /* Write out to PHY registers 29 and 30 to disable the Receiver. */ ++ e1000_write_phy_reg(&adapter->hw, 29, 0x001F); ++ e1000_write_phy_reg(&adapter->hw, 30, 0x8FFC); ++ e1000_write_phy_reg(&adapter->hw, 29, 0x001A); ++ e1000_write_phy_reg(&adapter->hw, 30, 0x8FF0); +} + -+static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) ++static int igb_integrated_phy_loopback(struct igb_adapter *adapter) +{ -+ struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; ++ u32 ctrl_reg = 0; + -+ if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) -+ return -EOPNOTSUPP; -+ -+ if (igb_wol_exclusion(adapter, wol)) -+ return wol->wolopts ? -EOPNOTSUPP : 0; ++ hw->mac.autoneg = FALSE; + -+ switch (hw->device_id) { -+ default: -+ break; ++ if (hw->phy.type == e1000_phy_m88) { ++ /* Auto-MDI/MDIX Off */ ++ e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); ++ /* reset to update Auto-MDI/MDIX */ ++ e1000_write_phy_reg(hw, PHY_CONTROL, 0x9140); ++ /* autoneg off */ ++ e1000_write_phy_reg(hw, PHY_CONTROL, 0x8140); + } + -+ /* these settings will always override what we currently have */ -+ adapter->wol = 0; ++ ctrl_reg = E1000_READ_REG(hw, E1000_CTRL); + -+ if (wol->wolopts & WAKE_UCAST) -+ adapter->wol |= E1000_WUFC_EX; -+ if (wol->wolopts & WAKE_MCAST) -+ adapter->wol |= E1000_WUFC_MC; -+ if (wol->wolopts & WAKE_BCAST) -+ adapter->wol |= E1000_WUFC_BC; -+ if (wol->wolopts & WAKE_MAGIC) -+ adapter->wol |= E1000_WUFC_MAG; ++ /* force 1000, set loopback */ ++ e1000_write_phy_reg(hw, PHY_CONTROL, 0x4140); ++ ++ /* Now set up the MAC to the same speed/duplex as the PHY. */ ++ ctrl_reg = E1000_READ_REG(hw, E1000_CTRL); ++ ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ ++ ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ ++ E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ ++ E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */ ++ E1000_CTRL_FD | /* Force Duplex to FULL */ ++ E1000_CTRL_SLU); /* Set link up enable bit */ ++ ++ if (hw->phy.type == e1000_phy_m88) ++ ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ ++ ++ E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg); ++ ++ /* Disable the receiver on the PHY so when a cable is plugged in, the ++ * PHY does not begin to autoneg when a cable is reconnected to the NIC. ++ */ ++ if (hw->phy.type == e1000_phy_m88) ++ igb_phy_disable_receiver(adapter); ++ ++ udelay(500); + + return 0; +} + -+/* toggle LED 4 times per second = 2 "blinks" per second */ -+#define IGB_ID_INTERVAL (HZ/4) -+ -+/* bit defines for adapter->led_status */ -+#define IGB_LED_ON 0 ++static int igb_set_phy_loopback(struct igb_adapter *adapter) ++{ ++ return igb_integrated_phy_loopback(adapter); ++} + -+static int igb_phys_id(struct net_device *netdev, u32 data) ++static int igb_setup_loopback_test(struct igb_adapter *adapter) +{ -+ struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; ++ u32 reg; + -+ if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) -+ data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); ++ reg = E1000_READ_REG(hw, E1000_CTRL_EXT); + -+ e1000_blink_led(hw); -+ msleep_interruptible(data * 1000); ++ /* use CTRL_EXT to identify link type as SGMII can appear as copper */ ++ if (reg & E1000_CTRL_EXT_LINK_MODE_MASK) { ++ reg = E1000_READ_REG(hw, E1000_RCTL); ++ reg |= E1000_RCTL_LBM_TCVR; ++ E1000_WRITE_REG(hw, E1000_RCTL, reg); + -+ e1000_led_off(hw); -+ clear_bit(IGB_LED_ON, &adapter->led_status); -+ e1000_cleanup_led(hw); ++ E1000_WRITE_REG(hw, E1000_SCTL, E1000_ENABLE_SERDES_LOOPBACK); + -+ return 0; -+} ++ reg = E1000_READ_REG(hw, E1000_CTRL); ++ reg &= ~(E1000_CTRL_RFCE | ++ E1000_CTRL_TFCE | ++ E1000_CTRL_LRST); ++ reg |= E1000_CTRL_SLU | ++ E1000_CTRL_FD; ++ E1000_WRITE_REG(hw, E1000_CTRL, reg); + -+static int igb_set_coalesce(struct net_device *netdev, -+ struct ethtool_coalesce *ec) -+{ -+ struct igb_adapter *adapter = netdev_priv(netdev); -+ struct e1000_hw *hw = &adapter->hw; -+ int i; ++ /* Unset switch control to serdes energy detect */ ++ reg = E1000_READ_REG(hw, E1000_CONNSW); ++ reg &= ~E1000_CONNSW_ENRGSRC; ++ E1000_WRITE_REG(hw, E1000_CONNSW, reg); + -+ if ((ec->rx_coalesce_usecs > IGB_MAX_ITR_USECS) || -+ ((ec->rx_coalesce_usecs > 3) && -+ (ec->rx_coalesce_usecs < IGB_MIN_ITR_USECS)) || -+ (ec->rx_coalesce_usecs == 2)) -+ return -EINVAL; ++ /* Set PCS register for forced speed */ ++ reg = E1000_READ_REG(hw, E1000_PCS_LCTL); ++ reg &= ~E1000_PCS_LCTL_AN_ENABLE; /* Disable Autoneg*/ ++ reg |= E1000_PCS_LCTL_FLV_LINK_UP | /* Force link up */ ++ E1000_PCS_LCTL_FSV_1000 | /* Force 1000 */ ++ E1000_PCS_LCTL_FDV_FULL | /* SerDes Full duplex */ ++ E1000_PCS_LCTL_FSD | /* Force Speed */ ++ E1000_PCS_LCTL_FORCE_LINK; /* Force Link */ ++ E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg); + -+ /* convert to rate of irq's per second */ -+ if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3) { -+ adapter->itr = IGB_START_ITR; -+ adapter->itr_setting = ec->rx_coalesce_usecs; -+ } else { -+ adapter->itr = ec->rx_coalesce_usecs << 2; -+ adapter->itr_setting = adapter->itr; ++ return 0; + } + -+ for (i = 0; i < adapter->num_rx_queues; i++) -+ writel(adapter->itr, -+ hw->hw_addr + adapter->rx_ring[i].itr_register); -+ -+ return 0; ++ return igb_set_phy_loopback(adapter); +} + -+static int igb_get_coalesce(struct net_device *netdev, -+ struct ethtool_coalesce *ec) ++static void igb_loopback_cleanup(struct igb_adapter *adapter) +{ -+ struct igb_adapter *adapter = netdev_priv(netdev); ++ struct e1000_hw *hw = &adapter->hw; ++ u32 rctl; ++ u16 phy_reg; + -+ if (adapter->itr_setting <= 3) -+ ec->rx_coalesce_usecs = adapter->itr_setting; -+ else -+ ec->rx_coalesce_usecs = adapter->itr_setting >> 2; ++ rctl = E1000_READ_REG(hw, E1000_RCTL); ++ rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); ++ E1000_WRITE_REG(hw, E1000_RCTL, rctl); + -+ return 0; ++ hw->mac.autoneg = TRUE; ++ e1000_read_phy_reg(hw, PHY_CONTROL, &phy_reg); ++ if (phy_reg & MII_CR_LOOPBACK) { ++ phy_reg &= ~MII_CR_LOOPBACK; ++ e1000_write_phy_reg(hw, PHY_CONTROL, phy_reg); ++ e1000_phy_commit(hw); ++ } +} + -+static int igb_nway_reset(struct net_device *netdev) ++static void igb_create_lbtest_frame(struct sk_buff *skb, ++ unsigned int frame_size) +{ -+ struct igb_adapter *adapter = netdev_priv(netdev); -+ if (netif_running(netdev)) -+ igb_reinit_locked(adapter); -+ return 0; ++ memset(skb->data, 0xFF, frame_size); ++ frame_size &= ~1; ++ memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1); ++ memset(&skb->data[frame_size / 2 + 10], 0xBE, 1); ++ memset(&skb->data[frame_size / 2 + 12], 0xAF, 1); +} + -+static int igb_get_stats_count(struct net_device *netdev) ++static int igb_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size) +{ -+ return IGB_STATS_LEN; ++ frame_size &= ~1; ++ if (*(skb->data + 3) == 0xFF) { ++ if ((*(skb->data + frame_size / 2 + 10) == 0xBE) && ++ (*(skb->data + frame_size / 2 + 12) == 0xAF)) { ++ return 0; ++ } ++ } ++ return 13; +} + -+static void igb_get_ethtool_stats(struct net_device *netdev, -+ struct ethtool_stats *stats, u64 *data) ++static int igb_run_loopback_test(struct igb_adapter *adapter) +{ -+ struct igb_adapter *adapter = netdev_priv(netdev); -+ u64 *queue_stat; -+ int stat_count = sizeof(struct igb_queue_stats) / sizeof(u64); -+ int j; -+ int i; -+#ifdef IGB_LRO -+ int aggregated = 0, flushed = 0, no_desc = 0; -+ -+ for (i = 0; i < adapter->num_rx_queues; i++) { -+ aggregated += adapter->rx_ring[i].lro_mgr.stats.aggregated; -+ flushed += adapter->rx_ring[i].lro_mgr.stats.flushed; -+ no_desc += adapter->rx_ring[i].lro_mgr.stats.no_desc; -+ } -+ adapter->lro_aggregated = aggregated; -+ adapter->lro_flushed = flushed; -+ adapter->lro_no_desc = no_desc; -+#endif ++ struct igb_ring *tx_ring = &adapter->test_tx_ring; ++ struct igb_ring *rx_ring = &adapter->test_rx_ring; ++ int i, j, k, l, lc, good_cnt, ret_val = 0; ++ unsigned long time; + -+ igb_update_stats(adapter); ++ writel(rx_ring->count - 1, rx_ring->tail); + -+ for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) { -+ char *p = (char *)adapter+igb_gstrings_stats[i].stat_offset; -+ data[i] = (igb_gstrings_stats[i].sizeof_stat == -+ sizeof(u64)) ? *(u64 *)p : *(u32 *)p; -+ } -+ for (j = 0; j < adapter->num_tx_queues; j++) { -+ int k; -+ queue_stat = (u64 *)&adapter->tx_ring[j].tx_stats; -+ for (k = 0; k < stat_count; k++) -+ data[i + k] = queue_stat[k]; -+ i += k; -+ } -+ for (j = 0; j < adapter->num_rx_queues; j++) { -+ int k; -+ queue_stat = (u64 *)&adapter->rx_ring[j].rx_stats; -+ for (k = 0; k < stat_count; k++) -+ data[i + k] = queue_stat[k]; -+ i += k; -+ } -+} ++ /* Calculate the loop count based on the largest descriptor ring ++ * The idea is to wrap the largest ring a number of times using 64 ++ * send/receive pairs during each loop ++ */ + -+static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -+{ -+ struct igb_adapter *adapter = netdev_priv(netdev); -+ u8 *p = data; -+ int i; ++ if (rx_ring->count <= tx_ring->count) ++ lc = ((tx_ring->count / 64) * 2) + 1; ++ else ++ lc = ((rx_ring->count / 64) * 2) + 1; + -+ switch (stringset) { -+ case ETH_SS_TEST: -+ memcpy(data, *igb_gstrings_test, -+ IGB_TEST_LEN*ETH_GSTRING_LEN); -+ break; -+ case ETH_SS_STATS: -+ for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) { -+ memcpy(p, igb_gstrings_stats[i].stat_string, -+ ETH_GSTRING_LEN); -+ p += ETH_GSTRING_LEN; ++ k = l = 0; ++ for (j = 0; j <= lc; j++) { /* loop count loop */ ++ for (i = 0; i < 64; i++) { /* send the packets */ ++ igb_create_lbtest_frame(tx_ring->buffer_info[k].skb, ++ 1024); ++ pci_dma_sync_single_for_device(tx_ring->pdev, ++ tx_ring->buffer_info[k].dma, ++ tx_ring->buffer_info[k].length, ++ PCI_DMA_TODEVICE); ++ if (unlikely(++k == tx_ring->count)) ++ k = 0; + } -+ for (i = 0; i < adapter->num_tx_queues; i++) { -+ sprintf(p, "tx_queue_%u_packets", i); -+ p += ETH_GSTRING_LEN; -+ sprintf(p, "tx_queue_%u_bytes", i); -+ p += ETH_GSTRING_LEN; ++ writel(k, tx_ring->tail); ++ msleep(200); ++ ++ time = jiffies; /* set the start time for the receive */ ++ good_cnt = 0; ++ do { /* receive the sent packets */ ++ pci_dma_sync_single_for_cpu(rx_ring->pdev, ++ rx_ring->buffer_info[l].dma, ++ rx_ring->rx_buffer_len, ++ PCI_DMA_FROMDEVICE); ++ ++ ret_val = igb_check_lbtest_frame( ++ rx_ring->buffer_info[l].skb, 1024); ++ if (!ret_val) ++ good_cnt++; ++ if (unlikely(++l == rx_ring->count)) ++ l = 0; ++ /* time + 20 msecs (200 msecs on 2.4) is more than ++ * enough time to complete the receives, if it's ++ * exceeded, break and error off ++ */ ++ } while (good_cnt < 64 && jiffies < (time + 20)); ++ if (good_cnt != 64) { ++ ret_val = 13; /* ret_val is the same as mis-compare */ ++ break; + } -+ for (i = 0; i < adapter->num_rx_queues; i++) { -+ sprintf(p, "rx_queue_%u_packets", i); -+ p += ETH_GSTRING_LEN; -+ sprintf(p, "rx_queue_%u_bytes", i); -+ p += ETH_GSTRING_LEN; ++ if (jiffies >= (time + 20)) { ++ ret_val = 14; /* error code for time out error */ ++ break; + } -+/* BUG_ON(p - data != IGB_STATS_LEN * ETH_GSTRING_LEN); */ -+ break; -+ } ++ } /* end loop count loop */ ++ return ret_val; +} + -+static struct ethtool_ops igb_ethtool_ops = { -+ .get_settings = igb_get_settings, -+ .set_settings = igb_set_settings, -+ .get_drvinfo = igb_get_drvinfo, -+ .get_regs_len = igb_get_regs_len, -+ .get_regs = igb_get_regs, -+ .get_wol = igb_get_wol, -+ .set_wol = igb_set_wol, -+ .get_msglevel = igb_get_msglevel, -+ .set_msglevel = igb_set_msglevel, -+ .nway_reset = igb_nway_reset, -+ .get_link = ethtool_op_get_link, -+ .get_eeprom_len = igb_get_eeprom_len, -+ .get_eeprom = igb_get_eeprom, -+ .set_eeprom = igb_set_eeprom, -+ .get_ringparam = igb_get_ringparam, -+ .set_ringparam = igb_set_ringparam, -+ .get_pauseparam = igb_get_pauseparam, -+ .set_pauseparam = igb_set_pauseparam, -+ .get_rx_csum = igb_get_rx_csum, -+ .set_rx_csum = igb_set_rx_csum, -+ .get_tx_csum = igb_get_tx_csum, -+ .set_tx_csum = igb_set_tx_csum, -+ .get_sg = ethtool_op_get_sg, -+ .set_sg = ethtool_op_set_sg, -+#ifdef NETIF_F_TSO -+ .get_tso = ethtool_op_get_tso, -+ .set_tso = igb_set_tso, -+#endif -+ .self_test_count = igb_diag_test_count, -+ .self_test = igb_diag_test, -+ .get_strings = igb_get_strings, -+ .phys_id = igb_phys_id, -+ .get_stats_count = igb_get_stats_count, -+ .get_ethtool_stats = igb_get_ethtool_stats, -+#ifdef ETHTOOL_GPERMADDR -+ .get_perm_addr = ethtool_op_get_perm_addr, -+#endif -+ .get_coalesce = igb_get_coalesce, -+ .set_coalesce = igb_set_coalesce, -+}; -+ -+void igb_set_ethtool_ops(struct net_device *netdev) ++static int igb_loopback_test(struct igb_adapter *adapter, u64 *data) +{ -+ SET_ETHTOOL_OPS(netdev, &igb_ethtool_ops); -+} -+#endif /* SIOCETHTOOL */ -Binary files vanilla/drivers/net/igb/igb_ethtool.o and linux-i686-2.6.22/drivers/net/igb/igb_ethtool.o differ -diff -Nru vanilla/drivers/net/igb/.igb_ethtool.o.cmd linux-i686-2.6.22/drivers/net/igb/.igb_ethtool.o.cmd ---- vanilla/drivers/net/igb/.igb_ethtool.o.cmd 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/.igb_ethtool.o.cmd 2009-07-16 19:53:44.000000000 -0400 -@@ -0,0 +1,556 @@ -+cmd_drivers/net/igb/igb_ethtool.o := gcc -m32 -Wp,-MD,drivers/net/igb/.igb_ethtool.o.d -nostdinc -isystem /usr/lib/gcc/i386-redhat-linux/4.1.2/include -D__KERNEL__ -Iinclude -include include/linux/autoconf.h -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Os -pipe -msoft-float -mregparm=3 -freg-struct-return -mpreferred-stack-boundary=2 -march=i686 -mtune=generic -ffreestanding -maccumulate-outgoing-args -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -Iinclude/asm-i386/mach-generic -Iinclude/asm-i386/mach-default -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -DMODULE -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(igb_ethtool)" -D"KBUILD_MODNAME=KBUILD_STR(igb)" -c -o drivers/net/igb/.tmp_igb_ethtool.o drivers/net/igb/igb_ethtool.c -+ -+deps_drivers/net/igb/igb_ethtool.o := \ -+ drivers/net/igb/igb_ethtool.c \ -+ include/linux/netdevice.h \ -+ $(wildcard include/config/ax25.h) \ -+ $(wildcard include/config/tr.h) \ -+ $(wildcard include/config/net/ipip.h) \ -+ $(wildcard include/config/net/ipgre.h) \ -+ $(wildcard include/config/ipv6/sit.h) \ -+ $(wildcard include/config/ipv6/tunnel.h) \ -+ $(wildcard include/config/wireless/ext.h) \ -+ $(wildcard include/config/netpoll.h) \ -+ $(wildcard include/config/net/poll/controller.h) \ -+ $(wildcard include/config/netpoll/trap.h) \ -+ $(wildcard include/config/net/dma.h) \ -+ $(wildcard include/config/bug.h) \ -+ $(wildcard include/config/proc/fs.h) \ -+ include/linux/if.h \ -+ include/linux/types.h \ -+ $(wildcard include/config/uid16.h) \ -+ $(wildcard include/config/lbd.h) \ -+ $(wildcard include/config/lsf.h) \ -+ $(wildcard include/config/resources/64bit.h) \ -+ include/linux/posix_types.h \ -+ include/linux/stddef.h \ -+ include/linux/compiler.h \ -+ $(wildcard include/config/enable/must/check.h) \ -+ include/linux/compiler-gcc4.h \ -+ $(wildcard include/config/forced/inlining.h) \ -+ include/linux/compiler-gcc.h \ -+ include/asm/posix_types.h \ -+ include/asm/types.h \ -+ $(wildcard include/config/highmem64g.h) \ -+ include/linux/socket.h \ -+ $(wildcard include/config/compat.h) \ -+ include/asm/socket.h \ -+ include/asm/sockios.h \ -+ include/linux/sockios.h \ -+ include/linux/uio.h \ -+ include/linux/hdlc/ioctl.h \ -+ include/linux/if_ether.h \ -+ $(wildcard include/config/sysctl.h) \ -+ include/linux/skbuff.h \ -+ $(wildcard include/config/nf/conntrack.h) \ -+ $(wildcard include/config/bridge/netfilter.h) \ -+ $(wildcard include/config/vlan/8021q.h) \ -+ $(wildcard include/config/net/sched.h) \ -+ $(wildcard include/config/net/cls/act.h) \ -+ $(wildcard include/config/network/secmark.h) \ -+ include/linux/kernel.h \ -+ $(wildcard include/config/preempt/voluntary.h) \ -+ $(wildcard include/config/debug/spinlock/sleep.h) \ -+ $(wildcard include/config/printk.h) \ -+ $(wildcard include/config/numa.h) \ -+ /usr/lib/gcc/i386-redhat-linux/4.1.2/include/stdarg.h \ -+ include/linux/linkage.h \ -+ include/asm/linkage.h \ -+ $(wildcard include/config/x86/alignment/16.h) \ -+ include/linux/bitops.h \ -+ include/asm/bitops.h \ -+ include/asm/alternative.h \ -+ $(wildcard include/config/smp.h) \ -+ $(wildcard include/config/paravirt.h) \ -+ include/asm-generic/bitops/sched.h \ -+ include/asm-generic/bitops/hweight.h \ -+ include/asm-generic/bitops/fls64.h \ -+ include/asm-generic/bitops/ext2-non-atomic.h \ -+ include/asm-generic/bitops/le.h \ -+ include/asm/byteorder.h \ -+ $(wildcard include/config/x86/bswap.h) \ -+ include/linux/byteorder/little_endian.h \ -+ include/linux/byteorder/swab.h \ -+ include/linux/byteorder/generic.h \ -+ include/asm-generic/bitops/minix.h \ -+ include/linux/log2.h \ -+ $(wildcard include/config/arch/has/ilog2/u32.h) \ -+ $(wildcard include/config/arch/has/ilog2/u64.h) \ -+ include/asm/bug.h \ -+ $(wildcard include/config/debug/bugverbose.h) \ -+ include/asm-generic/bug.h \ -+ $(wildcard include/config/generic/bug.h) \ -+ include/linux/time.h \ -+ include/linux/seqlock.h \ -+ include/linux/spinlock.h \ -+ $(wildcard include/config/debug/spinlock.h) \ -+ $(wildcard include/config/preempt.h) \ -+ $(wildcard include/config/debug/lock/alloc.h) \ -+ include/linux/preempt.h \ -+ $(wildcard include/config/debug/preempt.h) \ -+ include/linux/thread_info.h \ -+ include/asm/thread_info.h \ -+ $(wildcard include/config/4kstacks.h) \ -+ $(wildcard include/config/debug/stack/usage.h) \ -+ include/asm/page.h \ -+ $(wildcard include/config/x86/use/3dnow.h) \ -+ $(wildcard include/config/x86/pae.h) \ -+ $(wildcard include/config/hugetlb/page.h) \ -+ $(wildcard include/config/highmem4g.h) \ -+ $(wildcard include/config/page/offset.h) \ -+ $(wildcard include/config/flatmem.h) \ -+ include/asm-generic/pgtable-nopmd.h \ -+ include/asm-generic/pgtable-nopud.h \ -+ include/asm-generic/memory_model.h \ -+ $(wildcard include/config/discontigmem.h) \ -+ $(wildcard include/config/sparsemem.h) \ -+ $(wildcard include/config/out/of/line/pfn/to/page.h) \ -+ include/asm-generic/page.h \ -+ include/asm/processor.h \ -+ $(wildcard include/config/x86/ht.h) \ -+ $(wildcard include/config/mk8.h) \ -+ $(wildcard include/config/mk7.h) \ -+ include/asm/vm86.h \ -+ $(wildcard include/config/vm86.h) \ -+ include/asm/ptrace.h \ -+ include/asm/ptrace-abi.h \ -+ include/asm/segment.h \ -+ include/asm/math_emu.h \ -+ include/asm/sigcontext.h \ -+ include/asm/cpufeature.h \ -+ include/asm/required-features.h \ -+ $(wildcard include/config/x86/minimum/cpu.h) \ -+ $(wildcard include/config/x86/cmov.h) \ -+ $(wildcard include/config/x86/cmpxchg64.h) \ -+ include/asm/msr.h \ -+ include/asm/msr-index.h \ -+ include/asm/errno.h \ -+ include/asm-generic/errno.h \ -+ include/asm-generic/errno-base.h \ -+ include/linux/errno.h \ -+ include/asm/system.h \ -+ $(wildcard include/config/x86/oostore.h) \ -+ include/asm/cmpxchg.h \ -+ $(wildcard include/config/x86/cmpxchg.h) \ -+ include/linux/irqflags.h \ -+ $(wildcard include/config/trace/irqflags.h) \ -+ $(wildcard include/config/trace/irqflags/support.h) \ -+ $(wildcard include/config/x86.h) \ -+ include/asm/irqflags.h \ -+ include/asm/processor-flags.h \ -+ include/linux/cache.h \ -+ include/asm/cache.h \ -+ $(wildcard include/config/x86/l1/cache/shift.h) \ -+ include/linux/threads.h \ -+ $(wildcard include/config/nr/cpus.h) \ -+ $(wildcard include/config/base/small.h) \ -+ include/asm/percpu.h \ -+ include/linux/cpumask.h \ -+ $(wildcard include/config/hotplug/cpu.h) \ -+ include/linux/bitmap.h \ -+ include/linux/string.h \ -+ include/asm/string.h \ -+ include/linux/init.h \ -+ $(wildcard include/config/modules.h) \ -+ $(wildcard include/config/hotplug.h) \ -+ $(wildcard include/config/memory/hotplug.h) \ -+ $(wildcard include/config/acpi/hotplug/memory.h) \ -+ include/linux/stringify.h \ -+ include/linux/bottom_half.h \ -+ include/linux/spinlock_types.h \ -+ include/linux/lockdep.h \ -+ $(wildcard include/config/lockdep.h) \ -+ $(wildcard include/config/generic/hardirqs.h) \ -+ $(wildcard include/config/prove/locking.h) \ -+ include/asm/spinlock_types.h \ -+ include/asm/spinlock.h \ -+ $(wildcard include/config/x86/ppro/fence.h) \ -+ include/asm/atomic.h \ -+ $(wildcard include/config/m386.h) \ -+ include/asm-generic/atomic.h \ -+ include/asm/rwlock.h \ -+ include/linux/spinlock_api_smp.h \ -+ include/linux/vs_time.h \ -+ $(wildcard include/config/vserver/vtime.h) \ -+ include/linux/net.h \ -+ include/linux/wait.h \ -+ include/linux/list.h \ -+ $(wildcard include/config/debug/list.h) \ -+ include/linux/poison.h \ -+ include/linux/prefetch.h \ -+ include/asm/current.h \ -+ include/linux/random.h \ -+ include/linux/ioctl.h \ -+ include/asm/ioctl.h \ -+ include/asm-generic/ioctl.h \ -+ include/linux/sysctl.h \ -+ $(wildcard include/config/icmp/ipod.h) \ -+ $(wildcard include/config/web100/net100.h) \ -+ $(wildcard include/config/web100/stats.h) \ -+ include/linux/textsearch.h \ -+ include/linux/module.h \ -+ $(wildcard include/config/modversions.h) \ -+ $(wildcard include/config/unused/symbols.h) \ -+ $(wildcard include/config/module/unload.h) \ -+ $(wildcard include/config/kallsyms.h) \ -+ $(wildcard include/config/sysfs.h) \ -+ include/linux/stat.h \ -+ include/asm/stat.h \ -+ include/linux/kmod.h \ -+ $(wildcard include/config/kmod.h) \ -+ include/linux/elf.h \ -+ include/linux/auxvec.h \ -+ include/asm/auxvec.h \ -+ include/linux/elf-em.h \ -+ include/asm/elf.h \ -+ include/asm/user.h \ -+ include/asm/desc.h \ -+ include/asm/ldt.h \ -+ include/linux/smp.h \ -+ include/asm/smp.h \ -+ $(wildcard include/config/x86/local/apic.h) \ -+ $(wildcard include/config/x86/io/apic.h) \ -+ include/asm/mpspec.h \ -+ $(wildcard include/config/acpi.h) \ -+ include/asm/mpspec_def.h \ -+ include/asm-i386/mach-generic/mach_mpspec.h \ -+ include/asm/apic.h \ -+ $(wildcard include/config/x86/good/apic.h) \ -+ include/linux/pm.h \ -+ $(wildcard include/config/pm.h) \ -+ include/linux/delay.h \ -+ include/asm/delay.h \ -+ include/asm/fixmap.h \ -+ $(wildcard include/config/highmem.h) \ -+ $(wildcard include/config/x86/visws/apic.h) \ -+ $(wildcard include/config/x86/f00f/bug.h) \ -+ $(wildcard include/config/x86/cyclone/timer.h) \ -+ $(wildcard include/config/pci/mmconfig.h) \ -+ include/asm/acpi.h \ -+ $(wildcard include/config/acpi/sleep.h) \ -+ include/acpi/pdc_intel.h \ -+ include/asm/apicdef.h \ -+ include/asm/kmap_types.h \ -+ $(wildcard include/config/debug/highmem.h) \ -+ include/asm/io_apic.h \ -+ include/asm-i386/mach-generic/mach_apicdef.h \ -+ include/asm/genapic.h \ -+ include/linux/percpu.h \ -+ include/linux/slab.h \ -+ $(wildcard include/config/slab/debug.h) \ -+ $(wildcard include/config/slab.h) \ -+ $(wildcard include/config/slub.h) \ -+ $(wildcard include/config/debug/slab.h) \ -+ include/linux/gfp.h \ -+ $(wildcard include/config/zone/dma.h) \ -+ $(wildcard include/config/zone/dma32.h) \ -+ include/linux/mmzone.h \ -+ $(wildcard include/config/force/max/zoneorder.h) \ -+ $(wildcard include/config/arch/populates/node/map.h) \ -+ $(wildcard include/config/flat/node/mem/map.h) \ -+ $(wildcard include/config/have/memory/present.h) \ -+ $(wildcard include/config/need/node/memmap/size.h) \ -+ $(wildcard include/config/need/multiple/nodes.h) \ -+ $(wildcard include/config/have/arch/early/pfn/to/nid.h) \ -+ $(wildcard include/config/sparsemem/extreme.h) \ -+ $(wildcard include/config/nodes/span/other/nodes.h) \ -+ $(wildcard include/config/holes/in/zone.h) \ -+ include/linux/numa.h \ -+ $(wildcard include/config/nodes/shift.h) \ -+ include/linux/nodemask.h \ -+ include/linux/memory_hotplug.h \ -+ $(wildcard include/config/have/arch/nodedata/extension.h) \ -+ include/linux/notifier.h \ -+ include/linux/mutex.h \ -+ $(wildcard include/config/debug/mutexes.h) \ -+ $(wildcard include/config/chopstix.h) \ -+ include/linux/rwsem.h \ -+ $(wildcard include/config/rwsem/generic/spinlock.h) \ -+ include/asm/rwsem.h \ -+ include/linux/srcu.h \ -+ include/linux/topology.h \ -+ $(wildcard include/config/sched/smt.h) \ -+ $(wildcard include/config/sched/mc.h) \ -+ include/asm/topology.h \ -+ include/asm-generic/topology.h \ -+ include/linux/slab_def.h \ -+ include/linux/kmalloc_sizes.h \ -+ include/asm/mmu.h \ -+ include/asm/semaphore.h \ -+ include/linux/kobject.h \ -+ include/linux/sysfs.h \ -+ include/linux/kref.h \ -+ include/linux/moduleparam.h \ -+ include/asm/local.h \ -+ include/asm/module.h \ -+ $(wildcard include/config/m486.h) \ -+ $(wildcard include/config/m586.h) \ -+ $(wildcard include/config/m586tsc.h) \ -+ $(wildcard include/config/m586mmx.h) \ -+ $(wildcard include/config/mcore2.h) \ -+ $(wildcard include/config/m686.h) \ -+ $(wildcard include/config/mpentiumii.h) \ -+ $(wildcard include/config/mpentiumiii.h) \ -+ $(wildcard include/config/mpentiumm.h) \ -+ $(wildcard include/config/mpentium4.h) \ -+ $(wildcard include/config/mk6.h) \ -+ $(wildcard include/config/x86/elan.h) \ -+ $(wildcard include/config/mcrusoe.h) \ -+ $(wildcard include/config/mefficeon.h) \ -+ $(wildcard include/config/mwinchipc6.h) \ -+ $(wildcard include/config/mwinchip2.h) \ -+ $(wildcard include/config/mwinchip3d.h) \ -+ $(wildcard include/config/mcyrixiii.h) \ -+ $(wildcard include/config/mviac3/2.h) \ -+ $(wildcard include/config/mviac7.h) \ -+ $(wildcard include/config/mgeodegx1.h) \ -+ $(wildcard include/config/mgeode/lx.h) \ -+ include/linux/err.h \ -+ include/net/checksum.h \ -+ include/asm/uaccess.h \ -+ $(wildcard include/config/x86/intel/usercopy.h) \ -+ $(wildcard include/config/x86/wp/works/ok.h) \ -+ include/asm/checksum.h \ -+ include/linux/in6.h \ -+ include/linux/rcupdate.h \ -+ include/linux/dmaengine.h \ -+ $(wildcard include/config/dma/engine.h) \ -+ include/linux/device.h \ -+ $(wildcard include/config/debug/devres.h) \ -+ include/linux/ioport.h \ -+ include/linux/klist.h \ -+ include/linux/completion.h \ -+ include/asm/device.h \ -+ include/linux/hrtimer.h \ -+ $(wildcard include/config/high/res/timers.h) \ -+ $(wildcard include/config/timer/stats.h) \ -+ include/linux/rbtree.h \ -+ include/linux/ktime.h \ -+ $(wildcard include/config/ktime/scalar.h) \ -+ include/linux/jiffies.h \ -+ include/linux/calc64.h \ -+ include/asm/div64.h \ -+ include/linux/timex.h \ -+ $(wildcard include/config/time/interpolation.h) \ -+ $(wildcard include/config/no/hz.h) \ -+ include/asm/param.h \ -+ $(wildcard include/config/hz.h) \ -+ include/asm/timex.h \ -+ include/asm/tsc.h \ -+ $(wildcard include/config/x86/tsc.h) \ -+ $(wildcard include/config/x86/generic.h) \ -+ include/linux/if_packet.h \ -+ include/linux/timer.h \ -+ include/linux/interrupt.h \ -+ $(wildcard include/config/generic/irq/probe.h) \ -+ include/linux/irqreturn.h \ -+ include/linux/hardirq.h \ -+ $(wildcard include/config/preempt/bkl.h) \ -+ $(wildcard include/config/virt/cpu/accounting.h) \ -+ include/linux/smp_lock.h \ -+ $(wildcard include/config/lock/kernel.h) \ -+ include/linux/sched.h \ -+ $(wildcard include/config/detect/softlockup.h) \ -+ $(wildcard include/config/split/ptlock/cpus.h) \ -+ $(wildcard include/config/keys.h) \ -+ $(wildcard include/config/bsd/process/acct.h) \ -+ $(wildcard include/config/taskstats.h) \ -+ $(wildcard include/config/inotify/user.h) \ -+ $(wildcard include/config/schedstats.h) \ -+ $(wildcard include/config/task/delay/acct.h) \ -+ $(wildcard include/config/blk/dev/io/trace.h) \ -+ $(wildcard include/config/cc/stackprotector.h) \ -+ $(wildcard include/config/sysvipc.h) \ -+ $(wildcard include/config/rt/mutexes.h) \ -+ $(wildcard include/config/task/xacct.h) \ -+ $(wildcard include/config/cpusets.h) \ -+ $(wildcard include/config/fault/injection.h) \ -+ include/linux/capability.h \ -+ include/asm/cputime.h \ -+ include/asm-generic/cputime.h \ -+ include/linux/sem.h \ -+ include/linux/ipc.h \ -+ $(wildcard include/config/ipc/ns.h) \ -+ include/asm/ipcbuf.h \ -+ include/asm/sembuf.h \ -+ include/linux/signal.h \ -+ include/asm/signal.h \ -+ include/asm-generic/signal.h \ -+ include/asm/siginfo.h \ -+ include/asm-generic/siginfo.h \ -+ include/linux/securebits.h \ -+ include/linux/fs_struct.h \ -+ include/linux/pid.h \ -+ include/linux/seccomp.h \ -+ $(wildcard include/config/seccomp.h) \ -+ include/linux/futex.h \ -+ $(wildcard include/config/futex.h) \ -+ include/linux/rtmutex.h \ -+ $(wildcard include/config/debug/rt/mutexes.h) \ -+ include/linux/plist.h \ -+ $(wildcard include/config/debug/pi/list.h) \ -+ include/linux/param.h \ -+ include/linux/resource.h \ -+ include/asm/resource.h \ -+ include/asm-generic/resource.h \ -+ include/linux/task_io_accounting.h \ -+ $(wildcard include/config/task/io/accounting.h) \ -+ include/linux/aio.h \ -+ include/linux/workqueue.h \ -+ include/linux/aio_abi.h \ -+ include/asm/hardirq.h \ -+ include/linux/irq.h \ -+ $(wildcard include/config/s390.h) \ -+ $(wildcard include/config/irq/per/cpu.h) \ -+ $(wildcard include/config/irq/release/method.h) \ -+ $(wildcard include/config/generic/pending/irq.h) \ -+ $(wildcard include/config/irqbalance.h) \ -+ $(wildcard include/config/auto/irq/affinity.h) \ -+ $(wildcard include/config/generic/hardirqs/no//do/irq.h) \ -+ include/asm/irq.h \ -+ include/asm-i386/mach-default/irq_vectors.h \ -+ include/asm-i386/mach-default/irq_vectors_limits.h \ -+ include/asm/irq_regs.h \ -+ include/asm/hw_irq.h \ -+ include/linux/profile.h \ -+ $(wildcard include/config/profiling.h) \ -+ include/asm/sections.h \ -+ include/asm-generic/sections.h \ -+ include/linux/irq_cpustat.h \ -+ include/linux/vmalloc.h \ -+ include/linux/ethtool.h \ -+ drivers/net/igb/igb.h \ -+ $(wildcard include/config/dca.h) \ -+ $(wildcard include/config/inet/lro.h) \ -+ $(wildcard include/config/igb/separate/tx/handler.h) \ -+ $(wildcard include/config/igb/disable/packet/split.h) \ -+ include/linux/pci.h \ -+ $(wildcard include/config/pci/msi.h) \ -+ $(wildcard include/config/pci.h) \ -+ $(wildcard include/config/ht/irq.h) \ -+ $(wildcard include/config/pci/domains.h) \ -+ include/linux/pci_regs.h \ -+ include/linux/mod_devicetable.h \ -+ include/linux/pci_ids.h \ -+ include/linux/dmapool.h \ -+ include/asm/io.h \ -+ $(wildcard include/config/x86/numaq.h) \ -+ include/asm-generic/iomap.h \ -+ include/asm/scatterlist.h \ -+ include/asm/pci.h \ -+ include/linux/mm.h \ -+ $(wildcard include/config/mmu.h) \ -+ $(wildcard include/config/stack/growsup.h) \ -+ $(wildcard include/config/debug/vm.h) \ -+ $(wildcard include/config/shmem.h) \ -+ $(wildcard include/config/ia64.h) \ -+ $(wildcard include/config/debug/pagealloc.h) \ -+ include/linux/prio_tree.h \ -+ include/linux/fs.h \ -+ $(wildcard include/config/dnotify.h) \ -+ $(wildcard include/config/vserver/cowbl.h) \ -+ $(wildcard include/config/quota.h) \ -+ $(wildcard include/config/inotify.h) \ -+ $(wildcard include/config/security.h) \ -+ $(wildcard include/config/epoll.h) \ -+ $(wildcard include/config/auditsyscall.h) \ -+ $(wildcard include/config/block.h) \ -+ $(wildcard include/config/fs/xip.h) \ -+ $(wildcard include/config/migration.h) \ -+ include/linux/limits.h \ -+ include/linux/kdev_t.h \ -+ include/linux/dcache.h \ -+ include/linux/namei.h \ -+ include/linux/radix-tree.h \ -+ include/linux/quota.h \ -+ include/linux/dqblk_xfs.h \ -+ include/linux/dqblk_v1.h \ -+ include/linux/dqblk_v2.h \ -+ include/linux/nfs_fs_i.h \ -+ include/linux/nfs.h \ -+ include/linux/sunrpc/msg_prot.h \ -+ include/linux/fcntl.h \ -+ include/asm/fcntl.h \ -+ include/asm-generic/fcntl.h \ -+ $(wildcard include/config/64bit.h) \ -+ include/linux/debug_locks.h \ -+ $(wildcard include/config/debug/locking/api/selftests.h) \ -+ include/linux/backing-dev.h \ -+ include/linux/mm_types.h \ -+ include/asm/pgtable.h \ -+ $(wildcard include/config/highpte.h) \ -+ include/asm/paravirt.h \ -+ include/asm/pgtable-2level-defs.h \ -+ include/asm/pgtable-2level.h \ -+ include/asm-generic/pgtable.h \ -+ include/linux/page-flags.h \ -+ $(wildcard include/config/swap.h) \ -+ include/linux/vmstat.h \ -+ $(wildcard include/config/vm/event/counters.h) \ -+ include/asm-generic/pci-dma-compat.h \ -+ include/linux/dma-mapping.h \ -+ include/asm/dma-mapping.h \ -+ include/asm-generic/pci.h \ -+ drivers/net/igb/kcompat.h \ -+ $(wildcard include/config/e1000/napi.h) \ -+ $(wildcard include/config/e1000e/napi.h) \ -+ $(wildcard include/config/ixgb/napi.h) \ -+ $(wildcard include/config/e1000/disable/packet/split.h) \ -+ $(wildcard include/config/space/len.h) \ -+ $(wildcard include/config/netdevices/multiqueue.h) \ -+ include/linux/version.h \ -+ include/linux/etherdevice.h \ -+ include/linux/in.h \ -+ include/linux/ip.h \ -+ include/linux/udp.h \ -+ include/net/inet_sock.h \ -+ $(wildcard include/config/ipv6.h) \ -+ include/linux/jhash.h \ -+ include/net/flow.h \ -+ $(wildcard include/config/ipv6/mip6.h) \ -+ include/net/sock.h \ -+ $(wildcard include/config/security/network.h) \ -+ include/linux/security.h \ -+ $(wildcard include/config/security/network/xfrm.h) \ -+ include/linux/binfmts.h \ -+ include/linux/shm.h \ -+ include/asm/shmparam.h \ -+ include/asm/shmbuf.h \ -+ include/linux/msg.h \ -+ include/asm/msgbuf.h \ -+ include/linux/key.h \ -+ include/linux/xfrm.h \ -+ include/linux/filter.h \ -+ include/net/dst.h \ -+ $(wildcard include/config/net/cls/route.h) \ -+ $(wildcard include/config/xfrm.h) \ -+ include/linux/rtnetlink.h \ -+ include/linux/netlink.h \ -+ include/linux/if_link.h \ -+ include/linux/if_addr.h \ -+ include/linux/neighbour.h \ -+ include/net/neighbour.h \ -+ include/linux/seq_file.h \ -+ include/net/rtnetlink.h \ -+ include/net/netlink.h \ -+ include/net/request_sock.h \ -+ include/linux/mii.h \ -+ include/linux/latency.h \ -+ drivers/net/igb/e1000_api.h \ -+ drivers/net/igb/e1000_hw.h \ -+ drivers/net/igb/e1000_osdep.h \ -+ drivers/net/igb/e1000_regs.h \ -+ drivers/net/igb/e1000_defines.h \ -+ $(wildcard include/config/res.h) \ -+ $(wildcard include/config/fault.h) \ -+ drivers/net/igb/e1000_mac.h \ -+ drivers/net/igb/e1000_phy.h \ -+ drivers/net/igb/e1000_nvm.h \ -+ drivers/net/igb/e1000_manage.h \ -+ drivers/net/igb/e1000_82575.h \ -+ drivers/net/igb/igb_regtest.h \ -+ include/linux/if_vlan.h \ -+ -+drivers/net/igb/igb_ethtool.o: $(deps_drivers/net/igb/igb_ethtool.o) -+ -+$(deps_drivers/net/igb/igb_ethtool.o): -diff -Nru vanilla/drivers/net/igb/igb.h linux-i686-2.6.22/drivers/net/igb/igb.h ---- vanilla/drivers/net/igb/igb.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/igb.h 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,377 @@ -+/******************************************************************************* ++ /* PHY loopback cannot be performed if SoL/IDER ++ * sessions are active */ ++ if (e1000_check_reset_block(&adapter->hw)) { ++ DPRINTK(DRV, ERR, "Cannot do PHY loopback test " ++ "when SoL/IDER is active.\n"); ++ *data = 0; ++ goto out; ++ } ++ *data = igb_setup_desc_rings(adapter); ++ if (*data) ++ goto out; ++ *data = igb_setup_loopback_test(adapter); ++ if (*data) ++ goto err_loopback; ++ *data = igb_run_loopback_test(adapter); ++ igb_loopback_cleanup(adapter); + -+ Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++err_loopback: ++ igb_free_desc_rings(adapter); ++out: ++ return *data; ++} + -+ 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. ++static int igb_link_test(struct igb_adapter *adapter, u64 *data) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ *data = 0; ++ if (adapter->hw.phy.media_type == e1000_media_type_internal_serdes) { ++ int i = 0; ++ adapter->hw.mac.serdes_has_link = FALSE; + -+ 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. ++ /* On some blade server designs, link establishment ++ * could take as long as 2-3 minutes */ ++ do { ++ e1000_check_for_link(&adapter->hw); ++ if (adapter->hw.mac.serdes_has_link) ++ return *data; ++ msleep(20); ++ } while (i++ < 3750); + -+ 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. ++ *data = 1; ++ } else { ++ e1000_check_for_link(&adapter->hw); ++ if (adapter->hw.mac.autoneg) ++ msleep(4000); + -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". ++ if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) ++ *data = 1; ++ } ++ return *data; ++} + -+ Contact Information: -+ e1000-devel Mailing List -+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++static void igb_diag_test(struct net_device *netdev, ++ struct ethtool_test *eth_test, u64 *data) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ u16 autoneg_advertised; ++ u8 forced_speed_duplex, autoneg; ++ bool if_running = netif_running(netdev); + -+*******************************************************************************/ ++ set_bit(__IGB_TESTING, &adapter->state); ++ if (eth_test->flags == ETH_TEST_FL_OFFLINE) { ++ /* Offline tests */ + ++ /* save speed, duplex, autoneg settings */ ++ autoneg_advertised = adapter->hw.phy.autoneg_advertised; ++ forced_speed_duplex = adapter->hw.mac.forced_speed_duplex; ++ autoneg = adapter->hw.mac.autoneg; + -+/* Linux PRO/1000 Ethernet Driver main header file */ ++ DPRINTK(HW, INFO, "offline testing starting\n"); + -+#ifndef _IGB_H_ -+#define _IGB_H_ ++ /* Link test performed before hardware reset so autoneg doesn't ++ * interfere with test result */ ++ if (igb_link_test(adapter, &data[4])) ++ eth_test->flags |= ETH_TEST_FL_FAILED; + -+#include -+#include -+#include ++ if (if_running) ++ /* indicate we're in test mode */ ++ dev_close(netdev); ++ else ++ igb_reset(adapter); + -+#ifdef SIOCETHTOOL -+#include -+#endif ++ if (igb_reg_test(adapter, &data[0])) ++ eth_test->flags |= ETH_TEST_FL_FAILED; + -+struct igb_adapter; ++ igb_reset(adapter); ++ if (igb_eeprom_test(adapter, &data[1])) ++ eth_test->flags |= ETH_TEST_FL_FAILED; + -+#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) -+#define IGB_DCA -+#endif -+#ifdef IGB_DCA -+#include -+#endif ++ igb_reset(adapter); ++ if (igb_intr_test(adapter, &data[2])) ++ eth_test->flags |= ETH_TEST_FL_FAILED; + -+#ifdef IGB_LRO -+#undef IGB_LRO -+#ifdef NETIF_F_LRO -+#if defined(CONFIG_INET_LRO) || defined(CONFIG_INET_LRO_MODULE) -+#include -+#define MAX_LRO_DESCRIPTORS 8 -+#define IGB_LRO -+#endif -+#endif -+#endif /* IGB_LRO */ ++ igb_reset(adapter); ++ if (igb_loopback_test(adapter, &data[3])) ++ eth_test->flags |= ETH_TEST_FL_FAILED; + -+#include "kcompat.h" ++ /* restore speed, duplex, autoneg settings */ ++ adapter->hw.phy.autoneg_advertised = autoneg_advertised; ++ adapter->hw.mac.forced_speed_duplex = forced_speed_duplex; ++ adapter->hw.mac.autoneg = autoneg; + -+#include "e1000_api.h" -+#include "e1000_82575.h" ++ /* force this routine to wait until autoneg complete/timeout */ ++ adapter->hw.phy.autoneg_wait_to_complete = TRUE; ++ igb_reset(adapter); ++ adapter->hw.phy.autoneg_wait_to_complete = FALSE; + -+#define IGB_ERR(args...) printk(KERN_ERR "igb: " args) ++ clear_bit(__IGB_TESTING, &adapter->state); ++ if (if_running) ++ dev_open(netdev); ++ } else { ++ DPRINTK(HW, INFO, "online testing starting\n"); ++ /* Online tests */ ++ if (igb_link_test(adapter, &data[4])) ++ eth_test->flags |= ETH_TEST_FL_FAILED; + -+#define PFX "igb: " -+#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)) ++ /* Online tests aren't run; pass by default */ ++ data[0] = 0; ++ data[1] = 0; ++ data[2] = 0; ++ data[3] = 0; + -+/* Interrupt defines */ -+#define IGB_START_ITR 648 /* ~6000 ints/sec */ ++ clear_bit(__IGB_TESTING, &adapter->state); ++ } ++ msleep_interruptible(4 * 1000); ++} + -+/* Interrupt modes, as used by the IntMode paramter */ -+#define IGB_INT_MODE_LEGACY 0 -+#define IGB_INT_MODE_MSI 1 -+#define IGB_INT_MODE_MSIX_1Q 2 -+#define IGB_INT_MODE_MSIX_MQ 3 ++static int igb_wol_exclusion(struct igb_adapter *adapter, ++ struct ethtool_wolinfo *wol) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ int retval = 1; /* fail by default */ + -+#define HW_PERF -+/* TX/RX descriptor defines */ -+#define IGB_DEFAULT_TXD 256 -+#define IGB_MIN_TXD 80 -+#define IGB_MAX_TXD 4096 ++ switch (hw->device_id) { ++ case E1000_DEV_ID_82575GB_QUAD_COPPER: ++ /* WoL not supported */ ++ wol->supported = 0; ++ break; ++ case E1000_DEV_ID_82575EB_FIBER_SERDES: ++ case E1000_DEV_ID_82576_FIBER: ++ case E1000_DEV_ID_82576_SERDES: ++ /* Wake events not supported on port B */ ++ if (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_FUNC_1) { ++ wol->supported = 0; ++ break; ++ } ++ /* return success for non excluded adapter ports */ ++ retval = 0; ++ break; ++ case E1000_DEV_ID_82576_QUAD_COPPER: ++ /* quad port adapters only support WoL on port A */ ++ if (!(adapter->flags & IGB_FLAG_QUAD_PORT_A)) { ++ wol->supported = 0; ++ break; ++ } ++ /* return success for non excluded adapter ports */ ++ retval = 0; ++ break; ++ default: ++ /* dual port cards only support WoL on port A from now on ++ * unless it was enabled in the eeprom for port B ++ * so exclude FUNC_1 ports from having WoL enabled */ ++ if (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_FUNC_1 && ++ !adapter->eeprom_wol) { ++ wol->supported = 0; ++ break; ++ } + -+#define IGB_DEFAULT_RXD 256 -+#define IGB_MIN_RXD 80 -+#define IGB_MAX_RXD 4096 ++ retval = 0; ++ } + -+#define IGB_MIN_ITR_USECS 10 /* 100k irq/sec */ -+#define IGB_MAX_ITR_USECS 10000 /* 100 irq/sec */ ++ return retval; ++} + -+/* Transmit and receive queues */ -+#ifndef CONFIG_IGB_SEPARATE_TX_HANDLER -+#define IGB_MAX_RX_QUEUES (hw->mac.type > e1000_82575 ? 8 : 4) -+#define IGB_MAX_TX_QUEUES (hw->mac.type > e1000_82575 ? 8 : 4) -+#define IGB_ABS_MAX_TX_QUEUES 8 -+#else /* CONFIG_IGB_SEPARATE_TX_HANDLER */ -+#define IGB_MAX_RX_QUEUES 4 -+#define IGB_MAX_TX_QUEUES 4 -+#define IGB_ABS_MAX_TX_QUEUES 4 -+#endif /* CONFIG_IGB_SEPARATE_TX_HANDLER */ ++static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); + -+/* RX descriptor control thresholds. -+ * PTHRESH - MAC will consider prefetch if it has fewer than this number of -+ * descriptors available in its onboard memory. -+ * Setting this to 0 disables RX descriptor prefetch. -+ * HTHRESH - MAC will only prefetch if there are at least this many descriptors -+ * available in host memory. -+ * If PTHRESH is 0, this should also be 0. -+ * WTHRESH - RX descriptor writeback threshold - MAC will delay writing back -+ * descriptors until either it has this many to write back, or the -+ * ITR timer expires. -+ */ -+#define IGB_RX_PTHRESH 16 -+#define IGB_RX_HTHRESH 8 -+#define IGB_RX_WTHRESH 1 ++ wol->supported = WAKE_UCAST | WAKE_MCAST | ++ WAKE_BCAST | WAKE_MAGIC; ++ wol->wolopts = 0; + -+/* this is the size past which hardware will drop packets when setting LPE=0 */ -+#define MAXIMUM_ETHERNET_VLAN_SIZE 1522 ++ /* this function will set ->supported = 0 and return 1 if wol is not ++ * supported by this hardware */ ++ if (igb_wol_exclusion(adapter, wol) || ++ !device_can_wakeup(&adapter->pdev->dev)) ++ return; + -+/* Supported Rx Buffer Sizes */ -+#define IGB_RXBUFFER_128 128 /* Used for packet split */ -+#define IGB_RXBUFFER_256 256 /* Used for packet split */ -+#define IGB_RXBUFFER_512 512 -+#define IGB_RXBUFFER_1024 1024 -+#define IGB_RXBUFFER_2048 2048 -+#define IGB_RXBUFFER_4096 4096 -+#define IGB_RXBUFFER_8192 8192 -+#define IGB_RXBUFFER_16384 16384 ++ /* apply any specific unsupported masks here */ ++ switch (adapter->hw.device_id) { ++ default: ++ break; ++ } + -+/* Packet Buffer allocations */ -+#define IGB_PBA_BYTES_SHIFT 0xA -+#define IGB_TX_HEAD_ADDR_SHIFT 7 -+#define IGB_PBA_TX_MASK 0xFFFF0000 ++ if (adapter->wol & E1000_WUFC_EX) ++ wol->wolopts |= WAKE_UCAST; ++ if (adapter->wol & E1000_WUFC_MC) ++ wol->wolopts |= WAKE_MCAST; ++ if (adapter->wol & E1000_WUFC_BC) ++ wol->wolopts |= WAKE_BCAST; ++ if (adapter->wol & E1000_WUFC_MAG) ++ wol->wolopts |= WAKE_MAGIC; + -+#define IGB_FC_PAUSE_TIME 0x0680 /* 858 usec */ ++ return; ++} + -+/* How many Tx Descriptors do we need to call netif_wake_queue ? */ -+#define IGB_TX_QUEUE_WAKE 32 -+/* How many Rx Buffers do we bundle into one write to the hardware ? */ -+#define IGB_RX_BUFFER_WRITE 16 /* Must be power of 2 */ ++static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); + -+#define AUTO_ALL_MODES 0 -+#define IGB_EEPROM_APME 0x0400 ++ if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) ++ return -EOPNOTSUPP; + -+#ifndef IGB_MASTER_SLAVE -+/* Switch to override PHY master/slave setting */ -+#define IGB_MASTER_SLAVE e1000_ms_hw_default -+#endif ++ if (igb_wol_exclusion(adapter, wol)) ++ return wol->wolopts ? -EOPNOTSUPP : 0; + -+#define IGB_MNG_VLAN_NONE -1 ++ /* these settings will always override what we currently have */ ++ adapter->wol = 0; + -+/* wrapper around a pointer to a socket buffer, -+ * so a DMA handle can be stored along with the buffer */ -+struct igb_buffer { -+ struct sk_buff *skb; -+ dma_addr_t dma; -+ union { -+ /* TX */ -+ struct { -+ unsigned long time_stamp; -+ u32 length; -+ }; ++ if (wol->wolopts & WAKE_UCAST) ++ adapter->wol |= E1000_WUFC_EX; ++ if (wol->wolopts & WAKE_MCAST) ++ adapter->wol |= E1000_WUFC_MC; ++ if (wol->wolopts & WAKE_BCAST) ++ adapter->wol |= E1000_WUFC_BC; ++ if (wol->wolopts & WAKE_MAGIC) ++ adapter->wol |= E1000_WUFC_MAG; ++ device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); + -+#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT -+ /* RX */ -+ struct { -+ struct page *page; -+ u64 page_dma; -+ unsigned int page_offset; -+ }; -+#endif -+ }; -+}; ++ return 0; ++} + -+struct igb_queue_stats { -+ u64 packets; -+ u64 bytes; -+}; ++/* bit defines for adapter->led_status */ ++#define IGB_LED_ON 0 + -+struct igb_ring { -+ struct igb_adapter *adapter; /* backlink */ -+ void *desc; /* descriptor ring memory */ -+ dma_addr_t dma; /* phys address of the ring */ -+ unsigned int size; /* length of desc. ring in bytes */ -+ unsigned int count; /* number of desc. in the ring */ -+ u16 next_to_use; -+ u16 next_to_clean; -+ u16 head; -+ u16 tail; -+ struct igb_buffer *buffer_info; /* array of buffer info structs */ ++static int igb_phys_id(struct net_device *netdev, u32 data) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ struct e1000_hw *hw = &adapter->hw; ++ unsigned long timeout; + -+ u32 eims_value; -+ u32 itr_val; -+ u16 itr_register; -+ u16 cpu; ++ timeout = data * 1000; + -+ int queue_index; -+ unsigned int total_bytes; -+ unsigned int total_packets; ++ /* ++ * msleep_interruptable only accepts unsigned int so we are limited ++ * in how long a duration we can wait ++ */ ++ if (!timeout || timeout > UINT_MAX) ++ timeout = UINT_MAX; + -+ char name[IFNAMSIZ + 5]; -+ union { -+ /* TX */ -+ struct { -+ struct igb_queue_stats tx_stats; -+ bool detect_tx_hung; -+ }; -+ /* RX */ -+ struct { -+ struct igb_queue_stats rx_stats; -+ struct napi_struct napi; -+ int set_itr; -+ struct igb_ring *buddy; -+#ifdef IGB_LRO -+ struct net_lro_mgr lro_mgr; -+ bool lro_used; -+#endif -+ }; -+ }; -+}; ++ e1000_blink_led(hw); ++ msleep_interruptible(timeout); + ++ e1000_led_off(hw); ++ clear_bit(IGB_LED_ON, &adapter->led_status); ++ e1000_cleanup_led(hw); + -+#define IGB_DESC_UNUSED(R) \ -+ ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \ -+ (R)->next_to_clean - (R)->next_to_use - 1) ++ return 0; ++} + -+#define E1000_RX_DESC_ADV(R, i) \ -+ (&(((union e1000_adv_rx_desc *)((R).desc))[i])) -+#define E1000_TX_DESC_ADV(R, i) \ -+ (&(((union e1000_adv_tx_desc *)((R).desc))[i])) -+#define E1000_TX_CTXTDESC_ADV(R, i) \ -+ (&(((struct e1000_adv_tx_context_desc *)((R).desc))[i])) -+#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) -+#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc) -+#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc) ++static int igb_set_coalesce(struct net_device *netdev, ++ struct ethtool_coalesce *ec) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ int i; + -+#define MAX_MSIX_COUNT 10 -+/* board specific private data structure */ ++ if ((ec->rx_coalesce_usecs > IGB_MAX_ITR_USECS) || ++ ((ec->rx_coalesce_usecs > 3) && ++ (ec->rx_coalesce_usecs < IGB_MIN_ITR_USECS)) || ++ (ec->rx_coalesce_usecs == 2)) ++ return -EINVAL; + -+struct igb_adapter { -+ struct timer_list watchdog_timer; -+ struct timer_list phy_info_timer; -+ struct vlan_group *vlgrp; -+ u16 mng_vlan_id; -+ u32 bd_number; -+ u32 rx_buffer_len; -+ u32 wol; -+ u32 en_mng_pt; -+ u16 link_speed; -+ u16 link_duplex; ++ /* convert to rate of irq's per second */ ++ if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3) { ++ adapter->itr = IGB_START_ITR; ++ adapter->itr_setting = ec->rx_coalesce_usecs; ++ } else { ++ adapter->itr = ec->rx_coalesce_usecs << 2; ++ adapter->itr_setting = adapter->itr; ++ } + -+ unsigned int total_tx_bytes; -+ unsigned int total_tx_packets; -+ unsigned int total_rx_bytes; -+ unsigned int total_rx_packets; -+ /* Interrupt Throttle Rate */ -+ u32 itr; -+ u32 itr_setting; -+ u16 tx_itr; -+ u16 rx_itr; ++ for (i = 0; i < adapter->num_q_vectors; i++) { ++ struct igb_q_vector *q_vector = adapter->q_vector[i]; ++ q_vector->itr_val = adapter->itr; ++ q_vector->set_itr = 1; ++ } + -+ struct work_struct reset_task; -+ struct work_struct watchdog_task; -+ bool fc_autoneg; -+ u8 tx_timeout_factor; -+#ifdef ETHTOOL_PHYS_ID -+ struct timer_list blink_timer; -+ unsigned long led_status; -+#endif ++ return 0; ++} + -+ /* TX */ -+ struct igb_ring *tx_ring; /* One per active queue */ -+ unsigned int restart_queue; -+ unsigned long tx_queue_len; -+ u32 txd_cmd; -+ u32 tx_timeout_count; ++static int igb_get_coalesce(struct net_device *netdev, ++ struct ethtool_coalesce *ec) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); + -+ /* RX */ -+ struct igb_ring *rx_ring; /* One per active queue */ -+ int num_tx_queues; -+ int num_rx_queues; ++ if (adapter->itr_setting <= 3) ++ ec->rx_coalesce_usecs = adapter->itr_setting; ++ else ++ ec->rx_coalesce_usecs = adapter->itr_setting >> 2; + -+ u64 hw_csum_err; -+ u64 hw_csum_good; -+ u64 rx_hdr_split; -+ u32 alloc_rx_buff_failed; -+ bool rx_csum; -+ u16 rx_ps_hdr_size; -+ u32 max_frame_size; -+ u32 min_frame_size; ++ return 0; ++} + ++static int igb_nway_reset(struct net_device *netdev) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ if (netif_running(netdev)) ++ igb_reinit_locked(adapter); ++ return 0; ++} + -+ /* OS defined structs */ -+ struct net_device *netdev; -+ struct pci_dev *pdev; -+ struct net_device_stats net_stats; ++#ifdef HAVE_ETHTOOL_GET_SSET_COUNT ++static int igb_get_sset_count(struct net_device *netdev, int sset) ++{ ++ switch (sset) { ++ case ETH_SS_STATS: ++ return IGB_STATS_LEN; ++ case ETH_SS_TEST: ++ return IGB_TEST_LEN; ++ default: ++ return -ENOTSUPP; ++ } ++} ++#else ++static int igb_get_stats_count(struct net_device *netdev) ++{ ++ return IGB_STATS_LEN; ++} + -+ /* structs defined in e1000_hw.h */ -+ struct e1000_hw hw; -+ struct e1000_hw_stats stats; -+ struct e1000_phy_info phy_info; -+ struct e1000_phy_stats phy_stats; ++static int igb_diag_test_count(struct net_device *netdev) ++{ ++ return IGB_TEST_LEN; ++} ++#endif + -+#ifdef ETHTOOL_TEST -+ u32 test_icr; -+ struct igb_ring test_tx_ring; -+ struct igb_ring test_rx_ring; ++static void igb_get_ethtool_stats(struct net_device *netdev, ++ struct ethtool_stats *stats, u64 *data) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ u64 *queue_stat; ++ int stat_count = sizeof(struct igb_queue_stats) / sizeof(u64); ++ int j; ++ int i; ++ u64 restart_queue = 0, hw_csum_err = 0, hw_csum_good = 0; ++#ifdef IGB_LRO ++ int aggregated = 0, flushed = 0, no_desc = 0; +#endif + ++ /* collect tx ring stats */ ++ for (i = 0; i < adapter->num_tx_queues; i++) ++ restart_queue += adapter->tx_ring[i].restart_queue; ++ adapter->restart_queue = restart_queue; + -+ int msg_enable; -+ struct msix_entry *msix_entries; -+ int int_mode; -+ u32 eims_enable_mask; -+ u32 eims_other; -+ u32 lli_port; -+ u32 lli_size; -+ u64 lli_int; -+ unsigned long state; -+ unsigned int flags; -+ u32 eeprom_wol; -+ u32 *config_space; -+#ifdef HAVE_TX_MQ -+ struct igb_ring *multi_tx_table[IGB_ABS_MAX_TX_QUEUES]; -+#endif /* HAVE_TX_MQ */ ++ ++ for (i = 0; i < adapter->num_rx_queues; i++) { ++ hw_csum_err += adapter->rx_ring[i].hw_csum_err; ++ hw_csum_good += adapter->rx_ring[i].hw_csum_good; +#ifdef IGB_LRO -+ unsigned int lro_max_aggr; -+ unsigned int lro_aggregated; -+ unsigned int lro_flushed; -+ unsigned int lro_no_desc; ++ aggregated += adapter->rx_ring[i].lro_mgr.stats.aggregated; ++ flushed += adapter->rx_ring[i].lro_mgr.stats.flushed; ++ no_desc += adapter->rx_ring[i].lro_mgr.stats.no_desc; ++ } ++ adapter->lro_aggregated = aggregated; ++ adapter->lro_flushed = flushed; ++ adapter->lro_no_desc = no_desc; ++#else ++ } +#endif -+ unsigned int tx_ring_count; -+ unsigned int rx_ring_count; -+}; ++ adapter->hw_csum_err = hw_csum_err; ++ adapter->hw_csum_good = hw_csum_good; + ++ igb_update_stats(adapter); + -+#define IGB_FLAG_HAS_MSI (1 << 0) -+#define IGB_FLAG_MSI_ENABLE (1 << 1) -+#define IGB_FLAG_HAS_DCA (1 << 2) -+#define IGB_FLAG_DCA_ENABLED (1 << 3) -+#define IGB_FLAG_LLI_PUSH (1 << 4) -+#define IGB_FLAG_IN_NETPOLL (1 << 5) -+#define IGB_FLAG_QUAD_PORT_A (1 << 6) -+#define IGB_FLAG_NEED_CTX_IDX (1 << 7) ++ for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) { ++ char *p = (char *)adapter+igb_gstrings_stats[i].stat_offset; ++ data[i] = (igb_gstrings_stats[i].sizeof_stat == ++ sizeof(u64)) ? *(u64 *)p : *(u32 *)p; ++ } ++ for (j = 0; j < adapter->num_tx_queues; j++) { ++ int k; ++ queue_stat = (u64 *)&adapter->tx_ring[j].stats; ++ for (k = 0; k < stat_count; k++) ++ data[i + k] = queue_stat[k]; ++ i += k; ++ } ++ for (j = 0; j < adapter->num_rx_queues; j++) { ++ int k; ++ queue_stat = (u64 *)&adapter->rx_ring[j].stats; ++ for (k = 0; k < stat_count; k++) ++ data[i + k] = queue_stat[k]; ++ i += k; ++ } ++} + -+enum e1000_state_t { -+ __IGB_TESTING, -+ __IGB_RESETTING, -+ __IGB_DOWN -+}; ++static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ u8 *p = data; ++ int i; + -+extern char igb_driver_name[]; -+extern char igb_driver_version[]; ++ switch (stringset) { ++ case ETH_SS_TEST: ++ memcpy(data, *igb_gstrings_test, ++ IGB_TEST_LEN*ETH_GSTRING_LEN); ++ break; ++ case ETH_SS_STATS: ++ for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) { ++ memcpy(p, igb_gstrings_stats[i].stat_string, ++ ETH_GSTRING_LEN); ++ p += ETH_GSTRING_LEN; ++ } ++ for (i = 0; i < adapter->num_tx_queues; i++) { ++ sprintf(p, "tx_queue_%u_packets", i); ++ p += ETH_GSTRING_LEN; ++ sprintf(p, "tx_queue_%u_bytes", i); ++ p += ETH_GSTRING_LEN; ++ } ++ for (i = 0; i < adapter->num_rx_queues; i++) { ++ sprintf(p, "rx_queue_%u_packets", i); ++ p += ETH_GSTRING_LEN; ++ sprintf(p, "rx_queue_%u_bytes", i); ++ p += ETH_GSTRING_LEN; ++ } ++/* BUG_ON(p - data != IGB_STATS_LEN * ETH_GSTRING_LEN); */ ++ break; ++ } ++} + -+extern int igb_up(struct igb_adapter *); -+extern void igb_down(struct igb_adapter *); -+extern void igb_reinit_locked(struct igb_adapter *); -+extern void igb_reset(struct igb_adapter *); -+extern int igb_set_spd_dplx(struct igb_adapter *, u16); -+extern int igb_setup_tx_resources(struct igb_adapter *, struct igb_ring *); -+extern int igb_setup_rx_resources(struct igb_adapter *, struct igb_ring *); -+extern void igb_free_tx_resources(struct igb_ring *); -+extern void igb_free_rx_resources(struct igb_ring *); -+extern void igb_update_stats(struct igb_adapter *); -+extern void igb_set_ethtool_ops(struct net_device *); -+extern void igb_check_options(struct igb_adapter *); -+#ifdef ETHTOOL_OPS_COMPAT -+extern int ethtool_ioctl(struct ifreq *); ++static struct ethtool_ops igb_ethtool_ops = { ++ .get_settings = igb_get_settings, ++ .set_settings = igb_set_settings, ++ .get_drvinfo = igb_get_drvinfo, ++ .get_regs_len = igb_get_regs_len, ++ .get_regs = igb_get_regs, ++ .get_wol = igb_get_wol, ++ .set_wol = igb_set_wol, ++ .get_msglevel = igb_get_msglevel, ++ .set_msglevel = igb_set_msglevel, ++ .nway_reset = igb_nway_reset, ++ .get_link = ethtool_op_get_link, ++ .get_eeprom_len = igb_get_eeprom_len, ++ .get_eeprom = igb_get_eeprom, ++ .set_eeprom = igb_set_eeprom, ++ .get_ringparam = igb_get_ringparam, ++ .set_ringparam = igb_set_ringparam, ++ .get_pauseparam = igb_get_pauseparam, ++ .set_pauseparam = igb_set_pauseparam, ++ .get_rx_csum = igb_get_rx_csum, ++ .set_rx_csum = igb_set_rx_csum, ++ .get_tx_csum = igb_get_tx_csum, ++ .set_tx_csum = igb_set_tx_csum, ++ .get_sg = ethtool_op_get_sg, ++ .set_sg = ethtool_op_set_sg, ++#ifdef NETIF_F_TSO ++ .get_tso = ethtool_op_get_tso, ++ .set_tso = igb_set_tso, ++#endif ++#ifdef HAVE_ETHTOOL_GET_SSET_COUNT ++ .get_sset_count = igb_get_sset_count, ++#else ++ .get_stats_count = igb_get_stats_count, ++ .self_test_count = igb_diag_test_count, ++#endif ++ .self_test = igb_diag_test, ++ .get_strings = igb_get_strings, ++ .phys_id = igb_phys_id, ++ .get_ethtool_stats = igb_get_ethtool_stats, ++#ifdef ETHTOOL_GPERMADDR ++ .get_perm_addr = ethtool_op_get_perm_addr, ++#endif ++ .get_coalesce = igb_get_coalesce, ++ .set_coalesce = igb_set_coalesce, ++#ifdef NETIF_F_LRO ++ .get_flags = ethtool_op_get_flags, ++ .set_flags = ethtool_op_set_flags, +#endif ++}; + -+#endif /* _IGB_H_ */ -diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/igb_main.c ---- vanilla/drivers/net/igb/igb_main.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/igb_main.c 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,4844 @@ ++void igb_set_ethtool_ops(struct net_device *netdev) ++{ ++ SET_ETHTOOL_OPS(netdev, &igb_ethtool_ops); ++} ++#endif /* SIOCETHTOOL */ +Index: linux-2.6.22/drivers/net/igb/igb_main.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/igb_main.c 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,6250 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ Copyright(c) 2007-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, @@ -17693,27 +15101,26 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + +#include "igb.h" + -+ -+#if defined(DEBUG) || defined (DEBUG_DUMP) || defined (DEBUG_ICR) || \ -+ defined(DEBUG_ITR) -+#define DRV_DEBUG "_debug" -+#else +#define DRV_DEBUG -+#endif +#define DRV_HW_PERF ++#define VERSION_SUFFIX + -+#define DRV_VERSION "1.3.8.6" DRV_DEBUG DRV_HW_PERF ++#define DRV_VERSION "2.0.6" VERSION_SUFFIX DRV_DEBUG DRV_HW_PERF + +char igb_driver_name[] = "igb"; +char igb_driver_version[] = DRV_VERSION; +static const char igb_driver_string[] = + "Intel(R) Gigabit Ethernet Network Driver"; -+static const char igb_copyright[] = "Copyright (c) 2007-2008 Intel Corporation."; ++static const char igb_copyright[] = "Copyright (c) 2007-2009 Intel Corporation."; + +static struct pci_device_id igb_pci_tbl[] = { + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576) }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS) }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS_SERDES) }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_FIBER) }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES) }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES_QUAD) }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_QUAD_COPPER) }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_COPPER) }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_FIBER_SERDES) }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575GB_QUAD_COPPER) }, @@ -17728,6 +15135,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +static int igb_setup_all_rx_resources(struct igb_adapter *); +static void igb_free_all_tx_resources(struct igb_adapter *); +static void igb_free_all_rx_resources(struct igb_adapter *); ++static void igb_setup_mrqc(struct igb_adapter *); +void igb_update_stats(struct igb_adapter *); +static int igb_probe(struct pci_dev *, const struct pci_device_id *); +static void __devexit igb_remove(struct pci_dev *pdev); @@ -17736,38 +15144,32 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +static int igb_close(struct net_device *); +static void igb_configure_tx(struct igb_adapter *); +static void igb_configure_rx(struct igb_adapter *); -+static void igb_setup_rctl(struct igb_adapter *); +static void igb_clean_all_tx_rings(struct igb_adapter *); +static void igb_clean_all_rx_rings(struct igb_adapter *); +static void igb_clean_tx_ring(struct igb_ring *); +static void igb_clean_rx_ring(struct igb_ring *); -+static void igb_set_multi(struct net_device *); ++static void igb_set_rx_mode(struct net_device *); +static void igb_update_phy_info(unsigned long); +static void igb_watchdog(unsigned long); +static void igb_watchdog_task(struct work_struct *); -+static int igb_xmit_frame_ring_adv(struct sk_buff *, struct net_device *, -+ struct igb_ring *); -+static int igb_xmit_frame_adv(struct sk_buff *skb, struct net_device *); -+static struct net_device_stats * igb_get_stats(struct net_device *); ++static netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *, struct net_device *, ++ struct igb_ring *); ++static netdev_tx_t igb_xmit_frame_adv(struct sk_buff *skb, struct net_device *); ++static struct net_device_stats *igb_get_stats(struct net_device *); +static int igb_change_mtu(struct net_device *, int); +static int igb_set_mac(struct net_device *, void *); ++static void igb_set_uta(struct igb_adapter *adapter); +static irqreturn_t igb_intr(int irq, void *); +static irqreturn_t igb_intr_msi(int irq, void *); +static irqreturn_t igb_msix_other(int irq, void *); -+static irqreturn_t igb_msix_rx(int irq, void *); -+#ifdef CONFIG_IGB_SEPARATE_TX_HANDLER -+static irqreturn_t igb_msix_tx(int irq, void *); -+#endif -+static int igb_clean_rx_ring_msix(struct napi_struct *, int); ++static irqreturn_t igb_msix_ring(int irq, void *); +#ifdef IGB_DCA -+static void igb_update_rx_dca(struct igb_ring *); -+static void igb_update_tx_dca(struct igb_ring *); ++static void igb_update_dca(struct igb_q_vector *); +static void igb_setup_dca(struct igb_adapter *); +#endif /* IGB_DCA */ -+static bool igb_clean_tx_irq(struct igb_ring *); ++static bool igb_clean_tx_irq(struct igb_q_vector *); +static int igb_poll(struct napi_struct *, int); -+static bool igb_clean_rx_irq_adv(struct igb_ring *, int *, int); -+static void igb_alloc_rx_buffers_adv(struct igb_ring *, int); ++static bool igb_clean_rx_irq_adv(struct igb_q_vector *, int *, int); +#ifdef IGB_LRO +static int igb_get_skb_hdr(struct sk_buff *skb, void **, void **, u64 *, void *); +#endif @@ -17778,9 +15180,15 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +static void igb_vlan_rx_add_vid(struct net_device *, u16); +static void igb_vlan_rx_kill_vid(struct net_device *, u16); +static void igb_restore_vlan(struct igb_adapter *); ++static void igb_rar_set_qsel(struct igb_adapter *, u8 *, u32 , u8); ++static void igb_ping_all_vfs(struct igb_adapter *); ++static void igb_msg_task(struct igb_adapter *); ++static void igb_vmm_control(struct igb_adapter *); ++static void igb_restore_vf_multicasts(struct igb_adapter *adapter); ++static void igb_vf_configuration(struct pci_dev *, unsigned int); + -+static int igb_suspend(struct pci_dev *, pm_message_t); +#ifdef CONFIG_PM ++static int igb_suspend(struct pci_dev *, pm_message_t); +static int igb_resume(struct pci_dev *); +#endif +#ifndef USE_REBOOT_NOTIFIER @@ -17835,7 +15243,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + .shutdown = igb_shutdown, +#endif +#ifdef HAVE_PCI_ERS -+ .err_handler = &igb_err_handler ++ .err_handler = &igb_err_handler, +#endif +}; + @@ -17844,6 +15252,48 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + ++static void igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add) ++{ ++ struct e1000_host_mng_dhcp_cookie *mng_cookie = &hw->mng_cookie; ++ u32 index = (vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK; ++ u32 mask = 1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK); ++ u32 vfta; ++ ++ /* ++ * if this is the management vlan the only option is to add it in so ++ * that the management pass through will continue to work ++ */ ++ if ((mng_cookie->status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && ++ (vid == mng_cookie->vlan_id)) ++ add = TRUE; ++ ++ vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, index); ++ if (add) ++ vfta |= mask; ++ else ++ vfta &= ~mask; ++ ++ e1000_write_vfta(hw, index, vfta); ++} ++ ++#ifdef SIOCSHWTSTAMP ++/** ++ * igb_read_clock - read raw cycle counter (to be used by time counter) ++ */ ++static cycle_t igb_read_clock(const struct cyclecounter *tc) ++{ ++ struct igb_adapter *adapter = ++ container_of(tc, struct igb_adapter, cycles); ++ struct e1000_hw *hw = &adapter->hw; ++ u64 stamp = 0; ++ int shift = 0; ++ ++ stamp |= (u64)E1000_READ_REG(hw, E1000_SYSTIML) << shift; ++ stamp |= (u64)E1000_READ_REG(hw, E1000_SYSTIMH) << (shift + 32); ++ return stamp; ++} ++ ++#endif /* SIOCSHWTSTAMP */ +static int debug = NETIF_MSG_DRV | NETIF_MSG_PROBE; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0=none, ..., 16=all)"); @@ -17854,26 +15304,23 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * igb_init_module is the first routine called when the driver is + * loaded. All it does is register with the PCI subsystem. + **/ -+ +static int __init igb_init_module(void) +{ + int ret; -+ -+ + printk(KERN_INFO "%s - version %s\n", + igb_driver_string, igb_driver_version); + + printk(KERN_INFO "%s\n", igb_copyright); + ++#ifdef IGB_DCA ++ dca_register_notify(&dca_notifier); ++#endif + ret = pci_register_driver(&igb_driver); +#ifdef USE_REBOOT_NOTIFIER + if (ret >= 0) { + register_reboot_notifier(&igb_notifier_reboot); + } +#endif -+#ifdef IGB_DCA -+ dca_register_notify(&dca_notifier); -+#endif + return ret; +} + @@ -17885,7 +15332,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * igb_exit_module is called just before the driver is removed + * from memory. + **/ -+ +static void __exit igb_exit_module(void) +{ +#ifdef IGB_DCA @@ -17897,7 +15343,59 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + pci_unregister_driver(&igb_driver); +} + -+module_exit(igb_exit_module); ++module_exit(igb_exit_module); ++ ++/** ++ * igb_cache_ring_register - Descriptor ring to register mapping ++ * @adapter: board private structure to initialize ++ * ++ * Once we know the feature-set enabled for the device, we'll cache ++ * the register offset the descriptor ring is assigned to. ++ **/ ++static void igb_cache_ring_register(struct igb_adapter *adapter) ++{ ++ int i = 0, j = 0; ++ u32 rbase_offset = adapter->vfs_allocated_count; ++ ++ switch (adapter->hw.mac.type) { ++ case e1000_82576: ++ /* The queues are allocated for virtualization such that VF 0 ++ * is allocated queues 0 and 8, VF 1 queues 1 and 9, etc. ++ * In order to avoid collision we start at the first free queue ++ * and continue consuming queues in the same sequence ++ */ ++ if ((adapter->RSS_queues > 1) && adapter->VMDQ_queues) { ++ for (; i < adapter->RSS_queues; i++) ++ adapter->rx_ring[i].reg_idx = rbase_offset + ++ ((i & 0x1) << 3) + (i >> 1); ++#ifdef HAVE_TX_MQ ++ for (; j < adapter->RSS_queues; j++) ++ adapter->tx_ring[j].reg_idx = rbase_offset + ++ ((j & 0x1) << 3) + (j >> 1); ++#endif ++ } ++ case e1000_82575: ++ default: ++ for (; i < adapter->num_rx_queues; i++) ++ adapter->rx_ring[i].reg_idx = rbase_offset + i; ++ for (; j < adapter->num_tx_queues; j++) ++ adapter->tx_ring[j].reg_idx = rbase_offset + j; ++ break; ++ } ++} ++ ++static void igb_free_queues(struct igb_adapter *adapter) ++{ ++ kfree(adapter->tx_ring); ++ kfree(adapter->rx_ring); ++ ++ adapter->tx_ring = NULL; ++ adapter->rx_ring = NULL; ++ ++ adapter->num_rx_queues = 0; ++ adapter->num_tx_queues = 0; ++ ++} + +/** + * igb_alloc_queues - Allocate memory for all rings @@ -17906,7 +15404,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * We allocate one ring per queue at run-time since we don't know the + * number of queues at compile-time. + **/ -+ +static int igb_alloc_queues(struct igb_adapter *adapter) +{ + int i; @@ -17921,40 +15418,45 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + if (!adapter->rx_ring) + goto err; + -+ adapter->rx_ring->buddy = adapter->tx_ring; -+ + for (i = 0; i < adapter->num_tx_queues; i++) { + struct igb_ring *ring = &(adapter->tx_ring[i]); + ring->count = adapter->tx_ring_count; -+ ring->adapter = adapter; + ring->queue_index = i; ++ ring->pdev = adapter->pdev; ++ /* For 82575, context index must be unique per ring. */ ++ if (adapter->hw.mac.type == e1000_82575) ++ ring->ctx_idx = i << 4; ++ + } + for (i = 0; i < adapter->num_rx_queues; i++) { + struct igb_ring *ring = &(adapter->rx_ring[i]); + ring->count = adapter->rx_ring_count; -+ ring->adapter = adapter; + ring->queue_index = i; -+ ring->itr_register = E1000_ITR; -+ /* set a default napi handler for each rx_ring */ -+ netif_napi_add(adapter->netdev, &ring->napi, igb_poll, 64); ++ ring->pdev = adapter->pdev; ++ ring->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE; ++ ring->rx_ps_hdr_size = 0; /* disable packet split */ ++ ring->rx_csum = true; /* enable rx checksum */ ++ ++#ifdef IGB_LRO ++ /* Intitial LRO Settings */ ++ ring->lro_mgr.max_aggr = adapter->lro_max_aggr; ++ ring->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS; ++ ring->lro_mgr.get_skb_header = igb_get_skb_hdr; ++ ring->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID; ++ ring->lro_mgr.dev = adapter->netdev; ++ ring->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY; ++ ring->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; ++#endif + } -+ return E1000_SUCCESS; + -+err: -+ kfree(adapter->tx_ring); -+ kfree(adapter->rx_ring); -+ return -ENOMEM; -+} ++ igb_cache_ring_register(adapter); + -+static void igb_free_queues(struct igb_adapter *adapter) -+{ -+ int i; ++ return E1000_SUCCESS; + -+ for (i = 0; i < adapter->num_rx_queues; i++) -+ netif_napi_del(&adapter->rx_ring[i].napi); ++err: ++ igb_free_queues(adapter); + -+ kfree(adapter->tx_ring); -+ kfree(adapter->rx_ring); ++ return -ENOMEM; +} + +static void igb_configure_lli(struct igb_adapter *adapter) @@ -17968,7 +15470,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + if (adapter->lli_port) { + /* use filter 0 for port */ -+ port = ntohs((u16)adapter->lli_port); ++ port = htons((u16)adapter->lli_port); + E1000_WRITE_REG(hw, E1000_IMIR(0), + (port | E1000_IMIR_PORT_IM_EN)); + E1000_WRITE_REG(hw, E1000_IMIREXT(0), @@ -17994,13 +15496,19 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +} + +#define IGB_N0_QUEUE -1 -+ -+static void igb_assign_vector(struct igb_adapter *adapter, int rx_queue, -+ int tx_queue, int msix_vector) ++static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector) +{ + u32 msixbm = 0; ++ struct igb_adapter *adapter = q_vector->adapter; + struct e1000_hw *hw = &adapter->hw; + u32 ivar, index; ++ int rx_queue = IGB_N0_QUEUE; ++ int tx_queue = IGB_N0_QUEUE; ++ ++ if (q_vector->rx_ring) ++ rx_queue = q_vector->rx_ring->reg_idx; ++ if (q_vector->tx_ring) ++ tx_queue = q_vector->tx_ring->reg_idx; + + switch (hw->mac.type) { + case e1000_82575: @@ -18008,16 +15516,12 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + bitmask for the EICR/EIMS/EIMC registers. To assign one + or more queues to a vector, we write the appropriate bits + into the MSIXBM register for that vector. */ -+ if (rx_queue > IGB_N0_QUEUE) { ++ if (rx_queue > IGB_N0_QUEUE) + msixbm = E1000_EICR_RX_QUEUE0 << rx_queue; -+ adapter->rx_ring[rx_queue].eims_value = msixbm; -+ } -+ if (tx_queue > IGB_N0_QUEUE) { ++ if (tx_queue > IGB_N0_QUEUE) + msixbm |= E1000_EICR_TX_QUEUE0 << tx_queue; -+ adapter->tx_ring[tx_queue].eims_value = -+ E1000_EICR_TX_QUEUE0 << tx_queue; -+ } + E1000_WRITE_REG_ARRAY(hw, E1000_MSIXBM(0), msix_vector, msixbm); ++ q_vector->eims_value = msixbm; + break; + case e1000_82576: + /* 82576 uses a table-based method for assigning vectors. @@ -18036,7 +15540,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + ivar = ivar & 0xFF00FFFF; + ivar |= (msix_vector | E1000_IVAR_VALID) << 16; + } -+ adapter->rx_ring[rx_queue].eims_value= 1 << msix_vector; + E1000_WRITE_REG_ARRAY(hw, E1000_IVAR0, index, ivar); + } + if (tx_queue > IGB_N0_QUEUE) { @@ -18051,9 +15554,9 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + ivar = ivar & 0x00FFFFFF; + ivar |= (msix_vector | E1000_IVAR_VALID) << 24; + } -+ adapter->tx_ring[tx_queue].eims_value= 1 << msix_vector; + E1000_WRITE_REG_ARRAY(hw, E1000_IVAR0, index, ivar); + } ++ q_vector->eims_value = 1 << msix_vector; + break; + default: + BUG(); @@ -18074,64 +15577,10 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + struct e1000_hw *hw = &adapter->hw; + + adapter->eims_enable_mask = 0; -+ if (hw->mac.type == e1000_82576) -+ /* Turn on MSI-X capability first, or our settings -+ * won't stick. And it will take days to debug. */ -+ E1000_WRITE_REG(hw, E1000_GPIE, E1000_GPIE_MSIX_MODE | -+ E1000_GPIE_PBA | E1000_GPIE_EIAME | -+ E1000_GPIE_NSICR); -+ -+#ifdef CONFIG_IGB_SEPARATE_TX_HANDLER -+ for (i = 0; i < adapter->num_tx_queues; i++) { -+ struct igb_ring *tx_ring = &adapter->tx_ring[i]; -+ igb_assign_vector(adapter, IGB_N0_QUEUE, i, vector++); -+ adapter->eims_enable_mask |= tx_ring->eims_value; -+ if (tx_ring->itr_val) -+ writel(tx_ring->itr_val, -+ hw->hw_addr + tx_ring->itr_register); -+ else -+ writel(1, hw->hw_addr + tx_ring->itr_register); -+ } -+ -+ for (i = 0; i < adapter->num_rx_queues; i++) { -+ struct igb_ring *rx_ring = &adapter->rx_ring[i]; -+ rx_ring->buddy = NULL; -+ igb_assign_vector(adapter, i, IGB_N0_QUEUE, vector++); -+ adapter->eims_enable_mask |= rx_ring->eims_value; -+ if (rx_ring->itr_val) -+ writel(rx_ring->itr_val, -+ hw->hw_addr + rx_ring->itr_register); -+ else -+ writel(1, hw->hw_addr + rx_ring->itr_register); -+ } -+ -+#else -+ for (i = 0; i < adapter->num_rx_queues; i++) { -+ struct igb_ring *rx_ring = &adapter->rx_ring[i]; -+ if (i < adapter->num_tx_queues) { -+ igb_assign_vector(adapter, i, i, vector++); -+ rx_ring->buddy = &adapter->tx_ring[i]; -+ rx_ring->eims_value |= adapter->tx_ring[i].eims_value; -+ } else { -+ igb_assign_vector(adapter, i, IGB_N0_QUEUE, vector++); -+ } -+ adapter->eims_enable_mask |= rx_ring->eims_value; -+ if (rx_ring->itr_val) -+ writel(rx_ring->itr_val, -+ hw->hw_addr + rx_ring->itr_register); -+ else -+ writel(1, hw->hw_addr + rx_ring->itr_register); -+ } -+ -+#endif + + /* set vector for other causes, i.e. link changes */ -+ + switch (hw->mac.type) { + case e1000_82575: -+ E1000_WRITE_REG_ARRAY(hw, E1000_MSIXBM(0), vector++, -+ E1000_EIMS_OTHER); -+ + tmp = E1000_READ_REG(hw, E1000_CTRL_EXT); + /* enable MSI-X PBA support*/ + tmp |= E1000_CTRL_EXT_PBA_CLR; @@ -18141,22 +15590,40 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + tmp |= E1000_CTRL_EXT_IRCA; + + E1000_WRITE_REG(hw, E1000_CTRL_EXT, tmp); -+ adapter->eims_enable_mask |= E1000_EIMS_OTHER; ++ ++ /* enable msix_other interrupt */ ++ E1000_WRITE_REG_ARRAY(hw, E1000_MSIXBM(0), vector++, ++ E1000_EIMS_OTHER); + adapter->eims_other = E1000_EIMS_OTHER; + + break; + + case e1000_82576: ++ /* Turn on MSI-X capability first, or our settings ++ * won't stick. And it will take days to debug. */ ++ E1000_WRITE_REG(hw, E1000_GPIE, E1000_GPIE_MSIX_MODE | ++ E1000_GPIE_PBA | E1000_GPIE_EIAME | ++ E1000_GPIE_NSICR); ++ ++ /* enable msix_other interrupt */ ++ adapter->eims_other = 1 << vector; + tmp = (vector++ | E1000_IVAR_VALID) << 8; -+ E1000_WRITE_REG(hw, E1000_IVAR_MISC, tmp); + -+ adapter->eims_enable_mask = (1 << (vector)) - 1; -+ adapter->eims_other = 1 << (vector - 1); ++ E1000_WRITE_REG(hw, E1000_IVAR_MISC, tmp); + break; + default: + /* do nothing, since nothing else supports MSI-X */ + break; + } /* switch (hw->mac.type) */ ++ ++ adapter->eims_enable_mask |= adapter->eims_other; ++ ++ for (i = 0; i < adapter->num_q_vectors; i++) { ++ struct igb_q_vector *q_vector = adapter->q_vector[i]; ++ igb_assign_vector(q_vector, vector++); ++ adapter->eims_enable_mask |= q_vector->eims_value; ++ } ++ + E1000_WRITE_FLUSH(hw); +} + @@ -18169,53 +15636,40 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +static int igb_request_msix(struct igb_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; ++ struct e1000_hw *hw = &adapter->hw; + int i, err = 0, vector = 0; + -+ vector = 0; -+ -+#ifdef CONFIG_IGB_SEPARATE_TX_HANDLER -+ for (i = 0; i < adapter->num_tx_queues; i++) { -+ struct igb_ring *ring = &(adapter->tx_ring[i]); -+ sprintf(ring->name, "%s-tx%d", netdev->name, i); -+ err = request_irq(adapter->msix_entries[vector].vector, -+ &igb_msix_tx, 0, ring->name, -+ &(adapter->tx_ring[i])); -+ if (err) -+ goto out; -+ ring->itr_register = E1000_EITR(0) + (vector << 2); -+ ring->itr_val = 1952; /* ~2000 ints/sec */ -+ vector++; -+ } -+#endif -+ for (i = 0; i < adapter->num_rx_queues; i++) { -+ struct igb_ring *ring = &(adapter->rx_ring[i]); -+ if (strlen(netdev->name) < (IFNAMSIZ - 5)) -+#ifdef CONFIG_IGB_SEPARATE_TX_HANDLER -+ sprintf(ring->name, "%s-rx%d", netdev->name, i); -+#else -+ sprintf(ring->name, "%s-Q%d", netdev->name, i); -+#endif ++ err = request_irq(adapter->msix_entries[vector].vector, ++ &igb_msix_other, 0, netdev->name, adapter); ++ if (err) ++ goto out; ++ vector++; ++ ++ for (i = 0; i < adapter->num_q_vectors; i++) { ++ struct igb_q_vector *q_vector = adapter->q_vector[i]; ++ ++ q_vector->itr_register = hw->hw_addr + E1000_EITR(vector); ++ ++ if (q_vector->rx_ring && q_vector->tx_ring) ++ sprintf(q_vector->name, "%s-TxRx-%u", netdev->name, ++ q_vector->rx_ring->queue_index); ++ else if (q_vector->tx_ring) ++ sprintf(q_vector->name, "%s-tx-%u", netdev->name, ++ q_vector->tx_ring->queue_index); ++ else if (q_vector->rx_ring) ++ sprintf(q_vector->name, "%s-rx-%u", netdev->name, ++ q_vector->rx_ring->queue_index); + else -+ memcpy(ring->name, netdev->name, IFNAMSIZ); ++ sprintf(q_vector->name, "%s-unused", netdev->name); ++ + err = request_irq(adapter->msix_entries[vector].vector, -+ &igb_msix_rx, 0, ring->name, -+ &(adapter->rx_ring[i])); ++ &igb_msix_ring, 0, q_vector->name, ++ q_vector); + if (err) + goto out; -+ ring->itr_register = E1000_EITR(0) + (vector << 2); -+ ring->itr_val = adapter->itr; -+ /* overwrite the poll routine for MSIX, we've already done -+ * netif_napi_add */ -+ ring->napi.poll = &igb_clean_rx_ring_msix; + vector++; + } + -+ err = request_irq(adapter->msix_entries[vector].vector, -+ &igb_msix_other, 0, netdev->name, netdev); -+ if (err) -+ goto out; -+ -+ + igb_configure_msix(adapter); + return 0; +out: @@ -18228,12 +15682,49 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + pci_disable_msix(adapter->pdev); + kfree(adapter->msix_entries); + adapter->msix_entries = NULL; -+ } else if (adapter->flags & IGB_FLAG_HAS_MSI) ++ } else if (adapter->flags & IGB_FLAG_HAS_MSI) { + pci_disable_msi(adapter->pdev); ++ } ++ ++ adapter->num_rx_queues = 0; ++ adapter->num_tx_queues = 0; + + return; +} + ++/** ++ * igb_free_q_vectors - Free memory allocated for interrupt vectors ++ * @adapter: board private structure to initialize ++ * ++ * This function frees the memory allocated to the q_vectors. In addition if ++ * NAPI is enabled it will delete any references to the NAPI struct prior ++ * to freeing the q_vector. ++ **/ ++static void igb_free_q_vectors(struct igb_adapter *adapter) ++{ ++ int v_idx; ++ ++ for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) { ++ struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; ++ adapter->q_vector[v_idx] = NULL; ++ netif_napi_del(&q_vector->napi); ++ kfree(q_vector); ++ } ++ adapter->num_q_vectors = 0; ++} ++ ++/** ++ * igb_clear_interrupt_scheme - reset the device to a state of no interrupts ++ * ++ * This function resets the device so that it has 0 rx queues, tx queues, and ++ * MSI-X interrupts allocated. ++ */ ++static void igb_clear_interrupt_scheme(struct igb_adapter *adapter) ++{ ++ igb_free_queues(adapter); ++ igb_free_q_vectors(adapter); ++ igb_reset_interrupt_capability(adapter); ++} + +/** + * igb_set_interrupt_capability - set MSI or MSI-X if supported @@ -18246,22 +15737,37 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + int err; + int numvecs, i; + ++ /* Number of supported queues. */ ++ adapter->num_rx_queues = adapter->RSS_queues; + -+ switch (adapter->int_mode) { -+ case IGB_INT_MODE_MSIX_1Q: -+ adapter->num_rx_queues = 1; -+ adapter->num_tx_queues = 1; -+ case IGB_INT_MODE_MSIX_MQ: -+#ifdef CONFIG_IGB_SEPARATE_TX_HANDLER -+ numvecs = adapter->num_tx_queues + adapter->num_rx_queues + 1; ++ if (adapter->VMDQ_queues > 1) ++ adapter->num_rx_queues += adapter->VMDQ_queues - 1; ++ ++#ifdef HAVE_TX_MQ ++ adapter->num_tx_queues = adapter->num_rx_queues; +#else -+ numvecs = adapter->num_rx_queues + 1; ++ adapter->num_tx_queues = max_t(u32, 1, adapter->VMDQ_queues); +#endif ++ ++ switch (adapter->int_mode) { ++ case IGB_INT_MODE_MSIX: ++ /* start with one vector for every rx queue */ ++ numvecs = adapter->num_rx_queues; ++ ++ /* if tx handler is seperate add 1 for every tx queue */ ++ if (!(adapter->flags & IGB_FLAG_QUEUE_PAIRS)) ++ numvecs += adapter->num_tx_queues; ++ ++ /* store the number of vectors reserved for queues */ ++ adapter->num_q_vectors = numvecs; ++ ++ /* add 1 vector for link status interrupts */ ++ numvecs++; + adapter->msix_entries = kcalloc(numvecs, + sizeof(struct msix_entry), + GFP_KERNEL); + if (adapter->msix_entries) { -+ for (i=0; i < numvecs; i++) ++ for (i = 0; i < numvecs; i++) + adapter->msix_entries[i].entry = i; + + err = pci_enable_msix(adapter->pdev, @@ -18281,8 +15787,14 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + "interrupts. Falling back to legacy interrupts.\n"); + /* Fall through */ + case IGB_INT_MODE_LEGACY: ++ /* disable advanced features and set number of queues to 1 */ ++ adapter->vfs_allocated_count = 0; ++ adapter->VMDQ_queues = 0; ++ adapter->RSS_queues = 1; ++ adapter->flags |= IGB_FLAG_QUEUE_PAIRS; + adapter->num_rx_queues = 1; + adapter->num_tx_queues = 1; ++ adapter->num_q_vectors = 1; + /* Don't do anything; this is system default */ + break; + } @@ -18290,16 +15802,142 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +#ifdef HAVE_TX_MQ + /* Notify the stack of the (possibly) reduced Tx Queue count. */ +#ifdef CONFIG_NETDEVICES_MULTIQUEUE -+ adapter->netdev->egress_subqueue_count = adapter->num_tx_queues; ++ adapter->netdev->egress_subqueue_count = ++ min_t(u32, adapter->num_tx_queues, adapter->RSS_queues); +#else -+ adapter->netdev->real_num_tx_queues = adapter->num_tx_queues; -+#endif ++ adapter->netdev->real_num_tx_queues = ++ min_t(u32, adapter->num_tx_queues, adapter->RSS_queues); ++#endif +#endif + + return; +} + +/** ++ * igb_alloc_q_vectors - Allocate memory for interrupt vectors ++ * @adapter: board private structure to initialize ++ * ++ * We allocate one q_vector per queue interrupt. If allocation fails we ++ * return -ENOMEM. ++ **/ ++static int igb_alloc_q_vectors(struct igb_adapter *adapter) ++{ ++ struct igb_q_vector *q_vector; ++ struct e1000_hw *hw = &adapter->hw; ++ int v_idx; ++ ++ for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) { ++ q_vector = kzalloc(sizeof(struct igb_q_vector), GFP_KERNEL); ++ if (!q_vector) ++ goto err_out; ++ q_vector->adapter = adapter; ++ q_vector->itr_val = adapter->itr; ++ q_vector->itr_shift = (hw->mac.type == e1000_82575) ? 16 : 0; ++ q_vector->itr_register = hw->hw_addr + E1000_EITR(0); ++ q_vector->set_itr = 1; ++ netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll, 64); ++ adapter->q_vector[v_idx] = q_vector; ++ } ++ return 0; ++ ++err_out: ++ while (v_idx) { ++ v_idx--; ++ q_vector = adapter->q_vector[v_idx]; ++ netif_napi_del(&q_vector->napi); ++ kfree(q_vector); ++ adapter->q_vector[v_idx] = NULL; ++ } ++ return -ENOMEM; ++} ++ ++/** ++ * igb_map_ring_to_vector - maps allocated queues to vectors ++ * ++ * This function maps the recently allocated queues to vectors. ++ **/ ++static int igb_map_ring_to_vector(struct igb_adapter *adapter) ++{ ++ struct igb_q_vector *q_vector; ++ int i; ++ int v_idx = 0; ++ ++ if ((adapter->num_q_vectors < adapter->num_rx_queues) || ++ (adapter->num_q_vectors < adapter->num_tx_queues)) ++ return -ENOMEM; ++ ++ if (adapter->num_q_vectors == (adapter->num_rx_queues + adapter->num_tx_queues)) { ++ for (i = 0; i < adapter->num_tx_queues; i++) { ++ q_vector = adapter->q_vector[v_idx++]; ++ adapter->tx_ring[i].q_vector = q_vector; ++ q_vector->tx_ring = &adapter->tx_ring[i]; ++ } ++ for (i = 0; i < adapter->num_rx_queues; i++) { ++ q_vector = adapter->q_vector[v_idx++]; ++ adapter->rx_ring[i].q_vector = q_vector; ++ q_vector->rx_ring = &adapter->rx_ring[i]; ++ q_vector->rx_ring->q_vector = q_vector; ++ } ++ } else { ++ for (i = 0; i < adapter->num_rx_queues; i++) { ++ q_vector = adapter->q_vector[v_idx++]; ++ adapter->rx_ring[i].q_vector = q_vector; ++ q_vector->rx_ring = &adapter->rx_ring[i]; ++ if (i < adapter->num_tx_queues) { ++ adapter->tx_ring[i].q_vector = q_vector; ++ q_vector->tx_ring = &adapter->tx_ring[i]; ++ } ++ } ++ for (; i < adapter->num_tx_queues; i++) { ++ q_vector = adapter->q_vector[v_idx++]; ++ adapter->tx_ring[i].q_vector = q_vector; ++ q_vector->tx_ring = &adapter->tx_ring[i]; ++ } ++ } ++ return 0; ++} ++ ++/** ++ * igb_init_interrupt_scheme - initialize interrupts, allocate queues/vectors ++ * ++ * This function initializes the interrupts and allocates all of the queues. ++ **/ ++static int igb_init_interrupt_scheme(struct igb_adapter *adapter) ++{ ++ int err; ++ ++ igb_set_interrupt_capability(adapter); ++ ++ err = igb_alloc_q_vectors(adapter); ++ if (err) { ++ DPRINTK(PROBE, ERR, "Unable to allocate memory for q_vectors\n"); ++ goto err_alloc_q_vectors; ++ } ++ ++ err = igb_alloc_queues(adapter); ++ if (err) { ++ DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n"); ++ goto err_alloc_queues; ++ } ++ ++ err = igb_map_ring_to_vector(adapter); ++ if (err) { ++ DPRINTK(PROBE, ERR, "Invalid q_vector to ring mapping\n"); ++ goto err_map_queues; ++ } ++ ++ ++ return 0; ++err_map_queues: ++ igb_free_queues(adapter); ++err_alloc_queues: ++ igb_free_q_vectors(adapter); ++err_alloc_q_vectors: ++ igb_reset_interrupt_capability(adapter); ++ return err; ++} ++ ++/** + * igb_request_irq - initialize interrupts + * + * Attempts to configure interrupts using the best available @@ -18316,18 +15954,33 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + if (!err) + goto request_done; + /* fall back to MSI */ -+ igb_reset_interrupt_capability(adapter); ++ igb_clear_interrupt_scheme(adapter); + if (!pci_enable_msi(adapter->pdev)) + adapter->flags |= IGB_FLAG_HAS_MSI; + igb_free_all_tx_resources(adapter); + igb_free_all_rx_resources(adapter); ++ adapter->num_tx_queues = 1; + adapter->num_rx_queues = 1; -+ igb_alloc_queues(adapter); ++ adapter->num_q_vectors = 1; ++ err = igb_alloc_q_vectors(adapter); ++ if (err) { ++ DPRINTK(PROBE, ERR, "Unable to allocate memory for q_vectors\n"); ++ goto request_done; ++ } ++ err = igb_alloc_queues(adapter); ++ if (err) { ++ DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n"); ++ igb_free_q_vectors(adapter); ++ goto request_done; ++ } ++ igb_setup_all_tx_resources(adapter); ++ igb_setup_all_rx_resources(adapter); + } else { + switch (hw->mac.type) { + case e1000_82575: + E1000_WRITE_REG(hw, E1000_MSIXBM(0), + (E1000_EICR_RX_QUEUE0 | ++ E1000_EICR_TX_QUEUE0 | + E1000_EIMS_OTHER)); + break; + case e1000_82576: @@ -18339,7 +15992,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + } + if (adapter->flags & IGB_FLAG_HAS_MSI) { + err = request_irq(adapter->pdev->irq, &igb_intr_msi, 0, -+ netdev->name, netdev); ++ netdev->name, adapter); + if (!err) + goto request_done; + @@ -18349,7 +16002,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + } + + err = request_irq(adapter->pdev->irq, &igb_intr, IRQF_SHARED, -+ netdev->name, netdev); ++ netdev->name, adapter); + + if (err) { + DPRINTK(PROBE, ERR, "Error %d getting interrupt\n", err); @@ -18362,40 +16015,42 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + +static void igb_free_irq(struct igb_adapter *adapter) +{ -+ struct net_device *netdev = adapter->netdev; -+ + if (adapter->msix_entries) { + int vector = 0, i; + -+#ifdef CONFIG_IGB_SEPARATE_TX_HANDLER -+ for (i = 0; i < adapter->num_tx_queues; i++) -+ free_irq(adapter->msix_entries[vector++].vector, -+ &(adapter->tx_ring[i])); -+#endif -+ for (i = 0; i < adapter->num_rx_queues; i++) -+ free_irq(adapter->msix_entries[vector++].vector, -+ &(adapter->rx_ring[i])); ++ free_irq(adapter->msix_entries[vector++].vector, adapter); + -+ free_irq(adapter->msix_entries[vector++].vector, netdev); -+ return; ++ for (i = 0; i < adapter->num_q_vectors; i++) { ++ struct igb_q_vector *q_vector = adapter->q_vector[i]; ++ free_irq(adapter->msix_entries[vector++].vector, ++ q_vector); ++ } ++ } else { ++ free_irq(adapter->pdev->irq, adapter); + } -+ -+ free_irq(adapter->pdev->irq, netdev); +} + +/** + * igb_irq_disable - Mask off interrupt generation on the NIC + * @adapter: board private structure + **/ -+ +static void igb_irq_disable(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + ++ /* ++ * we need to be careful when disabling interrupts. The VFs are also ++ * mapped into these registers and so clearing the bits can cause ++ * issues on the VF drivers so we only need to clear what we set ++ */ + if (adapter->msix_entries) { -+ E1000_WRITE_REG(hw, E1000_EIAM, 0); -+ E1000_WRITE_REG(hw, E1000_EIMC, ~0); -+ E1000_WRITE_REG(hw, E1000_EIAC, 0); ++ u32 regval = E1000_READ_REG(hw, E1000_EIAM); ++ regval &= ~adapter->eims_enable_mask; ++ E1000_WRITE_REG(hw, E1000_EIAM, regval); ++ E1000_WRITE_REG(hw, E1000_EIMC, adapter->eims_enable_mask); ++ regval = E1000_READ_REG(hw, E1000_EIAC); ++ regval &= ~adapter->eims_enable_mask; ++ E1000_WRITE_REG(hw, E1000_EIAC, regval); + } + + E1000_WRITE_REG(hw, E1000_IAM, 0); @@ -18409,16 +16064,24 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * igb_irq_enable - Enable default interrupt generation settings + * @adapter: board private structure + **/ -+ +static void igb_irq_enable(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + + if (adapter->msix_entries) { -+ E1000_WRITE_REG(hw, E1000_EIAC, adapter->eims_enable_mask); -+ E1000_WRITE_REG(hw, E1000_EIAM, adapter->eims_enable_mask); ++ u32 ims = E1000_IMS_LSC | E1000_IMS_DOUTSYNC; ++ u32 regval = E1000_READ_REG(hw, E1000_EIAC); ++ E1000_WRITE_REG(hw, E1000_EIAC, ++ regval | adapter->eims_enable_mask); ++ regval = E1000_READ_REG(hw, E1000_EIAM); ++ E1000_WRITE_REG(hw, E1000_EIAM, ++ regval | adapter->eims_enable_mask); + E1000_WRITE_REG(hw, E1000_EIMS, adapter->eims_enable_mask); -+ E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_LSC); ++ if (adapter->vfs_allocated_count) { ++ E1000_WRITE_REG(hw, E1000_MBVFIMR, 0xFF); ++ ims |= E1000_IMS_VMMB; ++ } ++ E1000_WRITE_REG(hw, E1000_IMS, ims); + } else { + E1000_WRITE_REG(hw, E1000_IMS, IMS_ENABLE_MASK); + E1000_WRITE_REG(hw, E1000_IAM, IMS_ENABLE_MASK); @@ -18427,24 +16090,23 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + +static void igb_update_mng_vlan(struct igb_adapter *adapter) +{ -+ struct net_device *netdev = adapter->netdev; ++ struct e1000_hw *hw = &adapter->hw; + u16 vid = adapter->hw.mng_cookie.vlan_id; + u16 old_vid = adapter->mng_vlan_id; -+ if (adapter->vlgrp) { -+ if (!vlan_group_get_device(adapter->vlgrp, vid)) { -+ if (adapter->hw.mng_cookie.status & -+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN) { -+ igb_vlan_rx_add_vid(netdev, vid); -+ adapter->mng_vlan_id = vid; -+ } else -+ adapter->mng_vlan_id = IGB_MNG_VLAN_NONE; -+ -+ if ((old_vid != (u16)IGB_MNG_VLAN_NONE) && -+ (vid != old_vid) && -+ !vlan_group_get_device(adapter->vlgrp, old_vid)) -+ igb_vlan_rx_kill_vid(netdev, old_vid); -+ } else -+ adapter->mng_vlan_id = vid; ++ ++ if (hw->mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) { ++ /* add VID to filter table */ ++ igb_vfta_set(hw, vid, TRUE); ++ adapter->mng_vlan_id = vid; ++ } else { ++ adapter->mng_vlan_id = IGB_MNG_VLAN_NONE; ++ } ++ ++ if ((old_vid != (u16)IGB_MNG_VLAN_NONE) && ++ (vid != old_vid) && ++ !vlan_group_get_device(adapter->vlgrp, old_vid)) { ++ /* remove VID from filter table */ ++ igb_vfta_set(hw, old_vid, FALSE); + } +} + @@ -18457,7 +16119,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * driver is no longer loaded. + * + **/ -+ +static void igb_release_hw_control(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; @@ -18469,7 +16130,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); +} + -+ +/** + * igb_get_hw_control - get control of the h/w from f/w + * @adapter: address of board private structure @@ -18479,7 +16139,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * the driver is loaded. + * + **/ -+ +static void igb_get_hw_control(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; @@ -18501,12 +16160,15 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + int i; + + igb_get_hw_control(adapter); -+ igb_set_multi(netdev); ++ igb_set_rx_mode(netdev); + + igb_restore_vlan(adapter); + -+ igb_configure_tx(adapter); ++ igb_setup_tctl(adapter); ++ igb_setup_mrqc(adapter); + igb_setup_rctl(adapter); ++ ++ igb_configure_tx(adapter); + igb_configure_rx(adapter); + + e1000_rx_fifo_flush_82575(&adapter->hw); @@ -18522,9 +16184,11 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * next_to_use != next_to_clean */ + for (i = 0; i < adapter->num_rx_queues; i++) { + struct igb_ring *ring = &adapter->rx_ring[i]; -+ igb_alloc_rx_buffers_adv(ring, IGB_DESC_UNUSED(ring)); ++ if (igb_alloc_rx_buffers_adv(ring, IGB_DESC_UNUSED(ring))) ++ adapter->alloc_rx_buff_failed++; + } + ++ + adapter->tx_queue_len = netdev->tx_queue_len; +} + @@ -18533,7 +16197,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * igb_up - Open the interface and prepare it to handle traffic + * @adapter: board private structure + **/ -+ +int igb_up(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; @@ -18544,8 +16207,10 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + clear_bit(__IGB_DOWN, &adapter->state); + -+ for (i = 0; i < adapter->num_rx_queues; i++) -+ napi_enable(&adapter->rx_ring[i].napi); ++ for (i = 0; i < adapter->num_q_vectors; i++) { ++ struct igb_q_vector *q_vector = adapter->q_vector[i]; ++ napi_enable(&q_vector->napi); ++ } + if (adapter->msix_entries) + igb_configure_msix(adapter); + @@ -18555,8 +16220,17 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + E1000_READ_REG(hw, E1000_ICR); + igb_irq_enable(adapter); + -+ /* Fire a link change interrupt to start the watchdog. */ -+ E1000_WRITE_REG(hw, E1000_ICS, E1000_ICS_LSC); ++ /* notify VFs that reset has been completed */ ++ if (adapter->vfs_allocated_count) { ++ u32 reg_data = E1000_READ_REG(hw, E1000_CTRL_EXT); ++ reg_data |= E1000_CTRL_EXT_PFRSTD; ++ E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg_data); ++ } ++ ++ /* start the watchdog. */ ++ hw->mac.get_link_status = 1; ++ mod_timer(&adapter->watchdog_timer, jiffies + 1); ++ + return 0; +} + @@ -18586,8 +16260,10 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + E1000_WRITE_FLUSH(hw); + msleep(10); + -+ for (i = 0; i < adapter->num_rx_queues; i++) -+ napi_disable(&adapter->rx_ring[i].napi); ++ for (i = 0; i < adapter->num_q_vectors; i++) { ++ struct igb_q_vector *q_vector = adapter->q_vector[i]; ++ napi_disable(&q_vector->napi); ++ } + + igb_irq_disable(adapter); + @@ -18602,7 +16278,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + adapter->link_speed = 0; + adapter->link_duplex = 0; -+ +#ifdef HAVE_PCI_ERS + if (!pci_channel_offline(adapter->pdev)) + igb_reset(adapter); @@ -18611,6 +16286,11 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +#endif + igb_clean_all_tx_rings(adapter); + igb_clean_all_rx_rings(adapter); ++#ifdef IGB_DCA ++ ++ /* since we reset the hardware DCA settings were cleared */ ++ igb_setup_dca(adapter); ++#endif +} + +void igb_reinit_locked(struct igb_adapter *adapter) @@ -18618,7 +16298,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + WARN_ON(in_interrupt()); + while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) + msleep(1); -+ + igb_down(adapter); + igb_up(adapter); + clear_bit(__IGB_RESETTING, &adapter->state); @@ -18635,11 +16314,15 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + /* Repartition Pba for greater than 9k mtu + * To take effect CTRL.RST is required. + */ -+ if (mac->type != e1000_82576) { -+ pba = E1000_PBA_34K; -+ } -+ else { -+ pba = E1000_PBA_64K; ++ switch (mac->type) { ++ case e1000_82576: ++ pba = E1000_READ_REG(hw, E1000_RXPBS); ++ pba &= E1000_RXPBS_SIZE_MASK_82576; ++ break; ++ case e1000_82575: ++ default: ++ pba = E1000_PBA_34K; ++ break; + } + + if ((adapter->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) && @@ -18703,7 +16386,21 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + } + fc->pause_time = 0xFFFF; + fc->send_xon = 1; -+ fc->type = fc->original_type; ++ fc->current_mode = fc->requested_mode; ++ ++ /* disable receive for all VFs and wait one second */ ++ if (adapter->vfs_allocated_count) { ++ int i; ++ for (i = 0 ; i < adapter->vfs_allocated_count; i++) ++ adapter->vf_data[i].flags = 0; ++ ++ /* ping all the active vfs to let them know we are going down */ ++ igb_ping_all_vfs(adapter); ++ ++ /* disable transmits and receives */ ++ E1000_WRITE_REG(hw, E1000_VFRE, 0); ++ E1000_WRITE_REG(hw, E1000_VFTE, 0); ++ } + + /* Allow time for pending master requests to run */ + e1000_reset_hw(hw); @@ -18711,6 +16408,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + if (e1000_init_hw(hw)) + DPRINTK(PROBE, ERR, "Hardware Error\n"); ++ + igb_update_mng_vlan(adapter); + + /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ @@ -18719,6 +16417,28 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + e1000_get_phy_info(hw); +} + ++#ifdef HAVE_NET_DEVICE_OPS ++static const struct net_device_ops igb_netdev_ops = { ++ .ndo_open = igb_open, ++ .ndo_stop = igb_close, ++ .ndo_start_xmit = igb_xmit_frame_adv, ++ .ndo_get_stats = igb_get_stats, ++ .ndo_set_rx_mode = igb_set_rx_mode, ++ .ndo_set_multicast_list = igb_set_rx_mode, ++ .ndo_set_mac_address = igb_set_mac, ++ .ndo_change_mtu = igb_change_mtu, ++ .ndo_do_ioctl = igb_ioctl, ++ .ndo_tx_timeout = igb_tx_timeout, ++ .ndo_validate_addr = eth_validate_addr, ++ .ndo_vlan_rx_register = igb_vlan_rx_register, ++ .ndo_vlan_rx_add_vid = igb_vlan_rx_add_vid, ++ .ndo_vlan_rx_kill_vid = igb_vlan_rx_kill_vid, ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ .ndo_poll_controller = igb_netpoll, ++#endif ++}; ++#endif /* HAVE_NET_DEVICE_OPS */ ++ +/** + * igb_probe - Device Initialization Routine + * @pdev: PCI device information struct @@ -18730,33 +16450,31 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * The OS initialization, configuring of the adapter private structure, + * and a hardware reset occur. + **/ -+ +static int __devinit igb_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct net_device *netdev; + struct igb_adapter *adapter; + struct e1000_hw *hw; -+ struct pci_dev *us_dev; ++ int i, err, pci_using_dac; ++ u16 eeprom_data = 0; ++ static int cards_found; ++ static int global_quad_port_a; /* global quad port a indication */ + -+ static int cards_found = 0; -+ int i, err, pci_using_dac, pos; -+ u16 eeprom_data = 0, state = 0; -+ u16 eeprom_apme_mask = IGB_EEPROM_APME; -+ err = pci_enable_device(pdev); ++ err = pci_enable_device_mem(pdev); + if (err) + return err; + + pci_using_dac = 0; -+ err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); ++ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); + if (!err) { -+ err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); ++ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + if (!err) + pci_using_dac = 1; + } else { -+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); ++ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (err) { -+ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); ++ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + if (err) { + IGB_ERR("No usable DMA configuration, " + "aborting\n"); @@ -18765,25 +16483,18 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + } + } + ++#ifndef HAVE_ASPM_QUIRKS + /* 82575 requires that the pci-e link partner disable the L0s state */ + switch (pdev->device) { + case E1000_DEV_ID_82575EB_COPPER: + case E1000_DEV_ID_82575EB_FIBER_SERDES: + case E1000_DEV_ID_82575GB_QUAD_COPPER: -+ us_dev = pdev->bus->self; -+ pos = pci_find_capability(us_dev, PCI_CAP_ID_EXP); -+ if (pos) { -+ pci_read_config_word(us_dev, pos + PCI_EXP_LNKCTL, &state); -+ state &= ~PCIE_LINK_STATE_L0S; -+ pci_write_config_word(us_dev, pos + PCI_EXP_LNKCTL, state); -+ printk(KERN_INFO "Disabling ASPM L0s upstream switch " -+ "port %x:%x.%x\n", us_dev->bus->number, -+ PCI_SLOT(us_dev->devfn), PCI_FUNC(us_dev->devfn)); -+ } ++ pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); + default: + break; + } + ++#endif /* HAVE_ASPM_QUIRKS */ + err = pci_request_selected_regions(pdev, + pci_select_bars(pdev, + IORESOURCE_MEM), @@ -18791,6 +16502,8 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + if (err) + goto err_pci_reg; + ++ pci_enable_pcie_error_reporting(pdev); ++ + pci_set_master(pdev); + + err = -ENOMEM; @@ -18824,17 +16537,21 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + if (!hw->hw_addr) + goto err_ioremap; + ++#ifdef HAVE_NET_DEVICE_OPS ++ netdev->netdev_ops = &igb_netdev_ops; ++#else /* HAVE_NET_DEVICE_OPS */ + netdev->open = &igb_open; + netdev->stop = &igb_close; + netdev->get_stats = &igb_get_stats; -+ netdev->set_multicast_list = &igb_set_multi; ++#ifdef HAVE_SET_RX_MODE ++ netdev->set_rx_mode = &igb_set_rx_mode; ++#endif ++ netdev->set_multicast_list = &igb_set_rx_mode; + netdev->set_mac_address = &igb_set_mac; + netdev->change_mtu = &igb_change_mtu; + netdev->do_ioctl = &igb_ioctl; -+ igb_set_ethtool_ops(netdev); +#ifdef HAVE_TX_TIMEOUT + netdev->tx_timeout = &igb_tx_timeout; -+ netdev->watchdog_timeo = 5 * HZ; +#endif + netdev->vlan_rx_register = igb_vlan_rx_register; + netdev->vlan_rx_add_vid = igb_vlan_rx_add_vid; @@ -18843,13 +16560,16 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + netdev->poll_controller = igb_netpoll; +#endif + netdev->hard_start_xmit = &igb_xmit_frame_adv; ++#endif /* HAVE_NET_DEVICE_OPS */ ++ igb_set_ethtool_ops(netdev); ++#ifdef HAVE_TX_TIMEOUT ++ netdev->watchdog_timeo = 5 * HZ; ++#endif + + strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); + + adapter->bd_number = cards_found; + -+ igb_check_options(adapter); -+ + /* setup the private structure */ + err = igb_sw_init(adapter); + if (err) @@ -18857,18 +16577,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + e1000_get_bus_info(hw); + -+ /* Set flags */ -+ switch (hw->mac.type) { -+ case e1000_82576: -+ /* Fall through */ -+ case e1000_82575: -+ adapter->flags |= IGB_FLAG_HAS_DCA; -+ adapter->flags |= IGB_FLAG_NEED_CTX_IDX; -+ break; -+ default: -+ break; -+ } -+ + hw->phy.autoneg_wait_to_complete = FALSE; + hw->mac.adaptive_ifs = FALSE; + @@ -18892,10 +16600,8 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +#ifdef NETIF_F_IPV6_CSUM + netdev->features |= NETIF_F_IPV6_CSUM; +#endif -+ +#ifdef NETIF_F_TSO + netdev->features |= NETIF_F_TSO; -+ +#ifdef NETIF_F_TSO6 + netdev->features |= NETIF_F_TSO6; +#endif @@ -18903,11 +16609,25 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + +#ifdef IGB_LRO + netdev->features |= NETIF_F_LRO; -+#endif /* IGB_LRO */ ++#endif ++#ifdef NETIF_F_GRO ++ netdev->features |= NETIF_F_GRO; ++#endif ++ ++#ifdef HAVE_NETDEV_VLAN_FEATURES ++ netdev->vlan_features |= NETIF_F_TSO; ++ netdev->vlan_features |= NETIF_F_TSO6; ++ netdev->vlan_features |= NETIF_F_IP_CSUM; ++ netdev->vlan_features |= NETIF_F_IPV6_CSUM; ++ netdev->vlan_features |= NETIF_F_SG; + ++#endif + if (pci_using_dac) + netdev->features |= NETIF_F_HIGHDMA; + ++ if (hw->mac.type >= e1000_82576) ++ netdev->features |= NETIF_F_SCTP_CSUM; ++ + adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw); + + /* before reading the NVM, reset the controller to put the device in a @@ -18953,23 +16673,21 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + hw->mac.autoneg = true; + hw->phy.autoneg_advertised = 0x2f; + -+ hw->fc.original_type = e1000_fc_default; -+ hw->fc.type = e1000_fc_default; ++ hw->fc.requested_mode = e1000_fc_default; ++ hw->fc.current_mode = e1000_fc_default; + + e1000_validate_mdi_setting(hw); + -+ adapter->rx_csum = 1; -+ + /* Initial Wake on LAN setting If APM wake is enabled in the EEPROM, + * enable the ACPI Magic Packet filter + */ + + if (hw->bus.func == 0) + e1000_read_nvm(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); -+ else if(hw->bus.func == 1) ++ else if (hw->bus.func == 1) + e1000_read_nvm(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); + -+ if (eeprom_data & eeprom_apme_mask) ++ if (eeprom_data & IGB_EEPROM_APME) + adapter->eeprom_wol |= E1000_WUFC_MAG; + + /* now that we have the eeprom settings, apply the special cases where @@ -18984,14 +16702,24 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + case E1000_DEV_ID_82576_SERDES: + /* Wake events only supported on port A for dual fiber + * regardless of eeprom setting */ -+ if (E1000_READ_REG(hw, E1000_STATUS) & -+ E1000_STATUS_FUNC_1) ++ if (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_FUNC_1) ++ adapter->eeprom_wol = 0; ++ break; ++ case E1000_DEV_ID_82576_QUAD_COPPER: ++ /* if quad port adapter, disable WoL on all but port A */ ++ if (global_quad_port_a != 0) + adapter->eeprom_wol = 0; ++ else ++ adapter->flags |= IGB_FLAG_QUAD_PORT_A; ++ /* Reset for multiple quad port adapters */ ++ if (++global_quad_port_a == 4) ++ global_quad_port_a = 0; + break; + } + + /* initialize the wol settings based on the eeprom settings */ + adapter->wol = adapter->eeprom_wol; ++ device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); + + /* reset the hardware with the new settings */ + igb_reset(adapter); @@ -19004,35 +16732,86 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + netif_carrier_off(netdev); + netif_tx_stop_all_queues(netdev); + -+ strcpy(netdev->name, "eth%d"); ++ strncpy(netdev->name, "eth%d", IFNAMSIZ); + err = register_netdev(netdev); + if (err) + goto err_register; + +#ifdef IGB_DCA -+ if (adapter->flags & IGB_FLAG_HAS_DCA) { -+ if (dca_add_requester(&pdev->dev) == E1000_SUCCESS) { -+ adapter->flags |= IGB_FLAG_DCA_ENABLED; -+ DPRINTK(PROBE, INFO, "DCA enabled\n"); -+ /* Always use CB2 mode, difference is masked -+ * in the CB driver. */ -+ E1000_WRITE_REG(hw, E1000_DCA_CTRL, 2); -+ igb_setup_dca(adapter); -+ } ++ if (dca_add_requester(&pdev->dev) == E1000_SUCCESS) { ++ adapter->flags |= IGB_FLAG_DCA_ENABLED; ++ DPRINTK(PROBE, INFO, "DCA enabled\n"); ++ igb_setup_dca(adapter); + } ++ +#endif ++#ifdef SIOCSHWTSTAMP ++ switch (hw->mac.type) { ++ case e1000_82576: ++ /* ++ * Initialize hardware timer: we keep it running just in case ++ * that some program needs it later on. ++ */ ++ memset(&adapter->cycles, 0, sizeof(adapter->cycles)); ++ adapter->cycles.read = igb_read_clock; ++ adapter->cycles.mask = CLOCKSOURCE_MASK(64); ++ adapter->cycles.mult = 1; ++ /** ++ * Scale the NIC clock cycle by a large factor so that ++ * relatively small clock corrections can be added or ++ * substracted at each clock tick. The drawbacks of a large ++ * factor are a) that the clock register overflows more quickly ++ * (not such a big deal) and b) that the increment per tick has ++ * to fit into 24 bits. As a result we need to use a shift of ++ * 19 so we can fit a value of 16 into the TIMINCA register. ++ */ ++ adapter->cycles.shift = IGB_82576_TSYNC_SHIFT; ++ E1000_WRITE_REG(hw, E1000_TIMINCA, ++ (1 << E1000_TIMINCA_16NS_SHIFT) | ++ (16 << IGB_82576_TSYNC_SHIFT)); ++ ++ /* Set registers so that rollover occurs soon to test this. */ ++ E1000_WRITE_REG(hw, E1000_SYSTIML, 0x00000000); ++ E1000_WRITE_REG(hw, E1000_SYSTIMH, 0xFF800000); ++ E1000_WRITE_FLUSH(hw); ++ ++ timecounter_init(&adapter->clock, ++ &adapter->cycles, ++ ktime_to_ns(ktime_get_real())); ++ /* ++ * Synchronize our NIC clock against system wall clock. NIC ++ * time stamp reading requires ~3us per sample, each sample ++ * was pretty stable even under load => only require 10 ++ * samples for each offset comparison. ++ */ ++ memset(&adapter->compare, 0, sizeof(adapter->compare)); ++ adapter->compare.source = &adapter->clock; ++ adapter->compare.target = ktime_get_real; ++ adapter->compare.num_samples = 10; ++ timecompare_update(&adapter->compare, 0); ++ break; ++ case e1000_82575: ++ /* 82575 does not support timesync */ ++ default: ++ break; ++ } + ++#endif /* SIOCSHWTSTAMP */ + DPRINTK(PROBE, INFO, "Intel(R) Gigabit Ethernet Network Connection\n"); + /* print bus type/speed/width info */ + DPRINTK(PROBE, INFO, "(PCIe:%s:%s) ", + ((hw->bus.speed == e1000_bus_speed_2500) ? "2.5Gb/s" : "unknown"), + ((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" : ++ (hw->bus.width == e1000_bus_width_pcie_x2) ? "Width x2" : + (hw->bus.width == e1000_bus_width_pcie_x1) ? "Width x1" : + "unknown")); + + for (i = 0; i < 6; i++) + printk("%2.2x%c", netdev->dev_addr[i], i == 5 ? '\n' : ':'); + ++ for (i = 0; i < adapter->vfs_allocated_count; i++) ++ igb_vf_configuration(pdev, (i | 0x10000000)); ++ + DPRINTK(PROBE, INFO, + "Using %s interrupts. %d rx queue(s), %d tx queue(s)\n", + adapter->msix_entries ? "MSI-X" : @@ -19051,9 +16830,8 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + if (hw->flash_address) + iounmap(hw->flash_address); -+ -+ igb_free_queues(adapter); +err_sw_init: ++ igb_clear_interrupt_scheme(adapter); + iounmap(hw->hw_addr); +err_ioremap: + free_netdev(netdev); @@ -19075,7 +16853,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * Hot-Plug event, or because the driver is going to be removed from + * memory. + **/ -+ +static void __devexit igb_remove(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); @@ -19090,6 +16867,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + flush_scheduled_work(); + ++ +#ifdef IGB_DCA + if (adapter->flags & IGB_FLAG_DCA_ENABLED) { + DPRINTK(PROBE, INFO, "DCA disabled\n"); @@ -19108,9 +16886,22 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + if (!e1000_check_reset_block(hw)) + e1000_phy_hw_reset(hw); + -+ igb_reset_interrupt_capability(adapter); ++ igb_clear_interrupt_scheme(adapter); + -+ igb_free_queues(adapter); ++#ifdef CONFIG_PCI_IOV ++ if (adapter->vf_data) { ++ /* disable iov and allow time for transactions to clear */ ++ pci_disable_sriov(pdev); ++ msleep(500); ++ ++ kfree(adapter->vf_data); ++ adapter->vf_data = NULL; ++ E1000_WRITE_REG(&adapter->hw, E1000_IOVCTL, ++ E1000_IOVCTL_REUSE_VFQ); ++ msleep(100); ++ dev_info(&adapter->pdev->dev, "IOV Disabled\n"); ++ } ++#endif + + iounmap(hw->hw_addr); + if (hw->flash_address) @@ -19120,10 +16911,51 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + free_netdev(netdev); + ++ pci_disable_pcie_error_reporting(pdev); ++ + pci_disable_device(pdev); +} + +/** ++ * igb_probe_vfs - Initialize vf data storage and add VFs to pci config space ++ * @adapter: board private structure to initialize ++ * ++ * This function initializes the vf specific data storage and then attempts to ++ * allocate the VFs. The reason for ordering it this way is because it is much ++ * more expensive time wise to disable SR-IOV than it is to allocate and free ++ * the memory for the VFs. ++ **/ ++static void __devinit igb_probe_vfs(struct igb_adapter *adapter) ++{ ++#ifdef CONFIG_PCI_IOV ++ struct pci_dev *pdev = adapter->pdev; ++ ++ if (adapter->vfs_allocated_count) { ++ adapter->vf_data = kcalloc(adapter->vfs_allocated_count, ++ sizeof(struct vf_data_storage), ++ GFP_KERNEL); ++ /* if allocation failed then we do not support SR-IOV */ ++ if (!adapter->vf_data) { ++ adapter->vfs_allocated_count = 0; ++ dev_err(&pdev->dev, "Unable to allocate memory for VF " ++ "Data Storage\n"); ++ } ++ } ++ ++ if (pci_enable_sriov(pdev, adapter->vfs_allocated_count)) { ++ kfree(adapter->vf_data); ++ adapter->vf_data = NULL; ++#endif /* CONFIG_PCI_IOV */ ++ adapter->vfs_allocated_count = 0; ++#ifdef CONFIG_PCI_IOV ++ } else { ++ dev_info(&pdev->dev, "IOV1 VFs enabled := %d\n", ++ adapter->vfs_allocated_count); ++ } ++ ++#endif /* CONFIG_PCI_IOV */ ++} ++/** + * igb_sw_init - Initialize general software structures (struct igb_adapter) + * @adapter: board private structure to initialize + * @@ -19131,7 +16963,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * Fields are initialized based on PCI device information and + * OS network device settings (MTU size). + **/ -+ +static int __devinit igb_sw_init(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; @@ -19151,8 +16982,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + adapter->tx_ring_count = IGB_DEFAULT_TXD; + adapter->rx_ring_count = IGB_DEFAULT_RXD; -+ adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE; -+ adapter->rx_ps_hdr_size = 0; /* disable packet split */ + adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; + adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; + @@ -19162,25 +16991,15 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + return -EIO; + } + -+ /* Number of supported queues. */ -+ /* Having more queues than CPUs doesn't make sense. */ -+ adapter->num_rx_queues = min((u32)IGB_MAX_RX_QUEUES, (u32)num_online_cpus()); -+#ifdef HAVE_TX_MQ -+ adapter->num_tx_queues = min(IGB_MAX_TX_QUEUES, num_online_cpus()); -+#else -+ adapter->num_tx_queues = 1; -+#endif -+ -+ -+ /* This call may decrease the number of queues depending on -+ * interrupt mode. */ -+ igb_set_interrupt_capability(adapter); ++ igb_check_options(adapter); + -+ if (igb_alloc_queues(adapter)) { ++ if (igb_init_interrupt_scheme(adapter)) { + DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n"); + return -ENOMEM; + } + ++ igb_probe_vfs(adapter); ++ + /* Explicitly disable IRQ since the NIC can be in any state. */ + igb_irq_disable(adapter); + @@ -19188,7 +17007,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + return 0; +} + -+ +/** + * igb_open - Called when a network interface is made active + * @netdev: network interface device structure @@ -19201,7 +17019,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * handler is registered with the OS, the watchdog timer is started, + * and the stack is notified that the interface is ready. + **/ -+ +static int igb_open(struct net_device *netdev) +{ + struct igb_adapter *adapter = netdev_priv(netdev); @@ -19225,12 +17042,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + /* e1000_power_up_phy(adapter); */ + -+ adapter->mng_vlan_id = IGB_MNG_VLAN_NONE; -+ if ((adapter->hw.mng_cookie.status & -+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN)) { -+ igb_update_mng_vlan(adapter); -+ } -+ + /* before we allocate an interrupt, we must be ready to handle it. + * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt + * as soon as we call pci_request_irq, so we have to setup our @@ -19244,8 +17055,10 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + /* From here on the code is the same as igb_up() */ + clear_bit(__IGB_DOWN, &adapter->state); + -+ for (i = 0; i < adapter->num_rx_queues; i++) -+ napi_enable(&adapter->rx_ring[i].napi); ++ for (i = 0; i < adapter->num_q_vectors; i++) { ++ struct igb_q_vector *q_vector = adapter->q_vector[i]; ++ napi_enable(&q_vector->napi); ++ } + igb_configure_lli(adapter); + + /* Clear any pending interrupts. */ @@ -19253,10 +17066,18 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + igb_irq_enable(adapter); + ++ /* notify VFs that reset has been completed */ ++ if (adapter->vfs_allocated_count) { ++ u32 reg_data = E1000_READ_REG(hw, E1000_CTRL_EXT); ++ reg_data |= E1000_CTRL_EXT_PFRSTD; ++ E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg_data); ++ } ++ + netif_tx_start_all_queues(netdev); + -+ /* Fire a link status change interrupt to start the watchdog. */ -+ E1000_WRITE_REG(hw, E1000_ICS, E1000_ICS_LSC); ++ /* start the watchdog. */ ++ hw->mac.get_link_status = 1; ++ mod_timer(&adapter->watchdog_timer, jiffies + 1); + + return E1000_SUCCESS; + @@ -19268,6 +17089,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + igb_free_all_tx_resources(adapter); +err_setup_tx: + igb_reset(adapter); ++ + return err; +} + @@ -19282,7 +17104,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * needs to be disabled. A global MAC reset is issued to stop the + * hardware, and all transmit and receive resources are freed. + **/ -+ +static int igb_close(struct net_device *netdev) +{ + struct igb_adapter *adapter = netdev_priv(netdev); @@ -19295,29 +17116,18 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + igb_free_all_tx_resources(adapter); + igb_free_all_rx_resources(adapter); + -+ /* kill manageability vlan ID if supported, but not if a vlan with -+ * the same ID is registered on the host OS (let 8021q kill it) */ -+ if ((adapter->hw.mng_cookie.status & -+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && -+ !(adapter->vlgrp && -+ vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id))) -+ igb_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); -+ + return 0; +} + +/** + * igb_setup_tx_resources - allocate Tx resources (Descriptors) -+ * @adapter: board private structure + * @tx_ring: tx descriptor ring (for a specific queue) to setup + * + * Return 0 on success, negative on failure + **/ -+ -+int igb_setup_tx_resources(struct igb_adapter *adapter, -+ struct igb_ring *tx_ring) ++int igb_setup_tx_resources(struct igb_ring *tx_ring) +{ -+ struct pci_dev *pdev = adapter->pdev; ++ struct pci_dev *pdev = tx_ring->pdev; + int size; + + size = sizeof(struct igb_buffer) * tx_ring->count; @@ -19327,45 +17137,40 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + memset(tx_ring->buffer_info, 0, size); + + /* round up to nearest 4K */ -+ tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc) -+ + sizeof(u32); ++ tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc); + tx_ring->size = ALIGN(tx_ring->size, 4096); + -+ tx_ring->desc = pci_alloc_consistent(pdev, tx_ring->size, ++ tx_ring->desc = pci_alloc_consistent(pdev, ++ tx_ring->size, + &tx_ring->dma); + + if (!tx_ring->desc) + goto err; + -+ tx_ring->adapter = adapter; + tx_ring->next_to_use = 0; + tx_ring->next_to_clean = 0; + return 0; + +err: + vfree(tx_ring->buffer_info); -+ DPRINTK(PROBE, ERR, "Unable to allocate memory for the transmit " -+ "descriptor ring\n"); ++ dev_err(&pdev->dev, "Unable to allocate memory for the " ++ "transmit descriptor ring\n"); + return -ENOMEM; +} + +/** + * igb_setup_all_tx_resources - wrapper to allocate Tx resources -+ * (Descriptors) for all queues ++ * (Descriptors) for all queues + * @adapter: board private structure + * + * Return 0 on success, negative on failure + **/ -+ +static int igb_setup_all_tx_resources(struct igb_adapter *adapter) +{ + int i, err = 0; -+#ifdef HAVE_TX_MQ -+ int r_idx; -+#endif + + for (i = 0; i < adapter->num_tx_queues; i++) { -+ err = igb_setup_tx_resources(adapter, &adapter->tx_ring[i]); ++ err = igb_setup_tx_resources(&adapter->tx_ring[i]); + if (err) { + DPRINTK(PROBE, ERR, + "Allocation for Tx Queue %u failed\n", i); @@ -19377,7 +17182,11 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + +#ifdef HAVE_TX_MQ + for (i = 0; i < IGB_ABS_MAX_TX_QUEUES; i++) { -+ r_idx = i % adapter->num_tx_queues; ++#ifdef CONFIG_NETDEVICES_MULTIQUEUE ++ int r_idx = i % adapter->netdev->egress_subqueue_count; ++#else ++ int r_idx = i % adapter->netdev->real_num_tx_queues; ++#endif + adapter->multi_tx_table[i] = &adapter->tx_ring[r_idx]; + } +#endif @@ -19385,57 +17194,18 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +} + +/** -+ * igb_configure_tx - Configure transmit Unit after Reset -+ * @adapter: board private structure -+ * -+ * Configure the Tx unit of the MAC after a reset. ++ * igb_setup_tctl - configure the transmit control registers ++ * @adapter: Board private structure + **/ -+ -+static void igb_configure_tx(struct igb_adapter *adapter) ++void igb_setup_tctl(struct igb_adapter *adapter) +{ -+ u64 tdba, tdwba; + struct e1000_hw *hw = &adapter->hw; + u32 tctl; -+ u32 txdctl, txctrl; -+ int i; -+ -+ for (i = 0; i < adapter->num_tx_queues; i++) { -+ struct igb_ring *ring = &(adapter->tx_ring[i]); -+ -+ E1000_WRITE_REG(hw, E1000_TDLEN(i), -+ ring->count * sizeof(struct e1000_tx_desc)); -+ tdba = ring->dma; -+ E1000_WRITE_REG(hw, E1000_TDBAL(i), -+ tdba & 0x00000000ffffffffULL); -+ E1000_WRITE_REG(hw, E1000_TDBAH(i), tdba >> 32); -+ -+ tdwba = ring->dma + ring->count * sizeof(struct e1000_tx_desc); -+ tdwba |= 1; /* enable head wb */ -+ E1000_WRITE_REG(hw, E1000_TDWBAL(i), -+ tdwba & 0x00000000ffffffffULL); -+ E1000_WRITE_REG(hw, E1000_TDWBAH(i), tdwba >> 32); -+ -+ ring->head = E1000_TDH(i); -+ ring->tail = E1000_TDT(i); -+ writel(0, hw->hw_addr + ring->tail); -+ writel(0, hw->hw_addr + ring->head); -+ txdctl = E1000_READ_REG(hw, E1000_TXDCTL(i)); -+ txdctl |= E1000_TXDCTL_QUEUE_ENABLE; -+ E1000_WRITE_REG(hw, E1000_TXDCTL(i), txdctl); -+ -+ /* Turn off Relaxed Ordering on head write-backs. The writebacks -+ * MUST be delivered in order or it will completely screw up -+ * our bookeeping. -+ */ -+ txctrl = E1000_READ_REG(hw, E1000_DCA_TXCTRL(i)); -+ txctrl &= ~E1000_DCA_TXCTRL_TX_WB_RO_EN; -+ E1000_WRITE_REG(hw, E1000_DCA_TXCTRL(i), txctrl); -+ } + -+ /* Use the default values for the Tx Inter Packet Gap (IPG) timer */ ++ /* disable queue 0 which is enabled by default on 82575 and 82576 */ ++ E1000_WRITE_REG(hw, E1000_TXDCTL(0), 0); + + /* Program the Transmit Control Register */ -+ + tctl = E1000_READ_REG(hw, E1000_TCTL); + tctl &= ~E1000_TCTL_CT; + tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC | @@ -19443,9 +17213,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + e1000_config_collision_dist(hw); + -+ /* Setup Transmit Descriptor Settings for eop descriptor */ -+ adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS; -+ + /* Enable transmits */ + tctl |= E1000_TCTL_EN; + @@ -19453,17 +17220,70 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +} + +/** -+ * igb_setup_rx_resources - allocate Rx resources (Descriptors) ++ * igb_configure_tx_ring - Configure transmit ring after Reset ++ * @adapter: board private structure ++ * @ring: tx ring to configure ++ * ++ * Configure a transmit ring after a reset. ++ **/ ++void igb_configure_tx_ring(struct igb_adapter *adapter, ++ struct igb_ring *ring) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 txdctl; ++ u64 tdba = ring->dma; ++ int reg_idx = ring->reg_idx; ++ ++ /* disable the queue */ ++ txdctl = E1000_READ_REG(hw, E1000_TXDCTL(reg_idx)); ++ E1000_WRITE_REG(hw, E1000_TXDCTL(reg_idx), ++ txdctl & ~E1000_TXDCTL_QUEUE_ENABLE); ++ E1000_WRITE_FLUSH(hw); ++ mdelay(10); ++ ++ E1000_WRITE_REG(hw, E1000_TDLEN(reg_idx), ++ ring->count * sizeof(struct e1000_tx_desc)); ++ E1000_WRITE_REG(hw, E1000_TDBAL(reg_idx), ++ tdba & 0x00000000ffffffffULL); ++ E1000_WRITE_REG(hw, E1000_TDBAH(reg_idx), tdba >> 32); ++ ++ ring->head = hw->hw_addr + E1000_TDH(reg_idx); ++ ring->tail = hw->hw_addr + E1000_TDT(reg_idx); ++ writel(0, ring->head); ++ writel(0, ring->tail); ++ ++ txdctl |= IGB_TX_PTHRESH; ++ txdctl |= IGB_TX_HTHRESH << 8; ++ txdctl |= IGB_TX_WTHRESH << 16; ++ ++ txdctl |= E1000_TXDCTL_QUEUE_ENABLE; ++ E1000_WRITE_REG(hw, E1000_TXDCTL(reg_idx), txdctl); ++} ++ ++/** ++ * igb_configure_tx - Configure transmit Unit after Reset + * @adapter: board private structure ++ * ++ * Configure the Tx unit of the MAC after a reset. ++ **/ ++static void igb_configure_tx(struct igb_adapter *adapter) ++{ ++ int i; ++ ++ for (i = 0; i < adapter->num_tx_queues; i++) ++ igb_configure_tx_ring(adapter, &adapter->tx_ring[i]); ++ ++} ++ ++/** ++ * igb_setup_rx_resources - allocate Rx resources (Descriptors) + * @rx_ring: rx descriptor ring (for a specific queue) to setup + * + * Returns 0 on success, negative on failure + **/ -+ -+int igb_setup_rx_resources(struct igb_adapter *adapter, -+ struct igb_ring *rx_ring) ++int igb_setup_rx_resources(struct igb_ring *rx_ring) +{ -+ struct pci_dev *pdev = adapter->pdev; ++ struct pci_dev *pdev = rx_ring->pdev; + int size, desc_len; + +#ifdef IGB_LRO @@ -19472,8 +17292,8 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + if (!rx_ring->lro_mgr.lro_arr) + goto err; + memset(rx_ring->lro_mgr.lro_arr, 0, size); -+ +#endif /* IGB_LRO */ ++ + size = sizeof(struct igb_buffer) * rx_ring->count; + rx_ring->buffer_info = vmalloc(size); + if (!rx_ring->buffer_info) @@ -19486,7 +17306,8 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + rx_ring->size = rx_ring->count * desc_len; + rx_ring->size = ALIGN(rx_ring->size, 4096); + -+ rx_ring->desc = pci_alloc_consistent(pdev, rx_ring->size, ++ rx_ring->desc = pci_alloc_consistent(pdev, ++ rx_ring->size, + &rx_ring->dma); + + if (!rx_ring->desc) @@ -19495,7 +17316,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + rx_ring->next_to_clean = 0; + rx_ring->next_to_use = 0; + -+ rx_ring->adapter = adapter; ++ + return 0; + +err: @@ -19505,8 +17326,8 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +#endif + vfree(rx_ring->buffer_info); + rx_ring->buffer_info = NULL; -+ DPRINTK(PROBE, ERR, "Unable to allocate memory for the receive " -+ "descriptor ring\n"); ++ dev_err(&pdev->dev, "Unable to allocate memory for the " ++ "receive descriptor ring\n"); + return -ENOMEM; +} + @@ -19517,13 +17338,12 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * + * Return 0 on success, negative on failure + **/ -+ +static int igb_setup_all_rx_resources(struct igb_adapter *adapter) +{ + int i, err = 0; + + for (i = 0; i < adapter->num_rx_queues; i++) { -+ err = igb_setup_rx_resources(adapter, &adapter->rx_ring[i]); ++ err = igb_setup_rx_resources(&adapter->rx_ring[i]); + if (err) { + DPRINTK(PROBE, ERR, + "Allocation for Rx Queue %u failed\n", i); @@ -19533,98 +17353,314 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + } + } + -+ return err; ++ return err; ++} ++ ++/** ++ * igb_setup_mrqc - configure the multiple receive queue control registers ++ * @adapter: Board private structure ++ **/ ++static void igb_setup_mrqc(struct igb_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 mrqc, rxcsum; ++ u32 j, num_rx_queues, shift = 0, shift2 = 0; ++ union e1000_reta { ++ u32 dword; ++ u8 bytes[4]; ++ } reta; ++ static const u8 rsshash[40] = { ++ 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2, 0x41, 0x67, ++ 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0, 0xd0, 0xca, 0x2b, 0xcb, ++ 0xae, 0x7b, 0x30, 0xb4, 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, ++ 0xf2, 0x0c, 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa }; ++ ++ /* Fill out hash function seeds */ ++ for (j = 0; j < 10; j++) { ++ u32 rsskey = rsshash[(j * 4)]; ++ rsskey |= rsshash[(j * 4) + 1] << 8; ++ rsskey |= rsshash[(j * 4) + 2] << 16; ++ rsskey |= rsshash[(j * 4) + 3] << 24; ++ E1000_WRITE_REG_ARRAY(hw, E1000_RSSRK(0), j, rsskey); ++ } ++ ++ num_rx_queues = adapter->RSS_queues; ++ ++ if (adapter->vfs_allocated_count || adapter->VMDQ_queues) { ++ /* 82575 and 82576 supports 2 RSS queues for VMDq */ ++ switch (hw->mac.type) { ++ case e1000_82576: ++ shift = 3; ++ num_rx_queues = 2; ++ break; ++ case e1000_82575: ++ shift = 2; ++ shift2 = 6; ++ default: ++ break; ++ } ++ } else { ++ if (hw->mac.type == e1000_82575) ++ shift = 6; ++ } ++ ++ for (j = 0; j < (32 * 4); j++) { ++ reta.bytes[j & 3] = (j % num_rx_queues) << shift; ++ if (shift2) ++ reta.bytes[j & 3] |= num_rx_queues << shift2; ++ if ((j & 3) == 3) ++ E1000_WRITE_REG(hw, E1000_RETA(j >> 2), reta.dword); ++ } ++ ++ /* ++ * Disable raw packet checksumming so that RSS hash is placed in ++ * descriptor on writeback. No need to enable TCP/UDP/IP checksum ++ * offloads as they are enabled by default ++ */ ++ rxcsum = E1000_READ_REG(hw, E1000_RXCSUM); ++ rxcsum |= E1000_RXCSUM_PCSD; ++ ++ if (adapter->hw.mac.type >= e1000_82576) ++ /* Enable Receive Checksum Offload for SCTP */ ++ rxcsum |= E1000_RXCSUM_CRCOFL; ++ ++ /* Don't need to set TUOFL or IPOFL, they default to 1 */ ++ E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum); ++ ++ /* If VMDq is enabled then we set the appropriate mode for that, else ++ * we default to RSS so that an RSS hash is calculated per packet even ++ * if we are only using one queue */ ++ if (adapter->vfs_allocated_count || adapter->VMDQ_queues) { ++ if (hw->mac.type > e1000_82575) { ++ /* Set the default pool for the PF's first queue */ ++ u32 vtctl = E1000_READ_REG(hw, E1000_VT_CTL); ++ vtctl &= ~(E1000_VT_CTL_DEFAULT_POOL_MASK | ++ E1000_VT_CTL_DISABLE_DEF_POOL); ++ vtctl |= adapter->vfs_allocated_count << ++ E1000_VT_CTL_DEFAULT_POOL_SHIFT; ++ E1000_WRITE_REG(hw, E1000_VT_CTL, vtctl); ++ } else if (adapter->RSS_queues > 1) { ++ /* set default queue for pool 1 to queue 2 */ ++ E1000_WRITE_REG(hw, E1000_VT_CTL, ++ adapter->RSS_queues << 7); ++ } ++ if (adapter->RSS_queues > 1) ++ mrqc = E1000_MRQC_ENABLE_VMDQ_RSS_2Q; ++ else ++ mrqc = E1000_MRQC_ENABLE_VMDQ; ++ } else { ++ mrqc = E1000_MRQC_ENABLE_RSS_4Q; ++ } ++ igb_vmm_control(adapter); ++ ++ mrqc |= (E1000_MRQC_RSS_FIELD_IPV4 | ++ E1000_MRQC_RSS_FIELD_IPV4_TCP); ++ mrqc |= (E1000_MRQC_RSS_FIELD_IPV6 | ++ E1000_MRQC_RSS_FIELD_IPV6_TCP); ++ mrqc |= (E1000_MRQC_RSS_FIELD_IPV4_UDP | ++ E1000_MRQC_RSS_FIELD_IPV6_UDP); ++ mrqc |= (E1000_MRQC_RSS_FIELD_IPV6_UDP_EX | ++ E1000_MRQC_RSS_FIELD_IPV6_TCP_EX); ++ ++ E1000_WRITE_REG(hw, E1000_MRQC, mrqc); ++} ++ ++/** ++ * igb_setup_rctl - configure the receive control registers ++ * @adapter: Board private structure ++ **/ ++void igb_setup_rctl(struct igb_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 rctl; ++ ++ rctl = E1000_READ_REG(hw, E1000_RCTL); ++ ++ rctl &= ~(3 << E1000_RCTL_MO_SHIFT); ++ rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); ++ ++ rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_RDMTS_HALF | ++ (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT); ++ ++ /* ++ * enable stripping of CRC. It's unlikely this will break BMC ++ * redirection as it did with e1000. Newer features require ++ * that the HW strips the CRC. ++ */ ++ rctl |= E1000_RCTL_SECRC; ++ ++ ++ /* disable store bad packets and clear size bits. */ ++ rctl &= ~(E1000_RCTL_SBP | E1000_RCTL_SZ_256); ++ ++ /* enable LPE to prevent packets larger than max_frame_size */ ++ rctl |= E1000_RCTL_LPE; ++ ++ /* disable rx queue 0 which is enabled by default on 82575 and 82576 */ ++ E1000_WRITE_REG(hw, E1000_RXDCTL(0), 0); ++ ++ /* Attention!!! For SR-IOV PF driver operations you must enable ++ * queue drop for all VF and PF queues to prevent head of line blocking ++ * if an un-trusted VF does not provide descriptors to hardware. ++ */ ++ if (adapter->vfs_allocated_count) { ++ /* set all queue drop enable bits */ ++ E1000_WRITE_REG(hw, E1000_QDE, 0xFF); ++ ++ } ++ ++ E1000_WRITE_REG(hw, E1000_RCTL, rctl); ++} ++ ++static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size, int vfn) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 vmolr; ++ ++ /* if it isn't the PF check to see if VFs are enabled and ++ * increase the size to support vlan tags */ ++ if (vfn < adapter->vfs_allocated_count && ++ adapter->vf_data[vfn].vlans_enabled) ++ size += VLAN_TAG_SIZE; ++ ++ vmolr = E1000_READ_REG(hw, E1000_VMOLR(vfn)); ++ vmolr &= ~E1000_VMOLR_RLPML_MASK; ++ vmolr |= size | E1000_VMOLR_LPE; ++ E1000_WRITE_REG(hw, E1000_VMOLR(vfn), vmolr); ++ ++ return 0; ++} ++ ++ ++/** ++ * igb_set_rlpml - set receive large packet maximum length ++ * @adapter: board private structure ++ * ++ * Configure the maximum size of packets that will be received ++ */ ++static void igb_set_rlpml(struct igb_adapter *adapter) ++{ ++ int max_frame_size = adapter->max_frame_size; ++ struct e1000_hw *hw = &adapter->hw; ++ u16 pf_id = adapter->vfs_allocated_count; ++ ++ if (adapter->vlgrp) ++ max_frame_size += VLAN_TAG_SIZE; ++ if (adapter->VMDQ_queues) { ++ int i; ++ for (i = 0; i < adapter->VMDQ_queues; i++) ++ igb_set_vf_rlpml(adapter, max_frame_size, pf_id + i); ++ max_frame_size = MAX_JUMBO_FRAME_SIZE; ++ } ++ E1000_WRITE_REG(hw, E1000_RLPML, max_frame_size); ++ +} + -+/** -+ * igb_setup_rctl - configure the receive control registers -+ * @adapter: Board private structure -+ **/ -+static void igb_setup_rctl(struct igb_adapter *adapter) ++static inline void igb_set_vmolr(struct igb_adapter *adapter, int vfn) +{ + struct e1000_hw *hw = &adapter->hw; -+ u32 rctl; -+ u32 srrctl = 0; -+ int i; ++ u32 vmolr; + -+ rctl = E1000_READ_REG(hw, E1000_RCTL); ++ /* ++ * This register exists only on 82576 and newer so if we are older then ++ * we should exit and do nothing ++ */ ++ if (hw->mac.type < e1000_82576) ++ return; + -+ rctl &= ~(3 << E1000_RCTL_MO_SHIFT); ++ vmolr = E1000_READ_REG(hw, E1000_VMOLR(vfn)); ++ vmolr |= E1000_VMOLR_AUPE | /* Accept untagged packets */ ++ E1000_VMOLR_STRVLAN; /* Strip vlan tags */ + -+ rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | -+ E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | -+ (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT); ++ /* clear all bits that might not be set */ ++ vmolr &= ~(E1000_VMOLR_BAM | E1000_VMOLR_RSSE); + ++ if (adapter->RSS_queues > 1 && vfn == adapter->vfs_allocated_count) ++ vmolr |= E1000_VMOLR_RSSE; /* enable RSS */ + /* -+ * enable stripping of CRC. It's unlikely this will break BMC -+ * redirection as it did with e1000. Newer features require -+ * that the HW strips the CRC. ++ * for VMDq only allow the VFs and pool 0 to accept broadcast and ++ * multicast packets + */ -+ rctl |= E1000_RCTL_SECRC; -+ -+ rctl &= ~E1000_RCTL_SBP; ++ if (vfn <= adapter->vfs_allocated_count) ++ vmolr |= E1000_VMOLR_BAM; /* Accept broadcast */ + -+ if (adapter->netdev->mtu <= ETH_DATA_LEN) -+ rctl &= ~E1000_RCTL_LPE; -+ else -+ rctl |= E1000_RCTL_LPE; -+ -+ if (adapter->rx_buffer_len <= IGB_RXBUFFER_2048) { -+ /* Setup buffer sizes */ -+ rctl &= ~E1000_RCTL_SZ_4096; -+ rctl |= E1000_RCTL_BSEX; -+ switch (adapter->rx_buffer_len) { -+ case IGB_RXBUFFER_256: -+ rctl |= E1000_RCTL_SZ_256; -+ rctl &= ~E1000_RCTL_BSEX; -+ break; -+ case IGB_RXBUFFER_512: -+ rctl |= E1000_RCTL_SZ_512; -+ rctl &= ~E1000_RCTL_BSEX; -+ break; -+ case IGB_RXBUFFER_1024: -+ rctl |= E1000_RCTL_SZ_1024; -+ rctl &= ~E1000_RCTL_BSEX; -+ break; -+ case IGB_RXBUFFER_2048: -+ default: -+ rctl |= E1000_RCTL_SZ_2048; -+ rctl &= ~E1000_RCTL_BSEX; -+ break; -+ } -+ } else { -+ rctl &= ~E1000_RCTL_BSEX; -+ srrctl = adapter->rx_buffer_len >> E1000_SRRCTL_BSIZEPKT_SHIFT; -+ } ++ E1000_WRITE_REG(hw, E1000_VMOLR(vfn), vmolr); ++} + ++/** ++ * igb_configure_rx_ring - Configure a receive ring after Reset ++ * @adapter: board private structure ++ * @ring: receive ring to be configured ++ * ++ * Configure the Rx unit of the MAC after a reset. ++ **/ ++void igb_configure_rx_ring(struct igb_adapter *adapter, ++ struct igb_ring *ring) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u64 rdba = ring->dma; ++ int reg_idx = ring->reg_idx; ++ u32 srrctl, rxdctl; ++ ++ /* disable the queue */ ++ rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(reg_idx)); ++ E1000_WRITE_REG(hw, E1000_RXDCTL(reg_idx), ++ rxdctl & ~E1000_RXDCTL_QUEUE_ENABLE); ++ ++ /* Set DMA base address registers */ ++ E1000_WRITE_REG(hw, E1000_RDBAL(reg_idx), ++ rdba & 0x00000000ffffffffULL); ++ E1000_WRITE_REG(hw, E1000_RDBAH(reg_idx), rdba >> 32); ++ E1000_WRITE_REG(hw, E1000_RDLEN(reg_idx), ++ ring->count * sizeof(union e1000_adv_rx_desc)); ++ ++ /* initialize head and tail */ ++ ring->head = hw->hw_addr + E1000_RDH(reg_idx); ++ ring->tail = hw->hw_addr + E1000_RDT(reg_idx); ++ writel(0, ring->head); ++ writel(0, ring->tail); ++ ++ /* set descriptor configuration */ ++ srrctl = ALIGN(ring->rx_buffer_len, 1024) >> ++ E1000_SRRCTL_BSIZEPKT_SHIFT; +#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT -+ /* 82575 and greater support packet-split where the protocol -+ * header is placed in skb->data and the packet data is -+ * placed in pages hanging off of skb_shinfo(skb)->nr_frags. -+ * In the case of a non-split, skb->data is linearly filled, -+ * followed by the page buffers. Therefore, skb->data is -+ * sized to hold the largest protocol header. -+ */ -+ /* allocations using alloc_page take too long for regular MTU -+ * so only enable packet split for jumbo frames */ -+ if (rctl & E1000_RCTL_LPE) { -+ adapter->rx_ps_hdr_size = IGB_RXBUFFER_128; -+ srrctl |= adapter->rx_ps_hdr_size << -+ E1000_SRRCTL_BSIZEHDRSIZE_SHIFT; ++ srrctl |= ALIGN(ring->rx_ps_hdr_size, 64) << ++ E1000_SRRCTL_BSIZEHDRSIZE_SHIFT; ++ if (ring->rx_ps_hdr_size) + srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS; -+ } else { ++ else +#endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ -+ adapter->rx_ps_hdr_size = 0; + srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF; -+#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT -+ } -+#endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ + -+ for (i = 0; i < adapter->num_rx_queues; i++) { -+ E1000_WRITE_REG(hw, E1000_SRRCTL(i), srrctl); -+ } ++ E1000_WRITE_REG(hw, E1000_SRRCTL(reg_idx), srrctl); + -+ E1000_WRITE_REG(hw, E1000_RCTL, rctl); ++ /* set filtering for VMDQ pools */ ++ igb_set_vmolr(adapter, reg_idx & 0x7); ++ ++ /* enable receive descriptor fetching */ ++ rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(reg_idx)); ++ rxdctl |= E1000_RXDCTL_QUEUE_ENABLE; ++ rxdctl &= 0xFFF00000; ++ rxdctl |= IGB_RX_PTHRESH; ++ rxdctl |= IGB_RX_HTHRESH << 8; ++ rxdctl |= IGB_RX_WTHRESH << 16; ++ E1000_WRITE_REG(hw, E1000_RXDCTL(reg_idx), rxdctl); ++} ++ ++static inline void igb_set_vlan_stripping(struct igb_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 reg; ++ ++ /* enable replication vlan tag stripping */ ++ reg = E1000_READ_REG(hw, E1000_RPLOLR); ++ reg |= E1000_RPLOLR_STRVLAN; ++ E1000_WRITE_REG(hw, E1000_RPLOLR, reg); ++ ++ /* notify HW that the MAC is adding vlan tags */ ++ reg = E1000_READ_REG(hw, E1000_DTXCTL); ++ reg |= E1000_DTXCTL_VLAN_ADDED; ++ E1000_WRITE_REG(hw, E1000_DTXCTL, reg); +} + +/** @@ -19633,148 +17669,45 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * + * Configure the Rx unit of the MAC after a reset. + **/ -+ +static void igb_configure_rx(struct igb_adapter *adapter) +{ -+ u64 rdba; -+ struct e1000_hw *hw = &adapter->hw; -+ u32 rctl, rxcsum; -+ u32 rxdctl; + int i; + -+ /* disable receives while setting up the descriptors */ -+ rctl = E1000_READ_REG(hw, E1000_RCTL); -+ E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); -+ E1000_WRITE_FLUSH(hw); -+ mdelay(10); -+ -+ if (adapter->itr_setting > 3) { -+ E1000_WRITE_REG(hw, E1000_ITR, adapter->itr); -+ } -+ /* Setup the HW Rx Head and Tail Descriptor Pointers and -+ * the Base and Length of the Rx Descriptor Ring */ -+ for (i = 0; i < adapter->num_rx_queues; i++) { -+ struct igb_ring *ring = &(adapter->rx_ring[i]); -+ rdba = ring->dma; -+ E1000_WRITE_REG(hw, E1000_RDBAL(i), -+ rdba & 0x00000000ffffffffULL); -+ E1000_WRITE_REG(hw, E1000_RDBAH(i), rdba >> 32); -+ E1000_WRITE_REG(hw, E1000_RDLEN(i), -+ ring->count * sizeof(union e1000_adv_rx_desc)); -+ -+ ring->head = E1000_RDH(i); -+ ring->tail = E1000_RDT(i); -+ writel(0, hw->hw_addr + ring->tail); -+ writel(0, hw->hw_addr + ring->head); -+ -+ rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(i)); -+ rxdctl |= E1000_RXDCTL_QUEUE_ENABLE; -+ rxdctl &= 0xFFF00000; -+ rxdctl |= IGB_RX_PTHRESH; -+ rxdctl |= IGB_RX_HTHRESH << 8; -+ rxdctl |= IGB_RX_WTHRESH << 16; -+ E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl); -+#ifdef IGB_LRO -+ /* Intitial LRO Settings */ -+ ring->lro_mgr.max_aggr = adapter->lro_max_aggr; -+ ring->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS; -+ ring->lro_mgr.get_skb_header = igb_get_skb_hdr; -+ ring->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID; -+ ring->lro_mgr.dev = adapter->netdev; -+ ring->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY; -+ ring->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; -+#endif -+ -+ } -+ -+ if (adapter->num_rx_queues > 1) { -+ u32 random[10]; -+ u32 mrqc; -+ u32 j, shift; -+ union e1000_reta { -+ u32 dword; -+ u8 bytes[4]; -+ } reta; -+ -+ /* ugh, using random bytes here means we'll never put the same -+ * flow in the same rx queue */ -+ get_random_bytes(&random[0], 40); -+ -+ if (hw->mac.type >= e1000_82576) -+ shift = 0; -+ else -+ shift = 6; -+ for (j = 0; j < (32 * 4); j++) { -+ reta.bytes[j & 3] = -+ (j % adapter->num_rx_queues) << shift; -+ if ((j & 3) == 3) { -+ writel(reta.dword, -+ hw->hw_addr + E1000_RETA(0) + (j & ~3)); -+ } -+ } -+ mrqc = E1000_MRQC_ENABLE_RSS_4Q; -+ -+ /* Fill out hash function seeds */ -+ for (j = 0; j < 10; j++) -+ E1000_WRITE_REG_ARRAY(hw, E1000_RSSRK(0), j, random[j]); -+ -+ mrqc |= (E1000_MRQC_RSS_FIELD_IPV4 | -+ E1000_MRQC_RSS_FIELD_IPV4_TCP); -+ mrqc |= (E1000_MRQC_RSS_FIELD_IPV6 | -+ E1000_MRQC_RSS_FIELD_IPV6_TCP); -+ mrqc |=( E1000_MRQC_RSS_FIELD_IPV4_UDP | -+ E1000_MRQC_RSS_FIELD_IPV6_UDP); -+ mrqc |=( E1000_MRQC_RSS_FIELD_IPV6_UDP_EX | -+ E1000_MRQC_RSS_FIELD_IPV6_TCP_EX); -+ -+ -+ E1000_WRITE_REG(hw, E1000_MRQC, mrqc); ++ /* enable vlan tag stripping for replicated packets */ ++ igb_set_vlan_stripping(adapter); + -+ /* Multiqueue and raw packet checksumming are mutually -+ * exclusive. Note that this not the same as TCP/IP -+ * checksumming, which works fine. */ -+ rxcsum = E1000_READ_REG(hw, E1000_RXCSUM); -+ rxcsum |= E1000_RXCSUM_PCSD; -+ E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum); -+ } else { -+ /* Enable Receive Checksum Offload for TCP and UDP */ -+ rxcsum = E1000_READ_REG(hw, E1000_RXCSUM); -+ if (adapter->rx_csum) -+ rxcsum |= E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPPCSE; -+ else -+ rxcsum &= ~E1000_RXCSUM_TUOFL; -+ /* don't need to clear IPPCSE as it defaults to 0 */ -+ E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum); -+ } ++ /* set UTA to appropriate mode */ ++ igb_set_uta(adapter); + -+ if (adapter->vlgrp) -+ E1000_WRITE_REG(hw, E1000_RLPML, -+ adapter->max_frame_size + VLAN_TAG_SIZE); -+ else -+ E1000_WRITE_REG(hw, E1000_RLPML, adapter->max_frame_size); ++ /* set the correct pool for the PF default MAC address in entry 0 */ ++ igb_rar_set_qsel(adapter, adapter->hw.mac.addr, 0, ++ adapter->vfs_allocated_count); + -+ /* Enable Receives */ -+ E1000_WRITE_REG(hw, E1000_RCTL, rctl); ++ /* Setup the HW Rx Head and Tail Descriptor Pointers and ++ * the Base and Length of the Rx Descriptor Ring */ ++ for (i = 0; i < adapter->num_rx_queues; i++) ++ igb_configure_rx_ring(adapter, &adapter->rx_ring[i]); +} + +/** + * igb_free_tx_resources - Free Tx Resources per Queue -+ * @adapter: board private structure + * @tx_ring: Tx descriptor ring for a specific queue + * + * Free all transmit software resources + **/ -+ +void igb_free_tx_resources(struct igb_ring *tx_ring) +{ -+ struct pci_dev *pdev = tx_ring->adapter->pdev; -+ + igb_clean_tx_ring(tx_ring); + + vfree(tx_ring->buffer_info); + tx_ring->buffer_info = NULL; + -+ pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma); ++ /* if not set, then don't free */ ++ if (!tx_ring->desc) ++ return; ++ ++ pci_free_consistent(tx_ring->pdev, tx_ring->size, ++ tx_ring->desc, tx_ring->dma); + + tx_ring->desc = NULL; +} @@ -19785,7 +17718,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * + * Free all transmit software resources + **/ -+ +static void igb_free_all_tx_resources(struct igb_adapter *adapter) +{ + int i; @@ -19794,11 +17726,18 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + igb_free_tx_resources(&adapter->tx_ring[i]); +} + -+static void igb_unmap_and_free_tx_resource(struct igb_adapter *adapter, ++static void igb_unmap_and_free_tx_resource(struct pci_dev *pdev, + struct igb_buffer *buffer_info) +{ ++ if (buffer_info->page_dma) { ++ pci_unmap_page(pdev, ++ buffer_info->page_dma, ++ buffer_info->length, ++ PCI_DMA_TODEVICE); ++ buffer_info->page_dma = 0; ++ } + if (buffer_info->dma) { -+ pci_unmap_page(adapter->pdev, ++ pci_unmap_single(pdev, + buffer_info->dma, + buffer_info->length, + PCI_DMA_TODEVICE); @@ -19809,18 +17748,16 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + buffer_info->skb = NULL; + } + buffer_info->time_stamp = 0; ++ buffer_info->next_to_watch = 0; + /* buffer_info must be completely set up in the transmit path */ +} + +/** + * igb_clean_tx_ring - Free Tx Buffers -+ * @adapter: board private structure + * @tx_ring: ring to be cleaned + **/ -+ +static void igb_clean_tx_ring(struct igb_ring *tx_ring) +{ -+ struct igb_adapter *adapter = tx_ring->adapter; + struct igb_buffer *buffer_info; + unsigned long size; + unsigned int i; @@ -19831,28 +17768,23 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + for (i = 0; i < tx_ring->count; i++) { + buffer_info = &tx_ring->buffer_info[i]; -+ igb_unmap_and_free_tx_resource(adapter, buffer_info); ++ igb_unmap_and_free_tx_resource(tx_ring->pdev, buffer_info); + } + + size = sizeof(struct igb_buffer) * tx_ring->count; + memset(tx_ring->buffer_info, 0, size); + + /* Zero out the descriptor ring */ -+ + memset(tx_ring->desc, 0, tx_ring->size); + + tx_ring->next_to_use = 0; + tx_ring->next_to_clean = 0; -+ -+ writel(0, adapter->hw.hw_addr + tx_ring->head); -+ writel(0, adapter->hw.hw_addr + tx_ring->tail); +} + +/** + * igb_clean_all_tx_rings - Free Tx Buffers for all queues + * @adapter: board private structure + **/ -+ +static void igb_clean_all_tx_rings(struct igb_adapter *adapter) +{ + int i; @@ -19863,16 +17795,12 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + +/** + * igb_free_rx_resources - Free Rx Resources -+ * @adapter: board private structure + * @rx_ring: ring to clean the resources from + * + * Free all receive software resources + **/ -+ +void igb_free_rx_resources(struct igb_ring *rx_ring) +{ -+ struct pci_dev *pdev = rx_ring->adapter->pdev; -+ + igb_clean_rx_ring(rx_ring); + + vfree(rx_ring->buffer_info); @@ -19883,7 +17811,12 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + rx_ring->lro_mgr.lro_arr = NULL; +#endif /* IGB_LRO */ + -+ pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma); ++ /* if not set, then don't free */ ++ if (!rx_ring->desc) ++ return; ++ ++ pci_free_consistent(rx_ring->pdev, rx_ring->size, ++ rx_ring->desc, rx_ring->dma); + + rx_ring->desc = NULL; +} @@ -19894,7 +17827,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * + * Free all receive software resources + **/ -+ +static void igb_free_all_rx_resources(struct igb_adapter *adapter) +{ + int i; @@ -19905,33 +17837,31 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + +/** + * igb_clean_rx_ring - Free Rx Buffers per Queue -+ * @adapter: board private structure + * @rx_ring: ring to free buffers from + **/ -+ +static void igb_clean_rx_ring(struct igb_ring *rx_ring) +{ -+ struct igb_adapter *adapter = rx_ring->adapter; + struct igb_buffer *buffer_info; -+ struct pci_dev *pdev = adapter->pdev; + unsigned long size; + unsigned int i; + + if (!rx_ring->buffer_info) + return; ++ + /* Free all the Rx ring sk_buffs */ + for (i = 0; i < rx_ring->count; i++) { + buffer_info = &rx_ring->buffer_info[i]; + if (buffer_info->dma) { -+ if (adapter->rx_ps_hdr_size){ -+ pci_unmap_single(pdev, buffer_info->dma, -+ adapter->rx_ps_hdr_size, ++ if (rx_ring->rx_ps_hdr_size) ++ pci_unmap_single(rx_ring->pdev, ++ buffer_info->dma, ++ rx_ring->rx_ps_hdr_size, + PCI_DMA_FROMDEVICE); -+ } else { -+ pci_unmap_single(pdev, buffer_info->dma, -+ adapter->rx_buffer_len, ++ else ++ pci_unmap_single(rx_ring->pdev, ++ buffer_info->dma, ++ rx_ring->rx_buffer_len, + PCI_DMA_FROMDEVICE); -+ } + buffer_info->dma = 0; + } + @@ -19942,8 +17872,9 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT + if (buffer_info->page) { + if (buffer_info->page_dma) -+ pci_unmap_page(pdev, buffer_info->page_dma, -+ PAGE_SIZE / 2, ++ pci_unmap_page(rx_ring->pdev, ++ buffer_info->page_dma, ++ rx_ring->rx_buffer_len, + PCI_DMA_FROMDEVICE); + put_page(buffer_info->page); + buffer_info->page = NULL; @@ -19961,16 +17892,12 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + rx_ring->next_to_clean = 0; + rx_ring->next_to_use = 0; -+ -+ writel(0, adapter->hw.hw_addr + rx_ring->head); -+ writel(0, adapter->hw.hw_addr + rx_ring->tail); +} + +/** + * igb_clean_all_rx_rings - Free Rx Buffers for all queues + * @adapter: board private structure + **/ -+ +static void igb_clean_all_rx_rings(struct igb_adapter *adapter) +{ + int i; @@ -19986,7 +17913,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * + * Returns 0 on success, negative on failure + **/ -+ +static int igb_set_mac(struct net_device *netdev, void *p) +{ + struct igb_adapter *adapter = netdev_priv(netdev); @@ -19999,58 +17925,44 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len); + -+ e1000_rar_set(hw, hw->mac.addr, 0); ++ /* set the correct pool for the new PF MAC address in entry 0 */ ++ igb_rar_set_qsel(adapter, hw->mac.addr, 0, ++ adapter->vfs_allocated_count); + + return 0; +} + +/** -+ * igb_set_multi - Multicast and Promiscuous mode set ++ * igb_write_mc_addr_list - write multicast addresses to MTA + * @netdev: network interface device structure + * -+ * The set_multi entry point is called whenever the multicast address -+ * list or the network interface flags are updated. This routine is -+ * responsible for configuring the hardware for proper multicast, -+ * promiscuous mode, and all-multi behavior. ++ * Writes multicast address list to the MTA hash table. ++ * Returns: -ENOMEM on failure ++ * 0 on no addresses written ++ * X on writing X addresses to MTA + **/ -+ -+static void igb_set_multi(struct net_device *netdev) ++static int igb_write_mc_addr_list(struct net_device *netdev) +{ + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; -+ struct e1000_mac_info *mac = &hw->mac; -+ struct dev_mc_list *mc_ptr; ++ struct dev_mc_list *mc_ptr = netdev->mc_list; + u8 *mta_list; -+ u32 rctl; ++ u32 vmolr = 0; + int i; + -+ /* Check for Promiscuous and All Multicast modes */ -+ -+ rctl = E1000_READ_REG(hw, E1000_RCTL); -+ -+ if (netdev->flags & IFF_PROMISC) { -+ rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); -+ rctl &= ~E1000_RCTL_VFE; -+ } else { -+ if (netdev->flags & IFF_ALLMULTI) { -+ rctl |= E1000_RCTL_MPE; -+ rctl &= ~E1000_RCTL_UPE; -+ } else -+ rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); -+ rctl |= E1000_RCTL_VFE; -+ } -+ E1000_WRITE_REG(hw, E1000_RCTL, rctl); -+ + if (!netdev->mc_count) { + /* nothing to program, so clear mc list */ -+ e1000_update_mc_addr_list(hw, NULL, 0, 1, -+ mac->rar_entry_count); -+ return; ++ e1000_update_mc_addr_list(hw, NULL, 0); ++ igb_restore_vf_multicasts(adapter); ++ return 0; + } + + mta_list = kzalloc(netdev->mc_count * 6, GFP_ATOMIC); + if (!mta_list) -+ return; ++ return -ENOMEM; ++ ++ /* set vmolr receive overflow multicast bit */ ++ vmolr |= E1000_VMOLR_ROMPE; + + /* The shared function expects a packed array of only addresses. */ + mc_ptr = netdev->mc_list; @@ -20061,13 +17973,149 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN); + mc_ptr = mc_ptr->next; + } -+ e1000_update_mc_addr_list(hw, mta_list, i, 1, mac->rar_entry_count); ++ e1000_update_mc_addr_list(hw, mta_list, i); + kfree(mta_list); ++ ++ return netdev->mc_count; ++} ++ ++#ifdef HAVE_SET_RX_MODE ++/** ++ * igb_write_uc_addr_list - write unicast addresses to RAR table ++ * @netdev: network interface device structure ++ * ++ * Writes unicast address list to the RAR table. ++ * Returns: -ENOMEM on failure/insufficient address space ++ * 0 on no addresses written ++ * X on writing X addresses to the RAR table ++ **/ ++static int igb_write_uc_addr_list(struct net_device *netdev) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ struct e1000_hw *hw = &adapter->hw; ++ unsigned int vfn = adapter->vfs_allocated_count; ++ unsigned int rar_entries = hw->mac.rar_entry_count - (vfn + 1); ++#ifndef HAVE_NETDEV_HW_ADDR ++ struct dev_mc_list *uc_ptr = netdev->uc_list; ++#endif ++ int count = 0; ++ ++ /* return ENOMEM indicating insufficient memory for addresses */ ++#ifndef HAVE_NETDEV_HW_ADDR ++ if (netdev->uc_count > rar_entries) ++#else ++ if (netdev->uc.count > rar_entries) ++#endif ++ return -ENOMEM; ++ ++#ifdef HAVE_NETDEV_HW_ADDR ++ if (netdev->uc.count && rar_entries) { ++ struct netdev_hw_addr *ha; ++ list_for_each_entry(ha, &netdev->uc.list, list) { ++ if (!rar_entries) ++ break; ++ igb_rar_set_qsel(adapter, ha->addr, ++ rar_entries--, ++ vfn); ++ count++; ++ } ++ } ++#else ++ while (uc_ptr) { ++ igb_rar_set_qsel(adapter, uc_ptr->da_addr, ++ rar_entries--, vfn); ++ uc_ptr = uc_ptr->next; ++ count++; ++ } ++#endif ++ /* write the addresses in reverse order to avoid write combining */ ++ for (; rar_entries > 0 ; rar_entries--) { ++ E1000_WRITE_REG(hw, E1000_RAH(rar_entries), 0); ++ E1000_WRITE_REG(hw, E1000_RAL(rar_entries), 0); ++ } ++ E1000_WRITE_FLUSH(hw); ++ ++ return count; ++} ++ ++#endif ++/** ++ * igb_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set ++ * @netdev: network interface device structure ++ * ++ * The set_rx_mode entry point is called whenever the unicast or multicast ++ * address lists or the network interface flags are updated. This routine is ++ * responsible for configuring the hardware for proper unicast, multicast, ++ * promiscuous mode, and all-multi behavior. ++ **/ ++static void igb_set_rx_mode(struct net_device *netdev) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ struct e1000_hw *hw = &adapter->hw; ++ unsigned int vfn = adapter->vfs_allocated_count; ++ u32 rctl, vmolr = 0; ++ int count; ++ ++ /* Check for Promiscuous and All Multicast modes */ ++ rctl = E1000_READ_REG(hw, E1000_RCTL); ++ ++ /* clear the effected bits */ ++ rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_VFE); ++ ++ if (netdev->flags & IFF_PROMISC) { ++ rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); ++ vmolr |= (E1000_VMOLR_ROPE | E1000_VMOLR_MPME); ++ } else { ++ if (netdev->flags & IFF_ALLMULTI) { ++ rctl |= E1000_RCTL_MPE; ++ vmolr |= E1000_VMOLR_MPME; ++ } else { ++ /* ++ * Write addresses to the MTA, if the attempt fails ++ * then we should just turn on promiscous mode so ++ * that we can at least receive multicast traffic ++ */ ++ count = igb_write_mc_addr_list(netdev); ++ if (count < 0) { ++ rctl |= E1000_RCTL_MPE; ++ vmolr |= E1000_VMOLR_MPME; ++ } else if (count) { ++ vmolr |= E1000_VMOLR_ROMPE; ++ } ++ } ++#ifdef HAVE_SET_RX_MODE ++ /* ++ * Write addresses to available RAR registers, if there is not ++ * sufficient space to store all the addresses then enable ++ * unicast promiscous mode ++ */ ++ count = igb_write_uc_addr_list(netdev); ++ if (count < 0) { ++ rctl |= E1000_RCTL_UPE; ++ vmolr |= E1000_VMOLR_ROPE; ++ } ++#endif ++ rctl |= E1000_RCTL_VFE; ++ } ++ E1000_WRITE_REG(hw, E1000_RCTL, rctl); ++ ++ /* ++ * In order to support SR-IOV and eventually VMDq it is necessary to set ++ * the VMOLR to enable the appropriate modes. Without this workaround ++ * we will have issues with VLAN tag stripping not being done for frames ++ * that are only arriving because we are the default pool ++ */ ++ if (hw->mac.type < e1000_82576) ++ return; ++ ++ vmolr |= E1000_READ_REG(hw, E1000_VMOLR(vfn)) & ++ ~(E1000_VMOLR_ROPE | E1000_VMOLR_MPME | E1000_VMOLR_ROMPE); ++ E1000_WRITE_REG(hw, E1000_VMOLR(vfn), vmolr); ++ igb_restore_vf_multicasts(adapter); +} + +/* Need to wait a few seconds after link up to get diagnostic information from + * the phy */ -+ +static void igb_update_phy_info(unsigned long data) +{ + struct igb_adapter *adapter = (struct igb_adapter *) data; @@ -20098,14 +18146,9 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + link_active = TRUE; + } + break; -+ case e1000_media_type_fiber: -+ ret_val = e1000_check_for_link(hw); -+ link_active = !!(E1000_READ_REG(hw, E1000_STATUS) & -+ E1000_STATUS_LU); -+ break; + case e1000_media_type_internal_serdes: + ret_val = e1000_check_for_link(hw); -+ link_active = adapter->hw.mac.serdes_has_link; ++ link_active = hw->mac.serdes_has_link; + break; + default: + case e1000_media_type_unknown: @@ -20131,15 +18174,12 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + struct igb_adapter *adapter = container_of(work, + struct igb_adapter, watchdog_task); + struct e1000_hw *hw = &adapter->hw; -+ struct igb_ring *tx_ring = adapter->tx_ring; + struct net_device *netdev = adapter->netdev; ++ struct igb_ring *tx_ring = adapter->tx_ring; + u32 link; -+ u32 eics = 0; + int i; + + link = igb_has_link(adapter); -+ if ((netif_carrier_ok(netdev)) && link) -+ goto link_up; + + if (link) { + if (!netif_carrier_ok(netdev)) { @@ -20175,6 +18215,13 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + netif_carrier_on(netdev); + netif_tx_wake_all_queues(netdev); ++ ++ igb_ping_all_vfs(adapter); ++ ++ /* link state has changed, schedule phy info update */ ++ if (!test_bit(__IGB_DOWN, &adapter->state)) ++ mod_timer(&adapter->phy_info_timer, ++ round_jiffies(jiffies + 2 * HZ)); + } + } else { + if (netif_carrier_ok(netdev)) { @@ -20183,10 +18230,16 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + DPRINTK(LINK, INFO, "NIC Link is Down\n"); + netif_carrier_off(netdev); + netif_tx_stop_all_queues(netdev); ++ ++ igb_ping_all_vfs(adapter); ++ ++ /* link state has changed, schedule phy info update */ ++ if (!test_bit(__IGB_DOWN, &adapter->state)) ++ mod_timer(&adapter->phy_info_timer, ++ round_jiffies(jiffies + 2 * HZ)); + } + } + -+link_up: + igb_update_stats(adapter); + + if (!netif_carrier_ok(netdev)) { @@ -20200,18 +18253,22 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + } + } + ++ /* Force detection of hung controller every watchdog period */ ++ for (i = 0; i < adapter->num_tx_queues; i++) ++ adapter->tx_ring[i].detect_tx_hung = TRUE; ++ + /* Cause software interrupt to ensure rx ring is cleaned */ + if (adapter->msix_entries) { -+ for (i = 0; i < adapter->num_rx_queues; i++) -+ eics |= adapter->rx_ring[i].eims_value; ++ u32 eics = 0; ++ for (i = 0; i < adapter->num_q_vectors; i++) { ++ struct igb_q_vector *q_vector = adapter->q_vector[i]; ++ eics |= q_vector->eims_value; ++ } + E1000_WRITE_REG(hw, E1000_EICS, eics); + } else { + E1000_WRITE_REG(hw, E1000_ICS, E1000_ICS_RXDMT0); + } + -+ /* Force detection of hung controller every watchdog period */ -+ tx_ring->detect_tx_hung = TRUE; -+ + /* Reset the timer */ + if (!test_bit(__IGB_DOWN, &adapter->state)) + mod_timer(&adapter->watchdog_timer, @@ -20240,29 +18297,38 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * parameter (see igb_param.c) + * NOTE: This function is called only when operating in a multiqueue + * receive environment. -+ * @rx_ring: pointer to ring ++ * @q_vector: pointer to q_vector + **/ -+static void igb_update_ring_itr(struct igb_ring *rx_ring) ++static void igb_update_ring_itr(struct igb_q_vector *q_vector) +{ -+ int new_val = rx_ring->itr_val; ++ int new_val = q_vector->itr_val; + int avg_wire_size = 0; -+ struct igb_adapter *adapter = rx_ring->adapter; -+ -+ if (!rx_ring->total_packets) -+ goto clear_counts; /* no packets, so don't do anything */ ++ struct igb_adapter *adapter = q_vector->adapter; + + /* For non-gigabit speeds, just fix the interrupt rate at 4000 + * ints/sec - ITR timer value of 120 ticks. + */ + if (adapter->link_speed != SPEED_1000) { -+ new_val = 120; ++ new_val = 976; + goto set_itr_val; + } -+ avg_wire_size = rx_ring->total_bytes / rx_ring->total_packets; -+ if (rx_ring->buddy && rx_ring->buddy->total_packets) -+ avg_wire_size = max(avg_wire_size, -+ (int)(rx_ring->buddy->total_bytes / -+ rx_ring->buddy->total_packets)); ++ ++ if (q_vector->rx_ring && q_vector->rx_ring->total_packets) { ++ struct igb_ring *ring = q_vector->rx_ring; ++ avg_wire_size = ring->total_bytes / ring->total_packets; ++ } ++ ++ if (q_vector->tx_ring && q_vector->tx_ring->total_packets) { ++ struct igb_ring *ring = q_vector->tx_ring; ++ avg_wire_size = max_t(u32, avg_wire_size, ++ (ring->total_bytes / ++ ring->total_packets)); ++ } ++ ++ /* if avg_wire_size isn't set no work was done */ ++ if (!avg_wire_size) ++ goto clear_counts; ++ + /* Add 24 bytes to size to account for CRC, preamble, and gap */ + avg_wire_size += 24; + @@ -20276,16 +18342,18 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + new_val = avg_wire_size / 2; + +set_itr_val: -+ if (new_val != rx_ring->itr_val) { -+ rx_ring->itr_val = new_val; -+ rx_ring->set_itr = 1; ++ if (new_val != q_vector->itr_val) { ++ q_vector->itr_val = new_val; ++ q_vector->set_itr = 1; + } +clear_counts: -+ rx_ring->total_bytes = 0; -+ rx_ring->total_packets = 0; -+ if (rx_ring->buddy) { -+ rx_ring->buddy->total_bytes = 0; -+ rx_ring->buddy->total_packets = 0; ++ if (q_vector->rx_ring) { ++ q_vector->rx_ring->total_bytes = 0; ++ q_vector->rx_ring->total_packets = 0; ++ } ++ if (q_vector->tx_ring) { ++ q_vector->tx_ring->total_bytes = 0; ++ q_vector->tx_ring->total_packets = 0; + } +} + @@ -20320,9 +18388,8 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + /* handle TSO and jumbo frames */ + if (bytes/packets > 8000) + retval = bulk_latency; -+ else if ((packets < 5) && (bytes > 512)) { ++ else if ((packets < 5) && (bytes > 512)) + retval = low_latency; -+ } + break; + case low_latency: /* 50 usec aka 20000 ints/s */ + if (bytes > 10000) { @@ -20342,9 +18409,8 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + break; + case bulk_latency: /* 250 usec aka 4000 ints/s */ + if (bytes > 25000) { -+ if (packets > 35) { ++ if (packets > 35) + retval = low_latency; -+ } + } else if (bytes < 1500) { + retval = low_latency; + } @@ -20354,7 +18420,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +update_itr_done: + return retval; +} -+ +static void igb_set_itr(struct igb_adapter *adapter) +{ + u16 current_itr; @@ -20372,15 +18437,11 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + adapter->rx_ring->total_packets, + adapter->rx_ring->total_bytes); + -+ if (adapter->rx_ring->buddy) { -+ adapter->tx_itr = igb_update_itr(adapter, -+ adapter->tx_itr, -+ adapter->tx_ring->total_packets, -+ adapter->tx_ring->total_bytes); -+ current_itr = max(adapter->rx_itr, adapter->tx_itr); -+ } else { -+ current_itr = adapter->rx_itr; -+ } ++ adapter->tx_itr = igb_update_itr(adapter, ++ adapter->tx_itr, ++ adapter->tx_ring->total_packets, ++ adapter->tx_ring->total_bytes); ++ current_itr = max(adapter->rx_itr, adapter->tx_itr); + + /* conservative mode (itr 3) eliminates the lowest_latency setting */ + if (adapter->itr_setting == 3 && current_itr == lowest_latency) @@ -20389,13 +18450,13 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + switch (current_itr) { + /* counts and packets in update_itr are dependent on these numbers */ + case lowest_latency: -+ new_itr = 70000; ++ new_itr = 56; /* aka 70,000 ints/sec */ + break; + case low_latency: -+ new_itr = 20000; /* aka hwitr = ~200 */ ++ new_itr = 196; /* aka 20,000 ints/sec */ + break; + case bulk_latency: -+ new_itr = 4000; ++ new_itr = 980; /* aka 4,000 ints/sec */ + break; + default: + break; @@ -20404,17 +18465,17 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +set_itr_now: + adapter->rx_ring->total_bytes = 0; + adapter->rx_ring->total_packets = 0; -+ if (adapter->rx_ring->buddy) { -+ adapter->rx_ring->buddy->total_bytes = 0; -+ adapter->rx_ring->buddy->total_packets = 0; -+ } ++ adapter->tx_ring->total_bytes = 0; ++ adapter->tx_ring->total_packets = 0; + + if (new_itr != adapter->itr) { ++ struct igb_q_vector *q_vector = adapter->q_vector[0]; + /* this attempts to bias the interrupt rate towards Bulk + * by adding intermediate steps when interrupt rate is + * increasing */ + new_itr = new_itr > adapter->itr ? -+ min(adapter->itr + (new_itr >> 2), new_itr) : ++ max((new_itr * adapter->itr) / ++ (new_itr + (adapter->itr >> 2)), new_itr) : + new_itr; + /* Don't write the value here; it resets the adapter's + * internal timer, and causes us to delay far longer than @@ -20423,23 +18484,22 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * ends up being correct. + */ + adapter->itr = new_itr; -+ adapter->rx_ring->itr_val = 1000000000 / (new_itr * 256); -+ adapter->rx_ring->set_itr = 1; ++ q_vector->itr_val = new_itr; ++ q_vector->set_itr = 1; + } + + return; +} + -+ +#define IGB_TX_FLAGS_CSUM 0x00000001 +#define IGB_TX_FLAGS_VLAN 0x00000002 +#define IGB_TX_FLAGS_TSO 0x00000004 +#define IGB_TX_FLAGS_IPV4 0x00000008 ++#define IGB_TX_FLAGS_TSTAMP 0x00000010 +#define IGB_TX_FLAGS_VLAN_MASK 0xffff0000 +#define IGB_TX_FLAGS_VLAN_SHIFT 16 + -+static inline int igb_tso_adv(struct igb_adapter *adapter, -+ struct igb_ring *tx_ring, ++static inline int igb_tso_adv(struct igb_ring *tx_ring, + struct sk_buff *skb, u32 tx_flags, u8 *hdr_len) +{ +#ifdef NETIF_F_TSO @@ -20486,8 +18546,8 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + info |= (tx_flags & IGB_TX_FLAGS_VLAN_MASK); + info |= (skb_network_offset(skb) << E1000_ADVTXD_MACLEN_SHIFT); + *hdr_len += skb_network_offset(skb); -+ info |= (skb_transport_header(skb) - skb_network_header(skb)); -+ *hdr_len += (skb_transport_header(skb) - skb_network_header(skb)); ++ info |= skb_network_header_len(skb); ++ *hdr_len += skb_network_header_len(skb); + context_desc->vlan_macip_lens = cpu_to_le32(info); + + /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */ @@ -20502,15 +18562,13 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + /* MSS L4LEN IDX */ + mss_l4len_idx = (skb_shinfo(skb)->gso_size << E1000_ADVTXD_MSS_SHIFT); + mss_l4len_idx |= (l4len << E1000_ADVTXD_L4LEN_SHIFT); -+ -+ /* For 82575, context index must be unique per ring. */ -+ if (adapter->flags & IGB_FLAG_NEED_CTX_IDX) -+ mss_l4len_idx |= tx_ring->queue_index << 4; ++ mss_l4len_idx |= tx_ring->ctx_idx; + + context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx); + context_desc->seqnum_seed = 0; + + buffer_info->time_stamp = jiffies; ++ buffer_info->next_to_watch = i; + buffer_info->dma = 0; + i++; + if (i == tx_ring->count) @@ -20524,14 +18582,14 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +#endif /* NETIF_F_TSO */ +} + -+static inline bool igb_tx_csum_adv(struct igb_adapter *adapter, -+ struct igb_ring *tx_ring, ++static inline bool igb_tx_csum_adv(struct igb_ring *tx_ring, + struct sk_buff *skb, u32 tx_flags) +{ + struct e1000_adv_tx_context_desc *context_desc; -+ unsigned int i; ++ struct pci_dev *pdev = tx_ring->pdev; + struct igb_buffer *buffer_info; + u32 info = 0, tu_cmd = 0; ++ unsigned int i; + + if ((skb->ip_summed == CHECKSUM_PARTIAL) || + (tx_flags & IGB_TX_FLAGS_VLAN)) { @@ -20544,31 +18602,44 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + info |= (skb_network_offset(skb) << E1000_ADVTXD_MACLEN_SHIFT); + if (skb->ip_summed == CHECKSUM_PARTIAL) -+ info |= (skb_transport_header(skb) - -+ skb_network_header(skb)); -+ ++ info |= skb_network_header_len(skb); + + context_desc->vlan_macip_lens = cpu_to_le32(info); + + tu_cmd |= (E1000_TXD_CMD_DEXT | E1000_ADVTXD_DTYP_CTXT); + + if (skb->ip_summed == CHECKSUM_PARTIAL) { -+ switch (skb->protocol) { ++ __be16 protocol; ++ ++ if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { ++ const struct vlan_ethhdr *vhdr = ++ (const struct vlan_ethhdr*)skb->data; ++ ++ protocol = vhdr->h_vlan_encapsulated_proto; ++ } else { ++ protocol = skb->protocol; ++ } ++ ++ switch (protocol) { + case __constant_htons(ETH_P_IP): + tu_cmd |= E1000_ADVTXD_TUCMD_IPV4; + if (ip_hdr(skb)->protocol == IPPROTO_TCP) + tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP; ++ else if (ip_hdr(skb)->protocol == IPPROTO_SCTP) ++ tu_cmd |= E1000_ADVTXD_TUCMD_L4T_SCTP; + break; +#ifdef NETIF_F_IPV6_CSUM + case __constant_htons(ETH_P_IPV6): + /* XXX what about other V6 headers?? */ + if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) + tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP; ++ else if (ipv6_hdr(skb)->nexthdr == IPPROTO_SCTP) ++ tu_cmd |= E1000_ADVTXD_TUCMD_L4T_SCTP; + break; +#endif + default: + if (unlikely(net_ratelimit())) { -+ DPRINTK(PROBE, WARNING, ++ dev_warn(&pdev->dev, + "partial checksum but proto=%x!\n", + skb->protocol); + } @@ -20578,13 +18649,10 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + context_desc->type_tucmd_mlhl = cpu_to_le32(tu_cmd); + context_desc->seqnum_seed = 0; -+ if (adapter->flags & IGB_FLAG_NEED_CTX_IDX) -+ context_desc->mss_l4len_idx = -+ cpu_to_le32(tx_ring->queue_index << 4); -+ else -+ context_desc->mss_l4len_idx = 0; ++ context_desc->mss_l4len_idx = cpu_to_le32(tx_ring->ctx_idx); + + buffer_info->time_stamp = jiffies; ++ buffer_info->next_to_watch = i; + buffer_info->dma = 0; + + i++; @@ -20594,17 +18662,14 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + return TRUE; + } -+ -+ + return FALSE; +} + +#define IGB_MAX_TXD_PWR 16 +#define IGB_MAX_DATA_PER_TXD (1<length = len; + /* set time_stamp *before* dma to help avoid a possible race */ + buffer_info->time_stamp = jiffies; -+ -+ buffer_info->dma = -+ pci_map_single(adapter->pdev, skb->data, len, ++ buffer_info->next_to_watch = i; ++ buffer_info->dma = pci_map_single(tx_ring->pdev, skb->data, len, + PCI_DMA_TODEVICE); -+ + count++; -+ i++; -+ if (i == tx_ring->count) -+ i = 0; + + for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) { + struct skb_frag_struct *frag; @@ -20634,38 +18694,38 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + frag = &skb_shinfo(skb)->frags[f]; + len = frag->size; + ++ i++; ++ if (i == tx_ring->count) ++ i = 0; ++ + buffer_info = &tx_ring->buffer_info[i]; + BUG_ON(len >= IGB_MAX_DATA_PER_TXD); + buffer_info->length = len; + buffer_info->time_stamp = jiffies; -+ buffer_info->dma = -+ pci_map_page(adapter->pdev, -+ frag->page, -+ frag->page_offset, -+ len, -+ PCI_DMA_TODEVICE); ++ buffer_info->next_to_watch = i; ++ buffer_info->page_dma = pci_map_page(tx_ring->pdev, ++ frag->page, ++ frag->page_offset, ++ len, ++ PCI_DMA_TODEVICE); + + count++; -+ i++; -+ if (i == tx_ring->count) -+ i = 0; + } + -+ i = (i == 0) ? tx_ring->count - 1 : i - 1; + tx_ring->buffer_info[i].skb = skb; ++ tx_ring->buffer_info[first].next_to_watch = i; + + return count; +} + -+static inline void igb_tx_queue_adv(struct igb_adapter *adapter, -+ struct igb_ring *tx_ring, ++static inline void igb_tx_queue_adv(struct igb_ring *tx_ring, + int tx_flags, int count, u32 paylen, + u8 hdr_len) +{ -+ union e1000_adv_tx_desc *tx_desc = NULL; ++ union e1000_adv_tx_desc *tx_desc; + struct igb_buffer *buffer_info; + u32 olinfo_status = 0, cmd_type_len; -+ unsigned int i; ++ unsigned int i = tx_ring->next_to_use; + + cmd_type_len = (E1000_ADVTXD_DTYP_DATA | E1000_ADVTXD_DCMD_IFCS | + E1000_ADVTXD_DCMD_DEXT); @@ -20673,6 +18733,9 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + if (tx_flags & IGB_TX_FLAGS_VLAN) + cmd_type_len |= E1000_ADVTXD_DCMD_VLE; + ++ if (tx_flags & IGB_TX_FLAGS_TSTAMP) ++ cmd_type_len |= E1000_ADVTXD_MAC_TSTAMP; ++ + if (tx_flags & IGB_TX_FLAGS_TSO) { + cmd_type_len |= E1000_ADVTXD_DCMD_TSE; + @@ -20687,27 +18750,28 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + olinfo_status |= E1000_TXD_POPTS_TXSM << 8; + } + -+ if ((adapter->flags & IGB_FLAG_NEED_CTX_IDX) && -+ (tx_flags & (IGB_TX_FLAGS_CSUM | -+ IGB_TX_FLAGS_TSO | IGB_TX_FLAGS_VLAN))) -+ olinfo_status |= tx_ring->queue_index << 4; ++ if (tx_flags & (IGB_TX_FLAGS_CSUM | IGB_TX_FLAGS_TSO | ++ IGB_TX_FLAGS_VLAN)) ++ olinfo_status |= tx_ring->ctx_idx; + + olinfo_status |= ((paylen - hdr_len) << E1000_ADVTXD_PAYLEN_SHIFT); + -+ i = tx_ring->next_to_use; -+ while (count--) { ++ do { + buffer_info = &tx_ring->buffer_info[i]; + tx_desc = E1000_TX_DESC_ADV(*tx_ring, i); -+ tx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma); ++ tx_desc->read.buffer_addr = buffer_info->dma ? ++ cpu_to_le64(buffer_info->dma) : ++ cpu_to_le64(buffer_info->page_dma); + tx_desc->read.cmd_type_len = + cpu_to_le32(cmd_type_len | buffer_info->length); + tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status); ++ count--; + i++; + if (i == tx_ring->count) + i = 0; -+ } ++ } while (count > 0); + -+ tx_desc->read.cmd_type_len |= cpu_to_le32(adapter->txd_cmd); ++ tx_desc->read.cmd_type_len |= cpu_to_le32(IGB_ADVTXD_DCMD); + /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, @@ -20715,7 +18779,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + wmb(); + + tx_ring->next_to_use = i; -+ writel(i, adapter->hw.hw_addr + tx_ring->tail); ++ writel(i, tx_ring->tail); + /* we need this if more than one processor can write to our tail + * at a time, it syncronizes IO on IA64/Altix systems */ + mmiowb(); @@ -20724,8 +18788,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +static int __igb_maybe_stop_tx(struct net_device *netdev, + struct igb_ring *tx_ring, int size) +{ -+ struct igb_adapter *adapter = netdev_priv(netdev); -+ + if (netif_is_multiqueue(netdev)) + netif_stop_subqueue(netdev, tx_ring->queue_index); + else @@ -20746,7 +18808,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + netif_wake_subqueue(netdev, tx_ring->queue_index); + else + netif_wake_queue(netdev); -+ ++adapter->restart_queue; ++ ++tx_ring->restart_queue; + return 0; +} + @@ -20760,17 +18822,18 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + +#define TXD_USE_COUNT(S) (((S) >> (IGB_MAX_TXD_PWR)) + 1) + -+static int igb_xmit_frame_ring_adv(struct sk_buff *skb, -+ struct net_device *netdev, -+ struct igb_ring *tx_ring) ++static netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb, ++ struct net_device *netdev, ++ struct igb_ring *tx_ring) +{ + struct igb_adapter *adapter = netdev_priv(netdev); ++ unsigned int first; + unsigned int tx_flags = 0; -+ unsigned int len; + u8 hdr_len = 0; + int tso = 0; -+ -+ len = skb_headlen(skb); ++#ifdef SIOCSHWTSTAMP ++ union skb_shared_tx *shtx = skb_tx(skb); ++#endif + + if (test_bit(__IGB_DOWN, &adapter->state)) { + dev_kfree_skb_any(skb); @@ -20783,16 +18846,22 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + } + + /* need: 1 descriptor per page, -+ * + 2 desc gap to keep tail from touching head, -+ * + 1 desc for skb->data, -+ * + 1 desc for context descriptor, -+ * otherwise try next time */ ++ * + 2 desc gap to keep tail from touching head, ++ * + 1 desc for skb->data, ++ * + 1 desc for context descriptor, ++ * otherwise try next time */ + if (igb_maybe_stop_tx(netdev, tx_ring, skb_shinfo(skb)->nr_frags + 4)) { + /* this is a hard error */ + return NETDEV_TX_BUSY; + } -+ skb_orphan(skb); + ++#ifdef SIOCSHWTSTAMP ++ if (unlikely(shtx->hardware)) { ++ shtx->in_progress = 1; ++ tx_flags |= IGB_TX_FLAGS_TSTAMP; ++ } ++ ++#endif + if (adapter->vlgrp && vlan_tx_tag_present(skb)) { + tx_flags |= IGB_TX_FLAGS_VLAN; + tx_flags |= (vlan_tx_tag_get(skb) << IGB_TX_FLAGS_VLAN_SHIFT); @@ -20801,24 +18870,26 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + if (skb->protocol == htons(ETH_P_IP)) + tx_flags |= IGB_TX_FLAGS_IPV4; + ++ first = tx_ring->next_to_use; +#ifdef NETIF_F_TSO -+ tso = skb_is_gso(skb) ? igb_tso_adv(adapter, tx_ring, skb, tx_flags, -+ &hdr_len) : 0; -+#endif ++ if (skb_is_gso(skb)) { ++ tso = igb_tso_adv(tx_ring, skb, tx_flags, &hdr_len); + -+ if (tso < 0) { -+ dev_kfree_skb_any(skb); -+ return NETDEV_TX_OK; ++ if (tso < 0) { ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++ } + } + -+ if (tso) { ++#endif ++ if (tso) + tx_flags |= IGB_TX_FLAGS_TSO; -+ } else if (igb_tx_csum_adv(adapter, tx_ring, skb, tx_flags)) -+ if (skb->ip_summed == CHECKSUM_PARTIAL) -+ tx_flags |= IGB_TX_FLAGS_CSUM; ++ else if (igb_tx_csum_adv(tx_ring, skb, tx_flags) && ++ (skb->ip_summed == CHECKSUM_PARTIAL)) ++ tx_flags |= IGB_TX_FLAGS_CSUM; + -+ igb_tx_queue_adv(adapter, tx_ring, tx_flags, -+ igb_tx_map_adv(adapter, tx_ring, skb), ++ igb_tx_queue_adv(tx_ring, tx_flags, ++ igb_tx_map_adv(tx_ring, skb, first), + skb->len, hdr_len); + + netdev->trans_start = jiffies; @@ -20829,7 +18900,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + return NETDEV_TX_OK; +} + -+static int igb_xmit_frame_adv(struct sk_buff *skb, struct net_device *netdev) ++static netdev_tx_t igb_xmit_frame_adv(struct sk_buff *skb, struct net_device *netdev) +{ + struct igb_adapter *adapter = netdev_priv(netdev); + struct igb_ring *tx_ring; @@ -20842,20 +18913,17 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + tx_ring = &adapter->tx_ring[0]; +#endif + -+ + /* This goes back to the question of how to logically map a tx queue + * to a flow. Right now, performance is impacted slightly negatively + * if using multiple tx queues. If the stack breaks away from a + * single qdisc implementation, we can look at this again. */ -+ return (igb_xmit_frame_ring_adv(skb, netdev, tx_ring)); ++ return igb_xmit_frame_ring_adv(skb, netdev, tx_ring); +} + -+ +/** + * igb_tx_timeout - Respond to a Tx Hang + * @netdev: network interface device structure + **/ -+ +static void igb_tx_timeout(struct net_device *netdev) +{ + struct igb_adapter *adapter = netdev_priv(netdev); @@ -20863,9 +18931,10 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + /* Do the reset outside of interrupt context */ + adapter->tx_timeout_count++; ++ + schedule_work(&adapter->reset_task); -+ E1000_WRITE_REG(hw, E1000_EICS, adapter->eims_enable_mask & -+ ~(E1000_EIMS_TCP_TIMER | E1000_EIMS_OTHER)); ++ E1000_WRITE_REG(hw, E1000_EICS, ++ (adapter->eims_enable_mask & ~adapter->eims_other)); +} + +static void igb_reset_task(struct work_struct *work) @@ -20883,9 +18952,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * Returns the address of the device statistics structure. + * The statistics are actually updated from the timer callback. + **/ -+ -+static struct net_device_stats * -+igb_get_stats(struct net_device *netdev) ++static struct net_device_stats *igb_get_stats(struct net_device *netdev) +{ + struct igb_adapter *adapter = netdev_priv(netdev); + @@ -20900,11 +18967,12 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * + * Returns 0 on success, negative on failure + **/ -+ +static int igb_change_mtu(struct net_device *netdev, int new_mtu) +{ + struct igb_adapter *adapter = netdev_priv(netdev); + int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; ++ u32 rx_buffer_len, i; ++ u16 rx_ps_hdr_size = 0; + + if ((new_mtu < 68) || (max_frame > MAX_JUMBO_FRAME_SIZE)) { + DPRINTK(PROBE, ERR, "Invalid MTU setting\n"); @@ -20920,49 +18988,67 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) + msleep(1); + -+ /* igb_down has a dependency on max_frame_size */ -+ adapter->max_frame_size = max_frame; -+ if (netif_running(netdev)) -+ igb_down(adapter); -+ -+ /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN ++ /* NOTE: dev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN + * means we reserve 2 more, this pushes us to allocate from the next + * larger slab size. + * i.e. RXBUFFER_2048 --> size-4096 slab + */ + -+ if (max_frame <= IGB_RXBUFFER_256) -+ adapter->rx_buffer_len = IGB_RXBUFFER_256; -+ else if (max_frame <= IGB_RXBUFFER_512) -+ adapter->rx_buffer_len = IGB_RXBUFFER_512; -+ else if (max_frame <= IGB_RXBUFFER_1024) -+ adapter->rx_buffer_len = IGB_RXBUFFER_1024; ++ /* igb_down has a dependency on max_frame_size */ ++ adapter->max_frame_size = max_frame; ++ ++ if (max_frame <= IGB_RXBUFFER_1024) ++ rx_buffer_len = IGB_RXBUFFER_1024; + else if (max_frame <= IGB_RXBUFFER_2048) -+ adapter->rx_buffer_len = IGB_RXBUFFER_2048; ++ rx_buffer_len = IGB_RXBUFFER_2048; +#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT + else +#if (PAGE_SIZE / 2) > IGB_RXBUFFER_16384 -+ adapter->rx_buffer_len = IGB_RXBUFFER_16384; ++ rx_buffer_len = IGB_RXBUFFER_16384; +#else -+ adapter->rx_buffer_len = PAGE_SIZE / 2; ++ rx_buffer_len = PAGE_SIZE / 2; +#endif +#else + else if (max_frame <= IGB_RXBUFFER_4096) -+ adapter->rx_buffer_len = IGB_RXBUFFER_4096; ++ rx_buffer_len = IGB_RXBUFFER_4096; + else if (max_frame <= IGB_RXBUFFER_8192) -+ adapter->rx_buffer_len = IGB_RXBUFFER_8192; -+ else if (max_frame <= IGB_RXBUFFER_16384) -+ adapter->rx_buffer_len = IGB_RXBUFFER_16384; ++ rx_buffer_len = IGB_RXBUFFER_8192; ++ else ++ rx_buffer_len = IGB_RXBUFFER_16384; +#endif ++ + /* adjust allocation if LPE protects us, and we aren't using SBP */ + if ((max_frame == ETH_FRAME_LEN + ETH_FCS_LEN) || + (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)) -+ adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE; ++ rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE; ++ ++ if (netif_running(netdev)) ++ igb_down(adapter); + + DPRINTK(PROBE, INFO, "changing MTU from %d to %d\n", + netdev->mtu, new_mtu); + netdev->mtu = new_mtu; + ++#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT ++ /* 82575 and greater support packet-split where the protocol ++ * header is placed in skb->data and the packet data is ++ * placed in pages hanging off of skb_shinfo(skb)->nr_frags. ++ * In the case of a non-split, skb->data is linearly filled, ++ * followed by the page buffers. Therefore, skb->data is ++ * sized to hold the largest protocol header. ++ */ ++ /* allocations using alloc_page take too long for regular MTU ++ * so only enable packet split for jumbo frames */ ++ if (new_mtu > ETH_DATA_LEN) ++ rx_ps_hdr_size = IGB_RXBUFFER_128; ++#endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ ++ ++ for (i = 0; i < adapter->num_rx_queues; i++) { ++ struct igb_ring *rx_ring = &adapter->rx_ring[i]; ++ rx_ring->rx_buffer_len = rx_buffer_len; ++ rx_ring->rx_ps_hdr_size = rx_ps_hdr_size; ++ } ++ + if (netif_running(netdev)) + igb_up(adapter); + else @@ -20999,6 +19085,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + return; +#endif + ++ /* read stats registers */ + adapter->stats.crcerrs += E1000_READ_REG(hw, E1000_CRCERRS); + adapter->stats.gprc += E1000_READ_REG(hw, E1000_GPRC); + adapter->stats.gorc += E1000_READ_REG(hw, E1000_GORCL); @@ -21093,232 +19180,643 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + adapter->net_stats.tx_window_errors = adapter->stats.latecol; + adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs; + -+ /* Tx Dropped needs to be maintained elsewhere */ ++ /* Tx Dropped needs to be maintained elsewhere */ ++ ++ /* Phy Stats */ ++ if (hw->phy.media_type == e1000_media_type_copper) { ++ if ((adapter->link_speed == SPEED_1000) && ++ (!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) { ++ phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK; ++ adapter->phy_stats.idle_errors += phy_tmp; ++ } ++ } ++ ++ /* Management Stats */ ++ adapter->stats.mgptc += E1000_READ_REG(hw, E1000_MGTPTC); ++ adapter->stats.mgprc += E1000_READ_REG(hw, E1000_MGTPRC); ++ adapter->stats.mgpdc += E1000_READ_REG(hw, E1000_MGTPDC); ++} ++ ++static irqreturn_t igb_msix_other(int irq, void *data) ++{ ++ struct igb_adapter *adapter = data; ++ struct e1000_hw *hw = &adapter->hw; ++ u32 icr = E1000_READ_REG(hw, E1000_ICR); ++ /* reading ICR causes bit 31 of EICR to be cleared */ ++ ++ if (icr & E1000_ICR_DOUTSYNC) { ++ /* HW is reporting DMA is out of sync */ ++ adapter->stats.doosync++; ++ } ++ ++ /* Check for a mailbox event */ ++ if (icr & E1000_ICR_VMMB) ++ igb_msg_task(adapter); ++ ++ if (!(icr & E1000_ICR_LSC)) ++ goto no_link_interrupt; ++ hw->mac.get_link_status = 1; ++ /* guard against interrupt when we're going down */ ++ if (!test_bit(__IGB_DOWN, &adapter->state)) ++ mod_timer(&adapter->watchdog_timer, jiffies + 1); ++ ++no_link_interrupt: ++ if (adapter->vfs_allocated_count) ++ E1000_WRITE_REG(hw, E1000_IMS, ++ E1000_IMS_LSC | ++ E1000_IMS_VMMB | ++ E1000_IMS_DOUTSYNC); ++ else ++ E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_LSC | E1000_IMS_DOUTSYNC); ++ E1000_WRITE_REG(hw, E1000_EIMS, adapter->eims_other); ++ ++ return IRQ_HANDLED; ++} ++ ++ ++static void igb_write_itr(struct igb_q_vector *q_vector) ++{ ++ u32 itr_val = q_vector->itr_val & 0x7FFC; ++ ++ if (!q_vector->set_itr) ++ return; ++ ++ if (!itr_val) ++ itr_val = 0x4; ++ ++ if (q_vector->itr_shift) ++ itr_val |= itr_val << q_vector->itr_shift; ++ else ++ itr_val |= 0x8000000; ++ ++ writel(itr_val, q_vector->itr_register); ++ q_vector->set_itr = 0; ++} ++ ++static irqreturn_t igb_msix_ring(int irq, void *data) ++{ ++ struct igb_q_vector *q_vector = data; ++ ++ /* Write the ITR value calculated from the previous interrupt. */ ++ igb_write_itr(q_vector); ++ ++ napi_schedule(&q_vector->napi); ++ ++ return IRQ_HANDLED; ++} ++ ++#ifdef IGB_DCA ++static void igb_update_dca(struct igb_q_vector *q_vector) ++{ ++ struct igb_adapter *adapter = q_vector->adapter; ++ struct e1000_hw *hw = &adapter->hw; ++ int cpu = get_cpu(); ++ ++ if (q_vector->cpu == cpu) ++ goto out_no_update; ++ ++ if (q_vector->tx_ring) { ++ int q = q_vector->tx_ring->reg_idx; ++ u32 dca_txctrl = E1000_READ_REG(hw, E1000_DCA_TXCTRL(q)); ++ if (hw->mac.type == e1000_82575) { ++ dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK; ++ dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); ++ } else { ++ dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK_82576; ++ dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) << ++ E1000_DCA_TXCTRL_CPUID_SHIFT_82576; ++ } ++ dca_txctrl |= E1000_DCA_TXCTRL_DESC_DCA_EN; ++ E1000_WRITE_REG(hw, E1000_DCA_TXCTRL(q), dca_txctrl); ++ } ++ if (q_vector->rx_ring) { ++ int q = q_vector->rx_ring->reg_idx; ++ u32 dca_rxctrl = E1000_READ_REG(hw, E1000_DCA_RXCTRL(q)); ++ if (hw->mac.type == e1000_82575) { ++ dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK; ++ dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); ++ } else { ++ dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK_82576; ++ dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) << ++ E1000_DCA_RXCTRL_CPUID_SHIFT_82576; ++ } ++ dca_rxctrl |= E1000_DCA_RXCTRL_DESC_DCA_EN; ++ dca_rxctrl |= E1000_DCA_RXCTRL_HEAD_DCA_EN; ++ dca_rxctrl |= E1000_DCA_RXCTRL_DATA_DCA_EN; ++ E1000_WRITE_REG(hw, E1000_DCA_RXCTRL(q), dca_rxctrl); ++ } ++ q_vector->cpu = cpu; ++out_no_update: ++ put_cpu(); ++} ++ ++static void igb_setup_dca(struct igb_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ int i; ++ ++ if (!(adapter->flags & IGB_FLAG_DCA_ENABLED)) ++ return; ++ ++ /* Always use CB2 mode, difference is masked in the CB driver. */ ++ E1000_WRITE_REG(hw, E1000_DCA_CTRL, 2); ++ ++ for (i = 0; i < adapter->num_q_vectors; i++) { ++ struct igb_q_vector *q_vector = adapter->q_vector[i]; ++ q_vector->cpu = -1; ++ igb_update_dca(q_vector); ++ } ++} ++ ++static int __igb_notify_dca(struct device *dev, void *data) ++{ ++ struct net_device *netdev = dev_get_drvdata(dev); ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ struct e1000_hw *hw = &adapter->hw; ++ unsigned long event = *(unsigned long *)data; ++ ++ switch (event) { ++ case DCA_PROVIDER_ADD: ++ /* if already enabled, don't do it again */ ++ if (adapter->flags & IGB_FLAG_DCA_ENABLED) ++ break; ++ if (dca_add_requester(dev) == E1000_SUCCESS) { ++ adapter->flags |= IGB_FLAG_DCA_ENABLED; ++ DPRINTK(PROBE, INFO, "DCA enabled\n"); ++ igb_setup_dca(adapter); ++ break; ++ } ++ /* Fall Through since DCA is disabled. */ ++ case DCA_PROVIDER_REMOVE: ++ if (adapter->flags & IGB_FLAG_DCA_ENABLED) { ++ /* without this a class_device is left ++ * hanging around in the sysfs model */ ++ dca_remove_requester(dev); ++ DPRINTK(PROBE, INFO, "DCA disabled\n"); ++ adapter->flags &= ~IGB_FLAG_DCA_ENABLED; ++ E1000_WRITE_REG(hw, E1000_DCA_CTRL, 1); ++ } ++ break; ++ } ++ ++ return E1000_SUCCESS; ++} ++ ++static int igb_notify_dca(struct notifier_block *nb, unsigned long event, ++ void *p) ++{ ++ int ret_val; ++ ++ ret_val = driver_for_each_device(&igb_driver.driver, NULL, &event, ++ __igb_notify_dca); ++ ++ return ret_val ? NOTIFY_BAD : NOTIFY_DONE; ++} ++#endif /* IGB_DCA */ ++ ++static void igb_ping_all_vfs(struct igb_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 ping; ++ int i; ++ ++ for (i = 0 ; i < adapter->vfs_allocated_count; i++) { ++ ping = E1000_PF_CONTROL_MSG; ++ if (adapter->vf_data[i].flags & IGB_VF_FLAG_CTS) ++ ping |= E1000_VT_MSGTYPE_CTS; ++ e1000_write_mbx(hw, &ping, 1, i); ++ } ++} ++ ++static int igb_set_vf_promisc(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) ++{ ++ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 vmolr = E1000_READ_REG(hw, E1000_VMOLR(vf)); ++ struct vf_data_storage *vf_data = &adapter->vf_data[vf]; ++ ++ vf_data->flags |= ~(IGB_VF_FLAG_UNI_PROMISC | ++ IGB_VF_FLAG_MULTI_PROMISC); ++ vmolr &= ~(E1000_VMOLR_ROPE | E1000_VMOLR_ROMPE | E1000_VMOLR_MPME); ++ ++#ifdef IGB_ENABLE_VF_PROMISC ++ if (*msgbuf & E1000_VF_SET_PROMISC_UNICAST) { ++ vmolr |= E1000_VMOLR_ROPE; ++ vf_data->flags |= IGB_VF_FLAG_UNI_PROMISC; ++ *msgbuf &= ~E1000_VF_SET_PROMISC_UNICAST; ++ } ++#endif ++ if (*msgbuf & E1000_VF_SET_PROMISC_MULTICAST) { ++ vmolr |= E1000_VMOLR_MPME; ++ *msgbuf &= ~E1000_VF_SET_PROMISC_MULTICAST; ++ } else { ++ /* ++ * if we have hashes and we are clearing a multicast promisc ++ * flag we need to write the hashes to the MTA as this step ++ * was previously skipped ++ */ ++ if (vf_data->num_vf_mc_hashes > 30) { ++ vmolr |= E1000_VMOLR_MPME; ++ } else if (vf_data->num_vf_mc_hashes) { ++ int j; ++ vmolr |= E1000_VMOLR_ROMPE; ++ for (j = 0; j < vf_data->num_vf_mc_hashes; j++) ++ hw->mac.ops.mta_set(hw, ++ vf_data->vf_mc_hashes[j]); ++ } ++ } ++ ++ E1000_WRITE_REG(hw, E1000_VMOLR(vf), vmolr); ++ ++ /* there are flags left unprocessed, likely not supported */ ++ if (*msgbuf & E1000_VT_MSGINFO_MASK) ++ return -EINVAL; ++ ++ return 0; ++ ++} ++ ++static int igb_set_vf_multicasts(struct igb_adapter *adapter, ++ u32 *msgbuf, u32 vf) ++{ ++ int n = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT; ++ u16 *hash_list = (u16 *)&msgbuf[1]; ++ struct vf_data_storage *vf_data = &adapter->vf_data[vf]; ++ int i; ++ ++ /* salt away the number of multicast addresses assigned ++ * to this VF for later use to restore when the PF multi cast ++ * list changes ++ */ ++ vf_data->num_vf_mc_hashes = n; ++ ++ /* only up to 30 hash values supported */ ++ if (n > 30) ++ n = 30; ++ ++ /* store the hashes for later use */ ++ for (i = 0; i < n; i++) ++ vf_data->vf_mc_hashes[i] = hash_list[i]; + -+ /* Phy Stats */ -+ if (hw->phy.media_type == e1000_media_type_copper) { -+ if ((adapter->link_speed == SPEED_1000) && -+ (!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) { -+ phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK; -+ adapter->phy_stats.idle_errors += phy_tmp; ++ /* Flush and reset the mta with the new values */ ++ igb_set_rx_mode(adapter->netdev); ++ ++ return 0; ++} ++ ++static void igb_restore_vf_multicasts(struct igb_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ struct vf_data_storage *vf_data; ++ int i, j; ++ ++ for (i = 0; i < adapter->vfs_allocated_count; i++) { ++ u32 vmolr = E1000_READ_REG(hw, E1000_VMOLR(i)); ++ vmolr &= ~(E1000_VMOLR_ROMPE | E1000_VMOLR_MPME); ++ ++ vf_data = &adapter->vf_data[i]; ++ ++ if ((vf_data->num_vf_mc_hashes > 30) || ++ (vf_data->flags & IGB_VF_FLAG_MULTI_PROMISC)) { ++ vmolr |= E1000_VMOLR_MPME; ++ } else if (vf_data->num_vf_mc_hashes) { ++ vmolr |= E1000_VMOLR_ROMPE; ++ for (j = 0; j < vf_data->num_vf_mc_hashes; j++) ++ hw->mac.ops.mta_set(hw, ++ vf_data->vf_mc_hashes[j]); + } ++ E1000_WRITE_REG(hw, E1000_VMOLR(i), vmolr); + } -+ -+ /* Management Stats */ -+ adapter->stats.mgptc += E1000_READ_REG(hw, E1000_MGTPTC); -+ adapter->stats.mgprc += E1000_READ_REG(hw, E1000_MGTPRC); -+ adapter->stats.mgpdc += E1000_READ_REG(hw, E1000_MGTPDC); +} + -+static irqreturn_t igb_msix_other(int irq, void *data) ++static void igb_clear_vf_vfta(struct igb_adapter *adapter, u32 vf) +{ -+ struct net_device *netdev = data; -+ struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; ++ u32 pool_mask, reg, vid; ++ u16 vlan_default; ++ int i; + -+ u32 icr = E1000_READ_REG(hw, E1000_ICR); -+ /* reading ICR causes bit 31 of EICR to be cleared */ -+ if (!(icr & E1000_ICR_LSC)) -+ goto no_link_interrupt; -+ hw->mac.get_link_status = 1; -+ /* guard against interrupt when we're going down */ -+ if (!test_bit(__IGB_DOWN, &adapter->state)) -+ mod_timer(&adapter->watchdog_timer, jiffies + 1); ++ pool_mask = 1 << (E1000_VLVF_POOLSEL_SHIFT + vf); + -+no_link_interrupt: -+ E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_LSC); -+ E1000_WRITE_REG(hw, E1000_EIMS, adapter->eims_other); ++ /* Find the vlan filter for this id */ ++ for (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) { ++ reg = E1000_READ_REG(hw, E1000_VLVF(i)); + -+ return IRQ_HANDLED; -+} ++ /* remove the vf from the pool */ ++ reg &= ~pool_mask; ++ ++ /* if pool is empty then remove entry from vfta */ ++ if (!(reg & E1000_VLVF_POOLSEL_MASK) && ++ (reg & E1000_VLVF_VLANID_ENABLE)) { ++ reg = 0; ++ vid = reg & E1000_VLVF_VLANID_MASK; ++ igb_vfta_set(hw, vid, FALSE); ++ } ++ ++ E1000_WRITE_REG(hw, E1000_VLVF(i), reg); ++ } ++ ++ adapter->vf_data[vf].vlans_enabled = 0; + ++ vlan_default = adapter->vf_data[vf].default_vf_vlan_id; ++ if (vlan_default) ++ igb_vlvf_set(adapter, vlan_default, true, vf); ++} + -+#ifdef CONFIG_IGB_SEPARATE_TX_HANDLER -+static irqreturn_t igb_msix_tx(int irq, void *data) ++s32 igb_vlvf_set(struct igb_adapter *adapter, u32 vid, bool add, u32 vf) +{ -+ struct igb_ring *tx_ring = data; -+ struct igb_adapter *adapter = tx_ring->adapter; + struct e1000_hw *hw = &adapter->hw; ++ u32 reg, i; + -+#ifdef IGB_DCA -+ if (adapter->flags & IGB_FLAG_DCA_ENABLED) -+ igb_update_tx_dca(tx_ring); -+#endif ++ /* The vlvf table only exists on 82576 hardware and newer */ ++ if (hw->mac.type < e1000_82576) ++ return -1; + -+ tx_ring->total_bytes = 0; -+ tx_ring->total_packets = 0; ++ /* we only need to do this if VMDq is enabled */ ++ if (!adapter->VMDQ_queues) ++ return -1; + -+ /* auto mask will automatically reenable the interrupt when we write -+ * EICS */ -+ if (!igb_clean_tx_irq(tx_ring)) -+ /* Ring was not completely cleaned, so fire another interrupt */ -+ E1000_WRITE_REG(hw, E1000_EICS, tx_ring->eims_value); -+ else -+ E1000_WRITE_REG(hw, E1000_EIMS, tx_ring->eims_value); ++ /* Find the vlan filter for this id */ ++ for (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) { ++ reg = E1000_READ_REG(hw, E1000_VLVF(i)); ++ if ((reg & E1000_VLVF_VLANID_ENABLE) && ++ vid == (reg & E1000_VLVF_VLANID_MASK)) ++ break; ++ } + -+ return IRQ_HANDLED; -+} -+#endif /* CONFIG_IGB_SEPARATE_TX_HANDLER */ ++ if (add) { ++ if (i == E1000_VLVF_ARRAY_SIZE) { ++ /* Did not find a matching VLAN ID entry that was ++ * enabled. Search for a free filter entry, i.e. ++ * one without the enable bit set ++ */ ++ for (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) { ++ reg = E1000_READ_REG(hw, E1000_VLVF(i)); ++ if (!(reg & E1000_VLVF_VLANID_ENABLE)) ++ break; ++ } ++ } ++ if (i < E1000_VLVF_ARRAY_SIZE) { ++ /* Found an enabled/available entry */ ++ reg |= 1 << (E1000_VLVF_POOLSEL_SHIFT + vf); ++ ++ /* if !enabled we need to set this up in vfta */ ++ if (!(reg & E1000_VLVF_VLANID_ENABLE)) { ++ /* add VID to filter table */ ++ igb_vfta_set(hw, vid, TRUE); ++ reg |= E1000_VLVF_VLANID_ENABLE; ++ } ++ reg &= ~E1000_VLVF_VLANID_MASK; ++ reg |= vid; ++ E1000_WRITE_REG(hw, E1000_VLVF(i), reg); ++ ++ printk(KERN_INFO "VLAN Enabled for vf %d\n", vf); ++ /* do not modify RLPML for PF devices */ ++ if (vf >= adapter->vfs_allocated_count) ++ return E1000_SUCCESS; ++ ++ if (!adapter->vf_data[vf].vlans_enabled) { ++ u32 size; ++ reg = E1000_READ_REG(hw, E1000_VMOLR(vf)); ++ size = reg & E1000_VMOLR_RLPML_MASK; ++ size += 4; ++ reg &= ~E1000_VMOLR_RLPML_MASK; ++ reg |= size; ++ E1000_WRITE_REG(hw, E1000_VMOLR(vf), reg); ++ } + -+static void igb_write_itr(struct igb_ring *ring) -+{ -+ struct e1000_hw *hw = &ring->adapter->hw; -+ if (ring->set_itr) { -+ switch(hw->mac.type) { -+ case e1000_82576: -+ E1000_WRITE_REG(hw, ring->itr_register, -+ ring->itr_val | -+ 0x80000000); -+ break; -+ default: -+ E1000_WRITE_REG(hw, ring->itr_register, -+ ring->itr_val | -+ (ring->itr_val << 16)); -+ break; ++ adapter->vf_data[vf].vlans_enabled++; ++ return E1000_SUCCESS; ++ } ++ } else { ++ if (i < E1000_VLVF_ARRAY_SIZE) { ++ /* remove vf from the pool */ ++ reg &= ~(1 << (E1000_VLVF_POOLSEL_SHIFT + vf)); ++ /* if pool is empty then remove entry from vfta */ ++ if (!(reg & E1000_VLVF_POOLSEL_MASK)) { ++ reg = 0; ++ igb_vfta_set(hw, vid, FALSE); ++ } ++ E1000_WRITE_REG(hw, E1000_VLVF(i), reg); ++ ++ /* do not modify RLPML for PF devices */ ++ if (vf >= adapter->vfs_allocated_count) ++ return E1000_SUCCESS; ++ ++ adapter->vf_data[vf].vlans_enabled--; ++ if (!adapter->vf_data[vf].vlans_enabled) { ++ u32 size; ++ reg = E1000_READ_REG(hw, E1000_VMOLR(vf)); ++ size = reg & E1000_VMOLR_RLPML_MASK; ++ size -= 4; ++ reg &= ~E1000_VMOLR_RLPML_MASK; ++ reg |= size; ++ E1000_WRITE_REG(hw, E1000_VMOLR(vf), reg); ++ } ++ return E1000_SUCCESS; + } -+ ring->set_itr = 0; + } ++ return -1; ++} ++ ++static int igb_set_vf_vlan(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) ++{ ++ int add = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT; ++ int vid = (msgbuf[1] & E1000_VLVF_VLANID_MASK); ++ ++ return igb_vlvf_set(adapter, vid, add, vf); +} + -+static irqreturn_t igb_msix_rx(int irq, void *data) ++static inline void igb_vf_reset_event(struct igb_adapter *adapter, u32 vf) +{ -+ struct igb_ring *rx_ring = data; -+ struct igb_adapter *adapter = rx_ring->adapter; ++ /* clear all flags */ ++ adapter->vf_data[vf].flags = 0; ++ adapter->vf_data[vf].last_nack = jiffies; + -+ igb_write_itr(rx_ring); -+ if (netif_rx_schedule_prep(adapter->netdev, &rx_ring->napi)) { -+ __netif_rx_schedule(adapter->netdev, &rx_ring->napi); ++ /* reset offloads to defaults */ ++ igb_set_vmolr(adapter, vf); + -+#ifdef IGB_DCA -+ if (adapter->flags & IGB_FLAG_DCA_ENABLED) -+ igb_update_rx_dca(rx_ring); -+#endif -+ } -+ return IRQ_HANDLED; ++ /* reset vlans for device */ ++ igb_clear_vf_vfta(adapter, vf); ++ ++ /* reset multicast table array for vf */ ++ adapter->vf_data[vf].num_vf_mc_hashes = 0; ++ ++ /* Flush and reset the mta with the new values */ ++ igb_set_rx_mode(adapter->netdev); +} + -+#ifdef IGB_DCA -+static void igb_update_rx_dca(struct igb_ring *rx_ring) ++static inline void igb_vf_reset_msg(struct igb_adapter *adapter, u32 vf) +{ -+ u32 dca_rxctrl; -+ struct igb_adapter *adapter = rx_ring->adapter; + struct e1000_hw *hw = &adapter->hw; -+ int cpu = get_cpu(); -+ int q = rx_ring->queue_index; ++ unsigned char *vf_mac = adapter->vf_data[vf].vf_mac_addresses; ++ int rar_entry = hw->mac.rar_entry_count - (vf + 1); ++ u32 reg, msgbuf[3]; ++ u8 *addr = (u8 *)(&msgbuf[1]); + -+ if (rx_ring->cpu != cpu) { -+ dca_rxctrl = E1000_READ_REG(hw, E1000_DCA_RXCTRL(q)); -+ if (hw->mac.type == e1000_82576) { -+ dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK_82576; -+ dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) << -+ E1000_DCA_RXCTRL_CPUID_SHIFT; -+ } else { -+ dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK; -+ dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); -+ } -+ dca_rxctrl |= E1000_DCA_RXCTRL_DESC_DCA_EN; -+ dca_rxctrl |= E1000_DCA_RXCTRL_HEAD_DCA_EN; -+ dca_rxctrl |= E1000_DCA_RXCTRL_DATA_DCA_EN; -+ E1000_WRITE_REG(hw, E1000_DCA_RXCTRL(q), dca_rxctrl); -+ rx_ring->cpu = cpu; -+ } -+ put_cpu(); ++ /* process all the same items cleared in a function level reset */ ++ igb_vf_reset_event(adapter, vf); ++ ++ /* set vf mac address */ ++ igb_rar_set_qsel(adapter, vf_mac, rar_entry, vf); ++ ++ /* enable transmit and receive for vf */ ++ reg = E1000_READ_REG(hw, E1000_VFTE); ++ E1000_WRITE_REG(hw, E1000_VFTE, reg | (1 << vf)); ++ reg = E1000_READ_REG(hw, E1000_VFRE); ++ E1000_WRITE_REG(hw, E1000_VFRE, reg | (1 << vf)); ++ ++ adapter->vf_data[vf].flags = IGB_VF_FLAG_CTS; ++ ++ /* reply to reset with ack and vf mac address */ ++ msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_ACK; ++ memcpy(addr, vf_mac, 6); ++ e1000_write_mbx(hw, msgbuf, 3, vf); ++} ++ ++static int igb_set_vf_mac_addr(struct igb_adapter *adapter, u32 *msg, int vf) ++{ ++ unsigned char *addr = (char *)&msg[1]; ++ int err = -1; ++ ++ if (is_valid_ether_addr(addr)) ++ err = igb_set_vf_mac(adapter, vf, addr); ++ ++ return err; +} + -+static void igb_update_tx_dca(struct igb_ring *tx_ring) ++static void igb_rcv_ack_from_vf(struct igb_adapter *adapter, u32 vf) +{ -+ u32 dca_txctrl; -+ struct igb_adapter *adapter = tx_ring->adapter; + struct e1000_hw *hw = &adapter->hw; -+ int cpu = get_cpu(); -+ int q = tx_ring->queue_index; ++ struct vf_data_storage *vf_data = &adapter->vf_data[vf]; ++ u32 msg = E1000_VT_MSGTYPE_NACK; + -+ if (tx_ring->cpu != cpu) { -+ dca_txctrl = E1000_READ_REG(hw, E1000_DCA_TXCTRL(q)); -+ if (hw->mac.type == e1000_82576) { -+ dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK_82576; -+ dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) << -+ E1000_DCA_TXCTRL_CPUID_SHIFT; -+ } else { -+ dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK; -+ dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); -+ } -+ dca_txctrl |= E1000_DCA_TXCTRL_DESC_DCA_EN; -+ E1000_WRITE_REG(hw, E1000_DCA_TXCTRL(q), dca_txctrl); -+ tx_ring->cpu = cpu; ++ /* if device isn't clear to send it shouldn't be reading either */ ++ if (!(vf_data->flags & IGB_VF_FLAG_CTS) && ++ time_after(jiffies, vf_data->last_nack + (2 * HZ))) { ++ e1000_write_mbx(hw, &msg, 1, vf); ++ vf_data->last_nack = jiffies; + } -+ put_cpu(); +} + -+static void igb_setup_dca(struct igb_adapter *adapter) ++static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) +{ -+ int i; ++ u32 msgbuf[E1000_VFMAILBOX_SIZE]; ++ struct e1000_hw *hw = &adapter->hw; ++ struct vf_data_storage *vf_data = &adapter->vf_data[vf]; ++ s32 retval; + -+ if (!(adapter->flags & IGB_FLAG_DCA_ENABLED)) ++ retval = e1000_read_mbx(hw, msgbuf, E1000_VFMAILBOX_SIZE, vf); ++ ++ if (retval) ++ printk(KERN_ERR "Error receiving message from VF\n"); ++ ++ /* this is a message we already processed, do nothing */ ++ if (msgbuf[0] & (E1000_VT_MSGTYPE_ACK | E1000_VT_MSGTYPE_NACK)) + return; + -+ for (i = 0; i < adapter->num_tx_queues; i++) { -+ adapter->tx_ring[i].cpu = -1; -+ igb_update_tx_dca(&adapter->tx_ring[i]); ++ /* ++ * until the vf completes a virtual function reset it should not be ++ * allowed to start any configuration. ++ */ ++ ++ if (msgbuf[0] == E1000_VF_RESET) { ++ igb_vf_reset_msg(adapter, vf); ++ return; + } -+ for (i = 0; i < adapter->num_rx_queues; i++) { -+ adapter->rx_ring[i].cpu = -1; -+ igb_update_rx_dca(&adapter->rx_ring[i]); ++ ++ if (!(vf_data->flags & IGB_VF_FLAG_CTS)) { ++ msgbuf[0] = E1000_VT_MSGTYPE_NACK; ++ if (time_after(jiffies, vf_data->last_nack + (2 * HZ))) { ++ e1000_write_mbx(hw, msgbuf, 1, vf); ++ vf_data->last_nack = jiffies; ++ } ++ return; ++ } ++ ++ switch ((msgbuf[0] & 0xFFFF)) { ++ case E1000_VF_SET_MAC_ADDR: ++#ifndef IGB_DISABLE_VF_MAC_SET ++ retval = igb_set_vf_mac_addr(adapter, msgbuf, vf); ++#else ++ retval = -EINVAL; ++#endif ++ break; ++ case E1000_VF_SET_PROMISC: ++ retval = igb_set_vf_promisc(adapter, msgbuf, vf); ++ break; ++ case E1000_VF_SET_MULTICAST: ++ retval = igb_set_vf_multicasts(adapter, msgbuf, vf); ++ break; ++ case E1000_VF_SET_LPE: ++ retval = igb_set_vf_rlpml(adapter, msgbuf[1], vf); ++ break; ++ case E1000_VF_SET_VLAN: ++ retval = igb_set_vf_vlan(adapter, msgbuf, vf); ++ break; ++ default: ++ printk(KERN_ERR "Unhandled Msg %8.8x\n", msgbuf[0]); ++ retval = -E1000_ERR_MBX; ++ break; + } ++ ++ /* notify the VF of the results of what it sent us */ ++ if (retval) ++ msgbuf[0] |= E1000_VT_MSGTYPE_NACK; ++ else ++ msgbuf[0] |= E1000_VT_MSGTYPE_ACK; ++ ++ msgbuf[0] |= E1000_VT_MSGTYPE_CTS; ++ ++ e1000_write_mbx(hw, msgbuf, 1, vf); +} + -+static int __igb_notify_dca(struct device *dev, void *data) ++static void igb_msg_task(struct igb_adapter *adapter) +{ -+ struct net_device *netdev = dev_get_drvdata(dev); -+ struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; -+ unsigned long event = *(unsigned long *)data; ++ u32 vf; + -+ if (!(adapter->flags & IGB_FLAG_HAS_DCA)) -+ goto out; ++ for (vf = 0; vf < adapter->vfs_allocated_count; vf++) { ++ /* process any reset requests */ ++ if (!e1000_check_for_rst(hw, vf)) ++ igb_vf_reset_event(adapter, vf); + -+ switch (event) { -+ case DCA_PROVIDER_ADD: -+ /* if we're already enabled, don't do it again */ -+ if (adapter->flags & IGB_FLAG_DCA_ENABLED) -+ break; -+ adapter->flags |= IGB_FLAG_DCA_ENABLED; -+ /* Always use CB2 mode, difference is masked -+ * in the CB driver. */ -+ E1000_WRITE_REG(hw, E1000_DCA_CTRL, 2); -+ if (dca_add_requester(dev) == E1000_SUCCESS) { -+ DPRINTK(PROBE, INFO, "DCA enabled\n"); -+ igb_setup_dca(adapter); -+ break; -+ } -+ /* Fall Through since DCA is disabled. */ -+ case DCA_PROVIDER_REMOVE: -+ if (adapter->flags & IGB_FLAG_DCA_ENABLED) { -+ /* without this a class_device is left -+ * hanging around in the sysfs model */ -+ dca_remove_requester(dev); -+ DPRINTK(PROBE, INFO, "DCA disabled\n"); -+ adapter->flags &= ~IGB_FLAG_DCA_ENABLED; -+ E1000_WRITE_REG(hw, E1000_DCA_CTRL, 1); -+ } -+ break; -+ } ++ /* process any messages pending */ ++ if (!e1000_check_for_msg(hw, vf)) ++ igb_rcv_msg_from_vf(adapter, vf); + -+out: -+ return E1000_SUCCESS; ++ /* process any acks */ ++ if (!e1000_check_for_ack(hw, vf)) ++ igb_rcv_ack_from_vf(adapter, vf); ++ } +} + -+static int igb_notify_dca(struct notifier_block *nb, unsigned long event, -+ void *p) ++/** ++ * igb_set_uta - Set unicast filter table address ++ * @adapter: board private structure ++ * ++ * The unicast table address is a register array of 32-bit registers. ++ * The table is meant to be used in a way similar to how the MTA is used ++ * however due to certain limitations in the hardware it is necessary to ++ * set all the hash bits to 1 and use the VMOLR ROPE bit as a promiscous ++ * enable bit to allow vlan tag stripping when promiscous mode is enabled ++ **/ ++static void igb_set_uta(struct igb_adapter *adapter) +{ -+ int ret_val; ++ struct e1000_hw *hw = &adapter->hw; ++ int i; + -+ ret_val = driver_for_each_device(&igb_driver.driver, NULL, &event, -+ __igb_notify_dca); ++ /* The UTA table only exists on 82576 hardware and newer */ ++ if (hw->mac.type < e1000_82576) ++ return; + -+ return ret_val ? NOTIFY_BAD : NOTIFY_DONE; ++ /* we only need to do this if VMDq is enabled */ ++ if (!adapter->VMDQ_queues) ++ return; ++ ++ for (i = 0; i < hw->mac.uta_reg_count; i++) ++ E1000_WRITE_REG_ARRAY(hw, E1000_UTA, i, ~0); +} -+#endif /* IGB_DCA */ + +/** + * igb_intr_msi - Interrupt Handler @@ -21327,13 +19825,18 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + **/ +static irqreturn_t igb_intr_msi(int irq, void *data) +{ -+ struct net_device *netdev = data; -+ struct igb_adapter *adapter = netdev_priv(netdev); ++ struct igb_adapter *adapter = data; ++ struct igb_q_vector *q_vector = adapter->q_vector[0]; + struct e1000_hw *hw = &adapter->hw; + /* read ICR disables interrupts using IAM */ + u32 icr = E1000_READ_REG(hw, E1000_ICR); + -+ igb_write_itr(adapter->rx_ring); ++ igb_write_itr(q_vector); ++ ++ if (icr & E1000_ICR_DOUTSYNC) { ++ /* HW is reporting DMA is out of sync */ ++ adapter->stats.doosync++; ++ } + + if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { + hw->mac.get_link_status = 1; @@ -21341,7 +19844,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + -+ netif_rx_schedule(netdev, &adapter->rx_ring[0].napi); ++ napi_schedule(&q_vector->napi); + + return IRQ_HANDLED; +} @@ -21351,27 +19854,28 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * @irq: interrupt number + * @data: pointer to a network interface device structure + **/ -+ +static irqreturn_t igb_intr(int irq, void *data) +{ -+ struct net_device *netdev = data; -+ struct igb_adapter *adapter = netdev_priv(netdev); ++ struct igb_adapter *adapter = data; ++ struct igb_q_vector *q_vector = adapter->q_vector[0]; + struct e1000_hw *hw = &adapter->hw; + /* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No + * need for the IMC write */ + u32 icr = E1000_READ_REG(hw, E1000_ICR); -+ u32 eicr = 0; + if (!icr) + return IRQ_NONE; /* Not our interrupt */ + -+ igb_write_itr(adapter->rx_ring); ++ igb_write_itr(q_vector); + + /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is + * not set, then the adapter didn't send an interrupt */ + if (!(icr & E1000_ICR_INT_ASSERTED)) + return IRQ_NONE; + -+ eicr = E1000_READ_REG(hw, E1000_EICR); ++ if (icr & E1000_ICR_DOUTSYNC) { ++ /* HW is reporting DMA is out of sync */ ++ adapter->stats.doosync++; ++ } + + if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { + hw->mac.get_link_status = 1; @@ -21380,136 +19884,154 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + -+ netif_rx_schedule(netdev, &adapter->rx_ring[0].napi); -+ ++ napi_schedule(&q_vector->napi); + + return IRQ_HANDLED; +} + ++static inline void igb_ring_irq_enable(struct igb_q_vector *q_vector) ++{ ++ struct igb_adapter *adapter = q_vector->adapter; ++ struct e1000_hw *hw = &adapter->hw; ++ ++ if (adapter->itr_setting & 3) { ++ if (!adapter->msix_entries) ++ igb_set_itr(adapter); ++ else ++ igb_update_ring_itr(q_vector); ++ } ++ ++ if (!test_bit(__IGB_DOWN, &adapter->state)) { ++ if (adapter->msix_entries) ++ E1000_WRITE_REG(hw, E1000_EIMS, q_vector->eims_value); ++ else ++ igb_irq_enable(adapter); ++ } ++} ++ +/** + * igb_poll - NAPI Rx polling callback + * @napi: napi polling structure + * @budget: count of how many packets we should handle + **/ -+ +static int igb_poll(struct napi_struct *napi, int budget) +{ -+ struct igb_ring *rx_ring = container_of(napi, struct igb_ring, napi); -+ struct igb_adapter *adapter = rx_ring->adapter; -+ struct net_device *netdev = adapter->netdev; -+ int tx_clean_complete, work_done = 0; -+ -+ /* this poll routine only supports one tx and one rx queue */ -+#ifdef IGB_DCA -+ if (adapter->flags & IGB_FLAG_DCA_ENABLED) -+ igb_update_tx_dca(&adapter->tx_ring[0]); -+#endif -+ tx_clean_complete = igb_clean_tx_irq(&adapter->tx_ring[0]); ++ struct igb_q_vector *q_vector = container_of(napi, struct igb_q_vector, napi); ++ int tx_clean_complete = 1, work_done = 0; + +#ifdef IGB_DCA -+ if (adapter->flags & IGB_FLAG_DCA_ENABLED) -+ igb_update_rx_dca(&adapter->rx_ring[0]); ++ if (q_vector->adapter->flags & IGB_FLAG_DCA_ENABLED) ++ igb_update_dca(q_vector); +#endif -+ igb_clean_rx_irq_adv(&adapter->rx_ring[0], &work_done, budget); ++ if (q_vector->tx_ring) ++ tx_clean_complete = igb_clean_tx_irq(q_vector); + -+ /* If no Tx and not enough Rx work done, exit the polling mode */ -+ if ((tx_clean_complete && (work_done == 0)) || !netif_running(netdev)) { -+ netif_rx_complete(netdev, napi); -+ if (adapter->itr_setting & 3) -+ igb_set_itr(adapter); -+ if (!test_bit(__IGB_DOWN, &adapter->state)) -+ igb_irq_enable(adapter); -+ return 0; -+ } ++ if (q_vector->rx_ring) ++ igb_clean_rx_irq_adv(q_vector, &work_done, budget); + + if (!tx_clean_complete) + work_done = budget; + -+ return work_done; -+} -+ -+static int igb_clean_rx_ring_msix(struct napi_struct *napi, int budget) -+{ -+ struct igb_ring *rx_ring = container_of(napi, struct igb_ring, napi); -+ struct igb_adapter *adapter = rx_ring->adapter; -+ struct e1000_hw *hw = &adapter->hw; -+ struct net_device *netdev = adapter->netdev; -+ int tx_clean_complete = 1; -+ int work_done = 0; -+ -+#ifdef IGB_DCA -+ if (adapter->flags & IGB_FLAG_DCA_ENABLED) -+ igb_update_rx_dca(rx_ring); -+#endif -+ igb_clean_rx_irq_adv(rx_ring, &work_done, budget); ++#ifndef HAVE_NETDEV_NAPI_LIST ++ /* if netdev is disabled we need to stop polling */ ++ if (!netif_running(q_vector->adapter->netdev)) ++ work_done = 0; + -+ if (rx_ring->buddy) { -+#ifdef IGB_DCA -+ if (adapter->flags & IGB_FLAG_DCA_ENABLED) -+ igb_update_tx_dca(rx_ring->buddy); +#endif -+ tx_clean_complete = igb_clean_tx_irq(rx_ring->buddy); -+ } -+ + /* If not enough Rx work done, exit the polling mode */ -+ if ((tx_clean_complete && (work_done == 0)) || !netif_running(netdev)) { -+ netif_rx_complete(netdev, napi); -+ if (adapter->itr_setting & 3) { -+ if (adapter->num_rx_queues == 1) -+ igb_set_itr(adapter); -+ else -+ igb_update_ring_itr(rx_ring); -+ } -+ if (!test_bit(__IGB_DOWN, &adapter->state)) -+ E1000_WRITE_REG(hw, E1000_EIMS, rx_ring->eims_value); -+ -+ return 0; ++ if (work_done < budget) { ++ napi_complete(napi); ++ igb_ring_irq_enable(q_vector); + } + -+ if (!tx_clean_complete) -+ work_done = budget; -+ + return work_done; +} + -+static inline u32 get_head(struct igb_ring *tx_ring) ++#ifdef SIOCSHWTSTAMP ++/** ++ * igb_systim_to_hwtstamp - convert system time value to hw timestamp ++ * @adapter: board private structure ++ * @shhwtstamps: timestamp structure to update ++ * @regval: unsigned 64bit system time value. ++ * ++ * We need to convert the system time value stored in the RX/TXSTMP registers ++ * into a hwtstamp which can be used by the upper level timestamping functions ++ */ ++static void igb_systim_to_hwtstamp(struct igb_adapter *adapter, ++ struct skb_shared_hwtstamps *shhwtstamps, ++ u64 regval) ++{ ++ u64 ns; ++ ++ ns = timecounter_cyc2time(&adapter->clock, regval); ++ timecompare_update(&adapter->compare, ns); ++ memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps)); ++ shhwtstamps->hwtstamp = ns_to_ktime(ns); ++ shhwtstamps->syststamp = timecompare_transform(&adapter->compare, ns); ++} ++ ++/** ++ * igb_tx_hwtstamp - utility function which checks for TX time stamp ++ * @adapter: board private structure ++ * @skb: packet that was just sent ++ * ++ * If we were asked to do hardware stamping and such a time stamp is ++ * available, then it must have been for this skb here because we only ++ * allow only one such packet into the queue. ++ */ ++static void igb_tx_hwtstamp(struct igb_adapter *adapter, struct sk_buff *skb) +{ -+ void *end = (struct e1000_tx_desc *)tx_ring->desc + tx_ring->count; -+ return le32_to_cpu(*(volatile __le32 *)end); ++ union skb_shared_tx *shtx = skb_tx(skb); ++ struct e1000_hw *hw = &adapter->hw; ++ struct skb_shared_hwtstamps shhwtstamps; ++ u64 regval; ++ ++ /* if skb does not support hw timestamp or TX stamp not valid exit */ ++ if (likely(!shtx->hardware) || ++ !(E1000_READ_REG(hw, E1000_TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID)) ++ return; ++ ++ regval = E1000_READ_REG(hw, E1000_TXSTMPL); ++ regval |= (u64)E1000_READ_REG(hw, E1000_TXSTMPH) << 32; ++ ++ igb_systim_to_hwtstamp(adapter, &shhwtstamps, regval); ++ skb_tstamp_tx(skb, &shhwtstamps); +} + ++#endif +/** + * igb_clean_tx_irq - Reclaim resources after transmit completes -+ * @adapter: board private structure ++ * @q_vector: pointer to q_vector containing needed info + * returns TRUE if ring is completely cleaned + **/ -+static bool igb_clean_tx_irq(struct igb_ring *tx_ring) ++static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) +{ -+ struct igb_adapter *adapter = tx_ring->adapter; -+ struct e1000_hw *hw = &adapter->hw; ++ struct igb_adapter *adapter = q_vector->adapter; ++ struct igb_ring *tx_ring = q_vector->tx_ring; + struct net_device *netdev = adapter->netdev; -+ struct e1000_tx_desc *tx_desc; ++ struct e1000_hw *hw = &adapter->hw; + struct igb_buffer *buffer_info; + struct sk_buff *skb; -+ unsigned int i; -+ u32 head, oldhead; -+ unsigned int count = 0; ++ union e1000_adv_tx_desc *tx_desc, *eop_desc; + unsigned int total_bytes = 0, total_packets = 0; -+ bool retval = TRUE; ++ unsigned int i, eop, count = 0; ++ bool cleaned = false; + -+ rmb(); -+ head = get_head(tx_ring); + i = tx_ring->next_to_clean; -+ while (1) { -+ while (i != head) { -+ tx_desc = E1000_TX_DESC(*tx_ring, i); ++ eop = tx_ring->buffer_info[i].next_to_watch; ++ eop_desc = E1000_TX_DESC_ADV(*tx_ring, eop); ++ ++ while ((eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD)) && ++ (count < tx_ring->count)) { ++ for (cleaned = false; !cleaned; count++) { ++ tx_desc = E1000_TX_DESC_ADV(*tx_ring, i); + buffer_info = &tx_ring->buffer_info[i]; ++ cleaned = (i == eop); + skb = buffer_info->skb; + + if (skb) { +#ifdef NETIF_F_TSO + unsigned int segs, bytecount; -+ + /* gso_segs is currently only valid for tcp */ + segs = skb_shinfo(skb)->gso_segs ?: 1; + /* multiply data chunks by size of headers */ @@ -21521,28 +20043,23 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + total_packets++; + total_bytes += skb->len; +#endif ++#ifdef SIOCSHWTSTAMP ++ igb_tx_hwtstamp(adapter, skb); ++#endif + } + -+ igb_unmap_and_free_tx_resource(adapter, buffer_info); ++ igb_unmap_and_free_tx_resource(tx_ring->pdev, ++ buffer_info); ++ tx_desc->wb.status = 0; + + i++; + if (i == tx_ring->count) + i = 0; -+ -+ count++; -+ if (count == tx_ring->count) { -+ retval = FALSE; -+ goto done_cleaning; -+ } + } -+ oldhead = head; -+ rmb(); -+ head = get_head(tx_ring); -+ if (head == oldhead) -+ goto done_cleaning; -+ } /* while (1) */ -+ -+done_cleaning: ++ eop = tx_ring->buffer_info[i].next_to_watch; ++ eop_desc = E1000_TX_DESC_ADV(*tx_ring, eop); ++ } ++ + tx_ring->next_to_clean = i; + + if (unlikely(count && @@ -21552,19 +20069,21 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * sees the new next_to_clean. + */ + smp_mb(); -+#ifdef HAVE_TX_MQ -+ if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) && -+ !(test_bit(__IGB_DOWN, &adapter->state))) { -+ netif_wake_subqueue(netdev, tx_ring->queue_index); -+ ++adapter->restart_queue; -+ } -+#endif -+ if (netif_queue_stopped(netdev) && -+ !(test_bit(__IGB_DOWN, &adapter->state))) { -+ netif_wake_queue(netdev); -+ ++adapter->restart_queue; ++ if (netif_is_multiqueue(netdev)) { ++ if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) && ++ !(test_bit(__IGB_DOWN, &adapter->state))) { ++ netif_wake_subqueue(netdev, tx_ring->queue_index); ++ ++tx_ring->restart_queue; ++ } ++ } else { ++ if (netif_queue_stopped(netdev) && ++ !(test_bit(__IGB_DOWN, &adapter->state))) { ++ netif_wake_queue(netdev); ++ ++tx_ring->restart_queue; ++ } + } + } ++ + if (tx_ring->detect_tx_hung) { + /* Detect a transmit hang in hardware, this serializes the + * check with the clearing of time_stamp and movement of i */ @@ -21575,29 +20094,27 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + && !(E1000_READ_REG(hw, E1000_STATUS) & + E1000_STATUS_TXOFF)) { + -+ tx_desc = E1000_TX_DESC(*tx_ring, i); + /* detected Tx unit hang */ + DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n" -+ " Tx Queue <%lu>\n" ++ " Tx Queue <%d>\n" + " TDH <%x>\n" + " TDT <%x>\n" + " next_to_use <%x>\n" + " next_to_clean <%x>\n" -+ " head (WB) <%x>\n" + "buffer_info[next_to_clean]\n" + " time_stamp <%lx>\n" ++ " next_to_watch <%x>\n" + " jiffies <%lx>\n" + " desc.status <%x>\n", -+ (unsigned long)((tx_ring->queue_index) / -+ sizeof(struct igb_ring)), -+ readl(hw->hw_addr + tx_ring->head), -+ readl(hw->hw_addr + tx_ring->tail), ++ tx_ring->queue_index, ++ readl(tx_ring->head), ++ readl(tx_ring->tail), + tx_ring->next_to_use, + tx_ring->next_to_clean, -+ head, -+ tx_ring->buffer_info[i].time_stamp, ++ tx_ring->buffer_info[eop].time_stamp, ++ eop, + jiffies, -+ tx_desc->upper.fields.status); ++ eop_desc->wb.status); + if (netif_is_multiqueue(netdev)) + netif_stop_subqueue(netdev, + tx_ring->queue_index); @@ -21607,11 +20124,11 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + } + tx_ring->total_bytes += total_bytes; + tx_ring->total_packets += total_packets; -+ tx_ring->tx_stats.packets += total_packets; -+ tx_ring->tx_stats.bytes += total_bytes; ++ tx_ring->stats.bytes += total_bytes; ++ tx_ring->stats.packets += total_packets; + adapter->net_stats.tx_bytes += total_bytes; + adapter->net_stats.tx_packets += total_packets; -+ return retval; ++ return (count < tx_ring->count); +} + +#ifdef IGB_LRO @@ -21645,20 +20162,130 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + return 0; + +} ++ +#endif /* IGB_LRO */ ++/** ++ * igb_alloc_rx_buffers_adv - Replace used receive buffers; packet split ++ * @adapter: address of board private structure ++ **/ ++int igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, int cleaned_count) ++{ ++ struct net_device *netdev = pci_get_drvdata(rx_ring->pdev); ++ union e1000_adv_rx_desc *rx_desc; ++ struct igb_buffer *buffer_info; ++ struct sk_buff *skb; ++ unsigned int i; ++ int bufsz, err = 0; ++ ++ i = rx_ring->next_to_use; ++ buffer_info = &rx_ring->buffer_info[i]; ++ ++#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT ++ if (rx_ring->rx_ps_hdr_size) ++ bufsz = rx_ring->rx_ps_hdr_size; ++ else ++ bufsz = rx_ring->rx_buffer_len; ++#else ++ bufsz = rx_ring->rx_buffer_len; ++#endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ ++ ++ while (cleaned_count--) { ++ rx_desc = E1000_RX_DESC_ADV(*rx_ring, i); ++ ++#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT ++ if (rx_ring->rx_ps_hdr_size && !buffer_info->page_dma) { ++ if (!buffer_info->page) { ++ buffer_info->page = netdev_alloc_page(netdev); ++ if (!buffer_info->page) { ++ err = -ENOMEM; ++ goto no_buffers; ++ } ++ buffer_info->page_offset = 0; ++ } else { ++ buffer_info->page_offset ^= PAGE_SIZE / 2; ++ } ++ buffer_info->page_dma = ++ pci_map_page(rx_ring->pdev, buffer_info->page, ++ buffer_info->page_offset, ++ rx_ring->rx_buffer_len, ++ PCI_DMA_FROMDEVICE); ++ } ++#endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ ++ ++ if (!buffer_info->skb) { ++ skb = netdev_alloc_skb(netdev, bufsz + NET_IP_ALIGN); ++ if (!skb) { ++ err = -ENOMEM; ++ goto no_buffers; ++ } ++ ++ /* Make buffer alignment 2 beyond a 16 byte boundary ++ * this will result in a 16 byte aligned IP header after ++ * the 14 byte MAC header is removed ++ */ ++ skb_reserve(skb, NET_IP_ALIGN); ++ ++ buffer_info->skb = skb; ++ } ++ if (!buffer_info->dma) ++ buffer_info->dma = pci_map_single(rx_ring->pdev, ++ buffer_info->skb->data, ++ bufsz, ++ PCI_DMA_FROMDEVICE); ++ /* Refresh the desc even if buffer_addrs didn't change because ++ * each write-back erases this info. */ ++#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT ++ if (rx_ring->rx_ps_hdr_size) { ++ rx_desc->read.pkt_addr = ++ cpu_to_le64(buffer_info->page_dma); ++ rx_desc->read.hdr_addr = cpu_to_le64(buffer_info->dma); ++ } else { ++ rx_desc->read.pkt_addr = cpu_to_le64(buffer_info->dma); ++ rx_desc->read.hdr_addr = 0; ++ } ++#else ++ rx_desc->read.pkt_addr = cpu_to_le64(buffer_info->dma); ++ rx_desc->read.hdr_addr = 0; ++#endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ ++ ++ i++; ++ if (i == rx_ring->count) ++ i = 0; ++ buffer_info = &rx_ring->buffer_info[i]; ++ } ++ ++no_buffers: ++ if (rx_ring->next_to_use != i) { ++ rx_ring->next_to_use = i; ++ if (i == 0) ++ i = (rx_ring->count - 1); ++ else ++ i--; ++ ++ /* 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, rx_ring->tail); ++ } ++ ++ return err; ++} + +/** + * igb_receive_skb - helper function to handle rx indications -+ * @adapter: board private structure ++ * @ring: pointer to receive ring receving this packet + * @status: descriptor status field as written by hardware + * @rx_desc: receive descriptor containing vlan and type information. + * @skb: pointer to sk_buff to be indicated to stack + **/ +static void igb_receive_skb(struct igb_ring *ring, u8 status, -+ union e1000_adv_rx_desc * rx_desc, ++ union e1000_adv_rx_desc *rx_desc, + struct sk_buff *skb) +{ -+ struct igb_adapter * adapter = ring->adapter; ++ struct igb_q_vector *q_vector = ring->q_vector; ++ struct igb_adapter *adapter = q_vector->adapter; + bool vlan_extracted = (adapter->vlgrp && (status & E1000_RXD_STAT_VP)); + +#ifdef IGB_LRO @@ -21670,50 +20297,106 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + le16_to_cpu(rx_desc->wb.upper.vlan), + rx_desc); + else -+ lro_receive_skb(&ring->lro_mgr,skb, rx_desc); ++ lro_receive_skb(&ring->lro_mgr, skb, rx_desc); + ring->lro_used = TRUE; + } else { +#endif + if (vlan_extracted) -+ vlan_hwaccel_receive_skb(skb, adapter->vlgrp, -+ le16_to_cpu(rx_desc->wb.upper.vlan)); ++ vlan_gro_receive(&q_vector->napi, adapter->vlgrp, ++ le16_to_cpu(rx_desc->wb.upper.vlan), ++ skb); + else + -+ netif_receive_skb(skb); ++ napi_gro_receive(&q_vector->napi, skb); +#ifdef IGB_LRO + } +#endif +} + -+ -+static inline void igb_rx_checksum_adv(struct igb_adapter *adapter, ++static inline void igb_rx_checksum_adv(struct igb_ring *ring, + u32 status_err, struct sk_buff *skb) +{ ++ struct igb_adapter *adapter = ring->q_vector->adapter; + skb->ip_summed = CHECKSUM_NONE; + + /* Ignore Checksum bit is set or checksum is disabled through ethtool */ -+ if ((status_err & E1000_RXD_STAT_IXSM) || !adapter->rx_csum) ++ if (!ring->rx_csum || (status_err & E1000_RXD_STAT_IXSM)) + return; ++ + /* TCP/UDP checksum error bit is set */ + if (status_err & + (E1000_RXDEXT_STATERR_TCPE | E1000_RXDEXT_STATERR_IPE)) { ++ /* ++ * work around errata with sctp packets where the TCPE aka ++ * L4E bit is set incorrectly on 64 byte (60 byte w/o crc) ++ * packets, (aka let the stack check the crc32c) ++ */ ++ if (!((adapter->hw.mac.type >= e1000_82576) && ++ (skb->len == 60))) ++ ring->hw_csum_err++; ++ + /* let the stack verify checksum errors */ -+ adapter->hw_csum_err++; + return; + } + /* It must be a TCP or UDP packet with a valid checksum */ + if (status_err & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + -+ adapter->hw_csum_good++; ++ ring->hw_csum_good++; ++} ++ ++#ifdef SIOCSHWTSTAMP ++static inline void igb_rx_hwtstamp(struct igb_adapter *adapter, u32 staterr, ++ struct sk_buff *skb) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u64 regval; ++ ++ /* ++ * If this bit is set, then the RX registers contain the time stamp. No ++ * other packet will be time stamped until we read these registers, so ++ * read the registers to make them available again. Because only one ++ * packet can be time stamped at a time, we know that the register ++ * values must belong to this one here and therefore we don't need to ++ * compare any of the additional attributes stored for it. ++ * ++ * If nothing went wrong, then it should have a skb_shared_tx that we ++ * can turn into a skb_shared_hwtstamps. ++ */ ++ if (likely(!(staterr & E1000_RXDADV_STAT_TS))) ++ return; ++ if(!(E1000_READ_REG(hw, E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID)) ++ return; ++ ++ regval = E1000_READ_REG(hw, E1000_RXSTMPL); ++ regval |= (u64)E1000_READ_REG(hw, E1000_RXSTMPH) << 32; ++ ++ igb_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval); ++} ++#endif ++#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT ++static inline u16 igb_get_hlen(struct igb_ring *rx_ring, ++ union e1000_adv_rx_desc *rx_desc) ++{ ++ /* HW will not DMA in data larger than the given buffer, even if it ++ * parses the (NFS, of course) header to be larger. In that case, it ++ * fills the header buffer and spills the rest into the page. ++ */ ++ u16 hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.hdr_info) & ++ E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT; ++ if (hlen > rx_ring->rx_ps_hdr_size) ++ hlen = rx_ring->rx_ps_hdr_size; ++ return hlen; +} + -+static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, -+ int *work_done, int work_to_do) ++#endif ++static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector, ++ int *work_done, int budget) +{ -+ struct igb_adapter *adapter = rx_ring->adapter; ++ struct igb_adapter *adapter = q_vector->adapter; + struct net_device *netdev = adapter->netdev; -+ struct pci_dev *pdev = adapter->pdev; ++ struct igb_ring *rx_ring = q_vector->rx_ring; ++ struct pci_dev *pdev = rx_ring->pdev; + union e1000_adv_rx_desc *rx_desc , *next_rxd; + struct igb_buffer *buffer_info , *next_buffer; + struct sk_buff *skb; @@ -21721,75 +20404,64 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + int cleaned_count = 0; + unsigned int total_bytes = 0, total_packets = 0; + unsigned int i; -+#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT -+ u32 length, hlen, staterr; -+#else -+ u32 length, staterr; -+#endif ++ u32 staterr; ++ u16 length; + + i = rx_ring->next_to_clean; ++ buffer_info = &rx_ring->buffer_info[i]; + rx_desc = E1000_RX_DESC_ADV(*rx_ring, i); + staterr = le32_to_cpu(rx_desc->wb.upper.status_error); + + while (staterr & E1000_RXD_STAT_DD) { -+ -+ if (*work_done >= work_to_do) ++ if (*work_done >= budget) + break; + (*work_done)++; + -+ buffer_info = &rx_ring->buffer_info[i]; ++ skb = buffer_info->skb; ++ prefetch(skb->data - NET_IP_ALIGN); ++ buffer_info->skb = NULL; + -+#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT -+ /* HW will not DMA in data larger than the given buffer, even -+ * if it parses the (NFS, of course) header to be larger. In -+ * that case, it fills the header buffer and spills the rest -+ * into the page. -+ */ -+ hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.hdr_info) & -+ E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT; -+ if (hlen > adapter->rx_ps_hdr_size) -+ hlen = adapter->rx_ps_hdr_size; ++ i++; ++ if (i == rx_ring->count) ++ i = 0; + -+#endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ -+ if (staterr & E1000_RXD_STAT_DYNINT) -+ adapter->lli_int++; ++ next_rxd = E1000_RX_DESC_ADV(*rx_ring, i); ++ prefetch(next_rxd); ++ next_buffer = &rx_ring->buffer_info[i]; + + length = le16_to_cpu(rx_desc->wb.upper.length); + cleaned = TRUE; + cleaned_count++; + +#ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT -+ skb = buffer_info->skb; -+ prefetch(skb->data - NET_IP_ALIGN); -+ buffer_info->skb = NULL; + pci_unmap_single(pdev, buffer_info->dma, -+ adapter->rx_buffer_len + -+ NET_IP_ALIGN, ++ rx_ring->rx_buffer_len, + PCI_DMA_FROMDEVICE); ++ buffer_info->dma = 0; + skb_put(skb, length); ++ +#else -+ skb = buffer_info->skb; -+ prefetch(skb->data - NET_IP_ALIGN); -+ buffer_info->skb = NULL; -+ if (!adapter->rx_ps_hdr_size) { ++ if (!rx_ring->rx_ps_hdr_size) { + pci_unmap_single(pdev, buffer_info->dma, -+ adapter->rx_buffer_len + -+ NET_IP_ALIGN, ++ rx_ring->rx_buffer_len, + PCI_DMA_FROMDEVICE); ++ buffer_info->dma = 0; + skb_put(skb, length); + goto send_up; + } + -+ if (!skb_shinfo(skb)->nr_frags) { ++ if (buffer_info->dma) { ++ u16 hlen = igb_get_hlen(rx_ring, rx_desc); + pci_unmap_single(pdev, buffer_info->dma, -+ adapter->rx_ps_hdr_size + NET_IP_ALIGN, ++ rx_ring->rx_ps_hdr_size, + PCI_DMA_FROMDEVICE); ++ buffer_info->dma = 0; + skb_put(skb, hlen); + } + + if (length) { + pci_unmap_page(pdev, buffer_info->page_dma, -+ PAGE_SIZE / 2, ++ rx_ring->rx_buffer_len, + PCI_DMA_FROMDEVICE); + buffer_info->page_dma = 0; + @@ -21798,25 +20470,15 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + buffer_info->page_offset, + length); + -+ if ((adapter->rx_buffer_len > (PAGE_SIZE / 2)) || -+ (page_count(buffer_info->page) != 1)) ++ if (page_count(buffer_info->page) != 1) + buffer_info->page = NULL; + else + get_page(buffer_info->page); + + skb->len += length; + skb->data_len += length; -+ + skb->truesize += length; + } -+send_up: -+#endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ -+ i++; -+ if (i == rx_ring->count) -+ i = 0; -+ next_rxd = E1000_RX_DESC_ADV(*rx_ring, i); -+ prefetch(next_rxd); -+ next_buffer = &rx_ring->buffer_info[i]; + + if (!(staterr & E1000_RXD_STAT_EOP)) { + buffer_info->skb = next_buffer->skb; @@ -21825,170 +20487,67 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + next_buffer->dma = 0; + goto next_desc; + } -+ ++send_up: ++#endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ + if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) { + dev_kfree_skb_irq(skb); + goto next_desc; + } + ++#ifdef SIOCSHWTSTAMP ++ igb_rx_hwtstamp(adapter, staterr, skb); ++#endif + total_bytes += skb->len; + total_packets++; + -+ igb_rx_checksum_adv(adapter, staterr, skb); -+ -+ skb->protocol = eth_type_trans(skb, netdev); -+ -+ igb_receive_skb(rx_ring, staterr, rx_desc, skb); -+ -+ netdev->last_rx = jiffies; -+ -+next_desc: -+ rx_desc->wb.upper.status_error = 0; -+ -+ /* return some buffers to hardware, one at a time is too slow */ -+ if (cleaned_count >= IGB_RX_BUFFER_WRITE) { -+ igb_alloc_rx_buffers_adv(rx_ring, cleaned_count); -+ cleaned_count = 0; -+ } -+ -+ /* use prefetched values */ -+ rx_desc = next_rxd; -+ buffer_info = next_buffer; -+ -+ staterr = le32_to_cpu(rx_desc->wb.upper.status_error); -+ } -+ -+ rx_ring->next_to_clean = i; -+ cleaned_count = IGB_DESC_UNUSED(rx_ring); ++ igb_rx_checksum_adv(rx_ring, staterr, skb); + -+#ifdef IGB_LRO -+ if (rx_ring->lro_used) { -+ lro_flush_all(&rx_ring->lro_mgr); -+ rx_ring->lro_used = FALSE; -+ } ++#ifndef ETH_TYPE_TRANS_SETS_DEV ++ skb->dev = netdev; +#endif ++ skb->protocol = eth_type_trans(skb, netdev); + -+ if (cleaned_count) -+ igb_alloc_rx_buffers_adv(rx_ring, cleaned_count); -+ -+ rx_ring->total_packets += total_packets; -+ rx_ring->total_bytes += total_bytes; -+ rx_ring->rx_stats.packets += total_packets; -+ rx_ring->rx_stats.bytes += total_bytes; -+ adapter->net_stats.rx_bytes += total_bytes; -+ adapter->net_stats.rx_packets += total_packets; -+ return cleaned; -+} -+ -+ -+/** -+ * igb_alloc_rx_buffers_adv - Replace used receive buffers; packet split -+ * @adapter: address of board private structure -+ **/ -+ -+static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, -+ int cleaned_count) -+{ -+ struct igb_adapter *adapter = rx_ring->adapter; -+ struct net_device *netdev = adapter->netdev; -+ struct pci_dev *pdev = adapter->pdev; -+ union e1000_adv_rx_desc *rx_desc; -+ struct igb_buffer *buffer_info; -+ struct sk_buff *skb; -+ unsigned int i; -+ int bufsz; -+ -+ i = rx_ring->next_to_use; -+ buffer_info = &rx_ring->buffer_info[i]; -+ -+#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT -+ if (adapter->rx_ps_hdr_size) -+ bufsz = adapter->rx_ps_hdr_size; -+ else -+ bufsz = adapter->rx_buffer_len; -+ bufsz += NET_IP_ALIGN; -+#else -+ bufsz = adapter->rx_buffer_len + NET_IP_ALIGN; -+#endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ -+ -+ while (cleaned_count--) { -+ rx_desc = E1000_RX_DESC_ADV(*rx_ring, i); -+ -+#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT -+ if (adapter->rx_ps_hdr_size && !buffer_info->page_dma) { -+ if (!buffer_info->page) { -+ buffer_info->page = alloc_page(GFP_ATOMIC); -+ if (!buffer_info->page) { -+ adapter->alloc_rx_buff_failed++; -+ goto no_buffers; -+ } -+ buffer_info->page_offset = 0; -+ } else { -+ buffer_info->page_offset ^= PAGE_SIZE / 2; -+ } -+ buffer_info->page_dma = -+ pci_map_page(pdev, buffer_info->page, -+ buffer_info->page_offset, -+ PAGE_SIZE / 2, -+ PCI_DMA_FROMDEVICE); -+ } -+#endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ -+ -+ if (!buffer_info->skb) { -+ skb = netdev_alloc_skb(netdev, bufsz); -+ if (!skb) { -+ adapter->alloc_rx_buff_failed++; -+ goto no_buffers; -+ } -+ -+ /* Make buffer alignment 2 beyond a 16 byte boundary -+ * this will result in a 16 byte aligned IP header after -+ * the 14 byte MAC header is removed -+ */ -+ skb_reserve(skb, NET_IP_ALIGN); ++ igb_receive_skb(rx_ring, staterr, rx_desc, skb); + -+ buffer_info->skb = skb; -+ buffer_info->dma = pci_map_single(pdev, skb->data, -+ bufsz, -+ PCI_DMA_FROMDEVICE); -+ } -+ /* Refresh the desc even if buffer_addrs didn't change because -+ * each write-back erases this info. */ -+#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT -+ if (adapter->rx_ps_hdr_size) { -+ rx_desc->read.pkt_addr = -+ cpu_to_le64(buffer_info->page_dma); -+ rx_desc->read.hdr_addr = cpu_to_le64(buffer_info->dma); -+ } else { -+#else -+ { -+#endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ -+ rx_desc->read.pkt_addr = -+ cpu_to_le64(buffer_info->dma); -+ rx_desc->read.hdr_addr = 0; ++ netdev->last_rx = jiffies; ++ ++next_desc: ++ rx_desc->wb.upper.status_error = 0; ++ ++ /* return some buffers to hardware, one at a time is too slow */ ++ if (cleaned_count >= IGB_RX_BUFFER_WRITE) { ++ if (igb_alloc_rx_buffers_adv(rx_ring, cleaned_count)) ++ adapter->alloc_rx_buff_failed++; ++ cleaned_count = 0; + } + -+ i++; -+ if (i == rx_ring->count) -+ i = 0; -+ buffer_info = &rx_ring->buffer_info[i]; ++ /* use prefetched values */ ++ rx_desc = next_rxd; ++ buffer_info = next_buffer; ++ staterr = le32_to_cpu(rx_desc->wb.upper.status_error); + } + -+no_buffers: -+ if (rx_ring->next_to_use != i) { -+ rx_ring->next_to_use = i; -+ if (i == 0) -+ i = (rx_ring->count - 1); -+ else -+ i--; ++ rx_ring->next_to_clean = i; ++ cleaned_count = IGB_DESC_UNUSED(rx_ring); + -+ /* 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); ++#ifdef IGB_LRO ++ if (rx_ring->lro_used) { ++ lro_flush_all(&rx_ring->lro_mgr); ++ rx_ring->lro_used = FALSE; + } ++#endif ++ ++ if (cleaned_count) ++ if (igb_alloc_rx_buffers_adv(rx_ring, cleaned_count)) ++ adapter->alloc_rx_buff_failed++; ++ ++ rx_ring->total_packets += total_packets; ++ rx_ring->total_bytes += total_bytes; ++ rx_ring->stats.packets += total_packets; ++ rx_ring->stats.bytes += total_bytes; ++ adapter->net_stats.rx_bytes += total_bytes; ++ adapter->net_stats.rx_packets += total_packets; ++ return cleaned; +} + +#ifdef SIOCGMIIPHY @@ -21998,7 +20557,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + * @ifreq: + * @cmd: + **/ -+ +static int igb_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + struct igb_adapter *adapter = netdev_priv(netdev); @@ -22024,15 +20582,180 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + } + return E1000_SUCCESS; +} ++ +#endif ++#ifdef SIOCSHWTSTAMP ++/** ++ * igb_hwtstamp_ioctl - control hardware time stamping ++ * @netdev: ++ * @ifreq: ++ * @cmd: ++ * ++ * Outgoing time stamping can be enabled and disabled. Play nice and ++ * disable it when requested, although it shouldn't case any overhead ++ * when no packet needs it. At most one packet in the queue may be ++ * marked for time stamping, otherwise it would be impossible to tell ++ * for sure to which packet the hardware time stamp belongs. ++ * ++ * Incoming time stamping has to be configured via the hardware ++ * filters. Not all combinations are supported, in particular event ++ * type has to be specified. Matching the kind of event packet is ++ * not supported, with the exception of "all V2 events regardless of ++ * level 2 or 4". ++ * ++ **/ ++static int igb_hwtstamp_ioctl(struct net_device *netdev, ++ struct ifreq *ifr, int cmd) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ struct e1000_hw *hw = &adapter->hw; ++ struct hwtstamp_config config; ++ u32 tsync_tx_ctl = E1000_TSYNCTXCTL_ENABLED; ++ u32 tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED; ++ u32 tsync_rx_cfg = 0; ++ bool is_l4 = false; ++ bool is_l2 = false; ++ u32 regval; ++ ++ if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) ++ return -EFAULT; ++ ++ /* reserved for future extensions */ ++ if (config.flags) ++ return -EINVAL; ++ ++ switch (config.tx_type) { ++ case HWTSTAMP_TX_OFF: ++ tsync_tx_ctl = 0; ++ case HWTSTAMP_TX_ON: ++ break; ++ default: ++ return -ERANGE; ++ } ++ ++ switch (config.rx_filter) { ++ case HWTSTAMP_FILTER_NONE: ++ tsync_rx_ctl = 0; ++ break; ++ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: ++ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: ++ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: ++ case HWTSTAMP_FILTER_ALL: ++ /* ++ * register TSYNCRXCFG must be set, therefore it is not ++ * possible to time stamp both Sync and Delay_Req messages ++ * => fall back to time stamping all packets ++ */ ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; ++ config.rx_filter = HWTSTAMP_FILTER_ALL; ++ break; ++ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1; ++ tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE; ++ is_l4 = true; ++ break; ++ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1; ++ tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE; ++ is_l4 = true; ++ break; ++ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: ++ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2; ++ tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE; ++ is_l2 = true; ++ is_l4 = true; ++ config.rx_filter = HWTSTAMP_FILTER_SOME; ++ break; ++ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: ++ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2; ++ tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE; ++ is_l2 = true; ++ is_l4 = true; ++ config.rx_filter = HWTSTAMP_FILTER_SOME; ++ break; ++ case HWTSTAMP_FILTER_PTP_V2_EVENT: ++ case HWTSTAMP_FILTER_PTP_V2_SYNC: ++ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_EVENT_V2; ++ config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; ++ is_l2 = true; ++ break; ++ default: ++ return -ERANGE; ++ } ++ ++ if (hw->mac.type == e1000_82575) { ++ if (tsync_rx_ctl | tsync_tx_ctl) ++ return -EINVAL; ++ return 0; ++ } ++ ++ /* enable/disable TX */ ++ regval = E1000_READ_REG(hw, E1000_TSYNCTXCTL); ++ regval &= ~E1000_TSYNCTXCTL_ENABLED; ++ regval |= tsync_tx_ctl; ++ E1000_WRITE_REG(hw, E1000_TSYNCTXCTL, regval); ++ ++ /* enable/disable RX */ ++ regval = E1000_READ_REG(hw, E1000_TSYNCRXCTL); ++ regval &= ~(E1000_TSYNCRXCTL_ENABLED | E1000_TSYNCRXCTL_TYPE_MASK); ++ regval |= tsync_rx_ctl; ++ E1000_WRITE_REG(hw, E1000_TSYNCRXCTL, regval); ++ ++ /* define which PTP packets are time stamped */ ++ E1000_WRITE_REG(hw, E1000_TSYNCRXCFG, tsync_rx_cfg); ++ ++ /* define ethertype filter for timestamped packets */ ++ if (is_l2) ++ E1000_WRITE_REG(hw, E1000_ETQF(3), ++ (E1000_ETQF_FILTER_ENABLE | /* enable filter */ ++ E1000_ETQF_1588 | /* enable timestamping */ ++ ETH_P_1588)); /* 1588 eth protocol type */ ++ else ++ E1000_WRITE_REG(hw, E1000_ETQF(3), 0); ++ ++#define PTP_PORT 319 ++ /* L4 Queue Filter[3]: filter by destination port and protocol */ ++ if (is_l4) { ++ u32 ftqf = (IPPROTO_UDP /* UDP */ ++ | E1000_FTQF_VF_BP /* VF not compared */ ++ | E1000_FTQF_1588_TIME_STAMP /* Enable Timestamping */ ++ | E1000_FTQF_MASK); /* mask all inputs */ ++ ftqf &= ~E1000_FTQF_MASK_PROTO_BP; /* enable protocol check */ ++ ++ E1000_WRITE_REG(hw, E1000_IMIR(3), htons(PTP_PORT)); ++ E1000_WRITE_REG(hw, E1000_IMIREXT(3), ++ (E1000_IMIREXT_SIZE_BP | E1000_IMIREXT_CTRL_BP)); ++ if (hw->mac.type == e1000_82576) { ++ /* enable source port check */ ++ E1000_WRITE_REG(hw, E1000_SPQF(3), htons(PTP_PORT)); ++ ftqf &= ~E1000_FTQF_MASK_SOURCE_PORT_BP; ++ } ++ E1000_WRITE_REG(hw, E1000_FTQF(3), ftqf); ++ } else { ++ E1000_WRITE_REG(hw, E1000_FTQF(3), E1000_FTQF_MASK); ++ } ++ E1000_WRITE_FLUSH(hw); ++ ++ adapter->hwtstamp_config = config; ++ ++ /* clear TX/RX time stamp registers, just to be sure */ ++ regval = E1000_READ_REG(hw, E1000_TXSTMPH); ++ regval = E1000_READ_REG(hw, E1000_RXSTMPH); ++ ++ return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? ++ -EFAULT : 0; ++} + ++#endif +/** + * igb_ioctl - + * @netdev: + * @ifreq: + * @cmd: + **/ -+ +static int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + switch (cmd) { @@ -22042,6 +20765,10 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + case SIOCSMIIREG: + return igb_mii_ioctl(netdev, ifr, cmd); +#endif ++#ifdef SIOCSHWTSTAMP ++ case SIOCSHWTSTAMP: ++ return igb_hwtstamp_ioctl(netdev, ifr, cmd); ++#endif +#ifdef ETHTOOL_OPS_COMPAT + case SIOCETHTOOL: + return ethtool_ioctl(ifr); @@ -22051,15 +20778,21 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + } +} + -+void e1000_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value) ++s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) +{ + struct igb_adapter *adapter = hw->back; ++ u16 cap_offset; + -+ pci_read_config_word(adapter->pdev, reg, value); -+} ++ cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP); ++ if (!cap_offset) ++ return -E1000_ERR_CONFIG; + ++ pci_read_config_word(adapter->pdev, cap_offset + reg, value); + -+s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) ++ return E1000_SUCCESS; ++} ++ ++s32 e1000_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) +{ + struct igb_adapter *adapter = hw->back; + u16 cap_offset; @@ -22068,7 +20801,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + if (!cap_offset) + return -E1000_ERR_CONFIG; + -+ pci_read_config_word(adapter->pdev, cap_offset + reg, value); ++ pci_write_config_word(adapter->pdev, cap_offset + reg, *value); + + return E1000_SUCCESS; +} @@ -22093,23 +20826,15 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + rctl = E1000_READ_REG(hw, E1000_RCTL); + rctl &= ~E1000_RCTL_CFIEN; + E1000_WRITE_REG(hw, E1000_RCTL, rctl); -+ igb_update_mng_vlan(adapter); -+ E1000_WRITE_REG(hw, E1000_RLPML, -+ adapter->max_frame_size + VLAN_TAG_SIZE); + } else { + /* disable VLAN tag insert/strip */ + ctrl = E1000_READ_REG(hw, E1000_CTRL); + ctrl &= ~E1000_CTRL_VME; + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); -+ -+ if (adapter->mng_vlan_id != (u16)IGB_MNG_VLAN_NONE) { -+ igb_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); -+ adapter->mng_vlan_id = IGB_MNG_VLAN_NONE; -+ } -+ E1000_WRITE_REG(hw, E1000_RLPML, -+ adapter->max_frame_size); + } + ++ igb_set_rlpml(adapter); ++ + if (!test_bit(__IGB_DOWN, &adapter->state)) + igb_irq_enable(adapter); +} @@ -22118,31 +20843,32 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +{ + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; -+ u32 vfta, index; ++ int pf_id = adapter->vfs_allocated_count; ++#ifndef HAVE_NETDEV_VLAN_FEATURES + struct net_device *v_netdev; ++#endif + -+ if ((hw->mng_cookie.status & -+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && -+ (vid == adapter->mng_vlan_id)) -+ return; -+ /* add VID to filter table */ -+ index = (vid >> 5) & 0x7F; -+ vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, index); -+ vfta |= (1 << (vid & 0x1F)); -+ e1000_write_vfta(hw, index, vfta); ++ /* attempt to add filter to vlvf array */ ++ igb_vlvf_set(adapter, vid, TRUE, pf_id); ++ ++ /* add the filter since PF can receive vlans w/o entry in vlvf */ ++ igb_vfta_set(hw, vid, TRUE); ++#ifndef HAVE_NETDEV_VLAN_FEATURES + /* Copy feature flags from netdev to the vlan netdev for this vid. + * This allows things like TSO to bubble down to our vlan device. + */ + v_netdev = vlan_group_get_device(adapter->vlgrp, vid); + v_netdev->features |= adapter->netdev->features; + vlan_group_set_device(adapter->vlgrp, vid, v_netdev); ++#endif +} + +static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) +{ + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; -+ u32 vfta, index; ++ int pf_id = adapter->vfs_allocated_count; ++ s32 err; + + igb_irq_disable(adapter); + vlan_group_set_device(adapter->vlgrp, vid, NULL); @@ -22150,19 +20876,12 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + if (!test_bit(__IGB_DOWN, &adapter->state)) + igb_irq_enable(adapter); + -+ if ((adapter->hw.mng_cookie.status & -+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && -+ (vid == adapter->mng_vlan_id)) { -+ /* release control to f/w */ -+ igb_release_hw_control(adapter); -+ return; -+ } ++ /* remove vlan from VLVF table array */ ++ err = igb_vlvf_set(adapter, vid, FALSE, pf_id); + -+ /* remove VID from filter table */ -+ index = (vid >> 5) & 0x7F; -+ vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, index); -+ vfta &= ~(1 << (vid & 0x1F)); -+ e1000_write_vfta(hw, index, vfta); ++ /* if vid was not present in VLVF just remove it from table */ ++ if (err) ++ igb_vfta_set(hw, vid, FALSE); +} + +static void igb_restore_vlan(struct igb_adapter *adapter) @@ -22185,13 +20904,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + mac->autoneg = 0; + -+ /* Fiber NICs only allow 1000 gbps Full duplex */ -+ if ((adapter->hw.phy.media_type == e1000_media_type_fiber) && -+ spddplx != (SPEED_1000 + DUPLEX_FULL)) { -+ DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n"); -+ return -EINVAL; -+ } -+ + switch (spddplx) { + case SPEED_10 + DUPLEX_HALF: + mac->forced_speed_duplex = ADVERTISE_10_HALF; @@ -22235,9 +20947,9 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + } + return NOTIFY_DONE; +} -+#endif + -+static int igb_suspend(struct pci_dev *pdev, pm_message_t state) ++#endif ++static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct igb_adapter *adapter = netdev_priv(netdev); @@ -22253,9 +20965,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + if (netif_running(netdev)) + igb_close(netdev); + -+ igb_reset_interrupt_capability(adapter); -+ -+ igb_free_queues(adapter); ++ igb_clear_interrupt_scheme(adapter); + +#ifdef CONFIG_PM + retval = pci_save_state(pdev); @@ -22269,7 +20979,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + if (wufc) { + igb_setup_rctl(adapter); -+ igb_set_multi(netdev); ++ igb_set_rx_mode(netdev); + + /* turn on all-multi mode if wake on multicast is enabled */ + if (wufc & E1000_WUFC_MC) { @@ -22279,8 +20989,6 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + } + + ctrl = E1000_READ_REG(hw, E1000_CTRL); -+ /* advertise wake from D3Cold */ -+ #define E1000_CTRL_ADVD3WUC 0x00100000 + /* phy power management enable */ + #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 + ctrl |= E1000_CTRL_ADVD3WUC; @@ -22296,15 +21004,9 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + E1000_WRITE_REG(hw, E1000_WUFC, 0); + } + -+ /* make sure adapter isn't asleep if manageability/wol is enabled */ -+ if (wufc || adapter->en_mng_pt) { -+ pci_enable_wake(pdev, PCI_D3hot, 1); -+ pci_enable_wake(pdev, PCI_D3cold, 1); -+ } else { ++ *enable_wake = wufc || adapter->en_mng_pt; ++ if (!*enable_wake) + e1000_shutdown_fiber_serdes_link(hw); -+ pci_enable_wake(pdev, PCI_D3hot, 0); -+ pci_enable_wake(pdev, PCI_D3cold, 0); -+ } + + /* Release control of h/w to f/w. If f/w is AMT enabled, this + * would have already happened in close and is redundant. */ @@ -22312,12 +21014,29 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + pci_disable_device(pdev); + -+ pci_set_power_state(pdev, pci_choose_state(pdev, state)); -+ + return 0; +} + +#ifdef CONFIG_PM ++static int igb_suspend(struct pci_dev *pdev, pm_message_t state) ++{ ++ int retval; ++ bool wake; ++ ++ retval = __igb_shutdown(pdev, &wake); ++ if (retval) ++ return retval; ++ ++ if (wake) { ++ pci_prepare_to_sleep(pdev); ++ } else { ++ pci_wake_from_d3(pdev, false); ++ pci_set_power_state(pdev, PCI_D3hot); ++ } ++ ++ return 0; ++} ++ +static int igb_resume(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); @@ -22327,7 +21046,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); -+ err = pci_enable_device(pdev); ++ err = pci_enable_device_mem(pdev); + if (err) { + dev_err(&pdev->dev, "igb: Cannot enable PCI device " + "from suspend\n"); @@ -22338,9 +21057,7 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + -+ igb_set_interrupt_capability(adapter); -+ -+ if (igb_alloc_queues(adapter)) { ++ if (igb_init_interrupt_scheme(adapter)) { + DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n"); + return -ENOMEM; + } @@ -22348,6 +21065,11 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + /* e1000_power_up_phy(adapter); */ + + igb_reset(adapter); ++ ++ /* let the f/w know that the h/w is now under the control of the ++ * driver. */ ++ igb_get_hw_control(adapter); ++ + E1000_WRITE_REG(hw, E1000_WUS, ~0); + + if (netif_running(netdev)) { @@ -22365,10 +21087,17 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +#ifndef USE_REBOOT_NOTIFIER +static void igb_shutdown(struct pci_dev *pdev) +{ -+ igb_suspend(pdev, PMSG_SUSPEND); ++ bool wake; ++ ++ __igb_shutdown(pdev, &wake); ++ ++ if (system_state == SYSTEM_POWER_OFF) { ++ pci_wake_from_d3(pdev, wake); ++ pci_set_power_state(pdev, PCI_D3hot); ++ } +} -+#endif + ++#endif +#ifdef CONFIG_NET_POLL_CONTROLLER +/* + * Polling 'interrupt' - used by things like netconsole to send skbs @@ -22378,25 +21107,21 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i +static void igb_netpoll(struct net_device *netdev) +{ + struct igb_adapter *adapter = netdev_priv(netdev); ++ struct e1000_hw *hw = &adapter->hw; + int i; -+ int work_done = 0; + -+ igb_irq_disable(adapter); -+ adapter->flags |= IGB_FLAG_IN_NETPOLL; -+ -+#ifndef CONFIG_IGB_SEPARATE_TX_HANDLER -+ for (i = 0; i < adapter->num_tx_queues; i++) { -+ igb_clean_tx_irq(&adapter->tx_ring[i]); ++ if (!adapter->msix_entries) { ++ struct igb_q_vector *q_vector = adapter->q_vector[0]; ++ igb_irq_disable(adapter); ++ napi_schedule(&q_vector->napi); ++ return; + } -+#endif + -+ for (i = 0; i < adapter->num_rx_queues; i++) { -+ igb_clean_rx_irq_adv(&adapter->rx_ring[i], -+ &work_done, -+ adapter->rx_ring[i].napi.weight); ++ for (i = 0; i < adapter->num_q_vectors; i++) { ++ struct igb_q_vector *q_vector = adapter->q_vector[i]; ++ E1000_WRITE_REG(hw, E1000_EIMC, q_vector->eims_value); ++ napi_schedule(&q_vector->napi); + } -+ adapter->flags &= ~IGB_FLAG_IN_NETPOLL; -+ igb_irq_enable(adapter); +} +#endif /* CONFIG_NET_POLL_CONTROLLER */ + @@ -22417,6 +21142,9 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + + netif_device_detach(netdev); + ++ if (state == pci_channel_io_perm_failure) ++ return PCI_ERS_RESULT_DISCONNECT; ++ + if (netif_running(netdev)) + igb_down(adapter); + pci_disable_device(pdev); @@ -22437,659 +21165,150 @@ diff -Nru vanilla/drivers/net/igb/igb_main.c linux-i686-2.6.22/drivers/net/igb/i + struct net_device *netdev = pci_get_drvdata(pdev); + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; ++ pci_ers_result_t result; + -+ if (pci_enable_device(pdev)) { ++ if (pci_enable_device_mem(pdev)) { + dev_err(&pdev->dev, + "Cannot re-enable PCI device after reset.\n"); -+ return PCI_ERS_RESULT_DISCONNECT; ++ result = PCI_ERS_RESULT_DISCONNECT; ++ } else { ++ pci_set_master(pdev); ++ pci_restore_state(pdev); ++ ++ pci_enable_wake(pdev, PCI_D3hot, 0); ++ pci_enable_wake(pdev, PCI_D3cold, 0); ++ ++ igb_reset(adapter); ++ E1000_WRITE_REG(hw, E1000_WUS, ~0); ++ result = PCI_ERS_RESULT_RECOVERED; + } -+ pci_set_master(pdev); -+ pci_restore_state(pdev); + -+ pci_enable_wake(pdev, PCI_D3hot, 0); -+ pci_enable_wake(pdev, PCI_D3cold, 0); ++ pci_cleanup_aer_uncorrect_error_status(pdev); ++ ++ return result; ++} ++ ++/** ++ * igb_io_resume - called when traffic can start flowing again. ++ * @pdev: Pointer to PCI device ++ * ++ * This callback is called when the error recovery driver tells us that ++ * its OK to resume normal operation. Implementation resembles the ++ * second-half of the igb_resume routine. ++ */ ++static void igb_io_resume(struct pci_dev *pdev) ++{ ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ ++ if (netif_running(netdev)) { ++ if (igb_up(adapter)) { ++ dev_err(&pdev->dev, "igb_up failed after reset\n"); ++ return; ++ } ++ } ++ ++ netif_device_attach(netdev); ++ ++ /* let the f/w know that the h/w is now under the control of the ++ * driver. */ ++ igb_get_hw_control(adapter); ++} ++ ++#endif /* HAVE_PCI_ERS */ ++static void igb_rar_set_qsel(struct igb_adapter *adapter, u8 *addr, u32 index, ++ u8 qsel) ++{ ++ u32 rar_low, rar_high; ++ struct e1000_hw *hw = &adapter->hw; ++ ++ /* HW expects these in little endian so we reverse the byte order ++ * from network order (big endian) to little endian ++ */ ++ rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) | ++ ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); ++ rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); ++ ++ /* Indicate to hardware the Address is Valid. */ ++ rar_high |= E1000_RAH_AV; ++ ++ if (hw->mac.type == e1000_82575) ++ rar_high |= E1000_RAH_POOL_1 * qsel; ++ else ++ rar_high |= E1000_RAH_POOL_1 << qsel; ++ ++ E1000_WRITE_REG(hw, E1000_RAL(index), rar_low); ++ E1000_WRITE_FLUSH(hw); ++ E1000_WRITE_REG(hw, E1000_RAH(index), rar_high); ++ E1000_WRITE_FLUSH(hw); ++} ++ ++int igb_set_vf_mac(struct igb_adapter *adapter, ++ int vf, unsigned char *mac_addr) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ /* VF MAC addresses start at end of receive addresses and moves ++ * torwards the first, as a result a collision should not be possible */ ++ int rar_entry = hw->mac.rar_entry_count - (vf + 1); ++ ++ memcpy(adapter->vf_data[vf].vf_mac_addresses, mac_addr, 6); ++ ++ igb_rar_set_qsel(adapter, mac_addr, rar_entry, vf); ++ ++ return 0; ++} ++ ++static void igb_vmm_control(struct igb_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; + -+ igb_reset(adapter); -+ E1000_WRITE_REG(hw, E1000_WUS, ~0); ++ /* replication is not supported for 82575 */ ++ if (hw->mac.type == e1000_82575) ++ return; + -+ return PCI_ERS_RESULT_RECOVERED; ++ if (adapter->vfs_allocated_count || adapter->VMDQ_queues) { ++ e1000_vmdq_set_loopback_pf(hw, true); ++ e1000_vmdq_set_replication_pf(hw, true); ++ } else { ++ e1000_vmdq_set_loopback_pf(hw, false); ++ e1000_vmdq_set_replication_pf(hw, false); ++ } +} + -+/** -+ * igb_io_resume - called when traffic can start flowing again. -+ * @pdev: Pointer to PCI device -+ * -+ * This callback is called when the error recovery driver tells us that -+ * its OK to resume normal operation. Implementation resembles the -+ * second-half of the igb_resume routine. -+ */ -+static void igb_io_resume(struct pci_dev *pdev) ++static void igb_vf_configuration(struct pci_dev *pdev, unsigned int event_mask) +{ ++ unsigned char my_mac_addr[6]; ++ unsigned char oui[OUI_LEN] = {0x02, 0xAA, 0x00}; + struct net_device *netdev = pci_get_drvdata(pdev); + struct igb_adapter *adapter = netdev_priv(netdev); -+ -+ if (netif_running(netdev)) { -+ if (igb_up(adapter)) { -+ dev_err(&pdev->dev, "igb_up failed after reset\n"); -+ return; -+ } ++ unsigned int vfn = (event_mask & 7); ++ ++ bool enable = ((event_mask & 0x10000000U) != 0); ++ ++ if (enable) { ++ random_ether_addr(my_mac_addr); ++ memcpy(my_mac_addr, oui, OUI_LEN); ++ printk(KERN_INFO "IOV1: VF %d is enabled\n", vfn); ++ printk(KERN_INFO "Assigned MAC: " ++ "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", ++ my_mac_addr[0], my_mac_addr[1], my_mac_addr[2], ++ my_mac_addr[3], my_mac_addr[4], my_mac_addr[5]); ++ igb_set_vf_mac(adapter, vfn, my_mac_addr); ++ } else { ++ printk(KERN_INFO "IOV1: VF %d is disabled\n", vfn); + } -+ -+ netif_device_attach(netdev); -+ -+ /* let the f/w know that the h/w is now under the control of the -+ * driver. */ -+ igb_get_hw_control(adapter); -+ +} -+#endif /* HAVE_PCI_ERS */ -+ + +/* igb_main.c */ -Binary files vanilla/drivers/net/igb/igb_main.o and linux-i686-2.6.22/drivers/net/igb/igb_main.o differ -diff -Nru vanilla/drivers/net/igb/.igb_main.o.cmd linux-i686-2.6.22/drivers/net/igb/.igb_main.o.cmd ---- vanilla/drivers/net/igb/.igb_main.o.cmd 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/.igb_main.o.cmd 2009-07-16 19:52:20.000000000 -0400 -@@ -0,0 +1,585 @@ -+cmd_drivers/net/igb/igb_main.o := gcc -m32 -Wp,-MD,drivers/net/igb/.igb_main.o.d -nostdinc -isystem /usr/lib/gcc/i386-redhat-linux/4.1.2/include -D__KERNEL__ -Iinclude -include include/linux/autoconf.h -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Os -pipe -msoft-float -mregparm=3 -freg-struct-return -mpreferred-stack-boundary=2 -march=i686 -mtune=generic -ffreestanding -maccumulate-outgoing-args -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -Iinclude/asm-i386/mach-generic -Iinclude/asm-i386/mach-default -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -DMODULE -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(igb_main)" -D"KBUILD_MODNAME=KBUILD_STR(igb)" -c -o drivers/net/igb/.tmp_igb_main.o drivers/net/igb/igb_main.c -+ -+deps_drivers/net/igb/igb_main.o := \ -+ drivers/net/igb/igb_main.c \ -+ $(wildcard include/config/igb/separate/tx/handler.h) \ -+ $(wildcard include/config/pm.h) \ -+ $(wildcard include/config/net/poll/controller.h) \ -+ $(wildcard include/config/netdevices/multiqueue.h) \ -+ $(wildcard include/config/igb/disable/packet/split.h) \ -+ include/linux/module.h \ -+ $(wildcard include/config/modules.h) \ -+ $(wildcard include/config/modversions.h) \ -+ $(wildcard include/config/unused/symbols.h) \ -+ $(wildcard include/config/generic/bug.h) \ -+ $(wildcard include/config/module/unload.h) \ -+ $(wildcard include/config/kallsyms.h) \ -+ $(wildcard include/config/sysfs.h) \ -+ include/linux/spinlock.h \ -+ $(wildcard include/config/smp.h) \ -+ $(wildcard include/config/debug/spinlock.h) \ -+ $(wildcard include/config/preempt.h) \ -+ $(wildcard include/config/debug/lock/alloc.h) \ -+ include/linux/preempt.h \ -+ $(wildcard include/config/debug/preempt.h) \ -+ include/linux/thread_info.h \ -+ include/linux/types.h \ -+ $(wildcard include/config/uid16.h) \ -+ $(wildcard include/config/lbd.h) \ -+ $(wildcard include/config/lsf.h) \ -+ $(wildcard include/config/resources/64bit.h) \ -+ include/linux/posix_types.h \ -+ include/linux/stddef.h \ -+ include/linux/compiler.h \ -+ $(wildcard include/config/enable/must/check.h) \ -+ include/linux/compiler-gcc4.h \ -+ $(wildcard include/config/forced/inlining.h) \ -+ include/linux/compiler-gcc.h \ -+ include/asm/posix_types.h \ -+ include/asm/types.h \ -+ $(wildcard include/config/highmem64g.h) \ -+ include/linux/bitops.h \ -+ include/asm/bitops.h \ -+ include/asm/alternative.h \ -+ $(wildcard include/config/paravirt.h) \ -+ include/asm-generic/bitops/sched.h \ -+ include/asm-generic/bitops/hweight.h \ -+ include/asm-generic/bitops/fls64.h \ -+ include/asm-generic/bitops/ext2-non-atomic.h \ -+ include/asm-generic/bitops/le.h \ -+ include/asm/byteorder.h \ -+ $(wildcard include/config/x86/bswap.h) \ -+ include/linux/byteorder/little_endian.h \ -+ include/linux/byteorder/swab.h \ -+ include/linux/byteorder/generic.h \ -+ include/asm-generic/bitops/minix.h \ -+ include/asm/thread_info.h \ -+ $(wildcard include/config/4kstacks.h) \ -+ $(wildcard include/config/debug/stack/usage.h) \ -+ include/asm/page.h \ -+ $(wildcard include/config/x86/use/3dnow.h) \ -+ $(wildcard include/config/x86/pae.h) \ -+ $(wildcard include/config/hugetlb/page.h) \ -+ $(wildcard include/config/highmem4g.h) \ -+ $(wildcard include/config/page/offset.h) \ -+ $(wildcard include/config/flatmem.h) \ -+ include/asm-generic/pgtable-nopmd.h \ -+ include/asm-generic/pgtable-nopud.h \ -+ include/asm-generic/memory_model.h \ -+ $(wildcard include/config/discontigmem.h) \ -+ $(wildcard include/config/sparsemem.h) \ -+ $(wildcard include/config/out/of/line/pfn/to/page.h) \ -+ include/asm-generic/page.h \ -+ include/asm/processor.h \ -+ $(wildcard include/config/x86/ht.h) \ -+ $(wildcard include/config/mk8.h) \ -+ $(wildcard include/config/mk7.h) \ -+ include/asm/vm86.h \ -+ $(wildcard include/config/vm86.h) \ -+ include/asm/ptrace.h \ -+ include/asm/ptrace-abi.h \ -+ include/asm/segment.h \ -+ include/asm/math_emu.h \ -+ include/asm/sigcontext.h \ -+ include/asm/cpufeature.h \ -+ include/asm/required-features.h \ -+ $(wildcard include/config/x86/minimum/cpu.h) \ -+ $(wildcard include/config/x86/cmov.h) \ -+ $(wildcard include/config/x86/cmpxchg64.h) \ -+ include/asm/msr.h \ -+ include/asm/msr-index.h \ -+ include/asm/errno.h \ -+ include/asm-generic/errno.h \ -+ include/asm-generic/errno-base.h \ -+ include/linux/errno.h \ -+ include/asm/system.h \ -+ $(wildcard include/config/x86/oostore.h) \ -+ include/linux/kernel.h \ -+ $(wildcard include/config/preempt/voluntary.h) \ -+ $(wildcard include/config/debug/spinlock/sleep.h) \ -+ $(wildcard include/config/printk.h) \ -+ $(wildcard include/config/numa.h) \ -+ /usr/lib/gcc/i386-redhat-linux/4.1.2/include/stdarg.h \ -+ include/linux/linkage.h \ -+ include/asm/linkage.h \ -+ $(wildcard include/config/x86/alignment/16.h) \ -+ include/linux/log2.h \ -+ $(wildcard include/config/arch/has/ilog2/u32.h) \ -+ $(wildcard include/config/arch/has/ilog2/u64.h) \ -+ include/asm/bug.h \ -+ $(wildcard include/config/bug.h) \ -+ $(wildcard include/config/debug/bugverbose.h) \ -+ include/asm-generic/bug.h \ -+ include/asm/cmpxchg.h \ -+ $(wildcard include/config/x86/cmpxchg.h) \ -+ include/linux/irqflags.h \ -+ $(wildcard include/config/trace/irqflags.h) \ -+ $(wildcard include/config/trace/irqflags/support.h) \ -+ $(wildcard include/config/x86.h) \ -+ include/asm/irqflags.h \ -+ include/asm/processor-flags.h \ -+ include/linux/cache.h \ -+ include/asm/cache.h \ -+ $(wildcard include/config/x86/l1/cache/shift.h) \ -+ include/linux/threads.h \ -+ $(wildcard include/config/nr/cpus.h) \ -+ $(wildcard include/config/base/small.h) \ -+ include/asm/percpu.h \ -+ include/linux/cpumask.h \ -+ $(wildcard include/config/hotplug/cpu.h) \ -+ include/linux/bitmap.h \ -+ include/linux/string.h \ -+ include/asm/string.h \ -+ include/linux/init.h \ -+ $(wildcard include/config/hotplug.h) \ -+ $(wildcard include/config/memory/hotplug.h) \ -+ $(wildcard include/config/acpi/hotplug/memory.h) \ -+ include/linux/stringify.h \ -+ include/linux/bottom_half.h \ -+ include/linux/spinlock_types.h \ -+ include/linux/lockdep.h \ -+ $(wildcard include/config/lockdep.h) \ -+ $(wildcard include/config/generic/hardirqs.h) \ -+ $(wildcard include/config/prove/locking.h) \ -+ include/asm/spinlock_types.h \ -+ include/asm/spinlock.h \ -+ $(wildcard include/config/x86/ppro/fence.h) \ -+ include/asm/atomic.h \ -+ $(wildcard include/config/m386.h) \ -+ include/asm-generic/atomic.h \ -+ include/asm/rwlock.h \ -+ include/linux/spinlock_api_smp.h \ -+ include/linux/list.h \ -+ $(wildcard include/config/debug/list.h) \ -+ include/linux/poison.h \ -+ include/linux/prefetch.h \ -+ include/linux/stat.h \ -+ include/asm/stat.h \ -+ include/linux/time.h \ -+ include/linux/seqlock.h \ -+ include/linux/vs_time.h \ -+ $(wildcard include/config/vserver/vtime.h) \ -+ include/linux/kmod.h \ -+ $(wildcard include/config/kmod.h) \ -+ include/linux/elf.h \ -+ include/linux/auxvec.h \ -+ include/asm/auxvec.h \ -+ include/linux/elf-em.h \ -+ include/asm/elf.h \ -+ include/asm/user.h \ -+ include/asm/desc.h \ -+ include/asm/ldt.h \ -+ include/linux/smp.h \ -+ include/asm/smp.h \ -+ $(wildcard include/config/x86/local/apic.h) \ -+ $(wildcard include/config/x86/io/apic.h) \ -+ include/asm/mpspec.h \ -+ $(wildcard include/config/acpi.h) \ -+ include/asm/mpspec_def.h \ -+ include/asm-i386/mach-generic/mach_mpspec.h \ -+ include/asm/apic.h \ -+ $(wildcard include/config/x86/good/apic.h) \ -+ include/linux/pm.h \ -+ include/linux/delay.h \ -+ include/asm/delay.h \ -+ include/asm/fixmap.h \ -+ $(wildcard include/config/highmem.h) \ -+ $(wildcard include/config/x86/visws/apic.h) \ -+ $(wildcard include/config/x86/f00f/bug.h) \ -+ $(wildcard include/config/x86/cyclone/timer.h) \ -+ $(wildcard include/config/pci/mmconfig.h) \ -+ include/asm/acpi.h \ -+ $(wildcard include/config/acpi/sleep.h) \ -+ include/acpi/pdc_intel.h \ -+ include/asm/apicdef.h \ -+ include/asm/kmap_types.h \ -+ $(wildcard include/config/debug/highmem.h) \ -+ include/asm/io_apic.h \ -+ include/asm-i386/mach-generic/mach_apicdef.h \ -+ include/asm/genapic.h \ -+ include/linux/percpu.h \ -+ include/linux/slab.h \ -+ $(wildcard include/config/slab/debug.h) \ -+ $(wildcard include/config/slab.h) \ -+ $(wildcard include/config/slub.h) \ -+ $(wildcard include/config/debug/slab.h) \ -+ include/linux/gfp.h \ -+ $(wildcard include/config/zone/dma.h) \ -+ $(wildcard include/config/zone/dma32.h) \ -+ include/linux/mmzone.h \ -+ $(wildcard include/config/force/max/zoneorder.h) \ -+ $(wildcard include/config/arch/populates/node/map.h) \ -+ $(wildcard include/config/flat/node/mem/map.h) \ -+ $(wildcard include/config/have/memory/present.h) \ -+ $(wildcard include/config/need/node/memmap/size.h) \ -+ $(wildcard include/config/need/multiple/nodes.h) \ -+ $(wildcard include/config/have/arch/early/pfn/to/nid.h) \ -+ $(wildcard include/config/sparsemem/extreme.h) \ -+ $(wildcard include/config/nodes/span/other/nodes.h) \ -+ $(wildcard include/config/holes/in/zone.h) \ -+ include/linux/wait.h \ -+ include/asm/current.h \ -+ include/linux/numa.h \ -+ $(wildcard include/config/nodes/shift.h) \ -+ include/linux/nodemask.h \ -+ include/linux/memory_hotplug.h \ -+ $(wildcard include/config/have/arch/nodedata/extension.h) \ -+ include/linux/notifier.h \ -+ include/linux/mutex.h \ -+ $(wildcard include/config/debug/mutexes.h) \ -+ $(wildcard include/config/chopstix.h) \ -+ include/linux/rwsem.h \ -+ $(wildcard include/config/rwsem/generic/spinlock.h) \ -+ include/asm/rwsem.h \ -+ include/linux/srcu.h \ -+ include/linux/topology.h \ -+ $(wildcard include/config/sched/smt.h) \ -+ $(wildcard include/config/sched/mc.h) \ -+ include/asm/topology.h \ -+ include/asm-generic/topology.h \ -+ include/linux/slab_def.h \ -+ include/linux/kmalloc_sizes.h \ -+ include/asm/mmu.h \ -+ include/asm/semaphore.h \ -+ include/linux/kobject.h \ -+ include/linux/sysfs.h \ -+ include/linux/kref.h \ -+ include/linux/moduleparam.h \ -+ include/asm/local.h \ -+ include/asm/module.h \ -+ $(wildcard include/config/m486.h) \ -+ $(wildcard include/config/m586.h) \ -+ $(wildcard include/config/m586tsc.h) \ -+ $(wildcard include/config/m586mmx.h) \ -+ $(wildcard include/config/mcore2.h) \ -+ $(wildcard include/config/m686.h) \ -+ $(wildcard include/config/mpentiumii.h) \ -+ $(wildcard include/config/mpentiumiii.h) \ -+ $(wildcard include/config/mpentiumm.h) \ -+ $(wildcard include/config/mpentium4.h) \ -+ $(wildcard include/config/mk6.h) \ -+ $(wildcard include/config/x86/elan.h) \ -+ $(wildcard include/config/mcrusoe.h) \ -+ $(wildcard include/config/mefficeon.h) \ -+ $(wildcard include/config/mwinchipc6.h) \ -+ $(wildcard include/config/mwinchip2.h) \ -+ $(wildcard include/config/mwinchip3d.h) \ -+ $(wildcard include/config/mcyrixiii.h) \ -+ $(wildcard include/config/mviac3/2.h) \ -+ $(wildcard include/config/mviac7.h) \ -+ $(wildcard include/config/mgeodegx1.h) \ -+ $(wildcard include/config/mgeode/lx.h) \ -+ include/linux/vmalloc.h \ -+ include/linux/pagemap.h \ -+ include/linux/mm.h \ -+ $(wildcard include/config/sysctl.h) \ -+ $(wildcard include/config/mmu.h) \ -+ $(wildcard include/config/stack/growsup.h) \ -+ $(wildcard include/config/debug/vm.h) \ -+ $(wildcard include/config/shmem.h) \ -+ $(wildcard include/config/split/ptlock/cpus.h) \ -+ $(wildcard include/config/ia64.h) \ -+ $(wildcard include/config/proc/fs.h) \ -+ $(wildcard include/config/debug/pagealloc.h) \ -+ include/linux/capability.h \ -+ include/linux/rbtree.h \ -+ include/linux/prio_tree.h \ -+ include/linux/fs.h \ -+ $(wildcard include/config/dnotify.h) \ -+ $(wildcard include/config/vserver/cowbl.h) \ -+ $(wildcard include/config/quota.h) \ -+ $(wildcard include/config/inotify.h) \ -+ $(wildcard include/config/security.h) \ -+ $(wildcard include/config/epoll.h) \ -+ $(wildcard include/config/auditsyscall.h) \ -+ $(wildcard include/config/block.h) \ -+ $(wildcard include/config/fs/xip.h) \ -+ $(wildcard include/config/migration.h) \ -+ include/linux/limits.h \ -+ include/linux/ioctl.h \ -+ include/asm/ioctl.h \ -+ include/asm-generic/ioctl.h \ -+ include/linux/kdev_t.h \ -+ include/linux/dcache.h \ -+ $(wildcard include/config/profiling.h) \ -+ include/linux/rcupdate.h \ -+ include/linux/namei.h \ -+ include/linux/radix-tree.h \ -+ include/linux/pid.h \ -+ include/linux/quota.h \ -+ include/linux/dqblk_xfs.h \ -+ include/linux/dqblk_v1.h \ -+ include/linux/dqblk_v2.h \ -+ include/linux/nfs_fs_i.h \ -+ include/linux/nfs.h \ -+ include/linux/sunrpc/msg_prot.h \ -+ include/linux/fcntl.h \ -+ include/asm/fcntl.h \ -+ include/asm-generic/fcntl.h \ -+ $(wildcard include/config/64bit.h) \ -+ include/linux/err.h \ -+ include/linux/debug_locks.h \ -+ $(wildcard include/config/debug/locking/api/selftests.h) \ -+ include/linux/backing-dev.h \ -+ include/linux/mm_types.h \ -+ include/asm/pgtable.h \ -+ $(wildcard include/config/highpte.h) \ -+ include/asm/paravirt.h \ -+ include/asm/pgtable-2level-defs.h \ -+ include/asm/pgtable-2level.h \ -+ include/asm-generic/pgtable.h \ -+ include/linux/page-flags.h \ -+ $(wildcard include/config/s390.h) \ -+ $(wildcard include/config/swap.h) \ -+ include/linux/vmstat.h \ -+ $(wildcard include/config/vm/event/counters.h) \ -+ include/linux/highmem.h \ -+ include/linux/uaccess.h \ -+ include/asm/uaccess.h \ -+ $(wildcard include/config/x86/intel/usercopy.h) \ -+ $(wildcard include/config/x86/wp/works/ok.h) \ -+ include/asm/cacheflush.h \ -+ $(wildcard include/config/debug/rodata.h) \ -+ include/asm/highmem.h \ -+ include/linux/interrupt.h \ -+ $(wildcard include/config/high/res/timers.h) \ -+ $(wildcard include/config/generic/irq/probe.h) \ -+ include/linux/irqreturn.h \ -+ include/linux/hardirq.h \ -+ $(wildcard include/config/preempt/bkl.h) \ -+ $(wildcard include/config/virt/cpu/accounting.h) \ -+ include/linux/smp_lock.h \ -+ $(wildcard include/config/lock/kernel.h) \ -+ include/linux/sched.h \ -+ $(wildcard include/config/no/hz.h) \ -+ $(wildcard include/config/detect/softlockup.h) \ -+ $(wildcard include/config/keys.h) \ -+ $(wildcard include/config/bsd/process/acct.h) \ -+ $(wildcard include/config/taskstats.h) \ -+ $(wildcard include/config/inotify/user.h) \ -+ $(wildcard include/config/schedstats.h) \ -+ $(wildcard include/config/task/delay/acct.h) \ -+ $(wildcard include/config/blk/dev/io/trace.h) \ -+ $(wildcard include/config/cc/stackprotector.h) \ -+ $(wildcard include/config/sysvipc.h) \ -+ $(wildcard include/config/rt/mutexes.h) \ -+ $(wildcard include/config/task/xacct.h) \ -+ $(wildcard include/config/cpusets.h) \ -+ $(wildcard include/config/compat.h) \ -+ $(wildcard include/config/fault/injection.h) \ -+ include/asm/param.h \ -+ $(wildcard include/config/hz.h) \ -+ include/linux/timex.h \ -+ $(wildcard include/config/time/interpolation.h) \ -+ include/asm/timex.h \ -+ include/asm/tsc.h \ -+ $(wildcard include/config/x86/tsc.h) \ -+ $(wildcard include/config/x86/generic.h) \ -+ include/linux/jiffies.h \ -+ include/linux/calc64.h \ -+ include/asm/div64.h \ -+ include/asm/cputime.h \ -+ include/asm-generic/cputime.h \ -+ include/linux/sem.h \ -+ include/linux/ipc.h \ -+ $(wildcard include/config/ipc/ns.h) \ -+ include/asm/ipcbuf.h \ -+ include/asm/sembuf.h \ -+ include/linux/signal.h \ -+ include/asm/signal.h \ -+ include/asm-generic/signal.h \ -+ include/asm/siginfo.h \ -+ include/asm-generic/siginfo.h \ -+ include/linux/securebits.h \ -+ include/linux/fs_struct.h \ -+ include/linux/completion.h \ -+ include/linux/seccomp.h \ -+ $(wildcard include/config/seccomp.h) \ -+ include/linux/futex.h \ -+ $(wildcard include/config/futex.h) \ -+ include/linux/rtmutex.h \ -+ $(wildcard include/config/debug/rt/mutexes.h) \ -+ include/linux/plist.h \ -+ $(wildcard include/config/debug/pi/list.h) \ -+ include/linux/param.h \ -+ include/linux/resource.h \ -+ include/asm/resource.h \ -+ include/asm-generic/resource.h \ -+ include/linux/timer.h \ -+ $(wildcard include/config/timer/stats.h) \ -+ include/linux/ktime.h \ -+ $(wildcard include/config/ktime/scalar.h) \ -+ include/linux/hrtimer.h \ -+ include/linux/task_io_accounting.h \ -+ $(wildcard include/config/task/io/accounting.h) \ -+ include/linux/aio.h \ -+ include/linux/workqueue.h \ -+ include/linux/aio_abi.h \ -+ include/linux/uio.h \ -+ include/asm/hardirq.h \ -+ include/linux/irq.h \ -+ $(wildcard include/config/irq/per/cpu.h) \ -+ $(wildcard include/config/irq/release/method.h) \ -+ $(wildcard include/config/generic/pending/irq.h) \ -+ $(wildcard include/config/irqbalance.h) \ -+ $(wildcard include/config/auto/irq/affinity.h) \ -+ $(wildcard include/config/generic/hardirqs/no//do/irq.h) \ -+ include/asm/irq.h \ -+ include/asm-i386/mach-default/irq_vectors.h \ -+ include/asm-i386/mach-default/irq_vectors_limits.h \ -+ include/asm/irq_regs.h \ -+ include/asm/hw_irq.h \ -+ include/linux/profile.h \ -+ include/asm/sections.h \ -+ include/asm-generic/sections.h \ -+ include/linux/irq_cpustat.h \ -+ include/linux/device.h \ -+ $(wildcard include/config/debug/devres.h) \ -+ include/linux/ioport.h \ -+ include/linux/klist.h \ -+ include/asm/device.h \ -+ include/asm/tlbflush.h \ -+ $(wildcard include/config/x86/invlpg.h) \ -+ include/linux/netdevice.h \ -+ $(wildcard include/config/ax25.h) \ -+ $(wildcard include/config/tr.h) \ -+ $(wildcard include/config/net/ipip.h) \ -+ $(wildcard include/config/net/ipgre.h) \ -+ $(wildcard include/config/ipv6/sit.h) \ -+ $(wildcard include/config/ipv6/tunnel.h) \ -+ $(wildcard include/config/wireless/ext.h) \ -+ $(wildcard include/config/netpoll.h) \ -+ $(wildcard include/config/netpoll/trap.h) \ -+ $(wildcard include/config/net/dma.h) \ -+ include/linux/if.h \ -+ include/linux/socket.h \ -+ include/asm/socket.h \ -+ include/asm/sockios.h \ -+ include/linux/sockios.h \ -+ include/linux/hdlc/ioctl.h \ -+ include/linux/if_ether.h \ -+ include/linux/skbuff.h \ -+ $(wildcard include/config/nf/conntrack.h) \ -+ $(wildcard include/config/bridge/netfilter.h) \ -+ $(wildcard include/config/vlan/8021q.h) \ -+ $(wildcard include/config/net/sched.h) \ -+ $(wildcard include/config/net/cls/act.h) \ -+ $(wildcard include/config/network/secmark.h) \ -+ include/linux/net.h \ -+ include/linux/random.h \ -+ include/linux/sysctl.h \ -+ $(wildcard include/config/icmp/ipod.h) \ -+ $(wildcard include/config/web100/net100.h) \ -+ $(wildcard include/config/web100/stats.h) \ -+ include/linux/textsearch.h \ -+ include/net/checksum.h \ -+ include/asm/checksum.h \ -+ include/linux/in6.h \ -+ include/linux/dmaengine.h \ -+ $(wildcard include/config/dma/engine.h) \ -+ include/linux/if_packet.h \ -+ include/linux/tcp.h \ -+ $(wildcard include/config/tcp/md5sig.h) \ -+ include/net/sock.h \ -+ $(wildcard include/config/security/network.h) \ -+ include/linux/security.h \ -+ $(wildcard include/config/security/network/xfrm.h) \ -+ include/linux/binfmts.h \ -+ include/linux/shm.h \ -+ include/asm/shmparam.h \ -+ include/asm/shmbuf.h \ -+ include/linux/msg.h \ -+ include/asm/msgbuf.h \ -+ include/linux/key.h \ -+ include/linux/xfrm.h \ -+ include/net/flow.h \ -+ $(wildcard include/config/ipv6/mip6.h) \ -+ include/linux/filter.h \ -+ include/net/dst.h \ -+ $(wildcard include/config/net/cls/route.h) \ -+ $(wildcard include/config/xfrm.h) \ -+ include/linux/rtnetlink.h \ -+ include/linux/netlink.h \ -+ include/linux/if_link.h \ -+ include/linux/if_addr.h \ -+ include/linux/neighbour.h \ -+ include/net/neighbour.h \ -+ include/linux/seq_file.h \ -+ include/net/rtnetlink.h \ -+ include/net/netlink.h \ -+ include/net/inet_connection_sock.h \ -+ include/linux/poll.h \ -+ include/asm/poll.h \ -+ include/asm-generic/poll.h \ -+ include/net/inet_sock.h \ -+ $(wildcard include/config/ipv6.h) \ -+ include/linux/jhash.h \ -+ include/net/request_sock.h \ -+ include/net/inet_timewait_sock.h \ -+ include/net/tcp_states.h \ -+ include/net/timewait_sock.h \ -+ include/linux/ipv6.h \ -+ $(wildcard include/config/ipv6/privacy.h) \ -+ $(wildcard include/config/ipv6/router/pref.h) \ -+ $(wildcard include/config/ipv6/route/info.h) \ -+ $(wildcard include/config/ipv6/optimistic/dad.h) \ -+ $(wildcard include/config/ipv6/subtrees.h) \ -+ include/linux/icmpv6.h \ -+ include/linux/udp.h \ -+ include/net/if_inet6.h \ -+ include/net/snmp.h \ -+ include/linux/snmp.h \ -+ include/net/ip6_checksum.h \ -+ include/net/ip.h \ -+ $(wildcard include/config/inet.h) \ -+ include/linux/ip.h \ -+ include/linux/in.h \ -+ include/linux/mii.h \ -+ include/linux/ethtool.h \ -+ include/linux/if_vlan.h \ -+ include/linux/etherdevice.h \ -+ drivers/net/igb/igb.h \ -+ $(wildcard include/config/dca.h) \ -+ $(wildcard include/config/inet/lro.h) \ -+ include/linux/pci.h \ -+ $(wildcard include/config/pci/msi.h) \ -+ $(wildcard include/config/pci.h) \ -+ $(wildcard include/config/ht/irq.h) \ -+ $(wildcard include/config/pci/domains.h) \ -+ include/linux/pci_regs.h \ -+ include/linux/mod_devicetable.h \ -+ include/linux/pci_ids.h \ -+ include/linux/dmapool.h \ -+ include/asm/io.h \ -+ $(wildcard include/config/x86/numaq.h) \ -+ include/asm-generic/iomap.h \ -+ include/asm/scatterlist.h \ -+ include/asm/pci.h \ -+ include/asm-generic/pci-dma-compat.h \ -+ include/linux/dma-mapping.h \ -+ include/asm/dma-mapping.h \ -+ include/asm-generic/pci.h \ -+ drivers/net/igb/kcompat.h \ -+ $(wildcard include/config/e1000/napi.h) \ -+ $(wildcard include/config/e1000e/napi.h) \ -+ $(wildcard include/config/ixgb/napi.h) \ -+ $(wildcard include/config/e1000/disable/packet/split.h) \ -+ $(wildcard include/config/space/len.h) \ -+ include/linux/version.h \ -+ include/linux/latency.h \ -+ drivers/net/igb/e1000_api.h \ -+ drivers/net/igb/e1000_hw.h \ -+ drivers/net/igb/e1000_osdep.h \ -+ drivers/net/igb/e1000_regs.h \ -+ drivers/net/igb/e1000_defines.h \ -+ $(wildcard include/config/res.h) \ -+ $(wildcard include/config/fault.h) \ -+ drivers/net/igb/e1000_mac.h \ -+ drivers/net/igb/e1000_phy.h \ -+ drivers/net/igb/e1000_nvm.h \ -+ drivers/net/igb/e1000_manage.h \ -+ drivers/net/igb/e1000_82575.h \ -+ -+drivers/net/igb/igb_main.o: $(deps_drivers/net/igb/igb_main.o) -+ -+$(deps_drivers/net/igb/igb_main.o): -Binary files vanilla/drivers/net/igb/igb.o and linux-i686-2.6.22/drivers/net/igb/igb.o differ -diff -Nru vanilla/drivers/net/igb/.igb.o.cmd linux-i686-2.6.22/drivers/net/igb/.igb.o.cmd ---- vanilla/drivers/net/igb/.igb.o.cmd 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/.igb.o.cmd 2009-07-16 19:53:45.000000000 -0400 -@@ -0,0 +1 @@ -+cmd_drivers/net/igb/igb.o := ld -m elf_i386 -m elf_i386 -r -o drivers/net/igb/igb.o drivers/net/igb/e1000_82575.o drivers/net/igb/igb_main.o drivers/net/igb/e1000_mac.o drivers/net/igb/e1000_nvm.o drivers/net/igb/e1000_phy.o drivers/net/igb/e1000_manage.o drivers/net/igb/igb_param.o drivers/net/igb/igb_ethtool.o drivers/net/igb/kcompat.o drivers/net/igb/e1000_api.o -diff -Nru vanilla/drivers/net/igb/igb_param.c linux-i686-2.6.22/drivers/net/igb/igb_param.c ---- vanilla/drivers/net/igb/igb_param.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/igb_param.c 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,408 @@ +Index: linux-2.6.22/drivers/net/igb/igb_param.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/igb_param.c 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,599 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ Copyright(c) 2007-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, @@ -23152,7 +21371,7 @@ diff -Nru vanilla/drivers/net/igb/igb_param.c linux-i686-2.6.22/drivers/net/igb/ +#else +#define IGB_PARAM(X, desc) \ + static int __devinitdata X[IGB_MAX_NIC+1] = IGB_PARAM_INIT; \ -+ static unsigned int num_##X = 0; \ ++ static unsigned int num_##X; \ + module_param_array_named(X, X, int, &num_##X, 0); \ + MODULE_PARM_DESC(X, desc); +#endif @@ -23167,13 +21386,13 @@ diff -Nru vanilla/drivers/net/igb/igb_param.c linux-i686-2.6.22/drivers/net/igb/ +#define MIN_ITR 120 +/* IntMode (Interrupt Mode) + * -+ * Valid Range: 0 - 3 ++ * Valid Range: 0 - 2 + * -+ * Default Value: 2 (MSI-X single queue) ++ * Default Value: 2 (MSI-X) + */ +IGB_PARAM(IntMode, "Interrupt Mode"); -+#define MAX_INTMODE 3 -+#define MIN_INTMODE 0 ++#define MAX_INTMODE IGB_INT_MODE_MSIX ++#define MIN_INTMODE IGB_INT_MODE_LEGACY + +/* LLIPort (Low Latency Interrupt TCP Port) + * @@ -23225,6 +21444,57 @@ diff -Nru vanilla/drivers/net/igb/igb_param.c linux-i686-2.6.22/drivers/net/igb/ +#define MIN_LRO_AGGR 2 +#endif + ++/* RSS (Enable RSS multiqueue receive) ++ * ++ * Valid Range: 0 - 8 ++ * ++ * Default Value: 1 ++ */ ++IGB_PARAM(RSS, "RSS - multiqueue receive count"); ++ ++#define DEFAULT_RSS 1 ++#define MAX_RSS ((adapter->hw.mac.type == e1000_82575) ? 4 : 8) ++#define MIN_RSS 0 ++ ++/* VMDQ (Enable VMDq multiqueue receive) ++ * ++ * Valid Range: 0 - 8 ++ * ++ * Default Value: 0 ++ */ ++IGB_PARAM(VMDQ, "VMDQ - VMDq multiqueue receive"); ++ ++#define DEFAULT_VMDQ 0 ++#define MAX_VMDQ MAX_RSS ++#define MIN_VMDQ 0 ++ ++#ifdef CONFIG_PCI_IOV ++/* max_vfs (Enable SR-IOV VF devices) ++ * ++ * Valid Range: 0 - 7 ++ * ++ * Default Value: 0 ++ */ ++IGB_PARAM(max_vfs, "max_vfs - SR-IOV VF devices"); ++ ++#define DEFAULT_SRIOV 0 ++#define MAX_SRIOV 7 ++#define MIN_SRIOV 0 ++ ++#endif /* CONFIG_PCI_IOV */ ++ ++/* QueuePairs (Enable TX/RX queue pairs for interrupt handling) ++ * ++ * Valid Range: 0 - 1 ++ * ++ * Default Value: 1 ++ */ ++IGB_PARAM(QueuePairs, "QueuePairs - TX/RX queue pairs for interrupt handling"); ++ ++#define DEFAULT_QUEUE_PAIRS 1 ++#define MAX_QUEUE_PAIRS 1 ++#define MIN_QUEUE_PAIRS 0 ++ +struct igb_option { + enum { enable_option, range_option, list_option } type; + const char *name; @@ -23323,7 +21593,7 @@ diff -Nru vanilla/drivers/net/igb/igb_param.c linux-i686-2.6.22/drivers/net/igb/ + .err = "using default of " __MODULE_STRING(DEFAULT_ITR), + .def = DEFAULT_ITR, + .arg = { .r = { .min = MIN_ITR, -+ .max = MAX_ITR }} ++ .max = MAX_ITR } } + }; + +#ifdef module_param_array @@ -23351,15 +21621,15 @@ diff -Nru vanilla/drivers/net/igb/igb_param.c linux-i686-2.6.22/drivers/net/igb/ + default: + igb_validate_option(&adapter->itr, &opt, + adapter); -+ /* save the setting, because the dynamic bits change itr */ -+ /* in case of invalid user value, default to conservative mode, -+ * else need to clear the lower two bits because they are ++ /* Save the setting, because the dynamic bits ++ * change itr. In case of invalid user value, ++ * default to conservative mode, else need to ++ * clear the lower two bits because they are + * used as control */ + if (adapter->itr == 3) { + adapter->itr_setting = adapter->itr; + adapter->itr = IGB_START_ITR; -+ } -+ else { ++ } else { + adapter->itr = 1000000000 / (adapter->itr * 256); + adapter->itr_setting = adapter->itr & ~3; + } @@ -23376,10 +21646,10 @@ diff -Nru vanilla/drivers/net/igb/igb_param.c linux-i686-2.6.22/drivers/net/igb/ + struct igb_option opt = { + .type = range_option, + .name = "Interrupt Mode", -+ .err = "defaulting to 2 (MSI-X single queue)", -+ .def = IGB_INT_MODE_MSIX_1Q, ++ .err = "defaulting to 2 (MSI-X)", ++ .def = IGB_INT_MODE_MSIX, + .arg = { .r = { .min = MIN_INTMODE, -+ .max = MAX_INTMODE }} ++ .max = MAX_INTMODE } } + }; + +#ifdef module_param_array @@ -23401,7 +21671,7 @@ diff -Nru vanilla/drivers/net/igb/igb_param.c linux-i686-2.6.22/drivers/net/igb/ + .err = "using default of " __MODULE_STRING(DEFAULT_LLIPORT), + .def = DEFAULT_LLIPORT, + .arg = { .r = { .min = MIN_LLIPORT, -+ .max = MAX_LLIPORT }} ++ .max = MAX_LLIPORT } } + }; + +#ifdef module_param_array @@ -23428,7 +21698,7 @@ diff -Nru vanilla/drivers/net/igb/igb_param.c linux-i686-2.6.22/drivers/net/igb/ + .err = "using default of " __MODULE_STRING(DEFAULT_LLISIZE), + .def = DEFAULT_LLISIZE, + .arg = { .r = { .min = MIN_LLISIZE, -+ .max = MAX_LLISIZE }} ++ .max = MAX_LLISIZE } } + }; + +#ifdef module_param_array @@ -23476,7 +21746,7 @@ diff -Nru vanilla/drivers/net/igb/igb_param.c linux-i686-2.6.22/drivers/net/igb/ + .err = "using default of " __MODULE_STRING(DEFAULT_LRO_AGGR), + .def = DEFAULT_LRO_AGGR, + .arg = { .r = { .min = MIN_LRO_AGGR, -+ .max = MAX_LRO_AGGR }} ++ .max = MAX_LRO_AGGR } } + }; + +#ifdef module_param_array @@ -23492,575 +21762,157 @@ diff -Nru vanilla/drivers/net/igb/igb_param.c linux-i686-2.6.22/drivers/net/igb/ +#endif + } +#endif /* IGB_LRO */ ++#ifdef CONFIG_PCI_IOV ++ { /* SRIOV - Enable SR-IOV VF devices */ ++ struct igb_option opt = { ++ .type = range_option, ++ .name = "max_vfs - SR-IOV VF devices", ++ .err = "using default of " __MODULE_STRING(DEFAULT_SRIOV), ++ .def = DEFAULT_SRIOV, ++ .arg = { .r = { .min = MIN_SRIOV, ++ .max = MAX_SRIOV } } ++ }; ++ ++#ifdef module_param_array ++ if (num_max_vfs > bd) { ++#endif ++ adapter->vfs_allocated_count = max_vfs[bd]; ++ igb_validate_option(&adapter->vfs_allocated_count, &opt, adapter); ++ ++#ifdef module_param_array ++ } else { ++ adapter->vfs_allocated_count = opt.def; ++ } ++#endif ++ if (adapter->hw.mac.type != e1000_82576 && adapter->vfs_allocated_count) { ++ adapter->vfs_allocated_count = 0; ++ DPRINTK(PROBE, INFO, "SR-IOV option max_vfs only supported on 82576.\n"); ++ } ++ } ++#endif /* CONFIG_PCI_IOV */ ++ { /* VMDQ - Enable VMDq multiqueue receive */ ++ struct igb_option opt = { ++ .type = range_option, ++ .name = "VMDQ - VMDq multiqueue receive count", ++ .err = "using default of " __MODULE_STRING(DEFAULT_VMDQ), ++ .def = DEFAULT_VMDQ, ++ .arg = { .r = { .min = MIN_VMDQ, ++ .max = (MAX_VMDQ - adapter->vfs_allocated_count) } } ++ }; ++#ifdef module_param_array ++ if (num_VMDQ > bd) { ++#endif ++ adapter->VMDQ_queues = VMDQ[bd]; ++ if (adapter->vfs_allocated_count && !adapter->VMDQ_queues) { ++ DPRINTK(PROBE, INFO, "Enabling SR-IOV requires VMDq be set to at least 1\n"); ++ adapter->VMDQ_queues = 1; ++ } ++ igb_validate_option(&adapter->VMDQ_queues, &opt, adapter); ++ ++#ifdef module_param_array ++ } else { ++ if (!adapter->vfs_allocated_count) ++ adapter->VMDQ_queues = opt.def; ++ else ++ adapter->VMDQ_queues = 1; ++ } ++#endif ++ } ++ { /* RSS - Enable RSS multiqueue receives */ ++ struct igb_option opt = { ++ .type = range_option, ++ .name = "RSS - RSS multiqueue receive count", ++ .err = "using default of " __MODULE_STRING(DEFAULT_RSS), ++ .def = DEFAULT_RSS, ++ .arg = { .r = { .min = MIN_RSS, ++ .max = MAX_RSS } } ++ }; ++ ++ if (adapter->VMDQ_queues) { ++ switch (adapter->hw.mac.type) { ++ case e1000_82576: ++ opt.arg.r.max = 2; ++ break; ++ case e1000_82575: ++ if (adapter->VMDQ_queues == 2) ++ opt.arg.r.max = 3; ++ if (adapter->VMDQ_queues <= 2) ++ break; ++ default: ++ opt.arg.r.max = 1; ++ break; ++ } ++ } ++ ++#ifdef module_param_array ++ if (num_RSS > bd) { ++#endif ++ adapter->RSS_queues = RSS[bd]; ++ switch (adapter->RSS_queues) { ++ case 1: ++ break; ++ default: ++ igb_validate_option(&adapter->RSS_queues, &opt, adapter); ++ if (adapter->RSS_queues) ++ break; ++ case 0: ++ adapter->RSS_queues = min_t(u32, opt.arg.r.max, num_online_cpus()); ++ break; ++ } ++#ifdef module_param_array ++ } else { ++ adapter->RSS_queues = opt.def; ++ } ++#endif ++ } ++ { /* QueuePairs - Enable TX/RX queue pairs for interrupt handling */ ++ struct igb_option opt = { ++ .type = enable_option, ++ .name = "QueuePairs - TX/RX queue pairs for interrupt handling", ++ .err = "defaulting to Enabled", ++ .def = OPTION_ENABLED ++ }; ++ ++#ifdef module_param_array ++ if (num_QueuePairs > bd) { ++#endif ++ unsigned int qp = QueuePairs[bd]; ++ /* ++ * we must enable queue pairs if the number of queues ++ * exceeds the number of avaialble interrupts. We are ++ * limited to 10, or 3 per unallocated vf. ++ */ ++ if ((adapter->RSS_queues > 4) || ++ (adapter->VMDQ_queues > 4) || ++ ((adapter->RSS_queues > 1) && ++ ((adapter->VMDQ_queues > 3) || ++ (adapter->vfs_allocated_count > 6)))) { ++ if (qp == OPTION_DISABLED) { ++ qp = OPTION_ENABLED; ++ DPRINTK(PROBE, INFO, ++ "Number of queues exceeds available interrupts, %s\n",opt.err); ++ } ++ } ++ igb_validate_option(&qp, &opt, adapter); ++ adapter->flags |= qp ? IGB_FLAG_QUEUE_PAIRS : 0; ++ ++#ifdef module_param_array ++ } else { ++ adapter->flags |= opt.def ? IGB_FLAG_QUEUE_PAIRS : 0; ++ } ++#endif ++ } +} + -Binary files vanilla/drivers/net/igb/igb_param.o and linux-i686-2.6.22/drivers/net/igb/igb_param.o differ -diff -Nru vanilla/drivers/net/igb/.igb_param.o.cmd linux-i686-2.6.22/drivers/net/igb/.igb_param.o.cmd ---- vanilla/drivers/net/igb/.igb_param.o.cmd 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/.igb_param.o.cmd 2009-07-16 19:53:43.000000000 -0400 -@@ -0,0 +1,554 @@ -+cmd_drivers/net/igb/igb_param.o := gcc -m32 -Wp,-MD,drivers/net/igb/.igb_param.o.d -nostdinc -isystem /usr/lib/gcc/i386-redhat-linux/4.1.2/include -D__KERNEL__ -Iinclude -include include/linux/autoconf.h -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Os -pipe -msoft-float -mregparm=3 -freg-struct-return -mpreferred-stack-boundary=2 -march=i686 -mtune=generic -ffreestanding -maccumulate-outgoing-args -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -Iinclude/asm-i386/mach-generic -Iinclude/asm-i386/mach-default -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -DMODULE -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(igb_param)" -D"KBUILD_MODNAME=KBUILD_STR(igb)" -c -o drivers/net/igb/.tmp_igb_param.o drivers/net/igb/igb_param.c -+ -+deps_drivers/net/igb/igb_param.o := \ -+ drivers/net/igb/igb_param.c \ -+ include/linux/netdevice.h \ -+ $(wildcard include/config/ax25.h) \ -+ $(wildcard include/config/tr.h) \ -+ $(wildcard include/config/net/ipip.h) \ -+ $(wildcard include/config/net/ipgre.h) \ -+ $(wildcard include/config/ipv6/sit.h) \ -+ $(wildcard include/config/ipv6/tunnel.h) \ -+ $(wildcard include/config/wireless/ext.h) \ -+ $(wildcard include/config/netpoll.h) \ -+ $(wildcard include/config/net/poll/controller.h) \ -+ $(wildcard include/config/netpoll/trap.h) \ -+ $(wildcard include/config/net/dma.h) \ -+ $(wildcard include/config/bug.h) \ -+ $(wildcard include/config/proc/fs.h) \ -+ include/linux/if.h \ -+ include/linux/types.h \ -+ $(wildcard include/config/uid16.h) \ -+ $(wildcard include/config/lbd.h) \ -+ $(wildcard include/config/lsf.h) \ -+ $(wildcard include/config/resources/64bit.h) \ -+ include/linux/posix_types.h \ -+ include/linux/stddef.h \ -+ include/linux/compiler.h \ -+ $(wildcard include/config/enable/must/check.h) \ -+ include/linux/compiler-gcc4.h \ -+ $(wildcard include/config/forced/inlining.h) \ -+ include/linux/compiler-gcc.h \ -+ include/asm/posix_types.h \ -+ include/asm/types.h \ -+ $(wildcard include/config/highmem64g.h) \ -+ include/linux/socket.h \ -+ $(wildcard include/config/compat.h) \ -+ include/asm/socket.h \ -+ include/asm/sockios.h \ -+ include/linux/sockios.h \ -+ include/linux/uio.h \ -+ include/linux/hdlc/ioctl.h \ -+ include/linux/if_ether.h \ -+ $(wildcard include/config/sysctl.h) \ -+ include/linux/skbuff.h \ -+ $(wildcard include/config/nf/conntrack.h) \ -+ $(wildcard include/config/bridge/netfilter.h) \ -+ $(wildcard include/config/vlan/8021q.h) \ -+ $(wildcard include/config/net/sched.h) \ -+ $(wildcard include/config/net/cls/act.h) \ -+ $(wildcard include/config/network/secmark.h) \ -+ include/linux/kernel.h \ -+ $(wildcard include/config/preempt/voluntary.h) \ -+ $(wildcard include/config/debug/spinlock/sleep.h) \ -+ $(wildcard include/config/printk.h) \ -+ $(wildcard include/config/numa.h) \ -+ /usr/lib/gcc/i386-redhat-linux/4.1.2/include/stdarg.h \ -+ include/linux/linkage.h \ -+ include/asm/linkage.h \ -+ $(wildcard include/config/x86/alignment/16.h) \ -+ include/linux/bitops.h \ -+ include/asm/bitops.h \ -+ include/asm/alternative.h \ -+ $(wildcard include/config/smp.h) \ -+ $(wildcard include/config/paravirt.h) \ -+ include/asm-generic/bitops/sched.h \ -+ include/asm-generic/bitops/hweight.h \ -+ include/asm-generic/bitops/fls64.h \ -+ include/asm-generic/bitops/ext2-non-atomic.h \ -+ include/asm-generic/bitops/le.h \ -+ include/asm/byteorder.h \ -+ $(wildcard include/config/x86/bswap.h) \ -+ include/linux/byteorder/little_endian.h \ -+ include/linux/byteorder/swab.h \ -+ include/linux/byteorder/generic.h \ -+ include/asm-generic/bitops/minix.h \ -+ include/linux/log2.h \ -+ $(wildcard include/config/arch/has/ilog2/u32.h) \ -+ $(wildcard include/config/arch/has/ilog2/u64.h) \ -+ include/asm/bug.h \ -+ $(wildcard include/config/debug/bugverbose.h) \ -+ include/asm-generic/bug.h \ -+ $(wildcard include/config/generic/bug.h) \ -+ include/linux/time.h \ -+ include/linux/seqlock.h \ -+ include/linux/spinlock.h \ -+ $(wildcard include/config/debug/spinlock.h) \ -+ $(wildcard include/config/preempt.h) \ -+ $(wildcard include/config/debug/lock/alloc.h) \ -+ include/linux/preempt.h \ -+ $(wildcard include/config/debug/preempt.h) \ -+ include/linux/thread_info.h \ -+ include/asm/thread_info.h \ -+ $(wildcard include/config/4kstacks.h) \ -+ $(wildcard include/config/debug/stack/usage.h) \ -+ include/asm/page.h \ -+ $(wildcard include/config/x86/use/3dnow.h) \ -+ $(wildcard include/config/x86/pae.h) \ -+ $(wildcard include/config/hugetlb/page.h) \ -+ $(wildcard include/config/highmem4g.h) \ -+ $(wildcard include/config/page/offset.h) \ -+ $(wildcard include/config/flatmem.h) \ -+ include/asm-generic/pgtable-nopmd.h \ -+ include/asm-generic/pgtable-nopud.h \ -+ include/asm-generic/memory_model.h \ -+ $(wildcard include/config/discontigmem.h) \ -+ $(wildcard include/config/sparsemem.h) \ -+ $(wildcard include/config/out/of/line/pfn/to/page.h) \ -+ include/asm-generic/page.h \ -+ include/asm/processor.h \ -+ $(wildcard include/config/x86/ht.h) \ -+ $(wildcard include/config/mk8.h) \ -+ $(wildcard include/config/mk7.h) \ -+ include/asm/vm86.h \ -+ $(wildcard include/config/vm86.h) \ -+ include/asm/ptrace.h \ -+ include/asm/ptrace-abi.h \ -+ include/asm/segment.h \ -+ include/asm/math_emu.h \ -+ include/asm/sigcontext.h \ -+ include/asm/cpufeature.h \ -+ include/asm/required-features.h \ -+ $(wildcard include/config/x86/minimum/cpu.h) \ -+ $(wildcard include/config/x86/cmov.h) \ -+ $(wildcard include/config/x86/cmpxchg64.h) \ -+ include/asm/msr.h \ -+ include/asm/msr-index.h \ -+ include/asm/errno.h \ -+ include/asm-generic/errno.h \ -+ include/asm-generic/errno-base.h \ -+ include/linux/errno.h \ -+ include/asm/system.h \ -+ $(wildcard include/config/x86/oostore.h) \ -+ include/asm/cmpxchg.h \ -+ $(wildcard include/config/x86/cmpxchg.h) \ -+ include/linux/irqflags.h \ -+ $(wildcard include/config/trace/irqflags.h) \ -+ $(wildcard include/config/trace/irqflags/support.h) \ -+ $(wildcard include/config/x86.h) \ -+ include/asm/irqflags.h \ -+ include/asm/processor-flags.h \ -+ include/linux/cache.h \ -+ include/asm/cache.h \ -+ $(wildcard include/config/x86/l1/cache/shift.h) \ -+ include/linux/threads.h \ -+ $(wildcard include/config/nr/cpus.h) \ -+ $(wildcard include/config/base/small.h) \ -+ include/asm/percpu.h \ -+ include/linux/cpumask.h \ -+ $(wildcard include/config/hotplug/cpu.h) \ -+ include/linux/bitmap.h \ -+ include/linux/string.h \ -+ include/asm/string.h \ -+ include/linux/init.h \ -+ $(wildcard include/config/modules.h) \ -+ $(wildcard include/config/hotplug.h) \ -+ $(wildcard include/config/memory/hotplug.h) \ -+ $(wildcard include/config/acpi/hotplug/memory.h) \ -+ include/linux/stringify.h \ -+ include/linux/bottom_half.h \ -+ include/linux/spinlock_types.h \ -+ include/linux/lockdep.h \ -+ $(wildcard include/config/lockdep.h) \ -+ $(wildcard include/config/generic/hardirqs.h) \ -+ $(wildcard include/config/prove/locking.h) \ -+ include/asm/spinlock_types.h \ -+ include/asm/spinlock.h \ -+ $(wildcard include/config/x86/ppro/fence.h) \ -+ include/asm/atomic.h \ -+ $(wildcard include/config/m386.h) \ -+ include/asm-generic/atomic.h \ -+ include/asm/rwlock.h \ -+ include/linux/spinlock_api_smp.h \ -+ include/linux/vs_time.h \ -+ $(wildcard include/config/vserver/vtime.h) \ -+ include/linux/net.h \ -+ include/linux/wait.h \ -+ include/linux/list.h \ -+ $(wildcard include/config/debug/list.h) \ -+ include/linux/poison.h \ -+ include/linux/prefetch.h \ -+ include/asm/current.h \ -+ include/linux/random.h \ -+ include/linux/ioctl.h \ -+ include/asm/ioctl.h \ -+ include/asm-generic/ioctl.h \ -+ include/linux/sysctl.h \ -+ $(wildcard include/config/icmp/ipod.h) \ -+ $(wildcard include/config/web100/net100.h) \ -+ $(wildcard include/config/web100/stats.h) \ -+ include/linux/textsearch.h \ -+ include/linux/module.h \ -+ $(wildcard include/config/modversions.h) \ -+ $(wildcard include/config/unused/symbols.h) \ -+ $(wildcard include/config/module/unload.h) \ -+ $(wildcard include/config/kallsyms.h) \ -+ $(wildcard include/config/sysfs.h) \ -+ include/linux/stat.h \ -+ include/asm/stat.h \ -+ include/linux/kmod.h \ -+ $(wildcard include/config/kmod.h) \ -+ include/linux/elf.h \ -+ include/linux/auxvec.h \ -+ include/asm/auxvec.h \ -+ include/linux/elf-em.h \ -+ include/asm/elf.h \ -+ include/asm/user.h \ -+ include/asm/desc.h \ -+ include/asm/ldt.h \ -+ include/linux/smp.h \ -+ include/asm/smp.h \ -+ $(wildcard include/config/x86/local/apic.h) \ -+ $(wildcard include/config/x86/io/apic.h) \ -+ include/asm/mpspec.h \ -+ $(wildcard include/config/acpi.h) \ -+ include/asm/mpspec_def.h \ -+ include/asm-i386/mach-generic/mach_mpspec.h \ -+ include/asm/apic.h \ -+ $(wildcard include/config/x86/good/apic.h) \ -+ include/linux/pm.h \ -+ $(wildcard include/config/pm.h) \ -+ include/linux/delay.h \ -+ include/asm/delay.h \ -+ include/asm/fixmap.h \ -+ $(wildcard include/config/highmem.h) \ -+ $(wildcard include/config/x86/visws/apic.h) \ -+ $(wildcard include/config/x86/f00f/bug.h) \ -+ $(wildcard include/config/x86/cyclone/timer.h) \ -+ $(wildcard include/config/pci/mmconfig.h) \ -+ include/asm/acpi.h \ -+ $(wildcard include/config/acpi/sleep.h) \ -+ include/acpi/pdc_intel.h \ -+ include/asm/apicdef.h \ -+ include/asm/kmap_types.h \ -+ $(wildcard include/config/debug/highmem.h) \ -+ include/asm/io_apic.h \ -+ include/asm-i386/mach-generic/mach_apicdef.h \ -+ include/asm/genapic.h \ -+ include/linux/percpu.h \ -+ include/linux/slab.h \ -+ $(wildcard include/config/slab/debug.h) \ -+ $(wildcard include/config/slab.h) \ -+ $(wildcard include/config/slub.h) \ -+ $(wildcard include/config/debug/slab.h) \ -+ include/linux/gfp.h \ -+ $(wildcard include/config/zone/dma.h) \ -+ $(wildcard include/config/zone/dma32.h) \ -+ include/linux/mmzone.h \ -+ $(wildcard include/config/force/max/zoneorder.h) \ -+ $(wildcard include/config/arch/populates/node/map.h) \ -+ $(wildcard include/config/flat/node/mem/map.h) \ -+ $(wildcard include/config/have/memory/present.h) \ -+ $(wildcard include/config/need/node/memmap/size.h) \ -+ $(wildcard include/config/need/multiple/nodes.h) \ -+ $(wildcard include/config/have/arch/early/pfn/to/nid.h) \ -+ $(wildcard include/config/sparsemem/extreme.h) \ -+ $(wildcard include/config/nodes/span/other/nodes.h) \ -+ $(wildcard include/config/holes/in/zone.h) \ -+ include/linux/numa.h \ -+ $(wildcard include/config/nodes/shift.h) \ -+ include/linux/nodemask.h \ -+ include/linux/memory_hotplug.h \ -+ $(wildcard include/config/have/arch/nodedata/extension.h) \ -+ include/linux/notifier.h \ -+ include/linux/mutex.h \ -+ $(wildcard include/config/debug/mutexes.h) \ -+ $(wildcard include/config/chopstix.h) \ -+ include/linux/rwsem.h \ -+ $(wildcard include/config/rwsem/generic/spinlock.h) \ -+ include/asm/rwsem.h \ -+ include/linux/srcu.h \ -+ include/linux/topology.h \ -+ $(wildcard include/config/sched/smt.h) \ -+ $(wildcard include/config/sched/mc.h) \ -+ include/asm/topology.h \ -+ include/asm-generic/topology.h \ -+ include/linux/slab_def.h \ -+ include/linux/kmalloc_sizes.h \ -+ include/asm/mmu.h \ -+ include/asm/semaphore.h \ -+ include/linux/kobject.h \ -+ include/linux/sysfs.h \ -+ include/linux/kref.h \ -+ include/linux/moduleparam.h \ -+ include/asm/local.h \ -+ include/asm/module.h \ -+ $(wildcard include/config/m486.h) \ -+ $(wildcard include/config/m586.h) \ -+ $(wildcard include/config/m586tsc.h) \ -+ $(wildcard include/config/m586mmx.h) \ -+ $(wildcard include/config/mcore2.h) \ -+ $(wildcard include/config/m686.h) \ -+ $(wildcard include/config/mpentiumii.h) \ -+ $(wildcard include/config/mpentiumiii.h) \ -+ $(wildcard include/config/mpentiumm.h) \ -+ $(wildcard include/config/mpentium4.h) \ -+ $(wildcard include/config/mk6.h) \ -+ $(wildcard include/config/x86/elan.h) \ -+ $(wildcard include/config/mcrusoe.h) \ -+ $(wildcard include/config/mefficeon.h) \ -+ $(wildcard include/config/mwinchipc6.h) \ -+ $(wildcard include/config/mwinchip2.h) \ -+ $(wildcard include/config/mwinchip3d.h) \ -+ $(wildcard include/config/mcyrixiii.h) \ -+ $(wildcard include/config/mviac3/2.h) \ -+ $(wildcard include/config/mviac7.h) \ -+ $(wildcard include/config/mgeodegx1.h) \ -+ $(wildcard include/config/mgeode/lx.h) \ -+ include/linux/err.h \ -+ include/net/checksum.h \ -+ include/asm/uaccess.h \ -+ $(wildcard include/config/x86/intel/usercopy.h) \ -+ $(wildcard include/config/x86/wp/works/ok.h) \ -+ include/asm/checksum.h \ -+ include/linux/in6.h \ -+ include/linux/rcupdate.h \ -+ include/linux/dmaengine.h \ -+ $(wildcard include/config/dma/engine.h) \ -+ include/linux/device.h \ -+ $(wildcard include/config/debug/devres.h) \ -+ include/linux/ioport.h \ -+ include/linux/klist.h \ -+ include/linux/completion.h \ -+ include/asm/device.h \ -+ include/linux/hrtimer.h \ -+ $(wildcard include/config/high/res/timers.h) \ -+ $(wildcard include/config/timer/stats.h) \ -+ include/linux/rbtree.h \ -+ include/linux/ktime.h \ -+ $(wildcard include/config/ktime/scalar.h) \ -+ include/linux/jiffies.h \ -+ include/linux/calc64.h \ -+ include/asm/div64.h \ -+ include/linux/timex.h \ -+ $(wildcard include/config/time/interpolation.h) \ -+ $(wildcard include/config/no/hz.h) \ -+ include/asm/param.h \ -+ $(wildcard include/config/hz.h) \ -+ include/asm/timex.h \ -+ include/asm/tsc.h \ -+ $(wildcard include/config/x86/tsc.h) \ -+ $(wildcard include/config/x86/generic.h) \ -+ include/linux/if_packet.h \ -+ include/linux/timer.h \ -+ include/linux/interrupt.h \ -+ $(wildcard include/config/generic/irq/probe.h) \ -+ include/linux/irqreturn.h \ -+ include/linux/hardirq.h \ -+ $(wildcard include/config/preempt/bkl.h) \ -+ $(wildcard include/config/virt/cpu/accounting.h) \ -+ include/linux/smp_lock.h \ -+ $(wildcard include/config/lock/kernel.h) \ -+ include/linux/sched.h \ -+ $(wildcard include/config/detect/softlockup.h) \ -+ $(wildcard include/config/split/ptlock/cpus.h) \ -+ $(wildcard include/config/keys.h) \ -+ $(wildcard include/config/bsd/process/acct.h) \ -+ $(wildcard include/config/taskstats.h) \ -+ $(wildcard include/config/inotify/user.h) \ -+ $(wildcard include/config/schedstats.h) \ -+ $(wildcard include/config/task/delay/acct.h) \ -+ $(wildcard include/config/blk/dev/io/trace.h) \ -+ $(wildcard include/config/cc/stackprotector.h) \ -+ $(wildcard include/config/sysvipc.h) \ -+ $(wildcard include/config/rt/mutexes.h) \ -+ $(wildcard include/config/task/xacct.h) \ -+ $(wildcard include/config/cpusets.h) \ -+ $(wildcard include/config/fault/injection.h) \ -+ include/linux/capability.h \ -+ include/asm/cputime.h \ -+ include/asm-generic/cputime.h \ -+ include/linux/sem.h \ -+ include/linux/ipc.h \ -+ $(wildcard include/config/ipc/ns.h) \ -+ include/asm/ipcbuf.h \ -+ include/asm/sembuf.h \ -+ include/linux/signal.h \ -+ include/asm/signal.h \ -+ include/asm-generic/signal.h \ -+ include/asm/siginfo.h \ -+ include/asm-generic/siginfo.h \ -+ include/linux/securebits.h \ -+ include/linux/fs_struct.h \ -+ include/linux/pid.h \ -+ include/linux/seccomp.h \ -+ $(wildcard include/config/seccomp.h) \ -+ include/linux/futex.h \ -+ $(wildcard include/config/futex.h) \ -+ include/linux/rtmutex.h \ -+ $(wildcard include/config/debug/rt/mutexes.h) \ -+ include/linux/plist.h \ -+ $(wildcard include/config/debug/pi/list.h) \ -+ include/linux/param.h \ -+ include/linux/resource.h \ -+ include/asm/resource.h \ -+ include/asm-generic/resource.h \ -+ include/linux/task_io_accounting.h \ -+ $(wildcard include/config/task/io/accounting.h) \ -+ include/linux/aio.h \ -+ include/linux/workqueue.h \ -+ include/linux/aio_abi.h \ -+ include/asm/hardirq.h \ -+ include/linux/irq.h \ -+ $(wildcard include/config/s390.h) \ -+ $(wildcard include/config/irq/per/cpu.h) \ -+ $(wildcard include/config/irq/release/method.h) \ -+ $(wildcard include/config/generic/pending/irq.h) \ -+ $(wildcard include/config/irqbalance.h) \ -+ $(wildcard include/config/auto/irq/affinity.h) \ -+ $(wildcard include/config/generic/hardirqs/no//do/irq.h) \ -+ include/asm/irq.h \ -+ include/asm-i386/mach-default/irq_vectors.h \ -+ include/asm-i386/mach-default/irq_vectors_limits.h \ -+ include/asm/irq_regs.h \ -+ include/asm/hw_irq.h \ -+ include/linux/profile.h \ -+ $(wildcard include/config/profiling.h) \ -+ include/asm/sections.h \ -+ include/asm-generic/sections.h \ -+ include/linux/irq_cpustat.h \ -+ drivers/net/igb/igb.h \ -+ $(wildcard include/config/dca.h) \ -+ $(wildcard include/config/inet/lro.h) \ -+ $(wildcard include/config/igb/separate/tx/handler.h) \ -+ $(wildcard include/config/igb/disable/packet/split.h) \ -+ include/linux/pci.h \ -+ $(wildcard include/config/pci/msi.h) \ -+ $(wildcard include/config/pci.h) \ -+ $(wildcard include/config/ht/irq.h) \ -+ $(wildcard include/config/pci/domains.h) \ -+ include/linux/pci_regs.h \ -+ include/linux/mod_devicetable.h \ -+ include/linux/pci_ids.h \ -+ include/linux/dmapool.h \ -+ include/asm/io.h \ -+ $(wildcard include/config/x86/numaq.h) \ -+ include/asm-generic/iomap.h \ -+ include/linux/vmalloc.h \ -+ include/asm/scatterlist.h \ -+ include/asm/pci.h \ -+ include/linux/mm.h \ -+ $(wildcard include/config/mmu.h) \ -+ $(wildcard include/config/stack/growsup.h) \ -+ $(wildcard include/config/debug/vm.h) \ -+ $(wildcard include/config/shmem.h) \ -+ $(wildcard include/config/ia64.h) \ -+ $(wildcard include/config/debug/pagealloc.h) \ -+ include/linux/prio_tree.h \ -+ include/linux/fs.h \ -+ $(wildcard include/config/dnotify.h) \ -+ $(wildcard include/config/vserver/cowbl.h) \ -+ $(wildcard include/config/quota.h) \ -+ $(wildcard include/config/inotify.h) \ -+ $(wildcard include/config/security.h) \ -+ $(wildcard include/config/epoll.h) \ -+ $(wildcard include/config/auditsyscall.h) \ -+ $(wildcard include/config/block.h) \ -+ $(wildcard include/config/fs/xip.h) \ -+ $(wildcard include/config/migration.h) \ -+ include/linux/limits.h \ -+ include/linux/kdev_t.h \ -+ include/linux/dcache.h \ -+ include/linux/namei.h \ -+ include/linux/radix-tree.h \ -+ include/linux/quota.h \ -+ include/linux/dqblk_xfs.h \ -+ include/linux/dqblk_v1.h \ -+ include/linux/dqblk_v2.h \ -+ include/linux/nfs_fs_i.h \ -+ include/linux/nfs.h \ -+ include/linux/sunrpc/msg_prot.h \ -+ include/linux/fcntl.h \ -+ include/asm/fcntl.h \ -+ include/asm-generic/fcntl.h \ -+ $(wildcard include/config/64bit.h) \ -+ include/linux/debug_locks.h \ -+ $(wildcard include/config/debug/locking/api/selftests.h) \ -+ include/linux/backing-dev.h \ -+ include/linux/mm_types.h \ -+ include/asm/pgtable.h \ -+ $(wildcard include/config/highpte.h) \ -+ include/asm/paravirt.h \ -+ include/asm/pgtable-2level-defs.h \ -+ include/asm/pgtable-2level.h \ -+ include/asm-generic/pgtable.h \ -+ include/linux/page-flags.h \ -+ $(wildcard include/config/swap.h) \ -+ include/linux/vmstat.h \ -+ $(wildcard include/config/vm/event/counters.h) \ -+ include/asm-generic/pci-dma-compat.h \ -+ include/linux/dma-mapping.h \ -+ include/asm/dma-mapping.h \ -+ include/asm-generic/pci.h \ -+ include/linux/ethtool.h \ -+ drivers/net/igb/kcompat.h \ -+ $(wildcard include/config/e1000/napi.h) \ -+ $(wildcard include/config/e1000e/napi.h) \ -+ $(wildcard include/config/ixgb/napi.h) \ -+ $(wildcard include/config/e1000/disable/packet/split.h) \ -+ $(wildcard include/config/space/len.h) \ -+ $(wildcard include/config/netdevices/multiqueue.h) \ -+ include/linux/version.h \ -+ include/linux/etherdevice.h \ -+ include/linux/in.h \ -+ include/linux/ip.h \ -+ include/linux/udp.h \ -+ include/net/inet_sock.h \ -+ $(wildcard include/config/ipv6.h) \ -+ include/linux/jhash.h \ -+ include/net/flow.h \ -+ $(wildcard include/config/ipv6/mip6.h) \ -+ include/net/sock.h \ -+ $(wildcard include/config/security/network.h) \ -+ include/linux/security.h \ -+ $(wildcard include/config/security/network/xfrm.h) \ -+ include/linux/binfmts.h \ -+ include/linux/shm.h \ -+ include/asm/shmparam.h \ -+ include/asm/shmbuf.h \ -+ include/linux/msg.h \ -+ include/asm/msgbuf.h \ -+ include/linux/key.h \ -+ include/linux/xfrm.h \ -+ include/linux/filter.h \ -+ include/net/dst.h \ -+ $(wildcard include/config/net/cls/route.h) \ -+ $(wildcard include/config/xfrm.h) \ -+ include/linux/rtnetlink.h \ -+ include/linux/netlink.h \ -+ include/linux/if_link.h \ -+ include/linux/if_addr.h \ -+ include/linux/neighbour.h \ -+ include/net/neighbour.h \ -+ include/linux/seq_file.h \ -+ include/net/rtnetlink.h \ -+ include/net/netlink.h \ -+ include/net/request_sock.h \ -+ include/linux/mii.h \ -+ include/linux/latency.h \ -+ drivers/net/igb/e1000_api.h \ -+ drivers/net/igb/e1000_hw.h \ -+ drivers/net/igb/e1000_osdep.h \ -+ drivers/net/igb/e1000_regs.h \ -+ drivers/net/igb/e1000_defines.h \ -+ $(wildcard include/config/res.h) \ -+ $(wildcard include/config/fault.h) \ -+ drivers/net/igb/e1000_mac.h \ -+ drivers/net/igb/e1000_phy.h \ -+ drivers/net/igb/e1000_nvm.h \ -+ drivers/net/igb/e1000_manage.h \ -+ drivers/net/igb/e1000_82575.h \ -+ -+drivers/net/igb/igb_param.o: $(deps_drivers/net/igb/igb_param.o) -+ -+$(deps_drivers/net/igb/igb_param.o): -diff -Nru vanilla/drivers/net/igb/igb_regtest.h linux-i686-2.6.22/drivers/net/igb/igb_regtest.h ---- vanilla/drivers/net/igb/igb_regtest.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/igb_regtest.h 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,133 @@ +Index: linux-2.6.22/drivers/net/igb/igb_regtest.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/igb_regtest.h 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,135 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ Copyright(c) 2007-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, @@ -24117,26 +21969,29 @@ diff -Nru vanilla/drivers/net/igb/igb_regtest.h linux-i686-2.6.22/drivers/net/ig + { E1000_FCAH, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, + { E1000_FCT, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, + { E1000_VET, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, -+ { E1000_RDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, -+ { E1000_RDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, -+ { E1000_RDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, -+ { E1000_RDBAL(4), 0x40, 8, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, -+ { E1000_RDBAH(4), 0x40, 8, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, -+ { E1000_RDLEN(4), 0x40, 8, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, -+ /* Enable all four RX queues before testing. */ -+ { E1000_RXDCTL(0), 0x100, 1, WRITE_NO_TEST, 0, E1000_RXDCTL_QUEUE_ENABLE }, ++ { E1000_RDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, ++ { E1000_RDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, ++ { E1000_RDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, ++ { E1000_RDBAL(4), 0x40, 12, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, ++ { E1000_RDBAH(4), 0x40, 12, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, ++ { E1000_RDLEN(4), 0x40, 12, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, ++ /* Enable all queues before testing. */ ++ { E1000_RXDCTL(0), 0x100, 4, WRITE_NO_TEST, 0, E1000_RXDCTL_QUEUE_ENABLE }, ++ { E1000_RXDCTL(4), 0x40, 12, WRITE_NO_TEST, 0, E1000_RXDCTL_QUEUE_ENABLE }, + /* RDH is read-only for 82576, only test RDT. */ + { E1000_RDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, ++ { E1000_RDT(4), 0x40, 12, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, + { E1000_RXDCTL(0), 0x100, 4, WRITE_NO_TEST, 0, 0 }, ++ { E1000_RXDCTL(4), 0x40, 12, WRITE_NO_TEST, 0, 0 }, + { E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 }, + { E1000_FCTTV, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, + { E1000_TIPG, 0x100, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF }, + { E1000_TDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, + { E1000_TDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, + { E1000_TDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, -+ { E1000_TDBAL(4), 0x40, 8, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, -+ { E1000_TDBAH(4), 0x40, 8, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, -+ { E1000_TDLEN(4), 0x40, 8, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, ++ { E1000_TDBAL(4), 0x40, 12, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, ++ { E1000_TDBAH(4), 0x40, 12, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, ++ { E1000_TDLEN(4), 0x40, 12, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, + { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, + { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0x003FFFFB }, + { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0xFFFFFFFF }, @@ -24149,12 +22004,11 @@ diff -Nru vanilla/drivers/net/igb/igb_regtest.h linux-i686-2.6.22/drivers/net/ig + 0xFFFFFFFF, 0xFFFFFFFF }, + { E1000_RA2, 0, 8, TABLE64_TEST_HI, + 0x83FFFFFF, 0xFFFFFFFF }, -+ { E1000_MTA, 0, 128,TABLE32_TEST, ++ { E1000_MTA, 0, 128, TABLE32_TEST, + 0xFFFFFFFF, 0xFFFFFFFF }, + { 0, 0, 0, 0 } +}; + -+ +/* 82575 register test */ +static struct igb_reg_test reg_test_82575[] = { + { E1000_FCAL, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, @@ -24190,14 +22044,15 @@ diff -Nru vanilla/drivers/net/igb/igb_regtest.h linux-i686-2.6.22/drivers/net/ig +}; + + -diff -Nru vanilla/drivers/net/igb/kcompat.c linux-i686-2.6.22/drivers/net/igb/kcompat.c ---- vanilla/drivers/net/igb/kcompat.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/kcompat.c 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,413 @@ +Index: linux-2.6.22/drivers/net/igb/kcompat.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/kcompat.c 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,552 @@ +/******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++ Copyright(c) 2007-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, @@ -24212,3868 +22067,3508 @@ diff -Nru vanilla/drivers/net/igb/kcompat.c linux-i686-2.6.22/drivers/net/igb/kc + 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: -+ e1000-devel Mailing List -+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -+ -+*******************************************************************************/ -+ -+ -+ -+ -+#include "igb.h" -+ -+ -+ -+#include "kcompat.h" -+ -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) ) -+ -+/**************************************/ -+/* PCI DMA MAPPING */ -+ -+#if defined(CONFIG_HIGHMEM) -+ -+#ifndef PCI_DRAM_OFFSET -+#define PCI_DRAM_OFFSET 0 -+#endif -+ -+u64 -+_kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, -+ size_t size, int direction) -+{ -+ return (((u64) (page - mem_map) << PAGE_SHIFT) + offset + -+ PCI_DRAM_OFFSET); -+} -+ -+#else /* CONFIG_HIGHMEM */ -+ -+u64 -+_kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, -+ size_t size, int direction) -+{ -+ return pci_map_single(dev, (void *)page_address(page) + offset, size, -+ direction); -+} -+ -+#endif /* CONFIG_HIGHMEM */ -+ -+void -+_kc_pci_unmap_page(struct pci_dev *dev, u64 dma_addr, size_t size, -+ int direction) -+{ -+ return pci_unmap_single(dev, dma_addr, size, direction); -+} -+ -+#endif /* 2.4.13 => 2.4.3 */ -+ -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) ) -+ -+/**************************************/ -+/* PCI DRIVER API */ -+ -+int -+_kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask) -+{ -+ if (!pci_dma_supported(dev, mask)) -+ return -EIO; -+ dev->dma_mask = mask; -+ return 0; -+} -+ -+int -+_kc_pci_request_regions(struct pci_dev *dev, char *res_name) -+{ -+ int i; -+ -+ for (i = 0; i < 6; i++) { -+ if (pci_resource_len(dev, i) == 0) -+ continue; -+ -+ if (pci_resource_flags(dev, i) & IORESOURCE_IO) { -+ if (!request_region(pci_resource_start(dev, i), pci_resource_len(dev, i), res_name)) { -+ pci_release_regions(dev); -+ return -EBUSY; -+ } -+ } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) { -+ if (!request_mem_region(pci_resource_start(dev, i), pci_resource_len(dev, i), res_name)) { -+ pci_release_regions(dev); -+ return -EBUSY; -+ } -+ } -+ } -+ return 0; -+} -+ -+void -+_kc_pci_release_regions(struct pci_dev *dev) -+{ -+ int i; -+ -+ for (i = 0; i < 6; i++) { -+ if (pci_resource_len(dev, i) == 0) -+ continue; -+ -+ if (pci_resource_flags(dev, i) & IORESOURCE_IO) -+ release_region(pci_resource_start(dev, i), pci_resource_len(dev, i)); -+ -+ else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) -+ release_mem_region(pci_resource_start(dev, i), pci_resource_len(dev, i)); -+ } -+} -+ -+/**************************************/ -+/* NETWORK DRIVER API */ -+ -+struct net_device * -+_kc_alloc_etherdev(int sizeof_priv) -+{ -+ struct net_device *dev; -+ int alloc_size; -+ -+ alloc_size = sizeof(*dev) + sizeof_priv + IFNAMSIZ + 31; -+ dev = kmalloc(alloc_size, GFP_KERNEL); -+ if (!dev) -+ return NULL; -+ memset(dev, 0, alloc_size); -+ -+ if (sizeof_priv) -+ dev->priv = (void *) (((unsigned long)(dev + 1) + 31) & ~31); -+ dev->name[0] = '\0'; -+ ether_setup(dev); ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". + -+ return dev; -+} ++ Contact Information: ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + -+int -+_kc_is_valid_ether_addr(u8 *addr) -+{ -+ const char zaddr[6] = { 0, }; ++*******************************************************************************/ + -+ return !(addr[0] & 1) && memcmp(addr, zaddr, 6); -+} ++#include "igb.h" ++#include "kcompat.h" + -+#endif /* 2.4.3 => 2.4.0 */ ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,21) ) ++struct sk_buff * ++_kc_skb_pad(struct sk_buff *skb, int pad) ++{ ++ struct sk_buff *nskb; ++ ++ /* If the skbuff is non linear tailroom is always zero.. */ ++ if(skb_tailroom(skb) >= pad) ++ { ++ memset(skb->data+skb->len, 0, pad); ++ return skb; ++ } ++ ++ nskb = skb_copy_expand(skb, skb_headroom(skb), skb_tailroom(skb) + pad, GFP_ATOMIC); ++ kfree_skb(skb); ++ if(nskb) ++ memset(nskb->data+nskb->len, 0, pad); ++ return nskb; ++} ++#endif /* < 2.4.21 */ + +/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) ) ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) ) + -+int -+_kc_pci_set_power_state(struct pci_dev *dev, int state) -+{ -+ return 0; -+} ++/**************************************/ ++/* PCI DMA MAPPING */ + -+int -+_kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable) -+{ -+ return 0; -+} ++#if defined(CONFIG_HIGHMEM) + -+#endif /* 2.4.6 => 2.4.3 */ ++#ifndef PCI_DRAM_OFFSET ++#define PCI_DRAM_OFFSET 0 ++#endif + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) -+void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, -+ int off, int size) ++u64 ++_kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, ++ size_t size, int direction) +{ -+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; -+ frag->page = page; -+ frag->page_offset = off; -+ frag->size = size; -+ skb_shinfo(skb)->nr_frags = i + 1; ++ return (((u64) (page - mem_map) << PAGE_SHIFT) + offset + ++ PCI_DRAM_OFFSET); +} + -+/* -+ * Original Copyright: -+ * find_next_bit.c: fallback find next bit implementation -+ * -+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ */ ++#else /* CONFIG_HIGHMEM */ + -+/** -+ * find_next_bit - find the next set bit in a memory region -+ * @addr: The address to base the search on -+ * @offset: The bitnumber to start searching at -+ * @size: The maximum size to search -+ */ -+unsigned long find_next_bit(const unsigned long *addr, unsigned long size, -+ unsigned long offset) ++u64 ++_kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, ++ size_t size, int direction) +{ -+ const unsigned long *p = addr + BITOP_WORD(offset); -+ unsigned long result = offset & ~(BITS_PER_LONG-1); -+ unsigned long tmp; -+ -+ if (offset >= size) -+ return size; -+ size -= result; -+ offset %= BITS_PER_LONG; -+ if (offset) { -+ tmp = *(p++); -+ tmp &= (~0UL << offset); -+ if (size < BITS_PER_LONG) -+ goto found_first; -+ if (tmp) -+ goto found_middle; -+ size -= BITS_PER_LONG; -+ result += BITS_PER_LONG; -+ } -+ while (size & ~(BITS_PER_LONG-1)) { -+ if ((tmp = *(p++))) -+ goto found_middle; -+ result += BITS_PER_LONG; -+ size -= BITS_PER_LONG; -+ } -+ if (!size) -+ return result; -+ tmp = *p; -+ -+found_first: -+ tmp &= (~0UL >> (BITS_PER_LONG - size)); -+ if (tmp == 0UL) /* Are any bits set? */ -+ return result + size; /* Nope. */ -+found_middle: -+ return result + ffs(tmp); ++ return pci_map_single(dev, (void *)page_address(page) + offset, size, ++ direction); +} + -+#endif /* 2.6.0 => 2.4.6 */ ++#endif /* CONFIG_HIGHMEM */ + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ) -+void *_kc_kzalloc(size_t size, int flags) ++void ++_kc_pci_unmap_page(struct pci_dev *dev, u64 dma_addr, size_t size, ++ int direction) +{ -+ void *ret = kmalloc(size, flags); -+ if (ret) -+ memset(ret, 0, size); -+ return ret; ++ return pci_unmap_single(dev, dma_addr, size, direction); +} -+#endif /* <= 2.6.13 */ + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ) -+struct sk_buff *_kc_netdev_alloc_skb(struct net_device *dev, -+ unsigned int length) -+{ -+ /* 16 == NET_PAD_SKB */ -+ struct sk_buff *skb; -+ skb = alloc_skb(length + 16, GFP_ATOMIC); -+ if (likely(skb != NULL)) { -+ skb_reserve(skb, 16); -+ skb->dev = dev; -+ } -+ return skb; -+} -+#endif /* <= 2.6.17 */ ++#endif /* 2.4.13 => 2.4.3 */ + +/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ) -+int _kc_pci_save_state(struct pci_dev *pdev) -+{ -+ struct net_device *netdev = pci_get_drvdata(pdev); -+ struct adapter_struct *adapter = netdev_priv(netdev); -+ int size = PCI_CONFIG_SPACE_LEN, i; -+ u16 pcie_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_EXP); -+ u16 pcie_link_status; ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) ) + -+ if (pcie_cap_offset) { -+ if (!pci_read_config_word(pdev, -+ pcie_cap_offset + PCIE_LINK_STATUS, -+ &pcie_link_status)) -+ size = PCIE_CONFIG_SPACE_LEN; -+ } -+ pci_config_space_ich8lan(); -+#ifdef HAVE_PCI_ERS -+ if (adapter->config_space == NULL) -+#else -+ WARN_ON(adapter->config_space != NULL); -+#endif -+ adapter->config_space = kmalloc(size, GFP_KERNEL); -+ if (!adapter->config_space) { -+ printk(KERN_ERR "Out of memory in pci_save_state\n"); -+ return -ENOMEM; -+ } -+ for (i = 0; i < (size / 4); i++) -+ pci_read_config_dword(pdev, i * 4, &adapter->config_space[i]); -+ return 0; -+} ++/**************************************/ ++/* PCI DRIVER API */ + -+void _kc_pci_restore_state(struct pci_dev * pdev) ++int ++_kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask) +{ -+ struct net_device *netdev = pci_get_drvdata(pdev); -+ struct adapter_struct *adapter = netdev_priv(netdev); -+ int size = PCI_CONFIG_SPACE_LEN, i; -+ u16 pcie_cap_offset; -+ u16 pcie_link_status; -+ -+ if (adapter->config_space != NULL) { -+ pcie_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_EXP); -+ if (pcie_cap_offset && -+ !pci_read_config_word(pdev, -+ pcie_cap_offset + PCIE_LINK_STATUS, -+ &pcie_link_status)) -+ size = PCIE_CONFIG_SPACE_LEN; -+ -+ pci_config_space_ich8lan(); -+ for (i = 0; i < (size / 4); i++) -+ pci_write_config_dword(pdev, i * 4, adapter->config_space[i]); -+#ifndef HAVE_PCI_ERS -+ kfree(adapter->config_space); -+ adapter->config_space = NULL; -+#endif -+ } ++ if (!pci_dma_supported(dev, mask)) ++ return -EIO; ++ dev->dma_mask = mask; ++ return 0; +} + -+#ifdef HAVE_PCI_ERS -+void _kc_free_netdev(struct net_device *netdev) ++int ++_kc_pci_request_regions(struct pci_dev *dev, char *res_name) +{ -+ struct adapter_struct *adapter = netdev_priv(netdev); -+ -+ if (adapter->config_space != NULL) -+ kfree(adapter->config_space); -+#ifdef CONFIG_SYSFS -+ if (netdev->reg_state == NETREG_UNINITIALIZED) { -+ kfree((char *)netdev - netdev->padded); -+ } else { -+ BUG_ON(netdev->reg_state != NETREG_UNREGISTERED); -+ netdev->reg_state = NETREG_RELEASED; -+ class_device_put(&netdev->class_dev); -+ } -+#else -+ kfree((char *)netdev - netdev->padded); -+#endif -+} -+#endif -+#endif /* <= 2.6.18 */ ++ int i; + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) ) -+#endif /* < 2.6.23 */ ++ for (i = 0; i < 6; i++) { ++ if (pci_resource_len(dev, i) == 0) ++ continue; + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) ) -+#ifdef NAPI -+int __kc_adapter_clean(struct net_device *netdev, int *budget) -+{ -+ int work_done; -+ int work_to_do = min(*budget, netdev->quota); -+ /* kcompat.h netif_napi_add puts napi struct in "fake netdev->priv" */ -+ struct napi_struct *napi = netdev->priv; -+ work_done = napi->poll(napi, work_to_do); -+ *budget -= work_done; -+ netdev->quota -= work_done; -+ return work_done ? 1 : 0; ++ if (pci_resource_flags(dev, i) & IORESOURCE_IO) { ++ if (!request_region(pci_resource_start(dev, i), pci_resource_len(dev, i), res_name)) { ++ pci_release_regions(dev); ++ return -EBUSY; ++ } ++ } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) { ++ if (!request_mem_region(pci_resource_start(dev, i), pci_resource_len(dev, i), res_name)) { ++ pci_release_regions(dev); ++ return -EBUSY; ++ } ++ } ++ } ++ return 0; +} -+#endif /* NAPI */ -+#endif /* <= 2.6.24 */ -+ -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) ) -+#ifdef HAVE_TX_MQ -+void _kc_netif_tx_stop_all_queues(struct net_device *netdev) ++ ++void ++_kc_pci_release_regions(struct pci_dev *dev) +{ -+ struct adapter_struct *adapter = netdev_priv(netdev); + int i; + -+ netif_stop_queue(netdev); -+ if (netif_is_multiqueue(netdev)) -+ for (i = 0; i < adapter->num_tx_queues; i++) -+ netif_stop_subqueue(netdev, i); ++ for (i = 0; i < 6; i++) { ++ if (pci_resource_len(dev, i) == 0) ++ continue; ++ ++ if (pci_resource_flags(dev, i) & IORESOURCE_IO) ++ release_region(pci_resource_start(dev, i), pci_resource_len(dev, i)); ++ ++ else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) ++ release_mem_region(pci_resource_start(dev, i), pci_resource_len(dev, i)); ++ } +} -+void _kc_netif_tx_wake_all_queues(struct net_device *netdev) ++ ++/**************************************/ ++/* NETWORK DRIVER API */ ++ ++struct net_device * ++_kc_alloc_etherdev(int sizeof_priv) +{ -+ struct adapter_struct *adapter = netdev_priv(netdev); -+ int i; ++ struct net_device *dev; ++ int alloc_size; + -+ netif_wake_queue(netdev); -+ if (netif_is_multiqueue(netdev)) -+ for (i = 0; i < adapter->num_tx_queues; i++) -+ netif_wake_subqueue(netdev, i); ++ alloc_size = sizeof(*dev) + sizeof_priv + IFNAMSIZ + 31; ++ dev = kmalloc(alloc_size, GFP_KERNEL); ++ if (!dev) ++ return NULL; ++ memset(dev, 0, alloc_size); ++ ++ if (sizeof_priv) ++ dev->priv = (void *) (((unsigned long)(dev + 1) + 31) & ~31); ++ dev->name[0] = '\0'; ++ ether_setup(dev); ++ ++ return dev; +} -+void _kc_netif_tx_start_all_queues(struct net_device *netdev) ++ ++int ++_kc_is_valid_ether_addr(u8 *addr) +{ -+ struct adapter_struct *adapter = netdev_priv(netdev); -+ int i; ++ const char zaddr[6] = { 0, }; + -+ netif_start_queue(netdev); -+ if (netif_is_multiqueue(netdev)) -+ for (i = 0; i < adapter->num_tx_queues; i++) -+ netif_start_subqueue(netdev, i); ++ return !(addr[0] & 1) && memcmp(addr, zaddr, 6); +} -+#endif /* HAVE_TX_MQ */ -+#endif /* <= 2.6.27 */ -diff -Nru vanilla/drivers/net/igb/kcompat_ethtool.c linux-i686-2.6.22/drivers/net/igb/kcompat_ethtool.c ---- vanilla/drivers/net/igb/kcompat_ethtool.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/kcompat_ethtool.c 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,1168 @@ -+/******************************************************************************* + -+ Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 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. ++#endif /* 2.4.3 => 2.4.0 */ + -+ 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. ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) ) + -+ 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. ++int ++_kc_pci_set_power_state(struct pci_dev *dev, int state) ++{ ++ return 0; ++} + -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". ++int ++_kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable) ++{ ++ return 0; ++} + -+ Contact Information: -+ e1000-devel Mailing List -+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++#endif /* 2.4.6 => 2.4.3 */ + -+*******************************************************************************/ ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) ++void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, ++ int off, int size) ++{ ++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ++ frag->page = page; ++ frag->page_offset = off; ++ frag->size = size; ++ skb_shinfo(skb)->nr_frags = i + 1; ++} + +/* -+ * net/core/ethtool.c - Ethtool ioctl handler -+ * Copyright (c) 2003 Matthew Wilcox -+ * -+ * This file is where we call all the ethtool_ops commands to get -+ * the information ethtool needs. We fall back to calling do_ioctl() -+ * for drivers which haven't been converted to ethtool_ops yet. -+ * -+ * It's GPL, stupid. ++ * Original Copyright: ++ * find_next_bit.c: fallback find next bit implementation + * -+ * Modification by sfeldma@pobox.com to work as backward compat -+ * solution for pre-ethtool_ops kernels. -+ * - copied struct ethtool_ops from ethtool.h -+ * - defined SET_ETHTOOL_OPS -+ * - put in some #ifndef NETIF_F_xxx wrappers -+ * - changes refs to dev->ethtool_ops to ethtool_ops -+ * - changed dev_ethtool to ethtool_ioctl -+ * - remove EXPORT_SYMBOL()s -+ * - added _kc_ prefix in built-in ethtool_op_xxx ops. ++ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) + */ + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "kcompat.h" -+ -+#undef SUPPORTED_10000baseT_Full -+#define SUPPORTED_10000baseT_Full (1 << 12) -+#undef ADVERTISED_10000baseT_Full -+#define ADVERTISED_10000baseT_Full (1 << 12) -+#undef SPEED_10000 -+#define SPEED_10000 10000 ++/** ++ * find_next_bit - find the next set bit in a memory region ++ * @addr: The address to base the search on ++ * @offset: The bitnumber to start searching at ++ * @size: The maximum size to search ++ */ ++unsigned long find_next_bit(const unsigned long *addr, unsigned long size, ++ unsigned long offset) ++{ ++ const unsigned long *p = addr + BITOP_WORD(offset); ++ unsigned long result = offset & ~(BITS_PER_LONG-1); ++ unsigned long tmp; + -+#undef ethtool_ops -+#define ethtool_ops _kc_ethtool_ops ++ if (offset >= size) ++ return size; ++ size -= result; ++ offset %= BITS_PER_LONG; ++ if (offset) { ++ tmp = *(p++); ++ tmp &= (~0UL << offset); ++ if (size < BITS_PER_LONG) ++ goto found_first; ++ if (tmp) ++ goto found_middle; ++ size -= BITS_PER_LONG; ++ result += BITS_PER_LONG; ++ } ++ while (size & ~(BITS_PER_LONG-1)) { ++ if ((tmp = *(p++))) ++ goto found_middle; ++ result += BITS_PER_LONG; ++ size -= BITS_PER_LONG; ++ } ++ if (!size) ++ return result; ++ tmp = *p; + -+struct _kc_ethtool_ops { -+ int (*get_settings)(struct net_device *, struct ethtool_cmd *); -+ int (*set_settings)(struct net_device *, struct ethtool_cmd *); -+ void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); -+ int (*get_regs_len)(struct net_device *); -+ void (*get_regs)(struct net_device *, struct ethtool_regs *, void *); -+ void (*get_wol)(struct net_device *, struct ethtool_wolinfo *); -+ int (*set_wol)(struct net_device *, struct ethtool_wolinfo *); -+ u32 (*get_msglevel)(struct net_device *); -+ void (*set_msglevel)(struct net_device *, u32); -+ int (*nway_reset)(struct net_device *); -+ u32 (*get_link)(struct net_device *); -+ int (*get_eeprom_len)(struct net_device *); -+ int (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); -+ int (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); -+ int (*get_coalesce)(struct net_device *, struct ethtool_coalesce *); -+ int (*set_coalesce)(struct net_device *, struct ethtool_coalesce *); -+ void (*get_ringparam)(struct net_device *, struct ethtool_ringparam *); -+ int (*set_ringparam)(struct net_device *, struct ethtool_ringparam *); -+ void (*get_pauseparam)(struct net_device *, -+ struct ethtool_pauseparam*); -+ int (*set_pauseparam)(struct net_device *, -+ struct ethtool_pauseparam*); -+ u32 (*get_rx_csum)(struct net_device *); -+ int (*set_rx_csum)(struct net_device *, u32); -+ u32 (*get_tx_csum)(struct net_device *); -+ int (*set_tx_csum)(struct net_device *, u32); -+ u32 (*get_sg)(struct net_device *); -+ int (*set_sg)(struct net_device *, u32); -+ u32 (*get_tso)(struct net_device *); -+ int (*set_tso)(struct net_device *, u32); -+ int (*self_test_count)(struct net_device *); -+ void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); -+ void (*get_strings)(struct net_device *, u32 stringset, u8 *); -+ int (*phys_id)(struct net_device *, u32); -+ int (*get_stats_count)(struct net_device *); -+ void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, -+ u64 *); -+} *ethtool_ops = NULL; ++found_first: ++ tmp &= (~0UL >> (BITS_PER_LONG - size)); ++ if (tmp == 0UL) /* Are any bits set? */ ++ return result + size; /* Nope. */ ++found_middle: ++ return result + ffs(tmp); ++} + -+#undef SET_ETHTOOL_OPS -+#define SET_ETHTOOL_OPS(netdev, ops) (ethtool_ops = (ops)) ++#endif /* 2.6.0 => 2.4.6 */ + -+/* -+ * Some useful ethtool_ops methods that are device independent. If we find that -+ * all drivers want to do the same thing here, we can turn these into dev_() -+ * function calls. -+ */ ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ) ++void *_kc_kzalloc(size_t size, int flags) ++{ ++ void *ret = kmalloc(size, flags); ++ if (ret) ++ memset(ret, 0, size); ++ return ret; ++} ++#endif /* <= 2.6.13 */ + -+#undef ethtool_op_get_link -+#define ethtool_op_get_link _kc_ethtool_op_get_link -+u32 _kc_ethtool_op_get_link(struct net_device *dev) ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ) ++struct sk_buff *_kc_netdev_alloc_skb(struct net_device *dev, ++ unsigned int length) +{ -+ return netif_carrier_ok(dev) ? 1 : 0; ++ /* 16 == NET_PAD_SKB */ ++ struct sk_buff *skb; ++ skb = alloc_skb(length + 16, GFP_ATOMIC); ++ if (likely(skb != NULL)) { ++ skb_reserve(skb, 16); ++ skb->dev = dev; ++ } ++ return skb; +} ++#endif /* <= 2.6.17 */ + -+#undef ethtool_op_get_tx_csum -+#define ethtool_op_get_tx_csum _kc_ethtool_op_get_tx_csum -+u32 _kc_ethtool_op_get_tx_csum(struct net_device *dev) ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ) ++int _kc_pci_save_state(struct pci_dev *pdev) +{ -+#ifdef NETIF_F_IP_CSUM -+ return (dev->features & NETIF_F_IP_CSUM) != 0; ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct adapter_struct *adapter = netdev_priv(netdev); ++ int size = PCI_CONFIG_SPACE_LEN, i; ++ u16 pcie_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_EXP); ++ u16 pcie_link_status; ++ ++ if (pcie_cap_offset) { ++ if (!pci_read_config_word(pdev, ++ pcie_cap_offset + PCIE_LINK_STATUS, ++ &pcie_link_status)) ++ size = PCIE_CONFIG_SPACE_LEN; ++ } ++ pci_config_space_ich8lan(); ++#ifdef HAVE_PCI_ERS ++ if (adapter->config_space == NULL) +#else ++ WARN_ON(adapter->config_space != NULL); ++#endif ++ adapter->config_space = kmalloc(size, GFP_KERNEL); ++ if (!adapter->config_space) { ++ printk(KERN_ERR "Out of memory in pci_save_state\n"); ++ return -ENOMEM; ++ } ++ for (i = 0; i < (size / 4); i++) ++ pci_read_config_dword(pdev, i * 4, &adapter->config_space[i]); + return 0; ++} ++ ++void _kc_pci_restore_state(struct pci_dev * pdev) ++{ ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct adapter_struct *adapter = netdev_priv(netdev); ++ int size = PCI_CONFIG_SPACE_LEN, i; ++ u16 pcie_cap_offset; ++ u16 pcie_link_status; ++ ++ if (adapter->config_space != NULL) { ++ pcie_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_EXP); ++ if (pcie_cap_offset && ++ !pci_read_config_word(pdev, ++ pcie_cap_offset + PCIE_LINK_STATUS, ++ &pcie_link_status)) ++ size = PCIE_CONFIG_SPACE_LEN; ++ ++ pci_config_space_ich8lan(); ++ for (i = 0; i < (size / 4); i++) ++ pci_write_config_dword(pdev, i * 4, adapter->config_space[i]); ++#ifndef HAVE_PCI_ERS ++ kfree(adapter->config_space); ++ adapter->config_space = NULL; +#endif ++ } +} + -+#undef ethtool_op_set_tx_csum -+#define ethtool_op_set_tx_csum _kc_ethtool_op_set_tx_csum -+int _kc_ethtool_op_set_tx_csum(struct net_device *dev, u32 data) ++#ifdef HAVE_PCI_ERS ++void _kc_free_netdev(struct net_device *netdev) +{ -+#ifdef NETIF_F_IP_CSUM -+ if (data) -+#ifdef NETIF_F_IPV6_CSUM -+ dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); -+ else -+ dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); ++ struct adapter_struct *adapter = netdev_priv(netdev); ++ ++ if (adapter->config_space != NULL) ++ kfree(adapter->config_space); ++#ifdef CONFIG_SYSFS ++ if (netdev->reg_state == NETREG_UNINITIALIZED) { ++ kfree((char *)netdev - netdev->padded); ++ } else { ++ BUG_ON(netdev->reg_state != NETREG_UNREGISTERED); ++ netdev->reg_state = NETREG_RELEASED; ++ class_device_put(&netdev->class_dev); ++ } +#else -+ dev->features |= NETIF_F_IP_CSUM; -+ else -+ dev->features &= ~NETIF_F_IP_CSUM; ++ kfree((char *)netdev - netdev->padded); +#endif ++} +#endif ++#endif /* <= 2.6.18 */ + -+ return 0; ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) ) ++#ifdef NAPI ++struct net_device *napi_to_poll_dev(struct napi_struct *napi) ++{ ++ struct adapter_q_vector *q_vector = container_of(napi, ++ struct adapter_q_vector, ++ napi); ++ return &q_vector->poll_dev; +} + -+#undef ethtool_op_get_sg -+#define ethtool_op_get_sg _kc_ethtool_op_get_sg -+u32 _kc_ethtool_op_get_sg(struct net_device *dev) ++int __kc_adapter_clean(struct net_device *netdev, int *budget) +{ -+#ifdef NETIF_F_SG -+ return (dev->features & NETIF_F_SG) != 0; -+#else -+ return 0; -+#endif ++ int work_done; ++ int work_to_do = min(*budget, netdev->quota); ++ /* kcompat.h netif_napi_add puts napi struct in "fake netdev->priv" */ ++ struct napi_struct *napi = netdev->priv; ++ work_done = napi->poll(napi, work_to_do); ++ *budget -= work_done; ++ netdev->quota -= work_done; ++ return (work_done >= work_to_do) ? 1 : 0; +} ++#endif /* NAPI */ ++#endif /* <= 2.6.24 */ + -+#undef ethtool_op_set_sg -+#define ethtool_op_set_sg _kc_ethtool_op_set_sg -+int _kc_ethtool_op_set_sg(struct net_device *dev, u32 data) ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) ) ++#ifdef HAVE_TX_MQ ++void _kc_netif_tx_stop_all_queues(struct net_device *netdev) +{ -+#ifdef NETIF_F_SG -+ if (data) -+ dev->features |= NETIF_F_SG; -+ else -+ dev->features &= ~NETIF_F_SG; -+#endif ++ struct adapter_struct *adapter = netdev_priv(netdev); ++ int i; + -+ return 0; ++ netif_stop_queue(netdev); ++ if (netif_is_multiqueue(netdev)) ++ for (i = 0; i < adapter->num_tx_queues; i++) ++ netif_stop_subqueue(netdev, i); +} ++void _kc_netif_tx_wake_all_queues(struct net_device *netdev) ++{ ++ struct adapter_struct *adapter = netdev_priv(netdev); ++ int i; + -+#undef ethtool_op_get_tso -+#define ethtool_op_get_tso _kc_ethtool_op_get_tso -+u32 _kc_ethtool_op_get_tso(struct net_device *dev) ++ netif_wake_queue(netdev); ++ if (netif_is_multiqueue(netdev)) ++ for (i = 0; i < adapter->num_tx_queues; i++) ++ netif_wake_subqueue(netdev, i); ++} ++void _kc_netif_tx_start_all_queues(struct net_device *netdev) +{ -+#ifdef NETIF_F_TSO -+ return (dev->features & NETIF_F_TSO) != 0; -+#else -+ return 0; -+#endif ++ struct adapter_struct *adapter = netdev_priv(netdev); ++ int i; ++ ++ netif_start_queue(netdev); ++ if (netif_is_multiqueue(netdev)) ++ for (i = 0; i < adapter->num_tx_queues; i++) ++ netif_start_subqueue(netdev, i); +} ++#endif /* HAVE_TX_MQ */ ++#endif /* < 2.6.27 */ + -+#undef ethtool_op_set_tso -+#define ethtool_op_set_tso _kc_ethtool_op_set_tso -+int _kc_ethtool_op_set_tso(struct net_device *dev, u32 data) ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ) ++ ++int ++_kc_pci_prepare_to_sleep(struct pci_dev *dev) +{ -+#ifdef NETIF_F_TSO -+ if (data) -+ dev->features |= NETIF_F_TSO; -+ else -+ dev->features &= ~NETIF_F_TSO; -+#endif ++ pci_power_t target_state; ++ int error; + -+ return 0; -+} ++ target_state = pci_choose_state(dev, PMSG_SUSPEND); + -+/* Handlers for each ethtool command */ ++ pci_enable_wake(dev, target_state, true); + -+static int ethtool_get_settings(struct net_device *dev, void *useraddr) ++ error = pci_set_power_state(dev, target_state); ++ ++ if (error) ++ pci_enable_wake(dev, target_state, false); ++ ++ return error; ++} ++ ++int ++_kc_pci_wake_from_d3(struct pci_dev *dev, bool enable) +{ -+ struct ethtool_cmd cmd = { ETHTOOL_GSET }; + int err; + -+ if (!ethtool_ops->get_settings) -+ return -EOPNOTSUPP; ++ err = pci_enable_wake(dev, PCI_D3cold, enable); ++ if (err) ++ goto out; + -+ err = ethtool_ops->get_settings(dev, &cmd); -+ if (err < 0) -+ return err; ++ err = pci_enable_wake(dev, PCI_D3hot, enable); + -+ if (copy_to_user(useraddr, &cmd, sizeof(cmd))) -+ return -EFAULT; -+ return 0; ++out: ++ return err; +} ++#endif /* < 2.6.28 */ + -+static int ethtool_set_settings(struct net_device *dev, void *useraddr) ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) ) ++void _kc_pci_disable_link_state(struct pci_dev *pdev, int state) +{ -+ struct ethtool_cmd cmd; ++ struct pci_dev *parent = pdev->bus->self; ++ u16 link_state; ++ int pos; + -+ if (!ethtool_ops->set_settings) -+ return -EOPNOTSUPP; ++ if (!parent) ++ return; + -+ if (copy_from_user(&cmd, useraddr, sizeof(cmd))) -+ return -EFAULT; ++ pos = pci_find_capability(parent, PCI_CAP_ID_EXP); ++ if (pos) { ++ pci_read_config_word(parent, pos + PCI_EXP_LNKCTL, &link_state); ++ link_state &= ~state; ++ pci_write_config_word(parent, pos + PCI_EXP_LNKCTL, link_state); ++ } ++} ++#endif /* < 2.6.29 */ + -+ return ethtool_ops->set_settings(dev, &cmd); ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ) ++#ifdef HAVE_NETDEV_SELECT_QUEUE ++#include ++static u32 _kc_simple_tx_hashrnd; ++static u32 _kc_simple_tx_hashrnd_initialized; ++ ++u16 _kc_skb_tx_hash(struct net_device *dev, struct sk_buff *skb) ++{ ++ u32 addr1, addr2, ports; ++ u32 hash, ihl; ++ u8 ip_proto = 0; ++ ++ if (unlikely(!_kc_simple_tx_hashrnd_initialized)) { ++ get_random_bytes(&_kc_simple_tx_hashrnd, 4); ++ _kc_simple_tx_hashrnd_initialized = 1; ++ } ++ ++ switch (skb->protocol) { ++ case htons(ETH_P_IP): ++ if (!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET))) ++ ip_proto = ip_hdr(skb)->protocol; ++ addr1 = ip_hdr(skb)->saddr; ++ addr2 = ip_hdr(skb)->daddr; ++ ihl = ip_hdr(skb)->ihl; ++ break; ++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++ case htons(ETH_P_IPV6): ++ ip_proto = ipv6_hdr(skb)->nexthdr; ++ addr1 = ipv6_hdr(skb)->saddr.s6_addr32[3]; ++ addr2 = ipv6_hdr(skb)->daddr.s6_addr32[3]; ++ ihl = (40 >> 2); ++ break; ++#endif ++ default: ++ return 0; ++ } ++ ++ ++ switch (ip_proto) { ++ case IPPROTO_TCP: ++ case IPPROTO_UDP: ++ case IPPROTO_DCCP: ++ case IPPROTO_ESP: ++ case IPPROTO_AH: ++ case IPPROTO_SCTP: ++ case IPPROTO_UDPLITE: ++ ports = *((u32 *) (skb_network_header(skb) + (ihl * 4))); ++ break; ++ ++ default: ++ ports = 0; ++ break; ++ } ++ ++ hash = jhash_3words(addr1, addr2, ports, _kc_simple_tx_hashrnd); ++ ++ return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); +} ++#endif /* HAVE_NETDEV_SELECT_QUEUE */ ++#endif /* < 2.6.30 */ +Index: linux-2.6.22/drivers/net/igb/kcompat.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/kcompat.h 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,1793 @@ ++/******************************************************************************* + -+static int ethtool_get_drvinfo(struct net_device *dev, void *useraddr) -+{ -+ struct ethtool_drvinfo info; -+ struct ethtool_ops *ops = ethtool_ops; ++ Intel(R) Gigabit Ethernet Linux driver ++ Copyright(c) 2007-2009 Intel Corporation. + -+ if (!ops->get_drvinfo) -+ return -EOPNOTSUPP; ++ 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. + -+ memset(&info, 0, sizeof(info)); -+ info.cmd = ETHTOOL_GDRVINFO; -+ ops->get_drvinfo(dev, &info); ++ 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. + -+ if (ops->self_test_count) -+ info.testinfo_len = ops->self_test_count(dev); -+ if (ops->get_stats_count) -+ info.n_stats = ops->get_stats_count(dev); -+ if (ops->get_regs_len) -+ info.regdump_len = ops->get_regs_len(dev); -+ if (ops->get_eeprom_len) -+ info.eedump_len = ops->get_eeprom_len(dev); ++ 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: ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ + -+ if (copy_to_user(useraddr, &info, sizeof(info))) -+ return -EFAULT; -+ return 0; -+} ++#ifndef _KCOMPAT_H_ ++#define _KCOMPAT_H_ + -+static int ethtool_get_regs(struct net_device *dev, char *useraddr) -+{ -+ struct ethtool_regs regs; -+ struct ethtool_ops *ops = ethtool_ops; -+ void *regbuf; -+ int reglen, ret; ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+ if (!ops->get_regs || !ops->get_regs_len) -+ return -EOPNOTSUPP; ++/* NAPI enable/disable flags here */ ++#define NAPI + -+ if (copy_from_user(®s, useraddr, sizeof(regs))) -+ return -EFAULT; ++#define adapter_struct igb_adapter ++#define adapter_q_vector igb_q_vector ++#define NAPI + -+ reglen = ops->get_regs_len(dev); -+ if (regs.len > reglen) -+ regs.len = reglen; ++/* and finally set defines so that the code sees the changes */ ++#ifdef NAPI ++#else ++#endif /* NAPI */ + -+ regbuf = kmalloc(reglen, GFP_USER); -+ if (!regbuf) -+ return -ENOMEM; ++/* packet split disable/enable */ ++#ifdef DISABLE_PACKET_SPLIT ++#undef CONFIG_E1000_DISABLE_PACKET_SPLIT ++#define CONFIG_E1000_DISABLE_PACKET_SPLIT ++#undef CONFIG_IGB_DISABLE_PACKET_SPLIT ++#define CONFIG_IGB_DISABLE_PACKET_SPLIT ++#endif + -+ ops->get_regs(dev, ®s, regbuf); ++/* MSI compatibility code for all kernels and drivers */ ++#ifdef DISABLE_PCI_MSI ++#undef CONFIG_PCI_MSI ++#endif ++#ifndef CONFIG_PCI_MSI ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) ) ++struct msix_entry { ++ u16 vector; /* kernel uses to write allocated vector */ ++ u16 entry; /* driver uses to specify entry, OS writes */ ++}; ++#endif ++#define pci_enable_msi(a) -ENOTSUPP ++#define pci_disable_msi(a) do {} while (0) ++#define pci_enable_msix(a, b, c) -ENOTSUPP ++#define pci_disable_msix(a) do {} while (0) ++#define msi_remove_pci_irq_vectors(a) do {} while (0) ++#endif /* CONFIG_PCI_MSI */ ++#ifdef DISABLE_PM ++#undef CONFIG_PM ++#endif + -+ ret = -EFAULT; -+ if (copy_to_user(useraddr, ®s, sizeof(regs))) -+ goto out; -+ useraddr += offsetof(struct ethtool_regs, data); -+ if (copy_to_user(useraddr, regbuf, reglen)) -+ goto out; -+ ret = 0; ++#ifdef DISABLE_NET_POLL_CONTROLLER ++#undef CONFIG_NET_POLL_CONTROLLER ++#endif + -+out: -+ kfree(regbuf); -+ return ret; -+} ++#ifndef PMSG_SUSPEND ++#define PMSG_SUSPEND 3 ++#endif + -+static int ethtool_get_wol(struct net_device *dev, char *useraddr) -+{ -+ struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; ++/* generic boolean compatibility */ ++#undef TRUE ++#undef FALSE ++#define TRUE true ++#define FALSE false ++#ifdef GCC_VERSION ++#if ( GCC_VERSION < 3000 ) ++#define _Bool char ++#endif ++#else ++#define _Bool char ++#endif ++#ifndef bool ++#define bool _Bool ++#define true 1 ++#define false 0 ++#endif + -+ if (!ethtool_ops->get_wol) -+ return -EOPNOTSUPP; + -+ ethtool_ops->get_wol(dev, &wol); ++#ifndef module_param ++#define module_param(v,t,p) MODULE_PARM(v, "i"); ++#endif + -+ if (copy_to_user(useraddr, &wol, sizeof(wol))) -+ return -EFAULT; -+ return 0; -+} ++#ifndef DMA_64BIT_MASK ++#define DMA_64BIT_MASK 0xffffffffffffffffULL ++#endif + -+static int ethtool_set_wol(struct net_device *dev, char *useraddr) -+{ -+ struct ethtool_wolinfo wol; ++#ifndef DMA_32BIT_MASK ++#define DMA_32BIT_MASK 0x00000000ffffffffULL ++#endif + -+ if (!ethtool_ops->set_wol) -+ return -EOPNOTSUPP; ++#ifndef PCI_CAP_ID_EXP ++#define PCI_CAP_ID_EXP 0x10 ++#endif + -+ if (copy_from_user(&wol, useraddr, sizeof(wol))) -+ return -EFAULT; ++#ifndef PCIE_LINK_STATE_L0S ++#define PCIE_LINK_STATE_L0S 1 ++#endif + -+ return ethtool_ops->set_wol(dev, &wol); -+} ++#ifndef mmiowb ++#ifdef CONFIG_IA64 ++#define mmiowb() asm volatile ("mf.a" ::: "memory") ++#else ++#define mmiowb() ++#endif ++#endif + -+static int ethtool_get_msglevel(struct net_device *dev, char *useraddr) -+{ -+ struct ethtool_value edata = { ETHTOOL_GMSGLVL }; ++#ifndef SET_NETDEV_DEV ++#define SET_NETDEV_DEV(net, pdev) ++#endif + -+ if (!ethtool_ops->get_msglevel) -+ return -EOPNOTSUPP; ++#ifndef HAVE_FREE_NETDEV ++#define free_netdev(x) kfree(x) ++#endif + -+ edata.data = ethtool_ops->get_msglevel(dev); ++#ifdef HAVE_POLL_CONTROLLER ++#define CONFIG_NET_POLL_CONTROLLER ++#endif + -+ if (copy_to_user(useraddr, &edata, sizeof(edata))) -+ return -EFAULT; -+ return 0; -+} ++#ifndef NETDEV_TX_OK ++#define NETDEV_TX_OK 0 ++#endif + -+static int ethtool_set_msglevel(struct net_device *dev, char *useraddr) -+{ -+ struct ethtool_value edata; ++#ifndef NETDEV_TX_BUSY ++#define NETDEV_TX_BUSY 1 ++#endif + -+ if (!ethtool_ops->set_msglevel) -+ return -EOPNOTSUPP; ++#ifndef NETDEV_TX_LOCKED ++#define NETDEV_TX_LOCKED -1 ++#endif + -+ if (copy_from_user(&edata, useraddr, sizeof(edata))) -+ return -EFAULT; ++#ifdef CONFIG_PCI_IOV ++#define VMDQ_P(p) ((p) + adapter->num_vfs) ++#else ++#define VMDQ_P(p) (p) ++#endif + -+ ethtool_ops->set_msglevel(dev, edata.data); -+ return 0; -+} ++#ifndef SKB_DATAREF_SHIFT ++/* if we do not have the infrastructure to detect if skb_header is cloned ++ just return false in all cases */ ++#define skb_header_cloned(x) 0 ++#endif + -+static int ethtool_nway_reset(struct net_device *dev) -+{ -+ if (!ethtool_ops->nway_reset) -+ return -EOPNOTSUPP; ++#ifndef NETIF_F_GSO ++#define gso_size tso_size ++#define gso_segs tso_segs ++#endif + -+ return ethtool_ops->nway_reset(dev); -+} ++#ifndef NETIF_F_GRO ++#define vlan_gro_receive(_napi, _vlgrp, _vlan, _skb) \ ++ vlan_hwaccel_receive_skb(_skb, _vlgrp, _vlan) ++#define napi_gro_receive(_napi, _skb) netif_receive_skb(_skb) ++#endif + -+static int ethtool_get_link(struct net_device *dev, void *useraddr) -+{ -+ struct ethtool_value edata = { ETHTOOL_GLINK }; ++#ifndef NETIF_F_SCTP_CSUM ++#define NETIF_F_SCTP_CSUM 0 ++#endif + -+ if (!ethtool_ops->get_link) -+ return -EOPNOTSUPP; ++#ifndef IPPROTO_SCTP ++#define IPPROTO_SCTP 132 ++#endif + -+ edata.data = ethtool_ops->get_link(dev); ++#ifndef CHECKSUM_PARTIAL ++#define CHECKSUM_PARTIAL CHECKSUM_HW ++#define CHECKSUM_COMPLETE CHECKSUM_HW ++#endif + -+ if (copy_to_user(useraddr, &edata, sizeof(edata))) -+ return -EFAULT; -+ return 0; -+} ++#ifndef __read_mostly ++#define __read_mostly ++#endif + -+static int ethtool_get_eeprom(struct net_device *dev, void *useraddr) -+{ -+ struct ethtool_eeprom eeprom; -+ struct ethtool_ops *ops = ethtool_ops; -+ u8 *data; -+ int ret; ++#ifndef HAVE_NETIF_MSG ++#define HAVE_NETIF_MSG 1 ++enum { ++ NETIF_MSG_DRV = 0x0001, ++ NETIF_MSG_PROBE = 0x0002, ++ NETIF_MSG_LINK = 0x0004, ++ NETIF_MSG_TIMER = 0x0008, ++ NETIF_MSG_IFDOWN = 0x0010, ++ NETIF_MSG_IFUP = 0x0020, ++ NETIF_MSG_RX_ERR = 0x0040, ++ NETIF_MSG_TX_ERR = 0x0080, ++ NETIF_MSG_TX_QUEUED = 0x0100, ++ NETIF_MSG_INTR = 0x0200, ++ NETIF_MSG_TX_DONE = 0x0400, ++ NETIF_MSG_RX_STATUS = 0x0800, ++ NETIF_MSG_PKTDATA = 0x1000, ++ NETIF_MSG_HW = 0x2000, ++ NETIF_MSG_WOL = 0x4000, ++}; ++ ++#else ++#define NETIF_MSG_HW 0x2000 ++#define NETIF_MSG_WOL 0x4000 ++#endif /* HAVE_NETIF_MSG */ + -+ if (!ops->get_eeprom || !ops->get_eeprom_len) -+ return -EOPNOTSUPP; ++#ifndef MII_RESV1 ++#define MII_RESV1 0x17 /* Reserved... */ ++#endif + -+ if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) -+ return -EFAULT; ++#ifndef unlikely ++#define unlikely(_x) _x ++#define likely(_x) _x ++#endif + -+ /* Check for wrap and zero */ -+ if (eeprom.offset + eeprom.len <= eeprom.offset) -+ return -EINVAL; ++#ifndef WARN_ON ++#define WARN_ON(x) ++#endif + -+ /* Check for exceeding total eeprom len */ -+ if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) -+ return -EINVAL; ++#ifndef PCI_DEVICE ++#define PCI_DEVICE(vend,dev) \ ++ .vendor = (vend), .device = (dev), \ ++ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID ++#endif + -+ data = kmalloc(eeprom.len, GFP_USER); -+ if (!data) -+ return -ENOMEM; ++#ifndef num_online_cpus ++#define num_online_cpus() smp_num_cpus ++#endif + -+ ret = -EFAULT; -+ if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) -+ goto out; + -+ ret = ops->get_eeprom(dev, &eeprom, data); -+ if (ret) -+ goto out; ++#ifndef _LINUX_RANDOM_H ++#include ++#endif + -+ ret = -EFAULT; -+ if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) -+ goto out; -+ if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) -+ goto out; -+ ret = 0; ++#ifndef DECLARE_BITMAP ++#ifndef BITS_TO_LONGS ++#define BITS_TO_LONGS(bits) (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) ++#endif ++#define DECLARE_BITMAP(name,bits) long name[BITS_TO_LONGS(bits)] ++#endif + -+out: -+ kfree(data); -+ return ret; -+} ++#ifndef VLAN_HLEN ++#define VLAN_HLEN 4 ++#endif + -+static int ethtool_set_eeprom(struct net_device *dev, void *useraddr) -+{ -+ struct ethtool_eeprom eeprom; -+ struct ethtool_ops *ops = ethtool_ops; -+ u8 *data; -+ int ret; ++#ifndef VLAN_ETH_HLEN ++#define VLAN_ETH_HLEN 18 ++#endif + -+ if (!ops->set_eeprom || !ops->get_eeprom_len) -+ return -EOPNOTSUPP; ++#ifndef VLAN_ETH_FRAME_LEN ++#define VLAN_ETH_FRAME_LEN 1518 ++#endif + -+ if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) -+ return -EFAULT; ++#ifndef DCA_GET_TAG_TWO_ARGS ++#define dca3_get_tag(a,b) dca_get_tag(b) ++#endif + -+ /* Check for wrap and zero */ -+ if (eeprom.offset + eeprom.len <= eeprom.offset) -+ return -EINVAL; ++/*****************************************************************************/ ++/* Installations with ethtool version without eeprom, adapter id, or statistics ++ * support */ + -+ /* Check for exceeding total eeprom len */ -+ if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) -+ return -EINVAL; ++#ifndef ETH_GSTRING_LEN ++#define ETH_GSTRING_LEN 32 ++#endif + -+ data = kmalloc(eeprom.len, GFP_USER); -+ if (!data) -+ return -ENOMEM; ++#ifndef ETHTOOL_GSTATS ++#define ETHTOOL_GSTATS 0x1d ++#undef ethtool_drvinfo ++#define ethtool_drvinfo k_ethtool_drvinfo ++struct k_ethtool_drvinfo { ++ u32 cmd; ++ char driver[32]; ++ char version[32]; ++ char fw_version[32]; ++ char bus_info[32]; ++ char reserved1[32]; ++ char reserved2[16]; ++ u32 n_stats; ++ u32 testinfo_len; ++ u32 eedump_len; ++ u32 regdump_len; ++}; + -+ ret = -EFAULT; -+ if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) -+ goto out; ++struct ethtool_stats { ++ u32 cmd; ++ u32 n_stats; ++ u64 data[0]; ++}; ++#endif /* ETHTOOL_GSTATS */ + -+ ret = ops->set_eeprom(dev, &eeprom, data); -+ if (ret) -+ goto out; ++#ifndef ETHTOOL_PHYS_ID ++#define ETHTOOL_PHYS_ID 0x1c ++#endif /* ETHTOOL_PHYS_ID */ + -+ if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) -+ ret = -EFAULT; ++#ifndef ETHTOOL_GSTRINGS ++#define ETHTOOL_GSTRINGS 0x1b ++enum ethtool_stringset { ++ ETH_SS_TEST = 0, ++ ETH_SS_STATS, ++}; ++struct ethtool_gstrings { ++ u32 cmd; /* ETHTOOL_GSTRINGS */ ++ u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ ++ u32 len; /* number of strings in the string set */ ++ u8 data[0]; ++}; ++#endif /* ETHTOOL_GSTRINGS */ + -+out: -+ kfree(data); -+ return ret; -+} ++#ifndef ETHTOOL_TEST ++#define ETHTOOL_TEST 0x1a ++enum ethtool_test_flags { ++ ETH_TEST_FL_OFFLINE = (1 << 0), ++ ETH_TEST_FL_FAILED = (1 << 1), ++}; ++struct ethtool_test { ++ u32 cmd; ++ u32 flags; ++ u32 reserved; ++ u32 len; ++ u64 data[0]; ++}; ++#endif /* ETHTOOL_TEST */ + -+static int ethtool_get_coalesce(struct net_device *dev, void *useraddr) -+{ -+ struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE }; ++#ifndef ETHTOOL_GEEPROM ++#define ETHTOOL_GEEPROM 0xb ++#undef ETHTOOL_GREGS ++struct ethtool_eeprom { ++ u32 cmd; ++ u32 magic; ++ u32 offset; ++ u32 len; ++ u8 data[0]; ++}; + -+ if (!ethtool_ops->get_coalesce) -+ return -EOPNOTSUPP; ++struct ethtool_value { ++ u32 cmd; ++ u32 data; ++}; ++#endif /* ETHTOOL_GEEPROM */ + -+ ethtool_ops->get_coalesce(dev, &coalesce); ++#ifndef ETHTOOL_GLINK ++#define ETHTOOL_GLINK 0xa ++#endif /* ETHTOOL_GLINK */ + -+ if (copy_to_user(useraddr, &coalesce, sizeof(coalesce))) -+ return -EFAULT; -+ return 0; -+} ++#ifndef ETHTOOL_GREGS ++#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers */ ++#define ethtool_regs _kc_ethtool_regs ++/* for passing big chunks of data */ ++struct _kc_ethtool_regs { ++ u32 cmd; ++ u32 version; /* driver-specific, indicates different chips/revs */ ++ u32 len; /* bytes */ ++ u8 data[0]; ++}; ++#endif /* ETHTOOL_GREGS */ + -+static int ethtool_set_coalesce(struct net_device *dev, void *useraddr) -+{ -+ struct ethtool_coalesce coalesce; ++#ifndef ETHTOOL_GMSGLVL ++#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ ++#endif ++#ifndef ETHTOOL_SMSGLVL ++#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level, priv. */ ++#endif ++#ifndef ETHTOOL_NWAY_RST ++#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation, priv */ ++#endif ++#ifndef ETHTOOL_GLINK ++#define ETHTOOL_GLINK 0x0000000a /* Get link status */ ++#endif ++#ifndef ETHTOOL_GEEPROM ++#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ ++#endif ++#ifndef ETHTOOL_SEEPROM ++#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data */ ++#endif ++#ifndef ETHTOOL_GCOALESCE ++#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ ++/* for configuring coalescing parameters of chip */ ++#define ethtool_coalesce _kc_ethtool_coalesce ++struct _kc_ethtool_coalesce { ++ u32 cmd; /* ETHTOOL_{G,S}COALESCE */ + -+ if (!ethtool_ops->get_coalesce) -+ return -EOPNOTSUPP; ++ /* How many usecs to delay an RX interrupt after ++ * a packet arrives. If 0, only rx_max_coalesced_frames ++ * is used. ++ */ ++ u32 rx_coalesce_usecs; + -+ if (copy_from_user(&coalesce, useraddr, sizeof(coalesce))) -+ return -EFAULT; ++ /* How many packets to delay an RX interrupt after ++ * a packet arrives. If 0, only rx_coalesce_usecs is ++ * used. It is illegal to set both usecs and max frames ++ * to zero as this would cause RX interrupts to never be ++ * generated. ++ */ ++ u32 rx_max_coalesced_frames; + -+ return ethtool_ops->set_coalesce(dev, &coalesce); -+} ++ /* Same as above two parameters, except that these values ++ * apply while an IRQ is being serviced by the host. Not ++ * all cards support this feature and the values are ignored ++ * in that case. ++ */ ++ u32 rx_coalesce_usecs_irq; ++ u32 rx_max_coalesced_frames_irq; ++ ++ /* How many usecs to delay a TX interrupt after ++ * a packet is sent. If 0, only tx_max_coalesced_frames ++ * is used. ++ */ ++ u32 tx_coalesce_usecs; + -+static int ethtool_get_ringparam(struct net_device *dev, void *useraddr) -+{ -+ struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM }; ++ /* How many packets to delay a TX interrupt after ++ * a packet is sent. If 0, only tx_coalesce_usecs is ++ * used. It is illegal to set both usecs and max frames ++ * to zero as this would cause TX interrupts to never be ++ * generated. ++ */ ++ u32 tx_max_coalesced_frames; + -+ if (!ethtool_ops->get_ringparam) -+ return -EOPNOTSUPP; ++ /* Same as above two parameters, except that these values ++ * apply while an IRQ is being serviced by the host. Not ++ * all cards support this feature and the values are ignored ++ * in that case. ++ */ ++ u32 tx_coalesce_usecs_irq; ++ u32 tx_max_coalesced_frames_irq; + -+ ethtool_ops->get_ringparam(dev, &ringparam); ++ /* How many usecs to delay in-memory statistics ++ * block updates. Some drivers do not have an in-memory ++ * statistic block, and in such cases this value is ignored. ++ * This value must not be zero. ++ */ ++ u32 stats_block_coalesce_usecs; + -+ if (copy_to_user(useraddr, &ringparam, sizeof(ringparam))) -+ return -EFAULT; -+ return 0; -+} ++ /* Adaptive RX/TX coalescing is an algorithm implemented by ++ * some drivers to improve latency under low packet rates and ++ * improve throughput under high packet rates. Some drivers ++ * only implement one of RX or TX adaptive coalescing. Anything ++ * not implemented by the driver causes these values to be ++ * silently ignored. ++ */ ++ u32 use_adaptive_rx_coalesce; ++ u32 use_adaptive_tx_coalesce; + -+static int ethtool_set_ringparam(struct net_device *dev, void *useraddr) -+{ -+ struct ethtool_ringparam ringparam; ++ /* When the packet rate (measured in packets per second) ++ * is below pkt_rate_low, the {rx,tx}_*_low parameters are ++ * used. ++ */ ++ u32 pkt_rate_low; ++ u32 rx_coalesce_usecs_low; ++ u32 rx_max_coalesced_frames_low; ++ u32 tx_coalesce_usecs_low; ++ u32 tx_max_coalesced_frames_low; + -+ if (!ethtool_ops->get_ringparam) -+ return -EOPNOTSUPP; ++ /* When the packet rate is below pkt_rate_high but above ++ * pkt_rate_low (both measured in packets per second) the ++ * normal {rx,tx}_* coalescing parameters are used. ++ */ + -+ if (copy_from_user(&ringparam, useraddr, sizeof(ringparam))) -+ return -EFAULT; ++ /* When the packet rate is (measured in packets per second) ++ * is above pkt_rate_high, the {rx,tx}_*_high parameters are ++ * used. ++ */ ++ u32 pkt_rate_high; ++ u32 rx_coalesce_usecs_high; ++ u32 rx_max_coalesced_frames_high; ++ u32 tx_coalesce_usecs_high; ++ u32 tx_max_coalesced_frames_high; + -+ return ethtool_ops->set_ringparam(dev, &ringparam); -+} ++ /* How often to do adaptive coalescing packet rate sampling, ++ * measured in seconds. Must not be zero. ++ */ ++ u32 rate_sample_interval; ++}; ++#endif /* ETHTOOL_GCOALESCE */ + -+static int ethtool_get_pauseparam(struct net_device *dev, void *useraddr) -+{ -+ struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; ++#ifndef ETHTOOL_SCOALESCE ++#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ ++#endif ++#ifndef ETHTOOL_GRINGPARAM ++#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ ++/* for configuring RX/TX ring parameters */ ++#define ethtool_ringparam _kc_ethtool_ringparam ++struct _kc_ethtool_ringparam { ++ u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ + -+ if (!ethtool_ops->get_pauseparam) -+ return -EOPNOTSUPP; ++ /* Read only attributes. These indicate the maximum number ++ * of pending RX/TX ring entries the driver will allow the ++ * user to set. ++ */ ++ u32 rx_max_pending; ++ u32 rx_mini_max_pending; ++ u32 rx_jumbo_max_pending; ++ u32 tx_max_pending; + -+ ethtool_ops->get_pauseparam(dev, &pauseparam); ++ /* Values changeable by the user. The valid values are ++ * in the range 1 to the "*_max_pending" counterpart above. ++ */ ++ u32 rx_pending; ++ u32 rx_mini_pending; ++ u32 rx_jumbo_pending; ++ u32 tx_pending; ++}; ++#endif /* ETHTOOL_GRINGPARAM */ + -+ if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam))) -+ return -EFAULT; -+ return 0; -+} ++#ifndef ETHTOOL_SRINGPARAM ++#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters, priv. */ ++#endif ++#ifndef ETHTOOL_GPAUSEPARAM ++#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ ++/* for configuring link flow control parameters */ ++#define ethtool_pauseparam _kc_ethtool_pauseparam ++struct _kc_ethtool_pauseparam { ++ u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ + -+static int ethtool_set_pauseparam(struct net_device *dev, void *useraddr) -+{ -+ struct ethtool_pauseparam pauseparam; ++ /* If the link is being auto-negotiated (via ethtool_cmd.autoneg ++ * being true) the user may set 'autoneg' here non-zero to have the ++ * pause parameters be auto-negotiated too. In such a case, the ++ * {rx,tx}_pause values below determine what capabilities are ++ * advertised. ++ * ++ * If 'autoneg' is zero or the link is not being auto-negotiated, ++ * then {rx,tx}_pause force the driver to use/not-use pause ++ * flow control. ++ */ ++ u32 autoneg; ++ u32 rx_pause; ++ u32 tx_pause; ++}; ++#endif /* ETHTOOL_GPAUSEPARAM */ + -+ if (!ethtool_ops->get_pauseparam) -+ return -EOPNOTSUPP; ++#ifndef ETHTOOL_SPAUSEPARAM ++#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ ++#endif ++#ifndef ETHTOOL_GRXCSUM ++#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ ++#endif ++#ifndef ETHTOOL_SRXCSUM ++#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ ++#endif ++#ifndef ETHTOOL_GTXCSUM ++#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ ++#endif ++#ifndef ETHTOOL_STXCSUM ++#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ ++#endif ++#ifndef ETHTOOL_GSG ++#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable ++ * (ethtool_value) */ ++#endif ++#ifndef ETHTOOL_SSG ++#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable ++ * (ethtool_value). */ ++#endif ++#ifndef ETHTOOL_TEST ++#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */ ++#endif ++#ifndef ETHTOOL_GSTRINGS ++#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ ++#endif ++#ifndef ETHTOOL_PHYS_ID ++#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ ++#endif ++#ifndef ETHTOOL_GSTATS ++#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ ++#endif ++#ifndef ETHTOOL_GTSO ++#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ ++#endif ++#ifndef ETHTOOL_STSO ++#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ ++#endif + -+ if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam))) -+ return -EFAULT; ++#ifndef ETHTOOL_BUSINFO_LEN ++#define ETHTOOL_BUSINFO_LEN 32 ++#endif + -+ return ethtool_ops->set_pauseparam(dev, &pauseparam); -+} ++/*****************************************************************************/ ++/* 2.4.3 => 2.4.0 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) ) + -+static int ethtool_get_rx_csum(struct net_device *dev, char *useraddr) -+{ -+ struct ethtool_value edata = { ETHTOOL_GRXCSUM }; ++/**************************************/ ++/* PCI DRIVER API */ + -+ if (!ethtool_ops->get_rx_csum) -+ return -EOPNOTSUPP; ++#ifndef pci_set_dma_mask ++#define pci_set_dma_mask _kc_pci_set_dma_mask ++extern int _kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask); ++#endif + -+ edata.data = ethtool_ops->get_rx_csum(dev); ++#ifndef pci_request_regions ++#define pci_request_regions _kc_pci_request_regions ++extern int _kc_pci_request_regions(struct pci_dev *pdev, char *res_name); ++#endif + -+ if (copy_to_user(useraddr, &edata, sizeof(edata))) -+ return -EFAULT; -+ return 0; -+} ++#ifndef pci_release_regions ++#define pci_release_regions _kc_pci_release_regions ++extern void _kc_pci_release_regions(struct pci_dev *pdev); ++#endif + -+static int ethtool_set_rx_csum(struct net_device *dev, char *useraddr) -+{ -+ struct ethtool_value edata; ++/**************************************/ ++/* NETWORK DRIVER API */ + -+ if (!ethtool_ops->set_rx_csum) -+ return -EOPNOTSUPP; ++#ifndef alloc_etherdev ++#define alloc_etherdev _kc_alloc_etherdev ++extern struct net_device * _kc_alloc_etherdev(int sizeof_priv); ++#endif + -+ if (copy_from_user(&edata, useraddr, sizeof(edata))) -+ return -EFAULT; ++#ifndef is_valid_ether_addr ++#define is_valid_ether_addr _kc_is_valid_ether_addr ++extern int _kc_is_valid_ether_addr(u8 *addr); ++#endif + -+ ethtool_ops->set_rx_csum(dev, edata.data); -+ return 0; -+} ++/**************************************/ ++/* MISCELLANEOUS */ + -+static int ethtool_get_tx_csum(struct net_device *dev, char *useraddr) -+{ -+ struct ethtool_value edata = { ETHTOOL_GTXCSUM }; ++#ifndef INIT_TQUEUE ++#define INIT_TQUEUE(_tq, _routine, _data) \ ++ do { \ ++ INIT_LIST_HEAD(&(_tq)->list); \ ++ (_tq)->sync = 0; \ ++ (_tq)->routine = _routine; \ ++ (_tq)->data = _data; \ ++ } while (0) ++#endif + -+ if (!ethtool_ops->get_tx_csum) -+ return -EOPNOTSUPP; ++#endif /* 2.4.3 => 2.4.0 */ ++ ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,5) ) ++/* Generic MII registers. */ ++#define MII_BMCR 0x00 /* Basic mode control register */ ++#define MII_BMSR 0x01 /* Basic mode status register */ ++#define MII_PHYSID1 0x02 /* PHYS ID 1 */ ++#define MII_PHYSID2 0x03 /* PHYS ID 2 */ ++#define MII_ADVERTISE 0x04 /* Advertisement control reg */ ++#define MII_LPA 0x05 /* Link partner ability reg */ ++#define MII_EXPANSION 0x06 /* Expansion register */ ++/* Basic mode control register. */ ++#define BMCR_FULLDPLX 0x0100 /* Full duplex */ ++#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */ ++/* Basic mode status register. */ ++#define BMSR_ERCAP 0x0001 /* Ext-reg capability */ ++#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */ ++#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */ ++#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */ ++#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */ ++#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */ ++/* Advertisement control register. */ ++#define ADVERTISE_CSMA 0x0001 /* Only selector supported */ ++#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ ++#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ ++#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ ++#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ ++#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \ ++ ADVERTISE_100HALF | ADVERTISE_100FULL) ++/* Expansion register for auto-negotiation. */ ++#define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */ ++#endif + -+ edata.data = ethtool_ops->get_tx_csum(dev); ++/*****************************************************************************/ ++/* 2.4.6 => 2.4.3 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) ) + -+ if (copy_to_user(useraddr, &edata, sizeof(edata))) -+ return -EFAULT; -+ return 0; -+} ++#ifndef pci_set_power_state ++#define pci_set_power_state _kc_pci_set_power_state ++extern int _kc_pci_set_power_state(struct pci_dev *dev, int state); ++#endif + -+static int ethtool_set_tx_csum(struct net_device *dev, char *useraddr) -+{ -+ struct ethtool_value edata; ++#ifndef pci_enable_wake ++#define pci_enable_wake _kc_pci_enable_wake ++extern int _kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable); ++#endif + -+ if (!ethtool_ops->set_tx_csum) -+ return -EOPNOTSUPP; ++#ifndef pci_disable_device ++#define pci_disable_device _kc_pci_disable_device ++extern void _kc_pci_disable_device(struct pci_dev *pdev); ++#endif + -+ if (copy_from_user(&edata, useraddr, sizeof(edata))) -+ return -EFAULT; ++/* PCI PM entry point syntax changed, so don't support suspend/resume */ ++#undef CONFIG_PM + -+ return ethtool_ops->set_tx_csum(dev, edata.data); -+} ++#endif /* 2.4.6 => 2.4.3 */ + -+static int ethtool_get_sg(struct net_device *dev, char *useraddr) -+{ -+ struct ethtool_value edata = { ETHTOOL_GSG }; ++#ifndef HAVE_PCI_SET_MWI ++#define pci_set_mwi(X) pci_write_config_word(X, \ ++ PCI_COMMAND, adapter->hw.bus.pci_cmd_word | \ ++ PCI_COMMAND_INVALIDATE); ++#define pci_clear_mwi(X) pci_write_config_word(X, \ ++ PCI_COMMAND, adapter->hw.bus.pci_cmd_word & \ ++ ~PCI_COMMAND_INVALIDATE); ++#endif + -+ if (!ethtool_ops->get_sg) -+ return -EOPNOTSUPP; ++/*****************************************************************************/ ++/* 2.4.10 => 2.4.9 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) ) + -+ edata.data = ethtool_ops->get_sg(dev); ++/**************************************/ ++/* MODULE API */ + -+ if (copy_to_user(useraddr, &edata, sizeof(edata))) -+ return -EFAULT; -+ return 0; -+} ++#ifndef MODULE_LICENSE ++ #define MODULE_LICENSE(X) ++#endif + -+static int ethtool_set_sg(struct net_device *dev, char *useraddr) -+{ -+ struct ethtool_value edata; ++/**************************************/ ++/* OTHER */ + -+ if (!ethtool_ops->set_sg) -+ return -EOPNOTSUPP; ++#undef min ++#define min(x,y) ({ \ ++ const typeof(x) _x = (x); \ ++ const typeof(y) _y = (y); \ ++ (void) (&_x == &_y); \ ++ _x < _y ? _x : _y; }) + -+ if (copy_from_user(&edata, useraddr, sizeof(edata))) -+ return -EFAULT; ++#undef max ++#define max(x,y) ({ \ ++ const typeof(x) _x = (x); \ ++ const typeof(y) _y = (y); \ ++ (void) (&_x == &_y); \ ++ _x > _y ? _x : _y; }) + -+ return ethtool_ops->set_sg(dev, edata.data); -+} ++#define min_t(type,x,y) ({ \ ++ type _x = (x); \ ++ type _y = (y); \ ++ _x < _y ? _x : _y; }) + -+static int ethtool_get_tso(struct net_device *dev, char *useraddr) -+{ -+ struct ethtool_value edata = { ETHTOOL_GTSO }; ++#define max_t(type,x,y) ({ \ ++ type _x = (x); \ ++ type _y = (y); \ ++ _x > _y ? _x : _y; }) + -+ if (!ethtool_ops->get_tso) -+ return -EOPNOTSUPP; ++#ifndef list_for_each_safe ++#define list_for_each_safe(pos, n, head) \ ++ for (pos = (head)->next, n = pos->next; pos != (head); \ ++ pos = n, n = pos->next) ++#endif + -+ edata.data = ethtool_ops->get_tso(dev); ++#endif /* 2.4.10 -> 2.4.6 */ + -+ if (copy_to_user(useraddr, &edata, sizeof(edata))) -+ return -EFAULT; -+ return 0; -+} + -+static int ethtool_set_tso(struct net_device *dev, char *useraddr) -+{ -+ struct ethtool_value edata; ++/*****************************************************************************/ ++/* 2.4.13 => 2.4.10 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) ) + -+ if (!ethtool_ops->set_tso) -+ return -EOPNOTSUPP; ++/**************************************/ ++/* PCI DMA MAPPING */ + -+ if (copy_from_user(&edata, useraddr, sizeof(edata))) -+ return -EFAULT; ++#ifndef virt_to_page ++ #define virt_to_page(v) (mem_map + (virt_to_phys(v) >> PAGE_SHIFT)) ++#endif + -+ return ethtool_ops->set_tso(dev, edata.data); -+} ++#ifndef pci_map_page ++#define pci_map_page _kc_pci_map_page ++extern u64 _kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, size_t size, int direction); ++#endif + -+static int ethtool_self_test(struct net_device *dev, char *useraddr) -+{ -+ struct ethtool_test test; -+ struct ethtool_ops *ops = ethtool_ops; -+ u64 *data; -+ int ret; ++#ifndef pci_unmap_page ++#define pci_unmap_page _kc_pci_unmap_page ++extern void _kc_pci_unmap_page(struct pci_dev *dev, u64 dma_addr, size_t size, int direction); ++#endif + -+ if (!ops->self_test || !ops->self_test_count) -+ return -EOPNOTSUPP; ++/* pci_set_dma_mask takes dma_addr_t, which is only 32-bits prior to 2.4.13 */ + -+ if (copy_from_user(&test, useraddr, sizeof(test))) -+ return -EFAULT; ++#undef DMA_32BIT_MASK ++#define DMA_32BIT_MASK 0xffffffff ++#undef DMA_64BIT_MASK ++#define DMA_64BIT_MASK 0xffffffff + -+ test.len = ops->self_test_count(dev); -+ data = kmalloc(test.len * sizeof(u64), GFP_USER); -+ if (!data) -+ return -ENOMEM; ++/**************************************/ ++/* OTHER */ + -+ ops->self_test(dev, &test, data); ++#ifndef cpu_relax ++#define cpu_relax() rep_nop() ++#endif + -+ ret = -EFAULT; -+ if (copy_to_user(useraddr, &test, sizeof(test))) -+ goto out; -+ useraddr += sizeof(test); -+ if (copy_to_user(useraddr, data, test.len * sizeof(u64))) -+ goto out; -+ ret = 0; ++struct vlan_ethhdr { ++ unsigned char h_dest[ETH_ALEN]; ++ unsigned char h_source[ETH_ALEN]; ++ unsigned short h_vlan_proto; ++ unsigned short h_vlan_TCI; ++ unsigned short h_vlan_encapsulated_proto; ++}; ++#endif /* 2.4.13 => 2.4.10 */ + -+out: -+ kfree(data); -+ return ret; -+} ++/*****************************************************************************/ ++/* 2.4.17 => 2.4.12 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,17) ) + -+static int ethtool_get_strings(struct net_device *dev, void *useraddr) -+{ -+ struct ethtool_gstrings gstrings; -+ struct ethtool_ops *ops = ethtool_ops; -+ u8 *data; -+ int ret; ++#ifndef __devexit_p ++ #define __devexit_p(x) &(x) ++#endif + -+ if (!ops->get_strings) -+ return -EOPNOTSUPP; ++#endif /* 2.4.17 => 2.4.13 */ + -+ if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) -+ return -EFAULT; ++/*****************************************************************************/ ++/* 2.4.20 => 2.4.19 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20) ) + -+ switch (gstrings.string_set) { -+ case ETH_SS_TEST: -+ if (!ops->self_test_count) -+ return -EOPNOTSUPP; -+ gstrings.len = ops->self_test_count(dev); -+ break; -+ case ETH_SS_STATS: -+ if (!ops->get_stats_count) -+ return -EOPNOTSUPP; -+ gstrings.len = ops->get_stats_count(dev); -+ break; -+ default: -+ return -EINVAL; -+ } ++/* we won't support NAPI on less than 2.4.20 */ ++#ifdef NAPI ++#undef NAPI ++#endif + -+ data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); -+ if (!data) -+ return -ENOMEM; ++#endif /* 2.4.20 => 2.4.19 */ + -+ ops->get_strings(dev, gstrings.string_set, data); ++/*****************************************************************************/ ++/* < 2.4.21 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,21) ) ++#define skb_pad(x,y) _kc_skb_pad(x, y) ++struct sk_buff * _kc_skb_pad(struct sk_buff *skb, int pad); ++#endif /* < 2.4.21 */ + -+ ret = -EFAULT; -+ if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) -+ goto out; -+ useraddr += sizeof(gstrings); -+ if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) -+ goto out; -+ ret = 0; ++/*****************************************************************************/ ++/* 2.4.22 => 2.4.17 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) ++#define pci_name(x) ((x)->slot_name) ++#endif + -+out: -+ kfree(data); -+ return ret; ++/*****************************************************************************/ ++/*****************************************************************************/ ++/* 2.4.23 => 2.4.22 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) ) ++/*****************************************************************************/ ++#ifdef NAPI ++#ifndef netif_poll_disable ++#define netif_poll_disable(x) _kc_netif_poll_disable(x) ++static inline void _kc_netif_poll_disable(struct net_device *netdev) ++{ ++ while (test_and_set_bit(__LINK_STATE_RX_SCHED, &netdev->state)) { ++ /* No hurry */ ++ current->state = TASK_INTERRUPTIBLE; ++ schedule_timeout(1); ++ } +} -+ -+static int ethtool_phys_id(struct net_device *dev, void *useraddr) ++#endif ++#ifndef netif_poll_enable ++#define netif_poll_enable(x) _kc_netif_poll_enable(x) ++static inline void _kc_netif_poll_enable(struct net_device *netdev) +{ -+ struct ethtool_value id; ++ clear_bit(__LINK_STATE_RX_SCHED, &netdev->state); ++} ++#endif ++#endif /* NAPI */ ++#ifndef netif_tx_disable ++#define netif_tx_disable(x) _kc_netif_tx_disable(x) ++static inline void _kc_netif_tx_disable(struct net_device *dev) ++{ ++ spin_lock_bh(&dev->xmit_lock); ++ netif_stop_queue(dev); ++ spin_unlock_bh(&dev->xmit_lock); ++} ++#endif ++#endif /* 2.4.23 => 2.4.22 */ + -+ if (!ethtool_ops->phys_id) -+ return -EOPNOTSUPP; ++/*****************************************************************************/ ++/* 2.6.4 => 2.6.0 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25) || \ ++ ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ ++ LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) ) ++#define ETHTOOL_OPS_COMPAT ++#endif /* 2.6.4 => 2.6.0 */ + -+ if (copy_from_user(&id, useraddr, sizeof(id))) -+ return -EFAULT; ++/*****************************************************************************/ ++/* 2.5.71 => 2.4.x */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,71) ) ++#define sk_protocol protocol ++#define pci_get_device pci_find_device ++#endif /* 2.5.70 => 2.4.x */ + -+ return ethtool_ops->phys_id(dev, id.data); -+} ++/*****************************************************************************/ ++/* < 2.4.27 or 2.6.0 <= 2.6.5 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) || \ ++ ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ ++ LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) ) + -+static int ethtool_get_stats(struct net_device *dev, void *useraddr) ++#ifndef netif_msg_init ++#define netif_msg_init _kc_netif_msg_init ++static inline u32 _kc_netif_msg_init(int debug_value, int default_msg_enable_bits) +{ -+ struct ethtool_stats stats; -+ struct ethtool_ops *ops = ethtool_ops; -+ u64 *data; -+ int ret; ++ /* use default */ ++ if (debug_value < 0 || debug_value >= (sizeof(u32) * 8)) ++ return default_msg_enable_bits; ++ if (debug_value == 0) /* no output */ ++ return 0; ++ /* set low N bits */ ++ return (1 << debug_value) -1; ++} ++#endif + -+ if (!ops->get_ethtool_stats || !ops->get_stats_count) -+ return -EOPNOTSUPP; ++#endif /* < 2.4.27 or 2.6.0 <= 2.6.5 */ ++/*****************************************************************************/ ++#if (( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) ) || \ ++ (( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) && \ ++ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ))) ++#define netdev_priv(x) x->priv ++#endif + -+ if (copy_from_user(&stats, useraddr, sizeof(stats))) -+ return -EFAULT; ++/*****************************************************************************/ ++/* <= 2.5.0 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) ) ++#undef pci_register_driver ++#define pci_register_driver pci_module_init + -+ stats.n_stats = ops->get_stats_count(dev); -+ data = kmalloc(stats.n_stats * sizeof(u64), GFP_USER); -+ if (!data) -+ return -ENOMEM; ++#define dev_err(__unused_dev, format, arg...) \ ++ printk(KERN_ERR "%s: " format, pci_name(pdev) , ## arg) ++#define dev_warn(__unused_dev, format, arg...) \ ++ printk(KERN_WARNING "%s: " format, pci_name(pdev) , ## arg) + -+ ops->get_ethtool_stats(dev, &stats, data); ++/* hlist_* code - double linked lists */ ++struct hlist_head { ++ struct hlist_node *first; ++}; + -+ ret = -EFAULT; -+ if (copy_to_user(useraddr, &stats, sizeof(stats))) -+ goto out; -+ useraddr += sizeof(stats); -+ if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64))) -+ goto out; -+ ret = 0; ++struct hlist_node { ++ struct hlist_node *next, **pprev; ++}; + -+out: -+ kfree(data); -+ return ret; ++static inline void __hlist_del(struct hlist_node *n) ++{ ++ struct hlist_node *next = n->next; ++ struct hlist_node **pprev = n->pprev; ++ *pprev = next; ++ if (next) ++ next->pprev = pprev; +} + -+/* The main entry point in this file. Called from net/core/dev.c */ -+ -+#define ETHTOOL_OPS_COMPAT -+int ethtool_ioctl(struct ifreq *ifr) ++static inline void hlist_del(struct hlist_node *n) +{ -+ struct net_device *dev = __dev_get_by_name(ifr->ifr_name); -+ void *useraddr = (void *) ifr->ifr_data; -+ u32 ethcmd; -+ -+ /* -+ * XXX: This can be pushed down into the ethtool_* handlers that -+ * need it. Keep existing behavior for the moment. -+ */ -+ if (!capable(CAP_NET_ADMIN)) -+ return -EPERM; -+ -+ if (!dev || !netif_device_present(dev)) -+ return -ENODEV; -+ -+ if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) -+ return -EFAULT; ++ __hlist_del(n); ++ n->next = NULL; ++ n->pprev = NULL; ++} + -+ switch (ethcmd) { -+ case ETHTOOL_GSET: -+ return ethtool_get_settings(dev, useraddr); -+ case ETHTOOL_SSET: -+ return ethtool_set_settings(dev, useraddr); -+ case ETHTOOL_GDRVINFO: -+ return ethtool_get_drvinfo(dev, useraddr); -+ case ETHTOOL_GREGS: -+ return ethtool_get_regs(dev, useraddr); -+ case ETHTOOL_GWOL: -+ return ethtool_get_wol(dev, useraddr); -+ case ETHTOOL_SWOL: -+ return ethtool_set_wol(dev, useraddr); -+ case ETHTOOL_GMSGLVL: -+ return ethtool_get_msglevel(dev, useraddr); -+ case ETHTOOL_SMSGLVL: -+ return ethtool_set_msglevel(dev, useraddr); -+ case ETHTOOL_NWAY_RST: -+ return ethtool_nway_reset(dev); -+ case ETHTOOL_GLINK: -+ return ethtool_get_link(dev, useraddr); -+ case ETHTOOL_GEEPROM: -+ return ethtool_get_eeprom(dev, useraddr); -+ case ETHTOOL_SEEPROM: -+ return ethtool_set_eeprom(dev, useraddr); -+ case ETHTOOL_GCOALESCE: -+ return ethtool_get_coalesce(dev, useraddr); -+ case ETHTOOL_SCOALESCE: -+ return ethtool_set_coalesce(dev, useraddr); -+ case ETHTOOL_GRINGPARAM: -+ return ethtool_get_ringparam(dev, useraddr); -+ case ETHTOOL_SRINGPARAM: -+ return ethtool_set_ringparam(dev, useraddr); -+ case ETHTOOL_GPAUSEPARAM: -+ return ethtool_get_pauseparam(dev, useraddr); -+ case ETHTOOL_SPAUSEPARAM: -+ return ethtool_set_pauseparam(dev, useraddr); -+ case ETHTOOL_GRXCSUM: -+ return ethtool_get_rx_csum(dev, useraddr); -+ case ETHTOOL_SRXCSUM: -+ return ethtool_set_rx_csum(dev, useraddr); -+ case ETHTOOL_GTXCSUM: -+ return ethtool_get_tx_csum(dev, useraddr); -+ case ETHTOOL_STXCSUM: -+ return ethtool_set_tx_csum(dev, useraddr); -+ case ETHTOOL_GSG: -+ return ethtool_get_sg(dev, useraddr); -+ case ETHTOOL_SSG: -+ return ethtool_set_sg(dev, useraddr); -+ case ETHTOOL_GTSO: -+ return ethtool_get_tso(dev, useraddr); -+ case ETHTOOL_STSO: -+ return ethtool_set_tso(dev, useraddr); -+ case ETHTOOL_TEST: -+ return ethtool_self_test(dev, useraddr); -+ case ETHTOOL_GSTRINGS: -+ return ethtool_get_strings(dev, useraddr); -+ case ETHTOOL_PHYS_ID: -+ return ethtool_phys_id(dev, useraddr); -+ case ETHTOOL_GSTATS: -+ return ethtool_get_stats(dev, useraddr); -+ default: -+ return -EOPNOTSUPP; -+ } ++static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) ++{ ++ struct hlist_node *first = h->first; ++ n->next = first; ++ if (first) ++ first->pprev = &n->next; ++ h->first = n; ++ n->pprev = &h->first; ++} + -+ return -EOPNOTSUPP; ++static inline int hlist_empty(const struct hlist_head *h) ++{ ++ return !h->first; ++} ++#define HLIST_HEAD_INIT { .first = NULL } ++#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } ++#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) ++static inline void INIT_HLIST_NODE(struct hlist_node *h) ++{ ++ h->next = NULL; ++ h->pprev = NULL; +} ++#define hlist_entry(ptr, type, member) container_of(ptr,type,member) + -+#define mii_if_info _kc_mii_if_info -+struct _kc_mii_if_info { -+ int phy_id; -+ int advertising; -+ int phy_id_mask; -+ int reg_num_mask; ++#define hlist_for_each_entry(tpos, pos, head, member) \ ++ for (pos = (head)->first; \ ++ pos && ({ prefetch(pos->next); 1;}) && \ ++ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ ++ pos = pos->next) + -+ unsigned int full_duplex : 1; /* is full duplex? */ -+ unsigned int force_media : 1; /* is autoneg. disabled? */ ++#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ ++ for (pos = (head)->first; \ ++ pos && ({ n = pos->next; 1; }) && \ ++ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ ++ pos = n) + -+ struct net_device *dev; -+ int (*mdio_read) (struct net_device *dev, int phy_id, int location); -+ void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val); -+}; ++/* we ignore GFP here */ ++#define dma_alloc_coherent(dv, sz, dma, gfp) \ ++ pci_alloc_consistent(pdev, (sz), (dma)) ++#define dma_free_coherent(dv, sz, addr, dma_addr) \ ++ pci_free_consistent(pdev, (sz), (addr), (dma_addr)) + -+struct ethtool_cmd; -+struct mii_ioctl_data; ++#ifndef might_sleep ++#define might_sleep() ++#endif + -+#undef mii_link_ok -+#define mii_link_ok _kc_mii_link_ok -+#undef mii_nway_restart -+#define mii_nway_restart _kc_mii_nway_restart -+#undef mii_ethtool_gset -+#define mii_ethtool_gset _kc_mii_ethtool_gset -+#undef mii_ethtool_sset -+#define mii_ethtool_sset _kc_mii_ethtool_sset -+#undef mii_check_link -+#define mii_check_link _kc_mii_check_link -+#undef generic_mii_ioctl -+#define generic_mii_ioctl _kc_generic_mii_ioctl -+extern int _kc_mii_link_ok (struct mii_if_info *mii); -+extern int _kc_mii_nway_restart (struct mii_if_info *mii); -+extern int _kc_mii_ethtool_gset(struct mii_if_info *mii, -+ struct ethtool_cmd *ecmd); -+extern int _kc_mii_ethtool_sset(struct mii_if_info *mii, -+ struct ethtool_cmd *ecmd); -+extern void _kc_mii_check_link (struct mii_if_info *mii); -+extern int _kc_generic_mii_ioctl(struct mii_if_info *mii_if, -+ struct mii_ioctl_data *mii_data, int cmd, -+ unsigned int *duplex_changed); ++#endif /* <= 2.5.0 */ + ++/*****************************************************************************/ ++/* 2.5.28 => 2.4.23 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) + -+struct _kc_pci_dev_ext { -+ struct pci_dev *dev; -+ void *pci_drvdata; -+ struct pci_driver *driver; -+}; ++static inline void _kc_synchronize_irq(void) ++{ ++ synchronize_irq(); ++} ++#undef synchronize_irq ++#define synchronize_irq(X) _kc_synchronize_irq() + -+struct _kc_net_dev_ext { -+ struct net_device *dev; -+ unsigned int carrier; -+}; ++#include ++#define work_struct tq_struct ++#undef INIT_WORK ++#define INIT_WORK(a,b) INIT_TQUEUE(a,(void (*)(void *))b,a) ++#undef container_of ++#define container_of list_entry ++#define schedule_work schedule_task ++#define flush_scheduled_work flush_scheduled_tasks ++#define cancel_work_sync(x) flush_scheduled_work() + ++#endif /* 2.5.28 => 2.4.17 */ + -+/**************************************/ -+/* mii support */ ++/*****************************************************************************/ ++/* 2.6.0 => 2.5.28 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) ++#define MODULE_INFO(version, _version) ++#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT ++#define CONFIG_E1000_DISABLE_PACKET_SPLIT 1 ++#endif ++#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT ++#define CONFIG_IGB_DISABLE_PACKET_SPLIT 1 ++#endif + -+int _kc_mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) -+{ -+ struct net_device *dev = mii->dev; -+ u32 advert, bmcr, lpa, nego; ++#define pci_set_consistent_dma_mask(dev,mask) 1 + -+ ecmd->supported = -+ (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | -+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | -+ SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII); ++#undef dev_put ++#define dev_put(dev) __dev_put(dev) + -+ /* only supports twisted-pair */ -+ ecmd->port = PORT_MII; ++#ifndef skb_fill_page_desc ++#define skb_fill_page_desc _kc_skb_fill_page_desc ++extern void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size); ++#endif + -+ /* only supports internal transceiver */ -+ ecmd->transceiver = XCVR_INTERNAL; ++#undef ALIGN ++#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) + -+ /* this isn't fully supported at higher layers */ -+ ecmd->phy_address = mii->phy_id; ++#ifndef page_count ++#define page_count(p) atomic_read(&(p)->count) ++#endif + -+ ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII; -+ advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); -+ if (advert & ADVERTISE_10HALF) -+ ecmd->advertising |= ADVERTISED_10baseT_Half; -+ if (advert & ADVERTISE_10FULL) -+ ecmd->advertising |= ADVERTISED_10baseT_Full; -+ if (advert & ADVERTISE_100HALF) -+ ecmd->advertising |= ADVERTISED_100baseT_Half; -+ if (advert & ADVERTISE_100FULL) -+ ecmd->advertising |= ADVERTISED_100baseT_Full; ++/* find_first_bit and find_next bit are not defined for most ++ * 2.4 kernels (except for the redhat 2.4.21 kernels ++ */ ++#include ++#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) ++#undef find_next_bit ++#define find_next_bit _kc_find_next_bit ++extern unsigned long _kc_find_next_bit(const unsigned long *addr, ++ unsigned long size, ++ unsigned long offset); ++#define find_first_bit(addr, size) find_next_bit((addr), (size), 0) + -+ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); -+ lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA); -+ if (bmcr & BMCR_ANENABLE) { -+ ecmd->advertising |= ADVERTISED_Autoneg; -+ ecmd->autoneg = AUTONEG_ENABLE; -+ -+ nego = mii_nway_result(advert & lpa); -+ if (nego == LPA_100FULL || nego == LPA_100HALF) -+ ecmd->speed = SPEED_100; -+ else -+ ecmd->speed = SPEED_10; -+ if (nego == LPA_100FULL || nego == LPA_10FULL) { -+ ecmd->duplex = DUPLEX_FULL; -+ mii->full_duplex = 1; -+ } else { -+ ecmd->duplex = DUPLEX_HALF; -+ mii->full_duplex = 0; -+ } -+ } else { -+ ecmd->autoneg = AUTONEG_DISABLE; ++#endif /* 2.6.0 => 2.5.28 */ + -+ ecmd->speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; -+ ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; -+ } ++/*****************************************************************************/ ++/* 2.6.4 => 2.6.0 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) ++#define MODULE_VERSION(_version) MODULE_INFO(version, _version) ++#endif /* 2.6.4 => 2.6.0 */ + -+ /* ignore maxtxpkt, maxrxpkt for now */ ++/*****************************************************************************/ ++/* 2.6.5 => 2.6.0 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) ++#define pci_dma_sync_single_for_cpu pci_dma_sync_single ++#define pci_dma_sync_single_for_device pci_dma_sync_single_for_cpu ++#endif /* 2.6.5 => 2.6.0 */ + -+ return 0; ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,6) ) ++/* taken from 2.6 include/linux/bitmap.h */ ++#undef bitmap_zero ++#define bitmap_zero _kc_bitmap_zero ++static inline void _kc_bitmap_zero(unsigned long *dst, int nbits) ++{ ++ if (nbits <= BITS_PER_LONG) ++ *dst = 0UL; ++ else { ++ int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long); ++ memset(dst, 0, len); ++ } +} -+ -+int _kc_mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) ++#define random_ether_addr _kc_random_ether_addr ++static inline void _kc_random_ether_addr(u8 *addr) +{ -+ struct net_device *dev = mii->dev; -+ -+ if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100) -+ return -EINVAL; -+ if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) -+ return -EINVAL; -+ if (ecmd->port != PORT_MII) -+ return -EINVAL; -+ if (ecmd->transceiver != XCVR_INTERNAL) -+ return -EINVAL; -+ if (ecmd->phy_address != mii->phy_id) -+ return -EINVAL; -+ if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE) -+ return -EINVAL; -+ -+ /* ignore supported, maxtxpkt, maxrxpkt */ -+ -+ if (ecmd->autoneg == AUTONEG_ENABLE) { -+ u32 bmcr, advert, tmp; ++ get_random_bytes(addr, ETH_ALEN); ++ addr[0] &= 0xfe; /* clear multicast */ ++ addr[0] |= 0x02; /* set local assignment */ ++} ++#endif /* < 2.6.6 */ + -+ if ((ecmd->advertising & (ADVERTISED_10baseT_Half | -+ ADVERTISED_10baseT_Full | -+ ADVERTISED_100baseT_Half | -+ ADVERTISED_100baseT_Full)) == 0) -+ return -EINVAL; ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) ) ++#undef if_mii ++#define if_mii _kc_if_mii ++static inline struct mii_ioctl_data *_kc_if_mii(struct ifreq *rq) ++{ ++ return (struct mii_ioctl_data *) &rq->ifr_ifru; ++} ++#endif /* < 2.6.7 */ + -+ /* advertise only what has been requested */ -+ advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); -+ tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4); -+ if (ADVERTISED_10baseT_Half) -+ tmp |= ADVERTISE_10HALF; -+ if (ADVERTISED_10baseT_Full) -+ tmp |= ADVERTISE_10FULL; -+ if (ADVERTISED_100baseT_Half) -+ tmp |= ADVERTISE_100HALF; -+ if (ADVERTISED_100baseT_Full) -+ tmp |= ADVERTISE_100FULL; -+ if (advert != tmp) { -+ mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp); -+ mii->advertising = tmp; -+ } -+ -+ /* turn on autonegotiation, and force a renegotiate */ -+ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); -+ bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); -+ mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr); ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) ) ++#ifndef PCI_EXP_DEVCTL ++#define PCI_EXP_DEVCTL 8 ++#endif ++#ifndef PCI_EXP_DEVCTL_CERE ++#define PCI_EXP_DEVCTL_CERE 0x0001 ++#endif ++#define msleep(x) do { set_current_state(TASK_UNINTERRUPTIBLE); \ ++ schedule_timeout((x * HZ)/1000 + 2); \ ++ } while (0) + -+ mii->force_media = 0; -+ } else { -+ u32 bmcr, tmp; ++#endif /* < 2.6.8 */ + -+ /* turn off auto negotiation, set speed and duplexity */ -+ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); -+ tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX); -+ if (ecmd->speed == SPEED_100) -+ tmp |= BMCR_SPEED100; -+ if (ecmd->duplex == DUPLEX_FULL) { -+ tmp |= BMCR_FULLDPLX; -+ mii->full_duplex = 1; -+ } else -+ mii->full_duplex = 0; -+ if (bmcr != tmp) -+ mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp); ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)) ++#include ++#define __iomem + -+ mii->force_media = 1; -+ } -+ return 0; ++#ifndef kcalloc ++#define kcalloc(n, size, flags) _kc_kzalloc(((n) * (size)), flags) ++extern void *_kc_kzalloc(size_t size, int flags); ++#endif ++#define MSEC_PER_SEC 1000L ++static inline unsigned int _kc_jiffies_to_msecs(const unsigned long j) ++{ ++#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) ++ return (MSEC_PER_SEC / HZ) * j; ++#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) ++ return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC); ++#else ++ return (j * MSEC_PER_SEC) / HZ; ++#endif +} -+ -+int _kc_mii_link_ok (struct mii_if_info *mii) ++static inline unsigned long _kc_msecs_to_jiffies(const unsigned int m) +{ -+ /* first, a dummy read, needed to latch some MII phys */ -+ mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); -+ if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS) -+ return 1; -+ return 0; ++ if (m > _kc_jiffies_to_msecs(MAX_JIFFY_OFFSET)) ++ return MAX_JIFFY_OFFSET; ++#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) ++ return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ); ++#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) ++ return m * (HZ / MSEC_PER_SEC); ++#else ++ return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC; ++#endif +} + -+int _kc_mii_nway_restart (struct mii_if_info *mii) ++#define msleep_interruptible _kc_msleep_interruptible ++static inline unsigned long _kc_msleep_interruptible(unsigned int msecs) +{ -+ int bmcr; -+ int r = -EINVAL; -+ -+ /* if autoneg is off, it's an error */ -+ bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR); ++ unsigned long timeout = _kc_msecs_to_jiffies(msecs) + 1; + -+ if (bmcr & BMCR_ANENABLE) { -+ bmcr |= BMCR_ANRESTART; -+ mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr); -+ r = 0; ++ while (timeout && !signal_pending(current)) { ++ __set_current_state(TASK_INTERRUPTIBLE); ++ timeout = schedule_timeout(timeout); + } -+ -+ return r; ++ return _kc_jiffies_to_msecs(timeout); +} + -+void _kc_mii_check_link (struct mii_if_info *mii) -+{ -+ int cur_link = mii_link_ok(mii); -+ int prev_link = netif_carrier_ok(mii->dev); ++/* Basic mode control register. */ ++#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */ + -+ if (cur_link && !prev_link) -+ netif_carrier_on(mii->dev); -+ else if (prev_link && !cur_link) -+ netif_carrier_off(mii->dev); -+} ++#ifndef __le16 ++#define __le16 u16 ++#endif ++#ifndef __le32 ++#define __le32 u32 ++#endif ++#ifndef __le64 ++#define __le64 u64 ++#endif ++#ifndef __be16 ++#define __be16 u16 ++#endif + -+int _kc_generic_mii_ioctl(struct mii_if_info *mii_if, -+ struct mii_ioctl_data *mii_data, int cmd, -+ unsigned int *duplex_chg_out) ++#ifdef pci_dma_mapping_error ++#undef pci_dma_mapping_error ++#endif ++#define pci_dma_mapping_error _kc_pci_dma_mapping_error ++static inline int _kc_pci_dma_mapping_error(struct pci_dev *pdev, ++ dma_addr_t dma_addr) +{ -+ int rc = 0; -+ unsigned int duplex_changed = 0; -+ -+ if (duplex_chg_out) -+ *duplex_chg_out = 0; ++ return dma_addr == 0; ++} ++#endif /* < 2.6.9 */ + -+ mii_data->phy_id &= mii_if->phy_id_mask; -+ mii_data->reg_num &= mii_if->reg_num_mask; ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) ++#ifdef module_param_array_named ++#undef module_param_array_named ++#define module_param_array_named(name, array, type, nump, perm) \ ++ static struct kparam_array __param_arr_##name \ ++ = { ARRAY_SIZE(array), nump, param_set_##type, param_get_##type, \ ++ sizeof(array[0]), array }; \ ++ module_param_call(name, param_array_set, param_array_get, \ ++ &__param_arr_##name, perm) ++#endif /* module_param_array_named */ ++#endif /* < 2.6.10 */ + -+ switch(cmd) { -+ case SIOCDEVPRIVATE: /* binary compat, remove in 2.5 */ -+ case SIOCGMIIPHY: -+ mii_data->phy_id = mii_if->phy_id; -+ /* fall through */ ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) ) ++#define PCI_D0 0 ++#define PCI_D1 1 ++#define PCI_D2 2 ++#define PCI_D3hot 3 ++#define PCI_D3cold 4 ++typedef int pci_power_t; ++#define pci_choose_state(pdev,state) state ++#define PMSG_SUSPEND 3 ++#define PCI_EXP_LNKCTL 16 + -+ case SIOCDEVPRIVATE + 1:/* binary compat, remove in 2.5 */ -+ case SIOCGMIIREG: -+ mii_data->val_out = -+ mii_if->mdio_read(mii_if->dev, mii_data->phy_id, -+ mii_data->reg_num); -+ break; ++#undef NETIF_F_LLTX + -+ case SIOCDEVPRIVATE + 2:/* binary compat, remove in 2.5 */ -+ case SIOCSMIIREG: { -+ u16 val = mii_data->val_in; ++#ifndef ARCH_HAS_PREFETCH ++#define prefetch(X) ++#endif + -+ if (!capable(CAP_NET_ADMIN)) -+ return -EPERM; ++#ifndef NET_IP_ALIGN ++#define NET_IP_ALIGN 2 ++#endif + -+ if (mii_data->phy_id == mii_if->phy_id) { -+ switch(mii_data->reg_num) { -+ case MII_BMCR: { -+ unsigned int new_duplex = 0; -+ if (val & (BMCR_RESET|BMCR_ANENABLE)) -+ mii_if->force_media = 0; -+ else -+ mii_if->force_media = 1; -+ if (mii_if->force_media && -+ (val & BMCR_FULLDPLX)) -+ new_duplex = 1; -+ if (mii_if->full_duplex != new_duplex) { -+ duplex_changed = 1; -+ mii_if->full_duplex = new_duplex; -+ } -+ break; -+ } -+ case MII_ADVERTISE: -+ mii_if->advertising = val; -+ break; -+ default: -+ /* do nothing */ -+ break; -+ } -+ } ++#define KC_USEC_PER_SEC 1000000L ++#define usecs_to_jiffies _kc_usecs_to_jiffies ++static inline unsigned int _kc_jiffies_to_usecs(const unsigned long j) ++{ ++#if HZ <= KC_USEC_PER_SEC && !(KC_USEC_PER_SEC % HZ) ++ return (KC_USEC_PER_SEC / HZ) * j; ++#elif HZ > KC_USEC_PER_SEC && !(HZ % KC_USEC_PER_SEC) ++ return (j + (HZ / KC_USEC_PER_SEC) - 1)/(HZ / KC_USEC_PER_SEC); ++#else ++ return (j * KC_USEC_PER_SEC) / HZ; ++#endif ++} ++static inline unsigned long _kc_usecs_to_jiffies(const unsigned int m) ++{ ++ if (m > _kc_jiffies_to_usecs(MAX_JIFFY_OFFSET)) ++ return MAX_JIFFY_OFFSET; ++#if HZ <= KC_USEC_PER_SEC && !(KC_USEC_PER_SEC % HZ) ++ return (m + (KC_USEC_PER_SEC / HZ) - 1) / (KC_USEC_PER_SEC / HZ); ++#elif HZ > KC_USEC_PER_SEC && !(HZ % KC_USEC_PER_SEC) ++ return m * (HZ / KC_USEC_PER_SEC); ++#else ++ return (m * HZ + KC_USEC_PER_SEC - 1) / KC_USEC_PER_SEC; ++#endif ++} ++#endif /* < 2.6.11 */ + -+ mii_if->mdio_write(mii_if->dev, mii_data->phy_id, -+ mii_data->reg_num, val); -+ break; -+ } ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) ) ++#include ++#define USE_REBOOT_NOTIFIER + -+ default: -+ rc = -EOPNOTSUPP; -+ break; -+ } ++/* Generic MII registers. */ ++#define MII_CTRL1000 0x09 /* 1000BASE-T control */ ++#define MII_STAT1000 0x0a /* 1000BASE-T status */ ++/* Advertisement control register. */ ++#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */ ++#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymmetric pause */ ++/* 1000BASE-T Control register */ ++#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */ ++#endif /* < 2.6.12 */ + -+ if ((rc == 0) && (duplex_chg_out) && (duplex_changed)) -+ *duplex_chg_out = 1; ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ) ++#define pm_message_t u32 ++#ifndef kzalloc ++#define kzalloc _kc_kzalloc ++extern void *_kc_kzalloc(size_t size, int flags); ++#endif + -+ return rc; -+} ++/* Generic MII registers. */ ++#define MII_ESTATUS 0x0f /* Extended Status */ ++/* Basic mode status register. */ ++#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */ ++/* Extended status register. */ ++#define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */ ++#define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */ ++#endif /* < 2.6.14 */ + -diff -Nru vanilla/drivers/net/igb/kcompat.h linux-i686-2.6.22/drivers/net/igb/kcompat.h ---- vanilla/drivers/net/igb/kcompat.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/kcompat.h 2009-07-16 19:25:22.000000000 -0400 -@@ -0,0 +1,1637 @@ -+/******************************************************************************* ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) ) ++#ifndef device_can_wakeup ++#define device_can_wakeup(dev) (1) ++#endif ++#ifndef device_set_wakeup_enable ++#define device_set_wakeup_enable(dev, val) do{}while(0) ++#endif ++#ifndef device_init_wakeup ++#define device_init_wakeup(dev,val) do {} while (0) ++#endif ++#endif /* < 2.6.15 */ + -+ Intel(R) Gigabit Ethernet Linux driver -+ Copyright(c) 2007-2008 Intel Corporation. ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) ) ++#undef DEFINE_MUTEX ++#define DEFINE_MUTEX(x) DECLARE_MUTEX(x) ++#define mutex_lock(x) down_interruptible(x) ++#define mutex_unlock(x) up(x) + -+ 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. ++#undef HAVE_PCI_ERS ++#else /* 2.6.16 and above */ ++#undef HAVE_PCI_ERS ++#define HAVE_PCI_ERS ++#endif /* < 2.6.16 */ + -+ 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. ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ) + -+ 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. ++#ifndef IRQ_HANDLED ++#define irqreturn_t void ++#define IRQ_HANDLED ++#define IRQ_NONE ++#endif + -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". ++#ifndef IRQF_PROBE_SHARED ++#ifdef SA_PROBEIRQ ++#define IRQF_PROBE_SHARED SA_PROBEIRQ ++#else ++#define IRQF_PROBE_SHARED 0 ++#endif ++#endif + -+ Contact Information: -+ e1000-devel Mailing List -+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++#ifndef IRQF_SHARED ++#define IRQF_SHARED SA_SHIRQ ++#endif + -+*******************************************************************************/ ++#ifndef ARRAY_SIZE ++#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) ++#endif + -+#ifndef _KCOMPAT_H_ -+#define _KCOMPAT_H_ ++#ifndef netdev_alloc_skb ++#define netdev_alloc_skb _kc_netdev_alloc_skb ++extern struct sk_buff *_kc_netdev_alloc_skb(struct net_device *dev, ++ unsigned int length); ++#endif + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++#ifndef skb_is_gso ++#ifdef NETIF_F_TSO ++#define skb_is_gso _kc_skb_is_gso ++static inline int _kc_skb_is_gso(const struct sk_buff *skb) ++{ ++ return skb_shinfo(skb)->gso_size; ++} ++#else ++#define skb_is_gso(a) 0 ++#endif ++#endif + -+/* NAPI enable/disable flags here */ ++#endif /* < 2.6.18 */ + ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ) + -+#ifdef _E1000_H_ -+#ifdef CONFIG_E1000_NAPI -+#define NAPI ++#ifndef DIV_ROUND_UP ++#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) +#endif -+#ifdef E1000_NAPI -+#undef NAPI -+#define NAPI ++#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ) ++#ifndef RHEL_RELEASE_CODE ++#define RHEL_RELEASE_CODE 0 +#endif -+#ifdef E1000E_NAPI -+#undef NAPI -+#define NAPI ++#ifndef RHEL_RELEASE_VERSION ++#define RHEL_RELEASE_VERSION(a,b) 0 +#endif -+#ifdef E1000_NO_NAPI -+#undef NAPI ++#ifndef AX_RELEASE_CODE ++#define AX_RELEASE_CODE 0 +#endif -+#ifdef E1000E_NO_NAPI -+#undef NAPI ++#ifndef AX_RELEASE_VERSION ++#define AX_RELEASE_VERSION(a,b) 0 +#endif ++#if (!(( RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(4,4) ) && ( RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,0) ) || ( RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(5,0) ) || (AX_RELEASE_CODE > AX_RELEASE_VERSION(3,0)))) ++typedef irqreturn_t (*irq_handler_t)(int, void*, struct pt_regs *); +#endif -+ -+#ifdef _IGB_H_ -+#define NAPI ++#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(6,0)) ++#undef CONFIG_INET_LRO ++#undef CONFIG_INET_LRO_MODULE ++#ifdef IXGBE_FCOE ++#undef CONFIG_FCOE ++#undef CONFIG_FCOE_MODULE ++#endif /* IXGBE_FCOE */ +#endif ++typedef irqreturn_t (*new_handler_t)(int, void*); ++static inline irqreturn_t _kc_request_irq(unsigned int irq, new_handler_t handler, unsigned long flags, const char *devname, void *dev_id) ++#else /* 2.4.x */ ++typedef void (*irq_handler_t)(int, void*, struct pt_regs *); ++typedef void (*new_handler_t)(int, void*); ++static inline int _kc_request_irq(unsigned int irq, new_handler_t handler, unsigned long flags, const char *devname, void *dev_id) ++#endif /* >= 2.5.x */ ++{ ++ irq_handler_t new_handler = (irq_handler_t) handler; ++ return request_irq(irq, new_handler, flags, devname, dev_id); ++} + ++#undef request_irq ++#define request_irq(irq, handler, flags, devname, dev_id) _kc_request_irq((irq), (handler), (flags), (devname), (dev_id)) + ++#define irq_handler_t new_handler_t ++/* pci_restore_state and pci_save_state handles MSI/PCIE from 2.6.19 */ ++#define PCIE_CONFIG_SPACE_LEN 256 ++#define PCI_CONFIG_SPACE_LEN 64 ++#define PCIE_LINK_STATUS 0x12 ++#define pci_config_space_ich8lan() do {} while(0) ++#undef pci_save_state ++extern int _kc_pci_save_state(struct pci_dev *); ++#define pci_save_state(pdev) _kc_pci_save_state(pdev) ++#undef pci_restore_state ++extern void _kc_pci_restore_state(struct pci_dev *); ++#define pci_restore_state(pdev) _kc_pci_restore_state(pdev) ++#ifdef HAVE_PCI_ERS ++#undef free_netdev ++extern void _kc_free_netdev(struct net_device *); ++#define free_netdev(netdev) _kc_free_netdev(netdev) ++#endif ++static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev) ++{ ++ return 0; ++} ++#define pci_disable_pcie_error_reporting(dev) do {} while (0) ++#define pci_cleanup_aer_uncorrect_error_status(dev) do {} while (0) ++#else /* 2.6.19 */ ++#include ++#endif /* < 2.6.19 */ + ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ) ++#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28) ) ++#undef INIT_WORK ++#define INIT_WORK(_work, _func) \ ++do { \ ++ INIT_LIST_HEAD(&(_work)->entry); \ ++ (_work)->pending = 0; \ ++ (_work)->func = (void (*)(void *))_func; \ ++ (_work)->data = _work; \ ++ init_timer(&(_work)->timer); \ ++} while (0) ++#endif + ++#ifndef PCI_VDEVICE ++#define PCI_VDEVICE(ven, dev) \ ++ PCI_VENDOR_ID_##ven, (dev), \ ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0 ++#endif + ++#ifndef round_jiffies ++#define round_jiffies(x) x ++#endif + ++#define csum_offset csum + -+#define adapter_struct igb_adapter -+#define NAPI ++#endif /* < 2.6.20 */ + ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) ) ++#define to_net_dev(class) container_of(class, struct net_device, class_dev) ++#define NETDEV_CLASS_DEV ++#define vlan_group_get_device(vg, id) (vg->vlan_devices[id]) ++#define vlan_group_set_device(vg, id, dev) if (vg) vg->vlan_devices[id] = dev; ++#define pci_channel_offline(pdev) (pdev->error_state && \ ++ pdev->error_state != pci_channel_io_normal) ++#define pci_request_selected_regions(pdev, bars, name) \ ++ pci_request_regions(pdev, name) ++#define pci_release_selected_regions(pdev, bars) pci_release_regions(pdev); ++#endif /* < 2.6.21 */ + ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) ) ++#define tcp_hdr(skb) (skb->h.th) ++#define tcp_hdrlen(skb) (skb->h.th->doff << 2) ++#define skb_transport_offset(skb) (skb->h.raw - skb->data) ++#define skb_transport_header(skb) (skb->h.raw) ++#define ipv6_hdr(skb) (skb->nh.ipv6h) ++#define ip_hdr(skb) (skb->nh.iph) ++#define skb_network_offset(skb) (skb->nh.raw - skb->data) ++#define skb_network_header(skb) (skb->nh.raw) ++#define skb_tail_pointer(skb) skb->tail ++#define skb_copy_to_linear_data_offset(skb, offset, from, len) \ ++ memcpy(skb->data + offset, from, len) ++#define skb_network_header_len(skb) (skb->h.raw - skb->nh.raw) ++#define pci_register_driver pci_module_init ++#define skb_mac_header(skb) skb->mac.raw + -+/* and finally set defines so that the code sees the changes */ -+#ifdef NAPI -+#ifndef CONFIG_E1000_NAPI -+#define CONFIG_E1000_NAPI ++#ifdef NETIF_F_MULTI_QUEUE ++#ifndef alloc_etherdev_mq ++#define alloc_etherdev_mq(_a, _b) alloc_etherdev(_a) +#endif -+#ifndef CONFIG_E1000E_NAPI -+#define CONFIG_E1000E_NAPI ++#endif /* NETIF_F_MULTI_QUEUE */ ++ ++#ifndef ETH_FCS_LEN ++#define ETH_FCS_LEN 4 +#endif -+#else -+#undef CONFIG_E1000_NAPI -+#undef CONFIG_E1000E_NAPI -+#undef CONFIG_IXGB_NAPI ++#define cancel_work_sync(x) flush_scheduled_work() ++#ifndef udp_hdr ++#define udp_hdr _udp_hdr ++static inline struct udphdr *_udp_hdr(const struct sk_buff *skb) ++{ ++ return (struct udphdr *)skb_transport_header(skb); ++} +#endif ++#else /* 2.6.22 */ ++#define ETH_TYPE_TRANS_SETS_DEV ++#endif /* < 2.6.22 */ + -+/* packet split disable/enable */ -+#ifdef DISABLE_PACKET_SPLIT -+#undef CONFIG_E1000_DISABLE_PACKET_SPLIT -+#define CONFIG_E1000_DISABLE_PACKET_SPLIT -+#undef CONFIG_IGB_DISABLE_PACKET_SPLIT -+#define CONFIG_IGB_DISABLE_PACKET_SPLIT -+#endif ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) ) ++#undef ETHTOOL_GPERMADDR ++#undef SET_MODULE_OWNER ++#define SET_MODULE_OWNER(dev) do { } while (0) ++#endif /* > 2.6.22 */ + -+/* MSI compatibility code for all kernels and drivers */ -+#ifdef DISABLE_PCI_MSI -+#undef CONFIG_PCI_MSI -+#endif -+#ifndef CONFIG_PCI_MSI -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) ) -+struct msix_entry { -+ u16 vector; /* kernel uses to write allocated vector */ -+ u16 entry; /* driver uses to specify entry, OS writes */ ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) ) ++#define netif_subqueue_stopped(_a, _b) 0 ++#endif /* < 2.6.23 */ ++ ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) ) ++/* if GRO is supported then the napi struct must already exist */ ++#ifndef NETIF_F_GRO ++/* NAPI API changes in 2.6.24 break everything */ ++struct napi_struct { ++ /* used to look up the real NAPI polling routine */ ++ int (*poll)(struct napi_struct *, int); ++ struct net_device *dev; ++ int weight; +}; +#endif -+#define pci_enable_msi(a) -ENOTSUPP -+#define pci_disable_msi(a) do {} while (0) -+#define pci_enable_msix(a, b, c) -ENOTSUPP -+#define pci_disable_msix(a) do {} while (0) -+#define msi_remove_pci_irq_vectors(a) do {} while (0) -+#endif /* CONFIG_PCI_MSI */ -+#ifdef DISABLE_PM -+#undef CONFIG_PM -+#endif + -+#ifdef DISABLE_NET_POLL_CONTROLLER -+#undef CONFIG_NET_POLL_CONTROLLER -+#endif ++#ifdef NAPI ++extern int __kc_adapter_clean(struct net_device *, int *); ++extern struct net_device *napi_to_poll_dev(struct napi_struct *napi); ++#define napi_enable(napi) do { \ ++ struct napi_struct *_napi = (napi); \ ++ /* abuse if_port as a counter */ \ ++ if (!_napi->dev->if_port) { \ ++ netif_poll_enable(_napi->dev); \ ++ } \ ++ ++_napi->dev->if_port; \ ++ netif_poll_enable(napi_to_poll_dev(_napi)); \ ++ } while (0) ++#define napi_disable(napi) do { \ ++ struct napi_struct *_napi = (napi); \ ++ netif_poll_disable(napi_to_poll_dev(_napi)); \ ++ --_napi->dev->if_port; \ ++ if (!_napi->dev->if_port) \ ++ netif_poll_disable(_napi->dev); \ ++ } while (0) ++#define netif_napi_add(_netdev, _napi, _poll, _weight) \ ++ do { \ ++ struct napi_struct *__napi = (_napi); \ ++ struct net_device *poll_dev = napi_to_poll_dev(__napi); \ ++ poll_dev->poll = &(__kc_adapter_clean); \ ++ poll_dev->priv = (_napi); \ ++ poll_dev->weight = (_weight); \ ++ set_bit(__LINK_STATE_RX_SCHED, &poll_dev->state); \ ++ set_bit(__LINK_STATE_START, &poll_dev->state);\ ++ dev_hold(poll_dev); \ ++ _netdev->poll = &(__kc_adapter_clean); \ ++ _netdev->weight = (_weight); \ ++ __napi->poll = &(_poll); \ ++ __napi->weight = (_weight); \ ++ __napi->dev = (_netdev); \ ++ set_bit(__LINK_STATE_RX_SCHED, &(_netdev)->state); \ ++ } while (0) ++#define netif_napi_del(_napi) \ ++ do { \ ++ struct net_device *poll_dev = napi_to_poll_dev(_napi); \ ++ WARN_ON(!test_bit(__LINK_STATE_RX_SCHED, &poll_dev->state)); \ ++ dev_put(poll_dev); \ ++ memset(poll_dev, 0, sizeof(struct net_device));\ ++ } while (0) ++#define napi_schedule_prep(_napi) \ ++ (netif_running((_napi)->dev) && netif_rx_schedule_prep(napi_to_poll_dev(_napi))) ++#define napi_schedule(_napi) netif_rx_schedule(napi_to_poll_dev(_napi)) ++#define __napi_schedule(_napi) __netif_rx_schedule(napi_to_poll_dev(_napi)) ++#ifndef NETIF_F_GRO ++#define napi_complete(_napi) netif_rx_complete(napi_to_poll_dev(_napi)) ++#else ++#define napi_complete(_napi) \ ++ do { \ ++ napi_gro_flush(_napi); \ ++ netif_rx_complete(napi_to_poll_dev(_napi)); \ ++ } while (0) ++#endif /* NETIF_F_GRO */ ++#else /* NAPI */ ++#define netif_napi_add(_netdev, _napi, _poll, _weight) \ ++ do { \ ++ struct napi_struct *__napi = _napi; \ ++ _netdev->poll = &(_poll); \ ++ _netdev->weight = (_weight); \ ++ __napi->poll = &(_poll); \ ++ __napi->weight = (_weight); \ ++ __napi->dev = (_netdev); \ ++ } while (0) ++#define netif_napi_del(_a) do {} while (0) ++#endif /* NAPI */ ++ ++#undef dev_get_by_name ++#define dev_get_by_name(_a, _b) dev_get_by_name(_b) ++#define __netif_subqueue_stopped(_a, _b) netif_subqueue_stopped(_a, _b) ++#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) ++#else /* < 2.6.24 */ ++#define HAVE_ETHTOOL_GET_SSET_COUNT ++#define HAVE_NETDEV_NAPI_LIST ++#endif /* < 2.6.24 */ ++ ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24) ) ++#include ++#endif /* > 2.6.24 */ ++ ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) ) ++#define PM_QOS_CPU_DMA_LATENCY 1 ++ ++#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) ) ++#include ++#define PM_QOS_DEFAULT_VALUE INFINITE_LATENCY ++#define pm_qos_add_requirement(pm_qos_class, name, value) \ ++ set_acceptable_latency(name, value) ++#define pm_qos_remove_requirement(pm_qos_class, name) \ ++ remove_acceptable_latency(name) ++#define pm_qos_update_requirement(pm_qos_class, name, value) \ ++ modify_acceptable_latency(name, value) ++#else ++#define PM_QOS_DEFAULT_VALUE -1 ++#define pm_qos_add_requirement(pm_qos_class, name, value) ++#define pm_qos_remove_requirement(pm_qos_class, name) ++#define pm_qos_update_requirement(pm_qos_class, name, value) { \ ++ if (value != PM_QOS_DEFAULT_VALUE) { \ ++ printk(KERN_WARNING "%s: unable to set PM QoS requirement\n", \ ++ pci_name(adapter->pdev)); \ ++ } \ ++} ++#endif /* > 2.6.18 */ + -+#ifndef PMSG_SUSPEND -+#define PMSG_SUSPEND 3 -+#endif ++#define pci_enable_device_mem(pdev) pci_enable_device(pdev) + -+/* generic boolean compatibility */ -+#undef TRUE -+#undef FALSE -+#define TRUE true -+#define FALSE false -+#ifdef GCC_VERSION -+#if ( GCC_VERSION < 3000 ) -+#define _Bool char ++#endif /* < 2.6.25 */ ++ ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) ) ++#else /* < 2.6.26 */ ++#include ++#define HAVE_NETDEV_VLAN_FEATURES ++#endif /* < 2.6.26 */ ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) ) ++#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) ) ++#if (((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)) && defined(CONFIG_PM)) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)) && defined(CONFIG_PM_SLEEP))) ++#undef device_set_wakeup_enable ++#define device_set_wakeup_enable(dev, val) \ ++ do { \ ++ u16 pmc = 0; \ ++ int pm = pci_find_capability(adapter->pdev, PCI_CAP_ID_PM); \ ++ if (pm) { \ ++ pci_read_config_word(adapter->pdev, pm + PCI_PM_PMC, \ ++ &pmc); \ ++ } \ ++ (dev)->power.can_wakeup = !!(pmc >> 11); \ ++ (dev)->power.should_wakeup = (val && (pmc >> 11)); \ ++ } while (0) ++#endif /* 2.6.15-2.6.22 and CONFIG_PM or 2.6.23-2.6.25 and CONFIG_PM_SLEEP */ ++#endif /* 2.6.15 through 2.6.27 */ ++#ifndef netif_napi_del ++#define netif_napi_del(_a) do {} while (0) ++#ifdef NAPI ++#ifdef CONFIG_NETPOLL ++#undef netif_napi_del ++#define netif_napi_del(_a) list_del(&(_a)->dev_list); +#endif +#endif -+#ifndef bool -+#define bool _Bool -+#define true 1 -+#define false 0 ++#endif /* netif_napi_del */ ++#ifndef pci_dma_mapping_error ++#define pci_dma_mapping_error(pdev, dma_addr) pci_dma_mapping_error(dma_addr) +#endif + -+ -+#ifndef module_param -+#define module_param(v,t,p) MODULE_PARM(v, "i"); ++#ifdef CONFIG_NETDEVICES_MULTIQUEUE ++#define HAVE_TX_MQ +#endif + -+#ifndef DMA_64BIT_MASK -+#define DMA_64BIT_MASK 0xffffffffffffffffULL ++#ifdef HAVE_TX_MQ ++extern void _kc_netif_tx_stop_all_queues(struct net_device *); ++extern void _kc_netif_tx_wake_all_queues(struct net_device *); ++extern void _kc_netif_tx_start_all_queues(struct net_device *); ++#define netif_tx_stop_all_queues(a) _kc_netif_tx_stop_all_queues(a) ++#define netif_tx_wake_all_queues(a) _kc_netif_tx_wake_all_queues(a) ++#define netif_tx_start_all_queues(a) _kc_netif_tx_start_all_queues(a) ++#undef netif_stop_subqueue ++#define netif_stop_subqueue(_ndev,_qi) do { \ ++ if (netif_is_multiqueue((_ndev))) \ ++ netif_stop_subqueue((_ndev), (_qi)); \ ++ else \ ++ netif_stop_queue((_ndev)); \ ++ } while (0) ++#undef netif_start_subqueue ++#define netif_start_subqueue(_ndev,_qi) do { \ ++ if (netif_is_multiqueue((_ndev))) \ ++ netif_start_subqueue((_ndev), (_qi)); \ ++ else \ ++ netif_start_queue((_ndev)); \ ++ } while (0) ++#else /* HAVE_TX_MQ */ ++#define netif_tx_stop_all_queues(a) netif_stop_queue(a) ++#define netif_tx_wake_all_queues(a) netif_wake_queue(a) ++#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) ) ++#define netif_tx_start_all_queues(a) netif_start_queue(a) ++#else ++#define netif_tx_start_all_queues(a) do {} while (0) +#endif ++#define netif_stop_subqueue(_ndev,_qi) netif_stop_queue((_ndev)) ++#define netif_start_subqueue(_ndev,_qi) netif_start_queue((_ndev)) ++#endif /* HAVE_TX_MQ */ ++#ifndef NETIF_F_MULTI_QUEUE ++#define NETIF_F_MULTI_QUEUE 0 ++#define netif_is_multiqueue(a) 0 ++#define netif_wake_subqueue(a, b) ++#endif /* NETIF_F_MULTI_QUEUE */ ++#else /* < 2.6.27 */ ++#define HAVE_TX_MQ ++#define HAVE_NETDEV_SELECT_QUEUE ++#endif /* < 2.6.27 */ + -+#ifndef DMA_32BIT_MASK -+#define DMA_32BIT_MASK 0x00000000ffffffffULL -+#endif ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ) ++#define pci_ioremap_bar(pdev, bar) ioremap(pci_resource_start(pdev, bar), \ ++ pci_resource_len(pdev, bar)) ++#define pci_wake_from_d3 _kc_pci_wake_from_d3 ++#define pci_prepare_to_sleep _kc_pci_prepare_to_sleep ++extern int _kc_pci_wake_from_d3(struct pci_dev *dev, bool enable); ++extern int _kc_pci_prepare_to_sleep(struct pci_dev *dev); ++#define netdev_alloc_page(a) alloc_page(GFP_ATOMIC) ++#endif /* < 2.6.28 */ + -+#ifndef PCI_CAP_ID_EXP -+#define PCI_CAP_ID_EXP 0x10 -+#endif ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) ) ++#define pci_request_selected_regions_exclusive(pdev, bars, name) \ ++ pci_request_selected_regions(pdev, bars, name) ++extern void _kc_pci_disable_link_state(struct pci_dev *dev, int state); ++#define pci_disable_link_state(p, s) _kc_pci_disable_link_state(p, s) ++#else /* < 2.6.29 */ ++#ifdef CONFIG_DCB ++#define HAVE_PFC_MODE_ENABLE ++#endif /* CONFIG_DCB */ ++#endif /* < 2.6.29 */ + -+#ifndef mmiowb -+#ifdef CONFIG_IA64 -+#define mmiowb() asm volatile ("mf.a" ::: "memory") ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ) ++#ifdef IXGBE_FCOE ++#undef CONFIG_FCOE ++#undef CONFIG_FCOE_MODULE ++#endif /* IXGBE_FCOE */ ++extern u16 _kc_skb_tx_hash(struct net_device *dev, struct sk_buff *skb); ++#define skb_tx_hash(n, s) _kc_skb_tx_hash(n, s) ++#define skb_record_rx_queue(a, b) do {} while (0) +#else -+#define mmiowb() -+#endif -+#endif ++#define HAVE_ASPM_QUIRKS ++#endif /* < 2.6.30 */ + -+#ifndef IRQ_HANDLED -+#define irqreturn_t void -+#define IRQ_HANDLED -+#define IRQ_NONE ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) ) ++#define ETH_P_1588 0x88F7 ++#else ++#ifndef HAVE_NETDEV_STORAGE_ADDRESS ++#define HAVE_NETDEV_STORAGE_ADDRESS +#endif -+ -+#ifndef SET_NETDEV_DEV -+#define SET_NETDEV_DEV(net, pdev) ++#ifndef HAVE_NETDEV_HW_ADDR ++#define HAVE_NETDEV_HW_ADDR +#endif ++#endif /* < 2.6.31 */ + -+#ifndef HAVE_FREE_NETDEV -+#define free_netdev(x) kfree(x) -+#endif ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) ) ++#undef netdev_tx_t ++#define netdev_tx_t int ++#endif /* < 2.6.32 */ ++#endif /* _KCOMPAT_H_ */ +Index: linux-2.6.22/drivers/net/igb/kcompat_ethtool.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/net/igb/kcompat_ethtool.c 2009-12-18 12:39:22.000000000 -0500 +@@ -0,0 +1,1168 @@ ++/******************************************************************************* + -+#ifdef HAVE_POLL_CONTROLLER -+#define CONFIG_NET_POLL_CONTROLLER -+#endif ++ Intel(R) Gigabit Ethernet Linux driver ++ Copyright(c) 2007-2009 Intel Corporation. + -+#ifndef NETDEV_TX_OK -+#define NETDEV_TX_OK 0 -+#endif ++ 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. + -+#ifndef NETDEV_TX_BUSY -+#define NETDEV_TX_BUSY 1 -+#endif ++ 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. + -+#ifndef NETDEV_TX_LOCKED -+#define NETDEV_TX_LOCKED -1 -+#endif ++ 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. + -+#ifndef SKB_DATAREF_SHIFT -+/* if we do not have the infrastructure to detect if skb_header is cloned -+ just return false in all cases */ -+#define skb_header_cloned(x) 0 -+#endif ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". + -+#ifndef NETIF_F_GSO -+#define gso_size tso_size -+#define gso_segs tso_segs -+#endif ++ Contact Information: ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + -+#ifndef CHECKSUM_PARTIAL -+#define CHECKSUM_PARTIAL CHECKSUM_HW -+#define CHECKSUM_COMPLETE CHECKSUM_HW -+#endif ++*******************************************************************************/ + -+#ifndef __read_mostly -+#define __read_mostly -+#endif ++/* ++ * net/core/ethtool.c - Ethtool ioctl handler ++ * Copyright (c) 2003 Matthew Wilcox ++ * ++ * This file is where we call all the ethtool_ops commands to get ++ * the information ethtool needs. We fall back to calling do_ioctl() ++ * for drivers which haven't been converted to ethtool_ops yet. ++ * ++ * It's GPL, stupid. ++ * ++ * Modification by sfeldma@pobox.com to work as backward compat ++ * solution for pre-ethtool_ops kernels. ++ * - copied struct ethtool_ops from ethtool.h ++ * - defined SET_ETHTOOL_OPS ++ * - put in some #ifndef NETIF_F_xxx wrappers ++ * - changes refs to dev->ethtool_ops to ethtool_ops ++ * - changed dev_ethtool to ethtool_ioctl ++ * - remove EXPORT_SYMBOL()s ++ * - added _kc_ prefix in built-in ethtool_op_xxx ops. ++ */ + -+#ifndef HAVE_NETIF_MSG -+#define HAVE_NETIF_MSG 1 -+enum { -+ NETIF_MSG_DRV = 0x0001, -+ NETIF_MSG_PROBE = 0x0002, -+ NETIF_MSG_LINK = 0x0004, -+ NETIF_MSG_TIMER = 0x0008, -+ NETIF_MSG_IFDOWN = 0x0010, -+ NETIF_MSG_IFUP = 0x0020, -+ NETIF_MSG_RX_ERR = 0x0040, -+ NETIF_MSG_TX_ERR = 0x0080, -+ NETIF_MSG_TX_QUEUED = 0x0100, -+ NETIF_MSG_INTR = 0x0200, -+ NETIF_MSG_TX_DONE = 0x0400, -+ NETIF_MSG_RX_STATUS = 0x0800, -+ NETIF_MSG_PKTDATA = 0x1000, -+ NETIF_MSG_HW = 0x2000, -+ NETIF_MSG_WOL = 0x4000, -+}; ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+#else -+#define NETIF_MSG_HW 0x2000 -+#define NETIF_MSG_WOL 0x4000 -+#endif /* HAVE_NETIF_MSG */ ++#include "kcompat.h" + -+#ifndef MII_RESV1 -+#define MII_RESV1 0x17 /* Reserved... */ -+#endif ++#undef SUPPORTED_10000baseT_Full ++#define SUPPORTED_10000baseT_Full (1 << 12) ++#undef ADVERTISED_10000baseT_Full ++#define ADVERTISED_10000baseT_Full (1 << 12) ++#undef SPEED_10000 ++#define SPEED_10000 10000 + -+#ifndef unlikely -+#define unlikely(_x) _x -+#define likely(_x) _x -+#endif ++#undef ethtool_ops ++#define ethtool_ops _kc_ethtool_ops ++ ++struct _kc_ethtool_ops { ++ int (*get_settings)(struct net_device *, struct ethtool_cmd *); ++ int (*set_settings)(struct net_device *, struct ethtool_cmd *); ++ void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); ++ int (*get_regs_len)(struct net_device *); ++ void (*get_regs)(struct net_device *, struct ethtool_regs *, void *); ++ void (*get_wol)(struct net_device *, struct ethtool_wolinfo *); ++ int (*set_wol)(struct net_device *, struct ethtool_wolinfo *); ++ u32 (*get_msglevel)(struct net_device *); ++ void (*set_msglevel)(struct net_device *, u32); ++ int (*nway_reset)(struct net_device *); ++ u32 (*get_link)(struct net_device *); ++ int (*get_eeprom_len)(struct net_device *); ++ int (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); ++ int (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); ++ int (*get_coalesce)(struct net_device *, struct ethtool_coalesce *); ++ int (*set_coalesce)(struct net_device *, struct ethtool_coalesce *); ++ void (*get_ringparam)(struct net_device *, struct ethtool_ringparam *); ++ int (*set_ringparam)(struct net_device *, struct ethtool_ringparam *); ++ void (*get_pauseparam)(struct net_device *, ++ struct ethtool_pauseparam*); ++ int (*set_pauseparam)(struct net_device *, ++ struct ethtool_pauseparam*); ++ u32 (*get_rx_csum)(struct net_device *); ++ int (*set_rx_csum)(struct net_device *, u32); ++ u32 (*get_tx_csum)(struct net_device *); ++ int (*set_tx_csum)(struct net_device *, u32); ++ u32 (*get_sg)(struct net_device *); ++ int (*set_sg)(struct net_device *, u32); ++ u32 (*get_tso)(struct net_device *); ++ int (*set_tso)(struct net_device *, u32); ++ int (*self_test_count)(struct net_device *); ++ void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); ++ void (*get_strings)(struct net_device *, u32 stringset, u8 *); ++ int (*phys_id)(struct net_device *, u32); ++ int (*get_stats_count)(struct net_device *); ++ void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, ++ u64 *); ++} *ethtool_ops = NULL; + -+#ifndef WARN_ON -+#define WARN_ON(x) -+#endif ++#undef SET_ETHTOOL_OPS ++#define SET_ETHTOOL_OPS(netdev, ops) (ethtool_ops = (ops)) + -+#ifndef PCI_DEVICE -+#define PCI_DEVICE(vend,dev) \ -+ .vendor = (vend), .device = (dev), \ -+ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID -+#endif ++/* ++ * Some useful ethtool_ops methods that are device independent. If we find that ++ * all drivers want to do the same thing here, we can turn these into dev_() ++ * function calls. ++ */ + -+#ifndef num_online_cpus -+#define num_online_cpus() smp_num_cpus -+#endif ++#undef ethtool_op_get_link ++#define ethtool_op_get_link _kc_ethtool_op_get_link ++u32 _kc_ethtool_op_get_link(struct net_device *dev) ++{ ++ return netif_carrier_ok(dev) ? 1 : 0; ++} + -+#ifndef _LINUX_RANDOM_H -+#include ++#undef ethtool_op_get_tx_csum ++#define ethtool_op_get_tx_csum _kc_ethtool_op_get_tx_csum ++u32 _kc_ethtool_op_get_tx_csum(struct net_device *dev) ++{ ++#ifdef NETIF_F_IP_CSUM ++ return (dev->features & NETIF_F_IP_CSUM) != 0; ++#else ++ return 0; +#endif ++} + -+#ifndef DECLARE_BITMAP -+#ifndef BITS_TO_LONGS -+#define BITS_TO_LONGS(bits) (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) -+#endif -+#define DECLARE_BITMAP(name,bits) long name[BITS_TO_LONGS(bits)] ++#undef ethtool_op_set_tx_csum ++#define ethtool_op_set_tx_csum _kc_ethtool_op_set_tx_csum ++int _kc_ethtool_op_set_tx_csum(struct net_device *dev, u32 data) ++{ ++#ifdef NETIF_F_IP_CSUM ++ if (data) ++#ifdef NETIF_F_IPV6_CSUM ++ dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); ++ else ++ dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); ++#else ++ dev->features |= NETIF_F_IP_CSUM; ++ else ++ dev->features &= ~NETIF_F_IP_CSUM; +#endif -+ -+#ifndef VLAN_HLEN -+#define VLAN_HLEN 4 +#endif + -+#ifndef VLAN_ETH_HLEN -+#define VLAN_ETH_HLEN 18 -+#endif ++ return 0; ++} + -+#ifndef VLAN_ETH_FRAME_LEN -+#define VLAN_ETH_FRAME_LEN 1518 ++#undef ethtool_op_get_sg ++#define ethtool_op_get_sg _kc_ethtool_op_get_sg ++u32 _kc_ethtool_op_get_sg(struct net_device *dev) ++{ ++#ifdef NETIF_F_SG ++ return (dev->features & NETIF_F_SG) != 0; ++#else ++ return 0; +#endif ++} + -+#ifndef DCA_GET_TAG_TWO_ARGS -+#define dca3_get_tag(a,b) dca_get_tag(b) ++#undef ethtool_op_set_sg ++#define ethtool_op_set_sg _kc_ethtool_op_set_sg ++int _kc_ethtool_op_set_sg(struct net_device *dev, u32 data) ++{ ++#ifdef NETIF_F_SG ++ if (data) ++ dev->features |= NETIF_F_SG; ++ else ++ dev->features &= ~NETIF_F_SG; +#endif + ++ return 0; ++} + -+/*****************************************************************************/ -+/* Installations with ethtool version without eeprom, adapter id, or statistics -+ * support */ -+ -+#ifndef ETH_GSTRING_LEN -+#define ETH_GSTRING_LEN 32 ++#undef ethtool_op_get_tso ++#define ethtool_op_get_tso _kc_ethtool_op_get_tso ++u32 _kc_ethtool_op_get_tso(struct net_device *dev) ++{ ++#ifdef NETIF_F_TSO ++ return (dev->features & NETIF_F_TSO) != 0; ++#else ++ return 0; +#endif ++} + -+#ifndef ETHTOOL_GSTATS -+#define ETHTOOL_GSTATS 0x1d -+#undef ethtool_drvinfo -+#define ethtool_drvinfo k_ethtool_drvinfo -+struct k_ethtool_drvinfo { -+ u32 cmd; -+ char driver[32]; -+ char version[32]; -+ char fw_version[32]; -+ char bus_info[32]; -+ char reserved1[32]; -+ char reserved2[16]; -+ u32 n_stats; -+ u32 testinfo_len; -+ u32 eedump_len; -+ u32 regdump_len; -+}; -+ -+struct ethtool_stats { -+ u32 cmd; -+ u32 n_stats; -+ u64 data[0]; -+}; -+#endif /* ETHTOOL_GSTATS */ -+ -+#ifndef ETHTOOL_PHYS_ID -+#define ETHTOOL_PHYS_ID 0x1c -+#endif /* ETHTOOL_PHYS_ID */ -+ -+#ifndef ETHTOOL_GSTRINGS -+#define ETHTOOL_GSTRINGS 0x1b -+enum ethtool_stringset { -+ ETH_SS_TEST = 0, -+ ETH_SS_STATS, -+}; -+struct ethtool_gstrings { -+ u32 cmd; /* ETHTOOL_GSTRINGS */ -+ u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ -+ u32 len; /* number of strings in the string set */ -+ u8 data[0]; -+}; -+#endif /* ETHTOOL_GSTRINGS */ -+ -+#ifndef ETHTOOL_TEST -+#define ETHTOOL_TEST 0x1a -+enum ethtool_test_flags { -+ ETH_TEST_FL_OFFLINE = (1 << 0), -+ ETH_TEST_FL_FAILED = (1 << 1), -+}; -+struct ethtool_test { -+ u32 cmd; -+ u32 flags; -+ u32 reserved; -+ u32 len; -+ u64 data[0]; -+}; -+#endif /* ETHTOOL_TEST */ -+ -+#ifndef ETHTOOL_GEEPROM -+#define ETHTOOL_GEEPROM 0xb -+#undef ETHTOOL_GREGS -+struct ethtool_eeprom { -+ u32 cmd; -+ u32 magic; -+ u32 offset; -+ u32 len; -+ u8 data[0]; -+}; -+ -+struct ethtool_value { -+ u32 cmd; -+ u32 data; -+}; -+#endif /* ETHTOOL_GEEPROM */ -+ -+#ifndef ETHTOOL_GLINK -+#define ETHTOOL_GLINK 0xa -+#endif /* ETHTOOL_GLINK */ -+ -+#ifndef ETHTOOL_GREGS -+#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers */ -+#define ethtool_regs _kc_ethtool_regs -+/* for passing big chunks of data */ -+struct _kc_ethtool_regs { -+ u32 cmd; -+ u32 version; /* driver-specific, indicates different chips/revs */ -+ u32 len; /* bytes */ -+ u8 data[0]; -+}; -+#endif /* ETHTOOL_GREGS */ -+ -+#ifndef ETHTOOL_GMSGLVL -+#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ -+#endif -+#ifndef ETHTOOL_SMSGLVL -+#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level, priv. */ -+#endif -+#ifndef ETHTOOL_NWAY_RST -+#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation, priv */ -+#endif -+#ifndef ETHTOOL_GLINK -+#define ETHTOOL_GLINK 0x0000000a /* Get link status */ -+#endif -+#ifndef ETHTOOL_GEEPROM -+#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ -+#endif -+#ifndef ETHTOOL_SEEPROM -+#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data */ ++#undef ethtool_op_set_tso ++#define ethtool_op_set_tso _kc_ethtool_op_set_tso ++int _kc_ethtool_op_set_tso(struct net_device *dev, u32 data) ++{ ++#ifdef NETIF_F_TSO ++ if (data) ++ dev->features |= NETIF_F_TSO; ++ else ++ dev->features &= ~NETIF_F_TSO; +#endif -+#ifndef ETHTOOL_GCOALESCE -+#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ -+/* for configuring coalescing parameters of chip */ -+#define ethtool_coalesce _kc_ethtool_coalesce -+struct _kc_ethtool_coalesce { -+ u32 cmd; /* ETHTOOL_{G,S}COALESCE */ -+ -+ /* How many usecs to delay an RX interrupt after -+ * a packet arrives. If 0, only rx_max_coalesced_frames -+ * is used. -+ */ -+ u32 rx_coalesce_usecs; + -+ /* How many packets to delay an RX interrupt after -+ * a packet arrives. If 0, only rx_coalesce_usecs is -+ * used. It is illegal to set both usecs and max frames -+ * to zero as this would cause RX interrupts to never be -+ * generated. -+ */ -+ u32 rx_max_coalesced_frames; -+ -+ /* Same as above two parameters, except that these values -+ * apply while an IRQ is being serviced by the host. Not -+ * all cards support this feature and the values are ignored -+ * in that case. -+ */ -+ u32 rx_coalesce_usecs_irq; -+ u32 rx_max_coalesced_frames_irq; ++ return 0; ++} + -+ /* How many usecs to delay a TX interrupt after -+ * a packet is sent. If 0, only tx_max_coalesced_frames -+ * is used. -+ */ -+ u32 tx_coalesce_usecs; ++/* Handlers for each ethtool command */ + -+ /* How many packets to delay a TX interrupt after -+ * a packet is sent. If 0, only tx_coalesce_usecs is -+ * used. It is illegal to set both usecs and max frames -+ * to zero as this would cause TX interrupts to never be -+ * generated. -+ */ -+ u32 tx_max_coalesced_frames; ++static int ethtool_get_settings(struct net_device *dev, void *useraddr) ++{ ++ struct ethtool_cmd cmd = { ETHTOOL_GSET }; ++ int err; + -+ /* Same as above two parameters, except that these values -+ * apply while an IRQ is being serviced by the host. Not -+ * all cards support this feature and the values are ignored -+ * in that case. -+ */ -+ u32 tx_coalesce_usecs_irq; -+ u32 tx_max_coalesced_frames_irq; ++ if (!ethtool_ops->get_settings) ++ return -EOPNOTSUPP; + -+ /* How many usecs to delay in-memory statistics -+ * block updates. Some drivers do not have an in-memory -+ * statistic block, and in such cases this value is ignored. -+ * This value must not be zero. -+ */ -+ u32 stats_block_coalesce_usecs; ++ err = ethtool_ops->get_settings(dev, &cmd); ++ if (err < 0) ++ return err; + -+ /* Adaptive RX/TX coalescing is an algorithm implemented by -+ * some drivers to improve latency under low packet rates and -+ * improve throughput under high packet rates. Some drivers -+ * only implement one of RX or TX adaptive coalescing. Anything -+ * not implemented by the driver causes these values to be -+ * silently ignored. -+ */ -+ u32 use_adaptive_rx_coalesce; -+ u32 use_adaptive_tx_coalesce; ++ if (copy_to_user(useraddr, &cmd, sizeof(cmd))) ++ return -EFAULT; ++ return 0; ++} + -+ /* When the packet rate (measured in packets per second) -+ * is below pkt_rate_low, the {rx,tx}_*_low parameters are -+ * used. -+ */ -+ u32 pkt_rate_low; -+ u32 rx_coalesce_usecs_low; -+ u32 rx_max_coalesced_frames_low; -+ u32 tx_coalesce_usecs_low; -+ u32 tx_max_coalesced_frames_low; ++static int ethtool_set_settings(struct net_device *dev, void *useraddr) ++{ ++ struct ethtool_cmd cmd; + -+ /* When the packet rate is below pkt_rate_high but above -+ * pkt_rate_low (both measured in packets per second) the -+ * normal {rx,tx}_* coalescing parameters are used. -+ */ ++ if (!ethtool_ops->set_settings) ++ return -EOPNOTSUPP; + -+ /* When the packet rate is (measured in packets per second) -+ * is above pkt_rate_high, the {rx,tx}_*_high parameters are -+ * used. -+ */ -+ u32 pkt_rate_high; -+ u32 rx_coalesce_usecs_high; -+ u32 rx_max_coalesced_frames_high; -+ u32 tx_coalesce_usecs_high; -+ u32 tx_max_coalesced_frames_high; ++ if (copy_from_user(&cmd, useraddr, sizeof(cmd))) ++ return -EFAULT; + -+ /* How often to do adaptive coalescing packet rate sampling, -+ * measured in seconds. Must not be zero. -+ */ -+ u32 rate_sample_interval; -+}; -+#endif /* ETHTOOL_GCOALESCE */ ++ return ethtool_ops->set_settings(dev, &cmd); ++} + -+#ifndef ETHTOOL_SCOALESCE -+#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ -+#endif -+#ifndef ETHTOOL_GRINGPARAM -+#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ -+/* for configuring RX/TX ring parameters */ -+#define ethtool_ringparam _kc_ethtool_ringparam -+struct _kc_ethtool_ringparam { -+ u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ ++static int ethtool_get_drvinfo(struct net_device *dev, void *useraddr) ++{ ++ struct ethtool_drvinfo info; ++ struct ethtool_ops *ops = ethtool_ops; + -+ /* Read only attributes. These indicate the maximum number -+ * of pending RX/TX ring entries the driver will allow the -+ * user to set. -+ */ -+ u32 rx_max_pending; -+ u32 rx_mini_max_pending; -+ u32 rx_jumbo_max_pending; -+ u32 tx_max_pending; ++ if (!ops->get_drvinfo) ++ return -EOPNOTSUPP; + -+ /* Values changeable by the user. The valid values are -+ * in the range 1 to the "*_max_pending" counterpart above. -+ */ -+ u32 rx_pending; -+ u32 rx_mini_pending; -+ u32 rx_jumbo_pending; -+ u32 tx_pending; -+}; -+#endif /* ETHTOOL_GRINGPARAM */ ++ memset(&info, 0, sizeof(info)); ++ info.cmd = ETHTOOL_GDRVINFO; ++ ops->get_drvinfo(dev, &info); + -+#ifndef ETHTOOL_SRINGPARAM -+#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters, priv. */ -+#endif -+#ifndef ETHTOOL_GPAUSEPARAM -+#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ -+/* for configuring link flow control parameters */ -+#define ethtool_pauseparam _kc_ethtool_pauseparam -+struct _kc_ethtool_pauseparam { -+ u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ ++ if (ops->self_test_count) ++ info.testinfo_len = ops->self_test_count(dev); ++ if (ops->get_stats_count) ++ info.n_stats = ops->get_stats_count(dev); ++ if (ops->get_regs_len) ++ info.regdump_len = ops->get_regs_len(dev); ++ if (ops->get_eeprom_len) ++ info.eedump_len = ops->get_eeprom_len(dev); + -+ /* If the link is being auto-negotiated (via ethtool_cmd.autoneg -+ * being true) the user may set 'autoneg' here non-zero to have the -+ * pause parameters be auto-negotiated too. In such a case, the -+ * {rx,tx}_pause values below determine what capabilities are -+ * advertised. -+ * -+ * If 'autoneg' is zero or the link is not being auto-negotiated, -+ * then {rx,tx}_pause force the driver to use/not-use pause -+ * flow control. -+ */ -+ u32 autoneg; -+ u32 rx_pause; -+ u32 tx_pause; -+}; -+#endif /* ETHTOOL_GPAUSEPARAM */ ++ if (copy_to_user(useraddr, &info, sizeof(info))) ++ return -EFAULT; ++ return 0; ++} + -+#ifndef ETHTOOL_SPAUSEPARAM -+#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ -+#endif -+#ifndef ETHTOOL_GRXCSUM -+#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ -+#endif -+#ifndef ETHTOOL_SRXCSUM -+#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ -+#endif -+#ifndef ETHTOOL_GTXCSUM -+#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ -+#endif -+#ifndef ETHTOOL_STXCSUM -+#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ -+#endif -+#ifndef ETHTOOL_GSG -+#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable -+ * (ethtool_value) */ -+#endif -+#ifndef ETHTOOL_SSG -+#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable -+ * (ethtool_value). */ -+#endif -+#ifndef ETHTOOL_TEST -+#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */ -+#endif -+#ifndef ETHTOOL_GSTRINGS -+#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ -+#endif -+#ifndef ETHTOOL_PHYS_ID -+#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ -+#endif -+#ifndef ETHTOOL_GSTATS -+#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ -+#endif -+#ifndef ETHTOOL_GTSO -+#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ -+#endif -+#ifndef ETHTOOL_STSO -+#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ -+#endif ++static int ethtool_get_regs(struct net_device *dev, char *useraddr) ++{ ++ struct ethtool_regs regs; ++ struct ethtool_ops *ops = ethtool_ops; ++ void *regbuf; ++ int reglen, ret; + -+#ifndef ETHTOOL_BUSINFO_LEN -+#define ETHTOOL_BUSINFO_LEN 32 -+#endif ++ if (!ops->get_regs || !ops->get_regs_len) ++ return -EOPNOTSUPP; + -+/*****************************************************************************/ -+/* 2.4.3 => 2.4.0 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) ) ++ if (copy_from_user(®s, useraddr, sizeof(regs))) ++ return -EFAULT; + -+/**************************************/ -+/* PCI DRIVER API */ ++ reglen = ops->get_regs_len(dev); ++ if (regs.len > reglen) ++ regs.len = reglen; + -+#ifndef pci_set_dma_mask -+#define pci_set_dma_mask _kc_pci_set_dma_mask -+extern int _kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask); -+#endif ++ regbuf = kmalloc(reglen, GFP_USER); ++ if (!regbuf) ++ return -ENOMEM; + -+#ifndef pci_request_regions -+#define pci_request_regions _kc_pci_request_regions -+extern int _kc_pci_request_regions(struct pci_dev *pdev, char *res_name); -+#endif ++ ops->get_regs(dev, ®s, regbuf); + -+#ifndef pci_release_regions -+#define pci_release_regions _kc_pci_release_regions -+extern void _kc_pci_release_regions(struct pci_dev *pdev); -+#endif ++ ret = -EFAULT; ++ if (copy_to_user(useraddr, ®s, sizeof(regs))) ++ goto out; ++ useraddr += offsetof(struct ethtool_regs, data); ++ if (copy_to_user(useraddr, regbuf, reglen)) ++ goto out; ++ ret = 0; + -+/**************************************/ -+/* NETWORK DRIVER API */ ++out: ++ kfree(regbuf); ++ return ret; ++} + -+#ifndef alloc_etherdev -+#define alloc_etherdev _kc_alloc_etherdev -+extern struct net_device * _kc_alloc_etherdev(int sizeof_priv); -+#endif ++static int ethtool_get_wol(struct net_device *dev, char *useraddr) ++{ ++ struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; ++ ++ if (!ethtool_ops->get_wol) ++ return -EOPNOTSUPP; + -+#ifndef is_valid_ether_addr -+#define is_valid_ether_addr _kc_is_valid_ether_addr -+extern int _kc_is_valid_ether_addr(u8 *addr); -+#endif ++ ethtool_ops->get_wol(dev, &wol); + -+/**************************************/ -+/* MISCELLANEOUS */ ++ if (copy_to_user(useraddr, &wol, sizeof(wol))) ++ return -EFAULT; ++ return 0; ++} + -+#ifndef INIT_TQUEUE -+#define INIT_TQUEUE(_tq, _routine, _data) \ -+ do { \ -+ INIT_LIST_HEAD(&(_tq)->list); \ -+ (_tq)->sync = 0; \ -+ (_tq)->routine = _routine; \ -+ (_tq)->data = _data; \ -+ } while (0) -+#endif ++static int ethtool_set_wol(struct net_device *dev, char *useraddr) ++{ ++ struct ethtool_wolinfo wol; + -+#endif /* 2.4.3 => 2.4.0 */ ++ if (!ethtool_ops->set_wol) ++ return -EOPNOTSUPP; + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,5) ) -+/* Generic MII registers. */ -+#define MII_BMCR 0x00 /* Basic mode control register */ -+#define MII_BMSR 0x01 /* Basic mode status register */ -+#define MII_PHYSID1 0x02 /* PHYS ID 1 */ -+#define MII_PHYSID2 0x03 /* PHYS ID 2 */ -+#define MII_ADVERTISE 0x04 /* Advertisement control reg */ -+#define MII_LPA 0x05 /* Link partner ability reg */ -+#define MII_EXPANSION 0x06 /* Expansion register */ -+/* Basic mode control register. */ -+#define BMCR_FULLDPLX 0x0100 /* Full duplex */ -+#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */ -+/* Basic mode status register. */ -+#define BMSR_ERCAP 0x0001 /* Ext-reg capability */ -+#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */ -+#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */ -+#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */ -+#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */ -+#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */ -+/* Advertisement control register. */ -+#define ADVERTISE_CSMA 0x0001 /* Only selector supported */ -+#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ -+#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ -+#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ -+#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ -+#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \ -+ ADVERTISE_100HALF | ADVERTISE_100FULL) -+/* Expansion register for auto-negotiation. */ -+#define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */ -+#endif ++ if (copy_from_user(&wol, useraddr, sizeof(wol))) ++ return -EFAULT; + -+/*****************************************************************************/ -+/* 2.4.6 => 2.4.3 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) ) ++ return ethtool_ops->set_wol(dev, &wol); ++} + -+#ifndef pci_set_power_state -+#define pci_set_power_state _kc_pci_set_power_state -+extern int _kc_pci_set_power_state(struct pci_dev *dev, int state); -+#endif ++static int ethtool_get_msglevel(struct net_device *dev, char *useraddr) ++{ ++ struct ethtool_value edata = { ETHTOOL_GMSGLVL }; + -+#ifndef pci_enable_wake -+#define pci_enable_wake _kc_pci_enable_wake -+extern int _kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable); -+#endif ++ if (!ethtool_ops->get_msglevel) ++ return -EOPNOTSUPP; + -+#ifndef pci_disable_device -+#define pci_disable_device _kc_pci_disable_device -+extern void _kc_pci_disable_device(struct pci_dev *pdev); -+#endif ++ edata.data = ethtool_ops->get_msglevel(dev); + -+/* PCI PM entry point syntax changed, so don't support suspend/resume */ -+#undef CONFIG_PM ++ if (copy_to_user(useraddr, &edata, sizeof(edata))) ++ return -EFAULT; ++ return 0; ++} + -+#endif /* 2.4.6 => 2.4.3 */ ++static int ethtool_set_msglevel(struct net_device *dev, char *useraddr) ++{ ++ struct ethtool_value edata; + -+#ifndef HAVE_PCI_SET_MWI -+#define pci_set_mwi(X) pci_write_config_word(X, \ -+ PCI_COMMAND, adapter->hw.bus.pci_cmd_word | \ -+ PCI_COMMAND_INVALIDATE); -+#define pci_clear_mwi(X) pci_write_config_word(X, \ -+ PCI_COMMAND, adapter->hw.bus.pci_cmd_word & \ -+ ~PCI_COMMAND_INVALIDATE); -+#endif ++ if (!ethtool_ops->set_msglevel) ++ return -EOPNOTSUPP; + -+/*****************************************************************************/ -+/* 2.4.10 => 2.4.9 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) ) ++ if (copy_from_user(&edata, useraddr, sizeof(edata))) ++ return -EFAULT; + -+/**************************************/ -+/* MODULE API */ ++ ethtool_ops->set_msglevel(dev, edata.data); ++ return 0; ++} + -+#ifndef MODULE_LICENSE -+ #define MODULE_LICENSE(X) -+#endif ++static int ethtool_nway_reset(struct net_device *dev) ++{ ++ if (!ethtool_ops->nway_reset) ++ return -EOPNOTSUPP; + -+/**************************************/ -+/* OTHER */ ++ return ethtool_ops->nway_reset(dev); ++} + -+#undef min -+#define min(x,y) ({ \ -+ const typeof(x) _x = (x); \ -+ const typeof(y) _y = (y); \ -+ (void) (&_x == &_y); \ -+ _x < _y ? _x : _y; }) ++static int ethtool_get_link(struct net_device *dev, void *useraddr) ++{ ++ struct ethtool_value edata = { ETHTOOL_GLINK }; + -+#undef max -+#define max(x,y) ({ \ -+ const typeof(x) _x = (x); \ -+ const typeof(y) _y = (y); \ -+ (void) (&_x == &_y); \ -+ _x > _y ? _x : _y; }) ++ if (!ethtool_ops->get_link) ++ return -EOPNOTSUPP; + -+#ifndef list_for_each_safe -+#define list_for_each_safe(pos, n, head) \ -+ for (pos = (head)->next, n = pos->next; pos != (head); \ -+ pos = n, n = pos->next) -+#endif ++ edata.data = ethtool_ops->get_link(dev); + -+#endif /* 2.4.10 -> 2.4.6 */ ++ if (copy_to_user(useraddr, &edata, sizeof(edata))) ++ return -EFAULT; ++ return 0; ++} + ++static int ethtool_get_eeprom(struct net_device *dev, void *useraddr) ++{ ++ struct ethtool_eeprom eeprom; ++ struct ethtool_ops *ops = ethtool_ops; ++ u8 *data; ++ int ret; + -+/*****************************************************************************/ -+/* 2.4.13 => 2.4.10 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) ) ++ if (!ops->get_eeprom || !ops->get_eeprom_len) ++ return -EOPNOTSUPP; + -+/**************************************/ -+/* PCI DMA MAPPING */ ++ if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) ++ return -EFAULT; + -+#ifndef virt_to_page -+ #define virt_to_page(v) (mem_map + (virt_to_phys(v) >> PAGE_SHIFT)) -+#endif ++ /* Check for wrap and zero */ ++ if (eeprom.offset + eeprom.len <= eeprom.offset) ++ return -EINVAL; + -+#ifndef pci_map_page -+#define pci_map_page _kc_pci_map_page -+extern u64 _kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, size_t size, int direction); -+#endif ++ /* Check for exceeding total eeprom len */ ++ if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) ++ return -EINVAL; + -+#ifndef pci_unmap_page -+#define pci_unmap_page _kc_pci_unmap_page -+extern void _kc_pci_unmap_page(struct pci_dev *dev, u64 dma_addr, size_t size, int direction); -+#endif ++ data = kmalloc(eeprom.len, GFP_USER); ++ if (!data) ++ return -ENOMEM; + -+/* pci_set_dma_mask takes dma_addr_t, which is only 32-bits prior to 2.4.13 */ ++ ret = -EFAULT; ++ if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) ++ goto out; + -+#undef DMA_32BIT_MASK -+#define DMA_32BIT_MASK 0xffffffff -+#undef DMA_64BIT_MASK -+#define DMA_64BIT_MASK 0xffffffff ++ ret = ops->get_eeprom(dev, &eeprom, data); ++ if (ret) ++ goto out; + -+/**************************************/ -+/* OTHER */ ++ ret = -EFAULT; ++ if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) ++ goto out; ++ if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) ++ goto out; ++ ret = 0; + -+#ifndef cpu_relax -+#define cpu_relax() rep_nop() -+#endif ++out: ++ kfree(data); ++ return ret; ++} + -+#endif /* 2.4.13 => 2.4.10 */ ++static int ethtool_set_eeprom(struct net_device *dev, void *useraddr) ++{ ++ struct ethtool_eeprom eeprom; ++ struct ethtool_ops *ops = ethtool_ops; ++ u8 *data; ++ int ret; + -+/*****************************************************************************/ -+/* 2.4.17 => 2.4.12 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,17) ) ++ if (!ops->set_eeprom || !ops->get_eeprom_len) ++ return -EOPNOTSUPP; + -+#ifndef __devexit_p -+ #define __devexit_p(x) &(x) -+#endif ++ if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) ++ return -EFAULT; + -+#endif /* 2.4.17 => 2.4.13 */ ++ /* Check for wrap and zero */ ++ if (eeprom.offset + eeprom.len <= eeprom.offset) ++ return -EINVAL; + -+/*****************************************************************************/ -+/* 2.4.20 => 2.4.19 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20) ) ++ /* Check for exceeding total eeprom len */ ++ if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) ++ return -EINVAL; + -+/* we won't support NAPI on less than 2.4.20 */ -+#ifdef NAPI -+#undef CONFIG_E1000_NAPI -+#undef CONFIG_E1000E_NAPI -+#undef CONFIG_IXGB_NAPI -+#endif ++ data = kmalloc(eeprom.len, GFP_USER); ++ if (!data) ++ return -ENOMEM; + -+#endif /* 2.4.20 => 2.4.19 */ -+/*****************************************************************************/ -+/* 2.4.22 => 2.4.17 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) -+#define pci_name(x) ((x)->slot_name) -+#endif ++ ret = -EFAULT; ++ if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) ++ goto out; + -+/*****************************************************************************/ -+/* 2.4.22 => 2.4.17 */ ++ ret = ops->set_eeprom(dev, &eeprom, data); ++ if (ret) ++ goto out; + -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) -+#endif ++ if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) ++ ret = -EFAULT; + -+/*****************************************************************************/ -+/*****************************************************************************/ -+/* 2.4.23 => 2.4.22 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) ) -+/*****************************************************************************/ -+#ifdef NAPI -+#ifndef netif_poll_disable -+#define netif_poll_disable(x) _kc_netif_poll_disable(x) -+static inline void _kc_netif_poll_disable(struct net_device *netdev) -+{ -+ while (test_and_set_bit(__LINK_STATE_RX_SCHED, &netdev->state)) { -+ /* No hurry */ -+ current->state = TASK_INTERRUPTIBLE; -+ schedule_timeout(1); -+ } ++out: ++ kfree(data); ++ return ret; +} -+#endif + -+#ifndef netif_poll_enable -+#define netif_poll_enable(x) _kc_netif_poll_enable(x) -+static inline void _kc_netif_poll_enable(struct net_device *netdev) -+{ -+ clear_bit(__LINK_STATE_RX_SCHED, &netdev->state); -+} -+#endif -+#endif /* NAPI */ -+#ifndef netif_tx_disable -+#define netif_tx_disable(x) _kc_netif_tx_disable(x) -+static inline void _kc_netif_tx_disable(struct net_device *dev) ++static int ethtool_get_coalesce(struct net_device *dev, void *useraddr) +{ -+ spin_lock_bh(&dev->xmit_lock); -+ netif_stop_queue(dev); -+ spin_unlock_bh(&dev->xmit_lock); -+} -+#endif -+#endif /* 2.4.23 => 2.4.22 */ -+ -+/*****************************************************************************/ -+/* 2.6.4 => 2.6.0 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25) || \ -+ ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ -+ LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) ) -+#define ETHTOOL_OPS_COMPAT -+#endif /* 2.6.4 => 2.6.0 */ ++ struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE }; + -+/*****************************************************************************/ -+/* 2.5.71 => 2.4.x */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,71) ) -+#include -+#define sk_protocol protocol ++ if (!ethtool_ops->get_coalesce) ++ return -EOPNOTSUPP; + -+#define pci_get_device pci_find_device -+#endif /* 2.5.70 => 2.4.x */ ++ ethtool_ops->get_coalesce(dev, &coalesce); + -+/*****************************************************************************/ -+/* < 2.4.27 or 2.6.0 <= 2.6.5 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) || \ -+ ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ -+ LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) ) ++ if (copy_to_user(useraddr, &coalesce, sizeof(coalesce))) ++ return -EFAULT; ++ return 0; ++} + -+#ifndef netif_msg_init -+#define netif_msg_init _kc_netif_msg_init -+static inline u32 _kc_netif_msg_init(int debug_value, int default_msg_enable_bits) ++static int ethtool_set_coalesce(struct net_device *dev, void *useraddr) +{ -+ /* use default */ -+ if (debug_value < 0 || debug_value >= (sizeof(u32) * 8)) -+ return default_msg_enable_bits; -+ if (debug_value == 0) /* no output */ -+ return 0; -+ /* set low N bits */ -+ return (1 << debug_value) -1; -+} -+#endif ++ struct ethtool_coalesce coalesce; + -+#endif /* < 2.4.27 or 2.6.0 <= 2.6.5 */ -+/*****************************************************************************/ -+#if (( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) ) || \ -+ (( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) && \ -+ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ))) -+#define netdev_priv(x) x->priv -+#endif ++ if (!ethtool_ops->get_coalesce) ++ return -EOPNOTSUPP; + -+/*****************************************************************************/ -+/* <= 2.5.0 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) ) -+#undef pci_register_driver -+#define pci_register_driver pci_module_init ++ if (copy_from_user(&coalesce, useraddr, sizeof(coalesce))) ++ return -EFAULT; + -+#define dev_err(__unused_dev, format, arg...) \ -+ printk(KERN_ERR "%s: " format, pci_name(adapter->pdev) , ## arg) -+#define dev_warn(__unused_dev, format, arg...) \ -+ printk(KERN_WARNING "%s: " format, pci_name(pdev) , ## arg) ++ return ethtool_ops->set_coalesce(dev, &coalesce); ++} + -+/* hlist_* code - double linked lists */ -+struct hlist_head { -+ struct hlist_node *first; -+}; ++static int ethtool_get_ringparam(struct net_device *dev, void *useraddr) ++{ ++ struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM }; + -+struct hlist_node { -+ struct hlist_node *next, **pprev; -+}; ++ if (!ethtool_ops->get_ringparam) ++ return -EOPNOTSUPP; + -+static inline void __hlist_del(struct hlist_node *n) -+{ -+ struct hlist_node *next = n->next; -+ struct hlist_node **pprev = n->pprev; -+ *pprev = next; -+ if (next) -+ next->pprev = pprev; ++ ethtool_ops->get_ringparam(dev, &ringparam); ++ ++ if (copy_to_user(useraddr, &ringparam, sizeof(ringparam))) ++ return -EFAULT; ++ return 0; +} + -+static inline void hlist_del(struct hlist_node *n) ++static int ethtool_set_ringparam(struct net_device *dev, void *useraddr) +{ -+ __hlist_del(n); -+ n->next = NULL; -+ n->pprev = NULL; ++ struct ethtool_ringparam ringparam; ++ ++ if (!ethtool_ops->get_ringparam) ++ return -EOPNOTSUPP; ++ ++ if (copy_from_user(&ringparam, useraddr, sizeof(ringparam))) ++ return -EFAULT; ++ ++ return ethtool_ops->set_ringparam(dev, &ringparam); +} + -+static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) ++static int ethtool_get_pauseparam(struct net_device *dev, void *useraddr) +{ -+ struct hlist_node *first = h->first; -+ n->next = first; -+ if (first) -+ first->pprev = &n->next; -+ h->first = n; -+ n->pprev = &h->first; ++ struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; ++ ++ if (!ethtool_ops->get_pauseparam) ++ return -EOPNOTSUPP; ++ ++ ethtool_ops->get_pauseparam(dev, &pauseparam); ++ ++ if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam))) ++ return -EFAULT; ++ return 0; +} + -+static inline int hlist_empty(const struct hlist_head *h) ++static int ethtool_set_pauseparam(struct net_device *dev, void *useraddr) +{ -+ return !h->first; ++ struct ethtool_pauseparam pauseparam; ++ ++ if (!ethtool_ops->get_pauseparam) ++ return -EOPNOTSUPP; ++ ++ if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam))) ++ return -EFAULT; ++ ++ return ethtool_ops->set_pauseparam(dev, &pauseparam); +} -+#define HLIST_HEAD_INIT { .first = NULL } -+#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } -+#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) -+static inline void INIT_HLIST_NODE(struct hlist_node *h) ++ ++static int ethtool_get_rx_csum(struct net_device *dev, char *useraddr) +{ -+ h->next = NULL; -+ h->pprev = NULL; -+} -+#define hlist_entry(ptr, type, member) container_of(ptr,type,member) ++ struct ethtool_value edata = { ETHTOOL_GRXCSUM }; + -+#define hlist_for_each_entry(tpos, pos, head, member) \ -+ for (pos = (head)->first; \ -+ pos && ({ prefetch(pos->next); 1;}) && \ -+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ -+ pos = pos->next) ++ if (!ethtool_ops->get_rx_csum) ++ return -EOPNOTSUPP; + -+#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ -+ for (pos = (head)->first; \ -+ pos && ({ n = pos->next; 1; }) && \ -+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ -+ pos = n) ++ edata.data = ethtool_ops->get_rx_csum(dev); + -+/* we ignore GFP here */ -+#define dma_alloc_coherent(dv, sz, dma, gfp) \ -+ pci_alloc_consistent(pdev, (sz), (dma)) -+#define dma_free_coherent(dv, sz, addr, dma_addr) \ -+ pci_free_consistent(pdev, (sz), (addr), (dma_addr)) ++ if (copy_to_user(useraddr, &edata, sizeof(edata))) ++ return -EFAULT; ++ return 0; ++} + -+#ifndef might_sleep -+#define might_sleep() -+#endif ++static int ethtool_set_rx_csum(struct net_device *dev, char *useraddr) ++{ ++ struct ethtool_value edata; + -+#ifndef NETREG_REGISTERED -+#define NETREG_REGISTERED 1 -+#define reg_state deadbeaf -+#endif -+#endif /* <= 2.5.0 */ ++ if (!ethtool_ops->set_rx_csum) ++ return -EOPNOTSUPP; + -+/*****************************************************************************/ -+/* 2.5.28 => 2.4.23 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) ++ if (copy_from_user(&edata, useraddr, sizeof(edata))) ++ return -EFAULT; + -+static inline void _kc_synchronize_irq(void) -+{ -+ synchronize_irq(); ++ ethtool_ops->set_rx_csum(dev, edata.data); ++ return 0; +} -+#undef synchronize_irq -+#define synchronize_irq(X) _kc_synchronize_irq() + -+#include -+#define work_struct tq_struct -+#undef INIT_WORK -+#define INIT_WORK(a,b) INIT_TQUEUE(a,(void (*)(void *))b,a) -+#undef container_of -+#define container_of list_entry -+#define schedule_work schedule_task -+#define flush_scheduled_work flush_scheduled_tasks -+#define cancel_work_sync(x) flush_scheduled_work() ++static int ethtool_get_tx_csum(struct net_device *dev, char *useraddr) ++{ ++ struct ethtool_value edata = { ETHTOOL_GTXCSUM }; + -+#endif /* 2.5.28 => 2.4.17 */ ++ if (!ethtool_ops->get_tx_csum) ++ return -EOPNOTSUPP; + -+/*****************************************************************************/ -+/* 2.6.0 => 2.5.28 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) -+#define MODULE_INFO(version, _version) -+#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT -+#define CONFIG_E1000_DISABLE_PACKET_SPLIT 1 -+#endif -+#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT -+#define CONFIG_IGB_DISABLE_PACKET_SPLIT 1 -+#endif ++ edata.data = ethtool_ops->get_tx_csum(dev); + -+#define pci_set_consistent_dma_mask(dev,mask) 1 ++ if (copy_to_user(useraddr, &edata, sizeof(edata))) ++ return -EFAULT; ++ return 0; ++} + -+#undef dev_put -+#define dev_put(dev) __dev_put(dev) ++static int ethtool_set_tx_csum(struct net_device *dev, char *useraddr) ++{ ++ struct ethtool_value edata; + -+#ifndef skb_fill_page_desc -+#define skb_fill_page_desc _kc_skb_fill_page_desc -+extern void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size); -+#endif ++ if (!ethtool_ops->set_tx_csum) ++ return -EOPNOTSUPP; + -+#undef ALIGN -+#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) ++ if (copy_from_user(&edata, useraddr, sizeof(edata))) ++ return -EFAULT; + -+#ifndef page_count -+#define page_count(p) atomic_read(&(p)->count) -+#endif ++ return ethtool_ops->set_tx_csum(dev, edata.data); ++} + -+/* find_first_bit and find_next bit are not defined for most -+ * 2.4 kernels (except for the redhat 2.4.21 kernels -+ */ -+#include -+#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) -+#undef find_next_bit -+#define find_next_bit _kc_find_next_bit -+extern unsigned long _kc_find_next_bit(const unsigned long *addr, -+ unsigned long size, -+ unsigned long offset); -+#define find_first_bit(addr, size) find_next_bit((addr), (size), 0) ++static int ethtool_get_sg(struct net_device *dev, char *useraddr) ++{ ++ struct ethtool_value edata = { ETHTOOL_GSG }; + -+#endif /* 2.6.0 => 2.5.28 */ ++ if (!ethtool_ops->get_sg) ++ return -EOPNOTSUPP; + -+/*****************************************************************************/ -+/* 2.6.4 => 2.6.0 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) -+#define MODULE_VERSION(_version) MODULE_INFO(version, _version) -+#endif /* 2.6.4 => 2.6.0 */ ++ edata.data = ethtool_ops->get_sg(dev); + -+/*****************************************************************************/ -+/* 2.6.5 => 2.6.0 */ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) -+#define pci_dma_sync_single_for_cpu pci_dma_sync_single -+#define pci_dma_sync_single_for_device pci_dma_sync_single_for_cpu -+#endif /* 2.6.5 => 2.6.0 */ ++ if (copy_to_user(useraddr, &edata, sizeof(edata))) ++ return -EFAULT; ++ return 0; ++} + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,6) ) -+/* taken from 2.6 include/linux/bitmap.h */ -+#undef bitmap_zero -+#define bitmap_zero _kc_bitmap_zero -+static inline void _kc_bitmap_zero(unsigned long *dst, int nbits) ++static int ethtool_set_sg(struct net_device *dev, char *useraddr) +{ -+ if (nbits <= BITS_PER_LONG) -+ *dst = 0UL; -+ else { -+ int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long); -+ memset(dst, 0, len); -+ } ++ struct ethtool_value edata; ++ ++ if (!ethtool_ops->set_sg) ++ return -EOPNOTSUPP; ++ ++ if (copy_from_user(&edata, useraddr, sizeof(edata))) ++ return -EFAULT; ++ ++ return ethtool_ops->set_sg(dev, edata.data); +} -+#endif /* < 2.6.6 */ + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) ) -+#undef if_mii -+#define if_mii _kc_if_mii -+static inline struct mii_ioctl_data *_kc_if_mii(struct ifreq *rq) ++static int ethtool_get_tso(struct net_device *dev, char *useraddr) +{ -+ return (struct mii_ioctl_data *) &rq->ifr_ifru; -+} -+#endif /* < 2.6.7 */ ++ struct ethtool_value edata = { ETHTOOL_GTSO }; + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) ) -+#define msleep(x) do { set_current_state(TASK_UNINTERRUPTIBLE); \ -+ schedule_timeout((x * HZ)/1000 + 2); \ -+ } while (0) ++ if (!ethtool_ops->get_tso) ++ return -EOPNOTSUPP; + -+#endif /* < 2.6.8 */ ++ edata.data = ethtool_ops->get_tso(dev); + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)) -+#include -+#define __iomem ++ if (copy_to_user(useraddr, &edata, sizeof(edata))) ++ return -EFAULT; ++ return 0; ++} + -+#ifndef kcalloc -+#define kcalloc(n, size, flags) _kc_kzalloc(((n) * (size)), flags) -+extern void *_kc_kzalloc(size_t size, int flags); -+#endif -+#define MSEC_PER_SEC 1000L -+static inline unsigned int _kc_jiffies_to_msecs(const unsigned long j) ++static int ethtool_set_tso(struct net_device *dev, char *useraddr) +{ -+#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) -+ return (MSEC_PER_SEC / HZ) * j; -+#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) -+ return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC); -+#else -+ return (j * MSEC_PER_SEC) / HZ; -+#endif ++ struct ethtool_value edata; ++ ++ if (!ethtool_ops->set_tso) ++ return -EOPNOTSUPP; ++ ++ if (copy_from_user(&edata, useraddr, sizeof(edata))) ++ return -EFAULT; ++ ++ return ethtool_ops->set_tso(dev, edata.data); +} -+static inline unsigned long _kc_msecs_to_jiffies(const unsigned int m) ++ ++static int ethtool_self_test(struct net_device *dev, char *useraddr) +{ -+ if (m > _kc_jiffies_to_msecs(MAX_JIFFY_OFFSET)) -+ return MAX_JIFFY_OFFSET; -+#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) -+ return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ); -+#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) -+ return m * (HZ / MSEC_PER_SEC); -+#else -+ return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC; -+#endif ++ struct ethtool_test test; ++ struct ethtool_ops *ops = ethtool_ops; ++ u64 *data; ++ int ret; ++ ++ if (!ops->self_test || !ops->self_test_count) ++ return -EOPNOTSUPP; ++ ++ if (copy_from_user(&test, useraddr, sizeof(test))) ++ return -EFAULT; ++ ++ test.len = ops->self_test_count(dev); ++ data = kmalloc(test.len * sizeof(u64), GFP_USER); ++ if (!data) ++ return -ENOMEM; ++ ++ ops->self_test(dev, &test, data); ++ ++ ret = -EFAULT; ++ if (copy_to_user(useraddr, &test, sizeof(test))) ++ goto out; ++ useraddr += sizeof(test); ++ if (copy_to_user(useraddr, data, test.len * sizeof(u64))) ++ goto out; ++ ret = 0; ++ ++out: ++ kfree(data); ++ return ret; +} + -+#define msleep_interruptible _kc_msleep_interruptible -+static inline unsigned long _kc_msleep_interruptible(unsigned int msecs) ++static int ethtool_get_strings(struct net_device *dev, void *useraddr) +{ -+ unsigned long timeout = _kc_msecs_to_jiffies(msecs) + 1; ++ struct ethtool_gstrings gstrings; ++ struct ethtool_ops *ops = ethtool_ops; ++ u8 *data; ++ int ret; + -+ while (timeout && !signal_pending(current)) { -+ __set_current_state(TASK_INTERRUPTIBLE); -+ timeout = schedule_timeout(timeout); ++ if (!ops->get_strings) ++ return -EOPNOTSUPP; ++ ++ if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) ++ return -EFAULT; ++ ++ switch (gstrings.string_set) { ++ case ETH_SS_TEST: ++ if (!ops->self_test_count) ++ return -EOPNOTSUPP; ++ gstrings.len = ops->self_test_count(dev); ++ break; ++ case ETH_SS_STATS: ++ if (!ops->get_stats_count) ++ return -EOPNOTSUPP; ++ gstrings.len = ops->get_stats_count(dev); ++ break; ++ default: ++ return -EINVAL; + } -+ return _kc_jiffies_to_msecs(timeout); -+} + -+/* Basic mode control register. */ -+#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */ ++ data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); ++ if (!data) ++ return -ENOMEM; + -+#ifndef __le16 -+#define __le16 u16 -+#endif -+#ifndef __le32 -+#define __le32 u32 -+#endif -+#ifndef __le64 -+#define __le64 u64 -+#endif -+#endif /* < 2.6.9 */ ++ ops->get_strings(dev, gstrings.string_set, data); + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) -+#ifdef module_param_array_named -+#undef module_param_array_named -+#define module_param_array_named(name, array, type, nump, perm) \ -+ static struct kparam_array __param_arr_##name \ -+ = { ARRAY_SIZE(array), nump, param_set_##type, param_get_##type, \ -+ sizeof(array[0]), array }; \ -+ module_param_call(name, param_array_set, param_array_get, \ -+ &__param_arr_##name, perm) -+#endif /* module_param_array_named */ -+#endif /* < 2.6.10 */ ++ ret = -EFAULT; ++ if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) ++ goto out; ++ useraddr += sizeof(gstrings); ++ if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) ++ goto out; ++ ret = 0; + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) ) -+#define PCI_D0 0 -+#define PCI_D1 1 -+#define PCI_D2 2 -+#define PCI_D3hot 3 -+#define PCI_D3cold 4 -+#define pci_choose_state(pdev,state) state -+#define PMSG_SUSPEND 3 -+#define PCI_EXP_LNKCTL 16 ++out: ++ kfree(data); ++ return ret; ++} ++ ++static int ethtool_phys_id(struct net_device *dev, void *useraddr) ++{ ++ struct ethtool_value id; + -+#undef NETIF_F_LLTX ++ if (!ethtool_ops->phys_id) ++ return -EOPNOTSUPP; + -+#ifndef ARCH_HAS_PREFETCH -+#define prefetch(X) -+#endif ++ if (copy_from_user(&id, useraddr, sizeof(id))) ++ return -EFAULT; + -+#ifndef NET_IP_ALIGN -+#define NET_IP_ALIGN 2 -+#endif ++ return ethtool_ops->phys_id(dev, id.data); ++} + -+#define KC_USEC_PER_SEC 1000000L -+#define usecs_to_jiffies _kc_usecs_to_jiffies -+static inline unsigned int _kc_jiffies_to_usecs(const unsigned long j) ++static int ethtool_get_stats(struct net_device *dev, void *useraddr) +{ -+#if HZ <= KC_USEC_PER_SEC && !(KC_USEC_PER_SEC % HZ) -+ return (KC_USEC_PER_SEC / HZ) * j; -+#elif HZ > KC_USEC_PER_SEC && !(HZ % KC_USEC_PER_SEC) -+ return (j + (HZ / KC_USEC_PER_SEC) - 1)/(HZ / KC_USEC_PER_SEC); -+#else -+ return (j * KC_USEC_PER_SEC) / HZ; -+#endif ++ struct ethtool_stats stats; ++ struct ethtool_ops *ops = ethtool_ops; ++ u64 *data; ++ int ret; ++ ++ if (!ops->get_ethtool_stats || !ops->get_stats_count) ++ return -EOPNOTSUPP; ++ ++ if (copy_from_user(&stats, useraddr, sizeof(stats))) ++ return -EFAULT; ++ ++ stats.n_stats = ops->get_stats_count(dev); ++ data = kmalloc(stats.n_stats * sizeof(u64), GFP_USER); ++ if (!data) ++ return -ENOMEM; ++ ++ ops->get_ethtool_stats(dev, &stats, data); ++ ++ ret = -EFAULT; ++ if (copy_to_user(useraddr, &stats, sizeof(stats))) ++ goto out; ++ useraddr += sizeof(stats); ++ if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64))) ++ goto out; ++ ret = 0; ++ ++out: ++ kfree(data); ++ return ret; +} -+static inline unsigned long _kc_usecs_to_jiffies(const unsigned int m) ++ ++/* The main entry point in this file. Called from net/core/dev.c */ ++ ++#define ETHTOOL_OPS_COMPAT ++int ethtool_ioctl(struct ifreq *ifr) +{ -+ if (m > _kc_jiffies_to_usecs(MAX_JIFFY_OFFSET)) -+ return MAX_JIFFY_OFFSET; -+#if HZ <= KC_USEC_PER_SEC && !(KC_USEC_PER_SEC % HZ) -+ return (m + (KC_USEC_PER_SEC / HZ) - 1) / (KC_USEC_PER_SEC / HZ); -+#elif HZ > KC_USEC_PER_SEC && !(HZ % KC_USEC_PER_SEC) -+ return m * (HZ / KC_USEC_PER_SEC); -+#else -+ return (m * HZ + KC_USEC_PER_SEC - 1) / KC_USEC_PER_SEC; -+#endif -+} -+#endif /* < 2.6.11 */ ++ struct net_device *dev = __dev_get_by_name(ifr->ifr_name); ++ void *useraddr = (void *) ifr->ifr_data; ++ u32 ethcmd; + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) ) -+#include -+#define USE_REBOOT_NOTIFIER ++ /* ++ * XXX: This can be pushed down into the ethtool_* handlers that ++ * need it. Keep existing behavior for the moment. ++ */ ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; + -+/* Generic MII registers. */ -+#define MII_CTRL1000 0x09 /* 1000BASE-T control */ -+#define MII_STAT1000 0x0a /* 1000BASE-T status */ -+/* Advertisement control register. */ -+#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */ -+#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymmetric pause */ -+/* 1000BASE-T Control register */ -+#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */ -+#endif ++ if (!dev || !netif_device_present(dev)) ++ return -ENODEV; + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ) -+#define pm_message_t u32 -+#ifndef kzalloc -+#define kzalloc _kc_kzalloc -+extern void *_kc_kzalloc(size_t size, int flags); -+#endif ++ if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) ++ return -EFAULT; + -+/* Generic MII registers. */ -+#define MII_ESTATUS 0x0f /* Extended Status */ -+/* Basic mode status register. */ -+#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */ -+/* Extended status register. */ -+#define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */ -+#define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */ -+#endif ++ switch (ethcmd) { ++ case ETHTOOL_GSET: ++ return ethtool_get_settings(dev, useraddr); ++ case ETHTOOL_SSET: ++ return ethtool_set_settings(dev, useraddr); ++ case ETHTOOL_GDRVINFO: ++ return ethtool_get_drvinfo(dev, useraddr); ++ case ETHTOOL_GREGS: ++ return ethtool_get_regs(dev, useraddr); ++ case ETHTOOL_GWOL: ++ return ethtool_get_wol(dev, useraddr); ++ case ETHTOOL_SWOL: ++ return ethtool_set_wol(dev, useraddr); ++ case ETHTOOL_GMSGLVL: ++ return ethtool_get_msglevel(dev, useraddr); ++ case ETHTOOL_SMSGLVL: ++ return ethtool_set_msglevel(dev, useraddr); ++ case ETHTOOL_NWAY_RST: ++ return ethtool_nway_reset(dev); ++ case ETHTOOL_GLINK: ++ return ethtool_get_link(dev, useraddr); ++ case ETHTOOL_GEEPROM: ++ return ethtool_get_eeprom(dev, useraddr); ++ case ETHTOOL_SEEPROM: ++ return ethtool_set_eeprom(dev, useraddr); ++ case ETHTOOL_GCOALESCE: ++ return ethtool_get_coalesce(dev, useraddr); ++ case ETHTOOL_SCOALESCE: ++ return ethtool_set_coalesce(dev, useraddr); ++ case ETHTOOL_GRINGPARAM: ++ return ethtool_get_ringparam(dev, useraddr); ++ case ETHTOOL_SRINGPARAM: ++ return ethtool_set_ringparam(dev, useraddr); ++ case ETHTOOL_GPAUSEPARAM: ++ return ethtool_get_pauseparam(dev, useraddr); ++ case ETHTOOL_SPAUSEPARAM: ++ return ethtool_set_pauseparam(dev, useraddr); ++ case ETHTOOL_GRXCSUM: ++ return ethtool_get_rx_csum(dev, useraddr); ++ case ETHTOOL_SRXCSUM: ++ return ethtool_set_rx_csum(dev, useraddr); ++ case ETHTOOL_GTXCSUM: ++ return ethtool_get_tx_csum(dev, useraddr); ++ case ETHTOOL_STXCSUM: ++ return ethtool_set_tx_csum(dev, useraddr); ++ case ETHTOOL_GSG: ++ return ethtool_get_sg(dev, useraddr); ++ case ETHTOOL_SSG: ++ return ethtool_set_sg(dev, useraddr); ++ case ETHTOOL_GTSO: ++ return ethtool_get_tso(dev, useraddr); ++ case ETHTOOL_STSO: ++ return ethtool_set_tso(dev, useraddr); ++ case ETHTOOL_TEST: ++ return ethtool_self_test(dev, useraddr); ++ case ETHTOOL_GSTRINGS: ++ return ethtool_get_strings(dev, useraddr); ++ case ETHTOOL_PHYS_ID: ++ return ethtool_phys_id(dev, useraddr); ++ case ETHTOOL_GSTATS: ++ return ethtool_get_stats(dev, useraddr); ++ default: ++ return -EOPNOTSUPP; ++ } + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) ) -+#undef HAVE_PCI_ERS -+#else /* 2.6.16 and above */ -+#undef HAVE_PCI_ERS -+#define HAVE_PCI_ERS -+#endif ++ return -EOPNOTSUPP; ++} + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ) ++#define mii_if_info _kc_mii_if_info ++struct _kc_mii_if_info { ++ int phy_id; ++ int advertising; ++ int phy_id_mask; ++ int reg_num_mask; + -+#ifndef IRQF_PROBE_SHARED -+#ifdef SA_PROBEIRQ -+#define IRQF_PROBE_SHARED SA_PROBEIRQ -+#else -+#define IRQF_PROBE_SHARED 0 -+#endif -+#endif ++ unsigned int full_duplex : 1; /* is full duplex? */ ++ unsigned int force_media : 1; /* is autoneg. disabled? */ + -+#ifndef IRQF_SHARED -+#define IRQF_SHARED SA_SHIRQ -+#endif ++ struct net_device *dev; ++ int (*mdio_read) (struct net_device *dev, int phy_id, int location); ++ void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val); ++}; + -+#ifndef ARRAY_SIZE -+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -+#endif ++struct ethtool_cmd; ++struct mii_ioctl_data; + -+#ifndef netdev_alloc_skb -+#define netdev_alloc_skb _kc_netdev_alloc_skb -+extern struct sk_buff *_kc_netdev_alloc_skb(struct net_device *dev, -+ unsigned int length); -+#endif ++#undef mii_link_ok ++#define mii_link_ok _kc_mii_link_ok ++#undef mii_nway_restart ++#define mii_nway_restart _kc_mii_nway_restart ++#undef mii_ethtool_gset ++#define mii_ethtool_gset _kc_mii_ethtool_gset ++#undef mii_ethtool_sset ++#define mii_ethtool_sset _kc_mii_ethtool_sset ++#undef mii_check_link ++#define mii_check_link _kc_mii_check_link ++#undef generic_mii_ioctl ++#define generic_mii_ioctl _kc_generic_mii_ioctl ++extern int _kc_mii_link_ok (struct mii_if_info *mii); ++extern int _kc_mii_nway_restart (struct mii_if_info *mii); ++extern int _kc_mii_ethtool_gset(struct mii_if_info *mii, ++ struct ethtool_cmd *ecmd); ++extern int _kc_mii_ethtool_sset(struct mii_if_info *mii, ++ struct ethtool_cmd *ecmd); ++extern void _kc_mii_check_link (struct mii_if_info *mii); ++extern int _kc_generic_mii_ioctl(struct mii_if_info *mii_if, ++ struct mii_ioctl_data *mii_data, int cmd, ++ unsigned int *duplex_changed); + -+#ifndef skb_is_gso -+#ifdef NETIF_F_TSO -+#define skb_is_gso _kc_skb_is_gso -+static inline int _kc_skb_is_gso(const struct sk_buff *skb) -+{ -+ return skb_shinfo(skb)->gso_size; -+} -+#else -+#define skb_is_gso(a) 0 -+#endif -+#endif + -+#endif /* < 2.6.18 */ ++struct _kc_pci_dev_ext { ++ struct pci_dev *dev; ++ void *pci_drvdata; ++ struct pci_driver *driver; ++}; ++ ++struct _kc_net_dev_ext { ++ struct net_device *dev; ++ unsigned int carrier; ++}; + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ) + -+#ifndef DIV_ROUND_UP -+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) -+#endif ++/**************************************/ ++/* mii support */ + -+#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ) -+#ifndef RHEL_RELEASE_CODE -+#define RHEL_RELEASE_CODE 0 -+#endif -+#ifndef RHEL_RELEASE_VERSION -+#define RHEL_RELEASE_VERSION(a,b) 0 -+#endif -+#ifndef AX_RELEASE_CODE -+#define AX_RELEASE_CODE 0 -+#endif -+#ifndef AX_RELEASE_VERSION -+#define AX_RELEASE_VERSION(a,b) 0 -+#endif -+#if (!(( RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(4,4) ) && ( RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,0) ) || ( RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(5,0) ) || (AX_RELEASE_CODE > AX_RELEASE_VERSION(3,0)))) -+typedef irqreturn_t (*irq_handler_t)(int, void*, struct pt_regs *); -+#endif -+typedef irqreturn_t (*new_handler_t)(int, void*); -+static inline irqreturn_t _kc_request_irq(unsigned int irq, new_handler_t handler, unsigned long flags, const char *devname, void *dev_id) -+#else /* 2.4.x */ -+typedef void (*irq_handler_t)(int, void*, struct pt_regs *); -+typedef void (*new_handler_t)(int, void*); -+static inline int _kc_request_irq(unsigned int irq, new_handler_t handler, unsigned long flags, const char *devname, void *dev_id) -+#endif ++int _kc_mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) +{ -+ irq_handler_t new_handler = (irq_handler_t) handler; -+ return request_irq(irq, new_handler, flags, devname, dev_id); -+} ++ struct net_device *dev = mii->dev; ++ u32 advert, bmcr, lpa, nego; + -+#undef request_irq -+#define request_irq(irq, handler, flags, devname, dev_id) _kc_request_irq((irq), (handler), (flags), (devname), (dev_id)) ++ ecmd->supported = ++ (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | ++ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | ++ SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII); + -+#define irq_handler_t new_handler_t ++ /* only supports twisted-pair */ ++ ecmd->port = PORT_MII; + -+/* pci_restore_state and pci_save_state handles MSI/PCIE from 2.6.19 */ -+#define PCIE_CONFIG_SPACE_LEN 256 -+#define PCI_CONFIG_SPACE_LEN 64 -+#define PCIE_LINK_STATUS 0x12 -+#define pci_config_space_ich8lan() do {} while (0) -+#undef pci_save_state -+extern int _kc_pci_save_state(struct pci_dev *); -+#define pci_save_state(pdev) _kc_pci_save_state(pdev) -+#undef pci_restore_state -+extern void _kc_pci_restore_state(struct pci_dev *); -+#define pci_restore_state(pdev) _kc_pci_restore_state(pdev) -+#ifdef HAVE_PCI_ERS -+#undef free_netdev -+extern void _kc_free_netdev(struct net_device *); -+#define free_netdev(netdev) _kc_free_netdev(netdev) -+#endif ++ /* only supports internal transceiver */ ++ ecmd->transceiver = XCVR_INTERNAL; + -+#endif /* < 2.6.19 */ -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ) -+#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28) ) -+#undef INIT_WORK -+#define INIT_WORK(_work, _func) \ -+do { \ -+ INIT_LIST_HEAD(&(_work)->entry); \ -+ (_work)->pending = 0; \ -+ (_work)->func = (void (*)(void *))_func; \ -+ (_work)->data = _work; \ -+ init_timer(&(_work)->timer); \ -+} while (0) -+#endif ++ /* this isn't fully supported at higher layers */ ++ ecmd->phy_address = mii->phy_id; + -+#ifndef PCI_VDEVICE -+#define PCI_VDEVICE(ven, dev) \ -+ PCI_VENDOR_ID_##ven, (dev), \ -+ PCI_ANY_ID, PCI_ANY_ID, 0, 0 -+#endif ++ ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII; ++ advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); ++ if (advert & ADVERTISE_10HALF) ++ ecmd->advertising |= ADVERTISED_10baseT_Half; ++ if (advert & ADVERTISE_10FULL) ++ ecmd->advertising |= ADVERTISED_10baseT_Full; ++ if (advert & ADVERTISE_100HALF) ++ ecmd->advertising |= ADVERTISED_100baseT_Half; ++ if (advert & ADVERTISE_100FULL) ++ ecmd->advertising |= ADVERTISED_100baseT_Full; + -+#ifndef round_jiffies -+#define round_jiffies(x) x -+#endif ++ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); ++ lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA); ++ if (bmcr & BMCR_ANENABLE) { ++ ecmd->advertising |= ADVERTISED_Autoneg; ++ ecmd->autoneg = AUTONEG_ENABLE; + -+#define csum_offset csum ++ nego = mii_nway_result(advert & lpa); ++ if (nego == LPA_100FULL || nego == LPA_100HALF) ++ ecmd->speed = SPEED_100; ++ else ++ ecmd->speed = SPEED_10; ++ if (nego == LPA_100FULL || nego == LPA_10FULL) { ++ ecmd->duplex = DUPLEX_FULL; ++ mii->full_duplex = 1; ++ } else { ++ ecmd->duplex = DUPLEX_HALF; ++ mii->full_duplex = 0; ++ } ++ } else { ++ ecmd->autoneg = AUTONEG_DISABLE; + -+#endif /* < 2.6.20 */ ++ ecmd->speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; ++ ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; ++ } + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) ) -+#define vlan_group_get_device(vg, id) (vg->vlan_devices[id]) -+#define vlan_group_set_device(vg, id, dev) if (vg) vg->vlan_devices[id] = dev; -+#define pci_channel_offline(pdev) (pdev->error_state && \ -+ pdev->error_state != pci_channel_io_normal) -+#define pci_request_selected_regions(pdev, bars, name) \ -+ pci_request_regions(pdev, name) -+#define pci_release_selected_regions(pdev, bars) pci_release_regions(pdev); -+#endif /* < 2.6.21 */ ++ /* ignore maxtxpkt, maxrxpkt for now */ + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) ) -+#define tcp_hdr(skb) (skb->h.th) -+#define tcp_hdrlen(skb) (skb->h.th->doff << 2) -+#define skb_transport_offset(skb) (skb->h.raw - skb->data) -+#define skb_transport_header(skb) (skb->h.raw) -+#define ipv6_hdr(skb) (skb->nh.ipv6h) -+#define ip_hdr(skb) (skb->nh.iph) -+#define skb_network_offset(skb) (skb->nh.raw - skb->data) -+#define skb_network_header(skb) (skb->nh.raw) -+#define skb_tail_pointer(skb) skb->tail -+#define skb_copy_to_linear_data_offset(skb, offset, from, len) \ -+ memcpy(skb->data + offset, from, len) -+#define skb_network_header_len(skb) (skb->h.raw - skb->nh.raw) -+#define pci_register_driver pci_module_init -+#define skb_mac_header(skb) skb->mac.raw ++ return 0; ++} + -+#ifdef NETIF_F_MULTI_QUEUE -+#ifndef alloc_etherdev_mq -+#define alloc_etherdev_mq(_a, _b) alloc_etherdev(_a) -+#endif -+#endif /* NETIF_F_MULTI_QUEUE */ ++int _kc_mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) ++{ ++ struct net_device *dev = mii->dev; + -+#ifndef ETH_FCS_LEN -+#define ETH_FCS_LEN 4 -+#endif -+#define cancel_work_sync(x) flush_scheduled_work() -+#endif /* < 2.6.22 */ ++ if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100) ++ return -EINVAL; ++ if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) ++ return -EINVAL; ++ if (ecmd->port != PORT_MII) ++ return -EINVAL; ++ if (ecmd->transceiver != XCVR_INTERNAL) ++ return -EINVAL; ++ if (ecmd->phy_address != mii->phy_id) ++ return -EINVAL; ++ if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE) ++ return -EINVAL; + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) ) -+#undef ETHTOOL_GPERMADDR -+#undef SET_MODULE_OWNER -+#define SET_MODULE_OWNER(dev) do { } while (0) -+#endif /* > 2.6.22 */ ++ /* ignore supported, maxtxpkt, maxrxpkt */ + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) ) -+/* NAPI API changes in 2.6.24 break everything */ -+struct napi_struct { -+ /* used to look up the real NAPI polling routine */ -+ int (*poll)(struct napi_struct *, int); -+ struct net_device poll_dev; -+ int weight; -+}; -+#ifdef NAPI -+extern int __kc_adapter_clean(struct net_device *, int *); -+#if defined(DRIVER_IGB) || defined(DRIVER_IXGBE) -+#define netif_rx_complete(_netdev, napi) netif_rx_complete(&(napi)->poll_dev) -+#define netif_rx_schedule_prep(_netdev, napi) \ -+ (netif_running(_netdev) && netif_rx_schedule_prep(&(napi)->poll_dev)) -+#define netif_rx_schedule(_netdev, napi) netif_rx_schedule(&(napi)->poll_dev) -+#define __netif_rx_schedule(_netdev, napi) __netif_rx_schedule(&(napi)->poll_dev) -+#define napi_enable(napi) do { \ -+ /* abuse if_port as a counter */ \ -+ if (!adapter->netdev->if_port) { \ -+ netif_poll_enable(adapter->netdev); \ -+ } \ -+ ++adapter->netdev->if_port; \ -+ netif_poll_enable(&(napi)->poll_dev); \ -+ } while (0) -+#define napi_disable(_napi) do { \ -+ netif_poll_disable(&(_napi)->poll_dev); \ -+ --adapter->netdev->if_port; \ -+ if (!adapter->netdev->if_port) \ -+ netif_poll_disable(adapter->netdev); \ -+ } while (0) ++ if (ecmd->autoneg == AUTONEG_ENABLE) { ++ u32 bmcr, advert, tmp; + -+#define netif_napi_add(_netdev, _napi, _poll, _weight) \ -+ do { \ -+ struct napi_struct *__napi = (_napi); \ -+ __napi->poll_dev.poll = &(__kc_adapter_clean); \ -+ __napi->poll_dev.priv = (_napi); \ -+ __napi->poll_dev.weight = (_weight); \ -+ dev_hold(&__napi->poll_dev); \ -+ set_bit(__LINK_STATE_START, &__napi->poll_dev.state);\ -+ _netdev->poll = &(__kc_adapter_clean); \ -+ _netdev->weight = (_weight); \ -+ __napi->poll = &(_poll); \ -+ __napi->weight = (_weight); \ -+ set_bit(__LINK_STATE_RX_SCHED, &(_netdev)->state); \ -+ set_bit(__LINK_STATE_RX_SCHED, &__napi->poll_dev.state); \ -+ } while (0) -+#define netif_napi_del(_napi) \ -+ do { \ -+ WARN_ON(!test_bit(__LINK_STATE_RX_SCHED, &(_napi)->poll_dev.state)); \ -+ dev_put(&(_napi)->poll_dev); \ -+ memset(&(_napi)->poll_dev, 0, sizeof(struct napi_struct));\ -+ } while (0) -+#else /* DRIVER_IGB || DRIVER_IXGBE */ -+#define netif_rx_complete(netdev, napi) netif_rx_complete(netdev) -+#define netif_rx_schedule_prep(netdev, napi) netif_rx_schedule_prep(netdev) -+#define netif_rx_schedule(netdev, napi) netif_rx_schedule(netdev) -+#define __netif_rx_schedule(netdev, napi) __netif_rx_schedule(netdev) -+#define napi_enable(napi) netif_poll_enable(adapter->netdev) -+#define napi_disable(napi) netif_poll_disable(adapter->netdev) -+#define netif_napi_add(_netdev, _napi, _poll, _weight) \ -+ do { \ -+ struct napi_struct *__napi = (_napi); \ -+ _netdev->poll = &(__kc_adapter_clean); \ -+ _netdev->weight = (_weight); \ -+ __napi->poll = &(_poll); \ -+ __napi->weight = (_weight); \ -+ netif_poll_disable(_netdev); \ -+ } while (0) -+#define netif_napi_del(_a) do {} while (0) -+#endif /* DRIVER_IGB || DRIVER_IXGBE */ -+#else /* NAPI */ -+#define netif_napi_add(_netdev, _napi, _poll, _weight) \ -+ do { \ -+ struct napi_struct *__napi = _napi; \ -+ _netdev->poll = &(_poll); \ -+ _netdev->weight = (_weight); \ -+ __napi->poll = &(_poll); \ -+ __napi->weight = (_weight); \ -+ } while (0) -+#define netif_napi_del(_a) do {} while (0) -+#endif /* NAPI */ ++ if ((ecmd->advertising & (ADVERTISED_10baseT_Half | ++ ADVERTISED_10baseT_Full | ++ ADVERTISED_100baseT_Half | ++ ADVERTISED_100baseT_Full)) == 0) ++ return -EINVAL; ++ ++ /* advertise only what has been requested */ ++ advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); ++ tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4); ++ if (ADVERTISED_10baseT_Half) ++ tmp |= ADVERTISE_10HALF; ++ if (ADVERTISED_10baseT_Full) ++ tmp |= ADVERTISE_10FULL; ++ if (ADVERTISED_100baseT_Half) ++ tmp |= ADVERTISE_100HALF; ++ if (ADVERTISED_100baseT_Full) ++ tmp |= ADVERTISE_100FULL; ++ if (advert != tmp) { ++ mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp); ++ mii->advertising = tmp; ++ } + -+#undef dev_get_by_name -+#define dev_get_by_name(_a, _b) dev_get_by_name(_b) -+#define __netif_subqueue_stopped(_a, _b) netif_subqueue_stopped(_a, _b) -+#else -+#define netif_napi_del(_a) do {} while (0) -+#endif /* < 2.6.24 */ ++ /* turn on autonegotiation, and force a renegotiate */ ++ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); ++ bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); ++ mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr); + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24) ) -+#include -+#endif /* > 2.6.24 */ ++ mii->force_media = 0; ++ } else { ++ u32 bmcr, tmp; + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) ) -+#define PM_QOS_CPU_DMA_LATENCY 1 ++ /* turn off auto negotiation, set speed and duplexity */ ++ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); ++ tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX); ++ if (ecmd->speed == SPEED_100) ++ tmp |= BMCR_SPEED100; ++ if (ecmd->duplex == DUPLEX_FULL) { ++ tmp |= BMCR_FULLDPLX; ++ mii->full_duplex = 1; ++ } else ++ mii->full_duplex = 0; ++ if (bmcr != tmp) ++ mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp); + -+#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) ) -+#include -+#define PM_QOS_DEFAULT_VALUE INFINITE_LATENCY -+#define pm_qos_add_requirement(pm_qos_class, name, value) \ -+ set_acceptable_latency(name, value) -+#define pm_qos_remove_requirement(pm_qos_class, name) \ -+ remove_acceptable_latency(name) -+#define pm_qos_update_requirement(pm_qos_class, name, value) \ -+ modify_acceptable_latency(name, value) -+#else -+#define PM_QOS_DEFAULT_VALUE -1 -+#define pm_qos_add_requirement(pm_qos_class, name, value) -+#define pm_qos_remove_requirement(pm_qos_class, name) -+#define pm_qos_update_requirement(pm_qos_class, name, value) { \ -+ if (value != PM_QOS_DEFAULT_VALUE) { \ -+ printk(KERN_WARNING "%s: unable to set PM QoS requirement\n", \ -+ pci_name(adapter->pdev)); \ -+ } \ ++ mii->force_media = 1; ++ } ++ return 0; +} -+#endif /* > 2.6.18 */ + -+#define pci_enable_device_mem(pdev) pci_enable_device(pdev) ++int _kc_mii_link_ok (struct mii_if_info *mii) ++{ ++ /* first, a dummy read, needed to latch some MII phys */ ++ mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); ++ if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS) ++ return 1; ++ return 0; ++} + -+#endif /* < 2.6.25 */ ++int _kc_mii_nway_restart (struct mii_if_info *mii) ++{ ++ int bmcr; ++ int r = -EINVAL; + -+/*****************************************************************************/ -+#ifndef PCIE_LINK_STATE_L0S -+#define PCIE_LINK_STATE_L0S 1 -+#endif ++ /* if autoneg is off, it's an error */ ++ bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR); + -+/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) ) -+#ifndef netif_napi_del -+#define netif_napi_del(_a) do {} while (0) -+#ifdef NAPI -+#ifdef CONFIG_NETPOLL -+#undef netif_napi_del -+#define netif_napi_del(_a) list_del(&(_a)->dev_list); -+#endif -+#endif -+#endif /* netif_napi_del */ -+#ifndef pci_dma_mapping_error -+#define pci_dma_mapping_error _kc_pci_dma_mapping_error -+static inline int _kc_pci_dma_mapping_error(struct pci_dev *pdev, -+ dma_addr_t dma_addr) ++ if (bmcr & BMCR_ANENABLE) { ++ bmcr |= BMCR_ANRESTART; ++ mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr); ++ r = 0; ++ } ++ ++ return r; ++} ++ ++void _kc_mii_check_link (struct mii_if_info *mii) +{ -+ return dma_addr == 0; ++ int cur_link = mii_link_ok(mii); ++ int prev_link = netif_carrier_ok(mii->dev); ++ ++ if (cur_link && !prev_link) ++ netif_carrier_on(mii->dev); ++ else if (prev_link && !cur_link) ++ netif_carrier_off(mii->dev); +} -+#endif + -+#ifdef CONFIG_NETDEVICES_MULTIQUEUE -+#define HAVE_TX_MQ -+#endif ++int _kc_generic_mii_ioctl(struct mii_if_info *mii_if, ++ struct mii_ioctl_data *mii_data, int cmd, ++ unsigned int *duplex_chg_out) ++{ ++ int rc = 0; ++ unsigned int duplex_changed = 0; + -+#ifdef HAVE_TX_MQ -+extern void _kc_netif_tx_stop_all_queues(struct net_device *); -+extern void _kc_netif_tx_wake_all_queues(struct net_device *); -+extern void _kc_netif_tx_start_all_queues(struct net_device *); -+#define netif_tx_stop_all_queues(a) _kc_netif_tx_stop_all_queues(a) -+#define netif_tx_wake_all_queues(a) _kc_netif_tx_wake_all_queues(a) -+#define netif_tx_start_all_queues(a) _kc_netif_tx_start_all_queues(a) -+#else /* CONFIG_NETDEVICES_MULTIQUEUE */ -+#define netif_tx_stop_all_queues(a) netif_stop_queue(a) -+#define netif_tx_wake_all_queues(a) netif_wake_queue(a) -+#define netif_tx_start_all_queues(a) netif_start_queue(a) -+#endif /* CONFIG_NETDEVICES_MULTIQUEUE */ -+#ifndef NETIF_F_MULTI_QUEUE -+#define NETIF_F_MULTI_QUEUE 0 -+#define netif_is_multiqueue(a) 0 -+#define netif_stop_subqueue(a, b) -+#define netif_wake_subqueue(a, b) -+#define netif_start_subqueue(a, b) -+#endif /* NETIF_F_MULTI_QUEUE */ -+#else /* < 2.6.27 */ -+#define HAVE_TX_MQ -+#endif /* < 2.6.27 */ ++ if (duplex_chg_out) ++ *duplex_chg_out = 0; + -+#endif /* _KCOMPAT_H_ */ -Binary files vanilla/drivers/net/igb/kcompat.o and linux-i686-2.6.22/drivers/net/igb/kcompat.o differ -diff -Nru vanilla/drivers/net/igb/.kcompat.o.cmd linux-i686-2.6.22/drivers/net/igb/.kcompat.o.cmd ---- vanilla/drivers/net/igb/.kcompat.o.cmd 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/.kcompat.o.cmd 2009-07-16 19:53:45.000000000 -0400 -@@ -0,0 +1,554 @@ -+cmd_drivers/net/igb/kcompat.o := gcc -m32 -Wp,-MD,drivers/net/igb/.kcompat.o.d -nostdinc -isystem /usr/lib/gcc/i386-redhat-linux/4.1.2/include -D__KERNEL__ -Iinclude -include include/linux/autoconf.h -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Os -pipe -msoft-float -mregparm=3 -freg-struct-return -mpreferred-stack-boundary=2 -march=i686 -mtune=generic -ffreestanding -maccumulate-outgoing-args -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -Iinclude/asm-i386/mach-generic -Iinclude/asm-i386/mach-default -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -DMODULE -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(kcompat)" -D"KBUILD_MODNAME=KBUILD_STR(igb)" -c -o drivers/net/igb/.tmp_kcompat.o drivers/net/igb/kcompat.c -+ -+deps_drivers/net/igb/kcompat.o := \ -+ drivers/net/igb/kcompat.c \ -+ $(wildcard include/config/highmem.h) \ -+ $(wildcard include/config/space/len.h) \ -+ $(wildcard include/config/sysfs.h) \ -+ drivers/net/igb/igb.h \ -+ $(wildcard include/config/dca.h) \ -+ $(wildcard include/config/inet/lro.h) \ -+ $(wildcard include/config/igb/separate/tx/handler.h) \ -+ $(wildcard include/config/igb/disable/packet/split.h) \ -+ include/linux/pci.h \ -+ $(wildcard include/config/pci/msi.h) \ -+ $(wildcard include/config/pci.h) \ -+ $(wildcard include/config/ht/irq.h) \ -+ $(wildcard include/config/pci/domains.h) \ -+ include/linux/pci_regs.h \ -+ include/linux/mod_devicetable.h \ -+ include/linux/types.h \ -+ $(wildcard include/config/uid16.h) \ -+ $(wildcard include/config/lbd.h) \ -+ $(wildcard include/config/lsf.h) \ -+ $(wildcard include/config/resources/64bit.h) \ -+ include/linux/posix_types.h \ -+ include/linux/stddef.h \ -+ include/linux/compiler.h \ -+ $(wildcard include/config/enable/must/check.h) \ -+ include/linux/compiler-gcc4.h \ -+ $(wildcard include/config/forced/inlining.h) \ -+ include/linux/compiler-gcc.h \ -+ include/asm/posix_types.h \ -+ include/asm/types.h \ -+ $(wildcard include/config/highmem64g.h) \ -+ include/linux/ioport.h \ -+ include/linux/list.h \ -+ $(wildcard include/config/debug/list.h) \ -+ include/linux/poison.h \ -+ include/linux/prefetch.h \ -+ include/asm/processor.h \ -+ $(wildcard include/config/smp.h) \ -+ $(wildcard include/config/x86/ht.h) \ -+ $(wildcard include/config/paravirt.h) \ -+ $(wildcard include/config/mk8.h) \ -+ $(wildcard include/config/mk7.h) \ -+ include/asm/vm86.h \ -+ $(wildcard include/config/vm86.h) \ -+ include/asm/ptrace.h \ -+ include/asm/ptrace-abi.h \ -+ include/asm/segment.h \ -+ include/asm/math_emu.h \ -+ include/asm/sigcontext.h \ -+ include/asm/page.h \ -+ $(wildcard include/config/x86/use/3dnow.h) \ -+ $(wildcard include/config/x86/pae.h) \ -+ $(wildcard include/config/hugetlb/page.h) \ -+ $(wildcard include/config/highmem4g.h) \ -+ $(wildcard include/config/page/offset.h) \ -+ $(wildcard include/config/flatmem.h) \ -+ include/asm-generic/pgtable-nopmd.h \ -+ include/asm-generic/pgtable-nopud.h \ -+ include/asm-generic/memory_model.h \ -+ $(wildcard include/config/discontigmem.h) \ -+ $(wildcard include/config/sparsemem.h) \ -+ $(wildcard include/config/out/of/line/pfn/to/page.h) \ -+ include/asm-generic/page.h \ -+ include/asm/cpufeature.h \ -+ include/linux/bitops.h \ -+ include/asm/bitops.h \ -+ include/asm/alternative.h \ -+ include/asm-generic/bitops/sched.h \ -+ include/asm-generic/bitops/hweight.h \ -+ include/asm-generic/bitops/fls64.h \ -+ include/asm-generic/bitops/ext2-non-atomic.h \ -+ include/asm-generic/bitops/le.h \ -+ include/asm/byteorder.h \ -+ $(wildcard include/config/x86/bswap.h) \ -+ include/linux/byteorder/little_endian.h \ -+ include/linux/byteorder/swab.h \ -+ include/linux/byteorder/generic.h \ -+ include/asm-generic/bitops/minix.h \ -+ include/asm/required-features.h \ -+ $(wildcard include/config/x86/minimum/cpu.h) \ -+ $(wildcard include/config/x86/cmov.h) \ -+ $(wildcard include/config/x86/cmpxchg64.h) \ -+ include/asm/msr.h \ -+ include/asm/msr-index.h \ -+ include/asm/errno.h \ -+ include/asm-generic/errno.h \ -+ include/asm-generic/errno-base.h \ -+ include/linux/errno.h \ -+ include/asm/system.h \ -+ $(wildcard include/config/x86/oostore.h) \ -+ include/linux/kernel.h \ -+ $(wildcard include/config/preempt/voluntary.h) \ -+ $(wildcard include/config/debug/spinlock/sleep.h) \ -+ $(wildcard include/config/printk.h) \ -+ $(wildcard include/config/numa.h) \ -+ /usr/lib/gcc/i386-redhat-linux/4.1.2/include/stdarg.h \ -+ include/linux/linkage.h \ -+ include/asm/linkage.h \ -+ $(wildcard include/config/x86/alignment/16.h) \ -+ include/linux/log2.h \ -+ $(wildcard include/config/arch/has/ilog2/u32.h) \ -+ $(wildcard include/config/arch/has/ilog2/u64.h) \ -+ include/asm/bug.h \ -+ $(wildcard include/config/bug.h) \ -+ $(wildcard include/config/debug/bugverbose.h) \ -+ include/asm-generic/bug.h \ -+ $(wildcard include/config/generic/bug.h) \ -+ include/asm/cmpxchg.h \ -+ $(wildcard include/config/x86/cmpxchg.h) \ -+ include/linux/irqflags.h \ -+ $(wildcard include/config/trace/irqflags.h) \ -+ $(wildcard include/config/trace/irqflags/support.h) \ -+ $(wildcard include/config/x86.h) \ -+ include/asm/irqflags.h \ -+ include/asm/processor-flags.h \ -+ include/linux/cache.h \ -+ include/asm/cache.h \ -+ $(wildcard include/config/x86/l1/cache/shift.h) \ -+ include/linux/threads.h \ -+ $(wildcard include/config/nr/cpus.h) \ -+ $(wildcard include/config/base/small.h) \ -+ include/asm/percpu.h \ -+ include/linux/cpumask.h \ -+ $(wildcard include/config/hotplug/cpu.h) \ -+ include/linux/bitmap.h \ -+ include/linux/string.h \ -+ include/asm/string.h \ -+ include/linux/init.h \ -+ $(wildcard include/config/modules.h) \ -+ $(wildcard include/config/hotplug.h) \ -+ $(wildcard include/config/memory/hotplug.h) \ -+ $(wildcard include/config/acpi/hotplug/memory.h) \ -+ include/asm/atomic.h \ -+ $(wildcard include/config/m386.h) \ -+ include/asm-generic/atomic.h \ -+ include/linux/device.h \ -+ $(wildcard include/config/debug/devres.h) \ -+ include/linux/kobject.h \ -+ include/linux/sysfs.h \ -+ include/linux/spinlock.h \ -+ $(wildcard include/config/debug/spinlock.h) \ -+ $(wildcard include/config/preempt.h) \ -+ $(wildcard include/config/debug/lock/alloc.h) \ -+ include/linux/preempt.h \ -+ $(wildcard include/config/debug/preempt.h) \ -+ include/linux/thread_info.h \ -+ include/asm/thread_info.h \ -+ $(wildcard include/config/4kstacks.h) \ -+ $(wildcard include/config/debug/stack/usage.h) \ -+ include/linux/stringify.h \ -+ include/linux/bottom_half.h \ -+ include/linux/spinlock_types.h \ -+ include/linux/lockdep.h \ -+ $(wildcard include/config/lockdep.h) \ -+ $(wildcard include/config/generic/hardirqs.h) \ -+ $(wildcard include/config/prove/locking.h) \ -+ include/asm/spinlock_types.h \ -+ include/asm/spinlock.h \ -+ $(wildcard include/config/x86/ppro/fence.h) \ -+ include/asm/rwlock.h \ -+ include/linux/spinlock_api_smp.h \ -+ include/linux/kref.h \ -+ include/linux/wait.h \ -+ include/asm/current.h \ -+ include/linux/klist.h \ -+ include/linux/completion.h \ -+ include/linux/module.h \ -+ $(wildcard include/config/modversions.h) \ -+ $(wildcard include/config/unused/symbols.h) \ -+ $(wildcard include/config/module/unload.h) \ -+ $(wildcard include/config/kallsyms.h) \ -+ include/linux/stat.h \ -+ include/asm/stat.h \ -+ include/linux/time.h \ -+ include/linux/seqlock.h \ -+ include/linux/vs_time.h \ -+ $(wildcard include/config/vserver/vtime.h) \ -+ include/linux/kmod.h \ -+ $(wildcard include/config/kmod.h) \ -+ include/linux/elf.h \ -+ include/linux/auxvec.h \ -+ include/asm/auxvec.h \ -+ include/linux/elf-em.h \ -+ include/asm/elf.h \ -+ include/asm/user.h \ -+ include/asm/desc.h \ -+ include/asm/ldt.h \ -+ include/linux/smp.h \ -+ include/asm/smp.h \ -+ $(wildcard include/config/x86/local/apic.h) \ -+ $(wildcard include/config/x86/io/apic.h) \ -+ include/asm/mpspec.h \ -+ $(wildcard include/config/acpi.h) \ -+ include/asm/mpspec_def.h \ -+ include/asm-i386/mach-generic/mach_mpspec.h \ -+ include/asm/apic.h \ -+ $(wildcard include/config/x86/good/apic.h) \ -+ include/linux/pm.h \ -+ $(wildcard include/config/pm.h) \ -+ include/linux/delay.h \ -+ include/asm/delay.h \ -+ include/asm/fixmap.h \ -+ $(wildcard include/config/x86/visws/apic.h) \ -+ $(wildcard include/config/x86/f00f/bug.h) \ -+ $(wildcard include/config/x86/cyclone/timer.h) \ -+ $(wildcard include/config/pci/mmconfig.h) \ -+ include/asm/acpi.h \ -+ $(wildcard include/config/acpi/sleep.h) \ -+ include/acpi/pdc_intel.h \ -+ include/asm/apicdef.h \ -+ include/asm/kmap_types.h \ -+ $(wildcard include/config/debug/highmem.h) \ -+ include/asm/io_apic.h \ -+ include/asm-i386/mach-generic/mach_apicdef.h \ -+ include/asm/genapic.h \ -+ include/linux/percpu.h \ -+ include/linux/slab.h \ -+ $(wildcard include/config/slab/debug.h) \ -+ $(wildcard include/config/slab.h) \ -+ $(wildcard include/config/slub.h) \ -+ $(wildcard include/config/debug/slab.h) \ -+ include/linux/gfp.h \ -+ $(wildcard include/config/zone/dma.h) \ -+ $(wildcard include/config/zone/dma32.h) \ -+ include/linux/mmzone.h \ -+ $(wildcard include/config/force/max/zoneorder.h) \ -+ $(wildcard include/config/arch/populates/node/map.h) \ -+ $(wildcard include/config/flat/node/mem/map.h) \ -+ $(wildcard include/config/have/memory/present.h) \ -+ $(wildcard include/config/need/node/memmap/size.h) \ -+ $(wildcard include/config/need/multiple/nodes.h) \ -+ $(wildcard include/config/have/arch/early/pfn/to/nid.h) \ -+ $(wildcard include/config/sparsemem/extreme.h) \ -+ $(wildcard include/config/nodes/span/other/nodes.h) \ -+ $(wildcard include/config/holes/in/zone.h) \ -+ include/linux/numa.h \ -+ $(wildcard include/config/nodes/shift.h) \ -+ include/linux/nodemask.h \ -+ include/linux/memory_hotplug.h \ -+ $(wildcard include/config/have/arch/nodedata/extension.h) \ -+ include/linux/notifier.h \ -+ include/linux/mutex.h \ -+ $(wildcard include/config/debug/mutexes.h) \ -+ $(wildcard include/config/chopstix.h) \ -+ include/linux/rwsem.h \ -+ $(wildcard include/config/rwsem/generic/spinlock.h) \ -+ include/asm/rwsem.h \ -+ include/linux/srcu.h \ -+ include/linux/topology.h \ -+ $(wildcard include/config/sched/smt.h) \ -+ $(wildcard include/config/sched/mc.h) \ -+ include/asm/topology.h \ -+ include/asm-generic/topology.h \ -+ include/linux/slab_def.h \ -+ include/linux/kmalloc_sizes.h \ -+ include/asm/mmu.h \ -+ include/asm/semaphore.h \ -+ include/linux/moduleparam.h \ -+ include/asm/local.h \ -+ include/asm/module.h \ -+ $(wildcard include/config/m486.h) \ -+ $(wildcard include/config/m586.h) \ -+ $(wildcard include/config/m586tsc.h) \ -+ $(wildcard include/config/m586mmx.h) \ -+ $(wildcard include/config/mcore2.h) \ -+ $(wildcard include/config/m686.h) \ -+ $(wildcard include/config/mpentiumii.h) \ -+ $(wildcard include/config/mpentiumiii.h) \ -+ $(wildcard include/config/mpentiumm.h) \ -+ $(wildcard include/config/mpentium4.h) \ -+ $(wildcard include/config/mk6.h) \ -+ $(wildcard include/config/x86/elan.h) \ -+ $(wildcard include/config/mcrusoe.h) \ -+ $(wildcard include/config/mefficeon.h) \ -+ $(wildcard include/config/mwinchipc6.h) \ -+ $(wildcard include/config/mwinchip2.h) \ -+ $(wildcard include/config/mwinchip3d.h) \ -+ $(wildcard include/config/mcyrixiii.h) \ -+ $(wildcard include/config/mviac3/2.h) \ -+ $(wildcard include/config/mviac7.h) \ -+ $(wildcard include/config/mgeodegx1.h) \ -+ $(wildcard include/config/mgeode/lx.h) \ -+ include/asm/device.h \ -+ include/linux/pci_ids.h \ -+ include/linux/dmapool.h \ -+ include/asm/io.h \ -+ $(wildcard include/config/x86/numaq.h) \ -+ include/asm-generic/iomap.h \ -+ include/linux/vmalloc.h \ -+ include/asm/scatterlist.h \ -+ include/asm/pci.h \ -+ include/linux/mm.h \ -+ $(wildcard include/config/sysctl.h) \ -+ $(wildcard include/config/mmu.h) \ -+ $(wildcard include/config/stack/growsup.h) \ -+ $(wildcard include/config/debug/vm.h) \ -+ $(wildcard include/config/shmem.h) \ -+ $(wildcard include/config/split/ptlock/cpus.h) \ -+ $(wildcard include/config/ia64.h) \ -+ $(wildcard include/config/proc/fs.h) \ -+ $(wildcard include/config/debug/pagealloc.h) \ -+ include/linux/capability.h \ -+ include/linux/rbtree.h \ -+ include/linux/prio_tree.h \ -+ include/linux/fs.h \ -+ $(wildcard include/config/dnotify.h) \ -+ $(wildcard include/config/vserver/cowbl.h) \ -+ $(wildcard include/config/quota.h) \ -+ $(wildcard include/config/inotify.h) \ -+ $(wildcard include/config/security.h) \ -+ $(wildcard include/config/epoll.h) \ -+ $(wildcard include/config/auditsyscall.h) \ -+ $(wildcard include/config/block.h) \ -+ $(wildcard include/config/fs/xip.h) \ -+ $(wildcard include/config/migration.h) \ -+ include/linux/limits.h \ -+ include/linux/ioctl.h \ -+ include/asm/ioctl.h \ -+ include/asm-generic/ioctl.h \ -+ include/linux/kdev_t.h \ -+ include/linux/dcache.h \ -+ $(wildcard include/config/profiling.h) \ -+ include/linux/rcupdate.h \ -+ include/linux/namei.h \ -+ include/linux/radix-tree.h \ -+ include/linux/pid.h \ -+ include/linux/quota.h \ -+ include/linux/dqblk_xfs.h \ -+ include/linux/dqblk_v1.h \ -+ include/linux/dqblk_v2.h \ -+ include/linux/nfs_fs_i.h \ -+ include/linux/nfs.h \ -+ include/linux/sunrpc/msg_prot.h \ -+ include/linux/fcntl.h \ -+ include/asm/fcntl.h \ -+ include/asm-generic/fcntl.h \ -+ $(wildcard include/config/64bit.h) \ -+ include/linux/err.h \ -+ include/linux/debug_locks.h \ -+ $(wildcard include/config/debug/locking/api/selftests.h) \ -+ include/linux/backing-dev.h \ -+ include/linux/mm_types.h \ -+ include/asm/pgtable.h \ -+ $(wildcard include/config/highpte.h) \ -+ include/asm/paravirt.h \ -+ include/asm/pgtable-2level-defs.h \ -+ include/asm/pgtable-2level.h \ -+ include/asm-generic/pgtable.h \ -+ include/linux/page-flags.h \ -+ $(wildcard include/config/s390.h) \ -+ $(wildcard include/config/swap.h) \ -+ include/linux/vmstat.h \ -+ $(wildcard include/config/vm/event/counters.h) \ -+ include/asm-generic/pci-dma-compat.h \ -+ include/linux/dma-mapping.h \ -+ include/asm/dma-mapping.h \ -+ include/asm-generic/pci.h \ -+ include/linux/netdevice.h \ -+ $(wildcard include/config/ax25.h) \ -+ $(wildcard include/config/tr.h) \ -+ $(wildcard include/config/net/ipip.h) \ -+ $(wildcard include/config/net/ipgre.h) \ -+ $(wildcard include/config/ipv6/sit.h) \ -+ $(wildcard include/config/ipv6/tunnel.h) \ -+ $(wildcard include/config/wireless/ext.h) \ -+ $(wildcard include/config/netpoll.h) \ -+ $(wildcard include/config/net/poll/controller.h) \ -+ $(wildcard include/config/netpoll/trap.h) \ -+ $(wildcard include/config/net/dma.h) \ -+ include/linux/if.h \ -+ include/linux/socket.h \ -+ $(wildcard include/config/compat.h) \ -+ include/asm/socket.h \ -+ include/asm/sockios.h \ -+ include/linux/sockios.h \ -+ include/linux/uio.h \ -+ include/linux/hdlc/ioctl.h \ -+ include/linux/if_ether.h \ -+ include/linux/skbuff.h \ -+ $(wildcard include/config/nf/conntrack.h) \ -+ $(wildcard include/config/bridge/netfilter.h) \ -+ $(wildcard include/config/vlan/8021q.h) \ -+ $(wildcard include/config/net/sched.h) \ -+ $(wildcard include/config/net/cls/act.h) \ -+ $(wildcard include/config/network/secmark.h) \ -+ include/linux/net.h \ -+ include/linux/random.h \ -+ include/linux/sysctl.h \ -+ $(wildcard include/config/icmp/ipod.h) \ -+ $(wildcard include/config/web100/net100.h) \ -+ $(wildcard include/config/web100/stats.h) \ -+ include/linux/textsearch.h \ -+ include/net/checksum.h \ -+ include/asm/uaccess.h \ -+ $(wildcard include/config/x86/intel/usercopy.h) \ -+ $(wildcard include/config/x86/wp/works/ok.h) \ -+ include/asm/checksum.h \ -+ include/linux/in6.h \ -+ include/linux/dmaengine.h \ -+ $(wildcard include/config/dma/engine.h) \ -+ include/linux/hrtimer.h \ -+ $(wildcard include/config/high/res/timers.h) \ -+ $(wildcard include/config/timer/stats.h) \ -+ include/linux/ktime.h \ -+ $(wildcard include/config/ktime/scalar.h) \ -+ include/linux/jiffies.h \ -+ include/linux/calc64.h \ -+ include/asm/div64.h \ -+ include/linux/timex.h \ -+ $(wildcard include/config/time/interpolation.h) \ -+ $(wildcard include/config/no/hz.h) \ -+ include/asm/param.h \ -+ $(wildcard include/config/hz.h) \ -+ include/asm/timex.h \ -+ include/asm/tsc.h \ -+ $(wildcard include/config/x86/tsc.h) \ -+ $(wildcard include/config/x86/generic.h) \ -+ include/linux/if_packet.h \ -+ include/linux/timer.h \ -+ include/linux/interrupt.h \ -+ $(wildcard include/config/generic/irq/probe.h) \ -+ include/linux/irqreturn.h \ -+ include/linux/hardirq.h \ -+ $(wildcard include/config/preempt/bkl.h) \ -+ $(wildcard include/config/virt/cpu/accounting.h) \ -+ include/linux/smp_lock.h \ -+ $(wildcard include/config/lock/kernel.h) \ -+ include/linux/sched.h \ -+ $(wildcard include/config/detect/softlockup.h) \ -+ $(wildcard include/config/keys.h) \ -+ $(wildcard include/config/bsd/process/acct.h) \ -+ $(wildcard include/config/taskstats.h) \ -+ $(wildcard include/config/inotify/user.h) \ -+ $(wildcard include/config/schedstats.h) \ -+ $(wildcard include/config/task/delay/acct.h) \ -+ $(wildcard include/config/blk/dev/io/trace.h) \ -+ $(wildcard include/config/cc/stackprotector.h) \ -+ $(wildcard include/config/sysvipc.h) \ -+ $(wildcard include/config/rt/mutexes.h) \ -+ $(wildcard include/config/task/xacct.h) \ -+ $(wildcard include/config/cpusets.h) \ -+ $(wildcard include/config/fault/injection.h) \ -+ include/asm/cputime.h \ -+ include/asm-generic/cputime.h \ -+ include/linux/sem.h \ -+ include/linux/ipc.h \ -+ $(wildcard include/config/ipc/ns.h) \ -+ include/asm/ipcbuf.h \ -+ include/asm/sembuf.h \ -+ include/linux/signal.h \ -+ include/asm/signal.h \ -+ include/asm-generic/signal.h \ -+ include/asm/siginfo.h \ -+ include/asm-generic/siginfo.h \ -+ include/linux/securebits.h \ -+ include/linux/fs_struct.h \ -+ include/linux/seccomp.h \ -+ $(wildcard include/config/seccomp.h) \ -+ include/linux/futex.h \ -+ $(wildcard include/config/futex.h) \ -+ include/linux/rtmutex.h \ -+ $(wildcard include/config/debug/rt/mutexes.h) \ -+ include/linux/plist.h \ -+ $(wildcard include/config/debug/pi/list.h) \ -+ include/linux/param.h \ -+ include/linux/resource.h \ -+ include/asm/resource.h \ -+ include/asm-generic/resource.h \ -+ include/linux/task_io_accounting.h \ -+ $(wildcard include/config/task/io/accounting.h) \ -+ include/linux/aio.h \ -+ include/linux/workqueue.h \ -+ include/linux/aio_abi.h \ -+ include/asm/hardirq.h \ -+ include/linux/irq.h \ -+ $(wildcard include/config/irq/per/cpu.h) \ -+ $(wildcard include/config/irq/release/method.h) \ -+ $(wildcard include/config/generic/pending/irq.h) \ -+ $(wildcard include/config/irqbalance.h) \ -+ $(wildcard include/config/auto/irq/affinity.h) \ -+ $(wildcard include/config/generic/hardirqs/no//do/irq.h) \ -+ include/asm/irq.h \ -+ include/asm-i386/mach-default/irq_vectors.h \ -+ include/asm-i386/mach-default/irq_vectors_limits.h \ -+ include/asm/irq_regs.h \ -+ include/asm/hw_irq.h \ -+ include/linux/profile.h \ -+ include/asm/sections.h \ -+ include/asm-generic/sections.h \ -+ include/linux/irq_cpustat.h \ -+ include/linux/ethtool.h \ -+ drivers/net/igb/kcompat.h \ -+ $(wildcard include/config/e1000/napi.h) \ -+ $(wildcard include/config/e1000e/napi.h) \ -+ $(wildcard include/config/ixgb/napi.h) \ -+ $(wildcard include/config/e1000/disable/packet/split.h) \ -+ $(wildcard include/config/netdevices/multiqueue.h) \ -+ include/linux/version.h \ -+ include/linux/etherdevice.h \ -+ include/linux/in.h \ -+ include/linux/ip.h \ -+ include/linux/udp.h \ -+ include/net/inet_sock.h \ -+ $(wildcard include/config/ipv6.h) \ -+ include/linux/jhash.h \ -+ include/net/flow.h \ -+ $(wildcard include/config/ipv6/mip6.h) \ -+ include/net/sock.h \ -+ $(wildcard include/config/security/network.h) \ -+ include/linux/security.h \ -+ $(wildcard include/config/security/network/xfrm.h) \ -+ include/linux/binfmts.h \ -+ include/linux/shm.h \ -+ include/asm/shmparam.h \ -+ include/asm/shmbuf.h \ -+ include/linux/msg.h \ -+ include/asm/msgbuf.h \ -+ include/linux/key.h \ -+ include/linux/xfrm.h \ -+ include/linux/filter.h \ -+ include/net/dst.h \ -+ $(wildcard include/config/net/cls/route.h) \ -+ $(wildcard include/config/xfrm.h) \ -+ include/linux/rtnetlink.h \ -+ include/linux/netlink.h \ -+ include/linux/if_link.h \ -+ include/linux/if_addr.h \ -+ include/linux/neighbour.h \ -+ include/net/neighbour.h \ -+ include/linux/seq_file.h \ -+ include/net/rtnetlink.h \ -+ include/net/netlink.h \ -+ include/net/request_sock.h \ -+ include/linux/mii.h \ -+ include/linux/latency.h \ -+ drivers/net/igb/e1000_api.h \ -+ drivers/net/igb/e1000_hw.h \ -+ drivers/net/igb/e1000_osdep.h \ -+ drivers/net/igb/e1000_regs.h \ -+ drivers/net/igb/e1000_defines.h \ -+ $(wildcard include/config/res.h) \ -+ $(wildcard include/config/fault.h) \ -+ drivers/net/igb/e1000_mac.h \ -+ drivers/net/igb/e1000_phy.h \ -+ drivers/net/igb/e1000_nvm.h \ -+ drivers/net/igb/e1000_manage.h \ -+ drivers/net/igb/e1000_82575.h \ -+ -+drivers/net/igb/kcompat.o: $(deps_drivers/net/igb/kcompat.o) -+ -+$(deps_drivers/net/igb/kcompat.o): -diff -Nru vanilla/drivers/net/igb/Makefile linux-i686-2.6.22/drivers/net/igb/Makefile ---- vanilla/drivers/net/igb/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/Makefile 2009-07-16 19:53:34.000000000 -0400 -@@ -0,0 +1,32 @@ -+################################################################################ -+# -+# Intel(R) Gigabit Ethernet Linux driver -+# Copyright(c) 2007-2008 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: -+# e1000-devel Mailing List -+# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -+# -+################################################################################ ++ mii_data->phy_id &= mii_if->phy_id_mask; ++ mii_data->reg_num &= mii_if->reg_num_mask; + -+########################################################################### ++ switch(cmd) { ++ case SIOCDEVPRIVATE: /* binary compat, remove in 2.5 */ ++ case SIOCGMIIPHY: ++ mii_data->phy_id = mii_if->phy_id; ++ /* fall through */ + -+obj-$(CONFIG_IGB) += igb.o ++ case SIOCDEVPRIVATE + 1:/* binary compat, remove in 2.5 */ ++ case SIOCGMIIREG: ++ mii_data->val_out = ++ mii_if->mdio_read(mii_if->dev, mii_data->phy_id, ++ mii_data->reg_num); ++ break; + -+igb-objs := e1000_82575.o igb_main.o e1000_mac.o e1000_nvm.o e1000_phy.o e1000_manage.o igb_param.o igb_ethtool.o kcompat.o e1000_api.o -diff -Nru vanilla/drivers/net/igb/Makefile~ linux-i686-2.6.22/drivers/net/igb/Makefile~ ---- vanilla/drivers/net/igb/Makefile~ 1969-12-31 19:00:00.000000000 -0500 -+++ linux-i686-2.6.22/drivers/net/igb/Makefile~ 2009-07-16 19:29:30.000000000 -0400 -@@ -0,0 +1,32 @@ -+################################################################################ -+# -+# Intel(R) Gigabit Ethernet Linux driver -+# Copyright(c) 2007-2008 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: -+# e1000-devel Mailing List -+# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -+# -+################################################################################ ++ case SIOCDEVPRIVATE + 2:/* binary compat, remove in 2.5 */ ++ case SIOCSMIIREG: { ++ u16 val = mii_data->val_in; + -+########################################################################### ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; + -+obj-$(CONFIG_IGB) += igb.o ++ if (mii_data->phy_id == mii_if->phy_id) { ++ switch(mii_data->reg_num) { ++ case MII_BMCR: { ++ unsigned int new_duplex = 0; ++ if (val & (BMCR_RESET|BMCR_ANENABLE)) ++ mii_if->force_media = 0; ++ else ++ mii_if->force_media = 1; ++ if (mii_if->force_media && ++ (val & BMCR_FULLDPLX)) ++ new_duplex = 1; ++ if (mii_if->full_duplex != new_duplex) { ++ duplex_changed = 1; ++ mii_if->full_duplex = new_duplex; ++ } ++ break; ++ } ++ case MII_ADVERTISE: ++ mii_if->advertising = val; ++ break; ++ default: ++ /* do nothing */ ++ break; ++ } ++ } ++ ++ mii_if->mdio_write(mii_if->dev, mii_data->phy_id, ++ mii_data->reg_num, val); ++ break; ++ } ++ ++ default: ++ rc = -EOPNOTSUPP; ++ break; ++ } ++ ++ if ((rc == 0) && (duplex_chg_out) && (duplex_changed)) ++ *duplex_chg_out = 1; ++ ++ return rc; ++} + -+igb-objs := e1000_82575.o igb_main.o e1000_mac.0 e1000_nvm.o e1000_phy.o e1000_manage.o igb_param.o igb_ethtool.o kcompat.o e1000_api.o ---- linux-2.6.22-710/drivers/net/Kconfig 2009-07-16 19:36:18.000000000 -0400 -+++ linux-i686-2.6.22/drivers/net/Kconfig 2009-07-16 19:56:54.000000000 -0400 -@@ -1905,6 +1905,12 @@ - - if NETDEV_1000 - -+config IGB -+ tristate "Intel(R) IGB Ethernet support" -+ depends on PCI -+ ---help--- -+ Marc's port of the IGB driver. -+ - config ACENIC - tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support" - depends on PCI ---- linux-a/drivers/net/Makefile 2009-07-17 00:29:08.000000000 -0400 -+++ linux-b/drivers/net/Makefile 2009-07-17 00:29:37.000000000 -0400 -@@ -2,6 +2,7 @@ - # Makefile for the Linux network (ethercard) device drivers. - # - obj-m += vnet_tun.o -+obj-$(CONFIG_IGB) += igb/ - obj-$(CONFIG_E1000) += e1000/ - obj-$(CONFIG_E1000E) += e1000e/ - obj-$(CONFIG_IBM_EMAC) += ibm_emac/ - -- 2.43.0