aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEd Swierk <eswierk@arastra.com>2008-12-01 07:24:43 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-04 00:06:42 -0500
commitcb52deba12f27af90a46d2f8667a64888118a888 (patch)
tree91b9e3fa5d0670e98811a43a1f2ad6e1cbe668f7
parenta316084c2f18fd5371f81cfcfc8348a71c4a6fe8 (diff)
forcedeth: power down phy when interface is down
Bring the physical link down when the interface is down by placing the PHY in power-down state, unless WOL is enabled. This mirrors the behavior of other drivers including e1000 and tg3. Without the patch, ifconfig down leaves the physical link up, which confuses datacenter users who expect the link lights both on the NIC and the switch to go out when they bring an interface down. Furthermore, even though the phy is powered on, autonegotiation stops working, so a normally gigabit link might suddenly become 100 Mbit half-duplex when the interface goes down, and become gigabit when it comes up again. Ayaz said: I would not include this patch until further testing is performed. NVIDIA MCP chips use 3rd party PHY vendors. By powering down the phy, it could have adverse affects on certain phys. Arthur Jones said: I just ran across this patch. Tested on a Marvell 88E1121R (GigE PHY) and works great. This is a very important feature for me. Signed-off-by: Ed Swierk <eswierk@arastra.com> Tested-by: Arthur Jones <ajones@riverbed.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/forcedeth.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 0d7e5750245a..12384df8cb2b 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -1446,9 +1446,9 @@ static int phy_init(struct net_device *dev)
1446 /* some phys clear out pause advertisment on reset, set it back */ 1446 /* some phys clear out pause advertisment on reset, set it back */
1447 mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg); 1447 mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg);
1448 1448
1449 /* restart auto negotiation */ 1449 /* restart auto negotiation, power down phy */
1450 mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); 1450 mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
1451 mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE); 1451 mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE | BMCR_PDOWN);
1452 if (mii_rw(dev, np->phyaddr, MII_BMCR, mii_control)) { 1452 if (mii_rw(dev, np->phyaddr, MII_BMCR, mii_control)) {
1453 return PHY_ERROR; 1453 return PHY_ERROR;
1454 } 1454 }
@@ -5208,6 +5208,10 @@ static int nv_open(struct net_device *dev)
5208 5208
5209 dprintk(KERN_DEBUG "nv_open: begin\n"); 5209 dprintk(KERN_DEBUG "nv_open: begin\n");
5210 5210
5211 /* power up phy */
5212 mii_rw(dev, np->phyaddr, MII_BMCR,
5213 mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ) & ~BMCR_PDOWN);
5214
5211 /* erase previous misconfiguration */ 5215 /* erase previous misconfiguration */
5212 if (np->driver_data & DEV_HAS_POWER_CNTRL) 5216 if (np->driver_data & DEV_HAS_POWER_CNTRL)
5213 nv_mac_reset(dev); 5217 nv_mac_reset(dev);
@@ -5401,6 +5405,10 @@ static int nv_close(struct net_device *dev)
5401 if (np->wolenabled) { 5405 if (np->wolenabled) {
5402 writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags); 5406 writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags);
5403 nv_start_rx(dev); 5407 nv_start_rx(dev);
5408 } else {
5409 /* power down phy */
5410 mii_rw(dev, np->phyaddr, MII_BMCR,
5411 mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ)|BMCR_PDOWN);
5404 } 5412 }
5405 5413
5406 /* FIXME: power down nic */ 5414 /* FIXME: power down nic */