diff options
-rw-r--r-- | drivers/net/sfc/ethtool.c | 6 | ||||
-rw-r--r-- | drivers/net/sfc/mcdi_phy.c | 22 | ||||
-rw-r--r-- | drivers/net/sfc/mdio_10g.c | 24 | ||||
-rw-r--r-- | drivers/net/sfc/mdio_10g.h | 3 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 4 | ||||
-rw-r--r-- | drivers/net/sfc/qt202x_phy.c | 1 | ||||
-rw-r--r-- | drivers/net/sfc/selftest.c | 40 | ||||
-rw-r--r-- | drivers/net/sfc/selftest.h | 4 | ||||
-rw-r--r-- | drivers/net/sfc/tenxpress.c | 2 |
9 files changed, 66 insertions, 40 deletions
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 6c0bbed8c477..635c4205b4fb 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c | |||
@@ -342,8 +342,8 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, | |||
342 | unsigned int n = 0, i; | 342 | unsigned int n = 0, i; |
343 | enum efx_loopback_mode mode; | 343 | enum efx_loopback_mode mode; |
344 | 344 | ||
345 | efx_fill_test(n++, strings, data, &tests->mdio, | 345 | efx_fill_test(n++, strings, data, &tests->phy_alive, |
346 | "core", 0, "mdio", NULL); | 346 | "phy", 0, "alive", NULL); |
347 | efx_fill_test(n++, strings, data, &tests->nvram, | 347 | efx_fill_test(n++, strings, data, &tests->nvram, |
348 | "core", 0, "nvram", NULL); | 348 | "core", 0, "nvram", NULL); |
349 | efx_fill_test(n++, strings, data, &tests->interrupt, | 349 | efx_fill_test(n++, strings, data, &tests->interrupt, |
@@ -379,7 +379,7 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, | |||
379 | if (name == NULL) | 379 | if (name == NULL) |
380 | break; | 380 | break; |
381 | 381 | ||
382 | efx_fill_test(n++, strings, data, &tests->phy[i], | 382 | efx_fill_test(n++, strings, data, &tests->phy_ext[i], |
383 | "phy", 0, name, NULL); | 383 | "phy", 0, name, NULL); |
384 | } | 384 | } |
385 | } | 385 | } |
diff --git a/drivers/net/sfc/mcdi_phy.c b/drivers/net/sfc/mcdi_phy.c index d87e74d3994e..34c22fa986e2 100644 --- a/drivers/net/sfc/mcdi_phy.c +++ b/drivers/net/sfc/mcdi_phy.c | |||
@@ -572,6 +572,27 @@ static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ec | |||
572 | return 0; | 572 | return 0; |
573 | } | 573 | } |
574 | 574 | ||
575 | static int efx_mcdi_phy_test_alive(struct efx_nic *efx) | ||
576 | { | ||
577 | u8 outbuf[MC_CMD_GET_PHY_STATE_OUT_LEN]; | ||
578 | size_t outlen; | ||
579 | int rc; | ||
580 | |||
581 | BUILD_BUG_ON(MC_CMD_GET_PHY_STATE_IN_LEN != 0); | ||
582 | |||
583 | rc = efx_mcdi_rpc(efx, MC_CMD_GET_PHY_STATE, NULL, 0, | ||
584 | outbuf, sizeof(outbuf), &outlen); | ||
585 | if (rc) | ||
586 | return rc; | ||
587 | |||
588 | if (outlen < MC_CMD_GET_PHY_STATE_OUT_LEN) | ||
589 | return -EMSGSIZE; | ||
590 | if (MCDI_DWORD(outbuf, GET_PHY_STATE_STATE) != MC_CMD_PHY_STATE_OK) | ||
591 | return -EINVAL; | ||
592 | |||
593 | return 0; | ||
594 | } | ||
595 | |||
575 | struct efx_phy_operations efx_mcdi_phy_ops = { | 596 | struct efx_phy_operations efx_mcdi_phy_ops = { |
576 | .probe = efx_mcdi_phy_probe, | 597 | .probe = efx_mcdi_phy_probe, |
577 | .init = efx_port_dummy_op_int, | 598 | .init = efx_port_dummy_op_int, |
@@ -581,6 +602,7 @@ struct efx_phy_operations efx_mcdi_phy_ops = { | |||
581 | .remove = efx_mcdi_phy_remove, | 602 | .remove = efx_mcdi_phy_remove, |
582 | .get_settings = efx_mcdi_phy_get_settings, | 603 | .get_settings = efx_mcdi_phy_get_settings, |
583 | .set_settings = efx_mcdi_phy_set_settings, | 604 | .set_settings = efx_mcdi_phy_set_settings, |
605 | .test_alive = efx_mcdi_phy_test_alive, | ||
584 | .run_tests = NULL, | 606 | .run_tests = NULL, |
585 | .test_name = NULL, | 607 | .test_name = NULL, |
586 | }; | 608 | }; |
diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c index 1574e52f0594..0548fcbbdcd0 100644 --- a/drivers/net/sfc/mdio_10g.c +++ b/drivers/net/sfc/mdio_10g.c | |||
@@ -335,3 +335,27 @@ enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx) | |||
335 | mii_advertise_flowctrl(efx->wanted_fc), | 335 | mii_advertise_flowctrl(efx->wanted_fc), |
336 | efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_LPA)); | 336 | efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_LPA)); |
337 | } | 337 | } |
338 | |||
339 | int efx_mdio_test_alive(struct efx_nic *efx) | ||
340 | { | ||
341 | int rc; | ||
342 | int devad = __ffs(efx->mdio.mmds); | ||
343 | u16 physid1, physid2; | ||
344 | |||
345 | mutex_lock(&efx->mac_lock); | ||
346 | |||
347 | physid1 = efx_mdio_read(efx, devad, MDIO_DEVID1); | ||
348 | physid2 = efx_mdio_read(efx, devad, MDIO_DEVID2); | ||
349 | |||
350 | if ((physid1 == 0x0000) || (physid1 == 0xffff) || | ||
351 | (physid2 == 0x0000) || (physid2 == 0xffff)) { | ||
352 | EFX_ERR(efx, "no MDIO PHY present with ID %d\n", | ||
353 | efx->mdio.prtad); | ||
354 | rc = -EINVAL; | ||
355 | } else { | ||
356 | rc = efx_mdio_check_mmds(efx, efx->mdio.mmds, 0); | ||
357 | } | ||
358 | |||
359 | mutex_unlock(&efx->mac_lock); | ||
360 | return rc; | ||
361 | } | ||
diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h index f6ac9503339d..f89e71929603 100644 --- a/drivers/net/sfc/mdio_10g.h +++ b/drivers/net/sfc/mdio_10g.h | |||
@@ -106,4 +106,7 @@ efx_mdio_set_flag(struct efx_nic *efx, int devad, int addr, | |||
106 | mdio_set_flag(&efx->mdio, efx->mdio.prtad, devad, addr, mask, state); | 106 | mdio_set_flag(&efx->mdio, efx->mdio.prtad, devad, addr, mask, state); |
107 | } | 107 | } |
108 | 108 | ||
109 | /* Liveness self-test for MDIO PHYs */ | ||
110 | extern int efx_mdio_test_alive(struct efx_nic *efx); | ||
111 | |||
109 | #endif /* EFX_MDIO_10G_H */ | 112 | #endif /* EFX_MDIO_10G_H */ |
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index d5aab5b3fa06..8f951e4f15be 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
@@ -516,8 +516,9 @@ struct efx_mac_operations { | |||
516 | * @set_settings: Set ethtool settings. Serialised by the mac_lock. | 516 | * @set_settings: Set ethtool settings. Serialised by the mac_lock. |
517 | * @set_npage_adv: Set abilities advertised in (Extended) Next Page | 517 | * @set_npage_adv: Set abilities advertised in (Extended) Next Page |
518 | * (only needed where AN bit is set in mmds) | 518 | * (only needed where AN bit is set in mmds) |
519 | * @test_alive: Test that PHY is 'alive' (online) | ||
519 | * @test_name: Get the name of a PHY-specific test/result | 520 | * @test_name: Get the name of a PHY-specific test/result |
520 | * @run_tests: Run tests and record results as appropriate. | 521 | * @run_tests: Run tests and record results as appropriate (offline). |
521 | * Flags are the ethtool tests flags. | 522 | * Flags are the ethtool tests flags. |
522 | */ | 523 | */ |
523 | struct efx_phy_operations { | 524 | struct efx_phy_operations { |
@@ -532,6 +533,7 @@ struct efx_phy_operations { | |||
532 | int (*set_settings) (struct efx_nic *efx, | 533 | int (*set_settings) (struct efx_nic *efx, |
533 | struct ethtool_cmd *ecmd); | 534 | struct ethtool_cmd *ecmd); |
534 | void (*set_npage_adv) (struct efx_nic *efx, u32); | 535 | void (*set_npage_adv) (struct efx_nic *efx, u32); |
536 | int (*test_alive) (struct efx_nic *efx); | ||
535 | const char *(*test_name) (struct efx_nic *efx, unsigned int index); | 537 | const char *(*test_name) (struct efx_nic *efx, unsigned int index); |
536 | int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags); | 538 | int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags); |
537 | }; | 539 | }; |
diff --git a/drivers/net/sfc/qt202x_phy.c b/drivers/net/sfc/qt202x_phy.c index e0d13a451019..14793d8bd661 100644 --- a/drivers/net/sfc/qt202x_phy.c +++ b/drivers/net/sfc/qt202x_phy.c | |||
@@ -445,4 +445,5 @@ struct efx_phy_operations falcon_qt202x_phy_ops = { | |||
445 | .remove = qt202x_phy_remove, | 445 | .remove = qt202x_phy_remove, |
446 | .get_settings = qt202x_phy_get_settings, | 446 | .get_settings = qt202x_phy_get_settings, |
447 | .set_settings = efx_mdio_set_settings, | 447 | .set_settings = efx_mdio_set_settings, |
448 | .test_alive = efx_mdio_test_alive, | ||
448 | }; | 449 | }; |
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c index 250c8827b842..8a5a7b6d042d 100644 --- a/drivers/net/sfc/selftest.c +++ b/drivers/net/sfc/selftest.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include "workarounds.h" | 26 | #include "workarounds.h" |
27 | #include "spi.h" | 27 | #include "spi.h" |
28 | #include "io.h" | 28 | #include "io.h" |
29 | #include "mdio_10g.h" | ||
30 | 29 | ||
31 | /* | 30 | /* |
32 | * Loopback test packet structure | 31 | * Loopback test packet structure |
@@ -76,42 +75,15 @@ struct efx_loopback_state { | |||
76 | * | 75 | * |
77 | **************************************************************************/ | 76 | **************************************************************************/ |
78 | 77 | ||
79 | static int efx_test_mdio(struct efx_nic *efx, struct efx_self_tests *tests) | 78 | static int efx_test_phy_alive(struct efx_nic *efx, struct efx_self_tests *tests) |
80 | { | 79 | { |
81 | int rc = 0; | 80 | int rc = 0; |
82 | int devad; | ||
83 | u16 physid1, physid2; | ||
84 | |||
85 | if (efx->mdio.mode_support & MDIO_SUPPORTS_C45) | ||
86 | devad = __ffs(efx->mdio.mmds); | ||
87 | else if (efx->mdio.mode_support & MDIO_SUPPORTS_C22) | ||
88 | devad = MDIO_DEVAD_NONE; | ||
89 | else | ||
90 | return 0; | ||
91 | |||
92 | mutex_lock(&efx->mac_lock); | ||
93 | tests->mdio = -1; | ||
94 | |||
95 | physid1 = efx_mdio_read(efx, devad, MDIO_DEVID1); | ||
96 | physid2 = efx_mdio_read(efx, devad, MDIO_DEVID2); | ||
97 | 81 | ||
98 | if ((physid1 == 0x0000) || (physid1 == 0xffff) || | 82 | if (efx->phy_op->test_alive) { |
99 | (physid2 == 0x0000) || (physid2 == 0xffff)) { | 83 | rc = efx->phy_op->test_alive(efx); |
100 | EFX_ERR(efx, "no MDIO PHY present with ID %d\n", | 84 | tests->phy_alive = rc ? -1 : 1; |
101 | efx->mdio.prtad); | ||
102 | rc = -EINVAL; | ||
103 | goto out; | ||
104 | } | 85 | } |
105 | 86 | ||
106 | if (EFX_IS10G(efx)) { | ||
107 | rc = efx_mdio_check_mmds(efx, efx->mdio.mmds, 0); | ||
108 | if (rc) | ||
109 | goto out; | ||
110 | } | ||
111 | |||
112 | out: | ||
113 | mutex_unlock(&efx->mac_lock); | ||
114 | tests->mdio = rc ? -1 : 1; | ||
115 | return rc; | 87 | return rc; |
116 | } | 88 | } |
117 | 89 | ||
@@ -258,7 +230,7 @@ static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests, | |||
258 | return 0; | 230 | return 0; |
259 | 231 | ||
260 | mutex_lock(&efx->mac_lock); | 232 | mutex_lock(&efx->mac_lock); |
261 | rc = efx->phy_op->run_tests(efx, tests->phy, flags); | 233 | rc = efx->phy_op->run_tests(efx, tests->phy_ext, flags); |
262 | mutex_unlock(&efx->mac_lock); | 234 | mutex_unlock(&efx->mac_lock); |
263 | return rc; | 235 | return rc; |
264 | } | 236 | } |
@@ -684,7 +656,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, | |||
684 | /* Online (i.e. non-disruptive) testing | 656 | /* Online (i.e. non-disruptive) testing |
685 | * This checks interrupt generation, event delivery and PHY presence. */ | 657 | * This checks interrupt generation, event delivery and PHY presence. */ |
686 | 658 | ||
687 | rc = efx_test_mdio(efx, tests); | 659 | rc = efx_test_phy_alive(efx, tests); |
688 | if (rc && !rc_test) | 660 | if (rc && !rc_test) |
689 | rc_test = rc; | 661 | rc_test = rc; |
690 | 662 | ||
diff --git a/drivers/net/sfc/selftest.h b/drivers/net/sfc/selftest.h index f6feee04c96b..643bef72b99d 100644 --- a/drivers/net/sfc/selftest.h +++ b/drivers/net/sfc/selftest.h | |||
@@ -32,7 +32,7 @@ struct efx_loopback_self_tests { | |||
32 | */ | 32 | */ |
33 | struct efx_self_tests { | 33 | struct efx_self_tests { |
34 | /* online tests */ | 34 | /* online tests */ |
35 | int mdio; | 35 | int phy_alive; |
36 | int nvram; | 36 | int nvram; |
37 | int interrupt; | 37 | int interrupt; |
38 | int eventq_dma[EFX_MAX_CHANNELS]; | 38 | int eventq_dma[EFX_MAX_CHANNELS]; |
@@ -40,7 +40,7 @@ struct efx_self_tests { | |||
40 | int eventq_poll[EFX_MAX_CHANNELS]; | 40 | int eventq_poll[EFX_MAX_CHANNELS]; |
41 | /* offline tests */ | 41 | /* offline tests */ |
42 | int registers; | 42 | int registers; |
43 | int phy[EFX_MAX_PHY_TESTS]; | 43 | int phy_ext[EFX_MAX_PHY_TESTS]; |
44 | struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1]; | 44 | struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1]; |
45 | }; | 45 | }; |
46 | 46 | ||
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index 3009c297c135..10db071bd837 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c | |||
@@ -842,6 +842,7 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = { | |||
842 | .get_settings = tenxpress_get_settings, | 842 | .get_settings = tenxpress_get_settings, |
843 | .set_settings = tenxpress_set_settings, | 843 | .set_settings = tenxpress_set_settings, |
844 | .set_npage_adv = sfx7101_set_npage_adv, | 844 | .set_npage_adv = sfx7101_set_npage_adv, |
845 | .test_alive = efx_mdio_test_alive, | ||
845 | .test_name = sfx7101_test_name, | 846 | .test_name = sfx7101_test_name, |
846 | .run_tests = sfx7101_run_tests, | 847 | .run_tests = sfx7101_run_tests, |
847 | }; | 848 | }; |
@@ -856,6 +857,7 @@ struct efx_phy_operations falcon_sft9001_phy_ops = { | |||
856 | .get_settings = tenxpress_get_settings, | 857 | .get_settings = tenxpress_get_settings, |
857 | .set_settings = tenxpress_set_settings, | 858 | .set_settings = tenxpress_set_settings, |
858 | .set_npage_adv = sft9001_set_npage_adv, | 859 | .set_npage_adv = sft9001_set_npage_adv, |
860 | .test_alive = efx_mdio_test_alive, | ||
859 | .test_name = sft9001_test_name, | 861 | .test_name = sft9001_test_name, |
860 | .run_tests = sft9001_run_tests, | 862 | .run_tests = sft9001_run_tests, |
861 | }; | 863 | }; |