Skip to content

Commit 51e2a38

Browse files
Trent Piephodavem330
authored andcommitted
PHY: Avoid unnecessary aneg restarts
The PHY's aneg is configured and restarted whenever the link is brought up, e.g. when DHCP is started after the kernel has booted. This can take the link down for several seconds while auto-negotiation is redone. If the advertised features haven't changed, then it shouldn't be necessary to bring down the link and start auto-negotiation over again. genphy_config_advert() is enhanced to return 0 when the advertised features haven't been changed and >0 when they have been. genphy_config_aneg() then uses this information to not call genphy_restart_aneg() if there has been no change. Signed-off-by: Trent Piepho <[email protected]> Acked-by: Andy Fleming <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7bf6bf4 commit 51e2a38

File tree

1 file changed

+30
-19
lines changed

1 file changed

+30
-19
lines changed

drivers/net/phy/phy_device.c

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -419,21 +419,22 @@ EXPORT_SYMBOL(phy_detach);
419419
*
420420
* Description: Writes MII_ADVERTISE with the appropriate values,
421421
* after sanitizing the values to make sure we only advertise
422-
* what is supported.
422+
* what is supported. Returns < 0 on error, 0 if the PHY's advertisement
423+
* hasn't changed, and > 0 if it has changed.
423424
*/
424425
int genphy_config_advert(struct phy_device *phydev)
425426
{
426427
u32 advertise;
427-
int adv;
428-
int err;
428+
int oldadv, adv;
429+
int err, changed = 0;
429430

430431
/* Only allow advertising what
431432
* this PHY supports */
432433
phydev->advertising &= phydev->supported;
433434
advertise = phydev->advertising;
434435

435436
/* Setup standard advertisement */
436-
adv = phy_read(phydev, MII_ADVERTISE);
437+
oldadv = adv = phy_read(phydev, MII_ADVERTISE);
437438

438439
if (adv < 0)
439440
return adv;
@@ -453,15 +454,18 @@ int genphy_config_advert(struct phy_device *phydev)
453454
if (advertise & ADVERTISED_Asym_Pause)
454455
adv |= ADVERTISE_PAUSE_ASYM;
455456

456-
err = phy_write(phydev, MII_ADVERTISE, adv);
457+
if (adv != oldadv) {
458+
err = phy_write(phydev, MII_ADVERTISE, adv);
457459

458-
if (err < 0)
459-
return err;
460+
if (err < 0)
461+
return err;
462+
changed = 1;
463+
}
460464

461465
/* Configure gigabit if it's supported */
462466
if (phydev->supported & (SUPPORTED_1000baseT_Half |
463467
SUPPORTED_1000baseT_Full)) {
464-
adv = phy_read(phydev, MII_CTRL1000);
468+
oldadv = adv = phy_read(phydev, MII_CTRL1000);
465469

466470
if (adv < 0)
467471
return adv;
@@ -471,13 +475,17 @@ int genphy_config_advert(struct phy_device *phydev)
471475
adv |= ADVERTISE_1000HALF;
472476
if (advertise & SUPPORTED_1000baseT_Full)
473477
adv |= ADVERTISE_1000FULL;
474-
err = phy_write(phydev, MII_CTRL1000, adv);
475478

476-
if (err < 0)
477-
return err;
479+
if (adv != oldadv) {
480+
err = phy_write(phydev, MII_CTRL1000, adv);
481+
482+
if (err < 0)
483+
return err;
484+
changed = 1;
485+
}
478486
}
479487

480-
return adv;
488+
return changed;
481489
}
482490
EXPORT_SYMBOL(genphy_config_advert);
483491

@@ -561,19 +569,22 @@ int genphy_restart_aneg(struct phy_device *phydev)
561569
*/
562570
int genphy_config_aneg(struct phy_device *phydev)
563571
{
564-
int err = 0;
572+
int result = 0;
565573

566574
if (AUTONEG_ENABLE == phydev->autoneg) {
567-
err = genphy_config_advert(phydev);
575+
int result = genphy_config_advert(phydev);
568576

569-
if (err < 0)
570-
return err;
577+
if (result < 0) /* error */
578+
return result;
571579

572-
err = genphy_restart_aneg(phydev);
580+
/* Only restart aneg if we are advertising something different
581+
* than we were before. */
582+
if (result > 0)
583+
result = genphy_restart_aneg(phydev);
573584
} else
574-
err = genphy_setup_forced(phydev);
585+
result = genphy_setup_forced(phydev);
575586

576-
return err;
587+
return result;
577588
}
578589
EXPORT_SYMBOL(genphy_config_aneg);
579590

0 commit comments

Comments
 (0)