diff options
author | Bryan Wu <bryan.wu@canonical.com> | 2010-05-18 12:56:55 +0800 |
---|---|---|
committer | Lily Zhang <r58066@freescale.com> | 2010-05-18 12:58:07 +0800 |
commit | e30d2d898598f8f00ed291ddd6f216452a0bc6a4 (patch) | |
tree | 424d690c91bb65c24e1289a94ef1049047f12a9f | |
parent | c9281344c53d053ab95549762219cc04e2d308d6 (diff) |
netdev/fec: fix ifconfig eth0 down hang issue
BugLink: http://bugs.launchpad.net/bugs/559065
In fec open/close function, we need to use phy_connect and phy_disconnect
operation before we start/stop phy. Otherwise it will cause system hang.
Only call fec_enet_mii_probe() in open function, because the first open
action will cause NULL pointer error.
Signed-off-by: Bryan Wu <bryan.wu@canonical.com>
Acked-by: Tim Gardner <tim.gardner@canonical.com>
Acked-by: Colin King <colin.king@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
-rw-r--r-- | drivers/net/fec.c | 28 |
1 files changed, 17 insertions, 11 deletions
diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 44c1b65dcb6e..47a432668491 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -762,6 +762,8 @@ static int fec_enet_mii_probe(struct net_device *dev) int phy_addr; int fec_index = fep->pdev->id > 0 ? fep->pdev->id : 0; + fep->phy_dev = NULL; + /* find the phy, assuming fec index corresponds to addr */ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { if (fep->mii_bus->phy_map[phy_addr]) { @@ -793,6 +795,12 @@ static int fec_enet_mii_probe(struct net_device *dev) fep->link = 0; fep->full_duplex = 0; + printk(KERN_INFO "%s: Freescale FEC PHY driver [%s] " + "(mii_bus:phy_addr=%s, irq=%d)\n", dev->name, + fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev), + fep->phy_dev->irq); + + return 0; } @@ -1004,7 +1012,12 @@ fec_enet_open(struct net_device *dev) if (ret) return ret; - /* schedule a link state check */ + /* Probe and connect to PHY when open the interface */ + ret = fec_enet_mii_probe(dev); + if (ret) { + fec_enet_free_buffers(dev); + return ret; + } phy_start(fep->phy_dev); netif_start_queue(dev); fep->opened = 1; @@ -1018,10 +1031,12 @@ fec_enet_close(struct net_device *dev) /* Don't know what to do yet. */ fep->opened = 0; - phy_stop(fep->phy_dev); netif_stop_queue(dev); fec_stop(dev); + if (fep->phy_dev) + phy_disconnect(fep->phy_dev); + fec_enet_free_buffers(dev); clk_disable(fep->clk); @@ -1483,9 +1498,6 @@ fec_probe(struct platform_device *pdev) fep->mii_bus = fec_mii_bus; } - if (fec_enet_mii_probe(ndev) != 0) - goto failed_mii_probe; - fep->ptp_priv = kmalloc(sizeof(struct fec_ptp_private), GFP_KERNEL); if (fep->ptp_priv) { fep->ptp_priv->hwp = fep->hwp; @@ -1504,14 +1516,8 @@ fec_probe(struct platform_device *pdev) clk_disable(fep->clk); - printk(KERN_INFO "%s: Freescale FEC PHY driver [%s] " - "(mii_bus:phy_addr=%s, irq=%d)\n", ndev->name, - fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev), - fep->phy_dev->irq); - return 0; -failed_mii_probe: failed_register: fec_enet_mii_remove(fep); if (fep->ptimer_present) |