From 7fa63fdde703aaabaa7199ae879219737a98a3f3 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Fri, 6 Jan 2012 12:24:18 +0100 Subject: [PATCH] NET: bcm63xx_enet: move phy_(dis)connect into probe/remove Only connect/disconnect the phy during probe and remove, not during any open/close. The phy seldom changes during the runtime, and disconnecting the phy during close will prevent it from keeping any configuration over a down/up cycle. Signed-off-by: Jonas Gorski --- drivers/net/ethernet/broadcom/bcm63xx_enet.c | 158 +++++++++++++-------------- 1 file changed, 78 insertions(+), 80 deletions(-) --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -871,10 +871,8 @@ static int bcm_enet_open(struct net_devi struct bcm_enet_priv *priv; struct sockaddr addr; struct device *kdev; - struct phy_device *phydev; int i, ret; unsigned int size; - char phy_id[MII_BUS_ID_SIZE + 3]; void *p; u32 val; @@ -882,40 +880,10 @@ static int bcm_enet_open(struct net_devi kdev = &priv->pdev->dev; if (priv->has_phy) { - /* connect to PHY */ - snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, - priv->mii_bus->id, priv->phy_id); - - phydev = phy_connect(dev, phy_id, bcm_enet_adjust_phy_link, - PHY_INTERFACE_MODE_MII); - - if (IS_ERR(phydev)) { - dev_err(kdev, "could not attach to PHY\n"); - return PTR_ERR(phydev); - } - - /* mask with MAC supported features */ - phydev->supported &= (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_Pause | - SUPPORTED_MII); - phydev->advertising = phydev->supported; - - if (priv->pause_auto && priv->pause_rx && priv->pause_tx) - phydev->advertising |= SUPPORTED_Pause; - else - phydev->advertising &= ~SUPPORTED_Pause; - - phy_attached_info(phydev); - + /* Reset state */ priv->old_link = 0; priv->old_duplex = -1; priv->old_pause = -1; - } else { - phydev = NULL; } /* mask all interrupts and request them */ @@ -925,7 +893,7 @@ static int bcm_enet_open(struct net_devi ret = request_irq(dev->irq, bcm_enet_isr_mac, 0, dev->name, dev); if (ret) - goto out_phy_disconnect; + return ret; ret = request_irq(priv->irq_rx, bcm_enet_isr_dma, 0, dev->name, dev); @@ -1087,8 +1055,8 @@ static int bcm_enet_open(struct net_devi enet_dmac_writel(priv, priv->dma_chan_int_mask, ENETDMAC_IRMASK, priv->tx_chan); - if (phydev) - phy_start(phydev); + if (priv->has_phy) + phy_start(dev->phydev); else bcm_enet_adjust_link(dev); @@ -1129,10 +1097,6 @@ out_freeirq_rx: out_freeirq: free_irq(dev->irq, dev); -out_phy_disconnect: - if (phydev) - phy_disconnect(phydev); - return ret; } @@ -1237,10 +1201,6 @@ static int bcm_enet_stop(struct net_devi free_irq(priv->irq_rx, dev); free_irq(dev->irq, dev); - /* release phy */ - if (priv->has_phy) - phy_disconnect(dev->phydev); - return 0; } @@ -1822,14 +1782,46 @@ static int bcm_enet_probe(struct platfor /* do minimal hardware init to be able to probe mii bus */ bcm_enet_hw_preinit(priv); + spin_lock_init(&priv->rx_lock); + + /* init rx timeout (used for oom) */ + init_timer(&priv->rx_timeout); + priv->rx_timeout.function = bcm_enet_refill_rx_timer; + priv->rx_timeout.data = (unsigned long)dev; + + /* init the mib update lock&work */ + mutex_init(&priv->mib_update_lock); + INIT_WORK(&priv->mib_update_task, bcm_enet_update_mib_counters_defer); + + /* zero mib counters */ + for (i = 0; i < ENET_MIB_REG_COUNT; i++) + enet_writel(priv, 0, ENET_MIB_REG(i)); + + /* register netdevice */ + dev->netdev_ops = &bcm_enet_ops; + netif_napi_add(dev, &priv->napi, bcm_enet_poll, 16); + + dev->ethtool_ops = &bcm_enet_ethtool_ops; + SET_NETDEV_DEV(dev, &pdev->dev); + + ret = register_netdev(dev); + if (ret) + goto out_uninit_hw; + + netif_carrier_off(dev); + platform_set_drvdata(pdev, dev); + priv->pdev = pdev; + priv->net_dev = dev; /* MII bus registration */ if (priv->has_phy) { + struct phy_device *phydev; + char phy_id[MII_BUS_ID_SIZE + 3]; priv->mii_bus = mdiobus_alloc(); if (!priv->mii_bus) { ret = -ENOMEM; - goto out_uninit_hw; + goto out_unregister_netdev; } bus = priv->mii_bus; @@ -1853,6 +1845,35 @@ static int bcm_enet_probe(struct platfor dev_err(&pdev->dev, "unable to register mdio bus\n"); goto out_free_mdio; } + + /* connect to PHY */ + snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, + priv->mii_bus->id, priv->phy_id); + + phydev = phy_connect(dev, phy_id, bcm_enet_adjust_phy_link, + PHY_INTERFACE_MODE_MII); + + if (IS_ERR(phydev)) { + dev_err(&pdev->dev, "could not attach to PHY\n"); + goto out_unregister_mdio; + } + + /* mask with MAC supported features */ + phydev->supported &= (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_Pause | + SUPPORTED_MII); + phydev->advertising = phydev->supported; + + if (priv->pause_auto && priv->pause_rx && priv->pause_tx) + phydev->advertising |= SUPPORTED_Pause; + else + phydev->advertising &= ~SUPPORTED_Pause; + + phy_attached_info(phydev); } else { /* run platform code to initialize PHY device */ @@ -1860,44 +1881,16 @@ static int bcm_enet_probe(struct platfor pd->mii_config(dev, 1, bcm_enet_mdio_read_mii, bcm_enet_mdio_write_mii)) { dev_err(&pdev->dev, "unable to configure mdio bus\n"); - goto out_uninit_hw; + goto out_unregister_netdev; } } - spin_lock_init(&priv->rx_lock); - - /* init rx timeout (used for oom) */ - init_timer(&priv->rx_timeout); - priv->rx_timeout.function = bcm_enet_refill_rx_timer; - priv->rx_timeout.data = (unsigned long)dev; - - /* init the mib update lock&work */ - mutex_init(&priv->mib_update_lock); - INIT_WORK(&priv->mib_update_task, bcm_enet_update_mib_counters_defer); - - /* zero mib counters */ - for (i = 0; i < ENET_MIB_REG_COUNT; i++) - enet_writel(priv, 0, ENET_MIB_REG(i)); - - /* register netdevice */ - dev->netdev_ops = &bcm_enet_ops; - netif_napi_add(dev, &priv->napi, bcm_enet_poll, 16); - - dev->ethtool_ops = &bcm_enet_ethtool_ops; - SET_NETDEV_DEV(dev, &pdev->dev); - - ret = register_netdev(dev); - if (ret) - goto out_unregister_mdio; - - netif_carrier_off(dev); - platform_set_drvdata(pdev, dev); - priv->pdev = pdev; - priv->net_dev = dev; - return 0; out_unregister_mdio: + if (dev->phydev) + phy_disconnect(dev->phydev); + if (priv->mii_bus) mdiobus_unregister(priv->mii_bus); @@ -1905,6 +1898,9 @@ out_free_mdio: if (priv->mii_bus) mdiobus_free(priv->mii_bus); +out_unregister_netdev: + unregister_netdev(dev); + out_uninit_hw: /* turn off mdc clock */ enet_writel(priv, 0, ENET_MIISC_REG); @@ -1935,6 +1931,7 @@ static int bcm_enet_remove(struct platfo enet_writel(priv, 0, ENET_MIISC_REG); if (priv->has_phy) { + phy_disconnect(dev->phydev); mdiobus_unregister(priv->mii_bus); mdiobus_free(priv->mii_bus); } else {