aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/tenxpress.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sfc/tenxpress.c')
-rw-r--r--drivers/net/sfc/tenxpress.c218
1 files changed, 80 insertions, 138 deletions
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index b9768760fae7..f0efd246962c 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -67,6 +67,8 @@
67#define PMA_PMD_EXT_CLK312_WIDTH 1 67#define PMA_PMD_EXT_CLK312_WIDTH 1
68#define PMA_PMD_EXT_LPOWER_LBN 12 68#define PMA_PMD_EXT_LPOWER_LBN 12
69#define PMA_PMD_EXT_LPOWER_WIDTH 1 69#define PMA_PMD_EXT_LPOWER_WIDTH 1
70#define PMA_PMD_EXT_ROBUST_LBN 14
71#define PMA_PMD_EXT_ROBUST_WIDTH 1
70#define PMA_PMD_EXT_SSR_LBN 15 72#define PMA_PMD_EXT_SSR_LBN 15
71#define PMA_PMD_EXT_SSR_WIDTH 1 73#define PMA_PMD_EXT_SSR_WIDTH 1
72 74
@@ -177,35 +179,24 @@
177#define C22EXT_STATUS_LINK_LBN 2 179#define C22EXT_STATUS_LINK_LBN 2
178#define C22EXT_STATUS_LINK_WIDTH 1 180#define C22EXT_STATUS_LINK_WIDTH 1
179 181
180#define C22EXT_MSTSLV_REG 49162 182#define C22EXT_MSTSLV_CTRL 49161
181#define C22EXT_MSTSLV_1000_HD_LBN 10 183#define C22EXT_MSTSLV_CTRL_ADV_1000_HD_LBN 8
182#define C22EXT_MSTSLV_1000_HD_WIDTH 1 184#define C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN 9
183#define C22EXT_MSTSLV_1000_FD_LBN 11 185
184#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
185 189
186/* 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
187 * rails */ 191 * rails */
188#define LNPGA_PDOWN_WAIT (HZ / 5) 192#define LNPGA_PDOWN_WAIT (HZ / 5)
189 193
190static int crc_error_reset_threshold = 100;
191module_param(crc_error_reset_threshold, int, 0644);
192MODULE_PARM_DESC(crc_error_reset_threshold,
193 "Max number of CRC errors before XAUI reset");
194
195struct tenxpress_phy_data { 194struct tenxpress_phy_data {
196 enum efx_loopback_mode loopback_mode; 195 enum efx_loopback_mode loopback_mode;
197 atomic_t bad_crc_count;
198 enum efx_phy_mode phy_mode; 196 enum efx_phy_mode phy_mode;
199 int bad_lp_tries; 197 int bad_lp_tries;
200}; 198};
201 199
202void tenxpress_crc_err(struct efx_nic *efx)
203{
204 struct tenxpress_phy_data *phy_data = efx->phy_data;
205 if (phy_data != NULL)
206 atomic_inc(&phy_data->bad_crc_count);
207}
208
209static ssize_t show_phy_short_reach(struct device *dev, 200static ssize_t show_phy_short_reach(struct device *dev,
210 struct device_attribute *attr, char *buf) 201 struct device_attribute *attr, char *buf)
211{ 202{
@@ -284,7 +275,9 @@ static int tenxpress_init(struct efx_nic *efx)
284 PMA_PMD_XCONTROL_REG); 275 PMA_PMD_XCONTROL_REG);
285 reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) | 276 reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) |
286 (1 << PMA_PMD_EXT_CLK_OUT_LBN) | 277 (1 << PMA_PMD_EXT_CLK_OUT_LBN) |
287 (1 << PMA_PMD_EXT_CLK312_LBN)); 278 (1 << PMA_PMD_EXT_CLK312_LBN) |
279 (1 << PMA_PMD_EXT_ROBUST_LBN));
280
288 mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, 281 mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
289 PMA_PMD_XCONTROL_REG, reg); 282 PMA_PMD_XCONTROL_REG, reg);
290 mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, 283 mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
@@ -346,6 +339,7 @@ static int tenxpress_phy_init(struct efx_nic *efx)
346 rc = tenxpress_init(efx); 339 rc = tenxpress_init(efx);
347 if (rc < 0) 340 if (rc < 0)
348 goto fail; 341 goto fail;
342 mdio_clause45_set_pause(efx);
349 343
350 if (efx->phy_type == PHY_TYPE_SFT9001B) { 344 if (efx->phy_type == PHY_TYPE_SFT9001B) {
351 rc = device_create_file(&efx->pci_dev->dev, 345 rc = device_create_file(&efx->pci_dev->dev,
@@ -376,8 +370,8 @@ static int tenxpress_special_reset(struct efx_nic *efx)
376 370
377 /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so 371 /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so
378 * a special software reset can glitch the XGMAC sufficiently for stats 372 * a special software reset can glitch the XGMAC sufficiently for stats
379 * requests to fail. Since we don't often special_reset, just lock. */ 373 * requests to fail. */
380 spin_lock(&efx->stats_lock); 374 efx_stats_disable(efx);
381 375
382 /* Initiate reset */ 376 /* Initiate reset */
383 reg = mdio_clause45_read(efx, efx->mii.phy_id, 377 reg = mdio_clause45_read(efx, efx->mii.phy_id,
@@ -392,17 +386,17 @@ static int tenxpress_special_reset(struct efx_nic *efx)
392 rc = mdio_clause45_wait_reset_mmds(efx, 386 rc = mdio_clause45_wait_reset_mmds(efx,
393 TENXPRESS_REQUIRED_DEVS); 387 TENXPRESS_REQUIRED_DEVS);
394 if (rc < 0) 388 if (rc < 0)
395 goto unlock; 389 goto out;
396 390
397 /* Try and reconfigure the device */ 391 /* Try and reconfigure the device */
398 rc = tenxpress_init(efx); 392 rc = tenxpress_init(efx);
399 if (rc < 0) 393 if (rc < 0)
400 goto unlock; 394 goto out;
401 395
402 /* Wait for the XGXS state machine to churn */ 396 /* Wait for the XGXS state machine to churn */
403 mdelay(10); 397 mdelay(10);
404unlock: 398out:
405 spin_unlock(&efx->stats_lock); 399 efx_stats_enable(efx);
406 return rc; 400 return rc;
407} 401}
408 402
@@ -520,7 +514,7 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx)
520{ 514{
521 struct tenxpress_phy_data *phy_data = efx->phy_data; 515 struct tenxpress_phy_data *phy_data = efx->phy_data;
522 struct ethtool_cmd ecmd; 516 struct ethtool_cmd ecmd;
523 bool phy_mode_change, loop_reset, loop_toggle, loopback; 517 bool phy_mode_change, loop_reset;
524 518
525 if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) { 519 if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) {
526 phy_data->phy_mode = efx->phy_mode; 520 phy_data->phy_mode = efx->phy_mode;
@@ -531,12 +525,10 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx)
531 525
532 phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL && 526 phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL &&
533 phy_data->phy_mode != PHY_MODE_NORMAL); 527 phy_data->phy_mode != PHY_MODE_NORMAL);
534 loopback = LOOPBACK_MASK(efx) & efx->phy_op->loopbacks;
535 loop_toggle = LOOPBACK_CHANGED(phy_data, efx, efx->phy_op->loopbacks);
536 loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, efx->phy_op->loopbacks) || 528 loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, efx->phy_op->loopbacks) ||
537 LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY)); 529 LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY));
538 530
539 if (loop_reset || loop_toggle || loopback || phy_mode_change) { 531 if (loop_reset || phy_mode_change) {
540 int rc; 532 int rc;
541 533
542 efx->phy_op->get_settings(efx, &ecmd); 534 efx->phy_op->get_settings(efx, &ecmd);
@@ -551,20 +543,6 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx)
551 falcon_reset_xaui(efx); 543 falcon_reset_xaui(efx);
552 } 544 }
553 545
554 if (efx->phy_type != PHY_TYPE_SFX7101) {
555 /* Only change autoneg once, on coming out or
556 * going into loopback */
557 if (loop_toggle)
558 ecmd.autoneg = !loopback;
559 if (loopback) {
560 ecmd.duplex = DUPLEX_FULL;
561 if (efx->loopback_mode == LOOPBACK_GPHY)
562 ecmd.speed = SPEED_1000;
563 else
564 ecmd.speed = SPEED_10000;
565 }
566 }
567
568 rc = efx->phy_op->set_settings(efx, &ecmd); 546 rc = efx->phy_op->set_settings(efx, &ecmd);
569 WARN_ON(rc); 547 WARN_ON(rc);
570 } 548 }
@@ -623,23 +601,17 @@ static void tenxpress_phy_poll(struct efx_nic *efx)
623 601
624 if (phy_data->phy_mode != PHY_MODE_NORMAL) 602 if (phy_data->phy_mode != PHY_MODE_NORMAL)
625 return; 603 return;
626
627 if (EFX_WORKAROUND_10750(efx) &&
628 atomic_read(&phy_data->bad_crc_count) > crc_error_reset_threshold) {
629 EFX_ERR(efx, "Resetting XAUI due to too many CRC errors\n");
630 falcon_reset_xaui(efx);
631 atomic_set(&phy_data->bad_crc_count, 0);
632 }
633} 604}
634 605
635static void tenxpress_phy_fini(struct efx_nic *efx) 606static void tenxpress_phy_fini(struct efx_nic *efx)
636{ 607{
637 int reg; 608 int reg;
638 609
639 if (efx->phy_type == PHY_TYPE_SFT9001B) { 610 if (efx->phy_type == PHY_TYPE_SFT9001B)
640 device_remove_file(&efx->pci_dev->dev, 611 device_remove_file(&efx->pci_dev->dev,
641 &dev_attr_phy_short_reach); 612 &dev_attr_phy_short_reach);
642 } else { 613
614 if (efx->phy_type == PHY_TYPE_SFX7101) {
643 /* Power down the LNPGA */ 615 /* Power down the LNPGA */
644 reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN); 616 reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN);
645 mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, 617 mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
@@ -771,107 +743,76 @@ reset:
771 return rc; 743 return rc;
772} 744}
773 745
774static u32 tenxpress_get_xnp_lpa(struct efx_nic *efx) 746static void
747tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
775{ 748{
776 int phy = efx->mii.phy_id; 749 int phy_id = efx->mii.phy_id;
777 u32 lpa = 0; 750 u32 adv = 0, lpa = 0;
778 int reg; 751 int reg;
779 752
780 if (efx->phy_type != PHY_TYPE_SFX7101) { 753 if (efx->phy_type != PHY_TYPE_SFX7101) {
781 reg = mdio_clause45_read(efx, phy, MDIO_MMD_C22EXT, 754 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
782 C22EXT_MSTSLV_REG); 755 C22EXT_MSTSLV_CTRL);
783 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))
784 lpa |= ADVERTISED_1000baseT_Half; 761 lpa |= ADVERTISED_1000baseT_Half;
785 if (reg & (1 << C22EXT_MSTSLV_1000_FD_LBN)) 762 if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN))
786 lpa |= ADVERTISED_1000baseT_Full; 763 lpa |= ADVERTISED_1000baseT_Full;
787 } 764 }
788 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);
789 if (reg & (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN)) 771 if (reg & (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN))
790 lpa |= ADVERTISED_10000baseT_Full; 772 lpa |= ADVERTISED_10000baseT_Full;
791 return lpa;
792}
793 773
794static void sfx7101_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) 774 mdio_clause45_get_settings_ext(efx, ecmd, adv, lpa);
795{ 775
796 mdio_clause45_get_settings_ext(efx, ecmd, ADVERTISED_10000baseT_Full, 776 if (efx->phy_type != PHY_TYPE_SFX7101)
797 tenxpress_get_xnp_lpa(efx)); 777 ecmd->supported |= (SUPPORTED_100baseT_Full |
798 ecmd->supported |= SUPPORTED_10000baseT_Full; 778 SUPPORTED_1000baseT_Full);
799 ecmd->advertising |= ADVERTISED_10000baseT_Full; 779
780 /* In loopback, the PHY automatically brings up the correct interface,
781 * but doesn't advertise the correct speed. So override it */
782 if (efx->loopback_mode == LOOPBACK_GPHY)
783 ecmd->speed = SPEED_1000;
784 else if (LOOPBACK_MASK(efx) & efx->phy_op->loopbacks)
785 ecmd->speed = SPEED_10000;
800} 786}
801 787
802static void sft9001_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) 788static int tenxpress_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
803{ 789{
804 int phy_id = efx->mii.phy_id; 790 if (!ecmd->autoneg)
805 u32 xnp_adv = 0; 791 return -EINVAL;
806 int reg;
807
808 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
809 PMA_PMD_SPEED_ENABLE_REG);
810 if (EFX_WORKAROUND_13204(efx) && (reg & (1 << PMA_PMD_100TX_ADV_LBN)))
811 xnp_adv |= ADVERTISED_100baseT_Full;
812 if (reg & (1 << PMA_PMD_1000T_ADV_LBN))
813 xnp_adv |= ADVERTISED_1000baseT_Full;
814 if (reg & (1 << PMA_PMD_10000T_ADV_LBN))
815 xnp_adv |= ADVERTISED_10000baseT_Full;
816 792
817 mdio_clause45_get_settings_ext(efx, ecmd, xnp_adv, 793 return mdio_clause45_set_settings(efx, ecmd);
818 tenxpress_get_xnp_lpa(efx));
819
820 ecmd->supported |= (SUPPORTED_100baseT_Half |
821 SUPPORTED_100baseT_Full |
822 SUPPORTED_1000baseT_Full);
823
824 /* Use the vendor defined C22ext register for duplex settings */
825 if (ecmd->speed != SPEED_10000 && !ecmd->autoneg) {
826 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
827 GPHY_XCONTROL_REG);
828 ecmd->duplex = (reg & (1 << GPHY_DUPLEX_LBN) ?
829 DUPLEX_FULL : DUPLEX_HALF);
830 }
831} 794}
832 795
833static int sft9001_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) 796static void sfx7101_set_npage_adv(struct efx_nic *efx, u32 advertising)
834{ 797{
835 int phy_id = efx->mii.phy_id; 798 mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_AN,
836 int rc; 799 MDIO_AN_10GBT_CTRL,
837 800 MDIO_AN_10GBT_CTRL_ADV_10G_LBN,
838 rc = mdio_clause45_set_settings(efx, ecmd); 801 advertising & ADVERTISED_10000baseT_Full);
839 if (rc)
840 return rc;
841
842 if (ecmd->speed != SPEED_10000 && !ecmd->autoneg)
843 mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
844 GPHY_XCONTROL_REG, GPHY_DUPLEX_LBN,
845 ecmd->duplex == DUPLEX_FULL);
846
847 return rc;
848} 802}
849 803
850static bool sft9001_set_xnp_advertise(struct efx_nic *efx, u32 advertising) 804static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising)
851{ 805{
852 int phy = efx->mii.phy_id; 806 int phy_id = efx->mii.phy_id;
853 int reg = mdio_clause45_read(efx, phy, MDIO_MMD_PMAPMD, 807
854 PMA_PMD_SPEED_ENABLE_REG); 808 mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
855 bool enabled; 809 C22EXT_MSTSLV_CTRL,
856 810 C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN,
857 reg &= ~((1 << 2) | (1 << 3)); 811 advertising & ADVERTISED_1000baseT_Full);
858 if (EFX_WORKAROUND_13204(efx) && 812 mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN,
859 (advertising & ADVERTISED_100baseT_Full)) 813 MDIO_AN_10GBT_CTRL,
860 reg |= 1 << PMA_PMD_100TX_ADV_LBN; 814 MDIO_AN_10GBT_CTRL_ADV_10G_LBN,
861 if (advertising & ADVERTISED_1000baseT_Full) 815 advertising & ADVERTISED_10000baseT_Full);
862 reg |= 1 << PMA_PMD_1000T_ADV_LBN;
863 if (advertising & ADVERTISED_10000baseT_Full)
864 reg |= 1 << PMA_PMD_10000T_ADV_LBN;
865 mdio_clause45_write(efx, phy, MDIO_MMD_PMAPMD,
866 PMA_PMD_SPEED_ENABLE_REG, reg);
867
868 enabled = (advertising &
869 (ADVERTISED_1000baseT_Half |
870 ADVERTISED_1000baseT_Full |
871 ADVERTISED_10000baseT_Full));
872 if (EFX_WORKAROUND_13204(efx))
873 enabled |= (advertising & ADVERTISED_100baseT_Full);
874 return enabled;
875} 816}
876 817
877struct efx_phy_operations falcon_sfx7101_phy_ops = { 818struct efx_phy_operations falcon_sfx7101_phy_ops = {
@@ -881,8 +822,9 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = {
881 .poll = tenxpress_phy_poll, 822 .poll = tenxpress_phy_poll,
882 .fini = tenxpress_phy_fini, 823 .fini = tenxpress_phy_fini,
883 .clear_interrupt = efx_port_dummy_op_void, 824 .clear_interrupt = efx_port_dummy_op_void,
884 .get_settings = sfx7101_get_settings, 825 .get_settings = tenxpress_get_settings,
885 .set_settings = mdio_clause45_set_settings, 826 .set_settings = tenxpress_set_settings,
827 .set_npage_adv = sfx7101_set_npage_adv,
886 .num_tests = ARRAY_SIZE(sfx7101_test_names), 828 .num_tests = ARRAY_SIZE(sfx7101_test_names),
887 .test_names = sfx7101_test_names, 829 .test_names = sfx7101_test_names,
888 .run_tests = sfx7101_run_tests, 830 .run_tests = sfx7101_run_tests,
@@ -897,9 +839,9 @@ struct efx_phy_operations falcon_sft9001_phy_ops = {
897 .poll = tenxpress_phy_poll, 839 .poll = tenxpress_phy_poll,
898 .fini = tenxpress_phy_fini, 840 .fini = tenxpress_phy_fini,
899 .clear_interrupt = efx_port_dummy_op_void, 841 .clear_interrupt = efx_port_dummy_op_void,
900 .get_settings = sft9001_get_settings, 842 .get_settings = tenxpress_get_settings,
901 .set_settings = sft9001_set_settings, 843 .set_settings = tenxpress_set_settings,
902 .set_xnp_advertise = sft9001_set_xnp_advertise, 844 .set_npage_adv = sft9001_set_npage_adv,
903 .num_tests = ARRAY_SIZE(sft9001_test_names), 845 .num_tests = ARRAY_SIZE(sft9001_test_names),
904 .test_names = sft9001_test_names, 846 .test_names = sft9001_test_names,
905 .run_tests = sft9001_run_tests, 847 .run_tests = sft9001_run_tests,