unsigned int n = 0, i;
        enum efx_loopback_mode mode;
 
-       efx_fill_test(n++, strings, data, &tests->mdio,
-                     "core", 0, "mdio", NULL);
+       efx_fill_test(n++, strings, data, &tests->phy_alive,
+                     "phy", 0, "alive", NULL);
        efx_fill_test(n++, strings, data, &tests->nvram,
                      "core", 0, "nvram", NULL);
        efx_fill_test(n++, strings, data, &tests->interrupt,
                        if (name == NULL)
                                break;
 
-                       efx_fill_test(n++, strings, data, &tests->phy[i],
+                       efx_fill_test(n++, strings, data, &tests->phy_ext[i],
                                      "phy", 0, name, NULL);
                }
        }
 
        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 = {
        .probe          = efx_mcdi_phy_probe,
        .init           = efx_port_dummy_op_int,
        .remove         = efx_mcdi_phy_remove,
        .get_settings   = efx_mcdi_phy_get_settings,
        .set_settings   = efx_mcdi_phy_set_settings,
+       .test_alive     = efx_mcdi_phy_test_alive,
        .run_tests      = NULL,
        .test_name      = NULL,
 };
 
                mii_advertise_flowctrl(efx->wanted_fc),
                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;
+}
 
        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 */
 
  * @set_settings: Set ethtool settings. Serialised by the mac_lock.
  * @set_npage_adv: Set abilities advertised in (Extended) Next Page
  *     (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
- * @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.
  */
 struct efx_phy_operations {
        int (*set_settings) (struct efx_nic *efx,
                             struct ethtool_cmd *ecmd);
        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);
        int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags);
 };
 
        .remove          = qt202x_phy_remove,
        .get_settings    = qt202x_phy_get_settings,
        .set_settings    = efx_mdio_set_settings,
+       .test_alive      = efx_mdio_test_alive,
 };
 
 #include "workarounds.h"
 #include "spi.h"
 #include "io.h"
-#include "mdio_10g.h"
 
 /*
  * Loopback test packet structure
  *
  **************************************************************************/
 
-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 devad;
-       u16 physid1, physid2;
-
-       if (efx->mdio.mode_support & MDIO_SUPPORTS_C45)
-               devad = __ffs(efx->mdio.mmds);
-       else if (efx->mdio.mode_support & MDIO_SUPPORTS_C22)
-               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->phy_op->test_alive) {
+               rc = efx->phy_op->test_alive(efx);
+               tests->phy_alive = rc ? -1 : 1;
        }
 
-       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 0;
 
        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);
        return rc;
 }
        /* Online (i.e. non-disruptive) testing
         * 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)
                rc_test = rc;
 
 
  */
 struct efx_self_tests {
        /* online tests */
-       int mdio;
+       int phy_alive;
        int nvram;
        int interrupt;
        int eventq_dma[EFX_MAX_CHANNELS];
        int eventq_poll[EFX_MAX_CHANNELS];
        /* offline tests */
        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];
 };
 
 
        .get_settings     = tenxpress_get_settings,
        .set_settings     = tenxpress_set_settings,
        .set_npage_adv    = sfx7101_set_npage_adv,
+       .test_alive       = efx_mdio_test_alive,
        .test_name        = sfx7101_test_name,
        .run_tests        = sfx7101_run_tests,
 };
        .get_settings     = tenxpress_get_settings,
        .set_settings     = tenxpress_set_settings,
        .set_npage_adv    = sft9001_set_npage_adv,
+       .test_alive       = efx_mdio_test_alive,
        .test_name        = sft9001_test_name,
        .run_tests        = sft9001_run_tests,
 };