diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2004-11-16 14:26:23 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2004-11-16 14:26:23 +0000 |
commit | b39b9ec7e3b8568e892c39d092605c7e8b221c45 (patch) | |
tree | 0ddd603df711bd81c3e697500c5eeb66d5c83095 /sys | |
parent | 5fe1ebb86d28d9ef634955df7a468c305f7d0c4a (diff) |
if_dc.c rev 1.56
Do not call mii_pollstat() from within device tick routines; the status
information is updated by mii_tick().
dcphy.c rev 1.13
Work around an Intel 21143 chip bug.
Rev 1.56 of if_dc.c removed calls to mii_pollstat() from the dc_tick()
routine. dc_tick() is called regularly to detect link up and link down
status, especially when autonegotiating.
The expectation was that mii_tick() (which is still called from dc_tick())
would update status information automatically in all cases where it would
be sensible to do so.
Unfortunately, with authentic 21143 chips this is not the case, and
the driver never successfully autonegotiates. This is because (despite
what it says in the 21143 manual) the chip always claims that link is not
present while the autonegotiation enable bit is set. Autonegotation takes
place and succeeds, but the driver tests the link bits before it switches
off the autonegotiation enable bit, and success is not recognised.
The simplest solution is to call dcphy_status() more often for MII_TICK
calls by dropping out of the switch statement instead of exiting when
we are autonegotiating and link appears to not be present. When
autonegotiation succeeds, dcphy_status() will note the speed and fdx/hdx
state and turn off the autonegotiation enable bit. The next call to
dcphy_status() will notice that link is present, and the dc driver code
will be notified.
Macronix chips also use this code, but implement link detection as
described in the manual, and hence don't need this patch. However, tests
on a Macronix 98715AEC-C show that it does not adversely affect them.
From FreeBSD
ok deraadt@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ic/dc.c | 15 | ||||
-rw-r--r-- | sys/dev/mii/dcphy.c | 19 |
2 files changed, 17 insertions, 17 deletions
diff --git a/sys/dev/ic/dc.c b/sys/dev/ic/dc.c index b4ed082f430..ad5ba5b7c51 100644 --- a/sys/dev/ic/dc.c +++ b/sys/dev/ic/dc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dc.c,v 1.73 2004/10/29 01:10:43 brad Exp $ */ +/* $OpenBSD: dc.c,v 1.74 2004/11/16 14:26:21 brad Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -2396,14 +2396,11 @@ dc_tick(xsc) * that time, packets will stay in the send queue, and once the * link comes up, they will be flushed out to the wire. */ - if (!sc->dc_link) { - mii_pollstat(mii); - if (mii->mii_media_status & IFM_ACTIVE && - IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { - sc->dc_link++; - if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) - dc_start(ifp); - } + if (!sc->dc_link && mii->mii_media_status & IFM_ACTIVE && + IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { + sc->dc_link++; + if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) + dc_start(ifp); } if (sc->dc_flags & DC_21143_NWAY && !sc->dc_link) diff --git a/sys/dev/mii/dcphy.c b/sys/dev/mii/dcphy.c index 22667f8bdd3..0b68c91cc8b 100644 --- a/sys/dev/mii/dcphy.c +++ b/sys/dev/mii/dcphy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dcphy.c,v 1.10 2004/09/27 18:25:48 brad Exp $ */ +/* $OpenBSD: dcphy.c,v 1.11 2004/11/16 14:26:22 brad Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -283,17 +283,22 @@ dcphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) return (0); - reg = CSR_READ_4(dc_sc, DC_10BTSTAT) & - (DC_TSTAT_LS10|DC_TSTAT_LS100); - + reg = CSR_READ_4(dc_sc, DC_10BTSTAT); if (!(reg & DC_TSTAT_LS10) || !(reg & DC_TSTAT_LS100)) return (0); /* * Only retry autonegotiation every 5 seconds. + * + * Otherwise, fall through to calling dcphy_status() + * since real Intel 21143 chips don't show valid link + * status until autonegotiation is switched off, and + * that only happens in dcphy_status(). Without this, + * successful autonegotation is never recognised on + * these chips. */ if (++sc->mii_ticks != 50) - return (0); + break; sc->mii_ticks = 0; /*if (DC_IS_INTEL(dc_sc))*/ @@ -326,9 +331,7 @@ dcphy_status(struct mii_softc *sc) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) return; - reg = CSR_READ_4(dc_sc, DC_10BTSTAT) & - (DC_TSTAT_LS10|DC_TSTAT_LS100); - + reg = CSR_READ_4(dc_sc, DC_10BTSTAT); if (!(reg & DC_TSTAT_LS10) || !(reg & DC_TSTAT_LS100)) mii->mii_media_status |= IFM_ACTIVE; |