diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h index c980186f9e61..d9b32a62a65c 100644 --- a/sys/dev/cxgbe/adapter.h +++ b/sys/dev/cxgbe/adapter.h @@ -399,6 +399,7 @@ enum { EQ_TYPEMASK = 0x3, /* 2 lsbits hold the type (see above) */ EQ_ALLOCATED = (1 << 2), /* firmware resources allocated */ EQ_ENABLED = (1 << 3), /* open for business */ + EQ_QFLUSH = (1 << 4), /* if_qflush in progress */ }; /* Listed in order of preference. Update t4_sysctls too if you change these */ diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index c06524d77847..9b5e4ff09a11 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -1869,12 +1869,15 @@ cxgbe_qflush(struct ifnet *ifp) if (vi->flags & VI_INIT_DONE) { for_each_txq(vi, i, txq) { TXQ_LOCK(txq); - txq->eq.flags &= ~EQ_ENABLED; + txq->eq.flags |= EQ_QFLUSH; TXQ_UNLOCK(txq); while (!mp_ring_is_idle(txq->r)) { mp_ring_check_drainage(txq->r, 0); pause("qflush", 1); } + TXQ_LOCK(txq); + txq->eq.flags &= ~EQ_QFLUSH; + TXQ_UNLOCK(txq); } } if_qflush(ifp); diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c index 496b91dbbaa4..a0ccb52c2829 100644 --- a/sys/dev/cxgbe/t4_sge.c +++ b/sys/dev/cxgbe/t4_sge.c @@ -2452,6 +2452,13 @@ cannot_use_txpkts(struct mbuf *m) return (needs_tso(m)); } +static inline int +discard_tx(struct sge_eq *eq) +{ + + return ((eq->flags & (EQ_ENABLED | EQ_QFLUSH)) != EQ_ENABLED); +} + /* * r->items[cidx] to r->items[pidx], with a wraparound at r->size, are ready to * be consumed. Return the actual number consumed. 0 indicates a stall. @@ -2477,7 +2484,7 @@ eth_tx(struct mp_ring *r, u_int cidx, u_int pidx) total = 0; TXQ_LOCK(txq); - if (__predict_false((eq->flags & EQ_ENABLED) == 0)) { + if (__predict_false(discard_tx(eq))) { while (cidx != pidx) { m0 = r->items[cidx]; m_freem(m0);