#include "mlx5.h"
#include "mlx5_autoconf.h"
-#include "mlx5_mr.h"
/* TX burst subroutines return codes. */
enum mlx5_txcmp_code {
#define MLX5_TXOFF_CONFIG(mask) (olx & MLX5_TXOFF_CONFIG_##mask)
+#define MLX5_TXOFF_PRE_DECL(func) \
+uint16_t mlx5_tx_burst_##func(void *txq, \
+ struct rte_mbuf **pkts, \
+ uint16_t pkts_n)
+
#define MLX5_TXOFF_DECL(func, olx) \
-static uint16_t mlx5_tx_burst_##func(void *txq, \
- struct rte_mbuf **pkts, \
- uint16_t pkts_n) \
+uint16_t mlx5_tx_burst_##func(void *txq, \
+ struct rte_mbuf **pkts, \
+ uint16_t pkts_n) \
{ \
return mlx5_tx_burst_tmpl((struct mlx5_txq_data *)txq, \
pkts, pkts_n, (olx)); \
int mlx5_tx_hairpin_queue_setup
(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
const struct rte_eth_hairpin_conf *hairpin_conf);
-void mlx5_tx_queue_release(void *dpdk_txq);
+void mlx5_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid);
void txq_uar_init(struct mlx5_txq_ctrl *txq_ctrl);
int mlx5_tx_uar_init_secondary(struct rte_eth_dev *dev, int fd);
void mlx5_tx_uar_uninit_secondary(struct rte_eth_dev *dev);
int mlx5_tx_burst_mode_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
struct rte_eth_burst_mode *mode);
-/* mlx5_mr.c */
-
-uint32_t mlx5_tx_mb2mr_bh(struct mlx5_txq_data *txq, struct rte_mbuf *mb);
-uint32_t mlx5_tx_update_ext_mp(struct mlx5_txq_data *txq, uintptr_t addr,
- struct rte_mempool *mp);
+/* mlx5_tx_empw.c */
+
+MLX5_TXOFF_PRE_DECL(full_empw);
+MLX5_TXOFF_PRE_DECL(none_empw);
+MLX5_TXOFF_PRE_DECL(md_empw);
+MLX5_TXOFF_PRE_DECL(mt_empw);
+MLX5_TXOFF_PRE_DECL(mtsc_empw);
+MLX5_TXOFF_PRE_DECL(mti_empw);
+MLX5_TXOFF_PRE_DECL(mtv_empw);
+MLX5_TXOFF_PRE_DECL(mtiv_empw);
+MLX5_TXOFF_PRE_DECL(sc_empw);
+MLX5_TXOFF_PRE_DECL(sci_empw);
+MLX5_TXOFF_PRE_DECL(scv_empw);
+MLX5_TXOFF_PRE_DECL(sciv_empw);
+MLX5_TXOFF_PRE_DECL(i_empw);
+MLX5_TXOFF_PRE_DECL(v_empw);
+MLX5_TXOFF_PRE_DECL(iv_empw);
+
+/* mlx5_tx_nompw.c */
+
+MLX5_TXOFF_PRE_DECL(full);
+MLX5_TXOFF_PRE_DECL(none);
+MLX5_TXOFF_PRE_DECL(md);
+MLX5_TXOFF_PRE_DECL(mt);
+MLX5_TXOFF_PRE_DECL(mtsc);
+MLX5_TXOFF_PRE_DECL(mti);
+MLX5_TXOFF_PRE_DECL(mtv);
+MLX5_TXOFF_PRE_DECL(mtiv);
+MLX5_TXOFF_PRE_DECL(sc);
+MLX5_TXOFF_PRE_DECL(sci);
+MLX5_TXOFF_PRE_DECL(scv);
+MLX5_TXOFF_PRE_DECL(sciv);
+MLX5_TXOFF_PRE_DECL(i);
+MLX5_TXOFF_PRE_DECL(v);
+MLX5_TXOFF_PRE_DECL(iv);
+
+/* mlx5_tx_txpp.c */
+
+MLX5_TXOFF_PRE_DECL(full_ts_nompw);
+MLX5_TXOFF_PRE_DECL(full_ts_nompwi);
+MLX5_TXOFF_PRE_DECL(full_ts);
+MLX5_TXOFF_PRE_DECL(full_ts_noi);
+MLX5_TXOFF_PRE_DECL(none_ts);
+MLX5_TXOFF_PRE_DECL(mdi_ts);
+MLX5_TXOFF_PRE_DECL(mti_ts);
+MLX5_TXOFF_PRE_DECL(mtiv_ts);
+
+/* mlx5_tx_mpw.c */
+
+MLX5_TXOFF_PRE_DECL(none_mpw);
+MLX5_TXOFF_PRE_DECL(mci_mpw);
+MLX5_TXOFF_PRE_DECL(mc_mpw);
+MLX5_TXOFF_PRE_DECL(i_mpw);
static __rte_always_inline uint64_t *
mlx5_tx_bfreg(struct mlx5_txq_data *txq)
#endif
/**
- * Query LKey from a packet buffer for Tx. If not found, add the mempool.
+ * Query LKey from a packet buffer for Tx.
*
* @param txq
* Pointer to Tx queue structure.
- * @param addr
- * Address to search.
+ * @param mb
+ * Pointer to mbuf.
*
* @return
* Searched LKey on success, UINT32_MAX on no match.
mlx5_tx_mb2mr(struct mlx5_txq_data *txq, struct rte_mbuf *mb)
{
struct mlx5_mr_ctrl *mr_ctrl = &txq->mr_ctrl;
- uintptr_t addr = (uintptr_t)mb->buf_addr;
- uint32_t lkey;
-
- /* Check generation bit to see if there's any change on existing MRs. */
- if (unlikely(*mr_ctrl->dev_gen_ptr != mr_ctrl->cur_gen))
- mlx5_mr_flush_local_cache(mr_ctrl);
- /* Linear search on MR cache array. */
- lkey = mlx5_mr_lookup_lkey(mr_ctrl->cache, &mr_ctrl->mru,
- MLX5_MR_CACHE_N, addr);
- if (likely(lkey != UINT32_MAX))
- return lkey;
+ struct mlx5_txq_ctrl *txq_ctrl =
+ container_of(txq, struct mlx5_txq_ctrl, txq);
+ struct mlx5_priv *priv = txq_ctrl->priv;
+
/* Take slower bottom-half on miss. */
- return mlx5_tx_mb2mr_bh(txq, mb);
+ return mlx5_mr_mb2mr(priv->sh->cdev, &priv->mp_id, mr_ctrl, mb);
}
/**
* should be set regardless of HW offload.
*/
off = loc->mbuf->outer_l2_len;
- if (MLX5_TXOFF_CONFIG(VLAN) && ol & PKT_TX_VLAN_PKT)
+ if (MLX5_TXOFF_CONFIG(VLAN) && ol & PKT_TX_VLAN)
off += sizeof(struct rte_vlan_hdr);
set = (off >> 1) << 8; /* Outer L3 offset. */
off += loc->mbuf->outer_l3_len;
/* Fill metadata field if needed. */
es->metadata = MLX5_TXOFF_CONFIG(METADATA) ?
loc->mbuf->ol_flags & PKT_TX_DYNF_METADATA ?
- *RTE_FLOW_DYNF_METADATA(loc->mbuf) : 0 : 0;
+ rte_cpu_to_be_32(*RTE_FLOW_DYNF_METADATA(loc->mbuf)) :
+ 0 : 0;
/* Engage VLAN tag insertion feature if requested. */
if (MLX5_TXOFF_CONFIG(VLAN) &&
- loc->mbuf->ol_flags & PKT_TX_VLAN_PKT) {
+ loc->mbuf->ol_flags & PKT_TX_VLAN) {
/*
* We should get here only if device support
* this feature correctly.
/* Fill metadata field if needed. */
es->metadata = MLX5_TXOFF_CONFIG(METADATA) ?
loc->mbuf->ol_flags & PKT_TX_DYNF_METADATA ?
- *RTE_FLOW_DYNF_METADATA(loc->mbuf) : 0 : 0;
+ rte_cpu_to_be_32(*RTE_FLOW_DYNF_METADATA(loc->mbuf)) :
+ 0 : 0;
psrc = rte_pktmbuf_mtod(loc->mbuf, uint8_t *);
es->inline_hdr_sz = RTE_BE16(MLX5_ESEG_MIN_INLINE_SIZE);
es->inline_data = *(unaligned_uint16_t *)psrc;
/* Fill metadata field if needed. */
es->metadata = MLX5_TXOFF_CONFIG(METADATA) ?
loc->mbuf->ol_flags & PKT_TX_DYNF_METADATA ?
- *RTE_FLOW_DYNF_METADATA(loc->mbuf) : 0 : 0;
+ rte_cpu_to_be_32(*RTE_FLOW_DYNF_METADATA(loc->mbuf)) :
+ 0 : 0;
psrc = rte_pktmbuf_mtod(loc->mbuf, uint8_t *);
es->inline_hdr_sz = rte_cpu_to_be_16(inlen);
es->inline_data = *(unaligned_uint16_t *)psrc;
/* Fill metadata field if needed. */
es->metadata = MLX5_TXOFF_CONFIG(METADATA) ?
loc->mbuf->ol_flags & PKT_TX_DYNF_METADATA ?
- *RTE_FLOW_DYNF_METADATA(loc->mbuf) : 0 : 0;
+ rte_cpu_to_be_32(*RTE_FLOW_DYNF_METADATA(loc->mbuf)) :
+ 0 : 0;
MLX5_ASSERT(inlen >= MLX5_ESEG_MIN_INLINE_SIZE);
pdst = (uint8_t *)&es->inline_data;
if (MLX5_TXOFF_CONFIG(VLAN) && vlan) {
* Copying may be interrupted inside the routine
* if run into no inline hint flag.
*/
- copy = tlen >= txq->inlen_mode ? 0 : (txq->inlen_mode - tlen);
+ copy = tso ? inlen : txq->inlen_mode;
+ copy = tlen >= copy ? 0 : (copy - tlen);
copy = mlx5_tx_mseg_memcpy(pdst, loc, part, copy, olx);
tlen += copy;
if (likely(inlen <= tlen) || copy < part) {
* the required space in WQE ring buffer.
*/
dlen = rte_pktmbuf_pkt_len(loc->mbuf);
- if (MLX5_TXOFF_CONFIG(VLAN) && loc->mbuf->ol_flags & PKT_TX_VLAN_PKT)
+ if (MLX5_TXOFF_CONFIG(VLAN) && loc->mbuf->ol_flags & PKT_TX_VLAN)
vlan = sizeof(struct rte_vlan_hdr);
inlen = loc->mbuf->l2_len + vlan +
loc->mbuf->l3_len + loc->mbuf->l4_len;
/* Update sent data bytes counter. */
txq->stats.obytes += rte_pktmbuf_pkt_len(loc->mbuf);
if (MLX5_TXOFF_CONFIG(VLAN) &&
- loc->mbuf->ol_flags & PKT_TX_VLAN_PKT)
+ loc->mbuf->ol_flags & PKT_TX_VLAN)
txq->stats.obytes += sizeof(struct rte_vlan_hdr);
#endif
/*
* to estimate the required space for WQE.
*/
dlen = rte_pktmbuf_pkt_len(loc->mbuf);
- if (MLX5_TXOFF_CONFIG(VLAN) && loc->mbuf->ol_flags & PKT_TX_VLAN_PKT)
+ if (MLX5_TXOFF_CONFIG(VLAN) && loc->mbuf->ol_flags & PKT_TX_VLAN)
vlan = sizeof(struct rte_vlan_hdr);
inlen = dlen + vlan;
/* Check against minimal length. */
unsigned int nxlen;
uintptr_t start;
+ mbuf = loc->mbuf;
+ nxlen = rte_pktmbuf_data_len(mbuf);
/*
* Packet length exceeds the allowed inline data length,
* check whether the minimal inlining is required.
MLX5_ESEG_MIN_INLINE_SIZE);
MLX5_ASSERT(txq->inlen_mode <= txq->inlen_send);
inlen = txq->inlen_mode;
- } else {
- if (loc->mbuf->ol_flags & PKT_TX_DYNF_NOINLINE ||
- !vlan || txq->vlan_en) {
- /*
- * VLAN insertion will be done inside by HW.
- * It is not utmost effective - VLAN flag is
- * checked twice, but we should proceed the
- * inlining length correctly and take into
- * account the VLAN header being inserted.
- */
- return mlx5_tx_packet_multi_send
- (txq, loc, olx);
- }
+ } else if (vlan && !txq->vlan_en) {
+ /*
+ * VLAN insertion is requested and hardware does not
+ * support the offload, will do with software inline.
+ */
inlen = MLX5_ESEG_MIN_INLINE_SIZE;
+ } else if (mbuf->ol_flags & PKT_TX_DYNF_NOINLINE ||
+ nxlen > txq->inlen_send) {
+ return mlx5_tx_packet_multi_send(txq, loc, olx);
+ } else {
+ goto do_first;
}
/*
* Now we know the minimal amount of data is requested
* to inline. Check whether we should inline the buffers
* from the chain beginning to eliminate some mbufs.
*/
- mbuf = loc->mbuf;
- nxlen = rte_pktmbuf_data_len(mbuf);
if (unlikely(nxlen <= txq->inlen_send)) {
/* We can inline first mbuf at least. */
if (nxlen < inlen) {
goto do_align;
}
}
+do_first:
do {
inlen = nxlen;
mbuf = NEXT(mbuf);
}
dlen = rte_pktmbuf_data_len(loc->mbuf);
if (MLX5_TXOFF_CONFIG(VLAN) &&
- loc->mbuf->ol_flags & PKT_TX_VLAN_PKT) {
+ loc->mbuf->ol_flags & PKT_TX_VLAN) {
vlan = sizeof(struct rte_vlan_hdr);
}
/*
return MLX5_TXCMP_CODE_SINGLE;
/* Check if eMPW can be engaged. */
if (MLX5_TXOFF_CONFIG(VLAN) &&
- unlikely(loc->mbuf->ol_flags & PKT_TX_VLAN_PKT) &&
+ unlikely(loc->mbuf->ol_flags & PKT_TX_VLAN) &&
(!MLX5_TXOFF_CONFIG(INLINE) ||
unlikely((rte_pktmbuf_data_len(loc->mbuf) +
sizeof(struct rte_vlan_hdr)) > txq->inlen_empw))) {
/* Fill metadata field if needed. */
if (MLX5_TXOFF_CONFIG(METADATA) &&
es->metadata != (loc->mbuf->ol_flags & PKT_TX_DYNF_METADATA ?
- *RTE_FLOW_DYNF_METADATA(loc->mbuf) : 0))
+ rte_cpu_to_be_32(*RTE_FLOW_DYNF_METADATA(loc->mbuf)) : 0))
return false;
/* Legacy MPW can send packets with the same length only. */
if (MLX5_TXOFF_CONFIG(MPW) &&
return false;
/* There must be no VLAN packets in eMPW loop. */
if (MLX5_TXOFF_CONFIG(VLAN))
- MLX5_ASSERT(!(loc->mbuf->ol_flags & PKT_TX_VLAN_PKT));
+ MLX5_ASSERT(!(loc->mbuf->ol_flags & PKT_TX_VLAN));
/* Check if the scheduling is requested. */
if (MLX5_TXOFF_CONFIG(TXPP) &&
loc->mbuf->ol_flags & txq->ts_mask)
}
/* Inline entire packet, optional VLAN insertion. */
if (MLX5_TXOFF_CONFIG(VLAN) &&
- loc->mbuf->ol_flags & PKT_TX_VLAN_PKT) {
+ loc->mbuf->ol_flags & PKT_TX_VLAN) {
/*
* The packet length must be checked in
* mlx5_tx_able_to_empw() and packet
MLX5_ASSERT(room >= MLX5_WQE_DSEG_SIZE);
if (MLX5_TXOFF_CONFIG(VLAN))
MLX5_ASSERT(!(loc->mbuf->ol_flags &
- PKT_TX_VLAN_PKT));
+ PKT_TX_VLAN));
mlx5_tx_dseg_ptr(txq, loc, dseg, dptr, dlen, olx);
/* We have to store mbuf in elts.*/
txq->elts[txq->elts_head++ & txq->elts_m] = loc->mbuf;
inlen = rte_pktmbuf_data_len(loc->mbuf);
if (MLX5_TXOFF_CONFIG(VLAN) &&
- loc->mbuf->ol_flags & PKT_TX_VLAN_PKT) {
+ loc->mbuf->ol_flags & PKT_TX_VLAN) {
vlan = sizeof(struct rte_vlan_hdr);
inlen += vlan;
}
/* Update sent data bytes counter. */
txq->stats.obytes += rte_pktmbuf_data_len(loc->mbuf);
if (MLX5_TXOFF_CONFIG(VLAN) &&
- loc->mbuf->ol_flags & PKT_TX_VLAN_PKT)
+ loc->mbuf->ol_flags & PKT_TX_VLAN)
txq->stats.obytes +=
sizeof(struct rte_vlan_hdr);
#endif