ie, do the space check before trying to dequeue and mbuf. this also moves it to using m_defrag.
i dont have an msk plugged in and i dont know how to use the overdrive 1000 i have here. if someone could test and ok this, it would be great. Index: if_msk.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_msk.c,v retrieving revision 1.127 diff -u -p -r1.127 if_msk.c --- if_msk.c 10 Apr 2017 02:15:54 -0000 1.127 +++ if_msk.c 31 May 2017 00:27:04 -0000 @@ -1489,31 +1489,20 @@ msk_encap(struct sk_if_softc *sc_if, str cur = frag = *txidx; -#ifdef MSK_DEBUG - if (mskdebug >= 2) - msk_dump_mbuf(m_head); -#endif - - /* - * Start packing the mbufs in this chain into - * the fragment pointers. Stop when we run out - * of fragments or hit the end of the mbuf chain. - */ - if (bus_dmamap_load_mbuf(sc->sc_dmatag, txmap, m_head, - BUS_DMA_NOWAIT)) { - DPRINTFN(2, ("msk_encap: dmamap failed\n")); - return (ENOBUFS); - } - - entries = txmap->dm_nsegs * 2; - if (entries > (MSK_TX_RING_CNT - sc_if->sk_cdata.sk_tx_cnt - 2)) { - DPRINTFN(2, ("msk_encap: too few descriptors free\n")); - bus_dmamap_unload(sc->sc_dmatag, txmap); - return (ENOBUFS); + switch (bus_dmamap_load_mbuf(sc->sc_dmatag, txmap, m_head, + BUS_DMA_STREAMING | BUS_DMA_NOWAIT)) { + case 0: + break; + case EFBIG: /* mbuf chain is too fragmented */ + if (m_defrag(m_head, M_DONTWAIT) == 0 && + bus_dmamap_load_mbuf(sc->sc_dmatag, txmap, m_head, + BUS_DMA_STREAMING | BUS_DMA_NOWAIT) == 0) + break; + /* FALLTHROUGH */ + default: + return (1); } - DPRINTFN(2, ("msk_encap: dm_nsegs=%d\n", txmap->dm_nsegs)); - /* Sync the DMA map. */ bus_dmamap_sync(sc->sc_dmatag, txmap, 0, txmap->dm_mapsize, BUS_DMASYNC_PREWRITE); @@ -1585,12 +1574,16 @@ msk_start(struct ifnet *ifp) struct sk_if_softc *sc_if = ifp->if_softc; struct mbuf *m_head = NULL; u_int32_t idx = sc_if->sk_cdata.sk_tx_prod; - int pkts = 0; + int post = 0; - DPRINTFN(2, ("msk_start\n")); + for (;;) { + if (sc_if->sk_cdata.sk_tx_cnt + (SK_NTXSEG * 2) + 1 > + MSK_TX_RING_CNT) { + ifq_set_oactive(&ifp->if_snd); + break; + } - while (sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf == NULL) { - m_head = ifq_deq_begin(&ifp->if_snd); + m_head = ifq_dequeue(&ifp->if_snd); if (m_head == NULL) break; @@ -1600,14 +1593,11 @@ msk_start(struct ifnet *ifp) * for the NIC to drain the ring. */ if (msk_encap(sc_if, m_head, &idx)) { - ifq_deq_rollback(&ifp->if_snd, m_head); - ifq_set_oactive(&ifp->if_snd); - break; + m_freem(m_head); + continue; } /* now we are committed to transmit the packet */ - ifq_deq_commit(&ifp->if_snd, m_head); - pkts++; /* * If there's a BPF listener, bounce a copy of this frame @@ -1617,18 +1607,17 @@ msk_start(struct ifnet *ifp) if (ifp->if_bpf) bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT); #endif + post = 1; } - if (pkts == 0) + if (post == 0) return; /* Transmit */ - if (idx != sc_if->sk_cdata.sk_tx_prod) { - sc_if->sk_cdata.sk_tx_prod = idx; - SK_IF_WRITE_2(sc_if, 1, SK_TXQA1_Y2_PREF_PUTIDX, idx); + sc_if->sk_cdata.sk_tx_prod = idx; + SK_IF_WRITE_2(sc_if, 1, SK_TXQA1_Y2_PREF_PUTIDX, idx); - /* Set a timeout in case the chip goes out to lunch. */ - ifp->if_timer = MSK_TX_TIMEOUT; - } + /* Set a timeout in case the chip goes out to lunch. */ + ifp->if_timer = MSK_TX_TIMEOUT; } void