/branches/18.06.1/target/linux/brcm63xx/patches-4.9/404-NET-bcm63xx_enet-move-phy_-dis-connect-into-probe-re.patch |
@@ -0,0 +1,263 @@ |
From 7fa63fdde703aaabaa7199ae879219737a98a3f3 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] 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 | 158 +++++++++++++-------------- |
1 file changed, 78 insertions(+), 80 deletions(-) |
|
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c |
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c |
@@ -870,10 +870,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; |
|
@@ -881,40 +879,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 */ |
@@ -924,7 +892,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); |
@@ -1086,8 +1054,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); |
|
@@ -1128,10 +1096,6 @@ out_freeirq_rx: |
out_freeirq: |
free_irq(dev->irq, dev); |
|
-out_phy_disconnect: |
- if (phydev) |
- phy_disconnect(phydev); |
- |
return ret; |
} |
|
@@ -1236,10 +1200,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; |
} |
|
@@ -1821,14 +1781,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; |
@@ -1852,6 +1844,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 */ |
@@ -1859,44 +1880,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); |
|
@@ -1904,6 +1897,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); |
@@ -1934,6 +1930,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 { |