Skip to content

Commit

Permalink
amd-xgbe: Convert to using the new link mode settings
Browse files Browse the repository at this point in the history
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: Tom Lendacky <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
tlendacky authored and davem330 committed Aug 18, 2017
1 parent 606c07f commit 85f9feb
Show file tree
Hide file tree
Showing 5 changed files with 345 additions and 242 deletions.
56 changes: 32 additions & 24 deletions drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand All @@ -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);
Expand All @@ -300,30 +306,29 @@ 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;
}

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;

Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down
77 changes: 47 additions & 30 deletions drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -615,20 +615,22 @@ 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)
return XGBE_AN_NO_LINK;
} 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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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);
Expand Down
Loading

0 comments on commit 85f9feb

Please sign in to comment.