Merge branch 'for-rmk/samsung6' of git://git.fluff.org/bjdooks/linux into devel-stable
[linux-2.6.git] / drivers / net / e1000e / phy.c
index 8189d00..7f3ceb9 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2008 Intel Corporation.
+  Copyright(c) 1999 - 2009 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,
@@ -44,6 +44,8 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
 /* Cable length tables */
 static const u16 e1000_m88_cable_length_table[] =
        { 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
+#define M88E1000_CABLE_LENGTH_TABLE_SIZE \
+               ARRAY_SIZE(e1000_m88_cable_length_table)
 
 static const u16 e1000_igp_2_cable_length_table[] =
        { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, 0, 0, 0, 3,
@@ -71,7 +73,6 @@ static const u16 e1000_igp_2_cable_length_table[] =
 #define I82577_CFG_ASSERT_CRS_ON_TX       (1 << 15)
 #define I82577_CFG_ENABLE_DOWNSHIFT       (3 << 10) /* auto downshift 100/10 */
 #define I82577_CTRL_REG                   23
-#define I82577_CTRL_DOWNSHIFT_MASK        (7 << 10)
 
 /* 82577 specific PHY registers */
 #define I82577_PHY_CTRL_2            18
@@ -131,7 +132,7 @@ s32 e1000e_get_phy_id(struct e1000_hw *hw)
        u16 phy_id;
        u16 retry_count = 0;
 
-       if (!(phy->ops.read_phy_reg))
+       if (!(phy->ops.read_reg))
                goto out;
 
        while (retry_count < 2) {
@@ -151,32 +152,9 @@ s32 e1000e_get_phy_id(struct e1000_hw *hw)
                if (phy->id != 0 && phy->id != PHY_REVISION_MASK)
                        goto out;
 
-               /*
-                * If the PHY ID is still unknown, we may have an 82577i
-                * without link.  We will try again after setting Slow
-                * MDIC mode. No harm in trying again in this case since
-                * the PHY ID is unknown at this point anyway
-                */
-               ret_val = phy->ops.acquire_phy(hw);
-               if (ret_val)
-                       goto out;
-               ret_val = e1000_set_mdio_slow_mode_hv(hw, true);
-               if (ret_val)
-                       goto out;
-               phy->ops.release_phy(hw);
-
                retry_count++;
        }
 out:
-       /* Revert to MDIO fast mode, if applicable */
-       if (retry_count) {
-               ret_val = phy->ops.acquire_phy(hw);
-               if (ret_val)
-                       return ret_val;
-               ret_val = e1000_set_mdio_slow_mode_hv(hw, false);
-               phy->ops.release_phy(hw);
-       }
-
        return ret_val;
 }
 
@@ -212,7 +190,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
        u32 i, mdic = 0;
 
        if (offset > MAX_PHY_REG_ADDRESS) {
-               hw_dbg(hw, "PHY Address %d is out of range\n", offset);
+               e_dbg("PHY Address %d is out of range\n", offset);
                return -E1000_ERR_PARAM;
        }
 
@@ -239,11 +217,11 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
                        break;
        }
        if (!(mdic & E1000_MDIC_READY)) {
-               hw_dbg(hw, "MDI Read did not complete\n");
+               e_dbg("MDI Read did not complete\n");
                return -E1000_ERR_PHY;
        }
        if (mdic & E1000_MDIC_ERROR) {
-               hw_dbg(hw, "MDI Error\n");
+               e_dbg("MDI Error\n");
                return -E1000_ERR_PHY;
        }
        *data = (u16) mdic;
@@ -265,7 +243,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
        u32 i, mdic = 0;
 
        if (offset > MAX_PHY_REG_ADDRESS) {
-               hw_dbg(hw, "PHY Address %d is out of range\n", offset);
+               e_dbg("PHY Address %d is out of range\n", offset);
                return -E1000_ERR_PARAM;
        }
 
@@ -293,11 +271,11 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
                        break;
        }
        if (!(mdic & E1000_MDIC_READY)) {
-               hw_dbg(hw, "MDI Write did not complete\n");
+               e_dbg("MDI Write did not complete\n");
                return -E1000_ERR_PHY;
        }
        if (mdic & E1000_MDIC_ERROR) {
-               hw_dbg(hw, "MDI Error\n");
+               e_dbg("MDI Error\n");
                return -E1000_ERR_PHY;
        }
 
@@ -318,14 +296,14 @@ s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data)
 {
        s32 ret_val;
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
+       ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
                return ret_val;
 
        ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
                                           data);
 
-       hw->phy.ops.release_phy(hw);
+       hw->phy.ops.release(hw);
 
        return ret_val;
 }
@@ -343,14 +321,14 @@ s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
 {
        s32 ret_val;
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
+       ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
                return ret_val;
 
        ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
                                            data);
 
-       hw->phy.ops.release_phy(hw);
+       hw->phy.ops.release(hw);
 
        return ret_val;
 }
@@ -372,10 +350,10 @@ static s32 __e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data,
        s32 ret_val = 0;
 
        if (!locked) {
-               if (!(hw->phy.ops.acquire_phy))
+               if (!(hw->phy.ops.acquire))
                        goto out;
 
-               ret_val = hw->phy.ops.acquire_phy(hw);
+               ret_val = hw->phy.ops.acquire(hw);
                if (ret_val)
                        goto out;
        }
@@ -393,7 +371,7 @@ static s32 __e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data,
 
 release:
        if (!locked)
-               hw->phy.ops.release_phy(hw);
+               hw->phy.ops.release(hw);
 out:
        return ret_val;
 }
@@ -443,10 +421,10 @@ static s32 __e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data,
        s32 ret_val = 0;
 
        if (!locked) {
-               if (!(hw->phy.ops.acquire_phy))
+               if (!(hw->phy.ops.acquire))
                        goto out;
 
-               ret_val = hw->phy.ops.acquire_phy(hw);
+               ret_val = hw->phy.ops.acquire(hw);
                if (ret_val)
                        goto out;
        }
@@ -464,7 +442,7 @@ static s32 __e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data,
 
 release:
        if (!locked)
-               hw->phy.ops.release_phy(hw);
+               hw->phy.ops.release(hw);
 
 out:
        return ret_val;
@@ -516,10 +494,10 @@ static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
        s32 ret_val = 0;
 
        if (!locked) {
-               if (!(hw->phy.ops.acquire_phy))
+               if (!(hw->phy.ops.acquire))
                        goto out;
 
-               ret_val = hw->phy.ops.acquire_phy(hw);
+               ret_val = hw->phy.ops.acquire(hw);
                if (ret_val)
                        goto out;
        }
@@ -534,7 +512,7 @@ static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
        *data = (u16)kmrnctrlsta;
 
        if (!locked)
-               hw->phy.ops.release_phy(hw);
+               hw->phy.ops.release(hw);
 
 out:
        return ret_val;
@@ -588,10 +566,10 @@ static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data,
        s32 ret_val = 0;
 
        if (!locked) {
-               if (!(hw->phy.ops.acquire_phy))
+               if (!(hw->phy.ops.acquire))
                        goto out;
 
-               ret_val = hw->phy.ops.acquire_phy(hw);
+               ret_val = hw->phy.ops.acquire(hw);
                if (ret_val)
                        goto out;
        }
@@ -603,7 +581,7 @@ static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data,
        udelay(2);
 
        if (!locked)
-               hw->phy.ops.release_phy(hw);
+               hw->phy.ops.release(hw);
 
 out:
        return ret_val;
@@ -650,7 +628,7 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
        u16 phy_data;
 
        /* Enable CRS on TX. This must be set for half-duplex operation. */
-       ret_val = phy->ops.read_phy_reg(hw, I82577_CFG_REG, &phy_data);
+       ret_val = phy->ops.read_reg(hw, I82577_CFG_REG, &phy_data);
        if (ret_val)
                goto out;
 
@@ -659,16 +637,7 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
        /* Enable downshift */
        phy_data |= I82577_CFG_ENABLE_DOWNSHIFT;
 
-       ret_val = phy->ops.write_phy_reg(hw, I82577_CFG_REG, phy_data);
-       if (ret_val)
-               goto out;
-
-       /* Set number of link attempts before downshift */
-       ret_val = phy->ops.read_phy_reg(hw, I82577_CTRL_REG, &phy_data);
-       if (ret_val)
-               goto out;
-       phy_data &= ~I82577_CTRL_DOWNSHIFT_MASK;
-       ret_val = phy->ops.write_phy_reg(hw, I82577_CTRL_REG, phy_data);
+       ret_val = phy->ops.write_reg(hw, I82577_CFG_REG, phy_data);
 
 out:
        return ret_val;
@@ -786,12 +755,12 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
        /* Commit the changes. */
        ret_val = e1000e_commit_phy(hw);
        if (ret_val) {
-               hw_dbg(hw, "Error committing the PHY changes\n");
+               e_dbg("Error committing the PHY changes\n");
                return ret_val;
        }
 
        if (phy->type == e1000_phy_82578) {
-               ret_val = phy->ops.read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
+               ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
                                            &phy_data);
                if (ret_val)
                        return ret_val;
@@ -799,7 +768,7 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
                /* 82578 PHY - set the downshift count to 1x. */
                phy_data |= I82578_EPSCR_DOWNSHIFT_ENABLE;
                phy_data &= ~I82578_EPSCR_DOWNSHIFT_COUNTER_MASK;
-               ret_val = phy->ops.write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
+               ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
                                             phy_data);
                if (ret_val)
                        return ret_val;
@@ -823,7 +792,7 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw)
 
        ret_val = e1000_phy_hw_reset(hw);
        if (ret_val) {
-               hw_dbg(hw, "Error resetting the PHY.\n");
+               e_dbg("Error resetting the PHY.\n");
                return ret_val;
        }
 
@@ -834,9 +803,9 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw)
        msleep(100);
 
        /* disable lplu d0 during driver init */
-       ret_val = e1000_set_d0_lplu_state(hw, 0);
+       ret_val = e1000_set_d0_lplu_state(hw, false);
        if (ret_val) {
-               hw_dbg(hw, "Error Disabling LPLU D0\n");
+               e_dbg("Error Disabling LPLU D0\n");
                return ret_val;
        }
        /* Configure mdi-mdix settings */
@@ -972,39 +941,39 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
                                 NWAY_AR_10T_HD_CAPS);
        mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS);
 
-       hw_dbg(hw, "autoneg_advertised %x\n", phy->autoneg_advertised);
+       e_dbg("autoneg_advertised %x\n", phy->autoneg_advertised);
 
        /* Do we want to advertise 10 Mb Half Duplex? */
        if (phy->autoneg_advertised & ADVERTISE_10_HALF) {
-               hw_dbg(hw, "Advertise 10mb Half duplex\n");
+               e_dbg("Advertise 10mb Half duplex\n");
                mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
        }
 
        /* Do we want to advertise 10 Mb Full Duplex? */
        if (phy->autoneg_advertised & ADVERTISE_10_FULL) {
-               hw_dbg(hw, "Advertise 10mb Full duplex\n");
+               e_dbg("Advertise 10mb Full duplex\n");
                mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
        }
 
        /* Do we want to advertise 100 Mb Half Duplex? */
        if (phy->autoneg_advertised & ADVERTISE_100_HALF) {
-               hw_dbg(hw, "Advertise 100mb Half duplex\n");
+               e_dbg("Advertise 100mb Half duplex\n");
                mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
        }
 
        /* Do we want to advertise 100 Mb Full Duplex? */
        if (phy->autoneg_advertised & ADVERTISE_100_FULL) {
-               hw_dbg(hw, "Advertise 100mb Full duplex\n");
+               e_dbg("Advertise 100mb Full duplex\n");
                mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
        }
 
        /* We do not allow the Phy to advertise 1000 Mb Half Duplex */
        if (phy->autoneg_advertised & ADVERTISE_1000_HALF)
-               hw_dbg(hw, "Advertise 1000mb Half duplex request denied!\n");
+               e_dbg("Advertise 1000mb Half duplex request denied!\n");
 
        /* Do we want to advertise 1000 Mb Full Duplex? */
        if (phy->autoneg_advertised & ADVERTISE_1000_FULL) {
-               hw_dbg(hw, "Advertise 1000mb Full duplex\n");
+               e_dbg("Advertise 1000mb Full duplex\n");
                mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
        }
 
@@ -1063,7 +1032,7 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
                mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
                break;
        default:
-               hw_dbg(hw, "Flow control param set incorrectly\n");
+               e_dbg("Flow control param set incorrectly\n");
                ret_val = -E1000_ERR_CONFIG;
                return ret_val;
        }
@@ -1072,7 +1041,7 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       hw_dbg(hw, "Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
+       e_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
 
        if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
                ret_val = e1e_wphy(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
@@ -1109,13 +1078,13 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
        if (phy->autoneg_advertised == 0)
                phy->autoneg_advertised = phy->autoneg_mask;
 
-       hw_dbg(hw, "Reconfiguring auto-neg advertisement params\n");
+       e_dbg("Reconfiguring auto-neg advertisement params\n");
        ret_val = e1000_phy_setup_autoneg(hw);
        if (ret_val) {
-               hw_dbg(hw, "Error Setting up Auto-Negotiation\n");
+               e_dbg("Error Setting up Auto-Negotiation\n");
                return ret_val;
        }
-       hw_dbg(hw, "Restarting Auto-Neg\n");
+       e_dbg("Restarting Auto-Neg\n");
 
        /*
         * Restart auto-negotiation by setting the Auto Neg Enable bit and
@@ -1137,7 +1106,7 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
        if (phy->autoneg_wait_to_complete) {
                ret_val = e1000_wait_autoneg(hw);
                if (ret_val) {
-                       hw_dbg(hw, "Error while waiting for "
+                       e_dbg("Error while waiting for "
                                 "autoneg to complete\n");
                        return ret_val;
                }
@@ -1175,10 +1144,10 @@ s32 e1000e_setup_copper_link(struct e1000_hw *hw)
                 * PHY will be set to 10H, 10F, 100H or 100F
                 * depending on user settings.
                 */
-               hw_dbg(hw, "Forcing Speed and Duplex\n");
+               e_dbg("Forcing Speed and Duplex\n");
                ret_val = e1000_phy_force_speed_duplex(hw);
                if (ret_val) {
-                       hw_dbg(hw, "Error Forcing Speed and Duplex\n");
+                       e_dbg("Error Forcing Speed and Duplex\n");
                        return ret_val;
                }
        }
@@ -1195,11 +1164,11 @@ s32 e1000e_setup_copper_link(struct e1000_hw *hw)
                return ret_val;
 
        if (link) {
-               hw_dbg(hw, "Valid link established!!!\n");
+               e_dbg("Valid link established!!!\n");
                e1000e_config_collision_dist(hw);
                ret_val = e1000e_config_fc_after_link_up(hw);
        } else {
-               hw_dbg(hw, "Unable to establish link!!!\n");
+               e_dbg("Unable to establish link!!!\n");
        }
 
        return ret_val;
@@ -1245,12 +1214,12 @@ s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       hw_dbg(hw, "IGP PSCR: %X\n", phy_data);
+       e_dbg("IGP PSCR: %X\n", phy_data);
 
        udelay(1);
 
        if (phy->autoneg_wait_to_complete) {
-               hw_dbg(hw, "Waiting for forced speed/duplex link on IGP phy.\n");
+               e_dbg("Waiting for forced speed/duplex link on IGP phy.\n");
 
                ret_val = e1000e_phy_has_link_generic(hw,
                                                     PHY_FORCE_LIMIT,
@@ -1260,7 +1229,7 @@ s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw)
                        return ret_val;
 
                if (!link)
-                       hw_dbg(hw, "Link taking longer than expected.\n");
+                       e_dbg("Link taking longer than expected.\n");
 
                /* Try once more */
                ret_val = e1000e_phy_has_link_generic(hw,
@@ -1304,7 +1273,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       hw_dbg(hw, "M88E1000 PSCR: %X\n", phy_data);
+       e_dbg("M88E1000 PSCR: %X\n", phy_data);
 
        ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data);
        if (ret_val)
@@ -1322,7 +1291,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
                return ret_val;
 
        if (phy->autoneg_wait_to_complete) {
-               hw_dbg(hw, "Waiting for forced speed/duplex link on M88 phy.\n");
+               e_dbg("Waiting for forced speed/duplex link on M88 phy.\n");
 
                ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
                                                     100000, &link);
@@ -1330,17 +1299,22 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
                        return ret_val;
 
                if (!link) {
-                       /*
-                        * We didn't get link.
-                        * Reset the DSP and cross our fingers.
-                        */
-                       ret_val = e1e_wphy(hw, M88E1000_PHY_PAGE_SELECT,
-                                          0x001d);
-                       if (ret_val)
-                               return ret_val;
-                       ret_val = e1000e_phy_reset_dsp(hw);
-                       if (ret_val)
-                               return ret_val;
+                       if (hw->phy.type != e1000_phy_m88) {
+                               e_dbg("Link taking longer than expected.\n");
+                       } else {
+                               /*
+                                * We didn't get link.
+                                * Reset the DSP and cross our fingers.
+                                */
+                               ret_val = e1e_wphy(hw,
+                                               M88E1000_PHY_PAGE_SELECT,
+                                               0x001d);
+                               if (ret_val)
+                                       return ret_val;
+                               ret_val = e1000e_phy_reset_dsp(hw);
+                               if (ret_val)
+                                       return ret_val;
+                       }
                }
 
                /* Try once more */
@@ -1350,6 +1324,9 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
                        return ret_val;
        }
 
+       if (hw->phy.type != e1000_phy_m88)
+               return 0;
+
        ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
        if (ret_val)
                return ret_val;
@@ -1379,6 +1356,73 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
 }
 
 /**
+ *  e1000_phy_force_speed_duplex_ife - Force PHY speed & duplex
+ *  @hw: pointer to the HW structure
+ *
+ *  Forces the speed and duplex settings of the PHY.
+ *  This is a function pointer entry point only called by
+ *  PHY setup routines.
+ **/
+s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val;
+       u16 data;
+       bool link;
+
+       ret_val = e1e_rphy(hw, PHY_CONTROL, &data);
+       if (ret_val)
+               goto out;
+
+       e1000e_phy_force_speed_duplex_setup(hw, &data);
+
+       ret_val = e1e_wphy(hw, PHY_CONTROL, data);
+       if (ret_val)
+               goto out;
+
+       /* Disable MDI-X support for 10/100 */
+       ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data);
+       if (ret_val)
+               goto out;
+
+       data &= ~IFE_PMC_AUTO_MDIX;
+       data &= ~IFE_PMC_FORCE_MDIX;
+
+       ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, data);
+       if (ret_val)
+               goto out;
+
+       e_dbg("IFE PMC: %X\n", data);
+
+       udelay(1);
+
+       if (phy->autoneg_wait_to_complete) {
+               e_dbg("Waiting for forced speed/duplex link on IFE phy.\n");
+
+               ret_val = e1000e_phy_has_link_generic(hw,
+                                                    PHY_FORCE_LIMIT,
+                                                    100000,
+                                                    &link);
+               if (ret_val)
+                       goto out;
+
+               if (!link)
+                       e_dbg("Link taking longer than expected.\n");
+
+               /* Try once more */
+               ret_val = e1000e_phy_has_link_generic(hw,
+                                                    PHY_FORCE_LIMIT,
+                                                    100000,
+                                                    &link);
+               if (ret_val)
+                       goto out;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
  *  e1000e_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex
  *  @hw: pointer to the HW structure
  *  @phy_ctrl: pointer to current value of PHY_CONTROL
@@ -1413,11 +1457,11 @@ void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
        if (mac->forced_speed_duplex & E1000_ALL_HALF_DUPLEX) {
                ctrl &= ~E1000_CTRL_FD;
                *phy_ctrl &= ~MII_CR_FULL_DUPLEX;
-               hw_dbg(hw, "Half Duplex\n");
+               e_dbg("Half Duplex\n");
        } else {
                ctrl |= E1000_CTRL_FD;
                *phy_ctrl |= MII_CR_FULL_DUPLEX;
-               hw_dbg(hw, "Full Duplex\n");
+               e_dbg("Full Duplex\n");
        }
 
        /* Forcing 10mb or 100mb? */
@@ -1425,12 +1469,12 @@ void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
                ctrl |= E1000_CTRL_SPD_100;
                *phy_ctrl |= MII_CR_SPEED_100;
                *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10);
-               hw_dbg(hw, "Forcing 100mb\n");
+               e_dbg("Forcing 100mb\n");
        } else {
                ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
                *phy_ctrl |= MII_CR_SPEED_10;
                *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100);
-               hw_dbg(hw, "Forcing 10mb\n");
+               e_dbg("Forcing 10mb\n");
        }
 
        e1000e_config_collision_dist(hw);
@@ -1533,8 +1577,8 @@ s32 e1000e_check_downshift(struct e1000_hw *hw)
        switch (phy->type) {
        case e1000_phy_m88:
        case e1000_phy_gg82563:
+       case e1000_phy_bm:
        case e1000_phy_82578:
-       case e1000_phy_82577:
                offset  = M88E1000_PHY_SPEC_STATUS;
                mask    = M88E1000_PSSR_DOWNSHIFT;
                break;
@@ -1545,7 +1589,7 @@ s32 e1000e_check_downshift(struct e1000_hw *hw)
                break;
        default:
                /* speed downshift not supported */
-               phy->speed_downgraded = 0;
+               phy->speed_downgraded = false;
                return 0;
        }
 
@@ -1565,7 +1609,7 @@ s32 e1000e_check_downshift(struct e1000_hw *hw)
  *
  *  Polarity is determined based on the PHY specific status register.
  **/
-static s32 e1000_check_polarity_m88(struct e1000_hw *hw)
+s32 e1000_check_polarity_m88(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
@@ -1590,7 +1634,7 @@ static s32 e1000_check_polarity_m88(struct e1000_hw *hw)
  *  Polarity is determined based on the PHY port status register, and the
  *  current speed (since there is no polarity at 100Mbps).
  **/
-static s32 e1000_check_polarity_igp(struct e1000_hw *hw)
+s32 e1000_check_polarity_igp(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
@@ -1628,6 +1672,39 @@ static s32 e1000_check_polarity_igp(struct e1000_hw *hw)
 }
 
 /**
+ *  e1000_check_polarity_ife - Check cable polarity for IFE PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Polarity is determined on the polarity reversal feature being enabled.
+ **/
+s32 e1000_check_polarity_ife(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val;
+       u16 phy_data, offset, mask;
+
+       /*
+        * Polarity is determined based on the reversal feature being enabled.
+        */
+       if (phy->polarity_correction) {
+               offset = IFE_PHY_EXTENDED_STATUS_CONTROL;
+               mask = IFE_PESC_POLARITY_REVERSED;
+       } else {
+               offset = IFE_PHY_SPECIAL_CONTROL;
+               mask = IFE_PSC_FORCE_POLARITY;
+       }
+
+       ret_val = e1e_rphy(hw, offset, &phy_data);
+
+       if (!ret_val)
+               phy->cable_polarity = (phy_data & mask)
+                                      ? e1000_rev_polarity_reversed
+                                      : e1000_rev_polarity_normal;
+
+       return ret_val;
+}
+
+/**
  *  e1000_wait_autoneg - Wait for auto-neg completion
  *  @hw: pointer to the HW structure
  *
@@ -1727,15 +1804,21 @@ s32 e1000e_get_cable_length_m88(struct e1000_hw *hw)
 
        ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
        if (ret_val)
-               return ret_val;
+               goto out;
 
        index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
-               M88E1000_PSSR_CABLE_LENGTH_SHIFT;
+               M88E1000_PSSR_CABLE_LENGTH_SHIFT;
+       if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) {
+               ret_val = -E1000_ERR_PHY;
+               goto out;
+       }
+
        phy->min_cable_length = e1000_m88_cable_length_table[index];
-       phy->max_cable_length = e1000_m88_cable_length_table[index+1];
+       phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
 
        phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
 
+out:
        return ret_val;
 }
 
@@ -1746,7 +1829,7 @@ s32 e1000e_get_cable_length_m88(struct e1000_hw *hw)
  *  The automatic gain control (agc) normalizes the amplitude of the
  *  received signal, adjusting for the attenuation produced by the
  *  cable.  By reading the AGC registers, which represent the
- *  combination of course and fine gain value, the value can be put
+ *  combination of coarse and fine gain value, the value can be put
  *  into a lookup table to obtain the approximate cable length
  *  for each channel.
  **/
@@ -1771,7 +1854,7 @@ s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw)
 
                /*
                 * Getting bits 15:9, which represent the combination of
-                * course and fine gain values.  The result is a number
+                * coarse and fine gain values.  The result is a number
                 * that can be put into the lookup table to obtain the
                 * approximate cable length.
                 */
@@ -1825,8 +1908,8 @@ s32 e1000e_get_phy_info_m88(struct e1000_hw *hw)
        u16 phy_data;
        bool link;
 
-       if (hw->phy.media_type != e1000_media_type_copper) {
-               hw_dbg(hw, "Phy info is only valid for copper media\n");
+       if (phy->media_type != e1000_media_type_copper) {
+               e_dbg("Phy info is only valid for copper media\n");
                return -E1000_ERR_CONFIG;
        }
 
@@ -1835,7 +1918,7 @@ s32 e1000e_get_phy_info_m88(struct e1000_hw *hw)
                return ret_val;
 
        if (!link) {
-               hw_dbg(hw, "Phy info is only valid if link is up\n");
+               e_dbg("Phy info is only valid if link is up\n");
                return -E1000_ERR_CONFIG;
        }
 
@@ -1903,11 +1986,11 @@ s32 e1000e_get_phy_info_igp(struct e1000_hw *hw)
                return ret_val;
 
        if (!link) {
-               hw_dbg(hw, "Phy info is only valid if link is up\n");
+               e_dbg("Phy info is only valid if link is up\n");
                return -E1000_ERR_CONFIG;
        }
 
-       phy->polarity_correction = 1;
+       phy->polarity_correction = true;
 
        ret_val = e1000_check_polarity_igp(hw);
        if (ret_val)
@@ -1946,6 +2029,61 @@ s32 e1000e_get_phy_info_igp(struct e1000_hw *hw)
 }
 
 /**
+ *  e1000_get_phy_info_ife - Retrieves various IFE PHY states
+ *  @hw: pointer to the HW structure
+ *
+ *  Populates "phy" structure with various feature states.
+ **/
+s32 e1000_get_phy_info_ife(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val;
+       u16 data;
+       bool link;
+
+       ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
+       if (ret_val)
+               goto out;
+
+       if (!link) {
+               e_dbg("Phy info is only valid if link is up\n");
+               ret_val = -E1000_ERR_CONFIG;
+               goto out;
+       }
+
+       ret_val = e1e_rphy(hw, IFE_PHY_SPECIAL_CONTROL, &data);
+       if (ret_val)
+               goto out;
+       phy->polarity_correction = (data & IFE_PSC_AUTO_POLARITY_DISABLE)
+                                  ? false : true;
+
+       if (phy->polarity_correction) {
+               ret_val = e1000_check_polarity_ife(hw);
+               if (ret_val)
+                       goto out;
+       } else {
+               /* Polarity is forced */
+               phy->cable_polarity = (data & IFE_PSC_FORCE_POLARITY)
+                                     ? e1000_rev_polarity_reversed
+                                     : e1000_rev_polarity_normal;
+       }
+
+       ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data);
+       if (ret_val)
+               goto out;
+
+       phy->is_mdix = (data & IFE_PMC_MDIX_STATUS) ? true : false;
+
+       /* The following parameters are undefined for 10/100 operation. */
+       phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
+       phy->local_rx = e1000_1000t_rx_status_undefined;
+       phy->remote_rx = e1000_1000t_rx_status_undefined;
+
+out:
+       return ret_val;
+}
+
+/**
  *  e1000e_phy_sw_reset - PHY software reset
  *  @hw: pointer to the HW structure
  *
@@ -1990,7 +2128,7 @@ s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw)
        if (ret_val)
                return 0;
 
-       ret_val = phy->ops.acquire_phy(hw);
+       ret_val = phy->ops.acquire(hw);
        if (ret_val)
                return ret_val;
 
@@ -2005,7 +2143,7 @@ s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw)
 
        udelay(150);
 
-       phy->ops.release_phy(hw);
+       phy->ops.release(hw);
 
        return e1000_get_phy_cfg_done(hw);
 }
@@ -2031,7 +2169,7 @@ s32 e1000e_get_cfg_done(struct e1000_hw *hw)
  **/
 s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw)
 {
-       hw_dbg(hw, "Running IGP 3 PHY init script\n");
+       e_dbg("Running IGP 3 PHY init script\n");
 
        /* PHY init IGP 3 */
        /* Enable rise/fall, 10-mode work in class-A */
@@ -2199,28 +2337,34 @@ enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id)
 s32 e1000e_determine_phy_address(struct e1000_hw *hw)
 {
        s32 ret_val = -E1000_ERR_PHY_TYPE;
-       u32 phy_addr= 0;
-       u32 i = 0;
+       u32 phy_addr = 0;
+       u32 i;
        enum e1000_phy_type phy_type = e1000_phy_unknown;
 
-       do {
-               for (phy_addr = 0; phy_addr < 4; phy_addr++) {
-                       hw->phy.addr = phy_addr;
+       hw->phy.id = phy_type;
+
+       for (phy_addr = 0; phy_addr < E1000_MAX_PHY_ADDR; phy_addr++) {
+               hw->phy.addr = phy_addr;
+               i = 0;
+
+               do {
                        e1000e_get_phy_id(hw);
                        phy_type = e1000e_get_phy_type_from_id(hw->phy.id);
 
-                       /* 
+                       /*
                         * If phy_type is valid, break - we found our
                         * PHY address
                         */
                        if (phy_type  != e1000_phy_unknown) {
                                ret_val = 0;
-                               break;
+                               goto out;
                        }
-               }
-               i++;
-       } while ((ret_val != 0) && (i < 100));
+                       msleep(1);
+                       i++;
+               } while (i < 10);
+       }
 
+out:
        return ret_val;
 }
 
@@ -2256,7 +2400,7 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
        u32 page = offset >> IGP_PAGE_SHIFT;
        u32 page_shift = 0;
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
+       ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
                return ret_val;
 
@@ -2294,7 +2438,7 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
                                            data);
 
 out:
-       hw->phy.ops.release_phy(hw);
+       hw->phy.ops.release(hw);
        return ret_val;
 }
 
@@ -2315,7 +2459,7 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
        u32 page = offset >> IGP_PAGE_SHIFT;
        u32 page_shift = 0;
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
+       ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
                return ret_val;
 
@@ -2352,7 +2496,7 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
        ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
                                           data);
 out:
-       hw->phy.ops.release_phy(hw);
+       hw->phy.ops.release(hw);
        return ret_val;
 }
 
@@ -2371,7 +2515,7 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
        s32 ret_val;
        u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
+       ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
                return ret_val;
 
@@ -2397,7 +2541,7 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
        ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
                                           data);
 out:
-       hw->phy.ops.release_phy(hw);
+       hw->phy.ops.release(hw);
        return ret_val;
 }
 
@@ -2415,7 +2559,7 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
        s32 ret_val;
        u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
+       ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
                return ret_val;
 
@@ -2441,7 +2585,7 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
                                            data);
 
 out:
-       hw->phy.ops.release_phy(hw);
+       hw->phy.ops.release(hw);
        return ret_val;
 }
 
@@ -2474,7 +2618,7 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
        /* Gig must be disabled for MDIO accesses to page 800 */
        if ((hw->mac.type == e1000_pchlan) &&
           (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
-               hw_dbg(hw, "Attempting to access page 800 while gig enabled\n");
+               e_dbg("Attempting to access page 800 while gig enabled.\n");
 
        /* All operations in this function are phy address 1 */
        hw->phy.addr = 1;
@@ -2484,20 +2628,26 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
                                  (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
 
        ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg);
-       if (ret_val)
+       if (ret_val) {
+               e_dbg("Could not read PHY page 769\n");
                goto out;
+       }
 
        /* First clear bit 4 to avoid a power state change */
        phy_reg &= ~(BM_WUC_HOST_WU_BIT);
        ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
-       if (ret_val)
+       if (ret_val) {
+               e_dbg("Could not clear PHY page 769 bit 4\n");
                goto out;
+       }
 
        /* Write bit 2 = 1, and clear bit 4 to 769_17 */
        ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG,
                                            phy_reg | BM_WUC_ENABLE_BIT);
-       if (ret_val)
+       if (ret_val) {
+               e_dbg("Could not write PHY page 769 bit 2\n");
                goto out;
+       }
 
        /* Select page 800 */
        ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
@@ -2505,21 +2655,25 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
 
        /* Write the page 800 offset value using opcode 0x11 */
        ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg);
-       if (ret_val)
+       if (ret_val) {
+               e_dbg("Could not write address opcode to page 800\n");
                goto out;
+       }
 
        if (read) {
                /* Read the page 800 value using opcode 0x12 */
                ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
                                                   data);
        } else {
-               /* Read the page 800 value using opcode 0x12 */
+               /* Write the page 800 value using opcode 0x12 */
                ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
                                                    *data);
        }
 
-       if (ret_val)
+       if (ret_val) {
+               e_dbg("Could not access data value from page 800\n");
                goto out;
+       }
 
        /*
         * Restore 769_17.2 to its original value
@@ -2530,12 +2684,53 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
 
        /* Clear 769_17.2 */
        ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
+       if (ret_val) {
+               e_dbg("Could not clear PHY page 769 bit 2\n");
+               goto out;
+       }
 
 out:
        return ret_val;
 }
 
 /**
+ * e1000_power_up_phy_copper - Restore copper link in case of PHY power down
+ * @hw: pointer to the HW structure
+ *
+ * In the case of a PHY power down to save power, or to turn off link during a
+ * driver unload, or wake on lan is not enabled, restore the link to previous
+ * settings.
+ **/
+void e1000_power_up_phy_copper(struct e1000_hw *hw)
+{
+       u16 mii_reg = 0;
+
+       /* The PHY will retain its settings across a power down/up cycle */
+       e1e_rphy(hw, PHY_CONTROL, &mii_reg);
+       mii_reg &= ~MII_CR_POWER_DOWN;
+       e1e_wphy(hw, PHY_CONTROL, mii_reg);
+}
+
+/**
+ * e1000_power_down_phy_copper - Restore copper link in case of PHY power down
+ * @hw: pointer to the HW structure
+ *
+ * In the case of a PHY power down to save power, or to turn off link during a
+ * driver unload, or wake on lan is not enabled, restore the link to previous
+ * settings.
+ **/
+void e1000_power_down_phy_copper(struct e1000_hw *hw)
+{
+       u16 mii_reg = 0;
+
+       /* The PHY will retain its settings across a power down/up cycle */
+       e1e_rphy(hw, PHY_CONTROL, &mii_reg);
+       mii_reg |= MII_CR_POWER_DOWN;
+       e1e_wphy(hw, PHY_CONTROL, mii_reg);
+       msleep(1);
+}
+
+/**
  *  e1000e_commit_phy - Soft PHY reset
  *  @hw: pointer to the HW structure
  *
@@ -2544,8 +2739,8 @@ out:
  **/
 s32 e1000e_commit_phy(struct e1000_hw *hw)
 {
-       if (hw->phy.ops.commit_phy)
-               return hw->phy.ops.commit_phy(hw);
+       if (hw->phy.ops.commit)
+               return hw->phy.ops.commit(hw);
 
        return 0;
 }
@@ -2573,38 +2768,6 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
 }
 
 /**
- *  e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode
- *  @hw:   pointer to the HW structure
- *  @slow: true for slow mode, false for normal mode
- *
- *  Assumes semaphore already acquired.
- **/
-s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow)
-{
-       s32 ret_val = 0;
-       u16 data = 0;
-
-       /* Set MDIO mode - page 769, register 16: 0x2580==slow, 0x2180==fast */
-       hw->phy.addr = 1;
-       ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
-                                        (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
-       if (ret_val)
-               goto out;
-
-       ret_val = e1000e_write_phy_reg_mdic(hw, BM_CS_CTRL1,
-                                          (0x2180 | (slow << 10)));
-       if (ret_val)
-               goto out;
-
-       /* dummy read when reverting to fast mode - throw away result */
-       if (!slow)
-               ret_val = e1000e_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data);
-
-out:
-       return ret_val;
-}
-
-/**
  *  __e1000_read_phy_reg_hv -  Read HV PHY register
  *  @hw: pointer to the HW structure
  *  @offset: register offset to be read
@@ -2621,24 +2784,13 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
        s32 ret_val;
        u16 page = BM_PHY_REG_PAGE(offset);
        u16 reg = BM_PHY_REG_NUM(offset);
-       bool in_slow_mode = false;
 
        if (!locked) {
-               ret_val = hw->phy.ops.acquire_phy(hw);
+               ret_val = hw->phy.ops.acquire(hw);
                if (ret_val)
                        return ret_val;
        }
 
-       /* Workaround failure in MDIO access while cable is disconnected */
-       if ((hw->phy.type == e1000_phy_82577) &&
-           !(er32(STATUS) & E1000_STATUS_LU)) {
-               ret_val = e1000_set_mdio_slow_mode_hv(hw, true);
-               if (ret_val)
-                       goto out;
-
-               in_slow_mode = true;
-       }
-
        /* Page 800 works differently than the rest so it has its own func */
        if (page == BM_WUC_PAGE) {
                ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset,
@@ -2675,12 +2827,8 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
        ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
                                          data);
 out:
-       /* Revert to MDIO fast mode, if applicable */
-       if ((hw->phy.type == e1000_phy_82577) && in_slow_mode)
-               ret_val |= e1000_set_mdio_slow_mode_hv(hw, false);
-
        if (!locked)
-               hw->phy.ops.release_phy(hw);
+               hw->phy.ops.release(hw);
 
        return ret_val;
 }
@@ -2730,24 +2878,13 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
        s32 ret_val;
        u16 page = BM_PHY_REG_PAGE(offset);
        u16 reg = BM_PHY_REG_NUM(offset);
-       bool in_slow_mode = false;
 
        if (!locked) {
-               ret_val = hw->phy.ops.acquire_phy(hw);
+               ret_val = hw->phy.ops.acquire(hw);
                if (ret_val)
                        return ret_val;
        }
 
-       /* Workaround failure in MDIO access while cable is disconnected */
-       if ((hw->phy.type == e1000_phy_82577) &&
-           !(er32(STATUS) & E1000_STATUS_LU)) {
-               ret_val = e1000_set_mdio_slow_mode_hv(hw, true);
-               if (ret_val)
-                       goto out;
-
-               in_slow_mode = true;
-       }
-
        /* Page 800 works differently than the rest so it has its own func */
        if (page == BM_WUC_PAGE) {
                ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset,
@@ -2801,12 +2938,8 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
                                          data);
 
 out:
-       /* Revert to MDIO fast mode, if applicable */
-       if ((hw->phy.type == e1000_phy_82577) && in_slow_mode)
-               ret_val |= e1000_set_mdio_slow_mode_hv(hw, false);
-
        if (!locked)
-               hw->phy.ops.release_phy(hw);
+               hw->phy.ops.release(hw);
 
        return ret_val;
 }
@@ -2882,7 +3015,7 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
        /* masking with 0x3F to remove the page from offset */
        ret_val = e1000e_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F);
        if (ret_val) {
-               hw_dbg(hw, "Could not write PHY the HV address register\n");
+               e_dbg("Could not write PHY the HV address register\n");
                goto out;
        }
 
@@ -2893,7 +3026,7 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
                ret_val = e1000e_write_phy_reg_mdic(hw, data_reg, *data);
 
        if (ret_val) {
-               hw_dbg(hw, "Could not read data value from HV data register\n");
+               e_dbg("Could not read data value from HV data register\n");
                goto out;
        }
 
@@ -2921,12 +3054,12 @@ s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw)
                goto out;
 
        /* Do not apply workaround if in PHY loopback bit 14 set */
-       hw->phy.ops.read_phy_reg(hw, PHY_CONTROL, &data);
+       hw->phy.ops.read_reg(hw, PHY_CONTROL, &data);
        if (data & PHY_CONTROL_LB)
                goto out;
 
        /* check if link is up and at 1Gbps */
-       ret_val = hw->phy.ops.read_phy_reg(hw, BM_CS_STATUS, &data);
+       ret_val = hw->phy.ops.read_reg(hw, BM_CS_STATUS, &data);
        if (ret_val)
                goto out;
 
@@ -2942,13 +3075,13 @@ s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw)
        mdelay(200);
 
        /* flush the packets in the fifo buffer */
-       ret_val = hw->phy.ops.write_phy_reg(hw, HV_MUX_DATA_CTRL,
+       ret_val = hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL,
                                        HV_MUX_DATA_CTRL_GEN_TO_MAC |
                                        HV_MUX_DATA_CTRL_FORCE_SPEED);
        if (ret_val)
                goto out;
 
-       ret_val = hw->phy.ops.write_phy_reg(hw, HV_MUX_DATA_CTRL,
+       ret_val = hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL,
                                        HV_MUX_DATA_CTRL_GEN_TO_MAC);
 
 out:
@@ -2969,7 +3102,7 @@ s32 e1000_check_polarity_82577(struct e1000_hw *hw)
        s32 ret_val;
        u16 data;
 
-       ret_val = phy->ops.read_phy_reg(hw, I82577_PHY_STATUS_2, &data);
+       ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data);
 
        if (!ret_val)
                phy->cable_polarity = (data & I82577_PHY_STATUS2_REV_POLARITY)
@@ -2994,13 +3127,13 @@ s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
        u16 phy_data;
        bool link;
 
-       ret_val = phy->ops.read_phy_reg(hw, PHY_CONTROL, &phy_data);
+       ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
        if (ret_val)
                goto out;
 
        e1000e_phy_force_speed_duplex_setup(hw, &phy_data);
 
-       ret_val = phy->ops.write_phy_reg(hw, PHY_CONTROL, phy_data);
+       ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
        if (ret_val)
                goto out;
 
@@ -3008,23 +3141,23 @@ s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
         * Clear Auto-Crossover to force MDI manually.  82577 requires MDI
         * forced whenever speed and duplex are forced.
         */
-       ret_val = phy->ops.read_phy_reg(hw, I82577_PHY_CTRL_2, &phy_data);
+       ret_val = phy->ops.read_reg(hw, I82577_PHY_CTRL_2, &phy_data);
        if (ret_val)
                goto out;
 
        phy_data &= ~I82577_PHY_CTRL2_AUTO_MDIX;
        phy_data &= ~I82577_PHY_CTRL2_FORCE_MDI_MDIX;
 
-       ret_val = phy->ops.write_phy_reg(hw, I82577_PHY_CTRL_2, phy_data);
+       ret_val = phy->ops.write_reg(hw, I82577_PHY_CTRL_2, phy_data);
        if (ret_val)
                goto out;
 
-       hw_dbg(hw, "I82577_PHY_CTRL_2: %X\n", phy_data);
+       e_dbg("I82577_PHY_CTRL_2: %X\n", phy_data);
 
        udelay(1);
 
        if (phy->autoneg_wait_to_complete) {
-               hw_dbg(hw, "Waiting for forced speed/duplex link on 82577 phy\n");
+               e_dbg("Waiting for forced speed/duplex link on 82577 phy\n");
 
                ret_val = e1000e_phy_has_link_generic(hw,
                                                     PHY_FORCE_LIMIT,
@@ -3034,7 +3167,7 @@ s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
                        goto out;
 
                if (!link)
-                       hw_dbg(hw, "Link taking longer than expected.\n");
+                       e_dbg("Link taking longer than expected.\n");
 
                /* Try once more */
                ret_val = e1000e_phy_has_link_generic(hw,
@@ -3070,7 +3203,7 @@ s32 e1000_get_phy_info_82577(struct e1000_hw *hw)
                goto out;
 
        if (!link) {
-               hw_dbg(hw, "Phy info is only valid if link is up\n");
+               e_dbg("Phy info is only valid if link is up\n");
                ret_val = -E1000_ERR_CONFIG;
                goto out;
        }
@@ -3081,7 +3214,7 @@ s32 e1000_get_phy_info_82577(struct e1000_hw *hw)
        if (ret_val)
                goto out;
 
-       ret_val = phy->ops.read_phy_reg(hw, I82577_PHY_STATUS_2, &data);
+       ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data);
        if (ret_val)
                goto out;
 
@@ -3093,7 +3226,7 @@ s32 e1000_get_phy_info_82577(struct e1000_hw *hw)
                if (ret_val)
                        goto out;
 
-               ret_val = phy->ops.read_phy_reg(hw, PHY_1000T_STATUS, &data);
+               ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data);
                if (ret_val)
                        goto out;
 
@@ -3127,7 +3260,7 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw)
        s32 ret_val;
        u16 phy_data, length;
 
-       ret_val = phy->ops.read_phy_reg(hw, I82577_PHY_DIAG_STATUS, &phy_data);
+       ret_val = phy->ops.read_reg(hw, I82577_PHY_DIAG_STATUS, &phy_data);
        if (ret_val)
                goto out;
 
@@ -3135,7 +3268,7 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw)
                 I82577_DSTATUS_CABLE_LENGTH_SHIFT;
 
        if (length == E1000_CABLE_LENGTH_UNDEFINED)
-               ret_val = E1000_ERR_PHY;
+               ret_val = -E1000_ERR_PHY;
 
        phy->cable_length = length;