diff options
Diffstat (limited to 'drivers/net/sfc/falcon_xmac.c')
-rw-r--r-- | drivers/net/sfc/falcon_xmac.c | 92 |
1 files changed, 81 insertions, 11 deletions
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c index aa7521b24a5d..55c0d9760be8 100644 --- a/drivers/net/sfc/falcon_xmac.c +++ b/drivers/net/sfc/falcon_xmac.c | |||
@@ -32,7 +32,7 @@ | |||
32 | (FALCON_XMAC_REGBANK + ((mac_reg) * FALCON_XMAC_REG_SIZE)) | 32 | (FALCON_XMAC_REGBANK + ((mac_reg) * FALCON_XMAC_REG_SIZE)) |
33 | 33 | ||
34 | void falcon_xmac_writel(struct efx_nic *efx, | 34 | void falcon_xmac_writel(struct efx_nic *efx, |
35 | efx_dword_t *value, unsigned int mac_reg) | 35 | efx_dword_t *value, unsigned int mac_reg) |
36 | { | 36 | { |
37 | efx_oword_t temp; | 37 | efx_oword_t temp; |
38 | 38 | ||
@@ -69,6 +69,10 @@ static int falcon_reset_xmac(struct efx_nic *efx) | |||
69 | udelay(10); | 69 | udelay(10); |
70 | } | 70 | } |
71 | 71 | ||
72 | /* This often fails when DSP is disabled, ignore it */ | ||
73 | if (sfe4001_phy_flash_cfg != 0) | ||
74 | return 0; | ||
75 | |||
72 | EFX_ERR(efx, "timed out waiting for XMAC core reset\n"); | 76 | EFX_ERR(efx, "timed out waiting for XMAC core reset\n"); |
73 | return -ETIMEDOUT; | 77 | return -ETIMEDOUT; |
74 | } | 78 | } |
@@ -217,13 +221,13 @@ static int falcon_xgmii_status(struct efx_nic *efx) | |||
217 | { | 221 | { |
218 | efx_dword_t reg; | 222 | efx_dword_t reg; |
219 | 223 | ||
220 | if (FALCON_REV(efx) < FALCON_REV_B0) | 224 | if (falcon_rev(efx) < FALCON_REV_B0) |
221 | return 1; | 225 | return 1; |
222 | 226 | ||
223 | /* The ISR latches, so clear it and re-read */ | 227 | /* The ISR latches, so clear it and re-read */ |
224 | falcon_xmac_readl(efx, ®, XM_MGT_INT_REG_MAC_B0); | 228 | falcon_xmac_readl(efx, ®, XM_MGT_INT_REG_MAC_B0); |
225 | falcon_xmac_readl(efx, ®, XM_MGT_INT_REG_MAC_B0); | 229 | falcon_xmac_readl(efx, ®, XM_MGT_INT_REG_MAC_B0); |
226 | 230 | ||
227 | if (EFX_DWORD_FIELD(reg, XM_LCLFLT) || | 231 | if (EFX_DWORD_FIELD(reg, XM_LCLFLT) || |
228 | EFX_DWORD_FIELD(reg, XM_RMTFLT)) { | 232 | EFX_DWORD_FIELD(reg, XM_RMTFLT)) { |
229 | EFX_INFO(efx, "MGT_INT: "EFX_DWORD_FMT"\n", EFX_DWORD_VAL(reg)); | 233 | EFX_INFO(efx, "MGT_INT: "EFX_DWORD_FMT"\n", EFX_DWORD_VAL(reg)); |
@@ -237,7 +241,7 @@ static void falcon_mask_status_intr(struct efx_nic *efx, int enable) | |||
237 | { | 241 | { |
238 | efx_dword_t reg; | 242 | efx_dword_t reg; |
239 | 243 | ||
240 | if (FALCON_REV(efx) < FALCON_REV_B0) | 244 | if ((falcon_rev(efx) < FALCON_REV_B0) || LOOPBACK_INTERNAL(efx)) |
241 | return; | 245 | return; |
242 | 246 | ||
243 | /* Flush the ISR */ | 247 | /* Flush the ISR */ |
@@ -284,6 +288,9 @@ int falcon_xaui_link_ok(struct efx_nic *efx) | |||
284 | efx_dword_t reg; | 288 | efx_dword_t reg; |
285 | int align_done, sync_status, link_ok = 0; | 289 | int align_done, sync_status, link_ok = 0; |
286 | 290 | ||
291 | if (LOOPBACK_INTERNAL(efx)) | ||
292 | return 1; | ||
293 | |||
287 | /* Read link status */ | 294 | /* Read link status */ |
288 | falcon_xmac_readl(efx, ®, XX_CORE_STAT_REG_MAC); | 295 | falcon_xmac_readl(efx, ®, XX_CORE_STAT_REG_MAC); |
289 | 296 | ||
@@ -374,6 +381,61 @@ static void falcon_reconfigure_xmac_core(struct efx_nic *efx) | |||
374 | falcon_xmac_writel(efx, ®, XM_ADR_HI_REG_MAC); | 381 | falcon_xmac_writel(efx, ®, XM_ADR_HI_REG_MAC); |
375 | } | 382 | } |
376 | 383 | ||
384 | static void falcon_reconfigure_xgxs_core(struct efx_nic *efx) | ||
385 | { | ||
386 | efx_dword_t reg; | ||
387 | int xgxs_loopback = (efx->loopback_mode == LOOPBACK_XGXS) ? 1 : 0; | ||
388 | int xaui_loopback = (efx->loopback_mode == LOOPBACK_XAUI) ? 1 : 0; | ||
389 | int xgmii_loopback = | ||
390 | (efx->loopback_mode == LOOPBACK_XGMII) ? 1 : 0; | ||
391 | |||
392 | /* XGXS block is flaky and will need to be reset if moving | ||
393 | * into our out of XGMII, XGXS or XAUI loopbacks. */ | ||
394 | if (EFX_WORKAROUND_5147(efx)) { | ||
395 | int old_xgmii_loopback, old_xgxs_loopback, old_xaui_loopback; | ||
396 | int reset_xgxs; | ||
397 | |||
398 | falcon_xmac_readl(efx, ®, XX_CORE_STAT_REG_MAC); | ||
399 | old_xgxs_loopback = EFX_DWORD_FIELD(reg, XX_XGXS_LB_EN); | ||
400 | old_xgmii_loopback = EFX_DWORD_FIELD(reg, XX_XGMII_LB_EN); | ||
401 | |||
402 | falcon_xmac_readl(efx, ®, XX_SD_CTL_REG_MAC); | ||
403 | old_xaui_loopback = EFX_DWORD_FIELD(reg, XX_LPBKA); | ||
404 | |||
405 | /* The PHY driver may have turned XAUI off */ | ||
406 | reset_xgxs = ((xgxs_loopback != old_xgxs_loopback) || | ||
407 | (xaui_loopback != old_xaui_loopback) || | ||
408 | (xgmii_loopback != old_xgmii_loopback)); | ||
409 | if (reset_xgxs) { | ||
410 | falcon_xmac_readl(efx, ®, XX_PWR_RST_REG_MAC); | ||
411 | EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSTX_EN, 1); | ||
412 | EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSRX_EN, 1); | ||
413 | falcon_xmac_writel(efx, ®, XX_PWR_RST_REG_MAC); | ||
414 | udelay(1); | ||
415 | EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSTX_EN, 0); | ||
416 | EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSRX_EN, 0); | ||
417 | falcon_xmac_writel(efx, ®, XX_PWR_RST_REG_MAC); | ||
418 | udelay(1); | ||
419 | } | ||
420 | } | ||
421 | |||
422 | falcon_xmac_readl(efx, ®, XX_CORE_STAT_REG_MAC); | ||
423 | EFX_SET_DWORD_FIELD(reg, XX_FORCE_SIG, | ||
424 | (xgxs_loopback || xaui_loopback) ? | ||
425 | XX_FORCE_SIG_DECODE_FORCED : 0); | ||
426 | EFX_SET_DWORD_FIELD(reg, XX_XGXS_LB_EN, xgxs_loopback); | ||
427 | EFX_SET_DWORD_FIELD(reg, XX_XGMII_LB_EN, xgmii_loopback); | ||
428 | falcon_xmac_writel(efx, ®, XX_CORE_STAT_REG_MAC); | ||
429 | |||
430 | falcon_xmac_readl(efx, ®, XX_SD_CTL_REG_MAC); | ||
431 | EFX_SET_DWORD_FIELD(reg, XX_LPBKD, xaui_loopback); | ||
432 | EFX_SET_DWORD_FIELD(reg, XX_LPBKC, xaui_loopback); | ||
433 | EFX_SET_DWORD_FIELD(reg, XX_LPBKB, xaui_loopback); | ||
434 | EFX_SET_DWORD_FIELD(reg, XX_LPBKA, xaui_loopback); | ||
435 | falcon_xmac_writel(efx, ®, XX_SD_CTL_REG_MAC); | ||
436 | } | ||
437 | |||
438 | |||
377 | /* Try and bring the Falcon side of the Falcon-Phy XAUI link fails | 439 | /* Try and bring the Falcon side of the Falcon-Phy XAUI link fails |
378 | * to come back up. Bash it until it comes back up */ | 440 | * to come back up. Bash it until it comes back up */ |
379 | static int falcon_check_xaui_link_up(struct efx_nic *efx) | 441 | static int falcon_check_xaui_link_up(struct efx_nic *efx) |
@@ -382,7 +444,8 @@ static int falcon_check_xaui_link_up(struct efx_nic *efx) | |||
382 | tries = EFX_WORKAROUND_5147(efx) ? 5 : 1; | 444 | tries = EFX_WORKAROUND_5147(efx) ? 5 : 1; |
383 | max_tries = tries; | 445 | max_tries = tries; |
384 | 446 | ||
385 | if (efx->phy_type == PHY_TYPE_NONE) | 447 | if ((efx->loopback_mode == LOOPBACK_NETWORK) || |
448 | (efx->phy_type == PHY_TYPE_NONE)) | ||
386 | return 0; | 449 | return 0; |
387 | 450 | ||
388 | while (tries) { | 451 | while (tries) { |
@@ -391,12 +454,12 @@ static int falcon_check_xaui_link_up(struct efx_nic *efx) | |||
391 | 454 | ||
392 | EFX_LOG(efx, "%s Clobbering XAUI (%d tries left).\n", | 455 | EFX_LOG(efx, "%s Clobbering XAUI (%d tries left).\n", |
393 | __func__, tries); | 456 | __func__, tries); |
394 | (void) falcon_reset_xaui(efx); | 457 | falcon_reset_xaui(efx); |
395 | udelay(200); | 458 | udelay(200); |
396 | tries--; | 459 | tries--; |
397 | } | 460 | } |
398 | 461 | ||
399 | EFX_ERR(efx, "Failed to bring XAUI link back up in %d tries!\n", | 462 | EFX_LOG(efx, "Failed to bring XAUI link back up in %d tries!\n", |
400 | max_tries); | 463 | max_tries); |
401 | return 0; | 464 | return 0; |
402 | } | 465 | } |
@@ -408,8 +471,13 @@ void falcon_reconfigure_xmac(struct efx_nic *efx) | |||
408 | falcon_mask_status_intr(efx, 0); | 471 | falcon_mask_status_intr(efx, 0); |
409 | 472 | ||
410 | falcon_deconfigure_mac_wrapper(efx); | 473 | falcon_deconfigure_mac_wrapper(efx); |
474 | |||
475 | efx->tx_disabled = LOOPBACK_INTERNAL(efx); | ||
411 | efx->phy_op->reconfigure(efx); | 476 | efx->phy_op->reconfigure(efx); |
477 | |||
478 | falcon_reconfigure_xgxs_core(efx); | ||
412 | falcon_reconfigure_xmac_core(efx); | 479 | falcon_reconfigure_xmac_core(efx); |
480 | |||
413 | falcon_reconfigure_mac_wrapper(efx); | 481 | falcon_reconfigure_mac_wrapper(efx); |
414 | 482 | ||
415 | /* Ensure XAUI link is up */ | 483 | /* Ensure XAUI link is up */ |
@@ -491,18 +559,20 @@ void falcon_update_stats_xmac(struct efx_nic *efx) | |||
491 | (mac_stats->rx_bytes - mac_stats->rx_good_bytes); | 559 | (mac_stats->rx_bytes - mac_stats->rx_good_bytes); |
492 | } | 560 | } |
493 | 561 | ||
494 | #define EFX_XAUI_RETRAIN_MAX 8 | ||
495 | |||
496 | int falcon_check_xmac(struct efx_nic *efx) | 562 | int falcon_check_xmac(struct efx_nic *efx) |
497 | { | 563 | { |
498 | unsigned xaui_link_ok; | 564 | unsigned xaui_link_ok; |
499 | int rc; | 565 | int rc; |
500 | 566 | ||
567 | if ((efx->loopback_mode == LOOPBACK_NETWORK) || | ||
568 | (efx->phy_type == PHY_TYPE_NONE)) | ||
569 | return 0; | ||
570 | |||
501 | falcon_mask_status_intr(efx, 0); | 571 | falcon_mask_status_intr(efx, 0); |
502 | xaui_link_ok = falcon_xaui_link_ok(efx); | 572 | xaui_link_ok = falcon_xaui_link_ok(efx); |
503 | 573 | ||
504 | if (EFX_WORKAROUND_5147(efx) && !xaui_link_ok) | 574 | if (EFX_WORKAROUND_5147(efx) && !xaui_link_ok) |
505 | (void) falcon_reset_xaui(efx); | 575 | falcon_reset_xaui(efx); |
506 | 576 | ||
507 | /* Call the PHY check_hw routine */ | 577 | /* Call the PHY check_hw routine */ |
508 | rc = efx->phy_op->check_hw(efx); | 578 | rc = efx->phy_op->check_hw(efx); |
@@ -569,7 +639,7 @@ int falcon_xmac_set_pause(struct efx_nic *efx, enum efx_fc_type flow_control) | |||
569 | reset = ((flow_control & EFX_FC_TX) && | 639 | reset = ((flow_control & EFX_FC_TX) && |
570 | !(efx->flow_control & EFX_FC_TX)); | 640 | !(efx->flow_control & EFX_FC_TX)); |
571 | if (EFX_WORKAROUND_11482(efx) && reset) { | 641 | if (EFX_WORKAROUND_11482(efx) && reset) { |
572 | if (FALCON_REV(efx) >= FALCON_REV_B0) { | 642 | if (falcon_rev(efx) >= FALCON_REV_B0) { |
573 | /* Recover by resetting the EM block */ | 643 | /* Recover by resetting the EM block */ |
574 | if (efx->link_up) | 644 | if (efx->link_up) |
575 | falcon_drain_tx_fifo(efx); | 645 | falcon_drain_tx_fifo(efx); |