/*******************************************************************************
- Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Contact Information:
Linux NICS <linux.nics@intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
*******************************************************************************/
/* ixgb_hw.c
/* Local function prototypes */
-static u32 ixgb_hash_mc_addr(struct ixgb_hw *hw, u8 * mc_addr);
+static uint32_t ixgb_hash_mc_addr(struct ixgb_hw *hw, uint8_t * mc_addr);
-static void ixgb_mta_set(struct ixgb_hw *hw, u32 hash_value);
+static void ixgb_mta_set(struct ixgb_hw *hw, uint32_t hash_value);
static void ixgb_get_bus_info(struct ixgb_hw *hw);
-boolean_t mac_addr_valid(u8 * mac_addr);
-
static boolean_t ixgb_link_reset(struct ixgb_hw *hw);
static void ixgb_optics_reset(struct ixgb_hw *hw);
-u32 ixgb_mac_reset(struct ixgb_hw *hw);
+static ixgb_phy_type ixgb_identify_phy(struct ixgb_hw *hw);
+
+uint32_t ixgb_mac_reset(struct ixgb_hw *hw);
-u32
-ixgb_mac_reset(struct ixgb_hw *hw)
+uint32_t ixgb_mac_reset(struct ixgb_hw *hw)
{
- u32 ctrl_reg;
+ uint32_t ctrl_reg;
- /* Setup up hardware to known state with RESET. */
ctrl_reg = IXGB_CTRL0_RST | IXGB_CTRL0_SDP3_DIR | /* All pins are Output=1 */
IXGB_CTRL0_SDP2_DIR | IXGB_CTRL0_SDP1_DIR | IXGB_CTRL0_SDP0_DIR | IXGB_CTRL0_SDP3 | /* Initial value 1101 */
IXGB_CTRL0_SDP2 | IXGB_CTRL0_SDP0;
+
#ifdef HP_ZX1
- outl(IXGB_CTRL0, hw->io_base);
- outl(ctrl_reg, hw->io_base + 4);
+ /* Workaround for 82597EX reset errata */
+ IXGB_WRITE_REG_IO(hw, CTRL0, ctrl_reg);
#else
IXGB_WRITE_REG(hw, CTRL0, ctrl_reg);
#endif
ASSERT(!(ctrl_reg & IXGB_CTRL0_RST));
#endif
- ixgb_optics_reset(hw);
+ if (hw->phy_type == ixgb_phy_type_txn17401) {
+ ixgb_optics_reset(hw);
+ }
+
return ctrl_reg;
}
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-boolean_t
-ixgb_adapter_stop(struct ixgb_hw * hw)
+boolean_t ixgb_adapter_stop(struct ixgb_hw * hw)
{
- u32 ctrl_reg;
- u32 icr_reg;
+ uint32_t ctrl_reg;
+ uint32_t icr_reg;
DEBUGFUNC("ixgb_adapter_stop");
return (ctrl_reg & IXGB_CTRL0_RST);
}
+/******************************************************************************
+ * Identifies the vendor of the optics module on the adapter. The SR adapters
+ * support two different types of XPAK optics, so it is necessary to determine
+ * which optics are present before applying any optics-specific workarounds.
+ *
+ * hw - Struct containing variables accessed by shared code.
+ *
+ * Returns: the vendor of the XPAK optics module.
+ *****************************************************************************/
+static ixgb_xpak_vendor ixgb_identify_xpak_vendor(struct ixgb_hw *hw)
+{
+ uint32_t i;
+ uint16_t vendor_name[5];
+ ixgb_xpak_vendor xpak_vendor;
+
+ DEBUGFUNC("ixgb_identify_xpak_vendor");
+
+ /* Read the first few bytes of the vendor string from the XPAK NVR
+ * registers. These are standard XENPAK/XPAK registers, so all XPAK
+ * devices should implement them. */
+ for (i = 0; i < 5; i++) {
+ vendor_name[i] = ixgb_read_phy_reg(hw,
+ MDIO_PMA_PMD_XPAK_VENDOR_NAME
+ + i, IXGB_PHY_ADDRESS,
+ MDIO_PMA_PMD_DID);
+ }
+
+ /* Determine the actual vendor */
+ if (vendor_name[0] == 'I' &&
+ vendor_name[1] == 'N' &&
+ vendor_name[2] == 'T' &&
+ vendor_name[3] == 'E' && vendor_name[4] == 'L') {
+ xpak_vendor = ixgb_xpak_vendor_intel;
+ } else {
+ xpak_vendor = ixgb_xpak_vendor_infineon;
+ }
+
+ return (xpak_vendor);
+}
+
+/******************************************************************************
+ * Determine the physical layer module on the adapter.
+ *
+ * hw - Struct containing variables accessed by shared code. The device_id
+ * field must be (correctly) populated before calling this routine.
+ *
+ * Returns: the phy type of the adapter.
+ *****************************************************************************/
+static ixgb_phy_type ixgb_identify_phy(struct ixgb_hw *hw)
+{
+ ixgb_phy_type phy_type;
+ ixgb_xpak_vendor xpak_vendor;
+
+ DEBUGFUNC("ixgb_identify_phy");
+
+ /* Infer the transceiver/phy type from the device id */
+ switch (hw->device_id) {
+ case IXGB_DEVICE_ID_82597EX:
+ DEBUGOUT("Identified TXN17401 optics\n");
+ phy_type = ixgb_phy_type_txn17401;
+ break;
+
+ case IXGB_DEVICE_ID_82597EX_SR:
+ /* The SR adapters carry two different types of XPAK optics
+ * modules; read the vendor identifier to determine the exact
+ * type of optics. */
+ xpak_vendor = ixgb_identify_xpak_vendor(hw);
+ if (xpak_vendor == ixgb_xpak_vendor_intel) {
+ DEBUGOUT("Identified TXN17201 optics\n");
+ phy_type = ixgb_phy_type_txn17201;
+ } else {
+ DEBUGOUT("Identified G6005 optics\n");
+ phy_type = ixgb_phy_type_g6005;
+ }
+ break;
+
+ default:
+ DEBUGOUT("Unknown physical layer module\n");
+ phy_type = ixgb_phy_type_unknown;
+ break;
+ }
+
+ return (phy_type);
+}
+
/******************************************************************************
* Performs basic configuration of the adapter.
*
* hw - Struct containing variables accessed by shared code
- *
- * Resets the controller.
+ *
+ * Resets the controller.
* Reads and validates the EEPROM.
* Initializes the receive address registers.
* Initializes the multicast table.
- * Clears all on-chip counters.
- * Calls routine to setup flow control settings.
+ * Clears all on-chip counters.
+ * Calls routine to setup flow control settings.
* Leaves the transmit and receive units disabled and uninitialized.
- *
+ *
* Returns:
- * TRUE if successful,
+ * TRUE if successful,
* FALSE if unrecoverable problems were encountered.
*****************************************************************************/
-boolean_t
-ixgb_init_hw(struct ixgb_hw * hw)
+boolean_t ixgb_init_hw(struct ixgb_hw * hw)
{
- u32 i;
- u32 ctrl_reg;
+ uint32_t i;
+ uint32_t ctrl_reg;
boolean_t status;
DEBUGFUNC("ixgb_init_hw");
DEBUGOUT("Issuing an EE reset to MAC\n");
#ifdef HP_ZX1
- outl(IXGB_CTRL1, hw->io_base);
- outl(IXGB_CTRL1_EE_RST, hw->io_base + 4);
+ /* Workaround for 82597EX reset errata */
+ IXGB_WRITE_REG_IO(hw, CTRL1, IXGB_CTRL1_EE_RST);
#else
IXGB_WRITE_REG(hw, CTRL1, IXGB_CTRL1_EE_RST);
#endif
return (FALSE);
}
- /* Setup the receive addresses.
+ /* Use the device id to determine the type of phy/transceiver. */
+ hw->device_id = ixgb_get_ee_device_id(hw);
+ hw->phy_type = ixgb_identify_phy(hw);
+
+ /* Setup the receive addresses.
* Receive Address Registers (RARs 0 - 15).
*/
ixgb_init_rx_addrs(hw);
- /*
+ /*
* Check that a valid MAC address has been set.
* If it is not valid, we fail hardware init.
*/
/* Call a subroutine to setup flow control. */
status = ixgb_setup_fc(hw);
- /* check-for-link in case lane deskew is locked */
+ /* 82597EX errata: Call check-for-link in case lane deskew is locked */
ixgb_check_for_link(hw);
return (status);
/******************************************************************************
* Initializes receive address filters.
*
- * hw - Struct containing variables accessed by shared code
+ * hw - Struct containing variables accessed by shared code
*
* Places the MAC address in receive address register 0 and clears the rest
* of the receive addresss registers. Clears the multicast table. Assumes
* the receiver is in reset when the routine is called.
*****************************************************************************/
-void
-ixgb_init_rx_addrs(struct ixgb_hw *hw)
+void ixgb_init_rx_addrs(struct ixgb_hw *hw)
{
- u32 i;
+ uint32_t i;
DEBUGFUNC("ixgb_init_rx_addrs");
- /*
+ /*
* If the current mac address is valid, assume it is a software override
* to the permanent address.
* Otherwise, use the permanent address from the eeprom.
*
* The given list replaces any existing list. Clears the last 15 receive
* address registers and the multicast table. Uses receive address registers
- * for the first 15 multicast addresses, and hashes the rest into the
+ * for the first 15 multicast addresses, and hashes the rest into the
* multicast table.
*****************************************************************************/
void
ixgb_mc_addr_list_update(struct ixgb_hw *hw,
- u8 * mc_addr_list,
- u32 mc_addr_count, u32 pad)
+ uint8_t * mc_addr_list,
+ uint32_t mc_addr_count, uint32_t pad)
{
- u32 hash_value;
- u32 i;
- u32 rar_used_count = 1; /* RAR[0] is used for our MAC address */
+ uint32_t hash_value;
+ uint32_t i;
+ uint32_t rar_used_count = 1; /* RAR[0] is used for our MAC address */
DEBUGFUNC("ixgb_mc_addr_list_update");
5]);
/* Place this multicast address in the RAR if there is room, *
- * else put it in the MTA
+ * else put it in the MTA
*/
if (rar_used_count < IXGB_RAR_ENTRIES) {
ixgb_rar_set(hw,
* Hashes an address to determine its location in the multicast table
*
* hw - Struct containing variables accessed by shared code
- * mc_addr - the multicast address to hash
+ * mc_addr - the multicast address to hash
*
* Returns:
* The hash value
*****************************************************************************/
-static u32
-ixgb_hash_mc_addr(struct ixgb_hw *hw, u8 * mc_addr)
+static uint32_t ixgb_hash_mc_addr(struct ixgb_hw *hw, uint8_t * mc_addr)
{
- u32 hash_value = 0;
+ uint32_t hash_value = 0;
DEBUGFUNC("ixgb_hash_mc_addr");
/* The portion of the address that is used for the hash table is
- * determined by the mc_filter_type setting.
+ * determined by the mc_filter_type setting.
*/
switch (hw->mc_filter_type) {
/* [0] [1] [2] [3] [4] [5]
case 0:
/* [47:36] i.e. 0x563 for above example address */
hash_value =
- ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
+ ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4));
break;
case 1: /* [46:35] i.e. 0xAC6 for above example address */
hash_value =
- ((mc_addr[4] >> 3) | (((u16) mc_addr[5]) << 5));
+ ((mc_addr[4] >> 3) | (((uint16_t) mc_addr[5]) << 5));
break;
case 2: /* [45:34] i.e. 0x5D8 for above example address */
hash_value =
- ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
+ ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));
break;
case 3: /* [43:32] i.e. 0x634 for above example address */
- hash_value = ((mc_addr[4]) | (((u16) mc_addr[5]) << 8));
+ hash_value = ((mc_addr[4]) | (((uint16_t) mc_addr[5]) << 8));
break;
default:
/* Invalid mc_filter_type, what should we do? */
* hw - Struct containing variables accessed by shared code
* hash_value - Multicast address hash value
*****************************************************************************/
-static void
-ixgb_mta_set(struct ixgb_hw *hw, u32 hash_value)
+static void ixgb_mta_set(struct ixgb_hw *hw, uint32_t hash_value)
{
- u32 hash_bit, hash_reg;
- u32 mta_reg;
+ uint32_t hash_bit, hash_reg;
+ uint32_t mta_reg;
- /* The MTA is a register array of 128 32-bit registers.
- * It is treated like an array of 4096 bits. We want to set
+ /* The MTA is a register array of 128 32-bit registers.
+ * It is treated like an array of 4096 bits. We want to set
* bit BitArray[hash_value]. So we figure out what register
* the bit is in, read it, OR in the new bit, then write
- * back the new value. The register is determined by the
- * upper 7 bits of the hash value and the bit within that
+ * back the new value. The register is determined by the
+ * upper 7 bits of the hash value and the bit within that
* register are determined by the lower 5 bits of the value.
*/
hash_reg = (hash_value >> 5) & 0x7F;
* addr - Address to put into receive address register
* index - Receive address register to write
*****************************************************************************/
-void
-ixgb_rar_set(struct ixgb_hw *hw, u8 * addr, u32 index)
+void ixgb_rar_set(struct ixgb_hw *hw, uint8_t * addr, uint32_t index)
{
- u32 rar_low, rar_high;
+ uint32_t rar_low, rar_high;
DEBUGFUNC("ixgb_rar_set");
/* HW expects these in little endian so we reverse the byte order
- * from network order (big endian) to little endian
+ * from network order (big endian) to little endian
*/
- rar_low = ((u32) addr[0] |
- ((u32) addr[1] << 8) |
- ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
+ rar_low = ((uint32_t) addr[0] |
+ ((uint32_t) addr[1] << 8) |
+ ((uint32_t) addr[2] << 16) | ((uint32_t) addr[3] << 24));
- rar_high = ((u32) addr[4] |
- ((u32) addr[5] << 8) | IXGB_RAH_AV);
+ rar_high = ((uint32_t) addr[4] |
+ ((uint32_t) addr[5] << 8) | IXGB_RAH_AV);
IXGB_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
IXGB_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
* offset - Offset in VLAN filer table to write
* value - Value to write into VLAN filter table
*****************************************************************************/
-void
-ixgb_write_vfta(struct ixgb_hw *hw, u32 offset, u32 value)
+void ixgb_write_vfta(struct ixgb_hw *hw, uint32_t offset, uint32_t value)
{
IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, value);
return;
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void
-ixgb_clear_vfta(struct ixgb_hw *hw)
+void ixgb_clear_vfta(struct ixgb_hw *hw)
{
- u32 offset;
+ uint32_t offset;
for (offset = 0; offset < IXGB_VLAN_FILTER_TBL_SIZE; offset++)
IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, 0);
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-boolean_t
-ixgb_setup_fc(struct ixgb_hw * hw)
+boolean_t ixgb_setup_fc(struct ixgb_hw * hw)
{
- u32 ctrl_reg;
- u32 pap_reg = 0; /* by default, assume no pause time */
+ uint32_t ctrl_reg;
+ uint32_t pap_reg = 0; /* by default, assume no pause time */
boolean_t status = TRUE;
DEBUGFUNC("ixgb_setup_fc");
*/
switch (hw->fc.type) {
case ixgb_fc_none: /* 0 */
+ /* Set CMDC bit to disable Rx Flow control */
+ ctrl_reg |= (IXGB_CTRL0_CMDC);
break;
case ixgb_fc_rx_pause: /* 1 */
/* RX Flow control is enabled, and TX Flow control is
* these registers will be set to a default threshold that may be
* adjusted later by the driver's runtime code. However, if the
* ability to transmit pause frames in not enabled, then these
- * registers will be set to 0.
+ * registers will be set to 0.
*/
if (!(hw->fc.type & ixgb_fc_tx_pause)) {
IXGB_WRITE_REG(hw, FCRTL, 0);
*
* Returns: Data word (16 bits) from MDI device.
*
- * This routine uses the new protocol MDI Single Command and Address Operation.
+ * The 82597EX has support for several MDI access methods. This routine
+ * uses the new protocol MDI Single Command and Address Operation.
* This requires that first an address cycle command is sent, followed by a
* read command.
*****************************************************************************/
-u16
+uint16_t
ixgb_read_phy_reg(struct ixgb_hw * hw,
- u32 reg_address,
- u32 phy_address, u32 device_type)
+ uint32_t reg_address,
+ uint32_t phy_address, uint32_t device_type)
{
- u32 i;
- u32 data;
- u32 command = 0;
+ uint32_t i;
+ uint32_t data;
+ uint32_t command = 0;
ASSERT(reg_address <= IXGB_MAX_PHY_REG_ADDRESS);
ASSERT(phy_address <= IXGB_MAX_PHY_ADDRESS);
ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0);
/* Operation is complete, get the data from the MDIO Read/Write Data
- * register and return.
+ * register and return.
*/
data = IXGB_READ_REG(hw, MSRWD);
data >>= IXGB_MSRWD_READ_DATA_SHIFT;
- return ((u16) data);
+ return ((uint16_t) data);
}
/******************************************************************************
*
* Returns: void.
*
- * This routine uses the new protocol MDI Single Command and Address Operation.
+ * The 82597EX has support for several MDI access methods. This routine
+ * uses the new protocol MDI Single Command and Address Operation.
* This requires that first an address cycle command is sent, followed by a
* write command.
*****************************************************************************/
void
ixgb_write_phy_reg(struct ixgb_hw *hw,
- u32 reg_address,
- u32 phy_address, u32 device_type, u16 data)
+ uint32_t reg_address,
+ uint32_t phy_address, uint32_t device_type, uint16_t data)
{
- u32 i;
- u32 command = 0;
+ uint32_t i;
+ uint32_t command = 0;
ASSERT(reg_address <= IXGB_MAX_PHY_REG_ADDRESS);
ASSERT(phy_address <= IXGB_MAX_PHY_ADDRESS);
ASSERT(device_type <= IXGB_MAX_PHY_DEV_TYPE);
/* Put the data in the MDIO Read/Write Data register */
- IXGB_WRITE_REG(hw, MSRWD, (u32) data);
+ IXGB_WRITE_REG(hw, MSRWD, (uint32_t) data);
/* Setup and write the address cycle command */
command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
*
* Called by any function that needs to check the link status of the adapter.
*****************************************************************************/
-void
-ixgb_check_for_link(struct ixgb_hw *hw)
+void ixgb_check_for_link(struct ixgb_hw *hw)
{
- u32 status_reg;
- u32 xpcss_reg;
+ uint32_t status_reg;
+ uint32_t xpcss_reg;
DEBUGFUNC("ixgb_check_for_link");
DEBUGOUT("XPCSS Not Aligned while Status:LU is set.\n");
hw->link_up = ixgb_link_reset(hw);
} else {
+ /*
+ * 82597EX errata. Since the lane deskew problem may prevent
+ * link, reset the link before reporting link down.
+ */
hw->link_up = ixgb_link_reset(hw);
}
-
/* Anything else for 10 Gig?? */
}
-boolean_t
-ixgb_check_for_bad_link(struct ixgb_hw *hw)
+/******************************************************************************
+ * Check for a bad link condition that may have occured.
+ * The indication is that the RFC / LFC registers may be incrementing
+ * continually. A full adapter reset is required to recover.
+ *
+ * hw - Struct containing variables accessed by hw code
+ *
+ * Called by any function that needs to check the link status of the adapter.
+ *****************************************************************************/
+boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw)
{
- u32 newLFC, newRFC;
+ uint32_t newLFC, newRFC;
boolean_t bad_link_returncode = FALSE;
- /* check for a bad reset that may have occured
- * the indication is that the RFC / LFC registers may be incrementing
- * continually. Do a full adapter reset to recover
- */
- newLFC = IXGB_READ_REG(hw, LFC);
- newRFC = IXGB_READ_REG(hw, RFC);
- if ((hw->lastLFC + 250 < newLFC) || (hw->lastRFC + 250 < newRFC)) {
- DEBUGOUT("BAD LINK! too many LFC/RFC since last check\n");
- bad_link_returncode = TRUE;
+ if (hw->phy_type == ixgb_phy_type_txn17401) {
+ newLFC = IXGB_READ_REG(hw, LFC);
+ newRFC = IXGB_READ_REG(hw, RFC);
+ if ((hw->lastLFC + 250 < newLFC)
+ || (hw->lastRFC + 250 < newRFC)) {
+ DEBUGOUT
+ ("BAD LINK! too many LFC/RFC since last check\n");
+ bad_link_returncode = TRUE;
+ }
+ hw->lastLFC = newLFC;
+ hw->lastRFC = newRFC;
}
- hw->lastLFC = newLFC;
- hw->lastRFC = newRFC;
+
return bad_link_returncode;
}
/******************************************************************************
- * Clears all hardware statistics counters.
+ * Clears all hardware statistics counters.
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void
-ixgb_clear_hw_cntrs(struct ixgb_hw *hw)
+void ixgb_clear_hw_cntrs(struct ixgb_hw *hw)
{
- volatile u32 temp_reg;
+ volatile uint32_t temp_reg;
DEBUGFUNC("ixgb_clear_hw_cntrs");
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void
-ixgb_led_on(struct ixgb_hw *hw)
+void ixgb_led_on(struct ixgb_hw *hw)
{
- u32 ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
+ uint32_t ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
/* To turn on the LED, clear software-definable pin 0 (SDP0). */
ctrl0_reg &= ~IXGB_CTRL0_SDP0;
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void
-ixgb_led_off(struct ixgb_hw *hw)
+void ixgb_led_off(struct ixgb_hw *hw)
{
- u32 ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
+ uint32_t ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
/* To turn off the LED, set software-definable pin 0 (SDP0). */
ctrl0_reg |= IXGB_CTRL0_SDP0;
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void
-ixgb_get_bus_info(struct ixgb_hw *hw)
+static void ixgb_get_bus_info(struct ixgb_hw *hw)
{
- u32 status_reg;
+ uint32_t status_reg;
status_reg = IXGB_READ_REG(hw, STATUS);
/******************************************************************************
* Tests a MAC address to ensure it is a valid Individual Address
*
- * mac_addr - pointer to MAC address.
+ * mac_addr - pointer to MAC address.
*
*****************************************************************************/
-boolean_t
-mac_addr_valid(u8 * mac_addr)
+boolean_t mac_addr_valid(uint8_t * mac_addr)
{
boolean_t is_valid = TRUE;
DEBUGFUNC("mac_addr_valid");
}
/******************************************************************************
- * Resets the 10GbE link. Waits the settle time and returns the state of
+ * Resets the 10GbE link. Waits the settle time and returns the state of
* the link.
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-boolean_t
-ixgb_link_reset(struct ixgb_hw * hw)
+boolean_t ixgb_link_reset(struct ixgb_hw * hw)
{
boolean_t link_status = FALSE;
- u8 wait_retries = MAX_RESET_ITERATIONS;
- u8 lrst_retries = MAX_RESET_ITERATIONS;
+ uint8_t wait_retries = MAX_RESET_ITERATIONS;
+ uint8_t lrst_retries = MAX_RESET_ITERATIONS;
do {
+ /* Reset the link */
IXGB_WRITE_REG(hw, CTRL0,
IXGB_READ_REG(hw, CTRL0) | IXGB_CTRL0_LRST);
+ /* Wait for link-up and lane re-alignment */
do {
udelay(IXGB_DELAY_USECS_AFTER_LINK_RESET);
link_status =
&& (IXGB_READ_REG(hw, XPCSS) &
IXGB_XPCSS_ALIGN_STATUS)) ? TRUE : FALSE;
} while (!link_status && --wait_retries);
+
} while (!link_status && --lrst_retries);
return link_status;
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void
-ixgb_optics_reset(struct ixgb_hw *hw)
+void ixgb_optics_reset(struct ixgb_hw *hw)
{
- u16 mdio_reg;
-
- ixgb_write_phy_reg(hw,
- TXN17401_PMA_PMD_CR1,
- IXGB_PHY_ADDRESS,
- TXN17401_PMA_PMD_DID, TXN17401_PMA_PMD_CR1_RESET);
- mdio_reg = ixgb_read_phy_reg(hw,
- TXN17401_PMA_PMD_CR1,
- IXGB_PHY_ADDRESS, TXN17401_PMA_PMD_DID);
+ if (hw->phy_type == ixgb_phy_type_txn17401) {
+ uint16_t mdio_reg;
+
+ ixgb_write_phy_reg(hw,
+ MDIO_PMA_PMD_CR1,
+ IXGB_PHY_ADDRESS,
+ MDIO_PMA_PMD_DID, MDIO_PMA_PMD_CR1_RESET);
+
+ mdio_reg = ixgb_read_phy_reg(hw,
+ MDIO_PMA_PMD_CR1,
+ IXGB_PHY_ADDRESS,
+ MDIO_PMA_PMD_DID);
+ }
+
+ return;
}