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

Commit 8c5e850c authored by Russell King's avatar Russell King Committed by David S. Miller
Browse files

net: phy: add helper to convert negotiation result to phy settings



Add a helper to convert the result of the autonegotiation advertisment
into the PHYs speed and duplex settings.  If the result is full duplex,
also extract the pause mode settings from the link partner advertisment.

Signed-off-by: default avatarRussell King <rmk+kernel@armlinux.org.uk>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 36c4449a
Loading
Loading
Loading
Loading
+43 −0
Original line number Original line Diff line number Diff line
@@ -189,6 +189,49 @@ size_t phy_speeds(unsigned int *speeds, size_t size,
	return count;
	return count;
}
}


/**
 * phy_resolve_aneg_linkmode - resolve the advertisments into phy settings
 * @phydev: The phy_device struct
 *
 * Resolve our and the link partner advertisments into their corresponding
 * speed and duplex. If full duplex was negotiated, extract the pause mode
 * from the link partner mask.
 */
void phy_resolve_aneg_linkmode(struct phy_device *phydev)
{
	u32 common = phydev->lp_advertising & phydev->advertising;

	if (common & ADVERTISED_10000baseT_Full) {
		phydev->speed = SPEED_10000;
		phydev->duplex = DUPLEX_FULL;
	} else if (common & ADVERTISED_1000baseT_Full) {
		phydev->speed = SPEED_1000;
		phydev->duplex = DUPLEX_FULL;
	} else if (common & ADVERTISED_1000baseT_Half) {
		phydev->speed = SPEED_1000;
		phydev->duplex = DUPLEX_HALF;
	} else if (common & ADVERTISED_100baseT_Full) {
		phydev->speed = SPEED_100;
		phydev->duplex = DUPLEX_FULL;
	} else if (common & ADVERTISED_100baseT_Half) {
		phydev->speed = SPEED_100;
		phydev->duplex = DUPLEX_HALF;
	} else if (common & ADVERTISED_10baseT_Full) {
		phydev->speed = SPEED_10;
		phydev->duplex = DUPLEX_FULL;
	} else if (common & ADVERTISED_10baseT_Half) {
		phydev->speed = SPEED_10;
		phydev->duplex = DUPLEX_HALF;
	}

	if (phydev->duplex == DUPLEX_FULL) {
		phydev->pause = !!(phydev->lp_advertising & ADVERTISED_Pause);
		phydev->asym_pause = !!(phydev->lp_advertising &
					ADVERTISED_Asym_Pause);
	}
}
EXPORT_SYMBOL_GPL(phy_resolve_aneg_linkmode);

static void mmd_phy_indirect(struct mii_bus *bus, int phy_addr, int devad,
static void mmd_phy_indirect(struct mii_bus *bus, int phy_addr, int devad,
			     u16 regnum)
			     u16 regnum)
{
{
+2 −0
Original line number Original line Diff line number Diff line
@@ -690,6 +690,8 @@ phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
size_t phy_speeds(unsigned int *speeds, size_t size,
size_t phy_speeds(unsigned int *speeds, size_t size,
		  unsigned long *mask, size_t maxbit);
		  unsigned long *mask, size_t maxbit);


void phy_resolve_aneg_linkmode(struct phy_device *phydev);

/**
/**
 * phy_read_mmd - Convenience function for reading a register
 * phy_read_mmd - Convenience function for reading a register
 * from an MMD on a given PHY.
 * from an MMD on a given PHY.