Skip to content

Commit 0e55a42

Browse files
committed
Merge branch 'bcmgenet-phy-rework'
Florian Fainelli says: ==================== net: bcmgenet: PHY initialization rework This patch series reworks how we perform PHY initialization and resets in the GENET driver. Although this contains mostly fixes, some of the changes are a bit too intrusive to be backported to 'net' at the moment. Some of the motivations behind these changes were to reduce the time spent in how performing MDIO transactions, since it is better to perform then when we have interrupts enabled. This reduces the bring-up time of GENET from ~600 msecs down to ~8 msecs, and about the same time for suspend/resume. Since I do not currently have a system which is not DT-aware, can you (Petri, Jaedon) give this a try and confirm things keep working as expected? ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 2c1bcaf + 28b4591 commit 0e55a42

File tree

3 files changed

+59
-63
lines changed

3 files changed

+59
-63
lines changed

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

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -907,9 +907,8 @@ static void bcmgenet_power_up(struct bcmgenet_priv *priv,
907907
}
908908

909909
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
910-
911910
if (mode == GENET_POWER_PASSIVE)
912-
bcmgenet_mii_reset(priv->dev);
911+
bcmgenet_phy_power_set(priv->dev, true);
913912
}
914913

915914
/* ioctl handle special commands that are not present in ethtool. */
@@ -1725,7 +1724,7 @@ static int init_umac(struct bcmgenet_priv *priv)
17251724
int0_enable |= UMAC_IRQ_TXDMA_DONE;
17261725

17271726
/* Monitor cable plug/unplugged event for internal PHY */
1728-
if (phy_is_internal(priv->phydev)) {
1727+
if (priv->internal_phy) {
17291728
int0_enable |= UMAC_IRQ_LINK_EVENT;
17301729
} else if (priv->ext_phy) {
17311730
int0_enable |= UMAC_IRQ_LINK_EVENT;
@@ -2632,7 +2631,7 @@ static int bcmgenet_open(struct net_device *dev)
26322631
/* If this is an internal GPHY, power it back on now, before UniMAC is
26332632
* brought out of reset as absolutely no UniMAC activity is allowed
26342633
*/
2635-
if (phy_is_internal(priv->phydev))
2634+
if (priv->internal_phy)
26362635
bcmgenet_power_up(priv, GENET_POWER_PASSIVE);
26372636

26382637
/* take MAC out of reset */
@@ -2651,7 +2650,7 @@ static int bcmgenet_open(struct net_device *dev)
26512650

26522651
bcmgenet_set_hw_addr(priv, dev->dev_addr);
26532652

2654-
if (phy_is_internal(priv->phydev)) {
2653+
if (priv->internal_phy) {
26552654
reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
26562655
reg |= EXT_ENERGY_DET_MASK;
26572656
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
@@ -2687,18 +2686,20 @@ static int bcmgenet_open(struct net_device *dev)
26872686
goto err_irq0;
26882687
}
26892688

2690-
/* Re-configure the port multiplexer towards the PHY device */
2691-
bcmgenet_mii_config(priv->dev, false);
2692-
2693-
phy_connect_direct(dev, priv->phydev, bcmgenet_mii_setup,
2694-
priv->phy_interface);
2689+
ret = bcmgenet_mii_probe(dev);
2690+
if (ret) {
2691+
netdev_err(dev, "failed to connect to PHY\n");
2692+
goto err_irq1;
2693+
}
26952694

26962695
bcmgenet_netif_start(dev);
26972696

26982697
return 0;
26992698

2699+
err_irq1:
2700+
free_irq(priv->irq1, priv);
27002701
err_irq0:
2701-
free_irq(priv->irq0, dev);
2702+
free_irq(priv->irq0, priv);
27022703
err_fini_dma:
27032704
bcmgenet_fini_dma(priv);
27042705
err_clk_disable:
@@ -2757,7 +2758,7 @@ static int bcmgenet_close(struct net_device *dev)
27572758
free_irq(priv->irq0, priv);
27582759
free_irq(priv->irq1, priv);
27592760

2760-
if (phy_is_internal(priv->phydev))
2761+
if (priv->internal_phy)
27612762
ret = bcmgenet_power_down(priv, GENET_POWER_PASSIVE);
27622763

27632764
if (!IS_ERR(priv->clk))
@@ -3319,7 +3320,7 @@ static int bcmgenet_suspend(struct device *d)
33193320
if (device_may_wakeup(d) && priv->wolopts) {
33203321
ret = bcmgenet_power_down(priv, GENET_POWER_WOL_MAGIC);
33213322
clk_prepare_enable(priv->clk_wol);
3322-
} else if (phy_is_internal(priv->phydev)) {
3323+
} else if (priv->internal_phy) {
33233324
ret = bcmgenet_power_down(priv, GENET_POWER_PASSIVE);
33243325
}
33253326

@@ -3348,7 +3349,7 @@ static int bcmgenet_resume(struct device *d)
33483349
/* If this is an internal GPHY, power it back on now, before UniMAC is
33493350
* brought out of reset as absolutely no UniMAC activity is allowed
33503351
*/
3351-
if (phy_is_internal(priv->phydev))
3352+
if (priv->internal_phy)
33523353
bcmgenet_power_up(priv, GENET_POWER_PASSIVE);
33533354

33543355
bcmgenet_umac_reset(priv);
@@ -3363,14 +3364,14 @@ static int bcmgenet_resume(struct device *d)
33633364

33643365
phy_init_hw(priv->phydev);
33653366
/* Speed settings must be restored */
3366-
bcmgenet_mii_config(priv->dev, false);
3367+
bcmgenet_mii_config(priv->dev);
33673368

33683369
/* disable ethernet MAC while updating its registers */
33693370
umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, false);
33703371

33713372
bcmgenet_set_hw_addr(priv, dev->dev_addr);
33723373

3373-
if (phy_is_internal(priv->phydev)) {
3374+
if (priv->internal_phy) {
33743375
reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
33753376
reg |= EXT_ENERGY_DET_MASK;
33763377
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@ struct bcmgenet_priv {
593593
/* MDIO bus variables */
594594
wait_queue_head_t wq;
595595
struct phy_device *phydev;
596+
bool internal_phy;
596597
struct device_node *phy_dn;
597598
struct device_node *mdio_dn;
598599
struct mii_bus *mii_bus;
@@ -670,9 +671,9 @@ GENET_IO_MACRO(rbuf, GENET_RBUF_OFF);
670671

671672
/* MDIO routines */
672673
int bcmgenet_mii_init(struct net_device *dev);
673-
int bcmgenet_mii_config(struct net_device *dev, bool init);
674+
int bcmgenet_mii_config(struct net_device *dev);
675+
int bcmgenet_mii_probe(struct net_device *dev);
674676
void bcmgenet_mii_exit(struct net_device *dev);
675-
void bcmgenet_mii_reset(struct net_device *dev);
676677
void bcmgenet_phy_power_set(struct net_device *dev, bool enable);
677678
void bcmgenet_mii_setup(struct net_device *dev);
678679

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

Lines changed: 39 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -163,16 +163,6 @@ void bcmgenet_mii_setup(struct net_device *dev)
163163
phy_print_status(phydev);
164164
}
165165

166-
void bcmgenet_mii_reset(struct net_device *dev)
167-
{
168-
struct bcmgenet_priv *priv = netdev_priv(dev);
169-
170-
if (priv->phydev) {
171-
phy_init_hw(priv->phydev);
172-
phy_start_aneg(priv->phydev);
173-
}
174-
}
175-
176166
void bcmgenet_phy_power_set(struct net_device *dev, bool enable)
177167
{
178168
struct bcmgenet_priv *priv = netdev_priv(dev);
@@ -215,7 +205,6 @@ static void bcmgenet_internal_phy_setup(struct net_device *dev)
215205
reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
216206
reg |= EXT_PWR_DN_EN_LD;
217207
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
218-
bcmgenet_mii_reset(dev);
219208
}
220209

221210
static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
@@ -228,7 +217,7 @@ static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
228217
bcmgenet_sys_writel(priv, reg, SYS_PORT_CTRL);
229218
}
230219

231-
int bcmgenet_mii_config(struct net_device *dev, bool init)
220+
int bcmgenet_mii_config(struct net_device *dev)
232221
{
233222
struct bcmgenet_priv *priv = netdev_priv(dev);
234223
struct phy_device *phydev = priv->phydev;
@@ -238,10 +227,10 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
238227
u32 port_ctrl;
239228
u32 reg;
240229

241-
priv->ext_phy = !phy_is_internal(priv->phydev) &&
230+
priv->ext_phy = !priv->internal_phy &&
242231
(priv->phy_interface != PHY_INTERFACE_MODE_MOCA);
243232

244-
if (phy_is_internal(priv->phydev))
233+
if (priv->internal_phy)
245234
priv->phy_interface = PHY_INTERFACE_MODE_NA;
246235

247236
switch (priv->phy_interface) {
@@ -259,7 +248,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
259248

260249
bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);
261250

262-
if (phy_is_internal(priv->phydev)) {
251+
if (priv->internal_phy) {
263252
phy_name = "internal PHY";
264253
bcmgenet_internal_phy_setup(dev);
265254
} else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
@@ -321,13 +310,12 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
321310
bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
322311
}
323312

324-
if (init)
325-
dev_info(kdev, "configuring instance for %s\n", phy_name);
313+
dev_info_once(kdev, "configuring instance for %s\n", phy_name);
326314

327315
return 0;
328316
}
329317

330-
static int bcmgenet_mii_probe(struct net_device *dev)
318+
int bcmgenet_mii_probe(struct net_device *dev)
331319
{
332320
struct bcmgenet_priv *priv = netdev_priv(dev);
333321
struct device_node *dn = priv->pdev->dev.of_node;
@@ -345,22 +333,6 @@ static int bcmgenet_mii_probe(struct net_device *dev)
345333
priv->old_pause = -1;
346334

347335
if (dn) {
348-
if (priv->phydev) {
349-
pr_info("PHY already attached\n");
350-
return 0;
351-
}
352-
353-
/* In the case of a fixed PHY, the DT node associated
354-
* to the PHY is the Ethernet MAC DT node.
355-
*/
356-
if (!priv->phy_dn && of_phy_is_fixed_link(dn)) {
357-
ret = of_phy_register_fixed_link(dn);
358-
if (ret)
359-
return ret;
360-
361-
priv->phy_dn = of_node_get(dn);
362-
}
363-
364336
phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
365337
phy_flags, priv->phy_interface);
366338
if (!phydev) {
@@ -386,7 +358,7 @@ static int bcmgenet_mii_probe(struct net_device *dev)
386358
* PHY speed which is needed for bcmgenet_mii_config() to configure
387359
* things appropriately.
388360
*/
389-
ret = bcmgenet_mii_config(dev, true);
361+
ret = bcmgenet_mii_config(dev);
390362
if (ret) {
391363
phy_disconnect(priv->phydev);
392364
return ret;
@@ -397,14 +369,11 @@ static int bcmgenet_mii_probe(struct net_device *dev)
397369
/* The internal PHY has its link interrupts routed to the
398370
* Ethernet MAC ISRs
399371
*/
400-
if (phy_is_internal(priv->phydev))
372+
if (priv->internal_phy)
401373
priv->mii_bus->irq[phydev->addr] = PHY_IGNORE_INTERRUPT;
402374
else
403375
priv->mii_bus->irq[phydev->addr] = PHY_POLL;
404376

405-
pr_info("attached PHY at address %d [%s]\n",
406-
phydev->addr, phydev->drv->name);
407-
408377
return 0;
409378
}
410379

@@ -490,7 +459,9 @@ static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
490459
{
491460
struct device_node *dn = priv->pdev->dev.of_node;
492461
struct device *kdev = &priv->pdev->dev;
462+
const char *phy_mode_str = NULL;
493463
char *compat;
464+
int phy_mode;
494465
int ret;
495466

496467
compat = kasprintf(GFP_KERNEL, "brcm,genet-mdio-v%d", priv->version);
@@ -513,8 +484,36 @@ static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
513484
/* Fetch the PHY phandle */
514485
priv->phy_dn = of_parse_phandle(dn, "phy-handle", 0);
515486

487+
/* In the case of a fixed PHY, the DT node associated
488+
* to the PHY is the Ethernet MAC DT node.
489+
*/
490+
if (!priv->phy_dn && of_phy_is_fixed_link(dn)) {
491+
ret = of_phy_register_fixed_link(dn);
492+
if (ret)
493+
return ret;
494+
495+
priv->phy_dn = of_node_get(dn);
496+
}
497+
516498
/* Get the link mode */
517-
priv->phy_interface = of_get_phy_mode(dn);
499+
phy_mode = of_get_phy_mode(dn);
500+
priv->phy_interface = phy_mode;
501+
502+
/* We need to specifically look up whether this PHY interface is internal
503+
* or not *before* we even try to probe the PHY driver over MDIO as we
504+
* may have shut down the internal PHY for power saving purposes.
505+
*/
506+
if (phy_mode < 0) {
507+
ret = of_property_read_string(dn, "phy-mode", &phy_mode_str);
508+
if (ret < 0) {
509+
dev_err(kdev, "invalid PHY mode property\n");
510+
return ret;
511+
}
512+
513+
priv->phy_interface = PHY_INTERFACE_MODE_NA;
514+
if (!strcasecmp(phy_mode_str, "internal"))
515+
priv->internal_phy = true;
516+
}
518517

519518
return 0;
520519
}
@@ -614,10 +613,6 @@ int bcmgenet_mii_init(struct net_device *dev)
614613
return ret;
615614

616615
ret = bcmgenet_mii_bus_init(priv);
617-
if (ret)
618-
goto out_free;
619-
620-
ret = bcmgenet_mii_probe(dev);
621616
if (ret)
622617
goto out;
623618

@@ -626,7 +621,6 @@ int bcmgenet_mii_init(struct net_device *dev)
626621
out:
627622
of_node_put(priv->phy_dn);
628623
mdiobus_unregister(priv->mii_bus);
629-
out_free:
630624
kfree(priv->mii_bus->irq);
631625
mdiobus_free(priv->mii_bus);
632626
return ret;

0 commit comments

Comments
 (0)