aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2010-02-17 10:16:57 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-17 20:27:36 -0500
commit2712168f856e8cd42265e7ef855d64702da20089 (patch)
treed12c32c013844a7b57a67fa43873f1e571435a3c
parenta4153d401ac440c73e0721db0b6b031e8e6f77d1 (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.c94
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;