diff options
author | jfv <jfv@FreeBSD.org> | 2008-11-26 23:57:23 +0000 |
---|---|---|
committer | jfv <jfv@FreeBSD.org> | 2008-11-26 23:57:23 +0000 |
commit | acf860ad541ce9529aff0bf17061183badd98903 (patch) | |
tree | b0f0b3a2e29a0fc9f60b8bee9111f6827eb01416 /sys/dev/e1000/e1000_82575.c | |
parent | 62188214bdac09b8b3fe223bd994d8aef28db6db (diff) | |
download | FreeBSD-src-acf860ad541ce9529aff0bf17061183badd98903.zip FreeBSD-src-acf860ad541ce9529aff0bf17061183badd98903.tar.gz |
This delta is primarily a fix for es2lan devices that
will sometimes fail to initialize problem due to a lock
contention with management hardware. However, in order to
deliver that fix it was necessary to take a shared code
update as a whole, and this required scattered changes in
the core code to be compatible.
The em driver now has VLAN HW support added as the igb
driver had previously.
MFC after: ASAP - in time for 7.1 RELEASE
Diffstat (limited to 'sys/dev/e1000/e1000_82575.c')
-rw-r--r-- | sys/dev/e1000/e1000_82575.c | 262 |
1 files changed, 74 insertions, 188 deletions
diff --git a/sys/dev/e1000/e1000_82575.c b/sys/dev/e1000/e1000_82575.c index 2fbc0c3..3d16447 100644 --- a/sys/dev/e1000/e1000_82575.c +++ b/sys/dev/e1000/e1000_82575.c @@ -32,8 +32,11 @@ ******************************************************************************/ /*$FreeBSD$*/ -/* e1000_82575 - * e1000_82576 +/* + * 82575EB Gigabit Network Connection + * 82575EB Gigabit Backplane Connection + * 82575GB Gigabit Network Connection + * 82576 Gigabit Network Connection */ #include "e1000_api.h" @@ -77,18 +80,11 @@ static void e1000_init_rx_addrs_82575(struct e1000_hw *hw, u16 rar_count); static void e1000_update_mc_addr_list_82575(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, u32 rar_used_count, u32 rar_count); -void e1000_remove_device_82575(struct e1000_hw *hw); void e1000_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw); -struct e1000_dev_spec_82575 { - bool sgmii_active; -}; - /** * e1000_init_phy_params_82575 - 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_82575(struct e1000_hw *hw) { @@ -158,8 +154,6 @@ out: /** * e1000_init_nvm_params_82575 - 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_82575(struct e1000_hw *hw) { @@ -217,27 +211,15 @@ static s32 e1000_init_nvm_params_82575(struct e1000_hw *hw) /** * e1000_init_mac_params_82575 - 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_82575(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; - struct e1000_dev_spec_82575 *dev_spec; + struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; u32 ctrl_ext = 0; - s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_init_mac_params_82575"); - hw->dev_spec_size = sizeof(struct e1000_dev_spec_82575); - - /* Device-specific structure allocation */ - ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size); - if (ret_val) - goto out; - - dev_spec = (struct e1000_dev_spec_82575 *)hw->dev_spec; - /* Set media type */ /* * The 82575 uses bits 22:23 for link mode. The mode can be changed @@ -315,23 +297,19 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) /* 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_82575; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82575; /* link info */ mac->ops.get_link_up_info = e1000_get_link_up_info_82575; -out: - return ret_val; + return E1000_SUCCESS; } /** * e1000_init_function_pointers_82575 - 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_82575(struct e1000_hw *hw) { @@ -346,8 +324,7 @@ void e1000_init_function_pointers_82575(struct e1000_hw *hw) * e1000_acquire_phy_82575 - Acquire rights to access PHY * @hw: pointer to the HW structure * - * Acquire access rights to the correct PHY. This is a - * function pointer entry point called by the api module. + * Acquire access rights to the correct PHY. **/ static s32 e1000_acquire_phy_82575(struct e1000_hw *hw) { @@ -364,8 +341,7 @@ static s32 e1000_acquire_phy_82575(struct e1000_hw *hw) * e1000_release_phy_82575 - 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_82575(struct e1000_hw *hw) { @@ -1032,7 +1008,7 @@ static void e1000_update_mc_addr_list_82575(struct e1000_hw *hw, /* 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); + hash_value = e1000_hash_mc_addr(hw, mc_addr_list); DEBUGOUT1("Hash value = 0x%03X\n", hash_value); hw->mac.ops.mta_set(hw, hash_value); mc_addr_list += ETH_ADDR_LEN; @@ -1049,14 +1025,22 @@ static void e1000_update_mc_addr_list_82575(struct e1000_hw *hw, void e1000_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw) { u32 reg; + u16 eeprom_data = 0; if (hw->mac.type != e1000_82576 || (hw->phy.media_type != e1000_media_type_fiber && hw->phy.media_type != e1000_media_type_internal_serdes)) return; - /* if the management interface is not enabled, then power down */ - if (!e1000_enable_mng_pass_thru(hw)) { + if (hw->bus.func == 0) + hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); + + /* + * If APM is not enabled in the EEPROM and management interface is + * not enabled, then power down. + */ + if (!(eeprom_data & E1000_NVM_APME_82575) && + !e1000_enable_mng_pass_thru(hw)) { /* Disable PCS to turn off link */ reg = E1000_READ_REG(hw, E1000_PCS_CFG0); reg &= ~E1000_PCS_CFG_PCS_EN; @@ -1079,8 +1063,7 @@ void e1000_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw) * e1000_reset_hw_82575 - 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_82575(struct e1000_hw *hw) { @@ -1462,86 +1445,14 @@ out: **/ static bool e1000_sgmii_active_82575(struct e1000_hw *hw) { - struct e1000_dev_spec_82575 *dev_spec; - bool ret_val; + struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; DEBUGFUNC("e1000_sgmii_active_82575"); - if (hw->mac.type != e1000_82575 && hw->mac.type != e1000_82576) { - ret_val = FALSE; - goto out; - } - - dev_spec = (struct e1000_dev_spec_82575 *)hw->dev_spec; + if (hw->mac.type != e1000_82575 && hw->mac.type != e1000_82576) + return FALSE; - ret_val = dev_spec->sgmii_active; - -out: - return ret_val; -} - -/** - * e1000_translate_register_82576 - Translate the proper register offset - * @reg: e1000 register to be read - * - * Registers in 82576 are located in different offsets than other adapters - * even though they function in the same manner. This function takes in - * the name of the register to read and returns the correct offset for - * 82576 silicon. - **/ -u32 e1000_translate_register_82576(u32 reg) -{ - /* - * Some of the 82576 registers are located at different - * offsets than they are in older adapters. - * Despite the difference in location, the registers - * function in the same manner. - */ - switch (reg) { - case E1000_TDBAL(0): - reg = 0x0E000; - break; - case E1000_TDBAH(0): - reg = 0x0E004; - break; - case E1000_TDLEN(0): - reg = 0x0E008; - break; - case E1000_TDH(0): - reg = 0x0E010; - break; - case E1000_TDT(0): - reg = 0x0E018; - break; - case E1000_TXDCTL(0): - reg = 0x0E028; - break; - case E1000_RDBAL(0): - reg = 0x0C000; - break; - case E1000_RDBAH(0): - reg = 0x0C004; - break; - case E1000_RDLEN(0): - reg = 0x0C008; - break; - case E1000_RDH(0): - reg = 0x0C010; - break; - case E1000_RDT(0): - reg = 0x0C018; - break; - case E1000_RXDCTL(0): - reg = 0x0C028; - break; - case E1000_SRRCTL(0): - reg = 0x0C00C; - break; - default: - break; - } - - return reg; + return dev_spec->sgmii_active; } /** @@ -1620,30 +1531,6 @@ static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw) } /** - * e1000_remove_device_82575 - Free device specific structure - * @hw: pointer to the HW structure - * - * If a device specific structure was allocated, this function will - * free it after shutting down the serdes interface if available. - **/ -void e1000_remove_device_82575(struct e1000_hw *hw) -{ - u16 eeprom_data = 0; - - /* - * If APM is enabled in the EEPROM then leave the port on for fiber - * serdes adapters. - */ - if (hw->bus.func == 0) - hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); - - if (!(eeprom_data & E1000_NVM_APME_82575)) - e1000_shutdown_fiber_serdes_link_82575(hw); - - e1000_remove_device_generic(hw); -} - -/** * e1000_clear_hw_cntrs_82575 - Clear device specific hardware counters * @hw: pointer to the HW structure * @@ -1651,62 +1538,60 @@ void e1000_remove_device_82575(struct e1000_hw *hw) **/ static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw) { - volatile u32 temp; - DEBUGFUNC("e1000_clear_hw_cntrs_82575"); e1000_clear_hw_cntrs_base_generic(hw); - temp = E1000_READ_REG(hw, E1000_PRC64); - temp = E1000_READ_REG(hw, E1000_PRC127); - temp = E1000_READ_REG(hw, E1000_PRC255); - temp = E1000_READ_REG(hw, E1000_PRC511); - temp = E1000_READ_REG(hw, E1000_PRC1023); - temp = E1000_READ_REG(hw, E1000_PRC1522); - temp = E1000_READ_REG(hw, E1000_PTC64); - temp = E1000_READ_REG(hw, E1000_PTC127); - temp = E1000_READ_REG(hw, E1000_PTC255); - temp = E1000_READ_REG(hw, E1000_PTC511); - temp = E1000_READ_REG(hw, E1000_PTC1023); - temp = E1000_READ_REG(hw, E1000_PTC1522); - - temp = E1000_READ_REG(hw, E1000_ALGNERRC); - temp = E1000_READ_REG(hw, E1000_RXERRC); - temp = E1000_READ_REG(hw, E1000_TNCRS); - temp = E1000_READ_REG(hw, E1000_CEXTERR); - temp = E1000_READ_REG(hw, E1000_TSCTC); - temp = E1000_READ_REG(hw, E1000_TSCTFC); - - temp = E1000_READ_REG(hw, E1000_MGTPRC); - temp = E1000_READ_REG(hw, E1000_MGTPDC); - temp = E1000_READ_REG(hw, E1000_MGTPTC); - - temp = E1000_READ_REG(hw, E1000_IAC); - temp = E1000_READ_REG(hw, E1000_ICRXOC); - - temp = E1000_READ_REG(hw, E1000_ICRXPTC); - temp = E1000_READ_REG(hw, E1000_ICRXATC); - temp = E1000_READ_REG(hw, E1000_ICTXPTC); - temp = E1000_READ_REG(hw, E1000_ICTXATC); - temp = E1000_READ_REG(hw, E1000_ICTXQEC); - temp = E1000_READ_REG(hw, E1000_ICTXQMTC); - temp = E1000_READ_REG(hw, E1000_ICRXDMTC); - - temp = E1000_READ_REG(hw, E1000_CBTMPC); - temp = E1000_READ_REG(hw, E1000_HTDPMC); - temp = E1000_READ_REG(hw, E1000_CBRMPC); - temp = E1000_READ_REG(hw, E1000_RPTHC); - temp = E1000_READ_REG(hw, E1000_HGPTC); - temp = E1000_READ_REG(hw, E1000_HTCBDPC); - temp = E1000_READ_REG(hw, E1000_HGORCL); - temp = E1000_READ_REG(hw, E1000_HGORCH); - temp = E1000_READ_REG(hw, E1000_HGOTCL); - temp = E1000_READ_REG(hw, E1000_HGOTCH); - temp = E1000_READ_REG(hw, E1000_LENERRS); + E1000_READ_REG(hw, E1000_PRC64); + E1000_READ_REG(hw, E1000_PRC127); + E1000_READ_REG(hw, E1000_PRC255); + E1000_READ_REG(hw, E1000_PRC511); + E1000_READ_REG(hw, E1000_PRC1023); + E1000_READ_REG(hw, E1000_PRC1522); + E1000_READ_REG(hw, E1000_PTC64); + E1000_READ_REG(hw, E1000_PTC127); + E1000_READ_REG(hw, E1000_PTC255); + E1000_READ_REG(hw, E1000_PTC511); + E1000_READ_REG(hw, E1000_PTC1023); + E1000_READ_REG(hw, E1000_PTC1522); + + E1000_READ_REG(hw, E1000_ALGNERRC); + E1000_READ_REG(hw, E1000_RXERRC); + E1000_READ_REG(hw, E1000_TNCRS); + E1000_READ_REG(hw, E1000_CEXTERR); + E1000_READ_REG(hw, E1000_TSCTC); + E1000_READ_REG(hw, E1000_TSCTFC); + + E1000_READ_REG(hw, E1000_MGTPRC); + E1000_READ_REG(hw, E1000_MGTPDC); + E1000_READ_REG(hw, E1000_MGTPTC); + + E1000_READ_REG(hw, E1000_IAC); + E1000_READ_REG(hw, E1000_ICRXOC); + + E1000_READ_REG(hw, E1000_ICRXPTC); + E1000_READ_REG(hw, E1000_ICRXATC); + E1000_READ_REG(hw, E1000_ICTXPTC); + E1000_READ_REG(hw, E1000_ICTXATC); + E1000_READ_REG(hw, E1000_ICTXQEC); + E1000_READ_REG(hw, E1000_ICTXQMTC); + E1000_READ_REG(hw, E1000_ICRXDMTC); + + E1000_READ_REG(hw, E1000_CBTMPC); + E1000_READ_REG(hw, E1000_HTDPMC); + E1000_READ_REG(hw, E1000_CBRMPC); + E1000_READ_REG(hw, E1000_RPTHC); + E1000_READ_REG(hw, E1000_HGPTC); + E1000_READ_REG(hw, E1000_HTCBDPC); + E1000_READ_REG(hw, E1000_HGORCL); + E1000_READ_REG(hw, E1000_HGORCH); + E1000_READ_REG(hw, E1000_HGOTCL); + E1000_READ_REG(hw, E1000_HGOTCH); + E1000_READ_REG(hw, E1000_LENERRS); /* This register should not be read in copper configurations */ if (hw->phy.media_type == e1000_media_type_internal_serdes) - temp = E1000_READ_REG(hw, E1000_SCVPC); + E1000_READ_REG(hw, E1000_SCVPC); } /** * e1000_rx_fifo_flush_82575 - Clean rx fifo after RX enable @@ -1781,3 +1666,4 @@ void e1000_rx_fifo_flush_82575(struct e1000_hw *hw) E1000_READ_REG(hw, E1000_RNBC); E1000_READ_REG(hw, E1000_MPC); } + |