Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ixl/ixl_txrx.c
Show First 20 Lines • Show All 212 Lines • ▼ Show 20 Lines | |||||
** Find mbuf chains passed to the driver | ** Find mbuf chains passed to the driver | ||||
** that are 'sparse', using more than 8 | ** that are 'sparse', using more than 8 | ||||
** mbufs to deliver an mss-size chunk of data | ** mbufs to deliver an mss-size chunk of data | ||||
*/ | */ | ||||
static inline bool | static inline bool | ||||
ixl_tso_detect_sparse(struct mbuf *mp) | ixl_tso_detect_sparse(struct mbuf *mp) | ||||
{ | { | ||||
struct mbuf *m; | struct mbuf *m; | ||||
int num = 0, mss; | int num, mss; | ||||
bool ret = FALSE; | |||||
num = 0; | |||||
mss = mp->m_pkthdr.tso_segsz; | 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) { | for (m = mp->m_next; m != NULL; m = m->m_next) { | ||||
num++; | if (m == NULL) | ||||
mss -= m->m_len; | |||||
if (mss < 1) | |||||
break; | break; | ||||
if (m->m_next == NULL) | num++; | ||||
break; | mss -= m->m_len % mp->m_pkthdr.tso_segsz; | ||||
} | |||||
if (mss < 1) { | |||||
if (num > IXL_SPARSE_CHAIN) | if (num > IXL_SPARSE_CHAIN) | ||||
ret = TRUE; | return (true); | ||||
num = (mss == 0) ? 0 : 1; | |||||
mss += mp->m_pkthdr.tso_segsz; | |||||
} | |||||
} | |||||
return (ret); | return (false); | ||||
} | } | ||||
/********************************************************************* | /********************************************************************* | ||||
* | * | ||||
* This routine maps the mbufs to tx descriptors, allowing the | * This routine maps the mbufs to tx descriptors, allowing the | ||||
* TX engine to transmit the packets. | * TX engine to transmit the packets. | ||||
* - return 0 on success, positive on failure | * - return 0 on success, positive on failure | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | if (m == NULL) { | ||||
return (ENOBUFS); | return (ENOBUFS); | ||||
} | } | ||||
*m_headp = m; | *m_headp = m; | ||||
/* Try it again */ | /* Try it again */ | ||||
error = bus_dmamap_load_mbuf_sg(tag, map, | error = bus_dmamap_load_mbuf_sg(tag, map, | ||||
*m_headp, segs, &nsegs, BUS_DMA_NOWAIT); | *m_headp, segs, &nsegs, BUS_DMA_NOWAIT); | ||||
if (error == ENOMEM) { | if (error != 0) { | ||||
que->tx_dmamap_failed++; | que->tx_dmamap_failed++; | ||||
return (error); | |||||
} else if (error != 0) { | |||||
que->tx_dmamap_failed++; | |||||
m_freem(*m_headp); | m_freem(*m_headp); | ||||
*m_headp = NULL; | *m_headp = NULL; | ||||
return (error); | return (error); | ||||
} | } | ||||
} else if (error == ENOMEM) { | |||||
que->tx_dmamap_failed++; | |||||
return (error); | |||||
} else if (error != 0) { | } else if (error != 0) { | ||||
que->tx_dmamap_failed++; | que->tx_dmamap_failed++; | ||||
m_freem(*m_headp); | m_freem(*m_headp); | ||||
*m_headp = NULL; | *m_headp = NULL; | ||||
return (error); | return (error); | ||||
} | } | ||||
/* Make certain there are enough descriptors */ | /* Make certain there are enough descriptors */ | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | ixl_xmit(struct ixl_queue *que, struct mbuf **m_headp) | ||||
/* | /* | ||||
* Advance the Transmit Descriptor Tail (Tdt), this tells the | * Advance the Transmit Descriptor Tail (Tdt), this tells the | ||||
* hardware that this frame is available to transmit. | * hardware that this frame is available to transmit. | ||||
*/ | */ | ||||
++txr->total_packets; | ++txr->total_packets; | ||||
wr32(hw, txr->tail, i); | wr32(hw, txr->tail, i); | ||||
/* Mark outstanding work */ | /* Mark outstanding work */ | ||||
if (que->busy == 0) | atomic_store_rel_32(&txr->watchdog_timer, IXL_WATCHDOG); | ||||
que->busy = 1; | |||||
return (0); | return (0); | ||||
xmit_fail: | xmit_fail: | ||||
bus_dmamap_unload(tag, buf->map); | bus_dmamap_unload(tag, buf->map); | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | #endif /* DEV_NETMAP */ | ||||
bzero((void *)txr->base, | bzero((void *)txr->base, | ||||
(sizeof(struct i40e_tx_desc)) * que->num_desc); | (sizeof(struct i40e_tx_desc)) * que->num_desc); | ||||
/* Reset indices */ | /* Reset indices */ | ||||
txr->next_avail = 0; | txr->next_avail = 0; | ||||
txr->next_to_clean = 0; | txr->next_to_clean = 0; | ||||
/* Reset watchdog status */ | |||||
txr->watchdog_timer = 0; | |||||
#ifdef IXL_FDIR | #ifdef IXL_FDIR | ||||
/* Initialize flow director */ | /* Initialize flow director */ | ||||
txr->atr_rate = ixl_atr_rate; | txr->atr_rate = ixl_atr_rate; | ||||
txr->atr_count = 0; | txr->atr_count = 0; | ||||
#endif | #endif | ||||
/* Free any existing tx mbufs. */ | /* Free any existing tx mbufs. */ | ||||
buf = txr->buffers; | buf = txr->buffers; | ||||
for (int i = 0; i < que->num_desc; i++, buf++) { | for (int i = 0; i < que->num_desc; i++, buf++) { | ||||
if (buf->m_head != NULL) { | if (buf->m_head != NULL) { | ||||
bus_dmamap_sync(buf->tag, buf->map, | bus_dmamap_sync(buf->tag, buf->map, | ||||
BUS_DMASYNC_POSTWRITE); | BUS_DMASYNC_POSTWRITE); | ||||
bus_dmamap_unload(buf->tag, buf->map); | bus_dmamap_unload(buf->tag, buf->map); | ||||
m_freem(buf->m_head); | m_freem(buf->m_head); | ||||
▲ Show 20 Lines • Show All 272 Lines • ▼ Show 20 Lines | #endif | ||||
idx = txr->next_avail; | idx = txr->next_avail; | ||||
buf = &txr->buffers[idx]; | buf = &txr->buffers[idx]; | ||||
TXD = (struct i40e_tx_context_desc *) &txr->base[idx]; | TXD = (struct i40e_tx_context_desc *) &txr->base[idx]; | ||||
tsolen = mp->m_pkthdr.len - (elen + ip_hlen + tcp_hlen); | tsolen = mp->m_pkthdr.len - (elen + ip_hlen + tcp_hlen); | ||||
type = I40E_TX_DESC_DTYPE_CONTEXT; | type = I40E_TX_DESC_DTYPE_CONTEXT; | ||||
cmd = I40E_TX_CTX_DESC_TSO; | 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; | mss = mp->m_pkthdr.tso_segsz; | ||||
type_cmd_tso_mss = ((u64)type << I40E_TXD_CTX_QW1_DTYPE_SHIFT) | | type_cmd_tso_mss = ((u64)type << I40E_TXD_CTX_QW1_DTYPE_SHIFT) | | ||||
((u64)cmd << I40E_TXD_CTX_QW1_CMD_SHIFT) | | ((u64)cmd << I40E_TXD_CTX_QW1_CMD_SHIFT) | | ||||
((u64)tsolen << I40E_TXD_CTX_QW1_TSO_LEN_SHIFT) | | ((u64)tsolen << I40E_TXD_CTX_QW1_TSO_LEN_SHIFT) | | ||||
((u64)mss << I40E_TXD_CTX_QW1_MSS_SHIFT); | ((u64)mss << I40E_TXD_CTX_QW1_MSS_SHIFT); | ||||
TXD->type_cmd_tso_mss = htole64(type_cmd_tso_mss); | TXD->type_cmd_tso_mss = htole64(type_cmd_tso_mss); | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
#ifdef DEV_NETMAP | #ifdef DEV_NETMAP | ||||
// XXX todo: implement moderation | // XXX todo: implement moderation | ||||
if (netmap_tx_irq(que->vsi->ifp, que->me)) | if (netmap_tx_irq(que->vsi->ifp, que->me)) | ||||
return FALSE; | return FALSE; | ||||
#endif /* DEF_NETMAP */ | #endif /* DEF_NETMAP */ | ||||
/* These are not the descriptors you seek, move along :) */ | /* These are not the descriptors you seek, move along :) */ | ||||
if (txr->avail == que->num_desc) { | if (txr->avail == que->num_desc) { | ||||
que->busy = 0; | atomic_store_rel_32(&txr->watchdog_timer, 0); | ||||
return FALSE; | return FALSE; | ||||
} | } | ||||
processed = 0; | processed = 0; | ||||
first = txr->next_to_clean; | first = txr->next_to_clean; | ||||
buf = &txr->buffers[first]; | buf = &txr->buffers[first]; | ||||
tx_desc = (struct i40e_tx_desc *)&txr->base[first]; | tx_desc = (struct i40e_tx_desc *)&txr->base[first]; | ||||
last = buf->eop_index; | last = buf->eop_index; | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | #endif /* DEF_NETMAP */ | ||||
} | } | ||||
bus_dmamap_sync(txr->dma.tag, txr->dma.map, | bus_dmamap_sync(txr->dma.tag, txr->dma.map, | ||||
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | ||||
txr->next_to_clean = first; | txr->next_to_clean = first; | ||||
/* | /* | ||||
** 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 there are no pending descriptors, clear the timeout. | ||||
*/ | */ | ||||
if (txr->avail == que->num_desc) { | if (txr->avail == que->num_desc) { | ||||
que->busy = 0; | atomic_store_rel_32(&txr->watchdog_timer, 0); | ||||
return FALSE; | return FALSE; | ||||
} | } | ||||
return TRUE; | return TRUE; | ||||
} | } | ||||
/********************************************************************* | /********************************************************************* | ||||
* | * | ||||
▲ Show 20 Lines • Show All 761 Lines • ▼ Show 20 Lines | if (ixl_rx_unrefreshed(que)) | ||||
ixl_refresh_mbufs(que, i); | ixl_refresh_mbufs(que, i); | ||||
rxr->next_check = i; | rxr->next_check = i; | ||||
#if defined(INET6) || defined(INET) | #if defined(INET6) || defined(INET) | ||||
/* | /* | ||||
* Flush any outstanding LRO work | * Flush any outstanding LRO work | ||||
*/ | */ | ||||
#if __FreeBSD_version >= 1100105 | |||||
tcp_lro_flush_all(lro); | 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 | ||||
#endif /* defined(INET6) || defined(INET) */ | |||||
IXL_RX_UNLOCK(rxr); | IXL_RX_UNLOCK(rxr); | ||||
return (FALSE); | return (FALSE); | ||||
} | } | ||||
/********************************************************************* | /********************************************************************* | ||||
* | * | ||||
▲ Show 20 Lines • Show All 81 Lines • Show Last 20 Lines |