sfc: Move PHY software state initialisation from init() into probe()
This prevents efx->link_advertising from being blatted during a reset. The phy_short_reach sysfs node is now destroyed later in the port shutdown process, so check for STATE_RUNNING after acquiring the rtnl_lock (just like in set_phy_flash_cfg). 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
ed4b2019a6
commit
ff3b00a0fc
@@ -304,31 +304,47 @@ static u32 mcdi_to_ethtool_media(u32 media)
|
||||
|
||||
static int efx_mcdi_phy_probe(struct efx_nic *efx)
|
||||
{
|
||||
struct efx_mcdi_phy_cfg *phy_cfg;
|
||||
struct efx_mcdi_phy_cfg *phy_data;
|
||||
u8 outbuf[MC_CMD_GET_LINK_OUT_LEN];
|
||||
u32 caps;
|
||||
int rc;
|
||||
|
||||
/* TODO: Move phy_data initialisation to
|
||||
* phy_op->probe/remove, rather than init/fini */
|
||||
phy_cfg = kzalloc(sizeof(*phy_cfg), GFP_KERNEL);
|
||||
if (phy_cfg == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto fail_alloc;
|
||||
}
|
||||
rc = efx_mcdi_get_phy_cfg(efx, phy_cfg);
|
||||
/* Initialise and populate phy_data */
|
||||
phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
|
||||
if (phy_data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = efx_mcdi_get_phy_cfg(efx, phy_data);
|
||||
if (rc != 0)
|
||||
goto fail;
|
||||
|
||||
efx->phy_type = phy_cfg->type;
|
||||
/* Read initial link advertisement */
|
||||
BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
|
||||
rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
|
||||
outbuf, sizeof(outbuf), NULL);
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
efx->mdio_bus = phy_cfg->channel;
|
||||
efx->mdio.prtad = phy_cfg->port;
|
||||
efx->mdio.mmds = phy_cfg->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22);
|
||||
/* Fill out nic state */
|
||||
efx->phy_data = phy_data;
|
||||
efx->phy_type = phy_data->type;
|
||||
|
||||
efx->mdio_bus = phy_data->channel;
|
||||
efx->mdio.prtad = phy_data->port;
|
||||
efx->mdio.mmds = phy_data->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22);
|
||||
efx->mdio.mode_support = 0;
|
||||
if (phy_cfg->mmd_mask & (1 << MC_CMD_MMD_CLAUSE22))
|
||||
if (phy_data->mmd_mask & (1 << MC_CMD_MMD_CLAUSE22))
|
||||
efx->mdio.mode_support |= MDIO_SUPPORTS_C22;
|
||||
if (phy_cfg->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22))
|
||||
if (phy_data->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22))
|
||||
efx->mdio.mode_support |= MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
|
||||
|
||||
caps = MCDI_DWORD(outbuf, GET_LINK_OUT_CAP);
|
||||
if (caps & (1 << MC_CMD_PHY_CAP_AN_LBN))
|
||||
efx->link_advertising =
|
||||
mcdi_to_ethtool_cap(phy_data->media, caps);
|
||||
else
|
||||
phy_data->forced_cap = caps;
|
||||
|
||||
/* Assert that we can map efx -> mcdi loopback modes */
|
||||
BUILD_BUG_ON(LOOPBACK_NONE != MC_CMD_LOOPBACK_NONE);
|
||||
BUILD_BUG_ON(LOOPBACK_DATA != MC_CMD_LOOPBACK_DATA);
|
||||
@@ -365,46 +381,6 @@ static int efx_mcdi_phy_probe(struct efx_nic *efx)
|
||||
* but by convention we don't */
|
||||
efx->loopback_modes &= ~(1 << LOOPBACK_NONE);
|
||||
|
||||
kfree(phy_cfg);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
kfree(phy_cfg);
|
||||
fail_alloc:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int efx_mcdi_phy_init(struct efx_nic *efx)
|
||||
{
|
||||
struct efx_mcdi_phy_cfg *phy_data;
|
||||
u8 outbuf[MC_CMD_GET_LINK_OUT_LEN];
|
||||
u32 caps;
|
||||
int rc;
|
||||
|
||||
phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
|
||||
if (phy_data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = efx_mcdi_get_phy_cfg(efx, phy_data);
|
||||
if (rc != 0)
|
||||
goto fail;
|
||||
|
||||
efx->phy_data = phy_data;
|
||||
|
||||
BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
|
||||
rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
|
||||
outbuf, sizeof(outbuf), NULL);
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
caps = MCDI_DWORD(outbuf, GET_LINK_OUT_CAP);
|
||||
if (caps & (1 << MC_CMD_PHY_CAP_AN_LBN))
|
||||
efx->link_advertising =
|
||||
mcdi_to_ethtool_cap(phy_data->media, caps);
|
||||
else
|
||||
phy_data->forced_cap = caps;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -504,7 +480,7 @@ static bool efx_mcdi_phy_poll(struct efx_nic *efx)
|
||||
return !efx_link_state_equal(&efx->link_state, &old_state);
|
||||
}
|
||||
|
||||
static void efx_mcdi_phy_fini(struct efx_nic *efx)
|
||||
static void efx_mcdi_phy_remove(struct efx_nic *efx)
|
||||
{
|
||||
struct efx_mcdi_phy_data *phy_data = efx->phy_data;
|
||||
|
||||
@@ -586,10 +562,11 @@ static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ec
|
||||
|
||||
struct efx_phy_operations efx_mcdi_phy_ops = {
|
||||
.probe = efx_mcdi_phy_probe,
|
||||
.init = efx_mcdi_phy_init,
|
||||
.init = efx_port_dummy_op_int,
|
||||
.reconfigure = efx_mcdi_phy_reconfigure,
|
||||
.poll = efx_mcdi_phy_poll,
|
||||
.fini = efx_mcdi_phy_fini,
|
||||
.fini = efx_port_dummy_op_void,
|
||||
.remove = efx_mcdi_phy_remove,
|
||||
.get_settings = efx_mcdi_phy_get_settings,
|
||||
.set_settings = efx_mcdi_phy_set_settings,
|
||||
.run_tests = NULL,
|
||||
|
Reference in New Issue
Block a user