aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000/e1000_hw.c
diff options
context:
space:
mode:
authorJesse Brandeburg <jesse.brandeburg@intel.com>2009-09-25 08:17:44 -0400
committerDavid S. Miller <davem@davemloft.net>2009-09-26 23:15:36 -0400
commitbe0f071956e2142e2e88e9d6d5655ba1c75d07c8 (patch)
treee0b1be3f259841aaabcfbb02c4495dd2580d0130 /drivers/net/e1000/e1000_hw.c
parentbaa34745fe6263c733f43feddb0b8100d6538f37 (diff)
e1000: test link state conclusively
e1000 was using one particular way to detect link, but with the advent of some of the newer hardware designs using SERDES connections, tests for link must completely cover all cases. Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com> Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/e1000/e1000_hw.c')
-rw-r--r--drivers/net/e1000/e1000_hw.c179
1 files changed, 113 insertions, 66 deletions
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 765fd71ad5f2..076db19f69f4 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -2136,6 +2136,116 @@ static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw)
2136 return E1000_SUCCESS; 2136 return E1000_SUCCESS;
2137} 2137}
2138 2138
2139/**
2140 * e1000_check_for_serdes_link_generic - Check for link (Serdes)
2141 * @hw: pointer to the HW structure
2142 *
2143 * Checks for link up on the hardware. If link is not up and we have
2144 * a signal, then we need to force link up.
2145 **/
2146s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
2147{
2148 u32 rxcw;
2149 u32 ctrl;
2150 u32 status;
2151 s32 ret_val = E1000_SUCCESS;
2152
2153 DEBUGFUNC("e1000_check_for_serdes_link_generic");
2154
2155 ctrl = er32(CTRL);
2156 status = er32(STATUS);
2157 rxcw = er32(RXCW);
2158
2159 /*
2160 * If we don't have link (auto-negotiation failed or link partner
2161 * cannot auto-negotiate), and our link partner is not trying to
2162 * auto-negotiate with us (we are receiving idles or data),
2163 * we need to force link up. We also need to give auto-negotiation
2164 * time to complete.
2165 */
2166 /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
2167 if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) {
2168 if (hw->autoneg_failed == 0) {
2169 hw->autoneg_failed = 1;
2170 goto out;
2171 }
2172 DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
2173
2174 /* Disable auto-negotiation in the TXCW register */
2175 ew32(TXCW, (hw->txcw & ~E1000_TXCW_ANE));
2176
2177 /* Force link-up and also force full-duplex. */
2178 ctrl = er32(CTRL);
2179 ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
2180 ew32(CTRL, ctrl);
2181
2182 /* Configure Flow Control after forcing link up. */
2183 ret_val = e1000_config_fc_after_link_up(hw);
2184 if (ret_val) {
2185 DEBUGOUT("Error configuring flow control\n");
2186 goto out;
2187 }
2188 } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
2189 /*
2190 * If we are forcing link and we are receiving /C/ ordered
2191 * sets, re-enable auto-negotiation in the TXCW register
2192 * and disable forced link in the Device Control register
2193 * in an attempt to auto-negotiate with our link partner.
2194 */
2195 DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
2196 ew32(TXCW, hw->txcw);
2197 ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
2198
2199 hw->serdes_has_link = true;
2200 } else if (!(E1000_TXCW_ANE & er32(TXCW))) {
2201 /*
2202 * If we force link for non-auto-negotiation switch, check
2203 * link status based on MAC synchronization for internal
2204 * serdes media type.
2205 */
2206 /* SYNCH bit and IV bit are sticky. */
2207 udelay(10);
2208 rxcw = er32(RXCW);
2209 if (rxcw & E1000_RXCW_SYNCH) {
2210 if (!(rxcw & E1000_RXCW_IV)) {
2211 hw->serdes_has_link = true;
2212 DEBUGOUT("SERDES: Link up - forced.\n");
2213 }
2214 } else {
2215 hw->serdes_has_link = false;
2216 DEBUGOUT("SERDES: Link down - force failed.\n");
2217 }
2218 }
2219
2220 if (E1000_TXCW_ANE & er32(TXCW)) {
2221 status = er32(STATUS);
2222 if (status & E1000_STATUS_LU) {
2223 /* SYNCH bit and IV bit are sticky, so reread rxcw. */
2224 udelay(10);
2225 rxcw = er32(RXCW);
2226 if (rxcw & E1000_RXCW_SYNCH) {
2227 if (!(rxcw & E1000_RXCW_IV)) {
2228 hw->serdes_has_link = true;
2229 DEBUGOUT("SERDES: Link up - autoneg "
2230 "completed sucessfully.\n");
2231 } else {
2232 hw->serdes_has_link = false;
2233 DEBUGOUT("SERDES: Link down - invalid"
2234 "codewords detected in autoneg.\n");
2235 }
2236 } else {
2237 hw->serdes_has_link = false;
2238 DEBUGOUT("SERDES: Link down - no sync.\n");
2239 }
2240 } else {
2241 hw->serdes_has_link = false;
2242 DEBUGOUT("SERDES: Link down - autoneg failed\n");
2243 }
2244 }
2245
2246out:
2247 return ret_val;
2248}
2139/****************************************************************************** 2249/******************************************************************************
2140 * Checks to see if the link status of the hardware has changed. 2250 * Checks to see if the link status of the hardware has changed.
2141 * 2251 *
@@ -2300,74 +2410,11 @@ s32 e1000_check_for_link(struct e1000_hw *hw)
2300 } 2410 }
2301 } 2411 }
2302 } 2412 }
2303 /* If we don't have link (auto-negotiation failed or link partner cannot
2304 * auto-negotiate), the cable is plugged in (we have signal), and our
2305 * link partner is not trying to auto-negotiate with us (we are receiving
2306 * idles or data), we need to force link up. We also need to give
2307 * auto-negotiation time to complete, in case the cable was just plugged
2308 * in. The autoneg_failed flag does this.
2309 */
2310 else if ((((hw->media_type == e1000_media_type_fiber) &&
2311 ((ctrl & E1000_CTRL_SWDPIN1) == signal)) ||
2312 (hw->media_type == e1000_media_type_internal_serdes)) &&
2313 (!(status & E1000_STATUS_LU)) &&
2314 (!(rxcw & E1000_RXCW_C))) {
2315 if (hw->autoneg_failed == 0) {
2316 hw->autoneg_failed = 1;
2317 return 0;
2318 }
2319 DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
2320
2321 /* Disable auto-negotiation in the TXCW register */
2322 ew32(TXCW, (hw->txcw & ~E1000_TXCW_ANE));
2323 2413
2324 /* Force link-up and also force full-duplex. */ 2414 if ((hw->media_type == e1000_media_type_fiber) ||
2325 ctrl = er32(CTRL); 2415 (hw->media_type == e1000_media_type_internal_serdes))
2326 ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); 2416 e1000_check_for_serdes_link_generic(hw);
2327 ew32(CTRL, ctrl);
2328
2329 /* Configure Flow Control after forcing link up. */
2330 ret_val = e1000_config_fc_after_link_up(hw);
2331 if (ret_val) {
2332 DEBUGOUT("Error configuring flow control\n");
2333 return ret_val;
2334 }
2335 }
2336 /* If we are forcing link and we are receiving /C/ ordered sets, re-enable
2337 * auto-negotiation in the TXCW register and disable forced link in the
2338 * Device Control register in an attempt to auto-negotiate with our link
2339 * partner.
2340 */
2341 else if (((hw->media_type == e1000_media_type_fiber) ||
2342 (hw->media_type == e1000_media_type_internal_serdes)) &&
2343 (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
2344 DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
2345 ew32(TXCW, hw->txcw);
2346 ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
2347 2417
2348 hw->serdes_link_down = false;
2349 }
2350 /* If we force link for non-auto-negotiation switch, check link status
2351 * based on MAC synchronization for internal serdes media type.
2352 */
2353 else if ((hw->media_type == e1000_media_type_internal_serdes) &&
2354 !(E1000_TXCW_ANE & er32(TXCW))) {
2355 /* SYNCH bit and IV bit are sticky. */
2356 udelay(10);
2357 if (E1000_RXCW_SYNCH & er32(RXCW)) {
2358 if (!(rxcw & E1000_RXCW_IV)) {
2359 hw->serdes_link_down = false;
2360 DEBUGOUT("SERDES: Link is up.\n");
2361 }
2362 } else {
2363 hw->serdes_link_down = true;
2364 DEBUGOUT("SERDES: Link is down.\n");
2365 }
2366 }
2367 if ((hw->media_type == e1000_media_type_internal_serdes) &&
2368 (E1000_TXCW_ANE & er32(TXCW))) {
2369 hw->serdes_link_down = !(E1000_STATUS_LU & er32(STATUS));
2370 }
2371 return E1000_SUCCESS; 2418 return E1000_SUCCESS;
2372} 2419}
2373 2420