Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci * Account for the descriptor consumed by the Tx ...



details:   https://anonhg.NetBSD.org/src/rev/26729fb9ca54
branches:  trunk
changeset: 526689:26729fb9ca54
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Wed May 08 17:53:28 2002 +0000

description:
* Account for the descriptor consumed by the Tx checksum offload
  context setup.
* Implement Matt Thomas's sliding Tx interrupt window algorithm,
  forcing an interrupt when the Tx desc list is 2/3 consumed.
* Use the Report Packet Sent interrupt, rather than Report Status,
  since we use the Tx descriptor to count Tx errors.

diffstat:

 sys/dev/pci/if_wm.c |  69 +++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 52 insertions(+), 17 deletions(-)

diffs (204 lines):

diff -r 8c42012cfd14 -r 26729fb9ca54 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Wed May 08 16:51:39 2002 +0000
+++ b/sys/dev/pci/if_wm.c       Wed May 08 17:53:28 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.3 2002/05/02 16:34:47 thorpej Exp $        */
+/*     $NetBSD: if_wm.c,v 1.4 2002/05/08 17:53:28 thorpej Exp $        */
 
 /*
  * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
@@ -175,6 +175,7 @@
        bus_dmamap_t txs_dmamap;        /* our DMA map */
        int txs_firstdesc;              /* first descriptor in packet */
        int txs_lastdesc;               /* last descriptor in packet */
+       int txs_ndesc;                  /* # of descriptors used */
 };
 
 /*
@@ -227,7 +228,8 @@
        /* Event counters. */
        struct evcnt sc_ev_txsstall;    /* Tx stalled due to no txs */
        struct evcnt sc_ev_txdstall;    /* Tx stalled due to no txd */
-       struct evcnt sc_ev_txintr;      /* Tx interrupts */
+       struct evcnt sc_ev_txdw;        /* Tx descriptor interrupts */
+       struct evcnt sc_ev_txqe;        /* Tx queue empty interrupts */
        struct evcnt sc_ev_rxintr;      /* Rx interrupts */
        struct evcnt sc_ev_linkintr;    /* Link interrupts */
 
@@ -246,6 +248,7 @@
 
        int     sc_txfree;              /* number of free Tx descriptors */
        int     sc_txnext;              /* next ready Tx descriptor */
+       int     sc_txwin;               /* Tx descriptors since last Tx int */
 
        int     sc_txsfree;             /* number of free Tx jobs */
        int     sc_txsnext;             /* next free Tx job */
@@ -842,8 +845,10 @@
            NULL, sc->sc_dev.dv_xname, "txsstall");
        evcnt_attach_dynamic(&sc->sc_ev_txdstall, EVCNT_TYPE_MISC,
            NULL, sc->sc_dev.dv_xname, "txdstall");
-       evcnt_attach_dynamic(&sc->sc_ev_txintr, EVCNT_TYPE_INTR,
-           NULL, sc->sc_dev.dv_xname, "txintr");
+       evcnt_attach_dynamic(&sc->sc_ev_txdw, EVCNT_TYPE_INTR,
+           NULL, sc->sc_dev.dv_xname, "txdw");
+       evcnt_attach_dynamic(&sc->sc_ev_txqe, EVCNT_TYPE_INTR,
+           NULL, sc->sc_dev.dv_xname, "txqe");
        evcnt_attach_dynamic(&sc->sc_ev_rxintr, EVCNT_TYPE_INTR,
            NULL, sc->sc_dev.dv_xname, "rxintr");
        evcnt_attach_dynamic(&sc->sc_ev_linkintr, EVCNT_TYPE_INTR,
@@ -926,9 +931,10 @@
  *     specified packet.
  */
 static int
-wm_tx_cksum(struct wm_softc *sc, struct mbuf *m0, uint32_t *cmdp,
+wm_tx_cksum(struct wm_softc *sc, struct wm_txsoft *txs, uint32_t *cmdp,
     uint32_t *fieldsp)
 {
+       struct mbuf *m0 = txs->txs_mbuf;
        struct livengood_tcpip_ctxdesc *t;
        uint32_t fields = 0, tcmd = 0, ipcs, tucs;
        struct ip *ip;
@@ -984,6 +990,7 @@
        WM_CDTXSYNC(sc, sc->sc_txnext, 1, BUS_DMASYNC_PREWRITE);
 
        sc->sc_txnext = WM_NEXTTX(sc->sc_txnext);
+       txs->txs_ndesc++;
 
        *cmdp = WTX_CMD_DEXT | WTC_DTYP_D;
        *fieldsp = fields;
@@ -1112,15 +1119,29 @@
                WM_EVCNT_INCR(&sc->sc_ev_txseg[dmamap->dm_nsegs - 1]);
 
                /*
+                * Store a pointer to the packet so that we can free it
+                * later.
+                *
+                * Initially, we consider the number of descriptors the
+                * packet uses the number of DMA segments.  This may be
+                * incremented by 1 if we do checksum offload (a descriptor
+                * is used to set the checksum context).
+                */
+               txs->txs_mbuf = m0;
+               txs->txs_ndesc = dmamap->dm_nsegs;
+
+               /*
                 * Set up checksum offload parameters for
                 * this packet.
                 */
                if (m0->m_pkthdr.csum_flags &
                    (M_CSUM_IPv4|M_CSUM_TCPv4|M_CSUM_UDPv4)) {
-                       if (wm_tx_cksum(sc, m0, &cksumcmd, &cksumfields) != 0) {
+                       if (wm_tx_cksum(sc, txs, &cksumcmd,
+                                       &cksumfields) != 0) {
                                /* Error message already displayed. */
                                m_freem(m0);
                                bus_dmamap_unload(sc->sc_dmat, dmamap);
+                               txs->txs_mbuf = NULL;
                                continue;
                        }
                } else {
@@ -1146,6 +1167,8 @@
                            cksumfields;
                        lasttx = nexttx;
 
+                       sc->sc_txwin++;
+
                        DPRINTF(WM_DEBUG_TX,
                            ("%s: TX: desc %d: low 0x%08x, len 0x%04x\n",
                            sc->sc_dev.dv_xname, nexttx,
@@ -1159,10 +1182,12 @@
                 * delay the interrupt.
                 */
                sc->sc_txdescs[lasttx].wtx_cmdlen |=
-                   htole32(WTX_CMD_EOP | WTX_CMD_IFCS | WTX_CMD_RS);
-               if (sc->sc_txsnext & WM_TXINTR_MASK)
+                   htole32(WTX_CMD_EOP | WTX_CMD_IFCS | WTX_CMD_RPS);
+               if (sc->sc_txwin < (WM_NTXDESC * 2 / 3))
                        sc->sc_txdescs[lasttx].wtx_cmdlen |=
                            htole32(WTX_CMD_IDE);
+               else
+                       sc->sc_txwin = 0;
 
 #if 0 /* XXXJRT */
                /*
@@ -1195,11 +1220,13 @@
                    ("%s: TX: TDT -> %d\n", sc->sc_dev.dv_xname, nexttx));
 
                /*
-                * Store a pointer to the packet so we can free it later,
-                * and remember that txdirty will be once the packet is
+                * Remember that txdirty will be once the packet is
                 * done.
+                *
+                * Note: If we're doing checksum offload, we are actually
+                * using one descriptor before firstdesc, but it doesn't
+                * really matter.
                 */
-               txs->txs_mbuf = m0;
                txs->txs_firstdesc = sc->sc_txnext;
                txs->txs_lastdesc = lasttx;
 
@@ -1208,7 +1235,7 @@
                    sc->sc_dev.dv_xname, sc->sc_txsnext));
 
                /* Advance the tx pointer. */
-               sc->sc_txfree -= dmamap->dm_nsegs;
+               sc->sc_txfree -= txs->txs_ndesc;
                sc->sc_txnext = nexttx;
 
                sc->sc_txsfree--;
@@ -1331,11 +1358,16 @@
                        wm_rxintr(sc);
                }
 
-               if (icr & ICR_TXDW) {
+               if (icr & (ICR_TXDW|ICR_TXQE)) {
                        DPRINTF(WM_DEBUG_TX,
-                           ("%s: TX: got TXDW interrupt\n",
+                           ("%s: TX: got TDXW|TXQE interrupt\n",
                            sc->sc_dev.dv_xname));
-                       WM_EVCNT_INCR(&sc->sc_ev_txintr);
+#ifdef WM_EVENT_COUNTERS
+                       if (icr & ICR_TXDW)
+                               WM_EVCNT_INCR(&sc->sc_ev_txdw);
+                       else if (icr & ICR_TXQE)
+                               WM_EVCNT_INCR(&sc->sc_ev_txqe);
+#endif
                        wm_txintr(sc);
                }
 
@@ -1424,7 +1456,7 @@
                } else
                        ifp->if_opackets++;
 
-               sc->sc_txfree += txs->txs_dmamap->dm_nsegs;
+               sc->sc_txfree += txs->txs_ndesc;
                bus_dmamap_sync(sc->sc_dmat, txs->txs_dmamap,
                    0, txs->txs_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
                bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
@@ -1443,6 +1475,8 @@
         */
        if (sc->sc_txsfree == WM_TXQUEUELEN)
                ifp->if_timer = 0;
+       if (sc->sc_txfree == WM_NTXDESC)
+               sc->sc_txwin = 0;
 }
 
 /*
@@ -1789,6 +1823,7 @@
            BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        sc->sc_txfree = WM_NTXDESC;
        sc->sc_txnext = 0;
+       sc->sc_txwin = 0;
 
        if (sc->sc_type < WM_T_LIVENGOOD) {
                CSR_WRITE(sc, WMREG_OLD_TBDAH, 0);
@@ -1926,7 +1961,7 @@
         * Set up the interrupt registers.
         */
        CSR_WRITE(sc, WMREG_IMC, 0xffffffffU);
-       sc->sc_icr = ICR_TXDW | ICR_LSC | ICR_RXSEQ | ICR_RXDMT0 |
+       sc->sc_icr = ICR_TXDW | ICR_TXQE | ICR_LSC | ICR_RXSEQ | ICR_RXDMT0 |
            ICR_RXO | ICR_RXT0;
        if ((sc->sc_flags & WM_F_HAS_MII) == 0)
                sc->sc_icr |= ICR_RXCFG;



Home | Main Index | Thread Index | Old Index