Commit 70814e81 authored by Andrew Lunn's avatar Andrew Lunn Committed by David S. Miller
Browse files

net: ethernet: Add helper for set_pauseparam for Asym Pause



ethtool can be used to enable/disable pause. Add a helper to configure
the PHY when asym pause is supported.

Signed-off-by: default avatarAndrew Lunn <andrew@lunn.ch>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c306ad36
Loading
Loading
Loading
Loading
+4 −22
Original line number Original line Diff line number Diff line
@@ -306,7 +306,6 @@ static int xgene_set_pauseparam(struct net_device *ndev,
{
{
	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
	struct phy_device *phydev = ndev->phydev;
	struct phy_device *phydev = ndev->phydev;
	u32 oldadv, newadv;


	if (phy_interface_mode_is_rgmii(pdata->phy_mode) ||
	if (phy_interface_mode_is_rgmii(pdata->phy_mode) ||
	    pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
	    pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
@@ -322,29 +321,12 @@ static int xgene_set_pauseparam(struct net_device *ndev,
		pdata->tx_pause = pp->tx_pause;
		pdata->tx_pause = pp->tx_pause;
		pdata->rx_pause = pp->rx_pause;
		pdata->rx_pause = pp->rx_pause;


		oldadv = phydev->advertising;
		phy_set_asym_pause(phydev, pp->rx_pause,  pp->tx_pause);
		newadv = oldadv & ~(ADVERTISED_Pause | ADVERTISED_Asym_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) {
		if (!pp->autoneg) {
				pdata->mac_ops->flowctl_tx(pdata,
			pdata->mac_ops->flowctl_tx(pdata, pdata->tx_pause);
							   pdata->tx_pause);
			pdata->mac_ops->flowctl_rx(pdata, pdata->rx_pause);
				pdata->mac_ops->flowctl_rx(pdata,
							   pdata->rx_pause);
			}
		}
		}

	} else {
	} else {
		if (pp->autoneg)
		if (pp->autoneg)
			return -EINVAL;
			return -EINVAL;
+1 −8
Original line number Original line Diff line number Diff line
@@ -935,18 +935,11 @@ static void nb8800_pause_adv(struct net_device *dev)
{
{
	struct nb8800_priv *priv = netdev_priv(dev);
	struct nb8800_priv *priv = netdev_priv(dev);
	struct phy_device *phydev = dev->phydev;
	struct phy_device *phydev = dev->phydev;
	u32 adv = 0;


	if (!phydev)
	if (!phydev)
		return;
		return;


	if (priv->pause_rx)
	phy_set_asym_pause(phydev, priv->pause_rx, priv->pause_tx);
		adv |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
	if (priv->pause_tx)
		adv ^= ADVERTISED_Asym_Pause;

	phydev->supported |= adv;
	phydev->advertising |= adv;
}
}


static int nb8800_open(struct net_device *dev)
static int nb8800_open(struct net_device *dev)
+12 −31
Original line number Original line Diff line number Diff line
@@ -12492,7 +12492,6 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
		tg3_warn_mgmt_link_flap(tp);
		tg3_warn_mgmt_link_flap(tp);


	if (tg3_flag(tp, USE_PHYLIB)) {
	if (tg3_flag(tp, USE_PHYLIB)) {
		u32 newadv;
		struct phy_device *phydev;
		struct phy_device *phydev;


		phydev = mdiobus_get_phy(tp->mdio_bus, tp->phy_addr);
		phydev = mdiobus_get_phy(tp->mdio_bus, tp->phy_addr);
@@ -12503,20 +12502,16 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
			return -EINVAL;
			return -EINVAL;


		tp->link_config.flowctrl = 0;
		tp->link_config.flowctrl = 0;
		phy_set_asym_pause(phydev, epause->rx_pause, epause->tx_pause);
		if (epause->rx_pause) {
		if (epause->rx_pause) {
			tp->link_config.flowctrl |= FLOW_CTRL_RX;
			tp->link_config.flowctrl |= FLOW_CTRL_RX;


			if (epause->tx_pause) {
			if (epause->tx_pause) {
				tp->link_config.flowctrl |= FLOW_CTRL_TX;
				tp->link_config.flowctrl |= FLOW_CTRL_TX;
				newadv = ADVERTISED_Pause;
			}
			} else
				newadv = ADVERTISED_Pause |
					 ADVERTISED_Asym_Pause;
		} else if (epause->tx_pause) {
		} else if (epause->tx_pause) {
			tp->link_config.flowctrl |= FLOW_CTRL_TX;
			tp->link_config.flowctrl |= FLOW_CTRL_TX;
			newadv = ADVERTISED_Asym_Pause;
		}
		} else
			newadv = 0;


		if (epause->autoneg)
		if (epause->autoneg)
			tg3_flag_set(tp, PAUSE_AUTONEG);
			tg3_flag_set(tp, PAUSE_AUTONEG);
@@ -12524,33 +12519,19 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
			tg3_flag_clear(tp, PAUSE_AUTONEG);
			tg3_flag_clear(tp, PAUSE_AUTONEG);


		if (tp->phy_flags & TG3_PHYFLG_IS_CONNECTED) {
		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) {
			if (phydev->autoneg) {
					/*
				/* phy_set_asym_pause() will
					 * Always renegotiate the link to
				 * renegotiate the link to inform our
					 * inform our link partner of our
				 * link partner of our flow control
					 * flow control settings, even if the
				 * settings, even if the flow control
					 * flow control is forced.  Let
				 * is forced.  Let tg3_adjust_link()
					 * tg3_adjust_link() do the final
				 * do the final flow control setup.
					 * flow control setup.
				 */
				 */
					return phy_start_aneg(phydev);
				return 0;
				}
			}
			}


			if (!epause->autoneg)
			if (!epause->autoneg)
				tg3_setup_flow_control(tp, 0, 0);
				tg3_setup_flow_control(tp, 0, 0);
		} else {
			tp->link_config.advertising &=
					~(ADVERTISED_Pause |
					  ADVERTISED_Asym_Pause);
			tp->link_config.advertising |= newadv;
		}
		}
	} else {
	} else {
		int irq_sync = 0;
		int irq_sync = 0;
+3 −14
Original line number Original line Diff line number Diff line
@@ -1219,22 +1219,11 @@ static int ftgmac100_set_pauseparam(struct net_device *netdev,
	priv->tx_pause = pause->tx_pause;
	priv->tx_pause = pause->tx_pause;
	priv->rx_pause = pause->rx_pause;
	priv->rx_pause = pause->rx_pause;


	if (phydev) {
	if (phydev)
		phydev->advertising &= ~ADVERTISED_Pause;
		phy_set_asym_pause(phydev, pause->rx_pause, pause->tx_pause);
		phydev->advertising &= ~ADVERTISED_Asym_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 (netif_running(netdev)) {
		if (phydev && priv->aneg_pause)
		if (!(phydev && priv->aneg_pause))
			phy_start_aneg(phydev);
		else
			ftgmac100_config_pause(priv);
			ftgmac100_config_pause(priv);
	}
	}


+1 −22
Original line number Original line Diff line number Diff line
@@ -210,29 +210,8 @@ static int dpaa_set_pauseparam(struct net_device *net_dev,
	/* Determine the sym/asym advertised PAUSE capabilities from the desired
	/* Determine the sym/asym advertised PAUSE capabilities from the desired
	 * rx/tx pause settings.
	 * 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 &
	phy_set_asym_pause(phydev, epause->rx_pause, epause->tx_pause);
			(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);
		}
	}


	fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
	fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
	err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause);
	err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause);
Loading