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

Commit ff3b00a0 authored by Steve Hodgson's avatar Steve Hodgson Committed by David S. Miller
Browse files

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: default avatarBen Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ed4b2019
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -741,14 +741,14 @@ static int efx_probe_port(struct efx_nic *efx)

	EFX_LOG(efx, "create port\n");

	if (phy_flash_cfg)
		efx->phy_mode = PHY_MODE_SPECIAL;

	/* Connect up MAC/PHY operations table */
	rc = efx->type->probe_port(efx);
	if (rc)
		goto err;

	if (phy_flash_cfg)
		efx->phy_mode = PHY_MODE_SPECIAL;

	/* Sanity check MAC address */
	if (is_valid_ether_addr(efx->mac_address)) {
		memcpy(efx->net_dev->dev_addr, efx->mac_address, ETH_ALEN);
+1 −0
Original line number Diff line number Diff line
@@ -925,6 +925,7 @@ static int falcon_probe_port(struct efx_nic *efx)

static void falcon_remove_port(struct efx_nic *efx)
{
	efx->phy_op->remove(efx);
	efx_nic_free_buffer(efx, &efx->stats_buffer);
}

+35 −58
Original line number Diff line number Diff line
@@ -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;

	/* Fill out nic state */
	efx->phy_data = phy_data;
	efx->phy_type = phy_data->type;

	efx->mdio_bus = phy_cfg->channel;
	efx->mdio.prtad = phy_cfg->port;
	efx->mdio.mmds = phy_cfg->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22);
	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,
+1 −0
Original line number Diff line number Diff line
@@ -524,6 +524,7 @@ struct efx_phy_operations {
	int (*probe) (struct efx_nic *efx);
	int (*init) (struct efx_nic *efx);
	void (*fini) (struct efx_nic *efx);
	void (*remove) (struct efx_nic *efx);
	int (*reconfigure) (struct efx_nic *efx);
	bool (*poll) (struct efx_nic *efx);
	void (*get_settings) (struct efx_nic *efx,
+11 −9
Original line number Diff line number Diff line
@@ -137,6 +137,14 @@ static int qt202x_reset_phy(struct efx_nic *efx)

static int qt202x_phy_probe(struct efx_nic *efx)
{
	struct qt202x_phy_data *phy_data;

	phy_data = kzalloc(sizeof(struct qt202x_phy_data), GFP_KERNEL);
	if (!phy_data)
		return -ENOMEM;
	efx->phy_data = phy_data;
	phy_data->phy_mode = efx->phy_mode;

	efx->mdio.mmds = QT202X_REQUIRED_DEVS;
	efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
	efx->loopback_modes = QT202X_LOOPBACKS | FALCON_XMAC_LOOPBACKS;
@@ -145,7 +153,6 @@ static int qt202x_phy_probe(struct efx_nic *efx)

static int qt202x_phy_init(struct efx_nic *efx)
{
	struct qt202x_phy_data *phy_data;
	u32 devid;
	int rc;

@@ -155,17 +162,11 @@ static int qt202x_phy_init(struct efx_nic *efx)
		return rc;
	}

	phy_data = kzalloc(sizeof(struct qt202x_phy_data), GFP_KERNEL);
	if (!phy_data)
		return -ENOMEM;
	efx->phy_data = phy_data;

	devid = efx_mdio_read_id(efx, MDIO_MMD_PHYXS);
	EFX_INFO(efx, "PHY ID reg %x (OUI %06x model %02x revision %x)\n",
		 devid, efx_mdio_id_oui(devid), efx_mdio_id_model(devid),
		 efx_mdio_id_rev(devid));

	phy_data->phy_mode = efx->phy_mode;
	return 0;
}

@@ -224,7 +225,7 @@ static void qt202x_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecm
	mdio45_ethtool_gset(&efx->mdio, ecmd);
}

static void qt202x_phy_fini(struct efx_nic *efx)
static void qt202x_phy_remove(struct efx_nic *efx)
{
	/* Free the context block */
	kfree(efx->phy_data);
@@ -236,7 +237,8 @@ struct efx_phy_operations falcon_qt202x_phy_ops = {
	.init		 = qt202x_phy_init,
	.reconfigure	 = qt202x_phy_reconfigure,
	.poll	     	 = qt202x_phy_poll,
	.fini	  	 = qt202x_phy_fini,
	.fini		 = efx_port_dummy_op_void,
	.remove	  	 = qt202x_phy_remove,
	.get_settings	 = qt202x_phy_get_settings,
	.set_settings	 = efx_mdio_set_settings,
};
Loading