*
**************************************************************************/
-static int efx_test_mii(struct efx_nic *efx, struct efx_self_tests *tests)
+static int efx_test_mdio(struct efx_nic *efx, struct efx_self_tests *tests)
{
int rc = 0;
+ int devad = __ffs(efx->mdio.mmds);
u16 physid1, physid2;
- struct mii_if_info *mii = &efx->mii;
- struct net_device *net_dev = efx->net_dev;
if (efx->phy_type == PHY_TYPE_NONE)
return 0;
mutex_lock(&efx->mac_lock);
- tests->mii = -1;
+ tests->mdio = -1;
- physid1 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID1);
- physid2 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID2);
+ 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 MII PHY present with ID %d\n",
- mii->phy_id);
+ EFX_ERR(efx, "no MDIO PHY present with ID %d\n",
+ efx->mdio.prtad);
rc = -EINVAL;
goto out;
}
if (EFX_IS10G(efx)) {
- rc = mdio_clause45_check_mmds(efx, efx->phy_op->mmds, 0);
+ rc = efx_mdio_check_mmds(efx, efx->phy_op->mmds, 0);
if (rc)
goto out;
}
out:
mutex_unlock(&efx->mac_lock);
- tests->mii = rc ? -1 : 1;
+ tests->mdio = rc ? -1 : 1;
return rc;
}
return 0;
}
-static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests)
+static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests,
+ unsigned flags)
{
int rc;
- if (!efx->phy_op->test)
+ if (!efx->phy_op->run_tests)
return 0;
+ EFX_BUG_ON_PARANOID(efx->phy_op->num_tests == 0 ||
+ efx->phy_op->num_tests > EFX_MAX_PHY_TESTS);
+
mutex_lock(&efx->mac_lock);
- rc = efx->phy_op->test(efx);
+ rc = efx->phy_op->run_tests(efx, tests->phy, flags);
mutex_unlock(&efx->mac_lock);
- tests->phy = rc ? -1 : 1;
return rc;
}
kfree_skb(skb);
return -EPIPE;
}
+ efx->net_dev->trans_start = jiffies;
}
return 0;
/**************************************************************************
*
- * Entry points
+ * Entry point
*
*************************************************************************/
-/* Online (i.e. non-disruptive) testing
- * This checks interrupt generation, event delivery and PHY presence. */
-int efx_online_test(struct efx_nic *efx, struct efx_self_tests *tests)
+int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
+ unsigned flags)
{
+ enum efx_loopback_mode loopback_mode = efx->loopback_mode;
+ int phy_mode = efx->phy_mode;
+ enum reset_type reset_method = RESET_TYPE_INVISIBLE;
+ struct ethtool_cmd ecmd;
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);
- if (rc && !rc2)
- rc2 = rc;
+ rc = efx_test_mdio(efx, tests);
+ if (rc && !rc_test)
+ rc_test = rc;
rc = efx_test_nvram(efx, tests);
- if (rc && !rc2)
- rc2 = rc;
+ if (rc && !rc_test)
+ rc_test = rc;
rc = efx_test_interrupts(efx, tests);
- if (rc && !rc2)
- rc2 = rc;
+ if (rc && !rc_test)
+ rc_test = rc;
efx_for_each_channel(channel, efx) {
rc = efx_test_eventq_irq(channel, tests);
- if (rc && !rc2)
- rc2 = rc;
+ if (rc && !rc_test)
+ rc_test = rc;
}
- return rc2;
-}
+ if (rc_test)
+ return rc_test;
-/* 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;
- int phy_mode = efx->phy_mode;
- struct ethtool_cmd ecmd;
- int rc, rc2 = 0;
+ if (!(flags & ETH_TEST_FL_OFFLINE))
+ return efx_test_phy(efx, tests, flags);
+
+ /* 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
* the loopback test, and the watchdog timeout doesn't fire. Also put
mutex_unlock(&efx->mac_lock);
/* free up all consumers of SRAM (including all the queues) */
- efx_reset_down(efx, &ecmd);
+ efx_reset_down(efx, reset_method, &ecmd);
rc = efx_test_chip(efx, tests);
- if (rc && !rc2)
- rc2 = rc;
+ if (rc && !rc_test)
+ rc_test = rc;
/* reset the chip to recover from the register test */
- rc = falcon_reset_hw(efx, RESET_TYPE_ALL);
+ rc_reset = falcon_reset_hw(efx, reset_method);
/* Ensure that the phy is powered and out of loopback
* for the bist and loopback tests */
efx->phy_mode &= ~PHY_MODE_LOW_POWER;
efx->loopback_mode = LOOPBACK_NONE;
- rc = efx_reset_up(efx, &ecmd, rc == 0);
- if (rc) {
+ rc = efx_reset_up(efx, reset_method, &ecmd, rc_reset == 0);
+ if (rc && !rc_reset)
+ rc_reset = rc;
+
+ if (rc_reset) {
EFX_ERR(efx, "Unable to recover from chip test\n");
efx_schedule_reset(efx, RESET_TYPE_DISABLE);
- return rc;
+ return rc_reset;
}
- rc = efx_test_phy(efx, tests);
- if (rc && !rc2)
- rc2 = rc;
+ rc = efx_test_phy(efx, tests, flags);
+ if (rc && !rc_test)
+ rc_test = rc;
- rc = efx_test_loopbacks(efx, tests, loopback_modes);
- if (rc && !rc2)
- rc2 = rc;
+ rc = efx_test_loopbacks(efx, tests, efx->loopback_modes);
+ if (rc && !rc_test)
+ rc_test = rc;
/* restore the PHY to the previous state */
efx->loopback_mode = loopback_mode;
efx->port_inhibited = false;
efx_ethtool_set_settings(efx->net_dev, &ecmd);
- return rc2;
+ return rc_test;
}