basically check for space on the ring before dequeuing the packet.

any errors we hit after that cause us to drop the mbuf.

ok?

Index: if_bge.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_bge.c,v
retrieving revision 1.371
diff -u -p -r1.371 if_bge.c
--- if_bge.c    25 Oct 2015 13:04:28 -0000      1.371
+++ if_bge.c    11 Nov 2015 03:25:30 -0000
@@ -3985,7 +3985,7 @@ bge_cksum_pad(struct mbuf *m)
  * pointers to descriptors.
  */
 int
-bge_encap(struct bge_softc *sc, struct mbuf *m_head, int *txinc)
+bge_encap(struct bge_softc *sc, struct mbuf *m, int *txinc)
 {
        struct bge_tx_bd        *f = NULL;
        u_int32_t               frag, cur;
@@ -3995,20 +3995,20 @@ bge_encap(struct bge_softc *sc, struct m
 
        cur = frag = (sc->bge_tx_prodidx + *txinc) % BGE_TX_RING_CNT;
 
-       if (m_head->m_pkthdr.csum_flags) {
-               if (m_head->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT)
+       if (m->m_pkthdr.csum_flags) {
+               if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT)
                        csum_flags |= BGE_TXBDFLAG_IP_CSUM;
-               if (m_head->m_pkthdr.csum_flags & (M_TCP_CSUM_OUT |
-                   M_UDP_CSUM_OUT)) {
+               if (m->m_pkthdr.csum_flags &
+                   (M_TCP_CSUM_OUT | M_UDP_CSUM_OUT)) {
                        csum_flags |= BGE_TXBDFLAG_TCP_UDP_CSUM;
-                       if (m_head->m_pkthdr.len < ETHER_MIN_NOPAD &&
-                           bge_cksum_pad(m_head) != 0)
+                       if (m->m_pkthdr.len < ETHER_MIN_NOPAD &&
+                           bge_cksum_pad(m) != 0)
                                return (ENOBUFS);
                }
        }
 
        if (sc->bge_flags & BGE_JUMBO_FRAME && 
-           m_head->m_pkthdr.len > ETHER_MAX_LEN)
+           m->m_pkthdr.len > ETHER_MAX_LEN)
                csum_flags |= BGE_TXBDFLAG_JUMBO_FRAME;
 
        if (!(BGE_CHIPREV(sc->bge_chipid) == BGE_CHIPREV_5700_BX))
@@ -4019,7 +4019,7 @@ bge_encap(struct bge_softc *sc, struct m
         * less than eight bytes.  If we encounter a teeny mbuf
         * at the end of a chain, we can pad.  Otherwise, copy.
         */
-       if (bge_compact_dma_runt(m_head) != 0)
+       if (bge_compact_dma_runt(m) != 0)
                return (ENOBUFS);
 
 doit:
@@ -4030,13 +4030,13 @@ doit:
         * the fragment pointers. Stop when we run out
         * of fragments or hit the end of the mbuf chain.
         */
-       switch (bus_dmamap_load_mbuf(sc->bge_dmatag, dmamap, m_head,
+       switch (bus_dmamap_load_mbuf(sc->bge_dmatag, dmamap, m,
            BUS_DMA_NOWAIT)) {
        case 0:
                break;
        case EFBIG:
-               if (m_defrag(m_head, M_DONTWAIT) == 0 &&
-                   bus_dmamap_load_mbuf(sc->bge_dmatag, dmamap, m_head,
+               if (m_defrag(m, M_DONTWAIT) == 0 &&
+                   bus_dmamap_load_mbuf(sc->bge_dmatag, dmamap, m,
                     BUS_DMA_NOWAIT) == 0)
                        break;
 
@@ -4045,10 +4045,6 @@ doit:
                return (ENOBUFS);
        }
 
-       /* Check if we have enough free send BDs. */
-       if (sc->bge_txcnt + *txinc + dmamap->dm_nsegs >= BGE_TX_RING_CNT)
-               goto fail_unload;
-
        for (i = 0; i < dmamap->dm_nsegs; i++) {
                f = &sc->bge_rdata->bge_tx_ring[frag];
                if (sc->bge_cdata.bge_tx_chain[frag] != NULL)
@@ -4058,9 +4054,9 @@ doit:
                f->bge_flags = csum_flags;
                f->bge_vlan_tag = 0;
 #if NVLAN > 0
-               if (m_head->m_flags & M_VLANTAG) {
+               if (m->m_flags & M_VLANTAG) {
                        f->bge_flags |= BGE_TXBDFLAG_VLAN_TAG;
-                       f->bge_vlan_tag = m_head->m_pkthdr.ether_vtag;
+                       f->bge_vlan_tag = m->m_pkthdr.ether_vtag;
                }
 #endif
                cur = frag;
@@ -4077,7 +4073,7 @@ doit:
                goto fail_unload;
 
        sc->bge_rdata->bge_tx_ring[cur].bge_flags |= BGE_TXBDFLAG_END;
-       sc->bge_cdata.bge_tx_chain[cur] = m_head;
+       sc->bge_cdata.bge_tx_chain[cur] = m;
        sc->bge_cdata.bge_tx_map[cur] = dmamap;
        
        *txinc += dmamap->dm_nsegs;
@@ -4098,7 +4094,7 @@ void
 bge_start(struct ifnet *ifp)
 {
        struct bge_softc *sc;
-       struct mbuf *m_head;
+       struct mbuf *m;
        int txinc;
 
        sc = ifp->if_softc;
@@ -4110,25 +4106,28 @@ bge_start(struct ifnet *ifp)
 
        txinc = 0;
        while (1) {
-               IFQ_POLL(&ifp->if_snd, m_head);
-               if (m_head == NULL)
+               /* Check if we have enough free send BDs. */
+               if (sc->bge_txcnt + txinc + BGE_NTXSEG >= BGE_TX_RING_CNT) {
+                       ifp->if_flags |= IFF_OACTIVE;
                        break;
+               }
 
-               if (bge_encap(sc, m_head, &txinc))
+               IFQ_DEQUEUE(&ifp->if_snd, m);
+               if (m == NULL)
                        break;
 
-               /* now we are committed to transmit the packet */
-               IFQ_DEQUEUE(&ifp->if_snd, m_head);
+               if (bge_encap(sc, m, &txinc) != 0) {
+                       m_freem(m);
+                       continue;
+               }
 
 #if NBPFILTER > 0
                if (ifp->if_bpf)
-                       bpf_mtap_ether(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
+                       bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_OUT);
 #endif
        }
 
        if (txinc != 0) {
-               int txcnt;
-
                /* Transmit */
                sc->bge_tx_prodidx = (sc->bge_tx_prodidx + txinc) %
                    BGE_TX_RING_CNT;
@@ -4137,9 +4136,7 @@ bge_start(struct ifnet *ifp)
                        bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO,
                            sc->bge_tx_prodidx);
 
-               txcnt = atomic_add_int_nv(&sc->bge_txcnt, txinc);
-               if (txcnt > BGE_TX_RING_CNT - 16)
-                       ifp->if_flags |= IFF_OACTIVE;
+               atomic_add_int(&sc->bge_txcnt, txinc);
 
                /*
                 * Set a timeout in case the chip goes out to lunch.

Reply via email to