aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2010-02-03 04:30:50 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-03 22:12:44 -0500
commit4f16c0739145476ba37a7fa9eea0c33850efc2ce (patch)
tree3ba72c3d44a3d7ca4814cdb83caf2ca4aa608a85 /drivers/net
parent7a6b8f6f7f74085a1330b0f9765d81bcea8c58b7 (diff)
sfc: Replace PHY MDIO test with an 'alive' test
SFC9000-family boards do not all use MDIO PHYs, so we need a different test for PHY aliveness. Introduce a PHY operation test_alive(). For PHYs attached to Falcon, use a common implementation based on the existing PHY MDIO test. For PHYs managed through MCDI, use the appropriate MCDI request. Change test name in ethtool from 'core mdio' to 'phy alive'. Rename test_results::mdio to phy_alive and test_results::phy to phy_ext. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-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};