[PATCH] e1000: Fix loopback logic
authorJeff Kirsher <jeffrey.t.kirsher@intel.com>
Fri, 13 Jan 2006 00:50:44 +0000 (16:50 -0800)
committerJeff Garzik <jgarzik@pobox.com>
Tue, 17 Jan 2006 12:44:49 +0000 (07:44 -0500)
Fixed the loopback logic to work for the PCI express adapters.

Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: John Ronciak <john.ronciak@intel.com>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
drivers/net/e1000/e1000_ethtool.c

index ffdf76b725bc7c0ce7db0b123957c21989674aaf..ceb9cd059b901f158e13359877e33dade642b58c 100644 (file)
@@ -1326,22 +1326,33 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
 static int
 e1000_setup_loopback_test(struct e1000_adapter *adapter)
 {
+       struct e1000_hw *hw = &adapter->hw;
        uint32_t rctl;
 
-       if(adapter->hw.media_type == e1000_media_type_fiber ||
-          adapter->hw.media_type == e1000_media_type_internal_serdes) {
-               if(adapter->hw.mac_type == e1000_82545 ||
-                  adapter->hw.mac_type == e1000_82546 ||
-                  adapter->hw.mac_type == e1000_82545_rev_3 ||
-                  adapter->hw.mac_type == e1000_82546_rev_3)
+       if (hw->media_type == e1000_media_type_fiber ||
+           hw->media_type == e1000_media_type_internal_serdes) {
+               switch (hw->mac_type) {
+               case e1000_82545:
+               case e1000_82546:
+               case e1000_82545_rev_3:
+               case e1000_82546_rev_3:
                        return e1000_set_phy_loopback(adapter);
-               else {
-                       rctl = E1000_READ_REG(&adapter->hw, RCTL);
+                       break;
+               case e1000_82571:
+               case e1000_82572:
+#define E1000_SERDES_LB_ON 0x410
+                       e1000_set_phy_loopback(adapter);
+                       E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_ON);
+                       msec_delay(10);
+                       return 0;
+                       break;
+               default:
+                       rctl = E1000_READ_REG(hw, RCTL);
                        rctl |= E1000_RCTL_LBM_TCVR;
-                       E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+                       E1000_WRITE_REG(hw, RCTL, rctl);
                        return 0;
                }
-       } else if(adapter->hw.media_type == e1000_media_type_copper)
+       } else if (hw->media_type == e1000_media_type_copper)
                return e1000_set_phy_loopback(adapter);
 
        return 7;
@@ -1350,27 +1361,38 @@ e1000_setup_loopback_test(struct e1000_adapter *adapter)
 static void
 e1000_loopback_cleanup(struct e1000_adapter *adapter)
 {
+       struct e1000_hw *hw = &adapter->hw;
        uint32_t rctl;
        uint16_t phy_reg;
 
-       rctl = E1000_READ_REG(&adapter->hw, RCTL);
+       rctl = E1000_READ_REG(hw, RCTL);
        rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
-       E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+       E1000_WRITE_REG(hw, RCTL, rctl);
 
-       if(adapter->hw.media_type == e1000_media_type_copper ||
-          ((adapter->hw.media_type == e1000_media_type_fiber ||
-            adapter->hw.media_type == e1000_media_type_internal_serdes) &&
-           (adapter->hw.mac_type == e1000_82545 ||
-            adapter->hw.mac_type == e1000_82546 ||
-            adapter->hw.mac_type == e1000_82545_rev_3 ||
-            adapter->hw.mac_type == e1000_82546_rev_3))) {
-               adapter->hw.autoneg = TRUE;
-               e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
-               if(phy_reg & MII_CR_LOOPBACK) {
+       switch (hw->mac_type) {
+       case e1000_82571:
+       case e1000_82572:
+               if (hw->media_type == e1000_media_type_fiber ||
+                   hw->media_type == e1000_media_type_internal_serdes) {
+#define E1000_SERDES_LB_OFF 0x400
+                       E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_OFF);
+                       msec_delay(10);
+                       break;
+               }
+               /* Fall Through */
+       case e1000_82545:
+       case e1000_82546:
+       case e1000_82545_rev_3:
+       case e1000_82546_rev_3:
+       default:
+               hw->autoneg = TRUE;
+               e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
+               if (phy_reg & MII_CR_LOOPBACK) {
                        phy_reg &= ~MII_CR_LOOPBACK;
-                       e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
-                       e1000_phy_reset(&adapter->hw);
+                       e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
+                       e1000_phy_reset(hw);
                }
+               break;
        }
 }