[netdrvr] sfc: Report XAUI link down at default log level
[pandora-kernel.git] / drivers / net / sfc / falcon_xmac.c
index aa7521b..55c0d97 100644 (file)
@@ -32,7 +32,7 @@
        (FALCON_XMAC_REGBANK + ((mac_reg) * FALCON_XMAC_REG_SIZE))
 
 void falcon_xmac_writel(struct efx_nic *efx,
-                       efx_dword_t *value, unsigned int mac_reg)
+                        efx_dword_t *value, unsigned int mac_reg)
 {
        efx_oword_t temp;
 
@@ -69,6 +69,10 @@ static int falcon_reset_xmac(struct efx_nic *efx)
                udelay(10);
        }
 
+       /* This often fails when DSP is disabled, ignore it */
+       if (sfe4001_phy_flash_cfg != 0)
+               return 0;
+
        EFX_ERR(efx, "timed out waiting for XMAC core reset\n");
        return -ETIMEDOUT;
 }
@@ -217,13 +221,13 @@ static int falcon_xgmii_status(struct efx_nic *efx)
 {
        efx_dword_t reg;
 
-       if (FALCON_REV(efx) < FALCON_REV_B0)
+       if (falcon_rev(efx) < FALCON_REV_B0)
                return 1;
 
        /* The ISR latches, so clear it and re-read */
        falcon_xmac_readl(efx, &reg, XM_MGT_INT_REG_MAC_B0);
        falcon_xmac_readl(efx, &reg, XM_MGT_INT_REG_MAC_B0);
-       
+
        if (EFX_DWORD_FIELD(reg, XM_LCLFLT) ||
            EFX_DWORD_FIELD(reg, XM_RMTFLT)) {
                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)
 {
        efx_dword_t reg;
 
-       if (FALCON_REV(efx) < FALCON_REV_B0)
+       if ((falcon_rev(efx) < FALCON_REV_B0) || LOOPBACK_INTERNAL(efx))
                return;
 
        /* Flush the ISR */
@@ -284,6 +288,9 @@ int falcon_xaui_link_ok(struct efx_nic *efx)
        efx_dword_t reg;
        int align_done, sync_status, link_ok = 0;
 
+       if (LOOPBACK_INTERNAL(efx))
+               return 1;
+
        /* Read link status */
        falcon_xmac_readl(efx, &reg, XX_CORE_STAT_REG_MAC);
 
@@ -374,6 +381,61 @@ static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
        falcon_xmac_writel(efx, &reg, XM_ADR_HI_REG_MAC);
 }
 
+static void falcon_reconfigure_xgxs_core(struct efx_nic *efx)
+{
+       efx_dword_t reg;
+       int xgxs_loopback = (efx->loopback_mode == LOOPBACK_XGXS) ? 1 : 0;
+       int xaui_loopback = (efx->loopback_mode == LOOPBACK_XAUI) ? 1 : 0;
+       int xgmii_loopback =
+               (efx->loopback_mode == LOOPBACK_XGMII) ? 1 : 0;
+
+       /* XGXS block is flaky and will need to be reset if moving
+        * into our out of XGMII, XGXS or XAUI loopbacks. */
+       if (EFX_WORKAROUND_5147(efx)) {
+               int old_xgmii_loopback, old_xgxs_loopback, old_xaui_loopback;
+               int reset_xgxs;
+
+               falcon_xmac_readl(efx, &reg, XX_CORE_STAT_REG_MAC);
+               old_xgxs_loopback = EFX_DWORD_FIELD(reg, XX_XGXS_LB_EN);
+               old_xgmii_loopback = EFX_DWORD_FIELD(reg, XX_XGMII_LB_EN);
+
+               falcon_xmac_readl(efx, &reg, XX_SD_CTL_REG_MAC);
+               old_xaui_loopback = EFX_DWORD_FIELD(reg, XX_LPBKA);
+
+               /* The PHY driver may have turned XAUI off */
+               reset_xgxs = ((xgxs_loopback != old_xgxs_loopback) ||
+                             (xaui_loopback != old_xaui_loopback) ||
+                             (xgmii_loopback != old_xgmii_loopback));
+               if (reset_xgxs) {
+                       falcon_xmac_readl(efx, &reg, XX_PWR_RST_REG_MAC);
+                       EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSTX_EN, 1);
+                       EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSRX_EN, 1);
+                       falcon_xmac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
+                       udelay(1);
+                       EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSTX_EN, 0);
+                       EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSRX_EN, 0);
+                       falcon_xmac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
+                       udelay(1);
+               }
+       }
+
+       falcon_xmac_readl(efx, &reg, XX_CORE_STAT_REG_MAC);
+       EFX_SET_DWORD_FIELD(reg, XX_FORCE_SIG,
+                           (xgxs_loopback || xaui_loopback) ?
+                           XX_FORCE_SIG_DECODE_FORCED : 0);
+       EFX_SET_DWORD_FIELD(reg, XX_XGXS_LB_EN, xgxs_loopback);
+       EFX_SET_DWORD_FIELD(reg, XX_XGMII_LB_EN, xgmii_loopback);
+       falcon_xmac_writel(efx, &reg, XX_CORE_STAT_REG_MAC);
+
+       falcon_xmac_readl(efx, &reg, XX_SD_CTL_REG_MAC);
+       EFX_SET_DWORD_FIELD(reg, XX_LPBKD, xaui_loopback);
+       EFX_SET_DWORD_FIELD(reg, XX_LPBKC, xaui_loopback);
+       EFX_SET_DWORD_FIELD(reg, XX_LPBKB, xaui_loopback);
+       EFX_SET_DWORD_FIELD(reg, XX_LPBKA, xaui_loopback);
+       falcon_xmac_writel(efx, &reg, XX_SD_CTL_REG_MAC);
+}
+
+
 /* Try and bring the Falcon side of the Falcon-Phy XAUI link fails
  * to come back up. Bash it until it comes back up */
 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)
        tries = EFX_WORKAROUND_5147(efx) ? 5 : 1;
        max_tries = tries;
 
-       if (efx->phy_type == PHY_TYPE_NONE)
+       if ((efx->loopback_mode == LOOPBACK_NETWORK) ||
+           (efx->phy_type == PHY_TYPE_NONE))
                return 0;
 
        while (tries) {
@@ -391,12 +454,12 @@ static int falcon_check_xaui_link_up(struct efx_nic *efx)
 
                EFX_LOG(efx, "%s Clobbering XAUI (%d tries left).\n",
                        __func__, tries);
-               (void) falcon_reset_xaui(efx);
+               falcon_reset_xaui(efx);
                udelay(200);
                tries--;
        }
 
-       EFX_ERR(efx, "Failed to bring XAUI link back up in %d tries!\n",
+       EFX_LOG(efx, "Failed to bring XAUI link back up in %d tries!\n",
                max_tries);
        return 0;
 }
@@ -408,8 +471,13 @@ void falcon_reconfigure_xmac(struct efx_nic *efx)
        falcon_mask_status_intr(efx, 0);
 
        falcon_deconfigure_mac_wrapper(efx);
+
+       efx->tx_disabled = LOOPBACK_INTERNAL(efx);
        efx->phy_op->reconfigure(efx);
+
+       falcon_reconfigure_xgxs_core(efx);
        falcon_reconfigure_xmac_core(efx);
+
        falcon_reconfigure_mac_wrapper(efx);
 
        /* Ensure XAUI link is up */
@@ -491,18 +559,20 @@ void falcon_update_stats_xmac(struct efx_nic *efx)
                (mac_stats->rx_bytes - mac_stats->rx_good_bytes);
 }
 
-#define EFX_XAUI_RETRAIN_MAX 8
-
 int falcon_check_xmac(struct efx_nic *efx)
 {
        unsigned xaui_link_ok;
        int rc;
 
+       if ((efx->loopback_mode == LOOPBACK_NETWORK) ||
+           (efx->phy_type == PHY_TYPE_NONE))
+               return 0;
+
        falcon_mask_status_intr(efx, 0);
        xaui_link_ok = falcon_xaui_link_ok(efx);
 
        if (EFX_WORKAROUND_5147(efx) && !xaui_link_ok)
-               (void) falcon_reset_xaui(efx);
+               falcon_reset_xaui(efx);
 
        /* Call the PHY check_hw routine */
        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)
        reset = ((flow_control & EFX_FC_TX) &&
                 !(efx->flow_control & EFX_FC_TX));
        if (EFX_WORKAROUND_11482(efx) && reset) {
-               if (FALCON_REV(efx) >= FALCON_REV_B0) {
+               if (falcon_rev(efx) >= FALCON_REV_B0) {
                        /* Recover by resetting the EM block */
                        if (efx->link_up)
                                falcon_drain_tx_fifo(efx);