Skip to content

Commit 0299b6a

Browse files
ffainellidavem330
authored andcommitted
Revert "net: ethernet: bcmgenet: use phydev from struct net_device"
This reverts commit 62469c7 ("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 5dbebbb ("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 62469c7 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 62469c7, 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 <[email protected]> Signed-off-by: Florian Fainelli <[email protected]> Signed-off-by: Philippe Reynes <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 62c8d3d commit 0299b6a

File tree

3 files changed

+39
-31
lines changed

3 files changed

+39
-31
lines changed

drivers/net/ethernet/broadcom/genet/bcmgenet.c

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -453,25 +453,29 @@ static inline void bcmgenet_rdma_ring_writel(struct bcmgenet_priv *priv,
453453
static int bcmgenet_get_settings(struct net_device *dev,
454454
struct ethtool_cmd *cmd)
455455
{
456+
struct bcmgenet_priv *priv = netdev_priv(dev);
457+
456458
if (!netif_running(dev))
457459
return -EINVAL;
458460

459-
if (!dev->phydev)
461+
if (!priv->phydev)
460462
return -ENODEV;
461463

462-
return phy_ethtool_gset(dev->phydev, cmd);
464+
return phy_ethtool_gset(priv->phydev, cmd);
463465
}
464466

465467
static int bcmgenet_set_settings(struct net_device *dev,
466468
struct ethtool_cmd *cmd)
467469
{
470+
struct bcmgenet_priv *priv = netdev_priv(dev);
471+
468472
if (!netif_running(dev))
469473
return -EINVAL;
470474

471-
if (!dev->phydev)
475+
if (!priv->phydev)
472476
return -ENODEV;
473477

474-
return phy_ethtool_sset(dev->phydev, cmd);
478+
return phy_ethtool_sset(priv->phydev, cmd);
475479
}
476480

477481
static 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)
937941
e->eee_active = p->eee_active;
938942
e->tx_lpi_timer = bcmgenet_umac_readl(priv, UMAC_EEE_LPI_TIMER);
939943

940-
return phy_ethtool_get_eee(dev->phydev, e);
944+
return phy_ethtool_get_eee(priv->phydev, e);
941945
}
942946

943947
static 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)
954958
if (!p->eee_enabled) {
955959
bcmgenet_eee_enable_set(dev, false);
956960
} else {
957-
ret = phy_init_eee(dev->phydev, 0);
961+
ret = phy_init_eee(priv->phydev, 0);
958962
if (ret) {
959963
netif_err(priv, hw, dev, "EEE initialization failed\n");
960964
return ret;
@@ -964,12 +968,14 @@ static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e)
964968
bcmgenet_eee_enable_set(dev, true);
965969
}
966970

967-
return phy_ethtool_set_eee(dev->phydev, e);
971+
return phy_ethtool_set_eee(priv->phydev, e);
968972
}
969973

970974
static int bcmgenet_nway_reset(struct net_device *dev)
971975
{
972-
return genphy_restart_aneg(dev->phydev);
976+
struct bcmgenet_priv *priv = netdev_priv(dev);
977+
978+
return genphy_restart_aneg(priv->phydev);
973979
}
974980

975981
/* standard ethtool support functions. */
@@ -996,13 +1002,12 @@ static const struct ethtool_ops bcmgenet_ethtool_ops = {
9961002
static int bcmgenet_power_down(struct bcmgenet_priv *priv,
9971003
enum bcmgenet_power_mode mode)
9981004
{
999-
struct net_device *ndev = priv->dev;
10001005
int ret = 0;
10011006
u32 reg;
10021007

10031008
switch (mode) {
10041009
case GENET_POWER_CABLE_SENSE:
1005-
phy_detach(ndev->phydev);
1010+
phy_detach(priv->phydev);
10061011
break;
10071012

10081013
case GENET_POWER_WOL_MAGIC:
@@ -1063,6 +1068,7 @@ static void bcmgenet_power_up(struct bcmgenet_priv *priv,
10631068
/* ioctl handle special commands that are not present in ethtool. */
10641069
static int bcmgenet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
10651070
{
1071+
struct bcmgenet_priv *priv = netdev_priv(dev);
10661072
int val = 0;
10671073

10681074
if (!netif_running(dev))
@@ -1072,10 +1078,10 @@ static int bcmgenet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
10721078
case SIOCGMIIPHY:
10731079
case SIOCGMIIREG:
10741080
case SIOCSMIIREG:
1075-
if (!dev->phydev)
1081+
if (!priv->phydev)
10761082
val = -ENODEV;
10771083
else
1078-
val = phy_mii_ioctl(dev->phydev, rq, cmd);
1084+
val = phy_mii_ioctl(priv->phydev, rq, cmd);
10791085
break;
10801086

10811087
default:
@@ -2458,7 +2464,6 @@ static void bcmgenet_irq_task(struct work_struct *work)
24582464
{
24592465
struct bcmgenet_priv *priv = container_of(
24602466
work, struct bcmgenet_priv, bcmgenet_irq_work);
2461-
struct net_device *ndev = priv->dev;
24622467

24632468
netif_dbg(priv, intr, priv->dev, "%s\n", __func__);
24642469

@@ -2471,7 +2476,7 @@ static void bcmgenet_irq_task(struct work_struct *work)
24712476

24722477
/* Link UP/DOWN event */
24732478
if (priv->irq0_stat & UMAC_IRQ_LINK_EVENT) {
2474-
phy_mac_interrupt(ndev->phydev,
2479+
phy_mac_interrupt(priv->phydev,
24752480
!!(priv->irq0_stat & UMAC_IRQ_LINK_UP));
24762481
priv->irq0_stat &= ~UMAC_IRQ_LINK_EVENT;
24772482
}
@@ -2711,7 +2716,7 @@ static void bcmgenet_netif_start(struct net_device *dev)
27112716
/* Monitor link interrupts now */
27122717
bcmgenet_link_intr_enable(priv);
27132718

2714-
phy_start(dev->phydev);
2719+
phy_start(priv->phydev);
27152720
}
27162721

27172722
static int bcmgenet_open(struct net_device *dev)
@@ -2810,7 +2815,7 @@ static void bcmgenet_netif_stop(struct net_device *dev)
28102815
struct bcmgenet_priv *priv = netdev_priv(dev);
28112816

28122817
netif_tx_stop_all_queues(dev);
2813-
phy_stop(dev->phydev);
2818+
phy_stop(priv->phydev);
28142819
bcmgenet_intr_disable(priv);
28152820
bcmgenet_disable_rx_napi(priv);
28162821
bcmgenet_disable_tx_napi(priv);
@@ -2836,7 +2841,7 @@ static int bcmgenet_close(struct net_device *dev)
28362841
bcmgenet_netif_stop(dev);
28372842

28382843
/* Really kill the PHY state machine and disconnect from it */
2839-
phy_disconnect(dev->phydev);
2844+
phy_disconnect(priv->phydev);
28402845

28412846
/* Disable MAC receive */
28422847
umac_enable_set(priv, CMD_RX_EN, false);
@@ -3395,7 +3400,7 @@ static int bcmgenet_suspend(struct device *d)
33953400

33963401
bcmgenet_netif_stop(dev);
33973402

3398-
phy_suspend(dev->phydev);
3403+
phy_suspend(priv->phydev);
33993404

34003405
netif_device_detach(dev);
34013406

@@ -3459,7 +3464,7 @@ static int bcmgenet_resume(struct device *d)
34593464
if (priv->wolopts)
34603465
clk_disable_unprepare(priv->clk_wol);
34613466

3462-
phy_init_hw(dev->phydev);
3467+
phy_init_hw(priv->phydev);
34633468
/* Speed settings must be restored */
34643469
bcmgenet_mii_config(priv->dev);
34653470

@@ -3492,7 +3497,7 @@ static int bcmgenet_resume(struct device *d)
34923497

34933498
netif_device_attach(dev);
34943499

3495-
phy_resume(dev->phydev);
3500+
phy_resume(priv->phydev);
34963501

34973502
if (priv->eee.eee_enabled)
34983503
bcmgenet_eee_enable_set(dev, true);

drivers/net/ethernet/broadcom/genet/bcmgenet.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,7 @@ struct bcmgenet_priv {
597597

598598
/* MDIO bus variables */
599599
wait_queue_head_t wq;
600+
struct phy_device *phydev;
600601
bool internal_phy;
601602
struct device_node *phy_dn;
602603
struct device_node *mdio_dn;

drivers/net/ethernet/broadcom/genet/bcmmii.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ static int bcmgenet_mii_write(struct mii_bus *bus, int phy_id,
8686
void bcmgenet_mii_setup(struct net_device *dev)
8787
{
8888
struct bcmgenet_priv *priv = netdev_priv(dev);
89-
struct phy_device *phydev = dev->phydev;
89+
struct phy_device *phydev = priv->phydev;
9090
u32 reg, cmd_bits = 0;
9191
bool status_changed = false;
9292

@@ -183,9 +183,9 @@ void bcmgenet_mii_reset(struct net_device *dev)
183183
if (GENET_IS_V4(priv))
184184
return;
185185

186-
if (dev->phydev) {
187-
phy_init_hw(dev->phydev);
188-
phy_start_aneg(dev->phydev);
186+
if (priv->phydev) {
187+
phy_init_hw(priv->phydev);
188+
phy_start_aneg(priv->phydev);
189189
}
190190
}
191191

@@ -236,7 +236,6 @@ static void bcmgenet_internal_phy_setup(struct net_device *dev)
236236

237237
static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
238238
{
239-
struct net_device *ndev = priv->dev;
240239
u32 reg;
241240

242241
/* Speed settings are set in bcmgenet_mii_setup() */
@@ -245,14 +244,14 @@ static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
245244
bcmgenet_sys_writel(priv, reg, SYS_PORT_CTRL);
246245

247246
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,
249248
bcmgenet_fixed_phy_link_update);
250249
}
251250

252251
int bcmgenet_mii_config(struct net_device *dev)
253252
{
254253
struct bcmgenet_priv *priv = netdev_priv(dev);
255-
struct phy_device *phydev = dev->phydev;
254+
struct phy_device *phydev = priv->phydev;
256255
struct device *kdev = &priv->pdev->dev;
257256
const char *phy_name = NULL;
258257
u32 id_mode_dis = 0;
@@ -303,7 +302,7 @@ int bcmgenet_mii_config(struct net_device *dev)
303302
* capabilities, use that knowledge to also configure the
304303
* Reverse MII interface correctly.
305304
*/
306-
if ((phydev->supported & PHY_BASIC_FEATURES) ==
305+
if ((priv->phydev->supported & PHY_BASIC_FEATURES) ==
307306
PHY_BASIC_FEATURES)
308307
port_ctrl = PORT_MODE_EXT_RVMII_25;
309308
else
@@ -372,7 +371,7 @@ int bcmgenet_mii_probe(struct net_device *dev)
372371
return -ENODEV;
373372
}
374373
} else {
375-
phydev = dev->phydev;
374+
phydev = priv->phydev;
376375
phydev->dev_flags = phy_flags;
377376

378377
ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup,
@@ -383,14 +382,16 @@ int bcmgenet_mii_probe(struct net_device *dev)
383382
}
384383
}
385384

385+
priv->phydev = phydev;
386+
386387
/* Configure port multiplexer based on what the probed PHY device since
387388
* reading the 'max-speed' property determines the maximum supported
388389
* PHY speed which is needed for bcmgenet_mii_config() to configure
389390
* things appropriately.
390391
*/
391392
ret = bcmgenet_mii_config(dev);
392393
if (ret) {
393-
phy_disconnect(phydev);
394+
phy_disconnect(priv->phydev);
394395
return ret;
395396
}
396397

@@ -400,7 +401,7 @@ int bcmgenet_mii_probe(struct net_device *dev)
400401
* Ethernet MAC ISRs
401402
*/
402403
if (priv->internal_phy)
403-
phydev->irq = PHY_IGNORE_INTERRUPT;
404+
priv->phydev->irq = PHY_IGNORE_INTERRUPT;
404405

405406
return 0;
406407
}
@@ -605,6 +606,7 @@ static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)
605606

606607
}
607608

609+
priv->phydev = phydev;
608610
priv->phy_interface = pd->phy_interface;
609611

610612
return 0;

0 commit comments

Comments
 (0)