diff options
Diffstat (limited to 'drivers/net/sfc/selftest.c')
-rw-r--r-- | drivers/net/sfc/selftest.c | 76 |
1 files changed, 40 insertions, 36 deletions
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c index 7813ab354411..d10f6fbbb5ce 100644 --- a/drivers/net/sfc/selftest.c +++ b/drivers/net/sfc/selftest.c | |||
@@ -653,47 +653,48 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests, | |||
653 | 653 | ||
654 | /************************************************************************** | 654 | /************************************************************************** |
655 | * | 655 | * |
656 | * Entry points | 656 | * Entry point |
657 | * | 657 | * |
658 | *************************************************************************/ | 658 | *************************************************************************/ |
659 | 659 | ||
660 | /* Online (i.e. non-disruptive) testing | 660 | int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, |
661 | * This checks interrupt generation, event delivery and PHY presence. */ | 661 | unsigned flags) |
662 | int efx_online_test(struct efx_nic *efx, struct efx_self_tests *tests) | ||
663 | { | 662 | { |
663 | enum efx_loopback_mode loopback_mode = efx->loopback_mode; | ||
664 | int phy_mode = efx->phy_mode; | ||
665 | struct ethtool_cmd ecmd; | ||
664 | struct efx_channel *channel; | 666 | struct efx_channel *channel; |
665 | int rc, rc2 = 0; | 667 | int rc_test = 0, rc_reset = 0, rc; |
668 | |||
669 | /* Online (i.e. non-disruptive) testing | ||
670 | * This checks interrupt generation, event delivery and PHY presence. */ | ||
666 | 671 | ||
667 | rc = efx_test_mii(efx, tests); | 672 | rc = efx_test_mii(efx, tests); |
668 | if (rc && !rc2) | 673 | if (rc && !rc_test) |
669 | rc2 = rc; | 674 | rc_test = rc; |
670 | 675 | ||
671 | rc = efx_test_nvram(efx, tests); | 676 | rc = efx_test_nvram(efx, tests); |
672 | if (rc && !rc2) | 677 | if (rc && !rc_test) |
673 | rc2 = rc; | 678 | rc_test = rc; |
674 | 679 | ||
675 | rc = efx_test_interrupts(efx, tests); | 680 | rc = efx_test_interrupts(efx, tests); |
676 | if (rc && !rc2) | 681 | if (rc && !rc_test) |
677 | rc2 = rc; | 682 | rc_test = rc; |
678 | 683 | ||
679 | efx_for_each_channel(channel, efx) { | 684 | efx_for_each_channel(channel, efx) { |
680 | rc = efx_test_eventq_irq(channel, tests); | 685 | rc = efx_test_eventq_irq(channel, tests); |
681 | if (rc && !rc2) | 686 | if (rc && !rc_test) |
682 | rc2 = rc; | 687 | rc_test = rc; |
683 | } | 688 | } |
684 | 689 | ||
685 | return rc2; | 690 | if (rc_test) |
686 | } | 691 | return rc_test; |
687 | 692 | ||
688 | /* Offline (i.e. disruptive) testing | 693 | if (!(flags & ETH_TEST_FL_OFFLINE)) |
689 | * This checks MAC and PHY loopback on the specified port. */ | 694 | return 0; |
690 | int efx_offline_test(struct efx_nic *efx, | 695 | |
691 | struct efx_self_tests *tests, unsigned int loopback_modes) | 696 | /* Offline (i.e. disruptive) testing |
692 | { | 697 | * This checks MAC and PHY loopback on the specified port. */ |
693 | enum efx_loopback_mode loopback_mode = efx->loopback_mode; | ||
694 | int phy_mode = efx->phy_mode; | ||
695 | struct ethtool_cmd ecmd; | ||
696 | int rc, rc2 = 0; | ||
697 | 698 | ||
698 | /* force the carrier state off so the kernel doesn't transmit during | 699 | /* force the carrier state off so the kernel doesn't transmit during |
699 | * the loopback test, and the watchdog timeout doesn't fire. Also put | 700 | * the loopback test, and the watchdog timeout doesn't fire. Also put |
@@ -717,31 +718,34 @@ int efx_offline_test(struct efx_nic *efx, | |||
717 | efx_reset_down(efx, &ecmd); | 718 | efx_reset_down(efx, &ecmd); |
718 | 719 | ||
719 | rc = efx_test_chip(efx, tests); | 720 | rc = efx_test_chip(efx, tests); |
720 | if (rc && !rc2) | 721 | if (rc && !rc_test) |
721 | rc2 = rc; | 722 | rc_test = rc; |
722 | 723 | ||
723 | /* reset the chip to recover from the register test */ | 724 | /* reset the chip to recover from the register test */ |
724 | rc = falcon_reset_hw(efx, RESET_TYPE_ALL); | 725 | rc_reset = falcon_reset_hw(efx, RESET_TYPE_ALL); |
725 | 726 | ||
726 | /* Ensure that the phy is powered and out of loopback | 727 | /* Ensure that the phy is powered and out of loopback |
727 | * for the bist and loopback tests */ | 728 | * for the bist and loopback tests */ |
728 | efx->phy_mode &= ~PHY_MODE_LOW_POWER; | 729 | efx->phy_mode &= ~PHY_MODE_LOW_POWER; |
729 | efx->loopback_mode = LOOPBACK_NONE; | 730 | efx->loopback_mode = LOOPBACK_NONE; |
730 | 731 | ||
731 | rc = efx_reset_up(efx, &ecmd, rc == 0); | 732 | rc = efx_reset_up(efx, &ecmd, rc_reset == 0); |
732 | if (rc) { | 733 | if (rc && !rc_reset) |
734 | rc_reset = rc; | ||
735 | |||
736 | if (rc_reset) { | ||
733 | EFX_ERR(efx, "Unable to recover from chip test\n"); | 737 | EFX_ERR(efx, "Unable to recover from chip test\n"); |
734 | efx_schedule_reset(efx, RESET_TYPE_DISABLE); | 738 | efx_schedule_reset(efx, RESET_TYPE_DISABLE); |
735 | return rc; | 739 | return rc_reset; |
736 | } | 740 | } |
737 | 741 | ||
738 | rc = efx_test_phy(efx, tests); | 742 | rc = efx_test_phy(efx, tests); |
739 | if (rc && !rc2) | 743 | if (rc && !rc_test) |
740 | rc2 = rc; | 744 | rc_test = rc; |
741 | 745 | ||
742 | rc = efx_test_loopbacks(efx, tests, loopback_modes); | 746 | rc = efx_test_loopbacks(efx, tests, efx->loopback_modes); |
743 | if (rc && !rc2) | 747 | if (rc && !rc_test) |
744 | rc2 = rc; | 748 | rc_test = rc; |
745 | 749 | ||
746 | /* restore the PHY to the previous state */ | 750 | /* restore the PHY to the previous state */ |
747 | efx->loopback_mode = loopback_mode; | 751 | efx->loopback_mode = loopback_mode; |
@@ -749,6 +753,6 @@ int efx_offline_test(struct efx_nic *efx, | |||
749 | efx->port_inhibited = false; | 753 | efx->port_inhibited = false; |
750 | efx_ethtool_set_settings(efx->net_dev, &ecmd); | 754 | efx_ethtool_set_settings(efx->net_dev, &ecmd); |
751 | 755 | ||
752 | return rc2; | 756 | return rc_test; |
753 | } | 757 | } |
754 | 758 | ||