summaryrefslogtreecommitdiffstats
path: root/sys/dev/sf
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2001-08-16 00:32:20 +0000
committerwpaul <wpaul@FreeBSD.org>2001-08-16 00:32:20 +0000
commit63a42f31d018af8ee2b9e9e9125007af2b915337 (patch)
tree49620f04136f9649e8165e06b1b3b05f09fd9a53 /sys/dev/sf
parent35478e0db2b6c2bf559b202fa009a2dd0ce06fb8 (diff)
downloadFreeBSD-src-63a42f31d018af8ee2b9e9e9125007af2b915337.zip
FreeBSD-src-63a42f31d018af8ee2b9e9e9125007af2b915337.tar.gz
Still more changes to try to prevent TX lockups. Will wait for one more
night of testing before merging to -stable. Also added to code to detect TX underruns and automatically increase the TX threshold to avoid them. Carefully placed diagnostig printf() about this under #ifdef DIAGNOSTIC to avoid getting any panicky e-mails from confused users, like I always do with the xl and dc drivers.
Diffstat (limited to 'sys/dev/sf')
-rw-r--r--sys/dev/sf/if_sf.c52
-rw-r--r--sys/dev/sf/if_sfreg.h3
2 files changed, 48 insertions, 7 deletions
diff --git a/sys/dev/sf/if_sf.c b/sys/dev/sf/if_sf.c
index 69f5bc1..8f5fec3 100644
--- a/sys/dev/sf/if_sf.c
+++ b/sys/dev/sf/if_sf.c
@@ -170,6 +170,7 @@ static void sf_miibus_statchg __P((device_t));
static u_int32_t csr_read_4 __P((struct sf_softc *, int));
static void csr_write_4 __P((struct sf_softc *, int, u_int32_t));
+static void sf_txthresh_adjust __P((struct sf_softc *));
#ifdef SF_USEIOSPACE
#define SF_RES SYS_RES_IOPORT
@@ -1039,18 +1040,22 @@ static void sf_txeof(sc)
while (cmpconsidx != cmpprodidx) {
cur_cmp = &sc->sf_ldata->sf_tx_clist[cmpconsidx];
cur_tx = &sc->sf_ldata->sf_tx_dlist[cur_cmp->sf_index >> 7];
- SF_INC(cmpconsidx, SF_TX_CLIST_CNT);
if (cur_cmp->sf_txstat & SF_TXSTAT_TX_OK)
ifp->if_opackets++;
- else
+ else {
+ if (cur_cmp->sf_txstat & SF_TXSTAT_TX_UNDERRUN)
+ sf_txthresh_adjust(sc);
ifp->if_oerrors++;
+ }
sc->sf_tx_cnt--;
if (cur_tx->sf_mbuf != NULL) {
m_freem(cur_tx->sf_mbuf);
cur_tx->sf_mbuf = NULL;
- }
+ } else
+ break;
+ SF_INC(cmpconsidx, SF_TX_CLIST_CNT);
}
ifp->if_timer = 0;
@@ -1063,6 +1068,29 @@ static void sf_txeof(sc)
return;
}
+static void sf_txthresh_adjust(sc)
+ struct sf_softc *sc;
+{
+ u_int32_t txfctl;
+ u_int8_t txthresh;
+
+ txfctl = csr_read_4(sc, SF_TX_FRAMCTL);
+ txthresh = txfctl & SF_TXFRMCTL_TXTHRESH;
+ if (txthresh < 0xFF) {
+ txthresh++;
+ txfctl &= ~SF_TXFRMCTL_TXTHRESH;
+ txfctl |= txthresh;
+#ifdef DIAGNOSTIC
+ printf("sf%d: tx underrun, increasing "
+ "tx threshold to %d bytes\n",
+ sc->sf_unit, txthresh * 4);
+#endif
+ csr_write_4(sc, SF_TX_FRAMCTL, txfctl);
+ }
+
+ return;
+}
+
static void sf_intr(arg)
void *arg;
{
@@ -1096,10 +1124,12 @@ static void sf_intr(arg)
if (status & SF_ISR_TX_TXDONE ||
status & SF_ISR_TX_DMADONE ||
- status & SF_ISR_TX_QUEUEDONE ||
- status & SF_ISR_TX_LOFIFO)
+ status & SF_ISR_TX_QUEUEDONE)
sf_txeof(sc);
+ if (status & SF_ISR_TX_LOFIFO)
+ sf_txthresh_adjust(sc);
+
if (status & SF_ISR_ABNORMALINTR) {
if (status & SF_ISR_STATSOFLOW) {
untimeout(sf_stats_update, sc,
@@ -1318,11 +1348,21 @@ static void sf_start(ifp)
return;
}
+ if (sc->sf_tx_cnt)
+ sf_txeof(sc);
+
txprod = csr_read_4(sc, SF_TXDQ_PRODIDX);
i = SF_IDX_HI(txprod) >> 4;
+ if (sc->sf_ldata->sf_tx_dlist[i].sf_mbuf != NULL) {
+ printf("sf%d: TX ring full, resetting\n", sc->sf_unit);
+ sf_init(sc);
+ txprod = csr_read_4(sc, SF_TXDQ_PRODIDX);
+ i = SF_IDX_HI(txprod) >> 4;
+ }
+
while(sc->sf_ldata->sf_tx_dlist[i].sf_mbuf == NULL) {
- if (sc->sf_tx_cnt == (SF_TX_DLIST_CNT - 2)) {
+ if (sc->sf_tx_cnt >= (SF_TX_DLIST_CNT - 5)) {
ifp->if_flags |= IFF_OACTIVE;
cur_tx = NULL;
break;
diff --git a/sys/dev/sf/if_sfreg.h b/sys/dev/sf/if_sfreg.h
index fd2107f..1975cfc 100644
--- a/sys/dev/sf/if_sfreg.h
+++ b/sys/dev/sf/if_sfreg.h
@@ -349,7 +349,8 @@
(SF_IMR_RXDQ2_NOBUFS|SF_IMR_RXDQ1_DMADONE|SF_IMR_RXDQ2_DMADONE| \
SF_IMR_TX_TXDONE|SF_IMR_RXDQ1_NOBUFS|SF_IMR_RXDQ2_DMADONE| \
SF_IMR_NORMALINTR|SF_IMR_ABNORMALINTR|SF_IMR_TXCQ_NOBUFS| \
- SF_IMR_RXCQ1_NOBUFS|SF_IMR_RXCQ2_NOBUFS|SF_IMR_STATSOFLOW)
+ SF_IMR_RXCQ1_NOBUFS|SF_IMR_RXCQ2_NOBUFS|SF_IMR_STATSOFLOW| \
+ SF_IMR_TX_LOFIFO)
/* TX descriptor queue control registers */
#define SF_TXDQCTL_DESCTYPE 0x00000007
OpenPOWER on IntegriCloud