diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2010-02-17 10:16:57 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-17 20:27:36 -0500 |
commit | 2712168f856e8cd42265e7ef855d64702da20089 (patch) | |
tree | d12c32c013844a7b57a67fa43873f1e571435a3c | |
parent | a4153d401ac440c73e0721db0b6b031e8e6f77d1 (diff) |
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: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/tg3.c | 94 |
1 files changed, 52 insertions, 42 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f08e4b846458..11ee44bfa2f3 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -10093,56 +10093,66 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam | |||
10093 | int err = 0; | 10093 | int err = 0; |
10094 | 10094 | ||
10095 | if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { | 10095 | if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { |
10096 | if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)) | 10096 | u32 newadv; |
10097 | return -EAGAIN; | 10097 | struct phy_device *phydev; |
10098 | 10098 | ||
10099 | if (epause->autoneg) { | 10099 | phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; |
10100 | u32 newadv; | ||
10101 | struct phy_device *phydev; | ||
10102 | 10100 | ||
10103 | phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; | 10101 | if (!(phydev->supported & SUPPORTED_Pause) || |
10102 | (!(phydev->supported & SUPPORTED_Asym_Pause) && | ||
10103 | ((epause->rx_pause && !epause->tx_pause) || | ||
10104 | (!epause->rx_pause && epause->tx_pause)))) | ||
10105 | return -EINVAL; | ||
10104 | 10106 | ||
10105 | if (epause->rx_pause) { | 10107 | tp->link_config.flowctrl = 0; |
10106 | if (epause->tx_pause) | 10108 | if (epause->rx_pause) { |
10107 | newadv = ADVERTISED_Pause; | 10109 | tp->link_config.flowctrl |= FLOW_CTRL_RX; |
10108 | else | 10110 | |
10109 | newadv = ADVERTISED_Pause | | 10111 | if (epause->tx_pause) { |
10110 | ADVERTISED_Asym_Pause; | 10112 | tp->link_config.flowctrl |= FLOW_CTRL_TX; |
10111 | } else if (epause->tx_pause) { | 10113 | newadv = ADVERTISED_Pause; |
10112 | newadv = ADVERTISED_Asym_Pause; | ||
10113 | } else | 10114 | } else |
10114 | newadv = 0; | 10115 | newadv = ADVERTISED_Pause | |
10115 | 10116 | ADVERTISED_Asym_Pause; | |
10116 | if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) { | 10117 | } else if (epause->tx_pause) { |
10117 | u32 oldadv = phydev->advertising & | 10118 | tp->link_config.flowctrl |= FLOW_CTRL_TX; |
10118 | (ADVERTISED_Pause | | 10119 | newadv = ADVERTISED_Asym_Pause; |
10119 | ADVERTISED_Asym_Pause); | 10120 | } else |
10120 | if (oldadv != newadv) { | 10121 | newadv = 0; |
10121 | phydev->advertising &= | 10122 | |
10122 | ~(ADVERTISED_Pause | | 10123 | if (epause->autoneg) |
10123 | ADVERTISED_Asym_Pause); | 10124 | tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; |
10124 | phydev->advertising |= newadv; | 10125 | else |
10125 | err = phy_start_aneg(phydev); | 10126 | tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG; |
10127 | |||
10128 | if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) { | ||
10129 | u32 oldadv = phydev->advertising & | ||
10130 | (ADVERTISED_Pause | ADVERTISED_Asym_Pause); | ||
10131 | if (oldadv != newadv) { | ||
10132 | phydev->advertising &= | ||
10133 | ~(ADVERTISED_Pause | | ||
10134 | ADVERTISED_Asym_Pause); | ||
10135 | phydev->advertising |= newadv; | ||
10136 | if (phydev->autoneg) { | ||
10137 | /* | ||
10138 | * Always renegotiate the link to | ||
10139 | * inform our link partner of our | ||
10140 | * flow control settings, even if the | ||
10141 | * flow control is forced. Let | ||
10142 | * tg3_adjust_link() do the final | ||
10143 | * flow control setup. | ||
10144 | */ | ||
10145 | return phy_start_aneg(phydev); | ||
10126 | } | 10146 | } |
10127 | } else { | ||
10128 | tp->link_config.advertising &= | ||
10129 | ~(ADVERTISED_Pause | | ||
10130 | ADVERTISED_Asym_Pause); | ||
10131 | tp->link_config.advertising |= newadv; | ||
10132 | } | 10147 | } |
10133 | } else { | ||
10134 | if (epause->rx_pause) | ||
10135 | tp->link_config.flowctrl |= FLOW_CTRL_RX; | ||
10136 | else | ||
10137 | tp->link_config.flowctrl &= ~FLOW_CTRL_RX; | ||
10138 | |||
10139 | if (epause->tx_pause) | ||
10140 | tp->link_config.flowctrl |= FLOW_CTRL_TX; | ||
10141 | else | ||
10142 | tp->link_config.flowctrl &= ~FLOW_CTRL_TX; | ||
10143 | 10148 | ||
10144 | if (netif_running(dev)) | 10149 | if (!epause->autoneg) |
10145 | tg3_setup_flow_control(tp, 0, 0); | 10150 | tg3_setup_flow_control(tp, 0, 0); |
10151 | } else { | ||
10152 | tp->link_config.orig_advertising &= | ||
10153 | ~(ADVERTISED_Pause | | ||
10154 | ADVERTISED_Asym_Pause); | ||
10155 | tp->link_config.orig_advertising |= newadv; | ||
10146 | } | 10156 | } |
10147 | } else { | 10157 | } else { |
10148 | int irq_sync = 0; | 10158 | int irq_sync = 0; |