Commit 4f16c073 authored by Ben Hutchings's avatar Ben Hutchings Committed by David S. Miller

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: default avatarBen Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7a6b8f6f
...@@ -342,8 +342,8 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, ...@@ -342,8 +342,8 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
unsigned int n = 0, i; unsigned int n = 0, i;
enum efx_loopback_mode mode; enum efx_loopback_mode mode;
efx_fill_test(n++, strings, data, &tests->mdio, efx_fill_test(n++, strings, data, &tests->phy_alive,
"core", 0, "mdio", NULL); "phy", 0, "alive", NULL);
efx_fill_test(n++, strings, data, &tests->nvram, efx_fill_test(n++, strings, data, &tests->nvram,
"core", 0, "nvram", NULL); "core", 0, "nvram", NULL);
efx_fill_test(n++, strings, data, &tests->interrupt, efx_fill_test(n++, strings, data, &tests->interrupt,
...@@ -379,7 +379,7 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, ...@@ -379,7 +379,7 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
if (name == NULL) if (name == NULL)
break; break;
efx_fill_test(n++, strings, data, &tests->phy[i], efx_fill_test(n++, strings, data, &tests->phy_ext[i],
"phy", 0, name, NULL); "phy", 0, name, NULL);
} }
} }
......
...@@ -572,6 +572,27 @@ static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ec ...@@ -572,6 +572,27 @@ static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ec
return 0; return 0;
} }
static int efx_mcdi_phy_test_alive(struct efx_nic *efx)
{
u8 outbuf[MC_CMD_GET_PHY_STATE_OUT_LEN];
size_t outlen;
int rc;
BUILD_BUG_ON(MC_CMD_GET_PHY_STATE_IN_LEN != 0);
rc = efx_mcdi_rpc(efx, MC_CMD_GET_PHY_STATE, NULL, 0,
outbuf, sizeof(outbuf), &outlen);
if (rc)
return rc;
if (outlen < MC_CMD_GET_PHY_STATE_OUT_LEN)
return -EMSGSIZE;
if (MCDI_DWORD(outbuf, GET_PHY_STATE_STATE) != MC_CMD_PHY_STATE_OK)
return -EINVAL;
return 0;
}
struct efx_phy_operations efx_mcdi_phy_ops = { struct efx_phy_operations efx_mcdi_phy_ops = {
.probe = efx_mcdi_phy_probe, .probe = efx_mcdi_phy_probe,
.init = efx_port_dummy_op_int, .init = efx_port_dummy_op_int,
...@@ -581,6 +602,7 @@ struct efx_phy_operations efx_mcdi_phy_ops = { ...@@ -581,6 +602,7 @@ struct efx_phy_operations efx_mcdi_phy_ops = {
.remove = efx_mcdi_phy_remove, .remove = efx_mcdi_phy_remove,
.get_settings = efx_mcdi_phy_get_settings, .get_settings = efx_mcdi_phy_get_settings,
.set_settings = efx_mcdi_phy_set_settings, .set_settings = efx_mcdi_phy_set_settings,
.test_alive = efx_mcdi_phy_test_alive,
.run_tests = NULL, .run_tests = NULL,
.test_name = NULL, .test_name = NULL,
}; };
...@@ -335,3 +335,27 @@ enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx) ...@@ -335,3 +335,27 @@ enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx)
mii_advertise_flowctrl(efx->wanted_fc), mii_advertise_flowctrl(efx->wanted_fc),
efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_LPA)); efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_LPA));
} }
int efx_mdio_test_alive(struct efx_nic *efx)
{
int rc;
int devad = __ffs(efx->mdio.mmds);
u16 physid1, physid2;
mutex_lock(&efx->mac_lock);
physid1 = efx_mdio_read(efx, devad, MDIO_DEVID1);
physid2 = efx_mdio_read(efx, devad, MDIO_DEVID2);
if ((physid1 == 0x0000) || (physid1 == 0xffff) ||
(physid2 == 0x0000) || (physid2 == 0xffff)) {
EFX_ERR(efx, "no MDIO PHY present with ID %d\n",
efx->mdio.prtad);
rc = -EINVAL;
} else {
rc = efx_mdio_check_mmds(efx, efx->mdio.mmds, 0);
}
mutex_unlock(&efx->mac_lock);
return rc;
}
...@@ -106,4 +106,7 @@ efx_mdio_set_flag(struct efx_nic *efx, int devad, int addr, ...@@ -106,4 +106,7 @@ efx_mdio_set_flag(struct efx_nic *efx, int devad, int addr,
mdio_set_flag(&efx->mdio, efx->mdio.prtad, devad, addr, mask, state); mdio_set_flag(&efx->mdio, efx->mdio.prtad, devad, addr, mask, state);
} }
/* Liveness self-test for MDIO PHYs */
extern int efx_mdio_test_alive(struct efx_nic *efx);
#endif /* EFX_MDIO_10G_H */ #endif /* EFX_MDIO_10G_H */
...@@ -516,8 +516,9 @@ struct efx_mac_operations { ...@@ -516,8 +516,9 @@ struct efx_mac_operations {
* @set_settings: Set ethtool settings. Serialised by the mac_lock. * @set_settings: Set ethtool settings. Serialised by the mac_lock.
* @set_npage_adv: Set abilities advertised in (Extended) Next Page * @set_npage_adv: Set abilities advertised in (Extended) Next Page
* (only needed where AN bit is set in mmds) * (only needed where AN bit is set in mmds)
* @test_alive: Test that PHY is 'alive' (online)
* @test_name: Get the name of a PHY-specific test/result * @test_name: Get the name of a PHY-specific test/result
* @run_tests: Run tests and record results as appropriate. * @run_tests: Run tests and record results as appropriate (offline).
* Flags are the ethtool tests flags. * Flags are the ethtool tests flags.
*/ */
struct efx_phy_operations { struct efx_phy_operations {
...@@ -532,6 +533,7 @@ struct efx_phy_operations { ...@@ -532,6 +533,7 @@ struct efx_phy_operations {
int (*set_settings) (struct efx_nic *efx, int (*set_settings) (struct efx_nic *efx,
struct ethtool_cmd *ecmd); struct ethtool_cmd *ecmd);
void (*set_npage_adv) (struct efx_nic *efx, u32); void (*set_npage_adv) (struct efx_nic *efx, u32);
int (*test_alive) (struct efx_nic *efx);
const char *(*test_name) (struct efx_nic *efx, unsigned int index); const char *(*test_name) (struct efx_nic *efx, unsigned int index);
int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags); int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags);
}; };
......
...@@ -445,4 +445,5 @@ struct efx_phy_operations falcon_qt202x_phy_ops = { ...@@ -445,4 +445,5 @@ struct efx_phy_operations falcon_qt202x_phy_ops = {
.remove = qt202x_phy_remove, .remove = qt202x_phy_remove,
.get_settings = qt202x_phy_get_settings, .get_settings = qt202x_phy_get_settings,
.set_settings = efx_mdio_set_settings, .set_settings = efx_mdio_set_settings,
.test_alive = efx_mdio_test_alive,
}; };
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include "workarounds.h" #include "workarounds.h"
#include "spi.h" #include "spi.h"
#include "io.h" #include "io.h"
#include "mdio_10g.h"
/* /*
* Loopback test packet structure * Loopback test packet structure
...@@ -76,42 +75,15 @@ struct efx_loopback_state { ...@@ -76,42 +75,15 @@ struct efx_loopback_state {
* *
**************************************************************************/ **************************************************************************/
static int efx_test_mdio(struct efx_nic *efx, struct efx_self_tests *tests) static int efx_test_phy_alive(struct efx_nic *efx, struct efx_self_tests *tests)
{ {
int rc = 0; int rc = 0;
int devad;
u16 physid1, physid2;
if (efx->mdio.mode_support & MDIO_SUPPORTS_C45) if (efx->phy_op->test_alive) {
devad = __ffs(efx->mdio.mmds); rc = efx->phy_op->test_alive(efx);
else if (efx->mdio.mode_support & MDIO_SUPPORTS_C22) tests->phy_alive = rc ? -1 : 1;
devad = MDIO_DEVAD_NONE;
else
return 0;
mutex_lock(&efx->mac_lock);
tests->mdio = -1;
physid1 = efx_mdio_read(efx, devad, MDIO_DEVID1);
physid2 = efx_mdio_read(efx, devad, MDIO_DEVID2);
if ((physid1 == 0x0000) || (physid1 == 0xffff) ||
(physid2 == 0x0000) || (physid2 == 0xffff)) {
EFX_ERR(efx, "no MDIO PHY present with ID %d\n",
efx->mdio.prtad);
rc = -EINVAL;
goto out;
}
if (EFX_IS10G(efx)) {
rc = efx_mdio_check_mmds(efx, efx->mdio.mmds, 0);
if (rc)
goto out;
} }
out:
mutex_unlock(&efx->mac_lock);
tests->mdio = rc ? -1 : 1;
return rc; return rc;
} }
...@@ -258,7 +230,7 @@ static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests, ...@@ -258,7 +230,7 @@ static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests,
return 0; return 0;
mutex_lock(&efx->mac_lock); mutex_lock(&efx->mac_lock);
rc = efx->phy_op->run_tests(efx, tests->phy, flags); rc = efx->phy_op->run_tests(efx, tests->phy_ext, flags);
mutex_unlock(&efx->mac_lock); mutex_unlock(&efx->mac_lock);
return rc; return rc;
} }
...@@ -684,7 +656,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, ...@@ -684,7 +656,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
/* Online (i.e. non-disruptive) testing /* Online (i.e. non-disruptive) testing
* This checks interrupt generation, event delivery and PHY presence. */ * This checks interrupt generation, event delivery and PHY presence. */
rc = efx_test_mdio(efx, tests); rc = efx_test_phy_alive(efx, tests);
if (rc && !rc_test) if (rc && !rc_test)
rc_test = rc; rc_test = rc;
......
...@@ -32,7 +32,7 @@ struct efx_loopback_self_tests { ...@@ -32,7 +32,7 @@ struct efx_loopback_self_tests {
*/ */
struct efx_self_tests { struct efx_self_tests {
/* online tests */ /* online tests */
int mdio; int phy_alive;
int nvram; int nvram;
int interrupt; int interrupt;
int eventq_dma[EFX_MAX_CHANNELS]; int eventq_dma[EFX_MAX_CHANNELS];
...@@ -40,7 +40,7 @@ struct efx_self_tests { ...@@ -40,7 +40,7 @@ struct efx_self_tests {
int eventq_poll[EFX_MAX_CHANNELS]; int eventq_poll[EFX_MAX_CHANNELS];
/* offline tests */ /* offline tests */
int registers; int registers;
int phy[EFX_MAX_PHY_TESTS]; int phy_ext[EFX_MAX_PHY_TESTS];
struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1]; struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1];
}; };
......
...@@ -842,6 +842,7 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = { ...@@ -842,6 +842,7 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = {
.get_settings = tenxpress_get_settings, .get_settings = tenxpress_get_settings,
.set_settings = tenxpress_set_settings, .set_settings = tenxpress_set_settings,
.set_npage_adv = sfx7101_set_npage_adv, .set_npage_adv = sfx7101_set_npage_adv,
.test_alive = efx_mdio_test_alive,
.test_name = sfx7101_test_name, .test_name = sfx7101_test_name,
.run_tests = sfx7101_run_tests, .run_tests = sfx7101_run_tests,
}; };
...@@ -856,6 +857,7 @@ struct efx_phy_operations falcon_sft9001_phy_ops = { ...@@ -856,6 +857,7 @@ struct efx_phy_operations falcon_sft9001_phy_ops = {
.get_settings = tenxpress_get_settings, .get_settings = tenxpress_get_settings,
.set_settings = tenxpress_set_settings, .set_settings = tenxpress_set_settings,
.set_npage_adv = sft9001_set_npage_adv, .set_npage_adv = sft9001_set_npage_adv,
.test_alive = efx_mdio_test_alive,
.test_name = sft9001_test_name, .test_name = sft9001_test_name,
.run_tests = sft9001_run_tests, .run_tests = sft9001_run_tests,
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment