Commit 2712168f authored by Matt Carlson's avatar Matt Carlson Committed by David S. Miller

tg3: Allow phylib flowctrl changes anytime

This patch loosens the restriction that the phylib interface must be up
and running to change the flow control parameters.
Signed-off-by: default avatarMatt Carlson <mcarlson@broadcom.com>
Reviewed-by: default avatarMichael Chan <mchan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a4153d40
...@@ -10093,56 +10093,66 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam ...@@ -10093,56 +10093,66 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
int err = 0; int err = 0;
if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)) u32 newadv;
return -EAGAIN; struct phy_device *phydev;
if (epause->autoneg) { phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR];
u32 newadv;
struct phy_device *phydev;
phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; if (!(phydev->supported & SUPPORTED_Pause) ||
(!(phydev->supported & SUPPORTED_Asym_Pause) &&
((epause->rx_pause && !epause->tx_pause) ||
(!epause->rx_pause && epause->tx_pause))))
return -EINVAL;
if (epause->rx_pause) { tp->link_config.flowctrl = 0;
if (epause->tx_pause) if (epause->rx_pause) {
newadv = ADVERTISED_Pause; tp->link_config.flowctrl |= FLOW_CTRL_RX;
else
newadv = ADVERTISED_Pause | if (epause->tx_pause) {
ADVERTISED_Asym_Pause; tp->link_config.flowctrl |= FLOW_CTRL_TX;
} else if (epause->tx_pause) { newadv = ADVERTISED_Pause;
newadv = ADVERTISED_Asym_Pause;
} else } else
newadv = 0; newadv = ADVERTISED_Pause |
ADVERTISED_Asym_Pause;
if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) { } else if (epause->tx_pause) {
u32 oldadv = phydev->advertising & tp->link_config.flowctrl |= FLOW_CTRL_TX;
(ADVERTISED_Pause | newadv = ADVERTISED_Asym_Pause;
ADVERTISED_Asym_Pause); } else
if (oldadv != newadv) { newadv = 0;
phydev->advertising &=
~(ADVERTISED_Pause | if (epause->autoneg)
ADVERTISED_Asym_Pause); tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
phydev->advertising |= newadv; else
err = phy_start_aneg(phydev); tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG;
if (tp->tg3_flags3 & TG3_FLG3_PHY_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);
} }
} else {
tp->link_config.advertising &=
~(ADVERTISED_Pause |
ADVERTISED_Asym_Pause);
tp->link_config.advertising |= newadv;
} }
} else {
if (epause->rx_pause)
tp->link_config.flowctrl |= FLOW_CTRL_RX;
else
tp->link_config.flowctrl &= ~FLOW_CTRL_RX;
if (epause->tx_pause)
tp->link_config.flowctrl |= FLOW_CTRL_TX;
else
tp->link_config.flowctrl &= ~FLOW_CTRL_TX;
if (netif_running(dev)) if (!epause->autoneg)
tg3_setup_flow_control(tp, 0, 0); tg3_setup_flow_control(tp, 0, 0);
} else {
tp->link_config.orig_advertising &=
~(ADVERTISED_Pause |
ADVERTISED_Asym_Pause);
tp->link_config.orig_advertising |= newadv;
} }
} else { } else {
int irq_sync = 0; int irq_sync = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment