Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+3 −3
Original line number Original line Diff line number Diff line
@@ -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,
			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);
		}
		}
	}
	}
+22 −0
Original line number Original line Diff line number Diff line
@@ -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 = {
	.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,
};
};
+24 −0
Original line number Original line Diff line number Diff line
@@ -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;
}
+3 −0
Original line number Original line Diff line number Diff line
@@ -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 */
+3 −1
Original line number Original line Diff line number Diff line
@@ -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 {
	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);
};
};
Loading