aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/sfc/ethtool.c6
-rw-r--r--drivers/net/sfc/mcdi_phy.c22
-rw-r--r--drivers/net/sfc/mdio_10g.c24
-rw-r--r--drivers/net/sfc/mdio_10g.h3
-rw-r--r--drivers/net/sfc/net_driver.h4
-rw-r--r--drivers/net/sfc/qt202x_phy.c1
-rw-r--r--drivers/net/sfc/selftest.c40
-rw-r--r--drivers/net/sfc/selftest.h4
-rw-r--r--drivers/net/sfc/tenxpress.c2
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
575static 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
575struct efx_phy_operations efx_mcdi_phy_ops = { 596struct 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
339int 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 */
110extern 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 */
523struct efx_phy_operations { 524struct 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
79static int efx_test_mdio(struct efx_nic *efx, struct efx_self_tests *tests) 78static 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
112out:
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 */
33struct efx_self_tests { 33struct 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};