Merge branch 'Preparing-for-phylib-linkmodes'

Andrew Lunn says:

====================
Preparing for phylib linkmodes

phylib currently makes us of a u32 bitmap for advertising, supported,
and link partner capabilities. For a long time, this has been
sufficient, for devices up to 1Gbps. With more MAC/PHY combinations
now supporting speeds greater than 1Gbps, we have run out of
bits. There is the need to replace this u32 with an
__ETHTOOL_DECLARE_LINK_MODE_MASK, which makes use of linux's generic
bitmaps.

This patchset does some of the work preparing for this change. A few
cleanups are applied to PHY drivers. Some MAC drivers directly access
members of phydev which are going to change type. These patches adds
some helpers and swaps MAC drivers to use them, mostly dealing with
Pause configuration.

v3:
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Add missing at in commit message
Change Subject of patch 5
Fix return in from phy_set_asym_pause
Fix kerneldoc in phy_set_pause

v2:
Fixup bad indentation in tg3.c
Rename phy_support_pause() to phy_support_sym_pause()
Also trigger autoneg if the advertising settings have changed.
Rename phy_set_pause() to phy_set_sym_pause()
Use the bcm63xx_enet.c logic, not fec_main.c for validating pause
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2018-09-12 20:24:22 -07:00
commit 15665342d4
47 changed files with 256 additions and 341 deletions

View File

@ -377,9 +377,7 @@ static int ax_mii_probe(struct net_device *dev)
return ret;
}
/* mask with MAC supported features */
phy_dev->supported &= PHY_BASIC_FEATURES;
phy_dev->advertising = phy_dev->supported;
phy_set_max_speed(phy_dev, SPEED_100);
netdev_info(dev, "PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
phy_dev->drv->name, phydev_name(phy_dev), phy_dev->irq);

View File

@ -1279,9 +1279,9 @@ static int greth_mdio_probe(struct net_device *dev)
}
if (greth->gbit_mac)
phy->supported &= PHY_GBIT_FEATURES;
phy_set_max_speed(phy, SPEED_1000);
else
phy->supported &= PHY_BASIC_FEATURES;
phy_set_max_speed(phy, SPEED_100);
phy->advertising = phy->supported;

View File

@ -3258,19 +3258,11 @@ static int et131x_mii_probe(struct net_device *netdev)
return PTR_ERR(phydev);
}
phydev->supported &= (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_Autoneg |
SUPPORTED_MII |
SUPPORTED_TP);
phy_set_max_speed(phydev, SPEED_100);
if (adapter->pdev->device != ET131X_PCI_DEVICE_ID_FAST)
phydev->supported |= SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full;
phy_set_max_speed(phydev, SPEED_1000);
phydev->advertising = phydev->supported;
phydev->autoneg = AUTONEG_ENABLE;
phy_attached_info(phydev);

View File

@ -172,8 +172,7 @@ static int emac_mdio_probe(struct net_device *dev)
}
/* mask with MAC supported features */
phydev->supported &= PHY_BASIC_FEATURES;
phydev->advertising = phydev->supported;
phy_set_max_speed(phydev, SPEED_100);
db->link = 0;
db->speed = 0;

View File

@ -835,13 +835,10 @@ static int init_phy(struct net_device *dev)
}
/* Stop Advertising 1000BASE Capability if interface is not GMII
* Note: Checkpatch throws CHECKs for the camel case defines below,
* it's ok to ignore.
*/
if ((priv->phy_iface == PHY_INTERFACE_MODE_MII) ||
(priv->phy_iface == PHY_INTERFACE_MODE_RMII))
phydev->advertising &= ~(SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full);
phy_set_max_speed(phydev, SPEED_100);
/* Broken HW is sometimes missing the pull-up resistor on the
* MDIO line, which results in reads to non-existent devices returning

View File

@ -564,17 +564,7 @@ static int au1000_mii_probe(struct net_device *dev)
return PTR_ERR(phydev);
}
/* mask with MAC supported features */
phydev->supported &= (SUPPORTED_10baseT_Half
| SUPPORTED_10baseT_Full
| SUPPORTED_100baseT_Half
| SUPPORTED_100baseT_Full
| SUPPORTED_Autoneg
/* | SUPPORTED_Pause | SUPPORTED_Asym_Pause */
| SUPPORTED_MII
| SUPPORTED_TP);
phydev->advertising = phydev->supported;
phy_set_max_speed(phydev, SPEED_100);
aup->old_link = 0;
aup->old_speed = 0;

View File

@ -879,8 +879,8 @@ static bool xgbe_phy_finisar_phy_quirks(struct xgbe_prv_data *pdata)
phy_write(phy_data->phydev, 0x00, 0x9140);
phy_data->phydev->supported = PHY_GBIT_FEATURES;
phy_data->phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
phy_data->phydev->advertising = phy_data->phydev->supported;
phy_support_asym_pause(phy_data->phydev);
netif_dbg(pdata, drv, pdata->netdev,
"Finisar PHY quirk in place\n");
@ -951,8 +951,8 @@ static bool xgbe_phy_belfuse_phy_quirks(struct xgbe_prv_data *pdata)
phy_write(phy_data->phydev, 0x00, reg & ~0x00800);
phy_data->phydev->supported = PHY_GBIT_FEATURES;
phy_data->phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
phy_data->phydev->advertising = phy_data->phydev->supported;
phy_support_asym_pause(phy_data->phydev);
netif_dbg(pdata, drv, pdata->netdev,
"BelFuse PHY quirk in place\n");

View File

@ -306,45 +306,25 @@ static int xgene_set_pauseparam(struct net_device *ndev,
{
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
struct phy_device *phydev = ndev->phydev;
u32 oldadv, newadv;
if (phy_interface_mode_is_rgmii(pdata->phy_mode) ||
pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
if (!phydev)
return -EINVAL;
if (!(phydev->supported & SUPPORTED_Pause) ||
(!(phydev->supported & SUPPORTED_Asym_Pause) &&
pp->rx_pause != pp->tx_pause))
if (!phy_validate_pause(phydev, pp))
return -EINVAL;
pdata->pause_autoneg = pp->autoneg;
pdata->tx_pause = pp->tx_pause;
pdata->rx_pause = pp->rx_pause;
oldadv = phydev->advertising;
newadv = oldadv & ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
phy_set_asym_pause(phydev, pp->rx_pause, pp->tx_pause);
if (pp->rx_pause)
newadv |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
if (pp->tx_pause)
newadv ^= ADVERTISED_Asym_Pause;
if (oldadv ^ newadv) {
phydev->advertising = newadv;
if (phydev->autoneg)
return phy_start_aneg(phydev);
if (!pp->autoneg) {
pdata->mac_ops->flowctl_tx(pdata,
pdata->tx_pause);
pdata->mac_ops->flowctl_rx(pdata,
pdata->rx_pause);
}
if (!pp->autoneg) {
pdata->mac_ops->flowctl_tx(pdata, pdata->tx_pause);
pdata->mac_ops->flowctl_rx(pdata, pdata->rx_pause);
}
} else {
if (pp->autoneg)
return -EINVAL;

View File

@ -895,12 +895,10 @@ int xgene_enet_phy_connect(struct net_device *ndev)
}
pdata->phy_speed = SPEED_UNKNOWN;
phy_dev->supported &= ~SUPPORTED_10baseT_Half &
~SUPPORTED_100baseT_Half &
~SUPPORTED_1000baseT_Half;
phy_dev->supported |= SUPPORTED_Pause |
SUPPORTED_Asym_Pause;
phy_dev->advertising = phy_dev->supported;
phy_remove_link_mode(phy_dev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
phy_remove_link_mode(phy_dev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
phy_remove_link_mode(phy_dev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
phy_support_asym_pause(phy_dev);
return 0;
}

View File

@ -935,18 +935,11 @@ static void nb8800_pause_adv(struct net_device *dev)
{
struct nb8800_priv *priv = netdev_priv(dev);
struct phy_device *phydev = dev->phydev;
u32 adv = 0;
if (!phydev)
return;
if (priv->pause_rx)
adv |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
if (priv->pause_tx)
adv ^= ADVERTISED_Asym_Pause;
phydev->supported |= adv;
phydev->advertising |= adv;
phy_set_asym_pause(phydev, priv->pause_rx, priv->pause_tx);
}
static int nb8800_open(struct net_device *dev)

View File

@ -890,19 +890,10 @@ static int bcm_enet_open(struct net_device *dev)
}
/* mask with MAC supported features */
phydev->supported &= (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_Autoneg |
SUPPORTED_Pause |
SUPPORTED_MII);
phydev->advertising = phydev->supported;
if (priv->pause_auto && priv->pause_rx && priv->pause_tx)
phydev->advertising |= SUPPORTED_Pause;
else
phydev->advertising &= ~SUPPORTED_Pause;
phy_support_sym_pause(phydev);
phy_set_max_speed(phydev, SPEED_100);
phy_set_sym_pause(phydev, priv->pause_rx, priv->pause_rx,
priv->pause_auto);
phy_attached_info(phydev);

View File

@ -214,7 +214,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
case PHY_INTERFACE_MODE_MII:
phy_name = "external MII";
phydev->supported &= PHY_BASIC_FEATURES;
phy_set_max_speed(phydev, SPEED_100);
bcmgenet_sys_writel(priv,
PORT_MODE_EXT_EPHY, SYS_PORT_CTRL);
break;
@ -226,11 +226,10 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
* capabilities, use that knowledge to also configure the
* Reverse MII interface correctly.
*/
if ((dev->phydev->supported & PHY_BASIC_FEATURES) ==
PHY_BASIC_FEATURES)
port_ctrl = PORT_MODE_EXT_RVMII_25;
else
if (dev->phydev->supported & PHY_1000BT_FEATURES)
port_ctrl = PORT_MODE_EXT_RVMII_50;
else
port_ctrl = PORT_MODE_EXT_RVMII_25;
bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);
break;

View File

@ -2357,21 +2357,11 @@ static int sbmac_mii_probe(struct net_device *dev)
}
/* Remove any features not supported by the controller */
phy_dev->supported &= SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full |
SUPPORTED_Autoneg |
SUPPORTED_MII |
SUPPORTED_Pause |
SUPPORTED_Asym_Pause;
phy_set_max_speed(phy_dev, SPEED_1000);
phy_support_asym_pause(phy_dev);
phy_attached_info(phy_dev);
phy_dev->advertising = phy_dev->supported;
sc->phy_dev = phy_dev;
return 0;

View File

@ -2122,16 +2122,14 @@ static int tg3_phy_init(struct tg3 *tp)
case PHY_INTERFACE_MODE_GMII:
case PHY_INTERFACE_MODE_RGMII:
if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
phydev->supported &= (PHY_GBIT_FEATURES |
SUPPORTED_Pause |
SUPPORTED_Asym_Pause);
phy_set_max_speed(phydev, SPEED_1000);
phy_support_asym_pause(phydev);
break;
}
/* fallthru */
case PHY_INTERFACE_MODE_MII:
phydev->supported &= (PHY_BASIC_FEATURES |
SUPPORTED_Pause |
SUPPORTED_Asym_Pause);
phy_set_max_speed(phydev, SPEED_100);
phy_support_asym_pause(phydev);
break;
default:
phy_disconnect(mdiobus_get_phy(tp->mdio_bus, tp->phy_addr));
@ -2140,8 +2138,6 @@ static int tg3_phy_init(struct tg3 *tp)
tp->phy_flags |= TG3_PHYFLG_IS_CONNECTED;
phydev->advertising = phydev->supported;
phy_attached_info(phydev);
return 0;
@ -12496,31 +12492,24 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
tg3_warn_mgmt_link_flap(tp);
if (tg3_flag(tp, USE_PHYLIB)) {
u32 newadv;
struct phy_device *phydev;
phydev = mdiobus_get_phy(tp->mdio_bus, tp->phy_addr);
if (!(phydev->supported & SUPPORTED_Pause) ||
(!(phydev->supported & SUPPORTED_Asym_Pause) &&
(epause->rx_pause != epause->tx_pause)))
if (!phy_validate_pause(phydev, epause))
return -EINVAL;
tp->link_config.flowctrl = 0;
phy_set_asym_pause(phydev, epause->rx_pause, epause->tx_pause);
if (epause->rx_pause) {
tp->link_config.flowctrl |= FLOW_CTRL_RX;
if (epause->tx_pause) {
tp->link_config.flowctrl |= FLOW_CTRL_TX;
newadv = ADVERTISED_Pause;
} else
newadv = ADVERTISED_Pause |
ADVERTISED_Asym_Pause;
}
} else if (epause->tx_pause) {
tp->link_config.flowctrl |= FLOW_CTRL_TX;
newadv = ADVERTISED_Asym_Pause;
} else
newadv = 0;
}
if (epause->autoneg)
tg3_flag_set(tp, PAUSE_AUTONEG);
@ -12528,33 +12517,19 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
tg3_flag_clear(tp, PAUSE_AUTONEG);
if (tp->phy_flags & TG3_PHYFLG_IS_CONNECTED) {
u32 oldadv = phydev->advertising &
(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
if (oldadv != newadv) {
phydev->advertising &=
~(ADVERTISED_Pause |
ADVERTISED_Asym_Pause);
phydev->advertising |= newadv;
if (phydev->autoneg) {
/*
* Always renegotiate the link to
* inform our link partner of our
* flow control settings, even if the
* flow control is forced. Let
* tg3_adjust_link() do the final
* flow control setup.
*/
return phy_start_aneg(phydev);
}
if (phydev->autoneg) {
/* phy_set_asym_pause() will
* renegotiate the link to inform our
* link partner of our flow control
* settings, even if the flow control
* is forced. Let tg3_adjust_link()
* do the final flow control setup.
*/
return 0;
}
if (!epause->autoneg)
tg3_setup_flow_control(tp, 0, 0);
} else {
tp->link_config.advertising &=
~(ADVERTISED_Pause |
ADVERTISED_Asym_Pause);
tp->link_config.advertising |= newadv;
}
} else {
int irq_sync = 0;

View File

@ -544,14 +544,13 @@ static int macb_mii_probe(struct net_device *dev)
/* mask with MAC supported features */
if (macb_is_gem(bp) && bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
phydev->supported &= PHY_GBIT_FEATURES;
phy_set_max_speed(phydev, SPEED_1000);
else
phydev->supported &= PHY_BASIC_FEATURES;
phy_set_max_speed(phydev, SPEED_100);
if (bp->caps & MACB_CAPS_NO_GIGABIT_HALF)
phydev->supported &= ~SUPPORTED_1000baseT_Half;
phydev->advertising = phydev->supported;
phy_remove_link_mode(phydev,
ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
bp->link = 0;
bp->speed = 0;

View File

@ -372,9 +372,8 @@ static int gmac_setup_phy(struct net_device *netdev)
return -ENODEV;
netdev->phydev = phy;
phy->supported &= PHY_GBIT_FEATURES;
phy->supported |= SUPPORTED_Asym_Pause | SUPPORTED_Pause;
phy->advertising = phy->supported;
phy_set_max_speed(phy, SPEED_1000);
phy_support_asym_pause(phy);
/* set PHY interface type */
switch (phy->interface) {

View File

@ -284,13 +284,11 @@ static int dnet_mii_probe(struct net_device *dev)
/* mask with MAC supported features */
if (bp->capabilities & DNET_HAS_GIGABIT)
phydev->supported &= PHY_GBIT_FEATURES;
phy_set_max_speed(phydev, SPEED_1000);
else
phydev->supported &= PHY_BASIC_FEATURES;
phy_set_max_speed(phydev, SPEED_100);
phydev->supported |= SUPPORTED_Asym_Pause | SUPPORTED_Pause;
phydev->advertising = phydev->supported;
phy_support_asym_pause(phydev);
bp->link = 0;
bp->speed = 0;

View File

@ -721,10 +721,7 @@ static int ethoc_mdio_probe(struct net_device *dev)
return err;
}
phy->advertising &= ~(ADVERTISED_1000baseT_Full |
ADVERTISED_1000baseT_Half);
phy->supported &= ~(SUPPORTED_1000baseT_Full |
SUPPORTED_1000baseT_Half);
phy_set_max_speed(phy, SPEED_100);
return 0;
}

View File

@ -1079,8 +1079,7 @@ static int ftgmac100_mii_probe(struct ftgmac100 *priv, phy_interface_t intf)
/* Indicate that we support PAUSE frames (see comment in
* Documentation/networking/phy.txt)
*/
phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
phydev->advertising = phydev->supported;
phy_support_asym_pause(phydev);
/* Display what we found */
phy_attached_info(phydev);
@ -1220,22 +1219,11 @@ static int ftgmac100_set_pauseparam(struct net_device *netdev,
priv->tx_pause = pause->tx_pause;
priv->rx_pause = pause->rx_pause;
if (phydev) {
phydev->advertising &= ~ADVERTISED_Pause;
phydev->advertising &= ~ADVERTISED_Asym_Pause;
if (phydev)
phy_set_asym_pause(phydev, pause->rx_pause, pause->tx_pause);
if (pause->rx_pause) {
phydev->advertising |= ADVERTISED_Pause;
phydev->advertising |= ADVERTISED_Asym_Pause;
}
if (pause->tx_pause)
phydev->advertising ^= ADVERTISED_Asym_Pause;
}
if (netif_running(netdev)) {
if (phydev && priv->aneg_pause)
phy_start_aneg(phydev);
else
if (!(phydev && priv->aneg_pause))
ftgmac100_config_pause(priv);
}

View File

@ -2491,8 +2491,7 @@ static int dpaa_phy_init(struct net_device *net_dev)
/* Remove any features not supported by the controller */
phy_dev->supported &= mac_dev->if_support;
phy_dev->supported |= (SUPPORTED_Pause | SUPPORTED_Asym_Pause);
phy_dev->advertising = phy_dev->supported;
phy_support_asym_pause(phy_dev);
mac_dev->phy_dev = phy_dev;
net_dev->phydev = phy_dev;

View File

@ -194,9 +194,7 @@ static int dpaa_set_pauseparam(struct net_device *net_dev,
return -ENODEV;
}
if (!(phydev->supported & SUPPORTED_Pause) ||
(!(phydev->supported & SUPPORTED_Asym_Pause) &&
(epause->rx_pause != epause->tx_pause)))
if (!phy_validate_pause(phydev, epause))
return -EINVAL;
/* The MAC should know how to handle PAUSE frame autonegotiation before
@ -210,29 +208,8 @@ static int dpaa_set_pauseparam(struct net_device *net_dev,
/* Determine the sym/asym advertised PAUSE capabilities from the desired
* rx/tx pause settings.
*/
newadv = 0;
if (epause->rx_pause)
newadv = ADVERTISED_Pause | ADVERTISED_Asym_Pause;
if (epause->tx_pause)
newadv ^= ADVERTISED_Asym_Pause;
oldadv = phydev->advertising &
(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
/* If there are differences between the old and the new advertised
* values, restart PHY autonegotiation and advertise the new values.
*/
if (oldadv != newadv) {
phydev->advertising &= ~(ADVERTISED_Pause
| ADVERTISED_Asym_Pause);
phydev->advertising |= newadv;
if (phydev->autoneg) {
err = phy_start_aneg(phydev);
if (err < 0)
netdev_err(net_dev, "phy_start_aneg() = %d\n",
err);
}
}
phy_set_asym_pause(phydev, epause->rx_pause, epause->tx_pause);
fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause);

View File

@ -1946,16 +1946,15 @@ static int fec_enet_mii_probe(struct net_device *ndev)
/* mask with MAC supported features */
if (fep->quirks & FEC_QUIRK_HAS_GBIT) {
phy_dev->supported &= PHY_GBIT_FEATURES;
phy_dev->supported &= ~SUPPORTED_1000baseT_Half;
phy_set_max_speed(phy_dev, 1000);
phy_remove_link_mode(phy_dev,
ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
#if !defined(CONFIG_M5272)
phy_dev->supported |= SUPPORTED_Pause;
phy_support_sym_pause(phy_dev);
#endif
}
else
phy_dev->supported &= PHY_BASIC_FEATURES;
phy_dev->advertising = phy_dev->supported;
phy_set_max_speed(phy_dev, 100);
fep->link = 0;
fep->full_duplex = 0;
@ -2230,13 +2229,8 @@ static int fec_enet_set_pauseparam(struct net_device *ndev,
fep->pause_flag |= pause->rx_pause ? FEC_PAUSE_FLAG_ENABLE : 0;
fep->pause_flag |= pause->autoneg ? FEC_PAUSE_FLAG_AUTONEG : 0;
if (pause->rx_pause || pause->autoneg) {
ndev->phydev->supported |= ADVERTISED_Pause;
ndev->phydev->advertising |= ADVERTISED_Pause;
} else {
ndev->phydev->supported &= ~ADVERTISED_Pause;
ndev->phydev->advertising &= ~ADVERTISED_Pause;
}
phy_set_sym_pause(ndev->phydev, pause->rx_pause, pause->tx_pause,
pause->autoneg);
if (pause->autoneg) {
if (netif_running(ndev))

View File

@ -1814,8 +1814,8 @@ static int init_phy(struct net_device *dev)
phydev->supported &= (GFAR_SUPPORTED | gigabit_support);
phydev->advertising = phydev->supported;
/* Add support for flow control, but don't advertise it by default */
phydev->supported |= (SUPPORTED_Pause | SUPPORTED_Asym_Pause);
/* Add support for flow control */
phy_support_asym_pause(phydev);
/* disable EEE autoneg, EEE not supported by eTSEC */
memset(&edata, 0, sizeof(struct ethtool_eee));

View File

@ -503,65 +503,44 @@ static int gfar_spauseparam(struct net_device *dev,
struct gfar_private *priv = netdev_priv(dev);
struct phy_device *phydev = dev->phydev;
struct gfar __iomem *regs = priv->gfargrp[0].regs;
u32 oldadv, newadv;
if (!phydev)
return -ENODEV;
if (!(phydev->supported & SUPPORTED_Pause) ||
(!(phydev->supported & SUPPORTED_Asym_Pause) &&
(epause->rx_pause != epause->tx_pause)))
if (!phy_validate_pause(phydev, epause))
return -EINVAL;
priv->rx_pause_en = priv->tx_pause_en = 0;
phy_set_asym_pause(phydev, epause->rx_pause, epause->tx_pause);
if (epause->rx_pause) {
priv->rx_pause_en = 1;
if (epause->tx_pause) {
priv->tx_pause_en = 1;
/* FLOW_CTRL_RX & TX */
newadv = ADVERTISED_Pause;
} else /* FLOW_CTLR_RX */
newadv = ADVERTISED_Pause | ADVERTISED_Asym_Pause;
}
} else if (epause->tx_pause) {
priv->tx_pause_en = 1;
/* FLOW_CTLR_TX */
newadv = ADVERTISED_Asym_Pause;
} else
newadv = 0;
}
if (epause->autoneg)
priv->pause_aneg_en = 1;
else
priv->pause_aneg_en = 0;
oldadv = phydev->advertising &
(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
if (oldadv != newadv) {
phydev->advertising &=
~(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
phydev->advertising |= newadv;
if (phydev->autoneg)
/* inform link partner of our
* new flow ctrl settings
*/
return phy_start_aneg(phydev);
if (!epause->autoneg) {
u32 tempval = gfar_read(&regs->maccfg1);
if (!epause->autoneg) {
u32 tempval;
tempval = gfar_read(&regs->maccfg1);
tempval &= ~(MACCFG1_TX_FLOW | MACCFG1_RX_FLOW);
tempval &= ~(MACCFG1_TX_FLOW | MACCFG1_RX_FLOW);
priv->tx_actual_en = 0;
if (priv->tx_pause_en) {
priv->tx_actual_en = 1;
tempval |= MACCFG1_TX_FLOW;
}
if (priv->rx_pause_en)
tempval |= MACCFG1_RX_FLOW;
gfar_write(&regs->maccfg1, tempval);
priv->tx_actual_en = 0;
if (priv->tx_pause_en) {
priv->tx_actual_en = 1;
tempval |= MACCFG1_TX_FLOW;
}
if (priv->rx_pause_en)
tempval |= MACCFG1_RX_FLOW;
gfar_write(&regs->maccfg1, tempval);
}
return 0;

View File

@ -1742,12 +1742,7 @@ static int init_phy(struct net_device *dev)
if (priv->phy_interface == PHY_INTERFACE_MODE_SGMII)
uec_configure_serdes(dev);
phydev->supported &= (SUPPORTED_MII |
SUPPORTED_Autoneg |
ADVERTISED_10baseT_Half |
ADVERTISED_10baseT_Full |
ADVERTISED_100baseT_Half |
ADVERTISED_100baseT_Full);
phy_set_max_speed(phydev, SPEED_100);
if (priv->max_speed == SPEED_1000)
phydev->supported |= ADVERTISED_1000baseT_Full;

View File

@ -5228,13 +5228,7 @@ static void hclge_set_flowctrl_adv(struct hclge_dev *hdev, u32 rx_en, u32 tx_en)
if (!phydev)
return;
phydev->advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
if (rx_en)
phydev->advertising |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
if (tx_en)
phydev->advertising ^= ADVERTISED_Asym_Pause;
phy_set_asym_pause(phydev, rx_en, tx_en);
}
static int hclge_cfg_pauseparam(struct hclge_dev *hdev, u32 rx_en, u32 tx_en)

View File

@ -10,8 +10,6 @@
#define HCLGE_PHY_SUPPORTED_FEATURES (SUPPORTED_Autoneg | \
SUPPORTED_TP | \
SUPPORTED_Pause | \
SUPPORTED_Asym_Pause | \
PHY_10BT_FEATURES | \
PHY_100BT_FEATURES | \
PHY_1000BT_FEATURES)
@ -213,7 +211,7 @@ int hclge_mac_connect_phy(struct hclge_dev *hdev)
}
phydev->supported &= HCLGE_PHY_SUPPORTED_FEATURES;
phydev->advertising = phydev->supported;
phy_support_asym_pause(phydev);
return 0;
}

View File

@ -364,15 +364,8 @@ ltq_etop_mdio_probe(struct net_device *dev)
return PTR_ERR(phydev);
}
phydev->supported &= (SUPPORTED_10baseT_Half
| SUPPORTED_10baseT_Full
| SUPPORTED_100baseT_Half
| SUPPORTED_100baseT_Full
| SUPPORTED_Autoneg
| SUPPORTED_MII
| SUPPORTED_TP);
phy_set_max_speed(phydev, SPEED_100);
phydev->advertising = phydev->supported;
phy_attached_info(phydev);
return 0;

View File

@ -355,12 +355,8 @@ static int mtk_phy_connect(struct net_device *dev)
dev->phydev->speed = 0;
dev->phydev->duplex = 0;
if (of_phy_is_fixed_link(mac->of_node))
dev->phydev->supported |=
SUPPORTED_Pause | SUPPORTED_Asym_Pause;
dev->phydev->supported &= PHY_GBIT_FEATURES | SUPPORTED_Pause |
SUPPORTED_Asym_Pause;
phy_set_max_speed(dev->phydev, SPEED_1000);
phy_support_asym_pause(dev->phydev);
dev->phydev->advertising = dev->phydev->supported |
ADVERTISED_Autoneg;
phy_start_aneg(dev->phydev);

View File

@ -999,7 +999,6 @@ static int lan743x_phy_open(struct lan743x_adapter *adapter)
struct phy_device *phydev;
struct net_device *netdev;
int ret = -EIO;
u32 mii_adv;
netdev = adapter->netdev;
phydev = phy_find_first(adapter->mdiobus);
@ -1013,13 +1012,11 @@ static int lan743x_phy_open(struct lan743x_adapter *adapter)
goto return_error;
/* MAC doesn't support 1000T Half */
phydev->supported &= ~SUPPORTED_1000baseT_Half;
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
/* support both flow controls */
phy_support_asym_pause(phydev);
phy->fc_request_control = (FLOW_CTRL_RX | FLOW_CTRL_TX);
phydev->advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
mii_adv = (u32)mii_advertise_flowctrl(phy->fc_request_control);
phydev->advertising |= mii_adv_to_ethtool_adv_t(mii_adv);
phy->fc_autoneg = phydev->autoneg;
phy_start(phydev);

View File

@ -797,8 +797,7 @@ static int lpc_mii_probe(struct net_device *ndev)
return PTR_ERR(phydev);
}
/* mask with MAC supported features */
phydev->supported &= PHY_BASIC_FEATURES;
phy_set_max_speed(phydev, SPEED_100);
phydev->advertising = phydev->supported;

View File

@ -1024,16 +1024,8 @@ static int r6040_mii_probe(struct net_device *dev)
return PTR_ERR(phydev);
}
/* mask with MAC supported features */
phydev->supported &= (SUPPORTED_10baseT_Half
| SUPPORTED_10baseT_Full
| SUPPORTED_100baseT_Half
| SUPPORTED_100baseT_Full
| SUPPORTED_Autoneg
| SUPPORTED_MII
| SUPPORTED_TP);
phy_set_max_speed(phydev, SPEED_100);
phydev->advertising = phydev->supported;
lp->old_link = 0;
lp->old_duplex = -1;

View File

@ -1074,7 +1074,8 @@ static int ravb_phy_init(struct net_device *ndev)
}
/* 10BASE is not supported */
phydev->supported &= ~PHY_10BT_FEATURES;
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT);
phy_attached_info(phydev);

View File

@ -298,8 +298,8 @@ static int sxgbe_init_phy(struct net_device *ndev)
/* Stop Advertising 1000BASE Capability if interface is not GMII */
if ((phy_iface == PHY_INTERFACE_MODE_MII) ||
(phy_iface == PHY_INTERFACE_MODE_RMII))
phydev->advertising &= ~(SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full);
phy_set_max_speed(phydev, SPEED_1000);
if (phydev->phy_id == 0) {
phy_disconnect(phydev);
return -ENODEV;

View File

@ -1048,10 +1048,10 @@ static int smsc911x_mii_probe(struct net_device *dev)
phy_attached_info(phydev);
phy_set_max_speed(phydev, SPEED_100);
/* mask with MAC supported features */
phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause |
SUPPORTED_Asym_Pause);
phydev->advertising = phydev->supported;
phy_support_asym_pause(phydev);
pdata->last_duplex = -1;
pdata->last_carrier = -1;

View File

@ -1135,10 +1135,10 @@ static int smsc9420_mii_probe(struct net_device *dev)
return PTR_ERR(phydev);
}
phy_set_max_speed(phydev, SPEED_100);
/* mask with MAC supported features */
phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause |
SUPPORTED_Asym_Pause);
phydev->advertising = phydev->supported;
phy_support_asym_pause(phydev);
phy_attached_info(phydev);

View File

@ -461,16 +461,7 @@ static int ave_ethtool_set_pauseparam(struct net_device *ndev,
priv->pause_rx = pause->rx_pause;
priv->pause_tx = pause->tx_pause;
phydev->advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
if (pause->rx_pause)
phydev->advertising |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
if (pause->tx_pause)
phydev->advertising ^= ADVERTISED_Asym_Pause;
if (pause->autoneg) {
if (netif_running(ndev))
phy_start_aneg(phydev);
}
phy_set_asym_pause(phydev, pause->rx_pause, pause->tx_pause);
return 0;
}
@ -1223,11 +1214,10 @@ static int ave_init(struct net_device *ndev)
phy_ethtool_get_wol(phydev, &wol);
device_set_wakeup_capable(&ndev->dev, !!wol.supported);
if (!phy_interface_is_rgmii(phydev)) {
phydev->supported &= ~PHY_GBIT_FEATURES;
phydev->supported |= PHY_BASIC_FEATURES;
}
phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
if (!phy_interface_is_rgmii(phydev))
phy_set_max_speed(phydev, SPEED_100);
phy_support_asym_pause(phydev);
phy_attached_info(phydev);

View File

@ -987,17 +987,20 @@ static int stmmac_init_phy(struct net_device *dev)
if ((interface == PHY_INTERFACE_MODE_MII) ||
(interface == PHY_INTERFACE_MODE_RMII) ||
(max_speed < 1000 && max_speed > 0))
phydev->advertising &= ~(SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full);
phy_set_max_speed(phydev, SPEED_100);
/*
* Half-duplex mode not supported with multiqueue
* half-duplex can only works with single queue
*/
if (tx_cnt > 1)
phydev->supported &= ~(SUPPORTED_1000baseT_Half |
SUPPORTED_100baseT_Half |
SUPPORTED_10baseT_Half);
if (tx_cnt > 1) {
phy_remove_link_mode(phydev,
ETHTOOL_LINK_MODE_10baseT_Half_BIT);
phy_remove_link_mode(phydev,
ETHTOOL_LINK_MODE_100baseT_Half_BIT);
phy_remove_link_mode(phydev,
ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
}
/*
* Broken HW is sometimes missing the pull-up resistor on the

View File

@ -628,7 +628,7 @@ static int tc_mii_probe(struct net_device *dev)
phy_attached_info(phydev);
/* mask with MAC supported features */
phydev->supported &= PHY_BASIC_FEATURES;
phy_set_max_speed(phydev, SPEED_100);
dropmask = 0;
if (options.speed == 10)
dropmask |= SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full;

View File

@ -941,8 +941,7 @@ static int xemaclite_open(struct net_device *dev)
}
/* EmacLite doesn't support giga-bit speeds */
lp->phy_dev->supported &= (PHY_BASIC_FEATURES);
lp->phy_dev->advertising = lp->phy_dev->supported;
phy_set_max_speed(lp->phy_dev, SPEED_100);
/* Don't advertise 1000BASE-T Full/Half duplex speeds */
phy_write(lp->phy_dev, MII_CTRL1000, 0);

View File

@ -240,7 +240,7 @@ config AT803X_PHY
config BCM63XX_PHY
tristate "Broadcom 63xx SOCs internal PHY"
depends on BCM63XX
depends on BCM63XX || COMPILE_TEST
select BCM_NET_PHYLIB
---help---
Currently supports the 6348 and 6358 PHYs.

View File

@ -91,7 +91,7 @@ static struct phy_driver et1011c_driver[] = { {
.phy_id = 0x0282f014,
.name = "ET1011C",
.phy_id_mask = 0xfffffff0,
.features = (PHY_BASIC_FEATURES | SUPPORTED_1000baseT_Full),
.features = PHY_GBIT_FEATURES,
.flags = PHY_POLL,
.config_aneg = et1011c_config_aneg,
.read_status = et1011c_read_status,

View File

@ -1765,6 +1765,124 @@ int phy_set_max_speed(struct phy_device *phydev, u32 max_speed)
}
EXPORT_SYMBOL(phy_set_max_speed);
/**
* phy_remove_link_mode - Remove a supported link mode
* @phydev: phy_device structure to remove link mode from
* @link_mode: Link mode to be removed
*
* Description: Some MACs don't support all link modes which the PHY
* does. e.g. a 1G MAC often does not support 1000Half. Add a helper
* to remove a link mode.
*/
void phy_remove_link_mode(struct phy_device *phydev, u32 link_mode)
{
WARN_ON(link_mode > 31);
phydev->supported &= ~BIT(link_mode);
phydev->advertising = phydev->supported;
}
EXPORT_SYMBOL(phy_remove_link_mode);
/**
* phy_support_sym_pause - Enable support of symmetrical pause
* @phydev: target phy_device struct
*
* Description: Called by the MAC to indicate is supports symmetrical
* Pause, but not asym pause.
*/
void phy_support_sym_pause(struct phy_device *phydev)
{
phydev->supported |= SUPPORTED_Pause;
phydev->advertising = phydev->supported;
}
EXPORT_SYMBOL(phy_support_sym_pause);
/**
* phy_support_asym_pause - Enable support of asym pause
* @phydev: target phy_device struct
*
* Description: Called by the MAC to indicate is supports Asym Pause.
*/
void phy_support_asym_pause(struct phy_device *phydev)
{
phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
phydev->advertising = phydev->supported;
}
EXPORT_SYMBOL(phy_support_asym_pause);
/**
* phy_set_sym_pause - Configure symmetric Pause
* @phydev: target phy_device struct
* @rx: Receiver Pause is supported
* @tx: Transmit Pause is supported
* @autoneg: Auto neg should be used
*
* Description: Configure advertised Pause support depending on if
* receiver pause and pause auto neg is supported. Generally called
* from the set_pauseparam .ndo.
*/
void phy_set_sym_pause(struct phy_device *phydev, bool rx, bool tx,
bool autoneg)
{
phydev->supported &= ~SUPPORTED_Pause;
if (rx && tx && autoneg)
phydev->supported |= SUPPORTED_Pause;
phydev->advertising = phydev->supported;
}
EXPORT_SYMBOL(phy_set_sym_pause);
/**
* phy_set_asym_pause - Configure Pause and Asym Pause
* @phydev: target phy_device struct
* @rx: Receiver Pause is supported
* @tx: Transmit Pause is supported
*
* Description: Configure advertised Pause support depending on if
* transmit and receiver pause is supported. If there has been a
* change in adverting, trigger a new autoneg. Generally called from
* the set_pauseparam .ndo.
*/
void phy_set_asym_pause(struct phy_device *phydev, bool rx, bool tx)
{
u16 oldadv = phydev->advertising;
u16 newadv = oldadv &= ~(SUPPORTED_Pause | SUPPORTED_Asym_Pause);
if (rx)
newadv |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
if (tx)
newadv ^= SUPPORTED_Asym_Pause;
if (oldadv != newadv) {
phydev->advertising = newadv;
if (phydev->autoneg)
phy_start_aneg(phydev);
}
}
EXPORT_SYMBOL(phy_set_asym_pause);
/**
* phy_validate_pause - Test if the PHY/MAC support the pause configuration
* @phydev: phy_device struct
* @pp: requested pause configuration
*
* Description: Test if the PHY/MAC combination supports the Pause
* configuration the user is requesting. Returns True if it is
* supported, false otherwise.
*/
bool phy_validate_pause(struct phy_device *phydev,
struct ethtool_pauseparam *pp)
{
if (!(phydev->supported & SUPPORTED_Pause) ||
(!(phydev->supported & SUPPORTED_Asym_Pause) &&
pp->rx_pause != pp->tx_pause))
return false;
return true;
}
EXPORT_SYMBOL(phy_validate_pause);
static void of_set_phy_supported(struct phy_device *phydev)
{
struct device_node *node = phydev->mdio.dev.of_node;

View File

@ -86,7 +86,7 @@ static struct phy_driver ste10xp_pdriver[] = {
.phy_id = STE101P_PHY_ID,
.phy_id_mask = 0xfffffff0,
.name = "STe101p",
.features = PHY_BASIC_FEATURES | SUPPORTED_Pause,
.features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = ste10Xp_config_init,
.ack_interrupt = ste10Xp_ack_interrupt,
@ -97,7 +97,7 @@ static struct phy_driver ste10xp_pdriver[] = {
.phy_id = STE100P_PHY_ID,
.phy_id_mask = 0xffffffff,
.name = "STe100p",
.features = PHY_BASIC_FEATURES | SUPPORTED_Pause,
.features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = ste10Xp_config_init,
.ack_interrupt = ste10Xp_ack_interrupt,

View File

@ -2166,7 +2166,7 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
}
/* MAC doesn't support 1000T Half */
phydev->supported &= ~SUPPORTED_1000baseT_Half;
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
/* support both flow controls */
dev->fc_request_control = (FLOW_CTRL_RX | FLOW_CTRL_TX);

View File

@ -112,7 +112,7 @@ static void phy_init(struct mtk_eth *eth, struct mtk_mac *mac,
phy->autoneg = AUTONEG_ENABLE;
phy->speed = 0;
phy->duplex = 0;
phy->supported &= PHY_BASIC_FEATURES;
phy_set_max_speed(phy, SPEED_100);
phy->advertising = phy->supported | ADVERTISED_Autoneg;
phy_start_aneg(phy);

View File

@ -1049,6 +1049,14 @@ int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd);
int phy_start_interrupts(struct phy_device *phydev);
void phy_print_status(struct phy_device *phydev);
int phy_set_max_speed(struct phy_device *phydev, u32 max_speed);
void phy_remove_link_mode(struct phy_device *phydev, u32 link_mode);
void phy_support_sym_pause(struct phy_device *phydev);
void phy_support_asym_pause(struct phy_device *phydev);
void phy_set_sym_pause(struct phy_device *phydev, bool rx, bool tx,
bool autoneg);
void phy_set_asym_pause(struct phy_device *phydev, bool rx, bool tx);
bool phy_validate_pause(struct phy_device *phydev,
struct ethtool_pauseparam *pp);
int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
int (*run)(struct phy_device *));