From: Daniel Hokka Zakrisson Date: Thu, 27 Aug 2009 22:00:15 +0000 (+0000) Subject: New e1000e driver. X-Git-Tag: linux-2.6-22-43~13 X-Git-Url: http://git.onelab.eu/?p=linux-2.6.git;a=commitdiff_plain;h=2bdc896bb4e86f3b15e08df815485e999d353f0d New e1000e driver. --- diff --git a/linux-2.6-010-e1000e.patch b/linux-2.6-010-e1000e.patch index b5e3baedd..6cbe47ad4 100644 --- a/linux-2.6-010-e1000e.patch +++ b/linux-2.6-010-e1000e.patch @@ -1,11 +1,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10/drivers/net/e1000e/e1000_80003es2lan.c --- linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000_80003es2lan.c 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,1545 @@ ++++ linux-2.6.22-10/drivers/net/e1000e/e1000_80003es2lan.c 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,1474 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -30,18 +30,18 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + +*******************************************************************************/ + -+/* e1000_80003es2lan ++/* ++ * 80003ES2LAN Gigabit Ethernet Controller (Copper) ++ * 80003ES2LAN Gigabit Ethernet Controller (Serdes) + */ + -+#include "e1000_hw.h" ++#include "e1000.h" + +static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw); +static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw); +static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw); +static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw); -+static s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw); +static void e1000_release_phy_80003es2lan(struct e1000_hw *hw); -+static void e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw); +static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw); +static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw); +static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, @@ -65,8 +65,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 +static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex); +static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw); +static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw); -+static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 *data); -+static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 data); ++static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, ++ u16 *data); ++static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, ++ u16 data); +static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw); +static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw); +static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask); @@ -87,16 +89,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 +/** + * e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs. + * @hw: pointer to the HW structure -+ * -+ * This is a function pointer entry point called by the api module. + **/ +static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_init_phy_params_80003es2lan"); -+ + if (hw->phy.media_type != e1000_media_type_copper) { + phy->type = e1000_phy_none; + goto out; @@ -112,13 +110,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + + phy->ops.acquire = e1000_acquire_phy_80003es2lan; + phy->ops.check_polarity = e1000_check_polarity_m88; -+ phy->ops.check_reset_block = e1000_check_reset_block_generic; -+ phy->ops.commit = e1000_phy_sw_reset_generic; ++ phy->ops.check_reset_block = e1000e_check_reset_block_generic; ++ phy->ops.commit = e1000e_phy_sw_reset; + phy->ops.get_cfg_done = e1000_get_cfg_done_80003es2lan; -+ phy->ops.get_info = e1000_get_phy_info_m88; ++ phy->ops.get_info = e1000e_get_phy_info_m88; + phy->ops.release = e1000_release_phy_80003es2lan; -+ phy->ops.reset = e1000_phy_hw_reset_generic; -+ phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic; ++ phy->ops.reset = e1000e_phy_hw_reset_generic; ++ phy->ops.set_d3_lplu_state = e1000e_set_d3_lplu_state; + + phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_80003es2lan; + phy->ops.get_cable_length = e1000_get_cable_length_80003es2lan; @@ -128,7 +126,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + phy->ops.cfg_on_link_up = e1000_cfg_on_link_up_80003es2lan; + + /* This can only be done after all function pointers are setup. */ -+ ret_val = e1000_get_phy_id(hw); ++ ret_val = e1000e_get_phy_id(hw); + + /* Verify phy id */ + if (phy->id != GG82563_E_PHY_ID) { @@ -143,17 +141,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 +/** + * e1000_init_nvm_params_80003es2lan - Init ESB2 NVM func ptrs. + * @hw: pointer to the HW structure -+ * -+ * This is a function pointer entry point called by the api module. + **/ +static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw) +{ + struct e1000_nvm_info *nvm = &hw->nvm; -+ u32 eecd = E1000_READ_REG(hw, E1000_EECD); ++ u32 eecd = er32(EECD); + u16 size; + -+ DEBUGFUNC("e1000_init_nvm_params_80003es2lan"); -+ + nvm->opcode_bits = 8; + nvm->delay_usec = 1; + switch (nvm->override) { @@ -189,11 +183,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + + /* Function Pointers */ + nvm->ops.acquire = e1000_acquire_nvm_80003es2lan; -+ nvm->ops.read = e1000_read_nvm_eerd; ++ nvm->ops.read = e1000e_read_nvm_eerd; + nvm->ops.release = e1000_release_nvm_80003es2lan; -+ nvm->ops.update = e1000_update_nvm_checksum_generic; -+ nvm->ops.valid_led_default = e1000_valid_led_default_generic; -+ nvm->ops.validate = e1000_validate_nvm_checksum_generic; ++ nvm->ops.update = e1000e_update_nvm_checksum_generic; ++ nvm->ops.valid_led_default = e1000e_valid_led_default; ++ nvm->ops.validate = e1000e_validate_nvm_checksum_generic; + nvm->ops.write = e1000_write_nvm_80003es2lan; + + return E1000_SUCCESS; @@ -202,16 +196,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 +/** + * e1000_init_mac_params_80003es2lan - Init ESB2 MAC func ptrs. + * @hw: pointer to the HW structure -+ * -+ * This is a function pointer entry point called by the api module. + **/ +static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_init_mac_params_80003es2lan"); -+ + /* Set media type */ + switch (hw->device_id) { + case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: @@ -230,34 +220,34 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + mac->asf_firmware_present = true; + /* Set if manageability features are enabled. */ + mac->arc_subsystem_valid = -+ (E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK) ++ (er32(FWSM) & E1000_FWSM_MODE_MASK) + ? true : false; + + /* Function pointers */ + + /* bus type/speed/width */ -+ mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic; ++ mac->ops.get_bus_info = e1000e_get_bus_info_pcie; + /* reset */ + mac->ops.reset_hw = e1000_reset_hw_80003es2lan; + /* hw initialization */ + mac->ops.init_hw = e1000_init_hw_80003es2lan; + /* link setup */ -+ mac->ops.setup_link = e1000_setup_link_generic; ++ mac->ops.setup_link = e1000e_setup_link; + /* physical interface link setup */ + mac->ops.setup_physical_interface = + (hw->phy.media_type == e1000_media_type_copper) + ? e1000_setup_copper_link_80003es2lan -+ : e1000_setup_fiber_serdes_link_generic; ++ : e1000e_setup_fiber_serdes_link; + /* check for link */ + switch (hw->phy.media_type) { + case e1000_media_type_copper: -+ mac->ops.check_for_link = e1000_check_for_copper_link_generic; ++ mac->ops.check_for_link = e1000e_check_for_copper_link; + break; + case e1000_media_type_fiber: -+ mac->ops.check_for_link = e1000_check_for_fiber_link_generic; ++ mac->ops.check_for_link = e1000e_check_for_fiber_link; + break; + case e1000_media_type_internal_serdes: -+ mac->ops.check_for_link = e1000_check_for_serdes_link_generic; ++ mac->ops.check_for_link = e1000e_check_for_serdes_link; + break; + default: + ret_val = -E1000_ERR_CONFIG; @@ -267,26 +257,26 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + /* check management mode */ + mac->ops.check_mng_mode = e1000_check_mng_mode_generic; + /* multicast address update */ -+ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; ++ mac->ops.update_mc_addr_list = e1000e_update_mc_addr_list_generic; + /* writing VFTA */ -+ mac->ops.write_vfta = e1000_write_vfta_generic; ++ mac->ops.write_vfta = e1000e_write_vfta_generic; + /* clearing VFTA */ -+ mac->ops.clear_vfta = e1000_clear_vfta_generic; ++ mac->ops.clear_vfta = e1000e_clear_vfta_generic; + /* setting MTA */ + mac->ops.mta_set = e1000_mta_set_generic; + /* read mac address */ + mac->ops.read_mac_addr = e1000_read_mac_addr_80003es2lan; ++ /* ID LED init */ ++ mac->ops.id_led_init = e1000e_id_led_init; + /* blink LED */ -+ mac->ops.blink_led = e1000_blink_led_generic; ++ mac->ops.blink_led = e1000e_blink_led; + /* setup LED */ + mac->ops.setup_led = e1000_setup_led_generic; + /* cleanup LED */ -+ mac->ops.cleanup_led = e1000_cleanup_led_generic; ++ mac->ops.cleanup_led = e1000e_cleanup_led_generic; + /* turn on/off LED */ -+ mac->ops.led_on = e1000_led_on_generic; -+ mac->ops.led_off = e1000_led_off_generic; -+ /* remove device */ -+ mac->ops.remove_device = e1000_remove_device_generic; ++ mac->ops.led_on = e1000e_led_on_generic; ++ mac->ops.led_off = e1000e_led_off_generic; + /* clear hardware counters */ + mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_80003es2lan; + /* link info */ @@ -300,34 +290,28 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * e1000_init_function_pointers_80003es2lan - Init ESB2 func ptrs. + * @hw: pointer to the HW structure + * -+ * The only function explicitly called by the api module to initialize -+ * all function pointers and parameters. ++ * Called to initialize all function pointers and parameters. + **/ +void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw) +{ -+ DEBUGFUNC("e1000_init_function_pointers_80003es2lan"); -+ + e1000_init_mac_ops_generic(hw); + e1000_init_nvm_ops_generic(hw); + hw->mac.ops.init_params = e1000_init_mac_params_80003es2lan; + hw->nvm.ops.init_params = e1000_init_nvm_params_80003es2lan; + hw->phy.ops.init_params = e1000_init_phy_params_80003es2lan; -+ e1000_get_bus_info_pcie_generic(hw); ++ e1000e_get_bus_info_pcie(hw); +} + +/** + * e1000_acquire_phy_80003es2lan - Acquire rights to access PHY + * @hw: pointer to the HW structure + * -+ * A wrapper to acquire access rights to the correct PHY. This is a -+ * function pointer entry point called by the api module. ++ * A wrapper to acquire access rights to the correct PHY. + **/ +static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw) +{ + u16 mask; + -+ DEBUGFUNC("e1000_acquire_phy_80003es2lan"); -+ + mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; + return e1000_acquire_swfw_sync_80003es2lan(hw, mask); +} @@ -336,15 +320,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * e1000_release_phy_80003es2lan - Release rights to access PHY + * @hw: pointer to the HW structure + * -+ * A wrapper to release access rights to the correct PHY. This is a -+ * function pointer entry point called by the api module. ++ * A wrapper to release access rights to the correct PHY. + **/ +static void e1000_release_phy_80003es2lan(struct e1000_hw *hw) +{ + u16 mask; + -+ DEBUGFUNC("e1000_release_phy_80003es2lan"); -+ + mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; + e1000_release_swfw_sync_80003es2lan(hw, mask); +} @@ -361,9 +342,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 +{ + u16 mask; + -+ DEBUGFUNC("e1000_acquire_mac_csr_80003es2lan"); -+ -+ mask = E1000_SWFW_CSR_SM; ++ mask = E1000_SWFW_CSR_SM; + + return e1000_acquire_swfw_sync_80003es2lan(hw, mask); +} @@ -378,8 +357,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 +{ + u16 mask; + -+ DEBUGFUNC("e1000_release_mac_csr_80003es2lan"); -+ + mask = E1000_SWFW_CSR_SM; + + e1000_release_swfw_sync_80003es2lan(hw, mask); @@ -389,20 +366,17 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * e1000_acquire_nvm_80003es2lan - Acquire rights to access NVM + * @hw: pointer to the HW structure + * -+ * Acquire the semaphore to access the EEPROM. This is a function -+ * pointer entry point called by the api module. ++ * Acquire the semaphore to access the EEPROM. + **/ +static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw) +{ + s32 ret_val; + -+ DEBUGFUNC("e1000_acquire_nvm_80003es2lan"); -+ + ret_val = e1000_acquire_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); + if (ret_val) + goto out; + -+ ret_val = e1000_acquire_nvm_generic(hw); ++ ret_val = e1000e_acquire_nvm(hw); + + if (ret_val) + e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); @@ -415,14 +389,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * e1000_release_nvm_80003es2lan - Relinquish rights to access NVM + * @hw: pointer to the HW structure + * -+ * Release the semaphore used to access the EEPROM. This is a -+ * function pointer entry point called by the api module. ++ * Release the semaphore used to access the EEPROM. + **/ +static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw) +{ -+ DEBUGFUNC("e1000_release_nvm_80003es2lan"); -+ -+ e1000_release_nvm_generic(hw); ++ e1000e_release_nvm(hw); + e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); +} + @@ -442,15 +413,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + s32 ret_val = E1000_SUCCESS; + s32 i = 0, timeout = 50; + -+ DEBUGFUNC("e1000_acquire_swfw_sync_80003es2lan"); -+ + while (i < timeout) { -+ if (e1000_get_hw_semaphore_generic(hw)) { ++ if (e1000e_get_hw_semaphore(hw)) { + ret_val = -E1000_ERR_SWFW_SYNC; + goto out; + } + -+ swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); ++ swfw_sync = er32(SW_FW_SYNC); + if (!(swfw_sync & (fwmask | swmask))) + break; + @@ -458,21 +427,21 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * Firmware currently using resource (fwmask) + * or other software thread using resource (swmask) + */ -+ e1000_put_hw_semaphore_generic(hw); -+ msec_delay_irq(5); ++ e1000e_put_hw_semaphore(hw); ++ mdelay(5); + i++; + } + + if (i == timeout) { -+ DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); ++ e_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n"); + ret_val = -E1000_ERR_SWFW_SYNC; + goto out; + } + + swfw_sync |= swmask; -+ E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); ++ ew32(SW_FW_SYNC, swfw_sync); + -+ e1000_put_hw_semaphore_generic(hw); ++ e1000e_put_hw_semaphore(hw); + +out: + return ret_val; @@ -490,16 +459,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 +{ + u32 swfw_sync; + -+ DEBUGFUNC("e1000_release_swfw_sync_80003es2lan"); ++ while (e1000e_get_hw_semaphore(hw) != E1000_SUCCESS) ++ ; /* Empty */ + -+ while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS); -+ /* Empty */ -+ -+ swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); ++ swfw_sync = er32(SW_FW_SYNC); + swfw_sync &= ~mask; -+ E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); ++ ew32(SW_FW_SYNC, swfw_sync); + -+ e1000_put_hw_semaphore_generic(hw); ++ e1000e_put_hw_semaphore(hw); +} + +/** @@ -508,8 +475,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * @offset: offset of the register to read + * @data: pointer to the data returned from the operation + * -+ * Read the GG82563 PHY register. This is a function pointer entry -+ * point called by the api module. ++ * Read the GG82563 PHY register. + **/ +static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, + u32 offset, u16 *data) @@ -518,8 +484,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + u32 page_select; + u16 temp; + -+ DEBUGFUNC("e1000_read_phy_reg_gg82563_80003es2lan"); -+ + ret_val = e1000_acquire_phy_80003es2lan(hw); + if (ret_val) + goto out; @@ -536,7 +500,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + } + + temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT); -+ ret_val = e1000_write_phy_reg_mdic(hw, page_select, temp); ++ ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp); + if (ret_val) { + e1000_release_phy_80003es2lan(hw); + goto out; @@ -547,10 +511,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * before the device has completed the "Page Select" MDI + * transaction. So we wait 200us after each MDI command... + */ -+ usec_delay(200); ++ udelay(200); + + /* ...and verify the command was successful. */ -+ ret_val = e1000_read_phy_reg_mdic(hw, page_select, &temp); ++ ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp); + + if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { + ret_val = -E1000_ERR_PHY; @@ -558,13 +522,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + goto out; + } + -+ usec_delay(200); ++ udelay(200); + -+ ret_val = e1000_read_phy_reg_mdic(hw, -+ MAX_PHY_REG_ADDRESS & offset, -+ data); ++ ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, ++ data); + -+ usec_delay(200); ++ udelay(200); + e1000_release_phy_80003es2lan(hw); + +out: @@ -577,8 +540,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * @offset: offset of the register to read + * @data: value to write to the register + * -+ * Write to the GG82563 PHY register. This is a function pointer entry -+ * point called by the api module. ++ * Write to the GG82563 PHY register. + **/ +static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, + u32 offset, u16 data) @@ -587,8 +549,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + u32 page_select; + u16 temp; + -+ DEBUGFUNC("e1000_write_phy_reg_gg82563_80003es2lan"); -+ + ret_val = e1000_acquire_phy_80003es2lan(hw); + if (ret_val) + goto out; @@ -605,7 +565,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + } + + temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT); -+ ret_val = e1000_write_phy_reg_mdic(hw, page_select, temp); ++ ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp); + if (ret_val) { + e1000_release_phy_80003es2lan(hw); + goto out; @@ -617,10 +577,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * before the device has completed the "Page Select" MDI + * transaction. So we wait 200us after each MDI command... + */ -+ usec_delay(200); ++ udelay(200); + + /* ...and verify the command was successful. */ -+ ret_val = e1000_read_phy_reg_mdic(hw, page_select, &temp); ++ ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp); + + if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { + ret_val = -E1000_ERR_PHY; @@ -628,13 +588,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + goto out; + } + -+ usec_delay(200); ++ udelay(200); + -+ ret_val = e1000_write_phy_reg_mdic(hw, -+ MAX_PHY_REG_ADDRESS & offset, ++ ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, + data); + -+ usec_delay(200); ++ udelay(200); + e1000_release_phy_80003es2lan(hw); + +out: @@ -648,15 +607,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * @words: number of words to write + * @data: buffer of data to write to the NVM + * -+ * Write "words" of data to the ESB2 NVM. This is a function -+ * pointer entry point called by the api module. ++ * Write "words" of data to the ESB2 NVM. + **/ +static s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset, + u16 words, u16 *data) +{ -+ DEBUGFUNC("e1000_write_nvm_80003es2lan"); -+ -+ return e1000_write_nvm_spi(hw, offset, words, data); ++ return e1000e_write_nvm_spi(hw, offset, words, data); +} + +/** @@ -672,19 +628,17 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + s32 ret_val = E1000_SUCCESS; + u32 mask = E1000_NVM_CFG_DONE_PORT_0; + -+ DEBUGFUNC("e1000_get_cfg_done_80003es2lan"); -+ + if (hw->bus.func == 1) + mask = E1000_NVM_CFG_DONE_PORT_1; + + while (timeout) { -+ if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask) ++ if (er32(EEMNGCTL) & mask) + break; -+ msec_delay(1); ++ msleep(1); + timeout--; + } + if (!timeout) { -+ DEBUGOUT("MNG configuration cycle has not completed.\n"); ++ e_dbg("MNG configuration cycle has not completed.\n"); + ret_val = -E1000_ERR_RESET; + goto out; + } @@ -706,8 +660,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + u16 phy_data; + bool link; + -+ DEBUGFUNC("e1000_phy_force_speed_duplex_80003es2lan"); -+ + if (!(hw->phy.ops.read_reg)) + goto out; + @@ -715,37 +667,37 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI + * forced whenever speed and duplex are forced. + */ -+ ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); ++ ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + if (ret_val) + goto out; + + phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_AUTO; -+ ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data); ++ ret_val = e1e_wphy(hw, GG82563_PHY_SPEC_CTRL, phy_data); + if (ret_val) + goto out; + -+ DEBUGOUT1("GG82563 PSCR: %X\n", phy_data); ++ e_dbg("GG82563 PSCR: %X\n", phy_data); + -+ ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_data); ++ ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data); + if (ret_val) + goto out; + -+ e1000_phy_force_speed_duplex_setup(hw, &phy_data); ++ e1000e_phy_force_speed_duplex_setup(hw, &phy_data); + + /* Reset the phy to commit changes. */ + phy_data |= MII_CR_RESET; + -+ ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_data); ++ ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data); + if (ret_val) + goto out; + -+ usec_delay(1); ++ udelay(1); + + if (hw->phy.autoneg_wait_to_complete) { -+ DEBUGOUT("Waiting for forced speed/duplex link " ++ e_dbg("Waiting for forced speed/duplex link " + "on GG82563 phy.\n"); + -+ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, ++ ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, + 100000, &link); + if (ret_val) + goto out; @@ -755,19 +707,19 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * We didn't get link. + * Reset the DSP and cross our fingers. + */ -+ ret_val = e1000_phy_reset_dsp_generic(hw); ++ ret_val = e1000e_phy_reset_dsp(hw); + if (ret_val) + goto out; + } + + /* Try once more */ -+ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, ++ ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, + 100000, &link); + if (ret_val) + goto out; + } + -+ ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data); ++ ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data); + if (ret_val) + goto out; + @@ -786,7 +738,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * duplex. + */ + phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX; -+ ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data); ++ ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data); + +out: + return ret_val; @@ -805,16 +757,20 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + s32 ret_val = E1000_SUCCESS; + u16 phy_data, index; + -+ DEBUGFUNC("e1000_get_cable_length_80003es2lan"); -+ + if (!(hw->phy.ops.read_reg)) + goto out; + -+ ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_DSP_DISTANCE, &phy_data); ++ ret_val = e1e_rphy(hw, GG82563_PHY_DSP_DISTANCE, &phy_data); + if (ret_val) + goto out; + + index = phy_data & GG82563_DSPD_CABLE_LENGTH; ++ ++ if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE + 5) { ++ ret_val = E1000_ERR_PHY; ++ goto out; ++ } ++ + phy->min_cable_length = e1000_gg82563_cable_length_table[index]; + phy->max_cable_length = e1000_gg82563_cable_length_table[index+5]; + @@ -831,21 +787,19 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * @duplex: pointer to duplex buffer + * + * Retrieve the current speed and duplex configuration. -+ * This is a function pointer entry point called by the api module. + **/ +static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed, + u16 *duplex) +{ + s32 ret_val; + -+ DEBUGFUNC("e1000_get_link_up_info_80003es2lan"); -+ + if (hw->phy.media_type == e1000_media_type_copper) { -+ ret_val = e1000_get_speed_and_duplex_copper_generic(hw, ++ ret_val = e1000e_get_speed_and_duplex_copper(hw, + speed, + duplex); ++ hw->phy.ops.cfg_on_link_up(hw); + } else { -+ ret_val = e1000_get_speed_and_duplex_fiber_serdes_generic(hw, ++ ret_val = e1000e_get_speed_and_duplex_fiber_serdes(hw, + speed, + duplex); + } @@ -858,50 +812,46 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * @hw: pointer to the HW structure + * + * Perform a global reset to the ESB2 controller. -+ * This is a function pointer entry point called by the api module. + **/ +static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw) +{ + u32 ctrl, icr; + s32 ret_val; + -+ DEBUGFUNC("e1000_reset_hw_80003es2lan"); -+ + /* + * Prevent the PCI-E bus from sticking if there is no TLP connection + * on the last TLP read/write transaction when MAC is reset. + */ -+ ret_val = e1000_disable_pcie_master_generic(hw); -+ if (ret_val) { -+ DEBUGOUT("PCI-E Master disable polling has failed.\n"); -+ } ++ ret_val = e1000e_disable_pcie_master(hw); ++ if (ret_val) ++ e_dbg("PCI-E Master disable polling has failed.\n"); + -+ DEBUGOUT("Masking off all interrupts\n"); -+ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); ++ e_dbg("Masking off all interrupts\n"); ++ ew32(IMC, 0xffffffff); + -+ E1000_WRITE_REG(hw, E1000_RCTL, 0); -+ E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); -+ E1000_WRITE_FLUSH(hw); ++ ew32(RCTL, 0); ++ ew32(TCTL, E1000_TCTL_PSP); ++ e1e_flush(); + -+ msec_delay(10); ++ msleep(10); + -+ ctrl = E1000_READ_REG(hw, E1000_CTRL); ++ ctrl = er32(CTRL); + -+ ret_val = e1000_acquire_phy_80003es2lan(hw); -+ DEBUGOUT("Issuing a global reset to MAC\n"); -+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); ++ ret_val = e1000_acquire_phy_80003es2lan(hw); ++ e_dbg("Issuing a global reset to MAC\n"); ++ ew32(CTRL, ctrl | E1000_CTRL_RST); + e1000_release_phy_80003es2lan(hw); + -+ ret_val = e1000_get_auto_rd_done_generic(hw); ++ ret_val = e1000e_get_auto_rd_done(hw); + if (ret_val) + /* We don't want to continue accessing MAC registers. */ + goto out; + + /* Clear any pending interrupt events. */ -+ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); -+ icr = E1000_READ_REG(hw, E1000_ICR); ++ ew32(IMC, 0xffffffff); ++ icr = er32(ICR); + -+ e1000_check_alt_mac_addr_generic(hw); ++ ret_val = e1000_check_alt_mac_addr_generic(hw); + +out: + return ret_val; @@ -912,7 +862,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * @hw: pointer to the HW structure + * + * Initialize the hw bits, LED, VFTA, MTA, link and hw counters. -+ * This is a function pointer entry point called by the api module. + **/ +static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw) +{ @@ -921,26 +870,24 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + s32 ret_val; + u16 i; + -+ DEBUGFUNC("e1000_init_hw_80003es2lan"); -+ + e1000_initialize_hw_bits_80003es2lan(hw); + + /* 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"); ++ e_dbg("Error initializing identification LED\n"); + /* This is not fatal and we should not stop init due to this */ + } + + /* Disabling VLAN filtering */ -+ DEBUGOUT("Initializing the IEEE VLAN\n"); -+ mac->ops.clear_vfta(hw); ++ e_dbg("Initializing the IEEE VLAN\n"); ++ e1000e_clear_vfta(hw); + + /* Setup the receive address. */ -+ e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); ++ e1000e_init_rx_addrs(hw, mac->rar_entry_count); + + /* Zero out the Multicast HASH table */ -+ DEBUGOUT("Zeroing the MTA\n"); ++ e_dbg("Zeroing the MTA\n"); + for (i = 0; i < mac->mta_reg_count; i++) + E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); + @@ -948,33 +895,33 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + ret_val = mac->ops.setup_link(hw); + + /* Set the transmit descriptor write-back policy */ -+ reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0)); ++ reg_data = er32(TXDCTL(0)); + reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | + E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC; -+ E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data); ++ ew32(TXDCTL(0), reg_data); + + /* ...for both queues. */ -+ reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1)); ++ reg_data = er32(TXDCTL(1)); + reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | + E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC; -+ E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data); ++ ew32(TXDCTL(1), reg_data); + + /* Enable retransmit on late collisions */ -+ reg_data = E1000_READ_REG(hw, E1000_TCTL); ++ reg_data = er32(TCTL); + reg_data |= E1000_TCTL_RTLC; -+ E1000_WRITE_REG(hw, E1000_TCTL, reg_data); ++ ew32(TCTL, reg_data); + + /* Configure Gigabit Carry Extend Padding */ -+ reg_data = E1000_READ_REG(hw, E1000_TCTL_EXT); ++ reg_data = er32(TCTL_EXT); + reg_data &= ~E1000_TCTL_EXT_GCEX_MASK; + reg_data |= DEFAULT_TCTL_EXT_GCEX_80003ES2LAN; -+ E1000_WRITE_REG(hw, E1000_TCTL_EXT, reg_data); ++ ew32(TCTL_EXT, reg_data); + + /* Configure Transmit Inter-Packet Gap */ -+ reg_data = E1000_READ_REG(hw, E1000_TIPG); ++ reg_data = er32(TIPG); + reg_data &= ~E1000_TIPG_IPGT_MASK; + reg_data |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN; -+ E1000_WRITE_REG(hw, E1000_TIPG, reg_data); ++ ew32(TIPG, reg_data); + + reg_data = E1000_READ_REG_ARRAY(hw, E1000_FFLT, 0x0001); + reg_data &= ~0x00100000; @@ -1001,37 +948,31 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 +{ + u32 reg; + -+ DEBUGFUNC("e1000_initialize_hw_bits_80003es2lan"); -+ -+ if (hw->mac.disable_hw_init_bits) -+ goto out; -+ + /* Transmit Descriptor Control 0 */ -+ reg = E1000_READ_REG(hw, E1000_TXDCTL(0)); ++ reg = er32(TXDCTL(0)); + reg |= (1 << 22); -+ E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg); ++ ew32(TXDCTL(0), reg); + + /* Transmit Descriptor Control 1 */ -+ reg = E1000_READ_REG(hw, E1000_TXDCTL(1)); ++ reg = er32(TXDCTL(1)); + reg |= (1 << 22); -+ E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg); ++ ew32(TXDCTL(1), reg); + + /* Transmit Arbitration Control 0 */ -+ reg = E1000_READ_REG(hw, E1000_TARC(0)); ++ reg = er32(TARC(0)); + reg &= ~(0xF << 27); /* 30:27 */ + if (hw->phy.media_type != e1000_media_type_copper) + reg &= ~(1 << 20); -+ E1000_WRITE_REG(hw, E1000_TARC(0), reg); ++ ew32(TARC(0), reg); + + /* Transmit Arbitration Control 1 */ -+ reg = E1000_READ_REG(hw, E1000_TARC(1)); -+ if (E1000_READ_REG(hw, E1000_TCTL) & E1000_TCTL_MULR) ++ reg = er32(TARC(1)); ++ if (er32(TCTL) & E1000_TCTL_MULR) + reg &= ~(1 << 28); + else + reg |= (1 << 28); -+ E1000_WRITE_REG(hw, E1000_TARC(1), reg); ++ ew32(TARC(1), reg); + -+out: + return; +} + @@ -1048,10 +989,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + u32 ctrl_ext; + u16 data; + -+ DEBUGFUNC("e1000_copper_link_setup_gg82563_80003es2lan"); -+ + if (!phy->reset_disable) { -+ ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, ++ ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, + &data); + if (ret_val) + goto out; @@ -1060,7 +999,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + /* Use 25MHz for both link down and 1000Base-T for Tx clock. */ + data |= GG82563_MSCR_TX_CLK_1000MBPS_25; + -+ ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, ++ ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL, + data); + if (ret_val) + goto out; @@ -1073,7 +1012,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * 2 - MDI-X mode + * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) + */ -+ ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL, &data); ++ ret_val = e1e_rphy(hw, GG82563_PHY_SPEC_CTRL, &data); + if (ret_val) + goto out; + @@ -1103,14 +1042,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + if (phy->disable_polarity_correction) + data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE; + -+ ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, data); ++ ret_val = e1e_wphy(hw, GG82563_PHY_SPEC_CTRL, data); + if (ret_val) + goto out; + + /* SW Reset the PHY so all changes take effect */ -+ ret_val = hw->phy.ops.commit(hw); ++ ret_val = e1000e_commit_phy(hw); + if (ret_val) { -+ DEBUGOUT("Error Resetting the PHY\n"); ++ e_dbg("Error Resetting the PHY\n"); + goto out; + } + @@ -1118,9 +1057,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + + /* Bypass Rx and Tx FIFO's */ + ret_val = e1000_write_kmrn_reg_80003es2lan(hw, -+ E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL, -+ E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS | -+ E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS); ++ E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL, ++ E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS | ++ E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS); + if (ret_val) + goto out; + @@ -1136,20 +1075,20 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + if (ret_val) + goto out; + -+ ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL_2, &data); ++ ret_val = e1e_rphy(hw, GG82563_PHY_SPEC_CTRL_2, &data); + if (ret_val) + goto out; + + data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG; -+ ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL_2, data); ++ ret_val = e1e_wphy(hw, GG82563_PHY_SPEC_CTRL_2, data); + if (ret_val) + goto out; + -+ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ++ ctrl_ext = er32(CTRL_EXT); + ctrl_ext &= ~(E1000_CTRL_EXT_LINK_MODE_MASK); -+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); ++ ew32(CTRL_EXT, ctrl_ext); + -+ ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, &data); ++ ret_val = e1e_rphy(hw, GG82563_PHY_PWR_MGMT_CTRL, &data); + if (ret_val) + goto out; + @@ -1161,22 +1100,19 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + if (!(hw->mac.ops.check_mng_mode(hw))) { + /* Enable Electrical Idle on the PHY */ + data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE; -+ ret_val = hw->phy.ops.write_reg(hw, -+ GG82563_PHY_PWR_MGMT_CTRL, ++ ret_val = e1e_wphy(hw, GG82563_PHY_PWR_MGMT_CTRL, + data); + if (ret_val) + goto out; -+ ret_val = hw->phy.ops.read_reg(hw, -+ GG82563_PHY_KMRN_MODE_CTRL, -+ &data); -+ if (ret_val) -+ goto out; ++ ++ ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ++ &data); ++ if (ret_val) ++ goto out; + + data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; -+ ret_val = hw->phy.ops.write_reg(hw, -+ GG82563_PHY_KMRN_MODE_CTRL, ++ ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, + data); -+ + if (ret_val) + goto out; + } @@ -1185,12 +1121,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * Workaround: Disable padding in Kumeran interface in the MAC + * and in the PHY to avoid CRC errors. + */ -+ ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_INBAND_CTRL, &data); ++ ret_val = e1e_rphy(hw, GG82563_PHY_INBAND_CTRL, &data); + if (ret_val) + goto out; + + data |= GG82563_ICR_DIS_PADDING; -+ ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_INBAND_CTRL, data); ++ ret_val = e1e_wphy(hw, GG82563_PHY_INBAND_CTRL, data); + if (ret_val) + goto out; + @@ -1208,15 +1144,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 +static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw) +{ + u32 ctrl; -+ s32 ret_val; ++ s32 ret_val; + u16 reg_data; + -+ DEBUGFUNC("e1000_setup_copper_link_80003es2lan"); -+ -+ ctrl = E1000_READ_REG(hw, E1000_CTRL); ++ ctrl = er32(CTRL); + ctrl |= E1000_CTRL_SLU; + ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); -+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ++ ew32(CTRL, ctrl); + + /* + * Set the mac to wait the maximum time between each @@ -1252,7 +1186,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + if (ret_val) + goto out; + -+ ret_val = e1000_setup_copper_link_generic(hw); ++ ret_val = e1000e_setup_copper_link(hw); + +out: + return ret_val; @@ -1272,11 +1206,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + u16 speed; + u16 duplex; + -+ DEBUGFUNC("e1000_configure_on_link_up"); -+ + if (hw->phy.media_type == e1000_media_type_copper) { -+ -+ ret_val = e1000_get_speed_and_duplex_copper_generic(hw, ++ ret_val = e1000e_get_speed_and_duplex_copper(hw, + &speed, + &duplex); + if (ret_val) @@ -1307,8 +1238,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + u32 i = 0; + u16 reg_data, reg_data2; + -+ DEBUGFUNC("e1000_configure_kmrn_for_10_100"); -+ + reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT; + ret_val = e1000_write_kmrn_reg_80003es2lan(hw, + E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, @@ -1317,19 +1246,19 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + goto out; + + /* Configure Transmit Inter-Packet Gap */ -+ tipg = E1000_READ_REG(hw, E1000_TIPG); ++ tipg = er32(TIPG); + tipg &= ~E1000_TIPG_IPGT_MASK; + tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN; -+ E1000_WRITE_REG(hw, E1000_TIPG, tipg); ++ ew32(TIPG, tipg); + + + do { -+ ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, ++ ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, + ®_data); + if (ret_val) + goto out; + -+ ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, ++ ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, + ®_data2); + if (ret_val) + goto out; @@ -1341,7 +1270,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + else + reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; + -+ ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); ++ ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); + +out: + return ret_val; @@ -1361,8 +1290,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + u32 tipg; + u32 i = 0; + -+ DEBUGFUNC("e1000_configure_kmrn_for_1000"); -+ + reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT; + ret_val = e1000_write_kmrn_reg_80003es2lan(hw, + E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, @@ -1371,19 +1298,19 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + goto out; + + /* Configure Transmit Inter-Packet Gap */ -+ tipg = E1000_READ_REG(hw, E1000_TIPG); ++ tipg = er32(TIPG); + tipg &= ~E1000_TIPG_IPGT_MASK; + tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN; -+ E1000_WRITE_REG(hw, E1000_TIPG, tipg); ++ ew32(TIPG, tipg); + + + do { -+ ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, ++ ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, + ®_data); + if (ret_val) + goto out; + -+ ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, ++ ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, + ®_data2); + if (ret_val) + goto out; @@ -1391,7 +1318,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY)); + + reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; -+ ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); ++ ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); + +out: + return ret_val; @@ -1407,24 +1334,23 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * using the kumeran interface. The information retrieved is stored in data. + * Release the semaphore before exiting. + **/ -+s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 *data) ++static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, ++ u16 *data) +{ + u32 kmrnctrlsta; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_read_kmrn_reg_80003es2lan"); -+ + ret_val = e1000_acquire_mac_csr_80003es2lan(hw); + if (ret_val) + goto out; + + kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & + E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; -+ E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); ++ ew32(KMRNCTRLSTA, kmrnctrlsta); + -+ usec_delay(2); ++ udelay(2); + -+ kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA); ++ kmrnctrlsta = er32(KMRNCTRLSTA); + *data = (u16)kmrnctrlsta; + + e1000_release_mac_csr_80003es2lan(hw); @@ -1443,22 +1369,21 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + * at the offset using the kumeran interface. Release semaphore + * before exiting. + **/ -+s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 data) ++static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, ++ u16 data) +{ + u32 kmrnctrlsta; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_write_kmrn_reg_80003es2lan"); -+ + ret_val = e1000_acquire_mac_csr_80003es2lan(hw); + if (ret_val) + goto out; + + kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & + E1000_KMRNCTRLSTA_OFFSET) | data; -+ E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); ++ ew32(KMRNCTRLSTA, kmrnctrlsta); + -+ usec_delay(2); ++ udelay(2); + + e1000_release_mac_csr_80003es2lan(hw); + @@ -1474,10 +1399,18 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 +{ + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_read_mac_addr_80003es2lan"); -+ 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 = e1000e_read_mac_addr_generic(hw); + ++out: + return ret_val; +} + @@ -1492,7 +1425,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 +{ + /* If the management interface is not enabled, then power down */ + if (!(hw->mac.ops.check_mng_mode(hw) || -+ hw->phy.ops.check_reset_block(hw))) ++ e1000_check_reset_block(hw))) + e1000_power_down_phy_copper(hw); + + return; @@ -1506,55 +1439,51 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.c linux-2.6.22-10 + **/ +static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw) +{ -+ volatile u32 temp; -+ -+ DEBUGFUNC("e1000_clear_hw_cntrs_80003es2lan"); -+ -+ 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); ++ e1000e_clear_hw_cntrs_base(hw); ++ ++ er32(PRC64); ++ er32(PRC127); ++ er32(PRC255); ++ er32(PRC511); ++ er32(PRC1023); ++ er32(PRC1522); ++ er32(PTC64); ++ er32(PTC127); ++ er32(PTC255); ++ er32(PTC511); ++ er32(PTC1023); ++ er32(PTC1522); ++ ++ er32(ALGNERRC); ++ er32(RXERRC); ++ er32(TNCRS); ++ er32(CEXTERR); ++ er32(TSCTC); ++ er32(TSCTFC); ++ ++ er32(MGTPRC); ++ er32(MGTPDC); ++ er32(MGTPTC); ++ ++ er32(IAC); ++ er32(ICRXOC); ++ ++ er32(ICRXPTC); ++ er32(ICRXATC); ++ er32(ICTXPTC); ++ er32(ICTXATC); ++ er32(ICTXQEC); ++ er32(ICTXQMTC); ++ er32(ICRXDMTC); +} diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.h linux-2.6.22-10/drivers/net/e1000e/e1000_80003es2lan.h --- linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000_80003es2lan.h 2008-10-14 01:51:32.000000000 +0200 ++++ linux-2.6.22-10/drivers/net/e1000e/e1000_80003es2lan.h 2009-06-24 00:32:20.000000000 +0200 @@ -0,0 +1,95 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -1648,12 +1577,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_80003es2lan.h linux-2.6.22-10 +#endif diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drivers/net/e1000e/e1000_82571.c --- linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000_82571.c 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,1538 @@ ++++ linux-2.6.22-10/drivers/net/e1000e/e1000_82571.c 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,1767 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -1678,13 +1607,25 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + +*******************************************************************************/ + -+/* e1000_82571 -+ * e1000_82572 -+ * e1000_82573 -+ * e1000_82574 ++/* ++ * 82571EB Gigabit Ethernet Controller ++ * 82571EB Gigabit Ethernet Controller (Copper) ++ * 82571EB Gigabit Ethernet Controller (Fiber) ++ * 82571EB Dual Port Gigabit Mezzanine Adapter ++ * 82571EB Quad Port Gigabit Mezzanine Adapter ++ * 82571PT Gigabit PT Quad Port Server ExpressModule ++ * 82572EI Gigabit Ethernet Controller (Copper) ++ * 82572EI Gigabit Ethernet Controller (Fiber) ++ * 82572EI Gigabit Ethernet Controller ++ * 82573V Gigabit Ethernet Controller (Copper) ++ * 82573E Gigabit Ethernet Controller (Copper) ++ * 82573L Gigabit Ethernet Controller ++ * 82574L Gigabit Network Connection ++ * 82574L Gigabit Network Connection ++ * 82583V Gigabit Network Connection + */ + -+#include "e1000_hw.h" ++#include "e1000.h" + +static s32 e1000_init_phy_params_82571(struct e1000_hw *hw); +static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw); @@ -1703,11 +1644,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive +static void e1000_clear_vfta_82571(struct e1000_hw *hw); +static bool e1000_check_mng_mode_82574(struct e1000_hw *hw); +static s32 e1000_led_on_82574(struct e1000_hw *hw); -+static void e1000_update_mc_addr_list_82571(struct e1000_hw *hw, -+ u8 *mc_addr_list, u32 mc_addr_count, -+ u32 rar_used_count, u32 rar_count); +static s32 e1000_setup_link_82571(struct e1000_hw *hw); +static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw); ++static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw); +static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw); +static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data); +static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw); @@ -1721,25 +1660,17 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive +static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw); +static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw); + -+struct e1000_dev_spec_82571 { -+ bool laa_is_present; -+}; -+ +/** + * e1000_init_phy_params_82571 - Init PHY func ptrs. + * @hw: pointer to the HW structure -+ * -+ * This is a function pointer entry point called by the api module. + **/ +static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_init_phy_params_82571"); -+ + if (hw->phy.media_type != e1000_media_type_copper) { -+ phy->type = e1000_phy_none; ++ phy->type = e1000_phy_none; + goto out; + } + @@ -1749,11 +1680,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + + phy->ops.acquire = e1000_get_hw_semaphore_82571; + phy->ops.check_polarity = e1000_check_polarity_igp; -+ phy->ops.check_reset_block = e1000_check_reset_block_generic; ++ phy->ops.check_reset_block = e1000e_check_reset_block_generic; + phy->ops.release = e1000_put_hw_semaphore_82571; -+ phy->ops.reset = e1000_phy_hw_reset_generic; ++ phy->ops.reset = e1000e_phy_hw_reset_generic; + phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82571; -+ phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic; ++ phy->ops.set_d3_lplu_state = e1000e_set_d3_lplu_state; + phy->ops.power_up = e1000_power_up_phy_copper; + phy->ops.power_down = e1000_power_down_phy_copper_82571; + @@ -1762,11 +1693,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + case e1000_82572: + phy->type = e1000_phy_igp_2; + phy->ops.get_cfg_done = e1000_get_cfg_done_82571; -+ phy->ops.get_info = e1000_get_phy_info_igp; -+ phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp; -+ phy->ops.get_cable_length = e1000_get_cable_length_igp_2; -+ phy->ops.read_reg = e1000_read_phy_reg_igp; -+ phy->ops.write_reg = e1000_write_phy_reg_igp; ++ phy->ops.get_info = e1000e_get_phy_info_igp; ++ phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_igp; ++ phy->ops.get_cable_length = e1000e_get_cable_length_igp_2; ++ phy->ops.read_reg = e1000e_read_phy_reg_igp; ++ phy->ops.write_reg = e1000e_write_phy_reg_igp; + + /* This uses above function pointers */ + ret_val = e1000_get_phy_id_82571(hw); @@ -1779,13 +1710,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + break; + case e1000_82573: + phy->type = e1000_phy_m88; -+ phy->ops.get_cfg_done = e1000_get_cfg_done_generic; -+ phy->ops.get_info = e1000_get_phy_info_m88; -+ phy->ops.commit = e1000_phy_sw_reset_generic; -+ phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; -+ phy->ops.get_cable_length = e1000_get_cable_length_m88; -+ phy->ops.read_reg = e1000_read_phy_reg_m88; -+ phy->ops.write_reg = e1000_write_phy_reg_m88; ++ phy->ops.get_cfg_done = e1000e_get_cfg_done; ++ phy->ops.get_info = e1000e_get_phy_info_m88; ++ phy->ops.commit = e1000e_phy_sw_reset; ++ phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_m88; ++ phy->ops.get_cable_length = e1000e_get_cable_length_m88; ++ phy->ops.read_reg = e1000e_read_phy_reg_m88; ++ phy->ops.write_reg = e1000e_write_phy_reg_m88; + + /* This uses above function pointers */ + ret_val = e1000_get_phy_id_82571(hw); @@ -1793,26 +1724,27 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + /* Verify PHY ID */ + if (phy->id != M88E1111_I_PHY_ID) { + ret_val = -E1000_ERR_PHY; -+ DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id); ++ e_dbg("PHY ID unknown: type = 0x%08x\n", phy->id); + goto out; + } + break; ++ case e1000_82583: + case e1000_82574: + phy->type = e1000_phy_bm; -+ phy->ops.get_cfg_done = e1000_get_cfg_done_generic; -+ phy->ops.get_info = e1000_get_phy_info_m88; -+ phy->ops.commit = e1000_phy_sw_reset_generic; -+ phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; -+ phy->ops.get_cable_length = e1000_get_cable_length_m88; -+ phy->ops.read_reg = e1000_read_phy_reg_bm2; -+ phy->ops.write_reg = e1000_write_phy_reg_bm2; ++ phy->ops.get_cfg_done = e1000e_get_cfg_done; ++ phy->ops.get_info = e1000e_get_phy_info_m88; ++ phy->ops.commit = e1000e_phy_sw_reset; ++ phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_m88; ++ phy->ops.get_cable_length = e1000e_get_cable_length_m88; ++ phy->ops.read_reg = e1000e_read_phy_reg_bm2; ++ phy->ops.write_reg = e1000e_write_phy_reg_bm2; + + /* This uses above function pointers */ + ret_val = e1000_get_phy_id_82571(hw); + /* Verify PHY ID */ -+ if (phy->id != BME1000_E_PHY_ID_R2) { ++ if (phy->id != BME1000_E_PHY_ID_R2) { + ret_val = -E1000_ERR_PHY; -+ DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id); ++ e_dbg("PHY ID unknown: type = 0x%08x\n", phy->id); + goto out; + } + break; @@ -1829,30 +1761,26 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive +/** + * e1000_init_nvm_params_82571 - Init NVM func ptrs. + * @hw: pointer to the HW structure -+ * -+ * This is a function pointer entry point called by the api module. + **/ +static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) +{ + struct e1000_nvm_info *nvm = &hw->nvm; -+ u32 eecd = E1000_READ_REG(hw, E1000_EECD); ++ u32 eecd = er32(EECD); + u16 size; + -+ DEBUGFUNC("e1000_init_nvm_params_82571"); -+ -+ nvm->opcode_bits = 8; -+ nvm->delay_usec = 1; ++ nvm->opcode_bits = 8; ++ nvm->delay_usec = 1; + switch (nvm->override) { + case e1000_nvm_override_spi_large: -+ nvm->page_size = 32; ++ nvm->page_size = 32; + nvm->address_bits = 16; + break; + case e1000_nvm_override_spi_small: -+ nvm->page_size = 8; ++ nvm->page_size = 8; + nvm->address_bits = 8; + break; + default: -+ nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; ++ nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; + nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; + break; + } @@ -1860,6 +1788,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + switch (hw->mac.type) { + case e1000_82573: + case e1000_82574: ++ case e1000_82583: + if (((eecd >> 15) & 0x3) == 0x3) { + nvm->type = e1000_nvm_flash_hw; + nvm->word_size = 2048; @@ -1868,12 +1797,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + * to Flash update issue. + */ + eecd &= ~E1000_EECD_AUPDEN; -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); ++ ew32(EECD, eecd); + break; + } + /* Fall Through */ + default: -+ nvm->type = e1000_nvm_eeprom_spi; ++ nvm->type = e1000_nvm_eeprom_spi; + size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> + E1000_EECD_SIZE_EX_SHIFT); + /* @@ -1891,7 +1820,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + + /* Function Pointers */ + nvm->ops.acquire = e1000_acquire_nvm_82571; -+ nvm->ops.read = e1000_read_nvm_eerd; ++ nvm->ops.read = e1000e_read_nvm_eerd; + nvm->ops.release = e1000_release_nvm_82571; + nvm->ops.update = e1000_update_nvm_checksum_82571; + nvm->ops.validate = e1000_validate_nvm_checksum_82571; @@ -1904,15 +1833,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive +/** + * e1000_init_mac_params_82571 - Init MAC func ptrs. + * @hw: pointer to the HW structure -+ * -+ * This is a function pointer entry point called by the api module. + **/ +static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + s32 ret_val = E1000_SUCCESS; -+ -+ DEBUGFUNC("e1000_init_mac_params_82571"); ++ u32 swsm = 0; ++ u32 swsm2 = 0; ++ bool force_clear_smbi = false; + + /* Set media type */ + switch (hw->device_id) { @@ -1940,13 +1868,23 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + mac->asf_firmware_present = true; + /* Set if manageability features are enabled. */ + mac->arc_subsystem_valid = -+ (E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK) ++ (er32(FWSM) & E1000_FWSM_MODE_MASK) + ? true : false; + + /* Function pointers */ + + /* bus type/speed/width */ -+ mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic; ++ mac->ops.get_bus_info = e1000e_get_bus_info_pcie; ++ /* function id */ ++ switch (hw->mac.type) { ++ case e1000_82573: ++ case e1000_82574: ++ case e1000_82583: ++ mac->ops.set_lan_id = e1000_set_lan_id_single_port; ++ break; ++ default: ++ break; ++ } + /* reset */ + mac->ops.reset_hw = e1000_reset_hw_82571; + /* hw initialization */ @@ -1961,13 +1899,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + /* check for link */ + switch (hw->phy.media_type) { + case e1000_media_type_copper: -+ mac->ops.check_for_link = e1000_check_for_copper_link_generic; ++ mac->ops.check_for_link = e1000e_check_for_copper_link; + break; + case e1000_media_type_fiber: -+ mac->ops.check_for_link = e1000_check_for_fiber_link_generic; ++ mac->ops.check_for_link = e1000e_check_for_fiber_link; + break; + case e1000_media_type_internal_serdes: -+ mac->ops.check_for_link = e1000_check_for_serdes_link_generic; ++ mac->ops.check_for_link = e1000_check_for_serdes_link_82571; + break; + default: + ret_val = -E1000_ERR_CONFIG; @@ -1977,6 +1915,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + /* check management mode */ + switch (hw->mac.type) { + case e1000_82574: ++ case e1000_82583: + mac->ops.check_mng_mode = e1000_check_mng_mode_82574; + break; + default: @@ -1984,45 +1923,85 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + break; + } + /* multicast address update */ -+ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_82571; ++ mac->ops.update_mc_addr_list = e1000e_update_mc_addr_list_generic; + /* writing VFTA */ -+ mac->ops.write_vfta = e1000_write_vfta_generic; ++ mac->ops.write_vfta = e1000e_write_vfta_generic; + /* clearing VFTA */ + mac->ops.clear_vfta = e1000_clear_vfta_82571; + /* setting MTA */ + mac->ops.mta_set = e1000_mta_set_generic; + /* read mac address */ + mac->ops.read_mac_addr = e1000_read_mac_addr_82571; ++ /* ID LED init */ ++ mac->ops.id_led_init = e1000e_id_led_init; + /* blink LED */ -+ mac->ops.blink_led = e1000_blink_led_generic; ++ mac->ops.blink_led = e1000e_blink_led; + /* setup LED */ + mac->ops.setup_led = e1000_setup_led_generic; + /* cleanup LED */ -+ mac->ops.cleanup_led = e1000_cleanup_led_generic; ++ mac->ops.cleanup_led = e1000e_cleanup_led_generic; + /* turn on/off LED */ + switch (hw->mac.type) { + case e1000_82574: ++ case e1000_82583: + mac->ops.led_on = e1000_led_on_82574; + break; + default: -+ mac->ops.led_on = e1000_led_on_generic; ++ mac->ops.led_on = e1000e_led_on_generic; + break; + } -+ mac->ops.led_off = e1000_led_off_generic; -+ /* remove device */ -+ mac->ops.remove_device = e1000_remove_device_generic; ++ mac->ops.led_off = e1000e_led_off_generic; + /* clear hardware counters */ + mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82571; + /* link info */ + mac->ops.get_link_up_info = + (hw->phy.media_type == e1000_media_type_copper) -+ ? e1000_get_speed_and_duplex_copper_generic -+ : e1000_get_speed_and_duplex_fiber_serdes_generic; ++ ? e1000e_get_speed_and_duplex_copper ++ : e1000e_get_speed_and_duplex_fiber_serdes; ++ ++ /* ++ * Ensure that the inter-port SWSM.SMBI lock bit is clear before ++ * first NVM or PHY acess. This should be done for single-port ++ * devices, and for one port only on dual-port devices so that ++ * for those devices we can still use the SMBI lock to synchronize ++ * inter-port accesses to the PHY & NVM. ++ */ ++ switch (hw->mac.type) { ++ case e1000_82571: ++ case e1000_82572: ++ swsm2 = er32(SWSM2); ++ ++ if (!(swsm2 & E1000_SWSM2_LOCK)) { ++ /* Only do this for the first interface on this card */ ++ ew32(SWSM2, ++ swsm2 | E1000_SWSM2_LOCK); ++ force_clear_smbi = true; ++ } else ++ force_clear_smbi = false; ++ break; ++ default: ++ force_clear_smbi = true; ++ break; ++ } + -+ hw->dev_spec_size = sizeof(struct e1000_dev_spec_82571); ++ if (force_clear_smbi) { ++ /* Make sure SWSM.SMBI is clear */ ++ swsm = er32(SWSM); ++ if (swsm & E1000_SWSM_SMBI) { ++ /* This bit should not be set on a first interface, and ++ * indicates that the bootagent or EFI code has ++ * improperly left this bit enabled ++ */ ++ e_dbg("Please update your 82571 Bootagent\n"); ++ } ++ ew32(SWSM, swsm & ~E1000_SWSM_SMBI); ++ } + -+ /* Device-specific structure allocation */ -+ ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size); ++ /* ++ * Initialze device specific counter of SMBI acquisition ++ * timeouts. ++ */ ++ hw->dev_spec._82571.smb_counter = 0; + +out: + return ret_val; @@ -2032,13 +2011,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + * e1000_init_function_pointers_82571 - Init func ptrs. + * @hw: pointer to the HW structure + * -+ * The only function explicitly called by the api module to initialize -+ * all function pointers and parameters. ++ * Called to initialize all function pointers and parameters. + **/ +void e1000_init_function_pointers_82571(struct e1000_hw *hw) +{ -+ DEBUGFUNC("e1000_init_function_pointers_82571"); -+ + e1000_init_mac_ops_generic(hw); + e1000_init_nvm_ops_generic(hw); + hw->mac.ops.init_params = e1000_init_mac_params_82571; @@ -2059,8 +2035,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + s32 ret_val = E1000_SUCCESS; + u16 phy_id = 0; + -+ DEBUGFUNC("e1000_get_phy_id_82571"); -+ + switch (hw->mac.type) { + case e1000_82571: + case e1000_82572: @@ -2073,16 +2047,17 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + phy->id = IGP01E1000_I_PHY_ID; + break; + case e1000_82573: -+ ret_val = e1000_get_phy_id(hw); ++ ret_val = e1000e_get_phy_id(hw); + break; + case e1000_82574: -+ ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); ++ case e1000_82583: ++ ret_val = e1e_rphy(hw, PHY_ID1, &phy_id); + if (ret_val) + goto out; + + phy->id = (u32)(phy_id << 16); -+ usec_delay(20); -+ ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id); ++ udelay(20); ++ ret_val = e1e_rphy(hw, PHY_ID2, &phy_id); + if (ret_val) + goto out; + @@ -2104,31 +2079,55 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + * + * Acquire the HW semaphore to access the PHY or NVM + **/ -+static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw) ++s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw) +{ + u32 swsm; + s32 ret_val = E1000_SUCCESS; -+ s32 timeout = hw->nvm.word_size + 1; ++ s32 sw_timeout = hw->nvm.word_size + 1; ++ s32 fw_timeout = hw->nvm.word_size + 1; + s32 i = 0; + -+ DEBUGFUNC("e1000_get_hw_semaphore_82571"); ++ /* ++ * If we have timedout 3 times on trying to acquire ++ * the inter-port SMBI semaphore, there is old code ++ * operating on the other port, and it is not ++ * releasing SMBI. Modify the number of times that ++ * we try for the semaphore to interwork with this ++ * older code. ++ */ ++ if (hw->dev_spec._82571.smb_counter > 2) ++ sw_timeout = 1; ++ ++ /* Get the SW semaphore */ ++ while (i < sw_timeout) { ++ swsm = er32(SWSM); ++ if (!(swsm & E1000_SWSM_SMBI)) ++ break; ++ ++ udelay(50); ++ i++; ++ } + ++ if (i == sw_timeout) { ++ e_dbg("Driver can't access device - SMBI bit is set.\n"); ++ hw->dev_spec._82571.smb_counter++; ++ } + /* Get the FW semaphore. */ -+ for (i = 0; i < timeout; i++) { -+ swsm = E1000_READ_REG(hw, E1000_SWSM); -+ E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI); ++ for (i = 0; i < fw_timeout; i++) { ++ swsm = er32(SWSM); ++ ew32(SWSM, swsm | E1000_SWSM_SWESMBI); + + /* Semaphore acquired if bit latched */ -+ if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI) ++ if (er32(SWSM) & E1000_SWSM_SWESMBI) + break; + -+ usec_delay(50); ++ udelay(50); + } + -+ if (i == timeout) { ++ if (i == fw_timeout) { + /* Release semaphores */ -+ e1000_put_hw_semaphore_generic(hw); -+ DEBUGOUT("Driver can't access the NVM\n"); ++ e1000_put_hw_semaphore_82571(hw); ++ e_dbg("Driver can't access the NVM\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } @@ -2143,19 +2142,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + * + * Release hardware semaphore used to access the PHY or NVM + **/ -+static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw) ++void e1000_put_hw_semaphore_82571(struct e1000_hw *hw) +{ + u32 swsm; + -+ DEBUGFUNC("e1000_put_hw_semaphore_82571"); -+ -+ swsm = E1000_READ_REG(hw, E1000_SWSM); -+ -+ swsm &= ~E1000_SWSM_SWESMBI; -+ -+ E1000_WRITE_REG(hw, E1000_SWSM, swsm); ++ swsm = er32(SWSM); ++ swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); ++ ew32(SWSM, swsm); +} -+ +/** + * e1000_acquire_nvm_82571 - Request for access to the EEPROM + * @hw: pointer to the HW structure @@ -2169,14 +2163,19 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive +{ + s32 ret_val; + -+ DEBUGFUNC("e1000_acquire_nvm_82571"); -+ + ret_val = e1000_get_hw_semaphore_82571(hw); + if (ret_val) + goto out; + -+ if (hw->mac.type != e1000_82573 && hw->mac.type != e1000_82574) -+ ret_val = e1000_acquire_nvm_generic(hw); ++ switch (hw->mac.type) { ++ case e1000_82574: ++ case e1000_82583: ++ case e1000_82573: ++ break; ++ default: ++ ret_val = e1000e_acquire_nvm(hw); ++ break; ++ } + + if (ret_val) + e1000_put_hw_semaphore_82571(hw); @@ -2193,9 +2192,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + **/ +static void e1000_release_nvm_82571(struct e1000_hw *hw) +{ -+ DEBUGFUNC("e1000_release_nvm_82571"); -+ -+ e1000_release_nvm_generic(hw); ++ e1000e_release_nvm(hw); + e1000_put_hw_semaphore_82571(hw); +} + @@ -2216,16 +2213,15 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive +{ + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_write_nvm_82571"); -+ + switch (hw->mac.type) { + case e1000_82573: + case e1000_82574: ++ case e1000_82583: + ret_val = e1000_write_nvm_eewr_82571(hw, offset, words, data); + break; + case e1000_82571: + case e1000_82572: -+ ret_val = e1000_write_nvm_spi(hw, offset, words, data); ++ ret_val = e1000e_write_nvm_spi(hw, offset, words, data); + break; + default: + ret_val = -E1000_ERR_NVM; @@ -2249,9 +2245,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + s32 ret_val; + u16 i; + -+ DEBUGFUNC("e1000_update_nvm_checksum_82571"); -+ -+ ret_val = e1000_update_nvm_checksum_generic(hw); ++ ret_val = e1000e_update_nvm_checksum_generic(hw); + if (ret_val) + goto out; + @@ -2264,8 +2258,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + + /* Check for pending operations. */ + for (i = 0; i < E1000_FLASH_UPDATES; i++) { -+ msec_delay(1); -+ if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_FLUPD) == 0) ++ msleep(1); ++ if ((er32(EECD) & E1000_EECD_FLUPD) == 0) + break; + } + @@ -2275,23 +2269,23 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + } + + /* Reset the firmware if using STM opcode. */ -+ if ((E1000_READ_REG(hw, E1000_FLOP) & 0xFF00) == E1000_STM_OPCODE) { ++ if ((er32(FLOP) & 0xFF00) == E1000_STM_OPCODE) { + /* + * The enabling of and the actual reset must be done + * in two write cycles. + */ -+ E1000_WRITE_REG(hw, E1000_HICR, E1000_HICR_FW_RESET_ENABLE); -+ E1000_WRITE_FLUSH(hw); -+ E1000_WRITE_REG(hw, E1000_HICR, E1000_HICR_FW_RESET); ++ ew32(HICR, E1000_HICR_FW_RESET_ENABLE); ++ e1e_flush(); ++ ew32(HICR, E1000_HICR_FW_RESET); + } + + /* Commit the write to flash */ -+ eecd = E1000_READ_REG(hw, E1000_EECD) | E1000_EECD_FLUPD; -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); ++ eecd = er32(EECD) | E1000_EECD_FLUPD; ++ ew32(EECD, eecd); + + for (i = 0; i < E1000_FLASH_UPDATES; i++) { -+ msec_delay(1); -+ if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_FLUPD) == 0) ++ msleep(1); ++ if ((er32(EECD) & E1000_EECD_FLUPD) == 0) + break; + } + @@ -2313,12 +2307,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + **/ +static s32 e1000_validate_nvm_checksum_82571(struct e1000_hw *hw) +{ -+ DEBUGFUNC("e1000_validate_nvm_checksum_82571"); -+ + if (hw->nvm.type == e1000_nvm_flash_hw) + e1000_fix_nvm_checksum_82571(hw); + -+ return e1000_validate_nvm_checksum_generic(hw); ++ return e1000e_validate_nvm_checksum_generic(hw); +} + +/** @@ -2342,15 +2334,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + u32 i, eewr = 0; + s32 ret_val = 0; + -+ DEBUGFUNC("e1000_write_nvm_eewr_82571"); -+ + /* + * 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"); ++ e_dbg("nvm parameter(s) out of bounds\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } @@ -2360,13 +2350,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) | + E1000_NVM_RW_REG_START; + -+ ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE); ++ ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE); + if (ret_val) + break; + -+ E1000_WRITE_REG(hw, E1000_EEWR, eewr); ++ ew32(EEWR, eewr); + -+ ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE); ++ ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE); + if (ret_val) + break; + } @@ -2386,16 +2376,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + s32 timeout = PHY_CFG_TIMEOUT; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_get_cfg_done_82571"); -+ + while (timeout) { -+ if (E1000_READ_REG(hw, E1000_EEMNGCTL) & E1000_NVM_CFG_DONE_PORT_0) ++ if (er32(EEMNGCTL) & E1000_NVM_CFG_DONE_PORT_0) + break; -+ msec_delay(1); ++ msleep(1); + timeout--; + } + if (!timeout) { -+ DEBUGOUT("MNG configuration cycle has not completed.\n"); ++ e_dbg("MNG configuration cycle has not completed.\n"); + ret_val = -E1000_ERR_RESET; + goto out; + } @@ -2421,33 +2409,31 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + s32 ret_val = E1000_SUCCESS; + u16 data; + -+ DEBUGFUNC("e1000_set_d0_lplu_state_82571"); -+ + if (!(phy->ops.read_reg)) + goto out; + -+ ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); ++ ret_val = e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &data); + if (ret_val) + goto out; + + if (active) { + data |= IGP02E1000_PM_D0_LPLU; -+ ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, ++ ret_val = e1e_wphy(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, ++ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, + &data); + data &= ~IGP01E1000_PSCFR_SMART_SPEED; -+ ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, ++ ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, + data); + if (ret_val) + goto out; + } else { + data &= ~IGP02E1000_PM_D0_LPLU; -+ ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, ++ ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, + data); + /* + * LPLU and SmartSpeed are mutually exclusive. LPLU is used @@ -2456,27 +2442,27 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + * SmartSpeed, so performance is maintained. + */ + if (phy->smart_speed == e1000_smart_speed_on) { -+ ret_val = phy->ops.read_reg(hw, ++ ret_val = e1e_rphy(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); + if (ret_val) + goto out; + + data |= IGP01E1000_PSCFR_SMART_SPEED; -+ ret_val = phy->ops.write_reg(hw, ++ ret_val = e1e_wphy(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, ++ ret_val = e1e_rphy(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); + if (ret_val) + goto out; + + data &= ~IGP01E1000_PSCFR_SMART_SPEED; -+ ret_val = phy->ops.write_reg(hw, ++ ret_val = e1e_wphy(hw, + IGP01E1000_PHY_PORT_CONFIG, + data); + if (ret_val) @@ -2492,8 +2478,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + * e1000_reset_hw_82571 - Reset hardware + * @hw: pointer to the HW structure + * -+ * This resets the hardware into a known state. This is a -+ * function pointer entry point called by the api module. ++ * This resets the hardware into a known state. + **/ +static s32 e1000_reset_hw_82571(struct e1000_hw *hw) +{ @@ -2501,62 +2486,65 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + s32 ret_val; + u16 i = 0; + -+ DEBUGFUNC("e1000_reset_hw_82571"); -+ + /* + * Prevent the PCI-E bus from sticking if there is no TLP connection + * on the last TLP read/write transaction when MAC is reset. + */ -+ ret_val = e1000_disable_pcie_master_generic(hw); -+ if (ret_val) { -+ DEBUGOUT("PCI-E Master disable polling has failed.\n"); -+ } ++ ret_val = e1000e_disable_pcie_master(hw); ++ if (ret_val) ++ e_dbg("PCI-E Master disable polling has failed.\n"); + -+ DEBUGOUT("Masking off all interrupts\n"); -+ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); ++ e_dbg("Masking off all interrupts\n"); ++ ew32(IMC, 0xffffffff); + -+ E1000_WRITE_REG(hw, E1000_RCTL, 0); -+ E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); -+ E1000_WRITE_FLUSH(hw); ++ ew32(RCTL, 0); ++ ew32(TCTL, E1000_TCTL_PSP); ++ e1e_flush(); + -+ msec_delay(10); ++ msleep(10); + + /* + * Must acquire the MDIO ownership before MAC reset. + * Ownership defaults to firmware after a reset. + */ -+ if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) { -+ extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); ++ switch (hw->mac.type) { ++ case e1000_82574: ++ case e1000_82583: ++ case e1000_82573: ++ extcnf_ctrl = er32(EXTCNF_CTRL); + extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; + + do { -+ E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); -+ extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); ++ ew32(EXTCNF_CTRL, extcnf_ctrl); ++ extcnf_ctrl = er32(EXTCNF_CTRL); + + if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP) + break; + + extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; + -+ msec_delay(2); ++ msleep(2); + i++; + } while (i < MDIO_OWNERSHIP_TIMEOUT); ++ break; ++ default: ++ break; + } + -+ ctrl = E1000_READ_REG(hw, E1000_CTRL); ++ ctrl = er32(CTRL); + -+ DEBUGOUT("Issuing a global reset to MAC\n"); -+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); ++ e_dbg("Issuing a global reset to MAC\n"); ++ ew32(CTRL, ctrl | E1000_CTRL_RST); + + if (hw->nvm.type == e1000_nvm_flash_hw) { -+ usec_delay(10); -+ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ++ udelay(10); ++ ctrl_ext = er32(CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_EE_RST; -+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); -+ E1000_WRITE_FLUSH(hw); ++ ew32(CTRL_EXT, ctrl_ext); ++ e1e_flush(); + } + -+ ret_val = e1000_get_auto_rd_done_generic(hw); ++ ret_val = e1000e_get_auto_rd_done(hw); + if (ret_val) + /* We don't want to continue accessing MAC registers. */ + goto out; @@ -2566,15 +2554,31 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + * Need to wait for Phy configuration completion before accessing + * NVM and Phy. + */ -+ if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) -+ msec_delay(25); ++ ++ switch (hw->mac.type) { ++ case e1000_82574: ++ case e1000_82583: ++ case e1000_82573: ++ msleep(25); ++ break; ++ default: ++ break; ++ } + + /* Clear any pending interrupt events. */ -+ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); -+ icr = E1000_READ_REG(hw, E1000_ICR); ++ ew32(IMC, 0xffffffff); ++ icr = er32(ICR); ++ ++ /* Install any alternate MAC address into RAR0 */ ++ ret_val = e1000_check_alt_mac_addr_generic(hw); ++ if (ret_val) ++ goto out; ++ ++ e1000e_set_laa_state_82571(hw, true); + -+ if (!(e1000_check_alt_mac_addr_generic(hw))) -+ e1000_set_laa_state_82571(hw, true); ++ /* Reinitialize the 82571 serdes link state machine */ ++ if (hw->phy.media_type == e1000_media_type_internal_serdes) ++ hw->mac.serdes_link_state = e1000_serdes_link_down; + +out: + return ret_val; @@ -2593,20 +2597,18 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + s32 ret_val; + u16 i, rar_count = mac->rar_entry_count; + -+ DEBUGFUNC("e1000_init_hw_82571"); -+ + e1000_initialize_hw_bits_82571(hw); + + /* 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"); ++ e_dbg("Error initializing identification LED\n"); + /* This is not fatal and we should not stop init due to this */ + } + + /* Disabling VLAN filtering */ -+ DEBUGOUT("Initializing the IEEE VLAN\n"); -+ mac->ops.clear_vfta(hw); ++ e_dbg("Initializing the IEEE VLAN\n"); ++ e1000e_clear_vfta(hw); + + /* Setup the receive address. */ + /* @@ -2614,12 +2616,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + * 82571, we must reserve a RAR for it to work around an issue where + * resetting one port will reload the MAC on the other port. + */ -+ if (e1000_get_laa_state_82571(hw)) ++ if (e1000e_get_laa_state_82571(hw)) + rar_count--; -+ e1000_init_rx_addrs_generic(hw, rar_count); ++ e1000e_init_rx_addrs(hw, rar_count); + + /* Zero out the Multicast HASH table */ -+ DEBUGOUT("Zeroing the MTA\n"); ++ e_dbg("Zeroing the MTA\n"); + for (i = 0; i < mac->mta_reg_count; i++) + E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); + @@ -2627,24 +2629,29 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + ret_val = mac->ops.setup_link(hw); + + /* Set the transmit descriptor write-back policy */ -+ reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0)); ++ reg_data = er32(TXDCTL(0)); + reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | + E1000_TXDCTL_FULL_TX_DESC_WB | + E1000_TXDCTL_COUNT_DESC; -+ E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data); ++ ew32(TXDCTL(0), reg_data); + + /* ...for both queues. */ -+ if (mac->type != e1000_82573 && mac->type != e1000_82574) { -+ reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1)); -+ reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | -+ E1000_TXDCTL_FULL_TX_DESC_WB | -+ E1000_TXDCTL_COUNT_DESC; -+ E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data); -+ } else { -+ e1000_enable_tx_pkt_filtering_generic(hw); -+ reg_data = E1000_READ_REG(hw, E1000_GCR); ++ switch (mac->type) { ++ case e1000_82574: ++ case e1000_82583: ++ case e1000_82573: ++ e1000e_enable_tx_pkt_filtering(hw); ++ reg_data = er32(GCR); + reg_data |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX; -+ E1000_WRITE_REG(hw, E1000_GCR, reg_data); ++ ew32(GCR, reg_data); ++ break; ++ default: ++ reg_data = er32(TXDCTL(1)); ++ reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | ++ E1000_TXDCTL_FULL_TX_DESC_WB | ++ E1000_TXDCTL_COUNT_DESC; ++ ew32(TXDCTL(1), reg_data); ++ break; + } + + /* @@ -2668,23 +2675,18 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive +{ + u32 reg; + -+ DEBUGFUNC("e1000_initialize_hw_bits_82571"); -+ -+ if (hw->mac.disable_hw_init_bits) -+ goto out; -+ + /* Transmit Descriptor Control 0 */ -+ reg = E1000_READ_REG(hw, E1000_TXDCTL(0)); ++ reg = er32(TXDCTL(0)); + reg |= (1 << 22); -+ E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg); ++ ew32(TXDCTL(0), reg); + + /* Transmit Descriptor Control 1 */ -+ reg = E1000_READ_REG(hw, E1000_TXDCTL(1)); ++ reg = er32(TXDCTL(1)); + reg |= (1 << 22); -+ E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg); ++ ew32(TXDCTL(1), reg); + + /* Transmit Arbitration Control 0 */ -+ reg = E1000_READ_REG(hw, E1000_TARC(0)); ++ reg = er32(TARC(0)); + reg &= ~(0xF << 27); /* 30:27 */ + switch (hw->mac.type) { + case e1000_82571: @@ -2694,48 +2696,95 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + default: + break; + } -+ E1000_WRITE_REG(hw, E1000_TARC(0), reg); ++ ew32(TARC(0), reg); + + /* Transmit Arbitration Control 1 */ -+ reg = E1000_READ_REG(hw, E1000_TARC(1)); ++ reg = er32(TARC(1)); + switch (hw->mac.type) { + case e1000_82571: + case e1000_82572: + reg &= ~((1 << 29) | (1 << 30)); + reg |= (1 << 22) | (1 << 24) | (1 << 25) | (1 << 26); -+ if (E1000_READ_REG(hw, E1000_TCTL) & E1000_TCTL_MULR) ++ if (er32(TCTL) & E1000_TCTL_MULR) + reg &= ~(1 << 28); + else + reg |= (1 << 28); -+ E1000_WRITE_REG(hw, E1000_TARC(1), reg); ++ ew32(TARC(1), reg); + break; + default: + break; + } + + /* Device Control */ -+ if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) { -+ reg = E1000_READ_REG(hw, E1000_CTRL); ++ ++ switch (hw->mac.type) { ++ case e1000_82574: ++ case e1000_82583: ++ case e1000_82573: ++ reg = er32(CTRL); + reg &= ~(1 << 29); -+ E1000_WRITE_REG(hw, E1000_CTRL, reg); ++ ew32(CTRL, reg); ++ break; ++ default: ++ break; + } + + /* Extended Device Control */ -+ if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) { -+ reg = E1000_READ_REG(hw, E1000_CTRL_EXT); ++ switch (hw->mac.type) { ++ case e1000_82574: ++ case e1000_82583: ++ case e1000_82573: ++ reg = er32(CTRL_EXT); + reg &= ~(1 << 23); + reg |= (1 << 22); -+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); ++ ew32(CTRL_EXT, reg); ++ break; ++ default: ++ break; + } + -+ /* PCI-Ex Control Register */ -+ if (hw->mac.type == e1000_82574) { -+ reg = E1000_READ_REG(hw, E1000_GCR); ++ ++ if (hw->mac.type == e1000_82571) { ++ reg = er32(PBA_ECC); ++ reg |= E1000_PBA_ECC_CORR_EN; ++ ew32(PBA_ECC, reg); ++ } ++ ++ /* ++ * Workaround for hardware errata. ++ * Ensure that DMA Dynamic Clock gating is disabled on 82571 and 82572 ++ */ ++ ++ if ((hw->mac.type == e1000_82571) || ++ (hw->mac.type == e1000_82572)) { ++ reg = er32(CTRL_EXT); ++ reg &= ~E1000_CTRL_EXT_DMA_DYN_CLK_EN; ++ ew32(CTRL_EXT, reg); ++ } ++ ++ /* PCI-Ex Control Registers */ ++ ++ switch (hw->mac.type) { ++ case e1000_82574: ++ case e1000_82583: ++ reg = er32(GCR); + reg |= (1 << 22); -+ E1000_WRITE_REG(hw, E1000_GCR, reg); ++ ew32(GCR, reg); ++ /* ++ * Workaround for hardware errata. ++ * apply workaround for hardware errata documented in errata ++ * docs Fixes issue where some error prone or unreliable PCIe ++ * completions are occurring, particularly with ASPM enabled. ++ * Without fix, issue can cause tx timeouts. ++ */ ++ reg = er32(GCR2); ++ reg |= 1; ++ ew32(GCR2, reg); ++ break; ++ default: ++ break; + } + -+out: + return; +} + @@ -2753,33 +2802,39 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + u32 vfta_offset = 0; + u32 vfta_bit_in_reg = 0; + -+ DEBUGFUNC("e1000_clear_vfta_82571"); -+ -+ if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) { ++ switch (hw->mac.type) { ++ case e1000_82574: ++ case e1000_82583: ++ case e1000_82573: + if (hw->mng_cookie.vlan_id != 0) { + /* -+ * The VFTA is a 4096b bit-field, each identifying -+ * a single VLAN ID. The following operations -+ * determine which 32b entry (i.e. offset) into the -+ * array we want to set the VLAN ID (i.e. bit) of -+ * the manageability unit. -+ */ ++ *The VFTA is a 4096b bit-field, each identifying ++ *a single VLAN ID. The following operations ++ *determine which 32b entry (i.e. offset) into the ++ *array we want to set the VLAN ID (i.e. bit) of ++ *the manageability unit. ++ */ + vfta_offset = (hw->mng_cookie.vlan_id >> -+ E1000_VFTA_ENTRY_SHIFT) & -+ E1000_VFTA_ENTRY_MASK; ++ E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK; + vfta_bit_in_reg = 1 << (hw->mng_cookie.vlan_id & -+ E1000_VFTA_ENTRY_BIT_SHIFT_MASK); ++ E1000_VFTA_ENTRY_BIT_SHIFT_MASK); + } -+ } -+ for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { -+ /* -+ * If the offset we want to clear is the same offset of the -+ * manageability VLAN ID, then clear all bits except that of -+ * the manageability unit. -+ */ -+ vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0; -+ E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, vfta_value); -+ E1000_WRITE_FLUSH(hw); ++ ++ for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { ++ /* ++ *If the offset we want to clear is the same offset of ++ *the manageability VLAN ID, then clear all bits except ++ *that of the manageability unit ++ */ ++ vfta_value = (offset == vfta_offset) ? ++ vfta_bit_in_reg : 0; ++ E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, ++ vfta_value); ++ e1e_flush(); ++ } ++ break; ++ default: ++ break; + } +} + @@ -2794,16 +2849,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive +{ + u16 data; + -+ DEBUGFUNC("e1000_check_mng_mode_82574"); -+ -+ hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &data); -+ return ((data & E1000_NVM_INIT_CTRL2_MNGM) != 0); ++ e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data); ++ return (data & E1000_NVM_INIT_CTRL2_MNGM) != 0; +} + +/** + * e1000_led_on_82574 - Turn LED on + * @hw: pointer to the HW structure -+ * ++ * + * Turn LED on. + **/ +static s32 e1000_led_on_82574(struct e1000_hw *hw) @@ -2811,12 +2864,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + u32 ctrl; + u32 i; + -+ DEBUGFUNC("e1000_led_on_82574"); -+ + ctrl = hw->mac.ledctl_mode2; -+ if (!(E1000_STATUS_LU & E1000_READ_REG(hw, E1000_STATUS))) { -+ /* -+ * If no link, then turn LED on by setting the invert bit ++ if (!(E1000_STATUS_LU & er32(STATUS))) { ++ /* ++ * If no link, then turn LED on by setting the invert bit + * for each LED that's "on" (0x0E) in ledctl_mode2. + */ + for (i = 0; i < 4; i++) @@ -2824,36 +2875,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + E1000_LEDCTL_MODE_LED_ON) + ctrl |= (E1000_LEDCTL_LED0_IVRT << (i * 8)); + } -+ E1000_WRITE_REG(hw, E1000_LEDCTL, ctrl); ++ ew32(LEDCTL, ctrl); + + return E1000_SUCCESS; +} + -+/** -+ * e1000_update_mc_addr_list_82571 - 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_82571(struct e1000_hw *hw, -+ u8 *mc_addr_list, u32 mc_addr_count, -+ u32 rar_used_count, u32 rar_count) -+{ -+ DEBUGFUNC("e1000_update_mc_addr_list_82571"); -+ -+ if (e1000_get_laa_state_82571(hw)) -+ rar_count--; -+ -+ e1000_update_mc_addr_list_generic(hw, mc_addr_list, mc_addr_count, -+ rar_used_count, rar_count); -+} + +/** + * e1000_setup_link_82571 - Setup flow control and link settings @@ -2867,19 +2893,23 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + **/ +static s32 e1000_setup_link_82571(struct e1000_hw *hw) +{ -+ DEBUGFUNC("e1000_setup_link_82571"); -+ + /* + * 82573 does not have a word in the NVM to determine + * the default flow control setting, so we explicitly + * set it to full. + */ -+ if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) && -+ hw->fc.type == e1000_fc_default) -+ hw->fc.type = e1000_fc_full; -+ -+ return e1000_setup_link_generic(hw); -+} ++ switch (hw->mac.type) { ++ case e1000_82574: ++ case e1000_82583: ++ case e1000_82573: ++ if (hw->fc.requested_mode == e1000_fc_default) ++ hw->fc.requested_mode = e1000_fc_full; ++ break; ++ default: ++ break; ++ } ++ return e1000e_setup_link(hw); ++} + +/** + * e1000_setup_copper_link_82571 - Configure copper link settings @@ -2891,28 +2921,21 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + **/ +static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw) +{ -+ u32 ctrl, led_ctrl; ++ u32 ctrl; + s32 ret_val; + -+ DEBUGFUNC("e1000_setup_copper_link_82571"); -+ -+ ctrl = E1000_READ_REG(hw, E1000_CTRL); ++ ctrl = er32(CTRL); + ctrl |= E1000_CTRL_SLU; + ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); -+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ++ ew32(CTRL, ctrl); + + switch (hw->phy.type) { + case e1000_phy_m88: + case e1000_phy_bm: -+ ret_val = e1000_copper_link_setup_m88(hw); ++ ret_val = e1000e_copper_link_setup_m88(hw); + break; + case e1000_phy_igp_2: -+ 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); ++ ret_val = e1000e_copper_link_setup_igp(hw); + break; + default: + ret_val = -E1000_ERR_PHY; @@ -2922,7 +2945,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + if (ret_val) + goto out; + -+ ret_val = e1000_setup_copper_link_generic(hw); ++ ret_val = e1000e_setup_copper_link(hw); + +out: + return ret_val; @@ -2937,8 +2960,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + **/ +static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw) +{ -+ DEBUGFUNC("e1000_setup_fiber_serdes_link_82571"); -+ + switch (hw->mac.type) { + case e1000_82571: + case e1000_82572: @@ -2949,13 +2970,158 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + * mode. This prevents drivers from twiddling their thumbs + * if another tool failed to take it out of loopback mode. + */ -+ E1000_WRITE_REG(hw, E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); ++ ew32(SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); + break; + default: + break; + } + -+ return e1000_setup_fiber_serdes_link_generic(hw); ++ return e1000e_setup_fiber_serdes_link(hw); ++} ++ ++/** ++ * e1000_check_for_serdes_link_82571 - Check for link (Serdes) ++ * @hw: pointer to the HW structure ++ * ++ * Reports the link state as up or down. ++ * ++ * If autonegotiation is supported by the link partner, the link state is ++ * determined by the result of autongotiation. This is the most likely case. ++ * If autonegotiation is not supported by the link partner, and the link ++ * has a valid signal, force the link up. ++ * ++ * The link state is represented internally here by 4 states: ++ * ++ * 1) down ++ * 2) autoneg_progress ++ * 3) autoneg_complete (the link sucessfully autonegotiated) ++ * 4) forced_up (the link has been forced up, it did not autonegotiate) ++ * ++ **/ ++s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) ++{ ++ struct e1000_mac_info *mac = &hw->mac; ++ u32 rxcw; ++ u32 ctrl; ++ u32 status; ++ s32 ret_val = E1000_SUCCESS; ++ ++ ctrl = er32(CTRL); ++ status = er32(STATUS); ++ rxcw = er32(RXCW); ++ ++ if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) { ++ ++ /* Receiver is synchronized with no invalid bits. */ ++ switch (mac->serdes_link_state) { ++ case e1000_serdes_link_autoneg_complete: ++ if (!(status & E1000_STATUS_LU)) { ++ /* ++ * We have lost link, retry autoneg before ++ * reporting link failure ++ */ ++ mac->serdes_link_state = ++ e1000_serdes_link_autoneg_progress; ++ mac->serdes_has_link = false; ++ e_dbg("AN_UP -> AN_PROG\n"); ++ } ++ break; ++ ++ case e1000_serdes_link_forced_up: ++ /* ++ * If we are receiving /C/ ordered sets, re-enable ++ * auto-negotiation in the TXCW register and disable ++ * forced link in the Device Control register in an ++ * attempt to auto-negotiate with our link partner. ++ */ ++ if (rxcw & E1000_RXCW_C) { ++ /* Enable autoneg, and unforce link up */ ++ ew32(TXCW, mac->txcw); ++ ew32(CTRL, ++ (ctrl & ~E1000_CTRL_SLU)); ++ mac->serdes_link_state = ++ e1000_serdes_link_autoneg_progress; ++ mac->serdes_has_link = false; ++ e_dbg("FORCED_UP -> AN_PROG\n"); ++ } ++ break; ++ ++ case e1000_serdes_link_autoneg_progress: ++ if (rxcw & E1000_RXCW_C) { ++ /* We received /C/ ordered sets, meaning the ++ * link partner has autonegotiated, and we can ++ * trust the Link Up (LU) status bit ++ */ ++ if (status & E1000_STATUS_LU) { ++ mac->serdes_link_state = ++ e1000_serdes_link_autoneg_complete; ++ e_dbg("AN_PROG -> AN_UP\n"); ++ mac->serdes_has_link = true; ++ } else { ++ /* Autoneg completed, but failed */ ++ mac->serdes_link_state = ++ e1000_serdes_link_down; ++ e_dbg("AN_PROG -> DOWN\n"); ++ } ++ } else { ++ /* The link partner did not autoneg. ++ * Force link up and full duplex, and change ++ * state to forced. ++ */ ++ ew32(TXCW, ++ (mac->txcw & ~E1000_TXCW_ANE)); ++ ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); ++ ew32(CTRL, ctrl); ++ ++ /* Configure Flow Control after link up. */ ++ ret_val = ++ e1000e_config_fc_after_link_up(hw); ++ if (ret_val) { ++ e_dbg("Error config flow control\n"); ++ break; ++ } ++ mac->serdes_link_state = ++ e1000_serdes_link_forced_up; ++ mac->serdes_has_link = true; ++ e_dbg("AN_PROG -> FORCED_UP\n"); ++ } ++ break; ++ ++ case e1000_serdes_link_down: ++ default: ++ /* The link was down but the receiver has now gained ++ * valid sync, so lets see if we can bring the link ++ * up. */ ++ ew32(TXCW, mac->txcw); ++ ew32(CTRL, ++ (ctrl & ~E1000_CTRL_SLU)); ++ mac->serdes_link_state = ++ e1000_serdes_link_autoneg_progress; ++ e_dbg("DOWN -> AN_PROG\n"); ++ break; ++ } ++ } else { ++ if (!(rxcw & E1000_RXCW_SYNCH)) { ++ mac->serdes_has_link = false; ++ mac->serdes_link_state = e1000_serdes_link_down; ++ e_dbg("ANYSTATE -> DOWN\n"); ++ } else { ++ /* ++ * We have sync, and can tolerate one ++ * invalid (IV) codeword before declaring ++ * link down, so reread to look again ++ */ ++ udelay(10); ++ rxcw = er32(RXCW); ++ if (rxcw & E1000_RXCW_IV) { ++ mac->serdes_link_state = e1000_serdes_link_down; ++ mac->serdes_has_link = false; ++ e_dbg("ANYSTATE -> DOWN\n"); ++ } ++ } ++ } ++ ++ return ret_val; +} + +/** @@ -2970,69 +3136,60 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive +{ + s32 ret_val; + -+ DEBUGFUNC("e1000_valid_led_default_82571"); -+ -+ ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); ++ ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data); + if (ret_val) { -+ DEBUGOUT("NVM Read Error\n"); ++ e_dbg("NVM Read Error\n"); + goto out; + } + -+ if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) && -+ *data == ID_LED_RESERVED_F746) -+ *data = ID_LED_DEFAULT_82573; -+ else if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) -+ *data = ID_LED_DEFAULT; ++ switch (hw->mac.type) { ++ case e1000_82574: ++ case e1000_82583: ++ case e1000_82573: ++ if(*data == ID_LED_RESERVED_F746) ++ *data = ID_LED_DEFAULT_82573; ++ break; ++ default: ++ if (*data == ID_LED_RESERVED_0000 || ++ *data == ID_LED_RESERVED_FFFF) ++ *data = ID_LED_DEFAULT; ++ break; ++ } ++ +out: + return ret_val; +} + +/** -+ * e1000_get_laa_state_82571 - Get locally administered address state ++ * e1000e_get_laa_state_82571 - Get locally administered address state + * @hw: pointer to the HW structure + * + * Retrieve and return the current locally administered address state. + **/ -+bool e1000_get_laa_state_82571(struct e1000_hw *hw) ++bool e1000e_get_laa_state_82571(struct e1000_hw *hw) +{ -+ struct e1000_dev_spec_82571 *dev_spec; -+ bool state = false; -+ -+ DEBUGFUNC("e1000_get_laa_state_82571"); -+ + if (hw->mac.type != e1000_82571) -+ goto out; -+ -+ dev_spec = (struct e1000_dev_spec_82571 *)hw->dev_spec; ++ return false; + -+ state = dev_spec->laa_is_present; -+ -+out: -+ return state; ++ return hw->dev_spec._82571.laa_is_present; +} + +/** -+ * e1000_set_laa_state_82571 - Set locally administered address state ++ * e1000e_set_laa_state_82571 - Set locally administered address state + * @hw: pointer to the HW structure + * @state: enable/disable locally administered address + * + * Enable/Disable the current locally administered address state. + **/ -+void e1000_set_laa_state_82571(struct e1000_hw *hw, bool state) ++void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state) +{ -+ struct e1000_dev_spec_82571 *dev_spec; -+ -+ DEBUGFUNC("e1000_set_laa_state_82571"); -+ + if (hw->mac.type != e1000_82571) -+ goto out; -+ -+ dev_spec = (struct e1000_dev_spec_82571 *)hw->dev_spec; ++ return; + -+ dev_spec->laa_is_present = state; ++ hw->dev_spec._82571.laa_is_present = state; + + /* If workaround is activated... */ -+ if (state) { ++ if (state) + /* + * Hold a copy of the LAA in RAR[14] This is done so that + * between the time RAR[0] gets clobbered and the time it @@ -3040,11 +3197,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + * incoming packets directed to this port are dropped. + * Eventually the LAA will be in RAR[0] and RAR[14]. + */ -+ e1000_rar_set_generic(hw, hw->mac.addr, ++ e1000e_rar_set(hw, hw->mac.addr, + hw->mac.rar_entry_count - 1); -+ } -+ -+out: + return; +} + @@ -3064,8 +3218,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + s32 ret_val = E1000_SUCCESS; + u16 data; + -+ DEBUGFUNC("e1000_fix_nvm_checksum_82571"); -+ + if (nvm->type != e1000_nvm_flash_hw) + goto out; + @@ -3073,7 +3225,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + * Check bit 4 of word 10h. If it is 0, firmware is done updating + * 10h-12h. Checksum may need to be fixed. + */ -+ ret_val = nvm->ops.read(hw, 0x10, 1, &data); ++ ret_val = e1000_read_nvm(hw, 0x10, 1, &data); + if (ret_val) + goto out; + @@ -3086,16 +3238,16 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + * we need to set this bit to a 1 and update the + * checksum. + */ -+ ret_val = nvm->ops.read(hw, 0x23, 1, &data); ++ ret_val = e1000_read_nvm(hw, 0x23, 1, &data); + if (ret_val) + goto out; + + if (!(data & 0x8000)) { + data |= 0x8000; -+ ret_val = nvm->ops.write(hw, 0x23, 1, &data); ++ ret_val = e1000_write_nvm(hw, 0x23, 1, &data); + if (ret_val) + goto out; -+ ret_val = nvm->ops.update(hw); ++ ret_val = e1000e_update_nvm_checksum(hw); + } + } + @@ -3103,6 +3255,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + return ret_val; +} + ++ +/** + * e1000_read_mac_addr_82571 - Read device MAC address + * @hw: pointer to the HW structure @@ -3111,10 +3264,18 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive +{ + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_read_mac_addr_82571"); -+ 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 = e1000e_read_mac_addr_generic(hw); + ++out: + return ret_val; +} + @@ -3134,7 +3295,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + return; + + /* If the management interface is not enabled, then power down */ -+ if (!(mac->ops.check_mng_mode(hw) || phy->ops.check_reset_block(hw))) ++ if (!(mac->ops.check_mng_mode(hw) || e1000_check_reset_block(hw))) + e1000_power_down_phy_copper(hw); + + return; @@ -3148,54 +3309,51 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.c linux-2.6.22-10/drive + **/ +static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw) +{ -+ volatile u32 temp; -+ -+ DEBUGFUNC("e1000_clear_hw_cntrs_82571"); -+ -+ 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); ++ e1000e_clear_hw_cntrs_base(hw); ++ ++ er32(PRC64); ++ er32(PRC127); ++ er32(PRC255); ++ er32(PRC511); ++ er32(PRC1023); ++ er32(PRC1522); ++ er32(PTC64); ++ er32(PTC127); ++ er32(PTC255); ++ er32(PTC511); ++ er32(PTC1023); ++ er32(PTC1522); ++ ++ er32(ALGNERRC); ++ er32(RXERRC); ++ er32(TNCRS); ++ er32(CEXTERR); ++ er32(TSCTC); ++ er32(TSCTFC); ++ ++ er32(MGTPRC); ++ er32(MGTPDC); ++ er32(MGTPTC); ++ ++ er32(IAC); ++ er32(ICRXOC); ++ ++ er32(ICRXPTC); ++ er32(ICRXATC); ++ er32(ICTXPTC); ++ er32(ICTXATC); ++ er32(ICTXQEC); ++ er32(ICTXQMTC); ++ er32(ICRXDMTC); +} diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.h linux-2.6.22-10/drivers/net/e1000e/e1000_82571.h --- linux-2.6.22-0/drivers/net/e1000e/e1000_82571.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000_82571.h 2008-10-14 01:51:32.000000000 +0200 ++++ linux-2.6.22-10/drivers/net/e1000e/e1000_82571.h 2009-06-24 00:32:20.000000000 +0200 @@ -0,0 +1,53 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -3241,18 +3399,18 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_82571.h linux-2.6.22-10/drive + +#define E1000_RXCFGL 0x0B634 /* TimeSync Rx EtherType & Msg Type Reg - RW */ + -+bool e1000_get_laa_state_82571(struct e1000_hw *hw); -+void e1000_set_laa_state_82571(struct e1000_hw *hw, bool state); ++bool e1000e_get_laa_state_82571(struct e1000_hw *hw); ++void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state); + +#endif diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/drivers/net/e1000e/e1000_defines.h --- linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000_defines.h 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,1437 @@ ++++ linux-2.6.22-10/drivers/net/e1000e/e1000_defines.h 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,1466 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -3304,22 +3462,30 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ +#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */ +#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */ -+#define E1000_WUFC_IGNORE_TCO_BM 0x00000800 /* Ignore WakeOn TCO packets */ -+#define E1000_WUFC_FLX0_BM 0x00001000 /* Flexible Filter 0 Enable */ -+#define E1000_WUFC_FLX1_BM 0x00002000 /* Flexible Filter 1 Enable */ -+#define E1000_WUFC_FLX2_BM 0x00004000 /* Flexible Filter 2 Enable */ -+#define E1000_WUFC_FLX3_BM 0x00008000 /* Flexible Filter 3 Enable */ ++#define E1000_WUFC_IGNORE_TCO_PHY 0x00000800 /* Ignore WakeOn TCO packets */ ++#define E1000_WUFC_FLX0_PHY 0x00001000 /* Flexible Filter 0 Enable */ ++#define E1000_WUFC_FLX1_PHY 0x00002000 /* Flexible Filter 1 Enable */ ++#define E1000_WUFC_FLX2_PHY 0x00004000 /* Flexible Filter 2 Enable */ ++#define E1000_WUFC_FLX3_PHY 0x00008000 /* Flexible Filter 3 Enable */ ++#define E1000_WUFC_FLX4_PHY 0x00000200 /* Flexible Filter 4 Enable */ ++#define E1000_WUFC_FLX5_PHY 0x00000400 /* Flexible Filter 5 Enable */ +#define E1000_WUFC_IGNORE_TCO 0x00008000 /* Ignore WakeOn TCO packets */ +#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */ +#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */ +#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */ +#define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */ -+#define E1000_WUFC_ALL_FILTERS_BM 0x0000F0FF /* Mask for all wakeup filters */ -+#define E1000_WUFC_FLX_OFFSET_BM 12 /* Offset to the Flexible Filters bits */ -+#define E1000_WUFC_FLX_FILTERS_BM 0x0000F000 /* Mask for the 4 flexible filters */ ++#define E1000_WUFC_FLX4 0x00100000 /* Flexible Filter 4 Enable */ ++#define E1000_WUFC_FLX5 0x00200000 /* Flexible Filter 5 Enable */ ++#define E1000_WUFC_ALL_FILTERS_PHY_4 0x0000F0FF /*Mask for all wakeup filters*/ ++#define E1000_WUFC_FLX_OFFSET_PHY 12 /* Offset to the Flexible Filters bits */ ++#define E1000_WUFC_FLX_FILTERS_PHY_4 0x0000F000 /*Mask for 4 flexible filters*/ ++#define E1000_WUFC_ALL_FILTERS_PHY_6 0x0000F6FF /*Mask for 6 wakeup filters */ ++#define E1000_WUFC_FLX_FILTERS_PHY_6 0x0000F600 /*Mask for 6 flexible filters*/ +#define E1000_WUFC_ALL_FILTERS 0x000F00FF /* Mask for all wakeup filters */ ++#define E1000_WUFC_ALL_FILTERS_6 0x003F00FF /* Mask for all 6 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 */ ++#define E1000_WUFC_FLX_FILTERS_6 0x003F0000 /* Mask for 6 flexible filters */ + +/* Wake Up Status */ +#define E1000_WUS_LNKC E1000_WUFC_LNKC @@ -3330,27 +3496,36 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#define E1000_WUS_ARP E1000_WUFC_ARP +#define E1000_WUS_IPV4 E1000_WUFC_IPV4 +#define E1000_WUS_IPV6 E1000_WUFC_IPV6 -+#define E1000_WUS_FLX0_BM E1000_WUFC_FLX0_BM -+#define E1000_WUS_FLX1_BM E1000_WUFC_FLX1_BM -+#define E1000_WUS_FLX2_BM E1000_WUFC_FLX2_BM -+#define E1000_WUS_FLX3_BM E1000_WUFC_FLX3_BM -+#define E1000_WUS_FLX_FILTERS_BM E1000_WUFC_FLX_FILTERS_BM ++#define E1000_WUS_FLX0_PHY E1000_WUFC_FLX0_PHY ++#define E1000_WUS_FLX1_PHY E1000_WUFC_FLX1_PHY ++#define E1000_WUS_FLX2_PHY E1000_WUFC_FLX2_PHY ++#define E1000_WUS_FLX3_PHY E1000_WUFC_FLX3_PHY ++#define E1000_WUS_FLX_FILTERS_PHY_4 E1000_WUFC_FLX_FILTERS_PHY_4 +#define E1000_WUS_FLX0 E1000_WUFC_FLX0 +#define E1000_WUS_FLX1 E1000_WUFC_FLX1 +#define E1000_WUS_FLX2 E1000_WUFC_FLX2 +#define E1000_WUS_FLX3 E1000_WUFC_FLX3 ++#define E1000_WUS_FLX4 E1000_WUFC_FLX4 ++#define E1000_WUS_FLX5 E1000_WUFC_FLX5 ++#define E1000_WUS_FLX4_PHY E1000_WUFC_FLX4_PHY ++#define E1000_WUS_FLX5_PHY E1000_WUFC_FLX5_PHY +#define E1000_WUS_FLX_FILTERS E1000_WUFC_FLX_FILTERS ++#define E1000_WUS_FLX_FILTERS_6 E1000_WUFC_FLX_FILTERS_6 ++#define E1000_WUS_FLX_FILTERS_PHY_6 E1000_WUFC_FLX_FILTERS_PHY_6 + +/* Wake Up Packet Length */ +#define E1000_WUPL_LENGTH_MASK 0x0FFF /* Only the lower 12 bits are valid */ + +/* Four Flexible Filters are supported */ +#define E1000_FLEXIBLE_FILTER_COUNT_MAX 4 ++/* Six Flexible Filters are supported */ ++#define E1000_FLEXIBLE_FILTER_COUNT_MAX_6 6 + +/* Each Flexible Filter is at most 128 (0x80) bytes in length */ +#define E1000_FLEXIBLE_FILTER_SIZE_MAX 128 + +#define E1000_FFLT_SIZE E1000_FLEXIBLE_FILTER_COUNT_MAX ++#define E1000_FFLT_SIZE_6 E1000_FLEXIBLE_FILTER_COUNT_MAX_6 +#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX +#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX + @@ -3376,6 +3551,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */ +#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 @@ -3390,16 +3566,18 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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_CTRL_EXT_LSECCK 0x00001000 ++#define E1000_CTRL_EXT_PHYPDEN 0x00100000 +#define E1000_I2CCMD_REG_ADDR_SHIFT 16 +#define E1000_I2CCMD_REG_ADDR 0x00FF0000 +#define E1000_I2CCMD_PHY_ADDR_SHIFT 24 @@ -3525,8 +3703,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 */ @@ -3534,9 +3712,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 */ @@ -3591,10 +3769,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 */ @@ -3602,7 +3780,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 */ @@ -3617,9 +3795,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 */ @@ -3634,10 +3815,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 */ + -+/* Bit definitions for the Management Data IO (MDIO) and Management Data ++/* ++ * Bit definitions for the Management Data IO (MDIO) and Management Data + * Clock (MDC) pins in the Device Control Register. + */ +#define E1000_CTRL_PHY_RESET_DIR E1000_CTRL_SWDPIO0 @@ -3695,10 +3877,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 */ @@ -3708,7 +3892,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 @@ -3716,9 +3901,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 @@ -3736,10 +3921,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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) @@ -3750,6 +3935,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#define AUTONEG_ADVERTISE_SPEED_DEFAULT E1000_ALL_SPEED_DUPLEX + +/* LED Control */ ++#define E1000_PHY_LED0_MODE_MASK 0x00000007 ++#define E1000_PHY_LED0_IVRT 0x00000008 ++#define E1000_PHY_LED0_BLINK 0x00000010 ++#define E1000_PHY_LED0_MASK 0x0000001F ++ +#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F +#define E1000_LEDCTL_LED0_MODE_SHIFT 0 +#define E1000_LEDCTL_LED0_BLINK_RATE 0x00000020 @@ -3905,16 +4095,21 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 */ @@ -3935,6 +4130,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 */ @@ -3955,16 +4152,20 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 */ +#define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */ +#define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */ @@ -3972,22 +4173,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#define E1000_ICR_TXQ1 0x00800000 /* Tx Queue 1 Interrupt */ +#define E1000_ICR_OTHER 0x01000000 /* Other Interrupts */ + -+/* Extended Interrupt Cause Read */ -+#define E1000_EICR_RX_QUEUE0 0x00000001 /* Rx Queue 0 Interrupt */ -+#define E1000_EICR_RX_QUEUE1 0x00000002 /* Rx Queue 1 Interrupt */ -+#define E1000_EICR_RX_QUEUE2 0x00000004 /* Rx Queue 2 Interrupt */ -+#define E1000_EICR_RX_QUEUE3 0x00000008 /* Rx Queue 3 Interrupt */ -+#define E1000_EICR_TX_QUEUE0 0x00000100 /* Tx Queue 0 Interrupt */ -+#define E1000_EICR_TX_QUEUE1 0x00000200 /* Tx Queue 1 Interrupt */ -+#define E1000_EICR_TX_QUEUE2 0x00000400 /* Tx Queue 2 Interrupt */ -+#define E1000_EICR_TX_QUEUE3 0x00000800 /* Tx Queue 3 Interrupt */ -+#define E1000_EICR_TCP_TIMER 0x40000000 /* TCP Timer */ -+#define E1000_EICR_OTHER 0x80000000 /* Interrupt Cause Active */ -+/* TCP Timer */ -+#define E1000_TCPTIMER_KS 0x00000100 /* KickStart */ -+#define E1000_TCPTIMER_COUNT_ENABLE 0x00000200 /* Count Enable */ -+#define E1000_TCPTIMER_COUNT_FINISH 0x00000400 /* Count finish */ -+#define E1000_TCPTIMER_LOOP 0x00000800 /* Loop */ ++/* PBA ECC Register */ ++#define E1000_PBA_ECC_COUNTER_MASK 0xFFF00000 /* ECC counter mask */ ++#define E1000_PBA_ECC_COUNTER_SHIFT 20 /* ECC counter shift value */ ++#define E1000_PBA_ECC_CORR_EN 0x00000001 /* Enable ECC error correction */ ++#define E1000_PBA_ECC_STAT_CLR 0x00000002 /* Clear ECC error counter */ ++#define E1000_PBA_ECC_INT_EN 0x00000004 /* Enable ICR bit 5 on ECC error */ + +/* + * This defines the bits that are set in the Interrupt Mask @@ -4016,9 +4207,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri + 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 */ +#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ +#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ +#define E1000_IMS_RXO E1000_ICR_RXO /* rx overrun */ @@ -4034,14 +4226,21 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 +#define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */ +#define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */ @@ -4049,20 +4248,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#define E1000_IMS_TXQ1 E1000_ICR_TXQ1 /* Tx Queue 1 Interrupt */ +#define E1000_IMS_OTHER E1000_ICR_OTHER /* Other Interrupts */ + -+/* Extended Interrupt Mask Set */ -+#define E1000_EIMS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */ -+#define E1000_EIMS_RX_QUEUE1 E1000_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */ -+#define E1000_EIMS_RX_QUEUE2 E1000_EICR_RX_QUEUE2 /* Rx Queue 2 Interrupt */ -+#define E1000_EIMS_RX_QUEUE3 E1000_EICR_RX_QUEUE3 /* Rx Queue 3 Interrupt */ -+#define E1000_EIMS_TX_QUEUE0 E1000_EICR_TX_QUEUE0 /* Tx Queue 0 Interrupt */ -+#define E1000_EIMS_TX_QUEUE1 E1000_EICR_TX_QUEUE1 /* Tx Queue 1 Interrupt */ -+#define E1000_EIMS_TX_QUEUE2 E1000_EICR_TX_QUEUE2 /* Tx Queue 2 Interrupt */ -+#define E1000_EIMS_TX_QUEUE3 E1000_EICR_TX_QUEUE3 /* Tx Queue 3 Interrupt */ -+#define E1000_EIMS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */ -+#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 */ @@ -4080,28 +4267,23 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 + -+/* Extended Interrupt Cause Set */ -+#define E1000_EICS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */ -+#define E1000_EICS_RX_QUEUE1 E1000_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */ -+#define E1000_EICS_RX_QUEUE2 E1000_EICR_RX_QUEUE2 /* Rx Queue 2 Interrupt */ -+#define E1000_EICS_RX_QUEUE3 E1000_EICR_RX_QUEUE3 /* Rx Queue 3 Interrupt */ -+#define E1000_EICS_TX_QUEUE0 E1000_EICR_TX_QUEUE0 /* Tx Queue 0 Interrupt */ -+#define E1000_EICS_TX_QUEUE1 E1000_EICR_TX_QUEUE1 /* Tx Queue 1 Interrupt */ -+#define E1000_EICS_TX_QUEUE2 E1000_EICR_TX_QUEUE2 /* Tx Queue 2 Interrupt */ -+#define E1000_EICS_TX_QUEUE3 E1000_EICR_TX_QUEUE3 /* Tx Queue 3 Interrupt */ -+#define E1000_EICS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */ -+#define E1000_EICS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */ -+ +/* Transmit Descriptor Control */ +#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */ +#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */ @@ -4132,6 +4314,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri + */ +#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 @@ -4147,6 +4333,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 @@ -4189,6 +4376,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */ +#define E1000_RXCW_ANC 0x80000000 /* Auto-neg complete */ + ++ +/* PCI Express Control */ +#define E1000_GCR_RXD_NO_SNOOP 0x00000001 +#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 @@ -4196,6 +4384,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 | \ @@ -4276,7 +4468,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri + /* 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 */ @@ -4286,7 +4478,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri + +/* 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 */ @@ -4311,6 +4503,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 */ @@ -4339,10 +4533,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 */ @@ -4354,7 +4549,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 @@ -4368,8 +4563,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 @@ -4396,13 +4591,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#define NVM_WORD_SIZE_BASE_SHIFT 6 +#define NVM_SWDPIO_EXT_SHIFT 4 + -+/* NVM Commands - Microwire */ -+#define NVM_READ_OPCODE_MICROWIRE 0x6 /* NVM read opcode */ -+#define NVM_WRITE_OPCODE_MICROWIRE 0x5 /* NVM write opcode */ -+#define NVM_ERASE_OPCODE_MICROWIRE 0x7 /* NVM erase opcode */ -+#define NVM_EWEN_OPCODE_MICROWIRE 0x13 /* NVM erase/write enable */ -+#define NVM_EWDS_OPCODE_MICROWIRE 0x10 /* NVM erase/write disable */ -+ +/* NVM Commands - SPI */ +#define NVM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */ +#define NVM_READ_OPCODE_SPI 0x03 /* NVM read opcode */ @@ -4442,22 +4630,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#define IGP_LED3_MODE 0x07000000 + +/* PCI/PCI-X/PCI-EX Config space */ -+#define PCIX_COMMAND_REGISTER 0xE6 -+#define PCIX_STATUS_REGISTER_LO 0xE8 -+#define PCIX_STATUS_REGISTER_HI 0xEA +#define PCI_HEADER_TYPE_REGISTER 0x0E +#define PCIE_LINK_STATUS 0x12 ++#define PCIE_DEVICE_CONTROL2 0x28 + -+#define PCIX_COMMAND_MMRBC_MASK 0x000C -+#define PCIX_COMMAND_MMRBC_SHIFT 0x2 -+#define PCIX_STATUS_HI_MMRBC_MASK 0x0060 -+#define PCIX_STATUS_HI_MMRBC_SHIFT 0x5 -+#define PCIX_STATUS_HI_MMRBC_4K 0x3 -+#define PCIX_STATUS_HI_MMRBC_2K 0x2 -+#define PCIX_STATUS_LO_FUNC_MASK 0x7 +#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 @@ -4485,6 +4665,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#define IFE_C_E_PHY_ID 0x02A80310 +#define BME1000_E_PHY_ID 0x01410CB0 +#define BME1000_E_PHY_ID_R2 0x01410CB1 ++#define I82577_E_PHY_ID 0x01540050 ++#define I82578_E_PHY_ID 0x004DD040 +#define M88_VENDOR 0x0141 + +/* M88E1000 Specific Registers */ @@ -4503,11 +4685,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri + +/* 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 */ @@ -4523,7 +4705,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#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 */ @@ -4591,6 +4773,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_7X 0x0C00 +#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_8X 0x0E00 + ++#define I82578_EPSCR_DOWNSHIFT_ENABLE 0x0020 ++#define I82578_EPSCR_DOWNSHIFT_COUNTER_MASK 0x001C ++ +/* BME1000 PHY Specific Control Register */ +#define BME1000_PSCR_ENABLE_DOWNSHIFT 0x0800 /* 1 = enable downshift */ + @@ -4685,15 +4870,17 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_defines.h linux-2.6.22-10/dri +#define E1000_GEN_CTL_ADDRESS_SHIFT 8 +#define E1000_GEN_POLL_TIMEOUT 640 + -+#endif ++ ++ ++#endif /* _E1000_DEFINES_H_ */ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000.h linux-2.6.22-10/drivers/net/e1000e/e1000.h --- linux-2.6.22-0/drivers/net/e1000e/e1000.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000.h 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,447 @@ ++++ linux-2.6.22-10/drivers/net/e1000e/e1000.h 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,673 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -4724,13 +4911,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000.h linux-2.6.22-10/drivers/net +#define _E1000_H_ + +#include -+#include +#include +#include ++#include + +#include "kcompat.h" -+ -+#include "e1000_hw.h" ++#include "hw.h" + +struct e1000_info; + @@ -4739,7 +4925,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000.h linux-2.6.22-10/drivers/net + (strchr(adapter->netdev->name, '%') ? "" : \ + adapter->netdev->name), ## arg) + -+#define e_dbg(format, arg...) do { (void)(adapter); } while (0) ++#ifdef DEBUG ++#define e_dbg(format, arg...) \ ++ e_printk(KERN_DEBUG, hw->adapter, format, ## arg) ++#else ++#define e_dbg(format, arg...) do { (void)(hw); } while (0) ++#endif + +#define e_err(format, arg...) \ + e_printk(KERN_ERR, adapter, format, ## arg) @@ -4758,17 +4949,18 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000.h linux-2.6.22-10/drivers/net +#define E1000E_INT_MODE_MSIX 2 + +#endif /* CONFIG_E1000E_MSIX */ -+ ++#ifndef CONFIG_E1000E_NAPI +#define E1000_MAX_INTR 10 + ++#endif /* CONFIG_E1000E_NAPI */ +/* Tx/Rx descriptor defines */ +#define E1000_DEFAULT_TXD 256 +#define E1000_MAX_TXD 4096 -+#define E1000_MIN_TXD 80 ++#define E1000_MIN_TXD 64 + +#define E1000_DEFAULT_RXD 256 +#define E1000_MAX_RXD 4096 -+#define E1000_MIN_RXD 80 ++#define E1000_MIN_RXD 64 + +#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */ +#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */ @@ -4790,6 +4982,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000.h linux-2.6.22-10/drivers/net +/* Number of packet split data buffers (not including the header buffer) */ +#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1) + ++#define DEFAULT_JUMBO 9234 ++ +enum e1000_boards { + board_82571, + board_82572, @@ -4799,6 +4993,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000.h linux-2.6.22-10/drivers/net + board_ich8lan, + board_ich9lan, + board_ich10lan, ++ board_pchlan, ++ board_82583, +}; + +struct e1000_queue_stats { @@ -4891,8 +5087,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000.h linux-2.6.22-10/drivers/net + u16 mng_vlan_id; + u16 link_speed; + u16 link_duplex; -+ -+ spinlock_t tx_queue_lock; /* prevent concurrent tail updates */ ++ u16 eeprom_vers; + + /* track device up/down/testing state */ + unsigned long state; @@ -4968,6 +5163,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000.h linux-2.6.22-10/drivers/net + + unsigned int rx_ps_pages; + u16 rx_ps_bsize0; ++#ifndef CONFIG_E1000E_NAPI ++ u64 rx_dropped_backlog; /* count drops from rx int handler */ ++#endif + u32 max_frame_size; + u32 min_frame_size; + @@ -4975,7 +5173,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000.h linux-2.6.22-10/drivers/net + struct net_device *netdev; + struct pci_dev *pdev; + struct net_device_stats net_stats; -+ spinlock_t stats_lock; /* prevent concurrent stats updates */ + + /* structs defined in e1000_hw.h */ + struct e1000_hw hw; @@ -5003,6 +5200,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000.h linux-2.6.22-10/drivers/net + u32 eeprom_wol; + u32 wol; + u32 pba; ++ u32 max_hw_frame_size; + + bool fc_autoneg; + @@ -5010,17 +5208,20 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000.h linux-2.6.22-10/drivers/net + + unsigned int flags; + unsigned int flags2; ++ struct work_struct downshift_task; ++ struct work_struct update_phy_task; ++ struct work_struct led_blink_task; + u32 *config_space; -+ u32 stats_freq_us; /* stats update freq (microseconds) */ +}; + +struct e1000_info { -+ e1000_mac_type mac; ++ enum e1000_mac_type mac; + unsigned int flags; + unsigned int flags2; + u32 pba; -+ void (*init_ops)(struct e1000_hw *); ++ u32 max_hw_frame_size; + s32 (*get_variants)(struct e1000_adapter *); ++ void (*init_ops)(struct e1000_hw *); +}; + +/* hardware capability, feature, and workaround flags */ @@ -5032,9 +5233,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000.h linux-2.6.22-10/drivers/net +#define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5) +#define FLAG_HAS_SWSM_ON_LOAD (1 << 6) +#define FLAG_HAS_JUMBO_FRAMES (1 << 7) -+#define FLAG_HAS_ASPM (1 << 8) +#define FLAG_IS_ICH (1 << 9) ++#ifdef CONFIG_E1000E_MSIX +#define FLAG_HAS_MSIX (1 << 10) ++#endif +#define FLAG_HAS_SMART_POWER_DOWN (1 << 11) +#define FLAG_IS_QUAD_PORT_A (1 << 12) +#define FLAG_IS_QUAD_PORT (1 << 13) @@ -5054,10 +5256,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000.h linux-2.6.22-10/drivers/net +#define FLAG_MSI_ENABLED (1 << 27) +#define FLAG_RX_CSUM_ENABLED (1 << 28) +#define FLAG_TSO_FORCE (1 << 29) -+#define FLAG_MSI_TEST_FAILED (1 << 30) -+#define FLAG_RX_RESTART_NOW (1 << 31) ++#define FLAG_RX_RESTART_NOW (1 << 30) ++#define FLAG_MSI_TEST_FAILED (1 << 31) + -+#define FLAG2_READ_ONLY_NVM (1 << 1) ++/* CRC Stripping defines */ ++#define FLAG2_CRC_STRIPPING (1 << 0) ++#define FLAG2_HAS_PHY_WAKEUP (1 << 1) + +#define E1000_RX_DESC_PS(R, i) \ + (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) @@ -5082,28 +5286,216 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000.h linux-2.6.22-10/drivers/net +extern char e1000e_driver_name[]; +extern const char e1000e_driver_version[]; + -+extern void e1000_check_options(struct e1000_adapter *adapter); -+extern void e1000_set_ethtool_ops(struct net_device *netdev); ++extern void e1000e_check_options(struct e1000_adapter *adapter); ++extern void e1000e_set_ethtool_ops(struct net_device *netdev); +#ifdef ETHTOOL_OPS_COMPAT +extern int ethtool_ioctl(struct ifreq *ifr); +#endif + -+extern int e1000_up(struct e1000_adapter *adapter); -+extern void e1000_down(struct e1000_adapter *adapter); -+extern void e1000_reinit_locked(struct e1000_adapter *adapter); -+extern void e1000_reset(struct e1000_adapter *adapter); -+extern int e1000_setup_rx_resources(struct e1000_adapter *adapter); -+extern int e1000_setup_tx_resources(struct e1000_adapter *adapter); -+extern void e1000_free_rx_resources(struct e1000_adapter *adapter); -+extern void e1000_free_tx_resources(struct e1000_adapter *adapter); -+extern void e1000_update_stats(struct e1000_adapter *adapter); ++extern int e1000e_up(struct e1000_adapter *adapter); ++extern void e1000e_down(struct e1000_adapter *adapter); ++extern void e1000e_reinit_locked(struct e1000_adapter *adapter); ++extern void e1000e_reset(struct e1000_adapter *adapter); ++extern void e1000e_power_up_phy(struct e1000_adapter *adapter); ++extern int e1000e_setup_rx_resources(struct e1000_adapter *adapter); ++extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter); ++extern void e1000e_free_rx_resources(struct e1000_adapter *adapter); ++extern void e1000e_free_tx_resources(struct e1000_adapter *adapter); ++extern void e1000e_update_stats(struct e1000_adapter *adapter); ++extern bool e1000_has_link(struct e1000_adapter *adapter); +#ifdef CONFIG_E1000E_MSIX -+extern void e1000_set_interrupt_capability(struct e1000_adapter *adapter); -+extern void e1000_reset_interrupt_capability(struct e1000_adapter *adapter); ++extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); ++extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); +#endif + +extern unsigned int copybreak; + ++extern void e1000_init_function_pointers_82571(struct e1000_hw *hw); ++extern void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw); ++extern void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw); ++ ++extern s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num); ++ ++static inline s32 e1000e_commit_phy(struct e1000_hw *hw) ++{ ++ if (hw->phy.ops.commit) ++ return hw->phy.ops.commit(hw); ++ ++ return 0; ++} ++ ++extern bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw); ++ ++extern bool e1000e_get_laa_state_82571(struct e1000_hw *hw); ++extern void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state); ++ ++extern void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, ++ bool state); ++extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); ++extern void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw); ++extern void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw); ++ ++extern s32 e1000e_check_for_copper_link(struct e1000_hw *hw); ++extern s32 e1000e_check_for_fiber_link(struct e1000_hw *hw); ++extern s32 e1000e_check_for_serdes_link(struct e1000_hw *hw); ++extern s32 e1000e_cleanup_led_generic(struct e1000_hw *hw); ++extern s32 e1000e_led_on_generic(struct e1000_hw *hw); ++extern s32 e1000e_led_off_generic(struct e1000_hw *hw); ++extern s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw); ++extern s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, u16 *duplex); ++extern s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, u16 *speed, u16 *duplex); ++extern s32 e1000e_disable_pcie_master(struct e1000_hw *hw); ++extern s32 e1000e_get_auto_rd_done(struct e1000_hw *hw); ++extern s32 e1000e_id_led_init(struct e1000_hw *hw); ++extern void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw); ++extern s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw); ++extern s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw); ++extern s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw); ++extern s32 e1000e_setup_link(struct e1000_hw *hw); ++static inline void e1000e_clear_vfta(struct e1000_hw *hw) ++{ ++ hw->mac.ops.clear_vfta(hw); ++} ++extern void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count); ++extern void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, ++ u8 *mc_addr_list, ++ u32 mc_addr_count); ++extern void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index); ++extern s32 e1000e_set_fc_watermarks(struct e1000_hw *hw); ++extern void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop); ++extern s32 e1000e_get_hw_semaphore(struct e1000_hw *hw); ++extern s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data); ++extern void e1000e_config_collision_dist(struct e1000_hw *hw); ++extern s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw); ++extern s32 e1000e_force_mac_fc(struct e1000_hw *hw); ++extern s32 e1000e_blink_led(struct e1000_hw *hw); ++extern void e1000e_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); ++static inline void e1000e_write_vfta(struct e1000_hw *hw, u32 offset, u32 value) ++{ ++ if (hw->mac.ops.write_vfta) ++ hw->mac.ops.write_vfta(hw, offset, value); ++} ++extern void e1000e_reset_adaptive(struct e1000_hw *hw); ++extern void e1000e_update_adaptive(struct e1000_hw *hw); ++ ++extern s32 e1000e_setup_copper_link(struct e1000_hw *hw); ++extern void e1000e_put_hw_semaphore(struct e1000_hw *hw); ++extern s32 e1000e_check_reset_block_generic(struct e1000_hw *hw); ++extern s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw); ++extern s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw); ++extern s32 e1000e_get_phy_info_igp(struct e1000_hw *hw); ++extern s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); ++extern s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw); ++extern s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active); ++extern s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); ++extern s32 e1000e_phy_sw_reset(struct e1000_hw *hw); ++extern s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw); ++extern s32 e1000e_get_cfg_done(struct e1000_hw *hw); ++extern s32 e1000e_get_cable_length_m88(struct e1000_hw *hw); ++extern s32 e1000e_get_phy_info_m88(struct e1000_hw *hw); ++extern s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data); ++extern s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data); ++extern enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id); ++extern s32 e1000e_determine_phy_address(struct e1000_hw *hw); ++extern s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data); ++extern s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data); ++extern void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); ++extern s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data); ++extern s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data); ++extern s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, ++ u32 usec_interval, bool *success); ++extern s32 e1000e_phy_reset_dsp(struct e1000_hw *hw); ++extern s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); ++extern s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); ++extern s32 e1000e_check_downshift(struct e1000_hw *hw); ++ ++static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw) ++{ ++ if (hw->phy.ops.reset) ++ return hw->phy.ops.reset(hw); ++ ++ return 0; ++} ++ ++static inline s32 e1000_check_reset_block(struct e1000_hw *hw) ++{ ++ if (hw->phy.ops.check_reset_block) ++ return hw->phy.ops.check_reset_block(hw); ++ ++ return 0; ++} ++ ++static inline s32 e1e_rphy(struct e1000_hw *hw, u32 offset, u16 *data) ++{ ++ if (hw->phy.ops.read_reg) ++ return hw->phy.ops.read_reg(hw, offset, data); ++ ++ return 0; ++} ++ ++static inline s32 e1e_wphy(struct e1000_hw *hw, u32 offset, u16 data) ++{ ++ if (hw->phy.ops.write_reg) ++ return hw->phy.ops.write_reg(hw, offset, data); ++ ++ return 0; ++} ++ ++static inline s32 e1000_get_cable_length(struct e1000_hw *hw) ++{ ++ if (hw->phy.ops.get_cable_length) ++ return hw->phy.ops.get_cable_length(hw); ++ ++ return 0; ++} ++ ++extern s32 e1000e_acquire_nvm(struct e1000_hw *hw); ++extern s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); ++extern s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw); ++extern s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg); ++extern s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); ++extern s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw); ++extern void e1000e_release_nvm(struct e1000_hw *hw); ++ ++static inline s32 e1000e_read_mac_addr(struct e1000_hw *hw) ++{ ++ if (hw->mac.ops.read_mac_addr) ++ return hw->mac.ops.read_mac_addr(hw); ++ ++ return e1000e_read_mac_addr_generic(hw); ++} ++ ++static inline s32 e1000_validate_nvm_checksum(struct e1000_hw *hw) ++{ ++ return hw->nvm.ops.validate(hw); ++} ++ ++static inline s32 e1000e_update_nvm_checksum(struct e1000_hw *hw) ++{ ++ return hw->nvm.ops.update(hw); ++} ++ ++static inline s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) ++{ ++ return hw->nvm.ops.read(hw, offset, words, data); ++} ++ ++static inline s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) ++{ ++ return hw->nvm.ops.write(hw, offset, words, data); ++} ++ ++static inline s32 e1000_get_phy_info(struct e1000_hw *hw) ++{ ++ if (hw->phy.ops.get_info) ++ return hw->phy.ops.get_info(hw); ++ ++ return 0; ++} ++ ++extern bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw); ++extern s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length); ++ +static inline u32 __er32(struct e1000_hw *hw, unsigned long reg) +{ + return readl(hw->hw_addr + reg); @@ -5113,38 +5505,59 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000.h linux-2.6.22-10/drivers/net +{ + writel(val, hw->hw_addr + reg); +} -+#define er32(reg) E1000_READ_REG(hw, E1000_##reg) -+#define ew32(reg,val) E1000_WRITE_REG(hw, E1000_##reg, (val)) ++ ++#define er32(reg) __er32(hw, E1000_##reg) ++#define ew32(reg, val) __ew32(hw, E1000_##reg, (val)) +#define e1e_flush() er32(STATUS) + -+extern void e1000_init_function_pointers_82571(struct e1000_hw *hw); -+extern void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw); -+extern void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw); ++#define E1000_WRITE_REG(a, reg, value) ( \ ++ writel((value), ((a)->hw_addr + reg))) ++ ++#define E1000_READ_REG(a, reg) (readl((a)->hw_addr + reg)) ++ ++#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \ ++ writel((value), ((a)->hw_addr + reg + ((offset) << 2)))) ++ ++#define E1000_READ_REG_ARRAY(a, reg, offset) ( \ ++ readl((a)->hw_addr + reg + ((offset) << 2))) ++ ++#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY ++#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY ++ ++static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) ++{ ++ return readw(hw->flash_address + reg); ++} + -+static inline s32 e1000_read_mac_addr(struct e1000_hw *hw) ++static inline u32 __er32flash(struct e1000_hw *hw, unsigned long reg) +{ -+ if (hw->mac.ops.read_mac_addr) -+ return hw->mac.ops.read_mac_addr(hw); ++ return readl(hw->flash_address + reg); ++} + -+ return e1000_read_mac_addr_generic(hw); ++static inline void __ew16flash(struct e1000_hw *hw, unsigned long reg, u16 val) ++{ ++ writew(val, hw->flash_address + reg); +} + -+static inline void e1000_power_up_phy(struct e1000_hw *hw) ++static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val) +{ -+ if(hw->phy.ops.power_up) -+ hw->phy.ops.power_up(hw); -+ hw->mac.ops.setup_link(hw); ++ writel(val, hw->flash_address + reg); +} + ++#define er16flash(reg) __er16flash(hw, (reg)) ++#define er32flash(reg) __er32flash(hw, (reg)) ++#define ew16flash(reg, val) __ew16flash(hw, (reg), (val)) ++#define ew32flash(reg, val) __ew32flash(hw, (reg), (val)) ++ +#endif /* _E1000_H_ */ -diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_hw.h linux-2.6.22-10/drivers/net/e1000e/e1000_hw.h ---- linux-2.6.22-0/drivers/net/e1000e/e1000_hw.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000_hw.h 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,671 @@ +diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/drivers/net/e1000e/e1000_ich8lan.c +--- linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.22-10/drivers/net/e1000e/e1000_ich8lan.c 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,3042 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -5169,1086 +5582,1010 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_hw.h linux-2.6.22-10/drivers/ + +*******************************************************************************/ + -+#ifndef _E1000_HW_H_ -+#define _E1000_HW_H_ -+ -+#include "e1000_osdep.h" -+#include "e1000_regs.h" -+#include "e1000_defines.h" ++/* ++ * 82562G 10/100 Network Connection ++ * 82562G-2 10/100 Network Connection ++ * 82562GT 10/100 Network Connection ++ * 82562GT-2 10/100 Network Connection ++ * 82562V 10/100 Network Connection ++ * 82562V-2 10/100 Network Connection ++ * 82566DC-2 Gigabit Network Connection ++ * 82566DC Gigabit Network Connection ++ * 82566DM-2 Gigabit Network Connection ++ * 82566DM Gigabit Network Connection ++ * 82566MC Gigabit Network Connection ++ * 82566MM Gigabit Network Connection ++ * 82567LM Gigabit Network Connection ++ * 82567LF Gigabit Network Connection ++ * 82567V Gigabit Network Connection ++ * 82567LM-2 Gigabit Network Connection ++ * 82567LF-2 Gigabit Network Connection ++ * 82567V-2 Gigabit Network Connection ++ * 82567LF-3 Gigabit Network Connection ++ * 82567LM-3 Gigabit Network Connection ++ * 82567LM-4 Gigabit Network Connection ++ * 82577LM Gigabit Network Connection ++ * 82577LC Gigabit Network Connection ++ * 82578DM Gigabit Network Connection ++ * 82578DC Gigabit Network Connection ++ */ + -+struct e1000_hw; ++#include "e1000.h" + -+#define E1000_DEV_ID_82571EB_COPPER 0x105E -+#define E1000_DEV_ID_82571EB_FIBER 0x105F -+#define E1000_DEV_ID_82571EB_SERDES 0x1060 -+#define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9 -+#define E1000_DEV_ID_82571EB_SERDES_QUAD 0x10DA -+#define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4 -+#define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5 -+#define E1000_DEV_ID_82571EB_QUAD_FIBER 0x10A5 -+#define E1000_DEV_ID_82571EB_QUAD_COPPER_LP 0x10BC -+#define E1000_DEV_ID_82572EI_COPPER 0x107D -+#define E1000_DEV_ID_82572EI_FIBER 0x107E -+#define E1000_DEV_ID_82572EI_SERDES 0x107F -+#define E1000_DEV_ID_82572EI 0x10B9 -+#define E1000_DEV_ID_82573E 0x108B -+#define E1000_DEV_ID_82573E_IAMT 0x108C -+#define E1000_DEV_ID_82573L 0x109A -+#define E1000_DEV_ID_82574L 0x10D3 -+#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096 -+#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098 -+#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT 0x10BA -+#define E1000_DEV_ID_80003ES2LAN_SERDES_SPT 0x10BB -+#define E1000_DEV_ID_ICH8_IGP_M_AMT 0x1049 -+#define E1000_DEV_ID_ICH8_IGP_AMT 0x104A -+#define E1000_DEV_ID_ICH8_IGP_C 0x104B -+#define E1000_DEV_ID_ICH8_IFE 0x104C -+#define E1000_DEV_ID_ICH8_IFE_GT 0x10C4 -+#define E1000_DEV_ID_ICH8_IFE_G 0x10C5 -+#define E1000_DEV_ID_ICH8_IGP_M 0x104D -+#define E1000_DEV_ID_ICH9_IGP_M 0x10BF -+#define E1000_DEV_ID_ICH9_IGP_M_AMT 0x10F5 -+#define E1000_DEV_ID_ICH9_IGP_M_V 0x10CB -+#define E1000_DEV_ID_ICH9_IGP_AMT 0x10BD -+#define E1000_DEV_ID_ICH9_BM 0x10E5 -+#define E1000_DEV_ID_ICH9_IGP_C 0x294C -+#define E1000_DEV_ID_ICH9_IFE 0x10C0 -+#define E1000_DEV_ID_ICH9_IFE_GT 0x10C3 -+#define E1000_DEV_ID_ICH9_IFE_G 0x10C2 -+#define E1000_DEV_ID_ICH10_R_BM_LM 0x10CC -+#define E1000_DEV_ID_ICH10_R_BM_LF 0x10CD -+#define E1000_DEV_ID_ICH10_R_BM_V 0x10CE -+#define E1000_DEV_ID_ICH10_D_BM_LM 0x10DE -+#define E1000_DEV_ID_ICH10_D_BM_LF 0x10DF ++static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw); ++static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw); ++static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw); ++static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw); ++static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw); ++static void e1000_release_swflag_ich8lan(struct e1000_hw *hw); ++static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw); ++static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw); ++static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw); ++static s32 e1000_get_phy_info_ich8lan(struct e1000_hw *hw); ++static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, ++ bool active); ++static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, ++ bool active); ++static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, ++ u16 words, u16 *data); ++static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, ++ u16 words, u16 *data); ++static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw); ++static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw); ++static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, ++ u16 *data); ++static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw); ++static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw); ++static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw); ++static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw); ++static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw); ++static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw); ++static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, ++ u16 *speed, u16 *duplex); ++static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw); ++static s32 e1000_led_on_ich8lan(struct e1000_hw *hw); ++static s32 e1000_led_off_ich8lan(struct e1000_hw *hw); ++static s32 e1000_setup_led_pchlan(struct e1000_hw *hw); ++static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw); ++static s32 e1000_led_on_pchlan(struct e1000_hw *hw); ++static s32 e1000_led_off_pchlan(struct e1000_hw *hw); ++static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw); ++static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank); ++static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout); ++static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw); ++static s32 e1000_get_phy_info_ife_ich8lan(struct e1000_hw *hw); ++static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw); ++static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw); ++static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, ++ u32 offset, u8 *data); ++static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, ++ u8 size, u16 *data); ++static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, ++ u32 offset, u16 *data); ++static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, ++ u32 offset, u8 byte); ++static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, ++ u32 offset, u8 data); ++static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, ++ u8 size, u16 data); ++static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw); ++static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw); ++static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw); + -+#define E1000_REVISION_0 0 -+#define E1000_REVISION_1 1 -+#define E1000_REVISION_2 2 -+#define E1000_REVISION_3 3 -+#define E1000_REVISION_4 4 ++/* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ ++/* Offset 04h HSFSTS */ ++union ich8_hws_flash_status { ++ struct ich8_hsfsts { ++ u16 flcdone :1; /* bit 0 Flash Cycle Done */ ++ u16 flcerr :1; /* bit 1 Flash Cycle Error */ ++ u16 dael :1; /* bit 2 Direct Access error Log */ ++ u16 berasesz :2; /* bit 4:3 Sector Erase Size */ ++ u16 flcinprog :1; /* bit 5 flash cycle in Progress */ ++ u16 reserved1 :2; /* bit 13:6 Reserved */ ++ u16 reserved2 :6; /* bit 13:6 Reserved */ ++ u16 fldesvalid :1; /* bit 14 Flash Descriptor Valid */ ++ u16 flockdn :1; /* bit 15 Flash Config Lock-Down */ ++ } hsf_status; ++ u16 regval; ++}; + -+#define E1000_FUNC_0 0 -+#define E1000_FUNC_1 1 ++/* ICH GbE Flash Hardware Sequencing Flash control Register bit breakdown */ ++/* Offset 06h FLCTL */ ++union ich8_hws_flash_ctrl { ++ struct ich8_hsflctl { ++ u16 flcgo :1; /* 0 Flash Cycle Go */ ++ u16 flcycle :2; /* 2:1 Flash Cycle */ ++ u16 reserved :5; /* 7:3 Reserved */ ++ u16 fldbcount :2; /* 9:8 Flash Data Byte Count */ ++ u16 flockdn :6; /* 15:10 Reserved */ ++ } hsf_ctrl; ++ u16 regval; ++}; + -+typedef enum { -+ e1000_undefined = 0, -+ e1000_82571, -+ e1000_82572, -+ e1000_82573, -+ e1000_82574, -+ e1000_80003es2lan, -+ e1000_ich8lan, -+ e1000_ich9lan, -+ e1000_ich10lan, -+ e1000_num_macs /* List is 1-based, so subtract 1 for true count. */ -+} e1000_mac_type; ++/* ICH Flash Region Access Permissions */ ++union ich8_hws_flash_regacc { ++ struct ich8_flracc { ++ u32 grra :8; /* 0:7 GbE region Read Access */ ++ u32 grwa :8; /* 8:15 GbE region Write Access */ ++ u32 gmrag :8; /* 23:16 GbE Master Read Access Grant */ ++ u32 gmwag :8; /* 31:24 GbE Master Write Access Grant */ ++ } hsf_flregacc; ++ u16 regval; ++}; + -+typedef enum { -+ e1000_media_type_unknown = 0, -+ e1000_media_type_copper = 1, -+ e1000_media_type_fiber = 2, -+ e1000_media_type_internal_serdes = 3, -+ e1000_num_media_types -+} e1000_media_type; ++/** ++ * e1000_init_phy_params_pchlan - Initialize PHY function pointers ++ * @hw: pointer to the HW structure ++ * ++ * Initialize family-specific PHY parameters and function pointers. ++ **/ ++static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val = E1000_SUCCESS; + -+typedef enum { -+ e1000_nvm_unknown = 0, -+ e1000_nvm_none, -+ e1000_nvm_eeprom_spi, -+ e1000_nvm_eeprom_microwire, -+ e1000_nvm_flash_hw, -+ e1000_nvm_flash_sw -+} e1000_nvm_type; ++ phy->addr = 1; ++ phy->reset_delay_us = 100; + -+typedef enum { -+ e1000_nvm_override_none = 0, -+ e1000_nvm_override_spi_small, -+ e1000_nvm_override_spi_large, -+ e1000_nvm_override_microwire_small, -+ e1000_nvm_override_microwire_large -+} e1000_nvm_override; ++ phy->ops.acquire = e1000_acquire_swflag_ich8lan; ++ phy->ops.check_polarity = e1000_check_polarity_ife; ++ phy->ops.check_reset_block = e1000_check_reset_block_ich8lan; ++ phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_ife; ++ phy->ops.get_cable_length = e1000e_get_cable_length_igp_2; ++ phy->ops.get_cfg_done = e1000_get_cfg_done_ich8lan; ++ phy->ops.get_info = e1000_get_phy_info_ich8lan; ++ phy->ops.read_reg = e1000_read_phy_reg_hv; ++ phy->ops.release = e1000_release_swflag_ich8lan; ++ phy->ops.reset = e1000_phy_hw_reset_ich8lan; ++ phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_ich8lan; ++ phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_ich8lan; ++ phy->ops.write_reg = e1000_write_phy_reg_hv; ++ phy->ops.power_up = e1000_power_up_phy_copper; ++ phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; ++ phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; + -+typedef enum { -+ e1000_phy_unknown = 0, -+ e1000_phy_none, -+ e1000_phy_m88, -+ e1000_phy_igp, -+ e1000_phy_igp_2, -+ e1000_phy_gg82563, -+ e1000_phy_igp_3, -+ e1000_phy_ife, -+ e1000_phy_bm, -+} e1000_phy_type; ++ phy->id = e1000_phy_unknown; ++ e1000e_get_phy_id(hw); ++ phy->type = e1000e_get_phy_type_from_id(phy->id); + -+typedef enum { -+ e1000_bus_type_unknown = 0, -+ e1000_bus_type_pci, -+ e1000_bus_type_pcix, -+ e1000_bus_type_pci_express, -+ e1000_bus_type_reserved -+} e1000_bus_type; ++ if (phy->type == e1000_phy_82577) { ++ phy->ops.check_polarity = e1000_check_polarity_82577; ++ phy->ops.force_speed_duplex = ++ e1000_phy_force_speed_duplex_82577; ++ phy->ops.get_cable_length = e1000_get_cable_length_82577; ++ phy->ops.get_info = e1000_get_phy_info_82577; ++ phy->ops.commit = e1000e_phy_sw_reset; ++ } + -+typedef enum { -+ e1000_bus_speed_unknown = 0, -+ e1000_bus_speed_33, -+ e1000_bus_speed_66, -+ e1000_bus_speed_100, -+ e1000_bus_speed_120, -+ e1000_bus_speed_133, -+ e1000_bus_speed_2500, -+ e1000_bus_speed_5000, -+ e1000_bus_speed_reserved -+} e1000_bus_speed; ++ return ret_val; ++} + -+typedef enum { -+ e1000_bus_width_unknown = 0, -+ e1000_bus_width_pcie_x1, -+ e1000_bus_width_pcie_x2, -+ e1000_bus_width_pcie_x4 = 4, -+ e1000_bus_width_pcie_x8 = 8, -+ e1000_bus_width_32, -+ e1000_bus_width_64, -+ e1000_bus_width_reserved -+} e1000_bus_width; ++/** ++ * e1000_init_phy_params_ich8lan - Initialize PHY function pointers ++ * @hw: pointer to the HW structure ++ * ++ * Initialize family-specific PHY parameters and function pointers. ++ **/ ++static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val = E1000_SUCCESS; ++ u16 i = 0; + -+typedef enum { -+ e1000_1000t_rx_status_not_ok = 0, -+ e1000_1000t_rx_status_ok, -+ e1000_1000t_rx_status_undefined = 0xFF -+} e1000_1000t_rx_status; ++ phy->addr = 1; ++ phy->reset_delay_us = 100; + -+typedef enum { -+ e1000_rev_polarity_normal = 0, -+ e1000_rev_polarity_reversed, -+ e1000_rev_polarity_undefined = 0xFF -+} e1000_rev_polarity; ++ phy->ops.acquire = e1000_acquire_swflag_ich8lan; ++ phy->ops.check_polarity = e1000_check_polarity_ife; ++ phy->ops.check_reset_block = e1000_check_reset_block_ich8lan; ++ phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_ife; ++ phy->ops.get_cable_length = e1000e_get_cable_length_igp_2; ++ phy->ops.get_cfg_done = e1000_get_cfg_done_ich8lan; ++ phy->ops.get_info = e1000_get_phy_info_ich8lan; ++ phy->ops.read_reg = e1000e_read_phy_reg_igp; ++ phy->ops.release = e1000_release_swflag_ich8lan; ++ phy->ops.reset = e1000_phy_hw_reset_ich8lan; ++ phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_ich8lan; ++ phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_ich8lan; ++ phy->ops.write_reg = e1000e_write_phy_reg_igp; ++ phy->ops.power_up = e1000_power_up_phy_copper; ++ phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; + -+typedef enum { -+ e1000_fc_none = 0, -+ e1000_fc_rx_pause, -+ e1000_fc_tx_pause, -+ e1000_fc_full, -+ e1000_fc_default = 0xFF -+} e1000_fc_type; ++ /* ++ * We may need to do this twice - once for IGP and if that fails, ++ * we'll set BM func pointers and try again ++ */ ++ ret_val = e1000e_determine_phy_address(hw); ++ if (ret_val) { ++ phy->ops.write_reg = e1000e_write_phy_reg_bm; ++ phy->ops.read_reg = e1000e_read_phy_reg_bm; ++ ret_val = e1000e_determine_phy_address(hw); ++ if (ret_val) { ++ e_dbg("Cannot determine PHY addr. Erroring out\n"); ++ goto out; ++ } ++ } + ++ phy->id = 0; ++ while ((e1000_phy_unknown == e1000e_get_phy_type_from_id(phy->id)) && ++ (i++ < 100)) { ++ msleep(1); ++ ret_val = e1000e_get_phy_id(hw); ++ if (ret_val) ++ goto out; ++ } + -+/* Receive Descriptor */ -+struct e1000_rx_desc { -+ u64 buffer_addr; /* Address of the descriptor's data buffer */ -+ u16 length; /* Length of data DMAed into data buffer */ -+ u16 csum; /* Packet checksum */ -+ u8 status; /* Descriptor status */ -+ u8 errors; /* Descriptor Errors */ -+ u16 special; -+}; ++ /* Verify phy id */ ++ switch (phy->id) { ++ case IGP03E1000_E_PHY_ID: ++ phy->type = e1000_phy_igp_3; ++ phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; ++ break; ++ case IFE_E_PHY_ID: ++ case IFE_PLUS_E_PHY_ID: ++ case IFE_C_E_PHY_ID: ++ phy->type = e1000_phy_ife; ++ phy->autoneg_mask = E1000_ALL_NOT_GIG; ++ break; ++ case BME1000_E_PHY_ID: ++ phy->type = e1000_phy_bm; ++ phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; ++ phy->ops.read_reg = e1000e_read_phy_reg_bm; ++ phy->ops.write_reg = e1000e_write_phy_reg_bm; ++ phy->ops.commit = e1000e_phy_sw_reset; ++ break; ++ default: ++ ret_val = -E1000_ERR_PHY; ++ goto out; ++ } + -+/* Receive Descriptor - Extended */ -+union e1000_rx_desc_extended { -+ struct { -+ u64 buffer_addr; -+ u64 reserved; -+ } read; -+ struct { -+ struct { -+ u32 mrq; /* Multiple Rx Queues */ -+ union { -+ u32 rss; /* RSS Hash */ -+ struct { -+ u16 ip_id; /* IP id */ -+ u16 csum; /* Packet Checksum */ -+ } csum_ip; -+ } hi_dword; -+ } lower; -+ struct { -+ u32 status_error; /* ext status/error */ -+ u16 length; -+ u16 vlan; /* VLAN tag */ -+ } upper; -+ } wb; /* writeback */ -+}; -+ -+#define MAX_PS_BUFFERS 4 -+/* Receive Descriptor - Packet Split */ -+union e1000_rx_desc_packet_split { -+ struct { -+ /* one buffer for protocol header(s), three data buffers */ -+ u64 buffer_addr[MAX_PS_BUFFERS]; -+ } read; -+ struct { -+ struct { -+ u32 mrq; /* Multiple Rx Queues */ -+ union { -+ u32 rss; /* RSS Hash */ -+ struct { -+ u16 ip_id; /* IP id */ -+ u16 csum; /* Packet Checksum */ -+ } csum_ip; -+ } hi_dword; -+ } lower; -+ struct { -+ u32 status_error; /* ext status/error */ -+ u16 length0; /* length of buffer 0 */ -+ u16 vlan; /* VLAN tag */ -+ } middle; -+ struct { -+ u16 header_status; -+ u16 length[3]; /* length of buffers 1-3 */ -+ } upper; -+ u64 reserved; -+ } wb; /* writeback */ -+}; ++out: ++ return ret_val; ++} + -+/* Transmit Descriptor */ -+struct e1000_tx_desc { -+ u64 buffer_addr; /* Address of the descriptor's data buffer */ -+ union { -+ u32 data; -+ struct { -+ u16 length; /* Data buffer length */ -+ u8 cso; /* Checksum offset */ -+ u8 cmd; /* Descriptor control */ -+ } flags; -+ } lower; -+ union { -+ u32 data; -+ struct { -+ u8 status; /* Descriptor status */ -+ u8 css; /* Checksum start */ -+ u16 special; -+ } fields; -+ } upper; -+}; ++/** ++ * e1000_init_nvm_params_ich8lan - Initialize NVM function pointers ++ * @hw: pointer to the HW structure ++ * ++ * Initialize family-specific NVM parameters and function ++ * pointers. ++ **/ ++static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) ++{ ++ struct e1000_nvm_info *nvm = &hw->nvm; ++ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; ++ union ich8_hws_flash_status hsfsts; ++ u32 gfpreg, sector_base_addr, sector_end_addr; ++ s32 ret_val = E1000_SUCCESS; ++ u16 i; + -+/* Offload Context Descriptor */ -+struct e1000_context_desc { -+ union { -+ u32 ip_config; -+ struct { -+ u8 ipcss; /* IP checksum start */ -+ u8 ipcso; /* IP checksum offset */ -+ u16 ipcse; /* IP checksum end */ -+ } ip_fields; -+ } lower_setup; -+ union { -+ u32 tcp_config; -+ struct { -+ u8 tucss; /* TCP checksum start */ -+ u8 tucso; /* TCP checksum offset */ -+ u16 tucse; /* TCP checksum end */ -+ } tcp_fields; -+ } upper_setup; -+ u32 cmd_and_length; -+ union { -+ u32 data; -+ struct { -+ u8 status; /* Descriptor status */ -+ u8 hdr_len; /* Header length */ -+ u16 mss; /* Maximum segment size */ -+ } fields; -+ } tcp_seg_setup; -+}; ++ /* Can't read flash registers if the register set isn't mapped. */ ++ if (!hw->flash_address) { ++ e_dbg("ERROR: Flash registers not mapped\n"); ++ ret_val = -E1000_ERR_CONFIG; ++ goto out; ++ } + -+/* Offload data descriptor */ -+struct e1000_data_desc { -+ u64 buffer_addr; /* Address of the descriptor's buffer address */ -+ union { -+ u32 data; -+ struct { -+ u16 length; /* Data buffer length */ -+ u8 typ_len_ext; -+ u8 cmd; -+ } flags; -+ } lower; -+ union { -+ u32 data; -+ struct { -+ u8 status; /* Descriptor status */ -+ u8 popts; /* Packet Options */ -+ u16 special; -+ } fields; -+ } upper; -+}; ++ nvm->type = e1000_nvm_flash_sw; + -+/* Statistics counters collected by the MAC */ -+struct e1000_hw_stats { -+ u64 crcerrs; -+ u64 algnerrc; -+ u64 symerrs; -+ u64 rxerrc; -+ u64 mpc; -+ u64 scc; -+ u64 ecol; -+ u64 mcc; -+ u64 latecol; -+ u64 colc; -+ u64 dc; -+ u64 tncrs; -+ u64 sec; -+ u64 cexterr; -+ u64 rlec; -+ u64 xonrxc; -+ u64 xontxc; -+ u64 xoffrxc; -+ u64 xofftxc; -+ u64 fcruc; -+ u64 prc64; -+ u64 prc127; -+ u64 prc255; -+ u64 prc511; -+ u64 prc1023; -+ u64 prc1522; -+ u64 gprc; -+ u64 bprc; -+ u64 mprc; -+ u64 gptc; -+ u64 gorc; -+ u64 gotc; -+ u64 rnbc; -+ u64 ruc; -+ u64 rfc; -+ u64 roc; -+ u64 rjc; -+ u64 mgprc; -+ u64 mgpdc; -+ u64 mgptc; -+ u64 tor; -+ u64 tot; -+ u64 tpr; -+ u64 tpt; -+ u64 ptc64; -+ u64 ptc127; -+ u64 ptc255; -+ u64 ptc511; -+ u64 ptc1023; -+ u64 ptc1522; -+ u64 mptc; -+ u64 bptc; -+ u64 tsctc; -+ u64 tsctfc; -+ u64 iac; -+ u64 icrxptc; -+ u64 icrxatc; -+ u64 ictxptc; -+ u64 ictxatc; -+ u64 ictxqec; -+ u64 ictxqmtc; -+ u64 icrxdmtc; -+ u64 icrxoc; -+ u64 cbtmpc; -+ u64 htdpmc; -+ u64 cbrdpc; -+ u64 cbrmpc; -+ u64 rpthc; -+ u64 hgptc; -+ u64 htcbdpc; -+ u64 hgorc; -+ u64 hgotc; -+ u64 lenerrs; -+ u64 scvpc; -+ u64 hrmpc; -+}; ++ gfpreg = er32flash(ICH_FLASH_GFPREG); + -+struct e1000_phy_stats { -+ u32 idle_errors; -+ u32 receive_errors; -+}; ++ /* ++ * sector_X_addr is a "sector"-aligned address (4096 bytes) ++ * Add 1 to sector_end_addr since this sector is included in ++ * the overall size. ++ */ ++ sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK; ++ sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1; + -+struct e1000_host_mng_dhcp_cookie { -+ u32 signature; -+ u8 status; -+ u8 reserved0; -+ u16 vlan_id; -+ u32 reserved1; -+ u16 reserved2; -+ u8 reserved3; -+ u8 checksum; -+}; ++ /* flash_base_addr is byte-aligned */ ++ nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT; + -+/* Host Interface "Rev 1" */ -+struct e1000_host_command_header { -+ u8 command_id; -+ u8 command_length; -+ u8 command_options; -+ u8 checksum; -+}; ++ /* ++ * find total size of the NVM, then cut in half since the total ++ * size represents two separate NVM banks. ++ */ ++ nvm->flash_bank_size = (sector_end_addr - sector_base_addr) ++ << FLASH_SECTOR_ADDR_SHIFT; ++ nvm->flash_bank_size /= 2; ++ /* Adjust to word count */ ++ nvm->flash_bank_size /= sizeof(u16); + -+#define E1000_HI_MAX_DATA_LENGTH 252 -+struct e1000_host_command_info { -+ struct e1000_host_command_header command_header; -+ u8 command_data[E1000_HI_MAX_DATA_LENGTH]; -+}; ++ /* ++ * Make sure the flash bank size does not overwrite the 4k ++ * sector ranges. We may have 64k allotted to us but we only care ++ * about the first 2 4k sectors. Therefore, if we have anything less ++ * than 64k set in the HSFSTS register, we will reduce the bank size ++ * down to 4k and let the rest remain unused. If berasesz == 3, then ++ * we are working in 64k mode. Otherwise we are not. ++ */ ++ if (nvm->flash_bank_size > E1000_ICH8_SHADOW_RAM_WORDS) { ++ hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); ++ if (hsfsts.hsf_status.berasesz != 3) ++ nvm->flash_bank_size = E1000_ICH8_SHADOW_RAM_WORDS; ++ } + -+/* Host Interface "Rev 2" */ -+struct e1000_host_mng_command_header { -+ u8 command_id; -+ u8 checksum; -+ u16 reserved1; -+ u16 reserved2; -+ u16 command_length; -+}; ++ nvm->word_size = E1000_ICH8_SHADOW_RAM_WORDS; + -+#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 -+struct e1000_host_mng_command_info { -+ struct e1000_host_mng_command_header command_header; -+ u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; -+}; ++ /* Clear shadow ram */ ++ for (i = 0; i < nvm->word_size; i++) { ++ dev_spec->shadow_ram[i].modified = false; ++ dev_spec->shadow_ram[i].value = 0xFFFF; ++ } + -+#include "e1000_mac.h" -+#include "e1000_phy.h" -+#include "e1000_nvm.h" -+#include "e1000_manage.h" ++ /* Function Pointers */ ++ nvm->ops.acquire = e1000_acquire_swflag_ich8lan; ++ nvm->ops.read = e1000_read_nvm_ich8lan; ++ nvm->ops.release = e1000_release_swflag_ich8lan; ++ nvm->ops.update = e1000_update_nvm_checksum_ich8lan; ++ nvm->ops.valid_led_default = e1000_valid_led_default_ich8lan; ++ nvm->ops.validate = e1000_validate_nvm_checksum_ich8lan; ++ nvm->ops.write = e1000_write_nvm_ich8lan; + -+struct e1000_mac_operations { -+ /* Function pointers for the MAC. */ -+ s32 (*init_params)(struct e1000_hw *); -+ s32 (*blink_led)(struct e1000_hw *); -+ s32 (*check_for_link)(struct e1000_hw *); -+ bool (*check_mng_mode)(struct e1000_hw *hw); -+ s32 (*cleanup_led)(struct e1000_hw *); -+ void (*clear_hw_cntrs)(struct e1000_hw *); -+ void (*clear_vfta)(struct e1000_hw *); -+ s32 (*get_bus_info)(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 (*remove_device)(struct e1000_hw *); -+ s32 (*reset_hw)(struct e1000_hw *); -+ s32 (*init_hw)(struct e1000_hw *); -+ s32 (*setup_link)(struct e1000_hw *); -+ s32 (*setup_physical_interface)(struct e1000_hw *); -+ 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*); -+ 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*); -+}; ++out: ++ return ret_val; ++} + -+struct e1000_phy_operations { -+ s32 (*init_params)(struct e1000_hw *); -+ s32 (*acquire)(struct e1000_hw *); -+ s32 (*cfg_on_link_up)(struct e1000_hw *); -+ s32 (*check_polarity)(struct e1000_hw *); -+ s32 (*check_reset_block)(struct e1000_hw *); -+ s32 (*commit)(struct e1000_hw *); -+ s32 (*force_speed_duplex)(struct e1000_hw *); -+ s32 (*get_cfg_done)(struct e1000_hw *hw); -+ s32 (*get_cable_length)(struct e1000_hw *); -+ s32 (*get_info)(struct e1000_hw *); -+ s32 (*read_reg)(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); -+ void (*power_up)(struct e1000_hw *); -+ void (*power_down)(struct e1000_hw *); -+}; ++/** ++ * e1000_init_mac_params_ich8lan - Initialize MAC function pointers ++ * @hw: pointer to the HW structure ++ * ++ * Initialize family-specific MAC parameters and function ++ * pointers. ++ **/ ++static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) ++{ ++ struct e1000_mac_info *mac = &hw->mac; + -+struct e1000_nvm_operations { -+ s32 (*init_params)(struct e1000_hw *); -+ s32 (*acquire)(struct e1000_hw *); -+ s32 (*read)(struct e1000_hw *, u16, u16, u16 *); -+ void (*release)(struct e1000_hw *); -+ void (*reload)(struct e1000_hw *); -+ s32 (*update)(struct e1000_hw *); -+ s32 (*valid_led_default)(struct e1000_hw *, u16 *); -+ s32 (*validate)(struct e1000_hw *); -+ s32 (*write)(struct e1000_hw *, u16, u16, u16 *); -+}; ++ /* Set media type function pointer */ ++ hw->phy.media_type = e1000_media_type_copper; + -+struct e1000_mac_info { -+ struct e1000_mac_operations ops; -+ u8 addr[6]; -+ u8 perm_addr[6]; ++ /* Set mta register count */ ++ mac->mta_reg_count = 32; ++ /* Set rar entry count */ ++ mac->rar_entry_count = E1000_ICH_RAR_ENTRIES; ++ if (mac->type == e1000_ich8lan) ++ mac->rar_entry_count--; ++ /* Set if part includes ASF firmware */ ++ mac->asf_firmware_present = true; ++ /* Set if manageability features are enabled. */ ++ mac->arc_subsystem_valid = true; + -+ e1000_mac_type type; ++ /* Function pointers */ + -+ u32 collision_delta; -+ u32 ledctl_default; -+ u32 ledctl_mode1; -+ u32 ledctl_mode2; -+ u32 mc_filter_type; -+ u32 tx_packet_delta; -+ u32 txcw; ++ /* bus type/speed/width */ ++ mac->ops.get_bus_info = e1000_get_bus_info_ich8lan; ++ /* function id */ ++ mac->ops.set_lan_id = e1000_set_lan_id_single_port; ++ /* reset */ ++ mac->ops.reset_hw = e1000_reset_hw_ich8lan; ++ /* hw initialization */ ++ mac->ops.init_hw = e1000_init_hw_ich8lan; ++ /* link setup */ ++ mac->ops.setup_link = e1000_setup_link_ich8lan; ++ /* physical interface setup */ ++ mac->ops.setup_physical_interface = e1000_setup_copper_link_ich8lan; ++ /* check for link */ ++ mac->ops.check_for_link = e1000_check_for_copper_link_ich8lan; ++ /* check management mode */ ++ mac->ops.check_mng_mode = e1000_check_mng_mode_ich8lan; ++ /* link info */ ++ mac->ops.get_link_up_info = e1000_get_link_up_info_ich8lan; ++ /* multicast address update */ ++ mac->ops.update_mc_addr_list = e1000e_update_mc_addr_list_generic; ++ /* setting MTA */ ++ mac->ops.mta_set = e1000_mta_set_generic; ++ /* clear hardware counters */ ++ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan; + -+ u16 current_ifs_val; -+ u16 ifs_max_val; -+ u16 ifs_min_val; -+ u16 ifs_ratio; -+ u16 ifs_step_size; -+ u16 mta_reg_count; -+ u16 rar_entry_count; ++ /* LED operations */ ++ switch (mac->type) { ++ case e1000_ich8lan: ++ case e1000_ich9lan: ++ case e1000_ich10lan: ++ /* ID LED init */ ++ mac->ops.id_led_init = e1000e_id_led_init; ++ /* blink LED */ ++ mac->ops.blink_led = e1000e_blink_led; ++ /* setup LED */ ++ mac->ops.setup_led = e1000_setup_led_generic; ++ /* cleanup LED */ ++ mac->ops.cleanup_led = e1000_cleanup_led_ich8lan; ++ /* turn on/off LED */ ++ mac->ops.led_on = e1000_led_on_ich8lan; ++ mac->ops.led_off = e1000_led_off_ich8lan; ++ break; ++ case e1000_pchlan: ++ /* ID LED init */ ++ mac->ops.id_led_init = e1000_id_led_init_pchlan; ++ /* setup LED */ ++ mac->ops.setup_led = e1000_setup_led_pchlan; ++ /* cleanup LED */ ++ mac->ops.cleanup_led = e1000_cleanup_led_pchlan; ++ /* turn on/off LED */ ++ mac->ops.led_on = e1000_led_on_pchlan; ++ mac->ops.led_off = e1000_led_off_pchlan; ++ break; ++ default: ++ break; ++ } + -+ u8 forced_speed_duplex; ++ /* Enable PCS Lock-loss workaround for ICH8 */ ++ if (mac->type == e1000_ich8lan) ++ e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true); + -+ bool adaptive_ifs; -+ bool arc_subsystem_valid; -+ bool asf_firmware_present; -+ bool autoneg; -+ bool autoneg_failed; -+ bool disable_av; -+ bool disable_hw_init_bits; -+ bool get_link_status; -+ bool ifs_params_forced; -+ bool in_ifs_mode; -+ bool report_tx_early; -+ bool serdes_has_link; -+ bool tx_pkt_filtering; -+}; + -+struct e1000_phy_info { -+ struct e1000_phy_operations ops; -+ e1000_phy_type type; ++ return E1000_SUCCESS; ++} + -+ e1000_1000t_rx_status local_rx; -+ e1000_1000t_rx_status remote_rx; -+ e1000_ms_type ms_type; -+ e1000_ms_type original_ms_type; -+ e1000_rev_polarity cable_polarity; -+ e1000_smart_speed smart_speed; ++/** ++ * e1000_check_for_copper_link_ich8lan - Check for link (Copper) ++ * @hw: pointer to the HW structure ++ * ++ * Checks to see of the link status of the hardware has changed. If a ++ * change in link status has been detected, then we read the PHY registers ++ * to get the current speed/duplex if link exists. ++ **/ ++static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) ++{ ++ struct e1000_mac_info *mac = &hw->mac; ++ s32 ret_val; ++ bool link; + -+ u32 addr; -+ u32 id; -+ u32 reset_delay_us; /* in usec */ -+ u32 revision; ++ /* ++ * We only want to go out to the PHY registers to see if Auto-Neg ++ * has completed and/or if our link status has changed. The ++ * get_link_status flag is set upon receiving a Link Status ++ * Change or Rx Sequence Error interrupt. ++ */ ++ if (!mac->get_link_status) { ++ ret_val = E1000_SUCCESS; ++ goto out; ++ } + -+ e1000_media_type media_type; ++ if (hw->mac.type == e1000_pchlan) { ++ ret_val = e1000e_write_kmrn_reg(hw, ++ E1000_KMRNCTRLSTA_K1_CONFIG, ++ E1000_KMRNCTRLSTA_K1_ENABLE); ++ if (ret_val) ++ goto out; ++ } + -+ u16 autoneg_advertised; -+ u16 autoneg_mask; -+ u16 cable_length; -+ u16 max_cable_length; -+ u16 min_cable_length; ++ /* ++ * First we want to see if the MII Status Register reports ++ * link. If so, then we want to get the current speed/duplex ++ * of the PHY. ++ */ ++ ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); ++ if (ret_val) ++ goto out; + -+ u8 mdix; ++ if (!link) ++ goto out; /* No link detected */ + -+ bool disable_polarity_correction; -+ bool is_mdix; -+ bool polarity_correction; -+ bool reset_disable; -+ bool speed_downgraded; -+ bool autoneg_wait_to_complete; -+}; ++ mac->get_link_status = false; + -+struct e1000_nvm_info { -+ struct e1000_nvm_operations ops; -+ e1000_nvm_type type; -+ e1000_nvm_override override; ++ if (hw->phy.type == e1000_phy_82578) { ++ ret_val = e1000_link_stall_workaround_hv(hw); ++ if (ret_val) ++ goto out; ++ } + -+ u32 flash_bank_size; -+ u32 flash_base_addr; -+ u32 semaphore_delay; ++ /* ++ * Check if there was DownShift, must be checked ++ * immediately after link-up ++ */ ++ e1000e_check_downshift(hw); + -+ u16 word_size; -+ u16 delay_usec; -+ u16 address_bits; -+ u16 opcode_bits; -+ u16 page_size; -+}; ++ /* ++ * If we are forcing speed/duplex, then we simply return since ++ * we have already determined whether we have link or not. ++ */ ++ if (!mac->autoneg) { ++ ret_val = -E1000_ERR_CONFIG; ++ goto out; ++ } + -+struct e1000_bus_info { -+ e1000_bus_type type; -+ e1000_bus_speed speed; -+ e1000_bus_width width; ++ /* ++ * Auto-Neg is enabled. Auto Speed Detection takes care ++ * of MAC speed/duplex configuration. So we only need to ++ * configure Collision Distance in the MAC. ++ */ ++ e1000e_config_collision_dist(hw); + -+ u32 snoop; ++ /* ++ * Configure Flow Control now that Auto-Neg has completed. ++ * First, we need to restore the desired flow control ++ * settings because we may have had to re-autoneg with a ++ * different link partner. ++ */ ++ ret_val = e1000e_config_fc_after_link_up(hw); ++ if (ret_val) ++ e_dbg("Error configuring flow control\n"); + -+ u16 func; -+ u16 pci_cmd_word; -+}; ++out: ++ return ret_val; ++} + -+struct e1000_fc_info { -+ u32 high_water; /* Flow control high-water mark */ -+ u32 low_water; /* Flow control low-water mark */ -+ u16 pause_time; /* Flow control pause timer */ -+ bool send_xon; /* Flow control send XON */ -+ bool strict_ieee; /* Strict IEEE mode */ -+ e1000_fc_type type; /* Type of flow control */ -+ e1000_fc_type original_type; -+}; ++/** ++ * e1000_init_function_pointers_ich8lan - Initialize ICH8 function pointers ++ * @hw: pointer to the HW structure ++ * ++ * Initialize family-specific function pointers for PHY, MAC, and NVM. ++ **/ ++void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw) ++{ ++ e1000_init_mac_ops_generic(hw); ++ e1000_init_nvm_ops_generic(hw); ++ hw->mac.ops.init_params = e1000_init_mac_params_ich8lan; ++ hw->nvm.ops.init_params = e1000_init_nvm_params_ich8lan; ++ switch (hw->mac.type) { ++ case e1000_ich8lan: ++ case e1000_ich9lan: ++ case e1000_ich10lan: ++ hw->phy.ops.init_params = e1000_init_phy_params_ich8lan; ++ break; ++ case e1000_pchlan: ++ hw->phy.ops.init_params = e1000_init_phy_params_pchlan; ++ break; ++ default: ++ break; ++ } ++} + -+struct e1000_hw { -+ void *back; -+ void *dev_spec; ++static DEFINE_MUTEX(nvm_mutex); + -+ u8 __iomem *hw_addr; -+ u8 __iomem *flash_address; -+ unsigned long io_base; ++/** ++ * e1000_acquire_swflag_ich8lan - Acquire software control flag ++ * @hw: pointer to the HW structure ++ * ++ * Acquires the software control flag for performing NVM and PHY ++ * operations. This is a function pointer entry point only called by ++ * read/write routines for the PHY and NVM parts. ++ **/ ++static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) ++{ ++ u32 extcnf_ctrl, timeout = PHY_CFG_TIMEOUT; ++ s32 ret_val = E1000_SUCCESS; + -+ struct e1000_mac_info mac; -+ struct e1000_fc_info fc; -+ struct e1000_phy_info phy; -+ struct e1000_nvm_info nvm; -+ struct e1000_bus_info bus; -+ struct e1000_host_mng_dhcp_cookie mng_cookie; ++ might_sleep(); + -+ u32 dev_spec_size; ++ mutex_lock(&nvm_mutex); + -+ u16 device_id; -+ u16 subsystem_vendor_id; -+ u16 subsystem_device_id; -+ u16 vendor_id; ++ while (timeout) { ++ extcnf_ctrl = er32(EXTCNF_CTRL); + -+ u8 revision_id; -+}; ++ if (!(extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)) { ++ extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; ++ ew32(EXTCNF_CTRL, extcnf_ctrl); + -+#include "e1000_82571.h" -+#include "e1000_80003es2lan.h" -+#include "e1000_ich8lan.h" ++ extcnf_ctrl = er32(EXTCNF_CTRL); ++ if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) ++ break; ++ } ++ mdelay(1); ++ timeout--; ++ } + -+/* These functions must be implemented by drivers */ -+s32 e1000_alloc_zeroed_dev_spec_struct(struct e1000_hw *hw, u32 size); -+s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); -+void e1000_free_dev_spec_struct(struct e1000_hw *hw); -+void e1000_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value); ++ if (!timeout) { ++ e_dbg("SW/FW/HW has locked the resource for too long.\n"); ++ extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; ++ ew32(EXTCNF_CTRL, extcnf_ctrl); ++ mutex_unlock(&nvm_mutex); ++ ret_val = -E1000_ERR_CONFIG; ++ goto out; ++ } + -+#endif -diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/drivers/net/e1000e/e1000_ich8lan.c ---- linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000_ich8lan.c 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,2757 @@ -+/******************************************************************************* ++out: ++ return ret_val; ++} + -+ Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++/** ++ * e1000_release_swflag_ich8lan - Release software control flag ++ * @hw: pointer to the HW structure ++ * ++ * Releases the software control flag for performing NVM and PHY operations. ++ * This is a function pointer entry point only called by read/write ++ * routines for the PHY and NVM parts. ++ **/ ++static void e1000_release_swflag_ich8lan(struct e1000_hw *hw) ++{ ++ u32 extcnf_ctrl; + -+ 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. ++ extcnf_ctrl = er32(EXTCNF_CTRL); ++ extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; ++ ew32(EXTCNF_CTRL, extcnf_ctrl); + -+ 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. ++ mutex_unlock(&nvm_mutex); ++} + -+ 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. ++/** ++ * e1000_check_mng_mode_ich8lan - Checks management mode ++ * @hw: pointer to the HW structure ++ * ++ * This checks if the adapter has manageability enabled. ++ * This is a function pointer entry point only called by read/write ++ * routines for the PHY and NVM parts. ++ **/ ++static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw) ++{ ++ u32 fwsm; + -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". ++ fwsm = er32(FWSM); ++ return (fwsm & E1000_FWSM_MODE_MASK) == ++ (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); ++} ++/** ++ * e1000_check_reset_block_ich8lan - Check if PHY reset is blocked ++ * @hw: pointer to the HW structure ++ * ++ * Checks if firmware is blocking the reset of the PHY. ++ * This is a function pointer entry point only called by ++ * reset routines. ++ **/ ++static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw) ++{ ++ u32 fwsm; + -+ Contact Information: -+ Linux NICS -+ e1000-devel Mailing List -+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ fwsm = er32(FWSM); ++ return (fwsm & E1000_ICH_FWSM_RSPCIPHY) ? E1000_SUCCESS ++ : E1000_BLK_PHY_RESET; ++} + -+*******************************************************************************/ ++/** ++ * e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be ++ * done after every PHY reset. ++ **/ ++static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) ++{ ++ s32 ret_val = E1000_SUCCESS; + -+/* e1000_ich8lan -+ * e1000_ich9lan -+ */ ++ if (hw->mac.type != e1000_pchlan) ++ return ret_val; + -+#include "e1000_hw.h" ++ if (((hw->phy.type == e1000_phy_82577) && ++ ((hw->phy.revision == 1) || (hw->phy.revision == 2))) || ++ ((hw->phy.type == e1000_phy_82578) && (hw->phy.revision == 1))) { ++ /* Disable generation of early preamble */ ++ ret_val = e1e_wphy(hw, PHY_REG(769, 25), 0x4431); ++ if (ret_val) ++ return ret_val; + -+static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw); -+static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw); -+static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw); -+static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw); -+static void e1000_release_swflag_ich8lan(struct e1000_hw *hw); -+static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw); -+static s32 e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw); -+static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw); -+static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw); -+static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw); -+static s32 e1000_get_phy_info_ich8lan(struct e1000_hw *hw); -+static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, -+ bool active); -+static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, -+ bool active); -+static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, -+ u16 words, u16 *data); -+static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, -+ u16 words, u16 *data); -+static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw); -+static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw); -+static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, -+ u16 *data); -+static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw); -+static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw); -+static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw); -+static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw); -+static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw); -+static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, -+ u16 *speed, u16 *duplex); -+static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw); -+static s32 e1000_led_on_ich8lan(struct e1000_hw *hw); -+static s32 e1000_led_off_ich8lan(struct e1000_hw *hw); -+static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw); -+static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank); -+static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout); -+static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw); -+static s32 e1000_get_phy_info_ife_ich8lan(struct e1000_hw *hw); -+static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw); -+static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw); -+static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, -+ u32 offset, u8* data); -+static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, -+ u8 size, u16* data); -+static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, -+ u32 offset, u16 *data); -+static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, -+ u32 offset, u8 byte); -+static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, -+ u32 offset, u8 data); -+static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, -+ u8 size, u16 data); -+static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw); -+static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw); ++ /* Preamble tuning for SSC */ ++ ret_val = e1e_wphy(hw, PHY_REG(770, 16), 0xA204); ++ if (ret_val) ++ return ret_val; ++ } + -+/* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ -+/* Offset 04h HSFSTS */ -+union ich8_hws_flash_status { -+ struct ich8_hsfsts { -+ u16 flcdone :1; /* bit 0 Flash Cycle Done */ -+ u16 flcerr :1; /* bit 1 Flash Cycle Error */ -+ u16 dael :1; /* bit 2 Direct Access error Log */ -+ u16 berasesz :2; /* bit 4:3 Sector Erase Size */ -+ u16 flcinprog :1; /* bit 5 flash cycle in Progress */ -+ u16 reserved1 :2; /* bit 13:6 Reserved */ -+ u16 reserved2 :6; /* bit 13:6 Reserved */ -+ u16 fldesvalid :1; /* bit 14 Flash Descriptor Valid */ -+ u16 flockdn :1; /* bit 15 Flash Config Lock-Down */ -+ } hsf_status; -+ u16 regval; -+}; ++ if (hw->phy.type == e1000_phy_82578) { ++ /* ++ * Return registers to default by doing a soft reset then ++ * writing 0x3140 to the control register. ++ */ ++ if (hw->phy.revision < 2) { ++ e1000e_phy_sw_reset(hw); ++ ret_val = e1e_wphy(hw, PHY_CONTROL, ++ 0x3140); ++ } ++ } + -+/* ICH GbE Flash Hardware Sequencing Flash control Register bit breakdown */ -+/* Offset 06h FLCTL */ -+union ich8_hws_flash_ctrl { -+ struct ich8_hsflctl { -+ u16 flcgo :1; /* 0 Flash Cycle Go */ -+ u16 flcycle :2; /* 2:1 Flash Cycle */ -+ u16 reserved :5; /* 7:3 Reserved */ -+ u16 fldbcount :2; /* 9:8 Flash Data Byte Count */ -+ u16 flockdn :6; /* 15:10 Reserved */ -+ } hsf_ctrl; -+ u16 regval; -+}; ++ /* Select page 0 */ ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) ++ return ret_val; ++ hw->phy.addr = 1; ++ e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); ++ hw->phy.ops.release(hw); + -+/* ICH Flash Region Access Permissions */ -+union ich8_hws_flash_regacc { -+ struct ich8_flracc { -+ u32 grra :8; /* 0:7 GbE region Read Access */ -+ u32 grwa :8; /* 8:15 GbE region Write Access */ -+ u32 gmrag :8; /* 23:16 GbE Master Read Access Grant */ -+ u32 gmwag :8; /* 31:24 GbE Master Write Access Grant */ -+ } hsf_flregacc; -+ u16 regval; -+}; ++ return ret_val; ++} + -+struct e1000_shadow_ram { -+ u16 value; -+ bool modified; -+}; ++/** ++ * e1000_lan_init_done_ich8lan - Check for PHY config completion ++ * @hw: pointer to the HW structure ++ * ++ * Check the appropriate indication the MAC has finished configuring the ++ * PHY after a software reset. ++ **/ ++static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw) ++{ ++ u32 data, loop = E1000_ICH8_LAN_INIT_TIMEOUT; + -+struct e1000_dev_spec_ich8lan { -+ bool kmrn_lock_loss_workaround_enabled; -+ struct e1000_shadow_ram shadow_ram[E1000_SHADOW_RAM_WORDS]; -+}; ++ /* Wait for basic configuration completes before proceeding */ ++ do { ++ data = er32(STATUS); ++ data &= E1000_STATUS_LAN_INIT_DONE; ++ udelay(100); ++ } while ((!data) && --loop); ++ ++ /* ++ * If basic configuration is incomplete before the above loop ++ * count reaches 0, loading the configuration from NVM will ++ * leave the PHY in a bad state possibly resulting in no link. ++ */ ++ if (loop == 0) ++ e_dbg("LAN_INIT_DONE not set, increase timeout\n"); ++ ++ /* Clear the Init Done bit for the next init event */ ++ data = er32(STATUS); ++ data &= ~E1000_STATUS_LAN_INIT_DONE; ++ ew32(STATUS, data); ++} + +/** -+ * e1000_init_phy_params_ich8lan - Initialize PHY function pointers ++ * e1000_phy_hw_reset_ich8lan - Performs a PHY reset + * @hw: pointer to the HW structure + * -+ * Initialize family-specific PHY parameters and function pointers. ++ * Resets the PHY ++ * This is a function pointer entry point called by drivers ++ * or other shared routines. + **/ -+static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) ++static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; -+ s32 ret_val = E1000_SUCCESS; -+ u16 i = 0; -+ -+ DEBUGFUNC("e1000_init_phy_params_ich8lan"); -+ -+ phy->addr = 1; -+ phy->reset_delay_us = 100; ++ u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask; ++ s32 ret_val; ++ u16 word_addr, reg_data, reg_addr, phy_page = 0; + -+ phy->ops.acquire = e1000_acquire_swflag_ich8lan; -+ phy->ops.check_polarity = e1000_check_polarity_ife_ich8lan; -+ phy->ops.check_reset_block = e1000_check_reset_block_ich8lan; -+ phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_ich8lan; -+ phy->ops.get_cable_length = e1000_get_cable_length_igp_2; -+ phy->ops.get_cfg_done = e1000_get_cfg_done_ich8lan; -+ phy->ops.get_info = e1000_get_phy_info_ich8lan; -+ phy->ops.read_reg = e1000_read_phy_reg_igp; -+ phy->ops.release = e1000_release_swflag_ich8lan; -+ phy->ops.reset = e1000_phy_hw_reset_ich8lan; -+ phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_ich8lan; -+ phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_ich8lan; -+ phy->ops.write_reg = e1000_write_phy_reg_igp; -+ phy->ops.power_up = e1000_power_up_phy_copper; -+ phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; ++ ret_val = e1000e_phy_hw_reset_generic(hw); ++ if (ret_val) ++ goto out; + -+ /* -+ * We may need to do this twice - once for IGP and if that fails, -+ * we'll set BM func pointers and try again -+ */ -+ ret_val = e1000_determine_phy_address(hw); -+ if (ret_val) { -+ phy->ops.write_reg = e1000_write_phy_reg_bm; -+ phy->ops.read_reg = e1000_read_phy_reg_bm; -+ ret_val = e1000_determine_phy_address(hw); -+ if (ret_val) { -+ DEBUGOUT("Cannot determine PHY address. Erroring out\n"); -+ goto out; -+ } -+ } ++ /* Allow time for h/w to get to a quiescent state after reset */ ++ msleep(10); + -+ phy->id = 0; -+ while ((e1000_phy_unknown == e1000_get_phy_type_from_id(phy->id)) && -+ (i++ < 100)) { -+ msec_delay(1); -+ ret_val = e1000_get_phy_id(hw); ++ if (hw->mac.type == e1000_pchlan) { ++ ret_val = e1000_hv_phy_workarounds_ich8lan(hw); + if (ret_val) + goto out; + } + -+ /* Verify phy id */ -+ switch (phy->id) { -+ case IGP03E1000_E_PHY_ID: -+ phy->type = e1000_phy_igp_3; -+ phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; -+ break; -+ case IFE_E_PHY_ID: -+ case IFE_PLUS_E_PHY_ID: -+ case IFE_C_E_PHY_ID: -+ phy->type = e1000_phy_ife; -+ phy->autoneg_mask = E1000_ALL_NOT_GIG; -+ break; -+ case BME1000_E_PHY_ID: -+ phy->type = e1000_phy_bm; -+ phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; -+ phy->ops.read_reg = e1000_read_phy_reg_bm; -+ phy->ops.write_reg = e1000_write_phy_reg_bm; -+ phy->ops.commit = e1000_phy_sw_reset_generic; -+ break; -+ default: -+ ret_val = -E1000_ERR_PHY; -+ goto out; -+ } -+ -+out: -+ return ret_val; -+} ++ /* ++ * Initialize the PHY from the NVM on ICH platforms. This ++ * is needed due to an issue where the NVM configuration is ++ * not properly autoloaded after power transitions. ++ * Therefore, after each PHY reset, we will load the ++ * configuration data out of the NVM manually. ++ */ ++ if (hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) { ++ /* Check if SW needs configure the PHY */ ++ if ((hw->device_id == E1000_DEV_ID_ICH8_IGP_M_AMT) || ++ (hw->device_id == E1000_DEV_ID_ICH8_IGP_M)) ++ sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; ++ else ++ sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; + -+/** -+ * e1000_init_nvm_params_ich8lan - Initialize NVM function pointers -+ * @hw: pointer to the HW structure -+ * -+ * Initialize family-specific NVM parameters and function -+ * pointers. -+ **/ -+static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) -+{ -+ struct e1000_nvm_info *nvm = &hw->nvm; -+ struct e1000_dev_spec_ich8lan *dev_spec; -+ u32 gfpreg, sector_base_addr, sector_end_addr; -+ s32 ret_val = E1000_SUCCESS; -+ u16 i; ++ data = er32(FEXTNVM); ++ if (!(data & sw_cfg_mask)) ++ goto out; + -+ DEBUGFUNC("e1000_init_nvm_params_ich8lan"); ++ /* Wait for basic configuration completes before proceeding */ ++ e1000_lan_init_done_ich8lan(hw); + -+ /* Can't read flash registers if the register set isn't mapped. */ -+ if (!hw->flash_address) { -+ DEBUGOUT("ERROR: Flash registers not mapped\n"); -+ ret_val = -E1000_ERR_CONFIG; -+ goto out; -+ } ++ /* ++ * Make sure HW does not configure LCD from PHY ++ * extended configuration before SW configuration ++ */ ++ data = er32(EXTCNF_CTRL); ++ if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) ++ goto out; + -+ nvm->type = e1000_nvm_flash_sw; ++ cnf_size = er32(EXTCNF_SIZE); ++ cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK; ++ cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT; ++ if (!cnf_size) ++ goto out; + -+ gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG); ++ cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; ++ cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; + -+ /* -+ * sector_X_addr is a "sector"-aligned address (4096 bytes) -+ * Add 1 to sector_end_addr since this sector is included in -+ * the overall size. -+ */ -+ sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK; -+ sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1; ++ /* Configure LCD from extended configuration region. */ + -+ /* flash_base_addr is byte-aligned */ -+ nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT; ++ /* cnf_base_addr is in DWORD */ ++ word_addr = (u16)(cnf_base_addr << 1); + -+ /* -+ * find total size of the NVM, then cut in half since the total -+ * size represents two separate NVM banks. -+ */ -+ nvm->flash_bank_size = (sector_end_addr - sector_base_addr) -+ << FLASH_SECTOR_ADDR_SHIFT; -+ nvm->flash_bank_size /= 2; -+ /* Adjust to word count */ -+ nvm->flash_bank_size /= sizeof(u16); ++ for (i = 0; i < cnf_size; i++) { ++ ret_val = e1000_read_nvm(hw, (word_addr + i * 2), 1, ++ ®_data); ++ if (ret_val) ++ goto out; + -+ nvm->word_size = E1000_SHADOW_RAM_WORDS; ++ ret_val = e1000_read_nvm(hw, (word_addr + i * 2 + 1), ++ 1, ®_addr); ++ if (ret_val) ++ goto out; + -+ dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; ++ /* Save off the PHY page for future writes. */ ++ if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) { ++ phy_page = reg_data; ++ continue; ++ } + -+ if (!dev_spec) { -+ DEBUGOUT("dev_spec pointer is set to NULL.\n"); -+ ret_val = -E1000_ERR_CONFIG; -+ goto out; -+ } ++ reg_addr |= phy_page; + -+ /* Clear shadow ram */ -+ for (i = 0; i < nvm->word_size; i++) { -+ dev_spec->shadow_ram[i].modified = false; -+ dev_spec->shadow_ram[i].value = 0xFFFF; ++ ret_val = e1e_wphy(hw, (u32)reg_addr, reg_data); ++ if (ret_val) ++ goto out; ++ } + } + -+ /* Function Pointers */ -+ nvm->ops.acquire = e1000_acquire_swflag_ich8lan; -+ nvm->ops.read = e1000_read_nvm_ich8lan; -+ nvm->ops.release = e1000_release_swflag_ich8lan; -+ nvm->ops.update = e1000_update_nvm_checksum_ich8lan; -+ nvm->ops.valid_led_default = e1000_valid_led_default_ich8lan; -+ nvm->ops.validate = e1000_validate_nvm_checksum_ich8lan; -+ nvm->ops.write = e1000_write_nvm_ich8lan; -+ +out: + return ret_val; +} + +/** -+ * e1000_init_mac_params_ich8lan - Initialize MAC function pointers ++ * e1000_get_phy_info_ich8lan - Calls appropriate PHY type get_phy_info + * @hw: pointer to the HW structure + * -+ * Initialize family-specific MAC parameters and function -+ * pointers. ++ * Wrapper for calling the get_phy_info routines for the appropriate phy type. + **/ -+static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) ++static s32 e1000_get_phy_info_ich8lan(struct e1000_hw *hw) +{ -+ struct e1000_mac_info *mac = &hw->mac; -+ s32 ret_val = E1000_SUCCESS; ++ s32 ret_val = -E1000_ERR_PHY_TYPE; ++ ++ switch (hw->phy.type) { ++ case e1000_phy_ife: ++ ret_val = e1000_get_phy_info_ife_ich8lan(hw); ++ break; ++ case e1000_phy_igp_3: ++ case e1000_phy_bm: ++ case e1000_phy_82578: ++ case e1000_phy_82577: ++ ret_val = e1000e_get_phy_info_igp(hw); ++ break; ++ default: ++ break; ++ } + -+ DEBUGFUNC("e1000_init_mac_params_ich8lan"); ++ return ret_val; ++} + -+ /* Set media type function pointer */ -+ hw->phy.media_type = e1000_media_type_copper; ++/** ++ * e1000_get_phy_info_ife_ich8lan - Retrieves various IFE PHY states ++ * @hw: pointer to the HW structure ++ * ++ * Populates "phy" structure with various feature states. ++ * This function is only called by other family-specific ++ * routines. ++ **/ ++static s32 e1000_get_phy_info_ife_ich8lan(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ u16 data; ++ bool link; + -+ /* Set mta register count */ -+ mac->mta_reg_count = 32; -+ /* Set rar entry count */ -+ mac->rar_entry_count = E1000_ICH_RAR_ENTRIES; -+ if (mac->type == e1000_ich8lan) -+ mac->rar_entry_count--; -+ /* Set if part includes ASF firmware */ -+ mac->asf_firmware_present = true; -+ /* Set if manageability features are enabled. */ -+ mac->arc_subsystem_valid = true; ++ ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); ++ if (ret_val) ++ goto out; + -+ /* Function pointers */ ++ if (!link) { ++ e_dbg("Phy info is only valid if link is up\n"); ++ ret_val = -E1000_ERR_CONFIG; ++ goto out; ++ } + -+ /* bus type/speed/width */ -+ mac->ops.get_bus_info = e1000_get_bus_info_ich8lan; -+ /* reset */ -+ mac->ops.reset_hw = e1000_reset_hw_ich8lan; -+ /* hw initialization */ -+ mac->ops.init_hw = e1000_init_hw_ich8lan; -+ /* link setup */ -+ mac->ops.setup_link = e1000_setup_link_ich8lan; -+ /* physical interface setup */ -+ mac->ops.setup_physical_interface = e1000_setup_copper_link_ich8lan; -+ /* check for link */ -+ mac->ops.check_for_link = e1000_check_for_copper_link_generic; -+ /* check management mode */ -+ mac->ops.check_mng_mode = e1000_check_mng_mode_ich8lan; -+ /* link info */ -+ mac->ops.get_link_up_info = e1000_get_link_up_info_ich8lan; -+ /* multicast address update */ -+ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; -+ /* setting MTA */ -+ mac->ops.mta_set = e1000_mta_set_generic; -+ /* blink LED */ -+ mac->ops.blink_led = e1000_blink_led_generic; -+ /* setup LED */ -+ mac->ops.setup_led = e1000_setup_led_generic; -+ /* cleanup LED */ -+ mac->ops.cleanup_led = e1000_cleanup_led_ich8lan; -+ /* turn on/off LED */ -+ mac->ops.led_on = e1000_led_on_ich8lan; -+ mac->ops.led_off = e1000_led_off_ich8lan; -+ /* remove device */ -+ mac->ops.remove_device = e1000_remove_device_generic; -+ /* clear hardware counters */ -+ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan; ++ ret_val = e1e_rphy(hw, IFE_PHY_SPECIAL_CONTROL, &data); ++ if (ret_val) ++ goto out; ++ phy->polarity_correction = (data & IFE_PSC_AUTO_POLARITY_DISABLE) ++ ? false : true; + -+ hw->dev_spec_size = sizeof(struct e1000_dev_spec_ich8lan); ++ if (phy->polarity_correction) { ++ ret_val = e1000_check_polarity_ife(hw); ++ if (ret_val) ++ goto out; ++ } else { ++ /* Polarity is forced */ ++ phy->cable_polarity = (data & IFE_PSC_FORCE_POLARITY) ++ ? e1000_rev_polarity_reversed ++ : e1000_rev_polarity_normal; ++ } + -+ /* Device-specific structure allocation */ -+ ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size); ++ ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data); + if (ret_val) + goto out; + -+ /* Enable PCS Lock-loss workaround for ICH8 */ -+ if (mac->type == e1000_ich8lan) -+ e1000_set_kmrn_lock_loss_workaround_ich8lan(hw, true); ++ phy->is_mdix = (data & IFE_PMC_MDIX_STATUS) ? true : false; + ++ /* The following parameters are undefined for 10/100 operation. */ ++ 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_init_function_pointers_ich8lan - Initialize ICH8 function pointers -+ * @hw: pointer to the HW structure -+ * -+ * Initialize family-specific function pointers for PHY, MAC, and NVM. -+ **/ -+void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw) -+{ -+ DEBUGFUNC("e1000_init_function_pointers_ich8lan"); -+ -+ e1000_init_mac_ops_generic(hw); -+ e1000_init_nvm_ops_generic(hw); -+ hw->mac.ops.init_params = e1000_init_mac_params_ich8lan; -+ hw->nvm.ops.init_params = e1000_init_nvm_params_ich8lan; -+ hw->phy.ops.init_params = e1000_init_phy_params_ich8lan; -+} -+ -+/** -+ * e1000_acquire_swflag_ich8lan - Acquire software control flag ++ * e1000_set_d0_lplu_state_ich8lan - Set Low Power Linkup D0 state + * @hw: pointer to the HW structure ++ * @active: true to enable LPLU, false to disable + * -+ * Acquires the software control flag for performing NVM and PHY -+ * operations. This is a function pointer entry point only called by -+ * read/write routines for the PHY and NVM parts. ++ * Sets the LPLU D0 state according to the active flag. When ++ * activating LPLU this function also disables smart speed ++ * and vice versa. LPLU will not be activated unless the ++ * device autonegotiation advertisement meets standards of ++ * either 10 or 10/100 or 10/100/1000 at all duplexes. ++ * This is a function pointer entry point only called by ++ * PHY setup routines. + **/ -+static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) ++static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) +{ -+ u32 extcnf_ctrl, timeout = PHY_CFG_TIMEOUT; ++ struct e1000_phy_info *phy = &hw->phy; ++ u32 phy_ctrl; + s32 ret_val = E1000_SUCCESS; ++ u16 data; + -+ DEBUGFUNC("e1000_acquire_swflag_ich8lan"); ++ if (phy->type == e1000_phy_ife) ++ goto out; + -+ while (timeout) { -+ extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); -+ extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; -+ E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); ++ phy_ctrl = er32(PHY_CTRL); + -+ extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); -+ if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) -+ break; -+ msec_delay_irq(1); -+ timeout--; -+ } ++ if (active) { ++ phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU; ++ ew32(PHY_CTRL, phy_ctrl); + -+ if (!timeout) { -+ DEBUGOUT("FW or HW has locked the resource for too long.\n"); -+ extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; -+ E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); -+ ret_val = -E1000_ERR_CONFIG; -+ goto out; ++ if (phy->type != e1000_phy_igp_3) ++ goto out; ++ ++ /* ++ * Call gig speed drop workaround on LPLU before accessing ++ * any PHY registers ++ */ ++ if (hw->mac.type == e1000_ich8lan) ++ e1000e_gig_downshift_workaround_ich8lan(hw); ++ ++ /* When LPLU is enabled, we should disable SmartSpeed */ ++ ret_val = e1e_rphy(hw, ++ IGP01E1000_PHY_PORT_CONFIG, ++ &data); ++ data &= ~IGP01E1000_PSCFR_SMART_SPEED; ++ ret_val = e1e_wphy(hw, ++ IGP01E1000_PHY_PORT_CONFIG, ++ data); ++ if (ret_val) ++ goto out; ++ } else { ++ phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU; ++ ew32(PHY_CTRL, phy_ctrl); ++ ++ if (phy->type != e1000_phy_igp_3) ++ 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 = e1e_rphy(hw, ++ IGP01E1000_PHY_PORT_CONFIG, ++ &data); ++ if (ret_val) ++ goto out; ++ ++ data |= IGP01E1000_PSCFR_SMART_SPEED; ++ ret_val = e1e_wphy(hw, ++ IGP01E1000_PHY_PORT_CONFIG, ++ data); ++ if (ret_val) ++ goto out; ++ } else if (phy->smart_speed == e1000_smart_speed_off) { ++ ret_val = e1e_rphy(hw, ++ IGP01E1000_PHY_PORT_CONFIG, ++ &data); ++ if (ret_val) ++ goto out; ++ ++ data &= ~IGP01E1000_PSCFR_SMART_SPEED; ++ ret_val = e1e_wphy(hw, ++ IGP01E1000_PHY_PORT_CONFIG, ++ data); ++ if (ret_val) ++ goto out; ++ } + } + +out: @@ -6256,257 +6593,299 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri +} + +/** -+ * e1000_release_swflag_ich8lan - Release software control flag ++ * e1000_set_d3_lplu_state_ich8lan - Set Low Power Linkup D3 state + * @hw: pointer to the HW structure ++ * @active: true to enable LPLU, false to disable + * -+ * Releases the software control flag for performing NVM and PHY operations. -+ * This is a function pointer entry point only called by read/write -+ * routines for the PHY and NVM parts. ++ * Sets the LPLU D3 state according to the active flag. When ++ * activating LPLU this function also disables smart speed ++ * and vice versa. LPLU will not be activated unless the ++ * device autonegotiation advertisement meets standards of ++ * either 10 or 10/100 or 10/100/1000 at all duplexes. ++ * This is a function pointer entry point only called by ++ * PHY setup routines. + **/ -+static void e1000_release_swflag_ich8lan(struct e1000_hw *hw) ++static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) +{ -+ u32 extcnf_ctrl; ++ struct e1000_phy_info *phy = &hw->phy; ++ u32 phy_ctrl; ++ s32 ret_val = E1000_SUCCESS; ++ u16 data; + -+ DEBUGFUNC("e1000_release_swflag_ich8lan"); ++ phy_ctrl = er32(PHY_CTRL); + -+ extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); -+ extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; -+ E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); ++ if (!active) { ++ phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU; ++ ew32(PHY_CTRL, phy_ctrl); + -+ return; -+} ++ if (phy->type != e1000_phy_igp_3) ++ goto out; + -+/** -+ * e1000_check_mng_mode_ich8lan - Checks management mode -+ * @hw: pointer to the HW structure -+ * -+ * This checks if the adapter has manageability enabled. -+ * This is a function pointer entry point only called by read/write -+ * routines for the PHY and NVM parts. -+ **/ -+static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw) -+{ -+ u32 fwsm; ++ /* ++ * 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 = e1e_rphy(hw, ++ IGP01E1000_PHY_PORT_CONFIG, ++ &data); ++ if (ret_val) ++ goto out; + -+ DEBUGFUNC("e1000_check_mng_mode_ich8lan"); ++ data |= IGP01E1000_PSCFR_SMART_SPEED; ++ ret_val = e1e_wphy(hw, ++ IGP01E1000_PHY_PORT_CONFIG, ++ data); ++ if (ret_val) ++ goto out; ++ } else if (phy->smart_speed == e1000_smart_speed_off) { ++ ret_val = e1e_rphy(hw, ++ IGP01E1000_PHY_PORT_CONFIG, ++ &data); ++ if (ret_val) ++ goto out; + -+ fwsm = E1000_READ_REG(hw, E1000_FWSM); ++ data &= ~IGP01E1000_PSCFR_SMART_SPEED; ++ ret_val = e1e_wphy(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)) { ++ phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU; ++ ew32(PHY_CTRL, phy_ctrl); + -+ return ((fwsm & E1000_FWSM_MODE_MASK) == -+ (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); -+} ++ if (phy->type != e1000_phy_igp_3) ++ goto out; + -+/** -+ * e1000_check_reset_block_ich8lan - Check if PHY reset is blocked -+ * @hw: pointer to the HW structure -+ * -+ * Checks if firmware is blocking the reset of the PHY. -+ * This is a function pointer entry point only called by -+ * reset routines. -+ **/ -+static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw) -+{ -+ u32 fwsm; ++ /* ++ * Call gig speed drop workaround on LPLU before accessing ++ * any PHY registers ++ */ ++ if (hw->mac.type == e1000_ich8lan) ++ e1000e_gig_downshift_workaround_ich8lan(hw); + -+ DEBUGFUNC("e1000_check_reset_block_ich8lan"); ++ /* When LPLU is enabled, we should disable SmartSpeed */ ++ ret_val = e1e_rphy(hw, ++ IGP01E1000_PHY_PORT_CONFIG, ++ &data); ++ if (ret_val) ++ goto out; + -+ fwsm = E1000_READ_REG(hw, E1000_FWSM); ++ data &= ~IGP01E1000_PSCFR_SMART_SPEED; ++ ret_val = e1e_wphy(hw, ++ IGP01E1000_PHY_PORT_CONFIG, ++ data); ++ } + -+ return (fwsm & E1000_ICH_FWSM_RSPCIPHY) ? E1000_SUCCESS -+ : E1000_BLK_PHY_RESET; ++out: ++ return ret_val; +} + +/** -+ * e1000_phy_force_speed_duplex_ich8lan - Force PHY speed & duplex ++ * e1000_valid_nvm_bank_detect_ich8lan - finds out the valid bank 0 or 1 + * @hw: pointer to the HW structure ++ * @bank: pointer to the variable that returns the active bank + * -+ * Forces the speed and duplex settings of the PHY. -+ * This is a function pointer entry point only called by -+ * PHY setup routines. ++ * Reads signature byte from the NVM using the flash access registers. ++ * Word 0x13 bits 15:14 = 10b indicate a valid signature for that bank. + **/ -+static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw) ++static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) +{ -+ struct e1000_phy_info *phy = &hw->phy; -+ s32 ret_val; -+ u16 data; -+ bool link; -+ -+ DEBUGFUNC("e1000_phy_force_speed_duplex_ich8lan"); -+ -+ if (phy->type != e1000_phy_ife) { -+ ret_val = e1000_phy_force_speed_duplex_igp(hw); -+ goto out; -+ } -+ -+ ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &data); -+ if (ret_val) -+ goto out; -+ -+ e1000_phy_force_speed_duplex_setup(hw, &data); -+ -+ ret_val = phy->ops.write_reg(hw, PHY_CONTROL, data); -+ if (ret_val) -+ goto out; -+ -+ /* Disable MDI-X support for 10/100 */ -+ ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data); -+ if (ret_val) -+ goto out; -+ -+ data &= ~IFE_PMC_AUTO_MDIX; -+ data &= ~IFE_PMC_FORCE_MDIX; -+ -+ ret_val = phy->ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, data); -+ if (ret_val) -+ goto out; -+ -+ DEBUGOUT1("IFE PMC: %X\n", data); ++ u32 eecd; ++ struct e1000_nvm_info *nvm = &hw->nvm; ++ u32 bank1_offset = nvm->flash_bank_size * sizeof(u16); ++ u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1; ++ u8 sig_byte = 0; ++ s32 ret_val = E1000_SUCCESS; + -+ usec_delay(1); ++ switch (hw->mac.type) { ++ case e1000_ich8lan: ++ case e1000_ich9lan: ++ eecd = er32(EECD); ++ if ((eecd & E1000_EECD_SEC1VAL_VALID_MASK) == ++ E1000_EECD_SEC1VAL_VALID_MASK) { ++ if (eecd & E1000_EECD_SEC1VAL) ++ *bank = 1; ++ else ++ *bank = 0; + -+ if (phy->autoneg_wait_to_complete) { -+ DEBUGOUT("Waiting for forced speed/duplex link on IFE phy.\n"); ++ goto out; ++ } ++ e_dbg("Unable to determine valid NVM bank via EEC - " ++ "reading flash signature\n"); ++ /* fall-thru */ ++ default: ++ /* set bank to 0 in case flash read fails */ ++ *bank = 0; + -+ ret_val = e1000_phy_has_link_generic(hw, -+ PHY_FORCE_LIMIT, -+ 100000, -+ &link); ++ /* Check bank 0 */ ++ ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset, ++ &sig_byte); + if (ret_val) + goto out; -+ -+ if (!link) { -+ DEBUGOUT("Link taking longer than expected.\n"); ++ if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == ++ E1000_ICH_NVM_SIG_VALUE) { ++ *bank = 0; ++ goto out; + } + -+ /* Try once more */ -+ ret_val = e1000_phy_has_link_generic(hw, -+ PHY_FORCE_LIMIT, -+ 100000, -+ &link); ++ /* Check bank 1 */ ++ ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset + ++ bank1_offset, ++ &sig_byte); + if (ret_val) + goto out; -+ } ++ if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == ++ E1000_ICH_NVM_SIG_VALUE) { ++ *bank = 1; ++ goto out; ++ } + ++ e_dbg("ERROR: No valid NVM bank present\n"); ++ ret_val = -E1000_ERR_NVM; ++ break; ++ } +out: + return ret_val; +} + +/** -+ * e1000_phy_hw_reset_ich8lan - Performs a PHY reset ++ * e1000_read_nvm_ich8lan - Read word(s) from the NVM + * @hw: pointer to the HW structure ++ * @offset: The offset (in bytes) of the word(s) to read. ++ * @words: Size of data to read in words ++ * @data: Pointer to the word(s) to read at offset. + * -+ * Resets the PHY -+ * This is a function pointer entry point called by drivers -+ * or other shared routines. ++ * Reads a word(s) from the NVM using the flash access registers. + **/ -+static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) ++static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, ++ u16 *data) +{ -+ struct e1000_phy_info *phy = &hw->phy; + struct e1000_nvm_info *nvm = &hw->nvm; -+ u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask; -+ s32 ret_val; -+ u16 loop = E1000_ICH8_LAN_INIT_TIMEOUT; -+ u16 word_addr, reg_data, reg_addr, phy_page = 0; ++ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; ++ u32 act_offset; ++ s32 ret_val = E1000_SUCCESS; ++ u32 bank = 0; ++ u16 i, word; + -+ DEBUGFUNC("e1000_phy_hw_reset_ich8lan"); ++ if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || ++ (words == 0)) { ++ e_dbg("nvm parameter(s) out of bounds\n"); ++ ret_val = -E1000_ERR_NVM; ++ goto out; ++ } + -+ ret_val = e1000_phy_hw_reset_generic(hw); ++ ret_val = nvm->ops.acquire(hw); + if (ret_val) + goto out; + -+ /* -+ * Initialize the PHY from the NVM on ICH platforms. This -+ * is needed due to an issue where the NVM configuration is -+ * not properly autoloaded after power transitions. -+ * Therefore, after each PHY reset, we will load the -+ * configuration data out of the NVM manually. -+ */ -+ if (hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) { -+ /* Check if SW needs configure the PHY */ -+ if ((hw->device_id == E1000_DEV_ID_ICH8_IGP_M_AMT) || -+ (hw->device_id == E1000_DEV_ID_ICH8_IGP_M)) -+ sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; -+ else -+ sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; -+ -+ data = E1000_READ_REG(hw, E1000_FEXTNVM); -+ if (!(data & sw_cfg_mask)) -+ goto out; ++ ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); ++ if (ret_val != E1000_SUCCESS) ++ goto release; + -+ /* Wait for basic configuration completes before proceeding*/ -+ do { -+ data = E1000_READ_REG(hw, E1000_STATUS); -+ data &= E1000_STATUS_LAN_INIT_DONE; -+ usec_delay(100); -+ } while ((!data) && --loop); ++ act_offset = (bank) ? nvm->flash_bank_size : 0; ++ act_offset += offset; + -+ /* -+ * If basic configuration is incomplete before the above loop -+ * count reaches 0, loading the configuration from NVM will -+ * leave the PHY in a bad state possibly resulting in no link. -+ */ -+ if (loop == 0) { -+ DEBUGOUT("LAN_INIT_DONE not set, increase timeout\n"); ++ for (i = 0; i < words; i++) { ++ if ((dev_spec->shadow_ram) && ++ (dev_spec->shadow_ram[offset+i].modified)) { ++ data[i] = dev_spec->shadow_ram[offset+i].value; ++ } else { ++ ret_val = e1000_read_flash_word_ich8lan(hw, ++ act_offset + i, ++ &word); ++ if (ret_val) ++ break; ++ data[i] = word; + } ++ } + -+ /* Clear the Init Done bit for the next init event */ -+ data = E1000_READ_REG(hw, E1000_STATUS); -+ data &= ~E1000_STATUS_LAN_INIT_DONE; -+ E1000_WRITE_REG(hw, E1000_STATUS, data); -+ -+ /* -+ * Make sure HW does not configure LCD from PHY -+ * extended configuration before SW configuration -+ */ -+ data = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); -+ if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) -+ goto out; ++release: ++ nvm->ops.release(hw); + -+ cnf_size = E1000_READ_REG(hw, E1000_EXTCNF_SIZE); -+ cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK; -+ cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT; -+ if (!cnf_size) -+ goto out; ++out: ++ if (ret_val) ++ e_dbg("NVM read error: %d\n", ret_val); + -+ cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; -+ cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; ++ return ret_val; ++} + -+ /* -+ * Configure LCD from extended configuration -+ * region. -+ */ ++/** ++ * e1000_flash_cycle_init_ich8lan - Initialize flash ++ * @hw: pointer to the HW structure ++ * ++ * This function does initial flash setup so that a new read/write/erase cycle ++ * can be started. ++ **/ ++static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) ++{ ++ union ich8_hws_flash_status hsfsts; ++ s32 ret_val = -E1000_ERR_NVM; ++ s32 i = 0; + -+ /* cnf_base_addr is in DWORD */ -+ word_addr = (u16)(cnf_base_addr << 1); ++ hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); + -+ for (i = 0; i < cnf_size; i++) { -+ ret_val = nvm->ops.read(hw, -+ (word_addr + i * 2), -+ 1, -+ ®_data); -+ if (ret_val) -+ goto out; ++ /* Check if the flash descriptor is valid */ ++ if (hsfsts.hsf_status.fldesvalid == 0) { ++ e_dbg("Flash descriptor invalid. " ++ "SW Sequencing must be used."); ++ goto out; ++ } + -+ ret_val = nvm->ops.read(hw, -+ (word_addr + i * 2 + 1), -+ 1, -+ ®_addr); -+ if (ret_val) -+ goto out; ++ /* Clear FCERR and DAEL in hw status by writing 1 */ ++ hsfsts.hsf_status.flcerr = 1; ++ hsfsts.hsf_status.dael = 1; + -+ /* Save off the PHY page for future writes. */ -+ if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) { -+ phy_page = reg_data; -+ continue; -+ } ++ ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval); + -+ reg_addr |= phy_page; ++ /* ++ * Either we should have a hardware SPI cycle in progress ++ * bit to check against, in order to start a new cycle or ++ * FDONE bit should be changed in the hardware so that it ++ * is 1 after hardware reset, which can then be used as an ++ * indication whether a cycle is in progress or has been ++ * completed. ++ */ + -+ ret_val = phy->ops.write_reg(hw, -+ (u32)reg_addr, -+ reg_data); -+ if (ret_val) -+ goto out; ++ if (hsfsts.hsf_status.flcinprog == 0) { ++ /* ++ * There is no cycle running at present, ++ * so we can start a cycle. ++ * Begin by setting Flash Cycle Done. ++ */ ++ hsfsts.hsf_status.flcdone = 1; ++ ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval); ++ ret_val = E1000_SUCCESS; ++ } else { ++ /* ++ * Otherwise poll for sometime so the current ++ * cycle has a chance to end before giving up. ++ */ ++ for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) { ++ hsfsts.regval = er16flash( ++ ICH_FLASH_HSFSTS); ++ if (hsfsts.hsf_status.flcinprog == 0) { ++ ret_val = E1000_SUCCESS; ++ break; ++ } ++ udelay(1); ++ } ++ if (ret_val == E1000_SUCCESS) { ++ /* ++ * Successful in waiting for previous cycle to timeout, ++ * now set the Flash Cycle Done. ++ */ ++ hsfsts.hsf_status.flcdone = 1; ++ ew16flash(ICH_FLASH_HSFSTS, ++ hsfsts.regval); ++ } else { ++ e_dbg("Flash controller busy, cannot get access"); + } + } + @@ -6515,402 +6894,189 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri +} + +/** -+ * e1000_get_phy_info_ich8lan - Calls appropriate PHY type get_phy_info ++ * e1000_flash_cycle_ich8lan - Starts flash cycle (read/write/erase) + * @hw: pointer to the HW structure ++ * @timeout: maximum time to wait for completion + * -+ * Wrapper for calling the get_phy_info routines for the appropriate phy type. -+ * This is a function pointer entry point called by drivers -+ * or other shared routines. ++ * This function starts a flash cycle and waits for its completion. + **/ -+static s32 e1000_get_phy_info_ich8lan(struct e1000_hw *hw) ++static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) +{ -+ s32 ret_val = -E1000_ERR_PHY_TYPE; ++ union ich8_hws_flash_ctrl hsflctl; ++ union ich8_hws_flash_status hsfsts; ++ s32 ret_val = -E1000_ERR_NVM; ++ u32 i = 0; + -+ DEBUGFUNC("e1000_get_phy_info_ich8lan"); ++ /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */ ++ hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); ++ hsflctl.hsf_ctrl.flcgo = 1; ++ ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval); + -+ switch (hw->phy.type) { -+ case e1000_phy_ife: -+ ret_val = e1000_get_phy_info_ife_ich8lan(hw); -+ break; -+ case e1000_phy_igp_3: -+ case e1000_phy_bm: -+ ret_val = e1000_get_phy_info_igp(hw); -+ break; -+ default: -+ break; -+ } ++ /* wait till FDONE bit is set to 1 */ ++ do { ++ hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); ++ if (hsfsts.hsf_status.flcdone == 1) ++ break; ++ udelay(1); ++ } while (i++ < timeout); ++ ++ if (hsfsts.hsf_status.flcdone == 1 && hsfsts.hsf_status.flcerr == 0) ++ ret_val = E1000_SUCCESS; + + return ret_val; +} + +/** -+ * e1000_get_phy_info_ife_ich8lan - Retrieves various IFE PHY states ++ * e1000_read_flash_word_ich8lan - Read word from flash + * @hw: pointer to the HW structure ++ * @offset: offset to data location ++ * @data: pointer to the location for storing the data + * -+ * Populates "phy" structure with various feature states. -+ * This function is only called by other family-specific -+ * routines. ++ * Reads the flash word at offset into data. Offset is converted ++ * to bytes before read. + **/ -+static s32 e1000_get_phy_info_ife_ich8lan(struct e1000_hw *hw) ++static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, ++ u16 *data) +{ -+ struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; -+ u16 data; -+ bool link; -+ -+ DEBUGFUNC("e1000_get_phy_info_ife_ich8lan"); -+ -+ 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, IFE_PHY_SPECIAL_CONTROL, &data); -+ if (ret_val) ++ if (!data) { ++ ret_val = -E1000_ERR_NVM; + goto out; -+ phy->polarity_correction = (data & IFE_PSC_AUTO_POLARITY_DISABLE) -+ ? false : true; -+ -+ if (phy->polarity_correction) { -+ ret_val = e1000_check_polarity_ife_ich8lan(hw); -+ if (ret_val) -+ goto out; -+ } else { -+ /* Polarity is forced */ -+ phy->cable_polarity = (data & IFE_PSC_FORCE_POLARITY) -+ ? e1000_rev_polarity_reversed -+ : e1000_rev_polarity_normal; + } + -+ ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data); -+ if (ret_val) -+ goto out; -+ -+ phy->is_mdix = (data & IFE_PMC_MDIX_STATUS) ? true : false; ++ /* Must convert offset into bytes. */ ++ offset <<= 1; + -+ /* The following parameters are undefined for 10/100 operation. */ -+ phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; -+ phy->local_rx = e1000_1000t_rx_status_undefined; -+ phy->remote_rx = e1000_1000t_rx_status_undefined; ++ ret_val = e1000_read_flash_data_ich8lan(hw, offset, 2, data); + +out: + return ret_val; +} + +/** -+ * e1000_check_polarity_ife_ich8lan - Check cable polarity for IFE PHY ++ * e1000_read_flash_byte_ich8lan - Read byte from flash + * @hw: pointer to the HW structure ++ * @offset: The offset of the byte to read. ++ * @data: Pointer to a byte to store the value read. + * -+ * Polarity is determined on the polarity reversal feature being enabled. -+ * This function is only called by other family-specific -+ * routines. ++ * Reads a single byte from the NVM using the flash access registers. + **/ -+static s32 e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw) ++static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, ++ u8 *data) +{ -+ struct e1000_phy_info *phy = &hw->phy; -+ s32 ret_val; -+ u16 phy_data, offset, mask; -+ -+ DEBUGFUNC("e1000_check_polarity_ife_ich8lan"); -+ -+ /* -+ * 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; -+ } ++ s32 ret_val = E1000_SUCCESS; ++ u16 word = 0; + -+ ret_val = phy->ops.read_reg(hw, offset, &phy_data); ++ ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word); ++ if (ret_val) ++ goto out; + -+ if (!ret_val) -+ phy->cable_polarity = (phy_data & mask) -+ ? e1000_rev_polarity_reversed -+ : e1000_rev_polarity_normal; ++ *data = (u8)word; + ++out: + return ret_val; +} + +/** -+ * e1000_set_d0_lplu_state_ich8lan - Set Low Power Linkup D0 state ++ * e1000_read_flash_data_ich8lan - Read byte or word from NVM + * @hw: pointer to the HW structure -+ * @active: true to enable LPLU, false to disable ++ * @offset: The offset (in bytes) of the byte or word to read. ++ * @size: Size of data to read, 1=byte 2=word ++ * @data: Pointer to the word to store the value read. + * -+ * Sets the LPLU D0 state according to the active flag. When -+ * activating LPLU this function also disables smart speed -+ * and vice versa. LPLU will not be activated unless the -+ * device autonegotiation advertisement meets standards of -+ * either 10 or 10/100 or 10/100/1000 at all duplexes. -+ * This is a function pointer entry point only called by -+ * PHY setup routines. ++ * Reads a byte or word from the NVM using the flash access registers. + **/ -+static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, -+ bool active) ++static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, ++ u8 size, u16 *data) +{ -+ struct e1000_phy_info *phy = &hw->phy; -+ u32 phy_ctrl; -+ s32 ret_val = E1000_SUCCESS; -+ u16 data; -+ -+ DEBUGFUNC("e1000_set_d0_lplu_state_ich8lan"); ++ union ich8_hws_flash_status hsfsts; ++ union ich8_hws_flash_ctrl hsflctl; ++ u32 flash_linear_addr; ++ u32 flash_data = 0; ++ s32 ret_val = -E1000_ERR_NVM; ++ u8 count = 0; + -+ if (phy->type == e1000_phy_ife) ++ if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) + goto out; ++ flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) + ++ hw->nvm.flash_base_addr; + -+ phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); -+ -+ if (active) { -+ phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU; -+ E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); -+ -+ /* -+ * Call gig speed drop workaround on LPLU before accessing -+ * any PHY registers -+ */ -+ if ((hw->mac.type == e1000_ich8lan) && -+ (hw->phy.type == e1000_phy_igp_3)) -+ e1000_gig_downshift_workaround_ich8lan(hw); -+ -+ /* When LPLU is enabled, we should disable SmartSpeed */ -+ ret_val = phy->ops.read_reg(hw, -+ IGP01E1000_PHY_PORT_CONFIG, -+ &data); -+ data &= ~IGP01E1000_PSCFR_SMART_SPEED; -+ ret_val = phy->ops.write_reg(hw, -+ IGP01E1000_PHY_PORT_CONFIG, -+ data); -+ if (ret_val) -+ goto out; -+ } else { -+ phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU; -+ E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); -+ -+ /* -+ * 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; -+ } -+ } -+ -+out: -+ return ret_val; -+} -+ -+/** -+ * e1000_set_d3_lplu_state_ich8lan - Set Low Power Linkup D3 state -+ * @hw: pointer to the HW structure -+ * @active: true to enable LPLU, false to disable -+ * -+ * Sets the LPLU D3 state according to the active flag. When -+ * activating LPLU this function also disables smart speed -+ * and vice versa. LPLU will not be activated unless the -+ * device autonegotiation advertisement meets standards of -+ * either 10 or 10/100 or 10/100/1000 at all duplexes. -+ * This is a function pointer entry point only called by -+ * PHY setup routines. -+ **/ -+static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, -+ bool active) -+{ -+ struct e1000_phy_info *phy = &hw->phy; -+ u32 phy_ctrl; -+ s32 ret_val = E1000_SUCCESS; -+ u16 data; -+ -+ DEBUGFUNC("e1000_set_d3_lplu_state_ich8lan"); -+ -+ phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); -+ -+ if (!active) { -+ phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU; -+ E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); -+ /* -+ * 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)) { -+ phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU; -+ E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); -+ -+ /* -+ * Call gig speed drop workaround on LPLU before accessing -+ * any PHY registers -+ */ -+ if ((hw->mac.type == e1000_ich8lan) && -+ (hw->phy.type == e1000_phy_igp_3)) -+ e1000_gig_downshift_workaround_ich8lan(hw); -+ -+ /* 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; ++ do { ++ udelay(1); ++ /* Steps */ ++ ret_val = e1000_flash_cycle_init_ich8lan(hw); ++ if (ret_val != E1000_SUCCESS) ++ break; + -+ data &= ~IGP01E1000_PSCFR_SMART_SPEED; -+ ret_val = phy->ops.write_reg(hw, -+ IGP01E1000_PHY_PORT_CONFIG, -+ data); -+ } ++ hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); ++ /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ ++ hsflctl.hsf_ctrl.fldbcount = size - 1; ++ hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ; ++ ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval); + -+out: -+ return ret_val; -+} ++ ew32flash(ICH_FLASH_FADDR, flash_linear_addr); + -+/** -+ * e1000_valid_nvm_bank_detect_ich8lan - finds out the valid bank 0 or 1 -+ * @hw: pointer to the HW structure -+ * @bank: pointer to the variable that returns the active bank -+ * -+ * Reads signature byte from the NVM using the flash access registers. -+ **/ -+static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) -+{ -+ s32 ret_val = E1000_SUCCESS; -+ struct e1000_nvm_info *nvm = &hw->nvm; -+ /* flash bank size is in words */ -+ u32 bank1_offset = nvm->flash_bank_size * sizeof(u16); -+ u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1; -+ u8 bank_high_byte = 0; ++ ret_val = e1000_flash_cycle_ich8lan(hw, ++ ICH_FLASH_READ_COMMAND_TIMEOUT); + -+ if (hw->mac.type != e1000_ich10lan) { -+ if (E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_SEC1VAL) -+ *bank = 1; -+ else -+ *bank = 0; -+ } else if (hw->dev_spec != NULL) { + /* -+ * Make sure the signature for bank 0 is valid, -+ * if not check for bank1 ++ * Check if FCERR is set to 1, if set to 1, clear it ++ * and try the whole sequence a few more times, else ++ * read in (shift in) the Flash Data0, the order is ++ * least significant byte first msb to lsb + */ -+ e1000_read_flash_byte_ich8lan(hw, act_offset, &bank_high_byte); -+ if ((bank_high_byte & 0xC0) == 0x80) { -+ *bank = 0; ++ if (ret_val == E1000_SUCCESS) { ++ flash_data = er32flash(ICH_FLASH_FDATA0); ++ if (size == 1) ++ *data = (u8)(flash_data & 0x000000FF); ++ else if (size == 2) ++ *data = (u16)(flash_data & 0x0000FFFF); ++ break; + } else { + /* -+ * find if segment 1 is valid by verifying -+ * bit 15:14 = 10b in word 0x13 ++ * If we've gotten here, then things are probably ++ * completely hosed, but if the error condition is ++ * detected, it won't hurt to give it another try... ++ * ICH_FLASH_CYCLE_REPEAT_COUNT times. + */ -+ e1000_read_flash_byte_ich8lan(hw, -+ act_offset + bank1_offset, -+ &bank_high_byte); -+ -+ /* bank1 has a valid signature equivalent to SEC1V */ -+ if ((bank_high_byte & 0xC0) == 0x80) { -+ *bank = 1; -+ } else { -+ DEBUGOUT("ERROR: EEPROM not present\n"); -+ ret_val = -E1000_ERR_NVM; ++ hsfsts.regval = er16flash( ++ ICH_FLASH_HSFSTS); ++ if (hsfsts.hsf_status.flcerr == 1) { ++ /* Repeat for some time before giving up. */ ++ continue; ++ } else if (hsfsts.hsf_status.flcdone == 0) { ++ e_dbg("Timeout error - flash cycle " ++ "did not complete."); ++ break; + } + } -+ } else { -+ DEBUGOUT("DEV SPEC is NULL\n"); -+ ret_val = -E1000_ERR_NVM; -+ } -+ ++ } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); ++ ++out: + return ret_val; +} + +/** -+ * e1000_read_nvm_ich8lan - Read word(s) from the NVM ++ * e1000_write_nvm_ich8lan - Write word(s) to the NVM + * @hw: pointer to the HW structure -+ * @offset: The offset (in bytes) of the word(s) to read. -+ * @words: Size of data to read in words -+ * @data: Pointer to the word(s) to read at offset. ++ * @offset: The offset (in bytes) of the word(s) to write. ++ * @words: Size of data to write in words ++ * @data: Pointer to the word(s) to write at offset. + * -+ * Reads a word(s) from the NVM using the flash access registers. ++ * Writes a byte or word to the NVM using the flash access registers. + **/ -+static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, -+ u16 *data) ++static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, ++ u16 *data) +{ + struct e1000_nvm_info *nvm = &hw->nvm; -+ struct e1000_dev_spec_ich8lan *dev_spec; -+ u32 act_offset; ++ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; + s32 ret_val = E1000_SUCCESS; -+ u32 bank = 0; -+ u16 i, word; -+ -+ DEBUGFUNC("e1000_read_nvm_ich8lan"); -+ -+ dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; -+ -+ if (!dev_spec) { -+ DEBUGOUT("dev_spec pointer is set to NULL.\n"); -+ ret_val = -E1000_ERR_CONFIG; -+ goto out; -+ } ++ u16 i; + + if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || + (words == 0)) { -+ DEBUGOUT("nvm parameter(s) out of bounds\n"); ++ e_dbg("nvm parameter(s) out of bounds\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } @@ -6919,25 +7085,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri + if (ret_val) + goto out; + -+ ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); -+ if (ret_val != E1000_SUCCESS) -+ goto out; -+ -+ act_offset = (bank) ? nvm->flash_bank_size : 0; -+ act_offset += offset; -+ + for (i = 0; i < words; i++) { -+ if ((dev_spec->shadow_ram) && -+ (dev_spec->shadow_ram[offset+i].modified)) { -+ data[i] = dev_spec->shadow_ram[offset+i].value; -+ } else { -+ ret_val = e1000_read_flash_word_ich8lan(hw, -+ act_offset + i, -+ &word); -+ if (ret_val) -+ break; -+ data[i] = word; -+ } ++ dev_spec->shadow_ram[offset+i].modified = true; ++ dev_spec->shadow_ram[offset+i].value = data[i]; + } + + nvm->ops.release(hw); @@ -6947,185 +7097,226 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri +} + +/** -+ * e1000_flash_cycle_init_ich8lan - Initialize flash ++ * e1000_update_nvm_checksum_ich8lan - Update the checksum for NVM + * @hw: pointer to the HW structure + * -+ * This function does initial flash setup so that a new read/write/erase cycle -+ * can be started. ++ * The NVM checksum is updated by calling the generic update_nvm_checksum, ++ * which writes the checksum to the shadow ram. The changes in the shadow ++ * ram are then committed to the EEPROM by processing each bank at a time ++ * checking for the modified bit and writing only the pending changes. ++ * After a successful commit, the shadow ram is cleared and is ready for ++ * future writes. + **/ -+static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) ++static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) +{ -+ union ich8_hws_flash_status hsfsts; -+ s32 ret_val = -E1000_ERR_NVM; -+ s32 i = 0; -+ -+ DEBUGFUNC("e1000_flash_cycle_init_ich8lan"); ++ struct e1000_nvm_info *nvm = &hw->nvm; ++ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; ++ u32 i, act_offset, new_bank_offset, old_bank_offset, bank; ++ s32 ret_val; ++ u16 data; + -+ hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); ++ ret_val = e1000e_update_nvm_checksum_generic(hw); ++ if (ret_val) ++ goto out; + -+ /* Check if the flash descriptor is valid */ -+ if (hsfsts.hsf_status.fldesvalid == 0) { -+ DEBUGOUT("Flash descriptor invalid. " -+ "SW Sequencing must be used."); ++ if (nvm->type != e1000_nvm_flash_sw) + goto out; -+ } + -+ /* Clear FCERR and DAEL in hw status by writing 1 */ -+ hsfsts.hsf_status.flcerr = 1; -+ hsfsts.hsf_status.dael = 1; -+ -+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); ++ ret_val = nvm->ops.acquire(hw); ++ if (ret_val) ++ goto out; + + /* -+ * Either we should have a hardware SPI cycle in progress -+ * bit to check against, in order to start a new cycle or -+ * FDONE bit should be changed in the hardware so that it -+ * is 1 after hardware reset, which can then be used as an -+ * indication whether a cycle is in progress or has been -+ * completed. ++ * We're writing to the opposite bank so if we're on bank 1, ++ * write to bank 0 etc. We also need to erase the segment that ++ * is going to be written + */ ++ ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); ++ if (ret_val != E1000_SUCCESS) { ++ nvm->ops.release(hw); ++ goto out; ++ } + -+ if (hsfsts.hsf_status.flcinprog == 0) { -+ /* -+ * There is no cycle running at present, -+ * so we can start a cycle. -+ * Begin by setting Flash Cycle Done. -+ */ -+ hsfsts.hsf_status.flcdone = 1; -+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); -+ ret_val = E1000_SUCCESS; ++ if (bank == 0) { ++ new_bank_offset = nvm->flash_bank_size; ++ old_bank_offset = 0; ++ ret_val = e1000_erase_flash_bank_ich8lan(hw, 1); ++ if (ret_val) { ++ nvm->ops.release(hw); ++ goto out; ++ } + } else { ++ old_bank_offset = nvm->flash_bank_size; ++ new_bank_offset = 0; ++ ret_val = e1000_erase_flash_bank_ich8lan(hw, 0); ++ if (ret_val) { ++ nvm->ops.release(hw); ++ goto out; ++ } ++ } ++ ++ for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) { + /* -+ * Otherwise poll for sometime so the current -+ * cycle has a chance to end before giving up. ++ * Determine whether to write the value stored ++ * in the other NVM bank or a modified value stored ++ * in the shadow RAM + */ -+ for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) { -+ hsfsts.regval = E1000_READ_FLASH_REG16(hw, -+ ICH_FLASH_HSFSTS); -+ if (hsfsts.hsf_status.flcinprog == 0) { -+ ret_val = E1000_SUCCESS; -+ break; -+ } -+ usec_delay(1); -+ } -+ if (ret_val == E1000_SUCCESS) { -+ /* -+ * Successful in waiting for previous cycle to timeout, -+ * now set the Flash Cycle Done. -+ */ -+ hsfsts.hsf_status.flcdone = 1; -+ E1000_WRITE_FLASH_REG16(hw, -+ ICH_FLASH_HSFSTS, -+ hsfsts.regval); ++ if (dev_spec->shadow_ram[i].modified) { ++ data = dev_spec->shadow_ram[i].value; + } else { -+ DEBUGOUT("Flash controller busy, cannot get access"); ++ ret_val = e1000_read_flash_word_ich8lan(hw, i + ++ old_bank_offset, ++ &data); ++ if (ret_val) ++ break; + } -+ } -+ -+out: -+ return ret_val; -+} -+ -+/** -+ * e1000_flash_cycle_ich8lan - Starts flash cycle (read/write/erase) -+ * @hw: pointer to the HW structure -+ * @timeout: maximum time to wait for completion -+ * -+ * This function starts a flash cycle and waits for its completion. -+ **/ -+static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) -+{ -+ union ich8_hws_flash_ctrl hsflctl; -+ union ich8_hws_flash_status hsfsts; -+ s32 ret_val = -E1000_ERR_NVM; -+ u32 i = 0; + -+ DEBUGFUNC("e1000_flash_cycle_ich8lan"); ++ /* ++ * If the word is 0x13, then make sure the signature bits ++ * (15:14) are 11b until the commit has completed. ++ * This will allow us to write 10b which indicates the ++ * signature is valid. We want to do this after the write ++ * has completed so that we don't mark the segment valid ++ * while the write is still in progress ++ */ ++ if (i == E1000_ICH_NVM_SIG_WORD) ++ data |= E1000_ICH_NVM_SIG_MASK; + -+ /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */ -+ hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); -+ hsflctl.hsf_ctrl.flcgo = 1; -+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); ++ /* Convert offset to bytes. */ ++ act_offset = (i + new_bank_offset) << 1; + -+ /* wait till FDONE bit is set to 1 */ -+ do { -+ hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); -+ if (hsfsts.hsf_status.flcdone == 1) ++ udelay(100); ++ /* Write the bytes to the new bank. */ ++ ret_val = e1000_retry_write_flash_byte_ich8lan(hw, ++ act_offset, ++ (u8)data); ++ if (ret_val) + break; -+ usec_delay(1); -+ } while (i++ < timeout); -+ -+ if (hsfsts.hsf_status.flcdone == 1 && hsfsts.hsf_status.flcerr == 0) -+ ret_val = E1000_SUCCESS; + -+ return ret_val; -+} ++ udelay(100); ++ ret_val = e1000_retry_write_flash_byte_ich8lan(hw, ++ act_offset + 1, ++ (u8)(data >> 8)); ++ if (ret_val) ++ break; ++ } + -+/** -+ * e1000_read_flash_word_ich8lan - Read word from flash -+ * @hw: pointer to the HW structure -+ * @offset: offset to data location -+ * @data: pointer to the location for storing the data -+ * -+ * Reads the flash word at offset into data. Offset is converted -+ * to bytes before read. -+ **/ -+static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, -+ u16 *data) -+{ -+ s32 ret_val; ++ /* ++ * Don't bother writing the segment valid bits if sector ++ * programming failed. ++ */ ++ if (ret_val) { ++ e_dbg("Flash commit failed.\n"); ++ nvm->ops.release(hw); ++ goto out; ++ } + -+ DEBUGFUNC("e1000_read_flash_word_ich8lan"); ++ /* ++ * Finally validate the new segment by setting bit 15:14 ++ * to 10b in word 0x13 , this can be done without an ++ * erase as well since these bits are 11 to start with ++ * and we need to change bit 14 to 0b ++ */ ++ act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD; ++ ret_val = e1000_read_flash_word_ich8lan(hw, act_offset, &data); ++ if (ret_val) { ++ nvm->ops.release(hw); ++ goto out; ++ } ++ data &= 0xBFFF; ++ ret_val = e1000_retry_write_flash_byte_ich8lan(hw, ++ act_offset * 2 + 1, ++ (u8)(data >> 8)); ++ if (ret_val) { ++ nvm->ops.release(hw); ++ goto out; ++ } + -+ if (!data) { -+ ret_val = -E1000_ERR_NVM; ++ /* ++ * And invalidate the previously valid segment by setting ++ * its signature word (0x13) high_byte to 0b. This can be ++ * done without an erase because flash erase sets all bits ++ * to 1's. We can write 1's to 0's without an erase ++ */ ++ act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1; ++ ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0); ++ if (ret_val) { ++ nvm->ops.release(hw); + goto out; + } + -+ /* Must convert offset into bytes. */ -+ offset <<= 1; ++ /* Great! Everything worked, we can now clear the cached entries. */ ++ for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) { ++ dev_spec->shadow_ram[i].modified = false; ++ dev_spec->shadow_ram[i].value = 0xFFFF; ++ } + -+ ret_val = e1000_read_flash_data_ich8lan(hw, offset, 2, data); ++ nvm->ops.release(hw); ++ ++ /* ++ * Reload the EEPROM, or else modifications will not appear ++ * until after the next adapter reset. ++ */ ++ nvm->ops.reload(hw); ++ msleep(10); + +out: ++ if (ret_val) ++ e_dbg("NVM update error: %d\n", ret_val); ++ + return ret_val; +} + +/** -+ * e1000_read_flash_byte_ich8lan - Read byte from flash ++ * e1000_validate_nvm_checksum_ich8lan - Validate EEPROM checksum + * @hw: pointer to the HW structure -+ * @offset: The offset of the byte to read. -+ * @data: Pointer to a byte to store the value read. + * -+ * Reads a single byte from the NVM using the flash access registers. ++ * Check to see if checksum needs to be fixed by reading bit 6 in word 0x19. ++ * If the bit is 0, that the EEPROM had been modified, but the checksum was not ++ * calculated, in which case we need to calculate the checksum and set bit 6. + **/ -+static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, -+ u8* data) ++static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; -+ u16 word = 0; ++ u16 data; + -+ ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word); ++ /* ++ * Read 0x19 and check bit 6. If this bit is 0, the checksum ++ * needs to be fixed. This bit is an indication that the NVM ++ * was prepared by OEM software and did not calculate the ++ * checksum...a likely scenario. ++ */ ++ ret_val = e1000_read_nvm(hw, 0x19, 1, &data); + if (ret_val) + goto out; + -+ *data = (u8)word; ++ if ((data & 0x40) == 0) { ++ data |= 0x40; ++ ret_val = e1000_write_nvm(hw, 0x19, 1, &data); ++ if (ret_val) ++ goto out; ++ ret_val = e1000e_update_nvm_checksum(hw); ++ if (ret_val) ++ goto out; ++ } ++ ++ ret_val = e1000e_validate_nvm_checksum_generic(hw); + +out: + return ret_val; +} + +/** -+ * e1000_read_flash_data_ich8lan - Read byte or word from NVM ++ * e1000_write_flash_data_ich8lan - Writes bytes to the NVM + * @hw: pointer to the HW structure -+ * @offset: The offset (in bytes) of the byte or word to read. ++ * @offset: The offset (in bytes) of the byte/word to read. + * @size: Size of data to read, 1=byte 2=word -+ * @data: Pointer to the word to store the value read. ++ * @data: The byte(s) to write to the NVM. + * -+ * Reads a byte or word from the NVM using the flash access registers. ++ * Writes one/two bytes to the NVM using the flash access registers. + **/ -+static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, -+ u8 size, u16* data) ++static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, ++ u8 size, u16 data) +{ + union ich8_hws_flash_status hsfsts; + union ich8_hws_flash_ctrl hsflctl; @@ -7134,63 +7325,58 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri + s32 ret_val = -E1000_ERR_NVM; + u8 count = 0; + -+ DEBUGFUNC("e1000_read_flash_data_ich8lan"); -+ -+ if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) ++ if (size < 1 || size > 2 || data > size * 0xff || ++ offset > ICH_FLASH_LINEAR_ADDR_MASK) + goto out; + + flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) + + hw->nvm.flash_base_addr; + + do { -+ usec_delay(1); ++ udelay(1); + /* Steps */ + ret_val = e1000_flash_cycle_init_ich8lan(hw); + if (ret_val != E1000_SUCCESS) + break; + -+ hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); ++ hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); + /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ + hsflctl.hsf_ctrl.fldbcount = size - 1; -+ hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ; -+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); ++ hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; ++ ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval); ++ ++ ew32flash(ICH_FLASH_FADDR, flash_linear_addr); ++ ++ if (size == 1) ++ flash_data = (u32)data & 0x00FF; ++ else ++ flash_data = (u32)data; + -+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); ++ ew32flash(ICH_FLASH_FDATA0, flash_data); + ++ /* ++ * check if FCERR is set to 1 , if set to 1, clear it ++ * and try the whole sequence a few more times else done ++ */ + ret_val = e1000_flash_cycle_ich8lan(hw, -+ ICH_FLASH_READ_COMMAND_TIMEOUT); ++ ICH_FLASH_WRITE_COMMAND_TIMEOUT); ++ if (ret_val == E1000_SUCCESS) ++ break; + + /* -+ * Check if FCERR is set to 1, if set to 1, clear it -+ * and try the whole sequence a few more times, else -+ * read in (shift in) the Flash Data0, the order is -+ * least significant byte first msb to lsb ++ * If we're here, then things are most likely ++ * completely hosed, but if the error condition ++ * is detected, it won't hurt to give it another ++ * try...ICH_FLASH_CYCLE_REPEAT_COUNT times. + */ -+ if (ret_val == E1000_SUCCESS) { -+ flash_data = E1000_READ_FLASH_REG(hw, ICH_FLASH_FDATA0); -+ if (size == 1) { -+ *data = (u8)(flash_data & 0x000000FF); -+ } else if (size == 2) { -+ *data = (u16)(flash_data & 0x0000FFFF); -+ } ++ hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); ++ if (hsfsts.hsf_status.flcerr == 1) { ++ /* Repeat for some time before giving up. */ ++ continue; ++ } else if (hsfsts.hsf_status.flcdone == 0) { ++ e_dbg("Timeout error - flash cycle " ++ "did not complete."); + break; -+ } else { -+ /* -+ * If we've gotten here, then things are probably -+ * completely hosed, but if the error condition is -+ * detected, it won't hurt to give it another try... -+ * ICH_FLASH_CYCLE_REPEAT_COUNT times. -+ */ -+ hsfsts.regval = E1000_READ_FLASH_REG16(hw, -+ ICH_FLASH_HSFSTS); -+ if (hsfsts.hsf_status.flcerr == 1) { -+ /* Repeat for some time before giving up. */ -+ continue; -+ } else if (hsfsts.hsf_status.flcdone == 0) { -+ DEBUGOUT("Timeout error - flash cycle " -+ "did not complete."); -+ break; -+ } + } + } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); + @@ -7199,749 +7385,474 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri +} + +/** -+ * e1000_write_nvm_ich8lan - Write word(s) to the NVM ++ * e1000_write_flash_byte_ich8lan - Write a single byte to NVM + * @hw: pointer to the HW structure -+ * @offset: The offset (in bytes) of the word(s) to write. -+ * @words: Size of data to write in words -+ * @data: Pointer to the word(s) to write at offset. ++ * @offset: The index of the byte to read. ++ * @data: The byte to write to the NVM. + * -+ * Writes a byte or word to the NVM using the flash access registers. ++ * Writes a single byte to the NVM using the flash access registers. + **/ -+static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, -+ u16 *data) ++static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, ++ u8 data) +{ -+ struct e1000_nvm_info *nvm = &hw->nvm; -+ struct e1000_dev_spec_ich8lan *dev_spec; -+ s32 ret_val = E1000_SUCCESS; -+ u16 i; ++ u16 word = (u16)data; + -+ DEBUGFUNC("e1000_write_nvm_ich8lan"); ++ return e1000_write_flash_data_ich8lan(hw, offset, 1, word); ++} + -+ dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; ++/** ++ * e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM ++ * @hw: pointer to the HW structure ++ * @offset: The offset of the byte to write. ++ * @byte: The byte to write to the NVM. ++ * ++ * Writes a single byte to the NVM using the flash access registers. ++ * Goes through a retry algorithm before giving up. ++ **/ ++static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, ++ u32 offset, u8 byte) ++{ ++ s32 ret_val; ++ u16 program_retries; + -+ if (!dev_spec) { -+ DEBUGOUT("dev_spec pointer is set to NULL.\n"); -+ ret_val = -E1000_ERR_CONFIG; ++ ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); ++ if (ret_val == E1000_SUCCESS) + goto out; -+ } + -+ 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 (program_retries = 0; program_retries < 100; program_retries++) { ++ e_dbg("Retrying Byte %2.2X at offset %u\n", byte, offset); ++ udelay(100); ++ ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); ++ if (ret_val == E1000_SUCCESS) ++ break; + } -+ -+ ret_val = nvm->ops.acquire(hw); -+ if (ret_val) ++ if (program_retries == 100) { ++ ret_val = -E1000_ERR_NVM; + goto out; -+ -+ for (i = 0; i < words; i++) { -+ dev_spec->shadow_ram[offset+i].modified = true; -+ dev_spec->shadow_ram[offset+i].value = data[i]; + } + -+ nvm->ops.release(hw); -+ +out: + return ret_val; +} + +/** -+ * e1000_update_nvm_checksum_ich8lan - Update the checksum for NVM ++ * e1000_erase_flash_bank_ich8lan - Erase a bank (4k) from NVM + * @hw: pointer to the HW structure ++ * @bank: 0 for first bank, 1 for second bank, etc. + * -+ * The NVM checksum is updated by calling the generic update_nvm_checksum, -+ * which writes the checksum to the shadow ram. The changes in the shadow -+ * ram are then committed to the EEPROM by processing each bank at a time -+ * checking for the modified bit and writing only the pending changes. -+ * After a successful commit, the shadow ram is cleared and is ready for -+ * future writes. ++ * Erases the bank specified. Each bank is a 4k block. Banks are 0 based. ++ * bank N is 4096 * N + flash_reg_addr. + **/ -+static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) ++static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) +{ + struct e1000_nvm_info *nvm = &hw->nvm; -+ struct e1000_dev_spec_ich8lan *dev_spec; -+ u32 i, act_offset, new_bank_offset, old_bank_offset, bank; -+ s32 ret_val; -+ u16 data; -+ -+ DEBUGFUNC("e1000_update_nvm_checksum_ich8lan"); -+ -+ dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; -+ -+ ret_val = e1000_update_nvm_checksum_generic(hw); -+ if (ret_val) -+ goto out; -+ -+ if (nvm->type != e1000_nvm_flash_sw) -+ goto out; ++ union ich8_hws_flash_status hsfsts; ++ union ich8_hws_flash_ctrl hsflctl; ++ u32 flash_linear_addr; ++ /* bank size is in 16bit words - adjust to bytes */ ++ u32 flash_bank_size = nvm->flash_bank_size * 2; ++ s32 ret_val = E1000_SUCCESS; ++ s32 count = 0; ++ s32 j, iteration, sector_size; + -+ ret_val = nvm->ops.acquire(hw); -+ if (ret_val) -+ goto out; ++ hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); + + /* -+ * We're writing to the opposite bank so if we're on bank 1, -+ * write to bank 0 etc. We also need to erase the segment that -+ * is going to be written ++ * Determine HW Sector size: Read BERASE bits of hw flash status ++ * register ++ * 00: The Hw sector is 256 bytes, hence we need to erase 16 ++ * consecutive sectors. The start index for the nth Hw sector ++ * can be calculated as = bank * 4096 + n * 256 ++ * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector. ++ * The start index for the nth Hw sector can be calculated ++ * as = bank * 4096 ++ * 10: The Hw sector is 8K bytes, nth sector = bank * 8192 ++ * (ich9 only, otherwise error condition) ++ * 11: The Hw sector is 64K bytes, nth sector = bank * 65536 + */ -+ ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); -+ if (ret_val != E1000_SUCCESS) ++ switch (hsfsts.hsf_status.berasesz) { ++ case 0: ++ /* Hw sector size 256 */ ++ sector_size = ICH_FLASH_SEG_SIZE_256; ++ iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_256; ++ break; ++ case 1: ++ sector_size = ICH_FLASH_SEG_SIZE_4K; ++ iteration = 1; ++ break; ++ case 2: ++ if (hw->mac.type == e1000_ich9lan) { ++ sector_size = ICH_FLASH_SEG_SIZE_8K; ++ iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_8K; ++ } else { ++ ret_val = -E1000_ERR_NVM; ++ goto out; ++ } ++ break; ++ case 3: ++ sector_size = ICH_FLASH_SEG_SIZE_64K; ++ iteration = 1; ++ break; ++ default: ++ ret_val = -E1000_ERR_NVM; + goto out; -+ -+ if (bank == 0) { -+ new_bank_offset = nvm->flash_bank_size; -+ old_bank_offset = 0; -+ e1000_erase_flash_bank_ich8lan(hw, 1); -+ } else { -+ old_bank_offset = nvm->flash_bank_size; -+ new_bank_offset = 0; -+ e1000_erase_flash_bank_ich8lan(hw, 0); + } + -+ for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) { -+ /* -+ * Determine whether to write the value stored -+ * in the other NVM bank or a modified value stored -+ * in the shadow RAM -+ */ -+ if (dev_spec->shadow_ram[i].modified) { -+ data = dev_spec->shadow_ram[i].value; -+ } else { -+ e1000_read_flash_word_ich8lan(hw, -+ i + old_bank_offset, -+ &data); -+ } ++ /* Start with the base address, then add the sector offset. */ ++ flash_linear_addr = hw->nvm.flash_base_addr; ++ flash_linear_addr += (bank) ? (sector_size * iteration) : 0; + -+ /* -+ * If the word is 0x13, then make sure the signature bits -+ * (15:14) are 11b until the commit has completed. -+ * This will allow us to write 10b which indicates the -+ * signature is valid. We want to do this after the write -+ * has completed so that we don't mark the segment valid -+ * while the write is still in progress -+ */ -+ if (i == E1000_ICH_NVM_SIG_WORD) -+ data |= E1000_ICH_NVM_SIG_MASK; ++ for (j = 0; j < iteration ; j++) { ++ do { ++ /* Steps */ ++ ret_val = e1000_flash_cycle_init_ich8lan(hw); ++ if (ret_val) ++ goto out; + -+ /* Convert offset to bytes. */ -+ act_offset = (i + new_bank_offset) << 1; ++ /* ++ * Write a value 11 (block Erase) in Flash ++ * Cycle field in hw flash control ++ */ ++ hsflctl.regval = er16flash( ++ ICH_FLASH_HSFCTL); ++ hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE; ++ ew16flash(ICH_FLASH_HSFCTL, ++ hsflctl.regval); + -+ usec_delay(100); -+ /* Write the bytes to the new bank. */ -+ ret_val = e1000_retry_write_flash_byte_ich8lan(hw, -+ act_offset, -+ (u8)data); -+ if (ret_val) -+ break; ++ /* ++ * Write the last 24 bits of an index within the ++ * block into Flash Linear address field in Flash ++ * Address. ++ */ ++ flash_linear_addr += (j * sector_size); ++ ew32flash(ICH_FLASH_FADDR, ++ flash_linear_addr); + -+ usec_delay(100); -+ ret_val = e1000_retry_write_flash_byte_ich8lan(hw, -+ act_offset + 1, -+ (u8)(data >> 8)); -+ if (ret_val) -+ break; -+ } ++ ret_val = e1000_flash_cycle_ich8lan(hw, ++ ICH_FLASH_ERASE_COMMAND_TIMEOUT); ++ if (ret_val == E1000_SUCCESS) ++ break; + -+ /* -+ * Don't bother writing the segment valid bits if sector -+ * programming failed. -+ */ -+ if (ret_val) { -+ /* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */ -+ DEBUGOUT("Flash commit failed.\n"); -+ nvm->ops.release(hw); -+ goto out; ++ /* ++ * Check if FCERR is set to 1. If 1, ++ * clear it and try the whole sequence ++ * a few more times else Done ++ */ ++ hsfsts.regval = er16flash( ++ ICH_FLASH_HSFSTS); ++ if (hsfsts.hsf_status.flcerr == 1) ++ /* repeat for some time before giving up */ ++ continue; ++ else if (hsfsts.hsf_status.flcdone == 0) ++ goto out; ++ } while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT); + } + -+ /* -+ * Finally validate the new segment by setting bit 15:14 -+ * to 10b in word 0x13 , this can be done without an -+ * erase as well since these bits are 11 to start with -+ * and we need to change bit 14 to 0b -+ */ -+ act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD; -+ e1000_read_flash_word_ich8lan(hw, act_offset, &data); -+ data &= 0xBFFF; -+ ret_val = e1000_retry_write_flash_byte_ich8lan(hw, -+ act_offset * 2 + 1, -+ (u8)(data >> 8)); ++out: ++ return ret_val; ++} ++ ++/** ++ * e1000_valid_led_default_ich8lan - Set the default LED settings ++ * @hw: pointer to the HW structure ++ * @data: Pointer to the LED settings ++ * ++ * Reads the LED default settings from the NVM to data. If the NVM LED ++ * settings is all 0's or F's, set the LED default to a valid LED default ++ * setting. ++ **/ ++static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data) ++{ ++ s32 ret_val; ++ ++ ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data); + if (ret_val) { -+ nvm->ops.release(hw); ++ e_dbg("NVM Read Error\n"); + goto out; + } + -+ /* -+ * And invalidate the previously valid segment by setting -+ * its signature word (0x13) high_byte to 0b. This can be -+ * done without an erase because flash erase sets all bits -+ * to 1's. We can write 1's to 0's without an erase -+ */ -+ act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1; -+ ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0); -+ if (ret_val) { -+ nvm->ops.release(hw); -+ goto out; -+ } -+ -+ /* Great! Everything worked, we can now clear the cached entries. */ -+ for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) { -+ dev_spec->shadow_ram[i].modified = false; -+ dev_spec->shadow_ram[i].value = 0xFFFF; -+ } -+ -+ nvm->ops.release(hw); -+ -+ /* -+ * Reload the EEPROM, or else modifications will not appear -+ * until after the next adapter reset. -+ */ -+ nvm->ops.reload(hw); -+ msec_delay(10); ++ if (*data == ID_LED_RESERVED_0000 || ++ *data == ID_LED_RESERVED_FFFF) ++ *data = ID_LED_DEFAULT_ICH8LAN; + +out: + return ret_val; +} + +/** -+ * e1000_validate_nvm_checksum_ich8lan - Validate EEPROM checksum ++ * e1000_id_led_init_pchlan - store LED configurations + * @hw: pointer to the HW structure + * -+ * Check to see if checksum needs to be fixed by reading bit 6 in word 0x19. -+ * If the bit is 0, that the EEPROM had been modified, but the checksum was -+ * not calculated, in which case we need to calculate the checksum and set -+ * bit 6. ++ * PCH does not control LEDs via the LEDCTL register, rather it uses ++ * the PHY LED configuration register. ++ * ++ * PCH also does not have an "always on" or "always off" mode which ++ * complicates the ID feature. Instead of using the "on" mode to indicate ++ * in ledctl_mode2 the LEDs to use for ID (see e1000e_id_led_init()), ++ * use "link_up" mode. The LEDs will still ID on request if there is no ++ * link based on logic in e1000_led_[on|off]_pchlan(). + **/ -+static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) ++static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw) +{ -+ s32 ret_val = E1000_SUCCESS; -+ u16 data; -+ -+ DEBUGFUNC("e1000_validate_nvm_checksum_ich8lan"); ++ struct e1000_mac_info *mac = &hw->mac; ++ s32 ret_val; ++ const u32 ledctl_on = E1000_LEDCTL_MODE_LINK_UP; ++ const u32 ledctl_off = E1000_LEDCTL_MODE_LINK_UP | E1000_PHY_LED0_IVRT; ++ u16 data, i, temp, shift; + -+ /* -+ * Read 0x19 and check bit 6. If this bit is 0, the checksum -+ * needs to be fixed. This bit is an indication that the NVM -+ * was prepared by OEM software and did not calculate the -+ * checksum...a likely scenario. -+ */ -+ ret_val = hw->nvm.ops.read(hw, 0x19, 1, &data); ++ /* Get default ID LED modes */ ++ ret_val = hw->nvm.ops.valid_led_default(hw, &data); + if (ret_val) + goto out; + -+ if ((data & 0x40) == 0) { -+ data |= 0x40; -+ ret_val = hw->nvm.ops.write(hw, 0x19, 1, &data); -+ if (ret_val) -+ goto out; -+ ret_val = hw->nvm.ops.update(hw); -+ if (ret_val) -+ goto out; -+ } ++ mac->ledctl_default = er32(LEDCTL); ++ mac->ledctl_mode1 = mac->ledctl_default; ++ mac->ledctl_mode2 = mac->ledctl_default; + -+ ret_val = e1000_validate_nvm_checksum_generic(hw); ++ for (i = 0; i < 4; i++) { ++ temp = (data >> (i << 2)) & E1000_LEDCTL_LED0_MODE_MASK; ++ shift = (i * 5); ++ switch (temp) { ++ case ID_LED_ON1_DEF2: ++ case ID_LED_ON1_ON2: ++ case ID_LED_ON1_OFF2: ++ mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift); ++ mac->ledctl_mode1 |= (ledctl_on << shift); ++ break; ++ case ID_LED_OFF1_DEF2: ++ case ID_LED_OFF1_ON2: ++ case ID_LED_OFF1_OFF2: ++ mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift); ++ mac->ledctl_mode1 |= (ledctl_off << shift); ++ break; ++ default: ++ /* Do nothing */ ++ break; ++ } ++ switch (temp) { ++ case ID_LED_DEF1_ON2: ++ case ID_LED_ON1_ON2: ++ case ID_LED_OFF1_ON2: ++ mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift); ++ mac->ledctl_mode2 |= (ledctl_on << shift); ++ break; ++ case ID_LED_DEF1_OFF2: ++ case ID_LED_ON1_OFF2: ++ case ID_LED_OFF1_OFF2: ++ mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift); ++ mac->ledctl_mode2 |= (ledctl_off << shift); ++ break; ++ default: ++ /* Do nothing */ ++ break; ++ } ++ } + +out: + return ret_val; +} + +/** -+ * e1000e_write_protect_nvm_ich8lan - Make the NVM read-only ++ * e1000_get_bus_info_ich8lan - Get/Set the bus type and width + * @hw: pointer to the HW structure + * -+ * To prevent malicious write/erase of the NVM, set it to be read-only -+ * so that the hardware ignores all write/erase cycles of the NVM via -+ * the flash control registers. The shadow-ram copy of the NVM will -+ * still be updated, however any updates to this copy will not stick -+ * across driver reloads. ++ * ICH8 use the PCI Express bus, but does not contain a PCI Express Capability ++ * register, so the the bus width is hard coded. + **/ -+void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw) ++static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw) +{ -+ union ich8_flash_protected_range pr0; -+ union ich8_hws_flash_status hsfsts; -+ u32 gfpreg; ++ struct e1000_bus_info *bus = &hw->bus; + s32 ret_val; + -+ ret_val = e1000_acquire_swflag_ich8lan(hw); -+ if (ret_val) -+ return; -+ -+ gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG); -+ -+ /* Write-protect GbE Sector of NVM */ -+ pr0.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_PR0); -+ pr0.range.base = gfpreg & FLASH_GFPREG_BASE_MASK; -+ pr0.range.limit = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK); -+ pr0.range.wpe = true; -+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_PR0, pr0.regval); ++ ret_val = e1000e_get_bus_info_pcie(hw); + + /* -+ * Lock down a subset of GbE Flash Control Registers, e.g. -+ * PR0 to prevent the write-protection from being lifted. -+ * Once FLOCKDN is set, the registers protected by it cannot -+ * be written until FLOCKDN is cleared by a hardware reset. ++ * ICH devices are "PCI Express"-ish. They have ++ * a configuration space, but do not contain ++ * PCI Express Capability registers, so bus width ++ * must be hardcoded. + */ -+ hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); -+ hsfsts.hsf_status.flockdn = true; -+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); ++ if (bus->width == e1000_bus_width_unknown) ++ bus->width = e1000_bus_width_pcie_x1; + -+ e1000_release_swflag_ich8lan(hw); ++ return ret_val; +} + +/** -+ * e1000_write_flash_data_ich8lan - Writes bytes to the NVM ++ * e1000_reset_hw_ich8lan - Reset the hardware + * @hw: pointer to the HW structure -+ * @offset: The offset (in bytes) of the byte/word to read. -+ * @size: Size of data to read, 1=byte 2=word -+ * @data: The byte(s) to write to the NVM. + * -+ * Writes one/two bytes to the NVM using the flash access registers. ++ * Does a full reset of the hardware which includes a reset of the PHY and ++ * MAC. + **/ -+static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, -+ u8 size, u16 data) ++static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) +{ -+ union ich8_hws_flash_status hsfsts; -+ union ich8_hws_flash_ctrl hsflctl; -+ u32 flash_linear_addr; -+ u32 flash_data = 0; -+ s32 ret_val = -E1000_ERR_NVM; -+ u8 count = 0; -+ -+ DEBUGFUNC("e1000_write_ich8_data"); ++ u32 ctrl, icr, kab; ++ s32 ret_val; + -+ if (size < 1 || size > 2 || data > size * 0xff || -+ offset > ICH_FLASH_LINEAR_ADDR_MASK) -+ goto out; ++ /* ++ * Prevent the PCI-E bus from sticking if there is no TLP connection ++ * on the last TLP read/write transaction when MAC is reset. ++ */ ++ ret_val = e1000e_disable_pcie_master(hw); ++ if (ret_val) ++ e_dbg("PCI-E Master disable polling has failed.\n"); + -+ flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) + -+ hw->nvm.flash_base_addr; ++ e_dbg("Masking off all interrupts\n"); ++ ew32(IMC, 0xffffffff); + -+ do { -+ usec_delay(1); -+ /* Steps */ -+ ret_val = e1000_flash_cycle_init_ich8lan(hw); -+ if (ret_val != E1000_SUCCESS) -+ break; ++ /* ++ * Disable the Transmit and Receive units. Then delay to allow ++ * any pending transactions to complete before we hit the MAC ++ * with the global reset. ++ */ ++ ew32(RCTL, 0); ++ ew32(TCTL, E1000_TCTL_PSP); ++ e1e_flush(); + -+ hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); -+ /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ -+ hsflctl.hsf_ctrl.fldbcount = size -1; -+ hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; -+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); ++ msleep(10); + -+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); ++ /* Workaround for ICH8 bit corruption issue in FIFO memory */ ++ if (hw->mac.type == e1000_ich8lan) { ++ /* Set Tx and Rx buffer allocation to 8k apiece. */ ++ ew32(PBA, E1000_PBA_8K); ++ /* Set Packet Buffer Size to 16k. */ ++ ew32(PBS, E1000_PBS_16K); ++ } + -+ if (size == 1) -+ flash_data = (u32)data & 0x00FF; -+ else -+ flash_data = (u32)data; ++ ctrl = er32(CTRL); + -+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FDATA0, flash_data); ++ if (!e1000_check_reset_block(hw) && !hw->phy.reset_disable) { ++ /* Clear PHY Reset Asserted bit */ ++ if (hw->mac.type >= e1000_pchlan) { ++ u32 status = er32(STATUS); ++ ew32(STATUS, status & ++ ~E1000_STATUS_PHYRA); ++ } + + /* -+ * check if FCERR is set to 1 , if set to 1, clear it -+ * and try the whole sequence a few more times else done ++ * PHY HW reset requires MAC CORE reset at the same ++ * time to make sure the interface between MAC and the ++ * external PHY is reset. + */ -+ ret_val = e1000_flash_cycle_ich8lan(hw, -+ ICH_FLASH_WRITE_COMMAND_TIMEOUT); -+ if (ret_val == E1000_SUCCESS) { -+ break; -+ } else { ++ ctrl |= E1000_CTRL_PHY_RST; ++ } ++ ret_val = e1000_acquire_swflag_ich8lan(hw); ++ e_dbg("Issuing a global reset to ich8lan\n"); ++ ew32(CTRL, (ctrl | E1000_CTRL_RST)); ++ msleep(20); ++ ++ if (!ret_val) ++ e1000_release_swflag_ich8lan(hw); ++ ++ if (ctrl & E1000_CTRL_PHY_RST) ++ ret_val = hw->phy.ops.get_cfg_done(hw); ++ ++ if (hw->mac.type >= e1000_ich10lan) { ++ e1000_lan_init_done_ich8lan(hw); ++ } else { ++ if (!ret_val) { ++ /* release the swflag because it is not reset by ++ * hardware reset ++ */ ++ e1000_release_swflag_ich8lan(hw); ++ } ++ ++ ret_val = e1000e_get_auto_rd_done(hw); ++ if (ret_val) { + /* -+ * If we're here, then things are most likely -+ * completely hosed, but if the error condition -+ * is detected, it won't hurt to give it another -+ * try...ICH_FLASH_CYCLE_REPEAT_COUNT times. ++ * When auto config read does not complete, do not ++ * return with an error. This can happen in situations ++ * where there is no eeprom and prevents getting link. + */ -+ hsfsts.regval = E1000_READ_FLASH_REG16(hw, -+ ICH_FLASH_HSFSTS); -+ if (hsfsts.hsf_status.flcerr == 1) { -+ /* Repeat for some time before giving up. */ -+ continue; -+ } else if (hsfsts.hsf_status.flcdone == 0) { -+ DEBUGOUT("Timeout error - flash cycle " -+ "did not complete."); -+ break; -+ } ++ e_dbg("Auto Read Done did not complete\n"); + } -+ } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); ++ } + -+out: -+ return ret_val; -+} ++ /* ++ * For PCH, this write will make sure that any noise ++ * will be detected as a CRC error and be dropped rather than show up ++ * as a bad packet to the DMA engine. ++ */ ++ if (hw->mac.type == e1000_pchlan) ++ ew32(CRC_OFFSET, 0x65656565); + -+/** -+ * e1000_write_flash_byte_ich8lan - Write a single byte to NVM -+ * @hw: pointer to the HW structure -+ * @offset: The index of the byte to read. -+ * @data: The byte to write to the NVM. -+ * -+ * Writes a single byte to the NVM using the flash access registers. -+ **/ -+static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, -+ u8 data) -+{ -+ u16 word = (u16)data; ++ ew32(IMC, 0xffffffff); ++ icr = er32(ICR); ++ ++ kab = er32(KABGTXD); ++ kab |= E1000_KABGTXD_BGSQLBIAS; ++ ew32(KABGTXD, kab); + -+ DEBUGFUNC("e1000_write_flash_byte_ich8lan"); ++ if (hw->mac.type == e1000_pchlan) ++ ret_val = e1000_hv_phy_workarounds_ich8lan(hw); + -+ return e1000_write_flash_data_ich8lan(hw, offset, 1, word); ++ return ret_val; +} + +/** -+ * e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM ++ * e1000_init_hw_ich8lan - Initialize the hardware + * @hw: pointer to the HW structure -+ * @offset: The offset of the byte to write. -+ * @byte: The byte to write to the NVM. + * -+ * Writes a single byte to the NVM using the flash access registers. -+ * Goes through a retry algorithm before giving up. ++ * Prepares the hardware for transmit and receive by doing the following: ++ * - initialize hardware bits ++ * - initialize LED identification ++ * - setup receive address registers ++ * - setup flow control ++ * - setup transmit descriptors ++ * - clear statistics + **/ -+static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, -+ u32 offset, u8 byte) ++static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) +{ ++ struct e1000_mac_info *mac = &hw->mac; ++ u32 ctrl_ext, txdctl, snoop; + s32 ret_val; -+ u16 program_retries; ++ u16 i; + -+ DEBUGFUNC("e1000_retry_write_flash_byte_ich8lan"); ++ e1000_initialize_hw_bits_ich8lan(hw); + -+ ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); -+ if (ret_val == E1000_SUCCESS) -+ goto out; ++ /* Initialize identification LED */ ++ ret_val = mac->ops.id_led_init(hw); ++ if (ret_val) ++ /* This is not fatal and we should not stop init due to this */ ++ e_dbg("Error initializing identification LED\n"); + -+ for (program_retries = 0; program_retries < 100; program_retries++) { -+ DEBUGOUT2("Retrying Byte %2.2X at offset %u\n", byte, offset); -+ usec_delay(100); -+ ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); -+ if (ret_val == E1000_SUCCESS) -+ break; -+ } -+ if (program_retries == 100) { -+ ret_val = -E1000_ERR_NVM; -+ goto out; ++ /* Setup the receive address. */ ++ e1000e_init_rx_addrs(hw, mac->rar_entry_count); ++ ++ /* Zero out the Multicast HASH table */ ++ e_dbg("Zeroing the MTA\n"); ++ for (i = 0; i < mac->mta_reg_count; i++) ++ E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); ++ ++ /* ++ * The 82578 Rx buffer will stall if wakeup is enabled in host and ++ * the ME. Reading the BM_WUC register will clear the host wakeup bit. ++ * Reset the phy after disabling host wakeup to reset the Rx buffer. ++ */ ++ if (hw->phy.type == e1000_phy_82578) { ++ e1e_rphy(hw, BM_WUC, &i); ++ ret_val = e1000_phy_hw_reset_ich8lan(hw); ++ if (ret_val) ++ return ret_val; + } + -+out: -+ return ret_val; -+} -+ -+/** -+ * e1000_erase_flash_bank_ich8lan - Erase a bank (4k) from NVM -+ * @hw: pointer to the HW structure -+ * @bank: 0 for first bank, 1 for second bank, etc. -+ * -+ * Erases the bank specified. Each bank is a 4k block. Banks are 0 based. -+ * bank N is 4096 * N + flash_reg_addr. -+ **/ -+static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) -+{ -+ struct e1000_nvm_info *nvm = &hw->nvm; -+ union ich8_hws_flash_status hsfsts; -+ union ich8_hws_flash_ctrl hsflctl; -+ u32 flash_linear_addr; -+ /* bank size is in 16bit words - adjust to bytes */ -+ u32 flash_bank_size = nvm->flash_bank_size * 2; -+ s32 ret_val = E1000_SUCCESS; -+ s32 count = 0; -+ s32 j, iteration, sector_size; -+ -+ DEBUGFUNC("e1000_erase_flash_bank_ich8lan"); -+ -+ hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); -+ -+ /* -+ * Determine HW Sector size: Read BERASE bits of hw flash status -+ * register -+ * 00: The Hw sector is 256 bytes, hence we need to erase 16 -+ * consecutive sectors. The start index for the nth Hw sector -+ * can be calculated as = bank * 4096 + n * 256 -+ * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector. -+ * The start index for the nth Hw sector can be calculated -+ * as = bank * 4096 -+ * 10: The Hw sector is 8K bytes, nth sector = bank * 8192 -+ * (ich9 only, otherwise error condition) -+ * 11: The Hw sector is 64K bytes, nth sector = bank * 65536 -+ */ -+ switch (hsfsts.hsf_status.berasesz) { -+ case 0: -+ /* Hw sector size 256 */ -+ sector_size = ICH_FLASH_SEG_SIZE_256; -+ iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_256; -+ break; -+ case 1: -+ sector_size = ICH_FLASH_SEG_SIZE_4K; -+ iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_4K; -+ break; -+ case 2: -+ if (hw->mac.type == e1000_ich9lan) { -+ sector_size = ICH_FLASH_SEG_SIZE_8K; -+ iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_8K; -+ } else { -+ ret_val = -E1000_ERR_NVM; -+ goto out; -+ } -+ break; -+ case 3: -+ sector_size = ICH_FLASH_SEG_SIZE_64K; -+ iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_64K; -+ break; -+ default: -+ ret_val = -E1000_ERR_NVM; -+ goto out; -+ } -+ -+ /* Start with the base address, then add the sector offset. */ -+ flash_linear_addr = hw->nvm.flash_base_addr; -+ flash_linear_addr += (bank) ? (sector_size * iteration) : 0; -+ -+ for (j = 0; j < iteration ; j++) { -+ do { -+ /* Steps */ -+ ret_val = e1000_flash_cycle_init_ich8lan(hw); -+ if (ret_val) -+ goto out; -+ -+ /* -+ * Write a value 11 (block Erase) in Flash -+ * Cycle field in hw flash control -+ */ -+ hsflctl.regval = E1000_READ_FLASH_REG16(hw, -+ ICH_FLASH_HSFCTL); -+ hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE; -+ E1000_WRITE_FLASH_REG16(hw, -+ ICH_FLASH_HSFCTL, -+ hsflctl.regval); -+ -+ /* -+ * Write the last 24 bits of an index within the -+ * block into Flash Linear address field in Flash -+ * Address. -+ */ -+ flash_linear_addr += (j * sector_size); -+ E1000_WRITE_FLASH_REG(hw, -+ ICH_FLASH_FADDR, -+ flash_linear_addr); -+ -+ ret_val = e1000_flash_cycle_ich8lan(hw, -+ ICH_FLASH_ERASE_COMMAND_TIMEOUT); -+ if (ret_val == E1000_SUCCESS) { -+ break; -+ } else { -+ /* -+ * Check if FCERR is set to 1. If 1, -+ * clear it and try the whole sequence -+ * a few more times else Done -+ */ -+ hsfsts.regval = E1000_READ_FLASH_REG16(hw, -+ ICH_FLASH_HSFSTS); -+ if (hsfsts.hsf_status.flcerr == 1) { -+ /* -+ * repeat for some time before -+ * giving up -+ */ -+ continue; -+ } else if (hsfsts.hsf_status.flcdone == 0) -+ goto out; -+ } -+ } while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT); -+ } -+ -+out: -+ return ret_val; -+} -+ -+/** -+ * e1000_valid_led_default_ich8lan - Set the default LED settings -+ * @hw: pointer to the HW structure -+ * @data: Pointer to the LED settings -+ * -+ * Reads the LED default settings from the NVM to data. If the NVM LED -+ * settings is all 0's or F's, set the LED default to a valid LED default -+ * setting. -+ **/ -+static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data) -+{ -+ s32 ret_val; -+ -+ DEBUGFUNC("e1000_valid_led_default_ich8lan"); -+ -+ ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); -+ if (ret_val) { -+ DEBUGOUT("NVM Read Error\n"); -+ goto out; -+ } -+ -+ if (*data == ID_LED_RESERVED_0000 || -+ *data == ID_LED_RESERVED_FFFF) -+ *data = ID_LED_DEFAULT_ICH8LAN; -+ -+out: -+ return ret_val; -+} -+ -+/** -+ * e1000_get_bus_info_ich8lan - Get/Set the bus type and width -+ * @hw: pointer to the HW structure -+ * -+ * ICH8 use the PCI Express bus, but does not contain a PCI Express Capability -+ * register, so the the bus width is hard coded. -+ **/ -+static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw) -+{ -+ struct e1000_bus_info *bus = &hw->bus; -+ s32 ret_val; -+ -+ DEBUGFUNC("e1000_get_bus_info_ich8lan"); -+ -+ ret_val = e1000_get_bus_info_pcie_generic(hw); -+ -+ /* -+ * ICH devices are "PCI Express"-ish. They have -+ * a configuration space, but do not contain -+ * PCI Express Capability registers, so bus width -+ * must be hardcoded. -+ */ -+ if (bus->width == e1000_bus_width_unknown) -+ bus->width = e1000_bus_width_pcie_x1; -+ -+ return ret_val; -+} -+ -+/** -+ * e1000_reset_hw_ich8lan - Reset the hardware -+ * @hw: pointer to the HW structure -+ * -+ * Does a full reset of the hardware which includes a reset of the PHY and -+ * MAC. -+ **/ -+static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) -+{ -+ u32 ctrl, icr, kab; -+ s32 ret_val; -+ -+ DEBUGFUNC("e1000_reset_hw_ich8lan"); -+ -+ /* -+ * Prevent the PCI-E bus from sticking if there is no TLP connection -+ * on the last TLP read/write transaction when MAC is reset. -+ */ -+ ret_val = e1000_disable_pcie_master_generic(hw); -+ if (ret_val) { -+ DEBUGOUT("PCI-E Master disable polling has failed.\n"); -+ } -+ -+ DEBUGOUT("Masking off all interrupts\n"); -+ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); -+ -+ /* -+ * Disable the Transmit and Receive units. Then delay to allow -+ * any pending transactions to complete before we hit the MAC -+ * with the global reset. -+ */ -+ E1000_WRITE_REG(hw, E1000_RCTL, 0); -+ E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); -+ E1000_WRITE_FLUSH(hw); -+ -+ msec_delay(10); -+ -+ /* Workaround for ICH8 bit corruption issue in FIFO memory */ -+ if (hw->mac.type == e1000_ich8lan) { -+ /* Set Tx and Rx buffer allocation to 8k apiece. */ -+ E1000_WRITE_REG(hw, E1000_PBA, E1000_PBA_8K); -+ /* Set Packet Buffer Size to 16k. */ -+ E1000_WRITE_REG(hw, E1000_PBS, E1000_PBS_16K); -+ } -+ -+ ctrl = E1000_READ_REG(hw, E1000_CTRL); -+ -+ if (!hw->phy.ops.check_reset_block(hw) && !hw->phy.reset_disable) { -+ /* -+ * PHY HW reset requires MAC CORE reset at the same -+ * time to make sure the interface between MAC and the -+ * external PHY is reset. -+ */ -+ ctrl |= E1000_CTRL_PHY_RST; -+ } -+ ret_val = e1000_acquire_swflag_ich8lan(hw); -+ DEBUGOUT("Issuing a global reset to ich8lan"); -+ E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_RST)); -+ msec_delay(20); -+ -+ ret_val = e1000_get_auto_rd_done_generic(hw); -+ if (ret_val) { -+ /* -+ * When auto config read does not complete, do not -+ * return with an error. This can happen in situations -+ * where there is no eeprom and prevents getting link. -+ */ -+ DEBUGOUT("Auto Read Done did not complete\n"); -+ } -+ -+ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); -+ icr = E1000_READ_REG(hw, E1000_ICR); -+ -+ kab = E1000_READ_REG(hw, E1000_KABGTXD); -+ kab |= E1000_KABGTXD_BGSQLBIAS; -+ E1000_WRITE_REG(hw, E1000_KABGTXD, kab); -+ -+ return ret_val; -+} -+ -+/** -+ * e1000_init_hw_ich8lan - Initialize the hardware -+ * @hw: pointer to the HW structure -+ * -+ * Prepares the hardware for transmit and receive by doing the following: -+ * - initialize hardware bits -+ * - initialize LED identification -+ * - setup receive address registers -+ * - setup flow control -+ * - setup transmit descriptors -+ * - clear statistics -+ **/ -+static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) -+{ -+ struct e1000_mac_info *mac = &hw->mac; -+ u32 ctrl_ext, txdctl, snoop; -+ s32 ret_val; -+ u16 i; -+ -+ DEBUGFUNC("e1000_init_hw_ich8lan"); -+ -+ e1000_initialize_hw_bits_ich8lan(hw); -+ -+ /* Initialize identification LED */ -+ ret_val = e1000_id_led_init_generic(hw); -+ if (ret_val) { -+ DEBUGOUT("Error initializing identification LED\n"); -+ /* This is not fatal and we should not stop init due to this */ -+ } -+ -+ /* Setup the receive address. */ -+ e1000_init_rx_addrs_generic(hw, mac->rar_entry_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); -+ -+ /* Setup link and flow control */ -+ ret_val = mac->ops.setup_link(hw); ++ /* Setup link and flow control */ ++ ret_val = mac->ops.setup_link(hw); + + /* Set the transmit descriptor write-back policy for both queues */ -+ txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0)); ++ txdctl = er32(TXDCTL(0)); + txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) | + E1000_TXDCTL_FULL_TX_DESC_WB; + txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) | + E1000_TXDCTL_MAX_TX_DESC_PREFETCH; -+ E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl); -+ txdctl = E1000_READ_REG(hw, E1000_TXDCTL(1)); ++ ew32(TXDCTL(0), txdctl); ++ txdctl = er32(TXDCTL(1)); + txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) | + E1000_TXDCTL_FULL_TX_DESC_WB; + txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) | + E1000_TXDCTL_MAX_TX_DESC_PREFETCH; -+ E1000_WRITE_REG(hw, E1000_TXDCTL(1), txdctl); ++ ew32(TXDCTL(1), txdctl); + + /* + * ICH8 has opposite polarity of no_snoop bits. @@ -7951,11 +7862,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri + snoop = PCIE_ICH8_SNOOP_ALL; + else + snoop = (u32)~(PCIE_NO_SNOOP_ALL); -+ e1000_set_pcie_no_snoop_generic(hw, snoop); ++ e1000e_set_pcie_no_snoop(hw, snoop); + -+ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ++ ctrl_ext = er32(CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_RO_DIS; -+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); ++ ew32(CTRL_EXT, ctrl_ext); + + /* + * Clear all of the statistics registers (clear on read). It is @@ -7978,50 +7889,47 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri +{ + u32 reg; + -+ DEBUGFUNC("e1000_initialize_hw_bits_ich8lan"); -+ -+ if (hw->mac.disable_hw_init_bits) -+ goto out; -+ + /* Extended Device Control */ -+ reg = E1000_READ_REG(hw, E1000_CTRL_EXT); ++ reg = er32(CTRL_EXT); + reg |= (1 << 22); -+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); ++ /* Enable PHY low-power state when MAC is at D3 w/o WoL */ ++ if (hw->mac.type >= e1000_pchlan) ++ reg |= E1000_CTRL_EXT_PHYPDEN; ++ ew32(CTRL_EXT, reg); + + /* Transmit Descriptor Control 0 */ -+ reg = E1000_READ_REG(hw, E1000_TXDCTL(0)); ++ reg = er32(TXDCTL(0)); + reg |= (1 << 22); -+ E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg); ++ ew32(TXDCTL(0), reg); + + /* Transmit Descriptor Control 1 */ -+ reg = E1000_READ_REG(hw, E1000_TXDCTL(1)); ++ reg = er32(TXDCTL(1)); + reg |= (1 << 22); -+ E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg); ++ ew32(TXDCTL(1), reg); + + /* Transmit Arbitration Control 0 */ -+ reg = E1000_READ_REG(hw, E1000_TARC(0)); ++ reg = er32(TARC(0)); + if (hw->mac.type == e1000_ich8lan) + reg |= (1 << 28) | (1 << 29); + reg |= (1 << 23) | (1 << 24) | (1 << 26) | (1 << 27); -+ E1000_WRITE_REG(hw, E1000_TARC(0), reg); ++ ew32(TARC(0), reg); + + /* Transmit Arbitration Control 1 */ -+ reg = E1000_READ_REG(hw, E1000_TARC(1)); -+ if (E1000_READ_REG(hw, E1000_TCTL) & E1000_TCTL_MULR) ++ reg = er32(TARC(1)); ++ if (er32(TCTL) & E1000_TCTL_MULR) + reg &= ~(1 << 28); + else + reg |= (1 << 28); + reg |= (1 << 24) | (1 << 26) | (1 << 30); -+ E1000_WRITE_REG(hw, E1000_TARC(1), reg); ++ ew32(TARC(1), reg); + + /* Device Status */ + if (hw->mac.type == e1000_ich8lan) { -+ reg = E1000_READ_REG(hw, E1000_STATUS); ++ reg = er32(STATUS); + reg &= ~(1 << 31); -+ E1000_WRITE_REG(hw, E1000_STATUS, reg); ++ ew32(STATUS, reg); + } + -+out: + return; +} + @@ -8039,9 +7947,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri +{ + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_setup_link_ich8lan"); -+ -+ if (hw->phy.ops.check_reset_block(hw)) ++ if (e1000_check_reset_block(hw)) + goto out; + + /* @@ -8049,21 +7955,34 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri + * the default flow control setting, so we explicitly + * set it to full. + */ -+ if (hw->fc.type == e1000_fc_default) -+ hw->fc.type = e1000_fc_full; ++ if (hw->fc.requested_mode == e1000_fc_default) ++ hw->fc.requested_mode = e1000_fc_full; + -+ hw->fc.original_type = hw->fc.type; ++ /* ++ * 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.current_mode = hw->fc.requested_mode; + -+ DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc.type); ++ e_dbg("After fix-ups FlowControl is now = %x\n", ++ hw->fc.current_mode); + + /* Continue to configure the copper link. */ + ret_val = hw->mac.ops.setup_physical_interface(hw); + if (ret_val) + goto out; + -+ E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time); ++ ew32(FCTTV, hw->fc.pause_time); ++ if ((hw->phy.type == e1000_phy_82578) || ++ (hw->phy.type == e1000_phy_82577)) { ++ ret_val = e1e_wphy(hw, ++ PHY_REG(BM_PORT_CTRL_PAGE, 27), ++ hw->fc.pause_time); ++ if (ret_val) ++ goto out; ++ } + -+ ret_val = e1000_set_fc_watermarks_generic(hw); ++ ret_val = e1000e_set_fc_watermarks(hw); + +out: + return ret_val; @@ -8083,45 +8002,53 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri + s32 ret_val; + u16 reg_data; + -+ DEBUGFUNC("e1000_setup_copper_link_ich8lan"); -+ -+ ctrl = E1000_READ_REG(hw, E1000_CTRL); ++ ctrl = er32(CTRL); + ctrl |= E1000_CTRL_SLU; + ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); -+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ++ ew32(CTRL, ctrl); + + /* + * Set the mac to wait the maximum time between each iteration + * and increase the max iterations when polling the phy; + * this fixes erroneous timeouts at 10Mbps. + */ -+ ret_val = e1000_write_kmrn_reg_generic(hw, GG82563_REG(0x34, 4), ++ ret_val = e1000e_write_kmrn_reg(hw, ++ E1000_KMRNCTRLSTA_TIMEOUTS, + 0xFFFF); + if (ret_val) + goto out; -+ ret_val = e1000_read_kmrn_reg_generic(hw, GG82563_REG(0x34, 9), ++ ret_val = e1000e_read_kmrn_reg(hw, ++ E1000_KMRNCTRLSTA_INBAND_PARAM, + ®_data); + if (ret_val) + goto out; + reg_data |= 0x3F; -+ ret_val = e1000_write_kmrn_reg_generic(hw, GG82563_REG(0x34, 9), ++ ret_val = e1000e_write_kmrn_reg(hw, ++ E1000_KMRNCTRLSTA_INBAND_PARAM, + reg_data); + if (ret_val) + goto out; + -+ if (hw->phy.type == e1000_phy_igp_3) { -+ ret_val = e1000_copper_link_setup_igp(hw); ++ switch (hw->phy.type) { ++ case e1000_phy_igp_3: ++ ret_val = e1000e_copper_link_setup_igp(hw); + if (ret_val) + goto out; -+ } else if (hw->phy.type == e1000_phy_bm) { -+ ret_val = e1000_copper_link_setup_m88(hw); ++ break; ++ case e1000_phy_bm: ++ case e1000_phy_82578: ++ ret_val = e1000e_copper_link_setup_m88(hw); + if (ret_val) + goto out; -+ } -+ -+ if (hw->phy.type == e1000_phy_ife) { -+ ret_val = hw->phy.ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, -+ ®_data); ++ break; ++ case e1000_phy_82577: ++ ret_val = e1000_copper_link_setup_82577(hw); ++ if (ret_val) ++ goto out; ++ break; ++ case e1000_phy_ife: ++ ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, ++ ®_data); + if (ret_val) + goto out; + @@ -8139,12 +8066,15 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri + reg_data |= IFE_PMC_AUTO_MDIX; + break; + } -+ ret_val = hw->phy.ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, ++ ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, + reg_data); + if (ret_val) + goto out; ++ break; ++ default: ++ break; + } -+ ret_val = e1000_setup_copper_link_generic(hw); ++ ret_val = e1000e_setup_copper_link(hw); + +out: + return ret_val; @@ -8165,12 +8095,18 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri +{ + s32 ret_val; + -+ DEBUGFUNC("e1000_get_link_up_info_ich8lan"); -+ -+ ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex); ++ ret_val = e1000e_get_speed_and_duplex_copper(hw, speed, duplex); + if (ret_val) + goto out; + ++ if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) { ++ ret_val = e1000e_write_kmrn_reg(hw, ++ E1000_KMRNCTRLSTA_K1_CONFIG, ++ E1000_KMRNCTRLSTA_K1_DISABLE); ++ if (ret_val) ++ goto out; ++ } ++ + if ((hw->mac.type == e1000_ich8lan) && + (hw->phy.type == e1000_phy_igp_3) && + (*speed == SPEED_1000)) { @@ -8198,22 +8134,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri + **/ +static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) +{ -+ struct e1000_dev_spec_ich8lan *dev_spec; ++ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; + u32 phy_ctrl; + s32 ret_val = E1000_SUCCESS; + u16 i, data; + bool link; + -+ DEBUGFUNC("e1000_kmrn_lock_loss_workaround_ich8lan"); -+ -+ dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; -+ -+ if (!dev_spec) { -+ DEBUGOUT("dev_spec pointer is set to NULL.\n"); -+ ret_val = -E1000_ERR_CONFIG; -+ goto out; -+ } -+ + if (!(dev_spec->kmrn_lock_loss_workaround_enabled)) + goto out; + @@ -8222,7 +8148,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri + * Attempting this while link is negotiating fouled up link + * stability + */ -+ ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); ++ ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); + if (!link) { + ret_val = E1000_SUCCESS; + goto out; @@ -8230,11 +8156,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri + + for (i = 0; i < 10; i++) { + /* read once to clear */ -+ ret_val = hw->phy.ops.read_reg(hw, IGP3_KMRN_DIAG, &data); ++ ret_val = e1e_rphy(hw, IGP3_KMRN_DIAG, &data); + if (ret_val) + goto out; + /* and again to get new status */ -+ ret_val = hw->phy.ops.read_reg(hw, IGP3_KMRN_DIAG, &data); ++ ret_val = e1e_rphy(hw, IGP3_KMRN_DIAG, &data); + if (ret_val) + goto out; + @@ -8245,20 +8171,20 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri + } + + /* Issue PHY reset */ -+ hw->phy.ops.reset(hw); -+ msec_delay_irq(5); ++ e1000_phy_hw_reset(hw); ++ mdelay(5); + } + /* Disable GigE link negotiation */ -+ phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); ++ phy_ctrl = er32(PHY_CTRL); + phy_ctrl |= (E1000_PHY_CTRL_GBE_DISABLE | + E1000_PHY_CTRL_NOND0A_GBE_DISABLE); -+ E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); ++ ew32(PHY_CTRL, phy_ctrl); + + /* + * Call gig speed drop workaround on Gig disable before accessing + * any PHY registers + */ -+ e1000_gig_downshift_workaround_ich8lan(hw); ++ e1000e_gig_downshift_workaround_ich8lan(hw); + + /* unable to acquire PCS lock */ + ret_val = -E1000_ERR_PHY; @@ -8268,35 +8194,25 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri +} + +/** -+ * e1000_set_kmrn_lock_loss_workaround_ich8lan - Set Kumeran workaround state ++ * e1000e_set_kmrn_lock_loss_workaround_ich8lan - Set Kumeran workaround state + * @hw: pointer to the HW structure + * @state: boolean value used to set the current Kumeran workaround state + * + * If ICH8, set the current Kumeran workaround state (enabled - true + * /disabled - false). + **/ -+void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, ++void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, + bool state) +{ -+ struct e1000_dev_spec_ich8lan *dev_spec; -+ -+ DEBUGFUNC("e1000_set_kmrn_lock_loss_workaround_ich8lan"); ++ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; + + if (hw->mac.type != e1000_ich8lan) { -+ DEBUGOUT("Workaround applies to ICH8 only.\n"); -+ goto out; -+ } -+ -+ dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; -+ -+ if (!dev_spec) { -+ DEBUGOUT("dev_spec pointer is set to NULL.\n"); -+ goto out; ++ e_dbg("Workaround applies to ICH8 only.\n"); ++ return; + } + + dev_spec->kmrn_lock_loss_workaround_enabled = state; + -+out: + return; +} + @@ -8310,48 +8226,45 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri + * 3) read it back + * Continue if successful, else issue LCD reset and repeat + **/ -+void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) ++void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) +{ + u32 reg; + u16 data; + u8 retry = 0; + -+ DEBUGFUNC("e1000_igp3_phy_powerdown_workaround_ich8lan"); -+ + if (hw->phy.type != e1000_phy_igp_3) + goto out; + + /* Try the workaround twice (if needed) */ + do { + /* Disable link */ -+ reg = E1000_READ_REG(hw, E1000_PHY_CTRL); ++ reg = er32(PHY_CTRL); + reg |= (E1000_PHY_CTRL_GBE_DISABLE | + E1000_PHY_CTRL_NOND0A_GBE_DISABLE); -+ E1000_WRITE_REG(hw, E1000_PHY_CTRL, reg); ++ ew32(PHY_CTRL, reg); + + /* + * Call gig speed drop workaround on Gig disable before + * accessing any PHY registers + */ + if (hw->mac.type == e1000_ich8lan) -+ e1000_gig_downshift_workaround_ich8lan(hw); ++ e1000e_gig_downshift_workaround_ich8lan(hw); + + /* Write VR power-down enable */ -+ hw->phy.ops.read_reg(hw, IGP3_VR_CTRL, &data); ++ e1e_rphy(hw, IGP3_VR_CTRL, &data); + data &= ~IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK; -+ hw->phy.ops.write_reg(hw, -+ IGP3_VR_CTRL, ++ e1e_wphy(hw, IGP3_VR_CTRL, + data | IGP3_VR_CTRL_MODE_SHUTDOWN); + + /* Read it back and test */ -+ hw->phy.ops.read_reg(hw, IGP3_VR_CTRL, &data); ++ e1e_rphy(hw, IGP3_VR_CTRL, &data); + data &= IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK; + if ((data == IGP3_VR_CTRL_MODE_SHUTDOWN) || retry) + break; + + /* Issue PHY reset and repeat at most one more time */ -+ reg = E1000_READ_REG(hw, E1000_CTRL); -+ E1000_WRITE_REG(hw, E1000_CTRL, reg | E1000_CTRL_PHY_RST); ++ reg = er32(CTRL); ++ ew32(CTRL, reg | E1000_CTRL_PHY_RST); + retry++; + } while (retry); + @@ -8360,7 +8273,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri +} + +/** -+ * e1000_gig_downshift_workaround_ich8lan - WoL from S5 stops working ++ * e1000e_gig_downshift_workaround_ich8lan - WoL from S5 stops working + * @hw: pointer to the HW structure + * + * Steps to take when dropping from 1Gb/s (eg. link cable removal (LSC), @@ -8369,29 +8282,27 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri + * 2) Clear Kumeran Near-end loopback + * Should only be called for ICH8[m] devices with IGP_3 Phy. + **/ -+void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw) ++void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + u16 reg_data; + -+ DEBUGFUNC("e1000_gig_downshift_workaround_ich8lan"); -+ + if ((hw->mac.type != e1000_ich8lan) || + (hw->phy.type != e1000_phy_igp_3)) + goto out; + -+ ret_val = e1000_read_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, ++ ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, + ®_data); + if (ret_val) + goto out; + reg_data |= E1000_KMRNCTRLSTA_DIAG_NELPBK; -+ ret_val = e1000_write_kmrn_reg_generic(hw, ++ ret_val = e1000e_write_kmrn_reg(hw, + E1000_KMRNCTRLSTA_DIAG_OFFSET, + reg_data); + if (ret_val) + goto out; + reg_data &= ~E1000_KMRNCTRLSTA_DIAG_NELPBK; -+ ret_val = e1000_write_kmrn_reg_generic(hw, ++ ret_val = e1000e_write_kmrn_reg(hw, + E1000_KMRNCTRLSTA_DIAG_OFFSET, + reg_data); +out: @@ -8399,7 +8310,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri +} + +/** -+ * e1000_disable_gig_wol_ich8lan - disable gig during WoL ++ * e1000e_disable_gig_wol_ich8lan - disable gig during WoL + * @hw: pointer to the HW structure + * + * During S0 to Sx transition, it is possible the link remains at gig @@ -8407,18 +8318,26 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri + * 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation + * to a lower speed. + * -+ * Should only be called for ICH9 and ICH10 devices. ++ * Should only be called for applicable parts. + **/ -+void e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw) ++void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw) +{ + u32 phy_ctrl; + -+ if ((hw->mac.type == e1000_ich10lan) || -+ (hw->mac.type == e1000_ich9lan)) { -+ phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); ++ switch (hw->mac.type) { ++ case e1000_ich9lan: ++ case e1000_ich10lan: ++ case e1000_pchlan: ++ phy_ctrl = er32(PHY_CTRL); + phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | + E1000_PHY_CTRL_GBE_DISABLE; -+ E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); ++ ew32(PHY_CTRL, phy_ctrl); ++ ++ /* Workaround SWFLAG unexpectedly set during S0->Sx */ ++ if (hw->mac.type == e1000_pchlan) ++ udelay(500); ++ default: ++ break; + } + + return; @@ -8434,14 +8353,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri +{ + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_cleanup_led_ich8lan"); -+ + if (hw->phy.type == e1000_phy_ife) -+ ret_val = hw->phy.ops.write_reg(hw, -+ IFE_PHY_SPECIAL_CONTROL_LED, ++ ret_val = e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, + 0); + else -+ E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default); ++ ew32(LEDCTL, hw->mac.ledctl_default); + + return ret_val; +} @@ -8456,14 +8372,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri +{ + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_led_on_ich8lan"); -+ + if (hw->phy.type == e1000_phy_ife) -+ ret_val = hw->phy.ops.write_reg(hw, -+ IFE_PHY_SPECIAL_CONTROL_LED, ++ ret_val = e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, + (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON)); + else -+ E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode2); ++ ew32(LEDCTL, hw->mac.ledctl_mode2); + + return ret_val; +} @@ -8478,19 +8391,103 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri +{ + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_led_off_ich8lan"); -+ + if (hw->phy.type == e1000_phy_ife) -+ ret_val = hw->phy.ops.write_reg(hw, ++ ret_val = e1e_wphy(hw, + IFE_PHY_SPECIAL_CONTROL_LED, + (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_OFF)); + else -+ E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); ++ ew32(LEDCTL, hw->mac.ledctl_mode1); + + return ret_val; +} + +/** ++ * e1000_setup_led_pchlan - Configures SW controllable LED ++ * @hw: pointer to the HW structure ++ * ++ * This prepares the SW controllable LED for use. ++ **/ ++static s32 e1000_setup_led_pchlan(struct e1000_hw *hw) ++{ ++ return e1e_wphy(hw, HV_LED_CONFIG, ++ (u16)hw->mac.ledctl_mode1); ++} ++ ++/** ++ * e1000_cleanup_led_pchlan - Restore the default LED operation ++ * @hw: pointer to the HW structure ++ * ++ * Return the LED back to the default configuration. ++ **/ ++static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw) ++{ ++ return e1e_wphy(hw, HV_LED_CONFIG, ++ (u16)hw->mac.ledctl_default); ++} ++ ++/** ++ * e1000_led_on_pchlan - Turn LEDs on ++ * @hw: pointer to the HW structure ++ * ++ * Turn on the LEDs. ++ **/ ++static s32 e1000_led_on_pchlan(struct e1000_hw *hw) ++{ ++ u16 data = (u16)hw->mac.ledctl_mode2; ++ u32 i, led; ++ ++ /* ++ * If no link, then turn LED on by setting the invert bit ++ * for each LED that's mode is "link_up" in ledctl_mode2. ++ */ ++ if (!(er32(STATUS) & E1000_STATUS_LU)) { ++ for (i = 0; i < 3; i++) { ++ led = (data >> (i * 5)) & E1000_PHY_LED0_MASK; ++ if ((led & E1000_PHY_LED0_MODE_MASK) != ++ E1000_LEDCTL_MODE_LINK_UP) ++ continue; ++ if (led & E1000_PHY_LED0_IVRT) ++ data &= ~(E1000_PHY_LED0_IVRT << (i * 5)); ++ else ++ data |= (E1000_PHY_LED0_IVRT << (i * 5)); ++ } ++ } ++ ++ return e1e_wphy(hw, HV_LED_CONFIG, data); ++} ++ ++/** ++ * e1000_led_off_pchlan - Turn LEDs off ++ * @hw: pointer to the HW structure ++ * ++ * Turn off the LEDs. ++ **/ ++static s32 e1000_led_off_pchlan(struct e1000_hw *hw) ++{ ++ u16 data = (u16)hw->mac.ledctl_mode1; ++ u32 i, led; ++ ++ /* ++ * If no link, then turn LED off by clearing the invert bit ++ * for each LED that's mode is "link_up" in ledctl_mode1. ++ */ ++ if (!(er32(STATUS) & E1000_STATUS_LU)) { ++ for (i = 0; i < 3; i++) { ++ led = (data >> (i * 5)) & E1000_PHY_LED0_MASK; ++ if ((led & E1000_PHY_LED0_MODE_MASK) != ++ E1000_LEDCTL_MODE_LINK_UP) ++ continue; ++ if (led & E1000_PHY_LED0_IVRT) ++ data &= ~(E1000_PHY_LED0_IVRT << (i * 5)); ++ else ++ data |= (E1000_PHY_LED0_IVRT << (i * 5)); ++ } ++ } ++ ++ return e1e_wphy(hw, HV_LED_CONFIG, data); ++} ++ ++/** + * e1000_get_cfg_done_ich8lan - Read config done bit + * @hw: pointer to the HW structure + * @@ -8505,18 +8502,29 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri + s32 ret_val = E1000_SUCCESS; + u32 bank = 0; + -+ e1000_get_cfg_done_generic(hw); ++ if (hw->mac.type >= e1000_pchlan) { ++ u32 status = er32(STATUS); ++ ++ if (status & E1000_STATUS_PHYRA) { ++ ew32(STATUS, status & ++ ~E1000_STATUS_PHYRA); ++ } else ++ e_dbg("PHY Reset Asserted not set - needs delay\n"); ++ } ++ ++ e1000e_get_cfg_done(hw); + + /* If EEPROM is not marked present, init the IGP 3 PHY manually */ -+ if (hw->mac.type != e1000_ich10lan) { -+ if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) && -+ (hw->phy.type == e1000_phy_igp_3)) { ++ if ((hw->mac.type != e1000_ich10lan) && ++ (hw->mac.type != e1000_pchlan)) { ++ if (((er32(EECD) & E1000_EECD_PRES) == 0) && ++ (hw->phy.type == e1000_phy_igp_3)) { + e1000_phy_init_script_igp3(hw); + } + } else { + if (e1000_valid_nvm_bank_detect_ich8lan(hw, &bank)) { -+ /* Maybe we should do a basic Boazman config */ -+ DEBUGOUT("EEPROM not present\n"); ++ /* Maybe we should do a basic PHY config */ ++ e_dbg("EEPROM not present\n"); + ret_val = -E1000_ERR_CONFIG; + } + } @@ -8533,11 +8541,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri + **/ +static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw) +{ -+ struct e1000_phy_info *phy = &hw->phy; -+ struct e1000_mac_info *mac = &hw->mac; -+ + /* If the management interface is not enabled, then power down */ -+ if (!(mac->ops.check_mng_mode(hw) || phy->ops.check_reset_block(hw))) ++ if (!(hw->mac.ops.check_mng_mode(hw) || ++ e1000_check_reset_block(hw))) + e1000_power_down_phy_copper(hw); + + return; @@ -8552,35 +8558,52 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.c linux-2.6.22-10/dri + **/ +static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) +{ -+ volatile u32 temp; -+ -+ DEBUGFUNC("e1000_clear_hw_cntrs_ich8lan"); -+ -+ e1000_clear_hw_cntrs_base_generic(hw); -+ -+ 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); ++ u16 phy_data; + -+ temp = E1000_READ_REG(hw, E1000_IAC); -+ temp = E1000_READ_REG(hw, E1000_ICRXOC); ++ e1000e_clear_hw_cntrs_base(hw); ++ ++ er32(ALGNERRC); ++ er32(RXERRC); ++ er32(TNCRS); ++ er32(CEXTERR); ++ er32(TSCTC); ++ er32(TSCTFC); ++ ++ er32(MGTPRC); ++ er32(MGTPDC); ++ er32(MGTPTC); ++ ++ er32(IAC); ++ er32(ICRXOC); ++ ++ /* Clear PHY statistics registers */ ++ if ((hw->phy.type == e1000_phy_82578) || ++ (hw->phy.type == e1000_phy_82577)) { ++ e1e_rphy(hw, HV_SCC_UPPER, &phy_data); ++ e1e_rphy(hw, HV_SCC_LOWER, &phy_data); ++ e1e_rphy(hw, HV_ECOL_UPPER, &phy_data); ++ e1e_rphy(hw, HV_ECOL_LOWER, &phy_data); ++ e1e_rphy(hw, HV_MCC_UPPER, &phy_data); ++ e1e_rphy(hw, HV_MCC_LOWER, &phy_data); ++ e1e_rphy(hw, HV_LATECOL_UPPER, &phy_data); ++ e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data); ++ e1e_rphy(hw, HV_COLC_UPPER, &phy_data); ++ e1e_rphy(hw, HV_COLC_LOWER, &phy_data); ++ e1e_rphy(hw, HV_DC_UPPER, &phy_data); ++ e1e_rphy(hw, HV_DC_LOWER, &phy_data); ++ e1e_rphy(hw, HV_TNCRS_UPPER, &phy_data); ++ e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data); ++ } +} + diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.h linux-2.6.22-10/drivers/net/e1000e/e1000_ich8lan.h --- linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000_ich8lan.h 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,144 @@ ++++ linux-2.6.22-10/drivers/net/e1000e/e1000_ich8lan.h 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,167 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -8613,11 +8636,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.h linux-2.6.22-10/dri +#define ICH_FLASH_HSFCTL 0x0006 +#define ICH_FLASH_FADDR 0x0008 +#define ICH_FLASH_FDATA0 0x0010 -+#define ICH_FLASH_PR0 0x0074 + -+#define ICH_FLASH_READ_COMMAND_TIMEOUT 500 -+#define ICH_FLASH_WRITE_COMMAND_TIMEOUT 500 -+#define ICH_FLASH_ERASE_COMMAND_TIMEOUT 3000000 ++/* Requires up to 10 seconds when MNG might be accessing part. */ ++#define ICH_FLASH_READ_COMMAND_TIMEOUT 10000000 ++#define ICH_FLASH_WRITE_COMMAND_TIMEOUT 10000000 ++#define ICH_FLASH_ERASE_COMMAND_TIMEOUT 10000000 +#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF +#define ICH_FLASH_CYCLE_REPEAT_COUNT 10 + @@ -8628,8 +8651,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.h linux-2.6.22-10/dri +#define FLASH_GFPREG_BASE_MASK 0x1FFF +#define FLASH_SECTOR_ADDR_SHIFT 12 + -+#define E1000_SHADOW_RAM_WORDS 2048 -+ +#define ICH_FLASH_SEG_SIZE_256 256 +#define ICH_FLASH_SEG_SIZE_4K 4096 +#define ICH_FLASH_SEG_SIZE_8K 8192 @@ -8646,12 +8667,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.h linux-2.6.22-10/dri +#define E1000_ICH_MNG_IAMT_MODE 0x2 + +#define ID_LED_DEFAULT_ICH8LAN ((ID_LED_DEF1_DEF2 << 12) | \ -+ (ID_LED_DEF1_OFF2 << 8) | \ -+ (ID_LED_DEF1_ON2 << 4) | \ ++ (ID_LED_OFF1_OFF2 << 8) | \ ++ (ID_LED_OFF1_ON2 << 4) | \ + (ID_LED_DEF1_DEF2)) + +#define E1000_ICH_NVM_SIG_WORD 0x13 +#define E1000_ICH_NVM_SIG_MASK 0xC000 ++#define E1000_ICH_NVM_VALID_SIG_MASK 0xC0 ++#define E1000_ICH_NVM_SIG_VALUE 0x80 + +#define E1000_ICH8_LAN_INIT_TIMEOUT 1500 + @@ -8675,6 +8698,44 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.h linux-2.6.22-10/dri +#define IGP3_VR_CTRL_MODE_SHUTDOWN 0x0200 +#define IGP3_PM_CTRL_FORCE_PWR_DOWN 0x0020 + ++/* PHY Wakeup Registers and defines */ ++#define BM_RCTL PHY_REG(BM_WUC_PAGE, 0) ++#define BM_WUC PHY_REG(BM_WUC_PAGE, 1) ++#define BM_WUFC PHY_REG(BM_WUC_PAGE, 2) ++#define BM_WUS PHY_REG(BM_WUC_PAGE, 3) ++#define BM_RAR_L(_i) (BM_PHY_REG(BM_WUC_PAGE, 16 + ((_i) << 2))) ++#define BM_RAR_M(_i) (BM_PHY_REG(BM_WUC_PAGE, 17 + ((_i) << 2))) ++#define BM_RAR_H(_i) (BM_PHY_REG(BM_WUC_PAGE, 18 + ((_i) << 2))) ++#define BM_RAR_CTRL(_i) (BM_PHY_REG(BM_WUC_PAGE, 19 + ((_i) << 2))) ++#define BM_MTA(_i) (BM_PHY_REG(BM_WUC_PAGE, 128 + ((_i) << 1))) ++ ++#define BM_RCTL_UPE 0x0001 /* Unicast Promiscuous Mode */ ++#define BM_RCTL_MPE 0x0002 /* Multicast Promiscuous Mode */ ++#define BM_RCTL_MO_SHIFT 3 /* Multicast Offset Shift */ ++#define BM_RCTL_MO_MASK (3 << 3) /* Multicast Offset Mask */ ++#define BM_RCTL_BAM 0x0020 /* Broadcast Accept Mode */ ++#define BM_RCTL_PMCF 0x0040 /* Pass MAC Control Frames */ ++#define BM_RCTL_RFCE 0x0080 /* Rx Flow Control Enable */ ++ ++#define HV_LED_CONFIG PHY_REG(768, 30) /* LED Configuration */ ++#define HV_MUX_DATA_CTRL PHY_REG(776, 16) ++#define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400 ++#define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004 ++#define HV_SCC_UPPER PHY_REG(778, 16) /* Single Collision Count */ ++#define HV_SCC_LOWER PHY_REG(778, 17) ++#define HV_ECOL_UPPER PHY_REG(778, 18) /* Excessive Collision Count */ ++#define HV_ECOL_LOWER PHY_REG(778, 19) ++#define HV_MCC_UPPER PHY_REG(778, 20) /* Multiple Collision Count */ ++#define HV_MCC_LOWER PHY_REG(778, 21) ++#define HV_LATECOL_UPPER PHY_REG(778, 23) /* Late Collision Count */ ++#define HV_LATECOL_LOWER PHY_REG(778, 24) ++#define HV_COLC_UPPER PHY_REG(778, 25) /* Collision Count */ ++#define HV_COLC_LOWER PHY_REG(778, 26) ++#define HV_DC_UPPER PHY_REG(778, 27) /* Defer Count */ ++#define HV_DC_LOWER PHY_REG(778, 28) ++#define HV_TNCRS_UPPER PHY_REG(778, 29) /* Transmit with no CRS */ ++#define HV_TNCRS_LOWER PHY_REG(778, 30) ++ +/* + * Additional interrupts need to be handled for ICH family: + * DSW = The FW changed the status of the DISSW bit in FWSM @@ -8699,36 +8760,21 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_ich8lan.h linux-2.6.22-10/dri +#define E1000_RXDEXT_LINKSEC_ERROR_BAD_SIG 0x60000000 + + -+/* ICH Flash Protected Region */ -+union ich8_flash_protected_range { -+ struct ich8_pr { -+ u32 base:13; /* 0:12 Protected Range Base */ -+ u32 reserved1:2; /* 13:14 Reserved */ -+ u32 rpe:1; /* 15 Read Protection Enable */ -+ u32 limit:13; /* 16:28 Protected Range Limit */ -+ u32 reserved2:2; /* 29:30 Reserved */ -+ u32 wpe:1; /* 31 Write Protection Enable */ -+ } range; -+ u32 regval; -+}; -+ -+void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, ++void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, + bool state); -+void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw); -+ -+void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); -+void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw); -+void e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw); ++void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); ++void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw); ++void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw); + +#endif diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers/net/e1000e/e1000_mac.c --- linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000_mac.c 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,1988 @@ ++++ linux-2.6.22-10/drivers/net/e1000e/e1000_mac.c 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,1864 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -8753,7 +8799,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + +*******************************************************************************/ + -+#include "e1000_hw.h" ++#include "e1000.h" ++ ++static u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr); ++static s32 e1000_set_default_fc_generic(struct e1000_hw *hw); ++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 @@ -8764,54 +8817,36 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers +void e1000_init_mac_ops_generic(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; -+ DEBUGFUNC("e1000_init_mac_ops_generic"); -+ + /* General Setup */ -+ mac->ops.read_mac_addr = e1000_read_mac_addr_generic; -+ mac->ops.remove_device = e1000_remove_device_generic; -+ mac->ops.config_collision_dist = e1000_config_collision_dist_generic; ++ mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pcie; ++ mac->ops.read_mac_addr = e1000e_read_mac_addr_generic; ++ mac->ops.config_collision_dist = e1000e_config_collision_dist; + /* LINK */ -+ mac->ops.wait_autoneg = e1000_wait_autoneg_generic; ++ mac->ops.wait_autoneg = e1000_wait_autoneg; + /* Management */ + mac->ops.mng_host_if_write = e1000_mng_host_if_write_generic; + mac->ops.mng_write_cmd_header = e1000_mng_write_cmd_header_generic; + mac->ops.mng_enable_host_if = e1000_mng_enable_host_if_generic; + /* VLAN, MC, etc. */ -+ mac->ops.rar_set = e1000_rar_set_generic; ++ mac->ops.rar_set = e1000e_rar_set; + mac->ops.validate_mdi_setting = e1000_validate_mdi_setting_generic; +} + +/** -+ * e1000_remove_device_generic - Free device specific structure -+ * @hw: pointer to the HW structure -+ * -+ * If a device specific structure was allocated, this function will -+ * free it. -+ **/ -+void e1000_remove_device_generic(struct e1000_hw *hw) -+{ -+ DEBUGFUNC("e1000_remove_device_generic"); -+ -+ /* Freeing the dev_spec member of e1000_hw structure */ -+ e1000_free_dev_spec_struct(hw); -+} -+ -+/** -+ * e1000_get_bus_info_pcie_generic - Get PCIe bus information ++ * e1000e_get_bus_info_pcie - Get PCIe bus information + * @hw: pointer to the HW structure + * + * Determines and stores the system bus information for a particular + * network interface. The following bus information is determined and stored: + * bus speed, bus width, type (PCIe), and PCIe function. + **/ -+s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw) ++s32 e1000e_get_bus_info_pcie(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; + -+ DEBUGFUNC("e1000_get_bus_info_pcie_generic"); ++ s32 ret_val; ++ u16 pcie_link_status; + + bus->type = e1000_bus_type_pci_express; + bus->speed = e1000_bus_speed_2500; @@ -8822,43 +8857,68 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + if (ret_val) + bus->width = e1000_bus_width_unknown; + else -+ bus->width = (e1000_bus_width)((pcie_link_status & ++ bus->width = (enum e1000_bus_width)((pcie_link_status & + 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 = er32(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; ++} ++ ++/** ++ * e1000e_clear_vfta_generic - Clear VLAN filter table + * @hw: pointer to the HW structure + * + * Clears the register array which contains the VLAN filter table by + * setting all the values to 0. + **/ -+void e1000_clear_vfta_generic(struct e1000_hw *hw) ++void e1000e_clear_vfta_generic(struct e1000_hw *hw) +{ + u32 offset; + -+ DEBUGFUNC("e1000_clear_vfta_generic"); -+ + for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { + E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0); -+ E1000_WRITE_FLUSH(hw); ++ e1e_flush(); + } +} + +/** -+ * e1000_write_vfta_generic - Write value to VLAN filter table ++ * e1000e_write_vfta_generic - Write value to VLAN filter table + * @hw: pointer to the HW structure + * @offset: register offset in VLAN filter table + * @value: register value written to VLAN filter table @@ -8866,16 +8926,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * Writes value at the given offset in the register array which stores + * the VLAN filter table. + **/ -+void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value) ++void e1000e_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value) +{ -+ DEBUGFUNC("e1000_write_vfta_generic"); -+ + E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); -+ E1000_WRITE_FLUSH(hw); ++ e1e_flush(); +} + +/** -+ * e1000_init_rx_addrs_generic - Initialize receive address's ++ * e1000e_init_rx_addrs - Initialize receive address's + * @hw: pointer to the HW structure + * @rar_count: receive address registers + * @@ -8883,25 +8941,20 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * register to the devices MAC address and clearing all the other receive + * address registers to 0. + **/ -+void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count) ++void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count) +{ + u32 i; -+ -+ DEBUGFUNC("e1000_init_rx_addrs_generic"); ++ u8 mac_addr[ETH_ADDR_LEN] = {0}; + + /* Setup the receive address */ -+ DEBUGOUT("Programming MAC Address into RAR[0]\n"); ++ e_dbg("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++) { -+ 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); -+ } ++ e_dbg("Clearing RAR[1-%u]\n", rar_count-1); ++ for (i = 1; i < rar_count; i++) ++ hw->mac.ops.rar_set(hw, mac_addr, i); +} + +/** @@ -8910,10 +8963,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * + * 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) +{ @@ -8922,28 +8976,25 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + u16 offset, nvm_alt_mac_addr_offset, nvm_data; + u8 alt_mac_addr[ETH_ADDR_LEN]; + -+ DEBUGFUNC("e1000_check_alt_mac_addr_generic"); -+ -+ ret_val = hw->nvm.ops.read(hw, NVM_ALT_MAC_ADDR_PTR, 1, ++ ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1, + &nvm_alt_mac_addr_offset); + if (ret_val) { -+ DEBUGOUT("NVM Read Error\n"); ++ e_dbg("NVM Read Error\n"); + goto out; + } + + 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); ++ ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data); + if (ret_val) { -+ DEBUGOUT("NVM Read Error\n"); ++ e_dbg("NVM Read Error\n"); + goto out; + } + @@ -8953,21 +9004,23 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + + /* if multicast bit is set, the alternate address will not be used */ + if (alt_mac_addr[0] & 0x01) { -+ ret_val = -(E1000_NOT_IMPLEMENTED); ++ e_dbg("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; +} + +/** -+ * e1000_rar_set_generic - Set receive address register ++ * e1000e_rar_set - Set receive address register + * @hw: pointer to the HW structure + * @addr: pointer to the receive address + * @index: receive address array register @@ -8975,12 +9028,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * Sets the receive address array register at index to the address passed + * in by addr. + **/ -+void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) ++void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index) +{ + u32 rar_low, rar_high; + -+ DEBUGFUNC("e1000_rar_set_generic"); -+ + /* + * HW expects these in little endian so we reverse the byte order + * from network order (big endian) to little endian @@ -8992,13 +9043,18 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); + + /* If MAC address zero, no need to set the AV bit */ -+ if (rar_low || rar_high) { -+ if (!hw->mac.disable_av) -+ rar_high |= E1000_RAH_AV; -+ } ++ if (rar_low || rar_high) ++ rar_high |= E1000_RAH_AV; + -+ E1000_WRITE_REG(hw, E1000_RAL(index), rar_low); -+ E1000_WRITE_REG(hw, E1000_RAH(index), rar_high); ++ /* ++ * Some bridges will combine consecutive 32-bit writes into ++ * a single burst write, which will malfunction on some parts. ++ * The flushes avoid this. ++ */ ++ ew32(RAL(index), rar_low); ++ e1e_flush(); ++ ew32(RAH(index), rar_high); ++ e1e_flush(); +} + +/** @@ -9015,7 +9071,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers +{ + u32 hash_bit, hash_reg, mta; + -+ DEBUGFUNC("e1000_mta_set_generic"); + /* + * The MTA is a register array of 32-bit registers. It is + * treated like an array of (32*mta_reg_count) bits. We want to @@ -9034,63 +9089,42 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + mta |= (1 << hash_bit); + + E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg, mta); -+ E1000_WRITE_FLUSH(hw); ++ e1e_flush(); +} + +/** -+ * e1000_update_mc_addr_list_generic - Update Multicast addresses ++ * e1000e_update_mc_addr_list_generic - 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. ++ * 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) ++void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, ++ 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"); ++ /* clear mta_shadow */ ++ memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); + -+ /* -+ * 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); -+ } -+ } ++ /* 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); + -+ /* 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); -+ } ++ hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); ++ hash_bit = hash_value & 0x1F; + -+ /* Load any remaining multicast addresses into the hash table. */ -+ for (; mc_addr_count > 0; mc_addr_count--) { -+ 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; ++ 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]); ++ e1e_flush(); +} + +/** @@ -9102,13 +9136,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * the multicast filter table array address and new table value. See + * e1000_mta_set_generic() + **/ -+u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr) ++static u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr) +{ + u32 hash_value, hash_mask; + u8 bit_shift = 0; + -+ DEBUGFUNC("e1000_hash_mc_addr_generic"); -+ + /* Register count multiplied by bits per register */ + hash_mask = (hw->mac.mta_reg_count * 32) - 1; + @@ -9146,18 +9178,18 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * 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)) | @@ -9167,72 +9199,65 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_clear_hw_cntrs_base_generic - Clear base hardware counters ++ * e1000e_clear_hw_cntrs_base - Clear base hardware counters + * @hw: pointer to the HW structure + * + * Clears the base hardware counters by reading the counter registers. + **/ -+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_check_for_copper_link_generic - Check for link (Copper) ++void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw) ++{ ++ er32(CRCERRS); ++ er32(SYMERRS); ++ er32(MPC); ++ er32(SCC); ++ er32(ECOL); ++ er32(MCC); ++ er32(LATECOL); ++ er32(COLC); ++ er32(DC); ++ er32(SEC); ++ er32(RLEC); ++ er32(XONRXC); ++ er32(XONTXC); ++ er32(XOFFRXC); ++ er32(XOFFTXC); ++ er32(FCRUC); ++ er32(GPRC); ++ er32(BPRC); ++ er32(MPRC); ++ er32(GPTC); ++ er32(GORCL); ++ er32(GORCH); ++ er32(GOTCL); ++ er32(GOTCH); ++ er32(RNBC); ++ er32(RUC); ++ er32(RFC); ++ er32(ROC); ++ er32(RJC); ++ er32(TORL); ++ er32(TORH); ++ er32(TOTL); ++ er32(TOTH); ++ er32(TPR); ++ er32(TPT); ++ er32(MPTC); ++ er32(BPTC); ++} ++/** ++ * e1000e_check_for_copper_link - Check for link (Copper) + * @hw: pointer to the HW structure + * + * Checks to see of the link status of the hardware has changed. If a + * change in link status has been detected, then we read the PHY registers + * to get the current speed/duplex if link exists. + **/ -+s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw) ++s32 e1000e_check_for_copper_link(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + s32 ret_val; + bool link; + -+ DEBUGFUNC("e1000_check_for_copper_link"); -+ + /* + * We only want to go out to the PHY registers to see if Auto-Neg + * has completed and/or if our link status has changed. The @@ -9249,7 +9274,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * link. If so, then we want to get the current speed/duplex + * of the PHY. + */ -+ ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); ++ ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); + if (ret_val) + goto out; + @@ -9262,7 +9287,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * Check if there was DownShift, must be checked + * immediately after link-up + */ -+ e1000_check_downshift_generic(hw); ++ e1000e_check_downshift(hw); + + /* + * If we are forcing speed/duplex, then we simply return since @@ -9278,7 +9303,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * of MAC speed/duplex configuration. So we only need to + * configure Collision Distance in the MAC. + */ -+ e1000_config_collision_dist_generic(hw); ++ e1000e_config_collision_dist(hw); + + /* + * Configure Flow Control now that Auto-Neg has completed. @@ -9286,23 +9311,22 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * settings because we may have had to re-autoneg with a + * different link partner. + */ -+ ret_val = e1000_config_fc_after_link_up_generic(hw); -+ if (ret_val) { -+ DEBUGOUT("Error configuring flow control\n"); -+ } ++ ret_val = e1000e_config_fc_after_link_up(hw); ++ if (ret_val) ++ e_dbg("Error configuring flow control\n"); + +out: + return ret_val; +} + +/** -+ * e1000_check_for_fiber_link_generic - Check for link (Fiber) ++ * e1000e_check_for_fiber_link - Check for link (Fiber) + * @hw: pointer to the HW structure + * + * Checks for link up on the hardware. If link is not up and we have + * a signal, then we need to force link up. + **/ -+s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw) ++s32 e1000e_check_for_fiber_link(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + u32 rxcw; @@ -9310,11 +9334,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + u32 status; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_check_for_fiber_link_generic"); -+ -+ ctrl = E1000_READ_REG(hw, E1000_CTRL); -+ status = E1000_READ_REG(hw, E1000_STATUS); -+ rxcw = E1000_READ_REG(hw, E1000_RXCW); ++ ctrl = er32(CTRL); ++ status = er32(STATUS); ++ rxcw = er32(RXCW); + + /* + * If we don't have link (auto-negotiation failed or link partner @@ -9331,20 +9353,20 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + mac->autoneg_failed = 1; + goto out; + } -+ DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n"); ++ e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n"); + + /* Disable auto-negotiation in the TXCW register */ -+ E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE)); ++ ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE)); + + /* Force link-up and also force full-duplex. */ -+ ctrl = E1000_READ_REG(hw, E1000_CTRL); ++ ctrl = er32(CTRL); + ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); -+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ++ ew32(CTRL, ctrl); + + /* Configure Flow Control after forcing link up. */ -+ ret_val = e1000_config_fc_after_link_up_generic(hw); ++ ret_val = e1000e_config_fc_after_link_up(hw); + if (ret_val) { -+ DEBUGOUT("Error configuring flow control\n"); ++ e_dbg("Error configuring flow control\n"); + goto out; + } + } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { @@ -9354,9 +9376,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * and disable forced link in the Device Control register + * in an attempt to auto-negotiate with our link partner. + */ -+ DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n"); -+ E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); -+ E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); ++ e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n"); ++ ew32(TXCW, mac->txcw); ++ ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); + + mac->serdes_has_link = true; + } @@ -9366,13 +9388,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_check_for_serdes_link_generic - Check for link (Serdes) ++ * e1000e_check_for_serdes_link - Check for link (Serdes) + * @hw: pointer to the HW structure + * + * Checks for link up on the hardware. If link is not up and we have + * a signal, then we need to force link up. + **/ -+s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw) ++s32 e1000e_check_for_serdes_link(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + u32 rxcw; @@ -9380,11 +9402,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + u32 status; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_check_for_serdes_link_generic"); -+ -+ ctrl = E1000_READ_REG(hw, E1000_CTRL); -+ status = E1000_READ_REG(hw, E1000_STATUS); -+ rxcw = E1000_READ_REG(hw, E1000_RXCW); ++ ctrl = er32(CTRL); ++ status = er32(STATUS); ++ rxcw = er32(RXCW); + + /* + * If we don't have link (auto-negotiation failed or link partner @@ -9399,20 +9419,20 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + mac->autoneg_failed = 1; + goto out; + } -+ DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n"); ++ e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n"); + + /* Disable auto-negotiation in the TXCW register */ -+ E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE)); ++ ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE)); + + /* Force link-up and also force full-duplex. */ -+ ctrl = E1000_READ_REG(hw, E1000_CTRL); ++ ctrl = er32(CTRL); + ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); -+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ++ ew32(CTRL, ctrl); + + /* Configure Flow Control after forcing link up. */ -+ ret_val = e1000_config_fc_after_link_up_generic(hw); ++ ret_val = e1000e_config_fc_after_link_up(hw); + if (ret_val) { -+ DEBUGOUT("Error configuring flow control\n"); ++ e_dbg("Error configuring flow control\n"); + goto out; + } + } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { @@ -9422,54 +9442,54 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * and disable forced link in the Device Control register + * in an attempt to auto-negotiate with our link partner. + */ -+ DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n"); -+ E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); -+ E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); ++ e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n"); ++ ew32(TXCW, mac->txcw); ++ ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); + + mac->serdes_has_link = true; -+ } else if (!(E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW))) { ++ } else if (!(E1000_TXCW_ANE & er32(TXCW))) { + /* + * If we force link for non-auto-negotiation switch, check + * link status based on MAC synchronization for internal + * serdes media type. + */ + /* SYNCH bit and IV bit are sticky. */ -+ usec_delay(10); -+ rxcw = E1000_READ_REG(hw, E1000_RXCW); ++ udelay(10); ++ rxcw = er32(RXCW); + if (rxcw & E1000_RXCW_SYNCH) { + if (!(rxcw & E1000_RXCW_IV)) { + mac->serdes_has_link = true; -+ DEBUGOUT("SERDES: Link up - forced.\n"); ++ e_dbg("SERDES: Link up - forced.\n"); + } + } else { + mac->serdes_has_link = false; -+ DEBUGOUT("SERDES: Link down - force failed.\n"); ++ e_dbg("SERDES: Link down - force failed.\n"); + } + } + -+ if (E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW)) { -+ status = E1000_READ_REG(hw, E1000_STATUS); ++ if (E1000_TXCW_ANE & er32(TXCW)) { ++ status = er32(STATUS); + if (status & E1000_STATUS_LU) { + /* SYNCH bit and IV bit are sticky, so reread rxcw. */ -+ usec_delay(10); -+ rxcw = E1000_READ_REG(hw, E1000_RXCW); ++ udelay(10); ++ rxcw = er32(RXCW); + if (rxcw & E1000_RXCW_SYNCH) { + if (!(rxcw & E1000_RXCW_IV)) { -+ mac->serdes_has_link = TRUE; -+ DEBUGOUT("SERDES: Link up - autoneg " ++ mac->serdes_has_link = true; ++ e_dbg("SERDES: Link up - autoneg " + "completed sucessfully.\n"); + } else { -+ mac->serdes_has_link = FALSE; -+ DEBUGOUT("SERDES: Link down - invalid" ++ mac->serdes_has_link = false; ++ e_dbg("SERDES: Link down - invalid" + "codewords detected in autoneg.\n"); + } + } else { -+ mac->serdes_has_link = FALSE; -+ DEBUGOUT("SERDES: Link down - no sync.\n"); ++ mac->serdes_has_link = false; ++ e_dbg("SERDES: Link down - no sync.\n"); + } + } else { -+ mac->serdes_has_link = FALSE; -+ DEBUGOUT("SERDES: Link down - autoneg failed\n"); ++ mac->serdes_has_link = false; ++ e_dbg("SERDES: Link down - autoneg failed\n"); + } + } + @@ -9478,7 +9498,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_setup_link_generic - Setup flow control and link settings ++ * e1000e_setup_link - Setup flow control and link settings + * @hw: pointer to the HW structure + * + * Determines which flow control settings to use, then configures flow @@ -9487,38 +9507,36 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * should be established. Assumes the hardware has previously been reset + * and the transmitter and receiver are not enabled. + **/ -+s32 e1000_setup_link_generic(struct e1000_hw *hw) ++s32 e1000e_setup_link(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_setup_link_generic"); -+ + /* + * In the case of the phy reset being blocked, we already have a link. + * We do not need to set it up again. + */ + if (hw->phy.ops.check_reset_block) -+ if (hw->phy.ops.check_reset_block(hw)) ++ if (e1000_check_reset_block(hw)) + 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); ++ e_dbg("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); @@ -9531,39 +9549,37 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * control is disabled, because it does not hurt anything to + * initialize these registers. + */ -+ DEBUGOUT("Initializing the Flow Control address, type and timer regs\n"); -+ E1000_WRITE_REG(hw, E1000_FCT, FLOW_CONTROL_TYPE); -+ E1000_WRITE_REG(hw, E1000_FCAH, FLOW_CONTROL_ADDRESS_HIGH); -+ E1000_WRITE_REG(hw, E1000_FCAL, FLOW_CONTROL_ADDRESS_LOW); ++ e_dbg("Initializing the Flow Control address, type and timer regs\n"); ++ ew32(FCT, FLOW_CONTROL_TYPE); ++ ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH); ++ ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW); + -+ E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time); ++ ew32(FCTTV, hw->fc.pause_time); + -+ ret_val = e1000_set_fc_watermarks_generic(hw); ++ ret_val = e1000e_set_fc_watermarks(hw); + +out: + return ret_val; +} + +/** -+ * e1000_setup_fiber_serdes_link_generic - Setup link for fiber/serdes ++ * e1000e_setup_fiber_serdes_link - Setup link for fiber/serdes + * @hw: pointer to the HW structure + * + * Configures collision distance and flow control for fiber and serdes + * links. Upon successful setup, poll for link. + **/ -+s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw) ++s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw) +{ + u32 ctrl; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_setup_fiber_serdes_link_generic"); -+ -+ ctrl = E1000_READ_REG(hw, E1000_CTRL); ++ ctrl = er32(CTRL); + + /* Take the link out of reset */ + ctrl &= ~E1000_CTRL_LRST; + -+ e1000_config_collision_dist_generic(hw); ++ e1000e_config_collision_dist(hw); + + ret_val = e1000_commit_fc_settings_generic(hw); + if (ret_val) @@ -9576,11 +9592,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * then the link-up status bit will be set and the flow control enable + * bits (RFCE and TFCE) will be set according to their negotiated value. + */ -+ DEBUGOUT("Auto-negotiation enabled\n"); ++ e_dbg("Auto-negotiation enabled\n"); + -+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl); -+ E1000_WRITE_FLUSH(hw); -+ msec_delay(1); ++ ew32(CTRL, ctrl); ++ e1e_flush(); ++ msleep(1); + + /* + * For these adapters, the SW definable pin 1 is set when the optics @@ -9588,10 +9604,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * indication. + */ + if (hw->phy.media_type == e1000_media_type_internal_serdes || -+ (E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) { ++ (er32(CTRL) & E1000_CTRL_SWDPIN1)) { + ret_val = e1000_poll_fiber_serdes_link_generic(hw); + } else { -+ DEBUGOUT("No signal detected\n"); ++ e_dbg("No signal detected\n"); + } + +out: @@ -9599,26 +9615,24 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_config_collision_dist_generic - Configure collision distance ++ * e1000e_config_collision_dist - Configure collision distance + * @hw: pointer to the HW structure + * + * Configures the collision distance to the default value and is used + * during link setup. Currently no func pointer exists and all + * implementations are handled in the generic version of this function. + **/ -+void e1000_config_collision_dist_generic(struct e1000_hw *hw) ++void e1000e_config_collision_dist(struct e1000_hw *hw) +{ + u32 tctl; + -+ DEBUGFUNC("e1000_config_collision_dist_generic"); -+ -+ tctl = E1000_READ_REG(hw, E1000_TCTL); ++ tctl = er32(TCTL); + + tctl &= ~E1000_TCTL_COLD; + tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; + -+ E1000_WRITE_REG(hw, E1000_TCTL, tctl); -+ E1000_WRITE_FLUSH(hw); ++ ew32(TCTL, tctl); ++ e1e_flush(); +} + +/** @@ -9628,14 +9642,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * 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; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_poll_fiber_serdes_link_generic"); -+ + /* + * If we have a signal (the cable is plugged in, or assumed true for + * serdes media) then poll for a "Link-Up" indication in the Device @@ -9644,13 +9656,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * milliseconds even if the other end is doing it in SW). + */ + for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) { -+ msec_delay(10); -+ status = E1000_READ_REG(hw, E1000_STATUS); ++ msleep(10); ++ status = er32(STATUS); + if (status & E1000_STATUS_LU) + break; + } + if (i == FIBER_LINK_UP_LIMIT) { -+ DEBUGOUT("Never got a valid link from auto-neg!!!\n"); ++ e_dbg("Never got a valid link from auto-neg!!!\n"); + mac->autoneg_failed = 1; + /* + * AutoNeg failed to achieve a link, so we'll call @@ -9660,13 +9672,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + */ + ret_val = hw->mac.ops.check_for_link(hw); + if (ret_val) { -+ DEBUGOUT("Error while checking for link\n"); ++ e_dbg("Error while checking for link\n"); + goto out; + } + mac->autoneg_failed = 0; + } else { + mac->autoneg_failed = 0; -+ DEBUGOUT("Valid Link Found\n"); ++ e_dbg("Valid Link Found\n"); + } + +out: @@ -9680,14 +9692,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * Write the flow control settings to the Transmit Config Word Register (TXCW) + * base on the flow control settings in e1000_mac_info. + **/ -+s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) ++static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + u32 txcw; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_commit_fc_settings_generic"); -+ + /* + * Check for a software override of the flow control settings, and + * setup the device accordingly. If auto-negotiation is enabled, then @@ -9705,7 +9715,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * 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); @@ -9736,13 +9746,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); + break; + default: -+ DEBUGOUT("Flow control param set incorrectly\n"); ++ e_dbg("Flow control param set incorrectly\n"); + ret_val = -E1000_ERR_CONFIG; + goto out; + break; + } + -+ E1000_WRITE_REG(hw, E1000_TXCW, txcw); ++ ew32(TXCW, txcw); + mac->txcw = txcw; + +out: @@ -9750,20 +9760,18 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_set_fc_watermarks_generic - Set flow control high/low watermarks ++ * e1000e_set_fc_watermarks - Set flow control high/low watermarks + * @hw: pointer to the HW structure + * + * Sets the flow control high/low threshold (watermark) registers. If + * flow control XON frame transmission is enabled, then set XON frame + * transmission as well. + **/ -+s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw) ++s32 e1000e_set_fc_watermarks(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + u32 fcrtl = 0, fcrth = 0; + -+ DEBUGFUNC("e1000_set_fc_watermarks_generic"); -+ + /* + * Set the flow control receive threshold registers. Normally, + * these registers will be set to a default threshold that may be @@ -9771,7 +9779,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * 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 @@ -9783,8 +9791,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + + fcrth = hw->fc.high_water; + } -+ E1000_WRITE_REG(hw, E1000_FCRTL, fcrtl); -+ E1000_WRITE_REG(hw, E1000_FCRTH, fcrth); ++ ew32(FCRTL, fcrtl); ++ ew32(FCRTH, fcrth); + + return ret_val; +} @@ -9796,13 +9804,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * Read the EEPROM for the default values for flow control and store the + * values. + **/ -+s32 e1000_set_default_fc_generic(struct e1000_hw *hw) ++static s32 e1000_set_default_fc_generic(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + u16 nvm_data; + -+ DEBUGFUNC("e1000_set_default_fc_generic"); -+ + /* + * Read and store word 0x0F of the EEPROM. This word contains bits + * that determine the hardware's default PAUSE (flow control) mode, @@ -9812,27 +9818,27 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * control setting, then the variable hw->fc will + * be initialized based on a value in the EEPROM. + */ -+ ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data); ++ ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data); + + if (ret_val) { -+ DEBUGOUT("NVM Read Error\n"); ++ e_dbg("NVM Read Error\n"); + goto out; + } + + 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; +} + +/** -+ * e1000_force_mac_fc_generic - Force the MAC's flow control settings ++ * e1000e_force_mac_fc - Force the MAC's flow control settings + * @hw: pointer to the HW structure + * + * Force the MAC's flow control settings. Sets the TFCE and RFCE bits in the @@ -9841,14 +9847,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * autonegotiation is managed by the PHY rather than the MAC. Software must + * also configure these bits when link is forced on a fiber connection. + **/ -+s32 e1000_force_mac_fc_generic(struct e1000_hw *hw) ++s32 e1000e_force_mac_fc(struct e1000_hw *hw) +{ + u32 ctrl; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_force_mac_fc_generic"); -+ -+ ctrl = E1000_READ_REG(hw, E1000_CTRL); ++ ctrl = er32(CTRL); + + /* + * Because we didn't get link via the internal auto-negotiation @@ -9857,7 +9861,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * 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 @@ -9868,9 +9872,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * 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); ++ e_dbg("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; @@ -9886,19 +9890,19 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); + break; + default: -+ DEBUGOUT("Flow control param set incorrectly\n"); ++ e_dbg("Flow control param set incorrectly\n"); + ret_val = -E1000_ERR_CONFIG; + goto out; + } + -+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ++ ew32(CTRL, ctrl); + +out: + return ret_val; +} + +/** -+ * e1000_config_fc_after_link_up_generic - Configures flow control after link ++ * e1000e_config_fc_after_link_up - Configures flow control after link + * @hw: pointer to the HW structure + * + * Checks the status of auto-negotiation after link up to ensure that the @@ -9907,16 +9911,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * and did not fail, then we configure flow control based on our link + * partner. + **/ -+s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) ++s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; -+ struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; + u16 speed, duplex; + -+ DEBUGFUNC("e1000_config_fc_after_link_up_generic"); -+ + /* + * Check for the case where we have fiber media and auto-neg failed + * so we had to force link. In this case, we need to force the @@ -9925,14 +9926,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + if (mac->autoneg_failed) { + if (hw->phy.media_type == e1000_media_type_fiber || + hw->phy.media_type == e1000_media_type_internal_serdes) -+ ret_val = e1000_force_mac_fc_generic(hw); ++ ret_val = e1000e_force_mac_fc(hw); + } else { + if (hw->phy.media_type == e1000_media_type_copper) -+ ret_val = e1000_force_mac_fc_generic(hw); ++ ret_val = e1000e_force_mac_fc(hw); + } + + if (ret_val) { -+ DEBUGOUT("Error forcing flow control settings\n"); ++ e_dbg("Error forcing flow control settings\n"); + goto out; + } + @@ -9948,15 +9949,15 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * has completed. We read this twice because this reg has + * some "sticky" (latched) bits. + */ -+ ret_val = phy->ops.read_reg(hw, PHY_STATUS, &mii_status_reg); ++ ret_val = e1e_rphy(hw, PHY_STATUS, &mii_status_reg); + if (ret_val) + goto out; -+ ret_val = phy->ops.read_reg(hw, PHY_STATUS, &mii_status_reg); ++ ret_val = e1e_rphy(hw, PHY_STATUS, &mii_status_reg); + if (ret_val) + goto out; + + if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) { -+ DEBUGOUT("Copper PHY and Auto Neg " ++ e_dbg("Copper PHY and Auto Neg " + "has not completed.\n"); + goto out; + } @@ -9968,11 +9969,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * Page Ability Register (Address 5) to determine how + * flow control was negotiated. + */ -+ ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, ++ ret_val = e1e_rphy(hw, PHY_AUTONEG_ADV, + &mii_nway_adv_reg); + if (ret_val) + goto out; -+ ret_val = phy->ops.read_reg(hw, PHY_LP_ABILITY, ++ ret_val = e1e_rphy(hw, PHY_LP_ABILITY, + &mii_nway_lp_ability_reg); + if (ret_val) + goto out; @@ -10020,12 +10021,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * 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; -+ DEBUGOUT("Flow Control = FULL.\r\n"); ++ if (hw->fc.requested_mode == e1000_fc_full) { ++ hw->fc.current_mode = e1000_fc_full; ++ e_dbg("Flow Control = FULL.\r\n"); + } else { -+ hw->fc.type = e1000_fc_rx_pause; -+ DEBUGOUT("Flow Control = " ++ hw->fc.current_mode = e1000_fc_rx_pause; ++ e_dbg("Flow Control = " + "RX PAUSE frames only.\r\n"); + } + } @@ -10041,8 +10042,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + (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; -+ DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n"); ++ hw->fc.current_mode = e1000_fc_tx_pause; ++ e_dbg("Flow Control = TX PAUSE frames only.\r\n"); + } + /* + * For transmitting PAUSE frames ONLY. @@ -10056,15 +10057,15 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + (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; -+ DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); ++ hw->fc.current_mode = e1000_fc_rx_pause; ++ e_dbg("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; -+ DEBUGOUT("Flow Control = NONE.\r\n"); ++ hw->fc.current_mode = e1000_fc_none; ++ e_dbg("Flow Control = NONE.\r\n"); + } + + /* @@ -10074,20 +10075,20 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + */ + ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex); + if (ret_val) { -+ DEBUGOUT("Error getting link speed and duplex\n"); ++ e_dbg("Error getting link speed and duplex\n"); + goto out; + } + + 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 + * controller to use the correct flow control settings. + */ -+ ret_val = e1000_force_mac_fc_generic(hw); ++ ret_val = e1000e_force_mac_fc(hw); + if (ret_val) { -+ DEBUGOUT("Error forcing flow control settings\n"); ++ e_dbg("Error forcing flow control settings\n"); + goto out; + } + } @@ -10097,7 +10098,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_get_speed_and_duplex_copper_generic - Retrieve current speed/duplex ++ * e1000e_get_speed_and_duplex_copper - Retrieve current speed/duplex + * @hw: pointer to the HW structure + * @speed: stores the current speed + * @duplex: stores the current duplex @@ -10105,31 +10106,29 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * Read the status register for the current speed/duplex and store the current + * speed and duplex for copper connections. + **/ -+s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed, ++s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, + u16 *duplex) +{ + u32 status; + -+ DEBUGFUNC("e1000_get_speed_and_duplex_copper_generic"); -+ -+ status = E1000_READ_REG(hw, E1000_STATUS); ++ status = er32(STATUS); + if (status & E1000_STATUS_SPEED_1000) { + *speed = SPEED_1000; -+ DEBUGOUT("1000 Mbs, "); ++ e_dbg("1000 Mbs, "); + } else if (status & E1000_STATUS_SPEED_100) { + *speed = SPEED_100; -+ DEBUGOUT("100 Mbs, "); ++ e_dbg("100 Mbs, "); + } else { + *speed = SPEED_10; -+ DEBUGOUT("10 Mbs, "); ++ e_dbg("10 Mbs, "); + } + + if (status & E1000_STATUS_FD) { + *duplex = FULL_DUPLEX; -+ DEBUGOUT("Full Duplex\n"); ++ e_dbg("Full Duplex\n"); + } else { + *duplex = HALF_DUPLEX; -+ DEBUGOUT("Half Duplex\n"); ++ e_dbg("Half Duplex\n"); + } + + return E1000_SUCCESS; @@ -10144,11 +10143,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * Sets the speed and duplex to gigabit full duplex (the only possible option) + * for fiber/serdes links. + **/ -+s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw, ++s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, + u16 *speed, u16 *duplex) +{ -+ DEBUGFUNC("e1000_get_speed_and_duplex_fiber_serdes_generic"); -+ + *speed = SPEED_1000; + *duplex = FULL_DUPLEX; + @@ -10156,52 +10153,50 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_get_hw_semaphore_generic - Acquire hardware semaphore ++ * e1000e_get_hw_semaphore - Acquire hardware semaphore + * @hw: pointer to the HW structure + * + * Acquire the HW semaphore to access the PHY or NVM + **/ -+s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw) ++s32 e1000e_get_hw_semaphore(struct e1000_hw *hw) +{ + u32 swsm; + s32 ret_val = E1000_SUCCESS; + s32 timeout = hw->nvm.word_size + 1; + s32 i = 0; + -+ DEBUGFUNC("e1000_get_hw_semaphore_generic"); -+ + /* Get the SW semaphore */ + while (i < timeout) { -+ swsm = E1000_READ_REG(hw, E1000_SWSM); ++ swsm = er32(SWSM); + if (!(swsm & E1000_SWSM_SMBI)) + break; + -+ usec_delay(50); ++ udelay(50); + i++; + } + + if (i == timeout) { -+ DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); ++ e_dbg("Driver can't access device - SMBI bit is set.\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + + /* Get the FW semaphore. */ + for (i = 0; i < timeout; i++) { -+ swsm = E1000_READ_REG(hw, E1000_SWSM); -+ E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI); ++ swsm = er32(SWSM); ++ ew32(SWSM, swsm | E1000_SWSM_SWESMBI); + + /* Semaphore acquired if bit latched */ -+ if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI) ++ if (er32(SWSM) & E1000_SWSM_SWESMBI) + break; + -+ usec_delay(50); ++ udelay(50); + } + + if (i == timeout) { + /* Release semaphores */ -+ e1000_put_hw_semaphore_generic(hw); -+ DEBUGOUT("Driver can't access the NVM\n"); ++ e1000e_put_hw_semaphore(hw); ++ e_dbg("Driver can't access the NVM\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } @@ -10211,46 +10206,39 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_put_hw_semaphore_generic - Release hardware semaphore ++ * e1000e_put_hw_semaphore - Release hardware semaphore + * @hw: pointer to the HW structure + * + * Release hardware semaphore used to access the PHY or NVM + **/ -+void e1000_put_hw_semaphore_generic(struct e1000_hw *hw) ++void e1000e_put_hw_semaphore(struct e1000_hw *hw) +{ + u32 swsm; + -+ DEBUGFUNC("e1000_put_hw_semaphore_generic"); -+ -+ swsm = E1000_READ_REG(hw, E1000_SWSM); -+ ++ swsm = er32(SWSM); + swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); -+ -+ E1000_WRITE_REG(hw, E1000_SWSM, swsm); ++ ew32(SWSM, swsm); +} -+ +/** -+ * e1000_get_auto_rd_done_generic - Check for auto read completion ++ * e1000e_get_auto_rd_done - Check for auto read completion + * @hw: pointer to the HW structure + * + * Check EEPROM for Auto Read done bit. + **/ -+s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw) ++s32 e1000e_get_auto_rd_done(struct e1000_hw *hw) +{ + s32 i = 0; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_get_auto_rd_done_generic"); -+ + while (i < AUTO_READ_DONE_TIMEOUT) { -+ if (E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_AUTO_RD) ++ if (er32(EECD) & E1000_EECD_AUTO_RD) + break; -+ msec_delay(1); ++ msleep(1); + i++; + } + + if (i == AUTO_READ_DONE_TIMEOUT) { -+ DEBUGOUT("Auto read by HW from NVM has not completed.\n"); ++ e_dbg("Auto read by HW from NVM has not completed.\n"); + ret_val = -E1000_ERR_RESET; + goto out; + } @@ -10260,22 +10248,20 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_valid_led_default_generic - Verify a valid default LED config ++ * e1000e_valid_led_default - Verify a valid default LED config + * @hw: pointer to the HW structure + * @data: pointer to the NVM (EEPROM) + * + * Read the EEPROM for the current default LED configuration. If the + * LED configuration is not valid, set to a valid LED configuration. + **/ -+s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data) ++s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data) +{ + s32 ret_val; + -+ DEBUGFUNC("e1000_valid_led_default_generic"); -+ -+ ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); ++ ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data); + if (ret_val) { -+ DEBUGOUT("NVM Read Error\n"); ++ e_dbg("NVM Read Error\n"); + goto out; + } + @@ -10287,11 +10273,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_id_led_init_generic - ++ * e1000e_id_led_init - + * @hw: pointer to the HW structure + * + **/ -+s32 e1000_id_led_init_generic(struct e1000_hw * hw) ++s32 e1000e_id_led_init(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + s32 ret_val; @@ -10301,13 +10287,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + u16 data, i, temp; + const u16 led_mask = 0x0F; + -+ DEBUGFUNC("e1000_id_led_init_generic"); -+ + ret_val = hw->nvm.ops.valid_led_default(hw, &data); + if (ret_val) + goto out; + -+ mac->ledctl_default = E1000_READ_REG(hw, E1000_LEDCTL); ++ mac->ledctl_default = er32(LEDCTL); + mac->ledctl_mode1 = mac->ledctl_default; + mac->ledctl_mode2 = mac->ledctl_default; + @@ -10365,15 +10349,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + u32 ledctl; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_setup_led_generic"); -+ + if (hw->mac.ops.setup_led != e1000_setup_led_generic) { + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + if (hw->phy.media_type == e1000_media_type_fiber) { -+ ledctl = E1000_READ_REG(hw, E1000_LEDCTL); ++ ledctl = er32(LEDCTL); + hw->mac.ledctl_default = ledctl; + /* Turn off LED0 */ + ledctl &= ~(E1000_LEDCTL_LED0_IVRT | @@ -10381,9 +10363,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + E1000_LEDCTL_LED0_MODE_MASK); + ledctl |= (E1000_LEDCTL_MODE_LED_OFF << + E1000_LEDCTL_LED0_MODE_SHIFT); -+ E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl); ++ ew32(LEDCTL, ledctl); + } else if (hw->phy.media_type == e1000_media_type_copper) { -+ E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); ++ ew32(LEDCTL, hw->mac.ledctl_mode1); + } + +out: @@ -10391,42 +10373,38 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_cleanup_led_generic - Set LED config to default operation ++ * e1000e_cleanup_led_generic - Set LED config to default operation + * @hw: pointer to the HW structure + * + * Remove the current LED configuration and set the LED configuration + * to the default value, saved from the EEPROM. + **/ -+s32 e1000_cleanup_led_generic(struct e1000_hw *hw) ++s32 e1000e_cleanup_led_generic(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_cleanup_led_generic"); -+ -+ if (hw->mac.ops.cleanup_led != e1000_cleanup_led_generic) { ++ if (hw->mac.ops.cleanup_led != e1000e_cleanup_led_generic) { + ret_val = -E1000_ERR_CONFIG; + goto out; + } + -+ E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default); ++ ew32(LEDCTL, hw->mac.ledctl_default); + +out: + return ret_val; +} + +/** -+ * e1000_blink_led_generic - Blink LED ++ * e1000e_blink_led - Blink LED + * @hw: pointer to the HW structure + * + * Blink the LEDs which are set to be on. + **/ -+s32 e1000_blink_led_generic(struct e1000_hw *hw) ++s32 e1000e_blink_led(struct e1000_hw *hw) +{ + u32 ledctl_blink = 0; + u32 i; + -+ DEBUGFUNC("e1000_blink_led_generic"); -+ + if (hw->phy.media_type == e1000_media_type_fiber) { + /* always blink LED0 for PCI-E fiber */ + ledctl_blink = E1000_LEDCTL_LED0_BLINK | @@ -10444,32 +10422,30 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + (i * 8)); + } + -+ E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl_blink); ++ ew32(LEDCTL, ledctl_blink); + + return E1000_SUCCESS; +} + +/** -+ * e1000_led_on_generic - Turn LED on ++ * e1000e_led_on_generic - Turn LED on + * @hw: pointer to the HW structure + * + * Turn LED on. + **/ -+s32 e1000_led_on_generic(struct e1000_hw *hw) ++s32 e1000e_led_on_generic(struct e1000_hw *hw) +{ + u32 ctrl; + -+ DEBUGFUNC("e1000_led_on_generic"); -+ + switch (hw->phy.media_type) { + case e1000_media_type_fiber: -+ ctrl = E1000_READ_REG(hw, E1000_CTRL); ++ ctrl = er32(CTRL); + ctrl &= ~E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; -+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ++ ew32(CTRL, ctrl); + break; + case e1000_media_type_copper: -+ E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode2); ++ ew32(LEDCTL, hw->mac.ledctl_mode2); + break; + default: + break; @@ -10479,26 +10455,24 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_led_off_generic - Turn LED off ++ * e1000e_led_off_generic - Turn LED off + * @hw: pointer to the HW structure + * + * Turn LED off. + **/ -+s32 e1000_led_off_generic(struct e1000_hw *hw) ++s32 e1000e_led_off_generic(struct e1000_hw *hw) +{ + u32 ctrl; + -+ DEBUGFUNC("e1000_led_off_generic"); -+ + switch (hw->phy.media_type) { + case e1000_media_type_fiber: -+ ctrl = E1000_READ_REG(hw, E1000_CTRL); ++ ctrl = er32(CTRL); + ctrl |= E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; -+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ++ ew32(CTRL, ctrl); + break; + case e1000_media_type_copper: -+ E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); ++ ew32(LEDCTL, hw->mac.ledctl_mode1); + break; + default: + break; @@ -10508,33 +10482,31 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_set_pcie_no_snoop_generic - Set PCI-express capabilities ++ * e1000e_set_pcie_no_snoop - Set PCI-express capabilities + * @hw: pointer to the HW structure + * @no_snoop: bitmap of snoop events + * + * Set the PCI-express register to snoop for events enabled in 'no_snoop'. + **/ -+void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop) ++void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop) +{ + u32 gcr; + -+ DEBUGFUNC("e1000_set_pcie_no_snoop_generic"); -+ + if (hw->bus.type != e1000_bus_type_pci_express) + goto out; + + if (no_snoop) { -+ gcr = E1000_READ_REG(hw, E1000_GCR); ++ gcr = er32(GCR); + gcr &= ~(PCIE_NO_SNOOP_ALL); + gcr |= no_snoop; -+ E1000_WRITE_REG(hw, E1000_GCR, gcr); ++ ew32(GCR, gcr); + } +out: + return; +} + +/** -+ * e1000_disable_pcie_master_generic - Disables PCI-express master access ++ * e1000e_disable_pcie_master - Disables PCI-express master access + * @hw: pointer to the HW structure + * + * Returns 0 (E1000_SUCCESS) if successful, else returns -10 @@ -10544,31 +10516,29 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + * Disables PCI-Express master access and verifies there are no pending + * requests. + **/ -+s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw) ++s32 e1000e_disable_pcie_master(struct e1000_hw *hw) +{ + u32 ctrl; + s32 timeout = MASTER_DISABLE_TIMEOUT; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_disable_pcie_master_generic"); -+ + if (hw->bus.type != e1000_bus_type_pci_express) + goto out; + -+ ctrl = E1000_READ_REG(hw, E1000_CTRL); ++ ctrl = er32(CTRL); + ctrl |= E1000_CTRL_GIO_MASTER_DISABLE; -+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ++ ew32(CTRL, ctrl); + + while (timeout) { -+ if (!(E1000_READ_REG(hw, E1000_STATUS) & ++ if (!(er32(STATUS) & + E1000_STATUS_GIO_MASTER_ENABLE)) + break; -+ usec_delay(100); ++ udelay(100); + timeout--; + } + + if (!timeout) { -+ DEBUGOUT("Master requests are pending.\n"); ++ e_dbg("Master requests are pending.\n"); + ret_val = -E1000_ERR_MASTER_REQUESTS_PENDING; + goto out; + } @@ -10578,51 +10548,45 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_reset_adaptive_generic - Reset Adaptive Interframe Spacing ++ * e1000e_reset_adaptive - Reset Adaptive Interframe Spacing + * @hw: pointer to the HW structure + * + * Reset the Adaptive Interframe Spacing throttle to default values. + **/ -+void e1000_reset_adaptive_generic(struct e1000_hw *hw) ++void e1000e_reset_adaptive(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + -+ DEBUGFUNC("e1000_reset_adaptive_generic"); -+ + if (!mac->adaptive_ifs) { -+ DEBUGOUT("Not in Adaptive IFS mode!\n"); ++ e_dbg("Not in Adaptive IFS mode!\n"); + goto out; + } + -+ if (!mac->ifs_params_forced) { -+ mac->current_ifs_val = 0; -+ mac->ifs_min_val = IFS_MIN; -+ mac->ifs_max_val = IFS_MAX; -+ mac->ifs_step_size = IFS_STEP; -+ mac->ifs_ratio = IFS_RATIO; -+ } ++ mac->current_ifs_val = 0; ++ mac->ifs_min_val = IFS_MIN; ++ mac->ifs_max_val = IFS_MAX; ++ mac->ifs_step_size = IFS_STEP; ++ mac->ifs_ratio = IFS_RATIO; + + mac->in_ifs_mode = false; -+ E1000_WRITE_REG(hw, E1000_AIT, 0); ++ ew32(AIT, 0); +out: + return; +} + +/** -+ * e1000_update_adaptive_generic - Update Adaptive Interframe Spacing ++ * e1000e_update_adaptive - Update Adaptive Interframe Spacing + * @hw: pointer to the HW structure + * + * Update the Adaptive Interframe Spacing Throttle value based on the + * time between transmitted packets and time between collisions. + **/ -+void e1000_update_adaptive_generic(struct e1000_hw *hw) ++void e1000e_update_adaptive(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + -+ DEBUGFUNC("e1000_update_adaptive_generic"); -+ + if (!mac->adaptive_ifs) { -+ DEBUGOUT("Not in Adaptive IFS mode!\n"); ++ e_dbg("Not in Adaptive IFS mode!\n"); + goto out; + } + @@ -10635,7 +10599,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + else + mac->current_ifs_val += + mac->ifs_step_size; -+ E1000_WRITE_REG(hw, E1000_AIT, mac->current_ifs_val); ++ ew32(AIT, mac->current_ifs_val); + } + } + } else { @@ -10643,7 +10607,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers + (mac->tx_packet_delta <= MIN_NUM_XMITS)) { + mac->current_ifs_val = 0; + mac->in_ifs_mode = false; -+ E1000_WRITE_REG(hw, E1000_AIT, 0); ++ ew32(AIT, 0); + } + } +out: @@ -10661,10 +10625,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers +{ + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_validate_mdi_setting_generic"); -+ + if (!hw->mac.autoneg && (hw->phy.mdix == 0 || hw->phy.mdix == 3)) { -+ DEBUGOUT("Invalid MDI setting detected\n"); ++ e_dbg("Invalid MDI setting detected\n"); + hw->phy.mdix = 1; + ret_val = -E1000_ERR_CONFIG; + goto out; @@ -10673,54 +10635,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.c linux-2.6.22-10/drivers +out: + return ret_val; +} -+ -+/** -+ * e1000_write_8bit_ctrl_reg_generic - Write a 8bit CTRL register -+ * @hw: pointer to the HW structure -+ * @reg: 32bit register offset such as E1000_SCTL -+ * @offset: register offset to write to -+ * @data: data to write at register offset -+ * -+ * Writes an address/data control type register. There are several of these -+ * and they all have the format address << 8 | data and bit 31 is polled for -+ * completion. -+ **/ -+s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg, -+ u32 offset, u8 data) -+{ -+ u32 i, regvalue = 0; -+ s32 ret_val = E1000_SUCCESS; -+ -+ DEBUGFUNC("e1000_write_8bit_ctrl_reg_generic"); -+ -+ /* Set up the address and data */ -+ regvalue = ((u32)data) | (offset << E1000_GEN_CTL_ADDRESS_SHIFT); -+ E1000_WRITE_REG(hw, reg, regvalue); -+ -+ /* Poll the ready bit to see if the MDI read completed */ -+ for (i = 0; i < E1000_GEN_POLL_TIMEOUT; i++) { -+ usec_delay(5); -+ regvalue = E1000_READ_REG(hw, reg); -+ if (regvalue & E1000_GEN_CTL_READY) -+ break; -+ } -+ if (!(regvalue & E1000_GEN_CTL_READY)) { -+ DEBUGOUT1("Reg %08x did not indicate ready\n", reg); -+ ret_val = -E1000_ERR_PHY; -+ goto out; -+ } -+ -+out: -+ return ret_val; -+} diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.h linux-2.6.22-10/drivers/net/e1000e/e1000_mac.h --- linux-2.6.22-0/drivers/net/e1000e/e1000_mac.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000_mac.h 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,86 @@ ++++ linux-2.6.22-10/drivers/net/e1000e/e1000_mac.h 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,77 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -10753,64 +10675,55 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_mac.h linux-2.6.22-10/drivers + * by other files in this 'shared code' + */ +void e1000_init_mac_ops_generic(struct e1000_hw *hw); -+s32 e1000_blink_led_generic(struct e1000_hw *hw); -+s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw); -+s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw); -+s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw); -+s32 e1000_cleanup_led_generic(struct e1000_hw *hw); -+s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw); -+s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw); -+s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw); -+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); -+s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw); -+s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed, ++s32 e1000e_blink_led(struct e1000_hw *hw); ++s32 e1000e_check_for_copper_link(struct e1000_hw *hw); ++s32 e1000e_check_for_fiber_link(struct e1000_hw *hw); ++s32 e1000e_check_for_serdes_link(struct e1000_hw *hw); ++s32 e1000e_cleanup_led_generic(struct e1000_hw *hw); ++s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw); ++s32 e1000e_disable_pcie_master(struct e1000_hw *hw); ++s32 e1000e_force_mac_fc(struct e1000_hw *hw); ++s32 e1000e_get_auto_rd_done(struct e1000_hw *hw); ++s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw); ++void e1000_set_lan_id_single_port(struct e1000_hw *hw); ++s32 e1000e_get_hw_semaphore(struct e1000_hw *hw); ++s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, + u16 *duplex); -+s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw, ++s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, + u16 *speed, u16 *duplex); -+s32 e1000_id_led_init_generic(struct e1000_hw *hw); -+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); -+s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw); -+s32 e1000_set_default_fc_generic(struct e1000_hw *hw); -+s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw); -+s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw); ++s32 e1000e_id_led_init(struct e1000_hw *hw); ++s32 e1000e_led_on_generic(struct e1000_hw *hw); ++s32 e1000e_led_off_generic(struct e1000_hw *hw); ++void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, ++ u8 *mc_addr_list, u32 mc_addr_count); ++s32 e1000e_set_fc_watermarks(struct e1000_hw *hw); ++s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw); +s32 e1000_setup_led_generic(struct e1000_hw *hw); -+s32 e1000_setup_link_generic(struct e1000_hw *hw); -+s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw); -+s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg, -+ u32 offset, u8 data); ++s32 e1000e_setup_link(struct e1000_hw *hw); + -+u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr); -+ -+void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw); -+void e1000_clear_vfta_generic(struct e1000_hw *hw); -+void e1000_config_collision_dist_generic(struct e1000_hw *hw); -+void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count); ++void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw); ++void e1000e_clear_vfta_generic(struct e1000_hw *hw); ++void e1000e_config_collision_dist(struct e1000_hw *hw); ++void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count); +void e1000_mta_set_generic(struct e1000_hw *hw, u32 hash_value); +void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw); -+void e1000_put_hw_semaphore_generic(struct e1000_hw *hw); -+void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index); ++void e1000e_put_hw_semaphore(struct e1000_hw *hw); ++void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index); +s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw); -+void e1000_remove_device_generic(struct e1000_hw *hw); -+void e1000_reset_adaptive_generic(struct e1000_hw *hw); -+void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop); -+void e1000_update_adaptive_generic(struct e1000_hw *hw); -+void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); ++void e1000e_reset_adaptive(struct e1000_hw *hw); ++void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop); ++void e1000e_update_adaptive(struct e1000_hw *hw); ++void e1000e_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); + +#endif diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.c linux-2.6.22-10/drivers/net/e1000e/e1000_manage.c --- linux-2.6.22-0/drivers/net/e1000e/e1000_manage.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000_manage.c 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,383 @@ ++++ linux-2.6.22-10/drivers/net/e1000e/e1000_manage.c 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,365 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -10835,7 +10748,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.c linux-2.6.22-10/driv + +*******************************************************************************/ + -+#include "e1000_hw.h" ++#include "e1000.h" + +static u8 e1000_calculate_checksum(u8 *buffer, u32 length); + @@ -10852,11 +10765,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.c linux-2.6.22-10/driv + u32 i; + u8 sum = 0; + -+ DEBUGFUNC("e1000_calculate_checksum"); -+ + if (!buffer) + return 0; -+ + for (i = 0; i < length; i++) + sum += buffer[i]; + @@ -10873,31 +10783,29 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.c linux-2.6.22-10/driv + * 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; + u8 i; + -+ DEBUGFUNC("e1000_mng_enable_host_if_generic"); -+ + /* Check that the host interface is enabled. */ -+ hicr = E1000_READ_REG(hw, E1000_HICR); ++ hicr = er32(HICR); + if ((hicr & E1000_HICR_EN) == 0) { -+ DEBUGOUT("E1000_HOST_EN bit disabled.\n"); ++ e_dbg("E1000_HOST_EN bit disabled.\n"); + ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; + goto out; + } + /* check the previous command is completed */ + for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { -+ hicr = E1000_READ_REG(hw, E1000_HICR); ++ hicr = er32(HICR); + if (!(hicr & E1000_HICR_C)) + break; -+ msec_delay_irq(1); ++ mdelay(1); + } + + if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { -+ DEBUGOUT("Previous command timeout failed .\n"); ++ e_dbg("Previous command timeout failed .\n"); + ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; + goto out; + } @@ -10917,22 +10825,18 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.c linux-2.6.22-10/driv +{ + u32 fwsm; + -+ DEBUGFUNC("e1000_check_mng_mode_generic"); -+ -+ fwsm = E1000_READ_REG(hw, E1000_FWSM); -+ -+ return ((fwsm & E1000_FWSM_MODE_MASK) == -+ (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); ++ fwsm = er32(FWSM); ++ return (fwsm & E1000_FWSM_MODE_MASK) == ++ (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); +} -+ +/** -+ * e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on TX ++ * e1000e_enable_tx_pkt_filtering - Enable packet filtering on TX + * @hw: pointer to the HW structure + * + * Enables packet filtering on transmit packets if manageability is enabled + * and host interface is enabled. + **/ -+bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw) ++bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw) +{ + struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; + u32 *buffer = (u32 *)&hw->mng_cookie; @@ -10941,8 +10845,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.c linux-2.6.22-10/driv + u8 i, len; + bool tx_filter = true; + -+ DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic"); -+ + /* No manageability, no filtering */ + if (!hw->mac.ops.check_mng_mode(hw)) { + tx_filter = false; @@ -10991,22 +10893,20 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.c linux-2.6.22-10/driv +} + +/** -+ * e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface ++ * e1000e_mng_write_dhcp_info - Writes DHCP info to host interface + * @hw: pointer to the HW structure + * @buffer: pointer to the host interface + * @length: size of the buffer + * + * Writes the DHCP information to the host interface. + **/ -+s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw * hw, u8 *buffer, ++s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, + u16 length) +{ + struct e1000_host_mng_command_header hdr; + s32 ret_val; + u32 hicr; + -+ DEBUGFUNC("e1000_mng_write_dhcp_info_generic"); -+ + hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; + hdr.command_length = length; + hdr.reserved1 = 0; @@ -11030,8 +10930,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.c linux-2.6.22-10/driv + goto out; + + /* Tell the ARC a new command is pending. */ -+ hicr = E1000_READ_REG(hw, E1000_HICR); -+ E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); ++ hicr = er32(HICR); ++ ew32(HICR, hicr | E1000_HICR_C); + +out: + return ret_val; @@ -11044,13 +10944,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.c linux-2.6.22-10/driv + * + * 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); + -+ DEBUGFUNC("e1000_mng_write_cmd_header_generic"); -+ + /* Write the whole command header structure with new checksum. */ + + hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); @@ -11060,7 +10958,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.c linux-2.6.22-10/driv + for (i = 0; i < length; i++) { + E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, + *((u32 *) hdr + i)); -+ E1000_WRITE_FLUSH(hw); ++ e1e_flush(); + } + + return E1000_SUCCESS; @@ -11078,7 +10976,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.c linux-2.6.22-10/driv + * 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; @@ -11087,8 +10985,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.c linux-2.6.22-10/driv + s32 ret_val = E1000_SUCCESS; + u16 remaining, i, j, prev_bytes; + -+ DEBUGFUNC("e1000_mng_host_if_write_generic"); -+ + /* sum = only sum of the data and it is not checksum */ + + if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) { @@ -11127,7 +11023,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.c linux-2.6.22-10/driv + *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++) { @@ -11146,31 +11043,29 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.c linux-2.6.22-10/driv +} + +/** -+ * e1000_enable_mng_pass_thru - Enable processing of ARP's ++ * e1000e_enable_mng_pass_thru - Enable processing of ARP's + * @hw: pointer to the HW structure + * + * Verifies the hardware needs to allow ARPs to be processed by the host. + **/ -+bool e1000_enable_mng_pass_thru(struct e1000_hw *hw) ++bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw) +{ + u32 manc; + u32 fwsm, factps; + bool ret_val = false; + -+ DEBUGFUNC("e1000_enable_mng_pass_thru"); -+ + if (!hw->mac.asf_firmware_present) + goto out; + -+ manc = E1000_READ_REG(hw, E1000_MANC); ++ manc = er32(MANC); + + if (!(manc & E1000_MANC_RCV_TCO_EN) || + !(manc & E1000_MANC_EN_MAC_ADDR_FILTER)) + goto out; + + if (hw->mac.arc_subsystem_valid) { -+ fwsm = E1000_READ_REG(hw, E1000_FWSM); -+ factps = E1000_READ_REG(hw, E1000_FACTPS); ++ fwsm = er32(FWSM); ++ factps = er32(FACTPS); + + if (!(factps & E1000_FACTPS_MNGCG) && + ((fwsm & E1000_FWSM_MODE_MASK) == @@ -11192,12 +11087,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.c linux-2.6.22-10/driv + diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.h linux-2.6.22-10/drivers/net/e1000e/e1000_manage.h --- linux-2.6.22-0/drivers/net/e1000e/e1000_manage.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000_manage.h 2008-10-14 01:51:32.000000000 +0200 ++++ linux-2.6.22-10/drivers/net/e1000e/e1000_manage.h 2009-06-24 00:32:20.000000000 +0200 @@ -0,0 +1,82 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -11226,23 +11121,23 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.h linux-2.6.22-10/driv +#define _E1000_MANAGE_H_ + +bool e1000_check_mng_mode_generic(struct e1000_hw *hw); -+bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw); ++bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw); +s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw); +s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, + u16 length, u16 offset, u8 *sum); +s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, + struct e1000_host_mng_command_header *hdr); -+s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, ++s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, + u8 *buffer, u16 length); -+bool e1000_enable_mng_pass_thru(struct e1000_hw *hw); ++bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw); + -+typedef enum { ++enum e1000_mng_mode { + e1000_mng_mode_none = 0, + e1000_mng_mode_asf, + e1000_mng_mode_pt, + e1000_mng_mode_ipmi, + e1000_mng_mode_host_if_only -+} e1000_mng_mode; ++}; + +#define E1000_FACTPS_MNGCG 0x20000000 + @@ -11278,12 +11173,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_manage.h linux-2.6.22-10/driv +#endif diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers/net/e1000e/e1000_nvm.c --- linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000_nvm.c 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,875 @@ ++++ linux-2.6.22-10/drivers/net/e1000e/e1000_nvm.c 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,594 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -11308,7 +11203,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers + +*******************************************************************************/ + -+#include "e1000_hw.h" ++#include "e1000.h" ++ ++static void e1000_stop_nvm(struct e1000_hw *hw); ++static void e1000e_reload_nvm(struct e1000_hw *hw); + +/** + * e1000_init_nvm_ops_generic - Initialize NVM function pointers @@ -11319,10 +11217,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers +void e1000_init_nvm_ops_generic(struct e1000_hw *hw) +{ + struct e1000_nvm_info *nvm = &hw->nvm; -+ DEBUGFUNC("e1000_init_nvm_ops_generic"); -+ + /* Initialize function pointers */ -+ nvm->ops.reload = e1000_reload_nvm_generic; ++ nvm->ops.reload = e1000e_reload_nvm; +} + +/** @@ -11335,9 +11231,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers +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); ++ ew32(EECD, *eecd); ++ e1e_flush(); ++ udelay(hw->nvm.delay_usec); +} + +/** @@ -11350,9 +11246,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers +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); ++ ew32(EECD, *eecd); ++ e1e_flush(); ++ udelay(hw->nvm.delay_usec); +} + +/** @@ -11368,15 +11264,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers +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 eecd = er32(EECD); + u32 mask; + -+ DEBUGFUNC("e1000_shift_out_eec_bits"); -+ + mask = 0x01 << (count - 1); -+ if (nvm->type == e1000_nvm_eeprom_microwire) -+ eecd &= ~E1000_EECD_DO; -+ else if (nvm->type == e1000_nvm_eeprom_spi) ++ if (nvm->type == e1000_nvm_eeprom_spi) + eecd |= E1000_EECD_DO; + + do { @@ -11385,10 +11277,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers + if (data & mask) + eecd |= E1000_EECD_DI; + -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); -+ E1000_WRITE_FLUSH(hw); ++ ew32(EECD, eecd); ++ e1e_flush(); + -+ usec_delay(nvm->delay_usec); ++ udelay(nvm->delay_usec); + + e1000_raise_eec_clk(hw, &eecd); + e1000_lower_eec_clk(hw, &eecd); @@ -11397,7 +11289,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers + } while (mask); + + eecd &= ~E1000_EECD_DI; -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); ++ ew32(EECD, eecd); +} + +/** @@ -11417,10 +11309,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers + u32 i; + u16 data; + -+ DEBUGFUNC("e1000_shift_in_eec_bits"); -+ -+ eecd = E1000_READ_REG(hw, E1000_EECD); -+ ++ eecd = er32(EECD); + eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); + data = 0; + @@ -11428,7 +11317,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers + data <<= 1; + e1000_raise_eec_clk(hw, &eecd); + -+ eecd = E1000_READ_REG(hw, E1000_EECD); ++ eecd = er32(EECD); + + eecd &= ~E1000_EECD_DI; + if (eecd & E1000_EECD_DO) @@ -11441,69 +11330,64 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_poll_eerd_eewr_done - Poll for EEPROM read/write completion ++ * e1000e_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) ++s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg) +{ + u32 attempts = 100000; + u32 i, reg = 0; + s32 ret_val = -E1000_ERR_NVM; + -+ DEBUGFUNC("e1000_poll_eerd_eewr_done"); -+ + for (i = 0; i < attempts; i++) { + if (ee_reg == E1000_NVM_POLL_READ) -+ reg = E1000_READ_REG(hw, E1000_EERD); ++ reg = er32(EERD); + else -+ reg = E1000_READ_REG(hw, E1000_EEWR); ++ reg = er32(EEWR); + + if (reg & E1000_NVM_RW_REG_DONE) { + ret_val = E1000_SUCCESS; + break; + } + -+ usec_delay(5); ++ udelay(5); + } + + return ret_val; +} + +/** -+ * e1000_acquire_nvm_generic - Generic request for access to EEPROM ++ * e1000e_acquire_nvm - 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) ++s32 e1000e_acquire_nvm(struct e1000_hw *hw) +{ -+ u32 eecd = E1000_READ_REG(hw, E1000_EECD); ++ u32 eecd = er32(EECD); + s32 timeout = E1000_NVM_GRANT_ATTEMPTS; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_acquire_nvm_generic"); -+ -+ E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_REQ); -+ eecd = E1000_READ_REG(hw, E1000_EECD); -+ ++ ew32(EECD, eecd | E1000_EECD_REQ); ++ eecd = er32(EECD); + while (timeout) { + if (eecd & E1000_EECD_GNT) + break; -+ usec_delay(5); -+ eecd = E1000_READ_REG(hw, E1000_EECD); ++ udelay(5); ++ eecd = er32(EECD); + timeout--; + } + + if (!timeout) { + eecd &= ~E1000_EECD_REQ; -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); -+ DEBUGOUT("Could not acquire NVM grant\n"); ++ ew32(EECD, eecd); ++ e_dbg("Could not acquire NVM grant\n"); + ret_val = -E1000_ERR_NVM; + } + @@ -11519,35 +11403,18 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers +static void e1000_standby_nvm(struct e1000_hw *hw) +{ + struct e1000_nvm_info *nvm = &hw->nvm; -+ u32 eecd = E1000_READ_REG(hw, E1000_EECD); ++ u32 eecd = er32(EECD); + -+ DEBUGFUNC("e1000_standby_nvm"); -+ -+ if (nvm->type == e1000_nvm_eeprom_microwire) { -+ eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); -+ E1000_WRITE_FLUSH(hw); -+ usec_delay(nvm->delay_usec); -+ -+ e1000_raise_eec_clk(hw, &eecd); -+ -+ /* Select EEPROM */ -+ eecd |= E1000_EECD_CS; -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); -+ E1000_WRITE_FLUSH(hw); -+ usec_delay(nvm->delay_usec); -+ -+ e1000_lower_eec_clk(hw, &eecd); -+ } else if (nvm->type == e1000_nvm_eeprom_spi) { ++ 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); ++ ew32(EECD, eecd); ++ e1e_flush(); ++ udelay(nvm->delay_usec); + eecd &= ~E1000_EECD_CS; -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); -+ E1000_WRITE_FLUSH(hw); -+ usec_delay(nvm->delay_usec); ++ ew32(EECD, eecd); ++ e1e_flush(); ++ udelay(nvm->delay_usec); + } +} + @@ -11557,43 +11424,33 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers + * + * Terminates the current command by inverting the EEPROM's chip select pin. + **/ -+void e1000_stop_nvm(struct e1000_hw *hw) ++static void e1000_stop_nvm(struct e1000_hw *hw) +{ + u32 eecd; + -+ DEBUGFUNC("e1000_stop_nvm"); -+ -+ eecd = E1000_READ_REG(hw, E1000_EECD); ++ eecd = er32(EECD); + if (hw->nvm.type == e1000_nvm_eeprom_spi) { + /* Pull CS high */ + eecd |= E1000_EECD_CS; + e1000_lower_eec_clk(hw, &eecd); -+ } else if (hw->nvm.type == e1000_nvm_eeprom_microwire) { -+ /* CS on Microwire is active-high */ -+ eecd &= ~(E1000_EECD_CS | E1000_EECD_DI); -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); -+ e1000_raise_eec_clk(hw, &eecd); -+ e1000_lower_eec_clk(hw, &eecd); + } +} + +/** -+ * e1000_release_nvm_generic - Release exclusive access to EEPROM ++ * e1000e_release_nvm - 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) ++void e1000e_release_nvm(struct e1000_hw *hw) +{ + u32 eecd; + -+ DEBUGFUNC("e1000_release_nvm_generic"); -+ + e1000_stop_nvm(hw); + -+ eecd = E1000_READ_REG(hw, E1000_EECD); ++ eecd = er32(EECD); + eecd &= ~E1000_EECD_REQ; -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); ++ ew32(EECD, eecd); +} + +/** @@ -11605,25 +11462,16 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers +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); ++ u32 eecd = er32(EECD); + s32 ret_val = E1000_SUCCESS; + u16 timeout = 0; + u8 spi_stat_reg; + -+ DEBUGFUNC("e1000_ready_nvm_eeprom"); -+ -+ if (nvm->type == e1000_nvm_eeprom_microwire) { -+ /* Clear SK and DI */ -+ eecd &= ~(E1000_EECD_DI | E1000_EECD_SK); -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); -+ /* Set CS */ -+ eecd |= E1000_EECD_CS; -+ E1000_WRITE_REG(hw, E1000_EECD, eecd); -+ } else if (nvm->type == e1000_nvm_eeprom_spi) { ++ 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); ++ ew32(EECD, eecd); ++ udelay(1); + timeout = NVM_MAX_RETRY_SPI; + + /* @@ -11639,13 +11487,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers + if (!(spi_stat_reg & NVM_STATUS_RDY_SPI)) + break; + -+ usec_delay(5); ++ udelay(5); + e1000_standby_nvm(hw); + timeout--; + } + + if (!timeout) { -+ DEBUGOUT("SPI NVM Status error\n"); ++ e_dbg("SPI NVM Status error\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } @@ -11656,130 +11504,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_read_nvm_spi - Read EEPROM's using SPI -+ * @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 -+ * -+ * Reads a 16 bit word from the EEPROM. -+ **/ -+s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -+{ -+ struct e1000_nvm_info *nvm = &hw->nvm; -+ u32 i = 0; -+ s32 ret_val; -+ u16 word_in; -+ u8 read_opcode = NVM_READ_OPCODE_SPI; -+ -+ DEBUGFUNC("e1000_read_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; -+ -+ ret_val = e1000_ready_nvm_eeprom(hw); -+ if (ret_val) -+ goto release; -+ -+ e1000_standby_nvm(hw); -+ -+ if ((nvm->address_bits == 8) && (offset >= 128)) -+ read_opcode |= NVM_A8_OPCODE_SPI; -+ -+ /* Send the READ command (opcode + addr) */ -+ e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits); -+ e1000_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits); -+ -+ /* -+ * Read the data. SPI NVMs increment the address with each byte -+ * read and will roll over if reading beyond the end. This allows -+ * us to read the whole NVM from any offset -+ */ -+ for (i = 0; i < words; i++) { -+ word_in = e1000_shift_in_eec_bits(hw, 16); -+ data[i] = (word_in >> 8) | (word_in << 8); -+ } -+ -+release: -+ nvm->ops.release(hw); -+ -+out: -+ return ret_val; -+} -+ -+/** -+ * e1000_read_nvm_microwire - Reads EEPROM's using microwire -+ * @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 -+ * -+ * Reads a 16 bit word from the EEPROM. -+ **/ -+s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, -+ u16 *data) -+{ -+ struct e1000_nvm_info *nvm = &hw->nvm; -+ u32 i = 0; -+ s32 ret_val; -+ u8 read_opcode = NVM_READ_OPCODE_MICROWIRE; -+ -+ DEBUGFUNC("e1000_read_nvm_microwire"); -+ -+ /* -+ * 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; -+ -+ ret_val = e1000_ready_nvm_eeprom(hw); -+ if (ret_val) -+ goto release; -+ -+ for (i = 0; i < words; i++) { -+ /* Send the READ command (opcode + addr) */ -+ e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits); -+ e1000_shift_out_eec_bits(hw, (u16)(offset + i), -+ nvm->address_bits); -+ -+ /* -+ * Read the data. For microwire, each word requires the -+ * overhead of setup and tear-down. -+ */ -+ data[i] = e1000_shift_in_eec_bits(hw, 16); -+ e1000_standby_nvm(hw); -+ } -+ -+release: -+ nvm->ops.release(hw); -+ -+out: -+ return ret_val; -+} -+ -+/** -+ * e1000_read_nvm_eerd - Reads EEPROM using EERD register ++ * e1000e_read_nvm_eerd - Reads EEPROM using EERD register + * @hw: pointer to the HW structure + * @offset: offset of word in the EEPROM to read + * @words: number of words to read @@ -11787,21 +11512,19 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers + * + * Reads a 16 bit word from the EEPROM using the EERD register. + **/ -+s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) ++s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) +{ + 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"); ++ e_dbg("nvm parameter(s) out of bounds\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } @@ -11810,12 +11533,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers + eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) + + E1000_NVM_RW_REG_START; + -+ E1000_WRITE_REG(hw, E1000_EERD, eerd); -+ ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); ++ ew32(EERD, eerd); ++ ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); + if (ret_val) + break; + -+ data[i] = (E1000_READ_REG(hw, E1000_EERD) >> ++ data[i] = (er32(EERD) >> + E1000_NVM_RW_REG_DATA); + } + @@ -11824,7 +11547,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_write_nvm_spi - Write to EEPROM using SPI ++ * e1000e_write_nvm_spi - Write to EEPROM using SPI + * @hw: pointer to the HW structure + * @offset: offset within the EEPROM to be written to + * @words: number of words to write @@ -11835,21 +11558,19 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers + * If e1000_update_nvm_checksum is not called after this function , the + * EEPROM will most likely contain an invalid checksum. + **/ -+s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) ++s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) +{ + 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"); ++ e_dbg("nvm parameter(s) out of bounds\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } @@ -11899,97 +11620,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers + } + } + -+ msec_delay(nvm->semaphore_delay); -+release: -+ nvm->ops.release(hw); -+ -+out: -+ return ret_val; -+} -+ -+/** -+ * e1000_write_nvm_microwire - Writes EEPROM using microwire -+ * @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 microwire interface. -+ * -+ * If e1000_update_nvm_checksum is not called after this function , the -+ * EEPROM will most likely contain an invalid checksum. -+ **/ -+s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, -+ u16 *data) -+{ -+ struct e1000_nvm_info *nvm = &hw->nvm; -+ s32 ret_val; -+ u32 eecd; -+ u16 words_written = 0; -+ u16 widx = 0; -+ -+ DEBUGFUNC("e1000_write_nvm_microwire"); -+ -+ /* -+ * 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; -+ -+ ret_val = e1000_ready_nvm_eeprom(hw); -+ if (ret_val) -+ goto release; -+ -+ e1000_shift_out_eec_bits(hw, NVM_EWEN_OPCODE_MICROWIRE, -+ (u16)(nvm->opcode_bits + 2)); -+ -+ e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2)); -+ -+ e1000_standby_nvm(hw); -+ -+ while (words_written < words) { -+ e1000_shift_out_eec_bits(hw, NVM_WRITE_OPCODE_MICROWIRE, -+ nvm->opcode_bits); -+ -+ e1000_shift_out_eec_bits(hw, (u16)(offset + words_written), -+ nvm->address_bits); -+ -+ e1000_shift_out_eec_bits(hw, data[words_written], 16); -+ -+ e1000_standby_nvm(hw); -+ -+ for (widx = 0; widx < 200; widx++) { -+ eecd = E1000_READ_REG(hw, E1000_EECD); -+ if (eecd & E1000_EECD_DO) -+ break; -+ usec_delay(50); -+ } -+ -+ if (widx == 200) { -+ DEBUGOUT("NVM Write did not complete\n"); -+ ret_val = -E1000_ERR_NVM; -+ goto release; -+ } -+ -+ e1000_standby_nvm(hw); -+ -+ words_written++; -+ } -+ -+ e1000_shift_out_eec_bits(hw, NVM_EWDS_OPCODE_MICROWIRE, -+ (u16)(nvm->opcode_bits + 2)); -+ -+ e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2)); -+ ++ msleep(10); +release: + nvm->ops.release(hw); + @@ -11998,30 +11629,28 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_read_pba_num_generic - Read device part number ++ * e1000e_read_pba_num - Read device part number + * @hw: pointer to the HW structure + * @pba_num: pointer to device part number + * + * Reads the product board assembly (PBA) number from the EEPROM and stores + * the value in pba_num. + **/ -+s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num) ++s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num) +{ + s32 ret_val; + u16 nvm_data; + -+ DEBUGFUNC("e1000_read_pba_num_generic"); -+ -+ ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); ++ ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); + if (ret_val) { -+ DEBUGOUT("NVM Read Error\n"); ++ e_dbg("NVM Read Error\n"); + goto out; + } + *pba_num = (u32)(nvm_data << 16); + -+ ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data); ++ ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &nvm_data); + if (ret_val) { -+ DEBUGOUT("NVM Read Error\n"); ++ e_dbg("NVM Read Error\n"); + goto out; + } + *pba_num |= nvm_data; @@ -12031,68 +11660,58 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_read_mac_addr_generic - Read device MAC address ++ * e1000e_read_mac_addr_generic - Read device MAC address + * @hw: pointer to the HW structure + * + * 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_read_mac_addr_generic(struct e1000_hw *hw) ++s32 e1000e_read_mac_addr_generic(struct e1000_hw *hw) +{ -+ s32 ret_val = E1000_SUCCESS; -+ u16 offset, nvm_data, i; ++ u32 rar_high; ++ u32 rar_low; ++ u16 i; + -+ DEBUGFUNC("e1000_read_mac_addr"); ++ rar_high = er32(RAH(0)); ++ rar_low = er32(RAL(0)); + -+ 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); -+ } ++ for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++) ++ hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8)); + -+ /* 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; ++ for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++) ++ hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8)); + + 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_validate_nvm_checksum_generic - Validate EEPROM checksum ++ * e1000e_validate_nvm_checksum_generic - Validate EEPROM checksum + * @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) ++s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + u16 checksum = 0; + u16 i, nvm_data; + -+ DEBUGFUNC("e1000_validate_nvm_checksum_generic"); -+ + for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { -+ ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); ++ ret_val = e1000_read_nvm(hw, i, 1, &nvm_data); + if (ret_val) { -+ DEBUGOUT("NVM Read Error\n"); ++ e_dbg("NVM Read Error\n"); + goto out; + } + checksum += nvm_data; + } + + if (checksum != (u16) NVM_SUM) { -+ DEBUGOUT("NVM Checksum Invalid\n"); ++ e_dbg("NVM Checksum Invalid\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } @@ -12102,67 +11721,62 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_update_nvm_checksum_generic - Update EEPROM checksum ++ * e1000e_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 e1000e_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); ++ ret_val = e1000_read_nvm(hw, i, 1, &nvm_data); + if (ret_val) { -+ DEBUGOUT("NVM Read Error while updating checksum.\n"); ++ e_dbg("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"); -+ } ++ ret_val = e1000_write_nvm(hw, NVM_CHECKSUM_REG, 1, &checksum); ++ if (ret_val) ++ e_dbg("NVM Write Error while updating checksum.\n"); + +out: + return ret_val; +} + +/** -+ * e1000_reload_nvm_generic - Reloads EEPROM ++ * e1000e_reload_nvm - Reloads EEPROM + * @hw: pointer to the HW structure + * + * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the + * extended control register. + **/ -+void e1000_reload_nvm_generic(struct e1000_hw *hw) ++static void e1000e_reload_nvm(struct e1000_hw *hw) +{ + u32 ctrl_ext; + -+ DEBUGFUNC("e1000_reload_nvm_generic"); -+ -+ usec_delay(10); -+ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ++ udelay(10); ++ ctrl_ext = er32(CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_EE_RST; -+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); -+ E1000_WRITE_FLUSH(hw); ++ ew32(CTRL_EXT, ctrl_ext); ++ e1e_flush(); +} + diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.h linux-2.6.22-10/drivers/net/e1000e/e1000_nvm.h --- linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000_nvm.h 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,58 @@ ++++ linux-2.6.22-10/drivers/net/e1000e/e1000_nvm.h 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,51 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -12191,40 +11805,33 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_nvm.h linux-2.6.22-10/drivers +#define _E1000_NVM_H_ + +void e1000_init_nvm_ops_generic(struct e1000_hw *hw); -+s32 e1000_acquire_nvm_generic(struct e1000_hw *hw); -+ -+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_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); -+s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, -+ u16 words, u16 *data); -+s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, ++s32 e1000e_acquire_nvm(struct e1000_hw *hw); ++ ++s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg); ++s32 e1000e_read_mac_addr_generic(struct e1000_hw *hw); ++s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num); ++s32 e1000e_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 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data); ++s32 e1000e_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_microwire(struct e1000_hw *hw, u16 offset, -+ u16 words, u16 *data); -+s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, ++s32 e1000e_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_stop_nvm(struct e1000_hw *hw); -+void e1000_release_nvm_generic(struct e1000_hw *hw); -+void e1000_reload_nvm_generic(struct e1000_hw *hw); ++s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw); ++void e1000e_release_nvm(struct e1000_hw *hw); + +#define E1000_STM_OPCODE 0xDB00 + +#endif -diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_osdep.h linux-2.6.22-10/drivers/net/e1000e/e1000_osdep.h ---- linux-2.6.22-0/drivers/net/e1000e/e1000_osdep.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000_osdep.h 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,116 @@ +diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers/net/e1000e/e1000_phy.c +--- linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.22-10/drivers/net/e1000e/e1000_phy.c 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,3137 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -12249,135 +11856,23 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_osdep.h linux-2.6.22-10/drive + +*******************************************************************************/ + ++#include "e1000.h" + -+/* glue for the OS-dependent part of e1000 -+ * includes register access macros -+ */ -+ -+#ifndef _E1000_OSDEP_H_ -+#define _E1000_OSDEP_H_ -+ -+#include -+#include -+#include -+#include ++static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw); ++static s32 e1000_copper_link_autoneg(struct e1000_hw *hw); ++static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg); ++static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, ++ u16 *data, bool read); ++static u32 e1000_get_phy_addr_for_hv_page(u32 page); ++static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, ++ u16 *data, bool read); + -+#include "kcompat.h" -+ -+#define usec_delay(x) udelay(x) -+#ifndef msec_delay -+#define msec_delay(x) do { if(in_interrupt()) { \ -+ /* Don't sleep in interrupt context! */ \ -+ BUG(); \ -+ } else { \ -+ msleep(x); \ -+ } } while (0) -+ -+/* 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 -+ -+#define PCI_COMMAND_REGISTER PCI_COMMAND -+#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE -+#define ETH_ADDR_LEN ETH_ALEN -+ -+ -+#define DEBUGOUT(S) -+#define DEBUGOUT1(S, A...) -+ -+#define DEBUGFUNC(F) DEBUGOUT(F "\n") -+#define DEBUGOUT2 DEBUGOUT1 -+#define DEBUGOUT3 DEBUGOUT2 -+#define DEBUGOUT7 DEBUGOUT3 -+ -+#define E1000_WRITE_REG(a, reg, value) ( \ -+ writel((value), ((a)->hw_addr + reg))) -+ -+#define E1000_READ_REG(a, reg) (readl((a)->hw_addr + reg)) -+ -+#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \ -+ writel((value), ((a)->hw_addr + reg + ((offset) << 2)))) -+ -+#define E1000_READ_REG_ARRAY(a, reg, offset) ( \ -+ readl((a)->hw_addr + reg + ((offset) << 2))) -+ -+#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY -+#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY -+ -+#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \ -+ writew((value), ((a)->hw_addr + reg + ((offset) << 1)))) -+ -+#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \ -+ readw((a)->hw_addr + reg + ((offset) << 1))) -+ -+#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \ -+ writeb((value), ((a)->hw_addr + reg + (offset)))) -+ -+#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \ -+ readb((a)->hw_addr + reg + (offset))) -+ -+#define E1000_WRITE_REG_IO(a, reg, offset) do { \ -+ outl(reg, ((a)->io_base)); \ -+ outl(offset, ((a)->io_base + 4)); } while(0) -+ -+#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, E1000_STATUS) -+ -+#define E1000_WRITE_FLASH_REG(a, reg, value) ( \ -+ writel((value), ((a)->flash_address + reg))) -+ -+#define E1000_WRITE_FLASH_REG16(a, reg, value) ( \ -+ writew((value), ((a)->flash_address + reg))) -+ -+#define E1000_READ_FLASH_REG(a, reg) (readl((a)->flash_address + reg)) -+ -+#define E1000_READ_FLASH_REG16(a, reg) (readw((a)->flash_address + reg)) -+ -+#endif /* _E1000_OSDEP_H_ */ -diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers/net/e1000e/e1000_phy.c ---- linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000_phy.c 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,2489 @@ -+/******************************************************************************* -+ -+ Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 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: -+ Linux NICS -+ e1000-devel Mailing List -+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -+ -+*******************************************************************************/ -+ -+#include "e1000_hw.h" -+ -+static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg); -+/* 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])) ++/* 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])) + +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, @@ -12393,87 +11888,101 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + sizeof(e1000_igp_2_cable_length_table[0])) + +/** -+ * e1000_check_reset_block_generic - Check if PHY reset is blocked ++ * e1000e_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) ++s32 e1000e_check_reset_block_generic(struct e1000_hw *hw) +{ + u32 manc; + -+ DEBUGFUNC("e1000_check_reset_block"); -+ -+ manc = E1000_READ_REG(hw, E1000_MANC); ++ manc = er32(MANC); + + return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? + E1000_BLK_PHY_RESET : E1000_SUCCESS; +} + +/** -+ * e1000_get_phy_id - Retrieve the PHY ID and revision ++ * e1000e_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) ++s32 e1000e_get_phy_id(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + u16 phy_id; -+ -+ DEBUGFUNC("e1000_get_phy_id"); ++ u16 retry_count = 0; + + if (!(phy->ops.read_reg)) + goto out; + -+ ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); -+ if (ret_val) -+ goto out; ++ while (retry_count < 2) { ++ ret_val = e1e_rphy(hw, PHY_ID1, &phy_id); ++ if (ret_val) ++ goto out; + -+ 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 << 16); ++ udelay(20); ++ ret_val = e1e_rphy(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); ++ phy->id |= (u32)(phy_id & PHY_REVISION_MASK); ++ phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); ++ ++ if (phy->id != 0 && phy->id != PHY_REVISION_MASK) ++ goto out; ++ ++ /* ++ * If the PHY ID is still unknown, we may have an 82577 without link. ++ * We will try again after setting Slow MDIC mode. No harm in trying ++ * again in this case since the PHY ID is unknown at this point anyway ++ */ ++ ret_val = e1000_set_mdio_slow_mode_hv(hw, true); ++ if (ret_val) ++ goto out; + ++ retry_count++; ++ } +out: ++ /* Revert to MDIO fast mode, if applicable */ ++ if (retry_count) ++ ret_val = e1000_set_mdio_slow_mode_hv(hw, false); ++ + return ret_val; +} + +/** -+ * e1000_phy_reset_dsp_generic - Reset PHY DSP ++ * e1000e_phy_reset_dsp - Reset PHY DSP + * @hw: pointer to the HW structure + * + * Reset the digital signal processor. + **/ -+s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw) ++s32 e1000e_phy_reset_dsp(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_phy_reset_dsp_generic"); -+ + if (!(hw->phy.ops.write_reg)) + goto out; + -+ ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); ++ ret_val = e1e_wphy(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); + if (ret_val) + goto out; + -+ ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0); ++ ret_val = e1e_wphy(hw, M88E1000_PHY_GEN_CONTROL, 0); + +out: + return ret_val; +} + +/** -+ * e1000_read_phy_reg_mdic - Read MDI control register ++ * e1000e_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 @@ -12481,14 +11990,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * Reads the MDI control register in the PHY at offset and stores the + * information read to data. + **/ -+s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) ++s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) +{ + struct e1000_phy_info *phy = &hw->phy; + u32 i, mdic = 0; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_read_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 @@ -12498,7 +12005,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + (phy->addr << E1000_MDIC_PHY_SHIFT) | + (E1000_MDIC_OP_READ)); + -+ E1000_WRITE_REG(hw, E1000_MDIC, mdic); ++ ew32(MDIC, mdic); + + /* + * Poll the ready bit to see if the MDI read completed @@ -12506,18 +12013,18 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * the lower time out + */ + for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { -+ usec_delay(50); -+ mdic = E1000_READ_REG(hw, E1000_MDIC); ++ udelay(50); ++ mdic = er32(MDIC); + if (mdic & E1000_MDIC_READY) + break; + } + if (!(mdic & E1000_MDIC_READY)) { -+ DEBUGOUT("MDI Read did not complete\n"); ++ e_dbg("MDI Read did not complete\n"); + ret_val = -E1000_ERR_PHY; + goto out; + } + if (mdic & E1000_MDIC_ERROR) { -+ DEBUGOUT("MDI Error\n"); ++ e_dbg("MDI Error\n"); + ret_val = -E1000_ERR_PHY; + goto out; + } @@ -12528,21 +12035,19 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_write_phy_reg_mdic - Write MDI control register ++ * e1000e_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 + * + * Writes data to MDI control register in the PHY at offset. + **/ -+s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) ++s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, 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 @@ -12553,7 +12058,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + (phy->addr << E1000_MDIC_PHY_SHIFT) | + (E1000_MDIC_OP_WRITE)); + -+ E1000_WRITE_REG(hw, E1000_MDIC, mdic); ++ ew32(MDIC, mdic); + + /* + * Poll the ready bit to see if the MDI read completed @@ -12561,18 +12066,18 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * the lower time out + */ + for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { -+ usec_delay(50); -+ mdic = E1000_READ_REG(hw, E1000_MDIC); ++ udelay(50); ++ mdic = er32(MDIC); + if (mdic & E1000_MDIC_READY) + break; + } + if (!(mdic & E1000_MDIC_READY)) { -+ DEBUGOUT("MDI Write did not complete\n"); ++ e_dbg("MDI Write did not complete\n"); + ret_val = -E1000_ERR_PHY; + goto out; + } + if (mdic & E1000_MDIC_ERROR) { -+ DEBUGOUT("MDI Error\n"); ++ e_dbg("MDI Error\n"); + ret_val = -E1000_ERR_PHY; + goto out; + } @@ -12582,7 +12087,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_read_phy_reg_m88 - Read m88 PHY register ++ * e1000e_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 @@ -12591,12 +12096,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * and storing the retrieved information in data. Release any acquired + * semaphores before exiting. + **/ -+s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data) ++s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data) +{ + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_read_phy_reg_m88"); -+ + if (!(hw->phy.ops.acquire)) + goto out; + @@ -12604,8 +12107,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + if (ret_val) + goto out; + -+ ret_val = e1000_read_phy_reg_mdic(hw, -+ MAX_PHY_REG_ADDRESS & offset, ++ ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, + data); + + hw->phy.ops.release(hw); @@ -12615,7 +12117,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_write_phy_reg_m88 - Write m88 PHY register ++ * e1000e_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 @@ -12623,12 +12125,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * Acquires semaphore, if necessary, then writes the data to PHY register + * at the offset. Release any acquired semaphores before exiting. + **/ -+s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) ++s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) +{ + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_write_phy_reg_m88"); -+ + if (!(hw->phy.ops.acquire)) + goto out; + @@ -12636,8 +12136,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + if (ret_val) + goto out; + -+ ret_val = e1000_write_phy_reg_mdic(hw, -+ MAX_PHY_REG_ADDRESS & offset, ++ ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, + data); + + hw->phy.ops.release(hw); @@ -12647,7 +12146,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_read_phy_reg_igp - Read igp PHY register ++ * e1000e_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 @@ -12656,12 +12155,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * and storing the retrieved information in data. Release any acquired + * semaphores before exiting. + **/ -+s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) ++s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) +{ + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_read_phy_reg_igp"); -+ + if (!(hw->phy.ops.acquire)) + goto out; + @@ -12670,7 +12167,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + goto out; + + if (offset > MAX_PHY_MULTI_PAGE_REG) { -+ ret_val = e1000_write_phy_reg_mdic(hw, ++ ret_val = e1000e_write_phy_reg_mdic(hw, + IGP01E1000_PHY_PAGE_SELECT, + (u16)offset); + if (ret_val) { @@ -12679,8 +12176,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + } + } + -+ ret_val = e1000_read_phy_reg_mdic(hw, -+ MAX_PHY_REG_ADDRESS & offset, ++ ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, + data); + + hw->phy.ops.release(hw); @@ -12690,7 +12186,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_write_phy_reg_igp - Write igp PHY register ++ * e1000e_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 @@ -12698,12 +12194,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * Acquires semaphore, if necessary, then writes the data to PHY register + * at the offset. Release any acquired semaphores before exiting. + **/ -+s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) ++s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) +{ + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_write_phy_reg_igp"); -+ + if (!(hw->phy.ops.acquire)) + goto out; + @@ -12712,7 +12206,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + goto out; + + if (offset > MAX_PHY_MULTI_PAGE_REG) { -+ ret_val = e1000_write_phy_reg_mdic(hw, ++ ret_val = e1000e_write_phy_reg_mdic(hw, + IGP01E1000_PHY_PAGE_SELECT, + (u16)offset); + if (ret_val) { @@ -12721,8 +12215,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + } + } + -+ ret_val = e1000_write_phy_reg_mdic(hw, -+ MAX_PHY_REG_ADDRESS & offset, ++ ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, + data); + + hw->phy.ops.release(hw); @@ -12732,7 +12225,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_read_kmrn_reg_generic - Read kumeran register ++ * e1000e_read_kmrn_reg - Read kumeran register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data @@ -12741,13 +12234,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * using the kumeran interface. The information retrieved is stored in data. + * Release any acquired semaphores before exiting. + **/ -+s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data) ++s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data) +{ + u32 kmrnctrlsta; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_read_kmrn_reg_generic"); -+ + if (!(hw->phy.ops.acquire)) + goto out; + @@ -12757,11 +12248,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + + kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & + E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; -+ E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); ++ ew32(KMRNCTRLSTA, kmrnctrlsta); + -+ usec_delay(2); ++ udelay(2); + -+ kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA); ++ kmrnctrlsta = er32(KMRNCTRLSTA); + *data = (u16)kmrnctrlsta; + + hw->phy.ops.release(hw); @@ -12771,7 +12262,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_write_kmrn_reg_generic - Write kumeran register ++ * e1000e_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 @@ -12780,13 +12271,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * 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) ++s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data) +{ + u32 kmrnctrlsta; + s32 ret_val = E1000_SUCCESS; + -+ DEBUGFUNC("e1000_write_kmrn_reg_generic"); -+ + if (!(hw->phy.ops.acquire)) + goto out; + @@ -12796,9 +12285,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + + kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & + E1000_KMRNCTRLSTA_OFFSET) | data; -+ E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); ++ ew32(KMRNCTRLSTA, kmrnctrlsta); + -+ usec_delay(2); ++ udelay(2); + hw->phy.ops.release(hw); + +out: @@ -12806,32 +12295,72 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_copper_link_setup_m88 - Setup m88 PHY's for copper link ++ * e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link ++ * @hw: pointer to the HW structure ++ * ++ * Sets up Carrier-sense on Transmit and downshift values. ++ **/ ++s32 e1000_copper_link_setup_82577(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ u16 phy_data; ++ ++ if (phy->reset_disable) { ++ ret_val = E1000_SUCCESS; ++ goto out; ++ } ++ ++ /* Enable CRS on TX. This must be set for half-duplex operation. */ ++ ret_val = e1e_rphy(hw, I82577_CFG_REG, &phy_data); ++ if (ret_val) ++ goto out; ++ ++ phy_data |= I82577_CFG_ASSERT_CRS_ON_TX; ++ ++ /* Enable downshift */ ++ phy_data |= I82577_CFG_ENABLE_DOWNSHIFT; ++ ++ ret_val = e1e_wphy(hw, I82577_CFG_REG, phy_data); ++ if (ret_val) ++ goto out; ++ ++ /* Set number of link attempts before downshift */ ++ ret_val = e1e_rphy(hw, I82577_CTRL_REG, &phy_data); ++ if (ret_val) ++ goto out; ++ phy_data &= ~I82577_CTRL_DOWNSHIFT_MASK; ++ ret_val = e1e_wphy(hw, I82577_CTRL_REG, phy_data); ++ ++out: ++ return ret_val; ++} ++ ++/** ++ * e1000e_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) ++s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_data; + -+ DEBUGFUNC("e1000_copper_link_setup_m88"); -+ + if (phy->reset_disable) { + ret_val = E1000_SUCCESS; + goto out; + } + + /* 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); ++ ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + if (ret_val) + goto out; + -+ /* For newer PHYs this bit is downshift enable */ -+ if (phy->type == e1000_phy_m88) ++ /* For BM PHY this bit is downshift enable */ ++ if (phy->type != e1000_phy_bm) + phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; + + /* @@ -12845,19 +12374,19 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; + + 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; ++ 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; + } + + /* @@ -12875,7 +12404,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + if (phy->type == e1000_phy_bm) + phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT; + -+ ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); ++ ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + if (ret_val) + goto out; + @@ -12886,8 +12415,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * 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, ++ ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, + &phy_data); + if (ret_val) + goto out; @@ -12906,8 +12434,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | + M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); + } -+ ret_val = phy->ops.write_reg(hw, -+ M88E1000_EXT_PHY_SPEC_CTRL, ++ ret_val = e1e_wphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, + phy_data); + if (ret_val) + goto out; @@ -12915,50 +12442,63 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + + if ((phy->type == e1000_phy_bm) && (phy->id == BME1000_E_PHY_ID_R2)) { + /* Set PHY page 0, register 29 to 0x0003 */ -+ ret_val = phy->ops.write_reg(hw, 29, 0x0003); ++ ret_val = e1e_wphy(hw, 29, 0x0003); + if (ret_val) + goto out; + + /* Set PHY page 0, register 30 to 0x0000 */ -+ ret_val = phy->ops.write_reg(hw, 30, 0x0000); ++ ret_val = e1e_wphy(hw, 30, 0x0000); + if (ret_val) + goto out; + } + + /* Commit the changes. */ -+ ret_val = phy->ops.commit(hw); ++ ret_val = e1000e_commit_phy(hw); + if (ret_val) { -+ DEBUGOUT("Error committing the PHY changes\n"); ++ e_dbg("Error committing the PHY changes\n"); + goto out; + } + ++ if (phy->type == e1000_phy_82578) { ++ ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, ++ &phy_data); ++ if (ret_val) ++ goto out; ++ ++ /* 82578 PHY - set the downshift count to 1x. */ ++ phy_data |= I82578_EPSCR_DOWNSHIFT_ENABLE; ++ phy_data &= ~I82578_EPSCR_DOWNSHIFT_COUNTER_MASK; ++ ret_val = e1e_wphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, ++ phy_data); ++ if (ret_val) ++ goto out; ++ } ++ +out: + return ret_val; +} + +/** -+ * e1000_copper_link_setup_igp - Setup igp PHY's for copper link ++ * e1000e_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) ++s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 data; + -+ DEBUGFUNC("e1000_copper_link_setup_igp"); -+ + if (phy->reset_disable) { + ret_val = E1000_SUCCESS; + goto out; + } + -+ ret_val = hw->phy.ops.reset(hw); ++ ret_val = e1000_phy_hw_reset(hw); + if (ret_val) { -+ DEBUGOUT("Error resetting the PHY.\n"); ++ e_dbg("Error resetting the PHY.\n"); + goto out; + } + @@ -12966,7 +12506,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * Wait 100ms for MAC to configure PHY from NVM settings, to avoid + * timeout issues when LFS is enabled. + */ -+ msec_delay(100); ++ msleep(100); + + /* + * The NVM settings will configure LPLU in D3 for @@ -12976,7 +12516,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + /* 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"); ++ e_dbg("Error Disabling LPLU D3\n"); + goto out; + } + } @@ -12985,12 +12525,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + 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"); ++ e_dbg("Error Disabling LPLU D0\n"); + goto out; + } + } + /* Configure mdi-mdix settings */ -+ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data); ++ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CTRL, &data); + if (ret_val) + goto out; + @@ -13008,7 +12548,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + data |= IGP01E1000_PSCR_AUTO_MDIX; + break; + } -+ ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data); ++ ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CTRL, data); + if (ret_val) + goto out; + @@ -13021,31 +12561,31 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + */ + if (phy->autoneg_advertised == ADVERTISE_1000_FULL) { + /* Disable SmartSpeed */ -+ ret_val = phy->ops.read_reg(hw, ++ ret_val = e1e_rphy(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); + if (ret_val) + goto out; + + data &= ~IGP01E1000_PSCFR_SMART_SPEED; -+ ret_val = phy->ops.write_reg(hw, ++ ret_val = e1e_wphy(hw, + IGP01E1000_PHY_PORT_CONFIG, + data); + if (ret_val) + goto out; + + /* Set auto Master/Slave resolution process */ -+ ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); ++ ret_val = e1e_rphy(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); ++ ret_val = e1e_wphy(hw, PHY_1000T_CTRL, data); + if (ret_val) + goto out; + } + -+ ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); ++ ret_val = e1e_rphy(hw, PHY_1000T_CTRL, &data); + if (ret_val) + goto out; + @@ -13069,7 +12609,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + default: + break; + } -+ ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); ++ ret_val = e1e_wphy(hw, PHY_1000T_CTRL, data); + if (ret_val) + goto out; + } @@ -13087,14 +12627,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * 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) ++static s32 e1000_copper_link_autoneg(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_ctrl; + -+ DEBUGFUNC("e1000_copper_link_autoneg"); -+ + /* + * Perform some bounds checking on the autoneg advertisement + * parameter. @@ -13108,24 +12646,24 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + if (phy->autoneg_advertised == 0) + phy->autoneg_advertised = phy->autoneg_mask; + -+ DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); ++ e_dbg("Reconfiguring auto-neg advertisement params\n"); + ret_val = e1000_phy_setup_autoneg(hw); + if (ret_val) { -+ DEBUGOUT("Error Setting up Auto-Negotiation\n"); ++ e_dbg("Error Setting up Auto-Negotiation\n"); + goto out; + } -+ DEBUGOUT("Restarting Auto-Neg\n"); ++ e_dbg("Restarting Auto-Neg\n"); + + /* + * 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); ++ ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_ctrl); + if (ret_val) + goto out; + + phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); -+ ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl); ++ ret_val = e1e_wphy(hw, PHY_CONTROL, phy_ctrl); + if (ret_val) + goto out; + @@ -13136,7 +12674,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + if (phy->autoneg_wait_to_complete) { + ret_val = hw->mac.ops.wait_autoneg(hw); + if (ret_val) { -+ DEBUGOUT("Error while waiting for " ++ e_dbg("Error while waiting for " + "autoneg to complete\n"); + goto out; + } @@ -13157,26 +12695,23 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * return successful. Otherwise, setup advertisement and flow control to + * the appropriate values for the wanted auto-negotiation. + **/ -+s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) ++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"); -+ + phy->autoneg_advertised &= phy->autoneg_mask; + + /* Read the MII Auto-Neg Advertisement Register (Address 4). */ -+ ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); ++ ret_val = e1e_rphy(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, ++ ret_val = e1e_rphy(hw, PHY_1000T_CTRL, + &mii_1000t_ctrl_reg); + if (ret_val) + goto out; @@ -13201,40 +12736,39 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + 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); ++ e_dbg("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"); ++ e_dbg("Advertise 10mb Half duplex\n"); + mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; + } + + /* Do we want to advertise 10 Mb Full Duplex? */ + if (phy->autoneg_advertised & ADVERTISE_10_FULL) { -+ DEBUGOUT("Advertise 10mb Full duplex\n"); ++ e_dbg("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"); ++ e_dbg("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"); ++ e_dbg("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"); -+ } ++ if (phy->autoneg_advertised & ADVERTISE_1000_HALF) ++ e_dbg("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"); ++ e_dbg("Advertise 1000mb Full duplex\n"); + mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; + } + @@ -13256,7 +12790,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * other: No software override. The flow control configuration + * in the EEPROM is used. + */ -+ switch (hw->fc.type) { ++ switch (hw->fc.current_mode) { + case e1000_fc_none: + /* + * Flow control (Rx & Tx) is completely disabled by a @@ -13272,7 +12806,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * 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 ++ * (in e1000e_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); @@ -13293,19 +12827,19 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); + break; + default: -+ DEBUGOUT("Flow control param set incorrectly\n"); ++ e_dbg("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); ++ ret_val = e1e_wphy(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); + if (ret_val) + goto out; + -+ DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); ++ e_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); + + if (phy->autoneg_mask & ADVERTISE_1000_FULL) { -+ ret_val = phy->ops.write_reg(hw, ++ ret_val = e1e_wphy(hw, + PHY_1000T_CTRL, + mii_1000t_ctrl_reg); + if (ret_val) @@ -13317,7 +12851,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_setup_copper_link_generic - Configure copper link settings ++ * e1000e_setup_copper_link - Configure copper link settings + * @hw: pointer to the HW structure + * + * Calls the appropriate function to configure the link for auto-neg or forced @@ -13325,13 +12859,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * to configure collision distance and flow control are called. If link is + * not established, we return -E1000_ERR_PHY (-2). + **/ -+s32 e1000_setup_copper_link_generic(struct e1000_hw *hw) ++s32 e1000e_setup_copper_link(struct e1000_hw *hw) +{ + s32 ret_val; + bool link; + -+ DEBUGFUNC("e1000_setup_copper_link_generic"); -+ + if (hw->mac.autoneg) { + /* + * Setup autoneg and flow control advertisement and perform @@ -13345,10 +12877,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * PHY will be set to 10H, 10F, 100H or 100F + * depending on user settings. + */ -+ DEBUGOUT("Forcing Speed and Duplex\n"); ++ e_dbg("Forcing Speed and Duplex\n"); + ret_val = hw->phy.ops.force_speed_duplex(hw); + if (ret_val) { -+ DEBUGOUT("Error Forcing Speed and Duplex\n"); ++ e_dbg("Error Forcing Speed and Duplex\n"); + goto out; + } + } @@ -13357,7 +12889,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * Check link status. Wait up to 100 microseconds for link to become + * valid. + */ -+ ret_val = e1000_phy_has_link_generic(hw, ++ ret_val = e1000e_phy_has_link_generic(hw, + COPPER_LINK_UP_LIMIT, + 10, + &link); @@ -13365,11 +12897,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + 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); ++ e_dbg("Valid link established!!!\n"); ++ e1000e_config_collision_dist(hw); ++ ret_val = e1000e_config_fc_after_link_up(hw); + } else { -+ DEBUGOUT("Unable to establish link!!!\n"); ++ e_dbg("Unable to establish link!!!\n"); + } + +out: @@ -13377,29 +12909,27 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_phy_force_speed_duplex_igp - Force speed/duplex for igp PHY ++ * e1000e_phy_force_speed_duplex_igp - Force speed/duplex for igp PHY + * @hw: pointer to the HW structure + * + * 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). + **/ -+s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw) ++s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw) +{ + 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); ++ ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data); + if (ret_val) + goto out; + -+ e1000_phy_force_speed_duplex_setup(hw, &phy_data); ++ e1000e_phy_force_speed_duplex_setup(hw, &phy_data); + -+ ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); ++ ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data); + if (ret_val) + goto out; + @@ -13407,37 +12937,36 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * 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); ++ ret_val = e1e_rphy(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); ++ ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); + if (ret_val) + goto out; + -+ DEBUGOUT1("IGP PSCR: %X\n", phy_data); ++ e_dbg("IGP PSCR: %X\n", phy_data); + -+ usec_delay(1); ++ udelay(1); + + if (phy->autoneg_wait_to_complete) { -+ DEBUGOUT("Waiting for forced speed/duplex link on IGP phy.\n"); ++ e_dbg("Waiting for forced speed/duplex link on IGP phy.\n"); + -+ ret_val = e1000_phy_has_link_generic(hw, ++ ret_val = e1000e_phy_has_link_generic(hw, + PHY_FORCE_LIMIT, + 100000, + &link); + if (ret_val) + goto out; + -+ if (!link) { -+ DEBUGOUT("Link taking longer than expected.\n"); -+ } ++ if (!link) ++ e_dbg("Link taking longer than expected.\n"); + + /* Try once more */ -+ ret_val = e1000_phy_has_link_generic(hw, ++ ret_val = e1000e_phy_has_link_generic(hw, + PHY_FORCE_LIMIT, + 100000, + &link); @@ -13450,7 +12979,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_phy_force_speed_duplex_m88 - Force speed/duplex for m88 PHY ++ * e1000e_phy_force_speed_duplex_m88 - Force speed/duplex for m88 PHY + * @hw: pointer to the HW structure + * + * Calls the PHY setup function to force speed and duplex. Clears the @@ -13459,52 +12988,48 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * After reset, TX_CLK and CRS on Tx must be set. Return successful upon + * successful completion, else return corresponding error code. + **/ -+s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) ++s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_data; + bool link; + -+ DEBUGFUNC("e1000_phy_force_speed_duplex_m88"); -+ + /* + * 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); ++ ret_val = e1e_rphy(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); ++ ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + if (ret_val) + goto out; + -+ DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data); ++ e_dbg("M88E1000 PSCR: %X\n", phy_data); + -+ ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); ++ ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data); + if (ret_val) + goto out; + -+ e1000_phy_force_speed_duplex_setup(hw, &phy_data); -+ -+ /* Reset the phy to commit changes. */ -+ phy_data |= MII_CR_RESET; ++ e1000e_phy_force_speed_duplex_setup(hw, &phy_data); + -+ ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); ++ ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data); + if (ret_val) + goto out; + -+ usec_delay(1); ++ /* Reset the phy to commit changes. */ ++ ret_val = e1000e_commit_phy(hw); ++ if (ret_val) ++ goto out; + + if (phy->autoneg_wait_to_complete) { -+ DEBUGOUT("Waiting for forced speed/duplex link on M88 phy.\n"); ++ e_dbg("Waiting for forced speed/duplex link on M88 phy.\n"); + -+ ret_val = e1000_phy_has_link_generic(hw, -+ PHY_FORCE_LIMIT, -+ 100000, -+ &link); ++ ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, ++ 100000, &link); + if (ret_val) + goto out; + @@ -13513,26 +13038,24 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * We didn't get link. + * Reset the DSP and cross our fingers. + */ -+ ret_val = phy->ops.write_reg(hw, ++ ret_val = e1e_wphy(hw, + M88E1000_PHY_PAGE_SELECT, + 0x001d); + if (ret_val) + goto out; -+ ret_val = e1000_phy_reset_dsp_generic(hw); ++ ret_val = e1000e_phy_reset_dsp(hw); + if (ret_val) + goto out; + } + + /* Try once more */ -+ ret_val = e1000_phy_has_link_generic(hw, -+ PHY_FORCE_LIMIT, -+ 100000, -+ &link); ++ ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, ++ 100000, &link); + if (ret_val) + goto out; + } + -+ ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); ++ ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); + if (ret_val) + goto out; + @@ -13542,7 +13065,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * 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); ++ ret_val = e1e_wphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); + if (ret_val) + goto out; + @@ -13550,19 +13073,91 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * 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); ++ ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + if (ret_val) + goto out; + + phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; -+ ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); ++ ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, phy_data); ++ ++out: ++ return ret_val; ++} ++ ++/** ++ * 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; ++ ++ if (phy->type != e1000_phy_ife) { ++ ret_val = e1000e_phy_force_speed_duplex_igp(hw); ++ goto out; ++ } ++ ++ ret_val = e1e_rphy(hw, PHY_CONTROL, &data); ++ if (ret_val) ++ goto out; ++ ++ e1000e_phy_force_speed_duplex_setup(hw, &data); ++ ++ ret_val = e1e_wphy(hw, PHY_CONTROL, data); ++ if (ret_val) ++ goto out; ++ ++ /* Disable MDI-X support for 10/100 */ ++ ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data); ++ if (ret_val) ++ goto out; ++ ++ data &= ~IFE_PMC_AUTO_MDIX; ++ data &= ~IFE_PMC_FORCE_MDIX; ++ ++ ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, data); ++ if (ret_val) ++ goto out; ++ ++ e_dbg("IFE PMC: %X\n", data); ++ ++ udelay(1); ++ ++ if (phy->autoneg_wait_to_complete) { ++ e_dbg("Waiting for forced speed/duplex link on IFE phy.\n"); ++ ++ ret_val = e1000e_phy_has_link_generic(hw, ++ PHY_FORCE_LIMIT, ++ 100000, ++ &link); ++ if (ret_val) ++ goto out; ++ ++ if (!link) ++ e_dbg("Link taking longer than expected.\n"); ++ ++ /* Try once more */ ++ ret_val = e1000e_phy_has_link_generic(hw, ++ PHY_FORCE_LIMIT, ++ 100000, ++ &link); ++ if (ret_val) ++ goto out; ++ } + +out: + return ret_val; +} + +/** -+ * e1000_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex ++ * e1000e_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 + * @@ -13573,18 +13168,16 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * 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) ++void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl) +{ + 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; ++ hw->fc.current_mode = e1000_fc_none; + + /* Force speed/duplex on the mac */ -+ ctrl = E1000_READ_REG(hw, E1000_CTRL); ++ ctrl = er32(CTRL); + ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); + ctrl &= ~E1000_CTRL_SPD_SEL; + @@ -13598,11 +13191,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + if (mac->forced_speed_duplex & E1000_ALL_HALF_DUPLEX) { + ctrl &= ~E1000_CTRL_FD; + *phy_ctrl &= ~MII_CR_FULL_DUPLEX; -+ DEBUGOUT("Half Duplex\n"); ++ e_dbg("Half Duplex\n"); + } else { + ctrl |= E1000_CTRL_FD; + *phy_ctrl |= MII_CR_FULL_DUPLEX; -+ DEBUGOUT("Full Duplex\n"); ++ e_dbg("Full Duplex\n"); + } + + /* Forcing 10mb or 100mb? */ @@ -13610,21 +13203,21 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + 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"); ++ e_dbg("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"); ++ e_dbg("Forcing 10mb\n"); + } + -+ e1000_config_collision_dist_generic(hw); ++ e1000e_config_collision_dist(hw); + -+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ++ ew32(CTRL, ctrl); +} + +/** -+ * e1000_set_d3_lplu_state_generic - Sets low power link up state for D3 ++ * e1000e_set_d3_lplu_state - Sets low power link up state for D3 + * @hw: pointer to the HW structure + * @active: boolean used to enable/disable lplu + * @@ -13637,25 +13230,22 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * During driver activity, SmartSpeed should be enabled so performance is + * maintained. + **/ -+s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active) ++s32 e1000e_set_d3_lplu_state(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); ++ ret_val = e1e_rphy(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, ++ ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, + data); + if (ret_val) + goto out; @@ -13666,27 +13256,27 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * SmartSpeed, so performance is maintained. + */ + if (phy->smart_speed == e1000_smart_speed_on) { -+ ret_val = phy->ops.read_reg(hw, ++ ret_val = e1e_rphy(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); + if (ret_val) + goto out; + + data |= IGP01E1000_PSCFR_SMART_SPEED; -+ ret_val = phy->ops.write_reg(hw, ++ ret_val = e1e_wphy(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, ++ ret_val = e1e_rphy(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); + if (ret_val) + goto out; + + data &= ~IGP01E1000_PSCFR_SMART_SPEED; -+ ret_val = phy->ops.write_reg(hw, ++ ret_val = e1e_wphy(hw, + IGP01E1000_PHY_PORT_CONFIG, + data); + if (ret_val) @@ -13696,22 +13286,19 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + (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, ++ ret_val = e1e_wphy(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, ++ ret_val = e1e_rphy(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, ++ ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, + data); + } + @@ -13720,25 +13307,25 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_check_downshift_generic - Checks whether a downshift in speed occurred ++ * e1000e_check_downshift - 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) ++s32 e1000e_check_downshift(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: + case e1000_phy_bm: ++ case e1000_phy_82578: ++ case e1000_phy_82577: + offset = M88E1000_PHY_SPEC_STATUS; + mask = M88E1000_PSSR_DOWNSHIFT; + break; @@ -13755,7 +13342,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + goto out; + } + -+ ret_val = phy->ops.read_reg(hw, offset, &phy_data); ++ ret_val = e1e_rphy(hw, offset, &phy_data); + + if (!ret_val) + phy->speed_downgraded = (phy_data & mask) ? true : false; @@ -13778,9 +13365,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + s32 ret_val; + u16 data; + -+ DEBUGFUNC("e1000_check_polarity_m88"); -+ -+ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &data); ++ ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &data); + + if (!ret_val) + phy->cable_polarity = (data & M88E1000_PSSR_REV_POLARITY) @@ -13805,13 +13390,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + 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); ++ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_STATUS, &data); + if (ret_val) + goto out; + @@ -13828,7 +13411,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + mask = IGP01E1000_PSSR_POLARITY_REVERSED; + } + -+ ret_val = phy->ops.read_reg(hw, offset, &data); ++ ret_val = e1e_rphy(hw, offset, &data); + + if (!ret_val) + phy->cable_polarity = (data & mask) @@ -13840,33 +13423,64 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_wait_autoneg_generic - Wait for auto-neg completion ++ * e1000_check_polarity_ife - Check cable polarity for IFE PHY + * @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. ++ * Polarity is determined on the polarity reversal feature being enabled. + **/ -+s32 e1000_wait_autoneg_generic(struct e1000_hw *hw) ++s32 e1000_check_polarity_ife(struct e1000_hw *hw) +{ -+ s32 ret_val = E1000_SUCCESS; -+ u16 i, phy_status; ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ u16 phy_data, offset, mask; + -+ DEBUGFUNC("e1000_wait_autoneg_generic"); ++ /* ++ * 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 = e1e_rphy(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 - 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(struct e1000_hw *hw) ++{ ++ s32 ret_val = E1000_SUCCESS; ++ u16 i, phy_status; + + 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); ++ ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); + if (ret_val) + break; -+ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); ++ ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); + if (ret_val) + break; + if (phy_status & MII_SR_AUTONEG_COMPLETE) + break; -+ msec_delay(100); ++ msleep(100); + } + + /* @@ -13877,7 +13491,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_phy_has_link_generic - Polls PHY for link ++ * e1000e_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 @@ -13885,14 +13499,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * + * Polls the PHY status register for link, 'iterations' number of times. + **/ -+s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, ++s32 e1000e_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; + @@ -13902,18 +13514,24 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * 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); ++ ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); + if (ret_val) -+ break; -+ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); ++ /* ++ * 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. ++ */ ++ udelay(usec_interval); ++ ret_val = e1e_rphy(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); ++ mdelay(usec_interval/1000); + else -+ usec_delay(usec_interval); ++ udelay(usec_interval); + } + + *success = (i < iterations) ? true : false; @@ -13922,7 +13540,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_get_cable_length_m88 - Determine cable length for m88 PHY ++ * e1000e_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 @@ -13936,20 +13554,23 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * 3 110 - 140 meters + * 4 > 140 meters + **/ -+s32 e1000_get_cable_length_m88(struct e1000_hw *hw) ++s32 e1000e_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); ++ ret_val = e1e_rphy(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]; + @@ -13960,7 +13581,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_get_cable_length_igp_2 - Determine cable length for igp2 PHY ++ * e1000e_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 @@ -13970,7 +13591,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * into a lookup table to obtain the approximate cable length + * for each channel. + **/ -+s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw) ++s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; @@ -13983,11 +13604,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + 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); ++ ret_val = e1e_rphy(hw, agc_reg_array[i], &phy_data); + if (ret_val) + goto out; + @@ -14034,7 +13653,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_get_phy_info_m88 - Retrieve PHY information ++ * e1000e_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) @@ -14043,55 +13662,52 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * 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) ++s32 e1000e_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 (hw->phy.media_type != e1000_media_type_copper) { -+ DEBUGOUT("Phy info is only valid for copper media\n"); ++ e_dbg("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); ++ ret_val = e1000e_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"); ++ e_dbg("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); ++ ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + if (ret_val) + goto out; + + phy->polarity_correction = (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) -+ ? true -+ : false; ++ ? 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); ++ ret_val = e1e_rphy(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); ++ ret_val = e1000_get_cable_length(hw); + if (ret_val) + goto out; + -+ ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); ++ ret_val = e1e_rphy(hw, PHY_1000T_STATUS, &phy_data); + if (ret_val) + goto out; + @@ -14114,7 +13730,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_get_phy_info_igp - Retrieve igp PHY information ++ * e1000e_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 @@ -14122,21 +13738,19 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * 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) ++s32 e1000e_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); ++ ret_val = e1000e_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"); ++ e_dbg("Phy info is only valid if link is up\n"); + ret_val = -E1000_ERR_CONFIG; + goto out; + } @@ -14147,7 +13761,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + if (ret_val) + goto out; + -+ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); ++ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_STATUS, &data); + if (ret_val) + goto out; + @@ -14155,11 +13769,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + + if ((data & IGP01E1000_PSSR_SPEED_MASK) == + IGP01E1000_PSSR_SPEED_1000MBPS) { -+ ret_val = hw->phy.ops.get_cable_length(hw); ++ ret_val = e1000_get_cable_length(hw); + if (ret_val) + goto out; + -+ ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data); ++ ret_val = e1e_rphy(hw, PHY_1000T_STATUS, &data); + if (ret_val) + goto out; + @@ -14181,39 +13795,37 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_phy_sw_reset_generic - PHY software reset ++ * e1000e_phy_sw_reset - 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 e1000e_phy_sw_reset(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); ++ ret_val = e1e_rphy(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); ++ ret_val = e1e_wphy(hw, PHY_CONTROL, phy_ctrl); + if (ret_val) + goto out; + -+ usec_delay(1); ++ udelay(1); + +out: + return ret_val; +} + +/** -+ * e1000_phy_hw_reset_generic - PHY hardware reset ++ * e1000e_phy_hw_reset_generic - PHY hardware reset + * @hw: pointer to the HW structure + * + * Verify the reset block is not blocking us from resetting. Acquire @@ -14221,15 +13833,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * 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) ++s32 e1000e_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); ++ ret_val = e1000_check_reset_block(hw); + if (ret_val) { + ret_val = E1000_SUCCESS; + goto out; @@ -14239,16 +13849,16 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + 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); ++ ctrl = er32(CTRL); ++ ew32(CTRL, ctrl | E1000_CTRL_PHY_RST); ++ e1e_flush(); + -+ usec_delay(phy->reset_delay_us); ++ udelay(phy->reset_delay_us); + -+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl); -+ E1000_WRITE_FLUSH(hw); ++ ew32(CTRL, ctrl); ++ e1e_flush(); + -+ usec_delay(150); ++ udelay(150); + + phy->ops.release(hw); + @@ -14259,17 +13869,15 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_get_cfg_done_generic - Generic configuration done ++ * e1000e_get_cfg_done - 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) ++s32 e1000e_get_cfg_done(struct e1000_hw *hw) +{ -+ DEBUGFUNC("e1000_get_cfg_done_generic"); -+ -+ msec_delay_irq(10); ++ mdelay(10); + + return E1000_SUCCESS; +} @@ -14282,92 +13890,92 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + **/ +s32 e1000_phy_init_script_igp3(struct e1000_hw *hw) +{ -+ DEBUGOUT("Running IGP 3 PHY init script\n"); ++ e_dbg("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); ++ e1e_wphy(hw, 0x2F5B, 0x9018); + /* Remove all caps from Replica path filter */ -+ hw->phy.ops.write_reg(hw, 0x2F52, 0x0000); ++ e1e_wphy(hw, 0x2F52, 0x0000); + /* Bias trimming for ADC, AFE and Driver (Default) */ -+ hw->phy.ops.write_reg(hw, 0x2FB1, 0x8B24); ++ e1e_wphy(hw, 0x2FB1, 0x8B24); + /* Increase Hybrid poly bias */ -+ hw->phy.ops.write_reg(hw, 0x2FB2, 0xF8F0); ++ e1e_wphy(hw, 0x2FB2, 0xF8F0); + /* Add 4% to Tx amplitude in Gig mode */ -+ hw->phy.ops.write_reg(hw, 0x2010, 0x10B0); ++ e1e_wphy(hw, 0x2010, 0x10B0); + /* Disable trimming (TTT) */ -+ hw->phy.ops.write_reg(hw, 0x2011, 0x0000); ++ e1e_wphy(hw, 0x2011, 0x0000); + /* Poly DC correction to 94.6% + 2% for all channels */ -+ hw->phy.ops.write_reg(hw, 0x20DD, 0x249A); ++ e1e_wphy(hw, 0x20DD, 0x249A); + /* ABS DC correction to 95.9% */ -+ hw->phy.ops.write_reg(hw, 0x20DE, 0x00D3); ++ e1e_wphy(hw, 0x20DE, 0x00D3); + /* BG temp curve trim */ -+ hw->phy.ops.write_reg(hw, 0x28B4, 0x04CE); ++ e1e_wphy(hw, 0x28B4, 0x04CE); + /* Increasing ADC OPAMP stage 1 currents to max */ -+ hw->phy.ops.write_reg(hw, 0x2F70, 0x29E4); ++ e1e_wphy(hw, 0x2F70, 0x29E4); + /* Force 1000 ( required for enabling PHY regs configuration) */ -+ hw->phy.ops.write_reg(hw, 0x0000, 0x0140); ++ e1e_wphy(hw, 0x0000, 0x0140); + /* Set upd_freq to 6 */ -+ hw->phy.ops.write_reg(hw, 0x1F30, 0x1606); ++ e1e_wphy(hw, 0x1F30, 0x1606); + /* Disable NPDFE */ -+ hw->phy.ops.write_reg(hw, 0x1F31, 0xB814); ++ e1e_wphy(hw, 0x1F31, 0xB814); + /* Disable adaptive fixed FFE (Default) */ -+ hw->phy.ops.write_reg(hw, 0x1F35, 0x002A); ++ e1e_wphy(hw, 0x1F35, 0x002A); + /* Enable FFE hysteresis */ -+ hw->phy.ops.write_reg(hw, 0x1F3E, 0x0067); ++ e1e_wphy(hw, 0x1F3E, 0x0067); + /* Fixed FFE for short cable lengths */ -+ hw->phy.ops.write_reg(hw, 0x1F54, 0x0065); ++ e1e_wphy(hw, 0x1F54, 0x0065); + /* Fixed FFE for medium cable lengths */ -+ hw->phy.ops.write_reg(hw, 0x1F55, 0x002A); ++ e1e_wphy(hw, 0x1F55, 0x002A); + /* Fixed FFE for long cable lengths */ -+ hw->phy.ops.write_reg(hw, 0x1F56, 0x002A); ++ e1e_wphy(hw, 0x1F56, 0x002A); + /* Enable Adaptive Clip Threshold */ -+ hw->phy.ops.write_reg(hw, 0x1F72, 0x3FB0); ++ e1e_wphy(hw, 0x1F72, 0x3FB0); + /* AHT reset limit to 1 */ -+ hw->phy.ops.write_reg(hw, 0x1F76, 0xC0FF); ++ e1e_wphy(hw, 0x1F76, 0xC0FF); + /* Set AHT master delay to 127 msec */ -+ hw->phy.ops.write_reg(hw, 0x1F77, 0x1DEC); ++ e1e_wphy(hw, 0x1F77, 0x1DEC); + /* Set scan bits for AHT */ -+ hw->phy.ops.write_reg(hw, 0x1F78, 0xF9EF); ++ e1e_wphy(hw, 0x1F78, 0xF9EF); + /* Set AHT Preset bits */ -+ hw->phy.ops.write_reg(hw, 0x1F79, 0x0210); ++ e1e_wphy(hw, 0x1F79, 0x0210); + /* Change integ_factor of channel A to 3 */ -+ hw->phy.ops.write_reg(hw, 0x1895, 0x0003); ++ e1e_wphy(hw, 0x1895, 0x0003); + /* Change prop_factor of channels BCD to 8 */ -+ hw->phy.ops.write_reg(hw, 0x1796, 0x0008); ++ e1e_wphy(hw, 0x1796, 0x0008); + /* Change cg_icount + enable integbp for channels BCD */ -+ hw->phy.ops.write_reg(hw, 0x1798, 0xD008); ++ e1e_wphy(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); ++ e1e_wphy(hw, 0x1898, 0xD918); + /* Disable AHT in Slave mode on channel A */ -+ hw->phy.ops.write_reg(hw, 0x187A, 0x0800); ++ e1e_wphy(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); ++ e1e_wphy(hw, 0x0019, 0x008D); + /* Enable restart AN on an1000_dis change */ -+ hw->phy.ops.write_reg(hw, 0x001B, 0x2080); ++ e1e_wphy(hw, 0x001B, 0x2080); + /* Enable wh_fifo read clock in 10/100 modes */ -+ hw->phy.ops.write_reg(hw, 0x0014, 0x0045); ++ e1e_wphy(hw, 0x0014, 0x0045); + /* Restart AN, Speed selection is 1000 */ -+ hw->phy.ops.write_reg(hw, 0x0000, 0x1340); ++ e1e_wphy(hw, 0x0000, 0x1340); + + return E1000_SUCCESS; +} + +/** -+ * e1000_get_phy_type_from_id - Get PHY type from id ++ * e1000e_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. + **/ -+e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id) ++enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id) +{ -+ e1000_phy_type phy_type = e1000_phy_unknown; ++ enum e1000_phy_type phy_type = e1000_phy_unknown; + + switch (phy_id) { + case M88E1000_I_PHY_ID: @@ -14394,6 +14002,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + case BME1000_E_PHY_ID_R2: + phy_type = e1000_phy_bm; + break; ++ case I82578_E_PHY_ID: ++ phy_type = e1000_phy_82578; ++ break; ++ case I82577_E_PHY_ID: ++ phy_type = e1000_phy_82577; ++ break; + default: + phy_type = e1000_phy_unknown; + break; @@ -14402,37 +14016,39 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_determine_phy_address - Determines PHY address. ++ * e1000e_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 e1000e_determine_phy_address(struct e1000_hw *hw) +{ + s32 ret_val = -E1000_ERR_PHY_TYPE; -+ u32 phy_addr= 0; ++ u32 phy_addr = 0; + u32 i; -+ e1000_phy_type phy_type = e1000_phy_unknown; ++ 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); ++ e1000e_get_phy_id(hw); ++ phy_type = e1000e_get_phy_type_from_id(hw->phy.id); + -+ /* -+ * If phy_type is valid, break - we found our -+ * PHY address -+ */ ++ /* ++ * 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); ++ msleep(1); + i++; + } while (i < 10); + } @@ -14458,7 +14074,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_write_phy_reg_bm - Write BM PHY register ++ * e1000e_write_phy_reg_bm - Write BM PHY register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset @@ -14466,19 +14082,17 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * Acquires semaphore, if necessary, then writes the data to PHY register + * at the offset. Release any acquired semaphores before exiting. + **/ -+s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) ++s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) +{ + s32 ret_val; + u32 page_select = 0; + u32 page = offset >> IGP_PAGE_SHIFT; + u32 page_shift = 0; + -+ DEBUGFUNC("e1000_write_phy_reg_bm"); -+ + /* Page 800 works differently than the rest so it has its own func */ + if (page == BM_WUC_PAGE) { -+ ret_val = e1000_access_phy_wakeup_reg_bm(hw, -+ offset, &data, false); ++ ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, ++ false); + goto out; + } + @@ -14503,7 +14117,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + } + + /* Page is shifted left, PHY expects (page x 32) */ -+ ret_val = e1000_write_phy_reg_mdic(hw, page_select, ++ ret_val = e1000e_write_phy_reg_mdic(hw, page_select, + (page << page_shift)); + if (ret_val) { + hw->phy.ops.release(hw); @@ -14511,8 +14125,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + } + } + -+ ret_val = e1000_write_phy_reg_mdic(hw, -+ MAX_PHY_REG_ADDRESS & offset, ++ ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, + data); + + hw->phy.ops.release(hw); @@ -14522,7 +14135,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_read_phy_reg_bm - Read BM PHY register ++ * e1000e_read_phy_reg_bm - Read BM PHY register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data @@ -14531,19 +14144,17 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * and storing the retrieved information in data. Release any acquired + * semaphores before exiting. + **/ -+s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) ++s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) +{ + s32 ret_val; + u32 page_select = 0; + u32 page = offset >> IGP_PAGE_SHIFT; + u32 page_shift = 0; + -+ DEBUGFUNC("e1000_read_phy_reg_bm"); -+ + /* Page 800 works differently than the rest so it has its own func */ + if (page == BM_WUC_PAGE) { -+ ret_val = e1000_access_phy_wakeup_reg_bm(hw, -+ offset, data, true); ++ ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, ++ true); + goto out; + } + @@ -14568,7 +14179,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + } + + /* Page is shifted left, PHY expects (page x 32) */ -+ ret_val = e1000_write_phy_reg_mdic(hw, page_select, ++ ret_val = e1000e_write_phy_reg_mdic(hw, page_select, + (page << page_shift)); + if (ret_val) { + hw->phy.ops.release(hw); @@ -14576,9 +14187,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + } + } + -+ ret_val = e1000_read_phy_reg_mdic(hw, -+ MAX_PHY_REG_ADDRESS & offset, -+ data); ++ ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, ++ data); + hw->phy.ops.release(hw); + +out: @@ -14586,7 +14196,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_read_phy_reg_bm2 - Read BM PHY register ++ * e1000e_read_phy_reg_bm2 - Read BM PHY register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data @@ -14595,13 +14205,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * and storing the retrieved information in data. Release any acquired + * semaphores before exiting. + **/ -+s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data) ++s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data) +{ + s32 ret_val; + u16 page = (u16)(offset >> IGP_PAGE_SHIFT); + -+ DEBUGFUNC("e1000_write_phy_reg_bm2"); -+ + /* Page 800 works differently than the rest so it has its own func */ + if (page == BM_WUC_PAGE) { + ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, @@ -14618,7 +14226,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + if (offset > MAX_PHY_MULTI_PAGE_REG) { + + /* Page is shifted left, PHY expects (page x 32) */ -+ ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, ++ ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, + page); + + if (ret_val) { @@ -14627,7 +14235,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + } + } + -+ ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, ++ ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, + data); + hw->phy.ops.release(hw); + @@ -14636,7 +14244,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers +} + +/** -+ * e1000_write_phy_reg_bm2 - Write BM PHY register ++ * e1000e_write_phy_reg_bm2 - Write BM PHY register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset @@ -14644,13 +14252,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * Acquires semaphore, if necessary, then writes the data to PHY register + * at the offset. Release any acquired semaphores before exiting. + **/ -+s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) ++s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) +{ + s32 ret_val; + u16 page = (u16)(offset >> IGP_PAGE_SHIFT); + -+ DEBUGFUNC("e1000_write_phy_reg_bm2"); -+ + /* Page 800 works differently than the rest so it has its own func */ + if (page == BM_WUC_PAGE) { + ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, @@ -14666,7 +14272,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + + if (offset > MAX_PHY_MULTI_PAGE_REG) { + /* Page is shifted left, PHY expects (page x 32) */ -+ ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, ++ ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, + page); + + if (ret_val) { @@ -14675,7 +14281,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + } + } + -+ ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, ++ ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, + data); + + hw->phy.ops.release(hw); @@ -14701,19 +14307,22 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * 4) Read or write the data using the data opcode (0x12) + * 5) Restore 769_17.2 to its original value + **/ -+s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, -+ u32 offset, u16 *data, bool read) ++static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, ++ u16 *data, bool read) +{ + s32 ret_val; -+ u16 reg = ((u16)offset); ++ u16 reg = BM_PHY_REG_NUM(offset); + u16 phy_reg = 0; + u8 phy_acquired = 1; + -+ DEBUGFUNC("e1000_read_phy_wakeup_reg_bm"); ++ /* Gig must be disabled for MDIO accesses to page 800 */ ++ if ((hw->mac.type == e1000_pchlan) && ++ (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE))) ++ e_dbg("Attempting to access page 800 while gig enabled.\n"); + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) { -+ DEBUGOUT("Could not acquire PHY\n"); ++ e_dbg("Could not acquire PHY\n"); + phy_acquired = 0; + goto out; + } @@ -14722,55 +14331,55 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + hw->phy.addr = 1; + + /* Set page 769 */ -+ e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, ++ e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, + (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); + -+ ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg); ++ ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg); + if (ret_val) { -+ DEBUGOUT("Could not read PHY page 769\n"); ++ e_dbg("Could not read PHY page 769\n"); + goto out; + } + + /* First clear bit 4 to avoid a power state change */ + phy_reg &= ~(BM_WUC_HOST_WU_BIT); -+ ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); ++ ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); + if (ret_val) { -+ DEBUGOUT("Could not clear PHY page 769 bit 4\n"); ++ e_dbg("Could not clear PHY page 769 bit 4\n"); + goto out; + } + + /* Write bit 2 = 1, and clear bit 4 to 769_17 */ -+ ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, ++ ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, + phy_reg | BM_WUC_ENABLE_BIT); + if (ret_val) { -+ DEBUGOUT("Could not write PHY page 769 bit 2\n"); ++ e_dbg("Could not write PHY page 769 bit 2\n"); + goto out; + } + + /* Select page 800 */ -+ ret_val = e1000_write_phy_reg_mdic(hw, ++ ret_val = e1000e_write_phy_reg_mdic(hw, + IGP01E1000_PHY_PAGE_SELECT, + (BM_WUC_PAGE << IGP_PAGE_SHIFT)); + + /* Write the page 800 offset value using opcode 0x11 */ -+ ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg); ++ ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg); + if (ret_val) { -+ DEBUGOUT("Could not write address opcode to page 800\n"); ++ e_dbg("Could not write address opcode to page 800\n"); + goto out; + } + + if (read) { + /* Read the page 800 value using opcode 0x12 */ -+ ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, -+ data); ++ ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, ++ data); + } else { -+ /* Read the page 800 value using opcode 0x12 */ -+ ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, -+ *data); ++ /* Write the page 800 value using opcode 0x12 */ ++ ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, ++ *data); + } + + if (ret_val) { -+ DEBUGOUT("Could not read data value from page 800\n"); ++ e_dbg("Could not access data value from page 800\n"); + goto out; + } + @@ -14778,13 +14387,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + * Restore 769_17.2 to its original value + * Set page 769 + */ -+ e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, ++ e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, + (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); + + /* Clear 769_17.2 */ -+ ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); ++ ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); + if (ret_val) { -+ DEBUGOUT("Could not clear PHY page 769 bit 2\n"); ++ e_dbg("Could not clear PHY page 769 bit 2\n"); + goto out; + } + @@ -14807,9 +14416,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + 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); ++ e1e_rphy(hw, PHY_CONTROL, &mii_reg); + mii_reg &= ~MII_CR_POWER_DOWN; -+ hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); ++ e1e_wphy(hw, PHY_CONTROL, mii_reg); +} + +/** @@ -14825,220 +14434,552 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.c linux-2.6.22-10/drivers + 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); ++ e1e_rphy(hw, PHY_CONTROL, &mii_reg); + mii_reg |= MII_CR_POWER_DOWN; -+ hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); -+ msec_delay(1); ++ e1e_wphy(hw, PHY_CONTROL, mii_reg); ++ msleep(1); +} -diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.h linux-2.6.22-10/drivers/net/e1000e/e1000_phy.h ---- linux-2.6.22-0/drivers/net/e1000e/e1000_phy.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000_phy.h 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,190 @@ -+/******************************************************************************* + -+ Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow) ++{ ++ s32 ret_val = E1000_SUCCESS; ++ u16 data = 0; + -+ 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 = hw->phy.ops.acquire(hw); ++ if (ret_val) ++ 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. ++ /* Set MDIO mode - page 769, register 16: 0x2580==slow, 0x2180==fast */ ++ hw->phy.addr = 1; ++ ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, ++ (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); ++ if (ret_val) { ++ hw->phy.ops.release(hw); ++ return ret_val; ++ } ++ ret_val = e1000e_write_phy_reg_mdic(hw, BM_CS_CTRL1, ++ (0x2180 | (slow << 10))); + -+ 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. ++ /* dummy read when reverting to fast mode - throw away result */ ++ if (!slow) ++ e1000e_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data); + -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". ++ hw->phy.ops.release(hw); + -+ Contact Information: -+ Linux NICS -+ e1000-devel Mailing List -+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ return ret_val; ++} + -+*******************************************************************************/ ++/** ++ * e1000_read_phy_reg_hv - Read HV PHY register ++ * @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 ++ * semaphore before exiting. ++ **/ ++s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) ++{ ++ s32 ret_val; ++ u16 page = BM_PHY_REG_PAGE(offset); ++ u16 reg = BM_PHY_REG_NUM(offset); ++ bool in_slow_mode = false; ++ ++ /* Workaround failure in MDIO access while cable is disconnected */ ++ if ((hw->phy.type == e1000_phy_82577) && ++ !(er32(STATUS) & E1000_STATUS_LU)) { ++ ret_val = e1000_set_mdio_slow_mode_hv(hw, true); ++ if (ret_val) ++ goto out; + -+#ifndef _E1000_PHY_H_ -+#define _E1000_PHY_H_ ++ in_slow_mode = true; ++ } + -+typedef enum { -+ e1000_ms_hw_default = 0, -+ e1000_ms_force_master, -+ e1000_ms_force_slave, -+ e1000_ms_auto -+} e1000_ms_type; ++ /* Page 800 works differently than the rest so it has its own func */ ++ if (page == BM_WUC_PAGE) { ++ ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, ++ data, true); ++ goto out; ++ } + -+typedef enum { -+ e1000_smart_speed_default = 0, -+ e1000_smart_speed_on, -+ e1000_smart_speed_off -+} e1000_smart_speed; ++ if (page > 0 && page < HV_INTC_FC_PAGE_START) { ++ ret_val = e1000_access_phy_debug_regs_hv(hw, offset, ++ data, true); ++ 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_phy_setup_autoneg(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); -+e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id); -+s32 e1000_determine_phy_address(struct e1000_hw* hw); -+s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data); -+s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data); -+s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data, -+ bool read); -+s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data); -+s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data); -+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); ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) ++ goto out; + -+#define E1000_MAX_PHY_ADDR 4 ++ hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); + -+/* 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 ++ if (page == HV_INTC_FC_PAGE_START) ++ page = 0; + -+#define BM_WUC_PAGE 800 -+#define BM_WUC_ADDRESS_OPCODE 0x11 -+#define BM_WUC_DATA_OPCODE 0x12 -+#define BM_WUC_ENABLE_PAGE 769 -+#define BM_WUC_ENABLE_REG 17 -+#define BM_WUC_ENABLE_BIT (1 << 2) -+#define BM_WUC_HOST_WU_BIT (1 << 4) ++ if (reg > MAX_PHY_MULTI_PAGE_REG) { ++ if ((hw->phy.type != e1000_phy_82578) || ++ ((reg != I82578_ADDR_REG) && ++ (reg != I82578_ADDR_REG + 1))) { ++ u32 phy_addr = hw->phy.addr; + -+/* BM PHY Copper Specific Control 1 */ -+#define BM_CS_CTRL1 16 -+#define BM_CS_CTRL1_ENERGY_DETECT 0x0300 /* Enable Energy Detect */ ++ hw->phy.addr = 1; + -+/* BM PHY Copper Specific States */ -+#define BM_CS_STATUS 17 -+#define BM_CS_STATUS_ENERGY_DETECT 0x0010 /* Energy Detect Status */ ++ /* Page is shifted left, PHY expects (page x 32) */ ++ ret_val = e1000e_write_phy_reg_mdic(hw, ++ IGP01E1000_PHY_PAGE_SELECT, ++ (page << IGP_PAGE_SHIFT)); ++ if (ret_val) { ++ hw->phy.ops.release(hw); ++ goto out; ++ } ++ hw->phy.addr = phy_addr; ++ } ++ } + -+#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 -+#define IGP01E1000_PHY_POLARITY_MASK 0x0078 ++ ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, ++ data); ++ hw->phy.ops.release(hw); + -+#define IGP01E1000_PSCR_AUTO_MDIX 0x1000 -+#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */ ++out: ++ /* Revert to MDIO fast mode, if applicable */ ++ if ((hw->phy.type == e1000_phy_82577) && in_slow_mode) ++ ret_val = e1000_set_mdio_slow_mode_hv(hw, false); + -+#define IGP01E1000_PSCFR_SMART_SPEED 0x0080 ++ return ret_val; ++} + -+/* Enable flexible speed on link-up */ -+#define IGP01E1000_GMII_FLEX_SPD 0x0010 -+#define IGP01E1000_GMII_SPD 0x0020 /* Enable SPD */ ++/** ++ * e1000_write_phy_reg_hv - Write HV PHY 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 writes the data to PHY register ++ * at the offset. Release any acquired semaphores before exiting. ++ **/ ++s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) ++{ ++ s32 ret_val; ++ u16 page = BM_PHY_REG_PAGE(offset); ++ u16 reg = BM_PHY_REG_NUM(offset); ++ bool in_slow_mode = false; ++ ++ /* Workaround failure in MDIO access while cable is disconnected */ ++ if ((hw->phy.type == e1000_phy_82577) && ++ !(er32(STATUS) & E1000_STATUS_LU)) { ++ ret_val = e1000_set_mdio_slow_mode_hv(hw, true); ++ if (ret_val) ++ goto out; + -+#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 */ ++ in_slow_mode = true; ++ } + -+#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 ++ /* Page 800 works differently than the rest so it has its own func */ ++ if (page == BM_WUC_PAGE) { ++ ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, ++ &data, false); ++ goto out; ++ } + -+#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 -+#define IGP01E1000_PSSR_MDIX 0x0008 -+#define IGP01E1000_PSSR_SPEED_MASK 0xC000 -+#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 ++ if (page > 0 && page < HV_INTC_FC_PAGE_START) { ++ ret_val = e1000_access_phy_debug_regs_hv(hw, offset, ++ &data, false); ++ 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 = hw->phy.ops.acquire(hw); ++ 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 ++ hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); + -+#define IGP03E1000_PHY_MISC_CTRL 0x1B -+#define IGP03E1000_PHY_MISC_DUPLEX_MANUAL_SET 0x1000 /* Manually Set Duplex */ ++ if (page == HV_INTC_FC_PAGE_START) ++ page = 0; + -+#define E1000_CABLE_LENGTH_UNDEFINED 0xFF ++ /* ++ * Workaround MDIO accesses being disabled after entering IEEE Power ++ * Down (whenever bit 11 of the PHY Control register is set) ++ */ ++ if ((hw->phy.type == e1000_phy_82578) && ++ (hw->phy.revision >= 1) && ++ (hw->phy.addr == 2) && ++ ((MAX_PHY_REG_ADDRESS & reg) == 0) && ++ (data & (1 << 11))) { ++ u16 data2 = 0x7EFF; ++ hw->phy.ops.release(hw); ++ ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3, ++ &data2, false); ++ 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 */ ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) ++ goto out; ++ } + -+#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 */ ++ if (reg > MAX_PHY_MULTI_PAGE_REG) { ++ if ((hw->phy.type != e1000_phy_82578) || ++ ((reg != I82578_ADDR_REG) && ++ (reg != I82578_ADDR_REG + 1))) { ++ u32 phy_addr = hw->phy.addr; + -+/* IFE PHY Extended Status Control */ -+#define IFE_PESC_POLARITY_REVERSED 0x0100 ++ hw->phy.addr = 1; + -+/* 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 ++ /* Page is shifted left, PHY expects (page x 32) */ ++ ret_val = e1000e_write_phy_reg_mdic(hw, ++ IGP01E1000_PHY_PAGE_SELECT, ++ (page << IGP_PAGE_SHIFT)); ++ if (ret_val) { ++ hw->phy.ops.release(hw); ++ goto out; ++ } ++ hw->phy.addr = phy_addr; ++ } ++ } + -+/* 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 */ ++ ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, ++ data); ++ hw->phy.ops.release(hw); + -+/* 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 */ ++out: ++ /* Revert to MDIO fast mode, if applicable */ ++ if ((hw->phy.type == e1000_phy_82577) && in_slow_mode) ++ ret_val = e1000_set_mdio_slow_mode_hv(hw, false); + -+#endif -diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_regs.h linux-2.6.22-10/drivers/net/e1000e/e1000_regs.h ---- linux-2.6.22-0/drivers/net/e1000e/e1000_regs.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/e1000_regs.h 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,310 @@ -+/******************************************************************************* ++ return ret_val; ++} + -+ Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++/** ++ * e1000_get_phy_addr_for_hv_page - Get PHY adrress based on page ++ * @page: page to be accessed ++ **/ ++static u32 e1000_get_phy_addr_for_hv_page(u32 page) ++{ ++ u32 phy_addr = 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. ++ if (page >= HV_INTC_FC_PAGE_START) ++ phy_addr = 1; + -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ return phy_addr; ++} ++ ++/** ++ * e1000_access_phy_debug_regs_hv - Read HV PHY vendor specific high registers ++ * @hw: pointer to the HW structure ++ * @offset: register offset to be read or written ++ * @data: pointer to the data to be read or written ++ * @read: determines if operation is read or written ++ * ++ * Acquires semaphore, if necessary, then reads the PHY register at offset ++ * and storing the retreived information in data. Release any acquired ++ * semaphores before exiting. Note that the procedure to read these regs ++ * uses the address port and data port to read/write. ++ **/ ++static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, ++ u16 *data, bool read) ++{ ++ s32 ret_val; ++ u32 addr_reg = 0; ++ u32 data_reg = 0; ++ u8 phy_acquired = 1; ++ ++ /* This takes care of the difference with desktop vs mobile phy */ ++ addr_reg = (hw->phy.type == e1000_phy_82578) ? ++ I82578_ADDR_REG : I82577_ADDR_REG; ++ data_reg = addr_reg + 1; ++ ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) { ++ e_dbg("Could not acquire PHY\n"); ++ phy_acquired = 0; ++ goto out; ++ } ++ ++ /* All operations in this function are phy address 2 */ ++ hw->phy.addr = 2; ++ ++ /* masking with 0x3F to remove the page from offset */ ++ ret_val = e1000e_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F); ++ if (ret_val) { ++ e_dbg("Could not write PHY the HV address register\n"); ++ goto out; ++ } ++ ++ /* Read or write the data value next */ ++ if (read) ++ ret_val = e1000e_read_phy_reg_mdic(hw, data_reg, data); ++ else ++ ret_val = e1000e_write_phy_reg_mdic(hw, data_reg, *data); ++ ++ if (ret_val) { ++ e_dbg("Could not read data value from HV data register\n"); ++ goto out; ++ } ++ ++out: ++ if (phy_acquired == 1) ++ hw->phy.ops.release(hw); ++ return ret_val; ++} ++ ++/** ++ * e1000_link_stall_workaround_hv - Si workaround ++ * @hw: pointer to the HW structure ++ * ++ * This function works around a Si bug where the link partner can get ++ * a link up indication before the PHY does. If small packets are sent ++ * by the link partner they can be placed in the packet buffer without ++ * being properly accounted for by the PHY and will stall preventing ++ * further packets from being received. The workaround is to clear the ++ * packet buffer after the PHY detects link up. ++ **/ ++s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw) ++{ ++ s32 ret_val = E1000_SUCCESS; ++ u16 data; ++ ++ if (hw->phy.type != e1000_phy_82578) ++ goto out; ++ ++ /* Do not apply workaround if in PHY loopback bit 14 set */ ++ e1e_rphy(hw, PHY_CONTROL, &data); ++ if (data & PHY_CONTROL_LB) ++ goto out; ++ ++ /* check if link is up and at 1Gbps */ ++ ret_val = e1e_rphy(hw, BM_CS_STATUS, &data); ++ if (ret_val) ++ goto out; ++ ++ data &= BM_CS_STATUS_LINK_UP | ++ BM_CS_STATUS_RESOLVED | ++ BM_CS_STATUS_SPEED_MASK; ++ ++ if (data != (BM_CS_STATUS_LINK_UP | ++ BM_CS_STATUS_RESOLVED | ++ BM_CS_STATUS_SPEED_1000)) ++ goto out; ++ ++ msleep(200); ++ ++ /* flush the packets in the fifo buffer */ ++ ret_val = e1e_wphy(hw, HV_MUX_DATA_CTRL, ++ HV_MUX_DATA_CTRL_GEN_TO_MAC | ++ HV_MUX_DATA_CTRL_FORCE_SPEED); ++ if (ret_val) ++ goto out; ++ ++ ret_val = e1e_wphy(hw, HV_MUX_DATA_CTRL, ++ HV_MUX_DATA_CTRL_GEN_TO_MAC); ++ ++out: ++ return ret_val; ++} ++ ++/** ++ * e1000_check_polarity_82577 - 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_82577(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ u16 data; ++ ++ ret_val = e1e_rphy(hw, I82577_PHY_STATUS_2, &data); ++ ++ if (!ret_val) ++ phy->cable_polarity = (data & I82577_PHY_STATUS2_REV_POLARITY) ++ ? e1000_rev_polarity_reversed ++ : e1000_rev_polarity_normal; ++ ++ return ret_val; ++} ++ ++/** ++ * e1000_phy_force_speed_duplex_82577 - Force speed/duplex for I82577 PHY ++ * @hw: pointer to the HW structure ++ * ++ * 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). ++ **/ ++s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ u16 phy_data; ++ bool link; ++ ++ ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data); ++ if (ret_val) ++ goto out; ++ ++ e1000e_phy_force_speed_duplex_setup(hw, &phy_data); ++ ++ ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data); ++ if (ret_val) ++ goto out; ++ ++ /* ++ * Clear Auto-Crossover to force MDI manually. 82577 requires MDI ++ * forced whenever speed and duplex are forced. ++ */ ++ ret_val = e1e_rphy(hw, I82577_PHY_CTRL_2, &phy_data); ++ if (ret_val) ++ goto out; ++ ++ phy_data &= ~I82577_PHY_CTRL2_AUTO_MDIX; ++ phy_data &= ~I82577_PHY_CTRL2_FORCE_MDI_MDIX; ++ ++ ret_val = e1e_wphy(hw, I82577_PHY_CTRL_2, phy_data); ++ if (ret_val) ++ goto out; ++ ++ e_dbg("I82577_PHY_CTRL_2: %X\n", phy_data); ++ ++ udelay(1); ++ ++ if (phy->autoneg_wait_to_complete) { ++ e_dbg("Waiting for forced speed/duplex link on 82577 phy\n"); ++ ++ ret_val = e1000e_phy_has_link_generic(hw, ++ PHY_FORCE_LIMIT, ++ 100000, ++ &link); ++ if (ret_val) ++ goto out; ++ ++ if (!link) ++ e_dbg("Link taking longer than expected.\n"); ++ ++ /* Try once more */ ++ ret_val = e1000e_phy_has_link_generic(hw, ++ PHY_FORCE_LIMIT, ++ 100000, ++ &link); ++ if (ret_val) ++ goto out; ++ } ++ ++out: ++ return ret_val; ++} ++ ++/** ++ * e1000_get_phy_info_82577 - Retrieve I82577 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_82577(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ u16 data; ++ bool link; ++ ++ ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); ++ if (ret_val) ++ goto out; ++ ++ if (!link) { ++ e_dbg("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_82577(hw); ++ if (ret_val) ++ goto out; ++ ++ ret_val = e1e_rphy(hw, I82577_PHY_STATUS_2, &data); ++ if (ret_val) ++ goto out; ++ ++ phy->is_mdix = (data & I82577_PHY_STATUS2_MDIX) ? true : false; ++ ++ if ((data & I82577_PHY_STATUS2_SPEED_MASK) == ++ I82577_PHY_STATUS2_SPEED_1000MBPS) { ++ ret_val = e1000_get_cable_length(hw); ++ if (ret_val) ++ goto out; ++ ++ ret_val = e1e_rphy(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_get_cable_length_82577 - Determine cable length for 82577 PHY ++ * @hw: pointer to the HW structure ++ * ++ * Reads the diagnostic status register and verifies result is valid before ++ * placing it in the phy_cable_length field. ++ **/ ++s32 e1000_get_cable_length_82577(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ u16 phy_data, length; ++ ++ ret_val = e1e_rphy(hw, I82577_PHY_DIAG_STATUS, &phy_data); ++ if (ret_val) ++ goto out; ++ ++ length = (phy_data & I82577_DSTATUS_CABLE_LENGTH) >> ++ I82577_DSTATUS_CABLE_LENGTH_SHIFT; ++ ++ if (length == E1000_CABLE_LENGTH_UNDEFINED) ++ ret_val = E1000_ERR_PHY; ++ ++ phy->cable_length = length; ++ ++out: ++ return ret_val; ++} +diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_phy.h linux-2.6.22-10/drivers/net/e1000e/e1000_phy.h +--- linux-2.6.22-0/drivers/net/e1000e/e1000_phy.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.22-10/drivers/net/e1000e/e1000_phy.h 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,238 @@ ++/******************************************************************************* ++ ++ Intel PRO/1000 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. + @@ -15056,48 +14997,287 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_regs.h linux-2.6.22-10/driver + +*******************************************************************************/ + -+#ifndef _E1000_REGS_H_ -+#define _E1000_REGS_H_ ++#ifndef _E1000_PHY_H_ ++#define _E1000_PHY_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_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_IVAR 0x000E4 /* Interrupt Vector Allocation Register - RW */ -+#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_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 */ ++void e1000_init_phy_ops_generic(struct e1000_hw *hw); ++s32 e1000e_check_downshift(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 e1000e_check_reset_block_generic(struct e1000_hw *hw); ++s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw); ++s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw); ++s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw); ++s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw); ++s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw); ++s32 e1000e_get_cable_length_m88(struct e1000_hw *hw); ++s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw); ++s32 e1000e_get_cfg_done(struct e1000_hw *hw); ++s32 e1000e_get_phy_id(struct e1000_hw *hw); ++s32 e1000e_get_phy_info_igp(struct e1000_hw *hw); ++s32 e1000e_get_phy_info_m88(struct e1000_hw *hw); ++s32 e1000e_phy_sw_reset(struct e1000_hw *hw); ++void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); ++s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw); ++s32 e1000e_phy_reset_dsp(struct e1000_hw *hw); ++s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active); ++s32 e1000e_setup_copper_link(struct e1000_hw *hw); ++s32 e1000_wait_autoneg(struct e1000_hw *hw); ++s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000_phy_reset_dsp(struct e1000_hw *hw); ++s32 e1000e_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 e1000e_get_phy_type_from_id(u32 phy_id); ++s32 e1000e_determine_phy_address(struct e1000_hw *hw); ++s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data); ++void e1000_power_up_phy_copper(struct e1000_hw *hw); ++void e1000_power_down_phy_copper(struct e1000_hw *hw); ++s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow); ++s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw); ++s32 e1000_copper_link_setup_82577(struct e1000_hw *hw); ++s32 e1000_check_polarity_82577(struct e1000_hw *hw); ++s32 e1000_get_phy_info_82577(struct e1000_hw *hw); ++s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw); ++s32 e1000_get_cable_length_82577(struct e1000_hw *hw); ++ ++#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 ++ ++/* BM/HV Specific Registers */ ++#define BM_PORT_CTRL_PAGE 769 ++#define BM_PCIE_PAGE 770 ++#define BM_WUC_PAGE 800 ++#define BM_WUC_ADDRESS_OPCODE 0x11 ++#define BM_WUC_DATA_OPCODE 0x12 ++#define BM_WUC_ENABLE_PAGE BM_PORT_CTRL_PAGE ++#define BM_WUC_ENABLE_REG 17 ++#define BM_WUC_ENABLE_BIT (1 << 2) ++#define BM_WUC_HOST_WU_BIT (1 << 4) ++ ++#define PHY_UPPER_SHIFT 21 ++#define BM_PHY_REG(page, reg) \ ++ (((reg) & MAX_PHY_REG_ADDRESS) |\ ++ (((page) & 0xFFFF) << PHY_PAGE_SHIFT) |\ ++ (((reg) & ~MAX_PHY_REG_ADDRESS) << (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT))) ++#define BM_PHY_REG_PAGE(offset) \ ++ ((u16)(((offset) >> PHY_PAGE_SHIFT) & 0xFFFF)) ++#define BM_PHY_REG_NUM(offset) \ ++ ((u16)(((offset) & MAX_PHY_REG_ADDRESS) |\ ++ (((offset) >> (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)) &\ ++ ~MAX_PHY_REG_ADDRESS))) ++ ++#define HV_INTC_FC_PAGE_START 768 ++#define I82578_ADDR_REG 29 ++#define I82577_ADDR_REG 16 ++#define I82577_CFG_REG 22 ++#define I82577_CFG_ASSERT_CRS_ON_TX (1 << 15) ++#define I82577_CFG_ENABLE_DOWNSHIFT (3 << 10) /* auto downshift 100/10 */ ++#define I82577_CTRL_REG 23 ++#define I82577_CTRL_DOWNSHIFT_MASK (7 << 10) ++ ++/* 82577 specific PHY registers */ ++#define I82577_PHY_CTRL_2 18 ++#define I82577_PHY_LBK_CTRL 19 ++#define I82577_PHY_STATUS_2 26 ++#define I82577_PHY_DIAG_STATUS 31 ++ ++/* I82577 PHY Status 2 */ ++#define I82577_PHY_STATUS2_REV_POLARITY 0x0400 ++#define I82577_PHY_STATUS2_MDIX 0x0800 ++#define I82577_PHY_STATUS2_SPEED_MASK 0x0300 ++#define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200 ++#define I82577_PHY_STATUS2_SPEED_100MBPS 0x0100 ++ ++/* I82577 PHY Control 2 */ ++#define I82577_PHY_CTRL2_AUTO_MDIX 0x0400 ++#define I82577_PHY_CTRL2_FORCE_MDI_MDIX 0x0200 ++ ++/* I82577 PHY Diagnostics Status */ ++#define I82577_DSTATUS_CABLE_LENGTH 0x03FC ++#define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2 ++ ++/* BM PHY Copper Specific Control 1 */ ++#define BM_CS_CTRL1 16 ++#define BM_CS_CTRL1_ENERGY_DETECT 0x0300 /* Enable Energy Detect */ ++ ++/* BM PHY Copper Specific Status */ ++#define BM_CS_STATUS 17 ++#define BM_CS_STATUS_ENERGY_DETECT 0x0010 /* Energy Detect Status */ ++#define BM_CS_STATUS_LINK_UP 0x0400 ++#define BM_CS_STATUS_RESOLVED 0x0800 ++#define BM_CS_STATUS_SPEED_MASK 0xC000 ++#define BM_CS_STATUS_SPEED_1000 0x8000 ++ ++#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 E1000_KMRNCTRLSTA_K1_CONFIG 0x7 ++#define E1000_KMRNCTRLSTA_K1_ENABLE 0x140E ++#define E1000_KMRNCTRLSTA_K1_DISABLE 0x1400 ++ ++#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 +diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_regs.h linux-2.6.22-10/drivers/net/e1000e/e1000_regs.h +--- linux-2.6.22-0/drivers/net/e1000e/e1000_regs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.22-10/drivers/net/e1000e/e1000_regs.h 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,338 @@ ++/******************************************************************************* ++ ++ Intel PRO/1000 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 ++ ++*******************************************************************************/ ++ ++#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_IVAR 0x000E4 /* Interrupt Vector Allocation Register - RW */ ++#define E1000_SVCR 0x000F0 ++#define E1000_SVT 0x000F4 ++#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_PBA_ECC 0x01100 /* PBA ECC Register */ ++#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 */ @@ -15116,7 +15296,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_regs.h linux-2.6.22-10/driver +#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_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 */ @@ -15130,6 +15309,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_regs.h linux-2.6.22-10/driver +#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_RXCTL(_n) (0x0C014 + (0x40 * (_n))) ++#define E1000_RQDPC(_n) (0x0C030 + (0x40 * (_n))) +#define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */ +#define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */ +/* @@ -15140,31 +15321,48 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_regs.h linux-2.6.22-10/driver + * 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_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_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_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)) @@ -15244,14 +15442,19 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_regs.h linux-2.6.22-10/driver +#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_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 Minimum Threshold Count */ -+#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Descriptor Minimum Threshold 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 */ ++/* ++ * The CRC offset register is undocumented because it is for future use and ++ * may change in the future. ++ */ ++#define E1000_CRC_OFFSET 0x05F50 /* CRC Offset register */ + +#define E1000_PCS_CFG0 0x04200 /* PCS Configuration 0 - RW */ +#define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */ @@ -15281,7 +15484,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_regs.h linux-2.6.22-10/driver +#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */ +#define E1000_RA 0x05400 /* Receive Address - RW Array */ +#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */ -+#define E1000_VMD_CTL 0x0581C /* VMDq Control - RW */ ++#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 */ @@ -15299,2062 +15502,2803 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/e1000_regs.h linux-2.6.22-10/driver +#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */ +#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */ + -+#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 */ ++#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 */ ++#define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Msg Type - RW */ ++#define E1000_RXUDP 0x0B638 /* Time Sync Rx UDP Port - RW */ ++ ++#endif +diff -Nurp linux-2.6.22-0/drivers/net/e1000e/ethtool.c linux-2.6.22-10/drivers/net/e1000e/ethtool.c +--- linux-2.6.22-0/drivers/net/e1000e/ethtool.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.22-10/drivers/net/e1000e/ethtool.c 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,2033 @@ ++/******************************************************************************* ++ ++ Intel PRO/1000 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 ++ ++*******************************************************************************/ ++ ++/* ethtool support for e1000 */ ++ ++#include ++#ifdef SIOCETHTOOL ++#include ++#include ++#include ++ ++#include "e1000.h" ++#ifdef NETIF_F_HW_VLAN_TX ++#include ++#endif ++#ifdef ETHTOOL_OPS_COMPAT ++#include "kcompat_ethtool.c" ++#endif ++ ++struct e1000_stats { ++ char stat_string[ETH_GSTRING_LEN]; ++ int sizeof_stat; ++ int stat_offset; ++}; ++ ++#define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \ ++ offsetof(struct e1000_adapter, m) ++static const struct e1000_stats e1000_gstrings_stats[] = { ++ { "rx_packets", E1000_STAT(stats.gprc) }, ++ { "tx_packets", E1000_STAT(stats.gptc) }, ++ { "rx_bytes", E1000_STAT(stats.gorc) }, ++ { "tx_bytes", E1000_STAT(stats.gotc) }, ++ { "rx_broadcast", E1000_STAT(stats.bprc) }, ++ { "tx_broadcast", E1000_STAT(stats.bptc) }, ++ { "rx_multicast", E1000_STAT(stats.mprc) }, ++ { "tx_multicast", E1000_STAT(stats.mptc) }, ++ { "rx_errors", E1000_STAT(net_stats.rx_errors) }, ++ { "tx_errors", E1000_STAT(net_stats.tx_errors) }, ++#ifndef CONFIG_E1000E_NAPI ++ { "rx_dropped_backlog", E1000_STAT(rx_dropped_backlog) }, ++#endif ++ { "tx_dropped", E1000_STAT(net_stats.tx_dropped) }, ++ { "multicast", E1000_STAT(stats.mprc) }, ++ { "collisions", E1000_STAT(stats.colc) }, ++ { "rx_length_errors", E1000_STAT(net_stats.rx_length_errors) }, ++ { "rx_over_errors", E1000_STAT(net_stats.rx_over_errors) }, ++ { "rx_crc_errors", E1000_STAT(stats.crcerrs) }, ++ { "rx_frame_errors", E1000_STAT(net_stats.rx_frame_errors) }, ++ { "rx_no_buffer_count", E1000_STAT(stats.rnbc) }, ++ { "rx_missed_errors", E1000_STAT(stats.mpc) }, ++ { "tx_aborted_errors", E1000_STAT(stats.ecol) }, ++ { "tx_carrier_errors", E1000_STAT(stats.tncrs) }, ++ { "tx_fifo_errors", E1000_STAT(net_stats.tx_fifo_errors) }, ++ { "tx_heartbeat_errors", E1000_STAT(net_stats.tx_heartbeat_errors) }, ++ { "tx_window_errors", E1000_STAT(stats.latecol) }, ++ { "tx_abort_late_coll", E1000_STAT(stats.latecol) }, ++ { "tx_deferred_ok", E1000_STAT(stats.dc) }, ++ { "tx_single_coll_ok", E1000_STAT(stats.scc) }, ++ { "tx_multi_coll_ok", E1000_STAT(stats.mcc) }, ++ { "tx_timeout_count", E1000_STAT(tx_timeout_count) }, ++ { "tx_restart_queue", E1000_STAT(restart_queue) }, ++ { "rx_long_length_errors", E1000_STAT(stats.roc) }, ++ { "rx_short_length_errors", E1000_STAT(stats.ruc) }, ++ { "rx_align_errors", E1000_STAT(stats.algnerrc) }, ++ { "tx_tcp_seg_good", E1000_STAT(stats.tsctc) }, ++ { "tx_tcp_seg_failed", E1000_STAT(stats.tsctfc) }, ++ { "rx_flow_control_xon", E1000_STAT(stats.xonrxc) }, ++ { "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) }, ++ { "tx_flow_control_xon", E1000_STAT(stats.xontxc) }, ++ { "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) }, ++ { "rx_long_byte_count", E1000_STAT(stats.gorc) }, ++ { "rx_csum_offload_good", E1000_STAT(hw_csum_good) }, ++ { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }, ++ { "rx_header_split", E1000_STAT(rx_hdr_split) }, ++ { "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) }, ++ { "tx_smbus", E1000_STAT(stats.mgptc) }, ++ { "rx_smbus", E1000_STAT(stats.mgprc) }, ++ { "dropped_smbus", E1000_STAT(stats.mgpdc) }, ++ { "rx_dma_failed", E1000_STAT(rx_dma_failed) }, ++ { "tx_dma_failed", E1000_STAT(tx_dma_failed) }, ++}; ++ ++#define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats) ++#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN) ++static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = { ++ "Register test (offline)", "Eeprom test (offline)", ++ "Interrupt test (offline)", "Loopback test (offline)", ++ "Link test (on/offline)" ++}; ++#define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test) ++ ++static int e1000_get_settings(struct net_device *netdev, ++ struct ethtool_cmd *ecmd) ++{ ++ struct e1000_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); ++ if (hw->phy.type == e1000_phy_ife) ++ ecmd->supported &= ~SUPPORTED_1000baseT_Full; ++ 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; ++ ecmd->transceiver = XCVR_INTERNAL; ++ ++ } 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_EXTERNAL; ++ } ++ ++ status = er32(STATUS); ++ if (status & E1000_STATUS_LU) { ++ if (status & E1000_STATUS_SPEED_1000) ++ ecmd->speed = 1000; ++ else if (status & E1000_STATUS_SPEED_100) ++ ecmd->speed = 100; ++ else ++ ecmd->speed = 10; ++ ++ if (status & E1000_STATUS_FD) ++ 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 u32 e1000_get_link(struct net_device *netdev) ++{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ ++ return e1000_has_link(adapter); ++} ++ ++static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) ++{ ++ struct e1000_mac_info *mac = &adapter->hw.mac; ++ ++ 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)) { ++ e_err("Unsupported Speed/Duplex configuration\n"); ++ return -EINVAL; ++ } ++ ++ switch (spddplx) { ++ case SPEED_10 + DUPLEX_HALF: ++ mac->forced_speed_duplex = ADVERTISE_10_HALF; ++ break; ++ case SPEED_10 + DUPLEX_FULL: ++ mac->forced_speed_duplex = ADVERTISE_10_FULL; ++ break; ++ case SPEED_100 + DUPLEX_HALF: ++ mac->forced_speed_duplex = ADVERTISE_100_HALF; ++ break; ++ case SPEED_100 + DUPLEX_FULL: ++ mac->forced_speed_duplex = ADVERTISE_100_FULL; ++ break; ++ case SPEED_1000 + DUPLEX_FULL: ++ mac->autoneg = 1; ++ adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; ++ break; ++ case SPEED_1000 + DUPLEX_HALF: /* not supported */ ++ default: ++ e_err("Unsupported Speed/Duplex configuration\n"); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int e1000_set_settings(struct net_device *netdev, ++ struct ethtool_cmd *ecmd) ++{ ++ struct e1000_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)) { ++ e_err("Cannot change link characteristics when SoL/IDER is " ++ "active.\n"); ++ return -EINVAL; ++ } ++ ++ while (test_and_set_bit(__E1000_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) { ++ if (hw->mac.type == e1000_pchlan) { ++ /* Workaround h/w hang when Tx flow control ++ * enabled */ ++ hw->fc.requested_mode = e1000_fc_rx_pause; ++ } else { ++ hw->fc.requested_mode = e1000_fc_default; ++ } ++ } ++ } else { ++ if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) { ++ clear_bit(__E1000_RESETTING, &adapter->state); ++ return -EINVAL; ++ } ++ } ++ ++ /* reset the link */ ++ ++ if (netif_running(adapter->netdev)) { ++ e1000e_down(adapter); ++ e1000e_up(adapter); ++ } else { ++ e1000e_reset(adapter); ++ } ++ ++ clear_bit(__E1000_RESETTING, &adapter->state); ++ return 0; ++} ++ ++static void e1000_get_pauseparam(struct net_device *netdev, ++ struct ethtool_pauseparam *pause) ++{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ struct e1000_hw *hw = &adapter->hw; + -+/* 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 */ -+#define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Message Type - RW */ -+#define E1000_RXUDP 0x0B638 /* Time Sync Rx UDP Port - RW */ -+#endif -diff -Nurp linux-2.6.22-0/drivers/net/e1000e/ethtool.c linux-2.6.22-10/drivers/net/e1000e/ethtool.c ---- linux-2.6.22-0/drivers/net/e1000e/ethtool.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/ethtool.c 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,2005 @@ -+/******************************************************************************* ++ pause->autoneg = ++ (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); + -+ Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ 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; ++ } ++} + -+ 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 e1000_set_pauseparam(struct net_device *netdev, ++ struct ethtool_pauseparam *pause) ++{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ struct e1000_hw *hw = &adapter->hw; ++ int retval = 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. ++ adapter->fc_autoneg = pause->autoneg; + -+ 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. ++ while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) ++ msleep(1); + -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". ++ if (adapter->fc_autoneg == AUTONEG_ENABLE) { ++ if (hw->mac.type == e1000_pchlan) { ++ /* Workaround h/w hang when Tx flow control enabled */ ++ hw->fc.requested_mode = e1000_fc_rx_pause; ++ } else { ++ hw->fc.requested_mode = e1000_fc_default; ++ } ++ if (netif_running(adapter->netdev)) { ++ e1000e_down(adapter); ++ e1000e_up(adapter); ++ } else { ++ e1000e_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; + -+ Contact Information: -+ Linux NICS -+ e1000-devel Mailing List -+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ hw->fc.current_mode = hw->fc.requested_mode; + -+*******************************************************************************/ ++ retval = ((hw->phy.media_type == e1000_media_type_fiber) ? ++ hw->mac.ops.setup_link(hw) : e1000e_force_mac_fc(hw)); ++ } + -+/* ethtool support for e1000 */ ++ clear_bit(__E1000_RESETTING, &adapter->state); ++ return retval; ++} + -+#include -+#ifdef SIOCETHTOOL -+#include -+#include -+#include ++static u32 e1000_get_rx_csum(struct net_device *netdev) ++{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ return adapter->flags & FLAG_RX_CSUM_ENABLED; ++} + -+#include "e1000.h" ++static int e1000_set_rx_csum(struct net_device *netdev, u32 data) ++{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ ++ if (data) ++ adapter->flags |= FLAG_RX_CSUM_ENABLED; ++ else ++ adapter->flags &= ~FLAG_RX_CSUM_ENABLED; ++ ++ if (netif_running(netdev)) ++ e1000e_reinit_locked(adapter); ++ else ++ e1000e_reset(adapter); ++ return 0; ++} ++ ++static u32 e1000_get_tx_csum(struct net_device *netdev) ++{ ++ return ((netdev->features & NETIF_F_HW_CSUM) != 0); ++} ++ ++static int e1000_set_tx_csum(struct net_device *netdev, u32 data) ++{ ++ if (data) ++ netdev->features |= NETIF_F_HW_CSUM; ++ else ++ netdev->features &= ~NETIF_F_HW_CSUM; ++ ++ return 0; ++} ++ ++#ifdef NETIF_F_TSO ++static int e1000_set_tso(struct net_device *netdev, u32 data) ++{ ++ struct e1000_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 +#ifdef NETIF_F_HW_VLAN_TX -+#include ++ /* 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); ++ } ++#endif ++ } + -+#ifdef ETHTOOL_OPS_COMPAT -+#include "kcompat_ethtool.c" ++tso_out: ++ e_info("TSO is %s\n", data ? "Enabled" : "Disabled"); ++ adapter->flags |= FLAG_TSO_FORCE; ++ return 0; ++} +#endif + -+struct e1000_stats { -+ char stat_string[ETH_GSTRING_LEN]; -+ int sizeof_stat; -+ int stat_offset; -+}; ++static u32 e1000_get_msglevel(struct net_device *netdev) ++{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ return adapter->msg_enable; ++} + -+#define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \ -+ offsetof(struct e1000_adapter, m) -+static const struct e1000_stats e1000_gstrings_stats[] = { -+ { "rx_packets", E1000_STAT(stats.gprc) }, -+ { "tx_packets", E1000_STAT(stats.gptc) }, -+ { "rx_bytes", E1000_STAT(stats.gorc) }, -+ { "tx_bytes", E1000_STAT(stats.gotc) }, -+ { "rx_broadcast", E1000_STAT(stats.bprc) }, -+ { "tx_broadcast", E1000_STAT(stats.bptc) }, -+ { "rx_multicast", E1000_STAT(stats.mprc) }, -+ { "tx_multicast", E1000_STAT(stats.mptc) }, -+ { "rx_errors", E1000_STAT(net_stats.rx_errors) }, -+ { "tx_errors", E1000_STAT(net_stats.tx_errors) }, -+ { "tx_dropped", E1000_STAT(net_stats.tx_dropped) }, -+ { "multicast", E1000_STAT(stats.mprc) }, -+ { "collisions", E1000_STAT(stats.colc) }, -+ { "rx_length_errors", E1000_STAT(net_stats.rx_length_errors) }, -+ { "rx_over_errors", E1000_STAT(net_stats.rx_over_errors) }, -+ { "rx_crc_errors", E1000_STAT(stats.crcerrs) }, -+ { "rx_frame_errors", E1000_STAT(net_stats.rx_frame_errors) }, -+ { "rx_no_buffer_count", E1000_STAT(stats.rnbc) }, -+ { "rx_missed_errors", E1000_STAT(stats.mpc) }, -+ { "tx_aborted_errors", E1000_STAT(stats.ecol) }, -+ { "tx_carrier_errors", E1000_STAT(stats.tncrs) }, -+ { "tx_fifo_errors", E1000_STAT(net_stats.tx_fifo_errors) }, -+ { "tx_heartbeat_errors", E1000_STAT(net_stats.tx_heartbeat_errors) }, -+ { "tx_window_errors", E1000_STAT(stats.latecol) }, -+ { "tx_abort_late_coll", E1000_STAT(stats.latecol) }, -+ { "tx_deferred_ok", E1000_STAT(stats.dc) }, -+ { "tx_single_coll_ok", E1000_STAT(stats.scc) }, -+ { "tx_multi_coll_ok", E1000_STAT(stats.mcc) }, -+ { "tx_timeout_count", E1000_STAT(tx_timeout_count) }, -+ { "tx_restart_queue", E1000_STAT(restart_queue) }, -+ { "rx_long_length_errors", E1000_STAT(stats.roc) }, -+ { "rx_short_length_errors", E1000_STAT(stats.ruc) }, -+ { "rx_align_errors", E1000_STAT(stats.algnerrc) }, -+ { "tx_tcp_seg_good", E1000_STAT(stats.tsctc) }, -+ { "tx_tcp_seg_failed", E1000_STAT(stats.tsctfc) }, -+ { "rx_flow_control_xon", E1000_STAT(stats.xonrxc) }, -+ { "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) }, -+ { "tx_flow_control_xon", E1000_STAT(stats.xontxc) }, -+ { "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) }, -+ { "rx_long_byte_count", E1000_STAT(stats.gorc) }, -+ { "rx_csum_offload_good", E1000_STAT(hw_csum_good) }, -+ { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }, -+ { "rx_header_split", E1000_STAT(rx_hdr_split) }, -+ { "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) }, -+ { "tx_smbus", E1000_STAT(stats.mgptc) }, -+ { "rx_smbus", E1000_STAT(stats.mgprc) }, -+ { "dropped_smbus", E1000_STAT(stats.mgpdc) }, -+ { "rx_dma_failed", E1000_STAT(rx_dma_failed) }, -+ { "tx_dma_failed", E1000_STAT(tx_dma_failed) }, -+}; ++static void e1000_set_msglevel(struct net_device *netdev, u32 data) ++{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ adapter->msg_enable = data; ++} ++ ++static int e1000_get_regs_len(struct net_device *netdev) ++{ ++#define E1000_REGS_LEN 32 /* overestimate */ ++ return E1000_REGS_LEN * sizeof(u32); ++} ++ ++static void e1000_get_regs(struct net_device *netdev, ++ struct ethtool_regs *regs, void *p) ++{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ struct e1000_hw *hw = &adapter->hw; ++ u32 *regs_buff = p; ++ u16 phy_data; ++ u8 revision_id; ++ ++ memset(p, 0, E1000_REGS_LEN * sizeof(u32)); ++ ++ pci_read_config_byte(adapter->pdev, PCI_REVISION_ID, &revision_id); ++ ++ regs->version = (1 << 24) | (revision_id << 16) | adapter->pdev->device; + -+#define E1000_GLOBAL_STATS_LEN \ -+ sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats) -+#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN) -+static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = { -+ "Register test (offline)", "Eeprom test (offline)", -+ "Interrupt test (offline)", "Loopback test (offline)", -+ "Link test (on/offline)" -+}; -+#define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test) ++ regs_buff[0] = er32(CTRL); ++ regs_buff[1] = er32(STATUS); + -+static int e1000_get_settings(struct net_device *netdev, -+ struct ethtool_cmd *ecmd) ++ regs_buff[2] = er32(RCTL); ++ regs_buff[3] = er32(RDLEN(0)); ++ regs_buff[4] = er32(RDH(0)); ++ regs_buff[5] = er32(RDT(0)); ++ regs_buff[6] = er32(RDTR); ++ ++ regs_buff[7] = er32(TCTL); ++ regs_buff[8] = er32(TDLEN(0)); ++ regs_buff[9] = er32(TDH(0)); ++ regs_buff[10] = er32(TDT(0)); ++ regs_buff[11] = er32(TIDV); ++ ++ regs_buff[12] = adapter->hw.phy.type; /* PHY type (IGP=1, M88=0) */ ++ ++ /* ethtool doesn't use anything past this point, so all this ++ * code is likely legacy junk for apps that may or may not ++ * exist */ ++ if (hw->phy.type == e1000_phy_m88) { ++ e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); ++ regs_buff[13] = (u32)phy_data; /* cable length */ ++ regs_buff[14] = 0; /* Dummy (to align w/ IGP phy reg dump) */ ++ regs_buff[15] = 0; /* Dummy (to align w/ IGP phy reg dump) */ ++ regs_buff[16] = 0; /* Dummy (to align w/ IGP phy reg dump) */ ++ e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); ++ regs_buff[17] = (u32)phy_data; /* extended 10bt distance */ ++ regs_buff[18] = regs_buff[13]; /* cable polarity */ ++ regs_buff[19] = 0; /* Dummy (to align w/ IGP phy reg dump) */ ++ regs_buff[20] = regs_buff[17]; /* polarity correction */ ++ /* phy receive errors */ ++ regs_buff[22] = adapter->phy_stats.receive_errors; ++ regs_buff[23] = regs_buff[13]; /* mdix mode */ ++ } ++ regs_buff[21] = 0; /* was idle_errors */ ++ e1e_rphy(hw, PHY_1000T_STATUS, &phy_data); ++ regs_buff[24] = (u32)phy_data; /* phy local receiver status */ ++ regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ ++} ++ ++static int e1000_get_eeprom_len(struct net_device *netdev) ++{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ return adapter->hw.nvm.word_size * 2; ++} ++ ++static int e1000_get_eeprom(struct net_device *netdev, ++ struct ethtool_eeprom *eeprom, u8 *bytes) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; -+ u32 status; ++ u16 *eeprom_buff; ++ int first_word; ++ int last_word; ++ int ret_val = 0; ++ u16 i; + -+ if (hw->phy.media_type == e1000_media_type_copper) { ++ if (eeprom->len == 0) ++ return -EINVAL; + -+ ecmd->supported = (SUPPORTED_10baseT_Half | -+ SUPPORTED_10baseT_Full | -+ SUPPORTED_100baseT_Half | -+ SUPPORTED_100baseT_Full | -+ SUPPORTED_1000baseT_Full | -+ SUPPORTED_Autoneg | -+ SUPPORTED_TP); -+ if (hw->phy.type == e1000_phy_ife) -+ ecmd->supported &= ~SUPPORTED_1000baseT_Full; -+ ecmd->advertising = ADVERTISED_TP; ++ eeprom->magic = adapter->pdev->vendor | (adapter->pdev->device << 16); + -+ if (hw->mac.autoneg == 1) { -+ ecmd->advertising |= ADVERTISED_Autoneg; -+ /* the e1000 autoneg seems to match ethtool nicely */ -+ ecmd->advertising |= hw->phy.autoneg_advertised; -+ } ++ first_word = eeprom->offset >> 1; ++ last_word = (eeprom->offset + eeprom->len - 1) >> 1; + -+ ecmd->port = PORT_TP; -+ ecmd->phy_address = hw->phy.addr; -+ ecmd->transceiver = XCVR_INTERNAL; ++ eeprom_buff = kmalloc(sizeof(u16) * ++ (last_word - first_word + 1), GFP_KERNEL); ++ if (!eeprom_buff) ++ return -ENOMEM; + ++ if (hw->nvm.type == e1000_nvm_eeprom_spi) { ++ ret_val = e1000_read_nvm(hw, first_word, ++ last_word - first_word + 1, ++ eeprom_buff); + } 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_EXTERNAL; ++ 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; ++ } + } + -+ status = er32(STATUS); -+ if (status & E1000_STATUS_LU) { -+ if (status & E1000_STATUS_SPEED_1000) -+ ecmd->speed = 1000; -+ else if (status & E1000_STATUS_SPEED_100) -+ ecmd->speed = 100; -+ else -+ ecmd->speed = 10; -+ -+ if (status & E1000_STATUS_FD) -+ ecmd->duplex = DUPLEX_FULL; -+ else -+ ecmd->duplex = DUPLEX_HALF; ++ if (ret_val) { ++ /* a read error occurred, throw away the result */ ++ memset(eeprom_buff, 0xff, sizeof(eeprom_buff)); + } else { -+ ecmd->speed = -1; -+ ecmd->duplex = -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]); + } + -+ ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) || -+ hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE; -+ return 0; ++ memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len); ++ kfree(eeprom_buff); ++ ++ return ret_val; +} + -+static u32 e1000_get_link(struct net_device *netdev) ++static int e1000_set_eeprom(struct net_device *netdev, ++ struct ethtool_eeprom *eeprom, u8 *bytes) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; -+ u32 status; -+ -+ status = er32(STATUS); -+ return (status & E1000_STATUS_LU); -+} ++ u16 *eeprom_buff; ++ void *ptr; ++ int max_len; ++ int first_word; ++ int last_word; ++ int ret_val = 0; ++ u16 i; + -+static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) -+{ -+ struct e1000_mac_info *mac = &adapter->hw.mac; ++ if (eeprom->len == 0) ++ return -EOPNOTSUPP; + -+ mac->autoneg = 0; ++ if (eeprom->magic != (adapter->pdev->vendor | (adapter->pdev->device << 16))) ++ return -EFAULT; + -+ /* Fiber NICs only allow 1000 gbps Full duplex */ -+ if ((adapter->hw.phy.media_type == e1000_media_type_fiber) && -+ spddplx != (SPEED_1000 + DUPLEX_FULL)) { -+ e_err("Unsupported Speed/Duplex configuration\n"); -+ return -EINVAL; -+ } ++ max_len = hw->nvm.word_size * 2; + -+ switch (spddplx) { -+ case SPEED_10 + DUPLEX_HALF: -+ mac->forced_speed_duplex = ADVERTISE_10_HALF; -+ break; -+ case SPEED_10 + DUPLEX_FULL: -+ mac->forced_speed_duplex = ADVERTISE_10_FULL; -+ break; -+ case SPEED_100 + DUPLEX_HALF: -+ mac->forced_speed_duplex = ADVERTISE_100_HALF; -+ break; -+ case SPEED_100 + DUPLEX_FULL: -+ mac->forced_speed_duplex = ADVERTISE_100_FULL; -+ break; -+ case SPEED_1000 + DUPLEX_FULL: -+ mac->autoneg = 1; -+ adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; -+ break; -+ case SPEED_1000 + DUPLEX_HALF: /* not supported */ -+ default: -+ e_err("Unsupported Speed/Duplex configuration\n"); -+ return -EINVAL; ++ 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; ++ ++ 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++; + } -+ return 0; ++ 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 (ret_val) ++ goto out; ++ ++ /* 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(ptr, bytes, eeprom->len); ++ ++ for (i = 0; i < last_word - first_word + 1; i++) ++ eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]); ++ ++ ret_val = e1000_write_nvm(hw, first_word, ++ last_word - first_word + 1, eeprom_buff); ++ ++ if (ret_val) ++ goto out; ++ ++ /* ++ * Update the checksum over the first part of the EEPROM if needed ++ * and flush shadow RAM for applicable controllers ++ */ ++ if ((first_word <= NVM_CHECKSUM_REG) || ++ (hw->mac.type == e1000_82583) || ++ (hw->mac.type == e1000_82574) || ++ (hw->mac.type == e1000_82573)) ++ ret_val = e1000e_update_nvm_checksum(hw); ++ ++out: ++ kfree(eeprom_buff); ++ return ret_val; +} + -+static int e1000_set_settings(struct net_device *netdev, -+ struct ethtool_cmd *ecmd) ++static void e1000_get_drvinfo(struct net_device *netdev, ++ struct ethtool_drvinfo *drvinfo) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); -+ struct e1000_hw *hw = &adapter->hw; ++ char firmware_version[32]; ++ ++ strncpy(drvinfo->driver, e1000e_driver_name, 32); ++ strncpy(drvinfo->version, e1000e_driver_version, 32); + + /* -+ * When SoL/IDER sessions are active, autoneg/speed/duplex -+ * cannot be changed ++ * EEPROM image version # is reported as firmware version # for ++ * PCI-E controllers + */ -+ if (hw->phy.ops.check_reset_block && -+ hw->phy.ops.check_reset_block(&adapter->hw)) { -+ e_err("Cannot change link characteristics when SoL/IDER" -+ " is active.\n"); ++ sprintf(firmware_version, "%d.%d-%d", ++ (adapter->eeprom_vers & 0xF000) >> 12, ++ (adapter->eeprom_vers & 0x0FF0) >> 4, ++ (adapter->eeprom_vers & 0x000F)); ++ ++ strncpy(drvinfo->fw_version, firmware_version, 32); ++ strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); ++ drvinfo->regdump_len = e1000_get_regs_len(netdev); ++ drvinfo->eedump_len = e1000_get_eeprom_len(netdev); ++} ++ ++static void e1000_get_ringparam(struct net_device *netdev, ++ struct ethtool_ringparam *ring) ++{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ struct e1000_ring *tx_ring = adapter->tx_ring; ++ struct e1000_ring *rx_ring = adapter->rx_ring; ++ ++ ring->rx_max_pending = E1000_MAX_RXD; ++ ring->tx_max_pending = E1000_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; ++} ++ ++static int e1000_set_ringparam(struct net_device *netdev, ++ struct ethtool_ringparam *ring) ++{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ struct e1000_ring *tx_ring, *tx_old; ++ struct e1000_ring *rx_ring, *rx_old; ++ int err; ++ ++ if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) + return -EINVAL; -+ } + + while (test_and_set_bit(__E1000_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 (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) { -+ clear_bit(__E1000_RESETTING, &adapter->state); -+ return -EINVAL; -+ } -+ } ++ if (netif_running(adapter->netdev)) ++ e1000e_down(adapter); + -+ /* reset the link */ ++ tx_old = adapter->tx_ring; ++ rx_old = adapter->rx_ring; ++ ++ err = -ENOMEM; ++ tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); ++ if (!tx_ring) ++ goto err_alloc_tx; ++ /* ++ * use a memcpy to save any previously configured ++ * items like napi structs from having to be ++ * reinitialized ++ */ ++ memcpy(tx_ring, tx_old, sizeof(struct e1000_ring)); ++ ++ rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); ++ if (!rx_ring) ++ goto err_alloc_rx; ++ memcpy(rx_ring, rx_old, sizeof(struct e1000_ring)); ++ ++ adapter->tx_ring = tx_ring; ++ adapter->rx_ring = rx_ring; ++ ++ rx_ring->count = max(ring->rx_pending, (u32)E1000_MIN_RXD); ++ rx_ring->count = min(rx_ring->count, (u32)(E1000_MAX_RXD)); ++ rx_ring->count = ALIGN(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE); ++ ++ tx_ring->count = max(ring->tx_pending, (u32)E1000_MIN_TXD); ++ tx_ring->count = min(tx_ring->count, (u32)(E1000_MAX_TXD)); ++ tx_ring->count = ALIGN(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE); + + if (netif_running(adapter->netdev)) { -+ e1000_down(adapter); -+ e1000_up(adapter); -+ } else { -+ e1000_reset(adapter); ++ /* Try to get new resources before deleting old */ ++ err = e1000e_setup_rx_resources(adapter); ++ if (err) ++ goto err_setup_rx; ++ err = e1000e_setup_tx_resources(adapter); ++ if (err) ++ goto err_setup_tx; ++ ++ /* ++ * restore the old in order to free it, ++ * then add in the new ++ */ ++ adapter->rx_ring = rx_old; ++ adapter->tx_ring = tx_old; ++ e1000e_free_rx_resources(adapter); ++ e1000e_free_tx_resources(adapter); ++ kfree(tx_old); ++ kfree(rx_old); ++ adapter->rx_ring = rx_ring; ++ adapter->tx_ring = tx_ring; ++ err = e1000e_up(adapter); ++ if (err) ++ goto err_setup; + } + + clear_bit(__E1000_RESETTING, &adapter->state); + return 0; ++err_setup_tx: ++ e1000e_free_rx_resources(adapter); ++err_setup_rx: ++ adapter->rx_ring = rx_old; ++ adapter->tx_ring = tx_old; ++ kfree(rx_ring); ++err_alloc_rx: ++ kfree(tx_ring); ++err_alloc_tx: ++ e1000e_up(adapter); ++err_setup: ++ clear_bit(__E1000_RESETTING, &adapter->state); ++ return err; +} + -+static void e1000_get_pauseparam(struct net_device *netdev, -+ struct ethtool_pauseparam *pause) ++static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data, ++ int reg, int offset, u32 mask, u32 write) +{ -+ struct e1000_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; ++ u32 pat, val; ++ static const u32 test[] = ++ {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; ++ for (pat = 0; pat < ARRAY_SIZE(test); pat++) { ++ E1000_WRITE_REG_ARRAY(&adapter->hw, reg, offset, ++ (test[pat] & write)); ++ val = E1000_READ_REG_ARRAY(&adapter->hw, reg, offset); ++ if (val != (test[pat] & write & mask)) { ++ e_err("Register 0x%05X pattern test failed: got 0x%08X " ++ "expected 0x%08X\n", reg + offset, val, ++ (test[pat] & write & mask)); ++ *data = reg; ++ return 1; ++ } + } ++ return 0; +} + -+static int e1000_set_pauseparam(struct net_device *netdev, -+ struct ethtool_pauseparam *pause) ++static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data, ++ int reg, u32 mask, u32 write) +{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); -+ struct e1000_hw *hw = &adapter->hw; -+ int retval = 0; ++ u32 val; ++ __ew32(&adapter->hw, reg, write & mask); ++ val = __er32(&adapter->hw, reg); ++ if ((write & mask) != (val & mask)) { ++ e_err("Register 0x%05X set/check test failed: got 0x%08X " ++ "expected 0x%08X\n", reg, (val & mask), (write & mask)); ++ *data = reg; ++ return 1; ++ } ++ return 0; ++} ++#define REG_PATTERN_TEST_ARRAY(reg, offset, mask, write) \ ++ do { \ ++ if (reg_pattern_test(adapter, data, reg, offset, mask, write)) \ ++ return 1; \ ++ } while (0) ++#define REG_PATTERN_TEST(reg, mask, write) \ ++ REG_PATTERN_TEST_ARRAY(reg, 0, mask, write) + -+ adapter->fc_autoneg = pause->autoneg; ++#define REG_SET_AND_CHECK(reg, mask, write) \ ++ do { \ ++ if (reg_set_and_check(adapter, data, reg, mask, write)) \ ++ return 1; \ ++ } while (0) + -+ while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) -+ msleep(1); ++static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ struct e1000_mac_info *mac = &adapter->hw.mac; ++ u32 value; ++ u32 before; ++ u32 after; ++ u32 i; ++ u32 toggle; ++ u32 mask; + -+ 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; ++ /* ++ * The status register is Read Only, so a write should fail. ++ * Some bits that get toggled are ignored. ++ */ ++ switch (mac->type) { ++ /* there are several bits on newer hardware that are r/w */ ++ case e1000_82571: ++ case e1000_82572: ++ case e1000_80003es2lan: ++ toggle = 0x7FFFF3FF; ++ break; ++ default: ++ toggle = 0x7FFFF033; ++ break; ++ } + -+ hw->fc.original_type = hw->fc.type; ++ before = er32(STATUS); ++ value = (er32(STATUS) & toggle); ++ ew32(STATUS, toggle); ++ after = er32(STATUS) & toggle; ++ if (value != after) { ++ e_err("failed STATUS register test got: 0x%08X expected: " ++ "0x%08X\n", after, value); ++ *data = 1; ++ return 1; ++ } ++ /* restore previous status */ ++ ew32(STATUS, before); + -+ if (adapter->fc_autoneg == AUTONEG_ENABLE) { -+ hw->fc.type = e1000_fc_default; -+ if (netif_running(adapter->netdev)) { -+ e1000_down(adapter); -+ e1000_up(adapter); -+ } else { -+ e1000_reset(adapter); -+ } -+ } else { -+ retval = ((hw->phy.media_type == e1000_media_type_fiber) ? -+ hw->mac.ops.setup_link(hw) : -+ e1000_force_mac_fc_generic(hw)); ++ if (!(adapter->flags & FLAG_IS_ICH)) { ++ REG_PATTERN_TEST(E1000_FCAL, 0xFFFFFFFF, 0xFFFFFFFF); ++ REG_PATTERN_TEST(E1000_FCAH, 0x0000FFFF, 0xFFFFFFFF); ++ REG_PATTERN_TEST(E1000_FCT, 0x0000FFFF, 0xFFFFFFFF); ++ REG_PATTERN_TEST(E1000_VET, 0x0000FFFF, 0xFFFFFFFF); + } + -+ clear_bit(__E1000_RESETTING, &adapter->state); -+ return retval; -+} ++ REG_PATTERN_TEST(E1000_RDTR, 0x0000FFFF, 0xFFFFFFFF); ++ REG_PATTERN_TEST(E1000_RDBAH(0), 0xFFFFFFFF, 0xFFFFFFFF); ++ REG_PATTERN_TEST(E1000_RDLEN(0), 0x000FFF80, 0x000FFFFF); ++ REG_PATTERN_TEST(E1000_RDH(0), 0x0000FFFF, 0x0000FFFF); ++ REG_PATTERN_TEST(E1000_RDT(0), 0x0000FFFF, 0x0000FFFF); ++ REG_PATTERN_TEST(E1000_FCRTH, 0x0000FFF8, 0x0000FFF8); ++ REG_PATTERN_TEST(E1000_FCTTV, 0x0000FFFF, 0x0000FFFF); ++ REG_PATTERN_TEST(E1000_TIPG, 0x3FFFFFFF, 0x3FFFFFFF); ++ REG_PATTERN_TEST(E1000_TDBAH(0), 0xFFFFFFFF, 0xFFFFFFFF); ++ REG_PATTERN_TEST(E1000_TDLEN(0), 0x000FFF80, 0x000FFFFF); + -+static u32 e1000_get_rx_csum(struct net_device *netdev) -+{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); -+ return (adapter->flags & FLAG_RX_CSUM_ENABLED); -+} ++ REG_SET_AND_CHECK(E1000_RCTL, 0xFFFFFFFF, 0x00000000); + -+static int e1000_set_rx_csum(struct net_device *netdev, u32 data) -+{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); ++ before = ((adapter->flags & FLAG_IS_ICH) ? 0x06C3B33E : 0x06DFB3FE); ++ REG_SET_AND_CHECK(E1000_RCTL, before, 0x003FFFFB); ++ REG_SET_AND_CHECK(E1000_TCTL, 0xFFFFFFFF, 0x00000000); + -+ if (data) -+ adapter->flags |= FLAG_RX_CSUM_ENABLED; -+ else -+ adapter->flags &= ~FLAG_RX_CSUM_ENABLED; ++ REG_SET_AND_CHECK(E1000_RCTL, before, 0xFFFFFFFF); ++ REG_PATTERN_TEST(E1000_RDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF); ++ if (!(adapter->flags & FLAG_IS_ICH)) ++ REG_PATTERN_TEST(E1000_TXCW, 0xC000FFFF, 0x0000FFFF); ++ REG_PATTERN_TEST(E1000_TDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF); ++ REG_PATTERN_TEST(E1000_TIDV, 0x0000FFFF, 0x0000FFFF); ++ mask = 0x8003FFFF; ++ switch (mac->type) { ++ case e1000_ich10lan: ++ case e1000_pchlan: ++ mask |= (1 << 18); ++ break; ++ default: ++ break; ++ } ++ for (i = 0; i < mac->rar_entry_count; i++) ++ REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1), ++ mask, 0xFFFFFFFF); + -+ if (netif_running(netdev)) -+ e1000_reinit_locked(adapter); -+ else -+ e1000_reset(adapter); ++ for (i = 0; i < mac->mta_reg_count; i++) ++ REG_PATTERN_TEST_ARRAY(E1000_MTA, i, 0xFFFFFFFF, 0xFFFFFFFF); ++ ++ *data = 0; + return 0; +} + -+static u32 e1000_get_tx_csum(struct net_device *netdev) ++static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data) +{ -+ return ((netdev->features & NETIF_F_HW_CSUM) != 0); -+} ++ u16 temp; ++ u16 checksum = 0; ++ u16 i; + -+static int e1000_set_tx_csum(struct net_device *netdev, u32 data) -+{ -+ if (data) -+ netdev->features |= NETIF_F_HW_CSUM; -+ else -+ netdev->features &= ~NETIF_F_HW_CSUM; ++ *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; ++ return *data; ++ } ++ checksum += temp; ++ } ++ ++ /* If Checksum is not Correct return error else test passed */ ++ if ((checksum != (u16) NVM_SUM) && !(*data)) ++ *data = 2; + -+ return 0; ++ return *data; +} + -+#ifdef NETIF_F_TSO -+static int e1000_set_tso(struct net_device *netdev, u32 data) ++static irqreturn_t e1000_test_intr(int irq, void *data) +{ ++ struct net_device *netdev = (struct net_device *) data; + struct e1000_adapter *adapter = netdev_priv(netdev); -+ int i; -+ struct net_device *v_netdev; ++ struct e1000_hw *hw = &adapter->hw; + -+ 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; ++ adapter->test_icr |= er32(ICR); ++ ++ return IRQ_HANDLED; ++} ++ ++static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) ++{ ++ struct net_device *netdev = adapter->netdev; ++ struct e1000_hw *hw = &adapter->hw; ++ u32 mask; ++ u32 shared_int = 1; ++ u32 irq = adapter->pdev->irq; ++ int i; ++#ifdef CONFIG_E1000E_MSIX ++ int ret_val = 0; ++ int int_mode = E1000E_INT_MODE_LEGACY; +#endif -+#ifdef NETIF_F_HW_VLAN_TX -+ /* 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; ++ *data = 0; ++ ++#ifdef CONFIG_E1000E_MSIX ++ /* NOTE: we don't test MSI/MSI-X interrupts here, yet */ ++ if (adapter->int_mode == E1000E_INT_MODE_MSIX) { ++ int_mode = adapter->int_mode; ++ e1000e_reset_interrupt_capability(adapter); ++ adapter->int_mode = E1000E_INT_MODE_LEGACY; ++ e1000e_set_interrupt_capability(adapter); ++ } ++#else ++ /* NOTE: we don't test MSI interrupts here, yet */ +#endif -+ vlan_group_set_device(adapter->vlgrp, i, v_netdev); -+ } ++ /* Hook up test interrupt handler just for this test */ ++ if (!request_irq(irq, &e1000_test_intr, IRQF_PROBE_SHARED, netdev->name, ++ netdev)) { ++ shared_int = 0; ++ } else if (request_irq(irq, &e1000_test_intr, IRQF_SHARED, ++ netdev->name, netdev)) { ++ *data = 1; ++#ifdef CONFIG_E1000E_MSIX ++ ret_val = -1; ++ goto out; ++#else ++ return -1; +#endif + } -+ -+tso_out: -+ e_info("TSO is %s\n", data ? "Enabled" : "Disabled"); -+ adapter->flags |= FLAG_TSO_FORCE; -+ return 0; -+} -+#endif ++ e_info("testing %s interrupt\n", (shared_int ? "shared" : "unshared")); + -+static u32 e1000_get_msglevel(struct net_device *netdev) -+{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); -+ return adapter->msg_enable; -+} ++ /* Disable all the interrupts */ ++ ew32(IMC, 0xFFFFFFFF); ++ msleep(10); + -+static void e1000_set_msglevel(struct net_device *netdev, u32 data) -+{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); -+ adapter->msg_enable = data; -+} ++ /* Test each interrupt */ ++ for (i = 0; i < 10; i++) { ++ /* Interrupt to test */ ++ mask = 1 << i; + -+static int e1000_get_regs_len(struct net_device *netdev) -+{ -+#define E1000_REGS_LEN 32 /* overestimate */ -+ return E1000_REGS_LEN * sizeof(u32); -+} ++ if (adapter->flags & FLAG_IS_ICH) { ++ switch (mask) { ++ case E1000_ICR_RXSEQ: ++ continue; ++ case 0x00000100: ++ if (adapter->hw.mac.type == e1000_ich8lan || ++ adapter->hw.mac.type == e1000_ich9lan) ++ continue; ++ break; ++ default: ++ break; ++ } ++ } + -+static void e1000_get_regs(struct net_device *netdev, -+ struct ethtool_regs *regs, void *p) -+{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); -+ struct e1000_hw *hw = &adapter->hw; -+ u32 *regs_buff = p; -+ u16 phy_data; -+ u8 revision_id; ++ 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; ++ ew32(IMC, mask); ++ ew32(ICS, mask); ++ msleep(10); + -+ memset(p, 0, E1000_REGS_LEN * sizeof(u32)); ++ if (adapter->test_icr & mask) { ++ *data = 3; ++ break; ++ } ++ } + -+ pci_read_config_byte(adapter->pdev, PCI_REVISION_ID, &revision_id); ++ /* ++ * 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; ++ ew32(IMS, mask); ++ ew32(ICS, mask); ++ msleep(10); + -+ regs->version = (1 << 24) | (revision_id << 16) | adapter->pdev->device; ++ if (!(adapter->test_icr & mask)) { ++ *data = 4; ++ break; ++ } + -+ regs_buff[0] = er32(CTRL); -+ regs_buff[1] = er32(STATUS); ++ 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; ++ ew32(IMC, ~mask & 0x00007FFF); ++ ew32(ICS, ~mask & 0x00007FFF); ++ msleep(10); + -+ regs_buff[2] = er32(RCTL); -+ regs_buff[3] = er32(RDLEN(0)); -+ regs_buff[4] = er32(RDH(0)); -+ regs_buff[5] = er32(RDT(0)); -+ regs_buff[6] = er32(RDTR); ++ if (adapter->test_icr) { ++ *data = 5; ++ break; ++ } ++ } ++ } + -+ regs_buff[7] = er32(TCTL); -+ regs_buff[8] = er32(TDLEN(0)); -+ regs_buff[9] = er32(TDH(0)); -+ regs_buff[10] = er32(TDT(0)); -+ regs_buff[11] = er32(TIDV); ++ /* Disable all the interrupts */ ++ ew32(IMC, 0xFFFFFFFF); ++ msleep(10); + -+ regs_buff[12] = adapter->hw.phy.type; /* PHY type (IGP=1, M88=0) */ -+ if (hw->phy.type == e1000_phy_m88) { -+ hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); -+ regs_buff[13] = (u32)phy_data; /* cable length */ -+ regs_buff[14] = 0; /* Dummy (to align w/ IGP phy reg dump) */ -+ regs_buff[15] = 0; /* Dummy (to align w/ IGP phy reg dump) */ -+ regs_buff[16] = 0; /* Dummy (to align w/ IGP phy reg dump) */ -+ hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); -+ regs_buff[17] = (u32)phy_data; /* extended 10bt distance */ -+ regs_buff[18] = regs_buff[13]; /* cable polarity */ -+ regs_buff[19] = 0; /* Dummy (to align w/ IGP phy reg dump) */ -+ regs_buff[20] = regs_buff[17]; /* polarity correction */ -+ /* phy receive errors */ -+ regs_buff[22] = adapter->phy_stats.receive_errors; -+ regs_buff[23] = regs_buff[13]; /* mdix mode */ ++ /* Unhook test interrupt handler */ ++ free_irq(irq, netdev); ++ ++#ifdef CONFIG_E1000E_MSIX ++out: ++ if (int_mode == E1000E_INT_MODE_MSIX) { ++ e1000e_reset_interrupt_capability(adapter); ++ adapter->int_mode = int_mode; ++ e1000e_set_interrupt_capability(adapter); + } -+ regs_buff[21] = adapter->phy_stats.idle_errors; /* phy idle errors */ -+ hw->phy.ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); -+ regs_buff[24] = (u32)phy_data; /* phy local receiver status */ -+ regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ ++ ++ return ret_val; ++#else ++ return *data; ++#endif +} + -+static int e1000_get_eeprom_len(struct net_device *netdev) ++static void e1000_free_desc_rings(struct e1000_adapter *adapter) +{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); -+ return adapter->hw.nvm.word_size * 2; ++ struct e1000_ring *tx_ring = &adapter->test_tx_ring; ++ struct e1000_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++) { ++ if (tx_ring->buffer_info[i].dma) ++ pci_unmap_single(pdev, ++ tx_ring->buffer_info[i].dma, ++ tx_ring->buffer_info[i].length, ++ PCI_DMA_TODEVICE); ++ if (tx_ring->buffer_info[i].skb) ++ dev_kfree_skb(tx_ring->buffer_info[i].skb); ++ } ++ } ++ ++ if (rx_ring->desc && rx_ring->buffer_info) { ++ for (i = 0; i < rx_ring->count; i++) { ++ if (rx_ring->buffer_info[i].dma) ++ pci_unmap_single(pdev, ++ rx_ring->buffer_info[i].dma, ++ 2048, PCI_DMA_FROMDEVICE); ++ if (rx_ring->buffer_info[i].skb) ++ dev_kfree_skb(rx_ring->buffer_info[i].skb); ++ } ++ } ++ ++ if (tx_ring->desc) { ++ dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc, ++ tx_ring->dma); ++ tx_ring->desc = NULL; ++ } ++ if (rx_ring->desc) { ++ dma_free_coherent(&pdev->dev, 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; +} + -+static int e1000_get_eeprom(struct net_device *netdev, -+ struct ethtool_eeprom *eeprom, u8 *bytes) ++static int e1000_setup_desc_rings(struct e1000_adapter *adapter) +{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); ++ struct e1000_ring *tx_ring = &adapter->test_tx_ring; ++ struct e1000_ring *rx_ring = &adapter->test_rx_ring; ++ struct pci_dev *pdev = adapter->pdev; + struct e1000_hw *hw = &adapter->hw; -+ u16 *eeprom_buff; -+ int first_word; -+ int last_word; -+ int ret_val = 0; -+ u16 i; ++ u32 rctl; ++ int i; ++ int ret_val; + -+ if (eeprom->len == 0) -+ return -EINVAL; ++ /* Setup Tx descriptor ring and Tx buffers */ + -+ eeprom->magic = adapter->pdev->vendor | (adapter->pdev->device << 16); ++ if (!tx_ring->count) ++ tx_ring->count = E1000_DEFAULT_TXD; + -+ first_word = eeprom->offset >> 1; -+ last_word = (eeprom->offset + eeprom->len - 1) >> 1; ++ tx_ring->buffer_info = kcalloc(tx_ring->count, ++ sizeof(struct e1000_buffer), ++ GFP_KERNEL); ++ if (!(tx_ring->buffer_info)) { ++ ret_val = 1; ++ goto err_nomem; ++ } + -+ eeprom_buff = kmalloc(sizeof(u16) * -+ (last_word - first_word + 1), GFP_KERNEL); -+ if (!eeprom_buff) -+ return -ENOMEM; ++ tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc); ++ tx_ring->size = ALIGN(tx_ring->size, 4096); ++ tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size, ++ &tx_ring->dma, GFP_KERNEL); ++ if (!tx_ring->desc) { ++ ret_val = 2; ++ goto err_nomem; ++ } ++ tx_ring->next_to_use = 0; ++ tx_ring->next_to_clean = 0; + -+ if (hw->nvm.type == e1000_nvm_eeprom_spi) { -+ ret_val = hw->nvm.ops.read(hw, first_word, -+ last_word - first_word + 1, -+ eeprom_buff); -+ } else { -+ for (i = 0; i < last_word - first_word + 1; i++) { -+ ret_val = hw->nvm.ops.read(hw, first_word + i, 1, -+ &eeprom_buff[i]); -+ if (ret_val) -+ break; ++ ew32(TDBAL(0), ((u64) tx_ring->dma & 0x00000000FFFFFFFF)); ++ ew32(TDBAH(0), ((u64) tx_ring->dma >> 32)); ++ ew32(TDLEN(0), tx_ring->count * sizeof(struct e1000_tx_desc)); ++ ew32(TDH(0), 0); ++ ew32(TDT(0), 0); ++ ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN | E1000_TCTL_MULR | ++ E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT | ++ E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT); ++ ++ 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 skb_size = 1024; ++ ++ skb = alloc_skb(skb_size, GFP_KERNEL); ++ if (!skb) { ++ ret_val = 3; ++ goto err_nomem; ++ } ++ skb_put(skb, 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); ++ if (pci_dma_mapping_error(pdev, tx_ring->buffer_info[i].dma)) { ++ ret_val = 4; ++ goto err_nomem; + } ++ 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; + } + -+ /* 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]); ++ /* Setup Rx descriptor ring and Rx buffers */ + -+ memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len); -+ kfree(eeprom_buff); ++ if (!rx_ring->count) ++ rx_ring->count = E1000_DEFAULT_RXD; + -+ return ret_val; -+} ++ rx_ring->buffer_info = kcalloc(rx_ring->count, ++ sizeof(struct e1000_buffer), ++ GFP_KERNEL); ++ if (!(rx_ring->buffer_info)) { ++ ret_val = 5; ++ goto err_nomem; ++ } + -+static int e1000_set_eeprom(struct net_device *netdev, -+ struct ethtool_eeprom *eeprom, u8 *bytes) -+{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); -+ struct e1000_hw *hw = &adapter->hw; -+ u16 *eeprom_buff; -+ void *ptr; -+ int max_len; -+ int first_word; -+ int last_word; -+ int ret_val = 0; -+ u16 i; ++ rx_ring->size = rx_ring->count * sizeof(struct e1000_rx_desc); ++ rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size, ++ &rx_ring->dma, GFP_KERNEL); ++ if (!rx_ring->desc) { ++ ret_val = 6; ++ goto err_nomem; ++ } ++ rx_ring->next_to_use = 0; ++ rx_ring->next_to_clean = 0; + -+ if (eeprom->len == 0) -+ return -EOPNOTSUPP; ++ rctl = er32(RCTL); ++ ew32(RCTL, rctl & ~E1000_RCTL_EN); ++ ew32(RDBAL(0), ((u64) rx_ring->dma & 0xFFFFFFFF)); ++ ew32(RDBAH(0), ((u64) rx_ring->dma >> 32)); ++ ew32(RDLEN(0), rx_ring->size); ++ ew32(RDH(0), 0); ++ ew32(RDT(0), 0); ++ rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 | ++ E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_LPE | ++ E1000_RCTL_SBP | E1000_RCTL_SECRC | ++ E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | ++ (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); ++ ew32(RCTL, rctl); + -+ if (eeprom->magic != (adapter->pdev->vendor | (adapter->pdev->device << 16))) -+ return -EFAULT; ++ for (i = 0; i < rx_ring->count; i++) { ++ struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rx_ring, i); ++ struct sk_buff *skb; + -+ if (adapter->flags2 & FLAG2_READ_ONLY_NVM) -+ return -EINVAL; ++ skb = alloc_skb(2048 + NET_IP_ALIGN, GFP_KERNEL); ++ if (!skb) { ++ ret_val = 7; ++ 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, 2048, ++ PCI_DMA_FROMDEVICE); ++ if (pci_dma_mapping_error(pdev, rx_ring->buffer_info[i].dma)) { ++ ret_val = 8; ++ goto err_nomem; ++ } ++ rx_desc->buffer_addr = ++ cpu_to_le64(rx_ring->buffer_info[i].dma); ++ memset(skb->data, 0x00, skb->len); ++ } + -+ max_len = hw->nvm.word_size * 2; ++ return 0; + -+ 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; ++err_nomem: ++ e1000_free_desc_rings(adapter); ++ return ret_val; ++} + -+ ptr = (void *)eeprom_buff; ++static void e1000_phy_disable_receiver(struct e1000_adapter *adapter) ++{ ++ /* Write out to PHY registers 29 and 30 to disable the Receiver. */ ++ e1e_wphy(&adapter->hw, 29, 0x001F); ++ e1e_wphy(&adapter->hw, 30, 0x8FFC); ++ e1e_wphy(&adapter->hw, 29, 0x001A); ++ e1e_wphy(&adapter->hw, 30, 0x8FF0); ++} + -+ 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 = hw->nvm.ops.read(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 = hw->nvm.ops.read(hw, last_word, 1, -+ &eeprom_buff[last_word - first_word]); ++static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 ctrl_reg = 0; ++ u32 stat_reg = 0; ++ u16 phy_reg = 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]); ++ hw->mac.autoneg = 0; + -+ memcpy(ptr, bytes, eeprom->len); ++ if (hw->phy.type == e1000_phy_m88) { ++ /* Auto-MDI/MDIX Off */ ++ e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); ++ /* reset to update Auto-MDI/MDIX */ ++ e1e_wphy(hw, PHY_CONTROL, 0x9140); ++ /* autoneg off */ ++ e1e_wphy(hw, PHY_CONTROL, 0x8140); ++ } else if (hw->phy.type == e1000_phy_gg82563) ++ e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC); + -+ for (i = 0; i < last_word - first_word + 1; i++) -+ eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]); ++ ctrl_reg = er32(CTRL); + -+ ret_val = hw->nvm.ops.write(hw, first_word, last_word - first_word + 1, -+ eeprom_buff); ++ switch (hw->phy.type) { ++ case e1000_phy_ife: ++ /* force 100, set loopback */ ++ e1e_wphy(hw, PHY_CONTROL, 0x6100); + -+ /* -+ * 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) || -+ (hw->mac.type == e1000_82574) || -+ (hw->mac.type == e1000_82573))) -+ hw->nvm.ops.update(hw); ++ /* Now set up the MAC to the same speed/duplex as the PHY. */ ++ 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_100 |/* Force Speed to 100 */ ++ E1000_CTRL_FD); /* Force Duplex to FULL */ ++ break; ++ case e1000_phy_bm: ++ /* Set Default MAC Interface speed to 1GB */ ++ e1e_rphy(hw, PHY_REG(2, 21), &phy_reg); ++ phy_reg &= ~0x0007; ++ phy_reg |= 0x006; ++ e1e_wphy(hw, PHY_REG(2, 21), phy_reg); ++ /* Assert SW reset for above settings to take effect */ ++ e1000e_commit_phy(hw); ++ mdelay(1); ++ /* Force Full Duplex */ ++ e1e_rphy(hw, PHY_REG(769, 16), &phy_reg); ++ e1e_wphy(hw, PHY_REG(769, 16), phy_reg | 0x000C); ++ /* Set Link Up (in force link) */ ++ e1e_rphy(hw, PHY_REG(776, 16), &phy_reg); ++ e1e_wphy(hw, PHY_REG(776, 16), phy_reg | 0x0040); ++ /* Force Link */ ++ e1e_rphy(hw, PHY_REG(769, 16), &phy_reg); ++ e1e_wphy(hw, PHY_REG(769, 16), phy_reg | 0x0040); ++ /* Set Early Link Enable */ ++ e1e_rphy(hw, PHY_REG(769, 20), &phy_reg); ++ e1e_wphy(hw, PHY_REG(769, 20), phy_reg | 0x0400); ++ /* fall through */ ++ default: ++ /* force 1000, set loopback */ ++ e1e_wphy(hw, PHY_CONTROL, 0x4140); ++ mdelay(250); + -+ kfree(eeprom_buff); -+ return ret_val; -+} ++ /* Now set up the MAC to the same speed/duplex as the PHY. */ ++ ctrl_reg = er32(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 */ + -+static void e1000_get_drvinfo(struct net_device *netdev, -+ struct ethtool_drvinfo *drvinfo) -+{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); -+ struct e1000_hw *hw = &adapter->hw; -+ char firmware_version[32]; -+ u16 eeprom_data; ++ if (adapter->flags & FLAG_IS_ICH) ++ ctrl_reg |= E1000_CTRL_SLU; /* Set Link Up */ ++ } ++ ++ 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 = er32(STATUS); ++ if ((stat_reg & E1000_STATUS_FD) == 0) ++ ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU); ++ } + -+ strncpy(drvinfo->driver, e1000e_driver_name, 32); -+ strncpy(drvinfo->version, e1000e_driver_version, 32); ++ ew32(CTRL, ctrl_reg); + + /* -+ * EEPROM image version # is reported as firmware version # for -+ * PCI-E controllers ++ * 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. + */ -+ hw->nvm.ops.read(&adapter->hw, 5, 1, &eeprom_data); -+ sprintf(firmware_version, "%d.%d-%d", -+ (eeprom_data & 0xF000) >> 12, -+ (eeprom_data & 0x0FF0) >> 4, -+ eeprom_data & 0x000F); -+ -+ strncpy(drvinfo->fw_version, firmware_version, 32); -+ strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); -+ drvinfo->regdump_len = e1000_get_regs_len(netdev); -+ drvinfo->eedump_len = e1000_get_eeprom_len(netdev); -+} ++ if (hw->phy.type == e1000_phy_m88) ++ e1000_phy_disable_receiver(adapter); + -+static void e1000_get_ringparam(struct net_device *netdev, -+ struct ethtool_ringparam *ring) -+{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); -+ struct e1000_ring *tx_ring = adapter->tx_ring; -+ struct e1000_ring *rx_ring = adapter->rx_ring; ++ udelay(500); + -+ ring->rx_max_pending = E1000_MAX_RXD; -+ ring->tx_max_pending = E1000_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 0; +} + -+static int e1000_set_ringparam(struct net_device *netdev, -+ struct ethtool_ringparam *ring) ++static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter) +{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); -+ struct e1000_ring *tx_ring, *tx_old; -+ struct e1000_ring *rx_ring, *rx_old; -+ int err; -+ -+ if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) -+ return -EINVAL; -+ -+ while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) -+ msleep(1); -+ -+ if (netif_running(adapter->netdev)) -+ e1000_down(adapter); ++ struct e1000_hw *hw = &adapter->hw; ++ u32 ctrl = er32(CTRL); ++ int link = 0; + -+ tx_old = adapter->tx_ring; -+ rx_old = adapter->rx_ring; ++ /* special requirements for 82571/82572 fiber adapters */ + -+ err = -ENOMEM; -+ tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); -+ if (!tx_ring) -+ goto err_alloc_tx; + /* -+ * use a memcpy to save any previously configured -+ * items like napi structs from having to be -+ * reinitialized ++ * jump through hoops to make sure link is up because serdes ++ * link is hardwired up + */ -+ memcpy(tx_ring, tx_old, sizeof(struct e1000_ring)); -+ -+ rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); -+ if (!rx_ring) -+ goto err_alloc_rx; -+ memcpy(rx_ring, rx_old, sizeof(struct e1000_ring)); -+ -+ adapter->tx_ring = tx_ring; -+ adapter->rx_ring = rx_ring; -+ -+ rx_ring->count = max(ring->rx_pending, (u32)E1000_MIN_RXD); -+ rx_ring->count = min(rx_ring->count, (u32)(E1000_MAX_RXD)); -+ rx_ring->count = ALIGN(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE); ++ ctrl |= E1000_CTRL_SLU; ++ ew32(CTRL, ctrl); + -+ tx_ring->count = max(ring->tx_pending, (u32)E1000_MIN_TXD); -+ tx_ring->count = min(tx_ring->count, (u32)(E1000_MAX_TXD)); -+ tx_ring->count = ALIGN(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE); ++ /* disable autoneg */ ++ ctrl = er32(TXCW); ++ ctrl &= ~(1 << 31); ++ ew32(TXCW, ctrl); + -+ if (netif_running(adapter->netdev)) { -+ /* Try to get new resources before deleting old */ -+ err = e1000_setup_rx_resources(adapter); -+ if (err) -+ goto err_setup_rx; -+ err = e1000_setup_tx_resources(adapter); -+ if (err) -+ goto err_setup_tx; ++ link = (er32(STATUS) & E1000_STATUS_LU); + -+ /* -+ * restore the old in order to free it, -+ * then add in the new -+ */ -+ adapter->rx_ring = rx_old; -+ adapter->tx_ring = tx_old; -+ e1000_free_rx_resources(adapter); -+ e1000_free_tx_resources(adapter); -+ kfree(tx_old); -+ kfree(rx_old); -+ adapter->rx_ring = rx_ring; -+ adapter->tx_ring = tx_ring; -+ err = e1000_up(adapter); -+ if (err) -+ goto err_setup; ++ if (!link) { ++ /* set invert loss of signal */ ++ ctrl = er32(CTRL); ++ ctrl |= E1000_CTRL_ILOS; ++ ew32(CTRL, ctrl); + } + -+ clear_bit(__E1000_RESETTING, &adapter->state); -+ return 0; -+err_setup_tx: -+ e1000_free_rx_resources(adapter); -+err_setup_rx: -+ adapter->rx_ring = rx_old; -+ adapter->tx_ring = tx_old; -+ kfree(rx_ring); -+err_alloc_rx: -+ kfree(tx_ring); -+err_alloc_tx: -+ e1000_up(adapter); -+err_setup: -+ clear_bit(__E1000_RESETTING, &adapter->state); -+ return err; -+} -+ -+static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data, -+ int reg, int offset, u32 mask, u32 write) -+{ -+ u32 pat, val; -+ static const u32 test[] = -+ {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; -+ for (pat = 0; pat < ARRAY_SIZE(test); pat++) { -+ E1000_WRITE_REG_ARRAY(&adapter->hw, reg, offset, -+ (test[pat] & write)); -+ val = E1000_READ_REG_ARRAY(&adapter->hw, reg, offset); -+ if (val != (test[pat] & write & mask)) { -+ e_err("pattern test reg %04X failed: got " -+ "0x%08X expected 0x%08X\n", -+ reg + offset, -+ val, (test[pat] & write & mask)); -+ *data = reg; -+ return 1; -+ } -+ } -+ return 0; -+} ++ /* ++ * special write to serdes control register to enable SerDes analog ++ * loopback ++ */ ++#define E1000_SERDES_LB_ON 0x410 ++ ew32(SCTL, E1000_SERDES_LB_ON); ++ msleep(10); + -+static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data, -+ int reg, u32 mask, u32 write) -+{ -+ u32 val; -+ __ew32(&adapter->hw, reg, write & mask); -+ val = __er32(&adapter->hw, reg); -+ if ((write & mask) != (val & mask)) { -+ e_err("set/check reg %04X test failed: got 0x%08X" -+ "expected 0x%08X\n", reg, (val & mask), (write & mask)); -+ *data = reg; -+ return 1; -+ } + return 0; +} -+#define REG_PATTERN_TEST_ARRAY(reg, offset, mask, write) \ -+ do { \ -+ if (reg_pattern_test(adapter, data, reg, offset, mask, write)) \ -+ return 1; \ -+ } while (0) -+#define REG_PATTERN_TEST(reg, mask, write) \ -+ REG_PATTERN_TEST_ARRAY(reg, 0, mask, write) -+ -+#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 e1000_reg_test(struct e1000_adapter *adapter, u64 *data) ++/* only call this for fiber/serdes connections to es2lan */ ++static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; -+ struct e1000_mac_info *mac = &adapter->hw.mac; -+ u32 value; -+ u32 before; -+ u32 after; -+ u32 i; -+ u32 toggle; ++ u32 ctrlext = er32(CTRL_EXT); ++ u32 ctrl = er32(CTRL); + + /* -+ * The status register is Read Only, so a write should fail. -+ * Some bits that get toggled are ignored. ++ * save CTRL_EXT to restore later, reuse an empty variable (unused ++ * on mac_type 80003es2lan) + */ -+ switch (mac->type) { -+ /* there are several bits on newer hardware that are r/w */ -+ case e1000_82571: -+ case e1000_82572: -+ case e1000_80003es2lan: -+ toggle = 0x7FFFF3FF; -+ break; -+ case e1000_82573: -+ case e1000_82574: -+ case e1000_ich8lan: -+ case e1000_ich9lan: -+ case e1000_ich10lan: -+ toggle = 0x7FFFF033; -+ break; -+ default: -+ toggle = 0xFFFFF833; -+ break; -+ } -+ -+ before = er32(STATUS); -+ value = (er32(STATUS) & toggle); -+ ew32(STATUS, toggle); -+ after = er32(STATUS) & toggle; -+ if (value != after) { -+ e_err("failed STATUS register test got: " -+ "0x%08X expected: 0x%08X\n", after, value); -+ *data = 1; -+ return 1; -+ } -+ /* restore previous status */ -+ ew32(STATUS, before); -+ -+ if (!(adapter->flags & FLAG_IS_ICH)) { -+ REG_PATTERN_TEST(E1000_FCAL, 0xFFFFFFFF, 0xFFFFFFFF); -+ REG_PATTERN_TEST(E1000_FCAH, 0x0000FFFF, 0xFFFFFFFF); -+ REG_PATTERN_TEST(E1000_FCT, 0x0000FFFF, 0xFFFFFFFF); -+ REG_PATTERN_TEST(E1000_VET, 0x0000FFFF, 0xFFFFFFFF); -+ } -+ -+ REG_PATTERN_TEST(E1000_RDTR, 0x0000FFFF, 0xFFFFFFFF); -+ REG_PATTERN_TEST(E1000_RDBAH(0), 0xFFFFFFFF, 0xFFFFFFFF); -+ REG_PATTERN_TEST(E1000_RDLEN(0), 0x000FFF80, 0x000FFFFF); -+ REG_PATTERN_TEST(E1000_RDH(0), 0x0000FFFF, 0x0000FFFF); -+ REG_PATTERN_TEST(E1000_RDT(0), 0x0000FFFF, 0x0000FFFF); -+ REG_PATTERN_TEST(E1000_FCRTH, 0x0000FFF8, 0x0000FFF8); -+ REG_PATTERN_TEST(E1000_FCTTV, 0x0000FFFF, 0x0000FFFF); -+ REG_PATTERN_TEST(E1000_TIPG, 0x3FFFFFFF, 0x3FFFFFFF); -+ REG_PATTERN_TEST(E1000_TDBAH(0), 0xFFFFFFFF, 0xFFFFFFFF); -+ REG_PATTERN_TEST(E1000_TDLEN(0), 0x000FFF80, 0x000FFFFF); ++ adapter->tx_fifo_head = ctrlext; + -+ REG_SET_AND_CHECK(E1000_RCTL, 0xFFFFFFFF, 0x00000000); ++ /* clear the serdes mode bits, putting the device into mac loopback */ ++ ctrlext &= ~E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; ++ ew32(CTRL_EXT, ctrlext); + -+ before = ((adapter->flags & FLAG_IS_ICH) ? 0x06C3B33E : 0x06DFB3FE); -+ REG_SET_AND_CHECK(E1000_RCTL, before, 0x003FFFFB); -+ REG_SET_AND_CHECK(E1000_TCTL, 0xFFFFFFFF, 0x00000000); ++ /* force speed to 1000/FD, link up */ ++ ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); ++ ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | ++ E1000_CTRL_SPD_1000 | E1000_CTRL_FD); ++ ew32(CTRL, ctrl); + -+ REG_SET_AND_CHECK(E1000_RCTL, before, 0xFFFFFFFF); -+ REG_PATTERN_TEST(E1000_RDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF); -+ if (!(adapter->flags & FLAG_IS_ICH)) -+ REG_PATTERN_TEST(E1000_TXCW, 0xC000FFFF, 0x0000FFFF); -+ REG_PATTERN_TEST(E1000_TDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF); -+ REG_PATTERN_TEST(E1000_TIDV, 0x0000FFFF, 0x0000FFFF); -+ for (i = 0; i < mac->rar_entry_count; i++) -+ REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1), -+ ((mac->type == e1000_ich10lan) ? -+ 0x8007FFFF : 0x8003FFFF), -+ 0xFFFFFFFF); ++ /* set mac loopback */ ++ ctrl = er32(RCTL); ++ ctrl |= E1000_RCTL_LBM_MAC; ++ ew32(RCTL, ctrl); + -+ for (i = 0; i < mac->mta_reg_count; i++) -+ REG_PATTERN_TEST_ARRAY(E1000_MTA, i, 0xFFFFFFFF, 0xFFFFFFFF); ++ /* set testing mode parameters (no need to reset later) */ ++#define KMRNCTRLSTA_OPMODE (0x1F << 16) ++#define KMRNCTRLSTA_OPMODE_1GB_FD_GMII 0x0582 ++ ew32(KMRNCTRLSTA, ++ (KMRNCTRLSTA_OPMODE | KMRNCTRLSTA_OPMODE_1GB_FD_GMII)); + -+ *data = 0; + return 0; +} + -+static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data) ++static int e1000_setup_loopback_test(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; -+ u16 temp; -+ u16 checksum = 0; -+ u16 i; ++ u32 rctl; + -+ *data = 0; -+ /* Read and add up the contents of the EEPROM */ -+ for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { -+ if ((hw->nvm.ops.read(&adapter->hw, i, 1, &temp)) < 0) { -+ *data = 1; ++ if (hw->phy.media_type == e1000_media_type_fiber || ++ hw->phy.media_type == e1000_media_type_internal_serdes) { ++ switch (hw->mac.type) { ++ case e1000_80003es2lan: ++ return e1000_set_es2lan_mac_loopback(adapter); ++ break; ++ case e1000_82571: ++ case e1000_82572: ++ return e1000_set_82571_fiber_loopback(adapter); + break; ++ default: ++ rctl = er32(RCTL); ++ rctl |= E1000_RCTL_LBM_TCVR; ++ ew32(RCTL, rctl); ++ return 0; + } -+ checksum += temp; ++ } else if (hw->phy.media_type == e1000_media_type_copper) { ++ return e1000_integrated_phy_loopback(adapter); + } + -+ /* If Checksum is not Correct return error else test passed */ -+ if ((checksum != (u16) NVM_SUM) && !(*data)) -+ *data = 2; -+ -+ return *data; ++ return 7; +} + -+static irqreturn_t e1000_test_intr(int irq, void *data) ++static void e1000_loopback_cleanup(struct e1000_adapter *adapter) +{ -+ struct net_device *netdev = (struct net_device *) data; -+ struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; ++ u32 rctl; ++ u16 phy_reg; + -+ adapter->test_icr |= er32(ICR); ++ rctl = er32(RCTL); ++ rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); ++ ew32(RCTL, rctl); + -+ return IRQ_HANDLED; ++ switch (hw->mac.type) { ++ case e1000_80003es2lan: ++ if (hw->phy.media_type == e1000_media_type_fiber || ++ hw->phy.media_type == e1000_media_type_internal_serdes) { ++ /* restore CTRL_EXT, stealing space from tx_fifo_head */ ++ ew32(CTRL_EXT, adapter->tx_fifo_head); ++ adapter->tx_fifo_head = 0; ++ } ++ /* fall through */ ++ case e1000_82571: ++ case e1000_82572: ++ if (hw->phy.media_type == e1000_media_type_fiber || ++ hw->phy.media_type == e1000_media_type_internal_serdes) { ++#define E1000_SERDES_LB_OFF 0x400 ++ ew32(SCTL, E1000_SERDES_LB_OFF); ++ msleep(10); ++ break; ++ } ++ /* Fall Through */ ++ default: ++ hw->mac.autoneg = 1; ++ if (hw->phy.type == e1000_phy_gg82563) ++ e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x180); ++ e1e_rphy(hw, PHY_CONTROL, &phy_reg); ++ if (phy_reg & MII_CR_LOOPBACK) { ++ phy_reg &= ~MII_CR_LOOPBACK; ++ e1e_wphy(hw, PHY_CONTROL, phy_reg); ++ e1000e_commit_phy(hw); ++ } ++ break; ++ } +} + -+static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) ++static void e1000_create_lbtest_frame(struct sk_buff *skb, ++ unsigned int frame_size) +{ -+ struct net_device *netdev = adapter->netdev; -+ struct e1000_hw *hw = &adapter->hw; -+ u32 mask; -+ u32 shared_int = 1; -+ u32 irq = adapter->pdev->irq; -+ int i; -+#ifdef CONFIG_E1000E_MSIX -+ int ret_val = 0; -+ int int_mode = E1000E_INT_MODE_LEGACY; -+#endif -+ -+ *data = 0; -+ -+ /* NOTE: we don't test MSI/MSI-X interrupts here, yet */ -+#ifdef CONFIG_E1000E_MSIX -+ if (adapter->int_mode == E1000E_INT_MODE_MSIX) { -+ int_mode = adapter->int_mode; -+ e1000_reset_interrupt_capability(adapter); -+ adapter->int_mode = E1000E_INT_MODE_LEGACY; -+ e1000_set_interrupt_capability(adapter); -+ } -+#endif -+ /* Hook up test interrupt handler just for this test */ -+ if (!request_irq(irq, &e1000_test_intr, IRQF_PROBE_SHARED, netdev->name, -+ netdev)) { -+ shared_int = 0; -+ } else if (request_irq(irq, &e1000_test_intr, IRQF_SHARED, -+ netdev->name, netdev)) { -+ *data = 1; -+#ifdef CONFIG_E1000E_MSIX -+ ret_val = -1; -+ goto out; -+#else -+ return -1; -+#endif -+ } -+ e_info("testing %s interrupt\n", (shared_int ? "shared" : "unshared")); -+ -+ /* Disable all the interrupts */ -+ ew32(IMC, 0xFFFFFFFF); -+ msleep(10); ++ 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); ++} + -+ /* Test each interrupt */ -+ for (i = 0; i < 10; i++) { -+ /* Interrupt to test */ -+ mask = 1 << i; ++static int e1000_check_lbtest_frame(struct sk_buff *skb, ++ unsigned int frame_size) ++{ ++ 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; ++} + -+ if (adapter->flags & FLAG_IS_ICH) { -+ switch (mask) { -+ case E1000_ICR_RXSEQ: -+ continue; -+ case 0x00000100: -+ if (adapter->hw.mac.type == e1000_ich8lan || -+ adapter->hw.mac.type == e1000_ich9lan) -+ continue; -+ break; -+ default: -+ break; -+ } -+ } ++static int e1000_run_loopback_test(struct e1000_adapter *adapter) ++{ ++ struct e1000_ring *tx_ring = &adapter->test_tx_ring; ++ struct e1000_ring *rx_ring = &adapter->test_rx_ring; ++ struct pci_dev *pdev = adapter->pdev; ++ struct e1000_hw *hw = &adapter->hw; ++ int i, j, k, l; ++ int lc; ++ int good_cnt; ++ int ret_val = 0; ++ unsigned long time; + -+ 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; -+ ew32(IMC, mask); -+ ew32(ICS, mask); -+ msleep(10); ++ ew32(RDT(0), rx_ring->count - 1); + -+ if (adapter->test_icr & mask) { -+ *data = 3; -+ 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 ++ */ + -+ /* -+ * 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; -+ ew32(IMS, mask); -+ ew32(ICS, mask); -+ msleep(10); ++ if (rx_ring->count <= tx_ring->count) ++ lc = ((tx_ring->count / 64) * 2) + 1; ++ else ++ lc = ((rx_ring->count / 64) * 2) + 1; + -+ if (!(adapter->test_icr & mask)) { -+ *data = 4; -+ break; ++ k = 0; ++ l = 0; ++ for (j = 0; j <= lc; j++) { /* loop count loop */ ++ for (i = 0; i < 64; i++) { /* send the packets */ ++ e1000_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); ++ k++; ++ if (k == tx_ring->count) ++ k = 0; + } ++ ew32(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, 2048, ++ PCI_DMA_FROMDEVICE); + -+ if (!shared_int) { ++ ret_val = e1000_check_lbtest_frame( ++ rx_ring->buffer_info[l].skb, 1024); ++ if (!ret_val) ++ good_cnt++; ++ l++; ++ if (l == rx_ring->count) ++ l = 0; + /* -+ * 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. ++ * 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 + */ -+ adapter->test_icr = 0; -+ ew32(IMC, ~mask & 0x00007FFF); -+ ew32(ICS, ~mask & 0x00007FFF); -+ msleep(10); -+ -+ if (adapter->test_icr) { -+ *data = 5; -+ break; -+ } ++ } while ((good_cnt < 64) && !time_after(jiffies, time + 20)); ++ if (good_cnt != 64) { ++ ret_val = 13; /* ret_val is the same as mis-compare */ ++ break; + } -+ } -+ -+ /* Disable all the interrupts */ -+ ew32(IMC, 0xFFFFFFFF); -+ msleep(10); -+ -+ /* Unhook test interrupt handler */ -+ free_irq(irq, netdev); -+ -+#ifdef CONFIG_E1000E_MSIX -+out: -+ if (int_mode == E1000E_INT_MODE_MSIX) { -+ e1000_reset_interrupt_capability(adapter); -+ adapter->int_mode = int_mode; -+ e1000_set_interrupt_capability(adapter); -+ } -+ ++ if (jiffies >= (time + 20)) { ++ ret_val = 14; /* error code for time out error */ ++ break; ++ } ++ } /* end loop count loop */ + return ret_val; -+#else -+ return *data; -+#endif +} + -+static void e1000_free_desc_rings(struct e1000_adapter *adapter) ++static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data) +{ -+ struct e1000_ring *tx_ring = &adapter->test_tx_ring; -+ struct e1000_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++) { -+ if (tx_ring->buffer_info[i].dma) -+ pci_unmap_single(pdev, -+ tx_ring->buffer_info[i].dma, -+ tx_ring->buffer_info[i].length, -+ PCI_DMA_TODEVICE); -+ if (tx_ring->buffer_info[i].skb) -+ dev_kfree_skb(tx_ring->buffer_info[i].skb); -+ } ++ /* ++ * PHY loopback cannot be performed if SoL/IDER ++ * sessions are active ++ */ ++ if (e1000_check_reset_block(&adapter->hw)) { ++ e_err("Cannot do PHY loopback test when SoL/IDER is active.\n"); ++ *data = 0; ++ goto out; + } + -+ if (rx_ring->desc && rx_ring->buffer_info) { -+ for (i = 0; i < rx_ring->count; i++) { -+ if (rx_ring->buffer_info[i].dma) -+ pci_unmap_single(pdev, -+ rx_ring->buffer_info[i].dma, -+ 2048, PCI_DMA_FROMDEVICE); -+ if (rx_ring->buffer_info[i].skb) -+ dev_kfree_skb(rx_ring->buffer_info[i].skb); -+ } -+ } ++ *data = e1000_setup_desc_rings(adapter); ++ if (*data) ++ goto out; + -+ if (tx_ring->desc) { -+ dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc, -+ tx_ring->dma); -+ tx_ring->desc = NULL; -+ } -+ if (rx_ring->desc) { -+ dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc, -+ rx_ring->dma); -+ rx_ring->desc = NULL; -+ } ++ *data = e1000_setup_loopback_test(adapter); ++ if (*data) ++ goto err_loopback; + -+ kfree(tx_ring->buffer_info); -+ tx_ring->buffer_info = NULL; -+ kfree(rx_ring->buffer_info); -+ rx_ring->buffer_info = NULL; ++ *data = e1000_run_loopback_test(adapter); ++ e1000_loopback_cleanup(adapter); ++ ++err_loopback: ++ e1000_free_desc_rings(adapter); ++out: ++ return *data; +} + -+static int e1000_setup_desc_rings(struct e1000_adapter *adapter) ++static int e1000_link_test(struct e1000_adapter *adapter, u64 *data) +{ -+ struct e1000_ring *tx_ring = &adapter->test_tx_ring; -+ struct e1000_ring *rx_ring = &adapter->test_rx_ring; -+ struct pci_dev *pdev = adapter->pdev; + struct e1000_hw *hw = &adapter->hw; -+ u32 rctl; -+ int i; -+ int ret_val; + -+ /* Setup Tx descriptor ring and Tx buffers */ ++ *data = 0; ++ if (hw->phy.media_type == e1000_media_type_internal_serdes) { ++ int i = 0; ++ hw->mac.serdes_has_link = 0; + -+ if (!tx_ring->count) -+ tx_ring->count = E1000_DEFAULT_TXD; ++ /* ++ * On some blade server designs, link establishment ++ * could take as long as 2-3 minutes ++ */ ++ do { ++ hw->mac.ops.check_for_link(hw); ++ if (hw->mac.serdes_has_link) ++ return *data; ++ msleep(20); ++ } while (i++ < 3750); + -+ if (!(tx_ring->buffer_info = kcalloc(tx_ring->count, -+ sizeof(struct e1000_buffer), -+ GFP_KERNEL))) { -+ ret_val = 1; -+ goto err_nomem; -+ } ++ *data = 1; ++ } else { ++ hw->mac.ops.check_for_link(hw); ++ if (hw->mac.autoneg) ++ msleep(4000); + -+ tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc); -+ tx_ring->size = ALIGN(tx_ring->size, 4096); -+ tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size, -+ &tx_ring->dma, GFP_KERNEL); -+ if (!tx_ring->desc) { -+ ret_val = 2; -+ goto err_nomem; ++ if (!(er32(STATUS) & ++ E1000_STATUS_LU)) ++ *data = 1; + } -+ tx_ring->next_to_use = 0; -+ tx_ring->next_to_clean = 0; ++ return *data; ++} + -+ ew32(TDBAL(0), ((u64) tx_ring->dma & 0x00000000FFFFFFFF)); -+ ew32(TDBAH(0), ((u64) tx_ring->dma >> 32)); -+ ew32(TDLEN(0), tx_ring->count * sizeof(struct e1000_tx_desc)); -+ ew32(TDH(0), 0); -+ ew32(TDT(0), 0); -+ ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN | E1000_TCTL_MULR | -+ E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT | -+ E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT); ++static int e1000_get_self_test_count(struct net_device *netdev) ++{ ++ return E1000_TEST_LEN; ++} + -+ 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 skb_size = 1024; ++static int e1000_get_stats_count(struct net_device *netdev) ++{ ++ return E1000_STATS_LEN; ++} + -+ skb = alloc_skb(skb_size, GFP_KERNEL); -+ if (!skb) { -+ ret_val = 3; -+ goto err_nomem; -+ } -+ skb_put(skb, 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); -+ if (pci_dma_mapping_error(pdev, tx_ring->buffer_info[i].dma)) { -+ ret_val = 4; -+ goto err_nomem; -+ } -+ 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; -+ } ++static void e1000_diag_test(struct net_device *netdev, ++ struct ethtool_test *eth_test, u64 *data) ++{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ u16 autoneg_advertised; ++ u8 forced_speed_duplex; ++ u8 autoneg; ++ bool if_running = netif_running(netdev); + -+ /* Setup Rx descriptor ring and Rx buffers */ ++ set_bit(__E1000_TESTING, &adapter->state); ++ if (eth_test->flags == ETH_TEST_FL_OFFLINE) { ++ /* Offline tests */ + -+ if (!rx_ring->count) -+ rx_ring->count = E1000_DEFAULT_RXD; ++ /* 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 (!(rx_ring->buffer_info = kcalloc(rx_ring->count, -+ sizeof(struct e1000_buffer), -+ GFP_KERNEL))) { -+ ret_val = 5; -+ goto err_nomem; -+ } ++ e_info("offline testing starting\n"); + -+ rx_ring->size = rx_ring->count * sizeof(struct e1000_rx_desc); -+ rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size, -+ &rx_ring->dma, GFP_KERNEL); -+ if (!rx_ring->desc) { -+ ret_val = 6; -+ goto err_nomem; -+ } -+ rx_ring->next_to_use = 0; -+ rx_ring->next_to_clean = 0; ++ /* ++ * Link test performed before hardware reset so autoneg doesn't ++ * interfere with test result ++ */ ++ if (e1000_link_test(adapter, &data[4])) ++ eth_test->flags |= ETH_TEST_FL_FAILED; + -+ rctl = er32(RCTL); -+ ew32(RCTL, rctl & ~E1000_RCTL_EN); -+ ew32(RDBAL(0), ((u64) rx_ring->dma & 0xFFFFFFFF)); -+ ew32(RDBAH(0), ((u64) rx_ring->dma >> 32)); -+ ew32(RDLEN(0), rx_ring->size); -+ ew32(RDH(0), 0); -+ ew32(RDT(0), 0); -+ rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 | -+ E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_LPE | -+ E1000_RCTL_SBP | E1000_RCTL_SECRC | -+ E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | -+ (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); -+ ew32(RCTL, rctl); ++ if (if_running) ++ /* indicate we're in test mode */ ++ dev_close(netdev); ++ else ++ e1000e_reset(adapter); + -+ for (i = 0; i < rx_ring->count; i++) { -+ struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rx_ring, i); -+ struct sk_buff *skb; ++ if (e1000_reg_test(adapter, &data[0])) ++ eth_test->flags |= ETH_TEST_FL_FAILED; + -+ skb = alloc_skb(2048 + NET_IP_ALIGN, GFP_KERNEL); -+ if (!skb) { -+ ret_val = 7; -+ 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, 2048, -+ PCI_DMA_FROMDEVICE); -+ if (pci_dma_mapping_error(pdev, rx_ring->buffer_info[i].dma)) { -+ ret_val = 8; -+ goto err_nomem; -+ } -+ rx_desc->buffer_addr = -+ cpu_to_le64(rx_ring->buffer_info[i].dma); -+ memset(skb->data, 0x00, skb->len); -+ } ++ e1000e_reset(adapter); ++ if (e1000_eeprom_test(adapter, &data[1])) ++ eth_test->flags |= ETH_TEST_FL_FAILED; ++ ++ e1000e_reset(adapter); ++ if (e1000_intr_test(adapter, &data[2])) ++ eth_test->flags |= ETH_TEST_FL_FAILED; + -+ return 0; ++ e1000e_reset(adapter); ++ /* make sure the phy is powered up */ ++ e1000e_power_up_phy(adapter); ++ if (e1000_loopback_test(adapter, &data[3])) ++ eth_test->flags |= ETH_TEST_FL_FAILED; + -+err_nomem: -+ e1000_free_desc_rings(adapter); -+ return ret_val; -+} ++ /* 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; + -+static void e1000_phy_disable_receiver(struct e1000_adapter *adapter) -+{ -+ /* Write out to PHY registers 29 and 30 to disable the Receiver. */ -+ adapter->hw.phy.ops.write_reg(&adapter->hw, 29, 0x001F); -+ adapter->hw.phy.ops.write_reg(&adapter->hw, 30, 0x8FFC); -+ adapter->hw.phy.ops.write_reg(&adapter->hw, 29, 0x001A); -+ adapter->hw.phy.ops.write_reg(&adapter->hw, 30, 0x8FF0); ++ /* force this routine to wait until autoneg complete/timeout */ ++ adapter->hw.phy.autoneg_wait_to_complete = 1; ++ e1000e_reset(adapter); ++ adapter->hw.phy.autoneg_wait_to_complete = 0; ++ ++ clear_bit(__E1000_TESTING, &adapter->state); ++ if (if_running) ++ dev_open(netdev); ++ } else { ++ e_info("online testing starting\n"); ++ /* Online tests */ ++ if (e1000_link_test(adapter, &data[4])) ++ eth_test->flags |= ETH_TEST_FL_FAILED; ++ ++ /* Online tests aren't run; pass by default */ ++ data[0] = 0; ++ data[1] = 0; ++ data[2] = 0; ++ data[3] = 0; ++ ++ clear_bit(__E1000_TESTING, &adapter->state); ++ } ++ msleep_interruptible(4 * 1000); +} + -+static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) ++static void e1000_get_wol(struct net_device *netdev, ++ struct ethtool_wolinfo *wol) +{ -+ struct e1000_hw *hw = &adapter->hw; -+ u32 ctrl_reg = 0; -+ u32 stat_reg = 0; -+ u16 phy_reg = 0; ++ struct e1000_adapter *adapter = netdev_priv(netdev); + -+ hw->mac.autoneg = 0; ++ wol->supported = 0; ++ wol->wolopts = 0; + -+ if (hw->phy.type == e1000_phy_m88) { -+ /* Auto-MDI/MDIX Off */ -+ hw->phy.ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); -+ /* reset to update Auto-MDI/MDIX */ -+ hw->phy.ops.write_reg(hw, PHY_CONTROL, 0x9140); -+ /* autoneg off */ -+ hw->phy.ops.write_reg(hw, PHY_CONTROL, 0x8140); -+ } else if (hw->phy.type == e1000_phy_gg82563) -+ hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC); ++ if (!(adapter->flags & FLAG_HAS_WOL) || ++ !device_can_wakeup(&adapter->pdev->dev)) ++ return; + -+ ctrl_reg = er32(CTRL); ++ wol->supported = WAKE_UCAST | WAKE_MCAST | ++ WAKE_BCAST | WAKE_MAGIC | ++ WAKE_PHY | WAKE_ARP; + -+ switch (hw->phy.type) { -+ case e1000_phy_ife: -+ /* force 100, set loopback */ -+ hw->phy.ops.write_reg(hw, PHY_CONTROL, 0x6100); ++ /* apply any specific unsupported masks here */ ++ if (adapter->flags & FLAG_NO_WAKE_UCAST) { ++ wol->supported &= ~WAKE_UCAST; + -+ /* Now set up the MAC to the same speed/duplex as the PHY. */ -+ 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_100 |/* Force Speed to 100 */ -+ E1000_CTRL_FD); /* Force Duplex to FULL */ -+ break; -+ case e1000_phy_bm: -+ /* Set Default MAC Interface speed to 1GB */ -+ hw->phy.ops.read_reg(hw, PHY_REG(2, 21), &phy_reg); -+ phy_reg &= ~0x0007; -+ phy_reg |= 0x006; -+ hw->phy.ops.write_reg(hw, PHY_REG(2, 21), phy_reg); -+ /* Assert SW reset for above settings to take effect */ -+ hw->phy.ops.commit(hw); -+ mdelay(1); -+ /* Force Full Duplex */ -+ hw->phy.ops.read_reg(hw, PHY_REG(769, 16), &phy_reg); -+ hw->phy.ops.write_reg(hw, PHY_REG(769, 16), phy_reg | 0x000C); -+ /* Set Link Up (in force link) */ -+ hw->phy.ops.read_reg(hw, PHY_REG(776, 16), &phy_reg); -+ hw->phy.ops.write_reg(hw, PHY_REG(776, 16), phy_reg | 0x0040); -+ /* Force Link */ -+ hw->phy.ops.read_reg(hw, PHY_REG(769, 16), &phy_reg); -+ hw->phy.ops.write_reg(hw, PHY_REG(769, 16), phy_reg | 0x0040); -+ /* Set Early Link Enable */ -+ hw->phy.ops.read_reg(hw, PHY_REG(769, 20), &phy_reg); -+ hw->phy.ops.write_reg(hw, PHY_REG(769, 20), phy_reg | 0x0400); -+ /* fall through */ -+ default: -+ /* force 1000, set loopback */ -+ hw->phy.ops.write_reg(hw, PHY_CONTROL, 0x4140); -+ mdelay(250); ++ if (adapter->wol & E1000_WUFC_EX) ++ e_err("Interface does not support directed (unicast) " ++ "frame wake-up packets\n"); ++ } + -+ /* Now set up the MAC to the same speed/duplex as the PHY. */ -+ ctrl_reg = er32(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 */ ++ 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; ++ if (adapter->wol & E1000_WUFC_LNKC) ++ wol->wolopts |= WAKE_PHY; ++ if (adapter->wol & E1000_WUFC_ARP) ++ wol->wolopts |= WAKE_ARP; ++} + -+ if (adapter->flags & FLAG_IS_ICH) -+ ctrl_reg |= E1000_CTRL_SLU; /* Set Link Up */ -+ } ++static int e1000_set_wol(struct net_device *netdev, ++ struct ethtool_wolinfo *wol) ++{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); + -+ 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 = er32(STATUS); -+ if ((stat_reg & E1000_STATUS_FD) == 0) -+ ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU); -+ } ++ if (!(adapter->flags & FLAG_HAS_WOL) || ++ !device_can_wakeup(&adapter->pdev->dev) || ++ (wol->wolopts & ~(WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | ++ WAKE_MAGIC | WAKE_PHY | WAKE_ARP))) ++ return -EOPNOTSUPP; + -+ ew32(CTRL, ctrl_reg); ++ /* these settings will always override what we currently have */ ++ adapter->wol = 0; + -+ /* -+ * 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) -+ e1000_phy_disable_receiver(adapter); ++ 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; ++ if (wol->wolopts & WAKE_PHY) ++ adapter->wol |= E1000_WUFC_LNKC; ++ if (wol->wolopts & WAKE_ARP) ++ adapter->wol |= E1000_WUFC_ARP; + -+ udelay(500); ++ device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); + + return 0; +} + -+static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter) -+{ -+ struct e1000_hw *hw = &adapter->hw; -+ u32 ctrl = er32(CTRL); -+ int link = 0; -+ -+ /* special requirements for 82571/82572 fiber adapters */ -+ -+ /* -+ * jump through hoops to make sure link is up because serdes -+ * link is hardwired up -+ */ -+ ctrl |= E1000_CTRL_SLU; -+ ew32(CTRL, ctrl); ++/* toggle LED 4 times per second = 2 "blinks" per second */ ++#define E1000_ID_INTERVAL (HZ/4) + -+ /* disable autoneg */ -+ ctrl = er32(TXCW); -+ ctrl &= ~(1 << 31); -+ ew32(TXCW, ctrl); ++/* bit defines for adapter->led_status */ ++#define E1000_LED_ON 0 + -+ link = (er32(STATUS) & E1000_STATUS_LU); ++static void e1000e_led_blink_task(struct work_struct *work) ++{ ++ struct e1000_adapter *adapter = container_of(work, ++ struct e1000_adapter, led_blink_task); + -+ if (!link) { -+ /* set invert loss of signal */ -+ ctrl = er32(CTRL); -+ ctrl |= E1000_CTRL_ILOS; -+ ew32(CTRL, ctrl); -+ } ++ if (test_and_change_bit(E1000_LED_ON, &adapter->led_status)) ++ adapter->hw.mac.ops.led_off(&adapter->hw); ++ else ++ adapter->hw.mac.ops.led_on(&adapter->hw); ++} + -+ /* -+ * special write to serdes control register to enable SerDes analog -+ * loopback -+ */ -+#define E1000_SERDES_LB_ON 0x410 -+ ew32(SCTL, E1000_SERDES_LB_ON); -+ msleep(10); ++static void e1000_led_blink_callback(unsigned long data) ++{ ++ struct e1000_adapter *adapter = (struct e1000_adapter *) data; + -+ return 0; ++ schedule_work(&adapter->led_blink_task); ++ mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL); +} + -+/* only call this for fiber/serdes connections to es2lan */ -+static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter) ++static int e1000_phys_id(struct net_device *netdev, u32 data) +{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; -+ u32 ctrlext = er32(CTRL_EXT); -+ u32 ctrl = er32(CTRL); + -+ /* -+ * save CTRL_EXT to restore later, reuse an empty variable (unused -+ * on mac_type 80003es2lan) -+ */ -+ adapter->tx_fifo_head = ctrlext; ++ if (!data) ++ data = INT_MAX; + -+ /* clear the serdes mode bits, putting the device into mac loopback */ -+ ctrlext &= ~E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; -+ ew32(CTRL_EXT, ctrlext); ++ if ((hw->phy.type == e1000_phy_ife) || ++ (hw->mac.type == e1000_pchlan) || ++ (hw->mac.type == e1000_82583) || ++ (hw->mac.type == e1000_82574)) { ++ INIT_WORK(&adapter->led_blink_task, e1000e_led_blink_task); ++ if (!adapter->blink_timer.function) { ++ init_timer(&adapter->blink_timer); ++ adapter->blink_timer.function = ++ e1000_led_blink_callback; ++ adapter->blink_timer.data = (unsigned long) adapter; ++ } ++ mod_timer(&adapter->blink_timer, jiffies); ++ msleep_interruptible(data * 1000); ++ del_timer_sync(&adapter->blink_timer); ++ if (hw->phy.type == e1000_phy_ife) ++ e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, 0); ++ } else { ++ e1000e_blink_led(hw); ++ msleep_interruptible(data * 1000); ++ } + -+ /* force speed to 1000/FD, link up */ -+ ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); -+ ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | -+ E1000_CTRL_SPD_1000 | E1000_CTRL_FD); -+ ew32(CTRL, ctrl); ++ hw->mac.ops.led_off(hw); ++ clear_bit(E1000_LED_ON, &adapter->led_status); ++ hw->mac.ops.cleanup_led(hw); + -+ /* set mac loopback */ -+ ctrl = er32(RCTL); -+ ctrl |= E1000_RCTL_LBM_MAC; -+ ew32(RCTL, ctrl); ++ return 0; ++} + -+ /* set testing mode parameters (no need to reset later) */ -+#define KMRNCTRLSTA_OPMODE (0x1F << 16) -+#define KMRNCTRLSTA_OPMODE_1GB_FD_GMII 0x0582 -+ ew32(KMRNCTRLSTA, -+ (KMRNCTRLSTA_OPMODE | KMRNCTRLSTA_OPMODE_1GB_FD_GMII)); ++static int e1000_get_coalesce(struct net_device *netdev, ++ struct ethtool_coalesce *ec) ++{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ ++ if (adapter->itr_setting <= 3) ++ ec->rx_coalesce_usecs = adapter->itr_setting; ++ else ++ ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting; + + return 0; +} + -+static int e1000_setup_loopback_test(struct e1000_adapter *adapter) ++static int e1000_set_coalesce(struct net_device *netdev, ++ struct ethtool_coalesce *ec) +{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; -+ u32 rctl; + -+ if (hw->phy.media_type == e1000_media_type_fiber || -+ hw->phy.media_type == e1000_media_type_internal_serdes) { -+ switch (hw->mac.type) { -+ case e1000_80003es2lan: -+ return e1000_set_es2lan_mac_loopback(adapter); -+ break; -+ case e1000_82571: -+ case e1000_82572: -+ return e1000_set_82571_fiber_loopback(adapter); -+ break; -+ default: -+ rctl = er32(RCTL); -+ rctl |= E1000_RCTL_LBM_TCVR; -+ ew32(RCTL, rctl); -+ return 0; -+ } -+ } else if (hw->phy.media_type == e1000_media_type_copper) { -+ return e1000_integrated_phy_loopback(adapter); ++ if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) || ++ ((ec->rx_coalesce_usecs > 3) && ++ (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) || ++ (ec->rx_coalesce_usecs == 2)) ++ return -EINVAL; ++ ++ if (ec->rx_coalesce_usecs <= 3) { ++ adapter->itr = 20000; ++ adapter->itr_setting = ec->rx_coalesce_usecs; ++ } else { ++ adapter->itr = (1000000 / ec->rx_coalesce_usecs); ++ adapter->itr_setting = adapter->itr & ~3; + } + -+ return 7; ++ if (adapter->itr_setting != 0) ++ ew32(ITR, 1000000000 / (adapter->itr * 256)); ++ else ++ ew32(ITR, 0); ++ ++ return 0; +} + -+static void e1000_loopback_cleanup(struct e1000_adapter *adapter) ++static int e1000_nway_reset(struct net_device *netdev) +{ -+ struct e1000_hw *hw = &adapter->hw; -+ u32 rctl; -+ u16 phy_reg; ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ if (netif_running(netdev)) ++ e1000e_reinit_locked(adapter); ++ return 0; ++} + -+ rctl = er32(RCTL); -+ rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); -+ ew32(RCTL, rctl); ++static void e1000_get_ethtool_stats(struct net_device *netdev, ++ struct ethtool_stats *stats, ++ u64 *data) ++{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ int i; + -+ switch (hw->mac.type) { -+ case e1000_80003es2lan: -+ if (hw->phy.media_type == e1000_media_type_fiber || -+ hw->phy.media_type == e1000_media_type_internal_serdes) { -+ /* restore CTRL_EXT, stealing space from tx_fifo_head */ -+ ew32(CTRL_EXT, adapter->tx_fifo_head); -+ adapter->tx_fifo_head = 0; -+ } -+ /* fall through */ -+ case e1000_82571: -+ case e1000_82572: -+ if (hw->phy.media_type == e1000_media_type_fiber || -+ hw->phy.media_type == e1000_media_type_internal_serdes) { -+#define E1000_SERDES_LB_OFF 0x400 -+ ew32(SCTL, E1000_SERDES_LB_OFF); -+ msleep(10); -+ break; -+ } -+ /* Fall Through */ -+ default: -+ hw->mac.autoneg = 1; -+ if (hw->phy.type == e1000_phy_gg82563) -+ hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, -+ 0x180); -+ if(hw->phy.ops.read_reg) -+ hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_reg); -+ if (phy_reg & MII_CR_LOOPBACK) { -+ phy_reg &= ~MII_CR_LOOPBACK; -+ hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_reg); -+ if (hw->phy.ops.commit) -+ hw->phy.ops.commit(hw); -+ } -+ break; ++ e1000e_update_stats(adapter); ++ for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { ++ char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset; ++ data[i] = (e1000_gstrings_stats[i].sizeof_stat == ++ sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + } +} + -+static void e1000_create_lbtest_frame(struct sk_buff *skb, -+ unsigned int frame_size) ++static void e1000_get_strings(struct net_device *netdev, u32 stringset, ++ u8 *data) +{ -+ 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); -+} ++ u8 *p = data; ++ int i; + -+static int e1000_check_lbtest_frame(struct sk_buff *skb, -+ unsigned int frame_size) -+{ -+ 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; ++ switch (stringset) { ++ case ETH_SS_TEST: ++ memcpy(data, *e1000_gstrings_test, sizeof(e1000_gstrings_test)); ++ break; ++ case ETH_SS_STATS: ++ for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { ++ memcpy(p, e1000_gstrings_stats[i].stat_string, ++ ETH_GSTRING_LEN); ++ p += ETH_GSTRING_LEN; ++ } ++ break; ++ } +} + -+static int e1000_run_loopback_test(struct e1000_adapter *adapter) -+{ -+ struct e1000_ring *tx_ring = &adapter->test_tx_ring; -+ struct e1000_ring *rx_ring = &adapter->test_rx_ring; -+ struct pci_dev *pdev = adapter->pdev; -+ struct e1000_hw *hw = &adapter->hw; -+ int i, j, k, l; -+ int lc; -+ int good_cnt; -+ int ret_val = 0; -+ unsigned long time; -+ -+ ew32(RDT(0), rx_ring->count - 1); ++static const struct ethtool_ops e1000_ethtool_ops = { ++ .get_settings = e1000_get_settings, ++ .set_settings = e1000_set_settings, ++ .get_drvinfo = e1000_get_drvinfo, ++ .get_regs_len = e1000_get_regs_len, ++ .get_regs = e1000_get_regs, ++ .get_wol = e1000_get_wol, ++ .set_wol = e1000_set_wol, ++ .get_msglevel = e1000_get_msglevel, ++ .set_msglevel = e1000_set_msglevel, ++ .nway_reset = e1000_nway_reset, ++ .get_link = e1000_get_link, ++ .get_eeprom_len = e1000_get_eeprom_len, ++ .get_eeprom = e1000_get_eeprom, ++ .set_eeprom = e1000_set_eeprom, ++ .get_ringparam = e1000_get_ringparam, ++ .set_ringparam = e1000_set_ringparam, ++ .get_pauseparam = e1000_get_pauseparam, ++ .set_pauseparam = e1000_set_pauseparam, ++ .get_rx_csum = e1000_get_rx_csum, ++ .set_rx_csum = e1000_set_rx_csum, ++ .get_tx_csum = e1000_get_tx_csum, ++ .set_tx_csum = e1000_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 = e1000_set_tso, ++#endif ++ .self_test = e1000_diag_test, ++ .get_strings = e1000_get_strings, ++ .phys_id = e1000_phys_id, ++ .get_ethtool_stats = e1000_get_ethtool_stats, ++ .self_test_count = e1000_get_self_test_count, ++ .get_stats_count = e1000_get_stats_count, ++ .get_coalesce = e1000_get_coalesce, ++ .set_coalesce = e1000_set_coalesce, ++#ifdef NETIF_F_LRO ++ .get_flags = ethtool_op_get_flags, ++ .set_flags = ethtool_op_set_flags, ++#endif ++}; + -+ /* -+ * 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 -+ */ ++void e1000e_set_ethtool_ops(struct net_device *netdev) ++{ ++ /* have to "undeclare" const on this struct to remove warnings */ ++ SET_ETHTOOL_OPS(netdev, (struct ethtool_ops *)&e1000_ethtool_ops); ++} ++#endif /* SIOCETHTOOL */ +diff -Nurp linux-2.6.22-0/drivers/net/e1000e/hw.h linux-2.6.22-10/drivers/net/e1000e/hw.h +--- linux-2.6.22-0/drivers/net/e1000e/hw.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.22-10/drivers/net/e1000e/hw.h 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,701 @@ ++/******************************************************************************* + -+ if (rx_ring->count <= tx_ring->count) -+ lc = ((tx_ring->count / 64) * 2) + 1; -+ else -+ lc = ((rx_ring->count / 64) * 2) + 1; ++ Intel PRO/1000 Linux driver ++ Copyright(c) 1999 - 2009 Intel Corporation. + -+ k = 0; -+ l = 0; -+ for (j = 0; j <= lc; j++) { /* loop count loop */ -+ for (i = 0; i < 64; i++) { /* send the packets */ -+ e1000_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); -+ k++; -+ if (k == tx_ring->count) -+ k = 0; -+ } -+ ew32(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, 2048, -+ PCI_DMA_FROMDEVICE); ++ 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 = e1000_check_lbtest_frame( -+ rx_ring->buffer_info[l].skb, 1024); -+ if (!ret_val) -+ good_cnt++; -+ l++; -+ if (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) && !time_after(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; -+} ++ 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. + -+static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data) -+{ -+ struct e1000_hw *hw = &adapter->hw; -+ /* -+ * PHY loopback cannot be performed if SoL/IDER -+ * sessions are active -+ */ -+ if (hw->phy.ops.check_reset_block && -+ hw->phy.ops.check_reset_block(&adapter->hw)) { -+ e_err("Cannot do PHY loopback test when SoL/IDER is active.\n"); -+ *data = 0; -+ 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. + -+ *data = e1000_setup_desc_rings(adapter); -+ if (*data) -+ goto out; ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". + -+ *data = e1000_setup_loopback_test(adapter); -+ if (*data) -+ goto err_loopback; ++ Contact Information: ++ Linux NICS ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + -+ *data = e1000_run_loopback_test(adapter); -+ e1000_loopback_cleanup(adapter); ++*******************************************************************************/ + -+err_loopback: -+ e1000_free_desc_rings(adapter); -+out: -+ return *data; -+} ++#ifndef _E1000_HW_H_ ++#define _E1000_HW_H_ + -+static int e1000_link_test(struct e1000_adapter *adapter, u64 *data) -+{ -+ struct e1000_hw *hw = &adapter->hw; ++#include "e1000_regs.h" ++#include "e1000_defines.h" + -+ *data = 0; -+ if (hw->phy.media_type == e1000_media_type_internal_serdes) { -+ int i = 0; -+ hw->mac.serdes_has_link = 0; ++struct e1000_hw; + -+ /* -+ * On some blade server designs, link establishment -+ * could take as long as 2-3 minutes -+ */ -+ do { -+ hw->mac.ops.check_for_link(hw); -+ if (hw->mac.serdes_has_link) -+ return *data; -+ msleep(20); -+ } while (i++ < 3750); ++#define E1000_DEV_ID_82571EB_COPPER 0x105E ++#define E1000_DEV_ID_82571EB_FIBER 0x105F ++#define E1000_DEV_ID_82571EB_SERDES 0x1060 ++#define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9 ++#define E1000_DEV_ID_82571EB_SERDES_QUAD 0x10DA ++#define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4 ++#define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5 ++#define E1000_DEV_ID_82571EB_QUAD_FIBER 0x10A5 ++#define E1000_DEV_ID_82571EB_QUAD_COPPER_LP 0x10BC ++#define E1000_DEV_ID_82572EI_COPPER 0x107D ++#define E1000_DEV_ID_82572EI_FIBER 0x107E ++#define E1000_DEV_ID_82572EI_SERDES 0x107F ++#define E1000_DEV_ID_82572EI 0x10B9 ++#define E1000_DEV_ID_82573E 0x108B ++#define E1000_DEV_ID_82573E_IAMT 0x108C ++#define E1000_DEV_ID_82573L 0x109A ++#define E1000_DEV_ID_82574L 0x10D3 ++#define E1000_DEV_ID_82574LA 0x10F6 ++#define E1000_DEV_ID_82583V 0x150C ++#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096 ++#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098 ++#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT 0x10BA ++#define E1000_DEV_ID_80003ES2LAN_SERDES_SPT 0x10BB ++#define E1000_DEV_ID_ICH8_IGP_M_AMT 0x1049 ++#define E1000_DEV_ID_ICH8_IGP_AMT 0x104A ++#define E1000_DEV_ID_ICH8_IGP_C 0x104B ++#define E1000_DEV_ID_ICH8_IFE 0x104C ++#define E1000_DEV_ID_ICH8_IFE_GT 0x10C4 ++#define E1000_DEV_ID_ICH8_IFE_G 0x10C5 ++#define E1000_DEV_ID_ICH8_IGP_M 0x104D ++#define E1000_DEV_ID_ICH9_IGP_M 0x10BF ++#define E1000_DEV_ID_ICH9_IGP_M_AMT 0x10F5 ++#define E1000_DEV_ID_ICH9_IGP_M_V 0x10CB ++#define E1000_DEV_ID_ICH9_IGP_AMT 0x10BD ++#define E1000_DEV_ID_ICH9_BM 0x10E5 ++#define E1000_DEV_ID_ICH9_IGP_C 0x294C ++#define E1000_DEV_ID_ICH9_IFE 0x10C0 ++#define E1000_DEV_ID_ICH9_IFE_GT 0x10C3 ++#define E1000_DEV_ID_ICH9_IFE_G 0x10C2 ++#define E1000_DEV_ID_ICH10_R_BM_LM 0x10CC ++#define E1000_DEV_ID_ICH10_R_BM_LF 0x10CD ++#define E1000_DEV_ID_ICH10_R_BM_V 0x10CE ++#define E1000_DEV_ID_ICH10_D_BM_LM 0x10DE ++#define E1000_DEV_ID_ICH10_D_BM_LF 0x10DF ++#define E1000_DEV_ID_PCH_M_HV_LM 0x10EA ++#define E1000_DEV_ID_PCH_M_HV_LC 0x10EB ++#define E1000_DEV_ID_PCH_D_HV_DM 0x10EF ++#define E1000_DEV_ID_PCH_D_HV_DC 0x10F0 ++#define E1000_REVISION_0 0 ++#define E1000_REVISION_1 1 ++#define E1000_REVISION_2 2 ++#define E1000_REVISION_3 3 ++#define E1000_REVISION_4 4 + -+ *data = 1; -+ } else { -+ hw->mac.ops.check_for_link(hw); -+ if (hw->mac.autoneg) -+ msleep(4000); ++#define E1000_FUNC_0 0 ++#define E1000_FUNC_1 1 + -+ if (!(er32(STATUS) & -+ E1000_STATUS_LU)) -+ *data = 1; -+ } -+ return *data; -+} ++#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0 ++#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3 + -+static int e1000_get_self_test_count(struct net_device *netdev) -+{ -+ return E1000_TEST_LEN; -+} ++enum e1000_mac_type { ++ e1000_undefined = 0, ++ e1000_82571, ++ e1000_82572, ++ e1000_82573, ++ e1000_82574, ++ e1000_82583, ++ e1000_80003es2lan, ++ e1000_ich8lan, ++ e1000_ich9lan, ++ e1000_ich10lan, ++ e1000_pchlan, ++ e1000_num_macs /* List is 1-based, so subtract 1 for true count. */ ++}; + -+static int e1000_get_stats_count(struct net_device *netdev) -+{ -+ return E1000_STATS_LEN; -+} ++enum e1000_media_type { ++ e1000_media_type_unknown = 0, ++ e1000_media_type_copper = 1, ++ e1000_media_type_fiber = 2, ++ e1000_media_type_internal_serdes = 3, ++ e1000_num_media_types ++}; + -+static void e1000_diag_test(struct net_device *netdev, -+ struct ethtool_test *eth_test, u64 *data) -+{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); -+ u16 autoneg_advertised; -+ u8 forced_speed_duplex; -+ u8 autoneg; -+ bool if_running = netif_running(netdev); ++enum e1000_nvm_type { ++ e1000_nvm_unknown = 0, ++ e1000_nvm_none, ++ e1000_nvm_eeprom_spi, ++ e1000_nvm_flash_hw, ++ e1000_nvm_flash_sw ++}; + -+ set_bit(__E1000_TESTING, &adapter->state); -+ if (eth_test->flags == ETH_TEST_FL_OFFLINE) { -+ /* Offline tests */ ++enum e1000_nvm_override { ++ e1000_nvm_override_none = 0, ++ e1000_nvm_override_spi_small, ++ e1000_nvm_override_spi_large, ++}; + -+ /* 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; ++enum e1000_phy_type { ++ e1000_phy_unknown = 0, ++ e1000_phy_none, ++ e1000_phy_m88, ++ e1000_phy_igp, ++ e1000_phy_igp_2, ++ e1000_phy_gg82563, ++ e1000_phy_igp_3, ++ e1000_phy_ife, ++ e1000_phy_bm, ++ e1000_phy_82578, ++ e1000_phy_82577, ++}; + -+ e_info("offline testing starting\n"); ++enum e1000_bus_type { ++ e1000_bus_type_unknown = 0, ++ e1000_bus_type_pci, ++ e1000_bus_type_pcix, ++ e1000_bus_type_pci_express, ++ e1000_bus_type_reserved ++}; + -+ /* -+ * Link test performed before hardware reset so autoneg doesn't -+ * interfere with test result -+ */ -+ if (e1000_link_test(adapter, &data[4])) -+ eth_test->flags |= ETH_TEST_FL_FAILED; ++enum e1000_bus_speed { ++ e1000_bus_speed_unknown = 0, ++ e1000_bus_speed_33, ++ e1000_bus_speed_66, ++ e1000_bus_speed_100, ++ e1000_bus_speed_120, ++ e1000_bus_speed_133, ++ e1000_bus_speed_2500, ++ e1000_bus_speed_5000, ++ e1000_bus_speed_reserved ++}; + -+ if (if_running) -+ /* indicate we're in test mode */ -+ dev_close(netdev); -+ else -+ e1000_reset(adapter); ++enum e1000_bus_width { ++ e1000_bus_width_unknown = 0, ++ e1000_bus_width_pcie_x1, ++ e1000_bus_width_pcie_x2, ++ e1000_bus_width_pcie_x4 = 4, ++ e1000_bus_width_pcie_x8 = 8, ++ e1000_bus_width_32, ++ e1000_bus_width_64, ++ e1000_bus_width_reserved ++}; + -+ if (e1000_reg_test(adapter, &data[0])) -+ eth_test->flags |= ETH_TEST_FL_FAILED; ++enum e1000_1000t_rx_status { ++ e1000_1000t_rx_status_not_ok = 0, ++ e1000_1000t_rx_status_ok, ++ e1000_1000t_rx_status_undefined = 0xFF ++}; + -+ e1000_reset(adapter); -+ if (e1000_eeprom_test(adapter, &data[1])) -+ eth_test->flags |= ETH_TEST_FL_FAILED; ++enum e1000_rev_polarity { ++ e1000_rev_polarity_normal = 0, ++ e1000_rev_polarity_reversed, ++ e1000_rev_polarity_undefined = 0xFF ++}; + -+ e1000_reset(adapter); -+ if (e1000_intr_test(adapter, &data[2])) -+ eth_test->flags |= ETH_TEST_FL_FAILED; ++enum e1000_fc_mode { ++ e1000_fc_none = 0, ++ e1000_fc_rx_pause, ++ e1000_fc_tx_pause, ++ e1000_fc_full, ++ e1000_fc_default = 0xFF ++}; + -+ e1000_reset(adapter); -+ /* make sure the phy is powered up */ -+ e1000_power_up_phy(&adapter->hw); -+ if (e1000_loopback_test(adapter, &data[3])) -+ eth_test->flags |= ETH_TEST_FL_FAILED; ++enum e1000_ms_type { ++ e1000_ms_hw_default = 0, ++ e1000_ms_force_master, ++ e1000_ms_force_slave, ++ e1000_ms_auto ++}; + -+ /* 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; ++enum e1000_smart_speed { ++ e1000_smart_speed_default = 0, ++ e1000_smart_speed_on, ++ e1000_smart_speed_off ++}; + -+ /* force this routine to wait until autoneg complete/timeout */ -+ adapter->hw.phy.autoneg_wait_to_complete = 1; -+ e1000_reset(adapter); -+ adapter->hw.phy.autoneg_wait_to_complete = 0; ++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 ++}; + -+ clear_bit(__E1000_TESTING, &adapter->state); -+ if (if_running) -+ dev_open(netdev); -+ } else { -+ e_info("online testing starting\n"); -+ /* Online tests */ -+ if (e1000_link_test(adapter, &data[4])) -+ eth_test->flags |= ETH_TEST_FL_FAILED; ++/* Receive Descriptor */ ++struct e1000_rx_desc { ++ __le64 buffer_addr; /* Address of the descriptor's data buffer */ ++ __le16 length; /* Length of data DMAed into data buffer */ ++ __le16 csum; /* Packet checksum */ ++ u8 status; /* Descriptor status */ ++ u8 errors; /* Descriptor Errors */ ++ __le16 special; ++}; ++ ++/* Receive Descriptor - Extended */ ++union e1000_rx_desc_extended { ++ struct { ++ __le64 buffer_addr; ++ __le64 reserved; ++ } read; ++ struct { ++ struct { ++ __le32 mrq; /* Multiple Rx Queues */ ++ union { ++ __le32 rss; /* RSS Hash */ ++ struct { ++ __le16 ip_id; /* IP id */ ++ __le16 csum; /* Packet Checksum */ ++ } csum_ip; ++ } hi_dword; ++ } lower; ++ struct { ++ __le32 status_error; /* ext status/error */ ++ __le16 length; ++ __le16 vlan; /* VLAN tag */ ++ } upper; ++ } wb; /* writeback */ ++}; + -+ /* Online tests aren't run; pass by default */ -+ data[0] = 0; -+ data[1] = 0; -+ data[2] = 0; -+ data[3] = 0; ++#define MAX_PS_BUFFERS 4 ++/* Receive Descriptor - Packet Split */ ++union e1000_rx_desc_packet_split { ++ struct { ++ /* one buffer for protocol header(s), three data buffers */ ++ __le64 buffer_addr[MAX_PS_BUFFERS]; ++ } read; ++ struct { ++ struct { ++ __le32 mrq; /* Multiple Rx Queues */ ++ union { ++ __le32 rss; /* RSS Hash */ ++ struct { ++ __le16 ip_id; /* IP id */ ++ __le16 csum; /* Packet Checksum */ ++ } csum_ip; ++ } hi_dword; ++ } lower; ++ struct { ++ __le32 status_error; /* ext status/error */ ++ __le16 length0; /* length of buffer 0 */ ++ __le16 vlan; /* VLAN tag */ ++ } middle; ++ struct { ++ __le16 header_status; ++ __le16 length[3]; /* length of buffers 1-3 */ ++ } upper; ++ __le64 reserved; ++ } wb; /* writeback */ ++}; + -+ clear_bit(__E1000_TESTING, &adapter->state); -+ } -+ msleep_interruptible(4 * 1000); -+} ++/* Transmit Descriptor */ ++struct e1000_tx_desc { ++ __le64 buffer_addr; /* Address of the descriptor's data buffer */ ++ union { ++ __le32 data; ++ struct { ++ __le16 length; /* Data buffer length */ ++ u8 cso; /* Checksum offset */ ++ u8 cmd; /* Descriptor control */ ++ } flags; ++ } lower; ++ union { ++ __le32 data; ++ struct { ++ u8 status; /* Descriptor status */ ++ u8 css; /* Checksum start */ ++ __le16 special; ++ } fields; ++ } upper; ++}; + -+static void e1000_get_wol(struct net_device *netdev, -+ struct ethtool_wolinfo *wol) -+{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); ++/* Offload Context Descriptor */ ++struct e1000_context_desc { ++ union { ++ __le32 ip_config; ++ struct { ++ u8 ipcss; /* IP checksum start */ ++ u8 ipcso; /* IP checksum offset */ ++ __le16 ipcse; /* IP checksum end */ ++ } ip_fields; ++ } lower_setup; ++ union { ++ __le32 tcp_config; ++ struct { ++ u8 tucss; /* TCP checksum start */ ++ u8 tucso; /* TCP checksum offset */ ++ __le16 tucse; /* TCP checksum end */ ++ } tcp_fields; ++ } upper_setup; ++ __le32 cmd_and_length; ++ union { ++ __le32 data; ++ struct { ++ u8 status; /* Descriptor status */ ++ u8 hdr_len; /* Header length */ ++ __le16 mss; /* Maximum segment size */ ++ } fields; ++ } tcp_seg_setup; ++}; + -+ wol->supported = 0; -+ wol->wolopts = 0; ++/* Offload data descriptor */ ++struct e1000_data_desc { ++ __le64 buffer_addr; /* Address of the descriptor's buffer address */ ++ union { ++ __le32 data; ++ struct { ++ __le16 length; /* Data buffer length */ ++ u8 typ_len_ext; ++ u8 cmd; ++ } flags; ++ } lower; ++ union { ++ __le32 data; ++ struct { ++ u8 status; /* Descriptor status */ ++ u8 popts; /* Packet Options */ ++ __le16 special; ++ } fields; ++ } upper; ++}; + -+ if (!(adapter->flags & FLAG_HAS_WOL)) -+ return; ++/* Statistics counters collected by the MAC */ ++struct e1000_hw_stats { ++ u64 crcerrs; ++ u64 algnerrc; ++ u64 symerrs; ++ u64 rxerrc; ++ u64 mpc; ++ u64 scc; ++ u64 ecol; ++ u64 mcc; ++ u64 latecol; ++ u64 colc; ++ u64 dc; ++ u64 tncrs; ++ u64 sec; ++ u64 cexterr; ++ u64 rlec; ++ u64 xonrxc; ++ u64 xontxc; ++ u64 xoffrxc; ++ u64 xofftxc; ++ u64 fcruc; ++ u64 prc64; ++ u64 prc127; ++ u64 prc255; ++ u64 prc511; ++ u64 prc1023; ++ u64 prc1522; ++ u64 gprc; ++ u64 bprc; ++ u64 mprc; ++ u64 gptc; ++ u64 gorc; ++ u64 gotc; ++ u64 rnbc; ++ u64 ruc; ++ u64 rfc; ++ u64 roc; ++ u64 rjc; ++ u64 mgprc; ++ u64 mgpdc; ++ u64 mgptc; ++ u64 tor; ++ u64 tot; ++ u64 tpr; ++ u64 tpt; ++ u64 ptc64; ++ u64 ptc127; ++ u64 ptc255; ++ u64 ptc511; ++ u64 ptc1023; ++ u64 ptc1522; ++ u64 mptc; ++ u64 bptc; ++ u64 tsctc; ++ u64 tsctfc; ++ u64 iac; ++ u64 icrxptc; ++ u64 icrxatc; ++ u64 ictxptc; ++ u64 ictxatc; ++ u64 ictxqec; ++ u64 ictxqmtc; ++ u64 icrxdmtc; ++ u64 icrxoc; ++ u64 doosync; ++}; + -+ wol->supported = WAKE_UCAST | WAKE_MCAST | -+ WAKE_BCAST | WAKE_MAGIC | -+ WAKE_PHY | WAKE_ARP; + -+ /* apply any specific unsupported masks here */ -+ if (adapter->flags & FLAG_NO_WAKE_UCAST) { -+ wol->supported &= ~WAKE_UCAST; ++struct e1000_phy_stats { ++ u32 idle_errors; ++ u32 receive_errors; ++}; + -+ if (adapter->wol & E1000_WUFC_EX) -+ e_err("Interface does not support directed (unicast)" -+ " frame wake-up packets\n"); -+ } ++struct e1000_host_mng_dhcp_cookie { ++ u32 signature; ++ u8 status; ++ u8 reserved0; ++ u16 vlan_id; ++ u32 reserved1; ++ u16 reserved2; ++ u8 reserved3; ++ u8 checksum; ++}; + -+ 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; -+ if (adapter->wol & E1000_WUFC_LNKC) -+ wol->wolopts |= WAKE_PHY; -+ if (adapter->wol & E1000_WUFC_ARP) -+ wol->wolopts |= WAKE_ARP; -+} ++/* Host Interface "Rev 1" */ ++struct e1000_host_command_header { ++ u8 command_id; ++ u8 command_length; ++ u8 command_options; ++ u8 checksum; ++}; + -+static int e1000_set_wol(struct net_device *netdev, -+ struct ethtool_wolinfo *wol) -+{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); ++#define E1000_HI_MAX_DATA_LENGTH 252 ++struct e1000_host_command_info { ++ struct e1000_host_command_header command_header; ++ u8 command_data[E1000_HI_MAX_DATA_LENGTH]; ++}; + -+ if (wol->wolopts & WAKE_MAGICSECURE) -+ return -EOPNOTSUPP; ++/* Host Interface "Rev 2" */ ++struct e1000_host_mng_command_header { ++ u8 command_id; ++ u8 checksum; ++ u16 reserved1; ++ u16 reserved2; ++ u16 command_length; ++}; + -+ if (!(adapter->flags & FLAG_HAS_WOL)) -+ return wol->wolopts ? -EOPNOTSUPP : 0; ++#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 ++struct e1000_host_mng_command_info { ++ struct e1000_host_mng_command_header command_header; ++ u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; ++}; + -+ /* these settings will always override what we currently have */ -+ adapter->wol = 0; ++#include "e1000_mac.h" ++#include "e1000_phy.h" ++#include "e1000_nvm.h" ++#include "e1000_manage.h" + -+ 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; -+ if (wol->wolopts & WAKE_PHY) -+ adapter->wol |= E1000_WUFC_LNKC; -+ if (wol->wolopts & WAKE_ARP) -+ adapter->wol |= E1000_WUFC_ARP; ++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); ++ s32 (*cleanup_led)(struct e1000_hw *); ++ 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); ++ s32 (*reset_hw)(struct e1000_hw *); ++ s32 (*init_hw)(struct e1000_hw *); ++ s32 (*setup_link)(struct e1000_hw *); ++ s32 (*setup_physical_interface)(struct e1000_hw *); ++ 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*); ++ 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 *); ++}; + -+ return 0; -+} ++struct e1000_phy_operations { ++ s32 (*init_params)(struct e1000_hw *); ++ s32 (*acquire)(struct e1000_hw *); ++ s32 (*cfg_on_link_up)(struct e1000_hw *); ++ s32 (*check_polarity)(struct e1000_hw *); ++ s32 (*check_reset_block)(struct e1000_hw *); ++ s32 (*commit)(struct e1000_hw *); ++ s32 (*force_speed_duplex)(struct e1000_hw *); ++ s32 (*get_cfg_done)(struct e1000_hw *hw); ++ s32 (*get_cable_length)(struct e1000_hw *); ++ s32 (*get_info)(struct e1000_hw *); ++ s32 (*read_reg)(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); ++ void (*power_up)(struct e1000_hw *); ++ void (*power_down)(struct e1000_hw *); ++}; + -+/* toggle LED 4 times per second = 2 "blinks" per second */ -+#define E1000_ID_INTERVAL (HZ/4) ++struct e1000_nvm_operations { ++ s32 (*init_params)(struct e1000_hw *); ++ s32 (*acquire)(struct e1000_hw *); ++ s32 (*read)(struct e1000_hw *, u16, u16, u16 *); ++ void (*release)(struct e1000_hw *); ++ void (*reload)(struct e1000_hw *); ++ s32 (*update)(struct e1000_hw *); ++ s32 (*valid_led_default)(struct e1000_hw *, u16 *); ++ s32 (*validate)(struct e1000_hw *); ++ s32 (*write)(struct e1000_hw *, u16, u16, u16 *); ++}; + -+/* bit defines for adapter->led_status */ -+#define E1000_LED_ON 0 ++struct e1000_mac_info { ++ struct e1000_mac_operations ops; ++ u8 addr[6]; ++ u8 perm_addr[6]; + -+static void e1000_led_blink_callback(unsigned long data) -+{ -+ struct e1000_adapter *adapter = (struct e1000_adapter *) data; ++ enum e1000_mac_type type; + -+ if (test_and_change_bit(E1000_LED_ON, &adapter->led_status)) -+ adapter->hw.mac.ops.led_off(&adapter->hw); -+ else -+ adapter->hw.mac.ops.led_on(&adapter->hw); ++ u32 collision_delta; ++ u32 ledctl_default; ++ u32 ledctl_mode1; ++ u32 ledctl_mode2; ++ u32 mc_filter_type; ++ u32 tx_packet_delta; ++ u32 txcw; + -+ mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL); -+} ++ u16 current_ifs_val; ++ u16 ifs_max_val; ++ u16 ifs_min_val; ++ u16 ifs_ratio; ++ u16 ifs_step_size; ++ u16 mta_reg_count; + -+static int e1000_phys_id(struct net_device *netdev, u32 data) -+{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); -+ struct e1000_hw *hw = &adapter->hw; ++ /* 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; + -+ if (!data) -+ data = INT_MAX; ++ u8 forced_speed_duplex; + -+ if ((hw->phy.type == e1000_phy_ife) || -+ (hw->mac.type == e1000_82574)) { -+ if (!adapter->blink_timer.function) { -+ init_timer(&adapter->blink_timer); -+ adapter->blink_timer.function = -+ e1000_led_blink_callback; -+ adapter->blink_timer.data = (unsigned long) adapter; -+ } -+ mod_timer(&adapter->blink_timer, jiffies); -+ msleep_interruptible(data * 1000); -+ del_timer_sync(&adapter->blink_timer); -+ if (hw->phy.type == e1000_phy_ife) -+ hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED, -+ 0); -+ } else { -+ hw->mac.ops.blink_led(hw); -+ msleep_interruptible(data * 1000); -+ } ++ bool adaptive_ifs; ++ bool arc_subsystem_valid; ++ bool asf_firmware_present; ++ bool autoneg; ++ 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; ++}; + -+ hw->mac.ops.led_off(hw); -+ clear_bit(E1000_LED_ON, &adapter->led_status); -+ hw->mac.ops.cleanup_led(hw); ++struct e1000_phy_info { ++ struct e1000_phy_operations ops; ++ enum e1000_phy_type type; + -+ return 0; -+} ++ enum e1000_1000t_rx_status local_rx; ++ enum e1000_1000t_rx_status remote_rx; ++ enum e1000_ms_type ms_type; ++ enum e1000_ms_type original_ms_type; ++ enum e1000_rev_polarity cable_polarity; ++ enum e1000_smart_speed smart_speed; + -+static int e1000_get_coalesce(struct net_device *netdev, -+ struct ethtool_coalesce *ec) -+{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); ++ u32 addr; ++ u32 id; ++ u32 reset_delay_us; /* in usec */ ++ u32 revision; + -+ if (adapter->itr_setting <= 3) -+ ec->rx_coalesce_usecs = adapter->itr_setting; -+ else -+ ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting; ++ enum e1000_media_type media_type; + -+ ec->stats_block_coalesce_usecs = adapter->stats_freq_us; ++ u16 autoneg_advertised; ++ u16 autoneg_mask; ++ u16 cable_length; ++ u16 max_cable_length; ++ u16 min_cable_length; + -+ return 0; -+} ++ u8 mdix; + -+static int e1000_set_coalesce(struct net_device *netdev, -+ struct ethtool_coalesce *ec) -+{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); -+ struct e1000_hw *hw = &adapter->hw; ++ bool disable_polarity_correction; ++ bool is_mdix; ++ bool polarity_correction; ++ bool reset_disable; ++ bool speed_downgraded; ++ bool autoneg_wait_to_complete; ++}; + -+ if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) || -+ ((ec->rx_coalesce_usecs > 3) && -+ (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) || -+ (ec->rx_coalesce_usecs == 2) || -+ (ec->stats_block_coalesce_usecs > (10 * 1000000))) -+ return -EINVAL; ++struct e1000_nvm_info { ++ struct e1000_nvm_operations ops; ++ enum e1000_nvm_type type; ++ enum e1000_nvm_override override; + -+ adapter->stats_freq_us = ec->stats_block_coalesce_usecs; ++ u32 flash_bank_size; ++ u32 flash_base_addr; + -+ if (ec->rx_coalesce_usecs <= 3) { -+ adapter->itr = 20000; -+ adapter->itr_setting = ec->rx_coalesce_usecs; -+ } else { -+ adapter->itr = (1000000 / ec->rx_coalesce_usecs); -+ adapter->itr_setting = adapter->itr & ~3; -+ } ++ u16 word_size; ++ u16 delay_usec; ++ u16 address_bits; ++ u16 opcode_bits; ++ u16 page_size; ++}; + -+ if (adapter->itr_setting != 0) -+ ew32(ITR, 1000000000 / (adapter->itr * 256)); -+ else -+ ew32(ITR, 0); ++struct e1000_bus_info { ++ enum e1000_bus_type type; ++ enum e1000_bus_speed speed; ++ enum e1000_bus_width width; + -+ return 0; -+} ++ u16 func; ++ u16 pci_cmd_word; ++}; + -+static int e1000_nway_reset(struct net_device *netdev) -+{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); -+ if (netif_running(netdev)) -+ e1000_reinit_locked(adapter); -+ return 0; -+} ++struct e1000_fc_info { ++ u32 high_water; /* Flow control high-water mark */ ++ u32 low_water; /* Flow control low-water mark */ ++ u16 pause_time; /* Flow control pause timer */ ++ bool send_xon; /* Flow control send XON */ ++ bool strict_ieee; /* Strict IEEE mode */ ++ enum e1000_fc_mode current_mode; /* FC mode in effect */ ++ enum e1000_fc_mode requested_mode; /* FC mode requested by caller */ ++}; + -+static void e1000_get_ethtool_stats(struct net_device *netdev, -+ struct ethtool_stats *stats, -+ u64 *data) -+{ -+ struct e1000_adapter *adapter = netdev_priv(netdev); -+ int i; ++struct e1000_dev_spec_82571 { ++ bool laa_is_present; ++ u32 smb_counter; ++}; + -+ e1000_update_stats(adapter); -+ for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { -+ char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset; -+ data[i] = (e1000_gstrings_stats[i].sizeof_stat == -+ sizeof(u64)) ? *(u64 *)p : *(u32 *)p; -+ } -+} ++struct e1000_shadow_ram { ++ u16 value; ++ bool modified; ++}; + -+static void e1000_get_strings(struct net_device *netdev, u32 stringset, -+ u8 *data) -+{ -+ u8 *p = data; -+ int i; ++#define E1000_ICH8_SHADOW_RAM_WORDS 2048 + -+ switch (stringset) { -+ case ETH_SS_TEST: -+ memcpy(data, *e1000_gstrings_test, sizeof(e1000_gstrings_test)); -+ break; -+ case ETH_SS_STATS: -+ for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { -+ memcpy(p, e1000_gstrings_stats[i].stat_string, -+ ETH_GSTRING_LEN); -+ p += ETH_GSTRING_LEN; -+ } -+ break; -+ } -+} ++struct e1000_dev_spec_ich8lan { ++ bool kmrn_lock_loss_workaround_enabled; ++ struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS]; ++}; + -+static const struct ethtool_ops e1000_ethtool_ops = { -+ .get_settings = e1000_get_settings, -+ .set_settings = e1000_set_settings, -+ .get_drvinfo = e1000_get_drvinfo, -+ .get_regs_len = e1000_get_regs_len, -+ .get_regs = e1000_get_regs, -+ .get_wol = e1000_get_wol, -+ .set_wol = e1000_set_wol, -+ .get_msglevel = e1000_get_msglevel, -+ .set_msglevel = e1000_set_msglevel, -+ .nway_reset = e1000_nway_reset, -+ .get_link = e1000_get_link, -+ .get_eeprom_len = e1000_get_eeprom_len, -+ .get_eeprom = e1000_get_eeprom, -+ .set_eeprom = e1000_set_eeprom, -+ .get_ringparam = e1000_get_ringparam, -+ .set_ringparam = e1000_set_ringparam, -+ .get_pauseparam = e1000_get_pauseparam, -+ .set_pauseparam = e1000_set_pauseparam, -+ .get_rx_csum = e1000_get_rx_csum, -+ .set_rx_csum = e1000_set_rx_csum, -+ .get_tx_csum = e1000_get_tx_csum, -+ .set_tx_csum = e1000_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 = e1000_set_tso, -+#endif -+ .self_test = e1000_diag_test, -+ .get_strings = e1000_get_strings, -+ .phys_id = e1000_phys_id, -+ .get_ethtool_stats = e1000_get_ethtool_stats, -+ .self_test_count = e1000_get_self_test_count, -+ .get_stats_count = e1000_get_stats_count, -+ .get_coalesce = e1000_get_coalesce, -+ .set_coalesce = e1000_set_coalesce, ++struct e1000_hw { ++ struct e1000_adapter *adapter; ++ ++ u8 __iomem *hw_addr; ++ u8 __iomem *flash_address; ++ ++ struct e1000_mac_info mac; ++ struct e1000_fc_info fc; ++ struct e1000_phy_info phy; ++ struct e1000_nvm_info nvm; ++ struct e1000_bus_info bus; ++ struct e1000_host_mng_dhcp_cookie mng_cookie; ++ ++ union { ++ struct e1000_dev_spec_82571 _82571; ++ struct e1000_dev_spec_ich8lan ich8lan; ++ } dev_spec; ++ ++ u16 device_id; ++ u16 subsystem_vendor_id; ++ u16 subsystem_device_id; ++ u16 vendor_id; ++ ++ u8 revision_id; +}; + -+void e1000_set_ethtool_ops(struct net_device *netdev) -+{ -+ /* have to "undeclare" const on this struct to remove warnings */ -+ SET_ETHTOOL_OPS(netdev, (struct ethtool_ops *)&e1000_ethtool_ops); -+} -+#endif /* SIOCETHTOOL */ ++#include "e1000_82571.h" ++#include "e1000_80003es2lan.h" ++#include "e1000_ich8lan.h" ++ ++/* These functions must be implemented by drivers */ ++s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); ++ ++#endif diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.c linux-2.6.22-10/drivers/net/e1000e/kcompat.c --- linux-2.6.22-0/drivers/net/e1000e/kcompat.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/kcompat.c 2008-11-10 17:29:35.000000000 +0100 -@@ -0,0 +1,319 @@ ++++ linux-2.6.22-10/drivers/net/e1000e/kcompat.c 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,480 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -17379,19 +18323,32 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.c linux-2.6.22-10/drivers/n + +*******************************************************************************/ + -+ -+#define DRIVER_E1000E -+ -+#ifdef DRIVER_E1000E +#include "e1000.h" -+#endif -+ -+ -+ -+ +#include "kcompat.h" + +/*****************************************************************************/ ++#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,13) ) + +/**************************************/ @@ -17531,18 +18488,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.c linux-2.6.22-10/drivers/n +} + +int -+_kc_pci_save_state(struct pci_dev *dev, u32 *buffer) -+{ -+ return 0; -+} -+ -+int -+_kc_pci_restore_state(struct pci_dev *pdev, u32 *buffer) -+{ -+ return 0; -+} -+ -+int +_kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable) +{ + return 0; @@ -17645,39 +18590,199 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.c linux-2.6.22-10/drivers/n +#endif /* <= 2.6.17 */ + +/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) ) -+#endif /* < 2.6.23 */ ++#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 (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 ++ } ++} ++ ++#ifdef HAVE_PCI_ERS ++void _kc_free_netdev(struct net_device *netdev) ++{ ++ 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 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) ) +#ifdef NAPI ++/* this function returns the true netdev of the napi struct */ ++struct net_device * napi_to_netdev(struct napi_struct *napi) ++{ ++ struct adapter_struct *adapter = container_of(napi, ++ struct adapter_struct, ++ napi); ++ return adapter->netdev; ++} ++ +int __kc_adapter_clean(struct net_device *netdev, int *budget) +{ + int work_done; + int work_to_do = min(*budget, netdev->quota); + struct adapter_struct *adapter = netdev_priv(netdev); -+#ifdef DRIVER_E1000E + struct napi_struct *napi = &adapter->napi; -+#else -+ struct napi_struct *napi = &adapter->rx_ring[0].napi; -+#endif -+ + work_done = napi->poll(napi, work_to_do); + *budget -= work_done; + netdev->quota -= work_done; -+ return work_done ? 1 : 0; ++ return (work_done >= work_to_do) ? 1 : 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) ++{ ++ 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); ++} ++void _kc_netif_tx_wake_all_queues(struct net_device *netdev) ++{ ++ struct adapter_struct *adapter = netdev_priv(netdev); ++ int i; ++ ++ 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) ++{ ++ 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 */ ++ ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ) ++ ++int ++_kc_pci_prepare_to_sleep(struct pci_dev *dev) ++{ ++ pci_power_t target_state; ++ int error; ++ ++ target_state = pci_choose_state(dev, PMSG_SUSPEND); ++ ++ pci_enable_wake(dev, target_state, true); ++ ++ 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) ++{ ++ int err; ++ ++ err = pci_enable_wake(dev, PCI_D3cold, enable); ++ if (err) ++ goto out; ++ ++ err = pci_enable_wake(dev, PCI_D3hot, enable); ++ ++out: ++ return err; ++} ++#endif /* < 2.6.28 */ ++ ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) ) ++#endif /* < 2.6.29 */ ++ ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ) ++#endif /* < 2.6.30 */ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat_ethtool.c linux-2.6.22-10/drivers/net/e1000e/kcompat_ethtool.c --- linux-2.6.22-0/drivers/net/e1000e/kcompat_ethtool.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/kcompat_ethtool.c 2008-10-14 01:51:32.000000000 +0200 ++++ linux-2.6.22-10/drivers/net/e1000e/kcompat_ethtool.c 2009-06-24 00:32:20.000000000 +0200 @@ -0,0 +1,1169 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -18635,7 +19740,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat_ethtool.c linux-2.6.22-10/d + 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; @@ -18676,9 +19781,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat_ethtool.c linux-2.6.22-10/d + 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; + @@ -18703,7 +19808,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat_ethtool.c linux-2.6.22-10/d + 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); @@ -18845,12 +19950,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat_ethtool.c linux-2.6.22-10/d + diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/net/e1000e/kcompat.h --- linux-2.6.22-0/drivers/net/e1000e/kcompat.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/kcompat.h 2008-11-10 17:29:48.000000000 +0100 -@@ -0,0 +1,1629 @@ ++++ linux-2.6.22-10/drivers/net/e1000e/kcompat.h 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,1704 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -18898,68 +20003,23 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n +#include +#include + -+#define DRIVER_E1000E -+ +/* NAPI enable/disable flags here */ -+ -+#ifdef DRIVER_E1000E +#define NAPI -+#endif -+ -+#ifdef _E1000_H_ -+#ifdef CONFIG_E1000_NAPI -+#define NAPI -+#endif -+#ifdef E1000_NAPI -+#undef NAPI -+#define NAPI -+#endif -+#ifdef E1000E_NAPI -+#undef NAPI -+#define NAPI -+#endif -+#ifdef E1000_NO_NAPI -+#undef NAPI -+#endif +#ifdef E1000E_NO_NAPI +#undef NAPI +#endif -+#endif -+ -+ -+ + -+ -+ -+#ifdef DRIVER_E1000E +#define adapter_struct e1000_adapter +#define CONFIG_E1000E_MSIX -+#endif -+ -+ -+ + +/* and finally set defines so that the code sees the changes */ +#ifdef NAPI -+#ifndef CONFIG_E1000_NAPI -+#define CONFIG_E1000_NAPI -+#endif +#ifndef CONFIG_E1000E_NAPI +#define CONFIG_E1000E_NAPI +#endif +#else -+#undef CONFIG_E1000_NAPI +#undef CONFIG_E1000E_NAPI -+#undef CONFIG_IXGB_NAPI -+#endif -+ -+/* 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 ++#endif /* NAPI */ + +/* MSI compatibility code for all kernels and drivers */ +#ifdef DISABLE_PCI_MSI @@ -19023,6 +20083,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n +#define PCI_CAP_ID_EXP 0x10 +#endif + ++#ifndef PCIE_LINK_STATE_L0S ++#define PCIE_LINK_STATE_L0S 1 ++#endif ++ +#ifndef mmiowb +#ifdef CONFIG_IA64 +#define mmiowb() asm volatile ("mf.a" ::: "memory") @@ -19031,12 +20095,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n +#endif +#endif + -+#ifndef IRQ_HANDLED -+#define irqreturn_t void -+#define IRQ_HANDLED -+#define IRQ_NONE -+#endif -+ +#ifndef SET_NETDEV_DEV +#define SET_NETDEV_DEV(net, pdev) +#endif @@ -19072,6 +20130,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n +#define gso_segs tso_segs +#endif + ++#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 ++ +#ifndef CHECKSUM_PARTIAL +#define CHECKSUM_PARTIAL CHECKSUM_HW +#define CHECKSUM_COMPLETE CHECKSUM_HW @@ -19566,16 +20630,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n +extern int _kc_pci_set_power_state(struct pci_dev *dev, int state); +#endif + -+#ifndef pci_save_state -+#define pci_save_state _kc_pci_save_state -+extern int _kc_pci_save_state(struct pci_dev *dev, u32 *buffer); -+#endif -+ -+#ifndef pci_restore_state -+#define pci_restore_state _kc_pci_restore_state -+extern int _kc_pci_restore_state(struct pci_dev *pdev, u32 *buffer); -+#endif -+ +#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); @@ -19628,6 +20682,16 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n + (void) (&_x == &_y); \ + _x > _y ? _x : _y; }) + ++#define min_t(type,x,y) ({ \ ++ type _x = (x); \ ++ type _y = (y); \ ++ _x < _y ? _x : _y; }) ++ ++#define max_t(type,x,y) ({ \ ++ type _x = (x); \ ++ type _y = (y); \ ++ _x > _y ? _x : _y; }) ++ +#ifndef list_for_each_safe +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ @@ -19690,22 +20754,22 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n + +/* 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 + +#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 ++/* < 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 */ + +/*****************************************************************************/ +/* 2.4.22 => 2.4.17 */ -+ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) ++#define pci_name(x) ((x)->slot_name) +#endif + +/*****************************************************************************/ @@ -19798,6 +20862,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n + +#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) + +/* hlist_* code - double linked lists */ +struct hlist_head { @@ -19891,6 +20957,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n +#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 */ + @@ -19918,6 +20985,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n +#undef ALIGN +#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) + ++#ifndef page_count ++#define page_count(p) atomic_read(&(p)->count) ++#endif ++ +/* find_first_bit and find_next bit are not defined for most + * 2.4 kernels (except for the redhat 2.4.21 kernels + */ @@ -19973,6 +21044,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n + +/*****************************************************************************/ +#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) @@ -20027,6 +21104,16 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n +/* Basic mode control register. */ +#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */ + ++#ifndef __le16 ++#define __le16 u16 ++#endif ++#ifndef __le32 ++#define __le32 u32 ++#endif ++#ifndef __le64 ++#define __le64 u64 ++#endif ++ +#ifdef pci_dma_mapping_error +#undef pci_dma_mapping_error +#endif @@ -20040,44 +21127,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n +#endif /* < 2.6.9 */ + +/*****************************************************************************/ -+#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6) && \ -+ LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) -+#ifdef pci_save_state -+#undef pci_save_state -+#endif -+#define pci_save_state(X) { \ -+ int i; \ -+ if (adapter->pci_state) { \ -+ for (i = 0; i < 16; i++) { \ -+ pci_read_config_dword((X), \ -+ i * 4, \ -+ &adapter->pci_state[i]); \ -+ } \ -+ } \ -+} -+ -+#ifdef pci_restore_state -+#undef pci_restore_state -+#endif -+#define pci_restore_state(X) { \ -+ int i; \ -+ if (adapter->pci_state) { \ -+ for (i = 0; i < 16; i++) { \ -+ pci_write_config_dword((X), \ -+ i * 4, \ -+ adapter->pci_state[i]); \ -+ } \ -+ } else { \ -+ for (i = 0; i < 6; i++) { \ -+ pci_write_config_dword((X), \ -+ PCI_BASE_ADDRESS_0 + (i * 4), \ -+ (X)->resource[i].start); \ -+ } \ -+ } \ -+} -+#endif /* 2.4.6 <= x < 2.6.10 */ -+ -+/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) +#ifdef module_param_array_named +#undef module_param_array_named @@ -20097,8 +21146,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n +#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 + +#undef NETIF_F_LLTX + @@ -20149,7 +21200,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n +#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymmetric pause */ +/* 1000BASE-T Control register */ +#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */ -+#endif ++#endif /* < 2.6.12 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ) @@ -20166,19 +21217,42 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n +/* 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 */ ++ ++/*****************************************************************************/ ++#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 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) ) ++#define DEFINE_MUTEX(x) DECLARE_MUTEX(x) ++#define mutex_lock(x) down_interruptible(x) ++#define mutex_unlock(x) up(x) ++ +#undef HAVE_PCI_ERS +#else /* 2.6.16 and above */ +#undef HAVE_PCI_ERS +#define HAVE_PCI_ERS -+#endif ++#endif /* < 2.6.16 */ + +/*****************************************************************************/ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ) + ++#ifndef IRQ_HANDLED ++#define irqreturn_t void ++#define IRQ_HANDLED ++#define IRQ_NONE ++#endif ++ +#ifndef IRQF_PROBE_SHARED +#ifdef SA_PROBEIRQ +#define IRQF_PROBE_SHARED SA_PROBEIRQ @@ -20221,7 +21295,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n +#ifndef DIV_ROUND_UP +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) +#endif -+ +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ) +#ifndef RHEL_RELEASE_CODE +#define RHEL_RELEASE_CODE 0 @@ -20238,13 +21311,21 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n +#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 ++#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 ++#endif /* >= 2.5.x */ +{ + irq_handler_t new_handler = (irq_handler_t) handler; + return request_irq(irq, new_handler, flags, devname, dev_id); @@ -20254,64 +21335,35 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n +#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 -+#ifdef DRIVER_E1000E +#define pci_config_space_ich8lan() { \ + if (adapter->flags & FLAG_IS_ICH) \ + size = PCIE_CONFIG_SPACE_LEN; \ +} -+#else -+#define pci_config_space_ich8lan() -+#endif +#undef pci_save_state -+#define pci_save_state(pdev) _kc_pci_save_state(adapter) -+#define _kc_pci_save_state(adapter) 0; { \ -+ 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(); \ -+ WARN_ON(adapter->config_space != NULL); \ -+ 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]); \ -+} ++extern int _kc_pci_save_state(struct pci_dev *); ++#define pci_save_state(pdev) _kc_pci_save_state(pdev) +#undef pci_restore_state -+#define pci_restore_state(pdev) _kc_pci_restore_state(adapter) -+#define _kc_pci_restore_state(adapter) { \ -+ 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) { \ -+ if (!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]); \ -+ kfree(adapter->config_space); \ -+ adapter->config_space = NULL; \ -+ } \ ++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) ) @@ -20342,10 +21394,15 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n + +/*****************************************************************************/ +#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 */ + +/*****************************************************************************/ @@ -20374,6 +21431,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n +#ifndef ETH_FCS_LEN +#define ETH_FCS_LEN 4 +#endif ++#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 +#endif /* < 2.6.22 */ + +/*****************************************************************************/ @@ -20384,30 +21449,39 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n +#endif /* > 2.6.22 */ + +/*****************************************************************************/ ++#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) ) +/* 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 *); -+#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) ++extern struct net_device * napi_to_netdev(struct napi_struct *); ++#define napi_to_poll_dev(napi) napi_to_netdev(napi) +#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; \ ++ 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) ++#define napi_schedule_prep(napi) netif_rx_schedule_prep(napi_to_netdev(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)) ++#define napi_complete(napi) netif_rx_complete(napi_to_poll_dev(napi)) +#else /* NAPI */ +#define netif_napi_add(_netdev, _napi, _poll, _weight) \ + do { \ @@ -20417,11 +21491,15 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n + __napi->poll = &(_poll); \ + __napi->weight = (_weight); \ + } 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_NETDEV_NAPI_LIST +#endif /* < 2.6.24 */ + +/*****************************************************************************/ @@ -20454,36 +21532,138 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/kcompat.h linux-2.6.22-10/drivers/n +} +#endif /* > 2.6.18 */ + ++#define pci_enable_device_mem(pdev) pci_enable_device(pdev) ++ +#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 ++#endif /* netif_napi_del */ +#ifndef pci_dma_mapping_error +#define pci_dma_mapping_error(pdev, dma_addr) pci_dma_mapping_error(dma_addr) +#endif -+#endif /* < 2.6.27 */ + ++ ++#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_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 ++#define HAVE_NETDEV_SELECT_QUEUE ++#endif /* < 2.6.27 */ ++ ++/*****************************************************************************/ ++#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); ++#endif /* < 2.6.28 */ ++ ++/*****************************************************************************/ ++#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) ++#else /* < 2.6.29 */ ++#ifdef CONFIG_DCB ++#define HAVE_PFC_MODE_ENABLE ++#endif /* CONFIG_DCB */ ++#endif /* < 2.6.29 */ ++ ++/*****************************************************************************/ ++#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) ++#else ++#define HAVE_ASPM_QUIRKS ++#endif /* < 2.6.30 */ + ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) ) ++#else ++#ifndef HAVE_NETDEV_STORAGE_ADDRESS ++#define HAVE_NETDEV_STORAGE_ADDRESS ++#endif ++#endif /* < 2.6.31 */ +#endif /* _KCOMPAT_H_ */ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/Makefile linux-2.6.22-10/drivers/net/e1000e/Makefile --- linux-2.6.22-0/drivers/net/e1000e/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/Makefile 2008-11-10 00:06:14.000000000 +0100 ++++ linux-2.6.22-10/drivers/net/e1000e/Makefile 2009-08-27 23:56:36.000000000 +0200 @@ -0,0 +1,33 @@ +################################################################################ +# +# Intel PRO/1000 Linux driver -+# Copyright(c) 1999 - 2008 Intel Corporation. ++# Copyright(c) 1999 - 2009 Intel Corporation. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, @@ -20515,12 +21695,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/Makefile linux-2.6.22-10/drivers/ne + e1000_phy.o e1000_manage.o kcompat.o diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/net/e1000e/netdev.c --- linux-2.6.22-0/drivers/net/e1000e/netdev.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/netdev.c 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,5637 @@ ++++ linux-2.6.22-10/drivers/net/e1000e/netdev.c 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,6007 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -20568,14 +21748,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +#include "e1000.h" + +#ifdef CONFIG_E1000E_NAPI -+#define DRV_NAPI "-NAPI" ++#define DRV_EXTRAVERSION "-NAPI" +#else -+#define DRV_NAPI ++#define DRV_EXTRAVERSION +#endif + -+#define DRV_DEBUG -+ -+#define DRV_VERSION "0.4.1.12" DRV_NAPI DRV_DEBUG ++#define DRV_VERSION "1.0.2.5" DRV_EXTRAVERSION +char e1000e_driver_name[] = "e1000e"; +const char e1000e_driver_version[] = DRV_VERSION; + @@ -20625,10 +21803,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + + case e1000_82573: + if (pdev->device == E1000_DEV_ID_82573L) { -+ adapter->hw.nvm.ops.read(&adapter->hw, NVM_INIT_3GIO_3, -+ 1, &eeprom_data); -+ if (!(eeprom_data & NVM_WORD1A_ASPM_MASK)) ++ if (e1000_read_nvm(&adapter->hw, NVM_INIT_3GIO_3, 1, ++ &eeprom_data) < 0) ++ break; ++ if (!(eeprom_data & NVM_WORD1A_ASPM_MASK)) { + adapter->flags |= FLAG_HAS_JUMBO_FRAMES; ++ adapter->max_hw_frame_size = DEFAULT_JUMBO; ++ } + } + break; + @@ -20652,6 +21833,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + | FLAG_TARC_SPEED_MODE_BIT /* errata */ + | FLAG_APME_CHECK_PORT_B, + .pba = 38, ++ .max_hw_frame_size = DEFAULT_JUMBO, + .init_ops = e1000_init_function_pointers_82571, + .get_variants = e1000_get_variants_82571, +}; @@ -20666,6 +21848,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + | FLAG_HAS_CTRLEXT_ON_LOAD + | FLAG_TARC_SPEED_MODE_BIT, /* errata */ + .pba = 38, ++ .max_hw_frame_size = DEFAULT_JUMBO, + .init_ops = e1000_init_function_pointers_82571, + .get_variants = e1000_get_variants_82571, +}; @@ -20678,10 +21861,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + | FLAG_RX_CSUM_ENABLED + | FLAG_HAS_SMART_POWER_DOWN + | FLAG_HAS_AMT -+ | FLAG_HAS_ASPM + | FLAG_HAS_ERT + | FLAG_HAS_SWSM_ON_LOAD, + .pba = 20, ++ .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, + .init_ops = e1000_init_function_pointers_82571, + .get_variants = e1000_get_variants_82571, +}; @@ -20698,9 +21881,24 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + | FLAG_RX_CSUM_ENABLED + | FLAG_HAS_SMART_POWER_DOWN + | FLAG_HAS_AMT -+ | FLAG_HAS_ASPM + | FLAG_HAS_CTRLEXT_ON_LOAD, + .pba = 20, ++ .max_hw_frame_size = DEFAULT_JUMBO, ++ .init_ops = e1000_init_function_pointers_82571, ++ .get_variants = e1000_get_variants_82571, ++}; ++ ++static struct e1000_info e1000_82583_info = { ++ .mac = e1000_82583, ++ .flags = FLAG_HAS_HW_VLAN_FILTER ++ | FLAG_HAS_WOL ++ | FLAG_APME_IN_CTRL3 ++ | FLAG_RX_CSUM_ENABLED ++ | FLAG_HAS_SMART_POWER_DOWN ++ | FLAG_HAS_AMT ++ | FLAG_HAS_CTRLEXT_ON_LOAD, ++ .pba = 20, ++ .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, + .init_ops = e1000_init_function_pointers_82571, + .get_variants = e1000_get_variants_82571, +}; @@ -20719,14 +21917,17 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + | FLAG_DISABLE_FC_PAUSE_TIME /* errata */ + | FLAG_TIPG_MEDIUM_FOR_80003ESLAN, + .pba = 38, ++ .max_hw_frame_size = DEFAULT_JUMBO, + .init_ops = e1000_init_function_pointers_80003es2lan, + .get_variants = NULL, +}; + +static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) +{ -+ if (adapter->hw.phy.type == e1000_phy_ife) ++ if (adapter->hw.phy.type == e1000_phy_ife) { + adapter->flags &= ~FLAG_HAS_JUMBO_FRAMES; ++ adapter->max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN; ++ } + + if ((adapter->hw.mac.type == e1000_ich8lan) && + (adapter->hw.phy.type == e1000_phy_igp_3)) @@ -20745,6 +21946,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + | FLAG_HAS_FLASH + | FLAG_APME_IN_WUC, + .pba = 8, ++ .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, + .init_ops = e1000_init_function_pointers_ich8lan, + .get_variants = e1000_get_variants_ich8lan, +}; @@ -20761,6 +21963,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + | FLAG_HAS_FLASH + | FLAG_APME_IN_WUC, + .pba = 10, ++ .max_hw_frame_size = DEFAULT_JUMBO, + .init_ops = e1000_init_function_pointers_ich8lan, + .get_variants = e1000_get_variants_ich8lan, +}; @@ -20777,6 +21980,23 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + | FLAG_HAS_FLASH + | FLAG_APME_IN_WUC, + .pba = 10, ++ .max_hw_frame_size = DEFAULT_JUMBO, ++ .init_ops = e1000_init_function_pointers_ich8lan, ++ .get_variants = e1000_get_variants_ich8lan, ++}; ++ ++static struct e1000_info e1000_pch_info = { ++ .mac = e1000_pchlan, ++ .flags = FLAG_IS_ICH ++ | FLAG_HAS_WOL ++ | FLAG_RX_CSUM_ENABLED ++ | FLAG_HAS_CTRLEXT_ON_LOAD ++ | FLAG_HAS_AMT ++ | FLAG_HAS_FLASH ++ | FLAG_HAS_JUMBO_FRAMES ++ | FLAG_APME_IN_WUC, ++ .pba = 26, ++ .max_hw_frame_size = 4096, + .init_ops = e1000_init_function_pointers_ich8lan, + .get_variants = e1000_get_variants_ich8lan, +}; @@ -20786,52 +22006,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + [board_82572] = &e1000_82572_info, + [board_82573] = &e1000_82573_info, + [board_82574] = &e1000_82574_info, ++ [board_82583] = &e1000_82583_info, + [board_80003es2lan] = &e1000_es2_info, + [board_ich8lan] = &e1000_ich8_info, + [board_ich9lan] = &e1000_ich9_info, + [board_ich10lan] = &e1000_ich10_info, ++ [board_pchlan] = &e1000_pch_info, +}; + -+ -+void e1000_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value) -+{ -+ struct e1000_adapter *adapter = hw->back; -+ -+ pci_read_config_word(adapter->pdev, reg, value); -+} -+ -+s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) -+{ -+ struct e1000_adapter *adapter = hw->back; -+ u16 cap_offset; -+ -+ 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); -+ -+ return E1000_SUCCESS; -+} -+ -+s32 e1000_alloc_zeroed_dev_spec_struct(struct e1000_hw *hw, u32 size) -+{ -+ hw->dev_spec = kzalloc(size, GFP_KERNEL); -+ -+ if (!hw->dev_spec) -+ return -ENOMEM; -+ -+ return E1000_SUCCESS; -+} -+ -+void e1000_free_dev_spec_struct(struct e1000_hw *hw) -+{ -+ if (!hw->dev_spec) -+ return; -+ -+ kfree(hw->dev_spec); -+} -+ +/** + * e1000_desc_unused - calculate if we have unused descriptors + **/ @@ -20853,26 +22035,36 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +static void e1000_receive_skb(struct e1000_adapter *adapter, + struct net_device *netdev, + struct sk_buff *skb, -+ u8 status, u16 vlan) ++ u8 status, __le16 vlan) +{ ++#ifndef CONFIG_E1000E_NAPI ++ int ret; ++ ++#endif + skb->protocol = eth_type_trans(skb, netdev); + +#ifdef CONFIG_E1000E_NAPI + if (adapter->vlgrp && (status & E1000_RXD_STAT_VP)) + vlan_hwaccel_receive_skb(skb, adapter->vlgrp, -+ le16_to_cpu(vlan) & -+ E1000_RXD_SPC_VLAN_MASK); ++ le16_to_cpu(vlan)); + else ++#ifdef NETIF_F_GRO ++ napi_gro_receive(&adapter->napi, skb); ++#else + netif_receive_skb(skb); ++#endif /* NETIF_F_GRO */ +#else + if (adapter->vlgrp && (status & E1000_RXD_STAT_VP)) -+ vlan_hwaccel_rx(skb, adapter->vlgrp, -+ le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK); ++ ret = vlan_hwaccel_rx(skb, adapter->vlgrp, le16_to_cpu(vlan)); + else -+ netif_rx(skb); ++ ret = netif_rx(skb); ++ if (unlikely(ret == NET_RX_DROP)) ++ adapter->rx_dropped_backlog++; +#endif ++#ifndef NETIF_F_GRO + + netdev->last_rx = jiffies; ++#endif +} + +/** @@ -21022,7 +22214,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + ps_page = &buffer_info->ps_pages[j]; + if (j >= adapter->rx_ps_pages) { + /* all unused desc entries get hw null ptr */ -+ rx_desc->read.buffer_addr[j+1] = ~0; ++ rx_desc->read.buffer_addr[j+1] = ~cpu_to_le64(0); + continue; + } + if (!ps_page->page) { @@ -21114,7 +22306,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +/** + * e1000_alloc_jumbo_rx_buffers - Replace used jumbo receive buffers + * @adapter: address of board private structure -+ * @rx_ring: pointer to receive ring structure + * @cleaned_count: number of buffers to allocate this pass + **/ + @@ -21211,6 +22402,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +{ + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; ++ struct e1000_hw *hw = &adapter->hw; + struct e1000_ring *rx_ring = adapter->rx_ring; + struct e1000_rx_desc *rx_desc, *next_rxd; + struct e1000_buffer *buffer_info, *next_buffer; @@ -21274,6 +22466,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + goto next_desc; + } + ++ /* adjust length to remove Ethernet CRC */ ++ if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) ++ length -= 4; ++ + total_rx_bytes += length; + total_rx_packets++; + @@ -21288,11 +22484,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + if (new_skb) { + skb_reserve(new_skb, NET_IP_ALIGN); + skb_copy_to_linear_data_offset(new_skb, -+ -NET_IP_ALIGN, -+ (skb->data - -+ NET_IP_ALIGN), -+ (length + -+ NET_IP_ALIGN)); ++ -NET_IP_ALIGN, ++ (skb->data - ++ NET_IP_ALIGN), ++ (length + ++ NET_IP_ALIGN)); + /* save the skb in buffer_info as good */ + buffer_info->skb = skb; + skb = new_skb; @@ -21308,7 +22504,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + ((u32)(rx_desc->errors) << 24), + le16_to_cpu(rx_desc->csum), skb); + -+ e1000_receive_skb(adapter, netdev, skb,status,rx_desc->special); ++ e1000_receive_skb(adapter, netdev, skb, status, rx_desc->special); + +next_desc: + rx_desc->status = 0; @@ -21329,8 +22525,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + if (cleaned_count) + adapter->alloc_rx_buf(adapter, cleaned_count); + -+ adapter->total_rx_packets += total_rx_packets; + adapter->total_rx_bytes += total_rx_bytes; ++ adapter->total_rx_packets += total_rx_packets; + adapter->net_stats.rx_bytes += total_rx_bytes; + adapter->net_stats.rx_packets += total_rx_packets; + return cleaned; @@ -21379,158 +22575,105 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +} + +/** -+ * @e1000_alloc_ring - allocate memory for a ring structure -+ **/ -+static int e1000_alloc_ring_dma(struct e1000_adapter *adapter, -+ struct e1000_ring *ring) -+{ -+ struct pci_dev *pdev = adapter->pdev; -+ -+ ring->desc = dma_alloc_coherent(&pdev->dev, ring->size, &ring->dma, -+ GFP_KERNEL); -+ if (!ring->desc) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+/** -+ * e1000e_setup_tx_resources - allocate Tx resources (Descriptors) -+ * @adapter: board private structure -+ * -+ * Return 0 on success, negative on failure -+ **/ -+int e1000_setup_tx_resources(struct e1000_adapter *adapter) -+{ -+ struct e1000_ring *tx_ring = adapter->tx_ring; -+ int err = -ENOMEM, size; -+ -+ size = sizeof(struct e1000_buffer) * tx_ring->count; -+ tx_ring->buffer_info = vmalloc(size); -+ if (!tx_ring->buffer_info) -+ goto err; -+ memset(tx_ring->buffer_info, 0, size); -+ -+ /* round up to nearest 4K */ -+ tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc); -+ tx_ring->size = ALIGN(tx_ring->size, 4096); -+ -+ err = e1000_alloc_ring_dma(adapter, tx_ring); -+ if (err) -+ goto err; -+ -+ tx_ring->next_to_use = 0; -+ tx_ring->next_to_clean = 0; -+ spin_lock_init(&adapter->tx_queue_lock); -+ -+ return 0; -+err: -+ vfree(tx_ring->buffer_info); -+ e_err("Unable to allocate memory for the transmit descriptor ring\n"); -+ return err; -+} -+ -+/** -+ * e1000e_setup_rx_resources - allocate Rx resources (Descriptors) ++ * e1000_clean_tx_irq - Reclaim resources after transmit completes + * @adapter: board private structure + * -+ * Returns 0 on success, negative on failure -+ **/ -+int e1000_setup_rx_resources(struct e1000_adapter *adapter) -+{ -+ struct e1000_ring *rx_ring = adapter->rx_ring; -+ struct e1000_buffer *buffer_info; -+ int i, size, desc_len, err = -ENOMEM; -+ -+ size = sizeof(struct e1000_buffer) * rx_ring->count; -+ rx_ring->buffer_info = vmalloc(size); -+ if (!rx_ring->buffer_info) -+ goto err; -+ memset(rx_ring->buffer_info, 0, size); -+ -+ for (i = 0; i < rx_ring->count; i++) { -+ buffer_info = &rx_ring->buffer_info[i]; -+ buffer_info->ps_pages = kcalloc(PS_PAGE_BUFFERS, -+ sizeof(struct e1000_ps_page), -+ GFP_KERNEL); -+ if (!buffer_info->ps_pages) -+ goto err_pages; -+ } -+ -+ desc_len = sizeof(union e1000_rx_desc_packet_split); -+ -+ /* Round up to nearest 4K */ -+ rx_ring->size = rx_ring->count * desc_len; -+ rx_ring->size = ALIGN(rx_ring->size, 4096); -+ -+ err = e1000_alloc_ring_dma(adapter, rx_ring); -+ if (err) -+ goto err_pages; -+ -+ rx_ring->next_to_clean = 0; -+ rx_ring->next_to_use = 0; -+ rx_ring->rx_skb_top = NULL; -+ -+ return 0; -+ -+err_pages: -+ for (i = 0; i < rx_ring->count; i++) { -+ buffer_info = &rx_ring->buffer_info[i]; -+ kfree(buffer_info->ps_pages); -+ } -+err: -+ vfree(rx_ring->buffer_info); -+ e_err("Unable to allocate memory for the transmit descriptor ring\n"); -+ return err; -+} -+ -+/** -+ * e1000_clean_tx_ring - Free Tx Buffers -+ * @adapter: board private structure ++ * the return value indicates if there is more work to do (later) + **/ -+static void e1000_clean_tx_ring(struct e1000_adapter *adapter) ++static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) +{ ++ struct net_device *netdev = adapter->netdev; ++ struct e1000_hw *hw = &adapter->hw; + struct e1000_ring *tx_ring = adapter->tx_ring; ++ struct e1000_tx_desc *tx_desc, *eop_desc; + struct e1000_buffer *buffer_info; -+ unsigned long size; -+ unsigned int i; ++ unsigned int i, eop; ++ bool cleaned = 0, retval = 1; ++ unsigned int total_tx_bytes = 0, total_tx_packets = 0; + -+ for (i = 0; i < tx_ring->count; i++) { -+ buffer_info = &tx_ring->buffer_info[i]; -+ e1000_put_txbuf(adapter, buffer_info); -+ } ++ i = tx_ring->next_to_clean; ++ eop = tx_ring->buffer_info[i].next_to_watch; ++ eop_desc = E1000_TX_DESC(*tx_ring, eop); + -+ size = sizeof(struct e1000_buffer) * tx_ring->count; -+ memset(tx_ring->buffer_info, 0, size); ++ while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { ++ for (cleaned = 0; !cleaned; ) { ++ tx_desc = E1000_TX_DESC(*tx_ring, i); ++ buffer_info = &tx_ring->buffer_info[i]; ++ cleaned = (i == eop); + -+ memset(tx_ring->desc, 0, tx_ring->size); ++ if (cleaned) { ++ struct sk_buff *skb = buffer_info->skb; ++#ifdef NETIF_F_TSO ++ unsigned int segs, bytecount; ++ segs = skb_shinfo(skb)->gso_segs ?: 1; ++ /* multiply data chunks by size of headers */ ++ bytecount = ((segs - 1) * skb_headlen(skb)) + ++ skb->len; ++ total_tx_packets += segs; ++ total_tx_bytes += bytecount; ++#else ++ total_tx_packets++; ++ total_tx_bytes += skb->len; ++#endif ++ } + -+ tx_ring->next_to_use = 0; -+ tx_ring->next_to_clean = 0; ++ e1000_put_txbuf(adapter, buffer_info); ++ tx_desc->upper.data = 0; + -+ writel(0, adapter->hw.hw_addr + tx_ring->head); -+ writel(0, adapter->hw.hw_addr + tx_ring->tail); -+} ++ i++; ++ if (i == tx_ring->count) ++ i = 0; ++#ifdef CONFIG_E1000E_NAPI ++ if (total_tx_packets >= tx_ring->count) { ++ retval = 0; ++ goto done_cleaning; ++ } ++#endif ++ } + -+/** -+ * e1000_free_tx_resources - Free Tx Resources per Queue -+ * @adapter: board private structure -+ * -+ * Free all transmit software resources -+ **/ -+void e1000_free_tx_resources(struct e1000_adapter *adapter) -+{ -+ struct pci_dev *pdev = adapter->pdev; -+ struct e1000_ring *tx_ring = adapter->tx_ring; ++ eop = tx_ring->buffer_info[i].next_to_watch; ++ eop_desc = E1000_TX_DESC(*tx_ring, eop); ++ } + -+ e1000_clean_tx_ring(adapter); ++#ifdef CONFIG_E1000E_NAPI ++done_cleaning: ++#endif ++ tx_ring->next_to_clean = i; + -+ vfree(tx_ring->buffer_info); -+ tx_ring->buffer_info = NULL; ++#define TX_WAKE_THRESHOLD 32 ++ if (cleaned && netif_carrier_ok(netdev) && ++ e1000_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD) { ++ /* Make sure that anybody stopping the queue after this ++ * sees the new next_to_clean. ++ */ ++ smp_mb(); + -+ dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc, -+ tx_ring->dma); -+ tx_ring->desc = NULL; ++ if (netif_queue_stopped(netdev) && ++ !(test_bit(__E1000_DOWN, &adapter->state))) { ++ netif_wake_queue(netdev); ++ ++adapter->restart_queue; ++ } ++ } ++ ++ if (adapter->detect_tx_hung) { ++ /* ++ * Detect a transmit hang in hardware, this serializes the ++ * check with the clearing of time_stamp and movement of i ++ */ ++ adapter->detect_tx_hung = 0; ++ if (tx_ring->buffer_info[eop].dma && ++ time_after(jiffies, tx_ring->buffer_info[eop].time_stamp ++ + (adapter->tx_timeout_factor * HZ)) ++ && !(er32(STATUS) & E1000_STATUS_TXOFF)) { ++ e1000_print_tx_hang(adapter); ++ netif_stop_queue(netdev); ++ } ++ } ++ adapter->total_tx_bytes += total_tx_bytes; ++ adapter->total_tx_packets += total_tx_packets; ++ adapter->net_stats.tx_bytes += total_tx_bytes; ++ adapter->net_stats.tx_packets += total_tx_packets; ++ return retval; +} + +/** @@ -21547,6 +22690,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter) +#endif +{ ++ struct e1000_hw *hw = &adapter->hw; + union e1000_rx_desc_packet_split *rx_desc, *next_rxd; + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; @@ -21592,8 +22736,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + buffer_info->dma = 0; + + if (!(staterr & E1000_RXD_STAT_EOP)) { -+ e_dbg("Packet Split buffers didn't pick up the full" -+ " packet\n"); ++ e_dbg("Packet Split buffers didn't pick up the full " ++ "packet\n"); + dev_kfree_skb_irq(skb); + goto next_desc; + } @@ -21606,8 +22750,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + length = le16_to_cpu(rx_desc->wb.middle.length0); + + if (!length) { -+ e_dbg("Last part of the packet spanning multiple" -+ " descriptors\n"); ++ e_dbg("Last part of the packet spanning multiple " ++ "descriptors\n"); + dev_kfree_skb_irq(skb); + goto next_desc; + } @@ -21647,6 +22791,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + pci_dma_sync_single_for_device(pdev, ps_page->dma, + PAGE_SIZE, PCI_DMA_FROMDEVICE); + ++ /* remove the CRC */ ++ if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) ++ l1 -= 4; ++ + skb_put(skb, l1); + goto copydone; + } /* if */ @@ -21669,6 +22817,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + skb->truesize += length; + } + ++ /* strip the ethernet crc, problem is we're using pages now so ++ * this whole operation can get a little cpu intensive */ ++ if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) ++ pskb_trim(skb, skb->len - 4); ++ +#ifdef CONFIG_E1000E_NAPI +copydone: +#endif @@ -21707,18 +22860,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + if (cleaned_count) + adapter->alloc_rx_buf(adapter, cleaned_count); + -+ adapter->total_rx_packets += total_rx_packets; + adapter->total_rx_bytes += total_rx_bytes; ++ adapter->total_rx_packets += total_rx_packets; + adapter->net_stats.rx_bytes += total_rx_bytes; + adapter->net_stats.rx_packets += total_rx_packets; + return cleaned; +} + +#ifdef CONFIG_E1000E_NAPI -+/* NOTE: these new jumbo frame routines rely on NAPI because of the -+ * pskb_may_pull call, which eventually must call kmap_atomic which you cannot -+ * call from hard irq context */ -+ +/** + * e1000_consume_page - helper function + **/ @@ -21750,8 +22899,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + u32 length; + unsigned int i; + int cleaned_count = 0; -+ bool cleaned = FALSE; -+ unsigned int total_rx_bytes=0, total_rx_packets=0; ++ bool cleaned = false; ++ unsigned int total_rx_bytes = 0, total_rx_packets = 0; + + i = rx_ring->next_to_clean; + rx_desc = E1000_RX_DESC(*rx_ring, i); @@ -21777,7 +22926,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + + next_buffer = &rx_ring->buffer_info[i]; + -+ cleaned = TRUE; ++ cleaned = true; + cleaned_count++; + pci_unmap_page(pdev, buffer_info->dma, PAGE_SIZE, + PCI_DMA_FROMDEVICE); @@ -21798,7 +22947,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + goto next_desc; + } + -+#define rxtop rx_ring->rx_skb_top ++#define rxtop (rx_ring->rx_skb_top) + if (!(status & E1000_RXD_STAT_EOP)) { + /* this descriptor is only the beginning (or middle) */ + if (!rxtop) { @@ -21863,378 +23012,127 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + total_rx_bytes += skb->len; + total_rx_packets++; + -+ /* eth type trans needs skb->data to point to something */ -+ if (!pskb_may_pull(skb, ETH_HLEN)) { -+ e_err("pskb_may_pull failed.\n"); -+ dev_kfree_skb(skb); -+ goto next_desc; -+ } -+ -+ e1000_receive_skb(adapter, netdev, skb, status, -+ rx_desc->special); -+ -+next_desc: -+ rx_desc->status = 0; -+ -+ /* return some buffers to hardware, one at a time is too slow */ -+ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { -+ adapter->alloc_rx_buf(adapter, cleaned_count); -+ cleaned_count = 0; -+ } -+ -+ /* use prefetched values */ -+ rx_desc = next_rxd; -+ buffer_info = next_buffer; -+ } -+ rx_ring->next_to_clean = i; -+ -+ cleaned_count = e1000_desc_unused(rx_ring); -+ if (cleaned_count) -+ adapter->alloc_rx_buf(adapter, cleaned_count); -+ -+ adapter->total_rx_packets += total_rx_packets; -+ adapter->total_rx_bytes += total_rx_bytes; -+ adapter->net_stats.rx_bytes += total_rx_bytes; -+ adapter->net_stats.rx_packets += total_rx_packets; -+ return cleaned; -+} -+#endif /* CONFIG_E1000E_NAPI */ -+ -+/** -+ * e1000_clean_rx_ring - Free Rx Buffers per Queue -+ * @adapter: board private structure -+ **/ -+static void e1000_clean_rx_ring(struct e1000_adapter *adapter) -+{ -+ struct e1000_ring *rx_ring = adapter->rx_ring; -+ struct e1000_buffer *buffer_info; -+ struct e1000_ps_page *ps_page; -+ struct pci_dev *pdev = adapter->pdev; -+ unsigned int i, j; -+ -+ /* 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->clean_rx == e1000_clean_rx_irq) -+ pci_unmap_single(pdev, buffer_info->dma, -+ adapter->rx_buffer_len, -+ PCI_DMA_FROMDEVICE); -+#ifdef CONFIG_E1000E_NAPI -+ else if (adapter->clean_rx == e1000_clean_jumbo_rx_irq) -+ pci_unmap_page(pdev, buffer_info->dma, -+ PAGE_SIZE, -+ PCI_DMA_FROMDEVICE); -+#endif -+ else if (adapter->clean_rx == e1000_clean_rx_irq_ps) -+ pci_unmap_single(pdev, buffer_info->dma, -+ adapter->rx_ps_bsize0, -+ PCI_DMA_FROMDEVICE); -+ buffer_info->dma = 0; -+ } -+ -+ if (buffer_info->page) { -+ put_page(buffer_info->page); -+ buffer_info->page = NULL; -+ } -+ -+ if (buffer_info->skb) { -+ dev_kfree_skb(buffer_info->skb); -+ buffer_info->skb = NULL; -+ } -+ -+ for (j = 0; j < PS_PAGE_BUFFERS; j++) { -+ ps_page = &buffer_info->ps_pages[j]; -+ if (!ps_page->page) -+ break; -+ pci_unmap_page(pdev, ps_page->dma, PAGE_SIZE, -+ PCI_DMA_FROMDEVICE); -+ ps_page->dma = 0; -+ put_page(ps_page->page); -+ ps_page->page = NULL; -+ } -+ } -+ -+#ifdef CONFIG_E1000E_NAPI -+ /* there also may be some cached data from a chained receive */ -+ if (rx_ring->rx_skb_top) { -+ dev_kfree_skb(rx_ring->rx_skb_top); -+ rx_ring->rx_skb_top = NULL; -+ } -+#endif -+ -+ /* Zero out the descriptor ring */ -+ memset(rx_ring->desc, 0, rx_ring->size); -+ -+ 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); -+} -+ -+/** -+ * e1000_free_rx_resources - Free Rx Resources -+ * @adapter: board private structure -+ * -+ * Free all receive software resources -+ **/ -+ -+void e1000_free_rx_resources(struct e1000_adapter *adapter) -+{ -+ struct pci_dev *pdev = adapter->pdev; -+ struct e1000_ring *rx_ring = adapter->rx_ring; -+ int i; -+ -+ e1000_clean_rx_ring(adapter); -+ -+ for (i = 0; i < rx_ring->count; i++) { -+ kfree(rx_ring->buffer_info[i].ps_pages); -+ } -+ -+ vfree(rx_ring->buffer_info); -+ rx_ring->buffer_info = NULL; -+ -+ dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc, -+ rx_ring->dma); -+ rx_ring->desc = NULL; -+} -+ -+/** -+ * e1000_update_itr - update the dynamic ITR value based on statistics -+ * @adapter: pointer to adapter -+ * @itr_setting: current adapter->itr -+ * @packets: the number of packets during this measurement interval -+ * @bytes: the number of bytes during this measurement interval -+ * -+ * Stores a new ITR value based on packets and byte -+ * counts during the last interrupt. The advantage of per interrupt -+ * computation is faster updates and more accurate ITR for the current -+ * traffic pattern. Constants in this function were computed -+ * based on theoretical maximum wire speed and thresholds were set based -+ * on testing data as well as attempting to minimize response time -+ * while increasing bulk throughput. This functionality is controlled -+ * by the InterruptThrottleRate module parameter. -+ **/ -+static unsigned int e1000_update_itr(struct e1000_adapter *adapter, -+ u16 itr_setting, int packets, -+ int bytes) -+{ -+ unsigned int retval = itr_setting; -+ -+ if (packets == 0) -+ goto update_itr_done; -+ -+ switch (itr_setting) { -+ case lowest_latency: -+ /* handle TSO and jumbo frames */ -+ if (bytes/packets > 8000) -+ retval = bulk_latency; -+ else if ((packets < 5) && (bytes > 512)) { -+ retval = low_latency; -+ } -+ break; -+ case low_latency: /* 50 usec aka 20000 ints/s */ -+ if (bytes > 10000) { -+ /* this if handles the TSO accounting */ -+ if (bytes/packets > 8000) { -+ retval = bulk_latency; -+ } else if ((packets < 10) || ((bytes/packets) > 1200)) { -+ retval = bulk_latency; -+ } else if ((packets > 35)) { -+ retval = lowest_latency; -+ } -+ } else if (bytes/packets > 2000) { -+ retval = bulk_latency; -+ } else if (packets <= 2 && bytes < 512) { -+ retval = lowest_latency; -+ } -+ break; -+ case bulk_latency: /* 250 usec aka 4000 ints/s */ -+ if (bytes > 25000) { -+ if (packets > 35) { -+ retval = low_latency; -+ } -+ } else if (bytes < 6000) { -+ retval = low_latency; -+ } -+ break; -+ } -+ -+update_itr_done: -+ return retval; -+} -+ -+static void e1000_set_itr(struct e1000_adapter *adapter) -+{ -+ struct e1000_hw *hw = &adapter->hw; -+ u16 current_itr; -+ u32 new_itr = adapter->itr; -+ -+ /* for non-gigabit speeds, just fix the interrupt rate at 4000 */ -+ if (adapter->link_speed != SPEED_1000) { -+ current_itr = 0; -+ new_itr = 4000; -+ goto set_itr_now; -+ } ++ /* eth type trans needs skb->data to point to something */ ++ if (!pskb_may_pull(skb, ETH_HLEN)) { ++ e_err("pskb_may_pull failed.\n"); ++ dev_kfree_skb(skb); ++ goto next_desc; ++ } + -+ adapter->tx_itr = e1000_update_itr(adapter, -+ adapter->tx_itr, -+ adapter->total_tx_packets, -+ adapter->total_tx_bytes); -+ /* conservative mode (itr 3) eliminates the lowest_latency setting */ -+ if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency) -+ adapter->tx_itr = low_latency; ++ e1000_receive_skb(adapter, netdev, skb, status, ++ rx_desc->special); + -+ adapter->rx_itr = e1000_update_itr(adapter, -+ adapter->rx_itr, -+ adapter->total_rx_packets, -+ adapter->total_rx_bytes); -+ /* conservative mode (itr 3) eliminates the lowest_latency setting */ -+ if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency) -+ adapter->rx_itr = low_latency; ++next_desc: ++ rx_desc->status = 0; + -+ current_itr = max(adapter->rx_itr, adapter->tx_itr); ++ /* return some buffers to hardware, one at a time is too slow */ ++ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { ++ adapter->alloc_rx_buf(adapter, cleaned_count); ++ cleaned_count = 0; ++ } + -+ switch (current_itr) { -+ /* counts and packets in update_itr are dependent on these numbers */ -+ case lowest_latency: -+ new_itr = 70000; -+ break; -+ case low_latency: -+ new_itr = 20000; /* aka hwitr = ~200 */ -+ break; -+ case bulk_latency: -+ new_itr = 4000; -+ break; -+ default: -+ break; ++ /* use prefetched values */ ++ rx_desc = next_rxd; ++ buffer_info = next_buffer; + } ++ rx_ring->next_to_clean = i; + -+set_itr_now: -+ if (new_itr != adapter->itr) { -+ /* -+ * 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) : -+ new_itr; -+ adapter->itr = new_itr; -+#ifdef CONFIG_E1000E_MSIX -+ adapter->rx_ring->itr_val = new_itr; -+ if (adapter->msix_entries) -+ adapter->rx_ring->set_itr = 1; -+ else -+#endif -+ ew32(ITR, 1000000000 / (new_itr * 256)); -+ } ++ cleaned_count = e1000_desc_unused(rx_ring); ++ if (cleaned_count) ++ adapter->alloc_rx_buf(adapter, cleaned_count); ++ ++ adapter->total_rx_bytes += total_rx_bytes; ++ adapter->total_rx_packets += total_rx_packets; ++ adapter->net_stats.rx_bytes += total_rx_bytes; ++ adapter->net_stats.rx_packets += total_rx_packets; ++ return cleaned; +} + ++#endif /* CONFIG_E1000E_NAPI */ +/** -+ * e1000_clean_tx_irq - Reclaim resources after transmit completes ++ * e1000_clean_rx_ring - Free Rx Buffers per Queue + * @adapter: board private structure -+ * -+ * the return value indicates if there is more work to do (later) + **/ -+static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) ++static void e1000_clean_rx_ring(struct e1000_adapter *adapter) +{ -+ struct net_device *netdev = adapter->netdev; -+ struct e1000_hw *hw = &adapter->hw; -+ struct e1000_ring *tx_ring = adapter->tx_ring; -+ struct e1000_tx_desc *tx_desc, *eop_desc; ++ struct e1000_ring *rx_ring = adapter->rx_ring; + struct e1000_buffer *buffer_info; -+ unsigned int i, eop; -+ bool cleaned = 0, retval = 1; -+ unsigned int total_tx_bytes = 0, total_tx_packets = 0; -+ -+ i = tx_ring->next_to_clean; -+ eop = tx_ring->buffer_info[i].next_to_watch; -+ eop_desc = E1000_TX_DESC(*tx_ring, eop); -+ -+ while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { -+ for (cleaned = 0; !cleaned; ) { -+ tx_desc = E1000_TX_DESC(*tx_ring, i); -+ buffer_info = &tx_ring->buffer_info[i]; -+ cleaned = (i == eop); ++ struct e1000_ps_page *ps_page; ++ struct pci_dev *pdev = adapter->pdev; ++ unsigned int i, j; + -+ if (cleaned) { -+ struct sk_buff *skb = buffer_info->skb; -+#ifdef NETIF_F_TSO -+ unsigned int segs, bytecount; -+ segs = skb_shinfo(skb)->gso_segs ?: 1; -+ /* multiply data chunks by size of headers */ -+ bytecount = ((segs - 1) * skb_headlen(skb)) + -+ skb->len; -+ total_tx_packets += segs; -+ total_tx_bytes += bytecount; -+#else -+ total_tx_packets++; -+ total_tx_bytes += skb->len; ++ /* 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->clean_rx == e1000_clean_rx_irq) ++ pci_unmap_single(pdev, buffer_info->dma, ++ adapter->rx_buffer_len, ++ PCI_DMA_FROMDEVICE); ++#ifdef CONFIG_E1000E_NAPI ++ else if (adapter->clean_rx == e1000_clean_jumbo_rx_irq) ++ pci_unmap_page(pdev, buffer_info->dma, ++ PAGE_SIZE, ++ PCI_DMA_FROMDEVICE); +#endif -+ } ++ else if (adapter->clean_rx == e1000_clean_rx_irq_ps) ++ pci_unmap_single(pdev, buffer_info->dma, ++ adapter->rx_ps_bsize0, ++ PCI_DMA_FROMDEVICE); ++ buffer_info->dma = 0; ++ } + -+ e1000_put_txbuf(adapter, buffer_info); -+ tx_desc->upper.data = 0; ++ if (buffer_info->page) { ++ put_page(buffer_info->page); ++ buffer_info->page = NULL; ++ } + -+ i++; -+ if (i == tx_ring->count) -+ i = 0; -+#ifdef CONFIG_E1000E_NAPI -+ if (total_tx_packets >= tx_ring->count) { -+ retval = 0; -+ goto done_cleaning; -+ } -+#endif ++ if (buffer_info->skb) { ++ dev_kfree_skb(buffer_info->skb); ++ buffer_info->skb = NULL; + } + -+ eop = tx_ring->buffer_info[i].next_to_watch; -+ eop_desc = E1000_TX_DESC(*tx_ring, eop); ++ for (j = 0; j < PS_PAGE_BUFFERS; j++) { ++ ps_page = &buffer_info->ps_pages[j]; ++ if (!ps_page->page) ++ break; ++ pci_unmap_page(pdev, ps_page->dma, PAGE_SIZE, ++ PCI_DMA_FROMDEVICE); ++ ps_page->dma = 0; ++ put_page(ps_page->page); ++ ps_page->page = NULL; ++ } + } + +#ifdef CONFIG_E1000E_NAPI -+done_cleaning: ++ /* there also may be some cached data from a chained receive */ ++ if (rx_ring->rx_skb_top) { ++ dev_kfree_skb(rx_ring->rx_skb_top); ++ rx_ring->rx_skb_top = NULL; ++ } +#endif -+ tx_ring->next_to_clean = i; + -+#define TX_WAKE_THRESHOLD 32 -+ if (cleaned && netif_carrier_ok(netdev) && -+ e1000_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD) { -+ /* -+ * Make sure that anybody stopping the queue after this -+ * sees the new next_to_clean. -+ */ -+ smp_mb(); ++ /* Zero out the descriptor ring */ ++ memset(rx_ring->desc, 0, rx_ring->size); + -+ if (netif_queue_stopped(netdev) && -+ !(test_bit(__E1000_DOWN, &adapter->state))) { -+ netif_wake_queue(netdev); -+ ++adapter->restart_queue; -+ } -+ } ++ rx_ring->next_to_clean = 0; ++ rx_ring->next_to_use = 0; + -+ if (adapter->detect_tx_hung) { -+ /* -+ * Detect a transmit hang in hardware, this serializes the -+ * check with the clearing of time_stamp and movement of i -+ */ -+ adapter->detect_tx_hung = 0; -+ if (tx_ring->buffer_info[eop].dma && -+ time_after(jiffies, tx_ring->buffer_info[eop].time_stamp -+ + (adapter->tx_timeout_factor * HZ)) -+ && !(er32(STATUS) & E1000_STATUS_TXOFF)) { -+ e1000_print_tx_hang(adapter); -+ netif_stop_queue(netdev); -+ } -+ } -+ adapter->total_tx_bytes += total_tx_bytes; -+ adapter->total_tx_packets += total_tx_packets; -+ adapter->net_stats.tx_bytes += total_tx_bytes; -+ adapter->net_stats.tx_packets += total_tx_packets; -+ return retval; ++ writel(0, adapter->hw.hw_addr + rx_ring->head); ++ writel(0, adapter->hw.hw_addr + rx_ring->tail); +} + ++static void e1000e_downshift_workaround(struct work_struct *work) ++{ ++ struct e1000_adapter *adapter = container_of(work, ++ struct e1000_adapter, downshift_task); ++ ++ e1000e_gig_downshift_workaround_ich8lan(&adapter->hw); ++} ++ ++#ifndef CONFIG_E1000E_NAPI ++static void e1000_set_itr(struct e1000_adapter *adapter); ++#endif +/** + * e1000_intr_msi - Interrupt Handler + * @irq: interrupt number @@ -22248,10 +23146,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +#ifndef CONFIG_E1000E_NAPI + int i; +#endif -+ /* read ICR disables interrupts using IAM */ + u32 icr = er32(ICR); + -+ if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { ++ /* ++ * read ICR disables interrupts using IAM ++ */ ++ ++ if (icr & E1000_ICR_LSC) { + hw->mac.get_link_status = 1; + /* + * ICH8 workaround-- Call gig speed drop workaround on cable @@ -22259,7 +23160,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + */ + if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) && + (!(er32(STATUS) & E1000_STATUS_LU))) -+ e1000_gig_downshift_workaround_ich8lan(hw); ++ schedule_work(&adapter->downshift_task); + + /* + * 80003ES2LAN workaround-- For packet buffer work-around on @@ -22279,12 +23180,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + } + +#ifdef CONFIG_E1000E_NAPI -+ if (netif_rx_schedule_prep(netdev, &adapter->napi)) { ++ if (napi_schedule_prep(&adapter->napi)) { + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; + adapter->total_rx_bytes = 0; + adapter->total_rx_packets = 0; -+ __netif_rx_schedule(netdev, &adapter->napi); ++ __napi_schedule(&adapter->napi); + } +#else + adapter->total_tx_bytes = 0; @@ -22322,7 +23223,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +#endif + u32 rctl, icr = er32(ICR); + -+ if (!icr) ++ if (!icr || test_bit(__E1000_DOWN, &adapter->state)) + return IRQ_NONE; /* Not our interrupt */ + +#ifdef CONFIG_E1000E_NAPI @@ -22334,7 +23235,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + return IRQ_NONE; + +#endif /* CONFIG_E1000E_NAPI */ -+ if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { ++ /* ++ * Interrupt Auto-Mask...upon reading ICR, ++ * interrupts are masked. No need for the ++ * IMC write ++ */ ++ ++ if (icr & E1000_ICR_LSC) { + hw->mac.get_link_status = 1; + /* + * ICH8 workaround-- Call gig speed drop workaround on cable @@ -22342,7 +23249,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + */ + if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) && + (!(er32(STATUS) & E1000_STATUS_LU))) -+ e1000_gig_downshift_workaround_ich8lan(hw); ++ schedule_work(&adapter->downshift_task); + + /* + * 80003ES2LAN workaround-- @@ -22363,12 +23270,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + } + +#ifdef CONFIG_E1000E_NAPI -+ if (netif_rx_schedule_prep(netdev, &adapter->napi)) { ++ if (napi_schedule_prep(&adapter->napi)) { + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; + adapter->total_rx_bytes = 0; + adapter->total_rx_packets = 0; -+ __netif_rx_schedule(netdev, &adapter->napi); ++ __napi_schedule(&adapter->napi); + } +#else + adapter->total_tx_bytes = 0; @@ -22398,8 +23305,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + struct e1000_hw *hw = &adapter->hw; + u32 icr = er32(ICR); + -+ if (!(icr & E1000_ICR_INT_ASSERTED)) -+ { ++ if (!(icr & E1000_ICR_INT_ASSERTED)) { + ew32(IMS, E1000_IMS_OTHER); + return IRQ_NONE; + } @@ -22460,16 +23366,16 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + adapter->hw.hw_addr + adapter->rx_ring->itr_register); + adapter->rx_ring->set_itr = 0; + } -+ ++ +#ifdef CONFIG_E1000E_NAPI -+ if (netif_rx_schedule_prep(netdev, &adapter->napi)) { ++ if (napi_schedule_prep(&adapter->napi)) { + adapter->total_rx_bytes = 0; + adapter->total_rx_packets = 0; +#ifndef CONFIG_E1000E_SEPARATE_TX_HANDLER + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; +#endif /* CONFIG_E1000E_SEPARATE_TX_HANDLER */ -+ __netif_rx_schedule(netdev, &adapter->napi); ++ __napi_schedule(&adapter->napi); + } +#else + adapter->total_rx_bytes = 0; @@ -22573,7 +23479,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + e1e_flush(); +} + -+void e1000_reset_interrupt_capability(struct e1000_adapter *adapter) ++void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter) +{ + if (adapter->msix_entries) { + pci_disable_msix(adapter->pdev); @@ -22588,12 +23494,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +} + +/** -+ * e1000_set_interrupt_capability - set MSI or MSI-X if supported ++ * e1000e_set_interrupt_capability - set MSI or MSI-X if supported + * + * Attempt to configure interrupts using the best available + * capabilities of the hardware and kernel. + **/ -+void e1000_set_interrupt_capability(struct e1000_adapter *adapter) ++void e1000e_set_interrupt_capability(struct e1000_adapter *adapter) +{ + int err; + int numvecs, i; @@ -22611,19 +23517,19 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + 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, + adapter->msix_entries, -+ numvecs); ++ numvecs); + if (err == 0) + return; + } + /* MSI-X failed, so fall through and try MSI */ + e_err("Failed to initialize MSI-X interrupts. " + "Falling back to MSI interrupts.\n"); -+ e1000_reset_interrupt_capability(adapter); ++ e1000e_reset_interrupt_capability(adapter); + } + adapter->int_mode = E1000E_INT_MODE_MSI; + /* Fall through */ @@ -22657,7 +23563,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + + if (strlen(netdev->name) < (IFNAMSIZ - 5)) +#ifdef CONFIG_E1000E_SEPARATE_TX_HANDLER -+ sprintf(adapter->rx_ring->name, "%s-rx0", netdev->name); ++ sprintf(adapter->rx_ring->name, "%s-rx-0", netdev->name); +#else + sprintf(adapter->rx_ring->name, "%s-Q0", netdev->name); +#endif @@ -22665,7 +23571,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + memcpy(adapter->rx_ring->name, netdev->name, IFNAMSIZ); + err = request_irq(adapter->msix_entries[vector].vector, + &e1000_intr_msix_rx, 0, adapter->rx_ring->name, -+ netdev); ++ netdev); + if (err) + goto out; + adapter->rx_ring->itr_register = E1000_EITR_82574(vector); @@ -22674,53 +23580,31 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + +#ifdef CONFIG_E1000E_SEPARATE_TX_HANDLER + if (strlen(netdev->name) < (IFNAMSIZ - 5)) -+ sprintf(adapter->tx_ring->name, "%s-tx0", netdev->name); ++ sprintf(adapter->tx_ring->name, "%s-tx-0", netdev->name); + else + memcpy(adapter->tx_ring->name, netdev->name, IFNAMSIZ); + err = request_irq(adapter->msix_entries[vector].vector, + &e1000_intr_msix_tx, 0, adapter->tx_ring->name, -+ netdev); ++ netdev); + if (err) + goto out; + adapter->tx_ring->itr_register = E1000_EITR_82574(vector); -+ adapter->tx_ring->itr_val = adapter->itr; -+ vector++; -+ -+#endif /* CONFIG_E1000E_SEPARATE_TX_HANDLER */ -+ err = request_irq(adapter->msix_entries[vector].vector, -+ &e1000_msix_other, 0, netdev->name, netdev); -+ if (err) -+ goto out; -+ -+ e1000_configure_msix(adapter); -+ return 0; -+out: -+ return err; -+} -+ -+#endif /* CONFIG_E1000E_MSIX */ -+/** -+ * e1000_alloc_queues - Allocate memory for all rings -+ * @adapter: board private structure to initialize -+ **/ -+static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter) -+{ -+ adapter->tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); -+ if (!adapter->tx_ring) -+ goto err; ++ adapter->tx_ring->itr_val = adapter->itr; ++ vector++; + -+ adapter->rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); -+ if (!adapter->rx_ring) -+ goto err; ++#endif /* CONFIG_E1000E_SEPARATE_TX_HANDLER */ ++ err = request_irq(adapter->msix_entries[vector].vector, ++ &e1000_msix_other, 0, netdev->name, netdev); ++ if (err) ++ goto out; + ++ e1000_configure_msix(adapter); + return 0; -+err: -+ e_err("Unable to allocate memory for queues\n"); -+ kfree(adapter->rx_ring); -+ kfree(adapter->tx_ring); -+ return -ENOMEM; ++out: ++ return err; +} + ++#endif /* CONFIG_E1000E_MSIX */ +/** + * e1000_request_irq - initialize interrupts + * @@ -22730,36 +23614,37 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +static int e1000_request_irq(struct e1000_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; ++#ifndef CONFIG_E1000E_MSIX ++ int irq_flags = IRQF_SHARED; ++#endif + int err; -+#ifdef CONFIG_E1000E_MSIX + ++#ifdef CONFIG_E1000E_MSIX + if (adapter->msix_entries) { + err = e1000_request_msix(adapter); + if (!err) + return err; + /* fall back to MSI */ -+ e1000_reset_interrupt_capability(adapter); ++ e1000e_reset_interrupt_capability(adapter); + adapter->int_mode = E1000E_INT_MODE_MSI; -+ e1000_set_interrupt_capability(adapter); ++ e1000e_set_interrupt_capability(adapter); + } + if (adapter->flags & FLAG_MSI_ENABLED) { + err = request_irq(adapter->pdev->irq, &e1000_intr_msi, 0, -+ netdev->name, netdev); ++ netdev->name, netdev); + if (!err) + return err; + + /* fall back to legacy interrupt */ -+ e1000_reset_interrupt_capability(adapter); ++ e1000e_reset_interrupt_capability(adapter); + adapter->int_mode = E1000E_INT_MODE_LEGACY; + } + + err = request_irq(adapter->pdev->irq, &e1000_intr, IRQF_SHARED, -+ netdev->name, netdev); ++ netdev->name, netdev); + if (err) + e_err("Unable to allocate interrupt, Error: %d\n", err); +#else -+ int irq_flags = IRQF_SHARED; -+ + if (!(adapter->flags & FLAG_MSI_TEST_FAILED)) { + err = pci_enable_msi(adapter->pdev); + if (!err) { @@ -22816,90 +23701,427 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +} + +/** -+ * e1000_irq_disable - Mask off interrupt generation on the NIC ++ * e1000_irq_disable - Mask off interrupt generation on the NIC ++ **/ ++static void e1000_irq_disable(struct e1000_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ ++ ew32(IMC, ~0); ++#ifdef CONFIG_E1000E_MSIX ++ if (adapter->msix_entries) ++ ew32(EIAC_82574, 0); ++#endif /* CONFIG_E1000E_MSIX */ ++ e1e_flush(); ++ synchronize_irq(adapter->pdev->irq); ++} ++ ++/** ++ * e1000_irq_enable - Enable default interrupt generation settings ++ **/ ++static void e1000_irq_enable(struct e1000_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ ++#ifdef CONFIG_E1000E_MSIX ++ if (adapter->msix_entries) { ++ ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574); ++ ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC); ++ } else { ++ ew32(IMS, IMS_ENABLE_MASK); ++ } ++#else ++ ew32(IMS, IMS_ENABLE_MASK); ++#endif /* CONFIG_E1000E_MSIX */ ++ e1e_flush(); ++} ++ ++/** ++ * e1000_get_hw_control - get control of the h/w from f/w ++ * @adapter: address of board private structure ++ * ++ * e1000_get_hw_control sets {CTRL_EXT|SWSM}:DRV_LOAD bit. ++ * For ASF and Pass Through versions of f/w this means that ++ * the driver is loaded. For AMT version (only with 82573) ++ * of the f/w this means that the network i/f is open. ++ **/ ++static void e1000_get_hw_control(struct e1000_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 ctrl_ext; ++ u32 swsm; ++ ++ /* Let firmware know the driver has taken over */ ++ if (adapter->flags & FLAG_HAS_SWSM_ON_LOAD) { ++ swsm = er32(SWSM); ++ ew32(SWSM, swsm | E1000_SWSM_DRV_LOAD); ++ } else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) { ++ ctrl_ext = er32(CTRL_EXT); ++ ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); ++ } ++} ++ ++/** ++ * e1000_release_hw_control - release control of the h/w to f/w ++ * @adapter: address of board private structure ++ * ++ * e1000_release_hw_control resets {CTRL_EXT|SWSM}:DRV_LOAD bit. ++ * For ASF and Pass Through versions of f/w this means that the ++ * driver is no longer loaded. For AMT version (only with 82573) i ++ * of the f/w this means that the network i/f is closed. ++ * ++ **/ ++static void e1000_release_hw_control(struct e1000_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 ctrl_ext; ++ u32 swsm; ++ ++ /* Let firmware taken over control of h/w */ ++ if (adapter->flags & FLAG_HAS_SWSM_ON_LOAD) { ++ swsm = er32(SWSM); ++ ew32(SWSM, swsm & ~E1000_SWSM_DRV_LOAD); ++ } else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) { ++ ctrl_ext = er32(CTRL_EXT); ++ ew32(CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); ++ } ++} ++ ++/** ++ * @e1000_alloc_ring - allocate memory for a ring structure ++ **/ ++static int e1000_alloc_ring_dma(struct e1000_adapter *adapter, ++ struct e1000_ring *ring) ++{ ++ struct pci_dev *pdev = adapter->pdev; ++ ++ ring->desc = dma_alloc_coherent(&pdev->dev, ring->size, &ring->dma, ++ GFP_KERNEL); ++ if (!ring->desc) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++/** ++ * e1000e_setup_tx_resources - allocate Tx resources (Descriptors) ++ * @adapter: board private structure ++ * ++ * Return 0 on success, negative on failure ++ **/ ++int e1000e_setup_tx_resources(struct e1000_adapter *adapter) ++{ ++ struct e1000_ring *tx_ring = adapter->tx_ring; ++ int err = -ENOMEM, size; ++ ++ size = sizeof(struct e1000_buffer) * tx_ring->count; ++ tx_ring->buffer_info = vmalloc(size); ++ if (!tx_ring->buffer_info) ++ goto err; ++ memset(tx_ring->buffer_info, 0, size); ++ ++ /* round up to nearest 4K */ ++ tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc); ++ tx_ring->size = ALIGN(tx_ring->size, 4096); ++ ++ err = e1000_alloc_ring_dma(adapter, tx_ring); ++ if (err) ++ goto err; ++ ++ tx_ring->next_to_use = 0; ++ tx_ring->next_to_clean = 0; ++ ++ return 0; ++err: ++ vfree(tx_ring->buffer_info); ++ e_err("Unable to allocate memory for the transmit descriptor ring\n"); ++ return err; ++} ++ ++/** ++ * e1000e_setup_rx_resources - allocate Rx resources (Descriptors) ++ * @adapter: board private structure ++ * ++ * Returns 0 on success, negative on failure ++ **/ ++int e1000e_setup_rx_resources(struct e1000_adapter *adapter) ++{ ++ struct e1000_ring *rx_ring = adapter->rx_ring; ++ struct e1000_buffer *buffer_info; ++ int i, size, desc_len, err = -ENOMEM; ++ ++ size = sizeof(struct e1000_buffer) * rx_ring->count; ++ rx_ring->buffer_info = vmalloc(size); ++ if (!rx_ring->buffer_info) ++ goto err; ++ memset(rx_ring->buffer_info, 0, size); ++ ++ for (i = 0; i < rx_ring->count; i++) { ++ buffer_info = &rx_ring->buffer_info[i]; ++ buffer_info->ps_pages = kcalloc(PS_PAGE_BUFFERS, ++ sizeof(struct e1000_ps_page), ++ GFP_KERNEL); ++ if (!buffer_info->ps_pages) ++ goto err_pages; ++ } ++ ++ desc_len = sizeof(union e1000_rx_desc_packet_split); ++ ++ /* Round up to nearest 4K */ ++ rx_ring->size = rx_ring->count * desc_len; ++ rx_ring->size = ALIGN(rx_ring->size, 4096); ++ ++ err = e1000_alloc_ring_dma(adapter, rx_ring); ++ if (err) ++ goto err_pages; ++ ++ rx_ring->next_to_clean = 0; ++ rx_ring->next_to_use = 0; ++ rx_ring->rx_skb_top = NULL; ++ ++ return 0; ++ ++err_pages: ++ for (i = 0; i < rx_ring->count; i++) { ++ buffer_info = &rx_ring->buffer_info[i]; ++ kfree(buffer_info->ps_pages); ++ } ++err: ++ vfree(rx_ring->buffer_info); ++ e_err("Unable to allocate memory for the receive descriptor ring\n"); ++ return err; ++} ++ ++/** ++ * e1000_clean_tx_ring - Free Tx Buffers ++ * @adapter: board private structure ++ **/ ++static void e1000_clean_tx_ring(struct e1000_adapter *adapter) ++{ ++ struct e1000_ring *tx_ring = adapter->tx_ring; ++ struct e1000_buffer *buffer_info; ++ unsigned long size; ++ unsigned int i; ++ ++ for (i = 0; i < tx_ring->count; i++) { ++ buffer_info = &tx_ring->buffer_info[i]; ++ e1000_put_txbuf(adapter, buffer_info); ++ } ++ ++ size = sizeof(struct e1000_buffer) * tx_ring->count; ++ memset(tx_ring->buffer_info, 0, size); ++ ++ 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); ++} ++ ++/** ++ * e1000e_free_tx_resources - Free Tx Resources per Queue ++ * @adapter: board private structure ++ * ++ * Free all transmit software resources ++ **/ ++void e1000e_free_tx_resources(struct e1000_adapter *adapter) ++{ ++ struct pci_dev *pdev = adapter->pdev; ++ struct e1000_ring *tx_ring = adapter->tx_ring; ++ ++ e1000_clean_tx_ring(adapter); ++ ++ vfree(tx_ring->buffer_info); ++ tx_ring->buffer_info = NULL; ++ ++ dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc, ++ tx_ring->dma); ++ tx_ring->desc = NULL; ++} ++ ++/** ++ * e1000e_free_rx_resources - Free Rx Resources ++ * @adapter: board private structure ++ * ++ * Free all receive software resources + **/ -+static void e1000_irq_disable(struct e1000_adapter *adapter) ++ ++void e1000e_free_rx_resources(struct e1000_adapter *adapter) +{ -+ struct e1000_hw *hw = &adapter->hw; ++ struct pci_dev *pdev = adapter->pdev; ++ struct e1000_ring *rx_ring = adapter->rx_ring; ++ int i; + -+ ew32(IMC, ~0); -+#ifdef CONFIG_E1000E_MSIX -+ if (adapter->msix_entries) { -+ ew32(EIAC_82574, 0); ++ e1000_clean_rx_ring(adapter); ++ ++ for (i = 0; i < rx_ring->count; i++) { ++ kfree(rx_ring->buffer_info[i].ps_pages); + } -+#endif /* CONFIG_E1000E_MSIX */ -+ e1e_flush(); -+ synchronize_irq(adapter->pdev->irq); ++ ++ vfree(rx_ring->buffer_info); ++ rx_ring->buffer_info = NULL; ++ ++ dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc, ++ rx_ring->dma); ++ rx_ring->desc = NULL; +} + +/** -+ * e1000_irq_enable - Enable default interrupt generation settings ++ * e1000_update_itr - update the dynamic ITR value based on statistics ++ * @adapter: pointer to adapter ++ * @itr_setting: current adapter->itr ++ * @packets: the number of packets during this measurement interval ++ * @bytes: the number of bytes during this measurement interval ++ * ++ * Stores a new ITR value based on packets and byte ++ * counts during the last interrupt. The advantage of per interrupt ++ * computation is faster updates and more accurate ITR for the current ++ * traffic pattern. Constants in this function were computed ++ * based on theoretical maximum wire speed and thresholds were set based ++ * on testing data as well as attempting to minimize response time ++ * while increasing bulk throughput. This functionality is controlled ++ * by the InterruptThrottleRate module parameter. + **/ -+static void e1000_irq_enable(struct e1000_adapter *adapter) ++static unsigned int e1000_update_itr(struct e1000_adapter *adapter, ++ u16 itr_setting, int packets, ++ int bytes) +{ -+ struct e1000_hw *hw = &adapter->hw; -+#ifdef CONFIG_E1000E_MSIX ++ unsigned int retval = itr_setting; + -+ if (adapter->msix_entries) { -+ ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574); -+ ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC); -+ } else { -+ ew32(IMS, IMS_ENABLE_MASK); ++ if (packets == 0) ++ goto update_itr_done; ++ ++ switch (itr_setting) { ++ case lowest_latency: ++ /* handle TSO and jumbo frames */ ++ if (bytes/packets > 8000) ++ retval = bulk_latency; ++ else if ((packets < 5) && (bytes > 512)) { ++ retval = low_latency; ++ } ++ break; ++ case low_latency: /* 50 usec aka 20000 ints/s */ ++ if (bytes > 10000) { ++ /* this if handles the TSO accounting */ ++ if (bytes/packets > 8000) { ++ retval = bulk_latency; ++ } else if ((packets < 10) || ((bytes/packets) > 1200)) { ++ retval = bulk_latency; ++ } else if ((packets > 35)) { ++ retval = lowest_latency; ++ } ++ } else if (bytes/packets > 2000) { ++ retval = bulk_latency; ++ } else if (packets <= 2 && bytes < 512) { ++ retval = lowest_latency; ++ } ++ break; ++ case bulk_latency: /* 250 usec aka 4000 ints/s */ ++ if (bytes > 25000) { ++ if (packets > 35) { ++ retval = low_latency; ++ } ++ } else if (bytes < 6000) { ++ retval = low_latency; ++ } ++ break; + } -+#else -+ ew32(IMS, IMS_ENABLE_MASK); -+#endif /* CONFIG_E1000E_MSIX */ ++ ++update_itr_done: ++ return retval; +} + -+/** -+ * e1000_get_hw_control - get control of the h/w from f/w -+ * @adapter: address of board private structure -+ * -+ * e1000_get_hw_control sets {CTRL_EXT|SWSM}:DRV_LOAD bit. -+ * For ASF and Pass Through versions of f/w this means that -+ * the driver is loaded. For AMT version (only with 82573) -+ * of the f/w this means that the network i/f is open. -+ **/ -+static void e1000_get_hw_control(struct e1000_adapter *adapter) ++static void e1000_set_itr(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; -+ u32 ctrl_ext; -+ u32 swsm; ++ u16 current_itr; ++ u32 new_itr = adapter->itr; + -+ /* Let firmware know the driver has taken over */ -+ if (adapter->flags & FLAG_HAS_SWSM_ON_LOAD) { -+ swsm = er32(SWSM); -+ ew32(SWSM, swsm | E1000_SWSM_DRV_LOAD); -+ } else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) { -+ ctrl_ext = er32(CTRL_EXT); -+ ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); ++ /* for non-gigabit speeds, just fix the interrupt rate at 4000 */ ++ if (adapter->link_speed != SPEED_1000) { ++ current_itr = 0; ++ new_itr = 4000; ++ goto set_itr_now; ++ } ++ ++ adapter->tx_itr = e1000_update_itr(adapter, ++ adapter->tx_itr, ++ adapter->total_tx_packets, ++ adapter->total_tx_bytes); ++ /* conservative mode (itr 3) eliminates the lowest_latency setting */ ++ if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency) ++ adapter->tx_itr = low_latency; ++ ++ adapter->rx_itr = e1000_update_itr(adapter, ++ adapter->rx_itr, ++ adapter->total_rx_packets, ++ adapter->total_rx_bytes); ++ /* conservative mode (itr 3) eliminates the lowest_latency setting */ ++ if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency) ++ adapter->rx_itr = low_latency; ++ ++ current_itr = max(adapter->rx_itr, adapter->tx_itr); ++ ++ switch (current_itr) { ++ /* counts and packets in update_itr are dependent on these numbers */ ++ case lowest_latency: ++ new_itr = 70000; ++ break; ++ case low_latency: ++ new_itr = 20000; /* aka hwitr = ~200 */ ++ break; ++ case bulk_latency: ++ new_itr = 4000; ++ break; ++ default: ++ break; ++ } ++ ++set_itr_now: ++ if (new_itr != adapter->itr) { ++ /* ++ * 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) : ++ new_itr; ++ adapter->itr = new_itr; ++#ifdef CONFIG_E1000E_MSIX ++ adapter->rx_ring->itr_val = new_itr; ++ if (adapter->msix_entries) ++ adapter->rx_ring->set_itr = 1; ++ else ++ ew32(ITR, 1000000000 / (new_itr * 256)); ++#else ++ ew32(ITR, 1000000000 / (new_itr * 256)); ++#endif + } +} + +/** -+ * e1000_release_hw_control - release control of the h/w to f/w -+ * @adapter: address of board private structure -+ * -+ * e1000_release_hw_control resets {CTRL_EXT|SWSM}:DRV_LOAD bit. -+ * For ASF and Pass Through versions of f/w this means that the -+ * driver is no longer loaded. For AMT version (only with 82573) i -+ * of the f/w this means that the network i/f is closed. -+ * ++ * e1000_alloc_queues - Allocate memory for all rings ++ * @adapter: board private structure to initialize + **/ -+static void e1000_release_hw_control(struct e1000_adapter *adapter) ++static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter) +{ -+ struct e1000_hw *hw = &adapter->hw; -+ u32 ctrl_ext; -+ u32 swsm; ++ adapter->tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); ++ if (!adapter->tx_ring) ++ goto err; + -+ /* Let firmware taken over control of h/w */ -+ if (adapter->flags & FLAG_HAS_SWSM_ON_LOAD) { -+ swsm = er32(SWSM); -+ ew32(SWSM, swsm & ~E1000_SWSM_DRV_LOAD); -+ } else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) { -+ ctrl_ext = er32(CTRL_EXT); -+ ew32(CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); -+ } ++ adapter->rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); ++ if (!adapter->rx_ring) ++ goto err; ++ ++ return 0; ++err: ++ e_err("Unable to allocate memory for queues\n"); ++ kfree(adapter->rx_ring); ++ kfree(adapter->tx_ring); ++ return -ENOMEM; +} + +#ifdef CONFIG_E1000E_NAPI @@ -22912,35 +24134,30 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +{ + struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, + napi); -+ struct net_device *netdev = adapter->netdev; + int tx_clean_complete = 1, work_done = 0; +#ifdef CONFIG_E1000E_MSIX + struct e1000_hw *hw = &adapter->hw; -+ -+ if (adapter->msix_entries && -+ !(adapter->rx_ring->ims_val & adapter->tx_ring->ims_val)) -+ goto clean_rx; -+ +#endif -+ /* -+ * e1000_poll is called per-cpu. This lock protects -+ * tx_ring from being cleaned by multiple cpus -+ * simultaneously. A failure obtaining the lock means -+ * tx_ring is currently being cleaned anyway. -+ */ -+ if (spin_trylock(&adapter->tx_queue_lock)) { -+ tx_clean_complete &= e1000_clean_tx_irq(adapter); -+ spin_unlock(&adapter->tx_queue_lock); -+ } + +#ifdef CONFIG_E1000E_MSIX -+clean_rx: ++ if (!adapter->msix_entries || ++ (adapter->rx_ring->ims_val & adapter->tx_ring->ims_val)) +#endif ++ tx_clean_complete = e1000_clean_tx_irq(adapter); ++ + adapter->clean_rx(adapter, &work_done, budget); + ++ if (!tx_clean_complete) ++ work_done = budget; ++ ++#ifndef HAVE_NETDEV_NAPI_LIST ++ if (!netif_running(adapter->netdev)) ++ work_done = 0; ++ ++#endif + /* If Tx completed and all Rx work done, exit the polling mode */ -+ if ((tx_clean_complete && (work_done == 0)) || !netif_running(netdev)) { -+ netif_rx_complete(netdev, napi); ++ if (work_done < budget) { ++ napi_complete(napi); + if (adapter->itr_setting & 3) + e1000_set_itr(adapter); + if (!test_bit(__E1000_DOWN, &adapter->state)) { @@ -22951,12 +24168,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +#endif + e1000_irq_enable(adapter); + } -+ return 0; + } + -+ if (!tx_clean_complete) -+ work_done = budget; -+ + return work_done; +} + @@ -22977,8 +24190,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + index = (vid >> 5) & 0x7F; + vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, index); + vfta |= (1 << (vid & 0x1F)); -+ if (hw->mac.ops.write_vfta) -+ hw->mac.ops.write_vfta(hw, index, vfta); ++ e1000e_write_vfta(hw, index, vfta); + /* + * Copy feature flags from netdev to the vlan netdev for this vid. + * This allows things like TSO to bubble down to our vlan device. @@ -22997,6 +24209,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + if (!test_bit(__E1000_DOWN, &adapter->state)) + e1000_irq_disable(adapter); + vlan_group_set_device(adapter->vlgrp, vid, NULL); ++ + if (!test_bit(__E1000_DOWN, &adapter->state)) + e1000_irq_enable(adapter); + @@ -23012,8 +24225,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + index = (vid >> 5) & 0x7F; + vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, index); + vfta &= ~(1 << (vid & 0x1F)); -+ if (hw->mac.ops.write_vfta) -+ hw->mac.ops.write_vfta(hw, index, vfta); ++ e1000e_write_vfta(hw, index, vfta); +} + +static void e1000_update_mng_vlan(struct e1000_adapter *adapter) @@ -23063,7 +24275,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { + /* enable VLAN receive filtering */ + rctl = er32(RCTL); -+ rctl |= E1000_RCTL_VFE; + rctl &= ~E1000_RCTL_CFIEN; + ew32(RCTL, rctl); + e1000_update_mng_vlan(adapter); @@ -23075,10 +24286,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + ew32(CTRL, ctrl); + + if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { -+ /* disable VLAN filtering */ -+ rctl = er32(RCTL); -+ rctl &= ~E1000_RCTL_VFE; -+ ew32(RCTL, rctl); + if (adapter->mng_vlan_id != + (u16)E1000_MNG_VLAN_NONE) { + e1000_vlan_rx_kill_vid(netdev, @@ -23150,7 +24357,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + /* Setup the HW Tx Head and Tail descriptor pointers */ + tdba = tx_ring->dma; + tdlen = tx_ring->count * sizeof(struct e1000_tx_desc); -+ ew32(TDBAL(0), (tdba & DMA_32BIT_MASK)); ++ ew32(TDBAL(0), (tdba & DMA_BIT_MASK(32))); + ew32(TDBAH(0), (tdba >> 32)); + ew32(TDLEN(0), tdlen); + ew32(TDH(0), 0); @@ -23202,7 +24409,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + ew32(TARC(1), tarc); + } + -+ hw->mac.ops.config_collision_dist(hw); ++ e1000e_config_collision_dist(hw); + + /* Setup Transmit Descriptor Settings for eop descriptor */ + adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS; @@ -23248,8 +24455,28 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + else + rctl |= E1000_RCTL_LPE; + -+ /* Enable hardware CRC frame stripping */ -+ rctl |= E1000_RCTL_SECRC; ++ /* Some systems expect that the CRC is included in SMBUS traffic. The ++ * hardware strips the CRC before sending to both SMBUS (BMC) and to ++ * host memory when this is enabled */ ++ if (adapter->flags2 & FLAG2_CRC_STRIPPING) ++ rctl |= E1000_RCTL_SECRC; ++ ++ /* Workaround Si errata on 82577 PHY */ ++ if ((hw->phy.type == e1000_phy_82577) && (rctl & E1000_RCTL_LPE)) { ++ u16 phy_data; ++ ++ e1e_rphy(hw, PHY_REG(770, 26), &phy_data); ++ phy_data &= 0xfff8; ++ phy_data |= (1 << 2); ++ e1e_wphy(hw, PHY_REG(770, 26), phy_data); ++ ++ e1e_rphy(hw, 22, &phy_data); ++ phy_data &= 0x0fff; ++ phy_data |= (1 << 14); ++ e1e_wphy(hw, 0x10, 0x2823); ++ e1e_wphy(hw, 0x11, 0x0003); ++ e1e_wphy(hw, 22, phy_data); ++ } + + /* Setup buffer sizes */ + rctl &= ~E1000_RCTL_SZ_4096; @@ -23391,8 +24618,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + ew32(ITR, 1000000000 / (adapter->itr * 256)); + + ctrl_ext = er32(CTRL_EXT); -+ /* Reset delay timers after every interrupt */ -+ ctrl_ext |= E1000_CTRL_EXT_INT_TIMER_CLR; +#ifdef CONFIG_E1000E_NAPI + /* Auto-Mask interrupts upon ICR access */ + ctrl_ext |= E1000_CTRL_EXT_IAME; @@ -23406,7 +24631,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + * the Base and Length of the Rx Descriptor Ring + */ + rdba = rx_ring->dma; -+ ew32(RDBAL(0), (rdba & DMA_32BIT_MASK)); ++ ew32(RDBAL(0), (rdba & DMA_BIT_MASK(32))); + ew32(RDBAH(0), (rdba >> 32)); + ew32(RDLEN(0), rdlen); + ew32(RDH(0), 0); @@ -23436,21 +24661,23 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + * packet size is equal or larger than the specified value (in 8 byte + * units), e.g. using jumbo frames when setting to E1000_ERT_2048 + */ -+ if ((adapter->flags & FLAG_HAS_ERT) && -+ (adapter->netdev->mtu > ETH_DATA_LEN)) { -+ u32 rxdctl = er32(RXDCTL(0)); -+ ew32(RXDCTL(0), rxdctl | 0x3); -+ ew32(ERT, E1000_ERT_2048 | (1 << 13)); -+ /* -+ * With jumbo frames and early-receive enabled, excessive -+ * C4->C2 latencies result in dropped transactions. -+ */ -+ pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, -+ e1000e_driver_name, 55); -+ } else { -+ pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, -+ e1000e_driver_name, -+ PM_QOS_DEFAULT_VALUE); ++ if (adapter->flags & FLAG_HAS_ERT) { ++ if (adapter->netdev->mtu > ETH_DATA_LEN) { ++ u32 rxdctl = er32(RXDCTL(0)); ++ ew32(RXDCTL(0), rxdctl | 0x3); ++ ew32(ERT, E1000_ERT_2048 | (1 << 13)); ++ /* ++ * With jumbo frames and early-receive enabled, ++ * excessive C-state transition latencies result in ++ * dropped transactions. ++ */ ++ pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, ++ adapter->netdev->name, 55); ++ } else { ++ pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, ++ adapter->netdev->name, ++ PM_QOS_DEFAULT_VALUE); ++ } + } + + /* Enable Receives */ @@ -23458,6 +24685,21 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +} + +/** ++ * e1000_update_mc_addr_list - 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 ++ * ++ * Updates the Multicast Table Array. ++ * The caller must have a packed mc_addr_list of multicast addresses. ++ **/ ++static void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list, ++ u32 mc_addr_count) ++{ ++ hw->mac.ops.update_mc_addr_list(hw, mc_addr_list, mc_addr_count); ++} ++ ++/** + * e1000_set_multi - Multicast and Promiscuous mode set + * @netdev: network interface device structure + * @@ -23470,7 +24712,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; -+ struct e1000_mac_info *mac = &hw->mac; + struct dev_mc_list *mc_ptr; + u8 *mta_list; + u32 rctl; @@ -23482,11 +24723,16 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + + if (netdev->flags & IFF_PROMISC) { + rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); -+ } else if (netdev->flags & IFF_ALLMULTI) { -+ rctl |= E1000_RCTL_MPE; -+ rctl &= ~E1000_RCTL_UPE; ++ rctl &= ~E1000_RCTL_VFE; + } else { -+ rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); ++ if (netdev->flags & IFF_ALLMULTI) { ++ rctl |= E1000_RCTL_MPE; ++ rctl &= ~E1000_RCTL_UPE; ++ } else { ++ rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); ++ } ++ if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) ++ rctl |= E1000_RCTL_VFE; + } + + ew32(RCTL, rctl); @@ -23507,16 +24753,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + mc_ptr = mc_ptr->next; + } + -+ hw->mac.ops.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); + } else { + /* + * if we're called from probe, we might not have + * anything to do here, so clear out the list + */ -+ hw->mac.ops.update_mc_addr_list(hw, NULL, 0, 1, -+ mac->rar_entry_count); ++ e1000_update_mc_addr_list(hw, NULL, 0); + } +} + @@ -23538,6 +24782,38 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +} + +/** ++ * e1000e_power_up_phy - restore link in case the phy was powered down ++ * @adapter: address of board private structure ++ * ++ * The phy may be powered down to save power and turn off link when the ++ * driver is unloaded and wake on lan is not enabled (among others) ++ * *** this routine MUST be followed by a call to e1000e_reset *** ++ **/ ++void e1000e_power_up_phy(struct e1000_adapter *adapter) ++{ ++ if (adapter->hw.phy.ops.power_up) ++ adapter->hw.phy.ops.power_up(&adapter->hw); ++ ++ adapter->hw.mac.ops.setup_link(&adapter->hw); ++} ++ ++/** ++ * e1000_power_down_phy - Power down the PHY ++ * ++ * Power down the PHY so no link is implied when interface is down. ++ * The PHY cannot be powered down if management or WoL is active. ++ */ ++static void e1000_power_down_phy(struct e1000_adapter *adapter) ++{ ++ /* WoL is enabled */ ++ if (adapter->wol) ++ return; ++ ++ if (adapter->hw.phy.ops.power_down) ++ adapter->hw.phy.ops.power_down(&adapter->hw); ++} ++ ++/** + * e1000e_reset - bring the hardware into a known good state + * + * This function boots the hardware and enables some settings that @@ -23545,7 +24821,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + * set/changed during runtime. After reset the device needs to be + * properly configured for Rx, Tx etc. + */ -+void e1000_reset(struct e1000_adapter *adapter) ++void e1000e_reset(struct e1000_adapter *adapter) +{ + struct e1000_mac_info *mac = &adapter->hw.mac; + struct e1000_fc_info *fc = &adapter->hw.fc; @@ -23557,7 +24833,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + /* reset Packet Buffer Allocation to default */ + ew32(PBA, pba); + -+ if (adapter->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN ) { ++ if (adapter->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) { + /* + * To maintain wire speed transmits, the Tx FIFO should be + * large enough to accommodate two full transmit packets, @@ -23611,30 +24887,32 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + /* + * flow control settings + * -+ * The high water mark must be low enough to fit one full frame ++ * The high water mark must be low enough to fit two full frames + * (or the size used for early receive) above it in the Rx FIFO. + * Set it to the lower of: + * - 90% of the Rx FIFO size, and + * - the full Rx FIFO size minus the early receive size (for parts + * with ERT support assuming ERT set to E1000_ERT_2048), or -+ * - the full Rx FIFO size minus one full frame ++ * - the full Rx FIFO size minus two full frames + */ -+ if (adapter->flags & FLAG_HAS_ERT) ++ if ((adapter->flags & FLAG_HAS_ERT) && ++ (adapter->netdev->mtu > ETH_DATA_LEN)) + hwm = min(((pba << 10) * 9 / 10), + ((pba << 10) - (E1000_ERT_2048 << 3))); + else + hwm = min(((pba << 10) * 9 / 10), -+ ((pba << 10) - adapter->max_frame_size)); ++ ((pba << 10) - (2 * adapter->max_frame_size))); + -+ fc->high_water = hwm & 0xFFF8; /* 8-byte granularity */ -+ fc->low_water = fc->high_water - 8; ++ fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */ ++ fc->low_water = (fc->high_water - (2 * adapter->max_frame_size)); ++ fc->low_water &= E1000_FCRTL_RTL; /* 8-byte granularity */ + + if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME) + fc->pause_time = 0xFFFF; + else + fc->pause_time = E1000_FC_PAUSE_TIME; + fc->send_xon = 1; -+ fc->type = fc->original_type; ++ fc->current_mode = fc->requested_mode; + + /* Allow time for pending master requests to run */ + mac->ops.reset_hw(hw); @@ -23647,6 +24925,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + e1000_get_hw_control(adapter); + + ew32(WUC, 0); ++ if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) ++ e1e_wphy(&adapter->hw, BM_WUC, 0); + + if (mac->ops.init_hw(hw)) + e_err("Hardware Error\n"); @@ -23656,30 +24936,33 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ + ew32(VET, ETH_P_8021Q); + -+ e1000_reset_adaptive_generic(hw); -+ -+ if (!hw->phy.ops.get_info) -+ return; -+ -+ hw->phy.ops.get_info(hw); ++ e1000e_reset_adaptive(hw); ++ e1000_get_phy_info(hw); + -+ if (!(adapter->flags & FLAG_SMART_POWER_DOWN)) { ++ if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) && ++ !(adapter->flags & FLAG_SMART_POWER_DOWN)) { + u16 phy_data = 0; + /* + * speed up time to link by disabling smart power down, ignore + * the return value of this function because there is nothing + * different we would do if it failed + */ -+ hw->phy.ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data); ++ e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data); + phy_data &= ~IGP02E1000_PM_SPD; -+ hw->phy.ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data); ++ e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, phy_data); + } +} + -+int e1000_up(struct e1000_adapter *adapter) ++int e1000e_up(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + ++ /* DMA latency requirement to workaround early-receive/jumbo issue */ ++ if (adapter->flags & FLAG_HAS_ERT) ++ pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, ++ adapter->netdev->name, ++ PM_QOS_DEFAULT_VALUE); ++ + /* hardware has been reset, we need to reload some things */ + e1000_configure(adapter); + @@ -23699,7 +24982,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + return 0; +} + -+void e1000_down(struct e1000_adapter *adapter) ++void e1000e_down(struct e1000_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct e1000_hw *hw = &adapter->hw; @@ -23716,7 +24999,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + ew32(RCTL, rctl & ~E1000_RCTL_EN); + /* flush and sleep below */ + -+ netif_stop_queue(netdev); ++ netif_tx_stop_all_queues(netdev); + + /* disable transmits in the hardware */ + tctl = er32(TCTL); @@ -23729,7 +25012,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +#ifdef CONFIG_E1000E_NAPI + napi_disable(&adapter->napi); +#endif -+ + e1000_irq_disable(adapter); + + del_timer_sync(&adapter->watchdog_timer); @@ -23740,23 +25022,30 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + adapter->link_speed = 0; + adapter->link_duplex = 0; + -+ e1000_reset(adapter); ++#ifdef HAVE_PCI_ERS ++ if (!pci_channel_offline(adapter->pdev)) ++#endif ++ e1000e_reset(adapter); + e1000_clean_tx_ring(adapter); + e1000_clean_rx_ring(adapter); + ++ if (adapter->flags & FLAG_HAS_ERT) ++ pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, ++ adapter->netdev->name); ++ + /* + * TODO: for power management, we could drop the link and + * pci_disable_device here. + */ +} + -+void e1000_reinit_locked(struct e1000_adapter *adapter) ++void e1000e_reinit_locked(struct e1000_adapter *adapter) +{ + might_sleep(); + while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) + msleep(1); -+ e1000_down(adapter); -+ e1000_up(adapter); ++ e1000e_down(adapter); ++ e1000e_up(adapter); + clear_bit(__E1000_RESETTING, &adapter->state); +} + @@ -23794,19 +25083,15 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + return rc; + +#ifdef CONFIG_E1000E_MSIX -+ e1000_set_interrupt_capability(adapter); ++ e1000e_set_interrupt_capability(adapter); + +#endif /* CONFIG_E1000E_MSIX */ + if (e1000_alloc_queues(adapter)) + return -ENOMEM; + -+ spin_lock_init(&adapter->tx_queue_lock); -+ + /* Explicitly disable IRQ since the NIC can be in any state. */ + e1000_irq_disable(adapter); + -+ spin_lock_init(&adapter->stats_lock); -+ + set_bit(__E1000_DOWN, &adapter->state); + return 0; +} @@ -23828,7 +25113,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + adapter->flags &= ~FLAG_MSI_TEST_FAILED; + wmb(); + } -+ ++ + return IRQ_HANDLED; +} + @@ -23851,7 +25136,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + /* free the real vector and request a test handler */ + e1000_free_irq(adapter); +#ifdef CONFIG_E1000E_MSIX -+ e1000_reset_interrupt_capability(adapter); ++ e1000e_reset_interrupt_capability(adapter); +#endif + + /* Assume that the test fails, if it succeeds then the test @@ -23900,7 +25185,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + e_dbg("MSI interrupt test succeeded!\n"); +msi_test_failed: +#ifdef CONFIG_E1000E_MSIX -+ e1000_set_interrupt_capability(adapter); ++ e1000e_set_interrupt_capability(adapter); +#else + /* restore the original vector, even if it failed */ +#endif @@ -23973,16 +25258,16 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + return -EBUSY; + + /* allocate transmit descriptors */ -+ err = e1000_setup_tx_resources(adapter); ++ err = e1000e_setup_tx_resources(adapter); + if (err) + goto err_setup_tx; + + /* allocate receive descriptors */ -+ err = e1000_setup_rx_resources(adapter); ++ err = e1000e_setup_rx_resources(adapter); + if (err) + goto err_setup_rx; + -+ e1000_power_up_phy(hw); ++ e1000e_power_up_phy(adapter); + + adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; + if ((adapter->hw.mng_cookie.status & @@ -24014,9 +25299,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + * interrupt now + */ +#ifdef CONFIG_E1000E_MSIX -+ if (adapter->int_mode != E1000E_INT_MODE_LEGACY) -+#endif ++ if (adapter->int_mode != E1000E_INT_MODE_LEGACY) { ++#else + { ++#endif + err = e1000_test_msi(adapter); + if (err) { + e_err("Interrupt allocation failed\n"); @@ -24024,7 +25310,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + } + } + -+ /* From here on the code is the same as e1000_up() */ ++ /* From here on the code is the same as e1000e_up() */ + clear_bit(__E1000_DOWN, &adapter->state); + +#ifdef CONFIG_E1000E_NAPI @@ -24033,6 +25319,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + + e1000_irq_enable(adapter); + ++ netif_tx_start_all_queues(netdev); ++ + /* fire a link status change interrupt to start the watchdog */ + ew32(ICS, E1000_ICS_LSC); + @@ -24040,13 +25328,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + +err_req_irq: + e1000_release_hw_control(adapter); -+ if (!adapter->wol && hw->phy.ops.power_down) -+ hw->phy.ops.power_down(hw); -+ e1000_free_rx_resources(adapter); ++ e1000_power_down_phy(adapter); ++ e1000e_free_rx_resources(adapter); +err_setup_rx: -+ e1000_free_tx_resources(adapter); ++ e1000e_free_tx_resources(adapter); +err_setup_tx: -+ e1000_reset(adapter); ++ e1000e_reset(adapter); + + return err; +} @@ -24065,16 +25352,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +static int e1000_close(struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); -+ struct e1000_hw *hw = &adapter->hw; + + WARN_ON(test_bit(__E1000_RESETTING, &adapter->state)); -+ e1000_down(adapter); -+ if (!adapter->wol && hw->phy.ops.power_down) -+ hw->phy.ops.power_down(hw); ++ e1000e_down(adapter); ++ e1000_power_down_phy(adapter); + e1000_free_irq(adapter); + -+ e1000_free_tx_resources(adapter); -+ e1000_free_rx_resources(adapter); ++ e1000e_free_tx_resources(adapter); ++ e1000e_free_rx_resources(adapter); + + /* + * kill manageability vlan ID if supported, but not if a vlan with @@ -24113,11 +25398,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + memcpy(adapter->hw.mac.addr, addr->sa_data, netdev->addr_len); + -+ adapter->hw.mac.ops.rar_set(&adapter->hw, adapter->hw.mac.addr, 0); ++ e1000e_rar_set(&adapter->hw, adapter->hw.mac.addr, 0); + + if (adapter->flags & FLAG_RESET_OVERWRITES_LAA) { + /* activate the work around */ -+ e1000_set_laa_state_82571(&adapter->hw, 1); ++ e1000e_set_laa_state_82571(&adapter->hw, 1); + + /* + * Hold a copy of the LAA in RAR[14] This is done so that @@ -24127,38 +25412,50 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + * are dropped. Eventually the LAA will be in RAR[0] and + * RAR[14] + */ -+ adapter->hw.mac.ops.rar_set(&adapter->hw, adapter->hw.mac.addr, -+ adapter->hw.mac.rar_entry_count - 1); ++ e1000e_rar_set(&adapter->hw, ++ adapter->hw.mac.addr, ++ adapter->hw.mac.rar_entry_count - 1); + } + + return 0; +} + +/** ++ * e1000e_update_phy_task - work thread to update phy ++ * @work: pointer to our work struct ++ * ++ * this worker thread exists because we must acquire a ++ * semaphore to read the phy, which we could msleep while ++ * waiting for it, and we can't msleep in a timer. ++ **/ ++static void e1000e_update_phy_task(struct work_struct *work) ++{ ++ struct e1000_adapter *adapter = container_of(work, ++ struct e1000_adapter, update_phy_task); ++ e1000_get_phy_info(&adapter->hw); ++} ++ ++/* + * Need to wait a few seconds after link up to get diagnostic information from + * the phy -+ **/ ++ */ +static void e1000_update_phy_info(unsigned long data) +{ + struct e1000_adapter *adapter = (struct e1000_adapter *) data; -+ if (adapter->hw.phy.ops.get_info) -+ adapter->hw.phy.ops.get_info(&adapter->hw); ++ schedule_work(&adapter->update_phy_task); +} + +/** -+ * e1000_update_stats - Update the board statistics counters ++ * e1000e_update_stats - Update the board statistics counters + * @adapter: board private structure + **/ -+void e1000_update_stats(struct e1000_adapter *adapter) ++void e1000e_update_stats(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; +#ifdef HAVE_PCI_ERS + struct pci_dev *pdev = adapter->pdev; +#endif -+ unsigned long irq_flags; -+ u16 phy_tmp; -+ -+#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF ++ u16 phy_data; + + /* + * Prevent stats update while adapter is being reset, or if the pci @@ -24171,14 +25468,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + return; +#endif + -+ spin_lock_irqsave(&adapter->stats_lock, irq_flags); -+ -+ /* -+ * these counters are modified from e1000_adjust_tbi_stats, -+ * called from the interrupt context, so they must only -+ * be written while holding adapter->stats_lock -+ */ -+ + adapter->stats.crcerrs += er32(CRCERRS); + adapter->stats.gprc += er32(GPRC); + adapter->stats.gorc += er32(GORCL); @@ -24188,11 +25477,34 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + adapter->stats.roc += er32(ROC); + + adapter->stats.mpc += er32(MPC); -+ adapter->stats.scc += er32(SCC); -+ adapter->stats.ecol += er32(ECOL); -+ adapter->stats.mcc += er32(MCC); -+ adapter->stats.latecol += er32(LATECOL); -+ adapter->stats.dc += er32(DC); ++ if ((hw->phy.type == e1000_phy_82578) || ++ (hw->phy.type == e1000_phy_82577)) { ++ e1e_rphy(hw, HV_SCC_UPPER, &phy_data); ++ e1e_rphy(hw, HV_SCC_LOWER, &phy_data); ++ adapter->stats.scc += phy_data; ++ ++ e1e_rphy(hw, HV_ECOL_UPPER, &phy_data); ++ e1e_rphy(hw, HV_ECOL_LOWER, &phy_data); ++ adapter->stats.ecol += phy_data; ++ ++ e1e_rphy(hw, HV_MCC_UPPER, &phy_data); ++ e1e_rphy(hw, HV_MCC_LOWER, &phy_data); ++ adapter->stats.mcc += phy_data; ++ ++ e1e_rphy(hw, HV_LATECOL_UPPER, &phy_data); ++ e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data); ++ adapter->stats.latecol += phy_data; ++ ++ e1e_rphy(hw, HV_DC_UPPER, &phy_data); ++ e1e_rphy(hw, HV_DC_LOWER, &phy_data); ++ adapter->stats.dc += phy_data; ++ } else { ++ adapter->stats.scc += er32(SCC); ++ adapter->stats.ecol += er32(ECOL); ++ adapter->stats.mcc += er32(MCC); ++ adapter->stats.latecol += er32(LATECOL); ++ adapter->stats.dc += er32(DC); ++ } + adapter->stats.xonrxc += er32(XONRXC); + adapter->stats.xontxc += er32(XONTXC); + adapter->stats.xoffrxc += er32(XOFFRXC); @@ -24210,13 +25522,28 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + + hw->mac.tx_packet_delta = er32(TPT); + adapter->stats.tpt += hw->mac.tx_packet_delta; -+ hw->mac.collision_delta = er32(COLC); ++ if ((hw->phy.type == e1000_phy_82578) || ++ (hw->phy.type == e1000_phy_82577)) { ++ e1e_rphy(hw, HV_COLC_UPPER, &phy_data); ++ e1e_rphy(hw, HV_COLC_LOWER, &phy_data); ++ hw->mac.collision_delta = phy_data; ++ } else { ++ hw->mac.collision_delta = er32(COLC); ++ } + adapter->stats.colc += hw->mac.collision_delta; + + adapter->stats.algnerrc += er32(ALGNERRC); + adapter->stats.rxerrc += er32(RXERRC); -+ if (hw->mac.type != e1000_82574) -+ adapter->stats.tncrs += er32(TNCRS); ++ if ((hw->phy.type == e1000_phy_82578) || ++ (hw->phy.type == e1000_phy_82577)) { ++ e1e_rphy(hw, HV_TNCRS_UPPER, &phy_data); ++ e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data); ++ adapter->stats.tncrs += phy_data; ++ } else { ++ if ((hw->mac.type != e1000_82574) && ++ (hw->mac.type != e1000_82583)) ++ adapter->stats.tncrs += er32(TNCRS); ++ } + adapter->stats.cexterr += er32(CEXTERR); + adapter->stats.tsctc += er32(TSCTC); + adapter->stats.tsctfc += er32(TSCTFC); @@ -24250,21 +25577,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + + /* Tx Dropped needs to be maintained elsewhere */ + -+ /* Phy Stats */ -+ if (hw->phy.media_type == e1000_media_type_copper) { -+ if ((adapter->link_speed == SPEED_1000) && -+ (!hw->phy.ops.read_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 += er32(MGTPTC); + adapter->stats.mgprc += er32(MGTPRC); + adapter->stats.mgpdc += er32(MGTPDC); -+ -+ spin_unlock_irqrestore(&adapter->stats_lock, irq_flags); +} + +#ifdef SIOCGMIIPHY @@ -24277,26 +25593,17 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + struct e1000_hw *hw = &adapter->hw; + struct e1000_phy_regs *phy = &adapter->phy_regs; + int ret_val; -+ unsigned long irq_flags; -+ -+ -+ spin_lock_irqsave(&adapter->stats_lock, irq_flags); + + if ((er32(STATUS) & E1000_STATUS_LU) && + (adapter->hw.phy.media_type == e1000_media_type_copper)) { -+ ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy->bmcr); -+ ret_val |= hw->phy.ops.read_reg(hw, PHY_STATUS, &phy->bmsr); -+ ret_val |= hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV, -+ &phy->advertise); -+ ret_val |= hw->phy.ops.read_reg(hw, PHY_LP_ABILITY, &phy->lpa); -+ ret_val |= hw->phy.ops.read_reg(hw, PHY_AUTONEG_EXP, -+ &phy->expansion); -+ ret_val |= hw->phy.ops.read_reg(hw, PHY_1000T_CTRL, -+ &phy->ctrl1000); -+ ret_val |= hw->phy.ops.read_reg(hw, PHY_1000T_STATUS, -+ &phy->stat1000); -+ ret_val |= hw->phy.ops.read_reg(hw, PHY_EXT_STATUS, -+ &phy->estatus); ++ ret_val = e1e_rphy(hw, PHY_CONTROL, &phy->bmcr); ++ ret_val |= e1e_rphy(hw, PHY_STATUS, &phy->bmsr); ++ ret_val |= e1e_rphy(hw, PHY_AUTONEG_ADV, &phy->advertise); ++ ret_val |= e1e_rphy(hw, PHY_LP_ABILITY, &phy->lpa); ++ ret_val |= e1e_rphy(hw, PHY_AUTONEG_EXP, &phy->expansion); ++ ret_val |= e1e_rphy(hw, PHY_1000T_CTRL, &phy->ctrl1000); ++ ret_val |= e1e_rphy(hw, PHY_1000T_STATUS, &phy->stat1000); ++ ret_val |= e1e_rphy(hw, PHY_EXT_STATUS, &phy->estatus); + if (ret_val) + e_warn("Error reading PHY register\n"); + } else { @@ -24306,18 +25613,16 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + */ + phy->bmcr = (BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_FULLDPLX); + phy->bmsr = (BMSR_100FULL | BMSR_100HALF | BMSR_10FULL | -+ BMSR_10HALF | BMSR_ESTATEN | BMSR_ANEGCAPABLE | -+ BMSR_ERCAP); ++ BMSR_10HALF | BMSR_ESTATEN | BMSR_ANEGCAPABLE | ++ BMSR_ERCAP); + phy->advertise = (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP | -+ ADVERTISE_ALL | ADVERTISE_CSMA); ++ ADVERTISE_ALL | ADVERTISE_CSMA); + phy->lpa = 0; + phy->expansion = EXPANSION_ENABLENPAGE; + phy->ctrl1000 = ADVERTISE_1000FULL; + phy->stat1000 = 0; + phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF); + } -+ -+ spin_unlock_irqrestore(&adapter->stats_lock, irq_flags); +} + +#endif /* SIOCGMIIPHY */ @@ -24326,17 +25631,20 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + struct e1000_hw *hw = &adapter->hw; + u32 ctrl = er32(CTRL); + -+ e_info("Link is Up %d Mbps %s, Flow Control: %s\n", ++ /* Link status message must follow this format for user tools */ ++ printk(KERN_INFO "e1000e: %s NIC Link is Up %d Mbps %s, " ++ "Flow Control: %s\n", ++ adapter->netdev->name, + adapter->link_speed, + (adapter->link_duplex == FULL_DUPLEX) ? -+ "Full Duplex" : "Half Duplex", ++ "Full Duplex" : "Half Duplex", + ((ctrl & E1000_CTRL_TFCE) && (ctrl & E1000_CTRL_RFCE)) ? -+ "RX/TX" : ++ "RX/TX" : + ((ctrl & E1000_CTRL_RFCE) ? "RX" : -+ ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None" ))); ++ ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None"))); +} + -+static bool e1000_has_link(struct e1000_adapter *adapter) ++bool e1000_has_link(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + bool link_active = 0; @@ -24411,11 +25719,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + struct e1000_adapter, watchdog_task); + struct net_device *netdev = adapter->netdev; + struct e1000_mac_info *mac = &adapter->hw.mac; ++ struct e1000_phy_info *phy = &adapter->hw.phy; + struct e1000_ring *tx_ring = adapter->tx_ring; + struct e1000_hw *hw = &adapter->hw; + u32 link, tctl; + int tx_pending = 0; -+ unsigned long timer_val; + + link = e1000_has_link(adapter); + if ((netif_carrier_ok(netdev)) && link) { @@ -24423,7 +25731,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + goto link_up; + } + -+ if ((e1000_enable_tx_pkt_filtering_generic(hw)) && ++ if ((e1000e_enable_tx_pkt_filtering(hw)) && + (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)) + e1000_update_mng_vlan(adapter); + @@ -24438,27 +25746,25 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + &adapter->link_speed, + &adapter->link_duplex); + e1000_print_link_info(adapter); -+ + /* + * On supported PHYs, check for duplex mismatch only + * if link has autonegotiated at 10/100 half + */ + if ((hw->phy.type == e1000_phy_igp_3 || + hw->phy.type == e1000_phy_bm) && -+ (hw->mac.autoneg == TRUE) && ++ (hw->mac.autoneg == true) && + (adapter->link_speed == SPEED_10 || + adapter->link_speed == SPEED_100) && + (adapter->link_duplex == HALF_DUPLEX)) { + u16 autoneg_exp; + -+ hw->phy.ops.read_reg(hw, PHY_AUTONEG_EXP, -+ &autoneg_exp); ++ e1e_rphy(hw, PHY_AUTONEG_EXP, &autoneg_exp); + + if (!(autoneg_exp & NWAY_ER_LP_NWAY_CAPS)) + e_info("Autonegotiated half duplex but" + " link partner cannot autoneg. " + " Try forcing full duplex if " -+ "link gets many collisions."); ++ "link gets many collisions.\n"); + } + + /* @@ -24528,16 +25834,32 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + tctl |= E1000_TCTL_EN; + ew32(TCTL, tctl); + ++ /* ++ * Perform any post-link-up configuration before ++ * reporting link up. ++ */ ++ if (phy->ops.cfg_on_link_up) ++ phy->ops.cfg_on_link_up(hw); ++ + netif_carrier_on(netdev); -+ netif_wake_queue(netdev); ++ netif_tx_wake_all_queues(netdev); ++ ++ if (!test_bit(__E1000_DOWN, &adapter->state)) ++ mod_timer(&adapter->phy_info_timer, ++ round_jiffies(jiffies + 2 * HZ)); + } + } else { + if (netif_carrier_ok(netdev)) { + adapter->link_speed = 0; + adapter->link_duplex = 0; -+ e_info("Link is Down\n"); ++ /* Link status message must follow this format */ ++ printk(KERN_INFO "e1000e: %s NIC Link is Down\n", ++ adapter->netdev->name); + netif_carrier_off(netdev); -+ netif_stop_queue(netdev); ++ netif_tx_stop_all_queues(netdev); ++ if (!test_bit(__E1000_DOWN, &adapter->state)) ++ mod_timer(&adapter->phy_info_timer, ++ round_jiffies(jiffies + 2 * HZ)); + + if (adapter->flags & FLAG_RX_NEEDS_RESTART) + schedule_work(&adapter->reset_task); @@ -24545,7 +25867,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + } + +link_up: -+ e1000_update_stats(adapter); ++ e1000e_update_stats(adapter); + + mac->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; + adapter->tpt_old = adapter->stats.tpt; @@ -24557,7 +25879,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + adapter->gotc = adapter->stats.gotc - adapter->gotc_old; + adapter->gotc_old = adapter->stats.gotc; + -+ e1000_update_adaptive_generic(&adapter->hw); ++ e1000e_update_adaptive(&adapter->hw); + + if (!netif_carrier_ok(netdev)) { + tx_pending = (e1000_desc_unused(tx_ring) + 1 < @@ -24579,8 +25901,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + if (adapter->msix_entries) + ew32(ICS, adapter->rx_ring->ims_val); + else -+#endif + ew32(ICS, E1000_ICS_RXDMT0); ++#else ++ ew32(ICS, E1000_ICS_RXDMT0); ++#endif + + /* Force detection of hung controller every watchdog period */ + adapter->detect_tx_hung = 1; @@ -24589,16 +25913,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + * With 82571 controllers, LAA may be overwritten due to controller + * reset from the other port. Set the appropriate LAA in RAR[0] + */ -+ if (e1000_get_laa_state_82571(hw)) -+ hw->mac.ops.rar_set(hw, adapter->hw.mac.addr, 0); ++ if (e1000e_get_laa_state_82571(hw)) ++ e1000e_rar_set(hw, adapter->hw.mac.addr, 0); + + /* Reset the timer */ -+ if (!test_bit(__E1000_DOWN, &adapter->state)) { -+ timer_val = jiffies + usecs_to_jiffies(adapter->stats_freq_us); -+ if (adapter->stats_freq_us > 1000000) -+ timer_val = round_jiffies(timer_val); -+ mod_timer(&adapter->watchdog_timer, timer_val); -+ } ++ if (!test_bit(__E1000_DOWN, &adapter->state)) ++ mod_timer(&adapter->watchdog_timer, ++ round_jiffies(jiffies + 2 * HZ)); +} + +#define E1000_TX_FLAGS_CSUM 0x00000001 @@ -24636,19 +25957,16 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + struct iphdr *iph = ip_hdr(skb); + iph->tot_len = 0; + iph->check = 0; -+ tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, -+ iph->daddr, 0, -+ IPPROTO_TCP, -+ 0); ++ tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, ++ 0, IPPROTO_TCP, 0); + cmd_length = E1000_TXD_CMD_IP; + ipcse = skb_transport_offset(skb) - 1; +#ifdef NETIF_F_TSO6 + } else if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6) { + ipv6_hdr(skb)->payload_len = 0; -+ tcp_hdr(skb)->check = -+ ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, -+ &ipv6_hdr(skb)->daddr, -+ 0, IPPROTO_TCP, 0); ++ tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, ++ &ipv6_hdr(skb)->daddr, ++ 0, IPPROTO_TCP, 0); + ipcse = 0; +#endif + } @@ -24712,12 +26030,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + cmd_len |= E1000_TXD_CMD_TCP; + break; + default: -+ if (unlikely(net_ratelimit())) ++ if (unlikely(net_ratelimit())) + e_warn("checksum_partial proto=%x!\n", skb->protocol); + break; + } + -+ css = skb_transport_offset(skb); ++ css = skb_transport_offset(skb); + + i = tx_ring->next_to_use; + buffer_info = &tx_ring->buffer_info[i]; @@ -24725,7 +26043,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + + context_desc->lower_setup.ip_config = 0; + context_desc->upper_setup.tcp_fields.tucss = css; -+ context_desc->upper_setup.tcp_fields.tucso = css + skb->csum_offset; ++ context_desc->upper_setup.tcp_fields.tucso = ++ css + skb->csum_offset; + context_desc->upper_setup.tcp_fields.tucse = 0; + context_desc->tcp_seg_setup.data = 0; + context_desc->cmd_and_length = cpu_to_le32(cmd_len); @@ -24750,7 +26069,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + unsigned int mss) +{ + struct e1000_ring *tx_ring = adapter->tx_ring; -+ struct pci_dev *pdev = adapter->pdev; + struct e1000_buffer *buffer_info; + unsigned int len = skb->len - skb->data_len; + unsigned int offset = 0, size, count = 0, i; @@ -24770,8 +26088,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + skb->data + offset, + size, + PCI_DMA_TODEVICE); -+ if (pci_dma_mapping_error(pdev, buffer_info->dma)) { -+ dev_err(&pdev->dev, "TX DMA map failed\n"); ++ if (pci_dma_mapping_error(adapter->pdev, buffer_info->dma)) { ++ dev_err(&adapter->pdev->dev, "TX DMA map failed\n"); + adapter->tx_dma_failed++; + return -1; + } @@ -24804,7 +26122,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + offset, + size, + PCI_DMA_TODEVICE); -+ if (pci_dma_mapping_error(pdev, buffer_info->dma)) { ++ if (pci_dma_mapping_error(adapter->pdev, ++ buffer_info->dma)) { + dev_err(&adapter->pdev->dev, + "TX DMA page map failed\n"); + adapter->tx_dma_failed++; @@ -24929,8 +26248,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + + offset = (u8 *)udp + 8 - skb->data; + length = skb->len - offset; -+ return e1000_mng_write_dhcp_info_generic(hw, (u8 *)udp + 8, -+ length); ++ return e1000e_mng_write_dhcp_info(hw, (u8 *)udp + 8, length); + } + + return 0; @@ -24970,7 +26288,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + return __e1000_maybe_stop_tx(netdev, size); +} + -+#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 ) ++#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1) +static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); @@ -24980,9 +26298,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + unsigned int max_txd_pwr = E1000_MAX_TXD_PWR; + unsigned int tx_flags = 0; + unsigned int len = skb->len - skb->data_len; -+#ifdef NETIF_F_LLTX -+ unsigned long irq_flags; -+#endif + unsigned int nr_frags; + unsigned int mss = 0; + int count = 0; @@ -25056,20 +26371,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + if (adapter->hw.mac.tx_pkt_filtering) + e1000_transfer_dhcp_info(adapter, skb); + -+#ifdef NETIF_F_LLTX -+ if (!spin_trylock_irqsave(&adapter->tx_queue_lock, irq_flags)) -+ /* Collision - tell upper layer to requeue */ -+ return NETDEV_TX_LOCKED; -+#endif + + /* + * need: count + 2 desc gap to keep tail from touching + * head, otherwise try next time + */ + if (e1000_maybe_stop_tx(netdev, count + 2)) { -+#ifdef NETIF_F_LLTX -+ spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags); -+#endif + return NETDEV_TX_BUSY; + } + @@ -25081,11 +26388,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + first = tx_ring->next_to_use; + + tso = e1000_tso(adapter, skb); -+ if (unlikely(tso < 0)) { ++ if (tso < 0) { + dev_kfree_skb_any(skb); -+#ifdef NETIF_F_LLTX -+ spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags); -+#endif + return NETDEV_TX_OK; + } + @@ -25103,12 +26407,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + tx_flags |= E1000_TX_FLAGS_IPV4; + + count = e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss); -+ if (unlikely(count < 0)) { ++ if (count < 0) { + /* handle pci_map_single() error in e1000_tx_map */ + dev_kfree_skb_any(skb); -+#ifdef NETIF_F_LLTX -+ spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags); -+#endif + return NETDEV_TX_OK; + } + @@ -25119,9 +26420,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + /* Make sure there is space in the ring for the next send. */ + e1000_maybe_stop_tx(netdev, MAX_SKB_FRAGS + 2); + -+#ifdef NETIF_F_LLTX -+ spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags); -+#endif + return NETDEV_TX_OK; +} + @@ -25143,7 +26441,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + struct e1000_adapter *adapter; + adapter = container_of(work, struct e1000_adapter, reset_task); + -+ e1000_reinit_locked(adapter); ++ e1000e_reinit_locked(adapter); +} + +/** @@ -25173,31 +26471,26 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + struct e1000_adapter *adapter = netdev_priv(netdev); + int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; + -+ if ((new_mtu < 68) || (max_frame > MAX_JUMBO_FRAME_SIZE)) { -+ e_err("Invalid MTU setting\n"); ++ /* Jumbo frame support */ ++ if ((max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) && ++ !(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) { ++ e_err("Jumbo Frames not supported.\n"); + return -EINVAL; + } + -+ /* Jumbo frame size limits */ -+ if (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) { -+ if (!(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) { -+ e_err("Jumbo Frames not supported.\n"); -+ return -EINVAL; -+ } -+ } -+ -+#define MAX_STD_JUMBO_FRAME_SIZE 9234 -+ if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) { -+ e_err("MTU > 9216 not supported.\n"); ++ /* Supported frame sizes */ ++ if ((new_mtu < ETH_ZLEN + ETH_FCS_LEN + VLAN_HLEN) || ++ (max_frame > adapter->max_hw_frame_size)) { ++ e_err("Unsupported MTU setting\n"); + return -EINVAL; + } + + while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) + msleep(1); -+ /* e1000_down has a dependency on max_frame_size */ ++ /* e1000e_down has a dependency on max_frame_size */ + adapter->max_frame_size = max_frame; + if (netif_running(netdev)) -+ e1000_down(adapter); ++ e1000e_down(adapter); + + /* + * NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN @@ -25238,9 +26531,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + netdev->mtu = new_mtu; + + if (netif_running(netdev)) -+ e1000_up(adapter); ++ e1000e_up(adapter); + else -+ e1000_reset(adapter); ++ e1000e_reset(adapter); + + clear_bit(__E1000_RESETTING, &adapter->state); + @@ -25321,6 +26614,81 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + } +} + ++static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 i, mac_reg; ++ u16 phy_reg; ++ int retval = 0; ++ ++ /* copy MAC RARs to PHY RARs */ ++ for (i = 0; i < adapter->hw.mac.rar_entry_count; i++) { ++ mac_reg = er32(RAL(i)); ++ e1e_wphy(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF)); ++ e1e_wphy(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF)); ++ mac_reg = er32(RAH(i)); ++ e1e_wphy(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF)); ++ e1e_wphy(hw, BM_RAR_CTRL(i), (u16)((mac_reg >> 16) & 0xFFFF)); ++ } ++ ++ /* copy MAC MTA to PHY MTA */ ++ for (i = 0; i < adapter->hw.mac.mta_reg_count; i++) { ++ mac_reg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i); ++ e1e_wphy(hw, BM_MTA(i), (u16)(mac_reg & 0xFFFF)); ++ e1e_wphy(hw, BM_MTA(i) + 1, (u16)((mac_reg >> 16) & 0xFFFF)); ++ } ++ ++ /* configure PHY Rx Control register */ ++ e1e_rphy(&adapter->hw, BM_RCTL, &phy_reg); ++ mac_reg = er32(RCTL); ++ if (mac_reg & E1000_RCTL_UPE) ++ phy_reg |= BM_RCTL_UPE; ++ if (mac_reg & E1000_RCTL_MPE) ++ phy_reg |= BM_RCTL_MPE; ++ phy_reg &= ~(BM_RCTL_MO_MASK); ++ if (mac_reg & E1000_RCTL_MO_3) ++ phy_reg |= (((mac_reg & E1000_RCTL_MO_3) >> E1000_RCTL_MO_SHIFT) ++ << BM_RCTL_MO_SHIFT); ++ if (mac_reg & E1000_RCTL_BAM) ++ phy_reg |= BM_RCTL_BAM; ++ if (mac_reg & E1000_RCTL_PMCF) ++ phy_reg |= BM_RCTL_PMCF; ++ mac_reg = er32(CTRL); ++ if (mac_reg & E1000_CTRL_RFCE) ++ phy_reg |= BM_RCTL_RFCE; ++ e1e_wphy(&adapter->hw, BM_RCTL, phy_reg); ++ ++ /* enable PHY wakeup in MAC register */ ++ ew32(WUFC, wufc); ++ ew32(WUC, E1000_WUC_PHY_WAKE | E1000_WUC_PME_EN); ++ ++ /* configure and enable PHY wakeup in PHY registers */ ++ e1e_wphy(&adapter->hw, BM_WUFC, wufc); ++ e1e_wphy(&adapter->hw, BM_WUC, E1000_WUC_PME_EN); ++ ++ /* activate PHY wakeup */ ++ retval = hw->phy.ops.acquire(hw); ++ if (retval) { ++ e_err("Could not acquire PHY\n"); ++ return retval; ++ } ++ e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, ++ (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); ++ retval = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg); ++ if (retval) { ++ e_err("Could not read PHY page 769\n"); ++ goto out; ++ } ++ phy_reg |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT; ++ retval = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); ++ if (retval) ++ e_err("Could not set PHY Host Wakeup bit\n"); ++out: ++ hw->phy.ops.release(hw); ++ ++ return retval; ++} ++ +static int e1000_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); @@ -25334,15 +26702,16 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + + if (netif_running(netdev)) { + WARN_ON(test_bit(__E1000_RESETTING, &adapter->state)); -+ e1000_down(adapter); ++ e1000e_down(adapter); + e1000_free_irq(adapter); + } ++#ifdef CONFIG_E1000E_MSIX ++ e1000e_reset_interrupt_capability(adapter); ++#endif + -+#ifdef CONFIG_PM + retval = pci_save_state(pdev); + if (retval) + return retval; -+#endif + + status = er32(STATUS); + if (status & E1000_STATUS_LU) @@ -25364,12 +26733,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + #define E1000_CTRL_ADVD3WUC 0x00100000 + /* phy power management enable */ + #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 -+ ctrl |= E1000_CTRL_ADVD3WUC | -+ E1000_CTRL_EN_PHY_PWR_MGMT; ++ ctrl |= E1000_CTRL_ADVD3WUC; ++ if (!(adapter->flags2 & FLAG2_HAS_PHY_WAKEUP)) ++ ctrl |= E1000_CTRL_EN_PHY_PWR_MGMT; + ew32(CTRL, ctrl); + + if (adapter->hw.phy.media_type == e1000_media_type_fiber || -+ adapter->hw.phy.media_type == e1000_media_type_internal_serdes) { ++ adapter->hw.phy.media_type == ++ e1000_media_type_internal_serdes) { + /* keep the laser running in D3 */ + ctrl_ext = er32(CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA; @@ -25377,13 +26748,22 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + } + + if (adapter->flags & FLAG_IS_ICH) -+ e1000_disable_gig_wol_ich8lan(&adapter->hw); ++ e1000e_disable_gig_wol_ich8lan(&adapter->hw); + + /* Allow time for pending master requests to run */ -+ e1000_disable_pcie_master_generic(&adapter->hw); -+ -+ ew32(WUC, E1000_WUC_PME_EN); -+ ew32(WUFC, wufc); ++ e1000e_disable_pcie_master(&adapter->hw); ++ ++ if ((adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) && ++ !(hw->mac.ops.check_mng_mode(hw))) { ++ /* enable wakeup by the PHY */ ++ retval = e1000_init_phy_wakeup(adapter, wufc); ++ if (retval) ++ return retval; ++ } else { ++ /* enable wakeup by the MAC */ ++ ew32(WUFC, wufc); ++ ew32(WUC, E1000_WUC_PME_EN); ++ } + pci_enable_wake(pdev, PCI_D3hot, 1); + pci_enable_wake(pdev, PCI_D3cold, 1); + } else { @@ -25400,7 +26780,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + } + + if (adapter->hw.phy.type == e1000_phy_igp_3) -+ e1000_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw); ++ e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw); + + /* + * Release control of h/w to f/w. If f/w is AMT enabled, this @@ -25410,11 +26790,56 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + + pci_disable_device(pdev); + -+ pci_set_power_state(pdev, pci_choose_state(pdev, state)); ++ /* ++ * The pci-e switch on some quad port adapters will report a ++ * correctable error when the MAC transitions from D0 to D3. To ++ * prevent this we need to mask off the correctable errors on the ++ * downstream port of the pci-e switch. ++ */ ++ if (adapter->flags & FLAG_IS_QUAD_PORT) { ++ struct pci_dev *us_dev = pdev->bus->self; ++ int pos = pci_find_capability(us_dev, PCI_CAP_ID_EXP); ++ u16 devctl; ++ ++ pci_read_config_word(us_dev, pos + PCI_EXP_DEVCTL, &devctl); ++ pci_write_config_word(us_dev, pos + PCI_EXP_DEVCTL, ++ (devctl & ~PCI_EXP_DEVCTL_CERE)); ++ ++ pci_set_power_state(pdev, pci_choose_state(pdev, state)); ++ ++ pci_write_config_word(us_dev, pos + PCI_EXP_DEVCTL, devctl); ++ } else { ++ pci_set_power_state(pdev, pci_choose_state(pdev, state)); ++ } + + return 0; +} + ++static void e1000e_disable_l1aspm(struct pci_dev *pdev) ++{ ++ int pos; ++ u16 val; ++ ++ /* ++ * 82573 workaround - disable L1 ASPM on mobile chipsets ++ * ++ * L1 ASPM on various mobile (ich7) chipsets do not behave properly ++ * resulting in lost data or garbage information on the pci-e link ++ * level. This could result in (false) bad EEPROM checksum errors, ++ * long ping times (up to 2s) or even a system freeze/hang. ++ * ++ * Unfortunately this feature saves about 1W power consumption when ++ * active. ++ */ ++ pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); ++ pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &val); ++ if (val & 0x2) { ++ dev_warn(&pdev->dev, "Disabling L1 ASPM\n"); ++ val &= ~0x2; ++ pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, val); ++ } ++} ++ +#ifdef CONFIG_PM +static int e1000_resume(struct pci_dev *pdev) +{ @@ -25425,32 +26850,74 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); -+ err = pci_enable_device(pdev); ++ e1000e_disable_l1aspm(pdev); ++ ++ err = pci_enable_device_mem(pdev); + if (err) { + dev_err(&pdev->dev, + "Cannot enable PCI device from suspend\n"); + return err; + } + ++ /* AER (Advanced Error Reporting) hooks */ ++ err = pci_enable_pcie_error_reporting(pdev); ++ if (err) { ++ dev_err(&pdev->dev, "pci_enable_pcie_error_reporting failed " ++ "0x%x\n", err); ++ /* non-fatal, continue */ ++ } ++ + pci_set_master(pdev); + + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + ++#ifdef CONFIG_E1000E_MSIX ++ e1000e_set_interrupt_capability(adapter); ++#endif + if (netif_running(netdev)) { + err = e1000_request_irq(adapter); + if (err) + return err; + } + -+ e1000_power_up_phy(hw); -+ e1000_reset(adapter); -+ ew32(WUS, ~0); ++ e1000e_power_up_phy(adapter); ++ ++ /* report the system wakeup cause from S3/S4 */ ++ if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) { ++ u16 phy_data; ++ ++ e1e_rphy(&adapter->hw, BM_WUS, &phy_data); ++ if (phy_data) { ++ e_info("PHY Wakeup cause - %s\n", ++ phy_data & E1000_WUS_EX ? "Unicast Packet" : ++ phy_data & E1000_WUS_MC ? "Multicast Packet" : ++ phy_data & E1000_WUS_BC ? "Broadcast Packet" : ++ phy_data & E1000_WUS_MAG ? "Magic Packet" : ++ phy_data & E1000_WUS_LNKC ? "Link Status " ++ " Change" : "other"); ++ } ++ e1e_wphy(&adapter->hw, BM_WUS, ~0); ++ } else { ++ u32 wus = er32(WUS); ++ if (wus) { ++ e_info("MAC Wakeup cause - %s\n", ++ wus & E1000_WUS_EX ? "Unicast Packet" : ++ wus & E1000_WUS_MC ? "Multicast Packet" : ++ wus & E1000_WUS_BC ? "Broadcast Packet" : ++ wus & E1000_WUS_MAG ? "Magic Packet" : ++ wus & E1000_WUS_LNKC ? "Link Status Change" : ++ "other"); ++ } ++ ew32(WUS, ~0); ++ } ++ ++ e1000e_reset(adapter); + + e1000_init_manageability(adapter); + + if (netif_running(netdev)) -+ e1000_up(adapter); ++ e1000e_up(adapter); + + netif_device_attach(netdev); + @@ -25464,7 +26931,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + + return 0; +} -+#endif /* CONFIG_PM */ ++#endif + +#ifndef USE_REBOOT_NOTIFIER +static void e1000_shutdown(struct pci_dev *pdev) @@ -25511,11 +26978,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + disable_irq(adapter->pdev->irq); + e1000_intr(adapter->pdev->irq, netdev); + -+ e1000_clean_tx_irq(adapter); +#ifndef CONFIG_E1000E_NAPI + adapter->clean_rx(adapter); -+#endif + ++#endif + enable_irq(adapter->pdev->irq); +} +#endif @@ -25538,7 +27004,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + netif_device_detach(netdev); + + if (netif_running(netdev)) -+ e1000_down(adapter); ++ e1000e_down(adapter); + pci_disable_device(pdev); + + /* Request a slot slot reset. */ @@ -25557,21 +27023,30 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + struct net_device *netdev = pci_get_drvdata(pdev); + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; ++ int err; ++ pci_ers_result_t result; + -+ if (pci_enable_device(pdev)) { ++ e1000e_disable_l1aspm(pdev); ++ err = pci_enable_device_mem(pdev); ++ if (err) { + dev_err(&pdev->dev, + "Cannot re-enable PCI device after reset.\n"); -+ return PCI_ERS_RESULT_DISCONNECT; -+ } -+ pci_set_master(pdev); ++ 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); ++ pci_enable_wake(pdev, PCI_D3hot, 0); ++ pci_enable_wake(pdev, PCI_D3cold, 0); + -+ e1000_reset(adapter); -+ ew32(WUS, ~0); ++ e1000e_reset(adapter); ++ ew32(WUS, ~0); ++ result = PCI_ERS_RESULT_RECOVERED; ++ } ++ ++ pci_cleanup_aer_uncorrect_error_status(pdev); + -+ return PCI_ERS_RESULT_RECOVERED; ++ return result; +} + +/** @@ -25590,7 +27065,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + e1000_init_manageability(adapter); + + if (netif_running(netdev)) { -+ if (e1000_up(adapter)) { ++ if (e1000e_up(adapter)) { + dev_err(&pdev->dev, + "can't bring device back up after reset\n"); + return; @@ -25619,20 +27094,81 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + /* print bus type/speed/width info */ + e_info("(PCI Express:2.5GB/s:%s) %02x:%02x:%02x:%02x:%02x:%02x\n", + /* bus width */ -+ ((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" : -+ "Width x1"), ++ ((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" : ++ "Width x1"), + /* MAC address */ -+ netdev->dev_addr[0], netdev->dev_addr[1], -+ netdev->dev_addr[2], netdev->dev_addr[3], -+ netdev->dev_addr[4], netdev->dev_addr[5]); ++ netdev->dev_addr[0], netdev->dev_addr[1], ++ netdev->dev_addr[2], netdev->dev_addr[3], ++ netdev->dev_addr[4], netdev->dev_addr[5]); + e_info("Intel(R) PRO/%s Network Connection\n", + (hw->phy.type == e1000_phy_ife) ? "10/100" : "1000"); -+ e1000_read_pba_num_generic(hw, &pba_num); ++ e1000e_read_pba_num(hw, &pba_num); + e_info("MAC: %d, PHY: %d, PBA No: %06x-%03x\n", -+ hw->mac.type, hw->phy.type, -+ (pba_num >> 8), (pba_num & 0xff)); ++ hw->mac.type, hw->phy.type, (pba_num >> 8), (pba_num & 0xff)); ++} ++ ++static void e1000_eeprom_checks(struct e1000_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ int ret_val; ++ u16 buf = 0; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)) ++ struct pci_dev *pdev = adapter->pdev; ++#endif ++ ++ if (hw->mac.type != e1000_82573) ++ return; ++ ++ ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &buf); ++ if (!ret_val && (!(le16_to_cpu(buf) & (1 << 0)))) { ++ /* Deep Smart Power Down (DSPD) */ ++ dev_warn(&adapter->pdev->dev, ++ "Warning: detected DSPD enabled in EEPROM\n"); ++ } ++ ++ ret_val = e1000_read_nvm(hw, NVM_INIT_3GIO_3, 1, &buf); ++ if (!ret_val && (le16_to_cpu(buf) & (3 << 2))) { ++ /* ASPM enable */ ++ dev_warn(&adapter->pdev->dev, ++ "Warning: detected ASPM enabled in EEPROM\n"); ++ } ++} ++ ++s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) ++{ ++ u16 cap_offset; ++ ++ cap_offset = pci_find_capability(hw->adapter->pdev, PCI_CAP_ID_EXP); ++ if (!cap_offset) ++ return -E1000_ERR_CONFIG; ++ ++ pci_read_config_word(hw->adapter->pdev, cap_offset + reg, value); ++ ++ return E1000_SUCCESS; +} + ++#ifdef HAVE_NET_DEVICE_OPS ++static const struct net_device_ops e1000e_netdev_ops = { ++ .ndo_open = e1000_open, ++ .ndo_stop = e1000_close, ++ .ndo_start_xmit = e1000_xmit_frame, ++ .ndo_get_stats = e1000_get_stats, ++ .ndo_set_multicast_list = e1000_set_multi, ++ .ndo_set_mac_address = e1000_set_mac, ++ .ndo_change_mtu = e1000_change_mtu, ++ .ndo_do_ioctl = e1000_ioctl, ++ .ndo_tx_timeout = e1000_tx_timeout, ++ .ndo_validate_addr = eth_validate_addr, ++ ++ .ndo_vlan_rx_register = e1000_vlan_rx_register, ++ .ndo_vlan_rx_add_vid = e1000_vlan_rx_add_vid, ++ .ndo_vlan_rx_kill_vid = e1000_vlan_rx_kill_vid, ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ .ndo_poll_controller = e1000_netpoll, ++#endif ++}; ++ ++#endif /* HAVE_NET_DEVICE_OPS */ +/** + * e1000_probe - Device Initialization Routine + * @pdev: PCI device information struct @@ -25651,37 +27187,40 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + struct e1000_adapter *adapter; + struct e1000_hw *hw; + const struct e1000_info *ei = e1000_info_tbl[ent->driver_data]; -+ + static int cards_found; + int i, err, pci_using_dac; + u16 eeprom_data = 0; + u16 eeprom_apme_mask = E1000_EEPROM_APME; + -+ err = pci_enable_device(pdev); ++ e1000e_disable_l1aspm(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); ++ DMA_BIT_MASK(32)); + if (err) { + printk(KERN_ERR "%s: No usable DMA " -+ "configuration, aborting\n", -+ pci_name(pdev)); ++ "configuration, aborting\n", ++ pci_name(pdev)); + goto err_dma; + } + } + } + -+ err = pci_request_regions(pdev, e1000e_driver_name); ++ err = pci_request_selected_regions_exclusive(pdev, ++ pci_select_bars(pdev, IORESOURCE_MEM), ++ e1000e_driver_name); + if (err) + goto err_pci_reg; + @@ -25704,38 +27243,34 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + adapter->pba = ei->pba; + adapter->flags = ei->flags; + adapter->flags2 = ei->flags2; -+ adapter->hw.back = adapter; ++ adapter->hw.adapter = adapter; + adapter->hw.mac.type = ei->mac; ++ adapter->max_hw_frame_size = ei->max_hw_frame_size; + adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1; -+ adapter->stats_freq_us = 2 * 1000000; /* default watchdog timer 2sec */ + + /* PCI config space info */ -+ -+ hw->vendor_id = pdev->vendor; + hw->device_id = pdev->device; -+ hw->subsystem_vendor_id = pdev->subsystem_vendor; -+ hw->subsystem_device_id = pdev->subsystem_device; -+ -+ pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); -+ pci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word); ++#ifdef HAVE_PCI_ERS ++ err = pci_save_state(pdev); ++ if (err) ++ goto err_ioremap; ++#endif + + err = -EIO; -+ adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, 0), -+ pci_resource_len(pdev, 0)); ++ adapter->hw.hw_addr = pci_ioremap_bar(pdev, 0); + if (!adapter->hw.hw_addr) + goto err_ioremap; + + if ((adapter->flags & FLAG_HAS_FLASH) && + (pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) { -+ adapter->hw.flash_address = ioremap(pci_resource_start(pdev, 1), -+ pci_resource_len(pdev, 1)); ++ adapter->hw.flash_address = pci_ioremap_bar(pdev, 1); + if (!adapter->hw.flash_address) + goto err_flashmap; + } + + adapter->bd_number = cards_found++; + -+ e1000_check_options(adapter); ++ e1000e_check_options(adapter); + + /* setup adapter struct */ + err = e1000_sw_init(adapter); @@ -25749,6 +27284,9 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + } + + /* construct the net_device struct */ ++#ifdef HAVE_NET_DEVICE_OPS ++ netdev->netdev_ops = &e1000e_netdev_ops; ++#else + netdev->open = &e1000_open; + netdev->stop = &e1000_close; + netdev->hard_start_xmit = &e1000_xmit_frame; @@ -25757,24 +27295,21 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + netdev->set_mac_address = &e1000_set_mac; + netdev->change_mtu = &e1000_change_mtu; + netdev->do_ioctl = &e1000_ioctl; -+ e1000_set_ethtool_ops(netdev); + netdev->tx_timeout = &e1000_tx_timeout; -+ netdev->watchdog_timeo = 5 * HZ; -+#ifdef CONFIG_E1000E_NAPI -+ netif_napi_add(netdev, &adapter->napi, e1000_poll, 64); -+#endif + netdev->vlan_rx_register = e1000_vlan_rx_register; + netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid; + netdev->vlan_rx_kill_vid = e1000_vlan_rx_kill_vid; +#ifdef CONFIG_NET_POLL_CONTROLLER + netdev->poll_controller = e1000_netpoll; +#endif ++#endif /* HAVE_NET_DEVICE_OPS */ ++ e1000e_set_ethtool_ops(netdev); ++ netdev->watchdog_timeo = 5 * HZ; ++#ifdef CONFIG_E1000E_NAPI ++ netif_napi_add(netdev, &adapter->napi, e1000_poll, 64); ++#endif + strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); + -+ if ((adapter->flags & FLAG_IS_ICH) && -+ (adapter->flags2 & FLAG2_READ_ONLY_NVM)) -+ e1000e_write_protect_nvm_ich8lan(&adapter->hw); -+ + hw->mac.ops.get_bus_info(&adapter->hw); + + adapter->hw.phy.autoneg_wait_to_complete = 0; @@ -25786,8 +27321,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + adapter->hw.phy.ms_type = e1000_ms_hw_default; + } + -+ if (hw->phy.ops.check_reset_block && -+ hw->phy.ops.check_reset_block(hw)) ++ if (e1000_check_reset_block(&adapter->hw)) + e_info("PHY reset is blocked due to SOL/IDER session.\n"); + + netdev->features = NETIF_F_SG | @@ -25808,15 +27342,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + if (pci_using_dac) + netdev->features |= NETIF_F_HIGHDMA; + -+#ifdef NETIF_F_LLTX -+ /* -+ * We should not be using LLTX anymore, but we are still Tx faster with -+ * it. -+ */ -+ netdev->features |= NETIF_F_LLTX; -+#endif + -+ if (e1000_enable_mng_pass_thru(&adapter->hw)) ++ if (e1000e_enable_mng_pass_thru(&adapter->hw)) + adapter->flags |= FLAG_MNG_PT_ENABLED; + + /* @@ -25830,7 +27357,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + * attempt. Let's give it a few tries + */ + for (i = 0;; i++) { -+ if (hw->nvm.ops.validate(hw) >= 0) ++ if (e1000_validate_nvm_checksum(&adapter->hw) >= 0) + break; + if (i == 2) { + e_err("The NVM Checksum Is Not Valid\n"); @@ -25839,8 +27366,10 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + } + } + ++ e1000_eeprom_checks(adapter); ++ + /* copy the MAC address out of the NVM */ -+ if (e1000_read_mac_addr(&adapter->hw)) ++ if (e1000e_read_mac_addr(&adapter->hw)) + e_err("NVM Read Error while reading MAC address\n"); + + memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len); @@ -25869,12 +27398,20 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + + INIT_WORK(&adapter->reset_task, e1000_reset_task); + INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task); ++ INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround); ++ INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task); + + /* Initialize link parameters. User can change them with ethtool */ + adapter->hw.mac.autoneg = 1; + adapter->fc_autoneg = 1; -+ adapter->hw.fc.original_type = e1000_fc_default; -+ adapter->hw.fc.type = e1000_fc_default; ++ if (adapter->hw.mac.type == e1000_pchlan) { ++ /* Workaround h/w hang when Tx flow control enabled */ ++ adapter->hw.fc.requested_mode = e1000_fc_rx_pause; ++ adapter->hw.fc.current_mode = e1000_fc_rx_pause; ++ } else { ++ adapter->hw.fc.requested_mode = e1000_fc_default; ++ adapter->hw.fc.current_mode = e1000_fc_default; ++ } + adapter->hw.phy.autoneg_advertised = 0x2f; + + /* ring size defaults */ @@ -25889,14 +27426,16 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + /* APME bit in EEPROM is mapped to WUC.APME */ + eeprom_data = er32(WUC); + eeprom_apme_mask = E1000_WUC_APME; ++ if (eeprom_data & E1000_WUC_PHY_WAKE) ++ adapter->flags2 |= FLAG2_HAS_PHY_WAKEUP; + } else if (adapter->flags & FLAG_APME_IN_CTRL3) { + if (adapter->flags & FLAG_APME_CHECK_PORT_B && + (adapter->hw.bus.func == 1)) -+ hw->nvm.ops.read(&adapter->hw, NVM_INIT_CONTROL3_PORT_B, -+ 1, &eeprom_data); ++ e1000_read_nvm(&adapter->hw, NVM_INIT_CONTROL3_PORT_B, ++ 1, &eeprom_data); + else -+ hw->nvm.ops.read(&adapter->hw, NVM_INIT_CONTROL3_PORT_A, -+ 1, &eeprom_data); ++ e1000_read_nvm(&adapter->hw, NVM_INIT_CONTROL3_PORT_A, ++ 1, &eeprom_data); + } + + /* fetch WoL from EEPROM */ @@ -25913,9 +27452,13 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + + /* initialize the wol settings based on the eeprom settings */ + adapter->wol = adapter->eeprom_wol; ++ device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); ++ ++ /* save off EEPROM version number */ ++ e1000_read_nvm(&adapter->hw, 5, 1, &adapter->eeprom_vers); + + /* reset the hardware with the new settings */ -+ e1000_reset(adapter); ++ e1000e_reset(adapter); + + /* + * If the controller has AMT, do not set DRV_LOAD until the interface @@ -25927,7 +27470,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + + /* tell the stack to leave us alone until e1000_open() is called */ + netif_carrier_off(netdev); -+ netif_stop_queue(netdev); ++ netif_tx_stop_all_queues(netdev); + + strcpy(netdev->name, "eth%d"); + err = register_netdev(netdev); @@ -25942,14 +27485,15 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + if (!(adapter->flags & FLAG_HAS_AMT)) + e1000_release_hw_control(adapter); +err_eeprom: -+ if (hw->phy.ops.check_reset_block && -+ !hw->phy.ops.check_reset_block(hw)) -+ hw->phy.ops.reset(hw); ++ if (!e1000_check_reset_block(&adapter->hw)) ++ e1000_phy_hw_reset(&adapter->hw); +err_hw_init: -+ hw->mac.ops.remove_device(&adapter->hw); + kfree(adapter->tx_ring); + kfree(adapter->rx_ring); +err_sw_init: ++#ifdef CONFIG_E1000E_MSIX ++ e1000e_reset_interrupt_capability(adapter); ++#endif /* CONFIG_E1000E_MSIX */ + if (adapter->hw.flash_address) + iounmap(adapter->hw.flash_address); +err_flashmap: @@ -25957,7 +27501,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +err_ioremap: + free_netdev(netdev); +err_alloc_etherdev: -+ pci_release_regions(pdev); ++ pci_release_selected_regions(pdev, ++ pci_select_bars(pdev, IORESOURCE_MEM)); +err_pci_reg: +err_dma: + pci_disable_device(pdev); @@ -25977,7 +27522,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct e1000_adapter *adapter = netdev_priv(netdev); -+ struct e1000_hw *hw = &adapter->hw; + + /* + * flush_scheduled work may reschedule our watchdog task, so @@ -25997,24 +27541,26 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + + unregister_netdev(netdev); + -+ if (hw->phy.ops.check_reset_block && -+ !hw->phy.ops.check_reset_block(hw)) -+ hw->phy.ops.reset(hw); ++ if (!e1000_check_reset_block(&adapter->hw)) ++ e1000_phy_hw_reset(&adapter->hw); + +#ifdef CONFIG_E1000E_MSIX -+ e1000_reset_interrupt_capability(adapter); ++ e1000e_reset_interrupt_capability(adapter); +#endif /* CONFIG_E1000E_MSIX */ -+ hw->mac.ops.remove_device(&adapter->hw); + kfree(adapter->tx_ring); + kfree(adapter->rx_ring); + + iounmap(adapter->hw.hw_addr); + if (adapter->hw.flash_address) + iounmap(adapter->hw.flash_address); -+ pci_release_regions(pdev); ++ pci_release_selected_regions(pdev, ++ pci_select_bars(pdev, IORESOURCE_MEM)); + + free_netdev(netdev); + ++ /* AER disable */ ++ pci_disable_pcie_error_reporting(pdev); ++ + pci_disable_device(pdev); +} + @@ -26048,6 +27594,8 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82573L), board_82573 }, + + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82574L), board_82574 }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82574LA), board_82574 }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82583V), board_82583 }, + + { PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_COPPER_DPT), + board_80003es2lan }, @@ -26083,6 +27631,11 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LM), board_ich10lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LF), board_ich10lan }, + ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_M_HV_LM), board_pchlan }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_M_HV_LC), board_pchlan }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DM), board_pchlan }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DC), board_pchlan }, ++ + { } /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, e1000e_pci_tbl); @@ -26117,16 +27670,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + int ret; + printk(KERN_INFO "%s: Intel(R) PRO/1000 Network Driver - %s\n", + e1000e_driver_name, e1000e_driver_version); -+ printk(KERN_INFO "%s: Copyright (c) 1999-2008 Intel Corporation.\n", ++ printk(KERN_INFO "%s: Copyright(c) 1999 - 2009 Intel Corporation.\n", + e1000e_driver_name); + ret = pci_register_driver(&e1000_driver); -+ pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, e1000e_driver_name, -+ PM_QOS_DEFAULT_VALUE); +#ifdef USE_REBOOT_NOTIFIER + if (ret >= 0) + register_reboot_notifier(&e1000_notifier_reboot); +#endif -+ ++ + return ret; +} +module_init(e1000_init_module); @@ -26143,7 +27694,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne + unregister_reboot_notifier(&e1000_notifier_reboot); +#endif + pci_unregister_driver(&e1000_driver); -+ pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, e1000e_driver_name); +} +module_exit(e1000_exit_module); + @@ -26156,12 +27706,12 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/netdev.c linux-2.6.22-10/drivers/ne +/* netdev.c */ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/param.c linux-2.6.22-10/drivers/net/e1000e/param.c --- linux-2.6.22-0/drivers/net/e1000e/param.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.22-10/drivers/net/e1000e/param.c 2008-10-14 01:51:32.000000000 +0200 -@@ -0,0 +1,479 @@ ++++ linux-2.6.22-10/drivers/net/e1000e/param.c 2009-06-24 00:32:20.000000000 +0200 +@@ -0,0 +1,466 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver -+ Copyright(c) 1999 - 2008 Intel Corporation. ++ Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, @@ -26218,7 +27768,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/param.c linux-2.6.22-10/drivers/net +/* Module Parameters are always initialized to -1, so that the driver + * can tell the difference between no user specified value or the + * user asking for the default value. -+ * The true default values are loaded in when e1000_check_options is called. ++ * The true default values are loaded in when e1000e_check_options is called. + * + * This is a GCC extension to ANSI C. + * See the item "Labeled Elements in Initializers" in the section @@ -26238,6 +27788,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/param.c linux-2.6.22-10/drivers/net + MODULE_PARM_DESC(X, desc); +#endif + ++ +/* + * Transmit Interrupt Delay in units of 1.024 microseconds + * Tx interrupt delay needs to typically be set to something non zero @@ -26321,15 +27872,14 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/param.c linux-2.6.22-10/drivers/net +E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround"); + +/* -+ * Write Protect NVM ++ * Enable CRC Stripping + * + * Valid Range: 0, 1 + * + * Default Value: 1 (enabled) + */ -+E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can " -+ "lead to corrupted NVM]"); -+ ++E1000_PARAM(CrcStripping, "Enable CRC Stripping, disable if your BMC needs " \ ++ "the CRC"); + +struct e1000_option { + enum { enable_option, range_option, list_option } type; @@ -26399,7 +27949,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/param.c linux-2.6.22-10/drivers/net +} + +/** -+ * e1000_check_options - Range Checking for Command Line Parameters ++ * e1000e_check_options - Range Checking for Command Line Parameters + * @adapter: board private structure + * + * This routine checks all command line parameters for valid user @@ -26407,7 +27957,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/param.c linux-2.6.22-10/drivers/net + * value exists, a default value is used. The final value is stored + * in a variable in the adapter structure. + **/ -+void __devinit e1000_check_options(struct e1000_adapter *adapter) ++void __devinit e1000e_check_options(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + int bd = adapter->bd_number; @@ -26466,15 +28016,6 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/param.c linux-2.6.22-10/drivers/net + .max = MAX_RXDELAY } } + }; + -+ /* -+ * modify min and default if 82573 for slow ping w/a, -+ * a value greater than 8 needs to be set for RDTR -+ */ -+ if (adapter->flags & FLAG_HAS_ASPM) { -+ opt.def = 32; -+ opt.arg.r.min = 8; -+ } -+ + if (num_RxIntDelay > bd) { + adapter->rx_int_delay = RxIntDelay[bd]; + e1000_validate_option(&adapter->rx_int_delay, &opt, @@ -26536,7 +28077,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/param.c linux-2.6.22-10/drivers/net + * change itr. + */ + if (e1000_validate_option(&adapter->itr, &opt, -+ adapter) && ++ adapter) && + (adapter->itr == 3)) { + /* + * In case of invalid user value, @@ -26567,7 +28108,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/param.c linux-2.6.22-10/drivers/net + .err = "defaulting to 2 (MSI-X)", + .def = E1000E_INT_MODE_MSIX, + .arg = { .r = { .min = MIN_INTMODE, -+ .max = MAX_INTMODE }} ++ .max = MAX_INTMODE } } + }; + + if (num_IntMode > bd) { @@ -26595,6 +28136,23 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/param.c linux-2.6.22-10/drivers/net + adapter->flags |= FLAG_SMART_POWER_DOWN; + } + } ++ { /* CRC Stripping */ ++ const struct e1000_option opt = { ++ .type = enable_option, ++ .name = "CRC Stripping", ++ .err = "defaulting to Enabled", ++ .def = OPTION_ENABLED ++ }; ++ ++ if (num_CrcStripping > bd) { ++ unsigned int crc_stripping = CrcStripping[bd]; ++ e1000_validate_option(&crc_stripping, &opt, adapter); ++ if (crc_stripping == OPTION_ENABLED) ++ adapter->flags2 |= FLAG2_CRC_STRIPPING; ++ } else { ++ adapter->flags2 |= FLAG2_CRC_STRIPPING; ++ } ++ } + { /* Kumeran Lock Loss Workaround */ + const struct e1000_option opt = { + .type = enable_option, @@ -26607,39 +28165,18 @@ diff -Nurp linux-2.6.22-0/drivers/net/e1000e/param.c linux-2.6.22-10/drivers/net + unsigned int kmrn_lock_loss = KumeranLockLoss[bd]; + e1000_validate_option(&kmrn_lock_loss, &opt, adapter); + if (hw->mac.type == e1000_ich8lan) -+ e1000_set_kmrn_lock_loss_workaround_ich8lan(hw, ++ e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, + kmrn_lock_loss); + } else { + if (hw->mac.type == e1000_ich8lan) -+ e1000_set_kmrn_lock_loss_workaround_ich8lan(hw, ++ e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, + opt.def); + } + } -+ { /* Write-protect NVM */ -+ const struct e1000_option opt = { -+ .type = enable_option, -+ .name = "Write-protect NVM", -+ .err = "defaulting to Enabled", -+ .def = OPTION_ENABLED -+ }; -+ -+ if (adapter->flags & FLAG_IS_ICH) { -+ if (num_WriteProtectNVM > bd) { -+ unsigned int write_protect_nvm = WriteProtectNVM[bd]; -+ e1000_validate_option(&write_protect_nvm, &opt, -+ adapter); -+ if (write_protect_nvm) -+ adapter->flags2 |= FLAG2_READ_ONLY_NVM; -+ } else { -+ if (opt.def) -+ adapter->flags2 |= FLAG2_READ_ONLY_NVM; -+ } -+ } -+ } +} diff -Nurp linux-2.6.22-0/drivers/net/Kconfig linux-2.6.22-10/drivers/net/Kconfig --- linux-2.6.22-0/drivers/net/Kconfig 2007-07-09 01:32:17.000000000 +0200 -+++ linux-2.6.22-10/drivers/net/Kconfig 2008-11-10 00:06:46.000000000 +0100 ++++ linux-2.6.22-10/drivers/net/Kconfig 2009-08-27 23:57:46.000000000 +0200 @@ -1993,6 +1993,29 @@ config E1000_DISABLE_PACKET_SPLIT If in doubt, say N. @@ -26672,7 +28209,7 @@ diff -Nurp linux-2.6.22-0/drivers/net/Kconfig linux-2.6.22-10/drivers/net/Kconfi config MYRI_SBUS diff -Nurp linux-2.6.22-0/drivers/net/Makefile linux-2.6.22-10/drivers/net/Makefile --- linux-2.6.22-0/drivers/net/Makefile 2007-07-09 01:32:17.000000000 +0200 -+++ linux-2.6.22-10/drivers/net/Makefile 2008-11-10 00:02:57.000000000 +0100 ++++ linux-2.6.22-10/drivers/net/Makefile 2009-08-27 23:57:06.000000000 +0200 @@ -3,6 +3,7 @@ #