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:
parent
aba557bd7c
commit
10926b121d
@ -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) {
|
||||
|
@ -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
|
||||
|
||||
|
||||
/*
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user