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

Commit 85f9feb6 authored by Lendacky, Thomas's avatar Lendacky, Thomas Committed by David S. Miller
Browse files

amd-xgbe: Convert to using the new link mode settings



Convert from using the old u32 supported, advertising, etc. link settings
to the new link mode settings that support bit positions / settings
greater than 32 bits.

Signed-off-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 606c07f3
Loading
Loading
Loading
Loading
+32 −24
Original line number Diff line number Diff line
@@ -267,6 +267,7 @@ static int xgbe_set_pauseparam(struct net_device *netdev,
			       struct ethtool_pauseparam *pause)
{
	struct xgbe_prv_data *pdata = netdev_priv(netdev);
	struct ethtool_link_ksettings *lks = &pdata->phy.lks;
	int ret = 0;

	if (pause->autoneg && (pdata->phy.autoneg != AUTONEG_ENABLE)) {
@@ -279,16 +280,21 @@ static int xgbe_set_pauseparam(struct net_device *netdev,
	pdata->phy.tx_pause = pause->tx_pause;
	pdata->phy.rx_pause = pause->rx_pause;

	pdata->phy.advertising &= ~ADVERTISED_Pause;
	pdata->phy.advertising &= ~ADVERTISED_Asym_Pause;
	XGBE_CLR_ADV(lks, Pause);
	XGBE_CLR_ADV(lks, Asym_Pause);

	if (pause->rx_pause) {
		pdata->phy.advertising |= ADVERTISED_Pause;
		pdata->phy.advertising |= ADVERTISED_Asym_Pause;
		XGBE_SET_ADV(lks, Pause);
		XGBE_SET_ADV(lks, Asym_Pause);
	}

	if (pause->tx_pause)
		pdata->phy.advertising ^= ADVERTISED_Asym_Pause;
	if (pause->tx_pause) {
		/* Equivalent to XOR of Asym_Pause */
		if (XGBE_ADV(lks, Asym_Pause))
			XGBE_CLR_ADV(lks, Asym_Pause);
		else
			XGBE_SET_ADV(lks, Asym_Pause);
	}

	if (netif_running(netdev))
		ret = pdata->phy_if.phy_config_aneg(pdata);
@@ -300,22 +306,20 @@ static int xgbe_get_link_ksettings(struct net_device *netdev,
				   struct ethtool_link_ksettings *cmd)
{
	struct xgbe_prv_data *pdata = netdev_priv(netdev);
	struct ethtool_link_ksettings *lks = &pdata->phy.lks;

	cmd->base.phy_address = pdata->phy.address;

	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
						pdata->phy.supported);
	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
						pdata->phy.advertising);
	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising,
						pdata->phy.lp_advertising);

	cmd->base.autoneg = pdata->phy.autoneg;
	cmd->base.speed = pdata->phy.speed;
	cmd->base.duplex = pdata->phy.duplex;

	cmd->base.port = PORT_NONE;

	XGBE_LM_COPY(cmd, supported, lks, supported);
	XGBE_LM_COPY(cmd, advertising, lks, advertising);
	XGBE_LM_COPY(cmd, lp_advertising, lks, lp_advertising);

	return 0;
}

@@ -323,7 +327,8 @@ static int xgbe_set_link_ksettings(struct net_device *netdev,
				   const struct ethtool_link_ksettings *cmd)
{
	struct xgbe_prv_data *pdata = netdev_priv(netdev);
	u32 advertising;
	struct ethtool_link_ksettings *lks = &pdata->phy.lks;
	__ETHTOOL_DECLARE_LINK_MODE_MASK(advertising);
	u32 speed;
	int ret;

@@ -355,15 +360,17 @@ static int xgbe_set_link_ksettings(struct net_device *netdev,
		}
	}

	ethtool_convert_link_mode_to_legacy_u32(&advertising,
						cmd->link_modes.advertising);

	netif_dbg(pdata, link, netdev,
		  "requested advertisement %#x, phy supported %#x\n",
		  advertising, pdata->phy.supported);
		  "requested advertisement 0x%*pb, phy supported 0x%*pb\n",
		  __ETHTOOL_LINK_MODE_MASK_NBITS, cmd->link_modes.advertising,
		  __ETHTOOL_LINK_MODE_MASK_NBITS, lks->link_modes.supported);

	bitmap_and(advertising,
		   cmd->link_modes.advertising, lks->link_modes.supported,
		   __ETHTOOL_LINK_MODE_MASK_NBITS);

	advertising &= pdata->phy.supported;
	if ((cmd->base.autoneg == AUTONEG_ENABLE) && !advertising) {
	if ((cmd->base.autoneg == AUTONEG_ENABLE) &&
	    bitmap_empty(advertising, __ETHTOOL_LINK_MODE_MASK_NBITS)) {
		netdev_err(netdev,
			   "unsupported requested advertisement\n");
		return -EINVAL;
@@ -373,12 +380,13 @@ static int xgbe_set_link_ksettings(struct net_device *netdev,
	pdata->phy.autoneg = cmd->base.autoneg;
	pdata->phy.speed = speed;
	pdata->phy.duplex = cmd->base.duplex;
	pdata->phy.advertising = advertising;
	bitmap_copy(lks->link_modes.advertising, advertising,
		    __ETHTOOL_LINK_MODE_MASK_NBITS);

	if (cmd->base.autoneg == AUTONEG_ENABLE)
		pdata->phy.advertising |= ADVERTISED_Autoneg;
		XGBE_SET_ADV(lks, Autoneg);
	else
		pdata->phy.advertising &= ~ADVERTISED_Autoneg;
		XGBE_CLR_ADV(lks, Autoneg);

	if (netif_running(netdev))
		ret = pdata->phy_if.phy_config_aneg(pdata);
+47 −30
Original line number Diff line number Diff line
@@ -615,12 +615,14 @@ static enum xgbe_an xgbe_an73_page_received(struct xgbe_prv_data *pdata)

static enum xgbe_an xgbe_an73_incompat_link(struct xgbe_prv_data *pdata)
{
	struct ethtool_link_ksettings *lks = &pdata->phy.lks;

	/* Be sure we aren't looping trying to negotiate */
	if (xgbe_in_kr_mode(pdata)) {
		pdata->kr_state = XGBE_RX_ERROR;

		if (!(pdata->phy.advertising & ADVERTISED_1000baseKX_Full) &&
		    !(pdata->phy.advertising & ADVERTISED_2500baseX_Full))
		if (!XGBE_ADV(lks, 1000baseKX_Full) &&
		    !XGBE_ADV(lks, 2500baseX_Full))
			return XGBE_AN_NO_LINK;

		if (pdata->kx_state != XGBE_RX_BPA)
@@ -628,7 +630,7 @@ static enum xgbe_an xgbe_an73_incompat_link(struct xgbe_prv_data *pdata)
	} else {
		pdata->kx_state = XGBE_RX_ERROR;

		if (!(pdata->phy.advertising & ADVERTISED_10000baseKR_Full))
		if (!XGBE_ADV(lks, 10000baseKR_Full))
			return XGBE_AN_NO_LINK;

		if (pdata->kr_state != XGBE_RX_BPA)
@@ -944,18 +946,19 @@ static void xgbe_an_state_machine(struct work_struct *work)

static void xgbe_an37_init(struct xgbe_prv_data *pdata)
{
	unsigned int advertising, reg;
	struct ethtool_link_ksettings lks;
	unsigned int reg;

	advertising = pdata->phy_if.phy_impl.an_advertising(pdata);
	pdata->phy_if.phy_impl.an_advertising(pdata, &lks);

	/* Set up Advertisement register */
	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE);
	if (advertising & ADVERTISED_Pause)
	if (XGBE_ADV(&lks, Pause))
		reg |= 0x100;
	else
		reg &= ~0x100;

	if (advertising & ADVERTISED_Asym_Pause)
	if (XGBE_ADV(&lks, Asym_Pause))
		reg |= 0x80;
	else
		reg &= ~0x80;
@@ -992,13 +995,14 @@ static void xgbe_an37_init(struct xgbe_prv_data *pdata)

static void xgbe_an73_init(struct xgbe_prv_data *pdata)
{
	unsigned int advertising, reg;
	struct ethtool_link_ksettings lks;
	unsigned int reg;

	advertising = pdata->phy_if.phy_impl.an_advertising(pdata);
	pdata->phy_if.phy_impl.an_advertising(pdata, &lks);

	/* Set up Advertisement register 3 first */
	reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
	if (advertising & ADVERTISED_10000baseR_FEC)
	if (XGBE_ADV(&lks, 10000baseR_FEC))
		reg |= 0xc000;
	else
		reg &= ~0xc000;
@@ -1007,13 +1011,13 @@ static void xgbe_an73_init(struct xgbe_prv_data *pdata)

	/* Set up Advertisement register 2 next */
	reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
	if (advertising & ADVERTISED_10000baseKR_Full)
	if (XGBE_ADV(&lks, 10000baseKR_Full))
		reg |= 0x80;
	else
		reg &= ~0x80;

	if ((advertising & ADVERTISED_1000baseKX_Full) ||
	    (advertising & ADVERTISED_2500baseX_Full))
	if (XGBE_ADV(&lks, 1000baseKX_Full) ||
	    XGBE_ADV(&lks, 2500baseX_Full))
		reg |= 0x20;
	else
		reg &= ~0x20;
@@ -1022,12 +1026,12 @@ static void xgbe_an73_init(struct xgbe_prv_data *pdata)

	/* Set up Advertisement register 1 last */
	reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
	if (advertising & ADVERTISED_Pause)
	if (XGBE_ADV(&lks, Pause))
		reg |= 0x400;
	else
		reg &= ~0x400;

	if (advertising & ADVERTISED_Asym_Pause)
	if (XGBE_ADV(&lks, Asym_Pause))
		reg |= 0x800;
	else
		reg &= ~0x800;
@@ -1283,9 +1287,10 @@ static enum xgbe_mode xgbe_phy_status_aneg(struct xgbe_prv_data *pdata)

static void xgbe_phy_status_result(struct xgbe_prv_data *pdata)
{
	struct ethtool_link_ksettings *lks = &pdata->phy.lks;
	enum xgbe_mode mode;

	pdata->phy.lp_advertising = 0;
	XGBE_ZERO_LP_ADV(lks);

	if ((pdata->phy.autoneg != AUTONEG_ENABLE) || pdata->parallel_detect)
		mode = xgbe_cur_mode(pdata);
@@ -1515,17 +1520,21 @@ static void xgbe_dump_phy_registers(struct xgbe_prv_data *pdata)

static int xgbe_phy_best_advertised_speed(struct xgbe_prv_data *pdata)
{
	if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full)
	struct ethtool_link_ksettings *lks = &pdata->phy.lks;

	if (XGBE_ADV(lks, 10000baseKR_Full))
		return SPEED_10000;
	else if (pdata->phy.advertising & ADVERTISED_10000baseT_Full)
	else if (XGBE_ADV(lks, 10000baseT_Full))
		return SPEED_10000;
	else if (pdata->phy.advertising & ADVERTISED_2500baseX_Full)
	else if (XGBE_ADV(lks, 2500baseX_Full))
		return SPEED_2500;
	else if (pdata->phy.advertising & ADVERTISED_1000baseKX_Full)
	else if (XGBE_ADV(lks, 2500baseT_Full))
		return SPEED_2500;
	else if (XGBE_ADV(lks, 1000baseKX_Full))
		return SPEED_1000;
	else if (pdata->phy.advertising & ADVERTISED_1000baseT_Full)
	else if (XGBE_ADV(lks, 1000baseT_Full))
		return SPEED_1000;
	else if (pdata->phy.advertising & ADVERTISED_100baseT_Full)
	else if (XGBE_ADV(lks, 100baseT_Full))
		return SPEED_100;

	return SPEED_UNKNOWN;
@@ -1538,6 +1547,7 @@ static void xgbe_phy_exit(struct xgbe_prv_data *pdata)

static int xgbe_phy_init(struct xgbe_prv_data *pdata)
{
	struct ethtool_link_ksettings *lks = &pdata->phy.lks;
	int ret;

	mutex_init(&pdata->an_mutex);
@@ -1555,11 +1565,13 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
	ret = pdata->phy_if.phy_impl.init(pdata);
	if (ret)
		return ret;
	pdata->phy.advertising = pdata->phy.supported;

	/* Copy supported link modes to advertising link modes */
	XGBE_LM_COPY(lks, advertising, lks, supported);

	pdata->phy.address = 0;

	if (pdata->phy.advertising & ADVERTISED_Autoneg) {
	if (XGBE_ADV(lks, Autoneg)) {
		pdata->phy.autoneg = AUTONEG_ENABLE;
		pdata->phy.speed = SPEED_UNKNOWN;
		pdata->phy.duplex = DUPLEX_UNKNOWN;
@@ -1576,16 +1588,21 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
	pdata->phy.rx_pause = pdata->rx_pause;

	/* Fix up Flow Control advertising */
	pdata->phy.advertising &= ~ADVERTISED_Pause;
	pdata->phy.advertising &= ~ADVERTISED_Asym_Pause;
	XGBE_CLR_ADV(lks, Pause);
	XGBE_CLR_ADV(lks, Asym_Pause);

	if (pdata->rx_pause) {
		pdata->phy.advertising |= ADVERTISED_Pause;
		pdata->phy.advertising |= ADVERTISED_Asym_Pause;
		XGBE_SET_ADV(lks, Pause);
		XGBE_SET_ADV(lks, Asym_Pause);
	}

	if (pdata->tx_pause)
		pdata->phy.advertising ^= ADVERTISED_Asym_Pause;
	if (pdata->tx_pause) {
		/* Equivalent to XOR of Asym_Pause */
		if (XGBE_ADV(lks, Asym_Pause))
			XGBE_CLR_ADV(lks, Asym_Pause);
		else
			XGBE_SET_ADV(lks, Asym_Pause);
	}

	if (netif_msg_drv(pdata))
		xgbe_dump_phy_registers(pdata);
+31 −23
Original line number Diff line number Diff line
@@ -231,20 +231,21 @@ static void xgbe_phy_kr_training_post(struct xgbe_prv_data *pdata)

static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)
{
	struct ethtool_link_ksettings *lks = &pdata->phy.lks;
	struct xgbe_phy_data *phy_data = pdata->phy_data;
	enum xgbe_mode mode;
	unsigned int ad_reg, lp_reg;

	pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
	pdata->phy.lp_advertising |= ADVERTISED_Backplane;
	XGBE_SET_LP_ADV(lks, Autoneg);
	XGBE_SET_LP_ADV(lks, Backplane);

	/* Compare Advertisement and Link Partner register 1 */
	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
	if (lp_reg & 0x400)
		pdata->phy.lp_advertising |= ADVERTISED_Pause;
		XGBE_SET_LP_ADV(lks, Pause);
	if (lp_reg & 0x800)
		pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
		XGBE_SET_LP_ADV(lks, Asym_Pause);

	if (pdata->phy.pause_autoneg) {
		/* Set flow control based on auto-negotiation result */
@@ -266,12 +267,12 @@ static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)
	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
	if (lp_reg & 0x80)
		pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
		XGBE_SET_LP_ADV(lks, 10000baseKR_Full);
	if (lp_reg & 0x20) {
		if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
			pdata->phy.lp_advertising |= ADVERTISED_2500baseX_Full;
			XGBE_SET_LP_ADV(lks, 2500baseX_Full);
		else
			pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
			XGBE_SET_LP_ADV(lks, 1000baseKX_Full);
	}

	ad_reg &= lp_reg;
@@ -290,14 +291,17 @@ static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)
	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
	if (lp_reg & 0xc000)
		pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
		XGBE_SET_LP_ADV(lks, 10000baseR_FEC);

	return mode;
}

static unsigned int xgbe_phy_an_advertising(struct xgbe_prv_data *pdata)
static void xgbe_phy_an_advertising(struct xgbe_prv_data *pdata,
				    struct ethtool_link_ksettings *dlks)
{
	return pdata->phy.advertising;
	struct ethtool_link_ksettings *slks = &pdata->phy.lks;

	XGBE_LM_COPY(dlks, advertising, slks, advertising);
}

static int xgbe_phy_an_config(struct xgbe_prv_data *pdata)
@@ -565,11 +569,10 @@ static void xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
}

static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata,
				enum xgbe_mode mode, u32 advert)
				enum xgbe_mode mode, bool advert)
{
	if (pdata->phy.autoneg == AUTONEG_ENABLE) {
		if (pdata->phy.advertising & advert)
			return true;
		return advert;
	} else {
		enum xgbe_mode cur_mode;

@@ -583,16 +586,18 @@ static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata,

static bool xgbe_phy_use_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
{
	struct ethtool_link_ksettings *lks = &pdata->phy.lks;

	switch (mode) {
	case XGBE_MODE_KX_1000:
		return xgbe_phy_check_mode(pdata, mode,
					   ADVERTISED_1000baseKX_Full);
					   XGBE_ADV(lks, 1000baseKX_Full));
	case XGBE_MODE_KX_2500:
		return xgbe_phy_check_mode(pdata, mode,
					   ADVERTISED_2500baseX_Full);
					   XGBE_ADV(lks, 2500baseX_Full));
	case XGBE_MODE_KR:
		return xgbe_phy_check_mode(pdata, mode,
					   ADVERTISED_10000baseKR_Full);
					   XGBE_ADV(lks, 10000baseKR_Full));
	default:
		return false;
	}
@@ -672,6 +677,7 @@ static void xgbe_phy_exit(struct xgbe_prv_data *pdata)

static int xgbe_phy_init(struct xgbe_prv_data *pdata)
{
	struct ethtool_link_ksettings *lks = &pdata->phy.lks;
	struct xgbe_phy_data *phy_data;
	int ret;

@@ -790,21 +796,23 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
	}

	/* Initialize supported features */
	pdata->phy.supported = SUPPORTED_Autoneg;
	pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
	pdata->phy.supported |= SUPPORTED_Backplane;
	pdata->phy.supported |= SUPPORTED_10000baseKR_Full;
	XGBE_ZERO_SUP(lks);
	XGBE_SET_SUP(lks, Autoneg);
	XGBE_SET_SUP(lks, Pause);
	XGBE_SET_SUP(lks, Asym_Pause);
	XGBE_SET_SUP(lks, Backplane);
	XGBE_SET_SUP(lks, 10000baseKR_Full);
	switch (phy_data->speed_set) {
	case XGBE_SPEEDSET_1000_10000:
		pdata->phy.supported |= SUPPORTED_1000baseKX_Full;
		XGBE_SET_SUP(lks, 1000baseKX_Full);
		break;
	case XGBE_SPEEDSET_2500_10000:
		pdata->phy.supported |= SUPPORTED_2500baseX_Full;
		XGBE_SET_SUP(lks, 2500baseX_Full);
		break;
	}

	if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
		pdata->phy.supported |= SUPPORTED_10000baseR_FEC;
		XGBE_SET_SUP(lks, 10000baseR_FEC);

	pdata->phy_data = phy_data;

+189 −161

File changed.

Preview size limit exceeded, changes collapsed.

+46 −4
Original line number Diff line number Diff line
@@ -131,6 +131,7 @@
#include <linux/cpumask.h>
#include <linux/interrupt.h>
#include <linux/dcache.h>
#include <linux/ethtool.h>

#define XGBE_DRV_NAME		"amd-xgbe"
#define XGBE_DRV_VERSION	"1.0.3"
@@ -296,6 +297,48 @@
/* MDIO port types */
#define XGMAC_MAX_C22_PORT		3

/* Link mode bit operations */
#define XGBE_ZERO_SUP(_ls)		\
	ethtool_link_ksettings_zero_link_mode((_ls), supported)

#define XGBE_SET_SUP(_ls, _mode)	\
	ethtool_link_ksettings_add_link_mode((_ls), supported, _mode)

#define XGBE_CLR_SUP(_ls, _mode)	\
	ethtool_link_ksettings_del_link_mode((_ls), supported, _mode)

#define XGBE_IS_SUP(_ls, _mode)	\
	ethtool_link_ksettings_test_link_mode((_ls), supported, _mode)

#define XGBE_ZERO_ADV(_ls)		\
	ethtool_link_ksettings_zero_link_mode((_ls), advertising)

#define XGBE_SET_ADV(_ls, _mode)	\
	ethtool_link_ksettings_add_link_mode((_ls), advertising, _mode)

#define XGBE_CLR_ADV(_ls, _mode)	\
	ethtool_link_ksettings_del_link_mode((_ls), advertising, _mode)

#define XGBE_ADV(_ls, _mode)		\
	ethtool_link_ksettings_test_link_mode((_ls), advertising, _mode)

#define XGBE_ZERO_LP_ADV(_ls)		\
	ethtool_link_ksettings_zero_link_mode((_ls), lp_advertising)

#define XGBE_SET_LP_ADV(_ls, _mode)	\
	ethtool_link_ksettings_add_link_mode((_ls), lp_advertising, _mode)

#define XGBE_CLR_LP_ADV(_ls, _mode)	\
	ethtool_link_ksettings_del_link_mode((_ls), lp_advertising, _mode)

#define XGBE_LP_ADV(_ls, _mode)		\
	ethtool_link_ksettings_test_link_mode((_ls), lp_advertising, _mode)

#define XGBE_LM_COPY(_dst, _dname, _src, _sname)	\
	bitmap_copy((_dst)->link_modes._dname,		\
		    (_src)->link_modes._sname,		\
		    __ETHTOOL_LINK_MODE_MASK_NBITS)

struct xgbe_prv_data;

struct xgbe_packet_data {
@@ -563,9 +606,7 @@ enum xgbe_mdio_mode {
};

struct xgbe_phy {
	u32 supported;
	u32 advertising;
	u32 lp_advertising;
	struct ethtool_link_ksettings lks;

	int address;

@@ -817,7 +858,8 @@ struct xgbe_phy_impl_if {
	int (*an_config)(struct xgbe_prv_data *);

	/* Set/override auto-negotiation advertisement settings */
	unsigned int (*an_advertising)(struct xgbe_prv_data *);
	void (*an_advertising)(struct xgbe_prv_data *,
			       struct ethtool_link_ksettings *);

	/* Process results of auto-negotiation */
	enum xgbe_mode (*an_outcome)(struct xgbe_prv_data *);