aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/tenxpress.c
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2009-01-29 12:59:37 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-30 17:06:32 -0500
commitaf4ad9bca0c4039355b20d760b4fd39afa48c59d (patch)
tree720b182118bf2fcb5aa2fb34671d032cf75d0d43 /drivers/net/sfc/tenxpress.c
parentc9d5a53f060bb9ac6cd20d9768b4b75e22bc8689 (diff)
sfc: SFX7101/SFT9001: Fix AN advertisements
All 10Xpress PHYs require autonegotiation all the time; enforce this in the set_settings() method and do not treat it as a workaround. Remove claimed support for 100M HD mode since it is not supported by current firmware. Do not set speed override bits when AN is enabled, and do not use register 1.49192 for AN configuration as it can override what we set elsewhere. Always set the AN selector bits to 1 (802.3). Fix confusion between Next Page and Extended Next Page. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc/tenxpress.c')
-rw-r--r--drivers/net/sfc/tenxpress.c151
1 files changed, 58 insertions, 93 deletions
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index c9584619322a..412d209d8313 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -179,11 +179,13 @@
179#define C22EXT_STATUS_LINK_LBN 2 179#define C22EXT_STATUS_LINK_LBN 2
180#define C22EXT_STATUS_LINK_WIDTH 1 180#define C22EXT_STATUS_LINK_WIDTH 1
181 181
182#define C22EXT_MSTSLV_REG 49162 182#define C22EXT_MSTSLV_CTRL 49161
183#define C22EXT_MSTSLV_1000_HD_LBN 10 183#define C22EXT_MSTSLV_CTRL_ADV_1000_HD_LBN 8
184#define C22EXT_MSTSLV_1000_HD_WIDTH 1 184#define C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN 9
185#define C22EXT_MSTSLV_1000_FD_LBN 11 185
186#define C22EXT_MSTSLV_1000_FD_WIDTH 1 186#define C22EXT_MSTSLV_STATUS 49162
187#define C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN 10
188#define C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN 11
187 189
188/* Time to wait between powering down the LNPGA and turning off the power 190/* Time to wait between powering down the LNPGA and turning off the power
189 * rails */ 191 * rails */
@@ -741,114 +743,76 @@ reset:
741 return rc; 743 return rc;
742} 744}
743 745
744static u32 tenxpress_get_xnp_lpa(struct efx_nic *efx) 746static void
747tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
745{ 748{
746 int phy = efx->mii.phy_id; 749 int phy_id = efx->mii.phy_id;
747 u32 lpa = 0; 750 u32 adv = 0, lpa = 0;
748 int reg; 751 int reg;
749 752
750 if (efx->phy_type != PHY_TYPE_SFX7101) { 753 if (efx->phy_type != PHY_TYPE_SFX7101) {
751 reg = mdio_clause45_read(efx, phy, MDIO_MMD_C22EXT, 754 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
752 C22EXT_MSTSLV_REG); 755 C22EXT_MSTSLV_CTRL);
753 if (reg & (1 << C22EXT_MSTSLV_1000_HD_LBN)) 756 if (reg & (1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN))
757 adv |= ADVERTISED_1000baseT_Full;
758 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
759 C22EXT_MSTSLV_STATUS);
760 if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN))
754 lpa |= ADVERTISED_1000baseT_Half; 761 lpa |= ADVERTISED_1000baseT_Half;
755 if (reg & (1 << C22EXT_MSTSLV_1000_FD_LBN)) 762 if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN))
756 lpa |= ADVERTISED_1000baseT_Full; 763 lpa |= ADVERTISED_1000baseT_Full;
757 } 764 }
758 reg = mdio_clause45_read(efx, phy, MDIO_MMD_AN, MDIO_AN_10GBT_STATUS); 765 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
766 MDIO_AN_10GBT_CTRL);
767 if (reg & (1 << MDIO_AN_10GBT_CTRL_ADV_10G_LBN))
768 adv |= ADVERTISED_10000baseT_Full;
769 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
770 MDIO_AN_10GBT_STATUS);
759 if (reg & (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN)) 771 if (reg & (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN))
760 lpa |= ADVERTISED_10000baseT_Full; 772 lpa |= ADVERTISED_10000baseT_Full;
761 return lpa;
762}
763
764static void sfx7101_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
765{
766 mdio_clause45_get_settings_ext(efx, ecmd, ADVERTISED_10000baseT_Full,
767 tenxpress_get_xnp_lpa(efx));
768 ecmd->supported |= SUPPORTED_10000baseT_Full;
769 ecmd->advertising |= ADVERTISED_10000baseT_Full;
770}
771
772static void sft9001_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
773{
774 int phy_id = efx->mii.phy_id;
775 u32 xnp_adv = 0;
776 int reg;
777
778 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
779 PMA_PMD_SPEED_ENABLE_REG);
780 if (EFX_WORKAROUND_13204(efx) && (reg & (1 << PMA_PMD_100TX_ADV_LBN)))
781 xnp_adv |= ADVERTISED_100baseT_Full;
782 if (reg & (1 << PMA_PMD_1000T_ADV_LBN))
783 xnp_adv |= ADVERTISED_1000baseT_Full;
784 if (reg & (1 << PMA_PMD_10000T_ADV_LBN))
785 xnp_adv |= ADVERTISED_10000baseT_Full;
786
787 mdio_clause45_get_settings_ext(efx, ecmd, xnp_adv,
788 tenxpress_get_xnp_lpa(efx));
789 773
790 ecmd->supported |= (SUPPORTED_100baseT_Half | 774 mdio_clause45_get_settings_ext(efx, ecmd, adv, lpa);
791 SUPPORTED_100baseT_Full |
792 SUPPORTED_1000baseT_Full);
793 775
794 /* Use the vendor defined C22ext register for duplex settings */ 776 if (efx->phy_type != PHY_TYPE_SFX7101)
795 if (ecmd->speed != SPEED_10000 && !ecmd->autoneg) { 777 ecmd->supported |= (SUPPORTED_100baseT_Full |
796 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT, 778 SUPPORTED_1000baseT_Full);
797 GPHY_XCONTROL_REG);
798 ecmd->duplex = (reg & (1 << GPHY_DUPLEX_LBN) ?
799 DUPLEX_FULL : DUPLEX_HALF);
800 }
801 779
802 /* In loopback, the PHY automatically brings up the correct interface, 780 /* In loopback, the PHY automatically brings up the correct interface,
803 * but doesn't advertise the correct speed. So override it */ 781 * but doesn't advertise the correct speed. So override it */
804 if (efx->loopback_mode == LOOPBACK_GPHY) 782 if (efx->loopback_mode == LOOPBACK_GPHY)
805 ecmd->speed = SPEED_1000; 783 ecmd->speed = SPEED_1000;
806 else if (LOOPBACK_MASK(efx) & SFT9001_LOOPBACKS) 784 else if (LOOPBACK_MASK(efx) & efx->phy_op->loopbacks)
807 ecmd->speed = SPEED_10000; 785 ecmd->speed = SPEED_10000;
808} 786}
809 787
810static int sft9001_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) 788static int tenxpress_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
811{ 789{
812 int phy_id = efx->mii.phy_id; 790 if (!ecmd->autoneg)
813 int rc; 791 return -EINVAL;
814
815 rc = mdio_clause45_set_settings(efx, ecmd);
816 if (rc)
817 return rc;
818 792
819 if (ecmd->speed != SPEED_10000 && !ecmd->autoneg) 793 return mdio_clause45_set_settings(efx, ecmd);
820 mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, 794}
821 GPHY_XCONTROL_REG, GPHY_DUPLEX_LBN,
822 ecmd->duplex == DUPLEX_FULL);
823 795
824 return rc; 796static void sfx7101_set_npage_adv(struct efx_nic *efx, u32 advertising)
797{
798 mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_AN,
799 MDIO_AN_10GBT_CTRL,
800 MDIO_AN_10GBT_CTRL_ADV_10G_LBN,
801 advertising & ADVERTISED_10000baseT_Full);
825} 802}
826 803
827static bool sft9001_set_xnp_advertise(struct efx_nic *efx, u32 advertising) 804static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising)
828{ 805{
829 int phy = efx->mii.phy_id; 806 int phy_id = efx->mii.phy_id;
830 int reg = mdio_clause45_read(efx, phy, MDIO_MMD_PMAPMD, 807
831 PMA_PMD_SPEED_ENABLE_REG); 808 mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
832 bool enabled; 809 C22EXT_MSTSLV_CTRL,
833 810 C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN,
834 reg &= ~((1 << 2) | (1 << 3)); 811 advertising & ADVERTISED_1000baseT_Full);
835 if (EFX_WORKAROUND_13204(efx) && 812 mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN,
836 (advertising & ADVERTISED_100baseT_Full)) 813 MDIO_AN_10GBT_CTRL,
837 reg |= 1 << PMA_PMD_100TX_ADV_LBN; 814 MDIO_AN_10GBT_CTRL_ADV_10G_LBN,
838 if (advertising & ADVERTISED_1000baseT_Full) 815 advertising & ADVERTISED_10000baseT_Full);
839 reg |= 1 << PMA_PMD_1000T_ADV_LBN;
840 if (advertising & ADVERTISED_10000baseT_Full)
841 reg |= 1 << PMA_PMD_10000T_ADV_LBN;
842 mdio_clause45_write(efx, phy, MDIO_MMD_PMAPMD,
843 PMA_PMD_SPEED_ENABLE_REG, reg);
844
845 enabled = (advertising &
846 (ADVERTISED_1000baseT_Half |
847 ADVERTISED_1000baseT_Full |
848 ADVERTISED_10000baseT_Full));
849 if (EFX_WORKAROUND_13204(efx))
850 enabled |= (advertising & ADVERTISED_100baseT_Full);
851 return enabled;
852} 816}
853 817
854struct efx_phy_operations falcon_sfx7101_phy_ops = { 818struct efx_phy_operations falcon_sfx7101_phy_ops = {
@@ -858,8 +822,9 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = {
858 .poll = tenxpress_phy_poll, 822 .poll = tenxpress_phy_poll,
859 .fini = tenxpress_phy_fini, 823 .fini = tenxpress_phy_fini,
860 .clear_interrupt = efx_port_dummy_op_void, 824 .clear_interrupt = efx_port_dummy_op_void,
861 .get_settings = sfx7101_get_settings, 825 .get_settings = tenxpress_get_settings,
862 .set_settings = mdio_clause45_set_settings, 826 .set_settings = tenxpress_set_settings,
827 .set_npage_adv = sfx7101_set_npage_adv,
863 .num_tests = ARRAY_SIZE(sfx7101_test_names), 828 .num_tests = ARRAY_SIZE(sfx7101_test_names),
864 .test_names = sfx7101_test_names, 829 .test_names = sfx7101_test_names,
865 .run_tests = sfx7101_run_tests, 830 .run_tests = sfx7101_run_tests,
@@ -874,9 +839,9 @@ struct efx_phy_operations falcon_sft9001_phy_ops = {
874 .poll = tenxpress_phy_poll, 839 .poll = tenxpress_phy_poll,
875 .fini = tenxpress_phy_fini, 840 .fini = tenxpress_phy_fini,
876 .clear_interrupt = efx_port_dummy_op_void, 841 .clear_interrupt = efx_port_dummy_op_void,
877 .get_settings = sft9001_get_settings, 842 .get_settings = tenxpress_get_settings,
878 .set_settings = sft9001_set_settings, 843 .set_settings = tenxpress_set_settings,
879 .set_xnp_advertise = sft9001_set_xnp_advertise, 844 .set_npage_adv = sft9001_set_npage_adv,
880 .num_tests = ARRAY_SIZE(sft9001_test_names), 845 .num_tests = ARRAY_SIZE(sft9001_test_names),
881 .test_names = sft9001_test_names, 846 .test_names = sft9001_test_names,
882 .run_tests = sft9001_run_tests, 847 .run_tests = sft9001_run_tests,