diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2008-12-26 16:47:25 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-26 16:47:25 -0500 |
commit | 1796721a5a691a5d392abf8070ad40a0b787b667 (patch) | |
tree | 16ed5a5a8c77db9e8f70c9b23f6b26cde491c336 | |
parent | 2ef3068e6c40ec44d27f6f8027616e284d1b0466 (diff) |
sfc: Add support for multiple PHY self-tests
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/sfc/ethtool.c | 8 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 8 | ||||
-rw-r--r-- | drivers/net/sfc/selftest.c | 15 | ||||
-rw-r--r-- | drivers/net/sfc/selftest.h | 4 | ||||
-rw-r--r-- | drivers/net/sfc/tenxpress.c | 24 |
5 files changed, 44 insertions, 15 deletions
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 7fa28443c7bc..53d259e90187 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c | |||
@@ -345,7 +345,7 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, | |||
345 | u64 *data) | 345 | u64 *data) |
346 | { | 346 | { |
347 | struct efx_channel *channel; | 347 | struct efx_channel *channel; |
348 | unsigned int n = 0; | 348 | unsigned int n = 0, i; |
349 | enum efx_loopback_mode mode; | 349 | enum efx_loopback_mode mode; |
350 | 350 | ||
351 | efx_fill_test(n++, strings, data, &tests->mii, | 351 | efx_fill_test(n++, strings, data, &tests->mii, |
@@ -373,8 +373,10 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, | |||
373 | 373 | ||
374 | efx_fill_test(n++, strings, data, &tests->registers, | 374 | efx_fill_test(n++, strings, data, &tests->registers, |
375 | "core", 0, "registers", NULL); | 375 | "core", 0, "registers", NULL); |
376 | efx_fill_test(n++, strings, data, &tests->phy, | 376 | |
377 | "phy", 0, "bist", NULL); | 377 | for (i = 0; i < efx->phy_op->num_tests; i++) |
378 | efx_fill_test(n++, strings, data, &tests->phy[i], | ||
379 | "phy", 0, efx->phy_op->test_names[i], NULL); | ||
378 | 380 | ||
379 | /* Loopback tests */ | 381 | /* Loopback tests */ |
380 | for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) { | 382 | for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) { |
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index b0c79755ef2f..5f255f75754e 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
@@ -568,6 +568,10 @@ struct efx_mac_operations { | |||
568 | * @set_settings: Set ethtool settings. Serialised by the mac_lock. | 568 | * @set_settings: Set ethtool settings. Serialised by the mac_lock. |
569 | * @set_xnp_advertise: Set abilities advertised in Extended Next Page | 569 | * @set_xnp_advertise: Set abilities advertised in Extended Next Page |
570 | * (only needed where AN bit is set in mmds) | 570 | * (only needed where AN bit is set in mmds) |
571 | * @num_tests: Number of PHY-specific tests/results | ||
572 | * @test_names: Names of the tests/results | ||
573 | * @run_tests: Run tests and record results as appropriate. | ||
574 | * Flags are the ethtool tests flags. | ||
571 | * @mmds: MMD presence mask | 575 | * @mmds: MMD presence mask |
572 | * @loopbacks: Supported loopback modes mask | 576 | * @loopbacks: Supported loopback modes mask |
573 | */ | 577 | */ |
@@ -578,12 +582,14 @@ struct efx_phy_operations { | |||
578 | void (*reconfigure) (struct efx_nic *efx); | 582 | void (*reconfigure) (struct efx_nic *efx); |
579 | void (*clear_interrupt) (struct efx_nic *efx); | 583 | void (*clear_interrupt) (struct efx_nic *efx); |
580 | void (*poll) (struct efx_nic *efx); | 584 | void (*poll) (struct efx_nic *efx); |
581 | int (*test) (struct efx_nic *efx); | ||
582 | void (*get_settings) (struct efx_nic *efx, | 585 | void (*get_settings) (struct efx_nic *efx, |
583 | struct ethtool_cmd *ecmd); | 586 | struct ethtool_cmd *ecmd); |
584 | int (*set_settings) (struct efx_nic *efx, | 587 | int (*set_settings) (struct efx_nic *efx, |
585 | struct ethtool_cmd *ecmd); | 588 | struct ethtool_cmd *ecmd); |
586 | bool (*set_xnp_advertise) (struct efx_nic *efx, u32); | 589 | bool (*set_xnp_advertise) (struct efx_nic *efx, u32); |
590 | u32 num_tests; | ||
591 | const char *const *test_names; | ||
592 | int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags); | ||
587 | int mmds; | 593 | int mmds; |
588 | unsigned loopbacks; | 594 | unsigned loopbacks; |
589 | }; | 595 | }; |
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c index d10f6fbbb5ce..dba0d64d50cd 100644 --- a/drivers/net/sfc/selftest.c +++ b/drivers/net/sfc/selftest.c | |||
@@ -247,17 +247,20 @@ static int efx_test_eventq_irq(struct efx_channel *channel, | |||
247 | return 0; | 247 | return 0; |
248 | } | 248 | } |
249 | 249 | ||
250 | static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests) | 250 | static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests, |
251 | unsigned flags) | ||
251 | { | 252 | { |
252 | int rc; | 253 | int rc; |
253 | 254 | ||
254 | if (!efx->phy_op->test) | 255 | if (!efx->phy_op->run_tests) |
255 | return 0; | 256 | return 0; |
256 | 257 | ||
258 | EFX_BUG_ON_PARANOID(efx->phy_op->num_tests == 0 || | ||
259 | efx->phy_op->num_tests > EFX_MAX_PHY_TESTS); | ||
260 | |||
257 | mutex_lock(&efx->mac_lock); | 261 | mutex_lock(&efx->mac_lock); |
258 | rc = efx->phy_op->test(efx); | 262 | rc = efx->phy_op->run_tests(efx, tests->phy, flags); |
259 | mutex_unlock(&efx->mac_lock); | 263 | mutex_unlock(&efx->mac_lock); |
260 | tests->phy = rc ? -1 : 1; | ||
261 | return rc; | 264 | return rc; |
262 | } | 265 | } |
263 | 266 | ||
@@ -691,7 +694,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, | |||
691 | return rc_test; | 694 | return rc_test; |
692 | 695 | ||
693 | if (!(flags & ETH_TEST_FL_OFFLINE)) | 696 | if (!(flags & ETH_TEST_FL_OFFLINE)) |
694 | return 0; | 697 | return efx_test_phy(efx, tests, flags); |
695 | 698 | ||
696 | /* Offline (i.e. disruptive) testing | 699 | /* Offline (i.e. disruptive) testing |
697 | * This checks MAC and PHY loopback on the specified port. */ | 700 | * This checks MAC and PHY loopback on the specified port. */ |
@@ -739,7 +742,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, | |||
739 | return rc_reset; | 742 | return rc_reset; |
740 | } | 743 | } |
741 | 744 | ||
742 | rc = efx_test_phy(efx, tests); | 745 | rc = efx_test_phy(efx, tests, flags); |
743 | if (rc && !rc_test) | 746 | if (rc && !rc_test) |
744 | rc_test = rc; | 747 | rc_test = rc; |
745 | 748 | ||
diff --git a/drivers/net/sfc/selftest.h b/drivers/net/sfc/selftest.h index 97d6acc11ad3..39451cf938cf 100644 --- a/drivers/net/sfc/selftest.h +++ b/drivers/net/sfc/selftest.h | |||
@@ -24,6 +24,8 @@ struct efx_loopback_self_tests { | |||
24 | int rx_bad; | 24 | int rx_bad; |
25 | }; | 25 | }; |
26 | 26 | ||
27 | #define EFX_MAX_PHY_TESTS 20 | ||
28 | |||
27 | /* Efx self test results | 29 | /* Efx self test results |
28 | * For fields which are not counters, 1 indicates success and -1 | 30 | * For fields which are not counters, 1 indicates success and -1 |
29 | * indicates failure. | 31 | * indicates failure. |
@@ -38,7 +40,7 @@ struct efx_self_tests { | |||
38 | int eventq_poll[EFX_MAX_CHANNELS]; | 40 | int eventq_poll[EFX_MAX_CHANNELS]; |
39 | /* offline tests */ | 41 | /* offline tests */ |
40 | int registers; | 42 | int registers; |
41 | int phy; | 43 | int phy[EFX_MAX_PHY_TESTS]; |
42 | struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1]; | 44 | struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1]; |
43 | }; | 45 | }; |
44 | 46 | ||
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index 1567ab538e27..bd204820e189 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c | |||
@@ -654,10 +654,22 @@ void tenxpress_phy_blink(struct efx_nic *efx, bool blink) | |||
654 | PMA_PMD_LED_OVERR_REG, reg); | 654 | PMA_PMD_LED_OVERR_REG, reg); |
655 | } | 655 | } |
656 | 656 | ||
657 | static int tenxpress_phy_test(struct efx_nic *efx) | 657 | static const char *const tenxpress_test_names[] = { |
658 | "bist" | ||
659 | }; | ||
660 | |||
661 | static int | ||
662 | tenxpress_run_tests(struct efx_nic *efx, int *results, unsigned flags) | ||
658 | { | 663 | { |
664 | int rc; | ||
665 | |||
666 | if (!(flags & ETH_TEST_FL_OFFLINE)) | ||
667 | return 0; | ||
668 | |||
659 | /* BIST is automatically run after a special software reset */ | 669 | /* BIST is automatically run after a special software reset */ |
660 | return tenxpress_special_reset(efx); | 670 | rc = tenxpress_special_reset(efx); |
671 | results[0] = rc ? -1 : 1; | ||
672 | return rc; | ||
661 | } | 673 | } |
662 | 674 | ||
663 | static u32 tenxpress_get_xnp_lpa(struct efx_nic *efx) | 675 | static u32 tenxpress_get_xnp_lpa(struct efx_nic *efx) |
@@ -770,9 +782,11 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = { | |||
770 | .poll = tenxpress_phy_poll, | 782 | .poll = tenxpress_phy_poll, |
771 | .fini = tenxpress_phy_fini, | 783 | .fini = tenxpress_phy_fini, |
772 | .clear_interrupt = efx_port_dummy_op_void, | 784 | .clear_interrupt = efx_port_dummy_op_void, |
773 | .test = tenxpress_phy_test, | ||
774 | .get_settings = sfx7101_get_settings, | 785 | .get_settings = sfx7101_get_settings, |
775 | .set_settings = mdio_clause45_set_settings, | 786 | .set_settings = mdio_clause45_set_settings, |
787 | .num_tests = ARRAY_SIZE(tenxpress_test_names), | ||
788 | .test_names = tenxpress_test_names, | ||
789 | .run_tests = tenxpress_run_tests, | ||
776 | .mmds = TENXPRESS_REQUIRED_DEVS, | 790 | .mmds = TENXPRESS_REQUIRED_DEVS, |
777 | .loopbacks = SFX7101_LOOPBACKS, | 791 | .loopbacks = SFX7101_LOOPBACKS, |
778 | }; | 792 | }; |
@@ -784,10 +798,12 @@ struct efx_phy_operations falcon_sft9001_phy_ops = { | |||
784 | .poll = tenxpress_phy_poll, | 798 | .poll = tenxpress_phy_poll, |
785 | .fini = tenxpress_phy_fini, | 799 | .fini = tenxpress_phy_fini, |
786 | .clear_interrupt = efx_port_dummy_op_void, | 800 | .clear_interrupt = efx_port_dummy_op_void, |
787 | .test = tenxpress_phy_test, | ||
788 | .get_settings = sft9001_get_settings, | 801 | .get_settings = sft9001_get_settings, |
789 | .set_settings = sft9001_set_settings, | 802 | .set_settings = sft9001_set_settings, |
790 | .set_xnp_advertise = sft9001_set_xnp_advertise, | 803 | .set_xnp_advertise = sft9001_set_xnp_advertise, |
804 | .num_tests = ARRAY_SIZE(tenxpress_test_names), | ||
805 | .test_names = tenxpress_test_names, | ||
806 | .run_tests = tenxpress_run_tests, | ||
791 | .mmds = TENXPRESS_REQUIRED_DEVS, | 807 | .mmds = TENXPRESS_REQUIRED_DEVS, |
792 | .loopbacks = SFT9001_LOOPBACKS, | 808 | .loopbacks = SFT9001_LOOPBACKS, |
793 | }; | 809 | }; |