diff options
Diffstat (limited to 'sys/dev/e1000/e1000_mac.c')
-rw-r--r-- | sys/dev/e1000/e1000_mac.c | 598 |
1 files changed, 275 insertions, 323 deletions
diff --git a/sys/dev/e1000/e1000_mac.c b/sys/dev/e1000/e1000_mac.c index 4fc2a7c..95d6873 100644 --- a/sys/dev/e1000/e1000_mac.c +++ b/sys/dev/e1000/e1000_mac.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2011, Intel Corporation + Copyright (c) 2001-2012, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -36,6 +36,8 @@ static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw); static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw); +static void e1000_config_collision_dist_generic(struct e1000_hw *hw); +static void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index); /** * e1000_init_mac_ops_generic - Initialize MAC function pointers @@ -395,30 +397,30 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &nvm_data); if (ret_val) - goto out; + return ret_val; /* not supported on older hardware or 82573 */ if ((hw->mac.type < e1000_82571) || (hw->mac.type == e1000_82573)) - goto out; + return E1000_SUCCESS; /* * Alternate MAC address is handled by the option ROM for 82580 * and newer. SW support not required. */ if (hw->mac.type >= e1000_82580) - goto out; + return E1000_SUCCESS; ret_val = hw->nvm.ops.read(hw, NVM_ALT_MAC_ADDR_PTR, 1, &nvm_alt_mac_addr_offset); if (ret_val) { DEBUGOUT("NVM Read Error\n"); - goto out; + return ret_val; } if ((nvm_alt_mac_addr_offset == 0xFFFF) || (nvm_alt_mac_addr_offset == 0x0000)) /* There is no Alternate MAC Address */ - goto out; + return E1000_SUCCESS; if (hw->bus.func == E1000_FUNC_1) nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1; @@ -432,7 +434,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); - goto out; + return ret_val; } alt_mac_addr[i] = (u8)(nvm_data & 0xFF); @@ -442,7 +444,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) /* if multicast bit is set, the alternate address will not be used */ if (alt_mac_addr[0] & 0x01) { DEBUGOUT("Ignoring Alternate Mac Address with MC bit set\n"); - goto out; + return E1000_SUCCESS; } /* @@ -452,8 +454,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) */ hw->mac.ops.rar_set(hw, alt_mac_addr, 0); -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -465,7 +466,7 @@ out: * 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) +static void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) { u32 rar_low, rar_high; @@ -496,43 +497,6 @@ void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) } /** - * e1000_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 - * - * Updates entire Multicast Table Array. - * The caller must have a packed mc_addr_list of multicast addresses. - **/ -void e1000_update_mc_addr_list_generic(struct e1000_hw *hw, - u8 *mc_addr_list, u32 mc_addr_count) -{ - 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)); - - /* 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); - - hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); - hash_bit = hash_value & 0x1F; - - hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit); - mc_addr_list += (ETH_ADDR_LEN); - } - - /* replace the entire MTA table */ - for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]); - E1000_WRITE_FLUSH(hw); -} - -/** * e1000_hash_mc_addr_generic - Generate a multicast hash value * @hw: pointer to the HW structure * @mc_addr: pointer to a multicast address @@ -605,6 +569,43 @@ u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr) } /** + * e1000_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 + * + * Updates entire Multicast Table Array. + * The caller must have a packed mc_addr_list of multicast addresses. + **/ +void e1000_update_mc_addr_list_generic(struct e1000_hw *hw, + u8 *mc_addr_list, u32 mc_addr_count) +{ + 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)); + + /* 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); + + hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); + hash_bit = hash_value & 0x1F; + + hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit); + mc_addr_list += (ETH_ADDR_LEN); + } + + /* replace the entire MTA table */ + for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) + E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]); + E1000_WRITE_FLUSH(hw); +} + +/** * e1000_pcix_mmrbc_workaround_generic - Fix incorrect MMRBC value * @hw: pointer to the HW structure * @@ -712,10 +713,8 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw) * 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; - } + if (!mac->get_link_status) + return E1000_SUCCESS; /* * First we want to see if the MII Status Register reports @@ -724,10 +723,10 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw) */ ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) - goto out; + return ret_val; if (!link) - goto out; /* No link detected */ + return E1000_SUCCESS; /* No link detected */ mac->get_link_status = FALSE; @@ -741,10 +740,8 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw) * 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; - } + if (!mac->autoneg) + return -E1000_ERR_CONFIG; /* * Auto-Neg is enabled. Auto Speed Detection takes care @@ -763,7 +760,6 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw) if (ret_val) DEBUGOUT("Error configuring flow control\n"); -out: return ret_val; } @@ -780,7 +776,7 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw) u32 rxcw; u32 ctrl; u32 status; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; DEBUGFUNC("e1000_check_for_fiber_link_generic"); @@ -797,11 +793,11 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw) * was just plugged in. The autoneg_failed flag does this. */ /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ - if ((ctrl & E1000_CTRL_SWDPIN1) && (!(status & E1000_STATUS_LU)) && - (!(rxcw & E1000_RXCW_C))) { - if (mac->autoneg_failed == 0) { - mac->autoneg_failed = 1; - goto out; + if ((ctrl & E1000_CTRL_SWDPIN1) && !(status & E1000_STATUS_LU) && + !(rxcw & E1000_RXCW_C)) { + if (!mac->autoneg_failed) { + mac->autoneg_failed = TRUE; + return E1000_SUCCESS; } DEBUGOUT("NOT Rx'ing /C/, disable AutoNeg and force link.\n"); @@ -817,7 +813,7 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw) ret_val = e1000_config_fc_after_link_up_generic(hw); if (ret_val) { DEBUGOUT("Error configuring flow control\n"); - goto out; + return ret_val; } } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { /* @@ -833,8 +829,7 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw) mac->serdes_has_link = TRUE; } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -850,7 +845,7 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw) u32 rxcw; u32 ctrl; u32 status; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; DEBUGFUNC("e1000_check_for_serdes_link_generic"); @@ -866,10 +861,10 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw) * time to complete. */ /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ - if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) { - if (mac->autoneg_failed == 0) { - mac->autoneg_failed = 1; - goto out; + if (!(status & E1000_STATUS_LU) && !(rxcw & E1000_RXCW_C)) { + if (!mac->autoneg_failed) { + mac->autoneg_failed = TRUE; + return E1000_SUCCESS; } DEBUGOUT("NOT Rx'ing /C/, disable AutoNeg and force link.\n"); @@ -885,7 +880,7 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw) ret_val = e1000_config_fc_after_link_up_generic(hw); if (ret_val) { DEBUGOUT("Error configuring flow control\n"); - goto out; + return ret_val; } } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { /* @@ -943,8 +938,48 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw) } } -out: - return ret_val; + return E1000_SUCCESS; +} + +/** + * e1000_set_default_fc_generic - Set flow control default values + * @hw: pointer to the HW structure + * + * Read the EEPROM for the default values for flow control and store the + * values. + **/ +s32 e1000_set_default_fc_generic(struct e1000_hw *hw) +{ + s32 ret_val; + 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, + * a bit that determines whether the HW defaults to enabling or + * disabling auto-negotiation, and the direction of the + * SW defined pins. If there is no SW over-ride of the flow + * 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); + + if (ret_val) { + DEBUGOUT("NVM Read Error\n"); + return ret_val; + } + + if (!(nvm_data & NVM_WORD0F_PAUSE_MASK)) + hw->fc.requested_mode = e1000_fc_none; + else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == + NVM_WORD0F_ASM_DIR) + hw->fc.requested_mode = e1000_fc_tx_pause; + else + hw->fc.requested_mode = e1000_fc_full; + + return E1000_SUCCESS; } /** @@ -959,7 +994,7 @@ out: **/ s32 e1000_setup_link_generic(struct e1000_hw *hw) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; DEBUGFUNC("e1000_setup_link_generic"); @@ -967,8 +1002,8 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw) * In the case of the phy reset being blocked, we already have a link. * We do not need to set it up again. */ - if (e1000_check_reset_block(hw)) - goto out; + if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) + return E1000_SUCCESS; /* * If requested flow control is set to default, set flow control @@ -977,7 +1012,7 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw) if (hw->fc.requested_mode == e1000_fc_default) { ret_val = e1000_set_default_fc_generic(hw); if (ret_val) - goto out; + return ret_val; } /* @@ -992,7 +1027,7 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw) /* Call the necessary media_type subroutine to configure the link. */ ret_val = hw->mac.ops.setup_physical_interface(hw); if (ret_val) - goto out; + return ret_val; /* * Initialize the flow control address, type, and PAUSE timer @@ -1007,87 +1042,80 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time); - ret_val = e1000_set_fc_watermarks_generic(hw); - -out: - return ret_val; + return e1000_set_fc_watermarks_generic(hw); } /** - * e1000_setup_fiber_serdes_link_generic - Setup link for fiber/serdes + * e1000_commit_fc_settings_generic - Configure flow control * @hw: pointer to the HW structure * - * Configures collision distance and flow control for fiber and serdes - * links. Upon successful setup, poll for link. + * Write the flow control settings to the Transmit Config Word Register (TXCW) + * base on the flow control settings in e1000_mac_info. **/ -s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw) +s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; - u32 ctrl; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_setup_fiber_serdes_link_generic"); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - - /* Take the link out of reset */ - ctrl &= ~E1000_CTRL_LRST; - - mac->ops.config_collision_dist(hw); - - ret_val = e1000_commit_fc_settings_generic(hw); - if (ret_val) - goto out; - - /* - * Since auto-negotiation is enabled, take the link out of reset (the - * link will be in reset, because we previously reset the chip). This - * will restart auto-negotiation. If auto-negotiation is successful - * 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"); + u32 txcw; - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - msec_delay(1); + DEBUGFUNC("e1000_commit_fc_settings_generic"); /* - * For these adapters, the SW definable pin 1 is set when the optics - * detect a signal. If we have a signal, then poll for a "Link-Up" - * indication. + * Check for a software override of the flow control settings, and + * setup the device accordingly. If auto-negotiation is enabled, then + * software will have to set the "PAUSE" bits to the correct value in + * the Transmit Config Word Register (TXCW) and re-start auto- + * negotiation. However, if auto-negotiation is disabled, then + * software will have to manually configure the two flow control enable + * bits in the CTRL register. + * + * The possible values of the "fc" parameter are: + * 0: Flow control is completely disabled + * 1: Rx flow control is enabled (we can receive pause frames, + * but not send pause frames). + * 2: Tx flow control is enabled (we can send pause frames but we + * do not support receiving pause frames). + * 3: Both Rx and Tx flow control (symmetric) are enabled. */ - if (hw->phy.media_type == e1000_media_type_internal_serdes || - (E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) { - ret_val = e1000_poll_fiber_serdes_link_generic(hw); - } else { - DEBUGOUT("No signal detected\n"); + 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); + break; + case e1000_fc_rx_pause: + /* + * Rx Flow control is enabled and Tx Flow control is disabled + * by a software over-ride. Since there really isn't a way to + * advertise that we are capable of Rx Pause ONLY, we will + * advertise that we support both symmetric and asymmetric Rx + * PAUSE. Later, we will disable the adapter's ability to send + * PAUSE frames. + */ + txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); + break; + case e1000_fc_tx_pause: + /* + * Tx Flow control is enabled, and Rx Flow control is disabled, + * by a software over-ride. + */ + txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); + break; + case e1000_fc_full: + /* + * Flow control (both Rx and Tx) is enabled by a software + * over-ride. + */ + txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); + break; + default: + DEBUGOUT("Flow control param set incorrectly\n"); + return -E1000_ERR_CONFIG; + break; } -out: - return ret_val; -} - -/** - * e1000_config_collision_dist_generic - Configure collision distance - * @hw: pointer to the HW structure - * - * Configures the collision distance to the default value and is used - * during link setup. - **/ -void e1000_config_collision_dist_generic(struct e1000_hw *hw) -{ - u32 tctl; - - DEBUGFUNC("e1000_config_collision_dist_generic"); - - tctl = E1000_READ_REG(hw, E1000_TCTL); - - tctl &= ~E1000_TCTL_COLD; - tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; + E1000_WRITE_REG(hw, E1000_TXCW, txcw); + mac->txcw = txcw; - E1000_WRITE_REG(hw, E1000_TCTL, tctl); - E1000_WRITE_FLUSH(hw); + return E1000_SUCCESS; } /** @@ -1101,7 +1129,7 @@ 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; + s32 ret_val; DEBUGFUNC("e1000_poll_fiber_serdes_link_generic"); @@ -1120,7 +1148,7 @@ s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) } if (i == FIBER_LINK_UP_LIMIT) { DEBUGOUT("Never got a valid link from auto-neg!!!\n"); - mac->autoneg_failed = 1; + mac->autoneg_failed = TRUE; /* * AutoNeg failed to achieve a link, so we'll call * mac->check_for_link. This routine will force the @@ -1130,95 +1158,93 @@ s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) ret_val = mac->ops.check_for_link(hw); if (ret_val) { DEBUGOUT("Error while checking for link\n"); - goto out; + return ret_val; } - mac->autoneg_failed = 0; + mac->autoneg_failed = FALSE; } else { - mac->autoneg_failed = 0; + mac->autoneg_failed = FALSE; DEBUGOUT("Valid Link Found\n"); } -out: - return ret_val; + return E1000_SUCCESS; } /** - * e1000_commit_fc_settings_generic - Configure flow control + * e1000_setup_fiber_serdes_link_generic - Setup link for fiber/serdes * @hw: pointer to the HW structure * - * Write the flow control settings to the Transmit Config Word Register (TXCW) - * base on the flow control settings in e1000_mac_info. + * Configures collision distance and flow control for fiber and serdes + * links. Upon successful setup, poll for link. **/ -s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) +s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw) { - struct e1000_mac_info *mac = &hw->mac; - u32 txcw; - s32 ret_val = E1000_SUCCESS; + u32 ctrl; + s32 ret_val; - DEBUGFUNC("e1000_commit_fc_settings_generic"); + DEBUGFUNC("e1000_setup_fiber_serdes_link_generic"); + + ctrl = E1000_READ_REG(hw, E1000_CTRL); + + /* Take the link out of reset */ + ctrl &= ~E1000_CTRL_LRST; + + hw->mac.ops.config_collision_dist(hw); + + ret_val = e1000_commit_fc_settings_generic(hw); + if (ret_val) + return ret_val; /* - * Check for a software override of the flow control settings, and - * setup the device accordingly. If auto-negotiation is enabled, then - * software will have to set the "PAUSE" bits to the correct value in - * the Transmit Config Word Register (TXCW) and re-start auto- - * negotiation. However, if auto-negotiation is disabled, then - * software will have to manually configure the two flow control enable - * bits in the CTRL register. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames, - * but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames but we - * do not support receiving pause frames). - * 3: Both Rx and Tx flow control (symmetric) are enabled. + * Since auto-negotiation is enabled, take the link out of reset (the + * link will be in reset, because we previously reset the chip). This + * will restart auto-negotiation. If auto-negotiation is successful + * 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. */ - 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); - break; - case e1000_fc_rx_pause: - /* - * Rx Flow control is enabled and Tx Flow control is disabled - * by a software over-ride. Since there really isn't a way to - * advertise that we are capable of Rx Pause ONLY, we will - * advertise that we support both symmetric and asymmetric Rx - * PAUSE. Later, we will disable the adapter's ability to send - * PAUSE frames. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - case e1000_fc_tx_pause: - /* - * Tx Flow control is enabled, and Rx Flow control is disabled, - * by a software over-ride. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); - break; - case e1000_fc_full: - /* - * Flow control (both Rx and Tx) is enabled by a software - * over-ride. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - default: - DEBUGOUT("Flow control param set incorrectly\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - break; - } + DEBUGOUT("Auto-negotiation enabled\n"); - E1000_WRITE_REG(hw, E1000_TXCW, txcw); - mac->txcw = txcw; + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + E1000_WRITE_FLUSH(hw); + msec_delay(1); + + /* + * For these adapters, the SW definable pin 1 is set when the optics + * detect a signal. If we have a signal, then poll for a "Link-Up" + * indication. + */ + if (hw->phy.media_type == e1000_media_type_internal_serdes || + (E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) { + ret_val = e1000_poll_fiber_serdes_link_generic(hw); + } else { + DEBUGOUT("No signal detected\n"); + } -out: return ret_val; } /** + * e1000_config_collision_dist_generic - Configure collision distance + * @hw: pointer to the HW structure + * + * Configures the collision distance to the default value and is used + * during link setup. + **/ +static void e1000_config_collision_dist_generic(struct e1000_hw *hw) +{ + u32 tctl; + + DEBUGFUNC("e1000_config_collision_dist_generic"); + + tctl = E1000_READ_REG(hw, E1000_TCTL); + + tctl &= ~E1000_TCTL_COLD; + tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; + + E1000_WRITE_REG(hw, E1000_TCTL, tctl); + E1000_WRITE_FLUSH(hw); +} + +/** * e1000_set_fc_watermarks_generic - Set flow control high/low watermarks * @hw: pointer to the HW structure * @@ -1258,48 +1284,6 @@ s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw) } /** - * e1000_set_default_fc_generic - Set flow control default values - * @hw: pointer to the HW structure - * - * Read the EEPROM for the default values for flow control and store the - * values. - **/ -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, - * a bit that determines whether the HW defaults to enabling or - * disabling auto-negotiation, and the direction of the - * SW defined pins. If there is no SW over-ride of the flow - * 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); - - if (ret_val) { - DEBUGOUT("NVM Read Error\n"); - goto out; - } - - if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0) - hw->fc.requested_mode = e1000_fc_none; - else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == - NVM_WORD0F_ASM_DIR) - hw->fc.requested_mode = e1000_fc_tx_pause; - else - hw->fc.requested_mode = e1000_fc_full; - -out: - return ret_val; -} - -/** * e1000_force_mac_fc_generic - Force the MAC's flow control settings * @hw: pointer to the HW structure * @@ -1312,7 +1296,6 @@ out: s32 e1000_force_mac_fc_generic(struct e1000_hw *hw) { u32 ctrl; - s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_force_mac_fc_generic"); @@ -1355,14 +1338,12 @@ s32 e1000_force_mac_fc_generic(struct e1000_hw *hw) break; default: DEBUGOUT("Flow control param set incorrectly\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; + return -E1000_ERR_CONFIG; } E1000_WRITE_REG(hw, E1000_CTRL, ctrl); -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -1400,7 +1381,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) if (ret_val) { DEBUGOUT("Error forcing flow control settings\n"); - goto out; + return ret_val; } /* @@ -1417,14 +1398,14 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) */ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); if (ret_val) - goto out; + return ret_val; ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); if (ret_val) - goto out; + return ret_val; if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) { DEBUGOUT("Copper PHY and Auto Neg has not completed.\n"); - goto out; + return ret_val; } /* @@ -1437,11 +1418,11 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg); if (ret_val) - goto out; + return ret_val; ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg); if (ret_val) - goto out; + return ret_val; /* * Two bits in the Auto Negotiation Advertisement Register @@ -1540,7 +1521,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex); if (ret_val) { DEBUGOUT("Error getting link speed and duplex\n"); - goto out; + return ret_val; } if (duplex == HALF_DUPLEX) @@ -1553,12 +1534,11 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) ret_val = e1000_force_mac_fc_generic(hw); if (ret_val) { DEBUGOUT("Error forcing flow control settings\n"); - goto out; + return ret_val; } } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -1629,7 +1609,6 @@ s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw, s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw) { u32 swsm; - s32 ret_val = E1000_SUCCESS; s32 timeout = hw->nvm.word_size + 1; s32 i = 0; @@ -1647,8 +1626,7 @@ s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw) if (i == timeout) { DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); - ret_val = -E1000_ERR_NVM; - goto out; + return -E1000_ERR_NVM; } /* Get the FW semaphore. */ @@ -1667,12 +1645,10 @@ s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw) /* Release semaphores */ e1000_put_hw_semaphore_generic(hw); DEBUGOUT("Driver can't access the NVM\n"); - ret_val = -E1000_ERR_NVM; - goto out; + return -E1000_ERR_NVM; } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -1703,7 +1679,6 @@ void e1000_put_hw_semaphore_generic(struct e1000_hw *hw) s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw) { s32 i = 0; - s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_get_auto_rd_done_generic"); @@ -1716,12 +1691,10 @@ s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw) if (i == AUTO_READ_DONE_TIMEOUT) { DEBUGOUT("Auto read by HW from NVM has not completed.\n"); - ret_val = -E1000_ERR_RESET; - goto out; + return -E1000_ERR_RESET; } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -1741,14 +1714,13 @@ s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data) ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); - goto out; + return ret_val; } if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) *data = ID_LED_DEFAULT; -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -1770,7 +1742,7 @@ s32 e1000_id_led_init_generic(struct e1000_hw *hw) ret_val = hw->nvm.ops.valid_led_default(hw, &data); if (ret_val) - goto out; + return ret_val; mac->ledctl_default = E1000_READ_REG(hw, E1000_LEDCTL); mac->ledctl_mode1 = mac->ledctl_default; @@ -1814,8 +1786,7 @@ s32 e1000_id_led_init_generic(struct e1000_hw *hw) } } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -1828,14 +1799,11 @@ out: s32 e1000_setup_led_generic(struct e1000_hw *hw) { 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->mac.ops.setup_led != e1000_setup_led_generic) + return -E1000_ERR_CONFIG; if (hw->phy.media_type == e1000_media_type_fiber) { ledctl = E1000_READ_REG(hw, E1000_LEDCTL); @@ -1850,8 +1818,7 @@ s32 e1000_setup_led_generic(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -1976,7 +1943,7 @@ void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop) DEBUGFUNC("e1000_set_pcie_no_snoop_generic"); if (hw->bus.type != e1000_bus_type_pci_express) - goto out; + return; if (no_snoop) { gcr = E1000_READ_REG(hw, E1000_GCR); @@ -1984,8 +1951,6 @@ void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop) gcr |= no_snoop; E1000_WRITE_REG(hw, E1000_GCR, gcr); } -out: - return; } /** @@ -2003,12 +1968,11 @@ s32 e1000_disable_pcie_master_generic(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; + return E1000_SUCCESS; ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= E1000_CTRL_GIO_MASTER_DISABLE; @@ -2024,11 +1988,10 @@ s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw) if (!timeout) { DEBUGOUT("Master requests are pending.\n"); - ret_val = -E1000_ERR_MASTER_REQUESTS_PENDING; + return -E1000_ERR_MASTER_REQUESTS_PENDING; } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -2045,7 +2008,7 @@ void e1000_reset_adaptive_generic(struct e1000_hw *hw) if (!mac->adaptive_ifs) { DEBUGOUT("Not in Adaptive IFS mode!\n"); - goto out; + return; } mac->current_ifs_val = 0; @@ -2056,8 +2019,6 @@ void e1000_reset_adaptive_generic(struct e1000_hw *hw) mac->in_ifs_mode = FALSE; E1000_WRITE_REG(hw, E1000_AIT, 0); -out: - return; } /** @@ -2075,7 +2036,7 @@ void e1000_update_adaptive_generic(struct e1000_hw *hw) if (!mac->adaptive_ifs) { DEBUGOUT("Not in Adaptive IFS mode!\n"); - goto out; + return; } if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) { @@ -2099,8 +2060,6 @@ void e1000_update_adaptive_generic(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_AIT, 0); } } -out: - return; } /** @@ -2112,19 +2071,15 @@ out: **/ static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw) { - 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"); hw->phy.mdix = 1; - ret_val = -E1000_ERR_CONFIG; - goto out; + return -E1000_ERR_CONFIG; } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -2142,7 +2097,6 @@ 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"); @@ -2159,10 +2113,8 @@ s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg, } if (!(regvalue & E1000_GEN_CTL_READY)) { DEBUGOUT1("Reg %08x did not indicate ready\n", reg); - ret_val = -E1000_ERR_PHY; - goto out; + return -E1000_ERR_PHY; } -out: - return ret_val; + return E1000_SUCCESS; } |