From 3af50481eee6bb278da9050266ff31804e7a57d6 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 16 Jun 2010 13:25:55 +0000 Subject: e1000e: cleanup ethtool loopback setup code Refactor the loopback setup code to first handle the only 10/100 PHY supported by the driver if applicable and then handle the 1Gig PHYs in a switch statement for PHY-specific setups. Signed-off-by: Bruce Allan Tested-by: Emil Tantilov Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/ethtool.c | 74 +++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 32 deletions(-) (limited to 'drivers/net/e1000e/ethtool.c') diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 2c521218102b..86c6a26c0a39 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -1263,33 +1263,36 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) hw->mac.autoneg = 0; - /* Workaround: K1 must be disabled for stable 1Gbps operation */ - if (hw->mac.type == e1000_pchlan) - e1000_configure_k1_ich8lan(hw, false); - - if (hw->phy.type == e1000_phy_m88) { - /* Auto-MDI/MDIX Off */ - e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); - /* reset to update Auto-MDI/MDIX */ - e1e_wphy(hw, PHY_CONTROL, 0x9140); - /* autoneg off */ - e1e_wphy(hw, PHY_CONTROL, 0x8140); - } else if (hw->phy.type == e1000_phy_gg82563) - e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC); - - ctrl_reg = er32(CTRL); - - switch (hw->phy.type) { - case e1000_phy_ife: + if (hw->phy.type == e1000_phy_ife) { /* force 100, set loopback */ e1e_wphy(hw, PHY_CONTROL, 0x6100); /* Now set up the MAC to the same speed/duplex as the PHY. */ + ctrl_reg = er32(CTRL); ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ E1000_CTRL_SPD_100 |/* Force Speed to 100 */ E1000_CTRL_FD); /* Force Duplex to FULL */ + + ew32(CTRL, ctrl_reg); + udelay(500); + + return 0; + } + + /* Specific PHY configuration for loopback */ + switch (hw->phy.type) { + case e1000_phy_m88: + /* Auto-MDI/MDIX Off */ + e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); + /* reset to update Auto-MDI/MDIX */ + e1e_wphy(hw, PHY_CONTROL, 0x9140); + /* autoneg off */ + e1e_wphy(hw, PHY_CONTROL, 0x8140); + break; + case e1000_phy_gg82563: + e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC); break; case e1000_phy_bm: /* Set Default MAC Interface speed to 1GB */ @@ -1312,23 +1315,30 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) /* Set Early Link Enable */ e1e_rphy(hw, PHY_REG(769, 20), &phy_reg); e1e_wphy(hw, PHY_REG(769, 20), phy_reg | 0x0400); - /* fall through */ + break; + case e1000_phy_82577: + case e1000_phy_82578: + /* Workaround: K1 must be disabled for stable 1Gbps operation */ + e1000_configure_k1_ich8lan(hw, false); + break; default: - /* force 1000, set loopback */ - e1e_wphy(hw, PHY_CONTROL, 0x4140); - mdelay(250); + break; + } - /* Now set up the MAC to the same speed/duplex as the PHY. */ - ctrl_reg = er32(CTRL); - ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ - ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ - E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ - E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */ - E1000_CTRL_FD); /* Force Duplex to FULL */ + /* force 1000, set loopback */ + e1e_wphy(hw, PHY_CONTROL, 0x4140); + mdelay(250); - if (adapter->flags & FLAG_IS_ICH) - ctrl_reg |= E1000_CTRL_SLU; /* Set Link Up */ - } + /* Now set up the MAC to the same speed/duplex as the PHY. */ + ctrl_reg = er32(CTRL); + ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ + ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ + E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ + E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */ + E1000_CTRL_FD); /* Force Duplex to FULL */ + + if (adapter->flags & FLAG_IS_ICH) + ctrl_reg |= E1000_CTRL_SLU; /* Set Link Up */ if (hw->phy.media_type == e1000_media_type_copper && hw->phy.type == e1000_phy_m88) { -- cgit v1.2.3 From d3738bb8203acf8552c3ec8b3447133fc0938ddd Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 16 Jun 2010 13:27:28 +0000 Subject: e1000e: initial support for 82579 LOMs Signed-off-by: Bruce Allan Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/ethtool.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/net/e1000e/ethtool.c') diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 86c6a26c0a39..312c704aec34 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -880,6 +880,7 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) switch (mac->type) { case e1000_ich10lan: case e1000_pchlan: + case e1000_pch2lan: mask |= (1 << 18); break; default: @@ -1321,6 +1322,17 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) /* Workaround: K1 must be disabled for stable 1Gbps operation */ e1000_configure_k1_ich8lan(hw, false); break; + case e1000_phy_82579: + /* Disable PHY energy detect power down */ + e1e_rphy(hw, PHY_REG(0, 21), &phy_reg); + e1e_wphy(hw, PHY_REG(0, 21), phy_reg & ~(1 << 3)); + /* Disable full chip energy detect */ + e1e_rphy(hw, PHY_REG(776, 18), &phy_reg); + e1e_wphy(hw, PHY_REG(776, 18), phy_reg | 1); + /* Enable loopback on the PHY */ +#define I82577_PHY_LBK_CTRL 19 + e1e_wphy(hw, I82577_PHY_LBK_CTRL, 0x8001); + break; default: break; } @@ -1878,6 +1890,7 @@ static int e1000_phys_id(struct net_device *netdev, u32 data) if ((hw->phy.type == e1000_phy_ife) || (hw->mac.type == e1000_pchlan) || + (hw->mac.type == e1000_pch2lan) || (hw->mac.type == e1000_82583) || (hw->mac.type == e1000_82574)) { INIT_WORK(&adapter->led_blink_task, e1000e_led_blink_task); -- cgit v1.2.3 From 451152d97f3f4bababcb9c68b22c3d94bcdda67f Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 16 Jun 2010 13:28:11 +0000 Subject: e1000e: update copyright information Signed-off-by: Bruce Allan Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/e1000e/ethtool.c') diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 312c704aec34..db86850b1636 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 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.3 From 0c6bdb3084d015221270b418190b630553a38cf8 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Thu, 17 Jun 2010 18:58:43 +0000 Subject: e1000e: avoid polling h/w registers during link negotiation Avoid touching hardware registers when possible, otherwise link negotiation can get messed up when user-level scripts are rapidly polling the driver to see if/when link is up. Use the saved link state information instead when possible. Signed-off-by: Bruce Allan Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/ethtool.c | 54 +++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 26 deletions(-) (limited to 'drivers/net/e1000e/ethtool.c') diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index db86850b1636..77c5829ab945 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -118,7 +118,6 @@ static int e1000_get_settings(struct net_device *netdev, { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - u32 status; if (hw->phy.media_type == e1000_media_type_copper) { @@ -156,22 +155,29 @@ static int e1000_get_settings(struct net_device *netdev, ecmd->transceiver = XCVR_EXTERNAL; } - status = er32(STATUS); - if (status & E1000_STATUS_LU) { - if (status & E1000_STATUS_SPEED_1000) - ecmd->speed = 1000; - else if (status & E1000_STATUS_SPEED_100) - ecmd->speed = 100; - else - ecmd->speed = 10; + ecmd->speed = -1; + ecmd->duplex = -1; - if (status & E1000_STATUS_FD) - ecmd->duplex = DUPLEX_FULL; - else - ecmd->duplex = DUPLEX_HALF; + if (netif_running(netdev)) { + if (netif_carrier_ok(netdev)) { + ecmd->speed = adapter->link_speed; + ecmd->duplex = adapter->link_duplex - 1; + } } else { - ecmd->speed = -1; - ecmd->duplex = -1; + u32 status = er32(STATUS); + if (status & E1000_STATUS_LU) { + if (status & E1000_STATUS_SPEED_1000) + ecmd->speed = 1000; + else if (status & E1000_STATUS_SPEED_100) + ecmd->speed = 100; + else + ecmd->speed = 10; + + if (status & E1000_STATUS_FD) + ecmd->duplex = DUPLEX_FULL; + else + ecmd->duplex = DUPLEX_HALF; + } } ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) || @@ -179,7 +185,7 @@ static int e1000_get_settings(struct net_device *netdev, /* MDI-X => 2; MDI =>1; Invalid =>0 */ if ((hw->phy.media_type == e1000_media_type_copper) && - !hw->mac.get_link_status) + netif_carrier_ok(netdev)) ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X : ETH_TP_MDI; else @@ -191,19 +197,15 @@ static int e1000_get_settings(struct net_device *netdev, static u32 e1000_get_link(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_mac_info *mac = &adapter->hw.mac; + struct e1000_hw *hw = &adapter->hw; /* - * If the link is not reported up to netdev, interrupts are disabled, - * and so the physical link state may have changed since we last - * looked. Set get_link_status to make sure that the true link - * state is interrogated, rather than pulling a cached and possibly - * stale link state from the driver. + * Avoid touching hardware registers when possible, otherwise + * link negotiation can get messed up when user-level scripts + * are rapidly polling the driver to see if link is up. */ - if (!netif_carrier_ok(netdev)) - mac->get_link_status = 1; - - return e1000e_has_link(adapter); + return netif_running(netdev) ? netif_carrier_ok(netdev) : + !!(er32(STATUS) & E1000_STATUS_LU); } static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) -- cgit v1.2.3 From 52b6dcfe59d73347a598ba0826a6191a1e497679 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sun, 27 Jun 2010 23:26:23 +0000 Subject: e1000e: fail when try to setup unsupported features Signed-off-by: Stanislaw Gruszka Signed-off-by: David S. Miller --- drivers/net/e1000e/ethtool.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/e1000e/ethtool.c') diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 77c5829ab945..6355a1b779d3 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -2051,7 +2051,6 @@ static const struct ethtool_ops e1000_ethtool_ops = { .get_coalesce = e1000_get_coalesce, .set_coalesce = e1000_set_coalesce, .get_flags = ethtool_op_get_flags, - .set_flags = ethtool_op_set_flags, }; void e1000e_set_ethtool_ops(struct net_device *netdev) -- cgit v1.2.3