aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/broadcom
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2016-09-26 16:31:56 -0400
committerDavid S. Miller <davem@davemloft.net>2016-09-27 07:43:07 -0400
commit0299b6acf977f2c5ce9feea8faed0e264d3f01d3 (patch)
tree3b1bd87a2fb7d78d19a974642a3ef11fa954ea1f /drivers/net/ethernet/broadcom
parent62c8d3daada97dab481a8235f39f2283daf5c8ba (diff)
Revert "net: ethernet: bcmgenet: use phydev from struct net_device"
This reverts commit 62469c76007e ("net: ethernet: bcmgenet: use phydev from struct net_device") because it causes GENETv1/2/3 adapters to expose the following behavior after an ifconfig down/up sequence: PING fainelli-linux (10.112.156.244): 56 data bytes 64 bytes from 10.112.156.244: seq=1 ttl=61 time=1.352 ms 64 bytes from 10.112.156.244: seq=1 ttl=61 time=1.472 ms (DUP!) 64 bytes from 10.112.156.244: seq=1 ttl=61 time=1.496 ms (DUP!) 64 bytes from 10.112.156.244: seq=1 ttl=61 time=1.517 ms (DUP!) 64 bytes from 10.112.156.244: seq=1 ttl=61 time=1.536 ms (DUP!) 64 bytes from 10.112.156.244: seq=1 ttl=61 time=1.557 ms (DUP!) 64 bytes from 10.112.156.244: seq=1 ttl=61 time=752.448 ms (DUP!) This was previously fixed by commit 5dbebbb44a6a ("net: bcmgenet: Software reset EPHY after power on") but the commit we are reverting was essentially making this previous commit void, here is why. Without commit 62469c76007e we would have the following scenario after an ifconfig down then up sequence: - bcmgenet_open() calls bcmgenet_power_up() to make sure the PHY is initialized *before* we get to initialize the UniMAC, this is critical to ensure the PHY is in a correct state, priv->phydev is valid, this code executes fine - second time from bcmgenet_mii_probe(), through the normal phy_init_hw() call (which arguably could be optimized out) Everything is fine in that case. With commit 62469c76007e, we would have the following scenario to happen after an ifconfig down then up sequence: - bcmgenet_close() calls phy_disonnect() which makes dev->phydev become NULL - when bcmgenet_open() executes again and calls bcmgenet_mii_reset() from bcmgenet_power_up() to initialize the internal PHY, the NULL check becomes true, so we do not reset the PHY, yet we keep going on and initialize the UniMAC, causing MAC activity to occur - we call bcmgenet_mii_reset() from bcmgenet_mii_probe(), but this is too late, the PHY is botched, and causes the above bogus pings/packets transmission/reception to occur Reported-by: Jaedon Shin <jaedon.shin@gmail.com> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: Philippe Reynes <tremyfr@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/broadcom')
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.c45
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.h1
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmmii.c24
3 files changed, 39 insertions, 31 deletions
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 6d6f83b20654..55cbe2ed2929 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -453,25 +453,29 @@ static inline void bcmgenet_rdma_ring_writel(struct bcmgenet_priv *priv,
453static int bcmgenet_get_settings(struct net_device *dev, 453static int bcmgenet_get_settings(struct net_device *dev,
454 struct ethtool_cmd *cmd) 454 struct ethtool_cmd *cmd)
455{ 455{
456 struct bcmgenet_priv *priv = netdev_priv(dev);
457
456 if (!netif_running(dev)) 458 if (!netif_running(dev))
457 return -EINVAL; 459 return -EINVAL;
458 460
459 if (!dev->phydev) 461 if (!priv->phydev)
460 return -ENODEV; 462 return -ENODEV;
461 463
462 return phy_ethtool_gset(dev->phydev, cmd); 464 return phy_ethtool_gset(priv->phydev, cmd);
463} 465}
464 466
465static int bcmgenet_set_settings(struct net_device *dev, 467static int bcmgenet_set_settings(struct net_device *dev,
466 struct ethtool_cmd *cmd) 468 struct ethtool_cmd *cmd)
467{ 469{
470 struct bcmgenet_priv *priv = netdev_priv(dev);
471
468 if (!netif_running(dev)) 472 if (!netif_running(dev))
469 return -EINVAL; 473 return -EINVAL;
470 474
471 if (!dev->phydev) 475 if (!priv->phydev)
472 return -ENODEV; 476 return -ENODEV;
473 477
474 return phy_ethtool_sset(dev->phydev, cmd); 478 return phy_ethtool_sset(priv->phydev, cmd);
475} 479}
476 480
477static int bcmgenet_set_rx_csum(struct net_device *dev, 481static int bcmgenet_set_rx_csum(struct net_device *dev,
@@ -937,7 +941,7 @@ static int bcmgenet_get_eee(struct net_device *dev, struct ethtool_eee *e)
937 e->eee_active = p->eee_active; 941 e->eee_active = p->eee_active;
938 e->tx_lpi_timer = bcmgenet_umac_readl(priv, UMAC_EEE_LPI_TIMER); 942 e->tx_lpi_timer = bcmgenet_umac_readl(priv, UMAC_EEE_LPI_TIMER);
939 943
940 return phy_ethtool_get_eee(dev->phydev, e); 944 return phy_ethtool_get_eee(priv->phydev, e);
941} 945}
942 946
943static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e) 947static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e)
@@ -954,7 +958,7 @@ static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e)
954 if (!p->eee_enabled) { 958 if (!p->eee_enabled) {
955 bcmgenet_eee_enable_set(dev, false); 959 bcmgenet_eee_enable_set(dev, false);
956 } else { 960 } else {
957 ret = phy_init_eee(dev->phydev, 0); 961 ret = phy_init_eee(priv->phydev, 0);
958 if (ret) { 962 if (ret) {
959 netif_err(priv, hw, dev, "EEE initialization failed\n"); 963 netif_err(priv, hw, dev, "EEE initialization failed\n");
960 return ret; 964 return ret;
@@ -964,12 +968,14 @@ static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e)
964 bcmgenet_eee_enable_set(dev, true); 968 bcmgenet_eee_enable_set(dev, true);
965 } 969 }
966 970
967 return phy_ethtool_set_eee(dev->phydev, e); 971 return phy_ethtool_set_eee(priv->phydev, e);
968} 972}
969 973
970static int bcmgenet_nway_reset(struct net_device *dev) 974static int bcmgenet_nway_reset(struct net_device *dev)
971{ 975{
972 return genphy_restart_aneg(dev->phydev); 976 struct bcmgenet_priv *priv = netdev_priv(dev);
977
978 return genphy_restart_aneg(priv->phydev);
973} 979}
974 980
975/* standard ethtool support functions. */ 981/* standard ethtool support functions. */
@@ -996,13 +1002,12 @@ static const struct ethtool_ops bcmgenet_ethtool_ops = {
996static int bcmgenet_power_down(struct bcmgenet_priv *priv, 1002static int bcmgenet_power_down(struct bcmgenet_priv *priv,
997 enum bcmgenet_power_mode mode) 1003 enum bcmgenet_power_mode mode)
998{ 1004{
999 struct net_device *ndev = priv->dev;
1000 int ret = 0; 1005 int ret = 0;
1001 u32 reg; 1006 u32 reg;
1002 1007
1003 switch (mode) { 1008 switch (mode) {
1004 case GENET_POWER_CABLE_SENSE: 1009 case GENET_POWER_CABLE_SENSE:
1005 phy_detach(ndev->phydev); 1010 phy_detach(priv->phydev);
1006 break; 1011 break;
1007 1012
1008 case GENET_POWER_WOL_MAGIC: 1013 case GENET_POWER_WOL_MAGIC:
@@ -1063,6 +1068,7 @@ static void bcmgenet_power_up(struct bcmgenet_priv *priv,
1063/* ioctl handle special commands that are not present in ethtool. */ 1068/* ioctl handle special commands that are not present in ethtool. */
1064static int bcmgenet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 1069static int bcmgenet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
1065{ 1070{
1071 struct bcmgenet_priv *priv = netdev_priv(dev);
1066 int val = 0; 1072 int val = 0;
1067 1073
1068 if (!netif_running(dev)) 1074 if (!netif_running(dev))
@@ -1072,10 +1078,10 @@ static int bcmgenet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
1072 case SIOCGMIIPHY: 1078 case SIOCGMIIPHY:
1073 case SIOCGMIIREG: 1079 case SIOCGMIIREG:
1074 case SIOCSMIIREG: 1080 case SIOCSMIIREG:
1075 if (!dev->phydev) 1081 if (!priv->phydev)
1076 val = -ENODEV; 1082 val = -ENODEV;
1077 else 1083 else
1078 val = phy_mii_ioctl(dev->phydev, rq, cmd); 1084 val = phy_mii_ioctl(priv->phydev, rq, cmd);
1079 break; 1085 break;
1080 1086
1081 default: 1087 default:
@@ -2458,7 +2464,6 @@ static void bcmgenet_irq_task(struct work_struct *work)
2458{ 2464{
2459 struct bcmgenet_priv *priv = container_of( 2465 struct bcmgenet_priv *priv = container_of(
2460 work, struct bcmgenet_priv, bcmgenet_irq_work); 2466 work, struct bcmgenet_priv, bcmgenet_irq_work);
2461 struct net_device *ndev = priv->dev;
2462 2467
2463 netif_dbg(priv, intr, priv->dev, "%s\n", __func__); 2468 netif_dbg(priv, intr, priv->dev, "%s\n", __func__);
2464 2469
@@ -2471,7 +2476,7 @@ static void bcmgenet_irq_task(struct work_struct *work)
2471 2476
2472 /* Link UP/DOWN event */ 2477 /* Link UP/DOWN event */
2473 if (priv->irq0_stat & UMAC_IRQ_LINK_EVENT) { 2478 if (priv->irq0_stat & UMAC_IRQ_LINK_EVENT) {
2474 phy_mac_interrupt(ndev->phydev, 2479 phy_mac_interrupt(priv->phydev,
2475 !!(priv->irq0_stat & UMAC_IRQ_LINK_UP)); 2480 !!(priv->irq0_stat & UMAC_IRQ_LINK_UP));
2476 priv->irq0_stat &= ~UMAC_IRQ_LINK_EVENT; 2481 priv->irq0_stat &= ~UMAC_IRQ_LINK_EVENT;
2477 } 2482 }
@@ -2711,7 +2716,7 @@ static void bcmgenet_netif_start(struct net_device *dev)
2711 /* Monitor link interrupts now */ 2716 /* Monitor link interrupts now */
2712 bcmgenet_link_intr_enable(priv); 2717 bcmgenet_link_intr_enable(priv);
2713 2718
2714 phy_start(dev->phydev); 2719 phy_start(priv->phydev);
2715} 2720}
2716 2721
2717static int bcmgenet_open(struct net_device *dev) 2722static int bcmgenet_open(struct net_device *dev)
@@ -2810,7 +2815,7 @@ static void bcmgenet_netif_stop(struct net_device *dev)
2810 struct bcmgenet_priv *priv = netdev_priv(dev); 2815 struct bcmgenet_priv *priv = netdev_priv(dev);
2811 2816
2812 netif_tx_stop_all_queues(dev); 2817 netif_tx_stop_all_queues(dev);
2813 phy_stop(dev->phydev); 2818 phy_stop(priv->phydev);
2814 bcmgenet_intr_disable(priv); 2819 bcmgenet_intr_disable(priv);
2815 bcmgenet_disable_rx_napi(priv); 2820 bcmgenet_disable_rx_napi(priv);
2816 bcmgenet_disable_tx_napi(priv); 2821 bcmgenet_disable_tx_napi(priv);
@@ -2836,7 +2841,7 @@ static int bcmgenet_close(struct net_device *dev)
2836 bcmgenet_netif_stop(dev); 2841 bcmgenet_netif_stop(dev);
2837 2842
2838 /* Really kill the PHY state machine and disconnect from it */ 2843 /* Really kill the PHY state machine and disconnect from it */
2839 phy_disconnect(dev->phydev); 2844 phy_disconnect(priv->phydev);
2840 2845
2841 /* Disable MAC receive */ 2846 /* Disable MAC receive */
2842 umac_enable_set(priv, CMD_RX_EN, false); 2847 umac_enable_set(priv, CMD_RX_EN, false);
@@ -3395,7 +3400,7 @@ static int bcmgenet_suspend(struct device *d)
3395 3400
3396 bcmgenet_netif_stop(dev); 3401 bcmgenet_netif_stop(dev);
3397 3402
3398 phy_suspend(dev->phydev); 3403 phy_suspend(priv->phydev);
3399 3404
3400 netif_device_detach(dev); 3405 netif_device_detach(dev);
3401 3406
@@ -3459,7 +3464,7 @@ static int bcmgenet_resume(struct device *d)
3459 if (priv->wolopts) 3464 if (priv->wolopts)
3460 clk_disable_unprepare(priv->clk_wol); 3465 clk_disable_unprepare(priv->clk_wol);
3461 3466
3462 phy_init_hw(dev->phydev); 3467 phy_init_hw(priv->phydev);
3463 /* Speed settings must be restored */ 3468 /* Speed settings must be restored */
3464 bcmgenet_mii_config(priv->dev); 3469 bcmgenet_mii_config(priv->dev);
3465 3470
@@ -3492,7 +3497,7 @@ static int bcmgenet_resume(struct device *d)
3492 3497
3493 netif_device_attach(dev); 3498 netif_device_attach(dev);
3494 3499
3495 phy_resume(dev->phydev); 3500 phy_resume(priv->phydev);
3496 3501
3497 if (priv->eee.eee_enabled) 3502 if (priv->eee.eee_enabled)
3498 bcmgenet_eee_enable_set(dev, true); 3503 bcmgenet_eee_enable_set(dev, true);
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
index 0f0868c56f05..1e2dc34d331a 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
@@ -597,6 +597,7 @@ struct bcmgenet_priv {
597 597
598 /* MDIO bus variables */ 598 /* MDIO bus variables */
599 wait_queue_head_t wq; 599 wait_queue_head_t wq;
600 struct phy_device *phydev;
600 bool internal_phy; 601 bool internal_phy;
601 struct device_node *phy_dn; 602 struct device_node *phy_dn;
602 struct device_node *mdio_dn; 603 struct device_node *mdio_dn;
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
index e907acd81da9..457c3bc8cfff 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -86,7 +86,7 @@ static int bcmgenet_mii_write(struct mii_bus *bus, int phy_id,
86void bcmgenet_mii_setup(struct net_device *dev) 86void bcmgenet_mii_setup(struct net_device *dev)
87{ 87{
88 struct bcmgenet_priv *priv = netdev_priv(dev); 88 struct bcmgenet_priv *priv = netdev_priv(dev);
89 struct phy_device *phydev = dev->phydev; 89 struct phy_device *phydev = priv->phydev;
90 u32 reg, cmd_bits = 0; 90 u32 reg, cmd_bits = 0;
91 bool status_changed = false; 91 bool status_changed = false;
92 92
@@ -183,9 +183,9 @@ void bcmgenet_mii_reset(struct net_device *dev)
183 if (GENET_IS_V4(priv)) 183 if (GENET_IS_V4(priv))
184 return; 184 return;
185 185
186 if (dev->phydev) { 186 if (priv->phydev) {
187 phy_init_hw(dev->phydev); 187 phy_init_hw(priv->phydev);
188 phy_start_aneg(dev->phydev); 188 phy_start_aneg(priv->phydev);
189 } 189 }
190} 190}
191 191
@@ -236,7 +236,6 @@ static void bcmgenet_internal_phy_setup(struct net_device *dev)
236 236
237static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv) 237static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
238{ 238{
239 struct net_device *ndev = priv->dev;
240 u32 reg; 239 u32 reg;
241 240
242 /* Speed settings are set in bcmgenet_mii_setup() */ 241 /* Speed settings are set in bcmgenet_mii_setup() */
@@ -245,14 +244,14 @@ static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
245 bcmgenet_sys_writel(priv, reg, SYS_PORT_CTRL); 244 bcmgenet_sys_writel(priv, reg, SYS_PORT_CTRL);
246 245
247 if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET) 246 if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
248 fixed_phy_set_link_update(ndev->phydev, 247 fixed_phy_set_link_update(priv->phydev,
249 bcmgenet_fixed_phy_link_update); 248 bcmgenet_fixed_phy_link_update);
250} 249}
251 250
252int bcmgenet_mii_config(struct net_device *dev) 251int bcmgenet_mii_config(struct net_device *dev)
253{ 252{
254 struct bcmgenet_priv *priv = netdev_priv(dev); 253 struct bcmgenet_priv *priv = netdev_priv(dev);
255 struct phy_device *phydev = dev->phydev; 254 struct phy_device *phydev = priv->phydev;
256 struct device *kdev = &priv->pdev->dev; 255 struct device *kdev = &priv->pdev->dev;
257 const char *phy_name = NULL; 256 const char *phy_name = NULL;
258 u32 id_mode_dis = 0; 257 u32 id_mode_dis = 0;
@@ -303,7 +302,7 @@ int bcmgenet_mii_config(struct net_device *dev)
303 * capabilities, use that knowledge to also configure the 302 * capabilities, use that knowledge to also configure the
304 * Reverse MII interface correctly. 303 * Reverse MII interface correctly.
305 */ 304 */
306 if ((phydev->supported & PHY_BASIC_FEATURES) == 305 if ((priv->phydev->supported & PHY_BASIC_FEATURES) ==
307 PHY_BASIC_FEATURES) 306 PHY_BASIC_FEATURES)
308 port_ctrl = PORT_MODE_EXT_RVMII_25; 307 port_ctrl = PORT_MODE_EXT_RVMII_25;
309 else 308 else
@@ -372,7 +371,7 @@ int bcmgenet_mii_probe(struct net_device *dev)
372 return -ENODEV; 371 return -ENODEV;
373 } 372 }
374 } else { 373 } else {
375 phydev = dev->phydev; 374 phydev = priv->phydev;
376 phydev->dev_flags = phy_flags; 375 phydev->dev_flags = phy_flags;
377 376
378 ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup, 377 ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup,
@@ -383,6 +382,8 @@ int bcmgenet_mii_probe(struct net_device *dev)
383 } 382 }
384 } 383 }
385 384
385 priv->phydev = phydev;
386
386 /* Configure port multiplexer based on what the probed PHY device since 387 /* Configure port multiplexer based on what the probed PHY device since
387 * reading the 'max-speed' property determines the maximum supported 388 * reading the 'max-speed' property determines the maximum supported
388 * PHY speed which is needed for bcmgenet_mii_config() to configure 389 * PHY speed which is needed for bcmgenet_mii_config() to configure
@@ -390,7 +391,7 @@ int bcmgenet_mii_probe(struct net_device *dev)
390 */ 391 */
391 ret = bcmgenet_mii_config(dev); 392 ret = bcmgenet_mii_config(dev);
392 if (ret) { 393 if (ret) {
393 phy_disconnect(phydev); 394 phy_disconnect(priv->phydev);
394 return ret; 395 return ret;
395 } 396 }
396 397
@@ -400,7 +401,7 @@ int bcmgenet_mii_probe(struct net_device *dev)
400 * Ethernet MAC ISRs 401 * Ethernet MAC ISRs
401 */ 402 */
402 if (priv->internal_phy) 403 if (priv->internal_phy)
403 phydev->irq = PHY_IGNORE_INTERRUPT; 404 priv->phydev->irq = PHY_IGNORE_INTERRUPT;
404 405
405 return 0; 406 return 0;
406} 407}
@@ -605,6 +606,7 @@ static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)
605 606
606 } 607 }
607 608
609 priv->phydev = phydev;
608 priv->phy_interface = pd->phy_interface; 610 priv->phy_interface = pd->phy_interface;
609 611
610 return 0; 612 return 0;