]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/sfc/tenxpress.c
Merge branch 'topic/hda' into for-linus
[linux-2.6-omap-h63xx.git] / drivers / net / sfc / tenxpress.c
index 9ecb77da954527a9dff367f4aa0b4674e7f94d17..f0efd246962cf01e2a9639b6fdb4421e8a3e1438 100644 (file)
@@ -67,6 +67,8 @@
 #define PMA_PMD_EXT_CLK312_WIDTH 1
 #define PMA_PMD_EXT_LPOWER_LBN  12
 #define PMA_PMD_EXT_LPOWER_WIDTH 1
+#define PMA_PMD_EXT_ROBUST_LBN 14
+#define PMA_PMD_EXT_ROBUST_WIDTH 1
 #define PMA_PMD_EXT_SSR_LBN    15
 #define PMA_PMD_EXT_SSR_WIDTH  1
 
 #define C22EXT_STATUS_LINK_LBN  2
 #define C22EXT_STATUS_LINK_WIDTH 1
 
-#define C22EXT_MSTSLV_REG       49162
-#define C22EXT_MSTSLV_1000_HD_LBN 10
-#define C22EXT_MSTSLV_1000_HD_WIDTH 1
-#define C22EXT_MSTSLV_1000_FD_LBN 11
-#define C22EXT_MSTSLV_1000_FD_WIDTH 1
+#define C22EXT_MSTSLV_CTRL                     49161
+#define C22EXT_MSTSLV_CTRL_ADV_1000_HD_LBN     8
+#define C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN     9
+
+#define C22EXT_MSTSLV_STATUS                   49162
+#define C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN    10
+#define C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN    11
 
 /* Time to wait between powering down the LNPGA and turning off the power
  * rails */
 #define LNPGA_PDOWN_WAIT       (HZ / 5)
 
-static int crc_error_reset_threshold = 100;
-module_param(crc_error_reset_threshold, int, 0644);
-MODULE_PARM_DESC(crc_error_reset_threshold,
-                "Max number of CRC errors before XAUI reset");
-
 struct tenxpress_phy_data {
        enum efx_loopback_mode loopback_mode;
-       atomic_t bad_crc_count;
        enum efx_phy_mode phy_mode;
        int bad_lp_tries;
 };
 
-void tenxpress_crc_err(struct efx_nic *efx)
-{
-       struct tenxpress_phy_data *phy_data = efx->phy_data;
-       if (phy_data != NULL)
-               atomic_inc(&phy_data->bad_crc_count);
-}
-
 static ssize_t show_phy_short_reach(struct device *dev,
                                    struct device_attribute *attr, char *buf)
 {
@@ -284,7 +275,9 @@ static int tenxpress_init(struct efx_nic *efx)
                                         PMA_PMD_XCONTROL_REG);
                reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) |
                        (1 << PMA_PMD_EXT_CLK_OUT_LBN) |
-                       (1 << PMA_PMD_EXT_CLK312_LBN));
+                       (1 << PMA_PMD_EXT_CLK312_LBN) |
+                       (1 << PMA_PMD_EXT_ROBUST_LBN));
+
                mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
                                    PMA_PMD_XCONTROL_REG, reg);
                mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
@@ -346,6 +339,7 @@ static int tenxpress_phy_init(struct efx_nic *efx)
        rc = tenxpress_init(efx);
        if (rc < 0)
                goto fail;
+       mdio_clause45_set_pause(efx);
 
        if (efx->phy_type == PHY_TYPE_SFT9001B) {
                rc = device_create_file(&efx->pci_dev->dev,
@@ -376,8 +370,8 @@ static int tenxpress_special_reset(struct efx_nic *efx)
 
        /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so
         * a special software reset can glitch the XGMAC sufficiently for stats
-        * requests to fail. Since we don't often special_reset, just lock. */
-       spin_lock(&efx->stats_lock);
+        * requests to fail. */
+       efx_stats_disable(efx);
 
        /* Initiate reset */
        reg = mdio_clause45_read(efx, efx->mii.phy_id,
@@ -392,17 +386,17 @@ static int tenxpress_special_reset(struct efx_nic *efx)
        rc = mdio_clause45_wait_reset_mmds(efx,
                                           TENXPRESS_REQUIRED_DEVS);
        if (rc < 0)
-               goto unlock;
+               goto out;
 
        /* Try and reconfigure the device */
        rc = tenxpress_init(efx);
        if (rc < 0)
-               goto unlock;
+               goto out;
 
        /* Wait for the XGXS state machine to churn */
        mdelay(10);
-unlock:
-       spin_unlock(&efx->stats_lock);
+out:
+       efx_stats_enable(efx);
        return rc;
 }
 
@@ -520,7 +514,7 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx)
 {
        struct tenxpress_phy_data *phy_data = efx->phy_data;
        struct ethtool_cmd ecmd;
-       bool phy_mode_change, loop_reset, loop_toggle, loopback;
+       bool phy_mode_change, loop_reset;
 
        if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) {
                phy_data->phy_mode = efx->phy_mode;
@@ -531,12 +525,10 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx)
 
        phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL &&
                           phy_data->phy_mode != PHY_MODE_NORMAL);
-       loopback = LOOPBACK_MASK(efx) & efx->phy_op->loopbacks;
-       loop_toggle = LOOPBACK_CHANGED(phy_data, efx, efx->phy_op->loopbacks);
        loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, efx->phy_op->loopbacks) ||
                      LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY));
 
-       if (loop_reset || loop_toggle || loopback || phy_mode_change) {
+       if (loop_reset || phy_mode_change) {
                int rc;
 
                efx->phy_op->get_settings(efx, &ecmd);
@@ -551,20 +543,6 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx)
                                falcon_reset_xaui(efx);
                }
 
-               if (efx->phy_type != PHY_TYPE_SFX7101) {
-                       /* Only change autoneg once, on coming out or
-                        * going into loopback */
-                       if (loop_toggle)
-                               ecmd.autoneg = !loopback;
-                       if (loopback) {
-                               ecmd.duplex = DUPLEX_FULL;
-                               if (efx->loopback_mode == LOOPBACK_GPHY)
-                                       ecmd.speed = SPEED_1000;
-                               else
-                                       ecmd.speed = SPEED_10000;
-                       }
-               }
-
                rc = efx->phy_op->set_settings(efx, &ecmd);
                WARN_ON(rc);
        }
@@ -623,13 +601,6 @@ static void tenxpress_phy_poll(struct efx_nic *efx)
 
        if (phy_data->phy_mode != PHY_MODE_NORMAL)
                return;
-
-       if (EFX_WORKAROUND_10750(efx) &&
-           atomic_read(&phy_data->bad_crc_count) > crc_error_reset_threshold) {
-               EFX_ERR(efx, "Resetting XAUI due to too many CRC errors\n");
-               falcon_reset_xaui(efx);
-               atomic_set(&phy_data->bad_crc_count, 0);
-       }
 }
 
 static void tenxpress_phy_fini(struct efx_nic *efx)
@@ -772,107 +743,76 @@ reset:
        return rc;
 }
 
-static u32 tenxpress_get_xnp_lpa(struct efx_nic *efx)
+static void
+tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
 {
-       int phy = efx->mii.phy_id;
-       u32 lpa = 0;
+       int phy_id = efx->mii.phy_id;
+       u32 adv = 0, lpa = 0;
        int reg;
 
        if (efx->phy_type != PHY_TYPE_SFX7101) {
-               reg = mdio_clause45_read(efx, phy, MDIO_MMD_C22EXT,
-                                        C22EXT_MSTSLV_REG);
-               if (reg & (1 << C22EXT_MSTSLV_1000_HD_LBN))
+               reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
+                                        C22EXT_MSTSLV_CTRL);
+               if (reg & (1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN))
+                       adv |= ADVERTISED_1000baseT_Full;
+               reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
+                                        C22EXT_MSTSLV_STATUS);
+               if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN))
                        lpa |= ADVERTISED_1000baseT_Half;
-               if (reg & (1 << C22EXT_MSTSLV_1000_FD_LBN))
+               if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN))
                        lpa |= ADVERTISED_1000baseT_Full;
        }
-       reg = mdio_clause45_read(efx, phy, MDIO_MMD_AN, MDIO_AN_10GBT_STATUS);
+       reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
+                                MDIO_AN_10GBT_CTRL);
+       if (reg & (1 << MDIO_AN_10GBT_CTRL_ADV_10G_LBN))
+               adv |= ADVERTISED_10000baseT_Full;
+       reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
+                                MDIO_AN_10GBT_STATUS);
        if (reg & (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN))
                lpa |= ADVERTISED_10000baseT_Full;
-       return lpa;
-}
 
-static void sfx7101_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
-{
-       mdio_clause45_get_settings_ext(efx, ecmd, ADVERTISED_10000baseT_Full,
-                                      tenxpress_get_xnp_lpa(efx));
-       ecmd->supported |= SUPPORTED_10000baseT_Full;
-       ecmd->advertising |= ADVERTISED_10000baseT_Full;
+       mdio_clause45_get_settings_ext(efx, ecmd, adv, lpa);
+
+       if (efx->phy_type != PHY_TYPE_SFX7101)
+               ecmd->supported |= (SUPPORTED_100baseT_Full |
+                                   SUPPORTED_1000baseT_Full);
+
+       /* In loopback, the PHY automatically brings up the correct interface,
+        * but doesn't advertise the correct speed. So override it */
+       if (efx->loopback_mode == LOOPBACK_GPHY)
+               ecmd->speed = SPEED_1000;
+       else if (LOOPBACK_MASK(efx) & efx->phy_op->loopbacks)
+               ecmd->speed = SPEED_10000;
 }
 
-static void sft9001_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+static int tenxpress_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
 {
-       int phy_id = efx->mii.phy_id;
-       u32 xnp_adv = 0;
-       int reg;
-
-       reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
-                                PMA_PMD_SPEED_ENABLE_REG);
-       if (EFX_WORKAROUND_13204(efx) && (reg & (1 << PMA_PMD_100TX_ADV_LBN)))
-               xnp_adv |= ADVERTISED_100baseT_Full;
-       if (reg & (1 << PMA_PMD_1000T_ADV_LBN))
-               xnp_adv |= ADVERTISED_1000baseT_Full;
-       if (reg & (1 << PMA_PMD_10000T_ADV_LBN))
-               xnp_adv |= ADVERTISED_10000baseT_Full;
-
-       mdio_clause45_get_settings_ext(efx, ecmd, xnp_adv,
-                                      tenxpress_get_xnp_lpa(efx));
-
-       ecmd->supported |= (SUPPORTED_100baseT_Half |
-                           SUPPORTED_100baseT_Full |
-                           SUPPORTED_1000baseT_Full);
+       if (!ecmd->autoneg)
+               return -EINVAL;
 
-       /* Use the vendor defined C22ext register for duplex settings */
-       if (ecmd->speed != SPEED_10000 && !ecmd->autoneg) {
-               reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
-                                        GPHY_XCONTROL_REG);
-               ecmd->duplex = (reg & (1 << GPHY_DUPLEX_LBN) ?
-                               DUPLEX_FULL : DUPLEX_HALF);
-       }
+       return mdio_clause45_set_settings(efx, ecmd);
 }
 
-static int sft9001_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+static void sfx7101_set_npage_adv(struct efx_nic *efx, u32 advertising)
 {
-       int phy_id = efx->mii.phy_id;
-       int rc;
-
-       rc = mdio_clause45_set_settings(efx, ecmd);
-       if (rc)
-               return rc;
-
-       if (ecmd->speed != SPEED_10000 && !ecmd->autoneg)
-               mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
-                                      GPHY_XCONTROL_REG, GPHY_DUPLEX_LBN,
-                                      ecmd->duplex == DUPLEX_FULL);
-
-       return rc;
+       mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_AN,
+                              MDIO_AN_10GBT_CTRL,
+                              MDIO_AN_10GBT_CTRL_ADV_10G_LBN,
+                              advertising & ADVERTISED_10000baseT_Full);
 }
 
-static bool sft9001_set_xnp_advertise(struct efx_nic *efx, u32 advertising)
+static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising)
 {
-       int phy = efx->mii.phy_id;
-       int reg = mdio_clause45_read(efx, phy, MDIO_MMD_PMAPMD,
-                                    PMA_PMD_SPEED_ENABLE_REG);
-       bool enabled;
-
-       reg &= ~((1 << 2) | (1 << 3));
-       if (EFX_WORKAROUND_13204(efx) &&
-           (advertising & ADVERTISED_100baseT_Full))
-               reg |= 1 << PMA_PMD_100TX_ADV_LBN;
-       if (advertising & ADVERTISED_1000baseT_Full)
-               reg |= 1 << PMA_PMD_1000T_ADV_LBN;
-       if (advertising & ADVERTISED_10000baseT_Full)
-               reg |= 1 << PMA_PMD_10000T_ADV_LBN;
-       mdio_clause45_write(efx, phy, MDIO_MMD_PMAPMD,
-                           PMA_PMD_SPEED_ENABLE_REG, reg);
-
-       enabled = (advertising &
-                  (ADVERTISED_1000baseT_Half |
-                   ADVERTISED_1000baseT_Full |
-                   ADVERTISED_10000baseT_Full));
-       if (EFX_WORKAROUND_13204(efx))
-               enabled |= (advertising & ADVERTISED_100baseT_Full);
-       return enabled;
+       int phy_id = efx->mii.phy_id;
+
+       mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
+                              C22EXT_MSTSLV_CTRL,
+                              C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN,
+                              advertising & ADVERTISED_1000baseT_Full);
+       mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN,
+                              MDIO_AN_10GBT_CTRL,
+                              MDIO_AN_10GBT_CTRL_ADV_10G_LBN,
+                              advertising & ADVERTISED_10000baseT_Full);
 }
 
 struct efx_phy_operations falcon_sfx7101_phy_ops = {
@@ -882,8 +822,9 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = {
        .poll             = tenxpress_phy_poll,
        .fini             = tenxpress_phy_fini,
        .clear_interrupt  = efx_port_dummy_op_void,
-       .get_settings     = sfx7101_get_settings,
-       .set_settings     = mdio_clause45_set_settings,
+       .get_settings     = tenxpress_get_settings,
+       .set_settings     = tenxpress_set_settings,
+       .set_npage_adv    = sfx7101_set_npage_adv,
        .num_tests        = ARRAY_SIZE(sfx7101_test_names),
        .test_names       = sfx7101_test_names,
        .run_tests        = sfx7101_run_tests,
@@ -898,9 +839,9 @@ struct efx_phy_operations falcon_sft9001_phy_ops = {
        .poll             = tenxpress_phy_poll,
        .fini             = tenxpress_phy_fini,
        .clear_interrupt  = efx_port_dummy_op_void,
-       .get_settings     = sft9001_get_settings,
-       .set_settings     = sft9001_set_settings,
-       .set_xnp_advertise = sft9001_set_xnp_advertise,
+       .get_settings     = tenxpress_get_settings,
+       .set_settings     = tenxpress_set_settings,
+       .set_npage_adv    = sft9001_set_npage_adv,
        .num_tests        = ARRAY_SIZE(sft9001_test_names),
        .test_names       = sft9001_test_names,
        .run_tests        = sft9001_run_tests,