diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2006-11-18 15:54:30 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2006-11-18 15:54:30 +0000 |
commit | 29a7ff2110212b6a8531f117a729b0f7eae6e0f0 (patch) | |
tree | 4a25a2bc8d88ba1a9a7ba536d8cb1450431fd32a | |
parent | 350e2166502997a1a41c85dd395eb590bc3da757 (diff) |
- set descriptor DMA addresses before enabling TX and RX
- set RL_EARLY_TX_THRESH before starting TX and RX
- clear a TX timeout only if all queued packets are handled
- declare struct rl_txq separately
- minor style tweaks in re_txeof()
From tsutsui@NetBSD
Tested by brad@, maja@ and kettenis@
Tested on amd64/armish/i386/sparc64
-rw-r--r-- | sys/dev/ic/re.c | 63 | ||||
-rw-r--r-- | sys/dev/ic/rtl81x9reg.h | 19 |
2 files changed, 40 insertions, 42 deletions
diff --git a/sys/dev/ic/re.c b/sys/dev/ic/re.c index ff37fd84bd2..e28edcbc429 100644 --- a/sys/dev/ic/re.c +++ b/sys/dev/ic/re.c @@ -1,4 +1,4 @@ -/* $OpenBSD: re.c,v 1.52 2006/11/01 23:25:18 brad Exp $ */ +/* $OpenBSD: re.c,v 1.53 2006/11/18 15:54:29 brad Exp $ */ /* $FreeBSD: if_re.c,v 1.31 2004/09/04 07:54:05 ru Exp $ */ /* * Copyright (c) 1997, 1998-2003 @@ -1339,15 +1339,14 @@ void re_txeof(struct rl_softc *sc) { struct ifnet *ifp; - int idx; + struct rl_txq *txq; + uint32_t txstat; + int idx, descidx; ifp = &sc->sc_arpcom.ac_if; - idx = sc->rl_ldata.rl_txq_considx; - for (;;) { - struct rl_txq *txq = &sc->rl_ldata.rl_txq[idx]; - int descidx; - u_int32_t txstat; + for (idx = sc->rl_ldata.rl_txq_considx;; idx = RL_NEXT_TXQ(sc, idx)) { + txq = &sc->rl_ldata.rl_txq[idx]; if (txq->txq_mbuf == NULL) { KASSERT(idx == sc->rl_ldata.rl_txq_prodidx); @@ -1378,16 +1377,11 @@ re_txeof(struct rl_softc *sc) ifp->if_oerrors++; else ifp->if_opackets++; - - idx = RL_NEXT_TXQ(sc, idx); } - /* No changes made to the TX ring, so no flush needed */ - if (sc->rl_ldata.rl_tx_free) { sc->rl_ldata.rl_txq_considx = idx; ifp->if_flags &= ~IFF_OACTIVE; - ifp->if_timer = 0; } /* @@ -1406,8 +1400,10 @@ re_txeof(struct rl_softc *sc) * interrupt that will cause us to re-enter this routine. * This is done in case the transmitter has gone idle. */ - if (sc->rl_ldata.rl_tx_free != RL_TX_DESC_CNT(sc)) + if (sc->rl_ldata.rl_tx_free < RL_TX_DESC_CNT(sc)) CSR_WRITE_4(sc, RL_TIMERCNT, 1); + else + ifp->if_timer = 0; } void @@ -1465,15 +1461,13 @@ re_intr(void *arg) if ((status & RL_INTRS_CPLUS) == 0) break; - if ((status & RL_ISR_RX_OK) || - (status & RL_ISR_RX_ERR)) { + if (status & (RL_ISR_RX_OK | RL_ISR_RX_ERR)) { re_rxeof(sc); claimed = 1; } - if ((status & RL_ISR_TIMEOUT_EXPIRED) || - (status & RL_ISR_TX_ERR) || - (status & RL_ISR_TX_DESC_UNAVAIL)) { + if (status & (RL_ISR_TIMEOUT_EXPIRED | RL_ISR_TX_ERR | + RL_ISR_TX_DESC_UNAVAIL)) { re_txeof(sc); claimed = 1; } @@ -1491,7 +1485,7 @@ re_intr(void *arg) } } - if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd)) + if (claimed && !IFQ_IS_EMPTY(&ifp->if_snd)) re_start(ifp); return (claimed); @@ -1779,6 +1773,19 @@ re_init(struct ifnet *ifp) re_tx_list_init(sc); /* + * Load the addresses of the RX and TX lists into the chip. + */ + CSR_WRITE_4(sc, RL_RXLIST_ADDR_HI, + RL_ADDR_HI(sc->rl_ldata.rl_rx_list_map->dm_segs[0].ds_addr)); + CSR_WRITE_4(sc, RL_RXLIST_ADDR_LO, + RL_ADDR_LO(sc->rl_ldata.rl_rx_list_map->dm_segs[0].ds_addr)); + + CSR_WRITE_4(sc, RL_TXLIST_ADDR_HI, + RL_ADDR_HI(sc->rl_ldata.rl_tx_list_map->dm_segs[0].ds_addr)); + CSR_WRITE_4(sc, RL_TXLIST_ADDR_LO, + RL_ADDR_LO(sc->rl_ldata.rl_tx_list_map->dm_segs[0].ds_addr)); + + /* * Enable transmit and receive. */ CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_TX_ENB|RL_CMD_RX_ENB); @@ -1795,6 +1802,9 @@ re_init(struct ifnet *ifp) RL_TXCFG_CONFIG|RL_LOOPTEST_ON_CPLUS); } else CSR_WRITE_4(sc, RL_TXCFG, RL_TXCFG_CONFIG); + + CSR_WRITE_1(sc, RL_EARLY_TX_THRESH, 16); + CSR_WRITE_4(sc, RL_RXCFG, RL_RXCFG_CONFIG); /* Set the individual bit to receive frames for this host only. */ @@ -1834,21 +1844,6 @@ re_init(struct ifnet *ifp) /* Enable receiver and transmitter. */ CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_TX_ENB|RL_CMD_RX_ENB); #endif - /* - * Load the addresses of the RX and TX lists into the chip. - */ - - CSR_WRITE_4(sc, RL_RXLIST_ADDR_HI, - RL_ADDR_HI(sc->rl_ldata.rl_rx_list_map->dm_segs[0].ds_addr)); - CSR_WRITE_4(sc, RL_RXLIST_ADDR_LO, - RL_ADDR_LO(sc->rl_ldata.rl_rx_list_map->dm_segs[0].ds_addr)); - - CSR_WRITE_4(sc, RL_TXLIST_ADDR_HI, - RL_ADDR_HI(sc->rl_ldata.rl_tx_list_map->dm_segs[0].ds_addr)); - CSR_WRITE_4(sc, RL_TXLIST_ADDR_LO, - RL_ADDR_LO(sc->rl_ldata.rl_tx_list_map->dm_segs[0].ds_addr)); - - CSR_WRITE_1(sc, RL_EARLY_TX_THRESH, 16); /* * Initialize the timer interrupt register so that diff --git a/sys/dev/ic/rtl81x9reg.h b/sys/dev/ic/rtl81x9reg.h index 99ebe3a6962..6653ec463e6 100644 --- a/sys/dev/ic/rtl81x9reg.h +++ b/sys/dev/ic/rtl81x9reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rtl81x9reg.h,v 1.31 2006/11/01 23:25:18 brad Exp $ */ +/* $OpenBSD: rtl81x9reg.h,v 1.32 2006/11/18 15:54:29 brad Exp $ */ /* * Copyright (c) 1997, 1998 @@ -677,27 +677,30 @@ struct rl_rxsoft { bus_dmamap_t rxs_dmamap; }; +struct rl_txq { + struct mbuf *txq_mbuf; + bus_dmamap_t txq_dmamap; + int txq_descidx; +}; + struct rl_list_data { - struct rl_txq { - struct mbuf *txq_mbuf; - bus_dmamap_t txq_dmamap; - int txq_descidx; - } rl_txq[RL_TX_QLEN]; + struct rl_txq rl_txq[RL_TX_QLEN]; int rl_txq_considx; int rl_txq_prodidx; + bus_dmamap_t rl_tx_list_map; struct rl_desc *rl_tx_list; - bus_dma_segment_t rl_tx_listseg; int rl_tx_free; /* # of free descriptors */ int rl_tx_nextfree; /* next descriptor to use */ int rl_tx_desc_cnt; /* # of descriptors */ + bus_dma_segment_t rl_tx_listseg; int rl_tx_listnseg; struct rl_rxsoft rl_rxsoft[RL_RX_DESC_CNT]; bus_dmamap_t rl_rx_list_map; struct rl_desc *rl_rx_list; - bus_dma_segment_t rl_rx_listseg; int rl_rx_prodidx; + bus_dma_segment_t rl_rx_listseg; int rl_rx_listnseg; }; |