bcm63xx: add ethernet support for bcm6368
[openwrt.git] / target / linux / brcm63xx / patches-3.3 / 410-NET-bcm63xx_enet-move-phy_-dis-connect-into-probe-re.patch
diff --git a/target/linux/brcm63xx/patches-3.3/410-NET-bcm63xx_enet-move-phy_-dis-connect-into-probe-re.patch b/target/linux/brcm63xx/patches-3.3/410-NET-bcm63xx_enet-move-phy_-dis-connect-into-probe-re.patch
new file mode 100644 (file)
index 0000000..2102db3
--- /dev/null
@@ -0,0 +1,169 @@
+From b11218c750ab92cfab4408a0328f1b36ceec3f33 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Fri, 6 Jan 2012 12:24:18 +0100
+Subject: [PATCH 19/63] 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 <jonas.gorski@gmail.com>
+---
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c |   84 +++++++++++++-------------
+ 1 files changed, 41 insertions(+), 43 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -784,10 +784,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;
+@@ -795,40 +793,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, 0,
+-                                   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;
+-
+-              dev_info(kdev, "attached PHY at address %d [%s]\n",
+-                       phydev->addr, phydev->drv->name);
+-
++              /* Reset state */
+               priv->old_link = 0;
+               priv->old_duplex = -1;
+               priv->old_pause = -1;
+-              priv->phydev = phydev;
+       }
+       /* mask all interrupts and request them */
+@@ -838,7 +806,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, IRQF_DISABLED,
+                         dev->name, dev);
+@@ -1025,9 +993,6 @@ out_freeirq_rx:
+ out_freeirq:
+       free_irq(dev->irq, dev);
+-out_phy_disconnect:
+-      phy_disconnect(priv->phydev);
+-
+       return ret;
+ }
+@@ -1132,12 +1097,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(priv->phydev);
+-              priv->phydev = NULL;
+-      }
+-
+       return 0;
+ }
+@@ -1714,6 +1673,8 @@ static int __devinit bcm_enet_probe(stru
+       /* 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) {
+@@ -1750,6 +1711,38 @@ static int __devinit bcm_enet_probe(stru
+                       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, 0,
++                                   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;
++
++              dev_info(&pdev->dev, "attached PHY at address %d [%s]\n",
++                       phydev->addr, phydev->drv->name);
++
++              priv->phydev = phydev;
+       } else {
+               /* run platform code to initialize PHY device */
+@@ -1795,6 +1788,9 @@ static int __devinit bcm_enet_probe(stru
+       return 0;
+ out_unregister_mdio:
++      if (priv->phydev)
++              phy_disconnect(priv->phydev);
++
+       if (priv->mii_bus) {
+               mdiobus_unregister(priv->mii_bus);
+               kfree(priv->mii_bus->irq);
+@@ -1845,6 +1841,8 @@ static int __devexit bcm_enet_remove(str
+       enet_writel(priv, 0, ENET_MIISC_REG);
+       if (priv->has_phy) {
++              phy_disconnect(priv->phydev);
++              priv->phydev = NULL;
+               mdiobus_unregister(priv->mii_bus);
+               kfree(priv->mii_bus->irq);
+               mdiobus_free(priv->mii_bus);