aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000e
diff options
context:
space:
mode:
authorBruce Allan <bruce.w.allan@intel.com>2010-11-24 01:01:35 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2010-12-11 01:13:14 -0500
commitd9c76f99c2a79feb413e3e751362d59c0f5323f6 (patch)
tree77a7e393c0f7e465d9eb30b440b92d455e33d732 /drivers/net/e1000e
parentcbd006cb7d4e7b76c6febf7f51e970bced132914 (diff)
e1000e: 82571 Serdes can fail to get link
When link partner is sending continuous Config symbols, the 82571 Serdes FIFO can overflow resulting in Invalid bit getting set. To resolve this, if Sync and Config bits are both 1 ignore the Invalid bit and restart auto-negotiation. Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Tested-by: Emil Tantilov <emil.s.tantilov@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/e1000e')
-rw-r--r--drivers/net/e1000e/82571.c35
1 files changed, 27 insertions, 8 deletions
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
index 280d41fc2a2..e57e4097ef1 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/e1000e/82571.c
@@ -52,6 +52,7 @@
52 (ID_LED_DEF1_DEF2)) 52 (ID_LED_DEF1_DEF2))
53 53
54#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000 54#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
55#define AN_RETRY_COUNT 5 /* Autoneg Retry Count value */
55#define E1000_BASE1000T_STATUS 10 56#define E1000_BASE1000T_STATUS 10
56#define E1000_IDLE_ERROR_COUNT_MASK 0xFF 57#define E1000_IDLE_ERROR_COUNT_MASK 0xFF
57#define E1000_RECEIVE_ERROR_COUNTER 21 58#define E1000_RECEIVE_ERROR_COUNTER 21
@@ -1503,6 +1504,8 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
1503 u32 rxcw; 1504 u32 rxcw;
1504 u32 ctrl; 1505 u32 ctrl;
1505 u32 status; 1506 u32 status;
1507 u32 txcw;
1508 u32 i;
1506 s32 ret_val = 0; 1509 s32 ret_val = 0;
1507 1510
1508 ctrl = er32(CTRL); 1511 ctrl = er32(CTRL);
@@ -1613,16 +1616,32 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
1613 e_dbg("ANYSTATE -> DOWN\n"); 1616 e_dbg("ANYSTATE -> DOWN\n");
1614 } else { 1617 } else {
1615 /* 1618 /*
1616 * We have sync, and can tolerate one invalid (IV) 1619 * Check several times, if Sync and Config
1617 * codeword before declaring link down, so reread 1620 * both are consistently 1 then simply ignore
1618 * to look again. 1621 * the Invalid bit and restart Autoneg
1619 */ 1622 */
1620 udelay(10); 1623 for (i = 0; i < AN_RETRY_COUNT; i++) {
1621 rxcw = er32(RXCW); 1624 udelay(10);
1622 if (rxcw & E1000_RXCW_IV) { 1625 rxcw = er32(RXCW);
1623 mac->serdes_link_state = e1000_serdes_link_down; 1626 if ((rxcw & E1000_RXCW_IV) &&
1627 !((rxcw & E1000_RXCW_SYNCH) &&
1628 (rxcw & E1000_RXCW_C))) {
1629 mac->serdes_has_link = false;
1630 mac->serdes_link_state =
1631 e1000_serdes_link_down;
1632 e_dbg("ANYSTATE -> DOWN\n");
1633 break;
1634 }
1635 }
1636
1637 if (i == AN_RETRY_COUNT) {
1638 txcw = er32(TXCW);
1639 txcw |= E1000_TXCW_ANE;
1640 ew32(TXCW, txcw);
1641 mac->serdes_link_state =
1642 e1000_serdes_link_autoneg_progress;
1624 mac->serdes_has_link = false; 1643 mac->serdes_has_link = false;
1625 e_dbg("ANYSTATE -> DOWN\n"); 1644 e_dbg("ANYSTATE -> AN_PROG\n");
1626 } 1645 }
1627 } 1646 }
1628 } 1647 }