Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc0f4a87 authored by Andrew Lunn's avatar Andrew Lunn Committed by David S. Miller
Browse files

net: phy: fixed_phy: Set phy capabilities even when link down.



What features a phy supports is masked in genphy_config_init() by
looking at the PHYs BMSR register.

If the link is down, fixed_phy_update_regs() will only set the auto-
negotiation capable bit in BMSR. Thus genphy_config_init() comes to
the conclusion the PHY can only perform 10/Half, and masks out the
higher speed features. If however the link it up, BMSR is set to
indicate the speed the PHY is capable of auto-negotiating, and
genphy_config_init() does not mask out the high speed features.

To fix this, when the link is down, have fixed_phy_update_regs() leave
the link status, auto-negotiation complete, and link partner
capabilities unset, but set all the local capabilities depending on
the fixed phy speed.

Signed-off-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a5597008
Loading
Loading
Loading
Loading
+48 −25
Original line number Diff line number Diff line
@@ -57,8 +57,37 @@ static int fixed_phy_update_regs(struct fixed_phy *fp)
	if (gpio_is_valid(fp->link_gpio))
		fp->status.link = !!gpio_get_value_cansleep(fp->link_gpio);

	if (!fp->status.link)
		goto done;
	if (fp->status.duplex) {
		switch (fp->status.speed) {
		case 1000:
			bmsr |= BMSR_ESTATEN;
			break;
		case 100:
			bmsr |= BMSR_100FULL;
			break;
		case 10:
			bmsr |= BMSR_10FULL;
			break;
		default:
			break;
		}
	} else {
		switch (fp->status.speed) {
		case 1000:
			bmsr |= BMSR_ESTATEN;
			break;
		case 100:
			bmsr |= BMSR_100HALF;
			break;
		case 10:
			bmsr |= BMSR_10HALF;
			break;
		default:
			break;
		}
	}

	if (fp->status.link) {
		bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE;

		if (fp->status.duplex) {
@@ -66,17 +95,14 @@ static int fixed_phy_update_regs(struct fixed_phy *fp)

			switch (fp->status.speed) {
			case 1000:
			bmsr |= BMSR_ESTATEN;
				bmcr |= BMCR_SPEED1000;
				lpagb |= LPA_1000FULL;
				break;
			case 100:
			bmsr |= BMSR_100FULL;
				bmcr |= BMCR_SPEED100;
				lpa |= LPA_100FULL;
				break;
			case 10:
			bmsr |= BMSR_10FULL;
				lpa |= LPA_10FULL;
				break;
			default:
@@ -86,17 +112,14 @@ static int fixed_phy_update_regs(struct fixed_phy *fp)
		} else {
			switch (fp->status.speed) {
			case 1000:
			bmsr |= BMSR_ESTATEN;
				bmcr |= BMCR_SPEED1000;
				lpagb |= LPA_1000HALF;
				break;
			case 100:
			bmsr |= BMSR_100HALF;
				bmcr |= BMCR_SPEED100;
				lpa |= LPA_100HALF;
				break;
			case 10:
			bmsr |= BMSR_10HALF;
				lpa |= LPA_10HALF;
				break;
			default:
@@ -110,8 +133,8 @@ static int fixed_phy_update_regs(struct fixed_phy *fp)

		if (fp->status.asym_pause)
			lpa |= LPA_PAUSE_ASYM;
	}

done:
	fp->regs[MII_PHYSID1] = 0;
	fp->regs[MII_PHYSID2] = 0;