Commit 2ef3068e authored by Ben Hutchings's avatar Ben Hutchings Committed by David S. Miller

sfc: Merge top-level functions for self-tests

Pass in ethtool test flags to determine which tests to run.
Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a5692e49
...@@ -487,7 +487,7 @@ static void efx_ethtool_self_test(struct net_device *net_dev, ...@@ -487,7 +487,7 @@ static void efx_ethtool_self_test(struct net_device *net_dev,
{ {
struct efx_nic *efx = netdev_priv(net_dev); struct efx_nic *efx = netdev_priv(net_dev);
struct efx_self_tests efx_tests; struct efx_self_tests efx_tests;
int offline, already_up; int already_up;
int rc; int rc;
ASSERT_RTNL(); ASSERT_RTNL();
...@@ -507,24 +507,15 @@ static void efx_ethtool_self_test(struct net_device *net_dev, ...@@ -507,24 +507,15 @@ static void efx_ethtool_self_test(struct net_device *net_dev,
} }
memset(&efx_tests, 0, sizeof(efx_tests)); memset(&efx_tests, 0, sizeof(efx_tests));
offline = (test->flags & ETH_TEST_FL_OFFLINE);
/* Perform online self tests first */ rc = efx_selftest(efx, &efx_tests, test->flags);
rc = efx_online_test(efx, &efx_tests);
if (rc)
goto out;
/* Perform offline tests only if online tests passed */
if (offline)
rc = efx_offline_test(efx, &efx_tests,
efx->loopback_modes);
out:
if (!already_up) if (!already_up)
dev_close(efx->net_dev); dev_close(efx->net_dev);
EFX_LOG(efx, "%s all %sline self-tests\n", EFX_LOG(efx, "%s %sline self-tests\n",
rc == 0 ? "passed" : "failed", offline ? "off" : "on"); rc == 0 ? "passed" : "failed",
(test->flags & ETH_TEST_FL_OFFLINE) ? "off" : "on");
fail2: fail2:
fail1: fail1:
......
...@@ -653,47 +653,48 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests, ...@@ -653,47 +653,48 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests,
/************************************************************************** /**************************************************************************
* *
* Entry points * Entry point
* *
*************************************************************************/ *************************************************************************/
/* Online (i.e. non-disruptive) testing int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
* This checks interrupt generation, event delivery and PHY presence. */ unsigned flags)
int efx_online_test(struct efx_nic *efx, struct efx_self_tests *tests)
{ {
enum efx_loopback_mode loopback_mode = efx->loopback_mode;
int phy_mode = efx->phy_mode;
struct ethtool_cmd ecmd;
struct efx_channel *channel; struct efx_channel *channel;
int rc, rc2 = 0; int rc_test = 0, rc_reset = 0, rc;
/* Online (i.e. non-disruptive) testing
* This checks interrupt generation, event delivery and PHY presence. */
rc = efx_test_mii(efx, tests); rc = efx_test_mii(efx, tests);
if (rc && !rc2) if (rc && !rc_test)
rc2 = rc; rc_test = rc;
rc = efx_test_nvram(efx, tests); rc = efx_test_nvram(efx, tests);
if (rc && !rc2) if (rc && !rc_test)
rc2 = rc; rc_test = rc;
rc = efx_test_interrupts(efx, tests); rc = efx_test_interrupts(efx, tests);
if (rc && !rc2) if (rc && !rc_test)
rc2 = rc; rc_test = rc;
efx_for_each_channel(channel, efx) { efx_for_each_channel(channel, efx) {
rc = efx_test_eventq_irq(channel, tests); rc = efx_test_eventq_irq(channel, tests);
if (rc && !rc2) if (rc && !rc_test)
rc2 = rc; rc_test = rc;
} }
return rc2; if (rc_test)
} return rc_test;
/* Offline (i.e. disruptive) testing if (!(flags & ETH_TEST_FL_OFFLINE))
* This checks MAC and PHY loopback on the specified port. */ return 0;
int efx_offline_test(struct efx_nic *efx,
struct efx_self_tests *tests, unsigned int loopback_modes) /* Offline (i.e. disruptive) testing
{ * This checks MAC and PHY loopback on the specified port. */
enum efx_loopback_mode loopback_mode = efx->loopback_mode;
int phy_mode = efx->phy_mode;
struct ethtool_cmd ecmd;
int rc, rc2 = 0;
/* force the carrier state off so the kernel doesn't transmit during /* force the carrier state off so the kernel doesn't transmit during
* the loopback test, and the watchdog timeout doesn't fire. Also put * the loopback test, and the watchdog timeout doesn't fire. Also put
...@@ -717,31 +718,34 @@ int efx_offline_test(struct efx_nic *efx, ...@@ -717,31 +718,34 @@ int efx_offline_test(struct efx_nic *efx,
efx_reset_down(efx, &ecmd); efx_reset_down(efx, &ecmd);
rc = efx_test_chip(efx, tests); rc = efx_test_chip(efx, tests);
if (rc && !rc2) if (rc && !rc_test)
rc2 = rc; rc_test = rc;
/* reset the chip to recover from the register test */ /* reset the chip to recover from the register test */
rc = falcon_reset_hw(efx, RESET_TYPE_ALL); rc_reset = falcon_reset_hw(efx, RESET_TYPE_ALL);
/* Ensure that the phy is powered and out of loopback /* Ensure that the phy is powered and out of loopback
* for the bist and loopback tests */ * for the bist and loopback tests */
efx->phy_mode &= ~PHY_MODE_LOW_POWER; efx->phy_mode &= ~PHY_MODE_LOW_POWER;
efx->loopback_mode = LOOPBACK_NONE; efx->loopback_mode = LOOPBACK_NONE;
rc = efx_reset_up(efx, &ecmd, rc == 0); rc = efx_reset_up(efx, &ecmd, rc_reset == 0);
if (rc) { if (rc && !rc_reset)
rc_reset = rc;
if (rc_reset) {
EFX_ERR(efx, "Unable to recover from chip test\n"); EFX_ERR(efx, "Unable to recover from chip test\n");
efx_schedule_reset(efx, RESET_TYPE_DISABLE); efx_schedule_reset(efx, RESET_TYPE_DISABLE);
return rc; return rc_reset;
} }
rc = efx_test_phy(efx, tests); rc = efx_test_phy(efx, tests);
if (rc && !rc2) if (rc && !rc_test)
rc2 = rc; rc_test = rc;
rc = efx_test_loopbacks(efx, tests, loopback_modes); rc = efx_test_loopbacks(efx, tests, efx->loopback_modes);
if (rc && !rc2) if (rc && !rc_test)
rc2 = rc; rc_test = rc;
/* restore the PHY to the previous state */ /* restore the PHY to the previous state */
efx->loopback_mode = loopback_mode; efx->loopback_mode = loopback_mode;
...@@ -749,6 +753,6 @@ int efx_offline_test(struct efx_nic *efx, ...@@ -749,6 +753,6 @@ int efx_offline_test(struct efx_nic *efx,
efx->port_inhibited = false; efx->port_inhibited = false;
efx_ethtool_set_settings(efx->net_dev, &ecmd); efx_ethtool_set_settings(efx->net_dev, &ecmd);
return rc2; return rc_test;
} }
...@@ -44,10 +44,8 @@ struct efx_self_tests { ...@@ -44,10 +44,8 @@ struct efx_self_tests {
extern void efx_loopback_rx_packet(struct efx_nic *efx, extern void efx_loopback_rx_packet(struct efx_nic *efx,
const char *buf_ptr, int pkt_len); const char *buf_ptr, int pkt_len);
extern int efx_online_test(struct efx_nic *efx, extern int efx_selftest(struct efx_nic *efx,
struct efx_self_tests *tests); struct efx_self_tests *tests,
extern int efx_offline_test(struct efx_nic *efx, unsigned flags);
struct efx_self_tests *tests,
unsigned int loopback_modes);
#endif /* EFX_SELFTEST_H */ #endif /* EFX_SELFTEST_H */
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