Apply patch to allow TX underrun handling without issuing a complete

chip reset. Just temporarily turn off the transmitter instead.

Submitted by:	Stephen McKay <mckay@freebsd.org>
This commit is contained in:
wpaul 2001-02-22 19:26:55 +00:00
parent aba557bd7c
commit 10926b121d
4 changed files with 128 additions and 52 deletions

View File

@ -203,6 +203,7 @@ static int dc_rx_resync __P((struct dc_softc *));
static void dc_rxeof __P((struct dc_softc *));
static void dc_txeof __P((struct dc_softc *));
static void dc_tick __P((void *));
static void dc_tx_underrun __P((struct dc_softc *));
static void dc_intr __P((void *));
static void dc_start __P((struct ifnet *));
static int dc_ioctl __P((struct ifnet *, u_long, caddr_t));
@ -1317,17 +1318,16 @@ static void dc_setcfg(sc, media)
DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_TX_ON|DC_NETCFG_RX_ON));
for (i = 0; i < DC_TIMEOUT; i++) {
DELAY(10);
isr = CSR_READ_4(sc, DC_ISR);
if (isr & DC_ISR_TX_IDLE ||
if (isr & DC_ISR_TX_IDLE &&
(isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED)
break;
DELAY(10);
}
if (i == DC_TIMEOUT)
printf("dc%d: failed to force tx and "
"rx to idle state\n", sc->dc_unit);
}
if (IFM_SUBTYPE(media) == IFM_100_TX) {
@ -2705,6 +2705,57 @@ static void dc_tick(xsc)
return;
}
/*
* A transmit underrun has occurred. Back off the transmit threshold,
* or switch to store and forward mode if we have to.
*/
static void dc_tx_underrun(sc)
struct dc_softc *sc;
{
u_int32_t isr;
int i;
if (DC_IS_DAVICOM(sc))
dc_init(sc);
if (DC_IS_INTEL(sc)) {
/*
* The real 21143 requires that the transmitter be idle
* in order to change the transmit threshold or store
* and forward state.
*/
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
for (i = 0; i < DC_TIMEOUT; i++) {
isr = CSR_READ_4(sc, DC_ISR);
if (isr & DC_ISR_TX_IDLE)
break;
DELAY(10);
}
if (i == DC_TIMEOUT) {
printf("dc%d: failed to force tx to idle state\n",
sc->dc_unit);
dc_init(sc);
}
}
printf("dc%d: TX underrun -- ", sc->dc_unit);
sc->dc_txthresh += DC_TXTHRESH_INC;
if (sc->dc_txthresh > DC_TXTHRESH_MAX) {
printf("using store and forward mode\n");
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
} else {
printf("increasing TX threshold\n");
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_THRESH);
DC_SETBIT(sc, DC_NETCFG, sc->dc_txthresh);
}
if (DC_IS_INTEL(sc))
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
return;
}
static void dc_intr(arg)
void *arg;
{
@ -2757,27 +2808,8 @@ static void dc_intr(arg)
}
}
if (status & DC_ISR_TX_UNDERRUN) {
u_int32_t cfg;
printf("dc%d: TX underrun -- ", sc->dc_unit);
if (DC_IS_DAVICOM(sc) || DC_IS_INTEL(sc))
dc_init(sc);
cfg = CSR_READ_4(sc, DC_NETCFG);
cfg &= ~DC_NETCFG_TX_THRESH;
if (sc->dc_txthresh == DC_TXTHRESH_160BYTES) {
printf("using store and forward mode\n");
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
} else if (sc->dc_flags & DC_TX_STORENFWD) {
printf("resetting\n");
} else {
sc->dc_txthresh += 0x4000;
printf("increasing TX threshold\n");
CSR_WRITE_4(sc, DC_NETCFG, cfg);
DC_SETBIT(sc, DC_NETCFG, sc->dc_txthresh);
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
}
}
if (status & DC_ISR_TX_UNDERRUN)
dc_tx_underrun(sc);
if ((status & DC_ISR_RX_WATDOGTIMEO)
|| (status & DC_ISR_RX_NOBUF)) {
@ -3031,7 +3063,7 @@ static void dc_init(xsc)
if (sc->dc_flags & DC_TX_STORENFWD)
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
else {
if (sc->dc_txthresh == DC_TXTHRESH_160BYTES) {
if (sc->dc_txthresh > DC_TXTHRESH_MAX) {
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
} else {
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
@ -3072,7 +3104,7 @@ static void dc_init(xsc)
}
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_THRESH);
DC_SETBIT(sc, DC_NETCFG, DC_TXTHRESH_72BYTES);
DC_SETBIT(sc, DC_NETCFG, DC_TXTHRESH_MIN);
/* Init circular RX list. */
if (dc_list_rx_init(sc) == ENOBUFS) {

View File

@ -220,10 +220,16 @@
#define DC_OPMODE_INTLOOP 0x00000400
#define DC_OPMODE_EXTLOOP 0x00000800
#if 0
#define DC_TXTHRESH_72BYTES 0x00000000
#define DC_TXTHRESH_96BYTES 0x00004000
#define DC_TXTHRESH_128BYTES 0x00008000
#define DC_TXTHRESH_160BYTES 0x0000C000
#endif
#define DC_TXTHRESH_MIN 0x00000000
#define DC_TXTHRESH_INC 0x00004000
#define DC_TXTHRESH_MAX 0x0000C000
/*

View File

@ -203,6 +203,7 @@ static int dc_rx_resync __P((struct dc_softc *));
static void dc_rxeof __P((struct dc_softc *));
static void dc_txeof __P((struct dc_softc *));
static void dc_tick __P((void *));
static void dc_tx_underrun __P((struct dc_softc *));
static void dc_intr __P((void *));
static void dc_start __P((struct ifnet *));
static int dc_ioctl __P((struct ifnet *, u_long, caddr_t));
@ -1317,17 +1318,16 @@ static void dc_setcfg(sc, media)
DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_TX_ON|DC_NETCFG_RX_ON));
for (i = 0; i < DC_TIMEOUT; i++) {
DELAY(10);
isr = CSR_READ_4(sc, DC_ISR);
if (isr & DC_ISR_TX_IDLE ||
if (isr & DC_ISR_TX_IDLE &&
(isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED)
break;
DELAY(10);
}
if (i == DC_TIMEOUT)
printf("dc%d: failed to force tx and "
"rx to idle state\n", sc->dc_unit);
}
if (IFM_SUBTYPE(media) == IFM_100_TX) {
@ -2705,6 +2705,57 @@ static void dc_tick(xsc)
return;
}
/*
* A transmit underrun has occurred. Back off the transmit threshold,
* or switch to store and forward mode if we have to.
*/
static void dc_tx_underrun(sc)
struct dc_softc *sc;
{
u_int32_t isr;
int i;
if (DC_IS_DAVICOM(sc))
dc_init(sc);
if (DC_IS_INTEL(sc)) {
/*
* The real 21143 requires that the transmitter be idle
* in order to change the transmit threshold or store
* and forward state.
*/
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
for (i = 0; i < DC_TIMEOUT; i++) {
isr = CSR_READ_4(sc, DC_ISR);
if (isr & DC_ISR_TX_IDLE)
break;
DELAY(10);
}
if (i == DC_TIMEOUT) {
printf("dc%d: failed to force tx to idle state\n",
sc->dc_unit);
dc_init(sc);
}
}
printf("dc%d: TX underrun -- ", sc->dc_unit);
sc->dc_txthresh += DC_TXTHRESH_INC;
if (sc->dc_txthresh > DC_TXTHRESH_MAX) {
printf("using store and forward mode\n");
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
} else {
printf("increasing TX threshold\n");
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_THRESH);
DC_SETBIT(sc, DC_NETCFG, sc->dc_txthresh);
}
if (DC_IS_INTEL(sc))
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
return;
}
static void dc_intr(arg)
void *arg;
{
@ -2757,27 +2808,8 @@ static void dc_intr(arg)
}
}
if (status & DC_ISR_TX_UNDERRUN) {
u_int32_t cfg;
printf("dc%d: TX underrun -- ", sc->dc_unit);
if (DC_IS_DAVICOM(sc) || DC_IS_INTEL(sc))
dc_init(sc);
cfg = CSR_READ_4(sc, DC_NETCFG);
cfg &= ~DC_NETCFG_TX_THRESH;
if (sc->dc_txthresh == DC_TXTHRESH_160BYTES) {
printf("using store and forward mode\n");
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
} else if (sc->dc_flags & DC_TX_STORENFWD) {
printf("resetting\n");
} else {
sc->dc_txthresh += 0x4000;
printf("increasing TX threshold\n");
CSR_WRITE_4(sc, DC_NETCFG, cfg);
DC_SETBIT(sc, DC_NETCFG, sc->dc_txthresh);
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
}
}
if (status & DC_ISR_TX_UNDERRUN)
dc_tx_underrun(sc);
if ((status & DC_ISR_RX_WATDOGTIMEO)
|| (status & DC_ISR_RX_NOBUF)) {
@ -3031,7 +3063,7 @@ static void dc_init(xsc)
if (sc->dc_flags & DC_TX_STORENFWD)
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
else {
if (sc->dc_txthresh == DC_TXTHRESH_160BYTES) {
if (sc->dc_txthresh > DC_TXTHRESH_MAX) {
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
} else {
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
@ -3072,7 +3104,7 @@ static void dc_init(xsc)
}
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_THRESH);
DC_SETBIT(sc, DC_NETCFG, DC_TXTHRESH_72BYTES);
DC_SETBIT(sc, DC_NETCFG, DC_TXTHRESH_MIN);
/* Init circular RX list. */
if (dc_list_rx_init(sc) == ENOBUFS) {

View File

@ -220,10 +220,16 @@
#define DC_OPMODE_INTLOOP 0x00000400
#define DC_OPMODE_EXTLOOP 0x00000800
#if 0
#define DC_TXTHRESH_72BYTES 0x00000000
#define DC_TXTHRESH_96BYTES 0x00004000
#define DC_TXTHRESH_128BYTES 0x00008000
#define DC_TXTHRESH_160BYTES 0x0000C000
#endif
#define DC_TXTHRESH_MIN 0x00000000
#define DC_TXTHRESH_INC 0x00004000
#define DC_TXTHRESH_MAX 0x0000C000
/*