this builds on jmatthew@'s last commit and adds mpsafe tx.

ive beat on it pretty hard, but more eyes/tests are appreciated.

ok?

Index: re.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/re.c,v
retrieving revision 1.188
diff -u -p -r1.188 re.c
--- re.c        28 Dec 2015 05:49:15 -0000      1.188
+++ re.c        28 Dec 2015 07:51:23 -0000
@@ -1042,6 +1042,7 @@ re_attach(struct rl_softc *sc, const cha
        ifp->if_softc = sc;
        strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+       ifp->if_xflags = IFXF_MPSAFE;
        ifp->if_ioctl = re_ioctl;
        ifp->if_start = re_start;
        ifp->if_watchdog = re_watchdog;
@@ -1497,12 +1498,12 @@ re_txeof(struct rl_softc *sc)
         * to restart the channel here to flush them out. This only
         * seems to be required with the PCIe devices.
         */
-       if (tx_free < sc->rl_ldata.rl_tx_desc_cnt)
+       if (ifq_is_oactive(&ifp->if_snd))
+               ifq_restart(&ifp->if_snd);
+       else if (tx_free < sc->rl_ldata.rl_tx_desc_cnt)
                CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START);
-       else {
-               ifq_clr_oactive(&ifp->if_snd);
+       else
                ifp->if_timer = 0;
-       }
 
        return (1);
 }
@@ -1589,7 +1590,7 @@ re_intr(void *arg)
                                 * masks.
                                 */
                                re_rxeof(sc);
-                               tx = re_txeof(sc);
+                               re_txeof(sc);
                        } else
                                CSR_WRITE_4(sc, RL_TIMERCNT, 1); /* reload */
                } else if (tx | rx) {
@@ -1602,12 +1603,6 @@ re_intr(void *arg)
                }
        }
 
-       if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
-               KERNEL_LOCK();
-               re_start(ifp);
-               KERNEL_UNLOCK();
-       }
-
        CSR_WRITE_2(sc, RL_IMR, sc->rl_intrs);
 
        return (claimed);
@@ -1691,7 +1686,7 @@ re_encap(struct rl_softc *sc, struct mbu
 
                /* FALLTHROUGH */
        default:
-               return (ENOBUFS);
+               return (ENOMEM);
        }
 
        nsegs = map->dm_nsegs;
@@ -1715,8 +1710,8 @@ re_encap(struct rl_softc *sc, struct mbu
                nsegs++;
        }
 
-       if (sc->rl_ldata.rl_tx_free - (*used + nsegs) <= 1) {
-               error = EFBIG;
+       if (*used + nsegs + 1 >= sc->rl_ldata.rl_tx_free) {
+               error = ENOBUFS;
                goto fail_unload;
        }
 
@@ -1840,36 +1835,41 @@ re_start(struct ifnet *ifp)
        struct mbuf     *m;
        int             idx, used = 0, txq_free, error;
 
-       if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
-               return;
-       if ((sc->rl_flags & RL_FLAG_LINK) == 0)
+       if (!ISSET(sc->rl_flags, RL_FLAG_LINK)) {
+               IFQ_PURGE(&ifp->if_snd);
                return;
+       }
 
        txq_free = sc->rl_ldata.rl_txq_considx;
        idx = sc->rl_ldata.rl_txq_prodidx;
-       if (idx >= txq_free)
+       if (txq_free <= idx)
                txq_free += RL_TX_QLEN;
        txq_free -= idx;
 
-       while (txq_free > 1) {
+       for (;;) {
+               if (txq_free <= 1) {
+                       ifq_set_oactive(&ifp->if_snd);
+                       break;
+               }
+
                m = ifq_deq_begin(&ifp->if_snd);
                if (m == NULL)
                        break;
 
                error = re_encap(sc, m, &sc->rl_ldata.rl_txq[idx], &used);
-               if (error != 0 && error != ENOBUFS) {
+               if (error == 0)
+                       ifq_deq_commit(&ifp->if_snd, m);
+               else if (error == ENOBUFS) {
                        ifq_deq_rollback(&ifp->if_snd, m);
                        ifq_set_oactive(&ifp->if_snd);
                        break;
-               } else if (error != 0) {
+               } else {
                        ifq_deq_commit(&ifp->if_snd, m);
                        m_freem(m);
                        ifp->if_oerrors++;
                        continue;
                }
 
-               ifq_deq_commit(&ifp->if_snd, m);
-
 #if NBPFILTER > 0
                if (ifp->if_bpf)
                        bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_OUT);
@@ -1882,10 +1882,11 @@ re_start(struct ifnet *ifp)
                return;
        
        ifp->if_timer = 5;
-       sc->rl_ldata.rl_txq_prodidx = idx;
        atomic_sub_int(&sc->rl_ldata.rl_tx_free, used);
        KASSERT(sc->rl_ldata.rl_tx_free >= 0);
 
+       sc->rl_ldata.rl_txq_prodidx = idx;
+
        CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START);
 }
 
@@ -2112,7 +2113,6 @@ re_watchdog(struct ifnet *ifp)
        sc = ifp->if_softc;
        s = splnet();
        printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname);
-       ifp->if_oerrors++;
 
        re_txeof(sc);
        re_rxeof(sc);
@@ -2140,7 +2140,6 @@ re_stop(struct ifnet *ifp)
 
        timeout_del(&sc->timer_handle);
        ifp->if_flags &= ~IFF_RUNNING;
-       ifq_clr_oactive(&ifp->if_snd);
 
        /*
         * Disable accepting frames to put RX MAC into idle state.
@@ -2183,14 +2182,16 @@ re_stop(struct ifnet *ifp)
        CSR_WRITE_2(sc, RL_IMR, 0x0000);
        CSR_WRITE_2(sc, RL_ISR, 0xFFFF);
 
+       intr_barrier(sc->sc_ih);
+       ifq_barrier(&ifp->if_snd);
+
+       ifq_clr_oactive(&ifp->if_snd);
+       mii_down(&sc->sc_mii);
+
        if (sc->rl_head != NULL) {
                m_freem(sc->rl_head);
                sc->rl_head = sc->rl_tail = NULL;
        }
-
-       intr_barrier(sc->sc_ih);
-
-       mii_down(&sc->sc_mii);
 
        /* Free the TX list buffers. */
        for (i = 0; i < RL_TX_QLEN; i++) {

Reply via email to