]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/net/e1000e/82571.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / net / e1000e / 82571.c
index 7236f1a53ba0997da7ba66a218db4b56091faedf..89a69035e538f2ef024e2c6e747a1b762744a118 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -52,6 +52,7 @@
                              (ID_LED_DEF1_DEF2))
 
 #define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
+#define AN_RETRY_COUNT          5 /* Autoneg Retry Count value */
 #define E1000_BASE1000T_STATUS          10
 #define E1000_IDLE_ERROR_COUNT_MASK     0xFF
 #define E1000_RECEIVE_ERROR_COUNTER     21
@@ -74,6 +75,11 @@ 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);
+static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active);
+static s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active);
 
 /**
  *  e1000_init_phy_params_82571 - Init PHY func ptrs.
@@ -107,6 +113,10 @@ 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;
+               phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82574;
+               phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82574;
                break;
        default:
                return -E1000_ERR_PHY;
@@ -115,29 +125,36 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
 
        /* This can only be done after all function pointers are setup. */
        ret_val = e1000_get_phy_id_82571(hw);
+       if (ret_val) {
+               e_dbg("Error getting PHY ID\n");
+               return ret_val;
+       }
 
        /* Verify phy id */
        switch (hw->mac.type) {
        case e1000_82571:
        case e1000_82572:
                if (phy->id != IGP01E1000_I_PHY_ID)
-                       return -E1000_ERR_PHY;
+                       ret_val = -E1000_ERR_PHY;
                break;
        case e1000_82573:
                if (phy->id != M88E1111_I_PHY_ID)
-                       return -E1000_ERR_PHY;
+                       ret_val = -E1000_ERR_PHY;
                break;
        case e1000_82574:
        case e1000_82583:
                if (phy->id != BME1000_E_PHY_ID_R2)
-                       return -E1000_ERR_PHY;
+                       ret_val = -E1000_ERR_PHY;
                break;
        default:
-               return -E1000_ERR_PHY;
+               ret_val = -E1000_ERR_PHY;
                break;
        }
 
-       return 0;
+       if (ret_val)
+               e_dbg("PHY ID unknown: type = 0x%08x\n", phy->id);
+
+       return ret_val;
 }
 
 /**
@@ -200,6 +217,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;
 }
 
@@ -300,7 +328,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
 
        /*
         * Ensure that the inter-port SWSM.SMBI lock bit is clear before
-        * first NVM or PHY acess. This should be done for single-port
+        * first NVM or PHY access. This should be done for single-port
         * devices, and for one port only on dual-port devices so that
         * for those devices we can still use the SMBI lock to synchronize
         * inter-port accesses to the PHY & NVM.
@@ -542,6 +570,146 @@ 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_set_d0_lplu_state_82574 - Set Low Power Linkup D0 state
+ *  @hw: pointer to the HW structure
+ *  @active: true to enable LPLU, false to disable
+ *
+ *  Sets the LPLU D0 state according to the active flag.
+ *  LPLU will not be activated unless the
+ *  device autonegotiation advertisement meets standards of
+ *  either 10 or 10/100 or 10/100/1000 at all duplexes.
+ *  This is a function pointer entry point only called by
+ *  PHY setup routines.
+ **/
+static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active)
+{
+       u16 data = er32(POEMB);
+
+       if (active)
+               data |= E1000_PHY_CTRL_D0A_LPLU;
+       else
+               data &= ~E1000_PHY_CTRL_D0A_LPLU;
+
+       ew32(POEMB, data);
+       return 0;
+}
+
+/**
+ *  e1000_set_d3_lplu_state_82574 - Sets low power link up state for D3
+ *  @hw: pointer to the HW structure
+ *  @active: boolean used to enable/disable lplu
+ *
+ *  The low power link up (lplu) state is set to the power management level D3
+ *  when active is true, else clear lplu for D3. LPLU
+ *  is used during Dx states where the power conservation is most important.
+ *  During driver activity, SmartSpeed should be enabled so performance is
+ *  maintained.
+ **/
+static s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active)
+{
+       u16 data = er32(POEMB);
+
+       if (!active) {
+               data &= ~E1000_PHY_CTRL_NOND0A_LPLU;
+       } else if ((hw->phy.autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
+                  (hw->phy.autoneg_advertised == E1000_ALL_NOT_GIG) ||
+                  (hw->phy.autoneg_advertised == E1000_ALL_10_SPEED)) {
+               data |= E1000_PHY_CTRL_NOND0A_LPLU;
+       }
+
+       ew32(POEMB, data);
+       return 0;
+}
 
 /**
  *  e1000_acquire_nvm_82571 - Request for access to the EEPROM
@@ -562,8 +730,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 +1019,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;
        s32 ret_val;
-       u16 i = 0;
 
        /*
         * Prevent the PCI-E bus from sticking if there is no TLP connection
@@ -880,33 +1045,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);
@@ -938,7 +1103,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
 
        /* Clear any pending interrupt events. */
        ew32(IMC, 0xffffffff);
-       icr = er32(ICR);
+       er32(ICR);
 
        if (hw->mac.type == e1000_82571) {
                /* Install any alternate MAC address into RAR0 */
@@ -1145,7 +1310,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
                 * apply workaround for hardware errata documented in errata
                 * docs Fixes issue where some error prone or unreliable PCIe
                 * completions are occurring, particularly with ASPM enabled.
-                * Without fix, issue can cause tx timeouts.
+                * Without fix, issue can cause Tx timeouts.
                 */
                reg = er32(GCR2);
                reg |= 1;
@@ -1402,6 +1567,8 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
        u32 rxcw;
        u32 ctrl;
        u32 status;
+       u32 txcw;
+       u32 i;
        s32 ret_val = 0;
 
        ctrl = er32(CTRL);
@@ -1422,8 +1589,10 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
                                    e1000_serdes_link_autoneg_progress;
                                mac->serdes_has_link = false;
                                e_dbg("AN_UP     -> AN_PROG\n");
+                       } else {
+                               mac->serdes_has_link = true;
                        }
-               break;
+                       break;
 
                case e1000_serdes_link_forced_up:
                        /*
@@ -1431,8 +1600,10 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
                         * auto-negotiation in the TXCW register and disable
                         * forced link in the Device Control register in an
                         * attempt to auto-negotiate with our link partner.
+                        * If the partner code word is null, stop forcing
+                        * and restart auto negotiation.
                         */
-                       if (rxcw & E1000_RXCW_C) {
+                       if ((rxcw & E1000_RXCW_C) || !(rxcw & E1000_RXCW_CW))  {
                                /* Enable autoneg, and unforce link up */
                                ew32(TXCW, mac->txcw);
                                ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
@@ -1440,6 +1611,8 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
                                    e1000_serdes_link_autoneg_progress;
                                mac->serdes_has_link = false;
                                e_dbg("FORCED_UP -> AN_PROG\n");
+                       } else {
+                               mac->serdes_has_link = true;
                        }
                        break;
 
@@ -1495,6 +1668,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
                        ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
                        mac->serdes_link_state =
                            e1000_serdes_link_autoneg_progress;
+                       mac->serdes_has_link = false;
                        e_dbg("DOWN      -> AN_PROG\n");
                        break;
                }
@@ -1505,16 +1679,32 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
                        e_dbg("ANYSTATE  -> DOWN\n");
                } else {
                        /*
-                        * We have sync, and can tolerate one invalid (IV)
-                        * codeword before declaring link down, so reread
-                        * to look again.
+                        * Check several times, if Sync and Config
+                        * both are consistently 1 then simply ignore
+                        * the Invalid bit and restart Autoneg
                         */
-                       udelay(10);
-                       rxcw = er32(RXCW);
-                       if (rxcw & E1000_RXCW_IV) {
-                               mac->serdes_link_state = e1000_serdes_link_down;
+                       for (i = 0; i < AN_RETRY_COUNT; i++) {
+                               udelay(10);
+                               rxcw = er32(RXCW);
+                               if ((rxcw & E1000_RXCW_IV) &&
+                                   !((rxcw & E1000_RXCW_SYNCH) &&
+                                     (rxcw & E1000_RXCW_C))) {
+                                       mac->serdes_has_link = false;
+                                       mac->serdes_link_state =
+                                           e1000_serdes_link_down;
+                                       e_dbg("ANYSTATE  -> DOWN\n");
+                                       break;
+                               }
+                       }
+
+                       if (i == AN_RETRY_COUNT) {
+                               txcw = er32(TXCW);
+                               txcw |= E1000_TXCW_ANE;
+                               ew32(TXCW, txcw);
+                               mac->serdes_link_state =
+                                   e1000_serdes_link_autoneg_progress;
                                mac->serdes_has_link = false;
-                               e_dbg("ANYSTATE  -> DOWN\n");
+                               e_dbg("ANYSTATE  -> AN_PROG\n");
                        }
                }
        }
@@ -1897,7 +2087,7 @@ struct e1000_info e1000_82574_info = {
                                  | FLAG_HAS_AMT
                                  | FLAG_HAS_CTRLEXT_ON_LOAD,
        .flags2                   = FLAG2_CHECK_PHY_HANG,
-       .pba                    = 36,
+       .pba                    = 32,
        .max_hw_frame_size      = DEFAULT_JUMBO,
        .get_variants           = e1000_get_variants_82571,
        .mac_ops                = &e82571_mac_ops,
@@ -1914,7 +2104,7 @@ struct e1000_info e1000_82583_info = {
                                  | FLAG_HAS_SMART_POWER_DOWN
                                  | FLAG_HAS_AMT
                                  | FLAG_HAS_CTRLEXT_ON_LOAD,
-       .pba                    = 36,
+       .pba                    = 32,
        .max_hw_frame_size      = ETH_FRAME_LEN + ETH_FCS_LEN,
        .get_variants           = e1000_get_variants_82571,
        .mac_ops                = &e82571_mac_ops,