sfc: Merge top-level functions for self-tests
Pass in ethtool test flags to determine which tests to run. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
a5692e49cd
commit
2ef3068e6c
@@ -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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
*
|
*
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
struct efx_channel *channel;
|
|
||||||
int rc, rc2 = 0;
|
|
||||||
|
|
||||||
rc = efx_test_mii(efx, tests);
|
|
||||||
if (rc && !rc2)
|
|
||||||
rc2 = rc;
|
|
||||||
|
|
||||||
rc = efx_test_nvram(efx, tests);
|
|
||||||
if (rc && !rc2)
|
|
||||||
rc2 = rc;
|
|
||||||
|
|
||||||
rc = efx_test_interrupts(efx, tests);
|
|
||||||
if (rc && !rc2)
|
|
||||||
rc2 = rc;
|
|
||||||
|
|
||||||
efx_for_each_channel(channel, efx) {
|
|
||||||
rc = efx_test_eventq_irq(channel, tests);
|
|
||||||
if (rc && !rc2)
|
|
||||||
rc2 = rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Offline (i.e. disruptive) testing
|
|
||||||
* This checks MAC and PHY loopback on the specified port. */
|
|
||||||
int efx_offline_test(struct efx_nic *efx,
|
|
||||||
struct efx_self_tests *tests, unsigned int loopback_modes)
|
|
||||||
{
|
{
|
||||||
enum efx_loopback_mode loopback_mode = efx->loopback_mode;
|
enum efx_loopback_mode loopback_mode = efx->loopback_mode;
|
||||||
int phy_mode = efx->phy_mode;
|
int phy_mode = efx->phy_mode;
|
||||||
struct ethtool_cmd ecmd;
|
struct ethtool_cmd ecmd;
|
||||||
int rc, rc2 = 0;
|
struct efx_channel *channel;
|
||||||
|
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);
|
||||||
|
if (rc && !rc_test)
|
||||||
|
rc_test = rc;
|
||||||
|
|
||||||
|
rc = efx_test_nvram(efx, tests);
|
||||||
|
if (rc && !rc_test)
|
||||||
|
rc_test = rc;
|
||||||
|
|
||||||
|
rc = efx_test_interrupts(efx, tests);
|
||||||
|
if (rc && !rc_test)
|
||||||
|
rc_test = rc;
|
||||||
|
|
||||||
|
efx_for_each_channel(channel, efx) {
|
||||||
|
rc = efx_test_eventq_irq(channel, tests);
|
||||||
|
if (rc && !rc_test)
|
||||||
|
rc_test = rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc_test)
|
||||||
|
return rc_test;
|
||||||
|
|
||||||
|
if (!(flags & ETH_TEST_FL_OFFLINE))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Offline (i.e. disruptive) testing
|
||||||
|
* This checks MAC and PHY loopback on the specified port. */
|
||||||
|
|
||||||
/* 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,
|
|||||||
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,
|
|||||||
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 {
|
|||||||
|
|
||||||
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);
|
|
||||||
extern int efx_offline_test(struct efx_nic *efx,
|
|
||||||
struct efx_self_tests *tests,
|
struct efx_self_tests *tests,
|
||||||
unsigned int loopback_modes);
|
unsigned flags);
|
||||||
|
|
||||||
#endif /* EFX_SELFTEST_H */
|
#endif /* EFX_SELFTEST_H */
|
||||||
|
Reference in New Issue
Block a user