git: b38de28a77f4 - main - mii_physubr: Add support for limiting PHY max speed
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 24 Nov 2021 06:41:48 UTC
The branch main has been updated by wma: URL: https://cgit.FreeBSD.org/src/commit/?id=b38de28a77f4d368e0a477e55cb44272359ae9c9 commit b38de28a77f4d368e0a477e55cb44272359ae9c9 Author: Kornel Duleba <mindal@semihalf.com> AuthorDate: 2021-11-15 08:49:27 +0000 Commit: Wojciech Macek <wma@FreeBSD.org> CommitDate: 2021-11-24 06:40:35 +0000 mii_physubr: Add support for limiting PHY max speed In some cases we might want to limit the max speed advertised below of what the PHY is capable of. This is usually the case when we connect 1G capable PHY to 100M MAC, or when some exotic physical connection is used. Add a new mii_maxspeed field to mii_softc and parse it in mii_phy_dev_attach. Speed limit is normally located in DT. The property is already parsed in mii_fdt.c, but its value still has to be passed by the PHY driver. Obtained from: Semihalf Sponsored by: Alstom Group Differential revision: https://reviews.freebsd.org/D32727 --- sys/dev/mii/mii_physubr.c | 36 ++++++++++++++++++++++++++++++++++++ sys/dev/mii/miivar.h | 1 + 2 files changed, 37 insertions(+) diff --git a/sys/dev/mii/mii_physubr.c b/sys/dev/mii/mii_physubr.c index f56676d4e091..4ddb7d621652 100644 --- a/sys/dev/mii/mii_physubr.c +++ b/sys/dev/mii/mii_physubr.c @@ -618,11 +618,47 @@ mii_phy_dev_attach(device_t dev, u_int flags, const struct mii_phy_funcs *mpf, sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & sc->mii_capmask; if (sc->mii_capabilities & BMSR_EXTSTAT) sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); + + switch (sc->mii_maxspeed) { + case 100: + /* + * This is a bit tricky. + * If we have a 1G capable PHY, but we don't want to advertise + * 1G capabilities we need to clear the GTCR register before + * doing autonegotiation. + * Clearing the register here is not enough since its value + * can be restored after PHY_RESET is called. + */ + if ((sc->mii_extcapabilities & + (EXTSR_1000THDX | EXTSR_1000TFDX)) != 0) + sc->mii_flags |= MIIF_HAVE_GTCR; + + sc->mii_extcapabilities = 0; + break; + default: + device_printf(dev, + "Ignoring unsupported max speed value of %d\n", + sc->mii_maxspeed); + case 0: + case 1000: + break; + } device_printf(dev, " "); mii_phy_add_media(sc); printf("\n"); MIIBUS_MEDIAINIT(sc->mii_dev); + + /* + * If maxspeed was specified we have to restart autonegotiation. + * PHY might have attempted it and failed due to having mistakenly + * advertising modes that we do not in fact support. + */ + if (sc->mii_maxspeed != 0) { + sc->mii_flags |= MIIF_FORCEANEG; + mii_phy_setmedia(sc); + sc->mii_flags &= ~MIIF_FORCEANEG; + } } /* diff --git a/sys/dev/mii/miivar.h b/sys/dev/mii/miivar.h index 4658394797e9..cf8032f1eb53 100644 --- a/sys/dev/mii/miivar.h +++ b/sys/dev/mii/miivar.h @@ -117,6 +117,7 @@ struct mii_softc { u_int mii_anegticks; /* ticks before retrying aneg */ u_int mii_media_active; /* last active media */ u_int mii_media_status; /* last active status */ + u_int mii_maxspeed; /* Max speed supported by this PHY */ }; typedef struct mii_softc mii_softc_t;