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
This commit is contained in:
Stephen McKay 2002-04-18 14:40:20 +00:00
parent 8383349061
commit e3c5a44915
2 changed files with 20 additions and 14 deletions

View File

@ -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;

View File

@ -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;