summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>1999-10-21 19:42:03 +0000
committerwpaul <wpaul@FreeBSD.org>1999-10-21 19:42:03 +0000
commit6ac7cdd7154bae972f2dabc8a960faafc7607ed9 (patch)
treefb11a26f4ba217bd7b4f9ca728c68f086a925cfe
parente2a07af8e9edccde7317330a3790e61a69e2784f (diff)
downloadFreeBSD-src-6ac7cdd7154bae972f2dabc8a960faafc7607ed9.zip
FreeBSD-src-6ac7cdd7154bae972f2dabc8a960faafc7607ed9.tar.gz
Make some tweaks to the RealTek driver:
- Fix a bug in rl_rxeof() handler: in the case where the packet wraps from the end of the receive buffer back to the beginning, we need to insure that at least sizeof(ether_header) bytes make it into the first mbuf. If we don't, then doing eh = mtod(m, struct ether_header *) loses. To avoid this, we use m_pullup() to suck at least MHLEN - RL_ETHER_ALIGN bytes into the first mbuf, which should also help small packets fit into a single mbuf. Pointed out by: Philip A. Prindeville <philipp@zembu.com> - Make the transmit threshold autotuning: start off with a small value and jack it up when TX underruns are detected. - Also improve TX error recovery: kick the chip in the head with a reset/init sequence to make sure it recovers afer a transmit error.
-rw-r--r--sys/pci/if_rl.c36
-rw-r--r--sys/pci/if_rlreg.h4
2 files changed, 28 insertions, 12 deletions
diff --git a/sys/pci/if_rl.c b/sys/pci/if_rl.c
index a2e789d..bd90b70 100644
--- a/sys/pci/if_rl.c
+++ b/sys/pci/if_rl.c
@@ -988,7 +988,7 @@ static int rl_detach(dev)
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->rl_res);
bus_release_resource(dev, RL_RES, RL_RID, sc->rl_res);
- free(sc->rl_cdata.rl_rx_buf, M_DEVBUF);
+ contigfree(sc->rl_cdata.rl_rx_buf, RL_RXBUFLEN + 32, M_DEVBUF);
splx(s);
@@ -1125,12 +1125,12 @@ static void rl_rxeof(sc)
if (m == NULL) {
ifp->if_ierrors++;
printf("rl%d: out of mbufs, tried to "
- "copy %d bytes\n", sc->rl_unit, wrap);
- }
- else {
+ "copy %d bytes\n", sc->rl_unit, wrap);
+ } else {
m_adj(m, RL_ETHER_ALIGN);
m_copyback(m, wrap, total_len - wrap,
sc->rl_cdata.rl_rx_buf);
+ m_pullup(m, MHLEN - RL_ETHER_ALIGN);
}
cur_rx = (total_len - wrap + ETHER_CRC_LEN);
} else {
@@ -1139,7 +1139,7 @@ static void rl_rxeof(sc)
if (m == NULL) {
ifp->if_ierrors++;
printf("rl%d: out of mbufs, tried to "
- "copy %d bytes\n", sc->rl_unit, total_len);
+ "copy %d bytes\n", sc->rl_unit, total_len);
} else
m_adj(m, RL_ETHER_ALIGN);
cur_rx += total_len + 4 + ETHER_CRC_LEN;
@@ -1216,10 +1216,22 @@ static void rl_txeof(sc)
if (txstat & RL_TXSTAT_TX_OK)
ifp->if_opackets++;
else {
+ int oldthresh;
ifp->if_oerrors++;
if ((txstat & RL_TXSTAT_TXABRT) ||
(txstat & RL_TXSTAT_OUTOFWIN))
CSR_WRITE_4(sc, RL_TXCFG, RL_TXCFG_CONFIG);
+ oldthresh = sc->rl_txthresh;
+ /* error recovery */
+ rl_reset(sc);
+ rl_init(sc);
+ /*
+ * If there was a transmit underrun,
+ * bump the TX threshold.
+ */
+ if (txstat & RL_TXSTAT_TX_UNDERRUN)
+ sc->rl_txthresh = oldthresh + 32;
+ return;
}
RL_INC(sc->rl_cdata.last_tx);
ifp->if_flags &= ~IFF_OACTIVE;
@@ -1290,9 +1302,8 @@ static void rl_intr(arg)
/* Re-enable interrupts. */
CSR_WRITE_2(sc, RL_IMR, RL_INTRS);
- if (ifp->if_snd.ifq_head != NULL) {
+ if (ifp->if_snd.ifq_head != NULL)
rl_start(ifp);
- }
return;
}
@@ -1327,8 +1338,7 @@ static int rl_encap(sc, m_head)
return(1);
}
}
- m_copydata(m_head, 0, m_head->m_pkthdr.len,
- mtod(m_new, caddr_t));
+ m_copydata(m_head, 0, m_head->m_pkthdr.len, mtod(m_new, caddr_t));
m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len;
m_freem(m_head);
m_head = m_new;
@@ -1336,7 +1346,7 @@ static int rl_encap(sc, m_head)
/* Pad frames to at least 60 bytes. */
if (m_head->m_pkthdr.len < RL_MIN_FRAMELEN) {
m_head->m_pkthdr.len +=
- (RL_MIN_FRAMELEN - m_head->m_pkthdr.len);
+ (RL_MIN_FRAMELEN - m_head->m_pkthdr.len);
m_head->m_len = m_head->m_pkthdr.len;
}
@@ -1377,7 +1387,8 @@ static void rl_start(ifp)
CSR_WRITE_4(sc, RL_CUR_TXADDR(sc),
vtophys(mtod(RL_CUR_TXMBUF(sc), caddr_t)));
CSR_WRITE_4(sc, RL_CUR_TXSTAT(sc),
- RL_TX_EARLYTHRESH | RL_CUR_TXMBUF(sc)->m_pkthdr.len);
+ RL_TXTHRESH(sc->rl_txthresh) |
+ RL_CUR_TXMBUF(sc)->m_pkthdr.len);
RL_INC(sc->rl_cdata.cur_tx);
}
@@ -1472,6 +1483,9 @@ static void rl_init(xsc)
*/
CSR_WRITE_2(sc, RL_IMR, RL_INTRS);
+ /* Set initial TX threshold */
+ sc->rl_txthresh = RL_TX_THRESH_INIT;
+
/* Start RX/TX process. */
CSR_WRITE_4(sc, RL_MISSEDPKT, 0);
diff --git a/sys/pci/if_rlreg.h b/sys/pci/if_rlreg.h
index 8654f7e..0bb9ffc 100644
--- a/sys/pci/if_rlreg.h
+++ b/sys/pci/if_rlreg.h
@@ -299,7 +299,8 @@
#define RL_RXBUFLEN (1 << ((RL_RX_BUF_SZ >> 11) + 13))
#define RL_TX_LIST_CNT 4
#define RL_MIN_FRAMELEN 60
-#define RL_TX_EARLYTHRESH (256 << 11)
+#define RL_TXTHRESH(x) ((x) << 11)
+#define RL_TX_THRESH_INIT 96
#define RL_RX_FIFOTHRESH RL_RXFIFO_256BYTES
#define RL_RX_MAXDMA RL_RXDMA_UNLIMITED
#define RL_TX_MAXDMA RL_TXDMA_2048BYTES
@@ -364,6 +365,7 @@ struct rl_softc {
u_int8_t rl_unit; /* interface number */
u_int8_t rl_type;
u_int8_t rl_stats_no_timeout;
+ int rl_txthresh;
struct rl_chain_data rl_cdata;
struct callout_handle rl_stat_ch;
};
OpenPOWER on IntegriCloud