| 1 | From b11218c750ab92cfab4408a0328f1b36ceec3f33 Mon Sep 17 00:00:00 2001 |
| 2 | From: Jonas Gorski <jonas.gorski@gmail.com> |
| 3 | Date: Fri, 6 Jan 2012 12:24:18 +0100 |
| 4 | Subject: [PATCH 19/63] NET: bcm63xx_enet: move phy_(dis)connect into probe/remove |
| 5 | |
| 6 | Only connect/disconnect the phy during probe and remove, not during any |
| 7 | open/close. The phy seldom changes during the runtime, and disconnecting |
| 8 | the phy during close will prevent it from keeping any configuration over |
| 9 | a down/up cycle. |
| 10 | |
| 11 | Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com> |
| 12 | --- |
| 13 | drivers/net/ethernet/broadcom/bcm63xx_enet.c | 84 +++++++++++++------------- |
| 14 | 1 files changed, 41 insertions(+), 43 deletions(-) |
| 15 | |
| 16 | --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c |
| 17 | +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c |
| 18 | @@ -784,10 +784,8 @@ static int bcm_enet_open(struct net_devi |
| 19 | struct bcm_enet_priv *priv; |
| 20 | struct sockaddr addr; |
| 21 | struct device *kdev; |
| 22 | - struct phy_device *phydev; |
| 23 | int i, ret; |
| 24 | unsigned int size; |
| 25 | - char phy_id[MII_BUS_ID_SIZE + 3]; |
| 26 | void *p; |
| 27 | u32 val; |
| 28 | |
| 29 | @@ -795,40 +793,10 @@ static int bcm_enet_open(struct net_devi |
| 30 | kdev = &priv->pdev->dev; |
| 31 | |
| 32 | if (priv->has_phy) { |
| 33 | - /* connect to PHY */ |
| 34 | - snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, |
| 35 | - priv->mii_bus->id, priv->phy_id); |
| 36 | - |
| 37 | - phydev = phy_connect(dev, phy_id, bcm_enet_adjust_phy_link, 0, |
| 38 | - PHY_INTERFACE_MODE_MII); |
| 39 | - |
| 40 | - if (IS_ERR(phydev)) { |
| 41 | - dev_err(kdev, "could not attach to PHY\n"); |
| 42 | - return PTR_ERR(phydev); |
| 43 | - } |
| 44 | - |
| 45 | - /* mask with MAC supported features */ |
| 46 | - phydev->supported &= (SUPPORTED_10baseT_Half | |
| 47 | - SUPPORTED_10baseT_Full | |
| 48 | - SUPPORTED_100baseT_Half | |
| 49 | - SUPPORTED_100baseT_Full | |
| 50 | - SUPPORTED_Autoneg | |
| 51 | - SUPPORTED_Pause | |
| 52 | - SUPPORTED_MII); |
| 53 | - phydev->advertising = phydev->supported; |
| 54 | - |
| 55 | - if (priv->pause_auto && priv->pause_rx && priv->pause_tx) |
| 56 | - phydev->advertising |= SUPPORTED_Pause; |
| 57 | - else |
| 58 | - phydev->advertising &= ~SUPPORTED_Pause; |
| 59 | - |
| 60 | - dev_info(kdev, "attached PHY at address %d [%s]\n", |
| 61 | - phydev->addr, phydev->drv->name); |
| 62 | - |
| 63 | + /* Reset state */ |
| 64 | priv->old_link = 0; |
| 65 | priv->old_duplex = -1; |
| 66 | priv->old_pause = -1; |
| 67 | - priv->phydev = phydev; |
| 68 | } |
| 69 | |
| 70 | /* mask all interrupts and request them */ |
| 71 | @@ -838,7 +806,7 @@ static int bcm_enet_open(struct net_devi |
| 72 | |
| 73 | ret = request_irq(dev->irq, bcm_enet_isr_mac, 0, dev->name, dev); |
| 74 | if (ret) |
| 75 | - goto out_phy_disconnect; |
| 76 | + return ret; |
| 77 | |
| 78 | ret = request_irq(priv->irq_rx, bcm_enet_isr_dma, IRQF_DISABLED, |
| 79 | dev->name, dev); |
| 80 | @@ -1025,9 +993,6 @@ out_freeirq_rx: |
| 81 | out_freeirq: |
| 82 | free_irq(dev->irq, dev); |
| 83 | |
| 84 | -out_phy_disconnect: |
| 85 | - phy_disconnect(priv->phydev); |
| 86 | - |
| 87 | return ret; |
| 88 | } |
| 89 | |
| 90 | @@ -1132,12 +1097,6 @@ static int bcm_enet_stop(struct net_devi |
| 91 | free_irq(priv->irq_rx, dev); |
| 92 | free_irq(dev->irq, dev); |
| 93 | |
| 94 | - /* release phy */ |
| 95 | - if (priv->has_phy) { |
| 96 | - phy_disconnect(priv->phydev); |
| 97 | - priv->phydev = NULL; |
| 98 | - } |
| 99 | - |
| 100 | return 0; |
| 101 | } |
| 102 | |
| 103 | @@ -1714,6 +1673,8 @@ static int __devinit bcm_enet_probe(stru |
| 104 | |
| 105 | /* MII bus registration */ |
| 106 | if (priv->has_phy) { |
| 107 | + struct phy_device *phydev; |
| 108 | + char phy_id[MII_BUS_ID_SIZE + 3]; |
| 109 | |
| 110 | priv->mii_bus = mdiobus_alloc(); |
| 111 | if (!priv->mii_bus) { |
| 112 | @@ -1750,6 +1711,38 @@ static int __devinit bcm_enet_probe(stru |
| 113 | dev_err(&pdev->dev, "unable to register mdio bus\n"); |
| 114 | goto out_free_mdio; |
| 115 | } |
| 116 | + |
| 117 | + /* connect to PHY */ |
| 118 | + snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, |
| 119 | + priv->mii_bus->id, priv->phy_id); |
| 120 | + |
| 121 | + phydev = phy_connect(dev, phy_id, bcm_enet_adjust_phy_link, 0, |
| 122 | + PHY_INTERFACE_MODE_MII); |
| 123 | + |
| 124 | + if (IS_ERR(phydev)) { |
| 125 | + dev_err(&pdev->dev, "could not attach to PHY\n"); |
| 126 | + goto out_unregister_mdio; |
| 127 | + } |
| 128 | + |
| 129 | + /* mask with MAC supported features */ |
| 130 | + phydev->supported &= (SUPPORTED_10baseT_Half | |
| 131 | + SUPPORTED_10baseT_Full | |
| 132 | + SUPPORTED_100baseT_Half | |
| 133 | + SUPPORTED_100baseT_Full | |
| 134 | + SUPPORTED_Autoneg | |
| 135 | + SUPPORTED_Pause | |
| 136 | + SUPPORTED_MII); |
| 137 | + phydev->advertising = phydev->supported; |
| 138 | + |
| 139 | + if (priv->pause_auto && priv->pause_rx && priv->pause_tx) |
| 140 | + phydev->advertising |= SUPPORTED_Pause; |
| 141 | + else |
| 142 | + phydev->advertising &= ~SUPPORTED_Pause; |
| 143 | + |
| 144 | + dev_info(&pdev->dev, "attached PHY at address %d [%s]\n", |
| 145 | + phydev->addr, phydev->drv->name); |
| 146 | + |
| 147 | + priv->phydev = phydev; |
| 148 | } else { |
| 149 | |
| 150 | /* run platform code to initialize PHY device */ |
| 151 | @@ -1795,6 +1788,9 @@ static int __devinit bcm_enet_probe(stru |
| 152 | return 0; |
| 153 | |
| 154 | out_unregister_mdio: |
| 155 | + if (priv->phydev) |
| 156 | + phy_disconnect(priv->phydev); |
| 157 | + |
| 158 | if (priv->mii_bus) { |
| 159 | mdiobus_unregister(priv->mii_bus); |
| 160 | kfree(priv->mii_bus->irq); |
| 161 | @@ -1845,6 +1841,8 @@ static int __devexit bcm_enet_remove(str |
| 162 | enet_writel(priv, 0, ENET_MIISC_REG); |
| 163 | |
| 164 | if (priv->has_phy) { |
| 165 | + phy_disconnect(priv->phydev); |
| 166 | + priv->phydev = NULL; |
| 167 | mdiobus_unregister(priv->mii_bus); |
| 168 | kfree(priv->mii_bus->irq); |
| 169 | mdiobus_free(priv->mii_bus); |
| 170 | |