diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2008-12-26 16:47:04 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-26 16:47:04 -0500 |
commit | 2ef3068e6c40ec44d27f6f8027616e284d1b0466 (patch) | |
tree | f4aaf6d442f7dbbe64a7744c111707680893862b /drivers/net/sfc | |
parent | a5692e49cd9e6512c48ebf61e52991cbe643c12d (diff) |
sfc: Merge top-level functions for self-tests
Pass in ethtool test flags to determine which tests to run.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r-- | drivers/net/sfc/ethtool.c | 19 | ||||
-rw-r--r-- | drivers/net/sfc/selftest.c | 76 | ||||
-rw-r--r-- | drivers/net/sfc/selftest.h | 8 |
3 files changed, 48 insertions, 55 deletions
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 3aaece6b12cc..7fa28443c7bc 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c | |||
@@ -487,7 +487,7 @@ static void efx_ethtool_self_test(struct net_device *net_dev, | |||
487 | { | 487 | { |
488 | struct efx_nic *efx = netdev_priv(net_dev); | 488 | struct efx_nic *efx = netdev_priv(net_dev); |
489 | struct efx_self_tests efx_tests; | 489 | struct efx_self_tests efx_tests; |
490 | int offline, already_up; | 490 | int already_up; |
491 | int rc; | 491 | int rc; |
492 | 492 | ||
493 | ASSERT_RTNL(); | 493 | ASSERT_RTNL(); |
@@ -507,24 +507,15 @@ static void efx_ethtool_self_test(struct net_device *net_dev, | |||
507 | } | 507 | } |
508 | 508 | ||
509 | memset(&efx_tests, 0, sizeof(efx_tests)); | 509 | memset(&efx_tests, 0, sizeof(efx_tests)); |
510 | offline = (test->flags & ETH_TEST_FL_OFFLINE); | ||
511 | 510 | ||
512 | /* Perform online self tests first */ | 511 | rc = efx_selftest(efx, &efx_tests, test->flags); |
513 | rc = efx_online_test(efx, &efx_tests); | ||
514 | if (rc) | ||
515 | goto out; | ||
516 | |||
517 | /* Perform offline tests only if online tests passed */ | ||
518 | if (offline) | ||
519 | rc = efx_offline_test(efx, &efx_tests, | ||
520 | efx->loopback_modes); | ||
521 | 512 | ||
522 | out: | ||
523 | if (!already_up) | 513 | if (!already_up) |
524 | dev_close(efx->net_dev); | 514 | dev_close(efx->net_dev); |
525 | 515 | ||
526 | EFX_LOG(efx, "%s all %sline self-tests\n", | 516 | EFX_LOG(efx, "%s %sline self-tests\n", |
527 | rc == 0 ? "passed" : "failed", offline ? "off" : "on"); | 517 | rc == 0 ? "passed" : "failed", |
518 | (test->flags & ETH_TEST_FL_OFFLINE) ? "off" : "on"); | ||
528 | 519 | ||
529 | fail2: | 520 | fail2: |
530 | fail1: | 521 | fail1: |
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 | ||
diff --git a/drivers/net/sfc/selftest.h b/drivers/net/sfc/selftest.h index 252f7d717242..97d6acc11ad3 100644 --- a/drivers/net/sfc/selftest.h +++ b/drivers/net/sfc/selftest.h | |||
@@ -44,10 +44,8 @@ struct efx_self_tests { | |||
44 | 44 | ||
45 | extern void efx_loopback_rx_packet(struct efx_nic *efx, | 45 | extern void efx_loopback_rx_packet(struct efx_nic *efx, |
46 | const char *buf_ptr, int pkt_len); | 46 | const char *buf_ptr, int pkt_len); |
47 | extern int efx_online_test(struct efx_nic *efx, | 47 | extern int efx_selftest(struct efx_nic *efx, |
48 | struct efx_self_tests *tests); | 48 | struct efx_self_tests *tests, |
49 | extern int efx_offline_test(struct efx_nic *efx, | 49 | unsigned flags); |
50 | struct efx_self_tests *tests, | ||
51 | unsigned int loopback_modes); | ||
52 | 50 | ||
53 | #endif /* EFX_SELFTEST_H */ | 51 | #endif /* EFX_SELFTEST_H */ |