e1000: Try auto-negotiation for fixed 100 or 10 configuration

Currently if an e1000 interface is set to a fixed media configuration,
for gigabit, it will participate in auto-negotiation as required by
IEEE 802.3-2018 Clause 37. However, if set to fixed media configuration
for 100 or 10, it does NOT participate in auto-negotiation.

By my reading of Clauses 28 and 37, while auto-negotiation is optional
for 100 and 10, it is not prohibited and is, in fact, "highly
recommended".

This patch enables auto-negotiation for fixed 100 and 10 media
configuration, in a similar manner to that already performed for 1000.
I.e., the patch enables advertising of just the manually configured
settings with the goal of allowing the remote end to match the manually
configured settings if it has them available.

To be clear, this patch does NOT allow an em(4) interface that has been
manually configured with specific media settings to respond to
auto-negotiation by then configuring different parameters to those that
were manually configured. The intent of this patch is to fully comply
with the requirements of Clause 37, but for 100 and 10.

The need for this has arisen on an em(4) link where the other end is
under a different administrative control and is set to full
auto-negotiation. Due to the cable length GigE is not working well. It
is desired to set the em(4) end to "media 100baseTX mediatype
full-duplex" which does work when both ends are configured that way.
Currently, because em(4) does not participate in autoneg for this
setting, the remote defaults to half-duplex - i.e., there's a duplex
mismatch and things don't work. With this patch, em(4) would inform the
remote that it has only 100baseTX full, the remote would match that and
it will work.

Approved by:	erj
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D34449
This commit is contained in:
J.R. Oldroyd 2022-04-13 09:11:30 -07:00 committed by Kevin Bowling
parent 07ede75161
commit 9ab4dfce8f

View File

@ -1628,20 +1628,24 @@ em_if_media_change(if_ctx_t ctx)
sc->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL;
break;
case IFM_100_TX:
sc->hw.mac.autoneg = false;
sc->hw.phy.autoneg_advertised = 0;
if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX)
sc->hw.mac.autoneg = DO_AUTO_NEG;
if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) {
sc->hw.phy.autoneg_advertised = ADVERTISE_100_FULL;
sc->hw.mac.forced_speed_duplex = ADVERTISE_100_FULL;
else
} else {
sc->hw.phy.autoneg_advertised = ADVERTISE_100_HALF;
sc->hw.mac.forced_speed_duplex = ADVERTISE_100_HALF;
}
break;
case IFM_10_T:
sc->hw.mac.autoneg = false;
sc->hw.phy.autoneg_advertised = 0;
if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX)
sc->hw.mac.autoneg = DO_AUTO_NEG;
if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) {
sc->hw.phy.autoneg_advertised = ADVERTISE_10_FULL;
sc->hw.mac.forced_speed_duplex = ADVERTISE_10_FULL;
else
} else {
sc->hw.phy.autoneg_advertised = ADVERTISE_10_HALF;
sc->hw.mac.forced_speed_duplex = ADVERTISE_10_HALF;
}
break;
default:
device_printf(sc->dev, "Unsupported media type\n");