Imported Upstream version 16.07.2
[deb_dpdk.git] / drivers / net / mlx5 / mlx5_rxtx.c
index fce3381..79f7fa9 100644 (file)
 /* Verbs header. */
 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
 #ifdef PEDANTIC
-#pragma GCC diagnostic ignored "-pedantic"
+#pragma GCC diagnostic ignored "-Wpedantic"
 #endif
 #include <infiniband/verbs.h>
 #include <infiniband/mlx5_hw.h>
 #include <infiniband/arch.h>
 #ifdef PEDANTIC
-#pragma GCC diagnostic error "-pedantic"
+#pragma GCC diagnostic error "-Wpedantic"
 #endif
 
 /* DPDK headers don't like -pedantic. */
 #ifdef PEDANTIC
-#pragma GCC diagnostic ignored "-pedantic"
+#pragma GCC diagnostic ignored "-Wpedantic"
 #endif
 #include <rte_mbuf.h>
 #include <rte_mempool.h>
@@ -59,7 +59,7 @@
 #include <rte_branch_prediction.h>
 #include <rte_ether.h>
 #ifdef PEDANTIC
-#pragma GCC diagnostic error "-pedantic"
+#pragma GCC diagnostic error "-Wpedantic"
 #endif
 
 #include "mlx5.h"
@@ -290,226 +290,103 @@ txq_mp2mr(struct txq *txq, struct rte_mempool *mp)
  *   Pointer to TX queue structure.
  * @param wqe
  *   Pointer to the WQE to fill.
- * @param addr
- *   Buffer data address.
+ * @param buf
+ *   Buffer.
  * @param length
  *   Packet length.
- * @param lkey
- *   Memory region lkey.
- */
-static inline void
-mlx5_wqe_write(struct txq *txq, volatile union mlx5_wqe *wqe,
-              uintptr_t addr, uint32_t length, uint32_t lkey)
-{
-       wqe->wqe.ctrl.data[0] = htonl((txq->wqe_ci << 8) | MLX5_OPCODE_SEND);
-       wqe->wqe.ctrl.data[1] = htonl((txq->qp_num_8s) | 4);
-       wqe->wqe.ctrl.data[2] = 0;
-       wqe->wqe.ctrl.data[3] = 0;
-       wqe->inl.eseg.rsvd0 = 0;
-       wqe->inl.eseg.rsvd1 = 0;
-       wqe->inl.eseg.mss = 0;
-       wqe->inl.eseg.rsvd2 = 0;
-       wqe->wqe.eseg.inline_hdr_sz = htons(MLX5_ETH_INLINE_HEADER_SIZE);
-       /* Copy the first 16 bytes into inline header. */
-       rte_memcpy((uint8_t *)(uintptr_t)wqe->wqe.eseg.inline_hdr_start,
-                  (uint8_t *)(uintptr_t)addr,
-                  MLX5_ETH_INLINE_HEADER_SIZE);
-       addr += MLX5_ETH_INLINE_HEADER_SIZE;
-       length -= MLX5_ETH_INLINE_HEADER_SIZE;
-       /* Store remaining data in data segment. */
-       wqe->wqe.dseg.byte_count = htonl(length);
-       wqe->wqe.dseg.lkey = lkey;
-       wqe->wqe.dseg.addr = htonll(addr);
-       /* Increment consumer index. */
-       ++txq->wqe_ci;
-}
-
-/**
- * Write a regular WQE with VLAN.
  *
- * @param txq
- *   Pointer to TX queue structure.
- * @param wqe
- *   Pointer to the WQE to fill.
- * @param addr
- *   Buffer data address.
- * @param length
- *   Packet length.
- * @param lkey
- *   Memory region lkey.
- * @param vlan_tci
- *   VLAN field to insert in packet.
+ * @return ds
+ *   Number of DS elements consumed.
  */
-static inline void
-mlx5_wqe_write_vlan(struct txq *txq, volatile union mlx5_wqe *wqe,
-                   uintptr_t addr, uint32_t length, uint32_t lkey,
-                   uint16_t vlan_tci)
+static inline unsigned int
+mlx5_wqe_write(struct txq *txq, volatile union mlx5_wqe *wqe,
+              struct rte_mbuf *buf, uint32_t length)
 {
-       uint32_t vlan = htonl(0x81000000 | vlan_tci);
-
+       uintptr_t raw = (uintptr_t)&wqe->wqe.eseg.inline_hdr_start;
+       uint16_t ds;
+       uint16_t pkt_inline_sz = 16;
+       uintptr_t addr = rte_pktmbuf_mtod(buf, uintptr_t);
+       struct mlx5_wqe_data_seg *dseg = NULL;
+
+       assert(length >= 16);
+       /* Start the know and common part of the WQE structure. */
        wqe->wqe.ctrl.data[0] = htonl((txq->wqe_ci << 8) | MLX5_OPCODE_SEND);
-       wqe->wqe.ctrl.data[1] = htonl((txq->qp_num_8s) | 4);
        wqe->wqe.ctrl.data[2] = 0;
        wqe->wqe.ctrl.data[3] = 0;
-       wqe->inl.eseg.rsvd0 = 0;
-       wqe->inl.eseg.rsvd1 = 0;
-       wqe->inl.eseg.mss = 0;
-       wqe->inl.eseg.rsvd2 = 0;
-       wqe->wqe.eseg.inline_hdr_sz = htons(MLX5_ETH_VLAN_INLINE_HEADER_SIZE);
-       /*
-        * Copy 12 bytes of source & destination MAC address.
-        * Copy 4 bytes of VLAN.
-        * Copy 2 bytes of Ether type.
-        */
-       rte_memcpy((uint8_t *)(uintptr_t)wqe->wqe.eseg.inline_hdr_start,
-                  (uint8_t *)(uintptr_t)addr, 12);
-       rte_memcpy((uint8_t *)((uintptr_t)wqe->wqe.eseg.inline_hdr_start + 12),
-                  &vlan, sizeof(vlan));
-       rte_memcpy((uint8_t *)((uintptr_t)wqe->wqe.eseg.inline_hdr_start + 16),
-                  (uint8_t *)((uintptr_t)addr + 12), 2);
-       addr += MLX5_ETH_VLAN_INLINE_HEADER_SIZE - sizeof(vlan);
-       length -= MLX5_ETH_VLAN_INLINE_HEADER_SIZE - sizeof(vlan);
-       /* Store remaining data in data segment. */
-       wqe->wqe.dseg.byte_count = htonl(length);
-       wqe->wqe.dseg.lkey = lkey;
-       wqe->wqe.dseg.addr = htonll(addr);
-       /* Increment consumer index. */
-       ++txq->wqe_ci;
-}
-
-/**
- * Write a inline WQE.
- *
- * @param txq
- *   Pointer to TX queue structure.
- * @param wqe
- *   Pointer to the WQE to fill.
- * @param addr
- *   Buffer data address.
- * @param length
- *   Packet length.
- * @param lkey
- *   Memory region lkey.
- */
-static inline void
-mlx5_wqe_write_inline(struct txq *txq, volatile union mlx5_wqe *wqe,
-                     uintptr_t addr, uint32_t length)
-{
-       uint32_t size;
-       uint16_t wqe_cnt = txq->wqe_n - 1;
-       uint16_t wqe_ci = txq->wqe_ci + 1;
-
-       /* Copy the first 16 bytes into inline header. */
-       rte_memcpy((void *)(uintptr_t)wqe->inl.eseg.inline_hdr_start,
-                  (void *)(uintptr_t)addr,
-                  MLX5_ETH_INLINE_HEADER_SIZE);
-       addr += MLX5_ETH_INLINE_HEADER_SIZE;
-       length -= MLX5_ETH_INLINE_HEADER_SIZE;
-       size = 3 + ((4 + length + 15) / 16);
-       wqe->inl.byte_cnt = htonl(length | MLX5_INLINE_SEG);
-       rte_memcpy((void *)(uintptr_t)&wqe->inl.data[0],
-                  (void *)addr, MLX5_WQE64_INL_DATA);
-       addr += MLX5_WQE64_INL_DATA;
-       length -= MLX5_WQE64_INL_DATA;
-       while (length) {
-               volatile union mlx5_wqe *wqe_next =
-                       &(*txq->wqes)[wqe_ci & wqe_cnt];
-               uint32_t copy_bytes = (length > sizeof(*wqe)) ?
-                                     sizeof(*wqe) :
-                                     length;
-
-               rte_mov64((uint8_t *)(uintptr_t)&wqe_next->data[0],
-                         (uint8_t *)addr);
-               addr += copy_bytes;
-               length -= copy_bytes;
-               ++wqe_ci;
+       wqe->wqe.eseg.rsvd0 = 0;
+       wqe->wqe.eseg.rsvd1 = 0;
+       wqe->wqe.eseg.mss = 0;
+       wqe->wqe.eseg.rsvd2 = 0;
+       /* Start by copying the Ethernet Header. */
+       rte_mov16((uint8_t *)raw, (uint8_t *)addr);
+       length -= 16;
+       addr += 16;
+       /* Replace the Ethernet type by the VLAN if necessary. */
+       if (buf->ol_flags & PKT_TX_VLAN_PKT) {
+               uint32_t vlan = htonl(0x81000000 | buf->vlan_tci);
+
+               memcpy((uint8_t *)(raw + 16 - sizeof(vlan)),
+                      &vlan, sizeof(vlan));
+               addr -= sizeof(vlan);
+               length += sizeof(vlan);
        }
-       assert(size < 64);
-       wqe->inl.ctrl.data[0] = htonl((txq->wqe_ci << 8) | MLX5_OPCODE_SEND);
-       wqe->inl.ctrl.data[1] = htonl(txq->qp_num_8s | size);
-       wqe->inl.ctrl.data[2] = 0;
-       wqe->inl.ctrl.data[3] = 0;
-       wqe->inl.eseg.rsvd0 = 0;
-       wqe->inl.eseg.rsvd1 = 0;
-       wqe->inl.eseg.mss = 0;
-       wqe->inl.eseg.rsvd2 = 0;
-       wqe->inl.eseg.inline_hdr_sz = htons(MLX5_ETH_INLINE_HEADER_SIZE);
-       /* Increment consumer index. */
-       txq->wqe_ci = wqe_ci;
-}
-
-/**
- * Write a inline WQE with VLAN.
- *
- * @param txq
- *   Pointer to TX queue structure.
- * @param wqe
- *   Pointer to the WQE to fill.
- * @param addr
- *   Buffer data address.
- * @param length
- *   Packet length.
- * @param lkey
- *   Memory region lkey.
- * @param vlan_tci
- *   VLAN field to insert in packet.
- */
-static inline void
-mlx5_wqe_write_inline_vlan(struct txq *txq, volatile union mlx5_wqe *wqe,
-                          uintptr_t addr, uint32_t length, uint16_t vlan_tci)
-{
-       uint32_t size;
-       uint32_t wqe_cnt = txq->wqe_n - 1;
-       uint16_t wqe_ci = txq->wqe_ci + 1;
-       uint32_t vlan = htonl(0x81000000 | vlan_tci);
-
-       /*
-        * Copy 12 bytes of source & destination MAC address.
-        * Copy 4 bytes of VLAN.
-        * Copy 2 bytes of Ether type.
-        */
-       rte_memcpy((uint8_t *)(uintptr_t)wqe->inl.eseg.inline_hdr_start,
-                  (uint8_t *)addr, 12);
-       rte_memcpy((uint8_t *)(uintptr_t)wqe->inl.eseg.inline_hdr_start + 12,
-                  &vlan, sizeof(vlan));
-       rte_memcpy((uint8_t *)((uintptr_t)wqe->inl.eseg.inline_hdr_start + 16),
-                  (uint8_t *)(addr + 12), 2);
-       addr += MLX5_ETH_VLAN_INLINE_HEADER_SIZE - sizeof(vlan);
-       length -= MLX5_ETH_VLAN_INLINE_HEADER_SIZE - sizeof(vlan);
-       size = (sizeof(wqe->inl.ctrl.ctrl) +
-               sizeof(wqe->inl.eseg) +
-               sizeof(wqe->inl.byte_cnt) +
-               length + 15) / 16;
-       wqe->inl.byte_cnt = htonl(length | MLX5_INLINE_SEG);
-       rte_memcpy((void *)(uintptr_t)&wqe->inl.data[0],
-                  (void *)addr, MLX5_WQE64_INL_DATA);
-       addr += MLX5_WQE64_INL_DATA;
-       length -= MLX5_WQE64_INL_DATA;
-       while (length) {
-               volatile union mlx5_wqe *wqe_next =
-                       &(*txq->wqes)[wqe_ci & wqe_cnt];
-               uint32_t copy_bytes = (length > sizeof(*wqe)) ?
-                                     sizeof(*wqe) :
-                                     length;
-
-               rte_mov64((uint8_t *)(uintptr_t)&wqe_next->data[0],
-                         (uint8_t *)addr);
-               addr += copy_bytes;
-               length -= copy_bytes;
-               ++wqe_ci;
+       /* Inline if enough room. */
+       if (txq->max_inline != 0) {
+               uintptr_t end = (uintptr_t)&(*txq->wqes)[txq->wqe_n];
+               uint16_t max_inline = txq->max_inline * RTE_CACHE_LINE_SIZE;
+               uint16_t room;
+
+               raw += 16;
+               room = end - (uintptr_t)raw;
+               if (room > max_inline) {
+                       uintptr_t addr_end = (addr + max_inline) &
+                               ~(RTE_CACHE_LINE_SIZE - 1);
+                       uint16_t copy_b = ((addr_end - addr) > length) ?
+                                         length :
+                                         (addr_end - addr);
+
+                       rte_memcpy((void *)raw, (void *)addr, copy_b);
+                       addr += copy_b;
+                       length -= copy_b;
+                       pkt_inline_sz += copy_b;
+                       /* Sanity check. */
+                       assert(addr <= addr_end);
+               }
+               /* Store the inlined packet size in the WQE. */
+               wqe->wqe.eseg.inline_hdr_sz = htons(pkt_inline_sz);
+               /*
+                * 2 DWORDs consumed by the WQE header + 1 DSEG +
+                * the size of the inline part of the packet.
+                */
+               ds = 2 + ((pkt_inline_sz - 2 + 15) / 16);
+               if (length > 0) {
+                       dseg = (struct mlx5_wqe_data_seg *)
+                               ((uintptr_t)wqe + (ds * 16));
+                       if ((uintptr_t)dseg >= end)
+                               dseg = (struct mlx5_wqe_data_seg *)
+                                       ((uintptr_t)&(*txq->wqes)[0]);
+                       goto use_dseg;
+               }
+       } else {
+               /* Add the remaining packet as a simple ds. */
+               ds = 3;
+               /*
+                * No inline has been done in the packet, only the Ethernet
+                * Header as been stored.
+                */
+               wqe->wqe.eseg.inline_hdr_sz = htons(16);
+               dseg = (struct mlx5_wqe_data_seg *)
+                       ((uintptr_t)wqe + (ds * 16));
+use_dseg:
+               *dseg = (struct mlx5_wqe_data_seg) {
+                       .addr = htonll(addr),
+                       .byte_count = htonl(length),
+                       .lkey = txq_mp2mr(txq, txq_mb2mp(buf)),
+               };
+               ++ds;
        }
-       assert(size < 64);
-       wqe->inl.ctrl.data[0] = htonl((txq->wqe_ci << 8) | MLX5_OPCODE_SEND);
-       wqe->inl.ctrl.data[1] = htonl(txq->qp_num_8s | size);
-       wqe->inl.ctrl.data[2] = 0;
-       wqe->inl.ctrl.data[3] = 0;
-       wqe->inl.eseg.rsvd0 = 0;
-       wqe->inl.eseg.rsvd1 = 0;
-       wqe->inl.eseg.mss = 0;
-       wqe->inl.eseg.rsvd2 = 0;
-       wqe->inl.eseg.inline_hdr_sz = htons(MLX5_ETH_VLAN_INLINE_HEADER_SIZE);
-       /* Increment consumer index. */
-       txq->wqe_ci = wqe_ci;
+       wqe->wqe.ctrl.data[1] = htonl(txq->qp_num_8s | ds);
+       return ds;
 }
 
 /**
@@ -609,9 +486,7 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
        do {
                struct rte_mbuf *buf = *(pkts++);
                unsigned int elts_head_next;
-               uintptr_t addr;
                uint32_t length;
-               uint32_t lkey;
                unsigned int segs_n = buf->nb_segs;
                volatile struct mlx5_wqe_data_seg *dseg;
                unsigned int ds = sizeof(*wqe) / 16;
@@ -627,12 +502,10 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
                --pkts_n;
                elts_head_next = (elts_head + 1) & (elts_n - 1);
                wqe = &(*txq->wqes)[txq->wqe_ci & (txq->wqe_n - 1)];
-               dseg = &wqe->wqe.dseg;
-               rte_prefetch0(wqe);
+               tx_prefetch_wqe(txq, txq->wqe_ci);
+               tx_prefetch_wqe(txq, txq->wqe_ci + 1);
                if (pkts_n)
                        rte_prefetch0(*pkts);
-               /* Retrieve buffer information. */
-               addr = rte_pktmbuf_mtod(buf, uintptr_t);
                length = DATA_LEN(buf);
                /* Update element. */
                (*txq->elts)[elts_head] = buf;
@@ -640,13 +513,6 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
                if (pkts_n)
                        rte_prefetch0(rte_pktmbuf_mtod(*pkts,
                                                       volatile void *));
-               /* Retrieve Memory Region key for this memory pool. */
-               lkey = txq_mp2mr(txq, txq_mb2mp(buf));
-               if (buf->ol_flags & PKT_TX_VLAN_PKT)
-                       mlx5_wqe_write_vlan(txq, wqe, addr, length, lkey,
-                                           buf->vlan_tci);
-               else
-                       mlx5_wqe_write(txq, wqe, addr, length, lkey);
                /* Should we enable HW CKSUM offload */
                if (buf->ol_flags &
                    (PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM)) {
@@ -656,6 +522,11 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
                } else {
                        wqe->wqe.eseg.cs_flags = 0;
                }
+               ds = mlx5_wqe_write(txq, wqe, buf, length);
+               if (segs_n == 1)
+                       goto skip_segs;
+               dseg = (volatile struct mlx5_wqe_data_seg *)
+                       (((uintptr_t)wqe) + ds * 16);
                while (--segs_n) {
                        /*
                         * Spill on next WQE when the current one does not have
@@ -686,11 +557,13 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
                /* Update DS field in WQE. */
                wqe->wqe.ctrl.data[1] &= htonl(0xffffffc0);
                wqe->wqe.ctrl.data[1] |= htonl(ds & 0x3f);
-               elts_head = elts_head_next;
+skip_segs:
 #ifdef MLX5_PMD_SOFT_COUNTERS
                /* Increment sent bytes counter. */
                txq->stats.obytes += length;
 #endif
+               /* Increment consumer index. */
+               txq->wqe_ci += (ds + 3) / 4;
                elts_head = elts_head_next;
                ++i;
        } while (pkts_n);
@@ -718,166 +591,6 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
        return i;
 }
 
-/**
- * DPDK callback for TX with inline support.
- *
- * @param dpdk_txq
- *   Generic pointer to TX queue structure.
- * @param[in] pkts
- *   Packets to transmit.
- * @param pkts_n
- *   Number of packets in array.
- *
- * @return
- *   Number of packets successfully transmitted (<= pkts_n).
- */
-uint16_t
-mlx5_tx_burst_inline(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
-{
-       struct txq *txq = (struct txq *)dpdk_txq;
-       uint16_t elts_head = txq->elts_head;
-       const unsigned int elts_n = txq->elts_n;
-       unsigned int i = 0;
-       unsigned int j = 0;
-       unsigned int max;
-       unsigned int comp;
-       volatile union mlx5_wqe *wqe = NULL;
-       unsigned int max_inline = txq->max_inline;
-
-       if (unlikely(!pkts_n))
-               return 0;
-       /* Prefetch first packet cacheline. */
-       tx_prefetch_cqe(txq, txq->cq_ci);
-       tx_prefetch_cqe(txq, txq->cq_ci + 1);
-       rte_prefetch0(*pkts);
-       /* Start processing. */
-       txq_complete(txq);
-       max = (elts_n - (elts_head - txq->elts_tail));
-       if (max > elts_n)
-               max -= elts_n;
-       do {
-               struct rte_mbuf *buf = *(pkts++);
-               unsigned int elts_head_next;
-               uintptr_t addr;
-               uint32_t length;
-               uint32_t lkey;
-               unsigned int segs_n = buf->nb_segs;
-               volatile struct mlx5_wqe_data_seg *dseg;
-               unsigned int ds = sizeof(*wqe) / 16;
-
-               /*
-                * Make sure there is enough room to store this packet and
-                * that one ring entry remains unused.
-                */
-               assert(segs_n);
-               if (max < segs_n + 1)
-                       break;
-               max -= segs_n;
-               --pkts_n;
-               elts_head_next = (elts_head + 1) & (elts_n - 1);
-               wqe = &(*txq->wqes)[txq->wqe_ci & (txq->wqe_n - 1)];
-               dseg = &wqe->wqe.dseg;
-               tx_prefetch_wqe(txq, txq->wqe_ci);
-               tx_prefetch_wqe(txq, txq->wqe_ci + 1);
-               if (pkts_n)
-                       rte_prefetch0(*pkts);
-               /* Should we enable HW CKSUM offload */
-               if (buf->ol_flags &
-                   (PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM)) {
-                       wqe->inl.eseg.cs_flags =
-                               MLX5_ETH_WQE_L3_CSUM |
-                               MLX5_ETH_WQE_L4_CSUM;
-               } else {
-                       wqe->inl.eseg.cs_flags = 0;
-               }
-               /* Retrieve buffer information. */
-               addr = rte_pktmbuf_mtod(buf, uintptr_t);
-               length = DATA_LEN(buf);
-               /* Update element. */
-               (*txq->elts)[elts_head] = buf;
-               /* Prefetch next buffer data. */
-               if (pkts_n)
-                       rte_prefetch0(rte_pktmbuf_mtod(*pkts,
-                                                      volatile void *));
-               if ((length <= max_inline) && (segs_n == 1)) {
-                       if (buf->ol_flags & PKT_TX_VLAN_PKT)
-                               mlx5_wqe_write_inline_vlan(txq, wqe,
-                                                          addr, length,
-                                                          buf->vlan_tci);
-                       else
-                               mlx5_wqe_write_inline(txq, wqe, addr, length);
-                       goto skip_segs;
-               } else {
-                       /* Retrieve Memory Region key for this memory pool. */
-                       lkey = txq_mp2mr(txq, txq_mb2mp(buf));
-                       if (buf->ol_flags & PKT_TX_VLAN_PKT)
-                               mlx5_wqe_write_vlan(txq, wqe, addr, length,
-                                                   lkey, buf->vlan_tci);
-                       else
-                               mlx5_wqe_write(txq, wqe, addr, length, lkey);
-               }
-               while (--segs_n) {
-                       /*
-                        * Spill on next WQE when the current one does not have
-                        * enough room left. Size of WQE must a be a multiple
-                        * of data segment size.
-                        */
-                       assert(!(sizeof(*wqe) % sizeof(*dseg)));
-                       if (!(ds % (sizeof(*wqe) / 16)))
-                               dseg = (volatile void *)
-                                       &(*txq->wqes)[txq->wqe_ci++ &
-                                                     (txq->wqe_n - 1)];
-                       else
-                               ++dseg;
-                       ++ds;
-                       buf = buf->next;
-                       assert(buf);
-                       /* Store segment information. */
-                       dseg->byte_count = htonl(DATA_LEN(buf));
-                       dseg->lkey = txq_mp2mr(txq, txq_mb2mp(buf));
-                       dseg->addr = htonll(rte_pktmbuf_mtod(buf, uintptr_t));
-                       (*txq->elts)[elts_head_next] = buf;
-                       elts_head_next = (elts_head_next + 1) & (elts_n - 1);
-#ifdef MLX5_PMD_SOFT_COUNTERS
-                       length += DATA_LEN(buf);
-#endif
-                       ++j;
-               }
-               /* Update DS field in WQE. */
-               wqe->inl.ctrl.data[1] &= htonl(0xffffffc0);
-               wqe->inl.ctrl.data[1] |= htonl(ds & 0x3f);
-skip_segs:
-               elts_head = elts_head_next;
-#ifdef MLX5_PMD_SOFT_COUNTERS
-               /* Increment sent bytes counter. */
-               txq->stats.obytes += length;
-#endif
-               ++i;
-       } while (pkts_n);
-       /* Take a shortcut if nothing must be sent. */
-       if (unlikely(i == 0))
-               return 0;
-       /* Check whether completion threshold has been reached. */
-       comp = txq->elts_comp + i + j;
-       if (comp >= MLX5_TX_COMP_THRESH) {
-               /* Request completion on last WQE. */
-               wqe->inl.ctrl.data[2] = htonl(8);
-               /* Save elts_head in unused "immediate" field of WQE. */
-               wqe->inl.ctrl.data[3] = elts_head;
-               txq->elts_comp = 0;
-       } else {
-               txq->elts_comp = comp;
-       }
-#ifdef MLX5_PMD_SOFT_COUNTERS
-       /* Increment sent packets counter. */
-       txq->stats.opackets += i;
-#endif
-       /* Ring QP doorbell. */
-       mlx5_tx_dbrec(txq);
-       txq->elts_head = elts_head;
-       return i;
-}
-
 /**
  * Open a MPW session.
  *
@@ -908,7 +621,7 @@ mlx5_mpw_new(struct txq *txq, struct mlx5_mpw *mpw, uint32_t length)
        mpw->wqe->mpw.eseg.rsvd2 = 0;
        mpw->wqe->mpw.ctrl.data[0] = htonl((MLX5_OPC_MOD_MPW << 24) |
                                           (txq->wqe_ci << 8) |
-                                          MLX5_OPCODE_LSO_MPW);
+                                          MLX5_OPCODE_TSO);
        mpw->wqe->mpw.ctrl.data[2] = 0;
        mpw->wqe->mpw.ctrl.data[3] = 0;
        mpw->data.dseg[0] = &mpw->wqe->mpw.dseg[0];
@@ -1107,7 +820,7 @@ mlx5_mpw_inline_new(struct txq *txq, struct mlx5_mpw *mpw, uint32_t length)
        mpw->wqe = &(*txq->wqes)[idx];
        mpw->wqe->mpw_inl.ctrl.data[0] = htonl((MLX5_OPC_MOD_MPW << 24) |
                                               (txq->wqe_ci << 8) |
-                                              MLX5_OPCODE_LSO_MPW);
+                                              MLX5_OPCODE_TSO);
        mpw->wqe->mpw_inl.ctrl.data[2] = 0;
        mpw->wqe->mpw_inl.ctrl.data[3] = 0;
        mpw->wqe->mpw_inl.eseg.mss = htons(length);
@@ -1168,7 +881,7 @@ mlx5_tx_burst_mpw_inline(void *dpdk_txq, struct rte_mbuf **pkts,
        unsigned int j = 0;
        unsigned int max;
        unsigned int comp;
-       unsigned int inline_room = txq->max_inline;
+       unsigned int inline_room = txq->max_inline * RTE_CACHE_LINE_SIZE;
        struct mlx5_mpw mpw = {
                .state = MLX5_MPW_STATE_CLOSED,
        };
@@ -1222,7 +935,8 @@ mlx5_tx_burst_mpw_inline(void *dpdk_txq, struct rte_mbuf **pkts,
                            (length > inline_room) ||
                            (mpw.wqe->mpw_inl.eseg.cs_flags != cs_flags)) {
                                mlx5_mpw_inline_close(txq, &mpw);
-                               inline_room = txq->max_inline;
+                               inline_room =
+                                       txq->max_inline * RTE_CACHE_LINE_SIZE;
                        }
                }
                if (mpw.state == MLX5_MPW_STATE_CLOSED) {
@@ -1238,7 +952,8 @@ mlx5_tx_burst_mpw_inline(void *dpdk_txq, struct rte_mbuf **pkts,
                /* Multi-segment packets must be alone in their MPW. */
                assert((segs_n == 1) || (mpw.pkts_n == 0));
                if (mpw.state == MLX5_MPW_STATE_OPENED) {
-                       assert(inline_room == txq->max_inline);
+                       assert(inline_room ==
+                              txq->max_inline * RTE_CACHE_LINE_SIZE);
 #if defined(MLX5_PMD_SOFT_COUNTERS) || !defined(NDEBUG)
                        length = 0;
 #endif
@@ -1303,7 +1018,8 @@ mlx5_tx_burst_mpw_inline(void *dpdk_txq, struct rte_mbuf **pkts,
                        ++j;
                        if (mpw.pkts_n == MLX5_MPW_DSEG_MAX) {
                                mlx5_mpw_inline_close(txq, &mpw);
-                               inline_room = txq->max_inline;
+                               inline_room =
+                                       txq->max_inline * RTE_CACHE_LINE_SIZE;
                        } else {
                                inline_room -= length;
                        }
@@ -1365,19 +1081,19 @@ rxq_cq_to_pkt_type(volatile struct mlx5_cqe64 *cqe)
        uint8_t flags = cqe->l4_hdr_type_etc;
        uint8_t info = cqe->rsvd0[0];
 
-       if (info & IBV_EXP_CQ_RX_TUNNEL_PACKET)
+       if (info & MLX5_CQE_RX_TUNNEL_PACKET)
                pkt_type =
                        TRANSPOSE(flags,
-                                 IBV_EXP_CQ_RX_OUTER_IPV4_PACKET,
+                                 MLX5_CQE_RX_OUTER_IPV4_PACKET,
                                  RTE_PTYPE_L3_IPV4) |
                        TRANSPOSE(flags,
-                                 IBV_EXP_CQ_RX_OUTER_IPV6_PACKET,
+                                 MLX5_CQE_RX_OUTER_IPV6_PACKET,
                                  RTE_PTYPE_L3_IPV6) |
                        TRANSPOSE(flags,
-                                 IBV_EXP_CQ_RX_IPV4_PACKET,
+                                 MLX5_CQE_RX_IPV4_PACKET,
                                  RTE_PTYPE_INNER_L3_IPV4) |
                        TRANSPOSE(flags,
-                                 IBV_EXP_CQ_RX_IPV6_PACKET,
+                                 MLX5_CQE_RX_IPV6_PACKET,
                                  RTE_PTYPE_INNER_L3_IPV6);
        else
                pkt_type =
@@ -1520,13 +1236,13 @@ rxq_cq_to_ol_flags(struct rxq *rxq, volatile struct mlx5_cqe64 *cqe)
         * of PKT_RX_EIP_CKSUM_BAD because the latter is not functional
         * (its value is 0).
         */
-       if ((info & IBV_EXP_CQ_RX_TUNNEL_PACKET) && (rxq->csum_l2tun))
+       if ((info & MLX5_CQE_RX_TUNNEL_PACKET) && (rxq->csum_l2tun))
                ol_flags |=
                        TRANSPOSE(~cqe->l4_hdr_type_etc,
-                                 IBV_EXP_CQ_RX_OUTER_IP_CSUM_OK,
+                                 MLX5_CQE_RX_OUTER_IP_CSUM_OK,
                                  PKT_RX_IP_CKSUM_BAD) |
                        TRANSPOSE(~cqe->l4_hdr_type_etc,
-                                 IBV_EXP_CQ_RX_OUTER_TCP_UDP_CSUM_OK,
+                                 MLX5_CQE_RX_OUTER_TCP_UDP_CSUM_OK,
                                  PKT_RX_L4_CKSUM_BAD);
        return ol_flags;
 }
@@ -1572,6 +1288,14 @@ mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
                rte_prefetch0(wqe);
                rep = rte_mbuf_raw_alloc(rxq->mp);
                if (unlikely(rep == NULL)) {
+                       ++rxq->stats.rx_nombuf;
+                       if (!pkt) {
+                               /*
+                                * no buffers before we even started,
+                                * bail out silently.
+                                */
+                               break;
+                       }
                        while (pkt != seg) {
                                assert(pkt != (*rxq->elts)[idx]);
                                seg = NEXT(pkt);
@@ -1579,7 +1303,6 @@ mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
                                __rte_mbuf_raw_free(pkt);
                                pkt = seg;
                        }
-                       ++rxq->stats.rx_nombuf;
                        break;
                }
                if (!pkt) {