/drivers/net/e1000e/lib.c
C | 2692 lines | 1420 code | 329 blank | 943 comment | 272 complexity | 92b9b386eee13e3e9e05269425aa1b88 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
Large files files are truncated, but you can click here to view the full file
- /*******************************************************************************
- Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2011 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 <linux.nics@intel.com>
- e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
- Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *******************************************************************************/
- #include "e1000.h"
- 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
- };
- #define E1000_FACTPS_MNGCG 0x20000000
- /* Intel(R) Active Management Technology signature */
- #define E1000_IAMT_SIGNATURE 0x544D4149
- /**
- * 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 e1000e_get_bus_info_pcie(struct e1000_hw *hw)
- {
- struct e1000_mac_info *mac = &hw->mac;
- struct e1000_bus_info *bus = &hw->bus;
- struct e1000_adapter *adapter = hw->adapter;
- u16 pcie_link_status, cap_offset;
- cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
- if (!cap_offset) {
- bus->width = e1000_bus_width_unknown;
- } else {
- pci_read_config_word(adapter->pdev,
- cap_offset + PCIE_LINK_STATUS,
- &pcie_link_status);
- bus->width = (enum e1000_bus_width)((pcie_link_status &
- PCIE_LINK_WIDTH_MASK) >>
- PCIE_LINK_WIDTH_SHIFT);
- }
- mac->ops.set_lan_id(hw);
- return 0;
- }
- /**
- * 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;
- /*
- * 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;
- }
- /**
- * e1000_clear_vfta_generic - Clear VLAN filter table
- * @hw: pointer to the HW structure
- *
- * Clears the register array which contains the VLAN filter table by
- * setting all the values to 0.
- **/
- void e1000_clear_vfta_generic(struct e1000_hw *hw)
- {
- u32 offset;
- for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
- E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0);
- e1e_flush();
- }
- }
- /**
- * e1000_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
- *
- * 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)
- {
- E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value);
- e1e_flush();
- }
- /**
- * e1000e_init_rx_addrs - Initialize receive address's
- * @hw: pointer to the HW structure
- * @rar_count: receive address registers
- *
- * Setup the receive address registers by setting the base receive address
- * register to the devices MAC address and clearing all the other receive
- * address registers to 0.
- **/
- void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count)
- {
- u32 i;
- u8 mac_addr[ETH_ALEN] = {0};
- /* Setup the receive address */
- e_dbg("Programming MAC Address into RAR[0]\n");
- e1000e_rar_set(hw, hw->mac.addr, 0);
- /* Zero out the other (rar_entry_count - 1) receive addresses */
- e_dbg("Clearing RAR[1-%u]\n", rar_count-1);
- for (i = 1; i < rar_count; i++)
- e1000e_rar_set(hw, mac_addr, i);
- }
- /**
- * e1000_check_alt_mac_addr_generic - Check for alternate MAC addr
- * @hw: pointer to the HW structure
- *
- * 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 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)
- {
- u32 i;
- s32 ret_val = 0;
- u16 offset, nvm_alt_mac_addr_offset, nvm_data;
- u8 alt_mac_addr[ETH_ALEN];
- ret_val = e1000_read_nvm(hw, NVM_COMPAT, 1, &nvm_data);
- if (ret_val)
- goto out;
- /* Check for LOM (vs. NIC) or one of two valid mezzanine cards */
- if (!((nvm_data & NVM_COMPAT_LOM) ||
- (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_DUAL) ||
- (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD) ||
- (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES)))
- goto out;
- ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1,
- &nvm_alt_mac_addr_offset);
- if (ret_val) {
- e_dbg("NVM Read Error\n");
- goto out;
- }
- if (nvm_alt_mac_addr_offset == 0xFFFF) {
- /* There is no Alternate MAC Address */
- goto out;
- }
- if (hw->bus.func == E1000_FUNC_1)
- nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1;
- for (i = 0; i < ETH_ALEN; i += 2) {
- offset = nvm_alt_mac_addr_offset + (i >> 1);
- ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data);
- if (ret_val) {
- e_dbg("NVM Read Error\n");
- goto out;
- }
- alt_mac_addr[i] = (u8)(nvm_data & 0xFF);
- alt_mac_addr[i + 1] = (u8)(nvm_data >> 8);
- }
- /* if multicast bit is set, the alternate address will not be used */
- if (alt_mac_addr[0] & 0x01) {
- e_dbg("Ignoring Alternate Mac Address with MC bit set\n");
- goto out;
- }
- /*
- * 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.
- */
- e1000e_rar_set(hw, alt_mac_addr, 0);
- out:
- return ret_val;
- }
- /**
- * e1000e_rar_set - Set receive address register
- * @hw: pointer to the HW structure
- * @addr: pointer to the receive address
- * @index: receive address array register
- *
- * Sets the receive address array register at index to the address passed
- * in by addr.