static void tenxpress_phy_reconfigure(struct efx_nic *efx)
{
	struct tenxpress_phy_data *phy_data = efx->phy_data;
	struct ethtool_cmd ecmd;
	bool phy_mode_change, loop_reset;

	if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) {
		phy_data->phy_mode = efx->phy_mode;
		return;
	}

	tenxpress_low_power(efx);

	phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL &&
			   phy_data->phy_mode != PHY_MODE_NORMAL);
	loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, efx->phy_op->loopbacks) ||
		      LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY));

	if (loop_reset || phy_mode_change) {
		int rc;

		efx->phy_op->get_settings(efx, &ecmd);

		if (loop_reset || phy_mode_change) {
			tenxpress_special_reset(efx);

			/* Reset XAUI if we were in 10G, and are staying
			 * in 10G. If we're moving into and out of 10G
			 * then xaui will be reset anyway */
			if (EFX_IS10G(efx))
				falcon_reset_xaui(efx);
		}

		rc = efx->phy_op->set_settings(efx, &ecmd);
		WARN_ON(rc);
	}

	mdio_clause45_transmit_disable(efx);
	mdio_clause45_phy_reconfigure(efx);
	tenxpress_ext_loopback(efx);

	phy_data->loopback_mode = efx->loopback_mode;
	phy_data->phy_mode = efx->phy_mode;

	if (efx->phy_type == PHY_TYPE_SFX7101) {
		efx->link_speed = 10000;
		efx->link_fd = true;
		efx->link_up = sfx7101_link_ok(efx);
	} else {
		efx->phy_op->get_settings(efx, &ecmd);
		efx->link_speed = ecmd.speed;
		efx->link_fd = ecmd.duplex == DUPLEX_FULL;
		efx->link_up = sft9001_link_ok(efx, &ecmd);
	}
	efx->link_fc = mdio_clause45_get_pause(efx);
}
static void xfp_phy_reconfigure(struct efx_nic *efx)
{
	struct xfp_phy_data *phy_data = efx->phy_data;

	/* Reset the PHY when moving from tx off to tx on */
	if (phy_data->tx_disabled && !efx->tx_disabled)
		xfp_reset_phy(efx);

	mdio_clause45_transmit_disable(efx);
	mdio_clause45_phy_reconfigure(efx);

	phy_data->tx_disabled = efx->tx_disabled;
	efx->link_up = xfp_link_ok(efx);
	efx->link_options = GM_LPA_10000FULL;
}
static void xfp_phy_reconfigure(struct efx_nic *efx)
{
	struct xfp_phy_data *phy_data = efx->phy_data;

	/* Reset the PHY when moving from tx off to tx on */
	if (!(efx->phy_mode & PHY_MODE_TX_DISABLED) &&
	    (phy_data->phy_mode & PHY_MODE_TX_DISABLED))
		xfp_reset_phy(efx);

	mdio_clause45_transmit_disable(efx);
	mdio_clause45_phy_reconfigure(efx);

	phy_data->phy_mode = efx->phy_mode;
	efx->link_up = xfp_link_ok(efx);
	efx->link_speed = 10000;
	efx->link_fd = true;
	efx->link_fc = efx->wanted_fc;
}