aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2008-12-26 16:47:25 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-26 16:47:25 -0500
commit1796721a5a691a5d392abf8070ad40a0b787b667 (patch)
tree16ed5a5a8c77db9e8f70c9b23f6b26cde491c336 /drivers
parent2ef3068e6c40ec44d27f6f8027616e284d1b0466 (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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/sfc/ethtool.c8
-rw-r--r--drivers/net/sfc/net_driver.h8
-rw-r--r--drivers/net/sfc/selftest.c15
-rw-r--r--drivers/net/sfc/selftest.h4
-rw-r--r--drivers/net/sfc/tenxpress.c24
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
250static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests) 250static 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
657static int tenxpress_phy_test(struct efx_nic *efx) 657static const char *const tenxpress_test_names[] = {
658 "bist"
659};
660
661static int
662tenxpress_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
663static u32 tenxpress_get_xnp_lpa(struct efx_nic *efx) 675static 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};