diff options
Diffstat (limited to 'sys/dev/e1000/e1000_mac.c')
| -rw-r--r-- | sys/dev/e1000/e1000_mac.c | 263 |
1 files changed, 144 insertions, 119 deletions
diff --git a/sys/dev/e1000/e1000_mac.c b/sys/dev/e1000/e1000_mac.c index fdf72c0d0844..fcec3423c9fb 100644 --- a/sys/dev/e1000/e1000_mac.c +++ b/sys/dev/e1000/e1000_mac.c @@ -34,6 +34,8 @@ #include "e1000_api.h" +static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw); + /** * e1000_init_mac_ops_generic - Initialize MAC function pointers * @hw: pointer to the HW structure @@ -51,8 +53,8 @@ void e1000_init_mac_ops_generic(struct e1000_hw *hw) mac->ops.reset_hw = e1000_null_ops_generic; mac->ops.setup_physical_interface = e1000_null_ops_generic; mac->ops.get_bus_info = e1000_null_ops_generic; + mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pcie; 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.clear_hw_cntrs = e1000_null_mac_generic; /* LED */ @@ -161,21 +163,6 @@ void e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a) } /** - * 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_pci_generic - Get PCI(x) bus information * @hw: pointer to the HW structure * @@ -185,10 +172,10 @@ void e1000_remove_device_generic(struct e1000_hw *hw) **/ s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw) { + struct e1000_mac_info *mac = &hw->mac; struct e1000_bus_info *bus = &hw->bus; u32 status = E1000_READ_REG(hw, E1000_STATUS); s32 ret_val = E1000_SUCCESS; - u16 pci_header_type; DEBUGFUNC("e1000_get_bus_info_pci_generic"); @@ -225,12 +212,7 @@ s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw) : e1000_bus_width_32; /* Which PCI(-X) function? */ - e1000_read_pci_cfg(hw, PCI_HEADER_TYPE_REGISTER, &pci_header_type); - if (pci_header_type & PCI_HEADER_TYPE_MULTIFUNC) - bus->func = (status & E1000_STATUS_FUNC_MASK) - >> E1000_STATUS_FUNC_SHIFT; - else - bus->func = 0; + mac->ops.set_lan_id(hw); return ret_val; } @@ -245,10 +227,11 @@ s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw) **/ s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw) { + struct e1000_mac_info *mac = &hw->mac; struct e1000_bus_info *bus = &hw->bus; + s32 ret_val; - u32 status; - u16 pcie_link_status, pci_header_type; + u16 pcie_link_status; DEBUGFUNC("e1000_get_bus_info_pcie_generic"); @@ -265,6 +248,45 @@ s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw) PCIE_LINK_WIDTH_MASK) >> PCIE_LINK_WIDTH_SHIFT); + mac->ops.set_lan_id(hw); + + return E1000_SUCCESS; +} + +/** + * 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. + **/ +void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw) +{ + struct e1000_bus_info *bus = &hw->bus; + u32 reg; + + reg = E1000_READ_REG(hw, E1000_STATUS); + bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT; + + /* check for a port swap */ + reg = E1000_READ_REG(hw, E1000_FACTPS); + if (reg & E1000_FACTPS_LFS) + bus->func ^= 0x1; +} + +/** + * e1000_set_lan_id_multi_port_pci - Set LAN id for PCI multiple port devices + * @hw: pointer to the HW structure + * + * Determines the LAN function id by reading PCI config space. + **/ +void e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw) +{ + struct e1000_bus_info *bus = &hw->bus; + u16 pci_header_type; + u32 status; + 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); @@ -273,8 +295,19 @@ s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw) } else { bus->func = 0; } +} - return E1000_SUCCESS; +/** + * 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; } /** @@ -431,10 +464,8 @@ void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) 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); @@ -585,18 +616,18 @@ u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr) * 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)) | @@ -650,47 +681,45 @@ void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw) **/ void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw) { - volatile u32 temp; - DEBUGFUNC("e1000_clear_hw_cntrs_base_generic"); - temp = E1000_READ_REG(hw, E1000_CRCERRS); - temp = E1000_READ_REG(hw, E1000_SYMERRS); - temp = E1000_READ_REG(hw, E1000_MPC); - temp = E1000_READ_REG(hw, E1000_SCC); - temp = E1000_READ_REG(hw, E1000_ECOL); - temp = E1000_READ_REG(hw, E1000_MCC); - temp = E1000_READ_REG(hw, E1000_LATECOL); - temp = E1000_READ_REG(hw, E1000_COLC); - temp = E1000_READ_REG(hw, E1000_DC); - temp = E1000_READ_REG(hw, E1000_SEC); - temp = E1000_READ_REG(hw, E1000_RLEC); - temp = E1000_READ_REG(hw, E1000_XONRXC); - temp = E1000_READ_REG(hw, E1000_XONTXC); - temp = E1000_READ_REG(hw, E1000_XOFFRXC); - temp = E1000_READ_REG(hw, E1000_XOFFTXC); - temp = E1000_READ_REG(hw, E1000_FCRUC); - temp = E1000_READ_REG(hw, E1000_GPRC); - temp = E1000_READ_REG(hw, E1000_BPRC); - temp = E1000_READ_REG(hw, E1000_MPRC); - temp = E1000_READ_REG(hw, E1000_GPTC); - temp = E1000_READ_REG(hw, E1000_GORCL); - temp = E1000_READ_REG(hw, E1000_GORCH); - temp = E1000_READ_REG(hw, E1000_GOTCL); - temp = E1000_READ_REG(hw, E1000_GOTCH); - temp = E1000_READ_REG(hw, E1000_RNBC); - temp = E1000_READ_REG(hw, E1000_RUC); - temp = E1000_READ_REG(hw, E1000_RFC); - temp = E1000_READ_REG(hw, E1000_ROC); - temp = E1000_READ_REG(hw, E1000_RJC); - temp = E1000_READ_REG(hw, E1000_TORL); - temp = E1000_READ_REG(hw, E1000_TORH); - temp = E1000_READ_REG(hw, E1000_TOTL); - temp = E1000_READ_REG(hw, E1000_TOTH); - temp = E1000_READ_REG(hw, E1000_TPR); - temp = E1000_READ_REG(hw, E1000_TPT); - temp = E1000_READ_REG(hw, E1000_MPTC); - temp = E1000_READ_REG(hw, E1000_BPTC); + E1000_READ_REG(hw, E1000_CRCERRS); + E1000_READ_REG(hw, E1000_SYMERRS); + E1000_READ_REG(hw, E1000_MPC); + E1000_READ_REG(hw, E1000_SCC); + E1000_READ_REG(hw, E1000_ECOL); + E1000_READ_REG(hw, E1000_MCC); + E1000_READ_REG(hw, E1000_LATECOL); + E1000_READ_REG(hw, E1000_COLC); + E1000_READ_REG(hw, E1000_DC); + E1000_READ_REG(hw, E1000_SEC); + E1000_READ_REG(hw, E1000_RLEC); + E1000_READ_REG(hw, E1000_XONRXC); + E1000_READ_REG(hw, E1000_XONTXC); + E1000_READ_REG(hw, E1000_XOFFRXC); + E1000_READ_REG(hw, E1000_XOFFTXC); + E1000_READ_REG(hw, E1000_FCRUC); + E1000_READ_REG(hw, E1000_GPRC); + E1000_READ_REG(hw, E1000_BPRC); + E1000_READ_REG(hw, E1000_MPRC); + E1000_READ_REG(hw, E1000_GPTC); + E1000_READ_REG(hw, E1000_GORCL); + E1000_READ_REG(hw, E1000_GORCH); + E1000_READ_REG(hw, E1000_GOTCL); + E1000_READ_REG(hw, E1000_GOTCH); + E1000_READ_REG(hw, E1000_RNBC); + E1000_READ_REG(hw, E1000_RUC); + E1000_READ_REG(hw, E1000_RFC); + E1000_READ_REG(hw, E1000_ROC); + E1000_READ_REG(hw, E1000_RJC); + E1000_READ_REG(hw, E1000_TORL); + E1000_READ_REG(hw, E1000_TORH); + E1000_READ_REG(hw, E1000_TOTL); + E1000_READ_REG(hw, E1000_TOTH); + E1000_READ_REG(hw, E1000_TPR); + E1000_READ_REG(hw, E1000_TPT); + E1000_READ_REG(hw, E1000_MPTC); + E1000_READ_REG(hw, E1000_BPTC); } /** @@ -763,9 +792,8 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw) * different link partner. */ ret_val = e1000_config_fc_after_link_up_generic(hw); - if (ret_val) { + if (ret_val) DEBUGOUT("Error configuring flow control\n"); - } out: return ret_val; @@ -978,23 +1006,23 @@ s32 e1000_setup_link_generic(struct e1000_hw *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); + DEBUGOUT1("After fix-ups FlowControl is now = %x\n", + hw->fc.current_mode); /* Call the necessary media_type subroutine to configure the link. */ ret_val = hw->mac.ops.setup_physical_interface(hw); @@ -1181,7 +1209,7 @@ s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) * 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); @@ -1247,7 +1275,7 @@ s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw) * 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 @@ -1296,12 +1324,12 @@ s32 e1000_set_default_fc_generic(struct e1000_hw *hw) } 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; @@ -1333,7 +1361,7 @@ s32 e1000_force_mac_fc_generic(struct e1000_hw *hw) * 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 @@ -1344,9 +1372,9 @@ s32 e1000_force_mac_fc_generic(struct e1000_hw *hw) * 3: Both Rx and Tx flow control (symmetric) is enabled. * other: No other values should be possible at this point. */ - DEBUGOUT1("hw->fc.type = %u\n", hw->fc.type); + DEBUGOUT1("hw->fc.current_mode = %u\n", hw->fc.current_mode); - switch (hw->fc.type) { + switch (hw->fc.current_mode) { case e1000_fc_none: ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); break; @@ -1386,7 +1414,6 @@ out: s32 e1000_config_fc_after_link_up_generic(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; @@ -1424,10 +1451,10 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) * 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 = hw->phy.ops.read_reg(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 = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); if (ret_val) goto out; @@ -1444,11 +1471,11 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) * Page Ability Register (Address 5) to determine how * flow control was negotiated. */ - ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, + ret_val = hw->phy.ops.read_reg(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 = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg); if (ret_val) goto out; @@ -1496,11 +1523,11 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) * ONLY. Hence, we must now check to see if we need to * turn OFF the TRANSMISSION of PAUSE frames. */ - if (hw->fc.original_type == e1000_fc_full) { - hw->fc.type = e1000_fc_full; + if (hw->fc.requested_mode == e1000_fc_full) { + hw->fc.current_mode = e1000_fc_full; DEBUGOUT("Flow Control = FULL.\r\n"); } else { - hw->fc.type = e1000_fc_rx_pause; + hw->fc.current_mode = e1000_fc_rx_pause; DEBUGOUT("Flow Control = " "RX PAUSE frames only.\r\n"); } @@ -1517,7 +1544,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { - hw->fc.type = e1000_fc_tx_pause; + hw->fc.current_mode = e1000_fc_tx_pause; DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n"); } /* @@ -1532,14 +1559,14 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { - hw->fc.type = e1000_fc_rx_pause; + hw->fc.current_mode = e1000_fc_rx_pause; DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); } else { /* * Per the IEEE spec, at this point flow control * should be disabled. */ - hw->fc.type = e1000_fc_none; + hw->fc.current_mode = e1000_fc_none; DEBUGOUT("Flow Control = NONE.\r\n"); } @@ -1555,7 +1582,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) } 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 @@ -1767,7 +1794,7 @@ out: * @hw: pointer to the HW structure * **/ -s32 e1000_id_led_init_generic(struct e1000_hw * hw) +s32 e1000_id_led_init_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val; @@ -2070,13 +2097,11 @@ void e1000_reset_adaptive_generic(struct e1000_hw *hw) 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); |
