Refreshed patch against HEAD appears below, 

best, 
Richard. 

PS. Apologies for the quoted-printable encoding...looking now for an email
client capable of 7-bit... 

On 10/11/2015, at 5:18 PM, Richard Procter wrote:

> This reduces tsec(4) TX interrupts by over a factor of four per interface,
> boosting throughput by a couple of percent for
> 
>       $ dd if=/dev/zero bs=4096 | nc ${host} ${port}
> 
> It does this by reducing TX interrupts notifications to one per frame, from
> one per mbuf fragment, and by enabling TX interrupt coalescing.
> 
> I've chosen conservative coalescing parameters. The card now interrupts every
> four tx frames, leaving the tx ring fuller on average. But ample room remains
> on the card's tx ring of 256 descriptors, which can hold 16 frames in the 
> worst case of 16 mbuf fragments per frame. Testing showed descriptor use 
> peaking at 13 descriptors under load.
> 
> The hold-off timer, ensuring stale frames are not left on the tx ring 
> indefinitely, is not crucial for tx: as the frame has already been 
> transmitted, 
> latency isn't a concern. It need only last longer than the time to transmit 
> the 
> coalesced frames, and I've set it much longer, roughly 2ms for 1000baseT, 
> to give the stack some slack when feeding the card.
> 
> While here, also makes tsec_encap() error handling a tad more robust.
> 
> Tested on RB600A.

Index: arch/socppc/dev/if_tsec.c
===================================================================
RCS file: /cvs/src/sys/arch/socppc/dev/if_tsec.c,v
retrieving revision 1.42
diff -u -p -U6 -r1.42 if_tsec.c
--- arch/socppc/dev/if_tsec.c   25 Nov 2015 03:09:58 -0000      1.42
+++ arch/socppc/dev/if_tsec.c   3 Dec 2015 20:54:39 -0000
@@ -117,12 +117,14 @@ extern void myetheraddr(u_char *);
#define  TSEC_DMACTRL_WOP       0x00000001
#define TSEC_TBIPA              0x030

#define TSEC_TCTRL              0x100
#define TSEC_TSTAT              0x104
#define  TSEC_TSTAT_THLT        0x80000000
+#define TSEC_TXIC              0x110
+#define  TSEC_TXIC_ICEN                0x80000000
#define TSEC_TBPTR              0x184
#define TSEC_TBASE              0x204

#define TSEC_RCTRL              0x300
#define  TSEC_RCTRL_PROM        0x00000008
#define TSEC_RSTAT              0x304
@@ -533,13 +535,13 @@ tsec_start(struct ifnet *ifp)
                error = tsec_encap(sc, m, &idx);
                if (error == ENOBUFS) {
                        ifq_deq_rollback(&ifp->if_snd, m);
                        ifq_set_oactive(&ifp->if_snd);
                        break;
                } 
-               if (error == EFBIG) {
+               if (error) {
                        ifq_deq_commit(&ifp->if_snd, m);
                        m_freem(m); /* give up: drop it */
                        ifp->if_oerrors++;
                        continue;
                }

@@ -1017,12 +1019,15 @@ tsec_up(struct tsec_softc *sc)

        attr = tsec_read(sc, TSEC_ATTR);
        attr |= TSEC_ATTR_RDSEN;
        attr |= TSEC_ATTR_RBDSEN;
        tsec_write(sc, TSEC_ATTR, attr);

+       /* TX interrupts every 4 TSEC_TX_I with ~2ms hold-off @ 1000baseT */
+       tsec_write(sc, TSEC_TXIC, (TSEC_TXIC_ICEN | (0x4 << 21) | 0x1000));
+
        tsec_write(sc, TSEC_TSTAT, TSEC_TSTAT_THLT);
        tsec_write(sc, TSEC_RSTAT, TSEC_RSTAT_QHLT);

        /* Configure media. */
        if (LIST_FIRST(&sc->sc_mii.mii_phys))
                mii_mediachg(&sc->sc_mii);
@@ -1156,18 +1161,20 @@ tsec_encap(struct tsec_softc *sc, struct
            BUS_DMASYNC_PREWRITE);

        txd = &sc->sc_txdesc[frag];
        for (i = 0; i < map->dm_nsegs; i++) {
                status = txd->td_status & TSEC_TX_W;
                status |= TSEC_TX_TO1;
+               status |= TSEC_TX_TC;
                if (i == (map->dm_nsegs - 1))
-                       status |= TSEC_TX_L;
+                       status |= TSEC_TX_L | TSEC_TX_I;
+
                txd->td_len = map->dm_segs[i].ds_len;
                txd->td_addr = map->dm_segs[i].ds_addr;
                __asm volatile("eieio" ::: "memory");
-               txd->td_status = status | TSEC_TX_R | TSEC_TX_I | TSEC_TX_TC;
+               txd->td_status = status | TSEC_TX_R;

                bus_dmamap_sync(sc->sc_dmat, TSEC_DMA_MAP(sc->sc_txring),
                    frag * sizeof(*txd), sizeof(*txd), BUS_DMASYNC_PREWRITE);

                cur = frag;
                if (status & TSEC_TX_W) {

Reply via email to