diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/phy/phy_device.c | 49 |
1 files changed, 30 insertions, 19 deletions
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 16a0e7de5888..171627480058 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
@@ -419,13 +419,14 @@ EXPORT_SYMBOL(phy_detach); | |||
419 | * | 419 | * |
420 | * Description: Writes MII_ADVERTISE with the appropriate values, | 420 | * Description: Writes MII_ADVERTISE with the appropriate values, |
421 | * after sanitizing the values to make sure we only advertise | 421 | * 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. | ||
423 | */ | 424 | */ |
424 | int genphy_config_advert(struct phy_device *phydev) | 425 | int genphy_config_advert(struct phy_device *phydev) |
425 | { | 426 | { |
426 | u32 advertise; | 427 | u32 advertise; |
427 | int adv; | 428 | int oldadv, adv; |
428 | int err; | 429 | int err, changed = 0; |
429 | 430 | ||
430 | /* Only allow advertising what | 431 | /* Only allow advertising what |
431 | * this PHY supports */ | 432 | * this PHY supports */ |
@@ -433,7 +434,7 @@ int genphy_config_advert(struct phy_device *phydev) | |||
433 | advertise = phydev->advertising; | 434 | advertise = phydev->advertising; |
434 | 435 | ||
435 | /* Setup standard advertisement */ | 436 | /* Setup standard advertisement */ |
436 | adv = phy_read(phydev, MII_ADVERTISE); | 437 | oldadv = adv = phy_read(phydev, MII_ADVERTISE); |
437 | 438 | ||
438 | if (adv < 0) | 439 | if (adv < 0) |
439 | return adv; | 440 | return adv; |
@@ -453,15 +454,18 @@ int genphy_config_advert(struct phy_device *phydev) | |||
453 | if (advertise & ADVERTISED_Asym_Pause) | 454 | if (advertise & ADVERTISED_Asym_Pause) |
454 | adv |= ADVERTISE_PAUSE_ASYM; | 455 | adv |= ADVERTISE_PAUSE_ASYM; |
455 | 456 | ||
456 | err = phy_write(phydev, MII_ADVERTISE, adv); | 457 | if (adv != oldadv) { |
458 | err = phy_write(phydev, MII_ADVERTISE, adv); | ||
457 | 459 | ||
458 | if (err < 0) | 460 | if (err < 0) |
459 | return err; | 461 | return err; |
462 | changed = 1; | ||
463 | } | ||
460 | 464 | ||
461 | /* Configure gigabit if it's supported */ | 465 | /* Configure gigabit if it's supported */ |
462 | if (phydev->supported & (SUPPORTED_1000baseT_Half | | 466 | if (phydev->supported & (SUPPORTED_1000baseT_Half | |
463 | SUPPORTED_1000baseT_Full)) { | 467 | SUPPORTED_1000baseT_Full)) { |
464 | adv = phy_read(phydev, MII_CTRL1000); | 468 | oldadv = adv = phy_read(phydev, MII_CTRL1000); |
465 | 469 | ||
466 | if (adv < 0) | 470 | if (adv < 0) |
467 | return adv; | 471 | return adv; |
@@ -471,13 +475,17 @@ int genphy_config_advert(struct phy_device *phydev) | |||
471 | adv |= ADVERTISE_1000HALF; | 475 | adv |= ADVERTISE_1000HALF; |
472 | if (advertise & SUPPORTED_1000baseT_Full) | 476 | if (advertise & SUPPORTED_1000baseT_Full) |
473 | adv |= ADVERTISE_1000FULL; | 477 | adv |= ADVERTISE_1000FULL; |
474 | err = phy_write(phydev, MII_CTRL1000, adv); | ||
475 | 478 | ||
476 | if (err < 0) | 479 | if (adv != oldadv) { |
477 | return err; | 480 | err = phy_write(phydev, MII_CTRL1000, adv); |
481 | |||
482 | if (err < 0) | ||
483 | return err; | ||
484 | changed = 1; | ||
485 | } | ||
478 | } | 486 | } |
479 | 487 | ||
480 | return adv; | 488 | return changed; |
481 | } | 489 | } |
482 | EXPORT_SYMBOL(genphy_config_advert); | 490 | EXPORT_SYMBOL(genphy_config_advert); |
483 | 491 | ||
@@ -561,19 +569,22 @@ int genphy_restart_aneg(struct phy_device *phydev) | |||
561 | */ | 569 | */ |
562 | int genphy_config_aneg(struct phy_device *phydev) | 570 | int genphy_config_aneg(struct phy_device *phydev) |
563 | { | 571 | { |
564 | int err = 0; | 572 | int result = 0; |
565 | 573 | ||
566 | if (AUTONEG_ENABLE == phydev->autoneg) { | 574 | if (AUTONEG_ENABLE == phydev->autoneg) { |
567 | err = genphy_config_advert(phydev); | 575 | int result = genphy_config_advert(phydev); |
568 | 576 | ||
569 | if (err < 0) | 577 | if (result < 0) /* error */ |
570 | return err; | 578 | return result; |
571 | 579 | ||
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); | ||
573 | } else | 584 | } else |
574 | err = genphy_setup_forced(phydev); | 585 | result = genphy_setup_forced(phydev); |
575 | 586 | ||
576 | return err; | 587 | return result; |
577 | } | 588 | } |
578 | EXPORT_SYMBOL(genphy_config_aneg); | 589 | EXPORT_SYMBOL(genphy_config_aneg); |
579 | 590 | ||