|
@@ -2136,6 +2136,116 @@ static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw)
|
|
|
return E1000_SUCCESS;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * e1000_check_for_serdes_link_generic - Check for link (Serdes)
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ *
|
|
|
+ * Checks for link up on the hardware. If link is not up and we have
|
|
|
+ * a signal, then we need to force link up.
|
|
|
+ **/
|
|
|
+s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
|
|
|
+{
|
|
|
+ u32 rxcw;
|
|
|
+ u32 ctrl;
|
|
|
+ u32 status;
|
|
|
+ s32 ret_val = E1000_SUCCESS;
|
|
|
+
|
|
|
+ DEBUGFUNC("e1000_check_for_serdes_link_generic");
|
|
|
+
|
|
|
+ ctrl = er32(CTRL);
|
|
|
+ status = er32(STATUS);
|
|
|
+ rxcw = er32(RXCW);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If we don't have link (auto-negotiation failed or link partner
|
|
|
+ * cannot auto-negotiate), and our link partner is not trying to
|
|
|
+ * auto-negotiate with us (we are receiving idles or data),
|
|
|
+ * we need to force link up. We also need to give auto-negotiation
|
|
|
+ * time to complete.
|
|
|
+ */
|
|
|
+ /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
|
|
|
+ if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) {
|
|
|
+ if (hw->autoneg_failed == 0) {
|
|
|
+ hw->autoneg_failed = 1;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
|
|
|
+
|
|
|
+ /* Disable auto-negotiation in the TXCW register */
|
|
|
+ ew32(TXCW, (hw->txcw & ~E1000_TXCW_ANE));
|
|
|
+
|
|
|
+ /* Force link-up and also force full-duplex. */
|
|
|
+ ctrl = er32(CTRL);
|
|
|
+ ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
|
|
|
+ ew32(CTRL, ctrl);
|
|
|
+
|
|
|
+ /* Configure Flow Control after forcing link up. */
|
|
|
+ ret_val = e1000_config_fc_after_link_up(hw);
|
|
|
+ if (ret_val) {
|
|
|
+ DEBUGOUT("Error configuring flow control\n");
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
|
|
|
+ /*
|
|
|
+ * If we are forcing link and we are receiving /C/ ordered
|
|
|
+ * sets, re-enable 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.
|
|
|
+ */
|
|
|
+ DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
|
|
|
+ ew32(TXCW, hw->txcw);
|
|
|
+ ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
|
|
|
+
|
|
|
+ hw->serdes_has_link = true;
|
|
|
+ } else if (!(E1000_TXCW_ANE & er32(TXCW))) {
|
|
|
+ /*
|
|
|
+ * If we force link for non-auto-negotiation switch, check
|
|
|
+ * link status based on MAC synchronization for internal
|
|
|
+ * serdes media type.
|
|
|
+ */
|
|
|
+ /* SYNCH bit and IV bit are sticky. */
|
|
|
+ udelay(10);
|
|
|
+ rxcw = er32(RXCW);
|
|
|
+ if (rxcw & E1000_RXCW_SYNCH) {
|
|
|
+ if (!(rxcw & E1000_RXCW_IV)) {
|
|
|
+ hw->serdes_has_link = true;
|
|
|
+ DEBUGOUT("SERDES: Link up - forced.\n");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ hw->serdes_has_link = false;
|
|
|
+ DEBUGOUT("SERDES: Link down - force failed.\n");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (E1000_TXCW_ANE & er32(TXCW)) {
|
|
|
+ status = er32(STATUS);
|
|
|
+ if (status & E1000_STATUS_LU) {
|
|
|
+ /* SYNCH bit and IV bit are sticky, so reread rxcw. */
|
|
|
+ udelay(10);
|
|
|
+ rxcw = er32(RXCW);
|
|
|
+ if (rxcw & E1000_RXCW_SYNCH) {
|
|
|
+ if (!(rxcw & E1000_RXCW_IV)) {
|
|
|
+ hw->serdes_has_link = true;
|
|
|
+ DEBUGOUT("SERDES: Link up - autoneg "
|
|
|
+ "completed sucessfully.\n");
|
|
|
+ } else {
|
|
|
+ hw->serdes_has_link = false;
|
|
|
+ DEBUGOUT("SERDES: Link down - invalid"
|
|
|
+ "codewords detected in autoneg.\n");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ hw->serdes_has_link = false;
|
|
|
+ DEBUGOUT("SERDES: Link down - no sync.\n");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ hw->serdes_has_link = false;
|
|
|
+ DEBUGOUT("SERDES: Link down - autoneg failed\n");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+out:
|
|
|
+ return ret_val;
|
|
|
+}
|
|
|
/******************************************************************************
|
|
|
* Checks to see if the link status of the hardware has changed.
|
|
|
*
|
|
@@ -2300,74 +2410,11 @@ s32 e1000_check_for_link(struct e1000_hw *hw)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- /* If we don't have link (auto-negotiation failed or link partner cannot
|
|
|
- * auto-negotiate), the cable is plugged in (we have signal), and our
|
|
|
- * link partner is not trying to auto-negotiate with us (we are receiving
|
|
|
- * idles or data), we need to force link up. We also need to give
|
|
|
- * auto-negotiation time to complete, in case the cable was just plugged
|
|
|
- * in. The autoneg_failed flag does this.
|
|
|
- */
|
|
|
- else if ((((hw->media_type == e1000_media_type_fiber) &&
|
|
|
- ((ctrl & E1000_CTRL_SWDPIN1) == signal)) ||
|
|
|
- (hw->media_type == e1000_media_type_internal_serdes)) &&
|
|
|
- (!(status & E1000_STATUS_LU)) &&
|
|
|
- (!(rxcw & E1000_RXCW_C))) {
|
|
|
- if (hw->autoneg_failed == 0) {
|
|
|
- hw->autoneg_failed = 1;
|
|
|
- return 0;
|
|
|
- }
|
|
|
- DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
|
|
|
-
|
|
|
- /* Disable auto-negotiation in the TXCW register */
|
|
|
- ew32(TXCW, (hw->txcw & ~E1000_TXCW_ANE));
|
|
|
|
|
|
- /* Force link-up and also force full-duplex. */
|
|
|
- ctrl = er32(CTRL);
|
|
|
- ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
|
|
|
- ew32(CTRL, ctrl);
|
|
|
-
|
|
|
- /* Configure Flow Control after forcing link up. */
|
|
|
- ret_val = e1000_config_fc_after_link_up(hw);
|
|
|
- if (ret_val) {
|
|
|
- DEBUGOUT("Error configuring flow control\n");
|
|
|
- return ret_val;
|
|
|
- }
|
|
|
- }
|
|
|
- /* If we are forcing link and we are receiving /C/ ordered sets, re-enable
|
|
|
- * 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.
|
|
|
- */
|
|
|
- else if (((hw->media_type == e1000_media_type_fiber) ||
|
|
|
- (hw->media_type == e1000_media_type_internal_serdes)) &&
|
|
|
- (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
|
|
|
- DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
|
|
|
- ew32(TXCW, hw->txcw);
|
|
|
- ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
|
|
|
+ if ((hw->media_type == e1000_media_type_fiber) ||
|
|
|
+ (hw->media_type == e1000_media_type_internal_serdes))
|
|
|
+ e1000_check_for_serdes_link_generic(hw);
|
|
|
|
|
|
- hw->serdes_link_down = false;
|
|
|
- }
|
|
|
- /* If we force link for non-auto-negotiation switch, check link status
|
|
|
- * based on MAC synchronization for internal serdes media type.
|
|
|
- */
|
|
|
- else if ((hw->media_type == e1000_media_type_internal_serdes) &&
|
|
|
- !(E1000_TXCW_ANE & er32(TXCW))) {
|
|
|
- /* SYNCH bit and IV bit are sticky. */
|
|
|
- udelay(10);
|
|
|
- if (E1000_RXCW_SYNCH & er32(RXCW)) {
|
|
|
- if (!(rxcw & E1000_RXCW_IV)) {
|
|
|
- hw->serdes_link_down = false;
|
|
|
- DEBUGOUT("SERDES: Link is up.\n");
|
|
|
- }
|
|
|
- } else {
|
|
|
- hw->serdes_link_down = true;
|
|
|
- DEBUGOUT("SERDES: Link is down.\n");
|
|
|
- }
|
|
|
- }
|
|
|
- if ((hw->media_type == e1000_media_type_internal_serdes) &&
|
|
|
- (E1000_TXCW_ANE & er32(TXCW))) {
|
|
|
- hw->serdes_link_down = !(E1000_STATUS_LU & er32(STATUS));
|
|
|
- }
|
|
|
return E1000_SUCCESS;
|
|
|
}
|
|
|
|