diff options
Diffstat (limited to 'drivers/net/phy/phy_device.c')
-rw-r--r-- | drivers/net/phy/phy_device.c | 54 |
1 files changed, 33 insertions, 21 deletions
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 4b03e63639b7..4b970f7624c0 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
@@ -719,7 +719,7 @@ int phy_resume(struct phy_device *phydev) | |||
719 | static int genphy_config_advert(struct phy_device *phydev) | 719 | static int genphy_config_advert(struct phy_device *phydev) |
720 | { | 720 | { |
721 | u32 advertise; | 721 | u32 advertise; |
722 | int oldadv, adv; | 722 | int oldadv, adv, bmsr; |
723 | int err, changed = 0; | 723 | int err, changed = 0; |
724 | 724 | ||
725 | /* Only allow advertising what this PHY supports */ | 725 | /* Only allow advertising what this PHY supports */ |
@@ -744,26 +744,36 @@ static int genphy_config_advert(struct phy_device *phydev) | |||
744 | changed = 1; | 744 | changed = 1; |
745 | } | 745 | } |
746 | 746 | ||
747 | bmsr = phy_read(phydev, MII_BMSR); | ||
748 | if (bmsr < 0) | ||
749 | return bmsr; | ||
750 | |||
751 | /* Per 802.3-2008, Section 22.2.4.2.16 Extended status all | ||
752 | * 1000Mbits/sec capable PHYs shall have the BMSR_ESTATEN bit set to a | ||
753 | * logical 1. | ||
754 | */ | ||
755 | if (!(bmsr & BMSR_ESTATEN)) | ||
756 | return changed; | ||
757 | |||
747 | /* Configure gigabit if it's supported */ | 758 | /* Configure gigabit if it's supported */ |
759 | adv = phy_read(phydev, MII_CTRL1000); | ||
760 | if (adv < 0) | ||
761 | return adv; | ||
762 | |||
763 | oldadv = adv; | ||
764 | adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); | ||
765 | |||
748 | if (phydev->supported & (SUPPORTED_1000baseT_Half | | 766 | if (phydev->supported & (SUPPORTED_1000baseT_Half | |
749 | SUPPORTED_1000baseT_Full)) { | 767 | 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); | 768 | adv |= ethtool_adv_to_mii_ctrl1000_t(advertise); |
757 | 769 | 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; | 770 | changed = 1; |
764 | } | ||
765 | } | 771 | } |
766 | 772 | ||
773 | err = phy_write(phydev, MII_CTRL1000, adv); | ||
774 | if (err < 0) | ||
775 | return err; | ||
776 | |||
767 | return changed; | 777 | return changed; |
768 | } | 778 | } |
769 | 779 | ||
@@ -906,6 +916,8 @@ int genphy_read_status(struct phy_device *phydev) | |||
906 | int err; | 916 | int err; |
907 | int lpa; | 917 | int lpa; |
908 | int lpagb = 0; | 918 | int lpagb = 0; |
919 | int common_adv; | ||
920 | int common_adv_gb = 0; | ||
909 | 921 | ||
910 | /* Update the link, but return if there was an error */ | 922 | /* Update the link, but return if there was an error */ |
911 | err = genphy_update_link(phydev); | 923 | err = genphy_update_link(phydev); |
@@ -927,7 +939,7 @@ int genphy_read_status(struct phy_device *phydev) | |||
927 | 939 | ||
928 | phydev->lp_advertising = | 940 | phydev->lp_advertising = |
929 | mii_stat1000_to_ethtool_lpa_t(lpagb); | 941 | mii_stat1000_to_ethtool_lpa_t(lpagb); |
930 | lpagb &= adv << 2; | 942 | common_adv_gb = lpagb & adv << 2; |
931 | } | 943 | } |
932 | 944 | ||
933 | lpa = phy_read(phydev, MII_LPA); | 945 | lpa = phy_read(phydev, MII_LPA); |
@@ -940,25 +952,25 @@ int genphy_read_status(struct phy_device *phydev) | |||
940 | if (adv < 0) | 952 | if (adv < 0) |
941 | return adv; | 953 | return adv; |
942 | 954 | ||
943 | lpa &= adv; | 955 | common_adv = lpa & adv; |
944 | 956 | ||
945 | phydev->speed = SPEED_10; | 957 | phydev->speed = SPEED_10; |
946 | phydev->duplex = DUPLEX_HALF; | 958 | phydev->duplex = DUPLEX_HALF; |
947 | phydev->pause = 0; | 959 | phydev->pause = 0; |
948 | phydev->asym_pause = 0; | 960 | phydev->asym_pause = 0; |
949 | 961 | ||
950 | if (lpagb & (LPA_1000FULL | LPA_1000HALF)) { | 962 | if (common_adv_gb & (LPA_1000FULL | LPA_1000HALF)) { |
951 | phydev->speed = SPEED_1000; | 963 | phydev->speed = SPEED_1000; |
952 | 964 | ||
953 | if (lpagb & LPA_1000FULL) | 965 | if (common_adv_gb & LPA_1000FULL) |
954 | phydev->duplex = DUPLEX_FULL; | 966 | phydev->duplex = DUPLEX_FULL; |
955 | } else if (lpa & (LPA_100FULL | LPA_100HALF)) { | 967 | } else if (common_adv & (LPA_100FULL | LPA_100HALF)) { |
956 | phydev->speed = SPEED_100; | 968 | phydev->speed = SPEED_100; |
957 | 969 | ||
958 | if (lpa & LPA_100FULL) | 970 | if (common_adv & LPA_100FULL) |
959 | phydev->duplex = DUPLEX_FULL; | 971 | phydev->duplex = DUPLEX_FULL; |
960 | } else | 972 | } else |
961 | if (lpa & LPA_10FULL) | 973 | if (common_adv & LPA_10FULL) |
962 | phydev->duplex = DUPLEX_FULL; | 974 | phydev->duplex = DUPLEX_FULL; |
963 | 975 | ||
964 | if (phydev->duplex == DUPLEX_FULL) { | 976 | if (phydev->duplex == DUPLEX_FULL) { |