e1000e: fix unit hang during loopback test
[pandora-kernel.git] / drivers / net / ethernet / intel / e1000e / ethtool.c
index 11f486e..c62f0db 100644 (file)
@@ -1516,8 +1516,19 @@ static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter)
 static int e1000_setup_loopback_test(struct e1000_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
-       u32 rctl;
-
+       u32 rctl, fext_nvm11, tarc0;
+
+       if (hw->mac.type == e1000_pch_spt) {
+               fext_nvm11 = er32(FEXTNVM11);
+               fext_nvm11 |= E1000_FEXTNVM11_DISABLE_MULR_FIX;
+               ew32(FEXTNVM11, fext_nvm11);
+               tarc0 = er32(TARC(0));
+               /* clear bits 28 & 29 (control of MULR concurrent requests) */
+               tarc0 &= 0xcfffffff;
+               /* set bit 29 (value of MULR requests is now 2) */
+               tarc0 |= 0x20000000;
+               ew32(TARC(0), tarc0);
+       }
        if (hw->phy.media_type == e1000_media_type_fiber ||
            hw->phy.media_type == e1000_media_type_internal_serdes) {
                switch (hw->mac.type) {
@@ -1542,7 +1553,7 @@ static int e1000_setup_loopback_test(struct e1000_adapter *adapter)
 static void e1000_loopback_cleanup(struct e1000_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
-       u32 rctl;
+       u32 rctl, fext_nvm11, tarc0;
        u16 phy_reg;
 
        rctl = er32(RCTL);
@@ -1550,6 +1561,16 @@ static void e1000_loopback_cleanup(struct e1000_adapter *adapter)
        ew32(RCTL, rctl);
 
        switch (hw->mac.type) {
+       case e1000_pch_spt:
+               fext_nvm11 = er32(FEXTNVM11);
+               fext_nvm11 &= ~E1000_FEXTNVM11_DISABLE_MULR_FIX;
+               ew32(FEXTNVM11, fext_nvm11);
+               tarc0 = er32(TARC(0));
+               /* clear bits 28 & 29 (control of MULR concurrent requests) */
+               /* set bit 29 (value of MULR requests is now 0) */
+               tarc0 &= 0xcfffffff;
+               ew32(TARC(0), tarc0);
+               /* fall through */
        case e1000_80003es2lan:
                if (hw->phy.media_type == e1000_media_type_fiber ||
                    hw->phy.media_type == e1000_media_type_internal_serdes) {