Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/ic Rework the transmit logic. Use a "free" and "dir...



details:   https://anonhg.NetBSD.org/src/rev/a5a61665e241
branches:  trunk
changeset: 503162:a5a61665e241
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Fri Feb 02 04:34:19 2001 +0000

description:
Rework the transmit logic.  Use a "free" and "dirty" list of
transmit jobs.  The previous logic occasionally, under heavy
load, would attempt to sync and unload DMA maps that weren't
currently in use, and also occasionally leaked mbufs under
heavy load.

Yay, NFS now works pretty well on my Dreamcast.

diffstat:

 sys/dev/ic/rtl81x9.c    |  128 ++++++++++++++++++++++++++---------------------
 sys/dev/ic/rtl81x9var.h |   29 ++++------
 2 files changed, 82 insertions(+), 75 deletions(-)

diffs (truncated from 344 to 300 lines):

diff -r 64ab968b20ce -r a5a61665e241 sys/dev/ic/rtl81x9.c
--- a/sys/dev/ic/rtl81x9.c      Fri Feb 02 03:56:20 2001 +0000
+++ b/sys/dev/ic/rtl81x9.c      Fri Feb 02 04:34:19 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: rtl81x9.c,v 1.30 2001/02/02 03:51:51 thorpej Exp $     */
+/*     $NetBSD: rtl81x9.c,v 1.31 2001/02/02 04:34:19 thorpej Exp $     */
 
 /*
  * Copyright (c) 1997, 1998
@@ -631,6 +631,7 @@
        struct rtk_softc *sc;
 {
        struct ifnet *ifp;
+       struct rtk_tx_desc *txd;
        u_int16_t val;
        u_int8_t eaddr[ETHER_ADDR_LEN];
        int error;
@@ -691,14 +692,21 @@
                goto fail_3;
        }
 
-       for (i = 0; i < RTK_TX_LIST_CNT; i++)
+       for (i = 0; i < RTK_TX_LIST_CNT; i++) {
+               txd = &sc->rtk_tx_descs[i];
                if ((error = bus_dmamap_create(sc->sc_dmat,
                    MCLBYTES, 1, MCLBYTES, 0, BUS_DMA_NOWAIT,
-                   &sc->snd_dmamap[i])) != 0) {
+                   &txd->txd_dmamap)) != 0) {
                        printf("%s: can't create snd buffer DMA map,"
                            " error = %d\n", sc->sc_dev.dv_xname, error);
                        goto fail_4;
                }
+               txd->txd_txaddr = RTK_TXADDR0 + (i * 4);
+               txd->txd_txstat = RTK_TXSTAT0 + (i * 4);
+       }
+       SIMPLEQ_INIT(&sc->rtk_tx_free);
+       SIMPLEQ_INIT(&sc->rtk_tx_dirty);
+
        /*
         * From this point forward, the attachment cannot fail. A failure
         * before this releases all resources thar may have been
@@ -766,9 +774,11 @@
 
        return;
  fail_4:
-       for (i = 0; i < RTK_TX_LIST_CNT; i++)
-               if (sc->snd_dmamap[i] != NULL)
-                       bus_dmamap_destroy(sc->sc_dmat, sc->snd_dmamap[i]);
+       for (i = 0; i < RTK_TX_LIST_CNT; i++) {
+               txd = &sc->rtk_tx_descs[i];
+               if (txd->txd_dmamap != NULL)
+                       bus_dmamap_destroy(sc->sc_dmat, txd->txd_dmamap);
+       }
  fail_3:
        bus_dmamap_destroy(sc->sc_dmat, sc->recv_dmamap);
  fail_2:
@@ -786,19 +796,20 @@
 STATIC int rtk_list_tx_init(sc)
        struct rtk_softc        *sc;
 {
-       struct rtk_chain_data   *cd;
-       int                     i;
+       struct rtk_tx_desc *txd;
+       int i;
 
-       cd = &sc->rtk_cdata;
+       while ((txd = SIMPLEQ_FIRST(&sc->rtk_tx_dirty)) != NULL)
+               SIMPLEQ_REMOVE_HEAD(&sc->rtk_tx_dirty, txd, txd_q);
+       while ((txd = SIMPLEQ_FIRST(&sc->rtk_tx_free)) != NULL)
+               SIMPLEQ_REMOVE_HEAD(&sc->rtk_tx_free, txd, txd_q);
+
        for (i = 0; i < RTK_TX_LIST_CNT; i++) {
-               cd->rtk_tx_chain[i] = NULL;
-               CSR_WRITE_4(sc,
-                   RTK_TXADDR0 + (i * sizeof(u_int32_t)), 0x0000000);
+               txd = &sc->rtk_tx_descs[i];
+               CSR_WRITE_4(sc, txd->txd_txaddr, 0);
+               SIMPLEQ_INSERT_TAIL(&sc->rtk_tx_free, txd, txd_q);
        }
 
-       sc->rtk_cdata.cur_tx = 0;
-       sc->rtk_cdata.last_tx = 0;
-
        return (0);
 }
 
@@ -838,6 +849,7 @@
        struct rtk_softc *sc;
 {
        struct ifnet *ifp = &sc->ethercom.ec_if;
+       struct rtk_tx_desc *txd;
        int i;
 
        /*
@@ -858,9 +870,11 @@
        ether_ifdetach(ifp);
        if_detach(ifp);
 
-       for (i = 0; i < RTK_TX_LIST_CNT; i++)
-               if (sc->snd_dmamap[i] != NULL)
-                       bus_dmamap_destroy(sc->sc_dmat, sc->snd_dmamap[i]);
+       for (i = 0; i < RTK_TX_LIST_CNT; i++) {
+               txd = &sc->rtk_tx_descs[i];
+               if (txd->txd_dmamap != NULL)
+                       bus_dmamap_destroy(sc->sc_dmat, txd->txd_dmamap);
+       }
        bus_dmamap_destroy(sc->sc_dmat, sc->recv_dmamap);
        bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->rtk_rx_buf,
            RTK_RXBUFLEN + 16);
@@ -1153,8 +1167,9 @@
 STATIC void rtk_txeof(sc)
        struct rtk_softc        *sc;
 {
-       struct ifnet            *ifp;
-       u_int32_t               txstat;
+       struct ifnet *ifp;
+       struct rtk_tx_desc *txd;
+       u_int32_t txstat;
 
        ifp = &sc->ethercom.ec_if;
 
@@ -1165,20 +1180,19 @@
         * Go through our tx list and free mbufs for those
         * frames that have been uploaded.
         */
-       do {
-               txstat = CSR_READ_4(sc, RTK_LAST_TXSTAT(sc));
+       while ((txd = SIMPLEQ_FIRST(&sc->rtk_tx_dirty)) != NULL) {
+               txstat = CSR_READ_4(sc, txd->txd_txstat);
                if ((txstat & (RTK_TXSTAT_TX_OK|
                    RTK_TXSTAT_TX_UNDERRUN|RTK_TXSTAT_TXABRT)) == 0)
                        break;
 
-               bus_dmamap_sync(sc->sc_dmat,
-                   sc->snd_dmamap[sc->rtk_cdata.last_tx], 0,
-                   sc->snd_dmamap[sc->rtk_cdata.last_tx]->dm_mapsize,
-                   BUS_DMASYNC_POSTWRITE);
-               bus_dmamap_unload(sc->sc_dmat,
-                   sc->snd_dmamap[sc->rtk_cdata.last_tx]);
-               m_freem(RTK_LAST_TXMBUF(sc));
-               RTK_LAST_TXMBUF(sc) = NULL;
+               SIMPLEQ_REMOVE_HEAD(&sc->rtk_tx_dirty, txd, txd_q);
+
+               bus_dmamap_sync(sc->sc_dmat, txd->txd_dmamap, 0,
+                   txd->txd_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
+               bus_dmamap_unload(sc->sc_dmat, txd->txd_dmamap);
+               m_freem(txd->txd_mbuf);
+               txd->txd_mbuf = NULL;
 
                ifp->if_collisions += (txstat & RTK_TXSTAT_COLLCNT) >> 24;
 
@@ -1189,9 +1203,9 @@
                        if (txstat & (RTK_TXSTAT_TXABRT|RTK_TXSTAT_OUTOFWIN))
                                CSR_WRITE_4(sc, RTK_TXCFG, RTK_TXCFG_CONFIG);
                }
-               RTK_INC(sc->rtk_cdata.last_tx);
+               SIMPLEQ_INSERT_TAIL(&sc->rtk_tx_free, txd, txd_q);
                ifp->if_flags &= ~IFF_OACTIVE;
-       } while (sc->rtk_cdata.last_tx != sc->rtk_cdata.cur_tx);
+       }
 }
 
 int rtk_intr(arg)
@@ -1250,27 +1264,26 @@
 STATIC void rtk_start(ifp)
        struct ifnet            *ifp;
 {
-       struct rtk_softc        *sc;
-       struct mbuf             *m_head = NULL, *m_new;
-       int                     error, idx, len;
+       struct rtk_softc *sc;
+       struct rtk_tx_desc *txd;
+       struct mbuf *m_head = NULL, *m_new;
+       int error, len;
 
        sc = ifp->if_softc;
 
-       while(RTK_CUR_TXMBUF(sc) == NULL) {
+       while ((txd = SIMPLEQ_FIRST(&sc->rtk_tx_free)) != NULL) {
                IFQ_POLL(&ifp->if_snd, m_head);
                if (m_head == NULL)
                        break;
                m_new = NULL;
 
-               idx = sc->rtk_cdata.cur_tx;
-
                /*
                 * Load the DMA map.  If this fails, the packet didn't
                 * fit in one DMA segment, and we need to copy.  Note,
                 * the packet must also be aligned.
                 */
                if ((mtod(m_head, bus_addr_t) & 3) != 0 ||
-                   bus_dmamap_load_mbuf(sc->sc_dmat, sc->snd_dmamap[idx],
+                   bus_dmamap_load_mbuf(sc->sc_dmat, txd->txd_dmamap,
                        m_head, BUS_DMA_NOWAIT) != 0) {
                        MGETHDR(m_new, M_DONTWAIT, MT_DATA);
                        if (m_new == NULL) {
@@ -1292,7 +1305,7 @@
                        m_new->m_pkthdr.len = m_new->m_len =
                            m_head->m_pkthdr.len;
                        error = bus_dmamap_load_mbuf(sc->sc_dmat,
-                           sc->snd_dmamap[idx], m_new, BUS_DMA_NOWAIT);
+                           txd->txd_dmamap, m_new, BUS_DMA_NOWAIT);
                        if (error) {
                                printf("%s: unable to load Tx buffer, "
                                    "error = %d\n", sc->sc_dev.dv_xname, error);
@@ -1304,8 +1317,10 @@
                        m_freem(m_head);
                        m_head = m_new;
                }
+               txd->txd_mbuf = m_head;
 
-               RTK_CUR_TXMBUF(sc) = m_head;
+               SIMPLEQ_REMOVE_HEAD(&sc->rtk_tx_free, txd, txd_q);
+               SIMPLEQ_INSERT_TAIL(&sc->rtk_tx_dirty, txd, txd_q);
 
 #if NBPFILTER > 0
                /*
@@ -1313,24 +1328,22 @@
                 * to him.
                 */
                if (ifp->if_bpf)
-                       bpf_mtap(ifp->if_bpf, RTK_CUR_TXMBUF(sc));
+                       bpf_mtap(ifp->if_bpf, m_head);
 #endif
                /*
                 * Transmit the frame.
                 */
                bus_dmamap_sync(sc->sc_dmat,
-                   sc->snd_dmamap[idx], 0, sc->snd_dmamap[idx]->dm_mapsize,
+                   txd->txd_dmamap, 0, txd->txd_dmamap->dm_mapsize,
                    BUS_DMASYNC_PREWRITE);
 
-               len = sc->snd_dmamap[idx]->dm_segs[0].ds_len;
+               len = txd->txd_dmamap->dm_segs[0].ds_len;
                if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN))
                        len = (ETHER_MIN_LEN - ETHER_CRC_LEN);
 
-               CSR_WRITE_4(sc, RTK_CUR_TXADDR(sc),
-                   sc->snd_dmamap[idx]->dm_segs[0].ds_addr);
-               CSR_WRITE_4(sc, RTK_CUR_TXSTAT(sc), RTK_TX_EARLYTHRESH | len);
-
-               RTK_INC(sc->rtk_cdata.cur_tx);
+               CSR_WRITE_4(sc, txd->txd_txaddr,
+                   txd->txd_dmamap->dm_segs[0].ds_addr);
+               CSR_WRITE_4(sc, txd->txd_txstat, RTK_TX_EARLYTHRESH | len);
        }
 
        /*
@@ -1338,7 +1351,7 @@
         * full. Mark the NIC as busy until it drains some of the
         * packets from the queue.
         */
-       if (RTK_CUR_TXMBUF(sc) != NULL)
+       if (SIMPLEQ_FIRST(&sc->rtk_tx_free) == NULL)
                ifp->if_flags |= IFF_OACTIVE;
 
        /*
@@ -1536,7 +1549,7 @@
        int disable;
 {
        struct rtk_softc *sc = ifp->if_softc;
-       int i;
+       struct rtk_tx_desc *txd;
 
        callout_stop(&sc->rtk_tick_ch);
 
@@ -1548,13 +1561,12 @@
        /*
         * Free the TX list buffers.
         */
-       for (i = 0; i < RTK_TX_LIST_CNT; i++) {
-               if (sc->rtk_cdata.rtk_tx_chain[i] != NULL) {
-                       bus_dmamap_unload(sc->sc_dmat, sc->snd_dmamap[i]);
-                       m_freem(sc->rtk_cdata.rtk_tx_chain[i]);
-                       sc->rtk_cdata.rtk_tx_chain[i] = NULL;
-                       CSR_WRITE_4(sc, RTK_TXADDR0 + i, 0x0000000);
-               }
+       while ((txd = SIMPLEQ_FIRST(&sc->rtk_tx_dirty)) != NULL) {
+               SIMPLEQ_REMOVE_HEAD(&sc->rtk_tx_dirty, txd, txd_q);
+               bus_dmamap_unload(sc->sc_dmat, txd->txd_dmamap);
+               m_freem(txd->txd_mbuf);
+               txd->txd_mbuf = NULL;
+               CSR_WRITE_4(sc, txd->txd_txaddr, 0);
        }
 
        if (disable)
diff -r 64ab968b20ce -r a5a61665e241 sys/dev/ic/rtl81x9var.h
--- a/sys/dev/ic/rtl81x9var.h   Fri Feb 02 03:56:20 2001 +0000
+++ b/sys/dev/ic/rtl81x9var.h   Fri Feb 02 04:34:19 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: rtl81x9var.h,v 1.8 2001/02/02 03:51:51 thorpej Exp $   */
+/*     $NetBSD: rtl81x9var.h,v 1.9 2001/02/02 04:34:19 thorpej Exp $   */
 
 /*
  * Copyright (c) 1997, 1998
@@ -37,20 +37,6 @@
 #define RTK_ETHER_ALIGN        2
 #define RTK_RXSTAT_LEN 4
 



Home | Main Index | Thread Index | Old Index