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.
This commit is contained in:
Bill Paul 1999-10-21 19:42:03 +00:00
parent 86a4b08dc7
commit 11ad85d1f5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=52426
2 changed files with 28 additions and 12 deletions

View File

@ -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);

View File

@ -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;
};