Skip to content

Commit

Permalink
tg3: Allow phylib flowctrl changes anytime
Browse files Browse the repository at this point in the history
This patch loosens the restriction that the phylib interface must be up
and running to change the flow control parameters.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Matt Carlson authored and David S. Miller committed Feb 18, 2010
1 parent a4153d4 commit 2712168
Showing 1 changed file with 52 additions and 42 deletions.
94 changes: 52 additions & 42 deletions drivers/net/tg3.c
Original file line number Diff line number Diff line change
Expand Up @@ -10093,56 +10093,66 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
int err = 0;

if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED))
return -EAGAIN;
u32 newadv;
struct phy_device *phydev;

if (epause->autoneg) {
u32 newadv;
struct phy_device *phydev;
phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR];

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) {
if (epause->tx_pause)
newadv = ADVERTISED_Pause;
else
newadv = ADVERTISED_Pause |
ADVERTISED_Asym_Pause;
} else if (epause->tx_pause) {
newadv = ADVERTISED_Asym_Pause;
tp->link_config.flowctrl = 0;
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 = 0;

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;
err = phy_start_aneg(phydev);
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)
tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
else
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);
} else {
tp->link_config.orig_advertising &=
~(ADVERTISED_Pause |
ADVERTISED_Asym_Pause);
tp->link_config.orig_advertising |= newadv;
}
} else {
int irq_sync = 0;
Expand Down

0 comments on commit 2712168

Please sign in to comment.