From 842ec8b64ac34e9b245da31b4a5a49c3e744a714 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Thu, 19 Nov 2009 12:34:40 +0000 Subject: e1000e: read of PHY register may access wrong page on 82578 Remove unnecessary workaround that mistakenly does not perform a page select operation for PHY registers 29 and 30 (assuming these are the PHY debug port address and data registers) on 82578 which can cause reads of the Transmit with No Carrier Sense statistics register on page 778 to be read from an incorrect page. Also error out if the page select operation fails. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/phy.c | 46 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 24 deletions(-) (limited to 'drivers/net/e1000e/phy.c') diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 03175b3a2c9e..8189d00bfefe 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -2658,19 +2658,18 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, page = 0; if (reg > MAX_PHY_MULTI_PAGE_REG) { - if ((hw->phy.type != e1000_phy_82578) || - ((reg != I82578_ADDR_REG) && - (reg != I82578_ADDR_REG + 1))) { - u32 phy_addr = hw->phy.addr; + u32 phy_addr = hw->phy.addr; - hw->phy.addr = 1; + hw->phy.addr = 1; - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000e_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (page << IGP_PAGE_SHIFT)); - hw->phy.addr = phy_addr; - } + /* Page is shifted left, PHY expects (page x 32) */ + ret_val = e1000e_write_phy_reg_mdic(hw, + IGP01E1000_PHY_PAGE_SELECT, + (page << IGP_PAGE_SHIFT)); + hw->phy.addr = phy_addr; + + if (ret_val) + goto out; } ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, @@ -2678,7 +2677,7 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *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); + ret_val |= e1000_set_mdio_slow_mode_hv(hw, false); if (!locked) hw->phy.ops.release_phy(hw); @@ -2784,19 +2783,18 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, } if (reg > MAX_PHY_MULTI_PAGE_REG) { - if ((hw->phy.type != e1000_phy_82578) || - ((reg != I82578_ADDR_REG) && - (reg != I82578_ADDR_REG + 1))) { - u32 phy_addr = hw->phy.addr; + u32 phy_addr = hw->phy.addr; - hw->phy.addr = 1; + hw->phy.addr = 1; - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000e_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (page << IGP_PAGE_SHIFT)); - hw->phy.addr = phy_addr; - } + /* Page is shifted left, PHY expects (page x 32) */ + ret_val = e1000e_write_phy_reg_mdic(hw, + IGP01E1000_PHY_PAGE_SELECT, + (page << IGP_PAGE_SHIFT)); + hw->phy.addr = phy_addr; + + if (ret_val) + goto out; } ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, @@ -2805,7 +2803,7 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 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); + ret_val |= e1000_set_mdio_slow_mode_hv(hw, false); if (!locked) hw->phy.ops.release_phy(hw); -- cgit v1.2.2 From 189983d469c6d98e64ddfb9f9ce76725cb082ee5 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Thu, 19 Nov 2009 12:36:04 +0000 Subject: e1000e: remove unnecessary 82577 workaround causing link issues A workaround for pre-release versions of 82577 is causing link issues on some switches. The workaround is no longer needed on production parts so remove it. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/phy.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/net/e1000e/phy.c') diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 8189d00bfefe..85f955f70417 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -71,7 +71,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 @@ -660,15 +659,6 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw) 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); out: return ret_val; -- cgit v1.2.2 From 98086a954a75152f8b09c131fa443205bae5fde1 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 20 Nov 2009 23:23:53 +0000 Subject: e1000e: improper return code signage The e1000_get_cable_length_82577() should return a negative value upon error. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/e1000e/phy.c') diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 03175b3a2c9e..95a8196cf44c 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -3137,7 +3137,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; -- cgit v1.2.2 From 3bb99fe226ead584a4db674dab546689f705201f Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 20 Nov 2009 23:25:07 +0000 Subject: e1000e: consolidate two dbug macros into one simpler one This patch depends on a previous one that cleans up redundant #includes. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/phy.c | 92 ++++++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 46 deletions(-) (limited to 'drivers/net/e1000e/phy.c') diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 95a8196cf44c..cff1df204031 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -212,7 +212,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 +239,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 +265,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 +293,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; } @@ -786,7 +786,7 @@ 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; } @@ -823,7 +823,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; } @@ -836,7 +836,7 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw) /* disable lplu d0 during driver init */ ret_val = e1000_set_d0_lplu_state(hw, 0); 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 +972,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 +1063,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 +1072,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 +1109,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 +1137,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 +1175,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 +1195,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 +1245,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 +1260,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 +1304,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 +1322,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); @@ -1413,11 +1413,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 +1425,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); @@ -1826,7 +1826,7 @@ s32 e1000e_get_phy_info_m88(struct e1000_hw *hw) bool link; if (hw->phy.media_type != e1000_media_type_copper) { - hw_dbg(hw, "Phy info is only valid for copper media\n"); + e_dbg("Phy info is only valid for copper media\n"); return -E1000_ERR_CONFIG; } @@ -1835,7 +1835,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,7 +1903,7 @@ 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; } @@ -2031,7 +2031,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 */ @@ -2474,7 +2474,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; @@ -2884,7 +2884,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; } @@ -2895,7 +2895,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; } @@ -3021,12 +3021,12 @@ s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw) 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, @@ -3036,7 +3036,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, @@ -3072,7 +3072,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; } -- cgit v1.2.2 From 94d8186a693284344ee5cb9734086c7a2370241a Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 20 Nov 2009 23:25:26 +0000 Subject: e1000e: cleanup ops function pointers The phy and nvm operations structures have function pointers that contain "phy" and "nvm" in the pointer names which are redundant since the structures are already obviously in phy and nvm structures. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/phy.c | 110 +++++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 55 deletions(-) (limited to 'drivers/net/e1000e/phy.c') diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index cff1df204031..765dc389561b 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -131,7 +131,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) { @@ -157,24 +157,24 @@ s32 e1000e_get_phy_id(struct e1000_hw *hw) * 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); + ret_val = phy->ops.acquire(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); + phy->ops.release(hw); retry_count++; } out: /* Revert to MDIO fast mode, if applicable */ if (retry_count) { - ret_val = phy->ops.acquire_phy(hw); + ret_val = phy->ops.acquire(hw); if (ret_val) return ret_val; ret_val = e1000_set_mdio_slow_mode_hv(hw, false); - phy->ops.release_phy(hw); + phy->ops.release(hw); } return ret_val; @@ -318,14 +318,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 +343,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 +372,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 +393,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 +443,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 +464,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 +516,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 +534,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 +588,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 +603,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 +650,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 +659,16 @@ 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); + ret_val = phy->ops.write_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); + ret_val = phy->ops.read_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_CTRL_REG, phy_data); out: return ret_val; @@ -791,7 +791,7 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw) } 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 +799,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; @@ -1990,7 +1990,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 +2005,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); } @@ -2256,7 +2256,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 +2294,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 +2315,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 +2352,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 +2371,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 +2397,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 +2415,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 +2441,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; } @@ -2544,8 +2544,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; } @@ -2624,7 +2624,7 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, 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; } @@ -2681,7 +2681,7 @@ out: 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; } @@ -2734,7 +2734,7 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, 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; } @@ -2808,7 +2808,7 @@ out: 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; } @@ -2923,12 +2923,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; @@ -2944,13 +2944,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: @@ -2971,7 +2971,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) @@ -2996,13 +2996,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; @@ -3010,14 +3010,14 @@ 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; @@ -3083,7 +3083,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; @@ -3095,7 +3095,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; @@ -3129,7 +3129,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; -- cgit v1.2.2 From c7e54b1bf90480ca4bdfd1491ac6c4b7bfe07c03 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 20 Nov 2009 23:25:45 +0000 Subject: e1000e: update copyright information Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/e1000e/phy.c') diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 765dc389561b..440f366b73f6 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -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, -- cgit v1.2.2 From 564ea9bba1a1380d5474504bcd943ee84075534f Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 20 Nov 2009 23:26:44 +0000 Subject: e1000e: set bools to true/false instead of 1/0 Set booleans to 'true' or 'false' to make it clear it is a boolean. Also change instances of TRUE/FALSE in comments to lowercase true/false. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/phy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/e1000e/phy.c') diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 440f366b73f6..99d53fae4307 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -834,7 +834,7 @@ 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) { e_dbg("Error Disabling LPLU D0\n"); return ret_val; @@ -1545,7 +1545,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; } @@ -1907,7 +1907,7 @@ s32 e1000e_get_phy_info_igp(struct e1000_hw *hw) return -E1000_ERR_CONFIG; } - phy->polarity_correction = 1; + phy->polarity_correction = true; ret_val = e1000_check_polarity_igp(hw); if (ret_val) -- cgit v1.2.2 From eb656d4552a6c9de5fdcee4a376b171f57b8a4a2 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Tue, 1 Dec 2009 15:47:02 +0000 Subject: e1000e: guard against buffer overflow in cable length tables Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/phy.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/net/e1000e/phy.c') diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 5cd01c691c53..9ce499734dca 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -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, @@ -1717,15 +1719,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; } -- cgit v1.2.2 From 17f208deb9bf88315aa72c08c866a235c399fb9a Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Tue, 1 Dec 2009 15:47:22 +0000 Subject: e1000e: provide family-specific PHY power up/down operations The different families (80003es2lan, 8257x, ICHx/PCH) supported by the driver each have their own conditions when the PHY can be powered down. This patch rewrites the PHY power up/down code to fit with the family- specific style used in the driver. All pre-existing calls to power up or down the PHY remain untouched. A new call to power down the PHY when removing the driver when the interface is down replaces the current call to reset the PHY in order to reduce power consumption. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/phy.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'drivers/net/e1000e/phy.c') diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 9ce499734dca..140b23b320fd 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -2533,6 +2533,43 @@ 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 -- cgit v1.2.2 From 5ff5b664351a94754031c1e5783f0cea6b3000ed Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Tue, 1 Dec 2009 15:51:11 +0000 Subject: e1000e: comment corrections Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/phy.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/net/e1000e/phy.c') diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 140b23b320fd..1bc09b240e62 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -153,10 +153,10 @@ s32 e1000e_get_phy_id(struct e1000_hw *hw) 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 + * If the PHY ID is still unknown, we may have an 82577 + * 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(hw); if (ret_val) @@ -1744,7 +1744,7 @@ out: * 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. **/ @@ -1769,7 +1769,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. */ @@ -2511,7 +2511,7 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, 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); } -- cgit v1.2.2 From 9b71b419a60d200f553658a97c9f49a46f58e8bb Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Tue, 1 Dec 2009 15:53:07 +0000 Subject: e1000e: add debug messages Add some helpful debug messages. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/phy.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'drivers/net/e1000e/phy.c') diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 1bc09b240e62..3e5940afe36d 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -2472,7 +2472,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))) - e_dbg("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; @@ -2482,20 +2482,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, @@ -2503,8 +2509,10 @@ 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 */ @@ -2516,8 +2524,10 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, *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 @@ -2528,6 +2538,10 @@ 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; -- cgit v1.2.2 From 07f025e6bad7292af3904b8f49cd33e7b5fe3467 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Tue, 1 Dec 2009 15:53:48 +0000 Subject: e1000e: PHY type cleanups in e1000e_check_downshift() Remove the case for 82577 because it does not support the ability to check for downshift. Add case for e1000_phy_bm which can do this. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/e1000e/phy.c') diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 3e5940afe36d..0c69649af069 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -1525,8 +1525,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; -- cgit v1.2.2 From 5eb6f3c70fcc0fb19b9087863e6e29f96a76f3bd Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 2 Dec 2009 17:02:43 +0000 Subject: e1000e: refactor PHY ID detection workaround The workaround that detects the correct PHY ID when an initial read of the PHY ID registers returns an invalid one should retry up to ten times with a small delay between attempts using a single PHY address and then repeat using the remaining possible PHY addresses. Do this instead of trying each possible PHY address repeating that up to 100 times. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/phy.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers/net/e1000e/phy.c') diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 0c69649af069..67a718862e70 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -2197,28 +2197,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; } -- cgit v1.2.2 From 0be8401051c716be4533272e983b7eed3d83946d Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 2 Dec 2009 17:03:18 +0000 Subject: e1000e: correct ICH/PCH PHY operations function pointers Some function pointers for a few PHY operations (for 82578 and 82567) and were set incorrectly causing functions to be executed that were accessing incorrect PHY register offsets for that particular device. This patch also moves a few PHY-specific functions from ich8lan.c to the more appropriate phy.c. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/phy.c | 191 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 177 insertions(+), 14 deletions(-) (limited to 'drivers/net/e1000e/phy.c') diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 67a718862e70..55a2c0acfee7 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -1322,17 +1322,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 */ @@ -1342,6 +1347,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; @@ -1370,6 +1378,73 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw) return ret_val; } +/** + * 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 @@ -1557,7 +1632,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; @@ -1582,7 +1657,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; @@ -1619,6 +1694,39 @@ static s32 e1000_check_polarity_igp(struct e1000_hw *hw) return ret_val; } +/** + * 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 @@ -1823,7 +1931,7 @@ s32 e1000e_get_phy_info_m88(struct e1000_hw *hw) u16 phy_data; bool link; - if (hw->phy.media_type != e1000_media_type_copper) { + if (phy->media_type != e1000_media_type_copper) { e_dbg("Phy info is only valid for copper media\n"); return -E1000_ERR_CONFIG; } @@ -1943,6 +2051,61 @@ s32 e1000e_get_phy_info_igp(struct e1000_hw *hw) return ret_val; } +/** + * 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 -- cgit v1.2.2