Index: sys/dev/e1000/if_em.c =================================================================== --- sys/dev/e1000/if_em.c (revision 203658) +++ sys/dev/e1000/if_em.c (working copy) @@ -1020,7 +1020,7 @@ em_mq_start_locked(struct ifnet *ifp, struct mbuf { struct adapter *adapter = ifp->if_softc; struct mbuf *next; - int error = E1000_SUCCESS; + int ret, error = E1000_SUCCESS; EM_TX_LOCK_ASSERT(adapter); /* To allow being called from a tasklet */ @@ -1032,28 +1032,34 @@ em_mq_start_locked(struct ifnet *ifp, struct mbuf || (!adapter->link_active)) { error = drbr_enqueue(ifp, adapter->br, m); return (error); - } else if (drbr_empty(ifp, adapter->br) && - (adapter->num_tx_desc_avail > EM_TX_OP_THRESHOLD)) { - if ((error = em_xmit(adapter, &m)) != 0) { - if (m != NULL) - error = drbr_enqueue(ifp, adapter->br, m); - return (error); - } else { - /* - * We've bypassed the buf ring so we need to update - * ifp directly - */ - drbr_stats_update(ifp, m->m_pkthdr.len, m->m_flags); - /* - ** Send a copy of the frame to the BPF - ** listener and set the watchdog on. - */ - ETHER_BPF_MTAP(ifp, m); - adapter->watchdog_timer = EM_TX_TIMEOUT; - } - } else if ((error = drbr_enqueue(ifp, adapter->br, m)) != 0) - return (error); - + } + ret = drbr_maybe_enqueue(ifp, adapter->br, m); + if (ret == 0) { + if (adapter->num_tx_desc_avail > EM_TX_OP_THRESHOLD) { + if ((error = em_xmit(adapter, &m)) != 0) { + if (m) + error = drbr_enqueue(ifp, adapter->br, + m); + return (error); + } else { + /* + * We've bypassed the buf ring so we need to + * update ifp directly + */ + drbr_stats_update(ifp, m->m_pkthdr.len, + m->m_flags); + /* + ** Send a copy of the frame to the BPF + ** listener and set the watchdog on. + */ + ETHER_BPF_MTAP(ifp, m); + adapter->watchdog_timer = EM_TX_TIMEOUT; + } + } else if ((error = drbr_enqueue(ifp, adapter->br, m)) != 0) + return (error); + } else if (ret < 0) + return (-ret); + process: if (drbr_empty(ifp, adapter->br)) return(error); @@ -1066,7 +1072,7 @@ process: break; if ((error = em_xmit(adapter, &next)) != 0) { if (next != NULL) - error = drbr_enqueue(ifp, adapter->br, next); + error = drbr_requeue(ifp, adapter->br, next); break; } drbr_stats_update(ifp, next->m_pkthdr.len, next->m_flags); Index: sys/net/if_var.h =================================================================== --- sys/net/if_var.h (revision 201714) +++ sys/net/if_var.h (working copy) @@ -595,18 +595,26 @@ drbr_enqueue(struct ifnet *ifp, struct buf_ring *b return (error); } +static __inline int +drbr_requeue(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m) +{ +#ifdef ALTQ + if (ALTQ_IS_ENABLED(&ifp->if_snd)) { + IFQ_DRV_PREPEND(&ifp->if_snd, m); + return (0); + } +#endif + return drbr_enqueue(ifp, br, m); +} + static __inline void drbr_flush(struct ifnet *ifp, struct buf_ring *br) { struct mbuf *m; #ifdef ALTQ - if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) { - while (!IFQ_IS_EMPTY(&ifp->if_snd)) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - m_freem(m); - } - } + if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) + IFQ_DRV_PURGE(&ifp->if_snd); #endif while ((m = buf_ring_dequeue_sc(br)) != NULL) m_freem(m); @@ -640,11 +648,12 @@ drbr_dequeue_cond(struct ifnet *ifp, struct buf_ri { struct mbuf *m; #ifdef ALTQ - /* - * XXX need to evaluate / requeue - */ if (ALTQ_IS_ENABLED(&ifp->if_snd)) { IFQ_DRV_DEQUEUE(&ifp->if_snd, m); + if (m != NULL && func(m, arg) == 0) { + IFQ_DRV_PREPEND(&ifp->if_snd, m); + return (NULL); + } return (m); } #endif @@ -666,6 +675,24 @@ drbr_empty(struct ifnet *ifp, struct buf_ring *br) } static __inline int +drbr_maybe_enqueue(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m) +{ + int error; + +#ifdef ALTQ + if (ALTQ_IS_ENABLED(&ifp->if_snd)) { + IFQ_ENQUEUE(&ifp->if_snd, m, error); + return error ? -error : 1; + } +#endif + if (drbr_empty(ifp, br)) + return 0; + + error = drbr_enqueue(ifp, br, m); + return error ? -error : 1; +} + +static __inline int drbr_inuse(struct ifnet *ifp, struct buf_ring *br) { #ifdef ALTQ