]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/net/e1000e/82571.c
e1000e: 82574 intermittently fails to initialize with manageability f/w
[net-next-2.6.git] / drivers / net / e1000e / 82571.c
index 235856375ff3f825acefb11b3a56ad208b2132d8..9333921010cc23c7eff6d4a54ee30cbc3dc3fdbf 100644 (file)
@@ -74,6 +74,9 @@ static bool e1000_check_mng_mode_82574(struct e1000_hw *hw);
 static s32 e1000_led_on_82574(struct e1000_hw *hw);
 static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw);
 static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw);
+static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw);
+static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw);
+static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw);
 
 /**
  *  e1000_init_phy_params_82571 - Init PHY func ptrs.
@@ -107,6 +110,8 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
        case e1000_82574:
        case e1000_82583:
                phy->type                = e1000_phy_bm;
+               phy->ops.acquire = e1000_get_hw_semaphore_82574;
+               phy->ops.release = e1000_put_hw_semaphore_82574;
                break;
        default:
                return -E1000_ERR_PHY;
@@ -200,6 +205,17 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
                break;
        }
 
+       /* Function Pointers */
+       switch (hw->mac.type) {
+       case e1000_82574:
+       case e1000_82583:
+               nvm->ops.acquire = e1000_get_hw_semaphore_82574;
+               nvm->ops.release = e1000_put_hw_semaphore_82574;
+               break;
+       default:
+               break;
+       }
+
        return 0;
 }
 
@@ -542,6 +558,94 @@ static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw)
        swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
        ew32(SWSM, swsm);
 }
+/**
+ *  e1000_get_hw_semaphore_82573 - Acquire hardware semaphore
+ *  @hw: pointer to the HW structure
+ *
+ *  Acquire the HW semaphore during reset.
+ *
+ **/
+static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw)
+{
+       u32 extcnf_ctrl;
+       s32 ret_val = 0;
+       s32 i = 0;
+
+       extcnf_ctrl = er32(EXTCNF_CTRL);
+       extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
+       do {
+               ew32(EXTCNF_CTRL, extcnf_ctrl);
+               extcnf_ctrl = er32(EXTCNF_CTRL);
+
+               if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP)
+                       break;
+
+               extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
+
+               msleep(2);
+               i++;
+       } while (i < MDIO_OWNERSHIP_TIMEOUT);
+
+       if (i == MDIO_OWNERSHIP_TIMEOUT) {
+               /* Release semaphores */
+               e1000_put_hw_semaphore_82573(hw);
+               e_dbg("Driver can't access the PHY\n");
+               ret_val = -E1000_ERR_PHY;
+               goto out;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_put_hw_semaphore_82573 - Release hardware semaphore
+ *  @hw: pointer to the HW structure
+ *
+ *  Release hardware semaphore used during reset.
+ *
+ **/
+static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw)
+{
+       u32 extcnf_ctrl;
+
+       extcnf_ctrl = er32(EXTCNF_CTRL);
+       extcnf_ctrl &= ~E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
+       ew32(EXTCNF_CTRL, extcnf_ctrl);
+}
+
+static DEFINE_MUTEX(swflag_mutex);
+
+/**
+ *  e1000_get_hw_semaphore_82574 - Acquire hardware semaphore
+ *  @hw: pointer to the HW structure
+ *
+ *  Acquire the HW semaphore to access the PHY or NVM.
+ *
+ **/
+static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw)
+{
+       s32 ret_val;
+
+       mutex_lock(&swflag_mutex);
+       ret_val = e1000_get_hw_semaphore_82573(hw);
+       if (ret_val)
+               mutex_unlock(&swflag_mutex);
+       return ret_val;
+}
+
+/**
+ *  e1000_put_hw_semaphore_82574 - Release hardware semaphore
+ *  @hw: pointer to the HW structure
+ *
+ *  Release hardware semaphore used to access the PHY or NVM
+ *
+ **/
+static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw)
+{
+       e1000_put_hw_semaphore_82573(hw);
+       mutex_unlock(&swflag_mutex);
+}
 
 /**
  *  e1000_acquire_nvm_82571 - Request for access to the EEPROM
@@ -562,8 +666,6 @@ static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw)
 
        switch (hw->mac.type) {
        case e1000_82573:
-       case e1000_82574:
-       case e1000_82583:
                break;
        default:
                ret_val = e1000e_acquire_nvm(hw);
@@ -853,9 +955,8 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active)
  **/
 static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
 {
-       u32 ctrl, extcnf_ctrl, ctrl_ext, icr;
+       u32 ctrl, ctrl_ext, icr;
        s32 ret_val;
-       u16 i = 0;
 
        /*
         * Prevent the PCI-E bus from sticking if there is no TLP connection
@@ -880,33 +981,33 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
         */
        switch (hw->mac.type) {
        case e1000_82573:
+               ret_val = e1000_get_hw_semaphore_82573(hw);
+               break;
        case e1000_82574:
        case e1000_82583:
-               extcnf_ctrl = er32(EXTCNF_CTRL);
-               extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
-
-               do {
-                       ew32(EXTCNF_CTRL, extcnf_ctrl);
-                       extcnf_ctrl = er32(EXTCNF_CTRL);
-
-                       if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP)
-                               break;
-
-                       extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
-
-                       msleep(2);
-                       i++;
-               } while (i < MDIO_OWNERSHIP_TIMEOUT);
+               ret_val = e1000_get_hw_semaphore_82574(hw);
                break;
        default:
                break;
        }
+       if (ret_val)
+               e_dbg("Cannot acquire MDIO ownership\n");
 
        ctrl = er32(CTRL);
 
        e_dbg("Issuing a global reset to MAC\n");
        ew32(CTRL, ctrl | E1000_CTRL_RST);
 
+       /* Must release MDIO ownership and mutex after MAC reset. */
+       switch (hw->mac.type) {
+       case e1000_82574:
+       case e1000_82583:
+               e1000_put_hw_semaphore_82574(hw);
+               break;
+       default:
+               break;
+       }
+
        if (hw->nvm.type == e1000_nvm_flash_hw) {
                udelay(10);
                ctrl_ext = er32(CTRL_EXT);