diff options
Diffstat (limited to 'sys/dev/ixl/ixl_txrx.c')
-rw-r--r-- | sys/dev/ixl/ixl_txrx.c | 73 |
1 files changed, 35 insertions, 38 deletions
diff --git a/sys/dev/ixl/ixl_txrx.c b/sys/dev/ixl/ixl_txrx.c index 5cf54fa..b329dc4 100644 --- a/sys/dev/ixl/ixl_txrx.c +++ b/sys/dev/ixl/ixl_txrx.c @@ -217,22 +217,27 @@ static inline bool ixl_tso_detect_sparse(struct mbuf *mp) { struct mbuf *m; - int num = 0, mss; - bool ret = FALSE; + int num, mss; + num = 0; mss = mp->m_pkthdr.tso_segsz; + + /* Exclude first mbuf; assume it contains all headers */ for (m = mp->m_next; m != NULL; m = m->m_next) { - num++; - mss -= m->m_len; - if (mss < 1) - break; - if (m->m_next == NULL) + if (m == NULL) break; + num++; + mss -= m->m_len % mp->m_pkthdr.tso_segsz; + + if (mss < 1) { + if (num > IXL_SPARSE_CHAIN) + return (true); + num = (mss == 0) ? 0 : 1; + mss += mp->m_pkthdr.tso_segsz; + } } - if (num > IXL_SPARSE_CHAIN) - ret = TRUE; - return (ret); + return (false); } @@ -311,18 +316,12 @@ ixl_xmit(struct ixl_queue *que, struct mbuf **m_headp) error = bus_dmamap_load_mbuf_sg(tag, map, *m_headp, segs, &nsegs, BUS_DMA_NOWAIT); - if (error == ENOMEM) { - que->tx_dmamap_failed++; - return (error); - } else if (error != 0) { + if (error != 0) { que->tx_dmamap_failed++; m_freem(*m_headp); *m_headp = NULL; return (error); } - } else if (error == ENOMEM) { - que->tx_dmamap_failed++; - return (error); } else if (error != 0) { que->tx_dmamap_failed++; m_freem(*m_headp); @@ -403,8 +402,7 @@ ixl_xmit(struct ixl_queue *que, struct mbuf **m_headp) wr32(hw, txr->tail, i); /* Mark outstanding work */ - if (que->busy == 0) - que->busy = 1; + atomic_store_rel_32(&txr->watchdog_timer, IXL_WATCHDOG); return (0); xmit_fail: @@ -523,12 +521,14 @@ ixl_init_tx_ring(struct ixl_queue *que) txr->next_avail = 0; txr->next_to_clean = 0; + /* Reset watchdog status */ + txr->watchdog_timer = 0; + #ifdef IXL_FDIR /* Initialize flow director */ txr->atr_rate = ixl_atr_rate; txr->atr_count = 0; #endif - /* Free any existing tx mbufs. */ buf = txr->buffers; for (int i = 0; i < que->num_desc; i++, buf++) { @@ -817,7 +817,11 @@ ixl_tso_setup(struct ixl_queue *que, struct mbuf *mp) type = I40E_TX_DESC_DTYPE_CONTEXT; cmd = I40E_TX_CTX_DESC_TSO; - /* ERJ: this must not be less than 64 */ + /* TSO MSS must not be less than 64 */ + if (mp->m_pkthdr.tso_segsz < IXL_MIN_TSO_MSS) { + que->mss_too_small++; + mp->m_pkthdr.tso_segsz = IXL_MIN_TSO_MSS; + } mss = mp->m_pkthdr.tso_segsz; type_cmd_tso_mss = ((u64)type << I40E_TXD_CTX_QW1_DTYPE_SHIFT) | @@ -877,7 +881,7 @@ ixl_txeof(struct ixl_queue *que) /* These are not the descriptors you seek, move along :) */ if (txr->avail == que->num_desc) { - que->busy = 0; + atomic_store_rel_32(&txr->watchdog_timer, 0); return FALSE; } @@ -956,25 +960,10 @@ ixl_txeof(struct ixl_queue *que) /* - ** Hang detection, we know there's - ** work outstanding or the first return - ** would have been taken, so indicate an - ** unsuccessful pass, in local_timer if - ** the value is too great the queue will - ** be considered hung. If anything has been - ** cleaned then reset the state. - */ - if ((processed == 0) && (que->busy != IXL_QUEUE_HUNG)) - ++que->busy; - - if (processed) - que->busy = 1; /* Note this turns off HUNG */ - - /* * If there are no pending descriptors, clear the timeout. */ if (txr->avail == que->num_desc) { - que->busy = 0; + atomic_store_rel_32(&txr->watchdog_timer, 0); return FALSE; } @@ -1752,8 +1741,16 @@ next_desc: /* * Flush any outstanding LRO work */ +#if __FreeBSD_version >= 1100105 tcp_lro_flush_all(lro); +#else + struct lro_entry *queued; + while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) { + SLIST_REMOVE_HEAD(&lro->lro_active, next); + tcp_lro_flush(lro, queued); + } #endif +#endif /* defined(INET6) || defined(INET) */ IXL_RX_UNLOCK(rxr); return (FALSE); |