summaryrefslogtreecommitdiffstats
path: root/sys/dev/dc
diff options
context:
space:
mode:
authormckay <mckay@FreeBSD.org>2002-04-18 14:40:20 +0000
committermckay <mckay@FreeBSD.org>2002-04-18 14:40:20 +0000
commit8620a542520a67453e8e8f5d9a81c1bcc8544c32 (patch)
tree1f4fcc507264a02dd4e0aba184d6766de8caceef /sys/dev/dc
parent3ff4ea08ea60a63245c6bf4812d0dcab968800ae (diff)
downloadFreeBSD-src-8620a542520a67453e8e8f5d9a81c1bcc8544c32.zip
FreeBSD-src-8620a542520a67453e8e8f5d9a81c1bcc8544c32.tar.gz
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. This could be done better but is the minimal effective change, and most closely mimics what was happening prior to rev 1.56 of if_dc.c. (Actually I also deleted a small amount of unnecessary code while I was in the area.) Reviewed by: wpaul
Diffstat (limited to 'sys/dev/dc')
-rw-r--r--sys/dev/dc/dcphy.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/sys/dev/dc/dcphy.c b/sys/dev/dc/dcphy.c
index daf38c7..e957869 100644
--- a/sys/dev/dc/dcphy.c
+++ b/sys/dev/dc/dcphy.c
@@ -329,17 +329,22 @@ dcphy_service(sc, mii, cmd)
if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
break;
- 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))
break;
/*
* 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))*/
@@ -373,9 +378,7 @@ dcphy_status(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;
OpenPOWER on IntegriCloud