aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/phy_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/phy_device.c')
-rw-r--r--drivers/net/phy/phy_device.c57
1 files changed, 34 insertions, 23 deletions
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 4b03e63639b7..2f6989b1e0dc 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -683,10 +683,9 @@ EXPORT_SYMBOL(phy_detach);
683int phy_suspend(struct phy_device *phydev) 683int phy_suspend(struct phy_device *phydev)
684{ 684{
685 struct phy_driver *phydrv = to_phy_driver(phydev->dev.driver); 685 struct phy_driver *phydrv = to_phy_driver(phydev->dev.driver);
686 struct ethtool_wolinfo wol; 686 struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
687 687
688 /* If the device has WOL enabled, we cannot suspend the PHY */ 688 /* If the device has WOL enabled, we cannot suspend the PHY */
689 wol.cmd = ETHTOOL_GWOL;
690 phy_ethtool_get_wol(phydev, &wol); 689 phy_ethtool_get_wol(phydev, &wol);
691 if (wol.wolopts) 690 if (wol.wolopts)
692 return -EBUSY; 691 return -EBUSY;
@@ -719,7 +718,7 @@ int phy_resume(struct phy_device *phydev)
719static int genphy_config_advert(struct phy_device *phydev) 718static int genphy_config_advert(struct phy_device *phydev)
720{ 719{
721 u32 advertise; 720 u32 advertise;
722 int oldadv, adv; 721 int oldadv, adv, bmsr;
723 int err, changed = 0; 722 int err, changed = 0;
724 723
725 /* Only allow advertising what this PHY supports */ 724 /* Only allow advertising what this PHY supports */
@@ -744,26 +743,36 @@ static int genphy_config_advert(struct phy_device *phydev)
744 changed = 1; 743 changed = 1;
745 } 744 }
746 745
746 bmsr = phy_read(phydev, MII_BMSR);
747 if (bmsr < 0)
748 return bmsr;
749
750 /* Per 802.3-2008, Section 22.2.4.2.16 Extended status all
751 * 1000Mbits/sec capable PHYs shall have the BMSR_ESTATEN bit set to a
752 * logical 1.
753 */
754 if (!(bmsr & BMSR_ESTATEN))
755 return changed;
756
747 /* Configure gigabit if it's supported */ 757 /* Configure gigabit if it's supported */
758 adv = phy_read(phydev, MII_CTRL1000);
759 if (adv < 0)
760 return adv;
761
762 oldadv = adv;
763 adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
764
748 if (phydev->supported & (SUPPORTED_1000baseT_Half | 765 if (phydev->supported & (SUPPORTED_1000baseT_Half |
749 SUPPORTED_1000baseT_Full)) { 766 SUPPORTED_1000baseT_Full)) {
750 adv = phy_read(phydev, MII_CTRL1000);
751 if (adv < 0)
752 return adv;
753
754 oldadv = adv;
755 adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
756 adv |= ethtool_adv_to_mii_ctrl1000_t(advertise); 767 adv |= ethtool_adv_to_mii_ctrl1000_t(advertise);
757 768 if (adv != oldadv)
758 if (adv != oldadv) {
759 err = phy_write(phydev, MII_CTRL1000, adv);
760
761 if (err < 0)
762 return err;
763 changed = 1; 769 changed = 1;
764 }
765 } 770 }
766 771
772 err = phy_write(phydev, MII_CTRL1000, adv);
773 if (err < 0)
774 return err;
775
767 return changed; 776 return changed;
768} 777}
769 778
@@ -906,6 +915,8 @@ int genphy_read_status(struct phy_device *phydev)
906 int err; 915 int err;
907 int lpa; 916 int lpa;
908 int lpagb = 0; 917 int lpagb = 0;
918 int common_adv;
919 int common_adv_gb = 0;
909 920
910 /* Update the link, but return if there was an error */ 921 /* Update the link, but return if there was an error */
911 err = genphy_update_link(phydev); 922 err = genphy_update_link(phydev);
@@ -927,7 +938,7 @@ int genphy_read_status(struct phy_device *phydev)
927 938
928 phydev->lp_advertising = 939 phydev->lp_advertising =
929 mii_stat1000_to_ethtool_lpa_t(lpagb); 940 mii_stat1000_to_ethtool_lpa_t(lpagb);
930 lpagb &= adv << 2; 941 common_adv_gb = lpagb & adv << 2;
931 } 942 }
932 943
933 lpa = phy_read(phydev, MII_LPA); 944 lpa = phy_read(phydev, MII_LPA);
@@ -940,25 +951,25 @@ int genphy_read_status(struct phy_device *phydev)
940 if (adv < 0) 951 if (adv < 0)
941 return adv; 952 return adv;
942 953
943 lpa &= adv; 954 common_adv = lpa & adv;
944 955
945 phydev->speed = SPEED_10; 956 phydev->speed = SPEED_10;
946 phydev->duplex = DUPLEX_HALF; 957 phydev->duplex = DUPLEX_HALF;
947 phydev->pause = 0; 958 phydev->pause = 0;
948 phydev->asym_pause = 0; 959 phydev->asym_pause = 0;
949 960
950 if (lpagb & (LPA_1000FULL | LPA_1000HALF)) { 961 if (common_adv_gb & (LPA_1000FULL | LPA_1000HALF)) {
951 phydev->speed = SPEED_1000; 962 phydev->speed = SPEED_1000;
952 963
953 if (lpagb & LPA_1000FULL) 964 if (common_adv_gb & LPA_1000FULL)
954 phydev->duplex = DUPLEX_FULL; 965 phydev->duplex = DUPLEX_FULL;
955 } else if (lpa & (LPA_100FULL | LPA_100HALF)) { 966 } else if (common_adv & (LPA_100FULL | LPA_100HALF)) {
956 phydev->speed = SPEED_100; 967 phydev->speed = SPEED_100;
957 968
958 if (lpa & LPA_100FULL) 969 if (common_adv & LPA_100FULL)
959 phydev->duplex = DUPLEX_FULL; 970 phydev->duplex = DUPLEX_FULL;
960 } else 971 } else
961 if (lpa & LPA_10FULL) 972 if (common_adv & LPA_10FULL)
962 phydev->duplex = DUPLEX_FULL; 973 phydev->duplex = DUPLEX_FULL;
963 974
964 if (phydev->duplex == DUPLEX_FULL) { 975 if (phydev->duplex == DUPLEX_FULL) {