diff options
author | wpaul <wpaul@FreeBSD.org> | 1999-10-21 19:42:03 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 1999-10-21 19:42:03 +0000 |
commit | 6ac7cdd7154bae972f2dabc8a960faafc7607ed9 (patch) | |
tree | fb11a26f4ba217bd7b4f9ca728c68f086a925cfe | |
parent | e2a07af8e9edccde7317330a3790e61a69e2784f (diff) | |
download | FreeBSD-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.c | 36 | ||||
-rw-r--r-- | sys/pci/if_rlreg.h | 4 |
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; }; |