I noticed the new dwge(4) locks up after a while running tcpbench.
After scratching my head quite a lot I realised it wasn't restarting the
send queue after processing tx completions, it was just clearing OACTIVE,
Changing this to call ifq_restart() instead (as prescribed in ifq.h) things
work much better.  dwxe(4) also needs the same fix, but I haven't tested it.

ok?

Index: if_dwge.c
===================================================================
RCS file: /cvs/src/sys/dev/fdt/if_dwge.c,v
retrieving revision 1.1
diff -u -p -u -p -r1.1 if_dwge.c
--- if_dwge.c   29 Sep 2019 13:04:03 -0000      1.1
+++ if_dwge.c   6 Oct 2019 13:12:37 -0000
@@ -812,12 +812,13 @@ dwge_tx_proc(struct dwge_softc *sc)
        struct ifnet *ifp = &sc->sc_ac.ac_if;
        struct dwge_desc *txd;
        struct dwge_buf *txb;
-       int idx;
+       int idx, txfree;
 
        bus_dmamap_sync(sc->sc_dmat, DWGE_DMA_MAP(sc->sc_txring), 0,
            DWGE_DMA_LEN(sc->sc_txring),
            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 
+       txfree = 0;
        while (sc->sc_tx_cnt > 0) {
                idx = sc->sc_tx_cons;
                KASSERT(idx < DWGE_NTXDESC);
@@ -836,8 +837,7 @@ dwge_tx_proc(struct dwge_softc *sc)
                        txb->tb_m = NULL;
                }
 
-               ifq_clr_oactive(&ifp->if_snd);
-
+               txfree++;
                sc->sc_tx_cnt--;
 
                if (sc->sc_tx_cons == (DWGE_NTXDESC - 1))
@@ -850,6 +850,11 @@ dwge_tx_proc(struct dwge_softc *sc)
 
        if (sc->sc_tx_cnt == 0)
                ifp->if_timer = 0;
+
+       if (txfree) {
+               if (ifq_is_oactive(&ifp->if_snd))
+                       ifq_restart(&ifp->if_snd);
+       }
 }
 
 void
Index: if_dwxe.c
===================================================================
RCS file: /cvs/src/sys/dev/fdt/if_dwxe.c,v
retrieving revision 1.14
diff -u -p -u -p -r1.14 if_dwxe.c
--- if_dwxe.c   29 Sep 2019 13:04:03 -0000      1.14
+++ if_dwxe.c   6 Oct 2019 13:12:38 -0000
@@ -870,12 +870,13 @@ dwxe_tx_proc(struct dwxe_softc *sc)
        struct ifnet *ifp = &sc->sc_ac.ac_if;
        struct dwxe_desc *txd;
        struct dwxe_buf *txb;
-       int idx;
+       int idx, txfree;
 
        bus_dmamap_sync(sc->sc_dmat, DWXE_DMA_MAP(sc->sc_txring), 0,
            DWXE_DMA_LEN(sc->sc_txring),
            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 
+       txfree = 0;
        while (sc->sc_tx_cnt > 0) {
                idx = sc->sc_tx_cons;
                KASSERT(idx < DWXE_NTXDESC);
@@ -894,8 +895,7 @@ dwxe_tx_proc(struct dwxe_softc *sc)
                        txb->tb_m = NULL;
                }
 
-               ifq_clr_oactive(&ifp->if_snd);
-
+               txfree++;
                sc->sc_tx_cnt--;
 
                if (sc->sc_tx_cons == (DWXE_NTXDESC - 1))
@@ -908,6 +908,11 @@ dwxe_tx_proc(struct dwxe_softc *sc)
 
        if (sc->sc_tx_cnt == 0)
                ifp->if_timer = 0;
+
+       if (txfree) {
+               if (ifq_is_oactive(&ifp->if_snd))
+                       ifq_restart(&ifp->if_snd);
+       }
 }
 
 void

Reply via email to