Skip to content

Commit 05d539c

Browse files
Ansuelfrank-w
authored andcommitted
net: phy: as21xxx: fix read_status speed handling
With further test with 2.5G NIC it was discovered that phy_resolve_aneg_linkmode is not enough to detect speed higher that 1G when autoneg is enabled. Also in the switch case there is a typo where the speed mask is AND with VEND1_SPEED_STATUS instead of the correct mask VEND1_SPEED_MASK. Rework the read_status code to always read the speed from the vendor register and parse the generic bit only for the pause frame. Fixes: 830877d ("net: phy: Add support for Aeonsemi AS21xxx PHYs") Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
1 parent 72c9243 commit 05d539c

1 file changed

Lines changed: 53 additions & 43 deletions

File tree

drivers/net/phy/as21xxx.c

Lines changed: 53 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,7 @@ static int as21xxx_read_link(struct phy_device *phydev, int *bmcr)
671671

672672
static int as21xxx_read_c22_lpa(struct phy_device *phydev)
673673
{
674-
int lpagb;
674+
int lpagb, lpa;
675675

676676
/* MII_STAT1000 are only filled in the mapped C22
677677
* in C45, use that to fill lpagb values and check.
@@ -698,12 +698,20 @@ static int as21xxx_read_c22_lpa(struct phy_device *phydev)
698698
mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising,
699699
lpagb);
700700

701+
lpa = phy_read_mmd(phydev, MDIO_MMD_AN,
702+
AS21XXX_MDIO_AN_C22 + MII_LPA);
703+
if (lpa < 0)
704+
return lpa;
705+
706+
mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, lpa);
707+
701708
return 0;
702709
}
703710

704711
static int as21xxx_read_status(struct phy_device *phydev)
705712
{
706713
int bmcr, old_link = phydev->link;
714+
int speed;
707715
int ret;
708716

709717
ret = as21xxx_read_link(phydev, &bmcr);
@@ -720,58 +728,60 @@ static int as21xxx_read_status(struct phy_device *phydev)
720728
phydev->asym_pause = 0;
721729

722730
if (phydev->autoneg == AUTONEG_ENABLE) {
723-
ret = genphy_c45_read_lpa(phydev);
724-
if (ret)
725-
return ret;
731+
if (!phydev->autoneg_complete) {
732+
mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising,
733+
0);
734+
mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, 0);
735+
return 0;
736+
}
726737

727738
ret = as21xxx_read_c22_lpa(phydev);
728739
if (ret)
729740
return ret;
730-
731-
phy_resolve_aneg_linkmode(phydev);
732741
} else {
733-
int speed;
734-
735742
linkmode_zero(phydev->lp_advertising);
743+
}
736744

737-
speed = phy_read_mmd(phydev, MDIO_MMD_VEND1,
738-
VEND1_SPEED_STATUS);
739-
if (speed < 0)
740-
return speed;
741-
742-
switch (speed & VEND1_SPEED_STATUS) {
743-
case VEND1_SPEED_10000:
744-
phydev->speed = SPEED_10000;
745-
phydev->duplex = DUPLEX_FULL;
746-
break;
747-
case VEND1_SPEED_5000:
748-
phydev->speed = SPEED_5000;
749-
phydev->duplex = DUPLEX_FULL;
750-
break;
751-
case VEND1_SPEED_2500:
752-
phydev->speed = SPEED_2500;
753-
phydev->duplex = DUPLEX_FULL;
754-
break;
755-
case VEND1_SPEED_1000:
756-
phydev->speed = SPEED_1000;
757-
if (bmcr & BMCR_FULLDPLX)
758-
phydev->duplex = DUPLEX_FULL;
759-
else
760-
phydev->duplex = DUPLEX_HALF;
761-
break;
762-
case VEND1_SPEED_100:
763-
phydev->speed = SPEED_100;
745+
speed = phy_read_mmd(phydev, MDIO_MMD_VEND1,
746+
VEND1_SPEED_STATUS);
747+
if (speed < 0)
748+
return speed;
749+
750+
switch (speed & VEND1_SPEED_MASK) {
751+
case VEND1_SPEED_10000:
752+
phydev->speed = SPEED_10000;
753+
phydev->duplex = DUPLEX_FULL;
754+
break;
755+
case VEND1_SPEED_5000:
756+
phydev->speed = SPEED_5000;
757+
phydev->duplex = DUPLEX_FULL;
758+
break;
759+
case VEND1_SPEED_2500:
760+
phydev->speed = SPEED_2500;
761+
phydev->duplex = DUPLEX_FULL;
762+
break;
763+
case VEND1_SPEED_1000:
764+
phydev->speed = SPEED_1000;
765+
if (bmcr & BMCR_FULLDPLX)
764766
phydev->duplex = DUPLEX_FULL;
765-
break;
766-
case VEND1_SPEED_10:
767-
phydev->speed = SPEED_10;
768-
phydev->duplex = DUPLEX_FULL;
769-
break;
770-
default:
771-
return -EINVAL;
772-
}
767+
else
768+
phydev->duplex = DUPLEX_HALF;
769+
break;
770+
case VEND1_SPEED_100:
771+
phydev->speed = SPEED_100;
772+
phydev->duplex = DUPLEX_FULL;
773+
break;
774+
case VEND1_SPEED_10:
775+
phydev->speed = SPEED_10;
776+
phydev->duplex = DUPLEX_FULL;
777+
break;
778+
default:
779+
return -EINVAL;
773780
}
774781

782+
if (phydev->autoneg == AUTONEG_ENABLE)
783+
phy_resolve_aneg_pause(phydev);
784+
775785
return 0;
776786
}
777787

0 commit comments

Comments
 (0)