cxgbe(4): Do not assume that if_qflush is always followed by inteface-down.

MFC after:	3 days
Sponsored by:	Chelsio Communications
This commit is contained in:
Navdeep Parhar 2017-05-09 18:33:41 +00:00
parent 7dd10fded0
commit 1404daa76c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=318091
3 changed files with 13 additions and 2 deletions

View File

@ -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 */

View File

@ -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);

View File

@ -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);